Permalink
Browse files

Changed spawn position algorithm to make sure spawn position is not

underground or in the air.
  • Loading branch information...
1 parent 3761930 commit ac158ce6f17332948140e786d61942df1181cde1 @vargad vargad committed Aug 18, 2012
Showing with 60 additions and 36 deletions.
  1. +6 −0 include/map.h
  2. +52 −36 src/map.cpp
  3. +2 −0 src/mineserver.cpp
View
@@ -123,6 +123,12 @@ class Map
// Get pointer to struct
sChunk* getMapData(int x, int z, bool generate = true);
+ // Is specified position suitable for spawn position
+ bool suitableForSpawn(const vec &pos);
+
+ // Make sure spawn position is not underground
+ bool chooseSpawnPosition();
+
// Load map chunk
sChunk* loadMap(int x, int z, bool generate = true);
View
@@ -1127,6 +1127,58 @@ bool Map::sendProjectileSpawn(User* user, int8_t projID)
return true;
}
+bool Map::suitableForSpawn(const vec &pos)
+{
+ uint8_t block, meta;
+ return ((getBlock(pos.x(), pos.y()-1, pos.z(), &block, &meta, false) && block != BLOCK_AIR)
+ && (getBlock(pos.x(), pos.y(), pos.z(), &block, &meta, false) && block == BLOCK_AIR)
+ && (getBlock(pos.x(), pos.y()+1, pos.z(), &block, &meta, false) && block == BLOCK_AIR));
+}
+
+bool Map::chooseSpawnPosition()
+{
+ bool found = false;
+ // Make sure spawn position is not underground!
+ uint8_t new_y;
+ int new_x, new_z;
+ for (new_x = spawnPos.x(); new_x < spawnPos.x() + 100; new_x += 5)
+ {
+ for (new_z = spawnPos.z(); new_z < spawnPos.z() + 100; new_z += 5)
+ {
+ for (new_y = spawnPos.y(); new_y > 30; new_y--)
+ {
+ if (suitableForSpawn(vec(new_x, new_y, new_z)))
+ {
+ found = true;
+ goto labelFound;
+ }
+ }
+ }
+ }
+labelFound:
+ if (found)
+ {
+ //Store new spawn position to level.dat
+ spawnPos.x() = new_x;
+ spawnPos.y() = new_y;
+ spawnPos.z() = new_z;
+ std::string infile = mapDirectory + "/level.dat";
+ NBT_Value* root = NBT_Value::LoadFromFile(infile);
+ if (root != NULL)
+ {
+ NBT_Value& data = *((*root)["Data"]);
+ *data["SpawnX"] = (int32_t)spawnPos.x();
+ *data["SpawnY"] = (int32_t)spawnPos.y();
+ *data["SpawnZ"] = (int32_t)spawnPos.z();
+
+ root->SaveToFile(infile);
+
+ delete root;
+ }
+ }
+ return found;
+}
+
sChunk* Map::loadMap(int x, int z, bool generate)
{
const ChunkMap::const_iterator it = chunks.find(Coords(x, z));
@@ -1160,42 +1212,6 @@ sChunk* Map::loadMap(int x, int z, bool generate)
ServerInstance->mapGen(m_number)->init((int32_t)mapSeed);
ServerInstance->mapGen(m_number)->generateChunk(x, z, m_number);
generateLight(x, z);
- //If we generated spawn pos, make sure the position is not underground!
- if (x == blockToChunk(spawnPos.x()) && z == blockToChunk(spawnPos.z()))
- {
- uint8_t block, meta;
- bool foundLand = false;
- if (getBlock(spawnPos.x(), spawnPos.y(), spawnPos.z(), &block, &meta, false) && block == BLOCK_AIR)
- {
- uint8_t new_y;
- for (new_y = spawnPos.y(); new_y > 30; new_y--)
- {
- if (getBlock(spawnPos.x(), new_y, spawnPos.z(), &block, &meta, false) && block != BLOCK_AIR)
- {
- foundLand = true;
- break;
- }
- }
- if (foundLand)
- {
- //Store new spawn position to level.dat
- spawnPos.y() = new_y + 1;
- std::string infile = mapDirectory + "/level.dat";
- NBT_Value* root = NBT_Value::LoadFromFile(infile);
- if (root != NULL)
- {
- NBT_Value& data = *((*root)["Data"]);
- *data["SpawnX"] = (int32_t)spawnPos.x();
- *data["SpawnY"] = (int32_t)spawnPos.y();
- *data["SpawnZ"] = (int32_t)spawnPos.z();
-
- root->SaveToFile(infile);
-
- delete root;
- }
- }
- }
- }
delete newRegion;
delete [] chunkPointer;
return getChunk(x, z);
View
@@ -551,6 +551,8 @@ bool Mineserver::run()
}
}
}
+ // Choose proper spawn position
+ m_map[i]->chooseSpawnPosition();
#ifdef DEBUG
LOG(DEBUG, "Map", "Spawn area ready!");
#endif

0 comments on commit ac158ce

Please sign in to comment.