summaryrefslogtreecommitdiffstats
path: root/src/Simulator/IncrementalRedstoneSimulator.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/Simulator/IncrementalRedstoneSimulator.cpp')
-rw-r--r--src/Simulator/IncrementalRedstoneSimulator.cpp1550
1 files changed, 975 insertions, 575 deletions
diff --git a/src/Simulator/IncrementalRedstoneSimulator.cpp b/src/Simulator/IncrementalRedstoneSimulator.cpp
index d37d2eecf..ada8de4b8 100644
--- a/src/Simulator/IncrementalRedstoneSimulator.cpp
+++ b/src/Simulator/IncrementalRedstoneSimulator.cpp
@@ -2,21 +2,32 @@
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
#include "IncrementalRedstoneSimulator.h"
+#include "BoundingBox.h"
#include "../BlockEntities/DropSpenserEntity.h"
#include "../BlockEntities/NoteEntity.h"
+#include "../BlockEntities/ChestEntity.h"
#include "../BlockEntities/CommandBlockEntity.h"
#include "../Entities/TNTEntity.h"
#include "../Entities/Pickup.h"
#include "../Blocks/BlockTorch.h"
#include "../Blocks/BlockDoor.h"
-#include "../Piston.h"
+#include "../Blocks/BlockButton.h"
+#include "../Blocks/BlockLever.h"
+#include "../Blocks/BlockPiston.h"
+#include "../Blocks/BlockTripwireHook.h"
+
-
-cIncrementalRedstoneSimulator::cIncrementalRedstoneSimulator(cWorld & a_World)
- : super(a_World)
+cIncrementalRedstoneSimulator::cIncrementalRedstoneSimulator(cWorld & a_World) :
+ super(a_World),
+ m_RedstoneSimulatorChunkData(),
+ m_PoweredBlocks(),
+ m_LinkedPoweredBlocks(),
+ m_SimulatedPlayerToggleableBlocks(),
+ m_RepeatersDelayList(),
+ m_Chunk()
{
}
@@ -48,7 +59,7 @@ void cIncrementalRedstoneSimulator::RedstoneAddBlock(int a_BlockX, int a_BlockY,
// Use that Chunk pointer to get a relative position
int RelX = 0;
- int RelZ = 0;
+ int RelZ = 0;
BLOCKTYPE Block;
NIBBLETYPE Meta;
@@ -57,6 +68,10 @@ void cIncrementalRedstoneSimulator::RedstoneAddBlock(int a_BlockX, int a_BlockY,
RelX = a_BlockX - a_OtherChunk->GetPosX() * cChunkDef::Width;
RelZ = a_BlockZ - a_OtherChunk->GetPosZ() * cChunkDef::Width;
a_OtherChunk->GetBlockTypeMeta(RelX, a_BlockY, RelZ, Block, Meta);
+
+ // If a_OtherChunk is passed (not NULL), it is the chunk that had a block change, and a_Chunk will be the neighbouring chunk of that block
+ // Because said neighbouring chunk does not know of this change but still needs to update its redstone, we set it to dirty
+ a_Chunk->SetIsRedstoneDirty(true);
}
else
{
@@ -87,10 +102,9 @@ void cIncrementalRedstoneSimulator::RedstoneAddBlock(int a_BlockX, int a_BlockY,
// Changeable sources
((Block == E_BLOCK_REDSTONE_WIRE) && (Meta == 0)) ||
((Block == E_BLOCK_LEVER) && !IsLeverOn(Meta)) ||
- ((Block == E_BLOCK_DETECTOR_RAIL) && (Meta & 0x08) == 0) ||
+ ((Block == E_BLOCK_DETECTOR_RAIL) && ((Meta & 0x08) == 0)) ||
(((Block == E_BLOCK_STONE_BUTTON) || (Block == E_BLOCK_WOODEN_BUTTON)) && (!IsButtonOn(Meta))) ||
- (((Block == E_BLOCK_STONE_PRESSURE_PLATE) || (Block == E_BLOCK_WOODEN_PRESSURE_PLATE)) && (Meta == 0)) ||
- (((Block == E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE) || (Block == E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE)) && (Meta == 0))
+ ((Block == E_BLOCK_TRIPWIRE_HOOK) && ((Meta & 0x08) == 0))
)
{
LOGD("cIncrementalRedstoneSimulator: Erased block @ {%i, %i, %i} from powered blocks list due to present/past metadata mismatch", itr->a_BlockPos.x, itr->a_BlockPos.y, itr->a_BlockPos.z);
@@ -139,14 +153,14 @@ void cIncrementalRedstoneSimulator::RedstoneAddBlock(int a_BlockX, int a_BlockY,
SimulatedPlayerToggleableList * SimulatedPlayerToggleableBlocks = a_Chunk->GetRedstoneSimulatorSimulatedPlayerToggleableList();
for (SimulatedPlayerToggleableList::iterator itr = SimulatedPlayerToggleableBlocks->begin(); itr != SimulatedPlayerToggleableBlocks->end(); ++itr)
{
- if (!itr->a_BlockPos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ)))
+ if (!itr->a_RelBlockPos.Equals(Vector3i(RelX, a_BlockY, RelZ)))
{
continue;
}
if (!IsAllowedBlock(Block))
{
- LOGD("cIncrementalRedstoneSimulator: Erased block @ {%i, %i, %i} from toggleable simulated list as it is no longer redstone", itr->a_BlockPos.x, itr->a_BlockPos.y, itr->a_BlockPos.z);
+ LOGD("cIncrementalRedstoneSimulator: Erased block @ {%i, %i, %i} from toggleable simulated list as it is no longer redstone", itr->a_RelBlockPos.x, itr->a_RelBlockPos.y, itr->a_RelBlockPos.z);
SimulatedPlayerToggleableBlocks->erase(itr);
break;
}
@@ -155,7 +169,7 @@ void cIncrementalRedstoneSimulator::RedstoneAddBlock(int a_BlockX, int a_BlockY,
RepeatersDelayList * RepeatersDelayList = a_Chunk->GetRedstoneSimulatorRepeatersDelayList();
for (RepeatersDelayList::iterator itr = RepeatersDelayList->begin(); itr != RepeatersDelayList->end(); ++itr)
{
- if (!itr->a_BlockPos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ)))
+ if (!itr->a_RelBlockPos.Equals(Vector3i(RelX, a_BlockY, RelZ)))
{
continue;
}
@@ -176,15 +190,16 @@ void cIncrementalRedstoneSimulator::RedstoneAddBlock(int a_BlockX, int a_BlockY,
cRedstoneSimulatorChunkData * RedstoneSimulatorChunkData = a_Chunk->GetRedstoneSimulatorData();
for (cRedstoneSimulatorChunkData::iterator itr = RedstoneSimulatorChunkData->begin(); itr != RedstoneSimulatorChunkData->end(); ++itr)
{
- if ((itr->x == RelX) && (itr->y == a_BlockY) && (itr->z == RelZ)) // We are at an entry matching the current (changed) block
+ if ((itr->x == RelX) && (itr->y == a_BlockY) && (itr->z == RelZ)) // We are at an entry matching the current (changed) block
{
if (!IsAllowedBlock(Block))
{
- itr->DataTwo = true; // The new blocktype is not redstone; it must be queued to be removed from this list
+ itr->DataTwo = true; // The new blocktype is not redstone; it must be queued to be removed from this list
}
else
{
- itr->Data = Block; // Update block information
+ itr->DataTwo = false;
+ itr->Data = Block; // Update block information
}
return;
}
@@ -194,8 +209,16 @@ void cIncrementalRedstoneSimulator::RedstoneAddBlock(int a_BlockX, int a_BlockY,
{
return;
}
-
- RedstoneSimulatorChunkData->push_back(cCoordWithBlockAndBool(RelX, a_BlockY, RelZ, Block, false));
+
+ for (cRedstoneSimulatorChunkData::iterator itr = a_Chunk->GetRedstoneSimulatorQueuedData()->begin(); itr != a_Chunk->GetRedstoneSimulatorQueuedData()->end(); ++itr)
+ {
+ if ((itr->x == RelX) && (itr->y == a_BlockY) && (itr->z == RelZ))
+ {
+ // Can't have duplicates in here either, in case something adds the block again before the structure can written to the main chunk data
+ return;
+ }
+ }
+ a_Chunk->GetRedstoneSimulatorQueuedData()->push_back(cCoordWithBlockAndBool(RelX, a_BlockY, RelZ, Block, false));
}
@@ -204,25 +227,31 @@ void cIncrementalRedstoneSimulator::RedstoneAddBlock(int a_BlockX, int a_BlockY,
void cIncrementalRedstoneSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, cChunk * a_Chunk)
{
- // We still attempt to simulate all blocks in the chunk every tick, because of outside influence that needs to be taken into account
- // For example, repeaters need to be ticked, pressure plates checked for entities, daylight sensor checked for light changes, etc.
- // The easiest way to make this more efficient is probably just to reduce code within the handlers that put too much strain on server, like getting or setting blocks
- // A marking dirty system might be a TODO for later on, perhaps
-
m_RedstoneSimulatorChunkData = a_Chunk->GetRedstoneSimulatorData();
- if (m_RedstoneSimulatorChunkData->empty())
+ if (m_RedstoneSimulatorChunkData->empty() && a_Chunk->GetRedstoneSimulatorQueuedData()->empty())
{
return;
}
+ m_RedstoneSimulatorChunkData->insert(m_RedstoneSimulatorChunkData->end(), a_Chunk->GetRedstoneSimulatorQueuedData()->begin(), a_Chunk->GetRedstoneSimulatorQueuedData()->end());
+ a_Chunk->GetRedstoneSimulatorQueuedData()->clear();
+
m_PoweredBlocks = a_Chunk->GetRedstoneSimulatorPoweredBlocksList();
m_RepeatersDelayList = a_Chunk->GetRedstoneSimulatorRepeatersDelayList();
m_SimulatedPlayerToggleableBlocks = a_Chunk->GetRedstoneSimulatorSimulatedPlayerToggleableList();
m_LinkedPoweredBlocks = a_Chunk->GetRedstoneSimulatorLinkedBlocksList();
m_Chunk = a_Chunk;
+ bool ShouldUpdateSimulateOnceBlocks = false;
- int BaseX = a_Chunk->GetPosX() * cChunkDef::Width;
- int BaseZ = a_Chunk->GetPosZ() * cChunkDef::Width;
+ if (a_Chunk->IsRedstoneDirty())
+ {
+ // Simulate the majority of devices only if something (blockwise or power-wise) has changed
+ // Make sure to allow the chunk to resimulate after the initial run if there was a power change (ShouldUpdateSimulateOnceBlocks helps to do this)
+ a_Chunk->SetIsRedstoneDirty(false);
+ ShouldUpdateSimulateOnceBlocks = true;
+ }
+
+ HandleRedstoneRepeaterDelays();
for (cRedstoneSimulatorChunkData::iterator dataitr = m_RedstoneSimulatorChunkData->begin(); dataitr != m_RedstoneSimulatorChunkData->end();)
{
@@ -232,78 +261,88 @@ void cIncrementalRedstoneSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int
continue;
}
- int a_X = BaseX + dataitr->x;
- int a_Z = BaseZ + dataitr->z;
switch (dataitr->Data)
{
- case E_BLOCK_BLOCK_OF_REDSTONE: HandleRedstoneBlock(a_X, dataitr->y, a_Z); break;
- case E_BLOCK_LEVER: HandleRedstoneLever(a_X, dataitr->y, a_Z); break;
- case E_BLOCK_FENCE_GATE: HandleFenceGate(a_X, dataitr->y, a_Z); break;
- case E_BLOCK_TNT: HandleTNT(a_X, dataitr->y, a_Z); break;
- case E_BLOCK_TRAPDOOR: HandleTrapdoor(a_X, dataitr->y, a_Z); break;
- case E_BLOCK_REDSTONE_WIRE: HandleRedstoneWire(a_X, dataitr->y, a_Z); break;
- case E_BLOCK_NOTE_BLOCK: HandleNoteBlock(a_X, dataitr->y, a_Z); break;
- case E_BLOCK_DAYLIGHT_SENSOR: HandleDaylightSensor(a_X, dataitr->y, a_Z); break;
- case E_BLOCK_COMMAND_BLOCK: HandleCommandBlock(a_X, dataitr->y, a_Z); break;
+ case E_BLOCK_DAYLIGHT_SENSOR: HandleDaylightSensor(dataitr->x, dataitr->y, dataitr->z); break;
+ case E_BLOCK_TRIPWIRE: HandleTripwire(dataitr->x, dataitr->y, dataitr->z); break;
+ case E_BLOCK_TRIPWIRE_HOOK: HandleTripwireHook(dataitr->x, dataitr->y, dataitr->z); break;
- case E_BLOCK_REDSTONE_TORCH_OFF:
- case E_BLOCK_REDSTONE_TORCH_ON:
- {
- HandleRedstoneTorch(a_X, dataitr->y, a_Z, dataitr->Data);
- break;
- }
- case E_BLOCK_STONE_BUTTON:
- case E_BLOCK_WOODEN_BUTTON:
- {
- HandleRedstoneButton(a_X, dataitr->y, a_Z, dataitr->Data);
- break;
- }
- case E_BLOCK_REDSTONE_REPEATER_OFF:
- case E_BLOCK_REDSTONE_REPEATER_ON:
- {
- HandleRedstoneRepeater(a_X, dataitr->y, a_Z, dataitr->Data);
- break;
- }
- case E_BLOCK_PISTON:
- case E_BLOCK_STICKY_PISTON:
- {
- HandlePiston(a_X, dataitr->y, a_Z);
- break;
- }
- case E_BLOCK_REDSTONE_LAMP_OFF:
- case E_BLOCK_REDSTONE_LAMP_ON:
- {
- HandleRedstoneLamp(a_X, dataitr->y, a_Z, dataitr->Data);
- break;
- }
- case E_BLOCK_DISPENSER:
- case E_BLOCK_DROPPER:
- {
- HandleDropSpenser(a_X, dataitr->y, a_Z);
- break;
- }
- case E_BLOCK_WOODEN_DOOR:
- case E_BLOCK_IRON_DOOR:
- {
- HandleDoor(a_X, dataitr->y, a_Z);
- break;
- }
- case E_BLOCK_ACTIVATOR_RAIL:
- case E_BLOCK_DETECTOR_RAIL:
- case E_BLOCK_POWERED_RAIL:
- {
- HandleRail(a_X, dataitr->y, a_Z, dataitr->Data);
- break;
- }
case E_BLOCK_WOODEN_PRESSURE_PLATE:
case E_BLOCK_STONE_PRESSURE_PLATE:
case E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE:
case E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE:
{
- HandlePressurePlate(a_X, dataitr->y, a_Z, dataitr->Data);
+ HandlePressurePlate(dataitr->x, dataitr->y, dataitr->z, dataitr->Data);
break;
}
- default: LOGD("Unhandled block (!) or unimplemented redstone block: %s", ItemToString(dataitr->Data).c_str()); break;
+ default: break;
+ }
+
+ if (ShouldUpdateSimulateOnceBlocks)
+ {
+ switch (dataitr->Data)
+ {
+ case E_BLOCK_REDSTONE_WIRE: HandleRedstoneWire(dataitr->x, dataitr->y, dataitr->z); break;
+ case E_BLOCK_COMMAND_BLOCK: HandleCommandBlock(dataitr->x, dataitr->y, dataitr->z); break;
+ case E_BLOCK_NOTE_BLOCK: HandleNoteBlock(dataitr->x, dataitr->y, dataitr->z); break;
+ case E_BLOCK_BLOCK_OF_REDSTONE: HandleRedstoneBlock(dataitr->x, dataitr->y, dataitr->z); break;
+ case E_BLOCK_LEVER: HandleRedstoneLever(dataitr->x, dataitr->y, dataitr->z); break;
+ case E_BLOCK_FENCE_GATE: HandleFenceGate(dataitr->x, dataitr->y, dataitr->z); break;
+ case E_BLOCK_TNT: HandleTNT(dataitr->x, dataitr->y, dataitr->z); break;
+ case E_BLOCK_TRAPDOOR: HandleTrapdoor(dataitr->x, dataitr->y, dataitr->z); break;
+ case E_BLOCK_TRAPPED_CHEST: HandleTrappedChest(dataitr->x, dataitr->y, dataitr->z); break;
+
+ case E_BLOCK_ACTIVATOR_RAIL:
+ case E_BLOCK_DETECTOR_RAIL:
+ case E_BLOCK_POWERED_RAIL:
+ {
+ HandleRail(dataitr->x, dataitr->y, dataitr->z, dataitr->Data);
+ break;
+ }
+ case E_BLOCK_WOODEN_DOOR:
+ case E_BLOCK_IRON_DOOR:
+ {
+ HandleDoor(dataitr->x, dataitr->y, dataitr->z);
+ break;
+ }
+ case E_BLOCK_REDSTONE_LAMP_OFF:
+ case E_BLOCK_REDSTONE_LAMP_ON:
+ {
+ HandleRedstoneLamp(dataitr->x, dataitr->y, dataitr->z, dataitr->Data);
+ break;
+ }
+ case E_BLOCK_DISPENSER:
+ case E_BLOCK_DROPPER:
+ {
+ HandleDropSpenser(dataitr->x, dataitr->y, dataitr->z);
+ break;
+ }
+ case E_BLOCK_PISTON:
+ case E_BLOCK_STICKY_PISTON:
+ {
+ HandlePiston(dataitr->x, dataitr->y, dataitr->z);
+ break;
+ }
+ case E_BLOCK_REDSTONE_REPEATER_OFF:
+ case E_BLOCK_REDSTONE_REPEATER_ON:
+ {
+ HandleRedstoneRepeater(dataitr->x, dataitr->y, dataitr->z, dataitr->Data);
+ break;
+ }
+ case E_BLOCK_REDSTONE_TORCH_OFF:
+ case E_BLOCK_REDSTONE_TORCH_ON:
+ {
+ HandleRedstoneTorch(dataitr->x, dataitr->y, dataitr->z, dataitr->Data);
+ break;
+ }
+ case E_BLOCK_STONE_BUTTON:
+ case E_BLOCK_WOODEN_BUTTON:
+ {
+ HandleRedstoneButton(dataitr->x, dataitr->y, dataitr->z);
+ break;
+ }
+ default: break;
+ }
}
++dataitr;
}
@@ -314,18 +353,13 @@ void cIncrementalRedstoneSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int
void cIncrementalRedstoneSimulator::WakeUp(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk)
{
- if (
- ((a_BlockX % cChunkDef::Width) <= 1) ||
- ((a_BlockX % cChunkDef::Width) >= 14) ||
- ((a_BlockZ % cChunkDef::Width) <= 1) ||
- ((a_BlockZ % cChunkDef::Width) >= 14)
- ) // Are we on a chunk boundary? +- 2 because of LinkedPowered blocks
+ if (AreCoordsOnChunkBoundary(a_BlockX, a_BlockY, a_BlockZ))
{
// On a chunk boundary, alert all four sides (i.e. at least one neighbouring chunk)
AddBlock(a_BlockX, a_BlockY, a_BlockZ, a_Chunk);
// Pass the original coordinates, because when adding things to our simulator lists, we get the chunk that they are in, and therefore any updates need to preseve their position
- // RedstoneAddBlock to pass both the neighbouring chunk and the chunk which the coordiantes are in and +- 2 in GetNeighbour() to accomodate for LinkedPowered blocks being 2 away from chunk boundaries
+ // RedstoneAddBlock to pass both the neighbouring chunk and the chunk which the coordinates are in and +- 2 in GetNeighbour() to accomodate for LinkedPowered blocks being 2 away from chunk boundaries
RedstoneAddBlock(a_BlockX, a_BlockY, a_BlockZ, a_Chunk->GetNeighborChunk(a_BlockX - 2, a_BlockZ), a_Chunk);
RedstoneAddBlock(a_BlockX, a_BlockY, a_BlockZ, a_Chunk->GetNeighborChunk(a_BlockX + 2, a_BlockZ), a_Chunk);
RedstoneAddBlock(a_BlockX, a_BlockY, a_BlockZ, a_Chunk->GetNeighborChunk(a_BlockX, a_BlockZ - 2), a_Chunk);
@@ -342,9 +376,9 @@ void cIncrementalRedstoneSimulator::WakeUp(int a_BlockX, int a_BlockY, int a_Blo
-void cIncrementalRedstoneSimulator::HandleRedstoneTorch(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_MyState)
+void cIncrementalRedstoneSimulator::HandleRedstoneTorch(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, BLOCKTYPE a_MyState)
{
- static const struct // Define which directions the torch can power
+ static const struct // Define which directions the torch can power
{
int x, y, z;
} gCrossCoords[] =
@@ -358,64 +392,80 @@ void cIncrementalRedstoneSimulator::HandleRedstoneTorch(int a_BlockX, int a_Bloc
if (a_MyState == E_BLOCK_REDSTONE_TORCH_ON)
{
- // Check if the block the torch is on is powered
- int X = a_BlockX; int Y = a_BlockY; int Z = a_BlockZ;
- AddFaceDirection(X, Y, Z, cBlockTorchHandler::MetaDataToDirection(m_World.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ)), true); // Inverse true to get the block torch is on
+ // Check if the block the torch is on is powered
+ int X = a_RelBlockX; int Y = a_RelBlockY; int Z = a_RelBlockZ;
+ AddFaceDirection(X, Y, Z, cBlockTorchHandler::MetaDataToDirection(m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ)), true); // Inverse true to get the block torch is on
- if (AreCoordsDirectlyPowered(X, Y, Z))
+ cChunk * Neighbour = m_Chunk->GetRelNeighborChunk(X, Z);
+ if ((Neighbour == NULL) || !Neighbour->IsValid())
+ {
+ return;
+ }
+
+ if (AreCoordsDirectlyPowered(X, Y, Z, Neighbour))
{
// There was a match, torch goes off
- m_World.SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_TORCH_OFF, m_World.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ));
+ m_Chunk->SetBlock(a_RelBlockX, a_RelBlockY, a_RelBlockZ, E_BLOCK_REDSTONE_TORCH_OFF, m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ));
return;
}
// Torch still on, make all 4(X, Z) + 1(Y) sides powered
for (size_t i = 0; i < ARRAYCOUNT(gCrossCoords); i++)
{
- BLOCKTYPE Type = m_World.GetBlock(a_BlockX + gCrossCoords[i].x, a_BlockY + gCrossCoords[i].y, a_BlockZ + gCrossCoords[i].z);
- if (i + 1 < ARRAYCOUNT(gCrossCoords)) // Sides of torch, not top (top is last)
+ BLOCKTYPE Type = 0;
+ if (!m_Chunk->UnboundedRelGetBlockType(a_RelBlockX + gCrossCoords[i].x, a_RelBlockY + gCrossCoords[i].y, a_RelBlockZ + gCrossCoords[i].z, Type))
+ {
+ continue;
+ }
+ if (i + 1 < ARRAYCOUNT(gCrossCoords)) // Sides of torch, not top (top is last)
{
if (
- ((IsMechanism(Type)) || (Type == E_BLOCK_REDSTONE_WIRE)) && // Is it a mechanism or wire? Not block/other torch etc.
- (!Vector3i(a_BlockX + gCrossCoords[i].x, a_BlockY + gCrossCoords[i].y, a_BlockZ + gCrossCoords[i].z).Equals(Vector3i(X, Y, Z))) // CAN'T power block is that it is on
+ IsMechanism(Type) && // Is it a mechanism? Not block/other torch etc.
+ (!Vector3i(a_RelBlockX + gCrossCoords[i].x, a_RelBlockY + gCrossCoords[i].y, a_RelBlockZ + gCrossCoords[i].z).Equals(Vector3i(X, Y, Z))) // CAN'T power block is that it is on
)
{
- SetBlockPowered(a_BlockX + gCrossCoords[i].x, a_BlockY + gCrossCoords[i].y, a_BlockZ + gCrossCoords[i].z, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_TORCH_ON);
+ SetBlockPowered(a_RelBlockX + gCrossCoords[i].x, a_RelBlockY + gCrossCoords[i].y, a_RelBlockZ + gCrossCoords[i].z, a_RelBlockX, a_RelBlockY, a_RelBlockZ);
}
}
else
{
// Top side, power whatever is there, including blocks
- SetBlockPowered(a_BlockX + gCrossCoords[i].x, a_BlockY + gCrossCoords[i].y, a_BlockZ + gCrossCoords[i].z, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_TORCH_ON);
+ SetBlockPowered(a_RelBlockX + gCrossCoords[i].x, a_RelBlockY + gCrossCoords[i].y, a_RelBlockZ + gCrossCoords[i].z, a_RelBlockX, a_RelBlockY, a_RelBlockZ);
// Power all blocks surrounding block above torch
- SetDirectionLinkedPowered(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_YP, E_BLOCK_REDSTONE_TORCH_ON);
+ SetDirectionLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, BLOCK_FACE_YP);
}
}
- if (m_World.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ) != 0x5) // Is torch standing on ground? If NOT (i.e. on wall), power block beneath
+ if (m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ) != 0x5) // Is torch standing on ground? If NOT (i.e. on wall), power block beneath
{
- BLOCKTYPE Type = m_World.GetBlock(a_BlockX, a_BlockY - 1, a_BlockZ);
+ BLOCKTYPE Type = m_Chunk->GetBlock(a_RelBlockX, a_RelBlockY - 1, a_RelBlockZ);
- if ((IsMechanism(Type)) || (Type == E_BLOCK_REDSTONE_WIRE)) // Still can't make a normal block powered though!
+ if (IsMechanism(Type)) // Still can't make a normal block powered though!
{
- SetBlockPowered(a_BlockX, a_BlockY - 1, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_TORCH_ON);
+ SetBlockPowered(a_RelBlockX, a_RelBlockY - 1, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ);
}
}
}
else
{
- // Check if the block the torch is on is powered
- int X = a_BlockX; int Y = a_BlockY; int Z = a_BlockZ;
- AddFaceDirection(X, Y, Z, cBlockTorchHandler::MetaDataToDirection(m_World.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ)), true); // Inverse true to get the block torch is on
-
+ // Check if the block the torch is on is powered
+ int X = a_RelBlockX; int Y = a_RelBlockY; int Z = a_RelBlockZ;
+ AddFaceDirection(X, Y, Z, cBlockTorchHandler::MetaDataToDirection(m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ)), true); // Inverse true to get the block torch is on
+
+ cChunk * Neighbour = m_Chunk->GetRelNeighborChunk(X, Z);
+ if ((Neighbour == NULL) || !Neighbour->IsValid())
+ {
+ return;
+ }
+
// See if off state torch can be turned on again
- if (AreCoordsDirectlyPowered(X, Y, Z))
+ if (AreCoordsDirectlyPowered(X, Y, Z, Neighbour))
{
- return; // Something matches, torch still powered
+ return; // Something matches, torch still powered
}
// Block torch on not powered, can be turned on again!
- m_World.SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_TORCH_ON, m_World.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ));
+ m_Chunk->SetBlock(a_RelBlockX, a_RelBlockY, a_RelBlockZ, E_BLOCK_REDSTONE_TORCH_ON, m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ));
}
}
@@ -423,28 +473,28 @@ void cIncrementalRedstoneSimulator::HandleRedstoneTorch(int a_BlockX, int a_Bloc
-void cIncrementalRedstoneSimulator::HandleRedstoneBlock(int a_BlockX, int a_BlockY, int a_BlockZ)
+void cIncrementalRedstoneSimulator::HandleRedstoneBlock(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ)
{
- SetAllDirsAsPowered(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_BLOCK_OF_REDSTONE);
- SetBlockPowered(a_BlockX, a_BlockY, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_BLOCK_OF_REDSTONE); // Set self as powered
+ SetAllDirsAsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ);
+ SetBlockPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ); // Set self as powered
}
-void cIncrementalRedstoneSimulator::HandleRedstoneLever(int a_BlockX, int a_BlockY, int a_BlockZ)
+void cIncrementalRedstoneSimulator::HandleRedstoneLever(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ)
{
- if (IsLeverOn(m_World.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ)))
+ NIBBLETYPE Meta = m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ);
+ if (IsLeverOn(Meta))
{
- SetAllDirsAsPowered(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_LEVER);
+ SetAllDirsAsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ);
- SetDirectionLinkedPowered(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_XM, E_BLOCK_LEVER);
- SetDirectionLinkedPowered(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_XP, E_BLOCK_LEVER);
- SetDirectionLinkedPowered(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_YM, E_BLOCK_LEVER);
- SetDirectionLinkedPowered(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_YP, E_BLOCK_LEVER);
- SetDirectionLinkedPowered(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_ZM, E_BLOCK_LEVER);
- SetDirectionLinkedPowered(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_ZP, E_BLOCK_LEVER);
+ eBlockFace Dir = cBlockLeverHandler::BlockMetaDataToBlockFace(Meta);
+
+ Dir = ReverseBlockFace(Dir);
+
+ SetDirectionLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, Dir);
}
}
@@ -452,27 +502,34 @@ void cIncrementalRedstoneSimulator::HandleRedstoneLever(int a_BlockX, int a_Bloc
-void cIncrementalRedstoneSimulator::HandleFenceGate(int a_BlockX, int a_BlockY, int a_BlockZ)
+void cIncrementalRedstoneSimulator::HandleFenceGate(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ)
{
- cChunkInterface ChunkInterface(m_World.GetChunkMap());
- NIBBLETYPE MetaData = ChunkInterface.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ);
+ int BlockX = (m_Chunk->GetPosX() * cChunkDef::Width) + a_RelBlockX;
+ int BlockZ = (m_Chunk->GetPosZ() * cChunkDef::Width) + a_RelBlockZ;
+ NIBBLETYPE MetaData = m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ);
- if (AreCoordsPowered(a_BlockX, a_BlockY, a_BlockZ))
+ if (AreCoordsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ))
{
- if (!AreCoordsSimulated(a_BlockX, a_BlockY, a_BlockZ, true))
+ if (!AreCoordsSimulated(a_RelBlockX, a_RelBlockY, a_RelBlockZ, true))
{
- m_World.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, MetaData | 0x4);
- m_World.BroadcastSoundParticleEffect(1003, a_BlockX, a_BlockY, a_BlockZ, 0);
- SetPlayerToggleableBlockAsSimulated(a_BlockX, a_BlockY, a_BlockZ, true);
+ if ((MetaData & 0x4) == 0)
+ {
+ m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, MetaData | 0x4);
+ m_Chunk->BroadcastSoundParticleEffect(1003, BlockX, a_RelBlockY, BlockZ, 0);
+ }
+ SetPlayerToggleableBlockAsSimulated(a_RelBlockX, a_RelBlockY, a_RelBlockZ, true);
}
}
else
{
- if (!AreCoordsSimulated(a_BlockX, a_BlockY, a_BlockZ, false))
+ if (!AreCoordsSimulated(a_RelBlockX, a_RelBlockY, a_RelBlockZ, false))
{
- m_World.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, MetaData & 0xFFFFFFFB);
- m_World.BroadcastSoundParticleEffect(1003, a_BlockX, a_BlockY, a_BlockZ, 0);
- SetPlayerToggleableBlockAsSimulated(a_BlockX, a_BlockY, a_BlockZ, false);
+ if ((MetaData & 0x4) != 0)
+ {
+ m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, MetaData & ~0x04);
+ m_Chunk->BroadcastSoundParticleEffect(1003, BlockX, a_RelBlockY, BlockZ, 0);
+ }
+ SetPlayerToggleableBlockAsSimulated(a_RelBlockX, a_RelBlockY, a_RelBlockZ, false);
}
}
}
@@ -481,18 +538,16 @@ void cIncrementalRedstoneSimulator::HandleFenceGate(int a_BlockX, int a_BlockY,
-void cIncrementalRedstoneSimulator::HandleRedstoneButton(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType)
+void cIncrementalRedstoneSimulator::HandleRedstoneButton(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ)
{
- if (IsButtonOn(m_World.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ)))
+ NIBBLETYPE Meta = m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ);
+ if (IsButtonOn(Meta))
{
- SetAllDirsAsPowered(a_BlockX, a_BlockY, a_BlockZ, a_BlockType);
-
- SetDirectionLinkedPowered(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_XM, a_BlockType);
- SetDirectionLinkedPowered(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_XP, a_BlockType);
- SetDirectionLinkedPowered(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_YM, a_BlockType);
- SetDirectionLinkedPowered(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_YP, a_BlockType);
- SetDirectionLinkedPowered(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_ZM, a_BlockType);
- SetDirectionLinkedPowered(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_ZP, a_BlockType);
+ SetAllDirsAsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ);
+
+ eBlockFace Dir = cBlockButtonHandler::BlockMetaDataToBlockFace(Meta);
+ Dir = ReverseBlockFace(Dir);
+ SetDirectionLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, Dir);
}
}
@@ -500,9 +555,9 @@ void cIncrementalRedstoneSimulator::HandleRedstoneButton(int a_BlockX, int a_Blo
-void cIncrementalRedstoneSimulator::HandleRedstoneWire(int a_BlockX, int a_BlockY, int a_BlockZ)
+void cIncrementalRedstoneSimulator::HandleRedstoneWire(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ)
{
- static const struct // Define which directions the wire can receive power from
+ static const struct // Define which directions the wire can receive power from
{
int x, y, z;
} gCrossCoords[] =
@@ -515,13 +570,13 @@ void cIncrementalRedstoneSimulator::HandleRedstoneWire(int a_BlockX, int a_Block
{-1, 1, 0},
{ 0, 1, 1},
{ 0, 1, -1}, /* Wires one higher, surrounding self stop */
- { 1,-1, 0}, /* Wires one lower, surrounding self start */
- {-1,-1, 0},
- { 0,-1, 1},
- { 0,-1, -1}, /* Wires one lower, surrounding self stop */
+ { 1, -1, 0}, /* Wires one lower, surrounding self start */
+ {-1, -1, 0},
+ { 0, -1, 1},
+ { 0, -1, -1}, /* Wires one lower, surrounding self stop */
} ;
- static const struct // Define which directions the wire will check for repeater prescence
+ static const struct // Define which directions the wire will check for repeater prescence
{
int x, y, z;
} gSideCoords[] =
@@ -529,20 +584,22 @@ void cIncrementalRedstoneSimulator::HandleRedstoneWire(int a_BlockX, int a_Block
{ 1, 0, 0 },
{-1, 0, 0 },
{ 0, 0, 1 },
- { 0, 0,-1 },
+ { 0, 0, -1 },
{ 0, 1, 0 },
};
// Check to see if directly beside a power source
unsigned char MyPower;
- if (!IsWirePowered(a_BlockX, a_BlockY, a_BlockZ, MyPower))
+ if (!IsWirePowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, MyPower))
{
- m_World.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, 0);
- m_World.WakeUpSimulators(a_BlockX, a_BlockY, a_BlockZ);
+ int BlockX = (m_Chunk->GetPosX() * cChunkDef::Width) + a_RelBlockX;
+ int BlockZ = (m_Chunk->GetPosZ() * cChunkDef::Width) + a_RelBlockZ;
+ m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, 0);
+ m_World.WakeUpSimulators(BlockX, a_RelBlockY, BlockZ);
return;
}
- m_World.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, MyPower);
+ m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, MyPower);
if (MyPower < 1)
{
@@ -551,78 +608,102 @@ void cIncrementalRedstoneSimulator::HandleRedstoneWire(int a_BlockX, int a_Block
MyPower--;
- for (size_t i = 0; i < ARRAYCOUNT(gCrossCoords); i++) // Loop through all directions to transfer or receive power
+ for (size_t i = 0; i < ARRAYCOUNT(gCrossCoords); i++) // Loop through all directions to transfer or receive power
{
- if ((i >= 4) && (i <= 7)) // If we are currently checking for wire surrounding ourself one block above...
+ if ((i >= 4) && (i <= 7)) // If we are currently checking for wire surrounding ourself one block above...
{
- if (cBlockInfo::IsSolid(m_World.GetBlock(a_BlockX, a_BlockY + 1, a_BlockZ))) // If there is something solid above us (wire cut off)...
+ BLOCKTYPE Type = 0;
+ if (a_RelBlockY + 1 >= cChunkDef::Height)
+ {
+ continue;
+ }
+ if (!m_Chunk->UnboundedRelGetBlockType(a_RelBlockX, a_RelBlockY + 1, a_RelBlockZ, Type))
{
- continue; // We don't receive power from that wire
+ continue;
+ }
+ if (cBlockInfo::IsSolid(Type)) // If there is something solid above us (wire cut off)...
+ {
+ continue; // We don't receive power from that wire
}
}
- else if ((i >= 8) && (i <= 11)) // See above, but this is for wire below us
+ else if ((i >= 8) && (i <= 11)) // See above, but this is for wire below us
{
- if (cBlockInfo::IsSolid(m_World.GetBlock(a_BlockX, a_BlockY - 1, a_BlockZ)))
+ BLOCKTYPE Type = 0;
+ if (!m_Chunk->UnboundedRelGetBlockType(a_RelBlockX + gCrossCoords[i].x, a_RelBlockY, a_RelBlockZ + gCrossCoords[i].z, Type))
+ {
+ continue;
+ }
+ if (cBlockInfo::IsSolid(Type))
{
continue;
}
}
- if (m_World.GetBlock(a_BlockX + gCrossCoords[i].x, a_BlockY + gCrossCoords[i].y, a_BlockZ + gCrossCoords[i].z) == E_BLOCK_REDSTONE_WIRE)
+ BLOCKTYPE Type = 0;
+ if (!m_Chunk->UnboundedRelGetBlockType(a_RelBlockX + gCrossCoords[i].x, a_RelBlockY + gCrossCoords[i].y, a_RelBlockZ + gCrossCoords[i].z, Type))
{
- SetBlockPowered(a_BlockX + gCrossCoords[i].x, a_BlockY + gCrossCoords[i].y, a_BlockZ + gCrossCoords[i].z, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_WIRE, MyPower);
+ continue;
+ }
+ if (Type == E_BLOCK_REDSTONE_WIRE)
+ {
+ SetBlockPowered(a_RelBlockX + gCrossCoords[i].x, a_RelBlockY + gCrossCoords[i].y, a_RelBlockZ + gCrossCoords[i].z, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MyPower);
}
}
- for (size_t i = 0; i < ARRAYCOUNT(gSideCoords); i++) // Look for repeaters immediately surrounding self and try to power them
+ for (size_t i = 0; i < ARRAYCOUNT(gSideCoords); i++) // Look for repeaters immediately surrounding self and try to power them
{
- if (m_World.GetBlock(a_BlockX + gSideCoords[i].x, a_BlockY + gSideCoords[i].y, a_BlockZ + gSideCoords[i].z) == E_BLOCK_REDSTONE_REPEATER_OFF)
+ BLOCKTYPE Type = 0;
+ if (!m_Chunk->UnboundedRelGetBlockType(a_RelBlockX + gSideCoords[i].x, a_RelBlockY + gSideCoords[i].y, a_RelBlockZ + gSideCoords[i].z, Type))
+ {
+ continue;
+ }
+ if (Type == E_BLOCK_REDSTONE_REPEATER_OFF)
{
- SetBlockPowered(a_BlockX + gSideCoords[i].x, a_BlockY + gSideCoords[i].y, a_BlockZ + gSideCoords[i].z, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_WIRE, MyPower);
+ SetBlockPowered(a_RelBlockX + gSideCoords[i].x, a_RelBlockY + gSideCoords[i].y, a_RelBlockZ + gSideCoords[i].z, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MyPower);
}
}
// Wire still powered, power blocks beneath
- SetBlockPowered(a_BlockX, a_BlockY - 1, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_WIRE, MyPower);
- SetDirectionLinkedPowered(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_YM, E_BLOCK_REDSTONE_WIRE, MyPower);
+ SetBlockPowered(a_RelBlockX, a_RelBlockY - 1, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MyPower);
+ SetDirectionLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, BLOCK_FACE_YM, MyPower);
- switch (GetWireDirection(a_BlockX, a_BlockY, a_BlockZ))
+ switch (GetWireDirection(a_RelBlockX, a_RelBlockY, a_RelBlockZ))
{
case REDSTONE_NONE:
{
- SetBlockPowered(a_BlockX + 1, a_BlockY, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_WIRE, MyPower);
- SetBlockPowered(a_BlockX - 1, a_BlockY, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_WIRE, MyPower);
- SetBlockPowered(a_BlockX, a_BlockY, a_BlockZ + 1, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_WIRE, MyPower);
- SetBlockPowered(a_BlockX, a_BlockY, a_BlockZ - 1, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_WIRE, MyPower);
+ SetBlockPowered(a_RelBlockX + 1, a_RelBlockY, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MyPower);
+ SetBlockPowered(a_RelBlockX - 1, a_RelBlockY, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MyPower);
+ SetBlockPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ + 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MyPower);
+ SetBlockPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ - 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MyPower);
- SetDirectionLinkedPowered(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_XM, E_BLOCK_REDSTONE_WIRE, MyPower);
- SetDirectionLinkedPowered(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_XP, E_BLOCK_REDSTONE_WIRE, MyPower);
- SetDirectionLinkedPowered(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_ZM, E_BLOCK_REDSTONE_WIRE, MyPower);
- SetDirectionLinkedPowered(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_ZP, E_BLOCK_REDSTONE_WIRE, MyPower);
+ SetDirectionLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, BLOCK_FACE_XM, MyPower);
+ SetDirectionLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, BLOCK_FACE_XP, MyPower);
+ SetDirectionLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, BLOCK_FACE_ZM, MyPower);
+ SetDirectionLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, BLOCK_FACE_ZP, MyPower);
break;
}
case REDSTONE_X_POS:
{
- SetBlockPowered(a_BlockX + 1, a_BlockY, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_WIRE, MyPower);
- SetDirectionLinkedPowered(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_XP, E_BLOCK_REDSTONE_WIRE, MyPower);
+ SetBlockPowered(a_RelBlockX + 1, a_RelBlockY, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MyPower);
+ SetDirectionLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, BLOCK_FACE_XP, MyPower);
break;
}
case REDSTONE_X_NEG:
{
- SetBlockPowered(a_BlockX - 1, a_BlockY, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_WIRE, MyPower);
- SetDirectionLinkedPowered(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_XM, E_BLOCK_REDSTONE_WIRE, MyPower);
+ SetBlockPowered(a_RelBlockX - 1, a_RelBlockY, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MyPower);
+ SetDirectionLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, BLOCK_FACE_XM, MyPower);
break;
}
case REDSTONE_Z_POS:
{
- SetBlockPowered(a_BlockX, a_BlockY, a_BlockZ + 1, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_WIRE, MyPower);
- SetDirectionLinkedPowered(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_ZP, E_BLOCK_REDSTONE_WIRE, MyPower);
+ SetBlockPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ + 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MyPower);
+ SetDirectionLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, BLOCK_FACE_ZP, MyPower);
break;
}
case REDSTONE_Z_NEG:
{
- SetBlockPowered(a_BlockX, a_BlockY, a_BlockZ - 1, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_WIRE, MyPower);
- SetDirectionLinkedPowered(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_ZM, E_BLOCK_REDSTONE_WIRE, MyPower);
+ SetBlockPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ - 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MyPower);
+ SetDirectionLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, BLOCK_FACE_ZM, MyPower);
break;
}
}
@@ -632,7 +713,7 @@ void cIncrementalRedstoneSimulator::HandleRedstoneWire(int a_BlockX, int a_Block
-void cIncrementalRedstoneSimulator::HandleRedstoneRepeater(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_MyState)
+void cIncrementalRedstoneSimulator::HandleRedstoneRepeater(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, BLOCKTYPE a_MyState)
{
/* Repeater Orientation Mini Guide:
===================================
@@ -643,7 +724,7 @@ void cIncrementalRedstoneSimulator::HandleRedstoneRepeater(int a_BlockX, int a_B
X Axis ---->
- Repeater directions, values from a cWorld::GetBlockMeta(a_BlockX , a_BlockY, a_BlockZ) lookup:
+ Repeater directions, values from a cWorld::GetBlockMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ) lookup:
East (Right) (X+): 0x1
West (Left) (X-): 0x3
@@ -656,87 +737,81 @@ void cIncrementalRedstoneSimulator::HandleRedstoneRepeater(int a_BlockX, int a_B
*/
// Create a variable holding my meta to avoid multiple lookups.
- NIBBLETYPE a_Meta = m_World.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ);
+ NIBBLETYPE a_Meta = m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ);
bool IsOn = (a_MyState == E_BLOCK_REDSTONE_REPEATER_ON);
-
- if (!IsRepeaterLocked(a_BlockX, a_BlockY, a_BlockZ, a_Meta)) // If we're locked, change nothing. Otherwise:
+
+ if (!IsRepeaterLocked(a_RelBlockX, a_RelBlockY, a_RelBlockZ, a_Meta)) // If we're locked, change nothing. Otherwise:
{
- bool IsSelfPowered = IsRepeaterPowered(a_BlockX, a_BlockY, a_BlockZ, a_Meta);
- if (IsSelfPowered && !IsOn) // Queue a power change if powered, but not on and not locked.
+ bool IsSelfPowered = IsRepeaterPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, a_Meta);
+ if (IsSelfPowered && !IsOn) // Queue a power change if powered, but not on and not locked.
{
- QueueRepeaterPowerChange(a_BlockX, a_BlockY, a_BlockZ, a_Meta, true);
+ QueueRepeaterPowerChange(a_RelBlockX, a_RelBlockY, a_RelBlockZ, a_Meta, true);
}
- else if (!IsSelfPowered && IsOn) // Queue a power change if unpowered, on, and not locked.
+ else if (!IsSelfPowered && IsOn) // Queue a power change if unpowered, on, and not locked.
{
- QueueRepeaterPowerChange(a_BlockX, a_BlockY, a_BlockZ, a_Meta, false);
+ QueueRepeaterPowerChange(a_RelBlockX, a_RelBlockY, a_RelBlockZ, a_Meta, false);
}
}
+}
- for (RepeatersDelayList::iterator itr = m_RepeatersDelayList->begin(); itr != m_RepeatersDelayList->end(); ++itr)
+void cIncrementalRedstoneSimulator::HandleRedstoneRepeaterDelays()
+{
+ for (RepeatersDelayList::iterator itr = m_RepeatersDelayList->begin(); itr != m_RepeatersDelayList->end();)
{
- if (!itr->a_BlockPos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ)))
- {
- continue;
- }
-
- if (itr->a_ElapsedTicks >= itr->a_DelayTicks) // Has the elapsed ticks reached the target ticks?
+ if (itr->a_ElapsedTicks >= itr->a_DelayTicks) // Has the elapsed ticks reached the target ticks?
{
+ int RelBlockX = itr->a_RelBlockPos.x;
+ int RelBlockY = itr->a_RelBlockPos.y;
+ int RelBlockZ = itr->a_RelBlockPos.z;
+ BLOCKTYPE Block;
+ NIBBLETYPE Meta;
+ m_Chunk->GetBlockTypeMeta(RelBlockX, RelBlockY, RelBlockZ, Block, Meta);
if (itr->ShouldPowerOn)
{
- if (!IsOn)
+ if (Block != E_BLOCK_REDSTONE_REPEATER_ON) // For performance
{
- m_World.SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_REPEATER_ON, a_Meta); // For performance
+ m_Chunk->SetBlock(itr->a_RelBlockPos, E_BLOCK_REDSTONE_REPEATER_ON, Meta);
}
- switch (a_Meta & 0x3) // We only want the direction (bottom) bits
+ switch (Meta & 0x3) // We only want the direction (bottom) bits
{
case 0x0:
{
- SetBlockPowered(a_BlockX, a_BlockY, a_BlockZ - 1, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_REPEATER_ON);
- SetDirectionLinkedPowered(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_ZM, E_BLOCK_REDSTONE_REPEATER_ON);
+ SetBlockPowered(RelBlockX, RelBlockY, RelBlockZ - 1, RelBlockX, RelBlockY, RelBlockZ);
+ SetDirectionLinkedPowered(RelBlockX, RelBlockY, RelBlockZ, BLOCK_FACE_ZM);
break;
}
case 0x1:
{
- SetBlockPowered(a_BlockX + 1, a_BlockY, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_REPEATER_ON);
- SetDirectionLinkedPowered(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_XP, E_BLOCK_REDSTONE_REPEATER_ON);
+ SetBlockPowered(RelBlockX + 1, RelBlockY, RelBlockZ, RelBlockX, RelBlockY, RelBlockZ);
+ SetDirectionLinkedPowered(RelBlockX, RelBlockY, RelBlockZ, BLOCK_FACE_XP);
break;
}
case 0x2:
{
- SetBlockPowered(a_BlockX, a_BlockY, a_BlockZ + 1, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_REPEATER_ON);
- SetDirectionLinkedPowered(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_ZP, E_BLOCK_REDSTONE_REPEATER_ON);
+ SetBlockPowered(RelBlockX, RelBlockY, RelBlockZ + 1, RelBlockX, RelBlockY, RelBlockZ);
+ SetDirectionLinkedPowered(RelBlockX, RelBlockY, RelBlockZ, BLOCK_FACE_ZP);
break;
}
case 0x3:
{
- SetBlockPowered(a_BlockX - 1, a_BlockY, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_REPEATER_ON);
- SetDirectionLinkedPowered(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_XM, E_BLOCK_REDSTONE_REPEATER_ON);
+ SetBlockPowered(RelBlockX - 1, RelBlockY, RelBlockZ, RelBlockX, RelBlockY, RelBlockZ);
+ SetDirectionLinkedPowered(RelBlockX, RelBlockY, RelBlockZ, BLOCK_FACE_XM);
break;
}
}
-
- // Removal of the data entry will be handled in SimChunk - we still want to continue trying to power blocks, even if our delay time has reached
- // Otherwise, the power state of blocks in front won't update after we have powered on
- return;
}
- else
+ else if (Block != E_BLOCK_REDSTONE_REPEATER_OFF)
{
- if (IsOn)
- {
- m_World.SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_REPEATER_OFF, a_Meta);
- }
- m_RepeatersDelayList->erase(itr); // We can remove off repeaters which don't need further updating
- return;
+ m_Chunk->SetBlock(RelBlockX, RelBlockY, RelBlockZ, E_BLOCK_REDSTONE_REPEATER_OFF, Meta);
}
+ itr = m_RepeatersDelayList->erase(itr);
}
else
{
- // Apparently, incrementing ticks only works reliably here, and not in SimChunk;
- // With a world with lots of redstone, the repeaters simply do not delay
- // I am confounded to say why. Perhaps optimisation failure.
- LOGD("Incremented a repeater @ {%i %i %i} | Elapsed ticks: %i | Target delay: %i", itr->a_BlockPos.x, itr->a_BlockPos.y, itr->a_BlockPos.z, itr->a_ElapsedTicks, itr->a_DelayTicks);
+ LOGD("Incremented a repeater @ {%i %i %i} | Elapsed ticks: %i | Target delay: %i", itr->a_RelBlockPos.x, itr->a_RelBlockPos.y, itr->a_RelBlockPos.z, itr->a_ElapsedTicks, itr->a_DelayTicks);
itr->a_ElapsedTicks++;
+ itr++;
}
}
}
@@ -745,16 +820,18 @@ void cIncrementalRedstoneSimulator::HandleRedstoneRepeater(int a_BlockX, int a_B
-void cIncrementalRedstoneSimulator::HandlePiston(int a_BlockX, int a_BlockY, int a_BlockZ)
-{
- cPiston Piston(&m_World);
- if (IsPistonPowered(a_BlockX, a_BlockY, a_BlockZ, m_World.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ) & 0x7)) // We only want the bottom three bits (4th controls extended-ness)
+void cIncrementalRedstoneSimulator::HandlePiston(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ)
+{
+ int BlockX = (m_Chunk->GetPosX() * cChunkDef::Width) + a_RelBlockX;
+ int BlockZ = (m_Chunk->GetPosZ() * cChunkDef::Width) + a_RelBlockZ;
+
+ if (IsPistonPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ) & 0x7)) // We only want the bottom three bits (4th controls extended-ness)
{
- Piston.ExtendPiston(a_BlockX, a_BlockY, a_BlockZ);
+ cBlockPistonHandler::ExtendPiston(BlockX, a_RelBlockY, BlockZ, &m_World);
}
else
{
- Piston.RetractPiston(a_BlockX, a_BlockY, a_BlockZ);
+ cBlockPistonHandler::RetractPiston(BlockX, a_RelBlockY, BlockZ, &m_World);
}
}
@@ -762,7 +839,7 @@ void cIncrementalRedstoneSimulator::HandlePiston(int a_BlockX, int a_BlockY, int
-void cIncrementalRedstoneSimulator::HandleDropSpenser(int a_BlockX, int a_BlockY, int a_BlockZ)
+void cIncrementalRedstoneSimulator::HandleDropSpenser(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ)
{
class cSetPowerToDropSpenser :
public cDropSpenserCallback
@@ -776,29 +853,31 @@ void cIncrementalRedstoneSimulator::HandleDropSpenser(int a_BlockX, int a_BlockY
a_DropSpenser->SetRedstonePower(m_IsPowered);
return false;
}
- } DrSpSP (AreCoordsPowered(a_BlockX, a_BlockY, a_BlockZ));
+ } DrSpSP (AreCoordsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ));
- m_World.DoWithDropSpenserAt(a_BlockX, a_BlockY, a_BlockZ, DrSpSP);
+ int BlockX = (m_Chunk->GetPosX() * cChunkDef::Width) + a_RelBlockX;
+ int BlockZ = (m_Chunk->GetPosZ() * cChunkDef::Width) + a_RelBlockZ;
+ m_Chunk->DoWithDropSpenserAt(BlockX, a_RelBlockY, BlockZ, DrSpSP);
}
-void cIncrementalRedstoneSimulator::HandleRedstoneLamp(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_MyState)
+void cIncrementalRedstoneSimulator::HandleRedstoneLamp(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, BLOCKTYPE a_MyState)
{
if (a_MyState == E_BLOCK_REDSTONE_LAMP_OFF)
{
- if (AreCoordsPowered(a_BlockX, a_BlockY, a_BlockZ))
+ if (AreCoordsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ))
{
- m_World.SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_LAMP_ON, 0);
+ m_Chunk->SetBlock(a_RelBlockX, a_RelBlockY, a_RelBlockZ, E_BLOCK_REDSTONE_LAMP_ON, 0);
}
}
else
{
- if (!AreCoordsPowered(a_BlockX, a_BlockY, a_BlockZ))
+ if (!AreCoordsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ))
{
- m_World.SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_LAMP_OFF, 0);
+ m_Chunk->SetBlock(a_RelBlockX, a_RelBlockY, a_RelBlockZ, E_BLOCK_REDSTONE_LAMP_OFF, 0);
}
}
}
@@ -807,13 +886,16 @@ void cIncrementalRedstoneSimulator::HandleRedstoneLamp(int a_BlockX, int a_Block
-void cIncrementalRedstoneSimulator::HandleTNT(int a_BlockX, int a_BlockY, int a_BlockZ)
+void cIncrementalRedstoneSimulator::HandleTNT(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ)
{
- if (AreCoordsPowered(a_BlockX, a_BlockY, a_BlockZ))
+ int BlockX = (m_Chunk->GetPosX() * cChunkDef::Width) + a_RelBlockX;
+ int BlockZ = (m_Chunk->GetPosZ() * cChunkDef::Width) + a_RelBlockZ;
+
+ if (AreCoordsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ))
{
- m_World.BroadcastSoundEffect("game.tnt.primed", a_BlockX * 8, a_BlockY * 8, a_BlockZ * 8, 0.5f, 0.6f);
- m_World.SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_AIR, 0);
- m_World.SpawnPrimedTNT(a_BlockX + 0.5, a_BlockY + 0.5, a_BlockZ + 0.5); // 80 ticks to boom
+ m_Chunk->BroadcastSoundEffect("game.tnt.primed", (double)BlockX, (double)a_RelBlockY, (double)BlockZ, 0.5f, 0.6f);
+ m_Chunk->SetBlock(a_RelBlockX, a_RelBlockY, a_RelBlockZ, E_BLOCK_AIR, 0);
+ m_World.SpawnPrimedTNT(BlockX + 0.5, a_RelBlockY + 0.5, BlockZ + 0.5); // 80 ticks to boom
}
}
@@ -821,26 +903,35 @@ void cIncrementalRedstoneSimulator::HandleTNT(int a_BlockX, int a_BlockY, int a_
-void cIncrementalRedstoneSimulator::HandleDoor(int a_BlockX, int a_BlockY, int a_BlockZ)
+void cIncrementalRedstoneSimulator::HandleDoor(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ)
{
- if (AreCoordsPowered(a_BlockX, a_BlockY, a_BlockZ))
+ int BlockX = (m_Chunk->GetPosX() * cChunkDef::Width) + a_RelBlockX;
+ int BlockZ = (m_Chunk->GetPosZ() * cChunkDef::Width) + a_RelBlockZ;
+
+ if (AreCoordsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ))
{
- if (!AreCoordsSimulated(a_BlockX, a_BlockY, a_BlockZ, true))
+ if (!AreCoordsSimulated(a_RelBlockX, a_RelBlockY, a_RelBlockZ, true))
{
cChunkInterface ChunkInterface(m_World.GetChunkMap());
- cBlockDoorHandler::ChangeDoor(ChunkInterface, a_BlockX, a_BlockY, a_BlockZ);
- m_World.BroadcastSoundParticleEffect(1003, a_BlockX, a_BlockY, a_BlockZ, 0);
- SetPlayerToggleableBlockAsSimulated(a_BlockX, a_BlockY, a_BlockZ, true);
+ if (!cBlockDoorHandler::IsOpen(ChunkInterface, BlockX, a_RelBlockY, BlockZ))
+ {
+ cBlockDoorHandler::SetOpen(ChunkInterface, BlockX, a_RelBlockY, BlockZ, true);
+ m_Chunk->BroadcastSoundParticleEffect(1003, BlockX, a_RelBlockY, BlockZ, 0);
+ }
+ SetPlayerToggleableBlockAsSimulated(a_RelBlockX, a_RelBlockY, a_RelBlockZ, true);
}
}
else
{
- if (!AreCoordsSimulated(a_BlockX, a_BlockY, a_BlockZ, false))
+ if (!AreCoordsSimulated(a_RelBlockX, a_RelBlockY, a_RelBlockZ, false))
{
cChunkInterface ChunkInterface(m_World.GetChunkMap());
- cBlockDoorHandler::ChangeDoor(ChunkInterface, a_BlockX, a_BlockY, a_BlockZ);
- m_World.BroadcastSoundParticleEffect(1003, a_BlockX, a_BlockY, a_BlockZ, 0);
- SetPlayerToggleableBlockAsSimulated(a_BlockX, a_BlockY, a_BlockZ, false);
+ if (cBlockDoorHandler::IsOpen(ChunkInterface, BlockX, a_RelBlockY, BlockZ))
+ {
+ cBlockDoorHandler::SetOpen(ChunkInterface, BlockX, a_RelBlockY, BlockZ, false);
+ m_Chunk->BroadcastSoundParticleEffect(1003, BlockX, a_RelBlockY, BlockZ, 0);
+ }
+ SetPlayerToggleableBlockAsSimulated(a_RelBlockX, a_RelBlockY, a_RelBlockZ, false);
}
}
}
@@ -849,7 +940,7 @@ void cIncrementalRedstoneSimulator::HandleDoor(int a_BlockX, int a_BlockY, int a
-void cIncrementalRedstoneSimulator::HandleCommandBlock(int a_BlockX, int a_BlockY, int a_BlockZ)
+void cIncrementalRedstoneSimulator::HandleCommandBlock(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ)
{
class cSetPowerToCommandBlock :
public cCommandBlockCallback
@@ -863,37 +954,39 @@ void cIncrementalRedstoneSimulator::HandleCommandBlock(int a_BlockX, int a_Block
a_CommandBlock->SetRedstonePower(m_IsPowered);
return false;
}
- } CmdBlockSP (AreCoordsPowered(a_BlockX, a_BlockY, a_BlockZ));
+ } CmdBlockSP (AreCoordsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ));
- m_World.DoWithCommandBlockAt(a_BlockX, a_BlockY, a_BlockZ, CmdBlockSP);
+ int BlockX = (m_Chunk->GetPosX() * cChunkDef::Width) + a_RelBlockX;
+ int BlockZ = (m_Chunk->GetPosZ() * cChunkDef::Width) + a_RelBlockZ;
+ m_Chunk->DoWithCommandBlockAt(BlockX, a_RelBlockY, BlockZ, CmdBlockSP);
}
-void cIncrementalRedstoneSimulator::HandleRail(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_MyType)
+void cIncrementalRedstoneSimulator::HandleRail(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, BLOCKTYPE a_MyType)
{
switch (a_MyType)
{
case E_BLOCK_DETECTOR_RAIL:
{
- if ((m_World.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ) & 0x08) == 0x08)
+ if ((m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ) & 0x08) == 0x08)
{
- SetAllDirsAsPowered(a_BlockX, a_BlockY, a_BlockZ, a_MyType);
+ SetAllDirsAsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, a_MyType);
}
break;
}
case E_BLOCK_ACTIVATOR_RAIL:
case E_BLOCK_POWERED_RAIL:
{
- if (AreCoordsPowered(a_BlockX, a_BlockY, a_BlockZ))
+ if (AreCoordsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ))
{
- m_World.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, m_World.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ) | 0x08);
+ m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ) | 0x08);
}
else
{
- m_World.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, m_World.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ) & 0x07);
+ m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ) & 0x07);
}
break;
}
@@ -905,22 +998,25 @@ void cIncrementalRedstoneSimulator::HandleRail(int a_BlockX, int a_BlockY, int a
-void cIncrementalRedstoneSimulator::HandleTrapdoor(int a_BlockX, int a_BlockY, int a_BlockZ)
+void cIncrementalRedstoneSimulator::HandleTrapdoor(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ)
{
- if (AreCoordsPowered(a_BlockX, a_BlockY, a_BlockZ))
+ int BlockX = (m_Chunk->GetPosX() * cChunkDef::Width) + a_RelBlockX;
+ int BlockZ = (m_Chunk->GetPosZ() * cChunkDef::Width) + a_RelBlockZ;
+
+ if (AreCoordsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ))
{
- if (!AreCoordsSimulated(a_BlockX, a_BlockY, a_BlockZ, true))
+ if (!AreCoordsSimulated(a_RelBlockX, a_RelBlockY, a_RelBlockZ, true))
{
- m_World.SetTrapdoorOpen(a_BlockX, a_BlockY, a_BlockZ, true);
- SetPlayerToggleableBlockAsSimulated(a_BlockX, a_BlockY, a_BlockZ, true);
+ m_World.SetTrapdoorOpen(BlockX, a_RelBlockY, BlockZ, true);
+ SetPlayerToggleableBlockAsSimulated(a_RelBlockX, a_RelBlockY, a_RelBlockZ, true);
}
}
else
{
- if (!AreCoordsSimulated(a_BlockX, a_BlockY, a_BlockZ, false))
+ if (!AreCoordsSimulated(a_RelBlockX, a_RelBlockY, a_RelBlockZ, false))
{
- m_World.SetTrapdoorOpen(a_BlockX, a_BlockY, a_BlockZ, false);
- SetPlayerToggleableBlockAsSimulated(a_BlockX, a_BlockY, a_BlockZ, false);
+ m_World.SetTrapdoorOpen(BlockX, a_RelBlockY, BlockZ, false);
+ SetPlayerToggleableBlockAsSimulated(a_RelBlockX, a_RelBlockY, a_RelBlockZ, false);
}
}
}
@@ -929,13 +1025,13 @@ void cIncrementalRedstoneSimulator::HandleTrapdoor(int a_BlockX, int a_BlockY, i
-void cIncrementalRedstoneSimulator::HandleNoteBlock(int a_BlockX, int a_BlockY, int a_BlockZ)
+void cIncrementalRedstoneSimulator::HandleNoteBlock(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ)
{
- bool m_bAreCoordsPowered = AreCoordsPowered(a_BlockX, a_BlockY, a_BlockZ);
+ bool m_bAreCoordsPowered = AreCoordsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ);
if (m_bAreCoordsPowered)
{
- if (!AreCoordsSimulated(a_BlockX, a_BlockY, a_BlockZ, true))
+ if (!AreCoordsSimulated(a_RelBlockX, a_RelBlockY, a_RelBlockZ, true))
{
class cSetPowerToNoteBlock :
public cNoteBlockCallback
@@ -954,15 +1050,17 @@ void cIncrementalRedstoneSimulator::HandleNoteBlock(int a_BlockX, int a_BlockY,
}
} NoteBlockSP(m_bAreCoordsPowered);
- m_World.DoWithNoteBlockAt(a_BlockX, a_BlockY, a_BlockZ, NoteBlockSP);
- SetPlayerToggleableBlockAsSimulated(a_BlockX, a_BlockY, a_BlockZ, true);
+ int BlockX = (m_Chunk->GetPosX() * cChunkDef::Width) + a_RelBlockX;
+ int BlockZ = (m_Chunk->GetPosZ() * cChunkDef::Width) + a_RelBlockZ;
+ m_Chunk->DoWithNoteBlockAt(BlockX, a_RelBlockY, BlockZ, NoteBlockSP);
+ SetPlayerToggleableBlockAsSimulated(a_RelBlockX, a_RelBlockY, a_RelBlockZ, true);
}
}
else
{
- if (!AreCoordsSimulated(a_BlockX, a_BlockY, a_BlockZ, false))
+ if (!AreCoordsSimulated(a_RelBlockX, a_RelBlockY, a_RelBlockZ, false))
{
- SetPlayerToggleableBlockAsSimulated(a_BlockX, a_BlockY, a_BlockZ, false);
+ SetPlayerToggleableBlockAsSimulated(a_RelBlockX, a_RelBlockY, a_RelBlockZ, false);
}
}
}
@@ -971,21 +1069,25 @@ void cIncrementalRedstoneSimulator::HandleNoteBlock(int a_BlockX, int a_BlockY,
-void cIncrementalRedstoneSimulator::HandleDaylightSensor(int a_BlockX, int a_BlockY, int a_BlockZ)
+void cIncrementalRedstoneSimulator::HandleDaylightSensor(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ)
{
- int a_ChunkX, a_ChunkZ;
- cChunkDef::BlockToChunk(a_BlockX, a_BlockZ, a_ChunkX, a_ChunkZ);
+ int BlockX = (m_Chunk->GetPosX() * cChunkDef::Width) + a_RelBlockX, BlockZ = (m_Chunk->GetPosZ() * cChunkDef::Width) + a_RelBlockZ;
+ int ChunkX, ChunkZ;
+ cChunkDef::BlockToChunk(BlockX, BlockZ, ChunkX, ChunkZ);
- if (!m_World.IsChunkLighted(a_ChunkX, a_ChunkZ))
+ if (!m_World.IsChunkLighted(ChunkX, ChunkZ))
{
- m_World.QueueLightChunk(a_ChunkX, a_ChunkZ);
+ m_World.QueueLightChunk(ChunkX, ChunkZ);
}
else
{
- NIBBLETYPE SkyLight = m_World.GetBlockSkyLight(a_BlockX, a_BlockY + 1, a_BlockZ) - m_World.GetSkyDarkness();
- if (SkyLight > 8)
+ if (m_Chunk->GetTimeAlteredLight(m_World.GetBlockSkyLight(BlockX, a_RelBlockY + 1, BlockZ)) > 8)
+ {
+ SetAllDirsAsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ);
+ }
+ else
{
- SetAllDirsAsPowered(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_DAYLIGHT_SENSOR);
+ WakeUp(BlockX, a_RelBlockY, BlockZ, m_Chunk);
}
}
}
@@ -994,24 +1096,28 @@ void cIncrementalRedstoneSimulator::HandleDaylightSensor(int a_BlockX, int a_Blo
-void cIncrementalRedstoneSimulator::HandlePressurePlate(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_MyType)
+void cIncrementalRedstoneSimulator::HandlePressurePlate(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, BLOCKTYPE a_MyType)
{
+ int BlockX = (m_Chunk->GetPosX() * cChunkDef::Width) + a_RelBlockX;
+ int BlockZ = (m_Chunk->GetPosZ() * cChunkDef::Width) + a_RelBlockZ;
+
switch (a_MyType)
{
case E_BLOCK_STONE_PRESSURE_PLATE:
{
// MCS feature - stone pressure plates can only be triggered by players :D
- cPlayer * a_Player = m_World.FindClosestPlayer(Vector3f(a_BlockX + 0.5f, (float)a_BlockY, a_BlockZ + 0.5f), 0.5f, false);
+ cPlayer * a_Player = m_World.FindClosestPlayer(Vector3f(BlockX + 0.5f, (float)a_RelBlockY, BlockZ + 0.5f), 0.5f, false);
if (a_Player != NULL)
{
- m_World.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, 0x1);
- SetAllDirsAsPowered(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_STONE_PRESSURE_PLATE);
+ m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, 0x1);
+ SetAllDirsAsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ);
+ SetDirectionLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, BLOCK_FACE_YM, a_MyType);
}
else
{
- m_World.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, 0x0);
- m_World.WakeUpSimulators(a_BlockX, a_BlockY, a_BlockZ);
+ m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, 0x0);
+ SetSourceUnpowered(BlockX, a_RelBlockY, BlockZ, m_Chunk);
}
break;
}
@@ -1035,7 +1141,7 @@ void cIncrementalRedstoneSimulator::HandlePressurePlate(int a_BlockX, int a_Bloc
Vector3f BlockPos(m_X + 0.5f, (float)m_Y, m_Z + 0.5f);
double Distance = (EntityPos - BlockPos).Length();
- if (Distance <= 0.7)
+ if (Distance <= 0.5)
{
m_NumberOfEntities++;
}
@@ -1056,95 +1162,98 @@ void cIncrementalRedstoneSimulator::HandlePressurePlate(int a_BlockX, int a_Bloc
int m_Z;
};
- cPressurePlateCallback PressurePlateCallback(a_BlockX, a_BlockY, a_BlockZ);
- m_World.ForEachEntity(PressurePlateCallback);
+ cPressurePlateCallback PressurePlateCallback(BlockX, a_RelBlockY, BlockZ);
+ m_World.ForEachEntityInChunk(m_Chunk->GetPosX(), m_Chunk->GetPosZ(), PressurePlateCallback);
unsigned char Power;
- NIBBLETYPE Meta = m_World.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ);
+ NIBBLETYPE Meta = m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ);
if (PressurePlateCallback.GetPowerLevel(Power))
{
if (Meta == E_META_PRESSURE_PLATE_RAISED)
{
- m_World.BroadcastSoundEffect("random.click", (int)((a_BlockX + 0.5) * 8.0), (int)((a_BlockY + 0.1) * 8.0), (int)((a_BlockZ + 0.5) * 8.0), 0.3F, 0.5F);
+ m_Chunk->BroadcastSoundEffect("random.click", (double)BlockX + 0.5, (double)a_RelBlockY + 0.1, (double)BlockZ + 0.5, 0.3F, 0.5F);
}
- m_World.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, E_META_PRESSURE_PLATE_DEPRESSED);
- SetAllDirsAsPowered(a_BlockX, a_BlockY, a_BlockZ, a_MyType, Power);
+ m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, E_META_PRESSURE_PLATE_DEPRESSED);
+ SetAllDirsAsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, Power);
+ SetDirectionLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, BLOCK_FACE_YM, a_MyType);
}
else
{
if (Meta == E_META_PRESSURE_PLATE_DEPRESSED)
{
- m_World.BroadcastSoundEffect("random.click", (int)((a_BlockX + 0.5) * 8.0), (int)((a_BlockY + 0.1) * 8.0), (int)((a_BlockZ + 0.5) * 8.0), 0.3F, 0.6F);
+ m_Chunk->BroadcastSoundEffect("random.click", (double)BlockX + 0.5, (double)a_RelBlockY + 0.1, (double)BlockZ + 0.5, 0.3F, 0.6F);
}
- m_World.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, E_META_PRESSURE_PLATE_RAISED);
- m_World.WakeUpSimulators(a_BlockX, a_BlockY, a_BlockZ);
+ m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, E_META_PRESSURE_PLATE_RAISED);
+ SetSourceUnpowered(BlockX, a_RelBlockY, BlockZ, m_Chunk);
}
break;
}
case E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE:
- {class cPressurePlateCallback :
- public cEntityCallback
{
- public:
- cPressurePlateCallback(int a_BlockX, int a_BlockY, int a_BlockZ) :
- m_NumberOfEntities(0),
- m_X(a_BlockX),
- m_Y(a_BlockY),
- m_Z(a_BlockZ)
- {
- }
-
- virtual bool Item(cEntity * a_Entity) override
+ class cPressurePlateCallback :
+ public cEntityCallback
{
- Vector3f EntityPos = a_Entity->GetPosition();
- Vector3f BlockPos(m_X + 0.5f, (float)m_Y, m_Z + 0.5f);
- double Distance = (EntityPos - BlockPos).Length();
+ public:
+ cPressurePlateCallback(int a_BlockX, int a_BlockY, int a_BlockZ) :
+ m_NumberOfEntities(0),
+ m_X(a_BlockX),
+ m_Y(a_BlockY),
+ m_Z(a_BlockZ)
+ {
+ }
- if (Distance <= 0.7)
+ virtual bool Item(cEntity * a_Entity) override
{
- m_NumberOfEntities++;
+ Vector3f EntityPos = a_Entity->GetPosition();
+ Vector3f BlockPos(m_X + 0.5f, (float)m_Y, m_Z + 0.5f);
+ double Distance = (EntityPos - BlockPos).Length();
+
+ if (Distance <= 0.5)
+ {
+ m_NumberOfEntities++;
+ }
+ return false;
}
- return false;
- }
- bool GetPowerLevel(unsigned char & a_PowerLevel) const
- {
- a_PowerLevel = std::min((int)ceil(m_NumberOfEntities / (float)10), MAX_POWER_LEVEL);
- return (a_PowerLevel > 0);
- }
+ bool GetPowerLevel(unsigned char & a_PowerLevel) const
+ {
+ a_PowerLevel = std::min((int)ceil(m_NumberOfEntities / 10.f), MAX_POWER_LEVEL);
+ return (a_PowerLevel > 0);
+ }
- protected:
- int m_NumberOfEntities;
+ protected:
+ int m_NumberOfEntities;
- int m_X;
- int m_Y;
- int m_Z;
- };
+ int m_X;
+ int m_Y;
+ int m_Z;
+ };
- cPressurePlateCallback PressurePlateCallback(a_BlockX, a_BlockY, a_BlockZ);
- m_World.ForEachEntity(PressurePlateCallback);
+ cPressurePlateCallback PressurePlateCallback(BlockX, a_RelBlockY, BlockZ);
+ m_World.ForEachEntityInChunk(m_Chunk->GetPosX(), m_Chunk->GetPosZ(), PressurePlateCallback);
- unsigned char Power;
- NIBBLETYPE Meta = m_World.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ);
- if (PressurePlateCallback.GetPowerLevel(Power))
- {
- if (Meta == E_META_PRESSURE_PLATE_RAISED)
+ unsigned char Power;
+ NIBBLETYPE Meta = m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ);
+ if (PressurePlateCallback.GetPowerLevel(Power))
{
- m_World.BroadcastSoundEffect("random.click", (int)((a_BlockX + 0.5) * 8.0), (int)((a_BlockY + 0.1) * 8.0), (int)((a_BlockZ + 0.5) * 8.0), 0.3F, 0.5F);
+ if (Meta == E_META_PRESSURE_PLATE_RAISED)
+ {
+ m_Chunk->BroadcastSoundEffect("random.click", (double)BlockX + 0.5, (double)a_RelBlockY + 0.1, (double)BlockZ + 0.5, 0.3F, 0.5F);
+ }
+ m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, E_META_PRESSURE_PLATE_DEPRESSED);
+ SetAllDirsAsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, Power);
+ SetDirectionLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, BLOCK_FACE_YM, a_MyType);
}
- m_World.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, E_META_PRESSURE_PLATE_DEPRESSED);
- SetAllDirsAsPowered(a_BlockX, a_BlockY, a_BlockZ, a_MyType, Power);
- }
- else
- {
- if (Meta == E_META_PRESSURE_PLATE_DEPRESSED)
+ else
{
- m_World.BroadcastSoundEffect("random.click", (int)((a_BlockX + 0.5) * 8.0), (int)((a_BlockY + 0.1) * 8.0), (int)((a_BlockZ + 0.5) * 8.0), 0.3F, 0.6F);
+ if (Meta == E_META_PRESSURE_PLATE_DEPRESSED)
+ {
+ m_Chunk->BroadcastSoundEffect("random.click", (double)BlockX + 0.5, (double)a_RelBlockY + 0.1, (double)BlockZ + 0.5, 0.3F, 0.6F);
+ }
+ m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, E_META_PRESSURE_PLATE_RAISED);
+ SetSourceUnpowered(BlockX, a_RelBlockY, BlockZ, m_Chunk);
}
- m_World.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, E_META_PRESSURE_PLATE_RAISED);
- m_World.WakeUpSimulators(a_BlockX, a_BlockY, a_BlockZ);
- }
break;
}
@@ -1168,10 +1277,10 @@ void cIncrementalRedstoneSimulator::HandlePressurePlate(int a_BlockX, int a_Bloc
Vector3f BlockPos(m_X + 0.5f, (float)m_Y, m_Z + 0.5f);
double Distance = (EntityPos - BlockPos).Length();
- if (Distance <= 0.7)
+ if (Distance <= 0.5)
{
m_FoundEntity = true;
- return true; // Break out, we only need to know for plates that at least one entity is on top
+ return true; // Break out, we only need to know for plates that at least one entity is on top
}
return false;
}
@@ -1189,27 +1298,28 @@ void cIncrementalRedstoneSimulator::HandlePressurePlate(int a_BlockX, int a_Bloc
int m_Z;
} ;
- cPressurePlateCallback PressurePlateCallback(a_BlockX, a_BlockY, a_BlockZ);
- m_World.ForEachEntity(PressurePlateCallback);
+ cPressurePlateCallback PressurePlateCallback(BlockX, a_RelBlockY, BlockZ);
+ m_World.ForEachEntityInChunk(m_Chunk->GetPosX(), m_Chunk->GetPosZ(), PressurePlateCallback);
- NIBBLETYPE Meta = m_World.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ);
+ NIBBLETYPE Meta = m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ);
if (PressurePlateCallback.FoundEntity())
{
if (Meta == E_META_PRESSURE_PLATE_RAISED)
{
- m_World.BroadcastSoundEffect("random.click", (int) ((a_BlockX + 0.5) * 8.0), (int) ((a_BlockY + 0.1) * 8.0), (int) ((a_BlockZ + 0.5) * 8.0), 0.3F, 0.5F);
+ m_Chunk->BroadcastSoundEffect("random.click", (double)BlockX + 0.5, (double)a_RelBlockY + 0.1, (double)BlockZ + 0.5, 0.3F, 0.5F);
}
- m_World.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, E_META_PRESSURE_PLATE_DEPRESSED);
- SetAllDirsAsPowered(a_BlockX, a_BlockY, a_BlockZ, a_MyType);
+ m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, E_META_PRESSURE_PLATE_DEPRESSED);
+ SetAllDirsAsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ);
+ SetDirectionLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, BLOCK_FACE_YM, a_MyType);
}
else
{
if (Meta == E_META_PRESSURE_PLATE_DEPRESSED)
{
- m_World.BroadcastSoundEffect("random.click", (int) ((a_BlockX + 0.5) * 8.0), (int) ((a_BlockY + 0.1) * 8.0), (int) ((a_BlockZ + 0.5) * 8.0), 0.3F, 0.6F);
+ m_Chunk->BroadcastSoundEffect("random.click", (double)BlockX + 0.5, (double)a_RelBlockY + 0.1, (double)BlockZ + 0.5, 0.3F, 0.6F);
}
- m_World.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, E_META_PRESSURE_PLATE_RAISED);
- m_World.WakeUpSimulators(a_BlockX, a_BlockY, a_BlockZ);
+ m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, E_META_PRESSURE_PLATE_RAISED);
+ SetSourceUnpowered(BlockX, a_RelBlockY, BlockZ, m_Chunk);
}
break;
}
@@ -1225,27 +1335,204 @@ void cIncrementalRedstoneSimulator::HandlePressurePlate(int a_BlockX, int a_Bloc
-bool cIncrementalRedstoneSimulator::AreCoordsDirectlyPowered(int a_BlockX, int a_BlockY, int a_BlockZ)
+void cIncrementalRedstoneSimulator::HandleTripwireHook(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ)
{
- for (PoweredBlocksList::const_iterator itr = m_PoweredBlocks->begin(); itr != m_PoweredBlocks->end(); ++itr) // Check powered list
+ int BlockX = m_Chunk->GetPosX() * cChunkDef::Width + a_RelBlockX;
+ int BlockZ = m_Chunk->GetPosZ() * cChunkDef::Width + a_RelBlockZ;
+ int RelX = a_RelBlockX, RelZ = a_RelBlockZ;
+ bool FoundActivated = false;
+ eBlockFace FaceToGoTowards = cBlockTripwireHookHandler::MetadataToDirection(m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ));
+
+ for (int i = 0; i < 40; ++i) // Tripwires can be connected up to 40 blocks
{
- if (itr->a_BlockPos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ)))
+ BLOCKTYPE Type;
+ NIBBLETYPE Meta;
+
+ AddFaceDirection(RelX, a_RelBlockY, RelZ, FaceToGoTowards);
+ m_Chunk->UnboundedRelGetBlock(RelX, a_RelBlockY, RelZ, Type, Meta);
+
+ if (Type == E_BLOCK_TRIPWIRE)
+ {
+ if (Meta == 0x1)
+ {
+ FoundActivated = true;
+ }
+ }
+ else if (Type == E_BLOCK_TRIPWIRE_HOOK)
+ {
+ if (ReverseBlockFace(cBlockTripwireHookHandler::MetadataToDirection(Meta)) == FaceToGoTowards)
+ {
+ // Other hook facing in opposite direction - circuit completed!
+ break;
+ }
+ else
+ {
+ // Tripwire hook not connected at all, AND away all the power state bits
+ m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ) & 0x3);
+ SetSourceUnpowered(BlockX, a_RelBlockY, BlockZ, m_Chunk);
+ return;
+ }
+ }
+ else
+ {
+ // Tripwire hook not connected at all, AND away all the power state bits
+ m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ) & 0x3);
+ SetSourceUnpowered(BlockX, a_RelBlockY, BlockZ, m_Chunk);
+ return;
+ }
+ }
+
+ if (FoundActivated)
+ {
+ // Connected and activated, set the 3rd and 4th highest bits
+ m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ) | 0xC);
+ SetAllDirsAsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ);
+ }
+ else
+ {
+ // Connected but not activated, AND away the highest bit
+ m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, (m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ) & 0x7) | 0x4);
+ SetSourceUnpowered(BlockX, a_RelBlockY, BlockZ, m_Chunk);
+ }
+}
+
+
+
+
+
+void cIncrementalRedstoneSimulator::HandleTrappedChest(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ)
+{
+ class cGetTrappedChestPlayers :
+ public cChestCallback
+ {
+ public:
+ cGetTrappedChestPlayers(void) :
+ m_NumberOfPlayers(0)
+ {
+ }
+
+ virtual bool Item(cChestEntity * a_Chest) override
+ {
+ ASSERT(a_Chest->GetBlockType() == E_BLOCK_TRAPPED_CHEST);
+ m_NumberOfPlayers = a_Chest->GetNumberOfPlayers();
+ return (m_NumberOfPlayers <= 0);
+ }
+
+ unsigned char GetPowerLevel(void) const
+ {
+ return std::min(m_NumberOfPlayers, MAX_POWER_LEVEL);
+ }
+
+ private:
+ int m_NumberOfPlayers;
+
+ } GTCP;
+
+ int BlockX = m_Chunk->GetPosX() * cChunkDef::Width + a_RelBlockX;
+ int BlockZ = m_Chunk->GetPosZ() * cChunkDef::Width + a_RelBlockZ;
+ if (m_Chunk->DoWithChestAt(BlockX, a_RelBlockY, BlockZ, GTCP))
+ {
+ SetAllDirsAsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, GTCP.GetPowerLevel());
+ }
+ else
+ {
+ SetSourceUnpowered(BlockX, a_RelBlockY, BlockZ, m_Chunk);
+ }
+}
+
+
+
+
+
+void cIncrementalRedstoneSimulator::HandleTripwire(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ)
+{
+ int BlockX = m_Chunk->GetPosX() * cChunkDef::Width + a_RelBlockX;
+ int BlockZ = m_Chunk->GetPosZ() * cChunkDef::Width + a_RelBlockZ;
+
+ class cTripwireCallback :
+ public cEntityCallback
+ {
+ public:
+ cTripwireCallback(int a_BlockX, int a_BlockY, int a_BlockZ) :
+ m_FoundEntity(false),
+ m_X(a_BlockX),
+ m_Y(a_BlockY),
+ m_Z(a_BlockZ)
+ {
+ }
+
+ virtual bool Item(cEntity * a_Entity) override
+ {
+ cBoundingBox bbWire(m_X, m_X + 1, m_Y, m_Y + 0.1, m_Z, m_Z + 1);
+ cBoundingBox bbEntity(a_Entity->GetPosition(), a_Entity->GetWidth() / 2, a_Entity->GetHeight());
+
+ if (bbEntity.DoesIntersect(bbWire))
+ {
+ m_FoundEntity = true;
+ return true; // One entity is sufficient to trigger the wire
+ }
+ return false;
+ }
+
+ bool FoundEntity(void) const
+ {
+ return m_FoundEntity;
+ }
+
+ protected:
+ bool m_FoundEntity;
+
+ int m_X;
+ int m_Y;
+ int m_Z;
+ };
+
+ cTripwireCallback TripwireCallback(BlockX, a_RelBlockY, BlockZ);
+ m_World.ForEachEntityInChunk(m_Chunk->GetPosX(), m_Chunk->GetPosZ(), TripwireCallback);
+
+ if (TripwireCallback.FoundEntity())
+ {
+ m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, 0x1);
+ }
+ else
+ {
+ m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, 0x0);
+ }
+}
+
+
+
+
+
+bool cIncrementalRedstoneSimulator::AreCoordsDirectlyPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, cChunk * a_Chunk)
+{
+ // Torches want to access neighbour's data when on a wall, hence the extra chunk parameter
+
+ int BlockX = (m_Chunk->GetPosX() * cChunkDef::Width) + a_RelBlockX;
+ int BlockZ = (m_Chunk->GetPosZ() * cChunkDef::Width) + a_RelBlockZ;
+
+ for (PoweredBlocksList::const_iterator itr = a_Chunk->GetRedstoneSimulatorPoweredBlocksList()->begin(); itr != a_Chunk->GetRedstoneSimulatorPoweredBlocksList()->end(); ++itr) // Check powered list
+ {
+ if (itr->a_BlockPos.Equals(Vector3i(BlockX, a_RelBlockY, BlockZ)))
{
return true;
}
}
- return false;
+ return false;
}
-bool cIncrementalRedstoneSimulator::AreCoordsLinkedPowered(int a_BlockX, int a_BlockY, int a_BlockZ)
+bool cIncrementalRedstoneSimulator::AreCoordsLinkedPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ)
{
- for (LinkedBlocksList::const_iterator itr = m_LinkedPoweredBlocks->begin(); itr != m_LinkedPoweredBlocks->end(); ++itr) // Check linked powered list
+ int BlockX = (m_Chunk->GetPosX() * cChunkDef::Width) + a_RelBlockX;
+ int BlockZ = (m_Chunk->GetPosZ() * cChunkDef::Width) + a_RelBlockZ;
+
+ for (LinkedBlocksList::const_iterator itr = m_LinkedPoweredBlocks->begin(); itr != m_LinkedPoweredBlocks->end(); ++itr) // Check linked powered list
{
- if (itr->a_BlockPos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ)))
+ if (itr->a_BlockPos.Equals(Vector3i(BlockX, a_RelBlockY, BlockZ)))
{
return true;
}
@@ -1256,37 +1543,38 @@ bool cIncrementalRedstoneSimulator::AreCoordsLinkedPowered(int a_BlockX, int a_B
-// IsRepeaterPowered tests if a repeater should be powered by testing for power sources behind the repeater.
-// It takes the coordinates of the repeater the the meta value.
-bool cIncrementalRedstoneSimulator::IsRepeaterPowered(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_Meta)
+
+bool cIncrementalRedstoneSimulator::IsRepeaterPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, NIBBLETYPE a_Meta)
{
// Repeaters cannot be powered by any face except their back; verify that this is true for a source
+ int BlockX = (m_Chunk->GetPosX() * cChunkDef::Width) + a_RelBlockX;
+ int BlockZ = (m_Chunk->GetPosZ() * cChunkDef::Width) + a_RelBlockZ;
for (PoweredBlocksList::const_iterator itr = m_PoweredBlocks->begin(); itr != m_PoweredBlocks->end(); ++itr)
{
- if (!itr->a_BlockPos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ))) { continue; }
+ if (!itr->a_BlockPos.Equals(Vector3i(BlockX, a_RelBlockY, BlockZ))) { continue; }
switch (a_Meta & 0x3)
{
case 0x0:
{
// Flip the coords to check the back of the repeater
- if (itr->a_SourcePos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ + 1))) { return true; }
+ if (itr->a_SourcePos.Equals(Vector3i(BlockX, a_RelBlockY, BlockZ + 1))) { return true; }
break;
}
case 0x1:
{
- if (itr->a_SourcePos.Equals(Vector3i(a_BlockX - 1, a_BlockY, a_BlockZ))) { return true; }
+ if (itr->a_SourcePos.Equals(Vector3i(BlockX - 1, a_RelBlockY, BlockZ))) { return true; }
break;
}
case 0x2:
{
- if (itr->a_SourcePos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ - 1))) { return true; }
+ if (itr->a_SourcePos.Equals(Vector3i(BlockX, a_RelBlockY, BlockZ - 1))) { return true; }
break;
}
case 0x3:
{
- if (itr->a_SourcePos.Equals(Vector3i(a_BlockX + 1, a_BlockY, a_BlockZ))) { return true; }
+ if (itr->a_SourcePos.Equals(Vector3i(BlockX + 1, a_RelBlockY, BlockZ))) { return true; }
break;
}
}
@@ -1294,59 +1582,60 @@ bool cIncrementalRedstoneSimulator::IsRepeaterPowered(int a_BlockX, int a_BlockY
for (LinkedBlocksList::const_iterator itr = m_LinkedPoweredBlocks->begin(); itr != m_LinkedPoweredBlocks->end(); ++itr)
{
- if (!itr->a_BlockPos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ))) { continue; }
+ if (!itr->a_BlockPos.Equals(Vector3i(BlockX, a_RelBlockY, BlockZ))) { continue; }
switch (a_Meta & 0x3)
{
case 0x0:
{
- if (itr->a_MiddlePos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ + 1))) { return true; }
+ if (itr->a_MiddlePos.Equals(Vector3i(BlockX, a_RelBlockY, BlockZ + 1))) { return true; }
break;
}
case 0x1:
{
- if (itr->a_MiddlePos.Equals(Vector3i(a_BlockX - 1, a_BlockY, a_BlockZ))) { return true; }
+ if (itr->a_MiddlePos.Equals(Vector3i(BlockX - 1, a_RelBlockY, BlockZ))) { return true; }
break;
}
case 0x2:
{
- if (itr->a_MiddlePos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ - 1))) { return true; }
+ if (itr->a_MiddlePos.Equals(Vector3i(BlockX, a_RelBlockY, BlockZ - 1))) { return true; }
break;
}
case 0x3:
{
- if (itr->a_MiddlePos.Equals(Vector3i(a_BlockX + 1, a_BlockY, a_BlockZ))) { return true; }
+ if (itr->a_MiddlePos.Equals(Vector3i(BlockX + 1, a_RelBlockY, BlockZ))) { return true; }
break;
}
}
}
- return false; // Couldn't find power source behind repeater
+ return false; // Couldn't find power source behind repeater
}
-bool cIncrementalRedstoneSimulator::IsRepeaterLocked(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_Meta)
-{
- switch (a_Meta & 0x3) // We only want the 'direction' part of our metadata
+bool cIncrementalRedstoneSimulator::IsRepeaterLocked(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, NIBBLETYPE a_Meta)
+{
+ switch (a_Meta & 0x3) // We only want the 'direction' part of our metadata
{
// If the repeater is looking up or down (If parallel to the Z axis)
case 0x0:
case 0x2:
{
- // Check if eastern(right) neighbor is a powered on repeater who is facing us.
- if (m_World.GetBlock(a_BlockX + 1, a_BlockY, a_BlockZ) == E_BLOCK_REDSTONE_REPEATER_ON) // Is right neighbor a powered repeater?
+ // Check if eastern(right) neighbor is a powered on repeater who is facing us
+ BLOCKTYPE Block = 0;
+ if (m_Chunk->UnboundedRelGetBlockType(a_RelBlockX + 1, a_RelBlockY, a_RelBlockZ, Block) && (Block == E_BLOCK_REDSTONE_REPEATER_ON)) // Is right neighbor a powered repeater?
{
- NIBBLETYPE OtherRepeaterDir = m_World.GetBlockMeta(a_BlockX + 1, a_BlockY, a_BlockZ) & 0x3;
- if (OtherRepeaterDir == 0x3) { return true; } // If so, I am latched/locked.
+ NIBBLETYPE OtherRepeaterDir = m_Chunk->GetMeta(a_RelBlockX + 1, a_RelBlockY, a_RelBlockZ) & 0x3;
+ if (OtherRepeaterDir == 0x3) { return true; } // If so, I am latched/locked
}
- // Check if western(left) neighbor is a powered on repeater who is facing us.
- if (m_World.GetBlock(a_BlockX - 1, a_BlockY, a_BlockZ) == E_BLOCK_REDSTONE_REPEATER_ON)
+ // Check if western(left) neighbor is a powered on repeater who is facing us
+ if (m_Chunk->UnboundedRelGetBlockType(a_RelBlockX - 1, a_RelBlockY, a_RelBlockZ, Block) && (Block == E_BLOCK_REDSTONE_REPEATER_ON))
{
- NIBBLETYPE OtherRepeaterDir = m_World.GetBlockMeta(a_BlockX -1, a_BlockY, a_BlockZ) & 0x3;
- if (OtherRepeaterDir == 0x1) { return true; } // If so, I am latched/locked.
+ NIBBLETYPE OtherRepeaterDir = m_Chunk->GetMeta(a_RelBlockX -1, a_RelBlockY, a_RelBlockZ) & 0x3;
+ if (OtherRepeaterDir == 0x1) { return true; } // If so, I am latched/locked
}
break;
@@ -1356,205 +1645,232 @@ bool cIncrementalRedstoneSimulator::IsRepeaterLocked(int a_BlockX, int a_BlockY,
case 0x1:
case 0x3:
{
- // Check if southern(down) neighbor is a powered on repeater who is facing us.
- if (m_World.GetBlock(a_BlockX, a_BlockY, a_BlockZ + 1) == E_BLOCK_REDSTONE_REPEATER_ON)
- {
- NIBBLETYPE OtherRepeaterDir = m_World.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ + 1) & 0x3;
- if (OtherRepeaterDir == 0x0) { return true; } // If so, am latched/locked.
+ // Check if southern(down) neighbor is a powered on repeater who is facing us
+ BLOCKTYPE Block = 0;
+ if (m_Chunk->UnboundedRelGetBlockType(a_RelBlockX, a_RelBlockY, a_RelBlockZ + 1, Block) && (Block == E_BLOCK_REDSTONE_REPEATER_ON))
+ {
+ NIBBLETYPE OtherRepeaterDir = m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ + 1) & 0x3;
+ if (OtherRepeaterDir == 0x0) { return true; } // If so, am latched/locked
}
- // Check if northern(up) neighbor is a powered on repeater who is facing us.
- if (m_World.GetBlock(a_BlockX, a_BlockY, a_BlockZ -1) == E_BLOCK_REDSTONE_REPEATER_ON)
- {
- NIBBLETYPE OtherRepeaterDir = m_World.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ - 1) & 0x3;
- if (OtherRepeaterDir == 0x2) { return true; } // If so, I am latched/locked.
+ // Check if northern(up) neighbor is a powered on repeater who is facing us
+ if (m_Chunk->UnboundedRelGetBlockType(a_RelBlockX, a_RelBlockY, a_RelBlockZ - 1, Block) && (Block == E_BLOCK_REDSTONE_REPEATER_ON))
+ {
+ NIBBLETYPE OtherRepeaterDir = m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ - 1) & 0x3;
+ if (OtherRepeaterDir == 0x2) { return true; } // If so, I am latched/locked
}
break;
}
}
- return false; // None of the checks succeeded, I am not a locked repeater.
+ return false; // None of the checks succeeded, I am not a locked repeater
}
-bool cIncrementalRedstoneSimulator::IsPistonPowered(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_Meta)
+bool cIncrementalRedstoneSimulator::IsPistonPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, NIBBLETYPE a_Meta)
{
// Pistons cannot be powered through their front face; this function verifies that a source meets this requirement
- int OldX = a_BlockX, OldY = a_BlockY, OldZ = a_BlockZ;
- eBlockFace Face = cPiston::MetaDataToDirection(a_Meta);
+ eBlockFace Face = cBlockPistonHandler::MetaDataToDirection(a_Meta);
+ int BlockX = m_Chunk->GetPosX() * cChunkDef::Width + a_RelBlockX;
+ int BlockZ = m_Chunk->GetPosZ() * cChunkDef::Width + a_RelBlockZ;
for (PoweredBlocksList::const_iterator itr = m_PoweredBlocks->begin(); itr != m_PoweredBlocks->end(); ++itr)
{
- if (!itr->a_BlockPos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ))) { continue; }
+ if (!itr->a_BlockPos.Equals(Vector3i(BlockX, a_RelBlockY, BlockZ))) { continue; }
- AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, Face);
+ AddFaceDirection(BlockX, a_RelBlockY, BlockZ, Face);
- if (!itr->a_SourcePos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ)))
+ if (!itr->a_SourcePos.Equals(Vector3i(BlockX, a_RelBlockY, BlockZ)))
{
return true;
}
- a_BlockX = OldX;
- a_BlockY = OldY;
- a_BlockZ = OldZ;
+ AddFaceDirection(BlockX, a_RelBlockY, BlockZ, Face, true);
}
for (LinkedBlocksList::const_iterator itr = m_LinkedPoweredBlocks->begin(); itr != m_LinkedPoweredBlocks->end(); ++itr)
{
- if (!itr->a_BlockPos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ))) { continue; }
+ if (!itr->a_BlockPos.Equals(Vector3i(BlockX, a_RelBlockY, BlockZ))) { continue; }
- AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, Face);
+ AddFaceDirection(BlockX, a_RelBlockY, BlockZ, Face);
- if (!itr->a_MiddlePos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ)))
+ if (!itr->a_MiddlePos.Equals(Vector3i(BlockX, a_RelBlockY, BlockZ)))
{
return true;
}
- a_BlockX = OldX;
- a_BlockY = OldY;
- a_BlockZ = OldZ;
+ AddFaceDirection(BlockX, a_RelBlockY, BlockZ, Face, true);
}
- return false; // Source was in front of the piston's front face
+ return false; // Source was in front of the piston's front face
}
-bool cIncrementalRedstoneSimulator::IsWirePowered(int a_BlockX, int a_BlockY, int a_BlockZ, unsigned char & a_PowerLevel)
+bool cIncrementalRedstoneSimulator::IsWirePowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, unsigned char & a_PowerLevel)
{
a_PowerLevel = 0;
+ int BlockX = m_Chunk->GetPosX() * cChunkDef::Width + a_RelBlockX;
+ int BlockZ = m_Chunk->GetPosZ() * cChunkDef::Width + a_RelBlockZ;
- for (PoweredBlocksList::const_iterator itr = m_PoweredBlocks->begin(); itr != m_PoweredBlocks->end(); ++itr) // Check powered list
+ for (PoweredBlocksList::const_iterator itr = m_PoweredBlocks->begin(); itr != m_PoweredBlocks->end(); ++itr) // Check powered list
{
- if (!itr->a_BlockPos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ)))
+ if (!itr->a_BlockPos.Equals(Vector3i(BlockX, a_RelBlockY, BlockZ)))
{
continue;
}
- a_PowerLevel = std::max(a_PowerLevel, itr->a_PowerLevel);
+ 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)
}
- for (LinkedBlocksList::const_iterator itr = m_LinkedPoweredBlocks->begin(); itr != m_LinkedPoweredBlocks->end(); ++itr) // Check linked powered list
+ for (LinkedBlocksList::const_iterator itr = m_LinkedPoweredBlocks->begin(); itr != m_LinkedPoweredBlocks->end(); ++itr) // Check linked powered list
{
- if (!itr->a_BlockPos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ)))
+ if (!itr->a_BlockPos.Equals(Vector3i(BlockX, a_RelBlockY, BlockZ)))
{
continue;
}
- a_PowerLevel = std::max(a_PowerLevel, itr->a_PowerLevel);
+
+ BLOCKTYPE Type = E_BLOCK_AIR;
+ int RelSourceX = itr->a_SourcePos.x - m_Chunk->GetPosX() * cChunkDef::Width;
+ int RelSourceZ = itr->a_SourcePos.z - m_Chunk->GetPosZ() * cChunkDef::Width;
+ if (!m_Chunk->UnboundedRelGetBlockType(RelSourceX, itr->a_SourcePos.y, RelSourceZ, Type) || (Type == E_BLOCK_REDSTONE_WIRE))
+ {
+ continue;
+ }
+ a_PowerLevel = std::max(itr->a_PowerLevel, a_PowerLevel);
}
- return (a_PowerLevel != 0); // Source was in front of the piston's front face
+ return (a_PowerLevel != 0); // Answer the inital question: is the wire powered?
}
-bool cIncrementalRedstoneSimulator::AreCoordsSimulated(int a_BlockX, int a_BlockY, int a_BlockZ, bool IsCurrentStatePowered)
+bool cIncrementalRedstoneSimulator::AreCoordsSimulated(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, bool IsCurrentStatePowered)
{
for (SimulatedPlayerToggleableList::const_iterator itr = m_SimulatedPlayerToggleableBlocks->begin(); itr != m_SimulatedPlayerToggleableBlocks->end(); ++itr)
{
- if (itr->a_BlockPos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ)))
+ if (itr->a_RelBlockPos.Equals(Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ)))
{
- if (itr->WasLastStatePowered != IsCurrentStatePowered) // Was the last power state different to the current?
+ if (itr->WasLastStatePowered != IsCurrentStatePowered) // Was the last power state different to the current?
{
- return false; // It was, coordinates are no longer simulated
+ return false; // It was, coordinates are no longer simulated
}
else
{
- return true; // It wasn't, don't resimulate block, and allow players to toggle
+ return true; // It wasn't, don't resimulate block, and allow players to toggle
}
}
}
- return false; // Block wasn't even in the list, not simulated
+ return false; // Block wasn't even in the list, not simulated
}
-void cIncrementalRedstoneSimulator::SetDirectionLinkedPowered(int a_BlockX, int a_BlockY, int a_BlockZ, char a_Direction, BLOCKTYPE a_SourceType, unsigned char a_PowerLevel)
+void cIncrementalRedstoneSimulator::SetDirectionLinkedPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, char a_Direction, unsigned char a_PowerLevel)
{
+ BLOCKTYPE MiddleBlock = 0;
switch (a_Direction)
{
case BLOCK_FACE_XM:
{
- BLOCKTYPE MiddleBlock = m_World.GetBlock(a_BlockX - 1, a_BlockY, a_BlockZ);
+ if (!m_Chunk->UnboundedRelGetBlockType(a_RelBlockX - 1, a_RelBlockY, a_RelBlockZ, MiddleBlock))
+ {
+ return;
+ }
- SetBlockLinkedPowered(a_BlockX - 2, a_BlockY, a_BlockZ, a_BlockX - 1, a_BlockY, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock, a_PowerLevel);
- SetBlockLinkedPowered(a_BlockX - 1, a_BlockY + 1, a_BlockZ, a_BlockX - 1, a_BlockY, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock, a_PowerLevel);
- SetBlockLinkedPowered(a_BlockX - 1, a_BlockY - 1, a_BlockZ, a_BlockX - 1, a_BlockY, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock, a_PowerLevel);
- SetBlockLinkedPowered(a_BlockX - 1, a_BlockY, a_BlockZ + 1, a_BlockX - 1, a_BlockY, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock, a_PowerLevel);
- SetBlockLinkedPowered(a_BlockX - 1, a_BlockY, a_BlockZ - 1, a_BlockX - 1, a_BlockY, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock, a_PowerLevel);
+ SetBlockLinkedPowered(a_RelBlockX - 2, a_RelBlockY, a_RelBlockZ, a_RelBlockX - 1, a_RelBlockY, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel);
+ SetBlockLinkedPowered(a_RelBlockX - 1, a_RelBlockY + 1, a_RelBlockZ, a_RelBlockX - 1, a_RelBlockY, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel);
+ SetBlockLinkedPowered(a_RelBlockX - 1, a_RelBlockY - 1, a_RelBlockZ, a_RelBlockX - 1, a_RelBlockY, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel);
+ SetBlockLinkedPowered(a_RelBlockX - 1, a_RelBlockY, a_RelBlockZ + 1, a_RelBlockX - 1, a_RelBlockY, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel);
+ SetBlockLinkedPowered(a_RelBlockX - 1, a_RelBlockY, a_RelBlockZ - 1, a_RelBlockX - 1, a_RelBlockY, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel);
break;
}
case BLOCK_FACE_XP:
{
- BLOCKTYPE MiddleBlock = m_World.GetBlock(a_BlockX + 1, a_BlockY, a_BlockZ);
+ if (!m_Chunk->UnboundedRelGetBlockType(a_RelBlockX + 1, a_RelBlockY, a_RelBlockZ, MiddleBlock))
+ {
+ return;
+ }
- SetBlockLinkedPowered(a_BlockX + 2, a_BlockY, a_BlockZ, a_BlockX + 1, a_BlockY, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock, a_PowerLevel);
- SetBlockLinkedPowered(a_BlockX + 1, a_BlockY + 1, a_BlockZ, a_BlockX + 1, a_BlockY, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock, a_PowerLevel);
- SetBlockLinkedPowered(a_BlockX + 1, a_BlockY - 1, a_BlockZ, a_BlockX + 1, a_BlockY, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock, a_PowerLevel);
- SetBlockLinkedPowered(a_BlockX + 1, a_BlockY, a_BlockZ + 1, a_BlockX + 1, a_BlockY, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock, a_PowerLevel);
- SetBlockLinkedPowered(a_BlockX + 1, a_BlockY, a_BlockZ - 1, a_BlockX + 1, a_BlockY, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock, a_PowerLevel);
+ SetBlockLinkedPowered(a_RelBlockX + 2, a_RelBlockY, a_RelBlockZ, a_RelBlockX + 1, a_RelBlockY, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel);
+ SetBlockLinkedPowered(a_RelBlockX + 1, a_RelBlockY + 1, a_RelBlockZ, a_RelBlockX + 1, a_RelBlockY, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel);
+ SetBlockLinkedPowered(a_RelBlockX + 1, a_RelBlockY - 1, a_RelBlockZ, a_RelBlockX + 1, a_RelBlockY, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel);
+ SetBlockLinkedPowered(a_RelBlockX + 1, a_RelBlockY, a_RelBlockZ + 1, a_RelBlockX + 1, a_RelBlockY, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel);
+ SetBlockLinkedPowered(a_RelBlockX + 1, a_RelBlockY, a_RelBlockZ - 1, a_RelBlockX + 1, a_RelBlockY, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel);
break;
}
case BLOCK_FACE_YM:
{
- BLOCKTYPE MiddleBlock = m_World.GetBlock(a_BlockX, a_BlockY - 1, a_BlockZ);
+ if (!m_Chunk->UnboundedRelGetBlockType(a_RelBlockX, a_RelBlockY - 1, a_RelBlockZ, MiddleBlock))
+ {
+ return;
+ }
- SetBlockLinkedPowered(a_BlockX, a_BlockY - 2, a_BlockZ, a_BlockX, a_BlockY - 1, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock, a_PowerLevel);
- SetBlockLinkedPowered(a_BlockX + 1, a_BlockY - 1, a_BlockZ, a_BlockX, a_BlockY - 1, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock, a_PowerLevel);
- SetBlockLinkedPowered(a_BlockX - 1, a_BlockY - 1, a_BlockZ, a_BlockX, a_BlockY - 1, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock, a_PowerLevel);
- SetBlockLinkedPowered(a_BlockX, a_BlockY - 1, a_BlockZ + 1, a_BlockX, a_BlockY - 1, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock, a_PowerLevel);
- SetBlockLinkedPowered(a_BlockX, a_BlockY - 1, a_BlockZ - 1, a_BlockX, a_BlockY - 1, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock, a_PowerLevel);
+ SetBlockLinkedPowered(a_RelBlockX, a_RelBlockY - 2, a_RelBlockZ, a_RelBlockX, a_RelBlockY - 1, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel);
+ SetBlockLinkedPowered(a_RelBlockX + 1, a_RelBlockY - 1, a_RelBlockZ, a_RelBlockX, a_RelBlockY - 1, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel);
+ SetBlockLinkedPowered(a_RelBlockX - 1, a_RelBlockY - 1, a_RelBlockZ, a_RelBlockX, a_RelBlockY - 1, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel);
+ SetBlockLinkedPowered(a_RelBlockX, a_RelBlockY - 1, a_RelBlockZ + 1, a_RelBlockX, a_RelBlockY - 1, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel);
+ SetBlockLinkedPowered(a_RelBlockX, a_RelBlockY - 1, a_RelBlockZ - 1, a_RelBlockX, a_RelBlockY - 1, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel);
break;
}
case BLOCK_FACE_YP:
{
- BLOCKTYPE MiddleBlock = m_World.GetBlock(a_BlockX, a_BlockY + 1, a_BlockZ);
+ if (!m_Chunk->UnboundedRelGetBlockType(a_RelBlockX, a_RelBlockY + 1, a_RelBlockZ, MiddleBlock))
+ {
+ return;
+ }
- SetBlockLinkedPowered(a_BlockX, a_BlockY + 2, a_BlockZ, a_BlockX, a_BlockY + 1, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock, a_PowerLevel);
- SetBlockLinkedPowered(a_BlockX + 1, a_BlockY + 1, a_BlockZ, a_BlockX, a_BlockY + 1, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock, a_PowerLevel);
- SetBlockLinkedPowered(a_BlockX - 1, a_BlockY + 1, a_BlockZ, a_BlockX, a_BlockY + 1, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock, a_PowerLevel);
- SetBlockLinkedPowered(a_BlockX, a_BlockY + 1, a_BlockZ + 1, a_BlockX, a_BlockY + 1, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock, a_PowerLevel);
- SetBlockLinkedPowered(a_BlockX, a_BlockY + 1, a_BlockZ - 1, a_BlockX, a_BlockY + 1, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock, a_PowerLevel);
+ SetBlockLinkedPowered(a_RelBlockX, a_RelBlockY + 2, a_RelBlockZ, a_RelBlockX, a_RelBlockY + 1, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel);
+ SetBlockLinkedPowered(a_RelBlockX + 1, a_RelBlockY + 1, a_RelBlockZ, a_RelBlockX, a_RelBlockY + 1, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel);
+ SetBlockLinkedPowered(a_RelBlockX - 1, a_RelBlockY + 1, a_RelBlockZ, a_RelBlockX, a_RelBlockY + 1, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel);
+ SetBlockLinkedPowered(a_RelBlockX, a_RelBlockY + 1, a_RelBlockZ + 1, a_RelBlockX, a_RelBlockY + 1, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel);
+ SetBlockLinkedPowered(a_RelBlockX, a_RelBlockY + 1, a_RelBlockZ - 1, a_RelBlockX, a_RelBlockY + 1, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel);
break;
}
case BLOCK_FACE_ZM:
{
- BLOCKTYPE MiddleBlock = m_World.GetBlock(a_BlockX, a_BlockY, a_BlockZ - 1);
+ if (!m_Chunk->UnboundedRelGetBlockType(a_RelBlockX, a_RelBlockY, a_RelBlockZ - 1, MiddleBlock))
+ {
+ return;
+ }
- SetBlockLinkedPowered(a_BlockX, a_BlockY, a_BlockZ - 2, a_BlockX, a_BlockY, a_BlockZ - 1, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock, a_PowerLevel);
- SetBlockLinkedPowered(a_BlockX + 1, a_BlockY, a_BlockZ - 1, a_BlockX, a_BlockY, a_BlockZ - 1, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock, a_PowerLevel);
- SetBlockLinkedPowered(a_BlockX - 1, a_BlockY, a_BlockZ - 1, a_BlockX, a_BlockY, a_BlockZ - 1, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock, a_PowerLevel);
- SetBlockLinkedPowered(a_BlockX, a_BlockY + 1, a_BlockZ - 1, a_BlockX, a_BlockY, a_BlockZ - 1, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock, a_PowerLevel);
- SetBlockLinkedPowered(a_BlockX, a_BlockY - 1, a_BlockZ - 1, a_BlockX, a_BlockY, a_BlockZ - 1, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock, a_PowerLevel);
+ SetBlockLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ - 2, a_RelBlockX, a_RelBlockY, a_RelBlockZ - 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel);
+ SetBlockLinkedPowered(a_RelBlockX + 1, a_RelBlockY, a_RelBlockZ - 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ - 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel);
+ SetBlockLinkedPowered(a_RelBlockX - 1, a_RelBlockY, a_RelBlockZ - 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ - 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel);
+ SetBlockLinkedPowered(a_RelBlockX, a_RelBlockY + 1, a_RelBlockZ - 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ - 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel);
+ SetBlockLinkedPowered(a_RelBlockX, a_RelBlockY - 1, a_RelBlockZ - 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ - 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel);
break;
}
case BLOCK_FACE_ZP:
{
- BLOCKTYPE MiddleBlock = m_World.GetBlock(a_BlockX, a_BlockY, a_BlockZ + 1);
+ if (!m_Chunk->UnboundedRelGetBlockType(a_RelBlockX, a_RelBlockY, a_RelBlockZ + 1, MiddleBlock))
+ {
+ return;
+ }
- SetBlockLinkedPowered(a_BlockX, a_BlockY, a_BlockZ + 2, a_BlockX, a_BlockY, a_BlockZ + 1, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock, a_PowerLevel);
- SetBlockLinkedPowered(a_BlockX + 1, a_BlockY, a_BlockZ + 1, a_BlockX, a_BlockY, a_BlockZ + 1, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock, a_PowerLevel);
- SetBlockLinkedPowered(a_BlockX - 1, a_BlockY, a_BlockZ + 1, a_BlockX, a_BlockY, a_BlockZ + 1, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock, a_PowerLevel);
- SetBlockLinkedPowered(a_BlockX, a_BlockY + 1, a_BlockZ + 1, a_BlockX, a_BlockY, a_BlockZ + 1, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock, a_PowerLevel);
- SetBlockLinkedPowered(a_BlockX, a_BlockY - 1, a_BlockZ + 1, a_BlockX, a_BlockY, a_BlockZ + 1, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock, a_PowerLevel);
+ SetBlockLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ + 2, a_RelBlockX, a_RelBlockY, a_RelBlockZ + 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel);
+ SetBlockLinkedPowered(a_RelBlockX + 1, a_RelBlockY, a_RelBlockZ + 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ + 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel);
+ SetBlockLinkedPowered(a_RelBlockX - 1, a_RelBlockY, a_RelBlockZ + 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ + 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel);
+ SetBlockLinkedPowered(a_RelBlockX, a_RelBlockY + 1, a_RelBlockZ + 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ + 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel);
+ SetBlockLinkedPowered(a_RelBlockX, a_RelBlockY - 1, a_RelBlockZ + 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ + 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ, MiddleBlock, a_PowerLevel);
break;
}
default:
{
- ASSERT(!"Unhandled face direction when attempting to set blocks as linked powered!"); // Zombies, that wasn't supposed to happen...
+ ASSERT(!"Unhandled face direction when attempting to set blocks as linked powered!"); // Zombies, that wasn't supposed to happen...
break;
}
}
@@ -1564,7 +1880,7 @@ void cIncrementalRedstoneSimulator::SetDirectionLinkedPowered(int a_BlockX, int
-void cIncrementalRedstoneSimulator::SetAllDirsAsPowered(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_SourceBlock, unsigned char a_PowerLevel)
+void cIncrementalRedstoneSimulator::SetAllDirsAsPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, unsigned char a_PowerLevel)
{
static const struct
{
@@ -1572,16 +1888,16 @@ void cIncrementalRedstoneSimulator::SetAllDirsAsPowered(int a_BlockX, int a_Bloc
} gCrossCoords[] =
{
{ 1, 0, 0 },
- {-1, 0, 0 },
+ { -1, 0, 0 },
{ 0, 0, 1 },
- { 0, 0,-1 },
+ { 0, 0, -1 },
{ 0, 1, 0 },
- { 0,-1, 0 }
+ { 0, -1, 0 }
};
- for (size_t i = 0; i < ARRAYCOUNT(gCrossCoords); i++) // Loop through struct to power all directions
+ for (size_t i = 0; i < ARRAYCOUNT(gCrossCoords); i++) // Loop through struct to power all directions
{
- SetBlockPowered(a_BlockX + gCrossCoords[i].x, a_BlockY + gCrossCoords[i].y, a_BlockZ + gCrossCoords[i].z, a_BlockX, a_BlockY, a_BlockZ, a_SourceBlock, a_PowerLevel);
+ SetBlockPowered(a_RelBlockX + gCrossCoords[i].x, a_RelBlockY + gCrossCoords[i].y, a_RelBlockZ + gCrossCoords[i].z, a_RelBlockX, a_RelBlockY, a_RelBlockZ, a_PowerLevel);
}
}
@@ -1589,50 +1905,70 @@ void cIncrementalRedstoneSimulator::SetAllDirsAsPowered(int a_BlockX, int a_Bloc
-void cIncrementalRedstoneSimulator::SetBlockPowered(int a_BlockX, int a_BlockY, int a_BlockZ, int a_SourceX, int a_SourceY, int a_SourceZ, BLOCKTYPE a_SourceBlock, unsigned char a_PowerLevel)
+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)
{
- BLOCKTYPE Block = m_World.GetBlock(a_BlockX, a_BlockY, a_BlockZ);
- if (Block == E_BLOCK_AIR)
+ int BlockX = (m_Chunk->GetPosX() * cChunkDef::Width) + a_RelBlockX;
+ int BlockZ = (m_Chunk->GetPosZ() * cChunkDef::Width) + a_RelBlockZ;
+ int SourceX = (m_Chunk->GetPosX() * cChunkDef::Width) + a_RelSourceX;
+ int SourceZ = (m_Chunk->GetPosZ() * cChunkDef::Width) + a_RelSourceZ;
+
+ cChunk * Neighbour = m_Chunk->GetRelNeighborChunkAdjustCoords(a_RelBlockX, a_RelBlockZ); // Adjust coordinates for the later call using these values
+ if ((Neighbour == NULL) || !Neighbour->IsValid())
{
- // Don't set air, fixes some bugs (wires powering themselves)
return;
}
- PoweredBlocksList * Powered = m_Chunk->GetNeighborChunk(a_BlockX, a_BlockZ)->GetRedstoneSimulatorPoweredBlocksList();
- for (PoweredBlocksList::iterator itr = Powered->begin(); itr != Powered->end(); ++itr) // Check powered list
+ PoweredBlocksList * Powered = Neighbour->GetRedstoneSimulatorPoweredBlocksList(); // We need to insert the value into the chunk who owns the block position
+ for (PoweredBlocksList::iterator itr = Powered->begin(); itr != Powered->end(); ++itr)
{
if (
- itr->a_BlockPos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ)) &&
- itr->a_SourcePos.Equals(Vector3i(a_SourceX, a_SourceY, a_SourceZ))
- )
+ itr->a_BlockPos.Equals(Vector3i(BlockX, a_RelBlockY, BlockZ)) &&
+ itr->a_SourcePos.Equals(Vector3i(SourceX, a_RelSourceY, SourceZ))
+ )
{
- // Check for duplicates, update power level if everything else the same but either way, don't add a new listing
- if (itr->a_PowerLevel != a_PowerLevel)
- {
- itr->a_PowerLevel = a_PowerLevel;
- }
+ // Check for duplicates, update power level, don't add a new listing
+ itr->a_PowerLevel = a_PowerLevel;
return;
}
}
- PoweredBlocksList * OtherPowered = m_Chunk->GetNeighborChunk(a_SourceX, a_SourceZ)->GetRedstoneSimulatorPoweredBlocksList();
- for (PoweredBlocksList::const_iterator itr = OtherPowered->begin(); itr != OtherPowered->end(); ++itr) // Check powered list
+ // No need to get neighbouring chunk as we can guarantee that when something is powering us, the entry will be in our chunk
+ // TODO: on C++11 support, change this to a llama function pased to a std::remove_if
+ for (PoweredBlocksList::iterator itr = m_PoweredBlocks->begin(); itr != m_PoweredBlocks->end(); ++itr)
{
if (
- itr->a_BlockPos.Equals(Vector3i(a_SourceX, a_SourceY, a_SourceZ)) &&
- itr->a_SourcePos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ))
- )
+ itr->a_BlockPos.Equals(Vector3i(SourceX, a_RelSourceY, SourceZ)) &&
+ itr->a_SourcePos.Equals(Vector3i(BlockX, a_RelBlockY, BlockZ)) &&
+ (m_Chunk->GetBlock(a_RelSourceX, a_RelSourceY, a_RelSourceZ) == E_BLOCK_REDSTONE_WIRE)
+ )
{
- // Powered wires try to power their source - don't let them!
- return;
+ BLOCKTYPE Block;
+ NIBBLETYPE Meta;
+ Neighbour->GetBlockTypeMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, 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;
+ }
+ }
}
}
sPoweredBlocks RC;
- RC.a_BlockPos = Vector3i(a_BlockX, a_BlockY, a_BlockZ);
- RC.a_SourcePos = Vector3i(a_SourceX, a_SourceY, a_SourceZ);
+ RC.a_BlockPos = Vector3i(BlockX, a_RelBlockY, BlockZ);
+ RC.a_SourcePos = Vector3i(SourceX, a_RelSourceY, SourceZ);
RC.a_PowerLevel = a_PowerLevel;
Powered->push_back(RC);
+ Neighbour->SetIsRedstoneDirty(true);
+ m_Chunk->SetIsRedstoneDirty(true);
}
@@ -1640,58 +1976,64 @@ void cIncrementalRedstoneSimulator::SetBlockPowered(int a_BlockX, int a_BlockY,
void cIncrementalRedstoneSimulator::SetBlockLinkedPowered(
- int a_BlockX, int a_BlockY, int a_BlockZ,
- int a_MiddleX, int a_MiddleY, int a_MiddleZ,
- int a_SourceX, int a_SourceY, int a_SourceZ,
- BLOCKTYPE a_SourceBlock, BLOCKTYPE a_MiddleBlock, unsigned char a_PowerLevel
-)
+ 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_MiddleBlock, unsigned char a_PowerLevel
+ )
{
- BLOCKTYPE DestBlock = m_World.GetBlock(a_BlockX, a_BlockY, a_BlockZ);
- if (DestBlock == E_BLOCK_AIR)
+ int BlockX = (m_Chunk->GetPosX() * cChunkDef::Width) + a_RelBlockX;
+ int BlockZ = (m_Chunk->GetPosZ() * cChunkDef::Width) + a_RelBlockZ;
+ int MiddleX = (m_Chunk->GetPosX() * cChunkDef::Width) + a_RelMiddleX;
+ int MiddleZ = (m_Chunk->GetPosZ() * cChunkDef::Width) + a_RelMiddleZ;
+ int SourceX = (m_Chunk->GetPosX() * cChunkDef::Width) + a_RelSourceX;
+ int SourceZ = (m_Chunk->GetPosZ() * cChunkDef::Width) + a_RelSourceZ;
+
+ if (!IsViableMiddleBlock(a_MiddleBlock))
{
- // Don't set air, fixes some bugs (wires powering themselves)
return;
}
- if (!IsViableMiddleBlock(a_MiddleBlock))
+
+ cChunk * Neighbour = m_Chunk->GetNeighborChunk(BlockX, BlockZ);
+ if ((Neighbour == NULL) || !Neighbour->IsValid())
{
return;
}
- LinkedBlocksList * Linked = m_Chunk->GetNeighborChunk(a_BlockX, a_BlockZ)->GetRedstoneSimulatorLinkedBlocksList();
+ LinkedBlocksList * Linked = Neighbour->GetRedstoneSimulatorLinkedBlocksList();
for (LinkedBlocksList::iterator itr = Linked->begin(); itr != Linked->end(); ++itr) // Check linked powered list
{
if (
- itr->a_BlockPos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ)) &&
- itr->a_MiddlePos.Equals(Vector3i(a_MiddleX, a_MiddleY, a_MiddleZ)) &&
- itr->a_SourcePos.Equals(Vector3i(a_SourceX, a_SourceY, a_SourceZ))
+ itr->a_BlockPos.Equals(Vector3i(BlockX, a_RelBlockY, BlockZ)) &&
+ itr->a_MiddlePos.Equals(Vector3i(MiddleX, a_RelMiddleY, MiddleZ)) &&
+ itr->a_SourcePos.Equals(Vector3i(SourceX, a_RelSourceY, SourceZ))
)
{
- // Check for duplicates, update power level if everything else the same but either way, don't add a new listing
- if (itr->a_PowerLevel != a_PowerLevel)
- {
- itr->a_PowerLevel = a_PowerLevel;
- }
+ // Check for duplicates, update power level, don't add a new listing
+ itr->a_PowerLevel = a_PowerLevel;
return;
}
}
sLinkedPoweredBlocks RC;
- RC.a_BlockPos = Vector3i(a_BlockX, a_BlockY, a_BlockZ);
- RC.a_MiddlePos = Vector3i(a_MiddleX, a_MiddleY, a_MiddleZ);
- RC.a_SourcePos = Vector3i(a_SourceX, a_SourceY, a_SourceZ);
+ RC.a_BlockPos = Vector3i(BlockX, a_RelBlockY, BlockZ);
+ RC.a_MiddlePos = Vector3i(MiddleX, a_RelMiddleY, MiddleZ);
+ RC.a_SourcePos = Vector3i(SourceX, a_RelSourceY, SourceZ);
RC.a_PowerLevel = a_PowerLevel;
Linked->push_back(RC);
+ Neighbour->SetIsRedstoneDirty(true);
+ m_Chunk->SetIsRedstoneDirty(true);
}
-void cIncrementalRedstoneSimulator::SetPlayerToggleableBlockAsSimulated(int a_BlockX, int a_BlockY, int a_BlockZ, bool WasLastStatePowered)
+void cIncrementalRedstoneSimulator::SetPlayerToggleableBlockAsSimulated(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, bool WasLastStatePowered)
{
for (SimulatedPlayerToggleableList::iterator itr = m_SimulatedPlayerToggleableBlocks->begin(); itr != m_SimulatedPlayerToggleableBlocks->end(); ++itr)
{
- if (!itr->a_BlockPos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ)))
+ if (!itr->a_RelBlockPos.Equals(Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ)))
{
continue;
}
@@ -1711,7 +2053,7 @@ void cIncrementalRedstoneSimulator::SetPlayerToggleableBlockAsSimulated(int a_Bl
// We have arrive here; no block must be in list - add one
sSimulatedPlayerToggleableList RC;
- RC.a_BlockPos = Vector3i(a_BlockX, a_BlockY, a_BlockZ);
+ RC.a_RelBlockPos = Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ);
RC.WasLastStatePowered = WasLastStatePowered;
m_SimulatedPlayerToggleableBlocks->push_back(RC);
}
@@ -1720,89 +2062,147 @@ void cIncrementalRedstoneSimulator::SetPlayerToggleableBlockAsSimulated(int a_Bl
-void cIncrementalRedstoneSimulator::QueueRepeaterPowerChange(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_Meta, bool ShouldPowerOn)
+bool cIncrementalRedstoneSimulator::QueueRepeaterPowerChange(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, NIBBLETYPE a_Meta, bool ShouldPowerOn)
{
for (RepeatersDelayList::iterator itr = m_RepeatersDelayList->begin(); itr != m_RepeatersDelayList->end(); ++itr)
{
- if (itr->a_BlockPos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ)))
+ if (itr->a_RelBlockPos.Equals(Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ)))
{
- if (ShouldPowerOn == itr->ShouldPowerOn) // We are queued already for the same thing, don't replace entry
+ if (ShouldPowerOn == itr->ShouldPowerOn) // We are queued already for the same thing, don't replace entry
{
- return;
+ return false;
}
// Already in here (normal to allow repeater to continue on powering and updating blocks in front) - just update info and quit
- itr->a_DelayTicks = (((a_Meta & 0xC) >> 0x2) + 1) * 2; // See below for description
+ itr->a_DelayTicks = (((a_Meta & 0xC) >> 0x2) + 1) * 2; // See below for description
itr->a_ElapsedTicks = 0;
itr->ShouldPowerOn = ShouldPowerOn;
- return;
+ return false;
}
}
// Self not in list, add self to list
- sRepeatersDelayList RC;
- RC.a_BlockPos = Vector3i(a_BlockX, a_BlockY, a_BlockZ);
+ sRepeatersDelayList RC;
+ RC.a_RelBlockPos = Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ);
// Gets the top two bits (delay time), shifts them into the lower two bits, and adds one (meta 0 = 1 tick; 1 = 2 etc.)
- // * 2 because in MCS, 1 redstone tick = 1 world tick, but in Vanilla, 1 redstone tick = 2 world ticks, and we need to maintain compatibility
+ // Multiply by 2 because in MCS, 1 redstone tick = 1 world tick, but in Vanilla, 1 redstone tick = 2 world ticks, and we need to maintain compatibility
RC.a_DelayTicks = (((a_Meta & 0xC) >> 0x2) + 1) * 2;
RC.a_ElapsedTicks = 0;
RC.ShouldPowerOn = ShouldPowerOn;
m_RepeatersDelayList->push_back(RC);
- return;
+ return true;
}
-cIncrementalRedstoneSimulator::eRedstoneDirection cIncrementalRedstoneSimulator::GetWireDirection(int a_BlockX, int a_BlockY, int a_BlockZ)
+void cIncrementalRedstoneSimulator::SetSourceUnpowered(int a_SourceX, int a_SourceY, int a_SourceZ, cChunk * a_Chunk, bool a_IsFirstCall)
{
- int Dir = REDSTONE_NONE;
+ if (!a_IsFirstCall) // The neighbouring chunks passed when this parameter is false may be invalid
+ {
+ if ((a_Chunk == NULL) || !a_Chunk->IsValid())
+ {
+ return;
+ }
+ }
+ // TODO: on C++11 support, change both of these to llama functions pased to a std::remove_if
- BLOCKTYPE NegX = m_World.GetBlock(a_BlockX - 1, a_BlockY, a_BlockZ);
- if (IsPotentialSource(NegX))
+ for (PoweredBlocksList::iterator itr = a_Chunk->GetRedstoneSimulatorPoweredBlocksList()->begin(); itr != a_Chunk->GetRedstoneSimulatorPoweredBlocksList()->end();)
+ {
+ if (itr->a_SourcePos.Equals(Vector3i(a_SourceX, a_SourceY, a_SourceZ)))
+ {
+ itr = a_Chunk->GetRedstoneSimulatorPoweredBlocksList()->erase(itr);
+ a_Chunk->SetIsRedstoneDirty(true);
+ continue;
+ }
+ ++itr;
+ }
+ for (LinkedBlocksList::iterator itr = a_Chunk->GetRedstoneSimulatorLinkedBlocksList()->begin(); itr != a_Chunk->GetRedstoneSimulatorLinkedBlocksList()->end();)
{
- Dir |= (REDSTONE_X_POS);
+ if (itr->a_SourcePos.Equals(Vector3i(a_SourceX, a_SourceY, a_SourceZ)))
+ {
+ itr = a_Chunk->GetRedstoneSimulatorLinkedBlocksList()->erase(itr);
+ a_Chunk->SetIsRedstoneDirty(true);
+ continue;
+ }
+ ++itr;
}
-
- BLOCKTYPE PosX = m_World.GetBlock(a_BlockX + 1, a_BlockY, a_BlockZ);
- if (IsPotentialSource(PosX))
+
+ if (a_IsFirstCall && AreCoordsOnChunkBoundary(a_SourceX, a_SourceY, a_SourceZ))
{
- Dir |= (REDSTONE_X_NEG);
+ // +- 2 to accomodate linked powered blocks
+ SetSourceUnpowered(a_SourceX, a_SourceY, a_SourceZ, a_Chunk->GetNeighborChunk(a_SourceX - 2, a_SourceZ), false);
+ SetSourceUnpowered(a_SourceX, a_SourceY, a_SourceZ, a_Chunk->GetNeighborChunk(a_SourceX + 2, a_SourceZ), false);
+ SetSourceUnpowered(a_SourceX, a_SourceY, a_SourceZ, a_Chunk->GetNeighborChunk(a_SourceX, a_SourceZ - 2), false);
+ SetSourceUnpowered(a_SourceX, a_SourceY, a_SourceZ, a_Chunk->GetNeighborChunk(a_SourceX, a_SourceZ + 2), false);
}
-
- BLOCKTYPE NegZ = m_World.GetBlock(a_BlockX, a_BlockY, a_BlockZ - 1);
- if (IsPotentialSource(NegZ))
+}
+
+
+
+
+
+cIncrementalRedstoneSimulator::eRedstoneDirection cIncrementalRedstoneSimulator::GetWireDirection(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ)
+{
+ int Dir = REDSTONE_NONE;
+
+ BLOCKTYPE NegX = 0;
+ if (m_Chunk->UnboundedRelGetBlockType(a_RelBlockX - 1, a_RelBlockY, a_RelBlockZ, NegX))
{
- if ((Dir & REDSTONE_X_POS) && !(Dir & REDSTONE_X_NEG)) // corner
+ if (IsPotentialSource(NegX))
{
- Dir ^= REDSTONE_X_POS;
- Dir |= REDSTONE_X_NEG;
+ Dir |= (REDSTONE_X_POS);
}
- if ((Dir & REDSTONE_X_NEG) && !(Dir & REDSTONE_X_POS)) // corner
+ }
+
+ BLOCKTYPE PosX = 0;
+ if (m_Chunk->UnboundedRelGetBlockType(a_RelBlockX + 1, a_RelBlockY, a_RelBlockZ, PosX))
+ {
+ if (IsPotentialSource(PosX))
{
- Dir ^= REDSTONE_X_NEG;
- Dir |= REDSTONE_X_POS;
+ Dir |= (REDSTONE_X_NEG);
}
- Dir |= REDSTONE_Z_POS;
}
- BLOCKTYPE PosZ = m_World.GetBlock(a_BlockX, a_BlockY, a_BlockZ + 1);
- if (IsPotentialSource(PosZ))
+ BLOCKTYPE NegZ = 0;
+ if (m_Chunk->UnboundedRelGetBlockType(a_RelBlockX, a_RelBlockY, a_RelBlockZ - 1, NegZ))
{
- if ((Dir & REDSTONE_X_POS) && !(Dir & REDSTONE_X_NEG)) // corner
+ if (IsPotentialSource(NegZ))
{
- Dir ^= REDSTONE_X_POS;
- Dir |= REDSTONE_X_NEG;
+ if ((Dir & REDSTONE_X_POS) && !(Dir & REDSTONE_X_NEG)) // corner
+ {
+ Dir ^= REDSTONE_X_POS;
+ Dir |= REDSTONE_X_NEG;
+ }
+ if ((Dir & REDSTONE_X_NEG) && !(Dir & REDSTONE_X_POS)) // corner
+ {
+ Dir ^= REDSTONE_X_NEG;
+ Dir |= REDSTONE_X_POS;
+ }
+ Dir |= REDSTONE_Z_POS;
}
- if ((Dir & REDSTONE_X_NEG) && !(Dir & REDSTONE_X_POS)) // corner
+ }
+
+ BLOCKTYPE PosZ = 0;
+ if (m_Chunk->UnboundedRelGetBlockType(a_RelBlockX, a_RelBlockY, a_RelBlockZ + 1, PosZ))
+ {
+ if (IsPotentialSource(PosZ))
{
- Dir ^= REDSTONE_X_NEG;
- Dir |= REDSTONE_X_POS;
+ if ((Dir & REDSTONE_X_POS) && !(Dir & REDSTONE_X_NEG)) // corner
+ {
+ Dir ^= REDSTONE_X_POS;
+ Dir |= REDSTONE_X_NEG;
+ }
+ if ((Dir & REDSTONE_X_NEG) && !(Dir & REDSTONE_X_POS)) // corner
+ {
+ Dir ^= REDSTONE_X_NEG;
+ Dir |= REDSTONE_X_POS;
+ }
+ Dir |= REDSTONE_Z_NEG;
}
- Dir |= REDSTONE_Z_NEG;
}
return (eRedstoneDirection)Dir;
}