From d07000ed1dc78554b64e3d0ac8efdaead1cf68bb Mon Sep 17 00:00:00 2001 From: PilzAdam Date: Wed, 1 May 2013 15:47:14 +0200 Subject: Move sfan5 to core devs --- src/guiMainMenu.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/guiMainMenu.cpp b/src/guiMainMenu.cpp index 06e7cdff7..d3e3c007a 100644 --- a/src/guiMainMenu.cpp +++ b/src/guiMainMenu.cpp @@ -53,12 +53,12 @@ const wchar_t *contrib_core_strs[] = { L"Ilya Zhuravlev (thexyz) ", L"Lisa Milne (darkrose) ", L"Maciej Kasatkin (RealBadAngel) ", - L"proller " + L"proller ", + L"sfan5 " }; const wchar_t *contrib_active_strs[] = { L"kahrl ", - L"sfan5 ", L"sapier ", L"Vanessa Ezekowitz (VanessaE) ", L"Jurgen Doser (doserj) ", -- cgit v1.2.3 From b28734c82cdb88228a12a3cac90f51ab9384b653 Mon Sep 17 00:00:00 2001 From: PilzAdam Date: Wed, 1 May 2013 16:00:58 +0200 Subject: Fix minetest.features --- builtin/features.lua | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/builtin/features.lua b/builtin/features.lua index 0eef2519d..9d00cfd99 100644 --- a/builtin/features.lua +++ b/builtin/features.lua @@ -1,11 +1,11 @@ -- Minetest: builtin/features.lua minetest.features = { - "glasslike_framed" = true, - "nodebox_as_selectionbox" = true, - "chat_send_player_param3" = true, - "get_all_craft_recipes_works" = true, - "use_texture_alpha" = true, + glasslike_framed = true, + nodebox_as_selectionbox = true, + chat_send_player_param3 = true, + get_all_craft_recipes_works = true, + use_texture_alpha = true, } function minetest.has_feature(arg) -- cgit v1.2.3 From 084be3599a5ef0acba7c341bfd14a4e9801423a2 Mon Sep 17 00:00:00 2001 From: Perttu Ahola Date: Fri, 15 Feb 2013 21:13:53 +0200 Subject: Get menu background image from selected game --- src/guiMainMenu.cpp | 47 +++++++++++- src/guiMainMenu.h | 2 + src/main.cpp | 215 ++++++++++++++++++++++------------------------------ src/subgame.cpp | 14 +++- src/subgame.h | 13 +++- src/tile.cpp | 2 +- src/tile.h | 11 +++ 7 files changed, 170 insertions(+), 134 deletions(-) diff --git a/src/guiMainMenu.cpp b/src/guiMainMenu.cpp index d3e3c007a..07efbb62f 100644 --- a/src/guiMainMenu.cpp +++ b/src/guiMainMenu.cpp @@ -162,6 +162,8 @@ enum GUI_ID_SERVERLIST_TOGGLE, GUI_ID_SERVERLIST_DELETE, GUI_ID_SERVERLIST_TITLE, + GUI_ID_GAME_BUTTON_FIRST = 130, + GUI_ID_GAME_BUTTON_MAX = 150, }; enum @@ -255,8 +257,12 @@ void GUIMainMenu::regenerateGui(v2u32 screensize) { core::rect rect(0, 0, size.X, 40); rect += v2s32(4, 0); - Environment->addStaticText(narrow_to_wide( - "Minetest " VERSION_STRING).c_str(), + std::string t = "Minetest " VERSION_STRING; + if(m_data->selected_game != ""){ + t += "/"; + t += m_data->selected_game; + } + Environment->addStaticText(narrow_to_wide(t).c_str(), rect, false, true, this, -1); } @@ -900,6 +906,27 @@ void GUIMainMenu::regenerateGui(v2u32 screensize) } } + /* Add game selection buttons */ + + video::IVideoDriver* driver = Environment->getVideoDriver(); + for(size_t i=0; igames.size(); i++){ + const SubgameSpec *spec = &m_data->games[i]; + v2s32 p(8 + i*(48+8), screensize.Y - (48+8)); + core::rect rect(0, 0, 48, 48); + rect += p; + video::ITexture *bgtexture = NULL; + if(spec->menuicon_path != "") + bgtexture = driver->getTexture(spec->menuicon_path.c_str()); + gui::IGUIButton *b = Environment->addButton(rect, this, + GUI_ID_GAME_BUTTON_FIRST+i, narrow_to_wide(wrap_rows(spec->id, 4)).c_str()); + if(bgtexture){ + b->setImage(bgtexture); + b->setText(L""); + b->setDrawBorder(false); + b->setUseAlphaChannel(true); + } + } + m_is_regenerating = false; } @@ -909,7 +936,9 @@ void GUIMainMenu::drawMenu() if (!skin) return; video::IVideoDriver* driver = Environment->getVideoDriver(); - + + /* Draw menu background */ + /*video::SColor bgcolor(140,0,0,0); driver->draw2DRectangle(bgcolor, AbsoluteRect, &AbsoluteClippingRect);*/ @@ -976,6 +1005,8 @@ void GUIMainMenu::drawMenu() } } + /* Draw UI elements */ + gui::IGUIElement::draw(); } @@ -1221,7 +1252,7 @@ bool GUIMainMenu::OnEvent(const SEvent& event) return true; } case GUI_ID_CREATE_WORLD_BUTTON: { - std::vector games = getAvailableGames(); + const std::vector &games = m_data->games; if(games.size() == 0){ wchar_t* text = wgettext("Cannot create world: No games found"); GUIMessageMenu *menu = new GUIMessageMenu(env, parent, @@ -1308,6 +1339,14 @@ bool GUIMainMenu::OnEvent(const SEvent& event) } #endif } + /* Game buttons */ + int eid = event.GUIEvent.Caller->getID(); + if(eid >= GUI_ID_GAME_BUTTON_FIRST && + eid <= GUI_ID_GAME_BUTTON_MAX){ + m_data->selected_game = + m_data->games[eid - GUI_ID_GAME_BUTTON_FIRST].id; + regenerateGui(m_screensize_old); + } } if(event.GUIEvent.EventType==gui::EGET_EDITBOX_ENTER) { diff --git a/src/guiMainMenu.h b/src/guiMainMenu.h index a594ccd41..b0c9ff24b 100644 --- a/src/guiMainMenu.h +++ b/src/guiMainMenu.h @@ -39,6 +39,7 @@ struct MainMenuData // These are in the native format of the gui elements // Generic int selected_tab; + std::string selected_game; // Client options std::string servername; std::string serverdescription; @@ -78,6 +79,7 @@ struct MainMenuData MainMenuData(): // Generic selected_tab(0), + selected_game("minetest"), // Client opts fancy_trees(false), smooth_lighting(false), diff --git a/src/main.cpp b/src/main.cpp index eef65cdb2..67aa82bc4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -612,122 +612,65 @@ private: bool rightreleased; }; -//Draw the tiled menu background -void drawMenuBackground(video::IVideoDriver* driver) { - core::dimension2d screensize = driver->getScreenSize(); - - std::string path = getTexturePath("menubg.png"); - if (path[0]) { - static const video::ITexture *bgtexture = - driver->getTexture(path.c_str()); +void drawMenuBackground(video::IVideoDriver* driver, const SubgameSpec *spec) +{ + v2u32 screensize = driver->getScreenSize(); - if (bgtexture) { - s32 scaledsize = 128; - - // The important difference between destsize and screensize is - // that destsize is rounded to whole scaled pixels. - // These formulas use component-wise multiplication and division of v2u32. - v2u32 texturesize = bgtexture->getSize(); - v2u32 sourcesize = texturesize * screensize / scaledsize + v2u32(1,1); - v2u32 destsize = scaledsize * sourcesize / texturesize; - - // Default texture wrapping mode in Irrlicht is ETC_REPEAT. - driver->draw2DImage(bgtexture, - core::rect(0, 0, destsize.X, destsize.Y), - core::rect(0, 0, sourcesize.X, sourcesize.Y), - NULL, NULL, true); - } + /* Figure out background texture */ + video::ITexture *texture = NULL; + if(spec && spec->menubackground_path != ""){ + texture = driver->getTexture(spec->menubackground_path.c_str()); } -} -//Draw the footer at the bottom of the window -void drawMenuFooter(video::IVideoDriver* driver, bool clouds) { - core::dimension2d screensize = driver->getScreenSize(); - std::string path = getTexturePath(clouds ? - "menufooter_clouds.png" : "menufooter.png"); - if (path[0]) { - static const video::ITexture *footertexture = - driver->getTexture(path.c_str()); - - if (footertexture) { - f32 mult = (((f32)screensize.Width)) / - ((f32)footertexture->getOriginalSize().Width); - - v2s32 footersize(((f32)footertexture->getOriginalSize().Width) * mult, - ((f32)footertexture->getOriginalSize().Height) * mult); - - // Don't draw the footer if there isn't enough room - s32 free_space = (((s32)screensize.Height)-320)/2; - if (free_space > footersize.Y) { - core::rect rect(0,0,footersize.X,footersize.Y); - rect += v2s32(screensize.Width/2,screensize.Height-footersize.Y); - rect -= v2s32(footersize.X/2, 0); - - driver->draw2DImage(footertexture, rect, - core::rect(core::position2d(0,0), - core::dimension2di(footertexture->getSize())), - NULL, NULL, true); - } - } + /* If no texture, draw background of solid color */ + if(!texture){ + video::SColor color(255,80,58,37); + core::rect rect(0, 0, screensize.X, screensize.Y); + driver->draw2DRectangle(color, rect, NULL); + return; } -} - -// Draw the Header over the main menu -void drawMenuHeader(video::IVideoDriver* driver) { - core::dimension2d screensize = driver->getScreenSize(); - - std::string path = getTexturePath("menuheader.png"); - if (path[0]) { - static const video::ITexture *splashtexture = - driver->getTexture(path.c_str()); - - if(splashtexture) { - f32 mult = (((f32)screensize.Width / 2)) / - ((f32)splashtexture->getOriginalSize().Width); - v2s32 splashsize(((f32)splashtexture->getOriginalSize().Width) * mult, - ((f32)splashtexture->getOriginalSize().Height) * mult); - - // Don't draw the header is there isn't enough room - s32 free_space = (((s32)screensize.Height)-320)/2; - if (free_space > splashsize.Y) { - core::rect splashrect(0, 0, splashsize.X, splashsize.Y); - splashrect += v2s32((screensize.Width/2)-(splashsize.X/2), - ((free_space/2)-splashsize.Y/2)+10); + /* Draw background texture */ + v2u32 sourcesize = texture->getSize(); + driver->draw2DImage(texture, + core::rect(0, 0, screensize.X, screensize.Y), + core::rect(0, 0, sourcesize.X, sourcesize.Y), + NULL, NULL, true); +} - video::SColor bgcolor(255,50,50,50); +void drawMenuOverlay(video::IVideoDriver* driver, const SubgameSpec *spec) +{ + v2u32 screensize = driver->getScreenSize(); - driver->draw2DImage(splashtexture, splashrect, - core::rect(core::position2d(0,0), - core::dimension2di(splashtexture->getSize())), - NULL, NULL, true); - } - } + /* Figure out overlay texture */ + video::ITexture *texture = NULL; + if(spec && spec->menuoverlay_path != ""){ + texture = driver->getTexture(spec->menuoverlay_path.c_str()); } -} -// Draw the Splash over the clouds and under the main menu -void drawMenuSplash(video::IVideoDriver* driver) { - core::dimension2d screensize = driver->getScreenSize(); - std::string path = getTexturePath("menusplash.png"); - if (path[0]) { - static const video::ITexture *splashtexture = - driver->getTexture(path.c_str()); + /* If no texture, draw nothing */ + if(!texture) + return; - if(splashtexture) { - core::rect splashrect(0, 0, screensize.Width, screensize.Height); - - video::SColor bgcolor(255,50,50,50); + /* Draw overlay texture */ + v2u32 sourcesize = texture->getSize(); + driver->draw2DImage(texture, + core::rect(0, 0, screensize.X, screensize.Y), + core::rect(0, 0, sourcesize.X, sourcesize.Y), + NULL, NULL, true); +} - driver->draw2DImage(splashtexture, splashrect, - core::rect(core::position2d(0,0), - core::dimension2di(splashtexture->getSize())), - NULL, NULL, true); +static const SubgameSpec* getMenuGame(const MainMenuData &menudata) +{ + for(size_t i=0; igetS32("selected_mainmenu_tab"); if(g_settings->exists("selected_serverlist")) menudata.selected_serverlist = g_settings->getS32("selected_serverlist"); + if(g_settings->exists("selected_mainmenu_game")) + menudata.selected_game = g_settings->get("selected_mainmenu_game"); menudata.address = narrow_to_wide(address); menudata.name = narrow_to_wide(playername); menudata.port = narrow_to_wide(itos(port)); @@ -1611,6 +1556,14 @@ int main(int argc, char *argv[]) } // Copy worldspecs to menu menudata.worlds = worldspecs; + // Get game listing + menudata.games = getAvailableGames(); + // If selected game doesn't exist, take first from list + if(findSubgame(menudata.selected_game).id == "" && + !menudata.games.empty()){ + menudata.selected_game = menudata.games[0].id; + } + const SubgameSpec *menugame = getMenuGame(menudata); if(skip_main_menu == false) { @@ -1623,7 +1576,7 @@ int main(int argc, char *argv[]) break; driver->beginScene(true, true, video::SColor(255,128,128,128)); - drawMenuBackground(driver); + drawMenuBackground(driver, menugame); guienv->drawAll(); driver->endScene(); // On some computers framerate doesn't seem to be @@ -1637,21 +1590,17 @@ int main(int argc, char *argv[]) &g_menumgr, &menudata, g_gamecallback); menu->allowFocusRemoval(true); - // Clouds for the main menu - bool cloud_menu_background = false; - Clouds *clouds = NULL; - if (g_settings->getBool("menu_clouds")) { - cloud_menu_background = true; - clouds = new Clouds(smgr->getRootSceneNode(), - smgr, -1, rand(), 100); - clouds->update(v2f(0, 0), video::SColor(255,200,200,255)); - - // A camera to see the clouds - scene::ICameraSceneNode* camera; - camera = smgr->addCameraSceneNode(0, - v3f(0,0,0), v3f(0, 60, 100)); - camera->setFarValue(10000); - } + // Always create clouds because they may or may not be + // needed based on the game selected + Clouds *clouds = new Clouds(smgr->getRootSceneNode(), + smgr, -1, rand(), 100); + clouds->update(v2f(0, 0), video::SColor(255,200,200,255)); + + // A camera to see the clouds + scene::ICameraSceneNode* camera; + camera = smgr->addCameraSceneNode(0, + v3f(0,0,0), v3f(0, 60, 100)); + camera->setFarValue(10000); if(error_message != L"") { @@ -1675,6 +1624,24 @@ int main(int argc, char *argv[]) if(menu->getStatus() == true) break; + // Game can be selected in the menu + menugame = getMenuGame(menudata); + // Clouds for the main menu + bool cloud_menu_background = g_settings->getBool("menu_clouds"); + if(menugame){ + // If game has regular background and no overlay, don't use clouds + if(cloud_menu_background && + menugame->menuoverlay_path.empty() && + !menugame->menubackground_path.empty()){ + cloud_menu_background = false; + } + // If game game has overlay and no regular background, always draw clouds + else if(menugame->menubackground_path.empty() && + !menugame->menuoverlay_path.empty()){ + cloud_menu_background = true; + } + } + // Time calc for the clouds f32 dtime; // in seconds if (cloud_menu_background) { @@ -1694,12 +1661,9 @@ int main(int argc, char *argv[]) clouds->step(dtime*3); clouds->render(); smgr->drawAll(); - drawMenuSplash(driver); - drawMenuFooter(driver, true); - drawMenuHeader(driver); + drawMenuOverlay(driver, menugame); } else { - drawMenuBackground(driver); - drawMenuFooter(driver, false); + drawMenuBackground(driver, menugame); } guienv->drawAll(); @@ -1735,10 +1699,8 @@ int main(int argc, char *argv[]) infostream<<"Dropping main menu"<drop(); - if (cloud_menu_background) { - clouds->drop(); - smgr->clear(); - } + clouds->drop(); + smgr->clear(); } playername = wide_to_narrow(menudata.name); @@ -1755,6 +1717,7 @@ int main(int argc, char *argv[]) // Save settings g_settings->setS32("selected_mainmenu_tab", menudata.selected_tab); g_settings->setS32("selected_serverlist", menudata.selected_serverlist); + g_settings->set("selected_mainmenu_game", menudata.selected_game); g_settings->set("new_style_leaves", itos(menudata.fancy_trees)); g_settings->set("smooth_lighting", itos(menudata.smooth_lighting)); g_settings->set("enable_3d_clouds", itos(menudata.clouds_3d)); diff --git a/src/subgame.cpp b/src/subgame.cpp index 19ad4e636..a17b16234 100644 --- a/src/subgame.cpp +++ b/src/subgame.cpp @@ -22,6 +22,9 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "filesys.h" #include "settings.h" #include "log.h" +#ifndef SERVER +#include "tile.h" // getImagePath +#endif #include "util/string.h" bool getGameMinetestConfig(const std::string &game_path, Settings &conf) @@ -94,7 +97,16 @@ SubgameSpec findSubgame(const std::string &id) std::string game_name = getGameName(game_path); if(game_name == "") game_name = id; - return SubgameSpec(id, game_path, gamemod_path, mods_paths, game_name); + std::string menubackground_path; + std::string menuoverlay_path; + std::string menuicon_path; +#ifndef SERVER + menubackground_path = getImagePath(game_path + DIR_DELIM + "menu/background.png"); + menuoverlay_path = getImagePath(game_path + DIR_DELIM + "menu/overlay.png"); + menuicon_path = getImagePath(game_path + DIR_DELIM + "menu/icon.png"); +#endif + return SubgameSpec(id, game_path, gamemod_path, mods_paths, game_name, + menubackground_path, menuoverlay_path, menuicon_path); } SubgameSpec findWorldSubgame(const std::string &world_path) diff --git a/src/subgame.h b/src/subgame.h index b120b7542..2e16c2fec 100644 --- a/src/subgame.h +++ b/src/subgame.h @@ -35,17 +35,26 @@ struct SubgameSpec std::string gamemods_path; //path to mods of the game std::set addon_mods_paths; //paths to addon mods for this game std::string name; + std::string menubackground_path; + std::string menuoverlay_path; + std::string menuicon_path; SubgameSpec(const std::string &id_="", const std::string &path_="", const std::string &gamemods_path_="", const std::set &addon_mods_paths_=std::set(), - const std::string &name_=""): + const std::string &name_="", + const std::string &menubackground_path_="", + const std::string &menuoverlay_path_="", + const std::string &menuicon_path_=""): id(id_), path(path_), gamemods_path(gamemods_path_), addon_mods_paths(addon_mods_paths_), - name(name_) + name(name_), + menubackground_path(menubackground_path_), + menuoverlay_path(menuoverlay_path_), + menuicon_path(menuicon_path_) {} bool isValid() const diff --git a/src/tile.cpp b/src/tile.cpp index 39f47962e..5f25e123b 100644 --- a/src/tile.cpp +++ b/src/tile.cpp @@ -77,7 +77,7 @@ static bool replace_ext(std::string &path, const char *ext) If failed, return "". */ -static std::string getImagePath(std::string path) +std::string getImagePath(std::string path) { // A NULL-ended list of possible image extensions const char *extensions[] = { diff --git a/src/tile.h b/src/tile.h index ea5c4be54..531a93172 100644 --- a/src/tile.h +++ b/src/tile.h @@ -34,6 +34,17 @@ class IGameDef; tile.{h,cpp}: Texture handling stuff. */ +/* + Find out the full path of an image by trying different filename + extensions. + + If failed, return "". + + TODO: Should probably be moved out from here, because things needing + this function do not need anything else from this header +*/ +std::string getImagePath(std::string path); + /* Gets the path to a texture by first checking if the texture exists in texture_path and if not, using the data path. -- cgit v1.2.3 From 2708482f1bdb163d61193ebb976e9edc66449356 Mon Sep 17 00:00:00 2001 From: Perttu Ahola Date: Fri, 15 Feb 2013 22:06:38 +0200 Subject: Filter worlds by selected game --- src/guiMainMenu.cpp | 23 +++++++++++++++++------ src/guiMainMenu.h | 2 ++ 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/src/guiMainMenu.cpp b/src/guiMainMenu.cpp index 07efbb62f..2e7fb955d 100644 --- a/src/guiMainMenu.cpp +++ b/src/guiMainMenu.cpp @@ -348,11 +348,17 @@ void GUIMainMenu::regenerateGui(v2u32 screensize) gui::IGUIListBox *e = Environment->addListBox(rect, this, GUI_ID_WORLD_LISTBOX); e->setDrawBackground(true); - for(std::vector::const_iterator i = m_data->worlds.begin(); - i != m_data->worlds.end(); i++){ - e->addItem(narrow_to_wide(i->name+" ["+i->gameid+"]").c_str()); + m_world_indices.clear(); + for(size_t wi = 0; wi < m_data->worlds.size(); wi++){ + const WorldSpec &spec = m_data->worlds[wi]; + if(spec.gameid == m_data->selected_game){ + //e->addItem(narrow_to_wide(spec.name+" ["+spec.gameid+"]").c_str()); + e->addItem(narrow_to_wide(spec.name).c_str()); + m_world_indices.push_back(wi); + if(m_data->selected_world == (int)wi) + e->setSelected(m_world_indices.size()-1); + } } - e->setSelected(m_data->selected_world); Environment->setFocus(e); } // Delete world button @@ -1131,8 +1137,13 @@ void GUIMainMenu::readInput(MainMenuData *dst) { gui::IGUIElement *e = getElementFromId(GUI_ID_WORLD_LISTBOX); - if(e != NULL && e->getType() == gui::EGUIET_LIST_BOX) - dst->selected_world = ((gui::IGUIListBox*)e)->getSelected(); + if(e != NULL && e->getType() == gui::EGUIET_LIST_BOX){ + int list_i = ((gui::IGUIListBox*)e)->getSelected(); + if(list_i == -1) + dst->selected_world = -1; + else + dst->selected_world = m_world_indices[list_i]; + } } { ServerListSpec server = diff --git a/src/guiMainMenu.h b/src/guiMainMenu.h index b0c9ff24b..1c5ca4d37 100644 --- a/src/guiMainMenu.h +++ b/src/guiMainMenu.h @@ -130,6 +130,8 @@ private: s32 id; IMenuManager *menumgr; + std::vector m_world_indices; + bool m_is_regenerating; v2s32 m_topleft_client; v2s32 m_size_client; -- cgit v1.2.3 From 80874391b85a3afe18980c8dc9d46f73b3e73177 Mon Sep 17 00:00:00 2001 From: Perttu Ahola Date: Fri, 15 Feb 2013 21:50:21 +0200 Subject: games/minimal: Add menu/background.png and menu/icon.png --- games/minimal/menu/background.png | Bin 0 -> 1387 bytes games/minimal/menu/icon.png | Bin 0 -> 397 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 games/minimal/menu/background.png create mode 100644 games/minimal/menu/icon.png diff --git a/games/minimal/menu/background.png b/games/minimal/menu/background.png new file mode 100644 index 000000000..e020f909d Binary files /dev/null and b/games/minimal/menu/background.png differ diff --git a/games/minimal/menu/icon.png b/games/minimal/menu/icon.png new file mode 100644 index 000000000..fa8d7cd7f Binary files /dev/null and b/games/minimal/menu/icon.png differ -- cgit v1.2.3 From 2cf76f6f1b1c915ad198315b301221c28391265d Mon Sep 17 00:00:00 2001 From: Perttu Ahola Date: Thu, 2 May 2013 19:07:44 +0300 Subject: Pre-select current game in world creation dialog --- src/guiCreateWorld.cpp | 15 ++++++++++++--- src/guiCreateWorld.h | 4 +++- src/guiMainMenu.cpp | 2 +- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/guiCreateWorld.cpp b/src/guiCreateWorld.cpp index 09b18fb3c..caa884bc0 100644 --- a/src/guiCreateWorld.cpp +++ b/src/guiCreateWorld.cpp @@ -42,13 +42,22 @@ GUICreateWorld::GUICreateWorld(gui::IGUIEnvironment* env, gui::IGUIElement* parent, s32 id, IMenuManager *menumgr, CreateWorldDest *dest, - const std::vector &games + const std::vector &games, + const std::string &initial_game ): GUIModalMenu(env, parent, id, menumgr), m_dest(dest), - m_games(games) + m_games(games), + m_initial_game_i(0) { assert(games.size() > 0); + + for(size_t i=0; iaddItem(os.str().c_str()); } - e->setSelected(0); + e->setSelected(m_initial_game_i); } changeCtype(""); { diff --git a/src/guiCreateWorld.h b/src/guiCreateWorld.h index d9bc3638a..2765dc2bd 100644 --- a/src/guiCreateWorld.h +++ b/src/guiCreateWorld.h @@ -38,7 +38,8 @@ public: gui::IGUIElement* parent, s32 id, IMenuManager *menumgr, CreateWorldDest *dest, - const std::vector &games); + const std::vector &games, + const std::string &initial_game); ~GUICreateWorld(); void removeChildren(); @@ -56,6 +57,7 @@ public: private: CreateWorldDest *m_dest; std::vector m_games; + int m_initial_game_i; }; #endif diff --git a/src/guiMainMenu.cpp b/src/guiMainMenu.cpp index 2e7fb955d..c6142d4ce 100644 --- a/src/guiMainMenu.cpp +++ b/src/guiMainMenu.cpp @@ -1274,7 +1274,7 @@ bool GUIMainMenu::OnEvent(const SEvent& event) } else { CreateWorldDest *dest = new CreateWorldDestMainMenu(this); GUICreateWorld *menu = new GUICreateWorld(env, parent, -1, - menumgr, dest, games); + menumgr, dest, games, m_data->selected_game); menu->drop(); } return true; -- cgit v1.2.3 From ee8067f7cfa5b25e12a166bd5d306a905630ee92 Mon Sep 17 00:00:00 2001 From: Perttu Ahola Date: Thu, 2 May 2013 20:59:52 +0300 Subject: Switch menu to game selected in world creation dialog --- src/main.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main.cpp b/src/main.cpp index 67aa82bc4..9a646413d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1795,6 +1795,7 @@ int main(int argc, char *argv[]) continue; } g_settings->set("selected_world_path", path); + g_settings->set("selected_mainmenu_game", menudata.create_world_gameid); continue; } -- cgit v1.2.3 From b75505e6b2b82d48980ff71649dd4944b04b6f78 Mon Sep 17 00:00:00 2001 From: PilzAdam Date: Thu, 2 May 2013 19:57:03 +0200 Subject: Show game name instead of game ID of selected game --- src/guiMainMenu.cpp | 6 ++++-- src/guiMainMenu.h | 2 ++ src/main.cpp | 4 +++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/guiMainMenu.cpp b/src/guiMainMenu.cpp index c6142d4ce..5d5ae1e90 100644 --- a/src/guiMainMenu.cpp +++ b/src/guiMainMenu.cpp @@ -258,9 +258,9 @@ void GUIMainMenu::regenerateGui(v2u32 screensize) core::rect rect(0, 0, size.X, 40); rect += v2s32(4, 0); std::string t = "Minetest " VERSION_STRING; - if(m_data->selected_game != ""){ + if(m_data->selected_game_name != ""){ t += "/"; - t += m_data->selected_game; + t += m_data->selected_game_name; } Environment->addStaticText(narrow_to_wide(t).c_str(), rect, false, true, this, -1); @@ -1356,6 +1356,8 @@ bool GUIMainMenu::OnEvent(const SEvent& event) eid <= GUI_ID_GAME_BUTTON_MAX){ m_data->selected_game = m_data->games[eid - GUI_ID_GAME_BUTTON_FIRST].id; + m_data->selected_game_name = + m_data->games[eid - GUI_ID_GAME_BUTTON_FIRST].name; regenerateGui(m_screensize_old); } } diff --git a/src/guiMainMenu.h b/src/guiMainMenu.h index 1c5ca4d37..1d09c8baa 100644 --- a/src/guiMainMenu.h +++ b/src/guiMainMenu.h @@ -40,6 +40,7 @@ struct MainMenuData // Generic int selected_tab; std::string selected_game; + std::string selected_game_name; // Client options std::string servername; std::string serverdescription; @@ -80,6 +81,7 @@ struct MainMenuData // Generic selected_tab(0), selected_game("minetest"), + selected_game_name("Minetest"), // Client opts fancy_trees(false), smooth_lighting(false), diff --git a/src/main.cpp b/src/main.cpp index 9a646413d..501e4cdf4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1501,8 +1501,10 @@ int main(int argc, char *argv[]) menudata.selected_tab = g_settings->getS32("selected_mainmenu_tab"); if(g_settings->exists("selected_serverlist")) menudata.selected_serverlist = g_settings->getS32("selected_serverlist"); - if(g_settings->exists("selected_mainmenu_game")) + if(g_settings->exists("selected_mainmenu_game")){ menudata.selected_game = g_settings->get("selected_mainmenu_game"); + menudata.selected_game_name = findSubgame(menudata.selected_game).name; + } menudata.address = narrow_to_wide(address); menudata.name = narrow_to_wide(playername); menudata.port = narrow_to_wide(itos(port)); -- cgit v1.2.3 From 0deb68d81cd5ebbd24671702be940e1c871e43f2 Mon Sep 17 00:00:00 2001 From: PilzAdam Date: Thu, 2 May 2013 23:08:59 +0200 Subject: Use DIR_DELIM instead of / in file paths --- src/subgame.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/subgame.cpp b/src/subgame.cpp index a17b16234..1bee630b2 100644 --- a/src/subgame.cpp +++ b/src/subgame.cpp @@ -101,9 +101,9 @@ SubgameSpec findSubgame(const std::string &id) std::string menuoverlay_path; std::string menuicon_path; #ifndef SERVER - menubackground_path = getImagePath(game_path + DIR_DELIM + "menu/background.png"); - menuoverlay_path = getImagePath(game_path + DIR_DELIM + "menu/overlay.png"); - menuicon_path = getImagePath(game_path + DIR_DELIM + "menu/icon.png"); + menubackground_path = getImagePath(game_path + DIR_DELIM + "menu" + DIR_DELIM + "background.png"); + menuoverlay_path = getImagePath(game_path + DIR_DELIM + "menu" + DIR_DELIM + "overlay.png"); + menuicon_path = getImagePath(game_path + DIR_DELIM + "menu" + DIR_DELIM + "icon.png"); #endif return SubgameSpec(id, game_path, gamemod_path, mods_paths, game_name, menubackground_path, menuoverlay_path, menuicon_path); -- cgit v1.2.3 From be4cc306a54375f362ae13f9e4111ea11a739837 Mon Sep 17 00:00:00 2001 From: Kahrl Date: Sat, 27 Apr 2013 03:28:27 +0200 Subject: Server: force block send of pointed_pos_under after predicted node place --- src/server.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/server.cpp b/src/server.cpp index d5e505190..37bb7a35c 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -2980,12 +2980,16 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) playersao->setWieldedItem(item); } - // If item has node placement prediction, always send the above - // node to make sure the client knows what exactly happened + // If item has node placement prediction, always send the + // blocks to make sure the client knows what exactly happened if(item.getDefinition(m_itemdef).node_placement_prediction != ""){ RemoteClient *client = getClient(peer_id); v3s16 blockpos = getNodeBlockPos(floatToInt(pointed_pos_above, BS)); client->SetBlockNotSent(blockpos); + v3s16 blockpos2 = getNodeBlockPos(floatToInt(pointed_pos_under, BS)); + if(blockpos2 != blockpos){ + client->SetBlockNotSent(blockpos2); + } } } // action == 3 -- cgit v1.2.3 From 777ac58f85c74d2945886869e9b63b0f450ac3aa Mon Sep 17 00:00:00 2001 From: Kahrl Date: Sat, 27 Apr 2013 03:47:52 +0200 Subject: Predict wallmounted param2 during node placement prediction. Also clean up the_game a bit: move node placement prediction to a separate function. --- src/game.cpp | 112 ++++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 68 insertions(+), 44 deletions(-) diff --git a/src/game.cpp b/src/game.cpp index 189003e4c..a5011b6ff 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -789,6 +789,65 @@ public: } }; +void nodePlacementPrediction(Client &client, + const ItemDefinition &playeritem_def, + v3s16 nodepos, v3s16 neighbourpos) +{ + std::string prediction = playeritem_def.node_placement_prediction; + INodeDefManager *nodedef = client.ndef(); + ClientMap &map = client.getEnv().getClientMap(); + + if(prediction != "" && !nodedef->get(map.getNode(nodepos)).rightclickable) + { + verbosestream<<"Node placement prediction for " + <get(n_under).buildable_to) + p = nodepos; + }catch(InvalidPositionException &e){} + // Find id of predicted node + content_t id; + bool found = nodedef->getId(prediction, id); + if(!found){ + errorstream<<"Node placement prediction failed for " + <get(id).param_type_2 == CPT2_WALLMOUNTED){ + v3s16 dir = nodepos - neighbourpos; + if(abs(dir.Y) > MYMAX(abs(dir.X), abs(dir.Z))){ + param2 = dir.Y < 0 ? 1 : 0; + } else if(abs(dir.X) > abs(dir.Z)){ + param2 = dir.X < 0 ? 3 : 2; + } else { + param2 = dir.Z < 0 ? 5 : 4; + } + } + // TODO: Facedir prediction + // TODO: If predicted node is in attached_node group, check attachment + // Add node to client map + MapNode n(id, 0, param2); + try{ + // This triggers the required mesh update too + client.addNode(p, n); + }catch(InvalidPositionException &e){ + errorstream<<"Node placement prediction failed for " + <getItem(client.getPlayerItem()); - playeritem_usable = playeritem.getDefinition(itemdef).usable; - playeritem_liquids_pointable = playeritem.getDefinition(itemdef).liquids_pointable; } } + const ItemDefinition &playeritem_def = + playeritem.getDefinition(itemdef); ToolCapabilities playeritem_toolcap = playeritem.getToolCapabilities(itemdef); @@ -2267,7 +2324,7 @@ void the_game( // input &client, player_position, camera_direction, camera_position, shootline, d, - playeritem_liquids_pointable, !ldown_for_dig, + playeritem_def.liquids_pointable, !ldown_for_dig, // output hilightboxes, selected_object); @@ -2327,7 +2384,7 @@ void the_game( else repeat_rightclick_timer = 0; - if(playeritem_usable && input->getLeftState()) + if(playeritem_def.usable && input->getLeftState()) { if(input->getLeftClicked()) client.interact(4, pointed); @@ -2534,46 +2591,13 @@ void the_game( // If the wielded item has node placement prediction, // make that happen - const ItemDefinition &def = - playeritem.getDefinition(itemdef); - if(def.node_placement_prediction != "" - && !nodedef->get(map.getNode(nodepos)).rightclickable) - do{ // breakable - verbosestream<<"Node placement prediction for " - <get(n_under).buildable_to) - p = nodepos; - }catch(InvalidPositionException &e){} - // Find id of predicted node - content_t id; - bool found = - nodedef->getId(def.node_placement_prediction, id); - if(!found){ - errorstream<<"Node placement prediction failed for " - < Date: Sat, 20 Apr 2013 17:01:02 -0400 Subject: Don't predict placement of nodes if they would replace a non buildable_to node --- src/game.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/game.cpp b/src/game.cpp index a5011b6ff..3fbfad801 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -808,6 +808,8 @@ void nodePlacementPrediction(Client &client, MapNode n_under = map.getNode(nodepos); if(nodedef->get(n_under).buildable_to) p = nodepos; + else if (!nodedef->get(map.getNode(p)).buildable_to) + return; }catch(InvalidPositionException &e){} // Find id of predicted node content_t id; -- cgit v1.2.3 From 969d2b3eb1f30e257823d9220697e47735be68e3 Mon Sep 17 00:00:00 2001 From: Kahrl Date: Fri, 3 May 2013 23:58:22 +0200 Subject: Optional dependencies and properly handle mod name conflicts again --- doc/lua_api.txt | 11 ++ src/guiConfigureWorld.cpp | 22 ++- src/mods.cpp | 373 ++++++++++++++++++++++++++++++---------------- src/mods.h | 76 ++++++---- src/scriptapi.cpp | 3 +- src/server.cpp | 6 +- 6 files changed, 323 insertions(+), 168 deletions(-) diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 597f98c2c..02ca7cba3 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -120,6 +120,17 @@ depends.txt: List of mods that have to be loaded before loading this mod. A single line contains a single modname. + Optional dependencies can be defined by appending a question mark + to a single modname. Their meaning is that if the specified mod + is missing, that does not prevent this mod from being loaded. + +optdepends.txt: + An alternative way of specifying optional dependencies. + Like depends.txt, a single line contains a single modname. + + NOTE: This file exists for compatibility purposes only and + support for it will be removed from the engine by the end of 2013. + init.lua: The main Lua script. Running this script should register everything it wants to register. Subsequent execution depends on minetest calling the diff --git a/src/guiConfigureWorld.cpp b/src/guiConfigureWorld.cpp index b2debfbd2..f94ed7d17 100644 --- a/src/guiConfigureWorld.cpp +++ b/src/guiConfigureWorld.cpp @@ -407,14 +407,26 @@ bool GUIConfigureWorld::OnEvent(const SEvent& event) delete[] text; menu->drop(); - ModConfiguration modconf(m_wspec.path); - if(!modconf.isConsistent()) + try { - wchar_t* text = wgettext("Warning: Configuration not consistent. "); + ModConfiguration modconf(m_wspec.path); + if(!modconf.isConsistent()) + { + wchar_t* text = wgettext("Warning: Configuration not consistent. "); + GUIMessageMenu *menu = + new GUIMessageMenu(Environment, Parent, -1, m_menumgr, + text ); + delete[] text; + menu->drop(); + } + } + catch(ModError &err) + { + errorstream<drop(); } diff --git a/src/mods.cpp b/src/mods.cpp index 6a7ab79aa..64c319992 100644 --- a/src/mods.cpp +++ b/src/mods.cpp @@ -24,9 +24,74 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "subgame.h" #include "settings.h" #include "strfnd.h" +#include -std::map getModsInPath(std::string path) +static bool parseDependsLine(std::istream &is, + std::string &dep, std::set &symbols) { + std::getline(is, dep); + dep = trim(dep); + symbols.clear(); + size_t pos = dep.size(); + while(pos > 0 && !string_allowed(dep.substr(pos-1, 1), MODNAME_ALLOWED_CHARS)){ + // last character is a symbol, not part of the modname + symbols.insert(dep[pos-1]); + --pos; + } + dep = trim(dep.substr(0, pos)); + return dep != ""; +} + +void parseModContents(ModSpec &spec) +{ + // NOTE: this function works in mutual recursion with getModsInPath + + spec.depends.clear(); + spec.optdepends.clear(); + spec.is_modpack = false; + spec.modpack_content.clear(); + + // Handle modpacks (defined by containing modpack.txt) + std::ifstream modpack_is((spec.path+DIR_DELIM+"modpack.txt").c_str()); + if(modpack_is.good()){ //a modpack, recursively get the mods in it + modpack_is.close(); // We don't actually need the file + spec.is_modpack = true; + spec.modpack_content = getModsInPath(spec.path, true); + + // modpacks have no dependencies; they are defined and + // tracked separately for each mod in the modpack + } + else{ // not a modpack, parse the dependencies + std::ifstream is((spec.path+DIR_DELIM+"depends.txt").c_str()); + while(is.good()){ + std::string dep; + std::set symbols; + if(parseDependsLine(is, dep, symbols)){ + if(symbols.count('?') != 0){ + spec.optdepends.insert(dep); + } + else{ + spec.depends.insert(dep); + } + } + } + + // FIXME: optdepends.txt is deprecated + // remove this code at some point in the future + std::ifstream is2((spec.path+DIR_DELIM+"optdepends.txt").c_str()); + while(is2.good()){ + std::string dep; + std::set symbols; + if(parseDependsLine(is2, dep, symbols)) + spec.optdepends.insert(dep); + } + } +} + +std::map getModsInPath(std::string path, bool part_of_modpack) +{ + // NOTE: this function works in mutual recursion with parseModContents + std::map result; std::vector dirlist = fs::GetDirListing(path); for(u32 j=0; j getModsInPath(std::string path) continue; std::string modpath = path + DIR_DELIM + modname; - // Handle modpacks (defined by containing modpack.txt) - std::ifstream modpack_is((modpath+DIR_DELIM+"modpack.txt").c_str(), - std::ios_base::binary); - if(modpack_is.good()) //a modpack, recursively get the mods in it - { - modpack_is.close(); // We don't actually need the file - ModSpec spec(modname,modpath); - spec.modpack_content = getModsInPath(modpath); - spec.is_modpack = true; - result.insert(std::make_pair(modname,spec)); - } - else // not a modpack, add the modspec - { - std::set depends; - std::ifstream is((modpath+DIR_DELIM+"depends.txt").c_str(), - std::ios_base::binary); - while(is.good()) - { - std::string dep; - std::getline(is, dep); - dep = trim(dep); - if(dep != "") - depends.insert(dep); - } + ModSpec spec(modname, modpath); + spec.part_of_modpack = part_of_modpack; + parseModContents(spec); + result.insert(std::make_pair(modname, spec)); + } + return result; +} - ModSpec spec(modname, modpath, depends); - result.insert(std::make_pair(modname,spec)); +ModSpec findCommonMod(const std::string &modname) +{ + // Try to find in {$user,$share}/games/common/$modname + std::vector find_paths; + find_paths.push_back(porting::path_user + DIR_DELIM + "games" + + DIR_DELIM + "common" + DIR_DELIM + "mods" + DIR_DELIM + modname); + find_paths.push_back(porting::path_share + DIR_DELIM + "games" + + DIR_DELIM + "common" + DIR_DELIM + "mods" + DIR_DELIM + modname); + for(u32 i=0; i flattenModTree(std::map mods) @@ -109,109 +170,18 @@ std::vector flattenMods(std::map mods) } else //not a modpack { - // infostream << "inserting mod " << mod.name << std::endl; result.push_back(mod); } } return result; } -std::vector filterMods(std::vector mods, - std::set exclude_mod_names) -{ - std::vector result; - for(std::vector::iterator it = mods.begin(); - it != mods.end(); ++it) - { - ModSpec& mod = *it; - if(exclude_mod_names.count(mod.name) == 0) - result.push_back(mod); - } - return result; -} - -void ModConfiguration::addModsInPathFiltered(std::string path, std::set exclude_mods) -{ - addMods(filterMods(flattenMods(getModsInPath(path)),exclude_mods)); -} - - -void ModConfiguration::addMods(std::vector new_mods) -{ - // Step 1: remove mods in sorted_mods from unmet dependencies - // of new_mods. new mods without unmet dependencies are - // temporarily stored in satisfied_mods - std::vector satisfied_mods; - for(std::vector::iterator it = m_sorted_mods.begin(); - it != m_sorted_mods.end(); ++it) - { - ModSpec mod = *it; - for(std::vector::iterator it_new = new_mods.begin(); - it_new != new_mods.end(); ++it_new) - { - ModSpec& mod_new = *it_new; - //infostream << "erasing dependency " << mod.name << " from " << mod_new.name << std::endl; - mod_new.unsatisfied_depends.erase(mod.name); - } - } - - // split new mods into satisfied and unsatisfied - for(std::vector::iterator it = new_mods.begin(); - it != new_mods.end(); ++it) - { - ModSpec mod_new = *it; - if(mod_new.unsatisfied_depends.empty()) - satisfied_mods.push_back(mod_new); - else - m_unsatisfied_mods.push_back(mod_new); - } - - // Step 2: mods without unmet dependencies can be appended to - // the sorted list. - while(!satisfied_mods.empty()) - { - ModSpec mod = satisfied_mods.back(); - m_sorted_mods.push_back(mod); - satisfied_mods.pop_back(); - for(std::list::iterator it = m_unsatisfied_mods.begin(); - it != m_unsatisfied_mods.end(); ) - { - ModSpec& mod2 = *it; - mod2.unsatisfied_depends.erase(mod.name); - if(mod2.unsatisfied_depends.empty()) - { - satisfied_mods.push_back(mod2); - it = m_unsatisfied_mods.erase(it); - } - else - ++it; - } - } -} - -// If failed, returned modspec has name=="" -static ModSpec findCommonMod(const std::string &modname) -{ - // Try to find in {$user,$share}/games/common/$modname - std::vector find_paths; - find_paths.push_back(porting::path_user + DIR_DELIM + "games" + - DIR_DELIM + "common" + DIR_DELIM + "mods" + DIR_DELIM + modname); - find_paths.push_back(porting::path_share + DIR_DELIM + "games" + - DIR_DELIM + "common" + DIR_DELIM + "mods" + DIR_DELIM + modname); - for(u32 i=0; i common_mods; std::vector inexistent_common_mods; Settings gameconf; if(getGameConfig(gamespec.path, gameconf)){ @@ -225,7 +195,7 @@ ModConfiguration::ModConfiguration(std::string worldpath) if(spec.name.empty()) inexistent_common_mods.push_back(modname); else - m_sorted_mods.push_back(spec); + common_mods.insert(std::make_pair(modname, spec)); } } } @@ -238,10 +208,11 @@ ModConfiguration::ModConfiguration(std::string worldpath) s += " could not be found."; throw ModError(s); } + addMods(flattenMods(common_mods)); - // Add all world mods and all game mods - addModsInPath(worldpath + DIR_DELIM + "worldmods"); + // Add all game mods and all world mods addModsInPath(gamespec.gamemods_path); + addModsInPath(worldpath + DIR_DELIM + "worldmods"); // check world.mt file for mods explicitely declared to be // loaded or not by a load_mod_ = ... line. @@ -264,7 +235,155 @@ ModConfiguration::ModConfiguration(std::string worldpath) } } - for(std::set::const_iterator i = gamespec.addon_mods_paths.begin(); - i != gamespec.addon_mods_paths.end(); ++i) - addModsInPathFiltered((*i),exclude_mod_names); + // Collect all mods in gamespec.addon_mods_paths, + // excluding those in the set exclude_mod_names + std::vector addon_mods; + for(std::set::const_iterator it_path = gamespec.addon_mods_paths.begin(); + it_path != gamespec.addon_mods_paths.end(); ++it_path) + { + std::vector addon_mods_in_path = flattenMods(getModsInPath(*it_path)); + for(std::vector::iterator it = addon_mods_in_path.begin(); + it != addon_mods_in_path.end(); ++it) + { + ModSpec& mod = *it; + if(exclude_mod_names.count(mod.name) == 0) + addon_mods.push_back(mod); + } + } + + addMods(addon_mods); + + // report on name conflicts + if(!m_name_conflicts.empty()){ + std::string s = "Unresolved name conflicts for mods "; + for(std::set::const_iterator it = m_name_conflicts.begin(); + it != m_name_conflicts.end(); ++it) + { + if(it != m_name_conflicts.begin()) s += ", "; + s += std::string("\"") + (*it) + "\""; + } + s += "."; + throw ModError(s); + } + + // get the mods in order + resolveDependencies(); +} + +void ModConfiguration::addModsInPath(std::string path) +{ + addMods(flattenMods(getModsInPath(path))); +} + +void ModConfiguration::addMods(std::vector new_mods) +{ + // Maintain a map of all existing m_unsatisfied_mods. + // Keys are mod names and values are indices into m_unsatisfied_mods. + std::map existing_mods; + for(u32 i = 0; i < m_unsatisfied_mods.size(); ++i){ + existing_mods[m_unsatisfied_mods[i].name] = i; + } + + // Add new mods + for(int want_from_modpack = 1; want_from_modpack >= 0; --want_from_modpack){ + // First iteration: + // Add all the mods that come from modpacks + // Second iteration: + // Add all the mods that didn't come from modpacks + + std::set seen_this_iteration; + + for(std::vector::const_iterator it = new_mods.begin(); + it != new_mods.end(); ++it){ + const ModSpec &mod = *it; + if(mod.part_of_modpack != want_from_modpack) + continue; + if(existing_mods.count(mod.name) == 0){ + // GOOD CASE: completely new mod. + m_unsatisfied_mods.push_back(mod); + existing_mods[mod.name] = m_unsatisfied_mods.size() - 1; + } + else if(seen_this_iteration.count(mod.name) == 0){ + // BAD CASE: name conflict in different levels. + u32 oldindex = existing_mods[mod.name]; + const ModSpec &oldmod = m_unsatisfied_mods[oldindex]; + errorstream<<"WARNING: Mod name conflict detected: \"" + < modnames; + for(std::vector::iterator it = m_unsatisfied_mods.begin(); + it != m_unsatisfied_mods.end(); ++it){ + modnames.insert((*it).name); + } + + // Step 2: get dependencies (including optional dependencies) + // of each mod, split mods into satisfied and unsatisfied + std::list satisfied; + std::list unsatisfied; + for(std::vector::iterator it = m_unsatisfied_mods.begin(); + it != m_unsatisfied_mods.end(); ++it){ + ModSpec mod = *it; + mod.unsatisfied_depends = mod.depends; + // check which optional dependencies actually exist + for(std::set::iterator it_optdep = mod.optdepends.begin(); + it_optdep != mod.optdepends.end(); ++it_optdep){ + std::string optdep = *it_optdep; + if(modnames.count(optdep) != 0) + mod.unsatisfied_depends.insert(optdep); + } + // if a mod has no depends it is initially satisfied + if(mod.unsatisfied_depends.empty()) + satisfied.push_back(mod); + else + unsatisfied.push_back(mod); + } + + // Step 3: mods without unmet dependencies can be appended to + // the sorted list. + while(!satisfied.empty()){ + ModSpec mod = satisfied.back(); + m_sorted_mods.push_back(mod); + satisfied.pop_back(); + for(std::list::iterator it = unsatisfied.begin(); + it != unsatisfied.end(); ){ + ModSpec& mod2 = *it; + mod2.unsatisfied_depends.erase(mod.name); + if(mod2.unsatisfied_depends.empty()){ + satisfied.push_back(mod2); + it = unsatisfied.erase(it); + } + else{ + ++it; + } + } + } + + // Step 4: write back list of unsatisfied mods + m_unsatisfied_mods.assign(unsatisfied.begin(), unsatisfied.end()); } diff --git a/src/mods.h b/src/mods.h index 32bcfb471..a8100fcfd 100644 --- a/src/mods.h +++ b/src/mods.h @@ -30,6 +30,8 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include +#define MODNAME_ALLOWED_CHARS "abcdefghijklmnopqrstuvwxyz0123456789_" + class ModError : public std::exception { public: @@ -53,23 +55,32 @@ struct ModSpec std::string path; //if normal mod: std::set depends; + std::set optdepends; std::set unsatisfied_depends; + bool part_of_modpack; bool is_modpack; // if modpack: std::map modpack_content; - ModSpec(const std::string name_="", const std::string path_="", - const std::set depends_=std::set()): + ModSpec(const std::string name_="", const std::string path_=""): name(name_), path(path_), - depends(depends_), - unsatisfied_depends(depends_), - is_modpack(false), - modpack_content() + depends(), + optdepends(), + unsatisfied_depends(), + part_of_modpack(false), + is_modpack(false), + modpack_content() {} }; -std::map getModsInPath(std::string path); +// Retrieves depends, optdepends, is_modpack and modpack_content +void parseModContents(ModSpec &mod); + +std::map getModsInPath(std::string path, bool part_of_modpack = false); + +// If failed, returned modspec has name=="" +ModSpec findCommonMod(const std::string &modname); // expands modpack contents, but does not replace them. std::map flattenModTree(std::map mods); @@ -77,10 +88,6 @@ std::map flattenModTree(std::map mod // replaces modpack Modspecs with their content std::vector flattenMods(std::map mods); -// removes Mods mentioned in exclude_mod_names -std::vector filterMods(std::vector mods, - std::set exclude_mod_names); - // a ModConfiguration is a subset of installed mods, expected to have // all dependencies fullfilled, so it can be used as a list of mods to // load when the game starts. @@ -89,26 +96,13 @@ class ModConfiguration public: ModConfiguration(): m_unsatisfied_mods(), - m_sorted_mods() + m_sorted_mods(), + m_name_conflicts() {} ModConfiguration(std::string worldpath); - // adds all mods in the given path. used for games, modpacks - // and world-specific mods (worldmods-folders) - void addModsInPath(std::string path) - { - addMods(flattenMods(getModsInPath(path))); - } - - // adds all mods in the given path whose name does not appear - // in the exclude_mods set. - void addModsInPathFiltered(std::string path, std::set exclude_mods); - - // adds all mods in the set. - void addMods(std::vector mods); - // checks if all dependencies are fullfilled. bool isConsistent() { @@ -120,17 +114,27 @@ public: return m_sorted_mods; } - std::list getUnsatisfiedMods() + std::vector getUnsatisfiedMods() { return m_unsatisfied_mods; } private: + // adds all mods in the given path. used for games, modpacks + // and world-specific mods (worldmods-folders) + void addModsInPath(std::string path); - // mods with unmet dependencies. This is a list and not a - // vector because we want easy removal of elements at every - // position. - std::list m_unsatisfied_mods; + // adds all mods in the set. + void addMods(std::vector new_mods); + + // move mods from m_unsatisfied_mods to m_sorted_mods + // in an order that satisfies dependencies + void resolveDependencies(); + + // mods with unmet dependencies. Before dependencies are resolved, + // this is where all mods are stored. Afterwards this contains + // only the ones with really unsatisfied dependencies. + std::vector m_unsatisfied_mods; // list of mods sorted such that they can be loaded in the // given order with all dependencies being fullfilled. I.e., @@ -138,6 +142,16 @@ private: // appear earlier in the vector. std::vector m_sorted_mods; + // set of mod names for which an unresolved name conflict + // exists. A name conflict happens when two or more mods + // at the same level have the same name but different paths. + // Levels (mods in higher levels override mods in lower levels): + // 1. common mod in modpack; 2. common mod; + // 3. game mod in modpack; 4. game mod; + // 5. world mod in modpack; 6. world mod; + // 7. addon mod in modpack; 8. addon mod. + std::set m_name_conflicts; + }; #endif diff --git a/src/scriptapi.cpp b/src/scriptapi.cpp index f0fe1950e..26759a059 100644 --- a/src/scriptapi.cpp +++ b/src/scriptapi.cpp @@ -76,8 +76,7 @@ bool scriptapi_loadmod(lua_State *L, const std::string &scriptpath, { ModNameStorer modnamestorer(L, modname); - if(!string_allowed(modname, "abcdefghijklmnopqrstuvwxyz" - "0123456789_")){ + if(!string_allowed(modname, MODNAME_ALLOWED_CHARS)){ errorstream<<"Error loading mod \""< unsatisfied_mods = modconf.getUnsatisfiedMods(); + std::vector unsatisfied_mods = modconf.getUnsatisfiedMods(); // complain about mods with unsatisfied dependencies if(!modconf.isConsistent()) { - for(std::list::iterator it = unsatisfied_mods.begin(); + for(std::vector::iterator it = unsatisfied_mods.begin(); it != unsatisfied_mods.end(); ++it) { ModSpec mod = *it; @@ -745,7 +745,7 @@ Server::Server( for(std::vector::iterator it = m_mods.begin(); it != m_mods.end(); ++it) load_mod_names.erase((*it).name); - for(std::list::iterator it = unsatisfied_mods.begin(); + for(std::vector::iterator it = unsatisfied_mods.begin(); it != unsatisfied_mods.end(); ++it) load_mod_names.erase((*it).name); if(!load_mod_names.empty()) -- cgit v1.2.3 From 8d5b400d09cf79271bef19ccd69024316c80e39d Mon Sep 17 00:00:00 2001 From: PilzAdam Date: Sat, 4 May 2013 01:04:09 +0200 Subject: Fix documentation for HUD commands in protocol --- src/clientserver.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/clientserver.h b/src/clientserver.h index cfa87ada7..ee9271bbc 100644 --- a/src/clientserver.h +++ b/src/clientserver.h @@ -91,10 +91,10 @@ SharedBuffer makePacket_TOCLIENT_TIME_OF_DAY(u16 time, float time_speed); PROTOCOL_VERSION 19: GENERIC_CMD_SET_PHYSICS_OVERRIDE PROTOCOL_VERSION 20: - TOCLIENT_HUD_ADD - TOCLIENT_HUD_RM - TOCLIENT_HUD_CHANGE - TOCLIENT_HUD_BUILTIN_ENABLE + TOCLIENT_HUDADD + TOCLIENT_HUDRM + TOCLIENT_HUDCHANGE + TOCLIENT_HUD_SET_FLAGS */ #define LATEST_PROTOCOL_VERSION 20 -- cgit v1.2.3 From b88aa81da7031ddb228e8901071b5adf2980c7ed Mon Sep 17 00:00:00 2001 From: Sfan5 Date: Sat, 4 May 2013 07:31:22 +0200 Subject: Fix favorite Server List on Windows --- src/serverlist.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/serverlist.cpp b/src/serverlist.cpp index 7053436d0..ea5a616c2 100644 --- a/src/serverlist.cpp +++ b/src/serverlist.cpp @@ -53,7 +53,7 @@ std::vector getLocal() std::string liststring; if(fs::PathExists(path)) { - std::ifstream istream(path.c_str(), std::ios::binary); + std::ifstream istream(path.c_str()); if(istream.is_open()) { std::ostringstream ostream; -- cgit v1.2.3 From a888b232fe1315e4922c541f30b214647511bb93 Mon Sep 17 00:00:00 2001 From: Perttu Ahola Date: Sat, 4 May 2013 10:03:56 +0300 Subject: Add header.png and footer.png support for games, and support texture packs via _menu_.png --- src/main.cpp | 141 +++++++++++++++++++++++++++++++++++++++++++++++--------- src/subgame.cpp | 6 +-- src/subgame.h | 6 --- 3 files changed, 121 insertions(+), 32 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 501e4cdf4..3cf6728e4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -612,15 +612,53 @@ private: bool rightreleased; }; -void drawMenuBackground(video::IVideoDriver* driver, const SubgameSpec *spec) +struct MenuTextures { - v2u32 screensize = driver->getScreenSize(); + std::string current_gameid; + video::ITexture *background; + video::ITexture *overlay; + video::ITexture *header; + video::ITexture *footer; + + MenuTextures(): + background(NULL), + overlay(NULL), + header(NULL), + footer(NULL) + {} - /* Figure out background texture */ - video::ITexture *texture = NULL; - if(spec && spec->menubackground_path != ""){ - texture = driver->getTexture(spec->menubackground_path.c_str()); + static video::ITexture* getMenuTexture(const std::string &tname, + video::IVideoDriver* driver, const SubgameSpec *spec) + { + std::string path; + // eg. minetest_menu_background.png (for texture packs) + std::string pack_tname = spec->id + "_menu_" + tname + ".png"; + path = getTexturePath(pack_tname); + if(path != "") + return driver->getTexture(path.c_str()); + // eg. games/minetest_game/menu/background.png + path = getImagePath(spec->path + DIR_DELIM + "menu" + DIR_DELIM + tname + ".png"); + if(path != "") + return driver->getTexture(path.c_str()); + return NULL; + } + + void update(video::IVideoDriver* driver, const SubgameSpec *spec) + { + if(spec->id == current_gameid) + return; + current_gameid = spec->id; + background = getMenuTexture("background", driver, spec); + overlay = getMenuTexture("overlay", driver, spec); + header = getMenuTexture("header", driver, spec); + footer = getMenuTexture("footer", driver, spec); } +}; + +void drawMenuBackground(video::IVideoDriver* driver, const MenuTextures &menutextures) +{ + v2u32 screensize = driver->getScreenSize(); + video::ITexture *texture = menutextures.background; /* If no texture, draw background of solid color */ if(!texture){ @@ -638,15 +676,10 @@ void drawMenuBackground(video::IVideoDriver* driver, const SubgameSpec *spec) NULL, NULL, true); } -void drawMenuOverlay(video::IVideoDriver* driver, const SubgameSpec *spec) +void drawMenuOverlay(video::IVideoDriver* driver, const MenuTextures &menutextures) { v2u32 screensize = driver->getScreenSize(); - - /* Figure out overlay texture */ - video::ITexture *texture = NULL; - if(spec && spec->menuoverlay_path != ""){ - texture = driver->getTexture(spec->menuoverlay_path.c_str()); - } + video::ITexture *texture = menutextures.overlay; /* If no texture, draw nothing */ if(!texture) @@ -660,6 +693,66 @@ void drawMenuOverlay(video::IVideoDriver* driver, const SubgameSpec *spec) NULL, NULL, true); } +void drawMenuHeader(video::IVideoDriver* driver, const MenuTextures &menutextures) +{ + core::dimension2d screensize = driver->getScreenSize(); + video::ITexture *texture = menutextures.header; + + /* If no texture, draw nothing */ + if(!texture) + return; + + f32 mult = (((f32)screensize.Width / 2)) / + ((f32)texture->getOriginalSize().Width); + + v2s32 splashsize(((f32)texture->getOriginalSize().Width) * mult, + ((f32)texture->getOriginalSize().Height) * mult); + + // Don't draw the header is there isn't enough room + s32 free_space = (((s32)screensize.Height)-320)/2; + if (free_space > splashsize.Y) { + core::rect splashrect(0, 0, splashsize.X, splashsize.Y); + splashrect += v2s32((screensize.Width/2)-(splashsize.X/2), + ((free_space/2)-splashsize.Y/2)+10); + + video::SColor bgcolor(255,50,50,50); + + driver->draw2DImage(texture, splashrect, + core::rect(core::position2d(0,0), + core::dimension2di(texture->getSize())), + NULL, NULL, true); + } +} + +void drawMenuFooter(video::IVideoDriver* driver, const MenuTextures &menutextures) +{ + core::dimension2d screensize = driver->getScreenSize(); + video::ITexture *texture = menutextures.footer; + + /* If no texture, draw nothing */ + if(!texture) + return; + + f32 mult = (((f32)screensize.Width)) / + ((f32)texture->getOriginalSize().Width); + + v2s32 footersize(((f32)texture->getOriginalSize().Width) * mult, + ((f32)texture->getOriginalSize().Height) * mult); + + // Don't draw the footer if there isn't enough room + s32 free_space = (((s32)screensize.Height)-320)/2; + if (free_space > footersize.Y) { + core::rect rect(0,0,footersize.X,footersize.Y); + rect += v2s32(screensize.Width/2,screensize.Height-footersize.Y); + rect -= v2s32(footersize.X/2, 0); + + driver->draw2DImage(texture, rect, + core::rect(core::position2d(0,0), + core::dimension2di(texture->getSize())), + NULL, NULL, true); + } +} + static const SubgameSpec* getMenuGame(const MainMenuData &menudata) { for(size_t i=0; igetVideoDriver(); @@ -1578,7 +1674,7 @@ int main(int argc, char *argv[]) break; driver->beginScene(true, true, video::SColor(255,128,128,128)); - drawMenuBackground(driver, menugame); + drawMenuBackground(driver, menutextures); guienv->drawAll(); driver->endScene(); // On some computers framerate doesn't seem to be @@ -1628,18 +1724,17 @@ int main(int argc, char *argv[]) // Game can be selected in the menu menugame = getMenuGame(menudata); + menutextures.update(driver, menugame); // Clouds for the main menu bool cloud_menu_background = g_settings->getBool("menu_clouds"); if(menugame){ // If game has regular background and no overlay, don't use clouds - if(cloud_menu_background && - menugame->menuoverlay_path.empty() && - !menugame->menubackground_path.empty()){ + if(cloud_menu_background && menutextures.background && + !menutextures.overlay){ cloud_menu_background = false; } // If game game has overlay and no regular background, always draw clouds - else if(menugame->menubackground_path.empty() && - !menugame->menuoverlay_path.empty()){ + else if(menutextures.overlay && !menutextures.background){ cloud_menu_background = true; } } @@ -1663,9 +1758,13 @@ int main(int argc, char *argv[]) clouds->step(dtime*3); clouds->render(); smgr->drawAll(); - drawMenuOverlay(driver, menugame); + drawMenuOverlay(driver, menutextures); + drawMenuHeader(driver, menutextures); + drawMenuFooter(driver, menutextures); } else { - drawMenuBackground(driver, menugame); + drawMenuBackground(driver, menutextures); + drawMenuHeader(driver, menutextures); + drawMenuFooter(driver, menutextures); } guienv->drawAll(); diff --git a/src/subgame.cpp b/src/subgame.cpp index 1bee630b2..cdb546619 100644 --- a/src/subgame.cpp +++ b/src/subgame.cpp @@ -97,16 +97,12 @@ SubgameSpec findSubgame(const std::string &id) std::string game_name = getGameName(game_path); if(game_name == "") game_name = id; - std::string menubackground_path; - std::string menuoverlay_path; std::string menuicon_path; #ifndef SERVER - menubackground_path = getImagePath(game_path + DIR_DELIM + "menu" + DIR_DELIM + "background.png"); - menuoverlay_path = getImagePath(game_path + DIR_DELIM + "menu" + DIR_DELIM + "overlay.png"); menuicon_path = getImagePath(game_path + DIR_DELIM + "menu" + DIR_DELIM + "icon.png"); #endif return SubgameSpec(id, game_path, gamemod_path, mods_paths, game_name, - menubackground_path, menuoverlay_path, menuicon_path); + menuicon_path); } SubgameSpec findWorldSubgame(const std::string &world_path) diff --git a/src/subgame.h b/src/subgame.h index 2e16c2fec..4b15faa8d 100644 --- a/src/subgame.h +++ b/src/subgame.h @@ -35,8 +35,6 @@ struct SubgameSpec std::string gamemods_path; //path to mods of the game std::set addon_mods_paths; //paths to addon mods for this game std::string name; - std::string menubackground_path; - std::string menuoverlay_path; std::string menuicon_path; SubgameSpec(const std::string &id_="", @@ -44,16 +42,12 @@ struct SubgameSpec const std::string &gamemods_path_="", const std::set &addon_mods_paths_=std::set(), const std::string &name_="", - const std::string &menubackground_path_="", - const std::string &menuoverlay_path_="", const std::string &menuicon_path_=""): id(id_), path(path_), gamemods_path(gamemods_path_), addon_mods_paths(addon_mods_paths_), name(name_), - menubackground_path(menubackground_path_), - menuoverlay_path(menuoverlay_path_), menuicon_path(menuicon_path_) {} -- cgit v1.2.3 From 098692ef26d115a05c0a1e5916588c8523789556 Mon Sep 17 00:00:00 2001 From: PilzAdam Date: Sat, 4 May 2013 12:33:21 +0200 Subject: Install menu textures of minetest_game --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index ff44e9c26..ba273a0dc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -143,6 +143,7 @@ if(EXISTS ${MINETEST_GAME_SOURCE} AND IS_DIRECTORY ${MINETEST_GAME_SOURCE}) install(FILES ${MINETEST_GAME_SOURCE}/game.conf DESTINATION "${SHAREDIR}/games/minetest_game/") install(FILES ${MINETEST_GAME_SOURCE}/README.txt DESTINATION "${SHAREDIR}/games/minetest_game/") install(DIRECTORY ${MINETEST_GAME_SOURCE}/mods DESTINATION "${SHAREDIR}/games/minetest_game") + install(DIRECTORY ${MINETEST_GAME_SOURCE}/menu DESTINATION "${SHAREDIR}/games/minetest_game") endif() set(MINETEST_BUILD_GAME_SOURCE "${CMAKE_CURRENT_SOURCE_DIR}/games/build") if(EXISTS ${MINETEST_BUILD_GAME_SOURCE} AND IS_DIRECTORY ${MINETEST_BUILD_GAME_SOURCE}) -- cgit v1.2.3 From 58f036ad1d5f1928d3696730ece463ab1acb046e Mon Sep 17 00:00:00 2001 From: sapier Date: Mon, 22 Apr 2013 00:05:47 +0200 Subject: fix static data not beeing stored correctly on deactivation --- src/environment.cpp | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/environment.cpp b/src/environment.cpp index 438c9ef4f..e06b032f2 100644 --- a/src/environment.cpp +++ b/src/environment.cpp @@ -1084,8 +1084,8 @@ void ServerEnvironment::step(float dtime) { v3s16 p = *i; - /*infostream<<"Server: Block ("<getBlockNoCreateNoEx(p); if(block==NULL) @@ -1104,9 +1104,6 @@ void ServerEnvironment::step(float dtime) i != blocks_added.end(); ++i) { v3s16 p = *i; - - /*infostream<<"Server: Block ("<getBlockNoCreateNoEx(p); if(block==NULL){ @@ -1117,6 +1114,8 @@ void ServerEnvironment::step(float dtime) } activateBlock(block); + /* infostream<<"Server: Block " << PP(p) + << " became active"<m_static_objects.m_active.find(new_id) != block->m_static_objects.m_active.end()){ + if(id && block->m_static_objects.m_active.find(id) != block->m_static_objects.m_active.end()){ infostream<<"ServerEnv: WARNING: Performing hack #83274" <m_static_objects.remove(new_id); + block->m_static_objects.remove(id); } - block->m_static_objects.insert(new_id, s_obj); + //store static data + block->m_static_objects.insert(0, s_obj); // Only mark block as modified if data changed considerably if(shall_be_written) -- cgit v1.2.3 From 9a559eb8cf5c9178f89b9c3883f7d4ebec187eb9 Mon Sep 17 00:00:00 2001 From: Kahrl Date: Thu, 25 Apr 2013 18:32:18 +0200 Subject: Remove 'Meshbuffer ran out of indices' limitation --- src/mapblock_mesh.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/mapblock_mesh.cpp b/src/mapblock_mesh.cpp index f8a0b5f06..0f83e863c 100644 --- a/src/mapblock_mesh.cpp +++ b/src/mapblock_mesh.cpp @@ -1338,12 +1338,20 @@ void MeshCollector::append(const TileSpec &tile, const video::S3DVertex *vertices, u32 numVertices, const u16 *indices, u32 numIndices) { + if(numIndices > 65535) + { + dstream<<"FIXME: MeshCollector::append() called with numIndices="< 65535) + continue; p = &pp; break; @@ -1361,11 +1369,6 @@ void MeshCollector::append(const TileSpec &tile, for(u32 i=0; i 65535) - { - dstream<<"FIXME: Meshbuffer ran out of indices"<indices.push_back(j); } for(u32 i=0; i Date: Thu, 11 Apr 2013 16:32:37 -0400 Subject: Fix shader license headers to be LGPL --- README.txt | 2 +- src/shader.cpp | 8 ++++---- src/shader.h | 8 ++++---- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/README.txt b/README.txt index 74940a147..832928006 100644 --- a/README.txt +++ b/README.txt @@ -277,7 +277,7 @@ the Free Software Foundation; either version 2.1 of the License, or 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. +GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., diff --git a/src/shader.cpp b/src/shader.cpp index 62b7c99a9..9cef7f353 100644 --- a/src/shader.cpp +++ b/src/shader.cpp @@ -4,16 +4,16 @@ Copyright (C) 2013 celeron55, Perttu Ahola Copyright (C) 2013 Kahrl 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 +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 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. +GNU Lesser General Public License for more details. -You should have received a copy of the GNU General Public License along +You should have received a copy of the GNU Lesser 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. */ diff --git a/src/shader.h b/src/shader.h index a62569602..579cef635 100644 --- a/src/shader.h +++ b/src/shader.h @@ -4,16 +4,16 @@ Copyright (C) 2013 celeron55, Perttu Ahola Copyright (C) 2013 Kahrl 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 +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 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. +GNU Lesser General Public License for more details. -You should have received a copy of the GNU General Public License along +You should have received a copy of the GNU Lesser 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. */ -- cgit v1.2.3 From 7b41f54411bd49e231ab8255c96a9261161ae70c Mon Sep 17 00:00:00 2001 From: PilzAdam Date: Tue, 7 May 2013 14:40:13 +0200 Subject: Update default controls in README and pause menu --- README.txt | 18 +++++++++++------- src/guiPauseMenu.cpp | 16 ++++++++-------- 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/README.txt b/README.txt index 832928006..ae5003f77 100644 --- a/README.txt +++ b/README.txt @@ -30,13 +30,17 @@ This game is not finished Default Controls ----------------- -- WASD: Move -- Space: Jump -- E: Go down -- Shift: Sneak -- Q: Drop item -- I: Open inventory -- Mouse: Turn/look +- WASD: move +- Space: jump/climb +- Shift: sneak/go down +- Q: drop item +- I: inventory +- Mouse: turn/look +- Mouse left: dig/punch +- Mouse right: place/use +- Mouse wheel: select item +- Esc: pause menu +- T: chat - Settable in the configuration file, see the section below. Paths diff --git a/src/guiPauseMenu.cpp b/src/guiPauseMenu.cpp index b57b4a1d1..f5d323a9b 100644 --- a/src/guiPauseMenu.cpp +++ b/src/guiPauseMenu.cpp @@ -168,16 +168,16 @@ void GUIPauseMenu::regenerateGui(v2u32 screensize) core::rect rect(0, 0, 180, 240); rect = rect + v2s32(size.X/2 + 90, size.Y/2-rect.getHeight()/2); wchar_t* text = wgettext("Default Controls:\n" - "- WASD: Walk\n" - "- Mouse left: dig/hit\n" + "- WASD: move\n" + "- Space: jump/climb\n" + "- Shift: sneak/go down\n" + "- Q: drop item\n" + "- I: inventory\n" + "- Mouse: turn/look\n" + "- Mouse left: dig/punch\n" "- Mouse right: place/use\n" "- Mouse wheel: select item\n" - "- 0...9: select item\n" - "- Shift: sneak\n" - "- R: Toggle viewing all loaded chunks\n" - "- I: Inventory menu\n" - "- ESC: This menu\n" - "- T: Chat\n" + "- T: chat\n" ); Environment->addStaticText(text, rect, false, true, this, 258); delete[] text; -- cgit v1.2.3 From 0913287578504f89489df6e0573c28c7ac428805 Mon Sep 17 00:00:00 2001 From: Zeg9 Date: Wed, 8 May 2013 15:03:42 +0200 Subject: Add progress bar and clouds to loading screen --- src/game.cpp | 87 +++++++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 69 insertions(+), 18 deletions(-) diff --git a/src/game.cpp b/src/game.cpp index 3fbfad801..61e4963c0 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -395,11 +395,15 @@ PointedThing getPointedThing(Client *client, v3f player_position, /* Draws a screen with a single text on it. Text will be removed when the screen is drawn the next time. + Additionally, a progressbar can be drawn when percent is set between 0 and 100. + With drawsmgr, you can for example draw clouds */ /*gui::IGUIStaticText **/ void draw_load_screen(const std::wstring &text, - video::IVideoDriver* driver, gui::IGUIFont* font) + IrrlichtDevice* device, gui::IGUIFont* font, + int percent=-1, bool drawsmgr=false) { + video::IVideoDriver* driver = device->getVideoDriver(); v2u32 screensize = driver->getScreenSize(); const wchar_t *loadingtext = text.c_str(); core::vector2d textsize_u = font->getDimension(loadingtext); @@ -411,7 +415,28 @@ void draw_load_screen(const std::wstring &text, loadingtext, textrect, false, false); guitext->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT); - driver->beginScene(true, true, video::SColor(255,0,0,0)); + if (drawsmgr) + { + driver->beginScene(true, true, video::SColor(255,140,186,250)); + scene::ISceneManager* smgr = device->getSceneManager(); + smgr->drawAll(); + } + else + driver->beginScene(true, true, video::SColor(255,0,0,0)); + if (percent >= 0 && percent <= 100) // draw progress bar + { + core::vector2d barsize(256,32); + core::rect barrect(center-barsize/2, center+barsize/2); + driver->draw2DRectangle(video::SColor(255,255,255,255),barrect, NULL); // border + driver->draw2DRectangle(video::SColor(255,0,0,0), core::rect ( + barrect.UpperLeftCorner+1, + barrect.LowerRightCorner-1), NULL); // black inside the bar + driver->draw2DRectangle(video::SColor(255,128,128,128), core::rect ( + barrect.UpperLeftCorner+1, + core::vector2d( + barrect.LowerRightCorner.X-(barsize.X-1)+percent*(barsize.X-2)/100, + barrect.LowerRightCorner.Y-1)), NULL); // the actual progress + } guienv->drawAll(); driver->endScene(); @@ -882,7 +907,7 @@ void the_game( Draw "Loading" screen */ - draw_load_screen(L"Loading...", driver, font); + draw_load_screen(L"Loading...", device, font); // Create texture source IWritableTextureSource *tsrc = createTextureSource(device); @@ -939,7 +964,7 @@ void the_game( */ if(address == ""){ - draw_load_screen(L"Creating server...", driver, font); + draw_load_screen(L"Creating server...", device, font); infostream<<"Creating server"<clear(); + + scene::ISceneManager* smgr = device->getSceneManager(); + Clouds *clouds = 0; + if (g_settings->getBool("menu_clouds")) + { + // add clouds + clouds = new Clouds(smgr->getRootSceneNode(), + smgr, -1, rand(), 100); + clouds->update(v2f(0, 0), video::SColor(255,200,200,255)); + + // A camera to see the clouds + scene::ICameraSceneNode* camera; + camera = smgr->addCameraSceneNode(0, + v3f(0,0,0), v3f(0, 60, 100)); + camera->setFarValue(10000); + } + while(device->run()) { // Update client and server @@ -1087,21 +1129,30 @@ void the_game( // Display status std::wostringstream ss; - ss<step(frametime*3); + clouds->render(); + } + + draw_load_screen(ss.str(), device, font, client.mediaReceiveProgress()*100+0.5, clouds!=0); // Delay a bit sleep_ms(1000*frametime); time_counter += frametime; } + if (clouds != 0) + { + smgr->addToDeletionQueue(clouds); + clouds->drop(); + } } if(!got_content){ @@ -3227,7 +3278,7 @@ void the_game( */ { /*gui::IGUIStaticText *gui_shuttingdowntext = */ - draw_load_screen(L"Shutting down stuff...", driver, font); + draw_load_screen(L"Shutting down stuff...", device, font); /*driver->beginScene(true, true, video::SColor(255,0,0,0)); guienv->drawAll(); driver->endScene(); -- cgit v1.2.3 From f00cee75c153deceb0253b531228eec27d1e819b Mon Sep 17 00:00:00 2001 From: Kahrl Date: Wed, 8 May 2013 11:06:47 +0200 Subject: Fix world selection a bit (also fixes a main menu segfault) --- src/guiMainMenu.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/guiMainMenu.cpp b/src/guiMainMenu.cpp index 5d5ae1e90..48e41bb81 100644 --- a/src/guiMainMenu.cpp +++ b/src/guiMainMenu.cpp @@ -726,9 +726,11 @@ void GUIMainMenu::regenerateGui(v2u32 screensize) gui::IGUIListBox *e = Environment->addListBox(rect, this, GUI_ID_WORLD_LISTBOX); e->setDrawBackground(true); - for(std::vector::const_iterator i = m_data->worlds.begin(); - i != m_data->worlds.end(); i++){ - e->addItem(narrow_to_wide(i->name+" ["+i->gameid+"]").c_str()); + m_world_indices.clear(); + for(size_t wi = 0; wi < m_data->worlds.size(); wi++){ + const WorldSpec &spec = m_data->worlds[wi]; + e->addItem(narrow_to_wide(spec.name+" ["+spec.gameid+"]").c_str()); + m_world_indices.push_back(wi); } e->setSelected(m_data->selected_world); } @@ -1380,6 +1382,10 @@ bool GUIMainMenu::OnEvent(const SEvent& event) return true; } } + if(event.GUIEvent.EventType==gui::EGET_LISTBOX_CHANGED) + { + readInput(m_data); + } if(event.GUIEvent.EventType==gui::EGET_LISTBOX_SELECTED_AGAIN) { switch(event.GUIEvent.Caller->getID()) -- cgit v1.2.3 From 3332f606ed9d3016bd73bea2fde685df2a52b1c5 Mon Sep 17 00:00:00 2001 From: Kahrl Date: Thu, 9 May 2013 15:48:35 +0200 Subject: Drop IrrlichtDevice when running --speedtests --- src/main.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main.cpp b/src/main.cpp index 3cf6728e4..f2ff88c0c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1462,6 +1462,7 @@ int main(int argc, char *argv[]) { dstream<<"Running speed tests"<drop(); return 0; } -- cgit v1.2.3 From 3b1c3ac678157a1b7b7c17769499bec53868c9a9 Mon Sep 17 00:00:00 2001 From: Kahrl Date: Thu, 9 May 2013 15:53:29 +0200 Subject: Add --videomodes option to show available video modes --- doc/minetest.6 | 3 +++ src/main.cpp | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 60 insertions(+), 2 deletions(-) diff --git a/doc/minetest.6 b/doc/minetest.6 index b3fdd94d9..64dfdd149 100644 --- a/doc/minetest.6 +++ b/doc/minetest.6 @@ -61,6 +61,9 @@ Run dedicated server \-\-speedtests Run speed tests .TP +\-\-videomodes +List available video modes +.TP \-\-info Print more information to console .TP diff --git a/src/main.cpp b/src/main.cpp index f2ff88c0c..b87a3e6d0 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -936,6 +936,8 @@ int main(int argc, char *argv[]) allowed_options.insert(std::make_pair("gameid", ValueSpec(VALUETYPE_STRING, _("Set gameid (\"--gameid list\" prints available ones)")))); #ifndef SERVER + allowed_options.insert(std::make_pair("videomodes", ValueSpec(VALUETYPE_FLAG, + _("Show available video modes")))); allowed_options.insert(std::make_pair("speedtests", ValueSpec(VALUETYPE_FLAG, _("Run speed tests")))); allowed_options.insert(std::make_pair("address", ValueSpec(VALUETYPE_STRING, @@ -1035,7 +1037,7 @@ int main(int argc, char *argv[]) print_worldspecs(worldspecs, dstream); return 0; } - + // Print startup message infostream<(640, 480); + params.Bits = 24; + params.AntiAlias = fsaa; + params.Fullscreen = false; + params.Stencilbuffer = false; + params.Vsync = vsync; + params.EventReceiver = &receiver; + + nulldevice = createDeviceEx(params); + + if(nulldevice == 0) + return 1; + + dstream<<_("Available video modes (WxHxD):")<getVideoModeList(); + + if(videomode_list == 0){ + nulldevice->drop(); + return 1; + } + + s32 videomode_count = videomode_list->getVideoModeCount(); + core::dimension2d videomode_res; + s32 videomode_depth; + for (s32 i = 0; i < videomode_count; ++i){ + videomode_res = videomode_list->getVideoModeResolution(i); + videomode_depth = videomode_list->getVideoModeDepth(i); + dstream<getDesktopResolution(); + videomode_depth = videomode_list->getDesktopDepth(); + dstream<drop(); + + return 0; + } + + /* + Create device and exit if creation failed + */ + IrrlichtDevice *device; SIrrlichtCreationParameters params = SIrrlichtCreationParameters(); -- cgit v1.2.3 From ee1155fe6d5683578294c0ea20a8a3a0bf8ecbe4 Mon Sep 17 00:00:00 2001 From: sapier Date: Tue, 9 Apr 2013 20:14:07 +0200 Subject: Really fix itemdef memory leak --- src/itemdef.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/itemdef.cpp b/src/itemdef.cpp index 05328ea48..d660db77f 100644 --- a/src/itemdef.cpp +++ b/src/itemdef.cpp @@ -226,17 +226,11 @@ class CItemDefManager: public IWritableItemDefManager public: CItemDefManager() { - for (std::map::iterator iter = - m_item_definitions.begin(); iter != m_item_definitions.end(); - iter ++) { - delete iter->second; - } - m_item_definitions.clear(); + #ifndef SERVER m_main_thread = get_current_thread_id(); m_driver = NULL; #endif - clear(); } virtual ~CItemDefManager() @@ -260,6 +254,12 @@ public: } m_driver = NULL; #endif + for (std::map::iterator iter = + m_item_definitions.begin(); iter != m_item_definitions.end(); + iter ++) { + delete iter->second; + } + m_item_definitions.clear(); } virtual const ItemDefinition& get(const std::string &name_) const { -- cgit v1.2.3 From d859ad7ed7419ce858b4cb1fc02c681563145bdb Mon Sep 17 00:00:00 2001 From: sapier Date: Thu, 9 May 2013 23:14:32 +0200 Subject: Fix gettext memory leaks --- src/guiMainMenu.cpp | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/guiMainMenu.cpp b/src/guiMainMenu.cpp index 48e41bb81..9966b9fa7 100644 --- a/src/guiMainMenu.cpp +++ b/src/guiMainMenu.cpp @@ -483,16 +483,20 @@ void GUIMainMenu::regenerateGui(v2u32 screensize) { core::rect rect(0, 0, 390, 20); rect += m_topleft_client + v2s32(50, 10); - Environment->addStaticText(wgettext("Favorites:"), + wchar_t* text = wgettext("Favorites:"); + Environment->addStaticText(text, rect, false, true, this, GUI_ID_SERVERLIST_TITLE); + delete[] text; } } else { m_data->servers = ServerList::getOnline(); { core::rect rect(0, 0, 390, 20); rect += m_topleft_client + v2s32(50, 10); - Environment->addStaticText(wgettext("Public Server List:"), + wchar_t* text = wgettext("Public Server List:"); + Environment->addStaticText(text, rect, false, true, this, GUI_ID_SERVERLIST_TITLE); + delete[] text; } } #else @@ -500,8 +504,10 @@ void GUIMainMenu::regenerateGui(v2u32 screensize) { core::rect rect(0, 0, 390, 20); rect += m_topleft_client + v2s32(50, 10); - Environment->addStaticText(wgettext("Favorites:"), + wchar_t* text = wgettext("Favorites:"); + Environment->addStaticText(text, rect, false, true, this, GUI_ID_SERVERLIST_TITLE); + delete[] text; } #endif updateGuiServerList(); @@ -1372,9 +1378,11 @@ bool GUIMainMenu::OnEvent(const SEvent& event) readInput(&cur); if (getTab() == TAB_MULTIPLAYER && cur.address == L"") { + wchar_t* text = wgettext("Address required."); (new GUIMessageMenu(env, parent, -1, menumgr, - wgettext("Address required.")) + text) )->drop(); + delete[] text; return true; } acceptInput(); -- cgit v1.2.3 From 81c863ac4df1530123ef7952713623dadb049bec Mon Sep 17 00:00:00 2001 From: Zeg9 Date: Thu, 9 May 2013 18:23:48 +0200 Subject: Add clouds to all loading screens and better progress handling --- src/game.cpp | 188 ++++++++++++++++++++++++++++++++++++++++------------------- src/main.cpp | 44 ++++++++------ src/main.h | 8 +++ 3 files changed, 161 insertions(+), 79 deletions(-) diff --git a/src/game.cpp b/src/game.cpp index 61e4963c0..81f35d4c0 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -396,12 +396,11 @@ PointedThing getPointedThing(Client *client, v3f player_position, Draws a screen with a single text on it. Text will be removed when the screen is drawn the next time. Additionally, a progressbar can be drawn when percent is set between 0 and 100. - With drawsmgr, you can for example draw clouds */ /*gui::IGUIStaticText **/ void draw_load_screen(const std::wstring &text, IrrlichtDevice* device, gui::IGUIFont* font, - int percent=-1, bool drawsmgr=false) + float dtime=0 ,int percent=0, bool clouds=true) { video::IVideoDriver* driver = device->getVideoDriver(); v2u32 screensize = driver->getScreenSize(); @@ -415,11 +414,13 @@ void draw_load_screen(const std::wstring &text, loadingtext, textrect, false, false); guitext->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT); - if (drawsmgr) + bool cloud_menu_background = clouds && g_settings->getBool("menu_clouds"); + if (cloud_menu_background) { + g_menuclouds->step(dtime*3); + g_menuclouds->render(); driver->beginScene(true, true, video::SColor(255,140,186,250)); - scene::ISceneManager* smgr = device->getSceneManager(); - smgr->drawAll(); + g_menucloudsmgr->drawAll(); } else driver->beginScene(true, true, video::SColor(255,0,0,0)); @@ -428,7 +429,7 @@ void draw_load_screen(const std::wstring &text, core::vector2d barsize(256,32); core::rect barrect(center-barsize/2, center+barsize/2); driver->draw2DRectangle(video::SColor(255,255,255,255),barrect, NULL); // border - driver->draw2DRectangle(video::SColor(255,0,0,0), core::rect ( + driver->draw2DRectangle(video::SColor(255,64,64,64), core::rect ( barrect.UpperLeftCorner+1, barrect.LowerRightCorner-1), NULL); // black inside the bar driver->draw2DRectangle(video::SColor(255,128,128,128), core::rect ( @@ -907,7 +908,11 @@ void the_game( Draw "Loading" screen */ - draw_load_screen(L"Loading...", device, font); + { + wchar_t* text = wgettext("Loading..."); + draw_load_screen(text, device, font,0,0); + delete[] text; + } // Create texture source IWritableTextureSource *tsrc = createTextureSource(device); @@ -964,7 +969,9 @@ void the_game( */ if(address == ""){ - draw_load_screen(L"Creating server...", device, font); + wchar_t* text = wgettext("Creating server...."); + draw_load_screen(text, device, font,0,25); + delete[] text; infostream<<"Creating server"<clear(); + float fps_max = g_settings->getFloat("fps_max"); + bool cloud_menu_background = g_settings->getBool("menu_clouds"); + u32 lasttime = device->getTimer()->getTime(); while(device->run()) { + f32 dtime=0; // in seconds + if (cloud_menu_background) { + u32 time = device->getTimer()->getTime(); + if(time > lasttime) + dtime = (time - lasttime) / 1000.0; + else + dtime = 0; + lasttime = time; + } // Update client and server - client.step(frametime); + client.step(dtime); if(server != NULL) - server->step(frametime); + server->step(dtime); // End condition if(client.connectedAndInitialized()){ @@ -1049,15 +1075,37 @@ void the_game( } // Display status - std::wostringstream ss; - ss<getTimer()->getTime(); + if(time > lasttime) + busytime_u32 = time - lasttime; + else + busytime_u32 = 0; + busytime = busytime_u32 / 1000.0; + + // FPS limiter + u32 frametime_min = 1000./fps_max; + + if(busytime_u32 < frametime_min) { + u32 sleeptime = frametime_min - busytime_u32; + device->sleep(sleeptime); + } + } else { + sleep_ms(25); + } + time_counter += dtime; } } catch(con::PeerNotFoundException &e) @@ -1081,32 +1129,26 @@ void the_game( bool got_content = false; bool content_aborted = false; { - float frametime = 0.033; float time_counter = 0.0; input->clear(); - - scene::ISceneManager* smgr = device->getSceneManager(); - Clouds *clouds = 0; - if (g_settings->getBool("menu_clouds")) - { - // add clouds - clouds = new Clouds(smgr->getRootSceneNode(), - smgr, -1, rand(), 100); - clouds->update(v2f(0, 0), video::SColor(255,200,200,255)); - - // A camera to see the clouds - scene::ICameraSceneNode* camera; - camera = smgr->addCameraSceneNode(0, - v3f(0,0,0), v3f(0, 60, 100)); - camera->setFarValue(10000); - } - + float fps_max = g_settings->getFloat("fps_max"); + bool cloud_menu_background = g_settings->getBool("menu_clouds"); + u32 lasttime = device->getTimer()->getTime(); while(device->run()) { + f32 dtime=0; // in seconds + if (cloud_menu_background) { + u32 time = device->getTimer()->getTime(); + if(time > lasttime) + dtime = (time - lasttime) / 1000.0; + else + dtime = 0; + lasttime = time; + } // Update client and server - client.step(frametime); + client.step(dtime); if(server != NULL) - server->step(frametime); + server->step(dtime); // End condition if(client.texturesReceived() && @@ -1128,30 +1170,52 @@ void the_game( } // Display status - std::wostringstream ss; + std::ostringstream ss; + int progress=0; if (!client.itemdefReceived()) - ss << L"Item definitions..."; + { + ss << "Item definitions..."; + progress = 0; + } else if (!client.nodedefReceived()) - ss << L"Node definitions..."; + { + ss << "Node definitions..."; + progress = 25; + } else - ss << L"Media (" << (int)(client.mediaReceiveProgress()*100+0.5) << L"%)..."; - - if (clouds != 0) { - clouds->step(frametime*3); - clouds->render(); + ss << "Media..."; + progress = 50+client.mediaReceiveProgress()*50+0.5; } + wchar_t* text = wgettext(ss.str().c_str()); + draw_load_screen(text, device, font, dtime, progress); + delete[] text; - draw_load_screen(ss.str(), device, font, client.mediaReceiveProgress()*100+0.5, clouds!=0); - - // Delay a bit - sleep_ms(1000*frametime); - time_counter += frametime; - } - if (clouds != 0) - { - smgr->addToDeletionQueue(clouds); - clouds->drop(); + // On some computers framerate doesn't seem to be + // automatically limited + if (cloud_menu_background) { + // Time of frame without fps limit + float busytime; + u32 busytime_u32; + // not using getRealTime is necessary for wine + u32 time = device->getTimer()->getTime(); + if(time > lasttime) + busytime_u32 = time - lasttime; + else + busytime_u32 = 0; + busytime = busytime_u32 / 1000.0; + + // FPS limiter + u32 frametime_min = 1000./fps_max; + + if(busytime_u32 < frametime_min) { + u32 sleeptime = frametime_min - busytime_u32; + device->sleep(sleeptime); + } + } else { + sleep_ms(25); + } + time_counter += dtime; } } @@ -3278,7 +3342,9 @@ void the_game( */ { /*gui::IGUIStaticText *gui_shuttingdowntext = */ - draw_load_screen(L"Shutting down stuff...", device, font); + wchar_t* text = wgettext("Shutting down stuff..."); + draw_load_screen(text, device, font, 0, -1, false); + delete[] text; /*driver->beginScene(true, true, video::SColor(255,0,0,0)); guienv->drawAll(); driver->endScene(); diff --git a/src/main.cpp b/src/main.cpp index b87a3e6d0..94382ec60 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -88,6 +88,10 @@ Settings *g_settings = &main_settings; Profiler main_profiler; Profiler *g_profiler = &main_profiler; +// Menu clouds are created later +Clouds *g_menuclouds = 0; +irr::scene::ISceneManager *g_menucloudsmgr = 0; + /* Debug streams */ @@ -1569,6 +1573,19 @@ int main(int argc, char *argv[]) skin->setColor(gui::EGDC_FOCUSED_EDITABLE, video::SColor(255,96,134,49)); #endif + + // Create the menu clouds + if (!g_menucloudsmgr) + g_menucloudsmgr = smgr->createNewSceneManager(); + if (!g_menuclouds) + g_menuclouds = new Clouds(g_menucloudsmgr->getRootSceneNode(), + g_menucloudsmgr, -1, rand(), 100); + g_menuclouds->update(v2f(0, 0), video::SColor(255,200,200,255)); + scene::ICameraSceneNode* camera; + camera = g_menucloudsmgr->addCameraSceneNode(0, + v3f(0,0,0), v3f(0, 60, 100)); + camera->setFarValue(10000); + /* GUI stuff */ @@ -1744,18 +1761,6 @@ int main(int argc, char *argv[]) &g_menumgr, &menudata, g_gamecallback); menu->allowFocusRemoval(true); - // Always create clouds because they may or may not be - // needed based on the game selected - Clouds *clouds = new Clouds(smgr->getRootSceneNode(), - smgr, -1, rand(), 100); - clouds->update(v2f(0, 0), video::SColor(255,200,200,255)); - - // A camera to see the clouds - scene::ICameraSceneNode* camera; - camera = smgr->addCameraSceneNode(0, - v3f(0,0,0), v3f(0, 60, 100)); - camera->setFarValue(10000); - if(error_message != L"") { verbosestream<<"error_message = " @@ -1796,7 +1801,7 @@ int main(int argc, char *argv[]) } // Time calc for the clouds - f32 dtime; // in seconds + f32 dtime=0; // in seconds if (cloud_menu_background) { u32 time = device->getTimer()->getTime(); if(time > lasttime) @@ -1811,9 +1816,9 @@ int main(int argc, char *argv[]) if (cloud_menu_background) { // *3 otherwise the clouds would move very slowly - clouds->step(dtime*3); - clouds->render(); - smgr->drawAll(); + g_menuclouds->step(dtime*3); + g_menuclouds->render(); + g_menucloudsmgr->drawAll(); drawMenuOverlay(driver, menutextures); drawMenuHeader(driver, menutextures); drawMenuFooter(driver, menutextures); @@ -1856,8 +1861,6 @@ int main(int argc, char *argv[]) infostream<<"Dropping main menu"<drop(); - clouds->drop(); - smgr->clear(); } playername = wide_to_narrow(menudata.name); @@ -2018,6 +2021,7 @@ int main(int argc, char *argv[]) gamespec, simple_singleplayer_mode ); + smgr->clear(); } //try catch(con::PeerNotFoundException &e) @@ -2048,6 +2052,10 @@ int main(int argc, char *argv[]) } } // Menu-game loop + + g_menuclouds->drop(); + g_menucloudsmgr->drop(); + delete input; /* diff --git a/src/main.h b/src/main.h index daa8c70d2..df67a6348 100644 --- a/src/main.h +++ b/src/main.h @@ -28,6 +28,14 @@ extern Settings *g_settings; class Profiler; extern Profiler *g_profiler; +// Menu clouds +class Clouds; +extern Clouds *g_menuclouds; + +// Scene manager used for menu clouds +namespace irr{namespace scene{class ISceneManager;}} +extern irr::scene::ISceneManager *g_menucloudsmgr; + // Debug streams #include -- cgit v1.2.3 From 782d06be460e81c9fe4760c78003ac6522676e82 Mon Sep 17 00:00:00 2001 From: PilzAdam Date: Fri, 10 May 2013 19:12:02 +0200 Subject: Fix memory leak by dropping sky --- src/game.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/game.cpp b/src/game.cpp index 81f35d4c0..16d550776 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -3334,6 +3334,8 @@ void the_game( clouds->drop(); if (gui_chat_console) gui_chat_console->drop(); + if (sky) + sky->drop(); clear_particles(); /* -- cgit v1.2.3 From e5781b5e34a7f867c8dc7ebc1cbb6e81efaa9b86 Mon Sep 17 00:00:00 2001 From: PilzAdam Date: Fri, 10 May 2013 21:54:50 +0200 Subject: Fix memory leaks: delete font in main and GUIChatConsole --- src/guiChatConsole.cpp | 1 + src/main.cpp | 2 ++ 2 files changed, 3 insertions(+) diff --git a/src/guiChatConsole.cpp b/src/guiChatConsole.cpp index ec23648f8..f31e599dc 100644 --- a/src/guiChatConsole.cpp +++ b/src/guiChatConsole.cpp @@ -121,6 +121,7 @@ GUIChatConsole::GUIChatConsole( GUIChatConsole::~GUIChatConsole() { + delete m_font; } void GUIChatConsole::openConsole(f32 height) diff --git a/src/main.cpp b/src/main.cpp index 94382ec60..e2ea19295 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2063,6 +2063,8 @@ int main(int argc, char *argv[]) */ device->drop(); + delete font; + #endif // !SERVER // Update configuration file -- cgit v1.2.3 From 5068cb40ce437257b01234641779567531f132b1 Mon Sep 17 00:00:00 2001 From: PilzAdam Date: Sat, 11 May 2013 00:12:14 +0200 Subject: Fix memory leak: remove InventoryAction after sending and applying --- src/client.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/client.cpp b/src/client.cpp index 56505c66c..329496db7 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -2555,6 +2555,9 @@ void Client::inventoryAction(InventoryAction *a) Predict some local inventory changes */ a->clientApply(this, this); + + // Remove it + delete a; } ClientActiveObject * Client::getSelectedActiveObject( -- cgit v1.2.3 From 6911a7d279f487b832882d95318d432d0afbcc6b Mon Sep 17 00:00:00 2001 From: Aaron Suen Date: Thu, 9 May 2013 21:10:33 -0400 Subject: Clear custom player HUDs when emerging players. Fixes #711. --- src/server.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/server.cpp b/src/server.cpp index bf48a40d5..40a4f8a02 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -5077,6 +5077,9 @@ PlayerSAO* Server::emergePlayer(const char *name, u16 peer_id) getPlayerEffectivePrivs(player->getName()), isSingleplayer()); + /* Clean up old HUD elements from previous sessions */ + player->hud.clear(); + /* Add object to environment */ m_env->addActiveObject(playersao); -- cgit v1.2.3 From 9575b0a2a8bf6f5f24a98215cda494440e4f3831 Mon Sep 17 00:00:00 2001 From: RealBadAngel Date: Wed, 1 May 2013 13:09:10 +0200 Subject: Add code to play main_menu.ogg in main menu --- src/main.cpp | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 60 insertions(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index e2ea19295..56cb310ca 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -76,6 +76,8 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "subgame.h" #include "quicktune.h" #include "serverlist.h" +#include "sound.h" +#include "sound_openal.h" /* Settings. @@ -200,7 +202,49 @@ u32 getTime(TimePrecision prec) { return 0; return g_timegetter->getTime(prec); } +#endif + +//Client side main menu music fetcher +#ifndef SERVER +class MenuMusicFetcher: public OnDemandSoundFetcher +{ + std::set m_fetched; +public: + void fetchSounds(const std::string &name, + std::set &dst_paths, + std::set &dst_datas) + { + if(m_fetched.count(name)) + return; + m_fetched.insert(name); + std::string base; + base = porting::path_share + DIR_DELIM + "sounds"; + dst_paths.insert(base + DIR_DELIM + name + ".ogg"); + dst_paths.insert(base + DIR_DELIM + name + ".0.ogg"); + dst_paths.insert(base + DIR_DELIM + name + ".1.ogg"); + dst_paths.insert(base + DIR_DELIM + name + ".2.ogg"); + dst_paths.insert(base + DIR_DELIM + name + ".3.ogg"); + dst_paths.insert(base + DIR_DELIM + name + ".4.ogg"); + dst_paths.insert(base + DIR_DELIM + name + ".5.ogg"); + dst_paths.insert(base + DIR_DELIM + name + ".6.ogg"); + dst_paths.insert(base + DIR_DELIM + name + ".7.ogg"); + dst_paths.insert(base + DIR_DELIM + name + ".8.ogg"); + dst_paths.insert(base + DIR_DELIM + name + ".9.ogg"); + base = porting::path_user + DIR_DELIM + "sounds"; + dst_paths.insert(base + DIR_DELIM + name + ".ogg"); + dst_paths.insert(base + DIR_DELIM + name + ".0.ogg"); + dst_paths.insert(base + DIR_DELIM + name + ".1.ogg"); + dst_paths.insert(base + DIR_DELIM + name + ".2.ogg"); + dst_paths.insert(base + DIR_DELIM + name + ".3.ogg"); + dst_paths.insert(base + DIR_DELIM + name + ".4.ogg"); + dst_paths.insert(base + DIR_DELIM + name + ".5.ogg"); + dst_paths.insert(base + DIR_DELIM + name + ".6.ogg"); + dst_paths.insert(base + DIR_DELIM + name + ".7.ogg"); + dst_paths.insert(base + DIR_DELIM + name + ".8.ogg"); + dst_paths.insert(base + DIR_DELIM + name + ".9.ogg"); + } +}; #endif class StderrLogOutput: public ILogOutput @@ -1776,6 +1820,16 @@ int main(int argc, char *argv[]) // Time is in milliseconds, for clouds u32 lasttime = device->getTimer()->getTime(); + MenuMusicFetcher soundfetcher; + ISoundManager *sound = NULL; + sound = createOpenALSoundManager(&soundfetcher); + if(!sound) + sound = &dummySoundManager; + SimpleSoundSpec spec; + spec.name = "main_menu"; + spec.gain = 1; + s32 handle = sound->playSound(spec, true); + infostream<<"Created main menu"<run() && kill == false) @@ -1857,7 +1911,12 @@ int main(int argc, char *argv[]) sleep_ms(25); } } - + sound->stopSound(handle); + if(sound != &dummySoundManager){ + delete sound; + sound = NULL; + } + infostream<<"Dropping main menu"<drop(); -- cgit v1.2.3 From 2c09e8a84cac653b85bba3c85d781e24b5d6f4f8 Mon Sep 17 00:00:00 2001 From: Kahrl Date: Sun, 12 May 2013 06:28:33 +0200 Subject: Fix double free in createExtrudedMesh, reported by ptitSeb --- src/mesh.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/mesh.cpp b/src/mesh.cpp index da0dbe442..fd35a3a06 100644 --- a/src/mesh.cpp +++ b/src/mesh.cpp @@ -284,7 +284,6 @@ scene::IAnimatedMesh* createExtrudedMesh(video::ITexture *texture, if (img2 != NULL) { img1->copyTo(img2); - img1->drop(); mesh = extrudeARGB(size.Width, size.Height, (u8*) img2->lock()); img2->unlock(); -- cgit v1.2.3 From efc9329033ece46f04c5aaee3e34c49eb482eaa3 Mon Sep 17 00:00:00 2001 From: PilzAdam Date: Sat, 11 May 2013 16:08:01 +0200 Subject: Only use game filter in singleplayer tab; use menu_{background, overlay, header, footer}.png for other tabs --- src/guiMainMenu.cpp | 53 +++++++++++++++++++------------------------- src/guiMainMenu.h | 9 ++++++++ src/main.cpp | 63 ++++++++++++++++++++++++++++++++++++----------------- 3 files changed, 74 insertions(+), 51 deletions(-) diff --git a/src/guiMainMenu.cpp b/src/guiMainMenu.cpp index 9966b9fa7..36685db84 100644 --- a/src/guiMainMenu.cpp +++ b/src/guiMainMenu.cpp @@ -166,15 +166,6 @@ enum GUI_ID_GAME_BUTTON_MAX = 150, }; -enum -{ - TAB_SINGLEPLAYER=0, - TAB_MULTIPLAYER, - TAB_ADVANCED, - TAB_SETTINGS, - TAB_CREDITS -}; - GUIMainMenu::GUIMainMenu(gui::IGUIEnvironment* env, gui::IGUIElement* parent, s32 id, IMenuManager *menumgr, @@ -258,7 +249,8 @@ void GUIMainMenu::regenerateGui(v2u32 screensize) core::rect rect(0, 0, size.X, 40); rect += v2s32(4, 0); std::string t = "Minetest " VERSION_STRING; - if(m_data->selected_game_name != ""){ + if(m_data->selected_game_name != "" && + m_data->selected_tab == TAB_SINGLEPLAYER){ t += "/"; t += m_data->selected_game_name; } @@ -428,6 +420,26 @@ void GUIMainMenu::regenerateGui(v2u32 screensize) delete[] text; } changeCtype("C"); + + /* Add game selection buttons */ + video::IVideoDriver* driver = Environment->getVideoDriver(); + for(size_t i=0; igames.size(); i++){ + const SubgameSpec *spec = &m_data->games[i]; + v2s32 p(8 + i*(48+8), screensize.Y - (48+8)); + core::rect rect(0, 0, 48, 48); + rect += p; + video::ITexture *bgtexture = NULL; + if(spec->menuicon_path != "") + bgtexture = driver->getTexture(spec->menuicon_path.c_str()); + gui::IGUIButton *b = Environment->addButton(rect, this, + GUI_ID_GAME_BUTTON_FIRST+i, narrow_to_wide(wrap_rows(spec->id, 4)).c_str()); + if(bgtexture){ + b->setImage(bgtexture); + b->setText(L""); + b->setDrawBorder(false); + b->setUseAlphaChannel(true); + } + } } else if(m_data->selected_tab == TAB_MULTIPLAYER) { @@ -920,27 +932,6 @@ void GUIMainMenu::regenerateGui(v2u32 screensize) } } - /* Add game selection buttons */ - - video::IVideoDriver* driver = Environment->getVideoDriver(); - for(size_t i=0; igames.size(); i++){ - const SubgameSpec *spec = &m_data->games[i]; - v2s32 p(8 + i*(48+8), screensize.Y - (48+8)); - core::rect rect(0, 0, 48, 48); - rect += p; - video::ITexture *bgtexture = NULL; - if(spec->menuicon_path != "") - bgtexture = driver->getTexture(spec->menuicon_path.c_str()); - gui::IGUIButton *b = Environment->addButton(rect, this, - GUI_ID_GAME_BUTTON_FIRST+i, narrow_to_wide(wrap_rows(spec->id, 4)).c_str()); - if(bgtexture){ - b->setImage(bgtexture); - b->setText(L""); - b->setDrawBorder(false); - b->setUseAlphaChannel(true); - } - } - m_is_regenerating = false; } diff --git a/src/guiMainMenu.h b/src/guiMainMenu.h index 1d09c8baa..8697344c8 100644 --- a/src/guiMainMenu.h +++ b/src/guiMainMenu.h @@ -34,6 +34,15 @@ enum { SERVERLIST_PUBLIC, }; +enum +{ + TAB_SINGLEPLAYER=0, + TAB_MULTIPLAYER, + TAB_ADVANCED, + TAB_SETTINGS, + TAB_CREDITS +}; + struct MainMenuData { // These are in the native format of the gui elements diff --git a/src/main.cpp b/src/main.cpp index 56cb310ca..7f9ec1ace 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -663,12 +663,14 @@ private: struct MenuTextures { std::string current_gameid; + bool global_textures; video::ITexture *background; video::ITexture *overlay; video::ITexture *header; video::ITexture *footer; MenuTextures(): + global_textures(false), background(NULL), overlay(NULL), header(NULL), @@ -678,28 +680,49 @@ struct MenuTextures static video::ITexture* getMenuTexture(const std::string &tname, video::IVideoDriver* driver, const SubgameSpec *spec) { - std::string path; - // eg. minetest_menu_background.png (for texture packs) - std::string pack_tname = spec->id + "_menu_" + tname + ".png"; - path = getTexturePath(pack_tname); - if(path != "") - return driver->getTexture(path.c_str()); - // eg. games/minetest_game/menu/background.png - path = getImagePath(spec->path + DIR_DELIM + "menu" + DIR_DELIM + tname + ".png"); - if(path != "") - return driver->getTexture(path.c_str()); + if(spec){ + std::string path; + // eg. minetest_menu_background.png (for texture packs) + std::string pack_tname = spec->id + "_menu_" + tname + ".png"; + path = getTexturePath(pack_tname); + if(path != "") + return driver->getTexture(path.c_str()); + // eg. games/minetest_game/menu/background.png + path = getImagePath(spec->path + DIR_DELIM + "menu" + DIR_DELIM + tname + ".png"); + if(path != "") + return driver->getTexture(path.c_str()); + } else { + std::string path; + // eg. menu_background.png + std::string pack_tname = "menu_" + tname + ".png"; + path = getTexturePath(pack_tname); + if(path != "") + return driver->getTexture(path.c_str()); + } return NULL; } - void update(video::IVideoDriver* driver, const SubgameSpec *spec) + void update(video::IVideoDriver* driver, const SubgameSpec *spec, int tab) { - if(spec->id == current_gameid) - return; - current_gameid = spec->id; - background = getMenuTexture("background", driver, spec); - overlay = getMenuTexture("overlay", driver, spec); - header = getMenuTexture("header", driver, spec); - footer = getMenuTexture("footer", driver, spec); + if(tab == TAB_SINGLEPLAYER){ + if(spec->id == current_gameid) + return; + current_gameid = spec->id; + global_textures = false; + background = getMenuTexture("background", driver, spec); + overlay = getMenuTexture("overlay", driver, spec); + header = getMenuTexture("header", driver, spec); + footer = getMenuTexture("footer", driver, spec); + } else { + if(global_textures) + return; + current_gameid = ""; + global_textures = true; + background = getMenuTexture("background", driver, NULL); + overlay = getMenuTexture("overlay", driver, NULL); + header = getMenuTexture("header", driver, NULL); + footer = getMenuTexture("footer", driver, NULL); + } } }; @@ -1778,7 +1801,7 @@ int main(int argc, char *argv[]) const SubgameSpec *menugame = getMenuGame(menudata); MenuTextures menutextures; - menutextures.update(driver, menugame); + menutextures.update(driver, menugame, menudata.selected_tab); if(skip_main_menu == false) { @@ -1839,7 +1862,7 @@ int main(int argc, char *argv[]) // Game can be selected in the menu menugame = getMenuGame(menudata); - menutextures.update(driver, menugame); + menutextures.update(driver, menugame, menu->getTab()); // Clouds for the main menu bool cloud_menu_background = g_settings->getBool("menu_clouds"); if(menugame){ -- cgit v1.2.3 From bda62bd3bf7f41a25f2c6294ddc0ec144081e3ef Mon Sep 17 00:00:00 2001 From: Zeg9 Date: Sat, 11 May 2013 16:02:41 +0200 Subject: Add progress bar to item visuals preloading --- src/client.cpp | 16 +++++++++++++++- src/client.h | 2 +- src/game.cpp | 2 +- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/client.cpp b/src/client.cpp index 329496db7..929ed0eab 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -29,6 +29,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "mapblock.h" #include "settings.h" #include "profiler.h" +#include "gettext.h" #include "log.h" #include "nodemetadata.h" #include "nodedef.h" @@ -2804,7 +2805,10 @@ ClientEvent Client::getClientEvent() return m_client_event_queue.pop_front(); } -void Client::afterContentReceived() +void draw_load_screen(const std::wstring &text, + IrrlichtDevice* device, gui::IGUIFont* font, + float dtime=0 ,int percent=0, bool clouds=true); +void Client::afterContentReceived(IrrlichtDevice *device, gui::IGUIFont* font) { infostream<<"Client::afterContentReceived() started"<getBool("preload_item_visuals")) { verbosestream<<"Updating item textures and meshes"< names = m_itemdef->getAll(); + size_t size = names.size(); + size_t count = 0; + int percent = 0; for(std::set::const_iterator i = names.begin(); i != names.end(); ++i){ // Asking for these caches the result m_itemdef->getInventoryTexture(*i, this); m_itemdef->getWieldMesh(*i, this); + count++; + percent = count*100/size; + if (count%50 == 0) // only update every 50 item + draw_load_screen(text,device,font,0,percent); } + delete[] text; } // Start mesh update thread after setting up content definitions diff --git a/src/client.h b/src/client.h index 67ba6c565..f0cc55868 100644 --- a/src/client.h +++ b/src/client.h @@ -385,7 +385,7 @@ public: bool nodedefReceived() { return m_nodedef_received; } - void afterContentReceived(); + void afterContentReceived(IrrlichtDevice *device, gui::IGUIFont* font); float getRTT(void); diff --git a/src/game.cpp b/src/game.cpp index 16d550776..23e794de2 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -1232,7 +1232,7 @@ void the_game( After all content has been received: Update cached textures, meshes and materials */ - client.afterContentReceived(); + client.afterContentReceived(device,font); /* Create the camera node -- cgit v1.2.3 From 822723c2468ea763cdef447218059a5586e8e033 Mon Sep 17 00:00:00 2001 From: "Esteban I. Ruiz Moreno" Date: Sun, 14 Apr 2013 14:53:00 -0300 Subject: Add mouse_sensitivity option --- minetest.conf.example | 2 ++ src/defaultsettings.cpp | 1 + src/game.cpp | 3 ++- 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/minetest.conf.example b/minetest.conf.example index 36ef31459..7d56f99d8 100644 --- a/minetest.conf.example +++ b/minetest.conf.example @@ -151,6 +151,8 @@ #crosshair_color = (255,255,255) # Cross alpha (opaqueness, between 0 and 255) #crosshair_alpha = 255 +# Sensitivity multiplier +#mouse_sensitivity = 0.2 # Sound settings #enable_sound = true #sound_volume = 0.7 diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index 09ec45697..f270a47aa 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -117,6 +117,7 @@ void set_default_settings(Settings *settings) settings->setDefault("selectionbox_color", "(0,0,0)"); settings->setDefault("crosshair_color", "(255,255,255)"); settings->setDefault("crosshair_alpha", "255"); + settings->setDefault("mouse_sensitivity", "0.2"); settings->setDefault("enable_sound", "true"); settings->setDefault("sound_volume", "0.8"); settings->setDefault("desynchronize_mapblock_texture_animation", "true"); diff --git a/src/game.cpp b/src/game.cpp index 23e794de2..f63a4a400 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -2061,7 +2061,8 @@ void the_game( if(input->isKeyDown(irr::KEY_RIGHT)) dx += dtime * keyspeed;*/ - float d = 0.2; + float d = g_settings->getFloat("mouse_sensitivity"); + d = rangelim(d, 0.01, 100.0); camera_yaw -= dx*d; camera_pitch += dy*d; if(camera_pitch < -89.5) camera_pitch = -89.5; -- cgit v1.2.3