23 #include "gameclientrunner.h" 25 #include "apprunner.h" 26 #include "commandlinetokenizer.h" 27 #include "configuration/doomseekerconfig.h" 28 #include "gui/checkwadsdlg.h" 29 #include "ini/inisection.h" 30 #include "ini/inivariable.h" 32 #include "pathfinder/pathfinder.h" 33 #include "pathfinder/wadpathfinder.h" 34 #include "plugins/engineplugin.h" 35 #include "serverapi/exefile.h" 36 #include "serverapi/gameexeretriever.h" 37 #include "serverapi/message.h" 38 #include "serverapi/server.h" 40 #include <QScopedPointer> 41 #include <QStringList> 43 DClass<ServerConnectParams>
46 QString connectPassword;
48 QString inGamePassword;
68 ServerConnectParams::~ServerConnectParams()
74 return d->connectPassword;
84 return d->inGamePassword;
87 void ServerConnectParams::setConnectPassword(
const QString &val)
89 d->connectPassword = val;
92 void ServerConnectParams::setDemoName(
const QString &val)
97 void ServerConnectParams::setInGamePassword(
const QString &val)
99 d->inGamePassword = val;
102 #define BAIL_ON_ERROR(method) \ 105 if (isFatalError()) \ 112 DClass<GameClientRunner>
115 QString argBexLoading;
117 QString argConnectPassword;
118 QString argDehLoading;
119 QString argInGamePassword;
120 QString argIwadLoading;
121 QString argOptionalWadLoading;
123 QString argPwadLoading;
124 QString argDemoRecord;
127 mutable QString cachedIwadPath;
131 QList<PWad> missingPwads;
132 QList<PWad> incompatiblePwads;
153 POLYMORPHIC_DEFINE(
void,
GameClientRunner, addModFiles, (
const QStringList &files), (files))
155 POLYMORPHIC_DEFINE(
void,
GameClientRunner, createCommandLineArguments, (), ())
157 GameClientRunner::GameClientRunner(ServerPtr server)
159 set_addConnectCommand(&GameClientRunner::addConnectCommand_default);
160 set_addGamePaths(&GameClientRunner::addGamePaths_default);
161 set_addExtra(&GameClientRunner::addExtra_default);
162 set_addInGamePassword(&GameClientRunner::addInGamePassword_default);
163 set_addIwad(&GameClientRunner::addIwad_default);
164 set_addModFiles(&GameClientRunner::addModFiles_default);
165 set_addPassword(&GameClientRunner::addPassword_default);
166 set_createCommandLineArguments(&GameClientRunner::createCommandLineArguments_default);
167 d->argBexLoading =
"-deh";
168 d->argConnect =
"-connect";
169 d->argDehLoading =
"-deh";
170 d->argIwadLoading =
"-iwad";
171 d->argOptionalWadLoading =
"-file";
172 d->argPort =
"-port";
173 d->argPwadLoading =
"-file";
174 d->argDemoRecord =
"-record";
179 GameClientRunner::~GameClientRunner()
183 void GameClientRunner::addConnectCommand_default()
185 QString address = QString(
"%1:%2").arg(d->server->address().toString()).arg(d->server->port());
186 args() << argForConnect() << address;
191 IniSection config = gConfig.iniSectionForPlugin(d->server->plugin());
192 QString customParameters = config[
"CustomParameters"];
194 args() << tokenizer.tokenize(customParameters);
199 args() << argForDemoRecord() <<
demoName();
202 void GameClientRunner::addGamePaths_default()
204 GamePaths paths = gamePaths();
205 if (!paths.isValid())
211 QDir applicationDir = paths.workingDir;
212 if (paths.workingDir.isEmpty())
214 d->joinError.setType(JoinError::ConfigurationError);
215 d->joinError.setError(tr(
"Path to working directory for game \"%1\" is empty.\n\n" 216 "Make sure the configuration for the client executable is set properly.")
220 else if (!applicationDir.exists())
222 d->joinError.setType(JoinError::ConfigurationError);
223 d->joinError.setError(tr(
"%1\n\nThis directory cannot be used as working " 224 "directory for game: %2\n\nExecutable: %3")
225 .arg(paths.workingDir, pluginName(), paths.clientExe));
229 setExecutable(paths.clientExe);
230 setWorkingDir(applicationDir.path());
233 void GameClientRunner::addInGamePassword_default()
235 if (!argForInGamePassword().isNull())
241 gLog << tr(
"BUG: Plugin doesn't specify argument for in-game " 242 "password, but the server requires such password.");
246 void GameClientRunner::addExtra_default()
250 void GameClientRunner::addIwad_default()
252 args() << argForIwadLoading() << iwadPath();
260 if (!d->incompatiblePwads.isEmpty())
262 d->joinError.setIncompatibleWads(d->incompatiblePwads);
263 d->joinError.setType(JoinError::MissingWads);
265 if (!isIwadFound() || !d->missingPwads.isEmpty())
269 d->joinError.setMissingIwad(d->server->iwad());
270 d->joinError.setType(JoinError::MissingWads);
272 d->joinError.setMissingWads(d->missingPwads);
273 for (
const PWad &wad : d->missingPwads)
278 d->joinError.setType(JoinError::MissingWads);
285 void GameClientRunner::addPassword_default()
287 if (!argForConnectPassword().isNull())
293 gLog << tr(
"BUG: Plugin doesn't specify argument for connect " 294 "password, but the server is passworded.");
301 checkWadsDlg->addWads(d->server->wads());
302 const CheckResult checkResults = checkWadsDlg->checkWads();
303 for (
const PWad &wad : checkResults.missingWads)
305 markPwadAsMissing(wad);
307 for (
const PWad &wad : checkResults.incompatibleWads)
309 markPwadAsIncompatible(wad);
312 for (
const PWad &wad : checkResults.foundWads)
314 paths << findWad(wad.
name());
319 void GameClientRunner::addModFiles_default(
const QStringList &files)
321 for (
const QString &file : files)
323 args() << fileLoadingPrefix(file) << file;
329 QMap<QString, QStringList> groups;
330 for (
const QString &file : files)
332 QString prefix = fileLoadingPrefix(file);
333 groups[prefix] << file;
335 for (
const QString &prefix : groups.keys())
338 for (
const QString &file : groups[prefix])
345 QString GameClientRunner::fileLoadingPrefix(
const QString &file)
const 347 if (file.toLower().endsWith(
".deh"))
349 return argForDehLoading();
351 else if (file.toLower().endsWith(
".bex"))
353 return argForBexLoading();
355 return argForPwadLoading();
363 const QString &GameClientRunner::argForBexLoading()
const 365 return d->argBexLoading;
370 return d->argConnect;
375 return d->argConnectPassword;
380 return d->argDehLoading;
385 return d->argInGamePassword;
390 return d->argIwadLoading;
395 return d->argOptionalWadLoading;
405 return d->argPwadLoading;
410 return d->argDemoRecord;
413 bool GameClientRunner::canDownloadWadsInGame()
const 415 return d->server->plugin()->data()->inGameFileDownloads;
420 return d->connectParams.connectPassword();
423 void GameClientRunner::createCommandLineArguments_default()
425 BAIL_ON_ERROR(addGamePaths());
426 BAIL_ON_ERROR(addConnectCommand());
427 if (d->server->isLocked())
429 BAIL_ON_ERROR(addPassword());
431 if (d->server->isLockedInGame())
433 BAIL_ON_ERROR(addInGamePassword());
437 BAIL_ON_ERROR(addDemoRecordCommand());
439 BAIL_ON_ERROR(addWads());
440 BAIL_ON_ERROR(addExtra());
441 BAIL_ON_ERROR(addCustomParameters());
448 d->cli->args.clear();
449 d->connectParams = params;
453 if (d->joinError.isError())
457 createCommandLineArguments();
464 return d->connectParams.demoName();
467 QString GameClientRunner::findIwad()
const 469 return findWad(d->server->iwad().toLower());
477 GameClientRunner::GamePaths GameClientRunner::gamePaths()
482 QScopedPointer<ExeFile> exeFile(d->server->clientExe());
483 result.clientExe = exeFile->pathToExe(msg);
484 if (result.clientExe.isEmpty())
491 d->joinError.setError(msg.
contents());
495 d->joinError.setError(tr(
"Game can be installed by Doomseeker"));
500 d->joinError.setType(JoinError::ConfigurationError);
501 QString error = tr(
"Client binary cannot be obtained for %1, please " 502 "check the location given in the configuration.").arg(pluginName());
507 d->joinError.setError(error);
511 result.workingDir = exeFile->workingDirectory(msg);
517 return d->connectParams.inGamePassword();
520 bool GameClientRunner::isFatalError()
const 522 if (d->joinError.isError())
524 if (d->joinError.isMissingWadsError() && canDownloadWadsInGame())
533 bool GameClientRunner::isIwadFound()
const 535 return !d->cachedIwadPath.isEmpty();
538 const QString &GameClientRunner::iwadPath()
const 542 d->cachedIwadPath = findIwad();
544 return d->cachedIwadPath;
549 d->missingPwads << pwadName;
554 d->incompatiblePwads << pwadName;
559 return d->pathFinder;
562 const QString &GameClientRunner::pluginName()
const 564 return d->server->plugin()->data()->name;
569 return d->connectParams;
572 void GameClientRunner::setArgForBexLoading(
const QString &arg)
574 d->argBexLoading = arg;
577 void GameClientRunner::setArgForConnect(
const QString &arg)
582 void GameClientRunner::setArgForConnectPassword(
const QString &arg)
584 d->argConnectPassword = arg;
587 void GameClientRunner::setArgForDehLoading(
const QString &arg)
589 d->argDehLoading = arg;
592 void GameClientRunner::setArgForInGamePassword(
const QString &arg)
594 d->argInGamePassword = arg;
597 void GameClientRunner::setArgForIwadLoading(
const QString &arg)
599 d->argIwadLoading = arg;
602 void GameClientRunner::setArgForOptionalWadLoading(
const QString &arg)
604 d->argOptionalWadLoading = arg;
607 void GameClientRunner::setArgForPort(
const QString &arg)
612 void GameClientRunner::setArgForPwadLoading(
const QString &arg)
614 d->argPwadLoading = arg;
617 void GameClientRunner::setArgForDemoRecord(
const QString &arg)
619 d->argDemoRecord = arg;
622 void GameClientRunner::setExecutable(
const QString &path)
624 d->cli->executable = path;
627 void GameClientRunner::setWorkingDir(
const QString &path)
629 d->cli->applicationDir.setPath(path);
642 void GameClientRunner::setupPathFinder()
644 d->pathFinder = d->server->wadPathFinder();
Manages the checking process of wads when trying to enter a server or when executing the "Find missin...
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.
Contains the results of CheckWadsDlg::CheckWads(), categorized in "incomplete", "missing" and "found"...
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.
void markPwadAsIncompatible(const PWad &pwadName)
Stores PWAD in an internal list of incompatible WADs.
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.
const QString & name() const
File name of the WAD.