1
0

Replace PowerData struct with PowerLevel

* We no longer need to track the powering block with the removal of SolidBlockHandler. PowerLevel is now just an unsigned char
This commit is contained in:
Tiger Wang 2020-08-20 20:04:28 +01:00
parent 03557e978e
commit d8c8d0124d
25 changed files with 171 additions and 189 deletions

View File

@ -9,7 +9,7 @@
namespace CommandBlockHandler namespace CommandBlockHandler
{ {
inline unsigned char GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) inline PowerLevel GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked)
{ {
UNUSED(a_Chunk); UNUSED(a_Chunk);
UNUSED(a_Position); UNUSED(a_Position);
@ -20,12 +20,12 @@ namespace CommandBlockHandler
return 0; return 0;
} }
inline void Update(cChunk & a_Chunk, cChunk &, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) inline void Update(cChunk & a_Chunk, cChunk &, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, const PowerLevel Power)
{ {
// 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 = DataForChunk(a_Chunk).ExchangeUpdateOncePowerData(a_Position, a_PoweringData); const auto Previous = DataForChunk(a_Chunk).ExchangeUpdateOncePowerData(a_Position, Power);
if ((Previous.PowerLevel != 0) || (a_PoweringData.PowerLevel == 0)) if ((Previous != 0) || (Power == 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;

View File

@ -11,7 +11,7 @@ namespace DoorHandler
{ {
// "Doormammu, I've come to bargain" // "Doormammu, I've come to bargain"
inline unsigned char GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) inline PowerLevel GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked)
{ {
UNUSED(a_Chunk); UNUSED(a_Chunk);
UNUSED(a_Position); UNUSED(a_Position);
@ -22,7 +22,7 @@ namespace DoorHandler
return 0; return 0;
} }
inline void Update(cChunk & a_Chunk, cChunk &, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) inline void Update(cChunk & a_Chunk, cChunk &, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PowerLevel Power)
{ {
// 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);
@ -37,10 +37,10 @@ namespace DoorHandler
RedstoneHandler::ForValidSourcePositions(a_Chunk, TopPosition, a_BlockType, a_Meta, Callback); RedstoneHandler::ForValidSourcePositions(a_Chunk, TopPosition, a_BlockType, a_Meta, Callback);
// Factor in what the upper half is getting: // Factor in what the upper half is getting:
a_PoweringData = std::max(a_PoweringData, Callback.Power); Power = std::max(Power, Callback.Power);
cChunkInterface ChunkInterface(a_Chunk.GetWorld()->GetChunkMap()); cChunkInterface ChunkInterface(a_Chunk.GetWorld()->GetChunkMap());
const bool ShouldBeOpen = a_PoweringData.PowerLevel != 0; const bool ShouldBeOpen = Power != 0;
const auto AbsolutePosition = cChunkDef::RelativeToAbsolute(a_Position, a_Chunk.GetPos()); const auto AbsolutePosition = cChunkDef::RelativeToAbsolute(a_Position, a_Chunk.GetPos());
const bool IsOpen = cBlockDoorHandler::IsOpen(ChunkInterface, AbsolutePosition); const bool IsOpen = cBlockDoorHandler::IsOpen(ChunkInterface, AbsolutePosition);

View File

@ -26,7 +26,7 @@ namespace DropSpenserHandler
} }
} }
inline unsigned char GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) inline PowerLevel GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked)
{ {
UNUSED(a_Chunk); UNUSED(a_Chunk);
UNUSED(a_Position); UNUSED(a_Position);
@ -37,11 +37,11 @@ namespace DropSpenserHandler
return 0; return 0;
} }
inline void Update(cChunk & a_Chunk, cChunk &, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) inline void Update(cChunk & a_Chunk, cChunk &, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, const PowerLevel Power)
{ {
// 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);
const bool IsPoweredNow = (a_PoweringData.PowerLevel > 0); const bool IsPoweredNow = (Power > 0);
const bool WasPoweredPreviously = IsActivated(a_Meta); const bool WasPoweredPreviously = IsActivated(a_Meta);
if (IsPoweredNow && !WasPoweredPreviously) if (IsPoweredNow && !WasPoweredPreviously)

View File

@ -12,6 +12,7 @@
ForEachSourceCallback::ForEachSourceCallback(const cChunk & Chunk, const Vector3i Position, const BLOCKTYPE CurrentBlock) : ForEachSourceCallback::ForEachSourceCallback(const cChunk & Chunk, const Vector3i Position, const BLOCKTYPE CurrentBlock) :
Power(0),
m_Chunk(Chunk), m_Chunk(Chunk),
m_Position(Position), m_Position(Position),
m_CurrentBlock(CurrentBlock) m_CurrentBlock(CurrentBlock)
@ -26,8 +27,13 @@ bool ForEachSourceCallback::ShouldQueryLinkedPosition(const Vector3i Location, c
{ {
switch (Block) switch (Block)
{ {
// Normally we don't ask solid blocks for power because they don't have any (store, dirt, etc.)
// However, these are mechanisms that are IsSolid, but still give power. Don't ignore them:
case E_BLOCK_BLOCK_OF_REDSTONE: case E_BLOCK_BLOCK_OF_REDSTONE:
case E_BLOCK_OBSERVER:
case E_BLOCK_TRAPPED_CHEST: return false; case E_BLOCK_TRAPPED_CHEST: return false;
// If a mechanism asks for power from a block, redirect the query to linked positions if:
default: return cBlockInfo::IsSolid(Block); default: return cBlockInfo::IsSolid(Block);
} }
} }
@ -58,7 +64,13 @@ void ForEachSourceCallback::operator()(Vector3i Location)
} }
else else
{ {
Power = std::max(Power, QueryPower(*NeighbourChunk, Location, PotentialSourceBlock, NeighbourRelativeQueryPosition, m_CurrentBlock, false)); Power = std::max(
Power,
RedstoneHandler::GetPowerDeliveredToPosition(
*NeighbourChunk, Location, PotentialSourceBlock,
NeighbourRelativeQueryPosition, m_CurrentBlock, false
)
);
} }
} }
@ -66,26 +78,11 @@ void ForEachSourceCallback::operator()(Vector3i Location)
PoweringData ForEachSourceCallback::QueryPower(const cChunk & Chunk, const Vector3i SourcePosition, const BLOCKTYPE SourceBlock, const Vector3i QueryPosition, const BLOCKTYPE QueryBlock, const bool IsLinked) PowerLevel ForEachSourceCallback::QueryLinkedPower(const cChunk & Chunk, const Vector3i QueryPosition, const BLOCKTYPE QueryBlock, const Vector3i SolidBlockPosition)
{ {
return PowerLevel Power = 0;
{
SourceBlock,
RedstoneHandler::GetPowerDeliveredToPosition(
Chunk, SourcePosition, SourceBlock,
QueryPosition, QueryBlock, IsLinked
)
};
}
PoweringData ForEachSourceCallback::QueryLinkedPower(const cChunk & Chunk, const Vector3i QueryPosition, const BLOCKTYPE QueryBlock, const Vector3i SolidBlockPosition)
{
PoweringData Power;
// Loop through all linked powerable offsets in the direction requested:
for (const auto Offset : cSimulator::GetLinkedOffsets(SolidBlockPosition - QueryPosition)) for (const auto Offset : cSimulator::GetLinkedOffsets(SolidBlockPosition - QueryPosition))
{ {
auto SourcePosition = QueryPosition + Offset; auto SourcePosition = QueryPosition + Offset;
@ -100,8 +97,17 @@ PoweringData ForEachSourceCallback::QueryLinkedPower(const cChunk & Chunk, const
continue; continue;
} }
// Conduit block's position, relative to NeighbourChunk.
const auto NeighbourRelativeSolidBlockPosition = cIncrementalRedstoneSimulatorChunkData::RebaseRelativePosition(Chunk, *NeighbourChunk, SolidBlockPosition); const auto NeighbourRelativeSolidBlockPosition = cIncrementalRedstoneSimulatorChunkData::RebaseRelativePosition(Chunk, *NeighbourChunk, SolidBlockPosition);
Power = std::max(Power, QueryPower(*NeighbourChunk, SourcePosition, NeighbourChunk->GetBlock(SourcePosition), NeighbourRelativeSolidBlockPosition, QueryBlock, true));
// Do a standard power query, but the requester's position is actually the solid block that will conduct power:
Power = std::max(
Power,
RedstoneHandler::GetPowerDeliveredToPosition(
*NeighbourChunk, SourcePosition, NeighbourChunk->GetBlock(SourcePosition),
NeighbourRelativeSolidBlockPosition, QueryBlock, true
)
);
} }
return Power; return Power;

View File

@ -15,13 +15,11 @@ public:
/** Callback invoked for each potential source position of the redstone component. */ /** Callback invoked for each potential source position of the redstone component. */
void operator()(Vector3i Location); void operator()(Vector3i Location);
/** Asks a redstone component at the source position how much power it will deliver to the querying position. */ /** Asks redstone handlers adjacent to a solid block how much power they will deliver to the querying position, via the solid block.
static PoweringData QueryPower(const cChunk & Chunk, Vector3i SourcePosition, BLOCKTYPE SourceBlock, Vector3i QueryPosition, BLOCKTYPE QueryBlock, bool IsLinked); Both QueryPosition and SolidBlockPosition are relative to Chunk. */
static PowerLevel QueryLinkedPower(const cChunk & Chunk, Vector3i QueryPosition, BLOCKTYPE QueryBlock, Vector3i SolidBlockPosition);
/** Asks redstone handlers adjacent to a solid block how much power they will deliver to the querying position, via the solid block. */ PowerLevel Power;
static PoweringData QueryLinkedPower(const cChunk & Chunk, Vector3i QueryPosition, BLOCKTYPE QueryBlock, Vector3i SolidBlockPosition);
PoweringData Power;
private: private:

View File

@ -9,7 +9,7 @@
namespace HopperHandler namespace HopperHandler
{ {
inline unsigned char GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) inline PowerLevel GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked)
{ {
UNUSED(a_Chunk); UNUSED(a_Chunk);
UNUSED(a_Position); UNUSED(a_Position);
@ -20,19 +20,19 @@ namespace HopperHandler
return 0; return 0;
} }
inline void Update(cChunk & a_Chunk, cChunk &, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) inline void Update(cChunk & a_Chunk, cChunk &, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, const PowerLevel Power)
{ {
// LOGD("Evaluating holey the hopper (%d %d %d)", a_Position.x, a_Position.y, a_Position.z); // LOGD("Evaluating holey the hopper (%d %d %d)", a_Position.x, a_Position.y, a_Position.z);
auto Previous = DataForChunk(a_Chunk).ExchangeUpdateOncePowerData(a_Position, a_PoweringData); const auto Previous = DataForChunk(a_Chunk).ExchangeUpdateOncePowerData(a_Position, Power);
if (Previous.PowerLevel == a_PoweringData.PowerLevel) if (Previous == Power)
{ {
return; return;
} }
a_Chunk.DoWithHopperAt(a_Position, [a_PoweringData](cHopperEntity & a_Hopper) a_Chunk.DoWithHopperAt(a_Position, [Power](cHopperEntity & a_Hopper)
{ {
a_Hopper.SetLocked(a_PoweringData.PowerLevel != 0); a_Hopper.SetLocked(Power != 0);
return false; return false;
}); });
} }

View File

@ -9,7 +9,7 @@
namespace NoteBlockHandler namespace NoteBlockHandler
{ {
inline unsigned char GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) inline PowerLevel GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked)
{ {
UNUSED(a_Chunk); UNUSED(a_Chunk);
UNUSED(a_Position); UNUSED(a_Position);
@ -20,12 +20,12 @@ namespace NoteBlockHandler
return 0; return 0;
} }
inline void Update(cChunk & a_Chunk, cChunk &, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) inline void Update(cChunk & a_Chunk, cChunk &, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, const PowerLevel Power)
{ {
// 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, Power);
auto Previous = DataForChunk(a_Chunk).ExchangeUpdateOncePowerData(a_Position, a_PoweringData); const auto Previous = DataForChunk(a_Chunk).ExchangeUpdateOncePowerData(a_Position, Power);
if ((Previous.PowerLevel != 0) || (a_PoweringData.PowerLevel == 0)) if ((Previous != 0) || (Power == 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;

View File

@ -23,21 +23,36 @@ namespace ObserverHandler
return false; return false;
} }
// Cache the last seen block type and meta in the power data for this position auto & ObserverCache = a_Data.ObserverCache;
auto Observed = PoweringData(BlockType, BlockMeta); const auto FindResult = ObserverCache.find(a_Position);
auto Previous = a_Data.ExchangeUpdateOncePowerData(a_Position, Observed); const auto Observed = std::make_pair(BlockType, BlockMeta);
if (FindResult == ObserverCache.end())
{
// Cache the last seen block for this position:
ObserverCache.emplace(a_Position, Observed);
// Definitely should signal update:
return true;
}
// The block this observer previously saw.
const auto Previous = FindResult->second;
// Update the last seen block:
FindResult->second = 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 != Observed;
} }
inline unsigned char GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) inline PowerLevel GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked)
{ {
const auto Meta = a_Chunk.GetMeta(a_Position); const auto Meta = a_Chunk.GetMeta(a_Position);
return (IsOn(Meta) && (a_QueryPosition == (a_Position + cBlockObserverHandler::GetSignalOutputOffset(Meta)))) ? 15 : 0; return (IsOn(Meta) && (a_QueryPosition == (a_Position + cBlockObserverHandler::GetSignalOutputOffset(Meta)))) ? 15 : 0;
} }
inline void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) inline void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, const PowerLevel Power)
{ {
// 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);

View File

@ -9,7 +9,7 @@
namespace PistonHandler namespace PistonHandler
{ {
inline unsigned char GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) inline PowerLevel GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked)
{ {
UNUSED(a_Chunk); UNUSED(a_Chunk);
UNUSED(a_Position); UNUSED(a_Position);
@ -20,11 +20,11 @@ namespace PistonHandler
return 0; return 0;
} }
inline void Update(cChunk & a_Chunk, cChunk &, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) inline void Update(cChunk & a_Chunk, cChunk &, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, const PowerLevel Power)
{ {
// 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);
const bool ShouldBeExtended = a_PoweringData.PowerLevel != 0; const bool ShouldBeExtended = Power != 0;
if (ShouldBeExtended == cBlockPistonHandler::IsExtended(a_Meta)) if (ShouldBeExtended == cBlockPistonHandler::IsExtended(a_Meta))
{ {
return; return;

View File

@ -25,7 +25,7 @@ namespace PoweredRailHandler
} }
} }
inline unsigned char GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) inline PowerLevel GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked)
{ {
UNUSED(a_QueryBlockType); UNUSED(a_QueryBlockType);
@ -33,13 +33,13 @@ namespace PoweredRailHandler
const auto Offset = GetPoweredRailAdjacentXZCoordinateOffset(Meta); const auto Offset = GetPoweredRailAdjacentXZCoordinateOffset(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 = DataForChunk(a_Chunk).GetCachedPowerData(a_Position).PowerLevel; const auto Power = DataForChunk(a_Chunk).GetCachedPowerData(a_Position);
return (Power <= 7) ? 0 : --Power; return (Power <= 7) ? 0 : (Power - 1);
} }
return 0; return 0;
} }
inline void Update(cChunk & a_Chunk, cChunk & CurrentlyTickingChunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) inline void Update(cChunk & a_Chunk, cChunk & CurrentlyTickingChunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, const PowerLevel Power)
{ {
// 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);
@ -58,10 +58,10 @@ namespace PoweredRailHandler
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); const auto Offset = GetPoweredRailAdjacentXZCoordinateOffset(a_Meta);
if (a_PoweringData != DataForChunk(a_Chunk).ExchangeUpdateOncePowerData(a_Position, a_PoweringData)) if (Power != DataForChunk(a_Chunk).ExchangeUpdateOncePowerData(a_Position, Power))
{ {
a_Chunk.SetMeta(a_Position, (a_PoweringData.PowerLevel == 0) ? (a_Meta & 0x07) : (a_Meta | 0x08)); a_Chunk.SetMeta(a_Position, (Power == 0) ? (a_Meta & 0x07) : (a_Meta | 0x08));
UpdateAdjustedRelative(a_Chunk, CurrentlyTickingChunk, a_Position, Offset); UpdateAdjustedRelative(a_Chunk, CurrentlyTickingChunk, a_Position, Offset);
UpdateAdjustedRelative(a_Chunk, CurrentlyTickingChunk, a_Position, -Offset); UpdateAdjustedRelative(a_Chunk, CurrentlyTickingChunk, a_Position, -Offset);

View File

@ -91,7 +91,7 @@ namespace PressurePlateHandler
} }
} }
inline unsigned char GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) inline PowerLevel GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked)
{ {
UNUSED(a_BlockType); UNUSED(a_BlockType);
UNUSED(a_QueryPosition); UNUSED(a_QueryPosition);
@ -99,10 +99,10 @@ namespace PressurePlateHandler
// Plates only link power blocks below // Plates only link power blocks below
// Retrieve and return the cached power calculated by Update for performance: // Retrieve and return the cached power calculated by Update for performance:
return (IsLinked && (a_QueryPosition != (a_Position + OffsetYM))) ? 0 : DataForChunk(a_Chunk).GetCachedPowerData(a_Position).PowerLevel; return (IsLinked && (a_QueryPosition != (a_Position + OffsetYM))) ? 0 : DataForChunk(a_Chunk).GetCachedPowerData(a_Position);
} }
inline void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) inline void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, const PowerLevel Power)
{ {
// 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);
@ -110,13 +110,13 @@ namespace PressurePlateHandler
const auto PreviousPower = ChunkData.GetCachedPowerData(a_Position); const auto PreviousPower = ChunkData.GetCachedPowerData(a_Position);
const auto Absolute = cChunkDef::RelativeToAbsolute(a_Position, a_Chunk.GetPos()); 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 PowerLevel = GetPowerLevel(a_Chunk, Absolute, a_BlockType); // Get the current power of the platey
const auto DelayInfo = ChunkData.GetMechanismDelayInfo(a_Position); const auto DelayInfo = ChunkData.GetMechanismDelayInfo(a_Position);
// Resting state? // Resting state?
if (DelayInfo == nullptr) if (DelayInfo == nullptr)
{ {
if (Power == 0) if (PowerLevel == 0)
{ {
// Nothing happened, back to rest // Nothing happened, back to rest
return; return;
@ -129,7 +129,7 @@ namespace PressurePlateHandler
a_Chunk.GetWorld()->BroadcastSoundEffect(GetClickOnSound(a_BlockType), Absolute, 0.5f, 0.6f); a_Chunk.GetWorld()->BroadcastSoundEffect(GetClickOnSound(a_BlockType), Absolute, 0.5f, 0.6f);
// Update power // Update power
ChunkData.SetCachedPowerData(a_Position, PoweringData(a_BlockType, Power)); ChunkData.SetCachedPowerData(a_Position, PowerLevel);
// Immediately depress plate // Immediately depress plate
a_Chunk.SetMeta(a_Position, E_META_PRESSURE_PLATE_DEPRESSED); a_Chunk.SetMeta(a_Position, E_META_PRESSURE_PLATE_DEPRESSED);
@ -148,7 +148,7 @@ namespace PressurePlateHandler
if (DelayTicks > 0) if (DelayTicks > 0)
{ {
// 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 (PowerLevel == 0)
{ {
return; return;
} }
@ -161,10 +161,10 @@ namespace PressurePlateHandler
} }
// 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 (PowerLevel != PreviousPower)
{ {
// Yes. Update power // Yes. Update power
ChunkData.SetCachedPowerData(a_Position, PoweringData(a_BlockType, Power)); ChunkData.SetCachedPowerData(a_Position, PowerLevel);
UpdateAdjustedRelatives(a_Chunk, CurrentlyTicking, a_Position, RelativeAdjacents); UpdateAdjustedRelatives(a_Chunk, CurrentlyTicking, a_Position, RelativeAdjacents);
} }
@ -175,7 +175,7 @@ namespace PressurePlateHandler
if (HasExitedMinimumOnDelayPhase) if (HasExitedMinimumOnDelayPhase)
{ {
// Yep, initial delay elapsed. Has the player gotten off? // Yep, initial delay elapsed. Has the player gotten off?
if (Power == 0) if (PowerLevel == 0)
{ {
// 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);
@ -183,10 +183,10 @@ namespace PressurePlateHandler
} }
// 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 (PowerLevel != PreviousPower)
{ {
// Yes. Update power // Yes. Update power
ChunkData.SetCachedPowerData(a_Position, PoweringData(a_BlockType, Power)); ChunkData.SetCachedPowerData(a_Position, PowerLevel);
UpdateAdjustedRelatives(a_Chunk, CurrentlyTicking, a_Position, RelativeAdjacents); UpdateAdjustedRelatives(a_Chunk, CurrentlyTicking, a_Position, RelativeAdjacents);
} }
@ -198,7 +198,7 @@ namespace PressurePlateHandler
ChunkData.m_MechanismDelays.erase(a_Position); ChunkData.m_MechanismDelays.erase(a_Position);
a_Chunk.GetWorld()->BroadcastSoundEffect(GetClickOffSound(a_BlockType), Absolute, 0.5f, 0.5f); a_Chunk.GetWorld()->BroadcastSoundEffect(GetClickOffSound(a_BlockType), Absolute, 0.5f, 0.5f);
ChunkData.SetCachedPowerData(a_Position, PoweringData(a_BlockType, Power)); ChunkData.SetCachedPowerData(a_Position, PowerLevel);
a_Chunk.SetMeta(a_Position, E_META_PRESSURE_PLATE_RAISED); a_Chunk.SetMeta(a_Position, E_META_PRESSURE_PLATE_RAISED);
UpdateAdjustedRelatives(a_Chunk, CurrentlyTicking, a_Position, RelativeAdjacents); UpdateAdjustedRelatives(a_Chunk, CurrentlyTicking, a_Position, RelativeAdjacents);

View File

@ -7,7 +7,7 @@
namespace RedstoneBlockHandler namespace RedstoneBlockHandler
{ {
inline unsigned char GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) inline PowerLevel GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked)
{ {
UNUSED(a_Chunk); UNUSED(a_Chunk);
UNUSED(a_Position); UNUSED(a_Position);
@ -17,7 +17,7 @@ namespace RedstoneBlockHandler
return IsLinked ? 0 : 15; return IsLinked ? 0 : 15;
} }
inline void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) inline void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, const PowerLevel Power)
{ {
// 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);
} }

View File

@ -23,7 +23,7 @@ namespace RedstoneComparatorHandler
} }
} }
inline unsigned char GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) inline PowerLevel GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked)
{ {
UNUSED(a_QueryPosition); UNUSED(a_QueryPosition);
UNUSED(a_QueryBlockType); UNUSED(a_QueryBlockType);
@ -31,7 +31,7 @@ namespace RedstoneComparatorHandler
const auto Meta = a_Chunk.GetMeta(a_Position); const auto Meta = a_Chunk.GetMeta(a_Position);
return ( return (
(cBlockComparatorHandler::GetFrontCoordinate(a_Position, Meta & 0x3) == a_QueryPosition) ? (cBlockComparatorHandler::GetFrontCoordinate(a_Position, Meta & 0x3) == a_QueryPosition) ?
DataForChunk(a_Chunk).GetCachedPowerData(a_Position).PowerLevel : 0 DataForChunk(a_Chunk).GetCachedPowerData(a_Position) : 0
); );
} }
@ -79,9 +79,9 @@ namespace RedstoneComparatorHandler
); );
} }
inline void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) inline void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, const PowerLevel Power)
{ {
// Note that a_PoweringData here contains the maximum * side * power level, as specified by GetValidSourcePositions // Note that Power 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 = DataForChunk(a_Chunk); auto & Data = DataForChunk(a_Chunk);
@ -91,9 +91,9 @@ namespace RedstoneComparatorHandler
if (DelayInfo == nullptr) if (DelayInfo == nullptr)
{ {
const auto RearPower = GetPowerLevel(a_Chunk, a_Position, a_BlockType, a_Meta); const auto RearPower = GetPowerLevel(a_Chunk, a_Position, a_BlockType, a_Meta);
const auto FrontPower = GetFrontPowerLevel(a_Meta, a_PoweringData.PowerLevel, RearPower); const auto FrontPower = GetFrontPowerLevel(a_Meta, Power, RearPower);
const auto PreviousFrontPower = Data.GetCachedPowerData(a_Position); const auto PreviousFrontPower = Data.GetCachedPowerData(a_Position);
const bool ShouldUpdate = (FrontPower != PreviousFrontPower.PowerLevel); // "Business logic" (:P) - determined by side and rear power levels const bool ShouldUpdate = (FrontPower != PreviousFrontPower); // "Business logic" (:P) - determined by side and rear power levels
if (ShouldUpdate) if (ShouldUpdate)
{ {
@ -112,11 +112,11 @@ namespace RedstoneComparatorHandler
} }
const auto RearPower = GetPowerLevel(a_Chunk, a_Position, a_BlockType, a_Meta); const auto RearPower = GetPowerLevel(a_Chunk, a_Position, a_BlockType, a_Meta);
const auto FrontPower = GetFrontPowerLevel(a_Meta, a_PoweringData.PowerLevel, RearPower); const auto FrontPower = GetFrontPowerLevel(a_Meta, Power, RearPower);
const auto NewMeta = (FrontPower > 0) ? (a_Meta | 0x8) : (a_Meta & 0x7); const auto NewMeta = (FrontPower > 0) ? (a_Meta | 0x8) : (a_Meta & 0x7);
// Don't care about the previous power level so return value ignored // Don't care about the previous power level so return value ignored
Data.ExchangeUpdateOncePowerData(a_Position, PoweringData(a_PoweringData.PoweringBlock, FrontPower)); Data.ExchangeUpdateOncePowerData(a_Position, FrontPower);
a_Chunk.SetMeta(a_Position, NewMeta); a_Chunk.SetMeta(a_Position, NewMeta);
Data.m_MechanismDelays.erase(a_Position); Data.m_MechanismDelays.erase(a_Position);

View File

@ -87,7 +87,7 @@
namespace RedstoneHandler namespace RedstoneHandler
{ {
unsigned char GetPowerDeliveredToPosition(const cChunk & Chunk, const Vector3i Position, const BLOCKTYPE BlockType, const Vector3i QueryPosition, const BLOCKTYPE QueryBlockType, const bool IsLinked) PowerLevel GetPowerDeliveredToPosition(const cChunk & Chunk, const Vector3i Position, const BLOCKTYPE BlockType, const Vector3i QueryPosition, const BLOCKTYPE QueryBlockType, const bool IsLinked)
{ {
INVOKE_FOR_HANDLERS(GetPowerDeliveredToPosition(Chunk, Position, BlockType, QueryPosition, QueryBlockType, IsLinked)); INVOKE_FOR_HANDLERS(GetPowerDeliveredToPosition(Chunk, Position, BlockType, QueryPosition, QueryBlockType, IsLinked));
@ -99,28 +99,16 @@ namespace RedstoneHandler
return 0; return 0;
} }
void Update(cChunk & Chunk, cChunk & CurrentlyTicking, const Vector3i Position, const BLOCKTYPE BlockType, const NIBBLETYPE Meta, const PowerLevel PowerLevel)
void Update(cChunk & Chunk, cChunk & CurrentlyTicking, const Vector3i Position, const BLOCKTYPE BlockType, const NIBBLETYPE Meta, const PoweringData PoweringData)
{ {
INVOKE_FOR_HANDLERS(Update(Chunk, CurrentlyTicking, Position, BlockType, Meta, PoweringData)); INVOKE_FOR_HANDLERS(Update(Chunk, CurrentlyTicking, Position, BlockType, Meta, PowerLevel));
} }
void ForValidSourcePositions(const cChunk & Chunk, const Vector3i Position, const BLOCKTYPE BlockType, const NIBBLETYPE Meta, ForEachSourceCallback & Callback) void ForValidSourcePositions(const cChunk & Chunk, const Vector3i Position, const BLOCKTYPE BlockType, const NIBBLETYPE Meta, ForEachSourceCallback & Callback)
{ {
INVOKE_FOR_HANDLERS(ForValidSourcePositions(Chunk, Position, BlockType, Meta, Callback)); INVOKE_FOR_HANDLERS(ForValidSourcePositions(Chunk, Position, BlockType, Meta, Callback));
} }
void SetWireState(const cChunk & Chunk, const Vector3i Position) void SetWireState(const cChunk & Chunk, const Vector3i Position)
{ {
RedstoneWireHandler::SetWireState(Chunk, Position); RedstoneWireHandler::SetWireState(Chunk, Position);

View File

@ -8,11 +8,19 @@ class ForEachSourceCallback;
namespace RedstoneHandler namespace RedstoneHandler
{ {
unsigned char GetPowerDeliveredToPosition(const cChunk & Chunk, Vector3i Position, BLOCKTYPE BlockType, Vector3i QueryPosition, BLOCKTYPE QueryBlockType, bool IsLinked); /** Asks a redstone component at the source position how much power it will deliver to the querying position.
If IsLinked is true, QueryPosition should point to the intermediate conduit block.
The Position and QueryPosition are both relative to Chunk. */
PowerLevel GetPowerDeliveredToPosition(const cChunk & Chunk, Vector3i Position, BLOCKTYPE BlockType, Vector3i QueryPosition, BLOCKTYPE QueryBlockType, bool IsLinked);
void Update(cChunk & Chunk, cChunk & CurrentlyTicking, Vector3i Position, BLOCKTYPE BlockType, NIBBLETYPE Meta, PoweringData PoweringData); /** Tells a redstone component at this position to update itself.
PowerLevel represents the maximum power level all of its source positions gave to it.
Position is relative to Chunk, but if the component needs to queue neighbour updates, they are queued to CurrentlyTicking. */
void Update(cChunk & Chunk, cChunk & CurrentlyTicking, Vector3i Position, BLOCKTYPE BlockType, NIBBLETYPE Meta, PowerLevel PowerLevel);
/** Invokes Callback for each position this component can accept power from. */
void ForValidSourcePositions(const cChunk & Chunk, Vector3i Position, BLOCKTYPE BlockType, NIBBLETYPE Meta, ForEachSourceCallback & Callback); void ForValidSourcePositions(const cChunk & Chunk, Vector3i Position, BLOCKTYPE BlockType, NIBBLETYPE Meta, ForEachSourceCallback & Callback);
/** Temporary: compute and set the block state of a redstone wire. */
void SetWireState(const cChunk & Chunk, Vector3i Position); void SetWireState(const cChunk & Chunk, Vector3i Position);
} }

View File

@ -12,16 +12,16 @@ namespace RedstoneLampHandler
return (a_BlockType == E_BLOCK_REDSTONE_LAMP_ON); return (a_BlockType == E_BLOCK_REDSTONE_LAMP_ON);
} }
inline unsigned char GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) inline PowerLevel GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked)
{ {
return 0; return 0;
} }
inline void Update(cChunk & a_Chunk, cChunk &, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) inline void Update(cChunk & a_Chunk, cChunk &, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, const PowerLevel Power)
{ {
// 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);
if (a_PoweringData.PowerLevel > 0) if (Power > 0)
{ {
if (!IsOn(a_BlockType)) if (!IsOn(a_BlockType))
{ {

View File

@ -81,7 +81,7 @@ namespace RedstoneRepeaterHandler
return Rhs.first && DoesLhsLockMe(a_Meta, Rhs.second); return Rhs.first && DoesLhsLockMe(a_Meta, Rhs.second);
} }
inline unsigned char GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) inline PowerLevel GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked)
{ {
if (!IsOn(a_BlockType)) if (!IsOn(a_BlockType))
{ {
@ -98,7 +98,7 @@ namespace RedstoneRepeaterHandler
return 0; return 0;
} }
inline void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) inline void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, const PowerLevel Power)
{ {
// 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);
@ -118,7 +118,7 @@ namespace RedstoneRepeaterHandler
if (DelayInfo == nullptr) if (DelayInfo == nullptr)
{ {
bool ShouldBeOn = (a_PoweringData.PowerLevel != 0); bool ShouldBeOn = (Power != 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);
@ -143,7 +143,7 @@ namespace RedstoneRepeaterHandler
// While sleeping, we ignore any power changes and apply our saved ShouldBeOn when sleep expires // 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 // 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: // FastSetBlock doesn't wake simulators, so manually update ourselves:
Update(a_Chunk, CurrentlyTicking, a_Position, NewType, a_Meta, a_PoweringData); Update(a_Chunk, CurrentlyTicking, a_Position, NewType, a_Meta, Power);
UpdateAdjustedRelative(a_Chunk, CurrentlyTicking, a_Position, cBlockRedstoneRepeaterHandler::GetFrontCoordinateOffset(a_Meta)); UpdateAdjustedRelative(a_Chunk, CurrentlyTicking, a_Position, cBlockRedstoneRepeaterHandler::GetFrontCoordinateOffset(a_Meta));
} }

View File

@ -10,45 +10,7 @@
struct PoweringData using PowerLevel = unsigned char;
{
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);
}
};
@ -68,15 +30,15 @@ public:
return m_ActiveBlocks; return m_ActiveBlocks;
} }
const PoweringData GetCachedPowerData(const Vector3i Position) const PowerLevel GetCachedPowerData(const Vector3i Position) const
{ {
auto Result = m_CachedPowerLevels.find(Position); auto Result = m_CachedPowerLevels.find(Position);
return (Result == m_CachedPowerLevels.end()) ? PoweringData() : Result->second; return (Result == m_CachedPowerLevels.end()) ? 0 : Result->second;
} }
void SetCachedPowerData(const Vector3i Position, PoweringData PoweringData) void SetCachedPowerData(const Vector3i Position, const PowerLevel PowerLevel)
{ {
m_CachedPowerLevels[Position] = PoweringData; m_CachedPowerLevels[Position] = PowerLevel;
} }
std::pair<int, bool> * GetMechanismDelayInfo(const Vector3i Position) std::pair<int, bool> * GetMechanismDelayInfo(const Vector3i Position)
@ -92,18 +54,21 @@ public:
m_MechanismDelays.erase(Position); m_MechanismDelays.erase(Position);
AlwaysTickedPositions.erase(Position); AlwaysTickedPositions.erase(Position);
WireStates.erase(Position); WireStates.erase(Position);
ObserverCache.erase(Position);
} }
PoweringData ExchangeUpdateOncePowerData(const Vector3i & a_Position, PoweringData a_PoweringData) PowerLevel ExchangeUpdateOncePowerData(const Vector3i & a_Position, PowerLevel Power)
{ {
auto Result = m_CachedPowerLevels.find(a_Position); auto Result = m_CachedPowerLevels.find(a_Position);
if (Result == m_CachedPowerLevels.end()) if (Result == m_CachedPowerLevels.end())
{ {
m_CachedPowerLevels[a_Position] = a_PoweringData; m_CachedPowerLevels[a_Position] = Power;
return PoweringData(); return 0;
} }
std::swap(Result->second, a_PoweringData);
return a_PoweringData; std::swap(Result->second, Power);
return Power;
} }
/** Adjust From-relative coordinates into To-relative coordinates. */ /** Adjust From-relative coordinates into To-relative coordinates. */
@ -122,6 +87,9 @@ public:
std::unordered_set<Vector3i, VectorHasher<int>> AlwaysTickedPositions; std::unordered_set<Vector3i, VectorHasher<int>> AlwaysTickedPositions;
/** Structure storing an observer's last seen block. */
std::unordered_map<Vector3i, std::pair<BLOCKTYPE, NIBBLETYPE>, VectorHasher<int>> ObserverCache;
/** 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;
@ -131,8 +99,7 @@ private:
// 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, PoweringData, VectorHasher<int>> m_CachedPowerLevels; std::unordered_map<Vector3i, PowerLevel, VectorHasher<int>> m_CachedPowerLevels;
friend class cRedstoneHandlerFactory; friend class cRedstoneHandlerFactory;
}; };

View File

@ -74,7 +74,7 @@ namespace RedstoneToggleHandler
} }
} }
inline unsigned char GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) inline PowerLevel GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked)
{ {
UNUSED(a_QueryBlockType); UNUSED(a_QueryBlockType);
@ -89,7 +89,7 @@ namespace RedstoneToggleHandler
return GetPowerLevel(a_BlockType, Meta); return GetPowerLevel(a_BlockType, Meta);
} }
inline void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) inline void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, const PowerLevel Power)
{ {
// 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);
} }

View File

@ -29,7 +29,7 @@ namespace RedstoneTorchHandler
} }
} }
inline unsigned char GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) inline PowerLevel GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked)
{ {
const auto QueryOffset = a_QueryPosition - a_Position; const auto QueryOffset = a_QueryPosition - a_Position;
@ -45,7 +45,7 @@ namespace RedstoneTorchHandler
return 15; return 15;
} }
inline void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) inline void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, const PowerLevel Power)
{ {
// 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);
@ -54,7 +54,7 @@ namespace RedstoneTorchHandler
if (DelayInfo == nullptr) if (DelayInfo == nullptr)
{ {
const bool ShouldBeOn = (a_PoweringData.PowerLevel == 0); const bool ShouldBeOn = (Power == 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);

View File

@ -189,7 +189,7 @@ namespace RedstoneWireHandler
DataForChunk(Chunk).WireStates[Position] = Block; DataForChunk(Chunk).WireStates[Position] = Block;
} }
inline unsigned char GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) inline PowerLevel GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked)
{ {
// Starts off as the wire's meta value, modified appropriately and returned // Starts off as the wire's meta value, modified appropriately and returned
auto Power = a_Chunk.GetMeta(a_Position); auto Power = a_Chunk.GetMeta(a_Position);
@ -253,16 +253,16 @@ namespace RedstoneWireHandler
return Power; return Power;
} }
inline void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) inline void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, const PowerLevel Power)
{ {
// 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, Power);
if (a_Meta == a_PoweringData.PowerLevel) if (a_Meta == Power)
{ {
return; return;
} }
a_Chunk.SetMeta(a_Position, a_PoweringData.PowerLevel); a_Chunk.SetMeta(a_Position, Power);
// Notify all positions, sans YP, to update: // Notify all positions, sans YP, to update:
for (const auto Offset : RelativeAdjacents) for (const auto Offset : RelativeAdjacents)

View File

@ -7,7 +7,7 @@
namespace SmallGateHandler namespace SmallGateHandler
{ {
inline unsigned char GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) inline PowerLevel GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked)
{ {
UNUSED(a_Chunk); UNUSED(a_Chunk);
UNUSED(a_Position); UNUSED(a_Position);
@ -18,11 +18,11 @@ namespace SmallGateHandler
return 0; return 0;
} }
inline void Update(cChunk & a_Chunk, cChunk &, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) inline void Update(cChunk & a_Chunk, cChunk &, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, const PowerLevel Power)
{ {
// 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);
const bool ShouldBeOpen = a_PoweringData.PowerLevel != 0; const bool ShouldBeOpen = Power != 0;
const bool IsOpen = (a_Meta & 0x4) == 0x4; const bool IsOpen = (a_Meta & 0x4) == 0x4;
if (ShouldBeOpen != IsOpen) if (ShouldBeOpen != IsOpen)

View File

@ -7,7 +7,7 @@
namespace TNTHandler namespace TNTHandler
{ {
inline unsigned char GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) inline PowerLevel GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked)
{ {
UNUSED(a_Chunk); UNUSED(a_Chunk);
UNUSED(a_Position); UNUSED(a_Position);
@ -18,10 +18,10 @@ namespace TNTHandler
return 0; return 0;
} }
inline void Update(cChunk & a_Chunk, cChunk &, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) inline void Update(cChunk & a_Chunk, cChunk &, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, const PowerLevel Power)
{ {
// 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 (Power != 0)
{ {
a_Chunk.SetBlock(a_Position, E_BLOCK_AIR, 0); a_Chunk.SetBlock(a_Position, E_BLOCK_AIR, 0);
a_Chunk.GetWorld()->SpawnPrimedTNT(Vector3d(0.5, 0.5, 0.5) + cChunkDef::RelativeToAbsolute(a_Position, a_Chunk.GetPos())); // 80 ticks to boom a_Chunk.GetWorld()->SpawnPrimedTNT(Vector3d(0.5, 0.5, 0.5) + cChunkDef::RelativeToAbsolute(a_Position, a_Chunk.GetPos())); // 80 ticks to boom

View File

@ -9,14 +9,14 @@
namespace TrappedChestHandler namespace TrappedChestHandler
{ {
inline unsigned char GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) inline PowerLevel GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked)
{ {
UNUSED(a_BlockType); UNUSED(a_BlockType);
UNUSED(a_QueryPosition); UNUSED(a_QueryPosition);
UNUSED(a_QueryBlockType); UNUSED(a_QueryBlockType);
UNUSED(IsLinked); UNUSED(IsLinked);
return DataForChunk(a_Chunk).GetCachedPowerData(a_Position).PowerLevel; return DataForChunk(a_Chunk).GetCachedPowerData(a_Position);
} }
inline unsigned char GetPowerLevel(cChunk & a_Chunk, Vector3i a_Position) inline unsigned char GetPowerLevel(cChunk & a_Chunk, Vector3i a_Position)
@ -34,14 +34,14 @@ namespace TrappedChestHandler
return static_cast<unsigned char>(std::min(NumberOfPlayers, 15)); return static_cast<unsigned char>(std::min(NumberOfPlayers, 15));
} }
inline void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) inline void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, const PowerLevel Power)
{ {
// 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);
const auto Power = GetPowerLevel(a_Chunk, a_Position); const auto PowerLevel = GetPowerLevel(a_Chunk, a_Position);
const auto PreviousPower = DataForChunk(a_Chunk).ExchangeUpdateOncePowerData(a_Position, PoweringData(a_BlockType, Power)); const auto PreviousPower = DataForChunk(a_Chunk).ExchangeUpdateOncePowerData(a_Position, PowerLevel);
if (Power != PreviousPower.PowerLevel) if (PowerLevel != PreviousPower)
{ {
UpdateAdjustedRelatives(a_Chunk, CurrentlyTicking, a_Position, RelativeAdjacents); UpdateAdjustedRelatives(a_Chunk, CurrentlyTicking, a_Position, RelativeAdjacents);
} }

View File

@ -60,7 +60,7 @@ namespace TripwireHookHandler
return 0; return 0;
} }
inline unsigned char GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) inline PowerLevel GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked)
{ {
UNUSED(a_BlockType); UNUSED(a_BlockType);
UNUSED(a_QueryBlockType); UNUSED(a_QueryBlockType);
@ -69,22 +69,22 @@ namespace TripwireHookHandler
return (GetPowerLevel(a_Chunk, a_Position, a_Chunk.GetMeta(a_Position)) == 15) ? 15 : 0; return (GetPowerLevel(a_Chunk, a_Position, a_Chunk.GetMeta(a_Position)) == 15) ? 15 : 0;
} }
inline void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) inline void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, const PowerLevel Power)
{ {
// 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);
const auto Power = GetPowerLevel(a_Chunk, a_Position, a_Meta); const auto PowerLevel = GetPowerLevel(a_Chunk, a_Position, a_Meta);
NIBBLETYPE Meta; NIBBLETYPE Meta;
if (Power == 0) if (PowerLevel == 0)
{ {
Meta = (a_Meta & 0x3); Meta = (a_Meta & 0x3);
} }
else if (Power == 1) else if (PowerLevel == 1)
{ {
// Connected but not activated, AND away the highest bit // Connected but not activated, AND away the highest bit
Meta = (a_Meta & 0x7) | 0x4; Meta = (a_Meta & 0x7) | 0x4;
} }
else if (Power == 15) else if (PowerLevel == 15)
{ {
// Connected and activated, set the 3rd and 4th highest bits // Connected and activated, set the 3rd and 4th highest bits
Meta = (a_Meta | 0xC); Meta = (a_Meta | 0xC);