engineplugin.cpp
1 //------------------------------------------------------------------------------
2 // engineplugin.cpp
3 //------------------------------------------------------------------------------
4 //
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License
7 // as published by the Free Software Foundation; either version 2
8 // of the License, or (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 // 02110-1301, USA.
19 //
20 //------------------------------------------------------------------------------
21 // Copyright (C) 2011 "Blzut3" <admin@maniacsvault.net>
22 //------------------------------------------------------------------------------
23 
24 #include "gui/configuration/engineconfigpage.h"
25 #include "ini/ini.h"
26 #include "irc/entities/ircnetworkentity.h"
27 #include "pathfinder/pathfind.h"
28 #include "plugins/enginedefaults.h"
29 #include "plugins/engineplugin.h"
30 #include "serverapi/gameexefactory.h"
31 #include "serverapi/gamefile.h"
32 #include "serverapi/gamehost.h"
33 #include "serverapi/server.h"
34 #include "log.h"
35 #include "strings.h"
36 
37 #include <cstdarg>
38 #include <QPixmap>
39 
40 EnginePlugin::Data::Data()
41 {
42  // Init the defaults.
43  allowsConnectPassword = false;
44  allowsClientSlots = true;
45  allowsPlayerSlots = true;
46  allowsEmail = false;
47  allowsJoinPassword = false;
48  allowsMOTD = false;
49  allowsRConPassword = false;
50  allowsURL = false;
51  allowsUpnp = false;
52  allowsUpnpPort = false;
53  broadcast = NULL;
54  clientOnly = false;
56  defaultServerPort = 10666;
57  demoExtensionAutomatic = true;
58  demoExtension = "lmp";
59  hasIwad = true;
60  hasMapList = true;
61  icon = NULL;
62  inGameFileDownloads = false;
63  masterClient = NULL;
64  pConfig = NULL;
65  refreshThreshold = 2;
66  supportsRandomMapRotation = false;
67  valid = true;
68  version = 0;
69 }
70 
72 
73 EnginePlugin::EnginePlugin()
74 {
75  d = new Data;
76 
77  d->gameExeFactory = QSharedPointer<GameExeFactory>(new GameExeFactory(this));
78  d->difficulty = QSharedPointer<DefaultDifficultyProvider>(new DefaultDifficultyProvider());
79 
80  // At the moment I can't think of how we would support any ABI other than
81  // the current, but I suppose we might as well keep track of it?
82  d->abiVersion = DOOMSEEKER_ABI_VERSION;
83 }
84 
85 EnginePlugin::~EnginePlugin()
86 {
87  delete d->icon;
88  delete d->pConfig;
89  delete d;
90 }
91 
93 {
94  return new EngineConfigPage(this, *d->pConfig, parent);
95 }
96 
97 QList<DMFlagsSection> EnginePlugin::dmFlags() const
98 {
99  return QList<DMFlagsSection>();
100 }
101 
102 GameExeFactory* EnginePlugin::gameExe()
103 {
104  return data()->gameExeFactory.data();
105 }
106 
108 {
109  return new GameHost(this);
110 }
111 
112 QList<GameMode> EnginePlugin::gameModes() const
113 {
114  return QList<GameMode>();
115 }
116 
117 QList<GameCVar> EnginePlugin::gameModifiers() const
118 {
119  return QList<GameCVar>();
120 }
121 
122 void EnginePlugin::init(const char* name, const char* const icon[], ...)
123 {
124  d->name = name;
125  d->icon = new QPixmap(icon);
126  d->scheme = QString(d->name).replace(' ', "");
127 
128  va_list va;
129  va_start(va, icon);
130 
131  int feature;
132  while((feature = va_arg(va, int)) != EP_Done)
133  {
134  switch(feature)
135  {
136  default:
137  // Since we don't know if the feature has arguments we must abort.
138  gLog << QString("%1 plugin attempted to use unknown feature.").arg(name);
139  d->valid = false;
140  return;
141 
142  case EP_Author:
143  d->author = va_arg(va, const char*);
144  break;
145  case EP_Version:
146  d->version = va_arg(va, unsigned int);
147  break;
148 
150  d->allowsConnectPassword = true;
151  break;
152  case EP_AllowsEmail:
153  d->allowsEmail = true;
154  break;
155  case EP_AllowsURL:
156  d->allowsURL = true;
157  break;
159  d->allowsJoinPassword = true;
160  break;
162  d->allowsRConPassword = true;
163  break;
164  case EP_AllowsMOTD:
165  d->allowsMOTD = true;
166  break;
167  case EP_AllowsUpnp:
168  d->allowsUpnp = true;
169  break;
170  case EP_AllowsUpnpPort:
171  d->allowsUpnpPort = true;
172  break;
173  case EP_Broadcast:
174  d->broadcast = va_arg(va, Broadcast*);
175  break;
176  case EP_ClientOnly:
177  d->clientOnly = true;
178  break;
179  case EP_DefaultMaster:
180  d->defaultMaster = va_arg(va, const char*);
181  break;
183  d->defaultServerPort = va_arg(va, unsigned int);
184  break;
185  case EP_DemoExtension:
186  d->demoExtensionAutomatic = va_arg(va, unsigned int);
187  d->demoExtension = va_arg(va, const char*);
188  break;
190  d->difficulty = QSharedPointer<GameCVarProvider>(va_arg(va, GameCVarProvider*));
191  break;
193  d->createDMFlagsPagesAutomatic = false;
194  break;
196  d->inGameFileDownloads = true;
197  break;
198  case EP_IRCChannel:
199  {
200  // Either create an entity or put the channel in an existing one.
201  IRCNetworkEntity entity;
202  entity.setDescription(va_arg(va, const char*));
203  entity.setAddress(va_arg(va, const char*));
204  entity.autojoinChannels() << va_arg(va, const char*);
205 
206  if(d->ircChannels.contains(entity))
207  {
208  IRCNetworkEntity &existingEntity = d->ircChannels[d->ircChannels.indexOf(entity)];
209  existingEntity.autojoinChannels() << entity.autojoinChannels()[0];
210  }
211  else
212  d->ircChannels << entity;
213  break;
214  }
215  case EP_MasterClient:
216  d->masterClient = va_arg(va, MasterClient*);
217  break;
218  case EP_NoClientSlots:
219  d->allowsClientSlots = false;
220  break;
221  case EP_NoPlayerSlots:
222  d->allowsPlayerSlots = false;
223  break;
224  case EP_NoIwad:
225  d->hasIwad = false;
226  break;
227  case EP_NoMapList:
228  d->hasMapList = false;
229  break;
231  d->supportsRandomMapRotation = true;
232  break;
233  case EP_URLScheme:
234  d->scheme = va_arg(va, const char*);
235  break;
236  case EP_RefreshThreshold:
237  d->refreshThreshold = va_arg(va, unsigned int);
238  break;
239  case EP_ClientExeName:
240  d->clientExeName = va_arg(va, const char*);
241  break;
242  case EP_ServerExeName:
243  d->serverExeName = va_arg(va, const char*);
244  break;
246  {
247  QString suffixes = va_arg(va, const char*);
248  d->gameFileSearchSuffixes = suffixes.split(";", QString::SkipEmptyParts);
249  break;
250  }
251  }
252  }
253 
254  va_end(va);
255 }
256 
257 void EnginePlugin::masterHost(QString &host, unsigned short &port) const
258 {
259  QString str = d->pConfig->setting("Masterserver");
260  Strings::translateServerAddress(str, host, port, d->defaultMaster);
261 }
262 
264 {
265  QString name = data()->name;
266  name = name.toLower();
267  name = name.replace(QRegExp("\\s"), "_");
268  return name;
269 }
270 
271 ServerPtr EnginePlugin::server(const QHostAddress &address, unsigned short port) const
272 {
273  ServerPtr server = mkServer(address, port);
274  server->setSelf(server.toWeakRef());
275  return server;
276 }
277 
278 void EnginePlugin::setConfig(IniSection &ini)
279 {
280  d->pConfig = new IniSection(ini);
281 
282  ini.createSetting("Masterserver", data()->defaultMaster);
283  findGameFiles(ini);
284 
285  setupConfig(ini);
286 }
287 
289 {
290 }
291 
292 void EnginePlugin::setGameExeFactory(QSharedPointer<GameExeFactory> factory)
293 {
294  d->gameExeFactory = factory;
295 }
296 
297 void EnginePlugin::findGameFiles(IniSection &ini)
298 {
299  foreach (const GameFile &file, gameExe()->gameFiles().asQList())
300  {
301  if (!ini.hasSetting(file.configName()))
302  {
303  QString path = PathFind::findGameFile(collectKnownPaths(ini), file);
304  ini[file.configName()] = path;
305  }
306  }
307 }
308 
309 QStringList EnginePlugin::collectKnownPaths(const IniSection &ini) const
310 {
311  QStringList paths;
312  foreach (const GameFile &file, data()->gameExeFactory->gameFiles().asQList())
313  {
314  QString path = ini.retrieveSetting(file.configName()).valueString();
315  if (!path.isEmpty())
316  {
317  paths << path;
318  }
319  }
320  return paths;
321 }
322 
324 {
325 }
Disables specifying amount of player slots in create game box.
Definition: engineplugin.h:195
IniVariable createSetting(const QString &name, const QVariant &data)
Inits specified variable with specified data.
Definition: inisection.cpp:57
bool createDMFlagsPagesAutomatic
Controls behavior of "Create Game" dialog.
Definition: engineplugin.h:265
Creates GameCVar set.
Informs that the game has no notion of an IWAD.
Definition: engineplugin.h:177
QPixmap * icon
icon of the engine
Definition: engineplugin.h:242
(const char*) Author of the plugin.
Definition: engineplugin.h:86
virtual QList< DMFlagsSection > dmFlags() const
Game settings flags.
static void translateServerAddress(const QString &addressString, QString &hostname, unsigned short &port, const QString &defaultAddress)
Translates string in format "hostname:port" to atomic values.
Definition: strings.cpp:392
virtual ServerPtr mkServer(const QHostAddress &address, unsigned short port) const =0
Create an instance of local Server subclass and return a ServerPtr.
virtual void start()
Start services, init data structures.
virtual void setupConfig(IniSection &config)
Reimplement if you want to perform some ini initialization manually.
QSharedPointer< GameExeFactory > gameExeFactory
Factory of executable retrievers ExeFile objects.
Definition: engineplugin.h:277
Allows the player to join a server without downloading files through Wadseeker.
Definition: engineplugin.h:97
virtual ConfigPage * configuration(QWidget *parent)
Engine&#39;s configuration widget.
Tells the create game box that this game allows UPnP.
Definition: engineplugin.h:202
MasterClient object.
Definition: engineplugin.h:121
Signifies that servers can be created with a join password.
Definition: engineplugin.h:92
void init(const char *name, const char *const icon[],...)
virtual GameHost * gameHost()
Creates an instance of GameHost derivative class.
Signifies that a server can be created with a random map rotation.
Definition: engineplugin.h:99
const QString & configName() const
Setting name where path will be stored in plugin&#39;s IniSection.
Definition: gamefile.cpp:48
const QStringList & autojoinChannels() const
List of channels to which a /join command will be issued automatically when a connection with this ne...
File name for game&#39;s server executable if game has any.
Definition: engineplugin.h:141
void masterHost(QString &host, unsigned short &port) const
LAN Broadcast object.
Definition: engineplugin.h:117
Returns executable file retrievers from plugins to Doomseeker.
(const char*) Default ip address and port ("address:port") for master server. Requires EP_HasMasterSe...
Definition: engineplugin.h:95
(bool)auto, (const char*)extension Sets the extension taht will be used for demos (default is true an...
Definition: engineplugin.h:102
bool hasSetting(const QString &name) const
true if setting of given name exists within the section.
Definition: inisection.cpp:84
GameCVarProvider that returns difficulty levels ordered from easiest to hardest.
Definition: engineplugin.h:166
Signifies that servers can be created for remote console access.
Definition: engineplugin.h:93
IniVariable retrieveSetting(const QString &name)
Gets a variable but only if it already exists.
Definition: inisection.cpp:115
virtual ServerPtr server(const QHostAddress &address, unsigned short port) const
Creates an instance of server object from this plugin.
File name for game&#39;s client (main) executable.
Definition: engineplugin.h:130
Tells the create game box that this game allows to modify UPnP port.
Definition: engineplugin.h:216
Signifies that servers can have a message of the day.
Definition: engineplugin.h:94
Signifies that servers can provide a URL for potential wad downloads.
Definition: engineplugin.h:91
Signals the end of init parameters.
Definition: engineplugin.h:84
(quint8) The amount of time (in seconds) that must pass before a server can be requeried.
Definition: engineplugin.h:100
Signifies that servers can be created with a connection password.
Definition: engineplugin.h:89
Disables map list in create game box.
Definition: engineplugin.h:170
virtual QList< GameMode > gameModes() const
Game modes (cooperative, deathmatch, ctf).
Signifies that servers can have an administrative contact email attached.
Definition: engineplugin.h:90
Data structure that describes and defines a connection to an IRC network or server.
virtual QList< GameCVar > gameModifiers() const
Modifier that apply to all game modes (ex. instagib).
INI section representation.
Definition: inisection.h:40
Indicates that client binary serves the purpose of the client and server.
Definition: engineplugin.h:113
Creates game servers, offline games or demo playbacks.
Definition: gamehost.h:69
Game file definition allows to browse this file in configuration box.
Definition: gamefile.h:72
(unsigned int) Single version number for plugin.
Definition: engineplugin.h:87
(quint16) Default port for custom server creation.
Definition: engineplugin.h:96
QString nameCanonical() const
Derived from actual plugin name.
Abstract base for all MasterClients.
Definition: masterclient.h:49
Default search suffixes used to automatically find game files.
Definition: engineplugin.h:158
(const char*)server, (const char*)channel - Can be repeated. Default IRC channels.
Definition: engineplugin.h:98
(const char*) Overrides the URL scheme which Doomseeker sets for this plugin. By default it is the po...
Definition: engineplugin.h:101
Base for configuration pages for plugins; provides some default behavior.
QString defaultMaster
Default port on which servers for given engine are hosted.
Definition: engineplugin.h:239
Base class for configuration pages.
Definition: configpage.h:43
Disables specifying amount of client slots in create game box.
Definition: engineplugin.h:186