mirror of
https://github.com/minetest/minetest.git
synced 2024-08-18 20:44:16 +02:00
map unloading is now a whole lot better
This commit is contained in:
parent
3fccc67eb7
commit
dd22ea051a
@ -9,6 +9,10 @@
|
||||
#
|
||||
# Further documentation:
|
||||
# http://celeron.55.lt/~celeron55/minetest/wiki/doku.php
|
||||
#
|
||||
# NOTE: This file might not be up-to-date, refer to the
|
||||
# defaultsettings.cpp file for an up-to-date list:
|
||||
# https://bitbucket.org/celeron55/minetest/src/tip/src/defaultsettings.cpp
|
||||
|
||||
#
|
||||
# Client side stuff
|
||||
@ -92,7 +96,7 @@
|
||||
#random_input = false
|
||||
|
||||
# Timeout for client to remove unused map data from memory
|
||||
#client_delete_unused_sectors_timeout = 1200
|
||||
#client_unload_unused_data_timeout = 1200
|
||||
|
||||
#
|
||||
# Server side stuff
|
||||
@ -140,6 +144,6 @@
|
||||
#time_speed = 1440
|
||||
|
||||
#time_send_interval = 5
|
||||
#server_unload_unused_sectors_timeout = 60
|
||||
#server_unload_unused_data_timeout = 60
|
||||
#server_map_save_interval = 60
|
||||
|
||||
|
@ -199,7 +199,7 @@ Client::Client(
|
||||
m_access_denied(false)
|
||||
{
|
||||
m_packetcounter_timer = 0.0;
|
||||
m_delete_unused_sectors_timer = 0.0;
|
||||
//m_delete_unused_sectors_timer = 0.0;
|
||||
m_connection_reinit_timer = 0.0;
|
||||
m_avg_rtt_timer = 0.0;
|
||||
m_playerpos_send_timer = 0.0;
|
||||
@ -303,7 +303,11 @@ void Client::step(float dtime)
|
||||
m_packetcounter.clear();
|
||||
}
|
||||
}
|
||||
|
||||
// Get connection status
|
||||
bool connected = connectedAndInitialized();
|
||||
|
||||
#if 0
|
||||
{
|
||||
/*
|
||||
Delete unused sectors
|
||||
@ -324,8 +328,7 @@ void Client::step(float dtime)
|
||||
|
||||
core::list<v3s16> deleted_blocks;
|
||||
|
||||
float delete_unused_sectors_timeout =
|
||||
g_settings.getFloat("client_delete_unused_sectors_timeout");
|
||||
g_settings.getFloat("client_unload_unused_data_timeout");
|
||||
|
||||
// Delete sector blocks
|
||||
/*u32 num = m_env.getMap().unloadUnusedData
|
||||
@ -392,8 +395,7 @@ void Client::step(float dtime)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool connected = connectedAndInitialized();
|
||||
#endif
|
||||
|
||||
if(connected == false)
|
||||
{
|
||||
@ -438,6 +440,67 @@ void Client::step(float dtime)
|
||||
Do stuff if connected
|
||||
*/
|
||||
|
||||
/*
|
||||
Run Map's timers and unload unused data
|
||||
*/
|
||||
const float map_timer_and_unload_dtime = 5.25;
|
||||
if(m_map_timer_and_unload_interval.step(dtime, map_timer_and_unload_dtime))
|
||||
{
|
||||
ScopeProfiler sp(&g_profiler, "Client: map timer and unload");
|
||||
core::list<v3s16> deleted_blocks;
|
||||
m_env.getMap().timerUpdate(map_timer_and_unload_dtime,
|
||||
g_settings.getFloat("client_unload_unused_data_timeout"),
|
||||
&deleted_blocks);
|
||||
|
||||
/*if(deleted_blocks.size() > 0)
|
||||
dstream<<"Client: Unloaded "<<deleted_blocks.size()
|
||||
<<" unused blocks"<<std::endl;*/
|
||||
|
||||
/*
|
||||
Send info to server
|
||||
NOTE: This loop is intentionally iterated the way it is.
|
||||
*/
|
||||
|
||||
core::list<v3s16>::Iterator i = deleted_blocks.begin();
|
||||
core::list<v3s16> sendlist;
|
||||
for(;;)
|
||||
{
|
||||
if(sendlist.size() == 255 || i == deleted_blocks.end())
|
||||
{
|
||||
if(sendlist.size() == 0)
|
||||
break;
|
||||
/*
|
||||
[0] u16 command
|
||||
[2] u8 count
|
||||
[3] v3s16 pos_0
|
||||
[3+6] v3s16 pos_1
|
||||
...
|
||||
*/
|
||||
u32 replysize = 2+1+6*sendlist.size();
|
||||
SharedBuffer<u8> reply(replysize);
|
||||
writeU16(&reply[0], TOSERVER_DELETEDBLOCKS);
|
||||
reply[2] = sendlist.size();
|
||||
u32 k = 0;
|
||||
for(core::list<v3s16>::Iterator
|
||||
j = sendlist.begin();
|
||||
j != sendlist.end(); j++)
|
||||
{
|
||||
writeV3S16(&reply[2+1+6*k], *j);
|
||||
k++;
|
||||
}
|
||||
m_con.Send(PEER_ID_SERVER, 1, reply, true);
|
||||
|
||||
if(i == deleted_blocks.end())
|
||||
break;
|
||||
|
||||
sendlist.clear();
|
||||
}
|
||||
|
||||
sendlist.push_back(*i);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Handle environment
|
||||
*/
|
||||
@ -453,23 +516,23 @@ void Client::step(float dtime)
|
||||
//TimeTaker envtimer("env step", m_device);
|
||||
// Step environment
|
||||
m_env.step(dtime);
|
||||
|
||||
// Step active blocks
|
||||
|
||||
/*
|
||||
Handle active blocks
|
||||
NOTE: These old objects are DEPRECATED. TODO: Remove
|
||||
*/
|
||||
for(core::map<v3s16, bool>::Iterator
|
||||
i = m_active_blocks.getIterator();
|
||||
i.atEnd() == false; i++)
|
||||
{
|
||||
v3s16 p = i.getNode()->getKey();
|
||||
|
||||
MapBlock *block = NULL;
|
||||
try
|
||||
{
|
||||
block = m_env.getMap().getBlockNoCreate(p);
|
||||
block->stepObjects(dtime, false, m_env.getDayNightRatio());
|
||||
}
|
||||
catch(InvalidPositionException &e)
|
||||
{
|
||||
}
|
||||
MapBlock *block = m_env.getMap().getBlockNoCreateNoEx(p);
|
||||
if(block == NULL)
|
||||
continue;
|
||||
|
||||
// Step MapBlockObjects
|
||||
block->stepObjects(dtime, false, m_env.getDayNightRatio());
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1183,6 +1246,7 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
||||
|
||||
/*
|
||||
Read block objects
|
||||
NOTE: Deprecated stuff here, TODO: Remove
|
||||
*/
|
||||
|
||||
// Read active block count
|
||||
|
@ -28,6 +28,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "jmutex.h"
|
||||
#include <ostream>
|
||||
#include "clientobject.h"
|
||||
#include "utility.h" // For IntervalLimiter
|
||||
|
||||
struct MeshMakeData;
|
||||
|
||||
@ -306,11 +307,11 @@ private:
|
||||
void sendPlayerInfo();
|
||||
|
||||
float m_packetcounter_timer;
|
||||
float m_delete_unused_sectors_timer;
|
||||
float m_connection_reinit_timer;
|
||||
float m_avg_rtt_timer;
|
||||
float m_playerpos_send_timer;
|
||||
float m_ignore_damage_timer; // Used after server moves player
|
||||
IntervalLimiter m_map_timer_and_unload_interval;
|
||||
|
||||
MeshUpdateThread m_mesh_update_thread;
|
||||
|
||||
|
@ -37,7 +37,7 @@ enum ToClientCommand
|
||||
[0] u16 TOSERVER_INIT
|
||||
[2] u8 deployed version
|
||||
[3] v3s16 player's position + v3f(0,BS/2,0) floatToInt'd
|
||||
([4] u64 map seed (new as of 2011-02-27))
|
||||
[12] u64 map seed (new as of 2011-02-27)
|
||||
|
||||
NOTE: The position in here is deprecated; position is
|
||||
explicitly sent afterwards
|
||||
|
@ -56,7 +56,7 @@ void set_default_settings()
|
||||
g_settings.setDefault("screenH", "600");
|
||||
g_settings.setDefault("address", "");
|
||||
g_settings.setDefault("random_input", "false");
|
||||
g_settings.setDefault("client_delete_unused_sectors_timeout", "1200");
|
||||
g_settings.setDefault("client_unload_unused_data_timeout", "1200");
|
||||
g_settings.setDefault("enable_fog", "true");
|
||||
g_settings.setDefault("new_style_water", "false");
|
||||
g_settings.setDefault("new_style_leaves", "true");
|
||||
@ -94,7 +94,7 @@ void set_default_settings()
|
||||
g_settings.setDefault("max_block_generate_distance", "8");
|
||||
g_settings.setDefault("time_send_interval", "20");
|
||||
g_settings.setDefault("time_speed", "96");
|
||||
g_settings.setDefault("server_unload_unused_sectors_timeout", "60");
|
||||
g_settings.setDefault("server_unload_unused_data_timeout", "60");
|
||||
g_settings.setDefault("server_map_save_interval", "60");
|
||||
g_settings.setDefault("full_block_send_enable_min_time_from_building", "2.0");
|
||||
//g_settings.setDefault("dungeon_rarity", "0.025");
|
||||
|
@ -660,14 +660,6 @@ void ServerEnvironment::step(float dtime)
|
||||
m_game_time_fraction_counter -= (float)inc_i;
|
||||
}
|
||||
|
||||
/*
|
||||
Let map update it's timers
|
||||
*/
|
||||
{
|
||||
//TimeTaker timer("Server m_map->timerUpdate()");
|
||||
m_map->timerUpdate(dtime);
|
||||
}
|
||||
|
||||
/*
|
||||
Handle players
|
||||
*/
|
||||
@ -1469,11 +1461,6 @@ void ClientEnvironment::step(float dtime)
|
||||
bool free_move = g_settings.getBool("free_move");
|
||||
bool footprints = g_settings.getBool("footprints");
|
||||
|
||||
{
|
||||
//TimeTaker timer("Client m_map->timerUpdate()");
|
||||
m_map->timerUpdate(dtime);
|
||||
}
|
||||
|
||||
// Get local player
|
||||
LocalPlayer *lplayer = getLocalPlayer();
|
||||
assert(lplayer);
|
||||
@ -1672,7 +1659,7 @@ void ClientEnvironment::step(float dtime)
|
||||
// Step object
|
||||
obj->step(dtime, this);
|
||||
|
||||
if(m_active_object_light_update_interval.step(dtime, 0.5))
|
||||
if(m_active_object_light_update_interval.step(dtime, 0.21))
|
||||
{
|
||||
// Update lighting
|
||||
//u8 light = LIGHT_MAX;
|
||||
|
124
src/main.cpp
124
src/main.cpp
@ -27,6 +27,33 @@ NOTE: Global locale is now set at initialization
|
||||
NOTE: If VBO (EHM_STATIC) is used, remember to explicitly free the
|
||||
hardware buffer (it is not freed automatically)
|
||||
|
||||
NOTE: A random to-do list saved here as documentation:
|
||||
A list of "active blocks" in which stuff happens. (+=done)
|
||||
+ Add a never-resetted game timer to the server
|
||||
+ Add a timestamp value to blocks
|
||||
+ The simple rule: All blocks near some player are "active"
|
||||
- Do stuff in real time in active blocks
|
||||
+ Handle objects
|
||||
- Grow grass, delete leaves without a tree
|
||||
- Spawn some mobs based on some rules
|
||||
- Transform cobble to mossy cobble near water
|
||||
- Run a custom script
|
||||
- ...And all kinds of other dynamic stuff
|
||||
+ Keep track of when a block becomes active and becomes inactive
|
||||
+ When a block goes inactive:
|
||||
+ Store objects statically to block
|
||||
+ Store timer value as the timestamp
|
||||
+ When a block goes active:
|
||||
+ Create active objects out of static objects
|
||||
- Simulate the results of what would have happened if it would have
|
||||
been active for all the time
|
||||
- Grow a lot of grass and so on
|
||||
+ Initially it is fine to send information about every active object
|
||||
to every player. Eventually it should be modified to only send info
|
||||
about the nearest ones.
|
||||
+ This was left to be done by the old system and it sends only the
|
||||
nearest ones.
|
||||
|
||||
Old, wild and random suggestions that probably won't be done:
|
||||
-------------------------------------------------------------
|
||||
|
||||
@ -73,9 +100,6 @@ SUGG: Make the amount of blocks sending to client and the total
|
||||
SUGG: Meshes of blocks could be split into 6 meshes facing into
|
||||
different directions and then only those drawn that need to be
|
||||
|
||||
SUGG: Calculate lighting per vertex to get a lighting effect like in
|
||||
bartwe's game
|
||||
|
||||
SUGG: Background music based on cellular automata?
|
||||
http://www.earslap.com/projectslab/otomata
|
||||
|
||||
@ -90,6 +114,8 @@ SUGG: Make a system for pregenerating quick information for mapblocks, so
|
||||
or even generated.
|
||||
|
||||
SUGG: Erosion simulation at map generation time
|
||||
- This might be plausible if larger areas of map were pregenerated
|
||||
without lighting (which is slow)
|
||||
- Simulate water flows, which would carve out dirt fast and
|
||||
then turn stone into gravel and sand and relocate it.
|
||||
- How about relocating minerals, too? Coal and gold in
|
||||
@ -231,6 +257,7 @@ FIXME: Server sometimes goes into some infinite PeerNotFoundException loop
|
||||
* Fix the problem with the server constantly saving one or a few
|
||||
blocks? List the first saved block, maybe it explains.
|
||||
- It is probably caused by oscillating water
|
||||
- TODO: Investigate if this still happens (this is a very old one)
|
||||
* Make a small history check to transformLiquids to detect and log
|
||||
continuous oscillations, in such detail that they can be fixed.
|
||||
|
||||
@ -238,42 +265,12 @@ FIXME: The new optimized map sending doesn't sometimes send enough blocks
|
||||
from big caves and such
|
||||
FIXME: Block send distance configuration does not take effect for some reason
|
||||
|
||||
SUGG: Map unloading based on sector reference is not very good, it keeps
|
||||
unnecessary stuff in memory. I guess. Investigate this.
|
||||
|
||||
TODO: When block is placed and it has param_type==CPT_FACEDIR_SIMPLE, set
|
||||
the direction accordingly.
|
||||
|
||||
Environment:
|
||||
------------
|
||||
|
||||
TODO: A list of "active blocks" in which stuff happens. (+=done)
|
||||
+ Add a never-resetted game timer to the server
|
||||
+ Add a timestamp value to blocks
|
||||
+ The simple rule: All blocks near some player are "active"
|
||||
- Do stuff in real time in active blocks
|
||||
+ Handle objects
|
||||
TODO: Make proper hooks in here
|
||||
- Grow grass, delete leaves without a tree
|
||||
- Spawn some mobs based on some rules
|
||||
- Transform cobble to mossy cobble near water
|
||||
- Run a custom script
|
||||
- ...And all kinds of other dynamic stuff
|
||||
+ Keep track of when a block becomes active and becomes inactive
|
||||
+ When a block goes inactive:
|
||||
+ Store objects statically to block
|
||||
+ Store timer value as the timestamp
|
||||
+ When a block goes active:
|
||||
+ Create active objects out of static objects
|
||||
TODO: Make proper hooks in here
|
||||
- Simulate the results of what would have happened if it would have
|
||||
been active for all the time
|
||||
- Grow a lot of grass and so on
|
||||
+ Initially it is fine to send information about every active object
|
||||
to every player. Eventually it should be modified to only send info
|
||||
about the nearest ones.
|
||||
+ This was left to be done by the old system and it sends only the
|
||||
nearest ones.
|
||||
TODO: Add proper hooks to when adding and removing active blocks
|
||||
|
||||
TODO: Finish the ActiveBlockModifier stuff and use it for something
|
||||
|
||||
Objects:
|
||||
--------
|
||||
@ -285,6 +282,7 @@ TODO: Get rid of MapBlockObjects and use only ActiveObjects
|
||||
|
||||
SUGG: MovingObject::move and Player::move are basically the same.
|
||||
combine them.
|
||||
- NOTE: This is a bit tricky because player has the sneaking ability
|
||||
- NOTE: Player::move is more up-to-date.
|
||||
- NOTE: There is a simple move implementation now in collision.{h,cpp}
|
||||
- NOTE: MovingObject will be deleted (MapBlockObject)
|
||||
@ -303,42 +301,17 @@ TODO: Mineral and ground material properties
|
||||
TODO: Flowing water to actually contain flow direction information
|
||||
- There is a space for this - it just has to be implemented.
|
||||
|
||||
SUGG: Try out the notch way of generating maps, that is, make bunches
|
||||
of low-res 3d noise and interpolate linearly.
|
||||
|
||||
Mapgen v2 (the current one):
|
||||
* Possibly add some kind of erosion and other stuff
|
||||
* Better water generation (spread it to underwater caverns but don't
|
||||
fill dungeons that don't touch big water masses)
|
||||
* When generating a chunk and the neighboring chunk doesn't have mud
|
||||
and stuff yet and the ground is fairly flat, the mud will flow to
|
||||
the other chunk making nasty straight walls when the other chunk
|
||||
is generated. Fix it. Maybe just a special case if the ground is
|
||||
flat?
|
||||
* Consider not updating this one and make a good mainly block-based
|
||||
generator
|
||||
|
||||
SUGG: Make two "modified states", one that forces the block to be saved at
|
||||
the next save event, and one that makes the block to be saved at exit
|
||||
time.
|
||||
|
||||
TODO: Add a not_fully_generated flag to MapBlock, which would be set for
|
||||
blocks that contain eg. trees from neighboring generations but haven't
|
||||
been generated itself. This is required for the future generator.
|
||||
|
||||
Misc. stuff:
|
||||
------------
|
||||
- Make sure server handles removing grass when a block is placed (etc)
|
||||
- The client should not do it by itself
|
||||
- Block cube placement around player's head
|
||||
- Protocol version field
|
||||
- Consider getting some textures from cisoun's texture pack
|
||||
- Ask from Cisoun
|
||||
- Make sure the fence implementation and data format is good
|
||||
- Think about using same bits for material for fences and doors, for
|
||||
example
|
||||
- Finish the ActiveBlockModifier stuff and use it for something
|
||||
- Move mineral to param2, increment map serialization version, add conversion
|
||||
TODO: Make sure server handles removing grass when a block is placed (etc)
|
||||
- The client should not do it by itself
|
||||
- NOTE: I think nobody does it currently...
|
||||
TODO: Block cube placement around player's head
|
||||
TODO: Protocol version field
|
||||
TODO: Think about using same bits for material for fences and doors, for
|
||||
example
|
||||
TODO: Move mineral to param2, increment map serialization version, add
|
||||
conversion
|
||||
|
||||
TODO: Add a per-sector database to store surface stuff as simple flags/values
|
||||
- Light?
|
||||
@ -354,8 +327,6 @@ TODO: Restart irrlicht completely when coming back to main menu from game.
|
||||
|
||||
TODO: Merge bahamada's audio stuff (clean patch available)
|
||||
|
||||
TODO: Merge spongie's chest/furnace direction (by hand)
|
||||
|
||||
TODO: Merge key configuration menu (no clean patch available)
|
||||
|
||||
Making it more portable:
|
||||
@ -373,9 +344,6 @@ Stuff to do after release:
|
||||
Doing currently:
|
||||
----------------
|
||||
|
||||
TODO: Use MapBlock::resetUsageTimer() in appropriate places
|
||||
(on client and server)
|
||||
|
||||
======================================================================
|
||||
|
||||
*/
|
||||
@ -404,16 +372,12 @@ TODO: Use MapBlock::resetUsageTimer() in appropriate places
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
//#include <jmutexautolock.h>
|
||||
#include <locale.h>
|
||||
#include "main.h"
|
||||
#include "common_irrlicht.h"
|
||||
#include "debug.h"
|
||||
//#include "map.h"
|
||||
//#include "player.h"
|
||||
#include "test.h"
|
||||
#include "server.h"
|
||||
//#include "client.h"
|
||||
#include "constants.h"
|
||||
#include "porting.h"
|
||||
#include "gettime.h"
|
||||
@ -422,8 +386,6 @@ TODO: Use MapBlock::resetUsageTimer() in appropriate places
|
||||
#include "config.h"
|
||||
#include "guiMainMenu.h"
|
||||
#include "mineral.h"
|
||||
//#include "noise.h"
|
||||
//#include "tile.h"
|
||||
#include "materials.h"
|
||||
#include "game.h"
|
||||
#include "keycode.h"
|
||||
|
99
src/map.cpp
99
src/map.cpp
@ -1386,8 +1386,15 @@ bool Map::dayNightDiffed(v3s16 blockpos)
|
||||
/*
|
||||
Updates usage timers
|
||||
*/
|
||||
void Map::timerUpdate(float dtime)
|
||||
void Map::timerUpdate(float dtime, float unload_timeout,
|
||||
core::list<v3s16> *unloaded_blocks)
|
||||
{
|
||||
bool save_before_unloading = (mapType() == MAPTYPE_SERVER);
|
||||
|
||||
core::list<v2s16> sector_deletion_queue;
|
||||
u32 deleted_blocks_count = 0;
|
||||
u32 saved_blocks_count = 0;
|
||||
|
||||
core::map<v2s16, MapSector*>::Iterator si;
|
||||
|
||||
si = m_sectors.getIterator();
|
||||
@ -1395,13 +1402,60 @@ void Map::timerUpdate(float dtime)
|
||||
{
|
||||
MapSector *sector = si.getNode()->getValue();
|
||||
|
||||
bool all_blocks_deleted = true;
|
||||
|
||||
core::list<MapBlock*> blocks;
|
||||
sector->getBlocks(blocks);
|
||||
for(core::list<MapBlock*>::Iterator i = blocks.begin();
|
||||
i != blocks.end(); i++)
|
||||
{
|
||||
(*i)->incrementUsageTimer(dtime);
|
||||
MapBlock *block = (*i);
|
||||
|
||||
block->incrementUsageTimer(dtime);
|
||||
|
||||
if(block->getUsageTimer() > unload_timeout)
|
||||
{
|
||||
v3s16 p = block->getPos();
|
||||
|
||||
// Save if modified
|
||||
if(block->getModified() != MOD_STATE_CLEAN
|
||||
&& save_before_unloading)
|
||||
{
|
||||
saveBlock(block);
|
||||
saved_blocks_count++;
|
||||
}
|
||||
|
||||
// Delete from memory
|
||||
sector->deleteBlock(block);
|
||||
|
||||
if(unloaded_blocks)
|
||||
unloaded_blocks->push_back(p);
|
||||
|
||||
deleted_blocks_count++;
|
||||
}
|
||||
else
|
||||
{
|
||||
all_blocks_deleted = false;
|
||||
}
|
||||
}
|
||||
|
||||
if(all_blocks_deleted)
|
||||
{
|
||||
sector_deletion_queue.push_back(si.getNode()->getKey());
|
||||
}
|
||||
}
|
||||
|
||||
// Finally delete the empty sectors
|
||||
deleteSectors(sector_deletion_queue);
|
||||
|
||||
if(deleted_blocks_count != 0)
|
||||
{
|
||||
PrintInfo(dstream); // ServerMap/ClientMap:
|
||||
dstream<<"Unloaded "<<deleted_blocks_count
|
||||
<<" blocks from memory";
|
||||
if(save_before_unloading)
|
||||
dstream<<", of which "<<saved_blocks_count<<" were written";
|
||||
dstream<<"."<<std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1420,6 +1474,7 @@ void Map::deleteSectors(core::list<v2s16> &list)
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
void Map::unloadUnusedData(float timeout,
|
||||
core::list<v3s16> *deleted_blocks)
|
||||
{
|
||||
@ -1474,6 +1529,7 @@ void Map::unloadUnusedData(float timeout,
|
||||
//return sector_deletion_queue.getSize();
|
||||
//return deleted_blocks_count;
|
||||
}
|
||||
#endif
|
||||
|
||||
void Map::PrintInfo(std::ostream &out)
|
||||
{
|
||||
@ -1500,7 +1556,7 @@ void Map::transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks)
|
||||
*/
|
||||
v3s16 p0 = m_transforming_liquid.pop_front();
|
||||
|
||||
MapNode n0 = getNode(p0);
|
||||
MapNode n0 = getNodeNoEx(p0);
|
||||
|
||||
// Don't deal with non-liquids
|
||||
if(content_liquid(n0.d) == false)
|
||||
@ -1532,13 +1588,10 @@ void Map::transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks)
|
||||
};
|
||||
for(u16 i=0; i<5; i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
bool from_top = (i==0);
|
||||
|
||||
v3s16 p2 = p0 + dirs_from[i];
|
||||
MapNode n2 = getNode(p2);
|
||||
MapNode n2 = getNodeNoEx(p2);
|
||||
|
||||
if(content_liquid(n2.d))
|
||||
{
|
||||
@ -1572,10 +1625,6 @@ void Map::transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks)
|
||||
if(new_liquid_level > new_liquid_level_max)
|
||||
new_liquid_level_max = new_liquid_level;
|
||||
}
|
||||
|
||||
}catch(InvalidPositionException &e)
|
||||
{
|
||||
}
|
||||
} //for
|
||||
|
||||
/*
|
||||
@ -1618,20 +1667,13 @@ void Map::transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks)
|
||||
};
|
||||
for(u16 i=0; i<6; i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
v3s16 p2 = p0 + dirs[i];
|
||||
|
||||
MapNode n2 = getNode(p2);
|
||||
MapNode n2 = getNodeNoEx(p2);
|
||||
if(content_flowing_liquid(n2.d))
|
||||
{
|
||||
m_transforming_liquid.push_back(p2);
|
||||
}
|
||||
|
||||
}catch(InvalidPositionException &e)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1652,9 +1694,6 @@ void Map::transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks)
|
||||
};
|
||||
for(u16 i=0; i<5; i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
bool to_bottom = (i == 0);
|
||||
|
||||
// If liquid is at lowest possible height, it's not going
|
||||
@ -1680,7 +1719,7 @@ void Map::transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks)
|
||||
|
||||
v3s16 p2 = p0 + dirs_to[i];
|
||||
|
||||
MapNode n2 = getNode(p2);
|
||||
MapNode n2 = getNodeNoEx(p2);
|
||||
//dstream<<"[1] n2.param="<<(int)n2.param<<std::endl;
|
||||
|
||||
if(content_liquid(n2.d))
|
||||
@ -1746,10 +1785,6 @@ void Map::transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks)
|
||||
// If n2_changed to bottom, don't flow anywhere else
|
||||
if(to_bottom && flowed && !is_source)
|
||||
break;
|
||||
|
||||
}catch(InvalidPositionException &e)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
loopcount++;
|
||||
@ -1945,7 +1980,6 @@ ServerMap::~ServerMap()
|
||||
{
|
||||
if(m_map_saving_enabled)
|
||||
{
|
||||
//save(false);
|
||||
// Save only changed parts
|
||||
save(true);
|
||||
dstream<<DTIME<<"Server: saved map to "<<m_savedir<<std::endl;
|
||||
@ -2104,11 +2138,15 @@ MapBlock* ServerMap::finishBlockMake(mapgen::BlockMakeData *data,
|
||||
/*
|
||||
NOTE: Lighting and object adding shouldn't really be here, but
|
||||
lighting is a bit tricky to move properly to makeBlock.
|
||||
TODO: Do this the right way anyway.
|
||||
TODO: Do this the right way anyway, that is, move it to makeBlock.
|
||||
- There needs to be some way for makeBlock to report back if
|
||||
the lighting update is going further down because of the
|
||||
new block blocking light
|
||||
*/
|
||||
|
||||
/*
|
||||
Update lighting
|
||||
NOTE: This takes ~60ms, TODO: Investigate why
|
||||
*/
|
||||
{
|
||||
TimeTaker t("finishBlockMake lighting update");
|
||||
@ -3418,6 +3456,9 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Okay, this block will be drawn. Reset usage timer.
|
||||
block->resetUsageTimer();
|
||||
|
||||
// This is ugly (spherical distance limit?)
|
||||
/*if(m_control.range_all == false &&
|
||||
|
15
src/map.h
15
src/map.h
@ -223,19 +223,23 @@ public:
|
||||
|
||||
virtual void save(bool only_changed){assert(0);};
|
||||
|
||||
// Server implements this
|
||||
// Server implements this.
|
||||
// Client leaves it as no-op.
|
||||
virtual void saveBlock(MapBlock *block){};
|
||||
|
||||
/*
|
||||
Updates usage timers
|
||||
Updates usage timers and unloads unused blocks and sectors.
|
||||
Saves modified blocks before unloading on MAPTYPE_SERVER.
|
||||
*/
|
||||
void timerUpdate(float dtime);
|
||||
void timerUpdate(float dtime, float unload_timeout,
|
||||
core::list<v3s16> *unloaded_blocks=NULL);
|
||||
|
||||
// Deletes sectors and their blocks from memory
|
||||
// Takes cache into account
|
||||
// If deleted sector is in sector cache, clears cache
|
||||
void deleteSectors(core::list<v2s16> &list);
|
||||
|
||||
|
||||
#if 0
|
||||
/*
|
||||
Unload unused data
|
||||
= flush changed to disk and delete from memory, if usage timer of
|
||||
@ -243,8 +247,9 @@ public:
|
||||
*/
|
||||
void unloadUnusedData(float timeout,
|
||||
core::list<v3s16> *deleted_blocks=NULL);
|
||||
#endif
|
||||
|
||||
// For debug printing
|
||||
// For debug printing. Prints "Map: ", "ServerMap: " or "ClientMap: "
|
||||
virtual void PrintInfo(std::ostream &out);
|
||||
|
||||
void transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks);
|
||||
|
117
src/server.cpp
117
src/server.cpp
@ -602,6 +602,9 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
|
||||
bool block_is_invalid = false;
|
||||
if(block != NULL)
|
||||
{
|
||||
// Reset usage timer, this block will be of use in the future.
|
||||
block->resetUsageTimer();
|
||||
|
||||
// Block is dummy if data doesn't exist.
|
||||
// It means it has been not found from disk and not generated
|
||||
if(block->isDummy())
|
||||
@ -1297,12 +1300,21 @@ void Server::AsyncRunStep()
|
||||
}
|
||||
|
||||
{
|
||||
// Step environment
|
||||
// This also runs Map's timers
|
||||
JMutexAutoLock lock(m_env_mutex);
|
||||
// Step environment
|
||||
ScopeProfiler sp(&g_profiler, "Server: environment step");
|
||||
m_env.step(dtime);
|
||||
}
|
||||
|
||||
const float map_timer_and_unload_dtime = 5.15;
|
||||
if(m_map_timer_and_unload_interval.step(dtime, map_timer_and_unload_dtime))
|
||||
{
|
||||
JMutexAutoLock lock(m_env_mutex);
|
||||
// Run Map's timers and unload unused data
|
||||
ScopeProfiler sp(&g_profiler, "Server: map timer and unload");
|
||||
m_env.getMap().timerUpdate(map_timer_and_unload_dtime,
|
||||
g_settings.getFloat("server_unload_unused_data_timeout"));
|
||||
}
|
||||
|
||||
/*
|
||||
Do background stuff
|
||||
@ -1665,8 +1677,15 @@ void Server::AsyncRunStep()
|
||||
if(m_unsent_map_edit_queue.size() >= 4)
|
||||
disable_single_change_sending = true;
|
||||
|
||||
bool got_any_events = false;
|
||||
|
||||
// We'll log the amount of each
|
||||
Profiler prof;
|
||||
|
||||
while(m_unsent_map_edit_queue.size() != 0)
|
||||
{
|
||||
got_any_events = true;
|
||||
|
||||
MapEditEvent* event = m_unsent_map_edit_queue.pop_front();
|
||||
|
||||
// Players far away from the change are stored here.
|
||||
@ -1676,7 +1695,8 @@ void Server::AsyncRunStep()
|
||||
|
||||
if(event->type == MEET_ADDNODE)
|
||||
{
|
||||
dstream<<"Server: MEET_ADDNODE"<<std::endl;
|
||||
//dstream<<"Server: MEET_ADDNODE"<<std::endl;
|
||||
prof.add("MEET_ADDNODE", 1);
|
||||
if(disable_single_change_sending)
|
||||
sendAddNode(event->p, event->n, event->already_known_by_peer,
|
||||
&far_players, 5);
|
||||
@ -1686,7 +1706,8 @@ void Server::AsyncRunStep()
|
||||
}
|
||||
else if(event->type == MEET_REMOVENODE)
|
||||
{
|
||||
dstream<<"Server: MEET_REMOVENODE"<<std::endl;
|
||||
//dstream<<"Server: MEET_REMOVENODE"<<std::endl;
|
||||
prof.add("MEET_REMOVENODE", 1);
|
||||
if(disable_single_change_sending)
|
||||
sendRemoveNode(event->p, event->already_known_by_peer,
|
||||
&far_players, 5);
|
||||
@ -1697,15 +1718,18 @@ void Server::AsyncRunStep()
|
||||
else if(event->type == MEET_BLOCK_NODE_METADATA_CHANGED)
|
||||
{
|
||||
dstream<<"Server: MEET_BLOCK_NODE_METADATA_CHANGED"<<std::endl;
|
||||
prof.add("MEET_BLOCK_NODE_METADATA_CHANGED", 1);
|
||||
setBlockNotSent(event->p);
|
||||
}
|
||||
else if(event->type == MEET_OTHER)
|
||||
{
|
||||
prof.add("MEET_OTHER", 1);
|
||||
dstream<<"WARNING: Server: MEET_OTHER not implemented"
|
||||
<<std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
prof.add("unknown", 1);
|
||||
dstream<<"WARNING: Server: Unknown MapEditEvent "
|
||||
<<((u32)event->type)<<std::endl;
|
||||
}
|
||||
@ -1743,6 +1767,13 @@ void Server::AsyncRunStep()
|
||||
if(count >= 1 && m_unsent_map_edit_queue.size() < 100)
|
||||
break;*/
|
||||
}
|
||||
|
||||
if(got_any_events)
|
||||
{
|
||||
dstream<<"Server: MapEditEvents:"<<std::endl;
|
||||
prof.print(dstream);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1765,39 +1796,6 @@ void Server::AsyncRunStep()
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Step node metadata
|
||||
TODO: Move to ServerEnvironment and utilize active block stuff
|
||||
*/
|
||||
/*{
|
||||
//TimeTaker timer("Step node metadata");
|
||||
|
||||
JMutexAutoLock envlock(m_env_mutex);
|
||||
JMutexAutoLock conlock(m_con_mutex);
|
||||
|
||||
ScopeProfiler sp(&g_profiler, "Server: stepping node metadata");
|
||||
|
||||
core::map<v3s16, MapBlock*> changed_blocks;
|
||||
m_env.getMap().nodeMetadataStep(dtime, changed_blocks);
|
||||
|
||||
// Use setBlockNotSent
|
||||
|
||||
for(core::map<v3s16, MapBlock*>::Iterator
|
||||
i = changed_blocks.getIterator();
|
||||
i.atEnd() == false; i++)
|
||||
{
|
||||
MapBlock *block = i.getNode()->getValue();
|
||||
|
||||
for(core::map<u16, RemoteClient*>::Iterator
|
||||
i = m_clients.getIterator();
|
||||
i.atEnd()==false; i++)
|
||||
{
|
||||
RemoteClient *client = i.getNode()->getValue();
|
||||
client->SetBlockNotSent(block->getPos());
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
/*
|
||||
Trigger emergethread (it somehow gets to a non-triggered but
|
||||
bysy state sometimes)
|
||||
@ -1829,30 +1827,29 @@ void Server::AsyncRunStep()
|
||||
|
||||
// Map
|
||||
JMutexAutoLock lock(m_env_mutex);
|
||||
if(((ServerMap*)(&m_env.getMap()))->isSavingEnabled() == true)
|
||||
|
||||
/*// Unload unused data (delete from memory)
|
||||
m_env.getMap().unloadUnusedData(
|
||||
g_settings.getFloat("server_unload_unused_sectors_timeout"));
|
||||
*/
|
||||
/*u32 deleted_count = m_env.getMap().unloadUnusedData(
|
||||
g_settings.getFloat("server_unload_unused_sectors_timeout"));
|
||||
*/
|
||||
|
||||
// Save only changed parts
|
||||
m_env.getMap().save(true);
|
||||
|
||||
/*if(deleted_count > 0)
|
||||
{
|
||||
// Unload unused data (delete from memory)
|
||||
m_env.getMap().unloadUnusedData(
|
||||
g_settings.getFloat("server_unload_unused_sectors_timeout"));
|
||||
/*u32 deleted_count = m_env.getMap().unloadUnusedData(
|
||||
g_settings.getFloat("server_unload_unused_sectors_timeout"));
|
||||
*/
|
||||
dout_server<<"Server: Unloaded "<<deleted_count
|
||||
<<" blocks from memory"<<std::endl;
|
||||
}*/
|
||||
|
||||
// Save only changed parts
|
||||
m_env.getMap().save(true);
|
||||
|
||||
/*if(deleted_count > 0)
|
||||
{
|
||||
dout_server<<"Server: Unloaded "<<deleted_count
|
||||
<<" blocks from memory"<<std::endl;
|
||||
}*/
|
||||
|
||||
// Save players
|
||||
m_env.serializePlayers(m_mapsavedir);
|
||||
|
||||
// Save environment metadata
|
||||
m_env.saveMeta(m_mapsavedir);
|
||||
}
|
||||
// Save players
|
||||
m_env.serializePlayers(m_mapsavedir);
|
||||
|
||||
// Save environment metadata
|
||||
m_env.saveMeta(m_mapsavedir);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3336,7 +3333,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
||||
|
||||
void Server::onMapEditEvent(MapEditEvent *event)
|
||||
{
|
||||
dstream<<"Server::onMapEditEvent()"<<std::endl;
|
||||
//dstream<<"Server::onMapEditEvent()"<<std::endl;
|
||||
if(m_ignore_map_edit_events)
|
||||
return;
|
||||
MapEditEvent *e = event->clone();
|
||||
|
@ -534,6 +534,7 @@ private:
|
||||
float m_objectdata_timer;
|
||||
float m_emergethread_trigger_timer;
|
||||
float m_savemap_timer;
|
||||
IntervalLimiter m_map_timer_and_unload_interval;
|
||||
|
||||
// NOTE: If connection and environment are both to be locked,
|
||||
// environment shall be locked first.
|
||||
|
Loading…
Reference in New Issue
Block a user