summaryrefslogtreecommitdiffstats
path: root/src/Simulator
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/Simulator/FireSimulator.h2
-rw-r--r--src/Simulator/NoopFluidSimulator.h10
-rw-r--r--src/Simulator/RedstoneSimulator.cpp377
-rw-r--r--src/Simulator/RedstoneSimulator.h109
-rw-r--r--src/Simulator/SandSimulator.h2
-rw-r--r--src/Simulator/Simulator.h9
6 files changed, 242 insertions, 267 deletions
diff --git a/src/Simulator/FireSimulator.h b/src/Simulator/FireSimulator.h
index 66c31b440..9ccc3ef4f 100644
--- a/src/Simulator/FireSimulator.h
+++ b/src/Simulator/FireSimulator.h
@@ -22,7 +22,7 @@ public:
cFireSimulator(cWorld & a_World, cIniFile & a_IniFile);
~cFireSimulator();
- virtual void Simulate(float a_Dt) override {} // not used
+ virtual void Simulate(float a_Dt) override { UNUSED(a_Dt);} // not used
virtual void SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, cChunk * a_Chunk) override;
virtual bool IsAllowedBlock(BLOCKTYPE a_BlockType) override;
diff --git a/src/Simulator/NoopFluidSimulator.h b/src/Simulator/NoopFluidSimulator.h
index 8f894433f..9113aec3c 100644
--- a/src/Simulator/NoopFluidSimulator.h
+++ b/src/Simulator/NoopFluidSimulator.h
@@ -27,8 +27,14 @@ public:
}
// cSimulator overrides:
- virtual void AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk) override {}
- virtual void Simulate(float a_Dt) override {}
+ virtual void AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk) override
+ {
+ UNUSED(a_BlockX);
+ UNUSED(a_BlockY);
+ UNUSED(a_BlockZ);
+ UNUSED(a_Chunk);
+ }
+ virtual void Simulate(float a_Dt) override { UNUSED(a_Dt);}
} ;
diff --git a/src/Simulator/RedstoneSimulator.cpp b/src/Simulator/RedstoneSimulator.cpp
index f65908729..e361cbf49 100644
--- a/src/Simulator/RedstoneSimulator.cpp
+++ b/src/Simulator/RedstoneSimulator.cpp
@@ -4,6 +4,7 @@
#include "RedstoneSimulator.h"
#include "../BlockEntities/DropSpenserEntity.h"
#include "../BlockEntities/NoteEntity.h"
+#include "../BlockEntities/CommandBlockEntity.h"
#include "../Entities/TNTEntity.h"
#include "../Blocks/BlockTorch.h"
#include "../Blocks/BlockDoor.h"
@@ -44,83 +45,46 @@ void cRedstoneSimulator::AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, cChu
int RelX = a_BlockX - a_Chunk->GetPosX() * cChunkDef::Width;
int RelZ = a_BlockZ - a_Chunk->GetPosZ() * cChunkDef::Width;
+
+ BLOCKTYPE Block;
+ NIBBLETYPE Meta;
+ a_Chunk->GetBlockTypeMeta(RelX, a_BlockY, RelZ, Block, Meta);
- if (!IsAllowedBlock(a_Chunk->GetBlock(RelX, a_BlockY, RelZ)))
- {
- return;
- }
-
- // Check for duplicates:
- cRedstoneSimulatorChunkData & ChunkData = a_Chunk->GetRedstoneSimulatorData();
- for (cRedstoneSimulatorChunkData::const_iterator itr = ChunkData.begin(); itr != ChunkData.end(); ++itr)
- {
- if ((itr->x == RelX) && (itr->y == a_BlockY) && (itr->z == RelZ))
- {
- return;
- }
- }
-
- ChunkData.push_back(cCoordWithInt(RelX, a_BlockY, RelZ));
-}
-
-
-
-
-
-void cRedstoneSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, cChunk * a_Chunk)
-{
- cRedstoneSimulatorChunkData & ChunkData = a_Chunk->GetRedstoneSimulatorData();
- if (ChunkData.empty())
- {
- return;
- }
-
- int BaseX = a_Chunk->GetPosX() * cChunkDef::Width;
- int BaseZ = a_Chunk->GetPosZ() * cChunkDef::Width;
+ // Every time a block is changed (AddBlock called), we want to go through all lists and check to see if the coordiantes stored within are still valid
+ // Checking only when a block is changed, as opposed to every tick, also improves performance
- // Check to see if PoweredBlocks have invalid items (source is air or unpowered)
- for (PoweredBlocksList::iterator itr = m_PoweredBlocks.begin(); itr != m_PoweredBlocks.end();)
+ for (PoweredBlocksList::iterator itr = m_PoweredBlocks.begin(); itr != m_PoweredBlocks.end(); ++itr)
{
- int RelX = itr->a_SourcePos.x - a_ChunkX * cChunkDef::Width;
- int RelZ = itr->a_SourcePos.z - a_ChunkZ * cChunkDef::Width;
- int DestRelX = itr->a_BlockPos.x - a_ChunkX * cChunkDef::Width;
- int DestRelZ = itr->a_BlockPos.z - a_ChunkZ * cChunkDef::Width;
-
- BLOCKTYPE SourceBlockType;
- NIBBLETYPE SourceBlockMeta;
- BLOCKTYPE DestBlockType;
- if (
- !a_Chunk->UnboundedRelGetBlock(RelX, itr->a_SourcePos.y, RelZ, SourceBlockType, SourceBlockMeta) ||
- !a_Chunk->UnboundedRelGetBlockType(DestRelX, itr->a_BlockPos.y, DestRelZ, DestBlockType)
- )
+ if (!itr->a_SourcePos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ)))
{
continue;
}
- if (SourceBlockType != itr->a_SourceBlock)
+ if (!IsPotentialSource(Block))
{
- LOGD("cRedstoneSimulator: Erased block %s from powered blocks list due to present/past block type mismatch", ItemToFullString(itr->a_SourceBlock).c_str());
- itr = m_PoweredBlocks.erase(itr);
+ LOGD("cRedstoneSimulator: Erased block @ {%i, %i, %i} from powered blocks list as it no longer connected to a source", itr->a_BlockPos.x, itr->a_BlockPos.y, itr->a_BlockPos.z);
+ m_PoweredBlocks.erase(itr);
+ break;
}
else if (
// Changeable sources
- ((SourceBlockType == E_BLOCK_REDSTONE_WIRE) && (SourceBlockMeta == 0)) ||
- ((SourceBlockType == E_BLOCK_LEVER) && !IsLeverOn(SourceBlockMeta)) ||
- ((SourceBlockType == E_BLOCK_DETECTOR_RAIL) && (SourceBlockMeta & 0x08) == 0x08) ||
- (((SourceBlockType == E_BLOCK_STONE_BUTTON) || (SourceBlockType == E_BLOCK_WOODEN_BUTTON)) && (!IsButtonOn(SourceBlockMeta))) ||
- (((SourceBlockType == E_BLOCK_STONE_PRESSURE_PLATE) || (SourceBlockType == E_BLOCK_WOODEN_PRESSURE_PLATE)) && (SourceBlockMeta == 0))
+ ((Block == E_BLOCK_REDSTONE_WIRE) && (Meta == 0)) ||
+ ((Block == E_BLOCK_LEVER) && !IsLeverOn(Meta)) ||
+ ((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))
)
{
- LOGD("cRedstoneSimulator: Erased block %s from powered blocks list due to present/past metadata mismatch", ItemToFullString(itr->a_SourceBlock).c_str());
- itr = m_PoweredBlocks.erase(itr);
+ LOGD("cRedstoneSimulator: 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);
+ m_PoweredBlocks.erase(itr);
+ break;
}
- else if (SourceBlockType == E_BLOCK_DAYLIGHT_SENSOR)
+ else if (Block == E_BLOCK_DAYLIGHT_SENSOR)
{
if (!a_Chunk->IsLightValid())
{
- m_World.QueueLightChunk(a_ChunkX, a_ChunkZ);
- ++itr;
- continue;
+ m_World.QueueLightChunk(a_Chunk->GetPosX(), a_Chunk->GetPosZ());
+ break;
}
else
{
@@ -130,151 +94,151 @@ void cRedstoneSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, c
if (a_Chunk->GetTimeAlteredLight(SkyLight) <= 8) // Could use SkyLight - m_World.GetSkyDarkness();
{
LOGD("cRedstoneSimulator: Erased daylight sensor from powered blocks list due to insufficient light level");
- itr = m_PoweredBlocks.erase(itr);
- }
- else
- {
- ++itr;
- continue;
+ m_PoweredBlocks.erase(itr);
+ break;
}
}
}
- else if ((SourceBlockType == E_BLOCK_REDSTONE_WIRE) && (DestBlockType == E_BLOCK_REDSTONE_WIRE))
+ }
+
+ for (LinkedBlocksList::iterator itr = m_LinkedPoweredBlocks.begin(); itr != m_LinkedPoweredBlocks.end(); ++itr)
+ {
+ if (itr->a_SourcePos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ)))
{
- // It is simply not allowed that a wire powers another wire, presuming that data here is sane and a dest and source are beside each other
- LOGD("cRedstoneSimulator: Erased redstone wire from powered blocks list because its source was also wire");
- itr = m_PoweredBlocks.erase(itr);
+ if (!IsPotentialSource(Block))
+ {
+ LOGD("cRedstoneSimulator: Erased block @ {%i, %i, %i} from linked powered blocks list as it is no longer connected to a source", itr->a_BlockPos.x, itr->a_BlockPos.y, itr->a_BlockPos.z);
+ m_LinkedPoweredBlocks.erase(itr);
+ break;
+ }
+ else if (
+ // Things that can send power through a block but which depends on meta
+ ((Block == E_BLOCK_REDSTONE_WIRE) && (Meta == 0)) ||
+ ((Block == E_BLOCK_LEVER) && !IsLeverOn(Meta)) ||
+ (((Block == E_BLOCK_STONE_BUTTON) || (Block == E_BLOCK_WOODEN_BUTTON)) && (!IsButtonOn(Meta)))
+ )
+ {
+ LOGD("cRedstoneSimulator: Erased block @ {%i, %i, %i} from linked powered blocks list due to present/past metadata mismatch", itr->a_BlockPos.x, itr->a_BlockPos.y, itr->a_BlockPos.z);
+ m_LinkedPoweredBlocks.erase(itr);
+ break;
+ }
}
- else
+ else if (itr->a_MiddlePos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ)))
{
- ++itr;
+ if (!IsViableMiddleBlock(Block))
+ {
+ LOGD("cRedstoneSimulator: Erased block @ {%i, %i, %i} from linked powered blocks list as it is no longer powered through a valid middle block", itr->a_BlockPos.x, itr->a_BlockPos.y, itr->a_BlockPos.z);
+ m_LinkedPoweredBlocks.erase(itr);
+ break;
+ }
}
}
- // Check to see if LinkedPoweredBlocks have invalid items: source, block powered through, or power destination block has changed
- for (LinkedBlocksList::iterator itr = m_LinkedPoweredBlocks.begin(); itr != m_LinkedPoweredBlocks.end();)
+ for (SimulatedPlayerToggleableList::iterator itr = m_SimulatedPlayerToggleableBlocks.begin(); itr != m_SimulatedPlayerToggleableBlocks.end(); ++itr)
{
- int RelX = itr->a_SourcePos.x - a_ChunkX * cChunkDef::Width;
- int RelZ = itr->a_SourcePos.z - a_ChunkZ * cChunkDef::Width;
- int MidRelX = itr->a_MiddlePos.x - a_ChunkX * cChunkDef::Width;
- int MidRelZ = itr->a_MiddlePos.z - a_ChunkZ * cChunkDef::Width;
-
- BLOCKTYPE SourceBlockType;
- NIBBLETYPE SourceBlockMeta;
- BLOCKTYPE MiddleBlockType;
- if (
- !a_Chunk->UnboundedRelGetBlock(RelX, itr->a_SourcePos.y, RelZ, SourceBlockType, SourceBlockMeta) ||
- !a_Chunk->UnboundedRelGetBlockType(MidRelX, itr->a_MiddlePos.y, MidRelZ, MiddleBlockType)
- )
+ if (!itr->a_BlockPos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ)))
{
continue;
}
- if (SourceBlockType != itr->a_SourceBlock)
- {
- LOGD("cRedstoneSimulator: Erased block %s from linked powered blocks list due to present/past block type mismatch", ItemToFullString(itr->a_SourceBlock).c_str());
- itr = m_LinkedPoweredBlocks.erase(itr);
- }
- else if (MiddleBlockType != itr->a_MiddleBlock)
+ if (!IsAllowedBlock(Block))
{
- LOGD("cRedstoneSimulator: Erased block %s from linked powered blocks list due to present/past middle block mismatch", ItemToFullString(itr->a_SourceBlock).c_str());
- itr = m_LinkedPoweredBlocks.erase(itr);
- }
- else if (
- // Things that can send power through a block but which depends on meta
- ((SourceBlockType == E_BLOCK_REDSTONE_WIRE) && (SourceBlockMeta == 0)) ||
- ((SourceBlockType == E_BLOCK_LEVER) && !IsLeverOn(SourceBlockMeta)) ||
- (((SourceBlockType == E_BLOCK_STONE_BUTTON) || (SourceBlockType == E_BLOCK_WOODEN_BUTTON)) && (!IsButtonOn(SourceBlockMeta)))
- )
- {
- LOGD("cRedstoneSimulator: Erased block %s from linked powered blocks list due to present/past metadata mismatch", ItemToFullString(itr->a_SourceBlock).c_str());
- itr = m_LinkedPoweredBlocks.erase(itr);
- }
- else
- {
- ++itr;
+ LOGD("cRedstoneSimulator: 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);
+ m_SimulatedPlayerToggleableBlocks.erase(itr);
+ break;
}
}
- for (SimulatedPlayerToggleableList::iterator itr = m_SimulatedPlayerToggleableBlocks.begin(); itr != m_SimulatedPlayerToggleableBlocks.end();)
+ for (RepeatersDelayList::iterator itr = m_RepeatersDelayList.begin(); itr != m_RepeatersDelayList.end(); ++itr)
{
- int RelX = itr->a_BlockPos.x - a_ChunkX * cChunkDef::Width;
- int RelZ = itr->a_BlockPos.z - a_ChunkZ * cChunkDef::Width;
-
- BLOCKTYPE SourceBlockType;
- if (!a_Chunk->UnboundedRelGetBlockType(RelX, itr->a_BlockPos.y, RelZ, SourceBlockType))
+ if (!itr->a_BlockPos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ)))
{
continue;
}
- else if (!IsAllowedBlock(SourceBlockType))
+
+ if ((Block != E_BLOCK_REDSTONE_REPEATER_ON) && (Block != E_BLOCK_REDSTONE_REPEATER_OFF))
{
- LOGD("cRedstoneSimulator: Erased block %s from toggleable simulated list as block is no longer redstone", ItemToFullString(SourceBlockType).c_str());
- itr = m_SimulatedPlayerToggleableBlocks.erase(itr);
+ m_RepeatersDelayList.erase(itr);
+ break;
}
- else
+ }
+
+ cRedstoneSimulatorChunkData & ChunkData = a_Chunk->GetRedstoneSimulatorData();
+ for (cRedstoneSimulatorChunkData::iterator itr = ChunkData.begin(); itr != ChunkData.end(); ++itr)
+ {
+ if ((itr->x == RelX) && (itr->y == a_BlockY) && (itr->z == RelZ)) // We are at an entry matching the current (changed) block
{
- ++itr;
+ if (!IsAllowedBlock(Block))
+ {
+ ChunkData.erase(itr); // The new blocktype is not redstone; it must be removed from this list
+ }
+ else
+ {
+ itr->Data = Block; // Update block information
+ }
+ return;
}
}
- for (RepeatersDelayList::iterator itr = m_RepeatersDelayList.begin(); itr != m_RepeatersDelayList.end();)
+ if (!IsAllowedBlock(Block))
{
- int RelX = itr->a_BlockPos.x - a_ChunkX * cChunkDef::Width;
- int RelZ = itr->a_BlockPos.z - a_ChunkZ * cChunkDef::Width;
+ return;
+ }
+
+ ChunkData.push_back(cCoordWithBlock(RelX, a_BlockY, RelZ, Block));
+}
- BLOCKTYPE SourceBlockType;
- if (!a_Chunk->UnboundedRelGetBlockType(RelX, itr->a_BlockPos.y, RelZ, SourceBlockType))
- {
- continue;
- }
- if ((SourceBlockType != E_BLOCK_REDSTONE_REPEATER_ON) && (SourceBlockType != E_BLOCK_REDSTONE_REPEATER_OFF))
- {
- itr = m_RepeatersDelayList.erase(itr);
- continue;
- }
- ++itr;
- }
- for (cRedstoneSimulatorChunkData::iterator dataitr = ChunkData.begin(), end = ChunkData.end(); dataitr != end;)
+
+void cRedstoneSimulator::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
+
+ cRedstoneSimulatorChunkData & ChunkData = a_Chunk->GetRedstoneSimulatorData();
+ if (ChunkData.empty())
{
- BLOCKTYPE BlockType = a_Chunk->GetBlock(dataitr->x, dataitr->y, dataitr->z);
- if (!IsAllowedBlock(BlockType))
- {
- dataitr = ChunkData.erase(dataitr);
- continue;
- }
+ return;
+ }
- // PoweredBlock and LinkedPoweredBlock list was fine, now to the actual handling
+ int BaseX = a_Chunk->GetPosX() * cChunkDef::Width;
+ int BaseZ = a_Chunk->GetPosZ() * cChunkDef::Width;
+
+ for (cRedstoneSimulatorChunkData::const_iterator dataitr = ChunkData.begin(); dataitr != ChunkData.end(); ++dataitr)
+ {
int a_X = BaseX + dataitr->x;
int a_Z = BaseZ + dataitr->z;
- switch (BlockType)
+ 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_TNT: HandleTNT(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_REDSTONE_TORCH_OFF:
case E_BLOCK_REDSTONE_TORCH_ON:
{
- HandleRedstoneTorch(a_X, dataitr->y, a_Z, BlockType);
+ 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, BlockType);
+ 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, BlockType);
+ HandleRedstoneRepeater(a_X, dataitr->y, a_Z, dataitr->Data);
break;
}
case E_BLOCK_PISTON:
@@ -286,7 +250,7 @@ void cRedstoneSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, c
case E_BLOCK_REDSTONE_LAMP_OFF:
case E_BLOCK_REDSTONE_LAMP_ON:
{
- HandleRedstoneLamp(a_X, dataitr->y, a_Z, BlockType);
+ HandleRedstoneLamp(a_X, dataitr->y, a_Z, dataitr->Data);
break;
}
case E_BLOCK_DISPENSER:
@@ -305,18 +269,16 @@ void cRedstoneSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, c
case E_BLOCK_DETECTOR_RAIL:
case E_BLOCK_POWERED_RAIL:
{
- HandleRail(a_X, dataitr->y, a_Z, BlockType);
+ HandleRail(a_X, dataitr->y, a_Z, dataitr->Data);
break;
}
case E_BLOCK_WOODEN_PRESSURE_PLATE:
case E_BLOCK_STONE_PRESSURE_PLATE:
{
- HandlePressurePlate(a_X, dataitr->y, a_Z, BlockType);
+ HandlePressurePlate(a_X, dataitr->y, a_Z, dataitr->Data);
break;
}
}
-
- ++dataitr;
}
}
@@ -487,7 +449,7 @@ void cRedstoneSimulator::HandleRedstoneWire(int a_BlockX, int a_BlockY, int a_Bl
};
// Check to see if directly beside a power source
- if (AreCoordsPowered(a_BlockX, a_BlockY, a_BlockZ))
+ if (IsWirePowered(a_BlockX, a_BlockY, a_BlockZ))
{
m_World.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, 15); // Maximum power
}
@@ -545,7 +507,7 @@ void cRedstoneSimulator::HandleRedstoneWire(int a_BlockX, int a_BlockY, int a_Bl
// transferring power to other wires around.
// However, self not directly powered anymore, so source must have been removed,
// therefore, self must be set to meta zero
- m_World.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, 0);
+ m_World.SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_WIRE, 0); // SetMeta & WakeUpSims doesn't seem to work here, so SetBlock
return; // No need to process block power sets because self not powered
}
else
@@ -693,7 +655,7 @@ void cRedstoneSimulator::HandleRedstoneRepeater(int a_BlockX, int a_BlockY, int
// 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_BlockPos.x, itr->a_BlockPos.y, itr->a_BlockPos.z, itr->a_ElapsedTicks, itr->a_DelayTicks);
itr->a_ElapsedTicks++;
}
}
@@ -781,50 +743,45 @@ void cRedstoneSimulator::HandleTNT(int a_BlockX, int a_BlockY, int a_BlockZ)
void cRedstoneSimulator::HandleDoor(int a_BlockX, int a_BlockY, int a_BlockZ)
{
- if ((m_World.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ) & 0x08) == 0x08)
+ if (AreCoordsPowered(a_BlockX, a_BlockY, a_BlockZ))
{
- // Block position is located at top half of door
- // Is Y - 1 both within world boundaries, a door block, and the bottom half of a door?
- // The bottom half stores the open/closed information
- if (
- (a_BlockY - 1 >= 0) &&
- ((m_World.GetBlock(a_BlockX, a_BlockY, a_BlockZ) == E_BLOCK_WOODEN_DOOR) || (m_World.GetBlock(a_BlockX, a_BlockY, a_BlockZ) == E_BLOCK_IRON_DOOR)) &&
- (m_World.GetBlockMeta(a_BlockX, a_BlockY - 1, a_BlockZ & 0x08) == 0)
- )
+ if (!AreCoordsSimulated(a_BlockX, a_BlockY, a_BlockZ, true))
{
- if ((m_World.GetBlockMeta(a_BlockX, a_BlockY - 1, a_BlockZ) & 0x04) == 0) // Closed door?
- {
- if (AreCoordsPowered(a_BlockX, a_BlockY, a_BlockZ)) // Powered? If so, toggle open
- {
- cBlockDoorHandler::ChangeDoor(&m_World, a_BlockX, a_BlockY, a_BlockZ);
- }
- }
- else // Opened door
- {
- if (!AreCoordsPowered(a_BlockX, a_BlockY, a_BlockZ)) // Unpowered? Close if so
- {
- cBlockDoorHandler::ChangeDoor(&m_World, a_BlockX, a_BlockY, a_BlockZ);
- }
- }
+ cBlockDoorHandler::ChangeDoor(&m_World, a_BlockX, a_BlockY, a_BlockZ);
+ SetPlayerToggleableBlockAsSimulated(a_BlockX, a_BlockY, a_BlockZ, true);
}
}
else
{
- if ((m_World.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ) & 0x04) == 0) // Closed door?
+ if (!AreCoordsSimulated(a_BlockX, a_BlockY, a_BlockZ, false))
{
- if (AreCoordsPowered(a_BlockX, a_BlockY, a_BlockZ)) // Powered? If so, toggle open
- {
- cBlockDoorHandler::ChangeDoor(&m_World, a_BlockX, a_BlockY, a_BlockZ);
- }
+ cBlockDoorHandler::ChangeDoor(&m_World, a_BlockX, a_BlockY, a_BlockZ);
+ SetPlayerToggleableBlockAsSimulated(a_BlockX, a_BlockY, a_BlockZ, false);
}
- else // Opened door
+ }
+}
+
+
+
+
+
+void cRedstoneSimulator::HandleCommandBlock(int a_BlockX, int a_BlockY, int a_BlockZ)
+{
+ class cSetPowerToCommandBlock :
+ public cCommandBlockCallback
+ {
+ bool m_IsPowered;
+ public:
+ cSetPowerToCommandBlock(bool a_IsPowered) : m_IsPowered(a_IsPowered) {}
+
+ virtual bool Item(cCommandBlockEntity * a_CommandBlock) override
{
- if (!AreCoordsPowered(a_BlockX, a_BlockY, a_BlockZ)) // Unpowered? Close if so
- {
- cBlockDoorHandler::ChangeDoor(&m_World, a_BlockX, a_BlockY, a_BlockZ);
- }
+ a_CommandBlock->SetRedstonePower(m_IsPowered);
+ return false;
}
- }
+ } CmdBlockSP (AreCoordsPowered(a_BlockX, a_BlockY, a_BlockZ));
+
+ m_World.DoWithCommandBlockAt(a_BlockX, a_BlockY, a_BlockZ, CmdBlockSP);
}
@@ -970,6 +927,7 @@ void cRedstoneSimulator::HandlePressurePlate(int a_BlockX, int a_BlockY, int a_B
else
{
m_World.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, 0x0);
+ m_World.WakeUpSimulators(a_BlockX, a_BlockY, a_BlockZ);
}
break;
}
@@ -1032,6 +990,7 @@ void cRedstoneSimulator::HandlePressurePlate(int a_BlockX, int a_BlockY, int a_B
else
{
m_World.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, 0x0);
+ m_World.WakeUpSimulators(a_BlockX, a_BlockY, a_BlockZ);
}
break;
}
@@ -1188,6 +1147,33 @@ bool cRedstoneSimulator::IsPistonPowered(int a_BlockX, int a_BlockY, int a_Block
+bool cRedstoneSimulator::IsWirePowered(int a_BlockX, int a_BlockY, int a_BlockZ)
+{
+ 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 (m_World.GetBlock(itr->a_SourcePos) != E_BLOCK_REDSTONE_WIRE)
+ {
+ return 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 (m_World.GetBlock(itr->a_SourcePos) != E_BLOCK_REDSTONE_WIRE)
+ {
+ return true;
+ }
+ }
+ return false; // Source was in front of the piston's front face
+}
+
+
+
+
bool cRedstoneSimulator::AreCoordsSimulated(int a_BlockX, int a_BlockY, int a_BlockZ, bool IsCurrentStatePowered)
{
@@ -1333,11 +1319,6 @@ void cRedstoneSimulator::SetBlockPowered(int a_BlockX, int a_BlockY, int a_Block
// Don't set air, fixes some bugs (wires powering themselves)
return;
}
- if ((Block == E_BLOCK_REDSTONE_WIRE) && (a_SourceBlock == E_BLOCK_REDSTONE_WIRE))
- {
- // Wires cannot power themselves normally, instead, the wire handler will manually set meta
- return;
- }
for (PoweredBlocksList::const_iterator itr = m_PoweredBlocks.begin(); itr != m_PoweredBlocks.end(); ++itr) // Check powered list
{
@@ -1354,7 +1335,6 @@ void cRedstoneSimulator::SetBlockPowered(int a_BlockX, int a_BlockY, int a_Block
sPoweredBlocks RC;
RC.a_BlockPos = Vector3i(a_BlockX, a_BlockY, a_BlockZ);
RC.a_SourcePos = Vector3i(a_SourceX, a_SourceY, a_SourceZ);
- RC.a_SourceBlock = a_SourceBlock;
m_PoweredBlocks.push_back(RC);
}
@@ -1379,11 +1359,6 @@ void cRedstoneSimulator::SetBlockLinkedPowered(
{
return;
}
- if ((a_SourceBlock == E_BLOCK_REDSTONE_WIRE) && (DestBlock == E_BLOCK_REDSTONE_WIRE))
- {
- // Wires cannot power another wire through a block
- return;
- }
for (LinkedBlocksList::const_iterator itr = m_LinkedPoweredBlocks.begin(); itr != m_LinkedPoweredBlocks.end(); ++itr) // Check linked powered list
{
@@ -1402,8 +1377,6 @@ void cRedstoneSimulator::SetBlockLinkedPowered(
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_SourceBlock = a_SourceBlock;
- RC.a_MiddleBlock = a_MiddleBlock;
m_LinkedPoweredBlocks.push_back(RC);
}
diff --git a/src/Simulator/RedstoneSimulator.h b/src/Simulator/RedstoneSimulator.h
index 60c86a3c5..bb2efeb8a 100644
--- a/src/Simulator/RedstoneSimulator.h
+++ b/src/Simulator/RedstoneSimulator.h
@@ -4,7 +4,7 @@
#include "Simulator.h"
/// Per-chunk data for the simulator, specified individual chunks to simulate; 'Data' is not used
-typedef cCoordWithIntList cRedstoneSimulatorChunkData;
+typedef cCoordWithBlockVector cRedstoneSimulatorChunkData;
@@ -19,7 +19,7 @@ public:
cRedstoneSimulator(cWorld & a_World);
~cRedstoneSimulator();
- virtual void Simulate(float a_Dt) override {}; // Not used in this simulator
+ virtual void Simulate(float a_Dt) override { UNUSED(a_Dt);} // not used
virtual void SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, cChunk * a_Chunk) override;
virtual bool IsAllowedBlock( BLOCKTYPE a_BlockType ) override { return IsRedstone(a_BlockType); }
@@ -39,7 +39,6 @@ private:
{
Vector3i a_BlockPos; // Position of powered block
Vector3i a_SourcePos; // Position of source powering the block at a_BlockPos
- BLOCKTYPE a_SourceBlock; // The source block type (for pistons pushing away sources and replacing with non source etc.)
};
struct sLinkedPoweredBlocks // Define structure of the indirectly powered blocks list (i.e. repeaters powering through a block to the block at the other side)
@@ -47,8 +46,6 @@ private:
Vector3i a_BlockPos;
Vector3i a_MiddlePos;
Vector3i a_SourcePos;
- BLOCKTYPE a_SourceBlock;
- BLOCKTYPE a_MiddleBlock;
};
struct sSimulatedPlayerToggleableList
@@ -81,107 +78,97 @@ private:
// In addition to being non-performant, it would stop the player from actually breaking said device
/* ====== SOURCES ====== */
- /// <summary>Handles the redstone torch</summary>
+ /** Handles the redstone torch */
void HandleRedstoneTorch(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_MyState);
- /// <summary>Handles the redstone block</summary>
+ /** Handles the redstone block */
void HandleRedstoneBlock(int a_BlockX, int a_BlockY, int a_BlockZ);
- /// <summary>Handles levers</summary>
+ /** Handles levers */
void HandleRedstoneLever(int a_BlockX, int a_BlockY, int a_BlockZ);
- /// <summary>Handles buttons</summary>
+ /** Handles buttons */
void HandleRedstoneButton(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType);
- /// <summary>Handles daylight sensors</summary>
+ /** Handles daylight sensors */
void HandleDaylightSensor(int a_BlockX, int a_BlockY, int a_BlockZ);
- /// <summary>Handles pressure plates</summary>
+ /** Handles pressure plates */
void HandlePressurePlate(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_MyType);
/* ==================== */
/* ====== CARRIERS ====== */
- /// <summary>Handles redstone wire</summary>
+ /** Handles redstone wire */
void HandleRedstoneWire(int a_BlockX, int a_BlockY, int a_BlockZ);
- /// <summary>Handles repeaters</summary>
+ /** Handles repeaters */
void HandleRedstoneRepeater(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_MyState);
/* ====================== */
/* ====== DEVICES ====== */
- /// <summary>Handles pistons</summary>
+ /** Handles pistons */
void HandlePiston(int a_BlockX, int a_BlockY, int a_BlockZ);
- /// <summary>Handles dispensers and droppers</summary>
+ /** Handles dispensers and droppers */
void HandleDropSpenser(int a_BlockX, int a_BlockY, int a_BlockZ);
- /// <summary>Handles TNT (exploding)</summary>
+ /** Handles TNT (exploding) */
void HandleTNT(int a_BlockX, int a_BlockY, int a_BlockZ);
- /// <summary>Handles redstone lamps</summary>
+ /** Handles redstone lamps */
void HandleRedstoneLamp(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_MyState);
- /// <summary>Handles doords</summary>
+ /** Handles doords */
void HandleDoor(int a_BlockX, int a_BlockY, int a_BlockZ);
- /// <summary>Handles activator, detector, and powered rails</summary>
+ /** Handles command blocks */
+ void HandleCommandBlock(int a_BlockX, int a_BlockY, int a_BlockZ);
+ /** Handles activator, detector, and powered rails */
void HandleRail(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_MyType);
- /// <summary>Handles trapdoors</summary>
+ /** Handles trapdoors */
void HandleTrapdoor(int a_BlockX, int a_BlockY, int a_BlockZ);
- /// <summary>Handles noteblocks</summary>
+ /** Handles noteblocks */
void HandleNoteBlock(int a_BlockX, int a_BlockY, int a_BlockZ);
/* ===================== */
/* ====== Helper functions ====== */
- /// <summary>Marks a block as powered</summary>
+ /** Marks a block as powered */
void SetBlockPowered(int a_BlockX, int a_BlockY, int a_BlockZ, int a_SourceX, int a_SourceY, int a_SourceZ, BLOCKTYPE a_SourceBlock);
- /// <summary>Marks a block as being powered through another block</summary>
+ /** Marks a block as being powered through another block */
void 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_MiddeBlock);
- /// <summary>Marks a block as simulated, who should not be simulated further unless their power state changes, to accomodate a player manually toggling the block without triggering the simulator toggling it back</summary>
+ /** Marks a block as simulated, who should not be simulated further unless their power state changes, to accomodate a player manually toggling the block without triggering the simulator toggling it back */
void SetPlayerToggleableBlockAsSimulated(int a_BlockX, int a_BlockY, int a_BlockZ, bool WasLastStatePowered);
- /// <summary>Marks the second block in a direction as linked powered</summary>
+ /** Marks the second block in a direction as linked powered */
void SetDirectionLinkedPowered(int a_BlockX, int a_BlockY, int a_BlockZ, char a_Direction, BLOCKTYPE a_SourceBlock);
- /// <summary>Marks all blocks immediately surrounding a coordinate as powered</summary>
+ /** Marks all blocks immediately surrounding a coordinate as powered */
void SetAllDirsAsPowered(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_SourceBlock);
- /// <summary>Queues a repeater to be powered or unpowered</summary>
+ /** Queues a repeater to be powered or unpowered */
void QueueRepeaterPowerChange(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_Meta, short a_ElapsedTicks, bool ShouldPowerOn);
- /// <summary>Returns if a coordinate is powered or linked powered</summary>
+ /** Returns if a coordinate is powered or linked powered */
bool AreCoordsPowered(int a_BlockX, int a_BlockY, int a_BlockZ) { return AreCoordsDirectlyPowered(a_BlockX, a_BlockY, a_BlockZ) || AreCoordsLinkedPowered(a_BlockX, a_BlockY, a_BlockZ); }
- /// <summary>Returns if a coordinate is in the directly powered blocks list</summary>
+ /** Returns if a coordinate is in the directly powered blocks list */
bool AreCoordsDirectlyPowered(int a_BlockX, int a_BlockY, int a_BlockZ);
- /// <summary>Returns if a coordinate is in the indirectly powered blocks list</summary>
+ /** Returns if a coordinate is in the indirectly powered blocks list */
bool AreCoordsLinkedPowered(int a_BlockX, int a_BlockY, int a_BlockZ);
- /// <summary>Returns if a coordinate was marked as simulated (for blocks toggleable by players)</summary>
+ /** Returns if a coordinate was marked as simulated (for blocks toggleable by players) */
bool AreCoordsSimulated(int a_BlockX, int a_BlockY, int a_BlockZ, bool IsCurrentStatePowered);
- /// <summary>Returns if a repeater is powered</summary>
+ /** Returns if a repeater is powered */
bool IsRepeaterPowered(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_Meta);
- /// <summary>Returns if a piston is powered</summary>
+ /** Returns if a piston is powered */
bool IsPistonPowered(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_Meta);
+ /** Returns if a wire is powered
+ The only diffence between this and a normal AreCoordsPowered is that this function checks for a wire powering another wire
+ */
+ bool IsWirePowered(int a_BlockX, int a_BlockY, int a_BlockZ);
- /// <summary>Returns if lever metadata marks it as emitting power</summary>
+
+ /** Returns if lever metadata marks it as emitting power */
bool IsLeverOn(NIBBLETYPE a_BlockMeta);
- /// <summary>Returns if button metadata marks it as emitting power</summary>
+ /** Returns if button metadata marks it as emitting power */
bool IsButtonOn(NIBBLETYPE a_BlockMeta);
/* ============================== */
/* ====== Misc Functions ====== */
- /// <summary>Returns if a block is viable to be the MiddleBlock of a SetLinkedPowered operation</summary>
- inline static bool IsViableMiddleBlock(BLOCKTYPE Block)
- {
- if (!g_BlockIsSolid[Block]) { return false; }
+ /** Returns if a block is viable to be the MiddleBlock of a SetLinkedPowered operation */
+ inline static bool IsViableMiddleBlock(BLOCKTYPE Block) { return g_BlockFullyOccupiesVoxel[Block]; }
- switch (Block)
- {
- // Add SOLID but not viable middle blocks here
- case E_BLOCK_PISTON:
- case E_BLOCK_PISTON_EXTENSION:
- case E_BLOCK_STICKY_PISTON:
- case E_BLOCK_REDSTONE_REPEATER_ON:
- case E_BLOCK_REDSTONE_REPEATER_OFF:
- case E_BLOCK_DAYLIGHT_SENSOR:
- {
- return false;
- }
- default: return true;
- }
- }
-
- /// <summary>Returns if a block is a mechanism (something that accepts power and does something)</summary>
+ /** Returns if a block is a mechanism (something that accepts power and does something) */
inline static bool IsMechanism(BLOCKTYPE Block)
{
switch (Block)
{
case E_BLOCK_ACTIVATOR_RAIL:
+ case E_BLOCK_COMMAND_BLOCK:
case E_BLOCK_PISTON:
case E_BLOCK_STICKY_PISTON:
case E_BLOCK_DISPENSER:
@@ -205,16 +192,16 @@ private:
}
}
- /// <summary>Returns if a block has the potential to output power</summary>
+ /** Returns if a block has the potential to output power */
inline static bool IsPotentialSource(BLOCKTYPE Block)
{
switch (Block)
{
+ case E_BLOCK_DETECTOR_RAIL:
case E_BLOCK_DAYLIGHT_SENSOR:
case E_BLOCK_WOODEN_BUTTON:
case E_BLOCK_STONE_BUTTON:
case E_BLOCK_REDSTONE_WIRE:
- case E_BLOCK_REDSTONE_TORCH_OFF:
case E_BLOCK_REDSTONE_TORCH_ON:
case E_BLOCK_LEVER:
case E_BLOCK_REDSTONE_REPEATER_ON:
@@ -227,7 +214,7 @@ private:
}
}
- /// <summary>Returns if a block is any sort of redstone device</summary>
+ /** Returns if a block is any sort of redstone device */
inline static bool IsRedstone(BLOCKTYPE Block)
{
switch (Block)
@@ -236,6 +223,7 @@ private:
case E_BLOCK_ACTIVATOR_RAIL:
case E_BLOCK_ACTIVE_COMPARATOR:
case E_BLOCK_BLOCK_OF_REDSTONE:
+ case E_BLOCK_COMMAND_BLOCK:
case E_BLOCK_DETECTOR_RAIL:
case E_BLOCK_DISPENSER:
case E_BLOCK_DAYLIGHT_SENSOR:
@@ -248,6 +236,7 @@ private:
case E_BLOCK_LEVER:
case E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE:
case E_BLOCK_NOTE_BLOCK:
+ case E_BLOCK_POWERED_RAIL:
case E_BLOCK_REDSTONE_LAMP_OFF:
case E_BLOCK_REDSTONE_LAMP_ON:
case E_BLOCK_REDSTONE_REPEATER_OFF:
@@ -271,4 +260,4 @@ private:
default: return false;
}
}
-}; \ No newline at end of file
+};
diff --git a/src/Simulator/SandSimulator.h b/src/Simulator/SandSimulator.h
index 6e9ea15ac..6e64aa425 100644
--- a/src/Simulator/SandSimulator.h
+++ b/src/Simulator/SandSimulator.h
@@ -15,7 +15,7 @@ public:
cSandSimulator(cWorld & a_World, cIniFile & a_IniFile);
// cSimulator overrides:
- virtual void Simulate(float a_Dt) override {} // Unused in this simulator
+ virtual void Simulate(float a_Dt) override { UNUSED(a_Dt);} // not used
virtual void SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, cChunk * a_Chunk) override;
virtual bool IsAllowedBlock(BLOCKTYPE a_BlockType) override;
diff --git a/src/Simulator/Simulator.h b/src/Simulator/Simulator.h
index 5cd0e8657..a25b7f1b6 100644
--- a/src/Simulator/Simulator.h
+++ b/src/Simulator/Simulator.h
@@ -25,7 +25,14 @@ public:
virtual void Simulate(float a_Dt) = 0;
/// Called in each tick for each chunk, a_Dt is the time passed since the last tick, in msec; direct access to chunk data available
- virtual void SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, cChunk * a_Chunk) {};
+ virtual void SimulateChunk(float a_Dt, int a_ChunkX,
+ int a_ChunkZ, cChunk * a_Chunk)
+ {
+ UNUSED(a_Dt);
+ UNUSED(a_ChunkX);
+ UNUSED(a_ChunkZ);
+ UNUSED(a_Chunk);
+ };
/// Called when a block changes
virtual void WakeUp(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk);