Implemented weighted pressure plates

This commit is contained in:
Tiger Wang 2014-04-17 12:11:31 +01:00
parent 82b3d543e7
commit 2151ee997c
3 changed files with 177 additions and 31 deletions

View File

@ -504,6 +504,10 @@ enum
E_META_PLANKS_BIRCH = 2, E_META_PLANKS_BIRCH = 2,
E_META_PLANKS_JUNGLE = 3, E_META_PLANKS_JUNGLE = 3,
// E_BLOCK_(XXX_WEIGHTED)_PRESSURE_PLATE metas:
E_META_PRESSURE_PLATE_RAISED = 0,
E_META_PRESSURE_PLATE_DEPRESSED = 1,
// E_BLOCK_QUARTZ_BLOCK metas: // E_BLOCK_QUARTZ_BLOCK metas:
E_META_QUARTZ_NORMAL = 0, E_META_QUARTZ_NORMAL = 0,
E_META_QUARTZ_CHISELLED = 1, E_META_QUARTZ_CHISELLED = 1,

View File

@ -537,13 +537,14 @@ void cIncrementalRedstoneSimulator::HandleRedstoneWire(int a_BlockX, int a_Block
unsigned char MyPower; unsigned char MyPower;
if (!IsWirePowered(a_BlockX, a_BlockY, a_BlockZ, MyPower)) if (!IsWirePowered(a_BlockX, a_BlockY, a_BlockZ, MyPower))
{ {
m_World.SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_WIRE, 0); m_World.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, 0);
m_World.WakeUpSimulators(a_BlockX, a_BlockY, a_BlockZ);
return; return;
} }
m_World.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, MyPower); // Maximum power m_World.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, MyPower);
if (MyPower < 2) if (MyPower < 1)
{ {
return; return;
} }
@ -1015,16 +1016,13 @@ void cIncrementalRedstoneSimulator::HandlePressurePlate(int a_BlockX, int a_Bloc
break; break;
} }
case E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE: case E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE:
case E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE:
case E_BLOCK_WOODEN_PRESSURE_PLATE:
{ {
class cPressurePlateCallback : class cPressurePlateCallback :
public cEntityCallback public cEntityCallback
{ {
public: public:
cPressurePlateCallback(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World) : cPressurePlateCallback(int a_BlockX, int a_BlockY, int a_BlockZ) :
m_Entity(NULL), m_NumberOfEntities(0),
m_World(a_World),
m_X(a_BlockX), m_X(a_BlockX),
m_Y(a_BlockY), m_Y(a_BlockY),
m_Z(a_BlockZ) m_Z(a_BlockZ)
@ -1039,7 +1037,140 @@ void cIncrementalRedstoneSimulator::HandlePressurePlate(int a_BlockX, int a_Bloc
if (Distance <= 0.7) if (Distance <= 0.7)
{ {
m_Entity = a_Entity; m_NumberOfEntities++;
}
return false;
}
bool GetPowerLevel(unsigned char & a_PowerLevel) const
{
a_PowerLevel = std::min(m_NumberOfEntities, MAX_POWER_LEVEL);
return (a_PowerLevel > 0);
}
protected:
int m_NumberOfEntities;
int m_X;
int m_Y;
int m_Z;
};
cPressurePlateCallback PressurePlateCallback(a_BlockX, a_BlockY, a_BlockZ);
m_World.ForEachEntity(PressurePlateCallback);
unsigned char Power;
NIBBLETYPE Meta = m_World.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ);
if (PressurePlateCallback.GetPowerLevel(Power))
{
if (Meta == E_META_PRESSURE_PLATE_RAISED)
{
m_World.BroadcastSoundEffect("random.click", (int)((a_BlockX + 0.5) * 8.0), (int)((a_BlockY + 0.1) * 8.0), (int)((a_BlockZ + 0.5) * 8.0), 0.3F, 0.5F);
}
m_World.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, E_META_PRESSURE_PLATE_DEPRESSED);
SetAllDirsAsPowered(a_BlockX, a_BlockY, a_BlockZ, a_MyType, Power);
}
else
{
if (Meta == E_META_PRESSURE_PLATE_DEPRESSED)
{
m_World.BroadcastSoundEffect("random.click", (int)((a_BlockX + 0.5) * 8.0), (int)((a_BlockY + 0.1) * 8.0), (int)((a_BlockZ + 0.5) * 8.0), 0.3F, 0.6F);
}
m_World.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, E_META_PRESSURE_PLATE_RAISED);
m_World.WakeUpSimulators(a_BlockX, a_BlockY, a_BlockZ);
}
break;
}
case E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE:
{class cPressurePlateCallback :
public cEntityCallback
{
public:
cPressurePlateCallback(int a_BlockX, int a_BlockY, int a_BlockZ) :
m_NumberOfEntities(0),
m_X(a_BlockX),
m_Y(a_BlockY),
m_Z(a_BlockZ)
{
}
virtual bool Item(cEntity * a_Entity) override
{
Vector3f EntityPos = a_Entity->GetPosition();
Vector3f BlockPos(m_X + 0.5f, (float)m_Y, m_Z + 0.5f);
double Distance = (EntityPos - BlockPos).Length();
if (Distance <= 0.7)
{
m_NumberOfEntities++;
}
return false;
}
bool GetPowerLevel(unsigned char & a_PowerLevel) const
{
a_PowerLevel = std::min((int)ceil(m_NumberOfEntities / (float)10), MAX_POWER_LEVEL);
return (a_PowerLevel > 0);
}
protected:
int m_NumberOfEntities;
int m_X;
int m_Y;
int m_Z;
};
cPressurePlateCallback PressurePlateCallback(a_BlockX, a_BlockY, a_BlockZ);
m_World.ForEachEntity(PressurePlateCallback);
unsigned char Power;
NIBBLETYPE Meta = m_World.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ);
if (PressurePlateCallback.GetPowerLevel(Power))
{
if (Meta == E_META_PRESSURE_PLATE_RAISED)
{
m_World.BroadcastSoundEffect("random.click", (int)((a_BlockX + 0.5) * 8.0), (int)((a_BlockY + 0.1) * 8.0), (int)((a_BlockZ + 0.5) * 8.0), 0.3F, 0.5F);
}
m_World.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, E_META_PRESSURE_PLATE_DEPRESSED);
SetAllDirsAsPowered(a_BlockX, a_BlockY, a_BlockZ, a_MyType, Power);
}
else
{
if (Meta == E_META_PRESSURE_PLATE_DEPRESSED)
{
m_World.BroadcastSoundEffect("random.click", (int)((a_BlockX + 0.5) * 8.0), (int)((a_BlockY + 0.1) * 8.0), (int)((a_BlockZ + 0.5) * 8.0), 0.3F, 0.6F);
}
m_World.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, E_META_PRESSURE_PLATE_RAISED);
m_World.WakeUpSimulators(a_BlockX, a_BlockY, a_BlockZ);
}
break;
}
case E_BLOCK_WOODEN_PRESSURE_PLATE:
{
class cPressurePlateCallback :
public cEntityCallback
{
public:
cPressurePlateCallback(int a_BlockX, int a_BlockY, int a_BlockZ) :
m_FoundEntity(false),
m_X(a_BlockX),
m_Y(a_BlockY),
m_Z(a_BlockZ)
{
}
virtual bool Item(cEntity * a_Entity) override
{
Vector3f EntityPos = a_Entity->GetPosition();
Vector3f BlockPos(m_X + 0.5f, (float)m_Y, m_Z + 0.5f);
double Distance = (EntityPos - BlockPos).Length();
if (Distance <= 0.7)
{
m_FoundEntity = true;
return true; // Break out, we only need to know for plates that at least one entity is on top return true; // Break out, we only need to know for plates that at least one entity is on top
} }
return false; return false;
@ -1047,45 +1178,46 @@ void cIncrementalRedstoneSimulator::HandlePressurePlate(int a_BlockX, int a_Bloc
bool FoundEntity(void) const bool FoundEntity(void) const
{ {
return m_Entity != NULL; return m_FoundEntity;
} }
protected: protected:
cEntity * m_Entity; bool m_FoundEntity;
cWorld * m_World;
int m_X; int m_X;
int m_Y; int m_Y;
int m_Z; int m_Z;
} ; } ;
cPressurePlateCallback PressurePlateCallback(a_BlockX, a_BlockY, a_BlockZ, &m_World); cPressurePlateCallback PressurePlateCallback(a_BlockX, a_BlockY, a_BlockZ);
m_World.ForEachEntity(PressurePlateCallback); m_World.ForEachEntity(PressurePlateCallback);
NIBBLETYPE Meta = m_World.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ); NIBBLETYPE Meta = m_World.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ);
if (PressurePlateCallback.FoundEntity()) if (PressurePlateCallback.FoundEntity())
{ {
if (Meta == 0x0) if (Meta == E_META_PRESSURE_PLATE_RAISED)
{ {
m_World.BroadcastSoundEffect("random.click", (int) ((a_BlockX + 0.5) * 8.0), (int) ((a_BlockY + 0.1) * 8.0), (int) ((a_BlockZ + 0.5) * 8.0), 0.3F, 0.5F); m_World.BroadcastSoundEffect("random.click", (int) ((a_BlockX + 0.5) * 8.0), (int) ((a_BlockY + 0.1) * 8.0), (int) ((a_BlockZ + 0.5) * 8.0), 0.3F, 0.5F);
} }
m_World.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, 0x1); m_World.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, E_META_PRESSURE_PLATE_DEPRESSED);
SetAllDirsAsPowered(a_BlockX, a_BlockY, a_BlockZ, a_MyType); SetAllDirsAsPowered(a_BlockX, a_BlockY, a_BlockZ, a_MyType);
} }
else else
{ {
if (Meta == 0x1) if (Meta == E_META_PRESSURE_PLATE_DEPRESSED)
{ {
m_World.BroadcastSoundEffect("random.click", (int) ((a_BlockX + 0.5) * 8.0), (int) ((a_BlockY + 0.1) * 8.0), (int) ((a_BlockZ + 0.5) * 8.0), 0.3F, 0.6F); m_World.BroadcastSoundEffect("random.click", (int) ((a_BlockX + 0.5) * 8.0), (int) ((a_BlockY + 0.1) * 8.0), (int) ((a_BlockZ + 0.5) * 8.0), 0.3F, 0.6F);
} }
m_World.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, 0x0); m_World.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, E_META_PRESSURE_PLATE_RAISED);
m_World.WakeUpSimulators(a_BlockX, a_BlockY, a_BlockZ); m_World.WakeUpSimulators(a_BlockX, a_BlockY, a_BlockZ);
} }
break; break;
} }
default: default:
{
LOGD("Unimplemented pressure plate type %s in cRedstoneSimulator", ItemToFullString(a_MyType).c_str()); LOGD("Unimplemented pressure plate type %s in cRedstoneSimulator", ItemToFullString(a_MyType).c_str());
break; break;
}
} }
} }
@ -1426,7 +1558,7 @@ void cIncrementalRedstoneSimulator::SetDirectionLinkedPowered(int a_BlockX, int
void cIncrementalRedstoneSimulator::SetAllDirsAsPowered(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_SourceBlock) void cIncrementalRedstoneSimulator::SetAllDirsAsPowered(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_SourceBlock, unsigned char a_PowerLevel)
{ {
static const struct static const struct
{ {
@ -1443,7 +1575,7 @@ void cIncrementalRedstoneSimulator::SetAllDirsAsPowered(int a_BlockX, int a_Bloc
for (size_t i = 0; i < ARRAYCOUNT(gCrossCoords); i++) // Loop through struct to power all directions for (size_t i = 0; i < ARRAYCOUNT(gCrossCoords); i++) // Loop through struct to power all directions
{ {
SetBlockPowered(a_BlockX + gCrossCoords[i].x, a_BlockY + gCrossCoords[i].y, a_BlockZ + gCrossCoords[i].z, a_BlockX, a_BlockY, a_BlockZ, a_SourceBlock); SetBlockPowered(a_BlockX + gCrossCoords[i].x, a_BlockY + gCrossCoords[i].y, a_BlockZ + gCrossCoords[i].z, a_BlockX, a_BlockY, a_BlockZ, a_SourceBlock, a_PowerLevel);
} }
} }
@ -1460,21 +1592,25 @@ void cIncrementalRedstoneSimulator::SetBlockPowered(int a_BlockX, int a_BlockY,
return; return;
} }
PoweredBlocksList * Powered = m_Chunk->GetNeighborChunk(a_BlockX, a_BlockZ)->GetRedstoneSimulatorPoweredBlocksList(); auto Powered = m_Chunk->GetNeighborChunk(a_BlockX, a_BlockZ)->GetRedstoneSimulatorPoweredBlocksList();
for (PoweredBlocksList::const_iterator itr = Powered->begin(); itr != Powered->end(); ++itr) // Check powered list for (auto itr = Powered->begin(); itr != Powered->end(); ++itr) // Check powered list
{ {
if ( if (
itr->a_BlockPos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ)) && itr->a_BlockPos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ)) &&
itr->a_SourcePos.Equals(Vector3i(a_SourceX, a_SourceY, a_SourceZ)) itr->a_SourcePos.Equals(Vector3i(a_SourceX, a_SourceY, a_SourceZ))
) )
{ {
// Check for duplicates // Check for duplicates, update power level if everything else the same but either way, don't add a new listing
if (itr->a_PowerLevel != a_PowerLevel)
{
itr->a_PowerLevel = a_PowerLevel;
}
return; return;
} }
} }
PoweredBlocksList * OtherPowered = m_Chunk->GetNeighborChunk(a_SourceX, a_SourceZ)->GetRedstoneSimulatorPoweredBlocksList(); auto OtherPowered = m_Chunk->GetNeighborChunk(a_SourceX, a_SourceZ)->GetRedstoneSimulatorPoweredBlocksList();
for (PoweredBlocksList::const_iterator itr = OtherPowered->begin(); itr != OtherPowered->end(); ++itr) // Check powered list for (auto itr = OtherPowered->cbegin(); itr != OtherPowered->cend(); ++itr) // Check powered list
{ {
if ( if (
itr->a_BlockPos.Equals(Vector3i(a_SourceX, a_SourceY, a_SourceZ)) && itr->a_BlockPos.Equals(Vector3i(a_SourceX, a_SourceY, a_SourceZ)) &&
@ -1515,8 +1651,8 @@ void cIncrementalRedstoneSimulator::SetBlockLinkedPowered(
return; return;
} }
LinkedBlocksList * Linked = m_Chunk->GetNeighborChunk(a_BlockX, a_BlockZ)->GetRedstoneSimulatorLinkedBlocksList(); auto Linked = m_Chunk->GetNeighborChunk(a_BlockX, a_BlockZ)->GetRedstoneSimulatorLinkedBlocksList();
for (LinkedBlocksList::const_iterator itr = Linked->begin(); itr != Linked->end(); ++itr) // Check linked powered list for (auto itr = Linked->begin(); itr != Linked->end(); ++itr) // Check linked powered list
{ {
if ( if (
itr->a_BlockPos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ)) && itr->a_BlockPos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ)) &&
@ -1524,7 +1660,11 @@ void cIncrementalRedstoneSimulator::SetBlockLinkedPowered(
itr->a_SourcePos.Equals(Vector3i(a_SourceX, a_SourceY, a_SourceZ)) itr->a_SourcePos.Equals(Vector3i(a_SourceX, a_SourceY, a_SourceZ))
) )
{ {
// Check for duplicates // Check for duplicates, update power level if everything else the same but either way, don't add a new listing
if (itr->a_PowerLevel != a_PowerLevel)
{
itr->a_PowerLevel = a_PowerLevel;
}
return; return;
} }
} }

View File

@ -36,6 +36,8 @@ public:
private: private:
#define MAX_POWER_LEVEL 15
struct sPoweredBlocks // Define structure of the directly powered blocks list struct sPoweredBlocks // Define structure of the directly powered blocks list
{ {
Vector3i a_BlockPos; // Position of powered block Vector3i a_BlockPos; // Position of powered block
@ -134,15 +136,15 @@ private:
/* ====== Helper functions ====== */ /* ====== Helper functions ====== */
/** Marks a block as powered */ /** Marks a block as powered */
void SetBlockPowered(int a_BlockX, int a_BlockY, int a_BlockZ, int a_SourceX, int a_SourceY, int a_SourceZ, BLOCKTYPE a_SourceBlock, unsigned char a_PowerLevel = 15); void SetBlockPowered(int a_BlockX, int a_BlockY, int a_BlockZ, int a_SourceX, int a_SourceY, int a_SourceZ, BLOCKTYPE a_SourceBlock, unsigned char a_PowerLevel = MAX_POWER_LEVEL);
/** Marks a block as being powered through another block */ /** Marks a block as being powered through another block */
void SetBlockLinkedPowered(int a_BlockX, int a_BlockY, int a_BlockZ, int a_MiddleX, int a_MiddleY, int a_MiddleZ, int a_SourceX, int a_SourceY, int a_SourceZ, BLOCKTYPE a_SourceBlock, BLOCKTYPE a_MiddeBlock, unsigned char a_PowerLevel = 15); void SetBlockLinkedPowered(int a_BlockX, int a_BlockY, int a_BlockZ, int a_MiddleX, int a_MiddleY, int a_MiddleZ, int a_SourceX, int a_SourceY, int a_SourceZ, BLOCKTYPE a_SourceBlock, BLOCKTYPE a_MiddeBlock, unsigned char a_PowerLevel = MAX_POWER_LEVEL);
/** Marks a block as simulated, who should not be simulated further unless their power state changes, to accomodate a player manually toggling the block without triggering the simulator toggling it back */ /** Marks a block as simulated, who should not be simulated further unless their power state changes, to accomodate a player manually toggling the block without triggering the simulator toggling it back */
void SetPlayerToggleableBlockAsSimulated(int a_BlockX, int a_BlockY, int a_BlockZ, bool WasLastStatePowered); void SetPlayerToggleableBlockAsSimulated(int a_BlockX, int a_BlockY, int a_BlockZ, bool WasLastStatePowered);
/** Marks the second block in a direction as linked powered */ /** Marks the second block in a direction as linked powered */
void SetDirectionLinkedPowered(int a_BlockX, int a_BlockY, int a_BlockZ, char a_Direction, BLOCKTYPE a_SourceBlock, unsigned char a_PowerLevel = 15); void SetDirectionLinkedPowered(int a_BlockX, int a_BlockY, int a_BlockZ, char a_Direction, BLOCKTYPE a_SourceBlock, 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_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_SourceBlock); void SetAllDirsAsPowered(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_SourceBlock, unsigned char a_PowerLevel = MAX_POWER_LEVEL);
/** Queues a repeater to be powered or unpowered */ /** Queues a repeater to be powered or unpowered */
void QueueRepeaterPowerChange(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_Meta, bool ShouldPowerOn); void QueueRepeaterPowerChange(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_Meta, bool ShouldPowerOn);