Merge remote-tracking branch 'origin/master' into playerimprovements
This commit is contained in:
commit
a3759c1462
@ -801,6 +801,7 @@ enum eDamageType
|
|||||||
dtPotionOfHarming,
|
dtPotionOfHarming,
|
||||||
dtEnderPearl, // Thrown an ender pearl, teleported by it
|
dtEnderPearl, // Thrown an ender pearl, teleported by it
|
||||||
dtAdmin, // Damage applied by an admin command
|
dtAdmin, // Damage applied by an admin command
|
||||||
|
dtExplosion, // Damage applied by an explosion
|
||||||
|
|
||||||
// Some common synonyms:
|
// Some common synonyms:
|
||||||
dtPawnAttack = dtAttack,
|
dtPawnAttack = dtAttack,
|
||||||
|
@ -497,7 +497,7 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// Generic template that can store any kind of data together with a triplet of 3 coords:
|
/** Generic template that can store any kind of data together with a triplet of 3 coords*/
|
||||||
template <typename X> class cCoordWithData
|
template <typename X> class cCoordWithData
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -517,12 +517,40 @@ public:
|
|||||||
}
|
}
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
// Illegal in C++03: typedef std::list< cCoordWithData<X> > cCoordWithDataList<X>;
|
|
||||||
typedef cCoordWithData<int> cCoordWithInt;
|
typedef cCoordWithData<int> cCoordWithInt;
|
||||||
typedef cCoordWithData<BLOCKTYPE> cCoordWithBlock;
|
typedef cCoordWithData<BLOCKTYPE> cCoordWithBlock;
|
||||||
|
|
||||||
typedef std::list<cCoordWithInt> cCoordWithIntList;
|
typedef std::list<cCoordWithInt> cCoordWithIntList;
|
||||||
typedef std::vector<cCoordWithInt> cCoordWithIntVector;
|
typedef std::vector<cCoordWithInt> cCoordWithIntVector;
|
||||||
typedef std::vector<cCoordWithBlock> cCoordWithBlockVector;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/** Generic template that can store two types of any kind of data together with a triplet of 3 coords */
|
||||||
|
template <typename X, typename Z> class cCoordWithDoubleData
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
int x;
|
||||||
|
int y;
|
||||||
|
int z;
|
||||||
|
X Data;
|
||||||
|
Z DataTwo;
|
||||||
|
|
||||||
|
cCoordWithDoubleData(int a_X, int a_Y, int a_Z) :
|
||||||
|
x(a_X), y(a_Y), z(a_Z)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
cCoordWithDoubleData(int a_X, int a_Y, int a_Z, const X & a_Data, const Z & a_DataTwo) :
|
||||||
|
x(a_X), y(a_Y), z(a_Z), Data(a_Data), DataTwo(a_DataTwo)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef cCoordWithDoubleData <BLOCKTYPE, bool> cCoordWithBlockAndBool;
|
||||||
|
|
||||||
|
typedef std::vector<cCoordWithBlockAndBool> cCoordWithBlockAndBoolVector;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
157
src/ChunkMap.cpp
157
src/ChunkMap.cpp
@ -15,6 +15,9 @@
|
|||||||
#include "Blocks/BlockHandler.h"
|
#include "Blocks/BlockHandler.h"
|
||||||
#include "MobCensus.h"
|
#include "MobCensus.h"
|
||||||
#include "MobSpawner.h"
|
#include "MobSpawner.h"
|
||||||
|
#include "BoundingBox.h"
|
||||||
|
|
||||||
|
#include "Entities/Pickup.h"
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
#include <cstdlib> // abs
|
#include <cstdlib> // abs
|
||||||
@ -1657,49 +1660,52 @@ void cChunkMap::DoExplosionAt(double a_ExplosionSize, double a_BlockX, double a_
|
|||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ShouldDestroyBlocks = true;
|
||||||
|
|
||||||
// Don't explode if the explosion center is inside a liquid block:
|
// Don't explode if the explosion center is inside a liquid block:
|
||||||
switch (m_World->GetBlock((int)floor(a_BlockX), (int)floor(a_BlockY), (int)floor(a_BlockZ)))
|
if (IsBlockLiquid(m_World->GetBlock((int)floor(a_BlockX), (int)floor(a_BlockY), (int)floor(a_BlockZ))))
|
||||||
{
|
{
|
||||||
case E_BLOCK_WATER:
|
ShouldDestroyBlocks = false;
|
||||||
case E_BLOCK_STATIONARY_WATER:
|
|
||||||
case E_BLOCK_LAVA:
|
|
||||||
case E_BLOCK_STATIONARY_LAVA:
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cBlockArea area;
|
int ExplosionSizeInt = (int)ceil(a_ExplosionSize);
|
||||||
|
int ExplosionSizeSq = ExplosionSizeInt * ExplosionSizeInt;
|
||||||
|
|
||||||
int bx = (int)floor(a_BlockX);
|
int bx = (int)floor(a_BlockX);
|
||||||
int by = (int)floor(a_BlockY);
|
int by = (int)floor(a_BlockY);
|
||||||
int bz = (int)floor(a_BlockZ);
|
int bz = (int)floor(a_BlockZ);
|
||||||
int ExplosionSizeInt = (int) ceil(a_ExplosionSize);
|
|
||||||
int ExplosionSizeSq = ExplosionSizeInt * ExplosionSizeInt;
|
|
||||||
a_BlocksAffected.reserve(8 * ExplosionSizeInt * ExplosionSizeInt * ExplosionSizeInt);
|
|
||||||
int MinY = std::max((int)floor(a_BlockY - ExplosionSizeInt), 0);
|
int MinY = std::max((int)floor(a_BlockY - ExplosionSizeInt), 0);
|
||||||
int MaxY = std::min((int)ceil(a_BlockY + ExplosionSizeInt), cChunkDef::Height - 1);
|
int MaxY = std::min((int)ceil(a_BlockY + ExplosionSizeInt), cChunkDef::Height - 1);
|
||||||
area.Read(m_World, bx - ExplosionSizeInt, (int)ceil(a_BlockX + ExplosionSizeInt), MinY, MaxY, bz - ExplosionSizeInt, (int)ceil(a_BlockZ + ExplosionSizeInt));
|
|
||||||
for (int x = -ExplosionSizeInt; x < ExplosionSizeInt; x++)
|
if (ShouldDestroyBlocks)
|
||||||
{
|
{
|
||||||
for (int y = -ExplosionSizeInt; y < ExplosionSizeInt; y++)
|
cBlockArea area;
|
||||||
|
|
||||||
|
a_BlocksAffected.reserve(8 * ExplosionSizeInt * ExplosionSizeInt * ExplosionSizeInt);
|
||||||
|
|
||||||
|
area.Read(m_World, bx - ExplosionSizeInt, (int)ceil(a_BlockX + ExplosionSizeInt), MinY, MaxY, bz - ExplosionSizeInt, (int)ceil(a_BlockZ + ExplosionSizeInt));
|
||||||
|
for (int x = -ExplosionSizeInt; x < ExplosionSizeInt; x++)
|
||||||
{
|
{
|
||||||
if ((by + y >= cChunkDef::Height) || (by + y < 0))
|
for (int y = -ExplosionSizeInt; y < ExplosionSizeInt; y++)
|
||||||
{
|
{
|
||||||
// Outside of the world
|
if ((by + y >= cChunkDef::Height) || (by + y < 0))
|
||||||
continue;
|
|
||||||
}
|
|
||||||
for (int z = -ExplosionSizeInt; z < ExplosionSizeInt; z++)
|
|
||||||
{
|
|
||||||
if ((x * x + y * y + z * z) > ExplosionSizeSq)
|
|
||||||
{
|
{
|
||||||
// Too far away
|
// Outside of the world
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
for (int z = -ExplosionSizeInt; z < ExplosionSizeInt; z++)
|
||||||
BLOCKTYPE Block = area.GetBlockType(bx + x, by + y, bz + z);
|
|
||||||
switch (Block)
|
|
||||||
{
|
{
|
||||||
|
if ((x * x + y * y + z * z) > ExplosionSizeSq)
|
||||||
|
{
|
||||||
|
// Too far away
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
BLOCKTYPE Block = area.GetBlockType(bx + x, by + y, bz + z);
|
||||||
|
switch (Block)
|
||||||
|
{
|
||||||
case E_BLOCK_TNT:
|
case E_BLOCK_TNT:
|
||||||
{
|
{
|
||||||
// Activate the TNT, with a random fuse between 10 to 30 game ticks
|
// Activate the TNT, with a random fuse between 10 to 30 game ticks
|
||||||
@ -1724,20 +1730,20 @@ void cChunkMap::DoExplosionAt(double a_ExplosionSize, double a_BlockX, double a_
|
|||||||
area.SetBlockType(bx + x, by + y, bz + z, E_BLOCK_WATER);
|
area.SetBlockType(bx + x, by + y, bz + z, E_BLOCK_WATER);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case E_BLOCK_STATIONARY_LAVA:
|
case E_BLOCK_STATIONARY_LAVA:
|
||||||
{
|
{
|
||||||
// Turn into simulated lava:
|
// Turn into simulated lava:
|
||||||
area.SetBlockType(bx + x, by + y, bz + z, E_BLOCK_LAVA);
|
area.SetBlockType(bx + x, by + y, bz + z, E_BLOCK_LAVA);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case E_BLOCK_AIR:
|
case E_BLOCK_AIR:
|
||||||
{
|
{
|
||||||
// No pickups for air
|
// No pickups for air
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
if (m_World->GetTickRandomNumber(100) <= 25) // 25% chance of pickups
|
if (m_World->GetTickRandomNumber(100) <= 25) // 25% chance of pickups
|
||||||
@ -1751,11 +1757,90 @@ void cChunkMap::DoExplosionAt(double a_ExplosionSize, double a_BlockX, double a_
|
|||||||
area.SetBlockType(bx + x, by + y, bz + z, E_BLOCK_AIR);
|
area.SetBlockType(bx + x, by + y, bz + z, E_BLOCK_AIR);
|
||||||
a_BlocksAffected.push_back(Vector3i(bx + x, by + y, bz + z));
|
a_BlocksAffected.push_back(Vector3i(bx + x, by + y, bz + z));
|
||||||
}
|
}
|
||||||
} // switch (BlockType)
|
} // switch (BlockType)
|
||||||
} // for z
|
} // for z
|
||||||
} // for y
|
} // for y
|
||||||
} // for x
|
} // for x
|
||||||
area.Write(m_World, bx - ExplosionSizeInt, MinY, bz - ExplosionSizeInt);
|
area.Write(m_World, bx - ExplosionSizeInt, MinY, bz - ExplosionSizeInt);
|
||||||
|
}
|
||||||
|
|
||||||
|
class cTNTDamageCallback :
|
||||||
|
public cEntityCallback
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
cTNTDamageCallback(cBoundingBox & a_bbTNT, Vector3d a_ExplosionPos, int a_ExplosionSize, int a_ExplosionSizeSq) :
|
||||||
|
m_bbTNT(a_bbTNT),
|
||||||
|
m_ExplosionPos(a_ExplosionPos),
|
||||||
|
m_ExplosionSize(a_ExplosionSize),
|
||||||
|
m_ExplosionSizeSq(a_ExplosionSizeSq)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool Item(cEntity * a_Entity) override
|
||||||
|
{
|
||||||
|
if (a_Entity->IsPickup())
|
||||||
|
{
|
||||||
|
if (((cPickup *)a_Entity)->GetAge() < 20) // If pickup age is smaller than one second, it is invincible (so we don't kill pickups that were just spawned)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector3d EntityPos = a_Entity->GetPosition();
|
||||||
|
cBoundingBox bbEntity(EntityPos, a_Entity->GetWidth() / 2, a_Entity->GetHeight());
|
||||||
|
|
||||||
|
if (!m_bbTNT.IsInside(bbEntity)) // IsInside actually acts like DoesSurround
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector3d AbsoluteEntityPos(abs(EntityPos.x), abs(EntityPos.y), abs(EntityPos.z));
|
||||||
|
Vector3d MaxExplosionBoundary(m_ExplosionSizeSq, m_ExplosionSizeSq, m_ExplosionSizeSq);
|
||||||
|
|
||||||
|
// Work out how far we are from the edge of the TNT's explosive effect
|
||||||
|
AbsoluteEntityPos -= m_ExplosionPos;
|
||||||
|
AbsoluteEntityPos = MaxExplosionBoundary - AbsoluteEntityPos;
|
||||||
|
|
||||||
|
double FinalDamage = ((AbsoluteEntityPos.x + AbsoluteEntityPos.y + AbsoluteEntityPos.z) / 3) * m_ExplosionSize;
|
||||||
|
FinalDamage = a_Entity->GetMaxHealth() - abs(FinalDamage);
|
||||||
|
|
||||||
|
// Clip damage values
|
||||||
|
if (FinalDamage > a_Entity->GetMaxHealth())
|
||||||
|
FinalDamage = a_Entity->GetMaxHealth();
|
||||||
|
else if (FinalDamage < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!a_Entity->IsTNT()) // Don't apply damage to other TNT entities, they should be invincible
|
||||||
|
{
|
||||||
|
a_Entity->TakeDamage(dtExplosion, NULL, (int)FinalDamage, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply force to entities around the explosion - code modified from World.cpp DoExplosionAt()
|
||||||
|
Vector3d distance_explosion = a_Entity->GetPosition() - m_ExplosionPos;
|
||||||
|
if (distance_explosion.SqrLength() < 4096.0)
|
||||||
|
{
|
||||||
|
distance_explosion.Normalize();
|
||||||
|
distance_explosion *= m_ExplosionSizeSq;
|
||||||
|
|
||||||
|
a_Entity->AddSpeed(distance_explosion);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
cBoundingBox & m_bbTNT;
|
||||||
|
Vector3d m_ExplosionPos;
|
||||||
|
int m_ExplosionSize;
|
||||||
|
int m_ExplosionSizeSq;
|
||||||
|
};
|
||||||
|
|
||||||
|
cBoundingBox bbTNT(Vector3d(a_BlockX, a_BlockY, a_BlockZ), 0.5, 1);
|
||||||
|
bbTNT.Expand(ExplosionSizeInt * 2, ExplosionSizeInt * 2, ExplosionSizeInt * 2);
|
||||||
|
|
||||||
|
|
||||||
|
cTNTDamageCallback TNTDamageCallback(bbTNT, Vector3d(a_BlockX, a_BlockY, a_BlockZ), a_ExplosionSize, ExplosionSizeSq);
|
||||||
|
ForEachEntity(TNTDamageCallback);
|
||||||
|
|
||||||
// Wake up all simulators for the area, so that water and lava flows and sand falls into the blasted holes (FS #391):
|
// Wake up all simulators for the area, so that water and lava flows and sand falls into the blasted holes (FS #391):
|
||||||
WakeUpSimulatorsInArea(
|
WakeUpSimulatorsInArea(
|
||||||
|
@ -263,6 +263,15 @@ inline bool IsBlockWater(BLOCKTYPE a_BlockType)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
inline bool IsBlockWaterOrIce(BLOCKTYPE a_BlockType)
|
||||||
|
{
|
||||||
|
return (IsBlockWater(a_BlockType) || (a_BlockType == E_BLOCK_ICE));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
inline bool IsBlockLava(BLOCKTYPE a_BlockType)
|
inline bool IsBlockLava(BLOCKTYPE a_BlockType)
|
||||||
{
|
{
|
||||||
return ((a_BlockType == E_BLOCK_LAVA) || (a_BlockType == E_BLOCK_STATIONARY_LAVA));
|
return ((a_BlockType == E_BLOCK_LAVA) || (a_BlockType == E_BLOCK_STATIONARY_LAVA));
|
||||||
|
@ -397,6 +397,7 @@ int cEntity::GetArmorCoverAgainst(const cEntity * a_Attacker, eDamageType a_Dama
|
|||||||
case dtPotionOfHarming:
|
case dtPotionOfHarming:
|
||||||
case dtFalling:
|
case dtFalling:
|
||||||
case dtLightning:
|
case dtLightning:
|
||||||
|
case dtPlugin:
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -473,7 +474,7 @@ void cEntity::KilledBy(cEntity * a_Killer)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Drop loot:
|
// Drop loot:
|
||||||
cItems Drops;
|
cItems Drops;
|
||||||
GetDrops(Drops, a_Killer);
|
GetDrops(Drops, a_Killer);
|
||||||
m_World->SpawnItemPickups(Drops, GetPosX(), GetPosY(), GetPosZ());
|
m_World->SpawnItemPickups(Drops, GetPosX(), GetPosY(), GetPosZ());
|
||||||
|
@ -792,11 +792,11 @@ void cPlayer::SetFlying(bool a_IsFlying)
|
|||||||
|
|
||||||
void cPlayer::DoTakeDamage(TakeDamageInfo & a_TDI)
|
void cPlayer::DoTakeDamage(TakeDamageInfo & a_TDI)
|
||||||
{
|
{
|
||||||
if (a_TDI.DamageType != dtInVoid)
|
if ((a_TDI.DamageType != dtInVoid) && (a_TDI.DamageType != dtPlugin))
|
||||||
{
|
{
|
||||||
if (IsGameModeCreative())
|
if (IsGameModeCreative())
|
||||||
{
|
{
|
||||||
// No damage / health in creative mode if not void damage
|
// No damage / health in creative mode if not void or plugin damage
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -69,47 +69,51 @@ cGroupManager::cGroupManager()
|
|||||||
}
|
}
|
||||||
|
|
||||||
unsigned int NumKeys = IniFile.GetNumKeys();
|
unsigned int NumKeys = IniFile.GetNumKeys();
|
||||||
for( unsigned int i = 0; i < NumKeys; i++ )
|
for (size_t i = 0; i < NumKeys; i++)
|
||||||
{
|
{
|
||||||
std::string KeyName = IniFile.GetKeyName( i );
|
std::string KeyName = IniFile.GetKeyName( i );
|
||||||
cGroup* Group = GetGroup( KeyName.c_str() );
|
cGroup* Group = GetGroup( KeyName.c_str() );
|
||||||
|
|
||||||
LOGD("Loading group: %s", KeyName.c_str() );
|
LOGD("Loading group: %s", KeyName.c_str() );
|
||||||
|
|
||||||
Group->SetName( KeyName );
|
Group->SetName(KeyName);
|
||||||
char Color = IniFile.GetValue( KeyName, "Color", "-" )[0];
|
AString Color = IniFile.GetValue(KeyName, "Color", "-");
|
||||||
if( Color != '-' )
|
if ((Color != "-") && (Color.length() >= 1))
|
||||||
Group->SetColor( cChatColor::Color + Color );
|
{
|
||||||
|
Group->SetColor(cChatColor::Color + Color[0]);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
Group->SetColor( cChatColor::White );
|
|
||||||
|
|
||||||
AString Commands = IniFile.GetValue( KeyName, "Commands", "" );
|
|
||||||
if( Commands.size() > 0 )
|
|
||||||
{
|
{
|
||||||
AStringVector Split = StringSplit( Commands, "," );
|
Group->SetColor(cChatColor::White);
|
||||||
for( unsigned int i = 0; i < Split.size(); i++)
|
}
|
||||||
|
|
||||||
|
AString Commands = IniFile.GetValue(KeyName, "Commands", "");
|
||||||
|
if (!Commands.empty())
|
||||||
|
{
|
||||||
|
AStringVector Split = StringSplitAndTrim(Commands, ",");
|
||||||
|
for (size_t i = 0; i < Split.size(); i++)
|
||||||
{
|
{
|
||||||
Group->AddCommand( Split[i] );
|
Group->AddCommand(Split[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AString Permissions = IniFile.GetValue( KeyName, "Permissions", "" );
|
AString Permissions = IniFile.GetValue(KeyName, "Permissions", "");
|
||||||
if( Permissions.size() > 0 )
|
if (!Permissions.empty())
|
||||||
{
|
{
|
||||||
AStringVector Split = StringSplit( Permissions, "," );
|
AStringVector Split = StringSplitAndTrim(Permissions, ",");
|
||||||
for( unsigned int i = 0; i < Split.size(); i++)
|
for (size_t i = 0; i < Split.size(); i++)
|
||||||
{
|
{
|
||||||
Group->AddPermission( Split[i] );
|
Group->AddPermission(Split[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Groups = IniFile.GetValue( KeyName, "Inherits", "" );
|
std::string Groups = IniFile.GetValue(KeyName, "Inherits", "");
|
||||||
if( Groups.size() > 0 )
|
if (!Groups.empty())
|
||||||
{
|
{
|
||||||
AStringVector Split = StringSplit( Groups, "," );
|
AStringVector Split = StringSplitAndTrim(Groups, ",");
|
||||||
for( unsigned int i = 0; i < Split.size(); i++)
|
for (size_t i = 0; i < Split.size(); i++)
|
||||||
{
|
{
|
||||||
Group->InheritFrom( GetGroup( Split[i].c_str() ) );
|
Group->InheritFrom(GetGroup(Split[i].c_str()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -209,6 +209,10 @@ bool cSocketThreads::cSocketThread::RemoveClient(const cCallback * a_Client)
|
|||||||
if (m_Slots[i].m_State == sSlot::ssRemoteClosed)
|
if (m_Slots[i].m_State == sSlot::ssRemoteClosed)
|
||||||
{
|
{
|
||||||
// The remote has already closed the socket, remove the slot altogether:
|
// The remote has already closed the socket, remove the slot altogether:
|
||||||
|
if (m_Slots[i].m_Socket.IsValid())
|
||||||
|
{
|
||||||
|
m_Slots[i].m_Socket.CloseSocket();
|
||||||
|
}
|
||||||
m_Slots[i] = m_Slots[--m_NumSlots];
|
m_Slots[i] = m_Slots[--m_NumSlots];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -489,6 +493,7 @@ void cSocketThreads::cSocketThread::ReadFromSockets(fd_set * a_Read)
|
|||||||
// Notify the callback that the remote has closed the socket; keep the slot
|
// Notify the callback that the remote has closed the socket; keep the slot
|
||||||
m_Slots[i].m_Client->SocketClosed();
|
m_Slots[i].m_Client->SocketClosed();
|
||||||
m_Slots[i].m_State = sSlot::ssRemoteClosed;
|
m_Slots[i].m_State = sSlot::ssRemoteClosed;
|
||||||
|
m_Slots[i].m_Socket.CloseSocket();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case sSlot::ssWritingRestOut:
|
case sSlot::ssWritingRestOut:
|
||||||
@ -557,6 +562,11 @@ void cSocketThreads::cSocketThread::WriteToSockets(fd_set * a_Write)
|
|||||||
}
|
}
|
||||||
} // if (outgoing data is empty)
|
} // if (outgoing data is empty)
|
||||||
|
|
||||||
|
if (m_Slots[i].m_State == sSlot::ssRemoteClosed)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (!SendDataThroughSocket(m_Slots[i].m_Socket, m_Slots[i].m_Outgoing))
|
if (!SendDataThroughSocket(m_Slots[i].m_Socket, m_Slots[i].m_Outgoing))
|
||||||
{
|
{
|
||||||
int Err = cSocket::GetLastError();
|
int Err = cSocket::GetLastError();
|
||||||
@ -566,7 +576,7 @@ void cSocketThreads::cSocketThread::WriteToSockets(fd_set * a_Write)
|
|||||||
{
|
{
|
||||||
m_Slots[i].m_Client->SocketClosed();
|
m_Slots[i].m_Client->SocketClosed();
|
||||||
}
|
}
|
||||||
return;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_Slots[i].m_Outgoing.empty() && (m_Slots[i].m_State == sSlot::ssWritingRestOut))
|
if (m_Slots[i].m_Outgoing.empty() && (m_Slots[i].m_State == sSlot::ssWritingRestOut))
|
||||||
|
@ -9,7 +9,6 @@
|
|||||||
#include "../Blocks/BlockTorch.h"
|
#include "../Blocks/BlockTorch.h"
|
||||||
#include "../Blocks/BlockDoor.h"
|
#include "../Blocks/BlockDoor.h"
|
||||||
#include "../Piston.h"
|
#include "../Piston.h"
|
||||||
#include "../Tracer.h"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -170,7 +169,7 @@ void cRedstoneSimulator::AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, cChu
|
|||||||
{
|
{
|
||||||
if (!IsAllowedBlock(Block))
|
if (!IsAllowedBlock(Block))
|
||||||
{
|
{
|
||||||
ChunkData.erase(itr); // The new blocktype is not redstone; it must be removed from this list
|
itr->DataTwo = true; // The new blocktype is not redstone; it must be queued to be removed from this list
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -185,7 +184,7 @@ void cRedstoneSimulator::AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, cChu
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ChunkData.push_back(cCoordWithBlock(RelX, a_BlockY, RelZ, Block));
|
ChunkData.push_back(cCoordWithBlockAndBool(RelX, a_BlockY, RelZ, Block, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -208,8 +207,14 @@ void cRedstoneSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, c
|
|||||||
int BaseX = a_Chunk->GetPosX() * cChunkDef::Width;
|
int BaseX = a_Chunk->GetPosX() * cChunkDef::Width;
|
||||||
int BaseZ = a_Chunk->GetPosZ() * cChunkDef::Width;
|
int BaseZ = a_Chunk->GetPosZ() * cChunkDef::Width;
|
||||||
|
|
||||||
for (cRedstoneSimulatorChunkData::const_iterator dataitr = ChunkData.begin(); dataitr != ChunkData.end(); ++dataitr)
|
for (cRedstoneSimulatorChunkData::iterator dataitr = ChunkData.begin(); dataitr != ChunkData.end();)
|
||||||
{
|
{
|
||||||
|
if (dataitr->DataTwo)
|
||||||
|
{
|
||||||
|
dataitr = ChunkData.erase(dataitr);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
int a_X = BaseX + dataitr->x;
|
int a_X = BaseX + dataitr->x;
|
||||||
int a_Z = BaseZ + dataitr->z;
|
int a_Z = BaseZ + dataitr->z;
|
||||||
switch (dataitr->Data)
|
switch (dataitr->Data)
|
||||||
@ -279,6 +284,7 @@ void cRedstoneSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, c
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
++dataitr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -919,7 +925,7 @@ void cRedstoneSimulator::HandlePressurePlate(int a_BlockX, int a_BlockY, int a_B
|
|||||||
case E_BLOCK_STONE_PRESSURE_PLATE:
|
case E_BLOCK_STONE_PRESSURE_PLATE:
|
||||||
{
|
{
|
||||||
// MCS feature - stone pressure plates can only be triggered by players :D
|
// MCS feature - stone pressure plates can only be triggered by players :D
|
||||||
cPlayer * a_Player = m_World.FindClosestPlayer(Vector3f(a_BlockX + 0.5f, (float)a_BlockY, a_BlockZ + 0.5f), 0.5f);
|
cPlayer * a_Player = m_World.FindClosestPlayer(Vector3f(a_BlockX + 0.5f, (float)a_BlockY, a_BlockZ + 0.5f), 0.5f, false);
|
||||||
|
|
||||||
if (a_Player != NULL)
|
if (a_Player != NULL)
|
||||||
{
|
{
|
||||||
@ -950,19 +956,14 @@ void cRedstoneSimulator::HandlePressurePlate(int a_BlockX, int a_BlockY, int a_B
|
|||||||
|
|
||||||
virtual bool Item(cEntity * a_Entity) override
|
virtual bool Item(cEntity * a_Entity) override
|
||||||
{
|
{
|
||||||
cTracer LineOfSight(m_World);
|
|
||||||
|
|
||||||
Vector3f EntityPos = a_Entity->GetPosition();
|
Vector3f EntityPos = a_Entity->GetPosition();
|
||||||
Vector3f BlockPos(m_X + 0.5f, (float)m_Y, m_Z + 0.5f);
|
Vector3f BlockPos(m_X + 0.5f, (float)m_Y, m_Z + 0.5f);
|
||||||
float Distance = (EntityPos - BlockPos).Length();
|
float Distance = (EntityPos - BlockPos).Length();
|
||||||
|
|
||||||
if (Distance < 0.5)
|
if (Distance < 0.5)
|
||||||
{
|
{
|
||||||
if (!LineOfSight.Trace(BlockPos, (EntityPos - BlockPos), (int)(EntityPos - BlockPos).Length()))
|
m_Entity = a_Entity;
|
||||||
{
|
return true; // Break out, we only need to know for wooden plates that at least one entity is on top
|
||||||
m_Entity = a_Entity;
|
|
||||||
return true; // Break out, we only need to know for wooden plates that at least one entity is on top
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
#include "Simulator.h"
|
#include "Simulator.h"
|
||||||
|
|
||||||
/// Per-chunk data for the simulator, specified individual chunks to simulate; 'Data' is not used
|
/// Per-chunk data for the simulator, specified individual chunks to simulate; 'Data' is not used
|
||||||
typedef cCoordWithBlockVector cRedstoneSimulatorChunkData;
|
typedef cCoordWithBlockAndBoolVector cRedstoneSimulatorChunkData;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -632,7 +632,7 @@ void cWorld::GenerateRandomSpawn(void)
|
|||||||
{
|
{
|
||||||
LOGD("Generating random spawnpoint...");
|
LOGD("Generating random spawnpoint...");
|
||||||
|
|
||||||
while (IsBlockWater(GetBlock((int)m_SpawnX, GetHeight((int)m_SpawnX, (int)m_SpawnZ), (int)m_SpawnZ)))
|
while (IsBlockWaterOrIce(GetBlock((int)m_SpawnX, GetHeight((int)m_SpawnX, (int)m_SpawnZ), (int)m_SpawnZ)))
|
||||||
{
|
{
|
||||||
if ((GetTickRandomNumber(4) % 2) == 0) // Randomise whether to increment X or Z coords
|
if ((GetTickRandomNumber(4) % 2) == 0) // Randomise whether to increment X or Z coords
|
||||||
{
|
{
|
||||||
@ -1551,7 +1551,7 @@ void cWorld::SpawnItemPickups(const cItems & a_Pickups, double a_BlockX, double
|
|||||||
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)
|
||||||
{
|
{
|
||||||
if (!IsValidItem(itr->m_ItemType))
|
if (!IsValidItem(itr->m_ItemType) || itr->m_ItemType == E_BLOCK_AIR)
|
||||||
{
|
{
|
||||||
// Don't spawn pickup if item isn't even valid; should prevent client crashing too
|
// Don't spawn pickup if item isn't even valid; should prevent client crashing too
|
||||||
continue;
|
continue;
|
||||||
@ -1577,7 +1577,7 @@ void cWorld::SpawnItemPickups(const cItems & a_Pickups, double a_BlockX, double
|
|||||||
{
|
{
|
||||||
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)
|
||||||
{
|
{
|
||||||
if (!IsValidItem(itr->m_ItemType))
|
if (!IsValidItem(itr->m_ItemType) || itr->m_ItemType == E_BLOCK_AIR)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user