Further improvements on redstone speed
Based on suggestions of @worktycho * Repeaters now walk their data structure only when needed * Fixed a bug with cChunkData returning an incorrect value for whether a meta had changed
This commit is contained in:
parent
b768e54ce8
commit
d5649df326
@ -258,7 +258,7 @@ bool cChunkData::SetMeta(int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE a_Nibble
|
|||||||
(m_Sections[Section]->m_BlockMetas[Index / 2] & (0xf0 >> ((Index & 1) * 4))) | // The untouched nibble
|
(m_Sections[Section]->m_BlockMetas[Index / 2] & (0xf0 >> ((Index & 1) * 4))) | // The untouched nibble
|
||||||
((a_Nibble & 0x0f) << ((Index & 1) * 4)) // The nibble being set
|
((a_Nibble & 0x0f) << ((Index & 1) * 4)) // The nibble being set
|
||||||
);
|
);
|
||||||
return oldval == a_Nibble;
|
return oldval != a_Nibble;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -266,19 +266,20 @@ void cIncrementalRedstoneSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int
|
|||||||
case E_BLOCK_REDSTONE_REPEATER_OFF:
|
case E_BLOCK_REDSTONE_REPEATER_OFF:
|
||||||
case E_BLOCK_REDSTONE_REPEATER_ON:
|
case E_BLOCK_REDSTONE_REPEATER_ON:
|
||||||
{
|
{
|
||||||
if (ShouldUpdateSimulateOnceBlocks)
|
bool FoundItem = false;
|
||||||
{
|
for (RepeatersDelayList::iterator repeateritr = m_RepeatersDelayList->begin(); repeateritr != m_RepeatersDelayList->end(); ++repeateritr)
|
||||||
HandleRedstoneRepeater(dataitr->x, dataitr->y, dataitr->z, dataitr->Data);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
for (RepeatersDelayList::const_iterator repeateritr = m_RepeatersDelayList->begin(); repeateritr != m_RepeatersDelayList->end(); ++repeateritr)
|
|
||||||
{
|
{
|
||||||
if (repeateritr->a_RelBlockPos == Vector3i(dataitr->x, dataitr->y, dataitr->z))
|
if (repeateritr->a_RelBlockPos == Vector3i(dataitr->x, dataitr->y, dataitr->z))
|
||||||
{
|
{
|
||||||
HandleRedstoneRepeater(dataitr->x, dataitr->y, dataitr->z, dataitr->Data);
|
HandleRedstoneRepeater(dataitr->x, dataitr->y, dataitr->z, dataitr->Data, repeateritr);
|
||||||
|
FoundItem = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!FoundItem && ShouldUpdateSimulateOnceBlocks)
|
||||||
|
{
|
||||||
|
HandleRedstoneRepeater(dataitr->x, dataitr->y, dataitr->z, dataitr->Data, m_RepeatersDelayList->end());
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case E_BLOCK_WOODEN_PRESSURE_PLATE:
|
case E_BLOCK_WOODEN_PRESSURE_PLATE:
|
||||||
@ -746,7 +747,7 @@ void cIncrementalRedstoneSimulator::HandleRedstoneWire(int a_RelBlockX, int a_Re
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cIncrementalRedstoneSimulator::HandleRedstoneRepeater(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, BLOCKTYPE a_MyState)
|
void cIncrementalRedstoneSimulator::HandleRedstoneRepeater(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, BLOCKTYPE a_MyState, RepeatersDelayList::iterator a_Itr)
|
||||||
{
|
{
|
||||||
/* Repeater Orientation Mini Guide:
|
/* Repeater Orientation Mini Guide:
|
||||||
===================================
|
===================================
|
||||||
@ -773,29 +774,42 @@ void cIncrementalRedstoneSimulator::HandleRedstoneRepeater(int a_RelBlockX, int
|
|||||||
NIBBLETYPE a_Meta = m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ);
|
NIBBLETYPE a_Meta = m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ);
|
||||||
bool IsOn = (a_MyState == E_BLOCK_REDSTONE_REPEATER_ON);
|
bool IsOn = (a_MyState == E_BLOCK_REDSTONE_REPEATER_ON);
|
||||||
|
|
||||||
|
bool WereItrsChanged = false;
|
||||||
if (!IsRepeaterLocked(a_RelBlockX, a_RelBlockY, a_RelBlockZ, 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_RelBlockX, a_RelBlockY, a_RelBlockZ, a_Meta);
|
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.
|
if (IsSelfPowered && !IsOn) // Queue a power change if powered, but not on and not locked.
|
||||||
{
|
{
|
||||||
QueueRepeaterPowerChange(a_RelBlockX, a_RelBlockY, a_RelBlockZ, a_Meta, true);
|
WereItrsChanged = 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_RelBlockX, a_RelBlockY, a_RelBlockZ, a_Meta, false);
|
WereItrsChanged = QueueRepeaterPowerChange(a_RelBlockX, a_RelBlockY, a_RelBlockZ, a_Meta, false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (WereItrsChanged)
|
||||||
|
{
|
||||||
|
for (a_Itr = m_RepeatersDelayList->begin(); a_Itr != m_RepeatersDelayList->end(); ++a_Itr)
|
||||||
|
{
|
||||||
|
if (a_Itr->a_RelBlockPos == Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (RepeatersDelayList::iterator itr = m_RepeatersDelayList->begin(); itr != m_RepeatersDelayList->end(); ++itr)
|
if (a_Itr->a_ElapsedTicks >= a_Itr->a_DelayTicks) // Has the elapsed ticks reached the target ticks?
|
||||||
{
|
{
|
||||||
if (!itr->a_RelBlockPos.Equals(Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ)))
|
if (a_Itr->ShouldPowerOn)
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (itr->a_ElapsedTicks >= itr->a_DelayTicks) // Has the elapsed ticks reached the target ticks?
|
|
||||||
{
|
|
||||||
if (itr->ShouldPowerOn)
|
|
||||||
{
|
{
|
||||||
if (!IsOn)
|
if (!IsOn)
|
||||||
{
|
{
|
||||||
@ -840,7 +854,7 @@ void cIncrementalRedstoneSimulator::HandleRedstoneRepeater(int a_RelBlockX, int
|
|||||||
{
|
{
|
||||||
m_Chunk->SetBlock(a_RelBlockX, a_RelBlockY, a_RelBlockZ, E_BLOCK_REDSTONE_REPEATER_OFF, a_Meta);
|
m_Chunk->SetBlock(a_RelBlockX, a_RelBlockY, a_RelBlockZ, 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(a_Itr); // We can remove off repeaters which don't need further updating
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -849,9 +863,8 @@ void cIncrementalRedstoneSimulator::HandleRedstoneRepeater(int a_RelBlockX, int
|
|||||||
// Apparently, incrementing ticks only works reliably here, and not in SimChunk;
|
// Apparently, incrementing ticks only works reliably here, and not in SimChunk;
|
||||||
// With a world with lots of redstone, the repeaters simply do not delay
|
// With a world with lots of redstone, the repeaters simply do not delay
|
||||||
// I am confounded to say why. Perhaps optimisation failure.
|
// I am confounded to say why. Perhaps optimisation failure.
|
||||||
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);
|
LOGD("Incremented a repeater @ {%i %i %i} | Elapsed ticks: %i | Target delay: %i", a_Itr->a_RelBlockPos.x, a_Itr->a_RelBlockPos.y, a_Itr->a_RelBlockPos.z, a_Itr->a_ElapsedTicks, a_Itr->a_DelayTicks);
|
||||||
itr->a_ElapsedTicks++;
|
a_Itr->a_ElapsedTicks++;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1914,7 +1927,7 @@ void cIncrementalRedstoneSimulator::SetPlayerToggleableBlockAsSimulated(int a_Re
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cIncrementalRedstoneSimulator::QueueRepeaterPowerChange(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, 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)
|
for (RepeatersDelayList::iterator itr = m_RepeatersDelayList->begin(); itr != m_RepeatersDelayList->end(); ++itr)
|
||||||
{
|
{
|
||||||
@ -1922,14 +1935,14 @@ void cIncrementalRedstoneSimulator::QueueRepeaterPowerChange(int a_RelBlockX, in
|
|||||||
{
|
{
|
||||||
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
|
// 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->a_ElapsedTicks = 0;
|
||||||
itr->ShouldPowerOn = ShouldPowerOn;
|
itr->ShouldPowerOn = ShouldPowerOn;
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1944,7 +1957,7 @@ void cIncrementalRedstoneSimulator::QueueRepeaterPowerChange(int a_RelBlockX, in
|
|||||||
RC.a_ElapsedTicks = 0;
|
RC.a_ElapsedTicks = 0;
|
||||||
RC.ShouldPowerOn = ShouldPowerOn;
|
RC.ShouldPowerOn = ShouldPowerOn;
|
||||||
m_RepeatersDelayList->push_back(RC);
|
m_RepeatersDelayList->push_back(RC);
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -108,7 +108,7 @@ private:
|
|||||||
/** Handles redstone wire */
|
/** Handles redstone wire */
|
||||||
void HandleRedstoneWire(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
|
void HandleRedstoneWire(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
|
||||||
/** Handles repeaters */
|
/** Handles repeaters */
|
||||||
void HandleRedstoneRepeater(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, BLOCKTYPE a_MyState);
|
void HandleRedstoneRepeater(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, BLOCKTYPE a_MyState, RepeatersDelayList::iterator a_Itr);
|
||||||
/* ====================== */
|
/* ====================== */
|
||||||
|
|
||||||
/* ====== DEVICES ====== */
|
/* ====== DEVICES ====== */
|
||||||
@ -145,8 +145,8 @@ private:
|
|||||||
void SetDirectionLinkedPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, char a_Direction, unsigned char a_PowerLevel = MAX_POWER_LEVEL);
|
void SetDirectionLinkedPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, char a_Direction, unsigned char a_PowerLevel = MAX_POWER_LEVEL);
|
||||||
/** Marks all blocks immediately surrounding a coordinate as powered */
|
/** Marks all blocks immediately surrounding a coordinate as powered */
|
||||||
void SetAllDirsAsPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, unsigned char a_PowerLevel = MAX_POWER_LEVEL);
|
void SetAllDirsAsPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, unsigned char a_PowerLevel = MAX_POWER_LEVEL);
|
||||||
/** Queues a repeater to be powered or unpowered */
|
/** Queues a repeater to be powered or unpowered and returns if the m_RepeatersDelayList iterators were invalidated */
|
||||||
void QueueRepeaterPowerChange(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, NIBBLETYPE a_Meta, bool ShouldPowerOn);
|
bool QueueRepeaterPowerChange(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, NIBBLETYPE a_Meta, bool ShouldPowerOn);
|
||||||
|
|
||||||
/** Returns if a coordinate is powered or linked powered */
|
/** Returns if a coordinate is powered or linked powered */
|
||||||
bool AreCoordsPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ) { return AreCoordsDirectlyPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ) || AreCoordsLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ); }
|
bool AreCoordsPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ) { return AreCoordsDirectlyPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ) || AreCoordsLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ); }
|
||||||
|
Loading…
Reference in New Issue
Block a user