23 #include "gameclientrunner.h" 25 #include "configuration/doomseekerconfig.h" 26 #include "ini/inisection.h" 27 #include "ini/inivariable.h" 28 #include "pathfinder/pathfinder.h" 29 #include "pathfinder/wadpathfinder.h" 30 #include "plugins/engineplugin.h" 31 #include "serverapi/exefile.h" 32 #include "serverapi/gameexeretriever.h" 33 #include "serverapi/message.h" 34 #include "serverapi/server.h" 35 #include "apprunner.h" 36 #include "commandlinetokenizer.h" 39 #include <QScopedPointer> 40 #include <QStringList> 42 DClass<ServerConnectParams>
45 QString connectPassword;
47 QString inGamePassword;
67 ServerConnectParams::~ServerConnectParams()
73 return d->connectPassword;
83 return d->inGamePassword;
86 void ServerConnectParams::setConnectPassword(
const QString& val)
88 d->connectPassword = val;
91 void ServerConnectParams::setDemoName(
const QString& val)
96 void ServerConnectParams::setInGamePassword(
const QString& val)
98 d->inGamePassword = val;
101 #define BAIL_ON_ERROR(method) \ 104 if (isFatalError()) \ 111 DClass<GameClientRunner>
114 QString argBexLoading;
116 QString argConnectPassword;
117 QString argDehLoading;
118 QString argInGamePassword;
119 QString argIwadLoading;
120 QString argOptionalWadLoading;
122 QString argPwadLoading;
123 QString argDemoRecord;
126 mutable QString cachedIwadPath;
130 QList<PWad> missingPwads;
151 POLYMORPHIC_DEFINE(
void,
GameClientRunner, addModFiles, (
const QStringList &files), (files));
153 POLYMORPHIC_DEFINE(
void,
GameClientRunner, createCommandLineArguments, (), ());
155 GameClientRunner::GameClientRunner(ServerPtr server)
157 set_addConnectCommand(&GameClientRunner::addConnectCommand_default);
158 set_addGamePaths(&GameClientRunner::addGamePaths_default);
159 set_addExtra(&GameClientRunner::addExtra_default);
160 set_addInGamePassword(&GameClientRunner::addInGamePassword_default);
161 set_addIwad(&GameClientRunner::addIwad_default);
162 set_addModFiles(&GameClientRunner::addModFiles_default);
163 set_addPassword(&GameClientRunner::addPassword_default);
164 set_createCommandLineArguments(&GameClientRunner::createCommandLineArguments_default);
165 d->argBexLoading =
"-deh";
166 d->argConnect =
"-connect";
167 d->argDehLoading =
"-deh";
168 d->argIwadLoading =
"-iwad";
169 d->argOptionalWadLoading =
"-file";
170 d->argPort =
"-port";
171 d->argPwadLoading =
"-file";
172 d->argDemoRecord =
"-record";
177 GameClientRunner::~GameClientRunner()
181 void GameClientRunner::addConnectCommand_default()
183 QString address = QString(
"%1:%2").arg(d->server->address().toString()).arg(d->server->port());
184 args() << argForConnect() << address;
189 IniSection config = gConfig.iniSectionForPlugin(d->server->plugin());
190 QString customParameters = config[
"CustomParameters"];
192 args() << tokenizer.tokenize(customParameters);
197 args() << argForDemoRecord() <<
demoName();
200 void GameClientRunner::addGamePaths_default()
202 GamePaths paths = gamePaths();
203 if (!paths.isValid())
209 QDir applicationDir = paths.workingDir;
210 if (paths.workingDir.isEmpty())
212 d->joinError.setType(JoinError::ConfigurationError);
213 d->joinError.setError(tr(
"Path to working directory for game \"%1\" is empty.\n\n" 214 "Make sure the configuration for the client executable is set properly.")
218 else if (!applicationDir.exists())
220 d->joinError.setType(JoinError::ConfigurationError);
221 d->joinError.setError(tr(
"%1\n\nThis directory cannot be used as working " 222 "directory for game: %2\n\nExecutable: %3")
223 .arg(paths.workingDir, pluginName(), paths.clientExe));
227 setExecutable(paths.clientExe);
228 setWorkingDir(applicationDir.path());
231 void GameClientRunner::addInGamePassword_default()
233 if (!argForInGamePassword().isNull())
239 gLog << tr(
"BUG: Plugin doesn't specify argument for in-game " 240 "password, but the server requires such password.");
244 void GameClientRunner::addExtra_default()
248 void GameClientRunner::addIwad_default()
250 args() << argForIwadLoading() << iwadPath();
258 if (!isIwadFound() || !d->missingPwads.isEmpty())
262 d->joinError.setMissingIwad(d->server->iwad());
263 d->joinError.setType(JoinError::MissingWads);
265 d->joinError.setMissingWads(d->missingPwads);
266 foreach(
const PWad &wad, d->missingPwads)
271 d->joinError.setType(JoinError::MissingWads);
278 void GameClientRunner::addPassword_default()
280 if (!argForConnectPassword().isNull())
286 gLog << tr(
"BUG: Plugin doesn't specify argument for connect " 287 "password, but the server is passworded.");
294 for (
int i = 0; i < d->server->numWads(); ++i)
296 QString pwad = findWad(d->server->wad(i).name());
299 markPwadAsMissing(d->server->wad(i));
309 void GameClientRunner::addModFiles_default(
const QStringList &files)
311 foreach (
const QString &file, files)
313 args() << fileLoadingPrefix(file) << file;
319 QMap<QString, QStringList> groups;
320 foreach (
const QString &file, files)
322 QString prefix = fileLoadingPrefix(file);
323 groups[prefix] << file;
325 foreach (
const QString &prefix, groups.keys())
328 foreach (
const QString &file, groups[prefix])
335 QString GameClientRunner::fileLoadingPrefix(
const QString &file)
const 337 if (file.toLower().endsWith(
".deh"))
339 return argForDehLoading();
341 else if (file.toLower().endsWith(
".bex"))
343 return argForBexLoading();
345 return argForPwadLoading();
353 const QString& GameClientRunner::argForBexLoading()
const 355 return d->argBexLoading;
360 return d->argConnect;
365 return d->argConnectPassword;
370 return d->argDehLoading;
375 return d->argInGamePassword;
380 return d->argIwadLoading;
385 return d->argOptionalWadLoading;
395 return d->argPwadLoading;
400 return d->argDemoRecord;
403 bool GameClientRunner::canDownloadWadsInGame()
const 405 return d->server->plugin()->data()->inGameFileDownloads;
410 return d->connectParams.connectPassword();
413 void GameClientRunner::createCommandLineArguments_default()
415 BAIL_ON_ERROR(addGamePaths());
416 BAIL_ON_ERROR(addConnectCommand());
417 if (d->server->isLocked())
419 BAIL_ON_ERROR(addPassword());
421 if (d->server->isLockedInGame())
423 BAIL_ON_ERROR(addInGamePassword());
427 BAIL_ON_ERROR(addDemoRecordCommand());
429 BAIL_ON_ERROR(addWads());
430 BAIL_ON_ERROR(addExtra());
431 BAIL_ON_ERROR(addCustomParameters());
438 d->cli->args.clear();
439 d->connectParams = params;
443 if (d->joinError.isError())
447 createCommandLineArguments();
454 return d->connectParams.demoName();
457 QString GameClientRunner::findIwad()
const 459 return findWad(d->server->iwad().toLower());
467 GameClientRunner::GamePaths GameClientRunner::gamePaths()
472 QScopedPointer<ExeFile> exeFile(d->server->clientExe());
473 result.clientExe = exeFile->pathToExe(msg);
474 if (result.clientExe.isEmpty())
481 d->joinError.setError(msg.
contents());
485 d->joinError.setError(tr(
"Game can be installed by Doomseeker"));
490 d->joinError.setType(JoinError::ConfigurationError);
491 QString error = tr(
"Client binary cannot be obtained for %1, please " 492 "check the location given in the configuration.").arg(pluginName());
497 d->joinError.setError(error);
501 result.workingDir = exeFile->workingDirectory(msg);
507 return d->connectParams.inGamePassword();
510 bool GameClientRunner::isFatalError()
const 512 if (d->joinError.isError())
514 if (d->joinError.isMissingWadsError() && canDownloadWadsInGame())
523 bool GameClientRunner::isIwadFound()
const 525 return !d->cachedIwadPath.isEmpty();
528 const QString& GameClientRunner::iwadPath()
const 532 d->cachedIwadPath = findIwad();
534 return d->cachedIwadPath;
539 d->missingPwads << pwadName;
544 return d->pathFinder;
547 const QString& GameClientRunner::pluginName()
const 549 return d->server->plugin()->data()->name;
554 return d->connectParams;
557 void GameClientRunner::setArgForBexLoading(
const QString& arg)
559 d->argBexLoading = arg;
562 void GameClientRunner::setArgForConnect(
const QString& arg)
567 void GameClientRunner::setArgForConnectPassword(
const QString& arg)
569 d->argConnectPassword = arg;
572 void GameClientRunner::setArgForDehLoading(
const QString& arg)
574 d->argDehLoading = arg;
577 void GameClientRunner::setArgForInGamePassword(
const QString& arg)
579 d->argInGamePassword = arg;
582 void GameClientRunner::setArgForIwadLoading(
const QString& arg)
584 d->argIwadLoading = arg;
587 void GameClientRunner::setArgForOptionalWadLoading(
const QString& arg)
589 d->argOptionalWadLoading = arg;
592 void GameClientRunner::setArgForPort(
const QString& arg)
597 void GameClientRunner::setArgForPwadLoading(
const QString& arg)
599 d->argPwadLoading = arg;
602 void GameClientRunner::setArgForDemoRecord(
const QString& arg)
604 d->argDemoRecord = arg;
607 void GameClientRunner::setExecutable(
const QString &path)
609 d->cli->executable = path;
612 void GameClientRunner::setWorkingDir(
const QString &path)
614 d->cli->applicationDir = path;
627 void GameClientRunner::setupPathFinder()
629 d->pathFinder = d->server->wadPathFinder();
const QString & argForIwadLoading() const
Command line parameter that is used to set IWAD.
const QString & inGamePassword() const
"Join" password required in game.
const QString & argForOptionalWadLoading() const
Command line parameter that is used to load optional WADs.
Performs a case-insensitive (OS independent) file searches.
const QString & argForDehLoading() const
Command line parameter that is used to load a DEHACKED file.
const QString & argForConnect() const
Command line parameter that specifies the target server's IP and port.
Structure holding parameters for application launch.
Message object used to pass messages throughout the Doomseeker's system.
void addCustomParameters()
Adds custom parameters defined by user in configuration box to the args list.
ServerConnectParams & serverConnectParams()
Direct access to ServerConnectParams associated with current command line generation.
void addDemoRecordCommand()
Adds command for demo recording.
A DTO for GameClientRunner; exchanges information between main program and plugins, and allows future extensions.
const QString & demoName() const
Name of the demo if demo should be recorded, otherwise empty.
QString wadTargetDirectory() const
Directory where Doomseeker stores downloaded WADs.
QStringList & args()
Output command line arguments.
void addPwads()
Finds and adds each game modification file to the args list, marks missing files. ...
JoinError joinError() const
JoinError set by last call to createJoinCommandLine().
static const unsigned GAME_NOT_FOUND_BUT_CAN_BE_INSTALLED
Indicates that program executable was not found, but Doomseeker or plugin are capable of performing t...
const QString & argForConnectPassword() const
Command line parameter that is used to specify connection password.
Indicator of error for the server join process.
const QString & argForPort() const
Command line parameter that is used to set internet port for the game.
JoinError createJoinCommandLine(CommandLineInfo &cli, const ServerConnectParams ¶ms)
Fills out CommandLineInfo object that allows client executables to be launched.
bool isIgnore() const
True for 'Null' messages.
PathFinder & pathFinder()
Reference to a PathFinder belonging to this GameClientRunner.
QString findWad(const QString &wad) const
Finds WAD in a way that supports user configured aliases.
const QString & argForPwadLoading() const
Command line parameter that is used to load a PWAD.
const QString & connectPassword() const
Password for server connection.
void addModFiles_prefixOnce(const QStringList &files)
addModFiles() implementation that sorts files by extension and uses loading prefix arg only once for ...
void addWads()
Calls addIwad() then addPwads(), sets JoinError::MissingWads in case of failure.
static DoomseekerConfig & config()
Returns the Singleton.
const QString & argForDemoRecord() const
Command line parameter for recording a demo.
void setJoinError(const JoinError &e)
Apply error that is passed to the launching routine and can be displayed to user. ...
const QString & argForInGamePassword() const
Command line parameter that is used to specify in-game ("join") password.
INI section representation.
const QString & demoName() const
Name of demo if demo is to be recorded.
Splits command line into separate arguments in a manner appropriate for current OS.
Game executable was not found but it can be automatically installed by the plugin.
bool isOptional() const
Is this WAD required to join the server?
const QString & inGamePassword() const
In-game "join" password.
Wrapper for PathFinder that specializes in findings WADs.
unsigned type() const
Message::Type.
QString contents() const
Customized displayable contents of this Message.
Creates command line that launches the client executable of the game and connects it to a server...
void markPwadAsMissing(const PWad &pwadName)
Stores PWAD in an internal list of missing WADs.
const QString & connectPassword() const
Password for server connection.