mirror of
https://github.com/minetest/minetest.git
synced 2024-11-27 18:13:46 +01:00
Add /clearobjects
This commit is contained in:
parent
ea1fda5ebc
commit
78f4142f4f
@ -647,6 +647,92 @@ void ServerEnvironment::activateBlock(MapBlock *block, u32 additional_dtime)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ServerEnvironment::clearAllObjects()
|
||||||
|
{
|
||||||
|
infostream<<"ServerEnvironment::clearAllObjects(): "
|
||||||
|
<<"Removing all active objects"<<std::endl;
|
||||||
|
core::list<u16> objects_to_remove;
|
||||||
|
for(core::map<u16, ServerActiveObject*>::Iterator
|
||||||
|
i = m_active_objects.getIterator();
|
||||||
|
i.atEnd()==false; i++)
|
||||||
|
{
|
||||||
|
ServerActiveObject* obj = i.getNode()->getValue();
|
||||||
|
u16 id = i.getNode()->getKey();
|
||||||
|
v3f objectpos = obj->getBasePosition();
|
||||||
|
// Delete static object if block is loaded
|
||||||
|
if(obj->m_static_exists){
|
||||||
|
MapBlock *block = m_map->getBlockNoCreateNoEx(obj->m_static_block);
|
||||||
|
if(block){
|
||||||
|
block->m_static_objects.remove(id);
|
||||||
|
block->raiseModified(MOD_STATE_WRITE_NEEDED);
|
||||||
|
obj->m_static_exists = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// If known by some client, don't delete immediately
|
||||||
|
if(obj->m_known_by_count > 0){
|
||||||
|
obj->m_pending_deactivation = true;
|
||||||
|
obj->m_removed = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Delete active object
|
||||||
|
delete obj;
|
||||||
|
// Id to be removed from m_active_objects
|
||||||
|
objects_to_remove.push_back(id);
|
||||||
|
}
|
||||||
|
// Remove references from m_active_objects
|
||||||
|
for(core::list<u16>::Iterator i = objects_to_remove.begin();
|
||||||
|
i != objects_to_remove.end(); i++)
|
||||||
|
{
|
||||||
|
m_active_objects.remove(*i);
|
||||||
|
}
|
||||||
|
|
||||||
|
core::list<v3s16> loadable_blocks;
|
||||||
|
infostream<<"ServerEnvironment::clearAllObjects(): "
|
||||||
|
<<"Listing all loadable blocks"<<std::endl;
|
||||||
|
m_map->listAllLoadableBlocks(loadable_blocks);
|
||||||
|
infostream<<"ServerEnvironment::clearAllObjects(): "
|
||||||
|
<<"Done listing all loadable blocks: "
|
||||||
|
<<loadable_blocks.size()
|
||||||
|
<<", now clearing"<<std::endl;
|
||||||
|
u32 report_interval = loadable_blocks.size() / 10;
|
||||||
|
u32 num_blocks_checked = 0;
|
||||||
|
u32 num_blocks_cleared = 0;
|
||||||
|
u32 num_objs_cleared = 0;
|
||||||
|
for(core::list<v3s16>::Iterator i = loadable_blocks.begin();
|
||||||
|
i != loadable_blocks.end(); i++)
|
||||||
|
{
|
||||||
|
v3s16 p = *i;
|
||||||
|
MapBlock *block = m_map->emergeBlock(p, false);
|
||||||
|
if(!block){
|
||||||
|
errorstream<<"ServerEnvironment::clearAllObjects(): "
|
||||||
|
<<"Failed to emerge block "<<PP(p)<<std::endl;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
u32 num_stored = block->m_static_objects.m_stored.size();
|
||||||
|
u32 num_active = block->m_static_objects.m_active.size();
|
||||||
|
if(num_stored != 0 || num_active != 0){
|
||||||
|
block->m_static_objects.m_stored.clear();
|
||||||
|
block->m_static_objects.m_active.clear();
|
||||||
|
block->raiseModified(MOD_STATE_WRITE_NEEDED);
|
||||||
|
num_objs_cleared += num_stored + num_active;
|
||||||
|
num_blocks_cleared++;
|
||||||
|
}
|
||||||
|
num_blocks_checked++;
|
||||||
|
|
||||||
|
if(num_blocks_checked % report_interval == 0){
|
||||||
|
float percent = 100.0 * (float)num_blocks_checked /
|
||||||
|
loadable_blocks.size();
|
||||||
|
infostream<<"ServerEnvironment::clearAllObjects(): "
|
||||||
|
<<"Cleared "<<num_objs_cleared<<" objects"
|
||||||
|
<<" in "<<num_blocks_cleared<<" blocks ("
|
||||||
|
<<percent<<"%)"<<std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
infostream<<"ServerEnvironment::clearAllObjects(): "
|
||||||
|
<<"Finished: Cleared "<<num_objs_cleared<<" objects"
|
||||||
|
<<" in "<<num_blocks_cleared<<" blocks"<<std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
static void getMob_dungeon_master(Settings &properties)
|
static void getMob_dungeon_master(Settings &properties)
|
||||||
{
|
{
|
||||||
properties.set("looks", "dungeon_master");
|
properties.set("looks", "dungeon_master");
|
||||||
|
@ -218,6 +218,11 @@ public:
|
|||||||
|
|
||||||
void addActiveBlockModifier(ActiveBlockModifier *abm);
|
void addActiveBlockModifier(ActiveBlockModifier *abm);
|
||||||
|
|
||||||
|
/* Other stuff */
|
||||||
|
|
||||||
|
// Clear all objects, loading and going through every MapBlock
|
||||||
|
void clearAllObjects();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
198
src/map.cpp
198
src/map.cpp
@ -2623,152 +2623,6 @@ MapBlock * ServerMap::emergeBlock(v3s16 p, bool allow_generate)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
/*
|
|
||||||
Do not generate over-limit
|
|
||||||
*/
|
|
||||||
if(p.X < -MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
|
|
||||||
|| p.X > MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
|
|
||||||
|| p.Y < -MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
|
|
||||||
|| p.Y > MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
|
|
||||||
|| p.Z < -MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
|
|
||||||
|| p.Z > MAP_GENERATION_LIMIT / MAP_BLOCKSIZE)
|
|
||||||
throw InvalidPositionException("emergeBlock(): pos. over limit");
|
|
||||||
|
|
||||||
v2s16 p2d(p.X, p.Z);
|
|
||||||
s16 block_y = p.Y;
|
|
||||||
/*
|
|
||||||
This will create or load a sector if not found in memory.
|
|
||||||
If block exists on disk, it will be loaded.
|
|
||||||
*/
|
|
||||||
ServerMapSector *sector;
|
|
||||||
try{
|
|
||||||
sector = createSector(p2d);
|
|
||||||
//sector = emergeSector(p2d, changed_blocks);
|
|
||||||
}
|
|
||||||
catch(InvalidPositionException &e)
|
|
||||||
{
|
|
||||||
infostream<<"emergeBlock: createSector() failed: "
|
|
||||||
<<e.what()<<std::endl;
|
|
||||||
infostream<<"Path to failed sector: "<<getSectorDir(p2d)
|
|
||||||
<<std::endl
|
|
||||||
<<"You could try to delete it."<<std::endl;
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
catch(VersionMismatchException &e)
|
|
||||||
{
|
|
||||||
infostream<<"emergeBlock: createSector() failed: "
|
|
||||||
<<e.what()<<std::endl;
|
|
||||||
infostream<<"Path to failed sector: "<<getSectorDir(p2d)
|
|
||||||
<<std::endl
|
|
||||||
<<"You could try to delete it."<<std::endl;
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Try to get a block from the sector
|
|
||||||
*/
|
|
||||||
|
|
||||||
bool does_not_exist = false;
|
|
||||||
bool lighting_expired = false;
|
|
||||||
MapBlock *block = sector->getBlockNoCreateNoEx(block_y);
|
|
||||||
|
|
||||||
// If not found, try loading from disk
|
|
||||||
if(block == NULL)
|
|
||||||
{
|
|
||||||
block = loadBlock(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle result
|
|
||||||
if(block == NULL)
|
|
||||||
{
|
|
||||||
does_not_exist = true;
|
|
||||||
}
|
|
||||||
else if(block->isDummy() == true)
|
|
||||||
{
|
|
||||||
does_not_exist = true;
|
|
||||||
}
|
|
||||||
else if(block->getLightingExpired())
|
|
||||||
{
|
|
||||||
lighting_expired = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Valid block
|
|
||||||
//infostream<<"emergeBlock(): Returning already valid block"<<std::endl;
|
|
||||||
return block;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
If block was not found on disk and not going to generate a
|
|
||||||
new one, make sure there is a dummy block in place.
|
|
||||||
*/
|
|
||||||
if(only_from_disk && (does_not_exist || lighting_expired))
|
|
||||||
{
|
|
||||||
//infostream<<"emergeBlock(): Was not on disk but not generating"<<std::endl;
|
|
||||||
|
|
||||||
if(block == NULL)
|
|
||||||
{
|
|
||||||
// Create dummy block
|
|
||||||
block = new MapBlock(this, p, true);
|
|
||||||
|
|
||||||
// Add block to sector
|
|
||||||
sector->insertBlock(block);
|
|
||||||
}
|
|
||||||
// Done.
|
|
||||||
return block;
|
|
||||||
}
|
|
||||||
|
|
||||||
//infostream<<"Not found on disk, generating."<<std::endl;
|
|
||||||
// 0ms
|
|
||||||
//TimeTaker("emergeBlock() generate");
|
|
||||||
|
|
||||||
//infostream<<"emergeBlock(): Didn't find valid block -> making one"<<std::endl;
|
|
||||||
|
|
||||||
/*
|
|
||||||
If the block doesn't exist, generate the block.
|
|
||||||
*/
|
|
||||||
if(does_not_exist)
|
|
||||||
{
|
|
||||||
block = generateBlock(p, block, sector, changed_blocks,
|
|
||||||
lighting_invalidated_blocks);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(lighting_expired)
|
|
||||||
{
|
|
||||||
lighting_invalidated_blocks.insert(p, block);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
/*
|
|
||||||
Initially update sunlight
|
|
||||||
*/
|
|
||||||
{
|
|
||||||
core::map<v3s16, bool> light_sources;
|
|
||||||
bool black_air_left = false;
|
|
||||||
bool bottom_invalid =
|
|
||||||
block->propagateSunlight(light_sources, true,
|
|
||||||
&black_air_left);
|
|
||||||
|
|
||||||
// If sunlight didn't reach everywhere and part of block is
|
|
||||||
// above ground, lighting has to be properly updated
|
|
||||||
//if(black_air_left && some_part_underground)
|
|
||||||
if(black_air_left)
|
|
||||||
{
|
|
||||||
lighting_invalidated_blocks[block->getPos()] = block;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(bottom_invalid)
|
|
||||||
{
|
|
||||||
lighting_invalidated_blocks[block->getPos()] = block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return block;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
s16 ServerMap::findGroundLevel(v2s16 p2d)
|
s16 ServerMap::findGroundLevel(v2s16 p2d)
|
||||||
{
|
{
|
||||||
#if 0
|
#if 0
|
||||||
@ -2867,6 +2721,12 @@ void ServerMap::verifyDatabase() {
|
|||||||
throw FileNotGoodException("Cannot prepare write statement");
|
throw FileNotGoodException("Cannot prepare write statement");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
d = sqlite3_prepare(m_database, "SELECT `pos` FROM `blocks`", -1, &m_database_list, NULL);
|
||||||
|
if(d != SQLITE_OK) {
|
||||||
|
infostream<<"WARNING: Database list statment failed to prepare: "<<sqlite3_errmsg(m_database)<<std::endl;
|
||||||
|
throw FileNotGoodException("Cannot prepare read statement");
|
||||||
|
}
|
||||||
|
|
||||||
infostream<<"Server: Database opened"<<std::endl;
|
infostream<<"Server: Database opened"<<std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3039,6 +2899,52 @@ void ServerMap::save(bool only_changed)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static s32 unsignedToSigned(s32 i, s32 max_positive)
|
||||||
|
{
|
||||||
|
if(i < max_positive)
|
||||||
|
return i;
|
||||||
|
else
|
||||||
|
return i - 2*max_positive;
|
||||||
|
}
|
||||||
|
|
||||||
|
// modulo of a negative number does not work consistently in C
|
||||||
|
static sqlite3_int64 pythonmodulo(sqlite3_int64 i, sqlite3_int64 mod)
|
||||||
|
{
|
||||||
|
if(i >= 0)
|
||||||
|
return i % mod;
|
||||||
|
return mod - ((-i) % mod);
|
||||||
|
}
|
||||||
|
|
||||||
|
v3s16 ServerMap::getIntegerAsBlock(sqlite3_int64 i)
|
||||||
|
{
|
||||||
|
s32 x = unsignedToSigned(pythonmodulo(i, 4096), 2048);
|
||||||
|
i = (i - x) / 4096;
|
||||||
|
s32 y = unsignedToSigned(pythonmodulo(i, 4096), 2048);
|
||||||
|
i = (i - y) / 4096;
|
||||||
|
s32 z = unsignedToSigned(pythonmodulo(i, 4096), 2048);
|
||||||
|
return v3s16(x,y,z);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ServerMap::listAllLoadableBlocks(core::list<v3s16> &dst)
|
||||||
|
{
|
||||||
|
if(loadFromFolders()){
|
||||||
|
errorstream<<"Map::listAllLoadableBlocks(): Result will be missing "
|
||||||
|
<<"all blocks that are stored in flat files"<<std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
verifyDatabase();
|
||||||
|
|
||||||
|
while(sqlite3_step(m_database_list) == SQLITE_ROW)
|
||||||
|
{
|
||||||
|
sqlite3_int64 block_i = sqlite3_column_int64(m_database_list, 0);
|
||||||
|
v3s16 p = getIntegerAsBlock(block_i);
|
||||||
|
//dstream<<"block_i="<<block_i<<" p="<<PP(p)<<std::endl;
|
||||||
|
dst.push_back(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ServerMap::saveMapMeta()
|
void ServerMap::saveMapMeta()
|
||||||
{
|
{
|
||||||
DSTACK(__FUNCTION_NAME);
|
DSTACK(__FUNCTION_NAME);
|
||||||
|
@ -383,6 +383,7 @@ public:
|
|||||||
void verifyDatabase();
|
void verifyDatabase();
|
||||||
// Get an integer suitable for a block
|
// Get an integer suitable for a block
|
||||||
static sqlite3_int64 getBlockAsInteger(const v3s16 pos);
|
static sqlite3_int64 getBlockAsInteger(const v3s16 pos);
|
||||||
|
static v3s16 getIntegerAsBlock(sqlite3_int64 i);
|
||||||
|
|
||||||
// Returns true if the database file does not exist
|
// Returns true if the database file does not exist
|
||||||
bool loadFromFolders();
|
bool loadFromFolders();
|
||||||
@ -394,6 +395,8 @@ public:
|
|||||||
void save(bool only_changed);
|
void save(bool only_changed);
|
||||||
//void loadAll();
|
//void loadAll();
|
||||||
|
|
||||||
|
void listAllLoadableBlocks(core::list<v3s16> &dst);
|
||||||
|
|
||||||
// Saves map seed and possibly other stuff
|
// Saves map seed and possibly other stuff
|
||||||
void saveMapMeta();
|
void saveMapMeta();
|
||||||
void loadMapMeta();
|
void loadMapMeta();
|
||||||
@ -458,6 +461,7 @@ private:
|
|||||||
sqlite3 *m_database;
|
sqlite3 *m_database;
|
||||||
sqlite3_stmt *m_database_read;
|
sqlite3_stmt *m_database_read;
|
||||||
sqlite3_stmt *m_database_write;
|
sqlite3_stmt *m_database_write;
|
||||||
|
sqlite3_stmt *m_database_list;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -4136,6 +4136,11 @@ void Server::notifyPlayer(const char *name, const std::wstring msg)
|
|||||||
SendChatMessage(player->peer_id, std::wstring(L"Server: -!- ")+msg);
|
SendChatMessage(player->peer_id, std::wstring(L"Server: -!- ")+msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Server::notifyPlayers(const std::wstring msg)
|
||||||
|
{
|
||||||
|
BroadcastChatMessage(msg);
|
||||||
|
}
|
||||||
|
|
||||||
v3f findSpawnPos(ServerMap &map)
|
v3f findSpawnPos(ServerMap &map)
|
||||||
{
|
{
|
||||||
//return v3f(50,50,50)*BS;
|
//return v3f(50,50,50)*BS;
|
||||||
|
@ -475,6 +475,7 @@ public:
|
|||||||
|
|
||||||
// Envlock and conlock should be locked when calling this
|
// Envlock and conlock should be locked when calling this
|
||||||
void notifyPlayer(const char *name, const std::wstring msg);
|
void notifyPlayer(const char *name, const std::wstring msg);
|
||||||
|
void notifyPlayers(const std::wstring msg);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -277,6 +277,35 @@ void cmd_banunban(std::wostringstream &os, ServerCommandContext *ctx)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cmd_clearobjects(std::wostringstream &os,
|
||||||
|
ServerCommandContext *ctx)
|
||||||
|
{
|
||||||
|
if((ctx->privs & PRIV_SERVER) ==0)
|
||||||
|
{
|
||||||
|
os<<L"-!- You don't have permission to do that";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
actionstream<<ctx->player->getName()
|
||||||
|
<<" clears all objects"<<std::endl;
|
||||||
|
|
||||||
|
{
|
||||||
|
std::wstring msg;
|
||||||
|
msg += L"Clearing all objects. This may take long.";
|
||||||
|
msg += L" You may experience a timeout. (by ";
|
||||||
|
msg += narrow_to_wide(ctx->player->getName());
|
||||||
|
msg += L")";
|
||||||
|
ctx->server->notifyPlayers(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->env->clearAllObjects();
|
||||||
|
|
||||||
|
actionstream<<"object clearing done"<<std::endl;
|
||||||
|
|
||||||
|
os<<L"*** cleared all objects";
|
||||||
|
ctx->flags |= SEND_TO_OTHERS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
std::wstring processServerCommand(ServerCommandContext *ctx)
|
std::wstring processServerCommand(ServerCommandContext *ctx)
|
||||||
{
|
{
|
||||||
@ -302,45 +331,28 @@ std::wstring processServerCommand(ServerCommandContext *ctx)
|
|||||||
os<<L" ban unban";
|
os<<L" ban unban";
|
||||||
}
|
}
|
||||||
else if(ctx->parms[0] == L"status")
|
else if(ctx->parms[0] == L"status")
|
||||||
{
|
|
||||||
cmd_status(os, ctx);
|
cmd_status(os, ctx);
|
||||||
}
|
|
||||||
else if(ctx->parms[0] == L"privs")
|
else if(ctx->parms[0] == L"privs")
|
||||||
{
|
|
||||||
cmd_privs(os, ctx);
|
cmd_privs(os, ctx);
|
||||||
}
|
|
||||||
else if(ctx->parms[0] == L"grant" || ctx->parms[0] == L"revoke")
|
else if(ctx->parms[0] == L"grant" || ctx->parms[0] == L"revoke")
|
||||||
{
|
|
||||||
cmd_grantrevoke(os, ctx);
|
cmd_grantrevoke(os, ctx);
|
||||||
}
|
|
||||||
else if(ctx->parms[0] == L"time")
|
else if(ctx->parms[0] == L"time")
|
||||||
{
|
|
||||||
cmd_time(os, ctx);
|
cmd_time(os, ctx);
|
||||||
}
|
|
||||||
else if(ctx->parms[0] == L"shutdown")
|
else if(ctx->parms[0] == L"shutdown")
|
||||||
{
|
|
||||||
cmd_shutdown(os, ctx);
|
cmd_shutdown(os, ctx);
|
||||||
}
|
|
||||||
else if(ctx->parms[0] == L"setting")
|
else if(ctx->parms[0] == L"setting")
|
||||||
{
|
|
||||||
cmd_setting(os, ctx);
|
cmd_setting(os, ctx);
|
||||||
}
|
|
||||||
else if(ctx->parms[0] == L"teleport")
|
else if(ctx->parms[0] == L"teleport")
|
||||||
{
|
|
||||||
cmd_teleport(os, ctx);
|
cmd_teleport(os, ctx);
|
||||||
}
|
|
||||||
else if(ctx->parms[0] == L"ban" || ctx->parms[0] == L"unban")
|
else if(ctx->parms[0] == L"ban" || ctx->parms[0] == L"unban")
|
||||||
{
|
|
||||||
cmd_banunban(os, ctx);
|
cmd_banunban(os, ctx);
|
||||||
}
|
|
||||||
else if(ctx->parms[0] == L"me")
|
else if(ctx->parms[0] == L"me")
|
||||||
{
|
|
||||||
cmd_me(os, ctx);
|
cmd_me(os, ctx);
|
||||||
}
|
else if(ctx->parms[0] == L"clearobjects")
|
||||||
|
cmd_clearobjects(os, ctx);
|
||||||
else
|
else
|
||||||
{
|
|
||||||
os<<L"-!- Invalid command: " + ctx->parms[0];
|
os<<L"-!- Invalid command: " + ctx->parms[0];
|
||||||
}
|
|
||||||
return os.str();
|
return os.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user