Merge pull request #2894 from LogicParrot/spider
Spiders now friendly at daylight, new cChunk functions
This commit is contained in:
commit
30b95fcc4e
163
src/Chunk.cpp
163
src/Chunk.cpp
@ -123,9 +123,9 @@ cChunk::cChunk(
|
||||
cChunk::~cChunk()
|
||||
{
|
||||
cPluginManager::Get()->CallHookChunkUnloaded(*m_World, m_PosX, m_PosZ);
|
||||
|
||||
|
||||
// LOGINFO("### delete cChunk() (%i, %i) from %p, thread 0x%x ###", m_PosX, m_PosZ, this, GetCurrentThreadId());
|
||||
|
||||
|
||||
for (cBlockEntityList::iterator itr = m_BlockEntities.begin(); itr != m_BlockEntities.end(); ++itr)
|
||||
{
|
||||
delete *itr;
|
||||
@ -143,7 +143,7 @@ cChunk::~cChunk()
|
||||
delete *itr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (m_NeighborXM != nullptr)
|
||||
{
|
||||
m_NeighborXM->m_NeighborXP = nullptr;
|
||||
@ -284,12 +284,12 @@ void cChunk::GetAllData(cChunkDataCallback & a_Callback)
|
||||
a_Callback.LightIsValid(m_IsLightValid);
|
||||
|
||||
a_Callback.ChunkData(m_ChunkData);
|
||||
|
||||
|
||||
for (cEntityList::iterator itr = m_Entities.begin(); itr != m_Entities.end(); ++itr)
|
||||
{
|
||||
a_Callback.Entity(*itr);
|
||||
}
|
||||
|
||||
|
||||
for (cBlockEntityList::iterator itr = m_BlockEntities.begin(); itr != m_BlockEntities.end(); ++itr)
|
||||
{
|
||||
a_Callback.BlockEntity(*itr);
|
||||
@ -305,7 +305,7 @@ void cChunk::SetAllData(cSetChunkData & a_SetChunkData)
|
||||
ASSERT(a_SetChunkData.IsHeightMapValid());
|
||||
ASSERT(a_SetChunkData.AreBiomesValid());
|
||||
ASSERT(IsQueued());
|
||||
|
||||
|
||||
memcpy(m_BiomeMap, a_SetChunkData.GetBiomes(), sizeof(m_BiomeMap));
|
||||
memcpy(m_HeightMap, a_SetChunkData.GetHeightMap(), sizeof(m_HeightMap));
|
||||
|
||||
@ -339,19 +339,19 @@ void cChunk::SetAllData(cSetChunkData & a_SetChunkData)
|
||||
ASSERT(WorldBlockType == EntityBlockType);
|
||||
} // for itr - m_BlockEntities
|
||||
#endif // _DEBUG
|
||||
|
||||
|
||||
// Set all block entities' World variable:
|
||||
for (cBlockEntityList::iterator itr = m_BlockEntities.begin(); itr != m_BlockEntities.end(); ++itr)
|
||||
{
|
||||
(*itr)->SetWorld(m_World);
|
||||
}
|
||||
|
||||
|
||||
// Create block entities that the loader didn't load; fill them with defaults
|
||||
CreateBlockEntities();
|
||||
|
||||
|
||||
// Set the chunk data as valid. This may be needed for some simulators that perform actions upon block adding (Vaporize)
|
||||
SetPresence(cpPresent);
|
||||
|
||||
|
||||
// Wake up all simulators for their respective blocks:
|
||||
WakeUpSimulators();
|
||||
|
||||
@ -399,7 +399,7 @@ void cChunk::WriteBlockArea(cBlockArea & a_Area, int a_MinBlockX, int a_MinBlock
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// SizeX, SizeZ are the dimensions of the block data to copy to the chunk (size of the geometric union)
|
||||
|
||||
int BlockStartX = std::max(a_MinBlockX, m_PosX * cChunkDef::Width);
|
||||
@ -541,7 +541,7 @@ void cChunk::SpawnMobs(cMobSpawner & a_MobSpawner)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
a_MobSpawner.NewPack();
|
||||
int NumberOfTries = 0;
|
||||
int NumberOfSuccess = 0;
|
||||
@ -561,7 +561,7 @@ void cChunk::SpawnMobs(cMobSpawner & a_MobSpawner)
|
||||
|
||||
ASSERT(TryY > 0);
|
||||
ASSERT(TryY < cChunkDef::Height - 1);
|
||||
|
||||
|
||||
EMCSBiome Biome = m_ChunkMap->GetBiomeAt(TryX, TryZ);
|
||||
// MG TODO :
|
||||
// Moon cycle (for slime)
|
||||
@ -569,7 +569,7 @@ void cChunk::SpawnMobs(cMobSpawner & a_MobSpawner)
|
||||
// check mobs presence on the block
|
||||
|
||||
// MG TODO : check that "Level" really means Y
|
||||
|
||||
|
||||
/*
|
||||
NIBBLETYPE SkyLight = 0;
|
||||
|
||||
@ -581,7 +581,7 @@ void cChunk::SpawnMobs(cMobSpawner & a_MobSpawner)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
cEntity * newMob = a_MobSpawner.TryToSpawnHere(this, TryX, TryY, TryZ, Biome, MaxNbOfSuccess);
|
||||
if (newMob == nullptr)
|
||||
{
|
||||
@ -606,10 +606,10 @@ void cChunk::Tick(std::chrono::milliseconds a_Dt)
|
||||
BroadcastPendingBlockChanges();
|
||||
|
||||
CheckBlocks();
|
||||
|
||||
|
||||
// Tick simulators:
|
||||
m_World->GetSimulatorManager()->SimulateChunk(a_Dt, m_PosX, m_PosZ, this);
|
||||
|
||||
|
||||
TickBlocks();
|
||||
|
||||
// Tick all block entities in this chunk:
|
||||
@ -617,7 +617,7 @@ void cChunk::Tick(std::chrono::milliseconds a_Dt)
|
||||
{
|
||||
m_IsDirty = (*itr)->Tick(a_Dt, *this) | m_IsDirty;
|
||||
}
|
||||
|
||||
|
||||
for (cEntityList::iterator itr = m_Entities.begin(); itr != m_Entities.end();)
|
||||
{
|
||||
if (!((*itr)->IsMob())) // Mobs are ticked inside cWorld::TickMobs() (as we don't have to tick them if they are far away from players)
|
||||
@ -657,7 +657,7 @@ void cChunk::Tick(std::chrono::milliseconds a_Dt)
|
||||
++itr;
|
||||
}
|
||||
} // for itr - m_Entitites[]
|
||||
|
||||
|
||||
ApplyWeatherToTop();
|
||||
}
|
||||
|
||||
@ -715,7 +715,7 @@ void cChunk::MoveEntityToNewChunk(cEntity * a_Entity)
|
||||
m_Entity(a_CallbackEntity)
|
||||
{}
|
||||
} Mover(a_Entity);
|
||||
|
||||
|
||||
m_ChunkMap->CompareChunkClients(this, Neighbor, Mover);
|
||||
}
|
||||
|
||||
@ -761,10 +761,10 @@ void cChunk::CheckBlocks()
|
||||
}
|
||||
std::vector<Vector3i> ToTickBlocks;
|
||||
std::swap(m_ToTickBlocks, ToTickBlocks);
|
||||
|
||||
|
||||
cChunkInterface ChunkInterface(m_World->GetChunkMap());
|
||||
cBlockInServerPluginInterface PluginInterface(*m_World);
|
||||
|
||||
|
||||
for (std::vector<Vector3i>::const_iterator itr = ToTickBlocks.begin(), end = ToTickBlocks.end(); itr != end; ++itr)
|
||||
{
|
||||
Vector3i Pos = (*itr);
|
||||
@ -788,17 +788,17 @@ void cChunk::TickBlocks(void)
|
||||
int TickX = m_BlockTickX;
|
||||
int TickY = m_BlockTickY;
|
||||
int TickZ = m_BlockTickZ;
|
||||
|
||||
|
||||
cChunkInterface ChunkInterface(this->GetWorld()->GetChunkMap());
|
||||
cBlockInServerPluginInterface PluginInterface(*this->GetWorld());
|
||||
|
||||
// This for loop looks disgusting, but it actually does a simple thing - first processes m_BlockTick, then adds random to it
|
||||
// This is so that SetNextBlockTick() works
|
||||
for (int i = 0; i < 50; i++,
|
||||
|
||||
|
||||
// This weird construct (*2, then /2) is needed,
|
||||
// otherwise the blocktick distribution is too biased towards even coords!
|
||||
|
||||
|
||||
TickX = (TickX + RandomX) % (Width * 2),
|
||||
TickY = (TickY + RandomY) % (Height * 2),
|
||||
TickZ = (TickZ + RandomZ) % (Width * 2),
|
||||
@ -836,7 +836,7 @@ void cChunk::ApplyWeatherToTop()
|
||||
// Not the right weather, or not at this tick; bail out
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
int X = m_World->GetTickRandomNumber(15);
|
||||
int Z = m_World->GetTickRandomNumber(15);
|
||||
|
||||
@ -944,7 +944,7 @@ void cChunk::GrowMelonPumpkin(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_Bl
|
||||
// Neighbors not valid or already taken by the same produce
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Pick a direction in which to place the produce:
|
||||
int x = 0, z = 0;
|
||||
int CheckType = a_TickRandom.randInt(3); // The index to the neighbors array which should be checked for emptiness
|
||||
@ -955,7 +955,7 @@ void cChunk::GrowMelonPumpkin(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_Bl
|
||||
case 2: z = 1; break;
|
||||
case 3: z = -1; break;
|
||||
}
|
||||
|
||||
|
||||
// Check that the block in that direction is empty:
|
||||
switch (BlockType[CheckType])
|
||||
{
|
||||
@ -968,7 +968,7 @@ void cChunk::GrowMelonPumpkin(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_Bl
|
||||
}
|
||||
default: return;
|
||||
}
|
||||
|
||||
|
||||
// Check if there's soil under the neighbor. We already know the neighbors are valid. Place produce if ok
|
||||
BLOCKTYPE Soil;
|
||||
VERIFY(UnboundedRelGetBlock(a_RelX + x, a_RelY - 1, a_RelZ + z, Soil, BlockMeta));
|
||||
@ -1019,7 +1019,7 @@ void cChunk::GrowSugarcane(int a_RelX, int a_RelY, int a_RelZ, int a_NumBlocks)
|
||||
{
|
||||
--Bottom;
|
||||
}
|
||||
|
||||
|
||||
// Grow by at most a_NumBlocks, but no more than max height:
|
||||
int ToGrow = std::min(a_NumBlocks, m_World->GetMaxSugarcaneHeight() + 1 - (Top - Bottom));
|
||||
for (int i = 0; i < ToGrow; i++)
|
||||
@ -1060,7 +1060,7 @@ void cChunk::GrowCactus(int a_RelX, int a_RelY, int a_RelZ, int a_NumBlocks)
|
||||
{
|
||||
--Bottom;
|
||||
}
|
||||
|
||||
|
||||
// Grow by at most a_NumBlocks, but no more than max height:
|
||||
int ToGrow = std::min(a_NumBlocks, m_World->GetMaxCactusHeight() + 1 - (Top - Bottom));
|
||||
for (int i = 0; i < ToGrow; i++)
|
||||
@ -1273,7 +1273,7 @@ void cChunk::UnboundedQueueTickBlock(int a_RelX, int a_RelY, int a_RelZ)
|
||||
int cChunk::GetHeight(int a_X, int a_Z)
|
||||
{
|
||||
ASSERT((a_X >= 0) && (a_X < Width) && (a_Z >= 0) && (a_Z < Width));
|
||||
|
||||
|
||||
if ((a_X >= 0) && (a_X < Width) && (a_Z >= 0) && (a_Z < Width))
|
||||
{
|
||||
return m_HeightMap[a_X + a_Z * Width];
|
||||
@ -1410,7 +1410,7 @@ void cChunk::CalculateHeightmap(const BLOCKTYPE * a_BlockTypes)
|
||||
void cChunk::SetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, bool a_SendToClients)
|
||||
{
|
||||
FastSetBlock(a_RelX, a_RelY, a_RelZ, a_BlockType, a_BlockMeta, a_SendToClients);
|
||||
|
||||
|
||||
// Tick this block and its neighbors:
|
||||
m_ToTickBlocks.push_back(Vector3i(a_RelX, a_RelY, a_RelZ));
|
||||
QueueTickBlockNeighbors(a_RelX, a_RelY, a_RelZ);
|
||||
@ -1425,7 +1425,7 @@ void cChunk::SetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType,
|
||||
delete BlockEntity;
|
||||
BlockEntity = nullptr;
|
||||
}
|
||||
|
||||
|
||||
// If the new block is a block entity, create the entity object:
|
||||
switch (a_BlockType)
|
||||
{
|
||||
@ -1470,7 +1470,7 @@ void cChunk::QueueTickBlock(int a_RelX, int a_RelY, int a_RelZ)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
m_ToTickBlocks.push_back(Vector3i(a_RelX, a_RelY, a_RelZ));
|
||||
}
|
||||
|
||||
@ -1508,7 +1508,7 @@ void cChunk::FastSetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockT
|
||||
ASSERT(!((a_RelX < 0) || (a_RelX >= Width) || (a_RelY < 0) || (a_RelY >= Height) || (a_RelZ < 0) || (a_RelZ >= Width)));
|
||||
|
||||
ASSERT(IsValid());
|
||||
|
||||
|
||||
const BLOCKTYPE OldBlockType = GetBlock(a_RelX, a_RelY, a_RelZ);
|
||||
const BLOCKTYPE OldBlockMeta = m_ChunkData.GetMeta(a_RelX, a_RelY, a_RelZ);
|
||||
if ((OldBlockType == a_BlockType) && (OldBlockMeta == a_BlockMeta))
|
||||
@ -1543,7 +1543,7 @@ void cChunk::FastSetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockT
|
||||
{
|
||||
m_PendingSendBlocks.push_back(sSetBlock(m_PosX, m_PosZ, a_RelX, a_RelY, a_RelZ, a_BlockType, a_BlockMeta));
|
||||
}
|
||||
|
||||
|
||||
m_ChunkData.SetMeta(a_RelX, a_RelY, a_RelZ, a_BlockMeta);
|
||||
|
||||
// ONLY recalculate lighting if it's necessary!
|
||||
@ -1593,7 +1593,7 @@ void cChunk::SendBlockTo(int a_RelX, int a_RelY, int a_RelZ, cClientHandle * a_C
|
||||
|
||||
Vector3i wp = PositionToWorldPosition(a_RelX, a_RelY, a_RelZ);
|
||||
a_Client->SendBlockChange(wp.x, wp.y, wp.z, GetBlock(a_RelX, a_RelY, a_RelZ), GetMeta(a_RelX, a_RelY, a_RelZ));
|
||||
|
||||
|
||||
// FS #268 - if a BlockEntity digging is cancelled by a plugin, the entire block entity must be re-sent to the client:
|
||||
for (cBlockEntityList::iterator itr = m_BlockEntities.begin(), end = m_BlockEntities.end(); itr != end; ++itr)
|
||||
{
|
||||
@ -1637,7 +1637,7 @@ cBlockEntity * cChunk::GetBlockEntity(int a_BlockX, int a_BlockY, int a_BlockZ)
|
||||
return *itr;
|
||||
}
|
||||
} // for itr - m_BlockEntities[]
|
||||
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -1704,7 +1704,7 @@ void cChunk::SetAreaBiome(int a_MinRelX, int a_MaxRelX, int a_MinRelZ, int a_Max
|
||||
}
|
||||
}
|
||||
MarkDirty();
|
||||
|
||||
|
||||
// Re-send the chunk to all clients:
|
||||
for (auto ClientHandle : m_LoadedByClient)
|
||||
{
|
||||
@ -1721,7 +1721,7 @@ void cChunk::CollectPickupsByPlayer(cPlayer & a_Player)
|
||||
double PosX = a_Player.GetPosX();
|
||||
double PosY = a_Player.GetPosY();
|
||||
double PosZ = a_Player.GetPosZ();
|
||||
|
||||
|
||||
for (cEntityList::iterator itr = m_Entities.begin(); itr != m_Entities.end(); ++itr)
|
||||
{
|
||||
if ((!(*itr)->IsPickup()) && (!(*itr)->IsProjectile()))
|
||||
@ -2150,14 +2150,14 @@ bool cChunk::DoWithBlockEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBloc
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (a_Callback.Item(*itr))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
} // for itr - m_BlockEntitites[]
|
||||
|
||||
|
||||
// Not found:
|
||||
return false;
|
||||
}
|
||||
@ -2180,7 +2180,7 @@ bool cChunk::DoWithBeaconAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBeaconCal
|
||||
// There is a block entity here, but of different type. No other block entity can be here, so we can safely bail out
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// The correct block entity is here
|
||||
if (a_Callback.Item(reinterpret_cast<cBeaconEntity *>(*itr)))
|
||||
{
|
||||
@ -2188,7 +2188,7 @@ bool cChunk::DoWithBeaconAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBeaconCal
|
||||
}
|
||||
return true;
|
||||
} // for itr - m_BlockEntitites[]
|
||||
|
||||
|
||||
// Not found:
|
||||
return false;
|
||||
}
|
||||
@ -2244,7 +2244,7 @@ bool cChunk::DoWithChestAt(int a_BlockX, int a_BlockY, int a_BlockZ, cChestCallb
|
||||
// There is a block entity here, but of different type. No other block entity can be here, so we can safely bail out
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// The correct block entity is here
|
||||
if (a_Callback.Item(reinterpret_cast<cChestEntity *>(*itr)))
|
||||
{
|
||||
@ -2252,7 +2252,7 @@ bool cChunk::DoWithChestAt(int a_BlockX, int a_BlockY, int a_BlockZ, cChestCallb
|
||||
}
|
||||
return true;
|
||||
} // for itr - m_BlockEntitites[]
|
||||
|
||||
|
||||
// Not found:
|
||||
return false;
|
||||
}
|
||||
@ -2276,7 +2276,7 @@ bool cChunk::DoWithDispenserAt(int a_BlockX, int a_BlockY, int a_BlockZ, cDispen
|
||||
// There is a block entity here, but of different type. No other block entity can be here, so we can safely bail out
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// The correct block entity is here
|
||||
if (a_Callback.Item(reinterpret_cast<cDispenserEntity *>(*itr)))
|
||||
{
|
||||
@ -2284,7 +2284,7 @@ bool cChunk::DoWithDispenserAt(int a_BlockX, int a_BlockY, int a_BlockZ, cDispen
|
||||
}
|
||||
return true;
|
||||
} // for itr - m_BlockEntitites[]
|
||||
|
||||
|
||||
// Not found:
|
||||
return false;
|
||||
}
|
||||
@ -2308,7 +2308,7 @@ bool cChunk::DoWithDropperAt(int a_BlockX, int a_BlockY, int a_BlockZ, cDropperC
|
||||
// There is a block entity here, but of different type. No other block entity can be here, so we can safely bail out
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// The correct block entity is here
|
||||
if (a_Callback.Item(reinterpret_cast<cDropperEntity *>(*itr)))
|
||||
{
|
||||
@ -2316,7 +2316,7 @@ bool cChunk::DoWithDropperAt(int a_BlockX, int a_BlockY, int a_BlockZ, cDropperC
|
||||
}
|
||||
return true;
|
||||
} // for itr - m_BlockEntitites[]
|
||||
|
||||
|
||||
// Not found:
|
||||
return false;
|
||||
}
|
||||
@ -2340,7 +2340,7 @@ bool cChunk::DoWithDropSpenserAt(int a_BlockX, int a_BlockY, int a_BlockZ, cDrop
|
||||
// There is a block entity here, but of different type. No other block entity can be here, so we can safely bail out
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// The correct block entity is here
|
||||
if (a_Callback.Item(reinterpret_cast<cDropSpenserEntity *>(*itr)))
|
||||
{
|
||||
@ -2348,7 +2348,7 @@ bool cChunk::DoWithDropSpenserAt(int a_BlockX, int a_BlockY, int a_BlockZ, cDrop
|
||||
}
|
||||
return true;
|
||||
} // for itr - m_BlockEntitites[]
|
||||
|
||||
|
||||
// Not found:
|
||||
return false;
|
||||
}
|
||||
@ -2380,7 +2380,7 @@ bool cChunk::DoWithFurnaceAt(int a_BlockX, int a_BlockY, int a_BlockZ, cFurnaceC
|
||||
return false;
|
||||
}
|
||||
} // switch (BlockType)
|
||||
|
||||
|
||||
// The correct block entity is here,
|
||||
if (a_Callback.Item(reinterpret_cast<cFurnaceEntity *>(*itr)))
|
||||
{
|
||||
@ -2388,7 +2388,7 @@ bool cChunk::DoWithFurnaceAt(int a_BlockX, int a_BlockY, int a_BlockZ, cFurnaceC
|
||||
}
|
||||
return true;
|
||||
} // for itr - m_BlockEntitites[]
|
||||
|
||||
|
||||
// Not found:
|
||||
return false;
|
||||
}
|
||||
@ -2412,7 +2412,7 @@ bool cChunk::DoWithNoteBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cNoteBl
|
||||
// There is a block entity here, but of different type. No other block entity can be here, so we can safely bail out
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// The correct block entity is here
|
||||
if (a_Callback.Item(reinterpret_cast<cNoteEntity *>(*itr)))
|
||||
{
|
||||
@ -2420,7 +2420,7 @@ bool cChunk::DoWithNoteBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cNoteBl
|
||||
}
|
||||
return true;
|
||||
} // for itr - m_BlockEntitites[]
|
||||
|
||||
|
||||
// Not found:
|
||||
return false;
|
||||
}
|
||||
@ -2444,7 +2444,7 @@ bool cChunk::DoWithCommandBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cCom
|
||||
// There is a block entity here, but of different type. No other block entity can be here, so we can safely bail out
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// The correct block entity is here,
|
||||
if (a_Callback.Item(reinterpret_cast<cCommandBlockEntity *>(*itr)))
|
||||
{
|
||||
@ -2452,7 +2452,7 @@ bool cChunk::DoWithCommandBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cCom
|
||||
}
|
||||
return true;
|
||||
} // for itr - m_BlockEntitites[]
|
||||
|
||||
|
||||
// Not found:
|
||||
return false;
|
||||
}
|
||||
@ -2476,7 +2476,7 @@ bool cChunk::DoWithMobHeadAt(int a_BlockX, int a_BlockY, int a_BlockZ, cMobHeadC
|
||||
// There is a block entity here, but of different type. No other block entity can be here, so we can safely bail out
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// The correct block entity is here,
|
||||
if (a_Callback.Item(reinterpret_cast<cMobHeadEntity *>(*itr)))
|
||||
{
|
||||
@ -2484,7 +2484,7 @@ bool cChunk::DoWithMobHeadAt(int a_BlockX, int a_BlockY, int a_BlockZ, cMobHeadC
|
||||
}
|
||||
return true;
|
||||
} // for itr - m_BlockEntitites[]
|
||||
|
||||
|
||||
// Not found:
|
||||
return false;
|
||||
}
|
||||
@ -2508,7 +2508,7 @@ bool cChunk::DoWithFlowerPotAt(int a_BlockX, int a_BlockY, int a_BlockZ, cFlower
|
||||
// There is a block entity here, but of different type. No other block entity can be here, so we can safely bail out
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// The correct block entity is here
|
||||
if (a_Callback.Item(reinterpret_cast<cFlowerPotEntity *>(*itr)))
|
||||
{
|
||||
@ -2516,7 +2516,7 @@ bool cChunk::DoWithFlowerPotAt(int a_BlockX, int a_BlockY, int a_BlockZ, cFlower
|
||||
}
|
||||
return true;
|
||||
} // for itr - m_BlockEntitites[]
|
||||
|
||||
|
||||
// Not found:
|
||||
return false;
|
||||
}
|
||||
@ -2546,11 +2546,11 @@ bool cChunk::GetSignLines(int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_
|
||||
return true;
|
||||
}
|
||||
} // switch (BlockType)
|
||||
|
||||
|
||||
// There is a block entity here, but of different type. No other block entity can be here, so we can safely bail out
|
||||
return false;
|
||||
} // for itr - m_BlockEntitites[]
|
||||
|
||||
|
||||
// Not found:
|
||||
return false;
|
||||
}
|
||||
@ -2600,6 +2600,31 @@ void cChunk::GetBlockInfo(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE & a_Bloc
|
||||
|
||||
|
||||
|
||||
|
||||
bool cChunk::GetChunkAndRelByAbsolute(const Vector3d & a_Position, cChunk ** a_Chunk, Vector3i & a_Rel)
|
||||
{
|
||||
return GetChunkAndRelByAbsolute(Vector3i(FloorC(a_Position.x), FloorC(a_Position.y), FloorC(a_Position.z)), a_Chunk, a_Rel);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cChunk::GetChunkAndRelByAbsolute(const Vector3i & a_Position, cChunk ** a_Chunk, Vector3i & a_Rel)
|
||||
{
|
||||
*a_Chunk = this->GetNeighborChunk(a_Position.x, a_Position.z);
|
||||
if ((*a_Chunk == nullptr) || !(*a_Chunk)->IsValid())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
a_Rel.x = a_Position.x - (*a_Chunk)->GetPosX() * cChunkDef::Width;
|
||||
a_Rel.y = a_Position.y;
|
||||
a_Rel.z = a_Position.z - (*a_Chunk)->GetPosZ() * cChunkDef::Width;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
cChunk * cChunk::GetNeighborChunk(int a_BlockX, int a_BlockZ)
|
||||
{
|
||||
// Convert coords to relative, then call the relative version:
|
||||
@ -2652,7 +2677,7 @@ cChunk * cChunk::GetRelNeighborChunk(int a_RelX, int a_RelZ)
|
||||
// Going X first failed, but if the request is crossing Z as well, let's try the Z first later on.
|
||||
ReturnThis = false;
|
||||
}
|
||||
|
||||
|
||||
if (a_RelZ < 0)
|
||||
{
|
||||
if (m_NeighborZM != nullptr)
|
||||
@ -2671,7 +2696,7 @@ cChunk * cChunk::GetRelNeighborChunk(int a_RelX, int a_RelZ)
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
return (ReturnThis ? this : nullptr);
|
||||
}
|
||||
|
||||
@ -2691,7 +2716,7 @@ cChunk * cChunk::GetRelNeighborChunkAdjustCoords(int & a_RelX, int & a_RelZ) con
|
||||
{
|
||||
return ToReturn;
|
||||
}
|
||||
|
||||
|
||||
// Request for a different chunk, calculate chunk offset:
|
||||
int RelX = a_RelX; // Make a local copy of the coords (faster access)
|
||||
int RelZ = a_RelZ;
|
||||
@ -2721,7 +2746,7 @@ cChunk * cChunk::GetRelNeighborChunkAdjustCoords(int & a_RelX, int & a_RelZ) con
|
||||
a_RelZ = RelZ;
|
||||
return ToReturn;
|
||||
}
|
||||
|
||||
|
||||
// The chunk cannot be walked through neighbors, find it through the chunkmap:
|
||||
int AbsX = a_RelX + m_PosX * Width;
|
||||
int AbsZ = a_RelZ + m_PosZ * Width;
|
||||
|
149
src/Chunk.h
149
src/Chunk.h
@ -63,7 +63,9 @@ typedef cItemCallback<cCommandBlockEntity> cCommandBlockCallback;
|
||||
typedef cItemCallback<cMobHeadEntity> cMobHeadCallback;
|
||||
typedef cItemCallback<cFlowerPotEntity> cFlowerPotCallback;
|
||||
|
||||
|
||||
// A convenience macro for calling GetChunkAndRelByAbsolute.
|
||||
#define PREPARE_REL_AND_CHUNK(Position, OriginalChunk) cChunk * Chunk; Vector3i Rel; bool RelSuccess = (OriginalChunk).GetChunkAndRelByAbsolute(Position, &Chunk, Rel);
|
||||
#define PREPARE_BLOCKDATA BLOCKTYPE BlockType; NIBBLETYPE BlockMeta;
|
||||
|
||||
|
||||
// This class is not to be used directly
|
||||
@ -109,9 +111,9 @@ public:
|
||||
bool IsDirty(void) const {return m_IsDirty; }
|
||||
|
||||
bool CanUnload(void);
|
||||
|
||||
|
||||
bool IsLightValid(void) const {return m_IsLightValid; }
|
||||
|
||||
|
||||
/*
|
||||
To save a chunk, the WSSchema must:
|
||||
1. Mark the chunk as being saved (MarkSaving())
|
||||
@ -126,34 +128,34 @@ public:
|
||||
/** Marks the chunk as failed to load.
|
||||
If m_ShouldGenerateIfLoadFailed is set, queues the chunk for generating. */
|
||||
void MarkLoadFailed(void);
|
||||
|
||||
|
||||
/** Gets all chunk data, calls the a_Callback's methods for each data type */
|
||||
void GetAllData(cChunkDataCallback & a_Callback);
|
||||
|
||||
|
||||
/** Sets all chunk data as either loaded from the storage or generated.
|
||||
BlockLight and BlockSkyLight are optional, if not present, chunk will be marked as unlighted.
|
||||
Modifies the BlockEntity list in a_SetChunkData - moves the block entities into the chunk. */
|
||||
void SetAllData(cSetChunkData & a_SetChunkData);
|
||||
|
||||
|
||||
void SetLight(
|
||||
const cChunkDef::BlockNibbles & a_BlockLight,
|
||||
const cChunkDef::BlockNibbles & a_SkyLight
|
||||
);
|
||||
|
||||
|
||||
/** Copies m_BlockData into a_BlockTypes, only the block types */
|
||||
void GetBlockTypes(BLOCKTYPE * a_BlockTypes);
|
||||
|
||||
|
||||
/** Writes the specified cBlockArea at the coords specified. Note that the coords may extend beyond the chunk! */
|
||||
void WriteBlockArea(cBlockArea & a_Area, int a_MinBlockX, int a_MinBlockY, int a_MinBlockZ, int a_DataTypes);
|
||||
|
||||
/** Returns true if there is a block entity at the coords specified */
|
||||
bool HasBlockEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ);
|
||||
|
||||
|
||||
/** Sets or resets the internal flag that prevents chunk from being unloaded.
|
||||
The flag is cumulative - it can be set multiple times and then needs to be un-set that many times
|
||||
before the chunk is unloadable again. */
|
||||
void Stay(bool a_Stay = true);
|
||||
|
||||
|
||||
/** Recence all mobs proximities to players in order to know what to do with them */
|
||||
void CollectMobCensus(cMobCensus & toFill);
|
||||
|
||||
@ -161,22 +163,22 @@ public:
|
||||
void SpawnMobs(cMobSpawner & a_MobSpawner);
|
||||
|
||||
void Tick(std::chrono::milliseconds a_Dt);
|
||||
|
||||
|
||||
/** Ticks a single block. Used by cWorld::TickQueuedBlocks() to tick the queued blocks */
|
||||
void TickBlock(int a_RelX, int a_RelY, int a_RelZ);
|
||||
|
||||
int GetPosX(void) const { return m_PosX; }
|
||||
int GetPosZ(void) const { return m_PosZ; }
|
||||
|
||||
|
||||
cWorld * GetWorld(void) const { return m_World; }
|
||||
|
||||
void SetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, bool a_SendToClients = true);
|
||||
// SetBlock() does a lot of work (heightmap, tickblocks, blockentities) so a BlockIdx version doesn't make sense
|
||||
void SetBlock( const Vector3i & a_RelBlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) { SetBlock( a_RelBlockPos.x, a_RelBlockPos.y, a_RelBlockPos.z, a_BlockType, a_BlockMeta); }
|
||||
|
||||
|
||||
/** Queues block for ticking (m_ToTickQueue) */
|
||||
void QueueTickBlock(int a_RelX, int a_RelY, int a_RelZ);
|
||||
|
||||
|
||||
/** Queues all 6 neighbors of the specified block for ticking (m_ToTickQueue). If any are outside the chunk, relays the checking to the proper neighboring chunk */
|
||||
void QueueTickBlockNeighbors(int a_RelX, int a_RelY, int a_RelZ);
|
||||
|
||||
@ -185,18 +187,38 @@ public:
|
||||
BLOCKTYPE GetBlock(const Vector3i & a_RelCoords) const { return GetBlock(a_RelCoords.x, a_RelCoords.y, a_RelCoords.z); }
|
||||
void GetBlockTypeMeta(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta) const;
|
||||
void GetBlockInfo (int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_Meta, NIBBLETYPE & a_SkyLight, NIBBLETYPE & a_BlockLight);
|
||||
|
||||
|
||||
/** Convert absolute coordinates into relative coordinates.
|
||||
Returns false on failure to obtain a valid chunk. Returns true otherwise.
|
||||
@param a_Position The position you'd like to convert, a_Position need not be in the calling chunk and can safely be out
|
||||
of its bounds, but for best performance, it should not be too far from the calling chunk.
|
||||
@param a_Chunk Returns the chunk in which a_Position is in. If a_Position is within the calling chunk's bounds,
|
||||
returns the calling chunk. For best performance, a_Position shouldn't be too far from the calling chunk.
|
||||
@param a_Rel Returns the converted relative position. Note that it is relative to the returned a_Chunk.
|
||||
The vector will not be modified if the function returns false. */
|
||||
bool GetChunkAndRelByAbsolute(const Vector3d & a_Position, cChunk ** a_Chunk, Vector3i & a_Rel);
|
||||
|
||||
/** Convert absolute coordinates into relative coordinates.
|
||||
Returns false on failure to obtain a valid chunk. Returns true otherwise.
|
||||
@param a_Position The position you'd like to convert, a_Position need not be in the calling chunk and can safely be out
|
||||
of its bounds, but for best performance, it should not be too far from the calling chunk.
|
||||
@param a_Chunk Returns the chunk in which a_Position is in. If a_Position is within the calling chunk's bounds,
|
||||
returns the calling chunk. For best performance, a_Position shouldn't be too far from the calling chunk.
|
||||
@param a_Rel Returns the converted relative position. Note that it is relative to the returned a_Chunk.
|
||||
The vector will not be modified if the function returns false. */
|
||||
bool GetChunkAndRelByAbsolute(const Vector3i & a_Position, cChunk ** a_Chunk, Vector3i & a_Rel);
|
||||
|
||||
/** Returns the chunk into which the specified block belongs, by walking the neighbors.
|
||||
Will return self if appropriate. Returns nullptr if not reachable through neighbors.
|
||||
*/
|
||||
cChunk * GetNeighborChunk(int a_BlockX, int a_BlockZ);
|
||||
|
||||
|
||||
/**
|
||||
Returns the chunk into which the relatively-specified block belongs, by walking the neighbors.
|
||||
Will return self if appropriate. Returns nullptr if not reachable through neighbors.
|
||||
*/
|
||||
cChunk * GetRelNeighborChunk(int a_RelX, int a_RelZ);
|
||||
|
||||
|
||||
/**
|
||||
Returns the chunk into which the relatively-specified block belongs.
|
||||
Also modifies the relative coords from this-relative to return-relative.
|
||||
@ -204,19 +226,19 @@ public:
|
||||
Will try walking the neighbors first; if that fails, will query the chunkmap
|
||||
*/
|
||||
cChunk * GetRelNeighborChunkAdjustCoords(int & a_RelX, int & a_RelZ) const;
|
||||
|
||||
|
||||
EMCSBiome GetBiomeAt(int a_RelX, int a_RelZ) const {return cChunkDef::GetBiome(m_BiomeMap, a_RelX, a_RelZ); }
|
||||
|
||||
|
||||
/** Sets the biome at the specified relative coords.
|
||||
Doesn't resend the chunk to clients. */
|
||||
void SetBiomeAt(int a_RelX, int a_RelZ, EMCSBiome a_Biome);
|
||||
|
||||
|
||||
/** Sets the biome in the specified relative coords area. All the coords are inclusive.
|
||||
Sends the chunk to all relevant clients. */
|
||||
void SetAreaBiome(int a_MinRelX, int a_MaxRelX, int a_MinRelZ, int a_MaxRelZ, EMCSBiome a_Biome);
|
||||
|
||||
|
||||
void CollectPickupsByPlayer(cPlayer & a_Player);
|
||||
|
||||
|
||||
/** Sets the sign text. Returns true if successful. Also sends update packets to all clients in the chunk */
|
||||
bool SetSignLines(int a_RelX, int a_RelY, int a_RelZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4);
|
||||
|
||||
@ -226,20 +248,20 @@ public:
|
||||
|
||||
/** Adds a client to the chunk; returns true if added, false if already there */
|
||||
bool AddClient(cClientHandle * a_Client);
|
||||
|
||||
|
||||
/** Removes the specified client from the chunk; ignored if client not in chunk. */
|
||||
void RemoveClient(cClientHandle * a_Client);
|
||||
|
||||
|
||||
/** Returns true if the specified client is present in this chunk. */
|
||||
bool HasClient(cClientHandle * a_Client);
|
||||
|
||||
|
||||
/** Returns true if theres any client in the chunk; false otherwise */
|
||||
bool HasAnyClients(void) const;
|
||||
|
||||
void AddEntity(cEntity * a_Entity);
|
||||
void RemoveEntity(cEntity * a_Entity);
|
||||
bool HasEntity(UInt32 a_EntityID);
|
||||
|
||||
|
||||
/** Calls the callback for each entity; returns true if all entities processed, false if the callback aborted by returning true */
|
||||
bool ForEachEntity(cEntityCallback & a_Callback); // Lua-accessible
|
||||
|
||||
@ -270,10 +292,10 @@ public:
|
||||
|
||||
/** Calls the callback for each furnace; returns true if all furnaces processed, false if the callback aborted by returning true */
|
||||
bool ForEachFurnace(cFurnaceCallback & a_Callback); // Lua-accessible
|
||||
|
||||
|
||||
/** Calls the callback for the block entity at the specified coords; returns false if there's no block entity at those coords, true if found */
|
||||
bool DoWithBlockEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBlockEntityCallback & a_Callback); // Lua-acessible
|
||||
|
||||
|
||||
/** Calls the callback for the beacon at the specified coords; returns false if there's no beacon at those coords, true if found */
|
||||
bool DoWithBeaconAt(int a_BlockX, int a_BlockY, int a_BlockZ, cBeaconCallback & a_Callback); // Lua-acessible
|
||||
|
||||
@ -300,7 +322,7 @@ public:
|
||||
|
||||
/** Calls the callback for the command block at the specified coords; returns false if there's no command block at those coords or callback returns true, returns true if found */
|
||||
bool DoWithCommandBlockAt(int a_BlockX, int a_BlockY, int a_BlockZ, cCommandBlockCallback & a_Callback);
|
||||
|
||||
|
||||
/** Calls the callback for the mob head block at the specified coords; returns false if there's no mob head block at those coords or callback returns true, returns true if found */
|
||||
bool DoWithMobHeadAt(int a_BlockX, int a_BlockY, int a_BlockZ, cMobHeadCallback & a_Callback);
|
||||
|
||||
@ -341,14 +363,14 @@ public:
|
||||
void BroadcastSpawnEntity (cEntity & a_Entity, const cClientHandle * a_Exclude = nullptr);
|
||||
void BroadcastThunderbolt (int a_BlockX, int a_BlockY, int a_BlockZ, const cClientHandle * a_Exclude = nullptr);
|
||||
void BroadcastUseBed (const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ);
|
||||
|
||||
|
||||
void SendBlockEntity (int a_BlockX, int a_BlockY, int a_BlockZ, cClientHandle & a_Client);
|
||||
|
||||
Vector3i PositionToWorldPosition(const Vector3i & a_RelPos)
|
||||
{
|
||||
return PositionToWorldPosition(a_RelPos.x, a_RelPos.y, a_RelPos.z);
|
||||
}
|
||||
|
||||
|
||||
void PositionToWorldPosition(int a_RelX, int a_RelY, int a_RelZ, int & a_BlockX, int & a_BlockY, int & a_BlockZ);
|
||||
Vector3i PositionToWorldPosition(int a_RelX, int a_RelY, int a_RelZ);
|
||||
|
||||
@ -357,7 +379,7 @@ public:
|
||||
m_IsDirty = true;
|
||||
m_IsSaving = false;
|
||||
}
|
||||
|
||||
|
||||
/** Sets the blockticking to start at the specified block. Only one blocktick may be set, second call overwrites the first call */
|
||||
inline void SetNextBlockTick(int a_RelX, int a_RelY, int a_RelZ)
|
||||
{
|
||||
@ -365,7 +387,7 @@ public:
|
||||
m_BlockTickY = a_RelY;
|
||||
m_BlockTickZ = a_RelZ;
|
||||
}
|
||||
|
||||
|
||||
inline NIBBLETYPE GetMeta(int a_RelX, int a_RelY, int a_RelZ) const
|
||||
{
|
||||
return m_ChunkData.GetMeta(a_RelX, a_RelY, a_RelZ);
|
||||
@ -377,23 +399,32 @@ public:
|
||||
{
|
||||
MarkDirty();
|
||||
m_IsRedstoneDirty = true;
|
||||
|
||||
|
||||
m_PendingSendBlocks.push_back(sSetBlock(m_PosX, m_PosZ, a_RelX, a_RelY, a_RelZ, GetBlock(a_RelX, a_RelY, a_RelZ), a_Meta));
|
||||
}
|
||||
}
|
||||
|
||||
/** Light alterations based on time */
|
||||
NIBBLETYPE GetTimeAlteredLight(NIBBLETYPE a_Skylight) const;
|
||||
|
||||
/** Get the level of artificial light illuminating the block (0 - 15) */
|
||||
inline NIBBLETYPE GetBlockLight(int a_RelX, int a_RelY, int a_RelZ) const {return m_ChunkData.GetBlockLight(a_RelX, a_RelY, a_RelZ); }
|
||||
|
||||
/** Get the level of sky light illuminating the block (0 - 15) independent of daytime. */
|
||||
inline NIBBLETYPE GetSkyLight (int a_RelX, int a_RelY, int a_RelZ) const {return m_ChunkData.GetSkyLight(a_RelX, a_RelY, a_RelZ); }
|
||||
|
||||
|
||||
/** Get the level of sky light illuminating the block (0 - 15), taking daytime into a account. */
|
||||
inline NIBBLETYPE GetSkyLightAltered (int a_RelX, int a_RelY, int a_RelZ) const {return GetTimeAlteredLight(m_ChunkData.GetSkyLight(a_RelX, a_RelY, a_RelZ)); }
|
||||
|
||||
/** Same as GetBlock(), but relative coords needn't be in this chunk (uses m_Neighbor-s or m_ChunkMap in such a case); returns true on success */
|
||||
bool UnboundedRelGetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta) const;
|
||||
|
||||
|
||||
/** Same as GetBlockType(), but relative coords needn't be in this chunk (uses m_Neighbor-s or m_ChunkMap in such a case); returns true on success */
|
||||
bool UnboundedRelGetBlockType(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE & a_BlockType) const;
|
||||
|
||||
|
||||
/** Same as GetBlockMeta(), but relative coords needn't be in this chunk (uses m_Neighbor-s or m_ChunkMap in such a case); returns true on success */
|
||||
bool UnboundedRelGetBlockMeta(int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE & a_BlockMeta) const;
|
||||
|
||||
|
||||
/** Same as GetBlockBlockLight(), but relative coords needn't be in this chunk (uses m_Neighbor-s or m_ChunkMap in such a case); returns true on success */
|
||||
bool UnboundedRelGetBlockBlockLight(int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE & a_BlockLight) const;
|
||||
|
||||
@ -408,12 +439,10 @@ public:
|
||||
|
||||
/** Same as FastSetBlock(), but relative coords needn't be in this chunk (uses m_Neighbor-s or m_ChunkMap in such a case); returns true on success */
|
||||
bool UnboundedRelFastSetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta);
|
||||
|
||||
|
||||
/** Same as QueueTickBlock(), but relative coords needn't be in this chunk (uses m_Neighbor-s in such a case), ignores unsuccessful attempts */
|
||||
void UnboundedQueueTickBlock(int a_RelX, int a_RelY, int a_RelZ);
|
||||
|
||||
/** Light alterations based on time */
|
||||
NIBBLETYPE GetTimeAlteredLight(NIBBLETYPE a_Skylight) const;
|
||||
|
||||
|
||||
// Per-chunk simulator data:
|
||||
@ -429,11 +458,11 @@ public:
|
||||
|
||||
cBlockEntity * GetBlockEntity(int a_BlockX, int a_BlockY, int a_BlockZ);
|
||||
cBlockEntity * GetBlockEntity(const Vector3i & a_BlockPos) { return GetBlockEntity(a_BlockPos.x, a_BlockPos.y, a_BlockPos.z); }
|
||||
|
||||
|
||||
/** Returns true if the chunk should be ticked in the tick-thread.
|
||||
Checks if there are any clients and if the always-tick flag is set */
|
||||
bool ShouldBeTicked(void) const;
|
||||
|
||||
|
||||
/** Increments (a_AlwaysTicked == true) or decrements (false) the m_AlwaysTicked counter.
|
||||
If the m_AlwaysTicked counter is greater than zero, the chunk is ticked in the tick-thread regardless of
|
||||
whether it has any clients or not.
|
||||
@ -450,7 +479,7 @@ public:
|
||||
private:
|
||||
|
||||
friend class cChunkMap;
|
||||
|
||||
|
||||
struct sSetBlockQueueItem
|
||||
{
|
||||
Int64 m_Tick;
|
||||
@ -458,7 +487,7 @@ private:
|
||||
BLOCKTYPE m_BlockType;
|
||||
NIBBLETYPE m_BlockMeta;
|
||||
BLOCKTYPE m_PreviousType;
|
||||
|
||||
|
||||
sSetBlockQueueItem(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Int64 a_Tick, BLOCKTYPE a_PreviousBlockType) :
|
||||
m_Tick(a_Tick), m_RelX(a_RelX), m_RelY(a_RelY), m_RelZ(a_RelZ), m_BlockType(a_BlockType), m_BlockMeta(a_BlockMeta), m_PreviousType(a_PreviousBlockType)
|
||||
{
|
||||
@ -466,7 +495,7 @@ private:
|
||||
} ;
|
||||
|
||||
typedef std::vector<sSetBlockQueueItem> sSetBlockQueueVector;
|
||||
|
||||
|
||||
|
||||
/** Holds the presence status of the chunk - if it is present, or in the loader / generator queue, or unloaded */
|
||||
ePresence m_Presence;
|
||||
@ -478,15 +507,15 @@ private:
|
||||
bool m_IsDirty; // True if the chunk has changed since it was last saved
|
||||
bool m_IsSaving; // True if the chunk is being saved
|
||||
bool m_HasLoadFailed; // True if chunk failed to load and hasn't been generated yet since then
|
||||
|
||||
|
||||
std::vector<Vector3i> m_ToTickBlocks;
|
||||
sSetBlockVector m_PendingSendBlocks; ///< Blocks that have changed and need to be sent to all clients
|
||||
|
||||
|
||||
// A critical section is not needed, because all chunk access is protected by its parent ChunkMap's csLayers
|
||||
std::vector<cClientHandle *> m_LoadedByClient;
|
||||
cEntityList m_Entities;
|
||||
cBlockEntityList m_BlockEntities;
|
||||
|
||||
|
||||
/** Number of times the chunk has been requested to stay (by various cChunkStay objects); if zero, the chunk can be unloaded */
|
||||
int m_StayCount;
|
||||
|
||||
@ -500,12 +529,12 @@ private:
|
||||
cChunkDef::BiomeMap m_BiomeMap;
|
||||
|
||||
int m_BlockTickX, m_BlockTickY, m_BlockTickZ;
|
||||
|
||||
|
||||
cChunk * m_NeighborXM; // Neighbor at [X - 1, Z]
|
||||
cChunk * m_NeighborXP; // Neighbor at [X + 1, Z]
|
||||
cChunk * m_NeighborZM; // Neighbor at [X, Z - 1]
|
||||
cChunk * m_NeighborZP; // Neighbor at [X, Z + 1]
|
||||
|
||||
|
||||
// Per-chunk simulator data:
|
||||
cFireSimulatorChunkData m_FireSimulatorData;
|
||||
cFluidSimulatorData * m_WaterSimulatorData;
|
||||
@ -517,12 +546,12 @@ private:
|
||||
|
||||
/** Indicates if simulate-once blocks should be updated by the redstone simulator */
|
||||
bool m_IsRedstoneDirty;
|
||||
|
||||
|
||||
/** If greater than zero, the chunk is ticked even if it has no clients.
|
||||
Manipulated by the SetAlwaysTicked() function, allows for nested calls of the function.
|
||||
This is the support for plugin-accessible chunk tick forcing. */
|
||||
int m_AlwaysTicked;
|
||||
|
||||
|
||||
|
||||
// Pick up a random block of this chunk
|
||||
void GetRandomBlockCoords(int & a_X, int & a_Y, int & a_Z);
|
||||
@ -533,31 +562,31 @@ private:
|
||||
|
||||
/** Creates a block entity for each block that needs a block entity and doesn't have one in the list */
|
||||
void CreateBlockEntities(void);
|
||||
|
||||
|
||||
/** Wakes up each simulator for its specific blocks; through all the blocks in the chunk */
|
||||
void WakeUpSimulators(void);
|
||||
|
||||
/** Sends m_PendingSendBlocks to all clients */
|
||||
void BroadcastPendingBlockChanges(void);
|
||||
|
||||
|
||||
/** Checks the block scheduled for checking in m_ToTickBlocks[] */
|
||||
void CheckBlocks();
|
||||
|
||||
|
||||
/** Ticks several random blocks in the chunk */
|
||||
void TickBlocks(void);
|
||||
|
||||
|
||||
/** Adds snow to the top of snowy biomes and hydrates farmland / fills cauldrons in rainy biomes */
|
||||
void ApplyWeatherToTop(void);
|
||||
|
||||
|
||||
/** Grows sugarcane by the specified number of blocks, but no more than 3 blocks high (used by both bonemeal and ticking) */
|
||||
void GrowSugarcane (int a_RelX, int a_RelY, int a_RelZ, int a_NumBlocks);
|
||||
|
||||
|
||||
/** Grows cactus by the specified number of blocks, but no more than 3 blocks high (used by both bonemeal and ticking) */
|
||||
void GrowCactus (int a_RelX, int a_RelY, int a_RelZ, int a_NumBlocks);
|
||||
|
||||
/** Grows a melon or a pumpkin next to the block specified (assumed to be the stem) */
|
||||
void GrowMelonPumpkin(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType, MTRand & a_Random);
|
||||
|
||||
|
||||
/** Called by Tick() when an entity moves out of this chunk into a neighbor; moves the entity and sends spawn / despawn packet to clients */
|
||||
void MoveEntityToNewChunk(cEntity * a_Entity);
|
||||
};
|
||||
|
@ -37,7 +37,6 @@
|
||||
|
||||
|
||||
|
||||
|
||||
class cWorld;
|
||||
class cClientHandle;
|
||||
class cPlayer;
|
||||
|
@ -36,11 +36,11 @@ void cAggressiveMonster::InStateChasing(std::chrono::milliseconds a_Dt, cChunk &
|
||||
|
||||
|
||||
|
||||
void cAggressiveMonster::EventSeePlayer(cEntity * a_Entity)
|
||||
void cAggressiveMonster::EventSeePlayer(cEntity * a_Entity, cChunk & a_Chunk)
|
||||
{
|
||||
if (!static_cast<cPlayer *>(a_Entity)->IsGameModeCreative())
|
||||
{
|
||||
super::EventSeePlayer(a_Entity);
|
||||
super::EventSeePlayer(a_Entity, a_Chunk);
|
||||
m_EMState = CHASING;
|
||||
}
|
||||
}
|
||||
@ -59,7 +59,7 @@ void cAggressiveMonster::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
|
||||
}
|
||||
else
|
||||
{
|
||||
CheckEventSeePlayer();
|
||||
CheckEventSeePlayer(a_Chunk);
|
||||
}
|
||||
|
||||
if (m_Target == nullptr)
|
||||
|
@ -19,7 +19,7 @@ public:
|
||||
virtual void Tick (std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override;
|
||||
virtual void InStateChasing(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override;
|
||||
|
||||
virtual void EventSeePlayer(cEntity *) override;
|
||||
virtual void EventSeePlayer(cEntity * a_Player, cChunk & a_Chunk) override;
|
||||
|
||||
/** Try to perform attack
|
||||
returns true if attack was deemed successful (hit player, fired projectile, creeper exploded, etc.) even if it didn't actually do damage
|
||||
|
@ -28,32 +28,32 @@ public:
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
Vector3d Direction = m_EndermanPos - a_Player->GetPosition();
|
||||
|
||||
|
||||
// Don't check players who are more then SightDistance (64) blocks away
|
||||
if (Direction.Length() > m_SightDistance)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Don't check if the player has a pumpkin on his head
|
||||
if (a_Player->GetEquippedHelmet().m_ItemType == E_BLOCK_PUMPKIN)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Vector3d LookVector = a_Player->GetLookVector();
|
||||
double dot = Direction.Dot(LookVector);
|
||||
|
||||
|
||||
// 0.09 rad ~ 5 degrees
|
||||
// If the player's crosshair is within 5 degrees of the enderman, it counts as looking
|
||||
if (dot <= cos(0.09))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
cTracer LineOfSight(a_Player->GetWorld());
|
||||
if (LineOfSight.Trace(m_EndermanPos, Direction, static_cast<int>(Direction.Length())))
|
||||
{
|
||||
@ -64,7 +64,7 @@ public:
|
||||
m_Player = a_Player;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
cPlayer * GetPlayer(void) const { return m_Player; }
|
||||
|
||||
protected:
|
||||
@ -102,7 +102,7 @@ void cEnderman::GetDrops(cItems & a_Drops, cEntity * a_Killer)
|
||||
|
||||
|
||||
|
||||
void cEnderman::CheckEventSeePlayer()
|
||||
void cEnderman::CheckEventSeePlayer(cChunk & a_Chunk)
|
||||
{
|
||||
if (m_Target != nullptr)
|
||||
{
|
||||
@ -114,7 +114,7 @@ void cEnderman::CheckEventSeePlayer()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
ASSERT(Callback.GetPlayer() != nullptr);
|
||||
|
||||
if (!CheckLight())
|
||||
@ -126,7 +126,7 @@ void cEnderman::CheckEventSeePlayer()
|
||||
|
||||
if (!Callback.GetPlayer()->IsGameModeCreative())
|
||||
{
|
||||
cMonster::EventSeePlayer(Callback.GetPlayer());
|
||||
cMonster::EventSeePlayer(Callback.GetPlayer(), a_Chunk);
|
||||
m_EMState = CHASING;
|
||||
m_bIsScreaming = true;
|
||||
GetWorld()->BroadcastEntityMetadata(*this);
|
||||
@ -145,7 +145,7 @@ void cEnderman::CheckEventLostPlayer(void)
|
||||
EventLosePlayer();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -11,14 +11,14 @@ class cEnderman :
|
||||
public cPassiveAggressiveMonster
|
||||
{
|
||||
typedef cPassiveAggressiveMonster super;
|
||||
|
||||
|
||||
public:
|
||||
cEnderman(void);
|
||||
|
||||
CLASS_PROTODEF(cEnderman)
|
||||
|
||||
virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = nullptr) override;
|
||||
virtual void CheckEventSeePlayer(void) override;
|
||||
virtual void CheckEventSeePlayer(cChunk & a_Chunk) override;
|
||||
virtual void CheckEventLostPlayer(void) override;
|
||||
virtual void EventLosePlayer(void) override;
|
||||
virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override;
|
||||
|
@ -560,14 +560,14 @@ void cMonster::OnRightClicked(cPlayer & a_Player)
|
||||
|
||||
// Checks to see if EventSeePlayer should be fired
|
||||
// monster sez: Do I see the player
|
||||
void cMonster::CheckEventSeePlayer(void)
|
||||
void cMonster::CheckEventSeePlayer(cChunk & a_Chunk)
|
||||
{
|
||||
// TODO: Rewrite this to use cWorld's DoWithPlayers()
|
||||
cPlayer * Closest = m_World->FindClosestPlayer(GetPosition(), static_cast<float>(m_SightDistance), false);
|
||||
|
||||
if (Closest != nullptr)
|
||||
{
|
||||
EventSeePlayer(Closest);
|
||||
EventSeePlayer(Closest, a_Chunk);
|
||||
}
|
||||
}
|
||||
|
||||
@ -596,7 +596,7 @@ void cMonster::CheckEventLostPlayer(void)
|
||||
|
||||
// What to do if player is seen
|
||||
// default to change state to chasing
|
||||
void cMonster::EventSeePlayer(cEntity * a_SeenPlayer)
|
||||
void cMonster::EventSeePlayer(cEntity * a_SeenPlayer, cChunk & a_Chunk)
|
||||
{
|
||||
m_Target = a_SeenPlayer;
|
||||
}
|
||||
|
@ -67,8 +67,8 @@ public:
|
||||
eFamily GetMobFamily(void) const;
|
||||
// tolua_end
|
||||
|
||||
virtual void CheckEventSeePlayer(void);
|
||||
virtual void EventSeePlayer(cEntity * a_Player);
|
||||
virtual void CheckEventSeePlayer(cChunk & a_Chunk);
|
||||
virtual void EventSeePlayer(cEntity * a_Entity, cChunk & a_Chunk);
|
||||
|
||||
/** Reads the monster configuration for the specified monster name and assigns it to this object. */
|
||||
void GetMonsterConfig(const AString & a_Name);
|
||||
|
@ -25,7 +25,7 @@ bool cPassiveAggressiveMonster::DoTakeDamage(TakeDamageInfo & a_TDI)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if ((m_Target != nullptr) && (m_Target->IsPlayer()))
|
||||
{
|
||||
if (!static_cast<cPlayer *>(m_Target)->IsGameModeCreative())
|
||||
@ -39,7 +39,7 @@ bool cPassiveAggressiveMonster::DoTakeDamage(TakeDamageInfo & a_TDI)
|
||||
|
||||
|
||||
|
||||
void cPassiveAggressiveMonster::EventSeePlayer(cEntity *)
|
||||
void cPassiveAggressiveMonster::EventSeePlayer(cEntity *, cChunk & a_Chunk)
|
||||
{
|
||||
// don't do anything, neutral mobs don't react to just seeing the player
|
||||
}
|
||||
|
@ -11,12 +11,12 @@ class cPassiveAggressiveMonster :
|
||||
public cAggressiveMonster
|
||||
{
|
||||
typedef cAggressiveMonster super;
|
||||
|
||||
|
||||
public:
|
||||
cPassiveAggressiveMonster(const AString & a_ConfigName, eMonsterType a_MobType, const AString & a_SoundHurt, const AString & a_SoundDeath, double a_Width, double a_Height);
|
||||
|
||||
virtual bool DoTakeDamage(TakeDamageInfo & a_TDI) override;
|
||||
virtual void EventSeePlayer(cEntity *) override;
|
||||
virtual void EventSeePlayer(cEntity *, cChunk & a_Chunk) override;
|
||||
} ;
|
||||
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
#include "../World.h"
|
||||
#include "../Entities/Player.h"
|
||||
|
||||
#include "../Chunk.h"
|
||||
|
||||
|
||||
cSpider::cSpider(void) :
|
||||
@ -35,17 +35,22 @@ void cSpider::GetDrops(cItems & a_Drops, cEntity * a_Killer)
|
||||
|
||||
|
||||
|
||||
void cSpider::EventSeePlayer(cEntity * a_Entity)
|
||||
void cSpider::EventSeePlayer(cEntity * a_Entity, cChunk & a_Chunk)
|
||||
{
|
||||
if (!GetWorld()->IsChunkLighted(GetChunkX(), GetChunkZ()))
|
||||
{
|
||||
GetWorld()->QueueLightChunk(GetChunkX(), GetChunkZ());
|
||||
return;
|
||||
}
|
||||
|
||||
if (!static_cast<cPlayer *>(a_Entity)->IsGameModeCreative() && (GetWorld()->GetBlockBlockLight(this->GetPosition()) <= 9))
|
||||
PREPARE_REL_AND_CHUNK(GetPosition(), a_Chunk);
|
||||
if (!RelSuccess)
|
||||
{
|
||||
super::EventSeePlayer(a_Entity);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!static_cast<cPlayer *>(a_Entity)->IsGameModeCreative() && (Chunk->GetSkyLightAltered(Rel.x, Rel.y, Rel.z) <= 9))
|
||||
{
|
||||
super::EventSeePlayer(a_Entity, a_Chunk);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -11,14 +11,14 @@ class cSpider :
|
||||
public cAggressiveMonster
|
||||
{
|
||||
typedef cAggressiveMonster super;
|
||||
|
||||
|
||||
public:
|
||||
cSpider(void);
|
||||
|
||||
CLASS_PROTODEF(cSpider)
|
||||
|
||||
virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = nullptr) override;
|
||||
virtual void EventSeePlayer(cEntity *) override;
|
||||
virtual void EventSeePlayer(cEntity *, cChunk & a_Chunk) override;
|
||||
virtual bool DoTakeDamage(TakeDamageInfo & a_TDI) override;
|
||||
} ;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user