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
|
const Vector3i a_CursorPos
|
||||||
) override
|
) override
|
||||||
{
|
{
|
||||||
|
const auto Meta = a_ChunkInterface.GetBlockMeta(a_BlockPos);
|
||||||
|
|
||||||
// Toggle the 3rd bit (addition / subtraction):
|
// Toggle the 3rd bit (addition / subtraction):
|
||||||
NIBBLETYPE Meta = a_ChunkInterface.GetBlockMeta(a_BlockPos);
|
a_ChunkInterface.SetBlockMeta(a_BlockPos, Meta ^ 0x04);
|
||||||
Meta ^= 0x04;
|
|
||||||
a_ChunkInterface.SetBlockMeta(a_BlockPos, Meta);
|
// Update simulators:
|
||||||
|
a_WorldInterface.WakeUpSimulators(a_BlockPos);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,6 +59,7 @@ public:
|
|||||||
UNUSED(a_ChunkInterface);
|
UNUSED(a_ChunkInterface);
|
||||||
UNUSED(a_BlockFace);
|
UNUSED(a_BlockFace);
|
||||||
|
|
||||||
|
a_WorldInterface.WakeUpSimulators(a_BlockPos);
|
||||||
a_WorldInterface.SendBlockTo(a_BlockPos, a_Player);
|
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)
|
inline static Vector3i GetSideCoordinate(Vector3i a_Position, NIBBLETYPE a_Meta, bool a_bInverse)
|
||||||
{
|
{
|
||||||
if (!a_bInverse)
|
if (!a_bInverse)
|
||||||
|
@ -8,16 +8,13 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
class cCommandBlockHandler:
|
class cCommandBlockHandler final : public cRedstoneHandler
|
||||||
public cRedstoneHandler
|
|
||||||
{
|
{
|
||||||
using Super = cRedstoneHandler;
|
|
||||||
|
|
||||||
public:
|
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_Position);
|
||||||
UNUSED(a_BlockType);
|
UNUSED(a_BlockType);
|
||||||
UNUSED(a_Meta);
|
UNUSED(a_Meta);
|
||||||
@ -26,40 +23,29 @@ public:
|
|||||||
return 0;
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
// 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 ((Previous.PowerLevel != 0) || (a_PoweringData.PowerLevel == 0))
|
||||||
{
|
{
|
||||||
// If we're already powered or received an update of no power, don't activate
|
// 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_Chunk.DoWithCommandBlockAt(a_Position, [](cCommandBlockEntity & a_CommandBlock)
|
||||||
{
|
{
|
||||||
a_CommandBlock.Activate();
|
a_CommandBlock.Activate();
|
||||||
return false;
|
return false;
|
||||||
}
|
});
|
||||||
);
|
|
||||||
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_BlockType);
|
||||||
UNUSED(a_Meta);
|
UNUSED(a_Meta);
|
||||||
return GetAdjustedRelatives(a_Position, GetRelativeAdjacents());
|
InvokeForAdjustedRelatives(Callback, a_Position, RelativeAdjacents);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -8,16 +8,13 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
class cDoorHandler:
|
class cDoorHandler final : public cRedstoneHandler
|
||||||
public cRedstoneHandler
|
|
||||||
{
|
{
|
||||||
using Super = cRedstoneHandler;
|
|
||||||
|
|
||||||
public:
|
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_Position);
|
||||||
UNUSED(a_BlockType);
|
UNUSED(a_BlockType);
|
||||||
UNUSED(a_Meta);
|
UNUSED(a_Meta);
|
||||||
@ -26,46 +23,27 @@ public:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void Update(cChunk & a_Chunk, cChunk &, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
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
|
|
||||||
{
|
{
|
||||||
// LOGD("Evaluating dori the door (%d %d %d)", a_Position.x, a_Position.y, a_Position.z);
|
// 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_Chunk.GetWorld()->GetChunkMap());
|
||||||
{
|
const bool ShouldBeOpen = a_PoweringData.PowerLevel != 0;
|
||||||
cChunkInterface ChunkInterface(a_World.GetChunkMap());
|
const auto AbsolutePosition = cChunkDef::RelativeToAbsolute(a_Position, a_Chunk.GetPos());
|
||||||
cBlockDoorHandler::SetOpen(ChunkInterface, a_Position, (a_PoweringData.PowerLevel != 0));
|
const bool IsOpen = cBlockDoorHandler::IsOpen(ChunkInterface, AbsolutePosition);
|
||||||
a_World.BroadcastSoundParticleEffect(EffectID::SFX_RANDOM_WOODEN_DOOR_OPEN, a_Position, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
return {};
|
if (ShouldBeOpen != IsOpen)
|
||||||
|
{
|
||||||
|
cBlockDoorHandler::SetOpen(ChunkInterface, AbsolutePosition, ShouldBeOpen);
|
||||||
|
a_Chunk.GetWorld()->BroadcastSoundParticleEffect(EffectID::SFX_RANDOM_WOODEN_DOOR_OPEN, AbsolutePosition, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
virtual cVector3iArray GetValidSourcePositions(cWorld & a_World, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override
|
|
||||||
{
|
{
|
||||||
UNUSED(a_World);
|
UNUSED(a_Chunk);
|
||||||
UNUSED(a_BlockType);
|
UNUSED(a_BlockType);
|
||||||
UNUSED(a_Meta);
|
UNUSED(a_Meta);
|
||||||
return GetAdjustedRelatives(a_Position, GetRelativeAdjacents());
|
InvokeForAdjustedRelatives(Callback, a_Position, RelativeAdjacents);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -8,17 +8,15 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
class cDropSpenserHandler:
|
class cDropSpenserHandler final : public cRedstoneHandler
|
||||||
public cRedstoneHandler
|
|
||||||
{
|
{
|
||||||
using Super = cRedstoneHandler;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
inline static bool IsActivated(NIBBLETYPE a_Meta)
|
inline static bool IsActivated(NIBBLETYPE a_Meta)
|
||||||
{
|
{
|
||||||
return (a_Meta & E_META_DROPSPENSER_ACTIVATED) != 0;
|
return (a_Meta & E_META_DROPSPENSER_ACTIVATED) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static NIBBLETYPE SetActivationState(NIBBLETYPE a_Meta, bool IsOn)
|
inline static NIBBLETYPE SetActivationState(NIBBLETYPE a_Meta, bool IsOn)
|
||||||
{
|
{
|
||||||
if (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_Position);
|
||||||
UNUSED(a_BlockType);
|
UNUSED(a_BlockType);
|
||||||
UNUSED(a_Meta);
|
UNUSED(a_Meta);
|
||||||
@ -42,45 +40,34 @@ public:
|
|||||||
return 0;
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual cVector3iArray Update(cWorld & a_World, 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);
|
// 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)
|
if (IsPoweredNow && !WasPoweredPreviously)
|
||||||
{
|
{
|
||||||
a_World.DoWithDropSpenserAt(a_Position.x, a_Position.y, a_Position.z, [](cDropSpenserEntity & a_DropSpenser)
|
a_Chunk.DoWithDropSpenserAt(a_Position, [](cDropSpenserEntity & a_DropSpenser)
|
||||||
{
|
{
|
||||||
a_DropSpenser.Activate();
|
a_DropSpenser.Activate();
|
||||||
return false;
|
return false;
|
||||||
}
|
});
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the internal dropspenser state if necessary
|
// Update the internal dropspenser state if necessary
|
||||||
if (IsPoweredNow != WasPoweredPreviously)
|
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_BlockType);
|
||||||
UNUSED(a_Meta);
|
UNUSED(a_Meta);
|
||||||
|
InvokeForAdjustedRelatives(Callback, a_Position, RelativeAdjacents);
|
||||||
return GetAdjustedRelatives(a_Position, GetRelativeAdjacents());
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -8,16 +8,13 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
class cHopperHandler:
|
class cHopperHandler final : public cRedstoneHandler
|
||||||
public cRedstoneHandler
|
|
||||||
{
|
{
|
||||||
using Super = cRedstoneHandler;
|
|
||||||
|
|
||||||
public:
|
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_Position);
|
||||||
UNUSED(a_BlockType);
|
UNUSED(a_BlockType);
|
||||||
UNUSED(a_Meta);
|
UNUSED(a_Meta);
|
||||||
@ -26,39 +23,28 @@ public:
|
|||||||
return 0;
|
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);
|
// LOGD("Evaluating holey the hopper (%d %d %d)", a_Position.x, a_Position.y, a_Position.z);
|
||||||
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
|
auto Previous = DataForChunk(a_Chunk).ExchangeUpdateOncePowerData(a_Position, a_PoweringData);
|
||||||
{
|
if (Previous.PowerLevel == a_PoweringData.PowerLevel)
|
||||||
// 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)
|
|
||||||
{
|
{
|
||||||
return {};
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
a_World.DoWithHopperAt(a_Position.x, a_Position.y, a_Position.z, [a_PoweringData](cHopperEntity & a_Hopper)
|
a_Chunk.DoWithHopperAt(a_Position, [a_PoweringData](cHopperEntity & a_Hopper)
|
||||||
{
|
{
|
||||||
a_Hopper.SetLocked(a_PoweringData.PowerLevel != 0);
|
a_Hopper.SetLocked(a_PoweringData.PowerLevel != 0);
|
||||||
return false;
|
return false;
|
||||||
}
|
});
|
||||||
);
|
|
||||||
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_BlockType);
|
||||||
UNUSED(a_Meta);
|
UNUSED(a_Meta);
|
||||||
return GetAdjustedRelatives(a_Position, GetRelativeAdjacents());
|
InvokeForAdjustedRelatives(Callback, a_Position, RelativeAdjacents);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -7,7 +7,6 @@
|
|||||||
|
|
||||||
#include "CommandBlockHandler.h"
|
#include "CommandBlockHandler.h"
|
||||||
#include "DoorHandler.h"
|
#include "DoorHandler.h"
|
||||||
#include "RedstoneHandler.h"
|
|
||||||
#include "RedstoneTorchHandler.h"
|
#include "RedstoneTorchHandler.h"
|
||||||
#include "RedstoneWireHandler.h"
|
#include "RedstoneWireHandler.h"
|
||||||
#include "RedstoneRepeaterHandler.h"
|
#include "RedstoneRepeaterHandler.h"
|
||||||
@ -31,9 +30,10 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const cRedstoneHandler * cIncrementalRedstoneSimulator::GetComponentHandler(BLOCKTYPE a_BlockType)
|
const cRedstoneHandler * cIncrementalRedstoneSimulator::GetComponentHandler(BLOCKTYPE a_BlockType)
|
||||||
{
|
{
|
||||||
struct sComponents:
|
struct sComponents :
|
||||||
public std::array<std::unique_ptr<cRedstoneHandler>, 256>
|
public std::array<std::unique_ptr<cRedstoneHandler>, 256>
|
||||||
{
|
{
|
||||||
sComponents()
|
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)
|
if ((--DelayInfo.second.first) == 0)
|
||||||
{
|
{
|
||||||
m_Data.GetActiveBlocks().emplace_back(DelayInfo.first);
|
ChunkData.WakeUp(DelayInfo.first);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build our work queue
|
// Build our work queue
|
||||||
cVector3iArray WorkQueue;
|
auto & WorkQueue = ChunkData.GetActiveBlocks();
|
||||||
std::swap(WorkQueue, m_Data.GetActiveBlocks());
|
|
||||||
|
|
||||||
// Process the work queue
|
// Process the work queue
|
||||||
while (!WorkQueue.empty())
|
while (!WorkQueue.empty())
|
||||||
{
|
{
|
||||||
// Grab the first element and remove it from the list
|
// Grab the first element and remove it from the list
|
||||||
Vector3i CurrentLocation = WorkQueue.back();
|
Vector3i CurrentLocation = WorkQueue.top();
|
||||||
WorkQueue.pop_back();
|
WorkQueue.pop();
|
||||||
|
|
||||||
BLOCKTYPE CurrentBlock;
|
const auto NeighbourChunk = a_Chunk->GetRelNeighborChunkAdjustCoords(CurrentLocation);
|
||||||
NIBBLETYPE CurrentMeta;
|
if ((NeighbourChunk == nullptr) || !NeighbourChunk->IsValid())
|
||||||
if (!m_World.GetBlockTypeMeta(CurrentLocation.x, CurrentLocation.y, CurrentLocation.z, CurrentBlock, CurrentMeta))
|
|
||||||
{
|
{
|
||||||
continue;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto CurrentHandler = GetComponentHandler(CurrentBlock);
|
ProcessWorkItem(*NeighbourChunk, *a_Chunk, CurrentLocation);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
void cIncrementalRedstoneSimulator::AddBlock(Vector3i a_Block, cChunk * a_Chunk)
|
||||||
{
|
{
|
||||||
// Can't inspect block, so queue update anyway
|
// Can't inspect block, ignore:
|
||||||
if (a_Chunk == nullptr)
|
if ((a_Chunk == nullptr) || (!a_Chunk->IsValid()))
|
||||||
{
|
{
|
||||||
m_Data.WakeUp(a_Block);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto RelPos = cChunkDef::AbsoluteToRelative(a_Block, a_Chunk->GetPos());
|
auto & ChunkData = *static_cast<cIncrementalRedstoneSimulatorChunkData *>(a_Chunk->GetRedstoneSimulatorData());
|
||||||
const auto CurBlock = a_Chunk->GetBlock(RelPos);
|
const auto Relative = cChunkDef::AbsoluteToRelative(a_Block, a_Chunk->GetPos());
|
||||||
|
const auto CurrentBlock = a_Chunk->GetBlock(Relative);
|
||||||
|
|
||||||
// Always update redstone devices
|
// 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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Never update blocks without a handler
|
// Never update blocks without a handler
|
||||||
if (GetComponentHandler(CurBlock) == nullptr)
|
if (GetComponentHandler(CurrentBlock) == nullptr)
|
||||||
{
|
{
|
||||||
GetChunkData()->ErasePowerData(a_Block);
|
ChunkData.ErasePowerData(Relative);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -235,14 +261,14 @@ void cIncrementalRedstoneSimulator::AddBlock(Vector3i a_Block, cChunk * a_Chunk)
|
|||||||
{
|
{
|
||||||
for (int y = -1; y < 2; ++y)
|
for (int y = -1; y < 2; ++y)
|
||||||
{
|
{
|
||||||
if (!cChunkDef::IsValidHeight(RelPos.y + y))
|
if (!cChunkDef::IsValidHeight(Relative.y + y))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int z = -1; z < 2; ++z)
|
for (int z = -1; z < 2; ++z)
|
||||||
{
|
{
|
||||||
auto CheckPos = RelPos + Vector3i{x, y, z};
|
auto CheckPos = Relative + Vector3i{x, y, z};
|
||||||
BLOCKTYPE Block;
|
BLOCKTYPE Block;
|
||||||
NIBBLETYPE Meta;
|
NIBBLETYPE Meta;
|
||||||
|
|
||||||
@ -252,7 +278,7 @@ void cIncrementalRedstoneSimulator::AddBlock(Vector3i a_Block, cChunk * a_Chunk)
|
|||||||
IsRedstone(Block)
|
IsRedstone(Block)
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
m_Data.WakeUp(a_Block);
|
ChunkData.WakeUp(Relative);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,26 +2,29 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../RedstoneSimulator.h"
|
#include "../RedstoneSimulator.h"
|
||||||
|
#include "RedstoneHandler.h"
|
||||||
#include "RedstoneSimulatorChunkData.h"
|
#include "RedstoneSimulatorChunkData.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class cIncrementalRedstoneSimulator:
|
class cIncrementalRedstoneSimulator final :
|
||||||
public cRedstoneSimulator
|
public cRedstoneSimulator
|
||||||
{
|
{
|
||||||
using Super = cRedstoneSimulator;
|
using Super = cRedstoneSimulator;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
cIncrementalRedstoneSimulator(cWorld & a_World):
|
cIncrementalRedstoneSimulator(cWorld & a_World) :
|
||||||
Super(a_World)
|
Super(a_World)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void Simulate(float a_dt) override;
|
virtual void Simulate(float Dt) override {};
|
||||||
virtual void SimulateChunk(std::chrono::milliseconds a_Dt, int a_ChunkX, int a_ChunkZ, cChunk * a_Chunk) override {}
|
virtual void SimulateChunk(std::chrono::milliseconds Dt, int ChunkX, int ChunkZ, cChunk * Chunk) override;
|
||||||
|
|
||||||
|
void ProcessWorkItem(cChunk & Chunk, cChunk & TickingSource, const Vector3i Position);
|
||||||
|
|
||||||
virtual cIncrementalRedstoneSimulatorChunkData * CreateChunkData() override
|
virtual cIncrementalRedstoneSimulatorChunkData * CreateChunkData() override
|
||||||
{
|
{
|
||||||
@ -36,8 +39,7 @@ public:
|
|||||||
virtual void AddBlock(Vector3i a_Block, cChunk * a_Chunk) override;
|
virtual void AddBlock(Vector3i a_Block, cChunk * a_Chunk) override;
|
||||||
|
|
||||||
/** Returns if a block is a mechanism (something that accepts power and does something)
|
/** Returns if a block is a mechanism (something that accepts power and does something)
|
||||||
Used by torches to determine if they will power a block
|
Used by torches to determine if they will power a block */
|
||||||
*/
|
|
||||||
inline static bool IsMechanism(BLOCKTYPE Block)
|
inline static bool IsMechanism(BLOCKTYPE Block)
|
||||||
{
|
{
|
||||||
switch (Block)
|
switch (Block)
|
||||||
@ -158,14 +160,9 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cIncrementalRedstoneSimulatorChunkData * GetChunkData() { return &m_Data; }
|
|
||||||
|
|
||||||
static const cRedstoneHandler * GetComponentHandler(BLOCKTYPE a_BlockType);
|
static const cRedstoneHandler * GetComponentHandler(BLOCKTYPE a_BlockType);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
static std::unique_ptr<cRedstoneHandler> CreateComponent(BLOCKTYPE a_BlockType);
|
static std::unique_ptr<cRedstoneHandler> CreateComponent(BLOCKTYPE a_BlockType);
|
||||||
|
|
||||||
// oh yea its crazy time
|
|
||||||
cIncrementalRedstoneSimulatorChunkData m_Data;
|
|
||||||
} ;
|
} ;
|
||||||
|
@ -8,17 +8,13 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
class cNoteBlockHandler:
|
class cNoteBlockHandler: public cRedstoneHandler
|
||||||
public cRedstoneHandler
|
|
||||||
{
|
{
|
||||||
using Super = cRedstoneHandler;
|
|
||||||
|
|
||||||
public:
|
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_World);
|
|
||||||
UNUSED(a_Position);
|
UNUSED(a_Position);
|
||||||
UNUSED(a_BlockType);
|
UNUSED(a_BlockType);
|
||||||
UNUSED(a_Meta);
|
UNUSED(a_Meta);
|
||||||
@ -27,41 +23,29 @@ public:
|
|||||||
return 0;
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual cVector3iArray Update(cWorld & a_World, 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);
|
// 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 ((Previous.PowerLevel != 0) || (a_PoweringData.PowerLevel == 0))
|
||||||
{
|
{
|
||||||
// If we're already powered or received an update of no power, don't make a sound
|
// 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_Chunk.DoWithNoteBlockAt(a_Position, [](cNoteEntity & a_NoteBlock)
|
||||||
{
|
{
|
||||||
a_NoteBlock.MakeSound();
|
a_NoteBlock.MakeSound();
|
||||||
return false;
|
return false;
|
||||||
}
|
});
|
||||||
);
|
|
||||||
|
|
||||||
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_BlockType);
|
||||||
UNUSED(a_Meta);
|
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:
|
public:
|
||||||
|
|
||||||
@ -17,24 +17,24 @@ public:
|
|||||||
return (a_Meta & 0x8) == 0x8;
|
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;
|
BLOCKTYPE BlockType;
|
||||||
NIBBLETYPE BlockMeta;
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cache the last seen block type and meta in the power data for this position
|
// Cache the last seen block type and meta in the power data for this position
|
||||||
auto Observed = PoweringData(BlockType, BlockMeta);
|
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
|
// Determine if to signal an update based on the block previously observed changed
|
||||||
return (Previous.PoweringBlock != Observed.PoweringBlock) || (Previous.PowerLevel != Observed.PowerLevel);
|
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))))
|
if (IsOn(a_Meta) && (a_QueryPosition == (a_Position + cBlockObserverHandler::GetSignalOutputOffset(a_Meta))))
|
||||||
{
|
{
|
||||||
@ -44,30 +44,25 @@ public:
|
|||||||
return 0;
|
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 & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) 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
|
|
||||||
{
|
{
|
||||||
// LOGD("Evaluating Lenny the observer (%i %i %i)", a_Position.x, a_Position.y, a_Position.z);
|
// 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 & Data = DataForChunk(a_Chunk);
|
||||||
auto DelayInfo = Data->GetMechanismDelayInfo(a_Position);
|
auto DelayInfo = Data.GetMechanismDelayInfo(a_Position);
|
||||||
|
|
||||||
if (DelayInfo == nullptr)
|
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
|
// From rest, we've determined there was a block update
|
||||||
// Schedule power-on 1 tick in the future
|
// 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;
|
int DelayTicks;
|
||||||
@ -76,31 +71,30 @@ public:
|
|||||||
|
|
||||||
if (DelayTicks != 0)
|
if (DelayTicks != 0)
|
||||||
{
|
{
|
||||||
return {};
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ShouldPowerOn)
|
if (ShouldPowerOn)
|
||||||
{
|
{
|
||||||
// Remain on for 1 tick before resetting
|
// Remain on for 1 tick before resetting
|
||||||
*DelayInfo = std::make_pair(1, false);
|
*DelayInfo = std::make_pair(1, false);
|
||||||
a_World.SetBlockMeta(a_Position, a_Meta | 0x8);
|
a_Chunk.SetMeta(a_Position, a_Meta | 0x8);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// We've reset. Erase delay data in preparation for detecting further updates
|
// We've reset. Erase delay data in preparation for detecting further updates
|
||||||
Data->m_MechanismDelays.erase(a_Position);
|
Data.m_MechanismDelays.erase(a_Position);
|
||||||
a_World.SetBlockMeta(a_Position, a_Meta & ~0x8);
|
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_Position);
|
||||||
UNUSED(a_BlockType);
|
UNUSED(a_BlockType);
|
||||||
UNUSED(a_BlockType);
|
UNUSED(a_BlockType);
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -8,16 +8,13 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
class cPistonHandler:
|
class cPistonHandler final: public cRedstoneHandler
|
||||||
public cRedstoneHandler
|
|
||||||
{
|
{
|
||||||
using Super = cRedstoneHandler;
|
|
||||||
|
|
||||||
public:
|
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_Position);
|
||||||
UNUSED(a_BlockType);
|
UNUSED(a_BlockType);
|
||||||
UNUSED(a_Meta);
|
UNUSED(a_Meta);
|
||||||
@ -26,52 +23,45 @@ public:
|
|||||||
return 0;
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual cVector3iArray Update(cWorld & a_World, 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);
|
// 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))
|
if (ShouldBeExtended == cBlockPistonHandler::IsExtended(a_Meta))
|
||||||
{
|
{
|
||||||
return {};
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
a_Position = cChunkDef::RelativeToAbsolute(a_Position, a_Chunk.GetPos());
|
||||||
|
|
||||||
if (ShouldBeExtended)
|
if (ShouldBeExtended)
|
||||||
{
|
{
|
||||||
cBlockPistonHandler::ExtendPiston(a_Position, a_World);
|
cBlockPistonHandler::ExtendPiston(a_Position, *a_Chunk.GetWorld());
|
||||||
}
|
}
|
||||||
else
|
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)
|
// 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
|
// However, this delay is already present: as a side effect of the implementation of piston animation in Blocks\BlockPiston.cpp
|
||||||
|
|
||||||
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_BlockType);
|
||||||
|
|
||||||
auto PositionsOffset = GetRelativeAdjacents();
|
const auto Face = cBlockPistonHandler::MetaDataToDirection(a_Meta);
|
||||||
auto Face = cBlockPistonHandler::MetaDataToDirection(a_Meta);
|
const auto FrontOffset = AddFaceDirection(Vector3i(), Face);
|
||||||
int OffsetX = 0, OffsetY = 0, OffsetZ = 0;
|
|
||||||
|
|
||||||
AddFaceDirection(OffsetX, OffsetY, OffsetZ, Face);
|
for (const auto Offset : RelativeAdjacents)
|
||||||
PositionsOffset.erase(std::remove(PositionsOffset.begin(), PositionsOffset.end(), Vector3i(OffsetX, OffsetY, OffsetZ)), PositionsOffset.end());
|
{
|
||||||
|
if (Offset != FrontOffset)
|
||||||
return GetAdjustedRelatives(a_Position, PositionsOffset);
|
{
|
||||||
|
Callback(a_Position + Offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -7,11 +7,8 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
class cPoweredRailHandler:
|
class cPoweredRailHandler final : public cRedstoneHandler
|
||||||
public cRedstoneHandler
|
|
||||||
{
|
{
|
||||||
using Super = cRedstoneHandler;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
static Vector3i GetPoweredRailAdjacentXZCoordinateOffset(NIBBLETYPE a_Meta) // Not in cBlockRailHandler since specific to powered rails
|
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);
|
UNUSED(a_QueryBlockType);
|
||||||
|
|
||||||
auto Offset = GetPoweredRailAdjacentXZCoordinateOffset(a_Meta);
|
auto Offset = GetPoweredRailAdjacentXZCoordinateOffset(a_Meta);
|
||||||
if (((Offset + a_Position) == a_QueryPosition) || ((-Offset + a_Position) == a_QueryPosition))
|
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 (Power <= 7) ? 0 : --Power;
|
||||||
}
|
}
|
||||||
return 0;
|
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 & CurrentlyTickingChunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) 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
|
|
||||||
{
|
{
|
||||||
// LOGD("Evaluating tracky the rail (%d %d %d)", a_Position.x, a_Position.y, a_Position.z);
|
// 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);
|
SetAllDirsAsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, a_MyType);
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
return {};
|
return;
|
||||||
}
|
}
|
||||||
case E_BLOCK_ACTIVATOR_RAIL:
|
case E_BLOCK_ACTIVATOR_RAIL:
|
||||||
case E_BLOCK_POWERED_RAIL:
|
case E_BLOCK_POWERED_RAIL:
|
||||||
{
|
{
|
||||||
auto Offset = GetPoweredRailAdjacentXZCoordinateOffset(a_Meta);
|
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));
|
a_Chunk.SetMeta(a_Position, (a_PoweringData.PowerLevel == 0) ? (a_Meta & 0x07) : (a_Meta | 0x08));
|
||||||
return cVector3iArray{ { Offset + a_Position }, { -Offset + a_Position } };
|
|
||||||
|
UpdateAdjustedRelatives(a_Chunk, CurrentlyTickingChunk, a_Position + Offset);
|
||||||
|
UpdateAdjustedRelatives(a_Chunk, CurrentlyTickingChunk, a_Position + -Offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
return {};
|
return;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
ASSERT(!"Unhandled type of rail in passed to rail handler!");
|
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_Chunk);
|
||||||
UNUSED(a_BlockType);
|
|
||||||
UNUSED(a_Meta);
|
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:
|
class cPressurePlateHandler final : public cRedstoneHandler
|
||||||
public cRedstoneHandler
|
|
||||||
{
|
{
|
||||||
using Super = cRedstoneHandler;
|
|
||||||
|
|
||||||
public:
|
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_BlockType);
|
||||||
UNUSED(a_Meta);
|
UNUSED(a_Meta);
|
||||||
UNUSED(a_QueryPosition);
|
UNUSED(a_QueryPosition);
|
||||||
UNUSED(a_QueryBlockType);
|
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);
|
unsigned NumberOfEntities = 0;
|
||||||
|
|
||||||
int NumberOfEntities = 0;
|
|
||||||
bool FoundPlayer = false;
|
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())
|
Chunk.ForEachEntityInBox(cBoundingBox(Vector3d(0.5, 0, 0.5) + Position, 0.5, 0.5), [&](cEntity & Entity)
|
||||||
{
|
{
|
||||||
NumberOfEntities += static_cast<cPickup &>(a_Entity).GetItem().m_ItemCount;
|
if (Entity.IsPlayer())
|
||||||
return false;
|
{
|
||||||
}
|
FoundPlayer = true;
|
||||||
NumberOfEntities++;
|
}
|
||||||
|
|
||||||
|
if (Entity.IsPickup())
|
||||||
|
{
|
||||||
|
NumberOfEntities += static_cast<cPickup &>(Entity).GetItem().m_ItemCount;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
);
|
NumberOfEntities++;
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
switch (a_BlockType)
|
switch (BlockType)
|
||||||
{
|
{
|
||||||
case E_BLOCK_STONE_PRESSURE_PLATE:
|
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);
|
// 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);
|
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 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 PlateUpdates = GetAdjustedRelatives(a_Position, StaticAppend(GetRelativeLaterals(), cVector3iArray{ OffsetYM() }));
|
const auto DelayInfo = ChunkData.GetMechanismDelayInfo(a_Position);
|
||||||
auto DelayInfo = ChunkData->GetMechanismDelayInfo(a_Position);
|
|
||||||
|
|
||||||
// Resting state?
|
// Resting state?
|
||||||
if (DelayInfo == nullptr)
|
if (DelayInfo == nullptr)
|
||||||
@ -94,22 +93,21 @@ public:
|
|||||||
if (Power == 0)
|
if (Power == 0)
|
||||||
{
|
{
|
||||||
// Nothing happened, back to rest
|
// Nothing happened, back to rest
|
||||||
return {};
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// From rest, a player stepped on us
|
// From rest, a player stepped on us
|
||||||
// Schedule a minimum 0.5 second delay before even thinking about releasing
|
// 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_Chunk.GetWorld()->BroadcastSoundEffect(GetClickOnSound(a_BlockType), Absolute, 0.5f, 0.6f);
|
||||||
a_World.BroadcastSoundEffect(soundToPlay, a_Position, 0.5f, 0.6f);
|
|
||||||
|
|
||||||
// Update power
|
// Update power
|
||||||
ChunkData->SetCachedPowerData(a_Position, PoweringData(a_BlockType, Power));
|
ChunkData.SetCachedPowerData(a_Position, PoweringData(a_BlockType, Power));
|
||||||
|
|
||||||
// Immediately depress plate
|
// Immediately depress plate
|
||||||
a_World.SetBlockMeta(a_Position, E_META_PRESSURE_PLATE_DEPRESSED);
|
a_Chunk.SetMeta(a_Position, E_META_PRESSURE_PLATE_DEPRESSED);
|
||||||
return PlateUpdates;
|
return UpdatePlate(a_Chunk, CurrentlyTicking, a_Position);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Not a resting state
|
// Not a resting state
|
||||||
@ -124,7 +122,7 @@ public:
|
|||||||
// Nothing changes, if there is nothing on it anymore, because the state is locked.
|
// Nothing changes, if there is nothing on it anymore, because the state is locked.
|
||||||
if (Power == 0)
|
if (Power == 0)
|
||||||
{
|
{
|
||||||
return {};
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Yes. Are we waiting to release, and found that the player stepped on it again?
|
// Yes. Are we waiting to release, and found that the player stepped on it again?
|
||||||
@ -138,11 +136,11 @@ public:
|
|||||||
if (Power != PreviousPower.PowerLevel)
|
if (Power != PreviousPower.PowerLevel)
|
||||||
{
|
{
|
||||||
// Yes. Update power
|
// Yes. Update power
|
||||||
ChunkData->SetCachedPowerData(a_Position, PoweringData(a_BlockType, Power));
|
ChunkData.SetCachedPowerData(a_Position, PoweringData(a_BlockType, Power));
|
||||||
return PlateUpdates;
|
return UpdatePlate(a_Chunk, CurrentlyTicking, a_Position);
|
||||||
}
|
}
|
||||||
|
|
||||||
return {};
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Not waiting for anything. Has the initial delay elapsed?
|
// 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
|
// Yes. Go into subsequent release delay, for a further 0.5 seconds
|
||||||
*DelayInfo = std::make_pair(5, false);
|
*DelayInfo = std::make_pair(5, false);
|
||||||
return {};
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Did the power level change and is still above zero?
|
// Did the power level change and is still above zero?
|
||||||
if (Power != PreviousPower.PowerLevel)
|
if (Power != PreviousPower.PowerLevel)
|
||||||
{
|
{
|
||||||
// Yes. Update power
|
// Yes. Update power
|
||||||
ChunkData->SetCachedPowerData(a_Position, PoweringData(a_BlockType, Power));
|
ChunkData.SetCachedPowerData(a_Position, PoweringData(a_BlockType, Power));
|
||||||
return PlateUpdates;
|
return UpdatePlate(a_Chunk, CurrentlyTicking, a_Position);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Yes, but player's still on the plate, do nothing
|
// 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
|
// 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_Chunk.GetWorld()->BroadcastSoundEffect(GetClickOffSound(a_BlockType), Absolute, 0.5f, 0.5f);
|
||||||
a_World.BroadcastSoundEffect(soundToPlay, a_Position, 0.5f, 0.5f);
|
ChunkData.SetCachedPowerData(a_Position, PoweringData(a_BlockType, Power));
|
||||||
ChunkData->SetCachedPowerData(a_Position, PoweringData(a_BlockType, Power));
|
|
||||||
|
|
||||||
a_World.SetBlockMeta(a_Position, E_META_PRESSURE_PLATE_RAISED);
|
a_Chunk.SetMeta(a_Position, E_META_PRESSURE_PLATE_RAISED);
|
||||||
return PlateUpdates;
|
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_Position);
|
||||||
UNUSED(a_BlockType);
|
UNUSED(a_BlockType);
|
||||||
UNUSED(a_Meta);
|
UNUSED(a_Meta);
|
||||||
return {};
|
UNUSED(Callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static AString GetClickOnSound(BLOCKTYPE a_BlockType)
|
|
||||||
|
static const char * GetClickOnSound(BLOCKTYPE a_BlockType)
|
||||||
{
|
{
|
||||||
// manage on-sound
|
// manage on-sound
|
||||||
switch (a_BlockType)
|
switch (a_BlockType)
|
||||||
{
|
{
|
||||||
case E_BLOCK_STONE_PRESSURE_PLATE:
|
case E_BLOCK_STONE_PRESSURE_PLATE: return "block.stone_pressureplate.click_on";
|
||||||
return "block.stone_pressureplate.click_on";
|
case E_BLOCK_WOODEN_PRESSURE_PLATE: return "block.wood_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_HEAVY_WEIGHTED_PRESSURE_PLATE:
|
||||||
case E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE:
|
case E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE: return "block.metal_pressureplate.click_on";
|
||||||
return "block.metal_pressureplate.click_on";
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
ASSERT(!"No on sound for this one!");
|
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
|
// manage off-sound
|
||||||
switch (a_BlockType)
|
switch (a_BlockType)
|
||||||
{
|
{
|
||||||
case E_BLOCK_STONE_PRESSURE_PLATE:
|
case E_BLOCK_STONE_PRESSURE_PLATE: return "block.stone_pressureplate.click_off";
|
||||||
return "block.stone_pressureplate.click_off";
|
case E_BLOCK_WOODEN_PRESSURE_PLATE: return "block.wood_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_HEAVY_WEIGHTED_PRESSURE_PLATE:
|
||||||
case E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE:
|
case E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE: return "block.metal_pressureplate.click_off";
|
||||||
return "block.metal_pressureplate.click_off";
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
ASSERT(!"No off sound for this one!");
|
ASSERT(!"No off sound for this one!");
|
||||||
|
@ -7,16 +7,13 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
class cRedstoneBlockHandler:
|
class cRedstoneBlockHandler final : public cRedstoneHandler
|
||||||
public cRedstoneHandler
|
|
||||||
{
|
{
|
||||||
using Super = cRedstoneHandler;
|
|
||||||
|
|
||||||
public:
|
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_Position);
|
||||||
UNUSED(a_BlockType);
|
UNUSED(a_BlockType);
|
||||||
UNUSED(a_Meta);
|
UNUSED(a_Meta);
|
||||||
@ -24,27 +21,17 @@ public:
|
|||||||
return cIncrementalRedstoneSimulator::IsMechanism(a_QueryBlockType) ? 15 : 0;
|
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
|
virtual void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, 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 15;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual cVector3iArray Update(cWorld & a_World, 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);
|
// 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_Position);
|
||||||
UNUSED(a_BlockType);
|
UNUSED(a_BlockType);
|
||||||
UNUSED(a_Meta);
|
UNUSED(a_Meta);
|
||||||
return {};
|
UNUSED(Callback);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -8,14 +8,11 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
class cRedstoneComparatorHandler:
|
class cRedstoneComparatorHandler : public cRedstoneHandler
|
||||||
public cRedstoneHandler
|
|
||||||
{
|
{
|
||||||
using Super = cRedstoneHandler;
|
|
||||||
|
|
||||||
public:
|
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))
|
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_QueryPosition);
|
||||||
UNUSED(a_QueryBlockType);
|
UNUSED(a_QueryBlockType);
|
||||||
auto ChunkData = static_cast<cIncrementalRedstoneSimulator *>(a_World.GetRedstoneSimulator())->GetChunkData();
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
(cBlockComparatorHandler::GetFrontCoordinate(a_Position, a_Meta & 0x3) == a_QueryPosition) ?
|
(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;
|
UInt8 SignalStrength = 0;
|
||||||
auto RearCoordinate = cBlockComparatorHandler::GetRearCoordinate(a_Position, a_Meta & 0x3);
|
auto RearCoordinate = cBlockComparatorHandler::GetRearCoordinate(Position, 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 & Contents = BlockEntityWithItems->GetContents();
|
auto RearChunk = a_Chunk.GetRelNeighborChunkAdjustCoords(RearCoordinate);
|
||||||
float Fullness = 0; // Is a floating-point type to allow later calculation to produce a non-truncated value
|
if ((RearChunk == nullptr) || !RearChunk->IsValid())
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
NIBBLETYPE RearMeta = a_World.GetBlockMeta(RearCoordinate);
|
return SignalStrength;
|
||||||
RearPower = std::max(SignalStrength, PotentialSourceHandler->GetPowerDeliveredToPosition(a_World, RearCoordinate, RearType, RearMeta, a_Position, a_BlockType));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
// 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);
|
// 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)
|
// Delay is used here to prevent an infinite loop (#3168)
|
||||||
if (DelayInfo == nullptr)
|
if (DelayInfo == nullptr)
|
||||||
{
|
{
|
||||||
auto RearPower = GetPowerLevel(a_World, a_Position, a_BlockType, a_Meta);
|
const auto RearPower = GetPowerLevel(a_Chunk, a_Position, a_BlockType, a_Meta);
|
||||||
auto FrontPower = GetFrontPowerLevel(a_World, a_Position, a_BlockType, a_Meta, a_PoweringData.PowerLevel, RearPower);
|
const auto FrontPower = GetFrontPowerLevel(a_Meta, a_PoweringData.PowerLevel, RearPower);
|
||||||
auto PreviousFrontPower = Data->ExchangeUpdateOncePowerData(a_Position, PoweringData(a_PoweringData.PoweringBlock, FrontPower));
|
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
|
if (ShouldUpdate)
|
||||||
bool ShouldUpdate = (FrontPower != PreviousFrontPower.PowerLevel); // "Business logic" (:P) - determine by examining *side* power levels
|
|
||||||
|
|
||||||
if (ShouldUpdate || (ShouldBeOn != cBlockComparatorHandler::IsOn(a_Meta)))
|
|
||||||
{
|
{
|
||||||
Data->m_MechanismDelays[a_Position] = std::make_pair(1, ShouldBeOn);
|
Data.m_MechanismDelays[a_Position] = std::make_pair(1, bool());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int DelayTicks;
|
int DelayTicks;
|
||||||
bool ShouldPowerOn;
|
std::tie(DelayTicks, std::ignore) = *DelayInfo;
|
||||||
std::tie(DelayTicks, ShouldPowerOn) = *DelayInfo;
|
|
||||||
|
|
||||||
if (DelayTicks == 0)
|
if (DelayTicks == 0)
|
||||||
{
|
{
|
||||||
a_World.SetBlockMeta(a_Position, ShouldPowerOn ? (a_Meta | 0x8) : (a_Meta & 0x7));
|
const auto RearPower = GetPowerLevel(a_Chunk, a_Position, a_BlockType, a_Meta);
|
||||||
Data->m_MechanismDelays.erase(a_Position);
|
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.
|
// Don't care about the previous power level so return value ignored
|
||||||
// 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)
|
Data.ExchangeUpdateOncePowerData(a_Position, PoweringData(a_PoweringData.PoweringBlock, FrontPower));
|
||||||
// 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
|
a_Chunk.SetMeta(a_Position, NewMeta);
|
||||||
return StaticAppend(GetAdjustedRelatives(a_Position, GetRelativeLaterals()), cVector3iArray{ a_Position });
|
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);
|
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
|
#pragma once
|
||||||
|
|
||||||
#include "../../World.h"
|
#include "../../Chunk.h"
|
||||||
|
#include "RedstoneSimulatorChunkData.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -14,50 +15,11 @@ public:
|
|||||||
cRedstoneHandler() = default;
|
cRedstoneHandler() = default;
|
||||||
DISALLOW_COPY_AND_ASSIGN(cRedstoneHandler);
|
DISALLOW_COPY_AND_ASSIGN(cRedstoneHandler);
|
||||||
|
|
||||||
struct PoweringData
|
using SourceCallback = cFunctionRef<void(Vector3i)>;
|
||||||
{
|
|
||||||
public:
|
|
||||||
PoweringData(BLOCKTYPE a_PoweringBlock, unsigned char a_PowerLevel) :
|
|
||||||
PoweringBlock(a_PoweringBlock),
|
|
||||||
PowerLevel(a_PowerLevel)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
PoweringData(void) :
|
virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const = 0;
|
||||||
PoweringBlock(E_BLOCK_AIR),
|
virtual void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const = 0;
|
||||||
PowerLevel(0)
|
virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const = 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;
|
|
||||||
|
|
||||||
// Force a virtual destructor
|
// Force a virtual destructor
|
||||||
virtual ~cRedstoneHandler() {}
|
virtual ~cRedstoneHandler() {}
|
||||||
@ -72,15 +34,9 @@ protected:
|
|||||||
return ToReturn;
|
return ToReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static Vector3i OffsetYP()
|
inline static Vector3i OffsetYP{ 0, 1, 0 };
|
||||||
{
|
|
||||||
return Vector3i(0, 1, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline static Vector3i OffsetYM()
|
inline static Vector3i OffsetYM{ 0, -1, 0 };
|
||||||
{
|
|
||||||
return Vector3i(0, -1, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static cVector3iArray GetAdjustedRelatives(Vector3i a_Position, cVector3iArray a_Relatives)
|
static cVector3iArray GetAdjustedRelatives(Vector3i a_Position, cVector3iArray a_Relatives)
|
||||||
{
|
{
|
||||||
@ -91,31 +47,68 @@ protected:
|
|||||||
return a_Relatives;
|
return a_Relatives;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static cVector3iArray GetRelativeAdjacents()
|
inline static cIncrementalRedstoneSimulatorChunkData & DataForChunk(cChunk & a_Chunk)
|
||||||
{
|
{
|
||||||
return
|
return *static_cast<cIncrementalRedstoneSimulatorChunkData *>(a_Chunk.GetRedstoneSimulatorData());
|
||||||
{
|
|
||||||
{
|
|
||||||
{ 1, 0, 0 },
|
|
||||||
{ -1, 0, 0 },
|
|
||||||
{ 0, 1, 0 },
|
|
||||||
{ 0, -1, 0 },
|
|
||||||
{ 0, 0, 1 },
|
|
||||||
{ 0, 0, -1 },
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
{
|
DataForChunk(To).GetActiveBlocks().push(cIncrementalRedstoneSimulatorChunkData::RebaseRelativePosition(From, To, Position + Offset));
|
||||||
{ 1, 0, 0 },
|
}
|
||||||
{ -1, 0, 0 },
|
|
||||||
{ 0, 0, 1 },
|
UpdateAdjustedRelatives(From, To, Position, Relatives...);
|
||||||
{ 0, 0, -1 },
|
}
|
||||||
}
|
|
||||||
};
|
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:
|
public:
|
||||||
|
|
||||||
@ -14,17 +14,12 @@ public:
|
|||||||
return (a_BlockType == E_BLOCK_REDSTONE_LAMP_ON);
|
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;
|
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
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual cVector3iArray Update(cWorld & a_World, 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);
|
// LOGD("Evaluating lamp (%i %i %i)", a_Position.x, a_Position.y, a_Position.z);
|
||||||
|
|
||||||
@ -32,25 +27,23 @@ public:
|
|||||||
{
|
{
|
||||||
if (!IsOn(a_BlockType))
|
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
|
else
|
||||||
{
|
{
|
||||||
if (IsOn(a_BlockType))
|
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_Meta);
|
||||||
UNUSED(a_BlockType);
|
UNUSED(a_BlockType);
|
||||||
return GetAdjustedRelatives(a_Position, GetRelativeAdjacents());
|
InvokeForAdjustedRelatives(Callback, a_Position, RelativeAdjacents);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -15,37 +15,27 @@ class cRedstoneRepeaterHandler:
|
|||||||
|
|
||||||
public:
|
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 (
|
return ((a_QueryPosition == (a_Position + cBlockRedstoneRepeaterHandler::GetFrontCoordinateOffset(a_Meta))) && IsOn(a_BlockType)) ? 15 : 0;
|
||||||
(a_QueryPosition == (a_Position + cBlockRedstoneRepeaterHandler::GetFrontCoordinateOffset(a_Meta))) ?
|
|
||||||
GetPowerLevel(a_World, a_Position, a_BlockType, a_Meta) : 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 & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) 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
|
|
||||||
{
|
{
|
||||||
// LOGD("Evaluating loopy the repeater (%d %d %d)", a_Position.x, a_Position.y, a_Position.z);
|
// 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 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)
|
if (DelayInfo != nullptr)
|
||||||
{
|
{
|
||||||
Data->m_MechanismDelays.erase(a_Position);
|
Data.m_MechanismDelays.erase(a_Position);
|
||||||
}
|
}
|
||||||
|
|
||||||
return {};
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DelayInfo == nullptr)
|
if (DelayInfo == nullptr)
|
||||||
@ -53,7 +43,7 @@ public:
|
|||||||
bool ShouldBeOn = (a_PoweringData.PowerLevel != 0);
|
bool ShouldBeOn = (a_PoweringData.PowerLevel != 0);
|
||||||
if (ShouldBeOn != IsOn(a_BlockType))
|
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
|
else
|
||||||
@ -64,18 +54,23 @@ public:
|
|||||||
|
|
||||||
if (DelayTicks == 0)
|
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);
|
const auto NewType = ShouldPowerOn ? E_BLOCK_REDSTONE_REPEATER_ON : E_BLOCK_REDSTONE_REPEATER_OFF;
|
||||||
Data->m_MechanismDelays.erase(a_Position);
|
a_Chunk.FastSetBlock(a_Position, NewType, a_Meta);
|
||||||
return cVector3iArray{ cBlockRedstoneRepeaterHandler::GetFrontCoordinateOffset(a_Meta) + a_Position };
|
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:
|
private:
|
||||||
@ -87,12 +82,12 @@ private:
|
|||||||
|
|
||||||
/** Returns a pair with first element indicating if the block at the given position is an activated repeater.
|
/** 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. */
|
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;
|
BLOCKTYPE Type;
|
||||||
NIBBLETYPE Meta;
|
NIBBLETYPE Meta;
|
||||||
|
|
||||||
if (!a_World.GetBlockTypeMeta(a_Position, Type, Meta))
|
if (!Chunk.UnboundedRelGetBlock(a_Position, Type, Meta))
|
||||||
{
|
{
|
||||||
return std::make_pair(false, 0);
|
return std::make_pair(false, 0);
|
||||||
}
|
}
|
||||||
@ -103,20 +98,20 @@ private:
|
|||||||
/** Determine if a repeater is locked.
|
/** Determine if a repeater is locked.
|
||||||
A locked repeater is one with another powered repeater facing them, to their immediate left or right sides.
|
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. */
|
"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
|
// The left hand side offset. Will be negated to get the rhs offset
|
||||||
const auto LhsOffset = cBlockRedstoneRepeaterHandler::GetLeftCoordinateOffset(a_Meta);
|
const auto LhsOffset = cBlockRedstoneRepeaterHandler::GetLeftCoordinateOffset(a_Meta);
|
||||||
|
|
||||||
// Test the block to the left of us
|
// 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))
|
if (Lhs.first && DoesLhsLockMe(Lhs.second, a_Meta))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test the right side, flipping the argument order to DoesLhsLockMe
|
// 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);
|
return Rhs.first && DoesLhsLockMe(a_Meta, Rhs.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,73 +1,132 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "RedstoneHandler.h"
|
#include <stack>
|
||||||
|
|
||||||
#include "../RedstoneSimulator.h"
|
#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
|
class cIncrementalRedstoneSimulatorChunkData : public cRedstoneSimulatorChunkData
|
||||||
{
|
{
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
void WakeUp(const Vector3i & a_Position)
|
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);
|
auto Result = CachedPowerLevels.find(Position);
|
||||||
return (Result == m_CachedPowerLevels.end()) ? cRedstoneHandler::PoweringData() : Result->second;
|
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;
|
return (Result == m_MechanismDelays.end()) ? nullptr : &Result->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Erase cached PowerData for position */
|
/** Erase all cached redstone data for position. */
|
||||||
void ErasePowerData(const Vector3i & a_Position)
|
void ErasePowerData(const Vector3i Position)
|
||||||
{
|
{
|
||||||
m_CachedPowerLevels.erase(a_Position);
|
CachedPowerLevels.erase(Position);
|
||||||
m_MechanismDelays.erase(a_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);
|
auto Result = CachedPowerLevels.find(a_Position);
|
||||||
if (Result == m_CachedPowerLevels.end())
|
if (Result == CachedPowerLevels.end())
|
||||||
{
|
{
|
||||||
m_CachedPowerLevels[a_Position] = a_PoweringData;
|
CachedPowerLevels[a_Position] = a_PoweringData;
|
||||||
return cRedstoneHandler::PoweringData();
|
return PoweringData();
|
||||||
}
|
}
|
||||||
std::swap(Result->second, a_PoweringData);
|
std::swap(Result->second, a_PoweringData);
|
||||||
return 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 */
|
/** 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;
|
std::unordered_map<Vector3i, std::pair<int, bool>, VectorHasher<int>> m_MechanismDelays;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
cVector3iArray m_ActiveBlocks;
|
std::stack<Vector3i, std::vector<Vector3i>> ActiveBlocks;
|
||||||
|
|
||||||
// TODO: map<Vector3i, int> -> Position of torch + it's heat level
|
// 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;
|
friend class cRedstoneHandlerFactory;
|
||||||
|
|
||||||
|
@ -9,11 +9,8 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
class cRedstoneToggleHandler:
|
class cRedstoneToggleHandler final : public cRedstoneHandler
|
||||||
public cRedstoneHandler
|
|
||||||
{
|
{
|
||||||
using Super = cRedstoneHandler;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
inline static Vector3i GetPositionAttachedTo(Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta)
|
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);
|
UNUSED(a_QueryBlockType);
|
||||||
if ((GetPositionAttachedTo(a_Position, a_BlockType, a_Meta) == a_QueryPosition) || cIncrementalRedstoneSimulator::IsMechanism(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;
|
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)
|
switch (a_BlockType)
|
||||||
{
|
{
|
||||||
case E_BLOCK_LEVER: return cBlockLeverHandler::IsLeverOn(a_Meta) ? 15 : 0;
|
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);
|
// 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_Position);
|
||||||
UNUSED(a_BlockType);
|
UNUSED(a_BlockType);
|
||||||
UNUSED(a_Meta);
|
UNUSED(a_Meta);
|
||||||
return {};
|
UNUSED(Callback);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
class cRedstoneTorchHandler : public cRedstoneHandler
|
class cRedstoneTorchHandler final : public cRedstoneHandler
|
||||||
{
|
{
|
||||||
public:
|
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 (
|
if (
|
||||||
IsOn(a_BlockType) &&
|
IsOn(a_BlockType) &&
|
||||||
(a_QueryPosition != (a_Position + GetOffsetAttachedTo(a_Position, a_Meta))) &&
|
(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;
|
return 15;
|
||||||
@ -46,24 +46,19 @@ public:
|
|||||||
return 0;
|
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 & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) 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
|
|
||||||
{
|
{
|
||||||
// LOGD("Evaluating torchy the redstone torch (%i %i %i)", a_Position.x, a_Position.y, a_Position.z);
|
// 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 & Data = DataForChunk(a_Chunk);
|
||||||
auto DelayInfo = Data->GetMechanismDelayInfo(a_Position);
|
auto DelayInfo = Data.GetMechanismDelayInfo(a_Position);
|
||||||
|
|
||||||
if (DelayInfo == nullptr)
|
if (DelayInfo == nullptr)
|
||||||
{
|
{
|
||||||
bool ShouldBeOn = (a_PoweringData.PowerLevel == 0);
|
bool ShouldBeOn = (a_PoweringData.PowerLevel == 0);
|
||||||
if (ShouldBeOn != IsOn(a_BlockType))
|
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
|
else
|
||||||
@ -72,24 +67,28 @@ public:
|
|||||||
bool ShouldPowerOn;
|
bool ShouldPowerOn;
|
||||||
std::tie(DelayTicks, ShouldPowerOn) = *DelayInfo;
|
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);
|
return;
|
||||||
Data->m_MechanismDelays.erase(a_Position);
|
}
|
||||||
|
|
||||||
cVector3iArray RelativePositions = GetRelativeAdjacents();
|
a_Chunk.SetBlock(a_Position, ShouldPowerOn ? E_BLOCK_REDSTONE_TORCH_ON : E_BLOCK_REDSTONE_TORCH_OFF, a_Meta);
|
||||||
RelativePositions.erase(std::remove(RelativePositions.begin(), RelativePositions.end(), GetOffsetAttachedTo(a_Position, a_Meta)), RelativePositions.end());
|
Data.m_MechanismDelays.erase(a_Position);
|
||||||
return GetAdjustedRelatives(a_Position, RelativePositions);
|
|
||||||
|
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);
|
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:
|
class cRedstoneWireHandler final : public cRedstoneHandler
|
||||||
public cRedstoneHandler
|
|
||||||
{
|
{
|
||||||
using Super = cRedstoneHandler;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
inline static bool IsDirectlyConnectingMechanism(BLOCKTYPE a_Block, NIBBLETYPE a_BlockMeta, const Vector3i a_Offset)
|
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_Chunk.GetBlock(a_Position + OffsetYP);
|
||||||
const auto YPTerraceBlock = a_World.GetBlock(a_Position + OffsetYP());
|
|
||||||
const bool IsYPTerracingBlocked = cBlockInfo::IsSolid(YPTerraceBlock) && !cBlockInfo::IsTransparent(YPTerraceBlock);
|
const bool IsYPTerracingBlocked = cBlockInfo::IsSolid(YPTerraceBlock) && !cBlockInfo::IsTransparent(YPTerraceBlock);
|
||||||
|
|
||||||
for (const auto & Adjacent : GetRelativeLaterals())
|
for (const auto Adjacent : RelativeLaterals)
|
||||||
{
|
{
|
||||||
if (
|
// All laterals are counted as terracing, duh
|
||||||
// A block above us blocks all YP terracing, so the check is static in the loop
|
if (Callback(Adjacent))
|
||||||
!IsYPTerracingBlocked &&
|
|
||||||
(a_World.GetBlock(a_Position + Adjacent + OffsetYP()) == E_BLOCK_REDSTONE_WIRE)
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
RelativePositions.emplace_back(Adjacent + OffsetYP());
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto YMTerraceBlock = a_World.GetBlock(a_Position + Adjacent);
|
|
||||||
if (
|
if (
|
||||||
// IsYMTerracingBlocked (i.e. check block above lower terracing position, a.k.a. just the plain adjacent)
|
BLOCKTYPE YPBlock;
|
||||||
(!cBlockInfo::IsSolid(YMTerraceBlock) || cBlockInfo::IsTransparent(YMTerraceBlock)) &&
|
|
||||||
(a_World.GetBlock(a_Position + Adjacent + OffsetYM()) == E_BLOCK_REDSTONE_WIRE)
|
// 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
|
// Wires do not power things above them
|
||||||
return 0;
|
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
|
// 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
|
// Wires always deliver power to the block underneath, and any directly connecting mechanisms
|
||||||
if (
|
if (
|
||||||
(a_QueryPosition != (a_Position + OffsetYM())) &&
|
NIBBLETYPE QueryMeta;
|
||||||
!IsDirectlyConnectingMechanism(a_QueryBlockType, a_World.GetBlockMeta(a_QueryPosition), a_QueryPosition - a_Position)
|
|
||||||
|
(a_QueryPosition == (a_Position + OffsetYM)) ||
|
||||||
|
(a_Chunk.UnboundedRelGetBlockMeta(a_QueryPosition, QueryMeta) && IsDirectlyConnectingMechanism(a_QueryBlockType, QueryMeta, a_QueryPosition - a_Position))
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
/*
|
return a_Meta;
|
||||||
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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
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;
|
BLOCKTYPE Block;
|
||||||
NIBBLETYPE Meta;
|
NIBBLETYPE Meta;
|
||||||
|
|
||||||
if (
|
if (
|
||||||
!a_World.GetBlockTypeMeta(Offset + a_Position, Block, Meta) ||
|
!a_Chunk.UnboundedRelGetBlock(Offset + a_Position, Block, Meta) ||
|
||||||
!IsDirectlyConnectingMechanism(Block, Meta, Offset)
|
!IsDirectlyConnectingMechanism(Block, Meta, Offset)
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
continue;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FoundOneBorderingMechanism)
|
if (FoundOneBorderingMechanism)
|
||||||
{
|
{
|
||||||
// Case 3
|
// Case 3
|
||||||
return 0;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Potential case 2
|
// Potential case 2
|
||||||
FoundOneBorderingMechanism = true;
|
FoundOneBorderingMechanism = true;
|
||||||
PotentialOffset = { -Offset.x, 0, -Offset.z };
|
PotentialOffset = { -Offset.x, 0, -Offset.z };
|
||||||
}
|
|
||||||
|
|
||||||
if (FoundOneBorderingMechanism && (a_QueryPosition != (a_Position + PotentialOffset)))
|
return false;
|
||||||
{
|
})
|
||||||
// Case 2 fail
|
)
|
||||||
return 0;
|
{
|
||||||
}
|
// Case 3
|
||||||
|
return 0;
|
||||||
// Case 1
|
|
||||||
// Case 2 success
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
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);
|
// 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)
|
if (a_Meta != a_PoweringData.PowerLevel)
|
||||||
{
|
{
|
||||||
a_World.SetBlockMeta(a_Position, a_PoweringData.PowerLevel);
|
a_Chunk.SetMeta(a_Position, a_PoweringData.PowerLevel);
|
||||||
return GetAdjustedRelatives(a_Position, StaticAppend(StaticAppend(GetRelativeLaterals(), GetTerracingConnectionOffsets(a_World, a_Position)), cVector3iArray{ OffsetYM() }));
|
|
||||||
}
|
|
||||||
|
|
||||||
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_BlockType);
|
||||||
UNUSED(a_Meta);
|
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:
|
class cSmallGateHandler final : public cRedstoneHandler
|
||||||
public cRedstoneHandler
|
|
||||||
{
|
{
|
||||||
using Super = cRedstoneHandler;
|
|
||||||
|
|
||||||
public:
|
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_Position);
|
||||||
UNUSED(a_BlockType);
|
UNUSED(a_BlockType);
|
||||||
UNUSED(a_Meta);
|
UNUSED(a_Meta);
|
||||||
@ -25,32 +22,24 @@ public:
|
|||||||
return 0;
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual cVector3iArray Update(cWorld & a_World, 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);
|
// 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_BlockType);
|
||||||
UNUSED(a_Meta);
|
UNUSED(a_Meta);
|
||||||
return GetAdjustedRelatives(a_Position, GetRelativeAdjacents());
|
InvokeForAdjustedRelatives(Callback, a_Position, RelativeAdjacents);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -14,41 +14,34 @@ class cSolidBlockHandler:
|
|||||||
|
|
||||||
public:
|
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 (
|
return (
|
||||||
!cIncrementalRedstoneSimulator::IsRedstone(a_QueryBlockType) ||
|
!cIncrementalRedstoneSimulator::IsRedstone(a_QueryBlockType) ||
|
||||||
(
|
(
|
||||||
(a_QueryBlockType == E_BLOCK_REDSTONE_WIRE) &&
|
(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
|
virtual void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) 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
|
|
||||||
{
|
{
|
||||||
UNUSED(a_BlockType);
|
UNUSED(a_BlockType);
|
||||||
UNUSED(a_Meta);
|
UNUSED(a_Meta);
|
||||||
// LOGD("Evaluating blocky the generic block (%d %d %d)", a_Position.x, a_Position.y, a_Position.z);
|
// 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))
|
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_BlockType);
|
||||||
UNUSED(a_Meta);
|
UNUSED(a_Meta);
|
||||||
|
|
||||||
@ -64,6 +57,6 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
return GetAdjustedRelatives(a_Position, GetRelativeAdjacents());
|
InvokeForAdjustedRelatives(Callback, a_Position, RelativeAdjacents);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -7,16 +7,13 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
class cTNTHandler:
|
class cTNTHandler final : public cRedstoneHandler
|
||||||
public cRedstoneHandler
|
|
||||||
{
|
{
|
||||||
using Super = cRedstoneHandler;
|
|
||||||
|
|
||||||
public:
|
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_Position);
|
||||||
UNUSED(a_BlockType);
|
UNUSED(a_BlockType);
|
||||||
UNUSED(a_Meta);
|
UNUSED(a_Meta);
|
||||||
@ -25,31 +22,21 @@ public:
|
|||||||
return 0;
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual cVector3iArray Update(cWorld & a_World, 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);
|
// LOGD("Evaluating explodinator the trinitrotoluene (%d %d %d)", a_Position.x, a_Position.y, a_Position.z);
|
||||||
if (a_PoweringData.PowerLevel != 0)
|
if (a_PoweringData.PowerLevel != 0)
|
||||||
{
|
{
|
||||||
a_World.SetBlock(a_Position.x, a_Position.y, a_Position.z, E_BLOCK_AIR, 0);
|
a_Chunk.SetBlock(a_Position, E_BLOCK_AIR, 0);
|
||||||
a_World.SpawnPrimedTNT(Vector3d(a_Position) + Vector3d(0.5, 0.5, 0.5)); // 80 ticks to boom
|
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_BlockType);
|
||||||
UNUSED(a_Meta);
|
UNUSED(a_Meta);
|
||||||
return GetAdjustedRelatives(a_Position, GetRelativeAdjacents());
|
InvokeForAdjustedRelatives(Callback, a_Position, RelativeAdjacents);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -15,54 +15,51 @@ class cTrappedChestHandler:
|
|||||||
|
|
||||||
public:
|
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_BlockType);
|
||||||
UNUSED(a_Meta);
|
UNUSED(a_Meta);
|
||||||
UNUSED(a_QueryPosition);
|
UNUSED(a_QueryPosition);
|
||||||
UNUSED(a_QueryBlockType);
|
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;
|
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);
|
ASSERT(a_Chest.GetBlockType() == E_BLOCK_TRAPPED_CHEST);
|
||||||
NumberOfPlayers = a_Chest.GetNumberOfPlayers();
|
NumberOfPlayers = a_Chest.GetNumberOfPlayers();
|
||||||
return true;
|
return true;
|
||||||
}
|
})
|
||||||
));
|
);
|
||||||
|
|
||||||
return static_cast<unsigned char>(std::min(NumberOfPlayers, 15));
|
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);
|
// 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);
|
const auto Power = GetPowerLevel(a_Chunk, a_Position);
|
||||||
auto PreviousPower = static_cast<cIncrementalRedstoneSimulator *>(a_World.GetRedstoneSimulator())->GetChunkData()->ExchangeUpdateOncePowerData(a_Position, PoweringData(a_BlockType, Power));
|
const auto PreviousPower = DataForChunk(a_Chunk).ExchangeUpdateOncePowerData(a_Position, PoweringData(a_BlockType, Power));
|
||||||
|
|
||||||
if (Power != PreviousPower.PowerLevel)
|
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_Position);
|
||||||
UNUSED(a_BlockType);
|
UNUSED(a_BlockType);
|
||||||
UNUSED(a_Meta);
|
UNUSED(a_Meta);
|
||||||
|
UNUSED(Callback);
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -8,43 +8,53 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
class cTripwireHookHandler:
|
class cTripwireHookHandler final : public cRedstoneHandler
|
||||||
public cRedstoneHandler
|
|
||||||
{
|
{
|
||||||
using Super = cRedstoneHandler;
|
|
||||||
|
|
||||||
public:
|
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_QueryBlockType);
|
||||||
UNUSED(a_QueryPosition);
|
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;
|
bool FoundActivated = false;
|
||||||
auto Position = a_Position;
|
const auto FaceToGoTowards = cBlockTripwireHookHandler::MetadataToDirection(a_Meta);
|
||||||
eBlockFace FaceToGoTowards = cBlockTripwireHookHandler::MetadataToDirection(a_Meta);
|
|
||||||
|
|
||||||
for (int i = 0; i < 40; ++i) // Tripwires can be connected up to 40 blocks
|
for (int i = 0; i < 40; ++i) // Tripwires can be connected up to 40 blocks
|
||||||
{
|
{
|
||||||
BLOCKTYPE Type;
|
BLOCKTYPE Type;
|
||||||
NIBBLETYPE Meta;
|
NIBBLETYPE Meta;
|
||||||
|
|
||||||
AddFaceDirection(Position.x, Position.y, Position.z, FaceToGoTowards);
|
a_Position = AddFaceDirection(a_Position, FaceToGoTowards);
|
||||||
a_World.GetBlockTypeMeta(Position.x, Position.y, Position.z, Type, Meta);
|
if (!a_Chunk.UnboundedRelGetBlock(a_Position, Type, Meta))
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (Type == E_BLOCK_TRIPWIRE)
|
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;
|
FoundActivated = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
else if (Type == E_BLOCK_TRIPWIRE_HOOK)
|
else if (Type == E_BLOCK_TRIPWIRE_HOOK)
|
||||||
{
|
{
|
||||||
@ -53,27 +63,20 @@ public:
|
|||||||
// Other hook facing in opposite direction - circuit completed!
|
// Other hook facing in opposite direction - circuit completed!
|
||||||
return FoundActivated ? 15 : 1;
|
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;
|
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);
|
// 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;
|
NIBBLETYPE Meta;
|
||||||
if (Power == 0)
|
if (Power == 0)
|
||||||
{
|
{
|
||||||
@ -91,25 +94,22 @@ public:
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ASSERT(!"Unexpected tripwire hook power level!");
|
UNREACHABLE("Unexpected tripwire hook power level!");
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Meta != a_Meta)
|
if (Meta != a_Meta)
|
||||||
{
|
{
|
||||||
a_World.SetBlockMeta(a_Position, Meta);
|
a_Chunk.SetMeta(a_Position, Meta);
|
||||||
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_BlockType);
|
||||||
UNUSED(a_Meta);
|
UNUSED(a_Meta);
|
||||||
UNUSED(a_Position);
|
UNUSED(a_Position);
|
||||||
return {};
|
UNUSED(Callback);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
class cRedstoneNoopSimulator:
|
class cRedstoneNoopSimulator final :
|
||||||
public cRedstoneSimulator
|
public cRedstoneSimulator
|
||||||
{
|
{
|
||||||
using Super = cRedstoneSimulator;
|
using Super = cRedstoneSimulator;
|
||||||
|
Loading…
Reference in New Issue
Block a user