serverstructs.cpp
1 //------------------------------------------------------------------------------
2 // serverstructs.cpp
3 //------------------------------------------------------------------------------
4 //
5 // This library is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU Lesser General Public
7 // License as published by the Free Software Foundation; either
8 // version 2.1 of the License, or (at your option) any later version.
9 //
10 // This library 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 GNU
13 // Lesser General Public License for more details.
14 //
15 // You should have received a copy of the GNU Lesser General Public
16 // License along with this library; 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) 2014 "Zalewa" <zalewapl@gmail.com>
22 //------------------------------------------------------------------------------
23 #include "serverstructs.h"
24 #include "wadseeker/entities/checksum.h"
25 #include "wadseeker/entities/hash.h"
26 #include "wadseeker/entities/modfile.h"
27 #include <QRegExp>
28 #include <QVector>
29 
30 
31 static QString coerceInternalName(const QString &name)
32 {
33  return name.toLower().remove(QRegExp("[^a-z0-9]"));
34 }
35 
36 
37 DClass<DMFlag>
38 {
39 public:
40  QString name;
41  unsigned value;
42  QString internalName;
43 
44  void setInternalName(const QString &name)
45  {
46  internalName = coerceInternalName(name);
47  }
48 };
49 
50 DPointered(DMFlag)
51 
52 DMFlag::DMFlag()
53 {
54  d->value = 0;
55 }
56 
57 DMFlag::DMFlag(const QString &internalName, unsigned value)
58 {
59  d->name = internalName;
60  d->setInternalName(internalName);
61  d->value = value;
62 }
63 
64 DMFlag::DMFlag(const QString &internalName, unsigned value, const QString &name)
65 {
66  d->name = name;
67  d->setInternalName(internalName);
68  d->value = value;
69 }
70 
71 DMFlag::DMFlag(const DMFlag &other)
72 {
73  this->d = other.d;
74 }
75 
76 DMFlag::~DMFlag()
77 {
78 }
79 
80 DMFlag &DMFlag::operator=(const DMFlag &other)
81 {
82  if (this != &other)
83  this->d = other.d;
84  return *this;
85 }
86 
87 const QString &DMFlag::internalName() const
88 {
89  return d->internalName;
90 }
91 
92 bool DMFlag::isValid() const
93 {
94  return value() > 0;
95 }
96 
97 const QString &DMFlag::name() const
98 {
99  return d->name;
100 }
101 
102 unsigned DMFlag::value() const
103 {
104  return d->value;
105 }
106 
108 
109 DClass<DMFlagsSection>
110 {
111 public:
112  QString name;
113  QString internalName;
114  QVector<DMFlag> flags;
115 
116  void setInternalName(const QString &name)
117  {
118  internalName = coerceInternalName(name);
119  }
120 };
121 
122 DPointered(DMFlagsSection)
123 
124 DMFlagsSection::DMFlagsSection()
125 {
126 }
127 
128 DMFlagsSection::DMFlagsSection(const QString &internalName)
129 {
130  d->name = internalName;
131  d->setInternalName(internalName);
132 }
133 
134 DMFlagsSection::DMFlagsSection(const QString &internalName, const QString &name)
135 {
136  d->name = name;
137  d->setInternalName(internalName);
138 }
139 
140 DMFlagsSection::DMFlagsSection(const DMFlagsSection &other)
141 {
142  this->d = other.d;
143 }
144 
145 DMFlagsSection::~DMFlagsSection()
146 {
147 }
148 
149 DMFlagsSection &DMFlagsSection::operator=(const DMFlagsSection &other)
150 {
151  if (this != &other)
152  this->d = other.d;
153  return *this;
154 }
155 
156 void DMFlagsSection::add(const DMFlag &flag)
157 {
158  d->flags << flag;
159 }
160 
162 {
163  unsigned result = 0;
164  for (const DMFlag &flag : d->flags)
165  {
166  result |= flag.value();
167  }
168  return result;
169 }
170 
172 {
173  DMFlagsSection copy = *this;
174  copy.d->flags.clear();
175  return copy;
176 }
177 
179 {
180  return d->flags.count();
181 }
182 
183 const QString &DMFlagsSection::internalName() const
184 {
185  return d->internalName;
186 }
187 
189 {
190  return count() == 0;
191 }
192 
193 const QString &DMFlagsSection::name() const
194 {
195  return d->name;
196 }
197 
198 const DMFlag &DMFlagsSection::operator[](int index) const
199 {
200  return d->flags[index];
201 }
202 
204 {
205  return d->flags[index];
206 }
207 
208 QList<DMFlagsSection> DMFlagsSection::removedBySection(
209  const QList<DMFlagsSection> &original,
210  const QList<DMFlagsSection> &removals)
211 {
212  QList<DMFlagsSection> copy;
213  for (const DMFlagsSection &section : original)
214  {
215  bool removed = false;
216  for (const DMFlagsSection &removal : removals)
217  {
218  if (section.internalName() == removal.internalName())
219  {
220  copy << section.removed(removal);
221  removed = true;
222  break;
223  }
224  }
225  if (!removed)
226  {
227  copy << section;
228  }
229  }
230  return copy;
231 }
232 
234 {
235  DMFlagsSection copy = *this;
236  for (const DMFlag &removal : removals.d->flags)
237  {
238  QMutableVectorIterator<DMFlag> i(copy.d->flags);
239  while (i.hasNext())
240  {
241  DMFlag &flag = i.next();
242  if (flag.value() == removal.value())
243  {
244  i.remove();
245  break;
246  }
247  }
248  }
249  return copy;
250 }
251 
253 
254 DClass<GameCVar>
255 {
256 public:
257  QString command;
258  QString name;
259  QVariant value;
260 };
261 
262 DPointered(GameCVar)
263 
264 GameCVar::GameCVar()
265 {
266 }
267 
268 GameCVar::GameCVar(const QString &name, const QString &command)
269 {
270  d->name = name;
271  d->command = command;
272 }
273 
274 GameCVar::GameCVar(const QString &name, const QString &command, const QVariant &value)
275 {
276  d->name = name;
277  d->command = command;
278  setValue(value);
279 }
280 
281 GameCVar::GameCVar(const GameCVar &other)
282 {
283  this->d = other.d;
284 }
285 
286 GameCVar::~GameCVar()
287 {
288 }
289 
290 GameCVar &GameCVar::operator=(const GameCVar &other)
291 {
292  if (this != &other)
293  this->d = other.d;
294  return *this;
295 }
296 
297 const QString &GameCVar::command() const
298 {
299  return d->command;
300 }
301 
302 bool GameCVar::hasValue() const
303 {
304  return value().isValid();
305 }
306 
307 bool GameCVar::isValid() const
308 {
309  return !command().isEmpty();
310 }
311 
312 const QString &GameCVar::name() const
313 {
314  return d->name;
315 }
316 
317 void GameCVar::setValue(const QVariant &value)
318 {
319  d->value = value;
320 }
321 
322 const QVariant &GameCVar::value() const
323 {
324  return d->value;
325 }
326 
328 
329 DClass<GameCVarProvider>
330 {
331 };
332 
333 DPointeredNoCopy(GameCVarProvider)
334 
335 GameCVarProvider::GameCVarProvider()
336 {
337 }
338 
339 GameCVarProvider::~GameCVarProvider()
340 {
341 }
342 
343 QList<GameCVar> GameCVarProvider::get(const QVariant &context)
344 {
345  Q_UNUSED(context);
346  return QList<GameCVar>();
347 }
348 
350 
351 DClass<GameMode>
352 {
353 public:
354  gamemode_id index;
355  QString name;
356  bool teamgame;
357 };
358 
359 DPointered(GameMode)
360 
362 {
363  d->index = SGM_Unknown;
364  d->teamgame = false;
365 }
366 
367 GameMode::GameMode(gamemode_id index, const QString &name)
368 {
369  d->index = index;
370  d->name = name;
371  d->teamgame = false;
372 }
373 
374 GameMode::GameMode(const GameMode &other)
375 {
376  this->d = other.d;
377 }
378 
379 GameMode::~GameMode()
380 {
381 }
382 
383 GameMode &GameMode::operator=(const GameMode &other)
384 {
385  if (this != &other)
386  this->d = other.d;
387  return *this;
388 }
389 
390 GameMode GameMode::ffaGame(int index, const QString &name)
391 {
392  GameMode result(index, name);
393  result.setTeamGame(false);
394  return result;
395 }
396 
398 {
399  return d->index;
400 }
401 
402 GameMode GameMode::mkCooperative()
403 {
404  return ffaGame(SGM_Cooperative, QObject::tr("Cooperative"));
405 }
406 
407 GameMode GameMode::mkDeathmatch()
408 {
409  return ffaGame(SGM_Deathmatch, QObject::tr("Deathmatch"));
410 }
411 
412 GameMode GameMode::mkTeamDeathmatch()
413 {
414  return teamGame(SGM_TeamDeathmatch, QObject::tr("Team DM"));
415 }
416 
417 GameMode GameMode::mkCaptureTheFlag()
418 {
419  return teamGame(SGM_CTF, QObject::tr("CTF"));
420 }
421 
422 GameMode GameMode::mkUnknown()
423 {
424  return ffaGame(SGM_Unknown, QObject::tr("Unknown"));
425 }
426 
427 const QString &GameMode::name() const
428 {
429  return d->name;
430 }
431 
433 {
434  return d->teamgame;
435 }
436 
437 bool GameMode::isValid() const
438 {
439  return !d->name.isEmpty();
440 }
441 
442 void GameMode::setTeamGame(bool b)
443 {
444  d->teamgame = b;
445 }
446 
447 GameMode GameMode::teamGame(int index, const QString &name)
448 {
449  GameMode result(index, name);
450  result.setTeamGame(true);
451  return result;
452 }
453 
455 
456 DClass<PWad>
457 {
458 public:
459  QString name;
460  bool optional;
461  QList<Checksum> checksums;
462 };
463 
464 DPointered(PWad)
465 
466 PWad::PWad(const QString &name, bool optional, const QList<Checksum> &checksums)
467 {
468  d->name = name;
469  d->optional = optional;
470  d->checksums = checksums;
471 }
472 
473 PWad::PWad(const QString &name, bool optional)
474 {
475  d->name = name;
476  d->optional = optional;
477 }
478 
479 PWad::PWad(const ModFile &modFile)
480 {
481  d->name = modFile.fileName();
482  d->optional = false;
483  d->checksums = modFile.checksums();
484 }
485 
486 PWad::PWad(const PWad &other)
487 {
488  this->d = other.d;
489 }
490 
491 PWad::~PWad()
492 {
493 }
494 
495 PWad &PWad::operator=(const PWad &other)
496 {
497  if (this != &other)
498  this->d = other.d;
499  return *this;
500 }
501 
502 PWad::operator ModFile()
503 {
504  ModFile modFile(d->name);
505  modFile.setChecksums(d->checksums);
506  return modFile;
507 }
508 
509 bool PWad::isOptional() const
510 {
511  return d->optional;
512 }
513 
514 const QString &PWad::name() const
515 {
516  return d->name;
517 }
518 
519 const QList<Checksum> PWad::checksums() const
520 {
521  return d->checksums;
522 }
523 
524 void PWad::addChecksum(const QByteArray &hash, const QCryptographicHash::Algorithm &algorithm)
525 {
526  d->checksums.append(Checksum(hash, algorithm));
527 }
528 
529 bool PWad::validFile(const QString &path) const
530 {
531  for (const Checksum checksum : d->checksums)
532  {
533  if (Hash::hashFile(path, checksum.algorithm()) != checksum.hash())
534  {
535  return false;
536  }
537  }
538  return true;
539 }
void add(const DMFlag &flag)
Append a new DMFlag to this section.
Creates GameCVar set.
const QString & name() const
Nice name to display to user in Create Game dialog and in other widgets.
const QString & name() const
User-friendly name to display for game mode.
const QString & internalName() const
static GameMode ffaGame(int index, const QString &name)
Construct a custom FFA game where players don&#39;t belong to any teams.
GameMode()
Constructs an invalid GameMode object.
void setValue(const QVariant &value)
Assign value() to this GameCVar.
PWAD hosted on a server.
bool isValid() const
&#39;Null&#39; objects are invalid.
A group of DMFlag objects that can be safely OR&#39;ed together to form a meaningful value.
A game setting that is a part of a group of settings that can be OR&#39;ed logically as a single integer...
Definition: serverstructs.h:62
const QVariant & value() const
Passed as the second argument, following command().
int count() const
Number of DMFlag objects inside the collection.
virtual QList< GameCVar > get(const QVariant &context)
Default implementation creates empty set.
bool isTeamGame() const
Is this GameMode based on rivaling teams?
const QList< Checksum > checksums() const
List of checksums of the WAD.
bool hasValue() const
Is any value assigned to this GameCVar.
const QString & internalName() const
Uniquely identifiable name within its DMFlagsSection, ex. "Jump is allowed" or "jumpisallowed".
bool isValid() const
&#39;Null&#39; objects are invalid.
const DMFlag & operator[](int index) const
Access DMFlag at specific index with &#39;[]&#39; operator.
const QString & name() const
Server&#39;s name.
Definition: server.cpp:430
Game mode representation.
DMFlagsSection removed(const DMFlagsSection &removals) const
Returns a copy of this list with specified DMFlags removed.
unsigned combineValues() const
Logical OR of all DMFlag::value() results in this collection.
unsigned value() const
Bits that represent this flag (usually just a single &#39;1&#39; bit).
int gamemode_id
Unique identifier of a GameMode within the plugin.
const QString & name() const
User-displayable name of this section, ex. "Compatibility flags".
bool isValid() const
Valid objects have value() greater than zero.
bool isOptional() const
Is this WAD required to join the server?
bool validFile(const QString &path) const
Verifies if a file has the same checksums as the PWad.
static GameMode teamGame(int index, const QString &name)
Game mode based on rivaling teams.
gamemode_id index() const
Index, either a StandardGameMode or custom defined by plugin.
DMFlagsSection copyEmpty() const
Copies section maintaining its properties but removing all flags.
const QString & name() const
User-displayable, translateable name of the DMFlag, ex. "Jump is allowed".
bool isEmpty() const
Does this section contain any dmflag?
void addChecksum(const QByteArray &hash, const QCryptographicHash::Algorithm &algorithm)
Adds a checksum to the WAD.
A general game setting or variable (like fraglimit).
const QString & command() const
Command-line argument that sets this GameCVar.
static QList< DMFlagsSection > removedBySection(const QList< DMFlagsSection > &original, const QList< DMFlagsSection > &removals)
Matches sections by internalName() and calls removed() on them.
const QString & name() const
File name of the WAD.