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();
|
auto & Simulator = *m_World->GetRedstoneSimulator();
|
||||||
|
|
||||||
// Notify comparators:
|
// Notify comparators:
|
||||||
m_World->WakeUpSimulators(m_Pos + Vector3i(1, 0, 0));
|
m_World->WakeUpSimulators(m_Pos);
|
||||||
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));
|
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -248,10 +248,7 @@ void cChestEntity::OnSlotChanged(cItemGrid * a_Grid, int a_SlotNum)
|
|||||||
auto & Simulator = *m_World->GetRedstoneSimulator();
|
auto & Simulator = *m_World->GetRedstoneSimulator();
|
||||||
|
|
||||||
// Notify comparators:
|
// Notify comparators:
|
||||||
m_World->WakeUpSimulators(m_Pos + Vector3i(1, 0, 0));
|
m_World->WakeUpSimulators(m_Pos);
|
||||||
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));
|
|
||||||
return true;
|
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";
|
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);
|
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());
|
a_WorldInterface.GetBroadcastManager().BroadcastSoundEffect(SoundToPlay, a_BlockPos, 0.5f, 0.6f, a_Player.GetClientHandle());
|
||||||
|
|
||||||
// Queue a button reset (unpress)
|
// Queue a button reset (unpress)
|
||||||
@ -186,7 +186,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
a_World.SetBlockMeta(Pos, Meta | 0x08, false);
|
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
|
// 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);
|
a_World.GetBroadcastManager().BroadcastSoundEffect("block.wood_button.click_on", Pos, 0.5f, 0.6f);
|
||||||
@ -195,27 +195,6 @@ public:
|
|||||||
QueueButtonRelease(a_World, Pos, Type);
|
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:
|
private:
|
||||||
|
|
||||||
/** Schedules a recurring event at appropriate intervals to release a button at a given position.
|
/** 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";
|
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);
|
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);
|
a_World.BroadcastSoundEffect(SoundToPlayOnRelease, a_Position, 0.5f, 0.5f);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
#include "BlockHandler.h"
|
#include "BlockHandler.h"
|
||||||
#include "../Chunk.h"
|
#include "../Chunk.h"
|
||||||
#include "Mixins.h"
|
#include "Mixins.h"
|
||||||
#include "BlockButton.h"
|
|
||||||
#include "BlockSlab.h"
|
#include "BlockSlab.h"
|
||||||
|
|
||||||
|
|
||||||
@ -36,7 +35,7 @@ public:
|
|||||||
NIBBLETYPE Meta = (a_ChunkInterface.GetBlockMeta(a_BlockPos) ^ 0x08);
|
NIBBLETYPE Meta = (a_ChunkInterface.GetBlockMeta(a_BlockPos) ^ 0x08);
|
||||||
|
|
||||||
a_ChunkInterface.SetBlockMeta(a_BlockPos, Meta);
|
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);
|
a_WorldInterface.GetBroadcastManager().BroadcastSoundEffect("block.lever.click", a_BlockPos, 0.5f, (Meta & 0x08) ? 0.6f : 0.5f);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,17 @@
|
|||||||
target_sources(
|
target_sources(
|
||||||
${CMAKE_PROJECT_NAME} PRIVATE
|
${CMAKE_PROJECT_NAME} PRIVATE
|
||||||
|
|
||||||
|
ForEachSourceCallback.cpp
|
||||||
IncrementalRedstoneSimulator.cpp
|
IncrementalRedstoneSimulator.cpp
|
||||||
|
|
||||||
CommandBlockHandler.h
|
CommandBlockHandler.h
|
||||||
DoorHandler.h
|
DoorHandler.h
|
||||||
DropSpenserHandler.h
|
DropSpenserHandler.h
|
||||||
|
ForEachSourceCallback.h
|
||||||
HopperHandler.h
|
HopperHandler.h
|
||||||
IncrementalRedstoneSimulator.h
|
IncrementalRedstoneSimulator.h
|
||||||
RedstoneHandler.h
|
RedstoneHandler.h
|
||||||
RedstoneSimulatorChunkData.h
|
RedstoneSimulatorChunkData.h
|
||||||
SolidBlockHandler.h
|
|
||||||
RedstoneComparatorHandler.h
|
RedstoneComparatorHandler.h
|
||||||
RedstoneRepeaterHandler.h
|
RedstoneRepeaterHandler.h
|
||||||
RedstoneBlockHandler.h
|
RedstoneBlockHandler.h
|
||||||
|
@ -10,16 +10,14 @@
|
|||||||
|
|
||||||
class cCommandBlockHandler final : public cRedstoneHandler
|
class cCommandBlockHandler final : public cRedstoneHandler
|
||||||
{
|
{
|
||||||
public:
|
virtual unsigned char GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) const override
|
||||||
|
|
||||||
virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
|
|
||||||
{
|
{
|
||||||
UNUSED(a_Chunk);
|
UNUSED(a_Chunk);
|
||||||
UNUSED(a_Position);
|
UNUSED(a_Position);
|
||||||
UNUSED(a_BlockType);
|
UNUSED(a_BlockType);
|
||||||
UNUSED(a_Meta);
|
|
||||||
UNUSED(a_QueryPosition);
|
UNUSED(a_QueryPosition);
|
||||||
UNUSED(a_QueryBlockType);
|
UNUSED(a_QueryBlockType);
|
||||||
|
UNUSED(IsLinked);
|
||||||
return 0;
|
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_Chunk);
|
||||||
UNUSED(a_BlockType);
|
UNUSED(a_BlockType);
|
||||||
|
@ -10,16 +10,16 @@
|
|||||||
|
|
||||||
class cDoorHandler final : public cRedstoneHandler
|
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_Chunk);
|
||||||
UNUSED(a_Position);
|
UNUSED(a_Position);
|
||||||
UNUSED(a_BlockType);
|
UNUSED(a_BlockType);
|
||||||
UNUSED(a_Meta);
|
|
||||||
UNUSED(a_QueryPosition);
|
UNUSED(a_QueryPosition);
|
||||||
UNUSED(a_QueryBlockType);
|
UNUSED(a_QueryBlockType);
|
||||||
|
UNUSED(IsLinked);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -27,6 +27,19 @@ public:
|
|||||||
{
|
{
|
||||||
// LOGD("Evaluating dori the door (%d %d %d)", a_Position.x, a_Position.y, a_Position.z);
|
// LOGD("Evaluating dori the door (%d %d %d)", a_Position.x, a_Position.y, a_Position.z);
|
||||||
|
|
||||||
|
if ((a_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());
|
cChunkInterface ChunkInterface(a_Chunk.GetWorld()->GetChunkMap());
|
||||||
const bool ShouldBeOpen = a_PoweringData.PowerLevel != 0;
|
const bool ShouldBeOpen = a_PoweringData.PowerLevel != 0;
|
||||||
const auto AbsolutePosition = cChunkDef::RelativeToAbsolute(a_Position, a_Chunk.GetPos());
|
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_Chunk);
|
||||||
UNUSED(a_BlockType);
|
UNUSED(a_BlockType);
|
||||||
|
@ -10,8 +10,6 @@
|
|||||||
|
|
||||||
class cDropSpenserHandler final : public cRedstoneHandler
|
class cDropSpenserHandler final : public cRedstoneHandler
|
||||||
{
|
{
|
||||||
public:
|
|
||||||
|
|
||||||
inline static bool IsActivated(NIBBLETYPE a_Meta)
|
inline static bool IsActivated(NIBBLETYPE a_Meta)
|
||||||
{
|
{
|
||||||
return (a_Meta & E_META_DROPSPENSER_ACTIVATED) != 0;
|
return (a_Meta & E_META_DROPSPENSER_ACTIVATED) != 0;
|
||||||
@ -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_Chunk);
|
||||||
UNUSED(a_Position);
|
UNUSED(a_Position);
|
||||||
UNUSED(a_BlockType);
|
UNUSED(a_BlockType);
|
||||||
UNUSED(a_Meta);
|
|
||||||
UNUSED(a_QueryPosition);
|
UNUSED(a_QueryPosition);
|
||||||
UNUSED(a_QueryBlockType);
|
UNUSED(a_QueryBlockType);
|
||||||
|
UNUSED(IsLinked);
|
||||||
return 0;
|
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_Chunk);
|
||||||
UNUSED(a_BlockType);
|
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
|
class cHopperHandler final : public cRedstoneHandler
|
||||||
{
|
{
|
||||||
public:
|
virtual unsigned char GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) const override
|
||||||
|
|
||||||
virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
|
|
||||||
{
|
{
|
||||||
UNUSED(a_Chunk);
|
UNUSED(a_Chunk);
|
||||||
UNUSED(a_Position);
|
UNUSED(a_Position);
|
||||||
UNUSED(a_BlockType);
|
UNUSED(a_BlockType);
|
||||||
UNUSED(a_Meta);
|
|
||||||
UNUSED(a_QueryPosition);
|
UNUSED(a_QueryPosition);
|
||||||
UNUSED(a_QueryBlockType);
|
UNUSED(a_QueryBlockType);
|
||||||
|
UNUSED(IsLinked);
|
||||||
return 0;
|
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_Chunk);
|
||||||
UNUSED(a_BlockType);
|
UNUSED(a_BlockType);
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
|
|
||||||
|
|
||||||
#include "Globals.h"
|
#include "Globals.h"
|
||||||
|
|
||||||
#include "IncrementalRedstoneSimulator.h"
|
#include "IncrementalRedstoneSimulator.h"
|
||||||
#include "../../Chunk.h"
|
#include "ForEachSourceCallback.h"
|
||||||
|
|
||||||
#include "CommandBlockHandler.h"
|
#include "CommandBlockHandler.h"
|
||||||
#include "DoorHandler.h"
|
#include "DoorHandler.h"
|
||||||
@ -11,7 +10,6 @@
|
|||||||
#include "RedstoneWireHandler.h"
|
#include "RedstoneWireHandler.h"
|
||||||
#include "RedstoneRepeaterHandler.h"
|
#include "RedstoneRepeaterHandler.h"
|
||||||
#include "RedstoneToggleHandler.h"
|
#include "RedstoneToggleHandler.h"
|
||||||
#include "SolidBlockHandler.h"
|
|
||||||
#include "RedstoneLampHandler.h"
|
#include "RedstoneLampHandler.h"
|
||||||
#include "RedstoneBlockHandler.h"
|
#include "RedstoneBlockHandler.h"
|
||||||
#include "PistonHandler.h"
|
#include "PistonHandler.h"
|
||||||
@ -115,10 +113,6 @@ std::unique_ptr<cRedstoneHandler> cIncrementalRedstoneSimulator::CreateComponent
|
|||||||
return std::make_unique<cDoorHandler>();
|
return std::make_unique<cDoorHandler>();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cBlockInfo::FullyOccupiesVoxel(a_BlockType))
|
|
||||||
{
|
|
||||||
return std::make_unique<cSolidBlockHandler>();
|
|
||||||
}
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -182,42 +176,11 @@ void cIncrementalRedstoneSimulator::ProcessWorkItem(cChunk & Chunk, cChunk & Tic
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
PoweringData Power;
|
ForEachSourceCallback Callback(Chunk, Position, CurrentBlock);
|
||||||
CurrentHandler->ForValidSourcePositions(Chunk, Position, CurrentBlock, CurrentMeta, [&Chunk, Position, CurrentBlock, &Power](Vector3i Location)
|
CurrentHandler->ForValidSourcePositions(Chunk, Position, CurrentBlock, CurrentMeta, Callback);
|
||||||
{
|
|
||||||
if (!cChunk::IsValidHeight(Location.y))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto NeighbourChunk = Chunk.GetRelNeighborChunkAdjustCoords(Location);
|
|
||||||
if ((NeighbourChunk == nullptr) || !NeighbourChunk->IsValid())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
BLOCKTYPE PotentialBlock;
|
|
||||||
NIBBLETYPE PotentialMeta;
|
|
||||||
NeighbourChunk->GetBlockTypeMeta(Location, PotentialBlock, PotentialMeta);
|
|
||||||
|
|
||||||
auto PotentialSourceHandler = GetComponentHandler(PotentialBlock);
|
|
||||||
if (PotentialSourceHandler == nullptr)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const PoweringData PotentialPower(
|
|
||||||
PotentialBlock,
|
|
||||||
PotentialSourceHandler->GetPowerDeliveredToPosition(
|
|
||||||
*NeighbourChunk, Location, PotentialBlock, PotentialMeta,
|
|
||||||
cIncrementalRedstoneSimulatorChunkData::RebaseRelativePosition(Chunk, *NeighbourChunk, Position), CurrentBlock
|
|
||||||
)
|
|
||||||
);
|
|
||||||
Power = std::max(Power, PotentialPower);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Inform the handler to update
|
// 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);
|
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:
|
// Always update redstone devices:
|
||||||
ChunkData.WakeUp(a_Position);
|
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
|
// 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
|
// 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:
|
public:
|
||||||
|
|
||||||
cIncrementalRedstoneSimulator(cWorld & a_World) :
|
using Super::cRedstoneSimulator;
|
||||||
Super(a_World)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static const cRedstoneHandler * GetComponentHandler(BLOCKTYPE a_BlockType);
|
static const cRedstoneHandler * GetComponentHandler(BLOCKTYPE a_BlockType);
|
||||||
|
|
||||||
/** Returns if a block is a mechanism (something that accepts power and does something)
|
private:
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns if a redstone device is always ticked due to influence by its environment */
|
/** Returns if a redstone device is always ticked due to influence by its environment */
|
||||||
inline static bool IsAlwaysTicked(BLOCKTYPE a_Block)
|
inline static bool IsAlwaysTicked(BLOCKTYPE a_Block)
|
||||||
@ -133,7 +86,6 @@ public:
|
|||||||
case E_BLOCK_TRAPDOOR:
|
case E_BLOCK_TRAPDOOR:
|
||||||
case E_BLOCK_TRAPPED_CHEST:
|
case E_BLOCK_TRAPPED_CHEST:
|
||||||
case E_BLOCK_TRIPWIRE_HOOK:
|
case E_BLOCK_TRIPWIRE_HOOK:
|
||||||
case E_BLOCK_TRIPWIRE:
|
|
||||||
case E_BLOCK_WOODEN_BUTTON:
|
case E_BLOCK_WOODEN_BUTTON:
|
||||||
case E_BLOCK_WOODEN_DOOR:
|
case E_BLOCK_WOODEN_DOOR:
|
||||||
case E_BLOCK_WOODEN_PRESSURE_PLATE:
|
case E_BLOCK_WOODEN_PRESSURE_PLATE:
|
||||||
@ -145,8 +97,6 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
virtual void Simulate(float Dt) override {};
|
virtual void Simulate(float Dt) override {};
|
||||||
virtual void SimulateChunk(std::chrono::milliseconds Dt, int ChunkX, int ChunkZ, cChunk * Chunk) override;
|
virtual void SimulateChunk(std::chrono::milliseconds Dt, int ChunkX, int ChunkZ, cChunk * Chunk) override;
|
||||||
|
|
||||||
|
@ -10,16 +10,14 @@
|
|||||||
|
|
||||||
class cNoteBlockHandler: public cRedstoneHandler
|
class cNoteBlockHandler: public cRedstoneHandler
|
||||||
{
|
{
|
||||||
public:
|
virtual unsigned char GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) const override
|
||||||
|
|
||||||
virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
|
|
||||||
{
|
{
|
||||||
UNUSED(a_Chunk);
|
UNUSED(a_Chunk);
|
||||||
UNUSED(a_Position);
|
UNUSED(a_Position);
|
||||||
UNUSED(a_BlockType);
|
UNUSED(a_BlockType);
|
||||||
UNUSED(a_Meta);
|
|
||||||
UNUSED(a_QueryPosition);
|
UNUSED(a_QueryPosition);
|
||||||
UNUSED(a_QueryBlockType);
|
UNUSED(a_QueryBlockType);
|
||||||
|
UNUSED(IsLinked);
|
||||||
return 0;
|
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_Chunk);
|
||||||
UNUSED(a_BlockType);
|
UNUSED(a_BlockType);
|
||||||
|
@ -10,8 +10,6 @@
|
|||||||
|
|
||||||
class cObserverHandler final : public cRedstoneHandler
|
class cObserverHandler final : public cRedstoneHandler
|
||||||
{
|
{
|
||||||
public:
|
|
||||||
|
|
||||||
inline static bool IsOn(NIBBLETYPE a_Meta)
|
inline static bool IsOn(NIBBLETYPE a_Meta)
|
||||||
{
|
{
|
||||||
return (a_Meta & 0x8) == 0x8;
|
return (a_Meta & 0x8) == 0x8;
|
||||||
@ -34,14 +32,10 @@ public:
|
|||||||
return (Previous.PoweringBlock != Observed.PoweringBlock) || (Previous.PowerLevel != Observed.PowerLevel);
|
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))))
|
const auto Meta = a_Chunk.GetMeta(a_Position);
|
||||||
{
|
return (IsOn(Meta) && (a_QueryPosition == (a_Position + cBlockObserverHandler::GetSignalOutputOffset(Meta)))) ? 15 : 0;
|
||||||
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
|
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);
|
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_Chunk);
|
||||||
UNUSED(a_Position);
|
UNUSED(a_Position);
|
||||||
|
@ -10,16 +10,14 @@
|
|||||||
|
|
||||||
class cPistonHandler final: public cRedstoneHandler
|
class cPistonHandler final: public cRedstoneHandler
|
||||||
{
|
{
|
||||||
public:
|
virtual unsigned char GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) const override
|
||||||
|
|
||||||
virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
|
|
||||||
{
|
{
|
||||||
UNUSED(a_Chunk);
|
UNUSED(a_Chunk);
|
||||||
UNUSED(a_Position);
|
UNUSED(a_Position);
|
||||||
UNUSED(a_BlockType);
|
UNUSED(a_BlockType);
|
||||||
UNUSED(a_Meta);
|
|
||||||
UNUSED(a_QueryPosition);
|
UNUSED(a_QueryPosition);
|
||||||
UNUSED(a_QueryBlockType);
|
UNUSED(a_QueryBlockType);
|
||||||
|
UNUSED(IsLinked);
|
||||||
return 0;
|
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
|
// 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_Chunk);
|
||||||
UNUSED(a_BlockType);
|
UNUSED(a_BlockType);
|
||||||
|
@ -9,8 +9,6 @@
|
|||||||
|
|
||||||
class cPoweredRailHandler final : public cRedstoneHandler
|
class cPoweredRailHandler final : public cRedstoneHandler
|
||||||
{
|
{
|
||||||
public:
|
|
||||||
|
|
||||||
static Vector3i GetPoweredRailAdjacentXZCoordinateOffset(NIBBLETYPE a_Meta) // Not in cBlockRailHandler since specific to powered rails
|
static Vector3i GetPoweredRailAdjacentXZCoordinateOffset(NIBBLETYPE a_Meta) // Not in cBlockRailHandler since specific to powered rails
|
||||||
{
|
{
|
||||||
switch (a_Meta & 0x7)
|
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);
|
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))
|
if (((Offset + a_Position) == a_QueryPosition) || ((-Offset + a_Position) == a_QueryPosition))
|
||||||
{
|
{
|
||||||
auto Power = DataForChunk(a_Chunk).GetCachedPowerData(a_Position).PowerLevel;
|
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));
|
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;
|
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_Chunk);
|
||||||
UNUSED(a_Meta);
|
UNUSED(a_Meta);
|
||||||
|
@ -11,19 +11,18 @@
|
|||||||
|
|
||||||
class cPressurePlateHandler final : public cRedstoneHandler
|
class cPressurePlateHandler final : public cRedstoneHandler
|
||||||
{
|
{
|
||||||
public:
|
virtual unsigned char GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) const override
|
||||||
|
|
||||||
virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
|
|
||||||
{
|
{
|
||||||
UNUSED(a_BlockType);
|
UNUSED(a_BlockType);
|
||||||
UNUSED(a_Meta);
|
|
||||||
UNUSED(a_QueryPosition);
|
UNUSED(a_QueryPosition);
|
||||||
UNUSED(a_QueryBlockType);
|
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;
|
unsigned NumberOfEntities = 0;
|
||||||
bool FoundPlayer = false;
|
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
|
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);
|
// 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
|
// Immediately depress plate
|
||||||
a_Chunk.SetMeta(a_Position, E_META_PRESSURE_PLATE_DEPRESSED);
|
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
|
// Not a resting state
|
||||||
@ -137,7 +132,7 @@ public:
|
|||||||
{
|
{
|
||||||
// Yes. Update power
|
// Yes. Update power
|
||||||
ChunkData.SetCachedPowerData(a_Position, PoweringData(a_BlockType, Power));
|
ChunkData.SetCachedPowerData(a_Position, PoweringData(a_BlockType, Power));
|
||||||
return UpdatePlate(a_Chunk, CurrentlyTicking, a_Position);
|
UpdateAdjustedRelatives(a_Chunk, CurrentlyTicking, a_Position, RelativeAdjacents);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@ -159,7 +154,7 @@ public:
|
|||||||
{
|
{
|
||||||
// Yes. Update power
|
// Yes. Update power
|
||||||
ChunkData.SetCachedPowerData(a_Position, PoweringData(a_BlockType, 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
|
// Yes, but player's still on the plate, do nothing
|
||||||
@ -173,10 +168,10 @@ public:
|
|||||||
ChunkData.SetCachedPowerData(a_Position, PoweringData(a_BlockType, Power));
|
ChunkData.SetCachedPowerData(a_Position, PoweringData(a_BlockType, Power));
|
||||||
|
|
||||||
a_Chunk.SetMeta(a_Position, E_META_PRESSURE_PLATE_RAISED);
|
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_Chunk);
|
||||||
UNUSED(a_Position);
|
UNUSED(a_Position);
|
||||||
|
@ -11,14 +11,14 @@ class cRedstoneBlockHandler final : public cRedstoneHandler
|
|||||||
{
|
{
|
||||||
public:
|
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_Chunk);
|
||||||
UNUSED(a_Position);
|
UNUSED(a_Position);
|
||||||
UNUSED(a_BlockType);
|
UNUSED(a_BlockType);
|
||||||
UNUSED(a_Meta);
|
|
||||||
UNUSED(a_QueryPosition);
|
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
|
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);
|
// 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_Chunk);
|
||||||
UNUSED(a_Position);
|
UNUSED(a_Position);
|
||||||
|
@ -10,8 +10,6 @@
|
|||||||
|
|
||||||
class cRedstoneComparatorHandler : public cRedstoneHandler
|
class cRedstoneComparatorHandler : public cRedstoneHandler
|
||||||
{
|
{
|
||||||
public:
|
|
||||||
|
|
||||||
static unsigned char GetFrontPowerLevel(NIBBLETYPE a_Meta, unsigned char a_HighestSidePowerLevel, unsigned char a_HighestRearPowerLevel)
|
static unsigned char GetFrontPowerLevel(NIBBLETYPE a_Meta, unsigned char a_HighestSidePowerLevel, unsigned char a_HighestRearPowerLevel)
|
||||||
{
|
{
|
||||||
if (cBlockComparatorHandler::IsInSubtractionMode(a_Meta))
|
if (cBlockComparatorHandler::IsInSubtractionMode(a_Meta))
|
||||||
@ -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_QueryPosition);
|
||||||
UNUSED(a_QueryBlockType);
|
UNUSED(a_QueryBlockType);
|
||||||
|
|
||||||
|
const auto Meta = a_Chunk.GetMeta(a_Position);
|
||||||
return (
|
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
|
DataForChunk(a_Chunk).GetCachedPowerData(a_Position).PowerLevel : 0
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -71,11 +70,8 @@ public:
|
|||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
BLOCKTYPE RearType;
|
const auto RearType = RearChunk->GetBlock(RearCoordinate);
|
||||||
NIBBLETYPE RearMeta;
|
const auto PotentialSourceHandler = cIncrementalRedstoneSimulator::GetComponentHandler(RearType);
|
||||||
RearChunk->GetBlockTypeMeta(RearCoordinate, RearType, RearMeta);
|
|
||||||
|
|
||||||
auto PotentialSourceHandler = cIncrementalRedstoneSimulator::GetComponentHandler(RearType);
|
|
||||||
if (PotentialSourceHandler == nullptr)
|
if (PotentialSourceHandler == nullptr)
|
||||||
{
|
{
|
||||||
return SignalStrength;
|
return SignalStrength;
|
||||||
@ -84,8 +80,8 @@ public:
|
|||||||
return std::max(
|
return std::max(
|
||||||
SignalStrength,
|
SignalStrength,
|
||||||
PotentialSourceHandler->GetPowerDeliveredToPosition(
|
PotentialSourceHandler->GetPowerDeliveredToPosition(
|
||||||
*RearChunk, RearCoordinate, RearType, RearMeta,
|
*RearChunk, RearCoordinate, RearType,
|
||||||
cIncrementalRedstoneSimulatorChunkData::RebaseRelativePosition(a_Chunk, *RearChunk, Position), BlockType
|
cIncrementalRedstoneSimulatorChunkData::RebaseRelativePosition(a_Chunk, *RearChunk, Position), BlockType, false
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -110,14 +106,18 @@ public:
|
|||||||
{
|
{
|
||||||
Data.m_MechanismDelays[a_Position] = std::make_pair(1, bool());
|
Data.m_MechanismDelays[a_Position] = std::make_pair(1, bool());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
int DelayTicks;
|
int DelayTicks;
|
||||||
std::tie(DelayTicks, std::ignore) = *DelayInfo;
|
std::tie(DelayTicks, std::ignore) = *DelayInfo;
|
||||||
|
|
||||||
if (DelayTicks == 0)
|
if (DelayTicks != 0)
|
||||||
{
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const auto RearPower = GetPowerLevel(a_Chunk, a_Position, a_BlockType, a_Meta);
|
const auto RearPower = GetPowerLevel(a_Chunk, a_Position, a_BlockType, a_Meta);
|
||||||
const auto FrontPower = GetFrontPowerLevel(a_Meta, a_PoweringData.PowerLevel, RearPower);
|
const auto FrontPower = GetFrontPowerLevel(a_Meta, a_PoweringData.PowerLevel, RearPower);
|
||||||
const auto NewMeta = (FrontPower > 0) ? (a_Meta | 0x8) : (a_Meta & 0x7);
|
const auto NewMeta = (FrontPower > 0) ? (a_Meta | 0x8) : (a_Meta & 0x7);
|
||||||
@ -129,12 +129,10 @@ public:
|
|||||||
Data.m_MechanismDelays.erase(a_Position);
|
Data.m_MechanismDelays.erase(a_Position);
|
||||||
|
|
||||||
// Assume that an update (to front power) is needed:
|
// Assume that an update (to front power) is needed:
|
||||||
UpdateAdjustedRelative(a_Chunk, CurrentlyTicking, cBlockComparatorHandler::GetFrontCoordinate(a_Position, a_Meta & 0x3));
|
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_Chunk);
|
||||||
UNUSED(a_BlockType);
|
UNUSED(a_BlockType);
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../../Chunk.h"
|
#include "../../Chunk.h"
|
||||||
|
#include "ForEachSourceCallback.h"
|
||||||
#include "RedstoneSimulatorChunkData.h"
|
#include "RedstoneSimulatorChunkData.h"
|
||||||
|
|
||||||
|
|
||||||
@ -15,71 +16,55 @@ public:
|
|||||||
cRedstoneHandler() = default;
|
cRedstoneHandler() = default;
|
||||||
DISALLOW_COPY_AND_ASSIGN(cRedstoneHandler);
|
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 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
|
// Force a virtual destructor
|
||||||
virtual ~cRedstoneHandler() {}
|
virtual ~cRedstoneHandler() {}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
template <class Container>
|
inline static auto & DataForChunk(const cChunk & a_Chunk)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
return *static_cast<cIncrementalRedstoneSimulatorChunkData *>(a_Chunk.GetRedstoneSimulatorData());
|
return *static_cast<cIncrementalRedstoneSimulatorChunkData *>(a_Chunk.GetRedstoneSimulatorData());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename... ArrayTypes>
|
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>
|
template <typename ArrayType>
|
||||||
static void UpdateAdjustedRelatives(cChunk & From, cChunk & To, const Vector3i Position, const ArrayType & Relative, const ArrayTypes &... Relatives)
|
static void UpdateAdjustedRelatives(const cChunk & From, const cChunk & To, const Vector3i Position, const ArrayType & Relative)
|
||||||
{
|
{
|
||||||
for (const auto Offset : 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>
|
||||||
}
|
static void InvokeForAdjustedRelatives(SourceCallback Callback, const Vector3i Position, const ArrayType & Relative)
|
||||||
|
|
||||||
template <typename ArrayType, typename... ArrayTypes>
|
|
||||||
static void InvokeForAdjustedRelatives(SourceCallback Callback, const Vector3i Position, const ArrayType & Relative, const ArrayTypes &... Relatives)
|
|
||||||
{
|
{
|
||||||
for (const auto Offset : Relative)
|
for (const auto Offset : Relative)
|
||||||
{
|
{
|
||||||
Callback(Position + Offset);
|
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
|
inline static std::array<Vector3i, 6> RelativeAdjacents
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
@ -101,14 +86,4 @@ protected:
|
|||||||
{ 0, 0, -1 },
|
{ 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
|
class cRedstoneLampHandler final : public cRedstoneHandler
|
||||||
{
|
{
|
||||||
public:
|
|
||||||
|
|
||||||
inline static bool IsOn(BLOCKTYPE a_BlockType)
|
inline static bool IsOn(BLOCKTYPE a_BlockType)
|
||||||
{
|
{
|
||||||
return (a_BlockType == E_BLOCK_REDSTONE_LAMP_ON);
|
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;
|
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_Chunk);
|
||||||
UNUSED(a_Meta);
|
UNUSED(a_Meta);
|
||||||
|
@ -8,16 +8,23 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
class cRedstoneRepeaterHandler:
|
class cRedstoneRepeaterHandler final : public cRedstoneHandler
|
||||||
public cRedstoneHandler
|
|
||||||
{
|
{
|
||||||
using Super = cRedstoneHandler;
|
virtual unsigned char GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) const override
|
||||||
|
|
||||||
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
|
|
||||||
{
|
{
|
||||||
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
|
virtual void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override
|
||||||
@ -45,15 +52,19 @@ public:
|
|||||||
{
|
{
|
||||||
Data.m_MechanismDelays[a_Position] = std::make_pair((((a_Meta & 0xC) >> 0x2) + 1), ShouldBeOn);
|
Data.m_MechanismDelays[a_Position] = std::make_pair((((a_Meta & 0xC) >> 0x2) + 1), ShouldBeOn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
int DelayTicks;
|
int DelayTicks;
|
||||||
bool ShouldPowerOn;
|
bool ShouldPowerOn;
|
||||||
std::tie(DelayTicks, ShouldPowerOn) = *DelayInfo;
|
std::tie(DelayTicks, ShouldPowerOn) = *DelayInfo;
|
||||||
|
|
||||||
if (DelayTicks == 0)
|
if (DelayTicks != 0)
|
||||||
{
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const auto NewType = ShouldPowerOn ? E_BLOCK_REDSTONE_REPEATER_ON : E_BLOCK_REDSTONE_REPEATER_OFF;
|
const auto NewType = ShouldPowerOn ? E_BLOCK_REDSTONE_REPEATER_ON : E_BLOCK_REDSTONE_REPEATER_OFF;
|
||||||
a_Chunk.FastSetBlock(a_Position, NewType, a_Meta);
|
a_Chunk.FastSetBlock(a_Position, NewType, a_Meta);
|
||||||
Data.m_MechanismDelays.erase(a_Position);
|
Data.m_MechanismDelays.erase(a_Position);
|
||||||
@ -63,19 +74,14 @@ public:
|
|||||||
// FastSetBlock doesn't wake simulators, so manually update ourselves:
|
// FastSetBlock doesn't wake simulators, so manually update ourselves:
|
||||||
Update(a_Chunk, CurrentlyTicking, a_Position, NewType, a_Meta, a_PoweringData);
|
Update(a_Chunk, CurrentlyTicking, a_Position, NewType, a_Meta, a_PoweringData);
|
||||||
|
|
||||||
UpdateAdjustedRelative(a_Chunk, CurrentlyTicking, a_Position + cBlockRedstoneRepeaterHandler::GetFrontCoordinateOffset(a_Meta));
|
UpdateAdjustedRelative(a_Chunk, CurrentlyTicking, a_Position, cBlockRedstoneRepeaterHandler::GetFrontCoordinateOffset(a_Meta));
|
||||||
UpdateAdjustedRelatives(a_Chunk, CurrentlyTicking, a_Position + cBlockRedstoneRepeaterHandler::GetFrontCoordinateOffset(a_Meta), 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
|
||||||
{
|
{
|
||||||
Callback(cBlockRedstoneRepeaterHandler::GetRearCoordinateOffset(a_Meta) + a_Position);
|
Callback(cBlockRedstoneRepeaterHandler::GetRearCoordinateOffset(a_Meta) + a_Position);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
inline static bool IsOn(BLOCKTYPE a_Block)
|
inline static bool IsOn(BLOCKTYPE a_Block)
|
||||||
{
|
{
|
||||||
return (a_Block == E_BLOCK_REDSTONE_REPEATER_ON);
|
return (a_Block == E_BLOCK_REDSTONE_REPEATER_ON);
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include <stack>
|
#include <stack>
|
||||||
|
|
||||||
#include "../RedstoneSimulator.h"
|
#include "../RedstoneSimulator.h"
|
||||||
|
#include "../../Chunk.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -53,7 +54,7 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
class cIncrementalRedstoneSimulatorChunkData : public cRedstoneSimulatorChunkData
|
class cIncrementalRedstoneSimulatorChunkData final : public cRedstoneSimulatorChunkData
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@ -90,6 +91,7 @@ public:
|
|||||||
m_CachedPowerLevels.erase(Position);
|
m_CachedPowerLevels.erase(Position);
|
||||||
m_MechanismDelays.erase(Position);
|
m_MechanismDelays.erase(Position);
|
||||||
AlwaysTickedPositions.erase(Position);
|
AlwaysTickedPositions.erase(Position);
|
||||||
|
WireStates.erase(Position);
|
||||||
}
|
}
|
||||||
|
|
||||||
PoweringData ExchangeUpdateOncePowerData(const Vector3i & a_Position, PoweringData a_PoweringData)
|
PoweringData ExchangeUpdateOncePowerData(const Vector3i & a_Position, PoweringData a_PoweringData)
|
||||||
@ -105,7 +107,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Adjust From-relative coordinates into To-relative coordinates. */
|
/** 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
|
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;
|
std::unordered_set<Vector3i, VectorHasher<int>> AlwaysTickedPositions;
|
||||||
|
|
||||||
/** Structure storing position of mechanism + it's delay ticks (countdown) & if to power on */
|
/** Structure storing position of mechanism + it's delay ticks (countdown) & if to power on. */
|
||||||
std::unordered_map<Vector3i, std::pair<int, bool>, VectorHasher<int>> m_MechanismDelays;
|
std::unordered_map<Vector3i, std::pair<int, bool>, VectorHasher<int>> m_MechanismDelays;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -11,9 +11,7 @@
|
|||||||
|
|
||||||
class cRedstoneToggleHandler final : public cRedstoneHandler
|
class cRedstoneToggleHandler final : public cRedstoneHandler
|
||||||
{
|
{
|
||||||
public:
|
inline static Vector3i GetOffsetAttachedTo(Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta)
|
||||||
|
|
||||||
inline static Vector3i GetPositionAttachedTo(Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta)
|
|
||||||
{
|
{
|
||||||
switch (a_BlockType)
|
switch (a_BlockType)
|
||||||
{
|
{
|
||||||
@ -22,13 +20,13 @@ public:
|
|||||||
switch (a_Meta & 0x7)
|
switch (a_Meta & 0x7)
|
||||||
{
|
{
|
||||||
case 0x0:
|
case 0x0:
|
||||||
case 0x7: return { a_Position + Vector3i(0, 1, 0) };
|
case 0x7: return { 0, 1, 0 };
|
||||||
case 0x1: return { a_Position + Vector3i(-1, 0, 0) };
|
case 0x1: return { -1, 0, 0 };
|
||||||
case 0x2: return { a_Position + Vector3i(1, 0, 0) };
|
case 0x2: return { 1, 0, 0 };
|
||||||
case 0x3: return { a_Position + Vector3i(0, 0, -1) };
|
case 0x3: return { 0, 0, -1 };
|
||||||
case 0x4: return { a_Position + Vector3i(0, 0, 1) };
|
case 0x4: return { 0, 0, 1 };
|
||||||
case 0x5:
|
case 0x5:
|
||||||
case 0x6: return { a_Position + Vector3i(0, -1, 0) };
|
case 0x6: return { 0, -1, 0 };
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
ASSERT(!"Unhandled lever metadata!");
|
ASSERT(!"Unhandled lever metadata!");
|
||||||
@ -41,12 +39,12 @@ public:
|
|||||||
{
|
{
|
||||||
switch (a_Meta & 0x7)
|
switch (a_Meta & 0x7)
|
||||||
{
|
{
|
||||||
case 0x0: return { a_Position + Vector3i(0, 1, 0) };
|
case 0x0: return { 0, 1, 0 };
|
||||||
case 0x1: return { a_Position + Vector3i(-1, 0, 0) };
|
case 0x1: return { -1, 0, 0 };
|
||||||
case 0x2: return { a_Position + Vector3i(1, 0, 0) };
|
case 0x2: return { 1, 0, 0 };
|
||||||
case 0x3: return { a_Position + Vector3i(0, 0, -1) };
|
case 0x3: return { 0, 0, -1 };
|
||||||
case 0x4: return { a_Position + Vector3i(0, 0, 1) };
|
case 0x4: return { 0, 0, 1 };
|
||||||
case 0x5: return { a_Position + Vector3i(0, -1, 0) };
|
case 0x5: return { 0, -1, 0 };
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
ASSERT(!"Unhandled button metadata!");
|
ASSERT(!"Unhandled button metadata!");
|
||||||
@ -62,16 +60,21 @@ 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);
|
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)
|
static unsigned char GetPowerLevel(BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta)
|
||||||
{
|
{
|
||||||
switch (a_BlockType)
|
switch (a_BlockType)
|
||||||
@ -92,7 +95,7 @@ public:
|
|||||||
// LOGD("Evaluating templatio<> the lever/button (%d %d %d)", a_Position.x, a_Position.y, a_Position.z);
|
// LOGD("Evaluating templatio<> the lever/button (%d %d %d)", a_Position.x, a_Position.y, a_Position.z);
|
||||||
}
|
}
|
||||||
|
|
||||||
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_Chunk);
|
||||||
UNUSED(a_Position);
|
UNUSED(a_Position);
|
||||||
|
@ -9,14 +9,12 @@
|
|||||||
|
|
||||||
class cRedstoneTorchHandler final : public cRedstoneHandler
|
class cRedstoneTorchHandler final : public cRedstoneHandler
|
||||||
{
|
{
|
||||||
public:
|
|
||||||
|
|
||||||
inline static bool IsOn(BLOCKTYPE a_Block)
|
inline static bool IsOn(BLOCKTYPE a_Block)
|
||||||
{
|
{
|
||||||
return (a_Block == E_BLOCK_REDSTONE_TORCH_ON);
|
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)
|
switch (a_Meta)
|
||||||
{
|
{
|
||||||
@ -33,19 +31,22 @@ 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 (
|
if (
|
||||||
IsOn(a_BlockType) &&
|
!IsOn(a_BlockType) ||
|
||||||
(a_QueryPosition != (a_Position + GetOffsetAttachedTo(a_Position, a_Meta))) &&
|
(QueryOffset == GetOffsetAttachedTo(a_Chunk.GetMeta(a_Position))) ||
|
||||||
(cIncrementalRedstoneSimulator::IsMechanism(a_QueryBlockType) || (cBlockInfo::FullyOccupiesVoxel(a_QueryBlockType) && (a_QueryPosition == (a_Position + OffsetYP))))
|
(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
|
virtual void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override
|
||||||
{
|
{
|
||||||
// LOGD("Evaluating torchy the redstone torch (%i %i %i)", a_Position.x, a_Position.y, a_Position.z);
|
// LOGD("Evaluating torchy the redstone torch (%i %i %i)", a_Position.x, a_Position.y, a_Position.z);
|
||||||
@ -55,14 +56,15 @@ public:
|
|||||||
|
|
||||||
if (DelayInfo == nullptr)
|
if (DelayInfo == nullptr)
|
||||||
{
|
{
|
||||||
bool ShouldBeOn = (a_PoweringData.PowerLevel == 0);
|
const bool ShouldBeOn = (a_PoweringData.PowerLevel == 0);
|
||||||
if (ShouldBeOn != IsOn(a_BlockType))
|
if (ShouldBeOn != IsOn(a_BlockType))
|
||||||
{
|
{
|
||||||
Data.m_MechanismDelays[a_Position] = std::make_pair(1, ShouldBeOn);
|
Data.m_MechanismDelays[a_Position] = std::make_pair(1, ShouldBeOn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
int DelayTicks;
|
int DelayTicks;
|
||||||
bool ShouldPowerOn;
|
bool ShouldPowerOn;
|
||||||
std::tie(DelayTicks, ShouldPowerOn) = *DelayInfo;
|
std::tie(DelayTicks, ShouldPowerOn) = *DelayInfo;
|
||||||
@ -72,23 +74,24 @@ public:
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
a_Chunk.SetBlock(a_Position, ShouldPowerOn ? E_BLOCK_REDSTONE_TORCH_ON : E_BLOCK_REDSTONE_TORCH_OFF, a_Meta);
|
a_Chunk.FastSetBlock(a_Position, ShouldPowerOn ? E_BLOCK_REDSTONE_TORCH_ON : E_BLOCK_REDSTONE_TORCH_OFF, a_Meta);
|
||||||
Data.m_MechanismDelays.erase(a_Position);
|
Data.m_MechanismDelays.erase(a_Position);
|
||||||
|
|
||||||
for (const auto Adjacent : RelativeAdjacents)
|
for (const auto Adjacent : RelativeAdjacents)
|
||||||
{
|
{
|
||||||
if (Adjacent != GetOffsetAttachedTo(a_Position, a_Meta))
|
// Update all adjacents (including linked power positions)
|
||||||
|
// apart from our attachment, which can't possibly need an update:
|
||||||
|
if (Adjacent != GetOffsetAttachedTo(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_Chunk);
|
||||||
UNUSED(a_BlockType);
|
UNUSED(a_BlockType);
|
||||||
Callback(a_Position + GetOffsetAttachedTo(a_Position, a_Meta));
|
Callback(a_Position + GetOffsetAttachedTo(a_Meta));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "RedstoneHandler.h"
|
#include "RedstoneHandler.h"
|
||||||
|
#include "../../Registries/Blocks.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -9,8 +10,162 @@
|
|||||||
|
|
||||||
class cRedstoneWireHandler final : public cRedstoneHandler
|
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:
|
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)
|
inline static bool IsDirectlyConnectingMechanism(BLOCKTYPE a_Block, NIBBLETYPE a_BlockMeta, const Vector3i a_Offset)
|
||||||
{
|
{
|
||||||
switch (a_Block)
|
switch (a_Block)
|
||||||
@ -30,6 +185,7 @@ public:
|
|||||||
}
|
}
|
||||||
case E_BLOCK_ACTIVE_COMPARATOR:
|
case E_BLOCK_ACTIVE_COMPARATOR:
|
||||||
case E_BLOCK_INACTIVE_COMPARATOR:
|
case E_BLOCK_INACTIVE_COMPARATOR:
|
||||||
|
case E_BLOCK_BLOCK_OF_REDSTONE:
|
||||||
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: return true;
|
||||||
@ -37,170 +193,135 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class OffsetCallback>
|
virtual unsigned char GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) const override
|
||||||
static bool ForTerracingConnectionOffsets(cChunk & a_Chunk, const Vector3i a_Position, OffsetCallback Callback)
|
|
||||||
{
|
{
|
||||||
const auto YPTerraceBlock = a_Chunk.GetBlock(a_Position + OffsetYP);
|
// Starts off as the wire's meta value, modified appropriately and returned
|
||||||
const bool IsYPTerracingBlocked = cBlockInfo::IsSolid(YPTerraceBlock) && !cBlockInfo::IsTransparent(YPTerraceBlock);
|
auto Power = a_Chunk.GetMeta(a_Position);
|
||||||
|
const auto QueryOffset = a_QueryPosition - a_Position;
|
||||||
for (const auto Adjacent : RelativeLaterals)
|
|
||||||
{
|
|
||||||
// All laterals are counted as terracing, duh
|
|
||||||
if (Callback(Adjacent))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
if (
|
||||||
BLOCKTYPE YPBlock;
|
(QueryOffset == OffsetYP) || // Wires do not power things above them
|
||||||
|
(IsLinked && (a_QueryBlockType == E_BLOCK_REDSTONE_WIRE)) // Nor do they link power other wires
|
||||||
// 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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (a_QueryBlockType == E_BLOCK_REDSTONE_WIRE)
|
if (QueryOffset == OffsetYM)
|
||||||
{
|
{
|
||||||
// For mechanisms, wire of power one will still power them
|
// Wires always deliver power to the block underneath
|
||||||
// But for wire-to-wire connections, power level decreases by 1
|
return Power;
|
||||||
return (a_Meta != 0) ? --a_Meta : a_Meta;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wires always deliver power to the block underneath, and any directly connecting mechanisms
|
const auto & Data = DataForChunk(a_Chunk);
|
||||||
if (
|
const auto Block = Data.WireStates.find(a_Position)->second;
|
||||||
NIBBLETYPE QueryMeta;
|
|
||||||
|
|
||||||
(a_QueryPosition == (a_Position + OffsetYM)) ||
|
DoWithDirectionState(QueryOffset, Block, [a_QueryBlockType, &Power](const auto Left, const auto Front, const auto Right)
|
||||||
(a_Chunk.UnboundedRelGetBlockMeta(a_QueryPosition, QueryMeta) && IsDirectlyConnectingMechanism(a_QueryBlockType, QueryMeta, a_QueryPosition - a_Position))
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
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)>;
|
||||||
|
|
||||||
|
// Wires always deliver power to any directly connecting mechanisms:
|
||||||
|
if (Front != FrontState::None)
|
||||||
|
{
|
||||||
|
if ((a_QueryBlockType == E_BLOCK_REDSTONE_WIRE) && (Power != 0))
|
||||||
|
{
|
||||||
|
// For mechanisms, wire of power one will still power them
|
||||||
|
// But for wire-to-wire connections, power level decreases by 1:
|
||||||
|
Power--;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Okay, we do not directly connect to the wire.
|
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.
|
1. If there are no DC mechanisms at all, the wire powers all laterals. Great, left and right are both None.
|
||||||
If there is one DC mechanism, the wire "goes straight" along the axis of the wire and mechanism.
|
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.
|
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.
|
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))
|
||||||
Vector3i PotentialOffset;
|
|
||||||
bool FoundOneBorderingMechanism = false;
|
|
||||||
|
|
||||||
if (
|
|
||||||
ForTerracingConnectionOffsets(a_Chunk, a_Position, [&a_Chunk, a_Position, &FoundOneBorderingMechanism, &PotentialOffset](const Vector3i Offset)
|
|
||||||
{
|
{
|
||||||
BLOCKTYPE Block;
|
|
||||||
NIBBLETYPE Meta;
|
|
||||||
|
|
||||||
if (
|
|
||||||
!a_Chunk.UnboundedRelGetBlock(Offset + a_Position, Block, Meta) ||
|
|
||||||
!IsDirectlyConnectingMechanism(Block, Meta, Offset)
|
|
||||||
)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FoundOneBorderingMechanism)
|
|
||||||
{
|
|
||||||
// Case 3
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Potential case 2
|
|
||||||
FoundOneBorderingMechanism = true;
|
|
||||||
PotentialOffset = { -Offset.x, 0, -Offset.z };
|
|
||||||
|
|
||||||
return false;
|
|
||||||
})
|
|
||||||
)
|
|
||||||
{
|
|
||||||
// Case 3
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FoundOneBorderingMechanism && (a_QueryPosition != (a_Position + PotentialOffset)))
|
|
||||||
{
|
|
||||||
// Case 2 fail
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Case 1
|
// Case 1
|
||||||
// Case 2 success
|
// Case 2
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
return a_Meta;
|
// Case 3
|
||||||
|
Power = 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
return Power;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override
|
virtual void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, PoweringData a_PoweringData) const override
|
||||||
{
|
{
|
||||||
// LOGD("Evaluating dusty the wire (%d %d %d) %i", a_Position.x, a_Position.y, a_Position.z, a_PoweringData.PowerLevel);
|
// LOGD("Evaluating dusty the wire (%d %d %d) %i", a_Position.x, a_Position.y, a_Position.z, a_PoweringData.PowerLevel);
|
||||||
|
|
||||||
if (a_Meta != a_PoweringData.PowerLevel)
|
if (a_Meta == a_PoweringData.PowerLevel)
|
||||||
{
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
a_Chunk.SetMeta(a_Position, a_PoweringData.PowerLevel);
|
a_Chunk.SetMeta(a_Position, a_PoweringData.PowerLevel);
|
||||||
|
|
||||||
// Notify block below us to update:
|
// Notify all positions, sans YP, to update:
|
||||||
UpdateAdjustedRelative(a_Chunk, CurrentlyTicking, a_Position + OffsetYM);
|
for (const auto Offset : RelativeAdjacents)
|
||||||
|
|
||||||
// Notify all terracing positions:
|
|
||||||
ForTerracingConnectionOffsets(a_Chunk, a_Position, [&a_Chunk, &CurrentlyTicking, a_Position](const Vector3i Offset)
|
|
||||||
{
|
{
|
||||||
UpdateAdjustedRelative(a_Chunk, CurrentlyTicking, a_Position + Offset);
|
if (Offset == OffsetYP)
|
||||||
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_BlockType);
|
||||||
UNUSED(a_Meta);
|
UNUSED(a_Meta);
|
||||||
|
|
||||||
Callback(a_Position + OffsetYP);
|
Callback(a_Position + OffsetYP);
|
||||||
Callback(a_Position + OffsetYM);
|
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);
|
const auto Relative = a_Position + Offset;
|
||||||
return false;
|
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
|
class cSmallGateHandler final : public cRedstoneHandler
|
||||||
{
|
{
|
||||||
public:
|
virtual unsigned char GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) const override
|
||||||
|
|
||||||
virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
|
|
||||||
{
|
{
|
||||||
UNUSED(a_Chunk);
|
UNUSED(a_Chunk);
|
||||||
UNUSED(a_Position);
|
UNUSED(a_Position);
|
||||||
UNUSED(a_BlockType);
|
UNUSED(a_BlockType);
|
||||||
UNUSED(a_Meta);
|
|
||||||
UNUSED(a_QueryPosition);
|
UNUSED(a_QueryPosition);
|
||||||
UNUSED(a_QueryBlockType);
|
UNUSED(a_QueryBlockType);
|
||||||
|
UNUSED(IsLinked);
|
||||||
return 0;
|
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_Chunk);
|
||||||
UNUSED(a_BlockType);
|
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
|
class cTNTHandler final : public cRedstoneHandler
|
||||||
{
|
{
|
||||||
public:
|
virtual unsigned char GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) const override
|
||||||
|
|
||||||
virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
|
|
||||||
{
|
{
|
||||||
UNUSED(a_Chunk);
|
UNUSED(a_Chunk);
|
||||||
UNUSED(a_Position);
|
UNUSED(a_Position);
|
||||||
UNUSED(a_BlockType);
|
UNUSED(a_BlockType);
|
||||||
UNUSED(a_Meta);
|
|
||||||
UNUSED(a_QueryPosition);
|
UNUSED(a_QueryPosition);
|
||||||
UNUSED(a_QueryBlockType);
|
UNUSED(a_QueryBlockType);
|
||||||
|
UNUSED(IsLinked);
|
||||||
return 0;
|
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_Chunk);
|
||||||
UNUSED(a_BlockType);
|
UNUSED(a_BlockType);
|
||||||
|
@ -8,19 +8,14 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
class cTrappedChestHandler:
|
class cTrappedChestHandler final : public cRedstoneHandler
|
||||||
public cRedstoneHandler
|
|
||||||
{
|
{
|
||||||
using Super = cRedstoneHandler;
|
virtual unsigned char GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) const override
|
||||||
|
|
||||||
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
|
|
||||||
{
|
{
|
||||||
UNUSED(a_BlockType);
|
UNUSED(a_BlockType);
|
||||||
UNUSED(a_Meta);
|
|
||||||
UNUSED(a_QueryPosition);
|
UNUSED(a_QueryPosition);
|
||||||
UNUSED(a_QueryBlockType);
|
UNUSED(a_QueryBlockType);
|
||||||
|
UNUSED(IsLinked);
|
||||||
|
|
||||||
return DataForChunk(a_Chunk).GetCachedPowerData(a_Position).PowerLevel;
|
return DataForChunk(a_Chunk).GetCachedPowerData(a_Position).PowerLevel;
|
||||||
}
|
}
|
||||||
@ -49,12 +44,11 @@ public:
|
|||||||
|
|
||||||
if (Power != PreviousPower.PowerLevel)
|
if (Power != PreviousPower.PowerLevel)
|
||||||
{
|
{
|
||||||
UpdateAdjustedRelative(a_Chunk, CurrentlyTicking, OffsetYM);
|
UpdateAdjustedRelatives(a_Chunk, CurrentlyTicking, a_Position, RelativeAdjacents);
|
||||||
UpdateAdjustedRelatives(a_Chunk, CurrentlyTicking, a_Position, RelativeLaterals);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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_Chunk);
|
||||||
UNUSED(a_Position);
|
UNUSED(a_Position);
|
||||||
|
@ -10,18 +10,16 @@
|
|||||||
|
|
||||||
class cTripwireHookHandler final : public cRedstoneHandler
|
class cTripwireHookHandler final : public cRedstoneHandler
|
||||||
{
|
{
|
||||||
public:
|
virtual unsigned char GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked) const override
|
||||||
|
|
||||||
virtual unsigned char GetPowerDeliveredToPosition(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType) const override
|
|
||||||
{
|
{
|
||||||
UNUSED(a_BlockType);
|
UNUSED(a_BlockType);
|
||||||
UNUSED(a_QueryBlockType);
|
UNUSED(a_QueryBlockType);
|
||||||
UNUSED(a_QueryPosition);
|
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;
|
bool FoundActivated = false;
|
||||||
const auto FaceToGoTowards = cBlockTripwireHookHandler::MetadataToDirection(a_Meta);
|
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_Chunk);
|
||||||
UNUSED(a_BlockType);
|
UNUSED(a_BlockType);
|
||||||
|
@ -10,10 +10,11 @@
|
|||||||
class cRedstoneSimulatorChunkData
|
class cRedstoneSimulatorChunkData
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~cRedstoneSimulatorChunkData() = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
inline cRedstoneSimulatorChunkData::~cRedstoneSimulatorChunkData() {}
|
virtual ~cRedstoneSimulatorChunkData()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -26,11 +27,7 @@ class cRedstoneSimulator:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
cRedstoneSimulator(cWorld & a_World):
|
using Super::cSimulator;
|
||||||
Super(a_World)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual cRedstoneSimulatorChunkData * CreateChunkData() = 0;
|
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)
|
void cSimulator::WakeUp(cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_Block)
|
||||||
{
|
{
|
||||||
ASSERT(a_Chunk.IsValid());
|
ASSERT(a_Chunk.IsValid());
|
||||||
|
@ -27,7 +27,7 @@ public:
|
|||||||
|
|
||||||
virtual ~cSimulator() {}
|
virtual ~cSimulator() {}
|
||||||
|
|
||||||
// Contains our direct adjacents
|
/** Contains offsets for direct adjacents of any position. */
|
||||||
static constexpr std::array<Vector3i, 6> AdjacentOffsets
|
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:
|
protected:
|
||||||
|
|
||||||
friend class cChunk; // Calls AddBlock() in its WakeUpSimulators() function, to speed things up
|
friend class cChunk; // Calls AddBlock() in its WakeUpSimulators() function, to speed things up
|
||||||
|
Loading…
Reference in New Issue
Block a user