Added the "/regeneratechunk" command that regenerates either current chunk or a chunk specified with x, z parameters. TODO: permissions - we don't want guests erasing our chunks!
git-svn-id: http://mc-server.googlecode.com/svn/trunk@454 0a769ca7-a7f5-676a-18bf-c427514a06d6
This commit is contained in:
parent
e009569060
commit
c51a4b9469
@ -67,11 +67,11 @@ sSetBlock::sSetBlock( int a_X, int a_Y, int a_Z, char a_BlockType, char a_BlockM
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// cChunk:
|
||||
|
||||
cChunk::cChunk(int a_X, int a_Y, int a_Z, cChunkMap * a_ChunkMap, cWorld * a_World)
|
||||
cChunk::cChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ, cChunkMap * a_ChunkMap, cWorld * a_World)
|
||||
: m_bCalculateLighting( false )
|
||||
, m_PosX( a_X )
|
||||
, m_PosY( a_Y )
|
||||
, m_PosZ( a_Z )
|
||||
, m_PosX( a_ChunkX )
|
||||
, m_PosY( a_ChunkY )
|
||||
, m_PosZ( a_ChunkZ )
|
||||
, m_BlockTickNum( 0 )
|
||||
, m_BlockTickX( 0 )
|
||||
, m_BlockTickY( 0 )
|
||||
@ -121,38 +121,24 @@ cChunk::~cChunk()
|
||||
|
||||
|
||||
|
||||
void cChunk::SetValid(bool a_SendToClients)
|
||||
void cChunk::SetValid(void)
|
||||
{
|
||||
m_IsValid = true;
|
||||
|
||||
m_World->GetChunkMap()->ChunkValidated();
|
||||
|
||||
if (!a_SendToClients)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_LoadedByClient.empty())
|
||||
|
||||
|
||||
|
||||
|
||||
void cChunk::MarkRegenerating(void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Sending the chunk here interferes with the lighting done in the tick thread and results in the "invalid compressed data" on the client
|
||||
/*
|
||||
cPacket_PreChunk PreChunk;
|
||||
PreChunk.m_PosX = m_PosX;
|
||||
PreChunk.m_PosZ = m_PosZ;
|
||||
PreChunk.m_bLoad = true;
|
||||
cPacket_MapChunk MapChunk(this);
|
||||
Broadcast(&PreChunk);
|
||||
Broadcast(&MapChunk);
|
||||
|
||||
// Let all clients of this chunk know that it has been already sent to the client
|
||||
// Tell all clients attached to this chunk that they want this chunk:
|
||||
for (cClientHandleList::iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr)
|
||||
{
|
||||
(*itr)->ChunkJustSent(this);
|
||||
(*itr)->AddWantedChunk(m_PosX, m_PosZ);
|
||||
} // for itr - m_LoadedByClient[]
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
|
@ -51,11 +51,12 @@ class cChunk :
|
||||
public cChunkDef // The inheritance is "misused" here only to inherit the functions and constants defined in cChunkDef
|
||||
{
|
||||
public:
|
||||
cChunk(int a_X, int a_Y, int a_Z, cChunkMap * a_ChunkMap, cWorld * a_World);
|
||||
cChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ, cChunkMap * a_ChunkMap, cWorld * a_World);
|
||||
~cChunk();
|
||||
|
||||
bool IsValid(void) const {return m_IsValid; } // Returns true if the chunk is valid (loaded / generated)
|
||||
void SetValid(bool a_SendToClients = true); // Also wakes up all clients attached to this chunk to let them finish logging in
|
||||
void SetValid(void); // Also wakes up any calls to cChunkMap::GetHeight()
|
||||
void MarkRegenerating(void); // Marks all clients attached to this chunk as wanting this chunk
|
||||
bool IsDirty(void) const {return m_IsDirty; } // Returns true if the chunk has changed since it was last saved
|
||||
bool HasLoadFailed(void) const {return m_HasLoadFailed; } // Returns true if the chunk failed to load and hasn't been generated since then
|
||||
bool CanUnload(void);
|
||||
|
@ -155,15 +155,17 @@ void cChunkGenerator::Execute(void)
|
||||
Lock.Unlock(); // Unlock ASAP
|
||||
m_evtRemoved.Set();
|
||||
|
||||
if (m_World->IsChunkValid(coords.m_ChunkX, coords.m_ChunkY, coords.m_ChunkZ))
|
||||
// Hack for regenerating chunks: if Y != 0, the chunk is considered invalid, even if it has its data set
|
||||
if ((coords.m_ChunkY == 0) && m_World->IsChunkValid(coords.m_ChunkX, coords.m_ChunkY, coords.m_ChunkZ))
|
||||
{
|
||||
LOGD("Chunk [%d, %d] already generated, skipping generation", coords.m_ChunkX, coords.m_ChunkZ);
|
||||
// Already generated, ignore request
|
||||
continue;
|
||||
}
|
||||
|
||||
if (SkipEnabled && !m_World->HasChunkAnyClients(coords.m_ChunkX, coords.m_ChunkY, coords.m_ChunkZ))
|
||||
{
|
||||
LOGWARNING("Chunk generator overloaded, skipping chunk [%d, %d, %d] (HasClients: %d)", coords.m_ChunkX, coords.m_ChunkY, coords.m_ChunkZ);
|
||||
LOGWARNING("Chunk generator overloaded, skipping chunk [%d, %d, %d]", coords.m_ChunkX, coords.m_ChunkY, coords.m_ChunkZ);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -897,6 +897,22 @@ void cChunkMap::ChunksStay(const cChunkCoordsList & a_Chunks, bool a_Stay)
|
||||
|
||||
|
||||
|
||||
void cChunkMap::MarkChunkRegenerating(int a_ChunkX, int a_ChunkZ)
|
||||
{
|
||||
cCSLock Lock(m_CSLayers);
|
||||
cChunkPtr Chunk = GetChunkNoLoad(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ);
|
||||
if (Chunk == NULL)
|
||||
{
|
||||
// Not present
|
||||
return;
|
||||
}
|
||||
Chunk->MarkRegenerating();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cChunkMap::Tick( float a_Dt, MTRand & a_TickRandom )
|
||||
{
|
||||
cCSLock Lock(m_CSLayers);
|
||||
@ -971,7 +987,6 @@ cChunkPtr cChunkMap::cChunkLayer::GetChunk( int a_ChunkX, int a_ChunkY, int a_Ch
|
||||
const int LocalX = a_ChunkX - m_LayerX * LAYER_SIZE;
|
||||
const int LocalZ = a_ChunkZ - m_LayerZ * LAYER_SIZE;
|
||||
|
||||
|
||||
if (!((LocalX < LAYER_SIZE) && (LocalZ < LAYER_SIZE) && (LocalX > -1) && (LocalZ > -1)))
|
||||
{
|
||||
ASSERT(!"Asking a cChunkLayer for a chunk that doesn't belong to it!");
|
||||
|
@ -128,6 +128,9 @@ public:
|
||||
/// Marks (a_Stay == true) or unmarks (a_Stay == false) chunks as non-unloadable; to be used only by cChunkStay!
|
||||
void ChunksStay(const cChunkCoordsList & a_Chunks, bool a_Stay = true);
|
||||
|
||||
/// Marks the chunk as being regenerated - all its clients want that chunk again (used by cWorld::RegenerateChunk() )
|
||||
void MarkChunkRegenerating(int a_ChunkX, int a_ChunkZ);
|
||||
|
||||
void Tick( float a_Dt, MTRand & a_TickRand );
|
||||
|
||||
void UnloadUnusedChunks();
|
||||
|
@ -1708,9 +1708,9 @@ void cClientHandle::Send(const cPacket & a_Packet, ENUM_PRIORITY a_Priority /* =
|
||||
}
|
||||
}
|
||||
|
||||
// Check chunks being sent, erase them from m_ChunksToSend:
|
||||
if (a_Packet.m_PacketID == E_MAP_CHUNK)
|
||||
{
|
||||
// Check chunks being sent, erase them from m_ChunksToSend:
|
||||
int ChunkX = ((cPacket_MapChunk &)a_Packet).m_PosX;
|
||||
int ChunkZ = ((cPacket_MapChunk &)a_Packet).m_PosZ;
|
||||
bool Found = false;
|
||||
@ -1727,6 +1727,7 @@ void cClientHandle::Send(const cPacket & a_Packet, ENUM_PRIORITY a_Priority /* =
|
||||
} // for itr - m_ChunksToSend[]
|
||||
if (!Found)
|
||||
{
|
||||
LOGD("Refusing to send chunk [%d, %d] - no longer wanted by client \"%s\".", ChunkX, ChunkZ, m_Username.c_str());
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -1858,6 +1859,20 @@ bool cClientHandle::WantsSendChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
|
||||
|
||||
|
||||
|
||||
void cClientHandle::AddWantedChunk(int a_ChunkX, int a_ChunkZ)
|
||||
{
|
||||
LOGD("Adding chunk [%d, %d] to wanted chunks for client %p", a_ChunkX, a_ChunkZ, this);
|
||||
cCSLock Lock(m_CSChunkLists);
|
||||
if (std::find(m_ChunksToSend.begin(), m_ChunksToSend.end(), cChunkCoords(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ)) == m_ChunksToSend.end())
|
||||
{
|
||||
m_ChunksToSend.push_back(cChunkCoords(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cClientHandle::DataReceived(const char * a_Data, int a_Size)
|
||||
{
|
||||
// Data is received from the client
|
||||
|
@ -112,6 +112,9 @@ public:
|
||||
/// 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);
|
||||
|
||||
/// Adds the chunk specified to the list of chunks wanted for sending (m_ChunksToSend)
|
||||
void AddWantedChunk(int a_ChunkX, int a_ChunkZ);
|
||||
|
||||
private:
|
||||
|
||||
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 )
|
||||
|
@ -485,13 +485,40 @@ bool cServer::Command( cClientHandle & a_Client, const char* a_Cmd )
|
||||
{
|
||||
if (split.size() != 2)
|
||||
{
|
||||
a_Client.Send(cPacket_Chat(cChatColor::Green + "Invalid syntax, expected 1 parameter, the numebr of chunks to stream"));
|
||||
a_Client.Send(cPacket_Chat(cChatColor::Green + "Invalid syntax, expected 1 parameter, the number of chunks to stream"));
|
||||
return false;
|
||||
}
|
||||
int dist = atol(split[1].c_str());
|
||||
a_Client.SetViewDistance(dist);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (split[0].compare("/regeneratechunk") == 0)
|
||||
{
|
||||
int ChunkX, ChunkZ;
|
||||
if (split.size() == 1)
|
||||
{
|
||||
// Regenerate current chunk
|
||||
ChunkX = a_Client.GetPlayer()->GetChunkX();
|
||||
ChunkZ = a_Client.GetPlayer()->GetChunkZ();
|
||||
}
|
||||
else if (split.size() == 3)
|
||||
{
|
||||
// Regenerate chunk in params
|
||||
ChunkX = atoi(split[1].c_str());
|
||||
ChunkZ = atoi(split[2].c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
a_Client.Send(cPacket_Chat(cChatColor::Green + "Invalid syntax, expected either 0 (current chunk) or 2 (x, z) parameters"));
|
||||
return false;
|
||||
}
|
||||
AString Msg;
|
||||
Printf(Msg, "Regenerating chunk [%d, %d]", ChunkX, ChunkZ);
|
||||
a_Client.Send(cPacket_Chat(cChatColor::Green + Msg));
|
||||
a_Client.GetPlayer()->GetWorld()->RegenerateChunk(ChunkX, ChunkZ);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1426,6 +1426,18 @@ void cWorld::ChunksStay(const cChunkCoordsList & a_Chunks, bool a_Stay)
|
||||
|
||||
|
||||
|
||||
void cWorld::RegenerateChunk(int a_ChunkX, int a_ChunkZ)
|
||||
{
|
||||
m_ChunkMap->MarkChunkRegenerating(a_ChunkX, a_ChunkZ);
|
||||
|
||||
// Trick: use Y=1 to force the chunk generation even though the chunk data is already present
|
||||
m_Generator.GenerateChunk(a_ChunkX, 1, a_ChunkZ);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cWorld::SaveAllChunks()
|
||||
{
|
||||
LOG("Saving all chunks...");
|
||||
|
@ -176,6 +176,9 @@ public:
|
||||
/// Marks (a_Stay == true) or unmarks (a_Stay == false) chunks as non-unloadable. To be used only by cChunkStay!
|
||||
void ChunksStay(const cChunkCoordsList & a_Chunks, bool a_Stay = true);
|
||||
|
||||
/// Regenerate the given chunk:
|
||||
void RegenerateChunk(int a_ChunkX, int a_ChunkZ);
|
||||
|
||||
// TODO: Export to Lua
|
||||
bool DoWithEntity( int a_UniqueID, cEntityCallback & a_Callback );
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user