- Added more checks to statics loading and saving and replaced unnecessary LongInt casts

This commit is contained in:
Andreas Schneider 2009-03-09 17:24:53 +01:00
parent 114c218ca6
commit 7e86c7400c
3 changed files with 383 additions and 384 deletions

View File

@ -479,14 +479,14 @@ begin
FStaIdx.Position := ((AWorldBlock.X * FHeight) + AWorldBlock.Y) * 12; FStaIdx.Position := ((AWorldBlock.X * FHeight) + AWorldBlock.Y) * 12;
index := TGenericIndex.Create(FStaIdx); index := TGenericIndex.Create(FStaIdx);
size := AWorldBlock.GetSize; size := AWorldBlock.GetSize;
if (size > index.Size) or (index.Lookup = LongInt($FFFFFFFF)) then if (size > index.Size) or (index.Lookup < 0) then
begin begin
FStatics.Position := FStatics.Size; FStatics.Position := FStatics.Size;
index.Lookup := FStatics.Position; index.Lookup := FStatics.Position;
end; end;
index.Size := size; index.Size := size;
if size = 0 then if size = 0 then
index.Lookup := LongInt($FFFFFFFF) index.Lookup := -1
else else
begin begin
FStatics.Position := index.Lookup; FStatics.Position := index.Lookup;

View File

@ -1,12 +1,13 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<CONFIG> <CONFIG>
<ProjectOptions> <ProjectOptions>
<PathDelim Value="/"/> <Version Value="7"/>
<Version Value="6"/>
<General> <General>
<Flags>
<LRSInOutputDirectory Value="False"/>
</Flags>
<SessionStorage Value="InProjectDir"/> <SessionStorage Value="InProjectDir"/>
<MainUnit Value="0"/> <MainUnit Value="0"/>
<IconPath Value="./"/>
<TargetFileExt Value=".exe"/> <TargetFileExt Value=".exe"/>
</General> </General>
<VersionInfo> <VersionInfo>

View File

@ -1,379 +1,377 @@
(* (*
* CDDL HEADER START * CDDL HEADER START
* *
* The contents of this file are subject to the terms of the * The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only * Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance * (the "License"). You may not use this file except in compliance
* with the License. * with the License.
* *
* You can obtain a copy of the license at * You can obtain a copy of the license at
* http://www.opensource.org/licenses/cddl1.php. * http://www.opensource.org/licenses/cddl1.php.
* See the License for the specific language governing permissions * See the License for the specific language governing permissions
* and limitations under the License. * and limitations under the License.
* *
* When distributing Covered Code, include this CDDL HEADER in each * When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at * file and include the License file at
* http://www.opensource.org/licenses/cddl1.php. If applicable, * http://www.opensource.org/licenses/cddl1.php. If applicable,
* add the following below this CDDL HEADER, with the fields enclosed * add the following below this CDDL HEADER, with the fields enclosed
* by brackets "[]" replaced with your own identifying * information: * by brackets "[]" replaced with your own identifying * information:
* Portions Copyright [yyyy] [name of copyright owner] * Portions Copyright [yyyy] [name of copyright owner]
* *
* CDDL HEADER END * CDDL HEADER END
* *
* *
* Portions Copyright 2007 Andreas Schneider * Portions Copyright 2007 Andreas Schneider
*) *)
unit UStatics; unit UStatics;
{$mode objfpc}{$H+} {$mode objfpc}{$H+}
interface interface
uses uses
SysUtils, Classes, UMulBlock, UGenericIndex, UTiledata, UWorldItem; SysUtils, Classes, UMulBlock, UGenericIndex, UTiledata, UWorldItem;
type type
TStaticItem = class(TWorldItem) TStaticItem = class(TWorldItem)
constructor Create(AOwner: TWorldBlock; AData: TStream; ABlockX, ABlockY: Word); overload; constructor Create(AOwner: TWorldBlock; AData: TStream; ABlockX, ABlockY: Word); overload;
constructor Create(AOwner: TWorldBlock; AData: TStream); overload; constructor Create(AOwner: TWorldBlock; AData: TStream); overload;
function Clone: TStaticItem; override; function Clone: TStaticItem; override;
function GetIdentifier: Integer; function GetIdentifier: Integer;
function GetSize: Integer; override; function GetSize: Integer; override;
procedure Write(AData: TStream); override; procedure Write(AData: TStream); override;
protected protected
FHue, FOrgHue: Word; FHue, FOrgHue: Word;
procedure SetHue(AHue: Word); procedure SetHue(AHue: Word);
function HasChanged: Boolean; override; function HasChanged: Boolean; override;
public public
procedure InitOriginalState; override; procedure InitOriginalState; override;
property Hue: Word read FHue write SetHue; property Hue: Word read FHue write SetHue;
end; end;
TStaticBlock = class(TWorldBlock) TStaticBlock = class(TWorldBlock)
constructor Create(AData: TStream; AIndex: TGenericIndex; AX, AY: Word); overload; constructor Create(AData: TStream; AIndex: TGenericIndex; AX, AY: Word); overload;
constructor Create(AData: TStream; AIndex: TGenericIndex); overload; constructor Create(AData: TStream; AIndex: TGenericIndex); overload;
destructor Destroy; override; destructor Destroy; override;
function Clone: TStaticBlock; override; function Clone: TStaticBlock; override;
function GetSize: Integer; override; function GetSize: Integer; override;
procedure Write(AData: TStream); override; procedure Write(AData: TStream); override;
procedure ReverseWrite(AData: TStream); procedure ReverseWrite(AData: TStream);
procedure Sort; procedure Sort;
protected protected
FItems: TList; FItems: TList;
public public
property Items: TList read FItems write FItems; property Items: TList read FItems write FItems;
end; end;
TSeperatedStaticBlock = class(TStaticBlock) TSeperatedStaticBlock = class(TStaticBlock)
constructor Create(AData: TStream; AIndex: TGenericIndex; AX, AY: Word); overload; constructor Create(AData: TStream; AIndex: TGenericIndex; AX, AY: Word); overload;
constructor Create(AData: TStream; AIndex: TGenericIndex); overload; constructor Create(AData: TStream; AIndex: TGenericIndex); overload;
destructor Destroy; override; destructor Destroy; override;
function Clone: TSeperatedStaticBlock; override; function Clone: TSeperatedStaticBlock; override;
function GetSize: Integer; override; function GetSize: Integer; override;
protected protected
procedure RefreshList; procedure RefreshList;
public public
Cells: array[0..63] of TList; Cells: array[0..63] of TList;
end; end;
implementation implementation
{ TStaticItem } { TStaticItem }
constructor TStaticItem.Create(AOwner: TWorldBlock; AData: TStream; ABlockX, ABlockY: Word); constructor TStaticItem.Create(AOwner: TWorldBlock; AData: TStream; ABlockX, ABlockY: Word);
var var
iX, iY: Byte; iX, iY: Byte;
begin begin
inherited Create(AOwner); inherited Create(AOwner);
if assigned(AData) then if assigned(AData) then
begin begin
AData.Read(FTileID, SizeOf(SmallInt)); AData.Read(FTileID, SizeOf(SmallInt));
AData.Read(iX, SizeOf(Byte)); AData.Read(iX, SizeOf(Byte));
AData.Read(iY, SizeOf(Byte)); AData.Read(iY, SizeOf(Byte));
AData.Read(FZ, SizeOf(ShortInt)); AData.Read(FZ, SizeOf(ShortInt));
AData.Read(FHue, SizeOf(SmallInt)); AData.Read(FHue, SizeOf(SmallInt));
FX := ABlockX * 8 + iX; FX := ABlockX * 8 + iX;
FY := ABlockY * 8 + iY; FY := ABlockY * 8 + iY;
end; end;
InitOriginalState; InitOriginalState;
end; end;
constructor TStaticItem.Create(AOwner: TWorldBlock; AData: TStream); constructor TStaticItem.Create(AOwner: TWorldBlock; AData: TStream);
begin begin
Create(AOwner, AData, 0, 0); Create(AOwner, AData, 0, 0);
end; end;
function TStaticItem.Clone: TStaticItem; function TStaticItem.Clone: TStaticItem;
begin begin
Result := TStaticItem.Create(nil, nil); Result := TStaticItem.Create(nil, nil);
Result.FTileID := FTileID; Result.FTileID := FTileID;
Result.FX := FX; Result.FX := FX;
Result.FY := FY; Result.FY := FY;
Result.FZ := FZ; Result.FZ := FZ;
Result.FHue := FHue; Result.FHue := FHue;
end; end;
function TStaticItem.GetIdentifier: Integer; function TStaticItem.GetIdentifier: Integer;
begin begin
Result := 0 or (((FX mod 8) shl 28) and $F0000000) or (((FY mod 8) shl 24) and $0F000000) or ((Byte(FZ) shl 16) and $00FF0000) or (Word(FTileID) and $0000FFFF); Result := 0 or (((FX mod 8) shl 28) and $F0000000) or (((FY mod 8) shl 24) and $0F000000) or ((Byte(FZ) shl 16) and $00FF0000) or (Word(FTileID) and $0000FFFF);
end; end;
procedure TStaticItem.Write(AData: TStream); procedure TStaticItem.Write(AData: TStream);
var var
iX, iY: Byte; iX, iY: Byte;
begin begin
iX := FX mod 8; iX := FX mod 8;
iY := FY mod 8; iY := FY mod 8;
AData.Write(FTileID, SizeOf(SmallInt)); AData.Write(FTileID, SizeOf(SmallInt));
AData.Write(iX, SizeOf(Byte)); AData.Write(iX, SizeOf(Byte));
AData.Write(iY, SizeOf(Byte)); AData.Write(iY, SizeOf(Byte));
AData.Write(FZ, SizeOf(ShortInt)); AData.Write(FZ, SizeOf(ShortInt));
AData.Write(FHue, SizeOf(SmallInt)); AData.Write(FHue, SizeOf(SmallInt));
end; end;
function TStaticItem.GetSize: Integer; function TStaticItem.GetSize: Integer;
begin begin
Result := 7; Result := 7;
end; end;
function TStaticItem.HasChanged: Boolean; function TStaticItem.HasChanged: Boolean;
begin begin
Result := (FHue <> FOrgHue) or inherited HasChanged; Result := (FHue <> FOrgHue) or inherited HasChanged;
end; end;
procedure TStaticItem.InitOriginalState; procedure TStaticItem.InitOriginalState;
begin begin
FOrgHue := FHue; FOrgHue := FHue;
inherited InitOriginalState; inherited InitOriginalState;
end; end;
procedure TStaticItem.SetHue(AHue: Word); procedure TStaticItem.SetHue(AHue: Word);
begin begin
FHue := AHue; FHue := AHue;
DoChanged; DoChanged;
end; end;
{ TStaticBlock } { TStaticBlock }
constructor TStaticBlock.Create(AData: TStream; AIndex: TGenericIndex; AX, AY: Word); constructor TStaticBlock.Create(AData: TStream; AIndex: TGenericIndex; AX, AY: Word);
var var
i: Integer; i: Integer;
block: TMemoryStream; block: TMemoryStream;
begin begin
inherited Create; inherited Create;
FX := AX; FX := AX;
FY := AY; FY := AY;
FItems := TList.Create; FItems := TList.Create;
if assigned(AData) and (AIndex.Lookup <> LongInt($FFFFFFFF)) then if assigned(AData) and (AIndex.Lookup > 0) and (AIndex.Size > 0) then
begin begin
AData.Position := AIndex.Lookup; AData.Position := AIndex.Lookup;
block := TMemoryStream.Create; block := TMemoryStream.Create;
block.CopyFrom(AData, AIndex.Size); block.CopyFrom(AData, AIndex.Size);
block.Position := 0; block.Position := 0;
for i := 1 to (AIndex.Size div 7) do for i := 1 to (AIndex.Size div 7) do
FItems.Add(TStaticItem.Create(Self, block, AX, AY)); FItems.Add(TStaticItem.Create(Self, block, AX, AY));
block.Free; block.Free;
end; end;
end; end;
constructor TStaticBlock.Create(AData: TStream; AIndex: TGenericIndex); constructor TStaticBlock.Create(AData: TStream; AIndex: TGenericIndex);
begin begin
Create(AData, AIndex, 0, 0); Create(AData, AIndex, 0, 0);
end; end;
destructor TStaticBlock.Destroy; destructor TStaticBlock.Destroy;
var var
i: Integer; i: Integer;
begin begin
if Assigned(FItems) then if Assigned(FItems) then
begin begin
for i := 0 to FItems.Count - 1 do for i := 0 to FItems.Count - 1 do
if Assigned(FItems[i]) then if Assigned(FItems[i]) then
begin begin
TStaticItem(FItems[i]).Free; TStaticItem(FItems[i]).Free;
FItems[i] := nil; FItems[i] := nil;
end; end;
FItems.Free; FItems.Free;
FItems := nil; FItems := nil;
end; end;
inherited; inherited;
end; end;
function TStaticBlock.Clone: TStaticBlock; function TStaticBlock.Clone: TStaticBlock;
var var
i: Integer; i: Integer;
begin begin
Result := TStaticBlock.Create(nil, nil, FX, FY); Result := TStaticBlock.Create(nil, nil, FX, FY);
for i := 0 to FItems.Count - 1 do for i := 0 to FItems.Count - 1 do
Result.FItems.Add(TStaticItem(FItems.Items[i]).Clone); Result.FItems.Add(TStaticItem(FItems.Items[i]).Clone);
end; end;
function TStaticBlock.GetSize: Integer; function TStaticBlock.GetSize: Integer;
begin begin
Result := FItems.Count * 7; Result := FItems.Count * 7;
end; end;
procedure TStaticBlock.Write(AData: TStream); procedure TStaticBlock.Write(AData: TStream);
var var
i: Integer; i: Integer;
begin begin
for i := 0 to FItems.Count - 1 do for i := 0 to FItems.Count - 1 do
begin TStaticItem(FItems[i]).Write(AData);
TStaticItem(FItems[i]).Write(AData); end;
end;
end; procedure TStaticBlock.ReverseWrite(AData: TStream);
var
procedure TStaticBlock.ReverseWrite(AData: TStream); i: Integer;
var begin
i: Integer; for i := FItems.Count - 1 downto 0 do
begin begin
for i := FItems.Count - 1 downto 0 do TStaticItem(FItems[i]).Write(AData);
begin end;
TStaticItem(FItems[i]).Write(AData); end;
end;
end; procedure TStaticBlock.Sort;
var
procedure TStaticBlock.Sort; iMin, iMax: Integer;
var
iMin, iMax: Integer; procedure sift;
var
procedure sift; i, j: integer;
var begin
i, j: integer; i := iMin;
begin j := 2 * i;
i := iMin; FItems[0] := FItems[i];
j := 2 * i; while j <= iMax do
FItems[0] := FItems[i]; begin
while j <= iMax do if j < iMax then
begin if TStaticItem(FItems[j]).GetIdentifier < TStaticItem(FItems[j + 1]).GetIdentifier then inc(j);
if j < iMax then if TStaticItem(FItems[0]).GetIdentifier >= TStaticItem(FItems[j]).GetIdentifier then break;
if TStaticItem(FItems[j]).GetIdentifier < TStaticItem(FItems[j + 1]).GetIdentifier then inc(j); FItems[i] := FItems[j];
if TStaticItem(FItems[0]).GetIdentifier >= TStaticItem(FItems[j]).GetIdentifier then break; i := j;
FItems[i] := FItems[j]; j := 2 * i;
i := j; end;
j := 2 * i; FItems[i] := FItems[0];
end; end;
FItems[i] := FItems[0];
end; begin
if FItems.Count > 0 then
begin begin
if FItems.Count > 0 then iMax := FItems.Count;
begin iMin := iMax div 2 + 1;
iMax := FItems.Count; FItems.Insert(0, nil);
iMin := iMax div 2 + 1; while iMin > 1 do
FItems.Insert(0, nil); begin
while iMin > 1 do dec(iMin);
begin sift;
dec(iMin); end;
sift; while iMax > 1 do
end; begin
while iMax > 1 do FItems[0] := FItems[iMin];
begin FItems[iMin] := FItems[iMax];
FItems[0] := FItems[iMin]; FItems[iMax] := FItems[0];
FItems[iMin] := FItems[iMax]; dec(iMax);
FItems[iMax] := FItems[0]; sift;
dec(iMax); end;
sift; FItems.Delete(0);
end; end;
FItems.Delete(0); end;
end;
end; { TSeperatedStaticBlock }
{ TSeperatedStaticBlock } constructor TSeperatedStaticBlock.Create(AData: TStream; AIndex: TGenericIndex; AX, AY: Word);
var
constructor TSeperatedStaticBlock.Create(AData: TStream; AIndex: TGenericIndex; AX, AY: Word); i: Integer;
var item: TStaticItem;
i: Integer; block: TMemoryStream;
item: TStaticItem; begin
block: TMemoryStream; inherited Create;
begin FItems := TList.Create;
inherited Create;
FItems := TList.Create; FX := AX;
FY := AY;
FX := AX;
FY := AY; for i := 0 to 63 do
Cells[i] := TList.Create;
for i := 0 to 63 do
Cells[i] := TList.Create; if (AData <> nil) and (AIndex.Lookup > 0) and (AIndex.Size > 0) then
begin
if (AData <> nil) and (AIndex.Lookup <> LongInt($FFFFFFFF)) then AData.Position := AIndex.Lookup;
begin block := TMemoryStream.Create;
AData.Position := AIndex.Lookup; block.CopyFrom(AData, AIndex.Size);
block := TMemoryStream.Create; block.Position := 0;
block.CopyFrom(AData, AIndex.Size); for i := 1 to (AIndex.Size div 7) do
block.Position := 0; begin
for i := 1 to (AIndex.Size div 7) do item := TStaticItem.Create(Self, block, AX, AY);
begin Cells[(item.Y mod 8) * 8 + (item.X mod 8)].Add(item);
item := TStaticItem.Create(Self, block, AX, AY); end;
Cells[(item.Y mod 8) * 8 + (item.X mod 8)].Add(item); block.Free;
end; end;
block.Free; end;
end;
end; constructor TSeperatedStaticBlock.Create(AData: TStream; AIndex: TGenericIndex);
begin
constructor TSeperatedStaticBlock.Create(AData: TStream; AIndex: TGenericIndex); Create(AData, AIndex, 0, 0);
begin end;
Create(AData, AIndex, 0, 0);
end; destructor TSeperatedStaticBlock.Destroy;
var
destructor TSeperatedStaticBlock.Destroy; i, j: Integer;
var begin
i, j: Integer; if Assigned(FItems) then FreeAndNil(FItems);
begin for i := 0 to 63 do
if Assigned(FItems) then FreeAndNil(FItems); begin
for i := 0 to 63 do if Cells[i] <> nil then
begin begin
if Cells[i] <> nil then for j := 0 to Cells[i].Count - 1 do
begin begin
for j := 0 to Cells[i].Count - 1 do if Cells[i][j] <> nil then
begin begin
if Cells[i][j] <> nil then TStaticItem(Cells[i][j]).Free;
begin Cells[i][j] := nil;
TStaticItem(Cells[i][j]).Free; end;
Cells[i][j] := nil; end;
end; Cells[i].Free;
end; Cells[i] := nil;
Cells[i].Free; end;
Cells[i] := nil; end;
end; inherited Destroy;
end; end;
inherited Destroy;
end; function TSeperatedStaticBlock.Clone: TSeperatedStaticBlock;
var
function TSeperatedStaticBlock.Clone: TSeperatedStaticBlock; i, j: Integer;
var begin
i, j: Integer; Result := TSeperatedStaticBlock.Create(nil, nil, FX, FY);
begin
Result := TSeperatedStaticBlock.Create(nil, nil, FX, FY); for i := 0 to 63 do
for j := 0 to Cells[i].Count - 1 do
for i := 0 to 63 do Result.Cells[i].Add(TSeperatedStaticBlock(Cells[i].Items[j]).Clone);
for j := 0 to Cells[i].Count - 1 do end;
Result.Cells[i].Add(TSeperatedStaticBlock(Cells[i].Items[j]).Clone);
end; function TSeperatedStaticBlock.GetSize: Integer;
begin
function TSeperatedStaticBlock.GetSize: Integer; RefreshList;
begin Result := inherited GetSize;
RefreshList; end;
Result := inherited GetSize;
end; procedure TSeperatedStaticBlock.RefreshList;
var
procedure TSeperatedStaticBlock.RefreshList; i, j: Integer;
var begin
i, j: Integer; FItems.Clear;
begin for i := 0 to 63 do
FItems.Clear; begin
for i := 0 to 63 do if Cells[i] <> nil then
begin begin
if Cells[i] <> nil then for j := 0 to Cells[i].Count - 1 do
begin if Cells[i].Items[j] <> nil then
for j := 0 to Cells[i].Count - 1 do FItems.Add(Cells[i].Items[j]);
if Cells[i].Items[j] <> nil then end;
FItems.Add(Cells[i].Items[j]); end;
end; Sort;
end; end;
Sort;
end; end.
end.