summaryrefslogtreecommitdiffstats
path: root/src/Simulator
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/Simulator/RedstoneSimulator.cpp141
-rw-r--r--src/Simulator/RedstoneSimulator.h12
2 files changed, 134 insertions, 19 deletions
diff --git a/src/Simulator/RedstoneSimulator.cpp b/src/Simulator/RedstoneSimulator.cpp
index 9fdbd1151..63e4f04a8 100644
--- a/src/Simulator/RedstoneSimulator.cpp
+++ b/src/Simulator/RedstoneSimulator.cpp
@@ -160,6 +160,29 @@ void cRedstoneSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, c
}
}
+ for (SimulatedPlayerToggleableList::iterator itr = m_SimulatedPlayerToggleableBlocks.begin(); itr != m_SimulatedPlayerToggleableBlocks.end();)
+ {
+ sSimulatedPlayerToggleableList & Change = *itr;
+
+ int RelX = Change.a_BlockPos.x - a_ChunkX * cChunkDef::Width;
+ int RelZ = Change.a_BlockPos.z - a_ChunkZ * cChunkDef::Width;
+
+ BLOCKTYPE SourceBlockType;
+ if (!a_Chunk->UnboundedRelGetBlockType(RelX, Change.a_BlockPos.y, RelZ, SourceBlockType))
+ {
+ continue;
+ }
+ else if (!IsAllowedBlock(SourceBlockType))
+ {
+ LOGD("cRedstoneSimulator: Erased block %s from toggleable simulated list due to power state change", ItemToFullString(SourceBlockType).c_str());
+ itr = m_SimulatedPlayerToggleableBlocks.erase(itr);
+ }
+ else
+ {
+ ++itr;
+ }
+ }
+
for (cRedstoneSimulatorChunkData::iterator dataitr = ChunkData.begin(), end = ChunkData.end(); dataitr != end;)
{
BLOCKTYPE BlockType = a_Chunk->GetBlock(dataitr->x, dataitr->y, dataitr->z);
@@ -314,7 +337,6 @@ void cRedstoneSimulator::HandleRedstoneTorch(int a_BlockX, int a_BlockY, int a_B
// Block torch on not powered, can be turned on again!
m_World.FastSetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_TORCH_ON, m_World.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ));
}
- return;
}
@@ -325,7 +347,6 @@ void cRedstoneSimulator::HandleRedstoneBlock(int a_BlockX, int a_BlockY, int a_B
{
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
- return;
}
@@ -345,7 +366,6 @@ void cRedstoneSimulator::HandleRedstoneLever(int a_BlockX, int a_BlockY, int a_B
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);
}
- return;
}
@@ -497,7 +517,6 @@ void cRedstoneSimulator::HandleRedstoneWire(int a_BlockX, int a_BlockY, int a_Bl
}
}
}
- return;
}
@@ -556,7 +575,6 @@ void cRedstoneSimulator::HandleRedstoneRepeater(int a_BlockX, int a_BlockY, int
m_World.FastSetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_REPEATER_OFF, a_Meta);
}
}
- return;
}
@@ -574,7 +592,6 @@ void cRedstoneSimulator::HandlePiston(int a_BlockX, int a_BlockY, int a_BlockZ)
{
Piston.RetractPiston(a_BlockX, a_BlockY, a_BlockZ);
}
- return;
}
@@ -598,7 +615,6 @@ void cRedstoneSimulator::HandleDropSpenser(int a_BlockX, int a_BlockY, int a_Blo
} DrSpSP (AreCoordsPowered(a_BlockX, a_BlockY, a_BlockZ));
m_World.DoWithDropSpenserAt(a_BlockX, a_BlockY, a_BlockZ, DrSpSP);
- return;
}
@@ -611,17 +627,16 @@ void cRedstoneSimulator::HandleRedstoneLamp(int a_BlockX, int a_BlockY, int a_Bl
{
if (AreCoordsPowered(a_BlockX, a_BlockY, a_BlockZ))
{
- m_World.FastSetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_LAMP_ON, 0);
+ m_World.SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_LAMP_ON, 0);
}
}
else
{
if (!AreCoordsPowered(a_BlockX, a_BlockY, a_BlockZ))
{
- m_World.FastSetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_LAMP_OFF, 0);
+ m_World.SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_LAMP_OFF, 0);
}
}
- return;
}
@@ -634,9 +649,8 @@ void cRedstoneSimulator::HandleTNT(int a_BlockX, int a_BlockY, int a_BlockZ)
{
m_World.BroadcastSoundEffect("random.fuse", a_BlockX * 8, a_BlockY * 8, a_BlockZ * 8, 0.5f, 0.6f);
m_World.SpawnPrimedTNT(a_BlockX + 0.5, a_BlockY + 0.5, a_BlockZ + 0.5, 4); // 4 seconds to boom
- m_World.FastSetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_AIR, 0);
+ m_World.SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_AIR, 0);
}
- return;
}
@@ -689,7 +703,6 @@ void cRedstoneSimulator::HandleDoor(int a_BlockX, int a_BlockY, int a_BlockZ)
}
}
}
- return;
}
@@ -732,11 +745,19 @@ void cRedstoneSimulator::HandleTrapdoor(int a_BlockX, int a_BlockY, int a_BlockZ
{
if (AreCoordsPowered(a_BlockX, a_BlockY, a_BlockZ))
{
- m_World.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, m_World.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ) | 0x4);
+ if (!AreCoordsSimulated(a_BlockX, a_BlockY, a_BlockZ, true))
+ {
+ m_World.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, m_World.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ) | 0x4);
+ SetPlayerToggleableBlockAsSimulated(a_BlockX, a_BlockY, a_BlockZ, true);
+ }
}
else
{
- m_World.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, m_World.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ) & 0xB); // Take into account that the fourth bit is needed for trapdoors too
+ if (!AreCoordsSimulated(a_BlockX, a_BlockY, a_BlockZ, false))
+ {
+ m_World.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, m_World.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ) & 0xB); // Take into account that the fourth bit is needed for trapdoors too
+ SetPlayerToggleableBlockAsSimulated(a_BlockX, a_BlockY, a_BlockZ, false);
+ }
}
}
@@ -892,6 +913,31 @@ bool cRedstoneSimulator::IsPistonPowered(int a_BlockX, int a_BlockY, int a_Block
+bool cRedstoneSimulator::AreCoordsSimulated(int a_BlockX, int a_BlockY, int a_BlockZ, bool IsCurrentStatePowered)
+{
+ for (SimulatedPlayerToggleableList::iterator itr = m_SimulatedPlayerToggleableBlocks.begin(); itr != m_SimulatedPlayerToggleableBlocks.end(); ++itr)
+ {
+ sSimulatedPlayerToggleableList & Change = *itr;
+
+ if (Change.a_BlockPos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ)))
+ {
+ if (Change.WasLastStatePowered != IsCurrentStatePowered) // Was the last power state different to the current?
+ {
+ 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 false; // Block wasn't even in the list, not simulated
+}
+
+
+
+
+
void cRedstoneSimulator::SetDirectionLinkedPowered(int a_BlockX, int a_BlockY, int a_BlockZ, char a_Direction, BLOCKTYPE a_SourceType)
{
switch (a_Direction)
@@ -1124,7 +1170,6 @@ void cRedstoneSimulator::SetDirectionLinkedPowered(int a_BlockX, int a_BlockY, i
break;
}
}
- return;
}
@@ -1150,7 +1195,6 @@ void cRedstoneSimulator::SetAllDirsAsPowered(int a_BlockX, int a_BlockY, int a_B
{
SetBlockPowered(a_BlockX + gCrossCoords[i].x, a_BlockY + gCrossCoords[i].y, a_BlockZ + gCrossCoords[i].z, a_BlockX, a_BlockY, a_BlockZ, a_SourceBlock);
}
- return;
}
@@ -1165,12 +1209,25 @@ void cRedstoneSimulator::SetBlockPowered(int a_BlockX, int a_BlockY, int a_Block
return;
}
+ for (PoweredBlocksList::iterator itr = m_PoweredBlocks.begin(); itr != m_PoweredBlocks.end(); ++itr) // Check powered list
+ {
+ sPoweredBlocks & Change = *itr;
+
+ if (
+ Change.a_BlockPos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ)) &&
+ Change.a_SourcePos.Equals(Vector3i(a_SourceX, a_SourceY, a_SourceZ))
+ )
+ {
+ // Check for duplicates
+ 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_SourceBlock = a_SourceBlock;
m_PoweredBlocks.push_back(RC);
- return;
}
@@ -1194,6 +1251,21 @@ void cRedstoneSimulator::SetBlockLinkedPowered(
return;
}
+ for (LinkedBlocksList::iterator itr = m_LinkedPoweredBlocks.begin(); itr != m_LinkedPoweredBlocks.end(); ++itr) // Check linked powered list
+ {
+ sLinkedPoweredBlocks & Change = *itr;
+
+ if (
+ Change.a_BlockPos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ)) &&
+ Change.a_MiddlePos.Equals(Vector3i(a_MiddleX, a_MiddleY, a_MiddleZ)) &&
+ Change.a_SourcePos.Equals(Vector3i(a_SourceX, a_SourceY, a_SourceZ))
+ )
+ {
+ // Check for duplicates
+ return;
+ }
+ }
+
sLinkedPoweredBlocks RC;
RC.a_BlockPos = Vector3i(a_BlockX, a_BlockY, a_BlockZ);
RC.a_MiddlePos = Vector3i(a_MiddleX, a_MiddleY, a_MiddleZ);
@@ -1201,7 +1273,38 @@ void cRedstoneSimulator::SetBlockLinkedPowered(
RC.a_SourceBlock = a_SourceBlock;
RC.a_MiddleBlock = a_MiddleBlock;
m_LinkedPoweredBlocks.push_back(RC);
- return;
+}
+
+
+
+
+
+void cRedstoneSimulator::SetPlayerToggleableBlockAsSimulated(int a_BlockX, int a_BlockY, int a_BlockZ, bool WasLastStatePowered)
+{
+ for (SimulatedPlayerToggleableList::iterator itr = m_SimulatedPlayerToggleableBlocks.begin(); itr != m_SimulatedPlayerToggleableBlocks.end(); ++itr)
+ {
+ sSimulatedPlayerToggleableList & Change = *itr;
+
+ if (Change.a_BlockPos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ)))
+ {
+ if (Change.WasLastStatePowered != WasLastStatePowered)
+ {
+ // If power states different, erase the old listing in preparation to add new one
+ m_SimulatedPlayerToggleableBlocks.erase(itr);
+ break;
+ }
+ else
+ {
+ // If states the same, just ignore
+ return;
+ }
+ }
+ }
+
+ sSimulatedPlayerToggleableList RC;
+ RC.a_BlockPos = Vector3i(a_BlockX, a_BlockY, a_BlockZ);
+ RC.WasLastStatePowered = WasLastStatePowered;
+ m_SimulatedPlayerToggleableBlocks.push_back(RC);
}
diff --git a/src/Simulator/RedstoneSimulator.h b/src/Simulator/RedstoneSimulator.h
index 59400b614..e094150e8 100644
--- a/src/Simulator/RedstoneSimulator.h
+++ b/src/Simulator/RedstoneSimulator.h
@@ -50,12 +50,20 @@ private:
BLOCKTYPE a_SourceBlock;
BLOCKTYPE a_MiddleBlock;
};
+
+ struct sSimulatedPlayerToggleableList
+ {
+ Vector3i a_BlockPos;
+ bool WasLastStatePowered;
+ };
typedef std::vector <sPoweredBlocks> PoweredBlocksList;
typedef std::vector <sLinkedPoweredBlocks> LinkedBlocksList;
+ typedef std::vector <sSimulatedPlayerToggleableList> SimulatedPlayerToggleableList;
PoweredBlocksList m_PoweredBlocks;
LinkedBlocksList m_LinkedPoweredBlocks;
+ SimulatedPlayerToggleableList m_SimulatedPlayerToggleableBlocks;
virtual void AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk) override;
@@ -102,6 +110,8 @@ private:
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>
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>
+ 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>
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>
@@ -109,6 +119,8 @@ private:
/// <summary>Returns if a coordinate is powered or linked powered</summary>
bool AreCoordsPowered(int a_BlockX, int a_BlockY, int a_BlockZ);
+ /// <summary>Returns if a coordinate was marked as simulated (for blocks toggleable by players)</summary>
+ bool AreCoordsSimulated(int a_BlockX, int a_BlockY, int a_BlockZ, bool IsCurrentStatePowered);
/// <summary>Returns if a repeater is powered</summary>
bool IsRepeaterPowered(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_Meta);
/// <summary>Returns if a piston is powered</summary>