diff --git a/ChivalryServerLauncher.dpr b/ChivalryServerLauncher.dpr new file mode 100644 index 0000000..1bb41a8 --- /dev/null +++ b/ChivalryServerLauncher.dpr @@ -0,0 +1,30 @@ +program ChivalryServerLauncher; + +uses + Vcl.Forms, + Forms.Main in 'source\view\Forms.Main.pas' {MainForm}, + Game.Base in 'source\model\Game.Base.pas', + Game.Chivalry.MedievalWarfare in 'source\model\Game.Chivalry.MedievalWarfare.pas', + Game.Intf in 'source\model\Game.Intf.pas', + Game.Chivalry in 'source\model\Game.Chivalry.pas', + Game.Registry in 'source\model\Game.Registry.pas', + Resources in 'source\Resources.pas', + Game.Map in 'source\model\Game.Map.pas', + Forms.Game in 'source\view\Forms.Game.pas' {GameForm}, + Bindings.Converters in 'source\bindings\Bindings.Converters.pas', + Game.List in 'source\model\Game.List.pas', + Persist.GameList in 'source\persist\Persist.GameList.pas'; + +{$R *.res} + + +var + MainForm: TMainForm; + + +begin + Application.Initialize; + Application.MainFormOnTaskbar := True; + Application.CreateForm(TMainForm, MainForm); + Application.Run; +end. diff --git a/ChivalryServerLauncher.dproj b/ChivalryServerLauncher.dproj new file mode 100644 index 0000000..fa57723 --- /dev/null +++ b/ChivalryServerLauncher.dproj @@ -0,0 +1,214 @@ + + + {4CC5BE6F-BC4C-47D6-B434-FB070B81999F} + 13.4 + VCL + ChivalryServerLauncher.dpr + True + Build + Win64 + 3 + Application + + + true + + + true + Base + true + + + true + Base + true + + + true + Base + true + + + true + Cfg_1 + true + true + + + true + Cfg_1 + true + true + + + CompanyName=X²Software;FileDescription=Chivalry Server Launcher;FileVersion=0.1.0.0;InternalName=;LegalCopyright=Copyright (c) 2014 X²Software;LegalTrademarks=;OriginalFilename=ChivalryServerLauncher.exe;ProductName=Chivalry Server Launcher;ProductVersion=0.1 + 1 + true + 1043 + 0 + resources\icons\MainIcon.ico + None + fmx;IndySystem;DBXInterBaseDriver;DataSnapClient;DataSnapCommon;DataSnapServer;DataSnapProviderClient;DbxCommonDriver;dbxcds;DBXOracleDriver;CustomIPTransport;dsnap;fmxase;IndyCore;CloudService;FmxTeeUI;inetdbxpress;IPIndyImpl;bindcompfmx;rtl;dbrtl;DbxClientDriver;bindcomp;inetdb;xmlrtl;ibxpress;IndyProtocols;DBXMySQLDriver;soaprtl;bindengine;FMXTee;DBXInformixDriver;DBXFirebirdDriver;inet;fmxobj;DBXSybaseASADriver;fmxdae;dbexpress;DataSnapIndy10ServerTransport;$(DCC_UsePackage) + System;Xml;Data;Datasnap;Web;Soap;Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;$(DCC_Namespace) + .\lib\$(Platform)\ + .\bin\$(Platform)\ + + + .\lib\$(Platform)\ + .\bin\$(Platform)\ + + + JvBDE;JvGlobus;JvMM;JvManagedThreads;TeeDB;JvDlgs;JvCrypt;rbDIDE1516;vclib;inetdbbde;DBXSybaseASEDriver;JvDotNetCtrls;JvNet;vclimg;rbTCUI1516;rbTC1516;fmi;JvXPCtrls;rbRCL1516;rbDAD1516;vcldb;vcldsnap;X2CLGL;rbIBE1516;DBXDb2Driver;dclRBBDE1516;rbDB1516;JvCore;dclRBIBE1516;dclRBADO1516;vcl;DBXMSSQLDriver;CodeSiteExpressPkg;rbRAP1516;JvAppFrm;JvDB;JvRuntimeDesign;webdsnap;X2CLMB;OmniThreadLibraryRuntimeXE2;JclDeveloperTools;rbRIDE1516;adortl;JvDocking;JvWizards;rbADO1516;madBasic_;JvHMI;JvBands;vcldbx;rbDBDE1516;dclRBE1516;JvPluginSystem;rbIDE1516;Tee;rbUSERDesign1516;DBXOdbcDriver;JvCmp;madDisAsm_;JvSystem;svnui;JvControls;JvTimeFramework;TeeUI;vclactnband;bindcompvcl;vclie;Jcl;madExcept_;JvStdCtrls;vcltouch;JvCustom;JvJans;websnap;JvPageComps;JvPrintPreview;rbBDE1516;rbUSER1516;dclRBDBE1516;VclSmp;DataSnapConnectors;dsnapcon;JclVcl;JvPascalInterpreter;vclx;rbCIDE1516;svn;rbDBE1516;bdertl;VirtualTreesR;$(DCC_UsePackage) + Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) + $(BDS)\bin\default_app.manifest + + + false + true + true + true + + + $(BDS)\bin\default_app.manifest + + + $(BDS)\bin\default_app.manifest + false + + + + MainSource + + +
MainForm
+ dfm +
+ + + + + + + + +
GameForm
+ dfm +
+ + + + + Base + + + Cfg_1 + Base + +
+ + Delphi.Personality.12 + + + + + False + False + 1 + 0 + 0 + 0 + False + False + False + False + False + 1043 + 1252 + + + + + 1.0.0.0 + + + + + + 1.0.0.0 + + + + ChivalryServerLauncher.dpr + + + ExpressCoreLibrary by Developer Express Inc. + Express Cross Platform Library by Developer Express Inc. + ExpressPageControl by Developer Express Inc. + ExpressDataController Server Mode by Developer Express Inc. + ExpressEditors Library by Developer Express Inc. + ExpressWizardControl by Developer Express Inc. + ExpressBars by Developer Express Inc. + ExpressScheduler by Developer Express Inc. + ExpressQuantumGrid by Developer Express Inc. + ExpressPrinting System by Developer Express Inc. + ExpressPrinting System ReportLink for TeeChart by Developer Express Inc. + ExpressPivotGrid by Developer Express Inc. + ExpressOrgChart by Developer Express Inc. + ExpressPrinting System ReportLink for ExpressLayoutControl by Developer Express Inc. + dbExpress Data Source for ExpressDataController Server Mode by Developer Express Inc. + ADO Data Source for ExpressDataController Server Mode by Developer Express Inc. + ExpressEditors FieldLink by Developer Express Inc. + ExpressBars cxEditor item by Developer Express Inc. + ExpressBars extended DB items by Developer Express Inc. + ExpressBars extended items by Developer Express Inc. + ExpressBars DBNavigator by Developer Express Inc. + ExpressBars Ribbon controls by Developer Express Inc. + ExpressBars Tabbed MDI by Developer Express Inc. + ExpressDocking Library by Developer Express Inc. + ExpressLayout Control by Developer Express Inc. + ExpressQuantumTreeList by Developer Express Inc. + ExpressMemData by Developer Express Inc. + ExpressSpreadSheet by Developer Express Inc. + ExpressNavBar by Developer Express Inc. + ExpressPrinting System ReportLinks (Standard) by Developer Express Inc. + ExpressPrinting System ReportLink for DBTeeChart by Developer Express Inc. + ExpressPrinting System ContainerProducer for ExpressPageControl by Developer Express Inc. + ExpressPivotGrid OLAP by Developer Express Inc. + ExpressDBTree by Developer Express Inc. + ExpressTreePrintedDataSet by Developer Express Inc. + ExpressDBOrgChart by Developer Express Inc. + ExpressFlowChart by Developer Express Inc. + Express Cross Platform Library Icon Library by Developer Express Inc. + ExpressPageControl dxBar Popup Menu by Developer Express Inc. + ExpressScheduler Ribbon Event Window by Developer Express Inc. + ExpressScheduler connection to ExpressQuantumGrid by Developer Express Inc. + ExpressScheduler tree browser by Developer Express Inc. + ExpressQuantumTreeList dxBar Built-In Menu by Developer Express Inc. + ExpressQuantumGrid Wizard by Developer Express Inc. + ExpressPrinting System Cross Platform Library by Developer Express Inc. + ExpressPrinting System Extended Cross Platform Library by Developer Express Inc. + ExpressPrinting System ReportLink for ExpressPivotGrid by Developer Express Inc. + ExpressPrinting System ReportLink for ExpressScheduler by Developer Express Inc. + ExpressPrinting System ReportLink for ExpressSpreadSheet by Developer Express Inc. + ExpressPrinting System ReportLink for ExpressQuantumTreeList by Developer Express Inc. + ExpressPrinting System ReportLinks for ExpressDBOrgChart by Developer Express Inc. + ExpressPrinting System ReportLink for ExpressDBTree by Developer Express Inc. + ExpressPrinting System ReportLinks for ExpressFlowChart by Developer Express Inc. + ExpressPrinting System ReportLink for ExpressQuantumGrid by Developer Express Inc. + ExpressPrinting System ReportLinks for ExpressOrgChart by Developer Express Inc. + ExpressPrinting System Advanced Preview Window by Developer Express Inc. + ExpressPrinting System Ribbon Preview Window by Developer Express Inc. + ExpressPivotGrid connection to ExpressQuantumGrid Chart View by Developer Express Inc. + + + + + True + True + + + 12 + + + +
diff --git a/ChivalryServerLauncher.res b/ChivalryServerLauncher.res new file mode 100644 index 0000000..65fb718 Binary files /dev/null and b/ChivalryServerLauncher.res differ diff --git a/assets/Chivalry.MedievalWarfare.MapList.ini b/assets/Chivalry.MedievalWarfare.MapList.ini new file mode 100644 index 0000000..39901e5 --- /dev/null +++ b/assets/Chivalry.MedievalWarfare.MapList.ini @@ -0,0 +1,76 @@ +[Team Objective] +AOCTO-Battlegrounds_v3_P=Battlegrounds +AOCTO-Darkforest_p=Dark forest +AOCTO-Hillside_P=Hillside +AOCTO-Stoneshill_P=Stoneshill +AOCTO-Citadel_p=Citadel + +[Capture the Flag] +AOCCTF-Frigid_p=Frigid +AOCCTF-Moor_p=Moor +AOCCTF-Ruins_Large_P=Ruins Large +AOCCTF-Ruins_P=Ruins + +[Duel] +AOCDuel-Arena_Flat_p=Arena Flat +AOCDuel-Arena_p=Arena +AOCDuel-Bridge_p=Bridge +AOCDuel-Cistern_p=Cistern +AOCDuel-Courtyard_p=Courtyard +AOCDuel-Dininghall_p=Dining hall +AOCDuel-FrostPeak_p=Frost Peak +AOCDuel-Mines_p=Mines +AOCDuel-Shaft_p=Shaft +AOCDuel-Shipyard_p=Shipyard +AOCDuel-ThroneRoom_p=Throne Room +AOCDuel-Tower_p=Tower + +[King of the Hill] +AOCKOTH-Arena3_p=Arena +AOCKOTH-Hillside_P=Hillside +AOCKOTH-Moor_p=Moor +AOCKOTH-Darkforest_Valley_p=Dark forest Valley + +[Last Team Standing] +AOCLTS-Frigid_p=Frigid +AOCLTS-ArgonsWall_p=Argons Wall +AOCLTS-Arena3_p=Arena +AOCLTS-Battlegrounds_Farm_p=Battlegrounds Farm +AOCLTS-Battlegrounds_p=Battlegrounds +AOCLTS-Darkforest_XL_p=Dark forest +AOCLTS-Darkforest_Valley_p=Dark forest Valley +AOCLTS-Hillside_P=Hillside +AOCLTS-HillsidePyre_P=Hillside Pyre +AOCLTS-Moor_p=Moor +AOCLTS-Moor_Large_p=Moor Large +AOCLTS-Ruins_P=Ruins +AOCLTS-Ruins_Large_P=Ruins Large +AOCLTS-StoneshillVillage_P=Stoneshill Village +AOCLTS-ThroneRoom_P=Throne Room + +[Free for All] +AOCFFA-Arena3_p=Arena +AOCFFA-Darkforest_Cistern_p=Dark forest Cistern +AOCFFA-Darkforest_Valley_p=Dark forest Valley +AOCFFA-HillsidePyre_P=Hillside Pyre +AOCFFA-Hillside_P=Hillside +AOCFFA-Moor_p=Moor +AOCFFA-Ruins_P=Ruins +AOCFFA-ThroneRoomXL_P=Throne Room XL +AOCFFA-StoneshillVillage_P=Stoneshill Village + +[Team Deathmatch] +AOCTD-Frigid_p=Frigid +AOCTD-ArgonsWall_p=Argons Wall +AOCTD-Ruins_P=Ruins +AOCTD-ThroneRoom_P=Throne Room +AOCTD-StoneshillVillage_P=Stoneshill Village +AOCTD-Moor_p=Moor +AOCTD-Battlegrounds_Farm_p=Battlegrounds Farm +AOCTD-Battlegrounds_p=Battlegrounds +AOCTD-Hillside_P=Hillside +AOCTD-HillsidePyre_P=Hillside Pyre +AOCTD-Darkforest_XL_p=Dark forest XL +AOCTD-Darkforest_Valley_p=Dark forest Valley +AOCTD-Moor_Large_p=Moor Large +AOCTD-Ruins_Large_P=Ruins Large \ No newline at end of file diff --git a/license.txt b/license.txt new file mode 100644 index 0000000..fa64efe --- /dev/null +++ b/license.txt @@ -0,0 +1,23 @@ +Chivalry Server Launcher is released under the zlib/libpng OSI-approved license. +For more information: http://www.opensource.org/ + +Copyright (c) 2014 X2Software +http://www.x2software.net/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from +the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software in a + product, an acknowledgment in the product documentation would be + appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + +3. This notice may not be removed or altered from any source distribution. diff --git a/readme.txt b/readme.txt new file mode 100644 index 0000000..ea2d2b8 --- /dev/null +++ b/readme.txt @@ -0,0 +1,19 @@ +Built using Embarcadero Delphi XE2 + + +Required components: + +JEDI Code Library (JCL) and Visual Component Library (JVCL) +http://www.delphi-jedi.org/ + +SuperObject +https://code.google.com/p/superobject/ + +Virtual Treeview +http://www.soft-gems.net/index.php/controls/virtual-treeview + +X² Component Library +http://svn.x2software.net/wsvn/x2cl + +X² Utils +http://svn.x2software.net/wsvn/x2utils \ No newline at end of file diff --git a/resources/icons/MainIcon.ico b/resources/icons/MainIcon.ico new file mode 100644 index 0000000..898df04 Binary files /dev/null and b/resources/icons/MainIcon.ico differ diff --git a/resources/images/chiv_logoshadow.png b/resources/images/chiv_logoshadow.png new file mode 100644 index 0000000..21ff335 Binary files /dev/null and b/resources/images/chiv_logoshadow.png differ diff --git a/resources/images/chiv_logoshadow_75.png b/resources/images/chiv_logoshadow_75.png new file mode 100644 index 0000000..2622407 Binary files /dev/null and b/resources/images/chiv_logoshadow_75.png differ diff --git a/resources/images/menu/About.png b/resources/images/menu/About.png new file mode 100644 index 0000000..9d95129 Binary files /dev/null and b/resources/images/menu/About.png differ diff --git a/resources/images/menu/Games.png b/resources/images/menu/Games.png new file mode 100644 index 0000000..1093650 Binary files /dev/null and b/resources/images/menu/Games.png differ diff --git a/resources/images/menu/Maplist.png b/resources/images/menu/Maplist.png new file mode 100644 index 0000000..f0ade17 Binary files /dev/null and b/resources/images/menu/Maplist.png differ diff --git a/resources/images/menu/Network.png b/resources/images/menu/Network.png new file mode 100644 index 0000000..5d7fe65 Binary files /dev/null and b/resources/images/menu/Network.png differ diff --git a/resources/images/menu/Settings.png b/resources/images/menu/Settings.png new file mode 100644 index 0000000..5b958a8 Binary files /dev/null and b/resources/images/menu/Settings.png differ diff --git a/resources/images/toolbar/add.png b/resources/images/toolbar/add.png new file mode 100644 index 0000000..27e7249 Binary files /dev/null and b/resources/images/toolbar/add.png differ diff --git a/resources/images/toolbar/remove.png b/resources/images/toolbar/remove.png new file mode 100644 index 0000000..b59c23c Binary files /dev/null and b/resources/images/toolbar/remove.png differ diff --git a/resources/images/warning.png b/resources/images/warning.png new file mode 100644 index 0000000..64ee231 Binary files /dev/null and b/resources/images/warning.png differ diff --git a/source/Resources.pas b/source/Resources.pas new file mode 100644 index 0000000..310e2d2 --- /dev/null +++ b/source/Resources.pas @@ -0,0 +1,20 @@ +unit Resources; + +interface +const + AssetsPath = 'assets\'; + + + function GetAssetPath(const AAsset: string): string; + +implementation +uses + X2UtApp; + + +function GetAssetPath(const AAsset: string): string; +begin + Result := App.Path + AssetsPath + AAsset; +end; + +end. diff --git a/source/bindings/Bindings.Converters.pas b/source/bindings/Bindings.Converters.pas new file mode 100644 index 0000000..c7d30e7 --- /dev/null +++ b/source/bindings/Bindings.Converters.pas @@ -0,0 +1,42 @@ +unit Bindings.Converters; + +interface +implementation +uses + System.Bindings.Outputs, + System.Rtti; + + +const + IntToExtended = 'IntToExtended'; + ExtendedToInt = 'ExtendedToInt'; + + +procedure RegisterConverters; +begin + TValueRefConverterFactory.RegisterConversion([TypeInfo(Integer)], [TypeInfo(Extended)], + TConverterDescription.Create( + procedure(const I: TValue; var O: TValue) + begin + O := TValue.From(I.AsInteger); + end, + + IntToExtended, IntToExtended, '', True, '', nil) + ); + + TValueRefConverterFactory.RegisterConversion([TypeInfo(Extended)], [TypeInfo(Integer)], + TConverterDescription.Create( + procedure(const I: TValue; var O: TValue) + begin + O := TValue.From(Trunc(I.AsExtended)); + end, + + ExtendedToInt, ExtendedToInt, '', True, '', nil) + ); +end; + + +initialization + RegisterConverters; + +end. diff --git a/source/model/Game.Base.pas b/source/model/Game.Base.pas new file mode 100644 index 0000000..7b88cfa --- /dev/null +++ b/source/model/Game.Base.pas @@ -0,0 +1,48 @@ +unit Game.Base; + +interface +uses + System.Classes; + + +type + TCustomGame = class(TInterfacedPersistent) + private + FLocation: string; + protected + procedure Notify(const APropertyName: string); virtual; + public + class function GetGameName: string; virtual; abstract; + + constructor Create(const ALocation: string); virtual; + + procedure Load; virtual; abstract; + procedure Save; virtual; abstract; + + property Location: string read FLocation; + end; + + TCustomGameClass = class of TCustomGame; + + +implementation +uses + System.Bindings.Helper, + System.SysUtils; + + +{ TCustomGame } +constructor TCustomGame.Create(const ALocation: string); +begin + inherited Create; + + FLocation := IncludeTrailingPathDelimiter(ALocation); +end; + + +procedure TCustomGame.Notify(const APropertyName: string); +begin + TBindings.Notify(Self, APropertyName); +end; + +end. diff --git a/source/model/Game.Chivalry.MedievalWarfare.pas b/source/model/Game.Chivalry.MedievalWarfare.pas new file mode 100644 index 0000000..33a59e9 --- /dev/null +++ b/source/model/Game.Chivalry.MedievalWarfare.pas @@ -0,0 +1,88 @@ +unit Game.Chivalry.MedievalWarfare; + +interface +uses + System.Generics.Collections, + + Game.Chivalry, + Game.Intf; + + +type + { I haven't actually done any research into the dedicated server + for the other Chivalry game, so for now most stuff is implemented + in the base Chivalry class. } + TChivalryMedievalWarfareGame = class(TChivalryGame) + protected + procedure LoadSupportedMapList(AList: TList); override; + public + class function GetGameName: string; override; + end; + + +implementation +uses + System.Classes, + System.IniFiles, + System.SysUtils, + + Resources, + Game.Map, + Game.Registry; + + +{ TChivalryMedievalWarfareGame } +class function TChivalryMedievalWarfareGame.GetGameName: string; +begin + Result := 'Chivalry: Medieval Warfare'; +end; + + +procedure TChivalryMedievalWarfareGame.LoadSupportedMapList(AList: TList); +var + mapListFileName: string; + mapList: TMemIniFile; + categories: TStringList; + categoryName: string; + maps: TStringList; + mapIndex: Integer; + +begin + mapListFileName := GetAssetPath('Chivalry.MedievalWarfare.MapList.ini'); + if not FileExists(mapListFileName) then + exit; + + mapList := TMemIniFile.Create(mapListFileName); + try + categories := nil; + maps := nil; + try + categories := TStringList.Create; + maps := TStringList.Create; + + mapList.ReadSections(categories); + + for categoryName in categories do + begin + maps.Clear; + mapList.ReadSectionValues(categoryName, maps); + + for mapIndex := 0 to Pred(maps.Count) do + AList.Add(TGameMap.Create(Trim(maps.Names[mapIndex]), + Trim(maps.ValueFromIndex[mapIndex]), + Trim(categoryName))); + end; + finally + FreeAndNil(maps); + FreeAndNil(categories); + end; + finally + FreeAndNil(mapList); + end; +end; + + +initialization + TGameRegistry.Register(TChivalryMedievalWarfareGame); + +end. diff --git a/source/model/Game.Chivalry.pas b/source/model/Game.Chivalry.pas new file mode 100644 index 0000000..f5702e1 --- /dev/null +++ b/source/model/Game.Chivalry.pas @@ -0,0 +1,229 @@ +unit Game.Chivalry; + +interface +uses + System.Generics.Collections, + + Game.Base, + Game.Intf; + + +type + TChivalryGame = class(TCustomGame, IGameNetwork, IGameName, IGameMapList) + private + FServerPort: Integer; + FPeerPort: Integer; + FQueryPort: Integer; + + FServerName: string; + FMessageOfTheDay: string; + + FSupportedMapList: TList; + FMapList: TList; + protected + procedure LoadSupportedMapList(AList: TList); virtual; abstract; + public + constructor Create(const ALocation: string); override; + destructor Destroy; override; + + procedure Load; override; + procedure Save; override; + + { IGameNetwork } + function GetServerPort: Integer; + function GetPeerPort: Integer; + function GetQueryPort: Integer; + + procedure SetServerPort(const Value: Integer); + procedure SetPeerPort(const Value: Integer); + procedure SetQueryPort(const Value: Integer); + + property ServerPort: Integer read GetServerPort write SetServerPort; + property PeerPort: Integer read GetPeerPort write SetPeerPort; + property QueryPort: Integer read GetQueryPort write SetQueryPort; + + { IGameName } + function GetServerName: string; + function GetMessageOfTheDay: string; + + procedure SetServerName(const Value: string); + procedure SetMessageOfTheDay(const Value: string); + + property ServerName: string read GetServerName write SetServerName; + property MessageOfTheDay: string read GetMessageOfTheDay write SetMessageOfTheDay; + + { IGameMapList } + function GetMapList: System.Generics.Collections.TList; + function GetSupportedMapList: System.Generics.Collections.TList; + end; + + +implementation +uses + System.IniFiles, + System.SysUtils; + + +const + GameSettingsFileName = 'UDKGame\Config\PCServer-UDKGame.ini'; + GameURL = 'URL'; + GameURLPort = 'Port'; GameURLPortDefault = 7777; + GameURLPeerPort = 'PeerPort'; GameURLPeerPortDefault = 7778; + + GameReplicationInfo = 'Engine.GameReplicationInfo'; + GameReplicationInfoServerName = 'ServerName'; + GameReplicationInfoMessageOfTheDay = 'MessageOfTheDay'; + + + EngineSettingsFileName = 'UDKGame\Config\PCServer-UDKEngine.ini'; + EngineSteam = 'OnlineSubsystemSteamworks.OnlineSubsystemSteamworks'; + EngineSteamQueryPort = 'QueryPort'; EngineSteamQueryPortDefault = 27015; + + + +{ TChivalryGame } +constructor TChivalryGame.Create(const ALocation: string); +begin + inherited Create(ALocation); + + FSupportedMapList := TList.Create; + FMapList := TList.Create; + + LoadSupportedMapList(FSupportedMapList); +end; + + +destructor TChivalryGame.Destroy; +begin + FreeAndNil(FMapList); + FreeAndNil(FSupportedMapList); + + inherited Destroy; +end; + +procedure TChivalryGame.Load; +var + gameSettings: TMemIniFile; + engineSettings: TMemIniFile; + +begin + gameSettings := TMemIniFile.Create(Location + GameSettingsFileName); + try + FServerPort := gameSettings.ReadInteger(GameURL, GameURLPort, GameURLPortDefault); + FPeerPort := gameSettings.ReadInteger(GameURL, GameURLPeerPort, GameURLPeerPortDefault); + + FServerName := gameSettings.ReadString(GameReplicationInfo, GameReplicationInfoServerName, ''); + FMessageOfTheDay := gameSettings.ReadString(GameReplicationInfo, GameReplicationInfoMessageOfTheDay, ''); + finally + FreeAndNil(gameSettings); + end; + + engineSettings := TMemIniFile.Create(Location + EngineSettingsFileName); + try + FQueryPort := engineSettings.ReadInteger(EngineSteam, EngineSteamQueryPort, EngineSteamQueryPortDefault); + finally + FreeAndNil(engineSettings); + end; + + // #ToDo1 -oMvR: 30-6-2014: load map list +end; + + +procedure TChivalryGame.Save; +begin + // #ToDo1 -oMvR: 30-6-2014: save to INI files +end; + + +function TChivalryGame.GetServerPort: Integer; +begin + Result := FServerPort; +end; + + +function TChivalryGame.GetPeerPort: Integer; +begin + Result := FPeerPort; +end; + + +function TChivalryGame.GetQueryPort: Integer; +begin + Result := FQueryPort; +end; + + +procedure TChivalryGame.SetServerPort(const Value: Integer); +begin + if Value <> FServerPort then + begin + FServerPort := Value; + Notify('ServerPort'); + end; +end; + + +procedure TChivalryGame.SetPeerPort(const Value: Integer); +begin + if Value <> FPeerPort then + begin + FPeerPort := Value; + Notify('PeerPort'); + end; +end; + + +procedure TChivalryGame.SetQueryPort(const Value: Integer); +begin + if Value <> FQueryPort then + begin + FQueryPort := Value; + Notify('QueryPort'); + end; +end; + + +function TChivalryGame.GetServerName: string; +begin + Result := FServerName; +end; + + +function TChivalryGame.GetMessageOfTheDay: string; +begin + Result := FMessageOfTheDay; +end; + + +procedure TChivalryGame.SetServerName(const Value: string); +begin + if Value <> FServerName then + begin + FServerName := Value; + Notify('ServerName'); + end; +end; + + +procedure TChivalryGame.SetMessageOfTheDay(const Value: string); +begin + if Value <> FMessageOfTheDay then + begin + FMessageOfTheDay := Value; + Notify('MessageOfTheDay'); + end; +end; + + +function TChivalryGame.GetMapList: System.Generics.Collections.TList; +begin + Result := FMapList; +end; + + +function TChivalryGame.GetSupportedMapList: System.Generics.Collections.TList; +begin + Result := FSupportedMapList; +end; + +end. diff --git a/source/model/Game.Intf.pas b/source/model/Game.Intf.pas new file mode 100644 index 0000000..1680b93 --- /dev/null +++ b/source/model/Game.Intf.pas @@ -0,0 +1,59 @@ +unit Game.Intf; + +interface +uses + System.Generics.Collections; + + +type + IGameNetwork = interface + ['{0B1445D2-E6B7-45FD-98CB-A76F01B9D4B8}'] + function GetServerPort: Integer; + function GetPeerPort: Integer; + function GetQueryPort: Integer; + + procedure SetServerPort(const Value: Integer); + procedure SetPeerPort(const Value: Integer); + procedure SetQueryPort(const Value: Integer); + + property ServerPort: Integer read GetServerPort write SetServerPort; + property PeerPort: Integer read GetPeerPort write SetPeerPort; + property QueryPort: Integer read GetQueryPort write SetQueryPort; + end; + + + IGameName = interface + ['{44A04A0D-BE01-42B7-8EF1-7EC5CC431B66}'] + function GetServerName: string; + function GetMessageOfTheDay: string; + + procedure SetServerName(const Value: string); + procedure SetMessageOfTheDay(const Value: string); + + property ServerName: string read GetServerName write SetServerName; + property MessageOfTheDay: string read GetMessageOfTheDay write SetMessageOfTheDay; + end; + + + IGameMap = interface + ['{B50A090C-3731-401F-91B5-0895CBE99921}'] + function GetCategory: string; + function GetName: string; + function GetDisplayName: string; + + property Category: string read GetCategory; + property Name: string read GetName; + property DisplayName: string read GetDisplayName; + end; + + + IGameMapList = interface + ['{E8552B4C-9447-4FAD-BB20-C5EB3AF07B0E}'] + function GetSupportedMapList: TList; + function GetMapList: TList; + end; + + +implementation + +end. diff --git a/source/model/Game.List.pas b/source/model/Game.List.pas new file mode 100644 index 0000000..6494aa2 --- /dev/null +++ b/source/model/Game.List.pas @@ -0,0 +1,46 @@ +unit Game.List; + +interface +uses + System.Generics.Collections, + + Game.Base; + + +type + TGameList = class(TList) + private + class var SInstance: TGameList; + protected + class procedure Finalize; + public + class function Instance: TGameList; + end; + + +implementation +uses + System.SysUtils; + + +{ TGameList } +class procedure TGameList.Finalize; +begin + FreeAndNil(SInstance); +end; + + +class function TGameList.Instance: TGameList; +begin + if not Assigned(SInstance) then + SInstance := TGameList.Create; + + Result := SInstance; +end; + + +initialization +finalization + TGameList.Finalize; + +end. diff --git a/source/model/Game.Map.pas b/source/model/Game.Map.pas new file mode 100644 index 0000000..24be1ef --- /dev/null +++ b/source/model/Game.Map.pas @@ -0,0 +1,57 @@ +unit Game.Map; + +interface +uses + Game.Intf; + + +type + TGameMap = class(TInterfacedObject, IGameMap) + private + FCategory: string; + FName: string; + FDisplayName: string; + public + constructor Create(const AName: string; const ADisplayName, ACategory: string); + + { IGameMap } + function GetCategory: string; + function GetName: string; + function GetDisplayName: string; + end; + + +implementation +uses + System.StrUtils; + + +{ TGameMap } +constructor TGameMap.Create(const AName, ADisplayName, ACategory: string); +begin + inherited Create; + + FName := AName; + FDisplayName := IfThen(Length(ADisplayName) > 0, ADisplayName, AName); + FCategory := ACategory; +end; + + +function TGameMap.GetCategory: string; +begin + Result := FCategory; +end; + + +function TGameMap.GetName: string; +begin + Result := FName; +end; + + +function TGameMap.GetDisplayName: string; +begin + Result := FDisplayName; +end; + +end. diff --git a/source/model/Game.Registry.pas b/source/model/Game.Registry.pas new file mode 100644 index 0000000..7c55960 --- /dev/null +++ b/source/model/Game.Registry.pas @@ -0,0 +1,81 @@ +unit Game.Registry; + +interface +uses + System.Generics.Collections, + + Game.Base; + +type + TGameRegistryEnumerable = class(TObject) + public + function GetEnumerator: TEnumerator; + end; + + + TGameRegistry = class(TObject) + protected + class var SRegisteredGames: TList; + class var SEnumerable: TGameRegistryEnumerable; + + class procedure Initialize; + class procedure Finalize; + public + class function RegisteredGames: TGameRegistryEnumerable; + + class procedure Register(AGameClass: TCustomGameClass); + class procedure Unregister(AGameClass: TCustomGameClass); + end; + + +implementation +uses + System.SysUtils; + + +{ TGameRegistry } +class procedure TGameRegistry.Initialize; +begin + SRegisteredGames := TList.Create; + SEnumerable := TGameRegistryEnumerable.Create; +end; + + +class procedure TGameRegistry.Finalize; +begin + FreeAndNil(SEnumerable); + FreeAndNil(SRegisteredGames); +end; + + +class function TGameRegistry.RegisteredGames: TGameRegistryEnumerable; +begin + Result := SEnumerable; +end; + + +class procedure TGameRegistry.Register(AGameClass: TCustomGameClass); +begin + if not SRegisteredGames.Contains(AGameClass) then + SRegisteredGames.Add(AGameClass); +end; + +class procedure TGameRegistry.Unregister(AGameClass: TCustomGameClass); +begin + SRegisteredGames.Remove(AGameClass); +end; + + +{ TGameRegistryEnumerable } +function TGameRegistryEnumerable.GetEnumerator: TEnumerator; +begin + Result := TGameRegistry.SRegisteredGames.GetEnumerator; +end; + +initialization + TGameRegistry.Initialize; + +finalization + TGameRegistry.Finalize; + +end. diff --git a/source/persist/Persist.GameList.pas b/source/persist/Persist.GameList.pas new file mode 100644 index 0000000..344adf4 --- /dev/null +++ b/source/persist/Persist.GameList.pas @@ -0,0 +1,27 @@ +unit Persist.GameList; + +interface +uses + Game.List; + + +type + TGameListPersist = class(TObject) + public + class procedure Load(const AFileName: string; AList: TGameList); + end; + + +implementation +uses + System.SysUtils; + + +{ TGameListPersist } +class procedure TGameListPersist.Load(const AFileName: string; AList: TGameList); +begin + if not FileExists(AFileName) then + exit; +end; + +end. diff --git a/source/view/Forms.Game.dfm b/source/view/Forms.Game.dfm new file mode 100644 index 0000000..021e4fc --- /dev/null +++ b/source/view/Forms.Game.dfm @@ -0,0 +1,121 @@ +object GameForm: TGameForm + Left = 0 + Top = 0 + ActiveControl = deLocation + BorderIcons = [biSystemMenu] + BorderStyle = bsDialog + Caption = 'Game location' + ClientHeight = 124 + ClientWidth = 519 + Color = clBtnFace + Font.Charset = DEFAULT_CHARSET + Font.Color = clWindowText + Font.Height = -11 + Font.Name = 'Tahoma' + Font.Style = [] + OldCreateOrder = False + Position = poOwnerFormCenter + OnCreate = FormCreate + PixelsPerInch = 96 + TextHeight = 13 + object gbGame: TGroupBox + AlignWithMargins = True + Left = 8 + Top = 8 + Width = 503 + Height = 75 + Margins.Left = 8 + Margins.Top = 8 + Margins.Right = 8 + Margins.Bottom = 8 + Align = alClient + TabOrder = 0 + ExplicitLeft = 232 + ExplicitTop = 136 + ExplicitWidth = 185 + ExplicitHeight = 105 + DesignSize = ( + 503 + 75) + object lblGame: TLabel + Left = 20 + Top = 15 + Width = 31 + Height = 13 + Caption = 'Game:' + end + object lblLocation: TLabel + Left = 20 + Top = 42 + Width = 44 + Height = 13 + Caption = 'Location:' + end + object cmbGame: TComboBox + Left = 108 + Top = 12 + Width = 383 + Height = 21 + Style = csDropDownList + Anchors = [akLeft, akTop, akRight] + TabOrder = 0 + ExplicitWidth = 509 + end + object deLocation: TJvDirectoryEdit + Left = 108 + Top = 39 + Width = 383 + Height = 21 + DialogKind = dkWin32 + DialogText = 'Select game location' + DialogOptionsWin32 = [odStatusAvailable, odEditBox, odNewDialogStyle, odNoNewButtonFolder] + Anchors = [akLeft, akTop, akRight] + TabOrder = 1 + ExplicitWidth = 509 + end + end + object pnlButtons: TPanel + AlignWithMargins = True + Left = 8 + Top = 91 + Width = 503 + Height = 25 + Margins.Left = 8 + Margins.Top = 0 + Margins.Right = 8 + Margins.Bottom = 8 + Align = alBottom + AutoSize = True + BevelOuter = bvNone + TabOrder = 1 + object btnCancel: TButton + Left = 428 + Top = 0 + Width = 75 + Height = 25 + Align = alRight + Cancel = True + Caption = 'Cancel' + ModalResult = 2 + TabOrder = 1 + end + object btnOK: TButton + AlignWithMargins = True + Left = 345 + Top = 0 + Width = 75 + Height = 25 + Margins.Left = 0 + Margins.Top = 0 + Margins.Right = 8 + Margins.Bottom = 0 + Align = alRight + Caption = 'OK' + Default = True + TabOrder = 0 + OnClick = btnOKClick + ExplicitLeft = 347 + ExplicitTop = 3 + end + end +end diff --git a/source/view/Forms.Game.pas b/source/view/Forms.Game.pas new file mode 100644 index 0000000..5a7f19a --- /dev/null +++ b/source/view/Forms.Game.pas @@ -0,0 +1,133 @@ +unit Forms.Game; + +interface +uses + System.Classes, + Vcl.Controls, + Vcl.Dialogs, + Vcl.ExtCtrls, + Vcl.Forms, + Vcl.Mask, + Vcl.StdCtrls, + + JvExMask, + JvToolEdit, + + Game.Base; + + +type + TGameForm = class(TForm) + btnCancel: TButton; + btnOK: TButton; + cmbGame: TComboBox; + deLocation: TJvDirectoryEdit; + gbGame: TGroupBox; + lblGame: TLabel; + lblLocation: TLabel; + pnlButtons: TPanel; + + procedure FormCreate(Sender: TObject); + procedure btnOKClick(Sender: TObject); + private + function GetGameClass: TCustomGameClass; + function GetLocation: string; + procedure SetGameClass(const Value: TCustomGameClass); + procedure SetLocation(const Value: string); + protected + property GameClass: TCustomGameClass read GetGameClass write SetGameClass; + property Location: string read GetLocation write SetLocation; + public + class function Insert(AOwner: TComponent; out AGame: TCustomGame): Boolean; + end; + + +implementation +uses + System.SysUtils, + Winapi.Windows, + + Game.Registry; + + +{$R *.dfm} + + +{ TGameForm } +class function TGameForm.Insert(AOwner: TComponent; out AGame: TCustomGame): Boolean; +begin + with Self.Create(AOwner) do + try + Result := (ShowModal = mrOk); + if Result then + AGame := GameClass.Create(Location); + finally + Free; + end; +end; + + +procedure TGameForm.FormCreate(Sender: TObject); +var + gameClass: TCustomGameClass; + +begin + cmbGame.Items.BeginUpdate; + try + cmbGame.Items.Clear; + + for gameClass in TGameRegistry.RegisteredGames do + cmbGame.Items.AddObject(gameClass.GetGameName, TObject(gameClass)); + finally + cmbGame.Items.EndUpdate; + cmbGame.ItemIndex := 0; + end; +end; + + +procedure TGameForm.btnOKClick(Sender: TObject); +begin + if not Assigned(GameClass) then + begin + MessageBox(Self.Handle, 'Please select the game type', 'Error', MB_OK or MB_ICONERROR); + ActiveControl := cmbGame; + exit; + end; + + if (Length(Location) = 0) or (not DirectoryExists(Location)) then + begin + MessageBox(Self.Handle, 'Please enter a valid location', 'Error', MB_OK or MB_ICONERROR); + ActiveControl := deLocation; + exit; + end; + + ModalResult := mrOk; +end; + + +function TGameForm.GetGameClass: TCustomGameClass; +begin + Result := nil; + if cmbGame.ItemIndex > -1 then + Result := TCustomGameClass(cmbGame.Items.Objects[cmbGame.ItemIndex]); +end; + + +function TGameForm.GetLocation: string; +begin + Result := deLocation.Text; +end; + + +procedure TGameForm.SetGameClass(const Value: TCustomGameClass); +begin + cmbGame.ItemIndex := cmbGame.Items.IndexOfObject(TObject(Value)); +end; + + +procedure TGameForm.SetLocation(const Value: string); +begin + deLocation.Text := Value; +end; + +end. diff --git a/source/view/Forms.Main.dfm b/source/view/Forms.Main.dfm new file mode 100644 index 0000000..c3d4004 --- /dev/null +++ b/source/view/Forms.Main.dfm @@ -0,0 +1,1893 @@ +object MainForm: TMainForm + Left = 0 + Top = 0 + BorderIcons = [biSystemMenu, biMinimize] + BorderStyle = bsSingle + Caption = 'Chivalry Server Launcher' + ClientHeight = 547 + ClientWidth = 739 + Color = clBtnFace + Font.Charset = DEFAULT_CHARSET + Font.Color = clWindowText + Font.Height = -11 + Font.Name = 'Tahoma' + Font.Style = [] + OldCreateOrder = False + Position = poScreenCenter + ShowHint = True + OnCreate = FormCreate + OnDestroy = FormDestroy + PixelsPerInch = 96 + TextHeight = 13 + object grdMenu: TJvGradient + Left = 170 + Top = 75 + Width = 4 + Height = 472 + Align = alLeft + StartColor = clBtnShadow + EndColor = clBtnFace + ExplicitLeft = 244 + ExplicitTop = 67 + end + object shpMenu: TShape + Left = 169 + Top = 75 + Width = 1 + Height = 472 + Align = alLeft + Pen.Color = clWindowFrame + end + object pcMain: TPageControl + Left = 174 + Top = 75 + Width = 565 + Height = 472 + ActivePage = tsAbout + Align = alClient + Style = tsButtons + TabOrder = 2 + object tsNetwork: TTabSheet + Caption = 'Server - Network' + object gbPorts: TGroupBox + AlignWithMargins = True + Left = 8 + Top = 8 + Width = 541 + Height = 101 + Margins.Left = 8 + Margins.Top = 8 + Margins.Right = 8 + Margins.Bottom = 8 + Align = alTop + TabOrder = 0 + object lblServerPort: TLabel + Left = 12 + Top = 15 + Width = 59 + Height = 13 + Caption = 'Server port:' + end + object lblPeerPort: TLabel + Left = 12 + Top = 42 + Width = 49 + Height = 13 + Caption = 'Peer port:' + end + object lblQueryPort: TLabel + Left = 12 + Top = 69 + Width = 88 + Height = 13 + Caption = 'Steam query port:' + end + object seServerPort: TJvSpinEdit + Left = 132 + Top = 12 + Width = 105 + Height = 21 + Hint = 'INI:URL>Port' + ButtonKind = bkClassic + TabOrder = 0 + OnChange = SpinEditChange + end + object sePeerPort: TJvSpinEdit + Left = 132 + Top = 39 + Width = 105 + Height = 21 + Hint = 'INI:URL>PeerPort' + ButtonKind = bkClassic + TabOrder = 1 + OnChange = SpinEditChange + end + object seQueryPort: TJvSpinEdit + Left = 132 + Top = 66 + Width = 105 + Height = 21 + Hint = + 'INI:OnlineSubsystemSteamworks.OnlineSubsystemSteamworks>QueryPor' + + 't' + ButtonKind = bkClassic + TabOrder = 2 + OnChange = SpinEditChange + end + end + end + object tsConfiguration: TTabSheet + Caption = 'Server - Configuration' + ImageIndex = 1 + ExplicitLeft = 6 + object gbServerName: TGroupBox + AlignWithMargins = True + Left = 8 + Top = 8 + Width = 541 + Height = 77 + Margins.Left = 8 + Margins.Top = 8 + Margins.Right = 8 + Margins.Bottom = 8 + Align = alTop + TabOrder = 0 + DesignSize = ( + 541 + 77) + object lblServerName: TLabel + Left = 12 + Top = 15 + Width = 65 + Height = 13 + Caption = 'Server name:' + end + object lblMessageOfTheDay: TLabel + Left = 12 + Top = 42 + Width = 99 + Height = 13 + Caption = 'Message of the day:' + end + object edtServerName: TEdit + Left = 132 + Top = 12 + Width = 401 + Height = 21 + Hint = 'INI:Engine.GameReplicationInfo>ServerName' + Anchors = [akLeft, akTop, akRight] + TabOrder = 0 + OnChange = EditChange + end + object edtMessageOfTheDay: TEdit + Left = 132 + Top = 39 + Width = 401 + Height = 21 + Hint = 'INI:Engine.GameReplicationInfo>MessageOfTheDay' + Anchors = [akLeft, akTop, akRight] + TabOrder = 1 + OnChange = EditChange + end + end + end + object tsMapList: TTabSheet + Caption = 'Game - MapList' + ImageIndex = 2 + object vstMapList: TVirtualStringTree + AlignWithMargins = True + Left = 8 + Top = 8 + Width = 541 + Height = 425 + Margins.Left = 8 + Margins.Top = 8 + Margins.Right = 8 + Margins.Bottom = 8 + Align = alClient + Header.AutoSizeIndex = 0 + Header.Font.Charset = DEFAULT_CHARSET + Header.Font.Color = clWindowText + Header.Font.Height = -11 + Header.Font.Name = 'Tahoma' + Header.Font.Style = [] + Header.Options = [hoColumnResize, hoDrag, hoShowSortGlyphs, hoVisible] + TabOrder = 0 + Columns = < + item + Position = 0 + end> + end + end + object tsGames: TTabSheet + Caption = 'Launcher - Game locations' + ImageIndex = 3 + object VirtualStringTree2: TVirtualStringTree + AlignWithMargins = True + Left = 8 + Top = 30 + Width = 541 + Height = 341 + Margins.Left = 8 + Margins.Top = 0 + Margins.Right = 8 + Margins.Bottom = 8 + Align = alClient + Header.AutoSizeIndex = 0 + Header.Font.Charset = DEFAULT_CHARSET + Header.Font.Color = clWindowText + Header.Font.Height = -11 + Header.Font.Name = 'Tahoma' + Header.Font.Style = [] + Header.Options = [hoColumnResize, hoDrag, hoShowSortGlyphs, hoVisible] + TabOrder = 1 + Columns = < + item + Position = 0 + end> + end + object pnlGamesWarning: TPanel + AlignWithMargins = True + Left = 8 + Top = 379 + Width = 541 + Height = 54 + Margins.Left = 8 + Margins.Top = 0 + Margins.Right = 8 + Margins.Bottom = 8 + Align = alBottom + BevelOuter = bvLowered + ParentBackground = False + TabOrder = 2 + object imgGamesWarning: TImage + Left = 12 + Top = 12 + Width = 32 + Height = 32 + AutoSize = True + Picture.Data = { + 0954506E67496D61676589504E470D0A1A0A0000000D49484452000000200000 + 00200806000000737A7AF4000000097048597300000B1300000B1301009A9C18 + 00000A4F6943435050686F746F73686F70204943432070726F66696C65000078 + DA9D53675453E9163DF7DEF4424B8880944B6F5215082052428B801491262A21 + 09104A8821A1D91551C1114545041BC8A088038E8E808C15512C0C8A0AD807E4 + 21A28E83A3888ACAFBE17BA36BD6BCF7E6CDFEB5D73EE7ACF39DB3CF07C0080C + 9648335135800CA9421E11E083C7C4C6E1E42E40810A2470001008B3642173FD + 230100F87E3C3C2B22C007BE000178D30B0800C04D9BC0301C87FF0FEA42995C + 01808401C07491384B08801400407A8E42A600404601809D98265300A0040060 + CB6362E300502D0060277FE6D300809DF8997B01005B94211501A09100201365 + 884400683B00ACCF568A450058300014664BC43900D82D00304957664800B0B7 + 00C0CE100BB200080C00305188852900047B0060C8232378008499001446F257 + 3CF12BAE10E72A00007899B23CB9243945815B082D710757572E1E28CE49172B + 14366102619A402EC27999193281340FE0F3CC0000A0911511E083F3FD78CE0E + AECECE368EB60E5F2DEABF06FF226262E3FEE5CFAB70400000E1747ED1FE2C2F + B31A803B06806DFEA225EE04685E0BA075F78B66B20F40B500A0E9DA57F370F8 + 7E3C3C45A190B9D9D9E5E4E4D84AC4425B61CA577DFE67C25FC057FD6CF97E3C + FCF7F5E0BEE22481325D814704F8E0C2CCF44CA51CCF92098462DCE68F47FCB7 + 0BFFFC1DD322C44962B9582A14E35112718E449A8CF332A52289429229C525D2 + FF64E2DF2CFB033EDF3500B06A3E017B912DA85D6303F64B27105874C0E2F700 + 00F2BB6FC1D4280803806883E1CF77FFEF3FFD47A02500806649927100005E44 + 242E54CAB33FC708000044A0812AB0411BF4C1182CC0061CC105DCC10BFC6036 + 844224C4C24210420A64801C726029AC82422886CDB01D2A602FD4401D34C051 + 688693700E2EC255B80E3D700FFA61089EC128BC81090441C808136121DA8801 + 628A58238E08179985F821C14804128B2420C9881451224B91354831528A5420 + 55481DF23D720239875C46BA913BC8003282FC86BC47319481B2513DD40CB543 + B9A8371A8446A20BD06474319A8F16A09BD072B41A3D8C36A1E7D0AB680FDA8F + 3E43C730C0E8180733C46C302EC6C342B1382C099363CBB122AC0CABC61AB056 + AC03BB89F563CFB17704128145C0093604774220611E4148584C584ED848A820 + 1C243411DA093709038451C2272293A84BB426BA11F9C4186232318758482C23 + D6128F132F107B8843C437241289433227B9900249B1A454D212D246D26E5223 + E92CA99B34481A2393C9DA646BB20739942C202BC885E49DE4C3E433E41BE421 + F25B0A9D624071A4F853E22852CA6A4A19E510E534E5066598324155A39A52DD + A8A15411358F5A42ADA1B652AF5187A81334759A39CD8316494BA5ADA295D31A + 681768F769AFE874BA11DD951E4E97D057D2CBE947E897E803F4770C0D861583 + C7886728199B18071867197718AF984CA619D38B19C754303731EB98E7990F99 + 6F55582AB62A7C1591CA0A954A9526951B2A2F54A9AAA6AADEAA0B55F355CB54 + 8FA95E537DAE46553353E3A909D496AB55AA9D50EB531B5367A93BA887AA67A8 + 6F543FA47E59FD890659C34CC34F43A451A0B15FE3BCC6200B6319B3782C216B + 0DAB86758135C426B1CDD97C762ABB98FD1DBB8B3DAAA9A13943334A3357B352 + F394663F07E39871F89C744E09E728A797F37E8ADE14EF29E2291BA6344CB931 + 655C6BAA96979658AB48AB51AB47EBBD36AEEDA79DA6BD45BB59FB810E41C74A + 275C2747678FCE059DE753D953DDA70AA7164D3D3AF5AE2EAA6BA51BA1BB4477 + BF6EA7EE989EBE5E809E4C6FA7DE79BDE7FA1C7D2FFD54FD6DFAA7F5470C5806 + B30C2406DB0CCE183CC535716F3C1D2FC7DBF151435DC34043A561956197E184 + 91B9D13CA3D5468D460F8C69C65CE324E36DC66DC6A326062621264B4DEA4DEE + 9A524DB9A629A63B4C3B4CC7CDCCCDA2CDD699359B3D31D732E79BE79BD79BDF + B7605A785A2CB6A8B6B86549B2E45AA659EEB6BC6E855A3959A558555A5DB346 + AD9DAD25D6BBADBBA711A7B94E934EAB9ED667C3B0F1B6C9B6A9B719B0E5D806 + DBAEB66DB67D6167621767B7C5AEC3EE93BD937DBA7D8DFD3D070D87D90EAB1D + 5A1D7E73B472143A563ADE9ACE9CEE3F7DC5F496E92F6758CF10CFD833E3B613 + CB29C4699D539BD347671767B97383F3888B894B82CB2E973E2E9B1BC6DDC8BD + E44A74F5715DE17AD2F59D9BB39BC2EDA8DBAFEE36EE69EE87DC9FCC349F299E + 593373D0C3C843E051E5D13F0B9F95306BDFAC7E4F434F8167B5E7232F632F91 + 57ADD7B0B7A577AAF761EF173EF63E729FE33EE33C37DE32DE595FCC37C0B7C8 + B7CB4FC36F9E5F85DF437F23FF64FF7AFFD100A78025016703898141815B02FB + F87A7C21BF8E3F3ADB65F6B2D9ED418CA0B94115418F82AD82E5C1AD2168C8EC + 90AD21F7E798CE91CE690E85507EE8D6D00761E6618BC37E0C2785878557863F + 8E7088581AD131973577D1DC4373DF44FA449644DE9B67314F39AF2D4A352A3E + AA2E6A3CDA37BA34BA3FC62E6659CCD5589D58496C4B1C392E2AAE366E6CBEDF + FCEDF387E29DE20BE37B17982FC85D7079A1CEC2F485A716A92E122C3A96404C + 884E3894F041102AA8168C25F21377258E0A79C21DC267222FD136D188D8435C + 2A1E4EF2482A4D7A92EC91BC357924C533A52CE5B98427A990BC4C0D4CDD9B3A + 9E169A76206D323D3ABD31839291907142AA214D93B667EA67E66676CBAC6585 + B2FEC56E8BB72F1E9507C96BB390AC05592D0AB642A6E8545A28D72A07B26765 + 5766BFCD89CA3996AB9E2BCDEDCCB3CADB90379CEF9FFFED12C212E192B6A586 + 4B572D1D58E6BDAC6A39B23C7179DB0AE315052B865606AC3CB88AB62A6DD54F + ABED5797AE7EBD267A4D6B815EC1CA82C1B5016BEB0B550AE5857DEBDCD7ED5D + 4F582F59DFB561FA869D1B3E15898AAE14DB1797157FD828DC78E51B876FCABF + 99DC94B4A9ABC4B964CF66D266E9E6DE2D9E5B0E96AA97E6970E6E0DD9DAB40D + DF56B4EDF5F645DB2F97CD28DBBB83B643B9A3BF3CB8BC65A7C9CECD3B3F54A4 + 54F454FA5436EED2DDB561D7F86ED1EE1B7BBCF634ECD5DB5BBCF7FD3EC9BEDB + 5501554DD566D565FB49FBB3F73FAE89AAE9F896FB6D5DAD4E6D71EDC703D203 + FD07230EB6D7B9D4D51DD23D54528FD62BEB470EC71FBEFE9DEF772D0D360D55 + 8D9CC6E223704479E4E9F709DFF71E0D3ADA768C7BACE107D31F761D671D2F6A + 429AF29A469B539AFB5B625BBA4FCC3ED1D6EADE7AFC47DB1F0F9C343C59794A + F354C969DAE982D39367F2CF8C9D959D7D7E2EF9DC60DBA2B67BE763CEDF6A0F + 6FEFBA1074E1D245FF8BE73BBC3BCE5CF2B874F2B2DBE51357B8579AAF3A5F6D + EA74EA3CFE93D34FC7BB9CBB9AAEB95C6BB9EE7ABDB57B66F7E91B9E37CEDDF4 + BD79F116FFD6D59E393DDDBDF37A6FF7C5F7F5DF16DD7E7227FDCECBBBD97727 + EEADBC4FBC5FF440ED41D943DD87D53F5BFEDCD8EFDC7F6AC077A0F3D1DC47F7 + 068583CFFE91F58F0F43058F998FCB860D86EB9E383E3939E23F72FDE9FCA743 + CF64CF269E17FEA2FECBAE17162F7EF8D5EBD7CED198D1A197F29793BF6D7CA5 + FDEAC0EB19AFDBC6C2C61EBEC97833315EF456FBEDC177DC771DEFA3DF0F4FE4 + 7C207F28FF68F9B1F553D0A7FB93199393FF040398F3FC63332DDB0000060849 + 44415478DAC5970B50545518C7FFFB7E820BF8CA1C1F93D6D438038220282388 + 4144A1825A4E2FB3878D6339E994B2888801CB12A6F672B40C1DB51934482127 + B5D024CD6968981018682209C4440910D865DD377DE72E5EDDD8D5DD70A63B73 + E69C7BEE77CFFF77BFEF3CBE2B181C1CC4FF7909FC0558B264C99DB771437595 + AFEF9795958D0C202D2DED5633834AC1505B4B45EFCBFB478F1E1D1900BB162D + 5A74A7F8AD4B5B5E5EEE13C4880052535379F12D59815CDFD6BC7E080402D6CC + ACA8A828F0673CBF0052525278F182FC09080D4BE1FAEB2E9E4456F6350E4228 + 1466919BF3EF3B407272322F5EA823F1994FC2E968A4BB41084533505F771AD9 + 39D720128998C9E6D2D2D2BCFB06909898C88B17154C405844129CF6260CDA9B + 5D8388A7412826888BE7F05EFEDFCC0BCC1B392525255B470C909090C08933F7 + 16E9C7237C56029CB6DF09E00F373BA1F82108258F12C42FC8D7F7709EA07772 + 0F1D3A94FD9F01E2E2E23268104EFC83C2B1088F8C83C3DA4C002D1EED8592A9 + 10491F41435D038AB61B21168B41E3EB8A8B8B37F90D101B1B9B41AE7489EBC7 + 21223A1A4ECB250268E59E3FBFB219E72F185CB67302F0E5BEE95C5B249D0CA1 + EC6134D6B5E2A35D37394F381C8EC23D7BF664F80C3077EE5C2D09EB582C77BC + 3F06E1B323E0B0FC49E5326F93531088B6CB12AE3D79920D39DA7EFE99483A09 + 22F93434D57762F75E1B37275A5A5A36D312CDBB27404C4C8C965ED031F2ED85 + C188981D0687B995C4DBDDECF41F6A50DFC0AD7D4C9D6247DE2683DB73916C22 + 07D158DF8F6D3BBBD0D8D8C8C2B1A1BABABAC82B407474F44612D773E2054198 + 35E731D86F5E2680BF8679E9C8372138526AE5DACB9F5162E953D787D988E413 + 20564CC5CFE76AF0E6FAAE5BDD1B6A6A6A8A86014446466EA449A36713675BBE + 0651B1D36037B5134087C73972ECA4027BF7BBDE7DED65011627DFF46827563C + 00B172222E9CADC59AF5BD3C446D6D6D110F101515359FBEFC0CFB725DB61AF3 + 12A7C036709500AEC3DB557D5189CC1C970774395244859ABCDA8A95E320518D + 47E5F15AACCBE441E31B1A1AAA38008AFB0212AF645F9F9B2947EC82F1B019AF + C266EAF23AA8D1A2C4138B8D5CFBD43135D432EF0012E56848D40CA00E6B332C + 3C40535353151F82F8F8F85C02C8623356B74586881815ACFD1DE4891E8F830A + 8422C42FB4A0AFCF815FAB9418743A3C8BAB82210D1C8B9FCE5CC2CAD5FC44D5 + 363737EBDDE600BB92929272251249160BC5968D2284C700D6BEEBB01A6F781C + 5CFDE0740EC4D0FE9B6771B506B2516370FEFB56AC586DE4C56949F2C7F6B065 + 48279E4E2E976B593832DE166066B40196BE4E580D7D6E76074A8C283F31C0B5 + 43674891FD6E90DB73A97A14649A60FCF85D3B5E7A830F8FB6ADADCD2D67F0B8 + 11A5A7A7172A148A0D2C1CEBD7381116790DE6BE2E0AC9EDCD66D7011B72F5AE + F0CC8B55E0F06781B7C5030220D7685075AA032FACE2279DF6CA952BC31216AF + 5BF1B265CB8AD46AF53B6C2B5EBBCA8AD0C856986F741384CB959F1EA4DD2FDF + 05303F5E8523BBD52EF14035E44181387BA213CFBD6EE6C53B3A3A3C664B773D + 8CE83CC835994C59BDBDBDF87C8715094F87C0DC63A49098200B52411112C0D9 + D94D5618AFF650BC959007ABF1C3B7DD58FEAA9517EFECECF49AAADDF3380E09 + 09E17381C35F889190AA2108132CBD66373BD92839012971FA782F9E7DC5CE8B + 777777DF354FF42921D168343CC457C5622C58A822080B85C4B5A6651A1994A3 + E5385D61C4D295B7C5C973F74C527D4EC90202027888B27D223CBE580973B795 + 1D30508E91A1B2DC84F415FC5EA035180C3E65C87E25A52A958A87F87ABF1089 + 6932AEBFF29805692B9CBCF8C0C080CFE9B9DF6939ED113CC4C18F5D7D2FBEC5 + 3FD69ACD66BFFE0DFC06A05D524085FD09FD3BF5DE44994F0115BF06BC2B80C0 + F5B721A622A59D51CA6AA7D329A17764B449ADA1FB7543A63BA9FF1332B7523F + 5B7F56BBDDCED554EC04CC8B50BF5F00221A504D0304921D5BF42AAA552C12AC + 503B6CC8AE962AB62ECDD466FBAE916A0379A39FC0D8CEE5A47B4E88EEFDF300 + 5D42E6792AC2216F48088A798379423C64C73ECB4683B32FB6B10F655A541C64 + C3EA416F3AFF00DD5D9FDFB6E8655B0000000049454E44AE426082} + end + object lblGamesWarning: TLabel + Left = 60 + Top = 20 + Width = 444 + Height = 13 + Caption = + 'No game locations could be found. Please add the location of the' + + ' dedicated server manually.' + end + end + object tbGames: TToolBar + AlignWithMargins = True + Left = 8 + Top = 8 + Width = 541 + Height = 22 + Margins.Left = 8 + Margins.Top = 8 + Margins.Right = 8 + Margins.Bottom = 0 + AutoSize = True + ButtonWidth = 95 + Images = glToolbar + List = True + ShowCaptions = True + TabOrder = 0 + object tbGameAdd: TToolButton + Left = 0 + Top = 0 + Action = actGameAdd + AutoSize = True + end + object tbGameRemove: TToolButton + Left = 79 + Top = 0 + Action = actGameRemove + AutoSize = True + end + end + end + object tsAbout: TTabSheet + Caption = 'Launcher - About' + ImageIndex = 4 + object lblJCL: TLabel + Left = 12 + Top = 222 + Width = 319 + Height = 13 + Caption = 'Uses JEDI Code Library (JCL) and Visual Component Library (JVCL)' + end + object lblVirtualTreeview: TLabel + Left = 12 + Top = 334 + Width = 179 + Height = 13 + Caption = 'Uses Virtual Treeview by Mike Lischke' + end + object lblChivalry: TLabel + Left = 12 + Top = 16 + Width = 246 + Height = 13 + Caption = 'Chivalry: Medieval Warfare by Torn Banner Studios' + end + object lblPixelophilia: TLabel + Left = 12 + Top = 72 + Width = 293 + Height = 13 + Caption = 'Various icons are part of the Pixelophilia packs by '#214'mer '#199'etin' + end + object lblGentleface: TLabel + Left = 12 + Top = 147 + Width = 217 + Height = 13 + Caption = 'Toolbar icons are part of the Gentleface pack' + end + object lblSuperObject: TLabel + Left = 12 + Top = 278 + Width = 176 + Height = 13 + Caption = 'Uses SuperObject by Henri Gourvest' + end + object llJCL: TLinkLabel + Left = 12 + Top = 241 + Width = 101 + Height = 17 + Caption = 'www.delphi-jedi.org' + TabOrder = 5 + OnLinkClick = llLinkClick + end + object llVirtualTreeview: TLinkLabel + Left = 12 + Top = 353 + Width = 274 + Height = 17 + Caption = + 'www.soft-gems.net/index.php/controls/virtual-treeview' + TabOrder = 6 + OnLinkClick = llLinkClick + end + object llChivalry: TLinkLabel + Left = 12 + Top = 35 + Width = 109 + Height = 17 + Caption = 'www.tornbanner.com' + TabOrder = 0 + OnLinkClick = llLinkClick + end + object llPixelophilia: TLinkLabel + Left = 12 + Top = 91 + Width = 128 + Height = 17 + Caption = + 'omercetin.deviantart.' + + 'com' + TabOrder = 1 + OnLinkClick = llLinkClick + end + object llGentleface: TLinkLabel + Left = 12 + Top = 166 + Width = 172 + Height = 17 + Caption = + 'gentleface.co' + + 'm/free_icon_set.html' + TabOrder = 3 + OnLinkClick = llLinkClick + end + object llPixelophiliaCC: TLinkLabel + Left = 12 + Top = 110 + Width = 303 + Height = 17 + Caption = + 'Crea' + + 'tive Commons Attribution-Noncommercial-No Derivate 3.0' + TabOrder = 2 + OnLinkClick = llLinkClick + end + object llGentlefaceCC: TLinkLabel + Left = 12 + Top = 185 + Width = 242 + Height = 17 + Caption = + 'Creativ' + + 'e Commons Attribution-Noncommercial 3.0' + TabOrder = 4 + OnLinkClick = llLinkClick + end + object llSuperObject: TLinkLabel + Left = 12 + Top = 297 + Width = 157 + Height = 17 + Caption = + 'code.google.com' + + '/p/superobject' + TabOrder = 7 + OnLinkClick = llLinkClick + end + end + end + object mbMenu: TX2MenuBar + Left = 0 + Top = 75 + Width = 169 + Height = 472 + Align = alLeft + Groups = < + item + Caption = 'Server' + Expanded = True + Items = < + item + Caption = 'Network' + Enabled = False + ImageIndex = 0 + end + item + Caption = 'Configuration' + Enabled = False + ImageIndex = 1 + end> + end + item + Caption = 'Game' + Expanded = True + Items = < + item + Caption = 'Map list' + Enabled = False + ImageIndex = 2 + end> + end + item + Caption = 'Launcher' + Expanded = True + Items = < + item + Caption = 'Game locations' + ImageIndex = 3 + end + item + Caption = 'About' + ImageIndex = 4 + end> + end> + Images = glMenu + TabOrder = 1 + OnCollapsing = mbMenuCollapsing + OnSelectedChanged = mbMenuSelectedChanged + Painter = mbpMenuPainter + end + object pnlLogo: TPanel + Left = 0 + Top = 0 + Width = 739 + Height = 75 + Align = alTop + AutoSize = True + BevelOuter = bvNone + Color = 5066061 + ParentBackground = False + TabOrder = 0 + object imgLogo: TImage + Left = 0 + Top = 0 + Width = 739 + Height = 75 + Align = alTop + AutoSize = True + Center = True + Picture.Data = { + 0954506E67496D61676589504E470D0A1A0A0000000D49484452000001330000 + 004B08060000001C5E60460000001974455874536F6674776172650041646F62 + 6520496D616765526561647971C9653C000068324944415478DAEC7D077854D5 + 16EE9ADE67D24380848E34A588A2222A622FA05EFB15C55EC05E1051A40B8814 + 4104A40490DE7B098496909E904248EF756A6626D3DB5BEBCC9CCB184151DF7B + 572FD97CE7CB3073CA2E6BFFEB5F65EFC3F1F97CD05EDA4B7B692FFFF4C26907 + B3F6D25EDACBFF426907B3F6D25EDACBFF446907B3F6D25EDACBFF446907B3F6 + D25EDACBFF446907B3F6D25EDACBFF44B92C9871389CFF76BDFE9FB4150F6EE0 + A0E2C5C3F3DFAE547B692FEDE5EACB6F91AF6B05CCA841123C42F010831FC4CC + 7898F070FFB72BD75EDA4B7BB9BA72AD831935468647173CAE1F31E2F607D5CD + CD4DC525A51BF1FF55E007B4F6D25EDACB3FA05CCB60460D91E2D1158F7B274C + 78E78D6FBF9DDFF7BDF1E3753FAD59FB317E9788473DF84DCEF6D25EDACBDFBC + 5CCB604626651C1EA3DE7BF79D4F162C58D09D5ABB71C34678EBADB797DB9DCE + 65F8DF223C5CFFED8AB697F6D25E7EBF5CAB6026C0231A8F3B1E7BECD18FB76E + DD32C4D26A80D0B01038782001BEF87CF2A9BC0B859FE1EF797838FEDB956D2F + EDA5BDFC7EB916C18C1A108AC7E0EB7AF7FAE0F8F1A38F2895529048B8505355 + 0573672F8113A7CFAEAEA8AA5A88E794E2E1FC6F57B8BDB497F6F2FBE55A0433 + 8A5CF6128A44FF3E7860FF7BB7DE3244ECF3DA81306BDECC25B079DBEEACB2EA + AAD9F8450A1ECDD0EE336B2FEDE51F51AE3530A33CB20E78DCF3F1C79F7C397F + FEBC5ECD8DE51011A982837B8FC0DC39DF6B52B3B3BEF57A7DFBF09C6A3CECFF + ED0AB797F6D25EAEAE5C6B60466918D7F7EEDDFB838C8CCC67BC6E33F0785EA8 + AFAB85B9331779771D3CBCDE6436FF84E7E4833FD7ACBDB497F6F20F29D71298 + F1F088C1E3E11D3BB64FFFD7BF9E8CD2AA2B412211C0CCA97361C78EFDC56535 + D5D3F0F753D06E5EB697F6F28F2BD71298514ED9809B6E1AFA614A4ACAB3067D + 1388455CA8AA2887299366790F9F3CB5D2EE70AC007F3A46BB79D95EDACB3FAC + 5C2B604695A6548C514B977C3FE3EDB7DFECA6D5D48358CC85CDEBB7C292A5AB + 2B2F94964CC7DF8F809F95B5AFB06F2FEDE51F56FEB16026958899BF56DB5591 + 28CA2BEBDDB163CCABF9F9791FF8BC760EF85CD062D0C2A279CB60EF918483B5 + F5F5F3F09C4CBAE57FBB6DEDA5BDB4973F5EFEB160D6AB5B1C74E9DC018E9F4D + BF9AD3E578DCFCCC33CF7CB565CB96BB1A6A8B4022154161FE45F86EDE526FC2 + 99338B5A2D96D5784E31B4EF96D15EDACB3FB2FC63C1AC5B6C47187ED3403870 + FC2CB4985A7FEFF4483CEE5FB468F1ECF7DE1B1FAB6E2A03A9980FFBF61C851F + 97C51B923333BEC6DF77E35117DCD43607B4F98DED1CF6AF177E699E727EE71E + BEC0D1F63AF88D7B5CAEF8DA1C7099F33997F9FE72D7C065AE695BD7AB2D9CCB + DCE372DFB3BF79DBFC7EB96B7FAB6E7FD435C0B98ACFC1F7FD33AE87B66DE15C + E6FBDF1AD7E0BE61E524B81EECB6553CF8E5B8B66D0B7DE709BACFE5EAC9852B + CB3AFB9D37E83E7FBBF28F05B32E9D62E0EEDB6FC25EF6C1FEE349A0D119AE74 + 2A17EBDC05DBF2F4B16347A7DC75E76D520D82D94F3FAD819CDC627039BCD587 + 8E1D7F0FCF4BC6430FFE4125B394D23814E00F1CD0FFDB0A3CDB3934B8649A9A + 0307AD18E0075D4F7F857069AF34B6D0322953E0A0EBDBAE0125019504EE4187 + F80A7570C0A52D8BAC81E7509DE581BF7CF8B5D0D375B6C0E109BA4608BF9E64 + 24B896A0F6D9E1B7273627701F79E01004FAC411788E2470F0026D66EF6B0BDC + 571C74AD107E3999D97AB17DC9B6DF1A54B7DF63D6DCC033246DC6869DCC6C1B + DC81765B02F7FFA32B41786D64400CBF040C5E606CD8F604837DB0F27007DA68 + 0F1CB6A0768A02F70F09F4172FA8FDC16348E7B7E06108F4132B6BDCA0B15205 + EA2908EA5BB69E5CB8B435963170AFDF9383FFEFE51F0D66236FBB11647229D4 + 353443625206982D977577F1795C6E1F0E97FB7A4E76D67B313161F0E5E4CFE1 + 0C9AA752B1C4D6D0D4FC734363F31A3CAF11FC034683A9C4A36B74870E378487 + 8575E4727928883EAED7EB653A8CFA00EF077CBE00CC269353ABD568CC66733A + FE9683D769F0900A85C2FE0A85E266FCDB45201028783C9EC0E3F1F8A8E067FA + 6375B95C658D8D8D47F173055ED3965ED264EBD8A143873BB95C6E7F87C3A9F4 + F9BCD8141E8D8B8FE488C7E3E360F84C5872EC763BAD58206689E7707B2B95AA + DB385C4E270E731F0E5720140811D5451C0E97E7743ADD784E8BD96C2AC3CF8D + 919191DDDC6E7724364C85E708F0371F1E3CAC2F1FDBEA727B3C6ABD4E978AED + 279FA21A7E7B62B3EB5EFB4646460DC7B62A5B0C8626BBC35E8BDFC943C342BB + 0AF882306C023DA715EF59A9D56ACFE0FFCBC03F793A49A5D2113299AC3FF68F + 10EBE57560C1CF1EB158CCA5EEC37EE78BC522AED56A75637B8C5EAFA714DB9F + 81D7D65EA61FDB1602950E383683F19A6ED8BE30B15822C17AF23D1E370E2B97 + CB8C2F876BE3F1B88D3A9D2E19EB48116E5216573B79B901198AC3B11FA6542A + FBE1FD9478673E8D1CFEE5E2E344AA1095F0BADED7856465659A232222842A55 + 88009FE5763AED5E9A7EF8D98363EBD068B47A8BC5A2B7DB6D245BB4930B2574 + 6BF110454747DF141B1B7B93542AEBE8743AB0193CC031F5F0B160B7F1B02FB1 + 0A025B6E6E6EB65EAF3F0A7E570A81913B20631DB0BDFDC3C2C286F6E8D9B327 + 7EA6EB7C5E14361C7F0E8E155F22164BA9BF9B9B9AAA8A4B4A0EE0F779572107 + FFDFCB3F1ECC442221B8DC6EA8AA6B8233A9D980C2DFF654D23C7DC2C3C33F2A + 2EBAF8D2DEBD3B60C1770BB01DBCFAB2F2AA6D7687E32CF8B56F54A74E9D7A19 + 5B5AA0D562714F9830E1D1B75E7FF5461FC7CB45B94029F68144CC4364E4E1B5 + 3EE0F2F8201088B00379505C5C09EF8F9F909653903F19FB8C126E15C3860D7B + 7FCF9E3DE309045190FDFD86FD4975A57EA57BC6C7C71B274F9EFC1A0AED49BC + 4607BF647CA429076FDAB469E5A8BB47F6526B9AF1470E3E538020C605A7CB85 + A8C5039CE4B072D972F5F2D5ABDF46213E8DD788B0AD8F200B5D2C1470C52E97 + 1B270FEF3FD791B2773A6D505BD308CB96AD284B4D4F4FCCCACC7CD9E174086C + 361B532FB148CCB4B7B5B5950013BFE3C28C19D313376FDE3615FC09C52DBF31 + 34C412063EF9E453EFCF9D33EB71AD560D4B162DB16DDEBEFDDC4B2FBFD8FDCB + 2FBEECA6D36A412A9331CD5DBAF87BF38A55AB5EC53EA02D97E8CBBBE6CE9D3B + E3C517C7C6959797313744D0F1E104F3868686D1587010D4800EAA6F4579052C + 5DB8B0393129E90BECD713E007F4DF6267D4AF03172E5CB874D8CD837BDBED0E + BE2A24942710A21C399C407FF97C1ECA9504B66DDAE2FB7AFAB48FB1AFB7C01F + CB3D2499EB8CF2F4F89AB56B3FEFDE2D2EA2B1A116EF2D61FA538863818A0664 + 5219CAAB03D46A0D74E9D20D65C40BC6162D381C36401041191380CD6A8116A3 + 09C7DBE72BAFA8696D6E6ED6EFDBB7AFB0A0A0E0303E43FFEDB7F327BEF4E2BF + AF2F2B2B0111F68950C80737CA04C91BC98640C067C6B4A6B6D1FDD24BAFFEA0 + D1A837E07525E0679B5178DCF8F1279F4C1CF7D28BC35D2E1BC138CA071241BC + D6ED7481482A05854A49000C0BE72F869367CE9EB85852F209FC0D5398FE27C0 + CC62B383CDEE84CA9A3A282EAF068BD5167C2A0956FFDEBD7B7F929A72F6F977 + DE7E0BCE9C49CE6F6CD6ECC0F65DC4DFC4DDBA75BB6DEAD4A90FDC7EFBF0AEB3 + A74D771D4E48284C387468A0DB6E01B7C00796560BE06487F0509AA75E14101E + 769C070593030A850432D28B61CD8AF58EE3C9673FC14977104F0A1D3A74E817 + 191919FFAAAD2E81E6E646403AE1472A1F3060881A17267D3E4D7F2E2DFD73FC + FA00F899A11F6DFC25028F51CB97AF5830E6D1BB3B16159EC7C92026C680CF54 + A2B00B99CF269315562E5F638EDFB4F12304727AB64CA552BD80DAFE4BAED7C8 + 33184C3861BC606EB5320249253A2A144E9C3809FBF626EA13CF9E4E44D01D39 + 64C8F5E1C545458CE0FB99895F38A4523128E472D8BFFFB0E993CFBE988197EF + 05FFC69597DB1A894C126223CFA4A7A54F45E2212A2ACC836D5BF7C1B11389E6 + 2FBE9AA27862CCC350555988F795C2DAB53B60FFBEFDE7CBABABBF00FF0E2571 + 3D7AF4F8303D3DFD29BDAE0E34EA46466130608C2083ECD4FF1004650BB6272C + 2C046A6A6A60C59255703A2565ABC168FC1E7F3E0FBF1D91A67EBD7BF1E2C5F3 + 9F7AE2DE588DBA01042229D347C4B4911821500AC1A0D7C3E71F4F87336969B3 + 51011173AF84AB0733623CFDDF7EE79D598B172DB8AFA82095A93B4F20615495 + DBE366FA18419A011CEA5F8FD7C32862A46CCCD8BADC2EBFB0E0980985024671 + F10542E8DCB90B185AAC3063FAF4AAB56BD72674E9D23526E1D8D187D40D655C + C07B705084E8320FDED783D5A57F84EC9D3B7785E52BD7352E59B29412C389A1 + 91F2EC8EACFCD523C78E4D70D655716C7548F81C2EF0E1B55E8B0538688908BA + C442CC2D03217EED66387AF414D43634EE53EB745F811F10DBC1ECFF46690B66 + 668B0D105B406B6881A4F4F32894FFA93B8159F75B6EBDE593F8553FBEFAD0C3 + 634E5554D5D08424F0881B3D7ACC7D2B57AEB84B24E4F08B8A0AA1A4A8CCB77A + 757CDDFC59B33A0AF85C9EC16E62D8944CAE40017107845DCA00122A3D502A45 + B077CF31389590EC3D99726E96C56ADD84F7550E1A3468625A5AEA1375D51701 + B521DE83349E0B643229321F0E4E46334CFEE21BD3A9E47393F1FC5D7834B469 + 22052D1E42CD3B77CC2323A32B2A2EE26493A2D0FB2024240244F870B15800CD + 4D06983D6BAEE6E8C94412B0FD78A842C3C25ECF484FFBC06953735A5ACC60B1 + B8C0C5D41D8513274658A8144E21989D484CD31D3971FCC09D77DED9E7C4F1A3 + C372CFA7811DD98E0BA5DFEDF660FB3820974B703EF160CFAE4370E0C8D19359 + D939F3F119A9E0F7BFB41510F2BB0DBCE38E3B261D3A74F0D10B7929D0D0D008 + 73E77E0F4E9CC06BE3D783D76901A7A3050A2E14C1B21FD643754DF516ADC1B0 + 14FCCCE7CE653FFE38F3B5575EEA90927C1C1500311801D6C9C1000D1741CC68 + 3463DD10D47C1C080F5720B08B60D5F24D70FAD4D9DAFC92E229F0FBB9824CBF + 2E5CB878168259A7EAAA12E0F064C8F21CC86C2488072E080D9181BAA91666CD + 58826096311F4166255E530E570F66E483BAE99D77DE99367FFEBC11E7334F00 + 978FD62D47844AD1C5B032623D046068FD935317D0C445591683CBE9F483AAC7 + 834C1195B4C908121C33218219789039E29FF04E9DA1EBC0E1F0F1C79FA8172D + 5A98F2FA1B6F5D3FFBABCFBA171DD98D60847286C0D98A6C0E843C10A3BCF1C3 + C220E2FAFE50DB6880679E7AE600CAE81CF09BAAFDC7BFF7FE9C4F5F1C3BE8E2 + D68D20B43BC0D56204072A5A3B2A70794404F47E731C6C484C84EDDBF621436C + A96C6C56533E26B1E826F09BAA7F9B60C0FF1498795120D0D6879C8212309B5B + 591F1AF970C26F1C32E485FEFDFB5EBF7EC3C6EDF4659F3E7D862F59B264DCDD + 23EFEAD0D4580DE5E545D0AC364064543432290D748FEE84BDE3018B9726B717 + 012404F82884A4310918C8048B8A0C87E84839A4A5E7C1FAD5DB7D09674FCF41 + 139568BCA47FFFFE1F223B7AA1AAE20282991EEBE8372F954A056095418FAC63 + CA97738CA93939C44A2892DAD8A689CCA49B37EFDB39A31FBEAB434545290211 + 99253ED4F0C89664629C7472A828AB85A5DFFFA03F7232F14B042B0269556464 + D49B191969EF9B0DF5A0C7C9EF70F870B2F8FD7D3E04639AAC674E9E84D4B402 + ED9E83FBD7E098CAD3D2D25EED121B2E2A28C8C7E7C8F11A3732201F9A42121C + 730F2CF97E054447443BB6EDDDB3A0A6BA361EFC4CA52D3B23B3E59E4F3EF974 + FAA4891FF7C8C949212B1B162D594913C1B3EAA795BCBAEA32502A04F0C38F3F + 436E76AE39AFB0700E8E1981B0AC7BF7EE6F676767BFA8D7D642535323326C07 + B2176409385D08D85C2E27335189CD105B5128C4101E2683C4E3C97074FF515F + F6C5C21F8D26D372F0FB85AEE4CFA17E7D70F1E225739EFAD7FD311538EE0E97 + 10158D07958304FBC805528900158E00BEFA62261C4C48988FFDFA47C18C9CF2 + C35E7DF5B5AF972E59747B566A022A2F64614EB2DE3C20918881470CCD6E03A9 + 420112850CB8E48BC5C38B60666D52835DA763FEEF4299E621E84950FE481149 + 540A50862BC18B40E31184C39D77DC714C8D76EAA64D5B1EBB215424B3E99AC1 + DB6201A471E0460B854C46794418C862A3A116A7C34793A796175C28206BA008 + 07F6E615CB57CC1D25124454A69C01372A885604333D2A1A91460783667C0547 + 5BF4F0D38AB534F1DD1595954BB02F7E06BF89E9842B4747FF2BE51F0B665D3B + 7784BB870F65C0AC1507CD8466870F07DD851AADACA296F9FD7C61314539C9F4 + 9162BD43B13D6CA4AD2FD2ED9913268CBFFED0815D38D1ED2095C9C1882C462C + 9183DE6080FEBDAE43E0308350226412739BD55AC8C93E0F393979D0D8A425BF + 1A0CBD7110BCF6EA0B085606D8BD652F20A0CCD2B7B4904922EFD4A9D33BF9F9 + F96FAA9B2A99F39BD53A14621982A08931F3CCFA0698337BA93E2D37EF4BF09B + 6E6D991999430FCC9C396BDEE363EE8E29292E0489348C6178F42F3232144141 + 0AA5C595B075F356CBEE4387BEB25AAD04D4F2F08888D7D3CE257F646D6D82EA + BA2634D5644853B8080CC45E7DF8FC10387EE4189CCF2BD5EFD8BB671EF68B7E + ECD817274C9AF4C90D7A6D232A041EB4A05093BF45A55232A69C582C82BCCC5C + 389B927A2E21F1246D2B9E0BFEC81A5B2832D70B4DCC970E1ED8FF718852C4D7 + A1A9462CC3873F1110898422AA05343636C2968D7BC16AB5549C484AA2F617E0 + 31E4BBEF164C9D30E1CDAE057959603459F0772B021907D9AC1C8438CE061C17 + 02B3E0404C54A4124D6D33AC5CBA1A6AEAEBB2F22E5E9C8AF73A07FEC8F4E54A + 381EF72F5CB478F6BF9F1DDDA5B8A800B47A6C0687CFF8F1383837157211D850 + 594DFFFA1B48CEC858E0F23333DADBEE8F30B3612FBFFCCAD72B572C1B71FED8 + 4E7034E91957080759AE48A9A2300D78B93E50C5C54255631394979521382B18 + DFA6028FCE4A19636EFA90595950796AD0E268C5FE20D78217199ADDD60A911D + 7AC0E225CB12CF9E3DB3A567AF5EF77C3169D2D3470EEC04099F0FE168BAB6E2 + 9C68D4B7804A26013BCAABD1E674694DADE6C2E2E2A50EA733176F36E2E1071E + 1867D7A839E6162389957460AF5EFC41E1911083AC5F33E03A58F3F356C69758 + 5A5179CADCDA4A89E5E9417DFB3F13CD6443CA6CE89F0D23FF7F493A8D898A80 + 3B860D66261939C31D38E06422D9F17349590DF4EA168B34DECBC9CC2D24300A + 7E8D5C181EF7CF9D3B77FAC71F4DE8B271E3CF101A1ACAFCE074B818332E322A + 0ABAC645A360019C3A9D013F2EFF09D99A164D11C64560477666E471B9C4D0F8 + 62B1389CEA10A652951516154D450A7F1CCF898C8E8E7EABA0E0C278ADBA0AAA + 6AEA101C2C8C89A4D56A60D4DD23A0B1A614167CFBA321292B9B26F3E5981939 + E8EE9C3E6DFAB2679F1EDDB1B8E83CB213399A44FE950F2A34FF424214D0D8A0 + 83B56BD65A76EEDFFFB5CD66DB863F892412C98BE7CE9D9B18A1120873F32F00 + 5FA8003B0A24B13202B3C808251464E7C3911367743BF7ED23B3E1825C2E7F64 + EAD469AF3FFED803B29AAA4A30E2449088258CEFACA1510D8307F581ECF41CF8 + ECF329991ABD9EAEA1C0497020806123A3468DFA7CF3A6F5A372CFA7232BF0FA + A3BE3C1EE30FF22108452008EFD8B61F81310B9AF4FAC4DC0B1768EF38475454 + D4D8FCFC82370CDA6A50A3596EB379C1E3A360859B31E7AB2BAB1846D629AE0B + B85D7E30138944401B6B8AC57C885FB509AA2B2AACA75253E7E279D40FC4A42E + E7D7A3F1BF77F6EC6F66BF38F689EE15A545A0D39919E7BC582201119AD61231 + 9AB3AD3698336B119C4A4E5A8A60465BA897FC01D9A640C6E0679E7DF6EBB5AB + 57DD7364EF26FF9B731060489F1A8D2DC0436027D55A57DF0C5B36ED04BD4EEF + 42E5E1A668AD542E13F6BAAE3B32630138D0F4D36AB464AE5B8C4653ABDBE371 + 50C4D36AB5B5F0F8BC3AECDF33682510788784A854F761DB8762AF77467395E7 + 4639E5F2781E89488C4605D78BCCCE269149B9F57575D4379EDB6EB975608F98 + 98A88E9D3B73A552A9501116268D50A97802BD0EE26EEC0F6BB66E875327CF51 + FA93A5ACB2924C5362D0F58179FE7B798A6CF1C2AFF3E4DAE6CEFD5F297F05CC + 28C785508068BB3C2038948342B9288EC0FF3D70C9AEBE9A8A07E7115D29B1F0 + 3F1D42A606F91B28D5412414E28475F8C8BF456620FEC6898A08058DB6C58B5A + 887D2E999CDDF078F2CBC9933FF8E0BDF11167924E33660C0A09732F299A55DD + BAC6A07616C3B9E43C9836F31B64564DD52824793821ABF168F2783CACBF4885 + 13EA06A150D8C96C3613FD3E037E864591AC779199BDDDD4500E8585458C9949 + 7EBC2E5DE200AB064DB565B064D12AEBE9F48C6FF1FC9D78D404F515FBD6A801 + FDFBF6FB6CCC830FDE3768687FAE08B5258FAF4040E3810C3F8785A940A36E81 + B5AB10CC0EEC9F86604651374AA77806B5F5E4CE3172797E41314E1A4920C285 + B494CFC5EBC4909B950B878F26E9F71E3A383350EFDECF3DF7DC94D5AB57F649 + 493EC9045128A2E746B34888601D192E83B4E474F879F3EEDA94F4F479D80FB4 + E75B5DA0BE345E1DF118B36AD5EA694F3EF1707876560ADEC3F39FA1231F2381 + 6F25B2E60D6B369012B21C39756AAED3E924F0EFF6D96713BF9A3B77769F3327 + 0FA072E2208BF1A0A5C40529B6B31C0167E5B278EC1C8EF69D77C72BD14C1352 + A0821EAC54C8D12404EC070D9C399102C9696967CEE7E71383A009DE72199923 + 301B3575DAF4D9E39E7EA8A7B6AE025CC8CA3868BADB5099396C4EE888CCD568 + B3C2F4698BE0744AF272AC23F9F48AE0EAC18C344EF7C183074F1EFDE8E8E74F + 9E4C647C9C541C4E87D760D0BBA5529950264565D4D860AEADAF4FB2D9ED8508 + 52462E972B1209849D4255AABE664BABC3E170B6FAC06744856D0CF4B528707F + 7B4066285DA63430EF2825E63644B5075F7BE5D5C1E49FF5E8F49CE8A8489142 + 2E1329D18C09EFDA5578F0CC59AB42AE108CBEFB2EA145D38820AB0445781413 + 6CA8ADAFC3FEB78112FB60F1F72B202535DB515B57B717E707050D34416D6C3B + 9FD939CBE6A7B1E7B8820E4FE060F30EED4158117CFC295FDC9F053332DD08C4 + 068C1B37EE251CB45E9B366D2E2F28C8AFB0582CD4C11429A17C1F725AD982FE + B295672BCB260E12C80803872070F003079BB4C7B2BFB64730CA070B1B9BECD9 + 1A78365D4FA6DBB09E3D7B8EDBB17DFB3D61A14A6141411EE36F13A2A6F4A029 + 44CEF1F070159C3A91062B56FE642BADAA3A82E0484E65F2C36803F764FD3104 + 3892C06773E0777A568FAE5DBB4E40309BE07458A0F0421E93CAA15285414D6D + 2D8EB4072C460DACF821DE959074EE203681522ACA02F770C3A50457F241DD71 + CF5D239F7AE4A1FBA37AF5E9CE30471BF660449802C2C394A8B54DB07EED3A04 + B303D3B0EF09CC7808AECF6667A54F7139B4929A3A2D82828C712813A08421A0 + B8EC5658B4E847E810D3C9BD71EBD6F926B399AE930F1E32E493E4E4A4C77232 + CFA0E966C43A4B98F400A454A0528A2035E91C9CCFBE0859F9F9DB72F30B4853 + 1706C69326589FCE9D3BBF9F9B9BFBB241570715E5E540C147AAAF17CD7F32DD + C8C4DABA713B7050E11C4F4A3A5E515DBD18AFD38785853D999995F59E4CC2E5 + E5E666A2992B6414121F7B809E7B263115366CD8E2B8505A92FCF8E38FC7BCF6 + EAB8BE5AAD163BC88726191F01DA071DE3229069A6416A72B6EBE8E95373D144 + 25DFE5E5FC7AA480EF9E3F7FFE9C0746DED6B3AAF22214975543696925A8D528 + B65C3E74EAD419BAC47680C413A7E16452F2F70834CB038071B5EF5125B98D40 + 93F0262E97733BB2DEAE6121215DEC76BB496730D4BA5D6E332A4101628B004D + B752548E14816D08CC13BA960097944327F09BC54C726C870E1D625E7EF9E5EB + A3A222890573A32223B9EFBEF77EBC5EAF5F0BFE08B314EFFBF0C18387160EE8 + D323ACA2200BBC4D6A70A3794BA93608CAC0158B41D9A32770C452B0EA3560B5 + DB709CDCFF99DB1CECCFA88E9170F8E011D8BF2F018ACB2B4E596DB6D33D7AF6 + EC72FF7DF70F4274E5A322F3202BA45BFAB0EE1E7C268FF2D390257250CEBCF8 + D9C7473A8E80CD351A8D96D2D2122D2A1F2FFEEE75D8ED4EB3B9D5A2D120BFD7 + EB0D167AF9865FE9B009E4C6C0D1DA062F3CF03B64E8CF821945ADFA0E1B36EC + CD13278EBF4E93C46241FBBC51EDC6C9A0ADACAC6C696C6C32555555B6343737 + 6B50F034488535C86E28D14E1F18342F5CCAB45762635578C891EE2AD1EC93A3 + 86A24455496868980C4D39A2CC9C1683812391CA9064B82C783F07254D221BF1 + F2688745F0396D561B2A3097572010F85093D851D134B93DDE5CEC6FD2AA1CA5 + 52396C229677DE197F0B6A2FEEF16307A159AD4636A6C0017542089A2C22910F + 0EEC3906470E1F7794D6546DC34945D1C90B018076B6E9541EFC32439A15F69E + E43BCACACAFA7840FFFE62B5BA1EAAAA6AA0AEAE9E31B9EC0E1B48247C38BCEB + 80D7EE86D66EBD7B21B1331BF2F2F2B4C71212EADE7AEBEDB8E8E848C9CF1B37 + E9CACBCA1C9F7DF6C96D4FFE6B74A44EA7058A4EF27862C6891F81A0AB6936C2 + BA35F1965D870EFE879921303F9B99918A60D622AE6F5003E5FCB6E2F8D035E1 + 212A06CCB66EDB03069D114AABABF69E4B4DA5E55C761CDB47535353A7F6EC11 + 2BCB484F41B64A010F1F03BE4A8518D9850F8E1E3A05ABE337A7D637375188FF + 5C0080C9241EFEFAEB6F4C5BB972C590EC8C44344DB5E0F67291613940261531 + 7D5B565A0D9BD76D82B8B8CECE0D3B76923948A924D1D8DECF97FDF0FDAD2927 + F78219CD7127760AE51728C26410D2A1334CFF720E1C4E3C9E84CCFBF48D37DE + 38F49BD9D3EF6F353443A40401928201C840B8220EE8D0345EB1621B9457551D + 47F395D24872E0D79B6C529ED9D00F3FFCF0479BC9D82B2B238BF17FA239E633 + B69A1B4DAD965A4A1C8E8E88088B898E8A4DCFC9998A93795D006CAE9699914C + C803CA880089F6D1A3245A4E005CD94C7E6340AE34817AD2FD850120BBFE8E3B + EE7CE285179EBF49AB6EE2DD78D3CDAADEBD7ACB7C6E238F523004223E545454 + C3DBE33F4F292C2AFA34D0564A44BE7BF1F74B168F7BE1E9D8FCA4BDA84CF860 + 4693DDC713E2655E06AC98F40F1132510432B7C707780DD3DFC476232243A0E0 + 7C0EAC59B305CA2AAA2EAA75BA83F87BC4D123479EBBFBEE3B445A4D13932A43 + CA9FFC77D422968A31694794CC4D51684E80A4E197E4E220654EFF75386D8880 + 5EA6CFCD668BCBD062B4D7D4D499EA1B1A8C75B5B5FA949494CAA2A28B6508FC + C4FA59BC3005C0CD12E83716E07E01507F16CC6890EE8E8F8FFFE6BEFB46753D + 72640FF048A3758E4313AD17844744825CA1040F6A60140430194D3E0423C7F4 + 69534D4D4D4D3A9FD76354ABD51EBE40287DE4E187540A9944896C42525D53C7 + 7FE595978536AB99535D550DD5B5F5F0F0C30F83073B20253D1328D9F2E5D75E + 075D5303185A5AE0F4D973D0B75F5F10A3B979B1A8186AEBEA7D0F3CF020D4D6 + 5483BAB9D11B1B17EB7EE3ED77D7B7B65A289DC0DBAD5BB7672F165E9C2142BB + E45CD249A8AAAE008F87E7EF11641F1D63C29191B4C09C19DF79F38B4B8E05F6 + 37A3CC7AED65043938C1B5EDF7DDF178213323E3B30ED10A697EFE45D019CC20 + E0F31907AFC3E15F8D6232E8B06D1E1834F446080D55625F59E058C219E76DB7 + DD228C0893425272067C3D7D5EDDD01B6F144CFAFC9368BD5E0B3ABD91AA0A51 + 912A50213899F476D8B8619375F7A183D311DC3713988944E2E7B232D3BFB25B + 3422B5D60046B3139FCD639CE53C4610F96832A6C0A993A9BE94ECACB528488B + C01F6A1F3476ECD829B367CDBCBD203F8331BDED0E1F591F780D1799A018AACB + EBE08765EB1A523233A7A092D81FE81B7A89F293DBB66DFFEAB1D1F72BB2528F + 03EA5C64645CB09ACCA0544A40A294C3B225F160D419C0ECB0E7A764654D43F9 + AA4679BAFBC891A39F0FEDDF25B4BEBC00DC4E1EC3E07838462285008E2566C1 + B773E6AB6B9A9B680CF3860CB9F1E1C58B16BC7BECC00E68D1EB193542005F5B + DBC4B4CB81E6695454947EDFB163AF218B3813008BE0424CBA2BB29C1791250C + 469641AB0B2C2EBFFBA03A703E1334429994A2E6CCF6FA13A1F570F5A60F29E9 + 30BCBE2F02C400341563424242A2060E1C18456CACB2B2C2A4D1E8D466B3A9C2 + E3F5947ADC9E86C0042500248BE7BA679F7D6ECCA2050BEE30E91B9041350247 + 2400278E878722A0626CA7D7018B976CC2FE493EA3D66828BD272BF0ECEB2323 + 23DF9E3973D6B86EB13234212538FE8802563B82109F19530218F2F95A28A080 + 17C8A46226D8131AA28486FA1AF871F93AA8A8ACB6A2F9BB16C748FBC1FBEFBD + B470D1775D4B0AD31188AC0C98514087480C4D0166BC10C03C6E17DEDA8BCCDA + 0B22A18449A1A17399C2E531E0E746D2E0F6B8E82AFC4D885F0B914C2899009C + 58AC408075E158D6DB2B9010E19C56676664D6161515D52241AAF178DCB4C283 + 7C76CD81F1F8C512B63F0366D4FEAE1289E4F9A4A4B3530C86266156460A7098 + 067A202454050A45086A72257690D01F86E67AA063A79E307BF61C183AF80668 + 6E6E82FA8626E8D6BD3B74EC108D93C507172E1442A7D86E101B13CE74505A1A + 9A1B5C01BCF1CA58686EAC8783C71261D0A041D0A7770F342592A0B2A601F20B + 8BE1CBC993A0B9A10EF6EC3B003D7BF7869B6FBA09F6ECDE05036F1C0631682E + 3CF1F863FB91F9925FC88A02F5CCB66D5BBF88EDDC919B919A0412193232970F + 278381520D61D0C0EB40A3D5C3F4AFE7F8720B0B97A3A093797111FED8BB33A9 + 7F7A20F51E979797FBA9CBAE139657D681D16865728A28BC4ECEF056B319CDBC + 2826978B0409B19E49C415A0C66B41901308B81083ACA4BE5107274F9DF35D77 + 5D4F4E5C6C2C0366C422892991235FAF6985DD3BF6D8F7251C9D854A83FC763C + 8944FA7C5656C6E45663BD881CCC4E1797C96D92CBC46892A11911190A7BF7EC + 81F4B402F7F133A717A0168C07BF49168BF57EEE9B6FE67C3A66F47DF2E28BE7 + 996B1D76CA6FE2804ACE67CCC61F96AEB721587C83F2B131008203BA77EFFE5E + 4141C1BF2DFA4A282B2B466516015A543A1C046E3E4E96FC926AD8B261274446 + 453AF61F3FBE10818622AFBE71E3C67DF9EDBCB94FA49C39CC24F65EC82F0693 + D9CA4C16328DCDA656387EEAD4516D4B0B8D6123B2F47EF7DE7BEFFB6643CBED + 468381AF92CB698993C760341AAC0E7B2B325F4B884A65B85856B6D06832D18A + 80B66FA517C225C64420AC0C282567D038B3EB2809A809E06812B5FC0130635E + 2EFDE0830F7DF0C30F4BFE5D5C74812393C8443131515CCAEED7E9F48084C8A7 + D5E8CDDF7FBFB42CE9DCB99F5E7BEDD55B542A556C45458568E0C0419D9F7DE6 + C92E1459B6DB8C4C60CB8D4F26251CAA528042E681DD7B8EC3AA357B3C35F575 + DFA23C91495D1A98D4F48E8B1172B962E2EE5D3B06478671A0BAA6092B2E4210 + 016243E463665818D3C75E2F48C402E810158A726987A54B56426E5E91A5AEB1 + 7133DEF7C40DD70FB87FFDBAD5E38E1C4D80469C67528984495A260B43241632 + E9504854187F30458229399C94B5CFC765D2A3102790E444D39A4226A01411E1 + 9FDF44EA940A192A6415D810684DADA4EC45CCEC9149E5A8004310E014783F21 + CA20105E58CBCB2BB5A9A96955FBF6EFCBAEAFABCB0CCCCDFAC0D838FE0C98D1 + 20F78A8B8B7BF3C4F1840FB332CF2223AA6612FE2814AC54A918F6812634D811 + F929B193EEC313C8E1E8E1A3201192935D06452515F0C8230F42330ABCD16882 + DAFA2678EAC97F4151412E0C193400F61F3D090F3EF0005CC8CB013EDECF64B1 + C3934F3C0EE545F90C101E4A380583870C8691238643F2B914A8A96F843B86DF + 069515E5505A5E01639E7C9679EE84F1E38FA0ED390BEB6C4013F6C9F8B56B26 + F7ECD94D50565C083CD41E3A34B5EAEA6BC9D38E03AA4046A787295366BB0A4B + 4AC8314FBE8872F8631117A67FD03C7EBBA020EF7D9DBA0A8A8ACB9901A17E21 + 21A2C449399A46C044EBECCCF219267112C1CCE9A0AC7034CDE4325A3BEA5F39 + 807DA9371889C033034FDA9572A13A44874043AD1AF6ED39683F7AFAF43C34C3 + D7530550809ECBCECAFCCA626E1056236321DF95D7C7C10145D6121E02E1E162 + D8B3EB20945CAC85A3A74FCE47964BA907B43E944929B879D8B089A74E1CBB3B + 3361177898FC282F7085A45939BE8E3DE33829E74BBCEF7D34E9A756AB95A27C + C42A868C1F3F7ED613631E1EBA79D37A64985E888C8CC2496805232A0A1BCA01 + 25E1CAB13D17CBCB73F30A0B29829B4D93FE817BEF9D87BA7B14B22C219FC7F7 + 5A6C36835AAB35E324B3E1F8A14DCD6DC6FF1F44F6442C8B343131973ED89783 + 905D84904B011995052D00D2D4A4A5C985419ABB2E48D083593531B34E380E43 + B13D03D0848AE9D5AB57784868A81099B340151222EFD2A58B94E3F372359A66 + EBDEBD0796A349444B873470F5662601E4E0471F7DF4CB7DFBF6DC9399720CAC + 565AA56267B2F891B1E11809213F2F17A64E5FD2525357BB66F1E245F7BFF8EF + 27FAD7922B02594E232A705AAEE5448260B1D898D51BE1C8DEA5622F2427A7C1 + CEDD89505C5A9E6C6E35936C670680975DA8DF158F31F3E72FF8ECA5179F0DCB + 4C4B04979B0756BB7F250883B65229E3CB7423A04546A8903159213EFE67A8AF + 53C385E2921DD89F244B4D77DE71FB58B1487C5B56CE7909B12CB94C26C63E17 + 220CF82C168B17EB88562B4F84E28B5D2AF09118134A2050F2F01C2E9F7C6B38 + 27B0CD02F213CA64521EB2602EE5F485205B1FD0BF178C18710B5A2661686D19 + B19F6CCC5CA035D7641110D1910456A18484863309E316AB0B124E9CAA58B66C + F981CCCC4CB24628D26CF0FD069AFD1698F58C8989796DDFDE5D9FE49E4FE150 + 3E11B130427C0A3D53889BB2E4A51229CE5727E4175C4436668494D4140855CA + 402C12810A2B36A0DF75604273B149DD0CDD7B20AB1A3C00B5480D9E8B6CC227 + 809B065F8F0C2D050A8B4AE1F63B4642389A2BD55515D0D0A4818B25E5F0C233 + 8FA1E636C3A9E474E8DCB933484504A036A8536BE1DF2FBD82C292074BBEFFFE + 080A110DB84624143EB666CD9A6903070E10155FCC63C2EF8D0D6AE88D8C8ED6 + 1F2AE51CD0695AE0ABAFE7BA8ACB4ABFC36BD6C01F4B9664C1AC4F4C4CC777F3 + F2CEBF5559761E2AAB1A50184568D2A2F078BCCCE0509A01051C544A0AD7D3FA + 491FB33C8ACC40A2E974AECBE9661219BDA8E55A2DB46E52C424BF9210D296DF + DDBB7686C2BC62387CF098EB546ACA628D46B30A9FED1608854FA5A79D9BE235 + D64A1A6A1B99C117A28643C945C62481D87E5D60FFC193703EB3048E9C3EB940 + AFD7B379548C898C52F9785A5AFA149143233B7FF6347E2B003B02ACCDE505B1 + 5C0102340956ADDB9292949AF6369EDF88803064D2679F6D4C38762CACB206D1 + D3E7B5F2683535A11F70BCC8FCF41161A148CA22F9E9E7CF2FC6B6B37975E4C8 + 1E44E08F9A3ED64D36BF7F6501F99258DF08EB186673DA082848BD8706262FBB + AB853700540A2ED95308640888ACE636072924F2EF0D993163C6F78F3DF6D875 + 58377ED7B838C60C27A5626E3521006BB0BF4DB0E6A79F61ED86CD736D761BF5 + 4FF51F0033AADBADA3478FF91AD9D1CDE7CEEE45456F83561B2D37A2759F7C08 + 0B11A3999F088B7FD8D6ACD634EF7EE08107FBAD5BBBF48EE2C22C2697B0C56C + 4746EC667C5A0C02A369E9721860FBF603909B5FE6D3EA74674C6613BD7C8776 + 7B69844B2FABE60694D28D5DBA74FDE0CC99B3A35B0CF5A8E48BC0EEE0E2E161 + F2F6289996189548C865CCD6050B9721CBD743A35A9DA7D1E9E89DB1E4672673 + 99985E67F0FB1A89D5B23E62F659F41DF9BD83775D01B814C80BDA258423E0F1 + 7942A54221E8101D158A4AA37348888A1F17170BB7DE7233B2357F2A0E9FC764 + 2830B24EC0C6E579D1AAE1A2192C05B984C3B4C1604233D9CE85CF3E9BF87571 + 711159505A1FD9B87F10CCA862B142A1E8A9D5AB7F9C66B56865942D4E349392 + 42C96F21148AB1F3C54C9A03C950656529346BACB03E7E3DDC7CE34028282C45 + F0EAC6381E05483FEB90693DFCE0FDE0733B80D612A66565C3BDF7DC034E9B19 + 2A6AEA98D4095A582C12F098CCFBB28A2A20932B044D2D4AEE541BCCD0313A0A + AC16339A6106088DEC00CFBF3016909DC0CA152B0F9B5B5BC919ACC6AA3FBC72 + E58A5923EFBA534E6B1D35DA16884253CE6AB5A0166C850E9194386B8419B3BE + F75DB858B802018598074D88AB8D62FD07CC3A778E7D1799D95BE5253950565E + 83832362808C7C17A40EE4086812146A9FD7818385265C481468B53A686A6C64 + F2D928872A36B603DECC4D1804768B83495E245F8710079AE77341EC753DA0B2 + 560BBBB7EE82E49CEC55A808686DA205D9DC98A49309D3A3B966B919B5B11DC1 + D08D43C9E7122B4473572984037B13A0A6BA198E9D3EF56D53939A40B02C0008 + 34D9073CF7DC73EFF5B9AEF7BF36C4AFE328E5721F828DCFEBF17A9C482551B3 + DA6B9B9B56206321C7B801FB352E54A57ACCEE702851A337C2A5AD852030C91C + 817B93139718209B7449CF22938F1CE4B1C816C2AD562B997A36D4991C895422 + 424814CA15728952A19445474785F4E8D12342828235FCB6E1D11515E5A68D1B + 3716A3D966EED7AF6FC8E0C14362FAF6BD2E6AF0E0C1E185170AF513264C5868 + B15AC9AF57173486F4BC7B972F5F31FF99271FEAD05C57CE0447288045CBCD28 + 9955A190234B30C1373317434A66E6A240D2EC1FC93323301B3E76EC8BD3D7AC + 5939F874E21E264DC58260E6417B915C0B91115238713C11D6AEDBDDD8D8DCB4 + 19955F4C6ACAD9E71AEB0AA0C564C73AB971D2BA99DC47059A635EB715366EDC + 02D93985369D5E77D2E6770D10232333BFED763C04E6B1783CB468D1E2AFC6BD + F46274467A22B689968271195F26F9AD68695E8FAE1D61FFBE43B07DE77E34EF + 4D170DFEA4EF7C0493E81EDDBB0DC4DB76A0C01C62015FA90A11221B73E11C74 + D1DE2222A1882740DB303C3C541E1D15A90C0F0B1363DFF1D0BCA75D59B83299 + 8CAF542A044A859CCFEC4642077078A1A1213CA55C4A1B7BF029919D800BD186 + F1B7B9BD1CFF4A15660D33302B31B81C02390BE8756A04F212C8C92D03B5BA05 + DB6328696A6A9A8A0AE9C49F0533FA439A71C4D75326CFEDDB27AEB7CD8A60D2 + B113328E502829AD80FCFC42FC5BCA646C93794160F1D4934FC3B16347192763 + 1D9A845111618CFF85D911C0E1409611CBD8EFB420B7C544E014C92C59D1EA0C + 08383160D06919D34C8F606334B542EFEE5DF1AF1190C732C18656FA8C139DEE + 77E7C8518CEF49ABD1A0006CDCD6623492BF85B4FDBDF3BFFD76CEF3CF3F1F51 + 535D8AD79B9901265F1F222993198F3610D2ED4D50555D750C078ECD78FE23AF + 9D2330EB1D15153DBEB0F0C28486FA6226ECEF76FBC33EE407E2E2B328D99327 + E030C095742A1D0A2F96A026B623E9F270995D31B01F625063BDF4F23320F220 + 2B73F9D74BF2A41266B0DD1E3B7E16407DB3154E272493B9B8B6A6B67631032E + 5CEEA81309471735D6552A4F259E8116430B1355A40456CA3773E17DC8E771F3 + CD8361C396ED5F5556D50447EB489B46E038F743863DCCE57446A3DC0ABD481F + 717CB0825E62491465AA0AFC651DD72101B9200D4DDA5B18E80F32F9AA03E79A + E0525A4F5F949981A8A9A3232322A3C68D1B77FD238F3EDC51ADD638AB2ACA1C + A8148551D1D12264AA7C349BF9680E7188B932BE17219FF13372787CA0AC0262 + 2F087488431CD0EBD528472E38783011A67C3D3D0127E754F0AF56B004EA434C + 63F4B2653FCE1C33FAAEC8E2C21C9403B4C3B9A2C004F2A2F92366F2EBBE9BBF + 024E9C39BDCCE5722FFD8360467D31E2ADB7DE9EB178F1FC81C9A70F81D9EA0F + A6907890B5A252F0E17C7626AC89DF632DABAC588663DA1A1FBFEECD11B70D88 + A135C236072565FBE384C4E4C0E7801F7F5805A9E95985668B8522ECBB038AE1 + 728BBD398131197CFDF5D77F78F2E4A9C7CA4AF3A0A9A18E0154DA9C40A95432 + F78DE91002BBB6EF213073D5D4D713D33B8487E883F7C67FFEC6EB2FDF443B97 + F09885FEFE9D578839D1CA0C2AE4F32239A2602887595FEA65E63475A423B016 + 98290C38B1C102F2AEB09F9181211BA671152251A1882799E11475D568B58096 + 0694979125A66756E5A8D57A04793B2A068B46A36E3E83F393183E6DFD44CACA + F267CC4CFA437679EFEEDDBBBF32E79B29EF9B8C5AC8CD25C42C64F28310A589 + 49B9F16156EC00CA58B5F7EAD55B949F9FA7F0B89D16214AA2422615E2E4E2E1 + 64E6A01DCD090F0BA13DB47C35750DDC48043A4A824546E56B6ED6FAA222C369 + 1F1D0E6A485F554D9DF7FA01FDF00E3C9FDDEEF0D637363923C2C3C844F022B3 + 71190C46A75CA1F0900AF078BDD6B3C9292B5B5B2D94114E0EDE11EFBE3BE19B + 4F3FFDB46753430DD4D7D782D16CC341123393842276D535F530E0FA1BE0B5D7 + 5E6FAEAAAC24303B1898B88EE06E084C4A361F8E008CDD448F3AAD27B28CD7F2 + 0BF23F30565EE0D7E280B4B6B432FE2F3231C57231C8622240AD33C3AEADFB3C + A792924B9B74BA546CBF9E36A412F0F94A6C5F5CB74E9D6F193A6C98ECAE7B86 + 23EBB4317E97268D96A980BEB10E01DE80C2E982BE7DFAC2F133675667E5E450 + 7D5B8442E180E9D3A7CFDBB36B77485D6D0D3135577844040F99931581CDCAF1 + 7A2949C88A8254A1D1E9F7A266A3B03EEBE06637A7247611077E0D4FCC4904BF + 4C3F11E13D4350F0B876BB8D2B97CB95BD7AF7EE83758FEAD9B3272F342C5474 + DFBDA3E4BB77EC6A5CB5662D65D1B349974C247CD5AA555F8CBC6B788F16BD86 + 1B13D309DC0E3B18118804C848DD4E1BEDE6055E04169A48B4201BC7D29F9888 + F2478C829805AD86205F204D0E0A8AD0722D921B4AF22D2FAF83993317D4155D + 5A7CDE14181B6ACBE8850B17CD78FAC907232F14E4A242B3318120F255915253 + CAFD81AB15CBD6C3EE03FB5760DD1705C0EC6ADD0D6492DDF1C69B6F4E5FB460 + DEA0734909A8A0ADD80601B3409ED6BA8687A2999998089BB71E769457552EA4 + 1D5C1E7D74F4334B16CF7FA8AC241B6C4E3F98596D0EC6C9DE292614CA4B4B60 + D5AACD96CCDCBCD508146B0275B25DA10E24971455FFF7EEDD7B3EEE7B5D9CAC + B484A2EA5626E586B618A27C4A3ED70167CF24C3FA0D3BACB50D0DE48E49EADC + 29E68EBDBBB67EAD6F31F0D5CD6A464948A522C6F1CFACBC100B188649634356 + 06CD1DDA7584C688BC50741ED23026A0454A94140F110DB22ABCCCFA602FA398 + 09EC8815D372B416A39959C3DC6A6945EBAA059A9A344CB082B22110536C2693 + A9D9E1B057A2AC963A1C0E8ADC528E230566D8DC4EEF5F499AA5C4BEC177DC71 + C71B0F3C30EA89D3A75350FE3C5AB4002A0A0A2E9435363555218213F56B0D08 + 8100AF95F868256F407363E34404687EDF0A109891AF083530C3487D88F43E0F + F512FE4C04D5EB65F636F4319E460A61A1D18F5FB139276DB3879D8186D60404 + 99CAD0471F7D64C6B7F3E6DD666CD14175753970F838795CFE76D22270EAF0B8 + 4EA15059D304EF7E3031ADA2AC94DE0D40745E17B83FBBBE9318086960454070 + 1A020781425C5878F86B79E7733E31669DE55A690ED15E56787FABCB8926B706 + 34CD7A483E79CEF3F3AE9DFB7DFE652294CBC6E61A910FA2AB4C2AB96FE4ADB7 + BD824021301A4D1E1C446EABCDC689898E26166777381D1683D1A843CA54A9D6 + E976A8351AD2AA26AC603876600F1496F00030B159D74EB89480481A5D1F6897 + 310888597F884220140E1EFBCCD3EF87F178DD50A0843E1ECFCDF17A385C8F5B + D8B15347E5232FBC18454C1101D32D118B79A52525BCBCBC0278E3F59740C2F7 + 413DB673EDCA8D505078F1407246C6C781F1E87BD75D233FDFBF6FD72385F9E7 + 181FAB03D9A9DF9FE866C2FDB4534763A31A9A9B1A996D7EC804A14818BDB781 + 76B5A8AE69C409E0807E037AE3F732643C5E26A842CE725A5A466B40255221C4 + AFD9E2D9B879EB0A043A621CECFE5BC4CC1E9B366DFA8CD75E7D21223F2F0B27 + 0F4D1A171398722190868448B013B8306FF6025F52467A3C9EBF3EE87A969D05 + EF14CB66BAB37D4C7EBD11EFBDFFFECC39B3A7DF70FCD81E647F769C6D02A68E + 22110F9999000AF3736175FC6E777965C56C14E7A4D0D0D0BB4F26267EDCA2AF + 11984C1666D588466BC0F6085036C568CD2860C7B643B073F7BE0B38DE530978 + E0CA3B8450BDC8D7F5C44F3FAD9A7CDBAD832373B2D3102C3C08DC083C082694 + FF47CC2C2D350D56AFD9626E52AB29DF3003C7F2EEC58BBE9BA2528A9133B919 + F6E441F69B929A85A69E011E7CE04E660300222E9443466044AC4C2695321B31 + 907545263B456E4D6845895131D01E79744E332A630A6291A39FB640429966EE + 41FB6FA2B26D75B95C36B406CCB4CA067F6FB4D96C35A84C685ED507E6319B7B + 660C8CC77F5C407F16CCD8094DE642EFBE7DFADC4749AFF98862E067314D410F + 73C1A5BCBAE0AD89D92C772E5CB95C69FFF5E0E512973BD8DFDC7069E904F386 + A6B8B8B88F56FDB4725C64682854551433DA01650628ED9643CE29A71D041E07 + 44A3D6D2F984BE959BB66667E79C4F6B6C68A040000133EDE41A121515D52136 + B653E7CE9D3A751CD0AF6FA7AD5B779C28292F279F15F99EC291C68FCDCECAFA + 4AD750232844AA4EFEC48AB272C84A4B4793D8CC50E98A9A9AFCF2DA1ACAA44F + 0D00219B1AC02A8BEE214AE548A4F25156344129D91ABF13217913E240DB0340 + 4E0E73AA1BF9F628BDC212984C3436B4E2410297B69766079F13F83FBB0572F0 + 56CA6CFF864AA4D207F2CF9F5FCB2D2914366567A336E261A7FAC02611823D32 + 1C2461A1E499462070FAD797B99D5054520E43065F87CC43066BE3F7407949B5 + EB5C56E61CAD5EFF73E0D9F76FDDBA6DDAF05B0746E6E765E2E4E631217C1E93 + C94FFE560EC304962F89878CEC1C3D322DAE54825C5622A2DD652937CAE974B8 + B822B194DFA143248C1E733774ECDC1527871B01CDC3440A693F32DA51A3B2BC + 1A7E5AB5AE28333B9BB647A25516C40C89993D3671E2C4194F3CFE6078435D0D + C3CC9C6EFF5A4F0F8225AD3CA0285F4971856B75FCFA549D4E9B141857035CF2 + 4FB1DB6E7303DFA903134E1D18BFE19F7D3671E6D753BEB8E1E0816DC834F4C8 + 5CFCE94B94FB45C05453550E2B7FDA6A2E2E2BFD3A50BF1B366CD830A34FEF2E + 9D4B4BD0CA7173994D0ABCCC0A0C294484C9A0AEAE0996FDB8CE5B5155F93DCE + 4F52B42570E51D4208CC1EDFB869D3D43EBDE2C2B2B3331833D3C5B02A3E13F4 + 080B9540D1C58BB07CC506A346A725169B8CD6D4E0679F7DE6BBDADA5AA54AA1 + 60560E18CD666835FB37F18D8C8C60F2C7081F68E34CB5464B1B667A71AC3C5A + 9DD689F303658BE3445074619F328C09E719A7B5B5D56377D89D28FB461C4423 + 7E6E4186D68A726D74BBDD2D781EBB1280DD9E9BFDCCAE260A5E11F02B70FA2B + 6006014063F738E7073A95DDCFDD05574FCB7FEFA50E573AF78FA64C306F349F + 3CF98B99CF3DFD74A4BEB6069A2A4AC18E0226A00DED505B785B5B019907F215 + 0D131E8EBCF32EF08485FB0A2EE42339323968DBD84E9D3BC93BC67494848787 + 3260585C5406BB77EED5EED8B7EF79FC7F46A03F1E5DBB76EDACAD3FFF1C5A76 + B1C885A69EC7E976B92C68572330B53ADD6EB3D3E522D38BF2AD8AE1925F8E4D + C6A5BE65D7BED2A10CDC97408ED84584582C510D1932245226110BCEE7E5ADD4 + 6834B4CF9417154B1FD4F2B746444452D4391AF156793E37B7B1A1BE41239549 + F9B4E9B7D7EBB123A5AF32B6181383B6ED0EEE4FC6EFF3D9E793667EFEF1BB37 + A4EE5A0F8E329CAB21A1E088E940FE462F4728E0F2846226E244971290907CE0 + 1F40320187769F8673999919798585B4989C4CD9CE83060D1A7FFAD489E7D2D3 + 4E8156670293D1CAA42C20FB04F2032B157C38939806070F1DB595D7D4ECC1BA + 155310402412A279CAE1D9EC362DFE9F2F100ABA60FB078D1B37B6EB9D236EE6 + EA903198CC366401322632AD52CA1856B76BFB3EF7CAD56BE6E18C2276458044 + EB179FA08D06BA75ED104A8BBE290710AD6526C8443E640F8232450F2942AE6F + B1B8AAAA6A694B162B31E10B170AB50D0D0DE6912347769353A581E3B5D9AC4E + 5A9AB367CF9E1D6AB5FAE7C0C4BBE5F3CF3F9FF1F9E79F0EDAB563239A511630 + B7FA3D150A942B643DA8DC4A90652568D014A66DA068B7E1AECF3FFFFCE4B973 + 678D3CB06F3BE363B3589D8C9F894C397A3DE275BDBBC1CE1D8761CFFEFD59E6 + 560B033E81897FB9794260F6D4AE5DBBA775880E95A7A52633C9DB1C9CAA9471 + 4051435A2E565355032B7EDAD0A233E809F48FE3188A6532D99D6E8FA7AFCBE9 + A21D25517CF9E401A1394EE044FB6ADB3CB4E8DDC738C6283DC61D98F7EC7B13 + 6CF0EB1533F4D90197DE3FE1083A9C4147DB759A57E5ABFCABBB66B07F8399D2 + DF6A5B10F8E54B19080CFAF5EAD56BC2B6AD5B9EE5224DB6D554436556069869 + 478C961626F9D7A73780003573289A85CE9828D053DA478812A428BB2E8F7F3B + E2A6A626282A2AF6565557DBB332B3CDD15151F9A5E5E573B1CFC89E27AD7D5F + EF5EBDC6DF336A540F8D56634C3E97AA4133CA8342C2BBEBCE11A178ADA9B2B2 + F24C73B37A275E435BE0B4DD8A9A5818F9977AE1D11767732C02548C52A1EC30 + 69D2A4C13D7BF690CB655241ABD9C8DFB461131C3D716246655515254FF26EB8 + E18637B66FDFFE3E9FB1D63D0CDD277F1B972FF4327B78E31025269C849C9C5C + EBBE4307C71B0C06324F356DC68EFCA203BB75EBF6EED9A433FFCE493B097A0A + 5270D12C5785A2F452B6B7CF2793CB390EBB95896653FE1B056DA2A294509073 + 11CACB6ADC7B0F1FFEB1C568240641603D6ADDBA7553EEBCE396CE1919696030 + B432011E0604C1CB4C70BD4E073BB71D808AEAAA548D5ECFEE1C4B42CD061458 + 539800FEF6A79E7CEAADA79E1CD389968C1198094552C627A3C0B123E6565956 + 05DF7C332F41ADD37E037E6731F9B3FE357FFEFCE99D3A86ABAAABAB8002A894 + 9CE9CF8FE40426851BCD3B1E63B68684843152448A8BC69ED28E143205CE6A17 + 9326432B3BB66FDB0B870E1F3B82EC86808958F6D02FBEF862E6871FBC3768D3 + C6350C28D1FE6C7E3CF03120E2B25B60DD863D4D178B8B26E29709784474EFDE + FDCD0307F68F3F7A7827D8D064401EC39867CC3B1FB0D59D3A463099F3D3A6CD + 69AE6BA82725414EF05AF8357160C1EC992D5BB64E8D8E0A959D3A9980A06AC5 + FE66F3177DD0213A0C1AEBEA60F5DACD2C33A30D048881B22FD211C1AF5F22C3 + AE8366812AF83B77D0D176BF336F9BF3DAAEAFFE4BD8F157F733BBD2929EBF53 + 21E961DF60C30D7CEEFFC4138F8F9FF9F5D7B75246A99118DAF9F3A02B2F07AB + 5A0376AD1654D1D1108113428D20572744C10B09019D15B5ABD5EA8D8E88F429 + 42437825D55526955265D56A34EE630909A9C83068F9132583CA684B9BF9F3BF + FDE8BA2E5DC21C360B4728937B99DD5B057CAE0F959842A5820D3F6F6A9DB760 + E1C7384928C8D0D0A62F69D2F59D8652FBC003F70F32190C12BC4EA8D5344007 + 64462E8F9DD9D2272FEF025C28A8761F3C7AE45BAD4E476B3315C3870F9FB475 + EB968753CE1E60561AD02EA7947A454043CE73B95C0C7BB71F018F8FEFDA79F0 + C0D726A391A263356D9E4F0A8026C398D5ABD74CBB7170DF9093470E808F2F41 + 29E432E0E542939C26A77FC98ADF7514162263521B8EEC3B069A1663C5A16309 + B48693D843E4D09B6E7AFFF8B1A3CF1E4F38C46C80496936E4EBA289E5713BA0 + 4B5C14A42665C18993C9AE8A9AEA85687A109B6233DBDBCA1A29A681C89E3E7A + 7FFC3B8F89507DE8F52DCC3A547232D38E11B4B5935C2A8585F31735A5656753 + 3D0E04EE3386DE3310151512525A52C4EC9946FBBDD10A0D669F34DA84134D2B + 725CD3069D34E909C8F84C0047828C2F12D4CD4D4C3A0F8F4B91D448D8B2F900 + E45FB89868301AA705EA7CE3A79F7E3AF3E38F3E18B872C5626CA70F958A8B51 + 96E4F7532925E0B05961CBF6838DE51515046614A4A0B5958FAC5BB77E66AB59 + 134939959473467E45FF7B23A89F9DD0A35B57387820D177ECC489ED0EA79372 + C268B995057E5D2878F3349AAE5342543265C2B1438C294E4B88280A49DDD9B1 + 6314D07B2FE2E3375B9AD4EAA9F82505CB6AE1CAAF9E63CBE55EF1F7575ECBF7 + 97CB3F7673C63F508861440F1B36EC2D6445D1898989B4DD0E9901710F3FF8E0 + D84FC6BF33322C348C5B8B1A5A9D970B68778005DB68A39D3E69C7070A318B44 + E0A4B034970BB2C8705020B08923A390A500631E35E975B06FF741EDF1A4331F + 381C0ECA79915F7FFDF5EF7CF1E1BB1F56E564205BE0038FFC31B4E403EF41CB + 4014D11D60C7EE6370FCF4E93956ABF572C9B9C4CA6E5FB972E5D27E5D3BC5E4 + E566000F4D1FF22D113BA010366DCE5859590705F9D59E849389DF35ABD5044A + 612347DEFDD5C68DEB471E3DB899D90E9AC313310C8251AFB42160881C8E1F3C + 83FF117B76ECDF37C76834C6833FCC1FFC7C3A9DC964BFFDF61193F6EED975DF + CE1DEB987416BC5560370C9C6681C4438A2E52543922220C8A2F94406E563E64 + 17161EA8A8AA9A0B7E1FEA2D3FFEB87CF690C1036293CE1C47C6E164EE43899B + B4C48B80A35BD7CE9070E0349C3E975252525141EB0D29EB5F7D8571A5C9168B + A6CFD3CF3DF3CC949B870D929B8C3AE6053394CF47514DB95205E40AA82AAF86 + B9DF2E5C65329B287585FC30F77DF9E557B3A3A25491F4A2115A884380C1E504 + DEF8C6B233FFCA69FFC302722FA43592A8009934043447494150F47D079A7E45 + C5A567D15423FF17050B864C9AF4C5CCB7DF7E63D0F265DF317BB0519FA9D04C + D733694622C6C43E9E98D4545854F4199E4FAB0CC82774E3B3CF3E37F9E597C7 + DE7BF4F01E8631D2B3D0DC0B282317937F5855D6047BF71FAAAAAEAFA75D634F + 05FAA9ED842565F42F94A1E94A8548792EF9742009971778C18E97D9E493B645 + 5FBF6EABA3ACAA8AF2314986AAE0EF4F527E55AE0530230D7EDD73CF3D3773CE + 9C390F3EF1C413FBB3B2B276805FFB84778A89B9E7C3F1E31FBAA15FBFD89AEA + 6A68A8AF031E322729EDF5EF76310B6325212A70E3E4E089D01CC283FE4F5B69 + 2B943208450697939907C78F9EB29C389734D9E97452FE0FBF6FDFBE6FCC9B39 + 65628B410DCE40189AB2EF292A64438D6C6AB1C0E9D369702A39799EC96CA668 + 5B5B3021301BF103169EA335FA425101882462C6192B572898C945F93E7A1D25 + 42021C3B79728A5AA3A176291F7CF0C1D96BD6ACBA7BEFCE8DA06E5203A5F550 + DE0ED58196889086D76B5A90BDA860F7A143331004E3E1D719EE6C9087D6308E + DEB173E7148ED71E7AE2E8610444813FA283C0EC6426190F24121113E4902013 + AAADA885EA9A3AEBE144662B6F62436E04F737D1C49C5857538120E660D6EEE9 + 0C0666C90E3257662D6F636333E4669C8784A4B33F985B5BA94F7E2BF5E03F60 + DBB367CFF79E7FEE99C79D4E13F3420FDAD38EF2F9886D31BB380844B067F781 + 73A56565E3C11F51BD69FAB4E9DFA195DEADA8F002C3240538AE6E7A9315ADCB + 41D642B9781441F730EF42E0E13DFCCBF2FC19E9FE1405A63FB9FE1788A4A664 + 414161E1D9268DE693405F5EB760C1770B1E7DE4911BF7EED9EA5F1983E629B1 + D0F2B252267DA1B6B61EF2F32FAAF13AAA17F93B0968BB2895CAA791594F3D71 + EC90B0A1A19E79EB1203A05E7F463C99BEE4A9CACBBD007985851391C1D21AD9 + 46F8B5A949BED5FBBEFFFEFB05D8D6F0E2A28B4C7F5374945E10436E2EBA97C9 + 688173675220E7C28549D8779BE1F266EBDFBE5C2B603664F4E8D15FEEDAB5EB + BE33A74FC3CB2FBF72B2BAA69A263E39DE9985F3BD7AF6BCF9F661C3862A64B2 + 6E7AAD8E4C5226C194224961A879997DDA5110098828A44CC9AE2A3415C9F1DC + D4D80451A1E1D60309C72622ED271F864B2291DCFDD1871FCC68ACADEBD2585F + 4FAF17F3464547F14C26B38F762BC089E376BA9C2D49E9E99310A082F3A0D842 + 75E87BDFA851DFAA64F21B4C261337323252469314C18F1CAE3E04121F321AAF + C7E735A319F5219E431342141B1BFBC6BDF7DCF3586559B90CCD4C1E12281EF3 + 4CB78BE3A3FC00E00828B8D125B6932D25337BAA56ABA5BEB8DCDA4332D129F9 + B257FFFEFD5FEADFFBBA27AA2A2B036BF338B42C85472284F7F689452217F689 + 074D6DB7482474D436369EACAEADA5FC2C72BA0BBB76E9FAEFEE5DBB8CB5DBEC + A1B44E4F4AAFAAA4D5F468AD2263A29D2B6CA6D656BBB5D55C52515D4D40466F + 6BD2C16F3B7F29421D83F5191E1D15FD3C02A00C2728659B73D0FC95E31F29FE + A5F740D2F29D9D3891C90D40BEC9AE4F3EF9E42CB7C3794B4E7616F9ECC83275 + F1287B334036299BDCE3F530C9E83C2ED78DA6A71BD9910BE5C141BBB6BA7100 + 109004F8995E1FC597CAA4DEEA9A9A7D38364B03F58E1E3162C47BD8BEFBEA1B + 1A6438FE421F83FF1C1EE5E649A5328EB9D5ECF67ADCA51595950480EC7645CC + B877ECD8719C5422BDB7C5D8820600C7835512F8E8B5854CF0C6EBE5F1791E94 + 31378EDD1A6CF786C033DB0210059006DC7BEFBD53CD26D34D1AB55AE072B91D + 48405D94FA44A24F7244FD85836A29AFAE9E82E370E40AF7FADB976B01CCC819 + 3FE8D65B6F9D7CE4C8918769716F6A5A1A9C38915876F8F061A2D4AC29C34C0C + 3CBA878684F4890C0BEB111612D291CFE585898542A580CF17A22C7390F27399 + B80E0FA51B818500C5E2B0BBBB7489531F494C7C17270C85F1C98CA53DA96E10 + 8A447DB197656E7A1309820ABDB682F23EB1238D084C944A41FE0ECA606EBBCA + 80CC634AADE8CDA59C319F2F42A55044E3674ACB70BA28C7CEEBA56D96CD3ED2 + A4FEC003A506B09B3A52C22BBBB15FF01BCD8581EFC8A94EDA9C523A8849B0F9 + 80C1854DA0250644260B256192E39D5E6A2CA305C64C96B7CF472F0A66A35364 + 2A11FBA90CDCD718D416BA074513D955025482DFD86D0E8C0501AB017E99A87C + B9C2098C6F68A0ADECFA41763B77B6EDE44F62F300A99E04181458A15D876570 + 294F2C780B68D6211DECD466A373C1B966ECFAC3D6C03836069E270FC8536CA0 + ED62B8B4D9283F703DF54D15F8019F5D4DC1262C7708C890B84D7B5947BC33D0 + 478D81FEBADCF84902E3D52B7028E052AA52F0123DFA8E946945E0AF05DACDCC + BF6521E1E88BA6C827E9E91963691B93D4D42464564E3018CD96EF172F5EADD1 + 68C867450E7012061A709A1424F0245421D866DA38528AFD416F05A7645F2197 + D65E7018E1A2D72EE9D104A846569683E710A0D0C4A48944022D854B02FF9F7E + 07FFE421D0B3C02F9331D9C24E1471E01EE2C0FF59106023416DEFC3B65908BF + 5CE81BB4E09739D8C4623684CEDEAB6DA16BF881FB89E1D28EC0BC3675F1C02F + B7450ECE09E2065DC74EE8B6B982ECB5C1E1F8AB99506C9BD89518C1798CC13B + 14B349ADBEC0B9D41649A08FB87065877770A42D389791AD6F705E23FB0C7625 + 45F0EEC96D9FC1814BC9CB76B80494C1AB4BD8EBDAEEB3CF09AA4FF096D400BF + EC33761767B6AD3CB804D0DE36F762EB7EC53CAEBF7BB916C08C84A1AB582C7E + F5F889139F75EBDA857FF6CC29A8ADAD01CAB2DEB17357CDC58B1759272ABB52 + 8015A6B6DB78B3291EC19391DD0BCB0A9712FB2E17266F5B7C57F80CBF716DF0 + 64FBAB51A4E0FB060BF91F297F36E7EF8FDCFFFFD5A462419A4D41200526FA8D + 6707030AF5133121769B67DBEF3DEC37EA107CEFBF720F16B47D97F9AD6D1B82 + DBD7F6BD1BC1C0FD8F2AD702985121B3EBA1891327CEFCE28BCF3B25279D85F2 + 8A0A28C8BF0089274EFAAA6B6BE8A515E4A761F7B4BF629FC02FF36D82FFB6FD + 0CBF739FE0CFDEDF39F7FFB596FC23938A157EDF65CEBF12B361FF065F1BFCDB + 6F4DBAFF9BF56F0BBEC49CBB0F1E34E8B988C8C8AE3EAF57840C9CC3C3834E60 + 9CFB945BE676331B3E202BF7A1B9CFACBE6BA8AF379CCFCDA55418CA5D0BDE85 + F6B75EC2D3B6FFD872B9F1FFBD710F96C5E067FC1959B9D2B8FCA3CAB5026624 + B43763F9E2E8D123A3727232A1BEAE0101AD124E1D4F84AAAACA82AABA3A0A4B + 531636BBC9DD950AAB01AFB5C24637C95CA1FE245643C0DF1AF8CB0BFC462C87 + 98AC132E2D436115C4E5C08FF56DB1A66F5BE5C09A517F95BD88E0520228EBFF + 52F178BC9B5F7FEDB59FD3D3D3851EB7BB854BEB4F391CF245F23D1E8FC0EDF1 + 78057C3E7D67A3EFBD5E2F5722917087DD7C739F1F962DFB1A7F272568844B80 + C09A98E48B63FD5D2C631704B595FAC40297B647BADAF67103F790C1A575B7AC + A9FAB77AC3F8FFEF72AD80194D98DE686A8E4B4949F988CBF1F1E8CDDD0D8DCD + 907C3609CC3A9D27392BEB07BBDDCEAE75B3FFC5E7FD2F161A7815F6611F9552 + 39D4E174CA1C0E87DA66B351863E39BEB9212AD50091587C83D7E30911894446 + BDC19063B55A69FB1DF635696D592881232DCF8AE271799D854281DB66B73707 + CE91221BA21D67C9696F863F9F214ECF249F23B35615EBD50141AAC1ED765380 + 8236D51AFED28B2FFEB066EDDA1328EFB43E921CEA0436715151513777E912D7 + 2D232393A2C41428213704C992B473E7CE77213B3BE5F5075E98B7DE811FC809 + 5008643AF6EBD7F7A6BABA3AA3C964A6BC33529212954AD58702A1ADADAD5570 + 69DB672B5C9D99CF9AC51444E922954ABB61FF92AFB73850371BFC7976F68F2F + D70A9851A599AD673EF8E0831933664CEF71F0C03E66A7067A114A5E7A163434 + 375FCCCC3D3F152E2D48BE6635DC150AF561449F3E7D5ED8BF77D71C87D3CDDB + BD6BB765CAD4A90B504E68098CF3CE11233E5CBEFCC771C878B9A74F9FF6C6AF + 8B9FA5D168291D8200EA7259FC4A04AC7EB7DF3EFCA9712F8EFDF7F419B352AB + AAAB77DC3474E80D4387DEF8587CFCBA95086ECC06907029FAF647FD74C464C2 + 11846F19FDE8C32FF6EBD76FD4DC79F3E94D56940FC84130BBE5B5575FFD616D + 7CFCA6C07B09081C5458AFBB76EFDE39B9B6B63A6ADAB4D97B341A35ED665A18 + 787E78E0DE54276B97B8B89B5E7FE3B5176D367B787CFCFAF2C6C686E2575E19 + 77D7679F7D7A57D1C562CFDCB9F32E269F3B777240FFFE9DD6AEFDE911BDBE85 + B371D396DA8D1B372E4519A4654C04ACBF074404B0E4D7A3F7160C9B307EFCD8 + 3163C6DCBC62C58AB2DD7BF64CC2FB905561BACA3EF99F2CD70A985121EDDC2F + 3C3CFCFD73E7525EA8A929078DBA8149643CB4EF30E81A9BBCC7CF25AF34B75A + 889D91D05AFFDB15FE9B151A784A157860CDEA9F66BEF0FCF31DE67FB700962E + FBB1A8A1A181D63D9A90F53C959D91F2FCE1238761F19215B6DADA1ACA8627D0 + 2076C5461BD96D88E8F3FF69EF3AA0A2C8B6ED25E72820398A204111C130E6F4 + 9E011D67E6BD010302065014259850710441C94104C540121150511011240948 + 1CB2281911683274133BD2FC3ADAF5E13933FFFF797FCD7AC3D87BAD5E40535D + 75EB76D5AE73CE3D671F595E3E3E9398E828CFC1C17E2107C7D325980B57EEE7 + EB6D9B90F068322323F3FC249309254DC3683A4DE44B9774661133BE2A882FD2 + 20D6FFE72AC8CBDBDDBD7BD331272717F90704FB321874D8EF283717D7320B0B + 8B508C58EE50A8D438D658951415950E545616DB8685DD468F1F3D235455573B + A2CF610888A529FFF0FDF70EE9E9E9B923A3A36FB07D685B5B1F0ED8BFDF5CC5 + E3EA35E60869B8577FA1BE348D46E7DEB47913C2AC33141D1945D4D7D713C0DC + 587E29292964B078117AF4E8494372F273100E85EEF0FD685A170F5FC9C517A0 + F0941A390579852D172F9EB76E6C6A56ADACAC9C6C6F6FAF6BFBF0E122662142 + 8AD1389A5EFDC41F1EF8BCE3ED1071192B7C8EA6D0B484D6AC26C2AF89CCE08B + 03F37C8BABABABDB89E34715DEBCC9FF9411DDDEFE111564E7A3C1A1A1B6BCD2 + 5228BF81C44130FF7F4F57A6AF0190FBB4CDDFD7D7555D4D45B1A7B707253E4B + 62646666C763EEE0C7DD66663FECDE6DAA555D530D12CF13F5F5F54072A0D506 + 24033957F01D809506B1348827E962AF2D8E8EF6DB949494E42F5DBA5CCBA0D3 + AB848585D5FA0706A0272758C9E0A2017181652D895D7FE01A8A43F230467490 + 000BF12C11967C0C585560C501E181FBCACDFA1B627CDB7C7DBC9C3B091D7CA1 + A1772269342A48A20F029999EFDB17F2303E3E8625BF0C312C3D7D7DFD1F9293 + 1397979414A3D8D884218C74E0210725475470B58F1D3D7A232424E40E854603 + CB514C5C5CFC504646FA9E278F135070F0CDF6F1898912CC0D54387CE890F1CA + 552B79C2EFDD4369E9AF40B5785C5F4F4FE79493FD5CE87D71C9C5F509E6B2DF + 449FF3CC80B08070F03A4B31D69CE329247276C78FDB7EFBAD89FA89930ED4F7 + EFEBC0C5856BF5156B5EF1F823EC83CC9A6F51D67EE0C625B15E405E22AC3902 + F2EF67BDC868167B245F139901C03AD39296963E545C5C6CC36450B95252523E + 7542CACFCD4714E208AAAC7B9FD9DCD606CD4CE042999599D07F2020EEF437AF + 6BD7DC070707557574B450774F2FF2F1F56FA152281F9D9C1CD7BC2928641E3E + 7480D7C7D78F5C5151091500F97053DB1DB3B52D2B2FE7CBC9799D8059118D5C + 5C5C5207ACACCC4944A2A6AEDE02A6E41C49491717D786E1E1E162333353D58E + 8E0E524141215426B4F2F070CB393A3AD834D435289696957578B8BB7FD3DCD4 + C419101858BA69F366E6372B562C4D4848E8AE7DF7EE018D4683427FE11D2626 + BBE5E5E5E5C22322E2E9743A585BC6D783FC6DDA3EB6090407DF8AA3D36950A7 + D98F91D90A7373F3EB9865962E2E21413235FD6131762E8A797985D4D8870FD4 + 9A9A1A38AE0785503F7CF850A3BD40ABAFBCBCE2C3C40479D2F6E8D1C3B76EDE + 8CA5D2E9D01F009638CDD25FA5DB97941471F9FB0735B0BA8C4F4A4B49993E8C + 7B68F4E8D12384597950DA0549D50B1C4E9E30335EBA98CFD1F15C7B4F6F6F28 + 0F0F0FFDF4E9D33BCBCBCBFAD2D35F41613E73CD9AD54B8D8D8C97F50FF4D316 + 2D3290F4F2F26A5EBE6C194664760A0442F7545B5B5B5F6848484A6F5F1F1C8B + A9357FFE8AADDBB6AE8D897950333030803D04387877EEDCB151545454791C83 + 8000FF445252F263EC57A2ACACAC1EF695EC7D919ADA85DD0B91E8B30029CC13 + 9E8B37EBF0B5911998D6F034325ABB76EDB167CF9E9AC4C7C5A22190FCE1E542 + B919398897938B915B5A1A84596991E8B3FAC1FF9685FE3501C86C93AF8FB747 + EDDBB78A74068D72F08095C899B3E7C79414958618CC498596E696365F9F6B1A + 6E57AE528B4B4A6330226B3B78C072DF9225065AA094111B1B378C5914398E4E + 8E4B464747943A3B3B3EB514049C3A75B64E4F4F977AF76E98C1C3D887C8D72F + 308246A797999AFEF84F8BFD7BD7414721770FAF5ED9B97319870E1D507071B9 + 3C89DD94A455ABBF119FAFA9C9857DBE1123B3EC3D7BF6AC36325AA24BA38E21 + FAE414E9EA55EF4CCC1D9B8A7D1065F2EEFD7B011FEF8047343A0D88B61F23D5 + 150EF6F6417EFEFED5972E39ABDB585B2B415BBFE4A424E68A152B399A1ADF73 + 949456321D1C6C39444484395C5D3D299151D1F9972EB9ACF1F2F48C2353A821 + D87EC6B0BBE287FCFC3C97AAAA0A5E1F1FFF968FEDED60958275BF13DB973566 + AD72B9B85C82D86224F692D9B07EFDF18B174EEBEDD96BD5CB2FC05FE4E6E6B6 + 122334E961D210AAAB6BF850585848F6F1F1D181C2F657E9AF90889804CACAC8 + 9880966BE79CCF0ADEBC15863A3B3A691811C50C8F8C3C58B376CD16F3BDFB8E + 50A81411652525BAAB9B5BB9B0B008AF9DDD714311EC615D5050F0A99D5B4040 + E0133285D27AC4C6E6E0D2A5869204020105040617D6D57D92218292AAF17FEB + CAF813E06B2333005EB6B4C2C9E9D41967E773860F62C23FE96941527F55690D + EA270EBD4D4A4981180928C08EFDA707FC27C2A74594003F1F8F868646858771 + 712D776EDFD00119A0A6E656E4E67695A0ADAD45F4F3F5D27373BF4ACDC9C9CD + B6B0D83FBFA1A15EB8B9B9A5E3CA95CB46985B35B871E3468AA1A181C299B3CE + 75C2428254CCD05BC4C72FC871FEFCC506128934703B2CD4B8AABA9A373838B4 + D4CAD292534848502D322A8A909E96BAD0D5D57DB0A6A6E6635454B8A193D319 + DADBDADA02315151FEE8E8C8A5EE1E5789342AB55D5373BE7CE2D3A75DDFEE34 + 11F5F1769F6775D096919FFFE6E78C8C978BF2F2F2057D7D0312C9643258DF40 + 66AB02FDFD034F9F39D3B4DF628F8CB5B58D92829C3CEA1F1C42FDFD03A8B9A9 + 0161A486F4F516A096D66674CAE91C2325F565B98FB7F7920B172EC44E90C950 + 8B097966DBD35EA67A62242970F9B22B09B34AA11F03D497AE8E0CBF77924AA3 + F31F3972F4CD149A02F796CBD0D0F0C0B9B3A7D61F397ABC199B330E8C8445B1 + CF74595B1FD2C02C32E10BE75D3A1CEC4F4AAAA9AB089D3CE9D4DFDDD3DD4826 + 539A65656416C5C5C71AFC74D90DE5E6E6C1E2C17D313131EE850BF5AD6BAA6B + 84242424F8AE0707CECFCCC89ABA772FBCDADBCB43073B0F5E4F6FBF0F9C9C1C + AD98555975E88095E98BD4973C068B1791BF59BE5C353028B80D7B785B63FB02 + D79E4D66B30878CE11D4CC6DC15C15A7AD7FDFA4F23CF93152575743834432CA + C8C87A8BB90520B20741D591FFD7D1FE5A8098E3FAB05BA11E9DED1D6A57AE5E + 7BE37CCE517FE38675E21ED77C514E4E5EE5FA756B79838202754F9D3E43CE7D + 9D5B71FD7AE0524F2F6F829191118D4424CDCDC8CCACBA191A6A50555D211616 + 7617D236FA02030296AAA9AB89D9D81C69EAE9E9697FF2386E795959B9908F6F + 4075EEEB6CCDE8FBF74729642A5504C38D90909772B2B24A894F9FAC3EEF7C81 + 9E9B97F786C9648EC6C7C76D7E10F3809AFCFC791EE65E8A6CDEBC597DD7AE6F + 65D5D594F84CCDF6D1EAEB1BCA5EA6BE30C8CEC916BC7123F4194666BE706C20 + 333FCC54FBC9D5AD8E41A773BD7E9D61FCE0413C435C4C9CE347B31FB99A9B1B + 118938824647479190A010B23B71A201B36CBA9DCF9D5DEDE3E31B4BA1524140 + 12D239966156AAB783E3498DB367CF4F61AE623283C100725894FAE2B9694F6F + 0F9797A737A1A1B109946887B76DDDB25B476781BE9F7F6006769FF5E9E9EA6A + EBEA2E503531D92A4AA5D2786C6D4FD43B3ADA4BCDD3D4903A7DDAB99E482442 + 3BC02129A939DF0507F9EDB873370265E7E4426D7122F662F0F1F119A9ABAB6F + 505196D7DEB3C74C322EFE09253535AD2424D8DFB0A1B151E47AF02D883FA6C9 + CE95553437373B763D38B4D6D8D850B2B1BE69B86F60100816E2856DE8976DEB + 660DBE46320380BB0941554DEC62FE2E2222D2DE68898168634305AA7DD7868A + 8A4B0B5EBC780149B410DF98B54FAA3F009F2CB3FBD1515706FAFBE739389DCA + 30363212B7B73F66EC72C96DACB5F543AEC9F6ED1AC1C1D7B56D8F1DA36467E7 + 548005D545E8E27E9D9B379E9CFCBC08FB3C3D22FCDEA69EBE6E812B6E1E2D98 + A5D0E8E5796DC9220303190B0BCBE6DEDEDE0FF1710F969596968906065DAFC1 + AC29753151318CD8FC47E3E2E2C11229E3E5E5D14B887FB8273FBF80232434B4 + 1CBBF9FB6F86866CBEECEA56AFAFAF3779F8F0217D4F4FAF3E616161A287BBAB + B6B5B52DA5AEBEBEECDEBDDB866FDFD60A8686DC4CC6DC578899757072722E75 + 3E7BE6869F7F40C5C285BAD2D0F2CEEE844387F9FEBDD20A0AF2FCA01D07DD18 + D3525F8E5958EE177EF4E8F1407945D5BBBDBBCD963F8C8B4F60ED070AB4D5A4 + A5E6384644DCDE0B4A2AB76EDD1EC2AEA3C29D3BB66B1D3C68A9393E4E425595 + 354CBF80D0525E3E3ED2493BDBCD3131B11FBBBA7BF2ED8EDBAEC0C848F3F69D + BBEF9D1C4FCA4B4B4B4B1C3D6A577FF68CD3DCB972B212EE57AE556396135C8F + 4373E6485AF87A7B58C43E8C479959B9D1D83D9ABE6AD5AA159696FB7787DC08 + E1C1E66FD8D5F582525474ECC49B3745A54101DEC645C5854271F1CF40CDE5B1 + A484B88187FB45A7A4A424CA9B82F2AEB1F109D0F7833C3A5868815CB5DF4A70 + FED3E36B25333C5B1B567AB4A1F9486262A22537D7A4605A5A36CACDCF7F5A54 + 58086E022484B21368A7F189CC6E86065FE9EA24CCBB72D5330A7B18B46FDDB2 + C93A3B27EF2D464C956BD7AEDE1676F386EED97317269392538A8ED91ED658B7 + 6EAD9C8B8BDB20660DB50A080AD217EA2F50B2B4D8AB74E76E14E55546D6BBE3 + C76C9530CB4CE6BCF3C5CE2122A91EBB01973535B7888485DDAB3235FD5EE6C2 + F953F23FFDE4DE5751F9B65A485070B4F67DFDD0F6AD9BD6ACDFB0767E78780C + 4943439DC2603039525EA43E0F0CF0D9D1DBD73B37C03FA87ADDBAF5FC172F9E + D5C22C1B7A7171697564E46DFDA6A6663E3FBFEB6F585DEE411053C7C1DEEE66 + 7474CCDBD1B1F121017E7E8C08AFC82D365C28999F5F843E7E6C474A8AF2A8A7 + A7AF2FF1691279627C823C3A36D6B0C364EBB6C4C4E4F0492613562221D11A44 + 09366F58BF0AF33E4F693636B4A28A8AEA51790525A1F0F088EE2387F72AE8EA + CE432FD37347291426F7BBF7F594B2F2CABB4A8A0AF23131117BBDBD7DC65EA6 + 659584DC08582E252521646565DD646B7B544A4E5E4EC2CDF56A05914402055B + A2D41C492B2F4F37ABF884C71899E5DF6732278BCE9C76B4565090367074742E + C75C6CA69BEB79E3A0A020724151E5CFFEBE1EC6B9B9390249CF336131052C39 + 195B9B7D1E8282DC735EA6E73750A9CC062A85DCD6D9D5138EDDEE3313C6D964 + 368B80AB137CD28FC23C989D8181D7F7EAE9E9C8EDDAB5CBA3BBBB1B96DC2199 + F1F77433FFAB03628DEB3DAEFC74A5B0A040F5455A2604B9C11597C02693CAC7 + CFA7EA687FEC928E8EA644427C342A287A5B40228DBFFFC7F77F339157549383 + 766EE56595551515156576C7ACBE9F374F43B2B8A40A0D0D0D32448479B8FBFA + 89A8B0B8EAC5BAD54BB4E6CFD798575A563B52FA7375F13EB3EDCB76EFF9510C + 1AE34644DCEF4E7D990189BAD2870F98DA080989883536B54DA4A6658285D4F6 + E33F76581A18E8ADE8ED1D445DDD7D24A3253A824343A3BCD1F7E3AB376E5C2D + 6EB8584F252929835850547290C19884153C652B4B73BFD69626A9DCFCE2E435 + ABBF591B12E267989595839618AD4429CF93514B731D7271B9842EBBBAB73C7D + 9692A5394F43596BBEE69694D43450C385445BB84E20160B323BDFD91C323BB5 + 72E50AE1CCEC121417FF389B46A3D5AAAA28AC3E7EC46C7177DF044A4979D5D7 + D0D4020B0735E262A2CBCE9CB23D3739C5858A8ACAC60505B83956AD3414CCCA + 2E400606869FDAB4858545D6B677743A60DB13B5B5E6DB5E70763890F0F8294A + 4BCB09A233E8556B562DB1D9BE6DFDF2AA9A2672477BCFD4022D39417ECC252E + 2A7E3FF1DDAE1D823F9715A3ACACC2A71809C3A207C28EB16FF73F371C98A7A9 + C3555DD38072724B6A7BFB86CCD1E705AF59EB897CCD64F6E974D034A1A9F0F0 + F0686FDCB871517676763A7601E2E280ECD48CCF80B98238E31A8793B6D79E3C + 7E2AD44EE8B6479F83C690A3242424C8BF5C415E7A1F81D02D8AB982935388A3 + 9A343C01AEBAB2BA9AFC0E2271749C481A85245A88436AABAAC8990E8F903988 + 4452E91C4951153285D63F314101974754515E7A7DFFE04833954A85921F352D + 4DE56F4747C9935D3DFD600941AC4D50584860938CF49C6DAD6D9D6075404C88 + CAC5C5A9BBCC6891435B47F74057574F0136265E296929A9F67642054838696A + A8ACE9EE1D2C191B1B83FC378875C9C8C9CA7E7FE2B895BBA7F7F54C1A7D7278 + 9EBAF23A090971A1C0A04081D88709A8B8A86042595919E5BC2EAC1E181868B0 + 3D72E8BBC4A7C93D1D9D0410550442EC65CD0F5C47F3F9F9787ED4D5D1FAAEBC + B21672C0C03586DC2E79755505CBF109AA486FDF00882996B0E641455666CE51 + 3131B1856D1F3B4BA8341A417A8ED8628CF899E2E2221C3C3C5C3C24D2580D69 + 78046266E34A4A8A5B8504784DE80C860081D01B49A1525BB8B93857A92A4BDB + 1187298CC1A1E13C6C20937365A48C27C8B411713121BED1D191491A7D2A6D7C + 62021ED0E046AAF170737C2B22CCBB63884485FC36A86E80C4DD2ED6FF67436F + 8F5FE06B27331C4068908306C9957871F34C7D30363ECF9192B2B2D2960DEB56 + DE8C8A8E7B864D14241803D9C04D09314848CE84D41770B9E0A680553EC85B82 + 04595C04718CF51ECC358816C2620CDEA66C0C4DF7F54468FA41820B30C27783 + 3781E564BD07FB1945D3CA1512ACFD2234ADD78617C2E3D9F17434DD9311C6AC + 66B0487FEFAE1D9B8EDE8B882BE820748358A2BCCB79C7D51FDA09023131F140 + C8C3F272B27CE6FBCC966666BE669657565D449F65A340627A1C4D67DBE389AE + 50F20409BB78C76D485295618D03C6DACF3A5771D6FB306E5CD76E0A4D573AC0 + 67E1A18A27BB8AB23E8358E3A7B18EA9CE3ABF11D63E7031487CBBDE2FC622C7 + 3A2E1C136FAE3B867EBDEC6C56804D66ACD39AF1F3CFDC36EF3F0970A3243535 + 944F8C8F918DBB7AFBFDD1E7B22FB06E801C7075575CF70D6FC28C1798E37235 + B830205EA633B3FC66666BB299B23EB8C8E0CCD29B994293B81A2C07FA5721CC + 99AAB0F87B78090F3E3ED81E884749455971FBA6F54B6D08DDBDA3B979E57953 + 9F8919DA638E6EF9FBC6F90AF27375929FA775D6D537425A0794368192EEC88C + 3173CE18D34C5148E68CB9C1553BF0F0057E6EF8F633F785930A7E7EF85C70CD + 38BF2934ADB937737E6796747D29E288EBF571A37F552699D55E089BCC58A735 + E3773681FD3AF0D21890BE066B00AC11B03C70C507C0EF79A2FF1E0D33AE2FB6 + C17F72A25F4A06CD1CC3AFE99CCDD4EEC2FF0F3735583B907AB26499B1F67E09 + 513E9DD636024166AE2A7381B6967E7B4717232B3BEF15637212522160610812 + 62A166F4F70A5AE2F85AA5A4FE30B0C98C8DFF2B70AB0757D99DD9E8F5B7B69F + FA1FDEFB35D5DCDFEA60FFA55C34FEFA721F33090AA1DF26B399EFCD24B4FFEE + 18CFCD8556AB294BECE3E0E0576D6AEDAEC0367E863EC7C780C4C0250312FF77 + 898C8D3F006C3263838DCFC089118ABD210605AE27A88440FC0DE24D10578238 + 17B895B35E61E2AF083699B1C1C62F01D62704E061E10197E5C11712D824F627 + C5EF263336D860838DD9063699B1C1061B7F09B0C98C0D36D8F84B804D666CB0 + C1C65F02FF053C48A17721A4BE8F0000000049454E44AE426082} + ExplicitWidth = 307 + end + end + object mbpMenuPainter: TX2MenuBarmusikCubePainter + Left = 52 + Top = 460 + end + object gcMenu: TX2GraphicContainer + Left = 52 + Top = 400 + object gcMenuNetwork: TX2GraphicContainerItem + Picture.Data = { + 0954506E67496D61676589504E470D0A1A0A0000000D49484452000000100000 + 001008060000001FF3FF610000001974455874536F6674776172650041646F62 + 6520496D616765526561647971C9653C000003724944415478DA65925D881B55 + 1886DF3393F9C9CCE43F9B64D3646DBAD2CA9A25EC8FCA6AAD9845945ED46A45 + B160AFBD1111142A7BE1422F4ADB3B2FEC9D375650A9A0581171A5168B6EEBB6 + ABAD4BA536DB244DD6496693EC24994C26991F67970A053F7838EFE17CEFCBC7 + 3987BC72F612B62B1D91908AF8E0E39910CFD0872D50AF720CE10B9B0370C451 + 25165F7A3CD4B77D63D02C6E765152DA3B3EF260403AEADF27729E130EC8A1A8 + 9FE57896E072C984A6F6E018C3FE64CA7BC1A69D85BFE5F6EDFF07447D4FEE09 + 899FEF1DE553B457C4749286619A58A973F00C6CB4DC907EAB0E75E86C940DBC + 5656D4CB70DC8023677F0221645792A397A7D2422A9312200A148C7E0F3A1544 + 341C4546D0D0356C6C282D5CBC5A40B1CDDF53C03E6EDBB64CF69FBC2089C099 + 99A8F7CD0373124CCE42A13E02C61FC0C37E1629AF0C8BAE62E818E8A81E542A + 067EB95643C91E3DA39A6481E4DEFF6C7F8C505FBF91F78503231AAAAD38E870 + CE9D82C5437C19127F0B3D74A00D55E81A8D5E2384DFAFD7B0BCCED55A74F045 + 927DFBE31313012CCC6503C4A4C720C592E024061CCB20C914216F5521866440 + AC41EBEBD0FF8963ED5A173F5C19D8AA90788F8CBE7EFA53511F1E9DCD6591CE + A4DD661E9C206072AC0756BC02AA3B8D96B18636B382AD660FE804F0D7551B4B + CB40D71FFF888C1C5EFC5030D9B77213FBE078DD0B0CFAB02BE1C1CC53E7B169 + DE81408560AB49548B14EEAEC5119164DCFED3C61F450B8360F814091C3C7EE4 + 91B8F7DC4B2F2478B991415565E1F70D118C7D052E5E8294E842D233B8F573DE + 7D995150FD1A36EEB5B05E93F58DCACDA344987F2791F059E79ECF2BF3B3B949 + C8A52770B362A22AB72145563095BF08BDFC2894C2CBA029A0A134A0D464549A + E525F9D72F8E1161EE1888E33C3BBD975E9A79AC45F5B559DC58DF0DA567232A + D6313EFE09ECCE140CED19D4D50194FA261A9A6AA9851FE707E5D54B84D00C1C + 42233671E0837C7E7C716845B05A0C401B9808080431FA3B3874069A9D8565D9 + A82932DAEDD2F1FEDA37A7600E40F05F118ADE33F5F4C991DDB9774B4D1FD187 + 8EFB174430661B96638130222CA3AE37ABAB8BFDD2F5D3DBE61DDB7DBBC7C5EF + 12A5C5F041269279CEE293599A1102EE88B0CDDE96D329FD66B6EE9EB77B5BDF + BB7DBA8BF160C0F6CAB8B02E94BB0B81F38DB952D839756C0D46E78EAB9AF7FB + 4D177B5BFC0B55A17E80C406E83B0000000049454E44AE426082} + PictureName = 'Network' + end + object gcMenuSettings: TX2GraphicContainerItem + Picture.Data = { + 0954506E67496D61676589504E470D0A1A0A0000000D49484452000000100000 + 001008060000001FF3FF610000001974455874536F6674776172650041646F62 + 6520496D616765526561647971C9653C000003694944415478DAA5535B4B5B59 + 18FD8E8D471DAD9A88B7073371B48A29464783566311A361C64AAC17DA07AB33 + B5047D0803BE445F06A90AFAD2CE8B0E8322320F4E6929091DC641686BD1DADA + 3651ABE265A03ADE62A246BC908B47134DD7B6307F60367CECB3F7F9F6FAD65E + DFDA9CDFEFA7FF333883C170F1717E7E9E2E914806222222FEC57888B5592C16 + 7FEDF17834818181C73299EC8348245ADEDDDD259EE7093917F11F0063C271DC + 775555557FB95C2ECFD0D090BABEBE9EC2C3C3ABD6D7D76F5BAD36A97DDBF658 + 383E36A088636565E50B407373B3F2ECEC6C3220208070902F2929F9585C5C2C + 6F6969B9AF52A9DAF2F3F309556582703A2D96448BDFBF1B7F2B081E806EEC2E + 2F2F13D7DDDD3D2108C22B2CBA9292927A6A6A6AEECECECED2E0E0602358F58D + 8C8C90DBEDA6A2A2A2675D5D0F6E7ABD5E329BDF3E1F1F7F5DEA72B9CFB9F6F6 + F69F2B2A2A3A3636363EA5A6A65E595858A0E1E16156F52900EAA6A6A64E0070 + EFEA55F92F4A654EC4B759B9F8FF3771E433399D4E3DD7D4D4244E4E4EFE53AB + D55E9F9F9F2793C9E4D3E974A2E0E060EAEFEF7F343A3A3AA6D7EBBB2113DFD1 + D1D19B9090205164E4DEAAACD492C9F8E40FA60141E9709FCFF7231043434242 + C6D56A75576666E6F5CECE4E522A959491912120EF278BC5D25F5858182FFB26 + C522783CA17EBFF736D7DADA4A27272784C3B4B3B3437B7B7BAC1B0AB4CC8C56 + 0661A68383832D87C3A10A0B0B5BCFCACAA2FDFDFD4CECF1E890992B2828B8E8 + 2B13676D6D8D8E8E8E2EA14D03A85A67B3D93830A2B2B232DADADAFA677B7BFB + 4E6262E2F4D1E1217D420700082D308044300BF3020FF3FC8AC3BACDCD4DB25A + AD2F413DB7BCBCFC32B461450E2323238DE8FFEF28F4064C195B8EE04086238D + 8A8AEA494F4FD7E220CDCDCDFD161D1DADCFCBCBD3A5A5A5F5C2131CBB2ABB26 + 3473CECCCCA8E19D49C620202626E687949494B6F8F878295C478B8B8B7D3055 + 2314A7ECEC6C8A8D8D1DA8AEAEAEAFADADBD706C434303D9EDF63668749F3190 + 48A5D245B95C1E8B4D5A5D5D7D017A3700EC63EE6420A5A5A51A8542F1DC6834 + 52505010E5E4E4D0D2D29201851E300697B05906FA8F98EA30900AF31C7B5F08 + 2F7B701099D768347D305A1DBB32C4B58C8D8D5560B633009E25A15DDFE3E765 + 08F59A554738116E8408F11522342E2EEE1A7244283281F7E3C0DEE9672AB3AE + 908E05275B0000000049454E44AE426082} + PictureName = 'Settings' + end + object gcMenuMaplist: TX2GraphicContainerItem + Picture.Data = { + 0954506E67496D61676589504E470D0A1A0A0000000D49484452000000100000 + 001008060000001FF3FF610000001974455874536F6674776172650041646F62 + 6520496D616765526561647971C9653C000003A04944415478DA95937B4C9307 + 14C5CFB796AFA52F692B4529485B0A6D815A90ADC34D5166D0D869B4A2602466 + 8B31BA910C2DAF08211D1BB09A0D22B0D155A3B8EC01616C197BD03DD0093240 + 8856104460BCBADA025B27052BD53AE8EA24D9FEDD494E727392FBCB496E2E21 + 080E8E1647840B7BAE5BAE30480ACADFAD84EEE4491C3A9881F62B97932814CA + 72DA818CDE33D53578BBAC0CFAE2623CD1FAF5AA946987DD4E94E8F51734FBD2 + 8F345E345554567FF096E19D327761513199B67B67D1AE03997AA552B97CFEFD + 8A5253DD2786C2C2535E83E134E7D5CC747D81BE34B7B1BEE13C519097537BFB + 617056B43C06FB372BF05383A9992B8ADB3B3C074C385C48506F04339086A430 + 1ABEAAABFA9A1BA1DC239210580A1060BCE7A691C8CF3951314597E55A170848 + A552C4AD0DC437AD1DA0D099E0AD62431AFB1CDA06ED38B4250C49CCFBB8D4FE + 2544B15438ED1B601B68AB240A74D9EFD998B179AE67D8888854805C9CC5D0D8 + 24A8241D3C46000E6BB7C13C7C0FC5BBE4B0F7F5A1EB7A3942A5C970DC4BC068 + 5753C50A2026CF0536C4D172303C4EF48D4C804A25FDD529389EB11D12018948 + 3E1FCDE6CFD0D95587E5C8C3080F17C061BEFC5F000BA22805688B4E5886C640 + D268F03EF641F9FC0BC8DEBA0652010F9F36E9706B9884359405655408DCDF8E + FE0B98F3B1102A9683E65DC0F86F763CFACB072E9382EAEC3D0863317167E67B + F474B6E1527F101E89294891A660DAFCF90A801193F7FB92BF816203F60AAD20 + 9D373047AC068F2741CA965458263BF1C0DB8291DB8968B1F4831DC5C56E792A + FABEB8F01430E507581FF3519EBE062A8F195787BDF0112418340652B5895842 + 3B684C250C1FF1D174AB11EA6725D82FDA89EF1A3EAE20F275D9FE332A726D08 + 83493B0B2EC146B75305167512ABC8566C4A8E816FE60688052F5A262478B375 + 10DA140DD4BC04981BCF5512A7F2736A7BDD2159F33431EA5F1382ED99C6A0B5 + 03748E0BF39E7828138F82A4CE602DBD0323BD3771D56AC303C651847082D0FF + 73B391282BD157A976649EB8F8E3008EA99DF02C4F020F47E1451A82383288E3 + A2D137B68078F19F70DD35A1BB630242D90E6C7AF1083EAC395345F8FF82D46C + 7FE98D83AFBC9E15AFE24BE6DD77F0C77428C67E75DCADA9395DBA9ACB85AEA8 + A468E3E69888F1A11E5806DCE004CC4FD5D79B8DDDD77EA97E0208F67B9DDF3E + 61E83AF5B1E359FB8CC6DA1F66676D6DFECC83A70A9445C992352F6B3567CFD6 + 362F7AEE5F5BC96DC4CA40F17B09FF4FFFECFC0D7E6266877474632A00000000 + 49454E44AE426082} + PictureName = 'Maplist' + end + object gcMenuGames: TX2GraphicContainerItem + Picture.Data = { + 0954506E67496D61676589504E470D0A1A0A0000000D49484452000000100000 + 001008060000001FF3FF610000001974455874536F6674776172650041646F62 + 6520496D616765526561647971C9653C000003774944415478DA6D936D681C45 + 1CC69FD999DDBDDDCBEE5D2E977B69628E9C2FB13DD120B6123FF8428D118C20 + 0811514A2D05418A118456ECD7227E11D40F0A155A8A08C6422C624B6D418DC1 + A8215A9236973631E99D3963CF332F97DEE56EF776679C8B82FDE02E0FB3CCF2 + FFF19FE7FF0C397AE67B341F852A60948110E88AA20CB4E8DA80A9B33BE537B6 + 9CC6FC66CD392F84B8C0B9703DDF03F7F9761DB91540294B04187D336105F7A5 + DAC3A164A4054640C36AB586E97C71BDB0BA79CAF7F85B3EF74AFF0748EB847D + 1133CD4C47C4422C1244341C841DD451763C4CE58A98C917C13C77DA17788673 + 9EFB0F4060C32717359FEE09991AA221131DD1103AE33622B681DC7A15DF64F3 + A8AC9711330DAC37BC898AE33CA11052254746BF2310E430AFE16D2249864A11 + B10CA4E2217448B5CB63CCACAC612A9B43C2D0B0A32D0222BD9A5CCA0DBBBEFF + 3E797DE4EB0C383D8D06DD09088900021212B2B55A6F3A3EA7690C130BBF672C + 4AF574228636DB826D9A189B9BBF922DAC0C91E14F2EEE67D4F848218C09698C + 7419BEDFE0830FA4BEBA27ACFE28047079DD7DA8CEB5FE9E8E841C0A85AE01BF + 2C16DCB1D96B07C8A18F2F1C3583F6314D0D40700990050A77DCC303F79D387B + 66F45D8528CAE34F3DFDEA786EE34026D5A9C91942650AAE166E88B199EC11F2 + F28973AF45A2EDEF5896AD34FB571805EA556F30DD3A92E9BEED6CD3E999A5DF + 062F95EA435DC904633228014DC5C2F20D3E317B7598ECFFF0F3FEC48EE4A7C9 + CE8E48D303267F860D869B8B0BB9BEEEE4946C08E3D7F2BBF57822C598064BD7 + 6119015C59C8972E2FE69F23CFBF37625B96F541EFEEDE1754594C657BCDD506 + 477979B9E1FB40C3B0D5C2C65F6891FB21C380267D989C9E3BB571B37A88EC3B + FEA534CDBB379DEEFAA167D75D26171C32B2F00401956FADE661AD5C4365B308 + 95B8B00D13A5E26A35B7FCC783942AB32433F0AC4C21436ACFA307FBFAF71EEF + BEA38B788D065C57C07139EA32855E83C371EA70EB6BA86C6CF2EB73F3071582 + 938490EDB16F2752358262D79343AFEC7DF1A56377DFDFDB4AA906997B09F125 + CCC7D6561D4BB33FFF79E9DCE81BD9F39F9D14DCFFA7F05F00930A4985CDB6C4 + C3B7F73D36D0D3F7C84E3B1A8FCA5C8872A958FA75727CFAFA4FDF9EAE94569A + 97A726E5DC0A68AEAA94DEBC575241A33516570D534285F09C7A796BB55890FB + 153447257D95DABE8E7F031B867709CA0697DA0000000049454E44AE426082} + PictureName = 'Games' + end + object gcMenuAbout: TX2GraphicContainerItem + Picture.Data = { + 0954506E67496D61676589504E470D0A1A0A0000000D49484452000000100000 + 001008060000001FF3FF610000001974455874536F6674776172650041646F62 + 6520496D616765526561647971C9653C0000026F4944415478DA8D924D6B5A41 + 1885E7AAB954442A8424245015419B450A75E1221535260529A268115AA1AD95 + 84D08F4DFF407F43BB6921A1E0A22E0AD185A42B95FA8504C1EFAEDC88554308 + D184C68026516FCF88266D256D065EEEBD33F73C73E6CCCBACACAC90EB8C7EBF + 4FF87CFEBD6EB7DB6418A6C4E3F106F3CC7500548CA1379BCD9BCD66733F9148 + B85896AD00F47F0015A3F40E87634BA9544EC3058946A3C5582C6605E4C73F01 + 54CC711C157F99C5F07ABDDF452211EB72B96E87C3E19D542AB57E2500428273 + 6A607B5B2291CC0402819DBDBDBDE70B0B0B1F4C26D3FD743A7D94CBE51E5D09 + E8F57A646A6AEA9D4EA77B23954A49241289B55AAD03A7D3E90806831C00ABC8 + E0F31880EE0CB104693370FD7E6D6DED199D2F140A8482F2F97C1FD65FC1DDC6 + 5888F4CC58D06BB5DA8F489BB5582CF24EA733E1F7FB89502824383F07C00B08 + 37A9F88F6B1CA56DB7DBB7262727A7E96E87878704E2B3DDDDDD00E6D8E3E3E3 + AF70F66924BE00FC9E36029BC52E442E9713844470EE6AA3D1B88B7F8FA88036 + 904020B8042C2F2F131035369B6D7B06C3E7F37DAB56AB1180DEAAD56AB6DD6E + EF178BC53B101ED01EC03781A3415603C0D2D212999B9BDB70BBDDEBA150A88D + FB7DA8D1681C56AB7515CDC265B3D955083D5458AFD749AD5623E7E7E7970E0C + 06030DE8C1FCFCBCDF68340A4BA5D24FDCF5CD783CDECB6432AF11E206DDF16F + E10500ED481DD07ABCB8B8E8D1EBF53792C924877E7F89C61988211CA5C68D01 + 50132816C1F4140AC553954AF5A45C2E47E1C4837E10D29E429DA2DAC327AD33 + 7A7123001F456365C462314F2693DDAA542A8D9393136EB8D61F42BAC31ABD0F + DCFC024FCA3EDB163AAD5A0000000049454E44AE426082} + PictureName = 'About' + end + end + object glMenu: TX2GraphicList + Container = gcMenu + Convert = False + Left = 112 + Top = 400 + Bitmap = {} + end + object gcToolbar: TX2GraphicContainer + Left = 52 + Top = 340 + object gcToolbaradd: TX2GraphicContainerItem + Picture.Data = { + 0954506E67496D61676589504E470D0A1A0A0000000D49484452000000100000 + 001008060000001FF3FF6100000A0669545874584D4C3A636F6D2E61646F6265 + 2E786D7000000000003C3F787061636B657420626567696E3D22EFBBBF222069 + 643D2257354D304D7043656869487A7265537A4E54637A6B633964223F3E0A3C + 783A786D706D65746120786D6C6E733A783D2261646F62653A6E733A6D657461 + 2F2220783A786D70746B3D2241646F626520584D5020436F726520352E302D63 + 3036302036312E3133343737372C20323031302F30322F31322D31373A33323A + 30302020202020202020223E0A203C7264663A52444620786D6C6E733A726466 + 3D22687474703A2F2F7777772E77332E6F72672F313939392F30322F32322D72 + 64662D73796E7461782D6E7323223E0A20203C7264663A446573637269707469 + 6F6E207264663A61626F75743D22220A20202020786D6C6E733A786D70526967 + 6874733D22687474703A2F2F6E732E61646F62652E636F6D2F7861702F312E30 + 2F7269676874732F220A20202020786D6C6E733A64633D22687474703A2F2F70 + 75726C2E6F72672F64632F656C656D656E74732F312E312F220A20202020786D + 6C6E733A4970746334786D70436F72653D22687474703A2F2F697074632E6F72 + 672F7374642F4970746334786D70436F72652F312E302F786D6C6E732F220A20 + 202020786D6C6E733A706C75735F315F3D22687474703A2F2F6E732E75736570 + 6C75732E6F72672F6C64662F786D702F312E302F220A20202020786D6C6E733A + 786D703D22687474703A2F2F6E732E61646F62652E636F6D2F7861702F312E30 + 2F220A20202020786D6C6E733A786D704D4D3D22687474703A2F2F6E732E6164 + 6F62652E636F6D2F7861702F312E302F6D6D2F220A20202020786D6C6E733A73 + 744576743D22687474703A2F2F6E732E61646F62652E636F6D2F7861702F312E + 302F73547970652F5265736F757263654576656E7423220A202020786D705269 + 676874733A4D61726B65643D2254727565220A202020786D703A4D6574616461 + 7461446174653D22323031312D30312D32355431333A35353A31332B30313A30 + 30220A202020786D704D4D3A496E7374616E636549443D22786D702E6969643A + 3638434439343539383232384530313139383943433041314144303242354332 + 220A202020786D704D4D3A446F63756D656E7449443D22786D702E6469643A36 + 3843443934353938323238453031313938394343304131414430324235433222 + 0A202020786D704D4D3A4F726967696E616C446F63756D656E7449443D22786D + 702E6469643A3638434439343539383232384530313139383943433041314144 + 303242354332223E0A2020203C786D705269676874733A55736167655465726D + 733E0A202020203C7264663A416C743E0A20202020203C7264663A6C6920786D + 6C3A6C616E673D22782D64656661756C74223E437265617469766520436F6D6D + 6F6E73204174747269627574696F6E2D4E6F6E436F6D6D65726369616C206C69 + 63656E73653C2F7264663A6C693E0A202020203C2F7264663A416C743E0A2020 + 203C2F786D705269676874733A55736167655465726D733E0A2020203C64633A + 63726561746F723E0A202020203C7264663A5365713E0A20202020203C726466 + 3A6C693E47656E746C656661636520637573746F6D20746F6F6C626172206963 + 6F6E732064657369676E3C2F7264663A6C693E0A202020203C2F7264663A5365 + 713E0A2020203C2F64633A63726561746F723E0A2020203C64633A6465736372 + 697074696F6E3E0A202020203C7264663A416C743E0A20202020203C7264663A + 6C6920786D6C3A6C616E673D22782D64656661756C74223E576972656672616D + 65206D6F6E6F20746F6F6C6261722069636F6E733C2F7264663A6C693E0A2020 + 20203C2F7264663A416C743E0A2020203C2F64633A6465736372697074696F6E + 3E0A2020203C64633A7375626A6563743E0A202020203C7264663A4261673E0A + 20202020203C7264663A6C693E637573746F6D2069636F6E2064657369676E3C + 2F7264663A6C693E0A20202020203C7264663A6C693E746F6F6C626172206963 + 6F6E733C2F7264663A6C693E0A20202020203C7264663A6C693E637573746F6D + 2069636F6E733C2F7264663A6C693E0A20202020203C7264663A6C693E696E74 + 6572666163652064657369676E3C2F7264663A6C693E0A20202020203C726466 + 3A6C693E75692064657369676E3C2F7264663A6C693E0A20202020203C726466 + 3A6C693E6775692064657369676E3C2F7264663A6C693E0A20202020203C7264 + 663A6C693E7461736B6261722069636F6E733C2F7264663A6C693E0A20202020 + 3C2F7264663A4261673E0A2020203C2F64633A7375626A6563743E0A2020203C + 64633A7269676874733E0A202020203C7264663A416C743E0A20202020203C72 + 64663A6C6920786D6C3A6C616E673D22782D64656661756C74223E4372656174 + 69766520436F6D6D6F6E73204174747269627574696F6E2D4E6F6E436F6D6D65 + 726369616C206C6963656E73653C2F7264663A6C693E0A202020203C2F726466 + 3A416C743E0A2020203C2F64633A7269676874733E0A2020203C497074633478 + 6D70436F72653A43726561746F72436F6E74616374496E666F0A202020204970 + 746334786D70436F72653A436955726C576F726B3D22687474703A2F2F777777 + 2E67656E746C65666163652E636F6D222F3E0A2020203C706C75735F315F3A49 + 6D61676543726561746F723E0A202020203C7264663A5365713E0A2020202020 + 3C7264663A6C690A202020202020706C75735F315F3A496D6167654372656174 + 6F724E616D653D2267656E746C65666163652E636F6D222F3E0A202020203C2F + 7264663A5365713E0A2020203C2F706C75735F315F3A496D6167654372656174 + 6F723E0A2020203C706C75735F315F3A436F707972696768744F776E65723E0A + 202020203C7264663A5365713E0A20202020203C7264663A6C690A2020202020 + 20706C75735F315F3A436F707972696768744F776E65724E616D653D2267656E + 746C65666163652E636F6D222F3E0A202020203C2F7264663A5365713E0A2020 + 203C2F706C75735F315F3A436F707972696768744F776E65723E0A2020203C78 + 6D704D4D3A486973746F72793E0A202020203C7264663A5365713E0A20202020 + 203C7264663A6C690A20202020202073744576743A616374696F6E3D22736176 + 6564220A20202020202073744576743A696E7374616E636549443D22786D702E + 6969643A36384344393435393832323845303131393839434330413141443032 + 42354332220A20202020202073744576743A7768656E3D22323031312D30312D + 32355431333A35353A31332B30313A3030220A20202020202073744576743A63 + 68616E6765643D222F6D65746164617461222F3E0A202020203C2F7264663A53 + 65713E0A2020203C2F786D704D4D3A486973746F72793E0A20203C2F7264663A + 4465736372697074696F6E3E0A203C2F7264663A5244463E0A3C2F783A786D70 + 6D6574613E0A3C3F787061636B657420656E643D2272223F3EDB6EE5A3000000 + 1974455874536F6674776172650041646F626520496D616765526561647971C9 + 653C0000003C74455874414C545461670054686973206973207468652069636F + 6E2066726F6D2047656E746C65666163652E636F6D20667265652069636F6E73 + 207365742E20D86BE8C40000004474455874436F707972696768740043726561 + 7469766520436F6D6D6F6E73204174747269627574696F6E204E6F6E2D436F6D + 6D65726369616C204E6F2044657269766174697665737BDDB0A0000000456954 + 58744465736372697074696F6E00000000005468697320697320746865206963 + 6F6E2066726F6D2047656E746C65666163652E636F6D20667265652069636F6E + 73207365742E20BC11F81A0000004869545874436F7079726967687400000000 + 00437265617469766520436F6D6D6F6E73204174747269627574696F6E204E6F + 6E2D436F6D6D65726369616C204E6F2044657269766174697665735882CB0500 + 00013C4944415478DA9593516A834010866BC0878060EB434010142482609078 + 023D41C85172829A13E42C39817B02A9F8E083041404C107AB20F82068678B86 + E826743BB0FC3BB33BDF8C2BC3BCFDC32CCB727DDF771F630C4DA2699A976118 + AEABD5CAEBFBDE6118E61004C16906300CE31BE4FD21AF828BC7300CD16EB7B3 + 01E0818F406D5007C767005DD78745611445910371DCF227F6619DC7BD8DF770 + EEDE019AA62D0115543BC6718CB6DB2DAEEA818F4071370E8ECF3A50557509C0 + F675BBDDF6707681C4EBF8190EE801E2F3379065F929204DD3FDE4288AE22649 + F2FC2F4892F40CF00B19F5946519827B365602208AE22BC0DDA637C8F39C2100 + 9BCDE64FC064455190004110A801655992009EE7A901755D93008EE3A8014DD3 + 9080F57A4D0D68DB9604B02C4B0DE8BA8E04C0A42D87E9955530911F93F30370 + 1C8C11C5F7C3AE0000000049454E44AE426082} + PictureName = 'add' + end + object gcToolbarremove: TX2GraphicContainerItem + Picture.Data = { + 0954506E67496D61676589504E470D0A1A0A0000000D49484452000000100000 + 001008060000001FF3FF6100000A0669545874584D4C3A636F6D2E61646F6265 + 2E786D7000000000003C3F787061636B657420626567696E3D22EFBBBF222069 + 643D2257354D304D7043656869487A7265537A4E54637A6B633964223F3E0A3C + 783A786D706D65746120786D6C6E733A783D2261646F62653A6E733A6D657461 + 2F2220783A786D70746B3D2241646F626520584D5020436F726520352E302D63 + 3036302036312E3133343737372C20323031302F30322F31322D31373A33323A + 30302020202020202020223E0A203C7264663A52444620786D6C6E733A726466 + 3D22687474703A2F2F7777772E77332E6F72672F313939392F30322F32322D72 + 64662D73796E7461782D6E7323223E0A20203C7264663A446573637269707469 + 6F6E207264663A61626F75743D22220A20202020786D6C6E733A786D70526967 + 6874733D22687474703A2F2F6E732E61646F62652E636F6D2F7861702F312E30 + 2F7269676874732F220A20202020786D6C6E733A64633D22687474703A2F2F70 + 75726C2E6F72672F64632F656C656D656E74732F312E312F220A20202020786D + 6C6E733A4970746334786D70436F72653D22687474703A2F2F697074632E6F72 + 672F7374642F4970746334786D70436F72652F312E302F786D6C6E732F220A20 + 202020786D6C6E733A706C75735F315F3D22687474703A2F2F6E732E75736570 + 6C75732E6F72672F6C64662F786D702F312E302F220A20202020786D6C6E733A + 786D703D22687474703A2F2F6E732E61646F62652E636F6D2F7861702F312E30 + 2F220A20202020786D6C6E733A786D704D4D3D22687474703A2F2F6E732E6164 + 6F62652E636F6D2F7861702F312E302F6D6D2F220A20202020786D6C6E733A73 + 744576743D22687474703A2F2F6E732E61646F62652E636F6D2F7861702F312E + 302F73547970652F5265736F757263654576656E7423220A202020786D705269 + 676874733A4D61726B65643D2254727565220A202020786D703A4D6574616461 + 7461446174653D22323031312D30312D32355431333A35353A31332B30313A30 + 30220A202020786D704D4D3A496E7374616E636549443D22786D702E6969643A + 4244373243393539383232384530313139383943433041314144303242354332 + 220A202020786D704D4D3A446F63756D656E7449443D22786D702E6469643A42 + 4437324339353938323238453031313938394343304131414430324235433222 + 0A202020786D704D4D3A4F726967696E616C446F63756D656E7449443D22786D + 702E6469643A4244373243393539383232384530313139383943433041314144 + 303242354332223E0A2020203C786D705269676874733A55736167655465726D + 733E0A202020203C7264663A416C743E0A20202020203C7264663A6C6920786D + 6C3A6C616E673D22782D64656661756C74223E437265617469766520436F6D6D + 6F6E73204174747269627574696F6E2D4E6F6E436F6D6D65726369616C206C69 + 63656E73653C2F7264663A6C693E0A202020203C2F7264663A416C743E0A2020 + 203C2F786D705269676874733A55736167655465726D733E0A2020203C64633A + 63726561746F723E0A202020203C7264663A5365713E0A20202020203C726466 + 3A6C693E47656E746C656661636520637573746F6D20746F6F6C626172206963 + 6F6E732064657369676E3C2F7264663A6C693E0A202020203C2F7264663A5365 + 713E0A2020203C2F64633A63726561746F723E0A2020203C64633A6465736372 + 697074696F6E3E0A202020203C7264663A416C743E0A20202020203C7264663A + 6C6920786D6C3A6C616E673D22782D64656661756C74223E576972656672616D + 65206D6F6E6F20746F6F6C6261722069636F6E733C2F7264663A6C693E0A2020 + 20203C2F7264663A416C743E0A2020203C2F64633A6465736372697074696F6E + 3E0A2020203C64633A7375626A6563743E0A202020203C7264663A4261673E0A + 20202020203C7264663A6C693E637573746F6D2069636F6E2064657369676E3C + 2F7264663A6C693E0A20202020203C7264663A6C693E746F6F6C626172206963 + 6F6E733C2F7264663A6C693E0A20202020203C7264663A6C693E637573746F6D + 2069636F6E733C2F7264663A6C693E0A20202020203C7264663A6C693E696E74 + 6572666163652064657369676E3C2F7264663A6C693E0A20202020203C726466 + 3A6C693E75692064657369676E3C2F7264663A6C693E0A20202020203C726466 + 3A6C693E6775692064657369676E3C2F7264663A6C693E0A20202020203C7264 + 663A6C693E7461736B6261722069636F6E733C2F7264663A6C693E0A20202020 + 3C2F7264663A4261673E0A2020203C2F64633A7375626A6563743E0A2020203C + 64633A7269676874733E0A202020203C7264663A416C743E0A20202020203C72 + 64663A6C6920786D6C3A6C616E673D22782D64656661756C74223E4372656174 + 69766520436F6D6D6F6E73204174747269627574696F6E2D4E6F6E436F6D6D65 + 726369616C206C6963656E73653C2F7264663A6C693E0A202020203C2F726466 + 3A416C743E0A2020203C2F64633A7269676874733E0A2020203C497074633478 + 6D70436F72653A43726561746F72436F6E74616374496E666F0A202020204970 + 746334786D70436F72653A436955726C576F726B3D22687474703A2F2F777777 + 2E67656E746C65666163652E636F6D222F3E0A2020203C706C75735F315F3A49 + 6D61676543726561746F723E0A202020203C7264663A5365713E0A2020202020 + 3C7264663A6C690A202020202020706C75735F315F3A496D6167654372656174 + 6F724E616D653D2267656E746C65666163652E636F6D222F3E0A202020203C2F + 7264663A5365713E0A2020203C2F706C75735F315F3A496D6167654372656174 + 6F723E0A2020203C706C75735F315F3A436F707972696768744F776E65723E0A + 202020203C7264663A5365713E0A20202020203C7264663A6C690A2020202020 + 20706C75735F315F3A436F707972696768744F776E65724E616D653D2267656E + 746C65666163652E636F6D222F3E0A202020203C2F7264663A5365713E0A2020 + 203C2F706C75735F315F3A436F707972696768744F776E65723E0A2020203C78 + 6D704D4D3A486973746F72793E0A202020203C7264663A5365713E0A20202020 + 203C7264663A6C690A20202020202073744576743A616374696F6E3D22736176 + 6564220A20202020202073744576743A696E7374616E636549443D22786D702E + 6969643A42443732433935393832323845303131393839434330413141443032 + 42354332220A20202020202073744576743A7768656E3D22323031312D30312D + 32355431333A35353A31332B30313A3030220A20202020202073744576743A63 + 68616E6765643D222F6D65746164617461222F3E0A202020203C2F7264663A53 + 65713E0A2020203C2F786D704D4D3A486973746F72793E0A20203C2F7264663A + 4465736372697074696F6E3E0A203C2F7264663A5244463E0A3C2F783A786D70 + 6D6574613E0A3C3F787061636B657420656E643D2272223F3E99BFDFFC000000 + 1974455874536F6674776172650041646F626520496D616765526561647971C9 + 653C0000003C74455874414C545461670054686973206973207468652069636F + 6E2066726F6D2047656E746C65666163652E636F6D20667265652069636F6E73 + 207365742E20D86BE8C40000004474455874436F707972696768740043726561 + 7469766520436F6D6D6F6E73204174747269627574696F6E204E6F6E2D436F6D + 6D65726369616C204E6F2044657269766174697665737BDDB0A0000000456954 + 58744465736372697074696F6E00000000005468697320697320746865206963 + 6F6E2066726F6D2047656E746C65666163652E636F6D20667265652069636F6E + 73207365742E20BC11F81A0000004869545874436F7079726967687400000000 + 00437265617469766520436F6D6D6F6E73204174747269627574696F6E204E6F + 6E2D436F6D6D65726369616C204E6F2044657269766174697665735882CB0500 + 00013D4944415478DAA592416A84301486ABA028828C0B176E840A820A428FD0 + DEA41EC193B43798DCA0D313CC11145DB8112CB8115C98A520689FA9719C4C1C + 5AFA433079F9DF97C77B0A0FFF9440374F204110CEB0FD9AA6E9254D53CC9A37 + 9E539224D10A08C3905CC03ACC6700A43324CFF315C2F1A02CCB22020882A0A3 + 175414521405F67DFF2A79E3792700CFF392B942B6E4051243E2079BBCE807E0 + BAEE018C671EE48E505996D1DA44C771FE024155555D9A4865DBF66F20A8AEEB + E8668C5496653D2FA3BA11C031ACC7A6693017609A269D33AF6154643A6DDBE2 + 2B806118DC51ED5442205DD76102D075FDDECB78274E2004A0695AB7F3328278 + BCD758889F08405194237C5ED9E4BEEF49B75555E54E07E097FF4092A42D040D + C3106DCDB22CB390083C4860886F4B6931AF79A228CE9023F83EC7714473EC1B + 6CD9A8AA24D266B50000000049454E44AE426082} + PictureName = 'remove' + end + end + object glToolbar: TX2GraphicList + Container = gcToolbar + Left = 112 + Top = 340 + Bitmap = {} + end + object alMain: TActionList + Images = glToolbar + Left = 52 + Top = 288 + object actGameAdd: TAction + Caption = '&Add game' + ImageIndex = 0 + OnExecute = actGameAddExecute + end + object actGameRemove: TAction + Caption = '&Remove game' + Enabled = False + ImageIndex = 1 + OnExecute = actGameRemoveExecute + end + end +end diff --git a/source/view/Forms.Main.pas b/source/view/Forms.Main.pas new file mode 100644 index 0000000..b710851 --- /dev/null +++ b/source/view/Forms.Main.pas @@ -0,0 +1,502 @@ +unit Forms.Main; + +interface +uses + System.Bindings.Expression, + System.Classes, + System.Generics.Collections, + Vcl.ComCtrls, + Vcl.Controls, + Vcl.ExtCtrls, + Vcl.Forms, + Vcl.Imaging.pngimage, + Vcl.ImgList, + Vcl.Mask, + Vcl.StdCtrls, + Vcl.ToolWin, + + JvExControls, + JvExMask, + JvGradient, + JvGroupHeader, + JvSpin, + VirtualTrees, + X2CLGraphicList, + X2CLMenuBar, + X2CLmusikCubeMenuBarPainter, + + Game.Base, + Game.Intf, Vcl.ActnList; + + +type + TMainForm = class(TForm) + edtMessageOfTheDay: TEdit; + edtServerName: TEdit; + gbPorts: TGroupBox; + gbServerName: TGroupBox; + gcMenu: TX2GraphicContainer; + gcMenuAbout: TX2GraphicContainerItem; + gcMenuGames: TX2GraphicContainerItem; + gcMenuMaplist: TX2GraphicContainerItem; + gcMenuNetwork: TX2GraphicContainerItem; + gcMenuSettings: TX2GraphicContainerItem; + gcToolbar: TX2GraphicContainer; + gcToolbaradd: TX2GraphicContainerItem; + gcToolbarremove: TX2GraphicContainerItem; + glMenu: TX2GraphicList; + glToolbar: TX2GraphicList; + grdMenu: TJvGradient; + imgGamesWarning: TImage; + imgLogo: TImage; + lblChivalry: TLabel; + lblPixelophilia: TLabel; + lblGamesWarning: TLabel; + lblGentleface: TLabel; + lblJCL: TLabel; + lblMessageOfTheDay: TLabel; + lblPeerPort: TLabel; + lblQueryPort: TLabel; + lblServerName: TLabel; + lblServerPort: TLabel; + lblVirtualTreeview: TLabel; + llChivalry: TLinkLabel; + llPixelophilia: TLinkLabel; + llGentleface: TLinkLabel; + llPixelophiliaCC: TLinkLabel; + llGentlefaceCC: TLinkLabel; + llJCL: TLinkLabel; + llVirtualTreeview: TLinkLabel; + mbMenu: TX2MenuBar; + mbpMenuPainter: TX2MenuBarmusikCubePainter; + pcMain: TPageControl; + pnlLogo: TPanel; + pnlGamesWarning: TPanel; + sePeerPort: TJvSpinEdit; + seQueryPort: TJvSpinEdit; + seServerPort: TJvSpinEdit; + shpMenu: TShape; + tbGames: TToolBar; + tbGameAdd: TToolButton; + tbGameRemove: TToolButton; + tsAbout: TTabSheet; + tsConfiguration: TTabSheet; + tsGames: TTabSheet; + tsMapList: TTabSheet; + tsNetwork: TTabSheet; + vstMapList: TVirtualStringTree; + VirtualStringTree2: TVirtualStringTree; + alMain: TActionList; + actGameAdd: TAction; + actGameRemove: TAction; + lblSuperObject: TLabel; + llSuperObject: TLinkLabel; + + procedure FormCreate(Sender: TObject); + procedure FormDestroy(Sender: TObject); + procedure mbMenuCollapsing(Sender: TObject; Group: TX2MenuBarGroup; var Allowed: Boolean); + procedure mbMenuSelectedChanged(Sender: TObject; Item: TX2CustomMenuBarItem); + procedure llLinkClick(Sender: TObject; const Link: string; LinkType: TSysLinkType); + procedure SpinEditChange(Sender: TObject); + procedure EditChange(Sender: TObject); + procedure actGameAddExecute(Sender: TObject); + procedure actGameRemoveExecute(Sender: TObject); + private type + TBindingExpressionList = TList; + TPageMenuMap = TDictionary; + private + FActiveGame: TCustomGame; + FPageMenuMap: TPageMenuMap; + FUIBindings: TBindingExpressionList; + + procedure SetActiveGame(const Value: TCustomGame); + protected + procedure ActiveGameChanged; + + procedure ClearUIBindings; + procedure Bind(const APropertyName: string; ADestObject: TObject; const ADestPropertyName: string); + procedure BindGameNetwork; + procedure BindGameName; + procedure BindGameMapList; + procedure UpdateMenu; + + property ActiveGame: TCustomGame read FActiveGame write SetActiveGame; + property PageMenuMap: TPageMenuMap read FPageMenuMap; + property UIBindings: TBindingExpressionList read FUIBindings; + end; + + +implementation +uses + System.Bindings.Helper, + System.Math, + System.StrUtils, + System.SysUtils, + System.Types, + Vcl.Graphics, + Vcl.GraphUtil, + Vcl.Themes, + Winapi.ShellAPI, + Winapi.Windows, + + X2UtGraphics, + + Forms.Game, + Game.Chivalry.MedievalWarfare, + Game.List, + Persist.GameList; + + +type + TINIHintWindow = class(THintWindow) + protected + function IsINIHint(const AHint: string): Boolean; + function GetINIHint(const AHint: string; out ASection, AKey: string): Boolean; + + procedure Paint; override; + public + function CalcHintRect(MaxWidth: Integer; const AHint: string; AData: Pointer): TRect; override; + end; + + +const + INIHintPrefix = 'INI:'; + INIHintSeparator = '>'; + + +{$R *.dfm} + + +{ TMainForm } +procedure TMainForm.FormCreate(Sender: TObject); +var + lightBtnFace: TColor; + pageIndex: Integer; + menuGroup: TX2MenuBarGroup; + menuItem: TX2MenuBarItem; +// game: TCustomGame; + +begin + FUIBindings := TBindingExpressionList.Create; + FPageMenuMap := TPageMenuMap.Create(pcMain.PageCount); + + + { Configure pages } + for pageIndex := 0 to Pred(pcMain.PageCount) do + pcMain.Pages[pageIndex].TabVisible := False; + + pageIndex := 0; + + for menuGroup in mbMenu.Groups do + for menuItem in menuGroup.Items do + begin + Assert(pageIndex < pcMain.PageCount); + + FPageMenuMap.Add(pcMain.Pages[pageIndex], menuItem); + menuItem.Tag := pageIndex; + Inc(pageIndex); + end; + + + { Eye-candy } + lightBtnFace := BlendColors(clBtnFace, clWindow, 196); + 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; + + + { Initialize menu } + mbpMenuPainter.GroupColors.Hot.Assign(mbpMenuPainter.GroupColors.Normal); + + mbMenu.SelectFirst; +end; + + +procedure TMainForm.FormDestroy(Sender: TObject); +begin + ClearUIBindings; + + FreeAndNil(FPageMenuMap); + FreeAndNil(FUIBindings); +end; + + +procedure TMainForm.ActiveGameChanged; +begin + ClearUIBindings; + + // #ToDo1 -oMvR: 30-6-2014: attach observer to monitor changes + + if Supports(ActiveGame, IGameNetwork) then + BindGameNetwork; + + if Supports(ActiveGame, IGameName) then + BindGameName; + + if Supports(ActiveGame, IGameMapList) then + BindGameMapList; + + UpdateMenu; +end; + + +procedure TMainForm.ClearUIBindings; +var + binding: TBindingExpression; + +begin + for binding in UIBindings do + TBindings.RemoveBinding(binding); + + UIBindings.Clear; +end; + + +procedure TMainForm.Bind(const APropertyName: string; ADestObject: TObject; const ADestPropertyName: string); +begin + { Source -> Destination } + UIBindings.Add(TBindings.CreateManagedBinding( + [TBindings.CreateAssociationScope([Associate(ActiveGame, 'src')])], + 'src.' + APropertyName, + + [TBindings.CreateAssociationScope([Associate(ADestObject, 'dst')])], + 'dst.' + ADestPropertyName, + + nil, nil, [coNotifyOutput, coEvaluate])); + + { Destination -> Source } + UIBindings.Add(TBindings.CreateManagedBinding( + [TBindings.CreateAssociationScope([Associate(ADestObject, 'src')])], + 'src.' + ADestPropertyName, + + [TBindings.CreateAssociationScope([Associate(ActiveGame, 'dst')])], + 'dst.' + APropertyName, + + nil, nil, [coNotifyOutput])); +end; + + +procedure TMainForm.BindGameNetwork; +begin + Bind('ServerPort', seServerPort, 'Value'); + Bind('PeerPort', sePeerPort, 'Value'); + Bind('QueryPort', seQueryPort, 'Value'); +end; + + +procedure TMainForm.BindGameName; +begin + Bind('ServerName', edtServerName, 'Text'); + Bind('MessageOfTheDay', edtMessageOfTheDay, 'Text'); +end; + + +procedure TMainForm.BindGameMapList; +begin + // #ToDo1 -oMvR: 30-6-2014: load map list +end; + + +procedure TMainForm.UpdateMenu; + + procedure EnablePageByInterface(APage: TTabSheet; AInterface: TGUID); + begin + PageMenuMap[APage].Enabled := Supports(ActiveGame, AInterface); + end; + +begin + EnablePageByInterface(tsNetwork, IGameNetwork); + EnablePageByInterface(tsConfiguration, IGameName); + EnablePageByInterface(tsMapList, IGameMapList); + + if Assigned(mbMenu.SelectedItem) and (not mbMenu.SelectedItem.Enabled) then + mbMenu.SelectFirst; +end; + + +procedure TMainForm.SetActiveGame(const Value: TCustomGame); +begin + if Value <> FActiveGame then + begin + FActiveGame := Value; + ActiveGameChanged; + end; +end; + + +procedure TMainForm.mbMenuCollapsing(Sender: TObject; Group: TX2MenuBarGroup; var Allowed: Boolean); +begin + Allowed := False; +end; + + +procedure TMainForm.mbMenuSelectedChanged(Sender: TObject; Item: TX2CustomMenuBarItem); +begin + pcMain.ActivePageIndex := Item.Tag; +end; + + +procedure TMainForm.llLinkClick(Sender: TObject; const Link: string; LinkType: TSysLinkType); +begin + ShellExecute(0, 'open', PChar(Link), nil, nil, SW_SHOWNORMAL); +end; + + +procedure TMainForm.SpinEditChange(Sender: TObject); +begin + TBindings.Notify(Sender, 'Value'); +end; + + +procedure TMainForm.EditChange(Sender: TObject); +begin + TBindings.Notify(Sender, 'Text'); +end; + + +procedure TMainForm.actGameAddExecute(Sender: TObject); +var + game: TCustomGame; + +begin + if TGameForm.Insert(Self, game) then + begin + // + end; +end; + + +procedure TMainForm.actGameRemoveExecute(Sender: TObject); +begin + // +end; + + +{ TINIHintWindow } +function TINIHintWindow.CalcHintRect(MaxWidth: Integer; const AHint: string; AData: Pointer): TRect; +var + section: string; + key: string; + sectionRect: TRect; + +begin + if GetINIHint(AHint, section, key) then + begin + Canvas.Font.Style := [fsBold]; + try + sectionRect := inherited CalcHintRect(MaxWidth, section, AData); + finally + Canvas.Font.Style := []; + end; + + Result := inherited CalcHintRect(MaxWidth, key, AData); + + Result.Right := Max(Result.Right, sectionRect.Right); + Inc(Result.Bottom, RectHeight(sectionRect)); + end else + Result := inherited CalcHintRect(MaxWidth, AHint, AData); +end; + + +procedure TINIHintWindow.Paint; +var + section: string; + key: string; + textRect: TRect; + clipRect: TRect; + elementColor: TColor; + elementDetails: TThemedElementDetails; + gradientStart: TColor; + gradientEnd: TColor; + textColor: TColor; + +begin + if GetINIHint(Caption, section, key) then + begin + textRect := ClientRect; + textColor := Screen.HintFont.Color; + + if StyleServices.Enabled then + begin + clipRect := textRect; + InflateRect(textRect, 4, 4); + if TOSVersion.Check(6) and StyleServices.IsSystemStyle then + begin + // Paint Windows gradient background + StyleServices.DrawElement(Canvas.Handle, StyleServices.GetElementDetails(tttStandardNormal), textRect, clipRect); + end else + begin + elementDetails := StyleServices.GetElementDetails(thHintNormal); + if StyleServices.GetElementColor(elementDetails, ecGradientColor1, elementColor) and (elementColor <> clNone) then + gradientStart := elementColor + else + gradientStart := clInfoBk; + if StyleServices.GetElementColor(elementDetails, ecGradientColor2, elementColor) and (elementColor <> clNone) then + gradientEnd := elementColor + else + gradientEnd := clInfoBk; + if StyleServices.GetElementColor(elementDetails, ecTextColor, elementColor) and (elementColor <> clNone) then + textColor := elementColor + else + textColor := Screen.HintFont.Color; + GradientFillCanvas(Canvas, gradientStart, gradientEnd, textRect, gdVertical); + end; + + textRect := clipRect; + end; + + Inc(textRect.Left, 2); + Inc(textRect.Top, 2); + + Canvas.Font.Color := textColor; + Canvas.Font.Style := [fsBold]; + try + DrawText(Canvas.Handle, section, -1, textRect, DT_LEFT or DT_NOPREFIX or DT_WORDBREAK or DrawTextBiDiModeFlagsReadingOnly); + Inc(textRect.Top, Canvas.TextHeight(section) + 2); + finally + Canvas.Font.Style := []; + end; + + DrawText(Canvas.Handle, key, -1, textRect, DT_LEFT or DT_NOPREFIX or DT_WORDBREAK or DrawTextBiDiModeFlagsReadingOnly); + end else + inherited Paint; +end; + + +function TINIHintWindow.IsINIHint(const AHint: string): Boolean; +begin + Result := AnsiStartsText(INIHintPrefix, AHint); +end; + + +function TINIHintWindow.GetINIHint(const AHint: string; out ASection, AKey: string): Boolean; +var + hint: string; + separatorPos: Integer; + +begin + Result := IsINIHint(AHint); + if Result then + begin + hint := Copy(AHint, Succ(Length(INIHintPrefix)), MaxInt); + ASection := ''; + AKey := hint; + + separatorPos := Pos(INIHintSeparator, hint); + if separatorPos > 0 then + begin + ASection := hint; + SetLength(ASection, Pred(separatorPos)); + Delete(AKey, 1, Pred(separatorPos) + Length(INIHintSeparator)); + end; + end; +end; + + +initialization + HintWindowClass := TINIHintWindow; + +end.