Comparators
This commit is contained in:
parent
a54fa15bc6
commit
de5b1401f8
@ -91,7 +91,7 @@ public:
|
||||
|
||||
BLOCKTYPE GetBlockType(void) const { return m_BlockType; }
|
||||
|
||||
cWorld * GetWorld(void) const {return m_World; }
|
||||
cWorld * GetWorld(void) const { return m_World; }
|
||||
|
||||
int GetChunkX(void) const { return FAST_FLOOR_DIV(m_PosX, cChunkDef::Width); }
|
||||
int GetChunkZ(void) const { return FAST_FLOOR_DIV(m_PosZ, cChunkDef::Width); }
|
||||
|
@ -53,6 +53,24 @@ private:
|
||||
|
||||
/** Number of players who currently have this chest open */
|
||||
int m_NumActivePlayers;
|
||||
|
||||
/** cItemGrid::cListener overrides: */
|
||||
virtual void OnSlotChanged(cItemGrid * a_Grid, int a_SlotNum)
|
||||
{
|
||||
UNUSED(a_SlotNum);
|
||||
ASSERT(a_Grid == &m_Contents);
|
||||
if (m_World != nullptr)
|
||||
{
|
||||
if (GetWindow() != nullptr)
|
||||
{
|
||||
GetWindow()->BroadcastWholeWindow();
|
||||
}
|
||||
|
||||
m_World->MarkChunkDirty(GetChunkX(), GetChunkZ());
|
||||
m_World->MarkRedstoneDirty(GetChunkX(), GetChunkZ());
|
||||
}
|
||||
}
|
||||
|
||||
} ; // tolua_export
|
||||
|
||||
|
||||
|
@ -64,6 +64,85 @@ public:
|
||||
a_BlockMeta = cBlockRedstoneRepeaterHandler::RepeaterRotationToMetaData(a_Player->GetYaw());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
inline static Vector3i GetSideCoordinate(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_Meta, bool a_bInverse)
|
||||
{
|
||||
if (!a_bInverse)
|
||||
{
|
||||
switch (a_Meta)
|
||||
{
|
||||
case 0x0: a_BlockX++; break;
|
||||
case 0x1: a_BlockZ--; break;
|
||||
case 0x2: a_BlockX--; break;
|
||||
case 0x3: a_BlockZ++; break;
|
||||
default:
|
||||
{
|
||||
LOGWARNING("%s: Unknown metadata: %d", __FUNCTION__, a_Meta);
|
||||
ASSERT(!"Unknown metadata while determining orientation of comparator!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (a_Meta)
|
||||
{
|
||||
case 0x0: a_BlockX--; break;
|
||||
case 0x1: a_BlockZ++; break;
|
||||
case 0x2: a_BlockX++; break;
|
||||
case 0x3: a_BlockZ--; break;
|
||||
default:
|
||||
{
|
||||
LOGWARNING("%s: Unknown metadata: %d", __FUNCTION__, a_Meta);
|
||||
ASSERT(!"Unknown metadata while determining orientation of comparator!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Vector3i(a_BlockX, a_BlockY, a_BlockZ);
|
||||
}
|
||||
|
||||
|
||||
inline static Vector3i GetRearCoordinate(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_Meta)
|
||||
{
|
||||
switch (a_Meta)
|
||||
{
|
||||
case 0x0: a_BlockZ++; break;
|
||||
case 0x1: a_BlockX--; break;
|
||||
case 0x2: a_BlockZ--; break;
|
||||
case 0x3: a_BlockX++; break;
|
||||
default:
|
||||
{
|
||||
LOGWARNING("%s: Unknown metadata: %d", __FUNCTION__, a_Meta);
|
||||
ASSERT(!"Unknown metadata while determining orientation of comparator!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return Vector3i(a_BlockX, a_BlockY, a_BlockZ);
|
||||
}
|
||||
|
||||
|
||||
inline static Vector3i GetFrontCoordinate(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_Meta)
|
||||
{
|
||||
switch (a_Meta)
|
||||
{
|
||||
case 0x0: a_BlockZ--; break;
|
||||
case 0x1: a_BlockX++; break;
|
||||
case 0x2: a_BlockZ++; break;
|
||||
case 0x3: a_BlockX--; break;
|
||||
default:
|
||||
{
|
||||
LOGWARNING("%s: Unknown metadata: %d", __FUNCTION__, a_Meta);
|
||||
ASSERT(!"Unknown metadata while determining orientation of comparator!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return Vector3i(a_BlockX, a_BlockY, a_BlockZ);
|
||||
}
|
||||
} ;
|
||||
|
||||
|
||||
|
@ -96,6 +96,12 @@ public:
|
||||
a_Z = a_Z - a_ChunkZ * Width;
|
||||
}
|
||||
|
||||
/** Converts relative block coordinates into absolute coordinates with a known chunk location */
|
||||
inline static Vector3i RelativeToAbsolute(const Vector3i & a_RelBlockPosition, int a_ChunkX, int a_ChunkZ)
|
||||
{
|
||||
return Vector3i(a_RelBlockPosition.x + a_ChunkX * Width, a_RelBlockPosition.y, a_RelBlockPosition.z + a_ChunkZ * Width);
|
||||
}
|
||||
|
||||
|
||||
/// Converts absolute block coords to chunk coords:
|
||||
inline static void BlockToChunk(int a_X, int a_Z, int & a_ChunkX, int & a_ChunkZ)
|
||||
|
@ -192,14 +192,13 @@ template class SizeChecker<UInt8, 1>;
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#define _WIN32_WINNT _WIN32_WINNT_WS03 // We want to target Windows XP with Service Pack 2 & Windows Server 2003 with Service Pack 1 and higher
|
||||
|
||||
// Windows SDK defines min and max macros, messing up with our std::min and std::max usage
|
||||
#define NOMINMAX
|
||||
|
||||
#include <Windows.h>
|
||||
#include <winsock2.h>
|
||||
#include <Ws2tcpip.h> // IPv6 stuff
|
||||
|
||||
// Windows SDK defines min and max macros, messing up with our std::min and std::max usage
|
||||
#undef min
|
||||
#undef max
|
||||
|
||||
// Windows SDK defines GetFreeSpace as a constant, probably a Win16 API remnant
|
||||
#ifdef GetFreeSpace
|
||||
#undef GetFreeSpace
|
||||
|
@ -3,11 +3,10 @@
|
||||
|
||||
#include "BlockEntities/ChestEntity.h"
|
||||
|
||||
typedef cItemCallback<cChestEntity> cChestCallback;
|
||||
|
||||
#include "Chunk.h"
|
||||
#include "World.h"
|
||||
#include "Blocks/GetHandlerCompileTimeTemplate.h"
|
||||
#include "Blocks/BlockComparator.h"
|
||||
#include "Blocks/BlockTorch.h"
|
||||
#include "Blocks/BlockLever.h"
|
||||
#include "Blocks/BlockButton.h"
|
||||
@ -286,6 +285,12 @@ void cIncrementalRedstoneSimulator::SimulateChunk(std::chrono::milliseconds a_Dt
|
||||
HandleRedstoneButton(dataitr->x, dataitr->y, dataitr->z);
|
||||
break;
|
||||
}
|
||||
case E_BLOCK_ACTIVE_COMPARATOR:
|
||||
case E_BLOCK_INACTIVE_COMPARATOR:
|
||||
{
|
||||
HandleRedstoneComparator(dataitr->x, dataitr->y, dataitr->z);
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
@ -535,20 +540,16 @@ void cIncrementalRedstoneSimulator::HandleRedstoneWire(int a_RelBlockX, int a_Re
|
||||
};
|
||||
|
||||
// Check to see if directly beside a power source
|
||||
unsigned char MyPower;
|
||||
if (!IsWirePowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, MyPower))
|
||||
unsigned char MyPower = IsWirePowered(Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ));
|
||||
if (MyPower == 0)
|
||||
{
|
||||
SetSourceUnpowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, m_Chunk);
|
||||
m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, MyPower);
|
||||
|
||||
if (MyPower < 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
MyPower--;
|
||||
|
||||
for (size_t i = 0; i < ARRAYCOUNT(gCrossCoords); i++) // Loop through all directions to transfer or receive power
|
||||
@ -656,6 +657,67 @@ void cIncrementalRedstoneSimulator::HandleRedstoneWire(int a_RelBlockX, int a_Re
|
||||
|
||||
|
||||
|
||||
void cIncrementalRedstoneSimulator::HandleRedstoneComparator(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ)
|
||||
{
|
||||
auto Meta = m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ);
|
||||
auto HighestSidePower = std::max(IsWirePowered(AdjustRelativeCoords(cBlockComparatorHandler::GetSideCoordinate(a_RelBlockX, a_RelBlockY, a_RelBlockZ, Meta & 0x3, false))), IsWirePowered(AdjustRelativeCoords(cBlockComparatorHandler::GetSideCoordinate(a_RelBlockX, a_RelBlockY, a_RelBlockZ, Meta & 0x3, true))));
|
||||
auto FrontCoordinate = AdjustRelativeCoords(cBlockComparatorHandler::GetFrontCoordinate(a_RelBlockX, a_RelBlockY, a_RelBlockZ, Meta & 0x3));
|
||||
unsigned char Power = 0;
|
||||
|
||||
class cContainerCallback : public cBlockEntityCallback
|
||||
{
|
||||
public:
|
||||
cContainerCallback() : m_SignalStrength(0)
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool Item(cBlockEntity * a_BlockEntity) override
|
||||
{
|
||||
auto & Contents = static_cast<cBlockEntityWithItems *>(a_BlockEntity)->GetContents();
|
||||
float Fullness = 0; // Is a floating-point type to allow later calculation to produce a non-truncated value
|
||||
for (int Slot = 0; Slot != Contents.GetNumSlots(); ++Slot)
|
||||
{
|
||||
Fullness += Contents.GetSlot(Slot).m_ItemCount / Contents.GetSlot(Slot).GetMaxStackSize();
|
||||
}
|
||||
|
||||
m_SignalStrength = static_cast<unsigned char>(1 + (Fullness / Contents.GetNumSlots()) * 14);
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned char m_SignalStrength;
|
||||
} CCB;
|
||||
|
||||
auto AbsoluteComparatorCoords = cChunkDef::RelativeToAbsolute(Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ), m_Chunk->GetPosX(), m_Chunk->GetPosZ());
|
||||
auto AbsoluteRearCoords = cBlockComparatorHandler::GetRearCoordinate(AbsoluteComparatorCoords.x, AbsoluteComparatorCoords.y, AbsoluteComparatorCoords.z, Meta & 0x3);
|
||||
|
||||
m_Chunk->DoWithBlockEntityAt(AbsoluteRearCoords.x, AbsoluteRearCoords.y, AbsoluteRearCoords.z, CCB);
|
||||
auto RearPower = std::max(CCB.m_SignalStrength, IsWirePowered(AdjustRelativeCoords(cBlockComparatorHandler::GetRearCoordinate(a_RelBlockX, a_RelBlockY, a_RelBlockZ, Meta & 0x3))));
|
||||
|
||||
if ((Meta & 0x4) == 0x4)
|
||||
{ // Subtraction mode
|
||||
Power = RearPower - HighestSidePower;
|
||||
}
|
||||
else
|
||||
{ // Comparison mode
|
||||
Power = std::max(HighestSidePower, RearPower);
|
||||
}
|
||||
|
||||
if (Power > 0)
|
||||
{
|
||||
m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ) | 0x8);
|
||||
SetBlockPowered(FrontCoordinate, Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ), Power);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ) & 0x7);
|
||||
SetSourceUnpowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, m_Chunk);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cIncrementalRedstoneSimulator::HandleRedstoneRepeater(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, BLOCKTYPE a_MyState)
|
||||
{
|
||||
/* Repeater Orientation Mini Guide:
|
||||
@ -1017,19 +1079,19 @@ void cIncrementalRedstoneSimulator::HandleDaylightSensor(int a_RelBlockX, int a_
|
||||
int ChunkX, ChunkZ;
|
||||
cChunkDef::BlockToChunk(BlockX, BlockZ, ChunkX, ChunkZ);
|
||||
|
||||
if (!this->m_World.IsChunkLighted(ChunkX, ChunkZ))
|
||||
if (!m_World.IsChunkLighted(ChunkX, ChunkZ))
|
||||
{
|
||||
this->m_World.QueueLightChunk(ChunkX, ChunkZ);
|
||||
m_World.QueueLightChunk(ChunkX, ChunkZ);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_Chunk->GetTimeAlteredLight(this->m_World.GetBlockSkyLight(BlockX, a_RelBlockY + 1, BlockZ)) > 8)
|
||||
if (m_Chunk->GetTimeAlteredLight(m_Chunk->GetSkyLight(a_RelBlockX, a_RelBlockY + 1, a_RelBlockZ)) > 8)
|
||||
{
|
||||
SetAllDirsAsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ);
|
||||
}
|
||||
else
|
||||
{
|
||||
WakeUp(BlockX, a_RelBlockY, BlockZ, m_Chunk);
|
||||
SetSourceUnpowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, m_Chunk);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1702,22 +1764,22 @@ bool cIncrementalRedstoneSimulator::IsPistonPowered(int a_RelBlockX, int a_RelBl
|
||||
|
||||
|
||||
|
||||
bool cIncrementalRedstoneSimulator::IsWirePowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, unsigned char & a_PowerLevel)
|
||||
unsigned char cIncrementalRedstoneSimulator::IsWirePowered(Vector3i a_RelBlockPosition)
|
||||
{
|
||||
a_PowerLevel = 0;
|
||||
unsigned char PowerLevel = 0;
|
||||
|
||||
for (const auto & itr : *m_PoweredBlocks) // Check powered list
|
||||
{
|
||||
if (!itr.a_BlockPos.Equals(Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ)))
|
||||
if (itr.a_BlockPos != a_RelBlockPosition)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
a_PowerLevel = std::max(itr.a_PowerLevel, a_PowerLevel); // Get the highest power level (a_PowerLevel is initialised already and there CAN be multiple levels for one block)
|
||||
PowerLevel = std::max(itr.a_PowerLevel, PowerLevel); // Get the highest power level (a_PowerLevel is initialised already and there CAN be multiple levels for one block)
|
||||
}
|
||||
|
||||
for (const auto & itr : *m_LinkedPoweredBlocks) // Check linked powered list
|
||||
{
|
||||
if (!itr.a_BlockPos.Equals(Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ)))
|
||||
if (itr.a_BlockPos != a_RelBlockPosition)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@ -1727,10 +1789,10 @@ bool cIncrementalRedstoneSimulator::IsWirePowered(int a_RelBlockX, int a_RelBloc
|
||||
{
|
||||
continue;
|
||||
}
|
||||
a_PowerLevel = std::max(itr.a_PowerLevel, a_PowerLevel);
|
||||
PowerLevel = std::max(itr.a_PowerLevel, PowerLevel);
|
||||
}
|
||||
|
||||
return (a_PowerLevel != 0); // Answer the inital question: is the wire powered?
|
||||
return PowerLevel;
|
||||
}
|
||||
|
||||
|
||||
@ -1871,20 +1933,20 @@ void cIncrementalRedstoneSimulator::SetAllDirsAsPowered(int a_RelBlockX, int a_R
|
||||
{
|
||||
static const struct
|
||||
{
|
||||
int x, y, z;
|
||||
Vector3i Offset;
|
||||
} gCrossCoords[] =
|
||||
{
|
||||
{ 1, 0, 0 },
|
||||
{ -1, 0, 0 },
|
||||
{ 0, 0, 1 },
|
||||
{ 0, 0, -1 },
|
||||
{ 0, 1, 0 },
|
||||
{ 0, -1, 0 }
|
||||
Vector3i(1, 0, 0),
|
||||
Vector3i(-1, 0, 0),
|
||||
Vector3i(0, 0, 1),
|
||||
Vector3i(0, 0, -1),
|
||||
Vector3i(0, 1, 0),
|
||||
Vector3i(0, -1, 0)
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < ARRAYCOUNT(gCrossCoords); i++) // Loop through struct to power all directions
|
||||
{
|
||||
SetBlockPowered(a_RelBlockX + gCrossCoords[i].x, a_RelBlockY + gCrossCoords[i].y, a_RelBlockZ + gCrossCoords[i].z, a_RelBlockX, a_RelBlockY, a_RelBlockZ, a_PowerLevel);
|
||||
SetBlockPowered(Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ) + gCrossCoords[i].Offset, Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ), a_PowerLevel);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1892,60 +1954,64 @@ void cIncrementalRedstoneSimulator::SetAllDirsAsPowered(int a_RelBlockX, int a_R
|
||||
|
||||
|
||||
|
||||
void cIncrementalRedstoneSimulator::SetBlockPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, int a_RelSourceX, int a_RelSourceY, int a_RelSourceZ, unsigned char a_PowerLevel)
|
||||
void cIncrementalRedstoneSimulator::SetBlockPowered(Vector3i a_RelBlockPosition, Vector3i a_RelSourcePosition, unsigned char a_PowerLevel)
|
||||
{
|
||||
cChunk * Neighbour = m_Chunk->GetRelNeighborChunkAdjustCoords(a_RelBlockX, a_RelBlockZ); // Adjust coordinates for the later call using these values
|
||||
cChunk * Neighbour = m_Chunk->GetRelNeighborChunkAdjustCoords(a_RelBlockPosition.x, a_RelBlockPosition.z); // Adjust coordinates for the later call using these values
|
||||
if ((Neighbour == nullptr) || !Neighbour->IsValid())
|
||||
{
|
||||
return;
|
||||
}
|
||||
a_RelSourcePosition.x += (m_Chunk->GetPosX() - Neighbour->GetPosX()) * cChunkDef::Width;
|
||||
a_RelSourcePosition.z += (m_Chunk->GetPosZ() - Neighbour->GetPosZ()) * cChunkDef::Width;
|
||||
|
||||
auto & Powered = ((cIncrementalRedstoneSimulator::cIncrementalRedstoneSimulatorChunkData *)Neighbour->GetRedstoneSimulatorData())->m_PoweredBlocks; // We need to insert the value into the chunk who owns the block position
|
||||
for (auto itr = Powered.begin(); itr != Powered.end(); ++itr)
|
||||
{
|
||||
if (
|
||||
itr->a_BlockPos.Equals(Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ)) &&
|
||||
itr->a_SourcePos.Equals(Vector3i(a_RelSourceX, a_RelSourceY, a_RelSourceZ))
|
||||
)
|
||||
if ((itr->a_BlockPos == a_RelBlockPosition) && (itr->a_SourcePos == a_RelSourcePosition))
|
||||
{
|
||||
// Check for duplicates, update power level, don't add a new listing
|
||||
itr->a_PowerLevel = a_PowerLevel;
|
||||
if (itr->a_PowerLevel != a_PowerLevel)
|
||||
{
|
||||
// Update power level, don't add a new listing
|
||||
Neighbour->SetIsRedstoneDirty(true);
|
||||
m_Chunk->SetIsRedstoneDirty(true);
|
||||
itr->a_PowerLevel = a_PowerLevel;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// No need to get neighbouring chunk as we can guarantee that when something is powering us, the entry will be in our chunk
|
||||
for (auto itr = m_PoweredBlocks->begin(); itr != m_PoweredBlocks->end(); ++itr)
|
||||
{
|
||||
if (
|
||||
itr->a_BlockPos.Equals(Vector3i(a_RelSourceX, a_RelSourceY, a_RelSourceZ)) &&
|
||||
itr->a_SourcePos.Equals(Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ)) &&
|
||||
(m_Chunk->GetBlock(a_RelSourceX, a_RelSourceY, a_RelSourceZ) == E_BLOCK_REDSTONE_WIRE)
|
||||
)
|
||||
{
|
||||
BLOCKTYPE Block;
|
||||
NIBBLETYPE Meta;
|
||||
Neighbour->GetBlockTypeMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, Block, Meta);
|
||||
//// No need to get neighbouring chunk as we can guarantee that when something is powering us, the entry will be in our chunk
|
||||
//for (auto itr = m_PoweredBlocks->begin(); itr != m_PoweredBlocks->end(); ++itr)
|
||||
//{
|
||||
// if (
|
||||
// (itr->a_BlockPos == a_RelBlockPosition) &&
|
||||
// (itr->a_SourcePos == a_RelSourcePosition) &&
|
||||
// (m_Chunk->GetBlock(a_RelSourcePosition) == E_BLOCK_REDSTONE_WIRE)
|
||||
// )
|
||||
// {
|
||||
// BLOCKTYPE Block;
|
||||
// NIBBLETYPE Meta;
|
||||
// Neighbour->GetBlockTypeMeta(a_RelBlockPosition.x, a_RelBlockPosition.y, a_RelBlockPosition.z, Block, Meta);
|
||||
|
||||
if (Block == E_BLOCK_REDSTONE_WIRE)
|
||||
{
|
||||
if (Meta < a_PowerLevel)
|
||||
{
|
||||
m_PoweredBlocks->erase(itr); // Powering source with higher power level, allow it
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Powered wires try to power their source - don't let them!
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// if (Block == E_BLOCK_REDSTONE_WIRE)
|
||||
// {
|
||||
// if (Meta < a_PowerLevel)
|
||||
// {
|
||||
// m_PoweredBlocks->erase(itr); // Powering source with higher power level, allow it
|
||||
// break;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// // Powered wires try to power their source - don't let them!
|
||||
// return;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
sPoweredBlocks RC;
|
||||
RC.a_BlockPos = Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ);
|
||||
RC.a_SourcePos = Vector3i(a_RelSourceX, a_RelSourceY, a_RelSourceZ);
|
||||
RC.a_BlockPos = a_RelBlockPosition;
|
||||
RC.a_SourcePos = a_RelSourcePosition;
|
||||
RC.a_PowerLevel = a_PowerLevel;
|
||||
Powered.emplace_back(RC);
|
||||
Neighbour->SetIsRedstoneDirty(true);
|
||||
@ -2123,7 +2189,7 @@ void cIncrementalRedstoneSimulator::SetSourceUnpowered(int a_RelSourceX, int a_R
|
||||
for (const auto & itr : BlocksPotentiallyUnpowered)
|
||||
{
|
||||
auto Neighbour = a_Chunk->GetRelNeighborChunk(itr.x, itr.z);
|
||||
if (!AreCoordsPowered(itr.x, itr.y, itr.z) && (Neighbour->GetBlock(itr) != E_BLOCK_REDSTONE_REPEATER_ON))
|
||||
if (Neighbour->GetBlock(itr) != E_BLOCK_REDSTONE_REPEATER_ON)
|
||||
{
|
||||
// Repeaters time themselves with regards to unpowering; ensure we don't do it for them
|
||||
SetSourceUnpowered(itr.x, itr.y, itr.z, Neighbour);
|
||||
|
@ -114,73 +114,98 @@ private:
|
||||
// We want a_MyState for devices needing a full FastSetBlock (as opposed to meta) because with our simulation model, we cannot keep setting the block if it is already set correctly
|
||||
// In addition to being non-performant, it would stop the player from actually breaking said device
|
||||
|
||||
/* ====== SOURCES ====== */
|
||||
|
||||
/** Handles the redstone torch */
|
||||
void HandleRedstoneTorch(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, BLOCKTYPE a_MyState);
|
||||
|
||||
/** Handles the redstone block */
|
||||
void HandleRedstoneBlock(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
|
||||
|
||||
/** Handles levers */
|
||||
void HandleRedstoneLever(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
|
||||
|
||||
/** Handles buttons */
|
||||
void HandleRedstoneButton(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
|
||||
|
||||
/** Handles daylight sensors */
|
||||
void HandleDaylightSensor(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
|
||||
|
||||
/** Handles pressure plates */
|
||||
void HandlePressurePlate(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, BLOCKTYPE a_MyType);
|
||||
|
||||
/** Handles tripwire hooks
|
||||
Performs correct meta and power setting for self by going in the direction it faces and looking for a continous line of tripwire bounded by another oppositely facing hook
|
||||
If this line is complete, it verifies that at least on wire reports an entity is on top (via its meta), and performs its task
|
||||
*/
|
||||
void HandleTripwireHook(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
|
||||
|
||||
/** Handles trapped chests */
|
||||
void HandleTrappedChest(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
|
||||
/* ==================== */
|
||||
|
||||
/* ====== CARRIERS ====== */
|
||||
|
||||
/** Handles redstone wire */
|
||||
void HandleRedstoneWire(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
|
||||
|
||||
/** Handles repeaters */
|
||||
void HandleRedstoneRepeater(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, BLOCKTYPE a_MyState);
|
||||
/* ====================== */
|
||||
|
||||
/* ====== DEVICES ====== */
|
||||
/** Handles comparators */
|
||||
void HandleRedstoneComparator(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
|
||||
|
||||
|
||||
/** Handles pistons */
|
||||
void HandlePiston(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
|
||||
|
||||
/** Handles dispensers and droppers */
|
||||
void HandleDropSpenser(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
|
||||
|
||||
/** Handles TNT (exploding) */
|
||||
void HandleTNT(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
|
||||
|
||||
/** Handles redstone lamps */
|
||||
void HandleRedstoneLamp(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, BLOCKTYPE a_MyState);
|
||||
|
||||
/** Handles doords */
|
||||
void HandleDoor(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
|
||||
|
||||
/** Handles command blocks */
|
||||
void HandleCommandBlock(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
|
||||
|
||||
/** Handles activator, detector, and powered rails */
|
||||
void HandleRail(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, BLOCKTYPE a_MyType);
|
||||
|
||||
/** Handles trapdoors */
|
||||
void HandleTrapdoor(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
|
||||
|
||||
/** Handles fence gates */
|
||||
void HandleFenceGate(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
|
||||
|
||||
/** Handles noteblocks */
|
||||
void HandleNoteBlock(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
|
||||
|
||||
/** Handles tripwires */
|
||||
void HandleTripwire(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
|
||||
/* ===================== */
|
||||
|
||||
/* ====== Helper functions ====== */
|
||||
|
||||
/** Marks a block as powered */
|
||||
void SetBlockPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, int a_RelSourceX, int a_RelSourceY, int a_RelSourceZ, unsigned char a_PowerLevel = MAX_POWER_LEVEL);
|
||||
void SetBlockPowered(Vector3i a_RelBlockPosition, Vector3i a_RelSourcePosition, unsigned char a_PowerLevel = MAX_POWER_LEVEL);
|
||||
void SetBlockPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, int a_RelSourceX, int a_RelSourceY, int a_RelSourceZ, unsigned char a_PowerLevel = MAX_POWER_LEVEL) { SetBlockPowered(Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ), Vector3i(a_RelSourceX, a_RelSourceY, a_RelSourceZ), a_PowerLevel); }
|
||||
|
||||
/** Marks a block as being powered through another block */
|
||||
void SetBlockLinkedPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, int a_RelMiddleX, int a_RelMiddleY, int a_RelMiddleZ, int a_RelSourceX, int a_RelSourceY, int a_RelSourceZ, BLOCKTYPE a_MiddeBlock, unsigned char a_PowerLevel = MAX_POWER_LEVEL);
|
||||
|
||||
/** Marks a block as simulated, who should not be simulated further unless their power state changes, to accomodate a player manually toggling the block without triggering the simulator toggling it back */
|
||||
void SetPlayerToggleableBlockAsSimulated(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, bool WasLastStatePowered);
|
||||
|
||||
/** Marks the second block in a direction as linked powered */
|
||||
void SetDirectionLinkedPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, char a_Direction, unsigned char a_PowerLevel = MAX_POWER_LEVEL);
|
||||
|
||||
/** Marks all blocks immediately surrounding a coordinate as powered */
|
||||
void SetAllDirsAsPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, unsigned char a_PowerLevel = MAX_POWER_LEVEL);
|
||||
|
||||
/** Queues a repeater to be powered or unpowered and returns if the m_RepeatersDelayList iterators were invalidated */
|
||||
bool QueueRepeaterPowerChange(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, NIBBLETYPE a_Meta, bool ShouldPowerOn);
|
||||
|
||||
/** Removes a block from the Powered and LinkedPowered lists
|
||||
Used for variable sources such as tripwire hooks, daylight sensors, and trapped chests
|
||||
*/
|
||||
@ -189,31 +214,39 @@ private:
|
||||
|
||||
/** Returns if a coordinate is powered or linked powered */
|
||||
bool AreCoordsPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ) { return AreCoordsDirectlyPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, m_Chunk) || AreCoordsLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ); }
|
||||
|
||||
/** Returns if a coordinate is in the directly powered blocks list */
|
||||
bool AreCoordsDirectlyPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, cChunk * a_Chunk);
|
||||
|
||||
/** Returns if a coordinate is in the indirectly powered blocks list */
|
||||
bool AreCoordsLinkedPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
|
||||
|
||||
/** Returns if a coordinate was marked as simulated (for blocks toggleable by players) */
|
||||
bool AreCoordsSimulated(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, bool IsCurrentStatePowered);
|
||||
|
||||
/** Returns if a repeater is powered by testing for power sources behind the repeater */
|
||||
bool IsRepeaterPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, NIBBLETYPE a_Meta);
|
||||
|
||||
/** Returns if a repeater is locked */
|
||||
bool IsRepeaterLocked(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, NIBBLETYPE a_Meta);
|
||||
|
||||
/** Returns if a piston is powered */
|
||||
bool IsPistonPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, NIBBLETYPE a_Meta);
|
||||
|
||||
/** Returns if a wire is powered
|
||||
The only diffence between this and a normal AreCoordsPowered is that this function checks for a wire powering another wire */
|
||||
bool IsWirePowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, unsigned char & a_PowerLevel);
|
||||
unsigned char IsWirePowered(Vector3i a_RelBlockPosition);
|
||||
|
||||
/** Handles delayed updates to repeaters **/
|
||||
void HandleRedstoneRepeaterDelays(void);
|
||||
|
||||
/** Returns if lever metadata marks it as emitting power */
|
||||
bool IsLeverOn(NIBBLETYPE a_BlockMeta);
|
||||
|
||||
/** Returns if button metadata marks it as emitting power */
|
||||
bool IsButtonOn(NIBBLETYPE a_BlockMeta) { return IsLeverOn(a_BlockMeta); }
|
||||
/* ============================== */
|
||||
|
||||
/* ====== Misc Functions ====== */
|
||||
|
||||
/** Returns if a block is viable to be the MiddleBlock of a SetLinkedPowered operation */
|
||||
inline static bool IsViableMiddleBlock(BLOCKTYPE Block) { return cBlockInfo::FullyOccupiesVoxel(Block); }
|
||||
|
||||
@ -227,6 +260,7 @@ private:
|
||||
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:
|
||||
@ -236,6 +270,7 @@ private:
|
||||
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:
|
||||
@ -276,6 +311,7 @@ private:
|
||||
case E_BLOCK_REDSTONE_REPEATER_ON:
|
||||
case E_BLOCK_BLOCK_OF_REDSTONE:
|
||||
case E_BLOCK_ACTIVE_COMPARATOR:
|
||||
case E_BLOCK_INACTIVE_COMPARATOR:
|
||||
case E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE:
|
||||
case E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE:
|
||||
case E_BLOCK_STONE_PRESSURE_PLATE:
|
||||
|
Loading…
Reference in New Issue
Block a user