/*
Minetest
Copyright (C) 2010-2013 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 Lesser General Public License as published by
the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser 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.
*/
#ifdef NDEBUG
/*#ifdef _WIN32
#pragma message ("Disabling unit tests")
#else
#warning "Disabling unit tests"
#endif*/
// Disable unit tests
#define ENABLE_TESTS 0
#else
// Enable unit tests
#define ENABLE_TESTS 1
#endif
#ifdef _MSC_VER
#ifndef SERVER // Dedicated server isn't linked with Irrlicht
#pragma comment(lib, "Irrlicht.lib")
// This would get rid of the console window
//#pragma comment(linker, "/subsystem:windows /ENTRY:mainCRTStartup")
#endif
#pragma comment(lib, "zlibwapi.lib")
#pragma comment(lib, "Shell32.lib")
#endif
#include "irrlicht.h" // createDevice
#include "main.h"
#include "mainmenumanager.h"
#include <iostream>
#include <fstream>
#include <locale.h>
#include "irrlichttypes_extrabloated.h"
#include "debug.h"
#include "test.h"
#include "clouds.h"
#include "server.h"
#include "constants.h"
#include "porting.h"
#include "gettime.h"
#include "filesys.h"
#include "config.h"
#include "version.h"
#include "guiMainMenu.h"
#include "game.h"
#include "keycode.h"
#include "tile.h"
#include "chat.h"
#include "defaultsettings.h"
#include "gettext.h"
#include "settings.h"
#include "profiler.h"
#include "log.h"
#include "mods.h"
#include "util/string.h"
#include "subgame.h"
#include "quicktune.h"
#include "serverlist.h"
#include "httpfetch.h"
#include "guiEngine.h"
#include "mapsector.h"
#include "player.h"
#include "fontengine.h"
#include "database-sqlite3.h"
#ifdef USE_LEVELDB
#include "database-leveldb.h"
#endif
#if USE_REDIS
#include "database-redis.h"
#endif
#ifdef HAVE_TOUCHSCREENGUI
#include "touchscreengui.h"
#endif
/*
Settings.
These are loaded from the config file.
*/
static Settings main_settings;
Settings *g_settings = &main_settings;
std::string g_settings_path;
// Global profiler
Profiler main_profiler;
Profiler *g_profiler = &main_profiler;
// Menu clouds are created later
Clouds *g_menuclouds = 0;
irr::scene::ISceneManager *g_menucloudsmgr = 0;
/*
Debug streams
*/
// Connection
std::ostream *dout_con_ptr = &dummyout;
std::ostream *derr_con_ptr = &verbosestream;
// Server
std::ostream *dout_server_ptr = &infostream;
std::ostream *derr_server_ptr = &errorstream;
// Client
std::ostream *dout_client_ptr = &infostream;
std::ostream *derr_client_ptr = &errorstream;
#define DEBUGFILE "debug.txt"
#define DEFAULT_SERVER_PORT 30000
typedef std::map<std::string, ValueSpec> OptionList;
struct GameParams {
u16 socket_port;
std::string world_path;
SubgameSpec game_spec;
bool is_dedicated_server;
int log_level;
};
/**********************************************************************
* Private functions
**********************************************************************/
static bool get_cmdline_opts(int argc, char *argv[], Settings *cmd_args);
static void set_allowed_options(OptionList *allowed_options);
static void print_help(const OptionList &allowed_options);
static void print_allowed_options(const OptionList &allowed_options);
static void print_version();
static void print_worldspecs(const std::vector<WorldSpec> &worldspecs,
std::ostream &os);
static void print_modified_quicktune_values();
static void list_game_ids();
static void list_worlds();
static void setup_log_params(const Settings &cmd_args);
static bool create_userdata_path();
static bool init_common(int *log_level, const Settings &cmd_args, int argc, char *argv[]);
static void startup_message();
static bool read_config_file(const Settings &cmd_args);
static void init_debug_streams(int *log_level, const Settings &cmd_args);
static bool game_configure(GameParams *game_params, const Settings &cmd_args);
static void game_configure_port(GameParams *game_params, const Settings &cmd_args);
static bool game_configure_world(GameParams *game_params, const Settings &cmd_args);
static bool get_world_from_cmdline(GameParams *game_params, const Settings &cmd_args);
static bool get_world_from_config(GameParams *game_params, const Settings &cmd_args);
static bool auto_select_world(GameParams *game_params);
static std::string get_clean_world_path(const std::string &path);
static bool game_configure_subgame(GameParams *game_params, const Settings &cmd_args);
static bool get_game_from_cmdline(GameParams *game_params, const Settings &cmd_args);
static bool determine_subgame(GameParams *game_params);
static bool run_dedicated_server(const GameParams &game_params, const Settings &cmd_args);
static bool migrate_database(const GameParams &game_params, const Settings &cmd_args,
Server *server);
#ifndef SERVER
static bool print_video_modes();
static void speed_tests();
#endif
/**********************************************************************/
#ifndef SERVER
/*
Random stuff
*/
/* mainmenumanager.h */
gui::IGUIEnvironment* guienv = NULL;
gui::IGUIStaticText *guiroot = NULL;
MainMenuManager g_menumgr;
bool noMenuActive()
{
return (g_menumgr.menuCount() == 0);
}
// Passed to menus to allow disconnecting and exiting
MainGameCallback *g_gamecallback = NULL;
#endif
/*
gettime.h implementation
*/
#ifdef SERVER
u32 getTimeMs()
{
/* Use imprecise system calls directly (from porting.h) */
return porting::getTime(PRECISION_MILLI);
}
u32 getTime(TimePrecision prec)
{
return porting::getTime(prec);
}
#else
// A small helper class
class TimeGetter
{
public:
virtual u32 getTime(TimePrecision prec) = 0;
};
// A precise irrlicht one
class IrrlichtTimeGetter: public TimeGetter
{
public:
IrrlichtTimeGetter(IrrlichtDevice *device):
m_device(device)
{}
u32 getTime(TimePrecision prec)
{
if (prec == PRECISION_MILLI) {
if (m_device == NULL)
return 0;
return m_device->getTimer()->getRealTime();
} else {
return porting::getTime(prec);
}
}
private:
IrrlichtDevice *m_device;
};
// Not so precise one which works without irrlicht
class SimpleTimeGetter: public TimeGetter
{
public:
u32 getTime(TimePrecision prec)
{
return porting::getTime(prec);
}
};
// A pointer to a global instance of the time getter
// TODO: why?
TimeGetter *g_timegetter = NULL;
u32 getTimeMs()
{
if (g_timegetter == NULL)
return 0;
return g_timegetter->getTime(PRECISION_MILLI);
}
u32 getTime(TimePrecision prec) {
if (g_timegetter == NULL)
return 0;
return g_timegetter->getTime(prec);
}
#endif
class StderrLogOutput: public ILogOutput
{
public:
/* line: Full line with timestamp, level and thread */
void printLog(const std::string &line)
{
std::cerr << line << std::endl;
}
} main_stderr_log_out;
class DstreamNoStderrLogOutput: public ILogOutput
{
public:
/* line: Full line with timestamp, level and thread */
void printLog(const std::string &line)
{
dstream_no_stderr << line << std::endl;
}
} main_dstream_no_stderr_log_out;
#ifndef SERVER
/*
Event handler for Irrlicht
NOTE: Everything possible should be moved out from here,
probably to InputHandler and the_game
*/
class MyEventReceiver : public IEventReceiver
{
public:
// This is the one method that we have to implement
virtual bool OnEvent(const SEvent& event)
{
/*
React to nothing here if a menu is active
*/
if (noMenuActive() == false) {
#ifdef HAVE_TOUCHSCREENGUI
if (m_touchscreengui != 0) {
m_touchscreengui->Toggle(false);
}
#endif
|