- Added dynamic tiledata loading (everything after $4000 will be treated as static)

- Fixed server's TLandscape to validate statics and throw errors if no tiledata entry is found
This commit is contained in:
Andreas Schneider 2009-12-17 23:01:06 +01:00
parent b0b014f66a
commit bdc97b89f5
5 changed files with 2086 additions and 2054 deletions

View File

@ -1,156 +1,171 @@
(* (*
* 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 2009 Andreas Schneider * Portions Copyright 2009 Andreas Schneider
*) *)
unit UTileDataProvider; unit UTileDataProvider;
{$mode objfpc}{$H+} {$mode objfpc}{$H+}
interface interface
uses uses
SysUtils, Classes, UMulProvider, UMulBlock, UTiledata; SysUtils, Classes, UMulProvider, UMulBlock, UTiledata;
type type
TLandTileDataArray = array[$0..$3FFF] of TLandTileData; TLandTileDataArray = array[$0..$3FFF] of TLandTileData;
TStaticTileDataArray = array[$0..$3FFF] of TStaticTileData; TStaticTileDataArray = array of TStaticTileData;
{ TTiledataProvider } { TTiledataProvider }
TTiledataProvider = class(TMulProvider) TTiledataProvider = class(TMulProvider)
constructor Create(AData: TStream; AReadOnly: Boolean = False); overload; override; constructor Create(AData: TStream; AReadOnly: Boolean = False); overload; override;
constructor Create(AData: string; AReadOnly: Boolean = False); overload; override; constructor Create(AData: string; AReadOnly: Boolean = False); overload; override;
destructor Destroy; override; destructor Destroy; override;
protected protected
FLandTiles: TLandTileDataArray; FLandTiles: TLandTileDataArray;
FStaticTiles: TStaticTileDataArray; FStaticTiles: TStaticTileDataArray;
procedure InitArray; FStaticCount: Cardinal;
function CalculateOffset(AID: Integer): Integer; override; procedure InitArray;
function GetData(AID, AOffset: Integer): TMulBlock; override; function CalculateOffset(AID: Integer): Integer; override;
procedure SetData(AID, AOffset: Integer; ABlock: TMulBlock); override; function GetData(AID, AOffset: Integer): TMulBlock; override;
function GetTileData(AID: Integer): TTiledata; procedure SetData(AID, AOffset: Integer; ABlock: TMulBlock); override;
public function GetTileData(AID: Integer): TTiledata;
function GetBlock(AID: Integer): TMulBlock; override; public
property LandTiles: TLandTileDataArray read FLandTiles; function GetBlock(AID: Integer): TMulBlock; override;
property StaticTiles: TStaticTileDataArray read FStaticTiles; property LandTiles: TLandTileDataArray read FLandTiles;
property TileData[AID: Integer]: TTiledata read GetTileData; //all tiles, no cloning property StaticTiles: TStaticTileDataArray read FStaticTiles;
end; property TileData[AID: Integer]: TTiledata read GetTileData; //all tiles, no cloning
property StaticCount: Cardinal read FStaticCount;
implementation end;
{ TTiledataProvider } implementation
function TTiledataProvider.CalculateOffset(AID: Integer): Integer; uses
begin Logging;
Result := GetTileDataOffset(AID);
end; { TTiledataProvider }
constructor TTiledataProvider.Create(AData: TStream; AReadOnly: Boolean = False); function TTiledataProvider.CalculateOffset(AID: Integer): Integer;
begin begin
inherited; Result := GetTileDataOffset(AID);
InitArray; end;
end;
constructor TTiledataProvider.Create(AData: TStream; AReadOnly: Boolean = False);
constructor TTiledataProvider.Create(AData: string; AReadOnly: Boolean = False); begin
begin inherited;
inherited; InitArray;
InitArray; end;
end;
constructor TTiledataProvider.Create(AData: string; AReadOnly: Boolean = False);
destructor TTiledataProvider.Destroy; begin
var inherited;
i: Integer; InitArray;
begin end;
for i := $0 to $3FFF do
begin destructor TTiledataProvider.Destroy;
FreeAndNil(FLandTiles[i]); var
FreeAndNil(FStaticTiles[i]); i: Integer;
end; begin
for i := $0 to $3FFF do
inherited; FreeAndNil(FLandTiles[i]);
end; for i := 0 to FStaticCount - 1 do
FreeAndNil(FStaticTiles[i]);
function TTiledataProvider.GetBlock(AID: Integer): TMulBlock;
begin inherited Destroy;
Result := GetData(AID, 0); end;
end;
function TTiledataProvider.GetBlock(AID: Integer): TMulBlock;
function TTiledataProvider.GetData(AID, AOffset: Integer): TMulBlock; begin
begin Result := GetData(AID, 0);
if AID < $4000 then end;
Result := TMulBlock(FLandTiles[AID].Clone)
else function TTiledataProvider.GetData(AID, AOffset: Integer): TMulBlock;
Result := TMulBlock(FStaticTiles[AID - $4000].Clone); begin
Result.ID := AID; if AID < $4000 then
Result.OnChanged := @OnChanged; Result := TMulBlock(FLandTiles[AID].Clone)
Result.OnFinished := @OnFinished; else
end; Result := TMulBlock(FStaticTiles[AID - $4000].Clone);
Result.ID := AID;
procedure TTiledataProvider.InitArray; Result.OnChanged := @OnChanged;
var Result.OnFinished := @OnFinished;
i: Integer; end;
begin
for i := $0 to $3FFF do procedure TTiledataProvider.InitArray;
begin var
FData.Position := GetTileDataOffset(i); i: Integer;
FLandTiles[i] := TLandTileData.Create(FData); begin
end; FData.Position := 0;
Logger.Send([lcInfo], 'Loading $4000 LandTiledata Entries');
for i := $0 to $3FFF do for i := $0 to $3FFF do
begin begin
FData.Position := GetTileDataOffset($4000 + i); if i mod 32 = 0 then
FStaticTiles[i] := TStaticTileData.Create(FData); FData.Seek(4, soFromCurrent);
end; FLandTiles[i] := TLandTileData.Create(FData);
end; end;
procedure TTiledataProvider.SetData(AID, AOffset: Integer; FStaticCount := ((FData.Size - FData.Position) div StaticTileGroupSize) * 32;
ABlock: TMulBlock); Logger.Send([lcInfo], 'Loading $%x StaticTiledata Entries', [FStaticCount]);
begin SetLength(FStaticTiles, FStaticCount);
if AID < $4000 then
begin for i := 0 to FStaticCount - 1 do
FreeAndNil(FLandTiles[AID]); begin
FLandTiles[AID] := TLandTileData(ABlock.Clone); if i mod 32 = 0 then
end else FData.Seek(4, soFromCurrent);
begin FStaticTiles[i] := TStaticTileData.Create(FData);
FreeAndNil(FStaticTiles[AID - $4000]); end;
FStaticTiles[AID - $4000] := TStaticTileData(ABlock.Clone); end;
end;
procedure TTiledataProvider.SetData(AID, AOffset: Integer;
if not FReadOnly then ABlock: TMulBlock);
begin begin
FData.Position := AOffset; if AID >= $4000 + FStaticCount then
ABlock.Write(FData); Exit;
end;
end; if AID < $4000 then
begin
function TTiledataProvider.GetTileData(AID: Integer): TTiledata; FreeAndNil(FLandTiles[AID]);
begin FLandTiles[AID] := TLandTileData(ABlock.Clone);
if AID < $4000 then end else
Result := FLandTiles[AID] begin
else FreeAndNil(FStaticTiles[AID - $4000]);
Result := FStaticTiles[AID - $4000]; FStaticTiles[AID - $4000] := TStaticTileData(ABlock.Clone);
end; end;
end. if not FReadOnly then
begin
FData.Position := AOffset;
ABlock.Write(FData);
end;
end;
function TTiledataProvider.GetTileData(AID: Integer): TTiledata;
begin
if AID < $4000 then
Result := FLandTiles[AID]
else
Result := FStaticTiles[AID - $4000];
end;
end.

File diff suppressed because it is too large Load Diff

View File

@ -1,218 +1,218 @@
(* (*
* 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 UPacketHandlers; unit UPacketHandlers;
interface interface
uses uses
Classes, SysUtils, dzlib, math, UConfig, UNetState, UEnhancedMemoryStream, UEnums, Classes, SysUtils, dzlib, UConfig, UNetState, UEnhancedMemoryStream, UEnums,
ULinkedList, URegions; ULinkedList, URegions;
type type
TPacketProcessor = procedure(ABuffer: TEnhancedMemoryStream; ANetState: TNetState); TPacketProcessor = procedure(ABuffer: TEnhancedMemoryStream; ANetState: TNetState);
TPacketProcessorMethod = procedure(ABuffer: TEnhancedMemoryStream; ANetState: TNetState) of object; TPacketProcessorMethod = procedure(ABuffer: TEnhancedMemoryStream; ANetState: TNetState) of object;
{ TPacketHandler } { TPacketHandler }
TPacketHandler = class(TObject) TPacketHandler = class(TObject)
constructor Create(ALength: Cardinal; APacketProcessor: TPacketProcessor); overload; constructor Create(ALength: Cardinal; APacketProcessor: TPacketProcessor); overload;
constructor Create(ALength: Cardinal; APacketProcessorMethod: TPacketProcessorMethod); overload; constructor Create(ALength: Cardinal; APacketProcessorMethod: TPacketProcessorMethod); overload;
procedure Process(ABuffer: TEnhancedMemoryStream; ANetState: TNetState); procedure Process(ABuffer: TEnhancedMemoryStream; ANetState: TNetState);
protected protected
FLength: Cardinal; FLength: Cardinal;
FPacketProcessor: TPacketProcessor; FPacketProcessor: TPacketProcessor;
FPacketProcessorMethod: TPacketProcessorMethod; FPacketProcessorMethod: TPacketProcessorMethod;
published published
property PacketLength: Cardinal read FLength; property PacketLength: Cardinal read FLength;
end; end;
var var
PacketHandlers: array[0..$FF] of TPacketHandler; PacketHandlers: array[0..$FF] of TPacketHandler;
function ValidateAccess(ANetState: TNetState; ALevel: TAccessLevel): Boolean; overload; function ValidateAccess(ANetState: TNetState; ALevel: TAccessLevel): Boolean; overload;
function ValidateAccess(ANetState: TNetState; ALevel: TAccessLevel; AX, AY: Cardinal): Boolean; overload; function ValidateAccess(ANetState: TNetState; ALevel: TAccessLevel; AX, AY: Cardinal): Boolean; overload;
procedure RegisterPacketHandler(AID: Byte; APacketHandler: TPacketHandler); procedure RegisterPacketHandler(AID: Byte; APacketHandler: TPacketHandler);
implementation implementation
uses uses
UCEDServer, UPackets, UConnectionHandling, UAdminHandling, UClientHandling; UCEDServer, UPackets, UConnectionHandling, UAdminHandling, UClientHandling;
function ValidateAccess(ANetState: TNetState; ALevel: TAccessLevel): Boolean; function ValidateAccess(ANetState: TNetState; ALevel: TAccessLevel): Boolean;
begin begin
Result := (ANetState.Account <> nil) and (ANetState.Account.AccessLevel >= ALevel); Result := (ANetState.Account <> nil) and (ANetState.Account.AccessLevel >= ALevel);
end; end;
function ValidateAccess(ANetState: TNetState; ALevel: TAccessLevel; AX, AY: Cardinal): Boolean; function ValidateAccess(ANetState: TNetState; ALevel: TAccessLevel; AX, AY: Cardinal): Boolean;
var var
i,j: Word; i,j: Word;
region: TRegion; region: TRegion;
rect: TRect; rect: TRect;
begin begin
if not ValidateAccess(ANetState, ALevel) then Exit(False); if not ValidateAccess(ANetState, ALevel) then Exit(False);
if (ANetState.Account.Regions.Count = 0) or if (ANetState.Account.Regions.Count = 0) or
(ANetState.Account.AccessLevel >= alAdministrator) then Exit(True); //no restrictions (ANetState.Account.AccessLevel >= alAdministrator) then Exit(True); //no restrictions
Result := False; Result := False;
for i := 0 to ANetState.Account.Regions.Count - 1 do for i := 0 to ANetState.Account.Regions.Count - 1 do
begin begin
region := Config.Regions.Find(ANetState.Account.Regions[i]); region := Config.Regions.Find(ANetState.Account.Regions[i]);
if region <> nil then if region <> nil then
begin begin
for j := 0 to region.Areas.Count - 1 do for j := 0 to region.Areas.Count - 1 do
begin begin
rect := region.Areas.Rects[j]; rect := region.Areas.Rects[j];
if (AX >= rect.Left) and if (AX >= rect.Left) and
(AX < rect.Right) and (AX < rect.Right) and
(AY >= rect.Top) and (AY >= rect.Top) and
(AY < rect.Bottom) then (AY < rect.Bottom) then
Exit(True); Exit(True);
end; end;
end; end;
end; end;
end; end;
procedure RegisterPacketHandler(AID: Byte; APacketHandler: TPacketHandler); procedure RegisterPacketHandler(AID: Byte; APacketHandler: TPacketHandler);
begin begin
if Assigned(PacketHandlers[AID]) then FreeAndNil(PacketHandlers[AID]); if Assigned(PacketHandlers[AID]) then FreeAndNil(PacketHandlers[AID]);
PacketHandlers[AID] := APacketHandler; PacketHandlers[AID] := APacketHandler;
end; end;
{ TPacketHandler } { TPacketHandler }
constructor TPacketHandler.Create(ALength: Cardinal; APacketProcessor: TPacketProcessor); constructor TPacketHandler.Create(ALength: Cardinal; APacketProcessor: TPacketProcessor);
begin begin
inherited Create; inherited Create;
FLength := ALength; FLength := ALength;
FPacketProcessor := APacketProcessor; FPacketProcessor := APacketProcessor;
FPacketProcessorMethod := nil; FPacketProcessorMethod := nil;
end; end;
constructor TPacketHandler.Create(ALength: Cardinal; constructor TPacketHandler.Create(ALength: Cardinal;
APacketProcessorMethod: TPacketProcessorMethod); APacketProcessorMethod: TPacketProcessorMethod);
begin begin
inherited Create; inherited Create;
FLength := ALength; FLength := ALength;
FPacketProcessor := nil; FPacketProcessor := nil;
FPacketProcessorMethod := APacketProcessorMethod; FPacketProcessorMethod := APacketProcessorMethod;
end; end;
procedure TPacketHandler.Process(ABuffer: TEnhancedMemoryStream; ANetState: TNetState); procedure TPacketHandler.Process(ABuffer: TEnhancedMemoryStream; ANetState: TNetState);
begin begin
if Assigned(FPacketProcessor) then if Assigned(FPacketProcessor) then
FPacketProcessor(ABuffer, ANetState) FPacketProcessor(ABuffer, ANetState)
else if Assigned(FPacketProcessorMethod) then else if Assigned(FPacketProcessorMethod) then
FPacketProcessorMethod(ABuffer, ANetState); FPacketProcessorMethod(ABuffer, ANetState);
end; end;
procedure OnCompressedPacket(ABuffer: TEnhancedMemoryStream; ANetState: TNetState); procedure OnCompressedPacket(ABuffer: TEnhancedMemoryStream; ANetState: TNetState);
var var
uncompStream: TEnhancedMemoryStream; uncompStream: TEnhancedMemoryStream;
uncompBuffer: TDecompressionStream; uncompBuffer: TDecompressionStream;
targetSize: Cardinal; targetSize: Cardinal;
packetID: Byte; packetID: Byte;
begin begin
targetSize := ABuffer.ReadCardinal; targetSize := ABuffer.ReadCardinal;
uncompBuffer := TDecompressionStream.Create(ABuffer); uncompBuffer := TDecompressionStream.Create(ABuffer);
uncompStream := TEnhancedMemoryStream.Create; uncompStream := TEnhancedMemoryStream.Create;
try try
uncompStream.CopyFrom(uncompBuffer, targetSize); uncompStream.CopyFrom(uncompBuffer, targetSize);
uncompStream.Position := 0; uncompStream.Position := 0;
packetID := uncompStream.ReadByte; packetID := uncompStream.ReadByte;
if PacketHandlers[packetID] <> nil then if PacketHandlers[packetID] <> nil then
begin begin
if PacketHandlers[PacketID].PacketLength = 0 then if PacketHandlers[PacketID].PacketLength = 0 then
uncompStream.Position := uncompStream.Position + 4; uncompStream.Position := uncompStream.Position + 4;
uncompStream.Lock(uncompStream.Position, uncompStream.Size - uncompStream.Position); uncompStream.Lock(uncompStream.Position, uncompStream.Size - uncompStream.Position);
PacketHandlers[PacketID].Process(uncompStream, ANetState); PacketHandlers[PacketID].Process(uncompStream, ANetState);
uncompStream.Unlock; uncompStream.Unlock;
end else end else
begin begin
Writeln(TimeStamp, 'Dropping client due to unknown packet: ', ANetState.Socket.PeerAddress); Writeln(TimeStamp, 'Dropping client due to unknown packet: ', ANetState.Socket.PeerAddress);
ANetState.ReceiveQueue.Clear; ANetState.ReceiveQueue.Clear;
CEDServerInstance.Disconnect(ANetState.Socket); CEDServerInstance.Disconnect(ANetState.Socket);
end; end;
finally finally
if uncompBuffer <> nil then uncompBuffer.Free; if uncompBuffer <> nil then uncompBuffer.Free;
if uncompStream <> nil then uncompStream.Free; if uncompStream <> nil then uncompStream.Free;
end; end;
end; end;
procedure OnRequestBlocksPacket(ABuffer: TEnhancedMemoryStream; ANetState: TNetState); procedure OnRequestBlocksPacket(ABuffer: TEnhancedMemoryStream; ANetState: TNetState);
var var
coords: TBlockCoordsArray; coords: TBlockCoordsArray;
begin begin
if not ValidateAccess(ANetState, alView) then Exit; if not ValidateAccess(ANetState, alView) then Exit;
SetLength(coords, (ABuffer.Size - ABuffer.Position) div SizeOf(TBlockCoords)); SetLength(coords, (ABuffer.Size - ABuffer.Position) div SizeOf(TBlockCoords));
ABuffer.Read(coords[0], Length(coords) * SizeOf(TBlockCoords)); ABuffer.Read(coords[0], Length(coords) * SizeOf(TBlockCoords));
CEDServerInstance.SendPacket(ANetState, TCompressedPacket.Create(TBlockPacket.Create(coords, ANetState))); CEDServerInstance.SendPacket(ANetState, TCompressedPacket.Create(TBlockPacket.Create(coords, ANetState)));
end; end;
procedure OnFreeBlockPacket(ABuffer: TEnhancedMemoryStream; ANetState: TNetState); procedure OnFreeBlockPacket(ABuffer: TEnhancedMemoryStream; ANetState: TNetState);
var var
x, y: Word; x, y: Word;
blockSubscriptions: TLinkedList; blockSubscriptions: TLinkedList;
begin begin
if not ValidateAccess(ANetState, alView) then Exit; if not ValidateAccess(ANetState, alView) then Exit;
x := ABuffer.ReadWord; x := ABuffer.ReadWord;
y := ABuffer.ReadWord; y := ABuffer.ReadWord;
blockSubscriptions := CEDServerInstance.Landscape.BlockSubscriptions[X, Y]; blockSubscriptions := CEDServerInstance.Landscape.BlockSubscriptions[X, Y];
if blockSubscriptions <> nil then if blockSubscriptions <> nil then
begin begin
blockSubscriptions.Delete(ANetState); blockSubscriptions.Delete(ANetState);
ANetState.Subscriptions.Remove(blockSubscriptions); ANetState.Subscriptions.Remove(blockSubscriptions);
end; end;
end; end;
procedure OnNoOpPacket(ABuffer: TEnhancedMemoryStream; ANetState: TNetState); procedure OnNoOpPacket(ABuffer: TEnhancedMemoryStream; ANetState: TNetState);
begin begin
//no operation //no operation
end; end;
{$WARNINGS OFF} {$WARNINGS OFF}
var var
i: Integer; i: Integer;
initialization initialization
for i := 0 to $FF do for i := 0 to $FF do
PacketHandlers[i] := nil; PacketHandlers[i] := nil;
PacketHandlers[$01] := TPacketHandler.Create(0, @OnCompressedPacket); PacketHandlers[$01] := TPacketHandler.Create(0, @OnCompressedPacket);
PacketHandlers[$02] := TPacketHandler.Create(0, @OnConnectionHandlerPacket); PacketHandlers[$02] := TPacketHandler.Create(0, @OnConnectionHandlerPacket);
PacketHandlers[$03] := TPacketHandler.Create(0, @OnAdminHandlerPacket); PacketHandlers[$03] := TPacketHandler.Create(0, @OnAdminHandlerPacket);
PacketHandlers[$04] := TPacketHandler.Create(0, @OnRequestBlocksPacket); PacketHandlers[$04] := TPacketHandler.Create(0, @OnRequestBlocksPacket);
PacketHandlers[$05] := TPacketHandler.Create(5, @OnFreeBlockPacket); PacketHandlers[$05] := TPacketHandler.Create(5, @OnFreeBlockPacket);
//$06-$0B handled by landscape //$06-$0B handled by landscape
PacketHandlers[$0C] := TPacketHandler.Create(0, @OnClientHandlerPacket); PacketHandlers[$0C] := TPacketHandler.Create(0, @OnClientHandlerPacket);
//$0D handled by radarmap //$0D handled by radarmap
//$0E handled by landscape //$0E handled by landscape
PacketHandlers[$FF] := TPacketHandler.Create(1, @OnNoOpPacket); PacketHandlers[$FF] := TPacketHandler.Create(1, @OnNoOpPacket);
finalization finalization
for i := 0 to $FF do for i := 0 to $FF do
if PacketHandlers[i] <> nil then if PacketHandlers[i] <> nil then
PacketHandlers[i].Free; PacketHandlers[i].Free;
{$WARNINGS ON} {$WARNINGS ON}
end. end.

View File

@ -1,147 +1,148 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<CONFIG> <CONFIG>
<ProjectOptions> <ProjectOptions>
<Version Value="7"/> <Version Value="7"/>
<General> <General>
<Flags> <Flags>
<LRSInOutputDirectory Value="False"/> <LRSInOutputDirectory Value="False"/>
</Flags> </Flags>
<SessionStorage Value="InProjectDir"/> <SessionStorage Value="InProjectDir"/>
<MainUnit Value="0"/> <MainUnit Value="0"/>
<TargetFileExt Value=".exe"/> <TargetFileExt Value=".exe"/>
</General> </General>
<VersionInfo> <VersionInfo>
<ProjectVersion Value=""/> <ProjectVersion Value=""/>
</VersionInfo> </VersionInfo>
<PublishOptions> <PublishOptions>
<Version Value="2"/> <Version Value="2"/>
<IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/> <IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/>
<ExcludeFileFilter Value="*.(bak|ppu|ppw|o|so);*~;backup"/> <ExcludeFileFilter Value="*.(bak|ppu|ppw|o|so);*~;backup"/>
</PublishOptions> </PublishOptions>
<RunParams> <RunParams>
<local> <local>
<FormatVersion Value="1"/> <FormatVersion Value="1"/>
<LaunchingApplication PathPlusParams="/usr/bin/xterm -T 'Lazarus Run Output' -e $(LazarusDir)/tools/runwait.sh $(TargetCmdLine)"/> <LaunchingApplication PathPlusParams="/usr/bin/xterm -T 'Lazarus Run Output' -e $(LazarusDir)/tools/runwait.sh $(TargetCmdLine)"/>
</local> </local>
</RunParams> </RunParams>
<RequiredPackages Count="2"> <RequiredPackages Count="2">
<Item1> <Item1>
<PackageName Value="multiloglaz"/> <PackageName Value="multiloglaz"/>
</Item1> </Item1>
<Item2> <Item2>
<PackageName Value="lnetbase"/> <PackageName Value="lnetbase"/>
</Item2> </Item2>
</RequiredPackages> </RequiredPackages>
<Units Count="15"> <Units Count="15">
<Unit0> <Unit0>
<Filename Value="cedserver.lpr"/> <Filename Value="cedserver.lpr"/>
<IsPartOfProject Value="True"/> <IsPartOfProject Value="True"/>
<UnitName Value="cedserver"/> <UnitName Value="cedserver"/>
</Unit0> </Unit0>
<Unit1> <Unit1>
<Filename Value="UConfig.pas"/> <Filename Value="UConfig.pas"/>
<IsPartOfProject Value="True"/> <IsPartOfProject Value="True"/>
<UnitName Value="UConfig"/> <UnitName Value="UConfig"/>
</Unit1> </Unit1>
<Unit2> <Unit2>
<Filename Value="UCEDServer.pas"/> <Filename Value="UCEDServer.pas"/>
<IsPartOfProject Value="True"/> <IsPartOfProject Value="True"/>
<UnitName Value="UCEDServer"/> <UnitName Value="UCEDServer"/>
</Unit2> </Unit2>
<Unit3> <Unit3>
<Filename Value="UNetState.pas"/> <Filename Value="UNetState.pas"/>
<IsPartOfProject Value="True"/> <IsPartOfProject Value="True"/>
<UnitName Value="UNetState"/> <UnitName Value="UNetState"/>
</Unit3> </Unit3>
<Unit4> <Unit4>
<Filename Value="UAccount.pas"/> <Filename Value="UAccount.pas"/>
<IsPartOfProject Value="True"/> <IsPartOfProject Value="True"/>
<UnitName Value="UAccount"/> <UnitName Value="UAccount"/>
</Unit4> </Unit4>
<Unit5> <Unit5>
<Filename Value="UConnectionHandling.pas"/> <Filename Value="UConnectionHandling.pas"/>
<IsPartOfProject Value="True"/> <IsPartOfProject Value="True"/>
<UnitName Value="UConnectionHandling"/> <UnitName Value="UConnectionHandling"/>
</Unit5> </Unit5>
<Unit6> <Unit6>
<Filename Value="URadarMap.pas"/> <Filename Value="URadarMap.pas"/>
<IsPartOfProject Value="True"/> <IsPartOfProject Value="True"/>
<UnitName Value="URadarMap"/> <UnitName Value="URadarMap"/>
</Unit6> </Unit6>
<Unit7> <Unit7>
<Filename Value="ULargeScaleOperations.pas"/> <Filename Value="ULargeScaleOperations.pas"/>
<IsPartOfProject Value="True"/> <IsPartOfProject Value="True"/>
<UnitName Value="ULargeScaleOperations"/> <UnitName Value="ULargeScaleOperations"/>
</Unit7> </Unit7>
<Unit8> <Unit8>
<Filename Value="../UInterfaces.pas"/> <Filename Value="../UInterfaces.pas"/>
<IsPartOfProject Value="True"/> <IsPartOfProject Value="True"/>
<UnitName Value="UInterfaces"/> <UnitName Value="UInterfaces"/>
</Unit8> </Unit8>
<Unit9> <Unit9>
<Filename Value="UPacketHandlers.pas"/> <Filename Value="UPacketHandlers.pas"/>
<IsPartOfProject Value="True"/> <IsPartOfProject Value="True"/>
<UnitName Value="UPacketHandlers"/> <UnitName Value="UPacketHandlers"/>
</Unit9> </Unit9>
<Unit10> <Unit10>
<Filename Value="ULandscape.pas"/> <Filename Value="ULandscape.pas"/>
<IsPartOfProject Value="True"/> <IsPartOfProject Value="True"/>
<UnitName Value="ULandscape"/> <UnitName Value="ULandscape"/>
</Unit10> </Unit10>
<Unit11> <Unit11>
<Filename Value="UPackets.pas"/> <Filename Value="UPackets.pas"/>
<IsPartOfProject Value="True"/> <IsPartOfProject Value="True"/>
<UnitName Value="UPackets"/> <UnitName Value="UPackets"/>
</Unit11> </Unit11>
<Unit12> <Unit12>
<Filename Value="UAdminHandling.pas"/> <Filename Value="UAdminHandling.pas"/>
<IsPartOfProject Value="True"/> <IsPartOfProject Value="True"/>
<UnitName Value="UAdminHandling"/> <UnitName Value="UAdminHandling"/>
</Unit12> </Unit12>
<Unit13> <Unit13>
<Filename Value="UClientHandling.pas"/> <Filename Value="UClientHandling.pas"/>
<IsPartOfProject Value="True"/> <IsPartOfProject Value="True"/>
<UnitName Value="UClientHandling"/> <UnitName Value="UClientHandling"/>
</Unit13> </Unit13>
<Unit14> <Unit14>
<Filename Value="../UOLib/UStatics.pas"/> <Filename Value="../UOLib/UStatics.pas"/>
<IsPartOfProject Value="True"/> <IsPartOfProject Value="True"/>
<UnitName Value="UStatics"/> <UnitName Value="UStatics"/>
</Unit14> </Unit14>
</Units> </Units>
</ProjectOptions> </ProjectOptions>
<CompilerOptions> <CompilerOptions>
<Version Value="8"/> <Version Value="8"/>
<Target> <Target>
<Filename Value="../bin/cedserver"/> <Filename Value="../bin/cedserver"/>
</Target> </Target>
<SearchPaths> <SearchPaths>
<IncludeFiles Value="../;../Imaging/"/> <IncludeFiles Value="../;../Imaging/"/>
<OtherUnitFiles Value="../;../UOLib/;../MulProvider/;../Imaging/ZLib/"/> <OtherUnitFiles Value="../;../UOLib/;../MulProvider/;../Imaging/ZLib/"/>
<UnitOutputDirectory Value="../obj"/> <UnitOutputDirectory Value="../obj"/>
<SrcPath Value="../;../UOLib/;../MulProvider/;../Imaging/ZLib/"/> <SrcPath Value="../;../UOLib/;../MulProvider/;../Imaging/ZLib/"/>
</SearchPaths> </SearchPaths>
<Parsing> <Parsing>
<SyntaxOptions> <SyntaxOptions>
<CStyleOperator Value="False"/> <CStyleOperator Value="False"/>
</SyntaxOptions> </SyntaxOptions>
</Parsing> </Parsing>
<CodeGeneration> <CodeGeneration>
<SmartLinkUnit Value="True"/> <SmartLinkUnit Value="True"/>
<Optimizations> <Optimizations>
<OptimizationLevel Value="0"/> <OptimizationLevel Value="0"/>
</Optimizations> </Optimizations>
</CodeGeneration> </CodeGeneration>
<Linking> <Linking>
<Debugging> <Debugging>
<GenerateDebugInfo Value="True"/> <GenerateDebugInfo Value="True"/>
<UseHeaptrc Value="True"/> <UseHeaptrc Value="True"/>
</Debugging> </Debugging>
<LinkSmart Value="True"/> <LinkSmart Value="True"/>
</Linking> </Linking>
<Other> <Other>
<CustomOptions Value="-FE../bin/ "/> <CustomOptions Value="-FE../bin/
<CompilerPath Value="$(CompPath)"/> "/>
</Other> <CompilerPath Value="$(CompPath)"/>
</CompilerOptions> </Other>
</CONFIG> </CompilerOptions>
</CONFIG>

View File

@ -1,376 +1,376 @@
(* (*
* 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 2009 Andreas Schneider * Portions Copyright 2009 Andreas Schneider
*) *)
unit UTiledata; unit UTiledata;
{$mode objfpc}{$H+} {$mode objfpc}{$H+}
interface interface
uses uses
Classes, SysUtils, UMulBlock; Classes, SysUtils, UMulBlock;
const const
LandTileDataSize = 26; LandTileDataSize = 26;
LandTileGroupSize = 4 + 32 * LandTileDataSize; LandTileGroupSize = 4 + 32 * LandTileDataSize;
StaticTileDataSize = 37; StaticTileDataSize = 37;
StaticTileGroupSize = 4 + 32 * StaticTileDataSize; StaticTileGroupSize = 4 + 32 * StaticTileDataSize;
type type
TTileDataFlag = (tdfBackground, tdfWeapon, tdfTransparent, tdfTranslucent, TTileDataFlag = (tdfBackground, tdfWeapon, tdfTransparent, tdfTranslucent,
tdfWall, tdfDamaging, tdfImpassable, tdfWet, tdfUnknown1, tdfWall, tdfDamaging, tdfImpassable, tdfWet, tdfUnknown1,
tdfSurface, tdfBridge, tdfGeneric, tdfWindow, tdfNoShoot, tdfSurface, tdfBridge, tdfGeneric, tdfWindow, tdfNoShoot,
tdfArticleA, tdfArticleAn, tdfInternal, tdfFoliage, tdfArticleA, tdfArticleAn, tdfInternal, tdfFoliage,
tdfPartialHue, tdfUnknown2, tdfMap, tdfContainer, tdfPartialHue, tdfUnknown2, tdfMap, tdfContainer,
tdfWearable, tdfLightSource, tdfAnimation, tdfNoDiagonal, tdfWearable, tdfLightSource, tdfAnimation, tdfNoDiagonal,
tdfArtUsed, tdfArmor, tdfRoof, tdfDoor, tdfStairBack, tdfArtUsed, tdfArmor, tdfRoof, tdfDoor, tdfStairBack,
tdfStairRight); tdfStairRight);
TTileDataFlags = set of TTileDataFlag; TTileDataFlags = set of TTileDataFlag;
{ TTiledata } { TTiledata }
TTiledata = class(TMulBlock) TTiledata = class(TMulBlock)
protected protected
FFlags: TTileDataFlags; FFlags: TTileDataFlags;
FTileName: string; FTileName: string;
public public
property Flags: TTileDataFlags read FFlags write FFlags; property Flags: TTileDataFlags read FFlags write FFlags;
property TileName: string read FTileName write FTileName; property TileName: string read FTileName write FTileName;
end; end;
{ TLandTiledata } { TLandTiledata }
TLandTiledata = class(TTiledata) TLandTiledata = class(TTiledata)
constructor Create(AData: TStream); constructor Create(AData: TStream);
destructor Destroy; override; destructor Destroy; override;
function Clone: TLandTiledata; override; function Clone: TLandTiledata; override;
function GetSize: Integer; override; function GetSize: Integer; override;
procedure Write(AData: TStream); override; procedure Write(AData: TStream); override;
protected protected
FTextureID: Word; FTextureID: Word;
public public
property TextureID: Word read FTextureID write FTextureID; property TextureID: Word read FTextureID write FTextureID;
end; end;
{ TStaticTiledata } { TStaticTiledata }
TStaticTiledata = class(TTiledata) TStaticTiledata = class(TTiledata)
constructor Create(AData: TStream); constructor Create(AData: TStream);
destructor Destroy; override; destructor Destroy; override;
function Clone: TStaticTiledata; override; function Clone: TStaticTiledata; override;
function GetSize: Integer; override; function GetSize: Integer; override;
procedure Write(AData: TStream); override; procedure Write(AData: TStream); override;
protected protected
FWeight: Byte; FWeight: Byte;
FQuality: Byte; FQuality: Byte;
FUnknown1: Word; FUnknown1: Word;
FUnknown2: Byte; FUnknown2: Byte;
FQuantity: Byte; FQuantity: Byte;
FAnimID: Word; FAnimID: Word;
FUnknown3: Byte; FUnknown3: Byte;
FHue: Byte; FHue: Byte;
FUnknown4: Word; FUnknown4: Word;
FHeight: Byte; FHeight: Byte;
public public
property Weight: Byte read FWeight write FWeight; property Weight: Byte read FWeight write FWeight;
property Quality: Byte read FQuality write FQuality; property Quality: Byte read FQuality write FQuality;
property Unknown1: Word read FUnknown1 write FUnknown1; property Unknown1: Word read FUnknown1 write FUnknown1;
property Unknown2: Byte read FUnknown2 write FUnknown2; property Unknown2: Byte read FUnknown2 write FUnknown2;
property Quantity: Byte read FQuantity write FQuantity; property Quantity: Byte read FQuantity write FQuantity;
property AnimID: Word read FAnimID write FAnimID; property AnimID: Word read FAnimID write FAnimID;
property Unknown3: Byte read FUnknown3 write FUnknown3; property Unknown3: Byte read FUnknown3 write FUnknown3;
property Hue: Byte read FHue write FHue; property Hue: Byte read FHue write FHue;
property Unknown4: Word read FUnknown4 write FUnknown4; property Unknown4: Word read FUnknown4 write FUnknown4;
property Height: Byte read FHeight write FHeight; property Height: Byte read FHeight write FHeight;
end; end;
{ TLandTileGroup } { TLandTileGroup }
TLandTileGroup = class(TMulBlock) TLandTileGroup = class(TMulBlock)
constructor Create(AData: TStream); constructor Create(AData: TStream);
destructor Destroy; override; destructor Destroy; override;
function Clone: TLandTileGroup; override; function Clone: TLandTileGroup; override;
function GetSize: Integer; override; function GetSize: Integer; override;
procedure Write(AData: TStream); override; procedure Write(AData: TStream); override;
protected protected
FUnknown: LongInt; FUnknown: LongInt;
public public
LandTileData: array[0..31] of TLandTiledata; LandTileData: array[0..31] of TLandTiledata;
property Unknown: LongInt read FUnknown write FUnknown; property Unknown: LongInt read FUnknown write FUnknown;
end; end;
{ TStaticTileGroup } { TStaticTileGroup }
TStaticTileGroup = class(TMulBlock) TStaticTileGroup = class(TMulBlock)
constructor Create(AData: TStream); constructor Create(AData: TStream);
destructor Destroy; override; destructor Destroy; override;
function Clone: TStaticTileGroup; override; function Clone: TStaticTileGroup; override;
function GetSize: Integer; override; function GetSize: Integer; override;
procedure Write(AData: TStream); override; procedure Write(AData: TStream); override;
protected protected
FUnknown: LongInt; FUnknown: LongInt;
public public
StaticTileData: array[0..31] of TStaticTiledata; StaticTileData: array[0..31] of TStaticTiledata;
property Unknown: LongInt read FUnknown write FUnknown; property Unknown: LongInt read FUnknown write FUnknown;
end; end;
function GetTileDataOffset(ABlock: Integer): Integer; function GetTileDataOffset(ABlock: Integer): Integer;
implementation implementation
function GetTileDataOffset(ABlock: Integer): Integer; function GetTileDataOffset(ABlock: Integer): Integer;
var var
group, tile: Integer; group, tile: Integer;
begin begin
if ABlock > $3FFF then if ABlock > $3FFF then
begin begin
ABlock := ABlock - $4000; ABlock := ABlock - $4000;
group := ABlock div 32; group := ABlock div 32;
tile := ABlock mod 32; tile := ABlock mod 32;
Result := 512 * LandTileGroupSize + group * StaticTileGroupSize + 4 Result := 512 * LandTileGroupSize + group * StaticTileGroupSize + 4
+ tile * StaticTileDataSize; + tile * StaticTileDataSize;
end else end else
begin begin
group := ABlock div 32; group := ABlock div 32;
tile := ABlock mod 32; tile := ABlock mod 32;
Result := group * LandTileGroupSize + 4 + tile * LandTileDataSize; Result := group * LandTileGroupSize + 4 + tile * LandTileDataSize;
end; end;
end; end;
{ TLandTiledata } { TLandTiledata }
constructor TLandTiledata.Create(AData: TStream); constructor TLandTiledata.Create(AData: TStream);
begin begin
SetLength(FTileName, 20); SetLength(FTileName, 20);
if assigned(AData) then if assigned(AData) then
begin begin
AData.Read(FFlags, SizeOf(LongWord)); AData.Read(FFlags, SizeOf(LongWord));
AData.Read(FTextureID, SizeOf(Word)); AData.Read(FTextureID, SizeOf(Word));
AData.Read(PChar(FTileName)^, 20); AData.Read(PChar(FTileName)^, 20);
end; end;
FTileName := Trim(FTileName); FTileName := Trim(FTileName);
end; end;
destructor TLandTiledata.Destroy; destructor TLandTiledata.Destroy;
begin begin
SetLength(FTileName, 0); SetLength(FTileName, 0);
inherited; inherited;
end; end;
function TLandTiledata.Clone: TLandTiledata; function TLandTiledata.Clone: TLandTiledata;
begin begin
Result := TLandTiledata.Create(nil); Result := TLandTiledata.Create(nil);
Result.FFlags := FFlags; Result.FFlags := FFlags;
Result.FTextureID := FTextureID; Result.FTextureID := FTextureID;
Result.FTileName := FTileName; Result.FTileName := FTileName;
end; end;
procedure TLandTiledata.Write(AData: TStream); procedure TLandTiledata.Write(AData: TStream);
var var
i: Integer; i: Integer;
begin begin
if Length(FTileName) < 20 then if Length(FTileName) < 20 then
for i := Length(FTileName) to 20 do for i := Length(FTileName) to 20 do
FTileName := FTileName + #0; FTileName := FTileName + #0;
AData.Write(FFlags, SizeOf(LongWord)); AData.Write(FFlags, SizeOf(LongWord));
AData.Write(FTextureID, SizeOf(Word)); AData.Write(FTextureID, SizeOf(Word));
AData.Write(PChar(FTileName)^, 20); AData.Write(PChar(FTileName)^, 20);
end; end;
function TLandTiledata.GetSize: Integer; function TLandTiledata.GetSize: Integer;
begin begin
GetSize := LandTileDataSize; GetSize := LandTileDataSize;
end; end;
{ TStaticTiledata} { TStaticTiledata}
constructor TStaticTiledata.Create(AData: TStream); constructor TStaticTiledata.Create(AData: TStream);
begin begin
SetLength(FTileName, 20); SetLength(FTileName, 20);
if assigned(AData) then if AData <> nil then
begin begin
AData.Read(FFlags, SizeOf(LongWord)); AData.Read(FFlags, SizeOf(LongWord));
AData.Read(FWeight, SizeOf(Byte)); AData.Read(FWeight, SizeOf(Byte));
AData.Read(FQuality, SizeOf(Byte)); AData.Read(FQuality, SizeOf(Byte));
AData.Read(FUnknown1, SizeOf(Word)); AData.Read(FUnknown1, SizeOf(Word));
AData.Read(FUnknown2, SizeOf(Byte)); AData.Read(FUnknown2, SizeOf(Byte));
AData.Read(FQuantity, SizeOf(Byte)); AData.Read(FQuantity, SizeOf(Byte));
AData.Read(FAnimID, SizeOf(Word)); AData.Read(FAnimID, SizeOf(Word));
AData.Read(FUnknown3, SizeOf(Byte)); AData.Read(FUnknown3, SizeOf(Byte));
AData.Read(FHue, SizeOf(Byte)); AData.Read(FHue, SizeOf(Byte));
AData.Read(FUnknown4, SizeOf(Word)); AData.Read(FUnknown4, SizeOf(Word));
AData.Read(FHeight, SizeOf(Byte)); AData.Read(FHeight, SizeOf(Byte));
AData.Read(PChar(FTileName)^, 20); AData.Read(PChar(FTileName)^, 20);
end; end;
FTileName := Trim(FTileName); FTileName := Trim(FTileName);
end; end;
destructor TStaticTiledata.Destroy; destructor TStaticTiledata.Destroy;
begin begin
SetLength(FTileName, 0); SetLength(FTileName, 0);
inherited; inherited;
end; end;
function TStaticTiledata.Clone: TStaticTiledata; function TStaticTiledata.Clone: TStaticTiledata;
begin begin
Result := TStaticTiledata.Create(nil); Result := TStaticTiledata.Create(nil);
Result.FFlags := FFlags; Result.FFlags := FFlags;
Result.FWeight := FWeight; Result.FWeight := FWeight;
Result.FQuality := FQuality; Result.FQuality := FQuality;
Result.FUnknown1 := FUnknown1; Result.FUnknown1 := FUnknown1;
Result.FUnknown2 := FUnknown2; Result.FUnknown2 := FUnknown2;
Result.FQuantity := FQuantity; Result.FQuantity := FQuantity;
Result.FAnimID := FAnimID; Result.FAnimID := FAnimID;
Result.FUnknown3 := FUnknown3; Result.FUnknown3 := FUnknown3;
Result.FHue := FHue; Result.FHue := FHue;
Result.FUnknown4 := FUnknown4; Result.FUnknown4 := FUnknown4;
Result.FHeight := FHeight; Result.FHeight := FHeight;
Result.FTileName := FTileName; Result.FTileName := FTileName;
end; end;
procedure TStaticTiledata.Write(AData: TStream); procedure TStaticTiledata.Write(AData: TStream);
var var
i: Integer; i: Integer;
begin begin
if Length(FTileName) < 20 then if Length(FTileName) < 20 then
for i := Length(FTileName) to 20 do for i := Length(FTileName) to 20 do
FTileName := FTileName + #0; FTileName := FTileName + #0;
AData.Write(FFlags, SizeOf(LongWord)); AData.Write(FFlags, SizeOf(LongWord));
AData.Write(FWeight, SizeOf(Byte)); AData.Write(FWeight, SizeOf(Byte));
AData.Write(FQuality, SizeOf(Byte)); AData.Write(FQuality, SizeOf(Byte));
AData.Write(FUnknown1, SizeOf(Word)); AData.Write(FUnknown1, SizeOf(Word));
AData.Write(FUnknown2, SizeOf(Byte)); AData.Write(FUnknown2, SizeOf(Byte));
AData.Write(FQuantity, SizeOf(Byte)); AData.Write(FQuantity, SizeOf(Byte));
AData.Write(FAnimID, SizeOf(Word)); AData.Write(FAnimID, SizeOf(Word));
AData.Write(FUnknown3, SizeOf(Byte)); AData.Write(FUnknown3, SizeOf(Byte));
AData.Write(FHue, SizeOf(Byte)); AData.Write(FHue, SizeOf(Byte));
AData.Write(FUnknown4, SizeOf(Word)); AData.Write(FUnknown4, SizeOf(Word));
AData.Write(FHeight, SizeOf(Byte)); AData.Write(FHeight, SizeOf(Byte));
AData.Write(PChar(FTileName)^, 20); AData.Write(PChar(FTileName)^, 20);
end; end;
function TStaticTiledata.GetSize: Integer; function TStaticTiledata.GetSize: Integer;
begin begin
GetSize := StaticTileDataSize; GetSize := StaticTileDataSize;
end; end;
{ TLandTileGroup } { TLandTileGroup }
constructor TLandTileGroup.Create(AData: TStream); constructor TLandTileGroup.Create(AData: TStream);
var var
i: Integer; i: Integer;
begin begin
if assigned(AData) then if assigned(AData) then
begin begin
AData.Read(FUnknown, SizeOf(LongInt)); AData.Read(FUnknown, SizeOf(LongInt));
end; end;
for i := 0 to 31 do for i := 0 to 31 do
LandTileData[i] := TLandTiledata.Create(AData); LandTileData[i] := TLandTiledata.Create(AData);
end; end;
destructor TLandTileGroup.Destroy; destructor TLandTileGroup.Destroy;
var var
i: Integer; i: Integer;
begin begin
for i := 0 to 31 do for i := 0 to 31 do
LandTileData[i].Free; LandTileData[i].Free;
inherited; inherited;
end; end;
function TLandTileGroup.Clone: TLandTileGroup; function TLandTileGroup.Clone: TLandTileGroup;
var var
i: Integer; i: Integer;
begin begin
Result := TLandTileGroup.Create(nil); Result := TLandTileGroup.Create(nil);
Result.FUnknown := FUnknown; Result.FUnknown := FUnknown;
for i := 0 to 31 do for i := 0 to 31 do
Result.LandTileData[i] := LandTileData[i].Clone; Result.LandTileData[i] := LandTileData[i].Clone;
end; end;
procedure TLandTileGroup.Write(AData: TStream); procedure TLandTileGroup.Write(AData: TStream);
var var
i: Integer; i: Integer;
begin begin
AData.Write(FUnknown, SizeOf(LongInt)); AData.Write(FUnknown, SizeOf(LongInt));
for i := 0 to 31 do for i := 0 to 31 do
LandTileData[i].Write(AData); LandTileData[i].Write(AData);
end; end;
function TLandTileGroup.GetSize: Integer; function TLandTileGroup.GetSize: Integer;
begin begin
GetSize := LandTileGroupSize; GetSize := LandTileGroupSize;
end; end;
{ TStaticTileGroup } { TStaticTileGroup }
constructor TStaticTileGroup.Create(AData: TStream); constructor TStaticTileGroup.Create(AData: TStream);
var var
i: Integer; i: Integer;
begin begin
if assigned(AData) then if assigned(AData) then
begin begin
AData.Read(FUnknown, SizeOf(LongInt)); AData.Read(FUnknown, SizeOf(LongInt));
end; end;
for i := 0 to 31 do for i := 0 to 31 do
StaticTileData[i] := TStaticTiledata.Create(AData); StaticTileData[i] := TStaticTiledata.Create(AData);
end; end;
destructor TStaticTileGroup.Destroy; destructor TStaticTileGroup.Destroy;
var var
i: Integer; i: Integer;
begin begin
for i := 0 to 31 do for i := 0 to 31 do
StaticTileData[i].Free; StaticTileData[i].Free;
inherited; inherited;
end; end;
function TStaticTileGroup.Clone: TStaticTileGroup; function TStaticTileGroup.Clone: TStaticTileGroup;
var var
i: Integer; i: Integer;
begin begin
Result := TStaticTileGroup.Create(nil); Result := TStaticTileGroup.Create(nil);
Result.FUnknown := FUnknown; Result.FUnknown := FUnknown;
for i := 0 to 31 do for i := 0 to 31 do
Result.StaticTileData[i] := StaticTileData[i].Clone; Result.StaticTileData[i] := StaticTileData[i].Clone;
end; end;
procedure TStaticTileGroup.Write(AData: TStream); procedure TStaticTileGroup.Write(AData: TStream);
var var
i: Integer; i: Integer;
begin begin
AData.Write(FUnknown, SizeOf(LongInt)); AData.Write(FUnknown, SizeOf(LongInt));
for i := 0 to 31 do for i := 0 to 31 do
StaticTileData[i].Write(AData); StaticTileData[i].Write(AData);
end; end;
function TStaticTileGroup.GetSize: Integer; function TStaticTileGroup.GetSize: Integer;
begin begin
GetSize := StaticTileGroupSize; GetSize := StaticTileGroupSize;
end; end;
end. end.