Implement redstone quasi-connectivity (#4889)
This commit is contained in:
parent
23bca00831
commit
6183b28f93
@ -65,6 +65,11 @@ namespace DropSpenserHandler
|
|||||||
UNUSED(a_Chunk);
|
UNUSED(a_Chunk);
|
||||||
UNUSED(a_BlockType);
|
UNUSED(a_BlockType);
|
||||||
UNUSED(a_Meta);
|
UNUSED(a_Meta);
|
||||||
|
|
||||||
|
// Consider indirect power:
|
||||||
|
Callback.CheckIndirectPower();
|
||||||
|
|
||||||
|
// Consider normal adjacents:
|
||||||
InvokeForAdjustedRelatives(Callback, a_Position, RelativeAdjacents);
|
InvokeForAdjustedRelatives(Callback, a_Position, RelativeAdjacents);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -23,25 +23,6 @@ ForEachSourceCallback::ForEachSourceCallback(const cChunk & Chunk, const Vector3
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool ForEachSourceCallback::ShouldQueryLinkedPosition(const Vector3i Location, const BLOCKTYPE 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_OBSERVER:
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void ForEachSourceCallback::operator()(Vector3i Location)
|
void ForEachSourceCallback::operator()(Vector3i Location)
|
||||||
{
|
{
|
||||||
if (!cChunk::IsValidHeight(Location.y))
|
if (!cChunk::IsValidHeight(Location.y))
|
||||||
@ -58,7 +39,7 @@ void ForEachSourceCallback::operator()(Vector3i Location)
|
|||||||
const auto PotentialSourceBlock = NeighbourChunk->GetBlock(Location);
|
const auto PotentialSourceBlock = NeighbourChunk->GetBlock(Location);
|
||||||
const auto NeighbourRelativeQueryPosition = cIncrementalRedstoneSimulatorChunkData::RebaseRelativePosition(m_Chunk, *NeighbourChunk, m_Position);
|
const auto NeighbourRelativeQueryPosition = cIncrementalRedstoneSimulatorChunkData::RebaseRelativePosition(m_Chunk, *NeighbourChunk, m_Position);
|
||||||
|
|
||||||
if (ShouldQueryLinkedPosition(Location, PotentialSourceBlock))
|
if (ShouldQueryLinkedPosition(PotentialSourceBlock))
|
||||||
{
|
{
|
||||||
Power = std::max(Power, QueryLinkedPower(*NeighbourChunk, NeighbourRelativeQueryPosition, m_CurrentBlock, Location));
|
Power = std::max(Power, QueryLinkedPower(*NeighbourChunk, NeighbourRelativeQueryPosition, m_CurrentBlock, Location));
|
||||||
}
|
}
|
||||||
@ -78,6 +59,58 @@ void ForEachSourceCallback::operator()(Vector3i Location)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void ForEachSourceCallback::CheckIndirectPower()
|
||||||
|
{
|
||||||
|
const Vector3i OffsetYP(0, 1, 0);
|
||||||
|
const auto Above = m_Position + OffsetYP;
|
||||||
|
|
||||||
|
if (Above.y == cChunkDef::Height)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Object representing restarted power calculation where the
|
||||||
|
// block above this piston, dropspenser is requesting a power level.
|
||||||
|
ForEachSourceCallback QuasiQueryCallback(m_Chunk, Above, m_Chunk.GetBlock(Above));
|
||||||
|
|
||||||
|
// Manually feed the callback object all positions that may deliver power to Above:
|
||||||
|
for (const auto QuasiPowerOffset : cSimulator::GetLinkedOffsets(OffsetYP))
|
||||||
|
{
|
||||||
|
QuasiQueryCallback(m_Position + QuasiPowerOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the results:
|
||||||
|
Power = std::max(Power, QuasiQueryCallback.Power);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool ForEachSourceCallback::ShouldQueryLinkedPosition(const BLOCKTYPE 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_OBSERVER:
|
||||||
|
case E_BLOCK_TRAPPED_CHEST: return false;
|
||||||
|
|
||||||
|
// Pistons are solid but don't participate in link powering:
|
||||||
|
case E_BLOCK_PISTON:
|
||||||
|
case E_BLOCK_PISTON_EXTENSION:
|
||||||
|
case E_BLOCK_STICKY_PISTON: return false;
|
||||||
|
|
||||||
|
// If a mechanism asks for power from a block, redirect the query to linked positions if:
|
||||||
|
default: return cBlockInfo::IsSolid(Block);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
PowerLevel ForEachSourceCallback::QueryLinkedPower(const cChunk & Chunk, const Vector3i QueryPosition, const BLOCKTYPE QueryBlock, const Vector3i SolidBlockPosition)
|
PowerLevel ForEachSourceCallback::QueryLinkedPower(const cChunk & Chunk, const Vector3i QueryPosition, const BLOCKTYPE QueryBlock, const Vector3i SolidBlockPosition)
|
||||||
{
|
{
|
||||||
PowerLevel Power = 0;
|
PowerLevel Power = 0;
|
||||||
|
@ -13,20 +13,24 @@ public:
|
|||||||
|
|
||||||
ForEachSourceCallback(const cChunk & Chunk, Vector3i Position, BLOCKTYPE CurrentBlock);
|
ForEachSourceCallback(const cChunk & Chunk, Vector3i Position, BLOCKTYPE CurrentBlock);
|
||||||
|
|
||||||
/** Returns whether a potential source position should be treated as linked. */
|
|
||||||
bool ShouldQueryLinkedPosition(Vector3i Location, BLOCKTYPE Block);
|
|
||||||
|
|
||||||
/** 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);
|
||||||
|
|
||||||
|
/** Callback invoked for blocks supporting quasiconnectivity. */
|
||||||
|
void CheckIndirectPower();
|
||||||
|
|
||||||
|
// The maximum power level of all source locations.
|
||||||
|
PowerLevel Power;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
/** Returns whether a potential source position that's occupied by Block should be treated as linked. */
|
||||||
|
static bool ShouldQueryLinkedPosition(BLOCKTYPE Block);
|
||||||
|
|
||||||
/** Asks redstone handlers adjacent to a solid block how much power they will deliver to the querying position, via the solid block.
|
/** Asks redstone handlers adjacent to a solid block how much power they will deliver to the querying position, via the solid block.
|
||||||
Both QueryPosition and SolidBlockPosition are relative to Chunk. */
|
Both QueryPosition and SolidBlockPosition are relative to Chunk. */
|
||||||
static PowerLevel QueryLinkedPower(const cChunk & Chunk, Vector3i QueryPosition, BLOCKTYPE QueryBlock, Vector3i SolidBlockPosition);
|
static PowerLevel QueryLinkedPower(const cChunk & Chunk, Vector3i QueryPosition, BLOCKTYPE QueryBlock, Vector3i SolidBlockPosition);
|
||||||
|
|
||||||
PowerLevel Power;
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
const cChunk & m_Chunk;
|
const cChunk & m_Chunk;
|
||||||
const Vector3i m_Position;
|
const Vector3i m_Position;
|
||||||
const BLOCKTYPE m_CurrentBlock;
|
const BLOCKTYPE m_CurrentBlock;
|
||||||
|
@ -60,5 +60,8 @@ namespace PistonHandler
|
|||||||
Callback(a_Position + Offset);
|
Callback(a_Position + Offset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Consider indirect power:
|
||||||
|
Callback.CheckIndirectPower();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -88,11 +88,14 @@ namespace RedstoneWireHandler
|
|||||||
return a_Offset.z != 0;
|
return a_Offset.z != 0;
|
||||||
}
|
}
|
||||||
case E_BLOCK_ACTIVE_COMPARATOR:
|
case E_BLOCK_ACTIVE_COMPARATOR:
|
||||||
case E_BLOCK_INACTIVE_COMPARATOR:
|
|
||||||
case E_BLOCK_BLOCK_OF_REDSTONE:
|
case E_BLOCK_BLOCK_OF_REDSTONE:
|
||||||
|
case E_BLOCK_INACTIVE_COMPARATOR:
|
||||||
|
case E_BLOCK_LEVER:
|
||||||
case E_BLOCK_REDSTONE_TORCH_OFF:
|
case E_BLOCK_REDSTONE_TORCH_OFF:
|
||||||
case E_BLOCK_REDSTONE_TORCH_ON:
|
case E_BLOCK_REDSTONE_TORCH_ON:
|
||||||
case E_BLOCK_REDSTONE_WIRE: return true;
|
case E_BLOCK_REDSTONE_WIRE:
|
||||||
|
case E_BLOCK_STONE_BUTTON:
|
||||||
|
case E_BLOCK_WOODEN_BUTTON: return true;
|
||||||
default: return false;
|
default: return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user