Remove the redstone solid block handler
- Remove cSolidBlockHandler * Functionality now integrated into simulator dispatcher * Fix door double open/close issues, arisen due to the top/bottom halves getting different power + Small migration to block states for redstone wire
This commit is contained in:
parent
2f79ab2e26
commit
40eba5244d
@ -58,10 +58,7 @@ void cBlockEntityWithItems::OnSlotChanged(cItemGrid * a_Grid, int a_SlotNum)
|
||||
auto & Simulator = *m_World->GetRedstoneSimulator();
|
||||
|
||||
// Notify comparators:
|
||||
m_World->WakeUpSimulators(m_Pos + Vector3i(1, 0, 0));
|
||||
m_World->WakeUpSimulators(m_Pos + Vector3i(-1, 0, 0));
|
||||
m_World->WakeUpSimulators(m_Pos + Vector3i(0, 0, 1));
|
||||
m_World->WakeUpSimulators(m_Pos + Vector3i(0, 0, -1));
|
||||
m_World->WakeUpSimulators(m_Pos);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
@ -248,10 +248,7 @@ void cChestEntity::OnSlotChanged(cItemGrid * a_Grid, int a_SlotNum)
|
||||
auto & Simulator = *m_World->GetRedstoneSimulator();
|
||||
|
||||
// Notify comparators:
|
||||
m_World->WakeUpSimulators(m_Pos + Vector3i(1, 0, 0));
|
||||
m_World->WakeUpSimulators(m_Pos + Vector3i(-1, 0, 0));
|
||||
m_World->WakeUpSimulators(m_Pos + Vector3i(0, 0, 1));
|
||||
m_World->WakeUpSimulators(m_Pos + Vector3i(0, 0, -1));
|
||||
m_World->WakeUpSimulators(m_Pos);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
@ -48,7 +48,7 @@ public:
|
||||
const auto SoundToPlay = (m_BlockType == E_BLOCK_STONE_BUTTON) ? "block.stone_button.click_on" : "block.wood_button.click_on";
|
||||
|
||||
a_ChunkInterface.SetBlockMeta(a_BlockPos, Meta, false);
|
||||
WakeUpSimulators(a_WorldInterface, a_BlockPos);
|
||||
a_WorldInterface.WakeUpSimulators(a_BlockPos);
|
||||
a_WorldInterface.GetBroadcastManager().BroadcastSoundEffect(SoundToPlay, a_BlockPos, 0.5f, 0.6f, a_Player.GetClientHandle());
|
||||
|
||||
// Queue a button reset (unpress)
|
||||
@ -186,7 +186,7 @@ public:
|
||||
}
|
||||
|
||||
a_World.SetBlockMeta(Pos, Meta | 0x08, false);
|
||||
WakeUpSimulators(a_World, Pos);
|
||||
a_World.WakeUpSimulators(Pos);
|
||||
|
||||
// sound name is ok to be wood, because only wood gets triggered by arrow
|
||||
a_World.GetBroadcastManager().BroadcastSoundEffect("block.wood_button.click_on", Pos, 0.5f, 0.6f);
|
||||
@ -195,27 +195,6 @@ public:
|
||||
QueueButtonRelease(a_World, Pos, Type);
|
||||
}
|
||||
|
||||
/** Notify, mainly the redstone simulator, that this toggle component has updated. */
|
||||
template <class WorldType>
|
||||
static void WakeUpSimulators(WorldType & a_World, const Vector3i a_Position)
|
||||
{
|
||||
// Contains our direct adjacents
|
||||
static const Vector3i Offsets[] =
|
||||
{
|
||||
{ 1, 0, 0 },
|
||||
{ -1, 0, 0 },
|
||||
{ 0, 1, 0 },
|
||||
{ 0, -1, 0 },
|
||||
{ 0, 0, 1 },
|
||||
{ 0, 0, -1 }
|
||||
};
|
||||
|
||||
for (const auto & Offset : Offsets)
|
||||
{
|
||||
a_World.WakeUpSimulators(a_Position + Offset);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
/** Schedules a recurring event at appropriate intervals to release a button at a given position.
|
||||
@ -250,7 +229,7 @@ private:
|
||||
const auto SoundToPlayOnRelease = (Type == E_BLOCK_STONE_BUTTON) ? "block.stone_button.click_off" : "block.wood_button.click_off";
|
||||
|
||||
a_World.SetBlockMeta(a_Position, Meta & 0x07, false);
|
||||
WakeUpSimulators(a_World, a_Position);
|
||||
a_World.WakeUpSimulators(a_Position);
|
||||
a_World.BroadcastSoundEffect(SoundToPlayOnRelease, a_Position, 0.5f, 0.5f);
|
||||
}
|
||||
);
|
||||
|
@ -3,7 +3,6 @@
|
||||
#include "BlockHandler.h"
|
||||
#include "../Chunk.h"
|
||||
#include "Mixins.h"
|
||||
#include "BlockButton.h"
|
||||
#include "BlockSlab.h"
|
||||
|
||||
|
||||
@ -36,7 +35,7 @@ public:
|
||||
NIBBLETYPE Meta = (a_ChunkInterface.GetBlockMeta(a_BlockPos) ^ 0x08);
|
||||
|
||||
a_ChunkInterface.SetBlockMeta(a_BlockPos, Meta);
|
||||
cBlockButtonHandler::WakeUpSimulators(a_WorldInterface, a_BlockPos);
|
||||
a_WorldInterface.WakeUpSimulators(a_BlockPos);
|
||||
a_WorldInterface.GetBroadcastManager().BroadcastSoundEffect("block.lever.click", a_BlockPos, 0.5f, (Meta & 0x08) ? 0.6f : 0.5f);
|
||||
return true;
|
||||
}
|
||||
|
@ -1,16 +1,17 @@
|
||||
target_sources(
|
||||
${CMAKE_PROJECT_NAME} PRIVATE
|
||||
|
||||
ForEachSourceCallback.cpp
|
||||
IncrementalRedstoneSimulator.cpp
|
||||
|
||||
CommandBlockHandler.h
|
||||
DoorHandler.h
|
||||
DropSpenserHandler.h
|
||||
ForEachSourceCallback.h
|
||||
HopperHandler.h
|
||||
IncrementalRedstoneSimulator.h
|
||||
RedstoneHandler.h
|
||||
RedstoneSimulatorChunkData.h
|
||||
SolidBlockHandler.h
|
||||
RedstoneComparatorHandler.h
|
||||
RedstoneRepeaterHandler.h
|
||||
RedstoneBlockHandler.h
|
||||
|
@ -10,16 +10,14 @@
|
||||
|
||||
class cCommandBlockHandler final : public cRedstoneHandler
|
||||
{
|
||||
public:
|
||||
|
||||
virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
|
||||
virtual unsigned char GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) const override
|
||||
{
|
||||
UNUSED(a_Chunk);
|
||||
UNUSED(a_Position);
|
||||
UNUSED(a_BlockType);
|
||||
UNUSED(a_Meta);
|
||||
UNUSED(a_QueryPosition);
|
||||
UNUSED(a_QueryBlockType);
|
||||
UNUSED(IsLinked);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -41,7 +39,7 @@ public:
|
||||
});
|
||||
}
|
||||
|
||||
virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
|
||||
virtual void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
|
||||
{
|
||||
UNUSED(a_Chunk);
|
||||
UNUSED(a_BlockType);
|
||||
|
@ -10,16 +10,16 @@
|
||||
|
||||
class cDoorHandler final : public cRedstoneHandler
|
||||
{
|
||||
public:
|
||||
// "Doormammu, I've come to bargain"
|
||||
|
||||
virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
|
||||
virtual unsigned char GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) const override
|
||||
{
|
||||
UNUSED(a_Chunk);
|
||||
UNUSED(a_Position);
|
||||
UNUSED(a_BlockType);
|
||||
UNUSED(a_Meta);
|
||||
UNUSED(a_QueryPosition);
|
||||
UNUSED(a_QueryBlockType);
|
||||
UNUSED(IsLinked);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -27,6 +27,19 @@ public:
|
||||
{
|
||||
// LOGD("Evaluating dori the door (%d %d %d)", a_Position.x, a_Position.y, a_Position.z);
|
||||
|
||||
if ((a_Meta & 0x8) == 0x8)
|
||||
{
|
||||
// We're treating the bottom half as the source of truth, so ignore updates to the top:
|
||||
return;
|
||||
}
|
||||
|
||||
const auto TopPosition = a_Position + OffsetYP;
|
||||
ForEachSourceCallback Callback(a_Chunk, TopPosition, a_BlockType);
|
||||
ForValidSourcePositions(a_Chunk, TopPosition, a_BlockType, a_Meta, Callback);
|
||||
|
||||
// Factor in what the upper half is getting:
|
||||
a_PoweringData = std::max(a_PoweringData, Callback.Power);
|
||||
|
||||
cChunkInterface ChunkInterface(a_Chunk.GetWorld()->GetChunkMap());
|
||||
const bool ShouldBeOpen = a_PoweringData.PowerLevel != 0;
|
||||
const auto AbsolutePosition = cChunkDef::RelativeToAbsolute(a_Position, a_Chunk.GetPos());
|
||||
@ -39,7 +52,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
|
||||
virtual void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
|
||||
{
|
||||
UNUSED(a_Chunk);
|
||||
UNUSED(a_BlockType);
|
||||
|
@ -10,8 +10,6 @@
|
||||
|
||||
class cDropSpenserHandler final : public cRedstoneHandler
|
||||
{
|
||||
public:
|
||||
|
||||
inline static bool IsActivated(NIBBLETYPE a_Meta)
|
||||
{
|
||||
return (a_Meta & E_META_DROPSPENSER_ACTIVATED) != 0;
|
||||
@ -29,14 +27,14 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
|
||||
virtual unsigned char GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) const override
|
||||
{
|
||||
UNUSED(a_Chunk);
|
||||
UNUSED(a_Position);
|
||||
UNUSED(a_BlockType);
|
||||
UNUSED(a_Meta);
|
||||
UNUSED(a_QueryPosition);
|
||||
UNUSED(a_QueryBlockType);
|
||||
UNUSED(IsLinked);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -63,7 +61,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
|
||||
virtual void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
|
||||
{
|
||||
UNUSED(a_Chunk);
|
||||
UNUSED(a_BlockType);
|
||||
|
@ -0,0 +1,113 @@
|
||||
|
||||
#include "Globals.h"
|
||||
|
||||
#include "ForEachSourceCallback.h"
|
||||
#include "IncrementalRedstoneSimulator.h"
|
||||
#include "../../BlockInfo.h"
|
||||
#include "../../Chunk.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
ForEachSourceCallback::ForEachSourceCallback(const cChunk & Chunk, const Vector3i Position, const BLOCKTYPE CurrentBlock) :
|
||||
m_Chunk(Chunk),
|
||||
m_Position(Position),
|
||||
m_CurrentBlock(CurrentBlock)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool ForEachSourceCallback::ShouldQueryLinkedPosition(const Vector3i Location, const BLOCKTYPE Block)
|
||||
{
|
||||
switch (Block)
|
||||
{
|
||||
case E_BLOCK_BLOCK_OF_REDSTONE:
|
||||
case E_BLOCK_TRAPPED_CHEST: return false;
|
||||
default: return cBlockInfo::IsSolid(Block);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void ForEachSourceCallback::operator()(Vector3i Location)
|
||||
{
|
||||
if (!cChunk::IsValidHeight(Location.y))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const auto NeighbourChunk = m_Chunk.GetRelNeighborChunkAdjustCoords(Location);
|
||||
if ((NeighbourChunk == nullptr) || !NeighbourChunk->IsValid())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const auto PotentialSourceBlock = NeighbourChunk->GetBlock(Location);
|
||||
const auto NeighbourRelativeQueryPosition = cIncrementalRedstoneSimulatorChunkData::RebaseRelativePosition(m_Chunk, *NeighbourChunk, m_Position);
|
||||
|
||||
if (ShouldQueryLinkedPosition(Location, PotentialSourceBlock))
|
||||
{
|
||||
Power = std::max(Power, QueryLinkedPower(*NeighbourChunk, NeighbourRelativeQueryPosition, m_CurrentBlock, Location));
|
||||
}
|
||||
else
|
||||
{
|
||||
Power = std::max(Power, QueryPower(*NeighbourChunk, Location, PotentialSourceBlock, NeighbourRelativeQueryPosition, m_CurrentBlock, false));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
PoweringData ForEachSourceCallback::QueryPower(const cChunk & Chunk, const Vector3i SourcePosition, const BLOCKTYPE SourceBlock, const Vector3i QueryPosition, const BLOCKTYPE QueryBlock, const bool IsLinked)
|
||||
{
|
||||
const auto PotentialSourceHandler = cIncrementalRedstoneSimulator::GetComponentHandler(SourceBlock);
|
||||
if (PotentialSourceHandler == nullptr)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
return
|
||||
{
|
||||
SourceBlock,
|
||||
PotentialSourceHandler->GetPowerDeliveredToPosition(
|
||||
Chunk, SourcePosition, SourceBlock,
|
||||
QueryPosition, QueryBlock, IsLinked
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
PoweringData ForEachSourceCallback::QueryLinkedPower(const cChunk & Chunk, const Vector3i QueryPosition, const BLOCKTYPE QueryBlock, const Vector3i SolidBlockPosition)
|
||||
{
|
||||
PoweringData Power;
|
||||
|
||||
for (const auto Offset : cSimulator::GetLinkedOffsets(SolidBlockPosition - QueryPosition))
|
||||
{
|
||||
auto SourcePosition = QueryPosition + Offset;
|
||||
if (!cChunk::IsValidHeight(SourcePosition.y))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto NeighbourChunk = Chunk.GetRelNeighborChunkAdjustCoords(SourcePosition);
|
||||
if ((NeighbourChunk == nullptr) || !NeighbourChunk->IsValid())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto NeighbourRelativeSolidBlockPosition = cIncrementalRedstoneSimulatorChunkData::RebaseRelativePosition(Chunk, *NeighbourChunk, SolidBlockPosition);
|
||||
Power = std::max(Power, QueryPower(*NeighbourChunk, SourcePosition, NeighbourChunk->GetBlock(SourcePosition), NeighbourRelativeSolidBlockPosition, QueryBlock, true));
|
||||
}
|
||||
|
||||
return Power;
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ForEachSourceCallback.h"
|
||||
#include "RedstoneSimulatorChunkData.h"
|
||||
|
||||
class ForEachSourceCallback
|
||||
{
|
||||
public:
|
||||
|
||||
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. */
|
||||
void operator()(Vector3i Location);
|
||||
|
||||
/** Asks a redstone component at the source position how much power it will deliver to the querying position. */
|
||||
static PoweringData QueryPower(const cChunk & Chunk, Vector3i SourcePosition, BLOCKTYPE SourceBlock, Vector3i QueryPosition, BLOCKTYPE QueryBlock, bool IsLinked);
|
||||
|
||||
/** Asks redstone handlers adjacent to a solid block how much power they will deliver to the querying position, via the solid block. */
|
||||
static PoweringData QueryLinkedPower(const cChunk & Chunk, Vector3i QueryPosition, BLOCKTYPE QueryBlock, Vector3i SolidBlockPosition);
|
||||
|
||||
PoweringData Power;
|
||||
|
||||
private:
|
||||
|
||||
const cChunk & m_Chunk;
|
||||
const Vector3i m_Position;
|
||||
const BLOCKTYPE m_CurrentBlock;
|
||||
};
|
@ -10,16 +10,14 @@
|
||||
|
||||
class cHopperHandler final : public cRedstoneHandler
|
||||
{
|
||||
public:
|
||||
|
||||
virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
|
||||
virtual unsigned char GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) const override
|
||||
{
|
||||
UNUSED(a_Chunk);
|
||||
UNUSED(a_Position);
|
||||
UNUSED(a_BlockType);
|
||||
UNUSED(a_Meta);
|
||||
UNUSED(a_QueryPosition);
|
||||
UNUSED(a_QueryBlockType);
|
||||
UNUSED(IsLinked);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -40,7 +38,7 @@ public:
|
||||
});
|
||||
}
|
||||
|
||||
virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
|
||||
virtual void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
|
||||
{
|
||||
UNUSED(a_Chunk);
|
||||
UNUSED(a_BlockType);
|
||||
|
@ -1,9 +1,8 @@
|
||||
|
||||
|
||||
#include "Globals.h"
|
||||
|
||||
#include "IncrementalRedstoneSimulator.h"
|
||||
#include "../../Chunk.h"
|
||||
#include "ForEachSourceCallback.h"
|
||||
|
||||
#include "CommandBlockHandler.h"
|
||||
#include "DoorHandler.h"
|
||||
@ -11,7 +10,6 @@
|
||||
#include "RedstoneWireHandler.h"
|
||||
#include "RedstoneRepeaterHandler.h"
|
||||
#include "RedstoneToggleHandler.h"
|
||||
#include "SolidBlockHandler.h"
|
||||
#include "RedstoneLampHandler.h"
|
||||
#include "RedstoneBlockHandler.h"
|
||||
#include "PistonHandler.h"
|
||||
@ -115,10 +113,6 @@ std::unique_ptr<cRedstoneHandler> cIncrementalRedstoneSimulator::CreateComponent
|
||||
return std::make_unique<cDoorHandler>();
|
||||
}
|
||||
|
||||
if (cBlockInfo::FullyOccupiesVoxel(a_BlockType))
|
||||
{
|
||||
return std::make_unique<cSolidBlockHandler>();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
@ -182,42 +176,11 @@ void cIncrementalRedstoneSimulator::ProcessWorkItem(cChunk & Chunk, cChunk & Tic
|
||||
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);
|
||||
});
|
||||
ForEachSourceCallback Callback(Chunk, Position, CurrentBlock);
|
||||
CurrentHandler->ForValidSourcePositions(Chunk, Position, CurrentBlock, CurrentMeta, Callback);
|
||||
|
||||
// Inform the handler to update
|
||||
CurrentHandler->Update(Chunk, TickingSource, Position, CurrentBlock, CurrentMeta, Power);
|
||||
CurrentHandler->Update(Chunk, TickingSource, Position, CurrentBlock, CurrentMeta, Callback.Power);
|
||||
}
|
||||
|
||||
|
||||
@ -241,6 +204,12 @@ void cIncrementalRedstoneSimulator::AddBlock(cChunk & a_Chunk, Vector3i a_Positi
|
||||
ChunkData.AlwaysTickedPositions.emplace(a_Position);
|
||||
}
|
||||
|
||||
// Temporary: in the absence of block state support calculate our own:
|
||||
if (a_Block == E_BLOCK_REDSTONE_WIRE)
|
||||
{
|
||||
static_cast<const cRedstoneWireHandler *>(GetComponentHandler(a_Block))->SetWireState(a_Chunk, a_Position);
|
||||
}
|
||||
|
||||
// Always update redstone devices:
|
||||
ChunkData.WakeUp(a_Position);
|
||||
}
|
||||
@ -273,5 +242,21 @@ void cIncrementalRedstoneSimulator::WakeUp(cChunk & a_Chunk, Vector3i a_Position
|
||||
// The only thing to do go one block farther than this cross-coord, in the direction of Offset
|
||||
// in order to notify linked-powered positions that there was a change
|
||||
|
||||
// TODO: use a_Offset, exclude a_Position and a_Position - a_Offset
|
||||
for (const auto Offset : cSimulator::GetLinkedOffsets(a_Offset))
|
||||
{
|
||||
auto Relative = a_Position - a_Offset + Offset;
|
||||
if (!cChunkDef::IsValidHeight(Relative.y))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
auto Chunk = a_Chunk.GetRelNeighborChunkAdjustCoords(Relative);
|
||||
if ((Chunk == nullptr) || !Chunk->IsValid())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto Block = Chunk->GetBlock(Relative);
|
||||
AddBlock(*Chunk, Relative, Block);
|
||||
}
|
||||
}
|
||||
|
@ -16,58 +16,11 @@ class cIncrementalRedstoneSimulator final :
|
||||
|
||||
public:
|
||||
|
||||
cIncrementalRedstoneSimulator(cWorld & a_World) :
|
||||
Super(a_World)
|
||||
{
|
||||
}
|
||||
using Super::cRedstoneSimulator;
|
||||
|
||||
static const cRedstoneHandler * GetComponentHandler(BLOCKTYPE a_BlockType);
|
||||
|
||||
/** 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 */
|
||||
inline static bool IsMechanism(BLOCKTYPE Block)
|
||||
{
|
||||
switch (Block)
|
||||
{
|
||||
case E_BLOCK_ACACIA_DOOR:
|
||||
case E_BLOCK_ACACIA_FENCE_GATE:
|
||||
case E_BLOCK_ACTIVATOR_RAIL:
|
||||
case E_BLOCK_ACTIVE_COMPARATOR:
|
||||
case E_BLOCK_BIRCH_DOOR:
|
||||
case E_BLOCK_BIRCH_FENCE_GATE:
|
||||
case E_BLOCK_COMMAND_BLOCK:
|
||||
case E_BLOCK_DARK_OAK_DOOR:
|
||||
case E_BLOCK_DARK_OAK_FENCE_GATE:
|
||||
case E_BLOCK_DISPENSER:
|
||||
case E_BLOCK_DROPPER:
|
||||
case E_BLOCK_FENCE_GATE:
|
||||
case E_BLOCK_HOPPER:
|
||||
case E_BLOCK_INACTIVE_COMPARATOR:
|
||||
case E_BLOCK_IRON_DOOR:
|
||||
case E_BLOCK_IRON_TRAPDOOR:
|
||||
case E_BLOCK_JUNGLE_DOOR:
|
||||
case E_BLOCK_JUNGLE_FENCE_GATE:
|
||||
case E_BLOCK_NOTE_BLOCK:
|
||||
case E_BLOCK_OBSERVER:
|
||||
case E_BLOCK_PISTON:
|
||||
case E_BLOCK_POWERED_RAIL:
|
||||
case E_BLOCK_REDSTONE_LAMP_OFF:
|
||||
case E_BLOCK_REDSTONE_LAMP_ON:
|
||||
case E_BLOCK_REDSTONE_REPEATER_OFF:
|
||||
case E_BLOCK_REDSTONE_REPEATER_ON:
|
||||
case E_BLOCK_REDSTONE_WIRE:
|
||||
case E_BLOCK_SPRUCE_DOOR:
|
||||
case E_BLOCK_SPRUCE_FENCE_GATE:
|
||||
case E_BLOCK_STICKY_PISTON:
|
||||
case E_BLOCK_TNT:
|
||||
case E_BLOCK_TRAPDOOR:
|
||||
case E_BLOCK_WOODEN_DOOR:
|
||||
{
|
||||
return true;
|
||||
}
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
private:
|
||||
|
||||
/** Returns if a redstone device is always ticked due to influence by its environment */
|
||||
inline static bool IsAlwaysTicked(BLOCKTYPE a_Block)
|
||||
@ -133,7 +86,6 @@ public:
|
||||
case E_BLOCK_TRAPDOOR:
|
||||
case E_BLOCK_TRAPPED_CHEST:
|
||||
case E_BLOCK_TRIPWIRE_HOOK:
|
||||
case E_BLOCK_TRIPWIRE:
|
||||
case E_BLOCK_WOODEN_BUTTON:
|
||||
case E_BLOCK_WOODEN_DOOR:
|
||||
case E_BLOCK_WOODEN_PRESSURE_PLATE:
|
||||
@ -145,8 +97,6 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
virtual void Simulate(float Dt) override {};
|
||||
virtual void SimulateChunk(std::chrono::milliseconds Dt, int ChunkX, int ChunkZ, cChunk * Chunk) override;
|
||||
|
||||
|
@ -10,16 +10,14 @@
|
||||
|
||||
class cNoteBlockHandler: public cRedstoneHandler
|
||||
{
|
||||
public:
|
||||
|
||||
virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
|
||||
virtual unsigned char GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) const override
|
||||
{
|
||||
UNUSED(a_Chunk);
|
||||
UNUSED(a_Position);
|
||||
UNUSED(a_BlockType);
|
||||
UNUSED(a_Meta);
|
||||
UNUSED(a_QueryPosition);
|
||||
UNUSED(a_QueryBlockType);
|
||||
UNUSED(IsLinked);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -41,7 +39,7 @@ public:
|
||||
});
|
||||
}
|
||||
|
||||
virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
|
||||
virtual void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
|
||||
{
|
||||
UNUSED(a_Chunk);
|
||||
UNUSED(a_BlockType);
|
||||
|
@ -10,8 +10,6 @@
|
||||
|
||||
class cObserverHandler final : public cRedstoneHandler
|
||||
{
|
||||
public:
|
||||
|
||||
inline static bool IsOn(NIBBLETYPE a_Meta)
|
||||
{
|
||||
return (a_Meta & 0x8) == 0x8;
|
||||
@ -34,14 +32,10 @@ public:
|
||||
return (Previous.PoweringBlock != Observed.PoweringBlock) || (Previous.PowerLevel != Observed.PowerLevel);
|
||||
}
|
||||
|
||||
virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
|
||||
virtual unsigned char GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) const override
|
||||
{
|
||||
if (IsOn(a_Meta) && (a_QueryPosition == (a_Position + cBlockObserverHandler::GetSignalOutputOffset(a_Meta))))
|
||||
{
|
||||
return 15;
|
||||
}
|
||||
|
||||
return 0;
|
||||
const auto Meta = a_Chunk.GetMeta(a_Position);
|
||||
return (IsOn(Meta) && (a_QueryPosition == (a_Position + cBlockObserverHandler::GetSignalOutputOffset(Meta)))) ? 15 : 0;
|
||||
}
|
||||
|
||||
virtual void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override
|
||||
@ -87,10 +81,10 @@ public:
|
||||
a_Chunk.SetMeta(a_Position, a_Meta & ~0x8);
|
||||
}
|
||||
|
||||
UpdateAdjustedRelative(a_Chunk, CurrentlyTicking, a_Position + cBlockObserverHandler::GetSignalOutputOffset(a_Meta));
|
||||
UpdateAdjustedRelative(a_Chunk, CurrentlyTicking, a_Position, cBlockObserverHandler::GetSignalOutputOffset(a_Meta));
|
||||
}
|
||||
|
||||
virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
|
||||
virtual void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
|
||||
{
|
||||
UNUSED(a_Chunk);
|
||||
UNUSED(a_Position);
|
||||
|
@ -10,16 +10,14 @@
|
||||
|
||||
class cPistonHandler final: public cRedstoneHandler
|
||||
{
|
||||
public:
|
||||
|
||||
virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
|
||||
virtual unsigned char GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) const override
|
||||
{
|
||||
UNUSED(a_Chunk);
|
||||
UNUSED(a_Position);
|
||||
UNUSED(a_BlockType);
|
||||
UNUSED(a_Meta);
|
||||
UNUSED(a_QueryPosition);
|
||||
UNUSED(a_QueryBlockType);
|
||||
UNUSED(IsLinked);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -48,7 +46,7 @@ public:
|
||||
// However, this delay is already present: as a side effect of the implementation of piston animation in Blocks\BlockPiston.cpp
|
||||
}
|
||||
|
||||
virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
|
||||
virtual void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
|
||||
{
|
||||
UNUSED(a_Chunk);
|
||||
UNUSED(a_BlockType);
|
||||
|
@ -9,8 +9,6 @@
|
||||
|
||||
class cPoweredRailHandler final : public cRedstoneHandler
|
||||
{
|
||||
public:
|
||||
|
||||
static Vector3i GetPoweredRailAdjacentXZCoordinateOffset(NIBBLETYPE a_Meta) // Not in cBlockRailHandler since specific to powered rails
|
||||
{
|
||||
switch (a_Meta & 0x7)
|
||||
@ -29,11 +27,12 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
|
||||
virtual unsigned char GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) const override
|
||||
{
|
||||
UNUSED(a_QueryBlockType);
|
||||
|
||||
auto Offset = GetPoweredRailAdjacentXZCoordinateOffset(a_Meta);
|
||||
const auto Meta = a_Chunk.GetMeta(a_Position);
|
||||
const auto Offset = GetPoweredRailAdjacentXZCoordinateOffset(Meta);
|
||||
if (((Offset + a_Position) == a_QueryPosition) || ((-Offset + a_Position) == a_QueryPosition))
|
||||
{
|
||||
auto Power = DataForChunk(a_Chunk).GetCachedPowerData(a_Position).PowerLevel;
|
||||
@ -66,8 +65,8 @@ public:
|
||||
{
|
||||
a_Chunk.SetMeta(a_Position, (a_PoweringData.PowerLevel == 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);
|
||||
}
|
||||
|
||||
return;
|
||||
@ -79,7 +78,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
|
||||
virtual void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
|
||||
{
|
||||
UNUSED(a_Chunk);
|
||||
UNUSED(a_Meta);
|
||||
|
@ -11,19 +11,18 @@
|
||||
|
||||
class cPressurePlateHandler final : public cRedstoneHandler
|
||||
{
|
||||
public:
|
||||
|
||||
virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
|
||||
virtual unsigned char GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) const override
|
||||
{
|
||||
UNUSED(a_BlockType);
|
||||
UNUSED(a_Meta);
|
||||
UNUSED(a_QueryPosition);
|
||||
UNUSED(a_QueryBlockType);
|
||||
|
||||
return DataForChunk(a_Chunk).GetCachedPowerData(a_Position).PowerLevel;
|
||||
// Plates only link power blocks below
|
||||
// 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;
|
||||
}
|
||||
|
||||
static unsigned char GetPowerLevel(cChunk & Chunk, const Vector3i Position, const BLOCKTYPE BlockType)
|
||||
static unsigned char GetPowerLevel(const cChunk & Chunk, const Vector3i Position, const BLOCKTYPE BlockType)
|
||||
{
|
||||
unsigned NumberOfEntities = 0;
|
||||
bool FoundPlayer = false;
|
||||
@ -70,12 +69,6 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
static void UpdatePlate(cChunk & Chunk, cChunk & CurrentlyTicking, Vector3i Position)
|
||||
{
|
||||
UpdateAdjustedRelative(Chunk, CurrentlyTicking, Position + OffsetYM);
|
||||
UpdateAdjustedRelatives(Chunk, CurrentlyTicking, Position, RelativeLaterals);
|
||||
}
|
||||
|
||||
virtual void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override
|
||||
{
|
||||
// LOGD("Evaluating clicky the pressure plate (%d %d %d)", a_Position.x, a_Position.y, a_Position.z);
|
||||
@ -107,7 +100,9 @@ public:
|
||||
|
||||
// Immediately depress plate
|
||||
a_Chunk.SetMeta(a_Position, E_META_PRESSURE_PLATE_DEPRESSED);
|
||||
return UpdatePlate(a_Chunk, CurrentlyTicking, a_Position);
|
||||
|
||||
UpdateAdjustedRelatives(a_Chunk, CurrentlyTicking, a_Position, RelativeAdjacents);
|
||||
return;
|
||||
}
|
||||
|
||||
// Not a resting state
|
||||
@ -137,7 +132,7 @@ public:
|
||||
{
|
||||
// Yes. Update power
|
||||
ChunkData.SetCachedPowerData(a_Position, PoweringData(a_BlockType, Power));
|
||||
return UpdatePlate(a_Chunk, CurrentlyTicking, a_Position);
|
||||
UpdateAdjustedRelatives(a_Chunk, CurrentlyTicking, a_Position, RelativeAdjacents);
|
||||
}
|
||||
|
||||
return;
|
||||
@ -159,7 +154,7 @@ public:
|
||||
{
|
||||
// Yes. Update power
|
||||
ChunkData.SetCachedPowerData(a_Position, PoweringData(a_BlockType, Power));
|
||||
return UpdatePlate(a_Chunk, CurrentlyTicking, a_Position);
|
||||
UpdateAdjustedRelatives(a_Chunk, CurrentlyTicking, a_Position, RelativeAdjacents);
|
||||
}
|
||||
|
||||
// Yes, but player's still on the plate, do nothing
|
||||
@ -173,10 +168,10 @@ public:
|
||||
ChunkData.SetCachedPowerData(a_Position, PoweringData(a_BlockType, Power));
|
||||
|
||||
a_Chunk.SetMeta(a_Position, E_META_PRESSURE_PLATE_RAISED);
|
||||
return UpdatePlate(a_Chunk, CurrentlyTicking, a_Position);
|
||||
UpdateAdjustedRelatives(a_Chunk, CurrentlyTicking, a_Position, RelativeAdjacents);
|
||||
}
|
||||
|
||||
virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
|
||||
virtual void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
|
||||
{
|
||||
UNUSED(a_Chunk);
|
||||
UNUSED(a_Position);
|
||||
|
@ -11,14 +11,14 @@ class cRedstoneBlockHandler final : public cRedstoneHandler
|
||||
{
|
||||
public:
|
||||
|
||||
virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
|
||||
virtual unsigned char GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) const override
|
||||
{
|
||||
UNUSED(a_Chunk);
|
||||
UNUSED(a_Position);
|
||||
UNUSED(a_BlockType);
|
||||
UNUSED(a_Meta);
|
||||
UNUSED(a_QueryPosition);
|
||||
return cIncrementalRedstoneSimulator::IsMechanism(a_QueryBlockType) ? 15 : 0;
|
||||
UNUSED(IsLinked);
|
||||
return IsLinked ? 0 : 15;
|
||||
}
|
||||
|
||||
virtual void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override
|
||||
@ -26,7 +26,7 @@ public:
|
||||
// LOGD("Evaluating crimson the redstone block (%d %d %d)", a_Position.x, a_Position.y, a_Position.z);
|
||||
}
|
||||
|
||||
virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
|
||||
virtual void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
|
||||
{
|
||||
UNUSED(a_Chunk);
|
||||
UNUSED(a_Position);
|
||||
|
@ -10,8 +10,6 @@
|
||||
|
||||
class cRedstoneComparatorHandler : public cRedstoneHandler
|
||||
{
|
||||
public:
|
||||
|
||||
static unsigned char GetFrontPowerLevel(NIBBLETYPE a_Meta, unsigned char a_HighestSidePowerLevel, unsigned char a_HighestRearPowerLevel)
|
||||
{
|
||||
if (cBlockComparatorHandler::IsInSubtractionMode(a_Meta))
|
||||
@ -26,13 +24,14 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
|
||||
virtual unsigned char GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) const override
|
||||
{
|
||||
UNUSED(a_QueryPosition);
|
||||
UNUSED(a_QueryBlockType);
|
||||
|
||||
const auto Meta = a_Chunk.GetMeta(a_Position);
|
||||
return (
|
||||
(cBlockComparatorHandler::GetFrontCoordinate(a_Position, a_Meta & 0x3) == a_QueryPosition) ?
|
||||
(cBlockComparatorHandler::GetFrontCoordinate(a_Position, Meta & 0x3) == a_QueryPosition) ?
|
||||
DataForChunk(a_Chunk).GetCachedPowerData(a_Position).PowerLevel : 0
|
||||
);
|
||||
}
|
||||
@ -71,11 +70,8 @@ public:
|
||||
return false;
|
||||
});
|
||||
|
||||
BLOCKTYPE RearType;
|
||||
NIBBLETYPE RearMeta;
|
||||
RearChunk->GetBlockTypeMeta(RearCoordinate, RearType, RearMeta);
|
||||
|
||||
auto PotentialSourceHandler = cIncrementalRedstoneSimulator::GetComponentHandler(RearType);
|
||||
const auto RearType = RearChunk->GetBlock(RearCoordinate);
|
||||
const auto PotentialSourceHandler = cIncrementalRedstoneSimulator::GetComponentHandler(RearType);
|
||||
if (PotentialSourceHandler == nullptr)
|
||||
{
|
||||
return SignalStrength;
|
||||
@ -84,8 +80,8 @@ public:
|
||||
return std::max(
|
||||
SignalStrength,
|
||||
PotentialSourceHandler->GetPowerDeliveredToPosition(
|
||||
*RearChunk, RearCoordinate, RearType, RearMeta,
|
||||
cIncrementalRedstoneSimulatorChunkData::RebaseRelativePosition(a_Chunk, *RearChunk, Position), BlockType
|
||||
*RearChunk, RearCoordinate, RearType,
|
||||
cIncrementalRedstoneSimulatorChunkData::RebaseRelativePosition(a_Chunk, *RearChunk, Position), BlockType, false
|
||||
)
|
||||
);
|
||||
}
|
||||
@ -110,31 +106,33 @@ public:
|
||||
{
|
||||
Data.m_MechanismDelays[a_Position] = std::make_pair(1, bool());
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
else
|
||||
|
||||
int DelayTicks;
|
||||
std::tie(DelayTicks, std::ignore) = *DelayInfo;
|
||||
|
||||
if (DelayTicks != 0)
|
||||
{
|
||||
int DelayTicks;
|
||||
std::tie(DelayTicks, std::ignore) = *DelayInfo;
|
||||
|
||||
if (DelayTicks == 0)
|
||||
{
|
||||
const auto RearPower = GetPowerLevel(a_Chunk, a_Position, a_BlockType, a_Meta);
|
||||
const auto FrontPower = GetFrontPowerLevel(a_Meta, a_PoweringData.PowerLevel, RearPower);
|
||||
const auto NewMeta = (FrontPower > 0) ? (a_Meta | 0x8) : (a_Meta & 0x7);
|
||||
|
||||
// Don't care about the previous power level so return value ignored
|
||||
Data.ExchangeUpdateOncePowerData(a_Position, PoweringData(a_PoweringData.PoweringBlock, FrontPower));
|
||||
|
||||
a_Chunk.SetMeta(a_Position, NewMeta);
|
||||
Data.m_MechanismDelays.erase(a_Position);
|
||||
|
||||
// Assume that an update (to front power) is needed:
|
||||
UpdateAdjustedRelative(a_Chunk, CurrentlyTicking, cBlockComparatorHandler::GetFrontCoordinate(a_Position, a_Meta & 0x3));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const auto RearPower = GetPowerLevel(a_Chunk, a_Position, a_BlockType, a_Meta);
|
||||
const auto FrontPower = GetFrontPowerLevel(a_Meta, a_PoweringData.PowerLevel, RearPower);
|
||||
const auto NewMeta = (FrontPower > 0) ? (a_Meta | 0x8) : (a_Meta & 0x7);
|
||||
|
||||
// Don't care about the previous power level so return value ignored
|
||||
Data.ExchangeUpdateOncePowerData(a_Position, PoweringData(a_PoweringData.PoweringBlock, FrontPower));
|
||||
|
||||
a_Chunk.SetMeta(a_Position, NewMeta);
|
||||
Data.m_MechanismDelays.erase(a_Position);
|
||||
|
||||
// Assume that an update (to front power) is needed:
|
||||
UpdateAdjustedRelative(a_Chunk, CurrentlyTicking, a_Position, cBlockComparatorHandler::GetFrontCoordinate(a_Position, a_Meta & 0x3) - a_Position);
|
||||
}
|
||||
|
||||
virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
|
||||
virtual void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
|
||||
{
|
||||
UNUSED(a_Chunk);
|
||||
UNUSED(a_BlockType);
|
||||
|
@ -2,6 +2,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "../../Chunk.h"
|
||||
#include "ForEachSourceCallback.h"
|
||||
#include "RedstoneSimulatorChunkData.h"
|
||||
|
||||
|
||||
@ -15,71 +16,55 @@ public:
|
||||
cRedstoneHandler() = default;
|
||||
DISALLOW_COPY_AND_ASSIGN(cRedstoneHandler);
|
||||
|
||||
using SourceCallback = cFunctionRef<void(Vector3i)>;
|
||||
using SourceCallback = ForEachSourceCallback &;
|
||||
|
||||
virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const = 0;
|
||||
virtual unsigned char GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) const = 0;
|
||||
virtual void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const = 0;
|
||||
virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const = 0;
|
||||
virtual void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const = 0;
|
||||
|
||||
// Force a virtual destructor
|
||||
virtual ~cRedstoneHandler() {}
|
||||
|
||||
protected:
|
||||
|
||||
template <class Container>
|
||||
static Container StaticAppend(const Container & a_Lhs, const Container & a_Rhs)
|
||||
{
|
||||
Container ToReturn = a_Lhs;
|
||||
std::copy(a_Rhs.begin(), a_Rhs.end(), std::back_inserter(ToReturn));
|
||||
return ToReturn;
|
||||
}
|
||||
|
||||
inline static Vector3i OffsetYP{ 0, 1, 0 };
|
||||
|
||||
inline static Vector3i OffsetYM{ 0, -1, 0 };
|
||||
|
||||
static cVector3iArray GetAdjustedRelatives(Vector3i a_Position, cVector3iArray a_Relatives)
|
||||
{
|
||||
for (auto & Entry : a_Relatives)
|
||||
{
|
||||
Entry += a_Position;
|
||||
}
|
||||
return a_Relatives;
|
||||
}
|
||||
|
||||
inline static cIncrementalRedstoneSimulatorChunkData & DataForChunk(cChunk & a_Chunk)
|
||||
inline static auto & DataForChunk(const cChunk & a_Chunk)
|
||||
{
|
||||
return *static_cast<cIncrementalRedstoneSimulatorChunkData *>(a_Chunk.GetRedstoneSimulatorData());
|
||||
}
|
||||
|
||||
template <typename... ArrayTypes>
|
||||
static void UpdateAdjustedRelative(cChunk & From, cChunk & To, const Vector3i Position)
|
||||
static void UpdateAdjustedRelative(const cChunk & From, const cChunk & To, const Vector3i Position, const Vector3i Offset)
|
||||
{
|
||||
DataForChunk(To).WakeUp(cIncrementalRedstoneSimulatorChunkData::RebaseRelativePosition(From, To, Position));
|
||||
DataForChunk(To).WakeUp(cIncrementalRedstoneSimulatorChunkData::RebaseRelativePosition(From, To, Position + Offset));
|
||||
|
||||
for (const auto LinkedOffset : cSimulator::GetLinkedOffsets(Offset))
|
||||
{
|
||||
DataForChunk(To).WakeUp(cIncrementalRedstoneSimulatorChunkData::RebaseRelativePosition(From, To, Position + LinkedOffset));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename ArrayType, typename... ArrayTypes>
|
||||
static void UpdateAdjustedRelatives(cChunk & From, cChunk & To, const Vector3i Position, const ArrayType & Relative, const ArrayTypes &... Relatives)
|
||||
template <typename ArrayType>
|
||||
static void UpdateAdjustedRelatives(const cChunk & From, const cChunk & To, const Vector3i Position, const ArrayType & Relative)
|
||||
{
|
||||
for (const auto Offset : Relative)
|
||||
{
|
||||
DataForChunk(To).GetActiveBlocks().push(cIncrementalRedstoneSimulatorChunkData::RebaseRelativePosition(From, To, Position + Offset));
|
||||
UpdateAdjustedRelative(From, To, Position, Offset);
|
||||
}
|
||||
|
||||
UpdateAdjustedRelatives(From, To, Position, Relatives...);
|
||||
}
|
||||
|
||||
template <typename ArrayType, typename... ArrayTypes>
|
||||
static void InvokeForAdjustedRelatives(SourceCallback Callback, const Vector3i Position, const ArrayType & Relative, const ArrayTypes &... Relatives)
|
||||
template <typename ArrayType>
|
||||
static void InvokeForAdjustedRelatives(SourceCallback Callback, const Vector3i Position, const ArrayType & Relative)
|
||||
{
|
||||
for (const auto Offset : Relative)
|
||||
{
|
||||
Callback(Position + Offset);
|
||||
}
|
||||
|
||||
InvokeForAdjustedRelatives(Callback, Position, Relatives...);
|
||||
}
|
||||
|
||||
inline static Vector3i OffsetYP{ 0, 1, 0 };
|
||||
|
||||
inline static Vector3i OffsetYM{ 0, -1, 0 };
|
||||
|
||||
inline static std::array<Vector3i, 6> RelativeAdjacents
|
||||
{
|
||||
{
|
||||
@ -101,14 +86,4 @@ protected:
|
||||
{ 0, 0, -1 },
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
static void UpdateAdjustedRelatives(cChunk &, cChunk &, const Vector3i)
|
||||
{
|
||||
}
|
||||
|
||||
static void InvokeForAdjustedRelatives(SourceCallback, const Vector3i)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
@ -7,14 +7,12 @@
|
||||
|
||||
class cRedstoneLampHandler final : public cRedstoneHandler
|
||||
{
|
||||
public:
|
||||
|
||||
inline static bool IsOn(BLOCKTYPE a_BlockType)
|
||||
{
|
||||
return (a_BlockType == E_BLOCK_REDSTONE_LAMP_ON);
|
||||
}
|
||||
|
||||
virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
|
||||
virtual unsigned char GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) const override
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@ -39,7 +37,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
|
||||
virtual void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
|
||||
{
|
||||
UNUSED(a_Chunk);
|
||||
UNUSED(a_Meta);
|
||||
|
@ -8,16 +8,23 @@
|
||||
|
||||
|
||||
|
||||
class cRedstoneRepeaterHandler:
|
||||
public cRedstoneHandler
|
||||
class cRedstoneRepeaterHandler final : public cRedstoneHandler
|
||||
{
|
||||
using Super = cRedstoneHandler;
|
||||
|
||||
public:
|
||||
|
||||
virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
|
||||
virtual unsigned char GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) const override
|
||||
{
|
||||
return ((a_QueryPosition == (a_Position + cBlockRedstoneRepeaterHandler::GetFrontCoordinateOffset(a_Meta))) && IsOn(a_BlockType)) ? 15 : 0;
|
||||
if (!IsOn(a_BlockType))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
const auto FrontOffset = cBlockRedstoneRepeaterHandler::GetFrontCoordinateOffset(a_Chunk.GetMeta(a_Position));
|
||||
const auto FrontPosition = a_Position + FrontOffset;
|
||||
if (a_QueryPosition == FrontPosition)
|
||||
{
|
||||
return 15;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override
|
||||
@ -45,37 +52,36 @@ public:
|
||||
{
|
||||
Data.m_MechanismDelays[a_Position] = std::make_pair((((a_Meta & 0xC) >> 0x2) + 1), ShouldBeOn);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
else
|
||||
|
||||
int DelayTicks;
|
||||
bool ShouldPowerOn;
|
||||
std::tie(DelayTicks, ShouldPowerOn) = *DelayInfo;
|
||||
|
||||
if (DelayTicks != 0)
|
||||
{
|
||||
int DelayTicks;
|
||||
bool ShouldPowerOn;
|
||||
std::tie(DelayTicks, ShouldPowerOn) = *DelayInfo;
|
||||
|
||||
if (DelayTicks == 0)
|
||||
{
|
||||
const auto NewType = ShouldPowerOn ? E_BLOCK_REDSTONE_REPEATER_ON : E_BLOCK_REDSTONE_REPEATER_OFF;
|
||||
a_Chunk.FastSetBlock(a_Position, NewType, a_Meta);
|
||||
Data.m_MechanismDelays.erase(a_Position);
|
||||
|
||||
// While sleeping, we ignore any power changes and apply our saved ShouldBeOn when sleep expires
|
||||
// Now, we need to recalculate to be aware of any new changes that may e.g. cause a new output change
|
||||
// FastSetBlock doesn't wake simulators, so manually update ourselves:
|
||||
Update(a_Chunk, CurrentlyTicking, a_Position, NewType, a_Meta, a_PoweringData);
|
||||
|
||||
UpdateAdjustedRelative(a_Chunk, CurrentlyTicking, a_Position + cBlockRedstoneRepeaterHandler::GetFrontCoordinateOffset(a_Meta));
|
||||
UpdateAdjustedRelatives(a_Chunk, CurrentlyTicking, a_Position + cBlockRedstoneRepeaterHandler::GetFrontCoordinateOffset(a_Meta), RelativeAdjacents);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const auto NewType = ShouldPowerOn ? E_BLOCK_REDSTONE_REPEATER_ON : E_BLOCK_REDSTONE_REPEATER_OFF;
|
||||
a_Chunk.FastSetBlock(a_Position, NewType, a_Meta);
|
||||
Data.m_MechanismDelays.erase(a_Position);
|
||||
|
||||
// While sleeping, we ignore any power changes and apply our saved ShouldBeOn when sleep expires
|
||||
// Now, we need to recalculate to be aware of any new changes that may e.g. cause a new output change
|
||||
// FastSetBlock doesn't wake simulators, so manually update ourselves:
|
||||
Update(a_Chunk, CurrentlyTicking, a_Position, NewType, a_Meta, a_PoweringData);
|
||||
|
||||
UpdateAdjustedRelative(a_Chunk, CurrentlyTicking, a_Position, cBlockRedstoneRepeaterHandler::GetFrontCoordinateOffset(a_Meta));
|
||||
}
|
||||
|
||||
virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
|
||||
virtual void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
|
||||
{
|
||||
Callback(cBlockRedstoneRepeaterHandler::GetRearCoordinateOffset(a_Meta) + a_Position);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
inline static bool IsOn(BLOCKTYPE a_Block)
|
||||
{
|
||||
return (a_Block == E_BLOCK_REDSTONE_REPEATER_ON);
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <stack>
|
||||
|
||||
#include "../RedstoneSimulator.h"
|
||||
#include "../../Chunk.h"
|
||||
|
||||
|
||||
|
||||
@ -53,7 +54,7 @@ public:
|
||||
|
||||
|
||||
|
||||
class cIncrementalRedstoneSimulatorChunkData : public cRedstoneSimulatorChunkData
|
||||
class cIncrementalRedstoneSimulatorChunkData final : public cRedstoneSimulatorChunkData
|
||||
{
|
||||
public:
|
||||
|
||||
@ -90,6 +91,7 @@ public:
|
||||
m_CachedPowerLevels.erase(Position);
|
||||
m_MechanismDelays.erase(Position);
|
||||
AlwaysTickedPositions.erase(Position);
|
||||
WireStates.erase(Position);
|
||||
}
|
||||
|
||||
PoweringData ExchangeUpdateOncePowerData(const Vector3i & a_Position, PoweringData a_PoweringData)
|
||||
@ -105,7 +107,7 @@ public:
|
||||
}
|
||||
|
||||
/** Adjust From-relative coordinates into To-relative coordinates. */
|
||||
inline static Vector3i RebaseRelativePosition(cChunk & From, cChunk & To, const Vector3i Position)
|
||||
inline static Vector3i RebaseRelativePosition(const cChunk & From, const cChunk & To, const Vector3i Position)
|
||||
{
|
||||
return
|
||||
{
|
||||
@ -115,9 +117,12 @@ public:
|
||||
};
|
||||
}
|
||||
|
||||
/** Temporary, should be chunk data: wire block store, to avoid recomputing states every time. */
|
||||
std::unordered_map<Vector3i, short, VectorHasher<int>> WireStates;
|
||||
|
||||
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;
|
||||
|
||||
private:
|
||||
|
@ -11,9 +11,7 @@
|
||||
|
||||
class cRedstoneToggleHandler final : public cRedstoneHandler
|
||||
{
|
||||
public:
|
||||
|
||||
inline static Vector3i GetPositionAttachedTo(Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta)
|
||||
inline static Vector3i GetOffsetAttachedTo(Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta)
|
||||
{
|
||||
switch (a_BlockType)
|
||||
{
|
||||
@ -22,13 +20,13 @@ public:
|
||||
switch (a_Meta & 0x7)
|
||||
{
|
||||
case 0x0:
|
||||
case 0x7: return { a_Position + Vector3i(0, 1, 0) };
|
||||
case 0x1: return { a_Position + Vector3i(-1, 0, 0) };
|
||||
case 0x2: return { a_Position + Vector3i(1, 0, 0) };
|
||||
case 0x3: return { a_Position + Vector3i(0, 0, -1) };
|
||||
case 0x4: return { a_Position + Vector3i(0, 0, 1) };
|
||||
case 0x7: return { 0, 1, 0 };
|
||||
case 0x1: return { -1, 0, 0 };
|
||||
case 0x2: return { 1, 0, 0 };
|
||||
case 0x3: return { 0, 0, -1 };
|
||||
case 0x4: return { 0, 0, 1 };
|
||||
case 0x5:
|
||||
case 0x6: return { a_Position + Vector3i(0, -1, 0) };
|
||||
case 0x6: return { 0, -1, 0 };
|
||||
default:
|
||||
{
|
||||
ASSERT(!"Unhandled lever metadata!");
|
||||
@ -41,12 +39,12 @@ public:
|
||||
{
|
||||
switch (a_Meta & 0x7)
|
||||
{
|
||||
case 0x0: return { a_Position + Vector3i(0, 1, 0) };
|
||||
case 0x1: return { a_Position + Vector3i(-1, 0, 0) };
|
||||
case 0x2: return { a_Position + Vector3i(1, 0, 0) };
|
||||
case 0x3: return { a_Position + Vector3i(0, 0, -1) };
|
||||
case 0x4: return { a_Position + Vector3i(0, 0, 1) };
|
||||
case 0x5: return { a_Position + Vector3i(0, -1, 0) };
|
||||
case 0x0: return { 0, 1, 0 };
|
||||
case 0x1: return { -1, 0, 0 };
|
||||
case 0x2: return { 1, 0, 0 };
|
||||
case 0x3: return { 0, 0, -1 };
|
||||
case 0x4: return { 0, 0, 1 };
|
||||
case 0x5: return { 0, -1, 0 };
|
||||
default:
|
||||
{
|
||||
ASSERT(!"Unhandled button metadata!");
|
||||
@ -62,14 +60,19 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
|
||||
virtual unsigned char GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) const override
|
||||
{
|
||||
UNUSED(a_QueryBlockType);
|
||||
if ((GetPositionAttachedTo(a_Position, a_BlockType, a_Meta) == a_QueryPosition) || cIncrementalRedstoneSimulator::IsMechanism(a_QueryBlockType))
|
||||
|
||||
const auto Meta = a_Chunk.GetMeta(a_Position);
|
||||
const auto QueryOffset = a_QueryPosition - a_Position;
|
||||
|
||||
if (IsLinked && (QueryOffset != GetOffsetAttachedTo(a_Position, a_BlockType, Meta)))
|
||||
{
|
||||
return GetPowerLevel(a_BlockType, a_Meta);
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
|
||||
return GetPowerLevel(a_BlockType, Meta);
|
||||
}
|
||||
|
||||
static unsigned char GetPowerLevel(BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta)
|
||||
@ -92,7 +95,7 @@ public:
|
||||
// LOGD("Evaluating templatio<> the lever/button (%d %d %d)", a_Position.x, a_Position.y, a_Position.z);
|
||||
}
|
||||
|
||||
virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
|
||||
virtual void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
|
||||
{
|
||||
UNUSED(a_Chunk);
|
||||
UNUSED(a_Position);
|
||||
|
@ -9,14 +9,12 @@
|
||||
|
||||
class cRedstoneTorchHandler final : public cRedstoneHandler
|
||||
{
|
||||
public:
|
||||
|
||||
inline static bool IsOn(BLOCKTYPE a_Block)
|
||||
{
|
||||
return (a_Block == E_BLOCK_REDSTONE_TORCH_ON);
|
||||
}
|
||||
|
||||
inline static Vector3i GetOffsetAttachedTo(Vector3i a_Position, NIBBLETYPE a_Meta)
|
||||
inline static Vector3i GetOffsetAttachedTo(const NIBBLETYPE a_Meta)
|
||||
{
|
||||
switch (a_Meta)
|
||||
{
|
||||
@ -33,17 +31,20 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
|
||||
virtual unsigned char GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) const override
|
||||
{
|
||||
const auto QueryOffset = a_QueryPosition - a_Position;
|
||||
|
||||
if (
|
||||
IsOn(a_BlockType) &&
|
||||
(a_QueryPosition != (a_Position + GetOffsetAttachedTo(a_Position, a_Meta))) &&
|
||||
(cIncrementalRedstoneSimulator::IsMechanism(a_QueryBlockType) || (cBlockInfo::FullyOccupiesVoxel(a_QueryBlockType) && (a_QueryPosition == (a_Position + OffsetYP))))
|
||||
!IsOn(a_BlockType) ||
|
||||
(QueryOffset == GetOffsetAttachedTo(a_Chunk.GetMeta(a_Position))) ||
|
||||
(IsLinked && (QueryOffset != OffsetYP))
|
||||
)
|
||||
{
|
||||
return 15;
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
|
||||
return 15;
|
||||
}
|
||||
|
||||
virtual void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override
|
||||
@ -55,40 +56,42 @@ public:
|
||||
|
||||
if (DelayInfo == nullptr)
|
||||
{
|
||||
bool ShouldBeOn = (a_PoweringData.PowerLevel == 0);
|
||||
const bool ShouldBeOn = (a_PoweringData.PowerLevel == 0);
|
||||
if (ShouldBeOn != IsOn(a_BlockType))
|
||||
{
|
||||
Data.m_MechanismDelays[a_Position] = std::make_pair(1, ShouldBeOn);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
else
|
||||
|
||||
int DelayTicks;
|
||||
bool ShouldPowerOn;
|
||||
std::tie(DelayTicks, ShouldPowerOn) = *DelayInfo;
|
||||
|
||||
if (DelayTicks != 0)
|
||||
{
|
||||
int DelayTicks;
|
||||
bool ShouldPowerOn;
|
||||
std::tie(DelayTicks, ShouldPowerOn) = *DelayInfo;
|
||||
return;
|
||||
}
|
||||
|
||||
if (DelayTicks != 0)
|
||||
a_Chunk.FastSetBlock(a_Position, ShouldPowerOn ? E_BLOCK_REDSTONE_TORCH_ON : E_BLOCK_REDSTONE_TORCH_OFF, a_Meta);
|
||||
Data.m_MechanismDelays.erase(a_Position);
|
||||
|
||||
for (const auto Adjacent : RelativeAdjacents)
|
||||
{
|
||||
// Update all adjacents (including linked power positions)
|
||||
// apart from our attachment, which can't possibly need an update:
|
||||
if (Adjacent != GetOffsetAttachedTo(a_Meta))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
a_Chunk.SetBlock(a_Position, ShouldPowerOn ? E_BLOCK_REDSTONE_TORCH_ON : E_BLOCK_REDSTONE_TORCH_OFF, a_Meta);
|
||||
Data.m_MechanismDelays.erase(a_Position);
|
||||
|
||||
for (const auto Adjacent : RelativeAdjacents)
|
||||
{
|
||||
if (Adjacent != GetOffsetAttachedTo(a_Position, a_Meta))
|
||||
{
|
||||
UpdateAdjustedRelative(a_Chunk, CurrentlyTicking, a_Position + Adjacent);
|
||||
}
|
||||
UpdateAdjustedRelative(a_Chunk, CurrentlyTicking, a_Position, Adjacent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
|
||||
virtual void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
|
||||
{
|
||||
UNUSED(a_Chunk);
|
||||
UNUSED(a_BlockType);
|
||||
Callback(a_Position + GetOffsetAttachedTo(a_Position, a_Meta));
|
||||
Callback(a_Position + GetOffsetAttachedTo(a_Meta));
|
||||
}
|
||||
};
|
||||
|
@ -2,6 +2,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "RedstoneHandler.h"
|
||||
#include "../../Registries/Blocks.h"
|
||||
|
||||
|
||||
|
||||
@ -9,8 +10,162 @@
|
||||
|
||||
class cRedstoneWireHandler final : public cRedstoneHandler
|
||||
{
|
||||
/** A unified representation of wire direction. */
|
||||
enum class TemporaryDirection
|
||||
{
|
||||
Up,
|
||||
Side
|
||||
};
|
||||
|
||||
/** Adjusts a given wire block so that the direction represented by Offset has state Direction. */
|
||||
inline static void SetDirectionState(const Vector3i Offset, short & Block, TemporaryDirection Direction)
|
||||
{
|
||||
Block = DoWithDirectionState(Offset, Block, [Direction](auto, auto & Front, auto)
|
||||
{
|
||||
using FrontState = std::remove_reference_t<decltype(Front)>;
|
||||
switch (Direction)
|
||||
{
|
||||
case TemporaryDirection::Up:
|
||||
{
|
||||
Front = FrontState::Up;
|
||||
return;
|
||||
}
|
||||
case TemporaryDirection::Side:
|
||||
{
|
||||
Front = FrontState::Side;
|
||||
return;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/** Invokes Callback with the wire's left, front, and right direction state corresponding to Offset.
|
||||
Returns a new block constructed from the directions that the callback may have modified. */
|
||||
template <class OffsetCallback>
|
||||
inline static short DoWithDirectionState(const Vector3i Offset, short Block, OffsetCallback Callback)
|
||||
{
|
||||
auto North = Block::RedstoneWire::North(Block);
|
||||
auto South = Block::RedstoneWire::South(Block);
|
||||
auto West = Block::RedstoneWire::West(Block);
|
||||
auto East = Block::RedstoneWire::East(Block);
|
||||
|
||||
if (Offset.x == -1)
|
||||
{
|
||||
Callback(South, West, North);
|
||||
}
|
||||
else if (Offset.x == 1)
|
||||
{
|
||||
Callback(North, East, South);
|
||||
}
|
||||
|
||||
if (Offset.z == -1)
|
||||
{
|
||||
Callback(West, North, East);
|
||||
}
|
||||
else if (Offset.z == 1)
|
||||
{
|
||||
Callback(East, South, West);
|
||||
}
|
||||
|
||||
return Block::RedstoneWire::RedstoneWire(East, North, 0, South, West);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/** Temporary. Discovers a wire's connection state, including terracing, storing the block inside redstone chunk data.
|
||||
TODO: once the server supports block states this should go in the block handler, with data saved in the world. */
|
||||
void SetWireState(const cChunk & Chunk, const Vector3i Position) const
|
||||
{
|
||||
auto Block = Block::RedstoneWire::RedstoneWire();
|
||||
const auto YPTerraceBlock = Chunk.GetBlock(Position + OffsetYP);
|
||||
const bool IsYPTerracingBlocked = cBlockInfo::IsSolid(YPTerraceBlock) && !cBlockInfo::IsTransparent(YPTerraceBlock);
|
||||
|
||||
// Loop through laterals, discovering terracing connections:
|
||||
for (const auto Offset : RelativeLaterals)
|
||||
{
|
||||
auto Adjacent = Position + Offset;
|
||||
auto NeighbourChunk = Chunk.GetRelNeighborChunkAdjustCoords(Adjacent);
|
||||
|
||||
if ((NeighbourChunk == nullptr) || !NeighbourChunk->IsValid())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
BLOCKTYPE LateralBlock;
|
||||
NIBBLETYPE LateralMeta;
|
||||
NeighbourChunk->GetBlockTypeMeta(Adjacent, LateralBlock, LateralMeta);
|
||||
|
||||
if (IsDirectlyConnectingMechanism(LateralBlock, LateralMeta, Offset))
|
||||
{
|
||||
// Any direct connections on a lateral means the wire has side connection in that direction:
|
||||
SetDirectionState(Offset, Block, TemporaryDirection::Side);
|
||||
|
||||
// Temporary: this case will eventually be handled when wires are placed, with the state saved as blocks
|
||||
// When a neighbour wire was loaded into its chunk, its neighbour chunks may not have loaded yet
|
||||
// This function is called during chunk load (through AddBlock). Attempt to tell it its new state:
|
||||
if ((NeighbourChunk != &Chunk) && (LateralBlock == E_BLOCK_REDSTONE_WIRE))
|
||||
{
|
||||
auto & NeighbourBlock = DataForChunk(*NeighbourChunk).WireStates.find(Adjacent)->second;
|
||||
SetDirectionState(-Offset, NeighbourBlock, TemporaryDirection::Side);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (
|
||||
!IsYPTerracingBlocked && // A block above us blocks all YP terracing, so the check is static in the loop
|
||||
(Adjacent.y < (cChunkDef::Height - 1)) &&
|
||||
(NeighbourChunk->GetBlock(Adjacent + OffsetYP) == E_BLOCK_REDSTONE_WIRE) // Only terrace YP with another wire
|
||||
)
|
||||
{
|
||||
SetDirectionState(Offset, Block, TemporaryDirection::Up);
|
||||
|
||||
if (NeighbourChunk != &Chunk)
|
||||
{
|
||||
auto & NeighbourBlock = DataForChunk(*NeighbourChunk).WireStates.find(Adjacent + OffsetYP)->second;
|
||||
SetDirectionState(-Offset, NeighbourBlock, TemporaryDirection::Side);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (
|
||||
// IsYMTerracingBlocked (i.e. check block above lower terracing position, a.k.a. just the plain adjacent)
|
||||
(!cBlockInfo::IsSolid(LateralBlock) || cBlockInfo::IsTransparent(LateralBlock)) &&
|
||||
(NeighbourChunk->GetBlock(Adjacent + OffsetYM) == E_BLOCK_REDSTONE_WIRE) // Only terrace YM with another wire
|
||||
)
|
||||
{
|
||||
SetDirectionState(Offset, Block, TemporaryDirection::Side);
|
||||
|
||||
if (NeighbourChunk != &Chunk)
|
||||
{
|
||||
auto & NeighbourBlock = DataForChunk(*NeighbourChunk).WireStates.find(Adjacent + OffsetYM)->second;
|
||||
SetDirectionState(-Offset, NeighbourBlock, TemporaryDirection::Up);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto & States = DataForChunk(Chunk).WireStates;
|
||||
const auto FindResult = States.find(Position);
|
||||
if (FindResult != States.end())
|
||||
{
|
||||
if (Block != FindResult->second)
|
||||
{
|
||||
FindResult->second = Block;
|
||||
|
||||
// TODO: when state is stored as the block, the block handler updating via SetBlock will do this automatically
|
||||
// When a wire changes connection state, it needs to update its neighbours:
|
||||
Chunk.GetWorld()->WakeUpSimulators(cChunkDef::RelativeToAbsolute(Position, Chunk.GetPos()));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
DataForChunk(Chunk).WireStates[Position] = Block;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
inline static bool IsDirectlyConnectingMechanism(BLOCKTYPE a_Block, NIBBLETYPE a_BlockMeta, const Vector3i a_Offset)
|
||||
{
|
||||
switch (a_Block)
|
||||
@ -30,6 +185,7 @@ public:
|
||||
}
|
||||
case E_BLOCK_ACTIVE_COMPARATOR:
|
||||
case E_BLOCK_INACTIVE_COMPARATOR:
|
||||
case E_BLOCK_BLOCK_OF_REDSTONE:
|
||||
case E_BLOCK_REDSTONE_TORCH_OFF:
|
||||
case E_BLOCK_REDSTONE_TORCH_ON:
|
||||
case E_BLOCK_REDSTONE_WIRE: return true;
|
||||
@ -37,170 +193,135 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
template <class OffsetCallback>
|
||||
static bool ForTerracingConnectionOffsets(cChunk & a_Chunk, const Vector3i a_Position, OffsetCallback Callback)
|
||||
virtual unsigned char GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) const override
|
||||
{
|
||||
const auto YPTerraceBlock = a_Chunk.GetBlock(a_Position + OffsetYP);
|
||||
const bool IsYPTerracingBlocked = cBlockInfo::IsSolid(YPTerraceBlock) && !cBlockInfo::IsTransparent(YPTerraceBlock);
|
||||
// Starts off as the wire's meta value, modified appropriately and returned
|
||||
auto Power = a_Chunk.GetMeta(a_Position);
|
||||
const auto QueryOffset = a_QueryPosition - a_Position;
|
||||
|
||||
for (const auto Adjacent : RelativeLaterals)
|
||||
if (
|
||||
(QueryOffset == OffsetYP) || // Wires do not power things above them
|
||||
(IsLinked && (a_QueryBlockType == E_BLOCK_REDSTONE_WIRE)) // Nor do they link power other wires
|
||||
)
|
||||
{
|
||||
// All laterals are counted as terracing, duh
|
||||
if (Callback(Adjacent))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (
|
||||
BLOCKTYPE YPBlock;
|
||||
|
||||
// A block above us blocks all YP terracing, so the check is static in the loop
|
||||
!IsYPTerracingBlocked &&
|
||||
a_Chunk.UnboundedRelGetBlockType(a_Position + Adjacent + OffsetYP, YPBlock) &&
|
||||
(YPBlock == E_BLOCK_REDSTONE_WIRE)
|
||||
)
|
||||
{
|
||||
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 false;
|
||||
}
|
||||
|
||||
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))
|
||||
{
|
||||
// Wires do not power things above them
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (a_QueryBlockType == E_BLOCK_REDSTONE_WIRE)
|
||||
if (QueryOffset == OffsetYM)
|
||||
{
|
||||
// For mechanisms, wire of power one will still power them
|
||||
// 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
|
||||
return Power;
|
||||
}
|
||||
|
||||
// Wires always deliver power to the block underneath, and any directly connecting mechanisms
|
||||
if (
|
||||
NIBBLETYPE QueryMeta;
|
||||
const auto & Data = DataForChunk(a_Chunk);
|
||||
const auto Block = Data.WireStates.find(a_Position)->second;
|
||||
|
||||
(a_QueryPosition == (a_Position + OffsetYM)) ||
|
||||
(a_Chunk.UnboundedRelGetBlockMeta(a_QueryPosition, QueryMeta) && IsDirectlyConnectingMechanism(a_QueryBlockType, QueryMeta, a_QueryPosition - a_Position))
|
||||
)
|
||||
DoWithDirectionState(QueryOffset, Block, [a_QueryBlockType, &Power](const auto Left, const auto Front, const auto Right)
|
||||
{
|
||||
return a_Meta;
|
||||
}
|
||||
using LeftState = std::remove_reference_t<decltype(Left)>;
|
||||
using FrontState = std::remove_reference_t<decltype(Front)>;
|
||||
using RightState = std::remove_reference_t<decltype(Right)>;
|
||||
|
||||
/*
|
||||
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;
|
||||
|
||||
if (
|
||||
ForTerracingConnectionOffsets(a_Chunk, a_Position, [&a_Chunk, a_Position, &FoundOneBorderingMechanism, &PotentialOffset](const Vector3i Offset)
|
||||
// Wires always deliver power to any directly connecting mechanisms:
|
||||
if (Front != FrontState::None)
|
||||
{
|
||||
BLOCKTYPE Block;
|
||||
NIBBLETYPE Meta;
|
||||
|
||||
if (
|
||||
!a_Chunk.UnboundedRelGetBlock(Offset + a_Position, Block, Meta) ||
|
||||
!IsDirectlyConnectingMechanism(Block, Meta, Offset)
|
||||
)
|
||||
if ((a_QueryBlockType == E_BLOCK_REDSTONE_WIRE) && (Power != 0))
|
||||
{
|
||||
return false;
|
||||
// For mechanisms, wire of power one will still power them
|
||||
// But for wire-to-wire connections, power level decreases by 1:
|
||||
Power--;
|
||||
}
|
||||
|
||||
if (FoundOneBorderingMechanism)
|
||||
{
|
||||
// Case 3
|
||||
return true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Potential case 2
|
||||
FoundOneBorderingMechanism = true;
|
||||
PotentialOffset = { -Offset.x, 0, -Offset.z };
|
||||
/*
|
||||
Okay, we do not directly connect to the wire.
|
||||
1. If there are no DC mechanisms at all, the wire powers all laterals. Great, left and right are both None.
|
||||
2. 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.
|
||||
Check that left and right are both None.
|
||||
3. If there is more than one DC, no non-DCs are powered. Left, right, cannot both be None.
|
||||
*/
|
||||
if ((Left == LeftState::None) && (Right == RightState::None))
|
||||
{
|
||||
// Case 1
|
||||
// Case 2
|
||||
return;
|
||||
}
|
||||
|
||||
return false;
|
||||
})
|
||||
)
|
||||
{
|
||||
// Case 3
|
||||
return 0;
|
||||
}
|
||||
Power = 0;
|
||||
});
|
||||
|
||||
if (FoundOneBorderingMechanism && (a_QueryPosition != (a_Position + PotentialOffset)))
|
||||
{
|
||||
// Case 2 fail
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Case 1
|
||||
// Case 2 success
|
||||
|
||||
return a_Meta;
|
||||
return Power;
|
||||
}
|
||||
|
||||
virtual void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override
|
||||
{
|
||||
// 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_Chunk.SetMeta(a_Position, a_PoweringData.PowerLevel);
|
||||
return;
|
||||
}
|
||||
|
||||
// Notify block below us to update:
|
||||
UpdateAdjustedRelative(a_Chunk, CurrentlyTicking, a_Position + OffsetYM);
|
||||
a_Chunk.SetMeta(a_Position, a_PoweringData.PowerLevel);
|
||||
|
||||
// Notify all terracing positions:
|
||||
ForTerracingConnectionOffsets(a_Chunk, a_Position, [&a_Chunk, &CurrentlyTicking, a_Position](const Vector3i Offset)
|
||||
// Notify all positions, sans YP, to update:
|
||||
for (const auto Offset : RelativeAdjacents)
|
||||
{
|
||||
if (Offset == OffsetYP)
|
||||
{
|
||||
UpdateAdjustedRelative(a_Chunk, CurrentlyTicking, a_Position + Offset);
|
||||
return false;
|
||||
});
|
||||
continue;
|
||||
}
|
||||
|
||||
UpdateAdjustedRelative(a_Chunk, CurrentlyTicking, a_Position, Offset);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
|
||||
virtual void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
|
||||
{
|
||||
UNUSED(a_Chunk);
|
||||
UNUSED(a_BlockType);
|
||||
UNUSED(a_Meta);
|
||||
|
||||
Callback(a_Position + OffsetYP);
|
||||
Callback(a_Position + OffsetYM);
|
||||
|
||||
ForTerracingConnectionOffsets(a_Chunk, a_Position, [&Callback, a_Position](const Vector3i Offset)
|
||||
const auto & Data = DataForChunk(a_Chunk);
|
||||
const auto Block = Data.WireStates.find(a_Position)->second;
|
||||
|
||||
// Figure out, based on our pre-computed block, where we connect to:
|
||||
for (const auto Offset : RelativeLaterals)
|
||||
{
|
||||
Callback(a_Position + Offset);
|
||||
return false;
|
||||
});
|
||||
const auto Relative = a_Position + Offset;
|
||||
Callback(Relative);
|
||||
|
||||
DoWithDirectionState(Offset, Block, [&a_Chunk, &Callback, Relative](auto, const auto Front, auto)
|
||||
{
|
||||
using FrontState = std::remove_reference_t<decltype(Front)>;
|
||||
|
||||
if (Front == FrontState::Up)
|
||||
{
|
||||
Callback(Relative + OffsetYP);
|
||||
}
|
||||
else if (Front == FrontState::Side)
|
||||
{
|
||||
// Alas, no way to distinguish side lateral and side diagonal
|
||||
// Have to do a manual check to only accept power from YM diagonal if there's a wire there
|
||||
|
||||
const auto YMDiagonalPosition = Relative + OffsetYM;
|
||||
if (
|
||||
BLOCKTYPE Block;
|
||||
cChunkDef::IsValidHeight(YMDiagonalPosition.y) &&
|
||||
a_Chunk.UnboundedRelGetBlockType(YMDiagonalPosition, Block) &&
|
||||
(Block == E_BLOCK_REDSTONE_WIRE)
|
||||
)
|
||||
{
|
||||
Callback(YMDiagonalPosition);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -9,16 +9,14 @@
|
||||
|
||||
class cSmallGateHandler final : public cRedstoneHandler
|
||||
{
|
||||
public:
|
||||
|
||||
virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
|
||||
virtual unsigned char GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) const override
|
||||
{
|
||||
UNUSED(a_Chunk);
|
||||
UNUSED(a_Position);
|
||||
UNUSED(a_BlockType);
|
||||
UNUSED(a_Meta);
|
||||
UNUSED(a_QueryPosition);
|
||||
UNUSED(a_QueryBlockType);
|
||||
UNUSED(IsLinked);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -35,7 +33,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
|
||||
virtual void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
|
||||
{
|
||||
UNUSED(a_Chunk);
|
||||
UNUSED(a_BlockType);
|
||||
|
@ -1,62 +0,0 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "RedstoneHandler.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class cSolidBlockHandler:
|
||||
public cRedstoneHandler
|
||||
{
|
||||
using Super = cRedstoneHandler;
|
||||
|
||||
public:
|
||||
|
||||
virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
|
||||
{
|
||||
const auto SolidBlock = DataForChunk(a_Chunk).GetCachedPowerData(a_Position);
|
||||
return (
|
||||
!cIncrementalRedstoneSimulator::IsRedstone(a_QueryBlockType) ||
|
||||
(
|
||||
(a_QueryBlockType == E_BLOCK_REDSTONE_WIRE) &&
|
||||
(SolidBlock.PoweringBlock == E_BLOCK_REDSTONE_WIRE)
|
||||
)
|
||||
) ? 0 : SolidBlock.PowerLevel;
|
||||
}
|
||||
|
||||
virtual void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override
|
||||
{
|
||||
UNUSED(a_BlockType);
|
||||
UNUSED(a_Meta);
|
||||
// LOGD("Evaluating blocky the generic block (%d %d %d)", a_Position.x, a_Position.y, a_Position.z);
|
||||
|
||||
auto PreviousPower = DataForChunk(a_Chunk).ExchangeUpdateOncePowerData(a_Position, a_PoweringData);
|
||||
if ((a_PoweringData != PreviousPower) || (a_PoweringData.PoweringBlock != PreviousPower.PoweringBlock))
|
||||
{
|
||||
UpdateAdjustedRelatives(a_Chunk, CurrentlyTicking, a_Position, RelativeAdjacents);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
|
||||
{
|
||||
UNUSED(a_Chunk);
|
||||
UNUSED(a_BlockType);
|
||||
UNUSED(a_Meta);
|
||||
|
||||
/* TODO: is this more performant?
|
||||
cVector3iArray Adjacents;
|
||||
for (const auto Offset : GetRelativeAdjacents())
|
||||
{
|
||||
auto Position = Offset + a_Position;
|
||||
auto Block = m_World.GetBlock(Position);
|
||||
if ((Block == E_BLOCK_REDSTONE_REPEATER_ON) || (Block == E_BLOCK_REDSTONE_WIRE) || (Block == E_BLOCK_TRIPWIRE_HOOK))
|
||||
{
|
||||
Adjacents.emplace_back(Position);
|
||||
}
|
||||
}
|
||||
*/
|
||||
InvokeForAdjustedRelatives(Callback, a_Position, RelativeAdjacents);
|
||||
}
|
||||
};
|
@ -9,16 +9,14 @@
|
||||
|
||||
class cTNTHandler final : public cRedstoneHandler
|
||||
{
|
||||
public:
|
||||
|
||||
virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
|
||||
virtual unsigned char GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) const override
|
||||
{
|
||||
UNUSED(a_Chunk);
|
||||
UNUSED(a_Position);
|
||||
UNUSED(a_BlockType);
|
||||
UNUSED(a_Meta);
|
||||
UNUSED(a_QueryPosition);
|
||||
UNUSED(a_QueryBlockType);
|
||||
UNUSED(IsLinked);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -32,7 +30,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
|
||||
virtual void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
|
||||
{
|
||||
UNUSED(a_Chunk);
|
||||
UNUSED(a_BlockType);
|
||||
|
@ -8,19 +8,14 @@
|
||||
|
||||
|
||||
|
||||
class cTrappedChestHandler:
|
||||
public cRedstoneHandler
|
||||
class cTrappedChestHandler final : public cRedstoneHandler
|
||||
{
|
||||
using Super = cRedstoneHandler;
|
||||
|
||||
public:
|
||||
|
||||
virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
|
||||
virtual unsigned char GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) const override
|
||||
{
|
||||
UNUSED(a_BlockType);
|
||||
UNUSED(a_Meta);
|
||||
UNUSED(a_QueryPosition);
|
||||
UNUSED(a_QueryBlockType);
|
||||
UNUSED(IsLinked);
|
||||
|
||||
return DataForChunk(a_Chunk).GetCachedPowerData(a_Position).PowerLevel;
|
||||
}
|
||||
@ -49,12 +44,11 @@ public:
|
||||
|
||||
if (Power != PreviousPower.PowerLevel)
|
||||
{
|
||||
UpdateAdjustedRelative(a_Chunk, CurrentlyTicking, OffsetYM);
|
||||
UpdateAdjustedRelatives(a_Chunk, CurrentlyTicking, a_Position, RelativeLaterals);
|
||||
UpdateAdjustedRelatives(a_Chunk, CurrentlyTicking, a_Position, RelativeAdjacents);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
|
||||
virtual void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
|
||||
{
|
||||
UNUSED(a_Chunk);
|
||||
UNUSED(a_Position);
|
||||
|
@ -10,18 +10,16 @@
|
||||
|
||||
class cTripwireHookHandler final : public cRedstoneHandler
|
||||
{
|
||||
public:
|
||||
|
||||
virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
|
||||
virtual unsigned char GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) const override
|
||||
{
|
||||
UNUSED(a_BlockType);
|
||||
UNUSED(a_QueryBlockType);
|
||||
UNUSED(a_QueryPosition);
|
||||
|
||||
return (GetPowerLevel(a_Chunk, a_Position, a_Meta) == 15) ? 15 : 0;
|
||||
return (GetPowerLevel(a_Chunk, a_Position, a_Chunk.GetMeta(a_Position)) == 15) ? 15 : 0;
|
||||
}
|
||||
|
||||
static unsigned char GetPowerLevel(cChunk & a_Chunk, Vector3i a_Position, NIBBLETYPE a_Meta)
|
||||
static unsigned char GetPowerLevel(const cChunk & a_Chunk, Vector3i a_Position, NIBBLETYPE a_Meta)
|
||||
{
|
||||
bool FoundActivated = false;
|
||||
const auto FaceToGoTowards = cBlockTripwireHookHandler::MetadataToDirection(a_Meta);
|
||||
@ -104,7 +102,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
virtual void ForValidSourcePositions(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
|
||||
virtual void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, SourceCallback Callback) const override
|
||||
{
|
||||
UNUSED(a_Chunk);
|
||||
UNUSED(a_BlockType);
|
||||
|
@ -10,10 +10,11 @@
|
||||
class cRedstoneSimulatorChunkData
|
||||
{
|
||||
public:
|
||||
virtual ~cRedstoneSimulatorChunkData() = 0;
|
||||
};
|
||||
|
||||
inline cRedstoneSimulatorChunkData::~cRedstoneSimulatorChunkData() {}
|
||||
virtual ~cRedstoneSimulatorChunkData()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -26,11 +27,7 @@ class cRedstoneSimulator:
|
||||
|
||||
public:
|
||||
|
||||
cRedstoneSimulator(cWorld & a_World):
|
||||
Super(a_World)
|
||||
{
|
||||
}
|
||||
using Super::cSimulator;
|
||||
|
||||
virtual cRedstoneSimulatorChunkData * CreateChunkData() = 0;
|
||||
|
||||
};
|
||||
|
@ -10,6 +10,90 @@
|
||||
|
||||
|
||||
|
||||
std::array<Vector3i, 5> cSimulator::GetLinkedOffsets(const Vector3i Offset)
|
||||
{
|
||||
if (Offset.x == -1)
|
||||
{
|
||||
return
|
||||
{
|
||||
{
|
||||
{ -2, 0, 0 },
|
||||
{ -1, -1, 0 },
|
||||
{ -1, 1, 0 },
|
||||
{ -1, 0, -1 },
|
||||
{ -1, 0, 1 }
|
||||
}
|
||||
};
|
||||
}
|
||||
else if (Offset.x == 1)
|
||||
{
|
||||
return
|
||||
{
|
||||
{
|
||||
{ 2, 0, 0 },
|
||||
{ 1, -1, 0 },
|
||||
{ 1, 1, 0 },
|
||||
{ 1, 0, -1 },
|
||||
{ 1, 0, 1 }
|
||||
}
|
||||
};
|
||||
}
|
||||
else if (Offset.y == -1)
|
||||
{
|
||||
return
|
||||
{
|
||||
{
|
||||
{ 0, -2, 0 },
|
||||
{ -1, -1, 0 },
|
||||
{ 1, -1, 0 },
|
||||
{ 0, -1, -1 },
|
||||
{ 0, -1, 1 }
|
||||
}
|
||||
};
|
||||
}
|
||||
else if (Offset.y == 1)
|
||||
{
|
||||
return
|
||||
{
|
||||
{
|
||||
{ 0, 2, 0 },
|
||||
{ -1, 1, 0 },
|
||||
{ 1, 1, 0 },
|
||||
{ 0, 1, -1 },
|
||||
{ 0, 1, 1 }
|
||||
}
|
||||
};
|
||||
}
|
||||
else if (Offset.z == -1)
|
||||
{
|
||||
return
|
||||
{
|
||||
{
|
||||
{ 0, 0, -2 },
|
||||
{ -1, 0, -1 },
|
||||
{ 1, 0, -1 },
|
||||
{ 0, -1, -1 },
|
||||
{ 0, 1, -1 }
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return
|
||||
{
|
||||
{
|
||||
{ 0, 0, 2 },
|
||||
{ -1, 0, 1 },
|
||||
{ 1, 0, 1 },
|
||||
{ 0, -1, 1 },
|
||||
{ 0, 1, 1 }
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cSimulator::WakeUp(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_Block)
|
||||
{
|
||||
ASSERT(a_Chunk.IsValid());
|
||||
|
@ -27,7 +27,7 @@ public:
|
||||
|
||||
virtual ~cSimulator() {}
|
||||
|
||||
// Contains our direct adjacents
|
||||
/** Contains offsets for direct adjacents of any position. */
|
||||
static constexpr std::array<Vector3i, 6> AdjacentOffsets
|
||||
{
|
||||
{
|
||||
@ -40,6 +40,9 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
/** For a given offset from a position, return the offsets that represent the adjacents of the newly offset position, excluding the old position. */
|
||||
static std::array<Vector3i, 5> GetLinkedOffsets(Vector3i Offset);
|
||||
|
||||
protected:
|
||||
|
||||
friend class cChunk; // Calls AddBlock() in its WakeUpSimulators() function, to speed things up
|
||||
|
Loading…
Reference in New Issue
Block a user