Statistics
| Branch: | Tag: | Revision:

root / Server / UConfig.pas @ 13:c78b5eafa10e

History | View | Annotate | Download (10 kB)

1
(*
2
 * CDDL HEADER START
3
 *
4
 * The contents of this file are subject to the terms of the
5
 * Common Development and Distribution License, Version 1.0 only
6
 * (the "License").  You may not use this file except in compliance
7
 * with the License.
8
 *
9
 * You can obtain a copy of the license at
10
 * http://www.opensource.org/licenses/cddl1.php.
11
 * See the License for the specific language governing permissions
12
 * and limitations under the License.
13
 *
14
 * When distributing Covered Code, include this CDDL HEADER in each
15
 * file and include the License file at
16
 * http://www.opensource.org/licenses/cddl1.php.  If applicable,
17
 * add the following below this CDDL HEADER, with the fields enclosed
18
 * by brackets "[]" replaced with your own identifying * information:
19
 *      Portions Copyright [yyyy] [name of copyright owner]
20
 *
21
 * CDDL HEADER END
22
 *
23
 *
24
 *      Portions Copyright 2008 Andreas Schneider
25
 *)
26
unit UConfig;
27
28
{$mode objfpc}{$H+}
29
30
interface
31
32
uses
33
  Classes, SysUtils, DOM, XMLRead, XMLWrite, md5, Keyboard, UAccount,
34
  UXmlHelper, UInterfaces, UEnums, URegions;
35
36
type
37
38
  TInvalidConfigException = class(Exception);
39
40
  { TMapInfo }
41
42
  TMapInfo = class(TObject, ISerializable)
43
    constructor Create(AOwner: IInvalidate);
44
    constructor Deserialize(AOwner: IInvalidate; AElement: TDOMElement);
45
    procedure Serialize(AElement: TDOMElement);
46
  protected
47
    FOwner: IInvalidate;
48
    FMapFile: string;
49
    FStaticsFile: string;
50
    FStaIdxFile: string;
51
    FWidth: Word;
52
    FHeight: Word;
53
    procedure SetHeight(const AValue: Word);
54
    procedure SetMapFile(const AValue: string);
55
    procedure SetStaIdxFile(const AValue: string);
56
    procedure SetStaticsFile(const AValue: string);
57
    procedure SetWidth(const AValue: Word);
58
  public
59
    property MapFile: string read FMapFile write SetMapFile;
60
    property StaticsFile: string read FStaticsFile write SetStaticsFile;
61
    property StaIdxFile: string read FStaIdxFile write SetStaIdxFile;
62
    property Width: Word read FWidth write SetWidth;
63
    property Height: Word read FHeight write SetHeight;
64
  end;
65
66
  { TConfig }
67
68
  TConfig = class(TObject, ISerializable, IInvalidate)
69
    constructor Create(AFilename: string);
70
    constructor Init(AFilename: string);
71
    destructor Destroy; override;
72
    procedure Serialize(AElement: TDOMElement);
73
  protected
74
    FFilename: string;
75
    FPort: Integer;
76
    FMap: TMapInfo;
77
    FTiledata: string;
78
    FRadarcol: string;
79
    FRegions: TRegionList;
80
    FAccounts: TAccountList;
81
    FChanged: Boolean;
82
    procedure SetPort(const AValue: Integer);
83
    procedure SetRadarcol(const AValue: string);
84
    procedure SetTiledata(const AValue: string);
85
  public
86
    property Port: Integer read FPort write SetPort;
87
    property Map: TMapInfo read FMap;
88
    property Tiledata: string read FTiledata write SetTiledata;
89
    property Radarcol: string read FRadarcol write SetRadarcol;
90
    property Regions: TRegionList read FRegions;
91
    property Accounts: TAccountList read FAccounts;
92
    procedure Flush;
93
    procedure Invalidate;
94
  end;
95
  
96
var
97
  AppDir: string;
98
  ConfigFile: string;
99
  Config: TConfig;
100
  
101
function TimeStamp: string;
102
103
implementation
104
105
const
106
  CONFIGVERSION = 3;
107
  
108
function QueryPassword: String;
109
var
110
  pwChar: char;
111
begin
112
  Result := '';
113
114
  InitKeyboard;
115
  try
116
    repeat
117
      pwChar := GetKeyEventChar(TranslateKeyEvent(GetKeyEvent));
118
      case pwChar of
119
        #8: Result := Copy(Result, 1, Length(Result) - 1);
120
        #13: break;
121
      else
122
        Result := Result + pwChar;
123
      end;
124
    until pwChar = #13;
125
  finally
126
    DoneKeyboard;
127
  end;
128
  writeln('');
129
end;
130
131
function TimeStamp: string;
132
begin
133
  Result := '[' + DateTimeToStr(Now) + '] ';
134
end;
135
136
{ TMapInfo }
137
138
constructor TMapInfo.Create(AOwner: IInvalidate);
139
begin
140
  inherited Create;
141
  FOwner := AOwner;
142
end;
143
144
constructor TMapInfo.Deserialize(AOwner: IInvalidate; AElement: TDOMElement);
145
begin
146
  Create(AOwner);
147
  FMapFile := TXmlHelper.ReadString(AElement, 'Map', 'map0.mul');
148
  FStaIdxFile := TXmlHelper.ReadString(AElement, 'StaIdx', 'staidx0.mul');
149
  FStaticsFile := TXmlHelper.ReadString(AElement, 'Statics', 'statics0.mul');
150
  FWidth := TXmlHelper.ReadInteger(AElement, 'Width', 768);
151
  FHeight := TXmlHelper.ReadInteger(AElement, 'Height', 512);
152
end;
153
154
procedure TMapInfo.Serialize(AElement: TDOMElement);
155
begin
156
  TXmlHelper.WriteString(AElement, 'Map', FMapFile);
157
  TXmlHelper.WriteString(AElement, 'StaIdx', FStaIdxFile);
158
  TXmlHelper.WriteString(AElement, 'Statics', FStaticsFile);
159
  TXmlHelper.WriteInteger(AElement, 'Width', FWidth);
160
  TXmlHelper.WriteInteger(AElement, 'Height', FHeight);
161
end;
162
163
procedure TMapInfo.SetHeight(const AValue: Word);
164
begin
165
  FHeight := AValue;
166
  FOwner.Invalidate;
167
end;
168
169
procedure TMapInfo.SetMapFile(const AValue: string);
170
begin
171
  FMapFile := AValue;
172
  FOwner.Invalidate;
173
end;
174
175
procedure TMapInfo.SetStaIdxFile(const AValue: string);
176
begin
177
  FStaIdxFile := AValue;
178
  FOwner.Invalidate;
179
end;
180
181
procedure TMapInfo.SetStaticsFile(const AValue: string);
182
begin
183
  FStaticsFile := AValue;
184
  FOwner.Invalidate;
185
end;
186
187
procedure TMapInfo.SetWidth(const AValue: Word);
188
begin
189
  FWidth := AValue;
190
  FOwner.Invalidate;
191
end;
192
193
{ TConfig }
194
195
constructor TConfig.Create(AFilename: string);
196
var
197
  xmlDoc: TXMLDocument;
198
  version: Integer;
199
  xmlElement: TDOMElement;
200
begin
201
  inherited Create;
202
  FFilename := AFilename;
203
  ReadXMLFile(xmlDoc, AFilename);
204
  version := 0;
205
  if not ((xmlDoc.DocumentElement.NodeName = 'CEDConfig') and
206
    TryStrToInt(xmlDoc.DocumentElement.AttribStrings['Version'], version) and
207
    (version = CONFIGVERSION)) then
208
    raise TInvalidConfigException.Create(Format('Version mismatch: %d <> %d', [version, CONFIGVERSION]));
209
210
  FPort := TXmlHelper.ReadInteger(xmlDoc.DocumentElement, 'Port', 2597);
211
212
  xmlElement := TDOMElement(xmlDoc.DocumentElement.FindNode('Map'));
213
  if not assigned(xmlElement) then
214
    raise TInvalidConfigException.Create('Map information not found');
215
  FMap := TMapInfo.Deserialize(Self, xmlElement);
216
  
217
  FTiledata := TXmlHelper.ReadString(xmlDoc.DocumentElement, 'Tiledata', 'tiledata.mul');
218
  FRadarcol := TXmlHelper.ReadString(xmlDoc.DocumentElement, 'Radarcol', 'radarcol.mul');
219
220
  xmlElement := TDOMElement(xmlDoc.DocumentElement.FindNode('Regions'));
221
  if assigned(xmlElement) then
222
    FRegions := TRegionList.Deserialize(Self, xmlElement)
223
  else
224
    Fregions := TRegionList.Create(Self);
225
226
  xmlElement := TDOMElement(xmlDoc.DocumentElement.FindNode('Accounts'));
227
  if not assigned(xmlElement) then
228
    raise TInvalidConfigException.Create('Account information not found');
229
  FAccounts := TAccountList.Deserialize(Self, xmlElement);
230
231
  xmlDoc.Free;
232
  
233
  FChanged := False;
234
end;
235
236
constructor TConfig.Init(AFilename: string);
237
var
238
  stringValue, password: string;
239
  intValue: Integer;
240
begin
241
  inherited Create;
242
  FFilename := AFilename;
243
  FMap := TMapInfo.Create(Self);
244
  FAccounts := TAccountList.Create(Self);
245
  FRegions := TRegionList.Create(Self);
246
  
247
  Writeln('Configuring Network');
248
  Writeln('===================');
249
  Write  ('Port [2597]: ');
250
  Readln (stringValue);
251
  intValue := 0;
252
  if not TryStrToInt(stringValue, intValue) then intValue := 2597;
253
  FPort := intValue;
254
  Writeln('');
255
256
  Writeln('Configuring Paths');
257
  Writeln('=================');
258
  Write  ('map [map0.mul]: ');
259
  Readln (FMap.MapFile);
260
  if FMap.MapFile = '' then FMap.MapFile := 'map0.mul';
261
  Write  ('statics [statics0.mul]: ');
262
  Readln (FMap.StaticsFile);
263
  if FMap.StaticsFile = '' then FMap.StaticsFile := 'statics0.mul';
264
  Write  ('staidx [staidx0.mul]: ');
265
  Readln (FMap.StaIdxFile);
266
  if FMap.StaIdxFile = '' then FMap.StaIdxFile := 'staidx0.mul';
267
  Write  ('tiledata [tiledata.mul]: ');
268
  Readln (FTiledata);
269
  if FTiledata = '' then FTiledata := 'tiledata.mul';
270
  Write  ('radarcol [radarcol.mul]: ');
271
  Readln (FRadarcol);
272
  if FRadarcol = '' then FRadarcol := 'radarcol.mul';
273
  Writeln('');
274
275
  Writeln('Parameters');
276
  Writeln('==========');
277
  Write  ('Map width [768]: ');
278
  Readln (stringValue);
279
  if not TryStrToInt(stringValue, intValue) then intValue := 768;
280
  FMap.Width := intValue;
281
  Write  ('Map height [512]: ');
282
  Readln (stringValue);
283
  if not TryStrToInt(stringValue, intValue) then intValue := 512;
284
  FMap.Height := intValue;
285
  Writeln('');
286
287
  Writeln('Admin account');
288
  Writeln('=============');
289
  repeat
290
    Write('Account name: ');
291
    Readln(stringValue);
292
  until stringValue <> '';
293
  Write  ('Password [hidden]: ');
294
  password := QueryPassword;
295
  FAccounts.Add(TAccount.Create(FAccounts, stringValue,
296
    MD5Print(MD5String(password)), alAdministrator, nil));
297
  
298
  FChanged := True;
299
end;
300
301
destructor TConfig.Destroy;
302
begin
303
  if Assigned(FMap) then FreeAndNil(FMap);
304
  if Assigned(FAccounts) then FreeAndNil(FAccounts);
305
  if Assigned(FRegions) then FreeAndNil(FRegions);
306
  inherited Destroy;
307
end;
308
309
procedure TConfig.Serialize(AElement: TDOMElement);
310
begin
311
  TXmlHelper.WriteInteger(AElement, 'Port', FPort);
312
  FMap.Serialize(TXmlHelper.AssureElement(AElement, 'Map'));
313
  TXmlHelper.WriteString(AElement, 'Tiledata', FTiledata);
314
  TXmlHelper.WriteString(AElement, 'Radarcol', FRadarcol);
315
  FAccounts.Serialize(TXmlHelper.AssureElement(AElement, 'Accounts'));
316
  FRegions.Serialize(TXmlHelper.AssureElement(AElement, 'Regions'));
317
end;
318
319
procedure TConfig.SetPort(const AValue: Integer);
320
begin
321
  FPort := AValue;
322
  Invalidate;
323
end;
324
325
procedure TConfig.SetRadarcol(const AValue: string);
326
begin
327
  FRadarcol := AValue;
328
  Invalidate;
329
end;
330
331
procedure TConfig.SetTiledata(const AValue: string);
332
begin
333
  FTiledata := AValue;
334
  Invalidate;
335
end;
336
337
procedure TConfig.Flush;
338
var
339
  xmlDoc: TXMLDocument;
340
begin
341
  if FChanged then
342
  begin
343
    xmlDoc := TXMLDocument.Create;
344
    xmlDoc.AppendChild(xmlDoc.CreateElement('CEDConfig'));
345
    xmlDoc.DocumentElement.AttribStrings['Version'] := IntToStr(CONFIGVERSION);
346
    Serialize(xmlDoc.DocumentElement);
347
    WriteXMLFile(xmlDoc, FFilename);
348
    xmlDoc.Free;
349
    FChanged := False;
350
  end;
351
end;
352
353
procedure TConfig.Invalidate;
354
begin
355
  FChanged := True;
356
end;
357
358
initialization
359
begin
360
  AppDir := ExtractFilePath(ParamStr(0));
361
  if AppDir[Length(AppDir)] <> PathDelim then
362
    AppDir := AppDir + PathDelim;
363
    
364
  {TODO : add command line parameter to specify the config}
365
  Config := nil;
366
  ConfigFile := ChangeFileExt(ParamStr(0), '.xml');
367
end;
368
369
end.
370