Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- {(
- )) . . __ __ ___ __ _ _
- (( \`-"'"-'/ ( \/ )( _) / \( \/\/ )
- )) ) 6 6 ( - ) ( ) _)( () )\ /
- (( =. Y ,= (_/\/\_)(___) \__/ \/\/
- )) /^^^\ .
- (( / \ ) Mini EO? WOW!
- )) ( )-( )/ Created by Sordie out of boredom
- (( "" ""
- )}
- program MEOW;
- {$APPTYPE CONSOLE}
- {$DEFINE THREAD_SAFE}
- {$DEFINE LOG_CONFIG}
- {$DEFINE LOG_SQL}
- {$DEFINE LOG_UNHANDLED_PACKET_FAMILY}
- {$DEFINE LOG_UNHANDLED_PACKET_ACTION}
- {$DEFINE LOG_COMMANDS}
- {$DEFINE INTERNAL_PUB}
- {
- TODO:
- Server stats
- Weapon effects
- #commands
- Parties
- Book - showing kills, killed
- Item presets? Like "/equip dragon" for dragon armor etc
- SLN
- Re/over-log
- MEOW BASIC
- }
- uses
- Windows, WinSock;
- const
- Version = '0.2'; // Only I (Sordie) should change this!
- Branch = 'root'; // If you customize this source for your own needs, change this.
- localhost = $100007F; // 127.0.0.1
- type
- procedureref = reference to procedure;
- CriticalSectionHelper = record helper for TRTLCriticalSection
- procedure Create; inline;
- procedure Free; inline;
- procedure Enter; inline;
- procedure Leave; inline;
- procedure Section(Code: procedureref); inline;
- end;{CriticalSectionHelper}
- const
- sqlite3 = 'sqlite3.dll';
- type
- TSQLiteDB = Pointer;
- TSQLiteQuery = Pointer;
- function sqlite3_open(DBName: PAnsiChar; var DB: TSQLiteDB): Integer; cdecl; external sqlite3;
- function sqlite3_close(DB: TSQLiteDB): Integer; cdecl; external sqlite3;
- function sqlite3_prepare(DB: TSQLiteDB; QueryStr: PAnsiChar; QuerySize: Integer; var Query: TSQLiteQuery; var NextQuery: PAnsiChar): Integer; cdecl; external sqlite3;
- function sqlite3_step(Query: TSQLiteQuery): Integer; cdecl; external sqlite3;
- function sqlite3_finalize(Query: TSQLiteQuery): Integer; cdecl; external sqlite3;
- function sqlite3_column_count(Query: TSQLiteQuery): Integer; cdecl; external sqlite3;
- function sqlite3_column_name(Query: TSQLiteQuery; i: Integer): PAnsiChar; cdecl; external sqlite3;
- function sqlite3_column_type(Query: TSQLiteQuery; i: Integer): Integer; cdecl; external sqlite3;
- function sqlite3_column_int(Query: TSQLiteQuery; i: Integer): Integer; cdecl; external sqlite3;
- function sqlite3_column_text(Query: TSQLiteQuery; i: Integer): PAnsiChar; cdecl; external sqlite3;
- const
- SQLITE_OK = 0;
- SQLITE_ROW = 100;
- SQLITE_DONE = 101;
- SQLITE_INTEGER = 1;
- SQLITE_TEXT = 3;
- SQLITE_NULL = 5;
- type
- TDatabase = class
- var CriticalSection: TRTLCriticalSection;
- var FileName: AnsiString;
- var DB: TSQLiteDB;
- type TTable = class
- var Database: TDatabase;
- type TCell = record
- DataType: Integer;
- DataStr: AnsiString;
- DataInt: Integer;
- end;{TCell}
- var ColumnNames: array of AnsiString;
- var Table: array of array of TCell;
- constructor Create(ADatabase: TDatabase; SQL: AnsiString);
- destructor Destroy; override;
- function Empty: Boolean; inline;
- function Column(Name: AnsiString): Integer;
- function Value(Name: AnsiString; Row: Integer = 0; Default: AnsiString = ''): AnsiString; overload;
- function Value(Name: AnsiString; Row: Integer = 0; Default: Integer = 0): Integer; overload;
- end;{TTable}
- constructor Create(AFileName: AnsiString);
- destructor Destroy; override;
- function Prepare(SQL: AnsiString): TSQLiteQuery;
- procedure Finalize(var Query: TSQLiteQuery);
- function Query (SQL: AnsiString): Boolean;
- function QueryTable(SQL: AnsiString): TTable; inline;
- function TableExists(Name: AnsiString): Boolean;
- end;{TDatabase}
- TINIFile = class
- var CriticalSection: TRTLCriticalSection;
- var FileName: AnsiString;
- constructor Create(AFileName: AnsiString);
- destructor Destroy; override;
- function Read(Section, Key: AnsiString; Default: AnsiString = ''): AnsiString; overload;
- function Read(Section, Key: AnsiString; Default: Integer = 0): Integer; overload;
- function Read(Section, Key: AnsiString; Default: Boolean = False): Boolean; overload;
- end;{TINIFile}
- TArray<T: class> = class
- var Items: array of T;
- constructor Create;
- destructor Destroy; override;
- function Find (Item: T): Integer;
- function Add (Item: T): Integer;
- function Remove(Item: T): Integer;
- procedure Clear;
- end;{TArray<T>}
- TStrings = record
- Items: array of AnsiString;
- function Load(FileName: String): Boolean;
- function Save(FileName: String): Boolean;
- end;{TStrings}
- TSHA256Hash = packed record
- A, B, C, D, E, F, G, H: Cardinal;
- end;{TSHA256Hash}
- TSHA256 = record
- Hash: TSHA256Hash;
- MLen: Int64;
- Buffer: array[0..63] of Byte;
- Index: Integer;
- procedure Init;
- procedure Compress;
- procedure Update(Data: Pointer; Len: Integer);
- function Done: AnsiString;
- class function HashStr(S: AnsiString): AnsiString; static;
- end;{TSHA256}
- {$IFDEF INTERNAL_PUB}
- const
- ItemPubData: AnsiString = #$45#$49#$46#$90#$B0#$09#$B1#$03#$FE#$01#$05 +
- #$47#$6F#$6C#$64#$1A#$FE#$01#$01#$01#$01#$FE#$01#$FE#$01#$FE#$01#$FE +
- #$01#$FE#$01#$FE#$01#$FE#$02#$01#$01#$01#$01#$01#$01#$01#$01#$01#$01 +
- #$01#$01#$01#$FE#$FE#$01#$01#$01#$FE#$01#$FE#$01#$FE#$01#$FE#$01#$FE +
- #$01#$FE#$01#$FE#$01#$FE#$02#$02#$01#$01#$01#$04#$65#$6F#$66#$01#$FE +
- #$01#$01#$01#$01#$FE#$01#$FE#$01#$FE#$01#$FE#$01#$FE#$01#$FE#$01#$FE +
- #$01#$01#$01#$01#$01#$01#$01#$01#$01#$01#$01#$01#$01#$01#$FE#$FE#$01 +
- #$01#$01#$FE#$01#$FE#$01#$FE#$01#$FE#$01#$FE#$01#$FE#$01#$FE#$01#$FE +
- #$01#$01#$01#$01#$01;
- NPCPubData: AnsiString = #$45#$4E#$46#$02#$FE#$FE#$FE#$02#$FE#$01#$04 +
- #$65#$6F#$66#$01#$FE#$01#$01#$FE#$01#$FE#$01#$FE#$01#$FE#$01#$FE#$FE +
- #$01#$FE#$01#$FE#$01#$FE#$01#$FE#$01#$FE#$01#$FE#$01#$01#$FE#$01#$FE +
- #$01#$FE#$01#$FE#$01#$01#$FE#$FE;
- SpellPubData:AnsiString = #$45#$53#$46#$03#$FE#$FE#$FE#$02#$FE#$01#$04 +
- #$01#$65#$6F#$66#$01#$FE#$01#$FE#$01#$FE#$01#$FE#$01#$01#$01#$01#$FE +
- #$FE#$01#$01#$FE#$01#$01#$01#$01#$01#$FE#$01#$FE#$01#$FE#$01#$FE#$01 +
- #$FE#$01#$FE#$01#$01#$FE#$01#$FE#$01#$01#$FE#$01#$FE#$01#$FE#$01#$FE +
- #$01#$FE#$01#$FE;
- ClassPubData:AnsiString = #$45#$43#$46#$04#$FE#$FE#$FE#$03#$FE#$01#$07 +
- #$4E#$6F#$72#$6D#$61#$6C#$01#$01#$01#$FE#$01#$FE#$01#$FE#$01#$FE#$01 +
- #$FE#$01#$FE#$04#$65#$6F#$66#$01#$01#$01#$FE#$01#$FE#$01#$FE#$01#$FE +
- #$01#$FE#$01#$FE;
- type
- {$ENDIF INTERNAL_PUB}
- Server = class abstract
- const RequiredVersion: array[0..2] of Byte = (0, 0, 28);
- const ReceiveKey = 8;
- const SendKey = 10;
- const GoldID = 1;
- const MaxGold = 10000000;
- const CustomTitle = 'Customize Character -';
- const CustomRaceID = 1;
- const CustomSexID = 2;
- const PacketFamilyRaw = 255;
- const PacketFamilyConnection = 1;
- const PacketFamilyAccount = 2;
- const PacketFamilyLogin = 4;
- const PacketFamilyGameState = 5;
- const PacketFamilyWalk = 6;
- const PacketFamilyFace = 7;
- const PacketFamilyChair = 8;
- const PacketFamilyEmote = 9;
- const PacketFamilyAttack = 11;
- const PacketFamilyItem = 14;
- const PacketFamilySkill = 16;
- const PacketFamilyGlobal = 17;
- const PacketFamilyTalk = 18;
- const PacketFamilyWarp = 19;
- const PacketFamilyPlayers = 22;
- const PacketFamilyAppearance = 23;
- const PacketFamilyParty = 24;
- const PacketFamilyRefresh = 25;
- const PacketFamilyRequest = 27;
- const PacketFamilyEffect = 31;
- const PacketFamilyDoor = 34;
- const PacketFamilyMessage = 35;
- const PacketFamilyBarber = 38;
- const PacketFamilySound = 40;
- const PacketFamilySit = 41;
- const PacketFamilyUpdate = 42;
- const PacketFamilyArena = 45;
- const PacketFamilyAdmin = 48;
- const PacketFamilyInnKeeper = 49;
- const PacketFamilyQuest = 50;
- const PacketActionRaw = 255;
- const PacketActionRequest = 1;
- const PacketActionAccept = 2;
- const PacketActionReply = 3;
- const PacketActionRemove = 4;
- const PacketActionAgree = 5;
- const PacketActionCreate = 6;
- const PacketActionAdd = 7;
- const PacketActionPlayer = 8;
- const PacketActionTake = 9;
- const PacketActionUse = 10;
- const PacketActionBuy = 11;
- const PacketActionOpen = 13;
- const PacketActionClose = 14;
- const PacketActionMessage = 15;
- const PacketActionSpecial = 16;
- const PacketActionAdmin = 17;
- const PacketActionList = 18;
- const PacketActionTell = 20;
- const PacketActionReport = 21;
- const PacketActionAnnounce = 22;
- const PacketActionServer = 23;
- const PacketActionJunk = 25;
- const PacketActionGet = 27;
- const PacketActionDialog = 34;
- const PacketActionPing = 240;
- const PacketActionPong = 241;
- type TPacket = record
- Family: Byte;
- Action: Byte;
- Data: AnsiString;
- Time: Cardinal;
- procedure SetID(AFamily, AAction: Byte);
- procedure Reset; inline;
- procedure Discard(Count: Integer = 1); inline;
- procedure AddByte(b: Byte); inline;
- procedure AddInt1(i: Byte); inline;
- procedure AddInt2(i: Word); inline;
- procedure AddInt3(i: Cardinal); inline;
- procedure AddInt4(i: Cardinal); inline;
- procedure AddBreakString(s: AnsiString); inline;
- procedure AddString (s: AnsiString); inline;
- function GetByte: Byte;
- function GetInt1: Byte;
- function GetInt2: Word;
- function GetInt3: Cardinal;
- function GetInt4: Cardinal;
- function GetBreakString: AnsiString;
- function GetString(Len: Integer = -1): AnsiString;
- end;{TPacket}
- TGameData = class abstract
- var Data: AnsiString;
- var CRC: array[0..3] of Byte;
- var Len: array[0..1] of Byte;
- var FileName: AnsiString;
- class function DataID: Byte; virtual; abstract;
- constructor Create(AFileName: AnsiString);
- destructor Destroy; override;
- function Load: Boolean; virtual;
- procedure Clear; virtual;
- end;{TGameData}
- TItemData = class(TGameData)
- const ItemTypeSoda = 22;
- class function DataID: Byte; override;
- end;{TItemData}
- TNPCData = class(TGameData)
- class function DataID: Byte; override;
- end;{TNPCData}
- TSpellData = class(TGameData)
- class function DataID: Byte; override;
- end;{TSpellData}
- TClassData = class(TGameData)
- class function DataID: Byte; override;
- end;{TClassData}
- TMapData = class(TGameData)
- class function DataID: Byte; override;
- type TWarp = record
- var Enabled: Boolean;
- var X, Y, M: Integer;
- var ReqLevel: Integer;
- var ReqItem: Integer;
- end;{TWarp}
- const MapTileEmpty = 0;
- const MapTileWall = 1;
- const MapTileChairDown = 2;
- const MapTileChairLeft = 3;
- const MapTileChairRight = 4;
- const MapTileChairUp = 5;
- const MapTileChairDownRight = 6;
- const MapTileChairUpLeft = 7;
- const MapTileChairAll = 8;
- const MapTileDoor = 9;
- const MapTileChest = 10;
- const MapTileBankVault = 17;
- const MapTileNPCBoundary = 18;
- const MapTileMapEdge = 19;
- const MapTileBoard1 = 21;
- const MapTileBoard2 = 22;
- const MapTileBoard3 = 23;
- const MapTileBoard4 = 24;
- const MapTileBoard5 = 25;
- const MapTileBoard6 = 26;
- const MapTileBoard7 = 27;
- const MapTileBoard8 = 28;
- const MapTileJukebox = 29;
- const MapTileJump = 30;
- const MapTileWater = 31;
- const MapTileArena = 33;
- const MapTileSpikes1 = 35;
- const MapTileSpikes2 = 36;
- const MapTileSpikes3 = 37;
- const MapTilesImpassible = [MapTileWall,
- MapTileChairDown..MapTileChairAll,
- MapTileChest,
- MapTileBankVault,
- MapTileMapEdge,
- MapTileBoard1..MapTileBoard8,
- MapTileJukebox];
- type TMapTile = record
- Kind: Integer;
- Warp: TWarp;
- end;{TMapTile}
- var Width: Integer;
- var Height: Integer;
- var Tiles: array of array of TMapTile;
- function Load: Boolean; override;
- procedure Clear; override;
- function IsWalkable(X, Y: Integer; NPC: Boolean = False): Boolean;
- end;{TMapData}
- class var ItemData: TItemData;
- class var NPCData: TNPCData;
- class var SpellData: TSpellData;
- class var ClassData: TClassData;
- class var MapData: TMapData;
- type TSession = class
- var Offline: Boolean;
- var Socket: TSocket;
- var IPStr: AnsiString;
- var IPInt: Integer;
- var Thread: THandle;
- var Banned: Integer;
- var ID: Cardinal;
- var Initialized: Boolean;
- var LoggedIn: Boolean;
- var Packet: record
- Buffer: AnsiString;
- Queue: record
- Items: array of TPacket;
- Time: Cardinal;
- Active: Boolean;
- end;{Queue}
- Receive: TPacket;
- Send: TPacket;
- Time: Cardinal;
- end;{Packet}
- var Usage: record
- Started: Boolean;
- Last: Cardinal;
- Current: Cardinal;
- end;{Usage}
- var Name: AnsiString;
- var Password: AnsiString;
- var HDDSerial: AnsiString;
- const StateRaceSelected = 1;
- const StateSexSelected = 2;
- const StateHairSelected = 4;
- var State: Integer;
- var X: Integer;
- var Y: Integer;
- var D: Integer;
- var Sitting: Integer;
- var Hidden: Integer;
- var Admin: Integer;
- var Tag: AnsiString;
- var Sex: Integer;
- var HairStyle: Integer;
- var HairColour: Integer;
- var Race: Integer;
- var Boots: Integer;
- var Armour: Integer;
- var Hat: Integer;
- var Shield: Integer;
- var Weapon: Integer;
- var Gold: Integer;
- var HP, MaxHP: Integer;
- var TP, MaxTP: Integer;
- var Kills: Integer;
- const WarpAnimationNone = 1;
- const WarpAnimationBubbles = 2;
- var WarpInfo: record
- Time: Cardinal;
- X, Y: Integer;
- Animation: Integer;
- end;{WarpInfo}
- type TParty = class
- var Leader: TSession;
- var Members: TArray<TSession>;
- constructor Create(ALeader: TSession);
- destructor Destroy; override;
- procedure Join (Session: TSession);
- procedure Leave (Session: TSession); overload;
- procedure Leave (ID: Cardinal); overload;
- procedure Refresh(Session: TSession);
- procedure Update (Session: TSession);
- end;{TParty}
- var Party: TParty;
- constructor Create(ASocket: TSocket; ASockAddr: TSockAddr);
- destructor Destroy; override;
- class function CreateOffline(AName: AnsiString): TSession;
- procedure ClearQueue;
- procedure Disconnect;
- function Sync(Discard: Boolean = False): Boolean;
- procedure Unload;
- procedure Log(Params: array of const);
- procedure Send(var Packet: TPacket; Raw: Boolean = False); overload;
- procedure Send( Raw: Boolean = False); overload; inline;
- procedure SendData(Data: TGameData);
- procedure Login;
- procedure Logout;
- procedure BuildCharacterPacket(var Packet: TPacket);
- const DirectionDown = 0;
- const DirectionLeft = 1;
- const DirectionUp = 2;
- const DirectionRight = 3;
- const SittingStand = 0;
- const SittingChair = 1;
- const SittingFloor = 2;
- procedure Refresh;
- procedure RefreshAll;
- function Walk(Direction: Integer; Admin: Boolean = False; Ghost: Boolean = False; SendToSelf: Boolean = False): Boolean;
- function Face(Direction: Integer; SendToSelf: Boolean = False): Boolean;
- function Say(Text: AnsiString; SendToSelf: Boolean = False): Boolean;
- function SayGlobal(Text: AnsiString; SendToSelf: Boolean = False): Boolean;
- function SayGuild(Text: AnsiString; SendToSelf: Boolean = False): Boolean;
- function SayAdmin(Text: AnsiString; SendToSelf: Boolean = False): Boolean;
- function Announce(Text: AnsiString): Boolean;
- function Warp(WX, WY: Integer; Animation: Integer = WarpAnimationNone): Boolean;
- function Sit(Chair: Boolean = False): Boolean;
- function Stand: Boolean;
- function Emote(EmoteID: Integer; SendToSelf: Boolean = False): Boolean;
- function Status(Msg: AnsiString): Boolean;
- function Mute(From: AnsiString = 'Server'): Boolean;
- function Freeze: Boolean;
- function Unfreeze: Boolean;
- function Effect(EffectID: Integer; SendToSelf: Boolean = False): Boolean;
- function Drunk(Scale: Integer): Boolean;
- function Quake(Scale: Integer): Boolean;
- function HelloHax0r: Boolean;
- function Show: Boolean;
- function Hide: Boolean;
- function Sound(SoundID: Integer): Boolean;
- function Ban: Boolean;
- function UnBan: Boolean;
- function Sleep: Boolean;
- function Barber: Boolean;
- function SetGold(Value: Integer): Boolean;
- function Damage(Amount: Integer; By: TSession): Boolean;
- function SetHP(Value: Integer): Boolean;
- function SetTP(Value: Integer): Boolean;
- function SetMaxHP(Value: Integer): Boolean;
- function SetMaxTP(Value: Integer): Boolean;
- function UpdateHPTP: Boolean;
- function UpdateStats: Boolean;
- function Die(By: TSession): Boolean;
- function Resurrect: Boolean;
- function RaceDialog: Boolean;
- function SexDialog: Boolean;
- function ReceivePM(From, Text: AnsiString): Boolean;
- function SendPM(SendTo, Text: AnsiString): Boolean;
- function Attack(Direction: Integer; SendToSelf: Boolean = False): Boolean;
- procedure Attacked(By: TSession);
- function DoCommand(Cmd: AnsiString; Sender: TSession = nil): Boolean;
- function Execute: Boolean;
- procedure DefaultHandler(var Param); override;
- procedure UnhandledAction(Name: AnsiString = '');
- procedure HandleRaw (var Param); message PacketFamilyRaw;
- procedure HandleConnection(var Param); message PacketFamilyConnection;
- procedure HandleAccount (var Param); message PacketFamilyAccount;
- procedure HandleLogin (var Param); message PacketFamilyLogin;
- procedure HandleGameState (var Param); message PacketFamilyGameState;
- procedure HandleWalk (var Param); message PacketFamilyWalk;
- procedure HandleFace (var Param); message PacketFamilyFace;
- procedure HandleRequest (var Param); message PacketFamilyRequest;
- procedure HandleTalk (var Param); message PacketFamilyTalk;
- procedure HandleSit (var Param); message PacketFamilySit;
- procedure HandleChair (var Param); message PacketFamilyChair;
- procedure HandleAttack (var Param); message PacketFamilyAttack;
- procedure HandleWarp (var Param); message PacketFamilyWarp;
- procedure HandleEmote (var Param); message PacketFamilyEmote;
- procedure HandleRefresh (var Param); message PacketFamilyRefresh;
- procedure HandleMessage (var Param); message PacketFamilyMessage;
- procedure HandlePlayers (var Param); message PacketFamilyPlayers;
- procedure HandleDoor (var Param); message PacketFamilyDoor;
- procedure HandleGlobal (var Param); message PacketFamilyGlobal;
- procedure HandleQuest (var Param); message PacketFamilyQuest;
- procedure HandleBarber (var Param); message PacketFamilyBarber;
- procedure HandleAdmin (var Param); message PacketFamilyAdmin;
- procedure HandleParty (var Param); message PacketFamilyParty;
- procedure _test(Params: AnsiString);
- end;{Session}
- class var CriticalSection: TRTLCriticalSection;
- class var Sessions: TArray<TSession>;
- class var Socket: TSocket;
- class var Database: TDatabase;
- class var Configuration: TINIFile;
- class var Unapproved: TStrings;
- class var Connection: record
- Bind: AnsiString;
- Port: Word;
- Timeout: Cardinal;
- PerIP: Integer;
- BytesIn: Int64;
- BytesOut: Int64;
- end;{Connection}
- class var PacketQueue: record
- Enabled: Boolean;
- Size: Integer;
- Walk: Cardinal;
- Attack: Cardinal;
- end;{Packet}
- class var Defaults: record
- X, Y, D: Integer;
- Gold: Integer;
- HP, MaxHP: Integer;
- TP, MaxTP: Integer;
- end;{Defaults}
- class var Admin: record
- CommandChar: AnsiChar;
- EchoCommand: Boolean;
- TagAdmin: AnsiString;
- TagLocalhost: AnsiString;
- Level: record
- Appearance: Integer;
- Item: Integer;
- Action: Integer;
- Maintenance: Integer;
- end;{Level}
- end;{Admin}
- class var News: array[0..6] of AnsiString;
- const ViewRange = 12;
- const TextLength = 100;
- class constructor Create;
- class destructor Destroy;
- class procedure Main;
- class var Caption: AnsiString;
- class procedure UpdateCaption;
- class procedure Log(Params: array of const; Prefix: AnsiString = '');
- class procedure Send (var Packet: TPacket; Sender: TSession = nil; Ranged: Boolean = True);
- class procedure SendRanged(var Packet: TPacket; X, Y: Integer);
- class function GetSessionByID (ID: Cardinal): TSession;
- class function GetSessionByName(Name: AnsiString): TSession;
- class procedure Msg(Msg: AnsiString);
- class procedure AdminMsg(Msg: AnsiString; From: AnsiString = '[Server]');
- class procedure Freeze(Exclude: TSession);
- class procedure Unfreeze;
- class procedure Mute(Exclude: TSession);
- class procedure Quake(Scale: Integer);
- class procedure Effect(EffectID, X, Y: Integer);
- class procedure Sound(SoundID: Integer);
- class procedure SetMap(MapFile: AnsiString = '');
- class procedure Mutate;
- class procedure OpenDoor(X, Y: Integer);
- class procedure Shutdown;
- const NameMax = 12;
- const NameChars = 'abcdefghijklmnopqrstuvwxyz0123456789';
- class function ValidName(Name: AnsiString; IgnoreUnapproved: Boolean = False): Boolean;
- class function GetAccount(Name: AnsiString; Items: AnsiString = '*'): TDatabase.TTable;
- class function AccountExists(Name: AnsiString): Boolean;
- class procedure BanIP (IP: AnsiString);
- class procedure UnbanIP (IP: AnsiString);
- class function BannedIP(IP: Integer): Boolean;
- end;{Server}
- const
- EOInt1Max = 253;
- EOInt2Max = 64009;
- EOInt3Max = 16194277;
- function PackEOInt(b1: Byte = 0; b2: Byte = 0; b3: Byte = 0; b4: Byte = 0): Cardinal;
- begin
- if b1 = 254 then b1 := 0 else if b1 > 0 then dec(b1);
- if b2 = 254 then b2 := 0 else if b2 > 0 then dec(b2);
- if b3 = 254 then b3 := 0 else if b3 > 0 then dec(b3);
- if b4 = 254 then b4 := 0 else if b4 > 0 then dec(b4);
- Result := (b4 * EOInt3Max) + (b3 * EOInt2Max) + (b2 * EOInt1Max) + b1;
- end;{PackEOInt}
- function UnpackEOInt(Num: Cardinal): AnsiString;
- var
- i: Cardinal;
- begin
- Result := #254#254#254#254;
- i := Num;
- if i >= EOInt3Max then
- begin
- Result[4] := AnsiChar(Num div EOInt3Max + 1);
- Num := Num mod EOInt3Max;
- end;{if i >= EOInt3Max}
- if i >= EOInt2Max then
- begin
- Result[3] := AnsiChar(Num div EOInt2Max + 1);
- Num := Num mod EOInt2Max;
- end;{if i >= EOInt2Max}
- if i >= EOInt1Max then
- begin
- Result[2] := AnsiChar(Num div EOInt1Max + 1);
- Num := Num mod EOInt1Max;
- end;{if i >= EOInt3Max}
- Result[1] := AnsiChar(Num + 1);
- end;{UnpackEOInt}
- function FoldData(Str: AnsiString; Key: Byte): AnsiString;
- var
- i: Integer;
- c: AnsiChar;
- Buffer: AnsiString;
- begin
- if Key = 0 then exit(Str);
- Result := '';
- Buffer := '';
- for c in Str do
- begin
- if (ord(c) mod Key) = 0 then
- Buffer := Buffer + c
- else
- begin
- if length(Buffer) > 0 then
- begin
- for i := length(Buffer) downto 1 do
- Result := Result + Buffer[i];
- Buffer := '';
- end;{if length(Buffer)}
- Result := Result + c;
- end;{else}
- end;{for c}
- if length(Buffer) > 0 then
- for i := length(Buffer) downto 1 do
- Result := Result + Buffer[i];
- end;{FoldData}
- function bswap(A: integer): Integer;
- asm
- bswap eax
- end;{bswap}
- procedure bswap256(s, d: PInteger);
- asm
- push ebx
- mov ecx, eax
- mov eax,[ecx]; mov ebx,[ecx+4]; bswap eax; bswap ebx; mov [edx], eax; mov [edx+4], ebx
- mov eax,[ecx+8]; mov ebx,[ecx+12]; bswap eax; bswap ebx; mov [edx+8], eax; mov [edx+12], ebx
- mov eax,[ecx+16]; mov ebx,[ecx+20]; bswap eax; bswap ebx; mov [edx+16], eax; mov [edx+20], ebx
- mov eax,[ecx+24]; mov ebx,[ecx+28]; bswap eax; bswap ebx; mov [edx+24], eax; mov [edx+28], ebx
- pop ebx
- end;{bswap256}
- function InterlockedExchangeAdd64(var Addend: Int64; Value: Int64): Int64; register;
- asm
- push edi
- push esi
- push ebp
- push ebx
- mov esi, dword ptr [Value]
- mov edi, dword ptr [Value + 4]
- mov ebp, eax
- mov eax, [ebp]
- mov edx, [ebp + 4]
- @@lockmore:
- mov ecx, edx
- mov ebx, eax
- add ebx, esi
- adc ecx, edi
- lock cmpxchg8b [ebp]
- jnz @@lockmore
- pop ebx
- pop ebp
- pop esi
- pop edi
- end;{InterlockedExchangeAdd64}
- function Lower(S: AnsiString): AnsiString;
- var
- c: AnsiChar;
- begin
- Result := '';
- for c in S do
- case c of
- 'A'..'Z': Result := Result + AnsiChar(ord('a') + (ord(c) - ord('A')));
- else
- Result := Result + c;
- end;{case c}
- end;{Lower}
- function Capitalize(S: AnsiString): AnsiString;
- var
- i: Integer;
- begin
- Result := S;
- for i := 1 to length(Result) do
- if pos(String(Result[i]), 'abcdefghijklmnopqrstuvwxyz') > 0 then
- begin
- Result[i] := AnsiChar(ord('A') + (ord(Result[i]) - ord('a')));
- break;
- end{if pos...}
- else if pos(String(Result[i]), 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789') > 0 then
- break;
- end;{Captialize}
- function Trim(Str: AnsiString): AnsiString;
- var
- i: Integer;
- begin
- for i := 1 to length(Str) do
- if Str[i] <> ' ' then break;
- Result := copy(Str, i, length(Str));
- for i := length(Result) downto 1 do
- if Result[i] <> ' ' then break;
- Result := copy(Result, 1, i);
- end;{Trim}
- function Split(var Str: AnsiString; Delim: AnsiChar = ' '): AnsiString;
- var
- i: Integer;
- begin
- Str := Trim(Str);
- i := pos(Delim, Str);
- if i = 0 then
- begin
- Result := Str;
- Str := '';
- end{if i}
- else
- begin
- Result := Trim(copy(Str, 1, i - 1));
- Str := Trim(copy(Str, i + 1, length(Str)));
- end;{else}
- end;{Splt}
- function Int(S: AnsiString; Default: Integer = 0): Integer;
- var
- Code: Integer;
- begin
- Val(String(S), Result, Code);
- if Code <> 0 then Result := Default;
- end;{Int}
- function Str(I: Integer): AnsiString; overload;
- var
- S: ShortString;
- begin
- System.Str(I, S);
- Result := AnsiString(S);
- end;{Str(Integer}
- function Str(F: Extended): AnsiString; overload;
- var
- S: ShortString;
- begin
- System.Str(F:2:2, S);
- Result := AnsiString(S);
- end;{Str(Extended}
- function Tidy(s: AnsiString): AnsiString;
- var
- i: Integer;
- c: AnsiChar;
- begin
- Result := '';
- for c in s do
- if pos(String(c), '0123456789.') > 0 then Result := Result + c;
- if length(Result) = 0 then exit('0');
- if pos('.', String(Result)) > 0 then
- begin
- while Result[length(Result)] = '0' do
- Result := copy(Result, 1, length(Result) - 1);
- if Result[length(Result)] = '.' then
- Result := copy(Result, 1, length(Result) - 1);
- end;{if pos('.'...}
- while (length(Result) > 0) and (Result[1] = '0') do
- Result := copy(Result, 2, length(Result));
- i := pos('.', String(Result)) - 1; if i < 1 then i := length(Result);
- repeat
- dec(i, 3); if i < 1 then break;
- Result := copy(Result, 1, i) + ',' + copy(Result, i + 1, length(Result));
- until False;
- if (length(Result) = 0) or (Result[1] = '.') then Result := '0' + Result;
- end;{Tidy}
- function Scale(i: Int64): AnsiString;
- const
- MinAdjustValue = 900;
- ScaleStr: array[0..3] of AnsiString = ('B', 'KB', 'MB', 'GB');
- var
- j: Integer;
- k: Extended;
- begin
- j := 0;
- k := i;
- while k > MinAdjustValue do
- begin
- k := k / 1024;
- inc(j); if j = high(ScaleStr) then break;
- end;{while i}
- Result := Tidy(Str(k)) + ScaleStr[j];
- end;{Scale}
- function Str(B: Boolean): AnsiString; overload;
- begin
- if B then
- Result := 'TRUE'
- else
- Result := 'FALSE';
- end;{Str(Boolean}
- function Bool(S: AnsiString; Default: Boolean = False): Boolean;
- begin
- if length(S) = 0 then exit(Default);
- S := Lower(copy(S, 1, 2));
- if (S[1] = 't') or (S = 'ok') or (S = 'on') then
- Result := True
- else
- Result := Int(S, Integer(Default)) <> 0;
- end;{Bool}
- function Match(Mask, Str: AnsiString): Boolean;
- function Comp(MaskI, StrI: Integer): Boolean;
- var
- m: AnsiChar;
- begin
- if MaskI > length(Mask) then exit(StrI = length(Str) + 1);
- if StrI > length(Str) then exit(False);
- m := Mask[MaskI];
- if m = '*' then
- Result := Comp(succ(MaskI), succ(StrI)) or Comp(MaskI, succ(StrI))
- else if (m = '?') or (m = Str[StrI]) then
- Result := Comp(succ(MaskI), succ(StrI))
- else
- Result := False;
- end;{Comp}
- begin
- if copy(Mask, 1, 1) = '!' then
- Result := pos(copy(Mask, 2, length(Mask)), Str) > 0
- else
- Result := Comp(1, 1);
- end;{Match}
- procedure Error(Params: array of const);
- begin
- Server.Log(Params, '/!\ ERROR');
- Readln;
- halt(1);
- end;{Error}
- procedure CriticalSectionHelper.Create;
- begin
- {$IFDEF THREAD_SAFE}
- InitializeCriticalSection(Self);
- {$ENDIF THREAD_SAFE}
- end;{CriticalSectionHelper.Create}
- procedure CriticalSectionHelper.Free;
- begin
- {$IFDEF THREAD_SAFE}
- DeleteCriticalSection(Self);
- {$ENDIF THREAD_SAFE}
- end;{CriticalSectionHelper.Free}
- procedure CriticalSectionHelper.Enter;
- begin
- {$IFDEF THREAD_SAFE}
- EnterCriticalSection(Self);
- {$ENDIF THREAD_SAFE}
- end;{CriticalSectionHelper.Enter}
- procedure CriticalSectionHelper.Leave;
- begin
- {$IFDEF THREAD_SAFE}
- LeaveCriticalSection(Self);
- {$ENDIF THREAD_SAFE}
- end;{CriticalSectionHelper.Leave}
- procedure CriticalSectionHelper.Section(Code: procedureref);
- begin
- Enter;
- try
- Code;
- finally
- Leave;
- end;{try...finally}
- end;{CriticalSectionHelper.Secion}
- constructor TDatabase.TTable.Create(ADatabase: TDatabase; SQL: AnsiString);
- var
- i: Integer;
- Query: TSQLiteQuery;
- begin
- inherited Create;
- Database := ADatabase;
- Database.CriticalSection.Enter;
- try
- Query := Database.Prepare(SQL);
- if Query = nil then exit;
- try
- while sqlite3_step(Query) = SQLITE_ROW do
- begin
- if length(Table) = 0 then
- begin
- SetLength(ColumnNames, sqlite3_column_count(Query));
- for i := 0 to length(ColumnNames) - 1 do
- ColumnNames[i] := lower(sqlite3_column_name(Query, i));
- end;{if length(Table) = 0}
- SetLength(Table, length(Table) + 1);
- SetLength(Table[high(Table)], length(ColumnNames));
- for i := 0 to length(ColumnNames) - 1 do
- with Table[high(Table)][i] do
- begin
- DataType := sqlite3_column_type(Query, i);
- case DataType of
- SQLITE_INTEGER:
- begin
- DataInt := sqlite3_column_int(Query, i);
- DataStr := Str(DataInt);
- end;{SQLITE_INTEGER:}
- SQLITE_TEXT:
- begin
- DataStr := sqlite3_column_text(Query, i);
- DataInt := Int(DataStr);
- end;{SQLITE_TEXT:}
- else
- DataStr := '';
- DataInt := 0;
- end;{case DataType}
- end;{with Table}
- end;{while sqlite3_step}
- finally
- Database.Finalize(Query);
- end;{try...finally}
- finally
- Database.CriticalSection.Leave;
- end;{try...finally}
- end;{TDatabase.TTable.Create}
- destructor TDatabase.TTable.Destroy;
- begin
- Database.CriticalSection.Leave;
- inherited;
- end;{TDatabase.TTable.Destroy}
- function TDatabase.TTable.Empty: Boolean;
- begin
- Result := length(Table) = 0;
- end;{TDatabase.Empty}
- function TDatabase.TTable.Column(Name: AnsiString): Integer;
- var
- i: Integer;
- begin
- Name := lower(Name);
- for i := 0 to length(ColumnNames) - 1 do
- if Name = ColumnNames[i] then exit(i);
- Result := -1;
- end;{TDatabase.TTable.Column}
- function TDatabase.TTable.Value(Name: AnsiString; Row: Integer = 0; Default: AnsiString = ''): AnsiString;
- var
- i: Integer;
- begin
- i := Column(Name);
- if i = -1 then exit(Default);
- Result := Table[Row][i].DataStr;
- end;{TDatabase.TTable.Value(AnsiString}
- function TDatabase.TTable.Value(Name: AnsiString; Row: Integer = 0; Default: Integer = 0): Integer;
- var
- i: Integer;
- begin
- i := Column(Name);
- if i = -1 then exit(Default);
- Result := Table[Row][i].DataInt;
- end;{TDatabase.TTable.Value(Integer}
- constructor TDatabase.Create(AFileName: AnsiString);
- begin
- inherited Create;
- CriticalSection.Create;
- FileName := AFileName;
- if sqlite3_open(PAnsiChar(FileName), DB) <> SQLITE_OK then
- Error(['Failed to open database "', FileName, '"']);
- end;{TDatabase.Create}
- destructor TDatabase.Destroy;
- begin
- if DB <> nil then
- begin
- sqlite3_close(DB);
- DB := nil;
- end;{if DB <> nil}
- CriticalSection.Free;
- inherited;
- end;{TDatabase.Destroy}
- function TDatabase.Prepare(SQL: AnsiString): TSQLiteQuery;
- var
- NextQuery: PAnsiChar;
- begin
- if DB = nil then exit(nil);
- {$IFDEF LOG_SQL}
- Server.Log(['Database (', FileName, ') ', SQL]);
- {$ENDIF LOG_SQL}
- if sqlite3_prepare(DB, PAnsiChar(SQL), -1, Result, NextQuery) <> SQLITE_OK then
- if Result <> nil then
- Finalize(Result);
- end;{TDatabase.Prepare}
- procedure TDatabase.Finalize(var Query: TSQLiteQuery);
- begin
- if Query = nil then exit;
- sqlite3_finalize(Query);
- Query := nil;
- end;{TDatabase.Finalize}
- function TDatabase.Query(SQL: AnsiString): Boolean;
- var
- Query: TSQLiteQuery;
- begin
- CriticalSection.Enter;
- try
- Query := Prepare(SQL);
- if Query = nil then exit(False);
- Result := sqlite3_step(Query) = SQLITE_DONE;
- finally
- Finalize(Query);
- CriticalSection.Leave;
- end;{try...finally}
- end;{TDatabase.Query}
- function TDatabase.QueryTable(SQL: AnsiString): TTable;
- begin
- Result := TTable.Create(Self, SQL);
- end;{TDatabase.QueryTable}
- function TDatabase.TableExists(Name: AnsiString): Boolean;
- begin
- with QueryTable('SELECT `sql` FROM `sqlite_master` WHERE `type` = "table" AND `name` = "' + Name + '";') do try
- Result := not Empty;
- finally
- Free;
- end;{with QueryTable..}
- end;{TDatabase.TableExists}
- constructor TINIFile.Create(AFileName: AnsiString);
- begin
- inherited Create;
- FileName := AFileName;
- CriticalSection.Create;
- end;{TINIFile.Create}
- destructor TINIFile.Destroy;
- begin
- CriticalSection.Free;
- inherited;
- end;{TINIFile.Destroy}
- function TINIFile.Read(Section, Key: AnsiString; Default: AnsiString = ''): AnsiString;
- begin
- CriticalSection.Enter;
- try
- SetLength(Result, 256);
- SetLength(Result, GetPrivateProfileStringA(PAnsiChar(Section), PAnsiChar(Key), PAnsiChar(Default), PAnsiChar(Result), length(Result), PAnsiChar(FileName)));
- finally
- CriticalSection.Leave;
- end;{try...finally}
- {$IFDEF LOG_CONFIG}
- if (length(Result) > 0) and (Lower(Result) <> Lower(Default)) then Server.Log(['Configuration (', FileName, ') [', Section, '] ', Key ,'=', Result]);
- {$ENDIF LOG_CONFIG}
- end;{TINIFile.Read(String}
- function TINIFile.Read(Section, Key: AnsiString; Default: Integer = 0): Integer;
- begin
- Result := Int(Read(Section, Key, Str(Default)));
- end;{TINIFile.Read(Integer}
- function TINIFile.Read(Section, Key: AnsiString; Default: Boolean = False): Boolean;
- begin
- Result := Bool(Read(Section, Key, Str(Default)));
- end;{TINIFile.Read(Boolean}
- constructor TArray<T>.Create;
- begin
- inherited Create;
- Clear;
- end;{TArray<T>.Create}
- destructor TArray<T>.Destroy;
- begin
- Clear;
- inherited;
- end;{TArray<T>.Destroy}
- function TArray<T>.Find(Item: T): Integer;
- var
- i: Integer;
- begin
- for i := 0 to high(Items) do
- if Items[i] = Item then exit(i);
- Result := -1;
- end;{TArray<T>.Add}
- function TArray<T>.Add(Item: T): Integer;
- begin
- Result := Find(Item);
- if Result = -1 then
- begin
- SetLength(Items, length(Items) + 1);
- Result := high(Items);
- Items[Result] := Item;
- end;{if Result = -1}
- end;{TArray<T>.Add}
- function TArray<T>.Remove(Item: T): Integer;
- begin
- Result := Find(Item);
- if Result = -1 then exit;
- if Result < high(Items) then
- move(Items[Result + 1], Items[Result], sizeof(T) * (length(Items) - 1));
- SetLength(Items, length(Items) - 1);
- end;{TArray<T>.Remove}
- procedure TArray<T>.Clear;
- begin
- SetLength(Items, 0);
- end;{TArray<T>.Clear}
- {$I-}
- function TStrings.Load(FileName: String): Boolean;
- var
- f: TextFile;
- s: AnsiString;
- begin
- SetLength(Items, 0);
- AssignFile(f, FileName);
- Result := True;
- try
- try
- Reset(f);
- while not eof(f) do
- begin
- Readln(f, s);
- s := Trim(s);
- if length(s) = 0 then continue;
- SetLength(Items, length(Items) + 1);
- Items[high(Items)] := s;
- end;{while}
- except
- Result := False;
- end;{try...except}
- finally
- Close(f);
- end;{try...finally}
- end;{TStrings.Load}
- function TStrings.Save(FileName: String): Boolean;
- begin
- Result := False;
- end;{TStrings.Save}
- procedure TSHA256.Init;
- begin
- Hash.A := $6a09e667;
- Hash.B := $bb67ae85;
- Hash.C := $3c6ef372;
- Hash.D := $a54ff53a;
- Hash.E := $510e527f;
- Hash.F := $9b05688c;
- Hash.G := $1f83d9ab;
- Hash.H := $5be0cd19;
- FillChar(Buffer, sizeof(Buffer), 0);
- Index := 0;
- MLen := 0;
- end;{TSHA256.Init}
- procedure TSHA256.Compress;
- var
- a, b, c, d, e, f, g, h: Cardinal;
- t1, t2: Cardinal;
- W: array[0..63] of Cardinal;
- i: longword;
- begin
- Index:= 0;
- Move(Buffer,W,Sizeof(Buffer));
- a := Hash.A;
- b := Hash.B;
- c := Hash.C;
- d := Hash.D;
- e := Hash.E;
- f := Hash.F;
- g := Hash.G;
- h := Hash.H;
- for i:= 0 to 15 do
- W[i] := bswap(W[i]);
- for i:= 16 to 63 do
- W[i] := (((W[i - 2] shr 17) or (W[i - 2] shl 15)) xor ((W[i - 2] shr 19) or
- (W[i - 2] shl 13)) xor (W[i - 2] shr 10)) + W[i - 7] + (((W[i - 15]
- shr 7) or (W[i - 15] shl 25)) xor ((W[i - 15] shr 18) or (W[i - 15]
- shl 14)) xor (W[i - 15] shr 3)) + W[i - 16];
- 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;
- 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;
- 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;
- 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;
- 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;
- 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;
- 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;
- 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;
- 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;
- 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;
- 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;
- 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;
- 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;
- 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;
- 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;
- 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;
- 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;
- 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;
- 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;
- 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;
- 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;
- 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;
- 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;
- 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;
- 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;
- 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;
- 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;
- 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;
- 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;
- 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;
- 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;
- 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;
- 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;
- 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;
- 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;
- 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;
- 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;
- 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;
- 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;
- 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;
- 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;
- 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;
- 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;
- 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;
- 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;
- 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;
- 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;
- 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;
- 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;
- 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;
- 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;
- 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;
- 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;
- 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;
- 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;
- 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;
- 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;
- 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;
- 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;
- 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;
- 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;
- 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;
- 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;
- 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;
- inc(Hash.A, a);
- inc(Hash.B, b);
- inc(Hash.C, c);
- inc(Hash.D, d);
- inc(Hash.E, e);
- inc(Hash.F, f);
- inc(Hash.G, g);
- inc(Hash.H, h);
- FillChar(W,Sizeof(W),0);
- FillChar(Buffer,Sizeof(Buffer),0);
- end;{TSHA256.Compress}
- procedure TSHA256.Update(Data: Pointer; Len: Integer);
- var
- i: Integer;
- begin
- inc(MLen, Int64(Cardinal(Len) shl 3));
- while Len > 0 do
- begin
- i := 64 - Index;
- if i <= Len then
- begin
- move(Data^, Buffer[Index], i);
- dec(Len, i);
- inc(Integer(Data), i);
- Compress;
- Index := 0;
- end{if i <= Len}
- else
- begin
- move(Data^, Buffer[Index], Len);
- inc(Index, Len);
- break;
- end;{else}
- end;{while Len > 0}
- end;{TSHA256.Update}
- function TSHA256.Done: AnsiString;
- const
- HexChar: array[0..15] of AnsiChar = '0123456789ABCDEF';
- type
- TInt64 = packed record
- Lo, Hi: Cardinal;
- end;{TInt64}
- var
- i: Integer;
- PResult: PAnsiChar;
- Digest: array[0..31] of Byte;
- begin
- Buffer[Index] := $80;
- fillchar(Buffer[Index + 1], 63 - Index, 0);
- if Index >= 56 then
- begin
- Compress;
- fillchar(Buffer, 56, 0);
- end;{if Index >= 56}
- PInteger(@Buffer[56])^ := bswap(TInt64(MLen).Hi);
- PInteger(@Buffer[60])^ := bswap(TInt64(MLen).Lo);
- Compress;
- bswap256(@Hash, @Digest);
- Setlength(Result, sizeof(Digest) * 2);
- PResult := PAnsiChar(Result);
- for i := 0 to sizeof(Digest) - 1 do
- begin
- PResult[0] := HexChar[Digest[I] shr 4];
- PResult[1] := HexChar[Digest[I] and 15];
- inc(PResult,2);
- end;{for i}
- end;{TSHA256.Done}
- class function TSHA256.HashStr(S: AnsiString): AnsiString;
- var
- SHA256: TSHA256;
- begin
- SHA256.Init;
- SHA256.Update(PAnsiChar(S), length(S));
- Result := SHA256.Done;
- end;{class)TSHA256.HashStr}
- class constructor Server.Create;
- const
- Banner = ' . . __ __ ___ __ _ _'#13#10' \`-"''"-''/ '+
- '( \/ )( _) / \( \/\/ )'#13#10' } o o { - ) ( ) _)( () )\ '+
- '/'#13#10' =. Y ,= (_/\/\_)(___) \__/ \/\/'#13#10' /-O-\ .'#13#10+
- ' / \ ) Mini EO? WOW!'#13#10' ( )-( )/ Created by Sordie o'+
- 'ut of boredom'#13#10' "" ""';
- var
- i: Integer;
- WSAData: TWSAData;
- AddrIn: TSockAddrIn;
- begin
- Writeln(Banner);
- Writeln('Version ' + Version + '|' + Branch);
- CriticalSection.Create;
- Sessions := TArray<TSession>.Create;
- WSAStartup(MakeLong(2, 2), WSAData);
- Configuration := TINIFile.Create('.\MEOW.ini');
- Log(['Opening database...']);
- Database := TDatabase.Create(Configuration.Read('database', 'name', '.\MEOW.db'));
- //Database.Query('DROP TABLE `accounts`;');
- if not Database.TableExists('accounts') then
- begin
- Log(['Creating accounts database']);
- if not Database.Query('CREATE TABLE `accounts` (' +
- '`id` INTEGER PRIMARY KEY, ' +
- '`name` VARCHAR (' + Str(NameMax) + '), ' +
- '`banned` INTEGER, ' +
- '`password` VARCHAR (64), ' +
- '`usage` INTEGER, ' +
- '`state` INTEGER, ' +
- '`x` INTEGER, ' +
- '`y` INTEGER, ' +
- '`d` INTEGER, ' +
- '`s` INTEGER, ' +
- '`admin` INTEGER, ' +
- '`tag` VARCHAR (3), ' +
- '`sex` INTEGER, ' +
- '`hairstyle` INTEGER, ' +
- '`haircolour` INTEGER, ' +
- '`race` INTEGER, ' +
- '`boots` INTEGER, ' +
- '`armour` INTEGER, ' +
- '`hat` INTEGER, ' +
- '`shield` INTEGER, ' +
- '`weapon` INTEGER, ' +
- '`gold` INTEGER, ' +
- '`hp` INTEGER, ' +
- '`maxhp` INTEGER, ' +
- '`tp` INTEGER, ' +
- '`maxtp` INTEGER, ' +
- '`kills` INTEGER' +
- ');') then
- Error(['Failed to create table']);
- end;{if not Database.TableExists}
- if not Database.TableExists('banned') then
- begin
- Log(['Creating banned IP table']);
- if not Database.Query('CREATE TABLE `banned` (`ip` INTEGER PRIMARY KEY);') then
- Error(['Failed to create banned IP table']);
- end;{if not Database.TableExists}
- PacketQueue.Enabled := Configuration.Read('packetqueue', 'enabled', True);
- if PacketQueue.Enabled then
- begin
- PacketQueue.Size := Configuration.Read('packetqueue', 'size', 10);
- PacketQueue.Walk := Configuration.Read('packetqueue', 'walk', 500);
- PacketQueue.Attack := Configuration.Read('packetqueue', 'attack', 500);
- end;{if PacketQueue.Enabled}
- Log(['Creating socket...']);
- Socket := WinSock.socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
- if Socket = 0 then
- Error(['Failed to create socket']);
- Connection.Bind := Configuration.Read('connection', 'bind', '0.0.0.0');
- Connection.Port := Configuration.Read('connection', 'port', 8078);
- Connection.Timeout := Configuration.Read('connection', 'timeout', 300000);
- Log(['Bind ', Connection.Bind, ':', Connection.Port]);
- FillChar(AddrIn, sizeof(AddrIn), 0);
- with AddrIn do
- begin
- sin_family := AF_INET;
- sin_addr.S_addr := inet_addr(PAnsiChar(Connection.Bind));
- sin_port := htons(Connection.Port);
- end;{with AddrIn}
- if bind(Socket, AddrIn, sizeof(AddrIn)) <> 0 then
- Error(['Failed to bind socket']);
- if listen(Socket, 0) <> 0 then
- Error(['Cannot listen on socket']);
- Log(['Creating game data...']);
- ItemData := TItemData. Create({$IFDEF INTERNAL_PUB}'_internal_'{$ELSE}Configuration.Read('data', 'item', '.\Items.eif') {$ENDIF});
- NPCData := TNPCData. Create({$IFDEF INTERNAL_PUB}'_internal_'{$ELSE}Configuration.Read('data', 'npc', '.\NPCs.enf') {$ENDIF});
- SpellData := TSpellData.Create({$IFDEF INTERNAL_PUB}'_internal_'{$ELSE}Configuration.Read('data', 'spell', '.\Spells.esf') {$ENDIF});
- ClassData := TClassData.Create({$IFDEF INTERNAL_PUB}'_internal_'{$ELSE}Configuration.Read('data', 'class', '.\Classes.ecf'){$ENDIF});
- MapData := TMapData. Create(Configuration.Read('data', 'map', '.\00001.emf'));
- Connection.PerIP := Configuration.Read('connection', 'perip', 2);
- Defaults.X := Configuration.Read('defaults', 'x', 10);
- Defaults.Y := Configuration.Read('defaults', 'y', 10);
- Defaults.D := Configuration.Read('defaults', 'd', 0);
- Defaults.Gold := Configuration.Read('defaults', 'gold', 200);
- Defaults.HP := Configuration.Read('defaults', 'hp', 10);
- Defaults.MaxHP := Configuration.Read('defaults', 'maxhp', 10);
- Defaults.TP := Configuration.Read('defaults', 'tp', 10);
- Defaults.MaxTP := Configuration.Read('defaults', 'maxtp', 10);
- if Defaults.MaxHP < 1 then Defaults.MaxHP := 1;
- Admin.CommandChar := (Configuration.Read('admin', 'commandchar', '/') + '/')[1];
- Admin.EchoCommand := Configuration.Read('admin', 'echocommand', True);
- Admin.TagAdmin := Configuration.Read('admin', 'tagadmin', 'ª');
- Admin.TagLocalhost := Configuration.Read('admin', 'taglocalhost', '¹');
- Admin.Level.Appearance := Configuration.Read('admin', 'appearance', 0);
- Admin.Level.Item := Configuration.Read('admin', 'item', 0);
- Admin.Level.Action := Configuration.Read('admin', 'action', 1);
- Admin.Level.Maintenance := Configuration.Read('admin', 'maintenance', 4);
- for i := 0 to 6 do
- News[i] := Configuration.Read('news', Str(i), '');
- Unapproved.Load(String(Configuration.Read('data', 'unapproved', 'unapproved.txt')));
- Connection.BytesIn := 0;
- Connection.BytesOut := 0;
- UpdateCaption;
- Log(['Starting server...']);
- try
- Main;
- except
- Log(['Server Exception']);
- end;{try...except}
- end;{class)Server.Create}
- class destructor Server.Destroy;
- begin
- Log(['Shutting down server...']);
- if Socket <> 0 then
- begin
- closesocket(Socket);
- Socket := 0;
- end;{if Socket <> 0}
- Sessions.Free;
- ItemData.Free;
- NPCData.Free;
- SpellData.Free;
- ClassData.Free;
- MapData.Free;
- Configuration.Free;
- Database.Free;
- CriticalSection.Free;
- Readln;
- end;{class)Server.Destroy}
- class procedure Server.Main;
- var
- i: Integer;
- FDSet: TFDSet;
- SockAddr: TSockAddr;
- InSocket: TSocket;
- Session: TSession;
- begin
- Log(['Server running']);
- repeat
- Sleep(1);
- FDSet.fd_count := 1;
- FDSet.fd_array[0] := Socket;
- if select(0, @FDSet, nil, nil, nil) = 1 then
- begin
- i := sizeof(SockAddr);
- InSocket := accept(Socket, @SockAddr, @i);
- if InSocket = 0 then continue;
- if BannedIP(SockAddr.sin_addr.S_addr) then
- begin
- closesocket(InSocket);
- Log(['Denied connection from ' + AnsiString(inet_ntoa(SockAddr.sin_addr))]);
- continue;
- end;{if BannedIP}
- i := 0;
- CriticalSection.Enter;
- try
- for Session in Sessions.Items do
- if Session.IPInt = SockAddr.sin_addr.S_addr then
- begin
- inc(i);
- if i = Connection.PerIP then break;
- end;{if Session.IPInt}
- finally
- CriticalSection.Leave;
- end;{try...finally}
- if i = Connection.PerIP then
- closesocket(InSocket)
- else
- TSession.Create(InSocket, SockAddr);
- end;{if select}
- until Socket = 0;
- end;{class)Server.Main}
- class procedure Server.Log(Params: array of const; Prefix: AnsiString = '');
- var
- i: Integer;
- begin
- CriticalSection.Enter;
- try
- if length(Prefix) > 0 then
- Write(Prefix + ' ');
- for i := 0 to high(Params) do
- with TVarRec(Params[i]) do
- case VType of
- vtInteger: Write(VInteger);
- vtBoolean: Write(VBoolean);
- vtChar: Write(VChar);
- vtWideChar: Write(VWideChar);
- vtExtended: Write(VExtended^);
- vtString: Write(AnsiString(VString));
- vtPointer: Write(Cardinal(VPointer));
- vtPChar: Write(AnsiString(VPChar));
- vtObject: Write(VObject.ClassName);
- vtClass: Write(VClass.ClassName);
- vtPWideChar: Write(WideString(VPWideChar));
- vtWideString: Write(WideString(VWideString));
- vtInt64: Write(VInt64^);
- vtUnicodeString: Write(String(VUnicodeString));
- vtAnsiString: Write(AnsiString(VAnsiString));
- else
- Write('?(', VType, ')');
- end;{case VType}
- finally
- Writeln;
- CriticalSection.Leave;
- end;{try...finally}
- end;{class)Server.Log}
- class procedure Server.Send(var Packet: TPacket; Sender: TSession = nil; Ranged: Boolean = True);
- var
- Session: TSession;
- begin
- CriticalSection.Enter;
- try
- for Session in Sessions.Items do
- if (Session <> Sender) and Session.LoggedIn then
- begin
- if Ranged and (Sender <> nil) and
- ((Session.X < (Sender.X - ViewRange)) or (Session.X > (Sender.X + ViewRange)) or
- (Session.Y < (Sender.Y - ViewRange)) or (Session.Y > (Sender.Y + ViewRange))) then
- continue;
- Session.Send(Packet);
- end;{if (Session <> Sender)}
- finally
- CriticalSection.Leave;
- end;{try...finally}
- end;{Server.Send}
- class procedure Server.SendRanged(var Packet: TPacket; X, Y: Integer);
- var
- Session: TSession;
- begin
- CriticalSection.Enter;
- try
- for Session in Sessions.Items do
- if Session.LoggedIn and
- (Session.X > (X - ViewRange)) and (Session.X < (X + ViewRange)) and
- (Session.Y > (Y - ViewRange)) and (Session.Y < (Y + ViewRange)) then
- Session.Send(Packet);
- finally
- CriticalSection.Leave;
- end;{try...finally}
- end;{class)Server.SendRanged}
- class procedure Server.UpdateCaption;
- begin
- CriticalSection.Section(procedure
- var
- NewCaption: AnsiString;
- begin
- NewCaption := 'MEOW - ' +
- Str(length(Sessions.Items)) + ' Connection(s) - ' +
- Scale(Connection.BytesIn) + ' in / ' +
- Scale(Connection.BytesOut) + ' out';
- if NewCaption <> Caption then
- begin
- Caption := NewCaption;
- SetConsoleTitleA(PAnsiChar(Caption));
- end;{if NewCaption <> Caption}
- end);{CriticalSection.Section}
- end;{class)Server.Update}
- class function Server.GetSessionByID(ID: Cardinal): TSession;
- var
- Session: TSession;
- begin
- CriticalSection.Enter;
- try
- for Session in Sessions.Items do
- if Session.ID = ID then exit(Session);
- Result := nil;
- finally
- CriticalSection.Leave;
- end;{try...finally}
- end;{class)Server.GetSessionByID}
- class function Server.GetSessionByName(Name: AnsiString): TSession;
- var
- Session: TSession;
- begin
- Name := Lower(Name);
- CriticalSection.Enter;
- try
- for Session in Sessions.Items do
- if Session.Name = Name then exit(Session);
- Result := nil;
- finally
- CriticalSection.Leave;
- end;{try...finally}
- end;{Server.GetSessionByName}
- class procedure Server.Msg(Msg: AnsiString);
- var
- Packet: TPacket;
- begin
- if length(Msg) = 0 then exit;
- Packet.SetID(PacketFamilyTalk, PacketActionServer);
- Packet.AddString(Msg);
- Send(Packet);
- end;{class)Server.Msg}
- class procedure Server.AdminMsg(Msg: AnsiString; From: AnsiString = '[Server]');
- var
- Packet: TPacket;
- Session: TSession;
- begin
- if length(Msg) = 0 then exit;
- Packet.SetID(PacketFamilyTalk, PacketActionAdmin);
- Packet.AddBreakString(From);
- Packet.AddBreakString(copy(Msg, 1, TextLength));
- Log([Msg], 'Admin');
- CriticalSection.Enter;
- try
- for Session in Sessions.Items do
- if Session.LoggedIn and (Session.Admin > 0) then
- Session.Send(Packet)
- finally
- CriticalSection.Leave;
- end;{try...finally}
- end;{class)AdminMsg}
- class procedure Server.Freeze(Exclude: TSession);
- begin
- CriticalSection.Section(procedure
- var
- Session: TSession;
- begin
- for Session in Sessions.Items do
- if Session.LoggedIn and (Session <> Exclude) then
- Session.Freeze;
- end);{CriticalSection.Section}
- end;{class)Server.Freeze}
- class procedure Server.Unfreeze;
- begin
- CriticalSection.Section(procedure
- var
- Session: TSession;
- begin
- for Session in Sessions.Items do
- if Session.LoggedIn then
- Session.Unfreeze;
- end);{CriticalSection.Section}
- end;{class)Server.Unfreeze}
- class procedure Server.Mute(Exclude: TSession);
- begin
- CriticalSection.Section(procedure
- var
- Session: TSession;
- From: AnsiString;
- begin
- if (Exclude = nil) or (length(Exclude.Name) = 0) then From := 'Server' else From := Exclude.Name;
- for Session in Sessions.Items do
- if Session.LoggedIn and (Session <> Exclude) then
- Session.Mute(From);
- end);{CriticalSection.Section}
- end;{class)Server.Mute}
- class procedure Server.Quake(Scale: Integer);
- begin
- CriticalSection.Section(procedure
- var
- Session: TSession;
- begin
- for Session in Sessions.Items do
- if Session.LoggedIn then
- Session.Quake(Scale);
- end);{CriticalSection.Section}
- end;{class)Server.Quake}
- class procedure Server.Effect(EffectID, X, Y: Integer);
- var
- Packet: TPacket;
- begin
- Packet.SetID(PacketFamilyEffect, PacketActionAgree);
- Packet.AddInt1(X);
- Packet.AddInt1(Y);
- Packet.AddInt2(EffectID);
- SendRanged(Packet, X, Y);
- end;{class)Server.Effect}
- class procedure Server.Sound(SoundID: Integer);
- begin
- CriticalSection.Section(procedure
- var
- Session: TSession;
- begin
- for Session in Sessions.Items do
- if Session.LoggedIn then
- Session.Sound(SoundID);
- end);{CriticalSection.Section}
- end;{class)Server.Sound}
- class procedure Server.SetMap(MapFile: AnsiString = '');
- begin
- CriticalSection.Section(procedure
- var
- OldFile: AnsiString;
- begin
- OldFile := MapData.FileName;
- if length(MapFile) > 0 then
- MapData.FileName := MapFile + '.emf';
- if not MapData.Load then
- begin
- Log(['Failed to load map data ', MapFile]);
- MapData.FileName := OldFile;
- MapData.Load;
- exit;
- end;{if MapData.Load}
- end);{CriticalSection.Section}
- Mutate;
- end;{Server.SetMap}
- class procedure Server.Mutate;
- begin
- CriticalSection.Section(procedure
- var
- Packet: TPacket;
- Session: TSession;
- begin
- Packet.SetID(PacketFamilyRaw, PacketActionRaw);
- Packet.AddInt1(9);
- Packet.AddString(MapData.Data);
- for Session in Sessions.Items do
- if Session.LoggedIn then
- begin
- Session.Send(Packet, True);
- Session.RefreshAll;
- end;{if Session.LoggedIn}
- end);{CriticalSection.Section}
- end;{class)Server.Mutate}
- class procedure Server.OpenDoor(X, Y: Integer);
- var
- Packet: TPacket;
- begin
- if (X < 0) or (X >= MapData.Width) or
- (Y < 0) or (Y >= MapData.Height) then exit;
- if not MapData.Tiles[Y, X].Warp.Enabled then exit;
- Packet.SetID(PacketFamilyDoor, PacketActionOpen);
- Packet.AddInt1(X);
- Packet.AddInt2(Y);
- SendRanged(Packet, X, Y);
- end;{class)Server.OpenDoor}
- class procedure Server.Shutdown;
- var
- Packet: TPacket;
- begin
- Packet.SetID(PacketFamilyMessage, PacketActionClose);
- Send(Packet);
- end;{Server.Shutdown}
- class function Server.ValidName(Name: AnsiString; IgnoreUnapproved: Boolean = False): Boolean;
- var
- s: AnsiString;
- c: AnsiChar;
- begin
- if (length(Name) < 3) or (length(Name) > NameMax) then exit(False);
- for c in Name do
- if pos(String(c), NameChars) = 0 then
- exit(False);
- if not IgnoreUnapproved then
- for s in Unapproved.Items do
- if Match(lower(s), Name) then exit(False);
- Result := True;
- end;{class)Server.ValidName}
- class function Server.GetAccount(Name: AnsiString; Items: AnsiString = '*'): TDatabase.TTable;
- begin
- Result := Database.QueryTable('SELECT ' + Items + ' FROM `accounts` WHERE `name` = "' + Name + '";');
- end;{class)Server.GetAccount}
- class function Server.AccountExists(Name: AnsiString): Boolean;
- begin
- with GetAccount(Name, '`id`') do try
- Result := length(Table) > 0
- finally
- Free;
- end;{with GetAccount}
- end;{class)Server.AccountExists}
- class procedure Server.BanIP(IP: AnsiString);
- var
- IIP: Integer;
- begin
- if length(IP) = 0 then exit;
- IIP := inet_addr(PAnsiChar(IP));
- if IIP = localhost then exit;
- if Server.BannedIP(IIP) then exit;
- if Server.Database.Query('INSERT INTO `banned` (`ip`) VALUES (' + Str(IIP) + ');') then
- Log(['Banned IP ' + IP])
- else
- Log(['Failed to insert IP ban [' + IP + '] into database']);
- end;{Server.BanIP}
- class procedure Server.UnbanIP(IP: AnsiString);
- var
- IIP: Integer;
- begin
- if length(IP) = 0 then exit;
- IIP := inet_addr(PAnsiChar(IP));
- if not Server.BannedIP(IIP) then exit;
- if Server.Database.Query('DELETE FROM `banned` WHERE `ip` = ' + Str(IIP) + ';') then
- Log(['Unbanned IP ' + IP])
- else
- Log(['Failed to delete IP ban [' + IP + '] from database']);
- end;{Server.UnbanIP}
- class function Server.BannedIP(IP: Integer): Boolean;
- begin
- Result := not Database.QueryTable('SELECT * FROM `banned` WHERE `ip` = ' + Str(IP) + ';').Empty;
- end;{Server.BannedIP}
- procedure Server.TPacket.SetID(AFamily, AAction: Byte);
- begin
- Family := AFamily;
- Action := AAction;
- end;{Server.TPacket.SetID}
- procedure Server.TPacket.Reset;
- begin
- Data := '';
- end;{Server.TPacket.Reset}
- procedure Server.TPacket.Discard(Count: Integer = 1);
- begin
- Data := copy(Data, Count + 1, length(Data));
- end;{Server.TPacket.Discard}
- procedure Server.TPacket.AddByte(b: Byte);
- begin
- Data := Data + AnsiChar(b);
- end;{Server.TPacket.AddByte}
- procedure Server.TPacket.AddInt1(i: Byte);
- begin
- Data := Data + UnpackEOInt(i)[1];
- end;{Server.TPacket.AddInt1}
- procedure Server.TPacket.AddInt2(i: Word);
- begin
- Data := Data + copy(UnpackEOInt(i), 1, 2);
- end;{Server.TPacket.AddInt2}
- procedure Server.TPacket.AddInt3(i: Cardinal);
- begin
- Data := Data + copy(UnpackEOInt(i), 1, 3);
- end;{Server.TPacket.AddInt3}
- procedure Server.TPacket.AddInt4(i: Cardinal);
- begin
- Data := Data + UnpackEOInt(i);
- end;{Server.TPacket.AddInt4}
- procedure Server.TPacket.AddBreakString(s: AnsiString);
- begin
- Data := Data + s + #$FF;
- end;{Server.TPacket.AddBreakString}
- procedure Server.TPacket.AddString(s: AnsiString);
- begin
- Data := Data + s;
- end;{Server.TPacket.AddString}
- function Server.TPacket.GetByte: Byte;
- begin
- if length(Data) = 0 then exit(0);
- Result := ord(Data[1]);
- Data := copy(Data, 2, length(Data));
- end;{Server.TPacket.GetByte}
- function Server.TPacket.GetInt1: Byte;
- begin
- if length(Data) = 0 then exit(0);
- Result := PackEOInt(ord(Data[1]));
- Data := copy(Data, 2, length(Data));
- end;{Server.TPacket.GetInt1}
- function Server.TPacket.GetInt2: Word;
- begin
- if length(Data) = 0 then exit(0);
- if length(Data) < 2 then exit(GetInt1);
- Result := PackEOInt(ord(Data[1]), ord(Data[2]));
- Data := copy(Data, 3, length(Data));
- end;{Server.TPacket.GetInt2}
- function Server.TPacket.GetInt3: Cardinal;
- begin
- if length(Data) = 0 then exit(0);
- if length(Data) < 2 then exit(GetInt1);
- if length(Data) < 3 then exit(GetInt2);
- Result := PackEOInt(ord(Data[1]), ord(Data[2]), ord(Data[3]));
- Data := copy(Data, 4, length(Data));
- end;{Server.TPacket.GetInt3}
- function Server.TPacket.GetInt4: Cardinal;
- begin
- if length(Data) = 0 then exit(0);
- if length(Data) < 2 then exit(GetInt1);
- if length(Data) < 3 then exit(GetInt2);
- if length(Data) < 4 then exit(GetInt3);
- Result := PackEOInt(ord(Data[1]), ord(Data[2]), ord(Data[3]), ord(Data[4]));
- Data := copy(Data, 5, length(Data));
- end;{Server.TPacketGetInt4}
- function Server.TPacket.GetBreakString: AnsiString;
- var
- i: Integer;
- begin
- for i := 1 to length(Data) do
- if Data[i] = #$FF then break;
- Result := copy(Data, 1, i - 1);
- Data := copy(Data, i + 1, length(Data));
- end;{Server.TPacket.GetBreakString}
- function Server.TPacket.GetString(Len: Integer = -1): AnsiString;
- begin
- if Len = -1 then
- begin
- Result := Data;
- Data := '';
- end{if Len = -1}
- else
- begin
- Result := copy(Data, 1, Len);
- Data := copy(Data, Len + 1, length(Data));
- end;{else}
- end;{Server.TPacket.GetString}
- constructor Server.TGameData.Create(AFileName: AnsiString);
- begin
- inherited Create;
- FileName := AFileName;
- Load;
- end;{Server.TGameData.Create}
- destructor Server.TGameData.Destroy;
- begin
- Clear;
- inherited;
- end;{Server.TGameData.Destroy}
- function Server.TGameData.Load: Boolean;
- var
- l: Cardinal;
- f: THandle;
- begin
- Clear;
- {$IFDEF INTERNAL_PUB}
- case DataID of
- 5: Data := ItemPubData;
- 6: Data := NPCPubData;
- 7: Data := SpellPubData;
- 11: Data := ClassPubData;
- else
- {$ENDIF INTERNAL_PUB}
- Log([ClassName, ' (', FileName, ') loading...']);
- f := CreateFileA(PAnsiChar(FileName), GENERIC_READ, 0, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
- if f = 0 then exit(False);
- try
- l := SetFilePointer(f, 0, nil, FIlE_END);
- if (l = Cardinal(-1)) or (l < 11) then exit(False);
- SetLength(Data, l);
- SetFilePointer(f, 0, nil, FILE_BEGIN);
- ReadFile(f, Data[1], l, l, nil);
- finally
- CloseHandle(f);
- end;{try...finally}
- {$IFDEF INTERNAL_PUB}
- end;{case DataID}
- {$ENDIF INTERNAL_PUB}
- CRC[0] := ord(Data[4]);
- CRC[1] := ord(Data[5]);
- CRC[2] := ord(Data[6]);
- CRC[3] := ord(Data[7]);
- Len[0] := ord(Data[8]);
- Len[1] := ord(Data[9]);
- Result := True;
- end;{Server.TGameData.Load}
- procedure Server.TGameData.Clear;
- begin
- Data := '';
- CRC[0] := 0;
- CRC[1] := 0;
- CRC[2] := 0;
- CRC[3] := 0;
- Len[0] := 0;
- Len[1] := 0;
- end;{Server.TGameData.Clear}
- class function Server.TItemData.DataID: Byte;
- begin
- Result := 5;
- end;{class)Server.TItemData.DataID}
- class function Server.TNPCData.DataID: Byte;
- begin
- Result := 6;
- end;{class)Server.TNPCData.DataID}
- class function Server.TSpellData.DataID: Byte;
- begin
- Result := 7;
- end;{class)Server.TSpellData.DataID}
- class function Server.TClassData.DataID: Byte;
- begin
- Result := 11;
- end;{class)Server.TClassData.DataID}
- class function Server.TMapData.DataID: Byte;
- begin
- Result := 4;
- end;{class)Server.TMapData.DataID}
- function Server.TMapData.Load: Boolean;
- function ReadInt(Loc: Integer; Size: Integer = 1): Integer;
- var
- Ords: AnsiString;
- begin
- Ords := copy(Data, Loc, Size) + #0#0#0#0;
- Result := PackEOInt(ord(Ords[1]), ord(Ords[2]), ord(Ords[3]), ord(Ords[4]));
- end;{ReadInt}
- function ReadIntN(var Loc: Integer; Size: Integer = 1): Integer; inline;
- begin
- Result := ReadInt(Loc, Size); inc(Loc, Size);
- end;{ReadIntN}
- var
- i, j: Integer;
- x, y: Integer;
- p: Integer;
- Outer: Integer;
- Inner: Integer;
- begin
- Result := inherited;
- if not Result then exit;
- Width := ReadInt($26) + 1;
- Height := ReadInt($27) + 1;
- SetLength(Tiles, Height, Width);
- for y := 0 to Height - 1 do
- for x := 0 to Width - 1 do
- with Tiles[y, x] do
- begin
- Kind := 0;
- Warp.Enabled := False;
- end;{with Tiles[y, x]}
- Outer := ReadInt($2F); p := $30 + ( 8 * Outer);
- Outer := ReadIntN(p); p := p + ( 4 * Outer);
- Outer := ReadIntN(p); p := p + (12 * Outer);
- Outer := ReadIntN(p); p := p;
- for i := 0 to Outer - 1 do
- begin
- y := ReadIntN(p);
- Inner := ReadIntN(p);
- for j := 0 to Inner - 1 do
- begin
- x := ReadIntN(p);
- with Tiles[y, x] do
- begin
- Kind := ReadIntN(p) + 1;
- //Warp.Enabled := False;
- end;{with Tiles[y, x]}
- end;{for j}
- end;{for i}
- Outer := ReadIntN(p);
- for i := 0 to Outer - 1 do
- begin
- y := ReadIntN(p);
- Inner := ReadIntN(p);
- for j := 0 to Inner - 1 do
- begin
- x := ReadIntN(p);
- with Tiles[y, x] do
- begin
- Warp.Enabled := True;
- Warp.M := ReadIntN(p, 2);
- Warp.X := ReadIntN(p);
- Warp.Y := ReadIntN(p);
- Warp.ReqLevel := ReadIntN(p);
- Warp.ReqItem := ReadIntN(p, 2);
- end;{with Tiles[y, x]}
- end;{for j}
- end;{for i}
- end;{Server.TMapData.Load}
- procedure Server.TMapData.Clear;
- begin
- inherited;
- end;{Server.TMapData.Clear}
- function Server.TMapData.IsWalkable(X, Y: Integer; NPC: Boolean = False): Boolean;
- begin
- if (X < 0) or (X >= Width) or (Y < 0) or (Y >= Height) then exit(False);
- if NPC and (Tiles[Y, X].Kind = MapTileNPCBoundary) then exit(False);
- Result := not (Tiles[Y, X].Kind in MapTilesImpassible);
- end;{Server.TMapData.IsWalkable}
- function SessionThread(Session: Server.TSession): Integer;
- begin
- Result := 0;
- try
- try
- while Session.Execute do
- Sleep(1);
- except
- Server.Log(['Session exception']);
- end;{try...except}
- finally
- Server.CriticalSection.Enter;
- try Session.Free; except end;
- Server.CriticalSection.Leave;
- EndThread(Result);
- end;{try...finally}
- end;{SessionThread}
- constructor Server.TSession.Create(ASocket: TSocket; ASockAddr: TSockAddr);
- var
- i: Integer;
- begin
- inherited Create;
- Initialized := False;
- LoggedIn := False;
- Offline := False;
- Party := nil;
- Unload;
- Socket := ASocket;
- Offline := Socket = 0;
- if Offline then exit;
- IPStr := AnsiString(inet_ntoa(ASockAddr.sin_addr));
- IPInt := ASockAddr.sin_addr.S_addr;
- i := 1;
- ioctlsocket(Socket, FIONBIO, i);
- Server.CriticalSection.Section(procedure
- begin
- ID := 100;
- while Server.GetSessionByID(ID) <> nil do inc(ID);
- Server.Sessions.Add(Self);
- end);{Server.CriticalSection.Section}
- Packet.Time := GetTickCount + Server.Connection.Timeout;
- ClearQueue;
- Log(['Created']);
- BeginThread(nil, 0, @SessionThread, Pointer(Self), 0, Thread);
- Server.UpdateCaption;
- end;{Server.TSession.Create}
- class function Server.TSession.CreateOffline(AName: AnsiString): TSession;
- var
- InAddr: sockaddr_in;
- begin
- if Server.GetSessionByName(AName) <> nil then exit(nil);
- Result := TSession.Create(0, InAddr);
- Result.Name := AName;
- Result.IPStr := '(offline)';
- Result.Usage.Started := False;
- Result.Party := nil;
- Result.LoggedIn := Result.Sync(True);
- if not Result.LoggedIn then
- begin
- Result.Unload;
- Result.Free;
- Result := nil;
- end;{if not Result.LoggedIn}
- end;{Server.TSession.Create (offline)}
- destructor Server.TSession.Destroy;
- begin
- Logout;
- Disconnect;
- Server.CriticalSection.Section(procedure
- begin
- Server.Sessions.Remove(Self);
- end);{Server.CriticalSection.Section}
- Log(['Destroyed']);
- inherited;
- Server.UpdateCaption;
- end;{Server.TSession.Destroy}
- procedure Server.TSession.ClearQueue;
- begin
- SetLength(Packet.Queue.Items, 0);
- Packet.Queue.Time := GetTickCount;
- end;{Server.TSession.ClearQueue}
- procedure Server.TSession.Disconnect;
- begin
- if Socket <> 0 then
- begin
- closesocket(Socket);
- Socket := 0;
- end;{if Socket <> 0}
- end;{Server.TSession.Disconnect}
- function Server.TSession.Sync(Discard: Boolean = False): Boolean;
- var
- SQL: AnsiString;
- begin
- if length(Name) = 0 then exit(False);
- if Discard then
- with Server.GetAccount(Name) do try
- if length(Table) = 0 then exit(False);
- Banned := Value('banned', 0, 0);
- Password := Value('password', 0, '');
- if length(Password) = 0 then exit(False);
- State := Value('state', 0, 0);
- Usage.Current := Value('usage', 0, 0);
- X := Value('x', 0, Server.Defaults.X);
- Y := Value('y', 0, Server.Defaults.Y);
- D := Value('d', 0, Server.Defaults.D);
- Sitting := Value('s', 0, 0);
- //Hidden := Value('h', 0, 0);
- Admin := Value('admin', 0, 0);
- Tag := copy(Value('tag', 0, ''), 1, 3);
- Sex := Value('sex', 0, 0);
- HairStyle := Value('hairstyle', 0, 0);
- HairColour := Value('haircolour', 0, 0);
- Race := Value('race', 0, 0);
- Boots := Value('boots', 0, 0);
- Armour := Value('armour', 0, 0);
- Hat := Value('hat', 0, 0);
- Shield := Value('shield', 0, 0);
- Weapon := Value('weapon', 0, 0);
- Gold := Value('gold', 0, Server.Defaults.Gold);
- HP := Value('hp', 0, Server.Defaults.HP);
- MaxHP := Value('maxhp', 0, Server.Defaults.MaxHP);
- TP := Value('tp', 0, Server.Defaults.TP);
- MaxTP := Value('maxtp', 0, Server.Defaults.MaxTP);
- Kills := Value('kills', 0, 0);
- if MaxHP < 1 then MaxHP := 1;
- Result := True;
- finally
- Free;
- end{with Server.GetAccount}
- else
- begin
- if not Server.AccountExists(Name) then
- begin
- SQL := 'INSERT INTO `accounts` (`name`) VALUES ("' + Name + '");';
- Result := Server.Database.Query(SQL);
- if not Result then
- begin
- Log(['Failed to insert into database']);
- exit;
- end;{if not Result}
- end;{if not Server.AccountExists}
- if Usage.Started then
- begin
- Usage.Current := Usage.Current + ((GetTickCount - Usage.Last) div 60000);
- Usage.Last := GetTickCount;
- end;{if Usage.Started}
- SQL := 'UPDATE `accounts` SET ' +
- '`banned` = ' + Str(Banned) + ', ' +
- '`password` = "' + Password + '", ' +
- '`state` = ' + Str(State) + ', ' +
- '`usage` = ' + Str(Usage.Current) + ', ' +
- '`x` = ' + Str(X) + ', ' +
- '`y` = ' + Str(Y) + ', ' +
- '`d` = ' + Str(D) + ', ' +
- '`s` = ' + Str(Sitting) + ', ' +
- //'`s` = ' + Str(Hidden) + ', ' +
- '`admin` = ' + Str(Admin) + ', ' +
- '`tag` = "' + Tag + '", ' +
- '`sex` = ' + Str(Sex) + ', ' +
- '`hairstyle` = ' + Str(HairStyle) + ', ' +
- '`haircolour` = ' + Str(HairColour) + ', ' +
- '`race` = ' + Str(Race) + ', ' +
- '`boots` = ' + Str(Boots) + ', ' +
- '`armour` = ' + Str(Armour) + ', ' +
- '`hat` = ' + Str(Hat) + ', ' +
- '`shield` = ' + Str(Shield) + ', ' +
- '`weapon` = ' + Str(Weapon) + ', ' +
- '`gold` = ' + Str(Gold) + ', ' +
- '`hp` = ' + Str(HP) + ', ' +
- '`maxhp` = ' + Str(MaxHP) + ', ' +
- '`tp` = ' + Str(TP) + ', ' +
- '`maxtp` = ' + Str(MaxTP) + ', ' +
- '`kills` = ' + Str(Kills) +
- ' WHERE `name` = "' + Name + '";';
- Result := Server.Database.Query(SQL);
- if not Result then Log(['Database sync failed']);
- end{else}
- end;{Server.TSession.Sync}
- procedure Server.TSession.Unload;
- begin
- Usage.Started := False;
- Name := '';
- Password := '';
- LoggedIn := False;
- WarpInfo.Time := 0;
- end;{Server.TSession.Unload}
- procedure Server.TSession.Log(Params: array of const);
- var
- S: AnsiString;
- begin
- S := 'Session (' + IPStr + ')';
- if LoggedIn and (length(Name) > 0) then
- S := S + ' "' + Name + '"';
- Server.Log(Params, S);
- end;{Server.TSession.Log}
- procedure Server.TSession.Send(var Packet: TPacket; Raw: Boolean = False);
- var
- i, j, Size: Integer;
- Encoded: AnsiString;
- EncodeBuf: AnsiString;
- begin
- if Offline then exit;
- Encoded := copy(UnpackEOInt(length(Packet.Data) + 2), 1, 2) +
- AnsiChar(Packet.Action) +
- AnsiChar(Packet.Family) +
- Packet.Data;
- Size := length(Encoded);
- if not Raw then
- begin
- Encoded := FoldData(Encoded, Server.SendKey);
- SetLength(EncodeBuf, Size);
- EncodeBuf[1] := Encoded[1];
- EncodeBuf[2] := Encoded[2];
- i := 2; j := 2;
- while i < Size do
- begin
- EncodeBuf[i + 1] := AnsiChar(ord(Encoded[j + 1]) xor $80);
- inc(j);
- inc(i, 2);
- end;{while i < Size}
- i := Size - 1;
- if Boolean(Size mod 2) then dec(i);
- while i >= 2 do
- begin
- EncodeBuf[i + 1] := AnsiChar(ord(Encoded[j + 1]) xor $80);
- inc(j);
- dec(i, 2);
- end;{while i >= 2}
- for i := 3 to Size do
- if EncodeBuf[i] = #128 then EncodeBuf[i] := #0
- else if EncodeBuf[i] = #0 then EncodeBuf[i] := #128;
- Encoded := EncodeBuf;
- end;{if not Raw}
- WinSock.send(Socket, Encoded[1], Size, 0);
- InterlockedExchangeAdd64(Server.Connection.BytesOut, Size);
- Server.UpdateCaption;
- end;{Server.TSession.Send}
- procedure Server.TSession.Send(Raw: Boolean = False);
- begin
- Send(Packet.Send, Raw);
- end;{Server.TSession.Send}
- procedure Server.TSession.SendData(Data: TGameData);
- var
- Packet: Server.TPacket;
- begin
- Packet.SetID(PacketFamilyRaw, PacketActionRaw);
- Packet.AddInt1(Data.DataID);
- if Data.DataID <> 4 then
- Packet.AddInt1(1);
- Packet.AddString(Data.Data);
- Send(Packet, True);
- end;{Server.TSession.SendData}
- procedure Server.TSession.Login;
- var
- i: Integer;
- Packet: TPacket;
- Tag: AnsiString;
- begin
- Packet.SetID(PacketFamilyGameState, PacketActionReply);
- Packet.AddInt2(1);
- Packet.AddInt2(ID);
- Packet.AddInt4(ID);
- Packet.AddInt2(1); // Map ID
- Packet.AddByte(Server.MapData.CRC[0]);
- Packet.AddByte(Server.MapData.CRC[1]);
- Packet.AddByte(Server.MapData.CRC[2]);
- Packet.AddByte(Server.MapData.CRC[3]);
- Packet.AddInt3(length(Server.MapData.Data));
- Packet.AddByte(Server.ItemData.CRC[0]);
- Packet.AddByte(Server.ItemData.CRC[1]);
- Packet.AddByte(Server.ItemData.CRC[2]);
- Packet.AddByte(Server.ItemData.CRC[3]);
- Packet.AddByte(Server.ItemData.Len[0]);
- Packet.AddByte(Server.ItemData.Len[1]);
- Packet.AddByte(Server.NPCData.CRC[0]);
- Packet.AddByte(Server.NPCData.CRC[1]);
- Packet.AddByte(Server.NPCData.CRC[2]);
- Packet.AddByte(Server.NPCData.CRC[3]);
- Packet.AddByte(Server.NPCData.Len[0]);
- Packet.AddByte(Server.NPCData.Len[1]);
- Packet.AddByte(Server.SpellData.CRC[0]);
- Packet.AddByte(Server.SpellData.CRC[1]);
- Packet.AddByte(Server.SpellData.CRC[2]);
- Packet.AddByte(Server.SpellData.CRC[3]);
- Packet.AddByte(Server.SpellData.Len[0]);
- Packet.AddByte(Server.SpellData.Len[1]);
- Packet.AddByte(Server.ClassData.CRC[0]);
- Packet.AddByte(Server.ClassData.CRC[1]);
- Packet.AddByte(Server.ClassData.CRC[2]);
- Packet.AddByte(Server.ClassData.CRC[3]);
- Packet.AddByte(Server.ClassData.Len[0]);
- Packet.AddByte(Server.ClassData.Len[1]);
- Packet.AddBreakString(Name);
- Packet.AddBreakString(IPStr); // Title
- Packet.AddBreakString(''); // Guild
- Packet.AddBreakString(''); // Rank
- Packet.AddInt1(0); // Class
- if IPInt = localhost then
- Tag := Server.Admin.TagLocalhost
- else if Admin > 0 then
- Tag := Server.Admin.TagAdmin
- else
- Tag := '';
- Packet.AddString(copy(Tag + #160' ', 1, 3));
- Packet.AddInt1(Admin); // Admin
- Packet.AddInt1(0); // Level
- Packet.AddInt4(0); // Exp
- Packet.AddInt4(Usage.Current);
- Packet.AddInt2(HP);
- Packet.AddInt2(MaxHP);
- Packet.AddInt2(TP);
- Packet.AddInt2(MaxTP);
- Packet.AddInt2(10); // MaxSP
- Packet.AddInt2(0); // Stat points
- Packet.AddInt2(0); // Skill points
- Packet.AddInt2(0); // Karma
- Packet.AddInt2(0); // Min damage
- Packet.AddInt2(0); // Max damage
- Packet.AddInt2(0); // Accuracy
- Packet.AddInt2(0); // Evade
- Packet.AddInt2(0); // Armour
- Packet.AddInt2(0); // Str
- Packet.AddInt2(0); // Int
- Packet.AddInt2(0); // Wis
- Packet.AddInt2(0); // Agi
- Packet.AddInt2(0); // Con
- Packet.AddInt2(0); // Cha
- for i := 0 to 14 do
- Packet.AddInt2(0); // Paperdoll
- Packet.AddInt1(1); // Guild Rank
- Packet.AddInt2(0); // Jail map
- Packet.AddInt2(4);
- Packet.AddInt1(24);
- Packet.AddInt1(24);
- Packet.AddInt2(10);
- Packet.AddInt2(10);
- Packet.AddInt2(0);
- Packet.AddInt2(2);
- Packet.AddInt1(1);
- Packet.AddByte(255);
- Send(Packet);
- Usage.Last := GetTickCount;
- Usage.Started := True;
- end;{Server.TSession.Login}
- procedure Server.TSession.Logout;
- var
- Packet: TPacket;
- begin
- if not LoggedIn then exit;
- if Party <> nil then
- Party.Leave(Self);
- Packet.SetID(PacketFamilyPlayers, PacketActionRemove);
- Packet.AddInt2(ID);
- Server.Send(Packet, Self);
- Sync;
- Unload;
- end;{Server.TSession.Logout}
- procedure Server.TSession.BuildCharacterPacket(var Packet: TPacket);
- var
- Tag: AnsiString;
- begin
- Packet.AddBreakString(Name);
- Packet.AddInt2(ID);
- if LoggedIn then
- begin
- Packet.AddInt2(1);
- Packet.AddInt2(X);
- Packet.AddInt2(Y);
- end{if LoggedIn}
- else
- begin
- Packet.AddInt2(0);
- Packet.AddInt2(0);
- Packet.AddInt2(0);
- end;{else}
- Packet.AddInt1(D);
- Packet.AddInt1(6);
- if IPInt = localhost then
- Tag := Server.Admin.TagLocalhost
- else if Admin > 0 then
- Tag := Server.Admin.TagAdmin
- else
- Tag := '';
- Packet.AddString(copy(Tag + #160' ', 1, 3));
- Packet.AddInt1(0); // Level
- Packet.AddInt1(Sex);
- Packet.AddInt1(HairStyle);
- Packet.AddInt1(HairColour);
- Packet.AddInt1(Race);
- Packet.AddInt2(MaxHP);
- Packet.AddInt2(HP);
- Packet.AddInt2(MaxTP);
- Packet.AddInt2(TP);
- Packet.AddInt2(Boots);
- Packet.AddInt2(0);
- Packet.AddInt2(0);
- Packet.AddInt2(0);
- Packet.AddInt2(Armour);
- Packet.AddInt2(0);
- Packet.AddInt2(Hat);
- Packet.AddInt2(Shield);
- Packet.AddInt2(Weapon);
- Packet.AddInt1(Sitting);
- if LoggedIn then
- Packet.AddInt1(Hidden)
- else
- Packet.AddInt1(1);
- end;{Server.TSession.BuildCharacterPacket}
- procedure Server.TSession.Refresh;
- var
- Packet: TPacket;
- begin
- if (not LoggedIn) or Offline then exit;
- Packet.SetID(PacketFamilyPlayers, PacketActionRemove);
- Packet.AddInt2(ID);
- Server.Send(Packet);
- Packet.Reset;
- Packet.SetID(PacketFamilyPlayers, PacketActionAgree);
- Packet.AddByte(255);
- BuildCharacterPacket(Packet);
- Packet.AddInt1(1);
- Packet.AddByte(255);
- Packet.AddInt1(1);
- Server.Send(Packet);
- end;{Server.TSession.Refresh}
- procedure Server.TSession.RefreshAll;
- var
- Packet: TPacket;
- begin
- if (not LoggedIn) or Offline then exit;
- Packet.SetID(PacketFamilyRefresh, PacketActionReply);
- Server.CriticalSection.Section(procedure
- var
- p, Count: Integer;
- Session: TSession;
- begin
- p := length(Packet.Data) + 1;
- Packet.AddInt1(0);
- Packet.AddByte(255);
- Count := 0;
- for Session in Server.Sessions.Items do
- if Session.LoggedIn then
- begin
- Session.BuildCharacterPacket(Packet);
- Packet.AddByte(255);
- inc(Count);
- end;{if Session.LoggedIn}
- Packet.Data[p] := UnpackEOInt(Count)[1];
- end);{Server.CriticalSection.Section}
- Packet.AddByte(255);
- Send(Packet);
- end;{Server.TSession.RefreshAll}
- function Server.TSession.Walk(Direction: Integer; Admin: Boolean = False; Ghost: Boolean = False; SendToSelf: Boolean = False): Boolean;
- var
- i: Integer;
- State: Integer;
- NewX, NewY: Integer;
- PacketShow: TPacket;
- PacketHide: TPacket;
- PacketWalk: TPacket;
- PacketChar: TPacket;
- Session: TSession;
- NewCoords: array[-Server.ViewRange..Server.ViewRange] of TPoint;
- OldCoords: array[-Server.ViewRange..Server.ViewRange] of TPoint;
- begin
- if (not LoggedIn) or Offline then exit(False);
- NewX := X;
- NewY := Y;
- case Direction of
- DirectionDown: inc(NewY);
- DirectionLeft: dec(NewX);
- DirectionUp: dec(NewY);
- DirectionRight: inc(NewX);
- else
- Log(['Invalid walk direction ', Direction]);
- exit(False);
- end;{case Direction}
- if (NewX < 0) or (NewX >= Server.MapData.Width) or (NewY < 0) or (NewY >= Server.MapData.Height) then exit(False);
- if (not Admin) and (not Server.MapData.IsWalkable(NewX, NewY, False)) then exit(False);
- if (not Admin) and (not Ghost) then
- begin
- Server.CriticalSection.Enter;
- try
- for Session in Server.Sessions.Items do
- if (Session <> Self) and (Session.LoggedIn) and (Session.X = NewX) and (Session.Y = NewY) then exit(False);
- finally
- Server.CriticalSection.Leave;
- end;{try...finally}
- end;{if (not Admin) and (not Ghost)}
- D := Direction;
- X := NewX;
- Y := NewY;
- PacketShow.SetID(PacketFamilyPlayers, PacketActionAgree);
- PacketShow.AddByte(255);
- BuildCharacterPacket(PacketShow);
- PacketShow.AddByte(255);
- PacketShow.AddInt1(1);
- PacketHide.SetID(PacketFamilyPlayers, PacketActionRemove);
- PacketHide.AddInt2(ID);
- PacketWalk.SetID(PacketFamilyWalk, PacketActionPlayer);
- PacketWalk.AddInt2(ID);
- PacketWalk.AddInt1(D);
- PacketWalk.AddInt1(X);
- PacketWalk.AddInt1(Y);
- for i := -Server.ViewRange to Server.ViewRange do
- case Direction of
- DirectionDown:
- begin
- NewCoords[i].X := X + i;
- NewCoords[i].Y := Y + Server.ViewRange - abs(i);
- OldCoords[i].X := X + i;
- OldCoords[i].Y := Y - Server.ViewRange - 1 + abs(i);
- end;{DirectionDown:}
- DirectionLeft:
- begin
- NewCoords[i].X := X - Server.ViewRange + abs(i);
- NewCoords[i].Y := Y + i;
- OldCoords[i].X := X + Server.ViewRange + 1 - abs(i);
- OldCoords[i].Y := Y + i;
- end;{DirectionLeft:}
- DirectionUp:
- begin
- NewCoords[i].X := X + i;
- NewCoords[i].Y := Y - Server.ViewRange + abs(i);
- OldCoords[i].X := X + i;
- OldCoords[i].Y := Y + Server.ViewRange + 1 - abs(i);
- end;{DirectionUp:}
- DirectionRight:
- begin
- NewCoords[i].X := X + Server.ViewRange - abs(i);
- NewCoords[i].Y := Y + i;
- OldCoords[i].X := X - Server.ViewRange - 1 + abs(i);
- OldCoords[i].Y := Y + i;
- end;{DirectionRight:}
- end;{case Direction}
- Server.CriticalSection.Enter;
- try
- for Session in Server.Sessions.Items do
- if (Session <> Self) and Session.LoggedIn and
- (Session.X >= (X - Server.ViewRange)) and (Session.X <= (X + Server.ViewRange)) and
- (Session.Y >= (Y - Server.ViewRange)) and (Session.Y <= (Y + Server.ViewRange)) and
- (length(Session.Name) > 0) then
- begin
- State := 0;
- for i := -Server.ViewRange to Server.ViewRange do
- if (Session.X = NewCoords[i].X) and (Session.Y = NewCoords[i].Y) then
- begin
- State := 1;
- break;
- end{if (Session.X...}
- else if (Session.X = OldCoords[i].X) and (Session.Y = OldCoords[i].Y) then
- begin
- State := -1;
- break;
- end;{else if (Session.X...}
- case State of
- 1:
- begin
- PacketChar.Reset;
- PacketChar.SetID(PacketFamilyPlayers, PacketActionAgree);
- PacketChar.AddByte(255);
- Session.BuildCharacterPacket(PacketChar);
- PacketChar.AddByte(255);
- PacketChar.AddInt1(1);
- Session.Send(PacketShow);
- Send(PacketChar);
- end;{1:}
- -1:
- begin
- PacketChar.Reset;
- PacketChar.SetID(PacketFamilyPlayers, PacketActionRemove);
- PacketChar.AddInt2(Session.ID);
- Session.Send(PacketHide);
- Send(PacketChar);
- end;{-1:}
- else
- Session.Send(PacketWalk);
- end;{case State}
- end;{if Session <> Self}
- finally
- Server.CriticalSection.Leave;
- end;{try...finally}
- if SendToSelf then
- Send(PacketWalk);
- with Server.MapData.Tiles[Y, X].Warp do
- if Enabled then Self.Warp(X, Y);
- Result := True;
- end;{Server.TSession.Walk}
- function Server.TSession.Face(Direction: Integer; SendToSelf: Boolean = False): Boolean;
- var
- Packet: TPacket;
- begin
- if (not LoggedIn) or Offline then exit(False);
- if (Direction < 0) or (Direction > 3) then
- begin
- Log(['Invalid face direction ', Direction]);
- exit(False);
- end;{if Direction..}
- D := Direction;
- Packet.SetID(PacketFamilyFace, PacketActionPlayer);
- Packet.AddInt2(ID);
- Packet.AddInt1(D);
- if SendToSelf then Send(Packet);
- Server.Send(Packet, Self);
- Result := True;
- end;{Server.TSession.Face}
- function Server.TSession.Say(Text: AnsiString; SendToSelf: Boolean = False): Boolean;
- var
- i: Integer;
- Packet: TPacket;
- Player: AnsiString;
- Cmd: AnsiString;
- Session: TSession;
- begin
- if (not LoggedIn) or Offline then exit(False);
- if length(Text) = 0 then exit(False);
- Result := True;
- Packet.SetID(PacketFamilyTalk, PacketActionPlayer);
- Packet.AddInt2(ID);
- Packet.AddString(copy(Text, 1, Server.TextLength));
- if Text[1] = '#' then
- begin
- Text := Trim(copy(Text, 2, length(Text)));
- if length(Text) = 0 then exit(False);
- Cmd := Split(Text);
- if Cmd = 'server' then
- begin
- end
- else
- Result := False;
- exit;
- end{'#'}
- else if Text[1] = Server.Admin.CommandChar then
- begin
- Text := Trim(copy(Text, 2, length(Text)));
- if length(Text) = 0 then exit(False);
- Cmd := Split(Text);
- if Cmd[1] = Server.Admin.CommandChar then
- begin
- Cmd := copy(Cmd, 2, length(Cmd));
- Player := Split(Cmd, '.');
- for i := 0 to 2 do
- Player := Player + '.' + Split(Cmd, '.');
- Cmd := Trim(Cmd + ' ' + Text);
- if length(Cmd) = 0 then exit(False);
- Server.CriticalSection.Enter;
- try
- for Session in Server.Sessions.Items do
- if Session.IPStr = Player then
- Session.DoCommand(Cmd, Self);
- finally
- Server.CriticalSection.Leave;
- end;{try...finally}
- Result := True;
- end{if Cmd[1] = '@'}
- else if pos('.', String(Cmd)) > 1 then
- begin
- Player := Split(Cmd, '.');
- Server.CriticalSection.Enter;
- try
- Session := Server.GetSessionByName(Player);
- if Session = nil then
- begin
- Session := TSession.CreateOffline(Player);
- if Session <> nil then
- try
- Result := Session.DoCommand(Trim(Cmd + ' ' + Text), Self);
- finally
- Session.Free;
- end{try...finally}
- else
- Result := False;
- end{if Session = nil}
- else
- Result := Session.DoCommand(Trim(Cmd + ' ' + Text), Self)
- finally
- Server.CriticalSection.Leave;
- end;{try...finally}
- end{else if pos('.', Cmd)}
- else
- Result := DoCommand(Trim(Cmd + ' ' + Text), Self);
- if not Server.Admin.EchoCommand then exit;
- end;{if Text[1]}
- if SendToSelf then Send(Packet);
- Server.Send(Packet, Self);
- end;{Server.TSession.Say}
- function Server.TSession.SayGlobal(Text: AnsiString; SendToSelf: Boolean = False): Boolean;
- var
- Packet: TPacket;
- begin
- if (not LoggedIn) or Offline then exit(False);
- Packet.SetID(PacketFamilyTalk, PacketActionMessage);
- Packet.AddBreakString(Name);
- Packet.AddBreakString(copy(Text, 1, Server.TextLength));
- if SendToSelf then Send(Packet);
- Server.Send(Packet, Self, False);
- Result := True;
- end;{Server.TSession.SayGlobal}
- function Server.TSession.SayGuild(Text: AnsiString; SendToSelf: Boolean = False): Boolean;
- var
- Packet: TPacket;
- Session: TSession;
- begin
- if (not LoggedIn) or Offline then exit(False);
- if length(Tag) = 0 then exit(False);
- Packet.SetID(PacketFamilyTalk, PacketActionRequest);
- Packet.AddBreakString(Name);
- Packet.AddBreakString(copy(Text, 1, Server.TextLength));
- Server.CriticalSection.Enter;
- try
- for Session in Server.Sessions.Items do
- if Session.LoggedIn and ((Session <> Self) or SendToSelf) and (Session.Tag = Tag) then
- Session.Send(Packet)
- finally
- Server.CriticalSection.Leave;
- end;{try...finally}
- Result := True;
- end;{Server.TSession.SayGuild}
- function Server.TSession.SayAdmin(Text: AnsiString; SendToSelf: Boolean = False): Boolean;
- var
- Packet: TPacket;
- Session: TSession;
- begin
- if (not LoggedIn) or Offline then exit(False);
- Packet.SetID(PacketFamilyTalk, PacketActionAdmin);
- Packet.AddBreakString(Name);
- Packet.AddBreakString(copy(Text, 1, Server.TextLength));
- Server.CriticalSection.Enter;
- try
- for Session in Server.Sessions.Items do
- if Session.LoggedIn and ((Session <> Self) or SendToSelf) and (Session.Admin > 0) then
- Session.Send(Packet)
- finally
- Server.CriticalSection.Leave;
- end;{try...finally}
- Result := True;
- end;{Server.TSession.SayAdmin}
- function Server.TSession.Announce(Text: AnsiString): Boolean;
- var
- Packet: TPacket;
- begin
- if (not LoggedIn) or Offline then exit(False);
- if length(Text) = 0 then exit(False);
- Log(['Announce "', Text, '"']);
- Packet.SetID(PacketFamilyTalk, PacketActionAnnounce);
- Packet.AddBreakString(Name);
- Packet.AddBreakString(copy(Text, 1, Server.TextLength));
- Server.Send(Packet);
- Result := True;
- end;{Server.TSession.Announce}
- function Server.TSession.Warp(WX, WY: Integer; Animation: Integer = WarpAnimationNone): Boolean;
- var
- Packet: TPacket;
- begin
- if not LoggedIn then exit(False);
- if (WX < 0) or (WX >= Server.MapData.Width) or (WY < 0) or (WY > Server.MapData.Height) then exit(False);
- if Offline then
- begin
- X := WX;
- Y := WY;
- exit(True);
- end;{if Offline}
- WarpInfo.Time := GetTickCount + 2000;
- WarpInfo.X := WX;
- WarpInfo.Y := WY;
- WarpInfo.Animation := Animation;
- Packet.SetID(PacketFamilyWarp, PacketActionRequest);
- Packet.AddInt1(1);
- Packet.AddInt2(1);
- Packet.AddInt1(WX);
- Packet.AddInt1(WY);
- Send(Packet);
- Result := True;
- end;{Server.TSession.Warp}
- function Server.TSession.Sit(Chair: Boolean = False): Boolean;
- var
- Packet: TPacket;
- begin
- if not LoggedIn then exit(False);
- if Sitting <> SittingStand then exit(False);
- if Chair then
- begin
- if not Offline then Packet.SetID(PacketFamilyChair, PacketActionPlayer);
- Sitting := SittingChair;
- end{if Chair}
- else
- begin
- if not Offline then Packet.SetID(PacketFamilySit, PacketActionPlayer);
- Sitting := SittingFloor;
- end;{else}
- if Offline then exit(True);
- Packet.AddInt2(ID);
- Packet.AddInt1(X);
- Packet.AddInt1(Y);
- Packet.AddInt1(D);
- Packet.AddInt1(0);
- Server.SendRanged(Packet, X, Y);
- Result := True;
- end;{Server.TSession.Sit}
- function Server.TSession.Stand: Boolean;
- var
- Packet: TPacket;
- begin
- if not LoggedIn then exit(False);
- if Sitting = SittingStand then exit(False);
- Sitting := SittingStand;
- if Offline then exit(True);
- Packet.SetID(PacketFamilySit, PacketActionRemove);
- Packet.AddInt2(ID);
- Packet.AddInt1(X);
- Packet.AddInt1(Y);
- Server.SendRanged(Packet, X, Y);
- Result := True;
- end;{Server.TSession.Stand}
- function Server.TSession.Emote(EmoteID: Integer; SendToSelf: Boolean = False): Boolean;
- var
- Packet: TPacket;
- begin
- if (not LoggedIn) or Offline then exit(False);
- Packet.SetID(PacketFamilyEmote, PacketActionPlayer);
- Packet.AddInt2(ID);
- Packet.AddInt1(EmoteID);
- if SendToSelf then Send(Packet);
- Server.Send(Packet, Self);
- Result := True;
- end;{Server.TSession.Emote}
- function Server.TSession.Status(Msg: AnsiString): Boolean;
- var
- Packet: TPacket;
- begin
- if (not LoggedIn) or Offline then exit(False);
- Packet.SetID(PacketFamilyMessage, PacketActionOpen);
- Packet.AddString(Msg);
- Send(Packet);
- Result := True;
- end;{Server.TSession.Status}
- function Server.TSession.Mute(From: AnsiString = 'Server'): Boolean;
- var
- Packet: TPacket;
- begin
- if (not LoggedIn) or Offline then exit(False);
- Packet.SetID(PacketFamilyTalk, PacketActionSpecial);
- Packet.AddString(From);
- Send(Packet);
- Result := True;
- end;{Server.TSession.Mute}
- function Server.TSession.Freeze: Boolean;
- var
- Packet: TPacket;
- begin
- if (not LoggedIn) or Offline then exit(False);
- Packet.SetID(PacketFamilyWalk, PacketActionClose);
- Send(Packet);
- Result := True;
- end;{Server.TSession.Freeze}
- function Server.TSession.Unfreeze: Boolean;
- var
- Packet: TPacket;
- begin
- if (not LoggedIn) or Offline then exit(False);
- Packet.SetID(PacketFamilyWalk, PacketActionOpen);
- Send(Packet);
- Result := True;
- end;{Server.TSession.Unfreeze}
- function Server.TSession.Effect(EffectID: Integer; SendToSelf: Boolean = False): Boolean;
- var
- Packet: TPacket;
- begin
- if (not LoggedIn) or Offline then exit(False);
- Packet.SetID(PacketFamilyEffect, PacketActionPlayer);
- Packet.AddInt2(ID);
- Packet.AddInt2(EffectID);
- Packet.AddInt1(0);
- if SendToSelf then Send(Packet);
- Server.Send(Packet, Self);
- Result := True;
- end;{Server.TSession.Effect}
- function Server.TSession.Drunk(Scale: Integer): Boolean;
- var
- Packet: TPacket;
- begin
- if (not LoggedIn) or Offline then exit(False);
- Packet.SetID(PacketFamilyItem, PacketActionReply);
- Packet.AddInt1(Server.TItemData.ItemTypeSoda);
- Packet.AddInt2(0);
- Packet.AddInt4(0);
- Packet.AddInt1(0);
- Packet.AddInt1(50);
- Send(Packet);
- Result := True;
- end;{Server.TSession.Drunk}
- function Server.TSession.Quake(Scale: Integer): Boolean;
- var
- Packet: TPacket;
- begin
- if (not LoggedIn) or Offline then exit(False);
- Packet.SetID(PacketFamilyEffect, PacketActionUse);
- Packet.AddInt1(1);
- Packet.AddInt1(Scale);
- Send(Packet);
- Result := True;
- end;{Server.TSession.Quake}
- function Server.TSession.HelloHax0r: Boolean;
- var
- Packet: TPacket;
- begin
- if (not LoggedIn) or Offline then exit(False);
- Packet.SetID(PacketFamilyUpdate, PacketActionList);
- Packet.AddInt2(0);
- Packet.AddInt2($FFFF);
- Packet.AddInt2($FFFF);
- Packet.AddInt2($FFFF);
- Packet.AddInt2($FFFF);
- Packet.AddInt2($FFFF);
- Packet.AddInt2($FFFF);
- Packet.AddInt2($FFFF);
- Packet.AddInt2($FFFF);
- Packet.AddInt2($FFFF);
- Packet.AddInt2($FFFF);
- Packet.AddInt2($FFFF);
- Packet.AddInt2($FFFF);
- Packet.AddInt2($FFFF);
- Packet.AddInt2($FFFF);
- Packet.AddInt2($FFFF);
- Send(Packet);
- Disconnect;
- Result := True;
- end;{Server.TSession.Drunk}
- function Server.TSession.Show: Boolean;
- var
- Packet: TPacket;
- begin
- if not LoggedIn then exit(False);
- Result := True;
- if Hidden = 0 then exit;
- Hidden := 0;
- if Offline then exit;
- Packet.SetID(PacketFamilyAdmin, PacketActionAgree);
- Packet.AddInt2(ID);
- Server.SendRanged(Packet, X, Y);
- end;{Server.TSession.Show}
- function Server.TSession.Hide: Boolean;
- var
- Packet: TPacket;
- begin
- if not LoggedIn then exit(False);
- Result := True;
- if Hidden = 1 then exit;
- Hidden := 1;
- if Offline then exit;
- Packet.SetID(PacketFamilyAdmin, PacketActionRemove);
- Packet.AddInt2(ID);
- Server.SendRanged(Packet, X, Y);
- end;{Server.TSession.Hide}
- function Server.TSession.Sound(SoundID: Integer): Boolean;
- var
- Packet: TPacket;
- begin
- if (not LoggedIn) or Offline then exit(False);
- Packet.SetID(PacketFamilySound, PacketActionPlayer);
- Packet.AddInt2(SoundID);
- Send(Packet);
- Result := True;
- end;{Server.TSession.Sound}
- function Server.TSession.Ban: Boolean;
- begin
- if not LoggedIn then exit(False);
- Banned := 1;
- if not Offline then Disconnect;
- Result := True;
- end;{Server.TSession.Ban}
- function Server.TSession.UnBan: Boolean;
- begin
- if not LoggedIn then exit(False);
- Banned := 0;
- Result := True;
- end;{Server.TSession.UnBan}
- function Server.TSession.Sleep: Boolean;
- var
- Packet: TPacket;
- begin
- if (not LoggedIn) or Offline then exit(False);
- Packet.SetID(PacketFamilyInnKeeper, PacketActionAccept);
- Packet.AddInt4(0);
- Send(Packet);
- Result := True;
- end;{Server.TSession.Sleep}
- function Server.TSession.Barber: Boolean;
- var
- Packet: TPacket;
- begin
- if (not LoggedIn) or Offline then exit(False);
- Packet.SetID(PacketFamilyBarber, PacketActionOpen);
- Packet.AddInt4(0);
- Send(Packet);
- Result := True;
- end;{Server.TSession.Barber}
- function Server.TSession.SetGold(Value: Integer): Boolean;
- var
- OldGold: Integer;
- Packet: TPacket;
- begin
- if not LoggedIn then exit(False);
- OldGold := Gold;
- Gold := Value;
- if Gold < 0 then
- Gold := 0
- else if Gold > MaxGold then
- Gold := MaxGold;
- Result := True;
- if Offline then exit;
- OldGold := Gold - OldGold;
- if OldGold = 0 then exit;
- if OldGold > 0 then
- begin
- Packet.SetID(PacketFamilyItem, PacketActionGet);
- Packet.AddInt2(0);
- Packet.AddInt2(GoldID);
- Packet.AddInt3(OldGold);
- Packet.AddInt1(0);//Weight
- Packet.AddInt1(50);//MaxWeight
- end{if OldGold}
- else
- begin
- Packet.SetID(PacketFamilyItem, PacketActionJunk);
- Packet.AddInt2(GoldID);
- Packet.AddInt3(OldGold);
- Packet.AddInt4(Gold);
- Packet.AddInt1(0);//Weight
- Packet.AddInt1(50);//MaxWeight
- end;{else}
- Send(Packet);
- end;{Server.TSession.SetGold}
- function Server.TSession.Damage(Amount: Integer; By: TSession): Boolean;
- var
- Packet: TPacket;
- begin
- if not LoggedIn then exit(False);
- HP := HP - abs(Amount);
- if HP < 0 then HP := 0;
- Result := True;
- if not Offline then
- begin
- Packet.SetID(PacketFamilyAppearance, PacketActionReply);
- Packet.AddInt2(0);
- Packet.AddInt2(ID);
- Packet.AddInt3(abs(Amount));
- Packet.AddInt1(0);//Level
- Packet.AddInt1(round((HP / MaxHP) * 100));
- if HP = 0 then Packet.AddInt1(1) else Packet.AddInt1(0);
- Send(Packet);
- Server.Send(Packet, Self);
- UpdateHPTP;
- end;{if not Offline}
- if HP = 0 then Die(By);
- end;{Server.TSession.Damage}
- function Server.TSession.SetHP(Value: Integer): Boolean;
- begin
- if not LoggedIn then exit(False);
- HP := Value;
- if HP < 0 then HP := 0 else if HP > MaxHP then HP := MaxHP;
- UpdateHPTP;
- Result := True;
- end;{Server.TSession.SetHP}
- function Server.TSession.SetTP(Value: Integer): Boolean;
- begin
- if not LoggedIn then exit(False);
- TP := Value;
- if TP < 0 then TP := 0 else if TP > MaxTP then TP := MaxTP;
- UpdateHPTP;
- Result := True;
- end;{Server.TSession.SetTP}
- function Server.TSession.SetMaxHP(Value: Integer): Boolean;
- begin
- if not LoggedIn then exit(False);
- MaxHP := Value;
- if MaxHP < 1 then MaxHP := 1;
- if HP > MaxHP then HP := MaxHP;
- UpdateStats;
- Result := True;
- end;{Server.TSession.SetTP}
- function Server.TSession.SetMaxTP(Value: Integer): Boolean;
- begin
- if not LoggedIn then exit(False);
- MaxTP := Value;
- if MaxTP < 0 then MaxTP := 0;
- if TP > MaxTP then TP := MaxTP;
- UpdateStats;
- Result := True;
- end;{Server.TSession.SetTP}
- function Server.TSession.UpdateHPTP: Boolean;
- var
- Packet: TPacket;
- begin
- if (not LoggedIn) or Offline then exit(False);
- Packet.SetID(PacketFamilyUpdate, PacketActionPlayer);
- Packet.AddInt2(HP);
- Packet.AddInt2(TP);
- Send(Packet);
- if Party <> nil then
- Party.Update(Self);
- Result := True;
- end;{Server.TSession.UpdateHPTP}
- function Server.TSession.UpdateStats: Boolean;
- var
- Packet: TPacket;
- begin
- if (not LoggedIn) or Offline then exit(False);
- Packet.SetID(PacketFamilySkill, PacketActionPlayer);
- Packet.AddInt2(0); //statpoints
- Packet.AddInt2(0); //str
- Packet.AddInt2(0); //int
- Packet.AddInt2(0); //wis
- Packet.AddInt2(0); //agi
- Packet.AddInt2(0); //con
- Packet.AddInt2(0); //cha
- Packet.AddInt2(MaxHP);
- Packet.AddInt2(MaxTP);
- Packet.AddInt2(0); //max sp
- Packet.AddInt2(50);//max weight
- Packet.AddInt2(0); //min damage
- Packet.AddInt2(0); //max damage
- Packet.AddInt2(0); //accuracy
- Packet.AddInt2(0); //evade
- Packet.AddInt2(0); //armour
- Send(Packet);
- if Party <> nil then
- Party.Update(Self);
- Result := True;
- end;{Server.TSession.UpdateStats}
- function Server.TSession.Die(By: TSession): Boolean;
- var
- Packet: TPacket;
- begin
- if not LoggedIn then exit(False);
- if By <> nil then
- begin
- Server.CriticalSection.Section(procedure
- begin
- By.Kills := By.Kills + 1;
- end);{CriticalSection}
- Packet.SetID(PacketFamilyArena, PacketActionSpecial);
- Packet.AddInt2(0);
- Packet.AddByte(255);
- Packet.AddInt1(0);
- Packet.AddByte(255);
- Packet.AddInt2(By.Kills);
- Packet.AddInt1(0);
- Packet.AddByte(255);
- Packet.AddBreakString(Capitalize(By.Name));
- Packet.AddBreakString(Capitalize(Name));
- Server.Send(Packet);
- end;{if By <> nil}
- Resurrect;
- Result := True;
- end;{Server.TSession.Die}
- function Server.TSession.Resurrect: Boolean;
- begin
- if not LoggedIn then exit(False);
- HP := MaxHP;
- Warp(Server.Defaults.X, Server.Defaults.Y, 0);
- UpdateHPTP;
- Result := True;
- end;{Server.TSession.Resurrect}
- function Server.TSession.RaceDialog: Boolean;
- const
- RaceNames: array[0..5] of AnsiString = ('Fair', 'Dark', 'Light', 'Orc', 'Skeleton', 'Panda');
- var
- i: Integer;
- Packet: TPacket;
- begin
- if (not LoggedIn) or Offline then exit(False);
- Packet.SetID(PacketFamilyQuest, PacketActionDialog);
- Packet.AddInt1(1);
- Packet.AddInt2(0);
- Packet.AddInt2(0);
- Packet.AddInt4(CustomRaceID);
- Packet.AddByte(255);
- Packet.AddInt2(0);
- Packet.AddString(CustomTitle);
- Packet.AddByte(255);
- Packet.AddInt2(1);
- Packet.AddString('Select a race:');
- Packet.AddByte(255);
- for i := 0 to high(RaceNames) do
- begin
- Packet.AddInt2(2);
- Packet.AddInt2(i + 1);
- Packet.AddString(RaceNames[i]);
- Packet.AddByte(255);
- end;{for i}
- Send(Packet);
- Result := True;
- end;{of Server.TSession.RaceDialog}
- function Server.TSession.SexDialog: Boolean;
- const
- GenderNames: array[0..1] of AnsiString = ('Female', 'Male');
- var
- i: Integer;
- Packet: TPacket;
- begin
- if (not LoggedIn) or Offline then exit(False);
- Packet.SetID(PacketFamilyQuest, PacketActionDialog);
- Packet.AddInt1(1);
- Packet.AddInt2(0);
- Packet.AddInt2(0);
- Packet.AddInt4(CustomSexID);
- Packet.AddByte(255);
- Packet.AddInt2(0);
- Packet.AddString(CustomTitle);
- Packet.AddByte(255);
- Packet.AddInt2(1);
- Packet.AddString('Select a gender:');
- Packet.AddByte(255);
- for i := 0 to high(GenderNames) do
- begin
- Packet.AddInt2(2);
- Packet.AddInt2(i + 1);
- Packet.AddString(GenderNames[i]);
- Packet.AddByte(255);
- end;{for i}
- Send(Packet);
- Result := True;
- end;{of Server.TSession.SexDialog}
- function Server.TSession.ReceivePM(From, Text: AnsiString): Boolean;
- var
- Packet: TPacket;
- begin
- if (not LoggedIn) or Offline then exit(False);
- Packet.SetID(PacketFamilyTalk, PacketActionTell);
- Packet.AddBreakString(From);
- Packet.AddBreakString(copy(Text, 1, Server.TextLength));
- Send(Packet);
- Result := True;
- end;{Server.TSession.ReceivePM}
- function Server.TSession.SendPM(SendTo, Text: AnsiString): Boolean;
- var
- Session: TSession;
- Packet: TPacket;
- begin
- if not LoggedIn then exit(False);
- Server.CriticalSection.Enter;
- try
- Session := Server.GetSessionByName(SendTo);
- if (Session = nil) or not Session.LoggedIn then
- begin
- if Offline then exit(False);
- Packet.SetID(PacketFamilyTalk, PacketActionReply);
- Packet.AddInt2(1);
- Packet.AddString(SendTo);
- Send(Packet);
- Result := False;
- end{if Session = nil}
- else
- begin
- Session.ReceivePM(Name, Text);
- Result := True;
- end;{else}
- finally
- Server.CriticalSection.Leave;
- end;{try...finally}
- end;{Server.TSession.SendPM}
- function Server.TSession.Attack(Direction: Integer; SendToSelf: Boolean = False): Boolean;
- var
- i: Integer;
- ax, ay: Integer;
- Packet: TPacket;
- Range: Integer;
- Victim: TSession;
- Session: TSession;
- begin
- if (not LoggedIn) or Offline then exit(False);
- if (Direction < 0) or (Direction > 3) or (Sitting <> SittingStand) then exit(False);
- Packet.SetID(PacketFamilyAttack, PacketActionPlayer);
- Packet.AddInt2(ID);
- Packet.AddInt1(Direction);
- if SendToSelf then Send(Packet);
- Server.Send(Packet, Self);
- ax := X;
- ay := Y;
- D := Direction;
- Range := 1;//Server.ViewRange;
- Victim := nil;
- Server.CriticalSection.Enter;
- try
- for i := 0 to Range - 1 do
- begin
- case Direction of
- DirectionDown: inc(ay);
- DirectionLeft: dec(ax);
- DirectionUp: dec(ay);
- DirectionRight: inc(ax);
- end;{case Direction}
- for Session in Server.Sessions.Items do
- if (Session <> Self) and Session.LoggedIn and
- (Session.X = ax) and (Session.Y = ay) and
- (Server.MapData.Tiles[ay, ax].Kind = TMapData.MapTileArena) and
- (Server.MapData.Tiles[Y, X]. Kind = TMapData.MapTileArena) and
- (Session.HP > 0) then
- begin
- Victim := Session;
- break;
- end;{if (Session <> Self...}
- if (Victim <> nil) or (not Server.MapData.IsWalkable(ax, ay, True)) then
- begin
- //Server.Effect(31, ax, ay);
- break;
- end{if (Victim <> nil...}
- //else
- // Server.Effect(29, ax, ay);
- end;{for i}
- if Victim <> nil then Victim.Attacked(Self);
- finally
- Server.CriticalSection.Leave;
- end;{try...finally}
- Result := True;
- end;{Server.TSession.Attack}
- procedure Server.TSession.Attacked(By: TSession);
- begin
- if not LoggedIn then exit;
- Damage(1, By);
- end;{Server.TSession.Attacked}
- function Server.TSession.DoCommand(Cmd: AnsiString; Sender: TSession = nil): Boolean;
- var
- Param: AnsiString;
- S: AnsiString;
- A, B: Integer;
- SysCmd: Boolean;
- function CheckPermission(Level: Integer): Boolean;
- begin
- if SysCmd then exit(True);
- if Sender.IPInt = localhost then exit(True);
- Result := Sender.Admin >= Level;
- if Sender <> Self then Result := Result and (Sender.Admin > Self.Admin);
- if not Result then
- Sender.Status('You do not have permission to perform this command');
- end;{CheckPermission}
- function Alter(Param: AnsiString; Value: Integer): Integer;
- begin
- if length(Param) = 0 then exit(Value);
- if Param[1] = '+' then
- Result := Value + abs(Int(copy(Param, 2, length(Param))))
- else if Param[1] = '-' then
- Result := Value - abs(Int(copy(Param, 2, length(Param))))
- else
- Result := Int(Param, Value);
- end;{Alter}
- begin
- SysCmd := Sender = nil;
- if SysCmd then Sender := Self;
- {$IFDEF LOG_COMMANDS}
- Log(['Command "', Cmd, '" from ', Sender.Name]);
- {$ENDIF LOG_COMMANDS}
- Param := Cmd;
- Cmd := Split(Param, ' ');
- Result := True;
- if length(Cmd) = 0 then
- else if (Cmd = 'tag') and CheckPermission(Server.Admin.Level.Appearance) then begin Tag := copy(Param, 1, 3); Refresh; end
- 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
- 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
- else if (Cmd = 'haircolour') and CheckPermission(Server.Admin.Level.Appearance) then begin HairColour := Int(Param, HairColour); Refresh; end
- else if (Cmd = 'hairstyle') and CheckPermission(Server.Admin.Level.Appearance) then begin HairStyle := Int(Param, HairStyle); Refresh; end
- else if (Cmd = 'barber') and CheckPermission(Server.Admin.Level.Appearance) then Barber
- else if (Cmd = 'armour') and CheckPermission(Server.Admin.Level.Item) then begin Armour := Int(Param, Armour); Refresh; end
- else if (Cmd = 'hat') and CheckPermission(Server.Admin.Level.Item) then begin Hat := Int(Param, Hat); Refresh; end
- else if (Cmd = 'boots') and CheckPermission(Server.Admin.Level.Item) then begin Boots := Int(Param, Boots); Refresh; end
- else if (Cmd = 'weapon') and CheckPermission(Server.Admin.Level.Item) then begin Weapon := Int(Param, Weapon); Refresh; end
- else if (Cmd = 'shield') and CheckPermission(Server.Admin.Level.Item) then begin Shield := Int(Param, Shield); Refresh; end
- else if (Cmd = 'gold') and CheckPermission(Server.Admin.Level.Item) then SetGold(Alter(Param, Gold))
- else if (Cmd = 'kills') and CheckPermission(Server.Admin.Level.Item) then Kills := Alter(Param, Kills)
- else if (Cmd = 'save') and CheckPermission(0) then Sync
- else if (Cmd = 'disconnect') and CheckPermission(0) then Disconnect
- else if (Cmd = 'refresh') and CheckPermission(0) then Refresh
- else if (Cmd = 'warp')and CheckPermission(Server.Admin.Level.Action) then
- begin
- if length(Param) = 0 then
- Warp(Sender.X, Sender.Y, WarpAnimationBubbles)
- else if pos(String(Param[1]), '0123456789') > 0 then
- begin
- A := Alter(Split(Param), X);
- B := Alter(Split(Param), Y);
- Warp(A, B, Int(Param, WarpAnimationBubbles))
- end{else if pos...}
- else
- begin
- S := lower(Split(Param));
- Server.CriticalSection.Enter;
- try
- Sender := Server.GetSessionByName(S);
- if (Sender = nil) or (not Sender.LoggedIn) then exit;
- Warp(Sender.X, Sender.Y, Int(Param, WarpAnimationBubbles));
- finally
- Server.CriticalSection.Leave;
- end;{try...finally}
- end;{else}
- end{Warp}
- else if (Cmd = 'damage') and CheckPermission(Server.Admin.Level.Action) then Damage(Int(Param, 1), Sender)
- else if (Cmd = 'die') and CheckPermission(Server.Admin.Level.Action) then Die(Sender)
- else if (Cmd = 'hp') and CheckPermission(Server.Admin.Level.Action) then SetHP(Alter(Param, HP))
- else if (Cmd = 'tp') and CheckPermission(Server.Admin.Level.Action) then SetTP(Alter(Param, TP))
- else if (Cmd = 'maxhp') and CheckPermission(Server.Admin.Level.Action) then SetMaxHP(Alter(Param, MaxHP))
- else if (Cmd = 'maxtp') and CheckPermission(Server.Admin.Level.Action) then SetMaxTP(Alter(Param, MaxTP))
- else if (Cmd = 'attacked') and CheckPermission(Server.Admin.Level.Action) then Attacked(Sender)
- else if (Cmd = 'say') and CheckPermission(Server.Admin.Level.Action) then Say(Param, True)
- else if (Cmd = 'sit') and CheckPermission(Server.Admin.Level.Action) then Sit(Bool(Param))
- else if (Cmd = 'stand') and CheckPermission(Server.Admin.Level.Action) then Stand
- else if (Cmd = 'walk') and CheckPermission(Server.Admin.Level.Action) then Walk(Int(Param, D), False, False, True)
- else if (Cmd = 'face') and CheckPermission(Server.Admin.Level.Action) then Face(Int(Param, D), True)
- else if (Cmd = 'attack') and CheckPermission(Server.Admin.Level.Action) then Attack(Int(Param, D), True)
- else if (Cmd = 'emote') and CheckPermission(Server.Admin.Level.Action) then Emote(Int(Param), True)
- else if (Cmd = 'status') and CheckPermission(Server.Admin.Level.Action) then Status(Param)
- else if (Cmd = 'drunk') and CheckPermission(Server.Admin.Level.Action) then Drunk(Int(Param))
- else if (Cmd = 'effect') and CheckPermission(Server.Admin.Level.Action) then Effect(Int(Param), True)
- else if (Cmd = 'quake') and CheckPermission(Server.Admin.Level.Action) then Quake(Int(Param))
- else if (Cmd = 'hide') and CheckPermission(Server.Admin.Level.Action) then Hide
- else if (Cmd = 'show') and CheckPermission(Server.Admin.Level.Action) then Show
- else if (Cmd = 'sound') and CheckPermission(Server.Admin.Level.Action) then Sound(Int(Param, 1))
- else if (Cmd = 'sleep') and CheckPermission(Server.Admin.Level.Action) then Sleep
- else if (Cmd = 'unfreeze') and CheckPermission(Server.Admin.Level.Action) then Unfreeze
- else if (Cmd = 'freeze') and CheckPermission(Server.Admin.Level.Action) then
- begin
- S := Capitalize(Name) + ' was frozen by ' + Capitalize(Sender.Name);
- if length(Param) > 0 then S := S + ' [' + Param + '] ';
- Server.Msg(S);
- Freeze;
- end{'freeze'}
- else if (Cmd = 'mute') and CheckPermission(Server.Admin.Level.Action) then
- begin
- S := Capitalize(Name) + ' was muted by ' + Capitalize(Sender.Name);
- if length(Param) > 0 then S := S + ' [' + Param + '] ';
- Server.Msg(S);
- Mute(Sender.Name);
- end{'mute'}
- else if (Cmd = 'kick') and CheckPermission(Server.Admin.Level.Action) then
- begin
- S := Capitalize(Name) + ' was kicked by ' + Capitalize(Sender.Name);
- if length(Param) > 0 then S := S + ' [' + Param + '] ';
- Server.Msg(S);
- Disconnect;
- end{'kick'}
- else if (Cmd = 'ban') and CheckPermission(Server.Admin.Level.Action) then
- begin
- S := Capitalize(Name) + ' was banned by ' + Capitalize(Sender.Name);
- if length(Param) > 0 then S := S + ' [' + Param + '] ';
- Server.Msg(S);
- Ban;
- end{'ban'}
- else if (Cmd = 'unban') and CheckPermission(Server.Admin.Level.Action) then
- begin
- //S := Capitalize(Name) + ' was unbanned by ' + Capitalize(Sender.Name);
- //if length(Param) > 0 then S := S + ' [' + Param + '] ';
- //Server.Msg(S);
- UnBan;
- end{'unban'}
- else if (Cmd = 'ip') and CheckPermission(Server.Admin.Level.Action) then Sender.Status('IP Address of ' + Name + ':' + IPStr)
- else if (Cmd = 'log') and CheckPermission(1) then Log(['<', Sender.Name, '> "', Param, '"'])
- else if (Cmd = 'ipban') and CheckPermission(Server.Admin.Level.Maintenance) then
- begin
- if length(Param) > 0 then
- Server.BanIP(Param)
- else if Sender <> Self then
- begin
- Server.BanIP(IPStr);
- Disconnect;
- end
- else
- Status('Unable to ban own ip');
- end{'ipban'}
- else if (Cmd = 'ipunban') and CheckPermission(Server.Admin.Level.Maintenance) then Server.UnbanIP(Param)
- else if (Cmd = 'hellohax0r') and CheckPermission(Server.Admin.Level.Maintenance) then HelloHax0r
- else if (Cmd = 'admin') and CheckPermission(Server.Admin.Level.Maintenance) then Admin := Int(Param)
- else if (Cmd = 'halt') and CheckPermission(Server.Admin.Level.Maintenance) then Error(['Halted by ', Sender.Name])
- else if (Cmd = 'sql') and CheckPermission(Server.Admin.Level.Maintenance) then Server.Database.Query(Param)
- else if (Cmd = 'sync') and CheckPermission(Server.Admin.Level.Maintenance) then begin Sync(Bool(Param, True)); Warp(X, Y); end
- else if (Cmd = 'servermsg') and CheckPermission(Server.Admin.Level.Maintenance) then Server.Msg(Param + ' --' + Capitalize(Sender.Name))
- else if (Cmd = 'gfreeze') and CheckPermission(Server.Admin.Level.Maintenance) then Server.Freeze(Self)
- else if (Cmd = 'gunfreeze') and CheckPermission(Server.Admin.Level.Maintenance) then Server.Unfreeze
- else if (Cmd = 'gmute') and CheckPermission(Server.Admin.Level.Maintenance) then Server.Mute(Self)
- else if (Cmd = 'gquake') and CheckPermission(Server.Admin.Level.Maintenance) then Server.Quake(Int(Param))
- else if (Cmd = 'map') and CheckPermission(Server.Admin.Level.Maintenance) then Server.SetMap(Param)
- else if (Cmd = 'mutate') and CheckPermission(Server.Admin.Level.Maintenance) then Server.Mutate
- 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
- else if (Cmd = 'gsound') and CheckPermission(Server.Admin.Level.Maintenance) then Server.Sound(Int(Param, 1))
- else if (Cmd = 'shutdown') and CheckPermission(Server.Admin.Level.Maintenance) then Server.Shutdown
- else if (Cmd = '_test') and CheckPermission(Server.Admin.Level.Maintenance) then _test(Param)
- else
- begin
- Sender.Status('Unknown command "' + cmd + '"');
- Result := False;
- end;{else}
- end;{Server.TSession.DoCommand}
- function Server.TSession.Execute: Boolean;
- procedure QueuePacket(Time: Cardinal);
- begin
- if length(Packet.Queue.Items) = PacketQueue.Size then
- begin
- Log(['Packet queue full']);
- Initialized := False;
- exit;
- end;{if length(Packet.Queue.Items}
- SetLength(Packet.Queue.Items, length(Packet.Queue.Items) + 1);
- Packet.Queue.Items[high(Packet.Queue.Items)] := Packet.Receive;
- Packet.Queue.Items[high(Packet.Queue.Items)].Time := Time;
- end;{QueuePacket}
- function UnqueuePacket: Boolean;
- begin
- if (length(Packet.Queue.Items) = 0) or (GetTickCount < Packet.Queue.Time) then exit(False);
- Result := True;
- Packet.Receive := Packet.Queue.Items[high(Packet.Queue.Items)];
- SetLength(Packet.Queue.Items, length(Packet.Queue.Items) - 1);
- Packet.Queue.Time := GetTickCount + Packet.Receive.Time;
- Packet.Receive.Time := GetTickCount;
- end;{UnqueuePacket}
- const
- BufSize = 1024;
- var
- i: Integer;
- Size: Integer;
- ReadLen: Integer;
- ReadBuf: AnsiString;
- Time: Cardinal;
- begin
- //if Offline then exit(False);
- if (Socket = 0) or (recv(Socket, nil^, 0, MSG_OOB) = 0) then
- begin
- Log(['Connection dropped']);
- exit(False);
- end;{if (Socket = 0)..}
- Time := GetTickCount;
- if Time > Packet.Time then
- begin
- Log(['Connection timeout']);
- exit(False);
- end;{if Time > Packet.Time}
- if (WarpInfo.Time > 0) and (Time > WarpInfo.Time) then
- begin
- Log(['Ignored warp request']);
- exit(False);
- end;{if (WarpInfo.Time...}
- Packet.Queue.Active := UnqueuePacket;
- if not Packet.Queue.Active then
- begin
- if ioctlsocket(Socket, FIONREAD, i) = 0 then
- begin
- SetLength(ReadBuf, BufSize);
- repeat
- ReadLen := recv(Socket, ReadBuf[1], BufSize, 0);
- if ReadLen < 1 then break;
- InterlockedExchangeAdd64(Server.Connection.BytesIn, ReadLen);
- Packet.Buffer := Packet.Buffer + copy(ReadBuf, 1, ReadLen);
- until False;
- Server.UpdateCaption;
- Packet.Time := GetTickCount + Server.Connection.Timeout;
- end;{if ioctlsocket}
- if length(Packet.Buffer) < 2 then exit(True);
- Size := PackEOInt(ord(Packet.Buffer[1]), ord(Packet.Buffer[2]));
- if length(Packet.Buffer) < (Size + 2) then exit(True);
- Packet.Receive.Data := copy(Packet.Buffer, 3, Size);
- Packet.Buffer := copy(Packet.Buffer, Size + 3, length(Packet.Buffer));
- if Size < 3 then exit(true);
- if Initialized then
- begin
- ReadBuf := '';
- i := 1;
- while i <= length(Packet.Receive.Data) do
- begin
- ReadBuf := ReadBuf + AnsiChar(ord(Packet.Receive.Data[i]) xor $80);
- inc(i, 2);
- end;{while i <= length(Packet.Receive.Data)}
- dec(i);
- if Boolean(length(Packet.Receive.Data) mod 2) then dec(i, 2);
- repeat
- ReadBuf := ReadBuf + AnsiChar(ord(Packet.Receive.Data[i]) xor $80);
- dec(i, 2);
- until i <= 0;
- for i := 3 to length(Packet.Receive.Data) do
- if ReadBuf[i] = #128 then ReadBuf[i] := #0
- else if ReadBuf[i] = #0 then ReadBuf[i] := #128;
- Packet.Receive.Data := FoldData(ReadBuf, ReceiveKey);
- end;{if Initialized}
- Packet.Receive.Family := ord(Packet.Receive.Data[2]);
- Packet.Receive.Action := ord(Packet.Receive.Data[1]);
- Packet.Receive.Data := copy(Packet.Receive.Data, 3, length(Packet.Receive.Data));
- Packet.Receive.Time := GetTickCount;
- if Packet.Receive.Family <> PacketFamilyRaw then
- begin
- // Sequence
- Packet.Receive.GetByte;
- end;{if Packet.Receive.Family}
- end;{if not Packet.Queue.Active}
- Packet.Send.Reset;
- Packet.Send.SetID(Packet.Receive.Family, PacketActionReply);
- i := Packet.Receive.Family;
- if not Initialized then
- begin
- if Packet.Receive.Family = PacketFamilyPlayers then
- begin
- Log(['Remote player list request']);
- HandlePlayers(i);
- exit(False);
- end{if Packet.Receive.Action}
- else if Packet.Receive.Family <> PacketFamilyRaw then
- begin
- Log(['Packet before initialize']);
- exit(False);
- end;{else if Packet.Receive.Action}
- end;{if not Initialized}
- if (not PacketQueue.Enabled) or Packet.Queue.Active then
- Dispatch(i)
- else
- case Packet.Receive.Family of
- PacketFamilyWalk: QueuePacket(PacketQueue.Walk);
- PacketFamilyAttack: QueuePacket(PacketQueue.Attack);
- PacketFamilyFace: QueuePacket(0);
- PacketFamilyPlayers: QueuePacket(100);
- else
- Dispatch(i)
- end;{case Packet.Receive.Family}
- Result := Initialized;
- end;{Server.TSession.Execute}
- procedure Server.TSession.DefaultHandler;
- begin
- {$IFDEF LOG_UNHANDLED_PACKET_FAMILY}
- Log(['Unhandled packet family ', Packet.Receive.Family]);
- {$ENDIF LOG_UNHANDLED_PACKET_FAMILY}
- end;{Server.TSession.DefaultHandler}
- procedure Server.TSession.UnhandledAction(Name: AnsiString = '');
- begin
- {$IFDEF LOG_UNHANDLED_PACKET_ACTION}
- if length(Name) = 0 then Name := 'family (' + Str(Packet.Receive.Family) + ')';
- Log(['Unhandled ' + Name + ' action ', Packet.Receive.Action]);
- {$ENDIF LOG_UNHANDLED_PACKET_ACTION}
- end;{Server.TSession.UnhandledAction}
- procedure Server.TSession.HandleRaw;
- function AuthClient(Auth: Integer): Integer;
- begin
- inc(Auth);
- Result := (Auth mod 11 + 1) * 119;
- if Result = 0 then exit;
- Result := 110905 + (Auth mod 9 + 1) * ((11092004 - Auth) mod Result) * 119 + Auth mod 2004;
- end;{AuthClient}
- var
- Auth: Integer;
- s1, s2: Byte;
- Ver: array[0..2] of Byte;
- Seq: Byte;
- begin
- Packet.Send.SetID(PacketFamilyRaw, PacketActionRaw);
- Auth := Packet.Receive.GetInt3;
- Ver[0] := Packet.Receive.GetInt1;
- Ver[1] := Packet.Receive.GetInt1;
- Ver[2] := Packet.Receive.GetInt1;
- if (Ver[0] <> Server.RequiredVersion[0])
- or (Ver[1] <> Server.RequiredVersion[1])
- or (Ver[2] <> Server.RequiredVersion[2]) then
- begin
- Packet.Send.AddByte(1);
- Packet.Send.AddByte(Server.RequiredVersion[0] + 1);
- Packet.Send.AddByte(Server.RequiredVersion[1] + 1);
- Packet.Send.AddByte(Server.RequiredVersion[2] + 1);
- Log(['Invalid client version ', Ver[0], '.', Ver[1], '.', Ver[2]]);
- Send(True);
- exit;
- end;{if (Ver...}
- Packet.Receive.Discard(2);
- HDDSerial := Packet.Receive.GetString;
- //2 = ok
- //3 = ip permabanned
- //10 = some weird sound?
- Packet.Send.AddByte(2);
- Seq := 1 + Random(220);
- s1 := (Seq + 12) div 7;
- s2 := (Seq + 5) mod 7;
- Packet.Send.AddByte(s1);
- Packet.Send.AddByte(s2);
- Log(['Initialized']);// s1:' + Str(s1) + ' s2:' + Str(s2)]);
- Packet.Send.AddByte(Server.SendKey);
- Packet.Send.AddByte(Server.ReceiveKey);
- Packet.Send.AddInt2(ID);
- Packet.Send.AddInt3(AuthClient(Auth));
- Send(True);
- Initialized := True;
- end;{Server.TSession.HandleRaw}
- procedure Server.TSession.HandleConnection;
- procedure HandleConnectionAccept;
- begin
- SendData(Server.ItemData);
- SendData(Server.NPCData);
- SendData(Server.SpellData);
- SendData(Server.ClassData);
- end;{HandleConnectionAccept}
- begin
- case Packet.Receive.Action of
- PacketActionAccept: HandleConnectionAccept;
- else
- UnhandledAction('connection');
- end;{case Packet.Receive.Action}
- end;{Server.TSession.HandleConnection}
- procedure Server.TSession.HandleAccount;
- const
- AccountReplyAlreadyExists = 1;
- AccountReplyNotApproved = 2;
- AccountReplyCreated = 3;
- AccountReplyChangeFailed = 5;
- AccountReplyChanged = 6;
- AccountReplyContinue = 1000;
- function CheckAccount(AccountName: AnsiString): Boolean;
- begin
- Result := True;
- if False{AccountsDisabled} then
- else if not Server.ValidName(AccountName, IPInt = localhost) then
- begin
- Packet.Send.AddInt2(AccountReplyNotApproved);
- Packet.Send.AddString('NO');
- Send;
- end{else if not Server.ValidName}
- else if Server.AccountExists(AccountName) then
- begin
- Packet.Send.AddInt2(AccountReplyAlreadyExists);
- Packet.Send.AddString('NO');
- Send;
- end{else if}
- else Result := False;
- end;{CheckAccount}
- procedure HandleAccountRequest;
- var
- AccountName: AnsiString;
- begin
- AccountName := Lower(Packet.Receive.GetString);
- if CheckAccount(AccountName) then exit;
- Packet.Send.AddInt2(AccountReplyContinue);
- Packet.Send.AddString('OK');
- Send;
- end;{HandleAccountRequest}
- procedure HandleAccountCreate;
- var
- AccountName: AnsiString;
- begin
- Packet.Receive.Discard(3);
- AccountName := Lower(Packet.Receive.GetBreakString);
- if CheckAccount(AccountName) then exit;
- Name := AccountName;
- Password := TSHA256.HashStr(Packet.Receive.GetBreakString);
- {FullName := }Packet.Receive.GetBreakString;
- {Location := }Packet.Receive.GetBreakString;
- {EmailAddress := }Packet.Receive.GetBreakString;
- {ComputerName := }Packet.Receive.GetBreakString;
- if Packet.Receive.GetBreakString <> HDDSerial then
- begin
- Packet.Send.AddInt2(AccountReplyNotApproved);
- Packet.Send.AddString('NO');
- Send;
- exit;
- end;{if Packet.Receive.GetBreakString <> HDDSerial}
- Log(['Creating account']);
- X := Server.Defaults.X;
- Y := Server.Defaults.Y;
- D := Server.Defaults.D;
- Gold := Server.Defaults.Gold;
- HP := Server.Defaults.HP;
- MaxHP := Server.Defaults.MaxHP;
- TP := Server.Defaults.TP;
- MaxTP := Server.Defaults.MaxTP;
- Sync;
- Unload;
- Packet.Send.AddInt2(AccountReplyCreated);
- Packet.Send.AddString('OK');
- Send;
- end;{HandleAccountCreate}
- begin
- if LoggedIn then exit;
- case Packet.Receive.Action of
- PacketActionRequest: HandleAccountRequest;
- PacketActionCreate: HandleAccountCreate;
- else
- UnhandledAction('account');
- end;{case Packet.Receive.Action}
- end;{Server.TSession.HandleAccount}
- procedure Server.TSession.HandleLogin;
- const
- LoginReplyUnknownUser = 1;
- LoginReplyWrongPassword = 2;
- LoginReplyOK = 3;
- // 4 = clear input
- LoginReplyAlreadyLoggedIn = 5;
- procedure HandleLoginRequest;
- begin
- Server.CriticalSection.Section(procedure
- var
- User: AnsiString;
- Pass: AnsiString;
- begin
- User := Lower(Packet.Receive.GetBreakString);
- Pass := TSHA256.HashStr(Packet.Receive.GetBreakString);
- if GetSessionByName(User) <> nil then
- begin
- Unload;
- Packet.Send.AddInt2(LoginReplyAlreadyLoggedIn);
- Send;
- exit;
- end;{if GetSessionByName}
- Name := User;
- if not Sync(True) then
- begin
- Unload;
- Packet.Send.AddInt2(LoginReplyUnknownUser);
- Send;
- end{if not Sync(True)}
- else if Pass <> Password then
- begin
- Unload;
- Packet.Send.AddInt2(LoginReplyWrongPassword);
- Send;
- end{else if Pass <> Password}
- else
- begin
- if Banned <> 0 then
- begin
- Packet.Send.SetID(0, 0);
- Packet.Send.AddByte(3);
- Packet.Send.AddByte(2);
- Send(True);
- Disconnect;
- Log(['Login from banned account "' + Name + '"']);
- exit;
- end;{if Banned}
- Login;
- end;{else}
- end);{Server.CriticalSection.Section}
- end;{HandleLoginRequest}
- begin
- if LoggedIn then exit;
- case Packet.Receive.Action of
- PacketActionRequest: HandleLoginRequest;
- else
- UnhandledAction('login');
- end;{case Packet.Receive.Action}
- end;{Server.TSession.HandleLogin}
- procedure Server.TSession.HandleGameState;
- procedure HandleGameStateAgree;
- var
- FileID: Byte;
- begin
- FileID := Packet.Receive.GetInt1;
- case FileID of
- 1: SendData(Server.MapData);
- 2: SendData(Server.ItemData);
- 3: SendData(Server.NPCData);
- 4: SendData(Server.SpellData);
- 5: SendData(Server.ClassData);
- else
- Log(['Unknown file ID ', FileID]);
- end;{case FileID}
- end;{HandleGameStateAgree}
- procedure HandleGameStateMessage;
- var
- i: Integer;
- begin
- Packet.Send.AddInt2(2);
- Packet.Send.AddByte(255);
- Packet.Send.AddBreakString('MEOW');
- for i := 0 to 6 do
- Packet.Send.AddBreakString(News[i]);
- Packet.Send.AddByte(255);
- Packet.Send.AddInt1(0); // Weight
- Packet.Send.AddInt1(50); // Max weight
- Packet.Send.AddInt2(GoldID);
- Packet.Send.AddInt4(Gold);
- Packet.Send.AddByte(255);
- // Spells
- Packet.Send.AddByte(255);
- LoggedIn := True;
- Server.CriticalSection.Section(procedure
- var
- p, Count: Integer;
- Session: TSession;
- begin
- p := length(Packet.Send.Data) + 1;
- Packet.Send.AddInt1(0);
- Packet.Send.AddByte(255);
- Count := 0;
- for Session in Server.Sessions.Items do
- if Session.LoggedIn then
- begin
- Session.BuildCharacterPacket(Packet.Send);
- Packet.Send.AddByte(255);
- inc(Count);
- end;{if Session.LoggedIn}
- Packet.Send.Data[p] := UnpackEOInt(Count)[1];
- end);{Server.CriticalSection.Section}
- Packet.Send.AddByte(255); // NPCs
- //Packet.Send.AddByte(255); // Items
- Send;
- Packet.Send.Reset;
- Packet.Send.SetID(PacketFamilyPlayers, PacketActionAgree);
- Packet.Send.AddByte(255);
- BuildCharacterPacket(Packet.Send);
- Packet.Send.AddInt1(1);
- Packet.Send.AddByte(255);
- Packet.Send.AddInt1(1);
- Server.Send(Packet.Send, Self);
- if (State and StateSexSelected) = 0 then SexDialog
- else if (State and StateRaceSelected) = 0 then RaceDialog
- else if (State and StateHairSelected) = 0 then Barber;
- end;{HandleGameStateMessage}
- begin
- case Packet.Receive.Action of
- PacketActionRequest: Login;
- PacketActionAgree: HandleGameStateAgree;
- PacketActionMessage: HandleGameStateMessage;
- else
- UnhandledAction('game state');
- end;{case Packet.Receive.Action}
- end;{Server.TSession.HandleGameState}
- procedure Server.TSession.HandleWalk;
- begin
- case Packet.Receive.Action of
- PacketActionPlayer: Walk(Packet.Receive.GetInt1);
- PacketActionSpecial: Walk(Packet.Receive.GetInt1, False, True);
- PacketActionAdmin: Walk(Packet.Receive.GetInt1, True);
- else
- UnhandledAction('walk');
- end;{case Packet.Receive.Action}
- end;{Server.TSession.HandleWalk}
- procedure Server.TSession.HandleFace;
- begin
- case Packet.Receive.Action of
- PacketActionPlayer: Face(Packet.Receive.GetInt1);
- else
- UnhandledAction('face');
- end;{case Packet.Receive.Action}
- end;{Server.TSession.HandleFace}
- procedure Server.TSession.HandleRequest;
- procedure HandleRequestRequest;
- var
- RequestID: Integer;
- Session: TSession;
- begin
- if not LoggedIn then exit;
- RequestID := Packet.Receive.GetInt2;
- Packet.Send.SetID(PacketFamilyPlayers, PacketActionRemove);
- Packet.Send.AddInt2(RequestID);
- Send;
- Packet.Send.Reset;
- Packet.Send.SetID(PacketFamilyPlayers, PacketActionAgree);
- Packet.Send.AddByte(255);
- Server.CriticalSection.Enter;
- try
- Session := Server.GetSessionByID(RequestID);
- if Session = nil then exit;
- if not Session.LoggedIn then exit;
- Session.BuildCharacterPacket(Packet.Send);
- finally
- Server.CriticalSection.Leave;
- end;{try..finally}
- Packet.Send.AddInt1(1);
- Packet.Send.AddByte(255);
- Packet.Send.AddInt1(1);
- Send;
- end;{HandleRequestRequest}
- begin
- case Packet.Receive.Action of
- PacketActionRequest: HandleRequestRequest;
- else
- UnhandledAction('request');
- end;{case Packet.Receive.Action}
- end;{Server.TSession.HandleRequest}
- procedure Server.TSession.HandleTalk;
- procedure HandleTalkTell;
- var
- SendTo: AnsiString;
- begin
- SendTo := Packet.Receive.GetBreakString;
- SendTo := Lower(SendTo);
- SendPM(SendTo, Packet.Receive.GetBreakString);
- end;{HandleTalkTell}
- begin
- case Packet.Receive.Action of
- PacketActionReport: Say(Packet.Receive.GetBreakString);
- PacketActionAnnounce: if Admin > 0 then Announce(Packet.Receive.GetBreakString);
- PacketActionTell: HandleTalkTell;
- PacketActionAdmin: if Admin > 0 then SayAdmin(Packet.Receive.GetBreakString);
- PacketActionRequest: SayGuild(Packet.Receive.GetBreakString);
- PacketActionMessage: SayGlobal(Packet.Receive.GetBreakString);
- else
- UnhandledAction('talk');
- end;{case Packet.Receive.Action}
- end;{Server.TSession.HandleTalk}
- const
- SitActionSit = 1;
- SitActionStand = 2;
- procedure Server.TSession.HandleSit;
- procedure HandleSitRequest;
- var
- SitAction: Integer;
- begin
- SitAction := Packet.Receive.GetInt1;
- case SitAction of
- SitActionSit: Sit;
- SitActionStand: Stand;
- end;{case SitAction}
- end;{HandleSitRequest}
- begin
- case Packet.Receive.Action of
- PacketActionRequest: HandleSitRequest;
- else
- UnhandledAction('sit');
- end;{case Packet.Receive.Action}
- end;{Server.TSession.HandleSit}
- procedure Server.TSession.HandleChair;
- procedure HandleChairRequest;
- var
- ChairAction: Integer;
- ChairX, ChairY: Integer;
- Session: TSession;
- begin
- if not LoggedIn then exit;
- ChairAction := Packet.Receive.GetInt1;
- if (ChairAction = SitActionSit) and (Sitting = SittingStand) then
- begin
- ChairX := Packet.Receive.GetInt1;
- ChairY := Packet.Receive.GetInt2;
- if (ChairX < 0) or (ChairX >= Server.MapData.Width) or
- (ChairY < 0) or (ChairY >= Server.MapData.Height) then exit;
- if (ChairX + ChairY - X - Y) > 1 then exit;
- Server.CriticalSection.Enter;
- try
- for Session in Server.Sessions.Items do
- if (Session <> Self) and (Session.LoggedIn) and (Session.X = ChairX) and (Session.Y = ChairY) then exit;
- finally
- Server.CriticalSection.Leave;
- end;{try...finally}
- case Server.MapData.Tiles[ChairY, ChairX].Kind of
- TMapData.MapTileChairDown: if (Y = (ChairY + 1)) and (X = ChairX) then D := DirectionDown else exit;
- TMapData.MapTileChairLeft: if (X = (ChairX - 1)) and (Y = ChairY) then D := DirectionLeft else exit;
- TMapData.MapTileChairRight: if (X = (ChairX + 1)) and (Y = ChairY) then D := DirectionRight else exit;
- TMapData.MapTileChairUp: if (Y = (ChairY - 1)) and (X = ChairX) then D := DirectionUp else exit;
- TMapData.MapTileChairDownRight:
- if (Y = (ChairY + 1)) and (X = ChairX) then D := DirectionDown
- else if (X = (ChairX + 1)) and (Y = ChairY) then D := DirectionRight
- else exit;
- TMapData.MapTileChairUpLeft:
- if (Y = (ChairY - 1)) and (X = ChairX) then D := DirectionUp
- else if (X = (ChairX - 1)) and (Y = ChairY) then D := DirectionLeft
- else exit;
- TMapData.MapTileChairAll:
- if (Y = (ChairY + 1)) and (X = ChairX) then D := DirectionDown
- else if (X = (ChairX + 1)) and (Y = ChairY) then D := DirectionRight
- else if (Y = (ChairY - 1)) and (X = ChairX) then D := DirectionUp
- else if (X = (ChairX - 1)) and (Y = ChairY) then D := DirectionLeft
- else exit;
- else
- exit;
- end;{case Server.MapData.Tiles.Kind}
- X := ChairX;
- Y := ChairY;
- Sit(True);
- end{if ChairAction}
- else
- begin
- if Sitting <> SittingChair then exit;
- case D of
- DirectionDown: inc(Y);
- DirectionLeft: dec(X);
- DirectionUp: dec(Y);
- DirectionRight: inc(X);
- end;{case Character.D}
- Stand;
- end;{else}
- end;{HandleChairRequest}
- begin
- case Packet.Receive.Action of
- PacketActionRequest: HandleChairRequest;
- else
- UnhandledAction('chair');
- end;{case Packet.Receive.Action}
- end;{Server.TSession.HandleChair}
- procedure Server.TSession.HandleAttack;
- begin
- case Packet.Receive.Action of
- PacketActionUse: Attack(Packet.Receive.GetInt1);
- else
- UnhandledAction('attack');
- end;{case Packet.Receive.Action}
- end;{Server.TSession.HandleAttack}
- procedure Server.TSession.HandleWarp;
- procedure HandleWarpAccept;
- var
- WX, WY: Integer;
- begin
- if not LoggedIn then exit;
- if WarpInfo.Time = 0 then exit;
- WarpInfo.Time := 0;
- Packet.Receive.GetInt2;
- WX := Packet.Receive.GetInt1;
- WY := Packet.Receive.GetInt1;
- if (WX <> WarpInfo.X) or (WY <> WarpInfo.Y) then exit;
- // TODO: Party bug, leave the party for now
- if Party <> nil then Party.Leave(Self);
- Packet.Send.SetID(PacketFamilyPlayers, PacketActionRemove);
- Packet.Send.AddInt2(ID);
- if WarpInfo.Animation <> WarpAnimationNone then
- begin
- //Packet.Send.Family := Packet.Send.Family + 1;
- Packet.Send.AddInt1(WarpInfo.Animation);
- end;{if WarpInfo.Animation}
- Server.Send(Packet.Send, Self);
- X := WX;
- Y := WY;
- Sitting := SittingStand;
- Packet.Send.Reset;
- Packet.Send.SetID(PacketFamilyPlayers, PacketActionAgree);
- Packet.Send.AddByte(255);
- BuildCharacterPacket(Packet.Send);
- Packet.Send.AddInt1(WarpInfo.Animation);
- Packet.Send.AddByte(255);
- Packet.Send.AddInt1(1);
- Server.Send(Packet.Send, Self);
- Packet.Send.Reset;
- Packet.Send.SetID(PacketFamilyWarp, PacketActionAgree);
- Packet.Send.AddInt1(2);
- Packet.Send.AddInt2(1);
- Packet.Send.AddInt1(WarpInfo.Animation);
- Server.CriticalSection.Section(procedure
- var
- p, Count: Integer;
- Session: TSession;
- begin
- p := length(Packet.Send.Data) + 1;
- Packet.Send.AddInt1(0);
- Packet.Send.AddByte(255);
- Count := 0;
- for Session in Server.Sessions.Items do
- if Session.LoggedIn then
- begin
- Session.BuildCharacterPacket(Packet.Send);
- Packet.Send.AddByte(255);
- inc(Count);
- end;{if Session.LoggedIn}
- Packet.Send.Data[p] := UnpackEOInt(Count)[1];
- end);{Server.CriticalSection.Section}
- Packet.Send.AddByte(255);
- Send;
- end;{HandleWarpAccept}
- begin
- case Packet.Receive.Action of
- PacketActionAccept: HandleWarpAccept;
- else
- UnhandledAction('warp');
- end;{case Packet.Receive.Action}
- end;{Server.TSession.HandleWarp}
- procedure Server.TSession.HandleEmote;
- begin
- case Packet.Receive.Action of
- PacketActionReport: Emote(Packet.Receive.GetInt1);
- else
- UnhandledAction('emote');
- end;{case Packet.Receive.Action}
- end;{Server.TSession.HandleEmote}
- procedure Server.TSession.HandleRefresh;
- begin
- case Packet.Receive.Action of
- PacketActionRequest: RefreshAll;
- else
- UnhandledAction('refresh');
- end;{case Packet.Receive.Action}
- end;{Server.TSession.HandleRefresh}
- procedure Server.TSession.HandleMessage;
- procedure HandleMessagePing;
- begin
- Packet.Send.SetID(PacketFamilyMessage, PacketActionPong);
- Packet.Send.AddInt2(Packet.Receive.GetInt2);
- Send;
- end;{HandleMessagePing}
- begin
- case Packet.Receive.Action of
- PacketActionPing: HandleMessagePing;
- else
- UnhandledAction('message');
- end;{case Packet.Receive.Action}
- end;{Server.TSession.HandleMessage}
- procedure Server.TSession.HandlePlayers;
- procedure HandlePlayersRequest;
- begin
- Packet.Send.SetID(PacketFamilyRaw, PacketActionRaw);
- Packet.Send.AddInt1(8);
- Server.CriticalSection.Section(procedure
- var
- p, Count: Integer;
- Session: TSession;
- begin
- p := length(Packet.Send.Data) + 1;
- Packet.Send.AddInt2(0);
- Packet.Send.AddByte(255);
- Count := 0;
- for Session in Server.Sessions.Items do
- if Session.LoggedIn then
- begin
- Packet.Send.AddBreakString(Session.Name);
- Packet.Send.AddBreakString(Session.IPStr);
- Packet.Send.AddInt1(0);
- if (Session.Admin > 3) or (Session.IPInt = localhost) then
- Packet.Send.AddInt1(5)
- else if Session.Admin > 0 then
- Packet.Send.AddInt1(4)
- else
- Packet.Send.AddInt1(0);
- Packet.Send.AddInt1(0); // Class
- Packet.Send.AddString(copy(Session.Tag + ' ', 1, 3));
- Packet.Send.AddByte(255);
- inc(Count);
- end;{if Session.LoggedIn}
- Packet.Send.Data[p] := UnpackEOInt(Count)[1];
- Packet.Send.Data[p + 1] := UnpackEOInt(Count)[2];
- end);{Server.CriticalSection.Section}
- Send(Packet.Send, True);
- end;{HandlePlayersRequest}
- procedure HandlePlayersAccept;
- var
- PlayerName: AnsiString;
- PlayerSession: TSession;
- PlayerFound: Boolean;
- begin
- PlayerName := Lower(Packet.Receive.GetString);
- Server.CriticalSection.Enter;
- try
- PlayerSession := Server.GetSessionByName(PlayerName);
- if PlayerSession <> nil then
- PlayerFound := PlayerSession.LoggedIn
- else
- PlayerFound := False;
- finally
- Server.CriticalSection.Leave;
- end;{try...finally}
- if PlayerFound then
- Packet.Send.SetID(PacketFamilyPlayers, 241)
- else
- Packet.Send.SetID(PacketFamilyPlayers, 240);
- Packet.Send.AddString(PlayerName);
- Send;
- end;{HandlePlayersAccept}
- begin
- case Packet.Receive.Action of
- PacketActionRequest: HandlePlayersRequest;
- PacketActionAccept: HandlePlayersAccept;
- else
- UnhandledAction('players');
- end;{case Packet.Receive.Action}
- end;{Server.TSession.HandlePlayers}
- procedure Server.TSession.HandleDoor;
- procedure HandleDoorOpen;
- var
- X, Y: Integer;
- begin
- if not LoggedIn then exit;
- X := Packet.Receive.GetInt1;
- Y := Packet.Receive.GetInt1;
- Server.OpenDoor(X, Y);
- end;{HandleDoorOpen}
- begin
- case Packet.Receive.Action of
- PacketActionOpen: HandleDoorOpen;
- else
- UnhandledAction('door');
- end;{case Packet.Receive.Action}
- end;{Server.TSession.HandleDoor}
- procedure Server.TSession.HandleGlobal;
- begin
- case Packet.Receive.Action of
- PacketActionOpen: ;
- PacketActionClose: ;
- else
- UnhandledAction('global');
- end;{case Packet.Receive.Action}
- end;{Server.TSession.HandleGlobal}
- procedure Server.TSession.HandleQuest;
- procedure HandleQuestAccept;
- var
- QuestID: Integer;
- SelectID: Integer;
- begin
- if not LoggedIn then exit;
- QuestID := Packet.Receive.GetInt4;
- Packet.Receive.Discard(5);
- SelectID := Packet.Receive.GetInt2;
- if SelectID = 0 then exit;
- case QuestID of
- CustomRaceID: DoCommand('race ' + Str(SelectID - 1));
- CustomSexID: DoCommand('sex ' + Str(SelectID - 1));
- end;{case QuestID}
- end;{HandleQuestAccept}
- begin
- case Packet.Receive.Action of
- PacketActionAccept: HandleQuestAccept;
- else
- UnhandledAction('quest');
- end;{case Packet.Receive.Action}
- end;{Server.TSession.HandleQuest}
- procedure Server.TSession.HandleBarber;
- procedure HandleBarberBuy;
- var
- NewStyle: Integer;
- NewColour: Integer;
- begin
- if not LoggedIn then exit;
- NewStyle := Packet.Receive.GetInt1;
- NewColour := Packet.Receive.GetInt1;
- Packet.Send.SetID(PacketFamilyBarber, PacketActionAgree);
- Packet.Send.AddInt4(Gold);
- Send;
- HairStyle := NewStyle;
- HairColour := NewColour;
- State := State or StateHairSelected;
- Refresh;
- end;{HandleBarberBuy}
- begin
- case Packet.Receive.Action of
- PacketActionBuy: HandleBarberBuy;
- else
- UnhandledAction('barber');
- end;{case Packet.Receive.Action}
- end;{Server.TSession.HandleBarber}
- procedure Server.TSession.HandleAdmin;
- procedure HandleAdminTell;
- var
- s: AnsiString;
- begin
- s := '[request] ' + copy(Packet.Receive.GetString, 1, Server.TextLength);
- Server.AdminMsg(s, Name);
- end;{HandleAdminTell}
- procedure HandleAdminReport;
- var
- s: AnsiString;
- begin
- s := '[report:' + copy(Packet.Receive.GetBreakString, 1, 32) + '] ' + copy(Packet.Receive.GetString, 1, Server.TextLength);
- Server.AdminMsg(s, Name);
- end;{HandleAdminReport}
- begin
- case Packet.Receive.Action of
- PacketActionTell: HandleAdminTell;
- PacketActionReport: HandleAdminReport;
- else
- UnhandledAction('admin');
- end;{case Packet.Receive.Action}
- end;{Server.TSession.HandleAdmin}
- procedure Server.TSession.HandleParty;
- const
- PartyRequestJoin = 0;
- PartyRequestInvite = 1;
- procedure HandlePartyRequest;
- var
- Request: Integer;
- begin
- Request := Packet.Receive.GetInt1;
- if not (Request in [PartyRequestJoin, PartyRequestInvite]) then exit;
- Server.CriticalSection.Section(procedure
- var
- Invitee: TSession;
- Packet: TPacket;
- begin
- Invitee := Server.GetSessionByID(Self.Packet.Receive.GetInt2);
- if Invitee = nil then exit;
- if (Invitee.Offline) or (not Invitee.LoggedIn) then exit;
- if (Invitee.Party <> nil) and (Request = PartyRequestInvite) then exit;
- Packet.SetID(PacketFamilyParty, PacketActionRequest);
- Packet.AddInt1(Request);
- Packet.AddInt2(ID);
- Packet.AddString(Name);
- Invitee.Send(Packet);
- end);{Server.CriticalSection.Section}
- end;{HandlePartyRequest}
- procedure HandlePartyAccept;
- var
- Request: Integer;
- begin
- Request := Packet.Receive.GetInt1;
- Server.CriticalSection.Section(procedure
- var
- Inviter: TSession;
- begin
- Inviter := Server.GetSessionByID(Self.Packet.Receive.GetInt2);
- if Inviter = nil then exit;
- if (Inviter.Offline) or (not Inviter.LoggedIn) then exit;
- case Request of
- PartyRequestJoin:
- begin
- if Party = nil then
- TParty.Create(Self);
- Party.Join(Inviter);
- end;{PartyRequestJoin:}
- PartyRequestInvite:
- begin
- if Inviter.Party = nil then
- TParty.Create(Inviter);
- Inviter.Party.Join(Self);
- end;{PartyRequestInvite:}
- end;{case Request}
- end);{Server.CriticalSection.Section}
- end;{HandlePartyAccept}
- procedure HandlePartyRemove;
- var
- RemoveID: Cardinal;
- begin
- if Party = nil then exit;
- RemoveID := Packet.Receive.GetInt2;
- if (RemoveID = ID) or (Party.Leader = Self) then Party.Leave(RemoveID)
- end;{HandlePartyRemove}
- procedure HandlePartyTake;
- begin
- end;{HandlePartyTake}
- begin
- if (not LoggedIn) or Offline then exit;
- case Packet.Receive.Action of
- PacketActionRequest: HandlePartyRequest;
- PacketActionAccept: HandlePartyAccept;
- PacketActionRemove: HandlePartyRemove;
- PacketActionTake: HandlePartyTake;
- else
- UnhandledAction('party');
- end;{case Packet.Receive.Action}
- end;{Server.TSession.HandleParty}
- procedure Server.TSession._test(Params: AnsiString);
- var
- Packet: TPacket;
- i: Integer;
- begin
- for i := Int(Split(Params)) to Int(Params) do
- begin
- Packet.Reset;
- Packet.SetID(PacketFamilyEffect, i);
- Packet.AddString(Str(i) + Name);
- Send(Packet);
- end;
- end;{Server.TSession._test}
- constructor Server.TSession.TParty.Create(ALeader: TSession);
- begin
- inherited Create;
- Members := TArray<TSession>.Create;
- Leader := nil;
- Join(ALeader);
- end;{Server.TSession.TParty.Create}
- destructor Server.TSession.TParty.Destroy;
- var
- Packet: TPacket;
- begin
- Packet.SetID(PacketFamilyParty, PacketActionClose);
- Packet.AddInt2(255);
- Server.CriticalSection.Section(procedure
- var
- Member: TSession;
- begin
- for Member in Members.Items do
- begin
- Member.Send(Packet);
- Member.Party := nil;
- end;{for Member}
- if Leader <> nil then
- begin
- Leader.Send(Packet);
- Leader.Party := nil;
- Leader := nil;
- end;{if Leader}
- end);{Server.CriticalSection.Section}
- Members.Free;
- inherited;
- end;{Server.TSession.TParty.Destroy}
- procedure Server.TSession.TParty.Join(Session: TSession);
- begin
- Server.CriticalSection.Section(procedure
- var
- Packet: TPacket;
- Member: TSession;
- begin
- if Session.Party <> nil then exit;
- if Session = Leader then exit;
- for Member in Members.Items do
- if Member = Session then exit;
- if Leader = nil then
- Leader := Session
- else
- Members.Add(Session);
- Session.Party := Self;
- Packet.SetID(PacketFamilyParty, PacketActionAdd);
- Packet.AddInt2(Session.ID);
- Packet.AddInt1(0);// Admin icon
- Packet.AddInt1(0);// Level
- if Session.MaxHP = 1 then Session.MaxHP := 1;
- Packet.AddInt1(round((Session.HP / Session.MaxHP) * 100));
- Packet.AddString(Session.Name);
- for Member in Members.Items do
- if Member <> Session then Member.Send(Packet);
- if (Leader <> nil) and (Leader <> Session) then
- Leader.Send(Packet);
- end);{Server.CriticalSection.Section}
- Refresh(Session);
- end;{Server.TSession.TParty.Join}
- procedure Server.TSession.TParty.Leave(Session: TSession);
- begin
- Server.CriticalSection.Section(procedure
- var
- Packet: TPacket;
- Member: TSession;
- begin
- if Session.Party <> Self then exit;
- if Session = Leader then
- begin
- Free;
- exit;
- end;{if Session = Leader}
- Members.Remove(Session);
- Session.Party := nil;
- Packet.SetID(PacketFamilyParty, PacketActionRemove);
- Packet.AddInt2(Session.ID);
- for Member in Members.Items do
- Member.Send(Packet);
- if Leader <> nil then Leader.Send(Packet);
- Packet.Reset;
- Packet.SetID(PacketFamilyParty, PacketActionClose);
- Packet.AddInt2(255);
- Session.Send(Packet);
- if length(Members.Items) < 2 then Free;
- end);{Server.CriticalSection.Section}
- end;{Server.TSession.TParty.Leave (TSession)}
- procedure Server.TSession.TParty.Leave(ID: Cardinal);
- begin
- Server.CriticalSection.Section(procedure
- var
- Member: TSession;
- begin
- if (Leader <> nil) and (Leader.ID = ID) then
- Leave(Leader)
- else
- for Member in Members.Items do
- if Member.ID = ID then
- begin
- Leave(Member);
- break;
- end;{if Member.ID}
- end);{Server.CriticalSection.Section}
- end;{Server.TSession.TParty.Leave (Caridnal)}
- procedure Server.TSession.TParty.Refresh(Session: TSession);
- begin
- Server.CriticalSection.Section(procedure
- var
- Packet: TPacket;
- Member: TSession;
- procedure ListMember(Member: TSession; Icon: Integer = 0);
- begin
- Packet.AddInt2(Member.ID);
- Packet.AddInt1(Icon);
- Packet.AddInt1(0);//Level
- if Member.MaxHP < 1 then Member.MaxHP := 1;
- Packet.AddInt1(round((Member.HP / Member.MaxHP) * 100));
- Packet.AddBreakString(Member.Name);
- end;{ListMember}
- begin
- Packet.SetID(PacketFamilyParty, PacketActionCreate);
- if Leader <> nil then ListMember(Leader, 1);
- for Member in Members.Items do
- ListMember(Member);
- Session.Send(Packet);
- end);{Server.CriticalSection.Section}
- end;{Server.TSession.TParty.Refresh}
- procedure Server.TSession.TParty.Update(Session: TSession);
- begin
- Server.CriticalSection.Section(procedure
- var
- Packet: TPacket;
- Member: TSession;
- begin
- Packet.SetID(PacketFamilyParty, PacketActionAgree);
- Packet.AddInt2(Session.ID);
- if Session.MaxHP < 1 then Session.MaxHP := 1;
- Packet.AddInt1(round((Session.HP / Session.MaxHP) * 100));
- if Leader <> nil then Leader.Send(Packet);
- for Member in Members.Items do
- Member.Send(Packet);
- end);{Server.CriticalSection.Section}
- end;{Server.TSession.TParty.Update}
- begin
- Server.Create;
- end.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement