Advertisement
Guest User

MEOW

a guest
Jan 12th, 2012
454
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Delphi 171.72 KB | None | 0 0
  1. {(
  2.  )) .       .      __  __  ___   __  _    _
  3. ((  \`-"'"-'/     (  \/  )(  _) /  \( \/\/ )
  4.  ))  ) 6 6 (   -   )    (  ) _)( () )\    /
  5. ((  =.  Y  ,=     (_/\/\_)(___) \__/  \/\/
  6.  ))   /^^^\  .
  7. ((   /     \  )         Mini EO? WOW!
  8.  )) (  )-(  )/ Created by Sordie out of boredom
  9. ((   ""   ""
  10.  )}
  11.  
  12. program MEOW;
  13.  
  14. {$APPTYPE CONSOLE}
  15.  
  16. {$DEFINE THREAD_SAFE}
  17. {$DEFINE LOG_CONFIG}
  18. {$DEFINE LOG_SQL}
  19. {$DEFINE LOG_UNHANDLED_PACKET_FAMILY}
  20. {$DEFINE LOG_UNHANDLED_PACKET_ACTION}
  21. {$DEFINE LOG_COMMANDS}
  22. {$DEFINE INTERNAL_PUB}
  23.  
  24. {
  25.  TODO:
  26.  
  27.   Server stats
  28.  
  29.   Weapon effects
  30.  
  31.   #commands
  32.   Parties
  33.   Book - showing kills, killed
  34.   Item presets? Like "/equip dragon" for dragon armor etc
  35.  
  36.   SLN
  37.  
  38.   Re/over-log
  39.  
  40.   MEOW BASIC
  41. }
  42.  
  43. uses
  44.   Windows, WinSock;
  45.  
  46. const
  47.   Version = '0.2';   // Only I (Sordie) should change this!
  48.   Branch  = 'root';  // If you customize this source for your own needs, change this.
  49.  
  50.   localhost = $100007F; // 127.0.0.1
  51.  
  52. type
  53.   procedureref = reference to procedure;
  54.  
  55.   CriticalSectionHelper = record helper for TRTLCriticalSection
  56.     procedure Create; inline;
  57.     procedure Free;   inline;
  58.  
  59.     procedure Enter; inline;
  60.     procedure Leave; inline;
  61.  
  62.     procedure Section(Code: procedureref); inline;
  63.   end;{CriticalSectionHelper}
  64.  
  65. const
  66.   sqlite3 = 'sqlite3.dll';
  67.  
  68. type
  69.   TSQLiteDB    = Pointer;
  70.   TSQLiteQuery = Pointer;
  71.  
  72. function sqlite3_open(DBName: PAnsiChar; var DB: TSQLiteDB): Integer; cdecl; external sqlite3;
  73. function sqlite3_close(DB: TSQLiteDB): Integer; cdecl; external sqlite3;
  74. function sqlite3_prepare(DB: TSQLiteDB; QueryStr: PAnsiChar; QuerySize: Integer; var Query: TSQLiteQuery; var NextQuery: PAnsiChar): Integer; cdecl; external sqlite3;
  75. function sqlite3_step(Query: TSQLiteQuery): Integer; cdecl; external sqlite3;
  76. function sqlite3_finalize(Query: TSQLiteQuery): Integer; cdecl; external sqlite3;
  77. function sqlite3_column_count(Query: TSQLiteQuery): Integer; cdecl; external sqlite3;
  78. function sqlite3_column_name(Query: TSQLiteQuery; i: Integer): PAnsiChar; cdecl; external sqlite3;
  79. function sqlite3_column_type(Query: TSQLiteQuery; i: Integer): Integer; cdecl; external sqlite3;
  80. function sqlite3_column_int(Query: TSQLiteQuery; i: Integer): Integer; cdecl; external sqlite3;
  81. function sqlite3_column_text(Query: TSQLiteQuery; i: Integer): PAnsiChar; cdecl; external sqlite3;
  82.  
  83. const
  84.   SQLITE_OK   = 0;
  85.   SQLITE_ROW  = 100;
  86.   SQLITE_DONE = 101;
  87.  
  88.   SQLITE_INTEGER = 1;
  89.   SQLITE_TEXT    = 3;
  90.   SQLITE_NULL    = 5;
  91.  
  92. type
  93.   TDatabase = class
  94.     var CriticalSection: TRTLCriticalSection;
  95.  
  96.     var FileName: AnsiString;
  97.     var DB:       TSQLiteDB;
  98.  
  99.     type TTable = class
  100.       var Database: TDatabase;
  101.  
  102.       type TCell = record
  103.         DataType: Integer;
  104.  
  105.         DataStr:  AnsiString;
  106.         DataInt:  Integer;
  107.       end;{TCell}
  108.  
  109.       var ColumnNames: array of AnsiString;
  110.       var Table:       array of array of TCell;
  111.  
  112.       constructor Create(ADatabase: TDatabase; SQL: AnsiString);
  113.       destructor  Destroy; override;
  114.  
  115.       function Empty: Boolean; inline;
  116.  
  117.       function Column(Name: AnsiString): Integer;
  118.  
  119.       function Value(Name: AnsiString; Row: Integer = 0; Default: AnsiString = ''): AnsiString;  overload;
  120.       function Value(Name: AnsiString; Row: Integer = 0; Default: Integer    = 0):  Integer;     overload;
  121.     end;{TTable}
  122.  
  123.     constructor Create(AFileName: AnsiString);
  124.     destructor  Destroy; override;
  125.  
  126.     function  Prepare(SQL: AnsiString): TSQLiteQuery;
  127.     procedure Finalize(var Query: TSQLiteQuery);
  128.  
  129.     function Query     (SQL: AnsiString): Boolean;
  130.     function QueryTable(SQL: AnsiString): TTable; inline;
  131.  
  132.     function TableExists(Name: AnsiString): Boolean;
  133.   end;{TDatabase}
  134.  
  135.   TINIFile = class
  136.     var CriticalSection: TRTLCriticalSection;
  137.  
  138.     var FileName: AnsiString;
  139.  
  140.     constructor Create(AFileName: AnsiString);
  141.     destructor  Destroy; override;
  142.  
  143.     function Read(Section, Key: AnsiString; Default: AnsiString  = ''):    AnsiString; overload;
  144.     function Read(Section, Key: AnsiString; Default: Integer     = 0):     Integer;    overload;
  145.     function Read(Section, Key: AnsiString; Default: Boolean     = False): Boolean;    overload;
  146.   end;{TINIFile}
  147.  
  148.   TArray<T: class> = class
  149.     var Items: array of T;
  150.  
  151.     constructor Create;
  152.     destructor  Destroy; override;
  153.  
  154.     function Find  (Item: T): Integer;
  155.     function Add   (Item: T): Integer;
  156.     function Remove(Item: T): Integer;
  157.  
  158.     procedure Clear;
  159.   end;{TArray<T>}
  160.  
  161.   TStrings = record
  162.     Items: array of AnsiString;
  163.  
  164.     function Load(FileName: String): Boolean;
  165.     function Save(FileName: String): Boolean;
  166.   end;{TStrings}
  167.  
  168.   TSHA256Hash = packed record
  169.     A, B, C, D, E, F, G, H: Cardinal;
  170.   end;{TSHA256Hash}
  171.  
  172.   TSHA256 = record
  173.     Hash:   TSHA256Hash;
  174.     MLen:   Int64;
  175.     Buffer: array[0..63] of Byte;
  176.     Index:  Integer;
  177.  
  178.     procedure Init;
  179.     procedure Compress;
  180.     procedure Update(Data: Pointer; Len: Integer);
  181.     function  Done: AnsiString;
  182.  
  183.     class function HashStr(S: AnsiString): AnsiString; static;
  184.   end;{TSHA256}
  185.  
  186. {$IFDEF INTERNAL_PUB}
  187. const
  188.   ItemPubData: AnsiString = #$45#$49#$46#$90#$B0#$09#$B1#$03#$FE#$01#$05 +
  189.     #$47#$6F#$6C#$64#$1A#$FE#$01#$01#$01#$01#$FE#$01#$FE#$01#$FE#$01#$FE +
  190.     #$01#$FE#$01#$FE#$01#$FE#$02#$01#$01#$01#$01#$01#$01#$01#$01#$01#$01 +
  191.     #$01#$01#$01#$FE#$FE#$01#$01#$01#$FE#$01#$FE#$01#$FE#$01#$FE#$01#$FE +
  192.     #$01#$FE#$01#$FE#$01#$FE#$02#$02#$01#$01#$01#$04#$65#$6F#$66#$01#$FE +
  193.     #$01#$01#$01#$01#$FE#$01#$FE#$01#$FE#$01#$FE#$01#$FE#$01#$FE#$01#$FE +
  194.     #$01#$01#$01#$01#$01#$01#$01#$01#$01#$01#$01#$01#$01#$01#$FE#$FE#$01 +
  195.     #$01#$01#$FE#$01#$FE#$01#$FE#$01#$FE#$01#$FE#$01#$FE#$01#$FE#$01#$FE +
  196.     #$01#$01#$01#$01#$01;
  197.  
  198.   NPCPubData:  AnsiString = #$45#$4E#$46#$02#$FE#$FE#$FE#$02#$FE#$01#$04 +
  199.     #$65#$6F#$66#$01#$FE#$01#$01#$FE#$01#$FE#$01#$FE#$01#$FE#$01#$FE#$FE +
  200.     #$01#$FE#$01#$FE#$01#$FE#$01#$FE#$01#$FE#$01#$FE#$01#$01#$FE#$01#$FE +
  201.     #$01#$FE#$01#$FE#$01#$01#$FE#$FE;
  202.  
  203.   SpellPubData:AnsiString = #$45#$53#$46#$03#$FE#$FE#$FE#$02#$FE#$01#$04 +
  204.     #$01#$65#$6F#$66#$01#$FE#$01#$FE#$01#$FE#$01#$FE#$01#$01#$01#$01#$FE +
  205.     #$FE#$01#$01#$FE#$01#$01#$01#$01#$01#$FE#$01#$FE#$01#$FE#$01#$FE#$01 +
  206.     #$FE#$01#$FE#$01#$01#$FE#$01#$FE#$01#$01#$FE#$01#$FE#$01#$FE#$01#$FE +
  207.     #$01#$FE#$01#$FE;
  208.  
  209.   ClassPubData:AnsiString = #$45#$43#$46#$04#$FE#$FE#$FE#$03#$FE#$01#$07 +
  210.     #$4E#$6F#$72#$6D#$61#$6C#$01#$01#$01#$FE#$01#$FE#$01#$FE#$01#$FE#$01 +
  211.     #$FE#$01#$FE#$04#$65#$6F#$66#$01#$01#$01#$FE#$01#$FE#$01#$FE#$01#$FE +
  212.     #$01#$FE#$01#$FE;
  213.  
  214.  
  215. type
  216. {$ENDIF INTERNAL_PUB}
  217.   Server = class abstract
  218.     const RequiredVersion: array[0..2] of Byte = (0, 0, 28);
  219.  
  220.     const ReceiveKey = 8;
  221.     const SendKey    = 10;
  222.  
  223.     const GoldID  = 1;
  224.     const MaxGold = 10000000;
  225.  
  226.     const CustomTitle        = 'Customize Character -';
  227.     const CustomRaceID       = 1;
  228.     const CustomSexID        = 2;
  229.  
  230.     const PacketFamilyRaw        = 255;
  231.     const PacketFamilyConnection = 1;
  232.     const PacketFamilyAccount    = 2;
  233.     const PacketFamilyLogin      = 4;
  234.     const PacketFamilyGameState  = 5;
  235.     const PacketFamilyWalk       = 6;
  236.     const PacketFamilyFace       = 7;
  237.     const PacketFamilyChair      = 8;
  238.     const PacketFamilyEmote      = 9;
  239.     const PacketFamilyAttack     = 11;
  240.     const PacketFamilyItem       = 14;
  241.     const PacketFamilySkill      = 16;
  242.     const PacketFamilyGlobal     = 17;
  243.     const PacketFamilyTalk       = 18;
  244.     const PacketFamilyWarp       = 19;
  245.     const PacketFamilyPlayers    = 22;
  246.     const PacketFamilyAppearance = 23;
  247.     const PacketFamilyParty      = 24;
  248.     const PacketFamilyRefresh    = 25;
  249.     const PacketFamilyRequest    = 27;
  250.     const PacketFamilyEffect     = 31;
  251.     const PacketFamilyDoor       = 34;
  252.     const PacketFamilyMessage    = 35;
  253.     const PacketFamilyBarber     = 38;
  254.     const PacketFamilySound      = 40;
  255.     const PacketFamilySit        = 41;
  256.     const PacketFamilyUpdate     = 42;
  257.     const PacketFamilyArena      = 45;
  258.     const PacketFamilyAdmin      = 48;
  259.     const PacketFamilyInnKeeper  = 49;
  260.     const PacketFamilyQuest      = 50;
  261.  
  262.     const PacketActionRaw      = 255;
  263.     const PacketActionRequest  = 1;
  264.     const PacketActionAccept   = 2;
  265.     const PacketActionReply    = 3;
  266.     const PacketActionRemove   = 4;
  267.     const PacketActionAgree    = 5;
  268.     const PacketActionCreate   = 6;
  269.     const PacketActionAdd      = 7;
  270.     const PacketActionPlayer   = 8;
  271.     const PacketActionTake     = 9;
  272.     const PacketActionUse      = 10;
  273.     const PacketActionBuy      = 11;
  274.     const PacketActionOpen     = 13;
  275.     const PacketActionClose    = 14;
  276.     const PacketActionMessage  = 15;
  277.     const PacketActionSpecial  = 16;
  278.     const PacketActionAdmin    = 17;
  279.     const PacketActionList     = 18;
  280.     const PacketActionTell     = 20;
  281.     const PacketActionReport   = 21;
  282.     const PacketActionAnnounce = 22;
  283.     const PacketActionServer   = 23;
  284.     const PacketActionJunk     = 25;
  285.     const PacketActionGet      = 27;
  286.     const PacketActionDialog   = 34;
  287.     const PacketActionPing     = 240;
  288.     const PacketActionPong     = 241;
  289.  
  290.     type TPacket = record
  291.       Family: Byte;
  292.       Action: Byte;
  293.  
  294.       Data:   AnsiString;
  295.  
  296.       Time: Cardinal;
  297.  
  298.       procedure SetID(AFamily, AAction: Byte);
  299.  
  300.       procedure Reset; inline;
  301.  
  302.       procedure Discard(Count: Integer = 1); inline;
  303.  
  304.       procedure AddByte(b: Byte); inline;
  305.       procedure AddInt1(i: Byte); inline;
  306.       procedure AddInt2(i: Word); inline;
  307.       procedure AddInt3(i: Cardinal); inline;
  308.       procedure AddInt4(i: Cardinal); inline;
  309.       procedure AddBreakString(s: AnsiString); inline;
  310.       procedure AddString     (s: AnsiString); inline;
  311.  
  312.       function GetByte: Byte;
  313.       function GetInt1: Byte;
  314.       function GetInt2: Word;
  315.       function GetInt3: Cardinal;
  316.       function GetInt4: Cardinal;
  317.       function GetBreakString:               AnsiString;
  318.       function GetString(Len: Integer = -1): AnsiString;
  319.     end;{TPacket}
  320.  
  321.     TGameData = class abstract
  322.       var Data: AnsiString;
  323.       var CRC:  array[0..3] of Byte;
  324.       var Len:  array[0..1] of Byte;
  325.  
  326.       var FileName: AnsiString;
  327.  
  328.       class function DataID: Byte; virtual; abstract;
  329.  
  330.       constructor Create(AFileName: AnsiString);
  331.       destructor  Destroy; override;
  332.  
  333.       function  Load: Boolean; virtual;
  334.       procedure Clear; virtual;
  335.     end;{TGameData}
  336.  
  337.     TItemData = class(TGameData)
  338.       const ItemTypeSoda = 22;
  339.  
  340.       class function DataID: Byte; override;
  341.     end;{TItemData}
  342.  
  343.     TNPCData = class(TGameData)
  344.       class function DataID: Byte; override;
  345.     end;{TNPCData}
  346.  
  347.     TSpellData = class(TGameData)
  348.       class function DataID: Byte; override;
  349.     end;{TSpellData}
  350.  
  351.     TClassData = class(TGameData)
  352.       class function DataID: Byte; override;
  353.     end;{TClassData}
  354.  
  355.     TMapData = class(TGameData)
  356.       class function DataID: Byte; override;
  357.  
  358.       type TWarp = record
  359.         var Enabled:  Boolean;
  360.         var X, Y, M:  Integer;
  361.         var ReqLevel: Integer;
  362.         var ReqItem:  Integer;
  363.       end;{TWarp}
  364.  
  365.       const MapTileEmpty          = 0;
  366.       const MapTileWall           = 1;
  367.       const MapTileChairDown      = 2;
  368.       const MapTileChairLeft      = 3;
  369.       const MapTileChairRight     = 4;
  370.       const MapTileChairUp        = 5;
  371.       const MapTileChairDownRight = 6;
  372.       const MapTileChairUpLeft    = 7;
  373.       const MapTileChairAll       = 8;
  374.       const MapTileDoor           = 9;
  375.       const MapTileChest          = 10;
  376.       const MapTileBankVault      = 17;
  377.       const MapTileNPCBoundary    = 18;
  378.       const MapTileMapEdge        = 19;
  379.       const MapTileBoard1         = 21;
  380.       const MapTileBoard2         = 22;
  381.       const MapTileBoard3         = 23;
  382.       const MapTileBoard4         = 24;
  383.       const MapTileBoard5         = 25;
  384.       const MapTileBoard6         = 26;
  385.       const MapTileBoard7         = 27;
  386.       const MapTileBoard8         = 28;
  387.       const MapTileJukebox        = 29;
  388.       const MapTileJump           = 30;
  389.       const MapTileWater          = 31;
  390.       const MapTileArena          = 33;
  391.       const MapTileSpikes1        = 35;
  392.       const MapTileSpikes2        = 36;
  393.       const MapTileSpikes3        = 37;
  394.  
  395.       const MapTilesImpassible = [MapTileWall,
  396.                                   MapTileChairDown..MapTileChairAll,
  397.                                   MapTileChest,
  398.                                   MapTileBankVault,
  399.                                   MapTileMapEdge,
  400.                                   MapTileBoard1..MapTileBoard8,
  401.                                   MapTileJukebox];
  402.  
  403.       type TMapTile = record
  404.         Kind: Integer;
  405.         Warp: TWarp;
  406.       end;{TMapTile}
  407.  
  408.       var Width:  Integer;
  409.       var Height: Integer;
  410.       var Tiles:  array of array of TMapTile;
  411.  
  412.       function Load: Boolean; override;
  413.       procedure Clear; override;
  414.  
  415.       function IsWalkable(X, Y: Integer; NPC: Boolean = False): Boolean;
  416.     end;{TMapData}
  417.  
  418.     class var ItemData:  TItemData;
  419.     class var NPCData:   TNPCData;
  420.     class var SpellData: TSpellData;
  421.     class var ClassData: TClassData;
  422.     class var MapData:   TMapData;
  423.  
  424.     type TSession = class
  425.       var Offline: Boolean;
  426.  
  427.       var Socket: TSocket;
  428.       var IPStr:  AnsiString;
  429.       var IPInt:  Integer;
  430.  
  431.       var Thread: THandle;
  432.  
  433.       var Banned: Integer;
  434.  
  435.       var ID:          Cardinal;
  436.       var Initialized: Boolean;
  437.       var LoggedIn:    Boolean;
  438.  
  439.       var Packet: record
  440.         Buffer: AnsiString;
  441.  
  442.         Queue: record
  443.           Items:  array of TPacket;
  444.           Time:   Cardinal;
  445.           Active: Boolean;
  446.         end;{Queue}
  447.  
  448.         Receive: TPacket;
  449.         Send:    TPacket;
  450.  
  451.         Time: Cardinal;
  452.       end;{Packet}
  453.  
  454.       var Usage: record
  455.         Started: Boolean;
  456.         Last:    Cardinal;
  457.         Current: Cardinal;
  458.       end;{Usage}
  459.  
  460.       var Name:      AnsiString;
  461.       var Password:  AnsiString;
  462.       var HDDSerial: AnsiString;
  463.  
  464.       const StateRaceSelected = 1;
  465.       const StateSexSelected  = 2;
  466.       const StateHairSelected = 4;
  467.  
  468.       var State: Integer;
  469.  
  470.       var X: Integer;
  471.       var Y: Integer;
  472.       var D: Integer;
  473.  
  474.       var Sitting: Integer;
  475.       var Hidden:  Integer;
  476.  
  477.       var Admin: Integer;
  478.  
  479.       var Tag:        AnsiString;
  480.       var Sex:        Integer;
  481.       var HairStyle:  Integer;
  482.       var HairColour: Integer;
  483.       var Race:       Integer;
  484.  
  485.       var Boots:  Integer;
  486.       var Armour: Integer;
  487.       var Hat:    Integer;
  488.       var Shield: Integer;
  489.       var Weapon: Integer;
  490.  
  491.       var Gold: Integer;
  492.  
  493.       var HP, MaxHP: Integer;
  494.       var TP, MaxTP: Integer;
  495.  
  496.       var Kills: Integer;
  497.  
  498.       const WarpAnimationNone    = 1;
  499.       const WarpAnimationBubbles = 2;
  500.  
  501.       var WarpInfo: record
  502.         Time:      Cardinal;
  503.         X, Y:      Integer;
  504.         Animation: Integer;
  505.       end;{WarpInfo}
  506.  
  507.       type TParty = class
  508.         var Leader:  TSession;
  509.         var Members: TArray<TSession>;
  510.  
  511.         constructor Create(ALeader: TSession);
  512.         destructor  Destroy; override;
  513.  
  514.         procedure Join   (Session: TSession);
  515.         procedure Leave  (Session: TSession); overload;
  516.         procedure Leave  (ID: Cardinal);      overload;
  517.         procedure Refresh(Session: TSession);
  518.         procedure Update (Session: TSession);
  519.       end;{TParty}
  520.  
  521.       var Party: TParty;
  522.  
  523.       constructor Create(ASocket: TSocket; ASockAddr: TSockAddr);
  524.       destructor  Destroy; override;
  525.  
  526.       class function CreateOffline(AName: AnsiString): TSession;
  527.  
  528.       procedure ClearQueue;
  529.  
  530.       procedure Disconnect;
  531.  
  532.       function  Sync(Discard: Boolean = False): Boolean;
  533.       procedure Unload;
  534.  
  535.       procedure Log(Params: array of const);
  536.  
  537.       procedure Send(var Packet: TPacket; Raw: Boolean = False); overload;
  538.       procedure Send(                     Raw: Boolean = False); overload; inline;
  539.  
  540.       procedure SendData(Data: TGameData);
  541.  
  542.       procedure Login;
  543.       procedure Logout;
  544.  
  545.       procedure BuildCharacterPacket(var Packet: TPacket);
  546.  
  547.       const DirectionDown  = 0;
  548.       const DirectionLeft  = 1;
  549.       const DirectionUp    = 2;
  550.       const DirectionRight = 3;
  551.  
  552.       const SittingStand = 0;
  553.       const SittingChair = 1;
  554.       const SittingFloor = 2;
  555.  
  556.       procedure Refresh;
  557.       procedure RefreshAll;
  558.  
  559.       function Walk(Direction: Integer; Admin: Boolean = False; Ghost: Boolean = False; SendToSelf: Boolean = False): Boolean;
  560.       function Face(Direction: Integer; SendToSelf: Boolean = False): Boolean;
  561.       function Say(Text: AnsiString; SendToSelf: Boolean = False): Boolean;
  562.       function SayGlobal(Text: AnsiString; SendToSelf: Boolean = False): Boolean;
  563.       function SayGuild(Text: AnsiString; SendToSelf: Boolean = False): Boolean;
  564.       function SayAdmin(Text: AnsiString; SendToSelf: Boolean = False): Boolean;
  565.       function Announce(Text: AnsiString): Boolean;
  566.       function Warp(WX, WY: Integer; Animation: Integer = WarpAnimationNone): Boolean;
  567.       function Sit(Chair: Boolean = False): Boolean;
  568.       function Stand: Boolean;
  569.       function Emote(EmoteID: Integer; SendToSelf: Boolean = False): Boolean;
  570.       function Status(Msg: AnsiString): Boolean;
  571.       function Mute(From: AnsiString = 'Server'): Boolean;
  572.       function Freeze: Boolean;
  573.       function Unfreeze: Boolean;
  574.       function Effect(EffectID: Integer; SendToSelf: Boolean = False): Boolean;
  575.       function Drunk(Scale: Integer): Boolean;
  576.       function Quake(Scale: Integer): Boolean;
  577.       function HelloHax0r: Boolean;
  578.       function Show: Boolean;
  579.       function Hide: Boolean;
  580.       function Sound(SoundID: Integer): Boolean;
  581.       function Ban: Boolean;
  582.       function UnBan: Boolean;
  583.       function Sleep: Boolean;
  584.       function Barber: Boolean;
  585.       function SetGold(Value: Integer): Boolean;
  586.       function Damage(Amount: Integer; By: TSession): Boolean;
  587.       function SetHP(Value: Integer): Boolean;
  588.       function SetTP(Value: Integer): Boolean;
  589.       function SetMaxHP(Value: Integer): Boolean;
  590.       function SetMaxTP(Value: Integer): Boolean;
  591.       function UpdateHPTP: Boolean;
  592.       function UpdateStats: Boolean;
  593.       function Die(By: TSession): Boolean;
  594.       function Resurrect: Boolean;
  595.  
  596.       function RaceDialog: Boolean;
  597.       function SexDialog:  Boolean;
  598.  
  599.       function ReceivePM(From, Text: AnsiString): Boolean;
  600.       function SendPM(SendTo, Text: AnsiString): Boolean;
  601.  
  602.       function Attack(Direction: Integer; SendToSelf: Boolean = False): Boolean;
  603.       procedure Attacked(By: TSession);
  604.  
  605.       function DoCommand(Cmd: AnsiString; Sender: TSession = nil): Boolean;
  606.  
  607.       function Execute: Boolean;
  608.  
  609.       procedure DefaultHandler(var Param); override;
  610.       procedure UnhandledAction(Name: AnsiString = '');
  611.  
  612.       procedure HandleRaw       (var Param); message PacketFamilyRaw;
  613.       procedure HandleConnection(var Param); message PacketFamilyConnection;
  614.       procedure HandleAccount   (var Param); message PacketFamilyAccount;
  615.       procedure HandleLogin     (var Param); message PacketFamilyLogin;
  616.       procedure HandleGameState (var Param); message PacketFamilyGameState;
  617.       procedure HandleWalk      (var Param); message PacketFamilyWalk;
  618.       procedure HandleFace      (var Param); message PacketFamilyFace;
  619.       procedure HandleRequest   (var Param); message PacketFamilyRequest;
  620.       procedure HandleTalk      (var Param); message PacketFamilyTalk;
  621.       procedure HandleSit       (var Param); message PacketFamilySit;
  622.       procedure HandleChair     (var Param); message PacketFamilyChair;
  623.       procedure HandleAttack    (var Param); message PacketFamilyAttack;
  624.       procedure HandleWarp      (var Param); message PacketFamilyWarp;
  625.       procedure HandleEmote     (var Param); message PacketFamilyEmote;
  626.       procedure HandleRefresh   (var Param); message PacketFamilyRefresh;
  627.       procedure HandleMessage   (var Param); message PacketFamilyMessage;
  628.       procedure HandlePlayers   (var Param); message PacketFamilyPlayers;
  629.       procedure HandleDoor      (var Param); message PacketFamilyDoor;
  630.       procedure HandleGlobal    (var Param); message PacketFamilyGlobal;
  631.       procedure HandleQuest     (var Param); message PacketFamilyQuest;
  632.       procedure HandleBarber    (var Param); message PacketFamilyBarber;
  633.       procedure HandleAdmin     (var Param); message PacketFamilyAdmin;
  634.       procedure HandleParty     (var Param); message PacketFamilyParty;
  635.  
  636.       procedure _test(Params: AnsiString);
  637.     end;{Session}
  638.  
  639.     class var CriticalSection: TRTLCriticalSection;
  640.  
  641.     class var Sessions: TArray<TSession>;
  642.     class var Socket:   TSocket;
  643.  
  644.     class var Database:      TDatabase;
  645.     class var Configuration: TINIFile;
  646.  
  647.     class var Unapproved: TStrings;
  648.  
  649.     class var Connection: record
  650.       Bind:    AnsiString;
  651.       Port:    Word;
  652.       Timeout: Cardinal;
  653.       PerIP:   Integer;
  654.  
  655.       BytesIn:  Int64;
  656.       BytesOut: Int64;
  657.     end;{Connection}
  658.  
  659.     class var PacketQueue: record
  660.       Enabled: Boolean;
  661.       Size:    Integer;
  662.       Walk:    Cardinal;
  663.       Attack:  Cardinal;
  664.     end;{Packet}
  665.  
  666.     class var Defaults: record
  667.       X, Y, D:   Integer;
  668.       Gold:      Integer;
  669.       HP, MaxHP: Integer;
  670.       TP, MaxTP: Integer;
  671.     end;{Defaults}
  672.  
  673.     class var Admin: record
  674.       CommandChar: AnsiChar;
  675.       EchoCommand: Boolean;
  676.  
  677.       TagAdmin:     AnsiString;
  678.       TagLocalhost: AnsiString;
  679.  
  680.       Level: record
  681.         Appearance:  Integer;
  682.         Item:        Integer;
  683.         Action:      Integer;
  684.         Maintenance: Integer;
  685.       end;{Level}
  686.     end;{Admin}
  687.  
  688.     class var News: array[0..6] of AnsiString;
  689.  
  690.     const ViewRange  = 12;
  691.     const TextLength = 100;
  692.  
  693.     class constructor Create;
  694.     class destructor  Destroy;
  695.  
  696.     class procedure Main;
  697.  
  698.     class var Caption: AnsiString;
  699.     class procedure UpdateCaption;
  700.  
  701.     class procedure Log(Params: array of const; Prefix: AnsiString = '');
  702.  
  703.     class procedure Send      (var Packet: TPacket; Sender: TSession = nil; Ranged: Boolean = True);
  704.     class procedure SendRanged(var Packet: TPacket; X, Y: Integer);
  705.  
  706.     class function GetSessionByID  (ID:   Cardinal):   TSession;
  707.     class function GetSessionByName(Name: AnsiString): TSession;
  708.  
  709.     class procedure Msg(Msg: AnsiString);
  710.     class procedure AdminMsg(Msg: AnsiString; From: AnsiString = '[Server]');
  711.  
  712.     class procedure Freeze(Exclude: TSession);
  713.     class procedure Unfreeze;
  714.     class procedure Mute(Exclude: TSession);
  715.  
  716.     class procedure Quake(Scale: Integer);
  717.     class procedure Effect(EffectID, X, Y: Integer);
  718.     class procedure Sound(SoundID: Integer);
  719.  
  720.     class procedure SetMap(MapFile: AnsiString = '');
  721.     class procedure Mutate;
  722.  
  723.     class procedure OpenDoor(X, Y: Integer);
  724.  
  725.     class procedure Shutdown;
  726.  
  727.     const NameMax   = 12;
  728.     const NameChars = 'abcdefghijklmnopqrstuvwxyz0123456789';
  729.  
  730.     class function ValidName(Name: AnsiString; IgnoreUnapproved: Boolean = False): Boolean;
  731.  
  732.     class function GetAccount(Name: AnsiString; Items: AnsiString = '*'): TDatabase.TTable;
  733.     class function AccountExists(Name: AnsiString): Boolean;
  734.  
  735.     class procedure BanIP   (IP: AnsiString);
  736.     class procedure UnbanIP (IP: AnsiString);
  737.     class function  BannedIP(IP: Integer): Boolean;
  738.   end;{Server}
  739.  
  740. const
  741.   EOInt1Max = 253;
  742.   EOInt2Max = 64009;
  743.   EOInt3Max = 16194277;
  744.  
  745. function PackEOInt(b1: Byte = 0; b2: Byte = 0; b3: Byte = 0; b4: Byte = 0): Cardinal;
  746. begin
  747.   if b1 = 254 then b1 := 0 else if b1 > 0 then dec(b1);
  748.   if b2 = 254 then b2 := 0 else if b2 > 0 then dec(b2);
  749.   if b3 = 254 then b3 := 0 else if b3 > 0 then dec(b3);
  750.   if b4 = 254 then b4 := 0 else if b4 > 0 then dec(b4);
  751.  
  752.   Result := (b4 * EOInt3Max) + (b3 * EOInt2Max) + (b2 * EOInt1Max) + b1;
  753. end;{PackEOInt}
  754.  
  755. function UnpackEOInt(Num: Cardinal): AnsiString;
  756. var
  757.   i: Cardinal;
  758. begin
  759.   Result := #254#254#254#254;
  760.  
  761.   i := Num;
  762.  
  763.   if i >= EOInt3Max then
  764.   begin
  765.     Result[4] := AnsiChar(Num div EOInt3Max + 1);
  766.     Num := Num mod EOInt3Max;
  767.   end;{if i >= EOInt3Max}
  768.  
  769.   if i >= EOInt2Max then
  770.   begin
  771.     Result[3] := AnsiChar(Num div EOInt2Max + 1);
  772.     Num := Num mod EOInt2Max;
  773.   end;{if i >= EOInt2Max}
  774.  
  775.   if i >= EOInt1Max then
  776.   begin
  777.     Result[2] := AnsiChar(Num div EOInt1Max + 1);
  778.     Num := Num mod EOInt1Max;
  779.   end;{if i >= EOInt3Max}
  780.  
  781.   Result[1] := AnsiChar(Num + 1);
  782. end;{UnpackEOInt}
  783.  
  784. function FoldData(Str: AnsiString; Key: Byte): AnsiString;
  785. var
  786.   i:      Integer;
  787.   c:      AnsiChar;
  788.   Buffer: AnsiString;
  789. begin
  790.   if Key = 0 then exit(Str);
  791.  
  792.   Result := '';
  793.   Buffer := '';
  794.  
  795.   for c in Str do
  796.   begin
  797.     if (ord(c) mod Key) = 0 then
  798.       Buffer := Buffer + c
  799.     else
  800.     begin
  801.       if length(Buffer) > 0 then
  802.       begin
  803.         for i := length(Buffer) downto 1 do
  804.           Result := Result + Buffer[i];
  805.  
  806.         Buffer := '';
  807.       end;{if length(Buffer)}
  808.  
  809.       Result := Result + c;
  810.     end;{else}
  811.   end;{for c}
  812.  
  813.   if length(Buffer) > 0 then
  814.     for i := length(Buffer) downto 1 do
  815.       Result := Result + Buffer[i];
  816. end;{FoldData}
  817.  
  818. function bswap(A: integer): Integer;
  819. asm
  820.   bswap eax
  821. end;{bswap}
  822.  
  823. procedure bswap256(s, d: PInteger);
  824. asm
  825.   push ebx
  826.   mov ecx, eax
  827.   mov eax,[ecx];    mov ebx,[ecx+4];  bswap eax; bswap ebx; mov [edx],    eax; mov [edx+4],  ebx
  828.   mov eax,[ecx+8];  mov ebx,[ecx+12]; bswap eax; bswap ebx; mov [edx+8],  eax; mov [edx+12], ebx
  829.   mov eax,[ecx+16]; mov ebx,[ecx+20]; bswap eax; bswap ebx; mov [edx+16], eax; mov [edx+20], ebx
  830.   mov eax,[ecx+24]; mov ebx,[ecx+28]; bswap eax; bswap ebx; mov [edx+24], eax; mov [edx+28], ebx
  831.   pop ebx
  832. end;{bswap256}
  833.  
  834. function InterlockedExchangeAdd64(var Addend: Int64; Value: Int64): Int64; register;
  835. asm
  836.   push edi
  837.   push esi
  838.   push ebp
  839.   push ebx
  840.  
  841.   mov esi, dword ptr [Value]
  842.   mov edi, dword ptr [Value + 4]
  843.   mov ebp, eax
  844.  
  845.   mov eax, [ebp]
  846.   mov edx, [ebp + 4]
  847. @@lockmore:
  848.   mov ecx, edx
  849.   mov ebx, eax
  850.  
  851.   add ebx, esi
  852.   adc ecx, edi
  853.  
  854.   lock cmpxchg8b [ebp]
  855.   jnz @@lockmore
  856.  
  857.   pop ebx
  858.   pop ebp
  859.   pop esi
  860.   pop edi
  861. end;{InterlockedExchangeAdd64}
  862.  
  863. function Lower(S: AnsiString): AnsiString;
  864. var
  865.   c: AnsiChar;
  866. begin
  867.   Result := '';
  868.  
  869.   for c in S do
  870.     case c of
  871.       'A'..'Z': Result := Result + AnsiChar(ord('a') + (ord(c) - ord('A')));
  872.     else
  873.       Result := Result + c;
  874.     end;{case c}
  875. end;{Lower}
  876.  
  877. function Capitalize(S: AnsiString): AnsiString;
  878. var
  879.   i: Integer;
  880. begin
  881.   Result := S;
  882.  
  883.   for i := 1 to length(Result) do
  884.     if pos(String(Result[i]), 'abcdefghijklmnopqrstuvwxyz') > 0 then
  885.     begin
  886.       Result[i] := AnsiChar(ord('A') + (ord(Result[i]) - ord('a')));
  887.       break;
  888.     end{if pos...}
  889.     else if pos(String(Result[i]), 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789') > 0 then
  890.       break;
  891. end;{Captialize}
  892.  
  893. function Trim(Str: AnsiString): AnsiString;
  894. var
  895.   i: Integer;
  896. begin
  897.   for i := 1 to length(Str) do
  898.     if Str[i] <> ' ' then break;
  899.  
  900.   Result := copy(Str, i, length(Str));
  901.  
  902.   for i := length(Result) downto 1 do
  903.     if Result[i] <> ' ' then break;
  904.  
  905.   Result := copy(Result, 1, i);
  906. end;{Trim}
  907.  
  908. function Split(var Str: AnsiString; Delim: AnsiChar = ' '): AnsiString;
  909. var
  910.   i: Integer;
  911. begin
  912.   Str := Trim(Str);
  913.  
  914.   i := pos(Delim, Str);
  915.  
  916.   if i = 0 then
  917.   begin
  918.     Result := Str;
  919.     Str    := '';
  920.   end{if i}
  921.   else
  922.   begin
  923.     Result := Trim(copy(Str, 1, i - 1));
  924.     Str    := Trim(copy(Str, i + 1, length(Str)));
  925.   end;{else}
  926. end;{Splt}
  927.  
  928. function Int(S: AnsiString; Default: Integer = 0): Integer;
  929. var
  930.   Code: Integer;
  931. begin
  932.   Val(String(S), Result, Code);
  933.   if Code <> 0 then Result := Default;
  934. end;{Int}
  935.  
  936. function Str(I: Integer): AnsiString; overload;
  937. var
  938.   S: ShortString;
  939. begin
  940.   System.Str(I, S);
  941.   Result := AnsiString(S);
  942. end;{Str(Integer}
  943.  
  944. function Str(F: Extended): AnsiString; overload;
  945. var
  946.   S: ShortString;
  947. begin
  948.   System.Str(F:2:2, S);
  949.   Result := AnsiString(S);
  950. end;{Str(Extended}
  951.  
  952. function Tidy(s: AnsiString): AnsiString;
  953. var
  954.   i: Integer;
  955.   c: AnsiChar;
  956. begin
  957.   Result := '';
  958.  
  959.   for c in s do
  960.     if pos(String(c), '0123456789.') > 0 then Result := Result + c;
  961.  
  962.   if length(Result) = 0 then exit('0');
  963.  
  964.   if pos('.', String(Result)) > 0 then
  965.   begin
  966.     while Result[length(Result)] = '0' do
  967.       Result := copy(Result, 1, length(Result) - 1);
  968.  
  969.     if Result[length(Result)] = '.' then
  970.       Result := copy(Result, 1, length(Result) - 1);
  971.   end;{if pos('.'...}
  972.  
  973.   while (length(Result) > 0) and (Result[1] = '0') do
  974.     Result := copy(Result, 2, length(Result));
  975.  
  976.   i := pos('.', String(Result)) - 1; if i < 1 then i := length(Result);
  977.  
  978.   repeat
  979.     dec(i, 3); if i < 1 then break;
  980.  
  981.     Result := copy(Result, 1, i) + ',' + copy(Result, i + 1, length(Result));
  982.   until False;
  983.  
  984.   if (length(Result) = 0) or (Result[1] = '.') then Result := '0' + Result;
  985. end;{Tidy}
  986.  
  987. function Scale(i: Int64): AnsiString;
  988. const
  989.   MinAdjustValue = 900;
  990.   ScaleStr: array[0..3] of AnsiString = ('B', 'KB',  'MB',  'GB');
  991. var
  992.   j:  Integer;
  993.   k:  Extended;
  994. begin
  995.   j := 0;
  996.   k := i;
  997.  
  998.   while k > MinAdjustValue do
  999.   begin
  1000.     k := k / 1024;
  1001.     inc(j); if j = high(ScaleStr) then break;
  1002.   end;{while i}
  1003.  
  1004.   Result := Tidy(Str(k)) + ScaleStr[j];
  1005. end;{Scale}
  1006.  
  1007. function Str(B: Boolean): AnsiString; overload;
  1008. begin
  1009.   if B then
  1010.     Result := 'TRUE'
  1011.   else
  1012.     Result := 'FALSE';
  1013. end;{Str(Boolean}
  1014.  
  1015. function Bool(S: AnsiString; Default: Boolean = False): Boolean;
  1016. begin
  1017.   if length(S) = 0 then exit(Default);
  1018.   S := Lower(copy(S, 1, 2));
  1019.  
  1020.   if (S[1] = 't') or (S = 'ok') or (S = 'on') then
  1021.     Result := True
  1022.   else
  1023.     Result := Int(S, Integer(Default)) <> 0;
  1024. end;{Bool}
  1025.  
  1026. function Match(Mask, Str: AnsiString): Boolean;
  1027.   function Comp(MaskI, StrI: Integer): Boolean;
  1028.   var
  1029.     m: AnsiChar;
  1030.   begin
  1031.     if MaskI > length(Mask) then exit(StrI = length(Str) + 1);
  1032.     if StrI  > length(Str)  then exit(False);
  1033.  
  1034.     m := Mask[MaskI];
  1035.  
  1036.     if m = '*' then
  1037.       Result := Comp(succ(MaskI), succ(StrI)) or Comp(MaskI, succ(StrI))
  1038.     else if (m = '?') or (m = Str[StrI]) then
  1039.       Result := Comp(succ(MaskI), succ(StrI))
  1040.     else
  1041.       Result := False;
  1042.   end;{Comp}
  1043. begin
  1044.   if copy(Mask, 1, 1) = '!' then
  1045.     Result := pos(copy(Mask, 2, length(Mask)), Str) > 0
  1046.   else
  1047.     Result := Comp(1, 1);
  1048. end;{Match}
  1049.  
  1050. procedure Error(Params: array of const);
  1051. begin
  1052.   Server.Log(Params, '/!\ ERROR');
  1053.   Readln;
  1054.   halt(1);
  1055. end;{Error}
  1056.  
  1057. procedure CriticalSectionHelper.Create;
  1058. begin
  1059. {$IFDEF THREAD_SAFE}
  1060.   InitializeCriticalSection(Self);
  1061. {$ENDIF THREAD_SAFE}
  1062. end;{CriticalSectionHelper.Create}
  1063.  
  1064. procedure CriticalSectionHelper.Free;
  1065. begin
  1066. {$IFDEF THREAD_SAFE}
  1067.   DeleteCriticalSection(Self);
  1068. {$ENDIF THREAD_SAFE}
  1069. end;{CriticalSectionHelper.Free}
  1070.  
  1071. procedure CriticalSectionHelper.Enter;
  1072. begin
  1073. {$IFDEF THREAD_SAFE}
  1074.   EnterCriticalSection(Self);
  1075. {$ENDIF THREAD_SAFE}
  1076. end;{CriticalSectionHelper.Enter}
  1077.  
  1078. procedure CriticalSectionHelper.Leave;
  1079. begin
  1080. {$IFDEF THREAD_SAFE}
  1081.   LeaveCriticalSection(Self);
  1082. {$ENDIF THREAD_SAFE}
  1083. end;{CriticalSectionHelper.Leave}
  1084.  
  1085. procedure CriticalSectionHelper.Section(Code: procedureref);
  1086. begin
  1087.   Enter;
  1088.   try
  1089.     Code;
  1090.   finally
  1091.     Leave;
  1092.   end;{try...finally}
  1093. end;{CriticalSectionHelper.Secion}
  1094.  
  1095. constructor TDatabase.TTable.Create(ADatabase: TDatabase; SQL: AnsiString);
  1096. var
  1097.   i:     Integer;
  1098.   Query: TSQLiteQuery;
  1099. begin
  1100.   inherited Create;
  1101.  
  1102.   Database := ADatabase;
  1103.  
  1104.   Database.CriticalSection.Enter;
  1105.  
  1106.   try
  1107.     Query := Database.Prepare(SQL);
  1108.     if Query = nil then exit;
  1109.     try
  1110.       while sqlite3_step(Query) = SQLITE_ROW do
  1111.       begin
  1112.         if length(Table) = 0 then
  1113.         begin
  1114.           SetLength(ColumnNames, sqlite3_column_count(Query));
  1115.  
  1116.           for i := 0 to length(ColumnNames) - 1 do
  1117.             ColumnNames[i] := lower(sqlite3_column_name(Query, i));
  1118.         end;{if length(Table) = 0}
  1119.  
  1120.         SetLength(Table, length(Table) + 1);
  1121.         SetLength(Table[high(Table)], length(ColumnNames));
  1122.  
  1123.         for i := 0 to length(ColumnNames) - 1 do
  1124.           with Table[high(Table)][i] do
  1125.           begin
  1126.             DataType := sqlite3_column_type(Query, i);
  1127.  
  1128.             case DataType of
  1129.               SQLITE_INTEGER:
  1130.               begin
  1131.                 DataInt := sqlite3_column_int(Query, i);
  1132.                 DataStr := Str(DataInt);
  1133.               end;{SQLITE_INTEGER:}
  1134.  
  1135.               SQLITE_TEXT:
  1136.               begin
  1137.                 DataStr := sqlite3_column_text(Query, i);
  1138.                 DataInt := Int(DataStr);
  1139.               end;{SQLITE_TEXT:}
  1140.             else
  1141.               DataStr := '';
  1142.               DataInt := 0;
  1143.             end;{case DataType}
  1144.           end;{with Table}
  1145.       end;{while sqlite3_step}
  1146.     finally
  1147.       Database.Finalize(Query);
  1148.     end;{try...finally}
  1149.   finally
  1150.     Database.CriticalSection.Leave;
  1151.   end;{try...finally}
  1152. end;{TDatabase.TTable.Create}
  1153.  
  1154. destructor TDatabase.TTable.Destroy;
  1155. begin
  1156.   Database.CriticalSection.Leave;
  1157.  
  1158.   inherited;
  1159. end;{TDatabase.TTable.Destroy}
  1160.  
  1161. function TDatabase.TTable.Empty: Boolean;
  1162. begin
  1163.   Result := length(Table) = 0;
  1164. end;{TDatabase.Empty}
  1165.  
  1166. function TDatabase.TTable.Column(Name: AnsiString): Integer;
  1167. var
  1168.   i: Integer;
  1169. begin
  1170.   Name := lower(Name);
  1171.  
  1172.   for i := 0 to length(ColumnNames) - 1 do
  1173.     if Name = ColumnNames[i] then exit(i);
  1174.  
  1175.   Result := -1;
  1176. end;{TDatabase.TTable.Column}
  1177.  
  1178. function TDatabase.TTable.Value(Name: AnsiString; Row: Integer = 0; Default: AnsiString = ''): AnsiString;
  1179. var
  1180.   i: Integer;
  1181. begin
  1182.   i := Column(Name);
  1183.   if i = -1 then exit(Default);
  1184.  
  1185.   Result := Table[Row][i].DataStr;
  1186. end;{TDatabase.TTable.Value(AnsiString}
  1187.  
  1188. function TDatabase.TTable.Value(Name: AnsiString; Row: Integer = 0; Default: Integer = 0): Integer;
  1189. var
  1190.   i: Integer;
  1191. begin
  1192.   i := Column(Name);
  1193.   if i = -1 then exit(Default);
  1194.  
  1195.   Result := Table[Row][i].DataInt;
  1196. end;{TDatabase.TTable.Value(Integer}
  1197.  
  1198. constructor TDatabase.Create(AFileName: AnsiString);
  1199. begin
  1200.   inherited Create;
  1201.  
  1202.   CriticalSection.Create;
  1203.  
  1204.   FileName := AFileName;
  1205.  
  1206.   if sqlite3_open(PAnsiChar(FileName), DB) <> SQLITE_OK then
  1207.     Error(['Failed to open database "', FileName, '"']);
  1208. end;{TDatabase.Create}
  1209.  
  1210. destructor TDatabase.Destroy;
  1211. begin
  1212.   if DB <> nil then
  1213.   begin
  1214.     sqlite3_close(DB);
  1215.     DB := nil;
  1216.   end;{if DB <> nil}
  1217.  
  1218.   CriticalSection.Free;
  1219.  
  1220.   inherited;
  1221. end;{TDatabase.Destroy}
  1222.  
  1223. function TDatabase.Prepare(SQL: AnsiString): TSQLiteQuery;
  1224. var
  1225.   NextQuery: PAnsiChar;
  1226. begin
  1227.   if DB = nil then exit(nil);
  1228.  
  1229. {$IFDEF LOG_SQL}
  1230.   Server.Log(['Database (', FileName, ') ', SQL]);
  1231. {$ENDIF LOG_SQL}
  1232.  
  1233.   if sqlite3_prepare(DB, PAnsiChar(SQL), -1, Result, NextQuery) <> SQLITE_OK then
  1234.     if Result <> nil then
  1235.       Finalize(Result);
  1236. end;{TDatabase.Prepare}
  1237.  
  1238. procedure TDatabase.Finalize(var Query: TSQLiteQuery);
  1239. begin
  1240.   if Query = nil then exit;
  1241.  
  1242.   sqlite3_finalize(Query);
  1243.   Query := nil;
  1244. end;{TDatabase.Finalize}
  1245.  
  1246. function TDatabase.Query(SQL: AnsiString): Boolean;
  1247. var
  1248.   Query: TSQLiteQuery;
  1249. begin
  1250.   CriticalSection.Enter;
  1251.   try
  1252.     Query := Prepare(SQL);
  1253.     if Query = nil then exit(False);
  1254.  
  1255.     Result := sqlite3_step(Query) = SQLITE_DONE;
  1256.   finally
  1257.     Finalize(Query);
  1258.  
  1259.     CriticalSection.Leave;
  1260.   end;{try...finally}
  1261. end;{TDatabase.Query}
  1262.  
  1263. function TDatabase.QueryTable(SQL: AnsiString): TTable;
  1264. begin
  1265.   Result := TTable.Create(Self, SQL);
  1266. end;{TDatabase.QueryTable}
  1267.  
  1268. function TDatabase.TableExists(Name: AnsiString): Boolean;
  1269. begin
  1270.   with QueryTable('SELECT `sql` FROM `sqlite_master` WHERE `type` = "table" AND `name` = "' + Name + '";') do try
  1271.     Result := not Empty;
  1272.   finally
  1273.     Free;
  1274.   end;{with QueryTable..}
  1275. end;{TDatabase.TableExists}
  1276.  
  1277. constructor TINIFile.Create(AFileName: AnsiString);
  1278. begin
  1279.   inherited Create;
  1280.  
  1281.   FileName := AFileName;
  1282.  
  1283.   CriticalSection.Create;
  1284. end;{TINIFile.Create}
  1285.  
  1286. destructor TINIFile.Destroy;
  1287. begin
  1288.   CriticalSection.Free;
  1289.  
  1290.   inherited;
  1291. end;{TINIFile.Destroy}
  1292.  
  1293. function TINIFile.Read(Section, Key: AnsiString; Default: AnsiString = ''): AnsiString;
  1294. begin
  1295.   CriticalSection.Enter;
  1296.  
  1297.   try
  1298.     SetLength(Result, 256);
  1299.     SetLength(Result, GetPrivateProfileStringA(PAnsiChar(Section), PAnsiChar(Key), PAnsiChar(Default), PAnsiChar(Result), length(Result), PAnsiChar(FileName)));
  1300.   finally
  1301.     CriticalSection.Leave;
  1302.   end;{try...finally}
  1303.  
  1304. {$IFDEF LOG_CONFIG}
  1305.   if (length(Result) > 0) and (Lower(Result) <> Lower(Default)) then Server.Log(['Configuration (', FileName, ') [', Section, '] ', Key ,'=', Result]);
  1306. {$ENDIF LOG_CONFIG}
  1307. end;{TINIFile.Read(String}
  1308.  
  1309. function TINIFile.Read(Section, Key: AnsiString; Default: Integer = 0): Integer;
  1310. begin
  1311.   Result := Int(Read(Section, Key, Str(Default)));
  1312. end;{TINIFile.Read(Integer}
  1313.  
  1314. function TINIFile.Read(Section, Key: AnsiString; Default: Boolean = False): Boolean;
  1315. begin
  1316.   Result := Bool(Read(Section, Key, Str(Default)));
  1317. end;{TINIFile.Read(Boolean}
  1318.  
  1319. constructor TArray<T>.Create;
  1320. begin
  1321.   inherited Create;
  1322.  
  1323.   Clear;
  1324. end;{TArray<T>.Create}
  1325.  
  1326. destructor TArray<T>.Destroy;
  1327. begin
  1328.   Clear;
  1329.  
  1330.   inherited;
  1331. end;{TArray<T>.Destroy}
  1332.  
  1333. function TArray<T>.Find(Item: T): Integer;
  1334. var
  1335.   i: Integer;
  1336. begin
  1337.   for i := 0 to high(Items) do
  1338.     if Items[i] = Item then exit(i);
  1339.  
  1340.   Result := -1;
  1341. end;{TArray<T>.Add}
  1342.  
  1343. function TArray<T>.Add(Item: T): Integer;
  1344. begin
  1345.   Result := Find(Item);
  1346.  
  1347.   if Result = -1 then
  1348.   begin
  1349.     SetLength(Items, length(Items) + 1);
  1350.     Result := high(Items);
  1351.     Items[Result] := Item;
  1352.   end;{if Result = -1}
  1353. end;{TArray<T>.Add}
  1354.  
  1355. function TArray<T>.Remove(Item: T): Integer;
  1356. begin
  1357.   Result := Find(Item);
  1358.   if Result = -1 then exit;
  1359.  
  1360.   if Result < high(Items) then
  1361.     move(Items[Result + 1], Items[Result], sizeof(T) * (length(Items) - 1));
  1362.  
  1363.   SetLength(Items, length(Items) - 1);
  1364. end;{TArray<T>.Remove}
  1365.  
  1366. procedure TArray<T>.Clear;
  1367. begin
  1368.   SetLength(Items, 0);
  1369. end;{TArray<T>.Clear}
  1370.  
  1371. {$I-}
  1372.  
  1373. function TStrings.Load(FileName: String): Boolean;
  1374. var
  1375.   f: TextFile;
  1376.   s: AnsiString;
  1377. begin
  1378.   SetLength(Items, 0);
  1379.  
  1380.   AssignFile(f, FileName);
  1381.   Result := True;
  1382.  
  1383.   try
  1384.     try
  1385.       Reset(f);
  1386.  
  1387.       while not eof(f) do
  1388.       begin
  1389.         Readln(f, s);
  1390.         s := Trim(s);
  1391.  
  1392.         if length(s) = 0 then continue;
  1393.  
  1394.         SetLength(Items, length(Items) + 1);
  1395.         Items[high(Items)] := s;
  1396.       end;{while}
  1397.     except
  1398.       Result := False;
  1399.     end;{try...except}
  1400.   finally
  1401.     Close(f);
  1402.   end;{try...finally}
  1403. end;{TStrings.Load}
  1404.  
  1405. function TStrings.Save(FileName: String): Boolean;
  1406. begin
  1407.   Result := False;
  1408. end;{TStrings.Save}
  1409.  
  1410. procedure TSHA256.Init;
  1411. begin
  1412.   Hash.A := $6a09e667;
  1413.   Hash.B := $bb67ae85;
  1414.   Hash.C := $3c6ef372;
  1415.   Hash.D := $a54ff53a;
  1416.   Hash.E := $510e527f;
  1417.   Hash.F := $9b05688c;
  1418.   Hash.G := $1f83d9ab;
  1419.   Hash.H := $5be0cd19;
  1420.  
  1421.   FillChar(Buffer, sizeof(Buffer), 0);
  1422.  
  1423.   Index := 0;
  1424.   MLen  := 0;
  1425. end;{TSHA256.Init}
  1426.  
  1427. procedure TSHA256.Compress;
  1428. var
  1429.   a, b, c, d, e, f, g, h: Cardinal;
  1430.   t1, t2: Cardinal;
  1431.   W: array[0..63] of Cardinal;
  1432.   i: longword;
  1433. begin
  1434.   Index:= 0;
  1435.  
  1436.   Move(Buffer,W,Sizeof(Buffer));
  1437.  
  1438.   a := Hash.A;
  1439.   b := Hash.B;
  1440.   c := Hash.C;
  1441.   d := Hash.D;
  1442.   e := Hash.E;
  1443.   f := Hash.F;
  1444.   g := Hash.G;
  1445.   h := Hash.H;
  1446.  
  1447.   for i:= 0 to 15 do
  1448.     W[i] := bswap(W[i]);
  1449.  
  1450.   for i:= 16 to 63 do
  1451.     W[i] := (((W[i - 2] shr 17) or (W[i - 2] shl 15)) xor ((W[i - 2] shr 19) or
  1452.             (W[i - 2] shl 13)) xor (W[i - 2] shr 10)) + W[i - 7] + (((W[i - 15]
  1453.             shr 7) or (W[i - 15] shl 25)) xor ((W[i - 15] shr 18) or (W[i - 15]
  1454.             shl 14)) xor (W[i - 15] shr 3)) + W[i - 16];
  1455.  
  1456.   t1 := h + (((e shr 6) or (e shl 26)) xor ((e shr 11) or (e shl 21)) xor ((e shr 25) or (e shl 7))) + ((e and f) xor (not e and g)) + $428a2f98 + W[0];  t2:= (((a shr 2) or (a shl 30)) xor ((a shr 13) or (a shl 19)) xor ((a shr 22) xor (a shl 10))) + ((a and b) xor (a and c) xor (b and c)); h := t1 + t2; d := d + t1;
  1457.   t1 := g + (((d shr 6) or (d shl 26)) xor ((d shr 11) or (d shl 21)) xor ((d shr 25) or (d shl 7))) + ((d and e) xor (not d and f)) + $71374491 + W[1];  t2:= (((h shr 2) or (h shl 30)) xor ((h shr 13) or (h shl 19)) xor ((h shr 22) xor (h shl 10))) + ((h and a) xor (h and b) xor (a and b)); g := t1 + t2; c := c + t1;
  1458.   t1 := f + (((c shr 6) or (c shl 26)) xor ((c shr 11) or (c shl 21)) xor ((c shr 25) or (c shl 7))) + ((c and d) xor (not c and e)) + $b5c0fbcf + W[2];  t2:= (((g shr 2) or (g shl 30)) xor ((g shr 13) or (g shl 19)) xor ((g shr 22) xor (g shl 10))) + ((g and h) xor (g and a) xor (h and a)); f := t1 + t2; b := b + t1;
  1459.   t1 := e + (((b shr 6) or (b shl 26)) xor ((b shr 11) or (b shl 21)) xor ((b shr 25) or (b shl 7))) + ((b and c) xor (not b and d)) + $e9b5dba5 + W[3];  t2:= (((f shr 2) or (f shl 30)) xor ((f shr 13) or (f shl 19)) xor ((f shr 22) xor (f shl 10))) + ((f and g) xor (f and h) xor (g and h)); e := t1 + t2; a := a + t1;
  1460.   t1 := d + (((a shr 6) or (a shl 26)) xor ((a shr 11) or (a shl 21)) xor ((a shr 25) or (a shl 7))) + ((a and b) xor (not a and c)) + $3956c25b + W[4];  t2:= (((e shr 2) or (e shl 30)) xor ((e shr 13) or (e shl 19)) xor ((e shr 22) xor (e shl 10))) + ((e and f) xor (e and g) xor (f and g)); d := t1 + t2; h := h + t1;
  1461.   t1 := c + (((h shr 6) or (h shl 26)) xor ((h shr 11) or (h shl 21)) xor ((h shr 25) or (h shl 7))) + ((h and a) xor (not h and b)) + $59f111f1 + W[5];  t2:= (((d shr 2) or (d shl 30)) xor ((d shr 13) or (d shl 19)) xor ((d shr 22) xor (d shl 10))) + ((d and e) xor (d and f) xor (e and f)); c := t1 + t2; g := g + t1;
  1462.   t1 := b + (((g shr 6) or (g shl 26)) xor ((g shr 11) or (g shl 21)) xor ((g shr 25) or (g shl 7))) + ((g and h) xor (not g and a)) + $923f82a4 + W[6];  t2:= (((c shr 2) or (c shl 30)) xor ((c shr 13) or (c shl 19)) xor ((c shr 22) xor (c shl 10))) + ((c and d) xor (c and e) xor (d and e)); b := t1 + t2; f := f + t1;
  1463.   t1 := a + (((f shr 6) or (f shl 26)) xor ((f shr 11) or (f shl 21)) xor ((f shr 25) or (f shl 7))) + ((f and g) xor (not f and h)) + $ab1c5ed5 + W[7];  t2:= (((b shr 2) or (b shl 30)) xor ((b shr 13) or (b shl 19)) xor ((b shr 22) xor (b shl 10))) + ((b and c) xor (b and d) xor (c and d)); a := t1 + t2; e := e + t1;
  1464.   t1 := h + (((e shr 6) or (e shl 26)) xor ((e shr 11) or (e shl 21)) xor ((e shr 25) or (e shl 7))) + ((e and f) xor (not e and g)) + $d807aa98 + W[8];  t2:= (((a shr 2) or (a shl 30)) xor ((a shr 13) or (a shl 19)) xor ((a shr 22) xor (a shl 10))) + ((a and b) xor (a and c) xor (b and c)); h := t1 + t2; d := d + t1;
  1465.   t1 := g + (((d shr 6) or (d shl 26)) xor ((d shr 11) or (d shl 21)) xor ((d shr 25) or (d shl 7))) + ((d and e) xor (not d and f)) + $12835b01 + W[9];  t2:= (((h shr 2) or (h shl 30)) xor ((h shr 13) or (h shl 19)) xor ((h shr 22) xor (h shl 10))) + ((h and a) xor (h and b) xor (a and b)); g := t1 + t2; c := c + t1;
  1466.   t1 := f + (((c shr 6) or (c shl 26)) xor ((c shr 11) or (c shl 21)) xor ((c shr 25) or (c shl 7))) + ((c and d) xor (not c and e)) + $243185be + W[10]; t2:= (((g shr 2) or (g shl 30)) xor ((g shr 13) or (g shl 19)) xor ((g shr 22) xor (g shl 10))) + ((g and h) xor (g and a) xor (h and a)); f := t1 + t2; b := b + t1;
  1467.   t1 := e + (((b shr 6) or (b shl 26)) xor ((b shr 11) or (b shl 21)) xor ((b shr 25) or (b shl 7))) + ((b and c) xor (not b and d)) + $550c7dc3 + W[11]; t2:= (((f shr 2) or (f shl 30)) xor ((f shr 13) or (f shl 19)) xor ((f shr 22) xor (f shl 10))) + ((f and g) xor (f and h) xor (g and h)); e := t1 + t2; a := a + t1;
  1468.   t1 := d + (((a shr 6) or (a shl 26)) xor ((a shr 11) or (a shl 21)) xor ((a shr 25) or (a shl 7))) + ((a and b) xor (not a and c)) + $72be5d74 + W[12]; t2:= (((e shr 2) or (e shl 30)) xor ((e shr 13) or (e shl 19)) xor ((e shr 22) xor (e shl 10))) + ((e and f) xor (e and g) xor (f and g)); d := t1 + t2; h := h + t1;
  1469.   t1 := c + (((h shr 6) or (h shl 26)) xor ((h shr 11) or (h shl 21)) xor ((h shr 25) or (h shl 7))) + ((h and a) xor (not h and b)) + $80deb1fe + W[13]; t2:= (((d shr 2) or (d shl 30)) xor ((d shr 13) or (d shl 19)) xor ((d shr 22) xor (d shl 10))) + ((d and e) xor (d and f) xor (e and f)); c := t1 + t2; g := g + t1;
  1470.   t1 := b + (((g shr 6) or (g shl 26)) xor ((g shr 11) or (g shl 21)) xor ((g shr 25) or (g shl 7))) + ((g and h) xor (not g and a)) + $9bdc06a7 + W[14]; t2:= (((c shr 2) or (c shl 30)) xor ((c shr 13) or (c shl 19)) xor ((c shr 22) xor (c shl 10))) + ((c and d) xor (c and e) xor (d and e)); b := t1 + t2; f := f + t1;
  1471.   t1 := a + (((f shr 6) or (f shl 26)) xor ((f shr 11) or (f shl 21)) xor ((f shr 25) or (f shl 7))) + ((f and g) xor (not f and h)) + $c19bf174 + W[15]; t2:= (((b shr 2) or (b shl 30)) xor ((b shr 13) or (b shl 19)) xor ((b shr 22) xor (b shl 10))) + ((b and c) xor (b and d) xor (c and d)); a := t1 + t2; e := e + t1;
  1472.   t1 := h + (((e shr 6) or (e shl 26)) xor ((e shr 11) or (e shl 21)) xor ((e shr 25) or (e shl 7))) + ((e and f) xor (not e and g)) + $e49b69c1 + W[16]; t2:= (((a shr 2) or (a shl 30)) xor ((a shr 13) or (a shl 19)) xor ((a shr 22) xor (a shl 10))) + ((a and b) xor (a and c) xor (b and c)); h := t1 + t2; d := d + t1;
  1473.   t1 := g + (((d shr 6) or (d shl 26)) xor ((d shr 11) or (d shl 21)) xor ((d shr 25) or (d shl 7))) + ((d and e) xor (not d and f)) + $efbe4786 + W[17]; t2:= (((h shr 2) or (h shl 30)) xor ((h shr 13) or (h shl 19)) xor ((h shr 22) xor (h shl 10))) + ((h and a) xor (h and b) xor (a and b)); g := t1 + t2; c := c + t1;
  1474.   t1 := f + (((c shr 6) or (c shl 26)) xor ((c shr 11) or (c shl 21)) xor ((c shr 25) or (c shl 7))) + ((c and d) xor (not c and e)) + $0fc19dc6 + W[18]; t2:= (((g shr 2) or (g shl 30)) xor ((g shr 13) or (g shl 19)) xor ((g shr 22) xor (g shl 10))) + ((g and h) xor (g and a) xor (h and a)); f := t1 + t2; b := b + t1;
  1475.   t1 := e + (((b shr 6) or (b shl 26)) xor ((b shr 11) or (b shl 21)) xor ((b shr 25) or (b shl 7))) + ((b and c) xor (not b and d)) + $240ca1cc + W[19]; t2:= (((f shr 2) or (f shl 30)) xor ((f shr 13) or (f shl 19)) xor ((f shr 22) xor (f shl 10))) + ((f and g) xor (f and h) xor (g and h)); e := t1 + t2; a := a + t1;
  1476.   t1 := d + (((a shr 6) or (a shl 26)) xor ((a shr 11) or (a shl 21)) xor ((a shr 25) or (a shl 7))) + ((a and b) xor (not a and c)) + $2de92c6f + W[20]; t2:= (((e shr 2) or (e shl 30)) xor ((e shr 13) or (e shl 19)) xor ((e shr 22) xor (e shl 10))) + ((e and f) xor (e and g) xor (f and g)); d := t1 + t2; h := h + t1;
  1477.   t1 := c + (((h shr 6) or (h shl 26)) xor ((h shr 11) or (h shl 21)) xor ((h shr 25) or (h shl 7))) + ((h and a) xor (not h and b)) + $4a7484aa + W[21]; t2:= (((d shr 2) or (d shl 30)) xor ((d shr 13) or (d shl 19)) xor ((d shr 22) xor (d shl 10))) + ((d and e) xor (d and f) xor (e and f)); c := t1 + t2; g := g + t1;
  1478.   t1 := b + (((g shr 6) or (g shl 26)) xor ((g shr 11) or (g shl 21)) xor ((g shr 25) or (g shl 7))) + ((g and h) xor (not g and a)) + $5cb0a9dc + W[22]; t2:= (((c shr 2) or (c shl 30)) xor ((c shr 13) or (c shl 19)) xor ((c shr 22) xor (c shl 10))) + ((c and d) xor (c and e) xor (d and e)); b := t1 + t2; f := f + t1;
  1479.   t1 := a + (((f shr 6) or (f shl 26)) xor ((f shr 11) or (f shl 21)) xor ((f shr 25) or (f shl 7))) + ((f and g) xor (not f and h)) + $76f988da + W[23]; t2:= (((b shr 2) or (b shl 30)) xor ((b shr 13) or (b shl 19)) xor ((b shr 22) xor (b shl 10))) + ((b and c) xor (b and d) xor (c and d)); a := t1 + t2; e := e + t1;
  1480.   t1 := h + (((e shr 6) or (e shl 26)) xor ((e shr 11) or (e shl 21)) xor ((e shr 25) or (e shl 7))) + ((e and f) xor (not e and g)) + $983e5152 + W[24]; t2:= (((a shr 2) or (a shl 30)) xor ((a shr 13) or (a shl 19)) xor ((a shr 22) xor (a shl 10))) + ((a and b) xor (a and c) xor (b and c)); h := t1 + t2; d := d + t1;
  1481.   t1 := g + (((d shr 6) or (d shl 26)) xor ((d shr 11) or (d shl 21)) xor ((d shr 25) or (d shl 7))) + ((d and e) xor (not d and f)) + $a831c66d + W[25]; t2:= (((h shr 2) or (h shl 30)) xor ((h shr 13) or (h shl 19)) xor ((h shr 22) xor (h shl 10))) + ((h and a) xor (h and b) xor (a and b)); g := t1 + t2; c := c + t1;
  1482.   t1 := f + (((c shr 6) or (c shl 26)) xor ((c shr 11) or (c shl 21)) xor ((c shr 25) or (c shl 7))) + ((c and d) xor (not c and e)) + $b00327c8 + W[26]; t2:= (((g shr 2) or (g shl 30)) xor ((g shr 13) or (g shl 19)) xor ((g shr 22) xor (g shl 10))) + ((g and h) xor (g and a) xor (h and a)); f := t1 + t2; b := b + t1;
  1483.   t1 := e + (((b shr 6) or (b shl 26)) xor ((b shr 11) or (b shl 21)) xor ((b shr 25) or (b shl 7))) + ((b and c) xor (not b and d)) + $bf597fc7 + W[27]; t2:= (((f shr 2) or (f shl 30)) xor ((f shr 13) or (f shl 19)) xor ((f shr 22) xor (f shl 10))) + ((f and g) xor (f and h) xor (g and h)); e := t1 + t2; a := a + t1;
  1484.   t1 := d + (((a shr 6) or (a shl 26)) xor ((a shr 11) or (a shl 21)) xor ((a shr 25) or (a shl 7))) + ((a and b) xor (not a and c)) + $c6e00bf3 + W[28]; t2:= (((e shr 2) or (e shl 30)) xor ((e shr 13) or (e shl 19)) xor ((e shr 22) xor (e shl 10))) + ((e and f) xor (e and g) xor (f and g)); d := t1 + t2; h := h + t1;
  1485.   t1 := c + (((h shr 6) or (h shl 26)) xor ((h shr 11) or (h shl 21)) xor ((h shr 25) or (h shl 7))) + ((h and a) xor (not h and b)) + $d5a79147 + W[29]; t2:= (((d shr 2) or (d shl 30)) xor ((d shr 13) or (d shl 19)) xor ((d shr 22) xor (d shl 10))) + ((d and e) xor (d and f) xor (e and f)); c := t1 + t2; g := g + t1;
  1486.   t1 := b + (((g shr 6) or (g shl 26)) xor ((g shr 11) or (g shl 21)) xor ((g shr 25) or (g shl 7))) + ((g and h) xor (not g and a)) + $06ca6351 + W[30]; t2:= (((c shr 2) or (c shl 30)) xor ((c shr 13) or (c shl 19)) xor ((c shr 22) xor (c shl 10))) + ((c and d) xor (c and e) xor (d and e)); b := t1 + t2; f := f + t1;
  1487.   t1 := a + (((f shr 6) or (f shl 26)) xor ((f shr 11) or (f shl 21)) xor ((f shr 25) or (f shl 7))) + ((f and g) xor (not f and h)) + $14292967 + W[31]; t2:= (((b shr 2) or (b shl 30)) xor ((b shr 13) or (b shl 19)) xor ((b shr 22) xor (b shl 10))) + ((b and c) xor (b and d) xor (c and d)); a := t1 + t2; e := e + t1;
  1488.   t1 := h + (((e shr 6) or (e shl 26)) xor ((e shr 11) or (e shl 21)) xor ((e shr 25) or (e shl 7))) + ((e and f) xor (not e and g)) + $27b70a85 + W[32]; t2:= (((a shr 2) or (a shl 30)) xor ((a shr 13) or (a shl 19)) xor ((a shr 22) xor (a shl 10))) + ((a and b) xor (a and c) xor (b and c)); h := t1 + t2; d := d + t1;
  1489.   t1 := g + (((d shr 6) or (d shl 26)) xor ((d shr 11) or (d shl 21)) xor ((d shr 25) or (d shl 7))) + ((d and e) xor (not d and f)) + $2e1b2138 + W[33]; t2:= (((h shr 2) or (h shl 30)) xor ((h shr 13) or (h shl 19)) xor ((h shr 22) xor (h shl 10))) + ((h and a) xor (h and b) xor (a and b)); g := t1 + t2; c := c + t1;
  1490.   t1 := f + (((c shr 6) or (c shl 26)) xor ((c shr 11) or (c shl 21)) xor ((c shr 25) or (c shl 7))) + ((c and d) xor (not c and e)) + $4d2c6dfc + W[34]; t2:= (((g shr 2) or (g shl 30)) xor ((g shr 13) or (g shl 19)) xor ((g shr 22) xor (g shl 10))) + ((g and h) xor (g and a) xor (h and a)); f := t1 + t2; b := b + t1;
  1491.   t1 := e + (((b shr 6) or (b shl 26)) xor ((b shr 11) or (b shl 21)) xor ((b shr 25) or (b shl 7))) + ((b and c) xor (not b and d)) + $53380d13 + W[35]; t2:= (((f shr 2) or (f shl 30)) xor ((f shr 13) or (f shl 19)) xor ((f shr 22) xor (f shl 10))) + ((f and g) xor (f and h) xor (g and h)); e := t1 + t2; a := a + t1;
  1492.   t1 := d + (((a shr 6) or (a shl 26)) xor ((a shr 11) or (a shl 21)) xor ((a shr 25) or (a shl 7))) + ((a and b) xor (not a and c)) + $650a7354 + W[36]; t2:= (((e shr 2) or (e shl 30)) xor ((e shr 13) or (e shl 19)) xor ((e shr 22) xor (e shl 10))) + ((e and f) xor (e and g) xor (f and g)); d := t1 + t2; h := h + t1;
  1493.   t1 := c + (((h shr 6) or (h shl 26)) xor ((h shr 11) or (h shl 21)) xor ((h shr 25) or (h shl 7))) + ((h and a) xor (not h and b)) + $766a0abb + W[37]; t2:= (((d shr 2) or (d shl 30)) xor ((d shr 13) or (d shl 19)) xor ((d shr 22) xor (d shl 10))) + ((d and e) xor (d and f) xor (e and f)); c := t1 + t2; g := g + t1;
  1494.   t1 := b + (((g shr 6) or (g shl 26)) xor ((g shr 11) or (g shl 21)) xor ((g shr 25) or (g shl 7))) + ((g and h) xor (not g and a)) + $81c2c92e + W[38]; t2:= (((c shr 2) or (c shl 30)) xor ((c shr 13) or (c shl 19)) xor ((c shr 22) xor (c shl 10))) + ((c and d) xor (c and e) xor (d and e)); b := t1 + t2; f := f + t1;
  1495.   t1 := a + (((f shr 6) or (f shl 26)) xor ((f shr 11) or (f shl 21)) xor ((f shr 25) or (f shl 7))) + ((f and g) xor (not f and h)) + $92722c85 + W[39]; t2:= (((b shr 2) or (b shl 30)) xor ((b shr 13) or (b shl 19)) xor ((b shr 22) xor (b shl 10))) + ((b and c) xor (b and d) xor (c and d)); a := t1 + t2; e := e + t1;
  1496.   t1 := h + (((e shr 6) or (e shl 26)) xor ((e shr 11) or (e shl 21)) xor ((e shr 25) or (e shl 7))) + ((e and f) xor (not e and g)) + $a2bfe8a1 + W[40]; t2:= (((a shr 2) or (a shl 30)) xor ((a shr 13) or (a shl 19)) xor ((a shr 22) xor (a shl 10))) + ((a and b) xor (a and c) xor (b and c)); h := t1 + t2; d := d + t1;
  1497.   t1 := g + (((d shr 6) or (d shl 26)) xor ((d shr 11) or (d shl 21)) xor ((d shr 25) or (d shl 7))) + ((d and e) xor (not d and f)) + $a81a664b + W[41]; t2:= (((h shr 2) or (h shl 30)) xor ((h shr 13) or (h shl 19)) xor ((h shr 22) xor (h shl 10))) + ((h and a) xor (h and b) xor (a and b)); g := t1 + t2; c := c + t1;
  1498.   t1 := f + (((c shr 6) or (c shl 26)) xor ((c shr 11) or (c shl 21)) xor ((c shr 25) or (c shl 7))) + ((c and d) xor (not c and e)) + $c24b8b70 + W[42]; t2:= (((g shr 2) or (g shl 30)) xor ((g shr 13) or (g shl 19)) xor ((g shr 22) xor (g shl 10))) + ((g and h) xor (g and a) xor (h and a)); f := t1 + t2; b := b + t1;
  1499.   t1 := e + (((b shr 6) or (b shl 26)) xor ((b shr 11) or (b shl 21)) xor ((b shr 25) or (b shl 7))) + ((b and c) xor (not b and d)) + $c76c51a3 + W[43]; t2:= (((f shr 2) or (f shl 30)) xor ((f shr 13) or (f shl 19)) xor ((f shr 22) xor (f shl 10))) + ((f and g) xor (f and h) xor (g and h)); e := t1 + t2; a := a + t1;
  1500.   t1 := d + (((a shr 6) or (a shl 26)) xor ((a shr 11) or (a shl 21)) xor ((a shr 25) or (a shl 7))) + ((a and b) xor (not a and c)) + $d192e819 + W[44]; t2:= (((e shr 2) or (e shl 30)) xor ((e shr 13) or (e shl 19)) xor ((e shr 22) xor (e shl 10))) + ((e and f) xor (e and g) xor (f and g)); d := t1 + t2; h := h + t1;
  1501.   t1 := c + (((h shr 6) or (h shl 26)) xor ((h shr 11) or (h shl 21)) xor ((h shr 25) or (h shl 7))) + ((h and a) xor (not h and b)) + $d6990624 + W[45]; t2:= (((d shr 2) or (d shl 30)) xor ((d shr 13) or (d shl 19)) xor ((d shr 22) xor (d shl 10))) + ((d and e) xor (d and f) xor (e and f)); c := t1 + t2; g := g + t1;
  1502.   t1 := b + (((g shr 6) or (g shl 26)) xor ((g shr 11) or (g shl 21)) xor ((g shr 25) or (g shl 7))) + ((g and h) xor (not g and a)) + $f40e3585 + W[46]; t2:= (((c shr 2) or (c shl 30)) xor ((c shr 13) or (c shl 19)) xor ((c shr 22) xor (c shl 10))) + ((c and d) xor (c and e) xor (d and e)); b := t1 + t2; f := f + t1;
  1503.   t1 := a + (((f shr 6) or (f shl 26)) xor ((f shr 11) or (f shl 21)) xor ((f shr 25) or (f shl 7))) + ((f and g) xor (not f and h)) + $106aa070 + W[47]; t2:= (((b shr 2) or (b shl 30)) xor ((b shr 13) or (b shl 19)) xor ((b shr 22) xor (b shl 10))) + ((b and c) xor (b and d) xor (c and d)); a := t1 + t2; e := e + t1;
  1504.   t1 := h + (((e shr 6) or (e shl 26)) xor ((e shr 11) or (e shl 21)) xor ((e shr 25) or (e shl 7))) + ((e and f) xor (not e and g)) + $19a4c116 + W[48]; t2:= (((a shr 2) or (a shl 30)) xor ((a shr 13) or (a shl 19)) xor ((a shr 22) xor (a shl 10))) + ((a and b) xor (a and c) xor (b and c)); h := t1 + t2; d := d + t1;
  1505.   t1 := g + (((d shr 6) or (d shl 26)) xor ((d shr 11) or (d shl 21)) xor ((d shr 25) or (d shl 7))) + ((d and e) xor (not d and f)) + $1e376c08 + W[49]; t2:= (((h shr 2) or (h shl 30)) xor ((h shr 13) or (h shl 19)) xor ((h shr 22) xor (h shl 10))) + ((h and a) xor (h and b) xor (a and b)); g := t1 + t2; c := c + t1;
  1506.   t1 := f + (((c shr 6) or (c shl 26)) xor ((c shr 11) or (c shl 21)) xor ((c shr 25) or (c shl 7))) + ((c and d) xor (not c and e)) + $2748774c + W[50]; t2:= (((g shr 2) or (g shl 30)) xor ((g shr 13) or (g shl 19)) xor ((g shr 22) xor (g shl 10))) + ((g and h) xor (g and a) xor (h and a)); f := t1 + t2; b := b + t1;
  1507.   t1 := e + (((b shr 6) or (b shl 26)) xor ((b shr 11) or (b shl 21)) xor ((b shr 25) or (b shl 7))) + ((b and c) xor (not b and d)) + $34b0bcb5 + W[51]; t2:= (((f shr 2) or (f shl 30)) xor ((f shr 13) or (f shl 19)) xor ((f shr 22) xor (f shl 10))) + ((f and g) xor (f and h) xor (g and h)); e := t1 + t2; a := a + t1;
  1508.   t1 := d + (((a shr 6) or (a shl 26)) xor ((a shr 11) or (a shl 21)) xor ((a shr 25) or (a shl 7))) + ((a and b) xor (not a and c)) + $391c0cb3 + W[52]; t2:= (((e shr 2) or (e shl 30)) xor ((e shr 13) or (e shl 19)) xor ((e shr 22) xor (e shl 10))) + ((e and f) xor (e and g) xor (f and g)); d := t1 + t2; h := h + t1;
  1509.   t1 := c + (((h shr 6) or (h shl 26)) xor ((h shr 11) or (h shl 21)) xor ((h shr 25) or (h shl 7))) + ((h and a) xor (not h and b)) + $4ed8aa4a + W[53]; t2:= (((d shr 2) or (d shl 30)) xor ((d shr 13) or (d shl 19)) xor ((d shr 22) xor (d shl 10))) + ((d and e) xor (d and f) xor (e and f)); c := t1 + t2; g := g + t1;
  1510.   t1 := b + (((g shr 6) or (g shl 26)) xor ((g shr 11) or (g shl 21)) xor ((g shr 25) or (g shl 7))) + ((g and h) xor (not g and a)) + $5b9cca4f + W[54]; t2:= (((c shr 2) or (c shl 30)) xor ((c shr 13) or (c shl 19)) xor ((c shr 22) xor (c shl 10))) + ((c and d) xor (c and e) xor (d and e)); b := t1 + t2; f := f + t1;
  1511.   t1 := a + (((f shr 6) or (f shl 26)) xor ((f shr 11) or (f shl 21)) xor ((f shr 25) or (f shl 7))) + ((f and g) xor (not f and h)) + $682e6ff3 + W[55]; t2:= (((b shr 2) or (b shl 30)) xor ((b shr 13) or (b shl 19)) xor ((b shr 22) xor (b shl 10))) + ((b and c) xor (b and d) xor (c and d)); a := t1 + t2; e := e + t1;
  1512.   t1 := h + (((e shr 6) or (e shl 26)) xor ((e shr 11) or (e shl 21)) xor ((e shr 25) or (e shl 7))) + ((e and f) xor (not e and g)) + $748f82ee + W[56]; t2:= (((a shr 2) or (a shl 30)) xor ((a shr 13) or (a shl 19)) xor ((a shr 22) xor (a shl 10))) + ((a and b) xor (a and c) xor (b and c)); h := t1 + t2; d := d + t1;
  1513.   t1 := g + (((d shr 6) or (d shl 26)) xor ((d shr 11) or (d shl 21)) xor ((d shr 25) or (d shl 7))) + ((d and e) xor (not d and f)) + $78a5636f + W[57]; t2:= (((h shr 2) or (h shl 30)) xor ((h shr 13) or (h shl 19)) xor ((h shr 22) xor (h shl 10))) + ((h and a) xor (h and b) xor (a and b)); g := t1 + t2; c := c + t1;
  1514.   t1 := f + (((c shr 6) or (c shl 26)) xor ((c shr 11) or (c shl 21)) xor ((c shr 25) or (c shl 7))) + ((c and d) xor (not c and e)) + $84c87814 + W[58]; t2:= (((g shr 2) or (g shl 30)) xor ((g shr 13) or (g shl 19)) xor ((g shr 22) xor (g shl 10))) + ((g and h) xor (g and a) xor (h and a)); f := t1 + t2; b := b + t1;
  1515.   t1 := e + (((b shr 6) or (b shl 26)) xor ((b shr 11) or (b shl 21)) xor ((b shr 25) or (b shl 7))) + ((b and c) xor (not b and d)) + $8cc70208 + W[59]; t2:= (((f shr 2) or (f shl 30)) xor ((f shr 13) or (f shl 19)) xor ((f shr 22) xor (f shl 10))) + ((f and g) xor (f and h) xor (g and h)); e := t1 + t2; a := a + t1;
  1516.   t1 := d + (((a shr 6) or (a shl 26)) xor ((a shr 11) or (a shl 21)) xor ((a shr 25) or (a shl 7))) + ((a and b) xor (not a and c)) + $90befffa + W[60]; t2:= (((e shr 2) or (e shl 30)) xor ((e shr 13) or (e shl 19)) xor ((e shr 22) xor (e shl 10))) + ((e and f) xor (e and g) xor (f and g)); d := t1 + t2; h := h + t1;
  1517.   t1 := c + (((h shr 6) or (h shl 26)) xor ((h shr 11) or (h shl 21)) xor ((h shr 25) or (h shl 7))) + ((h and a) xor (not h and b)) + $a4506ceb + W[61]; t2:= (((d shr 2) or (d shl 30)) xor ((d shr 13) or (d shl 19)) xor ((d shr 22) xor (d shl 10))) + ((d and e) xor (d and f) xor (e and f)); c := t1 + t2; g := g + t1;
  1518.   t1 := b + (((g shr 6) or (g shl 26)) xor ((g shr 11) or (g shl 21)) xor ((g shr 25) or (g shl 7))) + ((g and h) xor (not g and a)) + $bef9a3f7 + W[62]; t2:= (((c shr 2) or (c shl 30)) xor ((c shr 13) or (c shl 19)) xor ((c shr 22) xor (c shl 10))) + ((c and d) xor (c and e) xor (d and e)); b := t1 + t2; f := f + t1;
  1519.   t1 := a + (((f shr 6) or (f shl 26)) xor ((f shr 11) or (f shl 21)) xor ((f shr 25) or (f shl 7))) + ((f and g) xor (not f and h)) + $c67178f2 + W[63]; t2:= (((b shr 2) or (b shl 30)) xor ((b shr 13) or (b shl 19)) xor ((b shr 22) xor (b shl 10))) + ((b and c) xor (b and d) xor (c and d)); a := t1 + t2; e := e + t1;
  1520.  
  1521.   inc(Hash.A, a);
  1522.   inc(Hash.B, b);
  1523.   inc(Hash.C, c);
  1524.   inc(Hash.D, d);
  1525.   inc(Hash.E, e);
  1526.   inc(Hash.F, f);
  1527.   inc(Hash.G, g);
  1528.   inc(Hash.H, h);
  1529.  
  1530.   FillChar(W,Sizeof(W),0);
  1531.   FillChar(Buffer,Sizeof(Buffer),0);
  1532. end;{TSHA256.Compress}
  1533.  
  1534. procedure TSHA256.Update(Data: Pointer; Len: Integer);
  1535. var
  1536.   i: Integer;
  1537. begin
  1538.   inc(MLen, Int64(Cardinal(Len) shl 3));
  1539.  
  1540.   while Len > 0 do
  1541.   begin
  1542.     i := 64 - Index;
  1543.  
  1544.     if i <= Len then
  1545.     begin
  1546.       move(Data^, Buffer[Index], i);
  1547.       dec(Len, i);
  1548.       inc(Integer(Data), i);
  1549.       Compress;
  1550.       Index := 0;
  1551.     end{if i <= Len}
  1552.     else
  1553.     begin
  1554.       move(Data^, Buffer[Index], Len);
  1555.       inc(Index, Len);
  1556.       break;
  1557.     end;{else}
  1558.   end;{while Len > 0}
  1559. end;{TSHA256.Update}
  1560.  
  1561. function TSHA256.Done: AnsiString;
  1562. const
  1563.   HexChar: array[0..15] of AnsiChar = '0123456789ABCDEF';
  1564. type
  1565.   TInt64 = packed record
  1566.     Lo, Hi: Cardinal;
  1567.   end;{TInt64}
  1568. var
  1569.   i:       Integer;
  1570.   PResult: PAnsiChar;
  1571.   Digest:  array[0..31] of Byte;
  1572. begin
  1573.   Buffer[Index] := $80;
  1574.  
  1575.   fillchar(Buffer[Index + 1], 63 - Index, 0);
  1576.  
  1577.   if Index >= 56 then
  1578.   begin
  1579.     Compress;
  1580.     fillchar(Buffer, 56, 0);
  1581.   end;{if Index >= 56}
  1582.  
  1583.   PInteger(@Buffer[56])^ := bswap(TInt64(MLen).Hi);
  1584.   PInteger(@Buffer[60])^ := bswap(TInt64(MLen).Lo);
  1585.  
  1586.   Compress;
  1587.  
  1588.   bswap256(@Hash, @Digest);
  1589.  
  1590.   Setlength(Result, sizeof(Digest) * 2);
  1591.   PResult := PAnsiChar(Result);
  1592.  
  1593.   for i := 0 to sizeof(Digest) - 1 do
  1594.   begin
  1595.     PResult[0] := HexChar[Digest[I] shr 4];
  1596.     PResult[1] := HexChar[Digest[I] and 15];
  1597.     inc(PResult,2);
  1598.   end;{for i}
  1599. end;{TSHA256.Done}
  1600.  
  1601. class function TSHA256.HashStr(S: AnsiString): AnsiString;
  1602. var
  1603.   SHA256: TSHA256;
  1604. begin
  1605.   SHA256.Init;
  1606.   SHA256.Update(PAnsiChar(S), length(S));
  1607.   Result := SHA256.Done;
  1608. end;{class)TSHA256.HashStr}
  1609.  
  1610. class constructor Server.Create;
  1611. const
  1612.   Banner = ' .       .       __  __  ___   __  _    _'#13#10' \`-"''"-''/      '+
  1613.     '(  \/  )(  _) /  \( \/\/ )'#13#10'  } o o {    -   )    (  ) _)( () )\    '+
  1614.     '/'#13#10' =.  Y  ,=      (_/\/\_)(___) \__/  \/\/'#13#10'   /-O-\  .'#13#10+
  1615.     '  /     \  )          Mini EO? WOW!'#13#10' (  )-(  )/ Created by Sordie o'+
  1616.     'ut of boredom'#13#10'  ""   ""';
  1617. var
  1618.   i:       Integer;
  1619.   WSAData: TWSAData;
  1620.   AddrIn:  TSockAddrIn;
  1621. begin
  1622.   Writeln(Banner);
  1623.   Writeln('Version ' + Version + '|' + Branch);
  1624.  
  1625.   CriticalSection.Create;
  1626.  
  1627.   Sessions := TArray<TSession>.Create;
  1628.  
  1629.   WSAStartup(MakeLong(2, 2), WSAData);
  1630.  
  1631.   Configuration := TINIFile.Create('.\MEOW.ini');
  1632.  
  1633.   Log(['Opening database...']);
  1634.   Database := TDatabase.Create(Configuration.Read('database', 'name', '.\MEOW.db'));
  1635.   //Database.Query('DROP TABLE `accounts`;');
  1636.  
  1637.   if not Database.TableExists('accounts') then
  1638.   begin
  1639.     Log(['Creating accounts database']);
  1640.  
  1641.     if not Database.Query('CREATE TABLE `accounts` (' +
  1642.         '`id` INTEGER PRIMARY KEY, ' +
  1643.         '`name` VARCHAR (' + Str(NameMax) + '), ' +
  1644.         '`banned` INTEGER, ' +
  1645.         '`password` VARCHAR (64), ' +
  1646.         '`usage` INTEGER, ' +
  1647.         '`state` INTEGER, ' +
  1648.         '`x` INTEGER, ' +
  1649.         '`y` INTEGER, ' +
  1650.         '`d` INTEGER, ' +
  1651.         '`s` INTEGER, ' +
  1652.         '`admin` INTEGER, ' +
  1653.         '`tag` VARCHAR (3), ' +
  1654.         '`sex` INTEGER, '  +
  1655.         '`hairstyle` INTEGER, ' +
  1656.         '`haircolour` INTEGER, ' +
  1657.         '`race` INTEGER, ' +
  1658.         '`boots` INTEGER, ' +
  1659.         '`armour` INTEGER, ' +
  1660.         '`hat` INTEGER, ' +
  1661.         '`shield` INTEGER, ' +
  1662.         '`weapon` INTEGER, ' +
  1663.         '`gold` INTEGER, ' +
  1664.         '`hp` INTEGER, ' +
  1665.         '`maxhp` INTEGER, ' +
  1666.         '`tp` INTEGER, ' +
  1667.         '`maxtp` INTEGER, ' +
  1668.         '`kills` INTEGER' +
  1669.       ');') then
  1670.       Error(['Failed to create table']);
  1671.   end;{if not Database.TableExists}
  1672.  
  1673.   if not Database.TableExists('banned') then
  1674.   begin
  1675.     Log(['Creating banned IP table']);
  1676.  
  1677.     if not Database.Query('CREATE TABLE `banned` (`ip` INTEGER PRIMARY KEY);') then
  1678.       Error(['Failed to create banned IP table']);
  1679.   end;{if not Database.TableExists}
  1680.  
  1681.   PacketQueue.Enabled := Configuration.Read('packetqueue', 'enabled', True);
  1682.   if PacketQueue.Enabled then
  1683.   begin
  1684.     PacketQueue.Size   := Configuration.Read('packetqueue', 'size',   10);
  1685.     PacketQueue.Walk   := Configuration.Read('packetqueue', 'walk',   500);
  1686.     PacketQueue.Attack := Configuration.Read('packetqueue', 'attack', 500);
  1687.   end;{if PacketQueue.Enabled}
  1688.  
  1689.   Log(['Creating socket...']);
  1690.   Socket := WinSock.socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
  1691.   if Socket = 0 then
  1692.     Error(['Failed to create socket']);
  1693.  
  1694.   Connection.Bind    := Configuration.Read('connection', 'bind',    '0.0.0.0');
  1695.   Connection.Port    := Configuration.Read('connection', 'port',    8078);
  1696.   Connection.Timeout := Configuration.Read('connection', 'timeout', 300000);
  1697.  
  1698.   Log(['Bind ', Connection.Bind, ':', Connection.Port]);
  1699.  
  1700.   FillChar(AddrIn, sizeof(AddrIn), 0);
  1701.   with AddrIn do
  1702.   begin
  1703.     sin_family      := AF_INET;
  1704.     sin_addr.S_addr := inet_addr(PAnsiChar(Connection.Bind));
  1705.     sin_port        := htons(Connection.Port);
  1706.   end;{with AddrIn}
  1707.   if bind(Socket, AddrIn, sizeof(AddrIn)) <> 0 then
  1708.     Error(['Failed to bind socket']);
  1709.  
  1710.   if listen(Socket, 0) <> 0 then
  1711.     Error(['Cannot listen on socket']);
  1712.  
  1713.   Log(['Creating game data...']);
  1714.  
  1715.   ItemData  := TItemData. Create({$IFDEF INTERNAL_PUB}'_internal_'{$ELSE}Configuration.Read('data', 'item',  '.\Items.eif')  {$ENDIF});
  1716.   NPCData   := TNPCData.  Create({$IFDEF INTERNAL_PUB}'_internal_'{$ELSE}Configuration.Read('data', 'npc',   '.\NPCs.enf')   {$ENDIF});
  1717.   SpellData := TSpellData.Create({$IFDEF INTERNAL_PUB}'_internal_'{$ELSE}Configuration.Read('data', 'spell', '.\Spells.esf') {$ENDIF});
  1718.   ClassData := TClassData.Create({$IFDEF INTERNAL_PUB}'_internal_'{$ELSE}Configuration.Read('data', 'class', '.\Classes.ecf'){$ENDIF});
  1719.   MapData   := TMapData.  Create(Configuration.Read('data', 'map', '.\00001.emf'));
  1720.  
  1721.   Connection.PerIP := Configuration.Read('connection', 'perip', 2);
  1722.  
  1723.   Defaults.X     := Configuration.Read('defaults', 'x',     10);
  1724.   Defaults.Y     := Configuration.Read('defaults', 'y',     10);
  1725.   Defaults.D     := Configuration.Read('defaults', 'd',     0);
  1726.   Defaults.Gold  := Configuration.Read('defaults', 'gold',  200);
  1727.   Defaults.HP    := Configuration.Read('defaults', 'hp',    10);
  1728.   Defaults.MaxHP := Configuration.Read('defaults', 'maxhp', 10);
  1729.   Defaults.TP    := Configuration.Read('defaults', 'tp',    10);
  1730.   Defaults.MaxTP := Configuration.Read('defaults', 'maxtp', 10);
  1731.  
  1732.   if Defaults.MaxHP < 1 then Defaults.MaxHP := 1;
  1733.  
  1734.   Admin.CommandChar := (Configuration.Read('admin', 'commandchar', '/') + '/')[1];
  1735.   Admin.EchoCommand :=  Configuration.Read('admin', 'echocommand', True);
  1736.  
  1737.   Admin.TagAdmin     := Configuration.Read('admin', 'tagadmin',     'ª');
  1738.   Admin.TagLocalhost := Configuration.Read('admin', 'taglocalhost', '¹');
  1739.  
  1740.   Admin.Level.Appearance  := Configuration.Read('admin', 'appearance',  0);
  1741.   Admin.Level.Item        := Configuration.Read('admin', 'item',        0);
  1742.   Admin.Level.Action      := Configuration.Read('admin', 'action',      1);
  1743.   Admin.Level.Maintenance := Configuration.Read('admin', 'maintenance', 4);
  1744.  
  1745.   for i := 0 to 6 do
  1746.     News[i] := Configuration.Read('news', Str(i), '');
  1747.  
  1748.   Unapproved.Load(String(Configuration.Read('data', 'unapproved', 'unapproved.txt')));
  1749.  
  1750.   Connection.BytesIn  := 0;
  1751.   Connection.BytesOut := 0;
  1752.  
  1753.   UpdateCaption;
  1754.  
  1755.   Log(['Starting server...']);
  1756.  
  1757.   try
  1758.     Main;
  1759.   except
  1760.     Log(['Server Exception']);
  1761.   end;{try...except}
  1762. end;{class)Server.Create}
  1763.  
  1764. class destructor Server.Destroy;
  1765. begin
  1766.   Log(['Shutting down server...']);
  1767.  
  1768.   if Socket <> 0 then
  1769.   begin
  1770.     closesocket(Socket);
  1771.     Socket := 0;
  1772.   end;{if Socket <> 0}
  1773.  
  1774.   Sessions.Free;
  1775.  
  1776.   ItemData.Free;
  1777.   NPCData.Free;
  1778.   SpellData.Free;
  1779.   ClassData.Free;
  1780.   MapData.Free;
  1781.  
  1782.   Configuration.Free;
  1783.   Database.Free;
  1784.  
  1785.   CriticalSection.Free;
  1786.   Readln;
  1787. end;{class)Server.Destroy}
  1788.  
  1789. class procedure Server.Main;
  1790. var
  1791.   i:        Integer;
  1792.   FDSet:    TFDSet;
  1793.   SockAddr: TSockAddr;
  1794.   InSocket: TSocket;
  1795.   Session:  TSession;
  1796. begin
  1797.   Log(['Server running']);
  1798.   repeat
  1799.     Sleep(1);
  1800.  
  1801.     FDSet.fd_count    := 1;
  1802.     FDSet.fd_array[0] := Socket;
  1803.  
  1804.     if select(0, @FDSet, nil, nil, nil) = 1 then
  1805.     begin
  1806.       i := sizeof(SockAddr);
  1807.       InSocket := accept(Socket, @SockAddr, @i);
  1808.       if InSocket = 0 then continue;
  1809.  
  1810.       if BannedIP(SockAddr.sin_addr.S_addr) then
  1811.       begin
  1812.         closesocket(InSocket);
  1813.         Log(['Denied connection from ' + AnsiString(inet_ntoa(SockAddr.sin_addr))]);
  1814.         continue;
  1815.       end;{if BannedIP}
  1816.  
  1817.       i := 0;
  1818.  
  1819.       CriticalSection.Enter;
  1820.       try
  1821.         for Session in Sessions.Items do
  1822.           if Session.IPInt = SockAddr.sin_addr.S_addr then
  1823.           begin
  1824.             inc(i);
  1825.             if i = Connection.PerIP then break;
  1826.           end;{if Session.IPInt}
  1827.       finally
  1828.         CriticalSection.Leave;
  1829.       end;{try...finally}
  1830.  
  1831.       if i = Connection.PerIP then
  1832.         closesocket(InSocket)
  1833.       else
  1834.         TSession.Create(InSocket, SockAddr);
  1835.     end;{if select}
  1836.   until Socket = 0;
  1837. end;{class)Server.Main}
  1838.  
  1839. class procedure Server.Log(Params: array of const; Prefix: AnsiString = '');
  1840. var
  1841.   i: Integer;
  1842. begin
  1843.   CriticalSection.Enter;
  1844.   try
  1845.     if length(Prefix) > 0 then
  1846.       Write(Prefix + ' ');
  1847.  
  1848.     for i := 0 to high(Params) do
  1849.       with TVarRec(Params[i]) do
  1850.         case VType of
  1851.           vtInteger:       Write(VInteger);
  1852.           vtBoolean:       Write(VBoolean);
  1853.           vtChar:          Write(VChar);
  1854.           vtWideChar:      Write(VWideChar);
  1855.           vtExtended:      Write(VExtended^);
  1856.           vtString:        Write(AnsiString(VString));
  1857.           vtPointer:       Write(Cardinal(VPointer));
  1858.           vtPChar:         Write(AnsiString(VPChar));
  1859.           vtObject:        Write(VObject.ClassName);
  1860.           vtClass:         Write(VClass.ClassName);
  1861.           vtPWideChar:     Write(WideString(VPWideChar));
  1862.           vtWideString:    Write(WideString(VWideString));
  1863.           vtInt64:         Write(VInt64^);
  1864.           vtUnicodeString: Write(String(VUnicodeString));
  1865.           vtAnsiString:    Write(AnsiString(VAnsiString));
  1866.         else
  1867.           Write('?(', VType, ')');
  1868.         end;{case VType}
  1869.   finally
  1870.     Writeln;
  1871.     CriticalSection.Leave;
  1872.   end;{try...finally}
  1873. end;{class)Server.Log}
  1874.  
  1875. class procedure Server.Send(var Packet: TPacket; Sender: TSession = nil; Ranged: Boolean = True);
  1876. var
  1877.   Session: TSession;
  1878. begin
  1879.   CriticalSection.Enter;
  1880.   try
  1881.     for Session in Sessions.Items do
  1882.       if (Session <> Sender) and Session.LoggedIn then
  1883.       begin
  1884.         if Ranged and (Sender <> nil) and
  1885.           ((Session.X < (Sender.X - ViewRange)) or (Session.X > (Sender.X + ViewRange)) or
  1886.            (Session.Y < (Sender.Y - ViewRange)) or (Session.Y > (Sender.Y + ViewRange))) then
  1887.           continue;
  1888.  
  1889.         Session.Send(Packet);
  1890.       end;{if (Session <> Sender)}
  1891.   finally
  1892.     CriticalSection.Leave;
  1893.   end;{try...finally}
  1894. end;{Server.Send}
  1895.  
  1896. class procedure Server.SendRanged(var Packet: TPacket; X, Y: Integer);
  1897. var
  1898.   Session: TSession;
  1899. begin
  1900.   CriticalSection.Enter;
  1901.   try
  1902.     for Session in Sessions.Items do
  1903.       if Session.LoggedIn and
  1904.         (Session.X > (X - ViewRange)) and (Session.X < (X + ViewRange)) and
  1905.         (Session.Y > (Y - ViewRange)) and (Session.Y < (Y + ViewRange)) then
  1906.           Session.Send(Packet);
  1907.   finally
  1908.     CriticalSection.Leave;
  1909.   end;{try...finally}
  1910. end;{class)Server.SendRanged}
  1911.  
  1912. class procedure Server.UpdateCaption;
  1913. begin
  1914.   CriticalSection.Section(procedure
  1915.   var
  1916.     NewCaption: AnsiString;
  1917.   begin
  1918.     NewCaption := 'MEOW - ' +
  1919.       Str(length(Sessions.Items)) + ' Connection(s) - ' +
  1920.       Scale(Connection.BytesIn)  + ' in / ' +
  1921.       Scale(Connection.BytesOut) + ' out';
  1922.  
  1923.     if NewCaption <> Caption then
  1924.     begin
  1925.       Caption := NewCaption;
  1926.       SetConsoleTitleA(PAnsiChar(Caption));
  1927.     end;{if NewCaption <> Caption}
  1928.   end);{CriticalSection.Section}
  1929. end;{class)Server.Update}
  1930.  
  1931. class function Server.GetSessionByID(ID: Cardinal): TSession;
  1932. var
  1933.   Session: TSession;
  1934. begin
  1935.   CriticalSection.Enter;
  1936.   try
  1937.     for Session in Sessions.Items do
  1938.       if Session.ID = ID then exit(Session);
  1939.  
  1940.     Result := nil;
  1941.   finally
  1942.     CriticalSection.Leave;
  1943.   end;{try...finally}
  1944. end;{class)Server.GetSessionByID}
  1945.  
  1946. class function Server.GetSessionByName(Name: AnsiString): TSession;
  1947. var
  1948.   Session: TSession;
  1949. begin
  1950.   Name := Lower(Name);
  1951.  
  1952.   CriticalSection.Enter;
  1953.   try
  1954.     for Session in Sessions.Items do
  1955.       if Session.Name = Name then exit(Session);
  1956.  
  1957.     Result := nil;
  1958.   finally
  1959.     CriticalSection.Leave;
  1960.   end;{try...finally}
  1961. end;{Server.GetSessionByName}
  1962.  
  1963. class procedure Server.Msg(Msg: AnsiString);
  1964. var
  1965.   Packet: TPacket;
  1966. begin
  1967.   if length(Msg) = 0 then exit;
  1968.  
  1969.   Packet.SetID(PacketFamilyTalk, PacketActionServer);
  1970.   Packet.AddString(Msg);
  1971.  
  1972.   Send(Packet);
  1973. end;{class)Server.Msg}
  1974.  
  1975. class procedure Server.AdminMsg(Msg: AnsiString; From: AnsiString = '[Server]');
  1976. var
  1977.   Packet:  TPacket;
  1978.   Session: TSession;
  1979. begin
  1980.   if length(Msg) = 0 then exit;
  1981.  
  1982.   Packet.SetID(PacketFamilyTalk, PacketActionAdmin);
  1983.   Packet.AddBreakString(From);
  1984.   Packet.AddBreakString(copy(Msg, 1, TextLength));
  1985.  
  1986.   Log([Msg], 'Admin');
  1987.  
  1988.   CriticalSection.Enter;
  1989.   try
  1990.     for Session in Sessions.Items do
  1991.       if Session.LoggedIn and (Session.Admin > 0) then
  1992.         Session.Send(Packet)
  1993.   finally
  1994.     CriticalSection.Leave;
  1995.   end;{try...finally}
  1996. end;{class)AdminMsg}
  1997.  
  1998. class procedure Server.Freeze(Exclude: TSession);
  1999. begin
  2000.   CriticalSection.Section(procedure
  2001.   var
  2002.     Session: TSession;
  2003.   begin
  2004.     for Session in Sessions.Items do
  2005.       if Session.LoggedIn and (Session <> Exclude) then
  2006.         Session.Freeze;
  2007.   end);{CriticalSection.Section}
  2008. end;{class)Server.Freeze}
  2009.  
  2010. class procedure Server.Unfreeze;
  2011. begin
  2012.   CriticalSection.Section(procedure
  2013.   var
  2014.     Session: TSession;
  2015.   begin
  2016.     for Session in Sessions.Items do
  2017.       if Session.LoggedIn then
  2018.         Session.Unfreeze;
  2019.   end);{CriticalSection.Section}
  2020. end;{class)Server.Unfreeze}
  2021.  
  2022. class procedure Server.Mute(Exclude: TSession);
  2023. begin
  2024.   CriticalSection.Section(procedure
  2025.   var
  2026.     Session: TSession;
  2027.     From:    AnsiString;
  2028.   begin
  2029.     if (Exclude = nil) or (length(Exclude.Name) = 0) then From := 'Server' else From := Exclude.Name;
  2030.  
  2031.     for Session in Sessions.Items do
  2032.       if Session.LoggedIn and (Session <> Exclude) then
  2033.         Session.Mute(From);
  2034.   end);{CriticalSection.Section}
  2035. end;{class)Server.Mute}
  2036.  
  2037. class procedure Server.Quake(Scale: Integer);
  2038. begin
  2039.   CriticalSection.Section(procedure
  2040.   var
  2041.     Session: TSession;
  2042.   begin
  2043.     for Session in Sessions.Items do
  2044.       if Session.LoggedIn then
  2045.         Session.Quake(Scale);
  2046.   end);{CriticalSection.Section}
  2047. end;{class)Server.Quake}
  2048.  
  2049. class procedure Server.Effect(EffectID, X, Y: Integer);
  2050. var
  2051.   Packet: TPacket;
  2052. begin
  2053.   Packet.SetID(PacketFamilyEffect, PacketActionAgree);
  2054.   Packet.AddInt1(X);
  2055.   Packet.AddInt1(Y);
  2056.   Packet.AddInt2(EffectID);
  2057.  
  2058.   SendRanged(Packet, X, Y);
  2059. end;{class)Server.Effect}
  2060.  
  2061. class procedure Server.Sound(SoundID: Integer);
  2062. begin
  2063.   CriticalSection.Section(procedure
  2064.   var
  2065.     Session: TSession;
  2066.   begin
  2067.     for Session in Sessions.Items do
  2068.       if Session.LoggedIn then
  2069.         Session.Sound(SoundID);
  2070.   end);{CriticalSection.Section}
  2071. end;{class)Server.Sound}
  2072.  
  2073. class procedure Server.SetMap(MapFile: AnsiString = '');
  2074. begin
  2075.   CriticalSection.Section(procedure
  2076.   var
  2077.     OldFile: AnsiString;
  2078.   begin
  2079.     OldFile := MapData.FileName;
  2080.  
  2081.     if length(MapFile) > 0 then
  2082.       MapData.FileName := MapFile + '.emf';
  2083.  
  2084.     if not MapData.Load then
  2085.     begin
  2086.       Log(['Failed to load map data ', MapFile]);
  2087.  
  2088.       MapData.FileName := OldFile;
  2089.       MapData.Load;
  2090.  
  2091.       exit;
  2092.     end;{if MapData.Load}
  2093.   end);{CriticalSection.Section}
  2094.  
  2095.   Mutate;
  2096. end;{Server.SetMap}
  2097.  
  2098. class procedure Server.Mutate;
  2099. begin
  2100.   CriticalSection.Section(procedure
  2101.   var
  2102.     Packet:  TPacket;
  2103.     Session: TSession;
  2104.   begin
  2105.     Packet.SetID(PacketFamilyRaw, PacketActionRaw);
  2106.     Packet.AddInt1(9);
  2107.     Packet.AddString(MapData.Data);
  2108.  
  2109.     for Session in Sessions.Items do
  2110.       if Session.LoggedIn then
  2111.       begin
  2112.         Session.Send(Packet, True);
  2113.         Session.RefreshAll;
  2114.       end;{if Session.LoggedIn}
  2115.   end);{CriticalSection.Section}
  2116. end;{class)Server.Mutate}
  2117.  
  2118. class procedure Server.OpenDoor(X, Y: Integer);
  2119. var
  2120.   Packet:  TPacket;
  2121. begin
  2122.   if (X < 0) or (X >= MapData.Width) or
  2123.      (Y < 0) or (Y >= MapData.Height) then exit;
  2124.  
  2125.   if not MapData.Tiles[Y, X].Warp.Enabled then exit;
  2126.  
  2127.   Packet.SetID(PacketFamilyDoor, PacketActionOpen);
  2128.   Packet.AddInt1(X);
  2129.   Packet.AddInt2(Y);
  2130.  
  2131.   SendRanged(Packet, X, Y);
  2132. end;{class)Server.OpenDoor}
  2133.  
  2134. class procedure Server.Shutdown;
  2135. var
  2136.   Packet: TPacket;
  2137. begin
  2138.   Packet.SetID(PacketFamilyMessage, PacketActionClose);
  2139.   Send(Packet);
  2140. end;{Server.Shutdown}
  2141.  
  2142. class function Server.ValidName(Name: AnsiString; IgnoreUnapproved: Boolean = False): Boolean;
  2143. var
  2144.   s: AnsiString;
  2145.   c: AnsiChar;
  2146. begin
  2147.   if (length(Name) < 3) or (length(Name) > NameMax) then exit(False);
  2148.  
  2149.   for c in Name do
  2150.     if pos(String(c), NameChars) = 0 then
  2151.       exit(False);
  2152.  
  2153.   if not IgnoreUnapproved then
  2154.     for s in Unapproved.Items do
  2155.       if Match(lower(s), Name) then exit(False);
  2156.  
  2157.   Result := True;
  2158. end;{class)Server.ValidName}
  2159.  
  2160. class function Server.GetAccount(Name: AnsiString; Items: AnsiString = '*'): TDatabase.TTable;
  2161. begin
  2162.   Result := Database.QueryTable('SELECT ' + Items + ' FROM `accounts` WHERE `name` = "' + Name + '";');
  2163. end;{class)Server.GetAccount}
  2164.  
  2165. class function Server.AccountExists(Name: AnsiString): Boolean;
  2166. begin
  2167.   with GetAccount(Name, '`id`') do try
  2168.     Result := length(Table) > 0
  2169.   finally
  2170.     Free;
  2171.   end;{with GetAccount}
  2172. end;{class)Server.AccountExists}
  2173.  
  2174. class procedure Server.BanIP(IP: AnsiString);
  2175. var
  2176.   IIP: Integer;
  2177. begin
  2178.   if length(IP) = 0 then exit;
  2179.  
  2180.   IIP := inet_addr(PAnsiChar(IP));
  2181.   if IIP = localhost then exit;
  2182.   if Server.BannedIP(IIP) then exit;
  2183.  
  2184.   if Server.Database.Query('INSERT INTO `banned` (`ip`) VALUES (' + Str(IIP) + ');') then
  2185.     Log(['Banned IP ' + IP])
  2186.   else
  2187.     Log(['Failed to insert IP ban [' + IP + '] into database']);
  2188. end;{Server.BanIP}
  2189.  
  2190. class procedure Server.UnbanIP(IP: AnsiString);
  2191. var
  2192.   IIP: Integer;
  2193. begin
  2194.   if length(IP) = 0 then exit;
  2195.  
  2196.   IIP := inet_addr(PAnsiChar(IP));
  2197.   if not Server.BannedIP(IIP) then exit;
  2198.  
  2199.   if Server.Database.Query('DELETE FROM `banned` WHERE `ip` = ' + Str(IIP) + ';') then
  2200.     Log(['Unbanned IP ' + IP])
  2201.   else
  2202.     Log(['Failed to delete IP ban [' + IP + '] from database']);
  2203. end;{Server.UnbanIP}
  2204.  
  2205. class function Server.BannedIP(IP: Integer): Boolean;
  2206. begin
  2207.   Result := not Database.QueryTable('SELECT * FROM `banned` WHERE `ip` = ' + Str(IP) + ';').Empty;
  2208. end;{Server.BannedIP}
  2209.  
  2210. procedure Server.TPacket.SetID(AFamily, AAction: Byte);
  2211. begin
  2212.   Family := AFamily;
  2213.   Action := AAction;
  2214. end;{Server.TPacket.SetID}
  2215.  
  2216. procedure Server.TPacket.Reset;
  2217. begin
  2218.   Data := '';
  2219. end;{Server.TPacket.Reset}
  2220.  
  2221. procedure Server.TPacket.Discard(Count: Integer = 1);
  2222. begin
  2223.   Data := copy(Data, Count + 1, length(Data));
  2224. end;{Server.TPacket.Discard}
  2225.  
  2226. procedure Server.TPacket.AddByte(b: Byte);
  2227. begin
  2228.   Data := Data + AnsiChar(b);
  2229. end;{Server.TPacket.AddByte}
  2230.  
  2231. procedure Server.TPacket.AddInt1(i: Byte);
  2232. begin
  2233.   Data := Data + UnpackEOInt(i)[1];
  2234. end;{Server.TPacket.AddInt1}
  2235.  
  2236. procedure Server.TPacket.AddInt2(i: Word);
  2237. begin
  2238.   Data := Data + copy(UnpackEOInt(i), 1, 2);
  2239. end;{Server.TPacket.AddInt2}
  2240.  
  2241. procedure Server.TPacket.AddInt3(i: Cardinal);
  2242. begin
  2243.   Data := Data + copy(UnpackEOInt(i), 1, 3);
  2244. end;{Server.TPacket.AddInt3}
  2245.  
  2246. procedure Server.TPacket.AddInt4(i: Cardinal);
  2247. begin
  2248.   Data := Data + UnpackEOInt(i);
  2249. end;{Server.TPacket.AddInt4}
  2250.  
  2251. procedure Server.TPacket.AddBreakString(s: AnsiString);
  2252. begin
  2253.   Data := Data + s + #$FF;
  2254. end;{Server.TPacket.AddBreakString}
  2255.  
  2256. procedure Server.TPacket.AddString(s: AnsiString);
  2257. begin
  2258.   Data := Data + s;
  2259. end;{Server.TPacket.AddString}
  2260.  
  2261. function Server.TPacket.GetByte: Byte;
  2262. begin
  2263.   if length(Data) = 0 then exit(0);
  2264.  
  2265.   Result := ord(Data[1]);
  2266.   Data   := copy(Data, 2, length(Data));
  2267. end;{Server.TPacket.GetByte}
  2268.  
  2269. function Server.TPacket.GetInt1: Byte;
  2270. begin
  2271.   if length(Data) = 0 then exit(0);
  2272.  
  2273.   Result := PackEOInt(ord(Data[1]));
  2274.   Data  := copy(Data, 2, length(Data));
  2275. end;{Server.TPacket.GetInt1}
  2276.  
  2277. function Server.TPacket.GetInt2: Word;
  2278. begin
  2279.   if length(Data) = 0 then exit(0);
  2280.   if length(Data) < 2 then exit(GetInt1);
  2281.  
  2282.   Result := PackEOInt(ord(Data[1]), ord(Data[2]));
  2283.   Data   := copy(Data, 3, length(Data));
  2284. end;{Server.TPacket.GetInt2}
  2285.  
  2286. function Server.TPacket.GetInt3: Cardinal;
  2287. begin
  2288.   if length(Data) = 0 then exit(0);
  2289.   if length(Data) < 2 then exit(GetInt1);
  2290.   if length(Data) < 3 then exit(GetInt2);
  2291.  
  2292.   Result := PackEOInt(ord(Data[1]), ord(Data[2]), ord(Data[3]));
  2293.   Data   := copy(Data, 4, length(Data));
  2294. end;{Server.TPacket.GetInt3}
  2295.  
  2296. function Server.TPacket.GetInt4: Cardinal;
  2297. begin
  2298.   if length(Data) = 0 then exit(0);
  2299.   if length(Data) < 2 then exit(GetInt1);
  2300.   if length(Data) < 3 then exit(GetInt2);
  2301.   if length(Data) < 4 then exit(GetInt3);
  2302.  
  2303.   Result := PackEOInt(ord(Data[1]), ord(Data[2]), ord(Data[3]), ord(Data[4]));
  2304.   Data   := copy(Data, 5, length(Data));
  2305. end;{Server.TPacketGetInt4}
  2306.  
  2307. function Server.TPacket.GetBreakString: AnsiString;
  2308. var
  2309.   i: Integer;
  2310. begin
  2311.   for i := 1 to length(Data) do
  2312.     if Data[i] = #$FF then break;
  2313.  
  2314.   Result := copy(Data, 1, i - 1);
  2315.   Data   := copy(Data, i + 1, length(Data));
  2316. end;{Server.TPacket.GetBreakString}
  2317.  
  2318. function Server.TPacket.GetString(Len: Integer = -1): AnsiString;
  2319. begin
  2320.   if Len = -1 then
  2321.   begin
  2322.     Result := Data;
  2323.     Data  := '';
  2324.   end{if Len = -1}
  2325.   else
  2326.   begin
  2327.     Result := copy(Data, 1, Len);
  2328.     Data   := copy(Data, Len + 1, length(Data));
  2329.   end;{else}
  2330. end;{Server.TPacket.GetString}
  2331.  
  2332. constructor Server.TGameData.Create(AFileName: AnsiString);
  2333. begin
  2334.   inherited Create;
  2335.  
  2336.   FileName := AFileName;
  2337.   Load;
  2338. end;{Server.TGameData.Create}
  2339.  
  2340. destructor Server.TGameData.Destroy;
  2341. begin
  2342.   Clear;
  2343.  
  2344.   inherited;
  2345. end;{Server.TGameData.Destroy}
  2346.  
  2347. function Server.TGameData.Load: Boolean;
  2348. var
  2349.   l: Cardinal;
  2350.   f: THandle;
  2351. begin
  2352.   Clear;
  2353.  
  2354. {$IFDEF INTERNAL_PUB}
  2355.   case DataID of
  2356.     5:  Data := ItemPubData;
  2357.     6:  Data := NPCPubData;
  2358.     7:  Data := SpellPubData;
  2359.     11: Data := ClassPubData;
  2360.   else
  2361. {$ENDIF INTERNAL_PUB}
  2362.   Log([ClassName, ' (', FileName, ') loading...']);
  2363.  
  2364.   f := CreateFileA(PAnsiChar(FileName), GENERIC_READ, 0, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
  2365.   if f = 0 then exit(False);
  2366.  
  2367.   try
  2368.     l := SetFilePointer(f, 0, nil, FIlE_END);
  2369.     if (l = Cardinal(-1)) or (l < 11) then exit(False);
  2370.  
  2371.     SetLength(Data, l);
  2372.  
  2373.     SetFilePointer(f, 0, nil, FILE_BEGIN);
  2374.     ReadFile(f, Data[1], l, l, nil);
  2375.   finally
  2376.     CloseHandle(f);
  2377.   end;{try...finally}
  2378. {$IFDEF INTERNAL_PUB}
  2379.   end;{case DataID}
  2380. {$ENDIF INTERNAL_PUB}
  2381.  
  2382.   CRC[0] := ord(Data[4]);
  2383.   CRC[1] := ord(Data[5]);
  2384.   CRC[2] := ord(Data[6]);
  2385.   CRC[3] := ord(Data[7]);
  2386.  
  2387.   Len[0] := ord(Data[8]);
  2388.   Len[1] := ord(Data[9]);
  2389.  
  2390.   Result := True;
  2391. end;{Server.TGameData.Load}
  2392.  
  2393. procedure Server.TGameData.Clear;
  2394. begin
  2395.   Data := '';
  2396.  
  2397.   CRC[0] := 0;
  2398.   CRC[1] := 0;
  2399.   CRC[2] := 0;
  2400.   CRC[3] := 0;
  2401.  
  2402.   Len[0] := 0;
  2403.   Len[1] := 0;
  2404. end;{Server.TGameData.Clear}
  2405.  
  2406. class function Server.TItemData.DataID: Byte;
  2407. begin
  2408.   Result := 5;
  2409. end;{class)Server.TItemData.DataID}
  2410.  
  2411. class function Server.TNPCData.DataID: Byte;
  2412. begin
  2413.   Result := 6;
  2414. end;{class)Server.TNPCData.DataID}
  2415.  
  2416. class function Server.TSpellData.DataID: Byte;
  2417. begin
  2418.   Result := 7;
  2419. end;{class)Server.TSpellData.DataID}
  2420.  
  2421. class function Server.TClassData.DataID: Byte;
  2422. begin
  2423.   Result := 11;
  2424. end;{class)Server.TClassData.DataID}
  2425.  
  2426. class function Server.TMapData.DataID: Byte;
  2427. begin
  2428.   Result := 4;
  2429. end;{class)Server.TMapData.DataID}
  2430.  
  2431. function Server.TMapData.Load: Boolean;
  2432.   function ReadInt(Loc: Integer; Size: Integer = 1): Integer;
  2433.   var
  2434.     Ords: AnsiString;
  2435.   begin
  2436.     Ords   := copy(Data, Loc, Size) + #0#0#0#0;
  2437.     Result := PackEOInt(ord(Ords[1]), ord(Ords[2]), ord(Ords[3]), ord(Ords[4]));
  2438.   end;{ReadInt}
  2439.  
  2440.   function ReadIntN(var Loc: Integer; Size: Integer = 1): Integer; inline;
  2441.   begin
  2442.     Result := ReadInt(Loc, Size); inc(Loc, Size);
  2443.   end;{ReadIntN}
  2444. var
  2445.   i, j:  Integer;
  2446.   x, y:  Integer;
  2447.   p:     Integer;
  2448.   Outer: Integer;
  2449.   Inner: Integer;
  2450. begin
  2451.   Result := inherited;
  2452.   if not Result then exit;
  2453.  
  2454.   Width  := ReadInt($26) + 1;
  2455.   Height := ReadInt($27) + 1;
  2456.  
  2457.   SetLength(Tiles, Height, Width);
  2458.  
  2459.   for y := 0 to Height - 1 do
  2460.     for x := 0 to Width - 1 do
  2461.       with Tiles[y, x] do
  2462.       begin
  2463.         Kind         := 0;
  2464.         Warp.Enabled := False;
  2465.       end;{with Tiles[y, x]}
  2466.  
  2467.   Outer := ReadInt($2F); p := $30 + ( 8 * Outer);
  2468.   Outer := ReadIntN(p);  p := p   + ( 4 * Outer);
  2469.   Outer := ReadIntN(p);  p := p   + (12 * Outer);
  2470.   Outer := ReadIntN(p);  p := p;
  2471.  
  2472.   for i := 0 to Outer - 1 do
  2473.   begin
  2474.     y     := ReadIntN(p);
  2475.     Inner := ReadIntN(p);
  2476.  
  2477.     for j := 0 to Inner - 1 do
  2478.     begin
  2479.       x := ReadIntN(p);
  2480.  
  2481.       with Tiles[y, x] do
  2482.       begin
  2483.         Kind := ReadIntN(p) + 1;
  2484.         //Warp.Enabled := False;
  2485.       end;{with Tiles[y, x]}
  2486.     end;{for j}
  2487.   end;{for i}
  2488.  
  2489.   Outer := ReadIntN(p);
  2490.  
  2491.   for i := 0 to Outer - 1 do
  2492.   begin
  2493.     y     := ReadIntN(p);
  2494.     Inner := ReadIntN(p);
  2495.  
  2496.     for j := 0 to Inner - 1 do
  2497.     begin
  2498.       x := ReadIntN(p);
  2499.  
  2500.       with Tiles[y, x] do
  2501.       begin
  2502.         Warp.Enabled  := True;
  2503.         Warp.M        := ReadIntN(p, 2);
  2504.         Warp.X        := ReadIntN(p);
  2505.         Warp.Y        := ReadIntN(p);
  2506.         Warp.ReqLevel := ReadIntN(p);
  2507.         Warp.ReqItem  := ReadIntN(p, 2);
  2508.       end;{with Tiles[y, x]}
  2509.     end;{for j}
  2510.   end;{for i}
  2511. end;{Server.TMapData.Load}
  2512.  
  2513. procedure Server.TMapData.Clear;
  2514. begin
  2515.   inherited;
  2516. end;{Server.TMapData.Clear}
  2517.  
  2518. function Server.TMapData.IsWalkable(X, Y: Integer; NPC: Boolean = False): Boolean;
  2519. begin
  2520.   if (X < 0) or (X >= Width) or (Y < 0) or (Y >= Height) then exit(False);
  2521.  
  2522.   if NPC and (Tiles[Y, X].Kind = MapTileNPCBoundary) then exit(False);
  2523.  
  2524.   Result := not (Tiles[Y, X].Kind in MapTilesImpassible);
  2525. end;{Server.TMapData.IsWalkable}
  2526.  
  2527. function SessionThread(Session: Server.TSession): Integer;
  2528. begin
  2529.   Result := 0;
  2530.  
  2531.   try
  2532.     try
  2533.       while Session.Execute do
  2534.         Sleep(1);
  2535.     except
  2536.       Server.Log(['Session exception']);
  2537.     end;{try...except}
  2538.   finally
  2539.     Server.CriticalSection.Enter;
  2540.     try Session.Free; except end;
  2541.     Server.CriticalSection.Leave;
  2542.  
  2543.     EndThread(Result);
  2544.   end;{try...finally}
  2545. end;{SessionThread}
  2546.  
  2547. constructor Server.TSession.Create(ASocket: TSocket; ASockAddr: TSockAddr);
  2548. var
  2549.   i: Integer;
  2550. begin
  2551.   inherited Create;
  2552.  
  2553.   Initialized := False;
  2554.   LoggedIn    := False;
  2555.   Offline     := False;
  2556.   Party       := nil;
  2557.  
  2558.   Unload;
  2559.  
  2560.   Socket := ASocket;
  2561.  
  2562.   Offline := Socket = 0;
  2563.   if Offline then exit;
  2564.  
  2565.   IPStr := AnsiString(inet_ntoa(ASockAddr.sin_addr));
  2566.   IPInt := ASockAddr.sin_addr.S_addr;
  2567.  
  2568.   i := 1;
  2569.   ioctlsocket(Socket, FIONBIO, i);
  2570.  
  2571.   Server.CriticalSection.Section(procedure
  2572.   begin
  2573.     ID := 100;
  2574.     while Server.GetSessionByID(ID) <> nil do inc(ID);
  2575.  
  2576.     Server.Sessions.Add(Self);
  2577.   end);{Server.CriticalSection.Section}
  2578.  
  2579.   Packet.Time := GetTickCount + Server.Connection.Timeout;
  2580.   ClearQueue;
  2581.  
  2582.   Log(['Created']);
  2583.  
  2584.   BeginThread(nil, 0, @SessionThread, Pointer(Self), 0, Thread);
  2585.  
  2586.   Server.UpdateCaption;
  2587. end;{Server.TSession.Create}
  2588.  
  2589. class function Server.TSession.CreateOffline(AName: AnsiString): TSession;
  2590. var
  2591.   InAddr: sockaddr_in;
  2592. begin
  2593.   if Server.GetSessionByName(AName) <> nil then exit(nil);
  2594.  
  2595.   Result := TSession.Create(0, InAddr);
  2596.  
  2597.   Result.Name          := AName;
  2598.   Result.IPStr         := '(offline)';
  2599.   Result.Usage.Started := False;
  2600.   Result.Party         := nil;
  2601.  
  2602.   Result.LoggedIn := Result.Sync(True);
  2603.  
  2604.   if not Result.LoggedIn then
  2605.   begin
  2606.     Result.Unload;
  2607.     Result.Free;
  2608.     Result := nil;
  2609.   end;{if not Result.LoggedIn}
  2610. end;{Server.TSession.Create (offline)}
  2611.  
  2612. destructor Server.TSession.Destroy;
  2613. begin
  2614.   Logout;
  2615.  
  2616.   Disconnect;
  2617.  
  2618.   Server.CriticalSection.Section(procedure
  2619.   begin
  2620.     Server.Sessions.Remove(Self);
  2621.   end);{Server.CriticalSection.Section}
  2622.  
  2623.   Log(['Destroyed']);
  2624.  
  2625.   inherited;
  2626.  
  2627.   Server.UpdateCaption;
  2628. end;{Server.TSession.Destroy}
  2629.  
  2630. procedure Server.TSession.ClearQueue;
  2631. begin
  2632.   SetLength(Packet.Queue.Items, 0);
  2633.   Packet.Queue.Time := GetTickCount;
  2634. end;{Server.TSession.ClearQueue}
  2635.  
  2636. procedure Server.TSession.Disconnect;
  2637. begin
  2638.   if Socket <> 0 then
  2639.   begin
  2640.     closesocket(Socket);
  2641.     Socket := 0;
  2642.   end;{if Socket <> 0}
  2643. end;{Server.TSession.Disconnect}
  2644.  
  2645. function Server.TSession.Sync(Discard: Boolean = False): Boolean;
  2646. var
  2647.   SQL: AnsiString;
  2648. begin
  2649.   if length(Name) = 0 then exit(False);
  2650.  
  2651.   if Discard then
  2652.     with Server.GetAccount(Name) do try
  2653.       if length(Table) = 0 then exit(False);
  2654.  
  2655.       Banned := Value('banned', 0, 0);
  2656.  
  2657.       Password := Value('password', 0, '');
  2658.       if length(Password) = 0 then exit(False);
  2659.  
  2660.       State         := Value('state', 0, 0);
  2661.       Usage.Current := Value('usage', 0, 0);
  2662.  
  2663.       X := Value('x', 0, Server.Defaults.X);
  2664.       Y := Value('y', 0, Server.Defaults.Y);
  2665.       D := Value('d', 0, Server.Defaults.D);
  2666.       Sitting := Value('s', 0, 0);
  2667.       //Hidden := Value('h', 0, 0);
  2668.       Admin      := Value('admin', 0, 0);
  2669.       Tag        := copy(Value('tag', 0, ''), 1, 3);
  2670.       Sex        := Value('sex',        0, 0);
  2671.       HairStyle  := Value('hairstyle',  0, 0);
  2672.       HairColour := Value('haircolour', 0, 0);
  2673.       Race       := Value('race',       0, 0);
  2674.       Boots      := Value('boots',      0, 0);
  2675.       Armour     := Value('armour',     0, 0);
  2676.       Hat        := Value('hat',        0, 0);
  2677.       Shield     := Value('shield',     0, 0);
  2678.       Weapon     := Value('weapon',     0, 0);
  2679.       Gold       := Value('gold',       0, Server.Defaults.Gold);
  2680.       HP         := Value('hp',         0, Server.Defaults.HP);
  2681.       MaxHP      := Value('maxhp',      0, Server.Defaults.MaxHP);
  2682.       TP         := Value('tp',         0, Server.Defaults.TP);
  2683.       MaxTP      := Value('maxtp',      0, Server.Defaults.MaxTP);
  2684.       Kills      := Value('kills',      0, 0);
  2685.  
  2686.       if MaxHP < 1 then MaxHP := 1;
  2687.  
  2688.       Result := True;
  2689.     finally
  2690.       Free;
  2691.     end{with Server.GetAccount}
  2692.   else
  2693.   begin
  2694.     if not Server.AccountExists(Name) then
  2695.     begin
  2696.       SQL := 'INSERT INTO `accounts` (`name`) VALUES ("' + Name + '");';
  2697.       Result := Server.Database.Query(SQL);
  2698.       if not Result then
  2699.       begin
  2700.         Log(['Failed to insert into database']);
  2701.         exit;
  2702.       end;{if not Result}
  2703.     end;{if not Server.AccountExists}
  2704.  
  2705.     if Usage.Started then
  2706.     begin
  2707.       Usage.Current := Usage.Current + ((GetTickCount - Usage.Last) div 60000);
  2708.       Usage.Last := GetTickCount;
  2709.     end;{if Usage.Started}
  2710.  
  2711.     SQL := 'UPDATE `accounts` SET ' +
  2712.       '`banned` = ' + Str(Banned) + ', ' +
  2713.       '`password` = "' + Password + '", ' +
  2714.       '`state` = ' + Str(State) + ', ' +
  2715.       '`usage` = ' + Str(Usage.Current) + ', ' +
  2716.       '`x` = ' + Str(X) + ', ' +
  2717.       '`y` = ' + Str(Y) + ', ' +
  2718.       '`d` = ' + Str(D) + ', ' +
  2719.       '`s` = ' + Str(Sitting) + ', ' +
  2720.       //'`s` = ' + Str(Hidden) + ', ' +
  2721.       '`admin` = ' + Str(Admin) + ', ' +
  2722.       '`tag` = "' + Tag + '", ' +
  2723.       '`sex` = ' + Str(Sex) + ', ' +
  2724.       '`hairstyle` = ' + Str(HairStyle) + ', ' +
  2725.       '`haircolour` = ' + Str(HairColour) + ', ' +
  2726.       '`race` = ' + Str(Race) + ', ' +
  2727.       '`boots` = ' + Str(Boots) + ', ' +
  2728.       '`armour` = ' + Str(Armour) + ', ' +
  2729.       '`hat` = ' + Str(Hat) + ', ' +
  2730.       '`shield` = ' + Str(Shield) + ', ' +
  2731.       '`weapon` = ' + Str(Weapon) + ', ' +
  2732.       '`gold` = ' + Str(Gold) + ', ' +
  2733.       '`hp` = ' + Str(HP) + ', ' +
  2734.       '`maxhp` = ' + Str(MaxHP) + ', ' +
  2735.       '`tp` = ' + Str(TP) + ', ' +
  2736.       '`maxtp` = ' + Str(MaxTP) + ', ' +
  2737.       '`kills` = ' + Str(Kills) +
  2738.       ' WHERE `name` = "' + Name + '";';
  2739.  
  2740.     Result := Server.Database.Query(SQL);
  2741.  
  2742.     if not Result then Log(['Database sync failed']);
  2743.   end{else}
  2744. end;{Server.TSession.Sync}
  2745.  
  2746. procedure Server.TSession.Unload;
  2747. begin
  2748.   Usage.Started := False;
  2749.   Name := '';
  2750.   Password := '';
  2751.   LoggedIn := False;
  2752.   WarpInfo.Time := 0;
  2753. end;{Server.TSession.Unload}
  2754.  
  2755. procedure Server.TSession.Log(Params: array of const);
  2756. var
  2757.   S: AnsiString;
  2758. begin
  2759.   S := 'Session (' + IPStr + ')';
  2760.  
  2761.   if LoggedIn and (length(Name) > 0) then
  2762.     S := S + ' "' + Name + '"';
  2763.  
  2764.   Server.Log(Params, S);
  2765. end;{Server.TSession.Log}
  2766.  
  2767. procedure Server.TSession.Send(var Packet: TPacket; Raw: Boolean = False);
  2768. var
  2769.   i, j, Size: Integer;
  2770.   Encoded:    AnsiString;
  2771.   EncodeBuf:  AnsiString;
  2772. begin
  2773.   if Offline then exit;
  2774.  
  2775.   Encoded := copy(UnpackEOInt(length(Packet.Data) + 2), 1, 2) +
  2776.              AnsiChar(Packet.Action) +
  2777.              AnsiChar(Packet.Family) +
  2778.              Packet.Data;
  2779.  
  2780.   Size := length(Encoded);
  2781.  
  2782.   if not Raw then
  2783.   begin
  2784.     Encoded := FoldData(Encoded, Server.SendKey);
  2785.  
  2786.     SetLength(EncodeBuf, Size);
  2787.  
  2788.     EncodeBuf[1] := Encoded[1];
  2789.     EncodeBuf[2] := Encoded[2];
  2790.  
  2791.     i := 2; j := 2;
  2792.  
  2793.     while i < Size do
  2794.     begin
  2795.       EncodeBuf[i + 1] := AnsiChar(ord(Encoded[j + 1]) xor $80);
  2796.       inc(j);
  2797.       inc(i, 2);
  2798.     end;{while i < Size}
  2799.  
  2800.     i := Size - 1;
  2801.     if Boolean(Size mod 2) then dec(i);
  2802.  
  2803.     while i >= 2 do
  2804.     begin
  2805.       EncodeBuf[i + 1] := AnsiChar(ord(Encoded[j + 1]) xor $80);
  2806.       inc(j);
  2807.       dec(i, 2);
  2808.     end;{while i >= 2}
  2809.  
  2810.     for i := 3 to Size do
  2811.            if EncodeBuf[i] = #128 then EncodeBuf[i] := #0
  2812.       else if EncodeBuf[i] = #0   then EncodeBuf[i] := #128;
  2813.  
  2814.     Encoded := EncodeBuf;
  2815.   end;{if not Raw}
  2816.  
  2817.   WinSock.send(Socket, Encoded[1], Size, 0);
  2818.   InterlockedExchangeAdd64(Server.Connection.BytesOut, Size);
  2819.   Server.UpdateCaption;
  2820. end;{Server.TSession.Send}
  2821.  
  2822. procedure Server.TSession.Send(Raw: Boolean = False);
  2823. begin
  2824.   Send(Packet.Send, Raw);
  2825. end;{Server.TSession.Send}
  2826.  
  2827. procedure Server.TSession.SendData(Data: TGameData);
  2828. var
  2829.   Packet: Server.TPacket;
  2830. begin
  2831.   Packet.SetID(PacketFamilyRaw, PacketActionRaw);
  2832.  
  2833.   Packet.AddInt1(Data.DataID);
  2834.  
  2835.   if Data.DataID <> 4 then
  2836.     Packet.AddInt1(1);
  2837.  
  2838.   Packet.AddString(Data.Data);
  2839.  
  2840.   Send(Packet, True);
  2841. end;{Server.TSession.SendData}
  2842.  
  2843. procedure Server.TSession.Login;
  2844. var
  2845.   i:      Integer;
  2846.   Packet: TPacket;
  2847.   Tag:    AnsiString;
  2848. begin
  2849.   Packet.SetID(PacketFamilyGameState, PacketActionReply);
  2850.  
  2851.   Packet.AddInt2(1);
  2852.   Packet.AddInt2(ID);
  2853.   Packet.AddInt4(ID);
  2854.   Packet.AddInt2(1); // Map ID
  2855.  
  2856.   Packet.AddByte(Server.MapData.CRC[0]);
  2857.   Packet.AddByte(Server.MapData.CRC[1]);
  2858.   Packet.AddByte(Server.MapData.CRC[2]);
  2859.   Packet.AddByte(Server.MapData.CRC[3]);
  2860.   Packet.AddInt3(length(Server.MapData.Data));
  2861.  
  2862.   Packet.AddByte(Server.ItemData.CRC[0]);
  2863.   Packet.AddByte(Server.ItemData.CRC[1]);
  2864.   Packet.AddByte(Server.ItemData.CRC[2]);
  2865.   Packet.AddByte(Server.ItemData.CRC[3]);
  2866.   Packet.AddByte(Server.ItemData.Len[0]);
  2867.   Packet.AddByte(Server.ItemData.Len[1]);
  2868.  
  2869.   Packet.AddByte(Server.NPCData.CRC[0]);
  2870.   Packet.AddByte(Server.NPCData.CRC[1]);
  2871.   Packet.AddByte(Server.NPCData.CRC[2]);
  2872.   Packet.AddByte(Server.NPCData.CRC[3]);
  2873.   Packet.AddByte(Server.NPCData.Len[0]);
  2874.   Packet.AddByte(Server.NPCData.Len[1]);
  2875.  
  2876.   Packet.AddByte(Server.SpellData.CRC[0]);
  2877.   Packet.AddByte(Server.SpellData.CRC[1]);
  2878.   Packet.AddByte(Server.SpellData.CRC[2]);
  2879.   Packet.AddByte(Server.SpellData.CRC[3]);
  2880.   Packet.AddByte(Server.SpellData.Len[0]);
  2881.   Packet.AddByte(Server.SpellData.Len[1]);
  2882.  
  2883.   Packet.AddByte(Server.ClassData.CRC[0]);
  2884.   Packet.AddByte(Server.ClassData.CRC[1]);
  2885.   Packet.AddByte(Server.ClassData.CRC[2]);
  2886.   Packet.AddByte(Server.ClassData.CRC[3]);
  2887.   Packet.AddByte(Server.ClassData.Len[0]);
  2888.   Packet.AddByte(Server.ClassData.Len[1]);
  2889.  
  2890.   Packet.AddBreakString(Name);
  2891.   Packet.AddBreakString(IPStr); // Title
  2892.   Packet.AddBreakString(''); // Guild
  2893.   Packet.AddBreakString(''); // Rank
  2894.  
  2895.   Packet.AddInt1(0); // Class
  2896.  
  2897.   if IPInt = localhost then
  2898.     Tag := Server.Admin.TagLocalhost
  2899.   else if Admin > 0 then
  2900.     Tag := Server.Admin.TagAdmin
  2901.   else
  2902.     Tag := '';
  2903.  
  2904.   Packet.AddString(copy(Tag + #160'  ', 1, 3));
  2905.  
  2906.   Packet.AddInt1(Admin);  // Admin
  2907.   Packet.AddInt1(0);  // Level
  2908.   Packet.AddInt4(0);  // Exp
  2909.   Packet.AddInt4(Usage.Current);
  2910.   Packet.AddInt2(HP);
  2911.   Packet.AddInt2(MaxHP);
  2912.   Packet.AddInt2(TP);
  2913.   Packet.AddInt2(MaxTP);
  2914.   Packet.AddInt2(10); // MaxSP
  2915.   Packet.AddInt2(0);  // Stat points
  2916.   Packet.AddInt2(0);  // Skill points
  2917.   Packet.AddInt2(0);  // Karma
  2918.   Packet.AddInt2(0);  // Min damage
  2919.   Packet.AddInt2(0);  // Max damage
  2920.   Packet.AddInt2(0);  // Accuracy
  2921.   Packet.AddInt2(0);  // Evade
  2922.   Packet.AddInt2(0);  // Armour
  2923.  
  2924.   Packet.AddInt2(0); // Str
  2925.   Packet.AddInt2(0); // Int
  2926.   Packet.AddInt2(0); // Wis
  2927.   Packet.AddInt2(0); // Agi
  2928.   Packet.AddInt2(0); // Con
  2929.   Packet.AddInt2(0); // Cha
  2930.  
  2931.   for i := 0 to 14 do
  2932.     Packet.AddInt2(0); // Paperdoll
  2933.  
  2934.   Packet.AddInt1(1); // Guild Rank
  2935.   Packet.AddInt2(0); // Jail map
  2936.   Packet.AddInt2(4);
  2937.   Packet.AddInt1(24);
  2938.   Packet.AddInt1(24);
  2939.   Packet.AddInt2(10);
  2940.   Packet.AddInt2(10);
  2941.   Packet.AddInt2(0);
  2942.   Packet.AddInt2(2);
  2943.   Packet.AddInt1(1);
  2944.  
  2945.   Packet.AddByte(255);
  2946.  
  2947.   Send(Packet);
  2948.  
  2949.   Usage.Last    := GetTickCount;
  2950.   Usage.Started := True;
  2951. end;{Server.TSession.Login}
  2952.  
  2953. procedure Server.TSession.Logout;
  2954. var
  2955.   Packet: TPacket;
  2956. begin
  2957.   if not LoggedIn then exit;
  2958.  
  2959.   if Party <> nil then
  2960.     Party.Leave(Self);
  2961.  
  2962.   Packet.SetID(PacketFamilyPlayers, PacketActionRemove);
  2963.   Packet.AddInt2(ID);
  2964.  
  2965.   Server.Send(Packet, Self);
  2966.  
  2967.   Sync;
  2968.   Unload;
  2969. end;{Server.TSession.Logout}
  2970.  
  2971. procedure Server.TSession.BuildCharacterPacket(var Packet: TPacket);
  2972. var
  2973.   Tag: AnsiString;
  2974. begin
  2975.   Packet.AddBreakString(Name);
  2976.  
  2977.   Packet.AddInt2(ID);
  2978.  
  2979.   if LoggedIn then
  2980.   begin
  2981.     Packet.AddInt2(1);
  2982.     Packet.AddInt2(X);
  2983.     Packet.AddInt2(Y);
  2984.   end{if LoggedIn}
  2985.   else
  2986.   begin
  2987.     Packet.AddInt2(0);
  2988.     Packet.AddInt2(0);
  2989.     Packet.AddInt2(0);
  2990.   end;{else}
  2991.  
  2992.   Packet.AddInt1(D);
  2993.   Packet.AddInt1(6);
  2994.  
  2995.   if IPInt = localhost then
  2996.     Tag := Server.Admin.TagLocalhost
  2997.   else if Admin > 0 then
  2998.     Tag := Server.Admin.TagAdmin
  2999.   else
  3000.     Tag := '';
  3001.  
  3002.   Packet.AddString(copy(Tag + #160'  ', 1, 3));
  3003.   Packet.AddInt1(0);  // Level
  3004.   Packet.AddInt1(Sex);
  3005.   Packet.AddInt1(HairStyle);
  3006.   Packet.AddInt1(HairColour);
  3007.   Packet.AddInt1(Race);
  3008.   Packet.AddInt2(MaxHP);
  3009.   Packet.AddInt2(HP);
  3010.   Packet.AddInt2(MaxTP);
  3011.   Packet.AddInt2(TP);
  3012.  
  3013.   Packet.AddInt2(Boots);
  3014.   Packet.AddInt2(0);
  3015.   Packet.AddInt2(0);
  3016.   Packet.AddInt2(0);
  3017.   Packet.AddInt2(Armour);
  3018.   Packet.AddInt2(0);
  3019.   Packet.AddInt2(Hat);
  3020.   Packet.AddInt2(Shield);
  3021.   Packet.AddInt2(Weapon);
  3022.  
  3023.   Packet.AddInt1(Sitting);
  3024.  
  3025.   if LoggedIn then
  3026.     Packet.AddInt1(Hidden)
  3027.   else
  3028.     Packet.AddInt1(1);
  3029. end;{Server.TSession.BuildCharacterPacket}
  3030.  
  3031. procedure Server.TSession.Refresh;
  3032. var
  3033.   Packet: TPacket;
  3034. begin
  3035.   if (not LoggedIn) or Offline then exit;
  3036.  
  3037.   Packet.SetID(PacketFamilyPlayers, PacketActionRemove);
  3038.   Packet.AddInt2(ID);
  3039.  
  3040.   Server.Send(Packet);
  3041.  
  3042.   Packet.Reset;
  3043.   Packet.SetID(PacketFamilyPlayers, PacketActionAgree);
  3044.   Packet.AddByte(255);
  3045.   BuildCharacterPacket(Packet);
  3046.   Packet.AddInt1(1);
  3047.   Packet.AddByte(255);
  3048.   Packet.AddInt1(1);
  3049.  
  3050.   Server.Send(Packet);
  3051. end;{Server.TSession.Refresh}
  3052.  
  3053. procedure Server.TSession.RefreshAll;
  3054. var
  3055.   Packet: TPacket;
  3056. begin
  3057.   if (not LoggedIn) or Offline then exit;
  3058.  
  3059.   Packet.SetID(PacketFamilyRefresh, PacketActionReply);
  3060.  
  3061.   Server.CriticalSection.Section(procedure
  3062.   var
  3063.     p, Count: Integer;
  3064.     Session:  TSession;
  3065.   begin
  3066.     p := length(Packet.Data) + 1;
  3067.     Packet.AddInt1(0);
  3068.     Packet.AddByte(255);
  3069.  
  3070.     Count := 0;
  3071.  
  3072.     for Session in Server.Sessions.Items do
  3073.       if Session.LoggedIn then
  3074.       begin
  3075.         Session.BuildCharacterPacket(Packet);
  3076.         Packet.AddByte(255);
  3077.         inc(Count);
  3078.       end;{if Session.LoggedIn}
  3079.  
  3080.     Packet.Data[p] := UnpackEOInt(Count)[1];
  3081.   end);{Server.CriticalSection.Section}
  3082.  
  3083.   Packet.AddByte(255);
  3084.   Send(Packet);
  3085. end;{Server.TSession.RefreshAll}
  3086.  
  3087. function Server.TSession.Walk(Direction: Integer; Admin: Boolean = False; Ghost: Boolean = False; SendToSelf: Boolean = False): Boolean;
  3088. var
  3089.   i:          Integer;
  3090.   State:      Integer;
  3091.   NewX, NewY: Integer;
  3092.   PacketShow: TPacket;
  3093.   PacketHide: TPacket;
  3094.   PacketWalk: TPacket;
  3095.   PacketChar: TPacket;
  3096.   Session:    TSession;
  3097.   NewCoords:  array[-Server.ViewRange..Server.ViewRange] of TPoint;
  3098.   OldCoords:  array[-Server.ViewRange..Server.ViewRange] of TPoint;
  3099. begin
  3100.   if (not LoggedIn) or Offline then exit(False);
  3101.  
  3102.   NewX := X;
  3103.   NewY := Y;
  3104.  
  3105.   case Direction of
  3106.     DirectionDown:  inc(NewY);
  3107.     DirectionLeft:  dec(NewX);
  3108.     DirectionUp:    dec(NewY);
  3109.     DirectionRight: inc(NewX);
  3110.   else
  3111.     Log(['Invalid walk direction ', Direction]);
  3112.     exit(False);
  3113.   end;{case Direction}
  3114.  
  3115.   if (NewX < 0) or (NewX >= Server.MapData.Width) or (NewY < 0) or (NewY >= Server.MapData.Height) then exit(False);
  3116.  
  3117.   if (not Admin) and (not Server.MapData.IsWalkable(NewX, NewY, False)) then exit(False);
  3118.  
  3119.   if (not Admin) and (not Ghost) then
  3120.   begin
  3121.     Server.CriticalSection.Enter;
  3122.     try
  3123.       for Session in Server.Sessions.Items do
  3124.         if (Session <> Self) and (Session.LoggedIn) and (Session.X = NewX) and (Session.Y = NewY) then exit(False);
  3125.     finally
  3126.       Server.CriticalSection.Leave;
  3127.     end;{try...finally}
  3128.   end;{if (not Admin) and (not Ghost)}
  3129.  
  3130.   D := Direction;
  3131.   X := NewX;
  3132.   Y := NewY;
  3133.  
  3134.   PacketShow.SetID(PacketFamilyPlayers, PacketActionAgree);
  3135.   PacketShow.AddByte(255);
  3136.   BuildCharacterPacket(PacketShow);
  3137.   PacketShow.AddByte(255);
  3138.   PacketShow.AddInt1(1);
  3139.  
  3140.   PacketHide.SetID(PacketFamilyPlayers, PacketActionRemove);
  3141.   PacketHide.AddInt2(ID);
  3142.  
  3143.   PacketWalk.SetID(PacketFamilyWalk, PacketActionPlayer);
  3144.   PacketWalk.AddInt2(ID);
  3145.   PacketWalk.AddInt1(D);
  3146.   PacketWalk.AddInt1(X);
  3147.   PacketWalk.AddInt1(Y);
  3148.  
  3149.   for i := -Server.ViewRange to Server.ViewRange do
  3150.     case Direction of
  3151.       DirectionDown:
  3152.       begin
  3153.         NewCoords[i].X := X + i;
  3154.         NewCoords[i].Y := Y + Server.ViewRange - abs(i);
  3155.         OldCoords[i].X := X + i;
  3156.         OldCoords[i].Y := Y - Server.ViewRange - 1 + abs(i);
  3157.       end;{DirectionDown:}
  3158.  
  3159.       DirectionLeft:
  3160.       begin
  3161.         NewCoords[i].X := X - Server.ViewRange + abs(i);
  3162.         NewCoords[i].Y := Y + i;
  3163.         OldCoords[i].X := X + Server.ViewRange + 1 - abs(i);
  3164.         OldCoords[i].Y := Y + i;
  3165.       end;{DirectionLeft:}
  3166.  
  3167.       DirectionUp:
  3168.       begin
  3169.         NewCoords[i].X := X + i;
  3170.         NewCoords[i].Y := Y - Server.ViewRange + abs(i);
  3171.         OldCoords[i].X := X + i;
  3172.         OldCoords[i].Y := Y + Server.ViewRange + 1 - abs(i);
  3173.       end;{DirectionUp:}
  3174.  
  3175.       DirectionRight:
  3176.       begin
  3177.         NewCoords[i].X := X + Server.ViewRange - abs(i);
  3178.         NewCoords[i].Y := Y + i;
  3179.         OldCoords[i].X := X - Server.ViewRange - 1 + abs(i);
  3180.         OldCoords[i].Y := Y + i;
  3181.       end;{DirectionRight:}
  3182.   end;{case Direction}
  3183.  
  3184.   Server.CriticalSection.Enter;
  3185.   try
  3186.     for Session in Server.Sessions.Items do
  3187.       if (Session <> Self) and Session.LoggedIn and
  3188.          (Session.X >= (X - Server.ViewRange)) and (Session.X <= (X + Server.ViewRange)) and
  3189.          (Session.Y >= (Y - Server.ViewRange)) and (Session.Y <= (Y + Server.ViewRange)) and
  3190.          (length(Session.Name) > 0) then
  3191.       begin
  3192.         State := 0;
  3193.  
  3194.         for i := -Server.ViewRange to Server.ViewRange do
  3195.           if (Session.X = NewCoords[i].X) and (Session.Y = NewCoords[i].Y) then
  3196.           begin
  3197.             State := 1;
  3198.             break;
  3199.           end{if (Session.X...}
  3200.           else if (Session.X = OldCoords[i].X) and (Session.Y = OldCoords[i].Y) then
  3201.           begin
  3202.             State := -1;
  3203.             break;
  3204.           end;{else if (Session.X...}
  3205.  
  3206.         case State of
  3207.           1:
  3208.           begin
  3209.             PacketChar.Reset;
  3210.             PacketChar.SetID(PacketFamilyPlayers, PacketActionAgree);
  3211.             PacketChar.AddByte(255);
  3212.             Session.BuildCharacterPacket(PacketChar);
  3213.             PacketChar.AddByte(255);
  3214.             PacketChar.AddInt1(1);
  3215.  
  3216.             Session.Send(PacketShow);
  3217.             Send(PacketChar);
  3218.           end;{1:}
  3219.  
  3220.           -1:
  3221.           begin
  3222.             PacketChar.Reset;
  3223.             PacketChar.SetID(PacketFamilyPlayers, PacketActionRemove);
  3224.             PacketChar.AddInt2(Session.ID);
  3225.  
  3226.             Session.Send(PacketHide);
  3227.             Send(PacketChar);
  3228.           end;{-1:}
  3229.         else
  3230.           Session.Send(PacketWalk);
  3231.         end;{case State}
  3232.       end;{if Session <> Self}
  3233.   finally
  3234.     Server.CriticalSection.Leave;
  3235.   end;{try...finally}
  3236.  
  3237.   if SendToSelf then
  3238.     Send(PacketWalk);
  3239.  
  3240.   with Server.MapData.Tiles[Y, X].Warp do
  3241.     if Enabled then Self.Warp(X, Y);
  3242.  
  3243.   Result := True;
  3244. end;{Server.TSession.Walk}
  3245.  
  3246. function Server.TSession.Face(Direction: Integer; SendToSelf: Boolean = False): Boolean;
  3247. var
  3248.   Packet: TPacket;
  3249. begin
  3250.   if (not LoggedIn) or Offline then exit(False);
  3251.  
  3252.   if (Direction < 0) or (Direction > 3) then
  3253.   begin
  3254.     Log(['Invalid face direction ', Direction]);
  3255.     exit(False);
  3256.   end;{if Direction..}
  3257.  
  3258.   D := Direction;
  3259.  
  3260.   Packet.SetID(PacketFamilyFace, PacketActionPlayer);
  3261.   Packet.AddInt2(ID);
  3262.   Packet.AddInt1(D);
  3263.  
  3264.   if SendToSelf then Send(Packet);
  3265.   Server.Send(Packet, Self);
  3266.  
  3267.   Result := True;
  3268. end;{Server.TSession.Face}
  3269.  
  3270. function Server.TSession.Say(Text: AnsiString; SendToSelf: Boolean = False): Boolean;
  3271. var
  3272.   i:       Integer;
  3273.   Packet:  TPacket;
  3274.   Player:  AnsiString;
  3275.   Cmd:     AnsiString;
  3276.   Session: TSession;
  3277. begin
  3278.   if (not LoggedIn) or Offline then exit(False);
  3279.  
  3280.   if length(Text) = 0 then exit(False);
  3281.  
  3282.   Result := True;
  3283.  
  3284.   Packet.SetID(PacketFamilyTalk, PacketActionPlayer);
  3285.  
  3286.   Packet.AddInt2(ID);
  3287.   Packet.AddString(copy(Text, 1, Server.TextLength));
  3288.   if Text[1] = '#' then
  3289.   begin
  3290.     Text := Trim(copy(Text, 2, length(Text)));
  3291.     if length(Text) = 0 then exit(False);
  3292.  
  3293.     Cmd := Split(Text);
  3294.  
  3295.     if Cmd = 'server' then
  3296.     begin
  3297.  
  3298.     end
  3299.     else
  3300.       Result := False;
  3301.  
  3302.     exit;
  3303.   end{'#'}
  3304.   else if Text[1] = Server.Admin.CommandChar then
  3305.   begin
  3306.     Text := Trim(copy(Text, 2, length(Text)));
  3307.     if length(Text) = 0 then exit(False);
  3308.  
  3309.     Cmd := Split(Text);
  3310.  
  3311.     if Cmd[1] = Server.Admin.CommandChar then
  3312.     begin
  3313.       Cmd := copy(Cmd, 2, length(Cmd));
  3314.       Player := Split(Cmd, '.');
  3315.  
  3316.       for i := 0 to 2 do
  3317.         Player := Player + '.' + Split(Cmd, '.');
  3318.  
  3319.       Cmd := Trim(Cmd + ' ' + Text);
  3320.       if length(Cmd) = 0 then exit(False);
  3321.  
  3322.       Server.CriticalSection.Enter;
  3323.       try
  3324.         for Session in Server.Sessions.Items do
  3325.           if Session.IPStr = Player then
  3326.             Session.DoCommand(Cmd, Self);
  3327.       finally
  3328.         Server.CriticalSection.Leave;
  3329.       end;{try...finally}
  3330.  
  3331.       Result := True;
  3332.     end{if Cmd[1] = '@'}
  3333.     else if pos('.', String(Cmd)) > 1 then
  3334.     begin
  3335.       Player := Split(Cmd, '.');
  3336.  
  3337.       Server.CriticalSection.Enter;
  3338.       try
  3339.         Session := Server.GetSessionByName(Player);
  3340.  
  3341.         if Session = nil then
  3342.         begin
  3343.           Session := TSession.CreateOffline(Player);
  3344.           if Session <> nil then
  3345.               try
  3346.                 Result := Session.DoCommand(Trim(Cmd + ' ' + Text), Self);
  3347.               finally
  3348.                 Session.Free;
  3349.               end{try...finally}
  3350.           else
  3351.             Result := False;
  3352.         end{if Session = nil}
  3353.         else
  3354.           Result := Session.DoCommand(Trim(Cmd + ' ' + Text), Self)
  3355.       finally
  3356.         Server.CriticalSection.Leave;
  3357.       end;{try...finally}
  3358.     end{else if pos('.', Cmd)}
  3359.     else
  3360.       Result := DoCommand(Trim(Cmd + ' ' + Text), Self);
  3361.  
  3362.     if not Server.Admin.EchoCommand then exit;
  3363.   end;{if Text[1]}
  3364.  
  3365.   if SendToSelf then Send(Packet);
  3366.   Server.Send(Packet, Self);
  3367. end;{Server.TSession.Say}
  3368.  
  3369. function Server.TSession.SayGlobal(Text: AnsiString; SendToSelf: Boolean = False): Boolean;
  3370. var
  3371.   Packet: TPacket;
  3372. begin
  3373.   if (not LoggedIn) or Offline then exit(False);
  3374.  
  3375.   Packet.SetID(PacketFamilyTalk, PacketActionMessage);
  3376.   Packet.AddBreakString(Name);
  3377.   Packet.AddBreakString(copy(Text, 1, Server.TextLength));
  3378.  
  3379.   if SendToSelf then Send(Packet);
  3380.   Server.Send(Packet, Self, False);
  3381.  
  3382.   Result := True;
  3383. end;{Server.TSession.SayGlobal}
  3384.  
  3385. function Server.TSession.SayGuild(Text: AnsiString; SendToSelf: Boolean = False): Boolean;
  3386. var
  3387.   Packet:  TPacket;
  3388.   Session: TSession;
  3389. begin
  3390.   if (not LoggedIn) or Offline then exit(False);
  3391.  
  3392.   if length(Tag) = 0 then exit(False);
  3393.  
  3394.   Packet.SetID(PacketFamilyTalk, PacketActionRequest);
  3395.   Packet.AddBreakString(Name);
  3396.   Packet.AddBreakString(copy(Text, 1, Server.TextLength));
  3397.  
  3398.   Server.CriticalSection.Enter;
  3399.   try
  3400.     for Session in Server.Sessions.Items do
  3401.       if Session.LoggedIn and ((Session <> Self) or SendToSelf) and (Session.Tag = Tag) then
  3402.         Session.Send(Packet)
  3403.   finally
  3404.     Server.CriticalSection.Leave;
  3405.   end;{try...finally}
  3406.  
  3407.   Result := True;
  3408. end;{Server.TSession.SayGuild}
  3409.  
  3410. function Server.TSession.SayAdmin(Text: AnsiString; SendToSelf: Boolean = False): Boolean;
  3411. var
  3412.   Packet:  TPacket;
  3413.   Session: TSession;
  3414. begin
  3415.   if (not LoggedIn) or Offline then exit(False);
  3416.  
  3417.   Packet.SetID(PacketFamilyTalk, PacketActionAdmin);
  3418.   Packet.AddBreakString(Name);
  3419.   Packet.AddBreakString(copy(Text, 1, Server.TextLength));
  3420.  
  3421.   Server.CriticalSection.Enter;
  3422.   try
  3423.     for Session in Server.Sessions.Items do
  3424.       if Session.LoggedIn and ((Session <> Self) or SendToSelf) and (Session.Admin > 0) then
  3425.         Session.Send(Packet)
  3426.   finally
  3427.     Server.CriticalSection.Leave;
  3428.   end;{try...finally}
  3429.  
  3430.   Result := True;
  3431. end;{Server.TSession.SayAdmin}
  3432.  
  3433. function Server.TSession.Announce(Text: AnsiString): Boolean;
  3434. var
  3435.   Packet: TPacket;
  3436. begin
  3437.   if (not LoggedIn) or Offline then exit(False);
  3438.  
  3439.   if length(Text) = 0 then exit(False);
  3440.  
  3441.   Log(['Announce "', Text, '"']);
  3442.  
  3443.   Packet.SetID(PacketFamilyTalk, PacketActionAnnounce);
  3444.   Packet.AddBreakString(Name);
  3445.   Packet.AddBreakString(copy(Text, 1, Server.TextLength));
  3446.  
  3447.   Server.Send(Packet);
  3448.  
  3449.   Result := True;
  3450. end;{Server.TSession.Announce}
  3451.  
  3452. function Server.TSession.Warp(WX, WY: Integer; Animation: Integer = WarpAnimationNone): Boolean;
  3453. var
  3454.   Packet: TPacket;
  3455. begin
  3456.   if not LoggedIn then exit(False);
  3457.  
  3458.   if (WX < 0) or (WX >= Server.MapData.Width) or (WY < 0) or (WY > Server.MapData.Height) then exit(False);
  3459.  
  3460.   if Offline then
  3461.   begin
  3462.     X := WX;
  3463.     Y := WY;
  3464.     exit(True);
  3465.   end;{if Offline}
  3466.  
  3467.   WarpInfo.Time      := GetTickCount + 2000;
  3468.   WarpInfo.X         := WX;
  3469.   WarpInfo.Y         := WY;
  3470.   WarpInfo.Animation := Animation;
  3471.  
  3472.   Packet.SetID(PacketFamilyWarp, PacketActionRequest);
  3473.   Packet.AddInt1(1);
  3474.   Packet.AddInt2(1);
  3475.   Packet.AddInt1(WX);
  3476.   Packet.AddInt1(WY);
  3477.  
  3478.   Send(Packet);
  3479.  
  3480.   Result := True;
  3481. end;{Server.TSession.Warp}
  3482.  
  3483. function Server.TSession.Sit(Chair: Boolean = False): Boolean;
  3484. var
  3485.   Packet: TPacket;
  3486. begin
  3487.   if not LoggedIn then exit(False);
  3488.  
  3489.   if Sitting <> SittingStand then exit(False);
  3490.  
  3491.   if Chair then
  3492.   begin
  3493.     if not Offline then Packet.SetID(PacketFamilyChair, PacketActionPlayer);
  3494.     Sitting := SittingChair;
  3495.   end{if Chair}
  3496.   else
  3497.   begin
  3498.     if not Offline then Packet.SetID(PacketFamilySit, PacketActionPlayer);
  3499.     Sitting := SittingFloor;
  3500.   end;{else}
  3501.  
  3502.   if Offline then exit(True);
  3503.  
  3504.   Packet.AddInt2(ID);
  3505.   Packet.AddInt1(X);
  3506.   Packet.AddInt1(Y);
  3507.   Packet.AddInt1(D);
  3508.   Packet.AddInt1(0);
  3509.  
  3510.   Server.SendRanged(Packet, X, Y);
  3511.  
  3512.   Result := True;
  3513. end;{Server.TSession.Sit}
  3514.  
  3515. function Server.TSession.Stand: Boolean;
  3516. var
  3517.   Packet: TPacket;
  3518. begin
  3519.   if not LoggedIn then exit(False);
  3520.  
  3521.   if Sitting = SittingStand then exit(False);
  3522.  
  3523.   Sitting := SittingStand;
  3524.  
  3525.   if Offline then exit(True);
  3526.  
  3527.   Packet.SetID(PacketFamilySit, PacketActionRemove);
  3528.  
  3529.   Packet.AddInt2(ID);
  3530.   Packet.AddInt1(X);
  3531.   Packet.AddInt1(Y);
  3532.  
  3533.   Server.SendRanged(Packet, X, Y);
  3534.  
  3535.   Result := True;
  3536. end;{Server.TSession.Stand}
  3537.  
  3538. function Server.TSession.Emote(EmoteID: Integer; SendToSelf: Boolean = False): Boolean;
  3539. var
  3540.   Packet: TPacket;
  3541. begin
  3542.   if (not LoggedIn) or Offline then exit(False);
  3543.  
  3544.   Packet.SetID(PacketFamilyEmote, PacketActionPlayer);
  3545.   Packet.AddInt2(ID);
  3546.   Packet.AddInt1(EmoteID);
  3547.  
  3548.   if SendToSelf then Send(Packet);
  3549.   Server.Send(Packet, Self);
  3550.  
  3551.   Result := True;
  3552. end;{Server.TSession.Emote}
  3553.  
  3554. function Server.TSession.Status(Msg: AnsiString): Boolean;
  3555. var
  3556.   Packet: TPacket;
  3557. begin
  3558.   if (not LoggedIn) or Offline then exit(False);
  3559.  
  3560.   Packet.SetID(PacketFamilyMessage, PacketActionOpen);
  3561.   Packet.AddString(Msg);
  3562.  
  3563.   Send(Packet);
  3564.  
  3565.   Result := True;
  3566. end;{Server.TSession.Status}
  3567.  
  3568. function Server.TSession.Mute(From: AnsiString = 'Server'): Boolean;
  3569. var
  3570.   Packet: TPacket;
  3571. begin
  3572.   if (not LoggedIn) or Offline then exit(False);
  3573.  
  3574.   Packet.SetID(PacketFamilyTalk, PacketActionSpecial);
  3575.   Packet.AddString(From);
  3576.  
  3577.   Send(Packet);
  3578.  
  3579.   Result := True;
  3580. end;{Server.TSession.Mute}
  3581.  
  3582. function Server.TSession.Freeze: Boolean;
  3583. var
  3584.   Packet: TPacket;
  3585. begin
  3586.   if (not LoggedIn) or Offline then exit(False);
  3587.  
  3588.   Packet.SetID(PacketFamilyWalk, PacketActionClose);
  3589.  
  3590.   Send(Packet);
  3591.  
  3592.   Result := True;
  3593. end;{Server.TSession.Freeze}
  3594.  
  3595. function Server.TSession.Unfreeze: Boolean;
  3596. var
  3597.   Packet: TPacket;
  3598. begin
  3599.   if (not LoggedIn) or Offline then exit(False);
  3600.  
  3601.   Packet.SetID(PacketFamilyWalk, PacketActionOpen);
  3602.  
  3603.   Send(Packet);
  3604.  
  3605.   Result := True;
  3606. end;{Server.TSession.Unfreeze}
  3607.  
  3608. function Server.TSession.Effect(EffectID: Integer; SendToSelf: Boolean = False): Boolean;
  3609. var
  3610.   Packet: TPacket;
  3611. begin
  3612.   if (not LoggedIn) or Offline then exit(False);
  3613.  
  3614.   Packet.SetID(PacketFamilyEffect, PacketActionPlayer);
  3615.   Packet.AddInt2(ID);
  3616.   Packet.AddInt2(EffectID);
  3617.   Packet.AddInt1(0);
  3618.  
  3619.   if SendToSelf then Send(Packet);
  3620.   Server.Send(Packet, Self);
  3621.  
  3622.   Result := True;
  3623. end;{Server.TSession.Effect}
  3624.  
  3625. function Server.TSession.Drunk(Scale: Integer): Boolean;
  3626. var
  3627.   Packet: TPacket;
  3628. begin
  3629.   if (not LoggedIn) or Offline then exit(False);
  3630.  
  3631.   Packet.SetID(PacketFamilyItem, PacketActionReply);
  3632.   Packet.AddInt1(Server.TItemData.ItemTypeSoda);
  3633.   Packet.AddInt2(0);
  3634.   Packet.AddInt4(0);
  3635.   Packet.AddInt1(0);
  3636.   Packet.AddInt1(50);
  3637.  
  3638.   Send(Packet);
  3639.  
  3640.   Result  := True;
  3641. end;{Server.TSession.Drunk}
  3642.  
  3643. function Server.TSession.Quake(Scale: Integer): Boolean;
  3644. var
  3645.   Packet: TPacket;
  3646. begin
  3647.   if (not LoggedIn) or Offline then exit(False);
  3648.  
  3649.   Packet.SetID(PacketFamilyEffect, PacketActionUse);
  3650.   Packet.AddInt1(1);
  3651.   Packet.AddInt1(Scale);
  3652.  
  3653.   Send(Packet);
  3654.  
  3655.   Result := True;
  3656. end;{Server.TSession.Quake}
  3657.  
  3658. function Server.TSession.HelloHax0r: Boolean;
  3659. var
  3660.   Packet: TPacket;
  3661. begin
  3662.   if (not LoggedIn) or Offline then exit(False);
  3663.  
  3664.   Packet.SetID(PacketFamilyUpdate, PacketActionList);
  3665.  
  3666.   Packet.AddInt2(0);
  3667.   Packet.AddInt2($FFFF);
  3668.   Packet.AddInt2($FFFF);
  3669.   Packet.AddInt2($FFFF);
  3670.   Packet.AddInt2($FFFF);
  3671.   Packet.AddInt2($FFFF);
  3672.   Packet.AddInt2($FFFF);
  3673.   Packet.AddInt2($FFFF);
  3674.   Packet.AddInt2($FFFF);
  3675.   Packet.AddInt2($FFFF);
  3676.   Packet.AddInt2($FFFF);
  3677.   Packet.AddInt2($FFFF);
  3678.   Packet.AddInt2($FFFF);
  3679.   Packet.AddInt2($FFFF);
  3680.   Packet.AddInt2($FFFF);
  3681.   Packet.AddInt2($FFFF);
  3682.  
  3683.   Send(Packet);
  3684.  
  3685.   Disconnect;
  3686.  
  3687.   Result := True;
  3688. end;{Server.TSession.Drunk}
  3689.  
  3690. function Server.TSession.Show: Boolean;
  3691. var
  3692.   Packet: TPacket;
  3693. begin
  3694.   if not LoggedIn then exit(False);
  3695.  
  3696.   Result := True;
  3697.  
  3698.   if Hidden = 0 then exit;
  3699.   Hidden := 0;
  3700.  
  3701.   if Offline then exit;
  3702.  
  3703.   Packet.SetID(PacketFamilyAdmin, PacketActionAgree);
  3704.   Packet.AddInt2(ID);
  3705.  
  3706.   Server.SendRanged(Packet, X, Y);
  3707. end;{Server.TSession.Show}
  3708.  
  3709. function Server.TSession.Hide: Boolean;
  3710. var
  3711.   Packet: TPacket;
  3712. begin
  3713.   if not LoggedIn then exit(False);
  3714.  
  3715.   Result := True;
  3716.  
  3717.   if Hidden = 1 then exit;
  3718.   Hidden := 1;
  3719.  
  3720.   if Offline then exit;
  3721.  
  3722.   Packet.SetID(PacketFamilyAdmin, PacketActionRemove);
  3723.   Packet.AddInt2(ID);
  3724.  
  3725.   Server.SendRanged(Packet, X, Y);
  3726. end;{Server.TSession.Hide}
  3727.  
  3728. function Server.TSession.Sound(SoundID: Integer): Boolean;
  3729. var
  3730.   Packet: TPacket;
  3731. begin
  3732.   if (not LoggedIn) or Offline then exit(False);
  3733.  
  3734.   Packet.SetID(PacketFamilySound, PacketActionPlayer);
  3735.   Packet.AddInt2(SoundID);
  3736.  
  3737.   Send(Packet);
  3738.  
  3739.   Result := True;
  3740. end;{Server.TSession.Sound}
  3741.  
  3742. function Server.TSession.Ban: Boolean;
  3743. begin
  3744.   if not LoggedIn then exit(False);
  3745.  
  3746.   Banned := 1;
  3747.  
  3748.   if not Offline then Disconnect;
  3749.  
  3750.   Result := True;
  3751. end;{Server.TSession.Ban}
  3752.  
  3753. function Server.TSession.UnBan: Boolean;
  3754. begin
  3755.   if not LoggedIn then exit(False);
  3756.  
  3757.   Banned := 0;
  3758.  
  3759.   Result := True;
  3760. end;{Server.TSession.UnBan}
  3761.  
  3762. function Server.TSession.Sleep: Boolean;
  3763. var
  3764.   Packet: TPacket;
  3765. begin
  3766.   if (not LoggedIn) or Offline then exit(False);
  3767.  
  3768.   Packet.SetID(PacketFamilyInnKeeper, PacketActionAccept);
  3769.   Packet.AddInt4(0);
  3770.  
  3771.   Send(Packet);
  3772.  
  3773.   Result := True;
  3774. end;{Server.TSession.Sleep}
  3775.  
  3776. function Server.TSession.Barber: Boolean;
  3777. var
  3778.   Packet: TPacket;
  3779. begin
  3780.   if (not LoggedIn) or Offline then exit(False);
  3781.  
  3782.   Packet.SetID(PacketFamilyBarber, PacketActionOpen);
  3783.   Packet.AddInt4(0);
  3784.  
  3785.   Send(Packet);
  3786.  
  3787.   Result := True;
  3788. end;{Server.TSession.Barber}
  3789.  
  3790. function Server.TSession.SetGold(Value: Integer): Boolean;
  3791. var
  3792.   OldGold: Integer;
  3793.   Packet: TPacket;
  3794. begin
  3795.   if not LoggedIn then exit(False);
  3796.  
  3797.   OldGold := Gold;
  3798.  
  3799.   Gold := Value;
  3800.   if Gold < 0 then
  3801.     Gold := 0
  3802.   else if Gold > MaxGold then
  3803.     Gold := MaxGold;
  3804.  
  3805.   Result := True;
  3806.  
  3807.   if Offline then exit;
  3808.  
  3809.   OldGold := Gold - OldGold;
  3810.   if OldGold = 0 then exit;
  3811.  
  3812.   if OldGold > 0 then
  3813.   begin
  3814.     Packet.SetID(PacketFamilyItem, PacketActionGet);
  3815.     Packet.AddInt2(0);
  3816.     Packet.AddInt2(GoldID);
  3817.     Packet.AddInt3(OldGold);
  3818.     Packet.AddInt1(0);//Weight
  3819.     Packet.AddInt1(50);//MaxWeight
  3820.   end{if OldGold}
  3821.   else
  3822.   begin
  3823.     Packet.SetID(PacketFamilyItem, PacketActionJunk);
  3824.     Packet.AddInt2(GoldID);
  3825.     Packet.AddInt3(OldGold);
  3826.     Packet.AddInt4(Gold);
  3827.     Packet.AddInt1(0);//Weight
  3828.     Packet.AddInt1(50);//MaxWeight
  3829.   end;{else}
  3830.  
  3831.   Send(Packet);
  3832. end;{Server.TSession.SetGold}
  3833.  
  3834. function Server.TSession.Damage(Amount: Integer; By: TSession): Boolean;
  3835. var
  3836.   Packet: TPacket;
  3837. begin
  3838.   if not LoggedIn then exit(False);
  3839.  
  3840.   HP := HP - abs(Amount);
  3841.   if HP < 0 then HP := 0;
  3842.  
  3843.   Result := True;
  3844.  
  3845.   if not Offline then
  3846.   begin
  3847.     Packet.SetID(PacketFamilyAppearance, PacketActionReply);
  3848.  
  3849.     Packet.AddInt2(0);
  3850.     Packet.AddInt2(ID);
  3851.     Packet.AddInt3(abs(Amount));
  3852.     Packet.AddInt1(0);//Level
  3853.     Packet.AddInt1(round((HP / MaxHP) * 100));
  3854.     if HP = 0 then Packet.AddInt1(1) else Packet.AddInt1(0);
  3855.  
  3856.     Send(Packet);
  3857.     Server.Send(Packet, Self);
  3858.  
  3859.     UpdateHPTP;
  3860.   end;{if not Offline}
  3861.  
  3862.   if HP = 0 then Die(By);
  3863. end;{Server.TSession.Damage}
  3864.  
  3865. function Server.TSession.SetHP(Value: Integer): Boolean;
  3866. begin
  3867.   if not LoggedIn then exit(False);
  3868.  
  3869.   HP := Value;
  3870.   if HP < 0 then HP := 0 else if HP > MaxHP then HP := MaxHP;
  3871.  
  3872.   UpdateHPTP;
  3873.  
  3874.   Result := True;
  3875. end;{Server.TSession.SetHP}
  3876.  
  3877. function Server.TSession.SetTP(Value: Integer): Boolean;
  3878. begin
  3879.   if not LoggedIn then exit(False);
  3880.  
  3881.   TP := Value;
  3882.   if TP < 0 then TP := 0 else if TP > MaxTP then TP := MaxTP;
  3883.  
  3884.   UpdateHPTP;
  3885.  
  3886.   Result := True;
  3887. end;{Server.TSession.SetTP}
  3888.  
  3889. function Server.TSession.SetMaxHP(Value: Integer): Boolean;
  3890. begin
  3891.   if not LoggedIn then exit(False);
  3892.  
  3893.   MaxHP := Value;
  3894.   if MaxHP < 1 then MaxHP := 1;
  3895.   if HP > MaxHP then HP := MaxHP;
  3896.  
  3897.   UpdateStats;
  3898.  
  3899.   Result := True;
  3900. end;{Server.TSession.SetTP}
  3901.  
  3902. function Server.TSession.SetMaxTP(Value: Integer): Boolean;
  3903. begin
  3904.   if not LoggedIn then exit(False);
  3905.  
  3906.   MaxTP := Value;
  3907.   if MaxTP < 0 then MaxTP := 0;
  3908.   if TP > MaxTP then TP := MaxTP;
  3909.  
  3910.   UpdateStats;
  3911.  
  3912.   Result := True;
  3913. end;{Server.TSession.SetTP}
  3914.  
  3915. function Server.TSession.UpdateHPTP: Boolean;
  3916. var
  3917.   Packet: TPacket;
  3918. begin
  3919.   if (not LoggedIn) or Offline then exit(False);
  3920.  
  3921.   Packet.SetID(PacketFamilyUpdate, PacketActionPlayer);
  3922.   Packet.AddInt2(HP);
  3923.   Packet.AddInt2(TP);
  3924.  
  3925.   Send(Packet);
  3926.  
  3927.   if Party <> nil then
  3928.     Party.Update(Self);
  3929.  
  3930.   Result := True;
  3931. end;{Server.TSession.UpdateHPTP}
  3932.  
  3933. function Server.TSession.UpdateStats: Boolean;
  3934. var
  3935.   Packet: TPacket;
  3936. begin
  3937.   if (not LoggedIn) or Offline then exit(False);
  3938.  
  3939.   Packet.SetID(PacketFamilySkill, PacketActionPlayer);
  3940.  
  3941.   Packet.AddInt2(0); //statpoints
  3942.   Packet.AddInt2(0); //str
  3943.   Packet.AddInt2(0); //int
  3944.   Packet.AddInt2(0); //wis
  3945.   Packet.AddInt2(0); //agi
  3946.   Packet.AddInt2(0); //con
  3947.   Packet.AddInt2(0); //cha
  3948.   Packet.AddInt2(MaxHP);
  3949.   Packet.AddInt2(MaxTP);
  3950.   Packet.AddInt2(0); //max sp
  3951.   Packet.AddInt2(50);//max weight
  3952.   Packet.AddInt2(0); //min damage
  3953.   Packet.AddInt2(0); //max damage
  3954.   Packet.AddInt2(0); //accuracy
  3955.   Packet.AddInt2(0); //evade
  3956.   Packet.AddInt2(0); //armour
  3957.  
  3958.   Send(Packet);
  3959.  
  3960.   if Party <> nil then
  3961.     Party.Update(Self);
  3962.  
  3963.   Result := True;
  3964. end;{Server.TSession.UpdateStats}
  3965.  
  3966. function Server.TSession.Die(By: TSession): Boolean;
  3967. var
  3968.   Packet: TPacket;
  3969. begin
  3970.   if not LoggedIn then exit(False);
  3971.  
  3972.   if By <> nil then
  3973.   begin
  3974.     Server.CriticalSection.Section(procedure
  3975.     begin
  3976.       By.Kills := By.Kills + 1;
  3977.     end);{CriticalSection}
  3978.  
  3979.     Packet.SetID(PacketFamilyArena, PacketActionSpecial);
  3980.     Packet.AddInt2(0);
  3981.     Packet.AddByte(255);
  3982.     Packet.AddInt1(0);
  3983.     Packet.AddByte(255);
  3984.     Packet.AddInt2(By.Kills);
  3985.     Packet.AddInt1(0);
  3986.     Packet.AddByte(255);
  3987.     Packet.AddBreakString(Capitalize(By.Name));
  3988.     Packet.AddBreakString(Capitalize(Name));
  3989.  
  3990.     Server.Send(Packet);
  3991.   end;{if By <> nil}
  3992.  
  3993.   Resurrect;
  3994.  
  3995.   Result := True;
  3996. end;{Server.TSession.Die}
  3997.  
  3998. function Server.TSession.Resurrect: Boolean;
  3999. begin
  4000.   if not LoggedIn then exit(False);
  4001.  
  4002.   HP := MaxHP;
  4003.   Warp(Server.Defaults.X, Server.Defaults.Y, 0);
  4004.   UpdateHPTP;
  4005.  
  4006.   Result := True;
  4007. end;{Server.TSession.Resurrect}
  4008.  
  4009. function Server.TSession.RaceDialog: Boolean;
  4010. const
  4011.   RaceNames: array[0..5] of AnsiString = ('Fair', 'Dark', 'Light', 'Orc', 'Skeleton', 'Panda');
  4012. var
  4013.   i:      Integer;
  4014.   Packet: TPacket;
  4015. begin
  4016.   if (not LoggedIn) or Offline then exit(False);
  4017.  
  4018.   Packet.SetID(PacketFamilyQuest, PacketActionDialog);
  4019.  
  4020.   Packet.AddInt1(1);
  4021.  
  4022.   Packet.AddInt2(0);
  4023.   Packet.AddInt2(0);
  4024.  
  4025.   Packet.AddInt4(CustomRaceID);
  4026.   Packet.AddByte(255);
  4027.  
  4028.   Packet.AddInt2(0);
  4029.   Packet.AddString(CustomTitle);
  4030.   Packet.AddByte(255);
  4031.  
  4032.   Packet.AddInt2(1);
  4033.   Packet.AddString('Select a race:');
  4034.   Packet.AddByte(255);
  4035.  
  4036.   for i := 0 to high(RaceNames) do
  4037.   begin
  4038.     Packet.AddInt2(2);
  4039.     Packet.AddInt2(i + 1);
  4040.     Packet.AddString(RaceNames[i]);
  4041.     Packet.AddByte(255);
  4042.   end;{for i}
  4043.  
  4044.   Send(Packet);
  4045.  
  4046.   Result := True;
  4047. end;{of Server.TSession.RaceDialog}
  4048.  
  4049. function Server.TSession.SexDialog: Boolean;
  4050. const
  4051.   GenderNames: array[0..1] of AnsiString = ('Female', 'Male');
  4052. var
  4053.   i:      Integer;
  4054.   Packet: TPacket;
  4055. begin
  4056.   if (not LoggedIn) or Offline then exit(False);
  4057.  
  4058.   Packet.SetID(PacketFamilyQuest, PacketActionDialog);
  4059.  
  4060.   Packet.AddInt1(1);
  4061.  
  4062.   Packet.AddInt2(0);
  4063.   Packet.AddInt2(0);
  4064.  
  4065.   Packet.AddInt4(CustomSexID);
  4066.   Packet.AddByte(255);
  4067.  
  4068.   Packet.AddInt2(0);
  4069.   Packet.AddString(CustomTitle);
  4070.   Packet.AddByte(255);
  4071.  
  4072.   Packet.AddInt2(1);
  4073.   Packet.AddString('Select a gender:');
  4074.   Packet.AddByte(255);
  4075.  
  4076.   for i := 0 to high(GenderNames) do
  4077.   begin
  4078.     Packet.AddInt2(2);
  4079.     Packet.AddInt2(i + 1);
  4080.     Packet.AddString(GenderNames[i]);
  4081.     Packet.AddByte(255);
  4082.   end;{for i}
  4083.  
  4084.   Send(Packet);
  4085.  
  4086.   Result := True;
  4087. end;{of Server.TSession.SexDialog}
  4088.  
  4089. function Server.TSession.ReceivePM(From, Text: AnsiString): Boolean;
  4090. var
  4091.   Packet: TPacket;
  4092. begin
  4093.   if (not LoggedIn) or Offline then exit(False);
  4094.  
  4095.   Packet.SetID(PacketFamilyTalk, PacketActionTell);
  4096.   Packet.AddBreakString(From);
  4097.   Packet.AddBreakString(copy(Text, 1, Server.TextLength));
  4098.  
  4099.   Send(Packet);
  4100.   Result := True;
  4101. end;{Server.TSession.ReceivePM}
  4102.  
  4103. function Server.TSession.SendPM(SendTo, Text: AnsiString): Boolean;
  4104. var
  4105.   Session: TSession;
  4106.   Packet:  TPacket;
  4107. begin
  4108.   if not LoggedIn then exit(False);
  4109.  
  4110.   Server.CriticalSection.Enter;
  4111.   try
  4112.     Session := Server.GetSessionByName(SendTo);
  4113.     if (Session = nil) or not Session.LoggedIn then
  4114.     begin
  4115.       if Offline then exit(False);
  4116.  
  4117.       Packet.SetID(PacketFamilyTalk, PacketActionReply);
  4118.       Packet.AddInt2(1);
  4119.       Packet.AddString(SendTo);
  4120.  
  4121.       Send(Packet);
  4122.  
  4123.       Result := False;
  4124.     end{if Session = nil}
  4125.     else
  4126.     begin
  4127.       Session.ReceivePM(Name, Text);
  4128.  
  4129.       Result := True;
  4130.     end;{else}
  4131.   finally
  4132.     Server.CriticalSection.Leave;
  4133.   end;{try...finally}
  4134. end;{Server.TSession.SendPM}
  4135.  
  4136. function Server.TSession.Attack(Direction: Integer; SendToSelf: Boolean = False): Boolean;
  4137. var
  4138.   i:       Integer;
  4139.   ax, ay:  Integer;
  4140.   Packet:  TPacket;
  4141.   Range:   Integer;
  4142.   Victim:  TSession;
  4143.   Session: TSession;
  4144. begin
  4145.   if (not LoggedIn) or Offline then exit(False);
  4146.  
  4147.   if (Direction < 0) or (Direction > 3) or (Sitting <> SittingStand) then exit(False);
  4148.  
  4149.   Packet.SetID(PacketFamilyAttack, PacketActionPlayer);
  4150.   Packet.AddInt2(ID);
  4151.   Packet.AddInt1(Direction);
  4152.  
  4153.   if SendToSelf then Send(Packet);
  4154.   Server.Send(Packet, Self);
  4155.  
  4156.   ax := X;
  4157.   ay := Y;
  4158.  
  4159.   D := Direction;
  4160.  
  4161.   Range  := 1;//Server.ViewRange;
  4162.   Victim := nil;
  4163.  
  4164.   Server.CriticalSection.Enter;
  4165.   try
  4166.     for i := 0 to Range - 1 do
  4167.     begin
  4168.       case Direction of
  4169.         DirectionDown:  inc(ay);
  4170.         DirectionLeft:  dec(ax);
  4171.         DirectionUp:    dec(ay);
  4172.         DirectionRight: inc(ax);
  4173.       end;{case Direction}
  4174.  
  4175.       for Session in Server.Sessions.Items do
  4176.         if (Session <> Self) and Session.LoggedIn and
  4177.            (Session.X = ax) and (Session.Y = ay) and
  4178.            (Server.MapData.Tiles[ay, ax].Kind = TMapData.MapTileArena) and
  4179.            (Server.MapData.Tiles[Y, X].  Kind = TMapData.MapTileArena) and
  4180.            (Session.HP > 0) then
  4181.         begin
  4182.           Victim := Session;
  4183.           break;
  4184.         end;{if (Session <> Self...}
  4185.  
  4186.       if (Victim <> nil) or (not Server.MapData.IsWalkable(ax, ay, True)) then
  4187.       begin
  4188.         //Server.Effect(31, ax, ay);
  4189.         break;
  4190.       end{if (Victim <> nil...}
  4191.       //else
  4192.       //  Server.Effect(29, ax, ay);
  4193.     end;{for i}
  4194.  
  4195.     if Victim <> nil then Victim.Attacked(Self);
  4196.   finally
  4197.     Server.CriticalSection.Leave;
  4198.   end;{try...finally}
  4199.  
  4200.   Result := True;
  4201. end;{Server.TSession.Attack}
  4202.  
  4203. procedure Server.TSession.Attacked(By: TSession);
  4204. begin
  4205.   if not LoggedIn then exit;
  4206.  
  4207.   Damage(1, By);
  4208. end;{Server.TSession.Attacked}
  4209.  
  4210. function Server.TSession.DoCommand(Cmd: AnsiString; Sender: TSession = nil): Boolean;
  4211. var
  4212.   Param:  AnsiString;
  4213.   S:      AnsiString;
  4214.   A, B:   Integer;
  4215.   SysCmd: Boolean;
  4216.  
  4217.   function CheckPermission(Level: Integer): Boolean;
  4218.   begin
  4219.     if SysCmd then exit(True);
  4220.     if Sender.IPInt = localhost then exit(True);
  4221.  
  4222.     Result := Sender.Admin >= Level;
  4223.     if Sender <> Self then Result := Result and (Sender.Admin > Self.Admin);
  4224.  
  4225.     if not Result then
  4226.       Sender.Status('You do not have permission to perform this command');
  4227.   end;{CheckPermission}
  4228.  
  4229.   function Alter(Param: AnsiString; Value: Integer): Integer;
  4230.   begin
  4231.     if length(Param) = 0 then exit(Value);
  4232.  
  4233.     if Param[1] = '+' then
  4234.       Result := Value + abs(Int(copy(Param, 2, length(Param))))
  4235.     else if Param[1] = '-' then
  4236.       Result := Value - abs(Int(copy(Param, 2, length(Param))))
  4237.     else
  4238.       Result := Int(Param, Value);
  4239.   end;{Alter}
  4240. begin
  4241.   SysCmd := Sender = nil;
  4242.   if SysCmd then Sender := Self;
  4243.  
  4244. {$IFDEF LOG_COMMANDS}
  4245.   Log(['Command "', Cmd, '" from ', Sender.Name]);
  4246. {$ENDIF LOG_COMMANDS}
  4247.  
  4248.   Param := Cmd;
  4249.   Cmd   := Split(Param, ' ');
  4250.  
  4251.   Result := True;
  4252.  
  4253.   if length(Cmd) = 0 then
  4254.  
  4255.   else if (Cmd = 'tag')        and CheckPermission(Server.Admin.Level.Appearance) then begin Tag := copy(Param, 1, 3); Refresh; end
  4256.   else if (Cmd = 'sex')        and CheckPermission(Server.Admin.Level.Appearance) then begin A := Int(Param, -1); if A = -1 then SexDialog  else if A in [0..1] then begin Sex  := Int(Param); State := State or StateSexSelected;  Refresh; if (State and StateRaceSelected) = 0 then RaceDialog; end; end
  4257.   else if (Cmd = 'race')       and CheckPermission(Server.Admin.Level.Appearance) then begin A := Int(Param, -1); if A = -1 then RaceDialog else if A in [0..5] then begin Race := Int(Param); State := State or StateRaceSelected; Refresh; if (State and StateHairSelected) = 0 then Barber;     end; end
  4258.   else if (Cmd = 'haircolour') and CheckPermission(Server.Admin.Level.Appearance) then begin HairColour := Int(Param, HairColour); Refresh; end
  4259.   else if (Cmd = 'hairstyle')  and CheckPermission(Server.Admin.Level.Appearance) then begin HairStyle  := Int(Param, HairStyle);  Refresh; end
  4260.   else if (Cmd = 'barber')     and CheckPermission(Server.Admin.Level.Appearance) then Barber
  4261.  
  4262.   else if (Cmd = 'armour')     and CheckPermission(Server.Admin.Level.Item) then begin Armour := Int(Param, Armour); Refresh; end
  4263.   else if (Cmd = 'hat')        and CheckPermission(Server.Admin.Level.Item) then begin Hat    := Int(Param, Hat);    Refresh; end
  4264.   else if (Cmd = 'boots')      and CheckPermission(Server.Admin.Level.Item) then begin Boots  := Int(Param, Boots);  Refresh; end
  4265.   else if (Cmd = 'weapon')     and CheckPermission(Server.Admin.Level.Item) then begin Weapon := Int(Param, Weapon); Refresh; end
  4266.   else if (Cmd = 'shield')     and CheckPermission(Server.Admin.Level.Item) then begin Shield := Int(Param, Shield); Refresh; end
  4267.  
  4268.   else if (Cmd = 'gold')  and CheckPermission(Server.Admin.Level.Item) then SetGold(Alter(Param, Gold))
  4269.   else if (Cmd = 'kills') and CheckPermission(Server.Admin.Level.Item) then Kills := Alter(Param, Kills)
  4270.  
  4271.   else if (Cmd = 'save')       and CheckPermission(0) then Sync
  4272.   else if (Cmd = 'disconnect') and CheckPermission(0) then Disconnect
  4273.   else if (Cmd = 'refresh')    and CheckPermission(0) then Refresh
  4274.  
  4275.   else if (Cmd = 'warp')and CheckPermission(Server.Admin.Level.Action) then
  4276.   begin
  4277.     if length(Param) = 0 then
  4278.       Warp(Sender.X, Sender.Y, WarpAnimationBubbles)
  4279.     else if pos(String(Param[1]), '0123456789') > 0 then
  4280.     begin
  4281.       A := Alter(Split(Param), X);
  4282.       B := Alter(Split(Param), Y);
  4283.       Warp(A, B, Int(Param, WarpAnimationBubbles))
  4284.     end{else if pos...}
  4285.     else
  4286.     begin
  4287.       S := lower(Split(Param));
  4288.  
  4289.       Server.CriticalSection.Enter;
  4290.       try
  4291.         Sender := Server.GetSessionByName(S);
  4292.         if (Sender = nil) or (not Sender.LoggedIn) then exit;
  4293.  
  4294.         Warp(Sender.X, Sender.Y, Int(Param, WarpAnimationBubbles));
  4295.       finally
  4296.         Server.CriticalSection.Leave;
  4297.       end;{try...finally}
  4298.     end;{else}
  4299.   end{Warp}
  4300.  
  4301.   else if (Cmd = 'damage')   and CheckPermission(Server.Admin.Level.Action) then Damage(Int(Param, 1), Sender)
  4302.   else if (Cmd = 'die')      and CheckPermission(Server.Admin.Level.Action) then Die(Sender)
  4303.   else if (Cmd = 'hp')       and CheckPermission(Server.Admin.Level.Action) then SetHP(Alter(Param, HP))
  4304.   else if (Cmd = 'tp')       and CheckPermission(Server.Admin.Level.Action) then SetTP(Alter(Param, TP))
  4305.   else if (Cmd = 'maxhp')    and CheckPermission(Server.Admin.Level.Action) then SetMaxHP(Alter(Param, MaxHP))
  4306.   else if (Cmd = 'maxtp')    and CheckPermission(Server.Admin.Level.Action) then SetMaxTP(Alter(Param, MaxTP))
  4307.   else if (Cmd = 'attacked') and CheckPermission(Server.Admin.Level.Action) then Attacked(Sender)
  4308.   else if (Cmd = 'say')      and CheckPermission(Server.Admin.Level.Action) then Say(Param, True)
  4309.   else if (Cmd = 'sit')      and CheckPermission(Server.Admin.Level.Action) then Sit(Bool(Param))
  4310.   else if (Cmd = 'stand')    and CheckPermission(Server.Admin.Level.Action) then Stand
  4311.   else if (Cmd = 'walk')     and CheckPermission(Server.Admin.Level.Action) then Walk(Int(Param, D), False, False, True)
  4312.   else if (Cmd = 'face')     and CheckPermission(Server.Admin.Level.Action) then Face(Int(Param, D), True)
  4313.   else if (Cmd = 'attack')   and CheckPermission(Server.Admin.Level.Action) then Attack(Int(Param, D), True)
  4314.   else if (Cmd = 'emote')    and CheckPermission(Server.Admin.Level.Action) then Emote(Int(Param), True)
  4315.   else if (Cmd = 'status')   and CheckPermission(Server.Admin.Level.Action) then Status(Param)
  4316.   else if (Cmd = 'drunk')    and CheckPermission(Server.Admin.Level.Action) then Drunk(Int(Param))
  4317.   else if (Cmd = 'effect')   and CheckPermission(Server.Admin.Level.Action) then Effect(Int(Param), True)
  4318.   else if (Cmd = 'quake')    and CheckPermission(Server.Admin.Level.Action) then Quake(Int(Param))
  4319.   else if (Cmd = 'hide')     and CheckPermission(Server.Admin.Level.Action) then Hide
  4320.   else if (Cmd = 'show')     and CheckPermission(Server.Admin.Level.Action) then Show
  4321.   else if (Cmd = 'sound')    and CheckPermission(Server.Admin.Level.Action) then Sound(Int(Param, 1))
  4322.   else if (Cmd = 'sleep')    and CheckPermission(Server.Admin.Level.Action) then Sleep
  4323.   else if (Cmd = 'unfreeze') and CheckPermission(Server.Admin.Level.Action) then Unfreeze
  4324.  
  4325.   else if (Cmd = 'freeze') and CheckPermission(Server.Admin.Level.Action) then
  4326.   begin
  4327.     S := Capitalize(Name) + ' was frozen by ' + Capitalize(Sender.Name);
  4328.     if length(Param) > 0 then S := S + ' [' + Param + '] ';
  4329.  
  4330.     Server.Msg(S);
  4331.  
  4332.     Freeze;
  4333.   end{'freeze'}
  4334.  
  4335.   else if (Cmd = 'mute') and CheckPermission(Server.Admin.Level.Action) then
  4336.   begin
  4337.     S := Capitalize(Name) + ' was muted by ' + Capitalize(Sender.Name);
  4338.     if length(Param) > 0 then S := S + ' [' + Param + '] ';
  4339.  
  4340.     Server.Msg(S);
  4341.  
  4342.     Mute(Sender.Name);
  4343.   end{'mute'}
  4344.  
  4345.   else if (Cmd = 'kick') and CheckPermission(Server.Admin.Level.Action) then
  4346.   begin
  4347.     S := Capitalize(Name) + ' was kicked by ' + Capitalize(Sender.Name);
  4348.     if length(Param) > 0 then S := S + ' [' + Param + '] ';
  4349.  
  4350.     Server.Msg(S);
  4351.  
  4352.     Disconnect;
  4353.   end{'kick'}
  4354.  
  4355.   else if (Cmd = 'ban') and CheckPermission(Server.Admin.Level.Action) then
  4356.   begin
  4357.     S := Capitalize(Name) + ' was banned by ' + Capitalize(Sender.Name);
  4358.     if length(Param) > 0 then S := S + ' [' + Param + '] ';
  4359.  
  4360.     Server.Msg(S);
  4361.  
  4362.     Ban;
  4363.   end{'ban'}
  4364.  
  4365.   else if (Cmd = 'unban') and CheckPermission(Server.Admin.Level.Action) then
  4366.   begin
  4367.     //S := Capitalize(Name) + ' was unbanned by ' + Capitalize(Sender.Name);
  4368.     //if length(Param) > 0 then S := S + ' [' + Param + '] ';
  4369.  
  4370.     //Server.Msg(S);
  4371.  
  4372.     UnBan;
  4373.   end{'unban'}
  4374.  
  4375.   else if (Cmd = 'ip') and CheckPermission(Server.Admin.Level.Action) then Sender.Status('IP Address of ' + Name + ':' + IPStr)
  4376.  
  4377.   else if (Cmd = 'log') and CheckPermission(1) then Log(['<', Sender.Name, '> "', Param, '"'])
  4378.  
  4379.   else if (Cmd = 'ipban') and CheckPermission(Server.Admin.Level.Maintenance) then
  4380.   begin
  4381.     if length(Param) > 0 then
  4382.       Server.BanIP(Param)
  4383.     else if Sender <> Self then
  4384.     begin
  4385.       Server.BanIP(IPStr);
  4386.       Disconnect;
  4387.     end
  4388.     else
  4389.       Status('Unable to ban own ip');
  4390.   end{'ipban'}
  4391.  
  4392.   else if (Cmd = 'ipunban') and CheckPermission(Server.Admin.Level.Maintenance) then Server.UnbanIP(Param)
  4393.  
  4394.   else if (Cmd = 'hellohax0r')  and CheckPermission(Server.Admin.Level.Maintenance) then HelloHax0r
  4395.   else if (Cmd = 'admin')       and CheckPermission(Server.Admin.Level.Maintenance) then Admin := Int(Param)
  4396.   else if (Cmd = 'halt')        and CheckPermission(Server.Admin.Level.Maintenance) then Error(['Halted by ', Sender.Name])
  4397.   else if (Cmd = 'sql')         and CheckPermission(Server.Admin.Level.Maintenance) then Server.Database.Query(Param)
  4398.   else if (Cmd = 'sync')        and CheckPermission(Server.Admin.Level.Maintenance) then begin Sync(Bool(Param, True)); Warp(X, Y); end
  4399.   else if (Cmd = 'servermsg')   and CheckPermission(Server.Admin.Level.Maintenance) then Server.Msg(Param + ' --' + Capitalize(Sender.Name))
  4400.   else if (Cmd = 'gfreeze')     and CheckPermission(Server.Admin.Level.Maintenance) then Server.Freeze(Self)
  4401.   else if (Cmd = 'gunfreeze')   and CheckPermission(Server.Admin.Level.Maintenance) then Server.Unfreeze
  4402.   else if (Cmd = 'gmute')       and CheckPermission(Server.Admin.Level.Maintenance) then Server.Mute(Self)
  4403.   else if (Cmd = 'gquake')      and CheckPermission(Server.Admin.Level.Maintenance) then Server.Quake(Int(Param))
  4404.   else if (Cmd = 'map')         and CheckPermission(Server.Admin.Level.Maintenance) then Server.SetMap(Param)
  4405.   else if (Cmd = 'mutate')      and CheckPermission(Server.Admin.Level.Maintenance) then Server.Mutate
  4406.   else if (Cmd = 'mapeffect')   and CheckPermission(Server.Admin.Level.Maintenance) then begin A := Int(Split(Param)); B := Int(Split(Param), X); Server.Effect(A, B, Int(Param, Y)); end
  4407.   else if (Cmd = 'gsound')      and CheckPermission(Server.Admin.Level.Maintenance) then Server.Sound(Int(Param, 1))
  4408.   else if (Cmd = 'shutdown')    and CheckPermission(Server.Admin.Level.Maintenance) then Server.Shutdown
  4409.  
  4410.   else if (Cmd = '_test') and CheckPermission(Server.Admin.Level.Maintenance) then _test(Param)
  4411.  
  4412.   else
  4413.   begin
  4414.     Sender.Status('Unknown command "' + cmd + '"');
  4415.     Result := False;
  4416.   end;{else}
  4417. end;{Server.TSession.DoCommand}
  4418.  
  4419. function Server.TSession.Execute: Boolean;
  4420.   procedure QueuePacket(Time: Cardinal);
  4421.   begin
  4422.     if length(Packet.Queue.Items) = PacketQueue.Size then
  4423.     begin
  4424.       Log(['Packet queue full']);
  4425.       Initialized := False;
  4426.       exit;
  4427.     end;{if length(Packet.Queue.Items}
  4428.  
  4429.     SetLength(Packet.Queue.Items, length(Packet.Queue.Items) + 1);
  4430.     Packet.Queue.Items[high(Packet.Queue.Items)] := Packet.Receive;
  4431.     Packet.Queue.Items[high(Packet.Queue.Items)].Time := Time;
  4432.   end;{QueuePacket}
  4433.  
  4434.   function UnqueuePacket: Boolean;
  4435.   begin
  4436.     if (length(Packet.Queue.Items) = 0) or (GetTickCount < Packet.Queue.Time) then exit(False);
  4437.  
  4438.     Result := True;
  4439.  
  4440.     Packet.Receive := Packet.Queue.Items[high(Packet.Queue.Items)];
  4441.     SetLength(Packet.Queue.Items, length(Packet.Queue.Items) - 1);
  4442.  
  4443.     Packet.Queue.Time   := GetTickCount + Packet.Receive.Time;
  4444.     Packet.Receive.Time := GetTickCount;
  4445.   end;{UnqueuePacket}
  4446. const
  4447.   BufSize = 1024;
  4448. var
  4449.   i:       Integer;
  4450.   Size:    Integer;
  4451.   ReadLen: Integer;
  4452.   ReadBuf: AnsiString;
  4453.   Time:    Cardinal;
  4454. begin
  4455.   //if Offline then exit(False);
  4456.  
  4457.   if (Socket = 0) or (recv(Socket, nil^, 0, MSG_OOB) = 0) then
  4458.   begin
  4459.     Log(['Connection dropped']);
  4460.     exit(False);
  4461.   end;{if (Socket = 0)..}
  4462.  
  4463.   Time := GetTickCount;
  4464.  
  4465.   if Time > Packet.Time then
  4466.   begin
  4467.     Log(['Connection timeout']);
  4468.     exit(False);
  4469.   end;{if Time > Packet.Time}
  4470.  
  4471.   if (WarpInfo.Time > 0) and (Time > WarpInfo.Time) then
  4472.   begin
  4473.     Log(['Ignored warp request']);
  4474.     exit(False);
  4475.   end;{if (WarpInfo.Time...}
  4476.  
  4477.   Packet.Queue.Active := UnqueuePacket;
  4478.  
  4479.   if not Packet.Queue.Active then
  4480.   begin
  4481.     if ioctlsocket(Socket, FIONREAD, i) = 0 then
  4482.     begin
  4483.       SetLength(ReadBuf, BufSize);
  4484.  
  4485.       repeat
  4486.         ReadLen := recv(Socket, ReadBuf[1], BufSize, 0);
  4487.         if ReadLen < 1 then break;
  4488.  
  4489.         InterlockedExchangeAdd64(Server.Connection.BytesIn, ReadLen);
  4490.  
  4491.         Packet.Buffer := Packet.Buffer + copy(ReadBuf, 1, ReadLen);
  4492.       until False;
  4493.  
  4494.       Server.UpdateCaption;
  4495.       Packet.Time := GetTickCount + Server.Connection.Timeout;
  4496.     end;{if ioctlsocket}
  4497.  
  4498.     if length(Packet.Buffer) < 2 then exit(True);
  4499.  
  4500.     Size := PackEOInt(ord(Packet.Buffer[1]), ord(Packet.Buffer[2]));
  4501.     if length(Packet.Buffer) < (Size + 2) then exit(True);
  4502.  
  4503.     Packet.Receive.Data := copy(Packet.Buffer, 3, Size);
  4504.     Packet.Buffer       := copy(Packet.Buffer, Size + 3, length(Packet.Buffer));
  4505.  
  4506.     if Size < 3 then exit(true);
  4507.  
  4508.     if Initialized then
  4509.     begin
  4510.       ReadBuf := '';
  4511.       i       := 1;
  4512.  
  4513.       while i <= length(Packet.Receive.Data) do
  4514.       begin
  4515.         ReadBuf := ReadBuf + AnsiChar(ord(Packet.Receive.Data[i]) xor $80);
  4516.         inc(i, 2);
  4517.       end;{while i <= length(Packet.Receive.Data)}
  4518.  
  4519.       dec(i);
  4520.       if Boolean(length(Packet.Receive.Data) mod 2) then dec(i, 2);
  4521.  
  4522.       repeat
  4523.         ReadBuf := ReadBuf + AnsiChar(ord(Packet.Receive.Data[i]) xor $80);
  4524.         dec(i, 2);
  4525.       until i <= 0;
  4526.  
  4527.       for i := 3 to length(Packet.Receive.Data) do
  4528.              if ReadBuf[i] = #128 then ReadBuf[i] := #0
  4529.         else if ReadBuf[i] = #0   then ReadBuf[i] := #128;
  4530.  
  4531.       Packet.Receive.Data := FoldData(ReadBuf, ReceiveKey);
  4532.     end;{if Initialized}
  4533.  
  4534.     Packet.Receive.Family := ord(Packet.Receive.Data[2]);
  4535.     Packet.Receive.Action := ord(Packet.Receive.Data[1]);
  4536.     Packet.Receive.Data   := copy(Packet.Receive.Data, 3, length(Packet.Receive.Data));
  4537.     Packet.Receive.Time   := GetTickCount;
  4538.  
  4539.     if Packet.Receive.Family <> PacketFamilyRaw then
  4540.     begin
  4541.       // Sequence
  4542.       Packet.Receive.GetByte;
  4543.     end;{if Packet.Receive.Family}
  4544.   end;{if not Packet.Queue.Active}
  4545.  
  4546.   Packet.Send.Reset;
  4547.   Packet.Send.SetID(Packet.Receive.Family, PacketActionReply);
  4548.  
  4549.   i := Packet.Receive.Family;
  4550.  
  4551.   if not Initialized then
  4552.   begin
  4553.     if Packet.Receive.Family = PacketFamilyPlayers then
  4554.     begin
  4555.       Log(['Remote player list request']);
  4556.       HandlePlayers(i);
  4557.  
  4558.       exit(False);
  4559.     end{if Packet.Receive.Action}
  4560.     else if Packet.Receive.Family <> PacketFamilyRaw then
  4561.     begin
  4562.       Log(['Packet before initialize']);
  4563.  
  4564.       exit(False);
  4565.     end;{else if Packet.Receive.Action}
  4566.   end;{if not Initialized}
  4567.  
  4568.   if (not PacketQueue.Enabled) or Packet.Queue.Active then
  4569.     Dispatch(i)
  4570.   else
  4571.     case Packet.Receive.Family of
  4572.       PacketFamilyWalk:    QueuePacket(PacketQueue.Walk);
  4573.       PacketFamilyAttack:  QueuePacket(PacketQueue.Attack);
  4574.       PacketFamilyFace:    QueuePacket(0);
  4575.       PacketFamilyPlayers: QueuePacket(100);
  4576.     else
  4577.       Dispatch(i)
  4578.     end;{case Packet.Receive.Family}
  4579.  
  4580.   Result := Initialized;
  4581. end;{Server.TSession.Execute}
  4582.  
  4583. procedure Server.TSession.DefaultHandler;
  4584. begin
  4585. {$IFDEF LOG_UNHANDLED_PACKET_FAMILY}
  4586.   Log(['Unhandled packet family ', Packet.Receive.Family]);
  4587. {$ENDIF LOG_UNHANDLED_PACKET_FAMILY}
  4588. end;{Server.TSession.DefaultHandler}
  4589.  
  4590. procedure Server.TSession.UnhandledAction(Name: AnsiString = '');
  4591. begin
  4592. {$IFDEF LOG_UNHANDLED_PACKET_ACTION}
  4593.   if length(Name) = 0 then Name := 'family (' + Str(Packet.Receive.Family) + ')';
  4594.   Log(['Unhandled ' + Name + ' action ', Packet.Receive.Action]);
  4595. {$ENDIF LOG_UNHANDLED_PACKET_ACTION}
  4596. end;{Server.TSession.UnhandledAction}
  4597.  
  4598. procedure Server.TSession.HandleRaw;
  4599.   function AuthClient(Auth: Integer): Integer;
  4600.   begin
  4601.     inc(Auth);
  4602.  
  4603.     Result := (Auth mod 11 + 1) * 119;
  4604.     if Result = 0 then exit;
  4605.  
  4606.     Result := 110905 + (Auth mod 9 + 1) * ((11092004 - Auth) mod Result) * 119 + Auth mod 2004;
  4607.   end;{AuthClient}
  4608. var
  4609.   Auth:   Integer;
  4610.   s1, s2: Byte;
  4611.   Ver:    array[0..2] of Byte;
  4612.   Seq:    Byte;
  4613. begin
  4614.   Packet.Send.SetID(PacketFamilyRaw, PacketActionRaw);
  4615.  
  4616.   Auth := Packet.Receive.GetInt3;
  4617.  
  4618.   Ver[0] := Packet.Receive.GetInt1;
  4619.   Ver[1] := Packet.Receive.GetInt1;
  4620.   Ver[2] := Packet.Receive.GetInt1;
  4621.  
  4622.   if (Ver[0] <> Server.RequiredVersion[0])
  4623.   or (Ver[1] <> Server.RequiredVersion[1])
  4624.   or (Ver[2] <> Server.RequiredVersion[2]) then
  4625.   begin
  4626.     Packet.Send.AddByte(1);
  4627.     Packet.Send.AddByte(Server.RequiredVersion[0] + 1);
  4628.     Packet.Send.AddByte(Server.RequiredVersion[1] + 1);
  4629.     Packet.Send.AddByte(Server.RequiredVersion[2] + 1);
  4630.  
  4631.     Log(['Invalid client version ', Ver[0], '.', Ver[1], '.', Ver[2]]);
  4632.  
  4633.     Send(True);
  4634.     exit;
  4635.   end;{if (Ver...}
  4636.  
  4637.   Packet.Receive.Discard(2);
  4638.   HDDSerial := Packet.Receive.GetString;
  4639.  
  4640.   //2 = ok
  4641.   //3 = ip permabanned
  4642.   //10 = some weird sound?
  4643.   Packet.Send.AddByte(2);
  4644.  
  4645.   Seq := 1 + Random(220);
  4646.  
  4647.   s1 := (Seq + 12) div 7;
  4648.   s2 := (Seq +  5) mod 7;
  4649.  
  4650.   Packet.Send.AddByte(s1);
  4651.   Packet.Send.AddByte(s2);
  4652.  
  4653.   Log(['Initialized']);// s1:' + Str(s1) + ' s2:' + Str(s2)]);
  4654.  
  4655.   Packet.Send.AddByte(Server.SendKey);
  4656.   Packet.Send.AddByte(Server.ReceiveKey);
  4657.  
  4658.   Packet.Send.AddInt2(ID);
  4659.  
  4660.   Packet.Send.AddInt3(AuthClient(Auth));
  4661.  
  4662.   Send(True);
  4663.  
  4664.   Initialized := True;
  4665. end;{Server.TSession.HandleRaw}
  4666.  
  4667. procedure Server.TSession.HandleConnection;
  4668.   procedure HandleConnectionAccept;
  4669.   begin
  4670.     SendData(Server.ItemData);
  4671.     SendData(Server.NPCData);
  4672.     SendData(Server.SpellData);
  4673.     SendData(Server.ClassData);
  4674.   end;{HandleConnectionAccept}
  4675. begin
  4676.   case Packet.Receive.Action of
  4677.     PacketActionAccept: HandleConnectionAccept;
  4678.   else
  4679.     UnhandledAction('connection');
  4680.   end;{case Packet.Receive.Action}
  4681. end;{Server.TSession.HandleConnection}
  4682.  
  4683. procedure Server.TSession.HandleAccount;
  4684. const
  4685.   AccountReplyAlreadyExists = 1;
  4686.   AccountReplyNotApproved   = 2;
  4687.   AccountReplyCreated       = 3;
  4688.   AccountReplyChangeFailed  = 5;
  4689.   AccountReplyChanged       = 6;
  4690.   AccountReplyContinue      = 1000;
  4691.  
  4692.   function CheckAccount(AccountName: AnsiString): Boolean;
  4693.   begin
  4694.     Result := True;
  4695.  
  4696.     if False{AccountsDisabled} then
  4697.  
  4698.     else if not Server.ValidName(AccountName, IPInt = localhost) then
  4699.     begin
  4700.       Packet.Send.AddInt2(AccountReplyNotApproved);
  4701.       Packet.Send.AddString('NO');
  4702.       Send;
  4703.     end{else if not Server.ValidName}
  4704.  
  4705.     else if Server.AccountExists(AccountName) then
  4706.     begin
  4707.       Packet.Send.AddInt2(AccountReplyAlreadyExists);
  4708.       Packet.Send.AddString('NO');
  4709.       Send;
  4710.     end{else if}
  4711.  
  4712.     else Result := False;
  4713.   end;{CheckAccount}
  4714.  
  4715.   procedure HandleAccountRequest;
  4716.   var
  4717.     AccountName: AnsiString;
  4718.   begin
  4719.     AccountName := Lower(Packet.Receive.GetString);
  4720.  
  4721.     if CheckAccount(AccountName) then exit;
  4722.  
  4723.     Packet.Send.AddInt2(AccountReplyContinue);
  4724.     Packet.Send.AddString('OK');
  4725.     Send;
  4726.   end;{HandleAccountRequest}
  4727.  
  4728.   procedure HandleAccountCreate;
  4729.   var
  4730.     AccountName: AnsiString;
  4731.   begin
  4732.     Packet.Receive.Discard(3);
  4733.     AccountName := Lower(Packet.Receive.GetBreakString);
  4734.  
  4735.     if CheckAccount(AccountName) then exit;
  4736.  
  4737.     Name     := AccountName;
  4738.     Password := TSHA256.HashStr(Packet.Receive.GetBreakString);
  4739.  
  4740.     {FullName     := }Packet.Receive.GetBreakString;
  4741.     {Location     := }Packet.Receive.GetBreakString;
  4742.     {EmailAddress := }Packet.Receive.GetBreakString;
  4743.     {ComputerName := }Packet.Receive.GetBreakString;
  4744.  
  4745.     if Packet.Receive.GetBreakString <> HDDSerial then
  4746.     begin
  4747.       Packet.Send.AddInt2(AccountReplyNotApproved);
  4748.       Packet.Send.AddString('NO');
  4749.       Send;
  4750.       exit;
  4751.     end;{if Packet.Receive.GetBreakString <> HDDSerial}
  4752.  
  4753.     Log(['Creating account']);
  4754.  
  4755.     X     := Server.Defaults.X;
  4756.     Y     := Server.Defaults.Y;
  4757.     D     := Server.Defaults.D;
  4758.     Gold  := Server.Defaults.Gold;
  4759.     HP    := Server.Defaults.HP;
  4760.     MaxHP := Server.Defaults.MaxHP;
  4761.     TP    := Server.Defaults.TP;
  4762.     MaxTP := Server.Defaults.MaxTP;
  4763.  
  4764.     Sync;
  4765.     Unload;
  4766.  
  4767.     Packet.Send.AddInt2(AccountReplyCreated);
  4768.     Packet.Send.AddString('OK');
  4769.     Send;
  4770.   end;{HandleAccountCreate}
  4771. begin
  4772.   if LoggedIn then exit;
  4773.  
  4774.   case Packet.Receive.Action of
  4775.     PacketActionRequest: HandleAccountRequest;
  4776.     PacketActionCreate:  HandleAccountCreate;
  4777.   else
  4778.     UnhandledAction('account');
  4779.   end;{case Packet.Receive.Action}
  4780. end;{Server.TSession.HandleAccount}
  4781.  
  4782. procedure Server.TSession.HandleLogin;
  4783. const
  4784.   LoginReplyUnknownUser     = 1;
  4785.   LoginReplyWrongPassword   = 2;
  4786.   LoginReplyOK              = 3;
  4787.   // 4 = clear input
  4788.   LoginReplyAlreadyLoggedIn = 5;
  4789.  
  4790.   procedure HandleLoginRequest;
  4791.   begin
  4792.     Server.CriticalSection.Section(procedure
  4793.     var
  4794.       User: AnsiString;
  4795.       Pass: AnsiString;
  4796.     begin
  4797.       User := Lower(Packet.Receive.GetBreakString);
  4798.       Pass := TSHA256.HashStr(Packet.Receive.GetBreakString);
  4799.  
  4800.       if GetSessionByName(User) <> nil then
  4801.       begin
  4802.         Unload;
  4803.  
  4804.         Packet.Send.AddInt2(LoginReplyAlreadyLoggedIn);
  4805.         Send;
  4806.  
  4807.         exit;
  4808.       end;{if GetSessionByName}
  4809.  
  4810.       Name := User;
  4811.  
  4812.       if not Sync(True) then
  4813.       begin
  4814.         Unload;
  4815.  
  4816.         Packet.Send.AddInt2(LoginReplyUnknownUser);
  4817.         Send;
  4818.       end{if not Sync(True)}
  4819.       else if Pass <> Password then
  4820.       begin
  4821.         Unload;
  4822.  
  4823.         Packet.Send.AddInt2(LoginReplyWrongPassword);
  4824.         Send;
  4825.       end{else if Pass <> Password}
  4826.  
  4827.       else
  4828.       begin
  4829.         if Banned <> 0 then
  4830.         begin
  4831.           Packet.Send.SetID(0, 0);
  4832.           Packet.Send.AddByte(3);
  4833.           Packet.Send.AddByte(2);
  4834.           Send(True);
  4835.           Disconnect;
  4836.           Log(['Login from banned account "' + Name + '"']);
  4837.           exit;
  4838.         end;{if Banned}
  4839.  
  4840.         Login;
  4841.       end;{else}
  4842.     end);{Server.CriticalSection.Section}
  4843.   end;{HandleLoginRequest}
  4844. begin
  4845.   if LoggedIn then exit;
  4846.  
  4847.   case Packet.Receive.Action of
  4848.     PacketActionRequest: HandleLoginRequest;
  4849.   else
  4850.     UnhandledAction('login');
  4851.   end;{case Packet.Receive.Action}
  4852. end;{Server.TSession.HandleLogin}
  4853.  
  4854. procedure Server.TSession.HandleGameState;
  4855.   procedure HandleGameStateAgree;
  4856.   var
  4857.     FileID: Byte;
  4858.   begin
  4859.     FileID := Packet.Receive.GetInt1;
  4860.  
  4861.     case FileID of
  4862.       1: SendData(Server.MapData);
  4863.       2: SendData(Server.ItemData);
  4864.       3: SendData(Server.NPCData);
  4865.       4: SendData(Server.SpellData);
  4866.       5: SendData(Server.ClassData);
  4867.     else
  4868.       Log(['Unknown file ID ', FileID]);
  4869.     end;{case FileID}
  4870.   end;{HandleGameStateAgree}
  4871.  
  4872.   procedure HandleGameStateMessage;
  4873.   var
  4874.     i: Integer;
  4875.   begin
  4876.     Packet.Send.AddInt2(2);
  4877.     Packet.Send.AddByte(255);
  4878.  
  4879.     Packet.Send.AddBreakString('MEOW');
  4880.  
  4881.     for i := 0 to 6 do
  4882.       Packet.Send.AddBreakString(News[i]);
  4883.  
  4884.     Packet.Send.AddByte(255);
  4885.  
  4886.     Packet.Send.AddInt1(0);  // Weight
  4887.     Packet.Send.AddInt1(50); // Max weight
  4888.  
  4889.     Packet.Send.AddInt2(GoldID);
  4890.     Packet.Send.AddInt4(Gold);
  4891.  
  4892.     Packet.Send.AddByte(255);
  4893.     // Spells
  4894.     Packet.Send.AddByte(255);
  4895.  
  4896.     LoggedIn := True;
  4897.  
  4898.     Server.CriticalSection.Section(procedure
  4899.     var
  4900.       p, Count: Integer;
  4901.       Session:  TSession;
  4902.     begin
  4903.       p := length(Packet.Send.Data) + 1;
  4904.       Packet.Send.AddInt1(0);
  4905.       Packet.Send.AddByte(255);
  4906.  
  4907.       Count := 0;
  4908.  
  4909.       for Session in Server.Sessions.Items do
  4910.         if Session.LoggedIn then
  4911.         begin
  4912.           Session.BuildCharacterPacket(Packet.Send);
  4913.           Packet.Send.AddByte(255);
  4914.           inc(Count);
  4915.         end;{if Session.LoggedIn}
  4916.  
  4917.       Packet.Send.Data[p] := UnpackEOInt(Count)[1];
  4918.     end);{Server.CriticalSection.Section}
  4919.  
  4920.     Packet.Send.AddByte(255); // NPCs
  4921.     //Packet.Send.AddByte(255); // Items
  4922.  
  4923.     Send;
  4924.  
  4925.     Packet.Send.Reset;
  4926.     Packet.Send.SetID(PacketFamilyPlayers, PacketActionAgree);
  4927.     Packet.Send.AddByte(255);
  4928.     BuildCharacterPacket(Packet.Send);
  4929.     Packet.Send.AddInt1(1);
  4930.     Packet.Send.AddByte(255);
  4931.     Packet.Send.AddInt1(1);
  4932.  
  4933.     Server.Send(Packet.Send, Self);
  4934.  
  4935.     if (State and StateSexSelected) = 0 then SexDialog
  4936.     else if (State and StateRaceSelected) = 0 then RaceDialog
  4937.     else if (State and StateHairSelected) = 0 then Barber;
  4938.   end;{HandleGameStateMessage}
  4939. begin
  4940.   case Packet.Receive.Action of
  4941.     PacketActionRequest: Login;
  4942.     PacketActionAgree:   HandleGameStateAgree;
  4943.     PacketActionMessage: HandleGameStateMessage;
  4944.   else
  4945.     UnhandledAction('game state');
  4946.   end;{case Packet.Receive.Action}
  4947. end;{Server.TSession.HandleGameState}
  4948.  
  4949. procedure Server.TSession.HandleWalk;
  4950. begin
  4951.   case Packet.Receive.Action of
  4952.     PacketActionPlayer:  Walk(Packet.Receive.GetInt1);
  4953.     PacketActionSpecial: Walk(Packet.Receive.GetInt1, False, True);
  4954.     PacketActionAdmin:   Walk(Packet.Receive.GetInt1, True);
  4955.   else
  4956.     UnhandledAction('walk');
  4957.   end;{case Packet.Receive.Action}
  4958. end;{Server.TSession.HandleWalk}
  4959.  
  4960. procedure Server.TSession.HandleFace;
  4961. begin
  4962.   case Packet.Receive.Action of
  4963.     PacketActionPlayer: Face(Packet.Receive.GetInt1);
  4964.   else
  4965.     UnhandledAction('face');
  4966.   end;{case Packet.Receive.Action}
  4967. end;{Server.TSession.HandleFace}
  4968.  
  4969. procedure Server.TSession.HandleRequest;
  4970.   procedure HandleRequestRequest;
  4971.   var
  4972.     RequestID: Integer;
  4973.     Session:   TSession;
  4974.   begin
  4975.     if not LoggedIn then exit;
  4976.  
  4977.     RequestID := Packet.Receive.GetInt2;
  4978.  
  4979.     Packet.Send.SetID(PacketFamilyPlayers, PacketActionRemove);
  4980.     Packet.Send.AddInt2(RequestID);
  4981.     Send;
  4982.  
  4983.     Packet.Send.Reset;
  4984.     Packet.Send.SetID(PacketFamilyPlayers, PacketActionAgree);
  4985.     Packet.Send.AddByte(255);
  4986.  
  4987.     Server.CriticalSection.Enter;
  4988.     try
  4989.       Session := Server.GetSessionByID(RequestID);
  4990.       if Session = nil then exit;
  4991.       if not Session.LoggedIn then exit;
  4992.  
  4993.       Session.BuildCharacterPacket(Packet.Send);
  4994.     finally
  4995.       Server.CriticalSection.Leave;
  4996.     end;{try..finally}
  4997.  
  4998.     Packet.Send.AddInt1(1);
  4999.     Packet.Send.AddByte(255);
  5000.     Packet.Send.AddInt1(1);
  5001.  
  5002.     Send;
  5003.   end;{HandleRequestRequest}
  5004. begin
  5005.   case Packet.Receive.Action of
  5006.     PacketActionRequest: HandleRequestRequest;
  5007.   else
  5008.     UnhandledAction('request');
  5009.   end;{case Packet.Receive.Action}
  5010. end;{Server.TSession.HandleRequest}
  5011.  
  5012. procedure Server.TSession.HandleTalk;
  5013.   procedure HandleTalkTell;
  5014.   var
  5015.     SendTo: AnsiString;
  5016.   begin
  5017.     SendTo := Packet.Receive.GetBreakString;
  5018.     SendTo := Lower(SendTo);
  5019.  
  5020.     SendPM(SendTo, Packet.Receive.GetBreakString);
  5021.   end;{HandleTalkTell}
  5022. begin
  5023.   case Packet.Receive.Action of
  5024.     PacketActionReport:   Say(Packet.Receive.GetBreakString);
  5025.     PacketActionAnnounce: if Admin > 0 then Announce(Packet.Receive.GetBreakString);
  5026.     PacketActionTell:     HandleTalkTell;
  5027.     PacketActionAdmin:    if Admin > 0 then SayAdmin(Packet.Receive.GetBreakString);
  5028.     PacketActionRequest:  SayGuild(Packet.Receive.GetBreakString);
  5029.     PacketActionMessage:  SayGlobal(Packet.Receive.GetBreakString);
  5030.   else
  5031.     UnhandledAction('talk');
  5032.   end;{case Packet.Receive.Action}
  5033. end;{Server.TSession.HandleTalk}
  5034.  
  5035. const
  5036.   SitActionSit   = 1;
  5037.   SitActionStand = 2;
  5038.  
  5039. procedure Server.TSession.HandleSit;
  5040.   procedure HandleSitRequest;
  5041.   var
  5042.     SitAction: Integer;
  5043.   begin
  5044.     SitAction := Packet.Receive.GetInt1;
  5045.  
  5046.     case SitAction of
  5047.       SitActionSit:   Sit;
  5048.       SitActionStand: Stand;
  5049.     end;{case SitAction}
  5050.   end;{HandleSitRequest}
  5051. begin
  5052.   case Packet.Receive.Action of
  5053.     PacketActionRequest: HandleSitRequest;
  5054.   else
  5055.     UnhandledAction('sit');
  5056.   end;{case Packet.Receive.Action}
  5057. end;{Server.TSession.HandleSit}
  5058.  
  5059. procedure Server.TSession.HandleChair;
  5060.   procedure HandleChairRequest;
  5061.   var
  5062.     ChairAction:    Integer;
  5063.     ChairX, ChairY: Integer;
  5064.     Session:        TSession;
  5065.   begin
  5066.     if not LoggedIn then exit;
  5067.  
  5068.     ChairAction := Packet.Receive.GetInt1;
  5069.  
  5070.     if (ChairAction = SitActionSit) and (Sitting = SittingStand) then
  5071.     begin
  5072.       ChairX := Packet.Receive.GetInt1;
  5073.       ChairY := Packet.Receive.GetInt2;
  5074.  
  5075.       if (ChairX < 0) or (ChairX >= Server.MapData.Width) or
  5076.          (ChairY < 0) or (ChairY >= Server.MapData.Height) then exit;
  5077.  
  5078.       if (ChairX + ChairY - X - Y) > 1 then exit;
  5079.  
  5080.       Server.CriticalSection.Enter;
  5081.       try
  5082.         for Session in Server.Sessions.Items do
  5083.           if (Session <> Self) and (Session.LoggedIn) and (Session.X = ChairX) and (Session.Y = ChairY) then exit;
  5084.       finally
  5085.         Server.CriticalSection.Leave;
  5086.       end;{try...finally}
  5087.  
  5088.       case Server.MapData.Tiles[ChairY, ChairX].Kind of
  5089.         TMapData.MapTileChairDown:  if (Y = (ChairY + 1)) and (X = ChairX) then D := DirectionDown  else exit;
  5090.         TMapData.MapTileChairLeft:  if (X = (ChairX - 1)) and (Y = ChairY) then D := DirectionLeft  else exit;
  5091.         TMapData.MapTileChairRight: if (X = (ChairX + 1)) and (Y = ChairY) then D := DirectionRight else exit;
  5092.         TMapData.MapTileChairUp:    if (Y = (ChairY - 1)) and (X = ChairX) then D := DirectionUp    else exit;
  5093.  
  5094.         TMapData.MapTileChairDownRight:
  5095.                if (Y = (ChairY + 1)) and (X = ChairX) then D := DirectionDown
  5096.           else if (X = (ChairX + 1)) and (Y = ChairY) then D := DirectionRight
  5097.           else exit;
  5098.  
  5099.         TMapData.MapTileChairUpLeft:
  5100.                if (Y = (ChairY - 1)) and (X = ChairX) then D := DirectionUp
  5101.           else if (X = (ChairX - 1)) and (Y = ChairY) then D := DirectionLeft
  5102.           else exit;
  5103.  
  5104.         TMapData.MapTileChairAll:
  5105.                if (Y = (ChairY + 1)) and (X = ChairX) then D := DirectionDown
  5106.           else if (X = (ChairX + 1)) and (Y = ChairY) then D := DirectionRight
  5107.           else if (Y = (ChairY - 1)) and (X = ChairX) then D := DirectionUp
  5108.           else if (X = (ChairX - 1)) and (Y = ChairY) then D := DirectionLeft
  5109.           else exit;
  5110.       else
  5111.         exit;
  5112.       end;{case Server.MapData.Tiles.Kind}
  5113.  
  5114.       X := ChairX;
  5115.       Y := ChairY;
  5116.  
  5117.       Sit(True);
  5118.     end{if ChairAction}
  5119.     else
  5120.     begin
  5121.       if Sitting <> SittingChair then exit;
  5122.  
  5123.       case D of
  5124.         DirectionDown:  inc(Y);
  5125.         DirectionLeft:  dec(X);
  5126.         DirectionUp:    dec(Y);
  5127.         DirectionRight: inc(X);
  5128.       end;{case Character.D}
  5129.  
  5130.       Stand;
  5131.     end;{else}
  5132.   end;{HandleChairRequest}
  5133. begin
  5134.   case Packet.Receive.Action of
  5135.     PacketActionRequest: HandleChairRequest;
  5136.   else
  5137.     UnhandledAction('chair');
  5138.   end;{case Packet.Receive.Action}
  5139. end;{Server.TSession.HandleChair}
  5140.  
  5141. procedure Server.TSession.HandleAttack;
  5142. begin
  5143.   case Packet.Receive.Action of
  5144.     PacketActionUse: Attack(Packet.Receive.GetInt1);
  5145.   else
  5146.     UnhandledAction('attack');
  5147.   end;{case Packet.Receive.Action}
  5148. end;{Server.TSession.HandleAttack}
  5149.  
  5150. procedure Server.TSession.HandleWarp;
  5151.   procedure HandleWarpAccept;
  5152.   var
  5153.     WX, WY: Integer;
  5154.   begin
  5155.     if not LoggedIn then exit;
  5156.  
  5157.     if WarpInfo.Time = 0 then exit;
  5158.     WarpInfo.Time := 0;
  5159.  
  5160.     Packet.Receive.GetInt2;
  5161.     WX := Packet.Receive.GetInt1;
  5162.     WY := Packet.Receive.GetInt1;
  5163.  
  5164.     if (WX <> WarpInfo.X) or (WY <> WarpInfo.Y) then exit;
  5165.  
  5166.     // TODO: Party bug, leave the party for now
  5167.     if Party <> nil then Party.Leave(Self);
  5168.  
  5169.    Packet.Send.SetID(PacketFamilyPlayers, PacketActionRemove);
  5170.     Packet.Send.AddInt2(ID);
  5171.     if WarpInfo.Animation <> WarpAnimationNone then
  5172.     begin
  5173.       //Packet.Send.Family := Packet.Send.Family + 1;
  5174.       Packet.Send.AddInt1(WarpInfo.Animation);
  5175.     end;{if WarpInfo.Animation}
  5176.  
  5177.     Server.Send(Packet.Send, Self);
  5178.  
  5179.     X := WX;
  5180.     Y := WY;
  5181.     Sitting := SittingStand;
  5182.  
  5183.     Packet.Send.Reset;
  5184.     Packet.Send.SetID(PacketFamilyPlayers, PacketActionAgree);
  5185.     Packet.Send.AddByte(255);
  5186.     BuildCharacterPacket(Packet.Send);
  5187.     Packet.Send.AddInt1(WarpInfo.Animation);
  5188.     Packet.Send.AddByte(255);
  5189.     Packet.Send.AddInt1(1);
  5190.     Server.Send(Packet.Send, Self);
  5191.  
  5192.     Packet.Send.Reset;
  5193.  
  5194.     Packet.Send.SetID(PacketFamilyWarp, PacketActionAgree);
  5195.     Packet.Send.AddInt1(2);
  5196.     Packet.Send.AddInt2(1);
  5197.     Packet.Send.AddInt1(WarpInfo.Animation);
  5198.  
  5199.     Server.CriticalSection.Section(procedure
  5200.     var
  5201.       p, Count: Integer;
  5202.       Session:  TSession;
  5203.     begin
  5204.       p := length(Packet.Send.Data) + 1;
  5205.       Packet.Send.AddInt1(0);
  5206.       Packet.Send.AddByte(255);
  5207.  
  5208.       Count := 0;
  5209.  
  5210.       for Session in Server.Sessions.Items do
  5211.         if Session.LoggedIn then
  5212.         begin
  5213.           Session.BuildCharacterPacket(Packet.Send);
  5214.           Packet.Send.AddByte(255);
  5215.           inc(Count);
  5216.         end;{if Session.LoggedIn}
  5217.  
  5218.       Packet.Send.Data[p] := UnpackEOInt(Count)[1];
  5219.     end);{Server.CriticalSection.Section}
  5220.  
  5221.     Packet.Send.AddByte(255);
  5222.  
  5223.     Send;
  5224.   end;{HandleWarpAccept}
  5225. begin
  5226.   case Packet.Receive.Action of
  5227.     PacketActionAccept: HandleWarpAccept;
  5228.   else
  5229.     UnhandledAction('warp');
  5230.   end;{case Packet.Receive.Action}
  5231. end;{Server.TSession.HandleWarp}
  5232.  
  5233. procedure Server.TSession.HandleEmote;
  5234. begin
  5235.   case Packet.Receive.Action of
  5236.     PacketActionReport: Emote(Packet.Receive.GetInt1);
  5237.   else
  5238.     UnhandledAction('emote');
  5239.   end;{case Packet.Receive.Action}
  5240. end;{Server.TSession.HandleEmote}
  5241.  
  5242. procedure Server.TSession.HandleRefresh;
  5243. begin
  5244.   case Packet.Receive.Action of
  5245.     PacketActionRequest: RefreshAll;
  5246.   else
  5247.     UnhandledAction('refresh');
  5248.   end;{case Packet.Receive.Action}
  5249. end;{Server.TSession.HandleRefresh}
  5250.  
  5251. procedure Server.TSession.HandleMessage;
  5252.   procedure HandleMessagePing;
  5253.   begin
  5254.     Packet.Send.SetID(PacketFamilyMessage, PacketActionPong);
  5255.     Packet.Send.AddInt2(Packet.Receive.GetInt2);
  5256.  
  5257.     Send;
  5258.   end;{HandleMessagePing}
  5259. begin
  5260.   case Packet.Receive.Action of
  5261.     PacketActionPing: HandleMessagePing;
  5262.   else
  5263.     UnhandledAction('message');
  5264.   end;{case Packet.Receive.Action}
  5265. end;{Server.TSession.HandleMessage}
  5266.  
  5267. procedure Server.TSession.HandlePlayers;
  5268.   procedure HandlePlayersRequest;
  5269.   begin
  5270.     Packet.Send.SetID(PacketFamilyRaw, PacketActionRaw);
  5271.     Packet.Send.AddInt1(8);
  5272.  
  5273.     Server.CriticalSection.Section(procedure
  5274.     var
  5275.       p, Count: Integer;
  5276.       Session:  TSession;
  5277.     begin
  5278.       p := length(Packet.Send.Data) + 1;
  5279.       Packet.Send.AddInt2(0);
  5280.       Packet.Send.AddByte(255);
  5281.  
  5282.       Count := 0;
  5283.  
  5284.       for Session in Server.Sessions.Items do
  5285.         if Session.LoggedIn then
  5286.         begin
  5287.           Packet.Send.AddBreakString(Session.Name);
  5288.           Packet.Send.AddBreakString(Session.IPStr);
  5289.           Packet.Send.AddInt1(0);
  5290.  
  5291.           if (Session.Admin > 3) or (Session.IPInt = localhost) then
  5292.             Packet.Send.AddInt1(5)
  5293.           else if Session.Admin > 0 then
  5294.             Packet.Send.AddInt1(4)
  5295.           else
  5296.             Packet.Send.AddInt1(0);
  5297.  
  5298.           Packet.Send.AddInt1(0); // Class
  5299.  
  5300.           Packet.Send.AddString(copy(Session.Tag + '   ', 1, 3));
  5301.           Packet.Send.AddByte(255);
  5302.  
  5303.           inc(Count);
  5304.         end;{if Session.LoggedIn}
  5305.  
  5306.       Packet.Send.Data[p]     := UnpackEOInt(Count)[1];
  5307.       Packet.Send.Data[p + 1] := UnpackEOInt(Count)[2];
  5308.     end);{Server.CriticalSection.Section}
  5309.  
  5310.     Send(Packet.Send, True);
  5311.   end;{HandlePlayersRequest}
  5312.  
  5313.   procedure HandlePlayersAccept;
  5314.   var
  5315.     PlayerName:    AnsiString;
  5316.     PlayerSession: TSession;
  5317.     PlayerFound:   Boolean;
  5318.   begin
  5319.     PlayerName := Lower(Packet.Receive.GetString);
  5320.  
  5321.     Server.CriticalSection.Enter;
  5322.     try
  5323.       PlayerSession := Server.GetSessionByName(PlayerName);
  5324.       if PlayerSession <> nil then
  5325.         PlayerFound := PlayerSession.LoggedIn
  5326.       else
  5327.         PlayerFound := False;
  5328.     finally
  5329.       Server.CriticalSection.Leave;
  5330.     end;{try...finally}
  5331.  
  5332.     if PlayerFound then
  5333.       Packet.Send.SetID(PacketFamilyPlayers, 241)
  5334.     else
  5335.       Packet.Send.SetID(PacketFamilyPlayers, 240);
  5336.  
  5337.     Packet.Send.AddString(PlayerName);
  5338.  
  5339.     Send;
  5340.   end;{HandlePlayersAccept}
  5341. begin
  5342.   case Packet.Receive.Action of
  5343.     PacketActionRequest: HandlePlayersRequest;
  5344.     PacketActionAccept:  HandlePlayersAccept;
  5345.   else
  5346.     UnhandledAction('players');
  5347.   end;{case Packet.Receive.Action}
  5348. end;{Server.TSession.HandlePlayers}
  5349.  
  5350. procedure Server.TSession.HandleDoor;
  5351.   procedure HandleDoorOpen;
  5352.   var
  5353.     X, Y: Integer;
  5354.   begin
  5355.     if not LoggedIn then exit;
  5356.  
  5357.     X := Packet.Receive.GetInt1;
  5358.     Y := Packet.Receive.GetInt1;
  5359.  
  5360.     Server.OpenDoor(X, Y);
  5361.   end;{HandleDoorOpen}
  5362. begin
  5363.   case Packet.Receive.Action of
  5364.     PacketActionOpen: HandleDoorOpen;
  5365.   else
  5366.     UnhandledAction('door');
  5367.   end;{case Packet.Receive.Action}
  5368. end;{Server.TSession.HandleDoor}
  5369.  
  5370. procedure Server.TSession.HandleGlobal;
  5371. begin
  5372.   case Packet.Receive.Action of
  5373.     PacketActionOpen:  ;
  5374.     PacketActionClose: ;
  5375.   else
  5376.     UnhandledAction('global');
  5377.   end;{case Packet.Receive.Action}
  5378. end;{Server.TSession.HandleGlobal}
  5379.  
  5380. procedure Server.TSession.HandleQuest;
  5381.   procedure HandleQuestAccept;
  5382.   var
  5383.     QuestID:  Integer;
  5384.     SelectID: Integer;
  5385.   begin
  5386.     if not LoggedIn then exit;
  5387.  
  5388.     QuestID := Packet.Receive.GetInt4;
  5389.     Packet.Receive.Discard(5);
  5390.     SelectID := Packet.Receive.GetInt2;
  5391.  
  5392.     if SelectID = 0 then exit;
  5393.  
  5394.     case QuestID of
  5395.       CustomRaceID: DoCommand('race ' + Str(SelectID - 1));
  5396.       CustomSexID:  DoCommand('sex '  + Str(SelectID - 1));
  5397.     end;{case QuestID}
  5398.   end;{HandleQuestAccept}
  5399. begin
  5400.   case Packet.Receive.Action of
  5401.     PacketActionAccept: HandleQuestAccept;
  5402.   else
  5403.     UnhandledAction('quest');
  5404.   end;{case Packet.Receive.Action}
  5405. end;{Server.TSession.HandleQuest}
  5406.  
  5407. procedure Server.TSession.HandleBarber;
  5408.   procedure HandleBarberBuy;
  5409.   var
  5410.     NewStyle:  Integer;
  5411.     NewColour: Integer;
  5412.   begin
  5413.     if not LoggedIn then exit;
  5414.  
  5415.     NewStyle  := Packet.Receive.GetInt1;
  5416.     NewColour := Packet.Receive.GetInt1;
  5417.  
  5418.     Packet.Send.SetID(PacketFamilyBarber, PacketActionAgree);
  5419.     Packet.Send.AddInt4(Gold);
  5420.  
  5421.     Send;
  5422.  
  5423.     HairStyle  := NewStyle;
  5424.     HairColour := NewColour;
  5425.  
  5426.     State := State or StateHairSelected;
  5427.  
  5428.     Refresh;
  5429.   end;{HandleBarberBuy}
  5430. begin
  5431.   case Packet.Receive.Action of
  5432.     PacketActionBuy: HandleBarberBuy;
  5433.   else
  5434.     UnhandledAction('barber');
  5435.   end;{case Packet.Receive.Action}
  5436. end;{Server.TSession.HandleBarber}
  5437.  
  5438. procedure Server.TSession.HandleAdmin;
  5439.   procedure HandleAdminTell;
  5440.   var
  5441.     s: AnsiString;
  5442.   begin
  5443.     s := '[request] ' + copy(Packet.Receive.GetString, 1, Server.TextLength);
  5444.     Server.AdminMsg(s, Name);
  5445.   end;{HandleAdminTell}
  5446.  
  5447.   procedure HandleAdminReport;
  5448.   var
  5449.     s: AnsiString;
  5450.   begin
  5451.     s := '[report:' + copy(Packet.Receive.GetBreakString, 1, 32) + '] ' + copy(Packet.Receive.GetString, 1, Server.TextLength);
  5452.     Server.AdminMsg(s, Name);
  5453.   end;{HandleAdminReport}
  5454. begin
  5455.   case Packet.Receive.Action of
  5456.     PacketActionTell:   HandleAdminTell;
  5457.     PacketActionReport: HandleAdminReport;
  5458.   else
  5459.     UnhandledAction('admin');
  5460.   end;{case Packet.Receive.Action}
  5461. end;{Server.TSession.HandleAdmin}
  5462.  
  5463. procedure Server.TSession.HandleParty;
  5464. const
  5465.   PartyRequestJoin   = 0;
  5466.   PartyRequestInvite = 1;
  5467.  
  5468.   procedure HandlePartyRequest;
  5469.   var
  5470.     Request: Integer;
  5471.   begin
  5472.     Request := Packet.Receive.GetInt1;
  5473.     if not (Request in [PartyRequestJoin, PartyRequestInvite]) then exit;
  5474.  
  5475.     Server.CriticalSection.Section(procedure
  5476.     var
  5477.       Invitee: TSession;
  5478.       Packet:   TPacket;
  5479.     begin
  5480.       Invitee := Server.GetSessionByID(Self.Packet.Receive.GetInt2);
  5481.  
  5482.       if Invitee = nil then exit;
  5483.       if (Invitee.Offline) or (not Invitee.LoggedIn) then exit;
  5484.       if (Invitee.Party <> nil) and (Request = PartyRequestInvite) then exit;
  5485.  
  5486.       Packet.SetID(PacketFamilyParty, PacketActionRequest);
  5487.       Packet.AddInt1(Request);
  5488.       Packet.AddInt2(ID);
  5489.       Packet.AddString(Name);
  5490.  
  5491.       Invitee.Send(Packet);
  5492.     end);{Server.CriticalSection.Section}
  5493.   end;{HandlePartyRequest}
  5494.  
  5495.   procedure HandlePartyAccept;
  5496.   var
  5497.     Request: Integer;
  5498.   begin
  5499.     Request := Packet.Receive.GetInt1;
  5500.  
  5501.     Server.CriticalSection.Section(procedure
  5502.     var
  5503.       Inviter: TSession;
  5504.     begin
  5505.       Inviter := Server.GetSessionByID(Self.Packet.Receive.GetInt2);
  5506.       if Inviter = nil then exit;
  5507.       if (Inviter.Offline) or (not Inviter.LoggedIn) then exit;
  5508.  
  5509.       case Request of
  5510.        PartyRequestJoin:
  5511.         begin
  5512.           if Party = nil then
  5513.             TParty.Create(Self);
  5514.  
  5515.           Party.Join(Inviter);
  5516.         end;{PartyRequestJoin:}
  5517.  
  5518.         PartyRequestInvite:
  5519.         begin
  5520.           if Inviter.Party = nil then
  5521.             TParty.Create(Inviter);
  5522.  
  5523.           Inviter.Party.Join(Self);
  5524.         end;{PartyRequestInvite:}
  5525.       end;{case Request}
  5526.     end);{Server.CriticalSection.Section}
  5527.   end;{HandlePartyAccept}
  5528.  
  5529.   procedure HandlePartyRemove;
  5530.   var
  5531.     RemoveID: Cardinal;
  5532.   begin
  5533.     if Party = nil then exit;
  5534.  
  5535.     RemoveID := Packet.Receive.GetInt2;
  5536.  
  5537.     if (RemoveID = ID) or (Party.Leader = Self) then Party.Leave(RemoveID)
  5538.   end;{HandlePartyRemove}
  5539.  
  5540.   procedure HandlePartyTake;
  5541.   begin
  5542.  
  5543.   end;{HandlePartyTake}
  5544. begin
  5545.   if (not LoggedIn) or Offline then exit;
  5546.  
  5547.   case Packet.Receive.Action of
  5548.     PacketActionRequest:  HandlePartyRequest;
  5549.     PacketActionAccept:   HandlePartyAccept;
  5550.     PacketActionRemove:   HandlePartyRemove;
  5551.     PacketActionTake:     HandlePartyTake;
  5552.   else
  5553.     UnhandledAction('party');
  5554.   end;{case Packet.Receive.Action}
  5555. end;{Server.TSession.HandleParty}
  5556.  
  5557. procedure Server.TSession._test(Params: AnsiString);
  5558. var
  5559.   Packet: TPacket;
  5560.   i: Integer;
  5561. begin
  5562.   for i := Int(Split(Params)) to Int(Params) do
  5563.   begin
  5564.     Packet.Reset;
  5565.     Packet.SetID(PacketFamilyEffect, i);
  5566.     Packet.AddString(Str(i) + Name);
  5567.  
  5568.   Send(Packet);
  5569.   end;
  5570. end;{Server.TSession._test}
  5571.  
  5572. constructor Server.TSession.TParty.Create(ALeader: TSession);
  5573. begin
  5574.   inherited Create;
  5575.  
  5576.   Members := TArray<TSession>.Create;
  5577.  
  5578.   Leader := nil;
  5579.   Join(ALeader);
  5580. end;{Server.TSession.TParty.Create}
  5581.  
  5582. destructor Server.TSession.TParty.Destroy;
  5583. var
  5584.   Packet: TPacket;
  5585. begin
  5586.   Packet.SetID(PacketFamilyParty, PacketActionClose);
  5587.   Packet.AddInt2(255);
  5588.  
  5589.   Server.CriticalSection.Section(procedure
  5590.   var
  5591.     Member: TSession;
  5592.   begin
  5593.     for Member in Members.Items do
  5594.     begin
  5595.       Member.Send(Packet);
  5596.       Member.Party := nil;
  5597.     end;{for Member}
  5598.  
  5599.     if Leader <> nil then
  5600.     begin
  5601.       Leader.Send(Packet);
  5602.       Leader.Party := nil;
  5603.       Leader := nil;
  5604.     end;{if Leader}
  5605.   end);{Server.CriticalSection.Section}
  5606.  
  5607.   Members.Free;
  5608.  
  5609.   inherited;
  5610. end;{Server.TSession.TParty.Destroy}
  5611.  
  5612. procedure Server.TSession.TParty.Join(Session: TSession);
  5613. begin
  5614.   Server.CriticalSection.Section(procedure
  5615.   var
  5616.     Packet: TPacket;
  5617.     Member: TSession;
  5618.   begin
  5619.     if Session.Party <> nil then exit;
  5620.  
  5621.     if Session = Leader then exit;
  5622.  
  5623.     for Member in Members.Items do
  5624.       if Member = Session then exit;
  5625.  
  5626.     if Leader = nil then
  5627.       Leader := Session
  5628.     else
  5629.       Members.Add(Session);
  5630.  
  5631.     Session.Party := Self;
  5632.  
  5633.     Packet.SetID(PacketFamilyParty, PacketActionAdd);
  5634.     Packet.AddInt2(Session.ID);
  5635.     Packet.AddInt1(0);// Admin icon
  5636.     Packet.AddInt1(0);// Level
  5637.     if Session.MaxHP = 1 then Session.MaxHP := 1;
  5638.     Packet.AddInt1(round((Session.HP / Session.MaxHP) * 100));
  5639.     Packet.AddString(Session.Name);
  5640.  
  5641.     for Member in Members.Items do
  5642.       if Member <> Session then Member.Send(Packet);
  5643.  
  5644.     if (Leader <> nil) and (Leader <> Session) then
  5645.       Leader.Send(Packet);
  5646.   end);{Server.CriticalSection.Section}
  5647.  
  5648.   Refresh(Session);
  5649. end;{Server.TSession.TParty.Join}
  5650.  
  5651. procedure Server.TSession.TParty.Leave(Session: TSession);
  5652. begin
  5653.   Server.CriticalSection.Section(procedure
  5654.   var
  5655.     Packet: TPacket;
  5656.     Member: TSession;
  5657.   begin
  5658.     if Session.Party <> Self then exit;
  5659.  
  5660.     if Session = Leader then
  5661.     begin
  5662.       Free;
  5663.       exit;
  5664.     end;{if Session = Leader}
  5665.  
  5666.     Members.Remove(Session);
  5667.     Session.Party := nil;
  5668.  
  5669.     Packet.SetID(PacketFamilyParty, PacketActionRemove);
  5670.     Packet.AddInt2(Session.ID);
  5671.  
  5672.     for Member in Members.Items do
  5673.       Member.Send(Packet);
  5674.  
  5675.     if Leader <> nil then Leader.Send(Packet);
  5676.  
  5677.     Packet.Reset;
  5678.     Packet.SetID(PacketFamilyParty, PacketActionClose);
  5679.     Packet.AddInt2(255);
  5680.  
  5681.     Session.Send(Packet);
  5682.  
  5683.     if length(Members.Items) < 2 then Free;
  5684.   end);{Server.CriticalSection.Section}
  5685. end;{Server.TSession.TParty.Leave (TSession)}
  5686.  
  5687. procedure Server.TSession.TParty.Leave(ID: Cardinal);
  5688. begin
  5689.   Server.CriticalSection.Section(procedure
  5690.   var
  5691.     Member: TSession;
  5692.   begin
  5693.     if (Leader <> nil) and (Leader.ID = ID) then
  5694.       Leave(Leader)
  5695.     else
  5696.       for Member in Members.Items do
  5697.         if Member.ID = ID then
  5698.         begin
  5699.           Leave(Member);
  5700.           break;
  5701.         end;{if Member.ID}
  5702.   end);{Server.CriticalSection.Section}
  5703. end;{Server.TSession.TParty.Leave (Caridnal)}
  5704.  
  5705. procedure Server.TSession.TParty.Refresh(Session: TSession);
  5706. begin
  5707.   Server.CriticalSection.Section(procedure
  5708.   var
  5709.     Packet: TPacket;
  5710.     Member: TSession;
  5711.  
  5712.     procedure ListMember(Member: TSession; Icon: Integer = 0);
  5713.     begin
  5714.       Packet.AddInt2(Member.ID);
  5715.       Packet.AddInt1(Icon);
  5716.       Packet.AddInt1(0);//Level
  5717.       if Member.MaxHP < 1 then Member.MaxHP := 1;
  5718.       Packet.AddInt1(round((Member.HP / Member.MaxHP) * 100));
  5719.       Packet.AddBreakString(Member.Name);
  5720.     end;{ListMember}
  5721.   begin
  5722.     Packet.SetID(PacketFamilyParty, PacketActionCreate);
  5723.  
  5724.     if Leader <> nil then ListMember(Leader, 1);
  5725.  
  5726.     for Member in Members.Items do
  5727.       ListMember(Member);
  5728.  
  5729.     Session.Send(Packet);
  5730.   end);{Server.CriticalSection.Section}
  5731. end;{Server.TSession.TParty.Refresh}
  5732.  
  5733. procedure Server.TSession.TParty.Update(Session: TSession);
  5734. begin
  5735.   Server.CriticalSection.Section(procedure
  5736.   var
  5737.     Packet: TPacket;
  5738.     Member: TSession;
  5739.   begin
  5740.     Packet.SetID(PacketFamilyParty, PacketActionAgree);
  5741.     Packet.AddInt2(Session.ID);
  5742.  
  5743.     if Session.MaxHP < 1 then Session.MaxHP := 1;
  5744.     Packet.AddInt1(round((Session.HP / Session.MaxHP) * 100));
  5745.  
  5746.     if Leader <> nil then Leader.Send(Packet);
  5747.  
  5748.     for Member in Members.Items do
  5749.       Member.Send(Packet);
  5750.   end);{Server.CriticalSection.Section}
  5751. end;{Server.TSession.TParty.Update}
  5752.  
  5753. begin
  5754.   Server.Create;
  5755. end.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement