Mana
Loading...
Searching...
No Matches
main.cpp
Go to the documentation of this file.
1/*
2 * The Mana Client
3 * Copyright (C) 2004-2009 The Mana World Development Team
4 * Copyright (C) 2009-2012 The Mana Developers
5 *
6 * This file is part of The Mana Client.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22#include "main.h"
23
24#include "client.h"
25
26#include "utils/filesystem.h"
27#include "utils/gettext.h"
28#include "utils/stringutils.h"
29#include "utils/xml.h"
30
31#include <getopt.h>
32#include <iostream>
33
34#ifdef __MINGW32__
35#include <windows.h>
36#endif
37#if ENABLE_NLS && defined(_WIN32)
38#include <winnls.h>
39#endif
40
41#ifdef __APPLE__
42#include "utils/specialfolder.h"
43#endif
44
45static void printHelp()
46{
47 using std::endl;
48
49 std::cout
50 << _("mana [options] [mana-file]") << endl << endl
51 << _("[mana-file] : The mana file is an XML file (.mana)") << endl
52 << _(" used to set custom parameters") << endl
53 << _(" to the mana client.")
54 << endl << endl
55 << _("Options:") << endl
56 << _(" -v --version : Display the version") << endl
57 << _(" -h --help : Display this help") << endl
58 << _(" -C --config-dir : Configuration directory to use") << endl
59 << _(" -U --username : Login with this username") << endl
60 << _(" -P --password : Login with this password") << endl
61 << _(" -c --character : Login with this character") << endl
62 << _(" -s --server : Login server name or IP") << endl
63 << _(" -p --port : Login server port") << endl
64 << _(" -y --server-type : Login server type") << endl
65 << _(" --update-host : Use this update host") << endl
66 << _(" -D --default : Choose default character server and "
67 "character") << endl
68 << _(" -u --skip-update : Skip the update downloads") << endl
69 << _(" -d --data : Directory to load game data from") << endl
70 << _(" --localdata-dir : Directory to use as local data directory") << endl
71 << _(" --chat-log-dir : Chat log dir to use") << endl
72 << _(" --screenshot-dir : Directory to store screenshots") << endl
73#ifdef USE_OPENGL
74 << _(" --no-opengl : Disable OpenGL for this session") << endl
75#endif
76 ;
77}
78
79static void printVersion()
80{
81 std::cout << strprintf("%s", FULL_VERSION) << std::endl;
82}
83
84static void parseOptions(int argc, char *argv[], Client::Options &options)
85{
86 const char *optstring = "hvud:U:P:Dc:s:p:C:y:";
87
88 const struct option long_options[] = {
89 { "config-dir", required_argument, nullptr, 'C' },
90 { "data", required_argument, nullptr, 'd' },
91 { "default", no_argument, nullptr, 'D' },
92 { "password", required_argument, nullptr, 'P' },
93 { "character", required_argument, nullptr, 'c' },
94 { "help", no_argument, nullptr, 'h' },
95 { "localdata-dir", required_argument, nullptr, 'L' },
96 { "update-host", required_argument, nullptr, 'H' },
97 { "port", required_argument, nullptr, 'p' },
98 { "server", required_argument, nullptr, 's' },
99 { "skip-update", no_argument, nullptr, 'u' },
100 { "username", required_argument, nullptr, 'U' },
101 { "no-opengl", no_argument, nullptr, 'O' },
102 { "chat-log-dir", required_argument, nullptr, 'T' },
103 { "version", no_argument, nullptr, 'v' },
104 { "screenshot-dir", required_argument, nullptr, 'i' },
105 { "server-type", required_argument, nullptr, 'y' },
106 { nullptr }
107 };
108
109 while (optind < argc)
110 {
111 int result = getopt_long(argc, argv, optstring, long_options, nullptr);
112
113 if (result == -1)
114 break;
115
116 switch (result)
117 {
118 case 'C':
119 options.configDir = optarg;
120 break;
121 case 'd':
122 options.dataPath = optarg;
123 break;
124 case 'D':
125 options.chooseDefault = true;
126 break;
127 case '?': // Unknown option
128 case ':': // Missing argument
129 options.exitWithError = true;
130 [[fallthrough]];
131 case 'h':
132 options.printHelp = true;
133 break;
134 case 'H':
135 options.updateHost = optarg;
136 break;
137 case 'c':
138 options.character = optarg;
139 break;
140 case 'P':
141 options.password = optarg;
142 break;
143 case 's':
144 options.serverName = optarg;
145 break;
146 case 'p':
147 options.serverPort = static_cast<uint16_t>(atoi(optarg));
148 break;
149 case 'u':
150 options.skipUpdate = true;
151 break;
152 case 'U':
153 options.username = optarg;
154 break;
155 case 'v':
156 options.printVersion = true;
157 break;
158 case 'L':
159 options.localDataDir = optarg;
160 break;
161 case 'O':
162 options.noOpenGL = true;
163 break;
164 case 'T':
165 options.chatLogDir = optarg;
166 break;
167 case 'i':
168 options.screenshotDir = optarg;
169 break;
170 case 'y':
171 options.serverType = ServerInfo::parseType(optarg);
172 if (options.serverType == ServerType::Unknown)
173 {
174 std::cerr << _("Invalid server type, expected one of: tmwathena, manaserv") << std::endl;
175 options.exitWithError = true;
176 }
177 break;
178 }
179 }
180
181 // when there are still options left use the last
182 // one as branding file
183 if (optind < argc)
184 {
185 options.brandingPath = argv[optind];
186 }
187}
188
189static void initInternationalization()
190{
191#if ENABLE_NLS
192#ifdef _WIN32
193 // On Windows we need to set the LANG environment variable to get the
194 // correct translation, because this isn't set by default.
195 ULONG numLanguages = 0;
196 ULONG bufferSize = 0;
197 if (!GetUserPreferredUILanguages(MUI_LANGUAGE_NAME, &numLanguages, nullptr, &bufferSize))
198 return;
199 if (numLanguages == 0 || bufferSize < 2)
200 return;
201
202 std::wstring localeNamesW(bufferSize, L'\0');
203 if (!GetUserPreferredUILanguages(MUI_LANGUAGE_NAME, &numLanguages, localeNamesW.data(), &bufferSize))
204 return;
205
206 // Replace the null characters used as separators with a colon, except for
207 // the last two. Also replace - with _, since gettext expects de_DE rather
208 // than de-DE.
209 for (size_t i = 0; i < localeNamesW.size() - 2; ++i) {
210 auto &c = localeNamesW[i];
211 if (c == L'\0')
212 c = L':';
213 else if (c == L'-')
214 c = L'_';
215 }
216
217 _wputenv_s(L"LANG", localeNamesW.c_str());
218#endif // _WIN32
219
220 setlocale(LC_MESSAGES, "");
221
222#ifdef __APPLE__
223 const auto translationsDir = getResourcesLocation() + "/Translations";
224 bindtextdomain("mana", translationsDir.c_str());
225#else
226 bindtextdomain("mana", LOCALEDIR);
227#endif
228
229 bind_textdomain_codeset("mana", "UTF-8");
230 textdomain("mana");
231#endif // ENABLE_NLS
232}
233
234
235int main(int argc, char *argv[])
236{
237#if defined(DEBUG) && defined(__MINGW32__)
238 // Load mingw crash handler. Won't fail if dll is not present.
239 LoadLibrary("exchndl.dll");
240#endif
241#ifdef _WIN32
242 setlocale(LC_ALL, ".UTF8");
243#endif
244
245 // Parse command line options
246 Client::Options options;
247 parseOptions(argc, argv, options);
248
249 if (options.printVersion)
250 printVersion();
251
252 if (options.printHelp)
253 printHelp();
254
255 if (options.printHelp || options.printVersion || options.exitWithError)
256 return options.exitWithError ? 1 : 0;
257
258 initInternationalization();
259
260 // Initialize PhysicsFS
261 if (!FS::init(argv[0])) {
262 std::cout << "Error while initializing PhysFS: "
263 << FS::getLastError() << std::endl;
264 return 1;
265 }
266 atexit((void(*)()) FS::deinit);
267
268 XML::init();
269
270 Client client(options);
271 return client.exec();
272}
The core part of the client.
Definition client.h:113
int exec()
Definition client.cpp:435
static ServerType parseType(const std::string &type)
Definition serverinfo.h:73
#define _(s)
Definition gettext.h:38
int main(int argc, char *argv[])
Definition main.cpp:235
#define FULL_VERSION
Definition main.h:55
bool init(const char *argv0)
Definition filesystem.h:37
const char * getLastError()
Definition filesystem.h:252
void deinit()
Definition filesystem.h:42
void init()
Initializes the XML engine.
Definition xml.cpp:95
std::string strprintf(char const *format,...)
A safe version of sprintf that returns a std::string of the result.
A structure holding the values of various options that can be passed from the command line.
Definition client.h:120
std::string chatLogDir
Definition client.h:133
bool chooseDefault
Definition client.h:124
std::string dataPath
Definition client.h:132
ServerType serverType
Definition client.h:137
bool exitWithError
Definition client.h:126
std::string screenshotDir
Definition client.h:136
std::string brandingPath
Definition client.h:130
std::string serverName
Definition client.h:139
uint16_t serverPort
Definition client.h:140
std::string updateHost
Definition client.h:131
std::string character
Definition client.h:129
bool printVersion
Definition client.h:122
std::string localDataDir
Definition client.h:135
bool skipUpdate
Definition client.h:123
std::string username
Definition client.h:127
std::string password
Definition client.h:128
std::string configDir
Definition client.h:134