From 4f17362aeb80e5339c58a5d3b0fbaeb88d9e701c Mon Sep 17 00:00:00 2001 From: "madmaxoft@gmail.com" Date: Mon, 13 Feb 2012 21:47:03 +0000 Subject: Rewritten most of the code for multithreading; still not 100%, but getting there. If this commit proves to be too problematic, we can always undo it. git-svn-id: http://mc-server.googlecode.com/svn/trunk@251 0a769ca7-a7f5-676a-18bf-c427514a06d6 --- source/cClientHandle.h | 76 ++++++++++++++++++++++++++++++++------------------ 1 file changed, 49 insertions(+), 27 deletions(-) (limited to 'source/cClientHandle.h') diff --git a/source/cClientHandle.h b/source/cClientHandle.h index 48a51c2df..f45cf5b7d 100644 --- a/source/cClientHandle.h +++ b/source/cClientHandle.h @@ -14,6 +14,7 @@ #include "packets/cPacket.h" #include "Vector3d.h" #include "cSocketThreads.h" +#include "cChunk.h" #include "packets/cPacket_KeepAlive.h" #include "packets/cPacket_PlayerPosition.h" @@ -46,8 +47,6 @@ -// class Game; -class cChunk; class cPlayer; class cRedstone; @@ -70,9 +69,6 @@ public: cClientHandle(const cSocket & a_Socket); ~cClientHandle(); - static const int VIEWDISTANCE = 17; // MUST be odd number or CRASH! - static const int GENERATEDISTANCE = 2; // Server generates this many chunks AHEAD of player sight. - const cSocket & GetSocket(void) const {return m_Socket; } cSocket & GetSocket(void) {return m_Socket; } @@ -81,21 +77,22 @@ public: void Kick(const AString & a_Reason); //tolua_export void Authenticate(void); // Called by cAuthenticator when the user passes authentication - void StreamChunks(); - void StreamChunksSmart( cChunk** a_Chunks, unsigned int a_NumChunks ); - void RemoveFromAllChunks(); + void StreamChunks(void); + + // Removes the client from all chunks. Used when switching worlds or destroying the player + void RemoveFromAllChunks(void); + + void ChunkJustSent(cChunk * a_ChunkSent); // Called by cChunk when it is loaded / generated and sent to all clients registered in it - inline void SetLoggedIn( bool a_bLoggedIn ) { m_bLoggedIn = a_bLoggedIn; } - inline bool IsLoggedIn() { return m_bLoggedIn; } + inline bool IsLoggedIn(void) const { return m_State >= csAuthenticating; } void Tick(float a_Dt); bool IsDestroyed() { return m_bDestroyed; } void Destroy(); - cChunk* m_LoadedChunks[VIEWDISTANCE*VIEWDISTANCE]; - - void Send( const cPacket & a_Packet, ENUM_PRIORITY a_Priority = E_PRIORITY_NORMAL ); + void Send(const cPacket & a_Packet, ENUM_PRIORITY a_Priority = E_PRIORITY_NORMAL) { Send(&a_Packet, a_Priority); } + void Send(const cPacket * a_Packet, ENUM_PRIORITY a_Priority = E_PRIORITY_NORMAL); static void SendThread( void *lpParam ); @@ -105,6 +102,9 @@ public: private: + static const int VIEWDISTANCE = 4; // 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 = 1; // Server generates this many chunks AHEAD of player sight. + int m_ProtocolVersion; AString m_Username; AString m_Password; @@ -114,13 +114,16 @@ private: PacketList m_PendingNrmSendPackets; PacketList m_PendingLowSendPackets; + 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) + cThread * m_pSendThread; cSocket m_Socket; cCriticalSection m_CriticalSection; cCriticalSection m_SendCriticalSection; - // cCriticalSection m_SocketCriticalSection; cSemaphore m_Semaphore; Vector3d m_ConfirmPosition; @@ -130,34 +133,46 @@ private: bool m_bDestroyed; cPlayer * m_Player; bool m_bKicking; + + // Chunk position when the last StreamChunks() was called; used to avoid re-streaming while in the same chunk + int m_LastStreamedChunkX; + int m_LastStreamedChunkZ; float m_TimeLastPacket; - + short m_Ping; int m_PingID; 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) - bool m_bLoggedIn; - bool m_bPositionConfirmed; - bool m_bSendLoginResponse; + 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; bool m_bKeepThreadGoing; void HandlePacket(cPacket * a_Packet); - // Packets handled while !m_bLoggedIn: - void HandlePing (void); - void HandleHandshake (cPacket_Handshake * a_Packet); - void HandleLogin (cPacket_Login * a_Packet); - void HandleMoveLookLogin(cPacket_PlayerMoveLook * a_Packet); // While !m_bLoggedIn - void HandleDefaultLogin (cPacket * a_Packet); // the default case + // 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 - // Packets handled while !m_bPositionConfirmed: + // Packets handled while in csConfirmingPos: void HandleMoveLookConfirm(cPacket_PlayerMoveLook * a_Packet); // While !m_bPositionConfirmed - // Packets handled while m_bPositionConfirmed (normal gameplay): + // Packets handled while in csPlaying: void HandleCreativeInventory(cPacket_CreativeInventoryAction * a_Packet); void HandlePlayerPos (cPacket_PlayerPosition * a_Packet); void HandleBlockDig (cPacket_BlockDig * a_Packet); @@ -179,7 +194,14 @@ private: /// Returns true if the rate block interactions is within a reasonable limit (bot protection) bool CheckBlockInteractionsRate(void); - void SendLoginResponse(); + /// 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() + void StreamChunk(int a_ChunkX, int a_ChunkZ); // cSocketThreads::cCallback overrides: virtual void DataReceived (const char * a_Data, int a_Size) override; // Data is received from the client -- cgit v1.2.3