diff options
author | Perttu Ahola <celeron55@gmail.com> | 2011-12-03 03:23:14 +0200 |
---|---|---|
committer | Perttu Ahola <celeron55@gmail.com> | 2011-12-03 03:23:14 +0200 |
commit | 2f4a92d70192468096e35974f0725532aef837b1 (patch) | |
tree | f8933e9d19539021d07e46ea268fa5bd4347feb7 /src | |
parent | 324c5449224e010a2cebbebff11fba2f2b96d7b0 (diff) | |
download | minetest-2f4a92d70192468096e35974f0725532aef837b1.tar.gz minetest-2f4a92d70192468096e35974f0725532aef837b1.tar.bz2 minetest-2f4a92d70192468096e35974f0725532aef837b1.zip |
Better mod loading error handling
Diffstat (limited to 'src')
-rw-r--r-- | src/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/main.cpp | 6 | ||||
-rw-r--r-- | src/mods.cpp | 98 | ||||
-rw-r--r-- | src/mods.h | 61 | ||||
-rw-r--r-- | src/server.cpp | 92 | ||||
-rw-r--r-- | src/servermain.cpp | 5 |
6 files changed, 174 insertions, 89 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index dca02f571..a0e063465 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -94,6 +94,7 @@ configure_file( ) set(common_SRCS + mods.cpp serverremoteplayer.cpp content_abm.cpp craftdef.cpp diff --git a/src/main.cpp b/src/main.cpp index c1b9d902b..83f532af1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -429,6 +429,7 @@ Doing currently: #include "settings.h" #include "profiler.h" #include "log.h" +#include "mods.h" /* Settings. @@ -1662,6 +1663,11 @@ int main(int argc, char *argv[]) errorstream<<"Socket error (port already in use?)"<<std::endl; error_message = L"Socket error (port already in use?)"; } + catch(ModError &e) + { + errorstream<<e.what()<<std::endl; + error_message = narrow_to_wide(e.what()); + } #ifdef NDEBUG catch(std::exception &e) { diff --git a/src/mods.cpp b/src/mods.cpp new file mode 100644 index 000000000..285c4cbb9 --- /dev/null +++ b/src/mods.cpp @@ -0,0 +1,98 @@ +/* +Minetest-c55 +Copyright (C) 2011 celeron55, Perttu Ahola <celeron55@gmail.com> + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "mods.h" +#include <queue> +#include <fstream> +#include <sstream> +#include "filesys.h" +#include "strfnd.h" + +// Get a dependency-sorted list of ModSpecs +core::list<ModSpec> getMods(core::list<std::string> &modspaths) + throw(ModError) +{ + std::queue<ModSpec> mods_satisfied; + core::list<ModSpec> mods_unsorted; + core::list<ModSpec> mods_sorted; + for(core::list<std::string>::Iterator i = modspaths.begin(); + i != modspaths.end(); i++){ + std::string modspath = *i; + std::vector<fs::DirListNode> dirlist = fs::GetDirListing(modspath); + for(u32 j=0; j<dirlist.size(); j++){ + if(!dirlist[j].dir) + continue; + std::string modname = dirlist[j].name; + std::string modpath = modspath + DIR_DELIM + modname; + std::set<std::string> 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, depends); + mods_unsorted.push_back(spec); + if(depends.empty()) + mods_satisfied.push(spec); + } + } + // Sort by depencencies + while(!mods_satisfied.empty()){ + ModSpec mod = mods_satisfied.front(); + mods_satisfied.pop(); + mods_sorted.push_back(mod); + for(core::list<ModSpec>::Iterator i = mods_unsorted.begin(); + i != mods_unsorted.end(); i++){ + ModSpec &mod2 = *i; + if(mod2.unsatisfied_depends.empty()) + continue; + mod2.unsatisfied_depends.erase(mod.name); + if(!mod2.unsatisfied_depends.empty()) + continue; + mods_satisfied.push(mod2); + } + } + std::ostringstream errs(std::ios::binary); + // Check unsatisfied dependencies + for(core::list<ModSpec>::Iterator i = mods_unsorted.begin(); + i != mods_unsorted.end(); i++){ + ModSpec &mod = *i; + if(mod.unsatisfied_depends.empty()) + continue; + errs<<"mod \""<<mod.name + <<"\" has unsatisfied dependencies:"; + for(std::set<std::string>::iterator + i = mod.unsatisfied_depends.begin(); + i != mod.unsatisfied_depends.end(); i++){ + errs<<" \""<<(*i)<<"\""; + } + errs<<"."<<std::endl; + mods_sorted.push_back(mod); + } + if(errs.str().size() != 0){ + throw ModError(errs.str()); + } + return mods_sorted; +} + + diff --git a/src/mods.h b/src/mods.h new file mode 100644 index 000000000..a6beb24f2 --- /dev/null +++ b/src/mods.h @@ -0,0 +1,61 @@ +/* +Minetest-c55 +Copyright (C) 2011 celeron55, Perttu Ahola <celeron55@gmail.com> + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "irrlichttypes.h" +#include <set> +#include <string> +#include <exception> + +class ModError : public std::exception +{ +public: + ModError(const std::string &s) + { + m_s = "ModError: "; + m_s += s; + } + virtual ~ModError() throw() + {} + virtual const char * what() const throw() + { + return m_s.c_str(); + } + std::string m_s; +}; + +struct ModSpec +{ + std::string name; + std::string path; + std::set<std::string> depends; + std::set<std::string> unsatisfied_depends; + + ModSpec(const std::string &name_="", const std::string path_="", + const std::set<std::string> &depends_=std::set<std::string>()): + name(name_), + path(path_), + depends(depends_), + unsatisfied_depends(depends_) + {} +}; + +// Get a dependency-sorted list of ModSpecs +core::list<ModSpec> getMods(core::list<std::string> &modspaths) + throw(ModError); + diff --git a/src/server.cpp b/src/server.cpp index 795b35b34..e4052015d 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -47,7 +47,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "craftitemdef.h" #include "mapgen.h" #include "content_abm.h" -#include "content_sao.h" // For PlayerSAO +#include "mods.h" #define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")" @@ -834,92 +834,6 @@ u32 PIChecksum(core::list<PlayerInfo> &l) } /* - Mods -*/ - -struct ModSpec -{ - std::string name; - std::string path; - std::set<std::string> depends; - std::set<std::string> unsatisfied_depends; - - ModSpec(const std::string &name_="", const std::string path_="", - const std::set<std::string> &depends_=std::set<std::string>()): - name(name_), - path(path_), - depends(depends_), - unsatisfied_depends(depends_) - {} -}; - -// Get a dependency-sorted list of ModSpecs -static core::list<ModSpec> getMods(core::list<std::string> &modspaths) -{ - std::queue<ModSpec> mods_satisfied; - core::list<ModSpec> mods_unsorted; - core::list<ModSpec> mods_sorted; - for(core::list<std::string>::Iterator i = modspaths.begin(); - i != modspaths.end(); i++){ - std::string modspath = *i; - std::vector<fs::DirListNode> dirlist = fs::GetDirListing(modspath); - for(u32 j=0; j<dirlist.size(); j++){ - if(!dirlist[j].dir) - continue; - std::string modname = dirlist[j].name; - std::string modpath = modspath + DIR_DELIM + modname; - std::set<std::string> 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, depends); - mods_unsorted.push_back(spec); - if(depends.empty()) - mods_satisfied.push(spec); - } - } - // Sort by depencencies - while(!mods_satisfied.empty()){ - ModSpec mod = mods_satisfied.front(); - mods_satisfied.pop(); - mods_sorted.push_back(mod); - for(core::list<ModSpec>::Iterator i = mods_unsorted.begin(); - i != mods_unsorted.end(); i++){ - ModSpec &mod2 = *i; - if(mod2.unsatisfied_depends.empty()) - continue; - mod2.unsatisfied_depends.erase(mod.name); - if(!mod2.unsatisfied_depends.empty()) - continue; - mods_satisfied.push(mod2); - } - } - // Check unsatisfied dependencies - for(core::list<ModSpec>::Iterator i = mods_unsorted.begin(); - i != mods_unsorted.end(); i++){ - ModSpec &mod = *i; - if(mod.unsatisfied_depends.empty()) - continue; - errorstream<<"mod \""<<mod.name - <<"\" has unsatisfied dependencies:"; - for(std::set<std::string>::iterator - i = mod.unsatisfied_depends.begin(); - i != mod.unsatisfied_depends.end(); i++){ - errorstream<<" \""<<(*i)<<"\""; - } - errorstream<<". Loading nevertheless."<<std::endl; - mods_sorted.push_back(mod); - } - return mods_sorted; -} - -/* Server */ @@ -985,7 +899,7 @@ Server::Server( if(!success){ errorstream<<"Server: Failed to load and run " <<builtinpath<<std::endl; - exit(1); + throw ModError("Failed to load and run "+builtinpath); } // Load and run "mod" scripts core::list<ModSpec> mods = getMods(m_modspaths); @@ -998,7 +912,7 @@ Server::Server( if(!success){ errorstream<<"Server: Failed to load and run " <<scriptpath<<std::endl; - exit(1); + throw ModError("Failed to load and run "+scriptpath); } } diff --git a/src/servermain.cpp b/src/servermain.cpp index 64853604b..e8a54512e 100644 --- a/src/servermain.cpp +++ b/src/servermain.cpp @@ -76,6 +76,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "log.h" #include "nodedef.h" // For init_contentfeatures #include "content_mapnode.h" // For content_mapnode_init +#include "mods.h" /* Settings. @@ -365,6 +366,10 @@ int main(int argc, char *argv[]) { errorstream<<"Connection timed out."<<std::endl; } + catch(ModError &e) + { + errorstream<<e.what()<<std::endl; + } END_DEBUG_EXCEPTION_HANDLER(errorstream) |