diff options
-rw-r--r-- | src/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/game.cpp | 8 | ||||
-rw-r--r-- | src/game.h | 7 | ||||
-rw-r--r-- | src/main.cpp | 74 | ||||
-rw-r--r-- | src/server.cpp | 58 | ||||
-rw-r--r-- | src/server.h | 18 | ||||
-rw-r--r-- | src/subgame.cpp | 82 | ||||
-rw-r--r-- | src/subgame.h | 53 |
8 files changed, 232 insertions, 69 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e1cfcfa09..e9fddf8c0 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -94,6 +94,7 @@ configure_file( ) set(common_SRCS + subgame.cpp inventorymanager.cpp mods.cpp serverremoteplayer.cpp diff --git a/src/game.cpp b/src/game.cpp index 0e3f570f4..ebf5028b7 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -51,6 +51,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "itemdef.h" #include "tile.h" // For TextureSource #include "logoutputbuffer.h" +#include "subgame.h" /* Setting this to 1 enables a special camera mode that forces @@ -651,11 +652,12 @@ void the_game( std::string map_dir, std::string playername, std::string password, - std::string address, + std::string address, // If "", local server is used u16 port, std::wstring &error_message, std::string configpath, - ChatBackend &chat_backend + ChatBackend &chat_backend, + const SubgameSpec &gamespec // Used for local game ) { video::IVideoDriver* driver = device->getVideoDriver(); @@ -705,7 +707,7 @@ void the_game( if(address == ""){ draw_load_screen(L"Creating server...", driver, font); infostream<<"Creating server"<<std::endl; - server = new Server(map_dir, configpath, "mesetint"); + server = new Server(map_dir, configpath, gamespec); server->start(port); } diff --git a/src/game.h b/src/game.h index 01e955ecd..4ca5a2433 100644 --- a/src/game.h +++ b/src/game.h @@ -22,7 +22,6 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "common_irrlicht.h" #include <string> - #include "keycode.h" class KeyList : protected core::list<KeyPress> @@ -123,6 +122,7 @@ public: }; class ChatBackend; /* to avoid having to include chat.h */ +struct SubgameSpec; void the_game( bool &kill, @@ -133,11 +133,12 @@ void the_game( std::string map_dir, std::string playername, std::string password, - std::string address, + std::string address, // If "", local server is used u16 port, std::wstring &error_message, std::string configpath, - ChatBackend &chat_backend + ChatBackend &chat_backend, + const SubgameSpec &gamespec // Used for local game ); #endif diff --git a/src/main.cpp b/src/main.cpp index 8b2ef3668..00776d89c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -69,6 +69,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "log.h" #include "mods.h" #include "utility_string.h" +#include "subgame.h" /* Settings. @@ -781,6 +782,8 @@ int main(int argc, char *argv[]) "Print more information to console")); allowed_options.insert("logfile", ValueSpec(VALUETYPE_STRING, "Set logfile path (debug.txt)")); + allowed_options.insert("gameid", ValueSpec(VALUETYPE_STRING, + "Set gameid")); #ifndef SERVER allowed_options.insert("speedtests", ValueSpec(VALUETYPE_FLAG, "Run speed tests")); @@ -958,22 +961,63 @@ int main(int argc, char *argv[]) port = 30000; // Map directory - std::string map_dir = porting::path_user + DIR_DELIM + "server" + DIR_DELIM + "worlds" + DIR_DELIM + "world"; - if(cmd_args.exists("map-dir")) - map_dir = cmd_args.get("map-dir"); + std::string world_path = porting::path_user + DIR_DELIM + "server" + DIR_DELIM + "worlds" + DIR_DELIM + "world"; + if(cmd_args.exists("world")) + world_path = cmd_args.get("world"); + else if(cmd_args.exists("map-dir")) + world_path = cmd_args.get("map-dir"); else if(g_settings->exists("map-dir")) - map_dir = g_settings->get("map-dir"); + world_path = g_settings->get("map-dir"); else{ // No map-dir option was specified. // Check if the world is found from the default directory, and if // not, see if the legacy world directory exists. - std::string legacy_map_dir = porting::path_user+DIR_DELIM+".."+DIR_DELIM+"world"; - if(!fs::PathExists(map_dir) && fs::PathExists(legacy_map_dir)){ + std::string legacy_world_path = porting::path_user+DIR_DELIM+".."+DIR_DELIM+"world"; + if(!fs::PathExists(world_path) && fs::PathExists(legacy_world_path)){ errorstream<<"Warning: Using legacy world directory \"" - <<legacy_map_dir<<"\""<<std::endl; - map_dir = legacy_map_dir; + <<legacy_world_path<<"\""<<std::endl; + world_path = legacy_world_path; } } + + // Determine gameid + std::string gameid = ""; + if(cmd_args.exists("gameid")) + gameid = cmd_args.get("gameid"); + std::string world_gameid = getWorldGameId(world_path); + if(world_gameid == ""){ + if(gameid != "") + world_gameid = gameid; + else{ + world_gameid = "mesetint"; + } + } + if(gameid == "") + gameid = world_gameid; + else if(world_gameid != ""){ + if(world_gameid != gameid){ + errorstream<<"World gameid mismatch"<<std::endl; + return 1; + } + } + if(gameid == ""){ + errorstream<<"No gameid supplied or detected"<<std::endl; + return 1; + } + + infostream<<"Using gameid \""<<gameid<<"\""<<std::endl; + + SubgameSpec gamespec = findSubgame(gameid); + if(!gamespec.isValid()){ + errorstream<<"Game \""<<gameid<<"\" not found"<<std::endl; + std::set<std::string> gameids = getAvailableGameIds(); + infostream<<"Available gameids: "; + for(std::set<std::string>::const_iterator i = gameids.begin(); + i != gameids.end(); i++) + infostream<<(*i)<<" "; + infostream<<std::endl; + return 1; + } // Run dedicated server if asked to or no other option #ifdef SERVER @@ -991,7 +1035,7 @@ int main(int argc, char *argv[]) #endif // Create server - Server server(map_dir, configpath, "mesetint"); + Server server(world_path, configpath, gamespec); server.start(port); // Run server @@ -1080,9 +1124,6 @@ int main(int argc, char *argv[]) */ //driver->setMinHardwareBufferVertexCount(50); - // Set the window caption - device->setWindowCaption(L"Minetest [Main Menu]"); - // Create time getter g_timegetter = new IrrlichtTimeGetter(device); @@ -1154,6 +1195,8 @@ int main(int argc, char *argv[]) */ while(device->run() && kill == false) { + // Set the window caption + device->setWindowCaption(L"Minetest [Main Menu]"); // This is used for catching disconnects try @@ -1257,7 +1300,7 @@ int main(int argc, char *argv[]) // Delete map if requested if(menudata.delete_map) { - bool r = fs::RecursiveDeleteContent(map_dir); + bool r = fs::RecursiveDeleteContent(world_path); if(r == false) error_message = L"Delete failed"; continue; @@ -1303,14 +1346,15 @@ int main(int argc, char *argv[]) input, device, font, - map_dir, + world_path, playername, password, address, port, error_message, configpath, - chat_backend + chat_backend, + gamespec ); } //try diff --git a/src/server.cpp b/src/server.cpp index 8f40cfa5b..7b34e3554 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -830,13 +830,13 @@ void PlayerInfo::PrintLine(std::ostream *s) */ Server::Server( - std::string path_world, - std::string path_config, - std::string gamename + const std::string &path_world, + const std::string &path_config, + const SubgameSpec &gamespec ): - m_gamename(gamename), m_path_world(path_world), m_path_config(path_config), + m_gamespec(gamespec), m_env(NULL), m_con(PROTOCOL_ID, 512, CONNECTION_TIMEOUT, this), m_authmanager(path_world+DIR_DELIM+"auth.txt"), @@ -865,55 +865,38 @@ Server::Server( m_step_dtime_mutex.Init(); m_step_dtime = 0.0; + if(!gamespec.isValid()) + throw ServerError("Supplied invalid gamespec"); + // Figure out some paths // share/server m_path_share = porting::path_share + DIR_DELIM + "server"; - // game - m_path_game = porting::path_user + DIR_DELIM + "server" + DIR_DELIM - + "games" + DIR_DELIM + m_gamename; - bool user_game = true; // Game is in user's directory - if(!fs::PathExists(m_path_game)){ - m_path_game = m_path_share + DIR_DELIM + "games" + DIR_DELIM - + m_gamename; - user_game = false; - } - if(!fs::PathExists(m_path_game)){ - throw ServerError("Could not find game files for game \"" - +gamename+"\""); - } - // addons - if(!user_game) - m_path_addons.insert(m_path_share + DIR_DELIM + "addons" - + DIR_DELIM + m_gamename); - m_path_addons.insert(porting::path_user + DIR_DELIM + "server" - + DIR_DELIM + "addons" + DIR_DELIM + m_gamename); - - infostream<<"Server created for gamename=\""<<gamename<<"\""<<std::endl; - infostream<<"- path_world = "<<m_path_world<<std::endl; - infostream<<"- path_config = "<<m_path_config<<std::endl; - infostream<<"- path_game = "<<m_path_game<<std::endl; - for(std::set<std::string>::const_iterator i = m_path_addons.begin(); - i != m_path_addons.end(); i++) - infostream<<"- path_addons+= "<<(*i)<<std::endl; + + infostream<<"Server created for gameid \""<<m_gamespec.id<<"\""<<std::endl; + infostream<<"- world: "<<m_path_world<<std::endl; + infostream<<"- config: "<<m_path_config<<std::endl; + infostream<<"- game: "<<m_gamespec.path<<std::endl; + for(std::set<std::string>::const_iterator i = m_gamespec.addon_paths.begin(); + i != m_gamespec.addon_paths.end(); i++) + infostream<<"- addons: "<<(*i)<<std::endl; // Path to builtin.lua std::string builtinpath = m_path_share + DIR_DELIM + "builtin.lua"; // Add default global mod search path - m_modspaths.push_front(m_path_game + DIR_DELIM "mods"); + m_modspaths.push_front(m_gamespec.path + DIR_DELIM "mods"); // Add world mod search path m_modspaths.push_front(m_path_world + DIR_DELIM + "worldmods"); // Add addon mod search path - for(std::set<std::string>::const_iterator i = m_path_addons.begin(); - i != m_path_addons.end(); i++){ + for(std::set<std::string>::const_iterator i = m_gamespec.addon_paths.begin(); + i != m_gamespec.addon_paths.end(); i++) m_modspaths.push_front((*i) + DIR_DELIM + "mods"); - } // Print out mod search paths for(core::list<std::string>::Iterator i = m_modspaths.begin(); i != m_modspaths.end(); i++){ std::string modspath = *i; - infostream<<"- modspath += "<<modspath<<std::endl; + infostream<<"- mods: "<<modspath<<std::endl; } // Lock environment @@ -1106,7 +1089,8 @@ void Server::start(unsigned short port) <<"| Y Y \\ | | \\ ___/| | \\ ___/ \\___ \\ | | "<<std::endl <<"|__|_| /__|___| /\\___ >__| \\___ >____ > |__| "<<std::endl <<" \\/ \\/ \\/ \\/ \\/ "<<std::endl; - actionstream<<"Server listening on port "<<port<<"."<<std::endl; + actionstream<<"Server for gameid=\""<<m_gamespec.id + <<"\" listening on port "<<port<<"."<<std::endl; } void Server::stop() diff --git a/src/server.h b/src/server.h index a1d7e5df7..4948b8ba1 100644 --- a/src/server.h +++ b/src/server.h @@ -34,6 +34,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "serverremoteplayer.h" #include "mods.h" #include "inventorymanager.h" +#include "subgame.h" struct LuaState; typedef struct lua_State lua_State; class IWritableItemDefManager; @@ -405,11 +406,11 @@ public: /* NOTE: Every public method should be thread-safe */ - + Server( - std::string gamename, - std::string mapsavedir, - std::string configpath + const std::string &path_world, + const std::string &path_config, + const SubgameSpec &gamespec ); ~Server(); void start(unsigned short port); @@ -647,20 +648,15 @@ private: Variables */ - // Game name - std::string m_gamename; // World directory std::string m_path_world; // Path to user's configuration file ("" = no configuration file) std::string m_path_config; + // Subgame specification + SubgameSpec m_gamespec; // Equivalent of /usr/share/minetest/server std::string m_path_share; - // Equivalent of /usr/share/minetest/server/games/gamename - std::string m_path_game; - // Equivalent of /usr/share/minetest/server/addons/gamename - // and ~/.minetest/server/addons/gamename - std::set<std::string> m_path_addons; // Some timers float m_liquid_transform_timer; diff --git a/src/subgame.cpp b/src/subgame.cpp new file mode 100644 index 000000000..ed50d09a4 --- /dev/null +++ b/src/subgame.cpp @@ -0,0 +1,82 @@ +/* +Minetest-c55 +Copyright (C) 2012 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 "subgame.h" +#include "porting.h" +#include "filesys.h" +#include "settings.h" + +SubgameSpec findSubgame(const std::string &id) +{ + if(id == "") + return SubgameSpec(); + std::string share_server = porting::path_share + DIR_DELIM + "server"; + std::string user_server = porting::path_user + DIR_DELIM + "server"; + // Find game directory + std::string game_path = + user_server + DIR_DELIM + "games" + DIR_DELIM + id; + bool user_game = true; // Game is in user's directory + if(!fs::PathExists(game_path)){ + game_path = share_server + DIR_DELIM + "games" + DIR_DELIM + id; + user_game = false; + } + if(!fs::PathExists(game_path)) + return SubgameSpec(); + // Find addon directories + std::set<std::string> addon_paths; + if(!user_game) + addon_paths.insert(share_server + DIR_DELIM + "addons" + + DIR_DELIM + id); + addon_paths.insert(user_server + DIR_DELIM + "addons" + + DIR_DELIM + id); + return SubgameSpec(id, game_path, addon_paths); +} + +std::set<std::string> getAvailableGameIds() +{ + std::set<std::string> gameids; + std::set<std::string> gamespaths; + gamespaths.insert(porting::path_share + DIR_DELIM + "server" + + DIR_DELIM + "games"); + gamespaths.insert(porting::path_user + DIR_DELIM + "server" + + DIR_DELIM + "games"); + for(std::set<std::string>::const_iterator i = gamespaths.begin(); + i != gamespaths.end(); i++){ + std::vector<fs::DirListNode> dirlist = fs::GetDirListing(*i); + for(u32 j=0; j<dirlist.size(); j++){ + if(!dirlist[j].dir) + continue; + gameids.insert(dirlist[j].name); + } + } + return gameids; +} + +std::string getWorldGameId(const std::string &world_path) +{ + std::string conf_path = world_path + DIR_DELIM + "world.mt"; + Settings conf; + bool succeeded = conf.readConfigFile(conf_path.c_str()); + if(!succeeded) + return ""; + if(!conf.exists("gameid")) + return ""; + return conf.get("gameid"); +} + diff --git a/src/subgame.h b/src/subgame.h new file mode 100644 index 000000000..ba2f235ed --- /dev/null +++ b/src/subgame.h @@ -0,0 +1,53 @@ +/* +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. +*/ + +#ifndef SUBGAME_HEADER +#define SUBGAME_HEADER + +#include <string> +#include <set> + +struct SubgameSpec +{ + std::string id; // "" = game does not exist + std::string path; + std::set<std::string> addon_paths; + + SubgameSpec(const std::string &id_="", + const std::string &path_="", + const std::set<std::string> &addon_paths_=std::set<std::string>()): + id(id_), + path(path_), + addon_paths(addon_paths_) + {} + + bool isValid() const + { + return (id != "" && path != ""); + } +}; + +SubgameSpec findSubgame(const std::string &id); + +std::set<std::string> getAvailableGameIds(); + +std::string getWorldGameId(const std::string &world_path); + +#endif + |