From 811d91cc8a46854e664326d1f165b8a7c9fa2d6d Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Sat, 7 Jan 2012 13:48:59 +0100 Subject: [PATCH] * Refactored tiledata cloning * Added support for new tiledata format (from the High Seas expansion) --- MulProvider/UTileDataProvider.pas | 18 +++-- UOLib/UTiledata.pas | 112 ++++++++++++++++++++++-------- 2 files changed, 96 insertions(+), 34 deletions(-) diff --git a/MulProvider/UTileDataProvider.pas b/MulProvider/UTileDataProvider.pas index 99f8f50..bc8969a 100644 --- a/MulProvider/UTileDataProvider.pas +++ b/MulProvider/UTileDataProvider.pas @@ -21,7 +21,7 @@ * CDDL HEADER END * * - * Portions Copyright 2009 Andreas Schneider + * Portions Copyright 2012 Andreas Schneider *) unit UTileDataProvider; @@ -114,14 +114,24 @@ end; procedure TTiledataProvider.InitArray; var i: Integer; + version: TTileDataVersion; begin + //Guess the version by looking at the filesize. + if FData.Size >= 3188736 then + version := tdvHighSeas + else + version := tdvLegacy; + FData.Position := 0; Logger.Send([lcInfo], 'Loading $4000 LandTiledata Entries'); for i := $0 to $3FFF do begin - if i mod 32 = 0 then + //In High Seas, the first header comes AFTER the unknown tile (for whatever + //reason). Therefore special handling is required. + if ((version = tdvLegacy) and (i mod 32 = 0)) or + ((version >= tdvHighSeas) and ((i = 1) or ((i > 1) and (i mod 32 = 0)))) then FData.Seek(4, soFromCurrent); - FLandTiles[i] := TLandTileData.Create(FData); + FLandTiles[i] := TLandTileData.Create(FData, version); end; FStaticCount := ((FData.Size - FData.Position) div StaticTileGroupSize) * 32; @@ -132,7 +142,7 @@ begin begin if i mod 32 = 0 then FData.Seek(4, soFromCurrent); - FStaticTiles[i] := TStaticTileData.Create(FData); + FStaticTiles[i] := TStaticTileData.Create(FData, version); end; end; diff --git a/UOLib/UTiledata.pas b/UOLib/UTiledata.pas index 5844cac..2dd464c 100644 --- a/UOLib/UTiledata.pas +++ b/UOLib/UTiledata.pas @@ -21,7 +21,7 @@ * CDDL HEADER END * * - * Portions Copyright 2009 Andreas Schneider + * Portions Copyright 2012 Andreas Schneider *) unit UTiledata; @@ -49,12 +49,19 @@ type tdfStairRight); TTileDataFlags = set of TTileDataFlag; + TTileDataVersion = (tdvLegacy, tdvHighSeas); + { TTiledata } TTiledata = class(TMulBlock) protected + FVersion: TTileDataVersion; FFlags: TTileDataFlags; + FNewFlags: LongWord; //HighSeas added new flags FTileName: string; + procedure ReadFlags(AData: TStream); + procedure WriteFlags(AData: TStream); + procedure PopulateClone(const AClone: TTiledata); public property Flags: TTileDataFlags read FFlags write FFlags; property TileName: string read FTileName write FTileName; @@ -63,13 +70,14 @@ type { TLandTiledata } TLandTiledata = class(TTiledata) - constructor Create(AData: TStream); + constructor Create(AData: TStream; AVersion: TTileDataVersion = tdvLegacy); destructor Destroy; override; function Clone: TLandTiledata; override; function GetSize: Integer; override; procedure Write(AData: TStream); override; protected FTextureID: Word; + procedure PopulateClone(const AClone: TLandTiledata); public property TextureID: Word read FTextureID write FTextureID; end; @@ -77,7 +85,7 @@ type { TStaticTiledata } TStaticTiledata = class(TTiledata) - constructor Create(AData: TStream); + constructor Create(AData: TStream; AVersion: TTileDataVersion = tdvLegacy); destructor Destroy; override; function Clone: TStaticTiledata; override; function GetSize: Integer; override; @@ -93,6 +101,7 @@ type FHue: Byte; FUnknown4: Word; FHeight: Byte; + procedure PopulateClone(const AClone: TStaticTiledata); public property Weight: Byte read FWeight write FWeight; property Quality: Byte read FQuality write FQuality; @@ -109,7 +118,7 @@ type { TLandTileGroup } TLandTileGroup = class(TMulBlock) - constructor Create(AData: TStream); + constructor Create(AData: TStream; AVersion: TTileDataVersion = tdvLegacy); destructor Destroy; override; function Clone: TLandTileGroup; override; function GetSize: Integer; override; @@ -124,7 +133,7 @@ type { TStaticTileGroup } TStaticTileGroup = class(TMulBlock) - constructor Create(AData: TStream); + constructor Create(AData: TStream; AVersion: TTileDataVersion = tdvLegacy); destructor Destroy; override; function Clone: TStaticTileGroup; override; function GetSize: Integer; override; @@ -161,14 +170,43 @@ begin end; end; +{ TTiledata } + +procedure TTiledata.ReadFlags(AData: TStream); +begin + AData.Read(FFlags, SizeOf(LongWord)); + if FVersion >= tdvHighSeas then + AData.Read(FNewFlags, SizeOf(LongWord)); +end; + +procedure TTiledata.WriteFlags(AData: TStream); +begin + AData.Write(FFlags, SizeOf(LongWord)); + if FVersion >= tdvHighSeas then + AData.Write(FNewFlags, SizeOf(LongWord)); +end; + +procedure TTiledata.PopulateClone(const AClone: TTiledata); +begin + AClone.FVersion := FVersion; + AClone.FFlags := FFlags; + AClone.FNewFlags := FNewFlags; + AClone.FTileName := FTileName; +end; + { TLandTiledata } -constructor TLandTiledata.Create(AData: TStream); +constructor TLandTiledata.Create(AData: TStream; + AVersion: TTileDataVersion = tdvLegacy); +var + legacyFlags: LongWord; + highSeasFlags: QWord; begin + FVersion := AVersion; SetLength(FTileName, 20); if assigned(AData) then begin - AData.Read(FFlags, SizeOf(LongWord)); + ReadFlags(AData); AData.Read(FTextureID, SizeOf(Word)); AData.Read(PChar(FTileName)^, 20); end; @@ -184,9 +222,7 @@ end; function TLandTiledata.Clone: TLandTiledata; begin Result := TLandTiledata.Create(nil); - Result.FFlags := FFlags; - Result.FTextureID := FTextureID; - Result.FTileName := FTileName; + PopulateClone(Result); end; procedure TLandTiledata.Write(AData: TStream); @@ -196,11 +232,18 @@ begin if Length(FTileName) < 20 then for i := Length(FTileName) to 20 do FTileName := FTileName + #0; - AData.Write(FFlags, SizeOf(LongWord)); + + WriteFlags(AData); AData.Write(FTextureID, SizeOf(Word)); AData.Write(PChar(FTileName)^, 20); end; +procedure TLandTiledata.PopulateClone(const AClone: TLandTiledata); +begin + inherited PopulateClone(AClone); + AClone.FTextureID := FTextureID; +end; + function TLandTiledata.GetSize: Integer; begin GetSize := LandTileDataSize; @@ -208,12 +251,14 @@ end; { TStaticTiledata} -constructor TStaticTiledata.Create(AData: TStream); +constructor TStaticTiledata.Create(AData: TStream; + AVersion: TTileDataVersion = tdvLegacy); begin + FVersion := AVersion; SetLength(FTileName, 20); if AData <> nil then begin - AData.Read(FFlags, SizeOf(LongWord)); + ReadFlags(AData); AData.Read(FWeight, SizeOf(Byte)); AData.Read(FQuality, SizeOf(Byte)); AData.Read(FUnknown1, SizeOf(Word)); @@ -238,18 +283,7 @@ end; function TStaticTiledata.Clone: TStaticTiledata; begin Result := TStaticTiledata.Create(nil); - Result.FFlags := FFlags; - Result.FWeight := FWeight; - Result.FQuality := FQuality; - Result.FUnknown1 := FUnknown1; - Result.FUnknown2 := FUnknown2; - Result.FQuantity := FQuantity; - Result.FAnimID := FAnimID; - Result.FUnknown3 := FUnknown3; - Result.FHue := FHue; - Result.FUnknown4 := FUnknown4; - Result.FHeight := FHeight; - Result.FTileName := FTileName; + PopulateClone(Result); end; procedure TStaticTiledata.Write(AData: TStream); @@ -259,7 +293,8 @@ begin if Length(FTileName) < 20 then for i := Length(FTileName) to 20 do FTileName := FTileName + #0; - AData.Write(FFlags, SizeOf(LongWord)); + + WriteFlags(AData); AData.Write(FWeight, SizeOf(Byte)); AData.Write(FQuality, SizeOf(Byte)); AData.Write(FUnknown1, SizeOf(Word)); @@ -273,6 +308,21 @@ begin AData.Write(PChar(FTileName)^, 20); end; +procedure TStaticTiledata.PopulateClone(const AClone: TStaticTiledata); +begin + inherited PopulateClone(AClone); + AClone.FWeight := FWeight; + AClone.FQuality := FQuality; + AClone.FUnknown1 := FUnknown1; + AClone.FUnknown2 := FUnknown2; + AClone.FQuantity := FQuantity; + AClone.FAnimID := FAnimID; + AClone.FUnknown3 := FUnknown3; + AClone.FHue := FHue; + AClone.FUnknown4 := FUnknown4; + AClone.FHeight := FHeight; +end; + function TStaticTiledata.GetSize: Integer; begin GetSize := StaticTileDataSize; @@ -280,7 +330,8 @@ end; { TLandTileGroup } -constructor TLandTileGroup.Create(AData: TStream); +constructor TLandTileGroup.Create(AData: TStream; + AVersion: TTileDataVersion = tdvLegacy); var i: Integer; begin @@ -289,7 +340,7 @@ begin AData.Read(FUnknown, SizeOf(LongInt)); end; for i := 0 to 31 do - LandTileData[i] := TLandTiledata.Create(AData); + LandTileData[i] := TLandTiledata.Create(AData, AVersion); end; destructor TLandTileGroup.Destroy; @@ -327,7 +378,8 @@ end; { TStaticTileGroup } -constructor TStaticTileGroup.Create(AData: TStream); +constructor TStaticTileGroup.Create(AData: TStream; + AVersion: TTileDataVersion = tdvLegacy); var i: Integer; begin @@ -336,7 +388,7 @@ begin AData.Read(FUnknown, SizeOf(LongInt)); end; for i := 0 to 31 do - StaticTileData[i] := TStaticTiledata.Create(AData); + StaticTileData[i] := TStaticTiledata.Create(AData, AVersion); end; destructor TStaticTileGroup.Destroy;