forked from Mirrorlandia_minetest/minetest
changed server to do object management at longer intervals (0.5s)
This commit is contained in:
parent
26eb607a11
commit
9d5ccafbb0
@ -449,227 +449,231 @@ void ServerEnvironment::step(float dtime)
|
||||
obj->step(dtime, m_active_object_messages, send_recommended);
|
||||
}
|
||||
|
||||
/*
|
||||
Remove objects that satisfy (m_removed && m_known_by_count==0)
|
||||
*/
|
||||
if(m_object_management_interval.step(dtime, 0.5))
|
||||
{
|
||||
core::list<u16> objects_to_remove;
|
||||
for(core::map<u16, ServerActiveObject*>::Iterator
|
||||
i = m_active_objects.getIterator();
|
||||
i.atEnd()==false; i++)
|
||||
/*
|
||||
Remove objects that satisfy (m_removed && m_known_by_count==0)
|
||||
*/
|
||||
{
|
||||
u16 id = i.getNode()->getKey();
|
||||
ServerActiveObject* obj = i.getNode()->getValue();
|
||||
// This shouldn't happen but check it
|
||||
if(obj == NULL)
|
||||
core::list<u16> objects_to_remove;
|
||||
for(core::map<u16, ServerActiveObject*>::Iterator
|
||||
i = m_active_objects.getIterator();
|
||||
i.atEnd()==false; i++)
|
||||
{
|
||||
dstream<<"WARNING: NULL object found in ServerEnvironment"
|
||||
<<" while finding removed objects. id="<<id<<std::endl;
|
||||
u16 id = i.getNode()->getKey();
|
||||
ServerActiveObject* obj = i.getNode()->getValue();
|
||||
// This shouldn't happen but check it
|
||||
if(obj == NULL)
|
||||
{
|
||||
dstream<<"WARNING: NULL object found in ServerEnvironment"
|
||||
<<" while finding removed objects. id="<<id<<std::endl;
|
||||
// Id to be removed from m_active_objects
|
||||
objects_to_remove.push_back(id);
|
||||
continue;
|
||||
}
|
||||
// If not m_removed, don't remove.
|
||||
if(obj->m_removed == false)
|
||||
continue;
|
||||
// Delete static data from block
|
||||
if(obj->m_static_exists)
|
||||
{
|
||||
MapBlock *block = m_map->getBlockNoCreateNoEx(obj->m_static_block);
|
||||
if(block)
|
||||
{
|
||||
block->m_static_objects.remove(id);
|
||||
block->setChangedFlag();
|
||||
}
|
||||
}
|
||||
// If m_known_by_count > 0, don't actually remove.
|
||||
if(obj->m_known_by_count > 0)
|
||||
continue;
|
||||
// Delete
|
||||
delete obj;
|
||||
// Id to be removed from m_active_objects
|
||||
objects_to_remove.push_back(id);
|
||||
continue;
|
||||
}
|
||||
// If not m_removed, don't remove.
|
||||
if(obj->m_removed == false)
|
||||
continue;
|
||||
// Delete static data from block
|
||||
if(obj->m_static_exists)
|
||||
// Remove references from m_active_objects
|
||||
for(core::list<u16>::Iterator i = objects_to_remove.begin();
|
||||
i != objects_to_remove.end(); i++)
|
||||
{
|
||||
MapBlock *block = m_map->getBlockNoCreateNoEx(obj->m_static_block);
|
||||
if(block)
|
||||
{
|
||||
block->m_static_objects.remove(id);
|
||||
block->setChangedFlag();
|
||||
}
|
||||
m_active_objects.remove(*i);
|
||||
}
|
||||
// If m_known_by_count > 0, don't actually remove.
|
||||
if(obj->m_known_by_count > 0)
|
||||
continue;
|
||||
// Delete
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const s16 to_active_max_blocks = 3;
|
||||
const f32 to_static_max_f = (to_active_max_blocks+1)*MAP_BLOCKSIZE*BS;
|
||||
|
||||
/*
|
||||
Convert stored objects from blocks near the players to active.
|
||||
*/
|
||||
for(core::list<Player*>::Iterator i = m_players.begin();
|
||||
i != m_players.end(); i++)
|
||||
{
|
||||
Player *player = *i;
|
||||
|
||||
// Ignore disconnected players
|
||||
if(player->peer_id == 0)
|
||||
continue;
|
||||
|
||||
v3f playerpos = player->getPosition();
|
||||
|
||||
v3s16 blockpos0 = getNodeBlockPos(floatToInt(playerpos, BS));
|
||||
v3s16 bpmin = blockpos0 - v3s16(1,1,1)*to_active_max_blocks;
|
||||
v3s16 bpmax = blockpos0 + v3s16(1,1,1)*to_active_max_blocks;
|
||||
// Loop through all nearby blocks
|
||||
for(s16 x=bpmin.X; x<=bpmax.X; x++)
|
||||
for(s16 y=bpmin.Y; y<=bpmax.Y; y++)
|
||||
for(s16 z=bpmin.Z; z<=bpmax.Z; z++)
|
||||
const s16 to_active_max_blocks = 3;
|
||||
const f32 to_static_max_f = (to_active_max_blocks+1)*MAP_BLOCKSIZE*BS;
|
||||
|
||||
/*
|
||||
Convert stored objects from blocks near the players to active.
|
||||
*/
|
||||
for(core::list<Player*>::Iterator i = m_players.begin();
|
||||
i != m_players.end(); i++)
|
||||
{
|
||||
v3s16 blockpos(x,y,z);
|
||||
MapBlock *block = m_map->getBlockNoCreateNoEx(blockpos);
|
||||
if(block==NULL)
|
||||
Player *player = *i;
|
||||
|
||||
// Ignore disconnected players
|
||||
if(player->peer_id == 0)
|
||||
continue;
|
||||
// Ignore if no stored objects (to not set changed flag)
|
||||
if(block->m_static_objects.m_stored.size() == 0)
|
||||
continue;
|
||||
// This will contain the leftovers of the stored list
|
||||
core::list<StaticObject> new_stored;
|
||||
// Loop through stored static objects
|
||||
for(core::list<StaticObject>::Iterator
|
||||
i = block->m_static_objects.m_stored.begin();
|
||||
i != block->m_static_objects.m_stored.end(); i++)
|
||||
|
||||
v3f playerpos = player->getPosition();
|
||||
|
||||
v3s16 blockpos0 = getNodeBlockPos(floatToInt(playerpos, BS));
|
||||
v3s16 bpmin = blockpos0 - v3s16(1,1,1)*to_active_max_blocks;
|
||||
v3s16 bpmax = blockpos0 + v3s16(1,1,1)*to_active_max_blocks;
|
||||
// Loop through all nearby blocks
|
||||
for(s16 x=bpmin.X; x<=bpmax.X; x++)
|
||||
for(s16 y=bpmin.Y; y<=bpmax.Y; y++)
|
||||
for(s16 z=bpmin.Z; z<=bpmax.Z; z++)
|
||||
{
|
||||
/*dstream<<"INFO: Server: Creating an active object from "
|
||||
<<"static data"<<std::endl;*/
|
||||
StaticObject &s_obj = *i;
|
||||
// Create an active object from the data
|
||||
ServerActiveObject *obj = ServerActiveObject::create
|
||||
(s_obj.type, this, 0, s_obj.pos, s_obj.data);
|
||||
if(obj==NULL)
|
||||
{
|
||||
// This is necessary to preserve stuff during bugs
|
||||
// and errors
|
||||
new_stored.push_back(s_obj);
|
||||
v3s16 blockpos(x,y,z);
|
||||
MapBlock *block = m_map->getBlockNoCreateNoEx(blockpos);
|
||||
if(block==NULL)
|
||||
continue;
|
||||
}
|
||||
// This will also add the object to the active static list
|
||||
addActiveObject(obj);
|
||||
//u16 id = addActiveObject(obj);
|
||||
}
|
||||
// Clear stored list
|
||||
block->m_static_objects.m_stored.clear();
|
||||
// Add leftover stuff to stored list
|
||||
for(core::list<StaticObject>::Iterator
|
||||
i = new_stored.begin();
|
||||
i != new_stored.end(); i++)
|
||||
{
|
||||
StaticObject &s_obj = *i;
|
||||
block->m_static_objects.m_stored.push_back(s_obj);
|
||||
}
|
||||
block->setChangedFlag();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Convert objects that are far away from all the players to static.
|
||||
*/
|
||||
{
|
||||
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();
|
||||
|
||||
// This shouldn't happen but check it
|
||||
if(obj == NULL)
|
||||
{
|
||||
dstream<<"WARNING: NULL object found in ServerEnvironment"
|
||||
<<std::endl;
|
||||
continue;
|
||||
}
|
||||
// If known by some client, don't convert to static.
|
||||
if(obj->m_known_by_count > 0)
|
||||
continue;
|
||||
|
||||
// If close to some player, don't convert to static.
|
||||
bool close_to_player = false;
|
||||
for(core::list<Player*>::Iterator i = m_players.begin();
|
||||
i != m_players.end(); i++)
|
||||
{
|
||||
Player *player = *i;
|
||||
|
||||
// Ignore disconnected players
|
||||
if(player->peer_id == 0)
|
||||
// Ignore if no stored objects (to not set changed flag)
|
||||
if(block->m_static_objects.m_stored.size() == 0)
|
||||
continue;
|
||||
|
||||
v3f playerpos = player->getPosition();
|
||||
f32 d = playerpos.getDistanceFrom(objectpos);
|
||||
if(d < to_static_max_f)
|
||||
// This will contain the leftovers of the stored list
|
||||
core::list<StaticObject> new_stored;
|
||||
// Loop through stored static objects
|
||||
for(core::list<StaticObject>::Iterator
|
||||
i = block->m_static_objects.m_stored.begin();
|
||||
i != block->m_static_objects.m_stored.end(); i++)
|
||||
{
|
||||
close_to_player = true;
|
||||
break;
|
||||
/*dstream<<"INFO: Server: Creating an active object from "
|
||||
<<"static data"<<std::endl;*/
|
||||
StaticObject &s_obj = *i;
|
||||
// Create an active object from the data
|
||||
ServerActiveObject *obj = ServerActiveObject::create
|
||||
(s_obj.type, this, 0, s_obj.pos, s_obj.data);
|
||||
if(obj==NULL)
|
||||
{
|
||||
// This is necessary to preserve stuff during bugs
|
||||
// and errors
|
||||
new_stored.push_back(s_obj);
|
||||
continue;
|
||||
}
|
||||
// This will also add the object to the active static list
|
||||
addActiveObject(obj);
|
||||
//u16 id = addActiveObject(obj);
|
||||
}
|
||||
}
|
||||
|
||||
if(close_to_player)
|
||||
continue;
|
||||
|
||||
/*
|
||||
Update the static data and remove the active object.
|
||||
*/
|
||||
|
||||
// Delete old static object
|
||||
MapBlock *oldblock = NULL;
|
||||
if(obj->m_static_exists)
|
||||
{
|
||||
MapBlock *block = m_map->getBlockNoCreateNoEx(obj->m_static_block);
|
||||
if(block)
|
||||
// Clear stored list
|
||||
block->m_static_objects.m_stored.clear();
|
||||
// Add leftover stuff to stored list
|
||||
for(core::list<StaticObject>::Iterator
|
||||
i = new_stored.begin();
|
||||
i != new_stored.end(); i++)
|
||||
{
|
||||
block->m_static_objects.remove(id);
|
||||
oldblock = block;
|
||||
StaticObject &s_obj = *i;
|
||||
block->m_static_objects.m_stored.push_back(s_obj);
|
||||
}
|
||||
}
|
||||
// Add new static object
|
||||
std::string staticdata = obj->getStaticData();
|
||||
StaticObject s_obj(obj->getType(), objectpos, staticdata);
|
||||
// Add to the block where the object is located in
|
||||
v3s16 blockpos = getNodeBlockPos(floatToInt(objectpos, BS));
|
||||
MapBlock *block = m_map->getBlockNoCreateNoEx(blockpos);
|
||||
if(block)
|
||||
{
|
||||
block->m_static_objects.insert(0, s_obj);
|
||||
block->setChangedFlag();
|
||||
obj->m_static_exists = true;
|
||||
obj->m_static_block = block->getPos();
|
||||
}
|
||||
// If not possible, add back to previous block
|
||||
else if(oldblock)
|
||||
{
|
||||
oldblock->m_static_objects.insert(0, s_obj);
|
||||
oldblock->setChangedFlag();
|
||||
obj->m_static_exists = true;
|
||||
obj->m_static_block = oldblock->getPos();
|
||||
}
|
||||
else{
|
||||
dstream<<"WARNING: Server: Could not find a block for "
|
||||
<<"storing static object"<<std::endl;
|
||||
obj->m_static_exists = false;
|
||||
continue;
|
||||
}
|
||||
/*dstream<<"INFO: Server: Stored static data. Deleting object."
|
||||
<<std::endl;*/
|
||||
// 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++)
|
||||
|
||||
/*
|
||||
Convert objects that are far away from all the players to static.
|
||||
*/
|
||||
{
|
||||
m_active_objects.remove(*i);
|
||||
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();
|
||||
|
||||
// This shouldn't happen but check it
|
||||
if(obj == NULL)
|
||||
{
|
||||
dstream<<"WARNING: NULL object found in ServerEnvironment"
|
||||
<<std::endl;
|
||||
continue;
|
||||
}
|
||||
// If known by some client, don't convert to static.
|
||||
if(obj->m_known_by_count > 0)
|
||||
continue;
|
||||
|
||||
// If close to some player, don't convert to static.
|
||||
bool close_to_player = false;
|
||||
for(core::list<Player*>::Iterator i = m_players.begin();
|
||||
i != m_players.end(); i++)
|
||||
{
|
||||
Player *player = *i;
|
||||
|
||||
// Ignore disconnected players
|
||||
if(player->peer_id == 0)
|
||||
continue;
|
||||
|
||||
v3f playerpos = player->getPosition();
|
||||
f32 d = playerpos.getDistanceFrom(objectpos);
|
||||
if(d < to_static_max_f)
|
||||
{
|
||||
close_to_player = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(close_to_player)
|
||||
continue;
|
||||
|
||||
/*
|
||||
Update the static data and remove the active object.
|
||||
*/
|
||||
|
||||
// Delete old static object
|
||||
MapBlock *oldblock = NULL;
|
||||
if(obj->m_static_exists)
|
||||
{
|
||||
MapBlock *block = m_map->getBlockNoCreateNoEx
|
||||
(obj->m_static_block);
|
||||
if(block)
|
||||
{
|
||||
block->m_static_objects.remove(id);
|
||||
oldblock = block;
|
||||
}
|
||||
}
|
||||
// Add new static object
|
||||
std::string staticdata = obj->getStaticData();
|
||||
StaticObject s_obj(obj->getType(), objectpos, staticdata);
|
||||
// Add to the block where the object is located in
|
||||
v3s16 blockpos = getNodeBlockPos(floatToInt(objectpos, BS));
|
||||
MapBlock *block = m_map->getBlockNoCreateNoEx(blockpos);
|
||||
if(block)
|
||||
{
|
||||
block->m_static_objects.insert(0, s_obj);
|
||||
block->setChangedFlag();
|
||||
obj->m_static_exists = true;
|
||||
obj->m_static_block = block->getPos();
|
||||
}
|
||||
// If not possible, add back to previous block
|
||||
else if(oldblock)
|
||||
{
|
||||
oldblock->m_static_objects.insert(0, s_obj);
|
||||
oldblock->setChangedFlag();
|
||||
obj->m_static_exists = true;
|
||||
obj->m_static_block = oldblock->getPos();
|
||||
}
|
||||
else{
|
||||
dstream<<"WARNING: Server: Could not find a block for "
|
||||
<<"storing static object"<<std::endl;
|
||||
obj->m_static_exists = false;
|
||||
continue;
|
||||
}
|
||||
/*dstream<<"INFO: Server: Stored static data. Deleting object."
|
||||
<<std::endl;*/
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -35,6 +35,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "player.h"
|
||||
#include "map.h"
|
||||
#include <ostream>
|
||||
#include "utility.h"
|
||||
|
||||
class Environment
|
||||
{
|
||||
@ -154,6 +155,7 @@ private:
|
||||
Queue<ActiveObjectMessage> m_active_object_messages;
|
||||
float m_random_spawn_timer;
|
||||
float m_send_recommended_timer;
|
||||
IntervalLimiter m_object_management_interval;
|
||||
};
|
||||
|
||||
#ifndef SERVER
|
||||
|
Loading…
Reference in New Issue
Block a user