/* Minetest-c55 Copyright (C) 2010 celeron55, Perttu Ahola This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "environment.h" #include "filesys.h" Environment::Environment(Map *map, std::ostream &dout): m_dout(dout) { m_map = map; m_daynight_ratio = 0.2; } Environment::~Environment() { // Deallocate players for(core::list::Iterator i = m_players.begin(); i != m_players.end(); i++) { 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 clien[Desktop Entry] Name=Minetest GenericName=Minetest Comment=Multiplayer infinite-world block sandbox Comment[de]=Mehrspieler-Sandkastenspiel mit unendlichen Blockwelten Comment[es]=Juego sandbox multijugador con mundos infinitos Comment[fr]=Jeu multijoueurs de type bac à sable avec des mondes infinis Comment[ja]=マルチプレイに対応した、無限の世界のブロック型サンドボックスゲームです Comment[ru]=Игра-песочница с безграничным миром, состоящим из блоков Comment[tr]=Tek-Çok oyuncuyla küplerden sonsuz dünyalar inşa et Exec=minetest Icon=minetest Terminal=false PrefersNonDefaultGPU=true Type=Application Categories=Game;Simulation; StartupNotify=false Keywords=sandbox;world;mining;crafting;blocks;nodes;multiplayer;roleplaying; yer = *i; if(player->peer_id == peer_id) return player; } return NULL; } Player * Environment::getPlayer(const char *name) { for(core::list::Iterator i = m_players.begin(); i != m_players.end(); i++) { Player *player = *i; if(strcmp(player->getName(), name) == 0) return player; } return NULL; } core::list Environment::getPlayers() { return m_players; } core::list Environment::getPlayers(bool ignore_disconnected) { core::list newlist; for(core::list::Iterator i = m_players.begin(); i != m_players.end(); i++) { Player *player = *i; if(ignore_disconnected) { // Ignore disconnected players if(player->peer_id == 0) continue; } newlist.push_back(player); } return newlist; } void Environment::printPlayers(std::ostream &o) { o<<"Players in environment:"<::Iterator i = m_players.begin(); i != m_players.end(); i++) { Player *player = *i; o<<"Player peer_id="<peer_id< saved_players; std::vector player_files = fs::GetDirListing(players_path); for(u32 i=0; iserialize(os); saved_players.insert(player, true); } } for(core::list::Iterator i = m_players.begin(); i != m_players.end(); i++) { Player *player = *i; if(saved_players.find(player) != NULL) { /*dstream<<"Player "<getName() <<" was already saved."<getName(); // Don't save unnamed player if(playername == "") { //dstream<<"Not saving unnamed player."<getName()<<" to " <serialize(os); saved_players.insert(player, true); } } //dstream<<"Saved "< saved_players; std::vector player_files = fs::GetDirListing(players_path); for(u32 i=0; ideSerialize(is); } if(newplayer) addPlayer(player); } } #ifndef SERVER void Environment::updateMeshes(v3s16 blockpos) { m_map->updateMeshes(blockpos, m_daynight_ratio); } void Environment::expireMeshes(bool only_daynight_diffed) { m_map->expireMeshes(only_daynight_diffed); } #endif void Environment::setDayNightRatio(u32 r) { m_daynight_ratio = r; } u32 Environment::getDayNightRatio() { return m_daynight_ratio; }