2012-02-02 16:13:24 -05:00
// cClientHandle.h
// Interfaces to the cClientHandle class representing a client connected to this server. The client need not be a player yet
2011-10-03 14:41:19 -04:00
# pragma once
2012-02-02 16:13:24 -05:00
# ifndef CCLIENTHANDLE_H_INCLUDED
# define CCLIENTHANDLE_H_INCLUDED
2012-02-04 14:40:48 -05:00
# include "packets/cPacket.h"
2012-02-02 16:13:24 -05:00
# include "Vector3d.h"
2012-02-08 05:02:46 -05:00
# include "cSocketThreads.h"
2012-02-13 16:47:03 -05:00
# include "cChunk.h"
2011-10-03 14:41:19 -04:00
2012-02-03 09:33:40 -05:00
# include "packets/cPacket_KeepAlive.h"
# include "packets/cPacket_PlayerPosition.h"
# include "packets/cPacket_Respawn.h"
# include "packets/cPacket_RelativeEntityMoveLook.h"
# include "packets/cPacket_Chat.h"
# include "packets/cPacket_Login.h"
# include "packets/cPacket_WindowClick.h"
# include "packets/cPacket_PlayerMoveLook.h"
# include "packets/cPacket_TimeUpdate.h"
# include "packets/cPacket_BlockDig.h"
# include "packets/cPacket_Handshake.h"
# include "packets/cPacket_PlayerLook.h"
# include "packets/cPacket_ArmAnim.h"
# include "packets/cPacket_BlockPlace.h"
# include "packets/cPacket_Flying.h"
# include "packets/cPacket_Disconnect.h"
# include "packets/cPacket_PickupSpawn.h"
# include "packets/cPacket_ItemSwitch.h"
# include "packets/cPacket_EntityEquipment.h"
# include "packets/cPacket_CreativeInventoryAction.h"
# include "packets/cPacket_NewInvalidState.h"
# include "packets/cPacket_UseEntity.h"
# include "packets/cPacket_WindowClose.h"
# include "packets/cPacket_UpdateSign.h"
# include "packets/cPacket_Ping.h"
# include "packets/cPacket_PlayerListItem.h"
2012-02-02 16:13:24 -05:00
2011-10-03 14:41:19 -04:00
class cPlayer ;
2011-11-04 01:01:55 -04:00
class cRedstone ;
2012-02-02 16:13:24 -05:00
2012-02-08 05:02:46 -05:00
class cClientHandle : // tolua_export
public cSocketThreads : : cCallback
2011-10-03 14:41:19 -04:00
{ // tolua_export
public :
enum ENUM_PRIORITY
{
E_PRIORITY_LOW ,
E_PRIORITY_NORMAL
} ;
2012-03-13 05:28:24 -04:00
static const int MAXBLOCKCHANGEINTERACTIONS = 20 ; // 5 didn't help, 10 still doesn't work in Creative, 20 seems to have done the trick
2012-02-23 17:51:03 -05:00
static const int DEFAULT_VIEW_DISTANCE = 9 ; // The default ViewDistance (used when no value is set in Settings.ini)
static const int MAX_VIEW_DISTANCE = 10 ;
static const int MIN_VIEW_DISTANCE = 4 ;
2011-12-27 11:27:22 -05:00
2012-02-23 17:51:03 -05:00
cClientHandle ( const cSocket & a_Socket , int a_ViewDistance ) ;
2011-10-03 14:41:19 -04:00
~ cClientHandle ( ) ;
2012-02-08 05:02:46 -05:00
const cSocket & GetSocket ( void ) const { return m_Socket ; }
cSocket & GetSocket ( void ) { return m_Socket ; }
2011-10-03 14:41:19 -04:00
cPlayer * GetPlayer ( ) { return m_Player ; } // tolua_export
2012-03-09 08:42:28 -05:00
void Kick ( const AString & a_Reason ) ; //tolua_export
2012-02-01 17:38:03 -05:00
void Authenticate ( void ) ; // Called by cAuthenticator when the user passes authentication
2011-10-03 14:41:19 -04:00
2012-02-13 16:47:03 -05:00
void StreamChunks ( void ) ;
// Removes the client from all chunks. Used when switching worlds or destroying the player
void RemoveFromAllChunks ( void ) ;
inline bool IsLoggedIn ( void ) const { return m_State > = csAuthenticating ; }
2011-10-03 14:41:19 -04:00
void Tick ( float a_Dt ) ;
bool IsDestroyed ( ) { return m_bDestroyed ; }
void Destroy ( ) ;
2012-03-05 11:41:57 -05:00
bool IsPlaying ( void ) const { return ( m_State = = csPlaying ) ; }
2011-10-03 14:41:19 -04:00
2012-03-10 16:34:47 -05:00
void Send ( const cPacket & a_Packet , ENUM_PRIORITY a_Priority = E_PRIORITY_NORMAL ) ;
2011-10-03 14:41:19 -04:00
2012-03-09 08:42:28 -05:00
const AString & GetUsername ( void ) const ; //tolua_export
2011-12-27 13:39:06 -05:00
2012-03-09 08:42:28 -05:00
inline short GetPing ( ) const { return m_Ping ; } //tolua_export
2012-02-23 17:51:03 -05:00
2012-03-09 08:42:28 -05:00
void SetViewDistance ( int a_ViewDistance ) ; //tolua_export
int GetUniqueID ( ) const { return m_UniqueID ; } //tolua_export
2012-03-11 06:48:20 -04:00
/// Returns true if the client wants the chunk specified to be sent (in m_ChunksToSend)
bool WantsSendChunk ( int a_ChunkX , int a_ChunkY , int a_ChunkZ ) ;
2011-10-03 14:41:19 -04:00
2012-02-03 09:33:40 -05:00
private :
2011-10-03 14:41:19 -04:00
2012-02-23 17:51:03 -05:00
int m_ViewDistance ; // Number of chunks the player can see in each direction; 4 is the minimum ( http://wiki.vg/Protocol_FAQ#.E2.80.A6all_connecting_clients_spasm_and_jerk_uncontrollably.21 )
static const int GENERATEDISTANCE = 2 ; // Server generates this many chunks AHEAD of player sight. 2 is the minimum, since foliage is generated 1 step behind chunk terrain generation
2012-02-13 16:47:03 -05:00
2012-02-03 09:33:40 -05:00
int m_ProtocolVersion ;
AString m_Username ;
AString m_Password ;
2012-02-08 05:02:46 -05:00
AString m_ReceivedData ; // Accumulator for the data received from the socket, waiting to be parsed; accessed from the cSocketThreads' thread only!
2012-02-02 16:13:24 -05:00
2012-02-25 19:36:51 -05:00
cCriticalSection m_CSPackets ;
PacketList m_PendingNrmSendPackets ;
PacketList m_PendingLowSendPackets ;
2012-02-02 16:13:24 -05:00
2012-02-13 16:47:03 -05:00
cCriticalSection m_CSChunkLists ;
cChunkCoordsList m_LoadedChunks ; // Chunks that the player belongs to
cChunkCoordsList m_ChunksToSend ; // Chunks that need to be sent to the player (queued because they weren't generated yet or there's not enough time to send them)
2012-02-03 09:33:40 -05:00
cSocket m_Socket ;
2011-10-03 14:41:19 -04:00
2012-02-03 09:33:40 -05:00
cCriticalSection m_CriticalSection ;
2012-02-02 16:13:24 -05:00
2012-02-03 09:33:40 -05:00
Vector3d m_ConfirmPosition ;
2012-02-02 16:13:24 -05:00
2012-02-03 09:33:40 -05:00
cPacket * m_PacketMap [ 256 ] ;
2012-02-02 16:13:24 -05:00
bool m_bDestroyed ;
cPlayer * m_Player ;
bool m_bKicking ;
2012-02-13 16:47:03 -05:00
// Chunk position when the last StreamChunks() was called; used to avoid re-streaming while in the same chunk
int m_LastStreamedChunkX ;
int m_LastStreamedChunkZ ;
2011-10-03 14:41:19 -04:00
float m_TimeLastPacket ;
2012-02-13 16:47:03 -05:00
2011-12-25 21:35:49 -05:00
short m_Ping ;
2012-02-03 09:33:40 -05:00
int m_PingID ;
2011-12-27 13:39:06 -05:00
long long m_PingStartTime ;
long long m_LastPingTime ;
static const unsigned short PING_TIME_MS = 1000 ; //minecraft sends 1 per 20 ticks (1 second or every 1000 ms)
2011-12-25 21:35:49 -05:00
2012-02-13 16:47:03 -05:00
enum eState
{
csConnected , // The client has just connected, waiting for their handshake / login
csAuthenticating , // The client has logged in, waiting for external authentication
csDownloadingWorld , // The client is waiting for chunks, we're waiting for the loader to provide and send them
csConfirmingPos , // The client has been sent the position packet, waiting for them to repeat the position back
csPlaying , // Normal gameplay
// TODO: Add Kicking and Destroyed here as well
} ;
eState m_State ;
2011-10-03 14:41:19 -04:00
bool m_bKeepThreadGoing ;
2012-02-03 09:33:40 -05:00
void HandlePacket ( cPacket * a_Packet ) ;
2012-02-13 16:47:03 -05:00
// Packets handled in csConnected:
void HandlePing ( void ) ;
void HandleHandshake ( cPacket_Handshake * a_Packet ) ;
void HandleLogin ( cPacket_Login * a_Packet ) ;
void HandleUnexpectedPacket ( cPacket * a_Packet ) ; // the default case -> kick
2012-02-03 09:33:40 -05:00
2012-02-13 16:47:03 -05:00
// Packets handled while in csConfirmingPos:
2012-02-03 09:33:40 -05:00
void HandleMoveLookConfirm ( cPacket_PlayerMoveLook * a_Packet ) ; // While !m_bPositionConfirmed
2012-02-13 16:47:03 -05:00
// Packets handled while in csPlaying:
2012-02-03 09:33:40 -05:00
void HandleCreativeInventory ( cPacket_CreativeInventoryAction * a_Packet ) ;
void HandlePlayerPos ( cPacket_PlayerPosition * a_Packet ) ;
void HandleBlockDig ( cPacket_BlockDig * a_Packet ) ;
void HandleBlockPlace ( cPacket_BlockPlace * a_Packet ) ;
void HandlePickupSpawn ( cPacket_PickupSpawn * a_Packet ) ;
void HandleChat ( cPacket_Chat * a_Packet ) ;
void HandlePlayerLook ( cPacket_PlayerLook * a_Packet ) ;
void HandlePlayerMoveLook ( cPacket_PlayerMoveLook * a_Packet ) ; // While m_bPositionConfirmed (normal gameplay)
void HandleAnimation ( cPacket_ArmAnim * a_Packet ) ;
void HandleItemSwitch ( cPacket_ItemSwitch * a_Packet ) ;
void HandleWindowClose ( cPacket_WindowClose * a_Packet ) ;
void HandleWindowClick ( cPacket_WindowClick * a_Packet ) ;
void HandleUpdateSign ( cPacket_UpdateSign * a_Packet ) ;
void HandleUseEntity ( cPacket_UseEntity * a_Packet ) ;
void HandleRespawn ( void ) ;
void HandleDisconnect ( cPacket_Disconnect * a_Packet ) ;
void HandleKeepAlive ( cPacket_KeepAlive * a_Packet ) ;
/// Returns true if the rate block interactions is within a reasonable limit (bot protection)
bool CheckBlockInteractionsRate ( void ) ;
2012-02-13 16:47:03 -05:00
/// Checks whether all loaded chunks have been sent to the client; if so, sends the position to confirm
void CheckIfWorldDownloaded ( void ) ;
/// Sends the PlayerMoveLook packet that the client needs to reply to for the game to start
void SendConfirmPosition ( void ) ;
/// Adds a single chunk to be streamed to the client; used by StreamChunks()
2012-02-17 12:56:25 -05:00
void StreamChunk ( int a_ChunkX , int a_ChunkY , int a_ChunkZ ) ;
2012-02-08 05:02:46 -05:00
// cSocketThreads::cCallback overrides:
virtual void DataReceived ( const char * a_Data , int a_Size ) override ; // Data is received from the client
virtual void GetOutgoingData ( AString & a_Data ) override ; // Data can be sent to client
virtual void SocketClosed ( void ) override ; // The socket has been closed for any reason
2012-03-09 08:42:28 -05:00
static int s_ClientCount ;
int m_UniqueID ;
2011-10-03 14:41:19 -04:00
} ; // tolua_export
2012-02-02 16:13:24 -05:00
# endif // CCLIENTHANDLE_H_INCLUDED