Use SimulateChunk in redstone simulator
+ Improved performance, reduces bottleneck in chunkmap lookup * Stop allocating and throwing away lots of small vectors in Update/GetValidSourcePositions return values - Remove unused GetPowerLevel virtual
This commit is contained in:
parent
de06ae7add
commit
4e5ab02a58
@ -34,10 +34,13 @@ public:
|
||||
const Vector3i a_CursorPos
|
||||
) override
|
||||
{
|
||||
const auto Meta = a_ChunkInterface.GetBlockMeta(a_BlockPos);
|
||||
|
||||
// Toggle the 3rd bit (addition / subtraction):
|
||||
NIBBLETYPE Meta = a_ChunkInterface.GetBlockMeta(a_BlockPos);
|
||||
Meta ^= 0x04;
|
||||
a_ChunkInterface.SetBlockMeta(a_BlockPos, Meta);
|
||||
a_ChunkInterface.SetBlockMeta(a_BlockPos, Meta ^ 0x04);
|
||||
|
||||
// Update simulators:
|
||||
a_WorldInterface.WakeUpSimulators(a_BlockPos);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -56,6 +59,7 @@ public:
|
||||
UNUSED(a_ChunkInterface);
|
||||
UNUSED(a_BlockFace);
|
||||
|
||||
a_WorldInterface.WakeUpSimulators(a_BlockPos);
|
||||
a_WorldInterface.SendBlockTo(a_BlockPos, a_Player);
|
||||
}
|
||||
|
||||
@ -120,15 +124,6 @@ public:
|
||||
|
||||
|
||||
|
||||
inline static bool IsOn(NIBBLETYPE a_Meta)
|
||||
{
|
||||
return ((a_Meta & 0x8) == 0x8);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
inline static Vector3i GetSideCoordinate(Vector3i a_Position, NIBBLETYPE a_Meta, bool a_bInverse)
|
||||
{
|
||||
if (!a_bInverse)
|
||||
|
@ -8,16 +8,13 @@
|
||||
|
||||
|
||||
|
||||
class cCommandBlockHandler:
|
||||
public cRedstoneHandler
|
||||
class cCommandBlockHandler final : public cRedstoneHandler
|
||||
{
|
||||
using Super = cRedstoneHandler;
|
||||
|
||||
public:
|
||||
|
||||
virtual unsigned char GetPowerDeliveredToPosition(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
|
||||
virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
|
||||
{
|
||||
UNUSED(a_World);
|
||||
UNUSED(a_Chunk);
|
||||
UNUSED(a_Position);
|
||||
UNUSED(a_BlockType);
|
||||
UNUSED(a_Meta);
|
||||
@ -26,40 +23,29 @@ public:
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual unsigned char GetPowerLevel(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override
|
||||
{
|
||||
UNUSED(a_World);
|
||||
UNUSED(a_Position);
|
||||
UNUSED(a_BlockType);
|
||||
UNUSED(a_Meta);
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual cVector3iArray Update(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override
|
||||
virtual void Update(cChunk & a_Chunk, cChunk &, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override
|
||||
{
|
||||
// LOGD("Evaluating commander the cmdblck (%d %d %d)", a_Position.x, a_Position.y, a_Position.z);
|
||||
|
||||
auto Previous = static_cast<cIncrementalRedstoneSimulator *>(a_World.GetRedstoneSimulator())->GetChunkData()->ExchangeUpdateOncePowerData(a_Position, a_PoweringData);
|
||||
auto Previous = DataForChunk(a_Chunk).ExchangeUpdateOncePowerData(a_Position, a_PoweringData);
|
||||
if ((Previous.PowerLevel != 0) || (a_PoweringData.PowerLevel == 0))
|
||||
{
|
||||
// If we're already powered or received an update of no power, don't activate
|
||||
return {};
|
||||
return;
|
||||
}
|
||||
|
||||
a_World.DoWithCommandBlockAt(a_Position.x, a_Position.y, a_Position.z, [](cCommandBlockEntity & a_CommandBlock)
|
||||
{
|
||||
a_CommandBlock.Activate();
|
||||
return false;
|
||||
}
|
||||
);
|
||||
return {};
|
||||
a_Chunk.DoWithCommandBlockAt(a_Position, [](cCommandBlockEntity & a_CommandBlock)
|
||||
{
|
||||
a_CommandBlock.Activate();
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
virtual cVector3iArray GetValidSourcePositions(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override
|
||||
virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
|
||||
{
|
||||
UNUSED(a_World);
|
||||
UNUSED(a_Chunk);
|
||||
UNUSED(a_BlockType);
|
||||
UNUSED(a_Meta);
|
||||
return GetAdjustedRelatives(a_Position, GetRelativeAdjacents());
|
||||
InvokeForAdjustedRelatives(Callback, a_Position, RelativeAdjacents);
|
||||
}
|
||||
};
|
||||
|
@ -8,16 +8,13 @@
|
||||
|
||||
|
||||
|
||||
class cDoorHandler:
|
||||
public cRedstoneHandler
|
||||
class cDoorHandler final : public cRedstoneHandler
|
||||
{
|
||||
using Super = cRedstoneHandler;
|
||||
|
||||
public:
|
||||
|
||||
virtual unsigned char GetPowerDeliveredToPosition(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
|
||||
virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
|
||||
{
|
||||
UNUSED(a_World);
|
||||
UNUSED(a_Chunk);
|
||||
UNUSED(a_Position);
|
||||
UNUSED(a_BlockType);
|
||||
UNUSED(a_Meta);
|
||||
@ -26,46 +23,27 @@ public:
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
virtual unsigned char GetPowerLevel(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override
|
||||
{
|
||||
UNUSED(a_World);
|
||||
UNUSED(a_Position);
|
||||
UNUSED(a_BlockType);
|
||||
UNUSED(a_Meta);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
virtual cVector3iArray Update(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override
|
||||
virtual void Update(cChunk & a_Chunk, cChunk &, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override
|
||||
{
|
||||
// LOGD("Evaluating dori the door (%d %d %d)", a_Position.x, a_Position.y, a_Position.z);
|
||||
|
||||
if (a_PoweringData != static_cast<cIncrementalRedstoneSimulator *>(a_World.GetRedstoneSimulator())->GetChunkData()->ExchangeUpdateOncePowerData(a_Position, a_PoweringData))
|
||||
{
|
||||
cChunkInterface ChunkInterface(a_World.GetChunkMap());
|
||||
cBlockDoorHandler::SetOpen(ChunkInterface, a_Position, (a_PoweringData.PowerLevel != 0));
|
||||
a_World.BroadcastSoundParticleEffect(EffectID::SFX_RANDOM_WOODEN_DOOR_OPEN, a_Position, 0);
|
||||
}
|
||||
cChunkInterface ChunkInterface(a_Chunk.GetWorld()->GetChunkMap());
|
||||
const bool ShouldBeOpen = a_PoweringData.PowerLevel != 0;
|
||||
const auto AbsolutePosition = cChunkDef::RelativeToAbsolute(a_Position, a_Chunk.GetPos());
|
||||
const bool IsOpen = cBlockDoorHandler::IsOpen(ChunkInterface, AbsolutePosition);
|
||||
|
||||
return {};
|
||||
if (ShouldBeOpen != IsOpen)
|
||||
{
|
||||
cBlockDoorHandler::SetOpen(ChunkInterface, AbsolutePosition, ShouldBeOpen);
|
||||
a_Chunk.GetWorld()->BroadcastSoundParticleEffect(EffectID::SFX_RANDOM_WOODEN_DOOR_OPEN, AbsolutePosition, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
virtual cVector3iArray GetValidSourcePositions(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override
|
||||
virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
|
||||
{
|
||||
UNUSED(a_World);
|
||||
UNUSED(a_Chunk);
|
||||
UNUSED(a_BlockType);
|
||||
UNUSED(a_Meta);
|
||||
return GetAdjustedRelatives(a_Position, GetRelativeAdjacents());
|
||||
InvokeForAdjustedRelatives(Callback, a_Position, RelativeAdjacents);
|
||||
}
|
||||
};
|
||||
|
@ -8,17 +8,15 @@
|
||||
|
||||
|
||||
|
||||
class cDropSpenserHandler:
|
||||
public cRedstoneHandler
|
||||
class cDropSpenserHandler final : public cRedstoneHandler
|
||||
{
|
||||
using Super = cRedstoneHandler;
|
||||
|
||||
public:
|
||||
|
||||
inline static bool IsActivated(NIBBLETYPE a_Meta)
|
||||
{
|
||||
return (a_Meta & E_META_DROPSPENSER_ACTIVATED) != 0;
|
||||
}
|
||||
|
||||
inline static NIBBLETYPE SetActivationState(NIBBLETYPE a_Meta, bool IsOn)
|
||||
{
|
||||
if (IsOn)
|
||||
@ -31,9 +29,9 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
virtual unsigned char GetPowerDeliveredToPosition(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
|
||||
virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
|
||||
{
|
||||
UNUSED(a_World);
|
||||
UNUSED(a_Chunk);
|
||||
UNUSED(a_Position);
|
||||
UNUSED(a_BlockType);
|
||||
UNUSED(a_Meta);
|
||||
@ -42,45 +40,34 @@ public:
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual unsigned char GetPowerLevel(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override
|
||||
{
|
||||
UNUSED(a_World);
|
||||
UNUSED(a_Position);
|
||||
UNUSED(a_BlockType);
|
||||
UNUSED(a_Meta);
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual cVector3iArray Update(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override
|
||||
virtual void Update(cChunk & a_Chunk, cChunk &, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override
|
||||
{
|
||||
// LOGD("Evaluating spencer the dropspenser (%d %d %d)", a_Position.x, a_Position.y, a_Position.z);
|
||||
bool IsPoweredNow = (a_PoweringData.PowerLevel > 0);
|
||||
bool WasPoweredPreviously = IsActivated(a_Meta);
|
||||
|
||||
const bool IsPoweredNow = (a_PoweringData.PowerLevel > 0);
|
||||
const bool WasPoweredPreviously = IsActivated(a_Meta);
|
||||
|
||||
if (IsPoweredNow && !WasPoweredPreviously)
|
||||
{
|
||||
a_World.DoWithDropSpenserAt(a_Position.x, a_Position.y, a_Position.z, [](cDropSpenserEntity & a_DropSpenser)
|
||||
{
|
||||
a_DropSpenser.Activate();
|
||||
return false;
|
||||
}
|
||||
);
|
||||
a_Chunk.DoWithDropSpenserAt(a_Position, [](cDropSpenserEntity & a_DropSpenser)
|
||||
{
|
||||
a_DropSpenser.Activate();
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
// Update the internal dropspenser state if necessary
|
||||
if (IsPoweredNow != WasPoweredPreviously)
|
||||
{
|
||||
a_World.SetBlockMeta(a_Position, SetActivationState(a_Meta, IsPoweredNow));
|
||||
a_Chunk.SetMeta(a_Position, SetActivationState(a_Meta, IsPoweredNow));
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
virtual cVector3iArray GetValidSourcePositions(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override
|
||||
virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
|
||||
{
|
||||
UNUSED(a_World);
|
||||
UNUSED(a_Chunk);
|
||||
UNUSED(a_BlockType);
|
||||
UNUSED(a_Meta);
|
||||
|
||||
return GetAdjustedRelatives(a_Position, GetRelativeAdjacents());
|
||||
InvokeForAdjustedRelatives(Callback, a_Position, RelativeAdjacents);
|
||||
}
|
||||
};
|
||||
|
@ -8,16 +8,13 @@
|
||||
|
||||
|
||||
|
||||
class cHopperHandler:
|
||||
public cRedstoneHandler
|
||||
class cHopperHandler final : public cRedstoneHandler
|
||||
{
|
||||
using Super = cRedstoneHandler;
|
||||
|
||||
public:
|
||||
|
||||
virtual unsigned char GetPowerDeliveredToPosition(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
|
||||
virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
|
||||
{
|
||||
UNUSED(a_World);
|
||||
UNUSED(a_Chunk);
|
||||
UNUSED(a_Position);
|
||||
UNUSED(a_BlockType);
|
||||
UNUSED(a_Meta);
|
||||
@ -26,39 +23,28 @@ public:
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual unsigned char GetPowerLevel(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override
|
||||
virtual void Update(cChunk & a_Chunk, cChunk &, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override
|
||||
{
|
||||
UNUSED(a_World);
|
||||
UNUSED(a_Position);
|
||||
UNUSED(a_BlockType);
|
||||
UNUSED(a_Meta);
|
||||
return 0;
|
||||
}
|
||||
// LOGD("Evaluating holey the hopper (%d %d %d)", a_Position.x, a_Position.y, a_Position.z);
|
||||
|
||||
virtual cVector3iArray Update(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override
|
||||
{
|
||||
// LOGD("Evaluating commander the cmdblck (%d %d %d)", a_Position.x, a_Position.y, a_Position.z);
|
||||
|
||||
auto Previous = static_cast<cIncrementalRedstoneSimulator *>(a_World.GetRedstoneSimulator())->GetChunkData()->ExchangeUpdateOncePowerData(a_Position, a_PoweringData);
|
||||
if (Previous.PowerLevel != a_PoweringData.PowerLevel)
|
||||
auto Previous = DataForChunk(a_Chunk).ExchangeUpdateOncePowerData(a_Position, a_PoweringData);
|
||||
if (Previous.PowerLevel == a_PoweringData.PowerLevel)
|
||||
{
|
||||
return {};
|
||||
return;
|
||||
}
|
||||
|
||||
a_World.DoWithHopperAt(a_Position.x, a_Position.y, a_Position.z, [a_PoweringData](cHopperEntity & a_Hopper)
|
||||
{
|
||||
a_Hopper.SetLocked(a_PoweringData.PowerLevel != 0);
|
||||
return false;
|
||||
}
|
||||
);
|
||||
return {};
|
||||
a_Chunk.DoWithHopperAt(a_Position, [a_PoweringData](cHopperEntity & a_Hopper)
|
||||
{
|
||||
a_Hopper.SetLocked(a_PoweringData.PowerLevel != 0);
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
virtual cVector3iArray GetValidSourcePositions(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override
|
||||
virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
|
||||
{
|
||||
UNUSED(a_World);
|
||||
UNUSED(a_Chunk);
|
||||
UNUSED(a_BlockType);
|
||||
UNUSED(a_Meta);
|
||||
return GetAdjustedRelatives(a_Position, GetRelativeAdjacents());
|
||||
InvokeForAdjustedRelatives(Callback, a_Position, RelativeAdjacents);
|
||||
}
|
||||
};
|
||||
|
@ -7,7 +7,6 @@
|
||||
|
||||
#include "CommandBlockHandler.h"
|
||||
#include "DoorHandler.h"
|
||||
#include "RedstoneHandler.h"
|
||||
#include "RedstoneTorchHandler.h"
|
||||
#include "RedstoneWireHandler.h"
|
||||
#include "RedstoneRepeaterHandler.h"
|
||||
@ -31,9 +30,10 @@
|
||||
|
||||
|
||||
|
||||
|
||||
const cRedstoneHandler * cIncrementalRedstoneSimulator::GetComponentHandler(BLOCKTYPE a_BlockType)
|
||||
{
|
||||
struct sComponents:
|
||||
struct sComponents :
|
||||
public std::array<std::unique_ptr<cRedstoneHandler>, 256>
|
||||
{
|
||||
sComponents()
|
||||
@ -128,76 +128,98 @@ std::unique_ptr<cRedstoneHandler> cIncrementalRedstoneSimulator::CreateComponent
|
||||
|
||||
|
||||
|
||||
void cIncrementalRedstoneSimulator::Simulate(float a_dt)
|
||||
void cIncrementalRedstoneSimulator::SimulateChunk(std::chrono::milliseconds a_Dt, int a_ChunkX, int a_ChunkZ, cChunk * a_Chunk)
|
||||
{
|
||||
for (auto & DelayInfo : m_Data.m_MechanismDelays)
|
||||
auto & ChunkData = *static_cast<cIncrementalRedstoneSimulatorChunkData *>(a_Chunk->GetRedstoneSimulatorData());
|
||||
for (auto & DelayInfo : ChunkData.m_MechanismDelays)
|
||||
{
|
||||
if ((--DelayInfo.second.first) == 0)
|
||||
{
|
||||
m_Data.GetActiveBlocks().emplace_back(DelayInfo.first);
|
||||
ChunkData.WakeUp(DelayInfo.first);
|
||||
}
|
||||
}
|
||||
|
||||
// Build our work queue
|
||||
cVector3iArray WorkQueue;
|
||||
std::swap(WorkQueue, m_Data.GetActiveBlocks());
|
||||
auto & WorkQueue = ChunkData.GetActiveBlocks();
|
||||
|
||||
// Process the work queue
|
||||
while (!WorkQueue.empty())
|
||||
{
|
||||
// Grab the first element and remove it from the list
|
||||
Vector3i CurrentLocation = WorkQueue.back();
|
||||
WorkQueue.pop_back();
|
||||
Vector3i CurrentLocation = WorkQueue.top();
|
||||
WorkQueue.pop();
|
||||
|
||||
BLOCKTYPE CurrentBlock;
|
||||
NIBBLETYPE CurrentMeta;
|
||||
if (!m_World.GetBlockTypeMeta(CurrentLocation.x, CurrentLocation.y, CurrentLocation.z, CurrentBlock, CurrentMeta))
|
||||
const auto NeighbourChunk = a_Chunk->GetRelNeighborChunkAdjustCoords(CurrentLocation);
|
||||
if ((NeighbourChunk == nullptr) || !NeighbourChunk->IsValid())
|
||||
{
|
||||
continue;
|
||||
return;
|
||||
}
|
||||
|
||||
auto CurrentHandler = GetComponentHandler(CurrentBlock);
|
||||
if (CurrentHandler == nullptr) // Block at CurrentPosition doesn't have a corresponding redstone handler
|
||||
{
|
||||
// Clean up cached PowerData for CurrentPosition
|
||||
GetChunkData()->ErasePowerData(CurrentLocation);
|
||||
continue;
|
||||
}
|
||||
|
||||
cRedstoneHandler::PoweringData Power;
|
||||
for (const auto & Location : CurrentHandler->GetValidSourcePositions(m_World, CurrentLocation, CurrentBlock, CurrentMeta))
|
||||
{
|
||||
if (!cChunk::IsValidHeight(Location.y))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
BLOCKTYPE PotentialBlock;
|
||||
NIBBLETYPE PotentialMeta;
|
||||
if (!m_World.GetBlockTypeMeta(Location.x, Location.y, Location.z, PotentialBlock, PotentialMeta))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
auto PotentialSourceHandler = GetComponentHandler(PotentialBlock);
|
||||
if (PotentialSourceHandler == nullptr)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
decltype(Power) PotentialPower(PotentialBlock, PotentialSourceHandler->GetPowerDeliveredToPosition(m_World, Location, PotentialBlock, PotentialMeta, CurrentLocation, CurrentBlock));
|
||||
Power = std::max(Power, PotentialPower);
|
||||
}
|
||||
|
||||
// Inform the handler to update
|
||||
cVector3iArray Updates = CurrentHandler->Update(m_World, CurrentLocation, CurrentBlock, CurrentMeta, Power);
|
||||
WorkQueue.insert(WorkQueue.end(), Updates.begin(), Updates.end());
|
||||
|
||||
if (IsAlwaysTicked(CurrentBlock))
|
||||
{
|
||||
m_Data.GetActiveBlocks().emplace_back(CurrentLocation);
|
||||
}
|
||||
ProcessWorkItem(*NeighbourChunk, *a_Chunk, CurrentLocation);
|
||||
}
|
||||
|
||||
for (const auto Position : ChunkData.AlwaysTickedPositions)
|
||||
{
|
||||
ChunkData.WakeUp(Position);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cIncrementalRedstoneSimulator::ProcessWorkItem(cChunk & Chunk, cChunk & TickingSource, const Vector3i Position)
|
||||
{
|
||||
auto & ChunkData = *static_cast<cIncrementalRedstoneSimulatorChunkData *>(Chunk.GetRedstoneSimulatorData());
|
||||
|
||||
BLOCKTYPE CurrentBlock;
|
||||
NIBBLETYPE CurrentMeta;
|
||||
Chunk.GetBlockTypeMeta(Position, CurrentBlock, CurrentMeta);
|
||||
|
||||
auto CurrentHandler = GetComponentHandler(CurrentBlock);
|
||||
if (CurrentHandler == nullptr) // Block at CurrentPosition doesn't have a corresponding redstone handler
|
||||
{
|
||||
// Clean up cached PowerData for CurrentPosition
|
||||
ChunkData.ErasePowerData(Position);
|
||||
return;
|
||||
}
|
||||
|
||||
PoweringData Power;
|
||||
CurrentHandler->ForValidSourcePositions(Chunk, Position, CurrentBlock, CurrentMeta, [&Chunk, Position, CurrentBlock, &Power](Vector3i Location)
|
||||
{
|
||||
if (!cChunk::IsValidHeight(Location.y))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const auto NeighbourChunk = Chunk.GetRelNeighborChunkAdjustCoords(Location);
|
||||
if ((NeighbourChunk == nullptr) || !NeighbourChunk->IsValid())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
BLOCKTYPE PotentialBlock;
|
||||
NIBBLETYPE PotentialMeta;
|
||||
NeighbourChunk->GetBlockTypeMeta(Location, PotentialBlock, PotentialMeta);
|
||||
|
||||
auto PotentialSourceHandler = GetComponentHandler(PotentialBlock);
|
||||
if (PotentialSourceHandler == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const PoweringData PotentialPower(
|
||||
PotentialBlock,
|
||||
PotentialSourceHandler->GetPowerDeliveredToPosition(
|
||||
*NeighbourChunk, Location, PotentialBlock, PotentialMeta,
|
||||
cIncrementalRedstoneSimulatorChunkData::RebaseRelativePosition(Chunk, *NeighbourChunk, Position), CurrentBlock
|
||||
)
|
||||
);
|
||||
Power = std::max(Power, PotentialPower);
|
||||
});
|
||||
|
||||
// Inform the handler to update
|
||||
CurrentHandler->Update(Chunk, TickingSource, Position, CurrentBlock, CurrentMeta, Power);
|
||||
}
|
||||
|
||||
|
||||
@ -206,27 +228,31 @@ void cIncrementalRedstoneSimulator::Simulate(float a_dt)
|
||||
|
||||
void cIncrementalRedstoneSimulator::AddBlock(Vector3i a_Block, cChunk * a_Chunk)
|
||||
{
|
||||
// Can't inspect block, so queue update anyway
|
||||
if (a_Chunk == nullptr)
|
||||
// Can't inspect block, ignore:
|
||||
if ((a_Chunk == nullptr) || (!a_Chunk->IsValid()))
|
||||
{
|
||||
m_Data.WakeUp(a_Block);
|
||||
return;
|
||||
}
|
||||
|
||||
const auto RelPos = cChunkDef::AbsoluteToRelative(a_Block, a_Chunk->GetPos());
|
||||
const auto CurBlock = a_Chunk->GetBlock(RelPos);
|
||||
auto & ChunkData = *static_cast<cIncrementalRedstoneSimulatorChunkData *>(a_Chunk->GetRedstoneSimulatorData());
|
||||
const auto Relative = cChunkDef::AbsoluteToRelative(a_Block, a_Chunk->GetPos());
|
||||
const auto CurrentBlock = a_Chunk->GetBlock(Relative);
|
||||
|
||||
// Always update redstone devices
|
||||
if (IsRedstone(CurBlock))
|
||||
if (IsRedstone(CurrentBlock))
|
||||
{
|
||||
m_Data.WakeUp(a_Block);
|
||||
if (IsAlwaysTicked(CurrentBlock))
|
||||
{
|
||||
ChunkData.AlwaysTickedPositions.emplace(Relative);
|
||||
}
|
||||
ChunkData.WakeUp(Relative);
|
||||
return;
|
||||
}
|
||||
|
||||
// Never update blocks without a handler
|
||||
if (GetComponentHandler(CurBlock) == nullptr)
|
||||
if (GetComponentHandler(CurrentBlock) == nullptr)
|
||||
{
|
||||
GetChunkData()->ErasePowerData(a_Block);
|
||||
ChunkData.ErasePowerData(Relative);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -235,14 +261,14 @@ void cIncrementalRedstoneSimulator::AddBlock(Vector3i a_Block, cChunk * a_Chunk)
|
||||
{
|
||||
for (int y = -1; y < 2; ++y)
|
||||
{
|
||||
if (!cChunkDef::IsValidHeight(RelPos.y + y))
|
||||
if (!cChunkDef::IsValidHeight(Relative.y + y))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int z = -1; z < 2; ++z)
|
||||
{
|
||||
auto CheckPos = RelPos + Vector3i{x, y, z};
|
||||
auto CheckPos = Relative + Vector3i{x, y, z};
|
||||
BLOCKTYPE Block;
|
||||
NIBBLETYPE Meta;
|
||||
|
||||
@ -252,7 +278,7 @@ void cIncrementalRedstoneSimulator::AddBlock(Vector3i a_Block, cChunk * a_Chunk)
|
||||
IsRedstone(Block)
|
||||
)
|
||||
{
|
||||
m_Data.WakeUp(a_Block);
|
||||
ChunkData.WakeUp(Relative);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -2,26 +2,29 @@
|
||||
#pragma once
|
||||
|
||||
#include "../RedstoneSimulator.h"
|
||||
#include "RedstoneHandler.h"
|
||||
#include "RedstoneSimulatorChunkData.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class cIncrementalRedstoneSimulator:
|
||||
class cIncrementalRedstoneSimulator final :
|
||||
public cRedstoneSimulator
|
||||
{
|
||||
using Super = cRedstoneSimulator;
|
||||
|
||||
public:
|
||||
|
||||
cIncrementalRedstoneSimulator(cWorld & a_World):
|
||||
cIncrementalRedstoneSimulator(cWorld & a_World) :
|
||||
Super(a_World)
|
||||
{
|
||||
}
|
||||
|
||||
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 Simulate(float Dt) override {};
|
||||
virtual void SimulateChunk(std::chrono::milliseconds Dt, int ChunkX, int ChunkZ, cChunk * Chunk) override;
|
||||
|
||||
void ProcessWorkItem(cChunk & Chunk, cChunk & TickingSource, const Vector3i Position);
|
||||
|
||||
virtual cIncrementalRedstoneSimulatorChunkData * CreateChunkData() override
|
||||
{
|
||||
@ -36,8 +39,7 @@ public:
|
||||
virtual void AddBlock(Vector3i a_Block, cChunk * a_Chunk) override;
|
||||
|
||||
/** 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 */
|
||||
inline static bool IsMechanism(BLOCKTYPE Block)
|
||||
{
|
||||
switch (Block)
|
||||
@ -158,14 +160,9 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
cIncrementalRedstoneSimulatorChunkData * GetChunkData() { return &m_Data; }
|
||||
|
||||
static const cRedstoneHandler * GetComponentHandler(BLOCKTYPE a_BlockType);
|
||||
|
||||
private:
|
||||
|
||||
static std::unique_ptr<cRedstoneHandler> CreateComponent(BLOCKTYPE a_BlockType);
|
||||
|
||||
// oh yea its crazy time
|
||||
cIncrementalRedstoneSimulatorChunkData m_Data;
|
||||
} ;
|
||||
|
@ -8,17 +8,13 @@
|
||||
|
||||
|
||||
|
||||
class cNoteBlockHandler:
|
||||
public cRedstoneHandler
|
||||
class cNoteBlockHandler: public cRedstoneHandler
|
||||
{
|
||||
using Super = cRedstoneHandler;
|
||||
|
||||
public:
|
||||
|
||||
virtual unsigned char GetPowerDeliveredToPosition(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
|
||||
virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
|
||||
{
|
||||
UNUSED(a_World);
|
||||
UNUSED(a_World);
|
||||
UNUSED(a_Chunk);
|
||||
UNUSED(a_Position);
|
||||
UNUSED(a_BlockType);
|
||||
UNUSED(a_Meta);
|
||||
@ -27,41 +23,29 @@ public:
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual unsigned char GetPowerLevel(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override
|
||||
{
|
||||
UNUSED(a_World);
|
||||
UNUSED(a_Position);
|
||||
UNUSED(a_BlockType);
|
||||
UNUSED(a_Meta);
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual cVector3iArray Update(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override
|
||||
virtual void Update(cChunk & a_Chunk, cChunk &, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override
|
||||
{
|
||||
// LOGD("Evaluating sparky the magical note block (%d %d %d) %i", a_Position.x, a_Position.y, a_Position.z, a_PoweringData.PowerLevel);
|
||||
|
||||
auto Previous = static_cast<cIncrementalRedstoneSimulator *>(a_World.GetRedstoneSimulator())->GetChunkData()->ExchangeUpdateOncePowerData(a_Position, a_PoweringData);
|
||||
auto Previous = DataForChunk(a_Chunk).ExchangeUpdateOncePowerData(a_Position, a_PoweringData);
|
||||
if ((Previous.PowerLevel != 0) || (a_PoweringData.PowerLevel == 0))
|
||||
{
|
||||
// If we're already powered or received an update of no power, don't make a sound
|
||||
return {};
|
||||
return;
|
||||
}
|
||||
|
||||
a_World.DoWithNoteBlockAt(a_Position.x, a_Position.y, a_Position.z, [](cNoteEntity & a_NoteBlock)
|
||||
{
|
||||
a_NoteBlock.MakeSound();
|
||||
return false;
|
||||
}
|
||||
);
|
||||
|
||||
return {};
|
||||
a_Chunk.DoWithNoteBlockAt(a_Position, [](cNoteEntity & a_NoteBlock)
|
||||
{
|
||||
a_NoteBlock.MakeSound();
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
virtual cVector3iArray GetValidSourcePositions(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override
|
||||
virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
|
||||
{
|
||||
UNUSED(a_World);
|
||||
UNUSED(a_Chunk);
|
||||
UNUSED(a_BlockType);
|
||||
UNUSED(a_Meta);
|
||||
return GetAdjustedRelatives(a_Position, GetRelativeAdjacents());
|
||||
InvokeForAdjustedRelatives(Callback, a_Position, RelativeAdjacents);
|
||||
}
|
||||
};
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
|
||||
|
||||
class cObserverHandler : public cRedstoneHandler
|
||||
class cObserverHandler final : public cRedstoneHandler
|
||||
{
|
||||
public:
|
||||
|
||||
@ -17,24 +17,24 @@ public:
|
||||
return (a_Meta & 0x8) == 0x8;
|
||||
}
|
||||
|
||||
static bool ShouldPowerOn(cWorld & a_World, const Vector3i a_Position, NIBBLETYPE a_Meta, cIncrementalRedstoneSimulatorChunkData * a_Data)
|
||||
static bool ShouldPowerOn(cChunk & Chunk, const Vector3i a_Position, NIBBLETYPE a_Meta, cIncrementalRedstoneSimulatorChunkData & a_Data)
|
||||
{
|
||||
BLOCKTYPE BlockType;
|
||||
NIBBLETYPE BlockMeta;
|
||||
if (!a_World.GetBlockTypeMeta(a_Position + cBlockObserverHandler::GetObservingFaceOffset(a_Meta), BlockType, BlockMeta))
|
||||
if (!Chunk.UnboundedRelGetBlock(a_Position + cBlockObserverHandler::GetObservingFaceOffset(a_Meta), BlockType, BlockMeta))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Cache the last seen block type and meta in the power data for this position
|
||||
auto Observed = PoweringData(BlockType, BlockMeta);
|
||||
auto Previous = a_Data->ExchangeUpdateOncePowerData(a_Position, Observed);
|
||||
auto Previous = a_Data.ExchangeUpdateOncePowerData(a_Position, Observed);
|
||||
|
||||
// Determine if to signal an update based on the block previously observed changed
|
||||
return (Previous.PoweringBlock != Observed.PoweringBlock) || (Previous.PowerLevel != Observed.PowerLevel);
|
||||
}
|
||||
|
||||
virtual unsigned char GetPowerDeliveredToPosition(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
|
||||
virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
|
||||
{
|
||||
if (IsOn(a_Meta) && (a_QueryPosition == (a_Position + cBlockObserverHandler::GetSignalOutputOffset(a_Meta))))
|
||||
{
|
||||
@ -44,30 +44,25 @@ public:
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual unsigned char GetPowerLevel(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override
|
||||
{
|
||||
return IsOn(a_BlockType) ? 15 : 0;
|
||||
}
|
||||
|
||||
virtual cVector3iArray Update(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override
|
||||
virtual void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override
|
||||
{
|
||||
// LOGD("Evaluating Lenny the observer (%i %i %i)", a_Position.x, a_Position.y, a_Position.z);
|
||||
|
||||
auto Data = static_cast<cIncrementalRedstoneSimulator *>(a_World.GetRedstoneSimulator())->GetChunkData();
|
||||
auto DelayInfo = Data->GetMechanismDelayInfo(a_Position);
|
||||
auto & Data = DataForChunk(a_Chunk);
|
||||
auto DelayInfo = Data.GetMechanismDelayInfo(a_Position);
|
||||
|
||||
if (DelayInfo == nullptr)
|
||||
{
|
||||
if (!ShouldPowerOn(a_World, a_Position, a_Meta, Data))
|
||||
if (!ShouldPowerOn(a_Chunk, a_Position, a_Meta, Data))
|
||||
{
|
||||
return {};
|
||||
return;
|
||||
}
|
||||
|
||||
// From rest, we've determined there was a block update
|
||||
// Schedule power-on 1 tick in the future
|
||||
Data->m_MechanismDelays[a_Position] = std::make_pair(1, true);
|
||||
Data.m_MechanismDelays[a_Position] = std::make_pair(1, true);
|
||||
|
||||
return {};
|
||||
return;
|
||||
}
|
||||
|
||||
int DelayTicks;
|
||||
@ -76,31 +71,30 @@ public:
|
||||
|
||||
if (DelayTicks != 0)
|
||||
{
|
||||
return {};
|
||||
return;
|
||||
}
|
||||
|
||||
if (ShouldPowerOn)
|
||||
{
|
||||
// Remain on for 1 tick before resetting
|
||||
*DelayInfo = std::make_pair(1, false);
|
||||
a_World.SetBlockMeta(a_Position, a_Meta | 0x8);
|
||||
a_Chunk.SetMeta(a_Position, a_Meta | 0x8);
|
||||
}
|
||||
else
|
||||
{
|
||||
// We've reset. Erase delay data in preparation for detecting further updates
|
||||
Data->m_MechanismDelays.erase(a_Position);
|
||||
a_World.SetBlockMeta(a_Position, a_Meta & ~0x8);
|
||||
Data.m_MechanismDelays.erase(a_Position);
|
||||
a_Chunk.SetMeta(a_Position, a_Meta & ~0x8);
|
||||
}
|
||||
|
||||
return { a_Position + cBlockObserverHandler::GetSignalOutputOffset(a_Meta) };
|
||||
UpdateAdjustedRelatives(a_Chunk, CurrentlyTicking, a_Position + cBlockObserverHandler::GetSignalOutputOffset(a_Meta));
|
||||
}
|
||||
|
||||
virtual cVector3iArray GetValidSourcePositions(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override
|
||||
virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
|
||||
{
|
||||
UNUSED(a_World);
|
||||
UNUSED(a_Chunk);
|
||||
UNUSED(a_Position);
|
||||
UNUSED(a_BlockType);
|
||||
UNUSED(a_BlockType);
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
@ -8,16 +8,13 @@
|
||||
|
||||
|
||||
|
||||
class cPistonHandler:
|
||||
public cRedstoneHandler
|
||||
class cPistonHandler final: public cRedstoneHandler
|
||||
{
|
||||
using Super = cRedstoneHandler;
|
||||
|
||||
public:
|
||||
|
||||
virtual unsigned char GetPowerDeliveredToPosition(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
|
||||
virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
|
||||
{
|
||||
UNUSED(a_World);
|
||||
UNUSED(a_Chunk);
|
||||
UNUSED(a_Position);
|
||||
UNUSED(a_BlockType);
|
||||
UNUSED(a_Meta);
|
||||
@ -26,52 +23,45 @@ public:
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual unsigned char GetPowerLevel(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override
|
||||
{
|
||||
UNUSED(a_World);
|
||||
UNUSED(a_Position);
|
||||
UNUSED(a_BlockType);
|
||||
UNUSED(a_Meta);
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual cVector3iArray Update(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override
|
||||
virtual void Update(cChunk & a_Chunk, cChunk &, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override
|
||||
{
|
||||
// LOGD("Evaluating pisty the piston (%d %d %d)", a_Position.x, a_Position.y, a_Position.z);
|
||||
|
||||
bool ShouldBeExtended = (a_PoweringData.PowerLevel != 0);
|
||||
const bool ShouldBeExtended = a_PoweringData.PowerLevel != 0;
|
||||
if (ShouldBeExtended == cBlockPistonHandler::IsExtended(a_Meta))
|
||||
{
|
||||
return {};
|
||||
return;
|
||||
}
|
||||
|
||||
a_Position = cChunkDef::RelativeToAbsolute(a_Position, a_Chunk.GetPos());
|
||||
|
||||
if (ShouldBeExtended)
|
||||
{
|
||||
cBlockPistonHandler::ExtendPiston(a_Position, a_World);
|
||||
cBlockPistonHandler::ExtendPiston(a_Position, *a_Chunk.GetWorld());
|
||||
}
|
||||
else
|
||||
{
|
||||
cBlockPistonHandler::RetractPiston(a_Position, a_World);
|
||||
cBlockPistonHandler::RetractPiston(a_Position, *a_Chunk.GetWorld());
|
||||
}
|
||||
|
||||
// It is necessary to delay after a signal to prevent an infinite loop (#3168)
|
||||
// However, that is present as a side effect of the implementation of piston animation in Blocks\BlockPiston.cpp
|
||||
|
||||
return {};
|
||||
// However, this delay is already present: as a side effect of the implementation of piston animation in Blocks\BlockPiston.cpp
|
||||
}
|
||||
|
||||
virtual cVector3iArray GetValidSourcePositions(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override
|
||||
virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
|
||||
{
|
||||
UNUSED(a_World);
|
||||
UNUSED(a_Chunk);
|
||||
UNUSED(a_BlockType);
|
||||
|
||||
auto PositionsOffset = GetRelativeAdjacents();
|
||||
auto Face = cBlockPistonHandler::MetaDataToDirection(a_Meta);
|
||||
int OffsetX = 0, OffsetY = 0, OffsetZ = 0;
|
||||
const auto Face = cBlockPistonHandler::MetaDataToDirection(a_Meta);
|
||||
const auto FrontOffset = AddFaceDirection(Vector3i(), Face);
|
||||
|
||||
AddFaceDirection(OffsetX, OffsetY, OffsetZ, Face);
|
||||
PositionsOffset.erase(std::remove(PositionsOffset.begin(), PositionsOffset.end(), Vector3i(OffsetX, OffsetY, OffsetZ)), PositionsOffset.end());
|
||||
|
||||
return GetAdjustedRelatives(a_Position, PositionsOffset);
|
||||
for (const auto Offset : RelativeAdjacents)
|
||||
{
|
||||
if (Offset != FrontOffset)
|
||||
{
|
||||
Callback(a_Position + Offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -7,11 +7,8 @@
|
||||
|
||||
|
||||
|
||||
class cPoweredRailHandler:
|
||||
public cRedstoneHandler
|
||||
class cPoweredRailHandler final : public cRedstoneHandler
|
||||
{
|
||||
using Super = cRedstoneHandler;
|
||||
|
||||
public:
|
||||
|
||||
static Vector3i GetPoweredRailAdjacentXZCoordinateOffset(NIBBLETYPE a_Meta) // Not in cBlockRailHandler since specific to powered rails
|
||||
@ -32,27 +29,20 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
virtual unsigned char GetPowerDeliveredToPosition(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
|
||||
virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
|
||||
{
|
||||
UNUSED(a_QueryBlockType);
|
||||
|
||||
auto Offset = GetPoweredRailAdjacentXZCoordinateOffset(a_Meta);
|
||||
if (((Offset + a_Position) == a_QueryPosition) || ((-Offset + a_Position) == a_QueryPosition))
|
||||
{
|
||||
auto Power = GetPowerLevel(a_World, a_Position, a_BlockType, a_Meta);
|
||||
auto Power = DataForChunk(a_Chunk).GetCachedPowerData(a_Position).PowerLevel;
|
||||
return (Power <= 7) ? 0 : --Power;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual unsigned char GetPowerLevel(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override
|
||||
{
|
||||
UNUSED(a_BlockType);
|
||||
UNUSED(a_Meta);
|
||||
return static_cast<cIncrementalRedstoneSimulator *>(a_World.GetRedstoneSimulator())->GetChunkData()->GetCachedPowerData(a_Position).PowerLevel;
|
||||
}
|
||||
|
||||
virtual cVector3iArray Update(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override
|
||||
virtual void Update(cChunk & a_Chunk, cChunk & CurrentlyTickingChunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override
|
||||
{
|
||||
// LOGD("Evaluating tracky the rail (%d %d %d)", a_Position.x, a_Position.y, a_Position.z);
|
||||
|
||||
@ -66,33 +56,37 @@ public:
|
||||
SetAllDirsAsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, a_MyType);
|
||||
}
|
||||
*/
|
||||
return {};
|
||||
return;
|
||||
}
|
||||
case E_BLOCK_ACTIVATOR_RAIL:
|
||||
case E_BLOCK_POWERED_RAIL:
|
||||
{
|
||||
auto Offset = GetPoweredRailAdjacentXZCoordinateOffset(a_Meta);
|
||||
if (a_PoweringData != static_cast<cIncrementalRedstoneSimulator *>(a_World.GetRedstoneSimulator())->GetChunkData()->ExchangeUpdateOncePowerData(a_Position, a_PoweringData))
|
||||
if (a_PoweringData != DataForChunk(a_Chunk).ExchangeUpdateOncePowerData(a_Position, a_PoweringData))
|
||||
{
|
||||
a_World.SetBlockMeta(a_Position, (a_PoweringData.PowerLevel == 0) ? (a_Meta & 0x07) : (a_Meta | 0x08));
|
||||
return cVector3iArray{ { Offset + a_Position }, { -Offset + a_Position } };
|
||||
a_Chunk.SetMeta(a_Position, (a_PoweringData.PowerLevel == 0) ? (a_Meta & 0x07) : (a_Meta | 0x08));
|
||||
|
||||
UpdateAdjustedRelatives(a_Chunk, CurrentlyTickingChunk, a_Position + Offset);
|
||||
UpdateAdjustedRelatives(a_Chunk, CurrentlyTickingChunk, a_Position + -Offset);
|
||||
}
|
||||
|
||||
return {};
|
||||
return;
|
||||
}
|
||||
default:
|
||||
{
|
||||
ASSERT(!"Unhandled type of rail in passed to rail handler!");
|
||||
return {};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual cVector3iArray GetValidSourcePositions(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override
|
||||
virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
|
||||
{
|
||||
UNUSED(a_World);
|
||||
UNUSED(a_BlockType);
|
||||
UNUSED(a_Chunk);
|
||||
UNUSED(a_Meta);
|
||||
return GetAdjustedRelatives(a_Position, GetRelativeAdjacents());
|
||||
|
||||
if ((a_BlockType == E_BLOCK_POWERED_RAIL) || (a_BlockType == E_BLOCK_ACTIVATOR_RAIL))
|
||||
{
|
||||
InvokeForAdjustedRelatives(Callback, a_Position, RelativeAdjacents);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -9,47 +9,42 @@
|
||||
|
||||
|
||||
|
||||
class cPressurePlateHandler:
|
||||
public cRedstoneHandler
|
||||
class cPressurePlateHandler final : public cRedstoneHandler
|
||||
{
|
||||
using Super = cRedstoneHandler;
|
||||
|
||||
public:
|
||||
|
||||
virtual unsigned char GetPowerDeliveredToPosition(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
|
||||
virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
|
||||
{
|
||||
UNUSED(a_BlockType);
|
||||
UNUSED(a_Meta);
|
||||
UNUSED(a_QueryPosition);
|
||||
UNUSED(a_QueryBlockType);
|
||||
|
||||
return static_cast<cIncrementalRedstoneSimulator *>(a_World.GetRedstoneSimulator())->GetChunkData()->GetCachedPowerData(a_Position).PowerLevel;
|
||||
return DataForChunk(a_Chunk).GetCachedPowerData(a_Position).PowerLevel;
|
||||
}
|
||||
|
||||
virtual unsigned char GetPowerLevel(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override
|
||||
static unsigned char GetPowerLevel(cChunk & Chunk, const Vector3i Position, const BLOCKTYPE BlockType)
|
||||
{
|
||||
UNUSED(a_Meta);
|
||||
|
||||
int NumberOfEntities = 0;
|
||||
unsigned NumberOfEntities = 0;
|
||||
bool FoundPlayer = false;
|
||||
a_World.ForEachEntityInBox(cBoundingBox(Vector3d(0.5, 0, 0.5) + a_Position, 0.5, 0.5), [&](cEntity & a_Entity)
|
||||
{
|
||||
if (a_Entity.IsPlayer())
|
||||
{
|
||||
FoundPlayer = true;
|
||||
}
|
||||
|
||||
if (a_Entity.IsPickup())
|
||||
{
|
||||
NumberOfEntities += static_cast<cPickup &>(a_Entity).GetItem().m_ItemCount;
|
||||
return false;
|
||||
}
|
||||
NumberOfEntities++;
|
||||
Chunk.ForEachEntityInBox(cBoundingBox(Vector3d(0.5, 0, 0.5) + Position, 0.5, 0.5), [&](cEntity & Entity)
|
||||
{
|
||||
if (Entity.IsPlayer())
|
||||
{
|
||||
FoundPlayer = true;
|
||||
}
|
||||
|
||||
if (Entity.IsPickup())
|
||||
{
|
||||
NumberOfEntities += static_cast<cPickup &>(Entity).GetItem().m_ItemCount;
|
||||
return false;
|
||||
}
|
||||
);
|
||||
NumberOfEntities++;
|
||||
return false;
|
||||
});
|
||||
|
||||
switch (a_BlockType)
|
||||
switch (BlockType)
|
||||
{
|
||||
case E_BLOCK_STONE_PRESSURE_PLATE:
|
||||
{
|
||||
@ -75,18 +70,22 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
virtual cVector3iArray Update(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override
|
||||
static void UpdatePlate(cChunk & Chunk, cChunk & CurrentlyTicking, Vector3i Position)
|
||||
{
|
||||
UpdateAdjustedRelatives(Chunk, CurrentlyTicking, Position, RelativeLaterals);
|
||||
UpdateAdjustedRelatives(Chunk, CurrentlyTicking, Position + OffsetYM);
|
||||
}
|
||||
|
||||
virtual void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override
|
||||
{
|
||||
UNUSED(a_PoweringData.PowerLevel);
|
||||
// LOGD("Evaluating clicky the pressure plate (%d %d %d)", a_Position.x, a_Position.y, a_Position.z);
|
||||
|
||||
auto ChunkData = static_cast<cIncrementalRedstoneSimulator *>(a_World.GetRedstoneSimulator())->GetChunkData();
|
||||
auto & ChunkData = DataForChunk(a_Chunk);
|
||||
|
||||
const auto PreviousPower = ChunkData->GetCachedPowerData(a_Position);
|
||||
auto Power = GetPowerLevel(a_World, a_Position, a_BlockType, a_Meta); // Get the current power of the platey
|
||||
|
||||
const auto PlateUpdates = GetAdjustedRelatives(a_Position, StaticAppend(GetRelativeLaterals(), cVector3iArray{ OffsetYM() }));
|
||||
auto DelayInfo = ChunkData->GetMechanismDelayInfo(a_Position);
|
||||
const auto PreviousPower = ChunkData.GetCachedPowerData(a_Position);
|
||||
const auto Absolute = cChunkDef::RelativeToAbsolute(a_Position, a_Chunk.GetPos());
|
||||
const auto Power = GetPowerLevel(a_Chunk, Absolute, a_BlockType); // Get the current power of the platey
|
||||
const auto DelayInfo = ChunkData.GetMechanismDelayInfo(a_Position);
|
||||
|
||||
// Resting state?
|
||||
if (DelayInfo == nullptr)
|
||||
@ -94,22 +93,21 @@ public:
|
||||
if (Power == 0)
|
||||
{
|
||||
// Nothing happened, back to rest
|
||||
return {};
|
||||
return;
|
||||
}
|
||||
|
||||
// From rest, a player stepped on us
|
||||
// Schedule a minimum 0.5 second delay before even thinking about releasing
|
||||
ChunkData->m_MechanismDelays[a_Position] = std::make_pair(5, true);
|
||||
ChunkData.m_MechanismDelays[a_Position] = std::make_pair(5, true);
|
||||
|
||||
auto soundToPlay = GetClickOnSound(a_BlockType);
|
||||
a_World.BroadcastSoundEffect(soundToPlay, a_Position, 0.5f, 0.6f);
|
||||
a_Chunk.GetWorld()->BroadcastSoundEffect(GetClickOnSound(a_BlockType), Absolute, 0.5f, 0.6f);
|
||||
|
||||
// Update power
|
||||
ChunkData->SetCachedPowerData(a_Position, PoweringData(a_BlockType, Power));
|
||||
ChunkData.SetCachedPowerData(a_Position, PoweringData(a_BlockType, Power));
|
||||
|
||||
// Immediately depress plate
|
||||
a_World.SetBlockMeta(a_Position, E_META_PRESSURE_PLATE_DEPRESSED);
|
||||
return PlateUpdates;
|
||||
a_Chunk.SetMeta(a_Position, E_META_PRESSURE_PLATE_DEPRESSED);
|
||||
return UpdatePlate(a_Chunk, CurrentlyTicking, a_Position);
|
||||
}
|
||||
|
||||
// Not a resting state
|
||||
@ -124,7 +122,7 @@ public:
|
||||
// Nothing changes, if there is nothing on it anymore, because the state is locked.
|
||||
if (Power == 0)
|
||||
{
|
||||
return {};
|
||||
return;
|
||||
}
|
||||
|
||||
// Yes. Are we waiting to release, and found that the player stepped on it again?
|
||||
@ -138,11 +136,11 @@ public:
|
||||
if (Power != PreviousPower.PowerLevel)
|
||||
{
|
||||
// Yes. Update power
|
||||
ChunkData->SetCachedPowerData(a_Position, PoweringData(a_BlockType, Power));
|
||||
return PlateUpdates;
|
||||
ChunkData.SetCachedPowerData(a_Position, PoweringData(a_BlockType, Power));
|
||||
return UpdatePlate(a_Chunk, CurrentlyTicking, a_Position);
|
||||
}
|
||||
|
||||
return {};
|
||||
return;
|
||||
}
|
||||
|
||||
// Not waiting for anything. Has the initial delay elapsed?
|
||||
@ -153,54 +151,51 @@ public:
|
||||
{
|
||||
// Yes. Go into subsequent release delay, for a further 0.5 seconds
|
||||
*DelayInfo = std::make_pair(5, false);
|
||||
return {};
|
||||
return;
|
||||
}
|
||||
|
||||
// Did the power level change and is still above zero?
|
||||
if (Power != PreviousPower.PowerLevel)
|
||||
{
|
||||
// Yes. Update power
|
||||
ChunkData->SetCachedPowerData(a_Position, PoweringData(a_BlockType, Power));
|
||||
return PlateUpdates;
|
||||
ChunkData.SetCachedPowerData(a_Position, PoweringData(a_BlockType, Power));
|
||||
return UpdatePlate(a_Chunk, CurrentlyTicking, a_Position);
|
||||
}
|
||||
|
||||
// Yes, but player's still on the plate, do nothing
|
||||
return {};
|
||||
return;
|
||||
}
|
||||
|
||||
// Just got out of the subsequent release phase, reset everything and raise the plate
|
||||
ChunkData->m_MechanismDelays.erase(a_Position);
|
||||
ChunkData.m_MechanismDelays.erase(a_Position);
|
||||
|
||||
auto soundToPlay = GetClickOffSound(a_BlockType);
|
||||
a_World.BroadcastSoundEffect(soundToPlay, a_Position, 0.5f, 0.5f);
|
||||
ChunkData->SetCachedPowerData(a_Position, PoweringData(a_BlockType, Power));
|
||||
a_Chunk.GetWorld()->BroadcastSoundEffect(GetClickOffSound(a_BlockType), Absolute, 0.5f, 0.5f);
|
||||
ChunkData.SetCachedPowerData(a_Position, PoweringData(a_BlockType, Power));
|
||||
|
||||
a_World.SetBlockMeta(a_Position, E_META_PRESSURE_PLATE_RAISED);
|
||||
return PlateUpdates;
|
||||
a_Chunk.SetMeta(a_Position, E_META_PRESSURE_PLATE_RAISED);
|
||||
return UpdatePlate(a_Chunk, CurrentlyTicking, a_Position);
|
||||
}
|
||||
|
||||
virtual cVector3iArray GetValidSourcePositions(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override
|
||||
virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
|
||||
{
|
||||
UNUSED(a_World);
|
||||
UNUSED(a_Chunk);
|
||||
UNUSED(a_Position);
|
||||
UNUSED(a_BlockType);
|
||||
UNUSED(a_Meta);
|
||||
return {};
|
||||
UNUSED(Callback);
|
||||
}
|
||||
|
||||
private:
|
||||
static AString GetClickOnSound(BLOCKTYPE a_BlockType)
|
||||
|
||||
static const char * GetClickOnSound(BLOCKTYPE a_BlockType)
|
||||
{
|
||||
// manage on-sound
|
||||
switch (a_BlockType)
|
||||
{
|
||||
case E_BLOCK_STONE_PRESSURE_PLATE:
|
||||
return "block.stone_pressureplate.click_on";
|
||||
case E_BLOCK_WOODEN_PRESSURE_PLATE:
|
||||
return "block.wood_pressureplate.click_on";
|
||||
case E_BLOCK_STONE_PRESSURE_PLATE: return "block.stone_pressureplate.click_on";
|
||||
case E_BLOCK_WOODEN_PRESSURE_PLATE: return "block.wood_pressureplate.click_on";
|
||||
case E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE:
|
||||
case E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE:
|
||||
return "block.metal_pressureplate.click_on";
|
||||
case E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE: return "block.metal_pressureplate.click_on";
|
||||
default:
|
||||
{
|
||||
ASSERT(!"No on sound for this one!");
|
||||
@ -209,18 +204,15 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
static AString GetClickOffSound(BLOCKTYPE a_BlockType)
|
||||
static const char * GetClickOffSound(BLOCKTYPE a_BlockType)
|
||||
{
|
||||
// manage off-sound
|
||||
switch (a_BlockType)
|
||||
{
|
||||
case E_BLOCK_STONE_PRESSURE_PLATE:
|
||||
return "block.stone_pressureplate.click_off";
|
||||
case E_BLOCK_WOODEN_PRESSURE_PLATE:
|
||||
return "block.wood_pressureplate.click_off";
|
||||
case E_BLOCK_STONE_PRESSURE_PLATE: return "block.stone_pressureplate.click_off";
|
||||
case E_BLOCK_WOODEN_PRESSURE_PLATE: return "block.wood_pressureplate.click_off";
|
||||
case E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE:
|
||||
case E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE:
|
||||
return "block.metal_pressureplate.click_off";
|
||||
case E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE: return "block.metal_pressureplate.click_off";
|
||||
default:
|
||||
{
|
||||
ASSERT(!"No off sound for this one!");
|
||||
|
@ -7,16 +7,13 @@
|
||||
|
||||
|
||||
|
||||
class cRedstoneBlockHandler:
|
||||
public cRedstoneHandler
|
||||
class cRedstoneBlockHandler final : public cRedstoneHandler
|
||||
{
|
||||
using Super = cRedstoneHandler;
|
||||
|
||||
public:
|
||||
|
||||
virtual unsigned char GetPowerDeliveredToPosition(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
|
||||
virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
|
||||
{
|
||||
UNUSED(a_World);
|
||||
UNUSED(a_Chunk);
|
||||
UNUSED(a_Position);
|
||||
UNUSED(a_BlockType);
|
||||
UNUSED(a_Meta);
|
||||
@ -24,27 +21,17 @@ public:
|
||||
return cIncrementalRedstoneSimulator::IsMechanism(a_QueryBlockType) ? 15 : 0;
|
||||
}
|
||||
|
||||
virtual unsigned char GetPowerLevel(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override
|
||||
{
|
||||
UNUSED(a_World);
|
||||
UNUSED(a_Position);
|
||||
UNUSED(a_BlockType);
|
||||
UNUSED(a_Meta);
|
||||
return 15;
|
||||
}
|
||||
|
||||
virtual cVector3iArray Update(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override
|
||||
virtual void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override
|
||||
{
|
||||
// LOGD("Evaluating crimson the redstone block (%d %d %d)", a_Position.x, a_Position.y, a_Position.z);
|
||||
return {};
|
||||
}
|
||||
|
||||
virtual cVector3iArray GetValidSourcePositions(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override
|
||||
virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
|
||||
{
|
||||
UNUSED(a_World);
|
||||
UNUSED(a_Chunk);
|
||||
UNUSED(a_Position);
|
||||
UNUSED(a_BlockType);
|
||||
UNUSED(a_Meta);
|
||||
return {};
|
||||
UNUSED(Callback);
|
||||
}
|
||||
};
|
||||
|
@ -8,14 +8,11 @@
|
||||
|
||||
|
||||
|
||||
class cRedstoneComparatorHandler:
|
||||
public cRedstoneHandler
|
||||
class cRedstoneComparatorHandler : public cRedstoneHandler
|
||||
{
|
||||
using Super = cRedstoneHandler;
|
||||
|
||||
public:
|
||||
|
||||
unsigned char GetFrontPowerLevel(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, unsigned char a_HighestSidePowerLevel, unsigned char a_HighestRearPowerLevel) const
|
||||
static unsigned char GetFrontPowerLevel(NIBBLETYPE a_Meta, unsigned char a_HighestSidePowerLevel, unsigned char a_HighestRearPowerLevel)
|
||||
{
|
||||
if (cBlockComparatorHandler::IsInSubtractionMode(a_Meta))
|
||||
{
|
||||
@ -29,107 +26,120 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
virtual unsigned char GetPowerDeliveredToPosition(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
|
||||
virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
|
||||
{
|
||||
UNUSED(a_QueryPosition);
|
||||
UNUSED(a_QueryBlockType);
|
||||
auto ChunkData = static_cast<cIncrementalRedstoneSimulator *>(a_World.GetRedstoneSimulator())->GetChunkData();
|
||||
|
||||
return (
|
||||
(cBlockComparatorHandler::GetFrontCoordinate(a_Position, a_Meta & 0x3) == a_QueryPosition) ?
|
||||
ChunkData->GetCachedPowerData(a_Position).PowerLevel : 0
|
||||
DataForChunk(a_Chunk).GetCachedPowerData(a_Position).PowerLevel : 0
|
||||
);
|
||||
}
|
||||
|
||||
virtual unsigned char GetPowerLevel(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override
|
||||
static unsigned char GetPowerLevel(cChunk & a_Chunk, Vector3i Position, BLOCKTYPE BlockType, NIBBLETYPE Meta)
|
||||
{
|
||||
UNUSED(a_Position);
|
||||
UNUSED(a_BlockType);
|
||||
|
||||
UInt8 SignalStrength = 0;
|
||||
auto RearCoordinate = cBlockComparatorHandler::GetRearCoordinate(a_Position, a_Meta & 0x3);
|
||||
a_World.DoWithBlockEntityAt(RearCoordinate.x, RearCoordinate.y, RearCoordinate.z, [&](cBlockEntity & a_BlockEntity)
|
||||
{
|
||||
// Skip BlockEntities that don't have slots
|
||||
auto BlockEntityWithItems = dynamic_cast<cBlockEntityWithItems *>(&a_BlockEntity);
|
||||
if (BlockEntityWithItems == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
auto RearCoordinate = cBlockComparatorHandler::GetRearCoordinate(Position, Meta & 0x3);
|
||||
|
||||
auto & Contents = BlockEntityWithItems->GetContents();
|
||||
float Fullness = 0; // Is a floating-point type to allow later calculation to produce a non-truncated value
|
||||
|
||||
for (int Slot = 0; Slot != Contents.GetNumSlots(); ++Slot)
|
||||
{
|
||||
Fullness += static_cast<float>(Contents.GetSlot(Slot).m_ItemCount) / Contents.GetSlot(Slot).GetMaxStackSize();
|
||||
}
|
||||
|
||||
SignalStrength = (Fullness < 0.001 /* container empty? */) ? 0 : static_cast<UInt8>(1 + (Fullness / Contents.GetNumSlots()) * 14);
|
||||
return false;
|
||||
}
|
||||
);
|
||||
auto RearPower = SignalStrength;
|
||||
auto RearType = a_World.GetBlock(RearCoordinate);
|
||||
|
||||
auto PotentialSourceHandler = cIncrementalRedstoneSimulator::GetComponentHandler(RearType);
|
||||
if (PotentialSourceHandler != nullptr)
|
||||
auto RearChunk = a_Chunk.GetRelNeighborChunkAdjustCoords(RearCoordinate);
|
||||
if ((RearChunk == nullptr) || !RearChunk->IsValid())
|
||||
{
|
||||
NIBBLETYPE RearMeta = a_World.GetBlockMeta(RearCoordinate);
|
||||
RearPower = std::max(SignalStrength, PotentialSourceHandler->GetPowerDeliveredToPosition(a_World, RearCoordinate, RearType, RearMeta, a_Position, a_BlockType));
|
||||
return SignalStrength;
|
||||
}
|
||||
|
||||
return RearPower;
|
||||
RearChunk->DoWithBlockEntityAt(RearCoordinate, [&](cBlockEntity & a_BlockEntity)
|
||||
{
|
||||
// Skip BlockEntities that don't have slots
|
||||
auto BlockEntityWithItems = dynamic_cast<cBlockEntityWithItems *>(&a_BlockEntity);
|
||||
if (BlockEntityWithItems == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: handle double chests
|
||||
|
||||
auto & Contents = BlockEntityWithItems->GetContents();
|
||||
float Fullness = 0; // Is a floating-point type to allow later calculation to produce a non-truncated value
|
||||
|
||||
for (int Slot = 0; Slot != Contents.GetNumSlots(); ++Slot)
|
||||
{
|
||||
Fullness += static_cast<float>(Contents.GetSlot(Slot).m_ItemCount) / Contents.GetSlot(Slot).GetMaxStackSize();
|
||||
}
|
||||
|
||||
SignalStrength = (Fullness < 0.001 /* container empty? */) ? 0 : static_cast<UInt8>(1 + (Fullness / Contents.GetNumSlots()) * 14);
|
||||
return false;
|
||||
});
|
||||
|
||||
BLOCKTYPE RearType;
|
||||
NIBBLETYPE RearMeta;
|
||||
RearChunk->GetBlockTypeMeta(RearCoordinate, RearType, RearMeta);
|
||||
|
||||
auto PotentialSourceHandler = cIncrementalRedstoneSimulator::GetComponentHandler(RearType);
|
||||
if (PotentialSourceHandler == nullptr)
|
||||
{
|
||||
return SignalStrength;
|
||||
}
|
||||
|
||||
return std::max(
|
||||
SignalStrength,
|
||||
PotentialSourceHandler->GetPowerDeliveredToPosition(
|
||||
*RearChunk, RearCoordinate, RearType, RearMeta,
|
||||
cIncrementalRedstoneSimulatorChunkData::RebaseRelativePosition(a_Chunk, *RearChunk, Position), BlockType
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
virtual cVector3iArray Update(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override
|
||||
virtual void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override
|
||||
{
|
||||
// Note that a_PoweringData here contains the maximum * side * power level, as specified by GetValidSourcePositions
|
||||
// LOGD("Evaluating ALU the comparator (%d %d %d)", a_Position.x, a_Position.y, a_Position.z);
|
||||
auto Data = static_cast<cIncrementalRedstoneSimulator *>(a_World.GetRedstoneSimulator())->GetChunkData();
|
||||
auto DelayInfo = Data->GetMechanismDelayInfo(a_Position);
|
||||
|
||||
auto & Data = DataForChunk(a_Chunk);
|
||||
auto DelayInfo = Data.GetMechanismDelayInfo(a_Position);
|
||||
|
||||
// Delay is used here to prevent an infinite loop (#3168)
|
||||
if (DelayInfo == nullptr)
|
||||
{
|
||||
auto RearPower = GetPowerLevel(a_World, a_Position, a_BlockType, a_Meta);
|
||||
auto FrontPower = GetFrontPowerLevel(a_World, a_Position, a_BlockType, a_Meta, a_PoweringData.PowerLevel, RearPower);
|
||||
auto PreviousFrontPower = Data->ExchangeUpdateOncePowerData(a_Position, PoweringData(a_PoweringData.PoweringBlock, FrontPower));
|
||||
const auto RearPower = GetPowerLevel(a_Chunk, a_Position, a_BlockType, a_Meta);
|
||||
const auto FrontPower = GetFrontPowerLevel(a_Meta, a_PoweringData.PowerLevel, RearPower);
|
||||
const auto PreviousFrontPower = Data.GetCachedPowerData(a_Position);
|
||||
const bool ShouldUpdate = (FrontPower != PreviousFrontPower.PowerLevel); // "Business logic" (:P) - determined by side and rear power levels
|
||||
|
||||
bool ShouldBeOn = (RearPower > 0); // Provide visual indication by examining * rear * power level
|
||||
bool ShouldUpdate = (FrontPower != PreviousFrontPower.PowerLevel); // "Business logic" (:P) - determine by examining *side* power levels
|
||||
|
||||
if (ShouldUpdate || (ShouldBeOn != cBlockComparatorHandler::IsOn(a_Meta)))
|
||||
if (ShouldUpdate)
|
||||
{
|
||||
Data->m_MechanismDelays[a_Position] = std::make_pair(1, ShouldBeOn);
|
||||
Data.m_MechanismDelays[a_Position] = std::make_pair(1, bool());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int DelayTicks;
|
||||
bool ShouldPowerOn;
|
||||
std::tie(DelayTicks, ShouldPowerOn) = *DelayInfo;
|
||||
std::tie(DelayTicks, std::ignore) = *DelayInfo;
|
||||
|
||||
if (DelayTicks == 0)
|
||||
{
|
||||
a_World.SetBlockMeta(a_Position, ShouldPowerOn ? (a_Meta | 0x8) : (a_Meta & 0x7));
|
||||
Data->m_MechanismDelays.erase(a_Position);
|
||||
const auto RearPower = GetPowerLevel(a_Chunk, a_Position, a_BlockType, a_Meta);
|
||||
const auto FrontPower = GetFrontPowerLevel(a_Meta, a_PoweringData.PowerLevel, RearPower);
|
||||
const auto NewMeta = (FrontPower > 0) ? (a_Meta | 0x8) : (a_Meta & 0x7);
|
||||
|
||||
// Assume that an update (to front power) is needed.
|
||||
// Note: potential inconsistencies will arise as power data is updated before-delay due to limitations of the power data caching functionality (only stores one bool)
|
||||
// This means that other mechanisms like wires may get our new power data before our delay has finished
|
||||
// This also means that we have to manually update ourselves to be aware of any changes that happened in the previous redstone tick
|
||||
return StaticAppend(GetAdjustedRelatives(a_Position, GetRelativeLaterals()), cVector3iArray{ a_Position });
|
||||
// Don't care about the previous power level so return value ignored
|
||||
Data.ExchangeUpdateOncePowerData(a_Position, PoweringData(a_PoweringData.PoweringBlock, FrontPower));
|
||||
|
||||
a_Chunk.SetMeta(a_Position, NewMeta);
|
||||
Data.m_MechanismDelays.erase(a_Position);
|
||||
|
||||
// Assume that an update (to front power) is needed:
|
||||
UpdateAdjustedRelatives(a_Chunk, CurrentlyTicking, cBlockComparatorHandler::GetFrontCoordinate(a_Position, a_Meta & 0x3));
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
virtual cVector3iArray GetValidSourcePositions(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override
|
||||
virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
|
||||
{
|
||||
UNUSED(a_World);
|
||||
UNUSED(a_Chunk);
|
||||
UNUSED(a_BlockType);
|
||||
return cVector3iArray {cBlockComparatorHandler::GetSideCoordinate(a_Position, a_Meta & 0x3, false), cBlockComparatorHandler::GetSideCoordinate(a_Position, a_Meta & 0x3, true)};
|
||||
|
||||
Callback(cBlockComparatorHandler::GetSideCoordinate(a_Position, a_Meta & 0x3, false));
|
||||
Callback(cBlockComparatorHandler::GetSideCoordinate(a_Position, a_Meta & 0x3, true));
|
||||
}
|
||||
};
|
||||
|
@ -1,7 +1,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../../World.h"
|
||||
#include "../../Chunk.h"
|
||||
#include "RedstoneSimulatorChunkData.h"
|
||||
|
||||
|
||||
|
||||
@ -14,50 +15,11 @@ public:
|
||||
cRedstoneHandler() = default;
|
||||
DISALLOW_COPY_AND_ASSIGN(cRedstoneHandler);
|
||||
|
||||
struct PoweringData
|
||||
{
|
||||
public:
|
||||
PoweringData(BLOCKTYPE a_PoweringBlock, unsigned char a_PowerLevel) :
|
||||
PoweringBlock(a_PoweringBlock),
|
||||
PowerLevel(a_PowerLevel)
|
||||
{
|
||||
}
|
||||
using SourceCallback = cFunctionRef<void(Vector3i)>;
|
||||
|
||||
PoweringData(void) :
|
||||
PoweringBlock(E_BLOCK_AIR),
|
||||
PowerLevel(0)
|
||||
{
|
||||
}
|
||||
|
||||
BLOCKTYPE PoweringBlock;
|
||||
unsigned char PowerLevel;
|
||||
|
||||
inline friend bool operator < (const PoweringData & a_Lhs, const PoweringData & a_Rhs)
|
||||
{
|
||||
return (
|
||||
(a_Lhs.PowerLevel < a_Rhs.PowerLevel) ||
|
||||
(
|
||||
(a_Lhs.PowerLevel == a_Rhs.PowerLevel) &&
|
||||
((a_Lhs.PoweringBlock == E_BLOCK_REDSTONE_WIRE) && (a_Rhs.PoweringBlock != E_BLOCK_REDSTONE_WIRE))
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
inline friend bool operator == (const PoweringData & a_Lhs, const PoweringData & a_Rhs)
|
||||
{
|
||||
return (a_Lhs.PowerLevel == a_Rhs.PowerLevel);
|
||||
}
|
||||
|
||||
inline friend bool operator != (const PoweringData & a_Lhs, const PoweringData & a_Rhs)
|
||||
{
|
||||
return !operator ==(a_Lhs, a_Rhs);
|
||||
}
|
||||
};
|
||||
|
||||
virtual cVector3iArray Update(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const = 0;
|
||||
virtual unsigned char GetPowerDeliveredToPosition(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const = 0;
|
||||
virtual unsigned char GetPowerLevel(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const = 0;
|
||||
virtual cVector3iArray GetValidSourcePositions(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const = 0;
|
||||
virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const = 0;
|
||||
virtual void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const = 0;
|
||||
virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const = 0;
|
||||
|
||||
// Force a virtual destructor
|
||||
virtual ~cRedstoneHandler() {}
|
||||
@ -72,15 +34,9 @@ protected:
|
||||
return ToReturn;
|
||||
}
|
||||
|
||||
inline static Vector3i OffsetYP()
|
||||
{
|
||||
return Vector3i(0, 1, 0);
|
||||
}
|
||||
inline static Vector3i OffsetYP{ 0, 1, 0 };
|
||||
|
||||
inline static Vector3i OffsetYM()
|
||||
{
|
||||
return Vector3i(0, -1, 0);
|
||||
}
|
||||
inline static Vector3i OffsetYM{ 0, -1, 0 };
|
||||
|
||||
static cVector3iArray GetAdjustedRelatives(Vector3i a_Position, cVector3iArray a_Relatives)
|
||||
{
|
||||
@ -91,31 +47,68 @@ protected:
|
||||
return a_Relatives;
|
||||
}
|
||||
|
||||
inline static cVector3iArray GetRelativeAdjacents()
|
||||
inline static cIncrementalRedstoneSimulatorChunkData & DataForChunk(cChunk & a_Chunk)
|
||||
{
|
||||
return
|
||||
{
|
||||
{
|
||||
{ 1, 0, 0 },
|
||||
{ -1, 0, 0 },
|
||||
{ 0, 1, 0 },
|
||||
{ 0, -1, 0 },
|
||||
{ 0, 0, 1 },
|
||||
{ 0, 0, -1 },
|
||||
}
|
||||
};
|
||||
return *static_cast<cIncrementalRedstoneSimulatorChunkData *>(a_Chunk.GetRedstoneSimulatorData());
|
||||
}
|
||||
|
||||
inline static cVector3iArray GetRelativeLaterals()
|
||||
template <typename... ArrayTypes>
|
||||
static void UpdateAdjustedRelatives(cChunk & From, cChunk & To, const Vector3i Position)
|
||||
{
|
||||
return
|
||||
DataForChunk(To).WakeUp(cIncrementalRedstoneSimulatorChunkData::RebaseRelativePosition(From, To, Position));
|
||||
}
|
||||
|
||||
template <typename ArrayType, typename... ArrayTypes>
|
||||
static void UpdateAdjustedRelatives(cChunk & From, cChunk & To, const Vector3i Position, const ArrayType & Relative, const ArrayTypes &... Relatives)
|
||||
{
|
||||
for (const auto Offset : Relative)
|
||||
{
|
||||
{
|
||||
{ 1, 0, 0 },
|
||||
{ -1, 0, 0 },
|
||||
{ 0, 0, 1 },
|
||||
{ 0, 0, -1 },
|
||||
}
|
||||
};
|
||||
DataForChunk(To).GetActiveBlocks().push(cIncrementalRedstoneSimulatorChunkData::RebaseRelativePosition(From, To, Position + Offset));
|
||||
}
|
||||
|
||||
UpdateAdjustedRelatives(From, To, Position, Relatives...);
|
||||
}
|
||||
|
||||
template <typename ArrayType, typename... ArrayTypes>
|
||||
static void InvokeForAdjustedRelatives(SourceCallback Callback, Vector3i Position, const ArrayType & Relative, const ArrayTypes &... Relatives)
|
||||
{
|
||||
for (const auto Offset : Relative)
|
||||
{
|
||||
Callback(Position + Offset);
|
||||
}
|
||||
|
||||
InvokeForAdjustedRelatives(Callback, Position, Relatives...);
|
||||
}
|
||||
|
||||
inline static std::array<Vector3i, 6> RelativeAdjacents
|
||||
{
|
||||
{
|
||||
{ 1, 0, 0 },
|
||||
{ -1, 0, 0 },
|
||||
{ 0, 1, 0 },
|
||||
{ 0, -1, 0 },
|
||||
{ 0, 0, 1 },
|
||||
{ 0, 0, -1 },
|
||||
}
|
||||
};
|
||||
|
||||
inline static std::array<Vector3i, 4> RelativeLaterals
|
||||
{
|
||||
{
|
||||
{ 1, 0, 0 },
|
||||
{ -1, 0, 0 },
|
||||
{ 0, 0, 1 },
|
||||
{ 0, 0, -1 },
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
static void UpdateAdjustedRelatives(cVector3iArray &, Vector3i)
|
||||
{
|
||||
}
|
||||
|
||||
static void InvokeForAdjustedRelatives(SourceCallback, Vector3i)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
|
||||
|
||||
class cRedstoneLampHandler : public cRedstoneHandler
|
||||
class cRedstoneLampHandler final : public cRedstoneHandler
|
||||
{
|
||||
public:
|
||||
|
||||
@ -14,17 +14,12 @@ public:
|
||||
return (a_BlockType == E_BLOCK_REDSTONE_LAMP_ON);
|
||||
}
|
||||
|
||||
virtual unsigned char GetPowerDeliveredToPosition(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
|
||||
virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual unsigned char GetPowerLevel(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual cVector3iArray Update(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override
|
||||
virtual void Update(cChunk & a_Chunk, cChunk &, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override
|
||||
{
|
||||
// LOGD("Evaluating lamp (%i %i %i)", a_Position.x, a_Position.y, a_Position.z);
|
||||
|
||||
@ -32,25 +27,23 @@ public:
|
||||
{
|
||||
if (!IsOn(a_BlockType))
|
||||
{
|
||||
a_World.SetBlock(a_Position.x, a_Position.y, a_Position.z, E_BLOCK_REDSTONE_LAMP_ON, 0);
|
||||
a_Chunk.FastSetBlock(a_Position, E_BLOCK_REDSTONE_LAMP_ON, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (IsOn(a_BlockType))
|
||||
{
|
||||
a_World.SetBlock(a_Position.x, a_Position.y, a_Position.z, E_BLOCK_REDSTONE_LAMP_OFF, 0);
|
||||
a_Chunk.FastSetBlock(a_Position, E_BLOCK_REDSTONE_LAMP_OFF, 0);
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
virtual cVector3iArray GetValidSourcePositions(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override
|
||||
virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
|
||||
{
|
||||
UNUSED(a_World);
|
||||
UNUSED(a_Chunk);
|
||||
UNUSED(a_Meta);
|
||||
UNUSED(a_BlockType);
|
||||
return GetAdjustedRelatives(a_Position, GetRelativeAdjacents());
|
||||
InvokeForAdjustedRelatives(Callback, a_Position, RelativeAdjacents);
|
||||
}
|
||||
};
|
||||
|
@ -15,37 +15,27 @@ class cRedstoneRepeaterHandler:
|
||||
|
||||
public:
|
||||
|
||||
virtual unsigned char GetPowerDeliveredToPosition(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
|
||||
virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
|
||||
{
|
||||
return (
|
||||
(a_QueryPosition == (a_Position + cBlockRedstoneRepeaterHandler::GetFrontCoordinateOffset(a_Meta))) ?
|
||||
GetPowerLevel(a_World, a_Position, a_BlockType, a_Meta) : 0
|
||||
);
|
||||
return ((a_QueryPosition == (a_Position + cBlockRedstoneRepeaterHandler::GetFrontCoordinateOffset(a_Meta))) && IsOn(a_BlockType)) ? 15 : 0;
|
||||
}
|
||||
|
||||
virtual unsigned char GetPowerLevel(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override
|
||||
{
|
||||
UNUSED(a_World);
|
||||
UNUSED(a_Position);
|
||||
UNUSED(a_Meta);
|
||||
return IsOn(a_BlockType) ? 15 : 0;
|
||||
}
|
||||
|
||||
virtual cVector3iArray Update(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override
|
||||
virtual void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override
|
||||
{
|
||||
// LOGD("Evaluating loopy the repeater (%d %d %d)", a_Position.x, a_Position.y, a_Position.z);
|
||||
auto Data = static_cast<cIncrementalRedstoneSimulator *>(a_World.GetRedstoneSimulator())->GetChunkData();
|
||||
auto DelayInfo = Data->GetMechanismDelayInfo(a_Position);
|
||||
|
||||
auto & Data = DataForChunk(a_Chunk);
|
||||
const auto DelayInfo = Data.GetMechanismDelayInfo(a_Position);
|
||||
|
||||
// If the repeater is locked by another, ignore and forget all power changes:
|
||||
if (IsLocked(a_World, a_Position, a_Meta))
|
||||
if (IsLocked(a_Chunk, a_Position, a_Meta))
|
||||
{
|
||||
if (DelayInfo != nullptr)
|
||||
{
|
||||
Data->m_MechanismDelays.erase(a_Position);
|
||||
Data.m_MechanismDelays.erase(a_Position);
|
||||
}
|
||||
|
||||
return {};
|
||||
return;
|
||||
}
|
||||
|
||||
if (DelayInfo == nullptr)
|
||||
@ -53,7 +43,7 @@ public:
|
||||
bool ShouldBeOn = (a_PoweringData.PowerLevel != 0);
|
||||
if (ShouldBeOn != IsOn(a_BlockType))
|
||||
{
|
||||
Data->m_MechanismDelays[a_Position] = std::make_pair((((a_Meta & 0xC) >> 0x2) + 1), ShouldBeOn);
|
||||
Data.m_MechanismDelays[a_Position] = std::make_pair((((a_Meta & 0xC) >> 0x2) + 1), ShouldBeOn);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -64,18 +54,23 @@ public:
|
||||
|
||||
if (DelayTicks == 0)
|
||||
{
|
||||
a_World.SetBlock(a_Position.x, a_Position.y, a_Position.z, ShouldPowerOn ? E_BLOCK_REDSTONE_REPEATER_ON : E_BLOCK_REDSTONE_REPEATER_OFF, a_Meta);
|
||||
Data->m_MechanismDelays.erase(a_Position);
|
||||
return cVector3iArray{ cBlockRedstoneRepeaterHandler::GetFrontCoordinateOffset(a_Meta) + a_Position };
|
||||
const auto NewType = ShouldPowerOn ? E_BLOCK_REDSTONE_REPEATER_ON : E_BLOCK_REDSTONE_REPEATER_OFF;
|
||||
a_Chunk.FastSetBlock(a_Position, NewType, a_Meta);
|
||||
Data.m_MechanismDelays.erase(a_Position);
|
||||
|
||||
// While sleeping, we ignore any power changes and apply our saved ShouldBeOn when sleep expires
|
||||
// Now, we need to recalculate to be aware of any new changes that may e.g. cause a new output change
|
||||
// FastSetBlock doesn't wake simulators, so manually update ourselves:
|
||||
Update(a_Chunk, CurrentlyTicking, a_Position, NewType, a_Meta, a_PoweringData);
|
||||
|
||||
UpdateAdjustedRelatives(a_Chunk, CurrentlyTicking, a_Position + cBlockRedstoneRepeaterHandler::GetFrontCoordinateOffset(a_Meta));
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
virtual cVector3iArray GetValidSourcePositions(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override
|
||||
virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
|
||||
{
|
||||
return { cBlockRedstoneRepeaterHandler::GetRearCoordinateOffset(a_Meta) + a_Position };
|
||||
Callback(cBlockRedstoneRepeaterHandler::GetRearCoordinateOffset(a_Meta) + a_Position);
|
||||
}
|
||||
|
||||
private:
|
||||
@ -87,12 +82,12 @@ private:
|
||||
|
||||
/** Returns a pair with first element indicating if the block at the given position is an activated repeater.
|
||||
If it is activated, the second element is the repeater metadata. */
|
||||
static std::pair<bool, NIBBLETYPE> IsOnRepeater(cWorld & a_World, const Vector3i a_Position)
|
||||
static std::pair<bool, NIBBLETYPE> IsOnRepeater(cChunk & Chunk, const Vector3i a_Position)
|
||||
{
|
||||
BLOCKTYPE Type;
|
||||
NIBBLETYPE Meta;
|
||||
|
||||
if (!a_World.GetBlockTypeMeta(a_Position, Type, Meta))
|
||||
if (!Chunk.UnboundedRelGetBlock(a_Position, Type, Meta))
|
||||
{
|
||||
return std::make_pair(false, 0);
|
||||
}
|
||||
@ -103,20 +98,20 @@ private:
|
||||
/** Determine if a repeater is locked.
|
||||
A locked repeater is one with another powered repeater facing them, to their immediate left or right sides.
|
||||
"Left" is relative to the direction the repeater output faces, naturally. */
|
||||
inline static bool IsLocked(cWorld & a_World, const Vector3i a_Position, const NIBBLETYPE a_Meta)
|
||||
inline static bool IsLocked(cChunk & Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta)
|
||||
{
|
||||
// The left hand side offset. Will be negated to get the rhs offset
|
||||
const auto LhsOffset = cBlockRedstoneRepeaterHandler::GetLeftCoordinateOffset(a_Meta);
|
||||
|
||||
// Test the block to the left of us
|
||||
const auto Lhs = IsOnRepeater(a_World, LhsOffset + a_Position);
|
||||
const auto Lhs = IsOnRepeater(Chunk, LhsOffset + a_Position);
|
||||
if (Lhs.first && DoesLhsLockMe(Lhs.second, a_Meta))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Test the right side, flipping the argument order to DoesLhsLockMe
|
||||
const auto Rhs = IsOnRepeater(a_World, -LhsOffset + a_Position);
|
||||
const auto Rhs = IsOnRepeater(Chunk, -LhsOffset + a_Position);
|
||||
return Rhs.first && DoesLhsLockMe(a_Meta, Rhs.second);
|
||||
}
|
||||
|
||||
|
@ -1,73 +1,132 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "RedstoneHandler.h"
|
||||
#include <stack>
|
||||
|
||||
#include "../RedstoneSimulator.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
struct PoweringData
|
||||
{
|
||||
public:
|
||||
PoweringData(BLOCKTYPE a_PoweringBlock, unsigned char a_PowerLevel) :
|
||||
PoweringBlock(a_PoweringBlock),
|
||||
PowerLevel(a_PowerLevel)
|
||||
{
|
||||
}
|
||||
|
||||
PoweringData(void) :
|
||||
PoweringBlock(E_BLOCK_AIR),
|
||||
PowerLevel(0)
|
||||
{
|
||||
}
|
||||
|
||||
BLOCKTYPE PoweringBlock;
|
||||
unsigned char PowerLevel;
|
||||
|
||||
inline friend bool operator < (const PoweringData & Lhs, const PoweringData & Rhs)
|
||||
{
|
||||
return (
|
||||
(Lhs.PowerLevel < Rhs.PowerLevel) ||
|
||||
(
|
||||
(Lhs.PowerLevel == Rhs.PowerLevel) &&
|
||||
((Lhs.PoweringBlock == E_BLOCK_REDSTONE_WIRE) && (Rhs.PoweringBlock != E_BLOCK_REDSTONE_WIRE))
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
inline friend bool operator == (const PoweringData & Lhs, const PoweringData & Rhs)
|
||||
{
|
||||
return (Lhs.PowerLevel == Rhs.PowerLevel);
|
||||
}
|
||||
|
||||
inline friend bool operator != (const PoweringData & Lhs, const PoweringData & Rhs)
|
||||
{
|
||||
return !operator ==(Lhs, Rhs);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class cIncrementalRedstoneSimulatorChunkData : public cRedstoneSimulatorChunkData
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
void WakeUp(const Vector3i & a_Position)
|
||||
{
|
||||
m_ActiveBlocks.push_back(a_Position);
|
||||
ActiveBlocks.push(a_Position);
|
||||
}
|
||||
|
||||
cVector3iArray & GetActiveBlocks()
|
||||
auto & GetActiveBlocks()
|
||||
{
|
||||
return m_ActiveBlocks;
|
||||
return ActiveBlocks;
|
||||
}
|
||||
|
||||
const cRedstoneHandler::PoweringData GetCachedPowerData(const Vector3i & a_Position) const
|
||||
const PoweringData GetCachedPowerData(const Vector3i Position) const
|
||||
{
|
||||
auto Result = m_CachedPowerLevels.find(a_Position);
|
||||
return (Result == m_CachedPowerLevels.end()) ? cRedstoneHandler::PoweringData() : Result->second;
|
||||
auto Result = CachedPowerLevels.find(Position);
|
||||
return (Result == CachedPowerLevels.end()) ? PoweringData() : Result->second;
|
||||
}
|
||||
|
||||
void SetCachedPowerData(const Vector3i & a_Position, cRedstoneHandler::PoweringData a_PoweringData)
|
||||
void SetCachedPowerData(const Vector3i Position, PoweringData PoweringData)
|
||||
{
|
||||
m_CachedPowerLevels[a_Position] = a_PoweringData;
|
||||
CachedPowerLevels[Position] = PoweringData;
|
||||
}
|
||||
|
||||
std::pair<int, bool> * GetMechanismDelayInfo(const Vector3i & a_Position)
|
||||
std::pair<int, bool> * GetMechanismDelayInfo(const Vector3i Position)
|
||||
{
|
||||
auto Result = m_MechanismDelays.find(a_Position);
|
||||
auto Result = m_MechanismDelays.find(Position);
|
||||
return (Result == m_MechanismDelays.end()) ? nullptr : &Result->second;
|
||||
}
|
||||
|
||||
/** Erase cached PowerData for position */
|
||||
void ErasePowerData(const Vector3i & a_Position)
|
||||
/** Erase all cached redstone data for position. */
|
||||
void ErasePowerData(const Vector3i Position)
|
||||
{
|
||||
m_CachedPowerLevels.erase(a_Position);
|
||||
m_MechanismDelays.erase(a_Position);
|
||||
CachedPowerLevels.erase(Position);
|
||||
m_MechanismDelays.erase(Position);
|
||||
AlwaysTickedPositions.erase(Position);
|
||||
}
|
||||
|
||||
cRedstoneHandler::PoweringData ExchangeUpdateOncePowerData(const Vector3i & a_Position, cRedstoneHandler::PoweringData a_PoweringData)
|
||||
PoweringData ExchangeUpdateOncePowerData(const Vector3i & a_Position, PoweringData a_PoweringData)
|
||||
{
|
||||
auto Result = m_CachedPowerLevels.find(a_Position);
|
||||
if (Result == m_CachedPowerLevels.end())
|
||||
auto Result = CachedPowerLevels.find(a_Position);
|
||||
if (Result == CachedPowerLevels.end())
|
||||
{
|
||||
m_CachedPowerLevels[a_Position] = a_PoweringData;
|
||||
return cRedstoneHandler::PoweringData();
|
||||
CachedPowerLevels[a_Position] = a_PoweringData;
|
||||
return PoweringData();
|
||||
}
|
||||
std::swap(Result->second, a_PoweringData);
|
||||
return a_PoweringData;
|
||||
}
|
||||
|
||||
/** Adjust From-relative coordinates into To-relative coordinates. */
|
||||
inline static Vector3i RebaseRelativePosition(cChunk & From, cChunk & To, const Vector3i Position)
|
||||
{
|
||||
return
|
||||
{
|
||||
Position.x + (From.GetPosX() - To.GetPosX()) * cChunkDef::Width,
|
||||
Position.y,
|
||||
Position.z + (From.GetPosZ() - To.GetPosZ()) * cChunkDef::Width
|
||||
};
|
||||
}
|
||||
|
||||
std::unordered_set<Vector3i, VectorHasher<int>> AlwaysTickedPositions;
|
||||
|
||||
/** Structure storing position of mechanism + it's delay ticks (countdown) & if to power on */
|
||||
std::unordered_map<Vector3i, std::pair<int, bool>, VectorHasher<int>> m_MechanismDelays;
|
||||
|
||||
private:
|
||||
|
||||
cVector3iArray m_ActiveBlocks;
|
||||
std::stack<Vector3i, std::vector<Vector3i>> ActiveBlocks;
|
||||
|
||||
// TODO: map<Vector3i, int> -> Position of torch + it's heat level
|
||||
|
||||
std::unordered_map<Vector3i, cRedstoneHandler::PoweringData, VectorHasher<int>> m_CachedPowerLevels;
|
||||
std::unordered_map<Vector3i, PoweringData, VectorHasher<int>> CachedPowerLevels;
|
||||
|
||||
friend class cRedstoneHandlerFactory;
|
||||
|
||||
|
@ -9,11 +9,8 @@
|
||||
|
||||
|
||||
|
||||
class cRedstoneToggleHandler:
|
||||
public cRedstoneHandler
|
||||
class cRedstoneToggleHandler final : public cRedstoneHandler
|
||||
{
|
||||
using Super = cRedstoneHandler;
|
||||
|
||||
public:
|
||||
|
||||
inline static Vector3i GetPositionAttachedTo(Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta)
|
||||
@ -65,21 +62,18 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
virtual unsigned char GetPowerDeliveredToPosition(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
|
||||
virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
|
||||
{
|
||||
UNUSED(a_QueryBlockType);
|
||||
if ((GetPositionAttachedTo(a_Position, a_BlockType, a_Meta) == a_QueryPosition) || cIncrementalRedstoneSimulator::IsMechanism(a_QueryBlockType))
|
||||
{
|
||||
return GetPowerLevel(a_World, a_Position, a_BlockType, a_Meta);
|
||||
return GetPowerLevel(a_BlockType, a_Meta);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual unsigned char GetPowerLevel(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override
|
||||
static unsigned char GetPowerLevel(BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta)
|
||||
{
|
||||
UNUSED(a_World);
|
||||
UNUSED(a_Position);
|
||||
|
||||
switch (a_BlockType)
|
||||
{
|
||||
case E_BLOCK_LEVER: return cBlockLeverHandler::IsLeverOn(a_Meta) ? 15 : 0;
|
||||
@ -93,18 +87,17 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
virtual cVector3iArray Update(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override
|
||||
virtual void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override
|
||||
{
|
||||
// LOGD("Evaluating templatio<> the lever/button (%d %d %d)", a_Position.x, a_Position.y, a_Position.z);
|
||||
return {};
|
||||
}
|
||||
|
||||
virtual cVector3iArray GetValidSourcePositions(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override
|
||||
virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
|
||||
{
|
||||
UNUSED(a_World);
|
||||
UNUSED(a_Chunk);
|
||||
UNUSED(a_Position);
|
||||
UNUSED(a_BlockType);
|
||||
UNUSED(a_Meta);
|
||||
return {};
|
||||
UNUSED(Callback);
|
||||
}
|
||||
};
|
||||
|
@ -7,7 +7,7 @@
|
||||
|
||||
|
||||
|
||||
class cRedstoneTorchHandler : public cRedstoneHandler
|
||||
class cRedstoneTorchHandler final : public cRedstoneHandler
|
||||
{
|
||||
public:
|
||||
|
||||
@ -33,12 +33,12 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
virtual unsigned char GetPowerDeliveredToPosition(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
|
||||
virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
|
||||
{
|
||||
if (
|
||||
IsOn(a_BlockType) &&
|
||||
(a_QueryPosition != (a_Position + GetOffsetAttachedTo(a_Position, a_Meta))) &&
|
||||
(cIncrementalRedstoneSimulator::IsMechanism(a_QueryBlockType) || (cBlockInfo::FullyOccupiesVoxel(a_QueryBlockType) && (a_QueryPosition == (a_Position + OffsetYP()))))
|
||||
(cIncrementalRedstoneSimulator::IsMechanism(a_QueryBlockType) || (cBlockInfo::FullyOccupiesVoxel(a_QueryBlockType) && (a_QueryPosition == (a_Position + OffsetYP))))
|
||||
)
|
||||
{
|
||||
return 15;
|
||||
@ -46,24 +46,19 @@ public:
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual unsigned char GetPowerLevel(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override
|
||||
{
|
||||
return IsOn(a_BlockType) ? 15 : 0;
|
||||
}
|
||||
|
||||
virtual cVector3iArray Update(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override
|
||||
virtual void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override
|
||||
{
|
||||
// LOGD("Evaluating torchy the redstone torch (%i %i %i)", a_Position.x, a_Position.y, a_Position.z);
|
||||
|
||||
auto Data = static_cast<cIncrementalRedstoneSimulator *>(a_World.GetRedstoneSimulator())->GetChunkData();
|
||||
auto DelayInfo = Data->GetMechanismDelayInfo(a_Position);
|
||||
auto & Data = DataForChunk(a_Chunk);
|
||||
auto DelayInfo = Data.GetMechanismDelayInfo(a_Position);
|
||||
|
||||
if (DelayInfo == nullptr)
|
||||
{
|
||||
bool ShouldBeOn = (a_PoweringData.PowerLevel == 0);
|
||||
if (ShouldBeOn != IsOn(a_BlockType))
|
||||
{
|
||||
Data->m_MechanismDelays[a_Position] = std::make_pair(1, ShouldBeOn);
|
||||
Data.m_MechanismDelays[a_Position] = std::make_pair(1, ShouldBeOn);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -72,24 +67,28 @@ public:
|
||||
bool ShouldPowerOn;
|
||||
std::tie(DelayTicks, ShouldPowerOn) = *DelayInfo;
|
||||
|
||||
if (DelayTicks == 0)
|
||||
if (DelayTicks != 0)
|
||||
{
|
||||
a_World.SetBlock(a_Position.x, a_Position.y, a_Position.z, ShouldPowerOn ? E_BLOCK_REDSTONE_TORCH_ON : E_BLOCK_REDSTONE_TORCH_OFF, a_Meta);
|
||||
Data->m_MechanismDelays.erase(a_Position);
|
||||
return;
|
||||
}
|
||||
|
||||
cVector3iArray RelativePositions = GetRelativeAdjacents();
|
||||
RelativePositions.erase(std::remove(RelativePositions.begin(), RelativePositions.end(), GetOffsetAttachedTo(a_Position, a_Meta)), RelativePositions.end());
|
||||
return GetAdjustedRelatives(a_Position, RelativePositions);
|
||||
a_Chunk.SetBlock(a_Position, ShouldPowerOn ? E_BLOCK_REDSTONE_TORCH_ON : E_BLOCK_REDSTONE_TORCH_OFF, a_Meta);
|
||||
Data.m_MechanismDelays.erase(a_Position);
|
||||
|
||||
for (const auto Adjacent : RelativeAdjacents)
|
||||
{
|
||||
if (Adjacent != GetOffsetAttachedTo(a_Position, a_Meta))
|
||||
{
|
||||
UpdateAdjustedRelatives(a_Chunk, CurrentlyTicking, a_Position + Adjacent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
virtual cVector3iArray GetValidSourcePositions(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override
|
||||
virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
|
||||
{
|
||||
UNUSED(a_World);
|
||||
UNUSED(a_Chunk);
|
||||
UNUSED(a_BlockType);
|
||||
return { (a_Position + GetOffsetAttachedTo(a_Position, a_Meta)) };
|
||||
Callback(a_Position + GetOffsetAttachedTo(a_Position, a_Meta));
|
||||
}
|
||||
};
|
||||
|
@ -7,11 +7,8 @@
|
||||
|
||||
|
||||
|
||||
class cRedstoneWireHandler:
|
||||
public cRedstoneHandler
|
||||
class cRedstoneWireHandler final : public cRedstoneHandler
|
||||
{
|
||||
using Super = cRedstoneHandler;
|
||||
|
||||
public:
|
||||
|
||||
inline static bool IsDirectlyConnectingMechanism(BLOCKTYPE a_Block, NIBBLETYPE a_BlockMeta, const Vector3i a_Offset)
|
||||
@ -40,133 +37,170 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
cVector3iArray GetTerracingConnectionOffsets(cWorld & a_World, const Vector3i a_Position) const
|
||||
template <class OffsetCallback>
|
||||
static bool ForTerracingConnectionOffsets(cChunk & a_Chunk, const Vector3i a_Position, OffsetCallback Callback)
|
||||
{
|
||||
auto RelativePositions = GetRelativeLaterals();
|
||||
const auto YPTerraceBlock = a_World.GetBlock(a_Position + OffsetYP());
|
||||
const auto YPTerraceBlock = a_Chunk.GetBlock(a_Position + OffsetYP);
|
||||
const bool IsYPTerracingBlocked = cBlockInfo::IsSolid(YPTerraceBlock) && !cBlockInfo::IsTransparent(YPTerraceBlock);
|
||||
|
||||
for (const auto & Adjacent : GetRelativeLaterals())
|
||||
for (const auto Adjacent : RelativeLaterals)
|
||||
{
|
||||
if (
|
||||
// A block above us blocks all YP terracing, so the check is static in the loop
|
||||
!IsYPTerracingBlocked &&
|
||||
(a_World.GetBlock(a_Position + Adjacent + OffsetYP()) == E_BLOCK_REDSTONE_WIRE)
|
||||
)
|
||||
// All laterals are counted as terracing, duh
|
||||
if (Callback(Adjacent))
|
||||
{
|
||||
RelativePositions.emplace_back(Adjacent + OffsetYP());
|
||||
return true;
|
||||
}
|
||||
|
||||
const auto YMTerraceBlock = a_World.GetBlock(a_Position + Adjacent);
|
||||
if (
|
||||
// IsYMTerracingBlocked (i.e. check block above lower terracing position, a.k.a. just the plain adjacent)
|
||||
(!cBlockInfo::IsSolid(YMTerraceBlock) || cBlockInfo::IsTransparent(YMTerraceBlock)) &&
|
||||
(a_World.GetBlock(a_Position + Adjacent + OffsetYM()) == E_BLOCK_REDSTONE_WIRE)
|
||||
BLOCKTYPE YPBlock;
|
||||
|
||||
// A block above us blocks all YP terracing, so the check is static in the loop
|
||||
!IsYPTerracingBlocked &&
|
||||
a_Chunk.UnboundedRelGetBlockType(a_Position + Adjacent + OffsetYP, YPBlock) &&
|
||||
(YPBlock == E_BLOCK_REDSTONE_WIRE)
|
||||
)
|
||||
{
|
||||
RelativePositions.emplace_back(Adjacent + OffsetYM());
|
||||
if (Callback(Adjacent + OffsetYP))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
BLOCKTYPE YMTerraceBlock, YMDiagonalBlock;
|
||||
|
||||
// IsYMTerracingBlocked (i.e. check block above lower terracing position, a.k.a. just the plain adjacent)
|
||||
a_Chunk.UnboundedRelGetBlockType(a_Position + Adjacent, YMTerraceBlock) &&
|
||||
(!cBlockInfo::IsSolid(YMTerraceBlock) || cBlockInfo::IsTransparent(YMTerraceBlock)) &&
|
||||
|
||||
a_Chunk.UnboundedRelGetBlockType(a_Position + Adjacent + OffsetYM, YMDiagonalBlock) &&
|
||||
(YMDiagonalBlock == E_BLOCK_REDSTONE_WIRE)
|
||||
)
|
||||
{
|
||||
if (Callback(Adjacent + OffsetYM))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return RelativePositions;
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual unsigned char GetPowerDeliveredToPosition(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
|
||||
virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
|
||||
{
|
||||
if (a_QueryPosition == (a_Position + OffsetYP()))
|
||||
if (a_QueryPosition == (a_Position + OffsetYP))
|
||||
{
|
||||
// Wires do not power things above them
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (a_QueryBlockType != E_BLOCK_REDSTONE_WIRE)
|
||||
if (a_QueryBlockType == E_BLOCK_REDSTONE_WIRE)
|
||||
{
|
||||
// For mechanisms, wire of power one will still power them
|
||||
a_Meta++;
|
||||
// But for wire-to-wire connections, power level decreases by 1
|
||||
return (a_Meta != 0) ? --a_Meta : a_Meta;
|
||||
}
|
||||
|
||||
// Wires always deliver power to the block underneath, and any directly connecting mechanisms
|
||||
if (
|
||||
(a_QueryPosition != (a_Position + OffsetYM())) &&
|
||||
!IsDirectlyConnectingMechanism(a_QueryBlockType, a_World.GetBlockMeta(a_QueryPosition), a_QueryPosition - a_Position)
|
||||
NIBBLETYPE QueryMeta;
|
||||
|
||||
(a_QueryPosition == (a_Position + OffsetYM)) ||
|
||||
(a_Chunk.UnboundedRelGetBlockMeta(a_QueryPosition, QueryMeta) && IsDirectlyConnectingMechanism(a_QueryBlockType, QueryMeta, a_QueryPosition - a_Position))
|
||||
)
|
||||
{
|
||||
/*
|
||||
Okay, we do not directly connect to the wire.
|
||||
If there are no DC mechanisms at all, the wire powers all laterals. Great, we fall out the loop.
|
||||
If there is one DC mechanism, the wire "goes straight" along the axis of the wire and mechanism.
|
||||
The only possible way for us to be powered is for us to be on the opposite end, with the wire pointing towards us.
|
||||
If there is more than one DC, no non-DCs are powered.
|
||||
*/
|
||||
return a_Meta;
|
||||
}
|
||||
|
||||
Vector3i PotentialOffset;
|
||||
bool FoundOneBorderingMechanism = false;
|
||||
/*
|
||||
Okay, we do not directly connect to the wire.
|
||||
If there are no DC mechanisms at all, the wire powers all laterals. Great, we fall out the loop.
|
||||
If there is one DC mechanism, the wire "goes straight" along the axis of the wire and mechanism.
|
||||
The only possible way for us to be powered is for us to be on the opposite end, with the wire pointing towards us.
|
||||
If there is more than one DC, no non-DCs are powered.
|
||||
*/
|
||||
|
||||
for (const auto & Offset : GetTerracingConnectionOffsets(a_World, a_Position))
|
||||
Vector3i PotentialOffset;
|
||||
bool FoundOneBorderingMechanism = false;
|
||||
|
||||
if (
|
||||
ForTerracingConnectionOffsets(a_Chunk, a_Position, [&a_Chunk, a_Position, &FoundOneBorderingMechanism, &PotentialOffset](const Vector3i Offset)
|
||||
{
|
||||
BLOCKTYPE Block;
|
||||
NIBBLETYPE Meta;
|
||||
|
||||
if (
|
||||
!a_World.GetBlockTypeMeta(Offset + a_Position, Block, Meta) ||
|
||||
!a_Chunk.UnboundedRelGetBlock(Offset + a_Position, Block, Meta) ||
|
||||
!IsDirectlyConnectingMechanism(Block, Meta, Offset)
|
||||
)
|
||||
{
|
||||
continue;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (FoundOneBorderingMechanism)
|
||||
{
|
||||
// Case 3
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Potential case 2
|
||||
FoundOneBorderingMechanism = true;
|
||||
PotentialOffset = { -Offset.x, 0, -Offset.z };
|
||||
}
|
||||
|
||||
if (FoundOneBorderingMechanism && (a_QueryPosition != (a_Position + PotentialOffset)))
|
||||
{
|
||||
// Case 2 fail
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Case 1
|
||||
// Case 2 success
|
||||
return false;
|
||||
})
|
||||
)
|
||||
{
|
||||
// Case 3
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (a_Meta != 0) ? --a_Meta : a_Meta;
|
||||
}
|
||||
if (FoundOneBorderingMechanism && (a_QueryPosition != (a_Position + PotentialOffset)))
|
||||
{
|
||||
// Case 2 fail
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Case 1
|
||||
// Case 2 success
|
||||
|
||||
virtual unsigned char GetPowerLevel(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override
|
||||
{
|
||||
UNUSED(a_World);
|
||||
UNUSED(a_Position);
|
||||
UNUSED(a_BlockType);
|
||||
return a_Meta;
|
||||
}
|
||||
|
||||
virtual cVector3iArray Update(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override
|
||||
virtual void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override
|
||||
{
|
||||
UNUSED(a_BlockType);
|
||||
// LOGD("Evaluating dusty the wire (%d %d %d) %i", a_Position.x, a_Position.y, a_Position.z, a_PoweringData.PowerLevel);
|
||||
|
||||
if (a_Meta != a_PoweringData.PowerLevel)
|
||||
{
|
||||
a_World.SetBlockMeta(a_Position, a_PoweringData.PowerLevel);
|
||||
return GetAdjustedRelatives(a_Position, StaticAppend(StaticAppend(GetRelativeLaterals(), GetTerracingConnectionOffsets(a_World, a_Position)), cVector3iArray{ OffsetYM() }));
|
||||
}
|
||||
a_Chunk.SetMeta(a_Position, a_PoweringData.PowerLevel);
|
||||
|
||||
return {};
|
||||
// Notify block below us to update:
|
||||
UpdateAdjustedRelatives(a_Chunk, CurrentlyTicking, a_Position + OffsetYM);
|
||||
|
||||
// Notify all terracing positions:
|
||||
ForTerracingConnectionOffsets(a_Chunk, a_Position, [&a_Chunk, &CurrentlyTicking, a_Position](const Vector3i Offset)
|
||||
{
|
||||
UpdateAdjustedRelatives(a_Chunk, CurrentlyTicking, a_Position + Offset);
|
||||
return false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
virtual cVector3iArray GetValidSourcePositions(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override
|
||||
virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
|
||||
{
|
||||
UNUSED(a_World);
|
||||
UNUSED(a_Chunk);
|
||||
UNUSED(a_BlockType);
|
||||
UNUSED(a_Meta);
|
||||
|
||||
return GetAdjustedRelatives(a_Position, StaticAppend(GetRelativeAdjacents(), GetTerracingConnectionOffsets(a_World, a_Position)));
|
||||
Callback(a_Position + OffsetYP);
|
||||
Callback(a_Position + OffsetYM);
|
||||
|
||||
ForTerracingConnectionOffsets(a_Chunk, a_Position, [&Callback, a_Position](const Vector3i Offset)
|
||||
{
|
||||
Callback(a_Position + Offset);
|
||||
return false;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
@ -7,16 +7,13 @@
|
||||
|
||||
|
||||
|
||||
class cSmallGateHandler:
|
||||
public cRedstoneHandler
|
||||
class cSmallGateHandler final : public cRedstoneHandler
|
||||
{
|
||||
using Super = cRedstoneHandler;
|
||||
|
||||
public:
|
||||
|
||||
virtual unsigned char GetPowerDeliveredToPosition(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
|
||||
virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
|
||||
{
|
||||
UNUSED(a_World);
|
||||
UNUSED(a_Chunk);
|
||||
UNUSED(a_Position);
|
||||
UNUSED(a_BlockType);
|
||||
UNUSED(a_Meta);
|
||||
@ -25,32 +22,24 @@ public:
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual unsigned char GetPowerLevel(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override
|
||||
{
|
||||
UNUSED(a_World);
|
||||
UNUSED(a_Position);
|
||||
UNUSED(a_BlockType);
|
||||
UNUSED(a_Meta);
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual cVector3iArray Update(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override
|
||||
virtual void Update(cChunk & a_Chunk, cChunk &, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override
|
||||
{
|
||||
// LOGD("Evaluating gateydory the fence gate/trapdoor (%d %d %d)", a_Position.x, a_Position.y, a_Position.z);
|
||||
auto Data = static_cast<cIncrementalRedstoneSimulator *>(a_World.GetRedstoneSimulator())->GetChunkData();
|
||||
if (a_PoweringData != Data->ExchangeUpdateOncePowerData(a_Position, a_PoweringData))
|
||||
{
|
||||
a_World.SetBlockMeta(a_Position, (a_PoweringData.PowerLevel > 0) ? (a_Meta | 0x4) : (a_Meta & ~0x04));
|
||||
}
|
||||
|
||||
return {};
|
||||
const bool ShouldBeOpen = a_PoweringData.PowerLevel != 0;
|
||||
const bool IsOpen = (a_Meta & 0x4) == 0x4;
|
||||
|
||||
if (ShouldBeOpen != IsOpen)
|
||||
{
|
||||
a_Chunk.SetMeta(a_Position, ShouldBeOpen ? (a_Meta | 0x4) : (a_Meta & ~0x04));
|
||||
}
|
||||
}
|
||||
|
||||
virtual cVector3iArray GetValidSourcePositions(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override
|
||||
virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
|
||||
{
|
||||
UNUSED(a_World);
|
||||
UNUSED(a_Chunk);
|
||||
UNUSED(a_BlockType);
|
||||
UNUSED(a_Meta);
|
||||
return GetAdjustedRelatives(a_Position, GetRelativeAdjacents());
|
||||
InvokeForAdjustedRelatives(Callback, a_Position, RelativeAdjacents);
|
||||
}
|
||||
};
|
||||
|
@ -14,41 +14,34 @@ class cSolidBlockHandler:
|
||||
|
||||
public:
|
||||
|
||||
virtual unsigned char GetPowerDeliveredToPosition(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
|
||||
virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
|
||||
{
|
||||
// TODO: wire isn't linked powered only if the source was a wire, not just because it is a wire
|
||||
const auto SolidBlock = DataForChunk(a_Chunk).GetCachedPowerData(a_Position);
|
||||
return (
|
||||
!cIncrementalRedstoneSimulator::IsRedstone(a_QueryBlockType) ||
|
||||
(
|
||||
(a_QueryBlockType == E_BLOCK_REDSTONE_WIRE) &&
|
||||
(static_cast<cIncrementalRedstoneSimulator *>(a_World.GetRedstoneSimulator())->GetChunkData()->GetCachedPowerData(a_Position).PoweringBlock == E_BLOCK_REDSTONE_WIRE)
|
||||
(SolidBlock.PoweringBlock == E_BLOCK_REDSTONE_WIRE)
|
||||
)
|
||||
) ? 0 : GetPowerLevel(a_World, a_Position, a_BlockType, a_Meta);
|
||||
) ? 0 : SolidBlock.PowerLevel;
|
||||
}
|
||||
|
||||
virtual unsigned char GetPowerLevel(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override
|
||||
{
|
||||
return static_cast<cIncrementalRedstoneSimulator *>(a_World.GetRedstoneSimulator())->GetChunkData()->GetCachedPowerData(a_Position).PowerLevel;
|
||||
}
|
||||
|
||||
virtual cVector3iArray Update(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override
|
||||
virtual void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override
|
||||
{
|
||||
UNUSED(a_BlockType);
|
||||
UNUSED(a_Meta);
|
||||
// LOGD("Evaluating blocky the generic block (%d %d %d)", a_Position.x, a_Position.y, a_Position.z);
|
||||
|
||||
auto PreviousPower = static_cast<cIncrementalRedstoneSimulator *>(a_World.GetRedstoneSimulator())->GetChunkData()->ExchangeUpdateOncePowerData(a_Position, a_PoweringData);
|
||||
auto PreviousPower = DataForChunk(a_Chunk).ExchangeUpdateOncePowerData(a_Position, a_PoweringData);
|
||||
if ((a_PoweringData != PreviousPower) || (a_PoweringData.PoweringBlock != PreviousPower.PoweringBlock))
|
||||
{
|
||||
return GetAdjustedRelatives(a_Position, GetRelativeAdjacents());
|
||||
UpdateAdjustedRelatives(a_Chunk, CurrentlyTicking, a_Position, RelativeAdjacents);
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
virtual cVector3iArray GetValidSourcePositions(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override
|
||||
virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
|
||||
{
|
||||
UNUSED(a_World);
|
||||
UNUSED(a_Chunk);
|
||||
UNUSED(a_BlockType);
|
||||
UNUSED(a_Meta);
|
||||
|
||||
@ -64,6 +57,6 @@ public:
|
||||
}
|
||||
}
|
||||
*/
|
||||
return GetAdjustedRelatives(a_Position, GetRelativeAdjacents());
|
||||
InvokeForAdjustedRelatives(Callback, a_Position, RelativeAdjacents);
|
||||
}
|
||||
};
|
||||
|
@ -7,16 +7,13 @@
|
||||
|
||||
|
||||
|
||||
class cTNTHandler:
|
||||
public cRedstoneHandler
|
||||
class cTNTHandler final : public cRedstoneHandler
|
||||
{
|
||||
using Super = cRedstoneHandler;
|
||||
|
||||
public:
|
||||
|
||||
virtual unsigned char GetPowerDeliveredToPosition(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
|
||||
virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
|
||||
{
|
||||
UNUSED(a_World);
|
||||
UNUSED(a_Chunk);
|
||||
UNUSED(a_Position);
|
||||
UNUSED(a_BlockType);
|
||||
UNUSED(a_Meta);
|
||||
@ -25,31 +22,21 @@ public:
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual unsigned char GetPowerLevel(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override
|
||||
{
|
||||
UNUSED(a_World);
|
||||
UNUSED(a_Position);
|
||||
UNUSED(a_BlockType);
|
||||
UNUSED(a_Meta);
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual cVector3iArray Update(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override
|
||||
virtual void Update(cChunk & a_Chunk, cChunk &, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override
|
||||
{
|
||||
// LOGD("Evaluating explodinator the trinitrotoluene (%d %d %d)", a_Position.x, a_Position.y, a_Position.z);
|
||||
if (a_PoweringData.PowerLevel != 0)
|
||||
{
|
||||
a_World.SetBlock(a_Position.x, a_Position.y, a_Position.z, E_BLOCK_AIR, 0);
|
||||
a_World.SpawnPrimedTNT(Vector3d(a_Position) + Vector3d(0.5, 0.5, 0.5)); // 80 ticks to boom
|
||||
a_Chunk.SetBlock(a_Position, E_BLOCK_AIR, 0);
|
||||
a_Chunk.GetWorld()->SpawnPrimedTNT(Vector3d(0.5, 0.5, 0.5) + cChunkDef::RelativeToAbsolute(a_Position, a_Chunk.GetPos())); // 80 ticks to boom
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
virtual cVector3iArray GetValidSourcePositions(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override
|
||||
virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
|
||||
{
|
||||
UNUSED(a_World);
|
||||
UNUSED(a_Chunk);
|
||||
UNUSED(a_BlockType);
|
||||
UNUSED(a_Meta);
|
||||
return GetAdjustedRelatives(a_Position, GetRelativeAdjacents());
|
||||
InvokeForAdjustedRelatives(Callback, a_Position, RelativeAdjacents);
|
||||
}
|
||||
};
|
||||
|
@ -15,54 +15,51 @@ class cTrappedChestHandler:
|
||||
|
||||
public:
|
||||
|
||||
virtual unsigned char GetPowerDeliveredToPosition(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
|
||||
virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
|
||||
{
|
||||
UNUSED(a_BlockType);
|
||||
UNUSED(a_Meta);
|
||||
UNUSED(a_QueryPosition);
|
||||
UNUSED(a_QueryBlockType);
|
||||
|
||||
return static_cast<cIncrementalRedstoneSimulator *>(a_World.GetRedstoneSimulator())->GetChunkData()->GetCachedPowerData(a_Position).PowerLevel;
|
||||
return DataForChunk(a_Chunk).GetCachedPowerData(a_Position).PowerLevel;
|
||||
}
|
||||
|
||||
virtual unsigned char GetPowerLevel(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override
|
||||
static unsigned char GetPowerLevel(cChunk & a_Chunk, Vector3i a_Position)
|
||||
{
|
||||
UNUSED(a_BlockType);
|
||||
UNUSED(a_Meta);
|
||||
|
||||
int NumberOfPlayers = 0;
|
||||
VERIFY(!a_World.DoWithChestAt(a_Position.x, a_Position.y, a_Position.z, [&](cChestEntity & a_Chest)
|
||||
VERIFY(
|
||||
!a_Chunk.DoWithChestAt(a_Position, [&](cChestEntity & a_Chest)
|
||||
{
|
||||
ASSERT(a_Chest.GetBlockType() == E_BLOCK_TRAPPED_CHEST);
|
||||
NumberOfPlayers = a_Chest.GetNumberOfPlayers();
|
||||
return true;
|
||||
}
|
||||
));
|
||||
})
|
||||
);
|
||||
|
||||
return static_cast<unsigned char>(std::min(NumberOfPlayers, 15));
|
||||
}
|
||||
|
||||
virtual cVector3iArray Update(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override
|
||||
virtual void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override
|
||||
{
|
||||
// LOGD("Evaluating tricky the trapped chest (%d %d %d)", a_Position.x, a_Position.y, a_Position.z);
|
||||
|
||||
auto Power = GetPowerLevel(a_World, a_Position, a_BlockType, a_Meta);
|
||||
auto PreviousPower = static_cast<cIncrementalRedstoneSimulator *>(a_World.GetRedstoneSimulator())->GetChunkData()->ExchangeUpdateOncePowerData(a_Position, PoweringData(a_BlockType, Power));
|
||||
const auto Power = GetPowerLevel(a_Chunk, a_Position);
|
||||
const auto PreviousPower = DataForChunk(a_Chunk).ExchangeUpdateOncePowerData(a_Position, PoweringData(a_BlockType, Power));
|
||||
|
||||
if (Power != PreviousPower.PowerLevel)
|
||||
{
|
||||
return GetAdjustedRelatives(a_Position, StaticAppend(GetRelativeLaterals(), cVector3iArray{ OffsetYM() }));
|
||||
UpdateAdjustedRelatives(a_Chunk, CurrentlyTicking, OffsetYM);
|
||||
UpdateAdjustedRelatives(a_Chunk, CurrentlyTicking, a_Position, RelativeLaterals);
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
virtual cVector3iArray GetValidSourcePositions(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override
|
||||
virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
|
||||
{
|
||||
UNUSED(a_World);
|
||||
UNUSED(a_Chunk);
|
||||
UNUSED(a_Position);
|
||||
UNUSED(a_BlockType);
|
||||
UNUSED(a_Meta);
|
||||
|
||||
return {};
|
||||
UNUSED(Callback);
|
||||
}
|
||||
};
|
||||
|
@ -8,43 +8,53 @@
|
||||
|
||||
|
||||
|
||||
class cTripwireHookHandler:
|
||||
public cRedstoneHandler
|
||||
class cTripwireHookHandler final : public cRedstoneHandler
|
||||
{
|
||||
using Super = cRedstoneHandler;
|
||||
|
||||
public:
|
||||
|
||||
virtual unsigned char GetPowerDeliveredToPosition(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
|
||||
virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
|
||||
{
|
||||
UNUSED(a_BlockType);
|
||||
UNUSED(a_QueryBlockType);
|
||||
UNUSED(a_QueryPosition);
|
||||
|
||||
return (GetPowerLevel(a_World, a_Position, a_BlockType, a_Meta) == 15) ? 15 : 0;
|
||||
return (GetPowerLevel(a_Chunk, a_Position, a_Meta) == 15) ? 15 : 0;
|
||||
}
|
||||
|
||||
virtual unsigned char GetPowerLevel(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override
|
||||
static unsigned char GetPowerLevel(cChunk & a_Chunk, Vector3i a_Position, NIBBLETYPE a_Meta)
|
||||
{
|
||||
UNUSED(a_BlockType);
|
||||
|
||||
bool FoundActivated = false;
|
||||
auto Position = a_Position;
|
||||
eBlockFace FaceToGoTowards = cBlockTripwireHookHandler::MetadataToDirection(a_Meta);
|
||||
const auto FaceToGoTowards = cBlockTripwireHookHandler::MetadataToDirection(a_Meta);
|
||||
|
||||
for (int i = 0; i < 40; ++i) // Tripwires can be connected up to 40 blocks
|
||||
{
|
||||
BLOCKTYPE Type;
|
||||
NIBBLETYPE Meta;
|
||||
|
||||
AddFaceDirection(Position.x, Position.y, Position.z, FaceToGoTowards);
|
||||
a_World.GetBlockTypeMeta(Position.x, Position.y, Position.z, Type, Meta);
|
||||
a_Position = AddFaceDirection(a_Position, FaceToGoTowards);
|
||||
if (!a_Chunk.UnboundedRelGetBlock(a_Position, Type, Meta))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (Type == E_BLOCK_TRIPWIRE)
|
||||
{
|
||||
if (!a_World.ForEachEntityInBox(cBoundingBox(Vector3d(0.5, 0, 0.5) + Position, 0.5, 0.5), [](cEntity &) { return true; }))
|
||||
if (FoundActivated)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (
|
||||
!a_Chunk.ForEachEntityInBox(
|
||||
cBoundingBox(Vector3d(0.5, 0, 0.5) + cChunkDef::RelativeToAbsolute(a_Position, a_Chunk.GetPos()), 0.5, 0.5),
|
||||
[](cEntity &) { return true; }
|
||||
)
|
||||
)
|
||||
{
|
||||
FoundActivated = true;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
else if (Type == E_BLOCK_TRIPWIRE_HOOK)
|
||||
{
|
||||
@ -53,27 +63,20 @@ public:
|
||||
// Other hook facing in opposite direction - circuit completed!
|
||||
return FoundActivated ? 15 : 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Tripwire hook not connected at all
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Tripwire hook not connected at all
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Tripwire hook not connected at all
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual cVector3iArray Update(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override
|
||||
virtual void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override
|
||||
{
|
||||
// LOGD("Evaluating hooky the tripwire hook (%d %d %d)", a_Position.x, a_Position.y, a_Position.z);
|
||||
|
||||
auto Power = GetPowerLevel(a_World, a_Position, a_BlockType, a_Meta);
|
||||
const auto Power = GetPowerLevel(a_Chunk, a_Position, a_Meta);
|
||||
NIBBLETYPE Meta;
|
||||
if (Power == 0)
|
||||
{
|
||||
@ -91,25 +94,22 @@ public:
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT(!"Unexpected tripwire hook power level!");
|
||||
return {};
|
||||
UNREACHABLE("Unexpected tripwire hook power level!");
|
||||
}
|
||||
|
||||
if (Meta != a_Meta)
|
||||
{
|
||||
a_World.SetBlockMeta(a_Position, Meta);
|
||||
return GetAdjustedRelatives(a_Position, GetRelativeAdjacents());
|
||||
a_Chunk.SetMeta(a_Position, Meta);
|
||||
UpdateAdjustedRelatives(a_Chunk, CurrentlyTicking, a_Position, RelativeAdjacents);
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
virtual cVector3iArray GetValidSourcePositions(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override
|
||||
virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
|
||||
{
|
||||
UNUSED(a_World);
|
||||
UNUSED(a_Chunk);
|
||||
UNUSED(a_BlockType);
|
||||
UNUSED(a_Meta);
|
||||
UNUSED(a_Position);
|
||||
return {};
|
||||
UNUSED(Callback);
|
||||
}
|
||||
};
|
||||
|
@ -7,7 +7,7 @@
|
||||
|
||||
|
||||
|
||||
class cRedstoneNoopSimulator:
|
||||
class cRedstoneNoopSimulator final :
|
||||
public cRedstoneSimulator
|
||||
{
|
||||
using Super = cRedstoneSimulator;
|
||||
|
Loading…
x
Reference in New Issue
Block a user