Added ability for users to edit configuration during installation

This commit is contained in:
Pax1601 2023-11-20 18:19:41 +01:00
parent 31af3a53ce
commit 806d0cc52f
5 changed files with 529 additions and 15 deletions

4
.gitignore vendored
View File

@ -1,5 +1,8 @@
bin
/scripts/old
/scripts/python/dist
/scripts/python/build
/scripts/python/venv
.vs
x64
core.user
@ -15,3 +18,4 @@ node_modules
hgt
/client/public/databases/units/old
/client/plugins/databasemanager/index.js

View File

@ -11,6 +11,7 @@ UninstallFilesDir={app}\Mods\Services\Olympus
SetupIconFile="..\img\olympus.ico"
DirExistsWarning=no
AppendDefaultDirName=no
LicenseFile="..\LEGAL"
[Messages]
WizardSelectDir=Select the location of DCS's Saved Games folder
@ -24,22 +25,26 @@ Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{
[Files]
; NOTE: Don't use "Flags: ignoreversion" on any shared system files
Source: "..\scripts\OlympusHook.lua"; DestDir: "{app}\Scripts\Hooks"; Flags: ignoreversion
; Source: "..\scripts\OlympusHook.lua"; DestDir: "{app}\Scripts\Hooks"; Flags: ignoreversion
Source: "..\olympus.json"; DestDir: "{app}\Mods\Services\Olympus"; Flags: onlyifdoesntexist
Source: "..\scripts\OlympusCommand.lua"; DestDir: "{app}\Mods\Services\Olympus\Scripts"; Flags: ignoreversion
Source: "..\scripts\unitPayloads.lua"; DestDir: "{app}\Mods\Services\Olympus\Scripts"; Flags: ignoreversion
Source: "..\scripts\templates.lua"; DestDir: "{app}\Mods\Services\Olympus\Scripts"; Flags: ignoreversion
Source: "..\scripts\mist.lua"; DestDir: "{app}\Mods\Services\Olympus\Scripts"; Flags: ignoreversion
Source: "..\mod\*"; DestDir: "{app}\Mods\Services\Olympus"; Flags: ignoreversion recursesubdirs;
Source: "..\bin\*.dll"; DestDir: "{app}\Mods\Services\Olympus\bin"; Flags: ignoreversion;
Source: "..\client\bin\*"; DestDir: "{app}\Mods\Services\Olympus\client\bin"; Flags: ignoreversion;
Source: "..\client\node_modules\*"; DestDir: "{app}\Mods\Services\Olympus\client\node_modules"; Flags: ignoreversion recursesubdirs;
Source: "..\client\public\*"; DestDir: "{app}\Mods\Services\Olympus\client\public"; Flags: ignoreversion recursesubdirs;
Source: "..\client\routes\*"; DestDir: "{app}\Mods\Services\Olympus\client\routes"; Flags: ignoreversion recursesubdirs;
Source: "..\client\views\*"; DestDir: "{app}\Mods\Services\Olympus\client\views"; Flags: ignoreversion recursesubdirs;
Source: "..\client\*.*"; DestDir: "{app}\Mods\Services\Olympus\client"; Flags: ignoreversion;
Source: "..\img\olympus.ico"; DestDir: "{app}\Mods\Services\Olympus\img"; Flags: ignoreversion;
Source: "{#nwjsFolder}\*.*"; DestDir: "{app}\Mods\Services\Olympus\client"; Flags: ignoreversion recursesubdirs;
; Source: "..\scripts\OlympusCommand.lua"; DestDir: "{app}\Mods\Services\Olympus\Scripts"; Flags: ignoreversion
; Source: "..\scripts\unitPayloads.lua"; DestDir: "{app}\Mods\Services\Olympus\Scripts"; Flags: ignoreversion
; Source: "..\scripts\templates.lua"; DestDir: "{app}\Mods\Services\Olympus\Scripts"; Flags: ignoreversion
; Source: "..\scripts\mist.lua"; DestDir: "{app}\Mods\Services\Olympus\Scripts"; Flags: ignoreversion
; Source: "..\mod\*"; DestDir: "{app}\Mods\Services\Olympus"; Flags: ignoreversion recursesubdirs;
; Source: "..\bin\*.dll"; DestDir: "{app}\Mods\Services\Olympus\bin"; Flags: ignoreversion;
; Source: "..\client\bin\*"; DestDir: "{app}\Mods\Services\Olympus\client\bin"; Flags: ignoreversion;
; Source: "..\client\node_modules\*"; DestDir: "{app}\Mods\Services\Olympus\client\node_modules"; Flags: ignoreversion recursesubdirs;
; Source: "..\client\public\*"; DestDir: "{app}\Mods\Services\Olympus\client\public"; Flags: ignoreversion recursesubdirs;
; Source: "..\client\routes\*"; DestDir: "{app}\Mods\Services\Olympus\client\routes"; Flags: ignoreversion recursesubdirs;
; Source: "..\client\views\*"; DestDir: "{app}\Mods\Services\Olympus\client\views"; Flags: ignoreversion recursesubdirs;
; Source: "..\client\*.*"; DestDir: "{app}\Mods\Services\Olympus\client"; Flags: ignoreversion;
; Source: "..\img\olympus.ico"; DestDir: "{app}\Mods\Services\Olympus\img"; Flags: ignoreversion;
; Source: "{#nwjsFolder}\*.*"; DestDir: "{app}\Mods\Services\Olympus\client"; Flags: ignoreversion recursesubdirs;
Source: "..\scripts\python\dist\configurator.exe"; DestDir: "{app}\Mods\Services\Olympus"; Flags: ignoreversion
[Run]
Filename: "{app}\Mods\Services\Olympus\configurator.exe"; Parameters: -a {code:GetAddress} -c {code:GetClientPort} -b {code:GetBackendPort} -p {code:GetPassword} -bp {code:GetBluePassword} -rp {code:GetRedPassword}
[Code]
function NeedsAddPath(Param: string): boolean;
@ -68,3 +73,393 @@ ChangesEnvironment=yes
[Icons]
Name: "{userdesktop}\DCS Olympus Client"; Filename: "{app}\Mods\Services\Olympus\client\nw.exe"; Tasks: desktopicon; IconFilename: "{app}\Mods\Services\Olympus\img\olympus.ico"
[Code]
var
lblLocalInstall: TLabel;
lblLocalInstallInstructions: TNewStaticText;
lblServerInstall: TLabel;
lblServerInstallInstructions: TNewStaticText;
lblClientPort: TLabel;
lblBackendPort: TLabel;
lblPassword: TLabel;
lblBluePassword: TLabel;
lblRedPassword: TLabel;
txtLocalInstall: TNewRadioButton;
txtServerInstall: TNewRadioButton;
txtClientPort: TEdit;
txtBackendPort: TEdit;
txtPassword: TPasswordEdit;
txtBluePassword: TPasswordEdit;
txtRedPassword: TPasswordEdit;
AddressPage: Integer;
PasswordPage: Integer;
lblPasswordInstructions: TNewStaticText;
procedure AcceptNumbersOnlyKeyPress(Sender: TObject; var Key: Char);
var
KeyCode: Integer;
begin
// allow only numbers
KeyCode := Ord(Key);
if not ((KeyCode = 8) or ((KeyCode >= 48) and (KeyCode <= 57))) then
Key := #0;
end;
procedure frmAddress_Activate(Page: TWizardPage);
begin
end;
function frmAddress_ShouldSkipPage(Page: TWizardPage): Boolean;
begin
Result := False;
end;
function frmAddress_BackButtonClick(Page: TWizardPage): Boolean;
begin
Result := True;
end;
function frmAddress_NextButtonClick(Page: TWizardPage): Boolean;
begin
Result := True;
end;
procedure frmAddress_CancelButtonClick(Page: TWizardPage; var Cancel, Confirm: Boolean);
begin
end;
function frmAddress_CreatePage(PreviousPageId: Integer): Integer;
var
Page: TWizardPage;
begin
Page := CreateCustomPage(
PreviousPageId,
'DCS Olympus configuration',
'Setup DCS Olympus connectivity'
);
{ lblLocalInstall }
lblLocalInstall := TLabel.Create(Page);
with lblLocalInstall do
begin
Parent := Page.Surface;
Left := ScaleX(30);
Top := ScaleY(14);
Width := ScaleX(35);
Height := ScaleY(10);
Font.Style := [fsBold];
Caption := 'Local installation';
end;
{ lblLocalInstallInstructions }
lblLocalInstallInstructions := TNewStaticText.Create(Page);
with lblLocalInstallInstructions do
begin
Parent := Page.Surface;
Left := ScaleX(30);
Top := ScaleY(31);
Width := ScaleX(340);
Height := ScaleY(23);
WordWrap := True;
Caption := 'Select this to install DCS Olympus locally. DCS Olympus will not be reachable by external clients (i.e. browsers running on different PCs)';
end;
{ txtLocalInstall }
txtLocalInstall := TNewRadioButton.Create(Page);
with txtLocalInstall do
begin
Parent := Page.Surface;
Left := ScaleX(10);
Top := ScaleY(12);
Width := ScaleX(185);
Height := ScaleY(21);
TabOrder := 0;
Checked := True
end;
{ lblServerInstall }
lblServerInstall := TLabel.Create(Page);
with lblServerInstall do
begin
Parent := Page.Surface;
Left := ScaleX(30);
Top := ScaleY(76);
Width := ScaleX(52);
Height := ScaleY(13);
Font.Style := [fsBold];
Caption := 'Dedicated server installation';
end;
{ lblServerInstallInstructions }
lblServerInstallInstructions := TNewStaticText.Create(Page);
with lblServerInstallInstructions do
begin
Parent := Page.Surface;
Left := ScaleX(30);
Top := ScaleY(93);
Width := ScaleX(340);
Height := ScaleY(13);
WordWrap := True;
Caption := 'Select this to install DCS Olympus on a dedicated server. DCS Olympus will be reachable by external clients. NOTE: to enable external connections, port forwarding must be enabled. By default, ports 3000 and 30000 must be forwarded on TCP and UDP.';
end;
{ txtServerInstall }
txtServerInstall := TNewRadioButton.Create(Page);
with txtServerInstall do
begin
Parent := Page.Surface;
Left := ScaleX(10);
Top := ScaleY(72);
Width := ScaleX(185);
Height := ScaleY(21);
TabOrder := 1;
end;
{ lblClientPort }
lblClientPort := TLabel.Create(Page);
with lblClientPort do
begin
Parent := Page.Surface;
Left := ScaleX(24);
Top := ScaleY(168);
Width := ScaleX(46);
Height := ScaleY(13);
Caption := 'Webserver port';
end;
{ txtClientPort }
txtClientPort := TEdit.Create(Page);
with txtClientPort do
begin
Parent := Page.Surface;
Left := ScaleX(180);
Top := ScaleY(165);
Width := ScaleX(185);
Height := ScaleY(21);
Text := '3000';
OnKeyPress := @AcceptNumbersOnlyKeyPress;
TabOrder := 3;
end;
{ lblBackendPort }
lblBackendPort := TLabel.Create(Page);
with lblBackendPort do
begin
Parent := Page.Surface;
Left := ScaleX(24);
Top := ScaleY(198);
Width := ScaleX(46);
Height := ScaleY(13);
Caption := 'DCS Olympus port';
end;
{ txtBackendPort }
txtBackendPort := TEdit.Create(Page);
with txtBackendPort do
begin
Parent := Page.Surface;
Left := ScaleX(180);
Top := ScaleY(195);
Width := ScaleX(185);
Height := ScaleY(21);
Text := '3001';
OnKeyPress := @AcceptNumbersOnlyKeyPress;
TabOrder := 4;
end;
with Page do
begin
OnActivate := @frmAddress_Activate;
OnShouldSkipPage := @frmAddress_ShouldSkipPage;
OnBackButtonClick := @frmAddress_BackButtonClick;
OnNextButtonClick := @frmAddress_NextButtonClick;
OnCancelButtonClick := @frmAddress_CancelButtonClick;
end;
Result := Page.ID;
end;
procedure frmPassword_Activate(Page: TWizardPage);
begin
end;
function frmPassword_ShouldSkipPage(Page: TWizardPage): Boolean;
begin
Result := False;
end;
function frmPassword_BackButtonClick(Page: TWizardPage): Boolean;
begin
Result := True;
end;
function frmPassword_NextButtonClick(Page: TWizardPage): Boolean;
begin
if (Trim(txtPassword.Text) <> '') and (Trim(txtBluePassword.Text) <> '') and (Trim(txtRedPassword.Text) <> '') then begin
Result := True;
end else
begin
MsgBox('All password fields must be filled to proceed.', mbInformation, MB_OK);
Result := False;
end;
end;
procedure frmPassword_CancelButtonClick(Page: TWizardPage; var Cancel, Confirm: Boolean);
begin
end;
function frmPassword_CreatePage(PreviousPageId: Integer): Integer;
var
Page: TWizardPage;
begin
Page := CreateCustomPage(
PreviousPageId,
'DCS Olympus passwords',
'Set DCS Olympus Admin and Commander passwords'
);
{ lblPassword }
lblPassword := TLabel.Create(Page);
with lblPassword do
begin
Parent := Page.Surface;
Left := ScaleX(24);
Top := ScaleY(28);
Width := ScaleX(46);
Height := ScaleY(13);
Caption := 'Game Master password';
end;
{ txtPassword }
txtPassword := TPasswordEdit.Create(Page);
with txtPassword do
begin
Parent := Page.Surface;
Left := ScaleX(180);
Top := ScaleY(25);
Width := ScaleX(185);
Height := ScaleY(21);
TabOrder := 2;
end;
{ lblBluePassword }
lblBluePassword := TLabel.Create(Page);
with lblBluePassword do
begin
Parent := Page.Surface;
Left := ScaleX(24);
Top := ScaleY(58);
Width := ScaleX(46);
Height := ScaleY(13);
Caption := 'Blue Commander password';
end;
{ txtBluePassword }
txtBluePassword := TPasswordEdit.Create(Page);
with txtBluePassword do
begin
Parent := Page.Surface;
Left := ScaleX(180);
Top := ScaleY(55);
Width := ScaleX(185);
Height := ScaleY(21);
TabOrder := 2;
end;
{ lblRedPassword }
lblRedPassword := TLabel.Create(Page);
with lblRedPassword do
begin
Parent := Page.Surface;
Left := ScaleX(24);
Top := ScaleY(88);
Width := ScaleX(46);
Height := ScaleY(13);
Caption := 'Red Commander password';
end;
{ txtRedPassword }
txtRedPassword := TPasswordEdit.Create(Page);
with txtRedPassword do
begin
Parent := Page.Surface;
Left := ScaleX(180);
Top := ScaleY(85);
Width := ScaleX(185);
Height := ScaleY(21);
TabOrder := 2;
end;
{ lblPasswordInstructions }
lblPasswordInstructions := TNewStaticText.Create(Page);
with lblPasswordInstructions do
begin
Parent := Page.Surface;
Left := ScaleX(24);
Top := ScaleY(120);
Width := ScaleX(340);
Height := ScaleY(13);
WordWrap := True;
Caption := 'Passwords can be changed in the future by editing the file "olympus.json". For more information, see the DCS Olympus Wiki';
end;
with Page do
begin
OnActivate := @frmPassword_Activate;
OnShouldSkipPage := @frmPassword_ShouldSkipPage;
OnBackButtonClick := @frmPassword_BackButtonClick;
OnNextButtonClick := @frmPassword_NextButtonClick;
OnCancelButtonClick := @frmPassword_CancelButtonClick;
end;
Result := Page.ID;
end;
procedure InitializeWizard();
begin
{this page will come after welcome page}
AddressPage := frmAddress_CreatePage(wpSelectDir);
PasswordPage:= frmPassword_CreatePage(AddressPage);
end;
function GetAddress(Value: string): string;
begin
if txtLocalInstall.Checked then begin
Result := 'localhost'
end else
begin
Result := '*'
end
end;
function GetClientPort(Value: string): string;
begin
Result := txtClientPort.Text;
end;
function GetBackendPort(Value: string): string;
begin
Result := txtBackendPort.Text;
end;
function GetPassword(Value: string): string;
begin
Result := txtPassword.Text;
end;
function GetBluePassword(Value: string): string;
begin
Result := txtBluePassword.Text;
end;
function GetRedPassword(Value: string): string;
begin
Result := txtRedPassword.Text;
end;

View File

@ -0,0 +1,4 @@
python -m venv venv
call ./venv/Scripts/activate
pip install pyinstaller
python -m PyInstaller configurator.py --onefile

View File

@ -0,0 +1,67 @@
import argparse, json
def main():
parser = argparse.ArgumentParser(
prog='DCS Olympus configurator',
description='This software allows to edit the DCS Olympus configuration file',
epilog='')
parser.add_argument('-a', '--address')
parser.add_argument('-c', '--clientPort')
parser.add_argument('-b', '--backendPort')
parser.add_argument('-p', '--password')
parser.add_argument('-bp', '--bluePassword')
parser.add_argument('-rp', '--redPassword')
args = parser.parse_args()
with open("olympus.json", "r") as fp:
config = json.load(fp)
if (args.address is not None):
config["server"]["address"] = args.address
print(f"Address set to {args.address}")
else:
print("No address provided, skipping...")
if args.backendPort is not None:
if args.backendPort.isdecimal():
config["server"]["port"] = int(args.backendPort)
print(f"Backend port set to {args.backendPort}")
else:
print(f"Invalid backend port provided {args.backendPort}")
else:
print("No backend port provided, skipping...")
if (args.password is not None):
config["authentication"]["gameMasterPassword"] = args.password
print(f"Game Master password set to {args.password}")
else:
print("No Game Master password provided, skipping...")
if (args.bluePassword is not None):
config["authentication"]["blueCommanderPassword"] = args.bluePassword
print(f"Blue Commander password set to {args.bluePassword}")
else:
print("No Blue Commander password provided, skipping...")
if (args.redPassword is not None):
config["authentication"]["redCommanderPassword"] = args.redPassword
print(f"Red Commander password set to {args.redPassword}")
else:
print("No Red Commander password provided, skipping...")
if args.clientPort is not None:
if args.clientPort.isdecimal():
config["client"]["port"] = int(args.clientPort)
print(f"Client port set to {args.clientPort}")
else:
print(f"Invalid client port provided {args.clientPort}")
else:
print("No client port provided, skipping...")
with open("olympus.json", "w") as fp:
json.dump(config, fp, indent = 4)
if __name__ == "__main__":
main()

View File

@ -0,0 +1,44 @@
# -*- mode: python ; coding: utf-8 -*-
block_cipher = None
a = Analysis(
['configurator.py'],
pathex=[],
binaries=[],
datas=[],
hiddenimports=[],
hookspath=[],
hooksconfig={},
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher,
noarchive=False,
)
pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)
exe = EXE(
pyz,
a.scripts,
a.binaries,
a.zipfiles,
a.datas,
[],
name='configurator',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
upx_exclude=[],
runtime_tmpdir=None,
console=True,
disable_windowed_traceback=False,
argv_emulation=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None,
)