Files

116 lines
3.0 KiB
ObjectPascal
Raw Permalink Normal View History

2026-09-15 10:16:31 +05:00
unit GameDiagnosticsExport;
{$mode objfpc}{$H+}
interface
type
TDiagnosticExportOutcomeKind = (deokSuccess, deokCancel, deokError);
TDiagnosticExportOutcome = record
Kind: TDiagnosticExportOutcomeKind;
ErrorMessage: string;
end;
TDiagnosticExportCallback = procedure(const AOutcome: TDiagnosticExportOutcome) of object;
procedure ExportDiagnosticReport(
const AJsonSnapshot: string;
const ACallback: TDiagnosticExportCallback
);
implementation
uses
Classes, CastleMessaging, CastleStringUtils, SysUtils;
const
ExportResultToken = 'diagnostic-report-export-result';
type
TDiagnosticExportListener = class
private
FPending: Boolean;
FCallback: TDiagnosticExportCallback;
procedure Complete(const AKind: TDiagnosticExportOutcomeKind;
const AErrorMessage: string);
function MessageReceived(const Received: TCastleStringList;
const ReceivedStream: TMemoryStream): Boolean;
public
constructor Create;
destructor Destroy; override;
procedure Export(const AJsonSnapshot: string;
const ACallback: TDiagnosticExportCallback);
end;
constructor TDiagnosticExportListener.Create;
begin
inherited;
Messaging.OnReceive.Add(@MessageReceived);
end;
destructor TDiagnosticExportListener.Destroy;
begin
Messaging.OnReceive.Remove(@MessageReceived);
inherited;
end;
procedure TDiagnosticExportListener.Complete(const AKind: TDiagnosticExportOutcomeKind;
const AErrorMessage: string);
var
Outcome: TDiagnosticExportOutcome;
Callback: TDiagnosticExportCallback;
begin
Callback := FCallback;
FCallback := nil;
FPending := False;
Outcome.Kind := AKind;
Outcome.ErrorMessage := AErrorMessage;
if Assigned(Callback) then
Callback(Outcome);
end;
function TDiagnosticExportListener.MessageReceived(
const Received: TCastleStringList;
const ReceivedStream: TMemoryStream): Boolean;
begin
Result := (Received.Count > 0) and (Received[0] = ExportResultToken);
if not Result or not FPending then
Exit;
if (Received.Count = 2) and (Received[1] = 'success') then
Complete(deokSuccess, '')
else
if (Received.Count = 2) and (Received[1] = 'cancel') then
Complete(deokCancel, '')
else
if (Received.Count = 3) and (Received[1] = 'error') then
Complete(deokError, Received[2])
else
Complete(deokError, 'Malformed export-service response');
end;
procedure TDiagnosticExportListener.Export(const AJsonSnapshot: string;
const ACallback: TDiagnosticExportCallback);
begin
if FPending then
raise Exception.Create('Diagnostic report export is already pending');
FPending := True;
FCallback := ACallback;
Messaging.Send(['diagnostic-report-export', AJsonSnapshot]);
end;
var
ExportListener: TDiagnosticExportListener;
procedure ExportDiagnosticReport(const AJsonSnapshot: string;
const ACallback: TDiagnosticExportCallback);
begin
ExportListener.Export(AJsonSnapshot, ACallback);
end;
initialization
ExportListener := TDiagnosticExportListener.Create;
finalization
FreeAndNil(ExportListener);
end.