1
0

Merge branch 'master' into Enchanting

This commit is contained in:
daniel0916 2014-04-18 15:04:32 +02:00
commit b239de66db
29 changed files with 1513 additions and 432 deletions

View File

@ -46,6 +46,10 @@ macro(set_flags)
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -std=c++11") set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -std=c++11")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -std=c++11") set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -std=c++11")
else() else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -std=c++0x")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -std=c++0x")
add_flags_cxx("-pthread") add_flags_cxx("-pthread")
endif() endif()
@ -56,6 +60,10 @@ macro(set_flags)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -std=c++11") set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -std=c++11")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -std=c++11") set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -std=c++11")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -std=c++0x")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -std=c++0x")
endif() endif()
# We use a signed char (fixes #640 on RasPi) # We use a signed char (fixes #640 on RasPi)

View File

@ -154,7 +154,7 @@ bool cIniFile::ReadFile(const AString & a_FileName, bool a_AllowExampleRedirect)
case ';': case ';':
case '#': case '#':
{ {
if (names.size() == 0) if (names.empty())
{ {
AddHeaderComment(line.substr(pLeft + 1)); AddHeaderComment(line.substr(pLeft + 1));
} }
@ -168,8 +168,9 @@ bool cIniFile::ReadFile(const AString & a_FileName, bool a_AllowExampleRedirect)
} // while (getline()) } // while (getline())
f.close(); f.close();
if (names.size() == 0) if (keys.empty() && names.empty() && comments.empty())
{ {
// File be empty or unreadable, equivalent to nonexistant
return false; return false;
} }

View File

@ -503,6 +503,10 @@ enum
E_META_PLANKS_CONIFER = 1, E_META_PLANKS_CONIFER = 1,
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,

View File

@ -2145,7 +2145,7 @@ void cClientHandle::SendExplosion(double a_BlockX, double a_BlockY, double a_Blo
} }
// Update the statistics: // Update the statistics:
m_NumExplosionsThisTick += 1; m_NumExplosionsThisTick++;
m_Protocol->SendExplosion(a_BlockX, a_BlockY, a_BlockZ, a_Radius, a_BlocksAffected, a_PlayerMotion); m_Protocol->SendExplosion(a_BlockX, a_BlockY, a_BlockZ, a_Radius, a_BlocksAffected, a_PlayerMotion);
} }

View File

@ -493,15 +493,17 @@ inline void EulerToVector(double a_Pan, double a_Pitch, double & a_X, double & a
inline void VectorToEuler(double a_X, double a_Y, double a_Z, double & a_Pan, double & a_Pitch) inline void VectorToEuler(double a_X, double a_Y, double a_Z, double & a_Pan, double & a_Pitch)
{ {
if (fabs(a_X) < std::numeric_limits<double>::epsilon()) double r = sqrt((a_X * a_X) + (a_Z * a_Z));
{ if (r < std::numeric_limits<double>::epsilon())
a_Pan = atan2(a_Z, a_X) * 180 / PI - 90;
}
else
{ {
a_Pan = 0; a_Pan = 0;
} }
a_Pitch = atan2(a_Y, sqrt((a_X * a_X) + (a_Z * a_Z))) * 180 / PI; else
{
a_Pan = atan2(a_Z, a_X) * 180 / PI - 90;
}
a_Pitch = atan2(a_Y, r) * 180 / PI;
} }

View File

@ -330,7 +330,7 @@ void cEntity::DoTakeDamage(TakeDamageInfo & a_TDI)
AddSpeed(a_TDI.Knockback * 2); AddSpeed(a_TDI.Knockback * 2);
} }
m_World->BroadcastEntityStatus(*this, ENTITY_STATUS_HURT); m_World->BroadcastEntityStatus(*this, esGenericHurt);
if (m_Health <= 0) if (m_Health <= 0)
{ {
@ -479,7 +479,7 @@ void cEntity::KilledBy(cEntity * a_Killer)
GetDrops(Drops, a_Killer); GetDrops(Drops, a_Killer);
m_World->SpawnItemPickups(Drops, GetPosX(), GetPosY(), GetPosZ()); m_World->SpawnItemPickups(Drops, GetPosX(), GetPosY(), GetPosZ());
m_World->BroadcastEntityStatus(*this, ENTITY_STATUS_DEAD); m_World->BroadcastEntityStatus(*this, esGenericDead);
} }
@ -519,37 +519,36 @@ void cEntity::Tick(float a_Dt, cChunk & a_Chunk)
} }
else else
{ {
if (a_Chunk.IsValid()) if (!a_Chunk.IsValid())
{ {
cChunk * NextChunk = a_Chunk.GetNeighborChunk(POSX_TOINT, POSZ_TOINT); return;
if ((NextChunk == NULL) || !NextChunk->IsValid())
{
return;
}
TickBurning(*NextChunk);
if (GetPosY() < VOID_BOUNDARY)
{
TickInVoid(*NextChunk);
}
else
{
m_TicksSinceLastVoidDamage = 0;
}
if (IsMob() || IsPlayer())
{
// Set swimming state
SetSwimState(*NextChunk);
// Handle drowning
HandleAir();
}
HandlePhysics(a_Dt, *NextChunk);
} }
// Position changed -> super::Tick() called
GET_AND_VERIFY_CURRENT_CHUNK(NextChunk, POSX_TOINT, POSZ_TOINT)
TickBurning(*NextChunk);
if (GetPosY() < VOID_BOUNDARY)
{
TickInVoid(*NextChunk);
}
else
{
m_TicksSinceLastVoidDamage = 0;
}
if (IsMob() || IsPlayer())
{
// Set swimming state
SetSwimState(*NextChunk);
// Handle drowning
HandleAir();
}
// None of the above functions change position, we remain in the chunk of NextChunk
HandlePhysics(a_Dt, *NextChunk);
} }
} }
@ -559,34 +558,30 @@ void cEntity::Tick(float a_Dt, cChunk & a_Chunk)
void cEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk) void cEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk)
{ {
int BlockX = POSX_TOINT;
int BlockY = POSY_TOINT;
int BlockZ = POSZ_TOINT;
// Position changed -> super::HandlePhysics() called
GET_AND_VERIFY_CURRENT_CHUNK(NextChunk, BlockX, BlockZ)
// TODO Add collision detection with entities. // TODO Add collision detection with entities.
a_Dt /= 1000; // Convert from msec to sec a_Dt /= 1000; // Convert from msec to sec
Vector3d NextPos = Vector3d(GetPosX(),GetPosY(),GetPosZ()); Vector3d NextPos = Vector3d(GetPosX(), GetPosY(), GetPosZ());
Vector3d NextSpeed = Vector3d(GetSpeedX(),GetSpeedY(),GetSpeedZ()); Vector3d NextSpeed = Vector3d(GetSpeedX(), GetSpeedY(), GetSpeedZ());
int BlockX = (int) floor(NextPos.x);
int BlockY = (int) floor(NextPos.y);
int BlockZ = (int) floor(NextPos.z);
if ((BlockY >= cChunkDef::Height) || (BlockY < 0)) if ((BlockY >= cChunkDef::Height) || (BlockY < 0))
{ {
// Outside of the world // Outside of the world
AddSpeedY(m_Gravity * a_Dt);
cChunk * NextChunk = a_Chunk.GetNeighborChunk(BlockX, BlockZ); AddPosition(GetSpeed() * a_Dt);
// See if we can commit our changes. If not, we will discard them.
if (NextChunk != NULL)
{
SetSpeed(NextSpeed);
NextPos += (NextSpeed * a_Dt);
SetPosition(NextPos);
}
return; return;
} }
int RelBlockX = BlockX - (a_Chunk.GetPosX() * cChunkDef::Width); int RelBlockX = BlockX - (NextChunk->GetPosX() * cChunkDef::Width);
int RelBlockZ = BlockZ - (a_Chunk.GetPosZ() * cChunkDef::Width); int RelBlockZ = BlockZ - (NextChunk->GetPosZ() * cChunkDef::Width);
BLOCKTYPE BlockIn = a_Chunk.GetBlock( RelBlockX, BlockY, RelBlockZ ); BLOCKTYPE BlockIn = NextChunk->GetBlock( RelBlockX, BlockY, RelBlockZ );
BLOCKTYPE BlockBelow = (BlockY > 0) ? a_Chunk.GetBlock(RelBlockX, BlockY - 1, RelBlockZ) : E_BLOCK_AIR; BLOCKTYPE BlockBelow = (BlockY > 0) ? NextChunk->GetBlock(RelBlockX, BlockY - 1, RelBlockZ) : E_BLOCK_AIR;
if (!cBlockInfo::IsSolid(BlockIn)) // Making sure we are not inside a solid block if (!cBlockInfo::IsSolid(BlockIn)) // Making sure we are not inside a solid block
{ {
if (m_bOnGround) // check if it's still on the ground if (m_bOnGround) // check if it's still on the ground
@ -616,7 +611,7 @@ void cEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk)
bool IsNoAirSurrounding = true; bool IsNoAirSurrounding = true;
for (size_t i = 0; i < ARRAYCOUNT(gCrossCoords); i++) for (size_t i = 0; i < ARRAYCOUNT(gCrossCoords); i++)
{ {
if (!a_Chunk.UnboundedRelGetBlockType(RelBlockX + gCrossCoords[i].x, BlockY, RelBlockZ + gCrossCoords[i].z, GotBlock)) if (!NextChunk->UnboundedRelGetBlockType(RelBlockX + gCrossCoords[i].x, BlockY, RelBlockZ + gCrossCoords[i].z, GotBlock))
{ {
// The pickup is too close to an unloaded chunk, bail out of any physics handling // The pickup is too close to an unloaded chunk, bail out of any physics handling
return; return;
@ -764,20 +759,8 @@ void cEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk)
} }
} }
BlockX = (int) floor(NextPos.x); SetPosition(NextPos);
BlockZ = (int) floor(NextPos.z); SetSpeed(NextSpeed);
cChunk * NextChunk = a_Chunk.GetNeighborChunk(BlockX, BlockZ);
// See if we can commit our changes. If not, we will discard them.
if (NextChunk != NULL)
{
if (NextPos.x != GetPosX()) SetPosX(NextPos.x);
if (NextPos.y != GetPosY()) SetPosY(NextPos.y);
if (NextPos.z != GetPosZ()) SetPosZ(NextPos.z);
if (NextSpeed.x != GetSpeedX()) SetSpeedX(NextSpeed.x);
if (NextSpeed.y != GetSpeedY()) SetSpeedY(NextSpeed.y);
if (NextSpeed.z != GetSpeedZ()) SetSpeedZ(NextSpeed.z);
}
} }
@ -806,7 +789,7 @@ void cEntity::TickBurning(cChunk & a_Chunk)
int MaxRelX = (int)floor(GetPosX() + m_Width / 2) - a_Chunk.GetPosX() * cChunkDef::Width; int MaxRelX = (int)floor(GetPosX() + m_Width / 2) - a_Chunk.GetPosX() * cChunkDef::Width;
int MinRelZ = (int)floor(GetPosZ() - m_Width / 2) - a_Chunk.GetPosZ() * cChunkDef::Width; int MinRelZ = (int)floor(GetPosZ() - m_Width / 2) - a_Chunk.GetPosZ() * cChunkDef::Width;
int MaxRelZ = (int)floor(GetPosZ() + m_Width / 2) - a_Chunk.GetPosZ() * cChunkDef::Width; int MaxRelZ = (int)floor(GetPosZ() + m_Width / 2) - a_Chunk.GetPosZ() * cChunkDef::Width;
int MinY = std::max(0, std::min(cChunkDef::Height - 1, (int)floor(GetPosY()))); int MinY = std::max(0, std::min(cChunkDef::Height - 1, POSY_TOINT));
int MaxY = std::max(0, std::min(cChunkDef::Height - 1, (int)ceil (GetPosY() + m_Height))); int MaxY = std::max(0, std::min(cChunkDef::Height - 1, (int)ceil (GetPosY() + m_Height)));
bool HasWater = false; bool HasWater = false;
bool HasLava = false; bool HasLava = false;
@ -981,13 +964,13 @@ void cEntity::HandleAir(void)
} }
else else
{ {
m_AirTickTimer -= 1; m_AirTickTimer--;
} }
} }
else else
{ {
// Reduce air supply // Reduce air supply
m_AirLevel -= 1; m_AirLevel--;
} }
} }
else else
@ -1099,15 +1082,15 @@ void cEntity::TeleportToCoords(double a_PosX, double a_PosY, double a_PosZ)
void cEntity::BroadcastMovementUpdate(const cClientHandle * a_Exclude) void cEntity::BroadcastMovementUpdate(const cClientHandle * a_Exclude)
{ {
//We need to keep updating the clients when there is movement or if there was a change in speed and after 2 ticks // Send velocity packet every two ticks if: speed is not negligible or speed was set (as indicated by the DirtySpeed flag)
if( (m_Speed.SqrLength() > 0.0004f || m_bDirtySpeed) && (m_World->GetWorldAge() - m_TimeLastSpeedPacket >= 2)) if (((m_Speed.SqrLength() > 0.0004f) || m_bDirtySpeed) && ((m_World->GetWorldAge() - m_TimeLastSpeedPacket) >= 2))
{ {
m_World->BroadcastEntityVelocity(*this,a_Exclude); m_World->BroadcastEntityVelocity(*this,a_Exclude);
m_bDirtySpeed = false; m_bDirtySpeed = false;
m_TimeLastSpeedPacket = m_World->GetWorldAge(); m_TimeLastSpeedPacket = m_World->GetWorldAge();
} }
//Have to process position related packets this every two ticks // Have to process position related packets this every two ticks
if (m_World->GetWorldAge() % 2 == 0) if (m_World->GetWorldAge() % 2 == 0)
{ {
int DiffX = (int) (floor(GetPosX() * 32.0) - floor(m_LastPosX * 32.0)); int DiffX = (int) (floor(GetPosX() * 32.0) - floor(m_LastPosX * 32.0));

View File

@ -32,6 +32,8 @@
#define POSZ_TOINT (int)floor(GetPosZ()) #define POSZ_TOINT (int)floor(GetPosZ())
#define POS_TOINT Vector3i(POSXTOINT, POSYTOINT, POSZTOINT) #define POS_TOINT Vector3i(POSXTOINT, POSYTOINT, POSZTOINT)
#define GET_AND_VERIFY_CURRENT_CHUNK(ChunkVarName, X, Z) cChunk * ChunkVarName = a_Chunk.GetNeighborChunk(X, Z); if ((ChunkVarName == NULL) || !ChunkVarName->IsValid()) { return; }
@ -88,23 +90,42 @@ public:
} ; } ;
// tolua_end // tolua_end
enum enum eEntityStatus
{ {
ENTITY_STATUS_HURT = 2, // TODO: Investiagate 0, 1, and 5 as Wiki.vg is not certain
ENTITY_STATUS_DEAD = 3,
ENTITY_STATUS_WOLF_TAMING = 6, // Entity becomes coloured red
ENTITY_STATUS_WOLF_TAMED = 7, esGenericHurt = 2,
ENTITY_STATUS_WOLF_SHAKING = 8, // Entity plays death animation (entity falls to ground)
ENTITY_STATUS_EATING_ACCEPTED = 9, esGenericDead = 3,
ENTITY_STATUS_SHEEP_EATING = 10, // Iron Golem plays attack animation (arms lift and fall)
ENTITY_STATUS_GOLEM_ROSING = 11, esIronGolemAttacking = 4,
ENTITY_STATUS_VILLAGER_HEARTS = 12, // Wolf taming particles spawn (smoke)
ENTITY_STATUS_VILLAGER_ANGRY = 13, esWolfTaming = 6,
ENTITY_STATUS_VILLAGER_HAPPY = 14, // Wolf tamed particles spawn (hearts)
ENTITY_STATUS_WITCH_MAGICKING = 15, esWolfTamed = 7,
// Wolf plays water removal animation (shaking and water particles)
esWolfDryingWater = 8,
// Informs client that eating was accepted
esPlayerEatingAccepted = 9,
// Sheep plays eating animation (head lowers to ground)
esSheepEating = 10,
// Iron Golem holds gift to villager children
esIronGolemGivingPlant = 11,
// Villager spawns heart particles
esVillagerBreeding = 12,
// Villager spawns thunderclound particles
esVillagerAngry = 13,
// Villager spawns green crosses
esVillagerHappy = 14,
// Witch spawns magic particle (TODO: investigation into what this is)
esWitchMagicking = 15,
// It seems 16 (zombie conversion) is now done with metadata // It seems 16 (zombie conversion) is now done with metadata
ENTITY_STATUS_FIREWORK_EXPLODE= 17,
// Informs client to explode a firework based on its metadata
esFireworkExploding = 17,
} ; } ;
enum enum
@ -118,7 +139,8 @@ public:
BURN_TICKS = 200, ///< How long to keep an entity burning after it has stood in lava / fire BURN_TICKS = 200, ///< How long to keep an entity burning after it has stood in lava / fire
MAX_AIR_LEVEL = 300, ///< Maximum air an entity can have MAX_AIR_LEVEL = 300, ///< Maximum air an entity can have
DROWNING_TICKS = 20, ///< Number of ticks per heart of damage DROWNING_TICKS = 20, ///< Number of ticks per heart of damage
VOID_BOUNDARY = -46 ///< At what position Y to begin applying void damage VOID_BOUNDARY = -46, ///< At what position Y to begin applying void damage
FALL_DAMAGE_HEIGHT = 4 ///< At what position Y fall damage is applied
} ; } ;
cEntity(eEntityType a_EntityType, double a_X, double a_Y, double a_Z, double a_Width, double a_Height); cEntity(eEntityType a_EntityType, double a_X, double a_Y, double a_Z, double a_Width, double a_Height);

View File

@ -132,7 +132,7 @@ void cMinecart::HandlePhysics(float a_Dt, cChunk & a_Chunk)
return; return;
} }
int PosY = (int)floor(GetPosY()); int PosY = POSY_TOINT;
if ((PosY <= 0) || (PosY >= cChunkDef::Height)) if ((PosY <= 0) || (PosY >= cChunkDef::Height))
{ {
// Outside the world, just process normal falling physics // Outside the world, just process normal falling physics
@ -141,8 +141,8 @@ void cMinecart::HandlePhysics(float a_Dt, cChunk & a_Chunk)
return; return;
} }
int RelPosX = (int)floor(GetPosX()) - a_Chunk.GetPosX() * cChunkDef::Width; int RelPosX = POSX_TOINT - a_Chunk.GetPosX() * cChunkDef::Width;
int RelPosZ = (int)floor(GetPosZ()) - a_Chunk.GetPosZ() * cChunkDef::Width; int RelPosZ = POSZ_TOINT - a_Chunk.GetPosZ() * cChunkDef::Width;
cChunk * Chunk = a_Chunk.GetRelNeighborChunkAdjustCoords(RelPosX, RelPosZ); cChunk * Chunk = a_Chunk.GetRelNeighborChunkAdjustCoords(RelPosX, RelPosZ);
if (Chunk == NULL) if (Chunk == NULL)
{ {
@ -195,7 +195,7 @@ void cMinecart::HandlePhysics(float a_Dt, cChunk & a_Chunk)
super::HandlePhysics(a_Dt, *Chunk); super::HandlePhysics(a_Dt, *Chunk);
} }
if (m_bIsOnDetectorRail && !Vector3i((int)floor(GetPosX()), (int)floor(GetPosY()), (int)floor(GetPosZ())).Equals(m_DetectorRailPosition)) if (m_bIsOnDetectorRail && !Vector3i(POSX_TOINT, POSY_TOINT, POSZ_TOINT).Equals(m_DetectorRailPosition))
{ {
m_World->SetBlock(m_DetectorRailPosition.x, m_DetectorRailPosition.y, m_DetectorRailPosition.z, E_BLOCK_DETECTOR_RAIL, m_World->GetBlockMeta(m_DetectorRailPosition) & 0x07); m_World->SetBlock(m_DetectorRailPosition.x, m_DetectorRailPosition.y, m_DetectorRailPosition.z, E_BLOCK_DETECTOR_RAIL, m_World->GetBlockMeta(m_DetectorRailPosition) & 0x07);
m_bIsOnDetectorRail = false; m_bIsOnDetectorRail = false;
@ -203,7 +203,7 @@ void cMinecart::HandlePhysics(float a_Dt, cChunk & a_Chunk)
else if (WasDetectorRail) else if (WasDetectorRail)
{ {
m_bIsOnDetectorRail = true; m_bIsOnDetectorRail = true;
m_DetectorRailPosition = Vector3i((int)floor(GetPosX()), (int)floor(GetPosY()), (int)floor(GetPosZ())); m_DetectorRailPosition = Vector3i(POSX_TOINT, POSY_TOINT, POSZ_TOINT);
} }
// Broadcast positioning changes to client // Broadcast positioning changes to client
@ -719,11 +719,11 @@ bool cMinecart::TestBlockCollision(NIBBLETYPE a_RailMeta)
{ {
if (GetSpeedZ() > 0) if (GetSpeedZ() > 0)
{ {
BLOCKTYPE Block = m_World->GetBlock((int)floor(GetPosX()), (int)floor(GetPosY()), (int)ceil(GetPosZ())); BLOCKTYPE Block = m_World->GetBlock(POSX_TOINT, POSY_TOINT, (int)ceil(GetPosZ()));
if (!IsBlockRail(Block) && cBlockInfo::IsSolid(Block)) if (!IsBlockRail(Block) && cBlockInfo::IsSolid(Block))
{ {
// We could try to detect a block in front based purely on coordinates, but xoft made a bounding box system - why not use? :P // We could try to detect a block in front based purely on coordinates, but xoft made a bounding box system - why not use? :P
cBoundingBox bbBlock(Vector3d((int)floor(GetPosX()), (int)floor(GetPosY()), (int)ceil(GetPosZ())), 0.5, 1); cBoundingBox bbBlock(Vector3d(POSX_TOINT, POSY_TOINT, (int)ceil(GetPosZ())), 0.5, 1);
cBoundingBox bbMinecart(Vector3d(GetPosX(), floor(GetPosY()), GetPosZ()), GetWidth() / 2, GetHeight()); cBoundingBox bbMinecart(Vector3d(GetPosX(), floor(GetPosY()), GetPosZ()), GetWidth() / 2, GetHeight());
if (bbBlock.DoesIntersect(bbMinecart)) if (bbBlock.DoesIntersect(bbMinecart))
@ -736,10 +736,10 @@ bool cMinecart::TestBlockCollision(NIBBLETYPE a_RailMeta)
} }
else if (GetSpeedZ() < 0) else if (GetSpeedZ() < 0)
{ {
BLOCKTYPE Block = m_World->GetBlock((int)floor(GetPosX()), (int)floor(GetPosY()), (int)floor(GetPosZ()) - 1); BLOCKTYPE Block = m_World->GetBlock(POSX_TOINT, POSY_TOINT, POSZ_TOINT - 1);
if (!IsBlockRail(Block) && cBlockInfo::IsSolid(Block)) if (!IsBlockRail(Block) && cBlockInfo::IsSolid(Block))
{ {
cBoundingBox bbBlock(Vector3d((int)floor(GetPosX()), (int)floor(GetPosY()), (int)floor(GetPosZ()) - 1), 0.5, 1); cBoundingBox bbBlock(Vector3d(POSX_TOINT, POSY_TOINT, POSZ_TOINT - 1), 0.5, 1);
cBoundingBox bbMinecart(Vector3d(GetPosX(), floor(GetPosY()), GetPosZ() - 1), GetWidth() / 2, GetHeight()); cBoundingBox bbMinecart(Vector3d(GetPosX(), floor(GetPosY()), GetPosZ() - 1), GetWidth() / 2, GetHeight());
if (bbBlock.DoesIntersect(bbMinecart)) if (bbBlock.DoesIntersect(bbMinecart))
@ -756,10 +756,10 @@ bool cMinecart::TestBlockCollision(NIBBLETYPE a_RailMeta)
{ {
if (GetSpeedX() > 0) if (GetSpeedX() > 0)
{ {
BLOCKTYPE Block = m_World->GetBlock((int)ceil(GetPosX()), (int)floor(GetPosY()), (int)floor(GetPosZ())); BLOCKTYPE Block = m_World->GetBlock((int)ceil(GetPosX()), POSY_TOINT, POSZ_TOINT);
if (!IsBlockRail(Block) && cBlockInfo::IsSolid(Block)) if (!IsBlockRail(Block) && cBlockInfo::IsSolid(Block))
{ {
cBoundingBox bbBlock(Vector3d((int)ceil(GetPosX()), (int)floor(GetPosY()), (int)floor(GetPosZ())), 0.5, 1); cBoundingBox bbBlock(Vector3d((int)ceil(GetPosX()), POSY_TOINT, POSZ_TOINT), 0.5, 1);
cBoundingBox bbMinecart(Vector3d(GetPosX(), floor(GetPosY()), GetPosZ()), GetWidth() / 2, GetHeight()); cBoundingBox bbMinecart(Vector3d(GetPosX(), floor(GetPosY()), GetPosZ()), GetWidth() / 2, GetHeight());
if (bbBlock.DoesIntersect(bbMinecart)) if (bbBlock.DoesIntersect(bbMinecart))
@ -772,10 +772,10 @@ bool cMinecart::TestBlockCollision(NIBBLETYPE a_RailMeta)
} }
else if (GetSpeedX() < 0) else if (GetSpeedX() < 0)
{ {
BLOCKTYPE Block = m_World->GetBlock((int)floor(GetPosX()) - 1, (int)floor(GetPosY()), (int)floor(GetPosZ())); BLOCKTYPE Block = m_World->GetBlock(POSX_TOINT - 1, POSY_TOINT, POSZ_TOINT);
if (!IsBlockRail(Block) && cBlockInfo::IsSolid(Block)) if (!IsBlockRail(Block) && cBlockInfo::IsSolid(Block))
{ {
cBoundingBox bbBlock(Vector3d((int)floor(GetPosX()) - 1, (int)floor(GetPosY()), (int)floor(GetPosZ())), 0.5, 1); cBoundingBox bbBlock(Vector3d(POSX_TOINT - 1, POSY_TOINT, POSZ_TOINT), 0.5, 1);
cBoundingBox bbMinecart(Vector3d(GetPosX() - 1, floor(GetPosY()), GetPosZ()), GetWidth() / 2, GetHeight()); cBoundingBox bbMinecart(Vector3d(GetPosX() - 1, floor(GetPosY()), GetPosZ()), GetWidth() / 2, GetHeight());
if (bbBlock.DoesIntersect(bbMinecart)) if (bbBlock.DoesIntersect(bbMinecart))
@ -793,10 +793,10 @@ bool cMinecart::TestBlockCollision(NIBBLETYPE a_RailMeta)
case E_META_RAIL_CURVED_ZP_XM: case E_META_RAIL_CURVED_ZP_XM:
case E_META_RAIL_CURVED_ZP_XP: case E_META_RAIL_CURVED_ZP_XP:
{ {
BLOCKTYPE BlockXM = m_World->GetBlock((int)floor(GetPosX()) - 1, (int)floor(GetPosY()), (int)floor(GetPosZ())); BLOCKTYPE BlockXM = m_World->GetBlock(POSX_TOINT - 1, POSY_TOINT, POSZ_TOINT);
BLOCKTYPE BlockXP = m_World->GetBlock((int)floor(GetPosX()) + 1, (int)floor(GetPosY()), (int)floor(GetPosZ())); BLOCKTYPE BlockXP = m_World->GetBlock(POSX_TOINT + 1, POSY_TOINT, POSZ_TOINT);
BLOCKTYPE BlockZM = m_World->GetBlock((int)floor(GetPosX()), (int)floor(GetPosY()), (int)floor(GetPosZ()) + 1); BLOCKTYPE BlockZM = m_World->GetBlock(POSX_TOINT, POSY_TOINT, POSZ_TOINT + 1);
BLOCKTYPE BlockZP = m_World->GetBlock((int)floor(GetPosX()), (int)floor(GetPosY()), (int)floor(GetPosZ()) + 1); BLOCKTYPE BlockZP = m_World->GetBlock(POSX_TOINT, POSY_TOINT, POSZ_TOINT + 1);
if ( if (
(!IsBlockRail(BlockXM) && cBlockInfo::IsSolid(BlockXM)) || (!IsBlockRail(BlockXM) && cBlockInfo::IsSolid(BlockXM)) ||
(!IsBlockRail(BlockXP) && cBlockInfo::IsSolid(BlockXP)) || (!IsBlockRail(BlockXP) && cBlockInfo::IsSolid(BlockXP)) ||
@ -805,7 +805,7 @@ bool cMinecart::TestBlockCollision(NIBBLETYPE a_RailMeta)
) )
{ {
SetSpeed(0, 0, 0); SetSpeed(0, 0, 0);
SetPosition((int)floor(GetPosX()) + 0.5, GetPosY(), (int)floor(GetPosZ()) + 0.5); SetPosition(POSX_TOINT + 0.5, GetPosY(), POSZ_TOINT + 0.5);
return true; return true;
} }
break; break;
@ -822,7 +822,7 @@ bool cMinecart::TestEntityCollision(NIBBLETYPE a_RailMeta)
{ {
cMinecartCollisionCallback MinecartCollisionCallback(GetPosition(), GetHeight(), GetWidth(), GetUniqueID(), ((m_Attachee == NULL) ? -1 : m_Attachee->GetUniqueID())); cMinecartCollisionCallback MinecartCollisionCallback(GetPosition(), GetHeight(), GetWidth(), GetUniqueID(), ((m_Attachee == NULL) ? -1 : m_Attachee->GetUniqueID()));
int ChunkX, ChunkZ; int ChunkX, ChunkZ;
cChunkDef::BlockToChunk((int)floor(GetPosX()), (int)floor(GetPosZ()), ChunkX, ChunkZ); cChunkDef::BlockToChunk(POSX_TOINT, POSZ_TOINT, ChunkX, ChunkZ);
m_World->ForEachEntityInChunk(ChunkX, ChunkZ, MinecartCollisionCallback); m_World->ForEachEntityInChunk(ChunkX, ChunkZ, MinecartCollisionCallback);
if (!MinecartCollisionCallback.FoundIntersection()) if (!MinecartCollisionCallback.FoundIntersection())

View File

@ -98,45 +98,44 @@ void cPickup::Tick(float a_Dt, cChunk & a_Chunk)
if (!m_bCollected) if (!m_bCollected)
{ {
int BlockY = (int) floor(GetPosY()); int BlockY = POSY_TOINT;
int BlockX = POSX_TOINT;
int BlockZ = POSZ_TOINT;
if ((BlockY >= 0) && (BlockY < cChunkDef::Height)) // Don't do anything except for falling when outside the world if ((BlockY >= 0) && (BlockY < cChunkDef::Height)) // Don't do anything except for falling when outside the world
{ {
int BlockX = (int) floor(GetPosX());
int BlockZ = (int) floor(GetPosZ());
// Position might have changed due to physics. So we have to make sure we have the correct chunk. // Position might have changed due to physics. So we have to make sure we have the correct chunk.
cChunk * CurrentChunk = a_Chunk.GetNeighborChunk(BlockX, BlockZ); GET_AND_VERIFY_CURRENT_CHUNK(CurrentChunk, BlockX, BlockZ)
if (CurrentChunk != NULL) // Make sure the chunk is loaded
{ int RelBlockX = BlockX - (CurrentChunk->GetPosX() * cChunkDef::Width);
int RelBlockX = BlockX - (CurrentChunk->GetPosX() * cChunkDef::Width); int RelBlockZ = BlockZ - (CurrentChunk->GetPosZ() * cChunkDef::Width);
int RelBlockZ = BlockZ - (CurrentChunk->GetPosZ() * cChunkDef::Width);
// If the pickup is on the bottommost block position, make it think the void is made of air: (#131) // If the pickup is on the bottommost block position, make it think the void is made of air: (#131)
BLOCKTYPE BlockBelow = (BlockY > 0) ? CurrentChunk->GetBlock(RelBlockX, BlockY - 1, RelBlockZ) : E_BLOCK_AIR; BLOCKTYPE BlockBelow = (BlockY > 0) ? CurrentChunk->GetBlock(RelBlockX, BlockY - 1, RelBlockZ) : E_BLOCK_AIR;
BLOCKTYPE BlockIn = CurrentChunk->GetBlock(RelBlockX, BlockY, RelBlockZ); BLOCKTYPE BlockIn = CurrentChunk->GetBlock(RelBlockX, BlockY, RelBlockZ);
if ( if (
IsBlockLava(BlockBelow) || (BlockBelow == E_BLOCK_FIRE) || IsBlockLava(BlockBelow) || (BlockBelow == E_BLOCK_FIRE) ||
IsBlockLava(BlockIn) || (BlockIn == E_BLOCK_FIRE) IsBlockLava(BlockIn) || (BlockIn == E_BLOCK_FIRE)
) )
{
m_bCollected = true;
m_Timer = 0; // We have to reset the timer.
m_Timer += a_Dt; // In case we have to destroy the pickup in the same tick.
if (m_Timer > 500.f)
{ {
m_bCollected = true; Destroy(true);
m_Timer = 0; // We have to reset the timer. return;
m_Timer += a_Dt; // In case we have to destroy the pickup in the same tick.
if (m_Timer > 500.f)
{
Destroy(true);
return;
}
} }
}
if (!IsDestroyed()) // Don't try to combine if someone has tried to combine me if (!IsDestroyed()) // Don't try to combine if someone has tried to combine me
{
cPickupCombiningCallback PickupCombiningCallback(GetPosition(), this);
m_World->ForEachEntity(PickupCombiningCallback); // Not ForEachEntityInChunk, otherwise pickups don't combine across chunk boundaries
if (PickupCombiningCallback.FoundMatchingPickup())
{ {
cPickupCombiningCallback PickupCombiningCallback(GetPosition(), this); m_World->BroadcastEntityMetadata(*this);
m_World->ForEachEntity(PickupCombiningCallback); // Not ForEachEntityInChunk, otherwise pickups don't combine across chunk boundaries
if (PickupCombiningCallback.FoundMatchingPickup())
{
m_World->BroadcastEntityMetadata(*this);
}
} }
} }
} }
@ -156,7 +155,7 @@ void cPickup::Tick(float a_Dt, cChunk & a_Chunk)
return; return;
} }
if (GetPosY() < -8) // Out of this world and no more visible! if (GetPosY() < VOID_BOUNDARY) // Out of this world and no more visible!
{ {
Destroy(true); Destroy(true);
return; return;

View File

@ -49,9 +49,6 @@ public:
bool IsPlayerCreated(void) const { return m_bIsPlayerCreated; } // tolua_export bool IsPlayerCreated(void) const { return m_bIsPlayerCreated; } // tolua_export
private: private:
Vector3d m_ResultingSpeed; //Can be used to modify the resulting speed for the current tick ;)
Vector3d m_WaterSpeed;
/** The number of ticks that the entity has existed / timer between collect and destroy; in msec */ /** The number of ticks that the entity has existed / timer between collect and destroy; in msec */
float m_Timer; float m_Timer;

View File

@ -437,7 +437,7 @@ void cPlayer::SetTouchGround(bool a_bTouchGround)
cWorld * World = GetWorld(); cWorld * World = GetWorld();
if ((GetPosY() >= 0) && (GetPosY() < cChunkDef::Height)) if ((GetPosY() >= 0) && (GetPosY() < cChunkDef::Height))
{ {
BLOCKTYPE BlockType = World->GetBlock((int)floor(GetPosX()), (int)floor(GetPosY()), (int)floor(GetPosZ())); BLOCKTYPE BlockType = World->GetBlock(POSX_TOINT, POSY_TOINT, POSZ_TOINT);
if (BlockType != E_BLOCK_AIR) if (BlockType != E_BLOCK_AIR)
{ {
m_bTouchGround = true; m_bTouchGround = true;
@ -466,7 +466,7 @@ void cPlayer::SetTouchGround(bool a_bTouchGround)
TakeDamage(dtFalling, NULL, Damage, Damage, 0); TakeDamage(dtFalling, NULL, Damage, Damage, 0);
// Fall particles // Fall particles
GetWorld()->BroadcastSoundParticleEffect(2006, (int)floor(GetPosX()), (int)GetPosY() - 1, (int)floor(GetPosZ()), Damage /* Used as particle effect speed modifier */); GetWorld()->BroadcastSoundParticleEffect(2006, POSX_TOINT, (int)GetPosY() - 1, POSZ_TOINT, Damage /* Used as particle effect speed modifier */);
} }
m_LastGroundHeight = (float)GetPosY(); m_LastGroundHeight = (float)GetPosY();
@ -590,7 +590,7 @@ void cPlayer::FinishEating(void)
m_EatingFinishTick = -1; m_EatingFinishTick = -1;
// Send the packets: // Send the packets:
m_ClientHandle->SendEntityStatus(*this, ENTITY_STATUS_EATING_ACCEPTED); m_ClientHandle->SendEntityStatus(*this, esPlayerEatingAccepted);
m_World->BroadcastEntityAnimation(*this, 0); m_World->BroadcastEntityAnimation(*this, 0);
m_World->BroadcastEntityMetadata(*this); m_World->BroadcastEntityMetadata(*this);
@ -1519,22 +1519,16 @@ void cPlayer::LoadPermissionsFromDisk()
cIniFile IniFile; cIniFile IniFile;
if (IniFile.ReadFile("users.ini")) if (IniFile.ReadFile("users.ini"))
{ {
std::string Groups = IniFile.GetValue(m_PlayerName, "Groups", ""); AString Groups = IniFile.GetValueSet(m_PlayerName, "Groups", "Default");
if (!Groups.empty()) AStringVector Split = StringSplitAndTrim(Groups, ",");
for (AStringVector::const_iterator itr = Split.begin(), end = Split.end(); itr != end; ++itr)
{ {
AStringVector Split = StringSplitAndTrim(Groups, ","); if (!cRoot::Get()->GetGroupManager()->ExistsGroup(*itr))
for (AStringVector::const_iterator itr = Split.begin(), end = Split.end(); itr != end; ++itr)
{ {
if (!cRoot::Get()->GetGroupManager()->ExistsGroup(*itr)) LOGWARNING("The group %s for player %s was not found!", itr->c_str(), m_PlayerName.c_str());
{
LOGWARNING("The group %s for player %s was not found!", itr->c_str(), m_PlayerName.c_str());
}
AddToGroup(*itr);
} }
} AddToGroup(*itr);
else
{
AddToGroup("Default");
} }
AString Color = IniFile.GetValue(m_PlayerName, "Color", "-"); AString Color = IniFile.GetValue(m_PlayerName, "Color", "-");
@ -1546,8 +1540,10 @@ void cPlayer::LoadPermissionsFromDisk()
else else
{ {
cGroupManager::GenerateDefaultUsersIni(IniFile); cGroupManager::GenerateDefaultUsersIni(IniFile);
IniFile.AddValue("Groups", m_PlayerName, "Default");
AddToGroup("Default"); AddToGroup("Default");
} }
IniFile.WriteFile("users.ini");
ResolvePermissions(); ResolvePermissions();
} }
@ -1899,9 +1895,9 @@ void cPlayer::ApplyFoodExhaustionFromMovement()
void cPlayer::Detach() void cPlayer::Detach()
{ {
super::Detach(); super::Detach();
int PosX = (int)floor(GetPosX()); int PosX = POSX_TOINT;
int PosY = (int)floor(GetPosY()); int PosY = POSY_TOINT;
int PosZ = (int)floor(GetPosZ()); int PosZ = POSZ_TOINT;
// Search for a position within an area to teleport player after detachment // Search for a position within an area to teleport player after detachment
// Position must be solid land, and occupied by a nonsolid block // Position must be solid land, and occupied by a nonsolid block

View File

@ -791,7 +791,7 @@ void cFireworkEntity::Tick(float a_Dt, cChunk & a_Chunk)
if (m_ExplodeTimer == m_FireworkItem.m_FireworkItem.m_FlightTimeInTicks) if (m_ExplodeTimer == m_FireworkItem.m_FireworkItem.m_FlightTimeInTicks)
{ {
m_World->BroadcastEntityStatus(*this, ENTITY_STATUS_FIREWORK_EXPLODE); m_World->BroadcastEntityStatus(*this, esFireworkExploding);
Destroy(); Destroy();
} }

View File

@ -70,6 +70,40 @@ public:
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Performance test of the NetherFort generator:
/*
#include "OSSupport/Timer.h"
static class cNetherFortPerfTest
{
public:
cNetherFortPerfTest(void)
{
cTimer Timer;
long long StartTime = Timer.GetNowTime();
const int GridSize = 512;
const int MaxDepth = 12;
const int NumIterations = 100;
for (int i = 0; i < NumIterations; i++)
{
cNetherFortGen FortGen(i, GridSize, MaxDepth);
delete new cNetherFortGen::cNetherFort(FortGen, 0, 0, GridSize, MaxDepth, i);
}
long long EndTime = Timer.GetNowTime();
printf("%d forts took %lld msec (%f sec) to generate\n", NumIterations, EndTime - StartTime, ((double)(EndTime - StartTime)) / 1000);
exit(0);
}
} g_PerfTest;
//*/
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// cNetherFortGen: // cNetherFortGen:
@ -258,6 +292,15 @@ cPieces cNetherFortGen::GetStartingPieces(void)
int cNetherFortGen::GetPieceWeight(const cPlacedPiece & a_PlacedPiece, const cPiece::cConnector & a_ExistingConnector, const cPiece & a_NewPiece)
{
return ((const cPrefab &)a_NewPiece).GetPieceWeight(a_PlacedPiece, a_ExistingConnector);
}
void cNetherFortGen::PiecePlaced(const cPiece & a_Piece) void cNetherFortGen::PiecePlaced(const cPiece & a_Piece)
{ {
UNUSED(a_Piece); UNUSED(a_Piece);

View File

@ -26,6 +26,7 @@ public:
virtual ~cNetherFortGen(); virtual ~cNetherFortGen();
protected: protected:
friend class cNetherFortPerfTest; // fwd: NetherFortGen.cpp
class cNetherFort; // fwd: NetherFortGen.cpp class cNetherFort; // fwd: NetherFortGen.cpp
typedef std::list<cNetherFort *> cNetherForts; typedef std::list<cNetherFort *> cNetherForts;
@ -77,6 +78,7 @@ protected:
// cPiecePool overrides: // cPiecePool overrides:
virtual cPieces GetPiecesWithConnector(int a_ConnectorType) override; virtual cPieces GetPiecesWithConnector(int a_ConnectorType) override;
virtual cPieces GetStartingPieces(void) override; virtual cPieces GetStartingPieces(void) override;
virtual int GetPieceWeight(const cPlacedPiece & a_PlacedPiece, const cPiece::cConnector & a_ExistingConnector, const cPiece & a_NewPiece) override;
virtual void PiecePlaced(const cPiece & a_Piece) override; virtual void PiecePlaced(const cPiece & a_Piece) override;
virtual void Reset(void) override; virtual void Reset(void) override;
} ; } ;

View File

@ -91,7 +91,19 @@ static const cPrefab::sDef g_TestPrefabDef =
7, /* 1, 2, 3 CCW rotations */ 7, /* 1, 2, 3 CCW rotations */
// Merge strategy: // Merge strategy:
cBlockArea::msImprint cBlockArea::msImprint,
// ShouldExtendFloor:
false,
// DefaultWeight:
10,
// DepthWeight:
"",
// AddWeightIfSame:
1000,
}; };
static cPrefab g_TestPrefab(g_TestPrefabDef); static cPrefab g_TestPrefab(g_TestPrefabDef);
@ -105,13 +117,17 @@ cPrefab::cPrefab(const cPrefab::sDef & a_Def) :
m_Size(a_Def.m_SizeX, a_Def.m_SizeY, a_Def.m_SizeZ), m_Size(a_Def.m_SizeX, a_Def.m_SizeY, a_Def.m_SizeZ),
m_HitBox(0, 0, 0, a_Def.m_SizeX - 1, a_Def.m_SizeY - 1, a_Def.m_SizeZ - 1), m_HitBox(0, 0, 0, a_Def.m_SizeX - 1, a_Def.m_SizeY - 1, a_Def.m_SizeZ - 1),
m_AllowedRotations(a_Def.m_AllowedRotations), m_AllowedRotations(a_Def.m_AllowedRotations),
m_MergeStrategy(a_Def.m_MergeStrategy) m_MergeStrategy(a_Def.m_MergeStrategy),
m_ShouldExtendFloor(a_Def.m_ShouldExtendFloor),
m_DefaultWeight(a_Def.m_DefaultWeight),
m_AddWeightIfSame(a_Def.m_AddWeightIfSame)
{ {
m_BlockArea[0].Create(m_Size); m_BlockArea[0].Create(m_Size);
CharMap cm; CharMap cm;
ParseCharMap(cm, a_Def.m_CharMap); ParseCharMap(cm, a_Def.m_CharMap);
ParseBlockImage(cm, a_Def.m_Image); ParseBlockImage(cm, a_Def.m_Image);
ParseConnectors(a_Def.m_Connectors); ParseConnectors(a_Def.m_Connectors);
ParseDepthWeight(a_Def.m_DepthWeight);
// 1 CCW rotation: // 1 CCW rotation:
if ((m_AllowedRotations & 0x01) != 0) if ((m_AllowedRotations & 0x01) != 0)
@ -142,12 +158,53 @@ cPrefab::cPrefab(const cPrefab::sDef & a_Def) :
void cPrefab::Draw(cChunkDesc & a_Dest, const cPlacedPiece * a_Placement) const void cPrefab::Draw(cChunkDesc & a_Dest, const cPlacedPiece * a_Placement) const
{ {
// Draw the basic image:
Vector3i Placement = a_Placement->GetCoords(); Vector3i Placement = a_Placement->GetCoords();
int ChunkStartX = a_Dest.GetChunkX() * cChunkDef::Width; int ChunkStartX = a_Dest.GetChunkX() * cChunkDef::Width;
int ChunkStartZ = a_Dest.GetChunkZ() * cChunkDef::Width; int ChunkStartZ = a_Dest.GetChunkZ() * cChunkDef::Width;
Placement.Move(-ChunkStartX, 0, -ChunkStartZ); Placement.Move(-ChunkStartX, 0, -ChunkStartZ);
a_Dest.WriteBlockArea(m_BlockArea[a_Placement->GetNumCCWRotations()], Placement.x, Placement.y, Placement.z, m_MergeStrategy); const cBlockArea & Image = m_BlockArea[a_Placement->GetNumCCWRotations()];
a_Dest.WriteBlockArea(Image, Placement.x, Placement.y, Placement.z, m_MergeStrategy);
// If requested, draw the floor (from the bottom of the prefab down to the nearest non-air)
int MaxX = Image.GetSizeX();
int MaxZ = Image.GetSizeZ();
for (int z = 0; z < MaxZ; z++)
{
int RelZ = Placement.z + z;
if ((RelZ < 0) || (RelZ >= cChunkDef::Width))
{
// Z coord outside the chunk
continue;
}
for (int x = 0; x < MaxX; x++)
{
int RelX = Placement.x + x;
if ((RelX < 0) || (RelX >= cChunkDef::Width))
{
// X coord outside the chunk
continue;
}
BLOCKTYPE BlockType;
NIBBLETYPE BlockMeta;
Image.GetRelBlockTypeMeta(x, 0, z, BlockType, BlockMeta);
if ((BlockType == E_BLOCK_AIR) || (BlockType == E_BLOCK_SPONGE))
{
// Do not expand air nor sponge blocks
continue;
}
for (int y = Placement.y - 1; y >= 0; y--)
{
BLOCKTYPE ExistingBlock = a_Dest.GetBlockType(RelX, y, RelZ);
if (ExistingBlock != E_BLOCK_AIR)
{
// End the expansion for this column, reached the end
break;
}
a_Dest.SetBlockTypeMeta(RelX, y, RelZ, BlockType, BlockMeta);
} // for y
} // for x
} // for z
} }
@ -170,6 +227,26 @@ bool cPrefab::HasConnectorType(int a_ConnectorType) const
int cPrefab::GetPieceWeight(const cPlacedPiece & a_PlacedPiece, const cPiece::cConnector & a_ExistingConnector) const
{
// Use the default or per-depth weight:
cDepthWeight::const_iterator itr = m_DepthWeight.find(a_PlacedPiece.GetDepth() + 1);
int res = (itr == m_DepthWeight.end()) ? m_DefaultWeight : itr->second;
// If the piece is the same as the parent, apply the m_AddWeightIfSame modifier:
const cPiece * ParentPiece = &a_PlacedPiece.GetPiece();
const cPiece * ThisPiece = this;
if (ThisPiece == ParentPiece)
{
res += m_AddWeightIfSame;
}
return res;
}
void cPrefab::ParseCharMap(CharMap & a_CharMapOut, const char * a_CharMapDef) void cPrefab::ParseCharMap(CharMap & a_CharMapOut, const char * a_CharMapDef)
{ {
ASSERT(a_CharMapDef != NULL); ASSERT(a_CharMapDef != NULL);
@ -277,6 +354,54 @@ void cPrefab::ParseConnectors(const char * a_ConnectorsDef)
void cPrefab::ParseDepthWeight(const char * a_DepthWeightDef)
{
// The member needn't be defined at all, if so, skip:
if (a_DepthWeightDef == NULL)
{
return;
}
// Split into individual records: "Record | Record | Record"
AStringVector Defs = StringSplitAndTrim(a_DepthWeightDef, "|");
// Add each record's contents:
for (AStringVector::const_iterator itr = Defs.begin(), end = Defs.end(); itr != end; ++itr)
{
// Split into components: "Depth : Weight"
AStringVector Components = StringSplitAndTrim(*itr, ":");
if (Components.size() != 2)
{
LOGWARNING("Bad prefab DepthWeight record: \"%s\", skipping.", itr->c_str());
continue;
}
// Parse depth:
int Depth = atoi(Components[0].c_str());
if ((Depth == 0) && (Components[0] != "0"))
{
LOGWARNING("Bad prefab DepthWeight record, cannot parse depth \"%s\", skipping.", Components[0].c_str());
continue;
}
// Parse weight:
int Weight = atoi(Components[1].c_str());
if ((Weight == 0) && (Components[1] != "0"))
{
LOGWARNING("Bad prefab DepthWeight record, cannot parse weight \"%s\", skipping.", Components[1].c_str());
continue;
}
// Save to map:
ASSERT(m_DepthWeight.find(Depth) == m_DepthWeight.end()); // Not a duplicate
m_DepthWeight[Depth] = Weight;
} // for itr - Defs[]
}
cPiece::cConnectors cPrefab::GetConnectors(void) const cPiece::cConnectors cPrefab::GetConnectors(void) const
{ {
return m_Connectors; return m_Connectors;

View File

@ -37,11 +37,47 @@ public:
int m_SizeX; int m_SizeX;
int m_SizeY; int m_SizeY;
int m_SizeZ; int m_SizeZ;
/** The mapping between characters in m_Image and the blocktype / blockmeta.
Format: "Char: BlockType: BlockMeta \n Char: BlockType : BlockMeta \n ..." */
const char * m_CharMap; const char * m_CharMap;
/** The actual image to be used for the prefab. Organized YZX (Y changes the least often).
Each character represents a single block, the type is mapped through m_CharMap. */
const char * m_Image; const char * m_Image;
/** List of connectors.
Format: "Type: X, Y, Z : Direction \n Type : X, Y, Z : Direction \n ...".
Type is an arbitrary number, Direction is the BlockFace constant value (0 .. 5). */
const char * m_Connectors; const char * m_Connectors;
/** Bitmask specifying the allowed rotations.
N rotations CCW are allowed if bit N is set. */
int m_AllowedRotations; int m_AllowedRotations;
/** The merge strategy to use while drawing the prefab. */
cBlockArea::eMergeStrategy m_MergeStrategy; cBlockArea::eMergeStrategy m_MergeStrategy;
/** If set to true, the prefab will extend its lowermost blocks until a solid block is found,
thus creating a foundation for the prefab. This is used for houses to be "on the ground", as well as
nether fortresses not to float. */
bool m_ShouldExtendFloor;
/** Chance of this piece being used, if no other modifier is active. */
int m_DefaultWeight;
/** Chances of this piece being used, per depth of the generated piece tree.
The starting piece has a depth of 0, the pieces connected to it are depth 1, etc.
The specified depth stands for the depth of the new piece (not the existing already-placed piece),
so valid depths start at 1.
Format: "Depth : Weight | Depth : Weight | Depth : Weight ..."
Depths that are not specified will use the m_DefaultWeight value. */
const char * m_DepthWeight;
/** The weight to add to this piece's base per-depth chance if the previous piece is the same.
Can be positive or negative.
This is used e. g. to make nether bridges prefer spanning multiple segments or to penalize turrets next to each other. */
int m_AddWeightIfSame;
}; };
cPrefab(const sDef & a_Def); cPrefab(const sDef & a_Def);
@ -51,6 +87,10 @@ public:
/** Returns true if the prefab has any connector of the specified type. */ /** Returns true if the prefab has any connector of the specified type. */
bool HasConnectorType(int a_ConnectorType) const; bool HasConnectorType(int a_ConnectorType) const;
/** Returns the weight (chance) of this prefab generating as the next piece after the specified placed piece.
PiecePool implementations can use this for their GetPieceWeight() implementations. */
int GetPieceWeight(const cPlacedPiece & a_PlacedPiece, const cPiece::cConnector & a_ExistingConnector) const;
protected: protected:
/** Packs complete definition of a single block, for per-letter assignment. */ /** Packs complete definition of a single block, for per-letter assignment. */
@ -60,9 +100,12 @@ protected:
NIBBLETYPE m_BlockMeta; NIBBLETYPE m_BlockMeta;
}; };
/** Maps letters in the sDef::m_Image onto a number, BlockType * 16 | BlockMeta */ /** Maps letters in the sDef::m_Image onto a sBlockTypeDef block type definition. */
typedef sBlockTypeDef CharMap[256]; typedef sBlockTypeDef CharMap[256];
/** Maps generator tree depth to weight. */
typedef std::map<int, int> cDepthWeight;
/** The cBlockArea that contains the block definitions for the prefab. /** The cBlockArea that contains the block definitions for the prefab.
The index identifies the number of CCW rotations applied (0 = no rotation, 1 = 1 CCW rotation, ...). */ The index identifies the number of CCW rotations applied (0 = no rotation, 1 = 1 CCW rotation, ...). */
@ -82,6 +125,26 @@ protected:
/** The merge strategy to use when drawing the prefab into a block area */ /** The merge strategy to use when drawing the prefab into a block area */
cBlockArea::eMergeStrategy m_MergeStrategy; cBlockArea::eMergeStrategy m_MergeStrategy;
/** If set to true, the prefab will extend its lowermost blocks until a solid block is found,
thus creating a foundation for the prefab. This is used for houses to be "on the ground", as well as
nether fortresses not to float. */
bool m_ShouldExtendFloor;
/** Chance of this piece being used, if no other modifier is active. */
int m_DefaultWeight;
/** Chances of this piece being used, per depth of the generated piece tree.
The starting piece has a depth of 0, the pieces connected to it are depth 1, etc.
The specified depth stands for the depth of the new piece (not the existing already-placed piece),
so valid depths start at 1.
Depths that are not specified will use the m_DefaultWeight value. */
cDepthWeight m_DepthWeight;
/** The weight to add to this piece's base per-depth chance if the previous piece is the same.
Can be positive or negative.
This is used e. g. to make nether bridges prefer spanning multiple segments or to penalize turrets next to each other. */
int m_AddWeightIfSame;
// cPiece overrides: // cPiece overrides:
@ -98,6 +161,9 @@ protected:
/** Parses the connectors definition text into m_Connectors member. */ /** Parses the connectors definition text into m_Connectors member. */
void ParseConnectors(const char * a_ConnectorsDef); void ParseConnectors(const char * a_ConnectorsDef);
/** Parses the per-depth weight into m_DepthWeight member. */
void ParseDepthWeight(const char * a_DepthWeightDef);
}; };

View File

@ -133,10 +133,22 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
"1: 0, 2, 2: 4\n" /* Type 1, direction X- */, "1: 0, 2, 2: 4\n" /* Type 1, direction X- */,
// AllowedRotations: // AllowedRotations:
7, /* 1, 2, 3 CCW rotations */ 7, /* 1, 2, 3 CCW rotation allowed */
// Merge strategy: // Merge strategy:
cBlockArea::msSpongePrint, cBlockArea::msSpongePrint,
// ShouldExtendFloor:
false,
// DefaultWeight:
20,
// DepthWeight:
"",
// AddWeightIfSame:
0,
}, // BalconyCorridor }, // BalconyCorridor
@ -274,10 +286,22 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
"1: 0, 2, 4: 4\n" /* Type 1, direction X- */, "1: 0, 2, 4: 4\n" /* Type 1, direction X- */,
// AllowedRotations: // AllowedRotations:
7, /* 1, 2, 3 CCW rotations */ 7, /* 1, 2, 3 CCW rotation allowed */
// Merge strategy: // Merge strategy:
cBlockArea::msSpongePrint, cBlockArea::msSpongePrint,
// ShouldExtendFloor:
false,
// DefaultWeight:
20,
// DepthWeight:
"",
// AddWeightIfSame:
0,
}, // BalconyTee2 }, // BalconyTee2
@ -378,10 +402,22 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
"0: 0, 1, 3: 4\n" /* Type 0, direction X- */, "0: 0, 1, 3: 4\n" /* Type 0, direction X- */,
// AllowedRotations: // AllowedRotations:
7, /* 1, 2, 3 CCW rotations */ 7, /* 1, 2, 3 CCW rotation allowed */
// Merge strategy: // Merge strategy:
cBlockArea::msSpongePrint, cBlockArea::msSpongePrint,
// ShouldExtendFloor:
false,
// DefaultWeight:
100,
// DepthWeight:
"",
// AddWeightIfSame:
0,
}, // BlazePlatform }, // BlazePlatform
@ -510,10 +546,22 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
"0: 0, 5, 3: 4\n" /* Type 0, direction X- */, "0: 0, 5, 3: 4\n" /* Type 0, direction X- */,
// AllowedRotations: // AllowedRotations:
7, /* 1, 2, 3 CCW rotations */ 7, /* 1, 2, 3 CCW rotation allowed */
// Merge strategy: // Merge strategy:
cBlockArea::msSpongePrint, cBlockArea::msSpongePrint,
// ShouldExtendFloor:
false,
// DefaultWeight:
100,
// DepthWeight:
"",
// AddWeightIfSame:
0,
}, // BlazePlatformOverhang }, // BlazePlatformOverhang
@ -694,10 +742,22 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
"0: 7, 5, 14: 3\n" /* Type 0, direction Z+ */, "0: 7, 5, 14: 3\n" /* Type 0, direction Z+ */,
// AllowedRotations: // AllowedRotations:
7, /* 1, 2, 3 CCW rotations */ 7, /* 1, 2, 3 CCW rotation allowed */
// Merge strategy: // Merge strategy:
cBlockArea::msSpongePrint, cBlockArea::msSpongePrint,
// ShouldExtendFloor:
false,
// DefaultWeight:
5,
// DepthWeight:
"",
// AddWeightIfSame:
0,
}, // BridgeCircleCrossing }, // BridgeCircleCrossing
@ -879,10 +939,22 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
"0: 14, 5, 7: 5\n" /* Type 0, direction X+ */, "0: 14, 5, 7: 5\n" /* Type 0, direction X+ */,
// AllowedRotations: // AllowedRotations:
7, /* 1, 2, 3 CCW rotations */ 7, /* 1, 2, 3 CCW rotation allowed */
// Merge strategy: // Merge strategy:
cBlockArea::msSpongePrint, cBlockArea::msSpongePrint,
// ShouldExtendFloor:
false,
// DefaultWeight:
10,
// DepthWeight:
"1:1000",
// AddWeightIfSame:
0,
}, // BridgeCrossing }, // BridgeCrossing
@ -957,10 +1029,22 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
"0: 0, 5, 2: 4\n" /* Type 0, direction X- */, "0: 0, 5, 2: 4\n" /* Type 0, direction X- */,
// AllowedRotations: // AllowedRotations:
7, /* 1, 2, 3 CCW rotations */ 7, /* 1, 2, 3 CCW rotation allowed */
// Merge strategy: // Merge strategy:
cBlockArea::msSpongePrint, cBlockArea::msSpongePrint,
// ShouldExtendFloor:
false,
// DefaultWeight:
100,
// DepthWeight:
"1:0",
// AddWeightIfSame:
0,
}, // BridgeCrumble1 }, // BridgeCrumble1
@ -1041,10 +1125,22 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
"1: 0, 5, 2: 4\n" /* Type 1, direction X- */, "1: 0, 5, 2: 4\n" /* Type 1, direction X- */,
// AllowedRotations: // AllowedRotations:
7, /* 1, 2, 3 CCW rotations */ 7, /* 1, 2, 3 CCW rotation allowed */
// Merge strategy: // Merge strategy:
cBlockArea::msSpongePrint, cBlockArea::msSpongePrint,
// ShouldExtendFloor:
false,
// DefaultWeight:
100,
// DepthWeight:
"1:0",
// AddWeightIfSame:
0,
}, // BridgeCrumble2 }, // BridgeCrumble2
@ -1204,14 +1300,262 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
"0: 2, 4, 15: 3\n" /* Type 0, direction Z+ */, "0: 2, 4, 15: 3\n" /* Type 0, direction Z+ */,
// AllowedRotations: // AllowedRotations:
7, /* 1, 2, 3 CCW rotations */ 7, /* 1, 2, 3 CCW rotation allowed */
// Merge strategy: // Merge strategy:
cBlockArea::msSpongePrint, cBlockArea::msSpongePrint,
// ShouldExtendFloor:
false,
// DefaultWeight:
10,
// DepthWeight:
"",
// AddWeightIfSame:
1000,
}, // BridgeDoubleCrumble }, // BridgeDoubleCrumble
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// BridgeFunnelDown:
// The data has been exported from the gallery Nether, area index 0, ID 2, created by Aloe_vera
{
// Size:
15, 12, 12, // SizeX = 15, SizeY = 12, SizeZ = 12
// Block definitions:
".: 0: 0\n" /* air */
"a:112: 0\n" /* netherbrick */
"b:114: 6\n" /* netherbrickstairs */
"c:114: 4\n" /* netherbrickstairs */
"d:114: 5\n" /* netherbrickstairs */
"e: 44:14\n" /* step */
"f:114: 7\n" /* netherbrickstairs */
"m: 19: 0\n" /* sponge */,
// Block data:
// Level 0
/* z\x* 11111 */
/* * 012345678901234 */
/* 0 */ "mmmmmmmmmmmmmmm"
/* 1 */ "aammmmmmmmmmmaa"
/* 2 */ "aammmmmmmmmmmaa"
/* 3 */ "aammmmmmmmmmmaa"
/* 4 */ "mmmmmmmmmmmmmmm"
/* 5 */ "mmmmmmmmmmmmmmm"
/* 6 */ "mmmmmmmmmmmmmmm"
/* 7 */ "mmmmmmmmmmmmmmm"
/* 8 */ "mmmmmmmmmmmmmmm"
/* 9 */ "mmmmmmaaammmmmm"
/* 10 */ "mmmmmmaaammmmmm"
/* 11 */ "mmmmmmaaammmmmm"
// Level 1
/* z\x* 11111 */
/* * 012345678901234 */
/* 0 */ "mmmmmmmmmmmmmmm"
/* 1 */ "aammmmmmmmmmmaa"
/* 2 */ "aammmmmmmmmmmaa"
/* 3 */ "aammmmmmmmmmmaa"
/* 4 */ "mmmmmmmmmmmmmmm"
/* 5 */ "mmmmmmmmmmmmmmm"
/* 6 */ "mmmmmmmmmmmmmmm"
/* 7 */ "mmmmmmmmmmmmmmm"
/* 8 */ "mmmmmmbbbmmmmmm"
/* 9 */ "mmmmmmaaammmmmm"
/* 10 */ "mmmmmmaaammmmmm"
/* 11 */ "mmmmmmaaammmmmm"
// Level 2
/* z\x* 11111 */
/* * 012345678901234 */
/* 0 */ "mmmmmmmmmmmmmmm"
/* 1 */ "aammmmmmmmmmmaa"
/* 2 */ "aammmmmmmmmmmaa"
/* 3 */ "aammmmmmmmmmmaa"
/* 4 */ "mmmmmmmmmmmmmmm"
/* 5 */ "mmmmmmmmmmmmmmm"
/* 6 */ "mmmmmmmmmmmmmmm"
/* 7 */ "mmmmmcbbbdmmmmm"
/* 8 */ "mmmmmcaaadmmmmm"
/* 9 */ "mmmmmcaaadmmmmm"
/* 10 */ "mmmmmcaaadmmmmm"
/* 11 */ "mmmmmcaaadmmmmm"
// Level 3
/* z\x* 11111 */
/* * 012345678901234 */
/* 0 */ "mmmmmmmmmmmmmmm"
/* 1 */ "aammmmmmmmmmmaa"
/* 2 */ "aammmmmmmmmmmaa"
/* 3 */ "aammmmmmmmmmmaa"
/* 4 */ "mmmmmmmmmmmmmmm"
/* 5 */ "mmmmmmmmmmmmmmm"
/* 6 */ "mmmmmmmmmmmmmmm"
/* 7 */ "mmmmmaaaaammmmm"
/* 8 */ "mmmmmaaaaammmmm"
/* 9 */ "mmmmmaaaaammmmm"
/* 10 */ "mmmmmaaaaammmmm"
/* 11 */ "mmmmmaaaaammmmm"
// Level 4
/* z\x* 11111 */
/* * 012345678901234 */
/* 0 */ "mmmmmmmmmmmmmmm"
/* 1 */ "aammmmmmmmmmmaa"
/* 2 */ "aammmmmmmmmmmaa"
/* 3 */ "aammmmmmmmmmmaa"
/* 4 */ "mmmmmmmmmmmmmmm"
/* 5 */ "mmmmmmmmmmmmmmm"
/* 6 */ "mmmmcbbbbbdmmmm"
/* 7 */ "mmmmaaaaaaammmm"
/* 8 */ "mmmma.....ammmm"
/* 9 */ "mmmmaa...aammmm"
/* 10 */ "mmmmma...ammmmm"
/* 11 */ "mmmmma...ammmmm"
// Level 5
/* z\x* 11111 */
/* * 012345678901234 */
/* 0 */ "mmmmmmmmmmmmmmm"
/* 1 */ "aadmmmmmmmmmcaa"
/* 2 */ "aadmmmmmmmmmcaa"
/* 3 */ "aadmmmmmmmmmcaa"
/* 4 */ "mmmmmmmmmmmmmmm"
/* 5 */ "mmmcbbbbbbbdmmm"
/* 6 */ "mmmaaaaaaaaaamm"
/* 7 */ "mmma.......ammm"
/* 8 */ "mmmaa.....aammm"
/* 9 */ "mmmmam...mammmm"
/* 10 */ "mmmmmm...mmmmmm"
/* 11 */ "mmmmmm...mmmmmm"
// Level 6
/* z\x* 11111 */
/* * 012345678901234 */
/* 0 */ "mmmmmmmmmmmmmmm"
/* 1 */ "aaademmmmmecaaa"
/* 2 */ "aaademmmmmecaaa"
/* 3 */ "aaademmmmmecaaa"
/* 4 */ "mmaaabbbbbaaaam"
/* 5 */ "mmaaaaaaaaaaaam"
/* 6 */ "mma.........amm"
/* 7 */ "mmaa.......aamm"
/* 8 */ "mmmam.....mammm"
/* 9 */ "mmmmmm...mmmmmm"
/* 10 */ "mmmmmm...mmmmmm"
/* 11 */ "mmmmmm...mmmmmm"
// Level 7
/* z\x* 11111 */
/* * 012345678901234 */
/* 0 */ "bbbbbbbbbbbbbbb"
/* 1 */ "aaaaaaaaaaaaaaa"
/* 2 */ "aaaaaaaaaaaaaaa"
/* 3 */ "aaaaaaaaaaaaaaa"
/* 4 */ "faaaaaaaaaaaaaa"
/* 5 */ "ma...........am"
/* 6 */ "maa.........aam"
/* 7 */ "mmam.......mamm"
/* 8 */ "mmmmm.....mmmmm"
/* 9 */ "mmmmmmmmmmmmmmm"
/* 10 */ "mmmmmmmmmmmmmmm"
/* 11 */ "mmmmmmmmmmmmmmm"
// Level 8
/* z\x* 11111 */
/* * 012345678901234 */
/* 0 */ "aaaaaaaaaaaaaaa"
/* 1 */ "aaaaaaaaaaaaaaa"
/* 2 */ "aaaaaaaaaaaaaaa"
/* 3 */ "aaaaaaaaaaaaaaa"
/* 4 */ "a.............a"
/* 5 */ "aa...........aa"
/* 6 */ "mam.........mam"
/* 7 */ "mmmm.......mmmm"
/* 8 */ "mmmmmmmmmmmmmmm"
/* 9 */ "mmmmmmmmmmmmmmm"
/* 10 */ "mmmmmmmmmmmmmmm"
/* 11 */ "mmmmmmmmmmmmmmm"
// Level 9
/* z\x* 11111 */
/* * 012345678901234 */
/* 0 */ "aaaaaaaaaaaaaaa"
/* 1 */ "..............."
/* 2 */ "..............."
/* 3 */ "..............."
/* 4 */ "a.............a"
/* 5 */ "am............a"
/* 6 */ "mmm.........mmm"
/* 7 */ "mmmmmmmmmmmmmmm"
/* 8 */ "mmmmmmmmmmmmmmm"
/* 9 */ "mmmmmmmmmmmmmmm"
/* 10 */ "mmmmmmmmmmmmmmm"
/* 11 */ "mmmmmmmmmmmmmmm"
// Level 10
/* z\x* 11111 */
/* * 012345678901234 */
/* 0 */ "mmmmmmmmmmmmmmm"
/* 1 */ "..............."
/* 2 */ "..............."
/* 3 */ "..............."
/* 4 */ "m.............m"
/* 5 */ "mm............m"
/* 6 */ "mmmmmmmmmmmmmmm"
/* 7 */ "mmmmmmmmmmmmmmm"
/* 8 */ "mmmmmmmmmmmmmmm"
/* 9 */ "mmmmmmmmmmmmmmm"
/* 10 */ "mmmmmmmmmmmmmmm"
/* 11 */ "mmmmmmmmmmmmmmm"
// Level 11
/* z\x* 11111 */
/* * 012345678901234 */
/* 0 */ "mmmmmmmmmmmmmmm"
/* 1 */ "..............."
/* 2 */ "..............."
/* 3 */ "..............."
/* 4 */ "m.............m"
/* 5 */ "mmmmmmmmmmmmmmm"
/* 6 */ "mmmmmmmmmmmmmmm"
/* 7 */ "mmmmmmmmmmmmmmm"
/* 8 */ "mmmmmmmmmmmmmmm"
/* 9 */ "mmmmmmmmmmmmmmm"
/* 10 */ "mmmmmmmmmmmmmmm"
/* 11 */ "mmmmmmmmmmmmmmm",
// Connectors:
"0: 7, 4, 11: 3\n" /* Type 0, direction Z+ */
"0: 0, 9, 2: 4\n" /* Type 0, direction X- */
"0: 14, 9, 2: 5\n" /* Type 0, direction X+ */,
// AllowedRotations:
7, /* 1, 2, 3 CCW rotation allowed */
// Merge strategy:
cBlockArea::msSpongePrint,
// ShouldExtendFloor:
false,
// DefaultWeight:
5,
// DepthWeight:
"",
// AddWeightIfSame:
0,
}, // BridgeFunnelDown
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// BridgeLevelCrossing: // BridgeLevelCrossing:
// The data has been exported from the gallery Nether, area index 45, ID 304, created by Aloe_vera // The data has been exported from the gallery Nether, area index 45, ID 304, created by Aloe_vera
@ -1514,10 +1858,22 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
"", "",
// AllowedRotations: // AllowedRotations:
7, /* 1, 2, 3 CCW rotations */ 7, /* 1, 2, 3 CCW rotation allowed */
// Merge strategy: // Merge strategy:
cBlockArea::msSpongePrint, cBlockArea::msSpongePrint,
// ShouldExtendFloor:
false,
// DefaultWeight:
100,
// DepthWeight:
"",
// AddWeightIfSame:
0,
}, // BridgeLevelCrossing }, // BridgeLevelCrossing
@ -1617,10 +1973,22 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
"0: 14, 5, 2: 5\n" /* Type 0, direction X+ */, "0: 14, 5, 2: 5\n" /* Type 0, direction X+ */,
// AllowedRotations: // AllowedRotations:
7, /* 1, 2, 3 CCW rotations */ 7, /* 1, 2, 3 CCW rotation allowed */
// Merge strategy: // Merge strategy:
cBlockArea::msSpongePrint, cBlockArea::msSpongePrint,
// ShouldExtendFloor:
false,
// DefaultWeight:
500,
// DepthWeight:
"",
// AddWeightIfSame:
1000,
}, // BridgeSegment }, // BridgeSegment
@ -1761,10 +2129,22 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
"0: 14, 5, 2: 5\n" /* Type 0, direction X+ */, "0: 14, 5, 2: 5\n" /* Type 0, direction X+ */,
// AllowedRotations: // AllowedRotations:
7, /* 1, 2, 3 CCW rotations */ 7, /* 1, 2, 3 CCW rotation allowed */
// Merge strategy: // Merge strategy:
cBlockArea::msSpongePrint, cBlockArea::msSpongePrint,
// ShouldExtendFloor:
false,
// DefaultWeight:
10,
// DepthWeight:
"1:500",
// AddWeightIfSame:
0,
}, // BridgeTee }, // BridgeTee
@ -1844,10 +2224,22 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
"1: 0, 1, 2: 4\n" /* Type 1, direction X- */, "1: 0, 1, 2: 4\n" /* Type 1, direction X- */,
// AllowedRotations: // AllowedRotations:
7, /* 1, 2, 3 CCW rotations */ 7, /* 1, 2, 3 CCW rotation allowed */
// Merge strategy: // Merge strategy:
cBlockArea::msSpongePrint, cBlockArea::msSpongePrint,
// ShouldExtendFloor:
false,
// DefaultWeight:
200,
// DepthWeight:
"",
// AddWeightIfSame:
0,
}, // Corridor11 }, // Corridor11
@ -1927,10 +2319,22 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
"1: 0, 1, 2: 4\n" /* Type 1, direction X- */, "1: 0, 1, 2: 4\n" /* Type 1, direction X- */,
// AllowedRotations: // AllowedRotations:
7, /* 1, 2, 3 CCW rotations */ 7, /* 1, 2, 3 CCW rotation allowed */
// Merge strategy: // Merge strategy:
cBlockArea::msSpongePrint, cBlockArea::msSpongePrint,
// ShouldExtendFloor:
false,
// DefaultWeight:
200,
// DepthWeight:
"",
// AddWeightIfSame:
0,
}, // Corridor13 }, // Corridor13
@ -2048,10 +2452,22 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
"1: 10, 1, 2: 5\n" /* Type 1, direction X+ */, "1: 10, 1, 2: 5\n" /* Type 1, direction X+ */,
// AllowedRotations: // AllowedRotations:
7, /* 1, 2, 3 CCW rotations */ 7, /* 1, 2, 3 CCW rotation allowed */
// Merge strategy: // Merge strategy:
cBlockArea::msSpongePrint, cBlockArea::msSpongePrint,
// ShouldExtendFloor:
false,
// DefaultWeight:
100,
// DepthWeight:
"",
// AddWeightIfSame:
0,
}, // CorridorCorner5 }, // CorridorCorner5
@ -2170,10 +2586,22 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
"1: 2, 1, 10: 3\n" /* Type 1, direction Z+ */, "1: 2, 1, 10: 3\n" /* Type 1, direction Z+ */,
// AllowedRotations: // AllowedRotations:
7, /* 1, 2, 3 CCW rotations */ 7, /* 1, 2, 3 CCW rotation allowed */
// Merge strategy: // Merge strategy:
cBlockArea::msSpongePrint, cBlockArea::msSpongePrint,
// ShouldExtendFloor:
false,
// DefaultWeight:
100,
// DepthWeight:
"",
// AddWeightIfSame:
0,
}, // CorridorCornerChest5 }, // CorridorCornerChest5
@ -2304,10 +2732,22 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
"1: 8, 8, 2: 5\n" /* Type 1, direction X+ */, "1: 8, 8, 2: 5\n" /* Type 1, direction X+ */,
// AllowedRotations: // AllowedRotations:
7, /* 1, 2, 3 CCW rotations */ 7, /* 1, 2, 3 CCW rotation allowed */
// Merge strategy: // Merge strategy:
cBlockArea::msSpongePrint, cBlockArea::msSpongePrint,
// ShouldExtendFloor:
false,
// DefaultWeight:
100,
// DepthWeight:
"",
// AddWeightIfSame:
0,
}, // CorridorStairs }, // CorridorStairs
@ -2367,11 +2807,11 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
// Level 4 // Level 4
/* z\x* 1111 */ /* z\x* 1111 */
/* * 01234567890123 */ /* * 01234567890123 */
/* 0 */ "aaaaaaaaaaaaaa" /* 0 */ "aabaaaaaaaabaa"
/* 1 */ ".............." /* 1 */ ".............."
/* 2 */ ".............." /* 2 */ ".............."
/* 3 */ ".............." /* 3 */ ".............."
/* 4 */ "aaaaaaaaaaaaaa" /* 4 */ "aabaaaaaaaabaa"
// Level 5 // Level 5
/* z\x* 1111 */ /* z\x* 1111 */
@ -2387,10 +2827,22 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
"1: 13, 1, 2: 5\n" /* Type 1, direction X+ */, "1: 13, 1, 2: 5\n" /* Type 1, direction X+ */,
// AllowedRotations: // AllowedRotations:
7, /* 1, 2, 3 CCW rotations */ 7, /* 1, 2, 3 CCW rotation allowed */
// Merge strategy: // Merge strategy:
cBlockArea::msSpongePrint, cBlockArea::msSpongePrint,
// ShouldExtendFloor:
false,
// DefaultWeight:
100,
// DepthWeight:
"",
// AddWeightIfSame:
0,
}, // DarkCorridor }, // DarkCorridor
@ -2625,10 +3077,22 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
"1: 9, 1, 0: 2\n" /* Type 1, direction Z- */, "1: 9, 1, 0: 2\n" /* Type 1, direction Z- */,
// AllowedRotations: // AllowedRotations:
7, /* 1, 2, 3 CCW rotations */ 7, /* 1, 2, 3 CCW rotation allowed */
// Merge strategy: // Merge strategy:
cBlockArea::msSpongePrint, cBlockArea::msSpongePrint,
// ShouldExtendFloor:
false,
// DefaultWeight:
100,
// DepthWeight:
"",
// AddWeightIfSame:
0,
}, // LavaStaircase }, // LavaStaircase
@ -2938,10 +3402,22 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
"1: 0, 9, 7: 4\n" /* Type 1, direction X- */, "1: 0, 9, 7: 4\n" /* Type 1, direction X- */,
// AllowedRotations: // AllowedRotations:
7, /* 1, 2, 3 CCW rotations */ 7, /* 1, 2, 3 CCW rotation allowed */
// Merge strategy: // Merge strategy:
cBlockArea::msSpongePrint, cBlockArea::msSpongePrint,
// ShouldExtendFloor:
false,
// DefaultWeight:
100,
// DepthWeight:
"",
// AddWeightIfSame:
0,
}, // LavaStaircaseBig }, // LavaStaircaseBig
@ -3200,10 +3676,22 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
"", "",
// AllowedRotations: // AllowedRotations:
7, /* 1, 2, 3 CCW rotations */ 7, /* 1, 2, 3 CCW rotation allowed */
// Merge strategy: // Merge strategy:
cBlockArea::msSpongePrint, cBlockArea::msSpongePrint,
// ShouldExtendFloor:
false,
// DefaultWeight:
100,
// DepthWeight:
"",
// AddWeightIfSame:
0,
}, // LavaStairsBridge }, // LavaStairsBridge
@ -3370,10 +3858,22 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
"1: 0, 1, 6: 4\n" /* Type 1, direction X- */, "1: 0, 1, 6: 4\n" /* Type 1, direction X- */,
// AllowedRotations: // AllowedRotations:
7, /* 1, 2, 3 CCW rotations */ 7, /* 1, 2, 3 CCW rotation allowed */
// Merge strategy: // Merge strategy:
cBlockArea::msSpongePrint, cBlockArea::msSpongePrint,
// ShouldExtendFloor:
false,
// DefaultWeight:
100,
// DepthWeight:
"",
// AddWeightIfSame:
0,
}, // MidStaircase }, // MidStaircase
@ -3497,10 +3997,22 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
"0: 3, 1, 0: 2\n" /* Type 0, direction Z- */, "0: 3, 1, 0: 2\n" /* Type 0, direction Z- */,
// AllowedRotations: // AllowedRotations:
7, /* 1, 2, 3 CCW rotations */ 7, /* 1, 2, 3 CCW rotation allowed */
// Merge strategy: // Merge strategy:
cBlockArea::msSpongePrint, cBlockArea::msSpongePrint,
// ShouldExtendFloor:
false,
// DefaultWeight:
100,
// DepthWeight:
"",
// AddWeightIfSame:
0,
}, // StairsToOpen1 }, // StairsToOpen1
@ -3624,10 +4136,22 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
"0: 3, 1, 0: 2\n" /* Type 0, direction Z- */, "0: 3, 1, 0: 2\n" /* Type 0, direction Z- */,
// AllowedRotations: // AllowedRotations:
7, /* 1, 2, 3 CCW rotations */ 7, /* 1, 2, 3 CCW rotation allowed */
// Merge strategy: // Merge strategy:
cBlockArea::msSpongePrint, cBlockArea::msSpongePrint,
// ShouldExtendFloor:
false,
// DefaultWeight:
100,
// DepthWeight:
"",
// AddWeightIfSame:
0,
}, // StairsToOpen2 }, // StairsToOpen2
@ -3722,10 +4246,22 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
"1: 12, 1, 4: 5\n" /* Type 1, direction X+ */, "1: 12, 1, 4: 5\n" /* Type 1, direction X+ */,
// AllowedRotations: // AllowedRotations:
7, /* 1, 2, 3 CCW rotations */ 7, /* 1, 2, 3 CCW rotation allowed */
// Merge strategy: // Merge strategy:
cBlockArea::msSpongePrint, cBlockArea::msSpongePrint,
// ShouldExtendFloor:
false,
// DefaultWeight:
100,
// DepthWeight:
"",
// AddWeightIfSame:
0,
}, // Tee2x4 }, // Tee2x4
@ -3832,10 +4368,22 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
"1: 12, 1, 6: 5\n" /* Type 1, direction X+ */, "1: 12, 1, 6: 5\n" /* Type 1, direction X+ */,
// AllowedRotations: // AllowedRotations:
7, /* 1, 2, 3 CCW rotations */ 7, /* 1, 2, 3 CCW rotation allowed */
// Merge strategy: // Merge strategy:
cBlockArea::msSpongePrint, cBlockArea::msSpongePrint,
// ShouldExtendFloor:
false,
// DefaultWeight:
100,
// DepthWeight:
"",
// AddWeightIfSame:
0,
}, // Tee4x4 }, // Tee4x4
@ -3921,10 +4469,22 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
"0: 3, 1, 6: 3\n" /* Type 0, direction Z+ */, "0: 3, 1, 6: 3\n" /* Type 0, direction Z+ */,
// AllowedRotations: // AllowedRotations:
7, /* 1, 2, 3 CCW rotations */ 7, /* 1, 2, 3 CCW rotation allowed */
// Merge strategy: // Merge strategy:
cBlockArea::msSpongePrint, cBlockArea::msSpongePrint,
// ShouldExtendFloor:
false,
// DefaultWeight:
100,
// DepthWeight:
"",
// AddWeightIfSame:
-99,
}, // Turret }, // Turret
}; // g_NetherFortPrefabs }; // g_NetherFortPrefabs
@ -4108,10 +4668,22 @@ const cPrefab::sDef g_NetherFortStartingPrefabs[] =
"1: 6, 1, 12: 3\n" /* Type 1, direction Z+ */, "1: 6, 1, 12: 3\n" /* Type 1, direction Z+ */,
// AllowedRotations: // AllowedRotations:
7, /* 1, 2, 3 CCW rotations */ 7, /* 1, 2, 3 CCW rotation allowed */
// Merge strategy: // Merge strategy:
cBlockArea::msSpongePrint, cBlockArea::msSpongePrint,
// ShouldExtendFloor:
false,
// DefaultWeight:
100,
// DepthWeight:
"",
// AddWeightIfSame:
0,
}, // CentralRoom }, // CentralRoom
}; };

View File

@ -111,9 +111,9 @@ void cMonster::SpawnOn(cClientHandle & a_Client)
void cMonster::TickPathFinding() void cMonster::TickPathFinding()
{ {
const int PosX = (int)floor(GetPosX()); const int PosX = POSX_TOINT;
const int PosY = (int)floor(GetPosY()); const int PosY = POSY_TOINT;
const int PosZ = (int)floor(GetPosZ()); const int PosZ = POSZ_TOINT;
m_FinalDestination.y = (double)FindFirstNonAirBlockPosition(m_FinalDestination.x, m_FinalDestination.z); m_FinalDestination.y = (double)FindFirstNonAirBlockPosition(m_FinalDestination.x, m_FinalDestination.z);
@ -148,13 +148,27 @@ void cMonster::TickPathFinding()
BLOCKTYPE BlockAtY = m_World->GetBlock(gCrossCoords[i].x + PosX, PosY, gCrossCoords[i].z + PosZ); BLOCKTYPE BlockAtY = m_World->GetBlock(gCrossCoords[i].x + PosX, PosY, gCrossCoords[i].z + PosZ);
BLOCKTYPE BlockAtYP = m_World->GetBlock(gCrossCoords[i].x + PosX, PosY + 1, gCrossCoords[i].z + PosZ); BLOCKTYPE BlockAtYP = m_World->GetBlock(gCrossCoords[i].x + PosX, PosY + 1, gCrossCoords[i].z + PosZ);
BLOCKTYPE BlockAtYPP = m_World->GetBlock(gCrossCoords[i].x + PosX, PosY + 2, gCrossCoords[i].z + PosZ); BLOCKTYPE BlockAtYPP = m_World->GetBlock(gCrossCoords[i].x + PosX, PosY + 2, gCrossCoords[i].z + PosZ);
BLOCKTYPE BlockAtYM = m_World->GetBlock(gCrossCoords[i].x + PosX, PosY - 1, gCrossCoords[i].z + PosZ); int LowestY = FindFirstNonAirBlockPosition(gCrossCoords[i].x + PosX, gCrossCoords[i].z + PosZ);
BLOCKTYPE BlockAtLowestY = m_World->GetBlock(gCrossCoords[i].x + PosX, LowestY, gCrossCoords[i].z + PosZ);
if ((!cBlockInfo::IsSolid(BlockAtY)) && (!cBlockInfo::IsSolid(BlockAtYP)) && (!IsBlockLava(BlockAtYM)) && (BlockAtY != E_BLOCK_FENCE) && (BlockAtY != E_BLOCK_FENCE_GATE)) if (
(!cBlockInfo::IsSolid(BlockAtY)) &&
(!cBlockInfo::IsSolid(BlockAtYP)) &&
(!IsBlockLava(BlockAtLowestY)) &&
(BlockAtLowestY != E_BLOCK_CACTUS) &&
(PosY - LowestY < FALL_DAMAGE_HEIGHT)
)
{ {
m_PotentialCoordinates.push_back(Vector3d((gCrossCoords[i].x + PosX), PosY, gCrossCoords[i].z + PosZ)); m_PotentialCoordinates.push_back(Vector3d((gCrossCoords[i].x + PosX), PosY, gCrossCoords[i].z + PosZ));
} }
else if ((cBlockInfo::IsSolid(BlockAtY)) && (!cBlockInfo::IsSolid(BlockAtYP)) && (!cBlockInfo::IsSolid(BlockAtYPP)) && (!IsBlockLava(BlockAtYM)) && (BlockAtY != E_BLOCK_FENCE) && (BlockAtY != E_BLOCK_FENCE_GATE)) else if (
(cBlockInfo::IsSolid(BlockAtY)) &&
(BlockAtY != E_BLOCK_CACTUS) &&
(!cBlockInfo::IsSolid(BlockAtYP)) &&
(!cBlockInfo::IsSolid(BlockAtYPP)) &&
(BlockAtY != E_BLOCK_FENCE) &&
(BlockAtY != E_BLOCK_FENCE_GATE)
)
{ {
m_PotentialCoordinates.push_back(Vector3d((gCrossCoords[i].x + PosX), PosY + 1, gCrossCoords[i].z + PosZ)); m_PotentialCoordinates.push_back(Vector3d((gCrossCoords[i].x + PosX), PosY + 1, gCrossCoords[i].z + PosZ));
} }
@ -402,7 +416,7 @@ void cMonster::HandleFalling()
GetWorld()->BroadcastSoundParticleEffect(2006, POSX_TOINT, POSY_TOINT - 1, POSZ_TOINT, Damage /* Used as particle effect speed modifier */); GetWorld()->BroadcastSoundParticleEffect(2006, POSX_TOINT, POSY_TOINT - 1, POSZ_TOINT, Damage /* Used as particle effect speed modifier */);
} }
m_LastGroundHeight = (int)floor(GetPosY()); m_LastGroundHeight = POSY_TOINT;
} }
} }
@ -411,7 +425,7 @@ void cMonster::HandleFalling()
int cMonster::FindFirstNonAirBlockPosition(double a_PosX, double a_PosZ) int cMonster::FindFirstNonAirBlockPosition(double a_PosX, double a_PosZ)
{ {
int PosY = (int)floor(GetPosY()); int PosY = POSY_TOINT;
if (PosY < 0) if (PosY < 0)
PosY = 0; PosY = 0;
@ -969,15 +983,15 @@ void cMonster::HandleDaylightBurning(cChunk & a_Chunk)
return; return;
} }
int RelY = (int)floor(GetPosY()); int RelY = POSY_TOINT;
if ((RelY < 0) || (RelY >= cChunkDef::Height)) if ((RelY < 0) || (RelY >= cChunkDef::Height))
{ {
// Outside the world // Outside the world
return; return;
} }
int RelX = (int)floor(GetPosX()) - GetChunkX() * cChunkDef::Width; int RelX = POSX_TOINT - GetChunkX() * cChunkDef::Width;
int RelZ = (int)floor(GetPosZ()) - GetChunkZ() * cChunkDef::Width; int RelZ = POSZ_TOINT - GetChunkZ() * cChunkDef::Width;
if (!a_Chunk.IsLightValid()) if (!a_Chunk.IsLightValid())
{ {

View File

@ -185,14 +185,14 @@ protected:
inline bool IsNextYPosReachable(int a_PosY) inline bool IsNextYPosReachable(int a_PosY)
{ {
return ( return (
(a_PosY <= (int)floor(GetPosY())) || (a_PosY <= POSY_TOINT) ||
DoesPosYRequireJump(a_PosY) DoesPosYRequireJump(a_PosY)
); );
} }
/** Returns if a monster can reach a given height by jumping */ /** Returns if a monster can reach a given height by jumping */
inline bool DoesPosYRequireJump(int a_PosY) inline bool DoesPosYRequireJump(int a_PosY)
{ {
return ((a_PosY > (int)floor(GetPosY())) && (a_PosY == (int)floor(GetPosY()) + 1)); return ((a_PosY > POSY_TOINT) && (a_PosY == POSY_TOINT + 1));
} }
/** A semi-temporary list to store the traversed coordinates during active pathfinding so we don't visit them again */ /** A semi-temporary list to store the traversed coordinates during active pathfinding so we don't visit them again */

View File

@ -101,7 +101,7 @@ void cSheep::Tick(float a_Dt, cChunk & a_Chunk)
{ {
if (m_World->GetBlock(PosX, PosY, PosZ) == E_BLOCK_GRASS) if (m_World->GetBlock(PosX, PosY, PosZ) == E_BLOCK_GRASS)
{ {
m_World->BroadcastEntityStatus(*this, ENTITY_STATUS_SHEEP_EATING); m_World->BroadcastEntityStatus(*this, esSheepEating);
m_TimeToStopEating = 40; m_TimeToStopEating = 40;
} }
} }

View File

@ -30,7 +30,7 @@ void cVillager::DoTakeDamage(TakeDamageInfo & a_TDI)
{ {
if (m_World->GetTickRandomNumber(5) == 3) if (m_World->GetTickRandomNumber(5) == 3)
{ {
m_World->BroadcastEntityStatus(*this, ENTITY_STATUS_VILLAGER_ANGRY); m_World->BroadcastEntityStatus(*this, esVillagerAngry);
} }
} }
} }

View File

@ -75,12 +75,12 @@ void cWolf::OnRightClicked(cPlayer & a_Player)
SetMaxHealth(20); SetMaxHealth(20);
SetIsTame(true); SetIsTame(true);
SetOwner(a_Player.GetName()); SetOwner(a_Player.GetName());
m_World->BroadcastEntityStatus(*this, ENTITY_STATUS_WOLF_TAMED); m_World->BroadcastEntityStatus(*this, esWolfTamed);
m_World->BroadcastParticleEffect("heart", (float) GetPosX(), (float) GetPosY(), (float) GetPosZ(), 0, 0, 0, 0, 5); m_World->BroadcastParticleEffect("heart", (float) GetPosX(), (float) GetPosY(), (float) GetPosZ(), 0, 0, 0, 0, 5);
} }
else else
{ {
m_World->BroadcastEntityStatus(*this, ENTITY_STATUS_WOLF_TAMING); m_World->BroadcastEntityStatus(*this, esWolfTaming);
m_World->BroadcastParticleEffect("smoke", (float) GetPosX(), (float) GetPosY(), (float) GetPosZ(), 0, 0, 0, 0, 5); m_World->BroadcastParticleEffect("smoke", (float) GetPosX(), (float) GetPosY(), (float) GetPosZ(), 0, 0, 0, 0, 5);
} }
} }

View File

@ -125,6 +125,8 @@ void cProtocol172::DataReceived(const char * a_Data, size_t a_Size)
void cProtocol172::SendAttachEntity(const cEntity & a_Entity, const cEntity * a_Vehicle) void cProtocol172::SendAttachEntity(const cEntity & a_Entity, const cEntity * a_Vehicle)
{ {
ASSERT(m_State == 3); // In game mode?
cPacketizer Pkt(*this, 0x1b); // Attach Entity packet cPacketizer Pkt(*this, 0x1b); // Attach Entity packet
Pkt.WriteInt(a_Entity.GetUniqueID()); Pkt.WriteInt(a_Entity.GetUniqueID());
Pkt.WriteInt((a_Vehicle != NULL) ? a_Vehicle->GetUniqueID() : 0); Pkt.WriteInt((a_Vehicle != NULL) ? a_Vehicle->GetUniqueID() : 0);
@ -137,6 +139,8 @@ void cProtocol172::SendAttachEntity(const cEntity & a_Entity, const cEntity * a_
void cProtocol172::SendBlockAction(int a_BlockX, int a_BlockY, int a_BlockZ, char a_Byte1, char a_Byte2, BLOCKTYPE a_BlockType) void cProtocol172::SendBlockAction(int a_BlockX, int a_BlockY, int a_BlockZ, char a_Byte1, char a_Byte2, BLOCKTYPE a_BlockType)
{ {
ASSERT(m_State == 3); // In game mode?
cPacketizer Pkt(*this, 0x24); // Block Action packet cPacketizer Pkt(*this, 0x24); // Block Action packet
Pkt.WriteInt(a_BlockX); Pkt.WriteInt(a_BlockX);
Pkt.WriteShort(a_BlockY); Pkt.WriteShort(a_BlockY);
@ -152,6 +156,8 @@ void cProtocol172::SendBlockAction(int a_BlockX, int a_BlockY, int a_BlockZ, cha
void cProtocol172::SendBlockBreakAnim(int a_EntityID, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Stage) void cProtocol172::SendBlockBreakAnim(int a_EntityID, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Stage)
{ {
ASSERT(m_State == 3); // In game mode?
cPacketizer Pkt(*this, 0x25); // Block Break Animation packet cPacketizer Pkt(*this, 0x25); // Block Break Animation packet
Pkt.WriteVarInt(a_EntityID); Pkt.WriteVarInt(a_EntityID);
Pkt.WriteInt(a_BlockX); Pkt.WriteInt(a_BlockX);
@ -166,6 +172,8 @@ void cProtocol172::SendBlockBreakAnim(int a_EntityID, int a_BlockX, int a_BlockY
void cProtocol172::SendBlockChange(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) void cProtocol172::SendBlockChange(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
{ {
ASSERT(m_State == 3); // In game mode?
cPacketizer Pkt(*this, 0x23); // Block Change packet cPacketizer Pkt(*this, 0x23); // Block Change packet
Pkt.WriteInt(a_BlockX); Pkt.WriteInt(a_BlockX);
Pkt.WriteByte(a_BlockY); Pkt.WriteByte(a_BlockY);
@ -180,6 +188,8 @@ void cProtocol172::SendBlockChange(int a_BlockX, int a_BlockY, int a_BlockZ, BLO
void cProtocol172::SendBlockChanges(int a_ChunkX, int a_ChunkZ, const sSetBlockVector & a_Changes) void cProtocol172::SendBlockChanges(int a_ChunkX, int a_ChunkZ, const sSetBlockVector & a_Changes)
{ {
ASSERT(m_State == 3); // In game mode?
cPacketizer Pkt(*this, 0x22); // Multi Block Change packet cPacketizer Pkt(*this, 0x22); // Multi Block Change packet
Pkt.WriteInt(a_ChunkX); Pkt.WriteInt(a_ChunkX);
Pkt.WriteInt(a_ChunkZ); Pkt.WriteInt(a_ChunkZ);
@ -199,6 +209,8 @@ void cProtocol172::SendBlockChanges(int a_ChunkX, int a_ChunkZ, const sSetBlockV
void cProtocol172::SendChat(const AString & a_Message) void cProtocol172::SendChat(const AString & a_Message)
{ {
ASSERT(m_State == 3); // In game mode?
cPacketizer Pkt(*this, 0x02); // Chat Message packet cPacketizer Pkt(*this, 0x02); // Chat Message packet
Pkt.WriteString(Printf("{\"text\":\"%s\"}", EscapeString(a_Message).c_str())); Pkt.WriteString(Printf("{\"text\":\"%s\"}", EscapeString(a_Message).c_str()));
} }
@ -209,6 +221,8 @@ void cProtocol172::SendChat(const AString & a_Message)
void cProtocol172::SendChat(const cCompositeChat & a_Message) void cProtocol172::SendChat(const cCompositeChat & a_Message)
{ {
ASSERT(m_State == 3); // In game mode?
// Compose the complete Json string to send: // Compose the complete Json string to send:
Json::Value msg; Json::Value msg;
msg["text"] = ""; // The client crashes without this msg["text"] = ""; // The client crashes without this
@ -281,6 +295,8 @@ void cProtocol172::SendChat(const cCompositeChat & a_Message)
void cProtocol172::SendChunkData(int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer) void cProtocol172::SendChunkData(int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer)
{ {
ASSERT(m_State == 3); // In game mode?
// Serialize first, before creating the Packetizer (the packetizer locks a CS) // Serialize first, before creating the Packetizer (the packetizer locks a CS)
// This contains the flags and bitmasks, too // This contains the flags and bitmasks, too
const AString & ChunkData = a_Serializer.Serialize(cChunkDataSerializer::RELEASE_1_3_2); const AString & ChunkData = a_Serializer.Serialize(cChunkDataSerializer::RELEASE_1_3_2);
@ -297,6 +313,8 @@ void cProtocol172::SendChunkData(int a_ChunkX, int a_ChunkZ, cChunkDataSerialize
void cProtocol172::SendCollectPickup(const cPickup & a_Pickup, const cPlayer & a_Player) void cProtocol172::SendCollectPickup(const cPickup & a_Pickup, const cPlayer & a_Player)
{ {
ASSERT(m_State == 3); // In game mode?
cPacketizer Pkt(*this, 0x0d); // Collect Item packet cPacketizer Pkt(*this, 0x0d); // Collect Item packet
Pkt.WriteInt(a_Pickup.GetUniqueID()); Pkt.WriteInt(a_Pickup.GetUniqueID());
Pkt.WriteInt(a_Player.GetUniqueID()); Pkt.WriteInt(a_Player.GetUniqueID());
@ -308,6 +326,8 @@ void cProtocol172::SendCollectPickup(const cPickup & a_Pickup, const cPlayer & a
void cProtocol172::SendDestroyEntity(const cEntity & a_Entity) void cProtocol172::SendDestroyEntity(const cEntity & a_Entity)
{ {
ASSERT(m_State == 3); // In game mode?
cPacketizer Pkt(*this, 0x13); // Destroy Entities packet cPacketizer Pkt(*this, 0x13); // Destroy Entities packet
Pkt.WriteByte(1); Pkt.WriteByte(1);
Pkt.WriteInt(a_Entity.GetUniqueID()); Pkt.WriteInt(a_Entity.GetUniqueID());
@ -344,6 +364,8 @@ void cProtocol172::SendDisconnect(const AString & a_Reason)
void cProtocol172::SendEditSign(int a_BlockX, int a_BlockY, int a_BlockZ) void cProtocol172::SendEditSign(int a_BlockX, int a_BlockY, int a_BlockZ)
{ {
ASSERT(m_State == 3); // In game mode?
cPacketizer Pkt(*this, 0x36); // Sign Editor Open packet cPacketizer Pkt(*this, 0x36); // Sign Editor Open packet
Pkt.WriteInt(a_BlockX); Pkt.WriteInt(a_BlockX);
Pkt.WriteInt(a_BlockY); Pkt.WriteInt(a_BlockY);
@ -356,6 +378,8 @@ void cProtocol172::SendEditSign(int a_BlockX, int a_BlockY, int a_BlockZ)
void cProtocol172::SendEntityEffect(const cEntity & a_Entity, int a_EffectID, int a_Amplifier, short a_Duration) void cProtocol172::SendEntityEffect(const cEntity & a_Entity, int a_EffectID, int a_Amplifier, short a_Duration)
{ {
ASSERT(m_State == 3); // In game mode?
cPacketizer Pkt(*this, 0x1D); // Entity Effect packet cPacketizer Pkt(*this, 0x1D); // Entity Effect packet
Pkt.WriteInt(a_Entity.GetUniqueID()); Pkt.WriteInt(a_Entity.GetUniqueID());
Pkt.WriteByte(a_EffectID); Pkt.WriteByte(a_EffectID);
@ -369,6 +393,8 @@ void cProtocol172::SendEntityEffect(const cEntity & a_Entity, int a_EffectID, in
void cProtocol172::SendEntityEquipment(const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item) void cProtocol172::SendEntityEquipment(const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item)
{ {
ASSERT(m_State == 3); // In game mode?
cPacketizer Pkt(*this, 0x04); // Entity Equipment packet cPacketizer Pkt(*this, 0x04); // Entity Equipment packet
Pkt.WriteInt(a_Entity.GetUniqueID()); Pkt.WriteInt(a_Entity.GetUniqueID());
Pkt.WriteShort(a_SlotNum); Pkt.WriteShort(a_SlotNum);
@ -381,6 +407,8 @@ void cProtocol172::SendEntityEquipment(const cEntity & a_Entity, short a_SlotNum
void cProtocol172::SendEntityHeadLook(const cEntity & a_Entity) void cProtocol172::SendEntityHeadLook(const cEntity & a_Entity)
{ {
ASSERT(m_State == 3); // In game mode?
cPacketizer Pkt(*this, 0x19); // Entity Head Look packet cPacketizer Pkt(*this, 0x19); // Entity Head Look packet
Pkt.WriteInt(a_Entity.GetUniqueID()); Pkt.WriteInt(a_Entity.GetUniqueID());
Pkt.WriteByteAngle(a_Entity.GetHeadYaw()); Pkt.WriteByteAngle(a_Entity.GetHeadYaw());
@ -392,6 +420,8 @@ void cProtocol172::SendEntityHeadLook(const cEntity & a_Entity)
void cProtocol172::SendEntityLook(const cEntity & a_Entity) void cProtocol172::SendEntityLook(const cEntity & a_Entity)
{ {
ASSERT(m_State == 3); // In game mode?
cPacketizer Pkt(*this, 0x16); // Entity Look packet cPacketizer Pkt(*this, 0x16); // Entity Look packet
Pkt.WriteInt(a_Entity.GetUniqueID()); Pkt.WriteInt(a_Entity.GetUniqueID());
Pkt.WriteByteAngle(a_Entity.GetYaw()); Pkt.WriteByteAngle(a_Entity.GetYaw());
@ -404,6 +434,8 @@ void cProtocol172::SendEntityLook(const cEntity & a_Entity)
void cProtocol172::SendEntityMetadata(const cEntity & a_Entity) void cProtocol172::SendEntityMetadata(const cEntity & a_Entity)
{ {
ASSERT(m_State == 3); // In game mode?
cPacketizer Pkt(*this, 0x1c); // Entity Metadata packet cPacketizer Pkt(*this, 0x1c); // Entity Metadata packet
Pkt.WriteInt(a_Entity.GetUniqueID()); Pkt.WriteInt(a_Entity.GetUniqueID());
Pkt.WriteEntityMetadata(a_Entity); Pkt.WriteEntityMetadata(a_Entity);
@ -416,6 +448,8 @@ void cProtocol172::SendEntityMetadata(const cEntity & a_Entity)
void cProtocol172::SendEntityProperties(const cEntity & a_Entity) void cProtocol172::SendEntityProperties(const cEntity & a_Entity)
{ {
ASSERT(m_State == 3); // In game mode?
cPacketizer Pkt(*this, 0x20); // Entity Properties packet cPacketizer Pkt(*this, 0x20); // Entity Properties packet
Pkt.WriteInt(a_Entity.GetUniqueID()); Pkt.WriteInt(a_Entity.GetUniqueID());
Pkt.WriteEntityProperties(a_Entity); Pkt.WriteEntityProperties(a_Entity);
@ -427,6 +461,8 @@ void cProtocol172::SendEntityProperties(const cEntity & a_Entity)
void cProtocol172::SendEntityRelMove(const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ) void cProtocol172::SendEntityRelMove(const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ)
{ {
ASSERT(m_State == 3); // In game mode?
cPacketizer Pkt(*this, 0x15); // Entity Relative Move packet cPacketizer Pkt(*this, 0x15); // Entity Relative Move packet
Pkt.WriteInt(a_Entity.GetUniqueID()); Pkt.WriteInt(a_Entity.GetUniqueID());
Pkt.WriteByte(a_RelX); Pkt.WriteByte(a_RelX);
@ -440,6 +476,8 @@ void cProtocol172::SendEntityRelMove(const cEntity & a_Entity, char a_RelX, char
void cProtocol172::SendEntityRelMoveLook(const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ) void cProtocol172::SendEntityRelMoveLook(const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ)
{ {
ASSERT(m_State == 3); // In game mode?
cPacketizer Pkt(*this, 0x17); // Entity Look And Relative Move packet cPacketizer Pkt(*this, 0x17); // Entity Look And Relative Move packet
Pkt.WriteInt(a_Entity.GetUniqueID()); Pkt.WriteInt(a_Entity.GetUniqueID());
Pkt.WriteByte(a_RelX); Pkt.WriteByte(a_RelX);
@ -455,6 +493,8 @@ void cProtocol172::SendEntityRelMoveLook(const cEntity & a_Entity, char a_RelX,
void cProtocol172::SendEntityStatus(const cEntity & a_Entity, char a_Status) void cProtocol172::SendEntityStatus(const cEntity & a_Entity, char a_Status)
{ {
ASSERT(m_State == 3); // In game mode?
cPacketizer Pkt(*this, 0x1a); // Entity Status packet cPacketizer Pkt(*this, 0x1a); // Entity Status packet
Pkt.WriteInt(a_Entity.GetUniqueID()); Pkt.WriteInt(a_Entity.GetUniqueID());
Pkt.WriteChar(a_Status); Pkt.WriteChar(a_Status);
@ -466,6 +506,8 @@ void cProtocol172::SendEntityStatus(const cEntity & a_Entity, char a_Status)
void cProtocol172::SendEntityVelocity(const cEntity & a_Entity) void cProtocol172::SendEntityVelocity(const cEntity & a_Entity)
{ {
ASSERT(m_State == 3); // In game mode?
cPacketizer Pkt(*this, 0x12); // Entity Velocity packet cPacketizer Pkt(*this, 0x12); // Entity Velocity packet
Pkt.WriteInt(a_Entity.GetUniqueID()); Pkt.WriteInt(a_Entity.GetUniqueID());
// 400 = 8000 / 20 ... Conversion from our speed in m/s to 8000 m/tick // 400 = 8000 / 20 ... Conversion from our speed in m/s to 8000 m/tick
@ -480,6 +522,8 @@ void cProtocol172::SendEntityVelocity(const cEntity & a_Entity)
void cProtocol172::SendExplosion(double a_BlockX, double a_BlockY, double a_BlockZ, float a_Radius, const cVector3iArray & a_BlocksAffected, const Vector3d & a_PlayerMotion) void cProtocol172::SendExplosion(double a_BlockX, double a_BlockY, double a_BlockZ, float a_Radius, const cVector3iArray & a_BlocksAffected, const Vector3d & a_PlayerMotion)
{ {
ASSERT(m_State == 3); // In game mode?
cPacketizer Pkt(*this, 0x27); // Explosion packet cPacketizer Pkt(*this, 0x27); // Explosion packet
Pkt.WriteFloat((float)a_BlockX); Pkt.WriteFloat((float)a_BlockX);
Pkt.WriteFloat((float)a_BlockY); Pkt.WriteFloat((float)a_BlockY);
@ -503,6 +547,8 @@ void cProtocol172::SendExplosion(double a_BlockX, double a_BlockY, double a_Bloc
void cProtocol172::SendGameMode(eGameMode a_GameMode) void cProtocol172::SendGameMode(eGameMode a_GameMode)
{ {
ASSERT(m_State == 3); // In game mode?
cPacketizer Pkt(*this, 0x2b); // Change Game State packet cPacketizer Pkt(*this, 0x2b); // Change Game State packet
Pkt.WriteByte(3); // Reason: Change game mode Pkt.WriteByte(3); // Reason: Change game mode
Pkt.WriteFloat((float)a_GameMode); Pkt.WriteFloat((float)a_GameMode);
@ -514,6 +560,8 @@ void cProtocol172::SendGameMode(eGameMode a_GameMode)
void cProtocol172::SendHealth(void) void cProtocol172::SendHealth(void)
{ {
ASSERT(m_State == 3); // In game mode?
cPacketizer Pkt(*this, 0x06); // Update Health packet cPacketizer Pkt(*this, 0x06); // Update Health packet
Pkt.WriteFloat((float)m_Client->GetPlayer()->GetHealth()); Pkt.WriteFloat((float)m_Client->GetPlayer()->GetHealth());
Pkt.WriteShort(m_Client->GetPlayer()->GetFoodLevel()); Pkt.WriteShort(m_Client->GetPlayer()->GetFoodLevel());
@ -526,6 +574,8 @@ void cProtocol172::SendHealth(void)
void cProtocol172::SendInventorySlot(char a_WindowID, short a_SlotNum, const cItem & a_Item) void cProtocol172::SendInventorySlot(char a_WindowID, short a_SlotNum, const cItem & a_Item)
{ {
ASSERT(m_State == 3); // In game mode?
cPacketizer Pkt(*this, 0x2f); // Set Slot packet cPacketizer Pkt(*this, 0x2f); // Set Slot packet
Pkt.WriteChar(a_WindowID); Pkt.WriteChar(a_WindowID);
Pkt.WriteShort(a_SlotNum); Pkt.WriteShort(a_SlotNum);
@ -598,6 +648,8 @@ void cProtocol172::SendLoginSuccess(void)
void cProtocol172::SendPaintingSpawn(const cPainting & a_Painting) void cProtocol172::SendPaintingSpawn(const cPainting & a_Painting)
{ {
ASSERT(m_State == 3); // In game mode?
cPacketizer Pkt(*this, 0x10); // Spawn Painting packet cPacketizer Pkt(*this, 0x10); // Spawn Painting packet
Pkt.WriteVarInt(a_Painting.GetUniqueID()); Pkt.WriteVarInt(a_Painting.GetUniqueID());
Pkt.WriteString(a_Painting.GetName().c_str()); Pkt.WriteString(a_Painting.GetName().c_str());
@ -613,6 +665,8 @@ void cProtocol172::SendPaintingSpawn(const cPainting & a_Painting)
void cProtocol172::SendMapColumn(int a_ID, int a_X, int a_Y, const Byte * a_Colors, unsigned int a_Length) void cProtocol172::SendMapColumn(int a_ID, int a_X, int a_Y, const Byte * a_Colors, unsigned int a_Length)
{ {
ASSERT(m_State == 3); // In game mode?
cPacketizer Pkt(*this, 0x34); cPacketizer Pkt(*this, 0x34);
Pkt.WriteVarInt(a_ID); Pkt.WriteVarInt(a_ID);
Pkt.WriteShort (3 + a_Length); Pkt.WriteShort (3 + a_Length);
@ -633,6 +687,8 @@ void cProtocol172::SendMapColumn(int a_ID, int a_X, int a_Y, const Byte * a_Colo
void cProtocol172::SendMapDecorators(int a_ID, const cMapDecoratorList & a_Decorators) void cProtocol172::SendMapDecorators(int a_ID, const cMapDecoratorList & a_Decorators)
{ {
ASSERT(m_State == 3); // In game mode?
cPacketizer Pkt(*this, 0x34); cPacketizer Pkt(*this, 0x34);
Pkt.WriteVarInt(a_ID); Pkt.WriteVarInt(a_ID);
Pkt.WriteShort (1 + (3 * a_Decorators.size())); Pkt.WriteShort (1 + (3 * a_Decorators.size()));
@ -653,6 +709,8 @@ void cProtocol172::SendMapDecorators(int a_ID, const cMapDecoratorList & a_Decor
void cProtocol172::SendMapInfo(int a_ID, unsigned int a_Scale) void cProtocol172::SendMapInfo(int a_ID, unsigned int a_Scale)
{ {
ASSERT(m_State == 3); // In game mode?
cPacketizer Pkt(*this, 0x34); cPacketizer Pkt(*this, 0x34);
Pkt.WriteVarInt(a_ID); Pkt.WriteVarInt(a_ID);
Pkt.WriteShort (2); Pkt.WriteShort (2);
@ -668,6 +726,8 @@ void cProtocol172::SendMapInfo(int a_ID, unsigned int a_Scale)
void cProtocol172::SendPickupSpawn(const cPickup & a_Pickup) void cProtocol172::SendPickupSpawn(const cPickup & a_Pickup)
{ {
ASSERT(m_State == 3); // In game mode?
{ {
cPacketizer Pkt(*this, 0x0e); // Spawn Object packet cPacketizer Pkt(*this, 0x0e); // Spawn Object packet
Pkt.WriteVarInt(a_Pickup.GetUniqueID()); Pkt.WriteVarInt(a_Pickup.GetUniqueID());
@ -694,6 +754,8 @@ void cProtocol172::SendPickupSpawn(const cPickup & a_Pickup)
void cProtocol172::SendPlayerAbilities(void) void cProtocol172::SendPlayerAbilities(void)
{ {
ASSERT(m_State == 3); // In game mode?
cPacketizer Pkt(*this, 0x39); // Player Abilities packet cPacketizer Pkt(*this, 0x39); // Player Abilities packet
Byte Flags = 0; Byte Flags = 0;
if (m_Client->GetPlayer()->IsGameModeCreative()) if (m_Client->GetPlayer()->IsGameModeCreative())
@ -720,6 +782,8 @@ void cProtocol172::SendPlayerAbilities(void)
void cProtocol172::SendEntityAnimation(const cEntity & a_Entity, char a_Animation) void cProtocol172::SendEntityAnimation(const cEntity & a_Entity, char a_Animation)
{ {
ASSERT(m_State == 3); // In game mode?
cPacketizer Pkt(*this, 0x0b); // Animation packet cPacketizer Pkt(*this, 0x0b); // Animation packet
Pkt.WriteVarInt(a_Entity.GetUniqueID()); Pkt.WriteVarInt(a_Entity.GetUniqueID());
Pkt.WriteChar(a_Animation); Pkt.WriteChar(a_Animation);
@ -731,6 +795,8 @@ void cProtocol172::SendEntityAnimation(const cEntity & a_Entity, char a_Animatio
void cProtocol172::SendParticleEffect(const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmmount) void cProtocol172::SendParticleEffect(const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmmount)
{ {
ASSERT(m_State == 3); // In game mode?
cPacketizer Pkt(*this, 0x2A); cPacketizer Pkt(*this, 0x2A);
Pkt.WriteString(a_ParticleName); Pkt.WriteString(a_ParticleName);
Pkt.WriteFloat(a_SrcX); Pkt.WriteFloat(a_SrcX);
@ -749,6 +815,8 @@ void cProtocol172::SendParticleEffect(const AString & a_ParticleName, float a_Sr
void cProtocol172::SendPlayerListItem(const cPlayer & a_Player, bool a_IsOnline) void cProtocol172::SendPlayerListItem(const cPlayer & a_Player, bool a_IsOnline)
{ {
ASSERT(m_State == 3); // In game mode?
cPacketizer Pkt(*this, 0x38); // Playerlist Item packet cPacketizer Pkt(*this, 0x38); // Playerlist Item packet
Pkt.WriteString(a_Player.GetName()); Pkt.WriteString(a_Player.GetName());
Pkt.WriteBool(a_IsOnline); Pkt.WriteBool(a_IsOnline);
@ -761,6 +829,8 @@ void cProtocol172::SendPlayerListItem(const cPlayer & a_Player, bool a_IsOnline)
void cProtocol172::SendPlayerMaxSpeed(void) void cProtocol172::SendPlayerMaxSpeed(void)
{ {
ASSERT(m_State == 3); // In game mode?
cPacketizer Pkt(*this, 0x20); // Entity Properties cPacketizer Pkt(*this, 0x20); // Entity Properties
Pkt.WriteInt(m_Client->GetPlayer()->GetUniqueID()); Pkt.WriteInt(m_Client->GetPlayer()->GetUniqueID());
Pkt.WriteInt(1); // Count Pkt.WriteInt(1); // Count
@ -787,6 +857,8 @@ void cProtocol172::SendPlayerMaxSpeed(void)
void cProtocol172::SendPlayerMoveLook(void) void cProtocol172::SendPlayerMoveLook(void)
{ {
ASSERT(m_State == 3); // In game mode?
cPacketizer Pkt(*this, 0x08); // Player Position And Look packet cPacketizer Pkt(*this, 0x08); // Player Position And Look packet
Pkt.WriteDouble(m_Client->GetPlayer()->GetPosX()); Pkt.WriteDouble(m_Client->GetPlayer()->GetPosX());
@ -816,6 +888,8 @@ void cProtocol172::SendPlayerPosition(void)
void cProtocol172::SendPlayerSpawn(const cPlayer & a_Player) void cProtocol172::SendPlayerSpawn(const cPlayer & a_Player)
{ {
ASSERT(m_State == 3); // In game mode?
// Called to spawn another player for the client // Called to spawn another player for the client
cPacketizer Pkt(*this, 0x0c); // Spawn Player packet cPacketizer Pkt(*this, 0x0c); // Spawn Player packet
Pkt.WriteVarInt(a_Player.GetUniqueID()); Pkt.WriteVarInt(a_Player.GetUniqueID());
@ -839,6 +913,8 @@ void cProtocol172::SendPlayerSpawn(const cPlayer & a_Player)
void cProtocol172::SendPluginMessage(const AString & a_Channel, const AString & a_Message) void cProtocol172::SendPluginMessage(const AString & a_Channel, const AString & a_Message)
{ {
ASSERT(m_State == 3); // In game mode?
cPacketizer Pkt(*this, 0x3f); cPacketizer Pkt(*this, 0x3f);
Pkt.WriteString(a_Channel); Pkt.WriteString(a_Channel);
Pkt.WriteShort((short)a_Message.size()); Pkt.WriteShort((short)a_Message.size());
@ -851,7 +927,9 @@ void cProtocol172::SendPluginMessage(const AString & a_Channel, const AString &
void cProtocol172::SendRemoveEntityEffect(const cEntity & a_Entity, int a_EffectID) void cProtocol172::SendRemoveEntityEffect(const cEntity & a_Entity, int a_EffectID)
{ {
cPacketizer Pkt(*this, 0x1E); ASSERT(m_State == 3); // In game mode?
cPacketizer Pkt(*this, 0x1e);
Pkt.WriteInt(a_Entity.GetUniqueID()); Pkt.WriteInt(a_Entity.GetUniqueID());
Pkt.WriteByte(a_EffectID); Pkt.WriteByte(a_EffectID);
} }
@ -875,7 +953,9 @@ void cProtocol172::SendRespawn(void)
void cProtocol172::SendExperience (void) void cProtocol172::SendExperience (void)
{ {
cPacketizer Pkt(*this, 0x1F); //Experience Packet ASSERT(m_State == 3); // In game mode?
cPacketizer Pkt(*this, 0x1f); // Experience Packet
Pkt.WriteFloat(m_Client->GetPlayer()->GetXpPercentage()); Pkt.WriteFloat(m_Client->GetPlayer()->GetXpPercentage());
Pkt.WriteShort(m_Client->GetPlayer()->GetXpLevel()); Pkt.WriteShort(m_Client->GetPlayer()->GetXpLevel());
Pkt.WriteShort(m_Client->GetPlayer()->GetCurrentXp()); Pkt.WriteShort(m_Client->GetPlayer()->GetCurrentXp());
@ -887,6 +967,8 @@ void cProtocol172::SendExperience (void)
void cProtocol172::SendExperienceOrb(const cExpOrb & a_ExpOrb) void cProtocol172::SendExperienceOrb(const cExpOrb & a_ExpOrb)
{ {
ASSERT(m_State == 3); // In game mode?
cPacketizer Pkt(*this, 0x11); cPacketizer Pkt(*this, 0x11);
Pkt.WriteVarInt(a_ExpOrb.GetUniqueID()); Pkt.WriteVarInt(a_ExpOrb.GetUniqueID());
Pkt.WriteInt((int) a_ExpOrb.GetPosX()); Pkt.WriteInt((int) a_ExpOrb.GetPosX());
@ -901,7 +983,9 @@ void cProtocol172::SendExperienceOrb(const cExpOrb & a_ExpOrb)
void cProtocol172::SendScoreboardObjective(const AString & a_Name, const AString & a_DisplayName, Byte a_Mode) void cProtocol172::SendScoreboardObjective(const AString & a_Name, const AString & a_DisplayName, Byte a_Mode)
{ {
cPacketizer Pkt(*this, 0x3B); ASSERT(m_State == 3); // In game mode?
cPacketizer Pkt(*this, 0x3b);
Pkt.WriteString(a_Name); Pkt.WriteString(a_Name);
Pkt.WriteString(a_DisplayName); Pkt.WriteString(a_DisplayName);
Pkt.WriteByte(a_Mode); Pkt.WriteByte(a_Mode);
@ -913,7 +997,9 @@ void cProtocol172::SendScoreboardObjective(const AString & a_Name, const AString
void cProtocol172::SendScoreUpdate(const AString & a_Objective, const AString & a_Player, cObjective::Score a_Score, Byte a_Mode) void cProtocol172::SendScoreUpdate(const AString & a_Objective, const AString & a_Player, cObjective::Score a_Score, Byte a_Mode)
{ {
cPacketizer Pkt(*this, 0x3C); ASSERT(m_State == 3); // In game mode?
cPacketizer Pkt(*this, 0x3c);
Pkt.WriteString(a_Player); Pkt.WriteString(a_Player);
Pkt.WriteByte(a_Mode); Pkt.WriteByte(a_Mode);
@ -930,7 +1016,9 @@ void cProtocol172::SendScoreUpdate(const AString & a_Objective, const AString &
void cProtocol172::SendDisplayObjective(const AString & a_Objective, cScoreboard::eDisplaySlot a_Display) void cProtocol172::SendDisplayObjective(const AString & a_Objective, cScoreboard::eDisplaySlot a_Display)
{ {
cPacketizer Pkt(*this, 0x3D); ASSERT(m_State == 3); // In game mode?
cPacketizer Pkt(*this, 0x3d);
Pkt.WriteByte((int) a_Display); Pkt.WriteByte((int) a_Display);
Pkt.WriteString(a_Objective); Pkt.WriteString(a_Objective);
} }
@ -941,6 +1029,8 @@ void cProtocol172::SendDisplayObjective(const AString & a_Objective, cScoreboard
void cProtocol172::SendSoundEffect(const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch) // a_Src coords are Block * 8 void cProtocol172::SendSoundEffect(const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch) // a_Src coords are Block * 8
{ {
ASSERT(m_State == 3); // In game mode?
cPacketizer Pkt(*this, 0x29); // Sound Effect packet cPacketizer Pkt(*this, 0x29); // Sound Effect packet
Pkt.WriteString(a_SoundName); Pkt.WriteString(a_SoundName);
Pkt.WriteInt(a_SrcX); Pkt.WriteInt(a_SrcX);
@ -956,6 +1046,8 @@ void cProtocol172::SendSoundEffect(const AString & a_SoundName, int a_SrcX, int
void cProtocol172::SendSoundParticleEffect(int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data) void cProtocol172::SendSoundParticleEffect(int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data)
{ {
ASSERT(m_State == 3); // In game mode?
cPacketizer Pkt(*this, 0x28); // Effect packet cPacketizer Pkt(*this, 0x28); // Effect packet
Pkt.WriteInt(a_EffectID); Pkt.WriteInt(a_EffectID);
Pkt.WriteInt(a_SrcX); Pkt.WriteInt(a_SrcX);
@ -971,6 +1063,8 @@ void cProtocol172::SendSoundParticleEffect(int a_EffectID, int a_SrcX, int a_Src
void cProtocol172::SendSpawnFallingBlock(const cFallingBlock & a_FallingBlock) void cProtocol172::SendSpawnFallingBlock(const cFallingBlock & a_FallingBlock)
{ {
ASSERT(m_State == 3); // In game mode?
cPacketizer Pkt(*this, 0x0e); // Spawn Object packet cPacketizer Pkt(*this, 0x0e); // Spawn Object packet
Pkt.WriteVarInt(a_FallingBlock.GetUniqueID()); Pkt.WriteVarInt(a_FallingBlock.GetUniqueID());
Pkt.WriteByte(70); // Falling block Pkt.WriteByte(70); // Falling block
@ -991,6 +1085,8 @@ void cProtocol172::SendSpawnFallingBlock(const cFallingBlock & a_FallingBlock)
void cProtocol172::SendSpawnMob(const cMonster & a_Mob) void cProtocol172::SendSpawnMob(const cMonster & a_Mob)
{ {
ASSERT(m_State == 3); // In game mode?
cPacketizer Pkt(*this, 0x0f); // Spawn Mob packet cPacketizer Pkt(*this, 0x0f); // Spawn Mob packet
Pkt.WriteVarInt(a_Mob.GetUniqueID()); Pkt.WriteVarInt(a_Mob.GetUniqueID());
Pkt.WriteByte((Byte)a_Mob.GetMobType()); Pkt.WriteByte((Byte)a_Mob.GetMobType());
@ -1013,6 +1109,8 @@ void cProtocol172::SendSpawnMob(const cMonster & a_Mob)
void cProtocol172::SendSpawnObject(const cEntity & a_Entity, char a_ObjectType, int a_ObjectData, Byte a_Yaw, Byte a_Pitch) void cProtocol172::SendSpawnObject(const cEntity & a_Entity, char a_ObjectType, int a_ObjectData, Byte a_Yaw, Byte a_Pitch)
{ {
ASSERT(m_State == 3); // In game mode?
cPacketizer Pkt(*this, 0xe); // Spawn Object packet cPacketizer Pkt(*this, 0xe); // Spawn Object packet
Pkt.WriteVarInt(a_Entity.GetUniqueID()); Pkt.WriteVarInt(a_Entity.GetUniqueID());
Pkt.WriteByte(a_ObjectType); Pkt.WriteByte(a_ObjectType);
@ -1036,6 +1134,8 @@ void cProtocol172::SendSpawnObject(const cEntity & a_Entity, char a_ObjectType,
void cProtocol172::SendSpawnVehicle(const cEntity & a_Vehicle, char a_VehicleType, char a_VehicleSubType) void cProtocol172::SendSpawnVehicle(const cEntity & a_Vehicle, char a_VehicleType, char a_VehicleSubType)
{ {
ASSERT(m_State == 3); // In game mode?
cPacketizer Pkt(*this, 0xe); // Spawn Object packet cPacketizer Pkt(*this, 0xe); // Spawn Object packet
Pkt.WriteVarInt(a_Vehicle.GetUniqueID()); Pkt.WriteVarInt(a_Vehicle.GetUniqueID());
Pkt.WriteByte(a_VehicleType); Pkt.WriteByte(a_VehicleType);
@ -1059,6 +1159,8 @@ void cProtocol172::SendSpawnVehicle(const cEntity & a_Vehicle, char a_VehicleTyp
void cProtocol172::SendTabCompletionResults(const AStringVector & a_Results) void cProtocol172::SendTabCompletionResults(const AStringVector & a_Results)
{ {
ASSERT(m_State == 3); // In game mode?
cPacketizer Pkt(*this, 0x3a); // Tab-Complete packet cPacketizer Pkt(*this, 0x3a); // Tab-Complete packet
Pkt.WriteVarInt(a_Results.size()); Pkt.WriteVarInt(a_Results.size());
@ -1074,6 +1176,8 @@ void cProtocol172::SendTabCompletionResults(const AStringVector & a_Results)
void cProtocol172::SendTeleportEntity(const cEntity & a_Entity) void cProtocol172::SendTeleportEntity(const cEntity & a_Entity)
{ {
ASSERT(m_State == 3); // In game mode?
cPacketizer Pkt(*this, 0x18); cPacketizer Pkt(*this, 0x18);
Pkt.WriteInt(a_Entity.GetUniqueID()); Pkt.WriteInt(a_Entity.GetUniqueID());
Pkt.WriteFPInt(a_Entity.GetPosX()); Pkt.WriteFPInt(a_Entity.GetPosX());
@ -1089,6 +1193,8 @@ void cProtocol172::SendTeleportEntity(const cEntity & a_Entity)
void cProtocol172::SendThunderbolt(int a_BlockX, int a_BlockY, int a_BlockZ) void cProtocol172::SendThunderbolt(int a_BlockX, int a_BlockY, int a_BlockZ)
{ {
ASSERT(m_State == 3); // In game mode?
cPacketizer Pkt(*this, 0x2c); // Spawn Global Entity packet cPacketizer Pkt(*this, 0x2c); // Spawn Global Entity packet
Pkt.WriteVarInt(0); // EntityID = 0, always Pkt.WriteVarInt(0); // EntityID = 0, always
Pkt.WriteByte(1); // Type = Thunderbolt Pkt.WriteByte(1); // Type = Thunderbolt
@ -1103,6 +1209,8 @@ void cProtocol172::SendThunderbolt(int a_BlockX, int a_BlockY, int a_BlockZ)
void cProtocol172::SendTimeUpdate(Int64 a_WorldAge, Int64 a_TimeOfDay) void cProtocol172::SendTimeUpdate(Int64 a_WorldAge, Int64 a_TimeOfDay)
{ {
ASSERT(m_State == 3); // In game mode?
cPacketizer Pkt(*this, 0x03); cPacketizer Pkt(*this, 0x03);
Pkt.WriteInt64(a_WorldAge); Pkt.WriteInt64(a_WorldAge);
Pkt.WriteInt64(a_TimeOfDay); Pkt.WriteInt64(a_TimeOfDay);
@ -1114,6 +1222,8 @@ void cProtocol172::SendTimeUpdate(Int64 a_WorldAge, Int64 a_TimeOfDay)
void cProtocol172::SendUnloadChunk(int a_ChunkX, int a_ChunkZ) void cProtocol172::SendUnloadChunk(int a_ChunkX, int a_ChunkZ)
{ {
ASSERT(m_State == 3); // In game mode?
cPacketizer Pkt(*this, 0x21); // Chunk Data packet cPacketizer Pkt(*this, 0x21); // Chunk Data packet
Pkt.WriteInt(a_ChunkX); Pkt.WriteInt(a_ChunkX);
Pkt.WriteInt(a_ChunkZ); Pkt.WriteInt(a_ChunkZ);
@ -1128,6 +1238,8 @@ void cProtocol172::SendUnloadChunk(int a_ChunkX, int a_ChunkZ)
void cProtocol172::SendUpdateBlockEntity(cBlockEntity & a_BlockEntity) void cProtocol172::SendUpdateBlockEntity(cBlockEntity & a_BlockEntity)
{ {
ASSERT(m_State == 3); // In game mode?
cPacketizer Pkt(*this, 0x35); // Update tile entity packet cPacketizer Pkt(*this, 0x35); // Update tile entity packet
Pkt.WriteInt(a_BlockEntity.GetPosX()); Pkt.WriteInt(a_BlockEntity.GetPosX());
Pkt.WriteShort(a_BlockEntity.GetPosY()); Pkt.WriteShort(a_BlockEntity.GetPosY());
@ -1153,6 +1265,8 @@ void cProtocol172::SendUpdateBlockEntity(cBlockEntity & a_BlockEntity)
void cProtocol172::SendUpdateSign(int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4) void cProtocol172::SendUpdateSign(int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4)
{ {
ASSERT(m_State == 3); // In game mode?
cPacketizer Pkt(*this, 0x33); cPacketizer Pkt(*this, 0x33);
Pkt.WriteInt(a_BlockX); Pkt.WriteInt(a_BlockX);
Pkt.WriteShort((short)a_BlockY); Pkt.WriteShort((short)a_BlockY);
@ -1170,6 +1284,8 @@ void cProtocol172::SendUpdateSign(int a_BlockX, int a_BlockY, int a_BlockZ, cons
void cProtocol172::SendUseBed(const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ) void cProtocol172::SendUseBed(const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ)
{ {
ASSERT(m_State == 3); // In game mode?
cPacketizer Pkt(*this, 0x0a); cPacketizer Pkt(*this, 0x0a);
Pkt.WriteInt(a_Entity.GetUniqueID()); Pkt.WriteInt(a_Entity.GetUniqueID());
Pkt.WriteInt(a_BlockX); Pkt.WriteInt(a_BlockX);
@ -1183,6 +1299,8 @@ void cProtocol172::SendUseBed(const cEntity & a_Entity, int a_BlockX, int a_Bloc
void cProtocol172::SendWeather(eWeather a_Weather) void cProtocol172::SendWeather(eWeather a_Weather)
{ {
ASSERT(m_State == 3); // In game mode?
{ {
cPacketizer Pkt(*this, 0x2b); // Change Game State packet cPacketizer Pkt(*this, 0x2b); // Change Game State packet
Pkt.WriteByte((a_Weather == wSunny) ? 1 : 2); // End rain / begin rain Pkt.WriteByte((a_Weather == wSunny) ? 1 : 2); // End rain / begin rain
@ -1198,6 +1316,8 @@ void cProtocol172::SendWeather(eWeather a_Weather)
void cProtocol172::SendWholeInventory(const cWindow & a_Window) void cProtocol172::SendWholeInventory(const cWindow & a_Window)
{ {
ASSERT(m_State == 3); // In game mode?
cPacketizer Pkt(*this, 0x30); // Window Items packet cPacketizer Pkt(*this, 0x30); // Window Items packet
Pkt.WriteChar(a_Window.GetWindowID()); Pkt.WriteChar(a_Window.GetWindowID());
Pkt.WriteShort(a_Window.GetNumSlots()); Pkt.WriteShort(a_Window.GetNumSlots());
@ -1215,6 +1335,8 @@ void cProtocol172::SendWholeInventory(const cWindow & a_Window)
void cProtocol172::SendWindowClose(const cWindow & a_Window) void cProtocol172::SendWindowClose(const cWindow & a_Window)
{ {
ASSERT(m_State == 3); // In game mode?
cPacketizer Pkt(*this, 0x2e); cPacketizer Pkt(*this, 0x2e);
Pkt.WriteChar(a_Window.GetWindowID()); Pkt.WriteChar(a_Window.GetWindowID());
} }
@ -1225,6 +1347,8 @@ void cProtocol172::SendWindowClose(const cWindow & a_Window)
void cProtocol172::SendWindowOpen(const cWindow & a_Window) void cProtocol172::SendWindowOpen(const cWindow & a_Window)
{ {
ASSERT(m_State == 3); // In game mode?
if (a_Window.GetWindowType() < 0) if (a_Window.GetWindowType() < 0)
{ {
// Do not send this packet for player inventory windows // Do not send this packet for player inventory windows
@ -1249,6 +1373,8 @@ void cProtocol172::SendWindowOpen(const cWindow & a_Window)
void cProtocol172::SendWindowProperty(const cWindow & a_Window, short a_Property, short a_Value) void cProtocol172::SendWindowProperty(const cWindow & a_Window, short a_Property, short a_Value)
{ {
ASSERT(m_State == 3); // In game mode?
cPacketizer Pkt(*this, 0x31); // Window Property packet cPacketizer Pkt(*this, 0x31); // Window Property packet
Pkt.WriteChar(a_Window.GetWindowID()); Pkt.WriteChar(a_Window.GetWindowID());
Pkt.WriteShort(a_Property); Pkt.WriteShort(a_Property);

View File

@ -69,18 +69,19 @@ void cIncrementalRedstoneSimulator::RedstoneAddBlock(int a_BlockX, int a_BlockY,
// Checking only when a block is changed, as opposed to every tick, also improves performance // Checking only when a block is changed, as opposed to every tick, also improves performance
PoweredBlocksList * PoweredBlocks = a_Chunk->GetRedstoneSimulatorPoweredBlocksList(); PoweredBlocksList * PoweredBlocks = a_Chunk->GetRedstoneSimulatorPoweredBlocksList();
for (PoweredBlocksList::iterator itr = PoweredBlocks->begin(); itr != PoweredBlocks->end(); ++itr) for (PoweredBlocksList::iterator itr = PoweredBlocks->begin(); itr != PoweredBlocks->end();)
{ {
if (!itr->a_SourcePos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ))) if (!itr->a_SourcePos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ)))
{ {
++itr;
continue; continue;
} }
if (!IsPotentialSource(Block)) if (!IsPotentialSource(Block))
{ {
LOGD("cIncrementalRedstoneSimulator: Erased block @ {%i, %i, %i} from powered blocks list as it no longer connected to a source", itr->a_BlockPos.x, itr->a_BlockPos.y, itr->a_BlockPos.z); LOGD("cIncrementalRedstoneSimulator: Erased block @ {%i, %i, %i} from powered blocks list as it no longer connected to a source", itr->a_BlockPos.x, itr->a_BlockPos.y, itr->a_BlockPos.z);
PoweredBlocks->erase(itr); itr = PoweredBlocks->erase(itr);
break; continue;
} }
else if ( else if (
// Changeable sources // Changeable sources
@ -93,9 +94,10 @@ void cIncrementalRedstoneSimulator::RedstoneAddBlock(int a_BlockX, int a_BlockY,
) )
{ {
LOGD("cIncrementalRedstoneSimulator: Erased block @ {%i, %i, %i} from powered blocks list due to present/past metadata mismatch", itr->a_BlockPos.x, itr->a_BlockPos.y, itr->a_BlockPos.z); LOGD("cIncrementalRedstoneSimulator: Erased block @ {%i, %i, %i} from powered blocks list due to present/past metadata mismatch", itr->a_BlockPos.x, itr->a_BlockPos.y, itr->a_BlockPos.z);
PoweredBlocks->erase(itr); itr = PoweredBlocks->erase(itr);
break; continue;
} }
++itr;
} }
LinkedBlocksList * LinkedPoweredBlocks = a_Chunk->GetRedstoneSimulatorLinkedBlocksList(); LinkedBlocksList * LinkedPoweredBlocks = a_Chunk->GetRedstoneSimulatorLinkedBlocksList();
@ -532,128 +534,96 @@ void cIncrementalRedstoneSimulator::HandleRedstoneWire(int a_BlockX, int a_Block
}; };
// Check to see if directly beside a power source // Check to see if directly beside a power source
if (IsWirePowered(a_BlockX, a_BlockY, a_BlockZ)) unsigned char MyPower;
if (!IsWirePowered(a_BlockX, a_BlockY, a_BlockZ, MyPower))
{ {
m_World.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, 15); // Maximum power m_World.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, 0);
m_World.WakeUpSimulators(a_BlockX, a_BlockY, a_BlockZ);
return;
} }
else
m_World.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, MyPower);
if (MyPower < 1)
{ {
NIBBLETYPE MyMeta = m_World.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ); return;
NIBBLETYPE MetaToSet = MyMeta; }
int TimesMetaSmaller = 0, TimesFoundAWire = 0;
for (size_t i = 0; i < ARRAYCOUNT(gCrossCoords); i++) // Loop through all directions to transfer or receive power MyPower--;
for (size_t i = 0; i < ARRAYCOUNT(gCrossCoords); i++) // Loop through all directions to transfer or receive power
{
if ((i >= 4) && (i <= 7)) // If we are currently checking for wire surrounding ourself one block above...
{ {
if ((i >= 4) && (i <= 7)) // If we are currently checking for wire surrounding ourself one block above... if (cBlockInfo::IsSolid(m_World.GetBlock(a_BlockX, a_BlockY + 1, a_BlockZ))) // If there is something solid above us (wire cut off)...
{ {
if (cBlockInfo::IsSolid(m_World.GetBlock(a_BlockX, a_BlockY + 1, a_BlockZ))) // If there is something solid above us (wire cut off)... continue; // We don't receive power from that wire
{
continue; // We don't receive power from that wire
}
} }
else if ((i >= 8) && (i <= 11)) // See above, but this is for wire below us }
else if ((i >= 8) && (i <= 11)) // See above, but this is for wire below us
{
if (cBlockInfo::IsSolid(m_World.GetBlock(a_BlockX, a_BlockY - 1, a_BlockZ)))
{ {
if (cBlockInfo::IsSolid(m_World.GetBlock(a_BlockX + gCrossCoords[i].x, a_BlockY + gCrossCoords[i].y + 1, a_BlockZ + gCrossCoords[i].z))) continue;
{
continue;
}
} }
BLOCKTYPE SurroundType;
NIBBLETYPE SurroundMeta;
m_World.GetBlockTypeMeta(a_BlockX + gCrossCoords[i].x, a_BlockY + gCrossCoords[i].y, a_BlockZ + gCrossCoords[i].z, SurroundType, SurroundMeta);
if (SurroundType == E_BLOCK_REDSTONE_WIRE)
{
TimesFoundAWire++;
if (SurroundMeta > 1) // Wires of power 1 or 0 cannot transfer power TO ME, don't bother checking
{
// Does surrounding wire have a higher power level than the highest so far (MetaToSet)?
// >= to fix a bug where wires bordering each other with the same power level will appear (in terms of meta) to power each other, when they aren't actually in the powered list
if (SurroundMeta >= MetaToSet)
{
MetaToSet = SurroundMeta - 1; // To improve performance
}
}
if (SurroundMeta < MyMeta) // Go through all surroundings to see if self power is larger than everyone else's
{
TimesMetaSmaller++;
}
}
} }
if ((TimesMetaSmaller == TimesFoundAWire) && (MyMeta != 0)) if (m_World.GetBlock(a_BlockX + gCrossCoords[i].x, a_BlockY + gCrossCoords[i].y, a_BlockZ + gCrossCoords[i].z) == E_BLOCK_REDSTONE_WIRE)
{ {
// All surrounding metas were smaller - self must have been a wire that was SetBlockPowered(a_BlockX + gCrossCoords[i].x, a_BlockY + gCrossCoords[i].y, a_BlockZ + gCrossCoords[i].z, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_WIRE, MyPower);
// transferring power to other wires around.
// However, self not directly powered anymore, so source must have been removed,
// therefore, self must be set to meta zero
m_World.SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_WIRE, 0); // SetMeta & WakeUpSims doesn't seem to work here, so SetBlock
return; // No need to process block power sets because self not powered
}
else if (MyMeta != MetaToSet)
{
m_World.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, MetaToSet);
} }
} }
if (m_World.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ) != 0) // A powered wire for (size_t i = 0; i < ARRAYCOUNT(gSideCoords); i++) // Look for repeaters immediately surrounding self and try to power them
{ {
for (size_t i = 0; i < ARRAYCOUNT(gSideCoords); i++) // Look for repeaters immediately surrounding self and try to power them if (m_World.GetBlock(a_BlockX + gSideCoords[i].x, a_BlockY + gSideCoords[i].y, a_BlockZ + gSideCoords[i].z) == E_BLOCK_REDSTONE_REPEATER_OFF)
{ {
if (m_World.GetBlock(a_BlockX + gSideCoords[i].x, a_BlockY + gSideCoords[i].y, a_BlockZ + gSideCoords[i].z) == E_BLOCK_REDSTONE_REPEATER_OFF) SetBlockPowered(a_BlockX + gSideCoords[i].x, a_BlockY + gSideCoords[i].y, a_BlockZ + gSideCoords[i].z, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_WIRE, MyPower);
{
SetBlockPowered(a_BlockX + gSideCoords[i].x, a_BlockY + gSideCoords[i].y, a_BlockZ + gSideCoords[i].z, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_WIRE);
}
} }
}
// Wire still powered, power blocks beneath // Wire still powered, power blocks beneath
SetBlockPowered(a_BlockX, a_BlockY - 1, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_WIRE); SetBlockPowered(a_BlockX, a_BlockY - 1, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_WIRE, MyPower);
SetDirectionLinkedPowered(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_YM, E_BLOCK_REDSTONE_WIRE); SetDirectionLinkedPowered(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_YM, E_BLOCK_REDSTONE_WIRE, MyPower);
switch (GetWireDirection(a_BlockX, a_BlockY, a_BlockZ)) switch (GetWireDirection(a_BlockX, a_BlockY, a_BlockZ))
{
case REDSTONE_NONE:
{ {
case REDSTONE_NONE: SetBlockPowered(a_BlockX + 1, a_BlockY, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_WIRE, MyPower);
{ SetBlockPowered(a_BlockX - 1, a_BlockY, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_WIRE, MyPower);
SetBlockPowered(a_BlockX, a_BlockY - 1, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_WIRE); SetBlockPowered(a_BlockX, a_BlockY, a_BlockZ + 1, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_WIRE, MyPower);
SetBlockPowered(a_BlockX + 1, a_BlockY, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_WIRE); SetBlockPowered(a_BlockX, a_BlockY, a_BlockZ - 1, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_WIRE, MyPower);
SetBlockPowered(a_BlockX - 1, a_BlockY, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_WIRE);
SetBlockPowered(a_BlockX, a_BlockY, a_BlockZ + 1, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_WIRE);
SetBlockPowered(a_BlockX, a_BlockY, a_BlockZ - 1, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_WIRE);
SetDirectionLinkedPowered(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_XM, E_BLOCK_REDSTONE_WIRE); SetDirectionLinkedPowered(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_XM, E_BLOCK_REDSTONE_WIRE, MyPower);
SetDirectionLinkedPowered(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_XP, E_BLOCK_REDSTONE_WIRE); SetDirectionLinkedPowered(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_XP, E_BLOCK_REDSTONE_WIRE, MyPower);
SetDirectionLinkedPowered(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_YM, E_BLOCK_REDSTONE_WIRE); SetDirectionLinkedPowered(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_ZM, E_BLOCK_REDSTONE_WIRE, MyPower);
SetDirectionLinkedPowered(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_ZM, E_BLOCK_REDSTONE_WIRE); SetDirectionLinkedPowered(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_ZP, E_BLOCK_REDSTONE_WIRE, MyPower);
SetDirectionLinkedPowered(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_ZP, E_BLOCK_REDSTONE_WIRE); break;
break; }
} case REDSTONE_X_POS:
case REDSTONE_X_POS: {
{ SetBlockPowered(a_BlockX + 1, a_BlockY, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_WIRE, MyPower);
SetBlockPowered(a_BlockX + 1, a_BlockY, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_WIRE); SetDirectionLinkedPowered(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_XP, E_BLOCK_REDSTONE_WIRE, MyPower);
SetDirectionLinkedPowered(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_XP, E_BLOCK_REDSTONE_WIRE); break;
break; }
} case REDSTONE_X_NEG:
case REDSTONE_X_NEG: {
{ SetBlockPowered(a_BlockX - 1, a_BlockY, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_WIRE, MyPower);
SetBlockPowered(a_BlockX - 1, a_BlockY, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_WIRE); SetDirectionLinkedPowered(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_XM, E_BLOCK_REDSTONE_WIRE, MyPower);
SetDirectionLinkedPowered(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_XM, E_BLOCK_REDSTONE_WIRE); break;
break; }
} case REDSTONE_Z_POS:
case REDSTONE_Z_POS: {
{ SetBlockPowered(a_BlockX, a_BlockY, a_BlockZ + 1, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_WIRE, MyPower);
SetBlockPowered(a_BlockX, a_BlockY, a_BlockZ + 1, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_WIRE); SetDirectionLinkedPowered(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_ZP, E_BLOCK_REDSTONE_WIRE, MyPower);
SetDirectionLinkedPowered(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_ZP, E_BLOCK_REDSTONE_WIRE); break;
break; }
} case REDSTONE_Z_NEG:
case REDSTONE_Z_NEG: {
{ SetBlockPowered(a_BlockX, a_BlockY, a_BlockZ - 1, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_WIRE, MyPower);
SetBlockPowered(a_BlockX, a_BlockY, a_BlockZ - 1, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_REDSTONE_WIRE); SetDirectionLinkedPowered(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_ZM, E_BLOCK_REDSTONE_WIRE, MyPower);
SetDirectionLinkedPowered(a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_ZM, E_BLOCK_REDSTONE_WIRE); break;
break;
}
} }
} }
} }
@ -1046,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)
@ -1070,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;
@ -1078,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;
}
} }
} }
@ -1323,28 +1424,29 @@ bool cIncrementalRedstoneSimulator::IsPistonPowered(int a_BlockX, int a_BlockY,
bool cIncrementalRedstoneSimulator::IsWirePowered(int a_BlockX, int a_BlockY, int a_BlockZ) bool cIncrementalRedstoneSimulator::IsWirePowered(int a_BlockX, int a_BlockY, int a_BlockZ, unsigned char & a_PowerLevel)
{ {
for (PoweredBlocksList::const_iterator itr = m_PoweredBlocks->begin(); itr != m_PoweredBlocks->end(); ++itr) a_PowerLevel = 0;
{
if (!itr->a_BlockPos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ))) { continue; }
if (m_World.GetBlock(itr->a_SourcePos) != E_BLOCK_REDSTONE_WIRE) for (PoweredBlocksList::const_iterator itr = m_PoweredBlocks->begin(); itr != m_PoweredBlocks->end(); ++itr) // Check powered list
{
if (!itr->a_BlockPos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ)))
{ {
return true; continue;
} }
a_PowerLevel = std::max(a_PowerLevel, itr->a_PowerLevel);
} }
for (LinkedBlocksList::const_iterator itr = m_LinkedPoweredBlocks->begin(); itr != m_LinkedPoweredBlocks->end(); ++itr) for (LinkedBlocksList::const_iterator itr = m_LinkedPoweredBlocks->begin(); itr != m_LinkedPoweredBlocks->end(); ++itr) // Check linked powered list
{ {
if (!itr->a_BlockPos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ))) { continue; } if (!itr->a_BlockPos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ)))
if (m_World.GetBlock(itr->a_SourcePos) != E_BLOCK_REDSTONE_WIRE)
{ {
return true; continue;
} }
a_PowerLevel = std::max(a_PowerLevel, itr->a_PowerLevel);
} }
return false; // Source was in front of the piston's front face
return (a_PowerLevel != 0); // Source was in front of the piston's front face
} }
@ -1374,7 +1476,7 @@ bool cIncrementalRedstoneSimulator::AreCoordsSimulated(int a_BlockX, int a_Block
void cIncrementalRedstoneSimulator::SetDirectionLinkedPowered(int a_BlockX, int a_BlockY, int a_BlockZ, char a_Direction, BLOCKTYPE a_SourceType) void cIncrementalRedstoneSimulator::SetDirectionLinkedPowered(int a_BlockX, int a_BlockY, int a_BlockZ, char a_Direction, BLOCKTYPE a_SourceType, unsigned char a_PowerLevel)
{ {
switch (a_Direction) switch (a_Direction)
{ {
@ -1382,11 +1484,11 @@ void cIncrementalRedstoneSimulator::SetDirectionLinkedPowered(int a_BlockX, int
{ {
BLOCKTYPE MiddleBlock = m_World.GetBlock(a_BlockX - 1, a_BlockY, a_BlockZ); BLOCKTYPE MiddleBlock = m_World.GetBlock(a_BlockX - 1, a_BlockY, a_BlockZ);
SetBlockLinkedPowered(a_BlockX - 2, a_BlockY, a_BlockZ, a_BlockX - 1, a_BlockY, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock); SetBlockLinkedPowered(a_BlockX - 2, a_BlockY, a_BlockZ, a_BlockX - 1, a_BlockY, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock, a_PowerLevel);
SetBlockLinkedPowered(a_BlockX - 1, a_BlockY + 1, a_BlockZ, a_BlockX - 1, a_BlockY, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock); SetBlockLinkedPowered(a_BlockX - 1, a_BlockY + 1, a_BlockZ, a_BlockX - 1, a_BlockY, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock, a_PowerLevel);
SetBlockLinkedPowered(a_BlockX - 1, a_BlockY - 1, a_BlockZ, a_BlockX - 1, a_BlockY, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock); SetBlockLinkedPowered(a_BlockX - 1, a_BlockY - 1, a_BlockZ, a_BlockX - 1, a_BlockY, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock, a_PowerLevel);
SetBlockLinkedPowered(a_BlockX - 1, a_BlockY, a_BlockZ + 1, a_BlockX - 1, a_BlockY, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock); SetBlockLinkedPowered(a_BlockX - 1, a_BlockY, a_BlockZ + 1, a_BlockX - 1, a_BlockY, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock, a_PowerLevel);
SetBlockLinkedPowered(a_BlockX - 1, a_BlockY, a_BlockZ - 1, a_BlockX - 1, a_BlockY, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock); SetBlockLinkedPowered(a_BlockX - 1, a_BlockY, a_BlockZ - 1, a_BlockX - 1, a_BlockY, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock, a_PowerLevel);
break; break;
} }
@ -1394,11 +1496,11 @@ void cIncrementalRedstoneSimulator::SetDirectionLinkedPowered(int a_BlockX, int
{ {
BLOCKTYPE MiddleBlock = m_World.GetBlock(a_BlockX + 1, a_BlockY, a_BlockZ); BLOCKTYPE MiddleBlock = m_World.GetBlock(a_BlockX + 1, a_BlockY, a_BlockZ);
SetBlockLinkedPowered(a_BlockX + 2, a_BlockY, a_BlockZ, a_BlockX + 1, a_BlockY, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock); SetBlockLinkedPowered(a_BlockX + 2, a_BlockY, a_BlockZ, a_BlockX + 1, a_BlockY, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock, a_PowerLevel);
SetBlockLinkedPowered(a_BlockX + 1, a_BlockY + 1, a_BlockZ, a_BlockX + 1, a_BlockY, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock); SetBlockLinkedPowered(a_BlockX + 1, a_BlockY + 1, a_BlockZ, a_BlockX + 1, a_BlockY, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock, a_PowerLevel);
SetBlockLinkedPowered(a_BlockX + 1, a_BlockY - 1, a_BlockZ, a_BlockX + 1, a_BlockY, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock); SetBlockLinkedPowered(a_BlockX + 1, a_BlockY - 1, a_BlockZ, a_BlockX + 1, a_BlockY, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock, a_PowerLevel);
SetBlockLinkedPowered(a_BlockX + 1, a_BlockY, a_BlockZ + 1, a_BlockX + 1, a_BlockY, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock); SetBlockLinkedPowered(a_BlockX + 1, a_BlockY, a_BlockZ + 1, a_BlockX + 1, a_BlockY, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock, a_PowerLevel);
SetBlockLinkedPowered(a_BlockX + 1, a_BlockY, a_BlockZ - 1, a_BlockX + 1, a_BlockY, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock); SetBlockLinkedPowered(a_BlockX + 1, a_BlockY, a_BlockZ - 1, a_BlockX + 1, a_BlockY, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock, a_PowerLevel);
break; break;
} }
@ -1406,11 +1508,11 @@ void cIncrementalRedstoneSimulator::SetDirectionLinkedPowered(int a_BlockX, int
{ {
BLOCKTYPE MiddleBlock = m_World.GetBlock(a_BlockX, a_BlockY - 1, a_BlockZ); BLOCKTYPE MiddleBlock = m_World.GetBlock(a_BlockX, a_BlockY - 1, a_BlockZ);
SetBlockLinkedPowered(a_BlockX, a_BlockY - 2, a_BlockZ, a_BlockX, a_BlockY - 1, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock); SetBlockLinkedPowered(a_BlockX, a_BlockY - 2, a_BlockZ, a_BlockX, a_BlockY - 1, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock, a_PowerLevel);
SetBlockLinkedPowered(a_BlockX + 1, a_BlockY - 1, a_BlockZ, a_BlockX, a_BlockY - 1, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock); SetBlockLinkedPowered(a_BlockX + 1, a_BlockY - 1, a_BlockZ, a_BlockX, a_BlockY - 1, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock, a_PowerLevel);
SetBlockLinkedPowered(a_BlockX - 1, a_BlockY - 1, a_BlockZ, a_BlockX, a_BlockY - 1, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock); SetBlockLinkedPowered(a_BlockX - 1, a_BlockY - 1, a_BlockZ, a_BlockX, a_BlockY - 1, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock, a_PowerLevel);
SetBlockLinkedPowered(a_BlockX, a_BlockY - 1, a_BlockZ + 1, a_BlockX, a_BlockY - 1, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock); SetBlockLinkedPowered(a_BlockX, a_BlockY - 1, a_BlockZ + 1, a_BlockX, a_BlockY - 1, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock, a_PowerLevel);
SetBlockLinkedPowered(a_BlockX, a_BlockY - 1, a_BlockZ - 1, a_BlockX, a_BlockY - 1, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock); SetBlockLinkedPowered(a_BlockX, a_BlockY - 1, a_BlockZ - 1, a_BlockX, a_BlockY - 1, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock, a_PowerLevel);
break; break;
} }
@ -1418,11 +1520,11 @@ void cIncrementalRedstoneSimulator::SetDirectionLinkedPowered(int a_BlockX, int
{ {
BLOCKTYPE MiddleBlock = m_World.GetBlock(a_BlockX, a_BlockY + 1, a_BlockZ); BLOCKTYPE MiddleBlock = m_World.GetBlock(a_BlockX, a_BlockY + 1, a_BlockZ);
SetBlockLinkedPowered(a_BlockX, a_BlockY + 2, a_BlockZ, a_BlockX, a_BlockY + 1, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock); SetBlockLinkedPowered(a_BlockX, a_BlockY + 2, a_BlockZ, a_BlockX, a_BlockY + 1, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock, a_PowerLevel);
SetBlockLinkedPowered(a_BlockX + 1, a_BlockY + 1, a_BlockZ, a_BlockX, a_BlockY + 1, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock); SetBlockLinkedPowered(a_BlockX + 1, a_BlockY + 1, a_BlockZ, a_BlockX, a_BlockY + 1, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock, a_PowerLevel);
SetBlockLinkedPowered(a_BlockX - 1, a_BlockY + 1, a_BlockZ, a_BlockX, a_BlockY + 1, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock); SetBlockLinkedPowered(a_BlockX - 1, a_BlockY + 1, a_BlockZ, a_BlockX, a_BlockY + 1, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock, a_PowerLevel);
SetBlockLinkedPowered(a_BlockX, a_BlockY + 1, a_BlockZ + 1, a_BlockX, a_BlockY + 1, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock); SetBlockLinkedPowered(a_BlockX, a_BlockY + 1, a_BlockZ + 1, a_BlockX, a_BlockY + 1, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock, a_PowerLevel);
SetBlockLinkedPowered(a_BlockX, a_BlockY + 1, a_BlockZ - 1, a_BlockX, a_BlockY + 1, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock); SetBlockLinkedPowered(a_BlockX, a_BlockY + 1, a_BlockZ - 1, a_BlockX, a_BlockY + 1, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock, a_PowerLevel);
break; break;
} }
@ -1430,11 +1532,11 @@ void cIncrementalRedstoneSimulator::SetDirectionLinkedPowered(int a_BlockX, int
{ {
BLOCKTYPE MiddleBlock = m_World.GetBlock(a_BlockX, a_BlockY, a_BlockZ - 1); BLOCKTYPE MiddleBlock = m_World.GetBlock(a_BlockX, a_BlockY, a_BlockZ - 1);
SetBlockLinkedPowered(a_BlockX, a_BlockY, a_BlockZ - 2, a_BlockX, a_BlockY, a_BlockZ - 1, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock); SetBlockLinkedPowered(a_BlockX, a_BlockY, a_BlockZ - 2, a_BlockX, a_BlockY, a_BlockZ - 1, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock, a_PowerLevel);
SetBlockLinkedPowered(a_BlockX + 1, a_BlockY, a_BlockZ - 1, a_BlockX, a_BlockY, a_BlockZ - 1, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock); SetBlockLinkedPowered(a_BlockX + 1, a_BlockY, a_BlockZ - 1, a_BlockX, a_BlockY, a_BlockZ - 1, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock, a_PowerLevel);
SetBlockLinkedPowered(a_BlockX - 1, a_BlockY, a_BlockZ - 1, a_BlockX, a_BlockY, a_BlockZ - 1, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock); SetBlockLinkedPowered(a_BlockX - 1, a_BlockY, a_BlockZ - 1, a_BlockX, a_BlockY, a_BlockZ - 1, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock, a_PowerLevel);
SetBlockLinkedPowered(a_BlockX, a_BlockY + 1, a_BlockZ - 1, a_BlockX, a_BlockY, a_BlockZ - 1, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock); SetBlockLinkedPowered(a_BlockX, a_BlockY + 1, a_BlockZ - 1, a_BlockX, a_BlockY, a_BlockZ - 1, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock, a_PowerLevel);
SetBlockLinkedPowered(a_BlockX, a_BlockY - 1, a_BlockZ - 1, a_BlockX, a_BlockY, a_BlockZ - 1, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock); SetBlockLinkedPowered(a_BlockX, a_BlockY - 1, a_BlockZ - 1, a_BlockX, a_BlockY, a_BlockZ - 1, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock, a_PowerLevel);
break; break;
} }
@ -1442,11 +1544,11 @@ void cIncrementalRedstoneSimulator::SetDirectionLinkedPowered(int a_BlockX, int
{ {
BLOCKTYPE MiddleBlock = m_World.GetBlock(a_BlockX, a_BlockY, a_BlockZ + 1); BLOCKTYPE MiddleBlock = m_World.GetBlock(a_BlockX, a_BlockY, a_BlockZ + 1);
SetBlockLinkedPowered(a_BlockX, a_BlockY, a_BlockZ + 2, a_BlockX, a_BlockY, a_BlockZ + 1, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock); SetBlockLinkedPowered(a_BlockX, a_BlockY, a_BlockZ + 2, a_BlockX, a_BlockY, a_BlockZ + 1, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock, a_PowerLevel);
SetBlockLinkedPowered(a_BlockX + 1, a_BlockY, a_BlockZ + 1, a_BlockX, a_BlockY, a_BlockZ + 1, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock); SetBlockLinkedPowered(a_BlockX + 1, a_BlockY, a_BlockZ + 1, a_BlockX, a_BlockY, a_BlockZ + 1, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock, a_PowerLevel);
SetBlockLinkedPowered(a_BlockX - 1, a_BlockY, a_BlockZ + 1, a_BlockX, a_BlockY, a_BlockZ + 1, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock); SetBlockLinkedPowered(a_BlockX - 1, a_BlockY, a_BlockZ + 1, a_BlockX, a_BlockY, a_BlockZ + 1, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock, a_PowerLevel);
SetBlockLinkedPowered(a_BlockX, a_BlockY + 1, a_BlockZ + 1, a_BlockX, a_BlockY, a_BlockZ + 1, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock); SetBlockLinkedPowered(a_BlockX, a_BlockY + 1, a_BlockZ + 1, a_BlockX, a_BlockY, a_BlockZ + 1, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock, a_PowerLevel);
SetBlockLinkedPowered(a_BlockX, a_BlockY - 1, a_BlockZ + 1, a_BlockX, a_BlockY, a_BlockZ + 1, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock); SetBlockLinkedPowered(a_BlockX, a_BlockY - 1, a_BlockZ + 1, a_BlockX, a_BlockY, a_BlockZ + 1, a_BlockX, a_BlockY, a_BlockZ, a_SourceType, MiddleBlock, a_PowerLevel);
break; break;
} }
@ -1462,7 +1564,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
{ {
@ -1479,7 +1581,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);
} }
} }
@ -1487,7 +1589,7 @@ void cIncrementalRedstoneSimulator::SetAllDirsAsPowered(int a_BlockX, int a_Bloc
void cIncrementalRedstoneSimulator::SetBlockPowered(int a_BlockX, int a_BlockY, int a_BlockZ, int a_SourceX, int a_SourceY, int a_SourceZ, BLOCKTYPE a_SourceBlock) void cIncrementalRedstoneSimulator::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)
{ {
BLOCKTYPE Block = m_World.GetBlock(a_BlockX, a_BlockY, a_BlockZ); BLOCKTYPE Block = m_World.GetBlock(a_BlockX, a_BlockY, a_BlockZ);
if (Block == E_BLOCK_AIR) if (Block == E_BLOCK_AIR)
@ -1497,15 +1599,31 @@ void cIncrementalRedstoneSimulator::SetBlockPowered(int a_BlockX, int a_BlockY,
} }
PoweredBlocksList * Powered = m_Chunk->GetNeighborChunk(a_BlockX, a_BlockZ)->GetRedstoneSimulatorPoweredBlocksList(); PoweredBlocksList * Powered = m_Chunk->GetNeighborChunk(a_BlockX, a_BlockZ)->GetRedstoneSimulatorPoweredBlocksList();
for (PoweredBlocksList::iterator itr = Powered->begin(); itr != Powered->end(); ++itr) // Check powered list
for (PoweredBlocksList::const_iterator 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;
}
}
PoweredBlocksList * OtherPowered = m_Chunk->GetNeighborChunk(a_SourceX, a_SourceZ)->GetRedstoneSimulatorPoweredBlocksList();
for (PoweredBlocksList::const_iterator itr = OtherPowered->begin(); itr != OtherPowered->end(); ++itr) // Check powered list
{
if (
itr->a_BlockPos.Equals(Vector3i(a_SourceX, a_SourceY, a_SourceZ)) &&
itr->a_SourcePos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ))
)
{
// Powered wires try to power their source - don't let them!
return; return;
} }
} }
@ -1513,6 +1631,7 @@ void cIncrementalRedstoneSimulator::SetBlockPowered(int a_BlockX, int a_BlockY,
sPoweredBlocks RC; sPoweredBlocks RC;
RC.a_BlockPos = Vector3i(a_BlockX, a_BlockY, a_BlockZ); RC.a_BlockPos = Vector3i(a_BlockX, a_BlockY, a_BlockZ);
RC.a_SourcePos = Vector3i(a_SourceX, a_SourceY, a_SourceZ); RC.a_SourcePos = Vector3i(a_SourceX, a_SourceY, a_SourceZ);
RC.a_PowerLevel = a_PowerLevel;
Powered->push_back(RC); Powered->push_back(RC);
} }
@ -1524,7 +1643,7 @@ void cIncrementalRedstoneSimulator::SetBlockLinkedPowered(
int a_BlockX, int a_BlockY, int a_BlockZ, int a_BlockX, int a_BlockY, int a_BlockZ,
int a_MiddleX, int a_MiddleY, int a_MiddleZ, int a_MiddleX, int a_MiddleY, int a_MiddleZ,
int a_SourceX, int a_SourceY, int a_SourceZ, int a_SourceX, int a_SourceY, int a_SourceZ,
BLOCKTYPE a_SourceBlock, BLOCKTYPE a_MiddleBlock BLOCKTYPE a_SourceBlock, BLOCKTYPE a_MiddleBlock, unsigned char a_PowerLevel
) )
{ {
BLOCKTYPE DestBlock = m_World.GetBlock(a_BlockX, a_BlockY, a_BlockZ); BLOCKTYPE DestBlock = m_World.GetBlock(a_BlockX, a_BlockY, a_BlockZ);
@ -1539,16 +1658,19 @@ void cIncrementalRedstoneSimulator::SetBlockLinkedPowered(
} }
LinkedBlocksList * Linked = m_Chunk->GetNeighborChunk(a_BlockX, a_BlockZ)->GetRedstoneSimulatorLinkedBlocksList(); LinkedBlocksList * Linked = m_Chunk->GetNeighborChunk(a_BlockX, a_BlockZ)->GetRedstoneSimulatorLinkedBlocksList();
for (LinkedBlocksList::iterator itr = Linked->begin(); itr != Linked->end(); ++itr) // Check linked powered list
for (LinkedBlocksList::const_iterator 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)) &&
itr->a_MiddlePos.Equals(Vector3i(a_MiddleX, a_MiddleY, a_MiddleZ)) && itr->a_MiddlePos.Equals(Vector3i(a_MiddleX, a_MiddleY, a_MiddleZ)) &&
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;
} }
} }
@ -1557,6 +1679,7 @@ void cIncrementalRedstoneSimulator::SetBlockLinkedPowered(
RC.a_BlockPos = Vector3i(a_BlockX, a_BlockY, a_BlockZ); RC.a_BlockPos = Vector3i(a_BlockX, a_BlockY, a_BlockZ);
RC.a_MiddlePos = Vector3i(a_MiddleX, a_MiddleY, a_MiddleZ); RC.a_MiddlePos = Vector3i(a_MiddleX, a_MiddleY, a_MiddleZ);
RC.a_SourcePos = Vector3i(a_SourceX, a_SourceY, a_SourceZ); RC.a_SourcePos = Vector3i(a_SourceX, a_SourceY, a_SourceZ);
RC.a_PowerLevel = a_PowerLevel;
Linked->push_back(RC); Linked->push_back(RC);
} }
@ -1621,7 +1744,7 @@ void cIncrementalRedstoneSimulator::QueueRepeaterPowerChange(int a_BlockX, int a
RC.a_BlockPos = Vector3i(a_BlockX, a_BlockY, a_BlockZ); RC.a_BlockPos = Vector3i(a_BlockX, a_BlockY, a_BlockZ);
// 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.)
// * 2 because apparently, MCS ticks are way faster than vanilla ticks, so repeater aren't noticeably delayed // * 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;
@ -1697,12 +1820,3 @@ bool cIncrementalRedstoneSimulator::IsLeverOn(NIBBLETYPE a_BlockMeta)
bool cIncrementalRedstoneSimulator::IsButtonOn(NIBBLETYPE a_BlockMeta)
{
return IsLeverOn(a_BlockMeta);
}

View File

@ -36,31 +36,35 @@ 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
Vector3i a_SourcePos; // Position of source powering the block at a_BlockPos Vector3i a_SourcePos; // Position of source powering the block at a_BlockPos
unsigned char a_PowerLevel;
}; };
struct sLinkedPoweredBlocks // Define structure of the indirectly powered blocks list (i.e. repeaters powering through a block to the block at the other side) struct sLinkedPoweredBlocks // Define structure of the indirectly powered blocks list (i.e. repeaters powering through a block to the block at the other side)
{ {
Vector3i a_BlockPos; Vector3i a_BlockPos;
Vector3i a_MiddlePos; Vector3i a_MiddlePos; // Position of block that is betwixt a source and the destination
Vector3i a_SourcePos; Vector3i a_SourcePos;
unsigned char a_PowerLevel;
}; };
struct sSimulatedPlayerToggleableList 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_BlockPos; Vector3i a_BlockPos;
bool WasLastStatePowered; bool WasLastStatePowered; // Was the last state powered or not? Determines whether a source update has happened and if I should resimulate
}; };
struct sRepeatersDelayList struct sRepeatersDelayList // Define structure of list containing repeaters' delay states
{ {
Vector3i a_BlockPos; Vector3i a_BlockPos;
unsigned char a_DelayTicks; unsigned char a_DelayTicks; // For how many ticks should the repeater delay
unsigned char a_ElapsedTicks; unsigned char a_ElapsedTicks; // How much of the previous has been elapsed?
bool ShouldPowerOn; bool ShouldPowerOn; // What happens when the delay time is fulfilled?
}; };
public: public:
@ -132,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); 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); 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); 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);
@ -159,15 +163,14 @@ private:
/** Returns if a piston is powered */ /** Returns if a piston is powered */
bool IsPistonPowered(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_Meta); bool IsPistonPowered(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_Meta);
/** Returns if a wire is powered /** Returns if a wire is powered
The only diffence between this and a normal AreCoordsPowered is that this function checks for a wire powering another wire The only diffence between this and a normal AreCoordsPowered is that this function checks for a wire powering another wire */
*/ bool IsWirePowered(int a_BlockX, int a_BlockY, int a_BlockZ, unsigned char & a_PowerLevel);
bool IsWirePowered(int a_BlockX, int a_BlockY, int a_BlockZ);
/** Returns if lever metadata marks it as emitting power */ /** Returns if lever metadata marks it as emitting power */
bool IsLeverOn(NIBBLETYPE a_BlockMeta); bool IsLeverOn(NIBBLETYPE a_BlockMeta);
/** Returns if button metadata marks it as emitting power */ /** Returns if button metadata marks it as emitting power */
bool IsButtonOn(NIBBLETYPE a_BlockMeta); bool IsButtonOn(NIBBLETYPE a_BlockMeta) { return IsLeverOn(a_BlockMeta); }
/* ============================== */ /* ============================== */
/* ====== Misc Functions ====== */ /* ====== Misc Functions ====== */

View File

@ -108,6 +108,11 @@ public:
return x == a_Rhs.x && y == a_Rhs.y && z == a_Rhs.z; return x == a_Rhs.x && y == a_Rhs.y && z == a_Rhs.z;
} }
inline bool operator == (const Vector3<T> & a_Rhs) const
{
return Equals(a_Rhs);
}
inline bool operator < (const Vector3<T> & a_Rhs) inline bool operator < (const Vector3<T> & a_Rhs)
{ {
// return (x < a_Rhs.x) && (y < a_Rhs.y) && (z < a_Rhs.z); ? // return (x < a_Rhs.x) && (y < a_Rhs.y) && (z < a_Rhs.z); ?

View File

@ -574,7 +574,7 @@ void cWorld::Start(void)
m_IsSugarcaneBonemealable = IniFile.GetValueSetB("Plants", "IsSugarcaneBonemealable", false); m_IsSugarcaneBonemealable = IniFile.GetValueSetB("Plants", "IsSugarcaneBonemealable", false);
m_IsDeepSnowEnabled = IniFile.GetValueSetB("Physics", "DeepSnow", true); m_IsDeepSnowEnabled = IniFile.GetValueSetB("Physics", "DeepSnow", true);
m_ShouldLavaSpawnFire = IniFile.GetValueSetB("Physics", "ShouldLavaSpawnFire", true); m_ShouldLavaSpawnFire = IniFile.GetValueSetB("Physics", "ShouldLavaSpawnFire", true);
int TNTShrapnelLevel = IniFile.GetValueSetI("Physics", "TNTShrapnelLevel", (int)slNone); int TNTShrapnelLevel = IniFile.GetValueSetI("Physics", "TNTShrapnelLevel", (int)slAll);
m_bCommandBlocksEnabled = IniFile.GetValueSetB("Mechanics", "CommandBlocksEnabled", false); m_bCommandBlocksEnabled = IniFile.GetValueSetB("Mechanics", "CommandBlocksEnabled", false);
m_bEnabledPVP = IniFile.GetValueSetB("Mechanics", "PVPEnabled", true); m_bEnabledPVP = IniFile.GetValueSetB("Mechanics", "PVPEnabled", true);
m_bUseChatPrefixes = IniFile.GetValueSetB("Mechanics", "UseChatPrefixes", true); m_bUseChatPrefixes = IniFile.GetValueSetB("Mechanics", "UseChatPrefixes", true);
@ -1632,7 +1632,6 @@ bool cWorld::WriteBlockArea(cBlockArea & a_Area, int a_MinBlockX, int a_MinBlock
void cWorld::SpawnItemPickups(const cItems & a_Pickups, double a_BlockX, double a_BlockY, double a_BlockZ, double a_FlyAwaySpeed, bool IsPlayerCreated) void cWorld::SpawnItemPickups(const cItems & a_Pickups, double a_BlockX, double a_BlockY, double a_BlockZ, double a_FlyAwaySpeed, bool IsPlayerCreated)
{ {
MTRand r1;
a_FlyAwaySpeed /= 100; // Pre-divide, so that we don't have to divide each time inside the loop a_FlyAwaySpeed /= 100; // Pre-divide, so that we don't have to divide each time inside the loop
for (cItems::const_iterator itr = a_Pickups.begin(); itr != a_Pickups.end(); ++itr) for (cItems::const_iterator itr = a_Pickups.begin(); itr != a_Pickups.end(); ++itr)
{ {
@ -1642,9 +1641,9 @@ void cWorld::SpawnItemPickups(const cItems & a_Pickups, double a_BlockX, double
continue; continue;
} }
float SpeedX = (float)(a_FlyAwaySpeed * (r1.randInt(10) - 5)); float SpeedX = (float)(a_FlyAwaySpeed * (GetTickRandomNumber(10) - 5));
float SpeedY = (float)(a_FlyAwaySpeed * r1.randInt(50)); float SpeedY = (float)(a_FlyAwaySpeed * GetTickRandomNumber(50));
float SpeedZ = (float)(a_FlyAwaySpeed * (r1.randInt(10) - 5)); float SpeedZ = (float)(a_FlyAwaySpeed * (GetTickRandomNumber(10) - 5));
cPickup * Pickup = new cPickup( cPickup * Pickup = new cPickup(
a_BlockX, a_BlockY, a_BlockZ, a_BlockX, a_BlockY, a_BlockZ,

View File

@ -231,7 +231,7 @@ void cFireworkItem::FadeColoursFromString(const AString & a_String, cFireworkIte
int cFireworkItem::GetVanillaColourCodeFromDye(short a_DyeMeta) int cFireworkItem::GetVanillaColourCodeFromDye(NIBBLETYPE a_DyeMeta)
{ {
/* /*
Colours are supposed to be calculated via: R << 16 + G << 8 + B Colours are supposed to be calculated via: R << 16 + G << 8 + B

View File

@ -81,7 +81,7 @@ public:
static void FadeColoursFromString(const AString & a_String, cFireworkItem & a_FireworkItem); static void FadeColoursFromString(const AString & a_String, cFireworkItem & a_FireworkItem);
/** Returns a colour code for fireworks used by the network code */ /** Returns a colour code for fireworks used by the network code */
static int GetVanillaColourCodeFromDye(short a_DyeMeta); static int GetVanillaColourCodeFromDye(NIBBLETYPE a_DyeMeta);
bool m_HasFlicker; bool m_HasFlicker;
bool m_HasTrail; bool m_HasTrail;