unit UUoaDesigns; {$mode ObjFPC}{$H+} {$modeSwitch advancedRecords} interface uses Classes, SysUtils, Generics.Collections, UStatics; type { TUoaDesignHeader } TUoaDesignHeader = record Name: String; Category: String; Subcategory: String; Width: Int32; Height: Int32; UserWidth: Int32; UserHeight: Int32; FilePosition: Int64; TileCount: Int32; public constructor CreateFromStream(AStream: TStream); end; { TUoaDesignHeaders } TUoaDesignHeaders = class(specialize TList) constructor CreateFromStream(AStream: TStream); end; { TUoaDesigns } TUoaDesigns = class private FHeaders: TUoaDesignHeaders; FData: TFileStream; public constructor Create(AIdxFile, ABinFile: String); destructor Destroy; override; function LoadTiles(AHeader: TUoaDesignHeader; AOffsetX, AOffsetY: Word): TStaticItemList; public property Headers: TUoaDesignHeaders read FHeaders; end; implementation function ReadString(AStream: TStream): String; var nonNullFlag: Byte; length: Byte; begin nonNullFlag := AStream.ReadByte; if nonNullFlag = 1 then begin length := AStream.ReadByte; SetLength(Result, length); if length > 0 then AStream.Read(PChar(Result)^, length); end; end; { TUoaDesignHeaders } constructor TUoaDesignHeaders.CreateFromStream(AStream: TStream); var headerCount, version: Int32; i: Integer; begin AStream.Read(headerCount, SizeOf(headerCount)); AStream.Read(version, SizeOf(version)); if version <> 0 then raise Exception.Create('Unknown UOA design index version'); inherited Create; for i := 0 to headerCount-1 do Add(TUoaDesignHeader.CreateFromStream(AStream)); end; { TUoaDesignHeader } constructor TUoaDesignHeader.CreateFromStream(AStream: TStream); begin Name := ReadString(AStream); Category := ReadString(AStream); Subcategory := ReadString(AStream); AStream.Read(Width, SizeOf(Width)); AStream.Read(Height, SizeOf(Height)); AStream.Read(UserWidth, SizeOf(UserWidth)); AStream.Read(UserHeight, SizeOf(UserHeight)); AStream.Read(FilePosition, SizeOf(FilePosition)); AStream.Read(TileCount, SizeOf(TileCount)); end; { TUoaDesigns } constructor TUoaDesigns.Create(AIdxFile, ABinFile: String); var idxStream: TFileStream; begin idxStream := TFileStream.Create(AIdxFile, fmOpenRead); try FHeaders := TUoaDesignHeaders.CreateFromStream(idxStream); finally idxStream.Free; end; FData := TFileStream.Create(ABinFile, fmOpenRead); end; destructor TUoaDesigns.Destroy; begin Headers.Free; end; function TUoaDesigns.LoadTiles(AHeader: TUoaDesignHeader; AOffsetX, AOffsetY: Word): TStaticItemList; var i: Integer; tile: TStaticItem; version: Int32; function ReadInt: Int32; begin FData.Read(Result, SizeOf(Result)); end; begin Result := TStaticItemList.Create(True); FData.Seek(AHeader.FilePosition, soFromBeginning); for i := 0 to AHeader.TileCount - 1 do begin FData.Read(version, SizeOf(version)); if (version < 0) or (version > 1) then raise Exception.Create('Unsupported binary version'); tile := TStaticItem.Create(nil); tile.TileID := ReadInt; tile.X := AOffsetX + ReadInt; tile.Y := AOffsetY + ReadInt; tile.Z := ReadInt; ReadInt; // TODO: Level?? if version = 1 then tile.Hue := ReadInt; Result.Add(tile); end; end; end.