382 lines
10 KiB
Plaintext
382 lines
10 KiB
Plaintext
(*
|
|
* CDDL HEADER START
|
|
*
|
|
* The contents of this file are subject to the terms of the
|
|
* Common Development and Distribution License, Version 1.0 only
|
|
* (the "License"). You may not use this file except in compliance
|
|
* with the License.
|
|
*
|
|
* You can obtain a copy of the license at
|
|
* http://www.opensource.org/licenses/cddl1.php.
|
|
* See the License for the specific language governing permissions
|
|
* and limitations under the License.
|
|
*
|
|
* When distributing Covered Code, include this CDDL HEADER in each
|
|
* file and include the License file at
|
|
* http://www.opensource.org/licenses/cddl1.php. If applicable,
|
|
* add the following below this CDDL HEADER, with the fields enclosed
|
|
* by brackets "[]" replaced with your own identifying * information:
|
|
* Portions Copyright [yyyy] [name of copyright owner]
|
|
*
|
|
* CDDL HEADER END
|
|
*
|
|
*
|
|
* Portions Copyright 2013 Andreas Schneider
|
|
*)
|
|
unit UConfig;
|
|
|
|
{$mode objfpc}{$H+}
|
|
|
|
interface
|
|
|
|
uses
|
|
Classes, SysUtils, DOM, XMLRead, XMLWrite, Keyboard, UAccount, UXmlHelper,
|
|
UInterfaces, UEnums, URegions, UMapManagement;
|
|
|
|
type
|
|
|
|
TInvalidConfigException = class(Exception);
|
|
|
|
{ TMapInfo }
|
|
|
|
TMapInfo = class(TObject, ISerializable)
|
|
constructor Create(AOwner: IInvalidate);
|
|
constructor Deserialize(AOwner: IInvalidate; AElement: TDOMElement);
|
|
procedure Serialize(AElement: TDOMElement);
|
|
protected
|
|
FOwner: IInvalidate;
|
|
FMapFile: string;
|
|
FStaticsFile: string;
|
|
FStaIdxFile: string;
|
|
FWidth: Word;
|
|
FHeight: Word;
|
|
procedure SetHeight(const AValue: Word);
|
|
procedure SetMapFile(const AValue: string);
|
|
procedure SetStaIdxFile(const AValue: string);
|
|
procedure SetStaticsFile(const AValue: string);
|
|
procedure SetWidth(const AValue: Word);
|
|
public
|
|
property MapFile: string read FMapFile write SetMapFile;
|
|
property StaticsFile: string read FStaticsFile write SetStaticsFile;
|
|
property StaIdxFile: string read FStaIdxFile write SetStaIdxFile;
|
|
property Width: Word read FWidth write SetWidth;
|
|
property Height: Word read FHeight write SetHeight;
|
|
end;
|
|
|
|
{ TConfig }
|
|
|
|
TConfig = class(TObject, ISerializable, IInvalidate)
|
|
constructor Create(AFilename: string);
|
|
constructor Init(AFilename: string);
|
|
destructor Destroy; override;
|
|
procedure Serialize(AElement: TDOMElement);
|
|
protected
|
|
FFilename: string;
|
|
FPort: Integer;
|
|
FMap: TMapInfo;
|
|
FTiledata: string;
|
|
FRadarcol: string;
|
|
FRegions: TRegionList;
|
|
FAccounts: TAccountList;
|
|
FMapStates: TMapStates;
|
|
FChanged: Boolean;
|
|
procedure SetPort(const AValue: Integer);
|
|
procedure SetRadarcol(const AValue: string);
|
|
procedure SetTiledata(const AValue: string);
|
|
public
|
|
property Port: Integer read FPort write SetPort;
|
|
property Map: TMapInfo read FMap;
|
|
property Tiledata: string read FTiledata write SetTiledata;
|
|
property Radarcol: string read FRadarcol write SetRadarcol;
|
|
property Regions: TRegionList read FRegions;
|
|
property Accounts: TAccountList read FAccounts;
|
|
property MapStates: TMapStates read FMapStates;
|
|
procedure Flush;
|
|
procedure Invalidate;
|
|
end;
|
|
|
|
var
|
|
AppDir: string;
|
|
ConfigFile: string;
|
|
Config: TConfig;
|
|
|
|
function TimeStamp: string;
|
|
|
|
implementation
|
|
|
|
const
|
|
CONFIGVERSION = 3;
|
|
|
|
function QueryPassword: String;
|
|
var
|
|
pwChar: char;
|
|
begin
|
|
Result := '';
|
|
|
|
InitKeyboard;
|
|
try
|
|
repeat
|
|
pwChar := GetKeyEventChar(TranslateKeyEvent(GetKeyEvent));
|
|
case pwChar of
|
|
#8: Result := Copy(Result, 1, Length(Result) - 1);
|
|
#13: break;
|
|
else
|
|
Result := Result + pwChar;
|
|
end;
|
|
until pwChar = #13;
|
|
finally
|
|
DoneKeyboard;
|
|
end;
|
|
writeln('');
|
|
end;
|
|
|
|
function TimeStamp: string;
|
|
begin
|
|
Result := '[' + DateTimeToStr(Now) + '] ';
|
|
end;
|
|
|
|
{ TMapInfo }
|
|
|
|
constructor TMapInfo.Create(AOwner: IInvalidate);
|
|
begin
|
|
inherited Create;
|
|
FOwner := AOwner;
|
|
end;
|
|
|
|
constructor TMapInfo.Deserialize(AOwner: IInvalidate; AElement: TDOMElement);
|
|
begin
|
|
Create(AOwner);
|
|
FMapFile := TXmlHelper.ReadString(AElement, 'Map', 'map0.mul');
|
|
FStaIdxFile := TXmlHelper.ReadString(AElement, 'StaIdx', 'staidx0.mul');
|
|
FStaticsFile := TXmlHelper.ReadString(AElement, 'Statics', 'statics0.mul');
|
|
FWidth := TXmlHelper.ReadInteger(AElement, 'Width', 768);
|
|
FHeight := TXmlHelper.ReadInteger(AElement, 'Height', 512);
|
|
end;
|
|
|
|
procedure TMapInfo.Serialize(AElement: TDOMElement);
|
|
begin
|
|
TXmlHelper.WriteString(AElement, 'Map', FMapFile);
|
|
TXmlHelper.WriteString(AElement, 'StaIdx', FStaIdxFile);
|
|
TXmlHelper.WriteString(AElement, 'Statics', FStaticsFile);
|
|
TXmlHelper.WriteInteger(AElement, 'Width', FWidth);
|
|
TXmlHelper.WriteInteger(AElement, 'Height', FHeight);
|
|
end;
|
|
|
|
procedure TMapInfo.SetHeight(const AValue: Word);
|
|
begin
|
|
FHeight := AValue;
|
|
FOwner.Invalidate;
|
|
end;
|
|
|
|
procedure TMapInfo.SetMapFile(const AValue: string);
|
|
begin
|
|
FMapFile := AValue;
|
|
FOwner.Invalidate;
|
|
end;
|
|
|
|
procedure TMapInfo.SetStaIdxFile(const AValue: string);
|
|
begin
|
|
FStaIdxFile := AValue;
|
|
FOwner.Invalidate;
|
|
end;
|
|
|
|
procedure TMapInfo.SetStaticsFile(const AValue: string);
|
|
begin
|
|
FStaticsFile := AValue;
|
|
FOwner.Invalidate;
|
|
end;
|
|
|
|
procedure TMapInfo.SetWidth(const AValue: Word);
|
|
begin
|
|
FWidth := AValue;
|
|
FOwner.Invalidate;
|
|
end;
|
|
|
|
{ TConfig }
|
|
|
|
constructor TConfig.Create(AFilename: string);
|
|
var
|
|
xmlDoc: TXMLDocument;
|
|
version: Integer;
|
|
xmlElement: TDOMElement;
|
|
begin
|
|
inherited Create;
|
|
FFilename := AFilename;
|
|
ReadXMLFile(xmlDoc, AFilename);
|
|
version := 0;
|
|
if not ((xmlDoc.DocumentElement.NodeName = 'CEDConfig') and
|
|
TryStrToInt(xmlDoc.DocumentElement.AttribStrings['Version'], version) and
|
|
(version = CONFIGVERSION)) then
|
|
raise TInvalidConfigException.Create(Format('Version mismatch: %d <> %d', [version, CONFIGVERSION]));
|
|
|
|
FPort := TXmlHelper.ReadInteger(xmlDoc.DocumentElement, 'Port', 2597);
|
|
|
|
xmlElement := TDOMElement(xmlDoc.DocumentElement.FindNode('Map'));
|
|
if not Assigned(xmlElement) then
|
|
raise TInvalidConfigException.Create('Map information not found');
|
|
FMap := TMapInfo.Deserialize(Self, xmlElement);
|
|
|
|
FTiledata := TXmlHelper.ReadString(xmlDoc.DocumentElement, 'Tiledata', 'tiledata.mul');
|
|
FRadarcol := TXmlHelper.ReadString(xmlDoc.DocumentElement, 'Radarcol', 'radarcol.mul');
|
|
|
|
xmlElement := TDOMElement(xmlDoc.DocumentElement.FindNode('Regions'));
|
|
if Assigned(xmlElement) then
|
|
FRegions := TRegionList.Deserialize(Self, xmlElement)
|
|
else
|
|
FRegions := TRegionList.Create(Self);
|
|
|
|
xmlElement := TDOMElement(xmlDoc.DocumentElement.FindNode('Accounts'));
|
|
if not Assigned(xmlElement) then
|
|
raise TInvalidConfigException.Create('Account information not found');
|
|
FAccounts := TAccountList.Deserialize(Self, xmlElement);
|
|
|
|
xmlElement := TDOMElement(xmlDoc.DocumentElement.FindNode('MapStates'));
|
|
if Assigned(xmlElement) then
|
|
FMapStates := TMapStates.Deserialize(Self, xmlElement)
|
|
else
|
|
FMapStates := TMapStates.Create(Self);
|
|
|
|
xmlDoc.Free;
|
|
|
|
FChanged := False;
|
|
end;
|
|
|
|
constructor TConfig.Init(AFilename: string);
|
|
var
|
|
stringValue, password: string;
|
|
intValue: Integer;
|
|
begin
|
|
inherited Create;
|
|
FFilename := AFilename;
|
|
FMap := TMapInfo.Create(Self);
|
|
FAccounts := TAccountList.Create(Self);
|
|
FRegions := TRegionList.Create(Self);
|
|
FMapStates := TMapStates.Create(Self);
|
|
|
|
Writeln('Configuring Network');
|
|
Writeln('===================');
|
|
Write ('Port [2597]: ');
|
|
Readln (stringValue);
|
|
intValue := 0;
|
|
if not TryStrToInt(stringValue, intValue) then intValue := 2597;
|
|
FPort := intValue;
|
|
Writeln('');
|
|
|
|
Writeln('Configuring Paths');
|
|
Writeln('=================');
|
|
Write ('map [map0.mul]: ');
|
|
Readln (FMap.FMapFile);
|
|
if FMap.MapFile = '' then FMap.MapFile := 'map0.mul';
|
|
Write ('statics [statics0.mul]: ');
|
|
Readln (FMap.FStaticsFile);
|
|
if FMap.StaticsFile = '' then FMap.StaticsFile := 'statics0.mul';
|
|
Write ('staidx [staidx0.mul]: ');
|
|
Readln (FMap.FStaIdxFile);
|
|
if FMap.StaIdxFile = '' then FMap.StaIdxFile := 'staidx0.mul';
|
|
Write ('tiledata [tiledata.mul]: ');
|
|
Readln (FTiledata);
|
|
if FTiledata = '' then FTiledata := 'tiledata.mul';
|
|
Write ('radarcol [radarcol.mul]: ');
|
|
Readln (FRadarcol);
|
|
if FRadarcol = '' then FRadarcol := 'radarcol.mul';
|
|
Writeln('');
|
|
|
|
Writeln('Parameters');
|
|
Writeln('==========');
|
|
Write ('Map width [768]: ');
|
|
Readln (stringValue);
|
|
if not TryStrToInt(stringValue, intValue) then intValue := 768;
|
|
FMap.Width := intValue;
|
|
Write ('Map height [512]: ');
|
|
Readln (stringValue);
|
|
if not TryStrToInt(stringValue, intValue) then intValue := 512;
|
|
FMap.Height := intValue;
|
|
Writeln('');
|
|
|
|
Writeln('Admin account');
|
|
Writeln('=============');
|
|
repeat
|
|
Write('Account name: ');
|
|
Readln(stringValue);
|
|
until stringValue <> '';
|
|
Write ('Password [hidden]: ');
|
|
password := QueryPassword;
|
|
FAccounts.Add(TAccount.Create(FAccounts, stringValue, password,
|
|
alAdministrator, nil));
|
|
|
|
FChanged := True;
|
|
end;
|
|
|
|
destructor TConfig.Destroy;
|
|
begin
|
|
if Assigned(FMap) then FreeAndNil(FMap);
|
|
if Assigned(FAccounts) then FreeAndNil(FAccounts);
|
|
if Assigned(FRegions) then FreeAndNil(FRegions);
|
|
if Assigned(FMapStates) then FreeAndNil(FMapStates);
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TConfig.Serialize(AElement: TDOMElement);
|
|
begin
|
|
TXmlHelper.WriteInteger(AElement, 'Port', FPort);
|
|
FMap.Serialize(TXmlHelper.AssureElement(AElement, 'Map'));
|
|
TXmlHelper.WriteString(AElement, 'Tiledata', FTiledata);
|
|
TXmlHelper.WriteString(AElement, 'Radarcol', FRadarcol);
|
|
FAccounts.Serialize(TXmlHelper.AssureElement(AElement, 'Accounts'));
|
|
FRegions.Serialize(TXmlHelper.AssureElement(AElement, 'Regions'));
|
|
FMapStates.Serialize(TXmlHelper.AssureElement(AElement, 'MapStates'));
|
|
end;
|
|
|
|
procedure TConfig.SetPort(const AValue: Integer);
|
|
begin
|
|
FPort := AValue;
|
|
Invalidate;
|
|
end;
|
|
|
|
procedure TConfig.SetRadarcol(const AValue: string);
|
|
begin
|
|
FRadarcol := AValue;
|
|
Invalidate;
|
|
end;
|
|
|
|
procedure TConfig.SetTiledata(const AValue: string);
|
|
begin
|
|
FTiledata := AValue;
|
|
Invalidate;
|
|
end;
|
|
|
|
procedure TConfig.Flush;
|
|
var
|
|
xmlDoc: TXMLDocument;
|
|
begin
|
|
if FChanged then
|
|
begin
|
|
xmlDoc := TXMLDocument.Create;
|
|
xmlDoc.AppendChild(xmlDoc.CreateElement('CEDConfig'));
|
|
xmlDoc.DocumentElement.AttribStrings['Version'] := IntToStr(CONFIGVERSION);
|
|
Serialize(xmlDoc.DocumentElement);
|
|
WriteXMLFile(xmlDoc, FFilename);
|
|
xmlDoc.Free;
|
|
FChanged := False;
|
|
end;
|
|
end;
|
|
|
|
procedure TConfig.Invalidate;
|
|
begin
|
|
FChanged := True;
|
|
end;
|
|
|
|
initialization
|
|
begin
|
|
AppDir := ExtractFilePath(ParamStr(0));
|
|
if AppDir[Length(AppDir)] <> PathDelim then
|
|
AppDir := AppDir + PathDelim;
|
|
|
|
{TODO : add command line parameter to specify the config}
|
|
Config := nil;
|
|
ConfigFile := ChangeFileExt(ParamStr(0), '.xml');
|
|
end;
|
|
|
|
end.
|
|
|