command-line/world game selection

This commit is contained in:
Perttu Ahola 2012-03-11 14:54:23 +02:00
parent df190b8f87
commit 7f7fb9750d
8 changed files with 231 additions and 68 deletions

@ -94,6 +94,7 @@ configure_file(
) )
set(common_SRCS set(common_SRCS
subgame.cpp
inventorymanager.cpp inventorymanager.cpp
mods.cpp mods.cpp
serverremoteplayer.cpp serverremoteplayer.cpp

@ -51,6 +51,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "itemdef.h" #include "itemdef.h"
#include "tile.h" // For TextureSource #include "tile.h" // For TextureSource
#include "logoutputbuffer.h" #include "logoutputbuffer.h"
#include "subgame.h"
/* /*
Setting this to 1 enables a special camera mode that forces Setting this to 1 enables a special camera mode that forces
@ -651,11 +652,12 @@ void the_game(
std::string map_dir, std::string map_dir,
std::string playername, std::string playername,
std::string password, std::string password,
std::string address, std::string address, // If "", local server is used
u16 port, u16 port,
std::wstring &error_message, std::wstring &error_message,
std::string configpath, std::string configpath,
ChatBackend &chat_backend ChatBackend &chat_backend,
const SubgameSpec &gamespec // Used for local game
) )
{ {
video::IVideoDriver* driver = device->getVideoDriver(); video::IVideoDriver* driver = device->getVideoDriver();
@ -705,7 +707,7 @@ void the_game(
if(address == ""){ if(address == ""){
draw_load_screen(L"Creating server...", driver, font); draw_load_screen(L"Creating server...", driver, font);
infostream<<"Creating server"<<std::endl; infostream<<"Creating server"<<std::endl;
server = new Server(map_dir, configpath, "mesetint"); server = new Server(map_dir, configpath, gamespec);
server->start(port); server->start(port);
} }

@ -22,7 +22,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "common_irrlicht.h" #include "common_irrlicht.h"
#include <string> #include <string>
#include "keycode.h" #include "keycode.h"
class KeyList : protected core::list<KeyPress> class KeyList : protected core::list<KeyPress>
@ -123,6 +122,7 @@ public:
}; };
class ChatBackend; /* to avoid having to include chat.h */ class ChatBackend; /* to avoid having to include chat.h */
struct SubgameSpec;
void the_game( void the_game(
bool &kill, bool &kill,
@ -133,11 +133,12 @@ void the_game(
std::string map_dir, std::string map_dir,
std::string playername, std::string playername,
std::string password, std::string password,
std::string address, std::string address, // If "", local server is used
u16 port, u16 port,
std::wstring &error_message, std::wstring &error_message,
std::string configpath, std::string configpath,
ChatBackend &chat_backend ChatBackend &chat_backend,
const SubgameSpec &gamespec // Used for local game
); );
#endif #endif

@ -69,6 +69,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "log.h" #include "log.h"
#include "mods.h" #include "mods.h"
#include "utility_string.h" #include "utility_string.h"
#include "subgame.h"
/* /*
Settings. Settings.
@ -781,6 +782,8 @@ int main(int argc, char *argv[])
"Print more information to console")); "Print more information to console"));
allowed_options.insert("logfile", ValueSpec(VALUETYPE_STRING, allowed_options.insert("logfile", ValueSpec(VALUETYPE_STRING,
"Set logfile path (debug.txt)")); "Set logfile path (debug.txt)"));
allowed_options.insert("gameid", ValueSpec(VALUETYPE_STRING,
"Set gameid"));
#ifndef SERVER #ifndef SERVER
allowed_options.insert("speedtests", ValueSpec(VALUETYPE_FLAG, allowed_options.insert("speedtests", ValueSpec(VALUETYPE_FLAG,
"Run speed tests")); "Run speed tests"));
@ -958,23 +961,64 @@ int main(int argc, char *argv[])
port = 30000; port = 30000;
// Map directory // Map directory
std::string map_dir = porting::path_user + DIR_DELIM + "server" + DIR_DELIM + "worlds" + DIR_DELIM + "world"; std::string world_path = porting::path_user + DIR_DELIM + "server" + DIR_DELIM + "worlds" + DIR_DELIM + "world";
if(cmd_args.exists("map-dir")) if(cmd_args.exists("world"))
map_dir = cmd_args.get("map-dir"); 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")) else if(g_settings->exists("map-dir"))
map_dir = g_settings->get("map-dir"); world_path = g_settings->get("map-dir");
else{ else{
// No map-dir option was specified. // No map-dir option was specified.
// Check if the world is found from the default directory, and if // Check if the world is found from the default directory, and if
// not, see if the legacy world directory exists. // not, see if the legacy world directory exists.
std::string legacy_map_dir = porting::path_user+DIR_DELIM+".."+DIR_DELIM+"world"; std::string legacy_world_path = porting::path_user+DIR_DELIM+".."+DIR_DELIM+"world";
if(!fs::PathExists(map_dir) && fs::PathExists(legacy_map_dir)){ if(!fs::PathExists(world_path) && fs::PathExists(legacy_world_path)){
errorstream<<"Warning: Using legacy world directory \"" errorstream<<"Warning: Using legacy world directory \""
<<legacy_map_dir<<"\""<<std::endl; <<legacy_world_path<<"\""<<std::endl;
map_dir = legacy_map_dir; 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 // Run dedicated server if asked to or no other option
#ifdef SERVER #ifdef SERVER
bool run_dedicated_server = true; bool run_dedicated_server = true;
@ -991,7 +1035,7 @@ int main(int argc, char *argv[])
#endif #endif
// Create server // Create server
Server server(map_dir, configpath, "mesetint"); Server server(world_path, configpath, gamespec);
server.start(port); server.start(port);
// Run server // Run server
@ -1080,9 +1124,6 @@ int main(int argc, char *argv[])
*/ */
//driver->setMinHardwareBufferVertexCount(50); //driver->setMinHardwareBufferVertexCount(50);
// Set the window caption
device->setWindowCaption(L"Minetest [Main Menu]");
// Create time getter // Create time getter
g_timegetter = new IrrlichtTimeGetter(device); g_timegetter = new IrrlichtTimeGetter(device);
@ -1154,6 +1195,8 @@ int main(int argc, char *argv[])
*/ */
while(device->run() && kill == false) while(device->run() && kill == false)
{ {
// Set the window caption
device->setWindowCaption(L"Minetest [Main Menu]");
// This is used for catching disconnects // This is used for catching disconnects
try try
@ -1257,7 +1300,7 @@ int main(int argc, char *argv[])
// Delete map if requested // Delete map if requested
if(menudata.delete_map) if(menudata.delete_map)
{ {
bool r = fs::RecursiveDeleteContent(map_dir); bool r = fs::RecursiveDeleteContent(world_path);
if(r == false) if(r == false)
error_message = L"Delete failed"; error_message = L"Delete failed";
continue; continue;
@ -1303,14 +1346,15 @@ int main(int argc, char *argv[])
input, input,
device, device,
font, font,
map_dir, world_path,
playername, playername,
password, password,
address, address,
port, port,
error_message, error_message,
configpath, configpath,
chat_backend chat_backend,
gamespec
); );
} //try } //try

@ -830,13 +830,13 @@ void PlayerInfo::PrintLine(std::ostream *s)
*/ */
Server::Server( Server::Server(
std::string path_world, const std::string &path_world,
std::string path_config, const std::string &path_config,
std::string gamename const SubgameSpec &gamespec
): ):
m_gamename(gamename),
m_path_world(path_world), m_path_world(path_world),
m_path_config(path_config), m_path_config(path_config),
m_gamespec(gamespec),
m_env(NULL), m_env(NULL),
m_con(PROTOCOL_ID, 512, CONNECTION_TIMEOUT, this), m_con(PROTOCOL_ID, 512, CONNECTION_TIMEOUT, this),
m_authmanager(path_world+DIR_DELIM+"auth.txt"), m_authmanager(path_world+DIR_DELIM+"auth.txt"),
@ -865,55 +865,38 @@ Server::Server(
m_step_dtime_mutex.Init(); m_step_dtime_mutex.Init();
m_step_dtime = 0.0; m_step_dtime = 0.0;
if(!gamespec.isValid())
throw ServerError("Supplied invalid gamespec");
// Figure out some paths // Figure out some paths
// share/server // share/server
m_path_share = porting::path_share + DIR_DELIM + "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<<"Server created for gameid \""<<m_gamespec.id<<"\""<<std::endl;
infostream<<"- path_world = "<<m_path_world<<std::endl; infostream<<"- world: "<<m_path_world<<std::endl;
infostream<<"- path_config = "<<m_path_config<<std::endl; infostream<<"- config: "<<m_path_config<<std::endl;
infostream<<"- path_game = "<<m_path_game<<std::endl; infostream<<"- game: "<<m_gamespec.path<<std::endl;
for(std::set<std::string>::const_iterator i = m_path_addons.begin(); for(std::set<std::string>::const_iterator i = m_gamespec.addon_paths.begin();
i != m_path_addons.end(); i++) i != m_gamespec.addon_paths.end(); i++)
infostream<<"- path_addons+= "<<(*i)<<std::endl; infostream<<"- addons: "<<(*i)<<std::endl;
// Path to builtin.lua // Path to builtin.lua
std::string builtinpath = m_path_share + DIR_DELIM + "builtin.lua"; std::string builtinpath = m_path_share + DIR_DELIM + "builtin.lua";
// Add default global mod search path // 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 // Add world mod search path
m_modspaths.push_front(m_path_world + DIR_DELIM + "worldmods"); m_modspaths.push_front(m_path_world + DIR_DELIM + "worldmods");
// Add addon mod search path // Add addon mod search path
for(std::set<std::string>::const_iterator i = m_path_addons.begin(); for(std::set<std::string>::const_iterator i = m_gamespec.addon_paths.begin();
i != m_path_addons.end(); i++){ i != m_gamespec.addon_paths.end(); i++)
m_modspaths.push_front((*i) + DIR_DELIM + "mods"); m_modspaths.push_front((*i) + DIR_DELIM + "mods");
}
// Print out mod search paths // Print out mod search paths
for(core::list<std::string>::Iterator i = m_modspaths.begin(); for(core::list<std::string>::Iterator i = m_modspaths.begin();
i != m_modspaths.end(); i++){ i != m_modspaths.end(); i++){
std::string modspath = *i; std::string modspath = *i;
infostream<<"- modspath += "<<modspath<<std::endl; infostream<<"- mods: "<<modspath<<std::endl;
} }
// Lock environment // Lock environment
@ -1106,7 +1089,8 @@ void Server::start(unsigned short port)
<<"| Y Y \\ | | \\ ___/| | \\ ___/ \\___ \\ | | "<<std::endl <<"| Y Y \\ | | \\ ___/| | \\ ___/ \\___ \\ | | "<<std::endl
<<"|__|_| /__|___| /\\___ >__| \\___ >____ > |__| "<<std::endl <<"|__|_| /__|___| /\\___ >__| \\___ >____ > |__| "<<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() void Server::stop()

@ -34,6 +34,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "serverremoteplayer.h" #include "serverremoteplayer.h"
#include "mods.h" #include "mods.h"
#include "inventorymanager.h" #include "inventorymanager.h"
#include "subgame.h"
struct LuaState; struct LuaState;
typedef struct lua_State lua_State; typedef struct lua_State lua_State;
class IWritableItemDefManager; class IWritableItemDefManager;
@ -407,9 +408,9 @@ public:
*/ */
Server( Server(
std::string gamename, const std::string &path_world,
std::string mapsavedir, const std::string &path_config,
std::string configpath const SubgameSpec &gamespec
); );
~Server(); ~Server();
void start(unsigned short port); void start(unsigned short port);
@ -647,20 +648,15 @@ private:
Variables Variables
*/ */
// Game name
std::string m_gamename;
// World directory // World directory
std::string m_path_world; std::string m_path_world;
// Path to user's configuration file ("" = no configuration file) // Path to user's configuration file ("" = no configuration file)
std::string m_path_config; std::string m_path_config;
// Subgame specification
SubgameSpec m_gamespec;
// Equivalent of /usr/share/minetest/server // Equivalent of /usr/share/minetest/server
std::string m_path_share; 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 // Some timers
float m_liquid_transform_timer; float m_liquid_transform_timer;

82
src/subgame.cpp Normal file

@ -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");
}

53
src/subgame.h Normal file

@ -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