1
0

Changed appropriate containers to unordered_map

Thanks to @worktycho for guidance!

* Potential speed improvements
This commit is contained in:
Tiger Wang 2015-06-02 13:29:52 +01:00
parent 6a831c0b6f
commit 171c59a01b
5 changed files with 93 additions and 204 deletions

View File

@ -514,32 +514,3 @@ typedef cCoordWithData<BLOCKTYPE> cCoordWithBlock;
typedef std::list<cCoordWithInt> cCoordWithIntList;
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;

View File

@ -124,21 +124,6 @@ public:
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:
/* General */
@ -160,7 +145,7 @@ private:
/* Pathfinding fields */
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_Source;
int m_BoundingBoxWidth;

View File

@ -92,67 +92,45 @@ void cIncrementalRedstoneSimulator::AddBlock(const Vector3i & a_RelBlockPosition
}
auto & SimulatedPlayerToggleableBlocks = static_cast<cIncrementalRedstoneSimulatorChunkData *>(a_OriginalChunk->GetRedstoneSimulatorData())->m_SimulatedPlayerToggleableBlocks;
if (
DoesIgnorePlayerToggle(Block) &&
std::find_if(SimulatedPlayerToggleableBlocks.begin(), SimulatedPlayerToggleableBlocks.end(),
[a_RelBlockPosition](const sSimulatedPlayerToggleableList & itr){ return itr.a_RelBlockPos == a_RelBlockPosition; }) == SimulatedPlayerToggleableBlocks.end()
)
if (DoesIgnorePlayerToggle(Block))
{
// 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)
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)
{
return (itr.a_RelBlockPos == a_RelBlockPosition) && !DoesIgnorePlayerToggle(Block);
}
), 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());
if ((Block != E_BLOCK_REDSTONE_REPEATER_ON) && (Block != E_BLOCK_REDSTONE_REPEATER_OFF))
{
static_cast<cIncrementalRedstoneSimulatorChunkData *>(a_OriginalChunk->GetRedstoneSimulatorData())->m_RepeatersDelayList.erase(a_RelBlockPosition);
}
auto & RedstoneSimulatorChunkData = static_cast<cIncrementalRedstoneSimulatorChunkData *>(a_OriginalChunk->GetRedstoneSimulatorData())->m_ChunkData;
for (auto & itr : RedstoneSimulatorChunkData)
{
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;
}
}
auto Iterator = RedstoneSimulatorChunkData.find(a_RelBlockPosition);
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;
}
auto & QueuedData = static_cast<cIncrementalRedstoneSimulatorChunkData *>(a_OriginalChunk->GetRedstoneSimulatorData())->m_QueuedChunkData;
for (const auto & itr : QueuedData)
else
{
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;
}
}
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();
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;
}
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_RepeatersDelayList = &m_RedstoneSimulatorChunkData->m_RepeatersDelayList;
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();)
{
if (dataitr->DataTwo)
if (dataitr->second.second)
{
dataitr = m_RedstoneSimulatorChunkData->m_ChunkData.erase(dataitr);
continue;
}
switch (dataitr->Data)
switch (dataitr->second.first)
{
case E_BLOCK_DAYLIGHT_SENSOR: HandleDaylightSensor(dataitr->x, dataitr->y, dataitr->z); break;
case E_BLOCK_TRIPWIRE: HandleTripwire(dataitr->x, dataitr->y, dataitr->z); break;
case E_BLOCK_TRIPWIRE_HOOK: HandleTripwireHook(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->first.x, dataitr->first.y, dataitr->first.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_STONE_PRESSURE_PLATE:
case E_BLOCK_LIGHT_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;
}
default: break;
@ -224,23 +194,23 @@ void cIncrementalRedstoneSimulator::SimulateChunk(std::chrono::milliseconds a_Dt
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_COMMAND_BLOCK: HandleCommandBlock(dataitr->x, dataitr->y, dataitr->z); break;
case E_BLOCK_NOTE_BLOCK: HandleNoteBlock(dataitr->x, dataitr->y, dataitr->z); break;
case E_BLOCK_BLOCK_OF_REDSTONE: HandleRedstoneBlock(dataitr->x, dataitr->y, dataitr->z); break;
case E_BLOCK_LEVER: HandleRedstoneLever(dataitr->x, dataitr->y, dataitr->z); break;
case E_BLOCK_TNT: HandleTNT(dataitr->x, dataitr->y, dataitr->z); break;
case E_BLOCK_IRON_TRAPDOOR: HandleTrapdoor(dataitr->x, dataitr->y, dataitr->z); break;
case E_BLOCK_TRAPDOOR: HandleTrapdoor(dataitr->x, dataitr->y, dataitr->z); break;
case E_BLOCK_TRAPPED_CHEST: HandleTrappedChest(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->first.x, dataitr->first.y, dataitr->first.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->first.x, dataitr->first.y, dataitr->first.z); break;
case E_BLOCK_LEVER: HandleRedstoneLever(dataitr->first.x, dataitr->first.y, dataitr->first.z); break;
case E_BLOCK_TNT: HandleTNT(dataitr->first.x, dataitr->first.y, dataitr->first.z); break;
case E_BLOCK_IRON_TRAPDOOR: HandleTrapdoor(dataitr->first.x, dataitr->first.y, dataitr->first.z); break;
case E_BLOCK_TRAPDOOR: HandleTrapdoor(dataitr->first.x, dataitr->first.y, dataitr->first.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_DETECTOR_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;
}
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_IRON_DOOR:
{
HandleDoor(dataitr->x, dataitr->y, dataitr->z);
HandleDoor(dataitr->first.x, dataitr->first.y, dataitr->first.z);
break;
}
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_SPRUCE_FENCE_GATE:
{
HandleFenceGate(dataitr->x, dataitr->y, dataitr->z);
HandleFenceGate(dataitr->first.x, dataitr->first.y, dataitr->first.z);
break;
}
case E_BLOCK_REDSTONE_LAMP_OFF:
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;
}
case E_BLOCK_DISPENSER:
case E_BLOCK_DROPPER:
{
HandleDropSpenser(dataitr->x, dataitr->y, dataitr->z);
HandleDropSpenser(dataitr->first.x, dataitr->first.y, dataitr->first.z);
break;
}
case E_BLOCK_PISTON:
case E_BLOCK_STICKY_PISTON:
{
HandlePiston(dataitr->x, dataitr->y, dataitr->z);
HandlePiston(dataitr->first.x, dataitr->first.y, dataitr->first.z);
break;
}
case E_BLOCK_REDSTONE_REPEATER_OFF:
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;
}
case E_BLOCK_REDSTONE_TORCH_OFF:
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;
}
case E_BLOCK_STONE_BUTTON:
case E_BLOCK_WOODEN_BUTTON:
{
HandleRedstoneButton(dataitr->x, dataitr->y, dataitr->z);
HandleRedstoneButton(dataitr->first.x, dataitr->first.y, dataitr->first.z);
break;
}
case E_BLOCK_ACTIVE_COMPARATOR:
case E_BLOCK_INACTIVE_COMPARATOR:
{
HandleRedstoneComparator(dataitr->x, dataitr->y, dataitr->z);
HandleRedstoneComparator(dataitr->first.x, dataitr->first.y, dataitr->first.z);
break;
}
default: break;
@ -872,32 +842,29 @@ void cIncrementalRedstoneSimulator::HandleRedstoneRepeaterDelays()
{
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;
NIBBLETYPE Meta;
m_Chunk->GetBlockTypeMeta(RelBlockX, RelBlockY, RelBlockZ, Block, Meta);
if (itr->ShouldPowerOn)
m_Chunk->GetBlockTypeMeta(itr->first.x, itr->first.y, itr->first.z, Block, Meta);
if (itr->second.ShouldPowerOn)
{
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)
{
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);
}
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);
itr->a_ElapsedTicks++;
itr++;
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->second.a_ElapsedTicks++;
++itr;
}
}
}
@ -1871,9 +1838,9 @@ bool cIncrementalRedstoneSimulator::AreCoordsSimulated(int a_RelBlockX, int a_Re
{
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
}
@ -2116,60 +2083,37 @@ void cIncrementalRedstoneSimulator::SetBlockLinkedPowered(
void cIncrementalRedstoneSimulator::SetPlayerToggleableBlockAsSimulated(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, bool a_WasLastStatePowered)
{
for (auto & itr : *m_SimulatedPlayerToggleableBlocks)
{
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);
m_SimulatedPlayerToggleableBlocks->operator[](Vector3i(a_RelBlockX, a_RelBlockY, a_RelBlockZ)) = a_WasLastStatePowered;
}
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;
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.)
// 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_ElapsedTicks = 0;
RC.ShouldPowerOn = ShouldPowerOn;
m_RepeatersDelayList->emplace_back(RC);
return true;
RC.ShouldPowerOn = a_ShouldPowerOn;
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;
}
}

View File

@ -3,7 +3,7 @@
#include "RedstoneSimulator.h"
#include "BlockEntities/RedstonePoweredEntity.h"
#include <bitset>
#include <unordered_map>
class cWorld;
class cChunk;
@ -38,15 +38,6 @@ public:
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 eRedstoneWireDirectionBitfieldPositions
{
eWbpXP = 0,
eWbpXN = 1,
eWbpZP = 2,
eWbpZN = 3,
};
std::bitset<4> GetWireDirection(int a_BlockX, int a_BlockY, int a_BlockZ);
private:
#define MAX_POWER_LEVEL 15
@ -66,15 +57,8 @@ private:
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
{
Vector3i a_RelBlockPos;
unsigned char a_DelayTicks; // For how many ticks should the repeater delay
unsigned char a_ElapsedTicks; // How much of the previous has been elapsed?
bool ShouldPowerOn; // What happens when the delay time is fulfilled?
@ -85,20 +69,19 @@ private:
{
public:
/// Per-chunk data for the simulator, specified individual chunks to simulate
cCoordWithBlockAndBoolVector m_ChunkData;
cCoordWithBlockAndBoolVector m_QueuedChunkData;
std::unordered_map<Vector3i, std::pair<BLOCKTYPE, bool>, Vector3i> m_ChunkData;
std::vector<sPoweredBlocks> m_PoweredBlocks;
std::vector<sLinkedPoweredBlocks> m_LinkedBlocks;
std::vector<sSimulatedPlayerToggleableList> m_SimulatedPlayerToggleableBlocks;
std::vector<sRepeatersDelayList> m_RepeatersDelayList;
std::unordered_map<Vector3i, bool, Vector3i> m_SimulatedPlayerToggleableBlocks;
std::unordered_map<Vector3i, sRepeatersDelayList, Vector3i> m_RepeatersDelayList;
};
public:
typedef std::vector <sPoweredBlocks> PoweredBlocksList;
typedef std::vector <sLinkedPoweredBlocks> LinkedBlocksList;
typedef std::vector <sSimulatedPlayerToggleableList> SimulatedPlayerToggleableList;
typedef std::vector <sRepeatersDelayList> RepeatersDelayList;
typedef std::unordered_map<Vector3i, bool, Vector3i> SimulatedPlayerToggleableList;
typedef std::unordered_map<Vector3i, sRepeatersDelayList, Vector3i> RepeatersDelayList;
private:
@ -211,7 +194,7 @@ private:
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 */
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
Recursively removes all blocks powered by the given one

View File

@ -235,6 +235,12 @@ public:
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
inline Vector3<T> operator + (const Vector3<T>& a_Rhs) const