Added: game list - adding, removing and persisting
Added: auto-detection of game location
This commit is contained in:
parent
75f07a0680
commit
736cb4b231
@ -3,9 +3,15 @@ unit Resources;
|
|||||||
interface
|
interface
|
||||||
const
|
const
|
||||||
AssetsPath = 'assets\';
|
AssetsPath = 'assets\';
|
||||||
|
AssetChivalryMedievalWarfareMapListFileName = 'Chivalry.MedievalWarfare.MapList.ini';
|
||||||
|
|
||||||
|
|
||||||
|
UserDataPath = 'Chivalry Server Launcher\';
|
||||||
|
UserGamesFileName = 'Games.json';
|
||||||
|
|
||||||
|
|
||||||
function GetAssetPath(const AAsset: string): string;
|
function GetAssetPath(const AAsset: string): string;
|
||||||
|
function GetUserDataPath(const AAsset: string): string;
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
uses
|
uses
|
||||||
@ -17,4 +23,10 @@ begin
|
|||||||
Result := App.Path + AssetsPath + AAsset;
|
Result := App.Path + AssetsPath + AAsset;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
function GetUserDataPath(const AAsset: string): string;
|
||||||
|
begin
|
||||||
|
Result := App.UserPath + UserDataPath + AAsset;
|
||||||
|
end;
|
||||||
|
|
||||||
end.
|
end.
|
||||||
|
@ -9,16 +9,22 @@ type
|
|||||||
TCustomGame = class(TInterfacedPersistent)
|
TCustomGame = class(TInterfacedPersistent)
|
||||||
private
|
private
|
||||||
FLocation: string;
|
FLocation: string;
|
||||||
|
FLoaded: Boolean;
|
||||||
protected
|
protected
|
||||||
procedure Notify(const APropertyName: string); virtual;
|
procedure Notify(const APropertyName: string); virtual;
|
||||||
|
|
||||||
|
procedure DoLoad; virtual; abstract;
|
||||||
|
procedure DoSave; virtual; abstract;
|
||||||
public
|
public
|
||||||
class function GetGameName: string; virtual; abstract;
|
class function GameName: string; virtual; abstract;
|
||||||
|
class function AutoDetect: TCustomGame; virtual;
|
||||||
|
|
||||||
constructor Create(const ALocation: string); virtual;
|
constructor Create(const ALocation: string); virtual;
|
||||||
|
|
||||||
procedure Load; virtual; abstract;
|
procedure Load; virtual;
|
||||||
procedure Save; virtual; abstract;
|
procedure Save; virtual;
|
||||||
|
|
||||||
|
property Loaded: Boolean read FLoaded;
|
||||||
property Location: string read FLocation;
|
property Location: string read FLocation;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -40,6 +46,25 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
class function TCustomGame.AutoDetect: TCustomGame;
|
||||||
|
begin
|
||||||
|
Result := nil;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure TCustomGame.Load;
|
||||||
|
begin
|
||||||
|
DoLoad;
|
||||||
|
FLoaded := True;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure TCustomGame.Save;
|
||||||
|
begin
|
||||||
|
DoSave;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
procedure TCustomGame.Notify(const APropertyName: string);
|
procedure TCustomGame.Notify(const APropertyName: string);
|
||||||
begin
|
begin
|
||||||
TBindings.Notify(Self, APropertyName);
|
TBindings.Notify(Self, APropertyName);
|
||||||
|
@ -4,6 +4,7 @@ interface
|
|||||||
uses
|
uses
|
||||||
System.Generics.Collections,
|
System.Generics.Collections,
|
||||||
|
|
||||||
|
Game.Base,
|
||||||
Game.Chivalry,
|
Game.Chivalry,
|
||||||
Game.Intf;
|
Game.Intf;
|
||||||
|
|
||||||
@ -16,7 +17,8 @@ type
|
|||||||
protected
|
protected
|
||||||
procedure LoadSupportedMapList(AList: TList<IGameMap>); override;
|
procedure LoadSupportedMapList(AList: TList<IGameMap>); override;
|
||||||
public
|
public
|
||||||
class function GetGameName: string; override;
|
class function GameName: string; override;
|
||||||
|
class function AutoDetect: TCustomGame; override;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
@ -25,19 +27,60 @@ uses
|
|||||||
System.Classes,
|
System.Classes,
|
||||||
System.IniFiles,
|
System.IniFiles,
|
||||||
System.SysUtils,
|
System.SysUtils,
|
||||||
|
System.Win.Registry,
|
||||||
|
Winapi.Windows,
|
||||||
|
|
||||||
Resources,
|
Resources,
|
||||||
Game.Map,
|
Game.Map,
|
||||||
Game.Registry;
|
Game.Registry;
|
||||||
|
|
||||||
|
|
||||||
|
const
|
||||||
|
SteamKey = '\Software\Valve\Steam';
|
||||||
|
SteamValuePath = 'SteamPath';
|
||||||
|
|
||||||
|
ChivalryServerSteamPath = 'steamapps\common\chivalry_ded_server\';
|
||||||
|
|
||||||
|
|
||||||
{ TChivalryMedievalWarfareGame }
|
{ TChivalryMedievalWarfareGame }
|
||||||
class function TChivalryMedievalWarfareGame.GetGameName: string;
|
class function TChivalryMedievalWarfareGame.GameName: string;
|
||||||
begin
|
begin
|
||||||
Result := 'Chivalry: Medieval Warfare';
|
Result := 'Chivalry: Medieval Warfare';
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
class function TChivalryMedievalWarfareGame.AutoDetect: TCustomGame;
|
||||||
|
var
|
||||||
|
registry: TRegistry;
|
||||||
|
steamPath: string;
|
||||||
|
serverPath: string;
|
||||||
|
|
||||||
|
begin
|
||||||
|
steamPath := '';
|
||||||
|
|
||||||
|
registry := TRegistry.Create(KEY_READ);
|
||||||
|
try
|
||||||
|
registry.RootKey := HKEY_CURRENT_USER;
|
||||||
|
if registry.OpenKeyReadOnly(SteamKey) then
|
||||||
|
try
|
||||||
|
if registry.ValueExists(SteamValuePath) then
|
||||||
|
steamPath := StringReplace(registry.ReadString(SteamValuePath), '/', '\', [rfReplaceAll]);
|
||||||
|
finally
|
||||||
|
registry.CloseKey;
|
||||||
|
end;
|
||||||
|
finally
|
||||||
|
FreeAndNil(registry);
|
||||||
|
end;
|
||||||
|
|
||||||
|
if (Length(steamPath) > 0) then
|
||||||
|
begin
|
||||||
|
serverPath := IncludeTrailingPathDelimiter(steamPath) + ChivalryServerSteamPath;
|
||||||
|
if DirectoryExists(serverPath) then
|
||||||
|
Result := TChivalryMedievalWarfareGame.Create(serverPath);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
procedure TChivalryMedievalWarfareGame.LoadSupportedMapList(AList: TList<IGameMap>);
|
procedure TChivalryMedievalWarfareGame.LoadSupportedMapList(AList: TList<IGameMap>);
|
||||||
var
|
var
|
||||||
mapListFileName: string;
|
mapListFileName: string;
|
||||||
@ -48,7 +91,7 @@ var
|
|||||||
mapIndex: Integer;
|
mapIndex: Integer;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
mapListFileName := GetAssetPath('Chivalry.MedievalWarfare.MapList.ini');
|
mapListFileName := Resources.GetAssetPath(Resources.AssetChivalryMedievalWarfareMapListFileName);
|
||||||
if not FileExists(mapListFileName) then
|
if not FileExists(mapListFileName) then
|
||||||
exit;
|
exit;
|
||||||
|
|
||||||
|
@ -15,12 +15,16 @@ type
|
|||||||
class procedure Finalize;
|
class procedure Finalize;
|
||||||
public
|
public
|
||||||
class function Instance: TGameList;
|
class function Instance: TGameList;
|
||||||
|
|
||||||
|
procedure AutoDetect;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
uses
|
uses
|
||||||
System.SysUtils;
|
System.SysUtils,
|
||||||
|
|
||||||
|
Game.Registry;
|
||||||
|
|
||||||
|
|
||||||
{ TGameList }
|
{ TGameList }
|
||||||
@ -39,6 +43,21 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure TGameList.AutoDetect;
|
||||||
|
var
|
||||||
|
gameClass: TCustomGameClass;
|
||||||
|
game: TCustomGame;
|
||||||
|
|
||||||
|
begin
|
||||||
|
for gameClass in TGameRegistry.RegisteredGames do
|
||||||
|
begin
|
||||||
|
game := gameClass.AutoDetect;
|
||||||
|
if Assigned(game) then
|
||||||
|
Add(game);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
initialization
|
initialization
|
||||||
finalization
|
finalization
|
||||||
TGameList.Finalize;
|
TGameList.Finalize;
|
||||||
|
@ -22,6 +22,7 @@ type
|
|||||||
class procedure Finalize;
|
class procedure Finalize;
|
||||||
public
|
public
|
||||||
class function RegisteredGames: TGameRegistryEnumerable;
|
class function RegisteredGames: TGameRegistryEnumerable;
|
||||||
|
class function ByClassName(const AClassName: string): TCustomGameClass;
|
||||||
|
|
||||||
class procedure Register(AGameClass: TCustomGameClass);
|
class procedure Register(AGameClass: TCustomGameClass);
|
||||||
class procedure Unregister(AGameClass: TCustomGameClass);
|
class procedure Unregister(AGameClass: TCustomGameClass);
|
||||||
@ -54,6 +55,22 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
class function TGameRegistry.ByClassName(const AClassName: string): TCustomGameClass;
|
||||||
|
var
|
||||||
|
gameClass: TCustomGameClass;
|
||||||
|
|
||||||
|
begin
|
||||||
|
Result := nil;
|
||||||
|
|
||||||
|
for gameClass in RegisteredGames do
|
||||||
|
if SameText(gameClass.ClassName, AClassName) then
|
||||||
|
begin
|
||||||
|
Result := gameClass;
|
||||||
|
break;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
class procedure TGameRegistry.Register(AGameClass: TCustomGameClass);
|
class procedure TGameRegistry.Register(AGameClass: TCustomGameClass);
|
||||||
begin
|
begin
|
||||||
if not SRegisteredGames.Contains(AGameClass) then
|
if not SRegisteredGames.Contains(AGameClass) then
|
||||||
|
@ -9,19 +9,71 @@ type
|
|||||||
TGameListPersist = class(TObject)
|
TGameListPersist = class(TObject)
|
||||||
public
|
public
|
||||||
class procedure Load(const AFileName: string; AList: TGameList);
|
class procedure Load(const AFileName: string; AList: TGameList);
|
||||||
|
class procedure Save(const AFileName: string; AList: TGameList);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
uses
|
uses
|
||||||
System.SysUtils;
|
System.IOUtils,
|
||||||
|
System.SysUtils,
|
||||||
|
|
||||||
|
superobject,
|
||||||
|
|
||||||
|
Game.Base,
|
||||||
|
Game.Registry;
|
||||||
|
|
||||||
|
|
||||||
|
const
|
||||||
|
KeyClassName = 'className';
|
||||||
|
KeyLocation = 'location';
|
||||||
|
|
||||||
|
|
||||||
{ TGameListPersist }
|
{ TGameListPersist }
|
||||||
class procedure TGameListPersist.Load(const AFileName: string; AList: TGameList);
|
class procedure TGameListPersist.Load(const AFileName: string; AList: TGameList);
|
||||||
|
var
|
||||||
|
inputList: ISuperObject;
|
||||||
|
inputGame: ISuperObject;
|
||||||
|
gameClass: TCustomGameClass;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
if not FileExists(AFileName) then
|
if not FileExists(AFileName) then
|
||||||
exit;
|
exit;
|
||||||
|
|
||||||
|
inputList := SO(TFile.ReadAllText(AFileName));
|
||||||
|
if Assigned(inputList) then
|
||||||
|
begin
|
||||||
|
for inputGame in inputList do
|
||||||
|
begin
|
||||||
|
gameClass := TGameRegistry.ByClassName(inputGame.S[KeyClassName]);
|
||||||
|
if Assigned(gameClass) then
|
||||||
|
AList.Add(gameClass.Create(inputGame.S[KeyLocation]));
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
class procedure TGameListPersist.Save(const AFileName: string; AList: TGameList);
|
||||||
|
var
|
||||||
|
outputList: ISuperObject;
|
||||||
|
outputGame: ISuperObject;
|
||||||
|
game: TCustomGame;
|
||||||
|
|
||||||
|
begin
|
||||||
|
outputList := SA([]);
|
||||||
|
|
||||||
|
for game in AList do
|
||||||
|
begin
|
||||||
|
outputGame := SO();
|
||||||
|
outputGame.S[KeyClassName] := game.ClassName;
|
||||||
|
outputGame.S[KeyLocation] := game.Location;
|
||||||
|
// outputGame.B['active'] := True;
|
||||||
|
|
||||||
|
outputList.AsArray.Add(outputGame);
|
||||||
|
end;
|
||||||
|
|
||||||
|
if ForceDirectories(ExtractFilePath(AFileName)) then
|
||||||
|
TFile.WriteAllText(AFileName, outputList.AsJSon(True));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
end.
|
end.
|
||||||
|
@ -59,7 +59,6 @@ object GameForm: TGameForm
|
|||||||
Style = csDropDownList
|
Style = csDropDownList
|
||||||
Anchors = [akLeft, akTop, akRight]
|
Anchors = [akLeft, akTop, akRight]
|
||||||
TabOrder = 0
|
TabOrder = 0
|
||||||
ExplicitWidth = 509
|
|
||||||
end
|
end
|
||||||
object deLocation: TJvDirectoryEdit
|
object deLocation: TJvDirectoryEdit
|
||||||
Left = 108
|
Left = 108
|
||||||
|
@ -77,7 +77,7 @@ begin
|
|||||||
cmbGame.Items.Clear;
|
cmbGame.Items.Clear;
|
||||||
|
|
||||||
for gameClass in TGameRegistry.RegisteredGames do
|
for gameClass in TGameRegistry.RegisteredGames do
|
||||||
cmbGame.Items.AddObject(gameClass.GetGameName, TObject(gameClass));
|
cmbGame.Items.AddObject(gameClass.GameName, TObject(gameClass));
|
||||||
finally
|
finally
|
||||||
cmbGame.Items.EndUpdate;
|
cmbGame.Items.EndUpdate;
|
||||||
cmbGame.ItemIndex := 0;
|
cmbGame.ItemIndex := 0;
|
||||||
|
@ -43,7 +43,7 @@ object MainForm: TMainForm
|
|||||||
Top = 75
|
Top = 75
|
||||||
Width = 565
|
Width = 565
|
||||||
Height = 472
|
Height = 472
|
||||||
ActivePage = tsAbout
|
ActivePage = tsGames
|
||||||
Align = alClient
|
Align = alClient
|
||||||
Style = tsButtons
|
Style = tsButtons
|
||||||
TabOrder = 2
|
TabOrder = 2
|
||||||
@ -119,7 +119,6 @@ object MainForm: TMainForm
|
|||||||
object tsConfiguration: TTabSheet
|
object tsConfiguration: TTabSheet
|
||||||
Caption = 'Server - Configuration'
|
Caption = 'Server - Configuration'
|
||||||
ImageIndex = 1
|
ImageIndex = 1
|
||||||
ExplicitLeft = 6
|
|
||||||
object gbServerName: TGroupBox
|
object gbServerName: TGroupBox
|
||||||
AlignWithMargins = True
|
AlignWithMargins = True
|
||||||
Left = 8
|
Left = 8
|
||||||
@ -202,7 +201,7 @@ object MainForm: TMainForm
|
|||||||
object tsGames: TTabSheet
|
object tsGames: TTabSheet
|
||||||
Caption = 'Launcher - Game locations'
|
Caption = 'Launcher - Game locations'
|
||||||
ImageIndex = 3
|
ImageIndex = 3
|
||||||
object VirtualStringTree2: TVirtualStringTree
|
object vstGames: TVirtualStringTree
|
||||||
AlignWithMargins = True
|
AlignWithMargins = True
|
||||||
Left = 8
|
Left = 8
|
||||||
Top = 30
|
Top = 30
|
||||||
@ -213,17 +212,29 @@ object MainForm: TMainForm
|
|||||||
Margins.Right = 8
|
Margins.Right = 8
|
||||||
Margins.Bottom = 8
|
Margins.Bottom = 8
|
||||||
Align = alClient
|
Align = alClient
|
||||||
Header.AutoSizeIndex = 0
|
Header.AutoSizeIndex = 1
|
||||||
Header.Font.Charset = DEFAULT_CHARSET
|
Header.Font.Charset = DEFAULT_CHARSET
|
||||||
Header.Font.Color = clWindowText
|
Header.Font.Color = clWindowText
|
||||||
Header.Font.Height = -11
|
Header.Font.Height = -11
|
||||||
Header.Font.Name = 'Tahoma'
|
Header.Font.Name = 'Tahoma'
|
||||||
Header.Font.Style = []
|
Header.Font.Style = []
|
||||||
Header.Options = [hoColumnResize, hoDrag, hoShowSortGlyphs, hoVisible]
|
Header.Options = [hoAutoResize, hoColumnResize, hoDrag, hoShowSortGlyphs, hoVisible]
|
||||||
TabOrder = 1
|
TabOrder = 1
|
||||||
|
TreeOptions.PaintOptions = [toHideFocusRect, toShowDropmark, toShowTreeLines, toThemeAware, toUseBlendedImages]
|
||||||
|
TreeOptions.SelectionOptions = [toFullRowSelect, toMiddleClickSelect, toRightClickSelect]
|
||||||
|
OnFocusChanged = vstGamesFocusChanged
|
||||||
|
OnGetText = vstGamesGetText
|
||||||
|
OnInitNode = vstGamesInitNode
|
||||||
Columns = <
|
Columns = <
|
||||||
item
|
item
|
||||||
Position = 0
|
Position = 0
|
||||||
|
Width = 200
|
||||||
|
WideText = 'Game'
|
||||||
|
end
|
||||||
|
item
|
||||||
|
Position = 1
|
||||||
|
Width = 337
|
||||||
|
WideText = 'Location'
|
||||||
end>
|
end>
|
||||||
end
|
end
|
||||||
object pnlGamesWarning: TPanel
|
object pnlGamesWarning: TPanel
|
||||||
@ -240,6 +251,7 @@ object MainForm: TMainForm
|
|||||||
BevelOuter = bvLowered
|
BevelOuter = bvLowered
|
||||||
ParentBackground = False
|
ParentBackground = False
|
||||||
TabOrder = 2
|
TabOrder = 2
|
||||||
|
Visible = False
|
||||||
object imgGamesWarning: TImage
|
object imgGamesWarning: TImage
|
||||||
Left = 12
|
Left = 12
|
||||||
Top = 12
|
Top = 12
|
||||||
|
@ -5,6 +5,7 @@ uses
|
|||||||
System.Bindings.Expression,
|
System.Bindings.Expression,
|
||||||
System.Classes,
|
System.Classes,
|
||||||
System.Generics.Collections,
|
System.Generics.Collections,
|
||||||
|
Vcl.ActnList,
|
||||||
Vcl.ComCtrls,
|
Vcl.ComCtrls,
|
||||||
Vcl.Controls,
|
Vcl.Controls,
|
||||||
Vcl.ExtCtrls,
|
Vcl.ExtCtrls,
|
||||||
@ -26,7 +27,7 @@ uses
|
|||||||
X2CLmusikCubeMenuBarPainter,
|
X2CLmusikCubeMenuBarPainter,
|
||||||
|
|
||||||
Game.Base,
|
Game.Base,
|
||||||
Game.Intf, Vcl.ActnList;
|
Game.Intf;
|
||||||
|
|
||||||
|
|
||||||
type
|
type
|
||||||
@ -85,7 +86,7 @@ type
|
|||||||
tsMapList: TTabSheet;
|
tsMapList: TTabSheet;
|
||||||
tsNetwork: TTabSheet;
|
tsNetwork: TTabSheet;
|
||||||
vstMapList: TVirtualStringTree;
|
vstMapList: TVirtualStringTree;
|
||||||
VirtualStringTree2: TVirtualStringTree;
|
vstGames: TVirtualStringTree;
|
||||||
alMain: TActionList;
|
alMain: TActionList;
|
||||||
actGameAdd: TAction;
|
actGameAdd: TAction;
|
||||||
actGameRemove: TAction;
|
actGameRemove: TAction;
|
||||||
@ -101,6 +102,9 @@ type
|
|||||||
procedure EditChange(Sender: TObject);
|
procedure EditChange(Sender: TObject);
|
||||||
procedure actGameAddExecute(Sender: TObject);
|
procedure actGameAddExecute(Sender: TObject);
|
||||||
procedure actGameRemoveExecute(Sender: TObject);
|
procedure actGameRemoveExecute(Sender: TObject);
|
||||||
|
procedure vstGamesInitNode(Sender: TBaseVirtualTree; ParentNode, Node: PVirtualNode; var InitialStates: TVirtualNodeInitStates);
|
||||||
|
procedure vstGamesGetText(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType; var CellText: string);
|
||||||
|
procedure vstGamesFocusChanged(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex);
|
||||||
private type
|
private type
|
||||||
TBindingExpressionList = TList<TBindingExpression>;
|
TBindingExpressionList = TList<TBindingExpression>;
|
||||||
TPageMenuMap = TDictionary<TTabSheet, TX2MenuBarItem>;
|
TPageMenuMap = TDictionary<TTabSheet, TX2MenuBarItem>;
|
||||||
@ -120,6 +124,8 @@ type
|
|||||||
procedure BindGameMapList;
|
procedure BindGameMapList;
|
||||||
procedure UpdateMenu;
|
procedure UpdateMenu;
|
||||||
|
|
||||||
|
procedure UpdateGameList;
|
||||||
|
|
||||||
property ActiveGame: TCustomGame read FActiveGame write SetActiveGame;
|
property ActiveGame: TCustomGame read FActiveGame write SetActiveGame;
|
||||||
property PageMenuMap: TPageMenuMap read FPageMenuMap;
|
property PageMenuMap: TPageMenuMap read FPageMenuMap;
|
||||||
property UIBindings: TBindingExpressionList read FUIBindings;
|
property UIBindings: TBindingExpressionList read FUIBindings;
|
||||||
@ -144,7 +150,8 @@ uses
|
|||||||
Forms.Game,
|
Forms.Game,
|
||||||
Game.Chivalry.MedievalWarfare,
|
Game.Chivalry.MedievalWarfare,
|
||||||
Game.List,
|
Game.List,
|
||||||
Persist.GameList;
|
Persist.GameList,
|
||||||
|
Resources;
|
||||||
|
|
||||||
|
|
||||||
type
|
type
|
||||||
@ -159,11 +166,18 @@ type
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
PCustomGame = ^TCustomGame;
|
||||||
|
|
||||||
|
|
||||||
const
|
const
|
||||||
INIHintPrefix = 'INI:';
|
INIHintPrefix = 'INI:';
|
||||||
INIHintSeparator = '>';
|
INIHintSeparator = '>';
|
||||||
|
|
||||||
|
|
||||||
|
GameColumnName = 0;
|
||||||
|
GameColumnLocation = 1;
|
||||||
|
|
||||||
|
|
||||||
{$R *.dfm}
|
{$R *.dfm}
|
||||||
|
|
||||||
|
|
||||||
@ -174,7 +188,7 @@ var
|
|||||||
pageIndex: Integer;
|
pageIndex: Integer;
|
||||||
menuGroup: TX2MenuBarGroup;
|
menuGroup: TX2MenuBarGroup;
|
||||||
menuItem: TX2MenuBarItem;
|
menuItem: TX2MenuBarItem;
|
||||||
// game: TCustomGame;
|
userGamesFileName: string;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
FUIBindings := TBindingExpressionList.Create;
|
FUIBindings := TBindingExpressionList.Create;
|
||||||
@ -202,11 +216,19 @@ begin
|
|||||||
lightBtnFace := BlendColors(clBtnFace, clWindow, 196);
|
lightBtnFace := BlendColors(clBtnFace, clWindow, 196);
|
||||||
pnlGamesWarning.Color := lightBtnFace;
|
pnlGamesWarning.Color := lightBtnFace;
|
||||||
|
|
||||||
// #ToDo1 -oMvR: 30-6-2014: load last active game
|
|
||||||
// game := TChivalryMedievalWarfareGame.Create('D:\Steam\steamapps\common\chivalry_ded_server');
|
|
||||||
// game.Load;
|
|
||||||
// ActiveGame := game;
|
|
||||||
|
|
||||||
|
{ Load games }
|
||||||
|
userGamesFileName := Resources.GetUserDataPath(Resources.UserGamesFileName);
|
||||||
|
if FileExists(userGamesFileName) then
|
||||||
|
TGameListPersist.Load(userGamesFileName, TGameList.Instance)
|
||||||
|
else
|
||||||
|
TGameList.Instance.AutoDetect;
|
||||||
|
|
||||||
|
UpdateGameList;
|
||||||
|
|
||||||
|
// #ToDo1 -oMvR: 30-6-2014: load last active game
|
||||||
|
if TGameList.Instance.Count > 0 then
|
||||||
|
ActiveGame := TGameList.Instance.First;
|
||||||
|
|
||||||
{ Initialize menu }
|
{ Initialize menu }
|
||||||
mbpMenuPainter.GroupColors.Hot.Assign(mbpMenuPainter.GroupColors.Normal);
|
mbpMenuPainter.GroupColors.Hot.Assign(mbpMenuPainter.GroupColors.Normal);
|
||||||
@ -227,6 +249,10 @@ end;
|
|||||||
procedure TMainForm.ActiveGameChanged;
|
procedure TMainForm.ActiveGameChanged;
|
||||||
begin
|
begin
|
||||||
ClearUIBindings;
|
ClearUIBindings;
|
||||||
|
vstMapList.Clear;
|
||||||
|
|
||||||
|
if Assigned(ActiveGame) and (not ActiveGame.Loaded) then
|
||||||
|
ActiveGame.Load;
|
||||||
|
|
||||||
// #ToDo1 -oMvR: 30-6-2014: attach observer to monitor changes
|
// #ToDo1 -oMvR: 30-6-2014: attach observer to monitor changes
|
||||||
|
|
||||||
@ -317,6 +343,15 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure TMainForm.UpdateGameList;
|
||||||
|
begin
|
||||||
|
vstGames.NodeDataSize := SizeOf(TCustomGame);
|
||||||
|
vstGames.RootNodeCount := TGameList.Instance.Count;
|
||||||
|
|
||||||
|
pnlGamesWarning.Visible := (TGameList.Instance.Count = 0);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
procedure TMainForm.SetActiveGame(const Value: TCustomGame);
|
procedure TMainForm.SetActiveGame(const Value: TCustomGame);
|
||||||
begin
|
begin
|
||||||
if Value <> FActiveGame then
|
if Value <> FActiveGame then
|
||||||
@ -364,14 +399,81 @@ var
|
|||||||
begin
|
begin
|
||||||
if TGameForm.Insert(Self, game) then
|
if TGameForm.Insert(Self, game) then
|
||||||
begin
|
begin
|
||||||
//
|
TGameList.Instance.Add(game);
|
||||||
|
|
||||||
|
// #ToDo1 -oMvR: 30-6-2014: move to shared spot
|
||||||
|
TGameListPersist.Save(Resources.GetUserDataPath(Resources.UserGamesFileName), TGameList.Instance);
|
||||||
|
UpdateGameList;
|
||||||
|
|
||||||
|
ActiveGame := game;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
procedure TMainForm.actGameRemoveExecute(Sender: TObject);
|
procedure TMainForm.actGameRemoveExecute(Sender: TObject);
|
||||||
|
var
|
||||||
|
nodeData: PCustomGame;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
//
|
if not Assigned(vstGames.FocusedNode) then
|
||||||
|
exit;
|
||||||
|
|
||||||
|
nodeData := vstGames.GetNodeData(vstGames.FocusedNode);
|
||||||
|
if MessageBox(Self.Handle, 'Do you want to remove the selected game?', 'Remove', MB_YESNO or MB_ICONQUESTION) = ID_YES then
|
||||||
|
begin
|
||||||
|
vstGames.BeginUpdate;
|
||||||
|
try
|
||||||
|
TGameList.Instance.Remove(nodeData^);
|
||||||
|
|
||||||
|
if nodeData^ = ActiveGame then
|
||||||
|
begin
|
||||||
|
if TGameList.Instance.Count > 0 then
|
||||||
|
ActiveGame := TGameList.Instance.First
|
||||||
|
else
|
||||||
|
ActiveGame := nil;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// #ToDo1 -oMvR: 30-6-2014: move to shared spot
|
||||||
|
TGameListPersist.Save(Resources.GetUserDataPath(Resources.UserGamesFileName), TGameList.Instance);
|
||||||
|
|
||||||
|
UpdateGameList;
|
||||||
|
finally
|
||||||
|
vstGames.EndUpdate;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure TMainForm.vstGamesInitNode(Sender: TBaseVirtualTree; ParentNode, Node: PVirtualNode; var InitialStates: TVirtualNodeInitStates);
|
||||||
|
var
|
||||||
|
nodeData: PCustomGame;
|
||||||
|
|
||||||
|
begin
|
||||||
|
nodeData := Sender.GetNodeData(Node);
|
||||||
|
nodeData^ := TGameList.Instance[Node^.Index];
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure TMainForm.vstGamesGetText(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType; var CellText: string);
|
||||||
|
var
|
||||||
|
nodeData: PCustomGame;
|
||||||
|
|
||||||
|
begin
|
||||||
|
nodeData := Sender.GetNodeData(Node);
|
||||||
|
|
||||||
|
case Column of
|
||||||
|
GameColumnName:
|
||||||
|
CellText := nodeData^.GameName;
|
||||||
|
|
||||||
|
GameColumnLocation:
|
||||||
|
CellText := nodeData^.Location;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure TMainForm.vstGamesFocusChanged(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex);
|
||||||
|
begin
|
||||||
|
actGameRemove.Enabled := Assigned(Sender.FocusedNode);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user