Changed appropriate containers to unordered_map
Thanks to @worktycho for guidance! * Potential speed improvements
This commit is contained in:
parent
6a831c0b6f
commit
171c59a01b
@ -514,32 +514,3 @@ typedef cCoordWithData<BLOCKTYPE> cCoordWithBlock;
|
|||||||
|
|
||||||
typedef std::list<cCoordWithInt> cCoordWithIntList;
|
typedef std::list<cCoordWithInt> cCoordWithIntList;
|
||||||
typedef std::vector<cCoordWithInt> cCoordWithIntVector;
|
typedef std::vector<cCoordWithInt> cCoordWithIntVector;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** Generic template that can store two types of any kind of data together with a triplet of 3 coords */
|
|
||||||
template <typename X, typename Z> class cCoordWithDoubleData
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
int x;
|
|
||||||
int y;
|
|
||||||
int z;
|
|
||||||
X Data;
|
|
||||||
Z DataTwo;
|
|
||||||
|
|
||||||
cCoordWithDoubleData(int a_X, int a_Y, int a_Z) :
|
|
||||||
x(a_X), y(a_Y), z(a_Z)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
cCoordWithDoubleData(int a_X, int a_Y, int a_Z, const X & a_Data, const Z & a_DataTwo) :
|
|
||||||
x(a_X), y(a_Y), z(a_Z), Data(a_Data), DataTwo(a_DataTwo)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef cCoordWithDoubleData <BLOCKTYPE, bool> cCoordWithBlockAndBool;
|
|
||||||
|
|
||||||
typedef std::vector<cCoordWithBlockAndBool> cCoordWithBlockAndBoolVector;
|
|
||||||
|
@ -124,21 +124,6 @@ public:
|
|||||||
return m_PathPoints.size();
|
return m_PathPoints.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
struct VectorHasher
|
|
||||||
{
|
|
||||||
std::size_t operator()(const Vector3i & a_Vector) const
|
|
||||||
{
|
|
||||||
// Guaranteed to have no hash collisions for any 128x128x128 area. Suitable for pathfinding.
|
|
||||||
int32_t t = 0;
|
|
||||||
t += static_cast<int8_t>(a_Vector.x);
|
|
||||||
t = t << 8;
|
|
||||||
t += static_cast<int8_t>(a_Vector.y);
|
|
||||||
t = t << 8;
|
|
||||||
t += static_cast<int8_t>(a_Vector.z);
|
|
||||||
t = t << 8;
|
|
||||||
return static_cast<size_t>(t);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
/* General */
|
/* General */
|
||||||
@ -160,7 +145,7 @@ private:
|
|||||||
|
|
||||||
/* Pathfinding fields */
|
/* Pathfinding fields */
|
||||||
std::priority_queue<cPathCell *, std::vector<cPathCell *>, compareHeuristics> m_OpenList;
|
std::priority_queue<cPathCell *, std::vector<cPathCell *>, compareHeuristics> m_OpenList;
|
||||||
std::unordered_map<Vector3i, cPathCell, VectorHasher> m_Map;
|
std::unordered_map<Vector3i, cPathCell, Vector3i> m_Map;
|
||||||
Vector3i m_Destination;
|
Vector3i m_Destination;
|
||||||
Vector3i m_Source;
|
Vector3i m_Source;
|
||||||
int m_BoundingBoxWidth;
|
int m_BoundingBoxWidth;
|
||||||
|
@ -92,67 +92,45 @@ void cIncrementalRedstoneSimulator::AddBlock(const Vector3i & a_RelBlockPosition
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto & SimulatedPlayerToggleableBlocks = static_cast<cIncrementalRedstoneSimulatorChunkData *>(a_OriginalChunk->GetRedstoneSimulatorData())->m_SimulatedPlayerToggleableBlocks;
|
auto & SimulatedPlayerToggleableBlocks = static_cast<cIncrementalRedstoneSimulatorChunkData *>(a_OriginalChunk->GetRedstoneSimulatorData())->m_SimulatedPlayerToggleableBlocks;
|
||||||
if (
|
if (DoesIgnorePlayerToggle(Block))
|
||||||
DoesIgnorePlayerToggle(Block) &&
|
|
||||||
std::find_if(SimulatedPlayerToggleableBlocks.begin(), SimulatedPlayerToggleableBlocks.end(),
|
|
||||||
[a_RelBlockPosition](const sSimulatedPlayerToggleableList & itr){ return itr.a_RelBlockPos == a_RelBlockPosition; }) == SimulatedPlayerToggleableBlocks.end()
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
// We have arrived here; no block must be in list - add one
|
|
||||||
sSimulatedPlayerToggleableList RC;
|
|
||||||
RC.a_RelBlockPos = a_RelBlockPosition;
|
|
||||||
RC.WasLastStatePowered = AreCoordsDirectlyPowered(a_RelBlockPosition.x, a_RelBlockPosition.y, a_RelBlockPosition.z, a_OriginalChunk) || AreCoordsLinkedPowered(a_RelBlockPosition.x, a_RelBlockPosition.y, a_RelBlockPosition.z, a_OriginalChunk);
|
|
||||||
|
|
||||||
// Initialise the toggleable blocks list so that trapdoors etc. aren't reset on restart (#1887)
|
// Initialise the toggleable blocks list so that trapdoors etc. aren't reset on restart (#1887)
|
||||||
SimulatedPlayerToggleableBlocks.emplace_back(RC);
|
SimulatedPlayerToggleableBlocks.emplace(
|
||||||
|
a_RelBlockPosition,
|
||||||
|
AreCoordsDirectlyPowered(a_RelBlockPosition.x, a_RelBlockPosition.y, a_RelBlockPosition.z, a_OriginalChunk) || AreCoordsLinkedPowered(a_RelBlockPosition.x, a_RelBlockPosition.y, a_RelBlockPosition.z, a_OriginalChunk)
|
||||||
|
); // This map won't insert if key already present, so no need to check
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SimulatedPlayerToggleableBlocks.erase(a_RelBlockPosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
SimulatedPlayerToggleableBlocks.erase(std::remove_if(SimulatedPlayerToggleableBlocks.begin(), SimulatedPlayerToggleableBlocks.end(), [a_RelBlockPosition, Block, this](const sSimulatedPlayerToggleableList & itr)
|
if ((Block != E_BLOCK_REDSTONE_REPEATER_ON) && (Block != E_BLOCK_REDSTONE_REPEATER_OFF))
|
||||||
{
|
{
|
||||||
return (itr.a_RelBlockPos == a_RelBlockPosition) && !DoesIgnorePlayerToggle(Block);
|
static_cast<cIncrementalRedstoneSimulatorChunkData *>(a_OriginalChunk->GetRedstoneSimulatorData())->m_RepeatersDelayList.erase(a_RelBlockPosition);
|
||||||
}
|
}
|
||||||
), SimulatedPlayerToggleableBlocks.end());
|
|
||||||
|
|
||||||
auto & RepeatersDelayList = static_cast<cIncrementalRedstoneSimulatorChunkData *>(a_OriginalChunk->GetRedstoneSimulatorData())->m_RepeatersDelayList;
|
|
||||||
RepeatersDelayList.erase(std::remove_if(RepeatersDelayList.begin(), RepeatersDelayList.end(), [a_RelBlockPosition, Block](const sRepeatersDelayList & itr)
|
|
||||||
{
|
|
||||||
return (itr.a_RelBlockPos == a_RelBlockPosition) && (Block != E_BLOCK_REDSTONE_REPEATER_ON) && (Block != E_BLOCK_REDSTONE_REPEATER_OFF);
|
|
||||||
}
|
|
||||||
), RepeatersDelayList.end());
|
|
||||||
|
|
||||||
auto & RedstoneSimulatorChunkData = static_cast<cIncrementalRedstoneSimulatorChunkData *>(a_OriginalChunk->GetRedstoneSimulatorData())->m_ChunkData;
|
auto & RedstoneSimulatorChunkData = static_cast<cIncrementalRedstoneSimulatorChunkData *>(a_OriginalChunk->GetRedstoneSimulatorData())->m_ChunkData;
|
||||||
for (auto & itr : RedstoneSimulatorChunkData)
|
auto Iterator = RedstoneSimulatorChunkData.find(a_RelBlockPosition);
|
||||||
{
|
|
||||||
if (a_RelBlockPosition == Vector3i(itr.x, itr.y, itr.z)) // We are at an entry matching the current (changed) block
|
|
||||||
{
|
|
||||||
if (!IsAllowedBlock(Block))
|
|
||||||
{
|
|
||||||
itr.DataTwo = true; // The new blocktype is not redstone; it must be queued to be removed from this list
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
itr.DataTwo = false;
|
|
||||||
itr.Data = Block; // Update block information
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!IsAllowedBlock(Block))
|
if (!IsAllowedBlock(Block))
|
||||||
{
|
{
|
||||||
|
if (Iterator != RedstoneSimulatorChunkData.end())
|
||||||
|
{
|
||||||
|
Iterator->second.second = true; // The new blocktype is not redstone; it must be queued to be removed from this list
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
auto & QueuedData = static_cast<cIncrementalRedstoneSimulatorChunkData *>(a_OriginalChunk->GetRedstoneSimulatorData())->m_QueuedChunkData;
|
|
||||||
for (const auto & itr : QueuedData)
|
|
||||||
{
|
{
|
||||||
if (a_RelBlockPosition == Vector3i(itr.x, itr.y, itr.z))
|
if (Iterator != RedstoneSimulatorChunkData.end())
|
||||||
{
|
{
|
||||||
// Can't have duplicates in here either, in case something adds the block again before the structure can written to the main chunk data
|
Iterator->second.second = false;
|
||||||
|
Iterator->second.first = Block; // Update block information
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
QueuedData.emplace_back(cCoordWithBlockAndBool(a_RelBlockPosition.x, a_RelBlockPosition.y, a_RelBlockPosition.z, Block, false));
|
|
||||||
|
RedstoneSimulatorChunkData.emplace(a_RelBlockPosition, std::make_pair(Block, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -167,19 +145,11 @@ void cIncrementalRedstoneSimulator::SimulateChunk(std::chrono::milliseconds a_Dt
|
|||||||
m_RedstoneSimulatorChunkData = new cIncrementalRedstoneSimulator::cIncrementalRedstoneSimulatorChunkData();
|
m_RedstoneSimulatorChunkData = new cIncrementalRedstoneSimulator::cIncrementalRedstoneSimulatorChunkData();
|
||||||
a_Chunk->SetRedstoneSimulatorData(m_RedstoneSimulatorChunkData);
|
a_Chunk->SetRedstoneSimulatorData(m_RedstoneSimulatorChunkData);
|
||||||
}
|
}
|
||||||
if (m_RedstoneSimulatorChunkData->m_ChunkData.empty() && static_cast<cIncrementalRedstoneSimulatorChunkData *>(a_Chunk->GetRedstoneSimulatorData())->m_QueuedChunkData.empty())
|
if (m_RedstoneSimulatorChunkData->m_ChunkData.empty())
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_RedstoneSimulatorChunkData->m_ChunkData.insert(
|
|
||||||
m_RedstoneSimulatorChunkData->m_ChunkData.end(),
|
|
||||||
m_RedstoneSimulatorChunkData->m_QueuedChunkData.begin(),
|
|
||||||
m_RedstoneSimulatorChunkData->m_QueuedChunkData.end()
|
|
||||||
);
|
|
||||||
|
|
||||||
m_RedstoneSimulatorChunkData->m_QueuedChunkData.clear();
|
|
||||||
|
|
||||||
m_PoweredBlocks = &m_RedstoneSimulatorChunkData->m_PoweredBlocks;
|
m_PoweredBlocks = &m_RedstoneSimulatorChunkData->m_PoweredBlocks;
|
||||||
m_RepeatersDelayList = &m_RedstoneSimulatorChunkData->m_RepeatersDelayList;
|
m_RepeatersDelayList = &m_RedstoneSimulatorChunkData->m_RepeatersDelayList;
|
||||||
m_SimulatedPlayerToggleableBlocks = &m_RedstoneSimulatorChunkData->m_SimulatedPlayerToggleableBlocks;
|
m_SimulatedPlayerToggleableBlocks = &m_RedstoneSimulatorChunkData->m_SimulatedPlayerToggleableBlocks;
|
||||||
@ -199,24 +169,24 @@ void cIncrementalRedstoneSimulator::SimulateChunk(std::chrono::milliseconds a_Dt
|
|||||||
|
|
||||||
for (auto dataitr = m_RedstoneSimulatorChunkData->m_ChunkData.begin(); dataitr != m_RedstoneSimulatorChunkData->m_ChunkData.end();)
|
for (auto dataitr = m_RedstoneSimulatorChunkData->m_ChunkData.begin(); dataitr != m_RedstoneSimulatorChunkData->m_ChunkData.end();)
|
||||||
{
|
{
|
||||||
if (dataitr->DataTwo)
|
if (dataitr->second.second)
|
||||||
{
|
{
|
||||||
dataitr = m_RedstoneSimulatorChunkData->m_ChunkData.erase(dataitr);
|
dataitr = m_RedstoneSimulatorChunkData->m_ChunkData.erase(dataitr);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (dataitr->Data)
|
switch (dataitr->second.first)
|
||||||
{
|
{
|
||||||
case E_BLOCK_DAYLIGHT_SENSOR: HandleDaylightSensor(dataitr->x, dataitr->y, dataitr->z); break;
|
case E_BLOCK_DAYLIGHT_SENSOR: HandleDaylightSensor(dataitr->first.x, dataitr->first.y, dataitr->first.z); break;
|
||||||
case E_BLOCK_TRIPWIRE: HandleTripwire(dataitr->x, dataitr->y, dataitr->z); break;
|
case E_BLOCK_TRIPWIRE: HandleTripwire(dataitr->first.x, dataitr->first.y, dataitr->first.z); break;
|
||||||
case E_BLOCK_TRIPWIRE_HOOK: HandleTripwireHook(dataitr->x, dataitr->y, dataitr->z); break;
|
case E_BLOCK_TRIPWIRE_HOOK: HandleTripwireHook(dataitr->first.x, dataitr->first.y, dataitr->first.z); 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:
|
||||||
case E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE:
|
case E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE:
|
||||||
{
|
{
|
||||||
HandlePressurePlate(dataitr->x, dataitr->y, dataitr->z, dataitr->Data);
|
HandlePressurePlate(dataitr->first.x, dataitr->first.y, dataitr->first.z, dataitr->second.first);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: break;
|
default: break;
|
||||||
@ -224,23 +194,23 @@ void cIncrementalRedstoneSimulator::SimulateChunk(std::chrono::milliseconds a_Dt
|
|||||||
|
|
||||||
if (ShouldUpdateSimulateOnceBlocks)
|
if (ShouldUpdateSimulateOnceBlocks)
|
||||||
{
|
{
|
||||||
switch (dataitr->Data)
|
switch (dataitr->second.first)
|
||||||
{
|
{
|
||||||
case E_BLOCK_REDSTONE_WIRE: HandleRedstoneWire(dataitr->x, dataitr->y, dataitr->z); break;
|
case E_BLOCK_REDSTONE_WIRE: HandleRedstoneWire(dataitr->first.x, dataitr->first.y, dataitr->first.z); break;
|
||||||
case E_BLOCK_COMMAND_BLOCK: HandleCommandBlock(dataitr->x, dataitr->y, dataitr->z); break;
|
case E_BLOCK_COMMAND_BLOCK: HandleCommandBlock(dataitr->first.x, dataitr->first.y, dataitr->first.z); break;
|
||||||
case E_BLOCK_NOTE_BLOCK: HandleNoteBlock(dataitr->x, dataitr->y, dataitr->z); break;
|
case E_BLOCK_NOTE_BLOCK: HandleNoteBlock(dataitr->first.x, dataitr->first.y, dataitr->first.z); break;
|
||||||
case E_BLOCK_BLOCK_OF_REDSTONE: HandleRedstoneBlock(dataitr->x, dataitr->y, dataitr->z); break;
|
case E_BLOCK_BLOCK_OF_REDSTONE: HandleRedstoneBlock(dataitr->first.x, dataitr->first.y, dataitr->first.z); break;
|
||||||
case E_BLOCK_LEVER: HandleRedstoneLever(dataitr->x, dataitr->y, dataitr->z); break;
|
case E_BLOCK_LEVER: HandleRedstoneLever(dataitr->first.x, dataitr->first.y, dataitr->first.z); break;
|
||||||
case E_BLOCK_TNT: HandleTNT(dataitr->x, dataitr->y, dataitr->z); break;
|
case E_BLOCK_TNT: HandleTNT(dataitr->first.x, dataitr->first.y, dataitr->first.z); break;
|
||||||
case E_BLOCK_IRON_TRAPDOOR: HandleTrapdoor(dataitr->x, dataitr->y, dataitr->z); break;
|
case E_BLOCK_IRON_TRAPDOOR: HandleTrapdoor(dataitr->first.x, dataitr->first.y, dataitr->first.z); break;
|
||||||
case E_BLOCK_TRAPDOOR: HandleTrapdoor(dataitr->x, dataitr->y, dataitr->z); break;
|
case E_BLOCK_TRAPDOOR: HandleTrapdoor(dataitr->first.x, dataitr->first.y, dataitr->first.z); break;
|
||||||
case E_BLOCK_TRAPPED_CHEST: HandleTrappedChest(dataitr->x, dataitr->y, dataitr->z); break;
|
case E_BLOCK_TRAPPED_CHEST: HandleTrappedChest(dataitr->first.x, dataitr->first.y, dataitr->first.z); break;
|
||||||
|
|
||||||
case E_BLOCK_ACTIVATOR_RAIL:
|
case E_BLOCK_ACTIVATOR_RAIL:
|
||||||
case E_BLOCK_DETECTOR_RAIL:
|
case E_BLOCK_DETECTOR_RAIL:
|
||||||
case E_BLOCK_POWERED_RAIL:
|
case E_BLOCK_POWERED_RAIL:
|
||||||
{
|
{
|
||||||
HandleRail(dataitr->x, dataitr->y, dataitr->z, dataitr->Data);
|
HandleRail(dataitr->first.x, dataitr->first.y, dataitr->first.z, dataitr->second.first);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case E_BLOCK_ACACIA_DOOR:
|
case E_BLOCK_ACACIA_DOOR:
|
||||||
@ -251,7 +221,7 @@ void cIncrementalRedstoneSimulator::SimulateChunk(std::chrono::milliseconds a_Dt
|
|||||||
case E_BLOCK_WOODEN_DOOR:
|
case E_BLOCK_WOODEN_DOOR:
|
||||||
case E_BLOCK_IRON_DOOR:
|
case E_BLOCK_IRON_DOOR:
|
||||||
{
|
{
|
||||||
HandleDoor(dataitr->x, dataitr->y, dataitr->z);
|
HandleDoor(dataitr->first.x, dataitr->first.y, dataitr->first.z);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case E_BLOCK_ACACIA_FENCE_GATE:
|
case E_BLOCK_ACACIA_FENCE_GATE:
|
||||||
@ -261,49 +231,49 @@ void cIncrementalRedstoneSimulator::SimulateChunk(std::chrono::milliseconds a_Dt
|
|||||||
case E_BLOCK_JUNGLE_FENCE_GATE:
|
case E_BLOCK_JUNGLE_FENCE_GATE:
|
||||||
case E_BLOCK_SPRUCE_FENCE_GATE:
|
case E_BLOCK_SPRUCE_FENCE_GATE:
|
||||||
{
|
{
|
||||||
HandleFenceGate(dataitr->x, dataitr->y, dataitr->z);
|
HandleFenceGate(dataitr->first.x, dataitr->first.y, dataitr->first.z);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case E_BLOCK_REDSTONE_LAMP_OFF:
|
case E_BLOCK_REDSTONE_LAMP_OFF:
|
||||||
case E_BLOCK_REDSTONE_LAMP_ON:
|
case E_BLOCK_REDSTONE_LAMP_ON:
|
||||||
{
|
{
|
||||||
HandleRedstoneLamp(dataitr->x, dataitr->y, dataitr->z, dataitr->Data);
|
HandleRedstoneLamp(dataitr->first.x, dataitr->first.y, dataitr->first.z, dataitr->second.first);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case E_BLOCK_DISPENSER:
|
case E_BLOCK_DISPENSER:
|
||||||
case E_BLOCK_DROPPER:
|
case E_BLOCK_DROPPER:
|
||||||
{
|
{
|
||||||
HandleDropSpenser(dataitr->x, dataitr->y, dataitr->z);
|
HandleDropSpenser(dataitr->first.x, dataitr->first.y, dataitr->first.z);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case E_BLOCK_PISTON:
|
case E_BLOCK_PISTON:
|
||||||
case E_BLOCK_STICKY_PISTON:
|
case E_BLOCK_STICKY_PISTON:
|
||||||
{
|
{
|
||||||
HandlePiston(dataitr->x, dataitr->y, dataitr->z);
|
HandlePiston(dataitr->first.x, dataitr->first.y, dataitr->first.z);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case E_BLOCK_REDSTONE_REPEATER_OFF:
|
case E_BLOCK_REDSTONE_REPEATER_OFF:
|
||||||
case E_BLOCK_REDSTONE_REPEATER_ON:
|
case E_BLOCK_REDSTONE_REPEATER_ON:
|
||||||
{
|
{
|
||||||
HandleRedstoneRepeater(dataitr->x, dataitr->y, dataitr->z, dataitr->Data);
|
HandleRedstoneRepeater(dataitr->first.x, dataitr->first.y, dataitr->first.z, dataitr->second.first);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case E_BLOCK_REDSTONE_TORCH_OFF:
|
case E_BLOCK_REDSTONE_TORCH_OFF:
|
||||||
case E_BLOCK_REDSTONE_TORCH_ON:
|
case E_BLOCK_REDSTONE_TORCH_ON:
|
||||||
{
|
{
|
||||||
HandleRedstoneTorch(dataitr->x, dataitr->y, dataitr->z, dataitr->Data);
|
HandleRedstoneTorch(dataitr->first.x, dataitr->first.y, dataitr->first.z, dataitr->second.first);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case E_BLOCK_STONE_BUTTON:
|
case E_BLOCK_STONE_BUTTON:
|
||||||
case E_BLOCK_WOODEN_BUTTON:
|
case E_BLOCK_WOODEN_BUTTON:
|
||||||
{
|
{
|
||||||
HandleRedstoneButton(dataitr->x, dataitr->y, dataitr->z);
|
HandleRedstoneButton(dataitr->first.x, dataitr->first.y, dataitr->first.z);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case E_BLOCK_ACTIVE_COMPARATOR:
|
case E_BLOCK_ACTIVE_COMPARATOR:
|
||||||
case E_BLOCK_INACTIVE_COMPARATOR:
|
case E_BLOCK_INACTIVE_COMPARATOR:
|
||||||
{
|
{
|
||||||
HandleRedstoneComparator(dataitr->x, dataitr->y, dataitr->z);
|
HandleRedstoneComparator(dataitr->first.x, dataitr->first.y, dataitr->first.z);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: break;
|
default: break;
|
||||||
@ -872,32 +842,29 @@ void cIncrementalRedstoneSimulator::HandleRedstoneRepeaterDelays()
|
|||||||
{
|
{
|
||||||
for (auto itr = m_RepeatersDelayList->begin(); itr != m_RepeatersDelayList->end();)
|
for (auto itr = m_RepeatersDelayList->begin(); itr != m_RepeatersDelayList->end();)
|
||||||
{
|
{
|
||||||
if (itr->a_ElapsedTicks >= itr->a_DelayTicks) // Has the elapsed ticks reached the target ticks?
|
if (itr->second.a_ElapsedTicks >= itr->second.a_DelayTicks) // Has the elapsed ticks reached the target ticks?
|
||||||
{
|
{
|
||||||
int RelBlockX = itr->a_RelBlockPos.x;
|
|
||||||
int RelBlockY = itr->a_RelBlockPos.y;
|
|
||||||
int RelBlockZ = itr->a_RelBlockPos.z;
|
|
||||||
BLOCKTYPE Block;
|
BLOCKTYPE Block;
|
||||||
NIBBLETYPE Meta;
|
NIBBLETYPE Meta;
|
||||||
m_Chunk->GetBlockTypeMeta(RelBlockX, RelBlockY, RelBlockZ, Block, Meta);
|
m_Chunk->GetBlockTypeMeta(itr->first.x, itr->first.y, itr->first.z, Block, Meta);
|
||||||
if (itr->ShouldPowerOn)
|
if (itr->second.ShouldPowerOn)
|
||||||
{
|
{
|
||||||
if (Block != E_BLOCK_REDSTONE_REPEATER_ON) // For performance
|
if (Block != E_BLOCK_REDSTONE_REPEATER_ON) // For performance
|
||||||
{
|
{
|
||||||
m_Chunk->SetBlock(itr->a_RelBlockPos, E_BLOCK_REDSTONE_REPEATER_ON, Meta);
|
m_Chunk->SetBlock(itr->first, E_BLOCK_REDSTONE_REPEATER_ON, Meta);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (Block != E_BLOCK_REDSTONE_REPEATER_OFF)
|
else if (Block != E_BLOCK_REDSTONE_REPEATER_OFF)
|
||||||
{
|
{
|
||||||
m_Chunk->SetBlock(RelBlockX, RelBlockY, RelBlockZ, E_BLOCK_REDSTONE_REPEATER_OFF, Meta);
|
m_Chunk->SetBlock(itr->first.x, itr->first.y, itr->first.z, E_BLOCK_REDSTONE_REPEATER_OFF, Meta);
|
||||||
}
|
}
|
||||||
itr = m_RepeatersDelayList->erase(itr);
|
itr = m_RepeatersDelayList->erase(itr);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
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", itr->first.x, itr->first.y, itr->first.z, itr->second.a_ElapsedTicks, itr->second.a_DelayTicks);
|
||||||
itr->a_ElapsedTicks++;
|
itr->second.a_ElapsedTicks++;
|
||||||
itr++;
|
++itr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1871,9 +1838,9 @@ bool cIncrementalRedstoneSimulator::AreCoordsSimulated(int a_RelBlockX, int a_Re
|
|||||||
{
|
{
|
||||||
for (const auto & itr : *m_SimulatedPlayerToggleableBlocks)
|
for (const auto & itr : *m_SimulatedPlayerToggleableBlocks)
|
||||||
{
|
{
|
||||||
if (itr.a_RelBlockPos.Equals(Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ)))
|
if (itr.first.Equals(Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ)))
|
||||||
{
|
{
|
||||||
if (itr.WasLastStatePowered != IsCurrentStatePowered) // Was the last power state different to the current?
|
if (itr.second != IsCurrentStatePowered) // Was the last power state different to the current?
|
||||||
{
|
{
|
||||||
return false; // It was, coordinates are no longer simulated
|
return false; // It was, coordinates are no longer simulated
|
||||||
}
|
}
|
||||||
@ -2116,60 +2083,37 @@ void cIncrementalRedstoneSimulator::SetBlockLinkedPowered(
|
|||||||
|
|
||||||
void cIncrementalRedstoneSimulator::SetPlayerToggleableBlockAsSimulated(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, bool a_WasLastStatePowered)
|
void cIncrementalRedstoneSimulator::SetPlayerToggleableBlockAsSimulated(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, bool a_WasLastStatePowered)
|
||||||
{
|
{
|
||||||
for (auto & itr : *m_SimulatedPlayerToggleableBlocks)
|
m_SimulatedPlayerToggleableBlocks->operator[](Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ)) = a_WasLastStatePowered;
|
||||||
{
|
|
||||||
if (!itr.a_RelBlockPos.Equals(Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ)))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update listing
|
|
||||||
itr.WasLastStatePowered = a_WasLastStatePowered;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// We have arrived here; no block must be in list - add one
|
|
||||||
sSimulatedPlayerToggleableList RC;
|
|
||||||
RC.a_RelBlockPos = Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ);
|
|
||||||
RC.WasLastStatePowered = a_WasLastStatePowered;
|
|
||||||
m_SimulatedPlayerToggleableBlocks->emplace_back(RC);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cIncrementalRedstoneSimulator::QueueRepeaterPowerChange(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, NIBBLETYPE a_Meta, bool ShouldPowerOn)
|
void cIncrementalRedstoneSimulator::QueueRepeaterPowerChange(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, NIBBLETYPE a_Meta, bool a_ShouldPowerOn)
|
||||||
{
|
{
|
||||||
for (auto itr = m_RepeatersDelayList->begin(); itr != m_RepeatersDelayList->end(); ++itr)
|
|
||||||
{
|
|
||||||
if (itr->a_RelBlockPos.Equals(Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ)))
|
|
||||||
{
|
|
||||||
if (ShouldPowerOn == itr->ShouldPowerOn) // We are queued already for the same thing, don't replace entry
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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_ElapsedTicks = 0;
|
|
||||||
itr->ShouldPowerOn = ShouldPowerOn;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Self not in list, add self to list
|
|
||||||
sRepeatersDelayList RC;
|
sRepeatersDelayList RC;
|
||||||
RC.a_RelBlockPos = Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ);
|
|
||||||
|
|
||||||
// Gets the top two bits (delay time), shifts them into the lower two bits, and adds one (meta 0 = 1 tick; 1 = 2 etc.)
|
// Gets the top two bits (delay time), shifts them into the lower two bits, and adds one (meta 0 = 1 tick; 1 = 2 etc.)
|
||||||
// Multiply by 2 because in MCS, 1 redstone tick = 1 world tick, but in Vanilla, 1 redstone tick = 2 world ticks, and we need to maintain compatibility
|
// Multiply by 2 because in MCS, 1 redstone tick = 1 world tick, but in Vanilla, 1 redstone tick = 2 world ticks, and we need to maintain compatibility
|
||||||
RC.a_DelayTicks = (((a_Meta & 0xC) >> 0x2) + 1) * 2;
|
RC.a_DelayTicks = (((a_Meta & 0xC) >> 0x2) + 1) * 2;
|
||||||
|
|
||||||
RC.a_ElapsedTicks = 0;
|
RC.a_ElapsedTicks = 0;
|
||||||
RC.ShouldPowerOn = ShouldPowerOn;
|
RC.ShouldPowerOn = a_ShouldPowerOn;
|
||||||
m_RepeatersDelayList->emplace_back(RC);
|
|
||||||
return true;
|
auto Result = m_RepeatersDelayList->emplace(Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ), RC);
|
||||||
|
if (!Result.second)
|
||||||
|
{
|
||||||
|
// Key exists
|
||||||
|
if (a_ShouldPowerOn == Result.first->second.ShouldPowerOn)
|
||||||
|
{
|
||||||
|
// We are queued already for the same thing, don't replace entry
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result.first->second.a_DelayTicks = RC.a_DelayTicks;
|
||||||
|
Result.first->second.a_ElapsedTicks = 0;
|
||||||
|
Result.first->second.ShouldPowerOn = a_ShouldPowerOn;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
#include "RedstoneSimulator.h"
|
#include "RedstoneSimulator.h"
|
||||||
#include "BlockEntities/RedstonePoweredEntity.h"
|
#include "BlockEntities/RedstonePoweredEntity.h"
|
||||||
#include <bitset>
|
#include <unordered_map>
|
||||||
|
|
||||||
class cWorld;
|
class cWorld;
|
||||||
class cChunk;
|
class cChunk;
|
||||||
@ -38,15 +38,6 @@ public:
|
|||||||
virtual bool IsAllowedBlock(BLOCKTYPE a_BlockType) override { return IsRedstone(a_BlockType); }
|
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;
|
virtual void WakeUp(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk) override;
|
||||||
|
|
||||||
enum eRedstoneWireDirectionBitfieldPositions
|
|
||||||
{
|
|
||||||
eWbpXP = 0,
|
|
||||||
eWbpXN = 1,
|
|
||||||
eWbpZP = 2,
|
|
||||||
eWbpZN = 3,
|
|
||||||
};
|
|
||||||
std::bitset<4> GetWireDirection(int a_BlockX, int a_BlockY, int a_BlockZ);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
#define MAX_POWER_LEVEL 15
|
#define MAX_POWER_LEVEL 15
|
||||||
@ -66,15 +57,8 @@ private:
|
|||||||
unsigned char a_PowerLevel;
|
unsigned char a_PowerLevel;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sSimulatedPlayerToggleableList // Define structure of the list containing simulate-on-update blocks (such as trapdoors that respond once to a block update, and can be toggled by a player)
|
|
||||||
{
|
|
||||||
Vector3i a_RelBlockPos;
|
|
||||||
bool WasLastStatePowered; // Was the last state powered or not? Determines whether a source update has happened and if I should resimulate
|
|
||||||
};
|
|
||||||
|
|
||||||
struct sRepeatersDelayList // Define structure of list containing repeaters' delay states
|
struct sRepeatersDelayList // Define structure of list containing repeaters' delay states
|
||||||
{
|
{
|
||||||
Vector3i a_RelBlockPos;
|
|
||||||
unsigned char a_DelayTicks; // For how many ticks should the repeater delay
|
unsigned char a_DelayTicks; // For how many ticks should the repeater delay
|
||||||
unsigned char a_ElapsedTicks; // How much of the previous has been elapsed?
|
unsigned char a_ElapsedTicks; // How much of the previous has been elapsed?
|
||||||
bool ShouldPowerOn; // What happens when the delay time is fulfilled?
|
bool ShouldPowerOn; // What happens when the delay time is fulfilled?
|
||||||
@ -85,20 +69,19 @@ private:
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/// Per-chunk data for the simulator, specified individual chunks to simulate
|
/// Per-chunk data for the simulator, specified individual chunks to simulate
|
||||||
cCoordWithBlockAndBoolVector m_ChunkData;
|
std::unordered_map<Vector3i, std::pair<BLOCKTYPE, bool>, Vector3i> m_ChunkData;
|
||||||
cCoordWithBlockAndBoolVector m_QueuedChunkData;
|
|
||||||
std::vector<sPoweredBlocks> m_PoweredBlocks;
|
std::vector<sPoweredBlocks> m_PoweredBlocks;
|
||||||
std::vector<sLinkedPoweredBlocks> m_LinkedBlocks;
|
std::vector<sLinkedPoweredBlocks> m_LinkedBlocks;
|
||||||
std::vector<sSimulatedPlayerToggleableList> m_SimulatedPlayerToggleableBlocks;
|
std::unordered_map<Vector3i, bool, Vector3i> m_SimulatedPlayerToggleableBlocks;
|
||||||
std::vector<sRepeatersDelayList> m_RepeatersDelayList;
|
std::unordered_map<Vector3i, sRepeatersDelayList, Vector3i> m_RepeatersDelayList;
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
typedef std::vector <sPoweredBlocks> PoweredBlocksList;
|
typedef std::vector <sPoweredBlocks> PoweredBlocksList;
|
||||||
typedef std::vector <sLinkedPoweredBlocks> LinkedBlocksList;
|
typedef std::vector <sLinkedPoweredBlocks> LinkedBlocksList;
|
||||||
typedef std::vector <sSimulatedPlayerToggleableList> SimulatedPlayerToggleableList;
|
typedef std::unordered_map<Vector3i, bool, Vector3i> SimulatedPlayerToggleableList;
|
||||||
typedef std::vector <sRepeatersDelayList> RepeatersDelayList;
|
typedef std::unordered_map<Vector3i, sRepeatersDelayList, Vector3i> RepeatersDelayList;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@ -211,7 +194,7 @@ private:
|
|||||||
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 and returns if the m_RepeatersDelayList iterators were invalidated */
|
/** Queues a repeater to be powered or unpowered and returns if the m_RepeatersDelayList iterators were invalidated */
|
||||||
bool QueueRepeaterPowerChange(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, NIBBLETYPE a_Meta, bool ShouldPowerOn);
|
void QueueRepeaterPowerChange(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, NIBBLETYPE a_Meta, bool ShouldPowerOn);
|
||||||
|
|
||||||
/** Removes a block from the Powered and LinkedPowered lists
|
/** Removes a block from the Powered and LinkedPowered lists
|
||||||
Recursively removes all blocks powered by the given one
|
Recursively removes all blocks powered by the given one
|
||||||
|
@ -235,6 +235,12 @@ public:
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Provides a hash of a vector's contents */
|
||||||
|
size_t operator()(const Vector3<T> & a_Vector) const
|
||||||
|
{
|
||||||
|
return ((std::hash<T>()(a_Vector.x) ^ (std::hash<T>()(a_Vector.y) << 1)) ^ std::hash<T>()(a_Vector.z));
|
||||||
|
}
|
||||||
|
|
||||||
// tolua_begin
|
// tolua_begin
|
||||||
|
|
||||||
inline Vector3<T> operator + (const Vector3<T>& a_Rhs) const
|
inline Vector3<T> operator + (const Vector3<T>& a_Rhs) const
|
||||||
|
Loading…
Reference in New Issue
Block a user