aboutsummaryrefslogtreecommitdiff
path: root/include/aoapplication.h
blob: 16895d8580a3442a76eeeafab8b4d7e45efe511f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
#ifndef AOAPPLICATION_H
#define AOAPPLICATION_H

#include "aopacket.h"
#include "datatypes.h"
#include "demoserver.h"
#include "discord_rich_presence.h"

#include "bass.h"
#include "bassmidi.h"
#include "bassopus.h"

#include <QApplication>
#include <QFile>
#include <QSettings>
#include <QVector>

#include <QDebug>
#include <QRect>

#include <QCryptographicHash>

#include <QDir>
#include <QStandardPaths>

#include <QColor>
#include <QScreen>
#include <QStringList>
#include <QTextStream>
#include <QTime>

#include <QElapsedTimer>

class NetworkManager;
class Lobby;
class Courtroom;

class VPath : QString {
  using QString::QString;

public:
  explicit VPath(const QString &str) : QString(str) {}
  inline QString const &toQString() const { return *this; }
  inline bool operator==(const VPath &str) const {
    return this->toQString() == str.toQString();
  }
  inline VPath operator+(const VPath &str) const {
    return VPath(this->toQString() + str.toQString());
  }
};

inline uint qHash(const VPath &key, uint seed = qGlobalQHashSeed())
{
  return qHash(key.toQString(), seed);
}

class AOApplication : public QApplication {
  Q_OBJECT

public:
  AOApplication(int &argc, char **argv);
  ~AOApplication();

  NetworkManager *net_manager;
  Lobby *w_lobby;
  Courtroom *w_courtroom;
  AttorneyOnline::Discord *discord;

  bool lobby_constructed = false;
  bool courtroom_constructed = false;

  void construct_lobby();
  void destruct_lobby();

  void construct_courtroom();
  void destruct_courtroom();

  void server_packet_received(AOPacket *p_packet);

  void send_server_packet(AOPacket *p_packet);

  void call_settings_menu();
  void call_announce_menu(Courtroom *court);

  qint64 latency = 0;
  QString window_title;

  /////////////////server metadata//////////////////

  bool yellow_text_supported = false;
  bool prezoom_supported = false;
  bool flipping_supported = false;
  bool custom_objection_supported = false;
  bool desk_mod_supported = false;
  bool evidence_supported = false;
  bool cccc_ic_supported = false;
  bool arup_supported = false;
  bool casing_alerts_supported = false;
  bool modcall_reason_supported = false;
  bool looping_sfx_supported = false;
  bool additive_text_supported = false;
  bool effects_supported = false;
  bool y_offset_supported = false;
  bool expanded_desk_mods_supported = false;
  bool auth_packet_supported = false;

  ///////////////loading info///////////////////

  // client ID. Not useful, to be removed eventually
  int client_id = 0;

  QString server_software = "";

  int char_list_size = 0;
  int loaded_chars = 0;
  int generated_chars = 0;
  int evidence_list_size = 0;
  int loaded_evidence = 0;
  int music_list_size = 0;
  int loaded_music = 0;

  bool courtroom_loaded = false;

  //////////////////versioning///////////////

  int get_release() const { return RELEASE; }
  int get_major_version() const { return MAJOR_VERSION; }
  int get_minor_version() const { return MINOR_VERSION; }
  QString get_version_string();

  ///////////////////////////////////////////

  void load_favorite_list();
  void save_favorite_list();
  QVector<server_type> &get_favorite_list() { return favorite_list; }

  // Adds the server to favorite_servers.ini
  void add_favorite_server(int p_server);
  void remove_favorite_server(int p_server);

  void set_server_list(QVector<server_type> &servers) { server_list = servers; }
  QVector<server_type> &get_server_list() { return server_list; }

  // reads the theme from config.ini and sets it accordingly
  void reload_theme();

  // Returns the character the player has currently selected
  QString get_current_char();

  // implementation in path_functions.cpp
  QString get_base_path();
  VPath get_theme_path(QString p_file, QString p_theme="");
  VPath get_character_path(QString p_char, QString p_file);
  VPath get_misc_path(QString p_misc, QString p_file);
  VPath get_sounds_path(QString p_file);
  VPath get_music_path(QString p_song);
  VPath get_background_path(QString p_file);
  VPath get_default_background_path(QString p_file);
  VPath get_evidence_path(QString p_file);
  QVector<VPath> get_asset_paths(QString p_element, QString p_theme="", QString p_subtheme="", QString p_default_theme="", QString p_misc="", QString p_character="", QString p_placeholder="");
  QString get_asset_path(QVector<VPath> pathlist);
  QString get_image_path(QVector<VPath> pathlist, bool static_image=false);
  QString get_sfx_path(QVector<VPath> pathlist);
  QString get_config_value(QString p_identifier, QString p_config, QString p_theme="", QString p_subtheme="", QString p_default_theme="", QString p_misc="");
  QString get_asset(QString p_element, QString p_theme="", QString p_subtheme="", QString p_default_theme="", QString p_misc="", QString p_character="", QString p_placeholder="");
  QString get_image(QString p_element, QString p_theme="", QString p_subtheme="", QString p_default_theme="", QString p_misc="", QString p_character="", QString p_placeholder="", bool static_image=false);
  QString get_sfx(QString p_sfx, QString p_misc="", QString p_character="");
  QString get_pos_path(const QString& pos, bool desk = false);
  QString get_case_sensitive_path(QString p_file);
  QString get_real_path(const VPath &vpath, const QStringList &suffixes={""});
  void invalidate_lookup_cache();

  ////// Functions for reading and writing files //////
  // Implementations file_functions.cpp

  // Instead of reinventing the wheel, we'll use a QSettings class.
  QSettings *configini;

  // Reads the theme from config.ini and loads it into the current_theme
  // variable
  QString read_theme();

  // Returns the value of ooc_name in config.ini
  QString get_ooc_name();

  // Returns the blip rate from config.ini (once per X symbols)
  int read_blip_rate();

  // Returns true if blank blips is enabled in config.ini and false otherwise
  bool get_blank_blip();

  // Returns true if looping sound effects are enabled in the config.ini
  bool get_looping_sfx();

  // Returns true if stop music on objection is enabled in the config.ini
  bool objection_stop_music();

  // Returns true if streaming is enabled in the config.ini
  bool is_streaming_disabled();

  // Returns the value of default_music in config.ini
  int get_default_music();

  // Returns the value of default_sfx in config.ini
  int get_default_sfx();

  // Returns the value of default_blip in config.ini
  int get_default_blip();

  // Returns the value of suppress_audio in config.ini
  int get_default_suppress_audio();

  // Returns the value if objections interrupt and skip the message queue
  // from the config.ini.
  bool is_instant_objection_enabled();

  // returns if log will show messages as-received, while viewport will parse according to the queue (Text Stay Time)
  // from the config.ini
  bool is_desyncrhonized_logs_enabled();

  // Returns the value of whether Discord should be enabled on startup
  // from the config.ini.
  bool is_discord_enabled();

  // Returns the value of whether shaking should be enabled.
  // from the config.ini.
  bool is_shake_enabled();

  // Returns the value of whether effects should be enabled.
  // from the config.ini.
  bool is_effects_enabled();

  // Returns the value of whether frame-specific effects defined in char.ini
  // should be sent/received over the network. from the config.ini.
  bool is_frame_network_enabled();

  // Returns the value of whether colored ic log should be a thing.
  // from the config.ini.
  bool is_colorlog_enabled();

  // Returns the value of whether sticky sounds should be a thing.
  // from the config.ini.
  bool is_stickysounds_enabled();

  // Returns the value of whether sticky effects should be a thing.
  // from the config.ini.
  bool is_stickyeffects_enabled();

  // Returns the value of whether sticky preanims should be a thing.
  // from the config.ini.
  bool is_stickypres_enabled();

  // Returns the value of whether custom chatboxes should be a thing.
  // from the config.ini.
  // I am increasingly maddened by the lack of dynamic auto-generation system
  // for settings.
  bool is_customchat_enabled();

  // Returns the value of characer sticker (avatar) setting
  bool is_sticker_enabled();

  // Returns the value of whether continuous playback should be used
  // from the config.ini.
  bool is_continuous_enabled();

  // Returns the value of whether stopping music by double clicking category should be used
  // from the config.ini.
  bool is_category_stop_enabled();

  // Returns the value of the maximum amount of lines the IC chatlog
  // may contain, from config.ini.
  int get_max_log_size();

  // Current wait time between messages for the queue system
  int stay_time();

  // Returns the letter display speed during text crawl in in-character messages
  int get_text_crawl();

  // Returns Minimum amount of time (in miliseconds) that must pass before the next Enter key press will send your IC message. (new behaviour)
  int get_chat_ratelimit();

  // Returns whether the log should go upwards (new behaviour)
  // or downwards (vanilla behaviour).
  bool get_log_goes_downwards();

  // Returns whether the log should separate name from text via newline or :
  bool get_log_newline();

  // Get spacing between IC log entries.
  int get_log_margin();

  // Returns whether the log should have a timestamp.
  bool get_log_timestamp();

  // Returns the format string for the log timestamp
  QString get_log_timestamp_format();

  // Returns whether to log IC actions.
  bool get_log_ic_actions();

  // Returns the username the user may have set in config.ini.
  QString get_default_username();

  // Returns the audio device used for the client.
  QString get_audio_output_device();

  // Returns whether the user would like to have custom shownames on by default.
  bool get_showname_enabled_by_default();

  //Returns the showname the user may have set in config.ini.
  QString get_default_showname();

  // Returns the list of words in callwords.ini
  QStringList get_call_words();

  // returns all of the file's lines in a QStringList
  QStringList get_list_file(VPath path);
  QStringList get_list_file(QString p_file);

  // Process a file and return its text as a QString
  QString read_file(QString filename);

  // Write text to file. make_dir would auto-create the directory if it doesn't
  // exist.
  bool write_to_file(QString p_text, QString p_file, bool make_dir = false);

  // Append text to the end of the file. make_dir would auto-create the
  // directory if it doesn't exist.
  bool append_to_file(QString p_text, QString p_file, bool make_dir = false);

  // Append to the currently open demo file if there is one
  void append_to_demofile(QString packet_string);

  /**
   * @brief Reads favorite_servers.ini and returns a list of servers.
   *
   * The demo server entry is always present at the top of the list.
   *
   * If the server list returned was to be empty (exluding the demo server entry),
   * will return a list of servers from the legacy serverlist.txt file.
   *
   * @return A list of servers.
   */
  QVector<server_type> read_favorite_servers();

  /**
   * @brief Reads serverlist.txt and returns a list of servers.
   *
   * @return A list of servers.
   */
  QVector<server_type> read_legacy_favorite_servers();

  // Returns the value of p_identifier in the design.ini file in p_design_path
  QString read_design_ini(QString p_identifier, VPath p_design_path);
  QString read_design_ini(QString p_identifier, QString p_design_path);

  // Returns the coordinates of widget with p_identifier from p_file
  QPoint get_button_spacing(QString p_identifier, QString p_file);

  // Returns the dimensions of widget with specified identifier from p_file
  pos_size_type get_element_dimensions(QString p_identifier, QString p_file,
                                       QString p_misc = "");

  // Returns the value to you
  QString get_design_element(QString p_identifier, QString p_file,
                             QString p_misc = "");

  // Returns the value of font_size with p_identifier from p_file
  int get_font_size(QString p_identifier, QString p_file);

  // Returns the color with p_identifier from p_file
  QColor get_color(QString p_identifier, QString p_file);

  // Returns the markup symbol used for specified p_identifier such as colors
  QString get_chat_markup(QString p_identifier, QString p_file);

  // Returns the color from the misc folder.
  QColor get_chat_color(QString p_identifier, QString p_chat);

  // Returns the value with p_identifier from penalty/penalty.ini in the current
  // theme path
  QString get_penalty_value(QString p_identifier);

  // Returns the sfx with p_identifier from courtroom_sounds.ini in the current theme path
  QString get_court_sfx(QString p_identifier, QString p_misc="");

  // Figure out if we can opus this or if we should fall back to wav
  QString get_sfx_suffix(VPath sound_to_check);

  // Can we use APNG for this? If not, WEBP? If not, GIF? If not, fall back to
  // PNG.
  QString get_image_suffix(VPath path_to_check, bool static_image=false);

  // Returns the value of p_search_line within target_tag and terminator_tag
  QString read_char_ini(QString p_char, QString p_search_line,
                        QString target_tag);

  // Returns a QStringList of all key=value definitions on a given tag.
  QStringList read_ini_tags(VPath p_file, QString target_tag = "");

  // Sets the char.ini p_search_line key under tag target_tag to value.
  void set_char_ini(QString p_char, QString value, QString p_search_line,
                    QString target_tag);

  // Returns the text between target_tag and terminator_tag in p_file
  QString get_stylesheet(QString p_file);

  // Returns the text between target_tag and terminator_tag in p_file
  QString get_tagged_stylesheet(QString target_tag, QString p_file);

  // Returns the side of the p_char character from that characters ini file
  QString get_char_side(QString p_char);

  // Returns the showname from the ini of p_char
  QString get_showname(QString p_char);

  // Returns the category of this character
  QString get_category(QString p_char);

  // Returns the value of chat image from the specific p_char's ini file
  QString get_chat(QString p_char);

  // Returns the value of chat font from the specific p_char's ini file
  QString get_chat_font(QString p_char);

  // Returns the value of chat font size from the specific p_char's ini file
  int get_chat_size(QString p_char);

  // Returns the preanim duration of p_char's p_emote
  int get_preanim_duration(QString p_char, QString p_emote);

  // Not in use
  int get_text_delay(QString p_char, QString p_emote);

  // Get the theme's effects folder, read it and return the list of filenames in
  // a string
  QStringList get_effects(QString p_char);

  // Get the correct effect image
  QString get_effect(QString effect, QString p_char, QString p_folder);

  // Return p_property of fx_name. If p_property is "sound", return
  // the value associated with fx_name, otherwise use fx_name + '_' + p_property.
  QString get_effect_property(QString fx_name, QString p_char, QString p_folder, QString p_property);

  // Returns the custom realisation used by the character.
  QString get_custom_realization(QString p_char);

  // Returns whether the given pos is a judge position
  bool get_pos_is_judge(const QString &p_pos);

  // Returns the total amount of emotes of p_char
  int get_emote_number(QString p_char);

  // Returns the emote comment of p_char's p_emote
  QString get_emote_comment(QString p_char, int p_emote);

  // Returns the base name of p_char's p_emote
  QString get_emote(QString p_char, int p_emote);

  // Returns the preanimation name of p_char's p_emote
  QString get_pre_emote(QString p_char, int p_emote);

  // Returns the sfx of p_char's p_emote
  QString get_sfx_name(QString p_char, int p_emote);

  // Returns the blipsound of p_char's p_emote
  QString get_emote_blip(QString p_char, int p_emote);

  // Returns if the sfx is defined as looping in char.ini
  QString get_sfx_looping(QString p_char, int p_emote);

  // Returns if an emote has a frame specific SFX for it
  QString get_sfx_frame(QString p_char, QString p_emote, int n_frame);

  // Returns if an emote has a frame specific SFX for it
  QString get_flash_frame(QString p_char, QString p_emote, int n_frame);

  // Returns if an emote has a frame specific SFX for it
  QString get_screenshake_frame(QString p_char, QString p_emote, int n_frame);

  // Not in use
  int get_sfx_delay(QString p_char, int p_emote);

  // Returns the modifier for p_char's p_emote
  int get_emote_mod(QString p_char, int p_emote);

  // Returns the desk modifier for p_char's p_emote
  int get_desk_mod(QString p_char, int p_emote);

  // Returns p_char's blips (previously called their "gender")
  QString get_blips(QString p_char);

  // Get a property of a given emote, or get it from "options" if emote doesn't have it
  QString get_emote_property(QString p_char, QString p_emote, QString p_property);

  // Return a transformation mode from a string ("smooth" for smooth, anything else for fast)
  Qt::TransformationMode get_scaling(QString p_scaling);

  // Returns the scaling type for p_miscname
  Qt::TransformationMode get_misc_scaling(QString p_miscname);

  // ======
  // These are all casing-related settings.
  // ======

  // Returns if the user has casing alerts enabled.
  bool get_casing_enabled();

  // Returns if the user wants to get alerts for the defence role.
  bool get_casing_defence_enabled();

  // Same for prosecution.
  bool get_casing_prosecution_enabled();

  // Same for judge.
  bool get_casing_judge_enabled();

  // Same for juror.
  bool get_casing_juror_enabled();

  // Same for steno.
  bool get_casing_steno_enabled();

  // Same for CM.
  bool get_casing_cm_enabled();

  // Get the message for the CM for casing alerts.
  QString get_casing_can_host_cases();

  // Get if text file logging is enabled
  bool get_text_logging_enabled();

  // Get if demo logging is enabled
  bool get_demo_logging_enabled();

  // Get the subtheme from settings
  QString get_subtheme();

  // Get if the theme is animated
  bool get_animated_theme();

  // Get the default scaling method
  QString get_default_scaling();

  // Get a list of custom mount paths
  QStringList get_mount_paths();

  // Get whether to opt out of player count metrics sent to the master server
  bool get_player_count_optout();

  // Get if sfx can be sent to play on idle
  bool get_sfx_on_idle();

  // Whether opening evidence requires a single or double click
  bool get_evidence_double_click();

  // Currently defined subtheme
  QString subtheme;

  QString default_theme = "default";
  QString current_theme = default_theme;

  // The file name of the log file in base/logs.
  QString log_filename;

  /**
   * @brief A QString of an URL that defines the content repository
   *        send by the server.
   *
   * @details Introduced in Version 2.9.2.
   *        Addresses the issue of contenturl devlivery for WebAO
   *        without relying on someone adding the link manually.
   */
  QString asset_url;

  void initBASS();
  static void load_bass_plugins();
  static void CALLBACK BASSreset(HSTREAM handle, DWORD channel, DWORD data,
                                 void *user);
  static void doBASSreset();

  QElapsedTimer demo_timer;
  DemoServer* demo_server = nullptr;

private:
  const int RELEASE = 2;
  const int MAJOR_VERSION = 10;
  const int MINOR_VERSION = 0;

  QVector<server_type> server_list;
  QVector<server_type> favorite_list;
  QHash<uint, QString> asset_lookup_cache;
  QHash<uint, QString> dir_listing_cache;
  QSet<uint> dir_listing_exist_cache;

public slots:
  void server_disconnected();
  void loading_cancelled();

signals:
  void qt_log_message(QtMsgType type, const QMessageLogContext &context,
                      const QString &msg);
};

#endif // AOAPPLICATION_H