2017-09-02 03:45:06 -04:00
|
|
|
|
2012-06-14 09:06:06 -04:00
|
|
|
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
|
|
|
|
|
2012-09-23 18:09:57 -04:00
|
|
|
#include "ChunkMap.h"
|
2020-04-03 02:57:01 -04:00
|
|
|
#include "BlockInfo.h"
|
2012-09-23 18:09:57 -04:00
|
|
|
#include "World.h"
|
|
|
|
#include "Root.h"
|
2013-08-19 05:39:13 -04:00
|
|
|
#include "Entities/Player.h"
|
2012-09-23 18:09:57 -04:00
|
|
|
#include "Item.h"
|
|
|
|
#include "Chunk.h"
|
2012-09-23 16:14:04 -04:00
|
|
|
#include "Generating/Trees.h" // used in cChunkMap::ReplaceTreeBlocks() for tree block discrimination
|
2012-10-06 12:58:31 -04:00
|
|
|
#include "BlockArea.h"
|
2013-12-08 06:17:54 -05:00
|
|
|
#include "Bindings/PluginManager.h"
|
2013-08-19 05:39:13 -04:00
|
|
|
#include "Entities/TNTEntity.h"
|
2013-10-23 18:40:59 -04:00
|
|
|
#include "Blocks/BlockHandler.h"
|
2013-09-07 16:19:56 -04:00
|
|
|
#include "MobCensus.h"
|
2013-09-07 18:11:38 -04:00
|
|
|
#include "MobSpawner.h"
|
2014-02-02 14:16:38 -05:00
|
|
|
#include "BoundingBox.h"
|
2014-07-24 12:32:05 -04:00
|
|
|
#include "SetChunkData.h"
|
2014-09-26 13:13:19 -04:00
|
|
|
#include "Blocks/ChunkInterface.h"
|
2014-02-02 14:16:38 -05:00
|
|
|
#include "Entities/Pickup.h"
|
2017-01-17 16:38:04 -05:00
|
|
|
#include "DeadlockDetect.h"
|
2017-09-27 17:22:15 -04:00
|
|
|
#include "BlockEntities/BlockEntity.h"
|
2012-06-14 09:06:06 -04:00
|
|
|
|
2013-11-27 02:40:59 -05:00
|
|
|
#include "zlib/zlib.h"
|
2013-11-27 03:17:25 -05:00
|
|
|
#include "json/json.h"
|
2012-06-14 09:06:06 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// cChunkMap:
|
|
|
|
|
2014-07-17 13:13:23 -04:00
|
|
|
cChunkMap::cChunkMap(cWorld * a_World) :
|
|
|
|
m_World(a_World),
|
2014-06-16 10:12:50 -04:00
|
|
|
m_Pool(
|
2020-08-01 14:18:03 -04:00
|
|
|
std::make_unique<cListAllocationPool<cChunkData::sChunkSection>>(
|
|
|
|
std::make_unique<cStarvationCallbacks>(), 1600u, 5000u
|
2014-06-16 10:12:50 -04:00
|
|
|
)
|
2014-07-17 13:13:23 -04:00
|
|
|
)
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2016-05-01 17:18:21 -04:00
|
|
|
cChunkMap::~cChunkMap()
|
|
|
|
{
|
2016-08-02 18:56:53 -04:00
|
|
|
// Explicitly destroy all chunks, so that they're guaranteed to be
|
2016-05-01 17:18:21 -04:00
|
|
|
// destroyed before other internals. This fixes crashes on stopping the server.
|
|
|
|
// because the chunk destructor deletes entities and those may access the chunkmap.
|
|
|
|
// Also, the cChunkData destructor accesses the chunkMap's allocator.
|
2016-08-02 18:56:53 -04:00
|
|
|
m_Chunks.clear();
|
2012-06-14 09:06:06 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-08-28 16:22:44 -04:00
|
|
|
cChunk & cChunkMap::ConstructChunk(int a_ChunkX, int a_ChunkZ)
|
2012-12-14 17:38:30 -05:00
|
|
|
{
|
2020-08-20 07:50:22 -04:00
|
|
|
// If not exists insert. Then, return the chunk at these coordinates:
|
2020-08-28 16:22:44 -04:00
|
|
|
return m_Chunks.try_emplace(
|
2020-08-20 07:50:22 -04:00
|
|
|
ChunkCoordinate{ a_ChunkX, a_ChunkZ },
|
|
|
|
a_ChunkX, a_ChunkZ, this, m_World, *m_Pool
|
|
|
|
).first->second;
|
2012-06-14 09:06:06 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-08-28 16:22:44 -04:00
|
|
|
cChunk & cChunkMap::GetChunk(int a_ChunkX, int a_ChunkZ)
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2016-08-02 18:56:53 -04:00
|
|
|
ASSERT(m_CSChunks.IsLockedByCurrentThread()); // m_CSChunks should already be locked by the operation that called us
|
2012-12-14 17:38:30 -05:00
|
|
|
|
2020-08-28 16:22:44 -04:00
|
|
|
auto & Chunk = ConstructChunk(a_ChunkX, a_ChunkZ);
|
|
|
|
if (!Chunk.IsValid() && !Chunk.IsQueued())
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2020-08-28 16:22:44 -04:00
|
|
|
Chunk.SetPresence(cChunk::cpQueued);
|
2014-09-05 17:26:00 -04:00
|
|
|
m_World->GetStorage().QueueLoadChunk(a_ChunkX, a_ChunkZ);
|
2012-06-14 09:06:06 -04:00
|
|
|
}
|
|
|
|
return Chunk;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2012-12-14 17:38:30 -05:00
|
|
|
cChunk * cChunkMap::FindChunk(int a_ChunkX, int a_ChunkZ)
|
|
|
|
{
|
2016-08-02 18:56:53 -04:00
|
|
|
ASSERT(m_CSChunks.IsLockedByCurrentThread());
|
2016-02-05 16:45:45 -05:00
|
|
|
|
2020-11-02 10:44:02 -05:00
|
|
|
const auto Chunk = m_Chunks.find({ a_ChunkX, a_ChunkZ });
|
2020-08-20 07:50:22 -04:00
|
|
|
return (Chunk == m_Chunks.end()) ? nullptr : &Chunk->second;
|
2012-12-14 17:38:30 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2012-08-24 03:58:26 -04:00
|
|
|
void cChunkMap::SendBlockEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cClientHandle & a_Client)
|
|
|
|
{
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
2012-08-24 03:58:26 -04:00
|
|
|
int ChunkX, ChunkZ;
|
2013-08-03 14:05:07 -04:00
|
|
|
cChunkDef::BlockToChunk(a_BlockX, a_BlockZ, ChunkX, ChunkZ);
|
2020-08-28 16:22:44 -04:00
|
|
|
const auto Chunk = FindChunk(ChunkX, ChunkZ);
|
2014-10-20 16:55:07 -04:00
|
|
|
if ((Chunk == nullptr) || !Chunk->IsValid())
|
2012-08-24 03:58:26 -04:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
Chunk->SendBlockEntity(a_BlockX, a_BlockY, a_BlockZ, a_Client);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2015-12-01 17:12:44 -05:00
|
|
|
bool cChunkMap::UseBlockEntity(cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ)
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
|
|
|
// a_Player rclked block entity at the coords specified, handle it
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
2012-06-14 09:06:06 -04:00
|
|
|
int ChunkX, ChunkZ;
|
2013-08-03 14:05:07 -04:00
|
|
|
cChunkDef::BlockToChunk(a_BlockX, a_BlockZ, ChunkX, ChunkZ);
|
2020-08-28 16:22:44 -04:00
|
|
|
const auto Chunk = FindChunk(ChunkX, ChunkZ);
|
2014-10-20 16:55:07 -04:00
|
|
|
if ((Chunk == nullptr) || !Chunk->IsValid())
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2015-12-01 17:12:44 -05:00
|
|
|
return false;
|
2012-06-14 09:06:06 -04:00
|
|
|
}
|
2015-12-01 17:12:44 -05:00
|
|
|
return Chunk->UseBlockEntity(a_Player, a_BlockX, a_BlockY, a_BlockZ);
|
2012-06-14 09:06:06 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2017-09-11 17:20:49 -04:00
|
|
|
bool cChunkMap::DoWithChunk(int a_ChunkX, int a_ChunkZ, cChunkCallback a_Callback)
|
2013-08-03 14:26:50 -04:00
|
|
|
{
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
2020-08-28 16:22:44 -04:00
|
|
|
const auto Chunk = FindChunk(a_ChunkX, a_ChunkZ);
|
|
|
|
if ((Chunk == nullptr) || !Chunk->IsValid())
|
2013-08-03 14:26:50 -04:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
2017-09-11 17:20:49 -04:00
|
|
|
return a_Callback(*Chunk);
|
2013-08-03 14:26:50 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-07-26 17:24:36 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
2017-09-11 17:20:49 -04:00
|
|
|
bool cChunkMap::DoWithChunkAt(Vector3i a_BlockPos, cChunkCallback a_Callback)
|
2015-03-21 13:17:26 -04:00
|
|
|
{
|
|
|
|
int ChunkX, ChunkZ;
|
|
|
|
cChunkDef::BlockToChunk(a_BlockPos.x, a_BlockPos.z, ChunkX, ChunkZ);
|
2017-09-11 17:20:49 -04:00
|
|
|
return DoWithChunk(ChunkX, ChunkZ, a_Callback);
|
2015-03-21 13:17:26 -04:00
|
|
|
}
|
|
|
|
|
2013-08-03 14:26:50 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
2018-07-26 17:24:36 -04:00
|
|
|
|
2017-08-17 09:48:38 -04:00
|
|
|
void cChunkMap::WakeUpSimulators(Vector3i a_Block)
|
2013-02-28 02:42:45 -05:00
|
|
|
{
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
2020-08-28 16:22:44 -04:00
|
|
|
const auto Position = cChunkDef::BlockToChunk(a_Block);
|
|
|
|
const auto Chunk = FindChunk(Position.m_ChunkX, Position.m_ChunkZ);
|
2014-10-20 16:55:07 -04:00
|
|
|
if ((Chunk == nullptr) || !Chunk->IsValid())
|
2013-02-28 02:42:45 -05:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2020-07-28 20:18:59 -04:00
|
|
|
|
2020-08-28 16:22:44 -04:00
|
|
|
m_World->GetSimulatorManager()->WakeUp(*Chunk, cChunkDef::AbsoluteToRelative(a_Block, Position));
|
2013-02-28 02:42:45 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2016-04-18 06:30:23 -04:00
|
|
|
void cChunkMap::MarkChunkDirty(int a_ChunkX, int a_ChunkZ)
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
2020-08-28 16:22:44 -04:00
|
|
|
const auto Chunk = FindChunk(a_ChunkX, a_ChunkZ);
|
2014-10-20 16:55:07 -04:00
|
|
|
if ((Chunk == nullptr) || !Chunk->IsValid())
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
Chunk->MarkDirty();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2013-04-13 17:02:10 -04:00
|
|
|
void cChunkMap::MarkChunkSaving(int a_ChunkX, int a_ChunkZ)
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
2020-08-28 16:22:44 -04:00
|
|
|
const auto Chunk = FindChunk(a_ChunkX, a_ChunkZ);
|
2014-10-20 16:55:07 -04:00
|
|
|
if ((Chunk == nullptr) || !Chunk->IsValid())
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
Chunk->MarkSaving();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2013-04-13 17:02:10 -04:00
|
|
|
void cChunkMap::MarkChunkSaved (int a_ChunkX, int a_ChunkZ)
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
2020-08-28 16:22:44 -04:00
|
|
|
const auto Chunk = FindChunk(a_ChunkX, a_ChunkZ);
|
2014-10-20 16:55:07 -04:00
|
|
|
if ((Chunk == nullptr) || !Chunk->IsValid())
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
Chunk->MarkSaved();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2014-07-24 12:32:05 -04:00
|
|
|
void cChunkMap::SetChunkData(cSetChunkData & a_SetChunkData)
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2014-07-24 12:32:05 -04:00
|
|
|
int ChunkX = a_SetChunkData.GetChunkX();
|
|
|
|
int ChunkZ = a_SetChunkData.GetChunkZ();
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
2020-08-28 16:22:44 -04:00
|
|
|
const auto Chunk = FindChunk(ChunkX, ChunkZ);
|
|
|
|
ASSERT(Chunk != nullptr); // Chunk cannot have unloaded since it is marked as queued
|
2014-07-24 12:32:05 -04:00
|
|
|
Chunk->SetAllData(a_SetChunkData);
|
2016-02-05 16:45:45 -05:00
|
|
|
|
2014-07-24 12:32:05 -04:00
|
|
|
if (a_SetChunkData.ShouldMarkDirty())
|
2014-02-08 15:55:21 -05:00
|
|
|
{
|
|
|
|
Chunk->MarkDirty();
|
|
|
|
}
|
2016-02-05 16:45:45 -05:00
|
|
|
|
2014-02-08 15:55:21 -05:00
|
|
|
// Notify relevant ChunkStays:
|
2014-04-12 16:15:09 -04:00
|
|
|
cChunkStays ToBeDisabled;
|
|
|
|
for (cChunkStays::iterator itr = m_ChunkStays.begin(), end = m_ChunkStays.end(); itr != end; ++itr)
|
2014-02-08 15:55:21 -05:00
|
|
|
{
|
2014-07-24 12:32:05 -04:00
|
|
|
if ((*itr)->ChunkAvailable(ChunkX, ChunkZ))
|
2014-02-10 16:47:10 -05:00
|
|
|
{
|
2014-04-12 16:15:09 -04:00
|
|
|
// The chunkstay wants to be disabled, add it to a list of to-be-disabled chunkstays for later processing:
|
|
|
|
ToBeDisabled.push_back(*itr);
|
2014-02-10 16:47:10 -05:00
|
|
|
}
|
2014-02-08 15:55:21 -05:00
|
|
|
} // for itr - m_ChunkStays[]
|
2016-02-05 16:45:45 -05:00
|
|
|
|
2014-04-12 16:15:09 -04:00
|
|
|
// Disable (and possibly remove) the chunkstays that chose to get disabled:
|
|
|
|
for (cChunkStays::iterator itr = ToBeDisabled.begin(), end = ToBeDisabled.end(); itr != end; ++itr)
|
|
|
|
{
|
|
|
|
(*itr)->Disable();
|
|
|
|
}
|
2012-06-14 09:06:06 -04:00
|
|
|
}
|
2013-02-05 14:57:22 -05:00
|
|
|
|
|
|
|
// Notify plugins of the chunk becoming available
|
2014-10-15 13:01:55 -04:00
|
|
|
cPluginManager::Get()->CallHookChunkAvailable(*m_World, ChunkX, ChunkZ);
|
2012-06-14 09:06:06 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void cChunkMap::ChunkLighted(
|
|
|
|
int a_ChunkX, int a_ChunkZ,
|
|
|
|
const cChunkDef::BlockNibbles & a_BlockLight,
|
|
|
|
const cChunkDef::BlockNibbles & a_SkyLight
|
|
|
|
)
|
|
|
|
{
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
2020-08-28 16:22:44 -04:00
|
|
|
const auto Chunk = FindChunk(a_ChunkX, a_ChunkZ);
|
2014-10-20 16:55:07 -04:00
|
|
|
if (Chunk == nullptr)
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2020-08-28 16:22:44 -04:00
|
|
|
// Chunk probably unloaded in the meantime
|
2012-06-14 09:06:06 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
Chunk->SetLight(a_BlockLight, a_SkyLight);
|
|
|
|
Chunk->MarkDirty();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2019-09-24 08:20:50 -04:00
|
|
|
bool cChunkMap::GetChunkData(cChunkCoords a_Coords, cChunkDataCallback & a_Callback)
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2019-09-24 08:20:50 -04:00
|
|
|
if (!a_Callback.Coords(a_Coords.m_ChunkX, a_Coords.m_ChunkZ))
|
|
|
|
{
|
|
|
|
// The callback doesn't want the data
|
|
|
|
return false;
|
|
|
|
}
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
2020-08-28 16:22:44 -04:00
|
|
|
const auto Chunk = FindChunk(a_Coords.m_ChunkX, a_Coords.m_ChunkZ);
|
2014-10-20 16:55:07 -04:00
|
|
|
if ((Chunk == nullptr) || !Chunk->IsValid())
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2019-09-24 08:20:50 -04:00
|
|
|
// The chunk is not present
|
2012-06-14 09:06:06 -04:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
Chunk->GetAllData(a_Callback);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2013-04-13 17:02:10 -04:00
|
|
|
bool cChunkMap::GetChunkBlockTypes(int a_ChunkX, int a_ChunkZ, BLOCKTYPE * a_BlockTypes)
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
2020-08-28 16:22:44 -04:00
|
|
|
const auto Chunk = FindChunk(a_ChunkX, a_ChunkZ);
|
2014-10-20 16:55:07 -04:00
|
|
|
if ((Chunk == nullptr) || !Chunk->IsValid())
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
Chunk->GetBlockTypes(a_BlockTypes);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2014-09-05 16:16:48 -04:00
|
|
|
bool cChunkMap::IsChunkQueued(int a_ChunkX, int a_ChunkZ)
|
|
|
|
{
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
2020-08-28 16:22:44 -04:00
|
|
|
const auto Chunk = FindChunk(a_ChunkX, a_ChunkZ);
|
2014-10-20 16:55:07 -04:00
|
|
|
return (Chunk != nullptr) && Chunk->IsQueued();
|
2014-09-05 16:16:48 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2013-04-13 17:02:10 -04:00
|
|
|
bool cChunkMap::IsChunkValid(int a_ChunkX, int a_ChunkZ)
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
2020-08-28 16:22:44 -04:00
|
|
|
const auto Chunk = FindChunk(a_ChunkX, a_ChunkZ);
|
2014-10-20 16:55:07 -04:00
|
|
|
return (Chunk != nullptr) && Chunk->IsValid();
|
2012-06-14 09:06:06 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2013-04-13 17:02:10 -04:00
|
|
|
bool cChunkMap::HasChunkAnyClients(int a_ChunkX, int a_ChunkZ)
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
2020-08-28 16:22:44 -04:00
|
|
|
const auto Chunk = FindChunk(a_ChunkX, a_ChunkZ);
|
2014-10-20 16:55:07 -04:00
|
|
|
return (Chunk != nullptr) && Chunk->HasAnyClients();
|
2012-06-14 09:06:06 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int cChunkMap::GetHeight(int a_BlockX, int a_BlockZ)
|
|
|
|
{
|
2014-01-07 10:00:19 -05:00
|
|
|
for (;;)
|
2013-04-13 17:02:10 -04:00
|
|
|
{
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
2013-04-13 17:02:10 -04:00
|
|
|
int ChunkX, ChunkZ, BlockY = 0;
|
|
|
|
cChunkDef::AbsoluteToRelative(a_BlockX, BlockY, a_BlockZ, ChunkX, ChunkZ);
|
2020-08-28 16:22:44 -04:00
|
|
|
auto & Chunk = GetChunk(ChunkX, ChunkZ);
|
|
|
|
if (Chunk.IsValid())
|
2013-04-13 17:02:10 -04:00
|
|
|
{
|
2020-08-28 16:22:44 -04:00
|
|
|
return Chunk.GetHeight(a_BlockX, a_BlockZ);
|
2013-04-13 17:02:10 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
// The chunk is not valid, wait for it to become valid:
|
|
|
|
cCSUnlock Unlock(Lock);
|
|
|
|
m_evtChunkValid.Wait();
|
|
|
|
} // while (true)
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool cChunkMap::TryGetHeight(int a_BlockX, int a_BlockZ, int & a_Height)
|
|
|
|
{
|
|
|
|
// Returns false if chunk not loaded / generated
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
2012-06-14 09:06:06 -04:00
|
|
|
int ChunkX, ChunkZ, BlockY = 0;
|
|
|
|
cChunkDef::AbsoluteToRelative(a_BlockX, BlockY, a_BlockZ, ChunkX, ChunkZ);
|
2020-08-28 16:22:44 -04:00
|
|
|
const auto Chunk = FindChunk(ChunkX, ChunkZ);
|
2014-10-20 16:55:07 -04:00
|
|
|
if ((Chunk == nullptr) || !Chunk->IsValid())
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2013-04-13 17:02:10 -04:00
|
|
|
return false;
|
2012-06-14 09:06:06 -04:00
|
|
|
}
|
2013-04-13 17:02:10 -04:00
|
|
|
a_Height = Chunk->GetHeight(a_BlockX, a_BlockZ);
|
|
|
|
return true;
|
2012-06-14 09:06:06 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2019-10-11 05:02:53 -04:00
|
|
|
void cChunkMap::FastSetBlock(Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
|
|
|
|
{
|
|
|
|
auto chunkPos = cChunkDef::BlockToChunk(a_BlockPos);
|
|
|
|
auto relPos = cChunkDef::AbsoluteToRelative(a_BlockPos, chunkPos);
|
|
|
|
|
|
|
|
cCSLock Lock(m_CSChunks);
|
2020-08-28 16:22:44 -04:00
|
|
|
const auto Chunk = FindChunk(chunkPos.m_ChunkX, chunkPos.m_ChunkZ);
|
|
|
|
if ((Chunk != nullptr) && Chunk->IsValid())
|
2019-10-11 05:02:53 -04:00
|
|
|
{
|
2020-08-28 16:22:44 -04:00
|
|
|
Chunk->FastSetBlock(relPos, a_BlockType, a_BlockMeta);
|
2019-10-11 05:02:53 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2014-10-15 13:01:55 -04:00
|
|
|
void cChunkMap::CollectPickupsByPlayer(cPlayer & a_Player)
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2020-08-28 16:35:38 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
2016-02-05 16:45:45 -05:00
|
|
|
|
2020-08-28 16:35:38 -04:00
|
|
|
auto BoundingBox = a_Player.GetBoundingBox();
|
|
|
|
BoundingBox.Expand(1, 0.5, 1);
|
2016-02-05 16:45:45 -05:00
|
|
|
|
2020-08-28 16:35:38 -04:00
|
|
|
ForEachEntityInBox(BoundingBox, [&a_Player](cEntity & Entity)
|
|
|
|
{
|
|
|
|
// Only pickups and projectiles can be picked up:
|
|
|
|
if (Entity.IsPickup())
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
LOG("Pickup %d being collected by player \"%s\", distance %f",
|
|
|
|
(*itr)->GetUniqueID(), a_Player->GetName().c_str(), SqrDist
|
|
|
|
);
|
|
|
|
*/
|
|
|
|
static_cast<cPickup &>(Entity).CollectedBy(a_Player);
|
|
|
|
}
|
|
|
|
else if (Entity.IsProjectile())
|
|
|
|
{
|
|
|
|
static_cast<cProjectileEntity &>(Entity).CollectedBy(a_Player);
|
|
|
|
}
|
2012-06-14 09:06:06 -04:00
|
|
|
|
2020-08-28 16:35:38 -04:00
|
|
|
// The entities will MarkDirty when they Destroy themselves
|
|
|
|
return false;
|
|
|
|
});
|
2012-06-14 09:06:06 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2019-10-11 05:02:53 -04:00
|
|
|
BLOCKTYPE cChunkMap::GetBlock(Vector3i a_BlockPos)
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2019-10-11 05:02:53 -04:00
|
|
|
auto chunkPos = cChunkDef::BlockToChunk(a_BlockPos);
|
|
|
|
auto relPos = cChunkDef::AbsoluteToRelative(a_BlockPos, chunkPos);
|
2014-12-24 01:20:17 -05:00
|
|
|
|
2015-06-26 18:24:51 -04:00
|
|
|
// Query the chunk, if loaded:
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
2020-08-28 16:22:44 -04:00
|
|
|
const auto Chunk = FindChunk(chunkPos.m_ChunkX, chunkPos.m_ChunkZ);
|
|
|
|
if ((Chunk != nullptr) && Chunk->IsValid())
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2020-08-28 16:22:44 -04:00
|
|
|
return Chunk->GetBlock(relPos);
|
2012-06-14 09:06:06 -04:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2019-10-11 05:02:53 -04:00
|
|
|
NIBBLETYPE cChunkMap::GetBlockMeta(Vector3i a_BlockPos)
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2019-10-11 05:02:53 -04:00
|
|
|
auto chunkPos = cChunkDef::BlockToChunk(a_BlockPos);
|
|
|
|
auto relPos = cChunkDef::AbsoluteToRelative(a_BlockPos, chunkPos);
|
2014-12-24 01:20:17 -05:00
|
|
|
|
2015-06-26 18:24:51 -04:00
|
|
|
// Query the chunk, if loaded:
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
2020-08-28 16:22:44 -04:00
|
|
|
const auto Chunk = FindChunk(chunkPos.m_ChunkX, chunkPos.m_ChunkZ);
|
|
|
|
if ((Chunk != nullptr) && Chunk->IsValid())
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2020-08-28 16:22:44 -04:00
|
|
|
return Chunk->GetMeta(relPos);
|
2012-06-14 09:06:06 -04:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2019-10-11 05:02:53 -04:00
|
|
|
NIBBLETYPE cChunkMap::GetBlockSkyLight(Vector3i a_BlockPos)
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2019-10-11 05:02:53 -04:00
|
|
|
auto chunkPos = cChunkDef::BlockToChunk(a_BlockPos);
|
|
|
|
auto relPos = cChunkDef::AbsoluteToRelative(a_BlockPos, chunkPos);
|
2012-06-14 09:06:06 -04:00
|
|
|
|
2019-10-11 05:02:53 -04:00
|
|
|
// Query the chunk, if loaded:
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
2020-08-28 16:22:44 -04:00
|
|
|
const auto Chunk = FindChunk(chunkPos.m_ChunkX, chunkPos.m_ChunkZ);
|
|
|
|
if ((Chunk != nullptr) && Chunk->IsValid())
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2020-08-28 16:22:44 -04:00
|
|
|
return Chunk->GetSkyLight(relPos);
|
2012-10-20 07:40:34 -04:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2019-10-11 05:02:53 -04:00
|
|
|
NIBBLETYPE cChunkMap::GetBlockBlockLight(Vector3i a_BlockPos)
|
2012-10-20 07:40:34 -04:00
|
|
|
{
|
2019-10-11 05:02:53 -04:00
|
|
|
auto chunkPos = cChunkDef::BlockToChunk(a_BlockPos);
|
|
|
|
auto relPos = cChunkDef::AbsoluteToRelative(a_BlockPos, chunkPos);
|
2012-10-20 07:40:34 -04:00
|
|
|
|
2019-10-11 05:02:53 -04:00
|
|
|
// Query the chunk, if loaded:
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
2020-08-28 16:22:44 -04:00
|
|
|
const auto Chunk = FindChunk(chunkPos.m_ChunkX, chunkPos.m_ChunkZ);
|
|
|
|
if ((Chunk != nullptr) && Chunk->IsValid())
|
2012-10-20 07:40:34 -04:00
|
|
|
{
|
2020-08-28 16:22:44 -04:00
|
|
|
return Chunk->GetBlockLight(relPos);
|
2012-06-14 09:06:06 -04:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-08-26 16:45:13 -04:00
|
|
|
void cChunkMap::SetBlockMeta(Vector3i a_BlockPos, NIBBLETYPE a_BlockMeta)
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2019-10-11 05:02:53 -04:00
|
|
|
auto chunkPos = cChunkDef::BlockToChunk(a_BlockPos);
|
|
|
|
auto relPos = cChunkDef::AbsoluteToRelative(a_BlockPos, chunkPos);
|
2012-06-14 09:06:06 -04:00
|
|
|
|
2019-10-11 05:02:53 -04:00
|
|
|
// Query the chunk, if loaded:
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
2020-08-28 16:22:44 -04:00
|
|
|
const auto Chunk = FindChunk(chunkPos.m_ChunkX, chunkPos.m_ChunkZ);
|
|
|
|
if ((Chunk != nullptr) && Chunk->IsValid())
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2020-08-28 16:22:44 -04:00
|
|
|
Chunk->SetMeta(relPos, a_BlockMeta);
|
2012-06-14 09:06:06 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2019-10-16 04:06:34 -04:00
|
|
|
void cChunkMap::SetBlock(Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2019-10-11 05:02:53 -04:00
|
|
|
auto chunkPos = cChunkDef::BlockToChunk(a_BlockPos);
|
|
|
|
auto relPos = cChunkDef::AbsoluteToRelative(a_BlockPos, chunkPos);
|
2012-06-14 09:06:06 -04:00
|
|
|
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
2020-08-28 16:22:44 -04:00
|
|
|
const auto Chunk = FindChunk(chunkPos.m_ChunkX, chunkPos.m_ChunkZ);
|
|
|
|
if ((Chunk != nullptr) && Chunk->IsValid())
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2020-08-28 16:22:44 -04:00
|
|
|
Chunk->SetBlock(relPos, a_BlockType, a_BlockMeta);
|
2012-06-14 09:06:06 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2019-10-16 04:06:34 -04:00
|
|
|
bool cChunkMap::GetBlockTypeMeta(Vector3i a_BlockPos, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta)
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2019-10-16 04:06:34 -04:00
|
|
|
auto chunkCoord = cChunkDef::BlockToChunk(a_BlockPos);
|
|
|
|
auto relPos = cChunkDef::AbsoluteToRelative(a_BlockPos, chunkCoord);
|
2012-06-14 09:06:06 -04:00
|
|
|
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
2020-08-28 16:22:44 -04:00
|
|
|
const auto Chunk = FindChunk(chunkCoord.m_ChunkX, chunkCoord.m_ChunkZ);
|
|
|
|
if ((Chunk != nullptr) && Chunk->IsValid())
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2020-08-28 16:22:44 -04:00
|
|
|
Chunk->GetBlockTypeMeta(relPos, a_BlockType, a_BlockMeta);
|
2012-10-26 04:47:30 -04:00
|
|
|
return true;
|
2012-06-14 09:06:06 -04:00
|
|
|
}
|
2012-10-26 04:47:30 -04:00
|
|
|
return false;
|
2012-06-14 09:06:06 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2019-10-11 05:02:53 -04:00
|
|
|
bool cChunkMap::GetBlockInfo(Vector3i a_BlockPos, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_Meta, NIBBLETYPE & a_SkyLight, NIBBLETYPE & a_BlockLight)
|
2012-10-20 07:40:34 -04:00
|
|
|
{
|
2019-10-11 05:02:53 -04:00
|
|
|
auto chunkPos = cChunkDef::BlockToChunk(a_BlockPos);
|
|
|
|
auto relPos = cChunkDef::AbsoluteToRelative(a_BlockPos, chunkPos);
|
2012-10-20 07:40:34 -04:00
|
|
|
|
2019-10-11 05:02:53 -04:00
|
|
|
// Query the chunk, if loaded:
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
2020-08-28 16:22:44 -04:00
|
|
|
const auto Chunk = FindChunk(chunkPos.m_ChunkX, chunkPos.m_ChunkZ);
|
|
|
|
if ((Chunk != nullptr) && Chunk->IsValid())
|
2012-10-20 07:40:34 -04:00
|
|
|
{
|
2020-08-28 16:22:44 -04:00
|
|
|
Chunk->GetBlockInfo(relPos, a_BlockType, a_Meta, a_SkyLight, a_BlockLight);
|
2012-10-26 04:47:30 -04:00
|
|
|
return true;
|
2012-10-20 07:40:34 -04:00
|
|
|
}
|
2012-10-26 04:47:30 -04:00
|
|
|
return false;
|
2012-10-20 07:40:34 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2012-06-14 09:06:06 -04:00
|
|
|
void cChunkMap::ReplaceTreeBlocks(const sSetBlockVector & a_Blocks)
|
|
|
|
{
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
2012-06-14 09:06:06 -04:00
|
|
|
for (sSetBlockVector::const_iterator itr = a_Blocks.begin(); itr != a_Blocks.end(); ++itr)
|
|
|
|
{
|
2020-08-28 16:22:44 -04:00
|
|
|
const auto Chunk = FindChunk(itr->m_ChunkX, itr->m_ChunkZ);
|
|
|
|
if ((Chunk == nullptr) || !Chunk->IsValid())
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
2019-10-16 04:06:34 -04:00
|
|
|
Vector3i relPos(itr->m_RelX, itr->m_RelY, itr->m_RelZ);
|
2020-08-28 16:22:44 -04:00
|
|
|
switch (Chunk->GetBlock(relPos))
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
|
|
|
CASE_TREE_OVERWRITTEN_BLOCKS:
|
|
|
|
{
|
2020-08-28 16:22:44 -04:00
|
|
|
Chunk->SetBlock(relPos, itr->m_BlockType, itr->m_BlockMeta);
|
2012-06-14 09:06:06 -04:00
|
|
|
break;
|
|
|
|
}
|
2012-07-02 15:54:47 -04:00
|
|
|
case E_BLOCK_LEAVES:
|
2014-03-16 09:01:22 -04:00
|
|
|
case E_BLOCK_NEW_LEAVES:
|
2012-07-02 15:54:47 -04:00
|
|
|
{
|
2014-12-24 01:20:17 -05:00
|
|
|
if ((itr->m_BlockType == E_BLOCK_LOG) || (itr->m_BlockType == E_BLOCK_NEW_LOG))
|
2012-07-02 15:54:47 -04:00
|
|
|
{
|
2020-08-28 16:22:44 -04:00
|
|
|
Chunk->SetBlock(relPos, itr->m_BlockType, itr->m_BlockMeta);
|
2012-07-02 15:54:47 -04:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2012-06-14 09:06:06 -04:00
|
|
|
}
|
|
|
|
} // for itr - a_Blocks[]
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
EMCSBiome cChunkMap::GetBiomeAt (int a_BlockX, int a_BlockZ)
|
|
|
|
{
|
|
|
|
int ChunkX, ChunkZ, X = a_BlockX, Y = 0, Z = a_BlockZ;
|
2014-02-18 07:06:18 -05:00
|
|
|
cChunkDef::AbsoluteToRelative(X, Y, Z, ChunkX, ChunkZ);
|
2012-06-14 09:06:06 -04:00
|
|
|
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
2020-08-28 16:22:44 -04:00
|
|
|
const auto Chunk = FindChunk(ChunkX, ChunkZ);
|
2014-10-20 16:55:07 -04:00
|
|
|
if ((Chunk != nullptr) && Chunk->IsValid())
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
|
|
|
return Chunk->GetBiomeAt(X, Z);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return m_World->GetGenerator().GetBiomeAt(a_BlockX, a_BlockZ);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2014-02-18 07:06:18 -05:00
|
|
|
bool cChunkMap::SetBiomeAt(int a_BlockX, int a_BlockZ, EMCSBiome a_Biome)
|
|
|
|
{
|
|
|
|
int ChunkX, ChunkZ, X = a_BlockX, Y = 0, Z = a_BlockZ;
|
|
|
|
cChunkDef::AbsoluteToRelative(X, Y, Z, ChunkX, ChunkZ);
|
|
|
|
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
2020-08-28 16:22:44 -04:00
|
|
|
const auto Chunk = FindChunk(ChunkX, ChunkZ);
|
2014-10-20 16:55:07 -04:00
|
|
|
if ((Chunk != nullptr) && Chunk->IsValid())
|
2014-02-18 07:06:18 -05:00
|
|
|
{
|
|
|
|
Chunk->SetBiomeAt(X, Z, a_Biome);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool cChunkMap::SetAreaBiome(int a_MinX, int a_MaxX, int a_MinZ, int a_MaxZ, EMCSBiome a_Biome)
|
|
|
|
{
|
|
|
|
// Translate coords to relative:
|
|
|
|
int Y = 0;
|
|
|
|
int MinChunkX, MinChunkZ, MinX = a_MinX, MinZ = a_MinZ;
|
|
|
|
int MaxChunkX, MaxChunkZ, MaxX = a_MaxX, MaxZ = a_MaxZ;
|
|
|
|
cChunkDef::AbsoluteToRelative(MinX, Y, MinZ, MinChunkX, MinChunkZ);
|
|
|
|
cChunkDef::AbsoluteToRelative(MaxX, Y, MaxZ, MaxChunkX, MaxChunkZ);
|
2016-02-05 16:45:45 -05:00
|
|
|
|
2014-02-18 07:06:18 -05:00
|
|
|
// Go through all chunks, set:
|
|
|
|
bool res = true;
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
2014-02-18 07:06:18 -05:00
|
|
|
for (int x = MinChunkX; x <= MaxChunkX; x++)
|
|
|
|
{
|
|
|
|
int MinRelX = (x == MinChunkX) ? MinX : 0;
|
|
|
|
int MaxRelX = (x == MaxChunkX) ? MaxX : cChunkDef::Width - 1;
|
|
|
|
for (int z = MinChunkZ; z <= MaxChunkZ; z++)
|
|
|
|
{
|
|
|
|
int MinRelZ = (z == MinChunkZ) ? MinZ : 0;
|
|
|
|
int MaxRelZ = (z == MaxChunkZ) ? MaxZ : cChunkDef::Width - 1;
|
2020-08-28 16:22:44 -04:00
|
|
|
const auto Chunk = FindChunk(x, z);
|
2014-10-20 16:55:07 -04:00
|
|
|
if ((Chunk != nullptr) && Chunk->IsValid())
|
2014-02-18 07:06:18 -05:00
|
|
|
{
|
|
|
|
Chunk->SetAreaBiome(MinRelX, MaxRelX, MinRelZ, MaxRelZ, a_Biome);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
res = false;
|
|
|
|
}
|
|
|
|
} // for z
|
|
|
|
} // for x
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2012-06-14 09:06:06 -04:00
|
|
|
bool cChunkMap::GetBlocks(sSetBlockVector & a_Blocks, bool a_ContinueOnFailure)
|
|
|
|
{
|
|
|
|
bool res = true;
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
2012-06-14 09:06:06 -04:00
|
|
|
for (sSetBlockVector::iterator itr = a_Blocks.begin(); itr != a_Blocks.end(); ++itr)
|
|
|
|
{
|
2020-08-28 16:22:44 -04:00
|
|
|
const auto Chunk = FindChunk(itr->m_ChunkX, itr->m_ChunkZ);
|
2014-10-20 16:55:07 -04:00
|
|
|
if ((Chunk == nullptr) || !Chunk->IsValid())
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
|
|
|
if (!a_ContinueOnFailure)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
res = false;
|
|
|
|
continue;
|
|
|
|
}
|
2014-12-24 01:20:17 -05:00
|
|
|
itr->m_BlockType = Chunk->GetBlock(itr->m_RelX, itr->m_RelY, itr->m_RelZ);
|
|
|
|
itr->m_BlockMeta = Chunk->GetMeta(itr->m_RelX, itr->m_RelY, itr->m_RelZ);
|
2012-06-14 09:06:06 -04:00
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2019-10-16 04:06:34 -04:00
|
|
|
bool cChunkMap::DigBlock(Vector3i a_BlockPos)
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2019-10-16 04:06:34 -04:00
|
|
|
auto chunkCoords = cChunkDef::BlockToChunk(a_BlockPos);
|
|
|
|
auto relPos = cChunkDef::AbsoluteToRelative(a_BlockPos, chunkCoords);
|
2012-06-14 09:06:06 -04:00
|
|
|
|
|
|
|
{
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
2020-08-28 16:22:44 -04:00
|
|
|
const auto Chunk = FindChunk(chunkCoords.m_ChunkX, chunkCoords.m_ChunkZ);
|
|
|
|
if ((Chunk == nullptr) || !Chunk->IsValid())
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
2016-02-05 16:45:45 -05:00
|
|
|
|
2020-08-28 16:22:44 -04:00
|
|
|
Chunk->SetBlock(relPos, E_BLOCK_AIR, 0);
|
2012-06-14 09:06:06 -04:00
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2019-10-16 04:06:34 -04:00
|
|
|
cItems cChunkMap::PickupsFromBlock(Vector3i a_BlockPos, const cEntity * a_Digger, const cItem * a_Tool)
|
|
|
|
{
|
|
|
|
auto chunkCoords = cChunkDef::BlockToChunk(a_BlockPos);
|
|
|
|
auto relPos = cChunkDef::AbsoluteToRelative(a_BlockPos, chunkCoords);
|
|
|
|
|
|
|
|
cCSLock Lock(m_CSChunks);
|
2020-08-28 16:22:44 -04:00
|
|
|
const auto Chunk = FindChunk(chunkCoords.m_ChunkX, chunkCoords.m_ChunkZ);
|
|
|
|
if ((Chunk == nullptr) || !Chunk->IsValid())
|
2019-10-16 04:06:34 -04:00
|
|
|
{
|
|
|
|
return {};
|
|
|
|
}
|
2020-08-28 16:22:44 -04:00
|
|
|
return Chunk->PickupsFromBlock(relPos, a_Digger, a_Tool);
|
2019-10-16 04:06:34 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2017-07-31 15:50:40 -04:00
|
|
|
void cChunkMap::SendBlockTo(int a_X, int a_Y, int a_Z, cPlayer & a_Player)
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
|
|
|
int ChunkX, ChunkZ;
|
|
|
|
cChunkDef::AbsoluteToRelative(a_X, a_Y, a_Z, ChunkX, ChunkZ);
|
2016-02-05 16:45:45 -05:00
|
|
|
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
2020-08-28 16:22:44 -04:00
|
|
|
const auto Chunk = FindChunk(ChunkX, ChunkZ);
|
2014-10-20 16:55:07 -04:00
|
|
|
if ((Chunk != nullptr) && (Chunk->IsValid()))
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2017-07-31 15:50:40 -04:00
|
|
|
Chunk->SendBlockTo(a_X, a_Y, a_Z, a_Player.GetClientHandle());
|
2012-06-14 09:06:06 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2013-04-13 17:02:10 -04:00
|
|
|
void cChunkMap::CompareChunkClients(int a_ChunkX1, int a_ChunkZ1, int a_ChunkX2, int a_ChunkZ2, cClientDiffCallback & a_Callback)
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
2020-08-28 16:22:44 -04:00
|
|
|
const auto Chunk1 = FindChunk(a_ChunkX1, a_ChunkZ1);
|
2014-10-20 16:55:07 -04:00
|
|
|
if (Chunk1 == nullptr)
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2020-08-28 16:22:44 -04:00
|
|
|
const auto Chunk2 = FindChunk(a_ChunkX2, a_ChunkZ2);
|
2014-10-20 16:55:07 -04:00
|
|
|
if (Chunk2 == nullptr)
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2016-02-05 16:45:45 -05:00
|
|
|
|
2013-04-13 17:02:10 -04:00
|
|
|
CompareChunkClients(Chunk1, Chunk2, a_Callback);
|
|
|
|
}
|
2012-06-14 09:06:06 -04:00
|
|
|
|
2013-04-13 17:02:10 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void cChunkMap::CompareChunkClients(cChunk * a_Chunk1, cChunk * a_Chunk2, cClientDiffCallback & a_Callback)
|
|
|
|
{
|
2018-07-24 17:30:49 -04:00
|
|
|
auto Clients1 = a_Chunk1->GetAllClients();
|
|
|
|
auto Clients2 = a_Chunk2->GetAllClients();
|
2016-02-05 16:45:45 -05:00
|
|
|
|
2012-06-14 09:06:06 -04:00
|
|
|
// Find "removed" clients:
|
2018-07-24 17:30:49 -04:00
|
|
|
for (auto * Client : Clients1)
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2018-07-24 17:30:49 -04:00
|
|
|
bool Found = (std::find(Clients2.begin(), Clients2.end(), Client) != Clients2.end());
|
2012-06-14 09:06:06 -04:00
|
|
|
if (!Found)
|
|
|
|
{
|
2018-07-24 17:30:49 -04:00
|
|
|
a_Callback.Removed(Client);
|
2012-06-14 09:06:06 -04:00
|
|
|
}
|
2018-07-24 17:30:49 -04:00
|
|
|
} // for Client - Clients1[]
|
2016-02-05 16:45:45 -05:00
|
|
|
|
2012-06-14 09:06:06 -04:00
|
|
|
// Find "added" clients:
|
2018-07-24 17:30:49 -04:00
|
|
|
for (auto * Client : Clients2)
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2018-07-24 17:30:49 -04:00
|
|
|
bool Found = (std::find(Clients1.begin(), Clients1.end(), Client) != Clients1.end());
|
2012-06-14 09:06:06 -04:00
|
|
|
if (!Found)
|
|
|
|
{
|
2018-07-24 17:30:49 -04:00
|
|
|
a_Callback.Added(Client);
|
2012-06-14 09:06:06 -04:00
|
|
|
}
|
2018-07-24 17:30:49 -04:00
|
|
|
} // for Client - Clients2[]
|
2012-06-14 09:06:06 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2013-04-13 17:02:10 -04:00
|
|
|
bool cChunkMap::AddChunkClient(int a_ChunkX, int a_ChunkZ, cClientHandle * a_Client)
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
2020-08-28 16:22:44 -04:00
|
|
|
return GetChunk(a_ChunkX, a_ChunkZ).AddClient(a_Client);
|
2012-06-14 09:06:06 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2013-04-13 17:02:10 -04:00
|
|
|
void cChunkMap::RemoveChunkClient(int a_ChunkX, int a_ChunkZ, cClientHandle * a_Client)
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
2020-08-28 16:22:44 -04:00
|
|
|
const auto Chunk = FindChunk(a_ChunkX, a_ChunkZ);
|
|
|
|
ASSERT(Chunk != nullptr);
|
2012-06-14 09:06:06 -04:00
|
|
|
Chunk->RemoveClient(a_Client);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void cChunkMap::RemoveClientFromChunks(cClientHandle * a_Client)
|
|
|
|
{
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
2020-08-20 07:50:22 -04:00
|
|
|
for (auto & Chunk : m_Chunks)
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2020-08-20 07:50:22 -04:00
|
|
|
Chunk.second.RemoveClient(a_Client);
|
2016-08-02 18:56:53 -04:00
|
|
|
}
|
2012-06-14 09:06:06 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2016-12-19 15:12:23 -05:00
|
|
|
void cChunkMap::AddEntity(OwnedEntity a_Entity)
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
2020-08-28 16:22:44 -04:00
|
|
|
const auto Chunk = FindChunk(a_Entity->GetChunkX(), a_Entity->GetChunkZ());
|
|
|
|
if (Chunk == nullptr)
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2013-06-25 02:48:17 -04:00
|
|
|
LOGWARNING("Entity at %p (%s, ID %d) spawning in a non-existent chunk, the entity is lost.",
|
2016-12-19 15:12:23 -05:00
|
|
|
static_cast<void *>(a_Entity.get()), a_Entity->GetClass(), a_Entity->GetUniqueID()
|
2013-06-25 02:48:17 -04:00
|
|
|
);
|
2013-04-13 17:28:55 -04:00
|
|
|
return;
|
2012-06-14 09:06:06 -04:00
|
|
|
}
|
2020-08-29 16:34:21 -04:00
|
|
|
|
|
|
|
const auto EntityPtr = a_Entity.get();
|
|
|
|
ASSERT(EntityPtr->GetWorld() == m_World);
|
|
|
|
|
2016-12-19 15:12:23 -05:00
|
|
|
Chunk->AddEntity(std::move(a_Entity));
|
2020-08-29 16:34:21 -04:00
|
|
|
|
|
|
|
EntityPtr->OnAddToWorld(*m_World);
|
|
|
|
ASSERT(!EntityPtr->IsTicking());
|
|
|
|
EntityPtr->SetIsTicking(true);
|
|
|
|
|
|
|
|
cPluginManager::Get()->CallHookSpawnedEntity(*m_World, *EntityPtr);
|
2012-06-14 09:06:06 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-09-03 17:25:35 -04:00
|
|
|
void cChunkMap::AddPlayer(std::unique_ptr<cPlayer> a_Player)
|
2014-06-10 12:25:53 -04:00
|
|
|
{
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
2020-09-03 17:25:35 -04:00
|
|
|
auto & Chunk = ConstructChunk(a_Player->GetChunkX(), a_Player->GetChunkZ()); // Always construct the chunk for players
|
|
|
|
ASSERT(!Chunk.HasEntity(a_Player->GetUniqueID()));
|
|
|
|
Chunk.AddEntity(std::move(a_Player));
|
2014-06-10 12:25:53 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-08-20 07:50:22 -04:00
|
|
|
bool cChunkMap::HasEntity(UInt32 a_UniqueID) const
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
|
|
|
for (const auto & Chunk : m_Chunks)
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2020-08-20 07:50:22 -04:00
|
|
|
if (Chunk.second.IsValid() && Chunk.second.HasEntity(a_UniqueID))
|
2013-04-13 17:28:55 -04:00
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
2012-06-14 09:06:06 -04:00
|
|
|
}
|
2013-04-13 17:28:55 -04:00
|
|
|
return false;
|
2012-06-14 09:06:06 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2016-12-19 15:12:23 -05:00
|
|
|
OwnedEntity cChunkMap::RemoveEntity(cEntity & a_Entity)
|
2013-04-13 17:02:10 -04:00
|
|
|
{
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
2020-08-28 16:22:44 -04:00
|
|
|
const auto Chunk = a_Entity.GetParentChunk();
|
2014-07-17 08:54:28 -04:00
|
|
|
|
2014-10-20 16:55:07 -04:00
|
|
|
if (Chunk == nullptr)
|
2013-04-13 17:02:10 -04:00
|
|
|
{
|
2016-12-19 15:12:23 -05:00
|
|
|
return nullptr;
|
2013-04-13 17:02:10 -04:00
|
|
|
}
|
2016-12-19 15:12:23 -05:00
|
|
|
|
|
|
|
// Remove the entity no matter whether the chunk itself is valid or not (#1190)
|
|
|
|
return Chunk->RemoveEntity(a_Entity);
|
2013-04-13 17:02:10 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-08-20 07:50:22 -04:00
|
|
|
bool cChunkMap::ForEachEntity(cEntityCallback a_Callback) const
|
2013-04-13 17:02:10 -04:00
|
|
|
{
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
|
|
|
for (const auto & Chunk : m_Chunks)
|
2013-04-13 17:02:10 -04:00
|
|
|
{
|
2020-08-20 07:50:22 -04:00
|
|
|
if (Chunk.second.IsValid() && !Chunk.second.ForEachEntity(a_Callback))
|
2013-04-13 17:02:10 -04:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2017-09-11 17:20:49 -04:00
|
|
|
bool cChunkMap::ForEachEntityInChunk(int a_ChunkX, int a_ChunkZ, cEntityCallback a_Callback)
|
2012-06-16 04:35:07 -04:00
|
|
|
{
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
2020-08-28 16:22:44 -04:00
|
|
|
const auto Chunk = FindChunk(a_ChunkX, a_ChunkZ);
|
2014-10-20 16:55:07 -04:00
|
|
|
if ((Chunk == nullptr) || !Chunk->IsValid())
|
2012-06-16 04:35:07 -04:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return Chunk->ForEachEntity(a_Callback);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2017-09-11 17:20:49 -04:00
|
|
|
bool cChunkMap::ForEachEntityInBox(const cBoundingBox & a_Box, cEntityCallback a_Callback)
|
2014-09-03 11:00:26 -04:00
|
|
|
{
|
|
|
|
// Calculate the chunk range for the box:
|
2015-07-29 11:04:03 -04:00
|
|
|
int MinChunkX = FloorC(a_Box.GetMinX() / cChunkDef::Width);
|
|
|
|
int MinChunkZ = FloorC(a_Box.GetMinZ() / cChunkDef::Width);
|
|
|
|
int MaxChunkX = FloorC((a_Box.GetMaxX() + cChunkDef::Width) / cChunkDef::Width);
|
|
|
|
int MaxChunkZ = FloorC((a_Box.GetMaxZ() + cChunkDef::Width) / cChunkDef::Width);
|
2016-02-05 16:45:45 -05:00
|
|
|
|
2014-09-03 11:00:26 -04:00
|
|
|
// Iterate over each chunk in the range:
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
2014-09-03 11:00:26 -04:00
|
|
|
for (int z = MinChunkZ; z <= MaxChunkZ; z++)
|
|
|
|
{
|
|
|
|
for (int x = MinChunkX; x <= MaxChunkX; x++)
|
|
|
|
{
|
2020-08-28 16:22:44 -04:00
|
|
|
const auto Chunk = FindChunk(x, z);
|
2014-10-20 16:55:07 -04:00
|
|
|
if ((Chunk == nullptr) || !Chunk->IsValid())
|
2014-09-03 11:00:26 -04:00
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (!Chunk->ForEachEntityInBox(a_Box, a_Callback))
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
} // for x
|
|
|
|
} // for z
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-08-20 07:50:22 -04:00
|
|
|
bool cChunkMap::DoWithEntityByID(UInt32 a_UniqueID, cEntityCallback a_Callback) const
|
2013-04-13 17:02:10 -04:00
|
|
|
{
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
2013-04-13 17:02:10 -04:00
|
|
|
bool res = false;
|
2016-08-02 18:56:53 -04:00
|
|
|
for (const auto & Chunk : m_Chunks)
|
2013-04-13 17:02:10 -04:00
|
|
|
{
|
2020-08-20 07:50:22 -04:00
|
|
|
if (Chunk.second.IsValid() && Chunk.second.DoWithEntityByID(a_UniqueID, a_Callback, res))
|
2013-04-13 17:02:10 -04:00
|
|
|
{
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2017-09-11 17:20:49 -04:00
|
|
|
bool cChunkMap::ForEachBlockEntityInChunk(int a_ChunkX, int a_ChunkZ, cBlockEntityCallback a_Callback)
|
2013-11-20 15:53:29 -05:00
|
|
|
{
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
2020-08-28 16:22:44 -04:00
|
|
|
const auto Chunk = FindChunk(a_ChunkX, a_ChunkZ);
|
2014-10-20 16:55:07 -04:00
|
|
|
if ((Chunk == nullptr) || !Chunk->IsValid())
|
2013-11-20 15:53:29 -05:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return Chunk->ForEachBlockEntity(a_Callback);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2017-09-11 17:20:49 -04:00
|
|
|
bool cChunkMap::ForEachBrewingstandInChunk(int a_ChunkX, int a_ChunkZ, cBrewingstandCallback a_Callback)
|
2015-09-24 04:48:33 -04:00
|
|
|
{
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
2020-08-28 16:22:44 -04:00
|
|
|
const auto Chunk = FindChunk(a_ChunkX, a_ChunkZ);
|
2015-09-24 04:48:33 -04:00
|
|
|
if ((Chunk == nullptr) || !Chunk->IsValid())
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return Chunk->ForEachBrewingstand(a_Callback);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2017-09-11 17:20:49 -04:00
|
|
|
bool cChunkMap::ForEachChestInChunk(int a_ChunkX, int a_ChunkZ, cChestCallback a_Callback)
|
2012-06-17 15:58:39 -04:00
|
|
|
{
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
2020-08-28 16:22:44 -04:00
|
|
|
const auto Chunk = FindChunk(a_ChunkX, a_ChunkZ);
|
2014-10-20 16:55:07 -04:00
|
|
|
if ((Chunk == nullptr) || !Chunk->IsValid())
|
2012-06-17 15:58:39 -04:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return Chunk->ForEachChest(a_Callback);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2017-09-11 17:20:49 -04:00
|
|
|
bool cChunkMap::ForEachDispenserInChunk(int a_ChunkX, int a_ChunkZ, cDispenserCallback a_Callback)
|
2012-12-26 12:16:33 -05:00
|
|
|
{
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
2020-08-28 16:22:44 -04:00
|
|
|
const auto Chunk = FindChunk(a_ChunkX, a_ChunkZ);
|
2014-10-20 16:55:07 -04:00
|
|
|
if ((Chunk == nullptr) || !Chunk->IsValid())
|
2012-12-26 12:16:33 -05:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return Chunk->ForEachDispenser(a_Callback);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2017-09-11 17:20:49 -04:00
|
|
|
bool cChunkMap::ForEachDropperInChunk(int a_ChunkX, int a_ChunkZ, cDropperCallback a_Callback)
|
2013-05-26 10:39:04 -04:00
|
|
|
{
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
2020-08-28 16:22:44 -04:00
|
|
|
const auto Chunk = FindChunk(a_ChunkX, a_ChunkZ);
|
2014-10-20 16:55:07 -04:00
|
|
|
if ((Chunk == nullptr) || !Chunk->IsValid())
|
2013-05-26 10:39:04 -04:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return Chunk->ForEachDropper(a_Callback);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2017-09-11 17:20:49 -04:00
|
|
|
bool cChunkMap::ForEachDropSpenserInChunk(int a_ChunkX, int a_ChunkZ, cDropSpenserCallback a_Callback)
|
2013-05-26 10:39:04 -04:00
|
|
|
{
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
2020-08-28 16:22:44 -04:00
|
|
|
const auto Chunk = FindChunk(a_ChunkX, a_ChunkZ);
|
2014-10-20 16:55:07 -04:00
|
|
|
if ((Chunk == nullptr) || !Chunk->IsValid())
|
2013-05-26 10:39:04 -04:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return Chunk->ForEachDropSpenser(a_Callback);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2017-09-11 17:20:49 -04:00
|
|
|
bool cChunkMap::ForEachFurnaceInChunk(int a_ChunkX, int a_ChunkZ, cFurnaceCallback a_Callback)
|
2012-06-17 15:58:39 -04:00
|
|
|
{
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
2020-08-28 16:22:44 -04:00
|
|
|
const auto Chunk = FindChunk(a_ChunkX, a_ChunkZ);
|
2014-10-20 16:55:07 -04:00
|
|
|
if ((Chunk == nullptr) || !Chunk->IsValid())
|
2012-06-17 15:58:39 -04:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return Chunk->ForEachFurnace(a_Callback);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2017-09-11 17:20:49 -04:00
|
|
|
bool cChunkMap::DoWithBlockEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBlockEntityCallback a_Callback)
|
2013-11-20 15:53:29 -05:00
|
|
|
{
|
|
|
|
int ChunkX, ChunkZ;
|
|
|
|
int BlockX = a_BlockX, BlockY = a_BlockY, BlockZ = a_BlockZ;
|
|
|
|
cChunkDef::AbsoluteToRelative(BlockX, BlockY, BlockZ, ChunkX, ChunkZ);
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
2020-08-28 16:22:44 -04:00
|
|
|
const auto Chunk = FindChunk(ChunkX, ChunkZ);
|
2014-10-20 16:55:07 -04:00
|
|
|
if ((Chunk == nullptr) || !Chunk->IsValid())
|
2013-11-20 15:53:29 -05:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
2020-07-25 15:31:48 -04:00
|
|
|
return Chunk->DoWithBlockEntityAt({ BlockX, BlockY, BlockZ }, a_Callback);
|
2013-11-20 15:53:29 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2017-09-11 17:20:49 -04:00
|
|
|
bool cChunkMap::DoWithBeaconAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBeaconCallback a_Callback)
|
2014-07-30 16:19:51 -04:00
|
|
|
{
|
|
|
|
int ChunkX, ChunkZ;
|
|
|
|
int BlockX = a_BlockX, BlockY = a_BlockY, BlockZ = a_BlockZ;
|
|
|
|
cChunkDef::AbsoluteToRelative(BlockX, BlockY, BlockZ, ChunkX, ChunkZ);
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
2020-08-28 16:22:44 -04:00
|
|
|
const auto Chunk = FindChunk(ChunkX, ChunkZ);
|
2014-10-20 16:55:07 -04:00
|
|
|
if ((Chunk == nullptr) || !Chunk->IsValid())
|
2014-07-30 16:19:51 -04:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
2020-07-25 15:31:48 -04:00
|
|
|
return Chunk->DoWithBeaconAt({ BlockX, BlockY, BlockZ }, a_Callback);
|
2014-07-30 16:19:51 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2017-09-11 17:20:49 -04:00
|
|
|
bool cChunkMap::DoWithBedAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBedCallback a_Callback)
|
2017-07-07 03:31:45 -04:00
|
|
|
{
|
|
|
|
int ChunkX, ChunkZ;
|
|
|
|
int BlockX = a_BlockX, BlockY = a_BlockY, BlockZ = a_BlockZ;
|
|
|
|
cChunkDef::AbsoluteToRelative(BlockX, BlockY, BlockZ, ChunkX, ChunkZ);
|
|
|
|
cCSLock Lock(m_CSChunks);
|
2020-08-28 16:22:44 -04:00
|
|
|
const auto Chunk = FindChunk(ChunkX, ChunkZ);
|
2017-07-07 03:31:45 -04:00
|
|
|
if ((Chunk == nullptr) || !Chunk->IsValid())
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
2020-07-25 15:31:48 -04:00
|
|
|
return Chunk->DoWithBedAt({ BlockX, BlockY, BlockZ }, a_Callback);
|
2017-07-07 03:31:45 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2017-09-11 17:20:49 -04:00
|
|
|
bool cChunkMap::DoWithBrewingstandAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBrewingstandCallback a_Callback)
|
2015-09-24 04:48:33 -04:00
|
|
|
{
|
|
|
|
int ChunkX, ChunkZ;
|
|
|
|
int BlockX = a_BlockX, BlockY = a_BlockY, BlockZ = a_BlockZ;
|
|
|
|
cChunkDef::AbsoluteToRelative(BlockX, BlockY, BlockZ, ChunkX, ChunkZ);
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
2020-08-28 16:22:44 -04:00
|
|
|
const auto Chunk = FindChunk(ChunkX, ChunkZ);
|
2015-09-24 04:48:33 -04:00
|
|
|
if ((Chunk == nullptr) || !Chunk->IsValid())
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
2020-07-25 15:31:48 -04:00
|
|
|
return Chunk->DoWithBrewingstandAt({ BlockX, BlockY, BlockZ }, a_Callback);
|
2015-09-24 04:48:33 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2017-09-11 17:20:49 -04:00
|
|
|
bool cChunkMap::DoWithChestAt(int a_BlockX, int a_BlockY, int a_BlockZ, cChestCallback a_Callback)
|
2012-06-17 15:58:39 -04:00
|
|
|
{
|
|
|
|
int ChunkX, ChunkZ;
|
|
|
|
int BlockX = a_BlockX, BlockY = a_BlockY, BlockZ = a_BlockZ;
|
|
|
|
cChunkDef::AbsoluteToRelative(BlockX, BlockY, BlockZ, ChunkX, ChunkZ);
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
2020-08-28 16:22:44 -04:00
|
|
|
const auto Chunk = FindChunk(ChunkX, ChunkZ);
|
2014-10-20 16:55:07 -04:00
|
|
|
if ((Chunk == nullptr) || !Chunk->IsValid())
|
2012-06-17 15:58:39 -04:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
2020-07-25 15:31:48 -04:00
|
|
|
return Chunk->DoWithChestAt({ BlockX, BlockY, BlockZ }, a_Callback);
|
2012-06-17 15:58:39 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2017-09-11 17:20:49 -04:00
|
|
|
bool cChunkMap::DoWithDispenserAt(int a_BlockX, int a_BlockY, int a_BlockZ, cDispenserCallback a_Callback)
|
2012-12-26 12:16:33 -05:00
|
|
|
{
|
|
|
|
int ChunkX, ChunkZ;
|
|
|
|
int BlockX = a_BlockX, BlockY = a_BlockY, BlockZ = a_BlockZ;
|
|
|
|
cChunkDef::AbsoluteToRelative(BlockX, BlockY, BlockZ, ChunkX, ChunkZ);
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
2020-08-28 16:22:44 -04:00
|
|
|
const auto Chunk = FindChunk(ChunkX, ChunkZ);
|
2014-10-20 16:55:07 -04:00
|
|
|
if ((Chunk == nullptr) || !Chunk->IsValid())
|
2012-12-26 12:16:33 -05:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
2020-07-25 15:31:48 -04:00
|
|
|
return Chunk->DoWithDispenserAt({ BlockX, BlockY, BlockZ }, a_Callback);
|
2012-12-26 12:16:33 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2017-09-11 17:20:49 -04:00
|
|
|
bool cChunkMap::DoWithDropperAt(int a_BlockX, int a_BlockY, int a_BlockZ, cDropperCallback a_Callback)
|
2013-05-26 10:39:04 -04:00
|
|
|
{
|
|
|
|
int ChunkX, ChunkZ;
|
|
|
|
int BlockX = a_BlockX, BlockY = a_BlockY, BlockZ = a_BlockZ;
|
|
|
|
cChunkDef::AbsoluteToRelative(BlockX, BlockY, BlockZ, ChunkX, ChunkZ);
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
2020-08-28 16:22:44 -04:00
|
|
|
const auto Chunk = FindChunk(ChunkX, ChunkZ);
|
2014-10-20 16:55:07 -04:00
|
|
|
if ((Chunk == nullptr) || !Chunk->IsValid())
|
2013-05-26 10:39:04 -04:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
2020-07-25 15:31:48 -04:00
|
|
|
return Chunk->DoWithDropperAt({ BlockX, BlockY, BlockZ }, a_Callback);
|
2013-05-26 10:39:04 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2017-09-11 17:20:49 -04:00
|
|
|
bool cChunkMap::DoWithDropSpenserAt(int a_BlockX, int a_BlockY, int a_BlockZ, cDropSpenserCallback a_Callback)
|
2013-05-26 10:39:04 -04:00
|
|
|
{
|
|
|
|
int ChunkX, ChunkZ;
|
|
|
|
int BlockX = a_BlockX, BlockY = a_BlockY, BlockZ = a_BlockZ;
|
|
|
|
cChunkDef::AbsoluteToRelative(BlockX, BlockY, BlockZ, ChunkX, ChunkZ);
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
2020-08-28 16:22:44 -04:00
|
|
|
const auto Chunk = FindChunk(ChunkX, ChunkZ);
|
2014-10-20 16:55:07 -04:00
|
|
|
if ((Chunk == nullptr) || !Chunk->IsValid())
|
2013-05-26 10:39:04 -04:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
2020-07-25 15:31:48 -04:00
|
|
|
return Chunk->DoWithDropSpenserAt({ BlockX, BlockY, BlockZ }, a_Callback);
|
2013-05-26 10:39:04 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2017-09-11 17:20:49 -04:00
|
|
|
bool cChunkMap::DoWithFurnaceAt(int a_BlockX, int a_BlockY, int a_BlockZ, cFurnaceCallback a_Callback)
|
2012-06-17 15:58:39 -04:00
|
|
|
{
|
|
|
|
int ChunkX, ChunkZ;
|
|
|
|
int BlockX = a_BlockX, BlockY = a_BlockY, BlockZ = a_BlockZ;
|
|
|
|
cChunkDef::AbsoluteToRelative(BlockX, BlockY, BlockZ, ChunkX, ChunkZ);
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
2020-08-28 16:22:44 -04:00
|
|
|
const auto Chunk = FindChunk(ChunkX, ChunkZ);
|
2014-10-20 16:55:07 -04:00
|
|
|
if ((Chunk == nullptr) || !Chunk->IsValid())
|
2012-06-17 15:58:39 -04:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
2020-07-25 15:31:48 -04:00
|
|
|
return Chunk->DoWithFurnaceAt({ BlockX, BlockY, BlockZ }, a_Callback);
|
2012-06-17 15:58:39 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2018-07-26 17:24:36 -04:00
|
|
|
|
2020-03-27 08:03:28 -04:00
|
|
|
bool cChunkMap::DoWithHopperAt(int a_BlockX, int a_BlockY, int a_BlockZ, cHopperCallback a_Callback)
|
|
|
|
{
|
|
|
|
int ChunkX, ChunkZ;
|
|
|
|
int BlockX = a_BlockX, BlockY = a_BlockY, BlockZ = a_BlockZ;
|
|
|
|
cChunkDef::AbsoluteToRelative(BlockX, BlockY, BlockZ, ChunkX, ChunkZ);
|
|
|
|
cCSLock Lock(m_CSChunks);
|
2020-08-28 16:22:44 -04:00
|
|
|
const auto Chunk = FindChunk(ChunkX, ChunkZ);
|
2020-03-27 08:03:28 -04:00
|
|
|
if ((Chunk == nullptr) || !Chunk->IsValid())
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
2020-07-25 15:31:48 -04:00
|
|
|
return Chunk->DoWithHopperAt({ BlockX, BlockY, BlockZ }, a_Callback);
|
2020-03-27 08:03:28 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2017-09-11 17:20:49 -04:00
|
|
|
bool cChunkMap::DoWithNoteBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cNoteBlockCallback a_Callback)
|
2013-12-14 11:52:22 -05:00
|
|
|
{
|
|
|
|
int ChunkX, ChunkZ;
|
|
|
|
int BlockX = a_BlockX, BlockY = a_BlockY, BlockZ = a_BlockZ;
|
|
|
|
cChunkDef::AbsoluteToRelative(BlockX, BlockY, BlockZ, ChunkX, ChunkZ);
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
2020-08-28 16:22:44 -04:00
|
|
|
const auto Chunk = FindChunk(ChunkX, ChunkZ);
|
2014-10-20 16:55:07 -04:00
|
|
|
if ((Chunk == nullptr) || !Chunk->IsValid())
|
2013-12-14 11:52:22 -05:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
2020-07-25 15:31:48 -04:00
|
|
|
return Chunk->DoWithNoteBlockAt({ BlockX, BlockY, BlockZ }, a_Callback);
|
2013-12-14 11:52:22 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2018-07-26 17:24:36 -04:00
|
|
|
|
2017-09-11 17:20:49 -04:00
|
|
|
bool cChunkMap::DoWithCommandBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cCommandBlockCallback a_Callback)
|
2014-01-18 08:16:47 -05:00
|
|
|
{
|
|
|
|
int ChunkX, ChunkZ;
|
|
|
|
int BlockX = a_BlockX, BlockY = a_BlockY, BlockZ = a_BlockZ;
|
|
|
|
cChunkDef::AbsoluteToRelative(BlockX, BlockY, BlockZ, ChunkX, ChunkZ);
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
2020-08-28 16:22:44 -04:00
|
|
|
const auto Chunk = FindChunk(ChunkX, ChunkZ);
|
2014-10-20 16:55:07 -04:00
|
|
|
if ((Chunk == nullptr) || !Chunk->IsValid())
|
2014-01-18 08:16:47 -05:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
2020-07-25 15:31:48 -04:00
|
|
|
return Chunk->DoWithCommandBlockAt({ BlockX, BlockY, BlockZ }, a_Callback);
|
2014-01-18 08:16:47 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2012-06-17 15:58:39 -04:00
|
|
|
|
2017-09-11 17:20:49 -04:00
|
|
|
bool cChunkMap::DoWithMobHeadAt(int a_BlockX, int a_BlockY, int a_BlockZ, cMobHeadCallback a_Callback)
|
2014-02-18 15:40:02 -05:00
|
|
|
{
|
|
|
|
int ChunkX, ChunkZ;
|
|
|
|
int BlockX = a_BlockX, BlockY = a_BlockY, BlockZ = a_BlockZ;
|
|
|
|
cChunkDef::AbsoluteToRelative(BlockX, BlockY, BlockZ, ChunkX, ChunkZ);
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
2020-08-28 16:22:44 -04:00
|
|
|
const auto Chunk = FindChunk(ChunkX, ChunkZ);
|
2014-10-20 16:55:07 -04:00
|
|
|
if ((Chunk == nullptr) || !Chunk->IsValid())
|
2014-02-18 15:40:02 -05:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
2020-07-25 15:31:48 -04:00
|
|
|
return Chunk->DoWithMobHeadAt({ BlockX, BlockY, BlockZ }, a_Callback);
|
2014-02-18 15:40:02 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2017-09-11 17:20:49 -04:00
|
|
|
bool cChunkMap::DoWithFlowerPotAt(int a_BlockX, int a_BlockY, int a_BlockZ, cFlowerPotCallback a_Callback)
|
2014-03-06 19:30:34 -05:00
|
|
|
{
|
|
|
|
int ChunkX, ChunkZ;
|
|
|
|
int BlockX = a_BlockX, BlockY = a_BlockY, BlockZ = a_BlockZ;
|
|
|
|
cChunkDef::AbsoluteToRelative(BlockX, BlockY, BlockZ, ChunkX, ChunkZ);
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
2020-08-28 16:22:44 -04:00
|
|
|
const auto Chunk = FindChunk(ChunkX, ChunkZ);
|
2014-10-20 16:55:07 -04:00
|
|
|
if ((Chunk == nullptr) || !Chunk->IsValid())
|
2014-03-06 19:30:34 -05:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
2020-07-25 15:31:48 -04:00
|
|
|
return Chunk->DoWithFlowerPotAt({ BlockX, BlockY, BlockZ }, a_Callback);
|
2014-02-18 15:40:02 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2012-06-17 15:58:39 -04:00
|
|
|
bool cChunkMap::GetSignLines(int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4)
|
|
|
|
{
|
|
|
|
int ChunkX, ChunkZ;
|
|
|
|
int BlockX = a_BlockX, BlockY = a_BlockY, BlockZ = a_BlockZ;
|
|
|
|
cChunkDef::AbsoluteToRelative(BlockX, BlockY, BlockZ, ChunkX, ChunkZ);
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
2020-08-28 16:22:44 -04:00
|
|
|
const auto Chunk = FindChunk(ChunkX, ChunkZ);
|
2014-10-20 16:55:07 -04:00
|
|
|
if ((Chunk == nullptr) || !Chunk->IsValid())
|
2012-06-17 15:58:39 -04:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
2020-07-25 15:31:48 -04:00
|
|
|
return Chunk->GetSignLines({ BlockX, BlockY, BlockZ }, a_Line1, a_Line2, a_Line3, a_Line4);
|
2012-06-17 15:58:39 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2015-05-30 06:11:17 -04:00
|
|
|
void cChunkMap::PrepareChunk(int a_ChunkX, int a_ChunkZ, std::unique_ptr<cChunkCoordCallback> a_Callback)
|
2014-12-10 16:35:16 -05:00
|
|
|
{
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
2020-08-28 16:22:44 -04:00
|
|
|
const auto Chunk = FindChunk(a_ChunkX, a_ChunkZ);
|
2014-12-10 16:35:16 -05:00
|
|
|
|
|
|
|
// If the chunk is not prepared, queue it in the lighting thread, that will do all the needed processing:
|
|
|
|
if ((Chunk == nullptr) || !Chunk->IsValid() || !Chunk->IsLightValid())
|
|
|
|
{
|
2015-05-30 06:11:17 -04:00
|
|
|
m_World->GetLightingThread().QueueChunk(a_ChunkX, a_ChunkZ, std::move(a_Callback));
|
2014-12-10 16:35:16 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-10-04 08:06:37 -04:00
|
|
|
// The chunk is present and lit, just call the callback, report as success:
|
2014-12-10 16:35:16 -05:00
|
|
|
if (a_Callback != nullptr)
|
|
|
|
{
|
2019-09-01 03:30:00 -04:00
|
|
|
a_Callback->Call({a_ChunkX, a_ChunkZ}, true);
|
2014-12-10 16:35:16 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-08-28 16:26:04 -04:00
|
|
|
void cChunkMap::GenerateChunk(int a_ChunkX, int a_ChunkZ)
|
2014-12-10 16:35:16 -05:00
|
|
|
{
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
2020-08-28 16:26:04 -04:00
|
|
|
GetChunk(a_ChunkX, a_ChunkZ); // Touches the chunk, loading or generating it
|
2014-12-10 16:35:16 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2014-08-28 05:36:35 -04:00
|
|
|
void cChunkMap::ChunkLoadFailed(int a_ChunkX, int a_ChunkZ)
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
2020-08-28 16:22:44 -04:00
|
|
|
const auto Chunk = FindChunk(a_ChunkX, a_ChunkZ);
|
|
|
|
ASSERT(Chunk != nullptr); // Chunk cannot have unloaded since it is marked as queued
|
2012-06-14 09:06:06 -04:00
|
|
|
Chunk->MarkLoadFailed();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2013-06-12 03:14:06 -04:00
|
|
|
bool cChunkMap::SetSignLines(int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4)
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
2012-06-14 09:06:06 -04:00
|
|
|
int ChunkX, ChunkZ;
|
2013-08-03 14:05:07 -04:00
|
|
|
cChunkDef::BlockToChunk(a_BlockX, a_BlockZ, ChunkX, ChunkZ);
|
2020-08-28 16:22:44 -04:00
|
|
|
const auto Chunk = FindChunk(ChunkX, ChunkZ);
|
2014-10-20 16:55:07 -04:00
|
|
|
if ((Chunk == nullptr) || !Chunk->IsValid())
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2013-06-12 03:14:06 -04:00
|
|
|
return false;
|
2012-06-14 09:06:06 -04:00
|
|
|
}
|
2013-06-12 03:14:06 -04:00
|
|
|
return Chunk->SetSignLines(a_BlockX, a_BlockY, a_BlockZ, a_Line1, a_Line2, a_Line3, a_Line4);
|
2012-06-14 09:06:06 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void cChunkMap::MarkChunkRegenerating(int a_ChunkX, int a_ChunkZ)
|
|
|
|
{
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
2020-08-28 16:22:44 -04:00
|
|
|
ConstructChunk(a_ChunkX, a_ChunkZ).MarkRegenerating();
|
2012-06-14 09:06:06 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool cChunkMap::IsChunkLighted(int a_ChunkX, int a_ChunkZ)
|
|
|
|
{
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
2020-08-28 16:22:44 -04:00
|
|
|
const auto Chunk = FindChunk(a_ChunkX, a_ChunkZ);
|
2014-10-20 16:55:07 -04:00
|
|
|
if (Chunk == nullptr)
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
|
|
|
// Not present
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return Chunk->IsLightValid();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2012-07-02 12:30:17 -04:00
|
|
|
bool cChunkMap::ForEachChunkInRect(int a_MinChunkX, int a_MaxChunkX, int a_MinChunkZ, int a_MaxChunkZ, cChunkDataCallback & a_Callback)
|
|
|
|
{
|
|
|
|
bool Result = true;
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
2012-07-02 12:30:17 -04:00
|
|
|
for (int z = a_MinChunkZ; z <= a_MaxChunkZ; z++)
|
|
|
|
{
|
|
|
|
for (int x = a_MinChunkX; x <= a_MaxChunkX; x++)
|
|
|
|
{
|
2020-08-28 16:22:44 -04:00
|
|
|
const auto Chunk = FindChunk(x, z);
|
|
|
|
if ((Chunk == nullptr) || !Chunk->IsValid())
|
2012-07-02 12:30:17 -04:00
|
|
|
{
|
|
|
|
// Not present / not valid
|
|
|
|
Result = false;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (!a_Callback.Coords(x, z))
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
Chunk->GetAllData(a_Callback);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-08-20 07:50:22 -04:00
|
|
|
bool cChunkMap::ForEachLoadedChunk(cFunctionRef<bool(int, int)> a_Callback) const
|
2015-09-24 10:43:31 -04:00
|
|
|
{
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
|
|
|
for (const auto & Chunk : m_Chunks)
|
2015-09-24 10:43:31 -04:00
|
|
|
{
|
2020-08-20 07:50:22 -04:00
|
|
|
if (Chunk.second.IsValid())
|
2015-09-24 10:43:31 -04:00
|
|
|
{
|
2016-08-02 18:56:53 -04:00
|
|
|
if (a_Callback(Chunk.first.ChunkX, Chunk.first.ChunkZ))
|
2015-09-24 10:43:31 -04:00
|
|
|
{
|
2016-08-02 18:56:53 -04:00
|
|
|
return false;
|
2015-09-24 10:43:31 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2012-10-06 12:58:31 -04:00
|
|
|
bool cChunkMap::WriteBlockArea(cBlockArea & a_Area, int a_MinBlockX, int a_MinBlockY, int a_MinBlockZ, int a_DataTypes)
|
|
|
|
{
|
|
|
|
// Convert block coords to chunks coords:
|
|
|
|
int MinChunkX, MaxChunkX;
|
|
|
|
int MinChunkZ, MaxChunkZ;
|
|
|
|
int MinBlockX = a_MinBlockX;
|
|
|
|
int MinBlockY = a_MinBlockY;
|
|
|
|
int MinBlockZ = a_MinBlockZ;
|
|
|
|
int MaxBlockX = a_MinBlockX + a_Area.GetSizeX();
|
|
|
|
int MaxBlockY = a_MinBlockY + a_Area.GetSizeY();
|
|
|
|
int MaxBlockZ = a_MinBlockZ + a_Area.GetSizeZ();
|
|
|
|
cChunkDef::AbsoluteToRelative(MinBlockX, MinBlockY, MinBlockZ, MinChunkX, MinChunkZ);
|
|
|
|
cChunkDef::AbsoluteToRelative(MaxBlockX, MaxBlockY, MaxBlockZ, MaxChunkX, MaxChunkZ);
|
2016-02-05 16:45:45 -05:00
|
|
|
|
2012-10-06 12:58:31 -04:00
|
|
|
// Iterate over chunks, write data into each:
|
|
|
|
bool Result = true;
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
2012-10-06 12:58:31 -04:00
|
|
|
for (int z = MinChunkZ; z <= MaxChunkZ; z++)
|
|
|
|
{
|
|
|
|
for (int x = MinChunkX; x <= MaxChunkX; x++)
|
|
|
|
{
|
2020-08-28 16:22:44 -04:00
|
|
|
const auto Chunk = FindChunk(x, z);
|
|
|
|
if ((Chunk == nullptr) || !Chunk->IsValid())
|
2012-10-06 12:58:31 -04:00
|
|
|
{
|
|
|
|
// Not present / not valid
|
|
|
|
Result = false;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
Chunk->WriteBlockArea(a_Area, a_MinBlockX, a_MinBlockY, a_MinBlockZ, a_DataTypes);
|
|
|
|
} // for x
|
|
|
|
} // for z
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-08-20 07:50:22 -04:00
|
|
|
void cChunkMap::GetChunkStats(int & a_NumChunksValid, int & a_NumChunksDirty) const
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
|
|
|
a_NumChunksValid = 0;
|
|
|
|
a_NumChunksDirty = 0;
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
|
|
|
for (const auto & Chunk : m_Chunks)
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2016-08-02 18:56:53 -04:00
|
|
|
a_NumChunksValid++;
|
2020-08-20 07:50:22 -04:00
|
|
|
if (Chunk.second.IsDirty())
|
2016-08-02 18:56:53 -04:00
|
|
|
{
|
|
|
|
a_NumChunksDirty++;
|
|
|
|
}
|
|
|
|
}
|
2012-06-14 09:06:06 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2019-10-11 05:02:53 -04:00
|
|
|
int cChunkMap::GrowPlantAt(Vector3i a_BlockPos, int a_NumStages)
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2019-10-11 05:02:53 -04:00
|
|
|
auto chunkPos = cChunkDef::BlockToChunk(a_BlockPos);
|
|
|
|
auto relPos = cChunkDef::AbsoluteToRelative(a_BlockPos, chunkPos);
|
|
|
|
cCSLock lock(m_CSChunks);
|
2020-08-28 16:22:44 -04:00
|
|
|
const auto Chunk = FindChunk(chunkPos.m_ChunkX, chunkPos.m_ChunkZ);
|
|
|
|
if ((Chunk == nullptr) || !Chunk->IsValid())
|
2016-05-29 16:10:35 -04:00
|
|
|
{
|
2019-10-11 05:02:53 -04:00
|
|
|
return 0;
|
2016-05-29 16:10:35 -04:00
|
|
|
}
|
2020-08-28 16:22:44 -04:00
|
|
|
return Chunk->GrowPlantAt(relPos, a_NumStages);
|
2016-05-29 16:10:35 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-04-17 05:36:37 -04:00
|
|
|
void cChunkMap::SetNextBlockToTick(const Vector3i a_BlockPos)
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2020-04-17 05:36:37 -04:00
|
|
|
auto ChunkPos = cChunkDef::BlockToChunk(a_BlockPos);
|
|
|
|
auto RelPos = cChunkDef::AbsoluteToRelative(a_BlockPos, ChunkPos);
|
2016-02-05 16:45:45 -05:00
|
|
|
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
2020-08-28 16:22:44 -04:00
|
|
|
const auto Chunk = FindChunk(ChunkPos.m_ChunkX, ChunkPos.m_ChunkZ);
|
2014-10-20 16:55:07 -04:00
|
|
|
if (Chunk != nullptr)
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2020-04-17 05:36:37 -04:00
|
|
|
Chunk->SetNextBlockToTick(RelPos);
|
2012-06-14 09:06:06 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2018-07-26 17:24:36 -04:00
|
|
|
|
2015-05-09 05:16:56 -04:00
|
|
|
void cChunkMap::CollectMobCensus(cMobCensus & a_ToFill)
|
2013-09-07 16:19:56 -04:00
|
|
|
{
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
2020-08-20 07:50:22 -04:00
|
|
|
for (auto & Chunk : m_Chunks)
|
2013-09-07 16:19:56 -04:00
|
|
|
{
|
2016-08-02 18:56:53 -04:00
|
|
|
// We do count every Mobs in the world. But we are assuming that every chunk not loaded by any client
|
|
|
|
// doesn't affect us. Normally they should not have mobs because every "too far" mobs despawn
|
|
|
|
// If they have (f.i. when player disconnect) we assume we don't have to make them live or despawn
|
2020-08-20 07:50:22 -04:00
|
|
|
if (Chunk.second.IsValid() && Chunk.second.HasAnyClients())
|
2016-08-02 18:56:53 -04:00
|
|
|
{
|
2020-08-20 07:50:22 -04:00
|
|
|
Chunk.second.CollectMobCensus(a_ToFill);
|
2016-08-02 18:56:53 -04:00
|
|
|
}
|
|
|
|
}
|
2013-09-07 16:19:56 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2015-05-09 05:16:56 -04:00
|
|
|
void cChunkMap::SpawnMobs(cMobSpawner & a_MobSpawner)
|
2013-09-07 18:11:38 -04:00
|
|
|
{
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
2020-08-20 07:50:22 -04:00
|
|
|
for (auto & Chunk : m_Chunks)
|
2013-09-07 18:11:38 -04:00
|
|
|
{
|
2016-08-02 18:56:53 -04:00
|
|
|
// We only spawn close to players
|
2020-08-20 07:50:22 -04:00
|
|
|
if (Chunk.second.IsValid() && Chunk.second.HasAnyClients())
|
2016-08-02 18:56:53 -04:00
|
|
|
{
|
2020-08-20 07:50:22 -04:00
|
|
|
Chunk.second.SpawnMobs(a_MobSpawner);
|
2016-08-02 18:56:53 -04:00
|
|
|
}
|
|
|
|
}
|
2013-09-07 18:11:38 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2015-01-11 16:12:26 -05:00
|
|
|
void cChunkMap::Tick(std::chrono::milliseconds a_Dt)
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
2020-08-20 07:50:22 -04:00
|
|
|
for (auto & Chunk : m_Chunks)
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2016-08-02 18:56:53 -04:00
|
|
|
// Only tick chunks that are valid and should be ticked:
|
2020-08-20 07:50:22 -04:00
|
|
|
if (Chunk.second.IsValid() && Chunk.second.ShouldBeTicked())
|
2016-08-02 18:56:53 -04:00
|
|
|
{
|
2020-08-20 07:50:22 -04:00
|
|
|
Chunk.second.Tick(a_Dt);
|
2016-08-02 18:56:53 -04:00
|
|
|
}
|
|
|
|
}
|
2012-06-14 09:06:06 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-04-17 05:36:37 -04:00
|
|
|
void cChunkMap::TickBlock(const Vector3i a_BlockPos)
|
2013-11-30 09:58:27 -05:00
|
|
|
{
|
2020-04-17 05:36:37 -04:00
|
|
|
auto ChunkPos = cChunkDef::BlockToChunk(a_BlockPos);
|
|
|
|
auto RelPos = cChunkDef::AbsoluteToRelative(a_BlockPos, ChunkPos);
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
2020-08-28 16:22:44 -04:00
|
|
|
const auto Chunk = FindChunk(ChunkPos.m_ChunkX, ChunkPos.m_ChunkZ);
|
2014-10-20 16:55:07 -04:00
|
|
|
if ((Chunk == nullptr) || !Chunk->IsValid())
|
2013-11-30 09:58:27 -05:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2020-04-17 05:36:37 -04:00
|
|
|
Chunk->TickBlock(RelPos);
|
2013-11-30 09:58:27 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void cChunkMap::UnloadUnusedChunks(void)
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
|
|
|
for (auto itr = m_Chunks.begin(); itr != m_Chunks.end();)
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2016-08-02 18:56:53 -04:00
|
|
|
if (
|
2020-09-22 16:21:47 -04:00
|
|
|
itr->second.CanUnload() && // Can unload
|
2016-08-02 18:56:53 -04:00
|
|
|
!cPluginManager::Get()->CallHookChunkUnloading(*GetWorld(), itr->first.ChunkX, itr->first.ChunkZ) // Plugins agree
|
|
|
|
)
|
|
|
|
{
|
2020-09-22 16:21:47 -04:00
|
|
|
// First notify plugins:
|
|
|
|
cPluginManager::Get()->CallHookChunkUnloaded(*m_World, itr->first.ChunkX, itr->first.ChunkZ);
|
|
|
|
|
|
|
|
// Notify entities within the chunk, while everything's still valid:
|
|
|
|
itr->second.OnUnload();
|
|
|
|
|
|
|
|
// Kill the chunk:
|
2016-08-02 18:56:53 -04:00
|
|
|
itr = m_Chunks.erase(itr);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
++itr;
|
|
|
|
}
|
|
|
|
}
|
2012-06-14 09:06:06 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-08-20 07:50:22 -04:00
|
|
|
void cChunkMap::SaveAllChunks(void) const
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
|
|
|
for (const auto & Chunk : m_Chunks)
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2020-08-20 07:50:22 -04:00
|
|
|
if (Chunk.second.IsValid() && Chunk.second.IsDirty())
|
2016-08-02 18:56:53 -04:00
|
|
|
{
|
|
|
|
GetWorld()->GetStorage().QueueSaveChunk(Chunk.first.ChunkX, Chunk.first.ChunkZ);
|
|
|
|
}
|
|
|
|
}
|
2012-06-14 09:06:06 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-08-20 07:50:22 -04:00
|
|
|
size_t cChunkMap::GetNumChunks(void) const
|
2012-10-14 14:30:16 -04:00
|
|
|
{
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
2016-09-03 11:38:29 -04:00
|
|
|
return m_Chunks.size();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2016-08-02 18:56:53 -04:00
|
|
|
|
2016-09-03 11:38:29 -04:00
|
|
|
|
2020-08-20 07:50:22 -04:00
|
|
|
size_t cChunkMap::GetNumUnusedDirtyChunks(void) const
|
2016-09-03 11:38:29 -04:00
|
|
|
{
|
|
|
|
cCSLock Lock(m_CSChunks);
|
|
|
|
size_t res = 0;
|
|
|
|
for (const auto & Chunk : m_Chunks)
|
|
|
|
{
|
2020-08-20 07:50:22 -04:00
|
|
|
if (Chunk.second.IsValid() && Chunk.second.CanUnloadAfterSaving())
|
2016-09-03 11:38:29 -04:00
|
|
|
{
|
|
|
|
res += 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return res;
|
2012-10-14 14:30:16 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void cChunkMap::ChunkValidated(void)
|
|
|
|
{
|
|
|
|
m_evtChunkValid.Set();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2014-07-10 12:18:32 -04:00
|
|
|
void cChunkMap::SetChunkAlwaysTicked(int a_ChunkX, int a_ChunkZ, bool a_AlwaysTicked)
|
|
|
|
{
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
2020-08-28 16:22:44 -04:00
|
|
|
GetChunk(a_ChunkX, a_ChunkZ).SetAlwaysTicked(a_AlwaysTicked);
|
2014-07-10 12:18:32 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2017-01-17 16:38:04 -05:00
|
|
|
void cChunkMap::TrackInDeadlockDetect(cDeadlockDetect & a_DeadlockDetect, const AString & a_WorldName)
|
|
|
|
{
|
|
|
|
a_DeadlockDetect.TrackCriticalSection(m_CSChunks, Printf("World %s chunkmap", a_WorldName.c_str()));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void cChunkMap::UntrackInDeadlockDetect(cDeadlockDetect & a_DeadlockDetect)
|
|
|
|
{
|
|
|
|
a_DeadlockDetect.UntrackCriticalSection(m_CSChunks);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2014-02-08 15:55:21 -05:00
|
|
|
void cChunkMap::AddChunkStay(cChunkStay & a_ChunkStay)
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
2016-02-05 16:45:45 -05:00
|
|
|
|
2014-02-08 15:55:21 -05:00
|
|
|
// Add it to the list:
|
|
|
|
ASSERT(std::find(m_ChunkStays.begin(), m_ChunkStays.end(), &a_ChunkStay) == m_ChunkStays.end()); // Has not yet been added
|
|
|
|
m_ChunkStays.push_back(&a_ChunkStay);
|
2016-02-05 16:45:45 -05:00
|
|
|
|
2014-02-08 15:55:21 -05:00
|
|
|
// Schedule all chunks to be loaded / generated, and mark each as locked:
|
|
|
|
const cChunkCoordsVector & WantedChunks = a_ChunkStay.GetChunks();
|
|
|
|
for (cChunkCoordsVector::const_iterator itr = WantedChunks.begin(); itr != WantedChunks.end(); ++itr)
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2020-08-28 16:22:44 -04:00
|
|
|
auto & Chunk = GetChunk(itr->m_ChunkX, itr->m_ChunkZ);
|
|
|
|
Chunk.Stay(true);
|
|
|
|
if (Chunk.IsValid())
|
2014-02-08 15:55:21 -05:00
|
|
|
{
|
2014-04-12 16:15:09 -04:00
|
|
|
if (a_ChunkStay.ChunkAvailable(itr->m_ChunkX, itr->m_ChunkZ))
|
|
|
|
{
|
|
|
|
// The chunkstay wants to be deactivated, disable it and bail out:
|
|
|
|
a_ChunkStay.Disable();
|
|
|
|
return;
|
|
|
|
}
|
2014-02-08 15:55:21 -05:00
|
|
|
}
|
|
|
|
} // for itr - WantedChunks[]
|
2012-06-14 09:06:06 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2014-02-08 15:55:21 -05:00
|
|
|
/** Removes the specified cChunkStay descendant from the internal list of ChunkStays. */
|
|
|
|
void cChunkMap::DelChunkStay(cChunkStay & a_ChunkStay)
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2016-08-02 18:56:53 -04:00
|
|
|
cCSLock Lock(m_CSChunks);
|
2016-02-05 16:45:45 -05:00
|
|
|
|
2014-02-08 15:55:21 -05:00
|
|
|
// Remove from the list of active chunkstays:
|
|
|
|
bool HasFound = false;
|
|
|
|
for (cChunkStays::iterator itr = m_ChunkStays.begin(), end = m_ChunkStays.end(); itr != end; ++itr)
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2014-02-08 15:55:21 -05:00
|
|
|
if (*itr == &a_ChunkStay)
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2014-02-08 15:55:21 -05:00
|
|
|
m_ChunkStays.erase(itr);
|
|
|
|
HasFound = true;
|
|
|
|
break;
|
2012-06-14 09:06:06 -04:00
|
|
|
}
|
2014-02-08 15:55:21 -05:00
|
|
|
} // for itr - m_ChunkStays[]
|
2016-02-05 16:45:45 -05:00
|
|
|
|
2014-02-08 15:55:21 -05:00
|
|
|
if (!HasFound)
|
|
|
|
{
|
|
|
|
ASSERT(!"Removing a cChunkStay that hasn't been added!");
|
|
|
|
return;
|
|
|
|
}
|
2016-02-05 16:45:45 -05:00
|
|
|
|
2014-02-08 15:55:21 -05:00
|
|
|
// Unmark all contained chunks:
|
|
|
|
const cChunkCoordsVector & Chunks = a_ChunkStay.GetChunks();
|
|
|
|
for (cChunkCoordsVector::const_iterator itr = Chunks.begin(), end = Chunks.end(); itr != end; ++itr)
|
2012-06-14 09:06:06 -04:00
|
|
|
{
|
2020-08-28 16:22:44 -04:00
|
|
|
const auto Chunk = FindChunk(itr->m_ChunkX, itr->m_ChunkZ);
|
|
|
|
ASSERT(Chunk != nullptr); // Stayed chunks cannot unload
|
2014-02-08 15:55:21 -05:00
|
|
|
Chunk->Stay(false);
|
|
|
|
} // for itr - Chunks[]
|
2014-04-12 16:15:09 -04:00
|
|
|
a_ChunkStay.OnDisabled();
|
2012-06-14 09:06:06 -04:00
|
|
|
}
|