commit
e400b1acd8
@ -802,7 +802,7 @@ void cCraftingRecipes::HandleFireworks(const cItem * a_CraftingGrid, cCraftingRe
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case E_ITEM_PAPER: break;
|
case E_ITEM_PAPER: break;
|
||||||
default: LOG("Unexpected item in firework rocket a_Recipe, was the crafting file fireworks section changed?"); break;
|
default: LOG("Unexpected item in firework rocket recipe, was the crafting file's fireworks section changed?"); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -837,7 +837,7 @@ void cCraftingRecipes::HandleFireworks(const cItem * a_CraftingGrid, cCraftingRe
|
|||||||
case E_ITEM_GOLD_NUGGET: a_Recipe->m_Result.m_FireworkItem.m_Type = 2; break;
|
case E_ITEM_GOLD_NUGGET: a_Recipe->m_Result.m_FireworkItem.m_Type = 2; break;
|
||||||
case E_ITEM_FEATHER: a_Recipe->m_Result.m_FireworkItem.m_Type = 4; break;
|
case E_ITEM_FEATHER: a_Recipe->m_Result.m_FireworkItem.m_Type = 4; break;
|
||||||
case E_ITEM_HEAD: a_Recipe->m_Result.m_FireworkItem.m_Type = 3; break;
|
case E_ITEM_HEAD: a_Recipe->m_Result.m_FireworkItem.m_Type = 3; break;
|
||||||
default: LOG("Unexpected item in firework star a_Recipe, was the crafting file fireworks section changed?"); break; // ermahgerd BARD ardmins
|
default: LOG("Unexpected item in firework star recipe, was the crafting file's fireworks section changed?"); break; // ermahgerd BARD ardmins
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
|
||||||
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
|
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
|
||||||
|
|
||||||
#include "Entity.h"
|
#include "Entity.h"
|
||||||
@ -10,7 +11,6 @@
|
|||||||
#include "../Simulator/FluidSimulator.h"
|
#include "../Simulator/FluidSimulator.h"
|
||||||
#include "../Bindings/PluginManager.h"
|
#include "../Bindings/PluginManager.h"
|
||||||
#include "../Tracer.h"
|
#include "../Tracer.h"
|
||||||
#include "Minecart.h"
|
|
||||||
#include "Player.h"
|
#include "Player.h"
|
||||||
|
|
||||||
|
|
||||||
@ -32,16 +32,10 @@ cEntity::cEntity(eEntityType a_EntityType, double a_X, double a_Y, double a_Z, d
|
|||||||
, m_Attachee(NULL)
|
, m_Attachee(NULL)
|
||||||
, m_bDirtyHead(true)
|
, m_bDirtyHead(true)
|
||||||
, m_bDirtyOrientation(true)
|
, m_bDirtyOrientation(true)
|
||||||
, m_bDirtyPosition(true)
|
, m_bHasSentNoSpeed(true)
|
||||||
, m_bDirtySpeed(true)
|
, m_bOnGround(false)
|
||||||
, m_bOnGround( false )
|
, m_Gravity(-9.81f)
|
||||||
, m_Gravity( -9.81f )
|
, m_LastPos(a_X, a_Y, a_Z)
|
||||||
, m_LastPosX( 0.0 )
|
|
||||||
, m_LastPosY( 0.0 )
|
|
||||||
, m_LastPosZ( 0.0 )
|
|
||||||
, m_TimeLastTeleportPacket(0)
|
|
||||||
, m_TimeLastMoveReltPacket(0)
|
|
||||||
, m_TimeLastSpeedPacket(0)
|
|
||||||
, m_IsInitialized(false)
|
, m_IsInitialized(false)
|
||||||
, m_EntityType(a_EntityType)
|
, m_EntityType(a_EntityType)
|
||||||
, m_World(NULL)
|
, m_World(NULL)
|
||||||
@ -55,7 +49,7 @@ cEntity::cEntity(eEntityType a_EntityType, double a_X, double a_Y, double a_Z, d
|
|||||||
, m_IsSubmerged(false)
|
, m_IsSubmerged(false)
|
||||||
, m_AirLevel(0)
|
, m_AirLevel(0)
|
||||||
, m_AirTickTimer(0)
|
, m_AirTickTimer(0)
|
||||||
, m_HeadYaw( 0.0 )
|
, m_HeadYaw(0.0)
|
||||||
, m_Rot(0.0, 0.0, 0.0)
|
, m_Rot(0.0, 0.0, 0.0)
|
||||||
, m_Pos(a_X, a_Y, a_Z)
|
, m_Pos(a_X, a_Y, a_Z)
|
||||||
, m_WaterSpeed(0, 0, 0)
|
, m_WaterSpeed(0, 0, 0)
|
||||||
@ -794,30 +788,43 @@ void cEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk)
|
|||||||
|
|
||||||
NextSpeed += m_WaterSpeed;
|
NextSpeed += m_WaterSpeed;
|
||||||
|
|
||||||
if( NextSpeed.SqrLength() > 0.f )
|
if (NextSpeed.SqrLength() > 0.f)
|
||||||
{
|
{
|
||||||
cTracer Tracer( GetWorld() );
|
cTracer Tracer(GetWorld());
|
||||||
bool HasHit = Tracer.Trace( NextPos, NextSpeed, 2 );
|
// Distance traced is an integer, so we round up from the distance we should go (Speed * Delta), else we will encounter collision detection failurse
|
||||||
if (HasHit) // Oh noez! we hit something
|
int DistanceToTrace = (int)(ceil((NextSpeed * a_Dt).SqrLength()) * 2);
|
||||||
|
bool HasHit = Tracer.Trace(NextPos, NextSpeed, DistanceToTrace);
|
||||||
|
|
||||||
|
if (HasHit)
|
||||||
{
|
{
|
||||||
// Set to hit position
|
// Oh noez! We hit something: verify that the (hit position - current) was smaller or equal to the (position that we should travel without obstacles - current)
|
||||||
|
// This is because previously, we traced with a length that was rounded up (due to integer limitations), and in the case that something was hit, we don't want to overshoot our projected movement
|
||||||
if ((Tracer.RealHit - NextPos).SqrLength() <= (NextSpeed * a_Dt).SqrLength())
|
if ((Tracer.RealHit - NextPos).SqrLength() <= (NextSpeed * a_Dt).SqrLength())
|
||||||
{
|
{
|
||||||
|
// Block hit was within our projected path
|
||||||
|
// Begin by stopping movement in the direction that we hit something. The Normal is the line perpendicular to a 2D face and in this case, stores what block face was hit through either -1 or 1.
|
||||||
|
// For example: HitNormal.y = -1 : BLOCK_FACE_YM; HitNormal.y = 1 : BLOCK_FACE_YP
|
||||||
if (Tracer.HitNormal.x != 0.f) NextSpeed.x = 0.f;
|
if (Tracer.HitNormal.x != 0.f) NextSpeed.x = 0.f;
|
||||||
if (Tracer.HitNormal.y != 0.f) NextSpeed.y = 0.f;
|
if (Tracer.HitNormal.y != 0.f) NextSpeed.y = 0.f;
|
||||||
if (Tracer.HitNormal.z != 0.f) NextSpeed.z = 0.f;
|
if (Tracer.HitNormal.z != 0.f) NextSpeed.z = 0.f;
|
||||||
|
|
||||||
if (Tracer.HitNormal.y > 0) // means on ground
|
if (Tracer.HitNormal.y == 1) // Hit BLOCK_FACE_YP, we are on the ground
|
||||||
{
|
{
|
||||||
m_bOnGround = true;
|
m_bOnGround = true;
|
||||||
}
|
}
|
||||||
NextPos.Set(Tracer.RealHit.x,Tracer.RealHit.y,Tracer.RealHit.z);
|
|
||||||
NextPos.x += Tracer.HitNormal.x * 0.3f;
|
// Now, set our position to the hit block (i.e. move part way along our intended trajectory)
|
||||||
NextPos.y += Tracer.HitNormal.y * 0.05f; // Any larger produces entity vibration-upon-the-spot
|
NextPos.Set(Tracer.RealHit.x, Tracer.RealHit.y, Tracer.RealHit.z);
|
||||||
NextPos.z += Tracer.HitNormal.z * 0.3f;
|
NextPos.x += Tracer.HitNormal.x * 0.1;
|
||||||
|
NextPos.y += Tracer.HitNormal.y * 0.05;
|
||||||
|
NextPos.z += Tracer.HitNormal.z * 0.1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// We have hit a block but overshot our intended trajectory, move normally, safe in the warm cocoon of knowledge that we won't appear to teleport forwards on clients,
|
||||||
|
// and that this piece of software will come to be hailed as the epitome of performance and functionality in C++, never before seen, and of such a like that will never
|
||||||
|
// be henceforth seen again in the time of programmers and man alike
|
||||||
|
// </&sensationalist>
|
||||||
NextPos += (NextSpeed * a_Dt);
|
NextPos += (NextSpeed * a_Dt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1010,9 +1017,9 @@ void cEntity::SetSwimState(cChunk & a_Chunk)
|
|||||||
{
|
{
|
||||||
// This sometimes happens on Linux machines
|
// This sometimes happens on Linux machines
|
||||||
// Ref.: http://forum.mc-server.org/showthread.php?tid=1244
|
// Ref.: http://forum.mc-server.org/showthread.php?tid=1244
|
||||||
LOGD("SetSwimState failure: RelX = %d, RelZ = %d, LastPos = {%.02f, %.02f}, Pos = %.02f, %.02f}",
|
LOGD("SetSwimState failure: RelX = %d, RelZ = %d, Pos = %.02f, %.02f}",
|
||||||
RelX, RelY, m_LastPosX, m_LastPosZ, GetPosX(), GetPosZ()
|
RelX, RelY, GetPosX(), GetPosZ()
|
||||||
);
|
);
|
||||||
m_IsSwimming = false;
|
m_IsSwimming = false;
|
||||||
m_IsSubmerged = false;
|
m_IsSubmerged = false;
|
||||||
return;
|
return;
|
||||||
@ -1178,72 +1185,70 @@ 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)
|
||||||
{
|
{
|
||||||
// Send velocity packet every two ticks if: speed is not negligible or speed was set (as indicated by the DirtySpeed flag)
|
// Process packet sending every two ticks
|
||||||
if (((m_Speed.SqrLength() > 0.0004f) || m_bDirtySpeed) && ((m_World->GetWorldAge() - m_TimeLastSpeedPacket) >= 2))
|
if (GetWorld()->GetWorldAge() % 2 == 0)
|
||||||
{
|
{
|
||||||
m_World->BroadcastEntityVelocity(*this,a_Exclude);
|
double SpeedSqr = GetSpeed().SqrLength();
|
||||||
m_bDirtySpeed = false;
|
if (SpeedSqr == 0.0)
|
||||||
m_TimeLastSpeedPacket = m_World->GetWorldAge();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Have to process position related packets this every two ticks
|
|
||||||
if (m_World->GetWorldAge() % 2 == 0)
|
|
||||||
{
|
|
||||||
int DiffX = (int) (floor(GetPosX() * 32.0) - floor(m_LastPosX * 32.0));
|
|
||||||
int DiffY = (int) (floor(GetPosY() * 32.0) - floor(m_LastPosY * 32.0));
|
|
||||||
int DiffZ = (int) (floor(GetPosZ() * 32.0) - floor(m_LastPosZ * 32.0));
|
|
||||||
Int64 DiffTeleportPacket = m_World->GetWorldAge() - m_TimeLastTeleportPacket;
|
|
||||||
// 4 blocks is max Relative So if the Diff is greater than 127 or. Send an absolute position every 20 seconds
|
|
||||||
if (DiffTeleportPacket >= 400 ||
|
|
||||||
((DiffX > 127) || (DiffX < -128) ||
|
|
||||||
(DiffY > 127) || (DiffY < -128) ||
|
|
||||||
(DiffZ > 127) || (DiffZ < -128)))
|
|
||||||
{
|
{
|
||||||
//
|
// Speed is zero, send this to clients once only as well as an absolute position
|
||||||
m_World->BroadcastTeleportEntity(*this,a_Exclude);
|
if (!m_bHasSentNoSpeed)
|
||||||
m_TimeLastTeleportPacket = m_World->GetWorldAge();
|
{
|
||||||
m_TimeLastMoveReltPacket = m_TimeLastTeleportPacket; //Must synchronize.
|
m_World->BroadcastEntityVelocity(*this, a_Exclude);
|
||||||
m_LastPosX = GetPosX();
|
m_World->BroadcastTeleportEntity(*this, a_Exclude);
|
||||||
m_LastPosY = GetPosY();
|
m_bHasSentNoSpeed = true;
|
||||||
m_LastPosZ = GetPosZ();
|
}
|
||||||
m_bDirtyPosition = false;
|
|
||||||
m_bDirtyOrientation = false;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Int64 DiffMoveRelPacket = m_World->GetWorldAge() - m_TimeLastMoveReltPacket;
|
// Movin'
|
||||||
//if the change is big enough.
|
m_World->BroadcastEntityVelocity(*this, a_Exclude);
|
||||||
if ((abs(DiffX) >= 4 || abs(DiffY) >= 4 || abs(DiffZ) >= 4 || DiffMoveRelPacket >= 60) && m_bDirtyPosition)
|
m_bHasSentNoSpeed = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Pickups move disgracefully if relative move packets are sent as opposed to just velocity. Have a system to send relmove only when SetPosXXX() is called with a large difference in position
|
||||||
|
int DiffX = (int)(floor(GetPosX() * 32.0) - floor(m_LastPos.x * 32.0));
|
||||||
|
int DiffY = (int)(floor(GetPosY() * 32.0) - floor(m_LastPos.y * 32.0));
|
||||||
|
int DiffZ = (int)(floor(GetPosZ() * 32.0) - floor(m_LastPos.z * 32.0));
|
||||||
|
|
||||||
|
if ((DiffX != 0) || (DiffY != 0) || (DiffZ != 0)) // Have we moved?
|
||||||
|
{
|
||||||
|
if ((abs(DiffX) <= 127) && (abs(DiffY) <= 127) && (abs(DiffZ) <= 127)) // Limitations of a Byte
|
||||||
{
|
{
|
||||||
|
// Difference within Byte limitations, use a relative move packet
|
||||||
if (m_bDirtyOrientation)
|
if (m_bDirtyOrientation)
|
||||||
{
|
{
|
||||||
m_World->BroadcastEntityRelMoveLook(*this, (char)DiffX, (char)DiffY, (char)DiffZ,a_Exclude);
|
m_World->BroadcastEntityRelMoveLook(*this, (char)DiffX, (char)DiffY, (char)DiffZ, a_Exclude);
|
||||||
m_bDirtyOrientation = false;
|
m_bDirtyOrientation = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_World->BroadcastEntityRelMove(*this, (char)DiffX, (char)DiffY, (char)DiffZ,a_Exclude);
|
m_World->BroadcastEntityRelMove(*this, (char)DiffX, (char)DiffY, (char)DiffZ, a_Exclude);
|
||||||
}
|
}
|
||||||
m_LastPosX = GetPosX();
|
// Clients seem to store two positions, one for the velocity packet and one for the teleport/relmove packet
|
||||||
m_LastPosY = GetPosY();
|
// The latter is only changed with a relmove/teleport, and m_LastPos stores this position
|
||||||
m_LastPosZ = GetPosZ();
|
m_LastPos = GetPosition();
|
||||||
m_bDirtyPosition = false;
|
|
||||||
m_TimeLastMoveReltPacket = m_World->GetWorldAge();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (m_bDirtyOrientation)
|
// Too big a movement, do a teleport
|
||||||
{
|
m_World->BroadcastTeleportEntity(*this, a_Exclude);
|
||||||
m_World->BroadcastEntityLook(*this,a_Exclude);
|
m_LastPos = GetPosition(); // See above
|
||||||
m_bDirtyOrientation = false;
|
m_bDirtyOrientation = false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_bDirtyHead)
|
if (m_bDirtyHead)
|
||||||
{
|
{
|
||||||
m_World->BroadcastEntityHeadLook(*this,a_Exclude);
|
m_World->BroadcastEntityHeadLook(*this, a_Exclude);
|
||||||
m_bDirtyHead = false;
|
m_bDirtyHead = false;
|
||||||
}
|
}
|
||||||
|
if (m_bDirtyOrientation)
|
||||||
|
{
|
||||||
|
// Send individual update in case above (sending with rel-move packet) wasn't done
|
||||||
|
GetWorld()->BroadcastEntityLook(*this, a_Exclude);
|
||||||
|
m_bDirtyOrientation = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1383,7 +1388,7 @@ void cEntity::SetRoll(double a_Roll)
|
|||||||
void cEntity::SetSpeed(double a_SpeedX, double a_SpeedY, double a_SpeedZ)
|
void cEntity::SetSpeed(double a_SpeedX, double a_SpeedY, double a_SpeedZ)
|
||||||
{
|
{
|
||||||
m_Speed.Set(a_SpeedX, a_SpeedY, a_SpeedZ);
|
m_Speed.Set(a_SpeedX, a_SpeedY, a_SpeedZ);
|
||||||
m_bDirtySpeed = true;
|
|
||||||
WrapSpeed();
|
WrapSpeed();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1393,7 +1398,7 @@ void cEntity::SetSpeed(double a_SpeedX, double a_SpeedY, double a_SpeedZ)
|
|||||||
void cEntity::SetSpeedX(double a_SpeedX)
|
void cEntity::SetSpeedX(double a_SpeedX)
|
||||||
{
|
{
|
||||||
m_Speed.x = a_SpeedX;
|
m_Speed.x = a_SpeedX;
|
||||||
m_bDirtySpeed = true;
|
|
||||||
WrapSpeed();
|
WrapSpeed();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1403,7 +1408,7 @@ void cEntity::SetSpeedX(double a_SpeedX)
|
|||||||
void cEntity::SetSpeedY(double a_SpeedY)
|
void cEntity::SetSpeedY(double a_SpeedY)
|
||||||
{
|
{
|
||||||
m_Speed.y = a_SpeedY;
|
m_Speed.y = a_SpeedY;
|
||||||
m_bDirtySpeed = true;
|
|
||||||
WrapSpeed();
|
WrapSpeed();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1413,7 +1418,7 @@ void cEntity::SetSpeedY(double a_SpeedY)
|
|||||||
void cEntity::SetSpeedZ(double a_SpeedZ)
|
void cEntity::SetSpeedZ(double a_SpeedZ)
|
||||||
{
|
{
|
||||||
m_Speed.z = a_SpeedZ;
|
m_Speed.z = a_SpeedZ;
|
||||||
m_bDirtySpeed = true;
|
|
||||||
WrapSpeed();
|
WrapSpeed();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1433,7 +1438,7 @@ void cEntity::SetWidth(double a_Width)
|
|||||||
void cEntity::AddPosX(double a_AddPosX)
|
void cEntity::AddPosX(double a_AddPosX)
|
||||||
{
|
{
|
||||||
m_Pos.x += a_AddPosX;
|
m_Pos.x += a_AddPosX;
|
||||||
m_bDirtyPosition = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1442,7 +1447,7 @@ void cEntity::AddPosX(double a_AddPosX)
|
|||||||
void cEntity::AddPosY(double a_AddPosY)
|
void cEntity::AddPosY(double a_AddPosY)
|
||||||
{
|
{
|
||||||
m_Pos.y += a_AddPosY;
|
m_Pos.y += a_AddPosY;
|
||||||
m_bDirtyPosition = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1451,7 +1456,7 @@ void cEntity::AddPosY(double a_AddPosY)
|
|||||||
void cEntity::AddPosZ(double a_AddPosZ)
|
void cEntity::AddPosZ(double a_AddPosZ)
|
||||||
{
|
{
|
||||||
m_Pos.z += a_AddPosZ;
|
m_Pos.z += a_AddPosZ;
|
||||||
m_bDirtyPosition = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1462,7 +1467,7 @@ void cEntity::AddPosition(double a_AddPosX, double a_AddPosY, double a_AddPosZ)
|
|||||||
m_Pos.x += a_AddPosX;
|
m_Pos.x += a_AddPosX;
|
||||||
m_Pos.y += a_AddPosY;
|
m_Pos.y += a_AddPosY;
|
||||||
m_Pos.z += a_AddPosZ;
|
m_Pos.z += a_AddPosZ;
|
||||||
m_bDirtyPosition = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1472,8 +1477,7 @@ void cEntity::AddSpeed(double a_AddSpeedX, double a_AddSpeedY, double a_AddSpeed
|
|||||||
{
|
{
|
||||||
m_Speed.x += a_AddSpeedX;
|
m_Speed.x += a_AddSpeedX;
|
||||||
m_Speed.y += a_AddSpeedY;
|
m_Speed.y += a_AddSpeedY;
|
||||||
m_Speed.z += a_AddSpeedZ;
|
m_Speed.z += a_AddSpeedZ;
|
||||||
m_bDirtySpeed = true;
|
|
||||||
WrapSpeed();
|
WrapSpeed();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1483,8 +1487,7 @@ void cEntity::AddSpeed(double a_AddSpeedX, double a_AddSpeedY, double a_AddSpeed
|
|||||||
|
|
||||||
void cEntity::AddSpeedX(double a_AddSpeedX)
|
void cEntity::AddSpeedX(double a_AddSpeedX)
|
||||||
{
|
{
|
||||||
m_Speed.x += a_AddSpeedX;
|
m_Speed.x += a_AddSpeedX;
|
||||||
m_bDirtySpeed = true;
|
|
||||||
WrapSpeed();
|
WrapSpeed();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1494,8 +1497,7 @@ void cEntity::AddSpeedX(double a_AddSpeedX)
|
|||||||
|
|
||||||
void cEntity::AddSpeedY(double a_AddSpeedY)
|
void cEntity::AddSpeedY(double a_AddSpeedY)
|
||||||
{
|
{
|
||||||
m_Speed.y += a_AddSpeedY;
|
m_Speed.y += a_AddSpeedY;
|
||||||
m_bDirtySpeed = true;
|
|
||||||
WrapSpeed();
|
WrapSpeed();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1505,8 +1507,7 @@ void cEntity::AddSpeedY(double a_AddSpeedY)
|
|||||||
|
|
||||||
void cEntity::AddSpeedZ(double a_AddSpeedZ)
|
void cEntity::AddSpeedZ(double a_AddSpeedZ)
|
||||||
{
|
{
|
||||||
m_Speed.z += a_AddSpeedZ;
|
m_Speed.z += a_AddSpeedZ;
|
||||||
m_bDirtySpeed = true;
|
|
||||||
WrapSpeed();
|
WrapSpeed();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1561,8 +1562,7 @@ Vector3d cEntity::GetLookVector(void) const
|
|||||||
// Set position
|
// Set position
|
||||||
void cEntity::SetPosition(double a_PosX, double a_PosY, double a_PosZ)
|
void cEntity::SetPosition(double a_PosX, double a_PosY, double a_PosZ)
|
||||||
{
|
{
|
||||||
m_Pos.Set(a_PosX, a_PosY, a_PosZ);
|
m_Pos.Set(a_PosX, a_PosY, a_PosZ);
|
||||||
m_bDirtyPosition = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1571,8 +1571,7 @@ void cEntity::SetPosition(double a_PosX, double a_PosY, double a_PosZ)
|
|||||||
|
|
||||||
void cEntity::SetPosX(double a_PosX)
|
void cEntity::SetPosX(double a_PosX)
|
||||||
{
|
{
|
||||||
m_Pos.x = a_PosX;
|
m_Pos.x = a_PosX;
|
||||||
m_bDirtyPosition = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1581,8 +1580,7 @@ void cEntity::SetPosX(double a_PosX)
|
|||||||
|
|
||||||
void cEntity::SetPosY(double a_PosY)
|
void cEntity::SetPosY(double a_PosY)
|
||||||
{
|
{
|
||||||
m_Pos.y = a_PosY;
|
m_Pos.y = a_PosY;
|
||||||
m_bDirtyPosition = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1592,7 +1590,6 @@ void cEntity::SetPosY(double a_PosY)
|
|||||||
void cEntity::SetPosZ(double a_PosZ)
|
void cEntity::SetPosZ(double a_PosZ)
|
||||||
{
|
{
|
||||||
m_Pos.z = a_PosZ;
|
m_Pos.z = a_PosZ;
|
||||||
m_bDirtyPosition = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -430,22 +430,29 @@ protected:
|
|||||||
/// The entity which is attached to this entity (rider), NULL if none
|
/// The entity which is attached to this entity (rider), NULL if none
|
||||||
cEntity * m_Attachee;
|
cEntity * m_Attachee;
|
||||||
|
|
||||||
// Flags that signal that we haven't updated the clients with the latest.
|
/** Stores whether head yaw has been set manually */
|
||||||
bool m_bDirtyHead;
|
bool m_bDirtyHead;
|
||||||
bool m_bDirtyOrientation;
|
|
||||||
bool m_bDirtyPosition;
|
|
||||||
bool m_bDirtySpeed;
|
|
||||||
|
|
||||||
bool m_bOnGround;
|
|
||||||
float m_Gravity;
|
|
||||||
|
|
||||||
// Last Position.
|
/** Stores whether our yaw/pitch/roll (body orientation) has been set manually */
|
||||||
double m_LastPosX, m_LastPosY, m_LastPosZ;
|
bool m_bDirtyOrientation;
|
||||||
|
|
||||||
|
/** Stores whether we have sent a Velocity packet with a speed of zero (no speed) to the client
|
||||||
|
Ensures that said packet is sent only once */
|
||||||
|
bool m_bHasSentNoSpeed;
|
||||||
|
|
||||||
// This variables keep track of the last time a packet was sent
|
/** Stores if the entity is on the ground */
|
||||||
Int64 m_TimeLastTeleportPacket, m_TimeLastMoveReltPacket, m_TimeLastSpeedPacket; // In ticks
|
bool m_bOnGround;
|
||||||
|
|
||||||
|
/** Stores gravity that is applied to an entity every tick
|
||||||
|
For realistic effects, this should be negative. For spaaaaaaace, this can be zero or even positive */
|
||||||
|
float m_Gravity;
|
||||||
|
|
||||||
|
/** Last position sent to client via the Relative Move or Teleport packets (not Velocity)
|
||||||
|
Only updated if cEntity::BroadcastMovementUpdate() is called! */
|
||||||
|
Vector3d m_LastPos;
|
||||||
|
|
||||||
bool m_IsInitialized; // Is set to true when it's initialized, until it's destroyed (Initialize() till Destroy() )
|
/** True when entity is initialised (Initialize()) and false when destroyed pending deletion (Destroy()) */
|
||||||
|
bool m_IsInitialized;
|
||||||
|
|
||||||
eEntityType m_EntityType;
|
eEntityType m_EntityType;
|
||||||
|
|
||||||
@ -469,12 +476,14 @@ protected:
|
|||||||
/// Time, in ticks, since the last damage dealt by the void. Reset to zero when moving out of the void.
|
/// Time, in ticks, since the last damage dealt by the void. Reset to zero when moving out of the void.
|
||||||
int m_TicksSinceLastVoidDamage;
|
int m_TicksSinceLastVoidDamage;
|
||||||
|
|
||||||
|
|
||||||
virtual void Destroyed(void) {} // Called after the entity has been destroyed
|
virtual void Destroyed(void) {} // Called after the entity has been destroyed
|
||||||
|
|
||||||
void SetWorld(cWorld * a_World) { m_World = a_World; }
|
void SetWorld(cWorld * a_World) { m_World = a_World; }
|
||||||
|
|
||||||
/** Called in each tick to handle air-related processing i.e. drowning */
|
/** Called in each tick to handle air-related processing i.e. drowning */
|
||||||
virtual void HandleAir();
|
virtual void HandleAir();
|
||||||
|
|
||||||
/** Called once per tick to set IsSwimming and IsSubmerged */
|
/** Called once per tick to set IsSwimming and IsSubmerged */
|
||||||
virtual void SetSwimState(cChunk & a_Chunk);
|
virtual void SetSwimState(cChunk & a_Chunk);
|
||||||
|
|
||||||
|
@ -34,8 +34,6 @@ cExpOrb::cExpOrb(const Vector3d & a_Pos, int a_Reward)
|
|||||||
void cExpOrb::SpawnOn(cClientHandle & a_Client)
|
void cExpOrb::SpawnOn(cClientHandle & a_Client)
|
||||||
{
|
{
|
||||||
a_Client.SendExperienceOrb(*this);
|
a_Client.SendExperienceOrb(*this);
|
||||||
m_bDirtyPosition = false;
|
|
||||||
m_bDirtySpeed = false;
|
|
||||||
m_bDirtyOrientation = false;
|
m_bDirtyOrientation = false;
|
||||||
m_bDirtyHead = false;
|
m_bDirtyHead = false;
|
||||||
}
|
}
|
||||||
|
@ -76,11 +76,8 @@ cPlayer::cPlayer(cClientHandle* a_Client, const AString & a_PlayerName)
|
|||||||
|
|
||||||
cTimer t1;
|
cTimer t1;
|
||||||
m_LastPlayerListTime = t1.GetNowTime();
|
m_LastPlayerListTime = t1.GetNowTime();
|
||||||
|
|
||||||
m_TimeLastTeleportPacket = 0;
|
|
||||||
|
|
||||||
m_PlayerName = a_PlayerName;
|
m_PlayerName = a_PlayerName;
|
||||||
m_bDirtyPosition = true; // So chunks are streamed to player at spawn
|
|
||||||
|
|
||||||
if (!LoadFromDisk())
|
if (!LoadFromDisk())
|
||||||
{
|
{
|
||||||
@ -209,25 +206,22 @@ void cPlayer::Tick(float a_Dt, cChunk & a_Chunk)
|
|||||||
m_BowCharge += 1;
|
m_BowCharge += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//handle updating experience
|
// Handle updating experience
|
||||||
if (m_bDirtyExperience)
|
if (m_bDirtyExperience)
|
||||||
{
|
{
|
||||||
SendExperience();
|
SendExperience();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_bDirtyPosition)
|
if (GetPosition() != m_LastPos) // Change in position from last tick?
|
||||||
{
|
{
|
||||||
// Apply food exhaustion from movement:
|
// Apply food exhaustion from movement:
|
||||||
ApplyFoodExhaustionFromMovement();
|
ApplyFoodExhaustionFromMovement();
|
||||||
|
|
||||||
cRoot::Get()->GetPluginManager()->CallHookPlayerMoving(*this);
|
cRoot::Get()->GetPluginManager()->CallHookPlayerMoving(*this);
|
||||||
BroadcastMovementUpdate(m_ClientHandle);
|
|
||||||
m_ClientHandle->StreamChunks();
|
m_ClientHandle->StreamChunks();
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
BroadcastMovementUpdate(m_ClientHandle);
|
||||||
BroadcastMovementUpdate(m_ClientHandle);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_Health > 0) // make sure player is alive
|
if (m_Health > 0) // make sure player is alive
|
||||||
{
|
{
|
||||||
@ -1596,10 +1590,7 @@ bool cPlayer::LoadFromDisk()
|
|||||||
SetPosX(JSON_PlayerPosition[(unsigned int)0].asDouble());
|
SetPosX(JSON_PlayerPosition[(unsigned int)0].asDouble());
|
||||||
SetPosY(JSON_PlayerPosition[(unsigned int)1].asDouble());
|
SetPosY(JSON_PlayerPosition[(unsigned int)1].asDouble());
|
||||||
SetPosZ(JSON_PlayerPosition[(unsigned int)2].asDouble());
|
SetPosZ(JSON_PlayerPosition[(unsigned int)2].asDouble());
|
||||||
m_LastPosX = GetPosX();
|
m_LastPos = GetPosition();
|
||||||
m_LastPosY = GetPosY();
|
|
||||||
m_LastPosZ = GetPosZ();
|
|
||||||
m_LastFoodPos = GetPosition();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Json::Value & JSON_PlayerRotation = root["rotation"];
|
Json::Value & JSON_PlayerRotation = root["rotation"];
|
||||||
@ -1860,17 +1851,16 @@ void cPlayer::ApplyFoodExhaustionFromMovement()
|
|||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate the distance travelled, update the last pos:
|
|
||||||
Vector3d Movement(GetPosition() - m_LastFoodPos);
|
|
||||||
Movement.y = 0; // Only take XZ movement into account
|
|
||||||
m_LastFoodPos = GetPosition();
|
|
||||||
|
|
||||||
// If riding anything, apply no food exhaustion
|
// If riding anything, apply no food exhaustion
|
||||||
if (m_AttachedTo != NULL)
|
if (m_AttachedTo != NULL)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Calculate the distance travelled, update the last pos:
|
||||||
|
Vector3d Movement(GetPosition() - m_LastPos);
|
||||||
|
Movement.y = 0; // Only take XZ movement into account
|
||||||
|
|
||||||
// Apply the exhaustion based on distance travelled:
|
// Apply the exhaustion based on distance travelled:
|
||||||
double BaseExhaustion = Movement.Length();
|
double BaseExhaustion = Movement.Length();
|
||||||
|
@ -423,9 +423,6 @@ protected:
|
|||||||
/** Number of ticks remaining for the foodpoisoning effect; zero if not foodpoisoned */
|
/** Number of ticks remaining for the foodpoisoning effect; zero if not foodpoisoned */
|
||||||
int m_FoodPoisonedTicksRemaining;
|
int m_FoodPoisonedTicksRemaining;
|
||||||
|
|
||||||
/** Last position that has been recorded for food-related processing: */
|
|
||||||
Vector3d m_LastFoodPos;
|
|
||||||
|
|
||||||
float m_LastJumpHeight;
|
float m_LastJumpHeight;
|
||||||
float m_LastGroundHeight;
|
float m_LastGroundHeight;
|
||||||
bool m_bTouchGround;
|
bool m_bTouchGround;
|
||||||
|
@ -30,8 +30,6 @@ cTNTEntity::cTNTEntity(const Vector3d & a_Pos, int a_FuseTicks) :
|
|||||||
void cTNTEntity::SpawnOn(cClientHandle & a_ClientHandle)
|
void cTNTEntity::SpawnOn(cClientHandle & a_ClientHandle)
|
||||||
{
|
{
|
||||||
a_ClientHandle.SendSpawnObject(*this, 50, 1, 0, 0); // 50 means TNT
|
a_ClientHandle.SendSpawnObject(*this, 50, 1, 0, 0); // 50 means TNT
|
||||||
m_bDirtyPosition = false;
|
|
||||||
m_bDirtySpeed = false;
|
|
||||||
m_bDirtyOrientation = false;
|
m_bDirtyOrientation = false;
|
||||||
m_bDirtyHead = false;
|
m_bDirtyHead = false;
|
||||||
}
|
}
|
||||||
|
@ -47,9 +47,9 @@ public:
|
|||||||
public cBlockTracer::cCallbacks
|
public cBlockTracer::cCallbacks
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
cCallbacks(cWorld * a_CBWorld) :
|
|
||||||
m_HasHitFluid(false),
|
cCallbacks(void) :
|
||||||
m_World(a_CBWorld)
|
m_HasHitFluid(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,10 +62,9 @@ public:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
AddFaceDirection(a_CBBlockX, a_CBBlockY, a_CBBlockZ, BLOCK_FACE_YP); // Always place pad at top of water block
|
AddFaceDirection(a_CBBlockX, a_CBBlockY, a_CBBlockZ, BLOCK_FACE_YP); // Always place pad at top of water block
|
||||||
BLOCKTYPE Block = m_World->GetBlock(a_CBBlockX, a_CBBlockY, a_CBBlockZ);
|
|
||||||
if (
|
if (
|
||||||
!IsBlockWater(Block) &&
|
!IsBlockWater(a_CBBlockType) &&
|
||||||
cBlockInfo::FullyOccupiesVoxel(Block)
|
cBlockInfo::FullyOccupiesVoxel(a_CBBlockType)
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
// Can't place lilypad on air/in another block!
|
// Can't place lilypad on air/in another block!
|
||||||
@ -80,11 +79,10 @@ public:
|
|||||||
|
|
||||||
Vector3i m_Pos;
|
Vector3i m_Pos;
|
||||||
bool m_HasHitFluid;
|
bool m_HasHitFluid;
|
||||||
cWorld * m_World;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
cCallbacks Callbacks(a_World);
|
cCallbacks Callbacks;
|
||||||
cLineBlockTracer Tracer(*a_Player->GetWorld(), Callbacks);
|
cLineBlockTracer Tracer(*a_Player->GetWorld(), Callbacks);
|
||||||
Vector3d Start(a_Player->GetEyePosition() + a_Player->GetLookVector());
|
Vector3d Start(a_Player->GetEyePosition() + a_Player->GetLookVector());
|
||||||
Vector3d End(a_Player->GetEyePosition() + a_Player->GetLookVector() * 5);
|
Vector3d End(a_Player->GetEyePosition() + a_Player->GetLookVector() * 5);
|
||||||
|
@ -28,15 +28,19 @@ public:
|
|||||||
|
|
||||||
virtual bool OnItemUse(cWorld * a_World, cPlayer * a_Player, const cItem & a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_Dir) override
|
virtual bool OnItemUse(cWorld * a_World, cPlayer * a_Player, const cItem & a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_Dir) override
|
||||||
{
|
{
|
||||||
|
Vector3d Pos = a_Player->GetThrowStartPos();
|
||||||
|
Vector3d Speed = a_Player->GetLookVector() * m_SpeedCoeff;
|
||||||
|
|
||||||
|
if (a_World->CreateProjectile(Pos.x, Pos.y, Pos.z, m_ProjectileKind, a_Player, a_Player->GetEquippedItem(), &Speed) < 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (!a_Player->IsGameModeCreative())
|
if (!a_Player->IsGameModeCreative())
|
||||||
{
|
{
|
||||||
a_Player->GetInventory().RemoveOneEquippedItem();
|
a_Player->GetInventory().RemoveOneEquippedItem();
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector3d Pos = a_Player->GetThrowStartPos();
|
|
||||||
Vector3d Speed = a_Player->GetLookVector() * m_SpeedCoeff;
|
|
||||||
a_World->CreateProjectile(Pos.x, Pos.y, Pos.z, m_ProjectileKind, a_Player, a_Player->GetEquippedItem(), &Speed);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,7 +131,10 @@ public:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
a_World->CreateProjectile(a_BlockX + 0.5, a_BlockY + 1, a_BlockZ + 0.5, m_ProjectileKind, a_Player, a_Player->GetEquippedItem());
|
if (a_World->CreateProjectile(a_BlockX + 0.5, a_BlockY + 1, a_BlockZ + 0.5, m_ProjectileKind, a_Player, a_Player->GetEquippedItem()) < 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (!a_Player->IsGameModeCreative())
|
if (!a_Player->IsGameModeCreative())
|
||||||
{
|
{
|
||||||
|
@ -219,6 +219,10 @@ bool cTracer::Trace( const Vector3f & a_Start, const Vector3f & a_Direction, int
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((pos.y < 0) || (pos.y >= cChunkDef::Height))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
BLOCKTYPE BlockID = m_World->GetBlock(pos.x, pos.y, pos.z);
|
BLOCKTYPE BlockID = m_World->GetBlock(pos.x, pos.y, pos.z);
|
||||||
// Block is counted as a collision if we are not doing a line of sight and it is solid,
|
// Block is counted as a collision if we are not doing a line of sight and it is solid,
|
||||||
// or if the block is not air and not water. That way mobs can still see underwater.
|
// or if the block is not air and not water. That way mobs can still see underwater.
|
||||||
@ -226,7 +230,7 @@ bool cTracer::Trace( const Vector3f & a_Start, const Vector3f & a_Direction, int
|
|||||||
{
|
{
|
||||||
BlockHitPosition = pos;
|
BlockHitPosition = pos;
|
||||||
int Normal = GetHitNormal(a_Start, End, pos );
|
int Normal = GetHitNormal(a_Start, End, pos );
|
||||||
if(Normal > 0)
|
if (Normal > 0)
|
||||||
{
|
{
|
||||||
HitNormal = m_NormalTable[Normal-1];
|
HitNormal = m_NormalTable[Normal-1];
|
||||||
}
|
}
|
||||||
|
@ -118,11 +118,6 @@ public:
|
|||||||
return (Abs(x - a_Rhs.x) < a_Eps) && (Abs(y - a_Rhs.y) < a_Eps) && (Abs(z - a_Rhs.z) < a_Eps);
|
return (Abs(x - a_Rhs.x) < a_Eps) && (Abs(y - a_Rhs.y) < a_Eps) && (Abs(z - a_Rhs.z) < a_Eps);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool operator == (const Vector3<T> & a_Rhs) const
|
|
||||||
{
|
|
||||||
return Equals(a_Rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void Move(T a_X, T a_Y, T a_Z)
|
inline void Move(T a_X, T a_Y, T a_Z)
|
||||||
{
|
{
|
||||||
x += a_X;
|
x += a_X;
|
||||||
@ -139,6 +134,16 @@ public:
|
|||||||
|
|
||||||
// tolua_end
|
// tolua_end
|
||||||
|
|
||||||
|
inline bool operator != (const Vector3<T> & a_Rhs) const
|
||||||
|
{
|
||||||
|
return !Equals(a_Rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool operator == (const Vector3<T> & a_Rhs) const
|
||||||
|
{
|
||||||
|
return Equals(a_Rhs);
|
||||||
|
}
|
||||||
|
|
||||||
inline void operator += (const Vector3<T> & a_Rhs)
|
inline void operator += (const Vector3<T> & a_Rhs)
|
||||||
{
|
{
|
||||||
x += a_Rhs.x;
|
x += a_Rhs.x;
|
||||||
|
@ -710,7 +710,9 @@ public:
|
|||||||
virtual int SpawnMob(double a_PosX, double a_PosY, double a_PosZ, cMonster::eType a_MonsterType) override; // tolua_export
|
virtual int SpawnMob(double a_PosX, double a_PosY, double a_PosZ, cMonster::eType a_MonsterType) override; // tolua_export
|
||||||
int SpawnMobFinalize(cMonster* a_Monster);
|
int SpawnMobFinalize(cMonster* a_Monster);
|
||||||
|
|
||||||
/** Creates a projectile of the specified type. Returns the projectile's EntityID if successful, <0 otherwise */
|
/** Creates a projectile of the specified type. Returns the projectile's EntityID if successful, <0 otherwise
|
||||||
|
Item parameter used currently for Fireworks to correctly set entity metadata based on item metadata
|
||||||
|
*/
|
||||||
int CreateProjectile(double a_PosX, double a_PosY, double a_PosZ, cProjectileEntity::eKind a_Kind, cEntity * a_Creator, const cItem & a_Item, const Vector3d * a_Speed = NULL); // tolua_export
|
int CreateProjectile(double a_PosX, double a_PosY, double a_PosZ, cProjectileEntity::eKind a_Kind, cEntity * a_Creator, const cItem & a_Item, const Vector3d * a_Speed = NULL); // tolua_export
|
||||||
|
|
||||||
/** Returns a random number from the m_TickRand in range [0 .. a_Range]. To be used only in the tick thread! */
|
/** Returns a random number from the m_TickRand in range [0 .. a_Range]. To be used only in the tick thread! */
|
||||||
|
Loading…
Reference in New Issue
Block a user