diff --git a/Client/Tools/UfrmHueSettings.lfm b/Client/Tools/UfrmHueSettings.lfm index 74e9169..bbb9851 100644 --- a/Client/Tools/UfrmHueSettings.lfm +++ b/Client/Tools/UfrmHueSettings.lfm @@ -5,7 +5,6 @@ object frmHueSettings: TfrmHueSettings Width = 217 HorzScrollBar.Page = 216 VertScrollBar.Page = 206 - ActiveControl = lbHue BorderIcons = [] BorderStyle = bsToolWindow Caption = 'Hue Settings' @@ -15,14 +14,23 @@ object frmHueSettings: TfrmHueSettings OnClose = FormClose OnCreate = FormCreate OnDeactivate = FormDeactivate + LCLVersion = '0.9.25' object lblHue: TLabel Left = 8 - Height = 16 + Height = 12 Top = 12 - Width = 26 + Width = 27 Caption = 'Hue:' ParentColor = False end + object edHue: TEdit + Left = 48 + Height = 23 + Top = 10 + Width = 80 + OnEditingDone = edHueEditingDone + TabOrder = 0 + end object lbHue: TListBox Left = 8 Height = 160 @@ -32,14 +40,7 @@ object frmHueSettings: TfrmHueSettings OnDrawItem = lbHueDrawItem OnSelectionChange = lbHueSelectionChange Style = lbOwnerDrawFixed - TabOrder = 0 - end - object edHue: TEdit - Left = 48 - Height = 23 - Top = 10 - Width = 80 - OnEditingDone = edHueEditingDone TabOrder = 1 + TopIndex = -1 end end diff --git a/Client/Tools/UfrmHueSettings.pas b/Client/Tools/UfrmHueSettings.pas index 2e773ef..8ff6d13 100644 --- a/Client/Tools/UfrmHueSettings.pas +++ b/Client/Tools/UfrmHueSettings.pas @@ -1,156 +1,156 @@ -(* - * 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 2007 Andreas Schneider - *) -unit UfrmHueSettings; - -{$mode objfpc}{$H+} - -interface - -uses - Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, StdCtrls, - LMessages, LCLIntf, UHue; - -type - - { TfrmHueSettings } - - TfrmHueSettings = class(TForm) - edHue: TEdit; - lblHue: TLabel; - lbHue: TListBox; - procedure edHueEditingDone(Sender: TObject); - procedure FormClose(Sender: TObject; var CloseAction: TCloseAction); - procedure FormCreate(Sender: TObject); - procedure FormDeactivate(Sender: TObject); - procedure lbHueDrawItem(Control: TWinControl; Index: Integer; ARect: TRect; - State: TOwnerDrawState); - procedure lbHueSelectionChange(Sender: TObject; User: boolean); - protected - procedure MouseLeave(var msg: TLMessage); message CM_MouseLeave; - public - class procedure DrawHue(AHue: THue; ACanvas: TCanvas; ARect: TRect; - ACaption: string); - end; - -var - frmHueSettings: TfrmHueSettings; - -implementation - -uses - UGameResources, UGraphicHelper; - -{ TfrmHueSettings } - -procedure TfrmHueSettings.FormClose(Sender: TObject; - var CloseAction: TCloseAction); -begin - CloseAction := caHide; -end; - -procedure TfrmHueSettings.edHueEditingDone(Sender: TObject); -var - hueID: Integer; -begin - if (not TryStrToInt(edHue.Text, hueID)) or (hueID >= lbHue.Items.Count) then - begin - edHue.Text := Format('$%x', [lbHue.ItemIndex]); - MessageDlg('Invalid Hue', 'The hue you''ve entered is invalid.', mtWarning, [mbOK], 0); - end else - lbHue.ItemIndex := hueID; -end; - -procedure TfrmHueSettings.FormCreate(Sender: TObject); -var - i: Integer; - hue: THue; -begin - lbHue.Clear; - lbHue.Items.Add('$0 (no hue)'); - for i := 1 to ResMan.Hue.Count do - begin - hue := ResMan.Hue.Hues[i-1]; - lbHue.Items.AddObject(Format('$%x (%s)', [i, hue.Name]), hue); - end; - lbHue.ItemIndex := 0; -end; - -procedure TfrmHueSettings.FormDeactivate(Sender: TObject); -begin - Close; -end; - -procedure TfrmHueSettings.lbHueDrawItem(Control: TWinControl; Index: Integer; - ARect: TRect; State: TOwnerDrawState); -var - hue: THue; -begin - if Index > 0 then - hue := ResMan.Hue.Hues[Index-1] - else - hue := nil; - DrawHue(hue, lbHue.Canvas, ARect, lbHue.Items.Strings[Index]); -end; - -procedure TfrmHueSettings.lbHueSelectionChange(Sender: TObject; User: boolean); -begin - edHue.Text := Format('$%x', [lbHue.ItemIndex]); -end; - -procedure TfrmHueSettings.MouseLeave(var msg: TLMessage); -begin - try - if not PtInRect(ClientRect, ScreenToClient(Mouse.CursorPos)) then - Close; - except - Close; - end; -end; - -class procedure TfrmHueSettings.DrawHue(AHue: THue; ACanvas: TCanvas; ARect: TRect; - ACaption: string); -var - hueColor: TColor; - i: Integer; -begin - ACanvas.Pen.Color := clWhite; - ACanvas.Rectangle(ARect); - if AHue <> nil then - for i := 0 to 31 do - begin - hueColor := ARGB2RGB(AHue.ColorTable[i]); - ACanvas.Pen.Color := hueColor; - ACanvas.MoveTo(ARect.Left + 2 + i, ARect.Top + 1); - ACanvas.LineTo(ARect.Left + 2 + i, ARect.Bottom - 1); - end; - ACanvas.TextOut(ARect.Left + 36, ARect.Top, ACaption); -end; - -initialization - {$I UfrmHueSettings.lrs} - -end. - +(* + * 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 2007 Andreas Schneider + *) +unit UfrmHueSettings; + +{$mode objfpc}{$H+} + +interface + +uses + Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, StdCtrls, + LMessages, LCLIntf, UHue; + +type + + { TfrmHueSettings } + + TfrmHueSettings = class(TForm) + edHue: TEdit; + lblHue: TLabel; + lbHue: TListBox; + procedure edHueEditingDone(Sender: TObject); + procedure FormClose(Sender: TObject; var CloseAction: TCloseAction); + procedure FormCreate(Sender: TObject); + procedure FormDeactivate(Sender: TObject); + procedure lbHueDrawItem(Control: TWinControl; Index: Integer; ARect: TRect; + State: TOwnerDrawState); + procedure lbHueSelectionChange(Sender: TObject; User: boolean); + protected + procedure MouseLeave(var msg: TLMessage); message CM_MouseLeave; + public + class procedure DrawHue(AHue: THue; ACanvas: TCanvas; ARect: TRect; + ACaption: string); + end; + +var + frmHueSettings: TfrmHueSettings; + +implementation + +uses + UGameResources, UGraphicHelper; + +{ TfrmHueSettings } + +procedure TfrmHueSettings.FormClose(Sender: TObject; + var CloseAction: TCloseAction); +begin + CloseAction := caHide; +end; + +procedure TfrmHueSettings.edHueEditingDone(Sender: TObject); +var + hueID: Integer; +begin + if (not TryStrToInt(edHue.Text, hueID)) or (hueID >= lbHue.Items.Count) then + begin + edHue.Text := Format('$%x', [lbHue.ItemIndex]); + MessageDlg('Invalid Hue', 'The hue you''ve entered is invalid.', mtWarning, [mbOK], 0); + end else + lbHue.ItemIndex := hueID; +end; + +procedure TfrmHueSettings.FormCreate(Sender: TObject); +var + i: Integer; + hue: THue; +begin + lbHue.Clear; + lbHue.Items.Add('$0 (no hue)'); + for i := 1 to ResMan.Hue.Count do + begin + hue := ResMan.Hue.Hues[i-1]; + lbHue.Items.AddObject(Format('$%x (%s)', [i, hue.Name]), hue); + end; + lbHue.ItemIndex := 0; +end; + +procedure TfrmHueSettings.FormDeactivate(Sender: TObject); +begin + Close; +end; + +procedure TfrmHueSettings.lbHueDrawItem(Control: TWinControl; Index: Integer; + ARect: TRect; State: TOwnerDrawState); +var + hue: THue; +begin + if Index > 0 then + hue := ResMan.Hue.Hues[Index-1] + else + hue := nil; + DrawHue(hue, lbHue.Canvas, ARect, lbHue.Items.Strings[Index]); +end; + +procedure TfrmHueSettings.lbHueSelectionChange(Sender: TObject; User: boolean); +begin + edHue.Text := Format('$%x', [lbHue.ItemIndex]); +end; + +procedure TfrmHueSettings.MouseLeave(var msg: TLMessage); +begin + try + if not PtInRect(ClientRect, ScreenToClient(Mouse.CursorPos)) then + Close; + except + Close; + end; +end; + +class procedure TfrmHueSettings.DrawHue(AHue: THue; ACanvas: TCanvas; ARect: TRect; + ACaption: string); +var + hueColor: TColor; + i: Integer; +begin + ACanvas.Pen.Color := clWhite; + ACanvas.Rectangle(ARect); + if AHue <> nil then + for i := 0 to 31 do + begin + hueColor := ARGB2RGB(AHue.ColorTable[i]); + ACanvas.Pen.Color := hueColor; + ACanvas.MoveTo(ARect.Left + 2 + i, ARect.Top + 1); + ACanvas.LineTo(ARect.Left + 2 + i, ARect.Bottom - 1); + end; + ACanvas.TextOut(ARect.Left + 36, ARect.Top, ACaption); +end; + +initialization + {$I UfrmHueSettings.lrs} + +end. + diff --git a/Client/ULandscape.pas b/Client/ULandscape.pas index 8e36a1d..9082bcf 100644 --- a/Client/ULandscape.pas +++ b/Client/ULandscape.pas @@ -32,7 +32,7 @@ interface uses SysUtils, Classes, math, contnrs, LCLIntf, GL, GLU, ImagingOpenGL, Imaging, ImagingClasses, ImagingTypes, ImagingUtility, - UGenericIndex, UMap, UStatics, UArt, UTexture, UTileData, UHue, UWorldItem, + UGenericIndex, UMap, UStatics, UArt, UTexture, UTiledata, UHue, UWorldItem, UMulBlock, UListSort, UVector, UEnhancedMemoryStream, UCacheManager, ULinkedList; diff --git a/Client/UfrmLogin.lfm b/Client/UfrmLogin.lfm index 212e1d9..9d89e6d 100644 --- a/Client/UfrmLogin.lfm +++ b/Client/UfrmLogin.lfm @@ -16,8 +16,8 @@ object frmLogin: TfrmLogin Position = poScreenCenter ShowInTaskBar = stAlways object lblCopyright: TLabel - Height = 17 - Top = 248 + Height = 19 + Top = 246 Width = 489 Align = alBottom Alignment = taCenter @@ -146,6 +146,7 @@ object frmLogin: TfrmLogin 233023312332233323342335517451745174222C0A2251745174517451745174 51745174517451745174517451745174517451745174227D3B0A } + Transparent = False end object imgUsername: TImage Left = 6 @@ -237,6 +238,7 @@ object frmLogin: TfrmLogin 233123322333233423355174517451745174222C0A2251745174517451745174 51745174517451745174517451745174517451745174227D3B0A } + Transparent = False end object imgPassword: TImage Left = 6 @@ -318,6 +320,7 @@ object frmLogin: TfrmLogin 5174222C0A2251742349234A236E234B51745174517451745174517451745174 517451745174227D3B0A } + Transparent = False end object edHost: TEdit Left = 101 @@ -433,103 +436,40 @@ object frmLogin: TfrmLogin Width = 23 Color = clBtnFace Glyph.Data = { - 010C00002F2A2058504D202A2F0A7374617469632063686172202A6772617068 - 69635B5D203D207B0A223136203136203135332032222C0A222E2E2063204E6F - 6E65222C0A222E2C20632023333636424243222C0A222E2D2063202333363642 - 4242222C0A222E2A20632023333636414242222C0A222E612063202333393643 - 4243222C0A222E6220632023334236454244222C0A222E632063202333413644 - 4242222C0A222E6420632023333836424242222C0A222E652063202333453730 - 4242222C0A222E6620632023443145304636222C0A222E672063202344314530 - 4637222C0A222E6820632023463846424645222C0A222E692063202346374642 - 4645222C0A222E6A20632023463646394644222C0A222E6B2063202346304635 - 4643222C0A222E6C20632023454146304641222C0A222E6D2063202345444632 - 4642222C0A222E6E20632023463746414644222C0A222E6F2063202345424631 - 4642222C0A222E7020632023444645394638222C0A222E712063202342444430 - 4543222C0A222E7220632023354538394339222C0A222E732063202344314446 - 4636222C0A222E7420632023383041414539222C0A222E752063202346364641 - 4645222C0A222E7620632023463646414644222C0A222E772063202336343843 - 4338222C0A222E7820632023454546334642222C0A222E792063202345414631 - 4642222C0A222E7A20632023463246364643222C0A222E412063202346314636 - 4643222C0A222E4220632023453245434639222C0A222E432063202344424537 - 4638222C0A222E4420632023424144304545222C0A222E452063202344304446 - 4636222C0A222E4620632023374541384538222C0A222E472063202345394631 - 4641222C0A222E4820632023454546344642222C0A222E492063202345384630 - 4641222C0A222E4A20632023444445384638222C0A222E4B2063202344424536 - 4637222C0A222E4C20632023374141334531222C0A222E4D2063202343334435 - 4546222C0A222E4E20632023333536394237222C0A222E4F2063202343434444 - 4635222C0A222E5020632023374541384537222C0A222E512063202336363844 - 4339222C0A222E5220632023453946304641222C0A222E532063202346334638 - 4644222C0A222E5420632023463846414645222C0A222E552063202345464634 - 4643222C0A222E5620632023444645394639222C0A222E572063202344424537 - 4637222C0A222E5820632023443945354637222C0A222E592063202337384132 - 4530222C0A222E5A20632023413943324537222C0A222E302063202333353638 - 4236222C0A222E3120632023433944434634222C0A222E322063202337444137 - 4537222C0A222E3320632023453145434639222C0A222E342063202345334544 - 4639222C0A222E3520632023454546344643222C0A222E362063202346334637 - 4644222C0A222E3720632023453545444641222C0A222E382063202344384535 - 4636222C0A222E3920632023373741304445222C0A222E402063202341344245 - 4534222C0A222E2320632023333436374234222C0A222E3B2063202343374439 - 4634222C0A222E3A20632023374441364536222C0A222E3D2063202336353844 - 4339222C0A222E2B20632023363738454339222C0A222E252063202336433932 - 4342222C0A222E2420632023364439324342222C0A222E282063202336393930 - 4341222C0A222E2920632023363538434338222C0A222E5B2063202337343943 - 4441222C0A222E5D20632023394642414531222C0A222C2E2063202333343636 - 4233222C0A222C2C20632023433544384632222C0A222C2D2063202337424134 - 4533222C0A222C2A20632023374141334533222C0A222C612063202337414134 - 4533222C0A222C6220632023374241344532222C0A222C632063202337424133 - 4532222C0A222C6420632023374241334531222C0A222C652063202337394132 - 4531222C0A222C6620632023373741304446222C0A222C672063202337363946 - 4445222C0A222C6820632023373439454444222C0A222C692063202337323943 - 4442222C0A222C6A20632023373439444443222C0A222C6B2063202339414235 - 4444222C0A222C6C20632023333436354231222C0A222C6D2063202343324435 - 4632222C0A222C6E20632023373841314530222C0A222C6F2063202337353945 - 4445222C0A222C7020632023373339424441222C0A222C712063202337333942 - 4439222C0A222C7220632023393542304441222C0A222C732063202333333634 - 4146222C0A222C7420632023424544324630222C0A222C752063202337414133 - 4532222C0A222C7620632023373739464445222C0A222C772063202337363946 - 4444222C0A222C7820632023373239424439222C0A222C792063202337313939 - 4438222C0A222C7A20632023373039394436222C0A222C412063202338454142 - 4435222C0A222C4220632023333336334144222C0A222C432063202333363641 - 4241222C0A222C4420632023424244304546222C0A222C452063202337414132 - 4532222C0A222C4620632023364439364433222C0A222C472063202338414137 - 4432222C0A222C4820632023333236324142222C0A222C492063202342384345 - 4546222C0A222C4A20632023463746414645222C0A222C4B2063202338384330 - 3632222C0A222C4C20632023364139334346222C0A222C4D2063202338344133 - 4345222C0A222C4E20632023333236314141222C0A222C4F2063202333383643 - 4242222C0A222C5020632023423643434545222C0A222C512063202337414132 - 4531222C0A222C5220632023433244434246222C0A222C532063202336383930 - 4344222C0A222C5420632023383139454343222C0A222C552063202333323631 - 4138222C0A222C5620632023333736424241222C0A222C572063202342334341 - 4544222C0A222C5820632023374141324530222C0A222C592063202336353844 - 4341222C0A222C5A20632023374339424339222C0A222C302063202333313630 - 4137222C0A222C3120632023333536414241222C0A222C322063202341444336 - 4542222C0A222C3320632023414443354541222C0A222C342063202337433941 - 4338222C0A222C3520632023373939384337222C0A222C362063202333353639 - 4239222C0A222C3720632023333536394238222C0A222C382063202333353638 - 4237222C0A222C3920632023333536384235222C0A222C402063202333343636 - 4232222C0A222C2320632023333336354230222C0A222C3B2063202333333634 - 4145222C0A222C3A20632023333236334143222C0A222C3D2063202333323632 - 4141222C0A222C2B20632023333236314139222C0A222C252063202333313630 - 4138222C0A222C2420632023333136304136222C0A222C282063202333313631 - 4138222C0A222E2E2E2C2E2C2E2C2E2C2E2D2E2D2E2A2E2A2E612E622E632E64 - 2E652E2E2E2E222C0A222E2C2E662E672E682E692E6A2E6B2E6C2E6D2E6A2E6E - 2E6F2E702E712E722E2E222C0A222E2C2E732E742E752E762E772E782E792E7A - 2E682E412E422E432E442E712E65222C0A222E2C2E452E462E412E412E772E47 - 2E482E6E2E6A2E492E4A2E4B2E4C2E4D2E4E222C0A222E2C2E4F2E502E492E49 - 2E512E522E532E542E552E562E572E582E592E5A2E30222C0A222E2D2E312E32 - 2E332E332E342E352E6E2E362E372E572E582E382E392E402E23222C0A222E2D - 2E3B2E3A2E772E3D2E2B2E252E242E282E292E772E772E772E5B2E5D2C2E222C - 0A222E2A2C2C2C2D2C2A2C612C622C632C642C652C662C672C682C692C6A2C6B - 2C6C222C0A222E2A2C6D2C2A2C2A2C632C632C622C652C6E2E392C6F2C6A2C70 - 2C712C722C73222C0A222E2A2C742C752C752E4C2C632C642C6E2C762C772C6A - 2C782C792C7A2C412C42222C0A222C432C442C452E682E682E682E682E682E68 - 2E682E682E682E682C462C472C48222C0A222E642C492C652C4A2C4B2C4B2C4B - 2C4B2C4B2C4B2C4B2C4B2E6A2C4C2C4D2C4E222C0A222C4F2C502C512C4A2C52 - 2C522C522C522C522C522C522C522E6A2C532C542C55222C0A222C562C572C58 - 2C4A2C4B2C4B2C4B2C4B2C4B2C4B2C4B2C4B2E6A2C592C5A2C30222C0A222C31 - 2C322C332E682E682E682E682E682E682E682E682E682E682C342C352C30222C - 0A222C432C362C372C382C392E232C402C232C3B2C3A2C3D2C2B2C252C302C24 - 2C28227D0A + 36040000424D3604000000000000360000002800000010000000100000000100 + 2000000000000004000064000000640000000000000000000000BA6A36FFB969 + 35FFB86935FFB76835FFB56835FFB46734FFB26634FFB06533FFAE6433FFAC63 + 32FFAA6232FFA96132FFA86031FFA76031FFA66031FFA86131FFBA6A35FFEBC6 + ADFFEAC5ADFFFEFBF8FFFEFBF8FFFEFBF8FFFEFBF8FFFEFBF8FFFEFBF8FFFEFB + F8FFFEFBF8FFFEFBF8FFFEFBF8FFC89A7CFFC79879FFA76031FFBA6B37FFEDCA + B3FFE0A27AFFFEFAF7FF62C088FF62C088FF62C088FF62C088FF62C088FF62C0 + 88FF62C088FF62C088FFFDF9F6FFCA8D65FFC99B7CFFA76031FFBB6C38FFEECC + B6FFE1A27AFFFEFAF7FFBFDCC2FFBFDCC2FFBFDCC2FFBFDCC2FFBFDCC2FFBFDC + C2FFBFDCC2FFBFDCC2FFFDF9F6FFCD9068FFCC9E81FFA86132FFBB6B38FFEFCE + B8FFE1A279FFFEFAF7FF62C088FF62C088FF62C088FF62C088FF62C088FF62C0 + 88FF62C088FF62C088FFFDF9F6FFCF936AFFCEA384FFAA6132FFBA6A36FFEFD0 + BBFFE2A27AFFFEFBF8FFFEFBF8FFFEFBF8FFFEFBF8FFFEFBF8FFFEFBF8FFFEFB + F8FFFEFBF8FFFEFBF8FFFEFBF8FFD3966DFFD2A78AFFAB6232FFBB6A36FFF0D2 + BEFFE2A37AFFE2A37AFFE1A37AFFE2A37BFFE1A37BFFE0A178FFDE9F77FFDD9F + 76FFDC9D74FFD99B72FFD89971FFD69970FFD5AB8EFFAD6333FFBB6A36FFF2D5 + C2FFE3A37AFFE3A37AFFE2A37BFFE2A37BFFE2A47BFFE1A279FFE0A178FFDEA0 + 77FFDE9E75FFDC9D74FFDA9B73FFD99B73FFDAB095FFAF6433FFBB6A36FFF2D8 + C5FFE3A47BFFE3A37AFFE3A47AFFE2A47BFFE2A37BFFE1A37BFFE1A279FFDFA0 + 77FFDE9F76FFDD9E74FFDB9C72FFDC9D74FFDDB59AFFB16534FFBB6B36FFF4D9 + C7FFE6A67DFFC88C64FFC98D65FFC98E67FFCB926CFFCB926DFFCA9069FFC88C + 65FFC88C64FFC88C64FFC88C64FFDA9C74FFE1BA9FFFB36634FFBB6B36FFF4DC + C9FFE7A77DFFF9ECE1FFF9ECE1FFF9EDE3FFFCF4EEFFFDFAF7FFFDF7F3FFFAED + E5FFF7E7DBFFF7E5D9FFF6E5D8FFDEA077FFE4BEA4FFB46734FFBC6B36FFF5DD + CCFFE7A87EFFFAF0E8FFFAF0E8FFC98D66FFFAF0E9FFFDF8F3FFFEFAF8FFFCF4 + EFFFF9E9DFFFF7E7DBFFF7E5D9FFE0A278FFE7C2A9FFB66835FFBC6B36FFF6DF + D0FFE8A87EFFFCF6F1FFFCF6F1FFC88C64FFFAF1E9FFFBF4EEFFFDFAF7FFFDF9 + F6FFFAF0E8FFF8E8DDFFF7E6DBFFE1A37AFFEFD5C3FFB76935FFBC6B36FFF6DF + D1FFE9AA80FFFEFAF6FFFDFAF6FFC88C64FFFBF3EEFFFBF1EAFFFCF6F2FFFEFB + F8FFFCF6F1FFF9ECE2FFF8E7DBFFEED0BAFFECD0BDFFBB703EFFBC6B36FFF6E0 + D1FFF7E0D1FFFEFBF8FFFEFBF7FFFDF9F6FFFCF5F0FFFAF0EAFFFBF2EDFFFDF9 + F6FFFDFAF7FFFBF1EBFFF8E9DFFFECD0BDFFC9895EFF0000000000000000BC6B + 36FFBC6B36FFBC6B36FFBC6B36FFBB6B36FFBB6B36FFBB6A36FFBB6A36FFBC6C + 39FFBD6E3BFFBB6D3AFFBB6B38FFBB703EFF0000000000000000 } NumGlyphs = 0 OnClick = btnSaveProfileClick @@ -545,71 +485,40 @@ object frmLogin: TfrmLogin Width = 23 Color = clBtnFace Glyph.Data = { - 100800002F2A2058504D202A2F0A7374617469632063686172202A6772617068 - 69635B5D203D207B0A2231362031362039302032222C0A222E2E2063204E6F6E - 65222C0A222E2C20632023464637373741222C0A222E2D206320234645373637 - 39222C0A222E2A20632023463836313634222C0A222E61206320234639363836 - 41222C0A222E6220632023463335313534222C0A222E63206320234646374538 - 31222C0A222E6420632023464537453831222C0A222E65206320234644373137 - 34222C0A222E6620632023463835463632222C0A222E67206320234642364436 - 46222C0A222E6820632023464637433745222C0A222E69206320234645373137 - 34222C0A222E6A20632023464537413744222C0A222E6B206320234646383738 - 41222C0A222E6C20632023464437393743222C0A222E6D206320234642363936 - 43222C0A222E6E20632023463835453631222C0A222E6F206320234641364336 - 45222C0A222E7020632023464637413744222C0A222E71206320234637354636 - 31222C0A222E7220632023463034363439222C0A222E73206320234643364236 - 45222C0A222E7420632023464437343737222C0A222E75206320234646383238 - 36222C0A222E7620632023464337333736222C0A222E77206320234638363236 - 34222C0A222E7820632023463735443630222C0A222E79206320234641364136 - 44222C0A222E7A20632023464637393742222C0A222E41206320234546343534 - 38222C0A222E4220632023463936333636222C0A222E43206320234642364437 - 30222C0A222E4420632023464637453830222C0A222E45206320234646374237 - 45222C0A222E4620632023464637393743222C0A222E47206320234646373737 - 39222C0A222E4820632023463735433545222C0A222E49206320234546343434 - 37222C0A222E4A20632023463635413544222C0A222E4B206320234646373937 - 44222C0A222E4C20632023464635423545222C0A222E4D206320234646353835 - 42222C0A222E4E20632023464637343736222C0A222E4F206320234546343334 - 36222C0A222E5020632023463735423544222C0A222E51206320234646373637 - 39222C0A222E5220632023464635363539222C0A222E53206320234646353435 - 37222C0A222E5420632023464637303732222C0A222E55206320234630343634 - 38222C0A222E5620632023463635413543222C0A222E57206320234641363436 - 37222C0A222E5820632023464637323734222C0A222E59206320234646373037 - 33222C0A222E5A20632023464636453730222C0A222E30206320234646364336 - 45222C0A222E3120632023463735353537222C0A222E32206320234545334433 - 46222C0A222E3320632023463635393542222C0A222E34206320234641363336 - 36222C0A222E3520632023464637313734222C0A222E36206320234636353835 - 41222C0A222E3720632023454534313433222C0A222E38206320234543334333 - 45222C0A222E3920632023463434443530222C0A222E40206320234646363736 - 38222C0A222E2320632023463534453530222C0A222E3B206320234542333433 - 36222C0A222E3A20632023463635383542222C0A222E3D206320234641363236 - 35222C0A222E2B20632023464637303731222C0A222E25206320234636353635 - 39222C0A222E2420632023454534303432222C0A222E28206320234539333233 - 35222C0A222E2920632023463234353437222C0A222E5B206320234646363236 - 33222C0A222E5D20632023463434383441222C0A222C2E206320234539324432 - 46222C0A222C2C20632023463535363538222C0A222C2D206320234641363136 - 33222C0A222C2A20632023463635353538222C0A222C61206320234544334634 - 31222C0A222C6220632023453632413243222C0A222C63206320234631334634 - 31222C0A222C6420632023463634413443222C0A222C65206320234541324633 - 31222C0A222C6620632023463234433446222C0A222C67206320234544334534 - 30222C0A222C6820632023453432323234222C0A222E2E2E2E2E2E2E2E2E2E2E - 2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E222C0A222E2E2E2E2E2E2E - 2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E222C0A222E2E2E - 2E2E2E2E2C2E2D2E2E2E2E2E2E2E2E2E2E2E2E2E2A2E612E622E2E2E2E222C0A - 222E2E2E2E2E2C2E632E642E652E2E2E2E2E2E2E2E2E662E672E682E662E2E2E - 2E222C0A222E2E2E2E2E692E6A2E6B2E6C2E6D2E2E2E2E2E6E2E6F2E702E712E - 722E2E2E2E222C0A222E2E2E2E2E2E2E732E742E752E762E772E782E792E7A2E - 782E412E2E2E2E2E2E222C0A222E2E2E2E2E2E2E2E2E422E432E442E452E462E - 472E482E492E2E2E2E2E2E2E2E222C0A222E2E2E2E2E2E2E2E2E2E2E4A2E4B2E - 4C2E4D2E4E2E4F2E2E2E2E2E2E2E2E2E2E222C0A222E2E2E2E2E2E2E2E2E2E2E - 502E512E522E532E542E552E2E2E2E2E2E2E2E2E2E222C0A222E2E2E2E2E2E2E - 2E2E562E572E582E592E5A2E302E312E322E2E2E2E2E2E2E2E222C0A222E2E2E - 2E2E2E2E332E342E352E362E372E382E392E402E232E3B2E2E2E2E2E2E222C0A - 222E2E2E2E2E3A2E3D2E2B2E252E242E2E2E2E2E282E292E5B2E5D2C2E2E2E2E - 2E222C0A222E2E2E2E2C2C2C2D2C2A2C612E2E2E2E2E2E2E2E2C622C632C642C - 652E2E2E2E222C0A222E2E2E2E2E2E2C662C672E2E2E2E2E2E2E2E2E2E2E2E2C - 682C652E2E2E2E2E2E222C0A222E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E - 2E2E2E2E2E2E2E2E2E2E2E2E2E222C0A222E2E2E2E2E2E2E2E2E2E2E2E2E2E2E - 2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E227D0A + 36040000424D3604000000000000360000002800000010000000100000000100 + 2000000000000004000064000000640000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000004F4CF2FF403EEDFF000000000000000000000000000000000000 + 0000000000002422E4FF312FEAFF000000000000000000000000000000000000 + 00005856F5FF6361FAFF5855F6FF413FEDFF0000000000000000000000000000 + 00002C2AE6FF413FF1FF4C4AF6FF312FEAFF0000000000000000000000000000 + 00005B58F6FF6562FAFF7170FFFF5956F6FF4240EEFF00000000000000003532 + E9FF4745F2FF6362FFFF4A48F4FF2F2DE9FF0000000000000000000000000000 + 0000000000005B59F6FF6663FAFF7471FFFF5A58F6FF4341EEFF3E3CECFF504D + F4FF6867FFFF504EF5FF3634EBFF000000000000000000000000000000000000 + 000000000000000000005C5AF6FF6764FAFF7472FFFF7370FFFF706EFFFF6E6C + FFFF5755F7FF3F3DEEFF00000000000000000000000000000000000000000000 + 00000000000000000000000000005D5BF7FF7976FFFF5956FFFF5754FFFF7270 + FFFF4846F0FF0000000000000000000000000000000000000000000000000000 + 00000000000000000000000000005D5AF6FF7D79FFFF5E5BFFFF5B58FFFF7674 + FFFF4643EFFF0000000000000000000000000000000000000000000000000000 + 000000000000000000006663F9FF706DFBFF807EFFFF7E7BFFFF7C79FFFF7977 + FFFF5E5CF7FF4744EFFF00000000000000000000000000000000000000000000 + 0000000000006E6BFCFF7774FDFF8682FFFF7673FCFF6462F8FF605DF7FF6D6A + FAFF7B79FFFF605DF7FF4845EFFF000000000000000000000000000000000000 + 00007471FEFF7D7AFEFF8A87FFFF7C79FDFF6C69FBFF0000000000000000615E + F8FF6E6CFAFF7D7AFFFF615FF7FF4946F0FF0000000000000000000000000000 + 00007A77FFFF817EFFFF817EFEFF7471FDFF0000000000000000000000000000 + 0000625FF8FF6F6DFBFF7E7CFFFF625FF8FF0000000000000000000000000000 + 0000000000007A77FFFF7976FEFF000000000000000000000000000000000000 + 0000000000006461F8FF6A68F9FF5451F3FF0000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000 } NumGlyphs = 0 OnClick = btnDeleteProfileClick diff --git a/Client/UfrmMain.lfm b/Client/UfrmMain.lfm index deab9d9..bc62e60 100644 --- a/Client/UfrmMain.lfm +++ b/Client/UfrmMain.lfm @@ -260,86 +260,40 @@ object frmMain: TfrmMain Width = 23 Color = clBtnFace Glyph.Data = { - F10900002F2A2058504D202A2F0A7374617469632063686172202A6772617068 - 69635B5D203D207B0A223136203136203132302032222C0A222E2E2063204E6F - 6E65222C0A222E2C20632023383442363645222C0A222E2D2063202338304233 - 3641222C0A222E2A20632023374342313637222C0A222E612063202337374145 - 3633222C0A222E6220632023383742383731222C0A222E632063202341344345 - 3934222C0A222E6420632023434245364333222C0A222E652063202344344542 - 4346222C0A222E6620632023434545394339222C0A222E672063202342384444 - 4146222C0A222E6820632023374642393644222C0A222E692063202336394135 - 3538222C0A222E6A20632023383742383730222C0A222E6B2063202342424443 - 4146222C0A222E6C20632023453046324443222C0A222E6D2063202342444534 - 4236222C0A222E6E20632023413544423942222C0A222E6F2063202341304439 - 3936222C0A222E7020632023414644464135222C0A222E712063202343354538 - 4330222C0A222E7220632023384143323739222C0A222E732063202335463945 - 3530222C0A222E7420632023423744414141222C0A222E752063202344434631 - 4438222C0A222E7620632023394444383932222C0A222E772063202339334344 - 3838222C0A222E7820632023384543433834222C0A222E792063202339364434 - 3842222C0A222E7A20632023393544343841222C0A222E412063202338454432 - 3833222C0A222E4220632023423745304146222C0A222E432063202337444239 - 3642222C0A222E4420632023353639383438222C0A222E452063202339374337 - 3835222C0A222E4620632023443745454432222C0A222E472063202341304439 - 3935222C0A222E4820632023393444333841222C0A222E492063202338394338 - 3746222C0A222E4A20632023464646464646222C0A222E4B2063202338354344 - 3739222C0A222E4C20632023374343333642222C0A222E4D2063202337454337 - 3646222C0A222E4E20632023423544464143222C0A222E4F2063202335373945 - 3435222C0A222E5020632023383342353644222C0A222E512063202342364444 - 4143222C0A222E5220632023414644464136222C0A222E532063202338434342 - 3831222C0A222E5420632023383643393743222C0A222E552063202337394244 - 3645222C0A222E5620632023364141433542222C0A222E572063202337374243 - 3630222C0A222E5820632023373342413543222C0A222E592063202339394431 - 3842222C0A222E5A20632023393243353830222C0A222E302063202334373845 - 3343222C0A222E3120632023374542323639222C0A222E322063202342454532 - 4236222C0A222E3320632023393744353842222C0A222E342063202338364339 - 3741222C0A222E3520632023373042383539222C0A222E362063202337454331 - 3639222C0A222E3720632023414144343944222C0A222E382063202334323842 - 3338222C0A222E3920632023374141463635222C0A222E402063202342334444 - 4139222C0A222E2320632023384143463744222C0A222E3B2063202338314343 - 3735222C0A222E3A20632023374442453637222C0A222E3D2063202341424434 - 3943222C0A222E2B20632023334438383334222C0A222E252063202337354143 - 3631222C0A222E2420632023393843433841222C0A222E282063202339364433 - 3839222C0A222E2920632023374143363642222C0A222E5B2063202337304331 - 3633222C0A222E5D20632023363541423535222C0A222C2E2063202337324239 - 3542222C0A222C2C20632023393743433835222C0A222C2D2063202338444245 - 3742222C0A222C2A20632023333938353330222C0A222C612063202336384142 - 3533222C0A222C6220632023423444444141222C0A222C632063202337394331 - 3634222C0A222C6420632023373142453546222C0A222C652063202336454235 - 3538222C0A222C6620632023373442373543222C0A222C672063202342344441 - 4136222C0A222C6820632023343338463338222C0A222C692063202336364133 - 3536222C0A222C6A20632023374442393641222C0A222C6B2063202342324442 - 4138222C0A222C6C20632023364642353539222C0A222C6D2063202336464235 - 3538222C0A222C6E20632023373442373542222C0A222C6F2063202342334439 - 4135222C0A222C7020632023364341413541222C0A222C712063202333343832 - 3243222C0A222C7220632023354439433444222C0A222C732063202337384234 - 3634222C0A222C7420632023423544424138222C0A222C752063202339384343 - 3837222C0A222C7620632023374442433636222C0A222C772063202337434241 - 3634222C0A222C7820632023393843423836222C0A222C792063202342344439 - 4135222C0A222C7A20632023364241413538222C0A222C412063202333343831 - 3243222C0A222C4220632023353339363435222C0A222C432063202335303939 - 3431222C0A222C4420632023384643323744222C0A222C452063202341364430 - 3936222C0A222C4620632023413643463936222C0A222C472063202338394245 - 3738222C0A222C4820632023343238443336222C0A222C492063202334343843 - 3341222C0A222C4A20632023343038393336222C0A222C4B2063202333433837 - 3332222C0A222C4C20632023333738343246222C0A222E2E2E2E2E2E2E2E2E2E - 2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E222C0A222E2E2E2E2E2E - 2E2E2E2E2E2E2E2C2E2D2E2A2E612E2E2E2E2E2E2E2E2E2E2E2E222C0A222E2E - 2E2E2E2E2E2E2E622E632E642E652E662E672E682E692E2E2E2E2E2E2E2E222C - 0A222E2E2E2E2E2E2E6A2E6B2E6C2E6D2E6E2E6F2E702E712E722E732E2E2E2E - 2E2E222C0A222E2E2E2E2E6A2E742E752E762E772E782E792E7A2E412E422E43 - 2E442E2E2E2E222C0A222E2E2E2E2E452E462E472E482E492E4A2E4A2E4B2E4C - 2E4D2E4E2E4F2E2E2E2E222C0A222E2E2E502E512E522E532E542E552E4A2E4A - 2E562E572E582E592E5A2E302E2E222C0A222E2E2E312E322E332E342E4A2E4A - 2E4A2E4A2E4A2E4A2E352E362E372E382E2E222C0A222E2E2E392E402E232E3B - 2E4A2E4A2E4A2E4A2E4A2E4A2E352E3A2E3D2E2B2E2E222C0A222E2E2E252E24 - 2E282E292E5B2E5D2E4A2E4A2E352E352C2E2C2C2C2D2C2A2E2E222C0A222E2E - 2E2E2C612C622C632C642E572E4A2E4A2E352C652C662C672C682E2E2E2E222C - 0A222E2E2E2E2C692C6A2C6B2E572E582E352C6C2C6D2C6E2C6F2C702C712E2E - 2E2E222C0A222E2E2E2E2E2E2C722C732C742C752C762C772C782C792C7A2C41 - 2E2E2E2E2E2E222C0A222E2E2E2E2E2E2E2E2C422C432C442C452C462C472C48 - 2C412E2E2E2E2E2E2E2E222C0A222E2E2E2E2E2E2E2E2E2E2E2E2C492C4A2C4B - 2C4C2E2E2E2E2E2E2E2E2E2E2E2E222C0A222E2E2E2E2E2E2E2E2E2E2E2E2E2E - 2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E227D0A + 36040000424D3604000000000000360000002800000010000000100000000100 + 2000000000000004000064000000640000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000003A8C44FF368940FF32873CFF2F84 + 37FF000000000000000000000000000000000000000000000000000000000000 + 00000000000000000000459653FF419950FF7DC28FFF96D0A6FF96CFA6FF78BE + 89FF368D42FF2C8134FF00000000000000000000000000000000000000000000 + 0000000000004D9C5DFF64B478FFA8DBB5FF87CC98FF66BC7DFF64BA7CFF86CB + 98FFA5D9B4FF58AA6BFF2C8134FF000000000000000000000000000000000000 + 000056A366FF6AB97DFFA8DBB2FF60BC77FF5CBA73FF59B870FF59B56FFF58B5 + 6FFF5BB774FFA5D9B3FF5AAA6CFF2C8234FF0000000000000000000000000000 + 000053AB68FFAADDB4FF64C179FF5FBE71FF60BC77FFFFFFFFFFFFFFFFFF59B8 + 70FF58B56EFF5CB774FFA6DAB4FF388F43FF00000000000000000000000061AC + 75FF8ACC98FF89D396FF6BC67AFF63C170FF55AB65FFFFFFFFFFFFFFFFFF59B8 + 70FF59B870FF5BB972FF85CC97FF7BBE8DFF308539FF000000000000000065AF + 7AFFA9DDB3FF7DCF8AFF75CC81FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFF59B870FF67BE7DFF9CD4ABFF34883DFF000000000000000069B2 + 7EFFB6E2BEFF8BD597FF7AC986FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFF59B870FF69C17EFF9DD4AAFF388B42FF00000000000000006DB5 + 83FFACDDB6FFA6DFAFFF81CB8CFF7CC986FF6EBD79FFFFFFFFFFFFFFFFFF5BAC + 6AFF60BC77FF5CBA73FF8BD199FF80C592FF3C8E47FF00000000000000000000 + 000085C797FFD2EED7FF95D9A0FF8AD394FF7FC889FFFFFFFFFFFFFFFFFF79CD + 85FF6BC37CFF6FC77EFFACDFB5FF459E57FF0000000000000000000000000000 + 000070B887FFAADAB7FFD8F1DCFF92D89DFF88CD93FF84CC8EFF8BD496FF8AD4 + 95FF83D28EFFAFE0B7FF6BB97DFF489856FF0000000000000000000000000000 + 00000000000070B887FFAFDCBBFFDCF2E0FFB6E4BDFF9BDBA5FF96D9A0FFA5DF + AFFFC0E8C5FF79C28AFF509E5FFF000000000000000000000000000000000000 + 0000000000000000000071B887FF94CEA4FFC3E6CBFFCFEBD4FFC9E9CEFFAFDD + B8FF6DB97FFF58A569FF00000000000000000000000000000000000000000000 + 0000000000000000000000000000000000006EB684FF6AB380FF67B17CFF63AE + 77FF000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000 } NumGlyphs = 0 OnClick = btnAddRandomClick @@ -353,83 +307,40 @@ object frmMain: TfrmMain Width = 23 Color = clBtnFace Glyph.Data = { - 810900002F2A2058504D202A2F0A7374617469632063686172202A6772617068 - 69635B5D203D207B0A223136203136203131332032222C0A222E2E2063204E6F - 6E65222C0A222E2C20632023444436413638222C0A222E2D2063202344433634 - 3633222C0A222E2A20632023444136343631222C0A222E612063202344393633 - 3544222C0A222E6220632023444636413641222C0A222E632063202345443933 - 3845222C0A222E6420632023463843334245222C0A222E652063202346394433 - 4343222C0A222E6620632023463943424334222C0A222E672063202346344234 - 4141222C0A222E6820632023453237303636222C0A222E692063202344313545 - 3533222C0A222E6A20632023453036393641222C0A222E6B2063202346324144 - 4141222C0A222E6C20632023464444434438222C0A222E6D2063202346414241 - 4145222C0A222E6E20632023464141333931222C0A222E6F2063202346413944 - 3842222C0A222E7020632023464241393943222C0A222E712063202346434337 - 4241222C0A222E7220632023453937423730222C0A222E732063202343433542 - 3443222C0A222E7420632023463341374133222C0A222E752063202346444442 - 4434222C0A222E7620632023464139413837222C0A222E772063202346303931 - 3746222C0A222E7820632023463138453741222C0A222E792063202346383934 - 3746222C0A222E7A20632023463939323745222C0A222E412063202346383843 - 3736222C0A222E4220632023463842364138222C0A222E432063202345333645 - 3633222C0A222E4420632023433735373435222C0A222E452063202345413833 - 3744222C0A222E4620632023464344344344222C0A222E472063202346373933 - 3745222C0A222E4820632023454538413735222C0A222E492063202346363834 - 3643222C0A222E4A20632023463337393633222C0A222E4B2063202346384146 - 4134222C0A222E4C20632023443034463345222C0A222E4D2063202344453641 - 3637222C0A222E4E20632023463541464135222C0A222E4F2063202346414142 - 3944222C0A222E5020632023463038433737222C0A222E512063202345433546 - 3534222C0A222E5220632023463237373633222C0A222E532063202346343845 - 3831222C0A222E5420632023453937463738222C0A222E552063202343303533 - 3341222C0A222E5620632023444236393634222C0A222E572063202346394239 - 4146222C0A222E5820632023464139333746222C0A222E592063202346303835 - 3730222C0A222E5A20632023464646464646222C0A222E302063202345393539 - 3444222C0A222E3120632023454536413545222C0A222E322063202346313944 - 3936222C0A222E3320632023424534463336222C0A222E342063202344413633 - 3546222C0A222E3520632023463741424131222C0A222E362063202346383836 - 3730222C0A222E3720632023463638323638222C0A222E382063202345413636 - 3543222C0A222E3920632023463139433936222C0A222E402063202342433530 - 3332222C0A222E2320632023443736323543222C0A222E3B2063202345453843 - 3831222C0A222E3A20632023463739313745222C0A222E3D2063202346333733 - 3544222C0A222E2B20632023453935423446222C0A222E252063202346303833 - 3742222C0A222E2420632023453237423735222C0A222E282063202342413442 - 3245222C0A222E2920632023444235363442222C0A222E5B2063202346364142 - 4132222C0A222E5D20632023463036343536222C0A222C2E2063202345453636 - 3532222C0A222C2C20632023453635383443222C0A222C2D2063202345363541 - 3532222C0A222C2A20632023463541333946222C0A222C612063202343343530 - 3334222C0A222C6220632023434636313533222C0A222C632063202345333642 - 3631222C0A222C6420632023463541434131222C0A222C652063202345413543 - 3530222C0A222C6620632023453635393445222C0A222C672063202345363536 - 3443222C0A222C6820632023453635363530222C0A222C692063202346344132 - 3945222C0A222C6A20632023443636303534222C0A222C6B2063202342383441 - 3241222C0A222C6C20632023434235393439222C0A222C6D2063202345303635 - 3543222C0A222C6E20632023463541364131222C0A222C6F2063202345463836 - 3745222C0A222C7020632023453936333542222C0A222C712063202345373544 - 3539222C0A222C7220632023454538343744222C0A222C732063202346344130 - 3945222C0A222C7420632023443735443531222C0A222C752063202342373441 - 3242222C0A222C7620632023433635353432222C0A222C772063202343433532 - 3343222C0A222C7820632023453837413735222C0A222C792063202345453932 - 3846222C0A222C7A20632023453437383731222C0A222C412063202343313444 - 3333222C0A222C4220632023424535333338222C0A222C432063202342443531 - 3335222C0A222C4420632023424334423330222C0A222C452063202342383445 - 3245222C0A222E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E - 2E2E2E2E2E2E222C0A222E2E2E2E2E2E2E2E2E2E2E2E2E2C2E2D2E2A2E612E2E - 2E2E2E2E2E2E2E2E2E2E222C0A222E2E2E2E2E2E2E2E2E622E632E642E652E66 - 2E672E682E692E2E2E2E2E2E2E2E222C0A222E2E2E2E2E2E2E6A2E6B2E6C2E6D - 2E6E2E6F2E702E712E722E732E2E2E2E2E2E222C0A222E2E2E2E2E6A2E742E75 - 2E762E772E782E792E7A2E412E422E432E442E2E2E2E222C0A222E2E2E2E2E45 - 2E462E6F2E472E482E492E492E492E492E4A2E4B2E4C2E2E2E2E222C0A222E2E - 2E4D2E4E2E4F2E502E512E512E512E512E512E512E522E532E542E552E2E222C - 0A222E2E2E562E572E582E592E5A2E5A2E5A2E5A2E5A2E5A2E302E312E322E33 - 2E2E222C0A222E2E2E342E352E362E372E5A2E5A2E5A2E5A2E5A2E5A2E302E38 - 2E392E402E2E222C0A222E2E2E232E3B2E3A2E3D2E302E302E302E302E302E30 - 2E2B2E252E242E282E2E222C0A222E2E2E2E2E292E5B2E5D2C2E2E302E302E30 - 2E302C2C2C2D2C2A2C612E2E2E2E222C0A222E2E2E2E2C622C632C642E512C65 - 2E302C662C672C682C692C6A2C6B2E2E2E2E222C0A222E2E2E2E2E2E2C6C2C6D - 2C6E2C6F2C702C712C722C732C742C752E2E2E2E2E2E222C0A222E2E2E2E2E2E - 2E2E2C762C772C782C792C792C7A2C412C752E2E2E2E2E2E2E2E222C0A222E2E - 2E2E2E2E2E2E2E2E2E2E2C422C432C442C452E2E2E2E2E2E2E2E2E2E2E2E222C - 0A222E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E - 2E2E227D0A + 36040000424D3604000000000000360000002800000010000000100000000100 + 2000000000000004000064000000640000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000003853BEFF3551BDFF304BBCFF2E4E + B8FF000000000000000000000000000000000000000000000000000000000000 + 000000000000000000004255C6FF3C52CCFF757AE8FF8F92EEFF8F92EEFF7178 + E4FF334DC1FF2B4AB7FF00000000000000000000000000000000000000000000 + 0000000000004959CBFF5C65E0FFA1A6F5FF7E86EFFF5B63E9FF595DE7FF7D84 + EEFF9EA0F4FF515DD7FF2B4AB7FF000000000000000000000000000000000000 + 00005361CFFF616BE3FFA1ACF5FF545FECFF505CEAFF4D59E9FF4E59E6FF4C56 + E6FF5056E6FF9EA2F4FF5460D6FF2A4AB8FF0000000000000000000000000000 + 00004B56DBFFA2ABF6FF5664F0FF5266EEFF4D59E9FF4D59E9FF4D59E9FF4D59 + E9FF4C58E6FF525AE6FF9FA3F5FF3450C4FF0000000000000000000000005C62 + D7FF818CEEFF7E91F7FF5D73F3FF4D59E9FF4D59E9FF4D59E9FF4D59E9FF4D59 + E9FF4D59E9FF4F5BE9FF7B83F0FF757BE2FF2E4BBAFF00000000000000005F63 + DAFFA1ABF7FF7086F8FF6882F6FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFF4D59E9FF5C66EAFF969CF1FF3250BCFF00000000000000006469 + DBFFAFB9F9FF7F93FAFF7085F0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFF4D59E9FF5E6AEEFF969DF1FF364FBEFF0000000000000000676A + DEFFA5AFF5FF9DABFAFF778CF0FF545FECFF545FECFF545FECFF545FECFF545F + ECFF545FECFF6377F2FF818EF4FF787FE9FF3A53C0FF00000000000000000000 + 00007D83EAFFCDD4FCFF8B9DFAFF7E93F7FF758AEEFF6C84F6FF6C84F6FF6C84 + F6FF6C84F6FF6379F3FFA4AFF8FF3E4FD0FF0000000000000000000000000000 + 00006A69E0FFA3A7F3FFD4DBFDFF879AFAFF7F91F0FF7A8EF1FF7F94F8FF7E92 + F9FF768CF8FFA8B6F8FF636EE3FF4557C7FF0000000000000000000000000000 + 0000000000006A69E0FFAAADF2FFD8DCFDFFAEBAFAFF91A3FAFF8B9DFAFF9CA9 + FBFFBAC7FCFF707BE9FF4C5BCCFF000000000000000000000000000000000000 + 000000000000000000006A6ADFFF8E93EDFFBEC3F8FFCCD3F9FFC4CBF9FFAAB4 + F4FF6670E2FF535ED1FF00000000000000000000000000000000000000000000 + 000000000000000000000000000000000000686ADDFF6364DCFF6164DAFF5D63 + D9FF000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000 } NumGlyphs = 0 OnClick = btnDeleteRandomClick @@ -443,78 +354,40 @@ object frmMain: TfrmMain Width = 23 Color = clBtnFace Glyph.Data = { - F10800002F2A2058504D202A2F0A7374617469632063686172202A6772617068 - 69635B5D203D207B0A223136203136203130342032222C0A222E2E2063204E6F - 6E65222C0A222E2C20632023464630303030222C0A222E2D2063202346443030 - 3030222C0A222E2A20632023464632423236222C0A222E612063202346463639 - 3543222C0A222E6220632023464636383542222C0A222E632063202346453637 - 3541222C0A222E6420632023464536353538222C0A222E652063202346453633 - 3536222C0A222E6620632023464536313534222C0A222E672063202346433237 - 3232222C0A222E6820632023464230303030222C0A222E692063202346463641 - 3544222C0A222E6A20632023464634373433222C0A222E6B2063202346453334 - 3334222C0A222E6C20632023464533323332222C0A222E6D2063202346443330 - 3330222C0A222E6E20632023464432443244222C0A222E6F2063202346433343 - 3338222C0A222E7020632023464335443446222C0A222E712063202346413235 - 3146222C0A222E7220632023463730303030222C0A222E732063202346463542 - 3538222C0A222E7420632023464643464346222C0A222E752063202346453532 - 3532222C0A222E7620632023464432463246222C0A222E772063202346443243 - 3243222C0A222E7820632023464334423442222C0A222E792063202346454343 - 4343222C0A222E7A20632023464234433438222C0A222E412063202346423537 - 3439222C0A222E4220632023463932333144222C0A222E432063202346353030 - 3030222C0A222E4420632023464534373433222C0A222E452063202346464633 - 4633222C0A222E4620632023464645444544222C0A222E472063202346433443 - 3443222C0A222E4820632023464334413441222C0A222E492063202346464543 - 4543222C0A222E4A20632023464646324632222C0A222E4B2063202346454341 - 4341222C0A222E4C20632023464132463241222C0A222E4D2063202346413531 - 3432222C0A222E4E20632023463330303030222C0A222E4F2063202346453333 - 3333222C0A222E5020632023464435303530222C0A222E512063202346454543 - 4543222C0A222E5220632023464133453345222C0A222E532063202346383137 - 3137222C0A222E5420632023463934453346222C0A222E552063202346313030 - 3030222C0A222E5620632023464536343537222C0A222E572063202346393344 - 3344222C0A222E5820632023463831363136222C0A222E592063202346373133 - 3133222C0A222E5A20632023463834423343222C0A222E302063202346453632 - 3535222C0A222E3120632023464332393239222C0A222E322063202346433438 - 3438222C0A222E3320632023463933413341222C0A222E342063202346373132 - 3132222C0A222E3520632023463630463046222C0A222E362063202346383438 - 3338222C0A222E3720632023464435463532222C0A222E382063202346433238 - 3238222C0A222E3920632023464334373437222C0A222E402063202346464631 - 4631222C0A222E2320632023464545414541222C0A222E3B2063202346373334 - 3334222C0A222E3A20632023463530423042222C0A222E3D2063202346383435 - 3335222C0A222E2B20632023454630303030222C0A222E252063202346443544 - 3446222C0A222E2420632023464233373332222C0A222E282063202346454342 - 4342222C0A222E2920632023464545424542222C0A222E5B2063202346393342 - 3342222C0A222E5D20632023463833393339222C0A222C2E2063202346454631 - 4631222C0A222C2C20632023464443354335222C0A222C2D2063202346363144 - 3138222C0A222C2A20632023463734333333222C0A222C612063202346393030 - 3030222C0A222C6220632023464235383441222C0A222C632063202346423437 - 3432222C0A222C6420632023464443394339222C0A222C652063202346363130 - 3130222C0A222C6620632023463733333333222C0A222C672063202346373335 - 3330222C0A222C6820632023463734343334222C0A222C692063202346323142 - 3134222C0A222C6A20632023454430303030222C0A222C6B2063202346413533 - 3434222C0A222C6C20632023463932393234222C0A222C6D2063202346353043 - 3043222C0A222C6E20632023463530393039222C0A222C6F2063202346353142 - 3136222C0A222C7020632023463131423134222C0A222C712063202346353230 - 3141222C0A222C7220632023463934433343222C0A222C732063202346383439 - 3341222C0A222C7420632023463834373338222C0A222C752063202346373433 - 3334222C0A222C7620632023463734323332222C0A222E2E2E2E2E2E2E2E2E2E - 2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E222C0A222E2E2E2E2E2E - 2E2E2E2C2E2C2E2C2E2C2E2D2E2D2E2D2E2D2E2E2E2E2E2E2E2E222C0A222E2E - 2E2E2E2E2E2C2E2A2E612E622E632E642E652E662E672E682E2E2E2E2E2E222C - 0A222E2E2E2E2E2C2E2A2E692E6A2E6B2E6C2E6D2E6E2E6F2E702E712E722E2E - 2E2E222C0A222E2E2E2C2E2A2E692E732E742E752E762E772E782E792E7A2E41 - 2E422E432E2E222C0A222E2E2E2C2E622E442E742E452E462E472E482E492E4A - 2E4B2E4C2E4D2E4E2E2E222C0A222E2E2E2C2E632E4F2E502E462E452E462E46 - 2E4A2E512E522E532E542E552E2E222C0A222E2E2E2D2E562E6D2E6E2E782E46 - 2E4A2E4A2E492E572E582E592E5A2E552E2E222C0A222E2E2E2D2E302E772E31 - 2E322E462E4A2E4A2E512E332E342E352E362E552E2E222C0A222E2E2E2D2E37 - 2E382E392E492E4A2E492E512E402E232E3B2E3A2E3D2E2B2E2E222C0A222E2E - 2E682E252E242E282E4A2E292E5B2E5D2E232C2E2C2C2C2D2C2A2E2B2E2E222C - 0A222E2E2C612E712C622C632C642E5B2E592C652C662C2C2C672C682C692C6A - 2E2E222C0A222E2E2E2E2E722E422C6B2C6C2E342E352C6D2C6E2C6F2C2A2C70 - 2C6A2E2E2E2E222C0A222E2E2E2E2E2E2E432C712C722C732C742E3D2C752C76 - 2C702C6A2E2E2E2E2E2E222C0A222E2E2E2E2E2E2E2E2E552E552E552E552E2B - 2E2B2C6A2C6A2E2E2E2E2E2E2E2E222C0A222E2E2E2E2E2E2E2E2E2E2E2E2E2E - 2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E227D0A + 36040000424D3604000000000000360000002800000010000000100000000100 + 2000000000000004000064000000640000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000000000000000000000F1FF0000F1FF0000F1FF0000F1FF0000EFFF0000 + EFFF0000EDFF0000EDFF00000000000000000000000000000000000000000000 + 0000000000000000F5FF1A20F5FF3C4CF9FF3A49F8FF3847F8FF3545F8FF3443 + F7FF3242F7FF141BF1FF0000EDFF000000000000000000000000000000000000 + 00000000F7FF1D23F9FF4453FAFF2429F9FF1212F7FF0F0FF6FF0C0CF5FF0909 + F5FF161BF5FF3343F7FF141BF1FF0000EDFF0000000000000000000000000000 + F9FF1F25FAFF4A58FBFF4247FBFFC9C9FDFF3B3BF9FF1313F7FF1010F6FF3333 + F7FFC5C5FDFF3035F7FF3444F7FF141BF2FF0000EDFF00000000000000000000 + FBFF4F5DFDFF3237FBFFCBCBFEFFF2F2FFFFEBEBFEFF3B3BF9FF3939F8FFEAEA + FEFFF1F1FEFFC5C5FDFF181DF6FF3343F7FF0000EFFF00000000000000000000 + FDFF525FFDFF2828FCFF4747FCFFECECFFFFF2F2FFFFECECFFFFECECFEFFF1F1 + FFFFEAEAFEFF3434F7FF0B0BF5FF3545F8FF0000EFFF00000000000000000000 + FDFF5562FEFF2C2CFDFF2929FCFF4848FCFFEDEDFFFFF2F2FFFFF2F2FFFFECEC + FEFF3A3AF9FF1212F7FF0F0FF6FF3848F8FF0000F1FF00000000000000000000 + FDFF5764FEFF3030FDFF2D2DFDFF4B4BFCFFEDEDFFFFF2F2FFFFF2F2FFFFECEC + FFFF3D3DF9FF1616F8FF1313F7FF3C4BF8FF0000F1FF00000000000000000000 + FFFF5A67FEFF3333FEFF5050FDFFEDEDFFFFF3F3FFFFEDEDFFFFEDEDFFFFF2F2 + FFFFECECFEFF3E3EFAFF1717F8FF3F4EF9FF0000F1FF00000000000000000000 + FFFF5B68FFFF4347FEFFCFCFFFFFF3F3FFFFEDEDFFFF4C4CFCFF4A4AFCFFECEC + FFFFF2F2FFFFCACAFEFF2A2FFAFF4251FAFF0000F3FF00000000000000000000 + FFFF262BFFFF5D6AFFFF585BFFFFCFCFFFFF5252FEFF2F2FFDFF2C2CFDFF4B4B + FCFFCCCCFEFF484CFBFF4957FBFF1D23F9FF0000F5FF00000000000000000000 + 00000000FFFF262BFFFF5D6AFFFF4347FFFF3434FEFF3232FEFF3030FDFF2D2D + FDFF383CFCFF4F5DFCFF1F25FAFF0000F7FF0000000000000000000000000000 + 0000000000000000FFFF262BFFFF5C69FFFF5B68FFFF5A67FEFF5865FEFF5663 + FEFF5461FEFF2227FCFF0000FBFF000000000000000000000000000000000000 + 000000000000000000000000FFFF0000FFFF0000FFFF0000FFFF0000FDFF0000 + FDFF0000FDFF0000FDFF00000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000 } NumGlyphs = 0 OnClick = btnClearRandomClick @@ -540,125 +413,40 @@ object frmMain: TfrmMain Width = 23 Color = clBtnFace Glyph.Data = { - C10E00002F2A2058504D202A2F0A7374617469632063686172202A6772617068 - 69635B5D203D207B0A223136203136203139372032222C0A222E2E2063204E6F - 6E65222C0A222E2C20632023344438424338222C0A222E2D2063202334463843 - 4338222C0A222E2A20632023344638444338222C0A222E612063202334463843 - 4339222C0A222E6220632023344638424337222C0A222E632063202334423839 - 4335222C0A222E6420632023334237364334222C0A222E652063202334393835 - 4334222C0A222E6620632023454346324637222C0A222E672063202345454634 - 4638222C0A222E6820632023454446334638222C0A222E692063202345434632 - 4638222C0A222E6A20632023443745364632222C0A222E6B2063202337444232 - 4532222C0A222E6C20632023363539344442222C0A222E6D2063202334423838 - 4335222C0A222E6E20632023463246364641222C0A222E6F2063202343374530 - 4641222C0A222E7020632023433945324642222C0A222E712063202343384530 - 4642222C0A222E7220632023433544464639222C0A222E732063202343314442 - 4638222C0A222E7420632023423844364634222C0A222E752063202346384642 - 4646222C0A222E7620632023423444384636222C0A222E772063202337444230 - 4531222C0A222E7820632023363439324442222C0A222E792063202334433839 - 4336222C0A222E7A20632023463146354639222C0A222E412063202343444533 - 4643222C0A222E4220632023434445334642222C0A222E432063202343424532 - 4642222C0A222E4420632023433845304639222C0A222E452063202343324443 - 4638222C0A222E4620632023424144364635222C0A222E472063202346384642 - 4644222C0A222E4820632023434445364643222C0A222E492063202343394535 - 4641222C0A222E4A20632023383442364532222C0A222E4B2063202334323739 - 4246222C0A222E4C20632023344238394336222C0A222E4D2063202343464533 - 4643222C0A222E4E20632023434645344643222C0A222E4F2063202343414531 - 4641222C0A222E5020632023433444444639222C0A222E512063202342434439 - 4636222C0A222E5220632023444645394634222C0A222E532063202346334637 - 4642222C0A222E5420632023453945464635222C0A222E552063202334353745 - 4332222C0A222E5620632023463046344639222C0A222E572063202344334536 - 4643222C0A222E5820632023443345374644222C0A222E592063202344314534 - 4643222C0A222E5A20632023433845304641222C0A222E302063202342424436 - 4635222C0A222E3120632023423544344633222C0A222E322063202342334432 - 4631222C0A222E3320632023463046344638222C0A222E342063202334363832 - 4334222C0A222E3520632023344138384336222C0A222E362063202345464634 - 4639222C0A222E3720632023443745374645222C0A222E382063202344354537 - 4644222C0A222E3920632023443445364644222C0A222E402063202344324536 - 4643222C0A222E2320632023364539374434222C0A222E3B2063202337423945 - 4434222C0A222E3A20632023373139384430222C0A222E3D2063202338324134 - 4436222C0A222E2B20632023363838454344222C0A222E252063202336393930 - 4344222C0A222E2420632023373539414430222C0A222E282063202337333939 - 4431222C0A222E2920632023363238424338222C0A222E5B2063202334393838 - 4336222C0A222E5D20632023454446344639222C0A222C2E2063202344384538 - 4645222C0A222C2C20632023443745384645222C0A222C2D2063202344364537 - 4645222C0A222C2A20632023443345354644222C0A222C612063202336353844 - 4343222C0A222C6220632023423043444633222C0A222C632063202346464646 - 4646222C0A222C6420632023423343374533222C0A222C652063202341314246 - 4541222C0A222C6620632023363038394339222C0A222C672063202334373834 - 4336222C0A222C6820632023454346334639222C0A222C692063202344364538 - 4645222C0A222C6A20632023443645374644222C0A222C6B2063202335423836 - 4337222C0A222C6C20632023394543304546222C0A222C6D2063202336453933 - 4343222C0A222C6E20632023463746424646222C0A222C6F2063202346314638 - 4646222C0A222C7020632023384341464534222C0A222C712063202336313841 - 4337222C0A222C7220632023343538324335222C0A222C732063202345424632 - 4638222C0A222C7420632023443545364644222C0A222C752063202335443838 - 4338222C0A222C7620632023413142464546222C0A222C772063202346414643 - 4644222C0A222C7820632023464246434645222C0A222C792063202346444644 - 4645222C0A222C7A20632023464346444645222C0A222C412063202346414642 - 4644222C0A222C4220632023464246434644222C0A222C432063202338354138 - 4444222C0A222C4420632023353337464331222C0A222C452063202334303743 - 4334222C0A222C4620632023453646304637222C0A222C472063202335354234 - 4638222C0A222C4820632023353442354637222C0A222C492063202335334234 - 4638222C0A222C4A20632023353342324638222C0A222C4B2063202336353844 - 4341222C0A222C4C20632023393942384541222C0A222C4D2063202337454135 - 4444222C0A222C4E20632023383041364444222C0A222C4F2063202337434133 - 4442222C0A222C5020632023374141304439222C0A222C512063202337394130 - 4439222C0A222C5220632023373839464438222C0A222C532063202337383945 - 4438222C0A222C5420632023354438344246222C0A222C552063202333433738 - 4331222C0A222C5620632023453345444637222C0A222C572063202336454332 - 4644222C0A222C5820632023394544374646222C0A222C592063202339424436 - 4646222C0A222C5A20632023393844374646222C0A222C302063202336313842 - 4339222C0A222C3120632023393242354536222C0A222C322063202338314137 - 4532222C0A222C3320632023383141374531222C0A222C342063202337444133 - 4445222C0A222C3520632023374241314443222C0A222C362063202337393946 - 4442222C0A222C3720632023373739454439222C0A222C382063202337333941 - 4434222C0A222C3920632023353737454242222C0A222C402063202333383731 - 4246222C0A222C2320632023444645424635222C0A222C3B2063202336384246 - 4644222C0A222C3A20632023363542454642222C0A222C3D2063202336344245 - 4643222C0A222C2B20632023353438314334222C0A222C252063202339374236 - 4541222C0A222C2420632023454146334633222C0A222C282063202345364631 - 4544222C0A222C2920632023453646314546222C0A222C5B2063202345364630 - 4546222C0A222C5D20632023453546314544222C0A222D2E2063202345444635 - 4633222C0A222D2C20632023373939434435222C0A222D2D2063202334343730 - 4230222C0A222D2A20632023333336394243222C0A222D612063202345414631 - 4638222C0A222D6220632023444645434637222C0A222D632063202344454541 - 4636222C0A222D6420632023444345414636222C0A222D652063202335313746 - 4333222C0A222D6620632023394142364546222C0A222D672063202345384633 - 4541222C0A222D6820632023383442463531222C0A222D692063202339384339 - 3646222C0A222D6A20632023393943393731222C0A222D6B2063202338344246 - 3534222C0A222D6C20632023453946344534222C0A222D6D2063202337423943 - 4444222C0A222D6E20632023334136394141222C0A222D6F2063202333303635 - 4241222C0A222D7020632023333136364242222C0A222D712063202333303636 - 4241222C0A222D7220632023353538334336222C0A222D732063202342414345 - 4546222C0A222D7420632023464646464444222C0A222D752063202343374545 - 3837222C0A222D7620632023443746344132222C0A222D772063202344374636 - 4132222C0A222D7820632023433745453843222C0A222D792063202346464646 - 4530222C0A222D7A20632023383541324444222C0A222D412063202333453641 - 4142222C0A222D4220632023333336384241222C0A222D432063202335383834 - 4333222C0A222D4420632023363838424433222C0A222D452063202337303846 - 4531222C0A222D4620632023364338444443222C0A222D472063202336443842 - 4441222C0A222D4820632023364538414437222C0A222D492063202336433842 - 4344222C0A222D4A20632023343436444142222C0A222D4B2063202332453546 - 4136222C0A222E2E2E2C2E2D2E2D2E2D2E2A2E612E622E632E642E2E2E2E2E2E - 2E2E2E2E2E2E222C0A222E652E662E672E682E682E682E692E662E6A2E6B2E6C - 2E2E2E2E2E2E2E2E2E2E222C0A222E6D2E6E2E6F2E702E712E722E732E742E75 - 2E762E772E782E2E2E2E2E2E2E2E222C0A222E792E7A2E412E422E432E442E45 - 2E462E472E482E492E4A2E4B2E2E2E2E2E2E222C0A222E4C2E7A2E4D2E4E2E41 - 2E4F2E502E512E522E662E532E542E552E2E2E2E2E2E222C0A222E4C2E562E57 - 2E582E592E422E5A2E452E302E312E322E332E342E2E2E2E2E2E222C0A222E35 - 2E362E372E382E392E402E232E3B2E3A2E3D2E2B2E252E242E282E292E2E222C - 0A222E5B2E5D2C2E2C2C2C2D2C2A2C612C622C632C642C632C632C632C632C65 - 2C66222C0A222C672C682C692C6A2C6A2E382C6B2C6C2C632C6D2C632C632C6E - 2C6F2C702C71222C0A222C722C732C2D2C6A2C6A2C742C752C762C772C782C79 - 2C7A2C412C422C432C44222C0A222C452C462C472C482C492C4A2C4B2C4C2C4D - 2C4E2C4F2C502C512C522C532C54222C0A222C552C562C572C582C592C5A2C30 - 2C312C322C332C342C352C362C372C382C39222C0A222C402C232C3B2C3A2C3D - 2C3D2C2B2C252C242C282C292C5B2C5D2D2E2D2C2D2D222C0A222D2A2D612D62 - 2D632D642D642D652D662D672D682D692D6A2D6B2D6C2D6D2D6E222C0A222E2E - 2D6F2D702D712D712D6F2D722D732D742D752D762D772D782D792D7A2D41222C - 0A222E2E2E2E2E2E2E2E2E2E2E2E2D422D432D442D452D462D472D482D492D4A - 2D4B227D0A + 36040000424D3604000000000000360000002800000010000000100000000100 + 2000000000000004000064000000640000000000000000000000000000000000 + 000000000000000000000000000000000000BA6833FFC38458FFD38B68FFE18F + 70FFDC8D6CFFDA8B6DFFD78A6EFFCD8B6CFFAB6D44FFA65F2EFF00000000BA65 + 30FFBB6631FFBA6630FFBA6630FFBA6530FFC68355FFEFCEBAFFDDFFFFFF87EE + C7FFA2F4D7FFA2F6D7FF8CEEC7FFE0FFFFFFDDA285FFAB6A3EFFBC6933FFF8F1 + EAFFF7ECDFFFF6EADEFFF6EADCFFF6EADCFFC37F51FFEFB69AFFEAF3E8FF51BF + 84FF6FC998FF71C999FF54BF84FFE4F4E9FFDD9C7BFFAA693AFFBF7138FFF5EB + DFFFFDBF68FFFBBE65FFFCBE64FFFCBE64FFC48154FFEAB697FFF3F3EAFFEDF1 + E6FFEFF1E6FFEFF0E6FFEDF1E5FFF3F5EDFFD59C79FFB07044FFC1783CFFF7ED + E3FFFDC26EFFFFD79EFFFFD69BFFFFD798FFC98B61FFE6B592FFE2A781FFE1A7 + 81FFDEA37DFFDCA17BFFDB9F79FFD99E77FFD49A73FFBB7E57FFC47C40FFF7F0 + E6FFF8B455FFF7B554FFF8B453FFF8B253FFCA8D65FFEAB899FFDDA57EFFDDA6 + 80FFDBA37CFFD9A07AFFD9A079FFD89F78FFD89E78FFBF845DFFC58245FFF8F2 + EBFFFEE7D6FFFDE7D6FFFDE7D6FFFDE6D5FFC8885DFFEFBFA1FFFDFCFAFFFEFC + FBFFFEFDFDFFFEFDFCFFFDFBFAFFFDFCFBFFDDA885FFC17F53FFC68447FFF9F3 + ECFFFEE8D6FFFDE7D6FFFDE7D6FFFDE7D5FFC7865BFFEFC09EFFFFFFFFFFCC93 + 6EFFFFFFFFFFFFFFFFFFFFFBF7FFFFF8F1FFE4AF8CFFC78A61FFC68849FFF9F4 + EDFFFEE8D8FFFEE8D7FFFEE7D6FFFDE5D3FFCC8D65FFF3CDB0FFFFFFFFFFE3C7 + B3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEABFA1FFC98960FFC6884AFFF9F4 + EFFFFEE7D7FFFDE7D5FFFDE6D4FFFCE6D2FFD4976EFFD49E7BFFD09871FFD6A4 + 82FFCD8E68FFCD9069FFD09A75FFD19973FFC88B62FF00000000C6894BFFF9F4 + F0FFFCE6D3FFFDE7D3FFFCE4D1FFFBE3CDFFFAE0C8FFF8DCC2FFF5D6BBFFF3D4 + B5FFF1D2B3FFF8F4F0FFC48246FF000000000000000000000000C6894BFFF9F5 + F1FFFCE3CFFFFCE4CFFFFCE3CDFFFAE1CAFFF9DDC4FFF6D9BCFFF4E9DFFFF7F2 + ECFFFBF7F3FFF5EFE9FFC27E45FF000000000000000000000000C6894CFFF9F5 + F1FFFCE3CDFFFBE3CDFFFBE2CBFFF9E0C8FFF8DCC2FFF5D6BAFFFDFBF8FFFCE6 + CDFFFAE5C9FFE2B684FFBF7942FF000000000000000000000000C5884BFFFAF6 + F2FFFAE0C7FFFBE2C9FFFBE0C8FFF9DFC5FFF8DBC1FFF4D6B8FFFFFBF8FFF6D8 + B4FFE1B07DFFDB9264FF00000000000000000000000000000000C48549FFF7F2 + ECFFF8F4EEFFF8F3EDFFF8F3EDFFF8F3EDFFF8F2ECFFF7F2ECFFF2E6D7FFE2B2 + 7DFFDB9465FF000000000000000000000000000000000000000000000000C88B + 4DFFC88C4FFFC88C4FFFC88C4FFFC88D4FFFC98C4FFFC78B4FFFC5894BFFC476 + 3BFF000000000000000000000000000000000000000000000000 } NumGlyphs = 0 OnClick = btnRandomPresetSaveClick @@ -673,114 +461,40 @@ object frmMain: TfrmMain Width = 23 Color = clBtnFace Glyph.Data = { - 710D00002F2A2058504D202A2F0A7374617469632063686172202A6772617068 - 69635B5D203D207B0A223136203136203137362032222C0A222E2E2063204E6F - 6E65222C0A222E2C20632023344438424338222C0A222E2D2063202334463843 - 4338222C0A222E2A20632023344638444338222C0A222E612063202334463843 - 4339222C0A222E6220632023344638424337222C0A222E632063202334423839 - 4335222C0A222E6420632023334237364334222C0A222E652063202334393835 - 4334222C0A222E6620632023454346324637222C0A222E672063202345454634 - 4638222C0A222E6820632023454446344638222C0A222E692063202345444633 - 4638222C0A222E6A20632023454346324638222C0A222E6B2063202344374536 - 4632222C0A222E6C20632023374442324532222C0A222E6D2063202336353934 - 4442222C0A222E6E20632023344238384335222C0A222E6F2063202346324636 - 4641222C0A222E7020632023433745304641222C0A222E712063202343394531 - 4642222C0A222E7220632023433945324642222C0A222E732063202343384530 - 4642222C0A222E7420632023433544464639222C0A222E752063202343314442 - 4638222C0A222E7620632023423844364634222C0A222E772063202346384642 - 4646222C0A222E7820632023423444384636222C0A222E792063202337444230 - 4531222C0A222E7A20632023363439324442222C0A222E412063202334433839 - 4336222C0A222E4220632023463146354639222C0A222E432063202343444533 - 4643222C0A222E4420632023434545334642222C0A222E452063202343444533 - 4642222C0A222E4620632023434245324642222C0A222E472063202343384530 - 4639222C0A222E4820632023433244434638222C0A222E492063202342414436 - 4635222C0A222E4A20632023463846424644222C0A222E4B2063202343444536 - 4643222C0A222E4C20632023433945354641222C0A222E4D2063202338344236 - 4532222C0A222E4E20632023343237394246222C0A222E4F2063202334423839 - 4336222C0A222E5020632023434645334643222C0A222E512063202344304534 - 4642222C0A222E5220632023434645344643222C0A222E532063202343414531 - 4641222C0A222E5420632023433444444639222C0A222E552063202342434439 - 4636222C0A222E5620632023444645394634222C0A222E572063202346334637 - 4642222C0A222E5820632023453945464635222C0A222E592063202334353745 - 4332222C0A222E5A20632023463046344639222C0A222E302063202344334536 - 4643222C0A222E3120632023443445364643222C0A222E322063202344334537 - 4644222C0A222E3320632023443145344643222C0A222E342063202343384530 - 4641222C0A222E3520632023424244364635222C0A222E362063202342354434 - 4633222C0A222E3720632023423344324631222C0A222E382063202346304634 - 4638222C0A222E3920632023343638324334222C0A222E402063202334413838 - 4336222C0A222E2320632023454646344639222C0A222E3B2063202344374537 - 4645222C0A222E3A20632023443645374644222C0A222E3D2063202344354537 - 4644222C0A222E2B20632023443445364644222C0A222E252063202344324536 - 4643222C0A222E2420632023434345314642222C0A222E282063202343374446 - 4641222C0A222E2920632023424444414636222C0A222E5B2063202342424438 - 4636222C0A222E5D20632023454646344641222C0A222C2E2063202334363833 - 4336222C0A222C2C20632023343938384336222C0A222C2D2063202345444634 - 4639222C0A222C2A20632023443845384645222C0A222C612063202344374538 - 4645222C0A222C6220632023443645374645222C0A222C632063202344334535 - 4644222C0A222C6420632023433344444639222C0A222C652063202345444634 - 4641222C0A222C6620632023343538324336222C0A222C672063202334373834 - 4336222C0A222C6820632023454346334639222C0A222C692063202344364538 - 4645222C0A222C6A20632023434345334642222C0A222C6B2063202343364446 - 4641222C0A222C6C20632023454146324641222C0A222C6D2063202334323830 - 4336222C0A222C6E20632023343538324335222C0A222C6F2063202345424632 - 4638222C0A222C7020632023443545364644222C0A222C712063202343394131 - 3934222C0A222C7220632023433135453241222C0A222C732063202342433433 - 3035222C0A222C7420632023424635393146222C0A222C752063202337393632 - 3638222C0A222C7620632023343238304335222C0A222C772063202345384631 - 4638222C0A222C7820632023443545354645222C0A222C792063202344334535 - 4643222C0A222C7A20632023443137363344222C0A222C412063202346374235 - 3844222C0A222C4220632023464544364238222C0A222C432063202346354138 - 3732222C0A222C4420632023433936423246222C0A222C452063202334303743 - 4334222C0A222C4620632023453646304637222C0A222C472063202335354234 - 4638222C0A222C4820632023353642344637222C0A222C492063202335344235 - 4637222C0A222C4A20632023353342344638222C0A222C4B2063202335334232 - 4638222C0A222C4C20632023353242334637222C0A222C4D2063202341423533 - 3234222C0A222C4E20632023463642353844222C0A222C4F2063202346463932 - 3444222C0A222C5020632023464637373131222C0A222C512063202346463836 - 3231222C0A222C5220632023454238413430222C0A222C532063202342393434 - 3033222C0A222C5420632023334337384331222C0A222C552063202345334544 - 4637222C0A222C5620632023364543324644222C0A222C572063202341304438 - 4646222C0A222C5820632023394544374646222C0A222C592063202339424436 - 4646222C0A222C5A20632023393844374646222C0A222C302063202339364436 - 4646222C0A222C3120632023464543444145222C0A222C322063202346464646 - 4646222C0A222C3320632023454637463138222C0A222C342063202342433432 - 3034222C0A222C3520632023333837314246222C0A222C362063202344464542 - 4635222C0A222C3720632023363842464644222C0A222C382063202336374244 - 4643222C0A222C3920632023363542454642222C0A222C402063202336344245 - 4643222C0A222C2320632023363242444643222C0A222C3B2063202342303532 - 3145222C0A222C3A20632023463439443633222C0A222C3D2063202346463746 - 3138222C0A222C2B20632023463837363030222C0A222C252063202345453736 - 3030222C0A222C2420632023453136383033222C0A222C282063202342393435 - 3033222C0A222C2920632023333336394243222C0A222C5B2063202345414631 - 4638222C0A222C5D20632023444645434637222C0A222D2E2063202344454542 - 4636222C0A222D2C20632023444545414636222C0A222D2D2063202344434541 - 4636222C0A222D2A20632023454246334641222C0A222D612063202344374135 - 3841222C0A222D6220632023434136363238222C0A222D632063202345363737 - 3231222C0A222D6420632023454137393035222C0A222D652063202344443634 - 3031222C0A222D6620632023424234443036222C0A222D672063202333303635 - 4241222C0A222D6820632023333136364242222C0A222D692063202333303636 - 4241222C0A222D6A20632023324636354241222C0A222D6B2063202332453635 - 4239222C0A222D6C20632023373635453645222C0A222D6D2063202341383439 - 3139222C0A222D6E20632023424234323035222C0A222D6F2063202341443438 - 3133222C0A222D7020632023384634453339222C0A222E2E2E2E2E2C2E2D2E2D - 2E2D2E2D2E2A2E612E622E632E642E2E2E2E2E2E2E2E222C0A222E2E2E652E66 - 2E672E682E692E692E692E6A2E662E6B2E6C2E6D2E2E2E2E2E2E222C0A222E2E - 2E6E2E6F2E702E712E722E732E742E752E762E772E782E792E7A2E2E2E2E222C - 0A222E2E2E412E422E432E442E452E462E472E482E492E4A2E4B2E4C2E4D2E4E - 2E2E222C0A222E2E2E4F2E422E502E512E522E432E532E542E552E562E662E57 - 2E582E592E2E222C0A222E2E2E4F2E5A2E302E312E322E332E452E342E482E35 - 2E362E372E382E392E2E222C0A222E2E2E402E232E3B2E3A2E3D2E2B2E252E24 - 2E282E482E292E5B2E5D2C2E2E2E222C0A222E2E2C2C2C2D2C2A2C2A2C612C62 - 2C632E332E242E702C642E482C652C662E2E222C0A222E2E2C672C682C692C61 - 2E3A2E3A2E3D2C632E512C6A2E282C6B2C6C2C6D2E2E222C0A222E2E2C6E2C6F - 2C622E3A2E3A2E3A2C702C632E332C712C722C732C742C752E2E222C0A222E2E - 2C762C772C782C632C632C792C792E332C712C7A2C412C422C432C442E2E222C - 0A222E2E2C452C462C472C482C492C4A2C4B2C4C2C4D2C4E2C4F2C502C512C52 - 2C53222C0A222E2E2C542C552C562C572C582C592C5A2C302C732C312C322C32 - 2C322C332C34222C0A222E2E2C352C362C372C382C392C402C402C232C3B2C3A - 2C3D2C2B2C252C242C28222C0A222E2E2C292C5B2C5D2D2E2D2C2D2D2D2D2D2A - 2D612D622D632D642D652D662E2E222C0A222E2E2E2E2D672D682D692D692D69 - 2D672D6A2D6B2D6C2D6D2D6E2D6F2D702E2E227D0A + 36040000424D3604000000000000360000002800000010000000100000000100 + 2000000000000004000064000000640000000000000000000000000000000000 + 0000BA6530FFBB6631FFBA6630FFBA6630FFBA6630FFBA6530FFBA652FFFB965 + 2EFF6E5E76FF1949A8FF0542BBFF1348ADFF394E8FFF0000000000000000BC69 + 33FFF8F1EAFFF7ECDFFFF6EBDEFFF6EADEFFF6EADCFFF6EADCFFFAF3EBFF8AA5 + D7FF2866CAFF2177E6FF0579EAFF0164DDFF064DBBFF0000000000000000BF71 + 38FFF5EBDFFFFDBF68FFFCBD67FFFBBE65FFFCBE64FFFCBE64FFFCBD62FF1E52 + B0FF639DF4FF187FFFFF0076F8FF0076EEFF0368E1FF0345B9FF00000000C178 + 3CFFF7EDE3FFFDC26EFFFFD8A0FFFFD79EFFFFD69BFFFFD798FFFFD696FF0543 + BCFFAECDFEFFFFFFFFFFFFFFFFFFFFFFFFFF187FEFFF0442BCFF00000000C47C + 40FFF7F0E6FFF8B455FFF7B456FFF7B554FFF8B453FFF8B253FFF7B352FF2453 + ABFF8DB5F6FF4D92FFFF1177FFFF2186FFFF408AEBFF0344B9FF00000000C580 + 42FFF8F1E8FFFEE5D5FFFDE5D3FFFDE5D3FFFCE5D3FFFCE5D3FFFCE4D1FF94A1 + C9FF3D76D1FF8DB5F7FFB8D6FEFF72A8F5FF2F6BC9FF0000000000000000C582 + 45FFF8F2EBFFFEE7D6FFFDE7D6FFFDE7D6FFFDE7D6FFFDE6D5FFFDE5D3FFFCE4 + D1FF94A1C9FF2A5EC1FF0543BCFF1F59BFFF686279FF0000000000000000C684 + 47FFF9F3ECFFFEE8D6FFFEE8D7FFFDE7D6FFFDE7D6FFFDE7D5FFFDE5D3FFFBE4 + D0FFFBE3CCFFFADFC7FFFADFC6FFFAF2EAFFC68042FF0000000000000000C688 + 49FFF9F4EDFFFEE8D8FFFEE8D8FFFEE8D7FFFEE7D6FFFDE5D3FFFCE4D1FFFBE1 + CCFFFAE0C7FFF9DDC3FFF8DCC2FFFAF4EDFFC68245FF0000000000000000C688 + 4AFFF9F4EFFFFEE7D7FFFDE7D6FFFDE7D5FFFDE6D4FFFCE6D2FFFBE1CCFFFADF + C7FFF8DCC2FFF6DABDFFF6D8BBFFFAF4EFFFC68346FF0000000000000000C689 + 4BFFF9F4F0FFFCE6D3FFFCE6D4FFFDE7D3FFFCE4D1FFFBE3CDFFFAE0C8FFF8DC + C2FFF5D6BBFFF3D4B5FFF1D2B3FFF8F4F0FFC48246FF0000000000000000C689 + 4BFFF9F5F1FFFCE3CFFFFBE4D0FFFCE4CFFFFCE3CDFFFAE1CAFFF9DDC4FFF6D9 + BCFFF4E9DFFFF7F2ECFFFBF7F3FFF5EFE9FFC27E45FF0000000000000000C689 + 4CFFF9F5F1FFFCE3CDFFFBE3CEFFFBE3CDFFFBE2CBFFF9E0C8FFF8DCC2FFF5D6 + BAFFFDFBF8FFFCE6CDFFFAE5C9FFE2B684FFBF7942FF0000000000000000C588 + 4BFFFAF6F2FFFAE0C7FFFBE1C9FFFBE2C9FFFBE0C8FFF9DFC5FFF8DBC1FFF4D6 + B8FFFFFBF8FFF6D8B4FFE1B07DFFDB9264FF000000000000000000000000C485 + 49FFF7F2ECFFF8F4EEFFF8F4EDFFF8F3EDFFF8F3EDFFF8F3EDFFF8F2ECFFF7F2 + ECFFF2E6D7FFE2B27DFFDB9465FF000000000000000000000000000000000000 + 0000C88B4DFFC88C4FFFC88C4FFFC88C4FFFC88C4FFFC88D4FFFC98C4FFFC78B + 4FFFC5894BFFC4763BFF00000000000000000000000000000000 } NumGlyphs = 0 OnClick = btnRandomPresetDeleteClick @@ -890,78 +604,40 @@ object frmMain: TfrmMain Width = 23 Color = clBtnFace Glyph.Data = { - F10800002F2A2058504D202A2F0A7374617469632063686172202A6772617068 - 69635B5D203D207B0A223136203136203130342032222C0A222E2E2063204E6F - 6E65222C0A222E2C20632023464630303030222C0A222E2D2063202346443030 - 3030222C0A222E2A20632023464632423236222C0A222E612063202346463639 - 3543222C0A222E6220632023464636383542222C0A222E632063202346453637 - 3541222C0A222E6420632023464536353538222C0A222E652063202346453633 - 3536222C0A222E6620632023464536313534222C0A222E672063202346433237 - 3232222C0A222E6820632023464230303030222C0A222E692063202346463641 - 3544222C0A222E6A20632023464634373433222C0A222E6B2063202346453334 - 3334222C0A222E6C20632023464533323332222C0A222E6D2063202346443330 - 3330222C0A222E6E20632023464432443244222C0A222E6F2063202346433343 - 3338222C0A222E7020632023464335443446222C0A222E712063202346413235 - 3146222C0A222E7220632023463730303030222C0A222E732063202346463542 - 3538222C0A222E7420632023464643464346222C0A222E752063202346453532 - 3532222C0A222E7620632023464432463246222C0A222E772063202346443243 - 3243222C0A222E7820632023464334423442222C0A222E792063202346454343 - 4343222C0A222E7A20632023464234433438222C0A222E412063202346423537 - 3439222C0A222E4220632023463932333144222C0A222E432063202346353030 - 3030222C0A222E4420632023464534373433222C0A222E452063202346464633 - 4633222C0A222E4620632023464645444544222C0A222E472063202346433443 - 3443222C0A222E4820632023464334413441222C0A222E492063202346464543 - 4543222C0A222E4A20632023464646324632222C0A222E4B2063202346454341 - 4341222C0A222E4C20632023464132463241222C0A222E4D2063202346413531 - 3432222C0A222E4E20632023463330303030222C0A222E4F2063202346453333 - 3333222C0A222E5020632023464435303530222C0A222E512063202346454543 - 4543222C0A222E5220632023464133453345222C0A222E532063202346383137 - 3137222C0A222E5420632023463934453346222C0A222E552063202346313030 - 3030222C0A222E5620632023464536343537222C0A222E572063202346393344 - 3344222C0A222E5820632023463831363136222C0A222E592063202346373133 - 3133222C0A222E5A20632023463834423343222C0A222E302063202346453632 - 3535222C0A222E3120632023464332393239222C0A222E322063202346433438 - 3438222C0A222E3320632023463933413341222C0A222E342063202346373132 - 3132222C0A222E3520632023463630463046222C0A222E362063202346383438 - 3338222C0A222E3720632023464435463532222C0A222E382063202346433238 - 3238222C0A222E3920632023464334373437222C0A222E402063202346464631 - 4631222C0A222E2320632023464545414541222C0A222E3B2063202346373334 - 3334222C0A222E3A20632023463530423042222C0A222E3D2063202346383435 - 3335222C0A222E2B20632023454630303030222C0A222E252063202346443544 - 3446222C0A222E2420632023464233373332222C0A222E282063202346454342 - 4342222C0A222E2920632023464545424542222C0A222E5B2063202346393342 - 3342222C0A222E5D20632023463833393339222C0A222C2E2063202346454631 - 4631222C0A222C2C20632023464443354335222C0A222C2D2063202346363144 - 3138222C0A222C2A20632023463734333333222C0A222C612063202346393030 - 3030222C0A222C6220632023464235383441222C0A222C632063202346423437 - 3432222C0A222C6420632023464443394339222C0A222C652063202346363130 - 3130222C0A222C6620632023463733333333222C0A222C672063202346373335 - 3330222C0A222C6820632023463734343334222C0A222C692063202346323142 - 3134222C0A222C6A20632023454430303030222C0A222C6B2063202346413533 - 3434222C0A222C6C20632023463932393234222C0A222C6D2063202346353043 - 3043222C0A222C6E20632023463530393039222C0A222C6F2063202346353142 - 3136222C0A222C7020632023463131423134222C0A222C712063202346353230 - 3141222C0A222C7220632023463934433343222C0A222C732063202346383439 - 3341222C0A222C7420632023463834373338222C0A222C752063202346373433 - 3334222C0A222C7620632023463734323332222C0A222E2E2E2E2E2E2E2E2E2E - 2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E222C0A222E2E2E2E2E2E - 2E2E2E2C2E2C2E2C2E2C2E2D2E2D2E2D2E2D2E2E2E2E2E2E2E2E222C0A222E2E - 2E2E2E2E2E2C2E2A2E612E622E632E642E652E662E672E682E2E2E2E2E2E222C - 0A222E2E2E2E2E2C2E2A2E692E6A2E6B2E6C2E6D2E6E2E6F2E702E712E722E2E - 2E2E222C0A222E2E2E2C2E2A2E692E732E742E752E762E772E782E792E7A2E41 - 2E422E432E2E222C0A222E2E2E2C2E622E442E742E452E462E472E482E492E4A - 2E4B2E4C2E4D2E4E2E2E222C0A222E2E2E2C2E632E4F2E502E462E452E462E46 - 2E4A2E512E522E532E542E552E2E222C0A222E2E2E2D2E562E6D2E6E2E782E46 - 2E4A2E4A2E492E572E582E592E5A2E552E2E222C0A222E2E2E2D2E302E772E31 - 2E322E462E4A2E4A2E512E332E342E352E362E552E2E222C0A222E2E2E2D2E37 - 2E382E392E492E4A2E492E512E402E232E3B2E3A2E3D2E2B2E2E222C0A222E2E - 2E682E252E242E282E4A2E292E5B2E5D2E232C2E2C2C2C2D2C2A2E2B2E2E222C - 0A222E2E2C612E712C622C632C642E5B2E592C652C662C2C2C672C682C692C6A - 2E2E222C0A222E2E2E2E2E722E422C6B2C6C2E342E352C6D2C6E2C6F2C2A2C70 - 2C6A2E2E2E2E222C0A222E2E2E2E2E2E2E432C712C722C732C742E3D2C752C76 - 2C702C6A2E2E2E2E2E2E222C0A222E2E2E2E2E2E2E2E2E552E552E552E552E2B - 2E2B2C6A2C6A2E2E2E2E2E2E2E2E222C0A222E2E2E2E2E2E2E2E2E2E2E2E2E2E - 2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E227D0A + 36040000424D3604000000000000360000002800000010000000100000000100 + 2000000000000004000064000000640000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000000000000000000000F1FF0000F1FF0000F1FF0000F1FF0000EFFF0000 + EFFF0000EDFF0000EDFF00000000000000000000000000000000000000000000 + 0000000000000000F5FF1A20F5FF3C4CF9FF3A49F8FF3847F8FF3545F8FF3443 + F7FF3242F7FF141BF1FF0000EDFF000000000000000000000000000000000000 + 00000000F7FF1D23F9FF4453FAFF2429F9FF1212F7FF0F0FF6FF0C0CF5FF0909 + F5FF161BF5FF3343F7FF141BF1FF0000EDFF0000000000000000000000000000 + F9FF1F25FAFF4A58FBFF4247FBFFC9C9FDFF3B3BF9FF1313F7FF1010F6FF3333 + F7FFC5C5FDFF3035F7FF3444F7FF141BF2FF0000EDFF00000000000000000000 + FBFF4F5DFDFF3237FBFFCBCBFEFFF2F2FFFFEBEBFEFF3B3BF9FF3939F8FFEAEA + FEFFF1F1FEFFC5C5FDFF181DF6FF3343F7FF0000EFFF00000000000000000000 + FDFF525FFDFF2828FCFF4747FCFFECECFFFFF2F2FFFFECECFFFFECECFEFFF1F1 + FFFFEAEAFEFF3434F7FF0B0BF5FF3545F8FF0000EFFF00000000000000000000 + FDFF5562FEFF2C2CFDFF2929FCFF4848FCFFEDEDFFFFF2F2FFFFF2F2FFFFECEC + FEFF3A3AF9FF1212F7FF0F0FF6FF3848F8FF0000F1FF00000000000000000000 + FDFF5764FEFF3030FDFF2D2DFDFF4B4BFCFFEDEDFFFFF2F2FFFFF2F2FFFFECEC + FFFF3D3DF9FF1616F8FF1313F7FF3C4BF8FF0000F1FF00000000000000000000 + FFFF5A67FEFF3333FEFF5050FDFFEDEDFFFFF3F3FFFFEDEDFFFFEDEDFFFFF2F2 + FFFFECECFEFF3E3EFAFF1717F8FF3F4EF9FF0000F1FF00000000000000000000 + FFFF5B68FFFF4347FEFFCFCFFFFFF3F3FFFFEDEDFFFF4C4CFCFF4A4AFCFFECEC + FFFFF2F2FFFFCACAFEFF2A2FFAFF4251FAFF0000F3FF00000000000000000000 + FFFF262BFFFF5D6AFFFF585BFFFFCFCFFFFF5252FEFF2F2FFDFF2C2CFDFF4B4B + FCFFCCCCFEFF484CFBFF4957FBFF1D23F9FF0000F5FF00000000000000000000 + 00000000FFFF262BFFFF5D6AFFFF4347FFFF3434FEFF3232FEFF3030FDFF2D2D + FDFF383CFCFF4F5DFCFF1F25FAFF0000F7FF0000000000000000000000000000 + 0000000000000000FFFF262BFFFF5C69FFFF5B68FFFF5A67FEFF5865FEFF5663 + FEFF5461FEFF2227FCFF0000FBFF000000000000000000000000000000000000 + 000000000000000000000000FFFF0000FFFF0000FFFF0000FFFF0000FDFF0000 + FDFF0000FDFF0000FDFF00000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000 } NumGlyphs = 0 OnClick = btnClearLocationsClick @@ -975,83 +651,40 @@ object frmMain: TfrmMain Width = 23 Color = clBtnFace Glyph.Data = { - 810900002F2A2058504D202A2F0A7374617469632063686172202A6772617068 - 69635B5D203D207B0A223136203136203131332032222C0A222E2E2063204E6F - 6E65222C0A222E2C20632023444436413638222C0A222E2D2063202344433634 - 3633222C0A222E2A20632023444136343631222C0A222E612063202344393633 - 3544222C0A222E6220632023444636413641222C0A222E632063202345443933 - 3845222C0A222E6420632023463843334245222C0A222E652063202346394433 - 4343222C0A222E6620632023463943424334222C0A222E672063202346344234 - 4141222C0A222E6820632023453237303636222C0A222E692063202344313545 - 3533222C0A222E6A20632023453036393641222C0A222E6B2063202346324144 - 4141222C0A222E6C20632023464444434438222C0A222E6D2063202346414241 - 4145222C0A222E6E20632023464141333931222C0A222E6F2063202346413944 - 3842222C0A222E7020632023464241393943222C0A222E712063202346434337 - 4241222C0A222E7220632023453937423730222C0A222E732063202343433542 - 3443222C0A222E7420632023463341374133222C0A222E752063202346444442 - 4434222C0A222E7620632023464139413837222C0A222E772063202346303931 - 3746222C0A222E7820632023463138453741222C0A222E792063202346383934 - 3746222C0A222E7A20632023463939323745222C0A222E412063202346383843 - 3736222C0A222E4220632023463842364138222C0A222E432063202345333645 - 3633222C0A222E4420632023433735373435222C0A222E452063202345413833 - 3744222C0A222E4620632023464344344344222C0A222E472063202346373933 - 3745222C0A222E4820632023454538413735222C0A222E492063202346363834 - 3643222C0A222E4A20632023463337393633222C0A222E4B2063202346384146 - 4134222C0A222E4C20632023443034463345222C0A222E4D2063202344453641 - 3637222C0A222E4E20632023463541464135222C0A222E4F2063202346414142 - 3944222C0A222E5020632023463038433737222C0A222E512063202345433546 - 3534222C0A222E5220632023463237373633222C0A222E532063202346343845 - 3831222C0A222E5420632023453937463738222C0A222E552063202343303533 - 3341222C0A222E5620632023444236393634222C0A222E572063202346394239 - 4146222C0A222E5820632023464139333746222C0A222E592063202346303835 - 3730222C0A222E5A20632023464646464646222C0A222E302063202345393539 - 3444222C0A222E3120632023454536413545222C0A222E322063202346313944 - 3936222C0A222E3320632023424534463336222C0A222E342063202344413633 - 3546222C0A222E3520632023463741424131222C0A222E362063202346383836 - 3730222C0A222E3720632023463638323638222C0A222E382063202345413636 - 3543222C0A222E3920632023463139433936222C0A222E402063202342433530 - 3332222C0A222E2320632023443736323543222C0A222E3B2063202345453843 - 3831222C0A222E3A20632023463739313745222C0A222E3D2063202346333733 - 3544222C0A222E2B20632023453935423446222C0A222E252063202346303833 - 3742222C0A222E2420632023453237423735222C0A222E282063202342413442 - 3245222C0A222E2920632023444235363442222C0A222E5B2063202346364142 - 4132222C0A222E5D20632023463036343536222C0A222C2E2063202345453636 - 3532222C0A222C2C20632023453635383443222C0A222C2D2063202345363541 - 3532222C0A222C2A20632023463541333946222C0A222C612063202343343530 - 3334222C0A222C6220632023434636313533222C0A222C632063202345333642 - 3631222C0A222C6420632023463541434131222C0A222C652063202345413543 - 3530222C0A222C6620632023453635393445222C0A222C672063202345363536 - 3443222C0A222C6820632023453635363530222C0A222C692063202346344132 - 3945222C0A222C6A20632023443636303534222C0A222C6B2063202342383441 - 3241222C0A222C6C20632023434235393439222C0A222C6D2063202345303635 - 3543222C0A222C6E20632023463541364131222C0A222C6F2063202345463836 - 3745222C0A222C7020632023453936333542222C0A222C712063202345373544 - 3539222C0A222C7220632023454538343744222C0A222C732063202346344130 - 3945222C0A222C7420632023443735443531222C0A222C752063202342373441 - 3242222C0A222C7620632023433635353432222C0A222C772063202343433532 - 3343222C0A222C7820632023453837413735222C0A222C792063202345453932 - 3846222C0A222C7A20632023453437383731222C0A222C412063202343313444 - 3333222C0A222C4220632023424535333338222C0A222C432063202342443531 - 3335222C0A222C4420632023424334423330222C0A222C452063202342383445 - 3245222C0A222E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E - 2E2E2E2E2E2E222C0A222E2E2E2E2E2E2E2E2E2E2E2E2E2C2E2D2E2A2E612E2E - 2E2E2E2E2E2E2E2E2E2E222C0A222E2E2E2E2E2E2E2E2E622E632E642E652E66 - 2E672E682E692E2E2E2E2E2E2E2E222C0A222E2E2E2E2E2E2E6A2E6B2E6C2E6D - 2E6E2E6F2E702E712E722E732E2E2E2E2E2E222C0A222E2E2E2E2E6A2E742E75 - 2E762E772E782E792E7A2E412E422E432E442E2E2E2E222C0A222E2E2E2E2E45 - 2E462E6F2E472E482E492E492E492E492E4A2E4B2E4C2E2E2E2E222C0A222E2E - 2E4D2E4E2E4F2E502E512E512E512E512E512E512E522E532E542E552E2E222C - 0A222E2E2E562E572E582E592E5A2E5A2E5A2E5A2E5A2E5A2E302E312E322E33 - 2E2E222C0A222E2E2E342E352E362E372E5A2E5A2E5A2E5A2E5A2E5A2E302E38 - 2E392E402E2E222C0A222E2E2E232E3B2E3A2E3D2E302E302E302E302E302E30 - 2E2B2E252E242E282E2E222C0A222E2E2E2E2E292E5B2E5D2C2E2E302E302E30 - 2E302C2C2C2D2C2A2C612E2E2E2E222C0A222E2E2E2E2C622C632C642E512C65 - 2E302C662C672C682C692C6A2C6B2E2E2E2E222C0A222E2E2E2E2E2E2C6C2C6D - 2C6E2C6F2C702C712C722C732C742C752E2E2E2E2E2E222C0A222E2E2E2E2E2E - 2E2E2C762C772C782C792C792C7A2C412C752E2E2E2E2E2E2E2E222C0A222E2E - 2E2E2E2E2E2E2E2E2E2E2C422C432C442C452E2E2E2E2E2E2E2E2E2E2E2E222C - 0A222E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E - 2E2E227D0A + 36040000424D3604000000000000360000002800000010000000100000000100 + 2000000000000004000064000000640000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000003853BEFF3551BDFF304BBCFF2E4E + B8FF000000000000000000000000000000000000000000000000000000000000 + 000000000000000000004255C6FF3C52CCFF757AE8FF8F92EEFF8F92EEFF7178 + E4FF334DC1FF2B4AB7FF00000000000000000000000000000000000000000000 + 0000000000004959CBFF5C65E0FFA1A6F5FF7E86EFFF5B63E9FF595DE7FF7D84 + EEFF9EA0F4FF515DD7FF2B4AB7FF000000000000000000000000000000000000 + 00005361CFFF616BE3FFA1ACF5FF545FECFF505CEAFF4D59E9FF4E59E6FF4C56 + E6FF5056E6FF9EA2F4FF5460D6FF2A4AB8FF0000000000000000000000000000 + 00004B56DBFFA2ABF6FF5664F0FF5266EEFF4D59E9FF4D59E9FF4D59E9FF4D59 + E9FF4C58E6FF525AE6FF9FA3F5FF3450C4FF0000000000000000000000005C62 + D7FF818CEEFF7E91F7FF5D73F3FF4D59E9FF4D59E9FF4D59E9FF4D59E9FF4D59 + E9FF4D59E9FF4F5BE9FF7B83F0FF757BE2FF2E4BBAFF00000000000000005F63 + DAFFA1ABF7FF7086F8FF6882F6FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFF4D59E9FF5C66EAFF969CF1FF3250BCFF00000000000000006469 + DBFFAFB9F9FF7F93FAFF7085F0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFF4D59E9FF5E6AEEFF969DF1FF364FBEFF0000000000000000676A + DEFFA5AFF5FF9DABFAFF778CF0FF545FECFF545FECFF545FECFF545FECFF545F + ECFF545FECFF6377F2FF818EF4FF787FE9FF3A53C0FF00000000000000000000 + 00007D83EAFFCDD4FCFF8B9DFAFF7E93F7FF758AEEFF6C84F6FF6C84F6FF6C84 + F6FF6C84F6FF6379F3FFA4AFF8FF3E4FD0FF0000000000000000000000000000 + 00006A69E0FFA3A7F3FFD4DBFDFF879AFAFF7F91F0FF7A8EF1FF7F94F8FF7E92 + F9FF768CF8FFA8B6F8FF636EE3FF4557C7FF0000000000000000000000000000 + 0000000000006A69E0FFAAADF2FFD8DCFDFFAEBAFAFF91A3FAFF8B9DFAFF9CA9 + FBFFBAC7FCFF707BE9FF4C5BCCFF000000000000000000000000000000000000 + 000000000000000000006A6ADFFF8E93EDFFBEC3F8FFCCD3F9FFC4CBF9FFAAB4 + F4FF6670E2FF535ED1FF00000000000000000000000000000000000000000000 + 000000000000000000000000000000000000686ADDFF6364DCFF6164DAFF5D63 + D9FF000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000 } NumGlyphs = 0 OnClick = btnDeleteLocationClick @@ -1065,86 +698,40 @@ object frmMain: TfrmMain Width = 23 Color = clBtnFace Glyph.Data = { - F10900002F2A2058504D202A2F0A7374617469632063686172202A6772617068 - 69635B5D203D207B0A223136203136203132302032222C0A222E2E2063204E6F - 6E65222C0A222E2C20632023383442363645222C0A222E2D2063202338304233 - 3641222C0A222E2A20632023374342313637222C0A222E612063202337374145 - 3633222C0A222E6220632023383742383731222C0A222E632063202341344345 - 3934222C0A222E6420632023434245364333222C0A222E652063202344344542 - 4346222C0A222E6620632023434545394339222C0A222E672063202342384444 - 4146222C0A222E6820632023374642393644222C0A222E692063202336394135 - 3538222C0A222E6A20632023383742383730222C0A222E6B2063202342424443 - 4146222C0A222E6C20632023453046324443222C0A222E6D2063202342444534 - 4236222C0A222E6E20632023413544423942222C0A222E6F2063202341304439 - 3936222C0A222E7020632023414644464135222C0A222E712063202343354538 - 4330222C0A222E7220632023384143323739222C0A222E732063202335463945 - 3530222C0A222E7420632023423744414141222C0A222E752063202344434631 - 4438222C0A222E7620632023394444383932222C0A222E772063202339334344 - 3838222C0A222E7820632023384543433834222C0A222E792063202339364434 - 3842222C0A222E7A20632023393544343841222C0A222E412063202338454432 - 3833222C0A222E4220632023423745304146222C0A222E432063202337444239 - 3642222C0A222E4420632023353639383438222C0A222E452063202339374337 - 3835222C0A222E4620632023443745454432222C0A222E472063202341304439 - 3935222C0A222E4820632023393444333841222C0A222E492063202338394338 - 3746222C0A222E4A20632023464646464646222C0A222E4B2063202338354344 - 3739222C0A222E4C20632023374343333642222C0A222E4D2063202337454337 - 3646222C0A222E4E20632023423544464143222C0A222E4F2063202335373945 - 3435222C0A222E5020632023383342353644222C0A222E512063202342364444 - 4143222C0A222E5220632023414644464136222C0A222E532063202338434342 - 3831222C0A222E5420632023383643393743222C0A222E552063202337394244 - 3645222C0A222E5620632023364141433542222C0A222E572063202337374243 - 3630222C0A222E5820632023373342413543222C0A222E592063202339394431 - 3842222C0A222E5A20632023393243353830222C0A222E302063202334373845 - 3343222C0A222E3120632023374542323639222C0A222E322063202342454532 - 4236222C0A222E3320632023393744353842222C0A222E342063202338364339 - 3741222C0A222E3520632023373042383539222C0A222E362063202337454331 - 3639222C0A222E3720632023414144343944222C0A222E382063202334323842 - 3338222C0A222E3920632023374141463635222C0A222E402063202342334444 - 4139222C0A222E2320632023384143463744222C0A222E3B2063202338314343 - 3735222C0A222E3A20632023374442453637222C0A222E3D2063202341424434 - 3943222C0A222E2B20632023334438383334222C0A222E252063202337354143 - 3631222C0A222E2420632023393843433841222C0A222E282063202339364433 - 3839222C0A222E2920632023374143363642222C0A222E5B2063202337304331 - 3633222C0A222E5D20632023363541423535222C0A222C2E2063202337324239 - 3542222C0A222C2C20632023393743433835222C0A222C2D2063202338444245 - 3742222C0A222C2A20632023333938353330222C0A222C612063202336384142 - 3533222C0A222C6220632023423444444141222C0A222C632063202337394331 - 3634222C0A222C6420632023373142453546222C0A222C652063202336454235 - 3538222C0A222C6620632023373442373543222C0A222C672063202342344441 - 4136222C0A222C6820632023343338463338222C0A222C692063202336364133 - 3536222C0A222C6A20632023374442393641222C0A222C6B2063202342324442 - 4138222C0A222C6C20632023364642353539222C0A222C6D2063202336464235 - 3538222C0A222C6E20632023373442373542222C0A222C6F2063202342334439 - 4135222C0A222C7020632023364341413541222C0A222C712063202333343832 - 3243222C0A222C7220632023354439433444222C0A222C732063202337384234 - 3634222C0A222C7420632023423544424138222C0A222C752063202339384343 - 3837222C0A222C7620632023374442433636222C0A222C772063202337434241 - 3634222C0A222C7820632023393843423836222C0A222C792063202342344439 - 4135222C0A222C7A20632023364241413538222C0A222C412063202333343831 - 3243222C0A222C4220632023353339363435222C0A222C432063202335303939 - 3431222C0A222C4420632023384643323744222C0A222C452063202341364430 - 3936222C0A222C4620632023413643463936222C0A222C472063202338394245 - 3738222C0A222C4820632023343238443336222C0A222C492063202334343843 - 3341222C0A222C4A20632023343038393336222C0A222C4B2063202333433837 - 3332222C0A222C4C20632023333738343246222C0A222E2E2E2E2E2E2E2E2E2E - 2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E222C0A222E2E2E2E2E2E - 2E2E2E2E2E2E2E2C2E2D2E2A2E612E2E2E2E2E2E2E2E2E2E2E2E222C0A222E2E - 2E2E2E2E2E2E2E622E632E642E652E662E672E682E692E2E2E2E2E2E2E2E222C - 0A222E2E2E2E2E2E2E6A2E6B2E6C2E6D2E6E2E6F2E702E712E722E732E2E2E2E - 2E2E222C0A222E2E2E2E2E6A2E742E752E762E772E782E792E7A2E412E422E43 - 2E442E2E2E2E222C0A222E2E2E2E2E452E462E472E482E492E4A2E4A2E4B2E4C - 2E4D2E4E2E4F2E2E2E2E222C0A222E2E2E502E512E522E532E542E552E4A2E4A - 2E562E572E582E592E5A2E302E2E222C0A222E2E2E312E322E332E342E4A2E4A - 2E4A2E4A2E4A2E4A2E352E362E372E382E2E222C0A222E2E2E392E402E232E3B - 2E4A2E4A2E4A2E4A2E4A2E4A2E352E3A2E3D2E2B2E2E222C0A222E2E2E252E24 - 2E282E292E5B2E5D2E4A2E4A2E352E352C2E2C2C2C2D2C2A2E2E222C0A222E2E - 2E2E2C612C622C632C642E572E4A2E4A2E352C652C662C672C682E2E2E2E222C - 0A222E2E2E2E2C692C6A2C6B2E572E582E352C6C2C6D2C6E2C6F2C702C712E2E - 2E2E222C0A222E2E2E2E2E2E2C722C732C742C752C762C772C782C792C7A2C41 - 2E2E2E2E2E2E222C0A222E2E2E2E2E2E2E2E2C422C432C442C452C462C472C48 - 2C412E2E2E2E2E2E2E2E222C0A222E2E2E2E2E2E2E2E2E2E2E2E2C492C4A2C4B - 2C4C2E2E2E2E2E2E2E2E2E2E2E2E222C0A222E2E2E2E2E2E2E2E2E2E2E2E2E2E - 2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E227D0A + 36040000424D3604000000000000360000002800000010000000100000000100 + 2000000000000004000064000000640000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000003A8C44FF368940FF32873CFF2F84 + 37FF000000000000000000000000000000000000000000000000000000000000 + 00000000000000000000459653FF419950FF7DC28FFF96D0A6FF96CFA6FF78BE + 89FF368D42FF2C8134FF00000000000000000000000000000000000000000000 + 0000000000004D9C5DFF64B478FFA8DBB5FF87CC98FF66BC7DFF64BA7CFF86CB + 98FFA5D9B4FF58AA6BFF2C8134FF000000000000000000000000000000000000 + 000056A366FF6AB97DFFA8DBB2FF60BC77FF5CBA73FF59B870FF59B56FFF58B5 + 6FFF5BB774FFA5D9B3FF5AAA6CFF2C8234FF0000000000000000000000000000 + 000053AB68FFAADDB4FF64C179FF5FBE71FF60BC77FFFFFFFFFFFFFFFFFF59B8 + 70FF58B56EFF5CB774FFA6DAB4FF388F43FF00000000000000000000000061AC + 75FF8ACC98FF89D396FF6BC67AFF63C170FF55AB65FFFFFFFFFFFFFFFFFF59B8 + 70FF59B870FF5BB972FF85CC97FF7BBE8DFF308539FF000000000000000065AF + 7AFFA9DDB3FF7DCF8AFF75CC81FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFF59B870FF67BE7DFF9CD4ABFF34883DFF000000000000000069B2 + 7EFFB6E2BEFF8BD597FF7AC986FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFF59B870FF69C17EFF9DD4AAFF388B42FF00000000000000006DB5 + 83FFACDDB6FFA6DFAFFF81CB8CFF7CC986FF6EBD79FFFFFFFFFFFFFFFFFF5BAC + 6AFF60BC77FF5CBA73FF8BD199FF80C592FF3C8E47FF00000000000000000000 + 000085C797FFD2EED7FF95D9A0FF8AD394FF7FC889FFFFFFFFFFFFFFFFFF79CD + 85FF6BC37CFF6FC77EFFACDFB5FF459E57FF0000000000000000000000000000 + 000070B887FFAADAB7FFD8F1DCFF92D89DFF88CD93FF84CC8EFF8BD496FF8AD4 + 95FF83D28EFFAFE0B7FF6BB97DFF489856FF0000000000000000000000000000 + 00000000000070B887FFAFDCBBFFDCF2E0FFB6E4BDFF9BDBA5FF96D9A0FFA5DF + AFFFC0E8C5FF79C28AFF509E5FFF000000000000000000000000000000000000 + 0000000000000000000071B887FF94CEA4FFC3E6CBFFCFEBD4FFC9E9CEFFAFDD + B8FF6DB97FFF58A569FF00000000000000000000000000000000000000000000 + 0000000000000000000000000000000000006EB684FF6AB380FF67B17CFF63AE + 77FF000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000 } NumGlyphs = 0 OnClick = btnAddLocationClick diff --git a/Server/UAccount.pas b/Server/UAccount.pas index cf102fc..b277cae 100644 --- a/Server/UAccount.pas +++ b/Server/UAccount.pas @@ -1,181 +1,213 @@ -(* - * 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 2007 Andreas Schneider - *) -unit UAccount; - -{$mode objfpc}{$H+} - -interface - -uses - Classes, SysUtils, md5, contnrs, math, UEnums; - -type - - { TAccount } - - TAccount = class(TObject) - constructor Create(AAccountString: string); - constructor Create(AName, APasswordHash: string; AAccessLevel: TAccessLevel); - protected - FName: string; - FAccessLevel: TAccessLevel; - FPasswordHash: string; - FLastPos: TPoint; - procedure SetAccessLevel(const AValue: TAccessLevel); - procedure SetPasswordHash(const AValue: string); - procedure SetLastPos(const AValue: TPoint); - public - property Name: string read FName; - property AccessLevel: TAccessLevel read FAccessLevel write SetAccessLevel; - property PasswordHash: string read FPasswordHash write SetPasswordHash; - property LastPos: TPoint read FLastPos write SetLastPos; - procedure Flush; - end; - - { TAccountList } - - TAccountList = class(TObjectList) - constructor Create; reintroduce; - public - function IndexOf(AName: string): Integer; - function Find(AName: string): TAccount; - procedure Delete(AName: string); - end; - -implementation - -uses - UCEDServer, UConfig; - -{ TAccount } - -constructor TAccount.Create(AAccountString: string); -var - i: Integer; - attribs: TStringList; -begin - inherited Create; - i := Pos('=', AAccountString); - if i > 0 then - FName := Trim(Copy(AAccountString, 1, i-1)); - AAccountString := Copy(AAccountString, i+1, Length(AAccountString)); - - attribs := TStringList.Create; - if ExtractStrings([':'], [' '], PChar(AAccountString), attribs) >= 2 then - begin - FAccessLevel := TAccessLevel(StrToInt(attribs.Strings[0])); - FPasswordHash := attribs.Strings[1]; - end; - if attribs.Count >= 4 then - begin - FLastPos.x := EnsureRange(StrToInt(attribs.Strings[2]), 0, Config.ReadInteger('Parameters', 'Width', 0) * 8 - 1); - FLastPos.y := EnsureRange(StrToInt(attribs.Strings[3]), 0, Config.ReadInteger('Parameters', 'Height', 0) * 8 - 1); - end else - begin - FLastPos.x := 0; - FLastPos.y := 0; - end; - attribs.Free; -end; - -constructor TAccount.Create(AName, APasswordHash: string; - AAccessLevel: TAccessLevel); -begin - inherited Create; - FName := AName; - FPasswordHash := APasswordHash; - FAccessLevel := AAccessLevel; - Flush; -end; - -procedure TAccount.SetAccessLevel(const AValue: TAccessLevel); -begin - FAccessLevel := AValue; - Flush; -end; - -procedure TAccount.SetPasswordHash(const AValue: string); -begin - FPasswordHash := AValue; - Flush; -end; - -procedure TAccount.SetLastPos(const AValue: TPoint); -begin - FLastPos.x := EnsureRange(AValue.x, 0, CEDServerInstance.Landscape.CellWidth - 1); - FLastPos.y := EnsureRange(AValue.y, 0, CEDServerInstance.Landscape.CellHeight - 1); - Flush; -end; - -procedure TAccount.Flush; -begin - Config.WriteString('Accounts', FName, IntToStr(Byte(FAccessLevel)) + ':' + - FPasswordHash + ':' + IntToStr(FLastPos.x) + ':' + IntToStr(FLastPos.y)); -end; - -{ TAccountList } - -constructor TAccountList.Create; -begin - inherited Create(True); -end; - -function TAccountList.IndexOf(AName: string): Integer; -var - i: Integer; -begin - Result := -1; - i := 0; - while (i < Count) and (Result = -1) do - begin - if TAccount(Items[i]).Name = AName then - Result := i; - Inc(i); - end; -end; - -function TAccountList.Find(AName: string): TAccount; -var - i: Integer; -begin - i := IndexOf(AName); - if i > -1 then - Result := TAccount(Items[i]) - else - Result := nil; -end; - -procedure TAccountList.Delete(AName: string); -var - i: Integer; -begin - i := IndexOf(AName); - if i > -1 then - inherited Delete(i); -end; - -end. - +(* + * 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 2008 Andreas Schneider + *) +unit UAccount; + +{$mode objfpc}{$H+} + +interface + +uses + Classes, SysUtils, md5, contnrs, math, DOM, UXmlHelper, UInterfaces, + UEnums; + +type + + { TAccount } + + TAccount = class(TObject, ISerializable, IInvalidate) + constructor Create(AOwner: IInvalidate; AName, APasswordHash: string; + AAccessLevel: TAccessLevel); + constructor Deserialize(AOwner: IInvalidate; AElement: TDOMElement); + procedure Serialize(AElement: TDOMElement); + protected + FOwner: IInvalidate; + FName: string; + FAccessLevel: TAccessLevel; + FPasswordHash: string; + FLastPos: TPoint; + procedure SetAccessLevel(const AValue: TAccessLevel); + procedure SetPasswordHash(const AValue: string); + procedure SetLastPos(const AValue: TPoint); + public + property Name: string read FName; + property AccessLevel: TAccessLevel read FAccessLevel write SetAccessLevel; + property PasswordHash: string read FPasswordHash write SetPasswordHash; + property LastPos: TPoint read FLastPos write SetLastPos; + procedure Invalidate; + end; + + { TAccountList } + + TAccountList = class(TObjectList, ISerializable, IInvalidate) + constructor Create(AOwner: IInvalidate); reintroduce; + constructor Deserialize(AOwner: IInvalidate; AElement: TDOMElement); + procedure Serialize(AElement: TDOMElement); + protected + FOwner: IInvalidate; + public + function IndexOf(AName: string): Integer; + function Find(AName: string): TAccount; + procedure Delete(AName: string); + procedure Invalidate; + end; + +implementation + +uses + UCEDServer, UConfig; + +{ TAccount } + +constructor TAccount.Create(AOwner: IInvalidate; AName, APasswordHash: string; + AAccessLevel: TAccessLevel); +begin + inherited Create; + FOwner := AOwner; + FName := AName; + FPasswordHash := APasswordHash; + FAccessLevel := AAccessLevel; +end; + +constructor TAccount.Deserialize(AOwner: IInvalidate; AElement: TDOMElement); +begin + inherited Create; + FOwner := AOwner; + FName := TXmlHelper.ReadString(AElement, 'Name', ''); + FAccessLevel := TAccessLevel(TXmlHelper.ReadInteger(AElement, 'AccessLevel', 0)); + FPasswordHash := TXmlHelper.ReadString(AElement, 'PasswordHash', ''); + FLastPos := Point(0, 0); + TXmlHelper.ReadCoords(AElement, 'LastPos', FLastPos.X, FLastPos.Y); +end; + +procedure TAccount.SetAccessLevel(const AValue: TAccessLevel); +begin + FAccessLevel := AValue; + Invalidate; +end; + +procedure TAccount.SetPasswordHash(const AValue: string); +begin + FPasswordHash := AValue; + Invalidate; +end; + +procedure TAccount.SetLastPos(const AValue: TPoint); +begin + FLastPos.x := EnsureRange(AValue.x, 0, CEDServerInstance.Landscape.CellWidth - 1); + FLastPos.y := EnsureRange(AValue.y, 0, CEDServerInstance.Landscape.CellHeight - 1); + Invalidate; +end; + +procedure TAccount.Invalidate; +begin + FOwner.Invalidate; +end; + +procedure TAccount.Serialize(AElement: TDOMElement); +begin + TXmlHelper.WriteString(AElement, 'Name', FName); + TXmlHelper.WriteString(AElement, 'PasswordHash', FPasswordHash); + TXmlHelper.WriteInteger(AElement, 'AccessLevel', Integer(FAccessLevel)); + TXmlHelper.WriteCoords(AElement, 'LastPos', FLastPos.X, FLastPos.Y); +end; + +{ TAccountList } + +constructor TAccountList.Create(AOwner: IInvalidate); +begin + inherited Create(True); + FOwner := AOwner; +end; + +constructor TAccountList.Deserialize(AOwner: IInvalidate; AElement: TDOMElement); +var + nodelist: TDOMNodeList; + i: Integer; +begin + Create(AOwner); + nodeList := AElement.GetChildNodes; + for i := 0 to nodeList.Count - 1 do + begin + if nodeList.Item[i].NodeName = 'Account' then + Add(TAccount.Deserialize(Self, TDOMElement(nodeList.Item[i]))); + end; + nodeList.Free; +end; + +function TAccountList.IndexOf(AName: string): Integer; +var + i: Integer; +begin + Result := -1; + i := 0; + while (i < Count) and (Result = -1) do + begin + if TAccount(Items[i]).Name = AName then + Result := i; + Inc(i); + end; +end; + +function TAccountList.Find(AName: string): TAccount; +var + i: Integer; +begin + i := IndexOf(AName); + if i > -1 then + Result := TAccount(Items[i]) + else + Result := nil; +end; + +procedure TAccountList.Delete(AName: string); +var + i: Integer; +begin + i := IndexOf(AName); + if i > -1 then + inherited Delete(i); +end; + +procedure TAccountList.Invalidate; +begin + FOwner.Invalidate; +end; + +procedure TAccountList.Serialize(AElement: TDOMElement); +var + i: Integer; + xmlAccount: TDOMElement; +begin + for i := 0 to Count - 1 do + begin + xmlAccount := AElement.OwnerDocument.CreateElement('Account'); + AElement.AppendChild(xmlAccount); + TAccount(Items[i]).Serialize(xmlAccount); + end; +end; + +end. + diff --git a/Server/UAdminHandling.pas b/Server/UAdminHandling.pas index 4312e16..a66d3bd 100644 --- a/Server/UAdminHandling.pas +++ b/Server/UAdminHandling.pas @@ -1,226 +1,229 @@ -(* - * 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 2007 Andreas Schneider - *) -unit UAdminHandling; - -{$mode objfpc}{$H+} - -interface - -uses - Classes, SysUtils, UPacket, UPacketHandlers, UConfig, UAccount, UNetState, - UEnhancedMemoryStream, UEnums, lNet; - -type - - { TModifyUserResponsePacket } - - TModifyUserResponsePacket = class(TPacket) - constructor Create(AStatus: TModifyUserStatus; AAccount: TAccount); - end; - - { TDeleteUserResponsePacket } - - TDeleteUserResponsePacket = class(TPacket) - constructor Create(AStatus: TDeleteUserStatus; AUsername: string); - end; - - { TUserListPacket } - - TUserListPacket = class(TPacket) - constructor Create; - end; - -procedure OnAdminHandlerPacket(ABuffer: TEnhancedMemoryStream; ANetState: TNetState); -procedure OnFlushPacket(ABuffer: TEnhancedMemoryStream; ANetState: TNetState); -procedure OnQuitPacket(ABuffer: TEnhancedMemoryStream; ANetState: TNetState); -procedure OnModifyUserPacket(ABuffer: TEnhancedMemoryStream; ANetState: TNetState); -procedure OnDeleteUserPacket(ABuffer: TEnhancedMemoryStream; ANetState: TNetState); -procedure OnListUsersPacket(ABuffer: TEnhancedMemoryStream; ANetState: TNetState); - -var - AdminPacketHandlers: array[0..$FF] of TPacketHandler; - -implementation - -uses - md5, UCEDServer, UPackets, UClientHandling; - -procedure OnAdminHandlerPacket(ABuffer: TEnhancedMemoryStream; ANetState: TNetState); -var - packetHandler: TPacketHandler; -begin - if not ValidateAccess(ANetState, alAdministrator) then Exit; - packetHandler := AdminPacketHandlers[ABuffer.ReadByte]; - if packetHandler <> nil then - packetHandler.Process(ABuffer, ANetState); -end; - -procedure OnFlushPacket(ABuffer: TEnhancedMemoryStream; ANetState: TNetState); -begin - CEDServerInstance.Landscape.Flush; -end; - -procedure OnQuitPacket(ABuffer: TEnhancedMemoryStream; ANetState: TNetState); -begin - CEDServerInstance.Quit := True; -end; - -procedure OnModifyUserPacket(ABuffer: TEnhancedMemoryStream; - ANetState: TNetState); -var - account: TAccount; - username, password: string; - accessLevel: TAccessLevel; - netState: TNetState; -begin - username := ABuffer.ReadStringNull; - password := ABuffer.ReadStringNull; - accessLevel := TAccessLevel(ABuffer.ReadByte); - account := Accounts.Find(username); - if account <> nil then - begin - if password <> '' then - account.PasswordHash := MD5Print(MD5String(password)); - if account.AccessLevel <> accessLevel then - begin - account.AccessLevel := accessLevel; - CEDServerInstance.TCPServer.IterReset; - while CEDServerInstance.TCPServer.IterNext do - begin - netState := TNetState(CEDServerInstance.TCPServer.Iterator.UserData); - if (netState <> nil) and (netState.Account = account) then - begin - CEDServerInstance.SendPacket(netState, TAccessLevelChangedPacket.Create(accessLevel)); - end; - end; - end; - CEDServerInstance.SendPacket(ANetState, TModifyUserResponsePacket.Create(muModified, account)); - end else - begin - account := TAccount.Create(username, MD5Print(MD5String(password)), accessLevel); - if (username = '') or (Pos('=', username) > 0) then - begin - CEDServerInstance.SendPacket(ANetState, TModifyUserResponsePacket.Create(muInvalidUsername, account)); - account.Free; - Exit; - end; - Accounts.Add(account); - CEDServerInstance.SendPacket(ANetState, TModifyUserResponsePacket.Create(muAdded, account)); - end; -end; - -procedure OnDeleteUserPacket(ABuffer: TEnhancedMemoryStream; - ANetState: TNetState); -var - account: TAccount; - username: string; - netState: TNetState; -begin - username := ABuffer.ReadStringNull; - account := Accounts.Find(username); - if (account <> nil) and (account <> ANetState.Account) then - begin - Config.DeleteKey('Accounts', username); - CEDServerInstance.TCPServer.IterReset; - while CEDServerInstance.TCPServer.IterNext do - begin - netState := TNetState(CEDServerInstance.TCPServer.Iterator.UserData); - if (netState <> nil) and (netState.Account = account) then - begin - CEDServerInstance.Disconnect(CEDServerInstance.TCPServer.Iterator); - netState.Account := nil; - end; - end; - Accounts.Remove(account); - CEDServerInstance.SendPacket(ANetState, TDeleteUserResponsePacket.Create(duDeleted, username)); - end else - CEDServerInstance.SendPacket(ANetState, TDeleteUserResponsePacket.Create(duNotFound, username)); -end; - -procedure OnListUsersPacket(ABuffer: TEnhancedMemoryStream; ANetState: TNetState); -begin - CEDServerInstance.SendPacket(ANetState, TCompressedPacket.Create(TUserListPacket.Create)); -end; - -{ TModifyUserResponsePacket } - -constructor TModifyUserResponsePacket.Create(AStatus: TModifyUserStatus; AAccount: TAccount); -begin - inherited Create($03, 0); - FStream.WriteByte($05); - FStream.WriteByte(Byte(AStatus)); - FStream.WriteStringNull(AAccount.Name); - FStream.WriteByte(Byte(AAccount.AccessLevel)); -end; - -{ TDeleteUserResponsePacket } - -constructor TDeleteUserResponsePacket.Create(AStatus: TDeleteUserStatus; AUsername: string); -begin - inherited Create($03, 0); - FStream.WriteByte($06); - FStream.WriteByte(Byte(AStatus)); - FStream.WriteStringNull(AUsername); -end; - -{ TUserListPacket } - -constructor TUserListPacket.Create; -var - i: Integer; - account: TAccount; -begin - inherited Create($03, 0); - FStream.WriteByte($07); - FStream.WriteWord(Accounts.Count); - for i := 0 to Accounts.Count - 1 do - begin - account := TAccount(Accounts.Items[i]); - FStream.WriteStringNull(account.Name); - FStream.WriteByte(Byte(account.AccessLevel)); - end; -end; - -{$WARNINGS OFF} -var - i: Integer; - -initialization - for i := 0 to $FF do - AdminPacketHandlers[i] := nil; - AdminPacketHandlers[$01] := TPacketHandler.Create(0, @OnFlushPacket); - AdminPacketHandlers[$02] := TPacketHandler.Create(0, @OnQuitPacket); - AdminPacketHandlers[$05] := TPacketHandler.Create(0, @OnModifyUserPacket); - AdminPacketHandlers[$06] := TPacketHandler.Create(0, @OnDeleteUserPacket); - AdminPacketHandlers[$07] := TPacketHandler.Create(0, @OnListUsersPacket); -finalization - for i := 0 to $FF do - if AdminPacketHandlers[i] <> nil then - AdminPacketHandlers[i].Free; -{$WARNINGS ON} - -end. - +(* + * 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 2008 Andreas Schneider + *) +unit UAdminHandling; + +{$mode objfpc}{$H+} + +interface + +uses + Classes, SysUtils, UPacket, UPacketHandlers, UConfig, UAccount, UNetState, + UEnhancedMemoryStream, UEnums, lNet; + +type + + { TModifyUserResponsePacket } + + TModifyUserResponsePacket = class(TPacket) + constructor Create(AStatus: TModifyUserStatus; AAccount: TAccount); + end; + + { TDeleteUserResponsePacket } + + TDeleteUserResponsePacket = class(TPacket) + constructor Create(AStatus: TDeleteUserStatus; AUsername: string); + end; + + { TUserListPacket } + + TUserListPacket = class(TPacket) + constructor Create; + end; + +procedure OnAdminHandlerPacket(ABuffer: TEnhancedMemoryStream; ANetState: TNetState); +procedure OnFlushPacket(ABuffer: TEnhancedMemoryStream; ANetState: TNetState); +procedure OnQuitPacket(ABuffer: TEnhancedMemoryStream; ANetState: TNetState); +procedure OnModifyUserPacket(ABuffer: TEnhancedMemoryStream; ANetState: TNetState); +procedure OnDeleteUserPacket(ABuffer: TEnhancedMemoryStream; ANetState: TNetState); +procedure OnListUsersPacket(ABuffer: TEnhancedMemoryStream; ANetState: TNetState); + +var + AdminPacketHandlers: array[0..$FF] of TPacketHandler; + +implementation + +uses + md5, UCEDServer, UPackets, UClientHandling; + +procedure OnAdminHandlerPacket(ABuffer: TEnhancedMemoryStream; ANetState: TNetState); +var + packetHandler: TPacketHandler; +begin + if not ValidateAccess(ANetState, alAdministrator) then Exit; + packetHandler := AdminPacketHandlers[ABuffer.ReadByte]; + if packetHandler <> nil then + packetHandler.Process(ABuffer, ANetState); +end; + +procedure OnFlushPacket(ABuffer: TEnhancedMemoryStream; ANetState: TNetState); +begin + CEDServerInstance.Landscape.Flush; + Config.Flush; +end; + +procedure OnQuitPacket(ABuffer: TEnhancedMemoryStream; ANetState: TNetState); +begin + CEDServerInstance.Quit := True; +end; + +procedure OnModifyUserPacket(ABuffer: TEnhancedMemoryStream; + ANetState: TNetState); +var + account: TAccount; + username, password: string; + accessLevel: TAccessLevel; + netState: TNetState; +begin + username := ABuffer.ReadStringNull; + password := ABuffer.ReadStringNull; + accessLevel := TAccessLevel(ABuffer.ReadByte); + account := Config.Accounts.Find(username); + if account <> nil then + begin + if password <> '' then + account.PasswordHash := MD5Print(MD5String(password)); + if account.AccessLevel <> accessLevel then + begin + account.AccessLevel := accessLevel; + CEDServerInstance.TCPServer.IterReset; + while CEDServerInstance.TCPServer.IterNext do + begin + netState := TNetState(CEDServerInstance.TCPServer.Iterator.UserData); + if (netState <> nil) and (netState.Account = account) then + begin + CEDServerInstance.SendPacket(netState, TAccessLevelChangedPacket.Create(accessLevel)); + end; + end; + end; + CEDServerInstance.SendPacket(ANetState, TModifyUserResponsePacket.Create(muModified, account)); + end else + begin + account := TAccount.Create(Config.Accounts, username, + MD5Print(MD5String(password)), accessLevel); + if (username = '') or (Pos('=', username) > 0) then + begin + CEDServerInstance.SendPacket(ANetState, TModifyUserResponsePacket.Create(muInvalidUsername, account)); + account.Free; + Exit; + end; + Config.Accounts.Add(account); + Config.Invalidate; + CEDServerInstance.SendPacket(ANetState, TModifyUserResponsePacket.Create(muAdded, account)); + end; +end; + +procedure OnDeleteUserPacket(ABuffer: TEnhancedMemoryStream; + ANetState: TNetState); +var + account: TAccount; + username: string; + netState: TNetState; +begin + username := ABuffer.ReadStringNull; + account := Config.Accounts.Find(username); + if (account <> nil) and (account <> ANetState.Account) then + begin + CEDServerInstance.TCPServer.IterReset; + while CEDServerInstance.TCPServer.IterNext do + begin + netState := TNetState(CEDServerInstance.TCPServer.Iterator.UserData); + if (netState <> nil) and (netState.Account = account) then + begin + CEDServerInstance.Disconnect(CEDServerInstance.TCPServer.Iterator); + netState.Account := nil; + end; + end; + Config.Accounts.Remove(account); + Config.Invalidate; + CEDServerInstance.SendPacket(ANetState, TDeleteUserResponsePacket.Create(duDeleted, username)); + end else + CEDServerInstance.SendPacket(ANetState, TDeleteUserResponsePacket.Create(duNotFound, username)); +end; + +procedure OnListUsersPacket(ABuffer: TEnhancedMemoryStream; ANetState: TNetState); +begin + CEDServerInstance.SendPacket(ANetState, TCompressedPacket.Create(TUserListPacket.Create)); +end; + +{ TModifyUserResponsePacket } + +constructor TModifyUserResponsePacket.Create(AStatus: TModifyUserStatus; AAccount: TAccount); +begin + inherited Create($03, 0); + FStream.WriteByte($05); + FStream.WriteByte(Byte(AStatus)); + FStream.WriteStringNull(AAccount.Name); + FStream.WriteByte(Byte(AAccount.AccessLevel)); +end; + +{ TDeleteUserResponsePacket } + +constructor TDeleteUserResponsePacket.Create(AStatus: TDeleteUserStatus; AUsername: string); +begin + inherited Create($03, 0); + FStream.WriteByte($06); + FStream.WriteByte(Byte(AStatus)); + FStream.WriteStringNull(AUsername); +end; + +{ TUserListPacket } + +constructor TUserListPacket.Create; +var + i: Integer; + account: TAccount; +begin + inherited Create($03, 0); + FStream.WriteByte($07); + FStream.WriteWord(Config.Accounts.Count); + for i := 0 to Config.Accounts.Count - 1 do + begin + account := TAccount(Config.Accounts.Items[i]); + FStream.WriteStringNull(account.Name); + FStream.WriteByte(Byte(account.AccessLevel)); + end; +end; + +{$WARNINGS OFF} +var + i: Integer; + +initialization + for i := 0 to $FF do + AdminPacketHandlers[i] := nil; + AdminPacketHandlers[$01] := TPacketHandler.Create(0, @OnFlushPacket); + AdminPacketHandlers[$02] := TPacketHandler.Create(0, @OnQuitPacket); + AdminPacketHandlers[$05] := TPacketHandler.Create(0, @OnModifyUserPacket); + AdminPacketHandlers[$06] := TPacketHandler.Create(0, @OnDeleteUserPacket); + AdminPacketHandlers[$07] := TPacketHandler.Create(0, @OnListUsersPacket); +finalization + for i := 0 to $FF do + if AdminPacketHandlers[i] <> nil then + AdminPacketHandlers[i].Free; +{$WARNINGS ON} + +end. + diff --git a/Server/UCEDServer.pas b/Server/UCEDServer.pas index eea56e5..f89b1ec 100644 --- a/Server/UCEDServer.pas +++ b/Server/UCEDServer.pas @@ -1,361 +1,358 @@ -(* - * 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 2007 Andreas Schneider - *) -unit UCEDServer; - -{$mode objfpc}{$H+} - -interface - -uses - Classes, SysUtils, lNet, UEnhancedMemoryStream, UConfig, ULandscape, - UNetState, UPacket, dateutils, - {$IFDEF Linux}BaseUnix,{$ENDIF} - {$IFDEF Windows}Windows,{$ENDIF} - UPacketHandlers, UConnectionHandling; - -type - - { TCEDServer } - - TCEDServer = class(TObject) - constructor Create; - destructor Destroy; override; - protected - FLandscape: TLandscape; - FTCPServer: TLTcp; - FQuit: Boolean; - FLastFlush: TDateTime; - FValid: Boolean; - procedure OnAccept(ASocket: TLSocket); - procedure OnCanSend(ASocket: TLSocket); - procedure OnDisconnect(ASocket: TLSocket); - procedure OnReceive(ASocket: TLSocket); - procedure OnError(const AError: string; ASocket: TLSocket); - procedure ProcessBuffer(ANetState: TNetState); - procedure CheckNetStates; - public - property Landscape: TLandscape read FLandscape; - property TCPServer: TLTcp read FTCPServer; - property Quit: Boolean read FQuit write FQuit; - procedure Run; - procedure SendPacket(ANetState: TNetState; APacket: TPacket; - AFreePacket: Boolean = True); - procedure Disconnect(ASocket: TLSocket); - end; - -var - CEDServerInstance: TCEDServer; - -implementation - -uses - UClientHandling; - -{$I version.inc} - -{$IFDEF Linux} -procedure OnSigInt(ASignal: cint); cdecl; -begin - Writeln(TimeStamp, 'Killed'); - if CEDServerInstance <> nil then CEDServerInstance.Quit := True; -end; - -procedure OnSigSegv(ASignal: cint); cdecl; -begin - Writeln(TimeStamp, 'Internal error'); - Halt; - //if CEDServerInstance <> nil then CEDServerInstance.Quit := True; -end; -{$ENDIF} - -{$IFDEF Windows} -function OnConsoleCtrlEvent(ACtrl: DWord): LongBool; stdcall; far; -begin - Result := False; - if (ACtrl = CTRL_C_EVENT) or (ACtrl = CTRL_BREAK_EVENT) then - begin - Writeln(TimeStamp, 'Killed'); - if CEDServerInstance <> nil then CEDServerInstance.Quit := True; - Result := True; - end; -end; -{$ENDIF} - -{ TCEDServer } - -constructor TCEDServer.Create; -begin - inherited Create; - FLandscape := TLandscape.Create(Config.ReadString('Paths', 'map', 'map0.mul'), - Config.ReadString('Paths', 'statics', 'statics0.mul'), - Config.ReadString('Paths', 'staidx', 'staidx0.mul'), - Config.ReadString('Paths', 'tiledata', 'tiledata.mul'), - Config.ReadString('Paths', 'radarcol', 'radarcol.mul'), - Config.ReadInteger('Parameters', 'Width', 0), - Config.ReadInteger('Parameters', 'Height', 0), - FValid); - FTCPServer := TLTcp.Create(nil); - FTCPServer.OnAccept := @OnAccept; - FTCPServer.OnCanSend := @OnCanSend; - FTCPServer.OnDisconnect := @OnDisconnect; - FTCPServer.OnReceive := @OnReceive; - FTCPServer.OnError := @OnError; - FQuit := False; - FLastFlush := Now; -end; - -destructor TCEDServer.Destroy; -begin - if FTCPServer <> nil then - begin - FTCPServer.IterReset; - if FTCPServer.Iterator <> nil then - while FTCPServer.IterNext do - begin - FTCPServer.Iterator.Disconnect; - if FTCPServer.Iterator.UserData <> nil then - begin - TObject(FTCPServer.Iterator.UserData).Free; - FTCPServer.Iterator.UserData := nil; - end; - end; - FreeAndNil(FTCPServer); - end; - if FLandscape <> nil then FreeAndNil(FLandscape); - inherited Destroy; -end; - -procedure TCEDServer.OnAccept(ASocket: TLSocket); -begin - writeln(TimeStamp, 'Connect: ', ASocket.PeerAddress); - ASocket.UserData := TNetState.Create(ASocket); - SendPacket(TNetState(ASocket.UserData), TProtocolVersionPacket.Create(ProtocolVersion)); -end; - -procedure TCEDServer.OnCanSend(ASocket: TLSocket); -var - netState: TNetState; - size: Integer; -begin - //writeln('CanSend: ', ASocket.PeerAddress); - netState := TNetState(ASocket.UserData); - if netState = nil then Exit; - while netState.SendQueue.Size > 0 do - begin - size := FTCPServer.Send(netState.SendQueue.Memory^, netState.SendQueue.Size, ASocket); - if size > 0 then - netState.SendQueue.Dequeue(size) - else - Break; - end; -end; - -procedure TCEDServer.OnDisconnect(ASocket: TLSocket); -var - netState: TNetState; -begin - writeln(TimeStamp, 'Disconnect: ', ASocket.PeerAddress); - if ASocket.UserData <> nil then - begin - netState := TNetState(ASocket.UserData); - ASocket.UserData := nil; - if netState.Account <> nil then - SendPacket(nil, TClientDisconnectedPacket.Create(netState.Account.Name)); - netState.Free; - end; -end; - -procedure TCEDServer.OnReceive(ASocket: TLSocket); -var - netState: TNetState; - buffer: array[0..4095] of byte; - size: Integer; -begin - netState := TNetState(ASocket.UserData); - if netState <> nil then - begin - repeat - size := FTCPServer.Get(buffer, 4096, ASocket); - if size > 0 then - netState.ReceiveQueue.Enqueue(buffer, size); - until size <= 0; - ProcessBuffer(netState); - end; -end; - -procedure TCEDServer.OnError(const AError: string; ASocket: TLSocket); -begin - writeln(TimeStamp, 'Error: ', ASocket.PeerAddress, ' :: ', AError); - //OnDisconnect(ASocket); -end; - -procedure TCEDServer.ProcessBuffer(ANetState: TNetState); -var - buffer: TEnhancedMemoryStream; - packetID: Byte; - packetHandler: TPacketHandler; - size: Cardinal; -begin - try - buffer := ANetState.ReceiveQueue; - buffer.Position := 0; - while (buffer.Size >= 1) and ANetState.Socket.Connected do - begin - packetID := buffer.ReadByte; - packetHandler := PacketHandlers[packetID]; - if packetHandler <> nil then - begin - ANetState.LastAction := Now; - size := packetHandler.PacketLength; - if size = 0 then - begin - if buffer.Size > 5 then - size := buffer.ReadCardinal - else - Break; //wait for more data - end; - - if buffer.Size >= size then - begin - buffer.Lock(buffer.Position, size - buffer.Position); //prevent handler from reading too much - packetHandler.Process(buffer, ANetState); - buffer.Unlock; - buffer.Dequeue(size); - end else - Break; //wait for more data - end else - begin - Writeln(TimeStamp, 'Dropping client due to unknown packet [', packetID, ']: ', ANetState.Socket.PeerAddress); - Disconnect(ANetState.Socket); - buffer.Clear; - end; - end; - ANetState.LastAction := Now; - except - Writeln(TimeStamp, 'Error processing buffer of client: ', ANetState.Socket.PeerAddress); - end; -end; - -procedure TCEDServer.CheckNetStates; -var - netState: TNetState; -begin - FTCPServer.IterReset; - while FTCPServer.IterNext do - begin - netState := TNetState(FTCPServer.Iterator.UserData); - if netState <> nil then - begin - if FTCPServer.Iterator.Connected then - begin - if (SecondsBetween(netState.LastAction, Now) > 120) then - begin - if netState.Account <> nil then - Writeln(TimeStamp, 'Timeout: ', netState.Account.Name, ' (', netState.Socket.PeerAddress, ')') - else - Writeln(TimeStamp, 'Timeout: ', netState.Socket.PeerAddress); - Disconnect(netState.Socket); - end; - end else {TODO : Unnecessary ...} - begin - OnDisconnect(FTCPServer.Iterator); - end; - end; - end; -end; - -procedure TCEDServer.Run; -begin - if not FValid then - begin - Writeln(TimeStamp, 'Invalid data. Check the map size and the files.'); - Exit; - end; - - if FTCPServer.Listen(Config.ReadInteger('Network', 'Port', 2597)) then - begin - repeat - FTCPServer.CallAction; - CheckNetStates; - if SecondsBetween(FLastFlush, Now) >= 60 then - begin - FLandscape.Flush; - FLastFlush := Now; - end; - Sleep(1); - until FQuit; - end; -end; - -procedure TCEDServer.SendPacket(ANetState: TNetState; APacket: TPacket; - AFreePacket: Boolean = True); -var - netState: TNetState; -begin - if ANetState <> nil then - begin - ANetState.SendQueue.Seek(0, soFromEnd); - ANetState.SendQueue.CopyFrom(APacket.Stream, 0); - OnCanSend(ANetState.Socket); - end else //broadcast - begin - FTCPServer.IterReset; - while FTCPServer.IterNext do - begin - netState := TNetState(FTCPServer.Iterator.UserData); - if (netState <> nil) and (FTCPServer.Iterator.Connected) then - begin - netState.SendQueue.Seek(0, soFromEnd); - netState.SendQueue.CopyFrom(APacket.Stream, 0); - OnCanSend(netState.Socket); - end; - end; - end; - if AFreePacket then - APacket.Free; -end; - -procedure TCEDServer.Disconnect(ASocket: TLSocket); -begin - if ASocket.Connected then - begin - ASocket.Disconnect; - //OnDisconnect(ASocket); - //Handling of the disconnect is done in CheckNetStates after each CallAction - end; -end; - -initialization -{$IFDEF Linux} - FpSignal(SIGINT, @OnSigInt); - //FpSignal(SIGSEGV, @OnSigSegv); -{$ENDIF} -{$IFDEF Windows} - SetConsoleCtrlHandler(@OnConsoleCtrlEvent, True); -{$ENDIF} - -end. - +(* + * 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 2007 Andreas Schneider + *) +unit UCEDServer; + +{$mode objfpc}{$H+} + +interface + +uses + Classes, SysUtils, lNet, UEnhancedMemoryStream, UConfig, ULandscape, + UNetState, UPacket, dateutils, + {$IFDEF Linux}BaseUnix,{$ENDIF} + {$IFDEF Windows}Windows,{$ENDIF} + UPacketHandlers, UConnectionHandling; + +type + + { TCEDServer } + + TCEDServer = class(TObject) + constructor Create; + destructor Destroy; override; + protected + FLandscape: TLandscape; + FTCPServer: TLTcp; + FQuit: Boolean; + FLastFlush: TDateTime; + FValid: Boolean; + procedure OnAccept(ASocket: TLSocket); + procedure OnCanSend(ASocket: TLSocket); + procedure OnDisconnect(ASocket: TLSocket); + procedure OnReceive(ASocket: TLSocket); + procedure OnError(const AError: string; ASocket: TLSocket); + procedure ProcessBuffer(ANetState: TNetState); + procedure CheckNetStates; + public + property Landscape: TLandscape read FLandscape; + property TCPServer: TLTcp read FTCPServer; + property Quit: Boolean read FQuit write FQuit; + procedure Run; + procedure SendPacket(ANetState: TNetState; APacket: TPacket; + AFreePacket: Boolean = True); + procedure Disconnect(ASocket: TLSocket); + end; + +var + CEDServerInstance: TCEDServer; + +implementation + +uses + UClientHandling; + +{$I version.inc} + +{$IFDEF Linux} +procedure OnSigInt(ASignal: cint); cdecl; +begin + Writeln(TimeStamp, 'Killed'); + if CEDServerInstance <> nil then CEDServerInstance.Quit := True; +end; + +procedure OnSigSegv(ASignal: cint); cdecl; +begin + Writeln(TimeStamp, 'Internal error'); + Halt; + //if CEDServerInstance <> nil then CEDServerInstance.Quit := True; +end; +{$ENDIF} + +{$IFDEF Windows} +function OnConsoleCtrlEvent(ACtrl: DWord): LongBool; stdcall; far; +begin + Result := False; + if (ACtrl = CTRL_C_EVENT) or (ACtrl = CTRL_BREAK_EVENT) then + begin + Writeln(TimeStamp, 'Killed'); + if CEDServerInstance <> nil then CEDServerInstance.Quit := True; + Result := True; + end; +end; +{$ENDIF} + +{ TCEDServer } + +constructor TCEDServer.Create; +begin + inherited Create; + FLandscape := TLandscape.Create(Config.Map.MapFile, Config.Map.StaticsFile, + Config.Map.StaIdxFile, Config.Tiledata, Config.Radarcol, Config.Map.Width, + Config.Map.Height, FValid); + FTCPServer := TLTcp.Create(nil); + FTCPServer.OnAccept := @OnAccept; + FTCPServer.OnCanSend := @OnCanSend; + FTCPServer.OnDisconnect := @OnDisconnect; + FTCPServer.OnReceive := @OnReceive; + FTCPServer.OnError := @OnError; + FQuit := False; + FLastFlush := Now; +end; + +destructor TCEDServer.Destroy; +begin + if FTCPServer <> nil then + begin + FTCPServer.IterReset; + if FTCPServer.Iterator <> nil then + while FTCPServer.IterNext do + begin + FTCPServer.Iterator.Disconnect; + if FTCPServer.Iterator.UserData <> nil then + begin + TObject(FTCPServer.Iterator.UserData).Free; + FTCPServer.Iterator.UserData := nil; + end; + end; + FreeAndNil(FTCPServer); + end; + if FLandscape <> nil then FreeAndNil(FLandscape); + inherited Destroy; +end; + +procedure TCEDServer.OnAccept(ASocket: TLSocket); +begin + writeln(TimeStamp, 'Connect: ', ASocket.PeerAddress); + ASocket.UserData := TNetState.Create(ASocket); + SendPacket(TNetState(ASocket.UserData), TProtocolVersionPacket.Create(ProtocolVersion)); +end; + +procedure TCEDServer.OnCanSend(ASocket: TLSocket); +var + netState: TNetState; + size: Integer; +begin + //writeln('CanSend: ', ASocket.PeerAddress); + netState := TNetState(ASocket.UserData); + if netState = nil then Exit; + while netState.SendQueue.Size > 0 do + begin + size := FTCPServer.Send(netState.SendQueue.Memory^, netState.SendQueue.Size, ASocket); + if size > 0 then + netState.SendQueue.Dequeue(size) + else + Break; + end; +end; + +procedure TCEDServer.OnDisconnect(ASocket: TLSocket); +var + netState: TNetState; +begin + writeln(TimeStamp, 'Disconnect: ', ASocket.PeerAddress); + if ASocket.UserData <> nil then + begin + netState := TNetState(ASocket.UserData); + ASocket.UserData := nil; + if netState.Account <> nil then + SendPacket(nil, TClientDisconnectedPacket.Create(netState.Account.Name)); + netState.Free; + end; +end; + +procedure TCEDServer.OnReceive(ASocket: TLSocket); +var + netState: TNetState; + buffer: array[0..4095] of byte; + size: Integer; +begin + netState := TNetState(ASocket.UserData); + if netState <> nil then + begin + repeat + size := FTCPServer.Get(buffer, 4096, ASocket); + if size > 0 then + netState.ReceiveQueue.Enqueue(buffer, size); + until size <= 0; + ProcessBuffer(netState); + end; +end; + +procedure TCEDServer.OnError(const AError: string; ASocket: TLSocket); +begin + writeln(TimeStamp, 'Error: ', ASocket.PeerAddress, ' :: ', AError); + //OnDisconnect(ASocket); +end; + +procedure TCEDServer.ProcessBuffer(ANetState: TNetState); +var + buffer: TEnhancedMemoryStream; + packetID: Byte; + packetHandler: TPacketHandler; + size: Cardinal; +begin + try + buffer := ANetState.ReceiveQueue; + buffer.Position := 0; + while (buffer.Size >= 1) and ANetState.Socket.Connected do + begin + packetID := buffer.ReadByte; + packetHandler := PacketHandlers[packetID]; + if packetHandler <> nil then + begin + ANetState.LastAction := Now; + size := packetHandler.PacketLength; + if size = 0 then + begin + if buffer.Size > 5 then + size := buffer.ReadCardinal + else + Break; //wait for more data + end; + + if buffer.Size >= size then + begin + buffer.Lock(buffer.Position, size - buffer.Position); //prevent handler from reading too much + packetHandler.Process(buffer, ANetState); + buffer.Unlock; + buffer.Dequeue(size); + end else + Break; //wait for more data + end else + begin + Writeln(TimeStamp, 'Dropping client due to unknown packet [', packetID, ']: ', ANetState.Socket.PeerAddress); + Disconnect(ANetState.Socket); + buffer.Clear; + end; + end; + ANetState.LastAction := Now; + except + Writeln(TimeStamp, 'Error processing buffer of client: ', ANetState.Socket.PeerAddress); + end; +end; + +procedure TCEDServer.CheckNetStates; +var + netState: TNetState; +begin + FTCPServer.IterReset; + while FTCPServer.IterNext do + begin + netState := TNetState(FTCPServer.Iterator.UserData); + if netState <> nil then + begin + if FTCPServer.Iterator.Connected then + begin + if (SecondsBetween(netState.LastAction, Now) > 120) then + begin + if netState.Account <> nil then + Writeln(TimeStamp, 'Timeout: ', netState.Account.Name, ' (', netState.Socket.PeerAddress, ')') + else + Writeln(TimeStamp, 'Timeout: ', netState.Socket.PeerAddress); + Disconnect(netState.Socket); + end; + end else {TODO : Unnecessary ...} + begin + OnDisconnect(FTCPServer.Iterator); + end; + end; + end; +end; + +procedure TCEDServer.Run; +begin + if not FValid then + begin + Writeln(TimeStamp, 'Invalid data. Check the map size and the files.'); + Exit; + end; + + if FTCPServer.Listen(Config.Port) then + begin + repeat + FTCPServer.CallAction; + CheckNetStates; + if SecondsBetween(FLastFlush, Now) >= 60 then + begin + FLandscape.Flush; + Config.Flush; + FLastFlush := Now; + end; + Sleep(1); + until FQuit; + end; +end; + +procedure TCEDServer.SendPacket(ANetState: TNetState; APacket: TPacket; + AFreePacket: Boolean = True); +var + netState: TNetState; +begin + if ANetState <> nil then + begin + ANetState.SendQueue.Seek(0, soFromEnd); + ANetState.SendQueue.CopyFrom(APacket.Stream, 0); + OnCanSend(ANetState.Socket); + end else //broadcast + begin + FTCPServer.IterReset; + while FTCPServer.IterNext do + begin + netState := TNetState(FTCPServer.Iterator.UserData); + if (netState <> nil) and (FTCPServer.Iterator.Connected) then + begin + netState.SendQueue.Seek(0, soFromEnd); + netState.SendQueue.CopyFrom(APacket.Stream, 0); + OnCanSend(netState.Socket); + end; + end; + end; + if AFreePacket then + APacket.Free; +end; + +procedure TCEDServer.Disconnect(ASocket: TLSocket); +begin + if ASocket.Connected then + begin + ASocket.Disconnect; + //OnDisconnect(ASocket); + //Handling of the disconnect is done in CheckNetStates after each CallAction + end; +end; + +initialization +{$IFDEF Linux} + FpSignal(SIGINT, @OnSigInt); + FpSignal(SIGTERM, @OnSigInt); //SIGTERM should shutdown the server cleanly too + //FpSignal(SIGSEGV, @OnSigSegv); +{$ENDIF} +{$IFDEF Windows} + SetConsoleCtrlHandler(@OnConsoleCtrlEvent, True); +{$ENDIF} + +end. + diff --git a/Server/UClientHandling.pas b/Server/UClientHandling.pas index e09f628..6c70cdc 100644 --- a/Server/UClientHandling.pas +++ b/Server/UClientHandling.pas @@ -1,207 +1,207 @@ -(* - * 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 2007 Andreas Schneider - *) -unit UClientHandling; - -{$mode objfpc}{$H+} - -interface - -uses - Classes, SysUtils, UPacket, UPacketHandlers, UConfig, UAccount, UNetState, - UEnhancedMemoryStream, UEnums, math; - -type - - { TClientConnectedPacket } - - TClientConnectedPacket = class(TPacket) - constructor Create(AUsername: string); - end; - - { TClientDisconnectedPacket } - - TClientDisconnectedPacket = class(TPacket) - constructor Create(AUsername: string); - end; - - { TClientListPacket } - - TClientListPacket = class(TPacket) - constructor Create(AAvoid: TNetState = nil); - end; - - { TSetClientPosPacket } - - TSetClientPosPacket = class(TPacket) - constructor Create(APos: TPoint); - end; - - { TChatMessagePacket } - - TChatMessagePacket = class(TPacket) - constructor Create(ASender, AMessage: string); - end; - - { TAccessLevelChangedPacket } - - TAccessLevelChangedPacket = class(TPacket) - constructor Create(AAccessLevel: TAccessLevel); - end; - -procedure OnClientHandlerPacket(ABuffer: TEnhancedMemoryStream; ANetState: TNetState); -procedure OnUpdateClientPosPacket(ABuffer: TEnhancedMemoryStream; ANetState: TNetState); -procedure OnChatMessagePacket(ABuffer: TEnhancedMemoryStream; ANetState: TNetState); -procedure OnGotoClientPosPacket(ABuffer: TEnhancedMemoryStream; ANetState: TNetState); - -var - ClientPacketHandlers: array[0..$FF] of TPacketHandler; - -implementation - -uses - UCEDServer, UPackets; - -procedure OnClientHandlerPacket(ABuffer: TEnhancedMemoryStream; ANetState: TNetState); -var - packetHandler: TPacketHandler; -begin - if not ValidateAccess(ANetState, alView) then Exit; - packetHandler := ClientPacketHandlers[ABuffer.ReadByte]; - if packetHandler <> nil then - packetHandler.Process(ABuffer, ANetState); -end; - -procedure OnUpdateClientPosPacket(ABuffer: TEnhancedMemoryStream; - ANetState: TNetState); -var - pos: TPoint; -begin - pos.x := ABuffer.ReadWord; - pos.y := ABuffer.ReadWord; - ANetState.Account.LastPos := pos; -end; - -procedure OnChatMessagePacket(ABuffer: TEnhancedMemoryStream; - ANetState: TNetState); -begin - CEDServerInstance.SendPacket(nil, TCompressedPacket.Create( - TChatMessagePacket.Create(ANetState.Account.Name, ABuffer.ReadStringNull))); -end; - -procedure OnGotoClientPosPacket(ABuffer: TEnhancedMemoryStream; - ANetState: TNetState); -var - account: TAccount; -begin - account := Accounts.Find(ABuffer.ReadStringNull); - if account <> nil then - CEDServerInstance.SendPacket(ANetState, TSetClientPosPacket.Create(account.LastPos)); -end; - -{ TClientConnectedPacket } - -constructor TClientConnectedPacket.Create(AUsername: string); -begin - inherited Create($0C, 0); - FStream.WriteByte($01); - FStream.WriteStringNull(AUsername); -end; - -{ TClientDisconnectedPacket } - -constructor TClientDisconnectedPacket.Create(AUsername: string); -begin - inherited Create($0C, 0); - FStream.WriteByte($02); - FStream.WriteStringNull(AUsername); -end; - -{ TClientListPacket } - -constructor TClientListPacket.Create(AAvoid: TNetState = nil); -var - netState: TNetState; -begin - inherited Create($0C, 0); - FStream.WriteByte($03); - CEDServerInstance.TCPServer.IterReset; - if CEDServerInstance.TCPServer.Iterator <> nil then - begin - repeat - netState := TNetState(CEDServerInstance.TCPServer.Iterator.UserData); - if (netState <> nil) and (netState <> AAvoid) and (netState.Account <> nil) then - FStream.WriteStringNull(netState.Account.Name); - until not CEDServerInstance.TCPServer.IterNext; - end; -end; - -{ TSetClientPosPacket } - -constructor TSetClientPosPacket.Create(APos: TPoint); -begin - inherited Create($0C, 0); - FStream.WriteByte($04); - FStream.WriteWord(EnsureRange(APos.x, 0, CEDServerInstance.Landscape.CellWidth - 1)); - FStream.WriteWord(EnsureRange(APos.y, 0, CEDServerInstance.Landscape.CellHeight - 1)); -end; - -{ TChatMessagePacket } - -constructor TChatMessagePacket.Create(ASender, AMessage: string); -begin - inherited Create($0C, 0); - FStream.WriteByte($05); - FStream.WriteStringNull(ASender); - FStream.WriteStringNull(AMessage); -end; - -{ TAccessLevelChangedPacket } - -constructor TAccessLevelChangedPacket.Create(AAccessLevel: TAccessLevel); -begin - inherited Create($0C, 0); - FStream.WriteByte($07); - FStream.WriteByte(Byte(AAccessLevel)); -end; - -{$WARNINGS OFF} -var - i: Integer; - -initialization - for i := 0 to $FF do - ClientPacketHandlers[i] := nil; - ClientPacketHandlers[$04] := TPacketHandler.Create(0, @OnUpdateClientPosPacket); - ClientPacketHandlers[$05] := TPacketHandler.Create(0, @OnChatMessagePacket); - ClientPacketHandlers[$06] := TPacketHandler.Create(0, @OnGotoClientPosPacket); -finalization - for i := 0 to $FF do - if ClientPacketHandlers[i] <> nil then - ClientPacketHandlers[i].Free; -{$WARNINGS ON} - -end. - +(* + * 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 2007 Andreas Schneider + *) +unit UClientHandling; + +{$mode objfpc}{$H+} + +interface + +uses + Classes, SysUtils, UPacket, UPacketHandlers, UConfig, UAccount, UNetState, + UEnhancedMemoryStream, UEnums, math; + +type + + { TClientConnectedPacket } + + TClientConnectedPacket = class(TPacket) + constructor Create(AUsername: string); + end; + + { TClientDisconnectedPacket } + + TClientDisconnectedPacket = class(TPacket) + constructor Create(AUsername: string); + end; + + { TClientListPacket } + + TClientListPacket = class(TPacket) + constructor Create(AAvoid: TNetState = nil); + end; + + { TSetClientPosPacket } + + TSetClientPosPacket = class(TPacket) + constructor Create(APos: TPoint); + end; + + { TChatMessagePacket } + + TChatMessagePacket = class(TPacket) + constructor Create(ASender, AMessage: string); + end; + + { TAccessLevelChangedPacket } + + TAccessLevelChangedPacket = class(TPacket) + constructor Create(AAccessLevel: TAccessLevel); + end; + +procedure OnClientHandlerPacket(ABuffer: TEnhancedMemoryStream; ANetState: TNetState); +procedure OnUpdateClientPosPacket(ABuffer: TEnhancedMemoryStream; ANetState: TNetState); +procedure OnChatMessagePacket(ABuffer: TEnhancedMemoryStream; ANetState: TNetState); +procedure OnGotoClientPosPacket(ABuffer: TEnhancedMemoryStream; ANetState: TNetState); + +var + ClientPacketHandlers: array[0..$FF] of TPacketHandler; + +implementation + +uses + UCEDServer, UPackets; + +procedure OnClientHandlerPacket(ABuffer: TEnhancedMemoryStream; ANetState: TNetState); +var + packetHandler: TPacketHandler; +begin + if not ValidateAccess(ANetState, alView) then Exit; + packetHandler := ClientPacketHandlers[ABuffer.ReadByte]; + if packetHandler <> nil then + packetHandler.Process(ABuffer, ANetState); +end; + +procedure OnUpdateClientPosPacket(ABuffer: TEnhancedMemoryStream; + ANetState: TNetState); +var + pos: TPoint; +begin + pos.x := ABuffer.ReadWord; + pos.y := ABuffer.ReadWord; + ANetState.Account.LastPos := pos; +end; + +procedure OnChatMessagePacket(ABuffer: TEnhancedMemoryStream; + ANetState: TNetState); +begin + CEDServerInstance.SendPacket(nil, TCompressedPacket.Create( + TChatMessagePacket.Create(ANetState.Account.Name, ABuffer.ReadStringNull))); +end; + +procedure OnGotoClientPosPacket(ABuffer: TEnhancedMemoryStream; + ANetState: TNetState); +var + account: TAccount; +begin + account := Config.Accounts.Find(ABuffer.ReadStringNull); + if account <> nil then + CEDServerInstance.SendPacket(ANetState, TSetClientPosPacket.Create(account.LastPos)); +end; + +{ TClientConnectedPacket } + +constructor TClientConnectedPacket.Create(AUsername: string); +begin + inherited Create($0C, 0); + FStream.WriteByte($01); + FStream.WriteStringNull(AUsername); +end; + +{ TClientDisconnectedPacket } + +constructor TClientDisconnectedPacket.Create(AUsername: string); +begin + inherited Create($0C, 0); + FStream.WriteByte($02); + FStream.WriteStringNull(AUsername); +end; + +{ TClientListPacket } + +constructor TClientListPacket.Create(AAvoid: TNetState = nil); +var + netState: TNetState; +begin + inherited Create($0C, 0); + FStream.WriteByte($03); + CEDServerInstance.TCPServer.IterReset; + if CEDServerInstance.TCPServer.Iterator <> nil then + begin + repeat + netState := TNetState(CEDServerInstance.TCPServer.Iterator.UserData); + if (netState <> nil) and (netState <> AAvoid) and (netState.Account <> nil) then + FStream.WriteStringNull(netState.Account.Name); + until not CEDServerInstance.TCPServer.IterNext; + end; +end; + +{ TSetClientPosPacket } + +constructor TSetClientPosPacket.Create(APos: TPoint); +begin + inherited Create($0C, 0); + FStream.WriteByte($04); + FStream.WriteWord(EnsureRange(APos.x, 0, CEDServerInstance.Landscape.CellWidth - 1)); + FStream.WriteWord(EnsureRange(APos.y, 0, CEDServerInstance.Landscape.CellHeight - 1)); +end; + +{ TChatMessagePacket } + +constructor TChatMessagePacket.Create(ASender, AMessage: string); +begin + inherited Create($0C, 0); + FStream.WriteByte($05); + FStream.WriteStringNull(ASender); + FStream.WriteStringNull(AMessage); +end; + +{ TAccessLevelChangedPacket } + +constructor TAccessLevelChangedPacket.Create(AAccessLevel: TAccessLevel); +begin + inherited Create($0C, 0); + FStream.WriteByte($07); + FStream.WriteByte(Byte(AAccessLevel)); +end; + +{$WARNINGS OFF} +var + i: Integer; + +initialization + for i := 0 to $FF do + ClientPacketHandlers[i] := nil; + ClientPacketHandlers[$04] := TPacketHandler.Create(0, @OnUpdateClientPosPacket); + ClientPacketHandlers[$05] := TPacketHandler.Create(0, @OnChatMessagePacket); + ClientPacketHandlers[$06] := TPacketHandler.Create(0, @OnGotoClientPosPacket); +finalization + for i := 0 to $FF do + if ClientPacketHandlers[i] <> nil then + ClientPacketHandlers[i].Free; +{$WARNINGS ON} + +end. + diff --git a/Server/UConfig.pas b/Server/UConfig.pas index 79b9a8e..499ec53 100644 --- a/Server/UConfig.pas +++ b/Server/UConfig.pas @@ -1,182 +1,357 @@ -(* - * 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 2007 Andreas Schneider - *) -unit UConfig; - -{$mode objfpc}{$H+} - -interface - -uses - Classes, SysUtils, IniFiles, md5, Keyboard, UAccount; - - -var - AppDir: string; - Config: TIniFile; - Accounts: TAccountList; - -procedure InitConfig; -function LoadConfig: Boolean; -function TimeStamp: string; - -implementation - -const - CONFIGVERSION = 2; - -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; - -procedure InitConfig; -var - configFile: string; - stringValue, password: string; - intValue: Integer; -begin - configFile := ChangeFileExt(ParamStr(0), '.ini'); - DeleteFile(configFile); - Config := TIniFile.Create(configFile); - Config.WriteInteger('Config', 'Version', CONFIGVERSION); - - Writeln('Configuring Network'); - Writeln('==================='); - Write ('Port [2597]: '); - Readln (stringValue); - if not TryStrToInt(stringValue, intValue) then intValue := 2597; - Config.WriteInteger('Network', 'Port', intValue); - Writeln(''); - - Writeln('Configuring Paths'); - Writeln('================='); - Write ('map [map0.mul]: '); - Readln (stringValue); - if stringValue = '' then stringValue := 'map0.mul'; - Config.WriteString('Paths', 'map', stringValue); - Write ('statics [statics0.mul]: '); - Readln (stringValue); - if stringValue = '' then stringValue := 'statics0.mul'; - Config.WriteString('Paths', 'statics', stringValue); - Write ('staidx [staidx0.mul]: '); - Readln (stringValue); - if stringValue = '' then stringValue := 'staidx0.mul'; - Config.WriteString('Paths', 'staidx', stringValue); - Write ('tiledata [tiledata.mul]: '); - Readln (stringValue); - if stringValue = '' then stringValue := 'tiledata.mul'; - Config.WriteString('Paths', 'tiledata', stringValue); - Write ('radarcol [radarcol.mul]: '); - Readln (stringValue); - if stringValue = '' then stringValue := 'radarcol.mul'; - Config.WriteString('Paths', 'radarcol', stringValue); - Writeln(''); - - Writeln('Parameters'); - Writeln('=========='); - Write ('Map width [768]: '); - Readln (stringValue); - if not TryStrToInt(stringValue, intValue) then intValue := 768; - Config.WriteInteger('Parameters', 'Width', intValue); - Write ('Map height [512]: '); - Readln (stringValue); - if not TryStrToInt(stringValue, intValue) then intValue := 512; - Config.WriteInteger('Parameters', 'Height', intValue); - Writeln(''); - - Writeln('Admin account'); - Writeln('============='); - repeat - Write('Account name: '); - Readln(stringValue); - until stringValue <> ''; - Write ('Password [hidden]: '); - password := QueryPassword; - Config.WriteString('Accounts', stringValue, '255:' + MD5Print(MD5String(password))); -end; - -function LoadConfig: Boolean; -var - configFile: string; - values: TStringList; - i: Integer; -begin - configFile := ChangeFileExt(ParamStr(0), '.ini'); - if FileExists(configFile) then - begin - Config := TIniFile.Create(configFile); - Result := (Config.ReadInteger('Config', 'Version', 0) = CONFIGVERSION); - if Result then - begin - Accounts := TAccountList.Create; - values := TStringList.Create; - Config.ReadSectionRaw('Accounts', values); - for i := 0 to values.Count - 1 do - Accounts.Add(TAccount.Create(values.Strings[i])); - values.Free; - end; - end else - Result := False; -end; - -function TimeStamp: string; -begin - Result := '[' + DateTimeToStr(Now) + '] '; -end; - -initialization -begin - AppDir := ExtractFilePath(ParamStr(0)); - if AppDir[Length(AppDir)] <> PathDelim then - AppDir := AppDir + PathDelim; -end; - -finalization -begin - if Config <> nil then FreeAndNil(Config); - if Accounts <> nil then FreeAndNil(Accounts); -end; - -end. - +(* + * 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 2008 Andreas Schneider + *) +unit UConfig; + +{$mode objfpc}{$H+} + +interface + +uses + Classes, SysUtils, DOM, XMLRead, XMLWrite, md5, Keyboard, UAccount, + UXmlHelper, UInterfaces, UEnums; + +type + + TInvalidConfigVersionExeption = 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; + FAccounts: TAccountList; + 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 Accounts: TAccountList read FAccounts; + 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); + if not ((xmlDoc.DocumentElement.NodeName = 'CEDConfig') and + TryStrToInt(xmlDoc.DocumentElement.AttribStrings['Version'], version) and + (version = CONFIGVERSION)) then + raise TInvalidConfigVersionExeption.Create(Format('%d <> %d', [version, CONFIGVERSION])); + + FPort := TXmlHelper.ReadInteger(xmlDoc.DocumentElement, 'Port', 2597); + + xmlElement := TDOMElement(xmlDoc.DocumentElement.FindNode('Map')); + if not assigned(xmlElement) then + raise TInvalidConfigVersionExeption.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('Accounts')); + if not assigned(xmlElement) then + raise TInvalidConfigVersionExeption.Create('Account information not found'); + FAccounts := TAccountList.Deserialize(Self, xmlElement); + + 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); + + Writeln('Configuring Network'); + Writeln('==================='); + Write ('Port [2597]: '); + Readln (stringValue); + if not TryStrToInt(stringValue, intValue) then intValue := 2597; + FPort := intValue; + Writeln(''); + + Writeln('Configuring Paths'); + Writeln('================='); + Write ('map [map0.mul]: '); + Readln (FMap.MapFile); + if FMap.MapFile = '' then FMap.MapFile := 'map0.mul'; + Write ('statics [statics0.mul]: '); + Readln (FMap.StaticsFile); + if FMap.StaticsFile = '' then FMap.StaticsFile := 'statics0.mul'; + Write ('staidx [staidx0.mul]: '); + Readln (FMap.StaIdxFile); + 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, + MD5Print(MD5String(password)), alAdministrator)); + + FChanged := True; +end; + +destructor TConfig.Destroy; +begin + if Assigned(FMap) then FreeAndNil(FMap); + if Assigned(FAccounts) then FreeAndNil(FAccounts); + 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')); +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. + diff --git a/Server/UConnectionHandling.pas b/Server/UConnectionHandling.pas index 580a0f3..5845fb9 100644 --- a/Server/UConnectionHandling.pas +++ b/Server/UConnectionHandling.pas @@ -1,195 +1,198 @@ -(* - * 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 2007 Andreas Schneider - *) -unit UConnectionHandling; - -{$mode objfpc}{$H+} - -interface - -uses - Classes, SysUtils, UPacket, UPacketHandlers, UConfig, UAccount, UNetState, - UEnhancedMemoryStream, UEnums; - -type - - { TProtocolVersion } - - TProtocolVersionPacket = class(TPacket) - constructor Create(AVersion: Cardinal); - end; - - { TLoginResponsePacket } - - TLoginResponsePacket = class(TPacket) - constructor Create(AState: TLoginState; AAccessLevel: TAccessLevel = alNone); - end; - - { TServerStatePacket } - - TServerStatePacket = class(TPacket) - constructor Create(AState: TServerState; AMessage: string = ''); - end; - -procedure OnConnectionHandlerPacket(ABuffer: TEnhancedMemoryStream; ANetState: TNetState); -procedure OnLoginRequestPacket(ABuffer: TEnhancedMemoryStream; ANetState: TNetState); -procedure OnQuitPacket(ABuffer: TEnhancedMemoryStream; ANetState: TNetState); - -var - ConnectionPacketHandlers: array[0..$FF] of TPacketHandler; - -implementation - -uses - md5, UCEDServer, UClientHandling, UPackets; - -procedure OnConnectionHandlerPacket(ABuffer: TEnhancedMemoryStream; ANetState: TNetState); -var - packetHandler: TPacketHandler; -begin - packetHandler := ConnectionPacketHandlers[ABuffer.ReadByte]; - if packetHandler <> nil then - packetHandler.Process(ABuffer, ANetState); -end; - -procedure OnLoginRequestPacket(ABuffer: TEnhancedMemoryStream; - ANetState: TNetState); -var - username, passwordHash: string; - account: TAccount; - pwHash: string; - netState: TNetState; - invalid: Boolean; -begin - username := ABuffer.ReadStringNull; - passwordHash := MD5Print(MD5String(ABuffer.ReadStringNull)); - account := Accounts.Find(username); - if account <> nil then - begin - if account.AccessLevel > alNone then - begin - if account.PasswordHash = passwordHash then - begin - invalid := False; - CEDServerInstance.TCPServer.IterReset; - if CEDServerInstance.TCPServer.Iterator <> nil then - begin - repeat - netState := TNetState(CEDServerInstance.TCPServer.Iterator.UserData); - if (netState <> nil) and (netState.Account = account) then - begin - CEDServerInstance.SendPacket(ANetState, TLoginResponsePacket.Create(lsAlreadyLoggedIn)); - CEDServerInstance.Disconnect(ANetState.Socket); - invalid := True; - Break; - end; - until not CEDServerInstance.TCPServer.IterNext; - end; - - if not invalid then - begin - Writeln(TimeStamp, 'Login (', username, '): ', ANetState.Socket.PeerAddress); - ANetState.Account := account; - CEDServerInstance.SendPacket(ANetState, TLoginResponsePacket.Create(lsOK, account.AccessLevel)); - CEDServerInstance.SendPacket(ANetState, TCompressedPacket.Create( - TClientListPacket.Create(ANetState))); - CEDServerInstance.SendPacket(nil, TClientConnectedPacket.Create(username)); - CEDServerInstance.SendPacket(ANetState, TSetClientPosPacket.Create(account.LastPos)); - end; - end else - begin - CEDServerInstance.SendPacket(ANetState, TLoginResponsePacket.Create(lsInvalidPassword)); - CEDServerInstance.Disconnect(ANetState.Socket); - end; - end else - begin - CEDServerInstance.SendPacket(ANetState, TLoginResponsePacket.Create(lsNoAccess)); - CEDServerInstance.Disconnect(ANetState.Socket); - end; - end else - begin - CEDServerInstance.SendPacket(ANetState, TLoginResponsePacket.Create(lsInvalidUser)); - CEDServerInstance.Disconnect(ANetState.Socket); - end; -end; - -procedure OnQuitPacket(ABuffer: TEnhancedMemoryStream; ANetState: TNetState); -begin - CEDServerInstance.Disconnect(ANetState.Socket); -end; - -{ TProtocolVersionPacket } - -constructor TProtocolVersionPacket.Create(AVersion: Cardinal); -begin - inherited Create($02, 0); - FStream.WriteByte($01); - FStream.WriteCardinal(AVersion); -end; - -{ TLoginResponsePacket } - -constructor TLoginResponsePacket.Create(AState: TLoginState; - AAccessLevel: TAccessLevel = alNone); -begin - inherited Create($02, 0); - FStream.WriteByte($03); - FStream.WriteByte(Byte(AState)); - if AState = lsOK then - begin - FStream.WriteByte(Byte(AAccessLevel)); - FStream.WriteWord(Config.ReadInteger('Parameters', 'Width', 768)); - FStream.WriteWord(Config.ReadInteger('Parameters', 'Height', 512)); - end; -end; - -{ TServerStatePacket } - -constructor TServerStatePacket.Create(AState: TServerState; AMessage: string = ''); -begin - inherited Create($02, 0); - FStream.WriteByte($04); - FStream.WriteByte(Byte(AState)); - if AState = ssOther then - FStream.WriteStringNull(AMessage); -end; - -{$WARNINGS OFF} -var - i: Integer; - -initialization - for i := 0 to $FF do - ConnectionPacketHandlers[i] := nil; - ConnectionPacketHandlers[$03] := TPacketHandler.Create(0, @OnLoginRequestPacket); - ConnectionPacketHandlers[$05] := TPacketHandler.Create(0, @OnQuitPacket); -finalization - for i := 0 to $FF do - if ConnectionPacketHandlers[i] <> nil then - ConnectionPacketHandlers[i].Free; -{$WARNINGS ON} - -end. - +(* + * 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 2008 Andreas Schneider + *) +unit UConnectionHandling; + +{$mode objfpc}{$H+} + +interface + +uses + Classes, SysUtils, UPacket, UPacketHandlers, UConfig, UAccount, UNetState, + UEnhancedMemoryStream, UEnums; + +type + + { TProtocolVersion } + + TProtocolVersionPacket = class(TPacket) + constructor Create(AVersion: Cardinal); + end; + + { TLoginResponsePacket } + + TLoginResponsePacket = class(TPacket) + constructor Create(AState: TLoginState; AAccessLevel: TAccessLevel = alNone); + end; + + { TServerStatePacket } + + TServerStatePacket = class(TPacket) + constructor Create(AState: TServerState; AMessage: string = ''); + end; + +procedure OnConnectionHandlerPacket(ABuffer: TEnhancedMemoryStream; ANetState: TNetState); +procedure OnLoginRequestPacket(ABuffer: TEnhancedMemoryStream; ANetState: TNetState); +procedure OnQuitPacket(ABuffer: TEnhancedMemoryStream; ANetState: TNetState); + +var + ConnectionPacketHandlers: array[0..$FF] of TPacketHandler; + +implementation + +uses + md5, UCEDServer, UClientHandling, UPackets; + +procedure OnConnectionHandlerPacket(ABuffer: TEnhancedMemoryStream; ANetState: TNetState); +var + packetHandler: TPacketHandler; +begin + packetHandler := ConnectionPacketHandlers[ABuffer.ReadByte]; + if packetHandler <> nil then + packetHandler.Process(ABuffer, ANetState); +end; + +procedure OnLoginRequestPacket(ABuffer: TEnhancedMemoryStream; + ANetState: TNetState); +var + username, passwordHash: string; + account: TAccount; + pwHash: string; + netState: TNetState; + invalid: Boolean; +begin + username := ABuffer.ReadStringNull; + passwordHash := MD5Print(MD5String(ABuffer.ReadStringNull)); + account := Config.Accounts.Find(username); + if account <> nil then + begin + if account.AccessLevel > alNone then + begin + if account.PasswordHash = passwordHash then + begin + invalid := False; + CEDServerInstance.TCPServer.IterReset; + if CEDServerInstance.TCPServer.Iterator <> nil then + begin + repeat + netState := TNetState(CEDServerInstance.TCPServer.Iterator.UserData); + if (netState <> nil) and (netState.Account = account) then + begin + CEDServerInstance.SendPacket(ANetState, TLoginResponsePacket.Create(lsAlreadyLoggedIn)); + CEDServerInstance.Disconnect(ANetState.Socket); + invalid := True; + Break; + end; + until not CEDServerInstance.TCPServer.IterNext; + end; + + if not invalid then + begin + Writeln(TimeStamp, 'Login (', username, '): ', ANetState.Socket.PeerAddress); + ANetState.Account := account; + CEDServerInstance.SendPacket(ANetState, TLoginResponsePacket.Create(lsOK, account.AccessLevel)); + CEDServerInstance.SendPacket(ANetState, TCompressedPacket.Create( + TClientListPacket.Create(ANetState))); + CEDServerInstance.SendPacket(nil, TClientConnectedPacket.Create(username)); + CEDServerInstance.SendPacket(ANetState, TSetClientPosPacket.Create(account.LastPos)); + end; + end else + begin + Writeln(TimeStamp, 'Invalid password for ', username); + CEDServerInstance.SendPacket(ANetState, TLoginResponsePacket.Create(lsInvalidPassword)); + CEDServerInstance.Disconnect(ANetState.Socket); + end; + end else + begin + Writeln(TimeStamp, 'Access denied for ', username); + CEDServerInstance.SendPacket(ANetState, TLoginResponsePacket.Create(lsNoAccess)); + CEDServerInstance.Disconnect(ANetState.Socket); + end; + end else + begin + Writeln(TimeStamp, 'Invalid account specified: ', ANetState.Socket.PeerAddress); + CEDServerInstance.SendPacket(ANetState, TLoginResponsePacket.Create(lsInvalidUser)); + CEDServerInstance.Disconnect(ANetState.Socket); + end; +end; + +procedure OnQuitPacket(ABuffer: TEnhancedMemoryStream; ANetState: TNetState); +begin + CEDServerInstance.Disconnect(ANetState.Socket); +end; + +{ TProtocolVersionPacket } + +constructor TProtocolVersionPacket.Create(AVersion: Cardinal); +begin + inherited Create($02, 0); + FStream.WriteByte($01); + FStream.WriteCardinal(AVersion); +end; + +{ TLoginResponsePacket } + +constructor TLoginResponsePacket.Create(AState: TLoginState; + AAccessLevel: TAccessLevel = alNone); +begin + inherited Create($02, 0); + FStream.WriteByte($03); + FStream.WriteByte(Byte(AState)); + if AState = lsOK then + begin + FStream.WriteByte(Byte(AAccessLevel)); + FStream.WriteWord(Config.Map.Width); + FStream.WriteWord(Config.Map.Height); + end; +end; + +{ TServerStatePacket } + +constructor TServerStatePacket.Create(AState: TServerState; AMessage: string = ''); +begin + inherited Create($02, 0); + FStream.WriteByte($04); + FStream.WriteByte(Byte(AState)); + if AState = ssOther then + FStream.WriteStringNull(AMessage); +end; + +{$WARNINGS OFF} +var + i: Integer; + +initialization + for i := 0 to $FF do + ConnectionPacketHandlers[i] := nil; + ConnectionPacketHandlers[$03] := TPacketHandler.Create(0, @OnLoginRequestPacket); + ConnectionPacketHandlers[$05] := TPacketHandler.Create(0, @OnQuitPacket); +finalization + for i := 0 to $FF do + if ConnectionPacketHandlers[i] <> nil then + ConnectionPacketHandlers[i].Free; +{$WARNINGS ON} + +end. + diff --git a/Server/ULandscape.pas b/Server/ULandscape.pas index 2a8b593..5b7062d 100644 --- a/Server/ULandscape.pas +++ b/Server/ULandscape.pas @@ -30,7 +30,7 @@ unit ULandscape; interface uses - SysUtils, Classes, contnrs, UGenericIndex, UMap, UStatics, UTileData, + SysUtils, Classes, contnrs, UGenericIndex, UMap, UStatics, UTiledata, UWorldItem, UMulBlock, math, UTileDataProvider, URadarMap, UListSort, UCacheManager, ULinkedList, UBufferedStreams, diff --git a/Server/cedserver.lpi b/Server/cedserver.lpi index 1c6eabe..73aecba 100644 --- a/Server/cedserver.lpi +++ b/Server/cedserver.lpi @@ -14,7 +14,6 @@ - @@ -29,7 +28,7 @@ - + @@ -70,6 +69,11 @@ + + + + + @@ -89,7 +93,7 @@ - + diff --git a/Server/cedserver.lpr b/Server/cedserver.lpr index 2889d79..1562d89 100644 --- a/Server/cedserver.lpr +++ b/Server/cedserver.lpr @@ -1,75 +1,73 @@ -(* - * 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 2007 Andreas Schneider - *) -program cedserver; - -{$mode objfpc}{$H+} - -uses - {$IFDEF UNIX}{$IFDEF UseCThreads} - cthreads, - {$ENDIF}{$ENDIF} - SysUtils, Classes, - lnetbase, - UConfig, UCEDServer, URadarMap, ULargeScaleOperations; - -{$I version.inc} - -begin - Writeln('UO CentrED Server Version ', ProductVersion); - Writeln('Copyright ', Copyright); - //Writeln('================================'); - Writeln(''); - - {$IFDEF Windows} - if not LoadConfig then - begin - InitConfig; - Writeln(''); - end; - {$ELSE} - if ParamStr(1) = '--init' then - begin - InitConfig; - Halt; - end; - - if not LoadConfig then - begin - Writeln('No valid config file was found. Use --init to create one.'); - Halt; - end; - {$ENDIF} - - Write(TimeStamp, 'Initializing ... '); - Randomize; - CEDServerInstance := TCEDServer.Create; - Writeln('Done'); - CEDServerInstance.Run; - Write(TimeStamp, 'Terminating ... '); - CEDServerInstance.Free; - Writeln('Done'); -end. - +(* + * 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 2008 Andreas Schneider + *) +program cedserver; + +{$mode objfpc}{$H+} + +uses + {$IFDEF UNIX}{$IFDEF UseCThreads} + cthreads, + {$ENDIF}{$ENDIF} + SysUtils, Classes, + lnetbase, + UConfig, UCEDServer, URadarMap, ULargeScaleOperations; + +{$I version.inc} + +begin + Writeln('UO CentrED Server Version ', ProductVersion); + Writeln('Copyright ', Copyright); + //Writeln('================================'); + Writeln(''); + + {$IFDEF Windows} + if FileExists(ConfigFile) then + Config := TConfig.Create(ConfigFile) + else + Config := TConfig.Init(ConfigFile); + {$ELSE} + if ParamStr(1) = '--init' then + Config := TConfig.Init(ConfigFile) + else if FileExists(ConfigFile) then + Config := TConfig.Create(ConfigFile) + else begin + Writeln('No valid config file was found. Use --init to create one.'); + Halt; + end; + {$ENDIF} + + Write(TimeStamp, 'Initializing ... '); + Randomize; + CEDServerInstance := TCEDServer.Create; + Writeln('Done'); + CEDServerInstance.Run; + Write(TimeStamp, 'Terminating ... '); + FreeAndNil(CEDServerInstance); + Config.Flush; + FreeAndNil(Config); + Writeln('Done'); +end. + diff --git a/UIStream.pas b/UIStream.pas deleted file mode 100644 index e38bc74..0000000 --- a/UIStream.pas +++ /dev/null @@ -1,75 +0,0 @@ -(* - * 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 2007 Andreas Schneider - *) - -{This unit contains the interface for objects which offer read/write access and -therefore streaming capability. - -@author(Andreas Schneider ) -@created(2007-07-08) -@lastmod(2007-11-14)} -unit UIStream; - -{$mode objfpc}{$H+} -{$interfaces corba} - -interface - -uses - Classes; - -type - {@abstract(The @name interface is used in objects which offer read/write access and - therefore streaming capability.)} - IStream = interface - function ReadBoolean: Boolean; // = class(TObject{, IStream}) {@abstract(@name implements @link(IStream) and offers a bunch of functions to ease reading and writing special types (like @link(Integer)s or @link(String)s.))} - TStreamWrapper = class(TObject, IStream) + TStreamWrapper = class(TObject) constructor Create(AStream: TStreamType; AOwnsStream: Boolean = True); //