swift
simulatorfs9.cpp
1 // SPDX-FileCopyrightText: Copyright (C) 2014 swift Project Community / Contributors
2 // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-swift-pilot-client-1
3 
4 #include "simulatorfs9.h"
5 
6 #include <algorithm>
7 
8 #include <QPointer>
9 #include <QTimer>
10 
11 #include "../fscommon/simulatorfscommonfunctions.h"
12 #include "directplayerror.h"
13 #include "fs9.h"
14 #include "fs9client.h"
16 #include "multiplayerpackets.h"
17 #include "registermetadata.h"
18 
19 #include "config/buildconfig.h"
20 #include "misc/logmessage.h"
22 #include "misc/propertyindexallclasses.h"
25 #include "misc/verify.h"
26 
27 using namespace swift::misc;
28 using namespace swift::misc::aviation;
29 using namespace swift::misc::network;
30 using namespace swift::misc::physical_quantities;
31 using namespace swift::misc::geo;
32 using namespace swift::misc::network;
33 using namespace swift::misc::simulation;
34 using namespace swift::misc::simulation::fscommon;
35 using namespace swift::core;
36 using namespace swift::simplugin::fscommon;
37 using namespace swift::config;
38 
39 namespace swift::simplugin::fs9
40 {
41  CSimulatorFs9::CSimulatorFs9(const CSimulatorPluginInfo &info, const QSharedPointer<CFs9Host> &fs9Host,
42  const QSharedPointer<CLobbyClient> &lobbyClient,
43  IOwnAircraftProvider *ownAircraftProvider,
44  IRemoteAircraftProvider *remoteAircraftProvider, IClientProvider *clientProvider,
45  QObject *parent)
46  : CSimulatorFsCommon(info, ownAircraftProvider, remoteAircraftProvider, clientProvider, parent),
47  m_fs9Host(fs9Host), m_lobbyClient(lobbyClient), m_fsuipc(new CFsuipc(this))
48  {
49  // disabled CG/elevation parts
50  this->setSimulationProviderEnabled(false, false);
51 
54  connect(lobbyClient.data(), &CLobbyClient::disconnected, this, [=] { this->emitSimulatorCombinedStatus(); });
55 
56  this->setDefaultModel({ "Boeing 737-400", CAircraftModel::TypeModelMatchingDefaultModel,
57  "B737-400 default model", CAircraftIcaoCode("B734", "L2J") });
58  }
59 
60  bool CSimulatorFs9::isConnected() const { return m_simConnected; }
61 
63  {
64  Q_ASSERT_X(m_fs9Host, Q_FUNC_INFO, "No FS9 host");
65  if (!m_fs9Host->isConnected()) { return false; } // host not available, we quit
66 
67  Q_ASSERT_X(m_fsuipc, Q_FUNC_INFO, "No FSUIPC");
68  m_connectionHostMessages =
69  connect(m_fs9Host.data(), &CFs9Host::customPacketReceived, this, &CSimulatorFs9::processFs9Message);
70 
71  m_fsuipc->open();
72 
73  this->initSimulatorInternals();
74  m_timerId = startTimer(50);
75  return true;
76  }
77 
79  {
80  if (!m_simConnected) { return true; }
81 
82  // Don't forward messages when disconnected
83  disconnect(m_connectionHostMessages);
84  safeKillTimer();
85  disconnectAllClients();
86 
87  if (m_fsuipc) { m_fsuipc->close(); }
88 
89  // emit status
90  CSimulatorFsCommon::disconnectFrom();
91  m_simConnected = false;
92  emitSimulatorCombinedStatus();
93  return true;
94  }
95 
97  {
98  const CCallsign callsign = newRemoteAircraft.getCallsign();
99  this->logAddingAircraftModel(newRemoteAircraft);
100 
101  if (m_hashFs9Clients.contains(callsign))
102  {
103  // already exists, remove first
104  this->physicallyRemoveRemoteAircraft(callsign);
105  }
106 
107  CFs9Client *client =
108  new CFs9Client(newRemoteAircraft, CTime(25, CTimeUnit::ms()), &m_interpolationLogger, this);
109  client->setHostAddress(m_fs9Host->getHostAddress());
110  client->setPlayerUserId(m_fs9Host->getPlayerUserId());
111  connect(client, &CFs9Client::statusChanged, this, &CSimulatorFs9::updateRenderStatus);
112  client->start();
113 
114  m_hashFs9Clients.insert(callsign, client);
115  return true;
116  }
117 
119  {
120  if (!m_hashFs9Clients.contains(callsign)) { return false; }
121 
122  auto fs9Client = m_hashFs9Clients.value(callsign);
123  delete fs9Client;
124  m_hashFs9Clients.remove(callsign);
125  updateAircraftRendered(callsign, false);
126  CLogMessage(this).info(u"FS9: Removed aircraft '%1'") << callsign.toQString();
127  return CSimulatorFsCommon::physicallyRemoveRemoteAircraft(callsign);
128  }
129 
131  {
132  if (m_hashFs9Clients.isEmpty()) { return 0; }
133  QList<CCallsign> callsigns(m_hashFs9Clients.keys());
134  int r = 0;
135  for (const CCallsign &cs : callsigns)
136  {
137  if (physicallyRemoveRemoteAircraft(cs)) { r++; }
138  }
139 
140  CSimulatorFsCommon::physicallyRemoveAllRemoteAircraft();
141  return r;
142  }
143 
145  {
146  return CCollection<CCallsign>(m_hashFs9Clients.keys());
147  }
148 
149  bool CSimulatorFs9::updateOwnSimulatorCockpit(const CSimulatedAircraft &ownAircraft, const CIdentifier &originator)
150  {
151  if (originator == this->identifier()) { return false; }
152  if (!this->isSimulating()) { return false; }
153 
154  // actually those data should be the same as ownAircraft
155  const CTransponder newTransponder = ownAircraft.getTransponder();
156 
157  bool changed = false;
158  if (newTransponder.getTransponderCode() != m_simTransponder.getTransponderCode()) { changed = true; }
159  if (newTransponder.getTransponderMode() != m_simTransponder.getTransponderMode()) { changed = true; }
160 
161  m_fsuipc->write(newTransponder);
162 
163  // avoid changes of cockpit back to old values due to an outdated read back value
164  if (changed) { m_skipCockpitUpdateCycles = SkipUpdateCyclesForCockpit; }
165 
166  // bye
167  return changed;
168  }
169 
170  bool CSimulatorFs9::updateOwnSimulatorSelcal(const CSelcal &selcal, const CIdentifier &originator)
171  {
172  if (originator == this->identifier()) { return false; }
173  if (!this->isSimulating()) { return false; }
174 
175  bool changed = false;
176  if (selcal != m_selcal)
177  {
181  m_selcal = selcal;
182  changed = true;
183  }
184 
185  return changed;
186  }
187 
189  {
190  if (!m_fs9Host.data()) { return; }
191 
192  // Avoid errors from CDirectPlayPeer as it may end in infinite loop
193  if (message.getSeverity() == CStatusMessage::SeverityError && message.isFromClass<CDirectPlayPeer>())
194  {
195  return;
196  }
197 
198  if (message.getSeverity() != CStatusMessage::SeverityDebug)
199  {
200  QMetaObject::invokeMethod(m_fs9Host.data(), "sendTextMessage", Q_ARG(QString, message.toQString()));
201  }
202  }
203 
205  {
206  if (!m_fs9Host.data()) { return; }
207  QMetaObject::invokeMethod(m_fs9Host.data(), "sendTextMessage", Q_ARG(QString, message.asString(true, true)));
208  }
209 
211  {
212  if (!m_hashFs9Clients.contains(callsign)) { return CStatusMessageList(); }
213  const CFs9Client *client = m_hashFs9Clients[callsign].data();
214  if (!client) { return CStatusMessageList(); }
216  this->getInterpolationSetupPerCallsignOrDefault(callsign);
217  return client->getInterpolationMessages(setup.getInterpolatorMode());
218  }
219 
221  const CAircraftParts &parts)
222  {
223  if (!m_hashFs9Clients.contains(callsign)) { return false; }
224  CFs9Client *client = m_hashFs9Clients[callsign].data();
225  if (!client) { return false; }
226 
227  Q_UNUSED(parts)
228  int u = 0;
229  if (!situation.isNull())
230  {
231  u++;
232  client->sendMultiplayerPosition(situation);
233  if (!parts.isNull()) { client->sendMultiplayerParts(parts); }
234  }
235  return u > 0;
236  }
237 
239  {
240  return m_hashFs9Clients.contains(callsign);
241  }
242 
243  void CSimulatorFs9::timerEvent(QTimerEvent *event)
244  {
245  Q_UNUSED(event)
246  dispatch();
247  }
248 
249  void CSimulatorFs9::dispatch()
250  {
251  if (m_fsuipc && m_fsuipc->isOpened())
252  {
253  CSimulatedAircraft fsuipcAircraft(getOwnAircraft());
254  const bool ok = m_fsuipc->read(fsuipcAircraft, true, true, true);
255  if (ok) { updateOwnAircraftFromSimulator(fsuipcAircraft); }
256  else
257  {
258  // FSUIPC read error means almost always that FS9 closed. Shutdown the driver.
259  CLogMessage(this).debug() << "Lost connection to FSUIPC. Shutting down.";
260  disconnectFrom();
261  }
262  synchronizeTime();
263  }
264  }
265 
266  QString getChangedParamsAsString(const MPParam &old, const MPParam &newParam)
267  {
268  // for debugging
269  QString str;
270  if (old.unknown8 != newParam.unknown8) str += "unknown8 " + QString::number(newParam.unknown8) + "\n";
271  if (old.unknown9 != newParam.unknown9) str += "unknown9 " + QString::number(newParam.unknown9) + "\n";
272  if (old.flaps_left != newParam.flaps_left) str += "flaps_left " + QString::number(newParam.flaps_left) + "\n";
273  if (old.flaps_right != newParam.flaps_right)
274  str += "flaps_right " + QString::number(newParam.flaps_right) + "\n";
275  if (old.unknown12 != newParam.unknown12) str += "unknown12 " + QString::number(newParam.unknown12) + "\n";
276  if (old.unknown13 != newParam.unknown13) str += "unknown13 " + QString::number(newParam.unknown13) + "\n";
277  if (old.unknown14 != newParam.unknown14) str += "unknown14 " + QString::number(newParam.unknown14) + "\n";
278  if (old.unknown15 != newParam.unknown15) str += "unknown15 " + QString::number(newParam.unknown15) + "\n";
279  if (old.unknown16 != newParam.unknown16) str += "unknown16 " + QString::number(newParam.unknown16) + "\n";
280  if (old.unknown17 != newParam.unknown17) str += "unknown17 " + QString::number(newParam.unknown17) + "\n";
281  if (old.unknown18 != newParam.unknown18) str += "unknown18 " + QString::number(newParam.unknown18) + "\n";
282  if (old.unknown19 != newParam.unknown19) str += "unknown19 " + QString::number(newParam.unknown19) + "\n";
283  if (old.gear_center != newParam.gear_center)
284  str += "gear_center " + QString::number(newParam.gear_center) + "\n";
285  if (old.gear_left != newParam.gear_left) str += "gear_left " + QString::number(newParam.gear_left) + "\n";
286  if (old.gear_right != newParam.gear_right) str += "gear_right " + QString::number(newParam.gear_right) + "\n";
287  if (old.engine_1 != newParam.engine_1) str += "engine_1 " + QString::number(newParam.engine_1) + "\n";
288  if (old.engine_2 != newParam.engine_2) str += "engine_2 " + QString::number(newParam.engine_2) + "\n";
289  if (old.unknown25 != newParam.unknown25) str += "unknown25 " + QString::number(newParam.unknown25) + "\n";
290  if (old.unknown26 != newParam.unknown26) str += "unknown26 " + QString::number(newParam.unknown26) + "\n";
291  if (old.unknown27 != newParam.unknown27) str += "unknown27 " + QString::number(newParam.unknown27) + "\n";
292  return str;
293  }
294 
295  void CSimulatorFs9::processFs9Message(const QByteArray &message)
296  {
297  if (!m_simConnected)
298  {
299  m_simConnected = true;
300  emitSimulatorCombinedStatus();
301  }
303  switch (messageType)
304  {
305  case CFs9Sdk::MULTIPLAYER_PACKET_ID_PARAMS:
306  {
307  MPParam mpParam;
308  MultiPlayerPacketParser::readMessage(message, mpParam);
309  // For debugging:
310  // QTextStream qtstdout(stdout);
311  // QString paramString = getChangedParamsAsString(m_lastParameters, mpParam);
312  // if (! paramString.isEmpty())
313  // {
314  // qtstdout << message.mid(4 * sizeof(qint32)).toHex() << Qt::endl;
315  // qtstdout << paramString << Qt::endl;
316  // }
317  // m_lastParameters = mpParam;
318  break;
319  }
320  case CFs9Sdk::MULTIPLAYER_PACKET_ID_CHANGE_PLAYER_PLANE:
321  {
322  MPChangePlayerPlane mpChangePlayerPlane;
323  MultiPlayerPacketParser::readMessage(message, mpChangePlayerPlane);
324  reverseLookupAndUpdateOwnAircraftModel(mpChangePlayerPlane.aircraft_name);
325  break;
326  }
327  case CFs9Sdk::MULTIPLAYER_PACKET_ID_POSITION_VELOCITY:
328  {
329  break;
330  }
331  case CFs9Sdk::MPCHAT_PACKET_ID_CHAT_TEXT_SEND:
332  {
333  MPChatText mpChatText;
334  MultiPlayerPacketParser::readMessage(message, mpChatText);
335  break;
336  }
337  default: break;
338  }
339  }
340 
341  void CSimulatorFs9::updateOwnAircraftFromSimulator(const CSimulatedAircraft &simDataOwnAircraft)
342  {
343  // When I change cockpit values in the sim (from GUI to simulator, not originating from simulator)
344  // it takes a little while before these values are set in the simulator.
345  // To avoid jitters, I wait some update cylces to stabilize the values
346  if (m_skipCockpitUpdateCycles < 1)
347  {
348  // we always use COM1 and COM2 from swift
349  const CComSystem oldCom1 = getOwnComSystem(CComSystem::Com1);
350  const CComSystem oldCom2 = getOwnComSystem(CComSystem::Com2);
351 
352  this->updateCockpit(oldCom1, oldCom2, simDataOwnAircraft.getTransponder(), this->identifier());
353  }
354  else { --m_skipCockpitUpdateCycles; }
355 
356  const CAircraftSituation aircraftSituation = simDataOwnAircraft.getSituation();
357  this->updateOwnSituationAndGroundElevation(aircraftSituation);
358 
359  this->updateOwnParts(simDataOwnAircraft.getParts());
360 
361  // slow updates
362  if (m_ownAircraftUpdateCycles % 25 == 0)
363  {
364  this->reverseLookupAndUpdateOwnAircraftModel(simDataOwnAircraft.getModelString());
365  const CLength cg = simDataOwnAircraft.getCG();
366  if (!cg.isNull()) { this->updateOwnCG(cg); }
367  } // slow updates
368 
369  m_ownAircraftUpdateCycles++;
370  }
371 
372  void CSimulatorFs9::updateRenderStatus(const CSimulatedAircraft &remoteAircraft, CFs9Client::ClientStatus)
373  {
374  const bool updated = updateAircraftRendered(remoteAircraft.getCallsign(), true);
375  CSimulatedAircraft remoteAircraftCopy(remoteAircraft);
376  remoteAircraftCopy.setRendered(true);
377  if (updated) { emit aircraftRenderingChanged(remoteAircraftCopy); }
378  CLogMessage(this).info(u"FS9: Added aircraft '%1'") << remoteAircraft.getCallsignAsString();
379  }
380 
381  void CSimulatorFs9::disconnectAllClients()
382  {
383  // Stop all FS9 client tasks
384  const QList<CCallsign> callsigns(m_hashFs9Clients.keys());
385  for (auto fs9Client : callsigns) { physicallyRemoveRemoteAircraft(fs9Client); }
386  }
387 
388  void CSimulatorFs9::synchronizeTime()
389  {
390  if (!m_simTimeSynced) { return; }
391  if (!this->isConnected()) { return; }
392  if (!m_fsuipc) { return; }
393  if (!m_fsuipc->isOpened()) { return; }
394 
395  QDateTime myDateTime = QDateTime::currentDateTimeUtc();
396  if (!m_syncTimeOffset.isZeroEpsilonConsidered())
397  {
398  int offsetSeconds = m_syncTimeOffset.valueInteger(CTimeUnit::s());
399  myDateTime = myDateTime.addSecs(offsetSeconds);
400  }
401 
402  const QTime myTime = myDateTime.time();
403  const int h = myTime.hour();
404  const int m = myTime.minute();
405  m_fsuipc->setSimulatorTime(h, m);
406  }
407 
409  const QSharedPointer<CFs9Host> &fs9Host,
410  const QSharedPointer<CLobbyClient> &lobbyClient)
411  : ISimulatorListener(info), m_timer(new QTimer(this)), m_fs9Host(fs9Host), m_lobbyClient(lobbyClient),
412  m_fsuipc(new CFsuipc(this))
413  {
414  const int QueryInterval = 5 * 1000; // 5 seconds
415  m_timer->setInterval(QueryInterval);
416  m_timer->setObjectName(this->objectName() + ":m_timer");
417 
418  // Test whether we can lobby connect at all.
419  const bool canLobbyConnect = m_lobbyClient->canLobbyConnect();
420 
421  // check connection
422  QPointer<CSimulatorFs9Listener> myself(this);
423  connect(m_timer, &QTimer::timeout, [=]() {
424  if (!myself) { return; }
425  this->checkConnection(canLobbyConnect);
426  });
427  }
428 
430  {
431  m_isStarted = false;
432  m_timer->start();
433  }
434 
435  void CSimulatorFs9Listener::stopImpl() { m_timer->stop(); }
436 
438  {
439  if (this->isShuttingDown()) { return; }
440  if (m_timer) { m_timer->start(); }
441 
442  QPointer<CSimulatorFs9Listener> myself(this);
443  QTimer::singleShot(10, this, [=] {
444  if (!myself) { return; }
445  const bool canLobbyConnect = m_lobbyClient->canLobbyConnect();
446  this->checkConnection(canLobbyConnect);
447  });
448  }
449 
450  bool CSimulatorFs9Listener::checkConnection(bool canLobbyConnect)
451  {
452  m_fsuipc->open();
453  if (!m_fsuipc->isOpen()) { return false; }
454  m_fsuipc->close();
455 
456  if (m_fs9Host->getHostAddress().isEmpty()) { return false; } // host not yet set up
457  if (canLobbyConnect)
458  {
459  if (m_isConnecting || isOk(m_lobbyClient->connectFs9ToHost(m_fs9Host->getHostAddress())))
460  {
461  m_isConnecting = true;
462  CLogMessage(this).info(u"swift is joining FS9 to the multiplayer session ...");
463  }
464  }
465 
466  if (!m_isStarted && m_fs9Host->isConnected())
467  {
468  m_isStarted = true;
469  m_isConnecting = false;
470  emit this->simulatorStarted(this->getPluginInfo());
471  }
472  return m_isConnecting;
473  }
474 
475  static void cleanupFs9Host(CFs9Host *host) { delete host; }
476 
477  static void cleanupLobbyClient(CLobbyClient *lobbyClient) { delete lobbyClient; }
478 
480  : QObject(parent), m_fs9Host(new CFs9Host, cleanupFs9Host), m_lobbyClient(new CLobbyClient, cleanupLobbyClient)
481  {
483 
484  /* After FS9 is disconnected, reset its data stored in the host */
485  connect(m_lobbyClient.data(), &CLobbyClient::disconnected, m_fs9Host.data(), &CFs9Host::reset);
486  }
487 
489 
491  IOwnAircraftProvider *ownAircraftProvider,
492  IRemoteAircraftProvider *remoteAircraftProvider,
493  IClientProvider *clientProvider)
494  {
495  return new CSimulatorFs9(info, m_fs9Host, m_lobbyClient, ownAircraftProvider, remoteAircraftProvider,
496  clientProvider, this);
497  }
498 
500  {
501  return new CSimulatorFs9Listener(info, m_fs9Host, m_lobbyClient);
502  }
503 } // namespace swift::simplugin::fs9
Interface to a simulator.
Definition: simulator.h:59
Interface to a simulator listener.
Definition: simulator.h:630
const swift::misc::simulation::CSimulatorPluginInfo & getPluginInfo() const
Corresponding info.
Definition: simulator.h:638
void simulatorStarted(const swift::misc::simulation::CSimulatorPluginInfo &info)
Emitted when the listener discovers the simulator running.
virtual bool isShuttingDown() const
Overall (swift) application shutting down.
Definition: simulator.cpp:1256
Value object encapsulating information identifying a component of a modular distributed swift process...
Definition: identifier.h:29
Class for emitting a log message.
Definition: logmessage.h:27
Derived & debug()
Set the severity to debug.
Derived & info(const char16_t(&format)[N])
Set the severity to info, providing a format string.
Streamable status message, e.g.
bool isFromClass(const T *pointer=nullptr) const
Returns true if this message was sent by an instance of class T.
StatusSeverity getSeverity() const
Message severity.
Status messages, e.g. from Core -> GUI.
Value object for ICAO classification.
Value object encapsulating information of aircraft's parts.
Definition: aircraftparts.h:26
bool isNull() const
NULL parts object?
Value object encapsulating information of an aircraft's situation.
virtual bool isNull() const
Null situation.
Value object encapsulating information of a callsign.
Definition: callsign.h:30
Value object for a set of callsigns.
Definition: callsignset.h:26
COM system (aka "radio")
Definition: comsystem.h:37
Value object for SELCAL.
Definition: selcal.h:31
int getTransponderCode() const
Transponder code.
Definition: transponder.h:107
TransponderMode getTransponderMode() const
Transponder mode.
Definition: transponder.h:95
QString toQString(bool i18n=false) const
Cast as QString.
Definition: mixinstring.h:76
Value object encapsulating information of a text message.
Definition: textmessage.h:31
QString asString(bool withSender, bool withRecipient, const QString &separator=", ") const
Whole message as formatted string. Used to display message in a console window.
Direct in memory access to client (network client) data.
Physical unit length (length)
Definition: length.h:18
Value object for interpolator and rendering per callsign.
Comprehensive information of an aircraft.
const aviation::CAircraftSituation & getSituation() const
Get situation.
const aviation::CTransponder & getTransponder() const
Get transponder.
const aviation::CCallsign & getCallsign() const
Get callsign.
QString getCallsignAsString() const
Get callsign.
const physical_quantities::CLength & getCG() const
Get CG from model.
const aviation::CAircraftParts & getParts() const
Get aircraft parts.
const QString & getModelString() const
Get model string.
Direct threadsafe in memory access to own aircraft.
Direct thread safe in memory access to remote aircraft.
DirectPlay peer implementation More information can be found in the DirectX9 SDK documentation http:/...
void customPacketReceived(const QByteArray &data)
Received custom FS9 packet.
void setPlayerUserId(DPNID id)
Sets users DirectPlay ID.
Class faking a FS9 multiplayer client connection.
Definition: fs9client.h:27
void setHostAddress(const QString &hostAddress)
Set DirectPlay host address.
Definition: fs9client.cpp:191
void sendMultiplayerParts(const swift::misc::aviation::CAircraftParts &parts)
Send parts (lights, gear ...)
Definition: fs9client.cpp:370
void sendMultiplayerPosition(const swift::misc::aviation::CAircraftSituation &situation)
Send a situation (position)
Definition: fs9client.cpp:356
void start()
Starts the FS9 client messaging.
Definition: fs9client.cpp:210
swift::misc::CStatusMessageList getInterpolationMessages(swift::misc::simulation::CInterpolationAndRenderingSetupBase::InterpolatorMode mode) const
Interpolation messages.
Definition: fs9client.cpp:218
void statusChanged(const swift::misc::simulation::CSimulatedAircraft &remoteAircraft, swift::simplugin::fs9::CFs9Client::ClientStatus)
Client status changed.
ClientStatus
Connection status.
Definition: fs9client.h:33
Class encapsulating a FS9 host.
Definition: fs9host.h:15
MULTIPLAYER_PACKET_ID
Multiplayer packet id.
Definition: fs9.h:37
Lobby client launching and connecting FS9.
Definition: lobbyclient.h:18
void disconnected()
Emitted when FS9 is closed.
virtual swift::core::ISimulatorListener * createListener(const swift::misc::simulation::CSimulatorPluginInfo &info)
Simulator listener instance.
virtual swift::core::ISimulator * create(const swift::misc::simulation::CSimulatorPluginInfo &info, swift::misc::simulation::IOwnAircraftProvider *ownAircraftProvider, swift::misc::simulation::IRemoteAircraftProvider *remoteAircraftProvider, swift::misc::network::IClientProvider *clientProvider)
Create a new instance of a driver.
CSimulatorFs9Factory(QObject *parent=nullptr)
Constructor.
FS9 Simulator Implementation.
Definition: simulatorfs9.h:32
virtual bool physicallyAddRemoteAircraft(const swift::misc::simulation::CSimulatedAircraft &newRemoteAircraft)
virtual void timerEvent(QTimerEvent *event)
Timer event dispatching.
virtual swift::misc::CStatusMessageList getInterpolationMessages(const swift::misc::aviation::CCallsign &callsign) const
virtual swift::misc::aviation::CCallsignSet physicallyRenderedAircraft() const
virtual bool isPhysicallyRenderedAircraft(const swift::misc::aviation::CCallsign &callsign) const
virtual bool isSimulating() const
Definition: simulatorfs9.h:73
virtual void displayTextMessage(const swift::misc::network::CTextMessage &message) const
virtual bool physicallyRemoveRemoteAircraft(const swift::misc::aviation::CCallsign &callsign)
virtual void displayStatusMessage(const swift::misc::CStatusMessage &message) const
virtual bool updateOwnSimulatorCockpit(const swift::misc::simulation::CSimulatedAircraft &ownAircraft, const swift::misc::CIdentifier &originator)
virtual bool testSendSituationAndParts(const swift::misc::aviation::CCallsign &callsign, const swift::misc::aviation::CAircraftSituation &situation, const swift::misc::aviation::CAircraftParts &parts)
virtual bool updateOwnSimulatorSelcal(const swift::misc::aviation::CSelcal &selcal, const swift::misc::CIdentifier &originator)
Listener for FS9 Listener starts the FS9 multiplayer host and tries to make the running instance of s...
Definition: simulatorfs9.h:120
virtual void stopImpl()
Plugin specific implementation to stop listener.
CSimulatorFs9Listener(const swift::misc::simulation::CSimulatorPluginInfo &info, const QSharedPointer< CFs9Host > &fs9Host, const QSharedPointer< CLobbyClient > &lobbyClient)
Constructor.
virtual void startImpl()
Plugin specific implementation to start listener.
virtual void checkImpl()
Plugin specific implementation to check.
static CFs9Sdk::MULTIPLAYER_PACKET_ID readType(const QByteArray &data)
Read the multiplayer packet type.
static QByteArray readMessage(const QByteArray &data, Message &message)
Read message from byte stream.
Class representing a FSUIPC "interface".
Definition: fsuipc.h:18
bool open(bool force=false)
Open connection with FSUIPC.
Definition: fsuipcdummy.cpp:19
bool isOpened() const
Is opened?
Definition: fsuipcdummy.cpp:27
bool write(const swift::misc::aviation::CTransponder &xpdr)
Write variables.
Definition: fsuipcdummy.cpp:31
bool read(swift::misc::simulation::CSimulatedAircraft &aircraft, bool cockpit, bool situation, bool aircraftParts)
Read data from FSUIPC.
Definition: fsuipcdummy.cpp:47
bool setSimulatorTime(int hour, int minute)
Set simulator time.
Definition: fsuipcdummy.cpp:37
Common base class for MS flight simulators.
Backend services of the swift project, like dealing with the network or the simulators.
Definition: actionbind.cpp:7
void registerMetadata()
Register all relevant metadata in swift::core.
Free functions in swift::misc.
auto singleShot(int msec, QObject *target, F &&task)
Starts a single-shot timer which will call a task in the thread of the given object when it times out...
Definition: threadutils.h:30