4 #define _CRT_SECURE_NO_WARNINGS
8 #include <QScopedArrayPointer>
10 #include "../fscommon/simulatorfscommonfunctions.h"
22 using namespace swift::misc::aviation;
23 using namespace swift::misc::simulation;
24 using namespace swift::misc::physical_quantities;
25 using namespace swift::misc::geo;
27 using namespace swift::simplugin::fscommon;
29 namespace swift::simplugin::fs9
33 :
CDirectPlayPeer(remoteAircraft.getCallsign(), simulator), m_remoteAircraft(remoteAircraft),
34 m_updateInterval(updateInterval), m_interpolator(remoteAircraft.getCallsign(), simulator, simulator,
35 simulator->getRemoteAircraftProvider(), logger),
36 m_modelName(remoteAircraft.getModelString())
39 Q_ASSERT_X(this->simulator(), Q_FUNC_INFO,
"Wrong owner, expect simulator object");
47 Q_UNUSED(oldSituation)
48 Q_UNUSED(updateInterval)
53 positionVelocity.
lat_i =
static_cast<qint32
>(latitude);
54 positionVelocity.
lat_f =
static_cast<quint16
>(qRound(qAbs((latitude - positionVelocity.
lat_i) * 65536)));
57 const double longitude =
59 positionVelocity.
lon_hi =
static_cast<qint32
>(longitude);
60 positionVelocity.
lon_lo =
static_cast<quint16
>(qRound(qAbs((longitude - positionVelocity.
lon_hi) * 65536)));
64 positionVelocity.
alt_i =
static_cast<qint32
>(altitude);
65 positionVelocity.
alt_f =
static_cast<quint16
>(qRound((altitude - positionVelocity.
alt_i) * 65536));
69 pbhstrct.
hdg =
static_cast<unsigned int>(
78 positionVelocity.
pbh = pbhstrct.
pbh;
92 const CLength distanceLatitudeObj = calculateGreatCircleDistance(oldPosition, helperPosition);
97 const CLength distanceLongitudeObj = calculateGreatCircleDistance(oldPosition, helperPosition);
100 positionVelocity.
lat_velocity = qRound(distanceLatitudeObj.
value(CLengthUnit::ft()) * 65536.0 / updateInterval);
103 qRound(distanceLongitudeObj.
value(CLengthUnit::ft()) * 65536.0 / updateInterval);
106 return positionVelocity;
111 MPPositionSlewMode positionSlewMode;
115 positionSlewMode.lat_i =
static_cast<qint32
>(latitude);
116 positionSlewMode.lat_f =
static_cast<quint16
>(qAbs((latitude - positionSlewMode.lat_i) * 65536));
119 const double longitude =
121 positionSlewMode.lon_hi =
static_cast<qint32
>(longitude);
122 positionSlewMode.lon_lo =
static_cast<quint16
>(qAbs((longitude - positionSlewMode.lon_hi) * 65536));
126 positionSlewMode.alt_i =
static_cast<qint32
>(altitude);
127 positionSlewMode.alt_f =
static_cast<quint16
>((altitude - positionSlewMode.alt_i) * 65536);
131 pbhstrct.
hdg =
static_cast<unsigned int>(
136 pbhstrct.pitch = ~pbhstrct.pitch;
137 pbhstrct.bank = ~pbhstrct.bank;
139 pbhstrct.onground = situation.
isOnGround() ? 1 : 0;
140 positionSlewMode.pbh = pbhstrct.pbh;
142 return positionSlewMode;
151 param.engine_2 = 140;
152 param.unknown14 = 60;
157 param.flaps_left = 228;
158 param.flaps_right = 228;
163 param.gear_center = 0xA1;
164 param.gear_left = 0xA1;
165 param.gear_right = 0xA1;
196 if (
isFailure(hr = CoCreateInstance(CLSID_DirectPlay8Address,
nullptr, CLSCTX_INPROC_SERVER,
197 IID_IDirectPlay8Address,
reinterpret_cast<void **
>(&m_hostAddress))))
199 logDirectPlayError(hr);
203 if (
isFailure(hr = m_hostAddress->BuildFromURLA(hostAddress.toLatin1().data())))
205 logDirectPlayError(hr);
227 sendMultiplayerPositionAndPartsFromInterpolation();
230 HRESULT CFs9Client::enumDirectPlayHosts()
240 DPN_APPLICATION_DESC dpAppDesc;
241 ZeroMemory(&dpAppDesc,
sizeof(DPN_APPLICATION_DESC));
242 dpAppDesc.dwSize =
sizeof(DPN_APPLICATION_DESC);
257 return logDirectPlayError(hr);
262 HRESULT CFs9Client::createHostAddress()
267 if (
isFailure(hr = CoCreateInstance(CLSID_DirectPlay8Address,
nullptr, CLSCTX_INPROC_SERVER,
268 IID_IDirectPlay8Address,
reinterpret_cast<void **
>(&m_hostAddress))))
270 return logDirectPlayError(hr);
274 if (
isFailure(hr = m_hostAddress->SetSP(&CLSID_DP8SP_TCPIP))) {
return logDirectPlayError(hr); }
277 const wchar_t hostname[] = L
"localhost";
281 m_hostAddress->AddComponent(DPNA_KEY_HOSTNAME, hostname, 2 * (wcslen(hostname) + 1),
282 DPNA_DATATYPE_STRING)))
284 return logDirectPlayError(hr);
290 HRESULT CFs9Client::connectToSession(
const CCallsign &callsign)
293 if (m_clientStatus == Connected) {
return hr; }
295 QScopedArrayPointer<wchar_t> wszPlayername(
new wchar_t[
static_cast<uint
>(callsign.
toQString().size() + 1)]);
296 callsign.
toQString().toWCharArray(wszPlayername.data());
297 wszPlayername[callsign.
toQString().size()] = 0;
299 Q_ASSERT(!m_modelName.isEmpty());
300 ZeroMemory(&m_playerInfo,
sizeof(PLAYER_INFO_STRUCT));
301 strcpy(m_playerInfo.
szAircraft, qPrintable(m_modelName));
305 ZeroMemory(&m_player,
sizeof(DPN_PLAYER_INFO));
306 m_player.dwSize =
sizeof(DPN_PLAYER_INFO);
307 m_player.pvData = &m_playerInfo;
308 m_player.dwDataSize =
sizeof(PLAYER_INFO_STRUCT);
309 m_player.dwInfoFlags = DPNINFO_NAME | DPNINFO_DATA;
310 m_player.pwszName = wszPlayername.data();
311 hr =
m_directPlayPeer->SetPeerInfo(&m_player,
nullptr,
nullptr, DPNSETPEERINFO_SYNC);
312 if (
isFailure(hr)) {
return logDirectPlayError(hr); }
315 DPN_APPLICATION_DESC dpAppDesc;
316 ZeroMemory(&dpAppDesc,
sizeof(DPN_APPLICATION_DESC));
317 dpAppDesc.dwSize =
sizeof(DPN_APPLICATION_DESC);
320 DPNHANDLE asyncOpHandle;
322 nullptr,
nullptr, &asyncOpHandle, 0);
323 if (!isPending(hr) &&
isFailure(hr)) {
return logDirectPlayError(hr); }
327 HRESULT CFs9Client::closeConnection()
331 if (m_clientStatus == Disconnected) {
return hr; }
335 m_clientStatus = Disconnected;
340 void CFs9Client::sendMultiplayerPositionAndPartsFromInterpolation()
343 if (m_clientStatus == Disconnected) {
return; }
344 const bool forceFullUpdate =
false;
346 this->simulator()->getInterpolationSetupConsolidated(
m_callsign, forceFullUpdate);
348 m_interpolator.
getInterpolation(QDateTime::currentMSecsSinceEpoch(), setup, 0);
360 QByteArray positionMessage;
373 QByteArray paramMessage;
374 MPParam param = aircraftPartsToFS9(parts);
389 if (type ==
'H')
return CFs9Sdk::ENGINE_TYPE_HELO_TURBINE;
390 if (engine ==
'J')
return CFs9Sdk::ENGINE_TYPE_JET;
391 if (engine ==
'P')
return CFs9Sdk::ENGINE_TYPE_PISTON;
392 if (engine ==
'T')
return CFs9Sdk::ENGINE_TYPE_TURBOPROP;
394 return CFs9Sdk::ENGINE_TYPE_JET;
397 void CFs9Client::sendMultiplayerChangePlayerPlane()
399 MPChangePlayerPlane mpChangePlayerPlane;
400 mpChangePlayerPlane.engine = aircraftToFS9EngineType(m_remoteAircraft);
401 mpChangePlayerPlane.aircraft_name = m_modelName;
409 void CFs9Client::handleConnectionCompleted()
413 m_clientStatus = Connected;
414 sendMultiplayerChangePlayerPlane();
415 sendMultiplayerPositionAndPartsFromInterpolation();
416 startTimer(m_updateInterval.
valueInteger(CTimeUnit::ms()));
421 const ISimulator *CFs9Client::simulator()
const {
return qobject_cast<const ISimulator *>(this->parent()); }
Interface to a simulator.
Class for emitting a log message.
Derived & warning(const char16_t(&format)[N])
Set the severity to warning, providing a format string.
Derived & info(const char16_t(&format)[N])
Set the severity to info, providing a format string.
Status messages, e.g. from Core -> GUI.
QChar getEngineTypeChar() const
Get engine type, e.g. "J".
QChar getAircraftTypeChar() const
Aircraft type, such a L(andplane), S(eaplane), H(elicopter)
Value object encapsulating information of aircraft's parts.
bool isFixedGearDown() const
Is fixed gear down?
bool isAnyEngineOn() const
Any engine on?
int getFlapsPercent() const
Get flaps position in percent.
Value object encapsulating information of an aircraft's situation.
const CHeading & getHeading() const
Get heading.
bool isOnGround() const
Is on ground?
virtual geo::CLatitude latitude() const
Latitude.
const physical_quantities::CSpeed & getGroundSpeed() const
Get ground speed.
const CAltitude & getAltitude() const
Get altitude.
const physical_quantities::CAngle & getBank() const
Get bank (angle)
const physical_quantities::CAngle & getPitch() const
Get pitch.
const geo::CCoordinateGeodetic & getPosition() const
Get position.
virtual geo::CLongitude longitude() const
Longitude.
Value object encapsulating information of a callsign.
void setLatitude(const CLatitude &latitude)
Set latitude.
virtual CLatitude latitude() const
Latitude.
virtual CLongitude longitude() const
Longitude.
void setLongitude(const CLongitude &longitude)
Set longitude.
QString toQString(bool i18n=false) const
Cast as QString.
Physical unit length (length)
int valueInteger(MU unit) const
As integer value.
double value(MU unit) const
Value in given unit.
InterpolatorMode
Interpolator type.
Value object for interpolator and rendering per callsign.
Record internal state of interpolator for debugging.
const CInterpolationStatus & getInterpolationStatus() const
Get status.
const aviation::CAircraftSituation & getInterpolatedSituation() const
Get situation.
const aviation::CAircraftParts & getInterpolatedParts() const
Get parts (interpolated or guessed)
bool hasValidSituation() const
Is the corresponding position valid?
CInterpolationResult getInterpolation(qint64 currentTimeSinceEpoch, const CInterpolationAndRenderingSetupPerCallsign &setup, uint32_t aircraftNumber)
Get interpolated situation.
const CStatusMessageList & getInterpolationMessages(CInterpolationAndRenderingSetupBase::InterpolatorMode mode) const
Interpolation messages.
void attachLogger(CInterpolationLogger *logger)
Attach an observer to read the interpolator's state for debugging.
Comprehensive information of an aircraft.
const aviation::CAircraftIcaoCode & getAircraftIcaoCode() const
Get aircraft ICAO info.
DirectPlay peer implementation More information can be found in the DirectX9 SDK documentation http:/...
IDirectPlay8Peer * m_directPlayPeer
DirectPlay peer address.
HRESULT initDirectPlay()
Initialize DirectPlay.
IDirectPlay8Address * m_deviceAddress
DirectPlay device address.
void connectionComplete()
Async operatione complete.
HRESULT sendMessage(const QByteArray &data)
Send a custom DirectPlay message.
quint32 m_packetIndex
Multiplayer packet index.
const swift::misc::aviation::CCallsign m_callsign
Peer callsign.
HRESULT createDeviceAddress()
Creates a new DirectPlay device address.
void setHostAddress(const QString &hostAddress)
Set DirectPlay host address.
virtual ~CFs9Client()
Destructor.
void sendMultiplayerParts(const swift::misc::aviation::CAircraftParts &parts)
Send parts (lights, gear ...)
swift::misc::simulation::CInterpolatorMulti * getInterpolator()
Get interpolator.
void sendMultiplayerPosition(const swift::misc::aviation::CAircraftSituation &situation)
Send a situation (position)
void sendTextMessage(const QString &textMessage)
Send new text message.
void start()
Starts the FS9 client messaging.
swift::misc::CStatusMessageList getInterpolationMessages(swift::misc::simulation::CInterpolationAndRenderingSetupBase::InterpolatorMode mode) const
Interpolation messages.
void statusChanged(const swift::misc::simulation::CSimulatedAircraft &remoteAircraft, swift::simplugin::fs9::CFs9Client::ClientStatus)
Client status changed.
virtual void timerEvent(QTimerEvent *event)
static double bankMultiplier()
Return the FS9 bank multiplier.
static GUID guid()
Get FS9 application GUID.
static double headingMultiplier()
Returns the FS9 heading multiplier.
static double pitchMultiplier()
Returns the FS9 pitch multiplier.
static void writeSize(QByteArray &data, qint32 size)
Write the multiplayer packet size.
static QByteArray writeMessage(QByteArray &data, const Message &message)
Write message to byte stream.
static void writeType(QByteArray &data, CFs9Sdk::MULTIPLAYER_PACKET_ID type)
Write the multiplayer packet type.
void SafeRelease(T *&pT)
Safely release a COM allocated object.
Backend services of the swift project, like dealing with the network or the simulators.
Free functions in swift::misc.
HRESULT s_ok()
Correctly casted values/checks.
bool isFailure(HRESULT result)
Correctly casted values/checks.
Multiplayer packet - chat text.
qint32 size() const
Struct size.
Multiplayer param packet - aircraft configuration.
qint32 size() const
Struct size.
Multiplayer packet in slew mode.
qint32 size() const
Struct size.
Multiplayer packet - position and velocity.
QString chat_data
Chat message.
quint8 engine_1
Engine 1 N1 in %.
quint32 packet_index
Packet index.
quint32 packet_index
Packet index.
qint32 lat_velocity
Latitude velocity.
qint32 lon_hi
Longitude - integer.
quint16 lat_f
Latitude - fraction.
quint32 ground_velocity
Ground velocity.
quint16 alt_f
Altitude - fraction.
quint32 pbh
Pitch/Bank/Heading.
quint16 lon_lo
Longitude - fraction.
qint32 lon_velocity
Longitude velocity.
qint32 lat_i
Latitude - integer.
qint32 alt_i
Altitude - integer.
quint32 dwFlags
Player flags.
char szAircraft[MAX_PATH+1]
Aircraft model type.
unsigned int pbh
Pitch/Bank/Heading as integer value.
unsigned int onground
Onground flag.