Add '/clearobjects quick'

This commit is contained in:
Kahrl 2016-02-08 22:20:04 +01:00 committed by paramat
parent 47464c9344
commit b1428ab4bb
6 changed files with 124 additions and 51 deletions

@ -848,14 +848,24 @@ core.register_chatcommand("kick", {
}) })
core.register_chatcommand("clearobjects", { core.register_chatcommand("clearobjects", {
params = "[full|quick]",
description = "clear all objects in world", description = "clear all objects in world",
privs = {server=true}, privs = {server=true},
func = function(name, param) func = function(name, param)
options = {}
if param == "" or param == "full" then
options.mode = "full"
elseif param == "quick" then
options.mode = "quick"
else
return false, "Invalid usage, see /help clearobjects."
end
core.log("action", name .. " clears all objects.") core.log("action", name .. " clears all objects.")
core.chat_send_all("Clearing all objects. This may take long." core.chat_send_all("Clearing all objects. This may take long."
.. " You may experience a timeout. (by " .. " You may experience a timeout. (by "
.. name .. ")") .. name .. ")")
core.clear_objects() core.clear_objects(options)
core.log("action", "Object clearing done.") core.log("action", "Object clearing done.")
core.chat_send_all("*** Cleared all objects.") core.chat_send_all("*** Cleared all objects.")
end, end,

@ -2046,8 +2046,12 @@ and `minetest.auth_reload` call the authetification handler.
* `minetest.generate_decorations(vm, pos1, pos2)` * `minetest.generate_decorations(vm, pos1, pos2)`
* Generate all registered decorations within the VoxelManip `vm` and in the area from `pos1` to `pos2`. * Generate all registered decorations within the VoxelManip `vm` and in the area from `pos1` to `pos2`.
* `pos1` and `pos2` are optional and default to mapchunk minp and maxp. * `pos1` and `pos2` are optional and default to mapchunk minp and maxp.
* `minetest.clear_objects()` * `minetest.clear_objects([options])`
* clear all objects in the environments * Clear all objects in the environment
* Takes an optional table as an argument with the field `mode`.
* mode = `"full"`: Load and go through every mapblock, clearing objects (default).
* mode = `"quick"`: Clear objects immediately in loaded mapblocks;
clear objects in unloaded mapblocks only when the mapblocks are next activated.
* `minetest.emerge_area(pos1, pos2, [callback], [param])` * `minetest.emerge_area(pos1, pos2, [callback], [param])`
* Queue all blocks in the area from `pos1` to `pos2`, inclusive, to be asynchronously * Queue all blocks in the area from `pos1` to `pos2`, inclusive, to be asynchronously
* fetched from memory, loaded from disk, or if inexistent, generates them. * fetched from memory, loaded from disk, or if inexistent, generates them.

@ -354,6 +354,7 @@ ServerEnvironment::ServerEnvironment(ServerMap *map,
m_active_block_interval_overload_skip(0), m_active_block_interval_overload_skip(0),
m_game_time(0), m_game_time(0),
m_game_time_fraction_counter(0), m_game_time_fraction_counter(0),
m_last_clear_objects_time(0),
m_recommended_send_interval(0.1), m_recommended_send_interval(0.1),
m_max_lag_estimate(0.1) m_max_lag_estimate(0.1)
{ {
@ -503,6 +504,7 @@ void ServerEnvironment::saveMeta()
Settings args; Settings args;
args.setU64("game_time", m_game_time); args.setU64("game_time", m_game_time);
args.setU64("time_of_day", getTimeOfDay()); args.setU64("time_of_day", getTimeOfDay());
args.setU64("last_clear_objects_time", m_last_clear_objects_time);
args.writeLines(ss); args.writeLines(ss);
ss<<"EnvArgsEnd\n"; ss<<"EnvArgsEnd\n";
@ -546,6 +548,13 @@ void ServerEnvironment::loadMeta()
// This is not as important // This is not as important
setTimeOfDay(9000); setTimeOfDay(9000);
} }
try {
m_last_clear_objects_time = args.getU64("last_clear_objects_time");
} catch (SettingNotFoundException &e) {
// If missing, do as if clearObjects was never called
m_last_clear_objects_time = 0;
}
} }
struct ActiveABM struct ActiveABM
@ -740,12 +749,18 @@ void ServerEnvironment::activateBlock(MapBlock *block, u32 additional_dtime)
u32 dtime_s = 0; u32 dtime_s = 0;
u32 stamp = block->getTimestamp(); u32 stamp = block->getTimestamp();
if (m_game_time > stamp && stamp != BLOCK_TIMESTAMP_UNDEFINED) if (m_game_time > stamp && stamp != BLOCK_TIMESTAMP_UNDEFINED)
dtime_s = m_game_time - block->getTimestamp(); dtime_s = m_game_time - stamp;
dtime_s += additional_dtime; dtime_s += additional_dtime;
/*infostream<<"ServerEnvironment::activateBlock(): block timestamp: " /*infostream<<"ServerEnvironment::activateBlock(): block timestamp: "
<<stamp<<", game time: "<<m_game_time<<std::endl;*/ <<stamp<<", game time: "<<m_game_time<<std::endl;*/
// Remove stored static objects if clearObjects was called since block's timestamp
if (stamp == BLOCK_TIMESTAMP_UNDEFINED || stamp < m_last_clear_objects_time) {
block->m_static_objects.m_stored.clear();
// do not set changed flag to avoid unnecessary mapblock writes
}
// Set current time as timestamp // Set current time as timestamp
block->setTimestampNoChangedFlag(m_game_time); block->setTimestampNoChangedFlag(m_game_time);
@ -858,9 +873,9 @@ void ServerEnvironment::getObjectsInsideRadius(std::vector<u16> &objects, v3f po
} }
} }
void ServerEnvironment::clearAllObjects() void ServerEnvironment::clearObjects(ClearObjectsMode mode)
{ {
infostream<<"ServerEnvironment::clearAllObjects(): " infostream << "ServerEnvironment::clearObjects(): "
<< "Removing all active objects" << std::endl; << "Removing all active objects" << std::endl;
std::vector<u16> objects_to_remove; std::vector<u16> objects_to_remove;
for (std::map<u16, ServerActiveObject*>::iterator for (std::map<u16, ServerActiveObject*>::iterator
@ -907,22 +922,29 @@ void ServerEnvironment::clearAllObjects()
// Get list of loaded blocks // Get list of loaded blocks
std::vector<v3s16> loaded_blocks; std::vector<v3s16> loaded_blocks;
infostream<<"ServerEnvironment::clearAllObjects(): " infostream << "ServerEnvironment::clearObjects(): "
<< "Listing all loaded blocks" << std::endl; << "Listing all loaded blocks" << std::endl;
m_map->listAllLoadedBlocks(loaded_blocks); m_map->listAllLoadedBlocks(loaded_blocks);
infostream<<"ServerEnvironment::clearAllObjects(): " infostream << "ServerEnvironment::clearObjects(): "
<< "Done listing all loaded blocks: " << "Done listing all loaded blocks: "
<< loaded_blocks.size()<<std::endl; << loaded_blocks.size()<<std::endl;
// Get list of loadable blocks // Get list of loadable blocks
std::vector<v3s16> loadable_blocks; std::vector<v3s16> loadable_blocks;
infostream<<"ServerEnvironment::clearAllObjects(): " if (mode == CLEAR_OBJECTS_MODE_FULL) {
infostream << "ServerEnvironment::clearObjects(): "
<< "Listing all loadable blocks" << std::endl; << "Listing all loadable blocks" << std::endl;
m_map->listAllLoadableBlocks(loadable_blocks); m_map->listAllLoadableBlocks(loadable_blocks);
infostream<<"ServerEnvironment::clearAllObjects(): " infostream << "ServerEnvironment::clearObjects(): "
<< "Done listing all loadable blocks: " << "Done listing all loadable blocks: "
<<loadable_blocks.size() << loadable_blocks.size() << std::endl;
<<", now clearing"<<std::endl; } else {
loadable_blocks = loaded_blocks;
}
infostream << "ServerEnvironment::clearObjects(): "
<< "Now clearing objects in " << loadable_blocks.size()
<< " blocks" << std::endl;
// Grab a reference on each loaded block to avoid unloading it // Grab a reference on each loaded block to avoid unloading it
for (std::vector<v3s16>::iterator i = loaded_blocks.begin(); for (std::vector<v3s16>::iterator i = loaded_blocks.begin();
@ -934,8 +956,11 @@ void ServerEnvironment::clearAllObjects()
} }
// Remove objects in all loadable blocks // Remove objects in all loadable blocks
u32 unload_interval = g_settings->getS32("max_clearobjects_extra_loaded_blocks"); u32 unload_interval = U32_MAX;
if (mode == CLEAR_OBJECTS_MODE_FULL) {
unload_interval = g_settings->getS32("max_clearobjects_extra_loaded_blocks");
unload_interval = MYMAX(unload_interval, 1); unload_interval = MYMAX(unload_interval, 1);
}
u32 report_interval = loadable_blocks.size() / 10; u32 report_interval = loadable_blocks.size() / 10;
u32 num_blocks_checked = 0; u32 num_blocks_checked = 0;
u32 num_blocks_cleared = 0; u32 num_blocks_cleared = 0;
@ -945,7 +970,7 @@ void ServerEnvironment::clearAllObjects()
v3s16 p = *i; v3s16 p = *i;
MapBlock *block = m_map->emergeBlock(p, false); MapBlock *block = m_map->emergeBlock(p, false);
if (!block) { if (!block) {
errorstream<<"ServerEnvironment::clearAllObjects(): " errorstream << "ServerEnvironment::clearObjects(): "
<< "Failed to emerge block " << PP(p) << std::endl; << "Failed to emerge block " << PP(p) << std::endl;
continue; continue;
} }
@ -965,7 +990,7 @@ void ServerEnvironment::clearAllObjects()
num_blocks_checked % report_interval == 0) { num_blocks_checked % report_interval == 0) {
float percent = 100.0 * (float)num_blocks_checked / float percent = 100.0 * (float)num_blocks_checked /
loadable_blocks.size(); loadable_blocks.size();
infostream<<"ServerEnvironment::clearAllObjects(): " infostream << "ServerEnvironment::clearObjects(): "
<< "Cleared " << num_objs_cleared << " objects" << "Cleared " << num_objs_cleared << " objects"
<< " in " << num_blocks_cleared << " blocks (" << " in " << num_blocks_cleared << " blocks ("
<< percent << "%)" << std::endl; << percent << "%)" << std::endl;
@ -985,7 +1010,9 @@ void ServerEnvironment::clearAllObjects()
block->refDrop(); block->refDrop();
} }
infostream<<"ServerEnvironment::clearAllObjects(): " m_last_clear_objects_time = m_game_time;
infostream << "ServerEnvironment::clearObjects(): "
<< "Finished: Cleared " << num_objs_cleared << " objects" << "Finished: Cleared " << num_objs_cleared << " objects"
<< " in " << num_blocks_cleared << " blocks" << std::endl; << " in " << num_blocks_cleared << " blocks" << std::endl;
} }

@ -203,6 +203,18 @@ public:
private: private:
}; };
/*
Operation mode for ServerEnvironment::clearObjects()
*/
enum ClearObjectsMode {
// Load and go through every mapblock, clearing objects
CLEAR_OBJECTS_MODE_FULL,
// Clear objects immediately in loaded mapblocks;
// clear objects in unloaded mapblocks only when the mapblocks are next activated.
CLEAR_OBJECTS_MODE_QUICK,
};
/* /*
The server-side environment. The server-side environment.
@ -319,8 +331,8 @@ public:
// Find all active objects inside a radius around a point // Find all active objects inside a radius around a point
void getObjectsInsideRadius(std::vector<u16> &objects, v3f pos, float radius); void getObjectsInsideRadius(std::vector<u16> &objects, v3f pos, float radius);
// Clear all objects, loading and going through every MapBlock // Clear objects, loading and going through every MapBlock
void clearAllObjects(); void clearObjects(ClearObjectsMode mode);
// This makes stuff happen // This makes stuff happen
void step(f32 dtime); void step(f32 dtime);
@ -410,6 +422,10 @@ private:
u32 m_game_time; u32 m_game_time;
// A helper variable for incrementing the latter // A helper variable for incrementing the latter
float m_game_time_fraction_counter; float m_game_time_fraction_counter;
// Time of last clearObjects call (game time).
// When a mapblock older than this is loaded, its objects are cleared.
u32 m_last_clear_objects_time;
// Active block modifiers
std::vector<ABMWithState> m_abms; std::vector<ABMWithState> m_abms;
// An interval for generally sending object positions and stuff // An interval for generally sending object positions and stuff
float m_recommended_send_interval; float m_recommended_send_interval;

@ -36,6 +36,13 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "emerge.h" #include "emerge.h"
#include "pathfinder.h" #include "pathfinder.h"
struct EnumString ModApiEnvMod::es_ClearObjectsMode[] =
{
{CLEAR_OBJECTS_MODE_FULL, "full"},
{CLEAR_OBJECTS_MODE_QUICK, "quick"},
{0, NULL},
};
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
@ -727,13 +734,20 @@ int ModApiEnvMod::l_get_voxel_manip(lua_State *L)
return 1; return 1;
} }
// clear_objects() // clear_objects([options])
// clear all objects in the environment // clear all objects in the environment
// where options = {mode = "full" or "quick"}
int ModApiEnvMod::l_clear_objects(lua_State *L) int ModApiEnvMod::l_clear_objects(lua_State *L)
{ {
GET_ENV_PTR; GET_ENV_PTR;
env->clearAllObjects(); ClearObjectsMode mode = CLEAR_OBJECTS_MODE_FULL;
if (lua_istable(L, 1)) {
mode = (ClearObjectsMode)getenumfield(L, 1, "mode",
ModApiEnvMod::es_ClearObjectsMode, mode);
}
env->clearObjects(mode);
return 0; return 0;
} }

@ -170,6 +170,8 @@ private:
public: public:
static void Initialize(lua_State *L, int top); static void Initialize(lua_State *L, int top);
static struct EnumString es_ClearObjectsMode[];
}; };
class LuaABM : public ActiveBlockModifier { class LuaABM : public ActiveBlockModifier {