Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: stop sending terrain on nd data if the sim stopped or is paused #87

Merged
merged 5 commits into from
Jul 9, 2023
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 75 additions & 6 deletions apps/server/src/terrain/communication/simconnect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,21 @@ import {
ClientDataRequestMessage,
ClientDataPeriod,
ClientDataRequest,
SystemEvent,
SystemEventType,
SystemEventMessage,
SystemEventSim,
SystemEventPause,
SystemEventPauseType,
} from '@flybywiresim/msfs-nodejs';
import { Logger } from '../processing/logging/logger';
import { NavigationDisplayData } from '../processing/navigationdisplaydata';
import { AircraftStatus, PositionData, TerrainRenderingMode } from './types';

export type UpdateCallbacks = {
connectionLost: () => void;
reset: () => void;
paused: () => void;
unpaused: () => void;
positionUpdate: (data: PositionData) => void;
aircraftStatusUpdate: (data: AircraftStatus) => void;
}
Expand All @@ -39,18 +47,27 @@ const enum DataDefinitionId {
NavigationDisplayFrameAreaRight = 4,
}

const enum SystemEventId {
SimulatorState = 0,
PauseState = 1,
}

const EnhancedGpwcAircraftStatusByteCount = 46;
const NavigationDisplayThresholdByteCount = 14;

export class SimConnect {
private callbacks: UpdateCallbacks = {
connectionLost: null,
reset: null,
paused: null,
unpaused: null,
positionUpdate: null,
aircraftStatusUpdate: null,
};

private shutdown: boolean = false;

private simulatorPaused: boolean = false;

private connection: Connection = null;

private receiver: Receiver = null;
Expand All @@ -65,6 +82,16 @@ export class SimConnect {

private frameDataRight: ClientDataArea = null;

private simulatorStateEvent: SystemEvent = null;

private pauseStateEvent: SystemEvent = null;

private registerSystemEvents(): boolean {
this.simulatorStateEvent = new SystemEvent(this.connection, SystemEventId.SimulatorState, SystemEventType.Sim);
this.pauseStateEvent = new SystemEvent(this.connection, SystemEventId.PauseState, SystemEventType.PauseEX1);
return true;
}

private registerEgpwcAircraftStatus(): boolean {
this.egpwcAircraftStatus = new ClientDataArea(this.connection, ClientDataId.EnhancedGpwcAircraftStatus);
if (!this.egpwcAircraftStatus.mapNameToId('FBW_SIMBRIDGE_EGPWC_AIRCRAFT_STATUS')) {
Expand Down Expand Up @@ -167,6 +194,12 @@ export class SimConnect {
if (!this.receiver.requestClientData(this.egpwcAircraftStatus, ClientDataPeriod.OnSet, ClientDataRequest.Default)) {
this.logging.error('Unable to request aircraft status data');
}
if (!this.receiver.subscribeSystemEvent(this.simulatorStateEvent)) {
this.logging.error('Unable to subscribe to the simulator states');
}
if (!this.receiver.subscribeSystemEvent(this.pauseStateEvent)) {
this.logging.error('Unable to subscribe to the pause states');
}
}
}

Expand All @@ -177,12 +210,14 @@ export class SimConnect {
this.frameMetadataRight = null;
this.frameDataLeft = null;
this.frameDataRight = null;
this.simulatorStateEvent = null;
this.pauseStateEvent = null;
this.connection.close();
}

private simConnectQuit(): void {
if (this.callbacks.connectionLost !== null) {
this.callbacks.connectionLost();
if (this.callbacks.reset !== null) {
this.callbacks.reset();
}

this.resetConnection();
Expand Down Expand Up @@ -251,12 +286,28 @@ export class SimConnect {
}
}

private simConnectSystemEvent(message: SystemEventMessage): void {
if (message.eventId === SystemEventId.SimulatorState) {
const sim = message.content as SystemEventSim;
if (sim.running === false && this.callbacks.reset !== null) {
this.callbacks.reset();
}
} else if (message.eventId === SystemEventId.PauseState) {
const pause = message.content as SystemEventPause;
if (pause.type !== SystemEventPauseType.Unpaused) {
if (this.callbacks.paused !== null) this.callbacks.paused();
} else if (this.callbacks.unpaused !== null) this.callbacks.unpaused();
} else {
this.logging.error(`Unknown system event ID: ${message.eventId}`);
}
}

private connectToSim() {
if (this.shutdown) return;

this.connection = new Connection();
if (this.connection.open(SimConnectClientName) === false) {
this.logging.error(`Connection failed: ${this.connection.lastError()} - Retry in 10 seconds`);
this.logging.error(`Connection to MSFS failed: ${this.connection.lastError()} - Retry in 10 seconds`);
svengcz marked this conversation as resolved.
Show resolved Hide resolved
setTimeout(() => this.connectToSim(), 10000);
return;
}
Expand All @@ -266,6 +317,7 @@ export class SimConnect {
this.receiver.addCallback('open', (message: OpenMessage) => this.simConnectOpen(message));
this.receiver.addCallback('quit', () => this.simConnectQuit());
this.receiver.addCallback('clientData', (message: ClientDataRequestMessage) => this.simConnectReceivedClientData(message));
this.receiver.addCallback('systemEvent', (message: SystemEventMessage) => this.simConnectSystemEvent(message));
this.receiver.addCallback('exception', (message: ExceptionMessage) => this.simConnectException(message));
this.receiver.addCallback('error', (message: ErrorMessage) => this.simConnectError(message));
this.receiver.start();
Expand Down Expand Up @@ -295,7 +347,7 @@ export class SimConnect {
return;
}

if (!this.registerNavigationDisplayData()) {
if (!this.registerNavigationDisplayData() || !this.registerSystemEvents()) {
this.receiver.stop();
this.connection.close();
setTimeout(() => this.connectToSim(), 10000);
Expand Down Expand Up @@ -324,12 +376,20 @@ export class SimConnect {
packed.writeUInt8(metadata.DisplayMode, 9);
packed.writeUInt32LE(metadata.FrameByteCount, 10);

let resetConnection = false;
if (side === 'L') {
if (this.frameMetadataLeft.setData({ ThresholdData: packed.buffer }) === false) {
this.logging.error(`Could not send metadata: ${this.frameMetadataLeft.lastError()}`);
resetConnection = true;
}
} else if (this.frameMetadataRight.setData({ ThresholdData: packed.buffer }) === false) {
this.logging.error(`Could not send metadata: ${this.frameMetadataRight.lastError()}`);
resetConnection = true;
}

if (resetConnection === true) {
this.logging.error('Resetting connection to MSFS due to transmission error');
this.simConnectQuit();
}
}

Expand All @@ -347,12 +407,21 @@ export class SimConnect {
frame.copy(stream, 0, i * ClientDataMaxSize, i * ClientDataMaxSize + byteCount);

// send the data
let resetConnection = false;
if (side === 'L') {
if (this.frameDataLeft.setData({ FrameData: stream.buffer }) === false) {
this.logging.error(`Could not send frame data: ${this.frameDataLeft.lastError()}`);
resetConnection = true;
}
} else if (this.frameDataRight.setData({ FrameData: stream.buffer }) === false) {
this.logging.error(`Could not send frame data: ${this.frameDataRight.lastError()}`);
resetConnection = true;
}

if (resetConnection === true) {
this.logging.error('Resetting connection to MSFS due to transmission error');
this.simConnectQuit();
break;
}
}
}
Expand Down
21 changes: 18 additions & 3 deletions apps/server/src/terrain/processing/maphandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,10 @@ const RenderingMapTransitionAngularStep = Math.round((90 / RenderingMapTransitio
class MapHandler {
private simconnect: SimConnect = null;

private simulatorStatus: {
paused: boolean,
} = { paused: false }

private worldmap: Worldmap = null;

private gpu: GPU = null;
Expand Down Expand Up @@ -171,8 +175,17 @@ class MapHandler {
this.resetFrameData('R');
}

private onConnectionLost(): void {
private onReset(): void {
this.cleanupMemory();
this.simulatorStatus.paused = false;
}

private onPaused(): void {
this.simulatorStatus.paused = true;
}

private onUnpaused(): void {
this.simulatorStatus.paused = false;
}

private onPositionUpdate(data: PositionData): void {
Expand Down Expand Up @@ -358,7 +371,9 @@ class MapHandler {
constructor(private logging: Logger) {
this.readTerrainMap().then((terrainmap) => {
this.simconnect = new SimConnect(logging);
this.simconnect.addUpdateCallback('connectionLost', () => this.onConnectionLost());
this.simconnect.addUpdateCallback('reset', () => this.onReset());
this.simconnect.addUpdateCallback('paused', () => this.onPaused());
this.simconnect.addUpdateCallback('unpaused', () => this.onUnpaused());
this.simconnect.addUpdateCallback('positionUpdate', (data: PositionData) => this.onPositionUpdate(data));
this.simconnect.addUpdateCallback('aircraftStatusUpdate', (data: AircraftStatus) => this.onAircraftStatusUpdate(data));

Expand Down Expand Up @@ -915,7 +930,7 @@ class MapHandler {
}

// transfer the transition frame
if (frame !== null) {
if (frame !== null && this.simulatorStatus.paused === false) {
sharp(frame, { raw: { width: RenderingMaxPixelWidth, height: RenderingScreenPixelHeight, channels: RenderingColorChannelCount } })
.png()
.toBuffer()
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
"react-dom": "^17.0.0"
},
"dependencies": {
"@flybywiresim/msfs-nodejs": "^0.2.0",
"@flybywiresim/msfs-nodejs": "^0.3.0",
"@nestjs/axios": "^0.0.6",
"@nestjs/common": "^8.0.0",
"@nestjs/config": "^1.2.0",
Expand Down