2017-09-19 04:34:08 -04:00
|
|
|
|
2012-06-14 09:06:06 -04:00
|
|
|
// ChunkSender.h
|
|
|
|
|
|
|
|
// Interfaces to the cChunkSender class representing the thread that waits for chunks becoming ready (loaded / generated) and sends them to clients
|
|
|
|
|
|
|
|
/*
|
|
|
|
The whole thing is a thread that runs in a loop, waiting for either:
|
|
|
|
"finished chunks" (ChunkReady()), or
|
2014-07-21 09:19:48 -04:00
|
|
|
"chunks to send" (QueueSendChunkTo())
|
2014-07-17 10:33:09 -04:00
|
|
|
to come to a queue.
|
2012-06-14 09:06:06 -04:00
|
|
|
And once they do, it requests the chunk data and sends it all away, either
|
|
|
|
broadcasting (ChunkReady), or
|
|
|
|
sends to a specific client (QueueSendChunkTo)
|
|
|
|
Chunk data is queried using the cChunkDataCallback interface.
|
|
|
|
It is cached inside the ChunkSender object during the query and then processed after the query ends.
|
2015-05-09 05:16:56 -04:00
|
|
|
Note that the data needs to be compressed only after the query finishes,
|
2012-06-14 09:06:06 -04:00
|
|
|
because the query callbacks run with ChunkMap's CS locked.
|
|
|
|
|
2014-07-17 10:33:09 -04:00
|
|
|
A client may remove itself from all direct requests(QueueSendChunkTo()) by calling RemoveClient();
|
2012-06-14 09:06:06 -04:00
|
|
|
this ensures that the client's Send() won't be called anymore by ChunkSender.
|
|
|
|
Note that it may be called by world's BroadcastToChunk() if the client is still in the chunk.
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
2012-09-23 17:23:33 -04:00
|
|
|
#include "OSSupport/IsThread.h"
|
2014-05-18 10:10:12 -04:00
|
|
|
#include "ChunkDataCallback.h"
|
2020-08-21 13:22:04 -04:00
|
|
|
#include "Protocol/ChunkDataSerializer.h"
|
2012-06-14 09:06:06 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class cWorld;
|
|
|
|
class cClientHandle;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// fwd:
|
|
|
|
class cChunkSender;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class cChunkSender:
|
|
|
|
public cIsThread,
|
2017-08-21 12:56:53 -04:00
|
|
|
public cChunkDataCopyCollector
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2020-04-13 12:38:06 -04:00
|
|
|
using Super = cIsThread;
|
|
|
|
|
2012-06-14 09:06:06 -04:00
|
|
|
public:
|
2020-04-13 12:38:06 -04:00
|
|
|
|
2015-06-10 10:16:05 -04:00
|
|
|
cChunkSender(cWorld & a_World);
|
2017-05-20 02:16:28 -04:00
|
|
|
virtual ~cChunkSender() override;
|
2014-10-06 15:27:53 -04:00
|
|
|
|
|
|
|
enum eChunkPriority
|
|
|
|
{
|
2015-06-22 16:27:13 -04:00
|
|
|
E_CHUNK_PRIORITY_HIGH = 0,
|
|
|
|
E_CHUNK_PRIORITY_MIDHIGH,
|
2015-06-10 10:16:05 -04:00
|
|
|
E_CHUNK_PRIORITY_MEDIUM,
|
|
|
|
E_CHUNK_PRIORITY_LOW,
|
2016-02-05 16:45:45 -05:00
|
|
|
|
2014-10-06 15:27:53 -04:00
|
|
|
};
|
2016-02-05 16:45:45 -05:00
|
|
|
|
2012-06-14 09:06:06 -04:00
|
|
|
void Stop(void);
|
2016-02-05 16:45:45 -05:00
|
|
|
|
2015-07-31 10:49:10 -04:00
|
|
|
/** Queues a chunk to be sent to a specific client */
|
2014-10-06 15:27:53 -04:00
|
|
|
void QueueSendChunkTo(int a_ChunkX, int a_ChunkZ, eChunkPriority a_Priority, cClientHandle * a_Client);
|
2018-07-24 17:30:49 -04:00
|
|
|
void QueueSendChunkTo(int a_ChunkX, int a_ChunkZ, eChunkPriority a_Priority, cChunkClientHandles a_Client);
|
2016-02-05 16:45:45 -05:00
|
|
|
|
2015-07-31 10:49:10 -04:00
|
|
|
/** Removes the a_Client from all waiting chunk send operations */
|
2012-06-14 09:06:06 -04:00
|
|
|
void RemoveClient(cClientHandle * a_Client);
|
2016-02-05 16:45:45 -05:00
|
|
|
|
2012-06-14 09:06:06 -04:00
|
|
|
protected:
|
2016-02-05 16:45:45 -05:00
|
|
|
|
2015-06-10 10:16:05 -04:00
|
|
|
struct sChunkQueue
|
|
|
|
{
|
|
|
|
eChunkPriority m_Priority;
|
|
|
|
cChunkCoords m_Chunk;
|
|
|
|
|
2015-06-22 16:27:13 -04:00
|
|
|
bool operator <(const sChunkQueue & a_Other) const
|
|
|
|
{
|
|
|
|
/* The Standard Priority Queue sorts from biggest to smallest
|
|
|
|
return true here means you are smaller than the other object, and you get pushed down.
|
|
|
|
|
|
|
|
The priorities go from HIGH (0) to LOW (2), so a smaller priority should mean further up the list
|
|
|
|
therefore, return true (affirm we're "smaller", and get pushed down) only if our priority is bigger than theirs (they're more urgent)
|
|
|
|
*/
|
|
|
|
return this->m_Priority > a_Other.m_Priority;
|
|
|
|
}
|
2015-06-10 10:16:05 -04:00
|
|
|
};
|
2012-06-14 09:06:06 -04:00
|
|
|
|
2015-07-31 10:49:10 -04:00
|
|
|
/** Used for sending chunks to specific clients */
|
2012-06-14 09:06:06 -04:00
|
|
|
struct sSendChunk
|
|
|
|
{
|
2015-06-10 10:16:05 -04:00
|
|
|
cChunkCoords m_Chunk;
|
|
|
|
std::unordered_set<cClientHandle *> m_Clients;
|
|
|
|
eChunkPriority m_Priority;
|
|
|
|
sSendChunk(cChunkCoords a_Chunk, eChunkPriority a_Priority) :
|
|
|
|
m_Chunk(a_Chunk),
|
|
|
|
m_Priority(a_Priority)
|
2015-06-07 15:45:47 -04:00
|
|
|
{
|
|
|
|
}
|
2015-06-10 10:16:05 -04:00
|
|
|
};
|
2016-02-05 16:45:45 -05:00
|
|
|
|
2015-06-10 10:16:05 -04:00
|
|
|
cWorld & m_World;
|
2016-02-05 16:45:45 -05:00
|
|
|
|
2020-08-21 13:22:04 -04:00
|
|
|
/** An instance of a chunk serializer, held to maintain its internal cache. */
|
|
|
|
cChunkDataSerializer m_Serializer;
|
|
|
|
|
2012-06-14 09:06:06 -04:00
|
|
|
cCriticalSection m_CS;
|
2015-06-10 10:16:05 -04:00
|
|
|
std::priority_queue<sChunkQueue> m_SendChunks;
|
|
|
|
std::unordered_map<cChunkCoords, sSendChunk, cChunkCoordsHash> m_ChunkInfo;
|
2015-06-22 16:27:13 -04:00
|
|
|
cEvent m_evtQueue; // Set when anything is added to m_ChunksReady
|
|
|
|
cEvent m_evtRemoved; // Set when removed clients are safe to be deleted
|
|
|
|
|
2012-06-14 09:06:06 -04:00
|
|
|
// Data about the chunk that is being sent:
|
|
|
|
// NOTE that m_BlockData[] is inherited from the cChunkDataCollector
|
|
|
|
unsigned char m_BiomeMap[cChunkDef::Width * cChunkDef::Width];
|
2015-06-10 10:16:05 -04:00
|
|
|
std::vector<Vector3i> m_BlockEntities; // Coords of the block entities to send
|
2020-06-24 07:48:50 -04:00
|
|
|
std::vector<UInt32> m_EntityIDs; // Entity-IDs of the entities to send
|
2016-02-05 16:45:45 -05:00
|
|
|
|
2012-06-14 09:06:06 -04:00
|
|
|
// cIsThread override:
|
|
|
|
virtual void Execute(void) override;
|
2016-02-05 16:45:45 -05:00
|
|
|
|
2012-06-14 09:06:06 -04:00
|
|
|
// cChunkDataCollector overrides:
|
|
|
|
// (Note that they are called while the ChunkMap's CS is locked - don't do heavy calculations here!)
|
|
|
|
virtual void BiomeData (const cChunkDef::BiomeMap * a_BiomeMap) override;
|
|
|
|
virtual void Entity (cEntity * a_Entity) override;
|
|
|
|
virtual void BlockEntity (cBlockEntity * a_Entity) override;
|
|
|
|
|
2015-07-31 10:49:10 -04:00
|
|
|
/** Sends the specified chunk to all the specified clients */
|
2015-06-10 10:16:05 -04:00
|
|
|
void SendChunk(int a_ChunkX, int a_ChunkZ, std::unordered_set<cClientHandle *> a_Clients);
|
2012-06-14 09:06:06 -04:00
|
|
|
} ;
|
|
|
|
|
|
|
|
|
|
|
|
|