From b9a45bf43befd3d26a5a2286d8fb9d1afdeef582 Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Sat, 23 Nov 2013 20:41:20 +0100 Subject: [PATCH] * Enhanced UXmlHelper (enumerator) * Added UMapManagement * Fixed TCPServer to allow address reuse --- Server/UCEDServer.pas | 1 + Server/UConfig.pas | 21 ++++-- Server/UMapManagement.pas | 153 ++++++++++++++++++++++++++++++++++++++ Server/cedserver.lpi | 12 ++- UXmlHelper.pas | 41 +++++++++- 5 files changed, 221 insertions(+), 7 deletions(-) create mode 100644 Server/UMapManagement.pas diff --git a/Server/UCEDServer.pas b/Server/UCEDServer.pas index 5e35d4b..8a92a7d 100644 --- a/Server/UCEDServer.pas +++ b/Server/UCEDServer.pas @@ -113,6 +113,7 @@ begin Config.Map.StaIdxFile, Config.Tiledata, Config.Radarcol, Config.Map.Width, Config.Map.Height, FValid); FTCPServer := TLTcp.Create(nil); + FTCPServer.ReuseAddress := True; FTCPServer.OnAccept := @OnAccept; FTCPServer.OnCanSend := @OnCanSend; FTCPServer.OnDisconnect := @OnDisconnect; diff --git a/Server/UConfig.pas b/Server/UConfig.pas index 581dcaa..769e8c8 100644 --- a/Server/UConfig.pas +++ b/Server/UConfig.pas @@ -31,7 +31,7 @@ interface uses Classes, SysUtils, DOM, XMLRead, XMLWrite, Keyboard, UAccount, UXmlHelper, - UInterfaces, UEnums, URegions; + UInterfaces, UEnums, URegions, UMapManagement; type @@ -78,6 +78,7 @@ type FRadarcol: string; FRegions: TRegionList; FAccounts: TAccountList; + FMapStates: TMapStates; FChanged: Boolean; procedure SetPort(const AValue: Integer); procedure SetRadarcol(const AValue: string); @@ -89,6 +90,7 @@ type 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; @@ -210,7 +212,7 @@ begin FPort := TXmlHelper.ReadInteger(xmlDoc.DocumentElement, 'Port', 2597); xmlElement := TDOMElement(xmlDoc.DocumentElement.FindNode('Map')); - if not assigned(xmlElement) then + if not Assigned(xmlElement) then raise TInvalidConfigException.Create('Map information not found'); FMap := TMapInfo.Deserialize(Self, xmlElement); @@ -218,16 +220,22 @@ begin FRadarcol := TXmlHelper.ReadString(xmlDoc.DocumentElement, 'Radarcol', 'radarcol.mul'); xmlElement := TDOMElement(xmlDoc.DocumentElement.FindNode('Regions')); - if assigned(xmlElement) then + if Assigned(xmlElement) then FRegions := TRegionList.Deserialize(Self, xmlElement) else - Fregions := TRegionList.Create(Self); + FRegions := TRegionList.Create(Self); xmlElement := TDOMElement(xmlDoc.DocumentElement.FindNode('Accounts')); - if not assigned(xmlElement) then + 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; @@ -243,6 +251,7 @@ begin FMap := TMapInfo.Create(Self); FAccounts := TAccountList.Create(Self); FRegions := TRegionList.Create(Self); + FMapStates := TMapStates.Create(Self); Writeln('Configuring Network'); Writeln('==================='); @@ -303,6 +312,7 @@ 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; @@ -314,6 +324,7 @@ begin 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); diff --git a/Server/UMapManagement.pas b/Server/UMapManagement.pas new file mode 100644 index 0000000..75e647c --- /dev/null +++ b/Server/UMapManagement.pas @@ -0,0 +1,153 @@ +(* + * 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 UMapManagement; + +{$mode objfpc}{$H+} + +interface + +uses + Classes, SysUtils, UPacket, UInterfaces, UXmlHelper, + DOM, fgl; + +type + + { TMapState } + + TMapState = class(TObject, IInvalidate, ISerializable) + private + FOwner: IInvalidate; + FName: String; + FPath: String; + FDescription: String; + public + constructor Create(AOwner: IInvalidate); + constructor Deserialize(AOwner: IInvalidate; AElement: TDOMElement); + procedure Invalidate; + procedure Serialize(AElement: TDOMElement); + end; + + { TMapStates } + + TMapStates = class(specialize TFPGObjectList, IInvalidate, + ISerializable) + private + FOwner: IInvalidate; + public + constructor Create(AOwner: IInvalidate); + constructor Deserialize(AOwner: IInvalidate; AElement: TDOMElement); + procedure Invalidate; + procedure Serialize(AElement: TDOMElement); + + function Add(const Item: TMapState): Integer; + function Remove(const Item: TMapState): Integer; + end; + +implementation + +{ TMapState } + +constructor TMapState.Create(AOwner: IInvalidate); +begin + inherited Create; + FOwner := AOwner; +end; + +constructor TMapState.Deserialize(AOwner: IInvalidate; AElement: TDOMElement); +begin + inherited Create; + FOwner := AOwner; + FName := TXmlHelper.ReadString(AElement, 'Name', ''); + FPath := TXmlHelper.ReadString(AElement, 'Path', ''); + FDescription := TXmlHelper.ReadString(AElement, 'Description', ''); +end; + +procedure TMapState.Invalidate; +begin + FOwner.Invalidate; +end; + +procedure TMapState.Serialize(AElement: TDOMElement); +begin + TXmlHelper.WriteString(AElement, 'Name', FName); + TXmlHelper.WriteString(AElement, 'Path', FPath); + TXmlHelper.WriteString(AElement, 'Description', FDescription); +end; + +{ TMapStates } + +constructor TMapStates.Create(AOwner: IInvalidate); +begin + inherited Create(True); + FOwner := AOwner; +end; + +constructor TMapStates.Deserialize(AOwner: IInvalidate; AElement: TDOMElement); +var + nodeList: TDOMNodeList; + node: TDOMNode; +begin + inherited Create(True); + FOwner := AOwner; + for node in AElement.ChildNodes do + begin + if node.NodeName = 'MapState' then + Add(TMapState.Deserialize(Self, TDOMElement(node))); + end; +end; + +procedure TMapStates.Invalidate; +begin + FOwner.Invalidate; +end; + +procedure TMapStates.Serialize(AElement: TDOMElement); +var + mapState: TMapState; + childElement: TDOMElement; +begin + for mapState in Self do + begin + childElement := AElement.OwnerDocument.CreateElement('MapState'); + AElement.AppendChild(childElement); + mapState.Serialize(childElement); + end; +end; + +function TMapStates.Add(const Item: TMapState): Integer; +begin + Result := inherited Add(Item); + Invalidate; +end; + +function TMapStates.Remove(const Item: TMapState): Integer; +begin + Result := inherited Remove(Item); + Invalidate; +end; + +end. + diff --git a/Server/cedserver.lpi b/Server/cedserver.lpi index f1b7e70..baf86b2 100644 --- a/Server/cedserver.lpi +++ b/Server/cedserver.lpi @@ -173,7 +173,7 @@ - + @@ -254,6 +254,16 @@ + + + + + + + + + + diff --git a/UXmlHelper.pas b/UXmlHelper.pas index e23c408..2a1f42b 100644 --- a/UXmlHelper.pas +++ b/UXmlHelper.pas @@ -25,7 +25,7 @@ *) unit UXmlHelper; -{$mode delphi}{$H+} +{$mode objfpc}{$H+} interface @@ -49,8 +49,47 @@ type class function ReadCoords(AParent: TDOMElement; AName: string; out X, Y: Integer): Boolean; end; + { TDOMNodeListEnumerator } + + TDOMNodeListEnumerator = class + private + FNodeList: TDOMNodeList; + FIndex: Integer; + function GetCurrent: TDOMNode; + public + constructor Create(const ANodeList: TDOMNodeList); + function MoveNext: Boolean; + property Current: TDOMNode read GetCurrent; + end; + +operator Enumerator(const ANodeList: TDOMNodeList): TDOMNodeListEnumerator; + implementation +operator Enumerator(const ANodeList: TDOMNodeList): TDOMNodeListEnumerator; +begin + Result := TDOMNodeListEnumerator.Create(ANodeList); +end; + +{ TDOMNodeListEnumerator } + +function TDOMNodeListEnumerator.GetCurrent: TDOMNode; +begin + Result := FNodeList[FIndex]; +end; + +constructor TDOMNodeListEnumerator.Create(const ANodeList: TDOMNodeList); +begin + FNodeList := ANodeList; + FIndex := -1; +end; + +function TDOMNodeListEnumerator.MoveNext: Boolean; +begin + Inc(FIndex); + Result := FIndex < FNodeList.Count; +end; + { TXmlHelper } class function TXmlHelper.FindChild(AParent: TDOMElement; AName: string): TDOMElement;