mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/4jcraft.git
synced 2026-06-17 11:21:53 +00:00
chore: format Minecraft.World
This commit is contained in:
@@ -20,27 +20,28 @@
|
||||
|
||||
const int MobSpawner::MIN_SPAWN_DISTANCE = 24;
|
||||
|
||||
TilePos MobSpawner::getRandomPosWithin(Level *level, int cx, int cz)
|
||||
{
|
||||
// 4J Stu - Added 1.2.3 but we don't need it as it was only used to access sections
|
||||
// Leaving here though to help explain why chunk coords are not passed in rather than full coords
|
||||
//LevelChunk *chunk = level->getChunk(cx, cz);
|
||||
int x = cx * 16 + level->random->nextInt(16);
|
||||
int y = level->random->nextInt(level->getHeight());
|
||||
int z = cz * 16 + level->random->nextInt(16);
|
||||
TilePos MobSpawner::getRandomPosWithin(Level* level, int cx, int cz) {
|
||||
// 4J Stu - Added 1.2.3 but we don't need it as it was only used to access
|
||||
// sections Leaving here though to help explain why chunk coords are not
|
||||
// passed in rather than full coords
|
||||
// LevelChunk *chunk = level->getChunk(cx, cz);
|
||||
int x = cx * 16 + level->random->nextInt(16);
|
||||
int y = level->random->nextInt(level->getHeight());
|
||||
int z = cz * 16 + level->random->nextInt(16);
|
||||
|
||||
return TilePos(x, y, z);
|
||||
return TilePos(x, y, z);
|
||||
}
|
||||
|
||||
#ifdef __PSVITA__
|
||||
// AP - See CustomMap.h for an explanation of this
|
||||
CustomMap MobSpawner::chunksToPoll;
|
||||
// AP - See CustomMap.h for an explanation of this
|
||||
CustomMap MobSpawner::chunksToPoll;
|
||||
#else
|
||||
std::unordered_map<ChunkPos,bool,ChunkPosKeyHash,ChunkPosKeyEq> MobSpawner::chunksToPoll;
|
||||
std::unordered_map<ChunkPos, bool, ChunkPosKeyHash, ChunkPosKeyEq>
|
||||
MobSpawner::chunksToPoll;
|
||||
#endif
|
||||
|
||||
const int MobSpawner::tick(ServerLevel *level, bool spawnEnemies, bool spawnFriendlies)
|
||||
{
|
||||
const int MobSpawner::tick(ServerLevel* level, bool spawnEnemies,
|
||||
bool spawnFriendlies) {
|
||||
#ifndef _CONTENT_PACKAGE
|
||||
|
||||
#if 0
|
||||
@@ -94,13 +95,12 @@ const int MobSpawner::tick(ServerLevel *level, bool spawnEnemies, bool spawnFrie
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (!spawnEnemies && !spawnFriendlies)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
MemSect(20);
|
||||
chunksToPoll.clear();
|
||||
|
||||
if (!spawnEnemies && !spawnFriendlies) {
|
||||
return 0;
|
||||
}
|
||||
MemSect(20);
|
||||
chunksToPoll.clear();
|
||||
|
||||
#if 0
|
||||
AUTO_VAR(itEnd, level->players.end());
|
||||
for (AUTO_VAR(it, level->players.begin()); it != itEnd; it++)
|
||||
@@ -117,478 +117,527 @@ const int MobSpawner::tick(ServerLevel *level, bool spawnEnemies, bool spawnFrie
|
||||
}
|
||||
}
|
||||
#else
|
||||
// 4J - rewritten to add chunks interleaved by player, and to add them from the centre outwards. We're going to be
|
||||
// potentially adding less creatures than the original so that our count stays consistent with number of players added, so
|
||||
// we want to make sure as best we can that the ones we do add are near the active players
|
||||
int playerCount = (int)level->players.size();
|
||||
int *xx = new int[playerCount];
|
||||
int *zz = new int[playerCount];
|
||||
for (int i = 0; i < playerCount; i++)
|
||||
{
|
||||
std::shared_ptr<Player> player = level->players[i];
|
||||
xx[i] = Mth::floor(player->x / 16);
|
||||
zz[i] = Mth::floor(player->z / 16);
|
||||
// 4J - rewritten to add chunks interleaved by player, and to add them from
|
||||
// the centre outwards. We're going to be potentially adding less creatures
|
||||
// than the original so that our count stays consistent with number of
|
||||
// players added, so we want to make sure as best we can that the ones we do
|
||||
// add are near the active players
|
||||
int playerCount = (int)level->players.size();
|
||||
int* xx = new int[playerCount];
|
||||
int* zz = new int[playerCount];
|
||||
for (int i = 0; i < playerCount; i++) {
|
||||
std::shared_ptr<Player> player = level->players[i];
|
||||
xx[i] = Mth::floor(player->x / 16);
|
||||
zz[i] = Mth::floor(player->z / 16);
|
||||
#ifdef __PSVITA__
|
||||
chunksToPoll.insert(ChunkPos(xx[i], zz[i] ),false);
|
||||
chunksToPoll.insert(ChunkPos(xx[i], zz[i]), false);
|
||||
#else
|
||||
chunksToPoll.insert(std::pair<ChunkPos,bool>(ChunkPos(xx[i], zz[i] ),false));
|
||||
chunksToPoll.insert(
|
||||
std::pair<ChunkPos, bool>(ChunkPos(xx[i], zz[i]), false));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
for( int r = 1; r <= 8; r++ )
|
||||
{
|
||||
for( int l = 0; l < ( r * 2 ) ; l++ )
|
||||
{
|
||||
for( int i = 0; i < playerCount; i++ )
|
||||
{
|
||||
bool edgeChunk = ( r == 8 );
|
||||
for (int r = 1; r <= 8; r++) {
|
||||
for (int l = 0; l < (r * 2); l++) {
|
||||
for (int i = 0; i < playerCount; i++) {
|
||||
bool edgeChunk = (r == 8);
|
||||
|
||||
// If this chunk isn't at the edge of the region for this player, then always store with a flag of false
|
||||
// so that if it was at the edge of another player, then this will remove that
|
||||
if( !edgeChunk )
|
||||
{
|
||||
// If this chunk isn't at the edge of the region for this
|
||||
// player, then always store with a flag of false so that if it
|
||||
// was at the edge of another player, then this will remove that
|
||||
if (!edgeChunk) {
|
||||
#ifdef __PSVITA__
|
||||
chunksToPoll.insert(ChunkPos( ( xx[i] - r ) + l , ( zz[i] - r ) ), false);
|
||||
chunksToPoll.insert(ChunkPos( ( xx[i] + r ) , ( zz[i] - r ) + l ), false);
|
||||
chunksToPoll.insert(ChunkPos( ( xx[i] + r ) - l , ( zz[i] + r ) ), false);
|
||||
chunksToPoll.insert(ChunkPos( ( xx[i] - r ) , ( zz[i] + r ) - l ), false);
|
||||
chunksToPoll.insert(ChunkPos((xx[i] - r) + l, (zz[i] - r)),
|
||||
false);
|
||||
chunksToPoll.insert(ChunkPos((xx[i] + r), (zz[i] - r) + l),
|
||||
false);
|
||||
chunksToPoll.insert(ChunkPos((xx[i] + r) - l, (zz[i] + r)),
|
||||
false);
|
||||
chunksToPoll.insert(ChunkPos((xx[i] - r), (zz[i] + r) - l),
|
||||
false);
|
||||
#else
|
||||
chunksToPoll.insert(std::pair<ChunkPos,bool>(ChunkPos( ( xx[i] - r ) + l , ( zz[i] - r ) ), false));
|
||||
chunksToPoll.insert(std::pair<ChunkPos,bool>(ChunkPos( ( xx[i] + r ) , ( zz[i] - r ) + l ), false));
|
||||
chunksToPoll.insert(std::pair<ChunkPos,bool>(ChunkPos( ( xx[i] + r ) - l , ( zz[i] + r ) ), false));
|
||||
chunksToPoll.insert(std::pair<ChunkPos,bool>(ChunkPos( ( xx[i] - r ) , ( zz[i] + r ) - l ), false));
|
||||
chunksToPoll.insert(std::pair<ChunkPos, bool>(
|
||||
ChunkPos((xx[i] - r) + l, (zz[i] - r)), false));
|
||||
chunksToPoll.insert(std::pair<ChunkPos, bool>(
|
||||
ChunkPos((xx[i] + r), (zz[i] - r) + l), false));
|
||||
chunksToPoll.insert(std::pair<ChunkPos, bool>(
|
||||
ChunkPos((xx[i] + r) - l, (zz[i] + r)), false));
|
||||
chunksToPoll.insert(std::pair<ChunkPos, bool>(
|
||||
ChunkPos((xx[i] - r), (zz[i] + r) - l), false));
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
#ifdef __PSVITA__
|
||||
ChunkPos cp = ChunkPos( ( xx[i] - r ) + l , ( zz[i] - r ));
|
||||
if( chunksToPoll.find( cp ) ) chunksToPoll.insert(cp, true);
|
||||
cp = ChunkPos( ( xx[i] + r ), ( zz[i] - r ) + l );
|
||||
if( chunksToPoll.find( cp ) ) chunksToPoll.insert(cp, true);
|
||||
cp = ChunkPos( ( xx[i] + r ) - l , ( zz[i] + r ));
|
||||
if( chunksToPoll.find( cp ) ) chunksToPoll.insert(cp, true);
|
||||
cp = ChunkPos( ( xx[i] - r ), ( zz[i] + r ) - l);
|
||||
if( chunksToPoll.find( cp ) ) chunksToPoll.insert(cp, true);
|
||||
ChunkPos cp = ChunkPos((xx[i] - r) + l, (zz[i] - r));
|
||||
if (chunksToPoll.find(cp)) chunksToPoll.insert(cp, true);
|
||||
cp = ChunkPos((xx[i] + r), (zz[i] - r) + l);
|
||||
if (chunksToPoll.find(cp)) chunksToPoll.insert(cp, true);
|
||||
cp = ChunkPos((xx[i] + r) - l, (zz[i] + r));
|
||||
if (chunksToPoll.find(cp)) chunksToPoll.insert(cp, true);
|
||||
cp = ChunkPos((xx[i] - r), (zz[i] + r) - l);
|
||||
if (chunksToPoll.find(cp)) chunksToPoll.insert(cp, true);
|
||||
#else
|
||||
ChunkPos cp = ChunkPos( ( xx[i] - r ) + l , ( zz[i] - r ));
|
||||
if( chunksToPoll.find( cp ) == chunksToPoll.end() ) chunksToPoll.insert(std::pair<ChunkPos,bool>(cp, true));
|
||||
cp = ChunkPos( ( xx[i] + r ), ( zz[i] - r ) + l );
|
||||
if( chunksToPoll.find( cp ) == chunksToPoll.end() ) chunksToPoll.insert(std::pair<ChunkPos,bool>(cp, true));
|
||||
cp = ChunkPos( ( xx[i] + r ) - l , ( zz[i] + r ));
|
||||
if( chunksToPoll.find( cp ) == chunksToPoll.end() ) chunksToPoll.insert(std::pair<ChunkPos,bool>(cp, true));
|
||||
cp = ChunkPos( ( xx[i] - r ), ( zz[i] + r ) - l);
|
||||
if( chunksToPoll.find( cp ) == chunksToPoll.end() ) chunksToPoll.insert(std::pair<ChunkPos,bool>(cp, true));
|
||||
ChunkPos cp = ChunkPos((xx[i] - r) + l, (zz[i] - r));
|
||||
if (chunksToPoll.find(cp) == chunksToPoll.end())
|
||||
chunksToPoll.insert(
|
||||
std::pair<ChunkPos, bool>(cp, true));
|
||||
cp = ChunkPos((xx[i] + r), (zz[i] - r) + l);
|
||||
if (chunksToPoll.find(cp) == chunksToPoll.end())
|
||||
chunksToPoll.insert(
|
||||
std::pair<ChunkPos, bool>(cp, true));
|
||||
cp = ChunkPos((xx[i] + r) - l, (zz[i] + r));
|
||||
if (chunksToPoll.find(cp) == chunksToPoll.end())
|
||||
chunksToPoll.insert(
|
||||
std::pair<ChunkPos, bool>(cp, true));
|
||||
cp = ChunkPos((xx[i] - r), (zz[i] + r) - l);
|
||||
if (chunksToPoll.find(cp) == chunksToPoll.end())
|
||||
chunksToPoll.insert(
|
||||
std::pair<ChunkPos, bool>(cp, true));
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
delete [] xx;
|
||||
delete [] zz;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
delete[] xx;
|
||||
delete[] zz;
|
||||
#endif
|
||||
MemSect(0);
|
||||
int count = 0;
|
||||
MemSect(31);
|
||||
Pos *spawnPos = level->getSharedSpawnPos();
|
||||
MemSect(0);
|
||||
|
||||
for (unsigned int i = 0; i < MobCategory::values.length; i++)
|
||||
{
|
||||
MobCategory *mobCategory = MobCategory::values[i];
|
||||
if ((mobCategory->isFriendly() && !spawnFriendlies) || (!mobCategory->isFriendly() && !spawnEnemies))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
MemSect(0);
|
||||
int count = 0;
|
||||
MemSect(31);
|
||||
Pos* spawnPos = level->getSharedSpawnPos();
|
||||
MemSect(0);
|
||||
|
||||
// 4J - this is now quite different to the java version. We just have global max counts for the level whereas the original has a max per chunk that
|
||||
// scales with the number of chunks to be polled.
|
||||
int categoryCount = level->countInstanceOf( mobCategory->getEnumBaseClass(), mobCategory->isSingleType());
|
||||
if( categoryCount >= mobCategory->getMaxInstancesPerLevel())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
for (unsigned int i = 0; i < MobCategory::values.length; i++) {
|
||||
MobCategory* mobCategory = MobCategory::values[i];
|
||||
if ((mobCategory->isFriendly() && !spawnFriendlies) ||
|
||||
(!mobCategory->isFriendly() && !spawnEnemies)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 4J - this is now quite different to the java version. We just have
|
||||
// global max counts for the level whereas the original has a max per
|
||||
// chunk that scales with the number of chunks to be polled.
|
||||
int categoryCount = level->countInstanceOf(
|
||||
mobCategory->getEnumBaseClass(), mobCategory->isSingleType());
|
||||
if (categoryCount >= mobCategory->getMaxInstancesPerLevel()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
#ifdef __PSVITA__
|
||||
for( int i = 0;i < chunksToPoll.end();i += 1 )
|
||||
{
|
||||
SCustomMapNode *it = chunksToPoll.get(i);
|
||||
for (int i = 0; i < chunksToPoll.end(); i += 1) {
|
||||
SCustomMapNode* it = chunksToPoll.get(i);
|
||||
#else
|
||||
AUTO_VAR(itEndCTP, chunksToPoll.end());
|
||||
for (AUTO_VAR(it, chunksToPoll.begin()); it != itEndCTP; it++)
|
||||
{
|
||||
AUTO_VAR(itEndCTP, chunksToPoll.end());
|
||||
for (AUTO_VAR(it, chunksToPoll.begin()); it != itEndCTP; it++) {
|
||||
#endif
|
||||
if( it->second )
|
||||
{
|
||||
// don't add mobs to edge chunks, to prevent adding mobs
|
||||
// "outside" of the active playground
|
||||
continue;
|
||||
}
|
||||
ChunkPos *cp = (ChunkPos *) (&it->first);
|
||||
if (it->second) {
|
||||
// don't add mobs to edge chunks, to prevent adding mobs
|
||||
// "outside" of the active playground
|
||||
continue;
|
||||
}
|
||||
ChunkPos* cp = (ChunkPos*)(&it->first);
|
||||
|
||||
// 4J - don't let this actually create/load a chunk that isn't here already - we'll let the normal updateDirtyChunks etc. processes do that, so it can happen on another thread
|
||||
if( !level->hasChunk(cp->x,cp->z) ) continue;
|
||||
// 4J - don't let this actually create/load a chunk that isn't here
|
||||
// already - we'll let the normal updateDirtyChunks etc. processes
|
||||
// do that, so it can happen on another thread
|
||||
if (!level->hasChunk(cp->x, cp->z)) continue;
|
||||
|
||||
TilePos start = getRandomPosWithin(level, cp->x, cp->z);
|
||||
int xStart = start.x;
|
||||
int yStart = start.y;
|
||||
int zStart = start.z;
|
||||
TilePos start = getRandomPosWithin(level, cp->x, cp->z);
|
||||
int xStart = start.x;
|
||||
int yStart = start.y;
|
||||
int zStart = start.z;
|
||||
|
||||
if (level->isSolidBlockingTile(xStart, yStart, zStart)) continue;
|
||||
if (level->getMaterial(xStart, yStart, zStart) != mobCategory->getSpawnPositionMaterial()) continue;
|
||||
int clusterSize = 0;
|
||||
if (level->isSolidBlockingTile(xStart, yStart, zStart)) continue;
|
||||
if (level->getMaterial(xStart, yStart, zStart) !=
|
||||
mobCategory->getSpawnPositionMaterial())
|
||||
continue;
|
||||
int clusterSize = 0;
|
||||
|
||||
for (int dd = 0; dd < 3; dd++)
|
||||
{
|
||||
int x = xStart;
|
||||
int y = yStart;
|
||||
int z = zStart;
|
||||
int ss = 6;
|
||||
for (int dd = 0; dd < 3; dd++) {
|
||||
int x = xStart;
|
||||
int y = yStart;
|
||||
int z = zStart;
|
||||
int ss = 6;
|
||||
|
||||
Biome::MobSpawnerData *currentMobType = NULL;
|
||||
Biome::MobSpawnerData* currentMobType = NULL;
|
||||
|
||||
for (int ll = 0; ll < 4; ll++)
|
||||
{
|
||||
x += level->random->nextInt(ss) - level->random->nextInt(ss);
|
||||
y += level->random->nextInt(1) - level->random->nextInt(1);
|
||||
z += level->random->nextInt(ss) - level->random->nextInt(ss);
|
||||
// int y = heightMap[x + z * w] + 1;
|
||||
for (int ll = 0; ll < 4; ll++) {
|
||||
x +=
|
||||
level->random->nextInt(ss) - level->random->nextInt(ss);
|
||||
y += level->random->nextInt(1) - level->random->nextInt(1);
|
||||
z +=
|
||||
level->random->nextInt(ss) - level->random->nextInt(ss);
|
||||
// int y = heightMap[x + z * w] + 1;
|
||||
|
||||
// 4J - don't let this actually create/load a chunk that isn't here already - we'll let the normal updateDirtyChunks etc. processes do that, so it can happen on another thread
|
||||
if( !level->hasChunkAt( x, y, z ) ) continue;
|
||||
// 4J - don't let this actually create/load a chunk that
|
||||
// isn't here already - we'll let the normal
|
||||
// updateDirtyChunks etc. processes do that, so it can
|
||||
// happen on another thread
|
||||
if (!level->hasChunkAt(x, y, z)) continue;
|
||||
|
||||
if (isSpawnPositionOk(mobCategory, level, x, y, z))
|
||||
{
|
||||
float xx = x + 0.5f;
|
||||
float yy = (float) y;
|
||||
float zz = z + 0.5f;
|
||||
if (level->getNearestPlayer(xx, yy, zz, MIN_SPAWN_DISTANCE) != NULL)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
float xd = xx - spawnPos->x;
|
||||
float yd = yy - spawnPos->y;
|
||||
float zd = zz - spawnPos->z;
|
||||
float sd = xd * xd + yd * yd + zd * zd;
|
||||
if (sd < MIN_SPAWN_DISTANCE * MIN_SPAWN_DISTANCE)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (currentMobType == NULL)
|
||||
{
|
||||
currentMobType = level->getRandomMobSpawnAt(mobCategory, x, y, z);
|
||||
if (currentMobType == NULL)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (isSpawnPositionOk(mobCategory, level, x, y, z)) {
|
||||
float xx = x + 0.5f;
|
||||
float yy = (float)y;
|
||||
float zz = z + 0.5f;
|
||||
if (level->getNearestPlayer(
|
||||
xx, yy, zz, MIN_SPAWN_DISTANCE) != NULL) {
|
||||
continue;
|
||||
} else {
|
||||
float xd = xx - spawnPos->x;
|
||||
float yd = yy - spawnPos->y;
|
||||
float zd = zz - spawnPos->z;
|
||||
float sd = xd * xd + yd * yd + zd * zd;
|
||||
if (sd < MIN_SPAWN_DISTANCE * MIN_SPAWN_DISTANCE) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<Mob> mob;
|
||||
// 4J - removed try/catch
|
||||
// try
|
||||
// {
|
||||
MemSect(29);
|
||||
//mob = type.mobClass.getConstructor(Level.class).newInstance(level);
|
||||
mob = std::dynamic_pointer_cast<Mob>(EntityIO::newByEnumType(currentMobType->mobClass, level));
|
||||
MemSect(0);
|
||||
// }
|
||||
// catch (exception e)
|
||||
// {
|
||||
// // TODO 4J We can't print a stack trace, and the newInstance function doesn't throw an exception just now anyway
|
||||
// //e.printStackTrace();
|
||||
// return count;
|
||||
// }
|
||||
if (currentMobType == NULL) {
|
||||
currentMobType = level->getRandomMobSpawnAt(
|
||||
mobCategory, x, y, z);
|
||||
if (currentMobType == NULL) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 4J - If it is an animal or a monster, don't let any one type of mob represent more than 50% of the total amount of these things. This
|
||||
// was added initially to stop flat lands being totally populated with slimes but seems like a generally good rule.
|
||||
eINSTANCEOF mobType = mob->GetType();
|
||||
std::shared_ptr<Mob> mob;
|
||||
// 4J - removed try/catch
|
||||
// try
|
||||
// {
|
||||
MemSect(29);
|
||||
// mob =
|
||||
// type.mobClass.getConstructor(Level.class).newInstance(level);
|
||||
mob = std::dynamic_pointer_cast<Mob>(
|
||||
EntityIO::newByEnumType(currentMobType->mobClass,
|
||||
level));
|
||||
MemSect(0);
|
||||
// }
|
||||
// catch
|
||||
//(exception e)
|
||||
// {
|
||||
// //
|
||||
//TODO 4J We can't print a stack trace, and the
|
||||
//newInstance function doesn't throw an exception just
|
||||
//now anyway
|
||||
// //e.printStackTrace();
|
||||
// return
|
||||
//count;
|
||||
// }
|
||||
|
||||
if( ( mobType & eTYPE_ANIMALS_SPAWN_LIMIT_CHECK ) || ( mobType & eTYPE_MONSTER ) )
|
||||
{
|
||||
// even more special rule for ghasts, because filling up the nether with 25 of them is a bit unpleasant. In the java version they are
|
||||
// only limited by the fact that the world fills up with pig zombies (the only other type of enemy mob in the nether) before them - they
|
||||
// aren't actually even counted properly themselves
|
||||
if( mobType == eTYPE_GHAST )
|
||||
{
|
||||
if( level->countInstanceOf(mobType, true) >= 4 ) continue;
|
||||
}
|
||||
else if( mobType == eTYPE_ENDERMAN && level->dimension->id == 1 )
|
||||
{
|
||||
// Special rule for the end, as we only have Endermen (plus the dragon). Increase the spawnable counts based on level difficulty
|
||||
int maxEndermen = mobCategory->getMaxInstancesPerLevel();
|
||||
// 4J - If it is an animal or a monster, don't let any
|
||||
// one type of mob represent more than 50% of the total
|
||||
// amount of these things. This was added initially to
|
||||
// stop flat lands being totally populated with slimes
|
||||
// but seems like a generally good rule.
|
||||
eINSTANCEOF mobType = mob->GetType();
|
||||
|
||||
if( level->difficulty == Difficulty::NORMAL )
|
||||
{
|
||||
maxEndermen -= mobCategory->getMaxInstancesPerLevel()/4;
|
||||
}
|
||||
else if( level->difficulty <= Difficulty::EASY)
|
||||
{
|
||||
maxEndermen -= mobCategory->getMaxInstancesPerLevel()/2;
|
||||
}
|
||||
if ((mobType & eTYPE_ANIMALS_SPAWN_LIMIT_CHECK) ||
|
||||
(mobType & eTYPE_MONSTER)) {
|
||||
// even more special rule for ghasts, because
|
||||
// filling up the nether with 25 of them is a bit
|
||||
// unpleasant. In the java version they are only
|
||||
// limited by the fact that the world fills up with
|
||||
// pig zombies (the only other type of enemy mob in
|
||||
// the nether) before them - they aren't actually
|
||||
// even counted properly themselves
|
||||
if (mobType == eTYPE_GHAST) {
|
||||
if (level->countInstanceOf(mobType, true) >= 4)
|
||||
continue;
|
||||
} else if (mobType == eTYPE_ENDERMAN &&
|
||||
level->dimension->id == 1) {
|
||||
// Special rule for the end, as we only have
|
||||
// Endermen (plus the dragon). Increase the
|
||||
// spawnable counts based on level difficulty
|
||||
int maxEndermen =
|
||||
mobCategory->getMaxInstancesPerLevel();
|
||||
|
||||
if( level->countInstanceOf(mobType, true) >= maxEndermen ) continue;
|
||||
}
|
||||
else if( level->countInstanceOf(mobType, true) >= ( mobCategory->getMaxInstancesPerLevel() / 2 ) ) continue;
|
||||
}
|
||||
if (level->difficulty == Difficulty::NORMAL) {
|
||||
maxEndermen -=
|
||||
mobCategory->getMaxInstancesPerLevel() /
|
||||
4;
|
||||
} else if (level->difficulty <=
|
||||
Difficulty::EASY) {
|
||||
maxEndermen -=
|
||||
mobCategory->getMaxInstancesPerLevel() /
|
||||
2;
|
||||
}
|
||||
|
||||
mob->moveTo(xx, yy, zz, level->random->nextFloat() * 360, 0);
|
||||
if (level->countInstanceOf(mobType, true) >=
|
||||
maxEndermen)
|
||||
continue;
|
||||
} else if (level->countInstanceOf(mobType, true) >=
|
||||
(mobCategory->getMaxInstancesPerLevel() /
|
||||
2))
|
||||
continue;
|
||||
}
|
||||
|
||||
if (mob->canSpawn())
|
||||
{
|
||||
// 4J - check if we are going to despawn straight away too, and don't add if we will - otherwise we'll be sending
|
||||
// network packets for adding & removal that we don't need
|
||||
mob->checkDespawn();
|
||||
if( !mob->removed )
|
||||
{
|
||||
clusterSize++;
|
||||
categoryCount++;
|
||||
mob->setDespawnProtected(); // 4J added - default to protected against despawning
|
||||
level->addEntity(mob);
|
||||
finalizeMobSettings(mob, level, xx, yy, zz);
|
||||
mob->finalizeMobSpawn();
|
||||
// 4J - change here so that we can't ever make more than the desired amount of entities in each priority. In the original java version
|
||||
// depending on the random spawn positions being considered the only limit as to the number of entities created per category is the number
|
||||
// of chunks to poll.
|
||||
if (categoryCount >= mobCategory->getMaxInstancesPerLevel() ) goto categoryLoop;
|
||||
if (clusterSize >= mob->getMaxSpawnClusterSize()) goto chunkLoop;
|
||||
}
|
||||
}
|
||||
count += clusterSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
chunkLoop: continue;
|
||||
}
|
||||
categoryLoop: continue;
|
||||
}
|
||||
delete spawnPos;
|
||||
mob->moveTo(xx, yy, zz,
|
||||
level->random->nextFloat() * 360, 0);
|
||||
|
||||
return count;
|
||||
if (mob->canSpawn()) {
|
||||
// 4J - check if we are going to despawn straight
|
||||
// away too, and don't add if we will - otherwise
|
||||
// we'll be sending network packets for adding &
|
||||
// removal that we don't need
|
||||
mob->checkDespawn();
|
||||
if (!mob->removed) {
|
||||
clusterSize++;
|
||||
categoryCount++;
|
||||
mob->setDespawnProtected(); // 4J added -
|
||||
// default to
|
||||
// protected
|
||||
// against
|
||||
// despawning
|
||||
level->addEntity(mob);
|
||||
finalizeMobSettings(mob, level, xx, yy, zz);
|
||||
mob->finalizeMobSpawn();
|
||||
// 4J - change here so that we can't ever make
|
||||
// more than the desired amount of entities in
|
||||
// each priority. In the original java version
|
||||
// depending on the random spawn positions being
|
||||
// considered the only limit as to the number of
|
||||
// entities created per category is the number
|
||||
// of chunks to poll.
|
||||
if (categoryCount >=
|
||||
mobCategory->getMaxInstancesPerLevel())
|
||||
goto categoryLoop;
|
||||
if (clusterSize >=
|
||||
mob->getMaxSpawnClusterSize())
|
||||
goto chunkLoop;
|
||||
}
|
||||
}
|
||||
count += clusterSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
chunkLoop:
|
||||
continue;
|
||||
}
|
||||
categoryLoop:
|
||||
continue;
|
||||
}
|
||||
delete spawnPos;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
bool MobSpawner::isSpawnPositionOk(MobCategory *category, Level *level, int x, int y, int z)
|
||||
{
|
||||
// 4J - don't let this actually create/load a chunk that isn't here already - we'll let the normal updateDirtyChunks etc. processes do that, so it can happen on another thread
|
||||
if( !level->hasChunkAt(x, y, z ) ) return false;
|
||||
bool MobSpawner::isSpawnPositionOk(MobCategory* category, Level* level, int x,
|
||||
int y, int z) {
|
||||
// 4J - don't let this actually create/load a chunk that isn't here already
|
||||
// - we'll let the normal updateDirtyChunks etc. processes do that, so it
|
||||
// can happen on another thread
|
||||
if (!level->hasChunkAt(x, y, z)) return false;
|
||||
|
||||
#ifdef __PSVITA__
|
||||
// AP - added this for Vita. Make sure a new spawn point has 2 chunks around it. This will make sure monsters don't keep getting spawned on the edge preventing other new monsters
|
||||
// from being spawned
|
||||
int r = 32;
|
||||
if( !level->hasChunksAt(x - r, 0, z - r, x + r, 0, z + r))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// AP - added this for Vita. Make sure a new spawn point has 2 chunks around
|
||||
// it. This will make sure monsters don't keep getting spawned on the edge
|
||||
// preventing other new monsters from being spawned
|
||||
int r = 32;
|
||||
if (!level->hasChunksAt(x - r, 0, z - r, x + r, 0, z + r)) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (category->getSpawnPositionMaterial() == Material::water)
|
||||
{
|
||||
// 4J - changed to spawn water things only in deep water
|
||||
int yo = 0;
|
||||
int liquidCount = 0;
|
||||
|
||||
while( ( y - yo ) >= 0 && ( yo < 5 ) )
|
||||
{
|
||||
if( level->getMaterial(x, y - yo, z)->isLiquid() ) liquidCount++;
|
||||
yo++;
|
||||
}
|
||||
if (category->getSpawnPositionMaterial() == Material::water) {
|
||||
// 4J - changed to spawn water things only in deep water
|
||||
int yo = 0;
|
||||
int liquidCount = 0;
|
||||
|
||||
// 4J - Sometimes deep water could be just a waterfall, so check that it's wide as well
|
||||
bool inEnoughWater = false;
|
||||
if( liquidCount == 5 )
|
||||
{
|
||||
if( level->getMaterial(x+5, y, z)->isLiquid() &&
|
||||
level->getMaterial(x-5, y, z)->isLiquid() &&
|
||||
level->getMaterial(x, y, z+5)->isLiquid() &&
|
||||
level->getMaterial(x, y, z-5)->isLiquid()
|
||||
)
|
||||
{
|
||||
inEnoughWater = true;
|
||||
}
|
||||
}
|
||||
while ((y - yo) >= 0 && (yo < 5)) {
|
||||
if (level->getMaterial(x, y - yo, z)->isLiquid()) liquidCount++;
|
||||
yo++;
|
||||
}
|
||||
|
||||
return inEnoughWater && !level->isSolidBlockingTile(x, y + 1, z);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!level->isTopSolidBlocking(x, y - 1, z)) return false;
|
||||
int tt = level->getTile(x, y - 1, z);
|
||||
return tt != Tile::unbreakable_Id && !level->isSolidBlockingTile(x, y, z) && !level->getMaterial(x, y, z)->isLiquid() && !level->isSolidBlockingTile(x, y + 1, z);
|
||||
}
|
||||
// 4J - Sometimes deep water could be just a waterfall, so check that
|
||||
// it's wide as well
|
||||
bool inEnoughWater = false;
|
||||
if (liquidCount == 5) {
|
||||
if (level->getMaterial(x + 5, y, z)->isLiquid() &&
|
||||
level->getMaterial(x - 5, y, z)->isLiquid() &&
|
||||
level->getMaterial(x, y, z + 5)->isLiquid() &&
|
||||
level->getMaterial(x, y, z - 5)->isLiquid()) {
|
||||
inEnoughWater = true;
|
||||
}
|
||||
}
|
||||
|
||||
return inEnoughWater && !level->isSolidBlockingTile(x, y + 1, z);
|
||||
} else {
|
||||
if (!level->isTopSolidBlocking(x, y - 1, z)) return false;
|
||||
int tt = level->getTile(x, y - 1, z);
|
||||
return tt != Tile::unbreakable_Id &&
|
||||
!level->isSolidBlockingTile(x, y, z) &&
|
||||
!level->getMaterial(x, y, z)->isLiquid() &&
|
||||
!level->isSolidBlockingTile(x, y + 1, z);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MobSpawner::finalizeMobSettings(std::shared_ptr<Mob> mob, Level *level, float xx, float yy, float zz)
|
||||
{
|
||||
if (std::dynamic_pointer_cast<Spider>( mob ) != NULL && level->random->nextInt(100) == 0)
|
||||
{
|
||||
std::shared_ptr<Skeleton> skeleton = std::shared_ptr<Skeleton>( new Skeleton(level) );
|
||||
skeleton->moveTo(xx, yy, zz, mob->yRot, 0);
|
||||
level->addEntity(skeleton);
|
||||
skeleton->ride(mob);
|
||||
}
|
||||
else if (std::dynamic_pointer_cast<Sheep >( mob ) != NULL)
|
||||
{
|
||||
(std::dynamic_pointer_cast<Sheep>( mob ))->setColor(Sheep::getSheepColor(level->random));
|
||||
}
|
||||
else if (std::dynamic_pointer_cast<Ozelot >( mob ) != NULL)
|
||||
{
|
||||
if (level->random->nextInt(7) == 0)
|
||||
{
|
||||
for (int kitten = 0; kitten < 2; kitten++)
|
||||
{
|
||||
std::shared_ptr<Ozelot> ozelot = std::shared_ptr<Ozelot>(new Ozelot(level));
|
||||
ozelot->moveTo(xx, yy, zz, mob->yRot, 0);
|
||||
ozelot->setAge(-20 * 60 * 20);
|
||||
level->addEntity(ozelot);
|
||||
}
|
||||
}
|
||||
}
|
||||
void MobSpawner::finalizeMobSettings(std::shared_ptr<Mob> mob, Level* level,
|
||||
float xx, float yy, float zz) {
|
||||
if (std::dynamic_pointer_cast<Spider>(mob) != NULL &&
|
||||
level->random->nextInt(100) == 0) {
|
||||
std::shared_ptr<Skeleton> skeleton =
|
||||
std::shared_ptr<Skeleton>(new Skeleton(level));
|
||||
skeleton->moveTo(xx, yy, zz, mob->yRot, 0);
|
||||
level->addEntity(skeleton);
|
||||
skeleton->ride(mob);
|
||||
} else if (std::dynamic_pointer_cast<Sheep>(mob) != NULL) {
|
||||
(std::dynamic_pointer_cast<Sheep>(mob))
|
||||
->setColor(Sheep::getSheepColor(level->random));
|
||||
} else if (std::dynamic_pointer_cast<Ozelot>(mob) != NULL) {
|
||||
if (level->random->nextInt(7) == 0) {
|
||||
for (int kitten = 0; kitten < 2; kitten++) {
|
||||
std::shared_ptr<Ozelot> ozelot =
|
||||
std::shared_ptr<Ozelot>(new Ozelot(level));
|
||||
ozelot->moveTo(xx, yy, zz, mob->yRot, 0);
|
||||
ozelot->setAge(-20 * 60 * 20);
|
||||
level->addEntity(ozelot);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 4J Stu TODO This was an array of Class type. I haven't made a base Class type
|
||||
// yet, but don't need to as this can be an array of Mob type?
|
||||
eINSTANCEOF MobSpawner::bedEnemies[bedEnemyCount] = {eTYPE_SPIDER, eTYPE_ZOMBIE,
|
||||
eTYPE_SKELETON};
|
||||
|
||||
// 4J Stu TODO This was an array of Class type. I haven't made a base Class type yet, but don't need to
|
||||
// as this can be an array of Mob type?
|
||||
eINSTANCEOF MobSpawner::bedEnemies[bedEnemyCount] = {
|
||||
eTYPE_SPIDER, eTYPE_ZOMBIE, eTYPE_SKELETON
|
||||
};
|
||||
bool MobSpawner::attackSleepingPlayers(
|
||||
Level* level, std::vector<std::shared_ptr<Player> >* players) {
|
||||
bool somebodyWokeUp = false;
|
||||
|
||||
PathFinder finder = PathFinder(level, true, false, false, true);
|
||||
|
||||
bool MobSpawner::attackSleepingPlayers(Level *level, std::vector<std::shared_ptr<Player> > *players)
|
||||
{
|
||||
AUTO_VAR(itEnd, players->end());
|
||||
for (AUTO_VAR(it, players->begin()); it != itEnd; it++) {
|
||||
std::shared_ptr<Player> player = (*it);
|
||||
|
||||
bool somebodyWokeUp = false;
|
||||
bool nextPlayer = false;
|
||||
|
||||
PathFinder finder = PathFinder(level, true, false, false, true);
|
||||
for (int attemptCount = 0; attemptCount < 20 && !nextPlayer;
|
||||
attemptCount++) {
|
||||
// limit position within the range of the player
|
||||
int x = Mth::floor(player->x) + level->random->nextInt(32) -
|
||||
level->random->nextInt(32);
|
||||
int z = Mth::floor(player->z) + level->random->nextInt(32) -
|
||||
level->random->nextInt(32);
|
||||
int yStart = Mth::floor(player->y) + level->random->nextInt(16) -
|
||||
level->random->nextInt(16);
|
||||
if (yStart < 1) {
|
||||
yStart = 1;
|
||||
} else if (yStart > Level::maxBuildHeight) {
|
||||
yStart = Level::maxBuildHeight;
|
||||
}
|
||||
|
||||
AUTO_VAR(itEnd, players->end());
|
||||
for (AUTO_VAR(it, players->begin()); it != itEnd; it++)
|
||||
{
|
||||
std::shared_ptr<Player> player = (*it);
|
||||
{
|
||||
int type = level->random->nextInt(bedEnemyCount);
|
||||
int y = yStart;
|
||||
|
||||
bool nextPlayer = false;
|
||||
while (y > 2 && !level->isTopSolidBlocking(x, y - 1, z)) {
|
||||
y--;
|
||||
}
|
||||
|
||||
for (int attemptCount = 0; attemptCount < 20 && !nextPlayer; attemptCount++)\
|
||||
{
|
||||
while (!isSpawnPositionOk((MobCategory*)MobCategory::monster,
|
||||
level, x, y, z) &&
|
||||
y < (yStart + 16) && y < Level::maxBuildHeight) {
|
||||
y++;
|
||||
}
|
||||
if (y >= (yStart + 16) || y >= Level::maxBuildHeight) {
|
||||
y = yStart;
|
||||
continue;
|
||||
} else {
|
||||
float xx = x + 0.5f;
|
||||
float yy = (float)y;
|
||||
float zz = z + 0.5f;
|
||||
|
||||
std::shared_ptr<Mob> mob;
|
||||
// 4J - removed try/catch
|
||||
// try
|
||||
// {
|
||||
// mob =
|
||||
// classes[type].getConstructor(Level.class).newInstance(level);
|
||||
// 4J - there was a classes array here which duplicated the
|
||||
// bedEnemies array but have removed it
|
||||
mob = std::dynamic_pointer_cast<Mob>(
|
||||
EntityIO::newByEnumType(bedEnemies[type], level));
|
||||
// }
|
||||
// catch (exception e)
|
||||
// {
|
||||
// // TODO 4J Stu -
|
||||
//We can't print a stack trace, and newInstance doesn't
|
||||
//currently throw an exception anyway
|
||||
// //e.printStackTrace();
|
||||
// return
|
||||
//somebodyWokeUp;
|
||||
// }
|
||||
|
||||
// limit position within the range of the player
|
||||
int x = Mth::floor(player->x) + level->random->nextInt(32) - level->random->nextInt(32);
|
||||
int z = Mth::floor(player->z) + level->random->nextInt(32) - level->random->nextInt(32);
|
||||
int yStart = Mth::floor(player->y) + level->random->nextInt(16) - level->random->nextInt(16);
|
||||
if (yStart < 1)
|
||||
{
|
||||
yStart = 1;
|
||||
}
|
||||
else if (yStart > Level::maxBuildHeight)
|
||||
{
|
||||
yStart = Level::maxBuildHeight;
|
||||
}
|
||||
// System.out.println("Placing night mob");
|
||||
mob->moveTo(xx, yy, zz, level->random->nextFloat() * 360,
|
||||
0);
|
||||
// check if the mob can spawn at this location
|
||||
if (!mob->canSpawn()) {
|
||||
continue;
|
||||
}
|
||||
Pos* bedPos = BedTile::findStandUpPosition(
|
||||
level, Mth::floor(player->x), Mth::floor(player->y),
|
||||
Mth::floor(player->z), 1);
|
||||
if (bedPos == NULL) {
|
||||
// an unlikely case where the bed is
|
||||
// completely blocked
|
||||
bedPos = new Pos(x, y + 1, z);
|
||||
}
|
||||
|
||||
{
|
||||
int type = level->random->nextInt(bedEnemyCount);
|
||||
int y = yStart;
|
||||
// 4J Stu - TU-1 hotfix
|
||||
// Fix for #13152 - If the player sleeps in a bed next to a
|
||||
// wall in an enclosed, well lit area they will be awoken by
|
||||
// a monster The pathfinder should attempt to get close to
|
||||
// the position that we will move the mob to, instead of the
|
||||
// player who could be next to a wall. Otherwise the paths
|
||||
// gets to the other side of the the wall, then moves the
|
||||
// mob inside the building
|
||||
// Path *findPath = finder.findPath(mob.get(),
|
||||
// player.get(), 32.0f);
|
||||
Path* findPath = finder.findPath(
|
||||
mob.get(), bedPos->x, bedPos->y, bedPos->z, 32.0f);
|
||||
if (findPath != NULL && findPath->getSize() > 1) {
|
||||
Node* last = findPath->last();
|
||||
|
||||
while (y > 2 && !level->isTopSolidBlocking(x, y - 1, z))
|
||||
{
|
||||
y--;
|
||||
}
|
||||
if (abs(last->x - bedPos->x) < 1.5 &&
|
||||
abs(last->z - bedPos->z) < 1.5 &&
|
||||
abs(last->y - bedPos->y) < 1.5) {
|
||||
// System.out.println("Found path!");
|
||||
|
||||
while (!isSpawnPositionOk( (MobCategory *) MobCategory::monster, level, x, y, z) && y < (yStart + 16) && y < Level::maxBuildHeight)
|
||||
{
|
||||
y++;
|
||||
}
|
||||
if (y >= (yStart + 16) || y >= Level::maxBuildHeight)
|
||||
{
|
||||
y = yStart;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
float xx = x + 0.5f;
|
||||
float yy = (float) y;
|
||||
float zz = z + 0.5f;
|
||||
mob->moveTo(bedPos->x + 0.5f, bedPos->y,
|
||||
bedPos->z + 0.5f, 0, 0);
|
||||
// the mob would maybe not be able to
|
||||
// spawn here, but we ignore that now (we assume
|
||||
// it walked here)
|
||||
{
|
||||
level->addEntity(mob);
|
||||
finalizeMobSettings(
|
||||
mob, level, bedPos->x + 0.5f,
|
||||
(float)bedPos->y, bedPos->z + 0.5f);
|
||||
mob->finalizeMobSpawn();
|
||||
player->stopSleepInBed(true, false, false);
|
||||
// play a sound effect to scare the player
|
||||
mob->playAmbientSound();
|
||||
somebodyWokeUp = true;
|
||||
nextPlayer = true;
|
||||
}
|
||||
}
|
||||
delete findPath;
|
||||
}
|
||||
delete bedPos;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<Mob> mob;
|
||||
// 4J - removed try/catch
|
||||
// try
|
||||
// {
|
||||
//mob = classes[type].getConstructor(Level.class).newInstance(level);
|
||||
// 4J - there was a classes array here which duplicated the bedEnemies array but have removed it
|
||||
mob = std::dynamic_pointer_cast<Mob>(EntityIO::newByEnumType(bedEnemies[type], level ));
|
||||
// }
|
||||
// catch (exception e)
|
||||
// {
|
||||
// // TODO 4J Stu - We can't print a stack trace, and newInstance doesn't currently throw an exception anyway
|
||||
// //e.printStackTrace();
|
||||
// return somebodyWokeUp;
|
||||
// }
|
||||
|
||||
// System.out.println("Placing night mob");
|
||||
mob->moveTo(xx, yy, zz, level->random->nextFloat() * 360, 0);
|
||||
// check if the mob can spawn at this location
|
||||
if (!mob->canSpawn())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
Pos *bedPos = BedTile::findStandUpPosition(level, Mth::floor(player->x), Mth::floor(player->y), Mth::floor(player->z), 1);
|
||||
if (bedPos == NULL)
|
||||
{
|
||||
// an unlikely case where the bed is
|
||||
// completely blocked
|
||||
bedPos = new Pos(x, y + 1, z);
|
||||
}
|
||||
|
||||
// 4J Stu - TU-1 hotfix
|
||||
// Fix for #13152 - If the player sleeps in a bed next to a wall in an enclosed, well lit area they will be awoken by a monster
|
||||
// The pathfinder should attempt to get close to the position that we will move the mob to,
|
||||
// instead of the player who could be next to a wall. Otherwise the paths gets to the other
|
||||
// side of the the wall, then moves the mob inside the building
|
||||
//Path *findPath = finder.findPath(mob.get(), player.get(), 32.0f);
|
||||
Path *findPath = finder.findPath(mob.get(), bedPos->x, bedPos->y, bedPos->z, 32.0f);
|
||||
if (findPath != NULL && findPath->getSize() > 1)
|
||||
{
|
||||
Node *last = findPath->last();
|
||||
|
||||
if (abs(last->x - bedPos->x) < 1.5 && abs(last->z - bedPos->z) < 1.5 && abs(last->y - bedPos->y) < 1.5)
|
||||
{
|
||||
// System.out.println("Found path!");
|
||||
|
||||
mob->moveTo(bedPos->x + 0.5f, bedPos->y, bedPos->z + 0.5f, 0, 0);
|
||||
// the mob would maybe not be able to
|
||||
// spawn here, but we ignore that now (we assume
|
||||
// it walked here)
|
||||
{
|
||||
level->addEntity(mob);
|
||||
finalizeMobSettings(mob, level, bedPos->x + 0.5f, (float) bedPos->y, bedPos->z + 0.5f);
|
||||
mob->finalizeMobSpawn();
|
||||
player->stopSleepInBed(true, false, false);
|
||||
// play a sound effect to scare the player
|
||||
mob->playAmbientSound();
|
||||
somebodyWokeUp = true;
|
||||
nextPlayer = true;
|
||||
}
|
||||
}
|
||||
delete findPath;
|
||||
}
|
||||
delete bedPos;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return somebodyWokeUp;
|
||||
return somebodyWokeUp;
|
||||
}
|
||||
|
||||
void MobSpawner::postProcessSpawnMobs(Level *level, Biome *biome, int xo, int zo, int cellWidth, int cellHeight, Random *random)
|
||||
{
|
||||
// 4J - not for our version. Creates a few too many mobs.
|
||||
void MobSpawner::postProcessSpawnMobs(Level* level, Biome* biome, int xo,
|
||||
int zo, int cellWidth, int cellHeight,
|
||||
Random* random) {
|
||||
// 4J - not for our version. Creates a few too many mobs.
|
||||
#if 0
|
||||
std::vector<Biome::MobSpawnerData *> *mobs = biome->getMobs(MobCategory::creature);
|
||||
if (mobs->empty())
|
||||
|
||||
Reference in New Issue
Block a user