Skip to content

Commit b1428ab

Browse files
kahrlparamat
authored andcommittedFeb 11, 2016
Add '/clearobjects quick'
1 parent 47464c9 commit b1428ab

File tree

6 files changed

+124
-51
lines changed

6 files changed

+124
-51
lines changed
 

‎builtin/game/chatcommands.lua

+11-1
Original file line numberDiff line numberDiff line change
@@ -848,14 +848,24 @@ core.register_chatcommand("kick", {
848848
})
849849

850850
core.register_chatcommand("clearobjects", {
851+
params = "[full|quick]",
851852
description = "clear all objects in world",
852853
privs = {server=true},
853854
func = function(name, param)
855+
options = {}
856+
if param == "" or param == "full" then
857+
options.mode = "full"
858+
elseif param == "quick" then
859+
options.mode = "quick"
860+
else
861+
return false, "Invalid usage, see /help clearobjects."
862+
end
863+
854864
core.log("action", name .. " clears all objects.")
855865
core.chat_send_all("Clearing all objects. This may take long."
856866
.. " You may experience a timeout. (by "
857867
.. name .. ")")
858-
core.clear_objects()
868+
core.clear_objects(options)
859869
core.log("action", "Object clearing done.")
860870
core.chat_send_all("*** Cleared all objects.")
861871
end,

‎doc/lua_api.txt

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

‎src/environment.cpp

+71-44
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,7 @@ ServerEnvironment::ServerEnvironment(ServerMap *map,
354354
m_active_block_interval_overload_skip(0),
355355
m_game_time(0),
356356
m_game_time_fraction_counter(0),
357+
m_last_clear_objects_time(0),
357358
m_recommended_send_interval(0.1),
358359
m_max_lag_estimate(0.1)
359360
{
@@ -503,6 +504,7 @@ void ServerEnvironment::saveMeta()
503504
Settings args;
504505
args.setU64("game_time", m_game_time);
505506
args.setU64("time_of_day", getTimeOfDay());
507+
args.setU64("last_clear_objects_time", m_last_clear_objects_time);
506508
args.writeLines(ss);
507509
ss<<"EnvArgsEnd\n";
508510

@@ -546,6 +548,13 @@ void ServerEnvironment::loadMeta()
546548
// This is not as important
547549
setTimeOfDay(9000);
548550
}
551+
552+
try {
553+
m_last_clear_objects_time = args.getU64("last_clear_objects_time");
554+
} catch (SettingNotFoundException &e) {
555+
// If missing, do as if clearObjects was never called
556+
m_last_clear_objects_time = 0;
557+
}
549558
}
550559

551560
struct ActiveABM
@@ -739,13 +748,19 @@ void ServerEnvironment::activateBlock(MapBlock *block, u32 additional_dtime)
739748
// Get time difference
740749
u32 dtime_s = 0;
741750
u32 stamp = block->getTimestamp();
742-
if(m_game_time > stamp && stamp != BLOCK_TIMESTAMP_UNDEFINED)
743-
dtime_s = m_game_time - block->getTimestamp();
751+
if (m_game_time > stamp && stamp != BLOCK_TIMESTAMP_UNDEFINED)
752+
dtime_s = m_game_time - stamp;
744753
dtime_s += additional_dtime;
745754

746755
/*infostream<<"ServerEnvironment::activateBlock(): block timestamp: "
747756
<<stamp<<", game time: "<<m_game_time<<std::endl;*/
748757

758+
// Remove stored static objects if clearObjects was called since block's timestamp
759+
if (stamp == BLOCK_TIMESTAMP_UNDEFINED || stamp < m_last_clear_objects_time) {
760+
block->m_static_objects.m_stored.clear();
761+
// do not set changed flag to avoid unnecessary mapblock writes
762+
}
763+
749764
// Set current time as timestamp
750765
block->setTimestampNoChangedFlag(m_game_time);
751766

@@ -858,30 +873,30 @@ void ServerEnvironment::getObjectsInsideRadius(std::vector<u16> &objects, v3f po
858873
}
859874
}
860875

861-
void ServerEnvironment::clearAllObjects()
876+
void ServerEnvironment::clearObjects(ClearObjectsMode mode)
862877
{
863-
infostream<<"ServerEnvironment::clearAllObjects(): "
864-
<<"Removing all active objects"<<std::endl;
878+
infostream << "ServerEnvironment::clearObjects(): "
879+
<< "Removing all active objects" << std::endl;
865880
std::vector<u16> objects_to_remove;
866-
for(std::map<u16, ServerActiveObject*>::iterator
881+
for (std::map<u16, ServerActiveObject*>::iterator
867882
i = m_active_objects.begin();
868883
i != m_active_objects.end(); ++i) {
869884
ServerActiveObject* obj = i->second;
870-
if(obj->getType() == ACTIVEOBJECT_TYPE_PLAYER)
885+
if (obj->getType() == ACTIVEOBJECT_TYPE_PLAYER)
871886
continue;
872887
u16 id = i->first;
873888
// Delete static object if block is loaded
874-
if(obj->m_static_exists){
889+
if (obj->m_static_exists) {
875890
MapBlock *block = m_map->getBlockNoCreateNoEx(obj->m_static_block);
876-
if(block){
891+
if (block) {
877892
block->m_static_objects.remove(id);
878893
block->raiseModified(MOD_STATE_WRITE_NEEDED,
879894
MOD_REASON_CLEAR_ALL_OBJECTS);
880895
obj->m_static_exists = false;
881896
}
882897
}
883898
// If known by some client, don't delete immediately
884-
if(obj->m_known_by_count > 0){
899+
if (obj->m_known_by_count > 0) {
885900
obj->m_pending_deactivation = true;
886901
obj->m_removed = true;
887902
continue;
@@ -893,39 +908,46 @@ void ServerEnvironment::clearAllObjects()
893908
m_script->removeObjectReference(obj);
894909

895910
// Delete active object
896-
if(obj->environmentDeletes())
911+
if (obj->environmentDeletes())
897912
delete obj;
898913
// Id to be removed from m_active_objects
899914
objects_to_remove.push_back(id);
900915
}
901916

902917
// Remove references from m_active_objects
903-
for(std::vector<u16>::iterator i = objects_to_remove.begin();
918+
for (std::vector<u16>::iterator i = objects_to_remove.begin();
904919
i != objects_to_remove.end(); ++i) {
905920
m_active_objects.erase(*i);
906921
}
907922

908923
// Get list of loaded blocks
909924
std::vector<v3s16> loaded_blocks;
910-
infostream<<"ServerEnvironment::clearAllObjects(): "
911-
<<"Listing all loaded blocks"<<std::endl;
925+
infostream << "ServerEnvironment::clearObjects(): "
926+
<< "Listing all loaded blocks" << std::endl;
912927
m_map->listAllLoadedBlocks(loaded_blocks);
913-
infostream<<"ServerEnvironment::clearAllObjects(): "
914-
<<"Done listing all loaded blocks: "
915-
<<loaded_blocks.size()<<std::endl;
928+
infostream << "ServerEnvironment::clearObjects(): "
929+
<< "Done listing all loaded blocks: "
930+
<< loaded_blocks.size()<<std::endl;
916931

917932
// Get list of loadable blocks
918933
std::vector<v3s16> loadable_blocks;
919-
infostream<<"ServerEnvironment::clearAllObjects(): "
920-
<<"Listing all loadable blocks"<<std::endl;
921-
m_map->listAllLoadableBlocks(loadable_blocks);
922-
infostream<<"ServerEnvironment::clearAllObjects(): "
923-
<<"Done listing all loadable blocks: "
924-
<<loadable_blocks.size()
925-
<<", now clearing"<<std::endl;
934+
if (mode == CLEAR_OBJECTS_MODE_FULL) {
935+
infostream << "ServerEnvironment::clearObjects(): "
936+
<< "Listing all loadable blocks" << std::endl;
937+
m_map->listAllLoadableBlocks(loadable_blocks);
938+
infostream << "ServerEnvironment::clearObjects(): "
939+
<< "Done listing all loadable blocks: "
940+
<< loadable_blocks.size() << std::endl;
941+
} else {
942+
loadable_blocks = loaded_blocks;
943+
}
944+
945+
infostream << "ServerEnvironment::clearObjects(): "
946+
<< "Now clearing objects in " << loadable_blocks.size()
947+
<< " blocks" << std::endl;
926948

927949
// Grab a reference on each loaded block to avoid unloading it
928-
for(std::vector<v3s16>::iterator i = loaded_blocks.begin();
950+
for (std::vector<v3s16>::iterator i = loaded_blocks.begin();
929951
i != loaded_blocks.end(); ++i) {
930952
v3s16 p = *i;
931953
MapBlock *block = m_map->getBlockNoCreateNoEx(p);
@@ -934,24 +956,27 @@ void ServerEnvironment::clearAllObjects()
934956
}
935957

936958
// Remove objects in all loadable blocks
937-
u32 unload_interval = g_settings->getS32("max_clearobjects_extra_loaded_blocks");
938-
unload_interval = MYMAX(unload_interval, 1);
959+
u32 unload_interval = U32_MAX;
960+
if (mode == CLEAR_OBJECTS_MODE_FULL) {
961+
unload_interval = g_settings->getS32("max_clearobjects_extra_loaded_blocks");
962+
unload_interval = MYMAX(unload_interval, 1);
963+
}
939964
u32 report_interval = loadable_blocks.size() / 10;
940965
u32 num_blocks_checked = 0;
941966
u32 num_blocks_cleared = 0;
942967
u32 num_objs_cleared = 0;
943-
for(std::vector<v3s16>::iterator i = loadable_blocks.begin();
968+
for (std::vector<v3s16>::iterator i = loadable_blocks.begin();
944969
i != loadable_blocks.end(); ++i) {
945970
v3s16 p = *i;
946971
MapBlock *block = m_map->emergeBlock(p, false);
947-
if(!block){
948-
errorstream<<"ServerEnvironment::clearAllObjects(): "
949-
<<"Failed to emerge block "<<PP(p)<<std::endl;
972+
if (!block) {
973+
errorstream << "ServerEnvironment::clearObjects(): "
974+
<< "Failed to emerge block " << PP(p) << std::endl;
950975
continue;
951976
}
952977
u32 num_stored = block->m_static_objects.m_stored.size();
953978
u32 num_active = block->m_static_objects.m_active.size();
954-
if(num_stored != 0 || num_active != 0){
979+
if (num_stored != 0 || num_active != 0) {
955980
block->m_static_objects.m_stored.clear();
956981
block->m_static_objects.m_active.clear();
957982
block->raiseModified(MOD_STATE_WRITE_NEEDED,
@@ -961,33 +986,35 @@ void ServerEnvironment::clearAllObjects()
961986
}
962987
num_blocks_checked++;
963988

964-
if(report_interval != 0 &&
965-
num_blocks_checked % report_interval == 0){
989+
if (report_interval != 0 &&
990+
num_blocks_checked % report_interval == 0) {
966991
float percent = 100.0 * (float)num_blocks_checked /
967-
loadable_blocks.size();
968-
infostream<<"ServerEnvironment::clearAllObjects(): "
969-
<<"Cleared "<<num_objs_cleared<<" objects"
970-
<<" in "<<num_blocks_cleared<<" blocks ("
971-
<<percent<<"%)"<<std::endl;
992+
loadable_blocks.size();
993+
infostream << "ServerEnvironment::clearObjects(): "
994+
<< "Cleared " << num_objs_cleared << " objects"
995+
<< " in " << num_blocks_cleared << " blocks ("
996+
<< percent << "%)" << std::endl;
972997
}
973-
if(num_blocks_checked % unload_interval == 0){
998+
if (num_blocks_checked % unload_interval == 0) {
974999
m_map->unloadUnreferencedBlocks();
9751000
}
9761001
}
9771002
m_map->unloadUnreferencedBlocks();
9781003

9791004
// Drop references that were added above
980-
for(std::vector<v3s16>::iterator i = loaded_blocks.begin();
1005+
for (std::vector<v3s16>::iterator i = loaded_blocks.begin();
9811006
i != loaded_blocks.end(); ++i) {
9821007
v3s16 p = *i;
9831008
MapBlock *block = m_map->getBlockNoCreateNoEx(p);
9841009
assert(block);
9851010
block->refDrop();
9861011
}
9871012

988-
infostream<<"ServerEnvironment::clearAllObjects(): "
989-
<<"Finished: Cleared "<<num_objs_cleared<<" objects"
990-
<<" in "<<num_blocks_cleared<<" blocks"<<std::endl;
1013+
m_last_clear_objects_time = m_game_time;
1014+
1015+
infostream << "ServerEnvironment::clearObjects(): "
1016+
<< "Finished: Cleared " << num_objs_cleared << " objects"
1017+
<< " in " << num_blocks_cleared << " blocks" << std::endl;
9911018
}
9921019

9931020
void ServerEnvironment::step(float dtime)

‎src/environment.h

+18-2
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,18 @@ class ActiveBlockList
203203
private:
204204
};
205205

206+
/*
207+
Operation mode for ServerEnvironment::clearObjects()
208+
*/
209+
enum ClearObjectsMode {
210+
// Load and go through every mapblock, clearing objects
211+
CLEAR_OBJECTS_MODE_FULL,
212+
213+
// Clear objects immediately in loaded mapblocks;
214+
// clear objects in unloaded mapblocks only when the mapblocks are next activated.
215+
CLEAR_OBJECTS_MODE_QUICK,
216+
};
217+
206218
/*
207219
The server-side environment.
208220
@@ -319,8 +331,8 @@ class ServerEnvironment : public Environment
319331
// Find all active objects inside a radius around a point
320332
void getObjectsInsideRadius(std::vector<u16> &objects, v3f pos, float radius);
321333

322-
// Clear all objects, loading and going through every MapBlock
323-
void clearAllObjects();
334+
// Clear objects, loading and going through every MapBlock
335+
void clearObjects(ClearObjectsMode mode);
324336

325337
// This makes stuff happen
326338
void step(f32 dtime);
@@ -410,6 +422,10 @@ class ServerEnvironment : public Environment
410422
u32 m_game_time;
411423
// A helper variable for incrementing the latter
412424
float m_game_time_fraction_counter;
425+
// Time of last clearObjects call (game time).
426+
// When a mapblock older than this is loaded, its objects are cleared.
427+
u32 m_last_clear_objects_time;
428+
// Active block modifiers
413429
std::vector<ABMWithState> m_abms;
414430
// An interval for generally sending object positions and stuff
415431
float m_recommended_send_interval;

‎src/script/lua_api/l_env.cpp

+16-2
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,13 @@ with this program; if not, write to the Free Software Foundation, Inc.,
3636
#include "emerge.h"
3737
#include "pathfinder.h"
3838

39+
struct EnumString ModApiEnvMod::es_ClearObjectsMode[] =
40+
{
41+
{CLEAR_OBJECTS_MODE_FULL, "full"},
42+
{CLEAR_OBJECTS_MODE_QUICK, "quick"},
43+
{0, NULL},
44+
};
45+
3946
///////////////////////////////////////////////////////////////////////////////
4047

4148

@@ -727,13 +734,20 @@ int ModApiEnvMod::l_get_voxel_manip(lua_State *L)
727734
return 1;
728735
}
729736

730-
// clear_objects()
737+
// clear_objects([options])
731738
// clear all objects in the environment
739+
// where options = {mode = "full" or "quick"}
732740
int ModApiEnvMod::l_clear_objects(lua_State *L)
733741
{
734742
GET_ENV_PTR;
735743

736-
env->clearAllObjects();
744+
ClearObjectsMode mode = CLEAR_OBJECTS_MODE_FULL;
745+
if (lua_istable(L, 1)) {
746+
mode = (ClearObjectsMode)getenumfield(L, 1, "mode",
747+
ModApiEnvMod::es_ClearObjectsMode, mode);
748+
}
749+
750+
env->clearObjects(mode);
737751
return 0;
738752
}
739753

‎src/script/lua_api/l_env.h

+2
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,8 @@ class ModApiEnvMod : public ModApiBase {
170170

171171
public:
172172
static void Initialize(lua_State *L, int top);
173+
174+
static struct EnumString es_ClearObjectsMode[];
173175
};
174176

175177
class LuaABM : public ActiveBlockModifier {

0 commit comments

Comments
 (0)
Please sign in to comment.