mirror of
https://github.com/celisej567/mcpe.git
synced 2026-09-04 19:36:43 +03:00
* Improve the level sending mechanism in the game.
Instead of sending a request for each chunk one by one, and in sequence, send all the level data in one block. I know this is not the best solution since we are working with UDP here, but it's way faster than loading the level chunk by chunk. In a blink of an eye, the level has already loaded.
This commit is contained in:
@@ -26,6 +26,8 @@ ClientSideNetworkHandler::ClientSideNetworkHandler(Minecraft* pMinecraft, RakNet
|
||||
m_pMinecraft = pMinecraft;
|
||||
m_pRakNetInstance = pRakNetInstance;
|
||||
m_pServerPeer = m_pRakNetInstance->getPeer();
|
||||
m_chunksRequested = 0;
|
||||
m_serverProtocolVersion = 0;
|
||||
}
|
||||
|
||||
void ClientSideNetworkHandler::levelGenerated(Level* level)
|
||||
@@ -108,6 +110,8 @@ void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& rakGuid, StartGa
|
||||
|
||||
m_pLevel->setTime(pStartGamePkt->m_time);
|
||||
|
||||
m_serverProtocolVersion = pStartGamePkt->m_version;
|
||||
|
||||
m_pMinecraft->setLevel(m_pLevel, "ClientSideNetworkHandler -> setLevel", pLocalPlayer);
|
||||
}
|
||||
|
||||
@@ -326,10 +330,13 @@ void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& rakGuid, ChunkDa
|
||||
|
||||
pChunk->m_bUnsaved = true;
|
||||
|
||||
if (areAllChunksLoaded())
|
||||
flushAllBufferedUpdates();
|
||||
else
|
||||
requestNextChunk();
|
||||
if (m_serverProtocolVersion < 2)
|
||||
{
|
||||
if (areAllChunksLoaded())
|
||||
flushAllBufferedUpdates();
|
||||
else
|
||||
requestNextChunk();
|
||||
}
|
||||
}
|
||||
|
||||
void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& rakGuid, PlayerEquipmentPacket* pPlayerEquipmentPkt)
|
||||
@@ -355,6 +362,99 @@ void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& rakGuid, PlayerE
|
||||
pPlayer->m_pInventory->selectItemById(pPlayerEquipmentPkt->m_itemID);
|
||||
}
|
||||
|
||||
void ClientSideNetworkHandler::handle(const RakNet::RakNetGUID& guid, LevelDataPacket* packet)
|
||||
{
|
||||
int uncompMagic = 12847812, compMagic = 58712758, chunkSepMagic = 284787658;
|
||||
RakNet::BitStream* bs = &packet->m_data, bs2;
|
||||
|
||||
int thing = 0;
|
||||
bs->Read(thing);
|
||||
if (thing != compMagic && thing != uncompMagic)
|
||||
{
|
||||
LogMsg("Error, invalid level data packet with magic %d", thing);
|
||||
return;
|
||||
}
|
||||
|
||||
if (thing == compMagic)
|
||||
{
|
||||
int uncompSize = 0, compSize = 0;
|
||||
bs->Read(uncompSize);
|
||||
bs->Read(compSize);
|
||||
|
||||
LogMsg("Decompressing level data. Compressed, uncompressed sizes: %d bytes, %d bytes", compSize, uncompSize);
|
||||
|
||||
uint8_t* pCompData = new uint8_t[compSize];
|
||||
bs->Read((char*)pCompData, compSize);
|
||||
|
||||
uint8_t* pUncompData = ZlibInflateToMemory(pCompData, compSize, uncompSize);
|
||||
delete[] pCompData;
|
||||
|
||||
if (!pUncompData)
|
||||
{
|
||||
LogMsg("Error, can't decompress level data");
|
||||
return;
|
||||
}
|
||||
|
||||
bs2.Reset();
|
||||
bs2.Write((const char*)pUncompData, uncompSize);
|
||||
bs2.ResetReadPointer();
|
||||
bs = &bs2;
|
||||
|
||||
bs->Read(thing);
|
||||
}
|
||||
|
||||
int chunksX = 0, chunksZ = 0;
|
||||
bs->Read(chunksX);
|
||||
bs->Read(chunksZ);
|
||||
|
||||
if (chunksX != C_MAX_CHUNKS_X || chunksZ != C_MAX_CHUNKS_Z)
|
||||
{
|
||||
LogMsg("Error, we don't yet support a level of size %d x %d chunks. Some chunks may disappear or be regenerated.", chunksX, chunksZ);
|
||||
}
|
||||
|
||||
for (int x = 0; x < chunksX; x++)
|
||||
{
|
||||
for (int z = 0; z < chunksZ; z++)
|
||||
{
|
||||
uint8_t ptype = 0;
|
||||
bs->Read(thing);
|
||||
|
||||
int dataSize = 0;
|
||||
bs->Read(dataSize);
|
||||
|
||||
if (thing != chunkSepMagic)
|
||||
{
|
||||
_FAIL_BECAUSE_INVALID:
|
||||
LogMsg("Error, aborting because level data is invalid. Reading chunk %d,%d. Thing=%d PType=%d",x,z,thing,ptype);
|
||||
return;
|
||||
}
|
||||
|
||||
LevelChunk* pChunk = m_pLevel->getChunk(x, z);
|
||||
if (!pChunk)
|
||||
LogMsg("No chunk at %d,%d", x, z);
|
||||
|
||||
RakNet::BitStream bs2;
|
||||
bs2.Write(*bs, 8 * dataSize);
|
||||
|
||||
bs2.Read(ptype);
|
||||
if (ptype != PACKET_CHUNK_DATA)
|
||||
goto _FAIL_BECAUSE_INVALID;
|
||||
|
||||
ChunkDataPacket cdp(x, z, pChunk);
|
||||
cdp.read(&bs2);
|
||||
LogMsg("Chunk %d,%d", cdp.m_x, cdp.m_z);
|
||||
|
||||
if (pChunk)
|
||||
handle(guid, &cdp);
|
||||
|
||||
while (m_pLevel->updateLights());
|
||||
}
|
||||
}
|
||||
|
||||
m_chunksRequested = 256;// all chunks are loaded!!
|
||||
flushAllBufferedUpdates();
|
||||
}
|
||||
|
||||
bool ClientSideNetworkHandler::areAllChunksLoaded()
|
||||
{
|
||||
return m_chunksRequested > 255;
|
||||
@@ -368,8 +468,15 @@ void ClientSideNetworkHandler::requestNextChunk()
|
||||
// @BUG: The return value of areAllChunksLoaded() is actually true even before the
|
||||
// 256th chunk is loaded.
|
||||
|
||||
m_pRakNetInstance->send(new RequestChunkPacket(m_chunksRequested % 16, m_chunksRequested / 16));
|
||||
m_chunksRequested++;
|
||||
if (m_serverProtocolVersion < 2)
|
||||
{
|
||||
m_pRakNetInstance->send(new RequestChunkPacket(m_chunksRequested % 16, m_chunksRequested / 16));
|
||||
m_chunksRequested++;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pRakNetInstance->send(new RequestChunkPacket(-9999, -9999));
|
||||
}
|
||||
}
|
||||
|
||||
void ClientSideNetworkHandler::flushAllBufferedUpdates()
|
||||
|
||||
Reference in New Issue
Block a user