From d73a0cd8b020b0a589e496bed56e6740314d9101 Mon Sep 17 00:00:00 2001 From: Samuel Barney Date: Mon, 21 Oct 2013 09:41:48 -0600 Subject: [PATCH 01/16] Current Mob Spawning code. --- source/Chunk.cpp | 29 ++++++++++++++++++++++------- source/MobSpawner.cpp | 26 +++++++++++++------------- source/MobSpawner.h | 4 ++-- 3 files changed, 37 insertions(+), 22 deletions(-) diff --git a/source/Chunk.cpp b/source/Chunk.cpp index 21401163..944cf82d 100644 --- a/source/Chunk.cpp +++ b/source/Chunk.cpp @@ -539,14 +539,29 @@ void cChunk::SpawnMobs(cMobSpawner& a_MobSpawner) // MG TODO: fix the "light" thing, I'm pretty sure that UnboundedRelGetBlock s not returning the right thing // MG TODO : check that "Level" really means Y - cEntity* newMob = a_MobSpawner.TryToSpawnHere(BlockType, BlockMeta, BlockType_below, BlockMeta_below, BlockType_above, BlockMeta_above, Biome, Try_Y, MaxNbOfSuccess); - if (newMob) + NIBBLETYPE SkyLight = GetSkyLight(Try_X, Try_Y+1, Try_Z); + if (!SkyLight) + SkyLight = GetSkyLight(Try_X, Try_Y, Try_Z); + if (!SkyLight) + SkyLight = GetSkyLight(Try_X, Try_Y - 1, Try_Z); + + NIBBLETYPE BlockLight = GetBlockLight(Try_X, Try_Y+1, Try_Z); + if (!BlockLight) + BlockLight = GetBlockLight(Try_X, Try_Y, Try_Z); + if (!BlockLight) + BlockLight = GetBlockLight(Try_X, Try_Y - 1, Try_Z); + + if (IsLightValid()) { - int WorldX, WorldY, WorldZ; - PositionToWorldPosition(Try_X, Try_Y, Try_Z, WorldX, WorldY, WorldZ); - newMob->SetPosition(WorldX, WorldY, WorldZ); - LOGD("Spawning %s #%i at %d,%d,%d",newMob->GetClass(),newMob->GetUniqueID(),WorldX, WorldY, WorldZ); - NumberOfSuccess++; + cEntity* newMob = a_MobSpawner.TryToSpawnHere(BlockType, BlockMeta, BlockType_below, BlockMeta_below, BlockType_above, BlockMeta_above, SkyLight, BlockLight, Biome, Try_Y, MaxNbOfSuccess); + if (newMob) + { + int WorldX, WorldY, WorldZ; + PositionToWorldPosition(Try_X, Try_Y, Try_Z, WorldX, WorldY, WorldZ); + newMob->SetPosition(WorldX, WorldY, WorldZ); + LOGD("Spawning %s #%i at %d,%d,%d",newMob->GetClass(),newMob->GetUniqueID(),WorldX, WorldY, WorldZ); + NumberOfSuccess++; + } } } diff --git a/source/MobSpawner.cpp b/source/MobSpawner.cpp index 1b3796f7..8f21e18f 100644 --- a/source/MobSpawner.cpp +++ b/source/MobSpawner.cpp @@ -124,7 +124,7 @@ cMonster::eType cMobSpawner::ChooseMobType(EMCSBiome a_Biome) -bool cMobSpawner::CanSpawnHere(cMonster::eType a_MobType, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, BLOCKTYPE a_BlockType_below, NIBBLETYPE a_BlockMeta_below, BLOCKTYPE a_BlockType_above, NIBBLETYPE a_BlockMeta_above, EMCSBiome a_Biome, int a_Level) +bool cMobSpawner::CanSpawnHere(cMonster::eType a_MobType, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, BLOCKTYPE a_BlockType_below, NIBBLETYPE a_BlockMeta_below, BLOCKTYPE a_BlockType_above, NIBBLETYPE a_BlockMeta_above, NIBBLETYPE a_Skylight, NIBBLETYPE a_Blocklight, EMCSBiome a_Biome, int a_Level) { bool toReturn = false; std::set::iterator itr = m_AllowedTypes.find(a_MobType); @@ -154,31 +154,31 @@ bool cMobSpawner::CanSpawnHere(cMonster::eType a_MobType, BLOCKTYPE a_BlockType, if (a_MobType == cMonster::mtChicken || a_MobType == cMonster::mtPig || a_MobType == cMonster::mtCow || a_MobType == cMonster::mtSheep) { toReturn = ( - a_BlockType_below == E_BLOCK_GRASS /*&& // MG TODO - a_LightLevel >= 9 */ + (a_BlockType_below == E_BLOCK_GRASS) && + (a_Skylight >= 9 ) ); } else if (a_MobType == cMonster::mtOcelot) { toReturn = ( - a_Level >= 62 && + (a_Level >= 62) && ( - a_BlockType_below == E_BLOCK_GRASS || - a_BlockType_below == E_BLOCK_LEAVES + (a_BlockType_below == E_BLOCK_GRASS) || + (a_BlockType_below == E_BLOCK_LEAVES) ) && - m_Random.NextInt(3,a_Biome) != 0 + (m_Random.NextInt(3,a_Biome) != 0) ); } else if (a_MobType == cMonster::mtCreeper || a_MobType == cMonster::mtSkeleton || a_MobType == cMonster::mtZombie || a_MobType == cMonster::mtSpider || a_MobType == cMonster::mtEnderman || a_MobType == cMonster::mtZombiePigman) { - toReturn = true /*a_LightLevel <= 7 MG TODO*/; - /*if (a_SunLight) MG TODO + toReturn = (a_Skylight <= 7) && (a_Blocklight <= 7); + if (a_Skylight) { if (m_Random.NextInt(2,a_Biome) != 0) { toReturn = false; } - }*/ + } } else if (a_MobType == cMonster::mtSlime) { @@ -192,7 +192,7 @@ bool cMobSpawner::CanSpawnHere(cMonster::eType a_MobType, BLOCKTYPE a_BlockType, else { LOGD("MG TODO : check I've got a Rule to write for type %d",a_MobType); - toReturn = true; + toReturn = false; } } } @@ -204,7 +204,7 @@ bool cMobSpawner::CanSpawnHere(cMonster::eType a_MobType, BLOCKTYPE a_BlockType, -cMonster* cMobSpawner::TryToSpawnHere(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, BLOCKTYPE a_BlockType_below, NIBBLETYPE a_BlockMeta_below, BLOCKTYPE a_BlockType_above, NIBBLETYPE a_BlockMeta_above, EMCSBiome a_Biome, int a_Level, int& a_MaxPackSize) +cMonster* cMobSpawner::TryToSpawnHere(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, BLOCKTYPE a_BlockType_below, NIBBLETYPE a_BlockMeta_below, BLOCKTYPE a_BlockType_above, NIBBLETYPE a_BlockMeta_above, NIBBLETYPE a_Skylight, NIBBLETYPE a_Blocklight, EMCSBiome a_Biome, int a_Level, int& a_MaxPackSize) { cMonster* toReturn = NULL; if (m_NewPack) @@ -226,7 +226,7 @@ cMonster* cMobSpawner::TryToSpawnHere(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockM } - if (CanSpawnHere(m_MobType, a_BlockType, a_BlockMeta, a_BlockType_below, a_BlockMeta_below, a_BlockType_above, a_BlockMeta_above, a_Biome, a_Level)) + if (CanSpawnHere(m_MobType, a_BlockType, a_BlockMeta, a_BlockType_below, a_BlockMeta_below, a_BlockType_above, a_BlockMeta_above, a_Skylight, a_Blocklight, a_Biome, a_Level)) { cMonster * newMob = cMonster::NewMonsterFromType(m_MobType); if (newMob) diff --git a/source/MobSpawner.h b/source/MobSpawner.h index ba2a18f2..e5b7e9b6 100644 --- a/source/MobSpawner.h +++ b/source/MobSpawner.h @@ -38,7 +38,7 @@ public : // if this is the first of a Pack : determine the type of monster // BlockType & BlockMeta are used to decide what kind of Mob can Spawn here // MaxPackSize is set to the maximal size for a pack this type of mob - cMonster * TryToSpawnHere(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, BLOCKTYPE a_BlockType_below, NIBBLETYPE a_BlockMeta_below, BLOCKTYPE a_BlockType_above, NIBBLETYPE a_BlockMeta_above, EMCSBiome a_Biome, int a_Level, int& a_MaxPackSize); + cMonster * TryToSpawnHere(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, BLOCKTYPE a_BlockType_below, NIBBLETYPE a_BlockMeta_below, BLOCKTYPE a_BlockType_above, NIBBLETYPE a_BlockMeta_above, NIBBLETYPE a_Skylight, NIBBLETYPE a_Blocklight, EMCSBiome a_Biome, int a_Level, int& a_MaxPackSize); // mark the beginning of a new Pack // all mobs of the same Pack are the same type @@ -52,7 +52,7 @@ public : protected : // return true if specified type of mob can spawn on specified block - bool CanSpawnHere(cMonster::eType a_MobType, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, BLOCKTYPE a_BlockType_below, NIBBLETYPE a_BlockMeta_below, BLOCKTYPE a_BlockType_above, NIBBLETYPE a_BlockMeta_above, EMCSBiome a_Biome, int a_Level); + bool CanSpawnHere(cMonster::eType a_MobType, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, BLOCKTYPE a_BlockType_below, NIBBLETYPE a_BlockMeta_below, BLOCKTYPE a_BlockType_above, NIBBLETYPE a_BlockMeta_above, NIBBLETYPE a_Skylight, NIBBLETYPE a_Blocklight, EMCSBiome a_Biome, int a_Level); // return a random type that can spawn on specified biome. // returns E_ENTITY_TYPE_DONOTUSE if none is possible From 56fa632d5e2b48a81f2a90878cb3656d1d3d563c Mon Sep 17 00:00:00 2001 From: Samuel Barney Date: Mon, 21 Oct 2013 10:03:05 -0600 Subject: [PATCH 02/16] Swapped which block is checked for light first. --- source/Chunk.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/source/Chunk.cpp b/source/Chunk.cpp index 944cf82d..5a54371a 100644 --- a/source/Chunk.cpp +++ b/source/Chunk.cpp @@ -539,15 +539,15 @@ void cChunk::SpawnMobs(cMobSpawner& a_MobSpawner) // MG TODO: fix the "light" thing, I'm pretty sure that UnboundedRelGetBlock s not returning the right thing // MG TODO : check that "Level" really means Y - NIBBLETYPE SkyLight = GetSkyLight(Try_X, Try_Y+1, Try_Z); + NIBBLETYPE SkyLight = GetSkyLight(Try_X, Try_Y, Try_Z); if (!SkyLight) - SkyLight = GetSkyLight(Try_X, Try_Y, Try_Z); + SkyLight = GetSkyLight(Try_X, Try_Y + 1, Try_Z); if (!SkyLight) SkyLight = GetSkyLight(Try_X, Try_Y - 1, Try_Z); - NIBBLETYPE BlockLight = GetBlockLight(Try_X, Try_Y+1, Try_Z); + NIBBLETYPE BlockLight = GetBlockLight(Try_X, Try_Y, Try_Z); if (!BlockLight) - BlockLight = GetBlockLight(Try_X, Try_Y, Try_Z); + BlockLight = GetBlockLight(Try_X, Try_Y + 1, Try_Z); if (!BlockLight) BlockLight = GetBlockLight(Try_X, Try_Y - 1, Try_Z); From 6e361f195fa61ff6585f78dd7cd7302b1dba5619 Mon Sep 17 00:00:00 2001 From: Samuel Barney Date: Mon, 21 Oct 2013 14:38:38 -0600 Subject: [PATCH 03/16] Added two new unbounded del functions to deal with looking up the lighting. --- source/Chunk.cpp | 109 ++++++++++++++++++++++++++++++++++++++++++----- source/Chunk.h | 3 ++ 2 files changed, 102 insertions(+), 10 deletions(-) diff --git a/source/Chunk.cpp b/source/Chunk.cpp index 5a54371a..ea6fed50 100644 --- a/source/Chunk.cpp +++ b/source/Chunk.cpp @@ -539,17 +539,10 @@ void cChunk::SpawnMobs(cMobSpawner& a_MobSpawner) // MG TODO: fix the "light" thing, I'm pretty sure that UnboundedRelGetBlock s not returning the right thing // MG TODO : check that "Level" really means Y - NIBBLETYPE SkyLight = GetSkyLight(Try_X, Try_Y, Try_Z); - if (!SkyLight) - SkyLight = GetSkyLight(Try_X, Try_Y + 1, Try_Z); - if (!SkyLight) - SkyLight = GetSkyLight(Try_X, Try_Y - 1, Try_Z); + + NIBBLETYPE SkyLight = UnboundedRelGetSkyLight(Try_X, Try_Y, Try_Z); - NIBBLETYPE BlockLight = GetBlockLight(Try_X, Try_Y, Try_Z); - if (!BlockLight) - BlockLight = GetBlockLight(Try_X, Try_Y + 1, Try_Z); - if (!BlockLight) - BlockLight = GetBlockLight(Try_X, Try_Y - 1, Try_Z); + NIBBLETYPE BlockLight = UnboundedRelGetBlockLight(Try_X, Try_Y, Try_Z); if (IsLightValid()) { @@ -1363,6 +1356,102 @@ void cChunk::UnboundedQueueTickBlock(int a_RelX, int a_RelY, int a_RelZ) +NIBBLETYPE cChunk::UnboundedRelGetSkyLight(int a_RelX, int a_RelY, int a_RelZ) +{ +if ((a_RelY < 0) || (a_RelY > cChunkDef::Height)) + { + LOGWARNING("UnboundedRelGetSkyLight(): requesting a block with a_RelY out of range: %d", a_RelY); + return -1; + } + + // Is it in this chunk? + if ((a_RelX >= 0) && (a_RelX < cChunkDef::Width) && (a_RelZ >= 0) && (a_RelZ < cChunkDef::Width)) + { + if (!IsValid()) + { + return -1; + } + return GetSkyLight(a_RelX, a_RelY, a_RelZ); + } + + // Not in this chunk, try walking the neighbors first: + if ((a_RelX < 0) && (m_NeighborXM != NULL)) + { + return m_NeighborXM->UnboundedRelGetSkyLight(a_RelX + cChunkDef::Width, a_RelY, a_RelZ); + } + if ((a_RelX >= cChunkDef::Width) && (m_NeighborXP != NULL)) + { + return m_NeighborXP->UnboundedRelGetSkyLight(a_RelX - cChunkDef::Width, a_RelY, a_RelZ); + } + if ((a_RelZ < 0) && (m_NeighborZM != NULL)) + { + return m_NeighborZM->UnboundedRelGetSkyLight(a_RelX, a_RelY, a_RelZ + cChunkDef::Width); + } + if ((a_RelZ >= cChunkDef::Width) && (m_NeighborZP != NULL)) + { + return m_NeighborZP->UnboundedRelGetSkyLight(a_RelX, a_RelY, a_RelZ - cChunkDef::Width); + } + + // Neighbors not available, use the chunkmap to locate the chunk: + return m_ChunkMap->GetBlockSkyLight( + m_PosX * cChunkDef::Width + a_RelX, + ZERO_CHUNK_Y * cChunkDef::Height + a_RelY, + m_PosZ * cChunkDef::Width + a_RelZ + ); +} + + + + + +NIBBLETYPE cChunk::UnboundedRelGetBlockLight(int a_RelX, int a_RelY, int a_RelZ) +{ +if ((a_RelY < 0) || (a_RelY > cChunkDef::Height)) + { + LOGWARNING("UnboundedRelGetBlockLight(): requesting a block with a_RelY out of range: %d", a_RelY); + return -1; + } + + // Is it in this chunk? + if ((a_RelX >= 0) && (a_RelX < cChunkDef::Width) && (a_RelZ >= 0) && (a_RelZ < cChunkDef::Width)) + { + if (!IsValid()) + { + return -1; + } + return GetBlockLight(a_RelX, a_RelY, a_RelZ); + } + + // Not in this chunk, try walking the neighbors first: + if ((a_RelX < 0) && (m_NeighborXM != NULL)) + { + return m_NeighborXM->UnboundedRelGetBlockLight(a_RelX + cChunkDef::Width, a_RelY, a_RelZ); + } + if ((a_RelX >= cChunkDef::Width) && (m_NeighborXP != NULL)) + { + return m_NeighborXP->UnboundedRelGetBlockLight(a_RelX - cChunkDef::Width, a_RelY, a_RelZ); + } + if ((a_RelZ < 0) && (m_NeighborZM != NULL)) + { + return m_NeighborZM->UnboundedRelGetBlockLight(a_RelX, a_RelY, a_RelZ + cChunkDef::Width); + } + if ((a_RelZ >= cChunkDef::Width) && (m_NeighborZP != NULL)) + { + return m_NeighborZP->UnboundedRelGetBlockLight(a_RelX, a_RelY, a_RelZ - cChunkDef::Width); + } + + // Neighbors not available, use the chunkmap to locate the chunk: + return m_ChunkMap->GetBlockBlockLight( + m_PosX * cChunkDef::Width + a_RelX, + ZERO_CHUNK_Y * cChunkDef::Height + a_RelY, + m_PosZ * cChunkDef::Width + a_RelZ + ); +} + + + + + int cChunk::GetHeight( int a_X, int a_Z ) { ASSERT((a_X >= 0) && (a_X < Width) && (a_Z >= 0) && (a_Z < Width)); diff --git a/source/Chunk.h b/source/Chunk.h index aca180d1..303e7b6a 100644 --- a/source/Chunk.h +++ b/source/Chunk.h @@ -317,6 +317,9 @@ public: /// 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); + NIBBLETYPE UnboundedRelGetBlockLight(int a_RelX, int a_RelY, int a_RelZ); + NIBBLETYPE UnboundedRelGetSkyLight(int a_RelX, int a_RelY, int a_RelZ); + // Simulator data: cFireSimulatorChunkData & GetFireSimulatorData (void) { return m_FireSimulatorData; } cFluidSimulatorData * GetWaterSimulatorData(void) { return m_WaterSimulatorData; } From d6d73a1754b67bc38404dcac54947812076b83ea Mon Sep 17 00:00:00 2001 From: Samuel Barney Date: Tue, 22 Oct 2013 17:10:32 -0600 Subject: [PATCH 04/16] Invalid light value is now 127 --- source/Chunk.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/source/Chunk.cpp b/source/Chunk.cpp index ea6fed50..32a8b5c0 100644 --- a/source/Chunk.cpp +++ b/source/Chunk.cpp @@ -544,7 +544,7 @@ void cChunk::SpawnMobs(cMobSpawner& a_MobSpawner) NIBBLETYPE BlockLight = UnboundedRelGetBlockLight(Try_X, Try_Y, Try_Z); - if (IsLightValid()) + if (IsLightValid() && (SkyLight != 127) && (BlockLight != 127)) { cEntity* newMob = a_MobSpawner.TryToSpawnHere(BlockType, BlockMeta, BlockType_below, BlockMeta_below, BlockType_above, BlockMeta_above, SkyLight, BlockLight, Biome, Try_Y, MaxNbOfSuccess); if (newMob) @@ -1361,7 +1361,7 @@ NIBBLETYPE cChunk::UnboundedRelGetSkyLight(int a_RelX, int a_RelY, int a_RelZ) if ((a_RelY < 0) || (a_RelY > cChunkDef::Height)) { LOGWARNING("UnboundedRelGetSkyLight(): requesting a block with a_RelY out of range: %d", a_RelY); - return -1; + return 127; } // Is it in this chunk? @@ -1369,7 +1369,7 @@ if ((a_RelY < 0) || (a_RelY > cChunkDef::Height)) { if (!IsValid()) { - return -1; + return 127; } return GetSkyLight(a_RelX, a_RelY, a_RelZ); } @@ -1409,7 +1409,7 @@ NIBBLETYPE cChunk::UnboundedRelGetBlockLight(int a_RelX, int a_RelY, int a_RelZ) if ((a_RelY < 0) || (a_RelY > cChunkDef::Height)) { LOGWARNING("UnboundedRelGetBlockLight(): requesting a block with a_RelY out of range: %d", a_RelY); - return -1; + return 127; } // Is it in this chunk? @@ -1417,7 +1417,7 @@ if ((a_RelY < 0) || (a_RelY > cChunkDef::Height)) { if (!IsValid()) { - return -1; + return 127; } return GetBlockLight(a_RelX, a_RelY, a_RelZ); } From 228ccc5c6aa4ac21f280ebd63af39909800e8a7f Mon Sep 17 00:00:00 2001 From: Samuel Barney Date: Tue, 22 Oct 2013 17:11:38 -0600 Subject: [PATCH 05/16] Bats only spawn where there is no sunlight, and the light level is below 5 --- source/MobSpawner.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/MobSpawner.cpp b/source/MobSpawner.cpp index 8f21e18f..a69c5653 100644 --- a/source/MobSpawner.cpp +++ b/source/MobSpawner.cpp @@ -141,7 +141,7 @@ bool cMobSpawner::CanSpawnHere(cMonster::eType a_MobType, BLOCKTYPE a_BlockType, } else if (a_MobType == cMonster::mtBat) { - toReturn = a_Level <= 60; // MG TODO : find a real rule + toReturn = a_Level <= 63 && (a_Skylight == 0) && (a_Blocklight <= 4); // MG TODO : find a real rule } else { From f558f3c6d29931090378f75f7ea0ba84e81fead0 Mon Sep 17 00:00:00 2001 From: Samuel Barney Date: Wed, 23 Oct 2013 17:41:24 -0600 Subject: [PATCH 06/16] Removed my hackish Light functions --- source/Chunk.cpp | 96 ------------------------------------------------ source/Chunk.h | 2 - 2 files changed, 98 deletions(-) diff --git a/source/Chunk.cpp b/source/Chunk.cpp index 32a8b5c0..2e81bf85 100644 --- a/source/Chunk.cpp +++ b/source/Chunk.cpp @@ -1356,102 +1356,6 @@ void cChunk::UnboundedQueueTickBlock(int a_RelX, int a_RelY, int a_RelZ) -NIBBLETYPE cChunk::UnboundedRelGetSkyLight(int a_RelX, int a_RelY, int a_RelZ) -{ -if ((a_RelY < 0) || (a_RelY > cChunkDef::Height)) - { - LOGWARNING("UnboundedRelGetSkyLight(): requesting a block with a_RelY out of range: %d", a_RelY); - return 127; - } - - // Is it in this chunk? - if ((a_RelX >= 0) && (a_RelX < cChunkDef::Width) && (a_RelZ >= 0) && (a_RelZ < cChunkDef::Width)) - { - if (!IsValid()) - { - return 127; - } - return GetSkyLight(a_RelX, a_RelY, a_RelZ); - } - - // Not in this chunk, try walking the neighbors first: - if ((a_RelX < 0) && (m_NeighborXM != NULL)) - { - return m_NeighborXM->UnboundedRelGetSkyLight(a_RelX + cChunkDef::Width, a_RelY, a_RelZ); - } - if ((a_RelX >= cChunkDef::Width) && (m_NeighborXP != NULL)) - { - return m_NeighborXP->UnboundedRelGetSkyLight(a_RelX - cChunkDef::Width, a_RelY, a_RelZ); - } - if ((a_RelZ < 0) && (m_NeighborZM != NULL)) - { - return m_NeighborZM->UnboundedRelGetSkyLight(a_RelX, a_RelY, a_RelZ + cChunkDef::Width); - } - if ((a_RelZ >= cChunkDef::Width) && (m_NeighborZP != NULL)) - { - return m_NeighborZP->UnboundedRelGetSkyLight(a_RelX, a_RelY, a_RelZ - cChunkDef::Width); - } - - // Neighbors not available, use the chunkmap to locate the chunk: - return m_ChunkMap->GetBlockSkyLight( - m_PosX * cChunkDef::Width + a_RelX, - ZERO_CHUNK_Y * cChunkDef::Height + a_RelY, - m_PosZ * cChunkDef::Width + a_RelZ - ); -} - - - - - -NIBBLETYPE cChunk::UnboundedRelGetBlockLight(int a_RelX, int a_RelY, int a_RelZ) -{ -if ((a_RelY < 0) || (a_RelY > cChunkDef::Height)) - { - LOGWARNING("UnboundedRelGetBlockLight(): requesting a block with a_RelY out of range: %d", a_RelY); - return 127; - } - - // Is it in this chunk? - if ((a_RelX >= 0) && (a_RelX < cChunkDef::Width) && (a_RelZ >= 0) && (a_RelZ < cChunkDef::Width)) - { - if (!IsValid()) - { - return 127; - } - return GetBlockLight(a_RelX, a_RelY, a_RelZ); - } - - // Not in this chunk, try walking the neighbors first: - if ((a_RelX < 0) && (m_NeighborXM != NULL)) - { - return m_NeighborXM->UnboundedRelGetBlockLight(a_RelX + cChunkDef::Width, a_RelY, a_RelZ); - } - if ((a_RelX >= cChunkDef::Width) && (m_NeighborXP != NULL)) - { - return m_NeighborXP->UnboundedRelGetBlockLight(a_RelX - cChunkDef::Width, a_RelY, a_RelZ); - } - if ((a_RelZ < 0) && (m_NeighborZM != NULL)) - { - return m_NeighborZM->UnboundedRelGetBlockLight(a_RelX, a_RelY, a_RelZ + cChunkDef::Width); - } - if ((a_RelZ >= cChunkDef::Width) && (m_NeighborZP != NULL)) - { - return m_NeighborZP->UnboundedRelGetBlockLight(a_RelX, a_RelY, a_RelZ - cChunkDef::Width); - } - - // Neighbors not available, use the chunkmap to locate the chunk: - return m_ChunkMap->GetBlockBlockLight( - m_PosX * cChunkDef::Width + a_RelX, - ZERO_CHUNK_Y * cChunkDef::Height + a_RelY, - m_PosZ * cChunkDef::Width + a_RelZ - ); -} - - - - - int cChunk::GetHeight( int a_X, int a_Z ) { ASSERT((a_X >= 0) && (a_X < Width) && (a_Z >= 0) && (a_Z < Width)); diff --git a/source/Chunk.h b/source/Chunk.h index 303e7b6a..2fa4a7a6 100644 --- a/source/Chunk.h +++ b/source/Chunk.h @@ -317,8 +317,6 @@ public: /// 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); - NIBBLETYPE UnboundedRelGetBlockLight(int a_RelX, int a_RelY, int a_RelZ); - NIBBLETYPE UnboundedRelGetSkyLight(int a_RelX, int a_RelY, int a_RelZ); // Simulator data: cFireSimulatorChunkData & GetFireSimulatorData (void) { return m_FireSimulatorData; } From 00480a1d9a4c0c48b32cfe7b2f3f20270dcb19ce Mon Sep 17 00:00:00 2001 From: Samuel Barney Date: Wed, 23 Oct 2013 17:51:14 -0600 Subject: [PATCH 07/16] Using provided UnboundedRelGetBlockBlockLight and UnboundedRelGetBlockSkyLight. --- source/Chunk.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/source/Chunk.cpp b/source/Chunk.cpp index e4e5a7ca..35da4c26 100644 --- a/source/Chunk.cpp +++ b/source/Chunk.cpp @@ -536,15 +536,13 @@ void cChunk::SpawnMobs(cMobSpawner& a_MobSpawner) // check player and playerspawn presence < 24 blocks // check mobs presence on the block - // MG TODO: fix the "light" thing, I'm pretty sure that UnboundedRelGetBlock s not returning the right thing - // MG TODO : check that "Level" really means Y - NIBBLETYPE SkyLight = UnboundedRelGetSkyLight(Try_X, Try_Y, Try_Z); + NIBBLETYPE SkyLight = 0; - NIBBLETYPE BlockLight = UnboundedRelGetBlockLight(Try_X, Try_Y, Try_Z); + NIBBLETYPE BlockLight = 0; - if (IsLightValid() && (SkyLight != 127) && (BlockLight != 127)) + if (IsLightValid() && (UnboundedRelGetBlockBlockLight(Try_X, Try_Y, Try_Z, BlockLight)) && (UnboundedRelGetBlockSkyLight(Try_X, Try_Y, Try_Z, SkyLight))) { cEntity* newMob = a_MobSpawner.TryToSpawnHere(BlockType, BlockMeta, BlockType_below, BlockMeta_below, BlockType_above, BlockMeta_above, SkyLight, BlockLight, Biome, Try_Y, MaxNbOfSuccess); if (newMob) From 4e024f5d87028ccb185c3698b1e050682a7e698d Mon Sep 17 00:00:00 2001 From: Samuel Barney Date: Fri, 25 Oct 2013 11:50:46 -0600 Subject: [PATCH 08/16] Fixed mob spawning so that hostile mobs will not spawn incorrectly. --- source/MobSpawner.cpp | 106 +++++++++++++++--------------------------- 1 file changed, 38 insertions(+), 68 deletions(-) diff --git a/source/MobSpawner.cpp b/source/MobSpawner.cpp index a69c5653..8bd005ac 100644 --- a/source/MobSpawner.cpp +++ b/source/MobSpawner.cpp @@ -126,78 +126,48 @@ cMonster::eType cMobSpawner::ChooseMobType(EMCSBiome a_Biome) bool cMobSpawner::CanSpawnHere(cMonster::eType a_MobType, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, BLOCKTYPE a_BlockType_below, NIBBLETYPE a_BlockMeta_below, BLOCKTYPE a_BlockType_above, NIBBLETYPE a_BlockMeta_above, NIBBLETYPE a_Skylight, NIBBLETYPE a_Blocklight, EMCSBiome a_Biome, int a_Level) { - bool toReturn = false; - std::set::iterator itr = m_AllowedTypes.find(a_MobType); - if (itr != m_AllowedTypes.end()) + if (m_AllowedTypes.find(a_MobType) != m_AllowedTypes.end()) { - // MG TODO : find a nicer paging - if (a_MobType == cMonster::mtSquid) + switch(a_MobType) { - toReturn = ( - IsBlockLiquid(a_BlockType) && - a_Level >= 45 && - a_Level <= 62 - ); - } - else if (a_MobType == cMonster::mtBat) - { - toReturn = a_Level <= 63 && (a_Skylight == 0) && (a_Blocklight <= 4); // MG TODO : find a real rule - } - else - { - if ( - a_BlockType == E_BLOCK_AIR && - a_BlockType_above == E_BLOCK_AIR && - ! (g_BlockTransparent[a_BlockType_below]) - ) - { - if (a_MobType == cMonster::mtChicken || a_MobType == cMonster::mtPig || a_MobType == cMonster::mtCow || a_MobType == cMonster::mtSheep) - { - toReturn = ( - (a_BlockType_below == E_BLOCK_GRASS) && - (a_Skylight >= 9 ) - ); - } - else if (a_MobType == cMonster::mtOcelot) - { - toReturn = ( - (a_Level >= 62) && - ( - (a_BlockType_below == E_BLOCK_GRASS) || - (a_BlockType_below == E_BLOCK_LEAVES) - ) && - (m_Random.NextInt(3,a_Biome) != 0) - ); - } - else if (a_MobType == cMonster::mtCreeper || a_MobType == cMonster::mtSkeleton || a_MobType == cMonster::mtZombie || a_MobType == cMonster::mtSpider || a_MobType == cMonster::mtEnderman || a_MobType == cMonster::mtZombiePigman) - { - toReturn = (a_Skylight <= 7) && (a_Blocklight <= 7); - if (a_Skylight) - { - if (m_Random.NextInt(2,a_Biome) != 0) - { - toReturn = false; - } - } - } - else if (a_MobType == cMonster::mtSlime) - { - toReturn = a_Level <= 40; - // MG TODO : much more complicated rules - } - else if (a_MobType == cMonster::mtGhast) - { - toReturn = m_Random.NextInt(20,a_Biome) == 0; - } - else - { - LOGD("MG TODO : check I've got a Rule to write for type %d",a_MobType); - toReturn = false; - } - } + case cMonster::mtSquid: + return IsBlockWater(a_BlockType) && (a_Level >= 45) && (a_Level <= 62); + + case cMonster::mtBat: + return a_Level <= 63 && (a_Skylight == 0) && (a_Blocklight <= 4) && (a_BlockType == E_BLOCK_AIR) && (!g_BlockTransparent[a_BlockType_above]); + + case cMonster::mtChicken: + case cMonster::mtCow: + case cMonster::mtPig: + case cMonster::mtHorse: + case cMonster::mtSheep: + return (a_BlockType == E_BLOCK_AIR) && (a_BlockType_above == E_BLOCK_AIR) && (!g_BlockTransparent[a_BlockType_below]) && + (a_BlockType_below == E_BLOCK_GRASS) && (a_Skylight >= 9); + + case cMonster::mtOcelot: + return (a_BlockType == E_BLOCK_AIR) && (a_BlockType_above == E_BLOCK_AIR) && + ((a_BlockType_below == E_BLOCK_GRASS) || (a_BlockType_below == E_BLOCK_LEAVES)) && (a_Level >= 62) && (m_Random.NextInt(3,a_Biome) != 0); + + case cMonster::mtEnderman: + return false; + case cMonster::mtCreeper: + case cMonster::mtZombie: + case cMonster::mtSpider: + return (a_BlockType == E_BLOCK_AIR) && (a_BlockType_above == E_BLOCK_AIR) && (!g_BlockTransparent[a_BlockType_below]) && + (a_Skylight <= 7) && (a_Blocklight <= 7) && (m_Random.NextInt(2,a_Biome) == 0); + + case cMonster::mtSlime: + return (a_BlockType == E_BLOCK_AIR) && (a_BlockType_above == E_BLOCK_AIR) && (!g_BlockTransparent[a_BlockType_below]) && + (a_Level <= 40); + case cMonster::mtGhast: + case cMonster::mtZombiePigman: + return (a_BlockType == E_BLOCK_AIR) && (a_BlockType_above == E_BLOCK_AIR) && (!g_BlockTransparent[a_BlockType_below]) && + (m_Random.NextInt(20,a_Biome) == 0); + default: + LOGD("MG TODO : check I've got a Rule to write for type %d",a_MobType); + return false; } } - return toReturn; } From 6f0d15b4485521ec1926e8c201c9b32309e89348 Mon Sep 17 00:00:00 2001 From: Samuel Barney Date: Fri, 25 Oct 2013 12:15:10 -0600 Subject: [PATCH 09/16] Checked Endermen; they work; adding them back in. --- source/MobSpawner.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/source/MobSpawner.cpp b/source/MobSpawner.cpp index 8bd005ac..5bb02119 100644 --- a/source/MobSpawner.cpp +++ b/source/MobSpawner.cpp @@ -149,7 +149,6 @@ bool cMobSpawner::CanSpawnHere(cMonster::eType a_MobType, BLOCKTYPE a_BlockType, ((a_BlockType_below == E_BLOCK_GRASS) || (a_BlockType_below == E_BLOCK_LEAVES)) && (a_Level >= 62) && (m_Random.NextInt(3,a_Biome) != 0); case cMonster::mtEnderman: - return false; case cMonster::mtCreeper: case cMonster::mtZombie: case cMonster::mtSpider: From 0b853dca93fdeca797825d4a0959cb3f3127dc04 Mon Sep 17 00:00:00 2001 From: Samuel Barney Date: Sat, 26 Oct 2013 03:50:34 -0600 Subject: [PATCH 10/16] Moving spawning position to the center of the block. --- source/Chunk.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/source/Chunk.cpp b/source/Chunk.cpp index 35da4c26..0892020e 100644 --- a/source/Chunk.cpp +++ b/source/Chunk.cpp @@ -549,7 +549,9 @@ void cChunk::SpawnMobs(cMobSpawner& a_MobSpawner) { int WorldX, WorldY, WorldZ; PositionToWorldPosition(Try_X, Try_Y, Try_Z, WorldX, WorldY, WorldZ); - newMob->SetPosition(WorldX, WorldY, WorldZ); + double ActualX = WorldX + 0.5; + double ActualZ = WorldZ + 0.5; + newMob->SetPosition(ActualX, WorldY, ActualZ); LOGD("Spawning %s #%i at %d,%d,%d",newMob->GetClass(),newMob->GetUniqueID(),WorldX, WorldY, WorldZ); NumberOfSuccess++; } From 6c30ce93dae4c14dc84385578e0857d46e7484f4 Mon Sep 17 00:00:00 2001 From: Samuel Barney Date: Sat, 26 Oct 2013 03:51:56 -0600 Subject: [PATCH 11/16] Disabling Endermen and spiders until I rework the CanSpawnHere to take a chunk and a position. --- source/MobSpawner.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/MobSpawner.cpp b/source/MobSpawner.cpp index 5bb02119..35eee4ac 100644 --- a/source/MobSpawner.cpp +++ b/source/MobSpawner.cpp @@ -149,9 +149,10 @@ bool cMobSpawner::CanSpawnHere(cMonster::eType a_MobType, BLOCKTYPE a_BlockType, ((a_BlockType_below == E_BLOCK_GRASS) || (a_BlockType_below == E_BLOCK_LEAVES)) && (a_Level >= 62) && (m_Random.NextInt(3,a_Biome) != 0); case cMonster::mtEnderman: + case cMonster::mtSpider: + return false; case cMonster::mtCreeper: case cMonster::mtZombie: - case cMonster::mtSpider: return (a_BlockType == E_BLOCK_AIR) && (a_BlockType_above == E_BLOCK_AIR) && (!g_BlockTransparent[a_BlockType_below]) && (a_Skylight <= 7) && (a_Blocklight <= 7) && (m_Random.NextInt(2,a_Biome) == 0); From 16bac5ace9a2388cee3fd0d9192b7cd69a06152d Mon Sep 17 00:00:00 2001 From: Samuel Barney Date: Mon, 28 Oct 2013 09:49:06 -0600 Subject: [PATCH 12/16] Made mob spawning code use the chunk so that it could use varying sizes of areas for different mobs. --- source/Chunk.cpp | 56 +++++++++++++------------------- source/MobSpawner.cpp | 74 ++++++++++++++++++++++++++++++++----------- source/MobSpawner.h | 5 +-- 3 files changed, 81 insertions(+), 54 deletions(-) diff --git a/source/Chunk.cpp b/source/Chunk.cpp index 0892020e..637b72b2 100644 --- a/source/Chunk.cpp +++ b/source/Chunk.cpp @@ -519,42 +519,30 @@ void cChunk::SpawnMobs(cMobSpawner& a_MobSpawner) ASSERT(Try_Y > 0); ASSERT(Try_Y < cChunkDef::Height-1); - BLOCKTYPE BlockType; - NIBBLETYPE BlockMeta; - BLOCKTYPE BlockType_below; - NIBBLETYPE BlockMeta_below; - BLOCKTYPE BlockType_above; - NIBBLETYPE BlockMeta_above; - if (UnboundedRelGetBlock(Try_X, Try_Y , Try_Z, BlockType, BlockMeta) && - UnboundedRelGetBlock(Try_X, Try_Y-1, Try_Z, BlockType_below, BlockMeta_below)&& - UnboundedRelGetBlock(Try_X, Try_Y+1, Try_Z, BlockType_above, BlockMeta_above) - ) + EMCSBiome Biome = m_ChunkMap->GetBiomeAt (Try_X, Try_Z); + // MG TODO : + // Moon cycle (for slime) + // check player and playerspawn presence < 24 blocks + // check mobs presence on the block + + // MG TODO : check that "Level" really means Y + + NIBBLETYPE SkyLight = 0; + + NIBBLETYPE BlockLight = 0; + + if (IsLightValid()) { - EMCSBiome Biome = m_ChunkMap->GetBiomeAt (Try_X, Try_Z); - // MG TODO : - // Moon cycle (for slime) - // check player and playerspawn presence < 24 blocks - // check mobs presence on the block - - // MG TODO : check that "Level" really means Y - - NIBBLETYPE SkyLight = 0; - - NIBBLETYPE BlockLight = 0; - - if (IsLightValid() && (UnboundedRelGetBlockBlockLight(Try_X, Try_Y, Try_Z, BlockLight)) && (UnboundedRelGetBlockSkyLight(Try_X, Try_Y, Try_Z, SkyLight))) + cEntity* newMob = a_MobSpawner.TryToSpawnHere(this, Try_X, Try_Y, Try_Z, Biome, MaxNbOfSuccess); + if (newMob) { - cEntity* newMob = a_MobSpawner.TryToSpawnHere(BlockType, BlockMeta, BlockType_below, BlockMeta_below, BlockType_above, BlockMeta_above, SkyLight, BlockLight, Biome, Try_Y, MaxNbOfSuccess); - if (newMob) - { - int WorldX, WorldY, WorldZ; - PositionToWorldPosition(Try_X, Try_Y, Try_Z, WorldX, WorldY, WorldZ); - double ActualX = WorldX + 0.5; - double ActualZ = WorldZ + 0.5; - newMob->SetPosition(ActualX, WorldY, ActualZ); - LOGD("Spawning %s #%i at %d,%d,%d",newMob->GetClass(),newMob->GetUniqueID(),WorldX, WorldY, WorldZ); - NumberOfSuccess++; - } + int WorldX, WorldY, WorldZ; + PositionToWorldPosition(Try_X, Try_Y, Try_Z, WorldX, WorldY, WorldZ); + double ActualX = WorldX + 0.5; + double ActualZ = WorldZ + 0.5; + newMob->SetPosition(ActualX, WorldY, ActualZ); + LOGD("Spawning %s #%i at %d,%d,%d",newMob->GetClass(),newMob->GetUniqueID(),WorldX, WorldY, WorldZ); + NumberOfSuccess++; } } diff --git a/source/MobSpawner.cpp b/source/MobSpawner.cpp index 35eee4ac..a076eaf0 100644 --- a/source/MobSpawner.cpp +++ b/source/MobSpawner.cpp @@ -124,57 +124,95 @@ cMonster::eType cMobSpawner::ChooseMobType(EMCSBiome a_Biome) -bool cMobSpawner::CanSpawnHere(cMonster::eType a_MobType, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, BLOCKTYPE a_BlockType_below, NIBBLETYPE a_BlockMeta_below, BLOCKTYPE a_BlockType_above, NIBBLETYPE a_BlockMeta_above, NIBBLETYPE a_Skylight, NIBBLETYPE a_Blocklight, EMCSBiome a_Biome, int a_Level) +bool cMobSpawner::CanSpawnHere(const cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ, cMonster::eType a_MobType, EMCSBiome a_Biome) { - if (m_AllowedTypes.find(a_MobType) != m_AllowedTypes.end()) + BLOCKTYPE TargetBlock; + BLOCKTYPE BlockAbove; + BLOCKTYPE BlockBelow; + NIBBLETYPE BlockLight; + NIBBLETYPE SkyLight; + if (m_AllowedTypes.find(a_MobType) != m_AllowedTypes.end() && a_Chunk->UnboundedRelGetBlockType(a_RelX, a_RelY, a_RelZ, TargetBlock)) { + + a_Chunk->UnboundedRelGetBlockBlockLight(a_RelX, a_RelY, a_RelZ, BlockLight); + a_Chunk->UnboundedRelGetBlockSkyLight(a_RelX, a_RelY, a_RelZ, SkyLight); + a_Chunk->UnboundedRelGetBlockType(a_RelX, a_RelY + 1, a_RelZ, BlockAbove); + a_Chunk->UnboundedRelGetBlockType(a_RelX, a_RelY - 1, a_RelZ, BlockBelow); switch(a_MobType) { case cMonster::mtSquid: - return IsBlockWater(a_BlockType) && (a_Level >= 45) && (a_Level <= 62); + return IsBlockWater(TargetBlock) && (a_RelY >= 45) && (a_RelY <= 62); case cMonster::mtBat: - return a_Level <= 63 && (a_Skylight == 0) && (a_Blocklight <= 4) && (a_BlockType == E_BLOCK_AIR) && (!g_BlockTransparent[a_BlockType_above]); + return (a_RelY <= 63) && (BlockLight <= 4) && (SkyLight <= 4) && (TargetBlock == E_BLOCK_AIR) && (!g_BlockTransparent[BlockAbove]); case cMonster::mtChicken: case cMonster::mtCow: case cMonster::mtPig: case cMonster::mtHorse: case cMonster::mtSheep: - return (a_BlockType == E_BLOCK_AIR) && (a_BlockType_above == E_BLOCK_AIR) && (!g_BlockTransparent[a_BlockType_below]) && - (a_BlockType_below == E_BLOCK_GRASS) && (a_Skylight >= 9); - + { + return (TargetBlock == E_BLOCK_AIR) && (BlockAbove == E_BLOCK_AIR) && (!g_BlockTransparent[BlockBelow]) && + (BlockBelow == E_BLOCK_GRASS) && (SkyLight >= 9); + } + case cMonster::mtOcelot: - return (a_BlockType == E_BLOCK_AIR) && (a_BlockType_above == E_BLOCK_AIR) && - ((a_BlockType_below == E_BLOCK_GRASS) || (a_BlockType_below == E_BLOCK_LEAVES)) && (a_Level >= 62) && (m_Random.NextInt(3,a_Biome) != 0); - + { + return (TargetBlock == E_BLOCK_AIR) && (BlockAbove == E_BLOCK_AIR) && + ((BlockBelow == E_BLOCK_GRASS) || (BlockBelow == E_BLOCK_LEAVES)) && (a_RelY >= 62) && (m_Random.NextInt(3,a_Biome) != 0); + } case cMonster::mtEnderman: + { + if (a_RelY < 250) + { + BLOCKTYPE BlockTop; + a_Chunk->UnboundedRelGetBlockType(a_RelX, a_RelY + 2, a_RelZ, BlockTop); + return (TargetBlock == E_BLOCK_AIR) && (BlockAbove == E_BLOCK_AIR) && (BlockTop == E_BLOCK_AIR) && (!g_BlockTransparent[BlockBelow]) && + (SkyLight <= 7) && (BlockLight <= 7); + } + break; + } case cMonster::mtSpider: - return false; + { + bool CanSpawn = true; + for (int x = -1; x < 2; ++x) + { + for(int z = -1; z < 2; ++x) + { + CanSpawn = a_Chunk->UnboundedRelGetBlockType(a_RelX + x, a_RelY, a_RelZ + z, TargetBlock); + CanSpawn = CanSpawn && (TargetBlock == E_BLOCK_AIR); + if (!CanSpawn) + return false; + } + } + return CanSpawn && (!g_BlockTransparent[BlockBelow]) && (SkyLight <= 7) && (BlockLight <= 7); + + } case cMonster::mtCreeper: case cMonster::mtZombie: - return (a_BlockType == E_BLOCK_AIR) && (a_BlockType_above == E_BLOCK_AIR) && (!g_BlockTransparent[a_BlockType_below]) && - (a_Skylight <= 7) && (a_Blocklight <= 7) && (m_Random.NextInt(2,a_Biome) == 0); + return (TargetBlock == E_BLOCK_AIR) && (BlockAbove == E_BLOCK_AIR) && (!g_BlockTransparent[BlockBelow]) && + (SkyLight <= 7) && (BlockLight <= 7) && (m_Random.NextInt(2,a_Biome) == 0); case cMonster::mtSlime: - return (a_BlockType == E_BLOCK_AIR) && (a_BlockType_above == E_BLOCK_AIR) && (!g_BlockTransparent[a_BlockType_below]) && - (a_Level <= 40); + return (TargetBlock == E_BLOCK_AIR) && (BlockAbove == E_BLOCK_AIR) && (!g_BlockTransparent[BlockBelow]) && + (a_RelY <= 40); case cMonster::mtGhast: case cMonster::mtZombiePigman: - return (a_BlockType == E_BLOCK_AIR) && (a_BlockType_above == E_BLOCK_AIR) && (!g_BlockTransparent[a_BlockType_below]) && + return (TargetBlock == E_BLOCK_AIR) && (BlockAbove == E_BLOCK_AIR) && (!g_BlockTransparent[BlockBelow]) && (m_Random.NextInt(20,a_Biome) == 0); default: LOGD("MG TODO : check I've got a Rule to write for type %d",a_MobType); return false; } } + return false; } -cMonster* cMobSpawner::TryToSpawnHere(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, BLOCKTYPE a_BlockType_below, NIBBLETYPE a_BlockMeta_below, BLOCKTYPE a_BlockType_above, NIBBLETYPE a_BlockMeta_above, NIBBLETYPE a_Skylight, NIBBLETYPE a_Blocklight, EMCSBiome a_Biome, int a_Level, int& a_MaxPackSize) +cMonster* cMobSpawner::TryToSpawnHere(const cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ, EMCSBiome a_Biome, int& a_MaxPackSize) { cMonster* toReturn = NULL; if (m_NewPack) @@ -196,7 +234,7 @@ cMonster* cMobSpawner::TryToSpawnHere(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockM } - if (CanSpawnHere(m_MobType, a_BlockType, a_BlockMeta, a_BlockType_below, a_BlockMeta_below, a_BlockType_above, a_BlockMeta_above, a_Skylight, a_Blocklight, a_Biome, a_Level)) + if (CanSpawnHere(a_Chunk, a_RelX, a_RelY, a_RelZ, m_MobType, a_Biome)) { cMonster * newMob = cMonster::NewMonsterFromType(m_MobType); if (newMob) diff --git a/source/MobSpawner.h b/source/MobSpawner.h index e5b7e9b6..22adb00f 100644 --- a/source/MobSpawner.h +++ b/source/MobSpawner.h @@ -4,6 +4,7 @@ #include #include "BlockID.h" #include "ChunkDef.h" +#include "Chunk.h" #include "FastRandom.h" #include "Mobs/Monster.h" //this is a side-effect of keeping Mobfamily inside Monster class. I'd prefer to keep both (Mobfamily and Monster) inside a "Monster" namespace MG TODO : do it @@ -38,7 +39,7 @@ public : // if this is the first of a Pack : determine the type of monster // BlockType & BlockMeta are used to decide what kind of Mob can Spawn here // MaxPackSize is set to the maximal size for a pack this type of mob - cMonster * TryToSpawnHere(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, BLOCKTYPE a_BlockType_below, NIBBLETYPE a_BlockMeta_below, BLOCKTYPE a_BlockType_above, NIBBLETYPE a_BlockMeta_above, NIBBLETYPE a_Skylight, NIBBLETYPE a_Blocklight, EMCSBiome a_Biome, int a_Level, int& a_MaxPackSize); + cMonster * TryToSpawnHere(const cChunk * a_Chunk, int A_RelX, int a_RelY, int a_RelZ, EMCSBiome a_Biome, int& a_MaxPackSize); // mark the beginning of a new Pack // all mobs of the same Pack are the same type @@ -52,7 +53,7 @@ public : protected : // return true if specified type of mob can spawn on specified block - bool CanSpawnHere(cMonster::eType a_MobType, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, BLOCKTYPE a_BlockType_below, NIBBLETYPE a_BlockMeta_below, BLOCKTYPE a_BlockType_above, NIBBLETYPE a_BlockMeta_above, NIBBLETYPE a_Skylight, NIBBLETYPE a_Blocklight, EMCSBiome a_Biome, int a_Level); + bool CanSpawnHere(const cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ, cMonster::eType a_MobType, EMCSBiome a_Biome); // return a random type that can spawn on specified biome. // returns E_ENTITY_TYPE_DONOTUSE if none is possible From 47283f9daa4a19514c211ceb1dc1e4bc7c06b26d Mon Sep 17 00:00:00 2001 From: Samuel Barney Date: Mon, 28 Oct 2013 16:38:34 -0600 Subject: [PATCH 13/16] Got spiders and other mobs respecting night and day for spawning --- source/Chunk.cpp | 3 ++- source/MobSpawner.cpp | 30 +++++++++++++++++++----------- source/MobSpawner.h | 4 ++-- 3 files changed, 23 insertions(+), 14 deletions(-) diff --git a/source/Chunk.cpp b/source/Chunk.cpp index 637b72b2..03883189 100644 --- a/source/Chunk.cpp +++ b/source/Chunk.cpp @@ -533,7 +533,8 @@ void cChunk::SpawnMobs(cMobSpawner& a_MobSpawner) if (IsLightValid()) { - cEntity* newMob = a_MobSpawner.TryToSpawnHere(this, Try_X, Try_Y, Try_Z, Biome, MaxNbOfSuccess); + int TimeOfDay = m_World->GetTimeOfDay(); + cEntity* newMob = a_MobSpawner.TryToSpawnHere(this, Try_X, Try_Y, Try_Z, Biome, TimeOfDay, MaxNbOfSuccess); if (newMob) { int WorldX, WorldY, WorldZ; diff --git a/source/MobSpawner.cpp b/source/MobSpawner.cpp index a076eaf0..7dff56d6 100644 --- a/source/MobSpawner.cpp +++ b/source/MobSpawner.cpp @@ -124,7 +124,7 @@ cMonster::eType cMobSpawner::ChooseMobType(EMCSBiome a_Biome) -bool cMobSpawner::CanSpawnHere(const cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ, cMonster::eType a_MobType, EMCSBiome a_Biome) +bool cMobSpawner::CanSpawnHere(const cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ, cMonster::eType a_MobType, int a_TimeOfDay, EMCSBiome a_Biome) { BLOCKTYPE TargetBlock; BLOCKTYPE BlockAbove; @@ -144,7 +144,7 @@ bool cMobSpawner::CanSpawnHere(const cChunk * a_Chunk, int a_RelX, int a_RelY, i return IsBlockWater(TargetBlock) && (a_RelY >= 45) && (a_RelY <= 62); case cMonster::mtBat: - return (a_RelY <= 63) && (BlockLight <= 4) && (SkyLight <= 4) && (TargetBlock == E_BLOCK_AIR) && (!g_BlockTransparent[BlockAbove]); + return (a_RelY <= 63) && (BlockLight <= 4) && (SkyLight <= 4 || a_TimeOfDay > 12500) && (TargetBlock == E_BLOCK_AIR) && (!g_BlockTransparent[BlockAbove]); case cMonster::mtChicken: case cMonster::mtCow: @@ -153,7 +153,7 @@ bool cMobSpawner::CanSpawnHere(const cChunk * a_Chunk, int a_RelX, int a_RelY, i case cMonster::mtSheep: { return (TargetBlock == E_BLOCK_AIR) && (BlockAbove == E_BLOCK_AIR) && (!g_BlockTransparent[BlockBelow]) && - (BlockBelow == E_BLOCK_GRASS) && (SkyLight >= 9); + (BlockBelow == E_BLOCK_GRASS) && (SkyLight >= 9) && (a_TimeOfDay <= 12500); } case cMonster::mtOcelot: @@ -168,34 +168,42 @@ bool cMobSpawner::CanSpawnHere(const cChunk * a_Chunk, int a_RelX, int a_RelY, i BLOCKTYPE BlockTop; a_Chunk->UnboundedRelGetBlockType(a_RelX, a_RelY + 2, a_RelZ, BlockTop); return (TargetBlock == E_BLOCK_AIR) && (BlockAbove == E_BLOCK_AIR) && (BlockTop == E_BLOCK_AIR) && (!g_BlockTransparent[BlockBelow]) && - (SkyLight <= 7) && (BlockLight <= 7); + ((SkyLight <= 7) || a_TimeOfDay > 12500 ) && (BlockLight <= 7) ; } break; } case cMonster::mtSpider: { bool CanSpawn = true; - for (int x = -1; x < 2; ++x) + bool HaveFloor = false; + for (int x = 0; x < 2; ++x) { - for(int z = -1; z < 2; ++x) + for(int z = 0; z < 2; ++z) { CanSpawn = a_Chunk->UnboundedRelGetBlockType(a_RelX + x, a_RelY, a_RelZ + z, TargetBlock); CanSpawn = CanSpawn && (TargetBlock == E_BLOCK_AIR); if (!CanSpawn) + { return false; + } + if (!HaveFloor) + { + a_Chunk->UnboundedRelGetBlockType(a_RelX + x, a_RelY - 1, a_RelZ + z, TargetBlock); + HaveFloor = HaveFloor || !g_BlockTransparent[TargetBlock]; + } } } - return CanSpawn && (!g_BlockTransparent[BlockBelow]) && (SkyLight <= 7) && (BlockLight <= 7); + return CanSpawn && HaveFloor && ((SkyLight <= 7) || a_TimeOfDay > 12500) && (BlockLight <= 7); } case cMonster::mtCreeper: case cMonster::mtZombie: return (TargetBlock == E_BLOCK_AIR) && (BlockAbove == E_BLOCK_AIR) && (!g_BlockTransparent[BlockBelow]) && - (SkyLight <= 7) && (BlockLight <= 7) && (m_Random.NextInt(2,a_Biome) == 0); + ((SkyLight <= 7) || a_TimeOfDay > 12500) && (BlockLight <= 7) && (m_Random.NextInt(2,a_Biome) == 0); case cMonster::mtSlime: return (TargetBlock == E_BLOCK_AIR) && (BlockAbove == E_BLOCK_AIR) && (!g_BlockTransparent[BlockBelow]) && - (a_RelY <= 40); + ((a_RelY <= 40) || a_Biome == biSwampland); case cMonster::mtGhast: case cMonster::mtZombiePigman: return (TargetBlock == E_BLOCK_AIR) && (BlockAbove == E_BLOCK_AIR) && (!g_BlockTransparent[BlockBelow]) && @@ -212,7 +220,7 @@ bool cMobSpawner::CanSpawnHere(const cChunk * a_Chunk, int a_RelX, int a_RelY, i -cMonster* cMobSpawner::TryToSpawnHere(const cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ, EMCSBiome a_Biome, int& a_MaxPackSize) +cMonster* cMobSpawner::TryToSpawnHere(const cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ, EMCSBiome a_Biome, int a_TimeOfDay, int& a_MaxPackSize) { cMonster* toReturn = NULL; if (m_NewPack) @@ -234,7 +242,7 @@ cMonster* cMobSpawner::TryToSpawnHere(const cChunk * a_Chunk, int a_RelX, int a_ } - if (CanSpawnHere(a_Chunk, a_RelX, a_RelY, a_RelZ, m_MobType, a_Biome)) + if (CanSpawnHere(a_Chunk, a_RelX, a_RelY, a_RelZ, m_MobType, a_TimeOfDay, a_Biome)) { cMonster * newMob = cMonster::NewMonsterFromType(m_MobType); if (newMob) diff --git a/source/MobSpawner.h b/source/MobSpawner.h index 22adb00f..3b9ede7c 100644 --- a/source/MobSpawner.h +++ b/source/MobSpawner.h @@ -39,7 +39,7 @@ public : // if this is the first of a Pack : determine the type of monster // BlockType & BlockMeta are used to decide what kind of Mob can Spawn here // MaxPackSize is set to the maximal size for a pack this type of mob - cMonster * TryToSpawnHere(const cChunk * a_Chunk, int A_RelX, int a_RelY, int a_RelZ, EMCSBiome a_Biome, int& a_MaxPackSize); + cMonster * TryToSpawnHere(const cChunk * a_Chunk, int A_RelX, int a_RelY, int a_RelZ, EMCSBiome a_Biome, int a_TimeOfDay, int& a_MaxPackSize); // mark the beginning of a new Pack // all mobs of the same Pack are the same type @@ -53,7 +53,7 @@ public : protected : // return true if specified type of mob can spawn on specified block - bool CanSpawnHere(const cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ, cMonster::eType a_MobType, EMCSBiome a_Biome); + bool CanSpawnHere(const cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ, cMonster::eType a_MobType, int a_TimeOfDay, EMCSBiome a_Biome); // return a random type that can spawn on specified biome. // returns E_ENTITY_TYPE_DONOTUSE if none is possible From e1a06153b2e93473af58e1d801998ff7f388dc6d Mon Sep 17 00:00:00 2001 From: Samuel Barney Date: Tue, 29 Oct 2013 10:44:51 -0600 Subject: [PATCH 14/16] Update to allow the light map to remain the same, but allow alteration of sky light values based on time. --- source/Chunk.cpp | 13 +++++++++++-- source/Chunk.h | 3 +++ source/MobSpawner.cpp | 25 ++++++++++++++++--------- source/MobSpawner.h | 4 ++-- source/Mobs/Monster.cpp | 6 +++--- source/World.cpp | 32 +++++++++++++++++++++++++++++++- source/World.h | 7 +++++++ 7 files changed, 73 insertions(+), 17 deletions(-) diff --git a/source/Chunk.cpp b/source/Chunk.cpp index c419cf7f..b38f5ea1 100644 --- a/source/Chunk.cpp +++ b/source/Chunk.cpp @@ -533,8 +533,7 @@ void cChunk::SpawnMobs(cMobSpawner& a_MobSpawner) if (IsLightValid()) { - int TimeOfDay = m_World->GetTimeOfDay(); - cEntity* newMob = a_MobSpawner.TryToSpawnHere(this, Try_X, Try_Y, Try_Z, Biome, TimeOfDay, MaxNbOfSuccess); + cEntity* newMob = a_MobSpawner.TryToSpawnHere(this, Try_X, Try_Y, Try_Z, Biome, MaxNbOfSuccess); if (newMob) { int WorldX, WorldY, WorldZ; @@ -2787,6 +2786,16 @@ Vector3i cChunk::PositionToWorldPosition(int a_RelX, int a_RelY, int a_RelZ) +NIBBLETYPE cChunk::GetTimeAlteredLight(NIBBLETYPE a_Skylight) const +{ + a_Skylight -= m_World->GetSkyDarkness(); + return (a_Skylight < 16)? a_Skylight : 0; +} + + + + + #if !C_CHUNK_USE_INLINE # include "cChunk.inl.h" #endif diff --git a/source/Chunk.h b/source/Chunk.h index 591e29ad..8648bdd2 100644 --- a/source/Chunk.h +++ b/source/Chunk.h @@ -329,6 +329,9 @@ public: /// 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; + // Simulator data: cFireSimulatorChunkData & GetFireSimulatorData (void) { return m_FireSimulatorData; } diff --git a/source/MobSpawner.cpp b/source/MobSpawner.cpp index 7dff56d6..7c7b25b6 100644 --- a/source/MobSpawner.cpp +++ b/source/MobSpawner.cpp @@ -124,7 +124,7 @@ cMonster::eType cMobSpawner::ChooseMobType(EMCSBiome a_Biome) -bool cMobSpawner::CanSpawnHere(const cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ, cMonster::eType a_MobType, int a_TimeOfDay, EMCSBiome a_Biome) +bool cMobSpawner::CanSpawnHere(const cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ, cMonster::eType a_MobType, EMCSBiome a_Biome) { BLOCKTYPE TargetBlock; BLOCKTYPE BlockAbove; @@ -138,13 +138,16 @@ bool cMobSpawner::CanSpawnHere(const cChunk * a_Chunk, int a_RelX, int a_RelY, i a_Chunk->UnboundedRelGetBlockSkyLight(a_RelX, a_RelY, a_RelZ, SkyLight); a_Chunk->UnboundedRelGetBlockType(a_RelX, a_RelY + 1, a_RelZ, BlockAbove); a_Chunk->UnboundedRelGetBlockType(a_RelX, a_RelY - 1, a_RelZ, BlockBelow); + + SkyLight = a_Chunk->GetTimeAlteredLight(SkyLight); + switch(a_MobType) { case cMonster::mtSquid: return IsBlockWater(TargetBlock) && (a_RelY >= 45) && (a_RelY <= 62); case cMonster::mtBat: - return (a_RelY <= 63) && (BlockLight <= 4) && (SkyLight <= 4 || a_TimeOfDay > 12500) && (TargetBlock == E_BLOCK_AIR) && (!g_BlockTransparent[BlockAbove]); + return (a_RelY <= 63) && (BlockLight <= 4) && (SkyLight <= 4) && (TargetBlock == E_BLOCK_AIR) && (!g_BlockTransparent[BlockAbove]); case cMonster::mtChicken: case cMonster::mtCow: @@ -153,7 +156,7 @@ bool cMobSpawner::CanSpawnHere(const cChunk * a_Chunk, int a_RelX, int a_RelY, i case cMonster::mtSheep: { return (TargetBlock == E_BLOCK_AIR) && (BlockAbove == E_BLOCK_AIR) && (!g_BlockTransparent[BlockBelow]) && - (BlockBelow == E_BLOCK_GRASS) && (SkyLight >= 9) && (a_TimeOfDay <= 12500); + (BlockBelow == E_BLOCK_GRASS) && (SkyLight >= 9); } case cMonster::mtOcelot: @@ -167,8 +170,12 @@ bool cMobSpawner::CanSpawnHere(const cChunk * a_Chunk, int a_RelX, int a_RelY, i { BLOCKTYPE BlockTop; a_Chunk->UnboundedRelGetBlockType(a_RelX, a_RelY + 2, a_RelZ, BlockTop); - return (TargetBlock == E_BLOCK_AIR) && (BlockAbove == E_BLOCK_AIR) && (BlockTop == E_BLOCK_AIR) && (!g_BlockTransparent[BlockBelow]) && - ((SkyLight <= 7) || a_TimeOfDay > 12500 ) && (BlockLight <= 7) ; + if (BlockTop == E_BLOCK_AIR) + { + a_Chunk->UnboundedRelGetBlockType(a_RelX, a_RelY + 3, a_RelZ, BlockTop); + return (TargetBlock == E_BLOCK_AIR) && (BlockAbove == E_BLOCK_AIR) && (BlockTop == E_BLOCK_AIR) && (!g_BlockTransparent[BlockBelow]) && + (SkyLight <= 7) && (BlockLight <= 7); + } } break; } @@ -193,13 +200,13 @@ bool cMobSpawner::CanSpawnHere(const cChunk * a_Chunk, int a_RelX, int a_RelY, i } } } - return CanSpawn && HaveFloor && ((SkyLight <= 7) || a_TimeOfDay > 12500) && (BlockLight <= 7); + return CanSpawn && HaveFloor && (SkyLight <= 7) && (BlockLight <= 7); } case cMonster::mtCreeper: case cMonster::mtZombie: return (TargetBlock == E_BLOCK_AIR) && (BlockAbove == E_BLOCK_AIR) && (!g_BlockTransparent[BlockBelow]) && - ((SkyLight <= 7) || a_TimeOfDay > 12500) && (BlockLight <= 7) && (m_Random.NextInt(2,a_Biome) == 0); + (SkyLight <= 7) && (BlockLight <= 7) && (m_Random.NextInt(2,a_Biome) == 0); case cMonster::mtSlime: return (TargetBlock == E_BLOCK_AIR) && (BlockAbove == E_BLOCK_AIR) && (!g_BlockTransparent[BlockBelow]) && @@ -220,7 +227,7 @@ bool cMobSpawner::CanSpawnHere(const cChunk * a_Chunk, int a_RelX, int a_RelY, i -cMonster* cMobSpawner::TryToSpawnHere(const cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ, EMCSBiome a_Biome, int a_TimeOfDay, int& a_MaxPackSize) +cMonster* cMobSpawner::TryToSpawnHere(const cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ, EMCSBiome a_Biome, int& a_MaxPackSize) { cMonster* toReturn = NULL; if (m_NewPack) @@ -242,7 +249,7 @@ cMonster* cMobSpawner::TryToSpawnHere(const cChunk * a_Chunk, int a_RelX, int a_ } - if (CanSpawnHere(a_Chunk, a_RelX, a_RelY, a_RelZ, m_MobType, a_TimeOfDay, a_Biome)) + if (CanSpawnHere(a_Chunk, a_RelX, a_RelY, a_RelZ, m_MobType, a_Biome)) { cMonster * newMob = cMonster::NewMonsterFromType(m_MobType); if (newMob) diff --git a/source/MobSpawner.h b/source/MobSpawner.h index 3b9ede7c..22adb00f 100644 --- a/source/MobSpawner.h +++ b/source/MobSpawner.h @@ -39,7 +39,7 @@ public : // if this is the first of a Pack : determine the type of monster // BlockType & BlockMeta are used to decide what kind of Mob can Spawn here // MaxPackSize is set to the maximal size for a pack this type of mob - cMonster * TryToSpawnHere(const cChunk * a_Chunk, int A_RelX, int a_RelY, int a_RelZ, EMCSBiome a_Biome, int a_TimeOfDay, int& a_MaxPackSize); + cMonster * TryToSpawnHere(const cChunk * a_Chunk, int A_RelX, int a_RelY, int a_RelZ, EMCSBiome a_Biome, int& a_MaxPackSize); // mark the beginning of a new Pack // all mobs of the same Pack are the same type @@ -53,7 +53,7 @@ public : protected : // return true if specified type of mob can spawn on specified block - bool CanSpawnHere(const cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ, cMonster::eType a_MobType, int a_TimeOfDay, EMCSBiome a_Biome); + bool CanSpawnHere(const cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ, cMonster::eType a_MobType, EMCSBiome a_Biome); // return a random type that can spawn on specified biome. // returns E_ENTITY_TYPE_DONOTUSE if none is possible diff --git a/source/Mobs/Monster.cpp b/source/Mobs/Monster.cpp index 9b1f2fc4..72dfb258 100644 --- a/source/Mobs/Monster.cpp +++ b/source/Mobs/Monster.cpp @@ -609,9 +609,9 @@ int cMonster::GetSpawnDelay(cMonster::eFamily a_MobFamily) { switch (a_MobFamily) { - case mfHostile: return 1; - case mfPassive: return 400; - case mfAmbient: return 400; + case mfHostile: return 40; + case mfPassive: return 40; + case mfAmbient: return 40; case mfWater: return 400; } ASSERT(!"Unhandled mob family"); diff --git a/source/World.cpp b/source/World.cpp index 786d97a4..dcd51afc 100644 --- a/source/World.cpp +++ b/source/World.cpp @@ -229,7 +229,8 @@ cWorld::cWorld(const AString & a_WorldName) : m_RSList(0), m_Weather(eWeather_Sunny), m_WeatherInterval(24000), // Guaranteed 1 day of sunshine at server start :) - m_TickThread(*this) + m_TickThread(*this), + m_SkyDarkness(0) { LOGD("cWorld::cWorld(\"%s\")", a_WorldName.c_str()); @@ -608,6 +609,8 @@ void cWorld::Tick(float a_Dt) m_WorldAge = (Int64)(m_WorldAgeSecs * 20.0); m_TimeOfDay = (Int64)(m_TimeOfDaySecs * 20.0); + UpdateSkyDarkness(); + // Broadcast time update every 40 ticks (2 seconds) if (m_LastTimeUpdate < m_WorldAge - 40) { @@ -2676,3 +2679,30 @@ void cWorld::cTaskSaveAllChunks::Run(cWorld & a_World) + +#define TIME_SUNSET 12000 +#define TIME_NIGHT_START 13187 +#define TIME_NIGHT_END 22812 +#define TIME_SUNRISE 23999 +#define TIME_SPAWN_DIVIZOR 148 + + + + + +void cWorld::UpdateSkyDarkness() +{ + int TempTime = m_TimeOfDay; + if (TempTime <= TIME_SUNSET) + m_SkyDarkness = 0; + else if (TempTime <= TIME_NIGHT_START) + m_SkyDarkness = (TIME_NIGHT_START - TempTime)/TIME_SPAWN_DIVIZOR; + else if (TempTime <= TIME_NIGHT_END) + m_SkyDarkness = 8; + else + m_SkyDarkness = (TIME_SUNRISE - TempTime)/TIME_SPAWN_DIVIZOR; +} + + + + diff --git a/source/World.h b/source/World.h index f174a1c2..5976321e 100644 --- a/source/World.h +++ b/source/World.h @@ -592,6 +592,9 @@ public: /// Appends all usernames starting with a_Text (case-insensitive) into Results void TabCompleteUserName(const AString & a_Text, AStringVector & a_Results); + /// Get the current darkness level based on the time + Int64 GetSkyDarkness() { return m_SkyDarkness; } + private: friend class cRoot; @@ -636,6 +639,8 @@ private: Int64 m_LastSave; // The last WorldAge (in ticks) in which save-all was triggerred std::map m_LastSpawnMonster; // The last WorldAge (in ticks) in which a monster was spawned (for each megatype of monster) // MG TODO : find a way to optimize without creating unmaintenability (if mob IDs are becoming unrowed) + Int64 m_SkyDarkness; + eGameMode m_GameMode; bool m_bEnabledPVP; bool m_IsDeepSnowEnabled; @@ -727,6 +732,8 @@ private: /// Ticks all clients that are in this world void TickClients(float a_Dt); + + void UpdateSkyDarkness(); /// Creates a new fluid simulator, loads its settings from the inifile (a_FluidName section) cFluidSimulator * InitializeFluidSimulator(cIniFile & a_IniFile, const char * a_FluidName, BLOCKTYPE a_SimulateBlock, BLOCKTYPE a_StationaryBlock); From e94307c29242e9d7e663c774840568a2b73fd400 Mon Sep 17 00:00:00 2001 From: Samuel Barney Date: Tue, 29 Oct 2013 12:43:41 -0600 Subject: [PATCH 15/16] Changes based on madmaxoft's nitpicker notes. --- source/Chunk.h | 2 +- source/MobSpawner.cpp | 24 ++++++++++-------------- source/MobSpawner.h | 4 ++-- source/World.cpp | 1 + source/World.h | 4 ++-- 5 files changed, 16 insertions(+), 19 deletions(-) diff --git a/source/Chunk.h b/source/Chunk.h index 8648bdd2..63a8f75c 100644 --- a/source/Chunk.h +++ b/source/Chunk.h @@ -329,7 +329,7 @@ public: /// 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 + /// Light alterations based on time NIBBLETYPE GetTimeAlteredLight(NIBBLETYPE a_Skylight) const; diff --git a/source/MobSpawner.cpp b/source/MobSpawner.cpp index 7c7b25b6..d4926bbe 100644 --- a/source/MobSpawner.cpp +++ b/source/MobSpawner.cpp @@ -124,20 +124,15 @@ cMonster::eType cMobSpawner::ChooseMobType(EMCSBiome a_Biome) -bool cMobSpawner::CanSpawnHere(const cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ, cMonster::eType a_MobType, EMCSBiome a_Biome) +bool cMobSpawner::CanSpawnHere(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ, cMonster::eType a_MobType, EMCSBiome a_Biome) { BLOCKTYPE TargetBlock; - BLOCKTYPE BlockAbove; - BLOCKTYPE BlockBelow; - NIBBLETYPE BlockLight; - NIBBLETYPE SkyLight; if (m_AllowedTypes.find(a_MobType) != m_AllowedTypes.end() && a_Chunk->UnboundedRelGetBlockType(a_RelX, a_RelY, a_RelZ, TargetBlock)) { - - a_Chunk->UnboundedRelGetBlockBlockLight(a_RelX, a_RelY, a_RelZ, BlockLight); - a_Chunk->UnboundedRelGetBlockSkyLight(a_RelX, a_RelY, a_RelZ, SkyLight); - a_Chunk->UnboundedRelGetBlockType(a_RelX, a_RelY + 1, a_RelZ, BlockAbove); - a_Chunk->UnboundedRelGetBlockType(a_RelX, a_RelY - 1, a_RelZ, BlockBelow); + NIBBLETYPE BlockLight = a_Chunk->GetBlockLight(a_RelX, a_RelY, a_RelZ); + NIBBLETYPE SkyLight = a_Chunk->GetSkyLight(a_RelX, a_RelY, a_RelZ); + BLOCKTYPE BlockAbove = a_Chunk->GetBlock(a_RelX, a_RelY + 1, a_RelZ); + BLOCKTYPE BlockBelow = a_Chunk->GetBlock(a_RelX, a_RelY - 1, a_RelZ); SkyLight = a_Chunk->GetTimeAlteredLight(SkyLight); @@ -168,11 +163,10 @@ bool cMobSpawner::CanSpawnHere(const cChunk * a_Chunk, int a_RelX, int a_RelY, i { if (a_RelY < 250) { - BLOCKTYPE BlockTop; - a_Chunk->UnboundedRelGetBlockType(a_RelX, a_RelY + 2, a_RelZ, BlockTop); + BLOCKTYPE BlockTop = a_Chunk->GetBlock(a_RelX, a_RelY + 2, a_RelZ); if (BlockTop == E_BLOCK_AIR) { - a_Chunk->UnboundedRelGetBlockType(a_RelX, a_RelY + 3, a_RelZ, BlockTop); + BlockTop = a_Chunk->GetBlock(a_RelX, a_RelY + 3, a_RelZ); return (TargetBlock == E_BLOCK_AIR) && (BlockAbove == E_BLOCK_AIR) && (BlockTop == E_BLOCK_AIR) && (!g_BlockTransparent[BlockBelow]) && (SkyLight <= 7) && (BlockLight <= 7); } @@ -227,7 +221,7 @@ bool cMobSpawner::CanSpawnHere(const cChunk * a_Chunk, int a_RelX, int a_RelY, i -cMonster* cMobSpawner::TryToSpawnHere(const cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ, EMCSBiome a_Biome, int& a_MaxPackSize) +cMonster* cMobSpawner::TryToSpawnHere(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ, EMCSBiome a_Biome, int& a_MaxPackSize) { cMonster* toReturn = NULL; if (m_NewPack) @@ -248,6 +242,8 @@ cMonster* cMobSpawner::TryToSpawnHere(const cChunk * a_Chunk, int a_RelX, int a_ m_NewPack = false; } + // Make sure we are looking at the right chunk to spawn in + a_Chunk = a_Chunk->GetRelNeighborChunkAdjustCoords(a_RelX, a_RelZ); if (CanSpawnHere(a_Chunk, a_RelX, a_RelY, a_RelZ, m_MobType, a_Biome)) { diff --git a/source/MobSpawner.h b/source/MobSpawner.h index 22adb00f..ea663631 100644 --- a/source/MobSpawner.h +++ b/source/MobSpawner.h @@ -39,7 +39,7 @@ public : // if this is the first of a Pack : determine the type of monster // BlockType & BlockMeta are used to decide what kind of Mob can Spawn here // MaxPackSize is set to the maximal size for a pack this type of mob - cMonster * TryToSpawnHere(const cChunk * a_Chunk, int A_RelX, int a_RelY, int a_RelZ, EMCSBiome a_Biome, int& a_MaxPackSize); + cMonster * TryToSpawnHere(cChunk * a_Chunk, int A_RelX, int a_RelY, int a_RelZ, EMCSBiome a_Biome, int& a_MaxPackSize); // mark the beginning of a new Pack // all mobs of the same Pack are the same type @@ -53,7 +53,7 @@ public : protected : // return true if specified type of mob can spawn on specified block - bool CanSpawnHere(const cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ, cMonster::eType a_MobType, EMCSBiome a_Biome); + bool CanSpawnHere(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ, cMonster::eType a_MobType, EMCSBiome a_Biome); // return a random type that can spawn on specified biome. // returns E_ENTITY_TYPE_DONOTUSE if none is possible diff --git a/source/World.cpp b/source/World.cpp index dcd51afc..ad34dc6a 100644 --- a/source/World.cpp +++ b/source/World.cpp @@ -609,6 +609,7 @@ void cWorld::Tick(float a_Dt) m_WorldAge = (Int64)(m_WorldAgeSecs * 20.0); m_TimeOfDay = (Int64)(m_TimeOfDaySecs * 20.0); + // Updates the sky darkness based on current time of day UpdateSkyDarkness(); // Broadcast time update every 40 ticks (2 seconds) diff --git a/source/World.h b/source/World.h index 5976321e..c4fd06d0 100644 --- a/source/World.h +++ b/source/World.h @@ -593,7 +593,7 @@ public: void TabCompleteUserName(const AString & a_Text, AStringVector & a_Results); /// Get the current darkness level based on the time - Int64 GetSkyDarkness() { return m_SkyDarkness; } + NIBBLETYPE GetSkyDarkness() { return m_SkyDarkness; } private: @@ -639,7 +639,7 @@ private: Int64 m_LastSave; // The last WorldAge (in ticks) in which save-all was triggerred std::map m_LastSpawnMonster; // The last WorldAge (in ticks) in which a monster was spawned (for each megatype of monster) // MG TODO : find a way to optimize without creating unmaintenability (if mob IDs are becoming unrowed) - Int64 m_SkyDarkness; + NIBBLETYPE m_SkyDarkness; eGameMode m_GameMode; bool m_bEnabledPVP; From 7157c392fa81f699ec66a5eda495a9bad465ea81 Mon Sep 17 00:00:00 2001 From: Samuel Barney Date: Wed, 30 Oct 2013 16:14:42 -0600 Subject: [PATCH 16/16] Last of the nitpicker note fixes. Added some inline commenting. --- source/Chunk.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/source/Chunk.cpp b/source/Chunk.cpp index b38f5ea1..be75eae4 100644 --- a/source/Chunk.cpp +++ b/source/Chunk.cpp @@ -2789,6 +2789,7 @@ Vector3i cChunk::PositionToWorldPosition(int a_RelX, int a_RelY, int a_RelZ) NIBBLETYPE cChunk::GetTimeAlteredLight(NIBBLETYPE a_Skylight) const { a_Skylight -= m_World->GetSkyDarkness(); + // Because NIBBLETYPE is unsigned, we clamp it to 0 .. 15 by checking for values above 15 return (a_Skylight < 16)? a_Skylight : 0; }