diff --git a/source/model/Game.Base.pas b/source/model/Game.Base.pas index ded4a8e..09c70fe 100644 --- a/source/model/Game.Base.pas +++ b/source/model/Game.Base.pas @@ -25,6 +25,10 @@ type procedure Load; virtual; procedure Save; virtual; + function GetExecutable: string; virtual; abstract; + function GetParameters: string; virtual; + function GetCommandLine: string; virtual; + property Loaded: Boolean read FLoaded; property Location: string read FLocation; property Modified: Boolean read FModified; @@ -85,6 +89,25 @@ begin end; +function TCustomGame.GetParameters: string; +begin + Result := ''; +end; + + +function TCustomGame.GetCommandLine: string; +var + parameters: string; + +begin + Result := GetExecutable; + + parameters := GetParameters; + if Length(parameters) > 0 then + Result := Result + ' ' + parameters; +end; + + procedure TCustomGame.PropertyChanged(const APropertyName: string); begin if not FModified then diff --git a/source/model/Game.Chivalry.pas b/source/model/Game.Chivalry.pas index b000094..5cfdc62 100644 --- a/source/model/Game.Chivalry.pas +++ b/source/model/Game.Chivalry.pas @@ -31,6 +31,9 @@ type constructor Create(const ALocation: string); override; destructor Destroy; override; + function GetExecutable: string; override; + function GetParameters: string; override; + { IGameNetwork } function GetServerPort: Integer; function GetPeerPort: Integer; @@ -80,6 +83,8 @@ uses System.IniFiles, System.SysUtils, + Winapi.Windows, + UDKIniFile; @@ -103,6 +108,7 @@ const + { TChivalryGame } constructor TChivalryGame.Create(const ALocation: string); begin @@ -124,6 +130,38 @@ begin end; +function TChivalryGame.GetExecutable: string; +var + isWow64: BOOL; + bits: string; + +begin + {$IFDEF WIN64} + bits := 'Win64'; + {$ELSE} + if IsWow64Process(GetCurrentProcess, isWow64) and isWow64 then + bits := 'Win64' + else + bits := 'Win32'; + {$ENDIF} + + Result := Location + 'Binaries\' + bits + '\UDKLogging.exe'; +end; + + +function TChivalryGame.GetParameters: string; +begin + // #ToDo1 -oMvR: 2-7-2014: check how changing the starting map influences the map list, + // that could make selecting the starting map possible. + // Otherwise, a starting map option would need to shuffle the + // map list a bit. + if MapCount = 0 then + raise Exception.Create('Please add at least one map to the map list'); + + Result := Map[0].Name + '?steamsockets -dedicated=true -seekfreeloadingserver'; +end; + + procedure TChivalryGame.DoLoad; var gameSettings: TUDKIniFile; @@ -142,6 +180,7 @@ begin SetMessageOfTheDay(gameSettings.ReadString(GameReplicationInfo, GameReplicationInfoMessageOfTheDay, '')); mapListChanged := (FMapList.Count > 0); + FMapList.Clear; { Maplist is special; it occurs multiple times and order matters } mapListValues := TStringList.Create; diff --git a/source/view/Forms.Main.dfm b/source/view/Forms.Main.dfm index 03268ff..00427a9 100644 --- a/source/view/Forms.Main.dfm +++ b/source/view/Forms.Main.dfm @@ -66,7 +66,7 @@ object MainForm: TMainForm Top = 76 Width = 565 Height = 428 - ActivePage = tsAbout + ActivePage = tsMapList Align = alClient Style = tsButtons TabOrder = 2 @@ -94,9 +94,9 @@ object MainForm: TMainForm Header.Options = [hoAutoResize, hoColumnResize, hoDrag, hoShowSortGlyphs, hoVisible] TabOrder = 0 TreeOptions.AutoOptions = [toAutoDropExpand, toAutoScrollOnExpand, toAutoSort, toAutoTristateTracking, toAutoChangeScale] - TreeOptions.MiscOptions = [toAcceptOLEDrop, toFullRepaintOnResize, toInitOnSave, toWheelPanning, toEditOnClick] + TreeOptions.MiscOptions = [toAcceptOLEDrop, toFullRepaintOnResize, toInitOnSave, toWheelPanning, toFullRowDrag, toEditOnClick] TreeOptions.PaintOptions = [toHideFocusRect, toShowDropmark, toThemeAware, toUseBlendedImages] - TreeOptions.SelectionOptions = [toFullRowSelect, toMiddleClickSelect, toMultiSelect, toRightClickSelect] + TreeOptions.SelectionOptions = [toDisableDrawSelection, toFullRowSelect, toMiddleClickSelect, toMultiSelect, toRightClickSelect] OnChange = vstMapListChange OnDragOver = vstMapListDragOver OnDragDrop = vstMapListDragDrop @@ -2502,9 +2502,11 @@ object MainForm: TMainForm Top = 440 object actLaunch: TAction Caption = '&Launch server' + OnExecute = actLaunchExecute end object actCopyCmdLine: TAction Caption = '&Copy command line' + OnExecute = actCopyCmdLineExecute end object actSave: TAction Caption = '&Save changes' diff --git a/source/view/Forms.Main.pas b/source/view/Forms.Main.pas index e4a7e20..89cc662 100644 --- a/source/view/Forms.Main.pas +++ b/source/view/Forms.Main.pas @@ -149,6 +149,10 @@ type procedure SpinEditChange(Sender: TObject); procedure EditChange(Sender: TObject); procedure actCloseExecute(Sender: TObject); + procedure actSaveExecute(Sender: TObject); + procedure actRevertExecute(Sender: TObject); + procedure actLaunchExecute(Sender: TObject); + procedure actCopyCmdLineExecute(Sender: TObject); procedure actGameAddExecute(Sender: TObject); procedure actGameRemoveExecute(Sender: TObject); procedure actGameActiveExecute(Sender: TObject); @@ -165,8 +169,6 @@ type procedure actMapRemoveExecute(Sender: TObject); procedure actMapUpExecute(Sender: TObject); procedure actMapDownExecute(Sender: TObject); - procedure actSaveExecute(Sender: TObject); - procedure actRevertExecute(Sender: TObject); private type TBindingExpressionList = TList; TPageMenuDictionary = TDictionary; @@ -215,6 +217,7 @@ uses System.Math, System.StrUtils, System.SysUtils, + Vcl.Clipbrd, Vcl.GraphUtil, Vcl.Themes, Winapi.ShellAPI, @@ -478,10 +481,15 @@ var gameMapList: IGameMapList; begin - if Supports(ActiveGame, IGameMapList, gameMapList) then - vstMapList.RootNodeCount := gameMapList.MapCount - else - vstMapList.Clear; + vstMapList.BeginUpdate; + try + if Supports(ActiveGame, IGameMapList, gameMapList) then + vstMapList.RootNodeCount := gameMapList.MapCount + else + vstMapList.Clear; + finally + vstMapList.EndUpdate; + end; end; @@ -888,6 +896,27 @@ begin end; +procedure TMainForm.actLaunchExecute(Sender: TObject); +begin + if not Assigned(ActiveGame) then + exit; + + if ShellExecute(0, 'open', PChar(ActiveGame.GetExecutable), PChar(ActiveGame.GetParameters), + PChar(ActiveGame.Location), SW_SHOWNORMAL) <= 32 then + RaiseLastOSError; +end; + + +procedure TMainForm.actCopyCmdLineExecute(Sender: TObject); +begin + if not Assigned(ActiveGame) then + exit; + + Clipboard.AsText := ActiveGame.GetCommandLine; + MessageBox(Self.Handle, 'Command line has been copied to the clipboard', 'Copy', MB_OK or MB_ICONINFORMATION); +end; + + procedure TMainForm.actMapAddExecute(Sender: TObject); var gameMapList: IGameMapList;