1
0

Player can sit in minecarts (but not move them yet)

git-svn-id: http://mc-server.googlecode.com/svn/trunk@1249 0a769ca7-a7f5-676a-18bf-c427514a06d6
This commit is contained in:
madmaxoft@gmail.com 2013-03-03 19:05:11 +00:00
parent 55326ee2a7
commit 01b24d73ea
21 changed files with 448 additions and 84 deletions

View File

@ -1,6 +1,6 @@
/*
** Lua binding: AllToLua
** Generated automatically by tolua++-1.0.92 on 03/03/13 14:57:13.
** Generated automatically by tolua++-1.0.92 on 03/03/13 20:02:17.
*/
#ifndef __cplusplus
@ -5046,6 +5046,39 @@ static int tolua_AllToLua_cEntity_SetRoll00(lua_State* tolua_S)
}
#endif //#ifndef TOLUA_DISABLE
/* method: AddSpeed of class cEntity */
#ifndef TOLUA_DISABLE_tolua_AllToLua_cEntity_AddSpeed00
static int tolua_AllToLua_cEntity_AddSpeed00(lua_State* tolua_S)
{
#ifndef TOLUA_RELEASE
tolua_Error tolua_err;
if (
!tolua_isusertype(tolua_S,1,"cEntity",0,&tolua_err) ||
(tolua_isvaluenil(tolua_S,2,&tolua_err) || !tolua_isusertype(tolua_S,2,"const Vector3d",0,&tolua_err)) ||
!tolua_isnoobj(tolua_S,3,&tolua_err)
)
goto tolua_lerror;
else
#endif
{
cEntity* self = (cEntity*) tolua_tousertype(tolua_S,1,0);
const Vector3d* a_AddSpeed = ((const Vector3d*) tolua_tousertype(tolua_S,2,0));
#ifndef TOLUA_RELEASE
if (!self) tolua_error(tolua_S,"invalid 'self' in function 'AddSpeed'", NULL);
#endif
{
self->AddSpeed(*a_AddSpeed);
}
}
return 0;
#ifndef TOLUA_RELEASE
tolua_lerror:
tolua_error(tolua_S,"#ferror in function 'AddSpeed'.",&tolua_err);
return 0;
#endif
}
#endif //#ifndef TOLUA_DISABLE
/* method: GetUniqueID of class cEntity */
#ifndef TOLUA_DISABLE_tolua_AllToLua_cEntity_GetUniqueID00
static int tolua_AllToLua_cEntity_GetUniqueID00(lua_State* tolua_S)
@ -22073,6 +22106,7 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S)
tolua_function(tolua_S,"SetRotation",tolua_AllToLua_cEntity_SetRotation00);
tolua_function(tolua_S,"SetPitch",tolua_AllToLua_cEntity_SetPitch00);
tolua_function(tolua_S,"SetRoll",tolua_AllToLua_cEntity_SetRoll00);
tolua_function(tolua_S,"AddSpeed",tolua_AllToLua_cEntity_AddSpeed00);
tolua_function(tolua_S,"GetUniqueID",tolua_AllToLua_cEntity_GetUniqueID00);
tolua_function(tolua_S,"IsDestroyed",tolua_AllToLua_cEntity_IsDestroyed00);
tolua_function(tolua_S,"Destroy",tolua_AllToLua_cEntity_Destroy00);

View File

@ -1,6 +1,6 @@
/*
** Lua binding: AllToLua
** Generated automatically by tolua++-1.0.92 on 03/03/13 14:57:13.
** Generated automatically by tolua++-1.0.92 on 03/03/13 20:02:18.
*/
/* Exported function */

View File

@ -1918,6 +1918,18 @@ cChunk * cChunk::GetRelNeighborChunk(int a_RelX, int a_RelZ)
void cChunk::BroadcastAttachEntity(const cEntity & a_Entity, const cEntity * a_Vehicle)
{
for (cClientHandleList::const_iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr )
{
(*itr)->SendAttachEntity(a_Entity, a_Vehicle);
} // for itr - LoadedByClient[]
}
void cChunk::BroadcastPlayerAnimation(const cPlayer & a_Player, char a_Animation, const cClientHandle * a_Exclude)
{
for (cClientHandleList::const_iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr )

View File

@ -207,6 +207,7 @@ public:
void CalculateLighting(); // Recalculate right now
void CalculateHeightmap();
void BroadcastAttachEntity (const cEntity & a_Entity, const cEntity * a_Vehicle);
void BroadcastPlayerAnimation (const cPlayer & a_Player, char a_Animation, const cClientHandle * a_Exclude = NULL);
void BroadcastEntityEquipment (const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item, const cClientHandle * a_Exclude = NULL);
void BroadcastEntRelMoveLook (const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ, const cClientHandle * a_Exclude = NULL);

View File

@ -274,6 +274,21 @@ cChunk * cChunkMap::FindChunk(int a_ChunkX, int a_ChunkZ)
void cChunkMap::BroadcastAttachEntity(const cEntity & a_Entity, const cEntity * a_Vehicle)
{
cCSLock Lock(m_CSLayers);
cChunkPtr Chunk = GetChunkNoGen(a_Entity.GetChunkX(), a_Entity.GetChunkY(), a_Entity.GetChunkZ());
if (Chunk == NULL)
{
return;
}
// It's perfectly legal to broadcast packets even to invalid chunks!
Chunk->BroadcastAttachEntity(a_Entity, a_Vehicle);
}
void cChunkMap::BroadcastPlayerAnimation(const cPlayer & a_Player, char a_Animation, const cClientHandle * a_Exclude)
{
cCSLock Lock(m_CSLayers);

View File

@ -45,6 +45,8 @@ public:
cChunkMap(cWorld* a_World );
~cChunkMap();
void BroadcastAttachEntity(const cEntity & a_Entity, const cEntity * a_Vehicle);
/// Broadcasts an a_Player's animation to all clients in the chunk where a_Player is
void BroadcastPlayerAnimation(const cPlayer & a_Player, char a_Animation, const cClientHandle * a_Exclude = NULL);

View File

@ -1048,9 +1048,24 @@ void cClientHandle::HandleUpdateSign(
void cClientHandle::HandleUseEntity(int a_TargetEntityID, bool a_IsLeftClick)
{
// TODO: Let plugins interfere via a hook
if (!a_IsLeftClick)
{
// TODO: we don't handle right-clicking yet
class cRclkEntity : public cEntityCallback
{
cPlayer & m_Player;
virtual bool Item(cEntity * a_Entity) override
{
a_Entity->OnRightClicked(m_Player);
return true;
}
public:
cRclkEntity(cPlayer & a_Player) : m_Player(a_Player) {}
} Callback (*m_Player);
cWorld * World = m_Player->GetWorld();
World->DoWithEntityByID(a_TargetEntityID, Callback);
return;
}
@ -1449,6 +1464,15 @@ void cClientHandle::SendEntHeadLook(const cEntity & a_Entity)
void cClientHandle::SendAttachEntity(const cEntity & a_Entity, const cEntity * a_Vehicle)
{
m_Protocol->SendAttachEntity(a_Entity, a_Vehicle);
}
void cClientHandle::SendBlockAction(int a_BlockX, int a_BlockY, int a_BlockZ, char a_Byte1, char a_Byte2, BLOCKTYPE a_BlockType)
{
m_Protocol->SendBlockAction(a_BlockX, a_BlockY, a_BlockZ, a_Byte1, a_Byte2, a_BlockType);

View File

@ -82,6 +82,7 @@ public:
bool IsDestroyed (void) const { return (m_State == csDestroyed); }
bool IsDestroying(void) const { return (m_State == csDestroying); }
void SendAttachEntity (const cEntity & a_Entity, const cEntity * a_Vehicle);
void SendBlockAction (int a_BlockX, int a_BlockY, int a_BlockZ, char a_Byte1, char a_Byte2, BLOCKTYPE a_BlockType);
void SendBlockChange (int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta);
void SendBlockChanges (int a_ChunkX, int a_ChunkZ, const sSetBlockVector & a_Changes);

View File

@ -24,6 +24,8 @@ cCriticalSection cEntity::m_CSCount;
cEntity::cEntity(eEntityType a_EntityType, double a_X, double a_Y, double a_Z)
: m_UniqueID(0)
, m_AttachedTo(NULL)
, m_Attachee(NULL)
, m_Referencers(new cReferenceManager(cReferenceManager::RFMNGR_REFERENCERS))
, m_References(new cReferenceManager(cReferenceManager::RFMNGR_REFERENCES))
, m_ChunkX(0)
@ -57,6 +59,15 @@ cEntity::~cEntity()
this
);
if (m_AttachedTo != NULL)
{
Detach();
}
if (m_Attachee != NULL)
{
m_Attachee->Detach();
}
if (!m_bDestroyed || !m_bRemovedFromChunk)
{
LOGERROR("ERROR: Entity deallocated without being destroyed %i or unlinked %i", m_bDestroyed, m_bRemovedFromChunk);
@ -213,8 +224,55 @@ void cEntity::Tick(float a_Dt, MTRand & a_TickRandom)
{
UNUSED(a_TickRandom);
if (m_AttachedTo != NULL)
{
if ((m_Pos - m_AttachedTo->GetPosition()).Length() > 0.5)
{
SetPosition(m_AttachedTo->GetPosition());
}
}
else
{
HandlePhysics(a_Dt);
}
}
void cEntity::AttachTo(cEntity * a_AttachTo)
{
if (m_AttachedTo == a_AttachTo)
{
// Already attached to that entity, nothing to do here
return;
}
// Detach from any previous entity:
Detach();
// Attach to the new entity:
m_AttachedTo = a_AttachTo;
a_AttachTo->m_Attachee = this;
m_World->BroadcastAttachEntity(*this, a_AttachTo);
}
void cEntity::Detach(void)
{
if (m_AttachedTo == NULL)
{
// Attached to no entity, our work is done
return;
}
m_AttachedTo->m_Attachee = NULL;
m_AttachedTo = NULL;
m_World->BroadcastAttachEntity(*this, NULL);
}
@ -271,6 +329,15 @@ void cEntity::SetRoll( float a_Roll )
void cEntity::AddSpeed(const Vector3d & a_AddSpeed)
{
m_Speed += a_AddSpeed;
}
//////////////////////////////////////////////////////////////////////////
// Get look vector (this is NOT a rotation!)
Vector3f cEntity::GetLookVector(void) const

View File

@ -37,6 +37,7 @@
class cWorld;
class cReferenceManager;
class cClientHandle;
class cPlayer;
class MTRand;
@ -130,6 +131,8 @@ public:
void SetRotation(float a_Rotation);
void SetPitch (float a_Pitch);
void SetRoll (float a_Roll);
void AddSpeed(const Vector3d & a_AddSpeed);
// tolua_end
inline int GetUniqueID(void) const { return m_UniqueID; } // tolua_export
@ -147,6 +150,12 @@ public:
*/
virtual void SpawnOn(cClientHandle & a_Client) {ASSERT(!"SpawnOn() unimplemented!"); }
/// Attaches to the specified entity; detaches from any previous one first
void AttachTo(cEntity * a_AttachTo);
/// Detaches from the currently attached entity, if any
void Detach(void);
void WrapRotation();
// tolua_begin
@ -160,8 +169,11 @@ public:
// tolua_end
/// Called when the specified player right-clicks this entity
virtual void OnRightClicked(cPlayer & a_Player) {};
protected:
virtual void Destroyed() {} // 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 MoveToCorrectChunk(bool a_bIgnoreOldChunk = false);
@ -176,6 +188,12 @@ protected:
int m_UniqueID;
/// The entity to which this entity is attached (vehicle), NULL if none
cEntity * m_AttachedTo;
/// The entity which is attached to this entity (rider), NULL if none
cEntity * m_Attachee;
cReferenceManager* m_Referencers;
cReferenceManager* m_References;

View File

@ -54,19 +54,21 @@ public:
}
}
cMinecart::ePayload Payload = cMinecart::mpNone;
double x = (double)a_BlockX + 0.5;
double y = (double)a_BlockY + 0.5;
double z = (double)a_BlockZ + 0.5;
cMinecart * Minecart = NULL;
switch (m_ItemType)
{
case E_ITEM_MINECART: Payload = cMinecart::mpNone; break;
case E_ITEM_CHEST_MINECART: Payload = cMinecart::mpChest; break;
case E_ITEM_FURNACE_MINECART: Payload = cMinecart::mpFurnace; break;
case E_ITEM_MINECART: Minecart = new cEmptyMinecart (x, y, z); break;
case E_ITEM_CHEST_MINECART: Minecart = new cMinecartWithChest (x, y, z); break;
case E_ITEM_FURNACE_MINECART: Minecart = new cMinecartWithFurnace(x, y, z); break;
default:
{
ASSERT(!"Unhandled minecart item");
return false;
}
} // switch (m_ItemType)
cMinecart * Minecart = new cMinecart(Payload, (double)a_BlockX + 0.5, a_BlockY, (double)a_BlockZ + 0.5);
a_World->AddEntity(Minecart);
Minecart->Initialize(a_World);
return true;

View File

@ -7,6 +7,7 @@
#include "Minecart.h"
#include "World.h"
#include "ClientHandle.h"
#include "Player.h"
@ -60,3 +61,89 @@ void cMinecart::Tick(float a_Dt, MTRand & a_TickRandom)
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// cEmptyMinecart:
cEmptyMinecart::cEmptyMinecart(double a_X, double a_Y, double a_Z) :
super(mpNone, a_X, a_Y, a_Z)
{
}
void cEmptyMinecart::OnRightClicked(cPlayer & a_Player)
{
if (m_Attachee != NULL)
{
if (m_Attachee->GetUniqueID() == a_Player.GetUniqueID())
{
// This player is already sitting in, they want out.
a_Player.Detach();
return;
}
if (m_Attachee->IsPlayer())
{
// Another player is already sitting in here, cannot attach
return;
}
// Detach whatever is sitting in this minecart now:
m_Attachee->Detach();
}
// Attach the player to this minecart
a_Player.AttachTo(this);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// cMinecartWithChest:
cMinecartWithChest::cMinecartWithChest(double a_X, double a_Y, double a_Z) :
super(mpChest, a_X, a_Y, a_Z)
{
}
void cMinecartWithChest::OnRightClicked(cPlayer & a_Player)
{
// Show the chest UI window to the player
// TODO
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// cMinecartWithFurnace:
cMinecartWithFurnace::cMinecartWithFurnace(double a_X, double a_Y, double a_Z) :
super(mpFurnace, a_X, a_Y, a_Z)
{
}
void cMinecartWithFurnace::OnRightClicked(cPlayer & a_Player)
{
// Try to power the furnace with whatever the player is holding
// TODO
}

View File

@ -31,8 +31,6 @@ public:
// TODO: Other 1.5 features: hopper, tnt, dispenser, spawner
} ;
cMinecart(ePayload a_Payload, double a_X, double a_Y, double a_Z);
// cEntity overrides:
virtual void Initialize(cWorld * a_World) override;
virtual void SpawnOn(cClientHandle & a_ClientHandle) override;
@ -42,6 +40,62 @@ public:
protected:
ePayload m_Payload;
cMinecart(ePayload a_Payload, double a_X, double a_Y, double a_Z);
} ;
class cEmptyMinecart :
public cMinecart
{
typedef cMinecart super;
public:
CLASS_PROTODEF(cEmptyMinecart);
cEmptyMinecart(double a_X, double a_Y, double a_Z);
// cEntity overrides:
virtual void OnRightClicked(cPlayer & a_Player) override;
} ;
class cMinecartWithChest :
public cMinecart
{
typedef cMinecart super;
public:
CLASS_PROTODEF(cMinecartWithChest);
cMinecartWithChest(double a_X, double a_Y, double a_Z);
// cEntity overrides:
virtual void OnRightClicked(cPlayer & a_Player) override;
} ;
class cMinecartWithFurnace :
public cMinecart
{
typedef cMinecart super;
public:
CLASS_PROTODEF(cMinecartWithFurnace);
cMinecartWithFurnace(double a_X, double a_Y, double a_Z);
// cEntity overrides:
virtual void OnRightClicked(cPlayer & a_Player) override;
} ;

View File

@ -558,6 +558,16 @@ void cPlayer::TeleportTo(double a_PosX, double a_PosY, double a_PosZ)
void cPlayer::MoveTo( const Vector3d & a_NewPos )
{
if (m_AttachedTo != NULL)
{
// When attached to an entity, the client sends position packets with weird coords:
// Y = -999 and X, Z = attempting to create speed, usually up to 0.03
Vector3d AddSpeed(a_NewPos);
AddSpeed.y = 0;
m_AttachedTo->AddSpeed(AddSpeed);
return;
}
// TODO: should do some checks to see if player is not moving through terrain
// TODO: Official server refuses position packets too far away from each other, kicking "hacked" clients; we should, too

View File

@ -50,6 +50,7 @@ public:
virtual void DataReceived(const char * a_Data, int a_Size) = 0;
// Sending stuff to clients (alphabetically sorted):
virtual void SendAttachEntity (const cEntity & a_Entity, const cEntity * a_Vehicle) = 0;
virtual void SendBlockAction (int a_BlockX, int a_BlockY, int a_BlockZ, char a_Byte1, char a_Byte2, BLOCKTYPE a_BlockType) = 0;
virtual void SendBlockBreakAnim (int a_EntityID, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Stage) = 0;
virtual void SendBlockChange (int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) = 0;

View File

@ -63,6 +63,7 @@ enum
PACKET_ENT_TELEPORT = 0x22,
PACKET_ENT_HEAD_LOOK = 0x23,
PACKET_ENT_STATUS = 0x26,
PACKET_ATTACH_ENTITY = 0x27,
PACKET_METADATA = 0x28,
PACKET_PRE_CHUNK = 0x32,
PACKET_MAP_CHUNK = 0x33,
@ -122,6 +123,19 @@ cProtocol125::cProtocol125(cClientHandle * a_Client) :
void cProtocol125::SendAttachEntity(const cEntity & a_Entity, const cEntity * a_Vehicle)
{
cCSLock Lock(m_CSPacket);
WriteByte(PACKET_ATTACH_ENTITY);
WriteInt(a_Entity.GetUniqueID());
WriteInt((a_Vehicle == NULL) ? -1 : a_Vehicle->GetUniqueID());
Flush();
}
void cProtocol125::SendBlockAction(int a_BlockX, int a_BlockY, int a_BlockZ, char a_Byte1, char a_Byte2, BLOCKTYPE a_BlockType)
{
UNUSED(a_BlockType);

View File

@ -27,6 +27,7 @@ public:
virtual void DataReceived(const char * a_Data, int a_Size) override;
/// Sending stuff to clients (alphabetically sorted):
virtual void SendAttachEntity (const cEntity & a_Entity, const cEntity * a_Vehicle) override;
virtual void SendBlockAction (int a_BlockX, int a_BlockY, int a_BlockZ, char a_Byte1, char a_Byte2, BLOCKTYPE a_BlockType) override;
virtual void SendBlockBreakAnim (int a_EntityID, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Stage) override;
virtual void SendBlockChange (int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) override;

View File

@ -88,6 +88,16 @@ void cProtocolRecognizer::DataReceived(const char * a_Data, int a_Size)
void cProtocolRecognizer::SendAttachEntity(const cEntity & a_Entity, const cEntity * a_Vehicle)
{
ASSERT(m_Protocol != NULL);
m_Protocol->SendAttachEntity(a_Entity, a_Vehicle);
}
void cProtocolRecognizer::SendBlockAction(int a_BlockX, int a_BlockY, int a_BlockZ, char a_Byte1, char a_Byte2, BLOCKTYPE a_BlockType)
{
ASSERT(m_Protocol != NULL);

View File

@ -52,6 +52,7 @@ public:
virtual void DataReceived(const char * a_Data, int a_Size) override;
/// Sending stuff to clients (alphabetically sorted):
virtual void SendAttachEntity (const cEntity & a_Entity, const cEntity * a_Vehicle) override;
virtual void SendBlockAction (int a_BlockX, int a_BlockY, int a_BlockZ, char a_Byte1, char a_Byte2, BLOCKTYPE a_BlockType) override;
virtual void SendBlockBreakAnim (int a_EntityID, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Stage) override;
virtual void SendBlockChange (int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) override;

View File

@ -1245,6 +1245,15 @@ int cWorld::GetHeight( int a_X, int a_Z )
void cWorld::BroadcastAttachEntity(const cEntity & a_Entity, const cEntity * a_Vehicle)
{
return m_ChunkMap->BroadcastAttachEntity(a_Entity, a_Vehicle);
}
void cWorld::BroadcastChat(const AString & a_Message, const cClientHandle * a_Exclude)
{
cCSLock Lock(m_CSPlayers);
@ -1862,7 +1871,7 @@ bool cWorld::ForEachEntityInChunk(int a_ChunkX, int a_ChunkZ, cEntityCallback &
bool cWorld::DoWithEntityByID(int a_UniqueID, cEntityCallback & a_Callback)
{
cCSLock Lock(m_CSEntities);
for (cEntityList::iterator itr = m_AllEntities.begin(); itr != m_AllEntities.end(); ++itr )
for (cEntityList::iterator itr = m_AllEntities.begin(), end = m_AllEntities.end(); itr != end; ++itr)
{
if ((*itr)->GetUniqueID() == a_UniqueID)
{

View File

@ -97,6 +97,7 @@ public:
// tolua_end
void BroadcastAttachEntity (const cEntity & a_Entity, const cEntity * a_Vehicle);
void BroadcastChat (const AString & a_Message, const cClientHandle * a_Exclude = NULL);
void BroadcastPlayerAnimation (const cPlayer & a_Player, char a_Animation, const cClientHandle * a_Exclude = NULL);
void BroadcastEntityEquipment (const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item, const cClientHandle * a_Exclude = NULL);