)
set(common_SRCS
+ subgame.cpp
inventorymanager.cpp
mods.cpp
serverremoteplayer.cpp
#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
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();
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);
}
#include "common_irrlicht.h"
#include <string>
-
#include "keycode.h"
class KeyList : protected core::list<KeyPress>
};
class ChatBackend; /* to avoid having to include chat.h */
+struct SubgameSpec;
void the_game(
bool &kill,
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
#include "log.h"
#include "mods.h"
#include "utility_string.h"
+#include "subgame.h"
/*
Settings.
"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"));
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
#endif
// Create server
- Server server(map_dir, configpath, "mesetint");
+ Server server(world_path, configpath, gamespec);
server.start(port);
// Run server
*/
//driver->setMinHardwareBufferVertexCount(50);
- // Set the window caption
- device->setWindowCaption(L"Minetest [Main Menu]");
-
// Create time getter
g_timegetter = new IrrlichtTimeGetter(device);
*/
while(device->run() && kill == false)
{
+ // Set the window caption
+ device->setWindowCaption(L"Minetest [Main Menu]");
// This is used for catching disconnects
try
// 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;
input,
device,
font,
- map_dir,
+ world_path,
playername,
password,
address,
port,
error_message,
configpath,
- chat_backend
+ chat_backend,
+ gamespec
);
} //try
*/
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"),
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
<<"| 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()
#include "serverremoteplayer.h"
#include "mods.h"
#include "inventorymanager.h"
+#include "subgame.h"
struct LuaState;
typedef struct lua_State lua_State;
class IWritableItemDefManager;
/*
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);
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;
--- /dev/null
+/*
+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");
+}
+
--- /dev/null
+/*
+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
+