swift
Loading...
Searching...
No Matches
contextnetworkimpl.cpp
1// SPDX-FileCopyrightText: Copyright (C) 2013 swift Project Community / Contributors
2// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-swift-pilot-client-1
3
5
6#include <QStringBuilder>
7#include <QTimer>
8
12#include "core/application.h"
16#include "core/corefacade.h"
17#include "core/fsd/fsdclient.h"
24#include "misc/dbusserver.h"
25#include "misc/logcategories.h"
26#include "misc/logmessage.h"
30#include "misc/pq/constants.h"
31#include "misc/pq/frequency.h"
32#include "misc/pq/time.h"
33#include "misc/pq/units.h"
34#include "misc/sequence.h"
37#include "misc/stringutils.h"
38
39using namespace swift::config;
40using namespace swift::misc;
41using namespace swift::misc::physical_quantities;
42using namespace swift::misc::aviation;
43using namespace swift::misc::network;
44using namespace swift::misc::geo;
45using namespace swift::misc::simulation;
46using namespace swift::misc::weather;
47using namespace swift::core::fsd;
48using namespace swift::core::vatsim;
49
50namespace swift::core::context
51{
53 : IContextNetwork(mode, runtime)
54 {
56 Q_ASSERT(this->getRuntime());
57 Q_ASSERT(this->getIContextOwnAircraft());
60
61 // 1. Init by "network driver"
62 m_fsdClient = new CFSDClient(this, // client provider
63 this->getRuntime()->getCContextOwnAircraft(), // own aircraft provider
64 this, // remote aircraft provider
65 this); // thread owner
66 m_fsdClient->start(); // FSD thread
67 connect(m_fsdClient, &CFSDClient::connectionStatusChanged, this, &CContextNetwork::onFsdConnectionStatusChanged,
70 connect(m_fsdClient, &CFSDClient::textMessagesReceived, this, &CContextNetwork::onTextMessagesReceived,
72 connect(m_fsdClient, &CFSDClient::textMessageSent, this, &CContextNetwork::onTextMessageSent,
78
79 // 2. Update timer for data (network data such as frequency)
80 // we use 2 timers so we can query at different times (not too many queirs at once)
81 m_requestAircraftDataTimer = new QTimer(this);
82 connect(m_requestAircraftDataTimer, &QTimer::timeout, this, &CContextNetwork::requestAircraftDataUpdates);
83 m_requestAircraftDataTimer->start(30 * 1000);
84 m_requestAircraftDataTimer->setObjectName("CContextNetwork::m_requestAircraftDataTimer");
85
86 m_requestAtisTimer = new QTimer(this);
88 m_requestAtisTimer->start(13 * 1000); // should not be called at the same time as above
89 m_requestAtisTimer->setObjectName("CContextNetwork::m_requestAtisTimer");
90
91 // 3. send staggered model matching signals, to avoid to many matchings at the same time
92 m_staggeredMatchingTimer = new QTimer(this);
93 connect(m_staggeredMatchingTimer, &QTimer::timeout, this, &CContextNetwork::emitReadyForMatching);
94 m_staggeredMatchingTimer->start(200);
95 m_staggeredMatchingTimer->setObjectName("CContextNetwork::m_staggeredMatchingTimer");
96
97 // 4. Airspace contents
98 Q_ASSERT_X(this->getRuntime()->getCContextOwnAircraft(), Q_FUNC_INFO,
99 "this and own aircraft context must be local");
100 Q_ASSERT_X(this->getRuntime()->getCContextSimulator(), Q_FUNC_INFO,
101 "this and own simulator context must be local");
102 m_airspace = new CAirspaceMonitor(this->getRuntime()->getCContextOwnAircraft(),
103 this->getRuntime()->getCContextSimulator(), m_fsdClient, this);
104 m_fsdClient->setClientProvider(m_airspace);
112 Qt::QueuedConnection); // DBus
114 &CContextNetwork::onReadyForModelMatching); // intentionally NOT QueuedConnection
117 connect(m_airspace, &CAirspaceMonitor::changedAtisReceived, this, &CContextNetwork::onChangedAtisReceived,
119 }
120
122 {
123 if (this->canUseAirspaceMonitor())
124 {
125 m_airspace->setSimulationEnvironmentProvider(provider);
126 }
127 if (this->canUseFsd())
128 {
129 m_fsdClient->setSimulationEnvironmentProvider(provider);
130 }
131 }
132
134
136 {
137 if (!this->canUseAirspaceMonitor())
138 {
139 return {};
140 }
141 return m_airspace->remoteAircraftSituations(callsign);
142 }
143
145 {
146 if (!this->canUseAirspaceMonitor())
147 {
148 return {};
149 }
150 return m_airspace->remoteAircraftSituation(callsign, index);
151 }
152
155 {
156 if (!this->canUseAirspaceMonitor())
157 {
158 return {};
159 }
160 return m_airspace->remoteAircraftSituationsTimestampDifferenceMinMaxMean(callsign);
161 }
162
164 {
165 if (!this->canUseAirspaceMonitor())
166 {
167 return {};
168 }
169 return m_airspace->latestRemoteAircraftSituations();
170 }
171
173 {
174 Q_ASSERT(m_airspace);
175 return m_airspace->latestOnGroundProviderElevations();
176 }
177
179 {
180 if (!this->canUseAirspaceMonitor())
181 {
182 return {};
183 }
184 return m_airspace->remoteAircraftParts(callsign);
185 }
186
188 {
189 if (!this->canUseAirspaceMonitor())
190 {
191 return 0;
192 }
193 return m_airspace->remoteAircraftPartsCount(callsign);
194 }
195
197 {
198 if (!this->canUseAirspaceMonitor())
199 {
200 return 0;
201 }
202 return m_airspace->remoteAircraftSituationsCount(callsign);
203 }
204
206 {
207 if (!this->canUseAirspaceMonitor())
208 {
209 return false;
210 }
211 return m_airspace->isRemoteAircraftSupportingParts(callsign);
212 }
213
215 {
216 if (!this->canUseAirspaceMonitor())
217 {
218 return {};
219 }
220 return m_airspace->remoteAircraftSupportingParts();
221 }
222
224 {
225 if (!this->canUseAirspaceMonitor())
226 {
227 return {};
228 }
229 return m_airspace->remoteAircraftSituationChanges(callsign);
230 }
231
233 {
234 if (!this->canUseAirspaceMonitor())
235 {
236 return {};
237 }
238 return m_airspace->remoteAircraftSituationChangesCount(callsign);
239 }
240
242 QObject *receiver, std::function<void(const CAircraftSituation &)> situationSlot,
243 std::function<void(const CCallsign &, const CAircraftParts &)> partsSlot,
244 std::function<void(const CCallsign &)> removedAircraftSlot,
245 std::function<void(const CAirspaceAircraftSnapshot &)> aircraftSnapshotSlot)
246 {
247 Q_ASSERT_X(m_airspace, Q_FUNC_INFO, "Missing airspace");
248 return m_airspace->connectRemoteAircraftProviderSignals(receiver, situationSlot, partsSlot, removedAircraftSlot,
249 aircraftSnapshotSlot);
250 }
251
253 {
254 this->disconnect(); // all signals
255 if (this->isConnected())
256 {
257 this->disconnectFromNetwork();
258 }
259 if (m_fsdClient)
260 {
261 m_fsdClient->gracefulShutdown();
262 m_fsdClient->setClientProvider(nullptr);
263 m_fsdClient->deleteLater();
264 m_fsdClient = nullptr;
265 }
266
267 if (m_airspace)
268 {
269 m_airspace->gracefulShutdown();
270 m_airspace->deleteLater();
271 m_airspace = nullptr;
272 }
273 }
274
275 CStatusMessage CContextNetwork::connectToNetwork(const CServer &server, const QString &extraLiveryString,
276 bool sendLivery, const QString &extraModelString,
277 bool sendModelString, const CCallsign &partnerCallsign,
278 CLoginMode mode)
279 {
280 if (!this->canUseFsd())
281 {
283 u"Invalid FSD state (shutdown)") };
284 }
285 if (this->isDebugEnabled())
286 {
287 CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO;
288 }
289
290 QString msg;
291 if (!server.getUser().hasCredentials())
292 {
294 u"Invalid user credentials");
295 }
296 if (!this->ownAircraft().getAircraftIcaoCode().hasDesignator())
297 {
299 u"Invalid ICAO data for own aircraft");
300 }
301 if (!CNetworkUtils::canConnect(server, msg, 5000))
302 {
303 return { CStatusMessage::SeverityError, msg };
304 }
305 if (m_fsdClient->isConnected())
306 {
308 u"Already connected");
309 }
310 if (this->isPendingConnection())
311 {
313 u"Pending connection, please wait");
314 }
315
317 const CSimulatedAircraft ownAircraft(this->ownAircraft());
318 m_fsdClient->setPartnerCallsign(
319 isValidPartnerCallsign(ownAircraft.getCallsign(), partnerCallsign) ? partnerCallsign : CCallsign());
320
321 // Fall back to observer mode, if no simulator is available or not simulating
322 if (!CBuildConfig::isLocalDeveloperDebugBuild() && !this->getIContextSimulator()->isSimulatorSimulating())
323 {
324 CLogMessage(this).info(
325 u"No simulator connected or connected simulator not simulating. Falling back to observer mode");
327 }
328
329 const CSimulatorInfo sim = this->getIContextSimulator() ?
332 const QString l =
333 extraLiveryString.isEmpty() ? ownAircraft.getModel().getSwiftLiveryString(sim) : extraLiveryString;
334 const QString m = extraModelString.isEmpty() ? ownAircraft.getModelString() : extraModelString;
335
336 // FG fix, do not send livery and model ids for FlightGear
337 // https://discordapp.com/channels/539048679160676382/567091362030419981/698124094482415616
338 if (sim.isFG() && extraModelString.isEmpty())
339 {
340 sendModelString = false;
341 }
342
343 m_currentMode = mode;
344 m_fsdClient->setLoginMode(mode);
345 m_fsdClient->setCallsign(ownAircraft.getCallsign());
346
347 // set this BEFORE model string as FG has different handling
348 m_fsdClient->setSimType(sim);
349
350 m_fsdClient->setIcaoCodes(ownAircraft);
351 m_fsdClient->setLiveryAndModelString(l, sendLivery, m, sendModelString);
352 m_fsdClient->setClientName(sApp->swiftVersionChar());
353 m_fsdClient->setVersion(CBuildConfig::getVersion().majorVersion(), CBuildConfig::getVersion().minorVersion());
354
355#ifdef SWIFT_VATSIM_SUPPORT
356 int clientId = 0;
357 QString clientKey;
358 if (!getEnvironmentClientIdAndKey(clientId, clientKey))
359 {
360 // if not set, use the default client id and key from build config
361 clientId = CBuildConfig::vatsimClientId();
362 clientKey = CBuildConfig::vatsimPrivateKey();
363 }
364
365 m_fsdClient->setClientIdAndKey(static_cast<quint16>(clientId), clientKey.toLocal8Bit());
366#endif
367 m_fsdClient->setClientCapabilities(Capabilities::AircraftInfo | Capabilities::FastPos | Capabilities::VisPos |
370 m_fsdClient->setServer(server);
371
372 m_fsdClient->setPilotRating(PilotRating::Student);
373 m_fsdClient->setAtcRating(AtcRating::Observer);
374
375 m_fsdClient->connectToServer();
377 u"Connection pending " % server.getAddress() % u' ' % QString::number(server.getPort()));
378 }
379
381 {
382 if (!this->canUseFsd())
383 {
384 return {};
385 }
386 return this->isConnected() ? m_fsdClient->getServer() : CServer();
387 }
388
390 {
391 if (!this->canUseFsd())
392 {
393 return {};
394 }
395 if (this->isDebugEnabled())
396 {
397 CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO;
398 }
399 return m_fsdClient->getLoginMode();
400 }
401
403 {
404 if (!this->canUseFsd())
405 {
407 u"Invalid FSD state (shutdown)") };
408 }
409 if (this->isDebugEnabled())
410 {
411 CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO;
412 }
413 if (m_fsdClient->isConnected() || m_fsdClient->isPendingConnection())
414 {
415 m_fsdClient->disconnectFromServer();
417 u"Connection terminating");
418 }
419 else
420 {
422 u"Already disconnected");
423 }
424 }
425
427 {
428 if (!this->canUseFsd())
429 {
430 return false;
431 }
432 if (this->isDebugEnabled())
433 {
434 CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO;
435 }
436 return m_fsdClient->isConnected();
437 }
438
440 {
441 if (!this->canUseFsd())
442 {
443 return false;
444 }
445 return m_fsdClient->isPendingConnection();
446 }
447
448 bool CContextNetwork::parseCommandLine(const QString &commandLine, const CIdentifier &originator)
449 {
450 Q_UNUSED(originator);
451
452 if (!this->canUseAirspaceMonitor())
453 {
454 return false;
455 }
456 if (!this->canUseFsd())
457 {
458 return false;
459 }
460 if (commandLine.isEmpty())
461 {
462 return false;
463 }
464
465 static const QStringList cmds({ ".msg", ".m", ".chat", ".altos", ".altoffset", ".addtimeos", ".addtimeoffset",
466 ".wallop", ".reinit", ".reinitialize", ".enable", ".disable", ".ignore",
467 ".unignore", ".fsd" });
468 CSimpleCommandParser parser(cmds);
469 parser.parse(commandLine);
470 if (!parser.isKnownCommand())
471 {
472 return false;
473 }
474 if (parser.matchesCommand(".msg", ".m", ".chat"))
475 {
476 if (!this->getIContextNetwork() || !this->getIContextNetwork()->isConnected())
477 {
478 CLogMessage(this).validationError(u"Network needs to be connected");
479 return false;
480 }
481 else if (!this->getIContextOwnAircraft())
482 {
483 CLogMessage(this).validationError(u"No own aircraft data, no text message can be sent");
484 return false;
485 }
486 if (parser.countParts() < 3)
487 {
488 CLogMessage(this).validationError(u"Incorrect message");
489 return false;
490 }
491
492 // set receiver
493 const CSimulatedAircraft ownAircraft(this->getIContextOwnAircraft()->getOwnAircraft());
494 const QString receiver = parser.part(1).trimmed().toLower(); // receiver
495 CCallsign ownCallsign = ownAircraft.getCallsign();
496 if (m_fsdClient)
497 {
498 // override with the preset callsign, as the own callsign can be different for partner callsign
499 // scenarios copilot scenarios
500 const CCallsign presetCallsign = m_fsdClient->getPresetCallsign();
501 if (!presetCallsign.isEmpty())
502 {
503 ownCallsign = presetCallsign;
504 }
505 }
506
507 if (ownCallsign.isEmpty())
508 {
509 CLogMessage(this).validationError(u"No own callsign");
510 return false;
511 }
512
513 CTextMessage tm;
514 tm.setSenderCallsign(ownCallsign);
515
516 // based on the CPZ bug
517 // https://discordapp.com/channels/539048679160676382/539486309882789888/576765888401768449 no longer use
518 // starts/ends with
519 if (receiver == QStringView(u"c1") || receiver == QStringView(u"com1") || receiver == QStringView(u"comm1"))
520 {
521 tm.setFrequency(ownAircraft.getCom1System().getFrequencyActive());
522 }
523 else if (receiver == QStringView(u"c2") || receiver == QStringView(u"com2") ||
524 receiver == QStringView(u"comm2"))
525 {
526 tm.setFrequency(ownAircraft.getCom2System().getFrequencyActive());
527 }
528 else if (receiver == "u" || receiver == QStringView(u"uni") || receiver == QStringView(u"unicom"))
529 {
531 }
532 else
533 {
534 const CFrequency radioFrequency =
536 if (!radioFrequency.isNull())
537 {
539 {
540 tm.setFrequency(radioFrequency);
541 }
542 else
543 {
544 CLogMessage(this).validationError(u"Wrong COM frequency for text message");
545 return false;
546 }
547 }
548 else
549 {
550 const CCallsign toCallsign(receiver);
551 tm.setRecipientCallsign(toCallsign);
552 }
553 }
554
555 const QString msg(parser.partAndRemainingStringAfter(2));
556 tm.setMessage(msg);
557 if (tm.isEmpty())
558 {
559 CLogMessage(this).validationError(u"No text message body");
560 return false;
561 }
562 CTextMessageList tml(tm);
563 this->sendTextMessages(tml);
564 return true;
565 }
566 else if (parser.matchesCommand(".altos", ".altoffset"))
567 {
568 if (!m_airspace)
569 {
570 return false;
571 }
572 if (parser.countParts() < 2)
573 {
574 return false;
575 }
576
577 const QString csPart(parser.part(1));
578 CCallsign cs;
579 if (csPart.contains('?'))
580 {
582 }
583 else
584 {
585 cs = CCallsign(csPart);
586 if (!m_airspace->isAircraftInRange(cs))
587 {
588 CLogMessage(this).validationError(u"Altitude offset unknown callsign");
589 return false;
590 }
591 }
592
594 if (parser.hasPart(2))
595 {
597 }
598
599 const bool added = this->testAddAltitudeOffset(cs, os);
600 if (added)
601 {
602 CLogMessage(this).info(u"Added altitude offset %1 for %2")
603 << os.valueRoundedWithUnit(2) << cs.asString();
604 }
605 else
606 {
607 CLogMessage(this).info(u"Removed altitude offset %1") << cs.asString();
608 }
609
610 return true;
611 }
612 else if (parser.matchesCommand(".addtimeos", ".addtimeoffset"))
613 {
614 if (!m_airspace)
615 {
616 return false;
617 }
618 if (parser.countParts() < 2)
619 {
620 return false;
621 }
622
623 CTime os(CTime::null());
624 if (parser.hasPart(2))
625 {
627 }
628
629 if (!os.isNull() && os.isPositiveWithEpsilonConsidered())
630 {
631 const qint64 ost = os.valueInteger(CTimeUnit::ms());
632 CLogMessage(this).info(u"Added add offset time %1ms") << ost;
633 }
634 else
635 {
636 CLogMessage(this).info(u"Reset add. time offset");
637 }
638 }
639 else if (parser.matchesCommand(".reinit", ".reinitialize"))
640 {
641 if (!m_airspace)
642 {
643 return false;
644 }
645 const int count = m_airspace->reInitializeAllAircraft();
646 if (count > 0)
647 {
648 CLogMessage(this).info(u"Re-init %1 aircraft") << count;
649 }
650 }
651 else if (parser.matchesCommand(".wallop"))
652 {
653 if (parser.countParts() < 2)
654 {
655 return false;
656 }
657 if (!m_fsdClient)
658 {
659 return false;
660 }
661 if (!this->isConnected())
662 {
663 CLogMessage(this).validationError(u"Network needs to be connected");
664 return false;
665 }
666 const QString wallopMsg = parser.partAndRemainingStringAfter(1);
667 if (wallopMsg.isEmpty())
668 {
669 CLogMessage(this).validationError(u"No wallop message body");
670 return false;
671 }
672 m_fsdClient->sendTextMessage(TextMessageGroups::AllSups, wallopMsg);
673 return true;
674 }
675 else if (parser.matchesCommand(".enable", ".unignore"))
676 {
677 if (parser.countParts() < 2)
678 {
679 return false;
680 }
681 if (!m_fsdClient)
682 {
683 return false;
684 }
685 if (!this->isConnected())
686 {
687 return false;
688 }
689 const CCallsign cs(parser.part(1));
690 if (cs.isValid())
691 {
692 this->updateAircraftEnabled(cs, true);
693 }
694 }
695 else if (parser.matchesCommand(".disable", ".ignore"))
696 {
697 if (parser.countParts() < 2)
698 {
699 return false;
700 }
701 if (!m_fsdClient)
702 {
703 return false;
704 }
705 if (!this->isConnected())
706 {
707 return false;
708 }
709 const CCallsign cs(parser.part(1));
710 if (cs.isValid())
711 {
712 this->updateAircraftEnabled(cs, false);
713 }
714 }
715 else if (m_airspace && parser.matchesCommand(".fsd"))
716 {
717 return m_airspace->parseCommandLine(commandLine, originator);
718 }
719
720 return false;
721 }
722
724 {
725 if (this->isDebugEnabled())
726 {
727 CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO << textMessages;
728 }
729 m_fsdClient->sendTextMessages(textMessages);
730 }
731
733 {
734 if (this->isDebugEnabled())
735 {
736 CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO << flightPlan;
737 }
738 m_fsdClient->sendFlightPlan(flightPlan);
739 m_fsdClient->sendClientQueryFlightPlan(this->ownAircraft().getCallsign());
740 }
741
743 {
744 if (!this->canUseFsd())
745 {
746 return {};
747 }
748 if (this->isDebugEnabled())
749 {
750 CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO;
751 }
752 return m_airspace->loadFlightPlanFromNetwork(callsign);
753 }
754
756 {
757 if (!this->canUseAirspaceMonitor())
758 {
759 return {};
760 }
761 if (this->isDebugEnabled())
762 {
763 CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO;
764 }
765 return m_airspace->getUsers();
766 }
767
769 {
770 if (!this->canUseAirspaceMonitor() || callsigns.isEmpty())
771 {
772 return {};
773 }
774 if (this->isDebugEnabled())
775 {
776 CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO;
777 }
778 return m_airspace->getUsersForCallsigns(callsigns);
779 }
780
782 {
783 if (this->isDebugEnabled())
784 {
785 CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO;
786 }
787 CCallsignSet callsigns;
788 callsigns.push_back(callsign);
789 const CUserList users = this->getUsersForCallsigns(callsigns);
790 if (users.isEmpty())
791 {
792 return {};
793 }
794 return users[0];
795 }
796
798 {
799 if (!this->canUseAirspaceMonitor())
800 {
801 return {};
802 }
803 if (this->isDebugEnabled())
804 {
805 CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO;
806 }
807 return m_airspace->getClients();
808 }
809
811 {
812 if (!this->canUseAirspaceMonitor())
813 {
814 return {};
815 }
816 if (this->isDebugEnabled())
817 {
818 CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO;
819 }
820 return m_airspace->getClientsForCallsigns(callsigns);
821 }
822
824 {
825 if (!this->canUseAirspaceMonitor())
826 {
827 return false;
828 }
829 if (this->isDebugEnabled())
830 {
831 CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO;
832 }
833 return m_airspace->setOtherClient(client);
834 }
835
837 {
838 if (!this->canUseAirspaceMonitor())
839 {
840 return 0;
841 }
842 return m_airspace->removeClient(callsign);
843 }
844
846 {
847 if (!this->canUseAirspaceMonitor())
848 {
849 return false;
850 }
851 return m_airspace->autoAdjustCientGndCapability(situation);
852 }
853
855 {
856 if (!this->canUseAirspaceMonitor())
857 {
858 return false;
859 }
860 return m_airspace->addClientGndCapability(callsign);
861 }
862
863 bool CContextNetwork::setClientGndCapability(const aviation::CCallsign &callsign, bool supportGndFlag)
864 {
865 if (!this->canUseAirspaceMonitor())
866 {
867 return false;
868 }
869 return m_airspace->setClientGndCapability(callsign, supportGndFlag);
870 }
871
872 void CContextNetwork::markAsSwiftClient(const CCallsign &callsign) { m_airspace->markAsSwiftClient(callsign); }
873
875 {
876 Q_ASSERT_X(sApp->getWebDataServices(), Q_FUNC_INFO, "Missing data reader");
877 if (this->isDebugEnabled())
878 {
879 CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO;
880 }
881 return sApp->getWebDataServices()->getVatsimFsdServers();
882 }
883
884 void CContextNetwork::onFsdConnectionStatusChanged(const CConnectionStatus &from, const CConnectionStatus &to)
885 {
886 // if (this->isDebugEnabled()) { CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO << from
887 // << to; }
888
889 if (to.isDisconnected())
890 {
891 // make sure airspace is really cleaned up
892 Q_ASSERT(m_airspace);
893 m_airspace->clear();
894 }
895
896 // send 1st position
897 if (to.isConnected())
898 {
899 CLogMessage(this).info(u"Connected, own aircraft %1") << this->ownAircraft().getCallsignAsString();
900
901 if (m_fsdClient)
902 {
903 const CServer server = m_fsdClient->getServer();
904 emit this->connectedServerChanged(server);
905 }
906 }
907
908 // send as message
909 static const QString chgMsg("Connection status changed from '%1' to '%2'");
910 CLogMessage(this).info(chgMsg) << from.toQString() << to.toQString();
911
912 // send as own signal
913 emit this->connectionStatusChanged(from, to);
914 }
915
916 void CContextNetwork::onReadyForModelMatching(const CSimulatedAircraft &aircraft)
917 {
918 m_readyForModelMatching.enqueue(aircraft);
919 }
920
921 void CContextNetwork::emitReadyForMatching()
922 {
923 if (m_readyForModelMatching.isEmpty())
924 {
925 return;
926 }
927 if (!sApp || sApp->isShuttingDown())
928 {
929 return;
930 }
931
932 const CSimulatedAircraft aircraft = m_readyForModelMatching.dequeue();
933 if (!this->isAircraftInRange(aircraft.getCallsign()))
934 {
935 return;
936 }
937 emit this->readyForModelMatching(aircraft);
938 }
939
940 void CContextNetwork::createRelayMessageToPartnerCallsign(const CTextMessage &textMessage,
941 const CCallsign &partnerCallsign,
942 CTextMessageList &relayedMessages)
943 {
944 if (textMessage.isEmpty())
945 {
946 return;
947 }
948 if (partnerCallsign.isEmpty())
949 {
950 return;
951 }
952 if (textMessage.getSenderCallsign() == partnerCallsign)
953 {
954 return;
955 } // no round trips
956
957 CTextMessage modified(textMessage);
958 modified.makeRelayedMessage(partnerCallsign);
959 relayedMessages.push_back(modified);
960 }
961
962 void CContextNetwork::xCtxSimulatorRenderRestrictionsChanged(bool restricted, bool enabled, int maxAircraft,
963 const CLength &maxRenderedDistance)
964 {
965 // mainly passing changed restrictions from simulator to network
966 if (!m_airspace)
967 {
968 return;
969 }
970 if (!m_airspace->analyzer())
971 {
972 return;
973 }
974 m_airspace->analyzer()->setSimulatorRenderRestrictionsChanged(restricted, enabled, maxAircraft,
975 maxRenderedDistance);
976 }
977
978 void CContextNetwork::xCtxSimulatorStatusChanged(int status)
979 {
980 const ISimulator::SimulatorStatus simStatus = static_cast<ISimulator::SimulatorStatus>(status);
982 {
983 const QPointer<CContextSimulator> sim = this->getRuntime()->getCContextSimulator();
984 this->setSimulationEnvironmentProvider(sim ? sim->simulator() : nullptr);
985 const CSimulatorInfo simInfo = sim ? sim->getSimulatorPluginInfo().getSimulatorInfo() : CSimulatorInfo();
986
987 m_simulatorConnected++;
988 m_lastConnectedSim = simInfo;
989 }
990 else
991 {
993 }
994 }
995
996 bool CContextNetwork::canUseFsd() const { return sApp && !sApp->isShuttingDown() && m_fsdClient; }
997
998 bool CContextNetwork::canUseAirspaceMonitor() const { return sApp && !sApp->isShuttingDown() && m_airspace; }
999
1000 void CContextNetwork::updateMetars(const CMetarList &metars)
1001 {
1002 if (this->isDebugEnabled())
1003 {
1004 CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO;
1005 }
1006 CLogMessage(this).info(u"%1 METARs updated") << metars.size();
1007 }
1008
1009 void CContextNetwork::onChangedAtisReceived(const CCallsign &callsign)
1010 {
1011 Q_UNUSED(callsign)
1012 m_dsAtcStationsOnlineChanged.inputSignal(); // the ATIS data are stored in the station object
1013 }
1014
1015 void CContextNetwork::onTextMessagesReceived(const CTextMessageList &messages)
1016 {
1017 if (messages.isEmpty())
1018 {
1019 return;
1020 }
1021
1022 const CCallsign partnerCallsign = this->getPartnerCallsign();
1023 const CCallsign ownCallsign = this->ownAircraft().getCallsign();
1024
1025 CTextMessageList textMessages = messages.withRelayedToPrivateMessages();
1026 CTextMessageList partnerMessages;
1027
1028 if (!partnerCallsign.isEmpty())
1029 {
1030 partnerMessages = textMessages.findBySender(partnerCallsign);
1031 const CTextMessageList relayedSentMessages =
1032 partnerMessages.findByNotForRecipient(ownCallsign).markedAsSent();
1033 partnerMessages =
1034 partnerMessages.findByRecipient(ownCallsign); // really send to me as PM and not a forwared one
1035
1036 // avoid infinite rountrips
1037 textMessages = textMessages.withRemovedPrivateMessagesFromCallsign(partnerCallsign);
1038
1039 // fake those as sent by myself
1040 for (const CTextMessage &rsm : relayedSentMessages)
1041 {
1042 emit this->textMessageSent(rsm);
1043 }
1044 }
1045
1046 // 1) relayed messaged "now look like PMs"
1047 // 2) all messaged of partner are EXCLUDED
1048 if (!textMessages.isEmpty())
1049 {
1050 emit this->textMessagesReceived(textMessages);
1051 }
1052 if (!partnerMessages.isEmpty())
1053 {
1054 emit this->textMessagesReceived(partnerMessages);
1055 }
1056
1057 if (textMessages.containsPrivateMessages())
1058 {
1059 const CTextMessageList supMessages(messages.getSupervisorMessages());
1060 for (const CTextMessage &m : supMessages)
1061 {
1062 emit this->supervisorTextMessageReceived(m);
1063 }
1064
1065 // part to send to partner, "forward/relay" to partner
1066 if (!partnerCallsign.isEmpty())
1067 {
1068 // IMPORTANT: partner messages already received
1069 CTextMessageList relayedMessages;
1070 const CTextMessageList privateMessages = messages.getPrivateMessages();
1071 for (const CTextMessage &m : privateMessages)
1072 {
1073 this->createRelayMessageToPartnerCallsign(m, partnerCallsign, relayedMessages);
1074 }
1075
1076 if (!relayedMessages.isEmpty())
1077 {
1078 QPointer<CContextNetwork> myself(this);
1079 QTimer::singleShot(10, this, [=] {
1080 if (myself)
1081 {
1082 myself->sendTextMessages(relayedMessages);
1083 }
1084 });
1085 }
1086 } // relay to partner
1087 }
1088 }
1089
1090 void CContextNetwork::onTextMessageSent(const CTextMessage &message)
1091 {
1092 if (message.isEmpty())
1093 {
1094 return;
1095 }
1096 if (message.isRelayedMessage())
1097 {
1098 return;
1099 }
1100
1101 if (message.isPrivateMessage())
1102 {
1103 // forward messages which are NO real PMs tp the partner
1104 const CCallsign partnerCallsign = this->getPartnerCallsign();
1105 if (!partnerCallsign.isEmpty() && message.getRecipientCallsign() != partnerCallsign)
1106 {
1107 QPointer<CContextNetwork> myself(this);
1108 CTextMessageList relayedMessages;
1109 this->createRelayMessageToPartnerCallsign(message, partnerCallsign, relayedMessages);
1110 if (!relayedMessages.isEmpty())
1111 {
1112 QTimer::singleShot(10, this, [=] {
1113 if (myself)
1114 {
1115 myself->sendTextMessages(relayedMessages);
1116 }
1117 });
1118 }
1119 }
1120 }
1121
1122 emit this->textMessageSent(message);
1123 }
1124
1125 CSimulatedAircraft CContextNetwork::ownAircraft() const
1126 {
1127 Q_ASSERT(this->getRuntime()); // must never be null
1128
1129 if (!this->getRuntime()->getIContextOwnAircraft())
1130 {
1131 return {};
1132 }
1134 }
1135
1137 {
1138 return m_fsdClient ? m_fsdClient->getPresetPartnerCallsign() : CCallsign();
1139 }
1140
1141 bool CContextNetwork::isValidPartnerCallsign(const CCallsign &ownCallsign, const CCallsign &partnerCallsign)
1142 {
1143 if (partnerCallsign.isEmpty())
1144 {
1145 return false;
1146 }
1147 if (ownCallsign == partnerCallsign)
1148 {
1149 return false;
1150 } // MUST NOT be the same
1151 return true;
1152 }
1153
1155 {
1156 if (this->isDebugEnabled())
1157 {
1158 CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO;
1159 }
1160 CAtcStationList stations = m_airspace->getAtcStationsOnline();
1161 if (!recalculateDistance || !this->getIContextOwnAircraft())
1162 {
1163 return stations;
1164 }
1166 this->getIContextOwnAircraft()->getOwnAircraftSituation());
1167 return stations;
1168 }
1169
1171 {
1172 if (!this->getIContextOwnAircraft())
1173 {
1174 return {};
1175 }
1177 const CAtcStationList stations = m_airspace->getAtcStationsOnline().findClosest(number, ownSituation);
1178 return stations;
1179 }
1180
1182 {
1183 if (this->isDebugEnabled())
1184 {
1185 CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO;
1186 }
1187 return m_airspace->getAircraftInRange();
1188 }
1189
1191 {
1192 if (this->isDebugEnabled())
1193 {
1194 CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO;
1195 }
1196 return m_airspace->getAircraftInRangeCallsigns();
1197 }
1198
1200 {
1201 if (this->isDebugEnabled())
1202 {
1203 CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO;
1204 }
1205 return m_airspace->getAircraftInRangeCount();
1206 }
1207
1209 {
1210 if (this->isDebugEnabled())
1211 {
1212 CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO;
1213 }
1214 return m_airspace->isAircraftInRange(callsign);
1215 }
1216
1217 bool CContextNetwork::isVtolAircraft(const CCallsign &callsign) const
1218 {
1219 if (this->isDebugEnabled())
1220 {
1221 CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO;
1222 }
1223 return m_airspace->isVtolAircraft(callsign);
1224 }
1225
1227 {
1228 if (this->isDebugEnabled())
1229 {
1230 CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO << callsign;
1231 }
1232 return m_airspace->getAircraftInRangeForCallsign(callsign);
1233 }
1234
1236 {
1237 if (this->isDebugEnabled())
1238 {
1239 CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO << callsign;
1240 }
1241 return m_airspace->getAircraftInRangeModelForCallsign(callsign);
1242 }
1243
1245 {
1246 if (this->isDebugEnabled())
1247 {
1248 CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO << callsign;
1249 }
1250 return m_airspace->getReverseLookupMessages(callsign);
1251 }
1252
1254 {
1255 if (this->isDebugEnabled())
1256 {
1257 CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO;
1258 }
1259 return m_airspace->isReverseLookupMessagesEnabled();
1260 }
1261
1262 void CContextNetwork::enableReverseLookupMessages(ReverseLookupLogging enable)
1263 {
1264 if (this->isDebugEnabled())
1265 {
1266 CLogMessage(this, CLogCategories::contextSlot()).debug() << enable;
1267 }
1268 const ReverseLookupLogging revEnabled = m_airspace->isReverseLookupMessagesEnabled();
1269 if (revEnabled == enable)
1270 {
1271 return;
1272 }
1273 m_airspace->enableReverseLookupMessages(enable);
1275 }
1276
1278 {
1279 if (this->isDebugEnabled())
1280 {
1281 CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO << callsign;
1282 }
1283 return m_airspace->getAircraftPartsHistory(callsign);
1284 }
1285
1287 {
1288 if (this->isDebugEnabled())
1289 {
1290 CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO << callsign;
1291 }
1292 return m_airspace->remoteAircraftParts(callsign);
1293 }
1294
1296 {
1297 if (this->isDebugEnabled())
1298 {
1299 CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO;
1300 }
1301 return m_airspace->getRemoteAircraftSupportingPartsCount();
1302 }
1303
1305 {
1306 if (this->isDebugEnabled())
1307 {
1308 CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO;
1309 }
1310 return m_airspace->isAircraftPartsHistoryEnabled();
1311 }
1312
1314 {
1315 if (this->isDebugEnabled())
1316 {
1317 CLogMessage(this, CLogCategories::contextSlot()).debug() << enabled;
1318 }
1319 m_airspace->enableAircraftPartsHistory(enabled);
1321 }
1322
1324 {
1325 if (this->isDebugEnabled())
1326 {
1327 CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO;
1328 }
1329 return m_airspace->aircraftSituationsAdded();
1330 }
1331
1333 {
1334 if (this->isDebugEnabled())
1335 {
1336 CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO;
1337 }
1338 return m_airspace->aircraftPartsAdded();
1339 }
1340
1342 {
1343 if (this->isDebugEnabled())
1344 {
1345 CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO;
1346 }
1347 return m_airspace->situationsLastModified(callsign);
1348 }
1349
1350 qint64 CContextNetwork::partsLastModified(const CCallsign &callsign) const
1351 {
1352 if (this->isDebugEnabled())
1353 {
1354 CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO;
1355 }
1356 return m_airspace->partsLastModified(callsign);
1357 }
1358
1360 {
1361 if (this->isDebugEnabled())
1362 {
1363 CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO;
1364 }
1365 if (!m_fsdClient)
1366 {
1367 return {};
1368 }
1369 return m_fsdClient->getNetworkStatisticsAsText(reset, separator);
1370 }
1371
1373 {
1374 if (this->isDebugEnabled())
1375 {
1376 CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO;
1377 }
1378 if (!m_fsdClient)
1379 {
1380 return false;
1381 }
1382 return m_fsdClient->setStatisticsEnable(enabled);
1383 }
1384
1385 bool CContextNetwork::testAddAltitudeOffset(const CCallsign &callsign, const CLength &offset)
1386 {
1387 if (this->isDebugEnabled())
1388 {
1389 CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO;
1390 }
1391 return m_airspace->testAddAltitudeOffset(callsign, offset);
1392 }
1393
1395 {
1396 if (!m_fsdClient)
1397 {
1398 return {};
1399 }
1400 return m_fsdClient->getPresetValues();
1401 }
1402
1404 {
1405 if (this->isDebugEnabled())
1406 {
1407 CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO << callsign;
1408 }
1409 return m_airspace->getAtcStationsOnline().findFirstByCallsign(callsign);
1410 }
1411
1413 {
1414 if (this->isDebugEnabled())
1415 {
1416 CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO;
1417 }
1418 return m_airspace->getAtcStationsOnline().findIfFrequencyIsWithinSpacing(frequency);
1419 }
1420
1422 {
1423 if (this->isDebugEnabled())
1424 {
1425 CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO << callsign;
1426 }
1427 return m_airspace->getAtcStationsOnline().containsCallsign(callsign);
1428 }
1429
1431 {
1432 if (!canUseAirspaceMonitor())
1433 {
1434 return;
1435 }
1436 if (this->isDebugEnabled())
1437 {
1438 CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO;
1439 }
1440 if (!this->isConnected())
1441 {
1442 return;
1443 }
1444
1445 m_airspace->requestAircraftDataUpdates();
1446 if (m_requestAircraftDataTimer)
1447 {
1448 m_requestAircraftDataTimer->start();
1449 } // restart
1450 }
1451
1453 {
1454 if (!canUseAirspaceMonitor())
1455 {
1456 return;
1457 }
1458 if (this->isDebugEnabled())
1459 {
1460 CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO;
1461 }
1462 if (!this->isConnected())
1463 {
1464 return;
1465 }
1466
1467 m_airspace->requestAtisUpdates();
1468 if (m_requestAtisTimer)
1469 {
1470 m_requestAtisTimer->start();
1471 } // restart
1472 }
1473
1474 bool CContextNetwork::updateAircraftEnabled(const CCallsign &callsign, bool enabledForRendering)
1475 {
1476 if (!canUseAirspaceMonitor())
1477 {
1478 return false;
1479 }
1480 if (this->isDebugEnabled())
1481 {
1482 CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO << callsign << enabledForRendering;
1483 }
1484 const bool c = m_airspace->updateAircraftEnabled(callsign, enabledForRendering);
1485 if (c)
1486 {
1487 const CSimulatedAircraft aircraft(this->getAircraftInRangeForCallsign(callsign));
1488 Q_ASSERT_X(!aircraft.getCallsign().isEmpty(), Q_FUNC_INFO, "missing callsign");
1489 emit this->changedRemoteAircraftEnabled(aircraft);
1490 }
1491 return c;
1492 }
1493
1494 bool CContextNetwork::setAircraftEnabledFlag(const CCallsign &callsign, bool enabledForRendering)
1495 {
1496 if (!canUseAirspaceMonitor())
1497 {
1498 return false;
1499 }
1500 if (this->isDebugEnabled())
1501 {
1502 CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO << callsign;
1503 }
1504 return m_airspace->setAircraftEnabledFlag(callsign, enabledForRendering);
1505 }
1506
1508 const CIdentifier &originator)
1509 {
1510 if (!canUseAirspaceMonitor())
1511 {
1512 return false;
1513 }
1514 if (this->isDebugEnabled())
1515 {
1516 CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO << callsign << model;
1517 }
1518 const bool c = m_airspace->updateAircraftModel(callsign, model, originator);
1519 if (c)
1520 {
1521 const CSimulatedAircraft aircraft(this->getAircraftInRangeForCallsign(callsign));
1522 Q_ASSERT_X(!aircraft.getCallsign().isEmpty(), Q_FUNC_INFO, "missing callsign");
1523 emit this->changedRemoteAircraftModel(aircraft, originator); // update aircraft model
1524 }
1525 return c;
1526 }
1527
1529 const CIdentifier &originator)
1530 {
1531 if (!canUseAirspaceMonitor())
1532 {
1533 return false;
1534 }
1535 if (this->isDebugEnabled())
1536 {
1537 CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO << callsign << model;
1538 }
1539 const bool c = m_airspace->updateAircraftNetworkModel(callsign, model, originator);
1540 if (c)
1541 {
1542 const CSimulatedAircraft aircraft(this->getAircraftInRangeForCallsign(callsign));
1543 emit this->changedRemoteAircraftModel(aircraft, originator); // updated network model
1544 }
1545 return c;
1546 }
1547
1548 bool CContextNetwork::updateFastPositionEnabled(const CCallsign &callsign, bool enableFastPositonUpdates)
1549 {
1550 if (!canUseAirspaceMonitor())
1551 {
1552 return false;
1553 }
1554 if (this->isDebugEnabled())
1555 {
1557 << Q_FUNC_INFO << callsign << enableFastPositonUpdates;
1558 }
1559 const bool c = m_airspace->updateFastPositionEnabled(callsign, enableFastPositonUpdates);
1560 if (c)
1561 {
1562 const CSimulatedAircraft aircraft(this->getAircraftInRangeForCallsign(callsign));
1563 CLogMessage(this).info(u"Callsign '%1' fast positions '%2'")
1564 << aircraft.getCallsign() << swift::misc::boolToOnOff(aircraft.fastPositionUpdates());
1565 emit this->changedFastPositionUpdates(aircraft);
1566 }
1567 return c;
1568 }
1569
1570 bool CContextNetwork::updateAircraftSupportingGndFLag(const CCallsign &callsign, bool supportGndFlag)
1571 {
1572 if (this->isDebugEnabled())
1573 {
1574 CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO << callsign << supportGndFlag;
1575 }
1576 const bool c = m_airspace->setClientGndCapability(callsign, supportGndFlag);
1577 if (c)
1578 {
1579 const CSimulatedAircraft aircraft(this->getAircraftInRangeForCallsign(callsign));
1580 CLogMessage(this).info(u"Callsign '%1' set gnd.capability: %2")
1581 << aircraft.getCallsign() << boolToOnOff(aircraft.isSupportingGndFlag());
1582 emit this->changedGndFlagCapability(aircraft);
1583 }
1584 return c;
1585 }
1586
1588 {
1589 if (!canUseAirspaceMonitor())
1590 {
1591 return false;
1592 }
1593 if (this->isDebugEnabled())
1594 {
1596 << Q_FUNC_INFO << callsign << cg.valueRoundedWithUnit(1);
1597 }
1598 const bool c = m_airspace->updateCG(callsign, cg);
1599 return c;
1600 }
1601
1603 {
1604 if (!canUseAirspaceMonitor())
1605 {
1606 return {};
1607 }
1608 if (this->isDebugEnabled())
1609 {
1611 << Q_FUNC_INFO << modelString << cg.valueRoundedWithUnit(1);
1612 }
1613 const CCallsignSet set = m_airspace->updateCGForModel(modelString, cg);
1614 return set;
1615 }
1616
1618 const QString &modelString)
1619 {
1620 if (!canUseAirspaceMonitor())
1621 {
1622 return false;
1623 }
1624 if (this->isDebugEnabled())
1625 {
1627 << Q_FUNC_INFO << callsign << cg.valueRoundedWithUnit(1) << modelString;
1628 }
1629 const bool c = m_airspace->updateCGAndModelString(callsign, cg, modelString);
1630 return c;
1631 }
1632
1633 bool CContextNetwork::updateAircraftRendered(const CCallsign &callsign, bool rendered)
1634 {
1635 if (!canUseAirspaceMonitor())
1636 {
1637 return false;
1638 }
1639 const bool c = m_airspace->updateAircraftRendered(callsign, rendered);
1640 return c;
1641 }
1642
1644 {
1645 if (!canUseAirspaceMonitor())
1646 {
1647 return 0;
1648 }
1649 const int c = m_airspace->updateMultipleAircraftRendered(callsigns, rendered);
1650 return c;
1651 }
1652
1654 {
1655 if (!canUseAirspaceMonitor())
1656 {
1657 return 0;
1658 }
1659 const int c = m_airspace->updateMultipleAircraftEnabled(callsigns, enabled);
1660 return c;
1661 }
1662
1665 bool *setForOnGroundPosition)
1666 {
1667 if (!canUseAirspaceMonitor())
1668 {
1669 return 0;
1670 }
1671 return m_airspace->updateAircraftGroundElevation(callsign, elevation, info, setForOnGroundPosition);
1672 }
1673
1675 {
1676 if (!canUseAirspaceMonitor())
1677 {
1678 return;
1679 }
1680 m_airspace->updateMarkAllAsNotRendered();
1681 }
1682
1684 {
1685 if (!canUseAirspaceMonitor())
1686 {
1687 return {};
1688 }
1689 return m_airspace->getCGFromDB(callsign);
1690 }
1691
1693 {
1694 if (!canUseAirspaceMonitor())
1695 {
1696 return {};
1697 }
1698 return m_airspace->getCGFromDB(modelString);
1699 }
1700
1701 void CContextNetwork::rememberCGFromDB(const CLength &cgFromDB, const CCallsign &callsign)
1702 {
1703 if (!canUseAirspaceMonitor())
1704 {
1705 return;
1706 }
1707 m_airspace->rememberCGFromDB(cgFromDB, callsign);
1708 }
1709
1710 void CContextNetwork::rememberCGFromDB(const CLength &cgFromDB, const QString &modelString)
1711 {
1712 if (!canUseAirspaceMonitor())
1713 {
1714 return;
1715 }
1716 m_airspace->rememberCGFromDB(cgFromDB, modelString);
1717 }
1718
1720 {
1721 if (!canUseAirspaceMonitor())
1722 {
1723 return 0;
1724 }
1725 if (this->isDebugEnabled())
1726 {
1727 CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO;
1728 }
1729 return m_airspace->reInitializeAllAircraft();
1730 }
1731
1733 {
1734 if (!canUseAirspaceMonitor())
1735 {
1736 return {};
1737 }
1738 return m_airspace->getLatestAirspaceAircraftSnapshot();
1739 }
1740
1742 const CLength &range, int minValues,
1743 int sufficientValues) const
1744 {
1745 if (!canUseAirspaceMonitor())
1746 {
1747 return {};
1748 }
1749 return m_airspace->averageElevationOfNonMovingAircraft(reference, range, minValues, sufficientValues);
1750 }
1751
1752 void CContextNetwork::setClients(const CClientList &clients) { m_airspace->setClients(clients); }
1753
1754 void CContextNetwork::clearClients() { m_airspace->clearClients(); }
1755
1757 {
1758 if (!canUseAirspaceMonitor())
1759 {
1760 return {};
1761 }
1762 return m_airspace->getClientOrDefaultForCallsign(callsign);
1763 }
1764
1766 {
1767 if (!canUseAirspaceMonitor())
1768 {
1769 return false;
1770 }
1771 return m_airspace->hasClientInfo(callsign);
1772 }
1773
1775 {
1776 if (!canUseAirspaceMonitor())
1777 {
1778 return false;
1779 }
1780 return m_airspace->addNewClient(client);
1781 }
1782
1784 bool skipEqualValues)
1785 {
1786 if (!canUseAirspaceMonitor())
1787 {
1788 return 0;
1789 }
1790 return m_airspace->updateOrAddClient(callsign, vm, skipEqualValues);
1791 }
1792
1794 {
1795 if (this->isDebugEnabled())
1796 {
1797 CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO << callsigns;
1798 }
1799 Q_ASSERT(m_fsdClient);
1800 m_fsdClient->setInterimPositionReceivers(callsigns);
1801 }
1802
1804 {
1805 if (this->isDebugEnabled())
1806 {
1807 CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO;
1808 }
1809 Q_ASSERT(m_fsdClient);
1810 return m_fsdClient->getInterimPositionReceivers();
1811 }
1812
1814 {
1815 if (!this->canUseFsd())
1816 {
1817 return;
1818 }
1819 if (this->isDebugEnabled())
1820 {
1821 CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO << callsign;
1822 }
1823 m_fsdClient->sendClientQueryAircraftConfig(callsign);
1824 }
1825
1827 {
1828 if (!this->canUseAirspaceMonitor())
1829 {
1830 return;
1831 }
1832 if (this->isDebugEnabled())
1833 {
1834 CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO << number;
1835 }
1836 m_airspace->testCreateDummyOnlineAtcStations(number);
1837 }
1838
1839 void CContextNetwork::testAddAircraftParts(const CCallsign &callsign, const CAircraftParts &parts, bool incremental)
1840 {
1841 if (!this->canUseAirspaceMonitor())
1842 {
1843 return;
1844 }
1845 if (this->isDebugEnabled())
1846 {
1847 CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO << parts << incremental;
1848 }
1849 m_airspace->testAddAircraftParts(callsign, parts, incremental);
1850 }
1851
1853 {
1854 if (!this->canUseFsd())
1855 {
1856 return;
1857 }
1858 if (this->isDebugEnabled())
1859 {
1860 CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO << callsign.asString();
1861 }
1862 emit this->fsdClient()->atisReplyReceived(callsign, msg);
1863 }
1864
1866 {
1867 if (!this->canUseFsd())
1868 {
1869 return;
1870 }
1871 if (this->isDebugEnabled())
1872 {
1873 CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO << textMessages.toQString();
1874 }
1875 emit this->fsdClient()->textMessagesReceived(textMessages);
1876 }
1877
1879 {
1880 if (this->isDebugEnabled())
1881 {
1882 CLogMessage(this, CLogCategories::contextSlot()).debug() << Q_FUNC_INFO << airportIcaoCode;
1883 }
1884 if (!sApp || !sApp->getWebDataServices())
1885 {
1886 return {};
1887 }
1888 return sApp->getWebDataServices()->getMetarForAirport(airportIcaoCode);
1889 }
1890
1893 {
1894 Q_ASSERT_X(receiver, Q_FUNC_INFO, "Missing receiver");
1895
1896 // bind does not allow to define connection type, so we use receiver as workaround
1897 const QMetaObject::Connection uc; // unconnected
1898 const QMetaObject::Connection c = rawFsdMessageReceivedSlot ? connect(m_fsdClient, &CFSDClient::rawFsdMessage,
1899 receiver, rawFsdMessageReceivedSlot) :
1900 uc;
1901 Q_ASSERT_X(c || !rawFsdMessageReceivedSlot, Q_FUNC_INFO, "connect failed");
1902 return c;
1903 }
1904} // namespace swift::core::context
SWIFT_CORE_EXPORT swift::core::CApplication * sApp
Single instance of application object.
static const QVersionNumber & getVersion()
Version as QVersionNumber.
static bool isLocalDeveloperDebugBuild()
Local build for developers.
Keeps track of other entities in the airspace: aircraft, ATC stations, etc. Central instance of data ...
void atcStationDisconnected(const swift::misc::aviation::CAtcStation &station)
ATC station disconnected.
void readyForModelMatching(const swift::misc::simulation::CSimulatedAircraft &remoteAircraft)
Ready for model matching.
void changedAtisReceived(const swift::misc::aviation::CCallsign &callsign)
An ATIS has been received.
void changedAtcStationsOnline()
Online ATC stations were changed.
void clear()
Clear the contents.
bool isShuttingDown() const
Is application shutting down?
ContextMode
How to handle a given context.
context::CContextSimulator * getCContextSimulator()
Context for simulator.
context::CContextOwnAircraft * getCContextOwnAircraft()
Context for own aircraft.
static bool isAnyConnectedStatus(SimulatorStatus status)
Any connected status?
void rememberCGFromDB(const swift::misc::physical_quantities::CLength &cgFromDB, const swift::misc::aviation::CCallsign &callsign)
CG values from DB.
bool setNetworkStatisticsEnable(bool enabled)
Statistics enable/disable.
swift::misc::aviation::CCallsignSet updateCGForModel(const QString &modelString, const swift::misc::physical_quantities::CLength &cg)
Update the CG for this model string.
swift::misc::network::CLoginMode getLoginMode() const
Login mode.
void markAsSwiftClient(const swift::misc::aviation::CCallsign &callsign)
Mark as other swift client.
swift::misc::weather::CMetar getMetarForAirport(const swift::misc::aviation::CAirportIcaoCode &airportIcaoCode) const
Get METAR, if not available request it (code such as EDDF, KLAX).
swift::misc::CStatusMessageList getAircraftPartsHistory(const swift::misc::aviation::CCallsign &callsign) const
Get aircraft parts history.
void setFastPositionEnabledCallsigns(swift::misc::aviation::CCallsignSet &callsigns)
Callsigns enabled for fast position updates.
int updateMultipleAircraftRendered(const swift::misc::aviation::CCallsignSet &callsigns, bool rendered)
Set aircraft rendered.
swift::misc::MillisecondsMinMaxMean remoteAircraftSituationsTimestampDifferenceMinMaxMean(const swift::misc::aviation::CCallsign &callsign) const
Average update time.
swift::misc::aviation::CCallsignSet remoteAircraftSupportingParts() const
Remote aircraft supporting parts.
bool isRemoteAircraftSupportingParts(const swift::misc::aviation::CCallsign &callsign) const
Parts supported?
swift::misc::aviation::CCallsignSet getFastPositionEnabledCallsigns() const
Callsigns enabled for fast position updates.
swift::misc::aviation::CCallsign getPartnerCallsign() const
Partner callsign if any.
swift::misc::aviation::CAircraftPartsList getRemoteAircraftParts(const swift::misc::aviation::CCallsign &callsign) const
Get remote aircraft parts.
swift::misc::aviation::CAtcStationList getAtcStationsOnline(bool recalculateDistance) const
The ATC list with online ATC controllers.
int updateOrAddClient(const swift::misc::aviation::CCallsign &callsign, const swift::misc::CPropertyIndexVariantMap &vm, bool skipEqualValues=true)
Update or add a client.
bool hasClientInfo(const swift::misc::aviation::CCallsign &callsign) const
Client info for given callsign?
QStringList getNetworkPresetValues() const
Network preset values.
void enableAircraftPartsHistory(bool enabled)
Enable storing of aircraft parts.
int getRemoteAircraftSupportingPartsCount() const
Number of aircraft supporting parts.
qint64 partsLastModified(const swift::misc::aviation::CCallsign &callsign) const
When last modified.
swift::misc::geo::CElevationPlane averageElevationOfNonMovingAircraft(const swift::misc::aviation::CAircraftSituation &reference, const swift::misc::physical_quantities::CLength &range, int minValues=1, int sufficientValues=2) const
Average elevation of aircraft in given range, which are NOT moving.
swift::misc::aviation::CAircraftSituationList latestOnGroundProviderElevations() const
Latest aircraft situation "on ground" having a provider elevation.
void setClients(const swift::misc::network::CClientList &clients)
Set other clients.
bool updateAircraftEnabled(const swift::misc::aviation::CCallsign &callsign, bool enabledForRendering)
Enable/disable aircraft and follow up logic like sending signals.
swift::misc::CStatusMessageList getReverseLookupMessages(const swift::misc::aviation::CCallsign &callsign) const
Get reverse lookup messages.
swift::misc::aviation::CAircraftSituationList latestRemoteAircraftSituations() const
Latest aircraft situation for all callsigns.
swift::misc::aviation::CAtcStation getOnlineStationForCallsign(const swift::misc::aviation::CCallsign &callsign) const
Online station for callsign.
bool addClientGndCapability(const swift::misc::aviation::CCallsign &callsign)
Add gnd.flag capability.
int updateAircraftGroundElevation(const swift::misc::aviation::CCallsign &callsign, const swift::misc::geo::CElevationPlane &elevation, swift::misc::aviation::CAircraftSituation::GndElevationInfo info, bool *setForOnGroundPosition)
Update the ground elevation.
swift::misc::CStatusMessage disconnectFromNetwork()
Disconnect from network.
swift::misc::aviation::CAtcStationList getOnlineStationsForFrequency(const swift::misc::physical_quantities::CFrequency &frequency) const
Online stations for frequency.
swift::misc::aviation::CAircraftSituation remoteAircraftSituation(const swift::misc::aviation::CCallsign &callsign, int index) const
Rendered aircraft situations (per callsign and index).
bool isAircraftPartsHistoryEnabled() const
Is storing the aircraft parts history enabled?
swift::misc::network::CClientList getClientsForCallsigns(const swift::misc::aviation::CCallsignSet &callsigns) const
Returns a list of other clients corresponding to the given callsigns.
void sendTextMessages(const swift::misc::network::CTextMessageList &textMessages)
Text messages (radio and private chat messages).
int getAircraftInRangeCount() const
Aircraft count.
bool setAircraftEnabledFlag(const swift::misc::aviation::CCallsign &callsign, bool enabledForRendering)
Set the enabled flag without any further logic like sending signals.
int removeClient(const swift::misc::aviation::CCallsign &callsign)
Remove client.
swift::misc::network::CUserList getUsers() const
Get all users.
bool setOtherClient(const swift::misc::network::CClient &client)
Set client for its callsign.
void gracefulShutdown()
Gracefully shut down, e.g. for thread safety.
swift::misc::simulation::CSimulatedAircraftList getAircraftInRange() const
Aircraft list.
swift::misc::simulation::CAircraftModel getAircraftInRangeModelForCallsign(const swift::misc::aviation::CCallsign &callsign) const
Aircraft model for callsign.
QMetaObject::Connection connectRawFsdMessageSignal(QObject *receiver, RawFsdMessageReceivedSlot rawFsdMessageReceivedSlot)
Connect to receive raw fsd messages.
bool isOnlineStation(const swift::misc::aviation::CCallsign &callsign) const
Online station for callsign?
swift::misc::network::CServerList getVatsimFsdServers() const
Known FSD servers, available when data file was first read.
swift::misc::CStatusMessage connectToNetwork(const swift::misc::network::CServer &server, const QString &extraLiveryString, bool sendLivery, const QString &extraModelString, bool sendModelString, const swift::misc::aviation::CCallsign &partnerCallsign, swift::misc::network::CLoginMode mode)
Connect to Network.
bool updateAircraftRendered(const swift::misc::aviation::CCallsign &callsign, bool rendered)
Set aircraft rendered.
void requestAircraftDataUpdates()
Request data updates (pilot's frequencies, ATIS, ..).
int aircraftPartsAdded() const
Number of parts added.
void testAddAircraftParts(const swift::misc::aviation::CCallsign &callsign, const swift::misc::aviation::CAircraftParts &parts, bool incremental)
Inject aircraft parts for testing.
bool addNewClient(const swift::misc::network::CClient &client)
Add a new client, if existing nothing will be added.
bool updateAircraftNetworkModel(const swift::misc::aviation::CCallsign &callsign, const swift::misc::simulation::CAircraftModel &model, const swift::misc::CIdentifier &originator)
Change network model.
QList< QMetaObject::Connection > connectRemoteAircraftProviderSignals(QObject *receiver, std::function< void(const swift::misc::aviation::CAircraftSituation &)> addedSituationSlot, std::function< void(const swift::misc::aviation::CCallsign &, const swift::misc::aviation::CAircraftParts &)> addedPartsSlot, std::function< void(const swift::misc::aviation::CCallsign &)> removedAircraftSlot, std::function< void(const swift::misc::simulation::CAirspaceAircraftSnapshot &)> aircraftSnapshotSlot)
Connect signals to slot receiver. As the interface is no QObject, slots can not be connected directly...
int reInitializeAllAircraft()
Re-initialize all aircraft.
swift::misc::aviation::CAircraftSituationChangeList remoteAircraftSituationChanges(const swift::misc::aviation::CCallsign &callsign) const
Aircraft changes.
void testReceivedTextMessages(const swift::misc::network::CTextMessageList &textMessages)
Inject a text message as received.
swift::misc::network::CUserList getUsersForCallsigns(const swift::misc::aviation::CCallsignSet &callsigns) const
Users for given callsigns, e.g. for voice room resolution.
void testCreateDummyOnlineAtcStations(int number)
Create dummy ATC stations for performance tests etc.
CContextNetwork(CCoreFacadeConfig::ContextMode, CCoreFacade *runtime)
Constructor, with link to runtime.
swift::misc::physical_quantities::CLength getCGFromDB(const swift::misc::aviation::CCallsign &callsign) const
CG values from DB.
void enableReverseLookupMessages(swift::misc::simulation::ReverseLookupLogging enable)
Enable reverse lookup logging.
bool autoAdjustCientGndCapability(const swift::misc::aviation::CAircraftSituation &situation)
Adjust gnd.flag capability from situation.
swift::misc::aviation::CAtcStationList getClosestAtcStationsOnline(int number) const
The ATC list with online ATC controllers.
bool isAircraftInRange(const swift::misc::aviation::CCallsign &callsign) const
Aircraft in range.
void updateMarkAllAsNotRendered()
Mark all as not rendered.
swift::misc::simulation::CSimulatedAircraft getAircraftInRangeForCallsign(const swift::misc::aviation::CCallsign &callsign) const
Aircraft for given callsign.
void testRequestAircraftConfig(const swift::misc::aviation::CCallsign &callsign)
Request parts for callsign (from another client).
bool updateCGAndModelString(const swift::misc::aviation::CCallsign &callsign, const swift::misc::physical_quantities::CLength &cg, const QString &modelString)
Update the CG and model string.
bool isPendingConnection() const
In transition state, e.g. connecting, disconnecting.
swift::misc::aviation::CCallsignSet getAircraftInRangeCallsigns() const
Aircraft callsigns.
swift::misc::network::CClient getClientOrDefaultForCallsign(const swift::misc::aviation::CCallsign &callsign) const
Other client for the given callsigns.
static void registerHelp()
Register help.
bool updateAircraftSupportingGndFLag(const swift::misc::aviation::CCallsign &callsign, bool supportGndFlag)
Enable/disable support of gnd. flag.
void sendFlightPlan(const swift::misc::aviation::CFlightPlan &flightPlan)
Send flight plan.
int remoteAircraftSituationsCount(const swift::misc::aviation::CCallsign &callsign) const
Number of remote aircraft situations for callsign.
bool updateFastPositionEnabled(const swift::misc::aviation::CCallsign &callsign, bool enableFastPositonUpdates)
Change fast position updates.
void setSimulationEnvironmentProvider(swift::misc::simulation::ISimulationEnvironmentProvider *provider)
Set the provider.
bool testAddAltitudeOffset(const swift::misc::aviation::CCallsign &callsign, const swift::misc::physical_quantities::CLength &offset=swift::misc::physical_quantities::CLength::null())
Add altitude offset for testing.
fsd::CFSDClient * fsdClient() const
Network library.
int remoteAircraftPartsCount(const swift::misc::aviation::CCallsign &callsign) const
All parts (per callsign, time history).
int updateMultipleAircraftEnabled(const swift::misc::aviation::CCallsignSet &callsigns, bool enabled)
Enable/disable aircraft.
swift::misc::network::CServer getConnectedServer() const
Server which is connected, if not connected empty default object.
int remoteAircraftSituationChangesCount(const swift::misc::aviation::CCallsign &callsign) const
Aircraft changes count.
swift::misc::aviation::CFlightPlan loadFlightPlanFromNetwork(const swift::misc::aviation::CCallsign &callsign) const
Load flight plan (from network).
void testReceivedAtisMessage(const swift::misc::aviation::CCallsign &callsign, const swift::misc::aviation::CInformationMessage &msg)
Inject an ATIS.
bool updateAircraftModel(const swift::misc::aviation::CCallsign &callsign, const swift::misc::simulation::CAircraftModel &model, const swift::misc::CIdentifier &originator)
Change model.
swift::misc::network::CClientList getClients() const
Get other clients.
swift::misc::simulation::ReverseLookupLogging isReverseLookupMessagesEnabled() const
Enabled reverse lookup logging?
QString getNetworkStatistics(bool reset, const QString &separator)
Statistics info.
swift::misc::simulation::CAirspaceAircraftSnapshot getLatestAirspaceAircraftSnapshot() const
Current snapshot.
swift::misc::aviation::CAircraftSituationList remoteAircraftSituations(const swift::misc::aviation::CCallsign &callsign) const
Rendered aircraft situations (per callsign, time history).
qint64 situationsLastModified(const swift::misc::aviation::CCallsign &callsign) const
When last modified.
bool setClientGndCapability(const swift::misc::aviation::CCallsign &callsign, bool supportGndFlag)
Set gnd.flag capability.
swift::misc::network::CUser getUserForCallsign(const swift::misc::aviation::CCallsign &callsign) const
User for given callsign, e.g. for text messages.
int aircraftSituationsAdded() const
Number of situations added.
swift::misc::aviation::CAircraftPartsList remoteAircraftParts(const swift::misc::aviation::CCallsign &callsign) const
All parts (per callsign, time history).
bool updateCG(const swift::misc::aviation::CCallsign &callsign, const swift::misc::physical_quantities::CLength &cg)
Update the CG.
bool isVtolAircraft(const swift::misc::aviation::CCallsign &callsign) const
Is VTOL aircraft?
bool isConnected() const
Network connected?
void requestAtisUpdates()
Request ATIS updates (for all stations).
swift::misc::simulation::CSimulatedAircraft getOwnAircraft() const
Get own aircraft.
void changedLogOrDebugSettings()
Log or debug values changed.
bool isUsingImplementingObject() const
Using local implementing object?
Definition context.h:45
const IContextSimulator * getIContextSimulator() const
Context for simulator.
Definition context.cpp:72
IContextNetwork * getIContextNetwork()
Context for network.
Definition context.cpp:29
IContextOwnAircraft * getIContextOwnAircraft()
Context for own aircraft.
Definition context.cpp:44
bool isDebugEnabled() const
Debug enabled?
Definition context.cpp:62
CCoreFacade * getRuntime()
Runtime.
Definition context.h:57
void textMessageSent(const swift::misc::network::CTextMessage &sentMessage)
Text message sent (by me).
void changedAircraftInRange()
Aircraft list has been changed.
void supervisorTextMessageReceived(const swift::misc::network::CTextMessage &message)
A supervisor text message was received.
void connectedServerChanged(const swift::misc::network::CServer &server)
The connected server has been changed.
void changedFastPositionUpdates(const swift::misc::simulation::CSimulatedAircraft &aircraft)
Aircraft enabled / disabled.
void addedAircraft(const swift::misc::simulation::CSimulatedAircraft &remoteAircraft)
A new aircraft appeared.
void changedGndFlagCapability(const swift::misc::simulation::CSimulatedAircraft &aircraft)
Changed gnd. flag capability.
void muteRequestReceived(bool mute)
Mute request received.
void changedRemoteAircraftModel(const swift::misc::simulation::CSimulatedAircraft &aircraft, const swift::misc::CIdentifier &originator)
Aircraft model was changed.
void changedAtcStationsOnline()
ATC station (online) list has been changed.
void textMessagesReceived(const swift::misc::network::CTextMessageList &textMessages)
Text messages received (also private chat messages, radio channel messages).
void kicked(const QString &kickMessage)
User has been kicked from network.
std::function< void(const swift::misc::network::CRawFsdMessage &)> RawFsdMessageReceivedSlot
Raw FSD message receiver functor.
void changedRemoteAircraftEnabled(const swift::misc::simulation::CSimulatedAircraft &aircraft)
Aircraft enabled / disabled.
void connectionStatusChanged(const swift::misc::network::CConnectionStatus &from, const swift::misc::network::CConnectionStatus &to)
Connection status changed.
void atcStationDisconnected(const swift::misc::aviation::CAtcStation &atcStation)
ATC station disconnected.
void severeNetworkError(const QString &errorMessage)
Network error.
void readyForModelMatching(const swift::misc::simulation::CSimulatedAircraft &renderedAircraft)
Read for model matching.
void removedAircraft(const swift::misc::aviation::CCallsign &callsign)
An aircraft disappeared.
virtual bool updateOwnAircraftPilot(const swift::misc::network::CUser &pilot)=0
Set current pilot.
virtual swift::misc::aviation::CAircraftSituation getOwnAircraftSituation() const =0
Get own aircraft.
virtual swift::misc::simulation::CSimulatorPluginInfo getSimulatorPluginInfo() const =0
Simulator info, currently loaded plugin.
FSD client Todo: Send (interim) data updates automatically Todo Check ':' in FSD messages....
Definition fsdclient.h:85
void rawFsdMessage(const swift::misc::network::CRawFsdMessage &rawFsdMessage)
Client responses received.
void textMessagesReceived(const swift::misc::network::CTextMessageList &messages)
Client responses received.
void muteRequestReceived(bool mute)
Client responses received.
void connectionStatusChanged(swift::misc::network::CConnectionStatus oldStatus, swift::misc::network::CConnectionStatus newStatus)
Connection status has been changed.
void atisReplyReceived(const swift::misc::aviation::CCallsign &callsign, const swift::misc::aviation::CInformationMessage &atis)
We received a reply to one of our ATIS queries.
void textMessageSent(const swift::misc::network::CTextMessage &sentMessage)
We have sent a text message.
const swift::misc::network::CServer & getServer() const
Get the server.
Definition fsdclient.h:161
void killRequestReceived(const QString &reason)
Kill request (aka kicked).
void severeNetworkError(const QString &errorMessage)
Network error.
bool isEmpty() const
Synonym for empty.
Definition collection.h:197
iterator push_back(const T &value)
Synonym for insert.
Definition collection.h:244
Value object encapsulating information identifying a component of a modular distributed swift process...
Definition identifier.h:29
static const QString & contextSlot()
Context slots.
static const QString & validation()
Validation.
Class for emitting a log message.
Definition logmessage.h:27
Derived & validationError(const char16_t(&format)[N])
Set the severity to error, providing a format string, and adding the validation category.
Derived & debug()
Set the severity to debug.
Derived & info(const char16_t(&format)[N])
Set the severity to info, providing a format string.
Specialized value object compliant map for variants, based on indexes.
size_type size() const
Returns number of elements in the sequence.
Definition sequence.h:273
void push_back(const T &value)
Appends an element at the end of the sequence.
Definition sequence.h:308
bool isEmpty() const
Synonym for empty.
Definition sequence.h:285
Utility methods for simple line parsing used with the command line.
Streamable status message, e.g.
static constexpr auto SeverityInfo
Status severities.
static constexpr auto SeverityError
Status severities.
static constexpr auto SeverityWarning
Status severities.
Status messages, e.g. from Core -> GUI.
Value object encapsulating information of aircraft's parts.
Value object encapsulating a list of aircraft parts.
Value object encapsulating a list of aircraft parts.
Value object encapsulating information of an aircraft's situation.
GndElevationInfo
Where did we get elevation from?
Value object encapsulating information of airport ICAO data.
Value object encapsulating information about an ATC station.
Definition atcstation.h:38
Value object for a list of ATC stations.
CAtcStationList findIfFrequencyIsWithinSpacing(const physical_quantities::CFrequency &frequency)
Find 0..n stations with frequency (with 5 kHz spacing for .x20/.x25 and .x70/.x75).
Value object encapsulating information of a callsign.
Definition callsign.h:30
const QString & asString() const
Get callsign (normalized).
Definition callsign.h:96
bool isEmpty() const
Is empty?
Definition callsign.h:63
bool isValid() const
Valid callsign?
Definition callsign.cpp:512
Value object for a set of callsigns.
Definition callsignset.h:26
static physical_quantities::CFrequency parseComFrequency(const QString &input, physical_quantities::CPqString::SeparatorMode sep)
Parses almost any shitty string to a valid COM frequency.
static bool isValidCivilAviationFrequency(const physical_quantities::CFrequency &f)
Valid civil aviation frequency?
Definition comsystem.cpp:98
Value object for a flight plan.
Definition flightplan.h:148
Value object encapsulating information message (ATIS, METAR, TAF).
bool containsCallsign(const CCallsign &callsign) const
Contains callsign?
Plane of same elevation, can be a single point or larger area (e.g. airport).
CONTAINER findClosest(int number, const ICoordinateGeodetic &coordinate) const
Find 0..n objects closest to the given coordinate.
void calculcateAndUpdateRelativeDistanceAndBearing(const ICoordinateGeodetic &position)
Calculate distances.
QString toQString(bool i18n=false) const
Cast as QString.
Definition mixinstring.h:74
Another client software.
Definition client.h:27
Value object encapsulating a list of voice rooms.
Definition clientlist.h:27
Value object encapsulating information about a connection status.
bool isDisconnected() const
Query status.
Value object encapsulating information about login mode.
Definition loginmode.h:18
LoginMode getLoginMode() const
Get login mode.
Definition loginmode.h:40
@ Observer
Login as observer.
Definition loginmode.h:24
void setLoginMode(LoginMode mode)
Set login mode.
Definition loginmode.h:43
static bool canConnect(const QString &hostAddress, int port, QString &message, int timeoutMs=getTimeoutMs())
Can connect?
Value object encapsulating information of a FSD server.
Definition server.h:28
int getPort() const
Get port.
Definition server.h:93
const QString & getAddress() const
Get address.
Definition server.h:57
const CUser & getUser() const
Get user.
Definition server.h:63
Value object encapsulating a list of servers.
Definition serverlist.h:23
Value object encapsulating information of a text message.
Definition textmessage.h:31
bool isRelayedMessage() const
Is relayed message.
void setMessage(const QString &message)
Set message.
bool isPrivateMessage() const
Is private message?
void setSenderCallsign(const aviation::CCallsign &callsign)
Set callsign (from).
Definition textmessage.h:57
bool isEmpty() const
Empty message.
Definition textmessage.h:90
void setRecipientCallsign(const aviation::CCallsign &callsign)
Set callsign (recipient).
Definition textmessage.h:63
void setFrequency(const physical_quantities::CFrequency &frequency)
Set frequency.
Definition textmessage.h:99
const aviation::CCallsign & getRecipientCallsign() const
Get callsign (to).
Definition textmessage.h:60
const aviation::CCallsign & getSenderCallsign() const
Get callsign (from).
Definition textmessage.h:54
Value object encapsulating a list of text messages.
CTextMessageList withRemovedPrivateMessagesFromCallsign(const aviation::CCallsign &callsign) const
With removed private messages from callsign.
bool containsPrivateMessages() const
Contains private messages?
CTextMessageList findByNotForRecipient(const swift::misc::aviation::CCallsign &recipient) const
Find by recipient is NOT addressed.
CTextMessageList findBySender(const swift::misc::aviation::CCallsign &sender) const
Find by sender.
CTextMessageList getPrivateMessages() const
Private messages.
CTextMessageList getSupervisorMessages() const
Supervisor messages.
CTextMessageList withRelayedToPrivateMessages() const
List with relayed messages (if any) as private messages.
CTextMessageList findByRecipient(const swift::misc::aviation::CCallsign &recipient) const
Find by recipient.
CTextMessageList markedAsSent()
Marked as sent.
Value object encapsulating information of a user.
Definition user.h:28
bool hasCredentials() const
Valid credentials?
Definition user.h:77
Value object encapsulating a list of voice rooms.
Definition userlist.h:26
Physical unit length (length).
Definition length.h:18
static const CFrequency & FrequencyUnicom()
Unicom frequency.
Definition constants.h:29
void parseFromString(const QString &value)
Parse value from string.
QString valueRoundedWithUnit(const MU &unit, int digits=-1, bool withGroupSeparator=false, bool i18n=false) const
Value to QString with the given unit, e.g. "5.00m".
bool isPositiveWithEpsilonConsidered() const
Value >= 0 epsilon considered.
void parseFromString(const QString &time)
From string hh:mm, or hh:mm:ss, or time units such as s, min.
Definition time.cpp:48
static CTimeUnit ms()
Millisecond ms.
Definition units.h:946
Aircraft model (used by another pilot, my models on disk).
void changedAircraftInRange()
Aircraft were changed.
void addedAircraft(const swift::misc::simulation::CSimulatedAircraft &remoteAircraft)
A new aircraft appeared.
void removedAircraft(const swift::misc::aviation::CCallsign &callsign)
An aircraft disappeared.
Comprehensive information of an aircraft.
bool isSupportingGndFlag() const
Is supporting gnd.flag?
bool fastPositionUpdates() const
Support fast position updates.
const aviation::CCallsign & getCallsign() const
Get callsign.
QString getCallsignAsString() const
Get callsign.
Value object encapsulating a list of aircraft.
Simple hardcoded info about the corresponding simulator.
const CSimulatorInfo & getSimulatorInfo() const
Simulator info object.
static const aviation::CCallsign & testAltitudeOffsetCallsign()
Wildcard callsign.
Value object encapsulating information about METAR FIXME: runway visibilities FIXME: runway wind shea...
Definition metar.h:38
@ AtcInfo
Can accept ATIS responses.
Definition enums.h:135
@ IcaoEquipment
Process aircraft ICAO in flightplan as ICAO equipment code (e.g.
Definition enums.h:175
@ FastPos
Can send/receive fast position updates (pilot only).
Definition enums.h:163
@ AircraftConfig
Aircraft Config.
Definition enums.h:172
@ VisPos
Can send/receive visual position updates (pilot only).
Definition enums.h:166
@ AircraftInfo
Can send/receive modern model packets.
Definition enums.h:150
bool parseCommandLine(const QString &commandLine, const swift::misc::CIdentifier &originator)
Free functions in swift::misc.
SWIFT_MISC_EXPORT const QString & boolToOnOff(bool v)
Bool to on/off.
QObject(QObject *parent)
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
bool disconnect(const QMetaObject::Connection &connection)
bool contains(QChar ch, Qt::CaseSensitivity cs) const const
bool isEmpty() const const
QString number(double n, char format, int precision)
QByteArray toLocal8Bit() const const
QueuedConnection
void timeout()
Milliseconds minimum/maximum/mean.