Merge pull request #1096 from mc-server/redstonerefactor
Moved delayed repeaters to be handled in a seperate pass
This commit is contained in:
commit
35a4aa419c
@ -274,8 +274,19 @@ inline eBlockFace RotateBlockFaceCW(eBlockFace a_BlockFace)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline eBlockFace ReverseBlockFace(eBlockFace a_BlockFace)
|
||||||
|
{
|
||||||
|
switch (a_BlockFace)
|
||||||
|
{
|
||||||
|
case BLOCK_FACE_YP: return BLOCK_FACE_YM;
|
||||||
|
case BLOCK_FACE_XP: return BLOCK_FACE_XM;
|
||||||
|
case BLOCK_FACE_ZP: return BLOCK_FACE_ZM;
|
||||||
|
case BLOCK_FACE_YM: return BLOCK_FACE_YP;
|
||||||
|
case BLOCK_FACE_XM: return BLOCK_FACE_XP;
|
||||||
|
case BLOCK_FACE_ZM: return BLOCK_FACE_ZP;
|
||||||
|
default: return a_BlockFace;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/** Returns the textual representation of the BlockFace constant. */
|
/** Returns the textual representation of the BlockFace constant. */
|
||||||
|
@ -271,6 +271,8 @@ void cIncrementalRedstoneSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int
|
|||||||
ShouldUpdateSimulateOnceBlocks = true;
|
ShouldUpdateSimulateOnceBlocks = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HandleRedstoneRepeaterDelays();
|
||||||
|
|
||||||
for (cRedstoneSimulatorChunkData::iterator dataitr = m_RedstoneSimulatorChunkData->begin(); dataitr != m_RedstoneSimulatorChunkData->end();)
|
for (cRedstoneSimulatorChunkData::iterator dataitr = m_RedstoneSimulatorChunkData->begin(); dataitr != m_RedstoneSimulatorChunkData->end();)
|
||||||
{
|
{
|
||||||
if (dataitr->DataTwo)
|
if (dataitr->DataTwo)
|
||||||
@ -282,26 +284,6 @@ void cIncrementalRedstoneSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int
|
|||||||
switch (dataitr->Data)
|
switch (dataitr->Data)
|
||||||
{
|
{
|
||||||
case E_BLOCK_DAYLIGHT_SENSOR: HandleDaylightSensor(dataitr->x, dataitr->y, dataitr->z); break;
|
case E_BLOCK_DAYLIGHT_SENSOR: HandleDaylightSensor(dataitr->x, dataitr->y, dataitr->z); break;
|
||||||
|
|
||||||
case E_BLOCK_REDSTONE_REPEATER_OFF:
|
|
||||||
case E_BLOCK_REDSTONE_REPEATER_ON:
|
|
||||||
{
|
|
||||||
bool FoundItem = false;
|
|
||||||
for (RepeatersDelayList::iterator repeateritr = m_RepeatersDelayList->begin(); repeateritr != m_RepeatersDelayList->end(); ++repeateritr)
|
|
||||||
{
|
|
||||||
if (repeateritr->a_RelBlockPos == Vector3i(dataitr->x, dataitr->y, dataitr->z))
|
|
||||||
{
|
|
||||||
HandleRedstoneRepeater(dataitr->x, dataitr->y, dataitr->z, dataitr->Data, repeateritr);
|
|
||||||
FoundItem = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!FoundItem && ShouldUpdateSimulateOnceBlocks)
|
|
||||||
{
|
|
||||||
HandleRedstoneRepeater(dataitr->x, dataitr->y, dataitr->z, dataitr->Data, m_RepeatersDelayList->end());
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case E_BLOCK_WOODEN_PRESSURE_PLATE:
|
case E_BLOCK_WOODEN_PRESSURE_PLATE:
|
||||||
case E_BLOCK_STONE_PRESSURE_PLATE:
|
case E_BLOCK_STONE_PRESSURE_PLATE:
|
||||||
case E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE:
|
case E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE:
|
||||||
@ -357,6 +339,11 @@ void cIncrementalRedstoneSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int
|
|||||||
HandlePiston(dataitr->x, dataitr->y, dataitr->z);
|
HandlePiston(dataitr->x, dataitr->y, dataitr->z);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case E_BLOCK_REDSTONE_REPEATER_OFF:
|
||||||
|
case E_BLOCK_REDSTONE_REPEATER_ON:
|
||||||
|
{
|
||||||
|
HandleRedstoneRepeater(dataitr->x, dataitr->y, dataitr->z, dataitr->Data);
|
||||||
|
}
|
||||||
case E_BLOCK_REDSTONE_TORCH_OFF:
|
case E_BLOCK_REDSTONE_TORCH_OFF:
|
||||||
case E_BLOCK_REDSTONE_TORCH_ON:
|
case E_BLOCK_REDSTONE_TORCH_ON:
|
||||||
{
|
{
|
||||||
@ -511,29 +498,10 @@ void cIncrementalRedstoneSimulator::HandleRedstoneLever(int a_RelBlockX, int a_R
|
|||||||
{
|
{
|
||||||
SetAllDirsAsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ);
|
SetAllDirsAsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ);
|
||||||
|
|
||||||
NIBBLETYPE Dir = cBlockLeverHandler::BlockMetaDataToBlockFace(Meta);
|
eBlockFace Dir = cBlockLeverHandler::BlockMetaDataToBlockFace(Meta);
|
||||||
switch (Dir) // Now, flip the direction into the type used by SetBlockLinkedPowered()
|
|
||||||
{
|
Dir = ReverseBlockFace(Dir);
|
||||||
case BLOCK_FACE_YP:
|
|
||||||
case BLOCK_FACE_XP:
|
|
||||||
case BLOCK_FACE_ZP:
|
|
||||||
{
|
|
||||||
Dir--;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case BLOCK_FACE_XM:
|
|
||||||
case BLOCK_FACE_ZM:
|
|
||||||
case BLOCK_FACE_YM:
|
|
||||||
{
|
|
||||||
Dir++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
ASSERT(!"Unhandled lever metadata!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SetDirectionLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, Dir);
|
SetDirectionLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, Dir);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -579,27 +547,8 @@ void cIncrementalRedstoneSimulator::HandleRedstoneButton(int a_RelBlockX, int a_
|
|||||||
{
|
{
|
||||||
SetAllDirsAsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ);
|
SetAllDirsAsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ);
|
||||||
|
|
||||||
NIBBLETYPE Dir = cBlockButtonHandler::BlockMetaDataToBlockFace(Meta);
|
eBlockFace Dir = cBlockButtonHandler::BlockMetaDataToBlockFace(Meta);
|
||||||
switch (Dir) // Now, flip the direction into the type used by SetBlockLinkedPowered()
|
Dir = ReverseBlockFace(Dir);
|
||||||
{
|
|
||||||
case BLOCK_FACE_XP:
|
|
||||||
case BLOCK_FACE_ZP:
|
|
||||||
{
|
|
||||||
Dir--;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case BLOCK_FACE_XM:
|
|
||||||
case BLOCK_FACE_ZM:
|
|
||||||
{
|
|
||||||
Dir++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
ASSERT(!"Unhandled button metadata!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SetDirectionLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, Dir);
|
SetDirectionLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, Dir);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -766,7 +715,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, RepeatersDelayList::iterator a_Itr)
|
void cIncrementalRedstoneSimulator::HandleRedstoneRepeater(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, BLOCKTYPE a_MyState)
|
||||||
{
|
{
|
||||||
/* Repeater Orientation Mini Guide:
|
/* Repeater Orientation Mini Guide:
|
||||||
===================================
|
===================================
|
||||||
@ -793,102 +742,79 @@ 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.
|
||||||
{
|
{
|
||||||
WereItrsChanged = QueueRepeaterPowerChange(a_RelBlockX, a_RelBlockY, a_RelBlockZ, a_Meta, true);
|
QueueRepeaterPowerChange(a_RelBlockX, a_RelBlockY, a_RelBlockZ, a_Meta, true);
|
||||||
}
|
}
|
||||||
else if (!IsSelfPowered && IsOn) // Queue a power change if unpowered, on, and not locked.
|
else if (!IsSelfPowered && IsOn) // Queue a power change if unpowered, on, and not locked.
|
||||||
{
|
{
|
||||||
WereItrsChanged = QueueRepeaterPowerChange(a_RelBlockX, a_RelBlockY, a_RelBlockZ, a_Meta, false);
|
QueueRepeaterPowerChange(a_RelBlockX, a_RelBlockY, a_RelBlockZ, a_Meta, false);
|
||||||
}
|
|
||||||
else if (a_Itr == m_RepeatersDelayList->end())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (a_Itr == m_RepeatersDelayList->end())
|
}
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (WereItrsChanged)
|
void cIncrementalRedstoneSimulator::HandleRedstoneRepeaterDelays()
|
||||||
|
{
|
||||||
|
for (RepeatersDelayList::iterator itr = m_RepeatersDelayList->begin(); itr != m_RepeatersDelayList->end(); itr++)
|
||||||
{
|
{
|
||||||
for (a_Itr = m_RepeatersDelayList->begin(); a_Itr != m_RepeatersDelayList->end(); ++a_Itr)
|
|
||||||
|
if (itr->a_ElapsedTicks >= itr->a_DelayTicks) // Has the elapsed ticks reached the target ticks?
|
||||||
{
|
{
|
||||||
if (a_Itr->a_RelBlockPos == Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ))
|
int RelBlockX = itr->a_RelBlockPos.x;
|
||||||
|
int RelBlockY = itr->a_RelBlockPos.y;
|
||||||
|
int RelBlockZ = itr->a_RelBlockPos.z;
|
||||||
|
NIBBLETYPE Meta = m_Chunk->GetMeta(RelBlockX, RelBlockY, RelBlockZ);
|
||||||
|
if (itr->ShouldPowerOn)
|
||||||
{
|
{
|
||||||
// Leave a_Itr at where we found the entry
|
|
||||||
break;
|
m_Chunk->SetBlock(itr->a_RelBlockPos, E_BLOCK_REDSTONE_REPEATER_ON, Meta); // For performance
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// a_Itr may be passed with m_RepeatersDelayList::end, however, we can guarantee this iterator is always valid because...
|
switch (Meta & 0x3) // We only want the direction (bottom) bits
|
||||||
// ...QueueRepeaterPowerChange is called to add an entry (and the above code updates iterator). However, if the repeater was locked or something similar...
|
|
||||||
// ...we will never get here because of the returns.
|
|
||||||
if (a_Itr->a_ElapsedTicks >= a_Itr->a_DelayTicks) // Has the elapsed ticks reached the target ticks?
|
|
||||||
{
|
|
||||||
if (a_Itr->ShouldPowerOn)
|
|
||||||
{
|
|
||||||
if (!IsOn)
|
|
||||||
{
|
|
||||||
m_Chunk->SetBlock(a_RelBlockX, a_RelBlockY, a_RelBlockZ, E_BLOCK_REDSTONE_REPEATER_ON, a_Meta); // For performance
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (a_Meta & 0x3) // We only want the direction (bottom) bits
|
|
||||||
{
|
|
||||||
case 0x0:
|
|
||||||
{
|
{
|
||||||
SetBlockPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ - 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ);
|
case 0x0:
|
||||||
SetDirectionLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, BLOCK_FACE_ZM);
|
{
|
||||||
break;
|
SetBlockPowered(RelBlockX, RelBlockY, RelBlockZ - 1, RelBlockX, RelBlockY, RelBlockZ);
|
||||||
}
|
SetDirectionLinkedPowered(RelBlockX, RelBlockY, RelBlockZ, BLOCK_FACE_ZM);
|
||||||
case 0x1:
|
break;
|
||||||
{
|
}
|
||||||
SetBlockPowered(a_RelBlockX + 1, a_RelBlockY, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ);
|
case 0x1:
|
||||||
SetDirectionLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, BLOCK_FACE_XP);
|
{
|
||||||
break;
|
SetBlockPowered(RelBlockX + 1, RelBlockY, RelBlockZ, RelBlockX, RelBlockY, RelBlockZ);
|
||||||
}
|
SetDirectionLinkedPowered(RelBlockX, RelBlockY, RelBlockZ, BLOCK_FACE_XP);
|
||||||
case 0x2:
|
break;
|
||||||
{
|
}
|
||||||
SetBlockPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ + 1, a_RelBlockX, a_RelBlockY, a_RelBlockZ);
|
case 0x2:
|
||||||
SetDirectionLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, BLOCK_FACE_ZP);
|
{
|
||||||
break;
|
SetBlockPowered(RelBlockX, RelBlockY, RelBlockZ + 1, RelBlockX, RelBlockY, RelBlockZ);
|
||||||
}
|
SetDirectionLinkedPowered(RelBlockX, RelBlockY, RelBlockZ, BLOCK_FACE_ZP);
|
||||||
case 0x3:
|
break;
|
||||||
{
|
}
|
||||||
SetBlockPowered(a_RelBlockX - 1, a_RelBlockY, a_RelBlockZ, a_RelBlockX, a_RelBlockY, a_RelBlockZ);
|
case 0x3:
|
||||||
SetDirectionLinkedPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ, BLOCK_FACE_XM);
|
{
|
||||||
break;
|
SetBlockPowered(RelBlockX - 1, RelBlockY, RelBlockZ, RelBlockX, RelBlockY, RelBlockZ);
|
||||||
|
SetDirectionLinkedPowered(RelBlockX, RelBlockY, RelBlockZ, BLOCK_FACE_XM);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
// Removal of the data entry will be handled in SimChunk - we still want to continue trying to power blocks, even if our delay time has reached
|
{
|
||||||
// Otherwise, the power state of blocks in front won't update after we have powered on
|
m_Chunk->SetBlock(RelBlockX, RelBlockY, RelBlockZ, E_BLOCK_REDSTONE_REPEATER_OFF, Meta);
|
||||||
return;
|
}
|
||||||
|
m_RepeatersDelayList->erase(itr);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (IsOn)
|
// Apparently, incrementing ticks only works reliably here, and not in SimChunk;
|
||||||
{
|
// With a world with lots of redstone, the repeaters simply do not delay
|
||||||
m_Chunk->SetBlock(a_RelBlockX, a_RelBlockY, a_RelBlockZ, E_BLOCK_REDSTONE_REPEATER_OFF, a_Meta);
|
// 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);
|
||||||
m_RepeatersDelayList->erase(a_Itr); // We can remove off repeaters which don't need further updating
|
itr->a_ElapsedTicks++;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
// Apparently, incrementing ticks only works reliably here, and not in SimChunk;
|
|
||||||
// With a world with lots of redstone, the repeaters simply do not delay
|
|
||||||
// I am confounded to say why. Perhaps optimisation failure.
|
|
||||||
LOGD("Incremented a repeater @ {%i %i %i} | Elapsed ticks: %i | Target delay: %i", a_Itr->a_RelBlockPos.x, a_Itr->a_RelBlockPos.y, a_Itr->a_RelBlockPos.z, a_Itr->a_ElapsedTicks, a_Itr->a_DelayTicks);
|
|
||||||
a_Itr->a_ElapsedTicks++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -108,7 +108,9 @@ 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, RepeatersDelayList::iterator a_Itr);
|
void HandleRedstoneRepeater(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, BLOCKTYPE a_MyState);
|
||||||
|
/** Handles delayed updates to Repeaters **/
|
||||||
|
void HandleRedstoneRepeaterDelays();
|
||||||
/* ====================== */
|
/* ====================== */
|
||||||
|
|
||||||
/* ====== DEVICES ====== */
|
/* ====== DEVICES ====== */
|
||||||
|
Loading…
Reference in New Issue
Block a user