2022-07-19 18:24:03 +02:00
|
|
|
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<TUoaDesignHeader>)
|
|
|
|
constructor CreateFromStream(AStream: TStream);
|
|
|
|
end;
|
|
|
|
|
2022-07-20 18:54:00 +02:00
|
|
|
TUoaDesign = class
|
|
|
|
private
|
|
|
|
FHeader: TUoaDesignHeader;
|
|
|
|
FTiles: TStaticItemList;
|
|
|
|
|
|
|
|
constructor Create(AHeader: TUoaDesignHeader; AData: TStream);
|
|
|
|
public
|
|
|
|
property Header: TUoaDesignHeader read FHeader;
|
|
|
|
property Tiles: TStaticItemList read Ftiles;
|
|
|
|
|
|
|
|
destructor Destroy; override;
|
|
|
|
end;
|
|
|
|
|
2022-07-19 18:24:03 +02:00
|
|
|
{ TUoaDesigns }
|
|
|
|
|
|
|
|
TUoaDesigns = class
|
|
|
|
private
|
|
|
|
FHeaders: TUoaDesignHeaders;
|
|
|
|
FData: TFileStream;
|
|
|
|
public
|
|
|
|
constructor Create(AIdxFile, ABinFile: String);
|
|
|
|
destructor Destroy; override;
|
|
|
|
|
2022-07-20 18:54:00 +02:00
|
|
|
function LoadDesign(AHeader: TUoaDesignHeader): TUoaDesign;
|
2022-07-19 18:24:03 +02:00
|
|
|
public
|
|
|
|
property Headers: TUoaDesignHeaders read FHeaders;
|
|
|
|
end;
|
|
|
|
|
|
|
|
implementation
|
|
|
|
|
2022-07-20 20:22:29 +02:00
|
|
|
uses
|
|
|
|
Math;
|
|
|
|
|
2022-07-19 18:24:03 +02:00
|
|
|
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;
|
|
|
|
|
2022-07-20 18:54:00 +02:00
|
|
|
{ TUoaDesign }
|
|
|
|
|
|
|
|
constructor TUoaDesign.Create(AHeader: TUoaDesignHeader; AData: TStream);
|
|
|
|
var
|
|
|
|
i: Integer;
|
|
|
|
tile: TStaticItem;
|
|
|
|
version: Int32;
|
|
|
|
|
|
|
|
function ReadInt: Int32;
|
|
|
|
begin
|
|
|
|
AData.Read(Result, SizeOf(Result));
|
|
|
|
end;
|
|
|
|
|
|
|
|
begin
|
|
|
|
FHeader := AHeader;
|
|
|
|
FTiles := TStaticItemList.Create(True);
|
|
|
|
AData.Seek(FHeader.FilePosition, soFromBeginning);
|
|
|
|
for i := 0 to FHeader.TileCount - 1 do
|
|
|
|
begin
|
|
|
|
AData.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 := ReadInt;
|
|
|
|
tile.Y := ReadInt;
|
2022-07-20 20:22:29 +02:00
|
|
|
tile.Z := EnsureRange(ReadInt, -128, 127);
|
2022-07-20 18:54:00 +02:00
|
|
|
ReadInt; // Level; unused
|
|
|
|
|
|
|
|
if version = 1 then
|
|
|
|
tile.Hue := ReadInt;
|
|
|
|
|
|
|
|
FTiles.Add(tile);
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
destructor TUoaDesign.Destroy;
|
|
|
|
begin
|
|
|
|
FTiles.Free;
|
|
|
|
inherited Destroy;
|
|
|
|
end;
|
|
|
|
|
2022-07-19 18:24:03 +02:00
|
|
|
{ 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;
|
|
|
|
|
2022-07-20 18:54:00 +02:00
|
|
|
function TUoaDesigns.LoadDesign(AHeader: TUoaDesignHeader): TUoaDesign;
|
2022-07-19 18:24:03 +02:00
|
|
|
begin
|
2022-07-20 18:54:00 +02:00
|
|
|
Result := TUoaDesign.Create(AHeader, FData);
|
2022-07-19 18:24:03 +02:00
|
|
|
end;
|
|
|
|
|
|
|
|
end.
|
|
|
|
|