From 2f4a92d70192468096e35974f0725532aef837b1 Mon Sep 17 00:00:00 2001 From: Perttu Ahola Date: Sat, 3 Dec 2011 03:23:14 +0200 Subject: [PATCH] Better mod loading error handling --- src/CMakeLists.txt | 1 + src/main.cpp | 6 +++ src/mods.cpp | 98 ++++++++++++++++++++++++++++++++++++++++++++++ src/mods.h | 61 +++++++++++++++++++++++++++++ src/server.cpp | 92 ++----------------------------------------- src/servermain.cpp | 5 +++ 6 files changed, 174 insertions(+), 89 deletions(-) create mode 100644 src/mods.cpp create mode 100644 src/mods.h 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?)"< + +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 +#include +#include +#include "filesys.h" +#include "strfnd.h" + +// Get a dependency-sorted list of ModSpecs +core::list getMods(core::list &modspaths) + throw(ModError) +{ + std::queue mods_satisfied; + core::list mods_unsorted; + core::list mods_sorted; + for(core::list::Iterator i = modspaths.begin(); + i != modspaths.end(); i++){ + std::string modspath = *i; + std::vector dirlist = fs::GetDirListing(modspath); + for(u32 j=0; j 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::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::Iterator i = mods_unsorted.begin(); + i != mods_unsorted.end(); i++){ + ModSpec &mod = *i; + if(mod.unsatisfied_depends.empty()) + continue; + errs<<"mod \""<::iterator + i = mod.unsatisfied_depends.begin(); + i != mod.unsatisfied_depends.end(); i++){ + errs<<" \""<<(*i)<<"\""; + } + errs<<"."< + +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 +#include +#include + +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 depends; + std::set unsatisfied_depends; + + ModSpec(const std::string &name_="", const std::string path_="", + const std::set &depends_=std::set()): + name(name_), + path(path_), + depends(depends_), + unsatisfied_depends(depends_) + {} +}; + +// Get a dependency-sorted list of ModSpecs +core::list getMods(core::list &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<<")" @@ -833,92 +833,6 @@ u32 PIChecksum(core::list &l) return checksum; } -/* - Mods -*/ - -struct ModSpec -{ - std::string name; - std::string path; - std::set depends; - std::set unsatisfied_depends; - - ModSpec(const std::string &name_="", const std::string path_="", - const std::set &depends_=std::set()): - name(name_), - path(path_), - depends(depends_), - unsatisfied_depends(depends_) - {} -}; - -// Get a dependency-sorted list of ModSpecs -static core::list getMods(core::list &modspaths) -{ - std::queue mods_satisfied; - core::list mods_unsorted; - core::list mods_sorted; - for(core::list::Iterator i = modspaths.begin(); - i != modspaths.end(); i++){ - std::string modspath = *i; - std::vector dirlist = fs::GetDirListing(modspath); - for(u32 j=0; j 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::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::Iterator i = mods_unsorted.begin(); - i != mods_unsorted.end(); i++){ - ModSpec &mod = *i; - if(mod.unsatisfied_depends.empty()) - continue; - errorstream<<"mod \""<::iterator - i = mod.unsatisfied_depends.begin(); - i != mod.unsatisfied_depends.end(); i++){ - errorstream<<" \""<<(*i)<<"\""; - } - errorstream<<". Loading nevertheless."< mods = getMods(m_modspaths); @@ -998,7 +912,7 @@ Server::Server( if(!success){ errorstream<<"Server: Failed to load and run " <