changed server to do object management at longer intervals (0.5s)

This commit is contained in:
Perttu Ahola 2011-04-10 23:14:41 +03:00
parent 26eb607a11
commit 9d5ccafbb0
2 changed files with 203 additions and 197 deletions

@ -449,227 +449,231 @@ void ServerEnvironment::step(float dtime)
obj->step(dtime, m_active_object_messages, send_recommended); obj->step(dtime, m_active_object_messages, send_recommended);
} }
/* if(m_object_management_interval.step(dtime, 0.5))
Remove objects that satisfy (m_removed && m_known_by_count==0)
*/
{ {
core::list<u16> objects_to_remove; /*
for(core::map<u16, ServerActiveObject*>::Iterator Remove objects that satisfy (m_removed && m_known_by_count==0)
i = m_active_objects.getIterator(); */
i.atEnd()==false; i++)
{ {
u16 id = i.getNode()->getKey(); core::list<u16> objects_to_remove;
ServerActiveObject* obj = i.getNode()->getValue(); for(core::map<u16, ServerActiveObject*>::Iterator
// This shouldn't happen but check it i = m_active_objects.getIterator();
if(obj == NULL) i.atEnd()==false; i++)
{ {
dstream<<"WARNING: NULL object found in ServerEnvironment" u16 id = i.getNode()->getKey();
<<" while finding removed objects. id="<<id<<std::endl; 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 // Id to be removed from m_active_objects
objects_to_remove.push_back(id); objects_to_remove.push_back(id);
continue;
} }
// If not m_removed, don't remove. // Remove references from m_active_objects
if(obj->m_removed == false) for(core::list<u16>::Iterator i = objects_to_remove.begin();
continue; i != objects_to_remove.end(); i++)
// Delete static data from block
if(obj->m_static_exists)
{ {
MapBlock *block = m_map->getBlockNoCreateNoEx(obj->m_static_block); m_active_objects.remove(*i);
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);
} }
// 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(); const s16 to_active_max_blocks = 3;
const f32 to_static_max_f = (to_active_max_blocks+1)*MAP_BLOCKSIZE*BS;
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; Convert stored objects from blocks near the players to active.
// Loop through all nearby blocks */
for(s16 x=bpmin.X; x<=bpmax.X; x++) for(core::list<Player*>::Iterator i = m_players.begin();
for(s16 y=bpmin.Y; y<=bpmax.Y; y++) i != m_players.end(); i++)
for(s16 z=bpmin.Z; z<=bpmax.Z; z++)
{ {
v3s16 blockpos(x,y,z); Player *player = *i;
MapBlock *block = m_map->getBlockNoCreateNoEx(blockpos);
if(block==NULL) // Ignore disconnected players
if(player->peer_id == 0)
continue; continue;
// Ignore if no stored objects (to not set changed flag)
if(block->m_static_objects.m_stored.size() == 0) v3f playerpos = player->getPosition();
continue;
// This will contain the leftovers of the stored list v3s16 blockpos0 = getNodeBlockPos(floatToInt(playerpos, BS));
core::list<StaticObject> new_stored; v3s16 bpmin = blockpos0 - v3s16(1,1,1)*to_active_max_blocks;
// Loop through stored static objects v3s16 bpmax = blockpos0 + v3s16(1,1,1)*to_active_max_blocks;
for(core::list<StaticObject>::Iterator // Loop through all nearby blocks
i = block->m_static_objects.m_stored.begin(); for(s16 x=bpmin.X; x<=bpmax.X; x++)
i != block->m_static_objects.m_stored.end(); i++) 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 " v3s16 blockpos(x,y,z);
<<"static data"<<std::endl;*/ MapBlock *block = m_map->getBlockNoCreateNoEx(blockpos);
StaticObject &s_obj = *i; if(block==NULL)
// 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; continue;
} // Ignore if no stored objects (to not set changed flag)
// This will also add the object to the active static list if(block->m_static_objects.m_stored.size() == 0)
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)
continue; continue;
// This will contain the leftovers of the stored list
v3f playerpos = player->getPosition(); core::list<StaticObject> new_stored;
f32 d = playerpos.getDistanceFrom(objectpos); // Loop through stored static objects
if(d < to_static_max_f) 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; /*dstream<<"INFO: Server: Creating an active object from "
break; <<"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);
} }
} // Clear stored list
block->m_static_objects.m_stored.clear();
if(close_to_player) // Add leftover stuff to stored list
continue; for(core::list<StaticObject>::Iterator
i = new_stored.begin();
/* i != new_stored.end(); i++)
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); StaticObject &s_obj = *i;
oldblock = block; 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(); 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 "player.h"
#include "map.h" #include "map.h"
#include <ostream> #include <ostream>
#include "utility.h"
class Environment class Environment
{ {
@ -154,6 +155,7 @@ private:
Queue<ActiveObjectMessage> m_active_object_messages; Queue<ActiveObjectMessage> m_active_object_messages;
float m_random_spawn_timer; float m_random_spawn_timer;
float m_send_recommended_timer; float m_send_recommended_timer;
IntervalLimiter m_object_management_interval;
}; };
#ifndef SERVER #ifndef SERVER