Sizeable speed improvements to redstone
+ Moved all simulator data into individual chunks * Cleaned up parameters for functions and some code * Fixed repeaters powering off faster than they power on The main issue before was that, although the redstone simulator stored blocks to be simulated in individual cChunks, other data, such as powered lists, and etcetera, were global regardless of which chunk was being simulated. Therefore, with worlds with lots of redstone, each tick saw the ticking of chunks, which themselves iterated through the entire dataset needlessly, creating LOTS of lag. Should be better now :)
This commit is contained in:
parent
a5b8d35845
commit
6eeeb2aa01
14
src/Chunk.h
14
src/Chunk.h
@ -343,12 +343,17 @@ public:
|
||||
NIBBLETYPE GetTimeAlteredLight(NIBBLETYPE a_Skylight) const;
|
||||
|
||||
|
||||
// Simulator data:
|
||||
// Per-chunk simulator data:
|
||||
cFireSimulatorChunkData & GetFireSimulatorData (void) { return m_FireSimulatorData; }
|
||||
cFluidSimulatorData * GetWaterSimulatorData(void) { return m_WaterSimulatorData; }
|
||||
cFluidSimulatorData * GetLavaSimulatorData (void) { return m_LavaSimulatorData; }
|
||||
cSandSimulatorChunkData & GetSandSimulatorData (void) { return m_SandSimulatorData; }
|
||||
cRedstoneSimulatorChunkData & GetRedstoneSimulatorData(void) { return m_RedstoneSimulatorData; }
|
||||
|
||||
cRedstoneSimulatorChunkData * GetRedstoneSimulatorData(void) { return &m_RedstoneSimulatorData; }
|
||||
cIncrementalRedstoneSimulator::PoweredBlocksList * GetRedstoneSimulatorPoweredBlocksList(void) { return &m_RedstoneSimulatorPoweredBlocksList; }
|
||||
cIncrementalRedstoneSimulator::LinkedBlocksList * GetRedstoneSimulatorLinkedBlocksList(void) { return &m_RedstoneSimulatorLinkedBlocksList; };
|
||||
cIncrementalRedstoneSimulator::SimulatedPlayerToggleableList * GetRedstoneSimulatorSimulatedPlayerToggleableList(void) { return &m_RedstoneSimulatorSimulatedPlayerToggleableList; };
|
||||
cIncrementalRedstoneSimulator::RepeatersDelayList * GetRedstoneSimulatorRepeatersDelayList(void) { return &m_RedstoneSimulatorRepeatersDelayList; };
|
||||
|
||||
cBlockEntity * GetBlockEntity(int a_BlockX, int a_BlockY, int a_BlockZ);
|
||||
cBlockEntity * GetBlockEntity(const Vector3i & a_BlockPos) { return GetBlockEntity(a_BlockPos.x, a_BlockPos.y, a_BlockPos.z); }
|
||||
@ -419,7 +424,12 @@ private:
|
||||
cFluidSimulatorData * m_WaterSimulatorData;
|
||||
cFluidSimulatorData * m_LavaSimulatorData;
|
||||
cSandSimulatorChunkData m_SandSimulatorData;
|
||||
|
||||
cRedstoneSimulatorChunkData m_RedstoneSimulatorData;
|
||||
cIncrementalRedstoneSimulator::PoweredBlocksList m_RedstoneSimulatorPoweredBlocksList;
|
||||
cIncrementalRedstoneSimulator::LinkedBlocksList m_RedstoneSimulatorLinkedBlocksList;
|
||||
cIncrementalRedstoneSimulator::SimulatedPlayerToggleableList m_RedstoneSimulatorSimulatedPlayerToggleableList;
|
||||
cIncrementalRedstoneSimulator::RepeatersDelayList m_RedstoneSimulatorRepeatersDelayList;
|
||||
|
||||
|
||||
// pick up a random block of this chunk
|
||||
|
@ -8,7 +8,6 @@
|
||||
#include "../Entities/TNTEntity.h"
|
||||
#include "../Blocks/BlockTorch.h"
|
||||
#include "../Blocks/BlockDoor.h"
|
||||
#include "../Blocks/BlockFenceGate.h"
|
||||
#include "../Piston.h"
|
||||
|
||||
|
||||
@ -53,7 +52,8 @@ void cIncrementalRedstoneSimulator::AddBlock(int a_BlockX, int a_BlockY, int a_B
|
||||
// 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
|
||||
|
||||
for (PoweredBlocksList::iterator itr = m_PoweredBlocks.begin(); itr != m_PoweredBlocks.end(); ++itr)
|
||||
PoweredBlocksList * PoweredBlocks = a_Chunk->GetRedstoneSimulatorPoweredBlocksList();
|
||||
for (PoweredBlocksList::iterator itr = PoweredBlocks->begin(); itr != PoweredBlocks->end(); ++itr)
|
||||
{
|
||||
if (!itr->a_SourcePos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ)))
|
||||
{
|
||||
@ -63,7 +63,7 @@ void cIncrementalRedstoneSimulator::AddBlock(int a_BlockX, int a_BlockY, int a_B
|
||||
if (!IsPotentialSource(Block))
|
||||
{
|
||||
LOGD("cIncrementalRedstoneSimulator: 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);
|
||||
&(*PoweredBlocks).erase(itr);
|
||||
break;
|
||||
}
|
||||
else if (
|
||||
@ -76,7 +76,7 @@ void cIncrementalRedstoneSimulator::AddBlock(int a_BlockX, int a_BlockY, int a_B
|
||||
)
|
||||
{
|
||||
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);
|
||||
m_PoweredBlocks.erase(itr);
|
||||
&(*PoweredBlocks).erase(itr);
|
||||
break;
|
||||
}
|
||||
else if (Block == E_BLOCK_DAYLIGHT_SENSOR)
|
||||
@ -94,21 +94,22 @@ void cIncrementalRedstoneSimulator::AddBlock(int a_BlockX, int a_BlockY, int a_B
|
||||
if (a_Chunk->GetTimeAlteredLight(SkyLight) <= 8) // Could use SkyLight - m_World.GetSkyDarkness();
|
||||
{
|
||||
LOGD("cIncrementalRedstoneSimulator: Erased daylight sensor from powered blocks list due to insufficient light level");
|
||||
m_PoweredBlocks.erase(itr);
|
||||
&(*PoweredBlocks).erase(itr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (LinkedBlocksList::iterator itr = m_LinkedPoweredBlocks.begin(); itr != m_LinkedPoweredBlocks.end(); ++itr)
|
||||
LinkedBlocksList * LinkedPoweredBlocks = a_Chunk->GetRedstoneSimulatorLinkedBlocksList();
|
||||
for (LinkedBlocksList::iterator itr = LinkedPoweredBlocks->begin(); itr != LinkedPoweredBlocks->end(); ++itr)
|
||||
{
|
||||
if (itr->a_SourcePos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ)))
|
||||
{
|
||||
if (!IsPotentialSource(Block))
|
||||
{
|
||||
LOGD("cIncrementalRedstoneSimulator: 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);
|
||||
&(*LinkedPoweredBlocks).erase(itr);
|
||||
break;
|
||||
}
|
||||
else if (
|
||||
@ -119,7 +120,7 @@ void cIncrementalRedstoneSimulator::AddBlock(int a_BlockX, int a_BlockY, int a_B
|
||||
)
|
||||
{
|
||||
LOGD("cIncrementalRedstoneSimulator: 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);
|
||||
&(*LinkedPoweredBlocks).erase(itr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -128,13 +129,14 @@ void cIncrementalRedstoneSimulator::AddBlock(int a_BlockX, int a_BlockY, int a_B
|
||||
if (!IsViableMiddleBlock(Block))
|
||||
{
|
||||
LOGD("cIncrementalRedstoneSimulator: 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);
|
||||
&(*LinkedPoweredBlocks).erase(itr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (SimulatedPlayerToggleableList::iterator itr = m_SimulatedPlayerToggleableBlocks.begin(); itr != m_SimulatedPlayerToggleableBlocks.end(); ++itr)
|
||||
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)))
|
||||
{
|
||||
@ -144,12 +146,13 @@ void cIncrementalRedstoneSimulator::AddBlock(int a_BlockX, int a_BlockY, int a_B
|
||||
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);
|
||||
m_SimulatedPlayerToggleableBlocks.erase(itr);
|
||||
&(*SimulatedPlayerToggleableBlocks).erase(itr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (RepeatersDelayList::iterator itr = m_RepeatersDelayList.begin(); itr != m_RepeatersDelayList.end(); ++itr)
|
||||
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)))
|
||||
{
|
||||
@ -158,13 +161,13 @@ void cIncrementalRedstoneSimulator::AddBlock(int a_BlockX, int a_BlockY, int a_B
|
||||
|
||||
if ((Block != E_BLOCK_REDSTONE_REPEATER_ON) && (Block != E_BLOCK_REDSTONE_REPEATER_OFF))
|
||||
{
|
||||
m_RepeatersDelayList.erase(itr);
|
||||
&(*RepeatersDelayList).erase(itr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
cRedstoneSimulatorChunkData & ChunkData = a_Chunk->GetRedstoneSimulatorData();
|
||||
for (cRedstoneSimulatorChunkData::iterator itr = ChunkData.begin(); itr != ChunkData.end(); ++itr)
|
||||
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
|
||||
{
|
||||
@ -185,7 +188,7 @@ void cIncrementalRedstoneSimulator::AddBlock(int a_BlockX, int a_BlockY, int a_B
|
||||
return;
|
||||
}
|
||||
|
||||
ChunkData.push_back(cCoordWithBlockAndBool(RelX, a_BlockY, RelZ, Block, false));
|
||||
RedstoneSimulatorChunkData->push_back(cCoordWithBlockAndBool(RelX, a_BlockY, RelZ, Block, false));
|
||||
}
|
||||
|
||||
|
||||
@ -199,20 +202,26 @@ void cIncrementalRedstoneSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int
|
||||
// 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())
|
||||
m_RedstoneSimulatorChunkData = a_Chunk->GetRedstoneSimulatorData();
|
||||
if (m_RedstoneSimulatorChunkData->empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_PoweredBlocks = a_Chunk->GetRedstoneSimulatorPoweredBlocksList();
|
||||
m_RepeatersDelayList = a_Chunk->GetRedstoneSimulatorRepeatersDelayList();
|
||||
m_SimulatedPlayerToggleableBlocks = a_Chunk->GetRedstoneSimulatorSimulatedPlayerToggleableList();
|
||||
m_LinkedPoweredBlocks = a_Chunk->GetRedstoneSimulatorLinkedBlocksList();
|
||||
m_Chunk = a_Chunk;
|
||||
|
||||
int BaseX = a_Chunk->GetPosX() * cChunkDef::Width;
|
||||
int BaseZ = a_Chunk->GetPosZ() * cChunkDef::Width;
|
||||
|
||||
for (cRedstoneSimulatorChunkData::iterator dataitr = ChunkData.begin(); dataitr != ChunkData.end();)
|
||||
for (cRedstoneSimulatorChunkData::iterator dataitr = m_RedstoneSimulatorChunkData->begin(); dataitr != m_RedstoneSimulatorChunkData->end();)
|
||||
{
|
||||
if (dataitr->DataTwo)
|
||||
{
|
||||
dataitr = ChunkData.erase(dataitr);
|
||||
dataitr = m_RedstoneSimulatorChunkData->erase(dataitr);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -293,6 +302,31 @@ 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) >= cChunkDef::Width - 2) ||
|
||||
((a_BlockX % cChunkDef::Width) <= cChunkDef::Width + 2) ||
|
||||
((a_BlockZ % cChunkDef::Width) >= cChunkDef::Width - 2) ||
|
||||
((a_BlockZ % cChunkDef::Width) <= cChunkDef::Width + 2)
|
||||
) // Are we on a chunk boundary? ± 2 because of LinkedPowered blocks
|
||||
{
|
||||
// On a chunk boundary, alert all four sides (i.e. at least one neighbouring chunk)
|
||||
AddBlock(a_BlockX, a_BlockY, a_BlockZ, a_Chunk);
|
||||
AddBlock(a_BlockX, a_BlockY, a_BlockZ, a_Chunk->GetNeighborChunk(a_BlockX - 1, a_BlockZ));
|
||||
AddBlock(a_BlockX, a_BlockY, a_BlockZ, a_Chunk->GetNeighborChunk(a_BlockX + 1, a_BlockZ));
|
||||
AddBlock(a_BlockX, a_BlockY, a_BlockZ, a_Chunk->GetNeighborChunk(a_BlockX, a_BlockZ - 1));
|
||||
AddBlock(a_BlockX, a_BlockY, a_BlockZ, a_Chunk->GetNeighborChunk(a_BlockX, a_BlockZ + 1));
|
||||
return;
|
||||
}
|
||||
|
||||
// Not on boundary, just alert this chunk for speed
|
||||
AddBlock(a_BlockX, a_BlockY, a_BlockZ, a_Chunk);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cIncrementalRedstoneSimulator::HandleRedstoneTorch(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_MyState)
|
||||
{
|
||||
@ -318,22 +352,6 @@ void cIncrementalRedstoneSimulator::HandleRedstoneTorch(int a_BlockX, int a_Bloc
|
||||
{
|
||||
// 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));
|
||||
|
||||
float Pitch = (((1.0F-0.0F)*((float)rand()/RAND_MAX)) - ((1.0F-0.0F)*((float)rand()/RAND_MAX))) * 0.8F;
|
||||
m_World.BroadcastSoundEffect("random.fizz",
|
||||
((int) (a_BlockX + 0.5F) * 8.0),
|
||||
((int) (a_BlockY + 0.5F) * 8.0),
|
||||
((int) (a_BlockZ + 0.5F) * 8.0),
|
||||
0.5F,
|
||||
2.6F + Pitch);
|
||||
|
||||
for (int l = 0; l < 5; ++l) {
|
||||
float d0 = a_BlockX + (double(rand())/RAND_MAX) * 0.6F + 0.2F;
|
||||
float d1 = a_BlockY + (double(rand())/RAND_MAX) * 0.6F + 0.2F;
|
||||
float d2 = a_BlockZ + (double(rand())/RAND_MAX) * 0.6F + 0.2F;
|
||||
m_World.BroadcastParticleEffect("smoke", d0, d1, d2, 0.0F, 0.0F, 0.0F, 0.01F, 1);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -554,7 +572,7 @@ void cIncrementalRedstoneSimulator::HandleRedstoneWire(int a_BlockX, int a_Block
|
||||
}
|
||||
}
|
||||
|
||||
if (TimesMetaSmaller == TimesFoundAWire)
|
||||
if ((TimesMetaSmaller == TimesFoundAWire) && (MyMeta != 0))
|
||||
{
|
||||
// All surrounding metas were smaller - self must have been a wire that was
|
||||
// transferring power to other wires around.
|
||||
@ -563,7 +581,7 @@ void cIncrementalRedstoneSimulator::HandleRedstoneWire(int a_BlockX, int a_Block
|
||||
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
|
||||
else if (MyMeta != MetaToSet)
|
||||
{
|
||||
m_World.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, MetaToSet);
|
||||
}
|
||||
@ -587,12 +605,15 @@ void cIncrementalRedstoneSimulator::HandleRedstoneWire(int a_BlockX, int a_Block
|
||||
{
|
||||
case REDSTONE_NONE:
|
||||
{
|
||||
SetAllDirsAsPowered(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_WIRE);
|
||||
SetBlockPowered(a_BlockX, a_BlockY - 1, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_WIRE);
|
||||
SetBlockPowered(a_BlockX + 1, a_BlockY, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_WIRE);
|
||||
SetBlockPowered(a_BlockX - 1, a_BlockY, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_WIRE);
|
||||
SetBlockPowered(a_BlockX, a_BlockY, a_BlockZ + 1, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_WIRE);
|
||||
SetBlockPowered(a_BlockX, a_BlockY, a_BlockZ - 1, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_WIRE);
|
||||
|
||||
SetDirectionLinkedPowered(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_XM, E_BLOCK_REDSTONE_WIRE);
|
||||
SetDirectionLinkedPowered(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_XP, E_BLOCK_REDSTONE_WIRE);
|
||||
SetDirectionLinkedPowered(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_YM, E_BLOCK_REDSTONE_WIRE);
|
||||
SetDirectionLinkedPowered(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_YP, E_BLOCK_REDSTONE_WIRE);
|
||||
SetDirectionLinkedPowered(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_ZM, E_BLOCK_REDSTONE_WIRE);
|
||||
SetDirectionLinkedPowered(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_ZP, E_BLOCK_REDSTONE_WIRE);
|
||||
break;
|
||||
@ -638,14 +659,14 @@ void cIncrementalRedstoneSimulator::HandleRedstoneRepeater(int a_BlockX, int a_B
|
||||
|
||||
if (IsSelfPowered && !IsOn) // Queue a power change if I am receiving power but not on
|
||||
{
|
||||
QueueRepeaterPowerChange(a_BlockX, a_BlockY, a_BlockZ, a_Meta, 0, true);
|
||||
QueueRepeaterPowerChange(a_BlockX, a_BlockY, a_BlockZ, a_Meta, true);
|
||||
}
|
||||
else if (!IsSelfPowered && IsOn) // Queue a power change if I am not receiving power but on
|
||||
{
|
||||
QueueRepeaterPowerChange(a_BlockX, a_BlockY, a_BlockZ, a_Meta, 0, false);
|
||||
QueueRepeaterPowerChange(a_BlockX, a_BlockY, a_BlockZ, a_Meta, false);
|
||||
}
|
||||
|
||||
for (RepeatersDelayList::iterator itr = m_RepeatersDelayList.begin(); itr != m_RepeatersDelayList.end(); ++itr)
|
||||
for (RepeatersDelayList::iterator itr = m_RepeatersDelayList->begin(); itr != m_RepeatersDelayList->end(); ++itr)
|
||||
{
|
||||
if (!itr->a_BlockPos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ)))
|
||||
{
|
||||
@ -699,7 +720,7 @@ void cIncrementalRedstoneSimulator::HandleRedstoneRepeater(int a_BlockX, int a_B
|
||||
{
|
||||
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
|
||||
m_RepeatersDelayList->erase(itr); // We can remove off repeaters which don't need further updating
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -1060,7 +1081,7 @@ void cIncrementalRedstoneSimulator::HandlePressurePlate(int a_BlockX, int a_Bloc
|
||||
|
||||
bool cIncrementalRedstoneSimulator::AreCoordsDirectlyPowered(int a_BlockX, int a_BlockY, int a_BlockZ)
|
||||
{
|
||||
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)))
|
||||
{
|
||||
@ -1076,7 +1097,7 @@ bool cIncrementalRedstoneSimulator::AreCoordsDirectlyPowered(int a_BlockX, int a
|
||||
|
||||
bool cIncrementalRedstoneSimulator::AreCoordsLinkedPowered(int a_BlockX, int a_BlockY, int a_BlockZ)
|
||||
{
|
||||
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)))
|
||||
{
|
||||
@ -1094,7 +1115,7 @@ bool cIncrementalRedstoneSimulator::IsRepeaterPowered(int a_BlockX, int a_BlockY
|
||||
{
|
||||
// Repeaters cannot be powered by any face except their back; verify that this is true for a source
|
||||
|
||||
for (PoweredBlocksList::const_iterator itr = m_PoweredBlocks.begin(); itr != m_PoweredBlocks.end(); ++itr)
|
||||
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; }
|
||||
|
||||
@ -1124,7 +1145,7 @@ bool cIncrementalRedstoneSimulator::IsRepeaterPowered(int a_BlockX, int a_BlockY
|
||||
}
|
||||
}
|
||||
|
||||
for (LinkedBlocksList::const_iterator itr = m_LinkedPoweredBlocks.begin(); itr != m_LinkedPoweredBlocks.end(); ++itr)
|
||||
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; }
|
||||
|
||||
@ -1165,7 +1186,7 @@ bool cIncrementalRedstoneSimulator::IsPistonPowered(int a_BlockX, int a_BlockY,
|
||||
int OldX = a_BlockX, OldY = a_BlockY, OldZ = a_BlockZ;
|
||||
eBlockFace Face = cPiston::MetaDataToDirection(a_Meta);
|
||||
|
||||
for (PoweredBlocksList::const_iterator itr = m_PoweredBlocks.begin(); itr != m_PoweredBlocks.end(); ++itr)
|
||||
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; }
|
||||
|
||||
@ -1181,7 +1202,7 @@ bool cIncrementalRedstoneSimulator::IsPistonPowered(int a_BlockX, int a_BlockY,
|
||||
a_BlockZ = OldZ;
|
||||
}
|
||||
|
||||
for (LinkedBlocksList::const_iterator itr = m_LinkedPoweredBlocks.begin(); itr != m_LinkedPoweredBlocks.end(); ++itr)
|
||||
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; }
|
||||
|
||||
@ -1204,7 +1225,7 @@ bool cIncrementalRedstoneSimulator::IsPistonPowered(int a_BlockX, int a_BlockY,
|
||||
|
||||
bool cIncrementalRedstoneSimulator::IsWirePowered(int a_BlockX, int a_BlockY, int a_BlockZ)
|
||||
{
|
||||
for (PoweredBlocksList::const_iterator itr = m_PoweredBlocks.begin(); itr != m_PoweredBlocks.end(); ++itr)
|
||||
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; }
|
||||
|
||||
@ -1214,7 +1235,7 @@ bool cIncrementalRedstoneSimulator::IsWirePowered(int a_BlockX, int a_BlockY, in
|
||||
}
|
||||
}
|
||||
|
||||
for (LinkedBlocksList::const_iterator itr = m_LinkedPoweredBlocks.begin(); itr != m_LinkedPoweredBlocks.end(); ++itr)
|
||||
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; }
|
||||
|
||||
@ -1232,7 +1253,7 @@ bool cIncrementalRedstoneSimulator::IsWirePowered(int a_BlockX, int a_BlockY, in
|
||||
|
||||
bool cIncrementalRedstoneSimulator::AreCoordsSimulated(int a_BlockX, int a_BlockY, int a_BlockZ, bool IsCurrentStatePowered)
|
||||
{
|
||||
for (SimulatedPlayerToggleableList::const_iterator itr = m_SimulatedPlayerToggleableBlocks.begin(); itr != m_SimulatedPlayerToggleableBlocks.end(); ++itr)
|
||||
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)))
|
||||
{
|
||||
@ -1375,7 +1396,9 @@ void cIncrementalRedstoneSimulator::SetBlockPowered(int a_BlockX, int a_BlockY,
|
||||
return;
|
||||
}
|
||||
|
||||
for (PoweredBlocksList::const_iterator itr = m_PoweredBlocks.begin(); itr != m_PoweredBlocks.end(); ++itr) // Check powered list
|
||||
PoweredBlocksList * Powered = m_Chunk->GetNeighborChunk(a_BlockX, a_BlockZ)->GetRedstoneSimulatorPoweredBlocksList();
|
||||
|
||||
for (PoweredBlocksList::const_iterator itr = Powered->begin(); itr != Powered->end(); ++itr) // Check powered list
|
||||
{
|
||||
if (
|
||||
itr->a_BlockPos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ)) &&
|
||||
@ -1390,7 +1413,7 @@ void cIncrementalRedstoneSimulator::SetBlockPowered(int a_BlockX, int a_BlockY,
|
||||
sPoweredBlocks RC;
|
||||
RC.a_BlockPos = Vector3i(a_BlockX, a_BlockY, a_BlockZ);
|
||||
RC.a_SourcePos = Vector3i(a_SourceX, a_SourceY, a_SourceZ);
|
||||
m_PoweredBlocks.push_back(RC);
|
||||
Powered->push_back(RC);
|
||||
}
|
||||
|
||||
|
||||
@ -1415,7 +1438,9 @@ void cIncrementalRedstoneSimulator::SetBlockLinkedPowered(
|
||||
return;
|
||||
}
|
||||
|
||||
for (LinkedBlocksList::const_iterator itr = m_LinkedPoweredBlocks.begin(); itr != m_LinkedPoweredBlocks.end(); ++itr) // Check linked powered list
|
||||
LinkedBlocksList * Linked = m_Chunk->GetNeighborChunk(a_BlockX, a_BlockZ)->GetRedstoneSimulatorLinkedBlocksList();
|
||||
|
||||
for (LinkedBlocksList::const_iterator itr = Linked->begin(); itr != Linked->end(); ++itr) // Check linked powered list
|
||||
{
|
||||
if (
|
||||
itr->a_BlockPos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ)) &&
|
||||
@ -1432,7 +1457,7 @@ void cIncrementalRedstoneSimulator::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);
|
||||
m_LinkedPoweredBlocks.push_back(RC);
|
||||
Linked->push_back(RC);
|
||||
}
|
||||
|
||||
|
||||
@ -1441,7 +1466,7 @@ void cIncrementalRedstoneSimulator::SetBlockLinkedPowered(
|
||||
|
||||
void cIncrementalRedstoneSimulator::SetPlayerToggleableBlockAsSimulated(int a_BlockX, int a_BlockY, int a_BlockZ, bool WasLastStatePowered)
|
||||
{
|
||||
for (SimulatedPlayerToggleableList::iterator itr = m_SimulatedPlayerToggleableBlocks.begin(); itr != m_SimulatedPlayerToggleableBlocks.end(); ++itr)
|
||||
for (SimulatedPlayerToggleableList::iterator itr = m_SimulatedPlayerToggleableBlocks->begin(); itr != m_SimulatedPlayerToggleableBlocks->end(); ++itr)
|
||||
{
|
||||
if (!itr->a_BlockPos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ)))
|
||||
{
|
||||
@ -1465,16 +1490,16 @@ void cIncrementalRedstoneSimulator::SetPlayerToggleableBlockAsSimulated(int a_Bl
|
||||
sSimulatedPlayerToggleableList RC;
|
||||
RC.a_BlockPos = Vector3i(a_BlockX, a_BlockY, a_BlockZ);
|
||||
RC.WasLastStatePowered = WasLastStatePowered;
|
||||
m_SimulatedPlayerToggleableBlocks.push_back(RC);
|
||||
m_SimulatedPlayerToggleableBlocks->push_back(RC);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cIncrementalRedstoneSimulator::QueueRepeaterPowerChange(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_Meta, short a_ElapsedTicks, bool ShouldPowerOn)
|
||||
void cIncrementalRedstoneSimulator::QueueRepeaterPowerChange(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_Meta, bool ShouldPowerOn)
|
||||
{
|
||||
for (RepeatersDelayList::iterator itr = m_RepeatersDelayList.begin(); itr != m_RepeatersDelayList.end(); ++itr)
|
||||
for (RepeatersDelayList::iterator itr = m_RepeatersDelayList->begin(); itr != m_RepeatersDelayList->end(); ++itr)
|
||||
{
|
||||
if (itr->a_BlockPos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ)))
|
||||
{
|
||||
@ -1484,7 +1509,7 @@ void cIncrementalRedstoneSimulator::QueueRepeaterPowerChange(int a_BlockX, int a
|
||||
}
|
||||
|
||||
// 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) + (ShouldPowerOn ? 1 : 0)) * 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;
|
||||
@ -1497,13 +1522,11 @@ void cIncrementalRedstoneSimulator::QueueRepeaterPowerChange(int a_BlockX, int a
|
||||
|
||||
// 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 apparently, MCS ticks are way faster than vanilla ticks, so repeater aren't noticeably delayed
|
||||
// We don't +1 when powering off because everything seems to already delay a tick when powering off, why? No idea :P
|
||||
RC.a_DelayTicks = (((a_Meta & 0xC) >> 0x2) + (ShouldPowerOn ? 1 : 0)) * 2;
|
||||
|
||||
RC.a_DelayTicks = (((a_Meta & 0xC) >> 0x2) + 1) * 2;
|
||||
|
||||
RC.a_ElapsedTicks = 0;
|
||||
RC.ShouldPowerOn = ShouldPowerOn;
|
||||
m_RepeatersDelayList.push_back(RC);
|
||||
m_RepeatersDelayList->push_back(RC);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
#include "RedstoneSimulator.h"
|
||||
|
||||
/// Per-chunk data for the simulator, specified individual chunks to simulate; 'Data' is not used
|
||||
/// Per-chunk data for the simulator, specified individual chunks to simulate
|
||||
typedef cCoordWithBlockAndBoolVector cRedstoneSimulatorChunkData;
|
||||
|
||||
|
||||
@ -22,6 +22,7 @@ public:
|
||||
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); }
|
||||
virtual void WakeUp(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk) override;
|
||||
|
||||
enum eRedstoneDirection
|
||||
{
|
||||
@ -57,22 +58,28 @@ private:
|
||||
struct sRepeatersDelayList
|
||||
{
|
||||
Vector3i a_BlockPos;
|
||||
short a_DelayTicks;
|
||||
short a_ElapsedTicks;
|
||||
unsigned char a_DelayTicks;
|
||||
unsigned char a_ElapsedTicks;
|
||||
bool ShouldPowerOn;
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
typedef std::vector <sPoweredBlocks> PoweredBlocksList;
|
||||
typedef std::vector <sLinkedPoweredBlocks> LinkedBlocksList;
|
||||
typedef std::vector <sSimulatedPlayerToggleableList> SimulatedPlayerToggleableList;
|
||||
typedef std::vector <sRepeatersDelayList> RepeatersDelayList;
|
||||
|
||||
PoweredBlocksList m_PoweredBlocks;
|
||||
LinkedBlocksList m_LinkedPoweredBlocks;
|
||||
SimulatedPlayerToggleableList m_SimulatedPlayerToggleableBlocks;
|
||||
RepeatersDelayList m_RepeatersDelayList;
|
||||
private:
|
||||
|
||||
cRedstoneSimulatorChunkData * m_RedstoneSimulatorChunkData;
|
||||
PoweredBlocksList * m_PoweredBlocks;
|
||||
LinkedBlocksList * m_LinkedPoweredBlocks;
|
||||
SimulatedPlayerToggleableList * m_SimulatedPlayerToggleableBlocks;
|
||||
RepeatersDelayList * m_RepeatersDelayList;
|
||||
|
||||
virtual void AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk) override;
|
||||
cChunk * m_Chunk;
|
||||
|
||||
// We want a_MyState for devices needing a full FastSetBlock (as opposed to meta) because with our simulation model, we cannot keep setting the block if it is already set correctly
|
||||
// In addition to being non-performant, it would stop the player from actually breaking said device
|
||||
@ -84,8 +91,6 @@ private:
|
||||
void HandleRedstoneBlock(int a_BlockX, int a_BlockY, int a_BlockZ);
|
||||
/** Handles levers */
|
||||
void HandleRedstoneLever(int a_BlockX, int a_BlockY, int a_BlockZ);
|
||||
/** Handles Fence Gates */
|
||||
void HandleFenceGate(int a_BlockX, int a_BlockY, int a_BlockZ);
|
||||
/** Handles buttons */
|
||||
void HandleRedstoneButton(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType);
|
||||
/** Handles daylight sensors */
|
||||
@ -118,6 +123,8 @@ private:
|
||||
void HandleRail(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_MyType);
|
||||
/** Handles trapdoors */
|
||||
void HandleTrapdoor(int a_BlockX, int a_BlockY, int a_BlockZ);
|
||||
/** Handles fence gates */
|
||||
void HandleFenceGate(int a_BlockX, int a_BlockY, int a_BlockZ);
|
||||
/** Handles noteblocks */
|
||||
void HandleNoteBlock(int a_BlockX, int a_BlockY, int a_BlockZ);
|
||||
/* ===================== */
|
||||
@ -134,7 +141,7 @@ private:
|
||||
/** Marks all blocks immediately surrounding a coordinate as powered */
|
||||
void SetAllDirsAsPowered(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_SourceBlock);
|
||||
/** 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);
|
||||
void QueueRepeaterPowerChange(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_Meta, bool ShouldPowerOn);
|
||||
|
||||
/** 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); }
|
||||
@ -267,3 +274,7 @@ private:
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user