// Server stuff
g_settings.setDefault("creative_mode", "false");
- g_settings.setDefault("heightmap_blocksize", "32");
+ /*g_settings.setDefault("heightmap_blocksize", "32");
g_settings.setDefault("height_randmax", "constant 45.0");
g_settings.setDefault("height_randfactor", "constant 0.6");
g_settings.setDefault("height_base", "linear 0 0 0");
g_settings.setDefault("plants_amount", "1.0");
g_settings.setDefault("ravines_amount", "1.0");
+ g_settings.setDefault("coal_amount", "1.0");*/
+ g_settings.setDefault("heightmap_blocksize", "16");
+ g_settings.setDefault("height_randmax", "linear 0 0 40");
+ g_settings.setDefault("height_randfactor", "linear 0.60 -0.10 0");
+ g_settings.setDefault("height_base", "linear 5 0 0");
+ g_settings.setDefault("plants_amount", "0.2");
+ g_settings.setDefault("ravines_amount", "0");
g_settings.setDefault("coal_amount", "1.0");
g_settings.setDefault("objectdata_interval", "0.2");
g_settings.setDefault("disable_water_climb", "true");
g_settings.setDefault("endless_water", "true");
g_settings.setDefault("max_block_send_distance", "5");
- g_settings.setDefault("max_block_generate_distance", "4");
+ g_settings.setDefault("max_block_generate_distance", "5");
g_settings.setDefault("time_send_interval", "20");
g_settings.setDefault("time_speed", "96");
g_settings.setDefault("server_unload_unused_sectors_timeout", "60");
f32 max_down = 1.0*BS;
if(speed.Y < -max_down) speed.Y = -max_down;
- f32 max = 2.0*BS;
+ f32 max = 2.5*BS;
if(speed.getLength() > max)
{
speed = speed / speed.getLength() * max;
\r
NOTE: VBO cannot be turned on for fast-changing stuff because there\r
is an apparanet memory leak in irrlicht when using it (not sure)\r
+ - It is not a memory leak but some kind of a buffer.\r
\r
NOTE: iostream.imbue(std::locale("C")) is very slow\r
NOTE: Global locale is now set at initialization\r
\r
SUGG: Fix address to be ipv6 compatible\r
\r
-FIXME: When a new sector is generated, it may change the ground level\r
- of it's and it's neighbors border that two blocks that are\r
- above and below each other and that are generated before and\r
- after the sector heightmap generation (order doesn't matter),\r
- can have a small gap between each other at the border.\r
-SUGGESTION: Use same technique for sector heightmaps as what we're\r
- using for UnlimitedHeightmap? (getting all neighbors\r
- when generating)\r
+NOTE: When a new sector is generated, it may change the ground level\r
+ of it's and it's neighbors border that two blocks that are\r
+ above and below each other and that are generated before and\r
+ after the sector heightmap generation (order doesn't matter),\r
+ can have a small gap between each other at the border.\r
+SUGG: Use same technique for sector heightmaps as what we're\r
+ using for UnlimitedHeightmap? (getting all neighbors\r
+ when generating)\r
\r
SUGG: Transfer more blocks in a single packet\r
SUGG: A blockdata combiner class, to which blocks are added and at\r
SUGG: Implement lighting using VoxelManipulator\r
- Would it be significantly faster?\r
\r
-FIXME: Rats somehow go underground sometimes (you can see it in water)\r
- - Does their position get saved to a border value or something?\r
- - Does this happen anymore?\r
-\r
SUGG: MovingObject::move and Player::move are basically the same.\r
combine them.\r
\r
- Use it in active block queue in water flowing\r
\r
SUGG: Precalculate lighting translation table at runtime (at startup)\r
+ - This is not doable because it is currently hand-made and not\r
+ based on some mathematical function.\r
\r
SUGG: A version number to blocks, which increments when the block is\r
modified (node add/remove, water update, lighting update)\r
different directions and then only those drawn that need to be\r
- Also an 1-dimensional tile map would be nice probably\r
\r
-TODO: Untie client network operations from framerate\r
- - Needs some input queues or something\r
- - Not really necessary?\r
+Networking:\r
+\r
+TODO: Get rid of GotSplitPacketException\r
+\r
+GUI:\r
+\r
+TODO: Add gui option to remove map\r
+\r
+TODO: Startup and configuration menu\r
+\r
+Graphics:\r
+\r
+TODO: Optimize day/night mesh updating somehow\r
+ - create copies of all textures for all lighting values and only\r
+ change texture for material?\r
+ - Umm... the collecting of the faces is the slow part\r
+ -> what about just changing the color values of the existing\r
+ meshbuffers? It should go quite fast.\r
+\r
+TODO: Draw big amounts of torches better (that is, throw them in the\r
+ same meshbuffer (can the meshcollector class be used?))\r
\r
TODO: Combine MapBlock's face caches to so big pieces that VBO\r
gets used\r
- That is >500 vertices\r
\r
-TODO: Startup and configuration menu\r
+TODO: Make fetching sector's blocks more efficient when rendering\r
+ sectors that have very large amounts of blocks (on client)\r
\r
-TODO: There are some lighting-related todos and fixmes in\r
- ServerMap::emergeBlock\r
+Configuration:\r
\r
-TODO: Proper handling of spawning place (try to find something that\r
- is not in the middle of an ocean (some land to stand on at\r
- least) and save it in map config.\r
+TODO: Make the video backend selectable\r
+\r
+Client:\r
+\r
+TODO: Untie client network operations from framerate\r
+ - Needs some input queues or something\r
+ - Not really necessary?\r
+\r
+Server:\r
+\r
+TODO: When player dies, throw items on map\r
+\r
+TODO: Make an option to the server to disable building and digging near\r
+ the starting position\r
\r
TODO: Players to only be hidden when the client quits.\r
TODO: - Players to be saved on disk, with inventory\r
TODO: Players to be saved as text in map/players/<name>\r
TODO: Player inventory to be saved on disk\r
\r
-TODO: Make fetching sector's blocks more efficient when rendering\r
- sectors that have very large amounts of blocks (on client)\r
-\r
-TODO: Make the video backend selectable\r
+TODO: Proper handling of spawning place (try to find something that\r
+ is not in the middle of an ocean (some land to stand on at\r
+ least) and save it in map config.\r
\r
TODO: Copy the text of the last picked sign to inventory in creative\r
mode\r
\r
-TODO: Get rid of GotSplitPacketException\r
-\r
TODO: Check what goes wrong with caching map to disk (Kray)\r
- Nothing?\r
\r
-Block object server side:\r
- - A "near blocks" buffer, in which some nearby blocks are stored.\r
- - For all blocks in the buffer, objects are stepped(). This\r
- means they are active.\r
- - TODO: A global active buffer is needed for the server\r
- - TODO: A timestamp to blocks\r
- - TODO: All blocks going in and out of the buffer are recorded.\r
- - TODO: For outgoing blocks, timestamp is written.\r
- - TODO: For incoming blocks, time difference is calculated and\r
- objects are stepped according to it.\r
+TODO: When server sees that client is removing an inexistent block or\r
+ adding a block to an existent position, resend the MapBlock.\r
+\r
+Objects:\r
\r
TODO: Better handling of objects and mobs\r
- Scripting?\r
- This is also needed for objects that don't get sent to client\r
but are used for triggers etc\r
\r
-TODO: Draw big amounts of torches better (that is, throw them in the\r
- same meshbuffer (can the meshcollector class be used?))\r
-\r
-TODO: Make an option to the server to disable building and digging near\r
- the starting position\r
-\r
SUGG: Signs could be done in the same way as torches. For this, blocks\r
need an additional metadata field for the texts\r
- This is also needed for item container chests\r
TODO: There has to be some better way to handle static objects than to\r
send them all the time. This affects signs and item objects.\r
\r
-TODO: When server sees that client is removing an inexistent block or\r
- adding a block to an existent position, resend the MapBlock.\r
+Block object server side:\r
+ - A "near blocks" buffer, in which some nearby blocks are stored.\r
+ - For all blocks in the buffer, objects are stepped(). This\r
+ means they are active.\r
+ - TODO: A global active buffer is needed for the server\r
+ - TODO: A timestamp to blocks\r
+ - TODO: All blocks going in and out of the buffer are recorded.\r
+ - TODO: For outgoing blocks, timestamp is written.\r
+ - TODO: For incoming blocks, time difference is calculated and\r
+ objects are stepped according to it.\r
\r
-TODO: When player dies, throw items on map\r
+Map generator:\r
\r
-TODO: Use porting::path_userdata for configuration file\r
+TODO: There are some lighting-related todos and fixmes in\r
+ ServerMap::emergeBlock\r
\r
-TODO: Optimize day/night mesh updating somehow\r
- - create copies of all textures for all lighting values and only\r
- change texture for material?\r
- - Umm... the collecting of the faces is the slow part\r
- -> what about just changing the color values of the existing\r
- meshbuffers? It should go quite fast.\r
+TODO: When generating a block, check that there is no sunlight\r
+ below the block if the bottom of the block doesn't have\r
+ sunlight. If it has, add it to the invalid lighting list.\r
\r
TODO: Map generator version 2\r
- Create surface areas based on central points; a given point's\r
- Flat land, mountains, forest, jungle\r
- Cliffs, arcs\r
\r
-TODO: Add gui option to remove map\r
-\r
Doing now:\r
======================================================================\r
\r
sector->setHeightmap(p_in_sector, hm);
//TODO: Make these values configurable
+
//hm->generateContinued(0.0, 0.0, corners);
- hm->generateContinued(0.5, 0.2, corners);
+ hm->generateContinued(0.25, 0.2, corners);
+ //hm->generateContinued(0.5, 0.2, corners);
//hm->generateContinued(1.0, 0.2, corners);
//hm->generateContinued(2.0, 0.2, corners);
{
underground_emptiness[i] = 0;
}
+
// Generate dungeons
{
/*
// DEBUG
//sector->printHeightmaps();
+ // Set to true if has caves.
+ // Set when some non-air is changed to air when making caves.
+ bool has_caves = false;
+
for(s16 z0=0; z0<MAP_BLOCKSIZE; z0++)
for(s16 x0=0; x0<MAP_BLOCKSIZE; x0++)
{
float max_slope = 1.20;
float min_slope_depth = 5.0;
float max_slope_depth = 0;
+
if(slope < min_slope)
surface_depth = min_slope_depth;
else if(slope > max_slope)
// Else it's ground or dungeons (air)
else
{
- // Create dungeons
- if(underground_emptiness[
- ued*ued*(z0*ued/MAP_BLOCKSIZE)
- +ued*(y0*ued/MAP_BLOCKSIZE)
- +(x0*ued/MAP_BLOCKSIZE)])
+ // If it's surface_depth under ground, it's stone
+ if(real_y <= surface_y - surface_depth)
{
- n.d = CONTENT_AIR;
+ n.d = CONTENT_STONE;
}
else
{
- // If it's surface_depth under ground, it's stone
- if(real_y <= surface_y - surface_depth)
+ // It is mud if it is under the first ground
+ // level or under water
+ if(real_y < WATER_LEVEL || real_y <= surface_y - 1)
{
- n.d = CONTENT_STONE;
+ n.d = CONTENT_MUD;
}
else
{
- // It is mud if it is under the first ground
- // level or under water
- if(real_y < WATER_LEVEL || real_y <= surface_y - 1)
- {
- n.d = CONTENT_MUD;
- }
- else
- {
- n.d = CONTENT_GRASS;
- }
-
- //n.d = CONTENT_MUD;
-
- /*// If under water level, it's mud
- if(real_y < WATER_LEVEL)
- n.d = CONTENT_MUD;
- // Only the topmost node is grass
- else if(real_y <= surface_y - 1)
- n.d = CONTENT_MUD;
- else
- n.d = CONTENT_GRASS;*/
+ n.d = CONTENT_GRASS;
}
+
+ //n.d = CONTENT_MUD;
+
+ /*// If under water level, it's mud
+ if(real_y < WATER_LEVEL)
+ n.d = CONTENT_MUD;
+ // Only the topmost node is grass
+ else if(real_y <= surface_y - 1)
+ n.d = CONTENT_MUD;
+ else
+ n.d = CONTENT_GRASS;*/
}
- }
-#if 0
- else if(real_y <= surface_y - surface_depth)
- {
+
// Create dungeons
if(underground_emptiness[
ued*ued*(z0*ued/MAP_BLOCKSIZE)
+ued*(y0*ued/MAP_BLOCKSIZE)
+(x0*ued/MAP_BLOCKSIZE)])
{
+ // Has now caves if previous content is air
+ if(n.d != CONTENT_AIR)
+ {
+ has_caves = true;
+ }
+
n.d = CONTENT_AIR;
}
- else
- {
- n.d = CONTENT_STONE;
- }
}
- // If node is at or under heightmap y
- else if(real_y <= surface_y)
- {
- // If under water level, it's mud
- if(real_y < WATER_LEVEL)
- n.d = CONTENT_MUD;
- // Only the topmost node is grass
- else if(real_y <= surface_y - 1)
- n.d = CONTENT_MUD;
- // Else it's the main material
- else
- n.d = material;
- }
-#endif
+
block->setNode(v3s16(x0,y0,z0), n);
}
}
/*
- Calculate is_underground
+ Calculate completely_underground
*/
- // Probably underground if the highest part of block is under lowest
- // ground height
- bool is_underground = (block_y+1) * MAP_BLOCKSIZE <= lowest_ground_y;
- block->setIsUnderground(is_underground);
+ // Completely underground if the highest part of block is under lowest
+ // ground height.
+ // This has to be very sure; it's probably one too strict now but
+ // that's just better.
+ bool completely_underground =
+ block_y * MAP_BLOCKSIZE + MAP_BLOCKSIZE < lowest_ground_y;
+
+ // This isn't used anymore (?) but set it anyway
+ block->setIsUnderground(completely_underground);
+
+ bool some_part_underground = block_y * MAP_BLOCKSIZE <= highest_ground_y;
/*
- Force lighting update if some part of block is underground
- This is needed because of caves.
+ Force lighting update if some part of block is partly
+ underground and has caves.
*/
- bool some_part_underground = (block_y+0) * MAP_BLOCKSIZE < highest_ground_y;
- if(some_part_underground)
- //if(is_underground)
+ if(some_part_underground && !completely_underground && has_caves)
{
+ //dstream<<"Half-ground caves"<<std::endl;
lighting_invalidated_blocks[block->getPos()] = block;
}
+ // DEBUG: Always update lighting
+ //lighting_invalidated_blocks[block->getPos()] = block;
+
/*
Add some minerals
*/
/*
Add meseblocks
*/
- for(s16 i=0; i<underground_level*1; i++)
+ for(s16 i=0; i< underground_level/4 + 1; i++)
{
- if(myrand()%2 == 0)
+ if(myrand()%10 == 0)
{
v3s16 cp(
(myrand()%(MAP_BLOCKSIZE-2))+1,
/*
Create a few rats in empty blocks underground
*/
- if(is_underground)
+ if(completely_underground)
{
//for(u16 i=0; i<2; i++)
{
v2s16 p2d(p.X,p.Z);
u8 d = i.getNode()->getValue();
- //v3s16 p = p_sector - v3s16(0, block_y*MAP_BLOCKSIZE, 0);
+ // Ground level point (user for stuff that is on ground)
+ v3s16 gp = p;
+ bool ground_found = true;
+ // Search real ground level
+ try{
+ for(;;)
+ {
+ MapNode n = sector->getNode(gp);
+
+ // If not air, go one up and continue to placing the tree
+ if(n.d != CONTENT_AIR)
+ {
+ gp += v3s16(0,1,0);
+ break;
+ }
+
+ // If air, go one down
+ gp += v3s16(0,-1,0);
+ }
+ }catch(InvalidPositionException &e)
+ {
+ // Ground not found.
+ ground_found = false;
+ // This is most close to ground
+ gp += v3s16(0,1,0);
+ }
+
try
{
}
else if(d == SECTOR_OBJECT_TREE_1)
{
- v3s16 p_min = p + v3s16(-1,0,-1);
- v3s16 p_max = p + v3s16(1,4,1);
+ if(ground_found == false)
+ continue;
+
+ v3s16 p_min = gp + v3s16(-1,0,-1);
+ v3s16 p_max = gp + v3s16(1,5,1);
if(sector->isValidArea(p_min, p_max,
&changed_blocks_sector))
{
MapNode n;
n.d = CONTENT_TREE;
- sector->setNode(p+v3s16(0,0,0), n);
- sector->setNode(p+v3s16(0,1,0), n);
- sector->setNode(p+v3s16(0,2,0), n);
- sector->setNode(p+v3s16(0,3,0), n);
+ sector->setNode(gp+v3s16(0,0,0), n);
+ sector->setNode(gp+v3s16(0,1,0), n);
+ sector->setNode(gp+v3s16(0,2,0), n);
+ sector->setNode(gp+v3s16(0,3,0), n);
n.d = CONTENT_LEAVES;
- sector->setNode(p+v3s16(0,4,0), n);
+ if(rand()%4!=0) sector->setNode(gp+v3s16(0,5,0), n);
+
+ if(rand()%3!=0) sector->setNode(gp+v3s16(-1,5,0), n);
+ if(rand()%3!=0) sector->setNode(gp+v3s16(1,5,0), n);
+ if(rand()%3!=0) sector->setNode(gp+v3s16(0,5,-1), n);
+ if(rand()%3!=0) sector->setNode(gp+v3s16(0,5,1), n);
+ /*if(rand()%3!=0) sector->setNode(gp+v3s16(1,5,1), n);
+ if(rand()%3!=0) sector->setNode(gp+v3s16(-1,5,1), n);
+ if(rand()%3!=0) sector->setNode(gp+v3s16(-1,5,-1), n);
+ if(rand()%3!=0) sector->setNode(gp+v3s16(1,5,-1), n);*/
+
+ sector->setNode(gp+v3s16(0,4,0), n);
- sector->setNode(p+v3s16(-1,4,0), n);
- sector->setNode(p+v3s16(1,4,0), n);
- sector->setNode(p+v3s16(0,4,-1), n);
- sector->setNode(p+v3s16(0,4,1), n);
- sector->setNode(p+v3s16(1,4,1), n);
- sector->setNode(p+v3s16(-1,4,1), n);
- sector->setNode(p+v3s16(-1,4,-1), n);
- sector->setNode(p+v3s16(1,4,-1), n);
-
- sector->setNode(p+v3s16(-1,3,0), n);
- sector->setNode(p+v3s16(1,3,0), n);
- sector->setNode(p+v3s16(0,3,-1), n);
- sector->setNode(p+v3s16(0,3,1), n);
- sector->setNode(p+v3s16(1,3,1), n);
- sector->setNode(p+v3s16(-1,3,1), n);
- sector->setNode(p+v3s16(-1,3,-1), n);
- sector->setNode(p+v3s16(1,3,-1), n);
+ sector->setNode(gp+v3s16(-1,4,0), n);
+ sector->setNode(gp+v3s16(1,4,0), n);
+ sector->setNode(gp+v3s16(0,4,-1), n);
+ sector->setNode(gp+v3s16(0,4,1), n);
+ sector->setNode(gp+v3s16(1,4,1), n);
+ sector->setNode(gp+v3s16(-1,4,1), n);
+ sector->setNode(gp+v3s16(-1,4,-1), n);
+ sector->setNode(gp+v3s16(1,4,-1), n);
+
+ sector->setNode(gp+v3s16(-1,3,0), n);
+ sector->setNode(gp+v3s16(1,3,0), n);
+ sector->setNode(gp+v3s16(0,3,-1), n);
+ sector->setNode(gp+v3s16(0,3,1), n);
+ sector->setNode(gp+v3s16(1,3,1), n);
+ sector->setNode(gp+v3s16(-1,3,1), n);
+ sector->setNode(gp+v3s16(-1,3,-1), n);
+ sector->setNode(gp+v3s16(1,3,-1), n);
+ if(rand()%3!=0) sector->setNode(gp+v3s16(-1,2,0), n);
+ if(rand()%3!=0) sector->setNode(gp+v3s16(1,2,0), n);
+ if(rand()%3!=0) sector->setNode(gp+v3s16(0,2,-1), n);
+ if(rand()%3!=0) sector->setNode(gp+v3s16(0,2,1), n);
+ /*if(rand()%3!=0) sector->setNode(gp+v3s16(1,2,1), n);
+ if(rand()%3!=0) sector->setNode(gp+v3s16(-1,2,1), n);
+ if(rand()%3!=0) sector->setNode(gp+v3s16(-1,2,-1), n);
+ if(rand()%3!=0) sector->setNode(gp+v3s16(1,2,-1), n);*/
+
+ // Objects are identified by wanted position
objects_to_remove.push_back(p);
// Lighting has to be recalculated for this one.
}
else if(d == SECTOR_OBJECT_BUSH_1)
{
- if(sector->isValidArea(p + v3s16(0,0,0),
- p + v3s16(0,0,0), &changed_blocks_sector))
+ if(ground_found == false)
+ continue;
+
+ if(sector->isValidArea(gp + v3s16(0,0,0),
+ gp + v3s16(0,0,0), &changed_blocks_sector))
{
MapNode n;
n.d = CONTENT_LEAVES;
- sector->setNode(p+v3s16(0,0,0), n);
+ sector->setNode(gp+v3s16(0,0,0), n);
+ // Objects are identified by wanted position
objects_to_remove.push_back(p);
}
}
{
for(s16 z=0; z<MAP_BLOCKSIZE; z++)
{
+#if 1
bool no_sunlight = false;
bool no_top_block = false;
// Check if node above block has sunlight
// No sunlight here
//no_sunlight = true;
}
+#endif
+#if 0 // Doesn't work; nothing gets light.
+ bool no_sunlight = true;
+ bool no_top_block = false;
+ // Check if node above block has sunlight
+ try{
+ MapNode n = getNodeParent(v3s16(x, MAP_BLOCKSIZE, z));
+ if(n.getLight(LIGHTBANK_DAY) == LIGHT_SUN)
+ {
+ no_sunlight = false;
+ }
+ }
+ catch(InvalidPositionException &e)
+ {
+ no_top_block = true;
+ }
+#endif
/*std::cout<<"("<<x<<","<<z<<"): "
<<"no_top_block="<<no_top_block
DiggingProperties(true, 15.0*toughness, 0));
g_material_properties[material].setDiggingProperties("WPick",
- DiggingProperties(true, 2.0*toughness, 65535./20.*toughness));
+ DiggingProperties(true, 1.5*toughness, 65535./20.*toughness));
g_material_properties[material].setDiggingProperties("STPick",
- DiggingProperties(true, 1.0*toughness, 65535./50.*toughness));
+ DiggingProperties(true, 0.7*toughness, 65535./60.*toughness));
/*g_material_properties[material].setDiggingProperties("MesePick",
DiggingProperties(true, 0.0*toughness, 65535./20.*toughness));*/
for(u16 i=0; i<MATERIAL_PROPERTIES_COUNT; i++)
{
g_material_properties[i].setDiggingProperties("MesePick",
- DiggingProperties(true, 0.0, 65535./20.));
+ DiggingProperties(true, 0.0, 65535./1337));
}
g_material_properties_initialized = true;
virtual void updateLight(u8 light_at_pos) {};
+ virtual bool isClientConnected() { return false; }
+ virtual void setClientConnected(bool) {}
+
bool touching_ground;
bool in_water;
class ServerRemotePlayer : public Player
{
public:
- ServerRemotePlayer()
+ ServerRemotePlayer(bool client_connected):
+ m_client_connected(client_connected)
{
}
virtual ~ServerRemotePlayer()
{
}
- bool isLocal() const
+ virtual bool isLocal() const
{
return false;
}
- void move(f32 dtime, Map &map)
+ virtual void move(f32 dtime, Map &map)
+ {
+ }
+
+ virtual bool isClientConnected()
+ {
+ return m_client_connected;
+ }
+ virtual void setClientConnected(bool client_connected)
{
+ m_client_connected = client_connected;
}
+ // This
+ bool m_client_connected;
+
private:
};
//derr_server<<"EmergeThread::Thread(): running"<<std::endl;
- //TimeTaker timer("block emerge", g_device);
+ //TimeTaker timer("block emerge");
/*
Try to emerge it from somewhere.
{//envlock
+ //TimeTaker envlockwaittimer("block emerge envlock wait time");
+
+ // 0-50ms
JMutexAutoLock envlock(m_server->m_env_mutex);
- //TimeTaker timer("block emerge envlock", g_device);
+ //envlockwaittimer.stop();
+
+ //TimeTaker timer("block emerge (while env locked)");
try{
bool only_from_disk = false;
}
/*dstream<<"lighting "<<lighting_invalidated_blocks.size()
- <<" blocks"<<std::endl;
- TimeTaker timer("** updateLighting", g_device);*/
+ <<" blocks"<<std::endl;*/
+
+ //TimeTaker timer("** updateLighting", g_device);
// Update lighting without locking the environment mutex,
// add modified blocks to changed blocks
bool generate = d <= d_max_gen;
- // Limit the generating area vertically to half
- if(abs(p.Y - center.Y) > d_max_gen / 2)
+ // Limit the generating area vertically to 2/3
+ if(abs(p.Y - center.Y) > d_max_gen - d_max_gen / 3)
generate = false;
/*
// The player shouldn't already exist
assert(player == NULL);
- player = new ServerRemotePlayer();
+ player = new ServerRemotePlayer(true);
player->peer_id = c.peer_id;
/*