summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/BlockEntities/BlockEntity.h2
-rw-r--r--src/BlockEntities/MobSpawnerEntity.cpp33
-rw-r--r--src/MobSpawner.cpp217
-rw-r--r--src/MobSpawner.h2
-rw-r--r--src/WorldStorage/NBTChunkSerializer.cpp1
-rwxr-xr-xsrc/WorldStorage/WSSAnvil.cpp25
6 files changed, 137 insertions, 143 deletions
diff --git a/src/BlockEntities/BlockEntity.h b/src/BlockEntities/BlockEntity.h
index 1933ed891..c133c186c 100644
--- a/src/BlockEntities/BlockEntity.h
+++ b/src/BlockEntities/BlockEntity.h
@@ -122,7 +122,7 @@ public:
cWorld * GetWorld() const { return m_World; }
int GetChunkX() const { return FAST_FLOOR_DIV(m_Pos.x, cChunkDef::Width); }
- int GetChunkZ() const { return FAST_FLOOR_DIV(m_Pos.y, cChunkDef::Width); }
+ int GetChunkZ() const { return FAST_FLOOR_DIV(m_Pos.z, cChunkDef::Width); }
int GetRelX() const { return m_RelX; }
int GetRelZ() const { return m_RelZ; }
diff --git a/src/BlockEntities/MobSpawnerEntity.cpp b/src/BlockEntities/MobSpawnerEntity.cpp
index d7b72714d..f5fb5c3ff 100644
--- a/src/BlockEntities/MobSpawnerEntity.cpp
+++ b/src/BlockEntities/MobSpawnerEntity.cpp
@@ -124,14 +124,13 @@ void cMobSpawnerEntity::ResetTimer(void)
void cMobSpawnerEntity::SpawnEntity(void)
{
- int NearbyEntities = GetNearbyMonsterNum(m_Entity);
+ auto NearbyEntities = GetNearbyMonsterNum(m_Entity);
if (NearbyEntities >= 6)
{
ResetTimer();
return;
}
- auto MobType = m_Entity;
bool EntitiesSpawned = m_World->DoWithChunk(GetChunkX(), GetChunkZ(), [&](cChunk & a_Chunk)
{
auto & Random = GetRandomProvider();
@@ -144,38 +143,34 @@ void cMobSpawnerEntity::SpawnEntity(void)
break;
}
- Vector3i spawnRelPos(GetRelPos());
- spawnRelPos += Vector3i(
+ auto SpawnRelPos(GetRelPos());
+ SpawnRelPos += Vector3i(
static_cast<int>((Random.RandReal<double>() - Random.RandReal<double>()) * 4.0),
Random.RandInt(-1, 1),
static_cast<int>((Random.RandReal<double>() - Random.RandReal<double>()) * 4.0)
);
- auto chunk = a_Chunk.GetRelNeighborChunkAdjustCoords(spawnRelPos);
- if ((chunk == nullptr) || !chunk->IsValid())
+ auto Chunk = a_Chunk.GetRelNeighborChunkAdjustCoords(SpawnRelPos);
+ if ((Chunk == nullptr) || !Chunk->IsValid())
{
continue;
}
- EMCSBiome Biome = chunk->GetBiomeAt(spawnRelPos.x, spawnRelPos.z);
+ EMCSBiome Biome = Chunk->GetBiomeAt(SpawnRelPos.x, SpawnRelPos.z);
- if (cMobSpawner::CanSpawnHere(chunk, spawnRelPos, MobType, Biome))
+ if (cMobSpawner::CanSpawnHere(Chunk, SpawnRelPos, m_Entity, Biome, true))
{
- auto absPos = chunk->RelativeToAbsolute(spawnRelPos);
- auto monster = cMonster::NewMonsterFromType(MobType);
- if (monster == nullptr)
+ auto AbsPos = Chunk->RelativeToAbsolute(SpawnRelPos);
+ auto Monster = cMonster::NewMonsterFromType(m_Entity);
+ if (Monster == nullptr)
{
continue;
}
- monster->SetPosition(absPos);
- monster->SetYaw(Random.RandReal(360.0f));
- if (chunk->GetWorld()->SpawnMobFinalize(std::move(monster)) != cEntity::INVALID_ID)
+ Monster->SetPosition(AbsPos);
+ Monster->SetYaw(Random.RandReal(360.0f));
+ if (Chunk->GetWorld()->SpawnMobFinalize(std::move(Monster)) != cEntity::INVALID_ID)
{
HaveSpawnedEntity = true;
- m_World->BroadcastSoundParticleEffect(
- EffectID::PARTICLE_MOBSPAWN,
- absPos,
- 0
- );
+ m_World->BroadcastSoundParticleEffect(EffectID::PARTICLE_MOBSPAWN, AbsPos, 0);
NearbyEntities++;
}
}
diff --git a/src/MobSpawner.cpp b/src/MobSpawner.cpp
index 4d18b7358..b83cd247d 100644
--- a/src/MobSpawner.cpp
+++ b/src/MobSpawner.cpp
@@ -72,7 +72,7 @@ eMonsterType cMobSpawner::ChooseMobType(EMCSBiome a_Biome)
-bool cMobSpawner::CanSpawnHere(cChunk * a_Chunk, Vector3i a_RelPos, eMonsterType a_MobType, EMCSBiome a_Biome)
+bool cMobSpawner::CanSpawnHere(cChunk * a_Chunk, Vector3i a_RelPos, eMonsterType a_MobType, EMCSBiome a_Biome, bool a_DisableSolidBelowCheck)
{
if (a_Chunk == nullptr)
{
@@ -88,59 +88,50 @@ bool cMobSpawner::CanSpawnHere(cChunk * a_Chunk, Vector3i a_RelPos, eMonsterType
return false; // Make sure mobs do not spawn on bedrock.
}
- auto & random = GetRandomProvider();
- auto targetBlock = a_Chunk->GetBlock(a_RelPos);
+ auto & Random = GetRandomProvider();
+ auto TargetBlock = a_Chunk->GetBlock(a_RelPos);
- // If too close to any player, don't spawn anything
- auto absPos = a_Chunk->RelativeToAbsolute(a_RelPos);
- static const double rangeLimit = 24;
- if (a_Chunk->GetWorld()->DoWithNearestPlayer(absPos, rangeLimit, [](cPlayer & a_Player) -> bool
- {
- return true;
- })
- )
- {
- return false;
- }
-
- auto blockLight = a_Chunk->GetBlockLight(a_RelPos);
- auto skyLight = a_Chunk->GetSkyLight(a_RelPos);
- auto blockAbove = a_Chunk->GetBlock(a_RelPos.addedY(1));
- auto blockBelow = a_Chunk->GetBlock(a_RelPos.addedY(-1));
+ auto BlockLight = a_Chunk->GetBlockLight(a_RelPos);
+ auto SkyLight = a_Chunk->GetSkyLight(a_RelPos);
+ auto BlockAbove = a_Chunk->GetBlock(a_RelPos.addedY(1));
+ auto BlockBelow = a_Chunk->GetBlock(a_RelPos.addedY(-1));
- skyLight = a_Chunk->GetTimeAlteredLight(skyLight);
+ SkyLight = a_Chunk->GetTimeAlteredLight(SkyLight);
switch (a_MobType)
{
case mtBat:
{
- return (
+ return
+ (
(a_RelPos.y <= 63) &&
- (blockLight <= 4) &&
- (skyLight <= 4) &&
- (targetBlock == E_BLOCK_AIR) &&
- (!cBlockInfo::IsTransparent(blockAbove))
+ (BlockLight <= 4) &&
+ (SkyLight <= 4) &&
+ (TargetBlock == E_BLOCK_AIR) &&
+ (!cBlockInfo::IsTransparent(BlockAbove))
);
}
case mtBlaze:
{
- return (
- (targetBlock == E_BLOCK_AIR) &&
- (blockAbove == E_BLOCK_AIR) &&
- (!cBlockInfo::IsTransparent(blockBelow)) &&
- (random.RandBool())
+ return
+ (
+ (TargetBlock == E_BLOCK_AIR) &&
+ (BlockAbove == E_BLOCK_AIR) &&
+ ((!cBlockInfo::IsTransparent(BlockBelow)) || (a_DisableSolidBelowCheck)) &&
+ (Random.RandBool())
);
}
case mtCaveSpider:
{
- return (
- (targetBlock == E_BLOCK_AIR) &&
- (!cBlockInfo::IsTransparent(blockBelow)) &&
- (skyLight <= 7) &&
- (blockLight <= 7) &&
- (random.RandBool())
+ return
+ (
+ (TargetBlock == E_BLOCK_AIR) &&
+ ((!cBlockInfo::IsTransparent(BlockBelow)) || (a_DisableSolidBelowCheck)) &&
+ (SkyLight <= 7) &&
+ (BlockLight <= 7) &&
+ (Random.RandBool())
);
}
@@ -151,11 +142,12 @@ bool cMobSpawner::CanSpawnHere(cChunk * a_Chunk, Vector3i a_RelPos, eMonsterType
case mtRabbit:
case mtSheep:
{
- return (
- (targetBlock == E_BLOCK_AIR) &&
- (blockAbove == E_BLOCK_AIR) &&
- (blockBelow == E_BLOCK_GRASS) &&
- (skyLight >= 9)
+ return
+ (
+ (TargetBlock == E_BLOCK_AIR) &&
+ (BlockAbove == E_BLOCK_AIR) &&
+ (BlockBelow == E_BLOCK_GRASS) &&
+ (SkyLight >= 9)
);
}
@@ -163,13 +155,14 @@ bool cMobSpawner::CanSpawnHere(cChunk * a_Chunk, Vector3i a_RelPos, eMonsterType
case mtSkeleton:
case mtZombie:
{
- return (
- (targetBlock == E_BLOCK_AIR) &&
- (blockAbove == E_BLOCK_AIR) &&
- (!cBlockInfo::IsTransparent(blockBelow)) &&
- (skyLight <= 7) &&
- (blockLight <= 7) &&
- (random.RandBool())
+ return
+ (
+ (TargetBlock == E_BLOCK_AIR) &&
+ (BlockAbove == E_BLOCK_AIR) &&
+ ((!cBlockInfo::IsTransparent(BlockBelow)) || (a_DisableSolidBelowCheck)) &&
+ (SkyLight <= 7) &&
+ (BlockLight <= 7) &&
+ (Random.RandBool())
);
}
@@ -181,13 +174,14 @@ bool cMobSpawner::CanSpawnHere(cChunk * a_Chunk, Vector3i a_RelPos, eMonsterType
if (blockTop == E_BLOCK_AIR)
{
blockTop = a_Chunk->GetBlock(a_RelPos.addedY(3));
- return (
- (targetBlock == E_BLOCK_AIR) &&
- (blockAbove == E_BLOCK_AIR) &&
+ return
+ (
+ (TargetBlock == E_BLOCK_AIR) &&
+ (BlockAbove == E_BLOCK_AIR) &&
(blockTop == E_BLOCK_AIR) &&
- (!cBlockInfo::IsTransparent(blockBelow)) &&
- (skyLight <= 7) &&
- (blockLight <= 7)
+ ((!cBlockInfo::IsTransparent(BlockBelow)) || (a_DisableSolidBelowCheck)) &&
+ (SkyLight <= 7) &&
+ (BlockLight <= 7)
);
}
}
@@ -196,18 +190,20 @@ bool cMobSpawner::CanSpawnHere(cChunk * a_Chunk, Vector3i a_RelPos, eMonsterType
case mtGhast:
{
- return (
- (targetBlock == E_BLOCK_AIR) &&
- (blockAbove == E_BLOCK_AIR) &&
- (random.RandBool(0.01))
+ return
+ (
+ (TargetBlock == E_BLOCK_AIR) &&
+ (BlockAbove == E_BLOCK_AIR) &&
+ (Random.RandBool(0.01))
);
}
case mtGuardian:
{
- return (
- IsBlockWater(targetBlock) &&
- IsBlockWater(blockBelow) &&
+ return
+ (
+ IsBlockWater(TargetBlock) &&
+ IsBlockWater(BlockBelow) &&
(a_RelPos.y >= 45) &&
(a_RelPos.y <= 62)
);
@@ -216,22 +212,22 @@ bool cMobSpawner::CanSpawnHere(cChunk * a_Chunk, Vector3i a_RelPos, eMonsterType
case mtMagmaCube:
case mtSlime:
{
- return (
- (targetBlock == E_BLOCK_AIR) &&
- (blockAbove == E_BLOCK_AIR) &&
- (!cBlockInfo::IsTransparent(blockBelow)) &&
- (
- (a_RelPos.y <= 40) || (a_Biome == biSwampland)
- )
+ return
+ (
+ (TargetBlock == E_BLOCK_AIR) &&
+ (BlockAbove == E_BLOCK_AIR) &&
+ ((!cBlockInfo::IsTransparent(BlockBelow)) || (a_DisableSolidBelowCheck)) &&
+ ((a_RelPos.y <= 40) || (a_Biome == biSwampland))
);
}
case mtMooshroom:
{
- return (
- (targetBlock == E_BLOCK_AIR) &&
- (blockAbove == E_BLOCK_AIR) &&
- (blockBelow == E_BLOCK_MYCELIUM) &&
+ return
+ (
+ (TargetBlock == E_BLOCK_AIR) &&
+ (BlockAbove == E_BLOCK_AIR) &&
+ (BlockBelow == E_BLOCK_MYCELIUM) &&
(
(a_Biome == biMushroomShore) ||
(a_Biome == biMushroomIsland)
@@ -242,46 +238,46 @@ bool cMobSpawner::CanSpawnHere(cChunk * a_Chunk, Vector3i a_RelPos, eMonsterType
case mtOcelot:
{
return (
- (targetBlock == E_BLOCK_AIR) &&
- (blockAbove == E_BLOCK_AIR) &&
+ (TargetBlock == E_BLOCK_AIR) &&
+ (BlockAbove == E_BLOCK_AIR) &&
(
- (blockBelow == E_BLOCK_GRASS) || (blockBelow == E_BLOCK_LEAVES) || (blockBelow == E_BLOCK_NEW_LEAVES)
+ (BlockBelow == E_BLOCK_GRASS) || (BlockBelow == E_BLOCK_LEAVES) || (BlockBelow == E_BLOCK_NEW_LEAVES)
) &&
(a_RelPos.y >= 62) &&
- (random.RandBool(2.0 / 3.0))
+ (Random.RandBool(2.0 / 3.0))
);
}
case mtSpider:
{
- bool canSpawn = true;
- bool hasFloor = false;
+ bool CanSpawn = true;
+ bool HasFloor = false;
for (int x = 0; x < 2; ++x)
{
for (int z = 0; z < 2; ++z)
{
- canSpawn = a_Chunk->UnboundedRelGetBlockType(a_RelPos.addedXZ(x, z), targetBlock);
- canSpawn = canSpawn && (targetBlock == E_BLOCK_AIR);
- if (!canSpawn)
+ CanSpawn = a_Chunk->UnboundedRelGetBlockType(a_RelPos.addedXZ(x, z), TargetBlock);
+ CanSpawn = CanSpawn && (TargetBlock == E_BLOCK_AIR);
+ if (!CanSpawn)
{
return false;
}
- hasFloor = (
- hasFloor ||
+ HasFloor = (
+ HasFloor ||
(
- a_Chunk->UnboundedRelGetBlockType(a_RelPos + Vector3i(x, -1, z), targetBlock) &&
- !cBlockInfo::IsTransparent(targetBlock)
+ a_Chunk->UnboundedRelGetBlockType(a_RelPos + Vector3i(x, -1, z), TargetBlock) &&
+ !cBlockInfo::IsTransparent(TargetBlock)
)
);
}
}
- return canSpawn && hasFloor && (skyLight <= 7) && (blockLight <= 7);
+ return CanSpawn && HasFloor && (SkyLight <= 7) && (BlockLight <= 7);
}
case mtSquid:
{
return (
- IsBlockWater(targetBlock) &&
+ IsBlockWater(TargetBlock) &&
(a_RelPos.y >= 45) &&
(a_RelPos.y <= 62)
);
@@ -290,20 +286,20 @@ bool cMobSpawner::CanSpawnHere(cChunk * a_Chunk, Vector3i a_RelPos, eMonsterType
case mtWitherSkeleton:
{
return (
- (targetBlock == E_BLOCK_AIR) &&
- (blockAbove == E_BLOCK_AIR) &&
- (!cBlockInfo::IsTransparent(blockBelow)) &&
- (skyLight <= 7) &&
- (blockLight <= 7) &&
- (random.RandBool(0.6))
+ (TargetBlock == E_BLOCK_AIR) &&
+ (BlockAbove == E_BLOCK_AIR) &&
+ ((!cBlockInfo::IsTransparent(BlockBelow)) || (a_DisableSolidBelowCheck)) &&
+ (SkyLight <= 7) &&
+ (BlockLight <= 7) &&
+ (Random.RandBool(0.6))
);
}
case mtWolf:
{
return (
- (targetBlock == E_BLOCK_GRASS) &&
- (blockAbove == E_BLOCK_AIR) &&
+ (TargetBlock == E_BLOCK_GRASS) &&
+ (BlockAbove == E_BLOCK_AIR) &&
(
(a_Biome == biColdTaiga) ||
(a_Biome == biColdTaigaHills) ||
@@ -321,9 +317,9 @@ bool cMobSpawner::CanSpawnHere(cChunk * a_Chunk, Vector3i a_RelPos, eMonsterType
case mtZombiePigman:
{
return (
- (targetBlock == E_BLOCK_AIR) &&
- (blockAbove == E_BLOCK_AIR) &&
- (!cBlockInfo::IsTransparent(blockBelow))
+ (TargetBlock == E_BLOCK_AIR) &&
+ (BlockAbove == E_BLOCK_AIR) &&
+ ((!cBlockInfo::IsTransparent(BlockBelow)) || (a_DisableSolidBelowCheck))
);
}
@@ -467,6 +463,23 @@ std::set<eMonsterType> cMobSpawner::GetAllowedMobTypes(EMCSBiome a_Biome)
cMonster * cMobSpawner::TryToSpawnHere(cChunk * a_Chunk, Vector3i a_RelPos, EMCSBiome a_Biome, int & a_MaxPackSize)
{
+ // If too close to any player, don't spawn anything
+ auto AbsPos = a_Chunk->RelativeToAbsolute(a_RelPos);
+ static const double RangeLimit = 24;
+ if (
+ a_Chunk->GetWorld()->DoWithNearestPlayer(
+ AbsPos,
+ RangeLimit,
+ [](cPlayer & a_Player)
+ {
+ return true;
+ }
+ )
+ )
+ {
+ return nullptr;
+ }
+
if (m_NewPack)
{
m_MobType = ChooseMobType(a_Biome);
@@ -494,11 +507,11 @@ cMonster * cMobSpawner::TryToSpawnHere(cChunk * a_Chunk, Vector3i a_RelPos, EMCS
if ((m_AllowedTypes.find(m_MobType) != m_AllowedTypes.end()) && CanSpawnHere(a_Chunk, a_RelPos, m_MobType, a_Biome))
{
- auto newMob = cMonster::NewMonsterFromType(m_MobType);
- auto NewMobPtr = newMob.get();
- if (newMob)
+ auto NewMob = cMonster::NewMonsterFromType(m_MobType);
+ auto NewMobPtr = NewMob.get();
+ if (NewMob)
{
- m_Spawned.push_back(std::move(newMob));
+ m_Spawned.push_back(std::move(NewMob));
}
return NewMobPtr;
}
diff --git a/src/MobSpawner.h b/src/MobSpawner.h
index 7d5ce5274..6625114a1 100644
--- a/src/MobSpawner.h
+++ b/src/MobSpawner.h
@@ -43,7 +43,7 @@ public :
}
/** Returns true if specified type of mob can spawn on specified block */
- static bool CanSpawnHere(cChunk * a_Chunk, Vector3i a_RelPos, eMonsterType a_MobType, EMCSBiome a_Biome);
+ static bool CanSpawnHere(cChunk * a_Chunk, Vector3i a_RelPos, eMonsterType a_MobType, EMCSBiome a_Biome, bool a_DisableSolidBelowCheck = false);
/** Returns all mob types that can spawn that biome */
static std::set<eMonsterType> GetAllowedMobTypes(EMCSBiome a_Biome);
diff --git a/src/WorldStorage/NBTChunkSerializer.cpp b/src/WorldStorage/NBTChunkSerializer.cpp
index c78b04c66..70f07557f 100644
--- a/src/WorldStorage/NBTChunkSerializer.cpp
+++ b/src/WorldStorage/NBTChunkSerializer.cpp
@@ -546,7 +546,6 @@ public:
{
mWriter.BeginCompound("");
AddBasicTileEntity(a_MobSpawner, "MobSpawner");
- mWriter.AddShort("Entity", static_cast<short>(a_MobSpawner->GetEntity()));
mWriter.AddString("EntityId", cMonster::MobTypeToVanillaName(a_MobSpawner->GetEntity()));
mWriter.AddShort("Delay", a_MobSpawner->GetSpawnDelay());
mWriter.EndCompound();
diff --git a/src/WorldStorage/WSSAnvil.cpp b/src/WorldStorage/WSSAnvil.cpp
index b01bb7fd5..03decbea3 100755
--- a/src/WorldStorage/WSSAnvil.cpp
+++ b/src/WorldStorage/WSSAnvil.cpp
@@ -1338,27 +1338,14 @@ OwnedBlockEntity cWSSAnvil::LoadMobSpawnerFromNBT(const cParsedNBT & a_NBT, int
auto MobSpawner = std::make_unique<cMobSpawnerEntity>(a_BlockType, a_BlockMeta, a_Pos, m_World);
- // Load entity (Cuberite worlds):
- int Type = a_NBT.FindChildByName(a_TagIdx, "Entity");
- if ((Type >= 0) && (a_NBT.GetType(Type) == TAG_Short))
+ // Load entity type
+ int Type = a_NBT.FindChildByName(a_TagIdx, "EntityId");
+ if ((Type >= 0) && (a_NBT.GetType(Type) == TAG_String))
{
- short MonsterType = a_NBT.GetShort(Type);
- if ((MonsterType >= 50) && (MonsterType <= 120))
+ eMonsterType MonsterType = cMonster::StringToMobType(a_NBT.GetString(Type));
+ if (MonsterType != eMonsterType::mtInvalidType)
{
- MobSpawner->SetEntity(static_cast<eMonsterType>(MonsterType));
- }
- }
- else
- {
- // Load entity (vanilla worlds):
- Type = a_NBT.FindChildByName(a_TagIdx, "EntityId");
- if ((Type >= 0) && (a_NBT.GetType(Type) == TAG_String))
- {
- eMonsterType MonsterType = cMonster::StringToMobType(a_NBT.GetString(Type));
- if (MonsterType != eMonsterType::mtInvalidType)
- {
- MobSpawner->SetEntity(MonsterType);
- }
+ MobSpawner->SetEntity(MonsterType);
}
}