From c57637b4c39319e0c0d5d80d0ae2884aec66d691 Mon Sep 17 00:00:00 2001 From: Perttu Ahola Date: Mon, 21 Feb 2011 00:45:14 +0200 Subject: Temporary commit; lots of test code and stuff --- src/environment.cpp | 843 ++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 648 insertions(+), 195 deletions(-) (limited to 'src/environment.cpp') diff --git a/src/environment.cpp b/src/environment.cpp index 07437ec40..5e16602e0 100644 --- a/src/environment.cpp +++ b/src/environment.cpp @@ -20,11 +20,9 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "environment.h" #include "filesys.h" -Environment::Environment(Map *map, std::ostream &dout): - m_dout(dout) +Environment::Environment() { - m_map = map; - m_daynight_ratio = 0.2; + m_daynight_ratio = 0.5; } Environment::~Environment() @@ -35,183 +33,16 @@ Environment::~Environment() { delete (*i); } - - // The map is removed by the SceneManager - m_map->drop(); - //delete m_map; -} - -void Environment::step(float dtime) -{ - DSTACK(__FUNCTION_NAME); - /* - Run Map's timers - */ - //TimeTaker maptimerupdatetimer("m_map->timerUpdate()", g_device); - // 0ms - m_map->timerUpdate(dtime); - //maptimerupdatetimer.stop(); - - /* - Get the highest speed some player is going - */ - //TimeTaker playerspeed("playerspeed", g_device); - // 0ms - f32 maximum_player_speed = 0.001; // just some small value - for(core::list::Iterator i = m_players.begin(); - i != m_players.end(); i++) - { - f32 speed = (*i)->getSpeed().getLength(); - if(speed > maximum_player_speed) - maximum_player_speed = speed; - } - //playerspeed.stop(); - - /* - Maximum position increment - */ - //f32 position_max_increment = 0.05*BS; - f32 position_max_increment = 0.1*BS; - - // Maximum time increment (for collision detection etc) - // time = distance / speed - f32 dtime_max_increment = position_max_increment / maximum_player_speed; - // Maximum time increment is 10ms or lower - if(dtime_max_increment > 0.01) - dtime_max_increment = 0.01; - - //TimeTaker playerupdate("playerupdate", g_device); - - /* - Stuff that has a maximum time increment - */ - // Don't allow overly huge dtime - if(dtime > 0.5) - dtime = 0.5; - - u32 loopcount = 0; - do - { - loopcount++; - - f32 dtime_part; - if(dtime > dtime_max_increment) - dtime_part = dtime_max_increment; - else - dtime_part = dtime; - dtime -= dtime_part; - - /* - Handle players - */ - for(core::list::Iterator i = m_players.begin(); - i != m_players.end(); i++) - { - Player *player = *i; - - v3f playerpos = player->getPosition(); - - // Apply physics to local player - bool free_move = g_settings.getBool("free_move"); - if(player->isLocal() && free_move == false) - { - // Apply gravity to local player - v3f speed = player->getSpeed(); - if(player->swimming_up == false) - speed.Y -= 9.81 * BS * dtime_part * 2; - - /* - Apply water resistance - */ - if(player->in_water_stable || player->in_water) - { - f32 max_down = 2.0*BS; - if(speed.Y < -max_down) speed.Y = -max_down; - - f32 max = 2.5*BS; - if(speed.getLength() > max) - { - speed = speed / speed.getLength() * max; - } - } - - player->setSpeed(speed); - } - - /* - Move the player. - For local player, this also calculates collision detection. - */ - player->move(dtime_part, *m_map, position_max_increment); - - /* - Update lighting on remote players on client - */ - u8 light = LIGHT_MAX; - try{ - // Get node at feet - v3s16 p = floatToInt(playerpos + v3f(0,BS/4,0)); - MapNode n = m_map->getNode(p); - light = n.getLightBlend(m_daynight_ratio); - } - catch(InvalidPositionException &e) {} - player->updateLight(light); - - /* - Add footsteps to grass - */ - if(g_settings.getBool("footprints")) - { - // Get node that is at BS/4 under player - v3s16 bottompos = floatToInt(playerpos + v3f(0,-BS/4,0)); - try{ - MapNode n = m_map->getNode(bottompos); - if(n.d == CONTENT_GRASS) - { - n.d = CONTENT_GRASS_FOOTSTEPS; - m_map->setNode(bottompos, n); -#ifndef SERVER - // Update mesh on client - if(m_map->mapType() == MAPTYPE_CLIENT) - { - v3s16 p_blocks = getNodeBlockPos(bottompos); - MapBlock *b = m_map->getBlockNoCreate(p_blocks); - b->updateMesh(m_daynight_ratio); - } -#endif - } - } - catch(InvalidPositionException &e) - { - } - } - } - } - while(dtime > 0.001); - - //std::cout<<"Looped "<isLocal() == true && getLocalPlayer() != NULL)); -#endif // If peer id is non-zero, it has to be unique. if(player->peer_id != 0) assert(getPlayer(player->peer_id) == NULL); @@ -240,20 +71,6 @@ re_search: } } -#ifndef SERVER -LocalPlayer * Environment::getLocalPlayer() -{ - for(core::list::Iterator i = m_players.begin(); - i != m_players.end(); i++) - { - Player *player = *i; - if(player->isLocal()) - return (LocalPlayer*)player; - } - return NULL; -} -#endif - Player * Environment::getPlayer(u16 peer_id) { for(core::list::Iterator i = m_players.begin(); @@ -315,7 +132,38 @@ void Environment::printPlayers(std::ostream &o) } } -void Environment::serializePlayers(const std::string &savedir) +void Environment::setDayNightRatio(u32 r) +{ + m_daynight_ratio = r; +} + +u32 Environment::getDayNightRatio() +{ + return m_daynight_ratio; +} + +/* + ServerEnvironment +*/ + +ServerEnvironment::ServerEnvironment(ServerMap *map): + m_map(map), + m_random_spawn_timer(0) +{ + /* + TEST CODE + */ + TestSAO *obj = new TestSAO(0, v3f(0, BS*5, 0)); + addActiveObject(obj); +} + +ServerEnvironment::~ServerEnvironment() +{ + // Drop/delete map + m_map->drop(); +} + +void ServerEnvironment::serializePlayers(const std::string &savedir) { std::string players_path = savedir + "/players"; fs::CreateDir(players_path); @@ -430,7 +278,7 @@ void Environment::serializePlayers(const std::string &savedir) //dstream<<"Saved "<timerUpdate()", g_device); + m_map->timerUpdate(dtime); + } + + /* + Handle players + */ + for(core::list::Iterator i = m_players.begin(); + i != m_players.end(); i++) + { + Player *player = *i; + v3f playerpos = player->getPosition(); + + // Move + player->move(dtime, *m_map, 100*BS); + + /* + Add footsteps to grass + */ + if(footprints) + { + // Get node that is at BS/4 under player + v3s16 bottompos = floatToInt(playerpos + v3f(0,-BS/4,0), BS); + try{ + MapNode n = m_map->getNode(bottompos); + if(n.d == CONTENT_GRASS) + { + n.d = CONTENT_GRASS_FOOTSTEPS; + m_map->setNode(bottompos, n); + } + } + catch(InvalidPositionException &e) + { + } + } + } + + /* + Step active objects + */ + for(core::map::Iterator + i = m_active_objects.getIterator(); + i.atEnd()==false; i++) + { + ServerActiveObject* obj = i.getNode()->getValue(); + // Step object, putting messages directly to the queue + obj->step(dtime, m_active_object_messages); + } + + /* + Remove (m_removed && m_known_by_count==0) objects + */ + { + core::list objects_to_remove; + for(core::map::Iterator + i = m_active_objects.getIterator(); + i.atEnd()==false; i++) + { + 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="<m_removed == false) + 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::Iterator i = objects_to_remove.begin(); + i != objects_to_remove.end(); i++) + { + m_active_objects.remove(*i); + } + } + + /* + TEST CODE + */ + m_random_spawn_timer -= dtime; + if(m_random_spawn_timer < 0) + { + m_random_spawn_timer += 0.1; + TestSAO *obj = new TestSAO(0, + v3f(myrand_range(-2*BS,2*BS), BS*5, myrand_range(-2*BS,2*BS))); + addActiveObject(obj); + } +} + +ServerActiveObject* ServerEnvironment::getActiveObject(u16 id) +{ + core::map::Node *n; + n = m_active_objects.find(id); + if(n == NULL) + return NULL; + return n->getValue(); +} + +bool isFreeServerActiveObjectId(u16 id, + core::map &objects) +{ + if(id == 0) + return false; + + for(core::map::Iterator + i = objects.getIterator(); + i.atEnd()==false; i++) + { + if(i.getNode()->getKey() == id) + return false; + } + return true; +} + +u16 getFreeServerActiveObjectId( + core::map &objects) +{ + u16 new_id = 1; + for(;;) + { + if(isFreeServerActiveObjectId(new_id, objects)) + return new_id; + + if(new_id == 65535) + return 0; + + new_id++; + } +} + +u16 ServerEnvironment::addActiveObject(ServerActiveObject *object) +{ + assert(object); + if(object->getId() == 0) + { + u16 new_id = getFreeServerActiveObjectId(m_active_objects); + if(new_id == 0) + { + dstream<<"WARNING: ServerEnvironment::addActiveObject(): " + <<"no free ids available"<setId(new_id); + } + if(isFreeServerActiveObjectId(object->getId(), m_active_objects) == false) + { + dstream<<"WARNING: ServerEnvironment::addActiveObject(): " + <<"id is not free ("<getId()<<")"<getId(), object); + return object->getId(); +} + +/* + Finds out what new objects have been added to + inside a radius around a position +*/ +void ServerEnvironment::getAddedActiveObjects(v3s16 pos, s16 radius, + core::map ¤t_objects, + core::map &added_objects) +{ + v3f pos_f = intToFloat(pos, BS); + f32 radius_f = radius * BS; + /* + Go through the object list, + - discard m_removed objects, + - discard objects that are too far away, + - discard objects that are found in current_objects. + - add remaining objects to added_objects + */ + for(core::map::Iterator + i = m_active_objects.getIterator(); + i.atEnd()==false; i++) + { + u16 id = i.getNode()->getKey(); + // Get object + ServerActiveObject *object = i.getNode()->getValue(); + if(object == NULL) + continue; + // Discard if removed + if(object->m_removed) + continue; + // Discard if too far + f32 distance_f = object->getBasePosition().getDistanceFrom(pos_f); + if(distance_f > radius_f) + continue; + // Discard if already on current_objects + core::map::Node *n; + n = current_objects.find(id); + if(n != NULL) + continue; + // Add to added_objects + added_objects.insert(id, false); + } +} + +/* + Finds out what objects have been removed from + inside a radius around a position +*/ +void ServerEnvironment::getRemovedActiveObjects(v3s16 pos, s16 radius, + core::map ¤t_objects, + core::map &removed_objects) +{ + v3f pos_f = intToFloat(pos, BS); + f32 radius_f = radius * BS; + /* + Go through current_objects; object is removed if: + - object is not found in m_active_objects (this is actually an + error condition; objects should be set m_removed=true and removed + only after all clients have been informed about removal), or + - object has m_removed=true, or + - object is too far away + */ + for(core::map::Iterator + i = current_objects.getIterator(); + i.atEnd()==false; i++) + { + u16 id = i.getNode()->getKey(); + ServerActiveObject *object = getActiveObject(id); + if(object == NULL) + { + dstream<<"WARNING: ServerEnvironment::getRemovedActiveObjects():" + <<" object in current_objects is NULL"<m_removed == false) + { + f32 distance_f = object->getBasePosition().getDistanceFrom(pos_f); + /*dstream<<"removed == false" + <<"distance_f = "<timerUpdate()", g_device); + m_map->timerUpdate(dtime); + } + + /* + Get the speed the player is going + */ + f32 player_speed = 0.001; // just some small value + LocalPlayer *lplayer = getLocalPlayer(); + if(lplayer) + player_speed = lplayer->getSpeed().getLength(); + + /* + Maximum position increment + */ + //f32 position_max_increment = 0.05*BS; + f32 position_max_increment = 0.1*BS; + + // Maximum time increment (for collision detection etc) + // time = distance / speed + f32 dtime_max_increment = position_max_increment / player_speed; + + // Maximum time increment is 10ms or lower + if(dtime_max_increment > 0.01) + dtime_max_increment = 0.01; + + // Don't allow overly huge dtime + if(dtime > 0.5) + dtime = 0.5; + + f32 dtime_downcount = dtime; + + /* + Stuff that has a maximum time increment + */ + + u32 loopcount = 0; + do + { + loopcount++; + + f32 dtime_part; + if(dtime_downcount > dtime_max_increment) + dtime_part = dtime_max_increment; + else + dtime_part = dtime; + dtime_downcount -= dtime_part; + + /* + Handle local player + */ + + { + Player *player = getLocalPlayer(); + + v3f playerpos = player->getPosition(); + + // Apply physics + if(free_move == false) + { + // Gravity + v3f speed = player->getSpeed(); + if(player->swimming_up == false) + speed.Y -= 9.81 * BS * dtime_part * 2; + + // Water resistance + if(player->in_water_stable || player->in_water) + { + f32 max_down = 2.0*BS; + if(speed.Y < -max_down) speed.Y = -max_down; + + f32 max = 2.5*BS; + if(speed.getLength() > max) + { + speed = speed / speed.getLength() * max; + } + } + + player->setSpeed(speed); + } + + /* + Move the player. + This also does collision detection. + */ + player->move(dtime_part, *m_map, position_max_increment); + } + } + while(dtime_downcount > 0.001); + + //std::cout<<"Looped "<::Iterator i = m_players.begin(); + i != m_players.end(); i++) + { + Player *player = *i; + v3f playerpos = player->getPosition(); + + /* + Handle non-local players + */ + if(player->isLocal() == false) + { + // Move + player->move(dtime, *m_map, 100*BS); + + // Update lighting on remote players on client + u8 light = LIGHT_MAX; + try{ + // Get node at head + v3s16 p = floatToInt(playerpos + v3f(0,BS+BS/2,0), BS); + MapNode n = m_map->getNode(p); + light = n.getLightBlend(m_daynight_ratio); + } + catch(InvalidPositionException &e) {} + player->updateLight(light); + } + + /* + Add footsteps to grass + */ + if(footprints) + { + // Get node that is at BS/4 under player + v3s16 bottompos = floatToInt(playerpos + v3f(0,-BS/4,0), BS); + try{ + MapNode n = m_map->getNode(bottompos); + if(n.d == CONTENT_GRASS) + { + n.d = CONTENT_GRASS_FOOTSTEPS; + m_map->setNode(bottompos, n); + // Update mesh on client + if(m_map->mapType() == MAPTYPE_CLIENT) + { + v3s16 p_blocks = getNodeBlockPos(bottompos); + MapBlock *b = m_map->getBlockNoCreate(p_blocks); + b->updateMesh(m_daynight_ratio); + } + } + } + catch(InvalidPositionException &e) + { + } + } + } + + /* + Step active objects + */ + for(core::map::Iterator + i = m_active_objects.getIterator(); + i.atEnd()==false; i++) + { + ClientActiveObject* obj = i.getNode()->getValue(); + // Step object + obj->step(dtime); + } +} + +void ClientEnvironment::updateMeshes(v3s16 blockpos) { m_map->updateMeshes(blockpos, m_daynight_ratio); } -void Environment::expireMeshes(bool only_daynight_diffed) +void ClientEnvironment::expireMeshes(bool only_daynight_diffed) { m_map->expireMeshes(only_daynight_diffed); } -#endif -void Environment::setDayNightRatio(u32 r) +ClientActiveObject* ClientEnvironment::getActiveObject(u16 id) { - m_daynight_ratio = r; + core::map::Node *n; + n = m_active_objects.find(id); + if(n == NULL) + return NULL; + return n->getValue(); } -u32 Environment::getDayNightRatio() +bool isFreeClientActiveObjectId(u16 id, + core::map &objects) { - return m_daynight_ratio; + if(id == 0) + return false; + + for(core::map::Iterator + i = objects.getIterator(); + i.atEnd()==false; i++) + { + if(i.getNode()->getKey() == id) + return false; + } + return true; +} + +u16 getFreeClientActiveObjectId( + core::map &objects) +{ + u16 new_id = 1; + for(;;) + { + if(isFreeClientActiveObjectId(new_id, objects)) + return new_id; + + if(new_id == 65535) + return 0; + + new_id++; + } } +u16 ClientEnvironment::addActiveObject(ClientActiveObject *object) +{ + assert(object); + if(object->getId() == 0) + { + u16 new_id = getFreeClientActiveObjectId(m_active_objects); + if(new_id == 0) + { + dstream<<"WARNING: ClientEnvironment::addActiveObject(): " + <<"no free ids available"<setId(new_id); + } + if(isFreeClientActiveObjectId(object->getId(), m_active_objects) == false) + { + dstream<<"WARNING: ClientEnvironment::addActiveObject(): " + <<"id is not free ("<getId()<<")"<getId(), object); + object->addToScene(m_smgr); + return object->getId(); +} + +void ClientEnvironment::addActiveObject(u16 id, u8 type) +{ + ClientActiveObject* obj = ClientActiveObject::create(type); + if(obj == NULL) + { + dstream<<"WARNING: ClientEnvironment::addActiveObject(): " + <<"id="<setId(id); + + addActiveObject(obj); +} + +void ClientEnvironment::removeActiveObject(u16 id) +{ + dstream<<"ClientEnvironment::removeActiveObject(): " + <<"id="<removeFromScene(); + delete obj; + m_active_objects.remove(id); +} + +void ClientEnvironment::processActiveObjectMessage(u16 id, + const std::string &data) +{ + ClientActiveObject* obj = getActiveObject(id); + if(obj == NULL) + { + dstream<<"WARNING: ClientEnvironment::processActiveObjectMessage():" + <<" got message for id="<processMessage(data); +} + +#endif // #ifndef SERVER + + -- cgit v1.2.3