CentrED/Server/ULargeScaleOperations.pas

380 lines
9.8 KiB
Plaintext

(*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at
* http://www.opensource.org/licenses/cddl1.php.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at
* http://www.opensource.org/licenses/cddl1.php. If applicable,
* add the following below this CDDL HEADER, with the fields enclosed
* by brackets "[]" replaced with your own identifying * information:
* Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*
*
* Portions Copyright 2009 Andreas Schneider
*)
unit ULargeScaleOperations;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, UMap, UStatics, UEnhancedMemoryStream, math,
ULandscape;
type
TCopyMoveType = (cmCopy = 0, cmMove = 1);
TSetAltitudeType = (saTerrain = 1, saRelative = 2);
TStaticsPlacement = (spTerrain = 1, spTop = 2, spFix = 3);
{ TLargeScaleOperation }
TLargeScaleOperation = class(TObject)
constructor Init(AData: TEnhancedMemoryStream; ALandscape: TLandscape); virtual;
protected
FLandscape: TLandscape;
public
procedure Apply(AMapCell: TMapCell; AStatics: TStaticItemList;
AAdditionalAffectedBlocks: TBits); virtual; abstract;
end;
{ TLSCopyMove }
TLSCopyMove = class(TLargeScaleOperation)
constructor Init(AData: TEnhancedMemoryStream; ALandscape: TLandscape); override;
protected
FType: TCopyMoveType;
FOffsetX: Integer;
FOffsetY: Integer;
FErase: Boolean;
public
property OffsetX: Integer read FOffsetX;
property OffsetY: Integer read FOffsetY;
procedure Apply(AMapCell: TMapCell; AStatics: TStaticItemList;
AAdditionalAffectedBlocks: TBits); override;
end;
{ TLSSetAltitude }
TLSSetAltitude = class(TLargeScaleOperation)
constructor Init(AData: TEnhancedMemoryStream; ALandscape: TLandscape); override;
protected
FType: TSetAltitudeType;
FMinZ: ShortInt;
FMaxZ: ShortInt;
FRelativeZ: ShortInt;
public
procedure Apply(AMapCell: TMapCell; AStatics: TStaticItemList;
AAdditionalAffectedBlocks: TBits); override;
end;
{ TLSDrawTerrain }
TLSDrawTerrain = class(TLargeScaleOperation)
constructor Init(AData: TEnhancedMemoryStream; ALandscape: TLandscape); override;
protected
FTileIDs: array of Word;
public
procedure Apply(AMapCell: TMapCell; AStatics: TStaticItemList;
AAdditionalAffectedBlocks: TBits); override;
end;
{ TLSDeleteStatics }
TLSDeleteStatics = class(TLargeScaleOperation)
constructor Init(AData: TEnhancedMemoryStream; ALandscape: TLandscape); override;
protected
FTileIDs: array of Word;
FMinZ: ShortInt;
FMaxZ: ShortInt;
public
procedure Apply(AMapCell: TMapCell; AStatics: TStaticItemList;
AAdditionalAffectedBlocks: TBits); override;
end;
{ TLSInsertStatics }
TLSInsertStatics = class(TLargeScaleOperation)
constructor Init(AData: TEnhancedMemoryStream; ALandscape: TLandscape); override;
protected
FTileIDs: array of Word;
FProbability: Byte;
FPlacementType: TStaticsPlacement;
FFixZ: ShortInt;
public
procedure Apply(AMapCell: TMapCell; AStatics: TStaticItemList;
AAdditionalAffectedBlocks: TBits); override;
end;
implementation
uses
UCEDServer;
{ TLargeScaleOperation }
constructor TLargeScaleOperation.Init(AData: TEnhancedMemoryStream;
ALandscape: TLandscape);
begin
inherited Create;
FLandscape := ALandscape;
end;
{ TLSCopyMove }
constructor TLSCopyMove.Init(AData: TEnhancedMemoryStream;
ALandscape: TLandscape);
begin
inherited Init(AData, ALandscape);
FType := TCopyMoveType(AData.ReadByte);
FOffsetX := AData.ReadInteger;
FOffsetY := AData.ReadInteger;
FErase := AData.ReadBoolean;
end;
procedure TLSCopyMove.Apply(AMapCell: TMapCell; AStatics: TStaticItemList;
AAdditionalAffectedBlocks: TBits);
var
x, y: Word;
targetCell: TMapCell;
targetStatics: TStaticItemList;
targetStaticsBlock: TSeperatedStaticBlock;
i: Integer;
staticItem: TStaticItem;
begin
x := EnsureRange(AMapCell.X + FOffsetX, 0, FLandscape.CellWidth - 1);
y := EnsureRange(AMapCell.Y + FOffsetY, 0, FLandscape.CellHeight - 1);
//writeln('target: ', x, ',', y);
targetCell := FLandscape.MapCell[x, y];
targetStaticsBlock := FLandscape.GetStaticBlock(x div 8, y div 8);
targetStatics := targetStaticsBlock.Cells[(y mod 8) * 8 + (x mod 8)];
if FErase then
begin
for i := 0 to targetStatics.Count - 1 do
targetStatics[i].Delete;
targetStatics.Clear;
end;
targetCell.TileID := AMapCell.TileID;
targetCell.Z := AMapCell.Z;
if FType = cmCopy then
begin
for i := 0 to AStatics.Count - 1 do
begin
staticItem := TStaticItem.Create(nil, nil, 0, 0);
staticItem.X := x;
staticItem.Y := y;
staticItem.Z := AStatics[i].Z;
staticItem.TileID := AStatics[i].TileID;
staticItem.Hue := AStatics[i].Hue;
staticItem.Owner := targetStaticsBlock;
targetStatics.Add(staticItem);
end;
end else
begin
for i := 0 to AStatics.Count - 1 do
begin
targetStatics.Add(AStatics[i]);
AStatics[i].UpdatePos(x, y, AStatics[i].Z);
AStatics[i].Owner := targetStaticsBlock;
AStatics[i] := nil;
end;
AStatics.Clear;
end;
FLandscape.SortStaticsList(targetStatics);
AAdditionalAffectedBlocks.Bits[(x div 8) * FLandscape.Height + (y div 8)] := True;
end;
{ TLSSetAltitude }
constructor TLSSetAltitude.Init(AData: TEnhancedMemoryStream;
ALandscape: TLandscape);
begin
inherited Init(AData, ALandscape);
FType := TSetAltitudeType(AData.ReadByte);
case FType of
saTerrain:
begin
FMinZ := AData.ReadShortInt;
FMaxZ := AData.ReadShortInt;
end;
saRelative:
begin
FRelativeZ := AData.ReadShortInt;
end;
end;
end;
procedure TLSSetAltitude.Apply(AMapCell: TMapCell; AStatics: TStaticItemList;
AAdditionalAffectedBlocks: TBits);
var
i: Integer;
newZ: ShortInt;
diff: ShortInt;
static: TStaticItem;
begin
if FType = saTerrain then
begin
newZ := FMinZ + Random(FMaxZ - FMinZ + 1);
diff := newZ - AMapCell.Z;
AMapCell.Z := newZ;
end else
begin
diff := FRelativeZ;
AMapCell.Z := EnsureRange(AMapCell.Z + diff, -128, 127);
end;
for i := 0 to AStatics.Count - 1 do
begin
static := AStatics[i];
static.Z := EnsureRange(static.Z + diff, -128, 127);
end;
end;
{ TLSDrawTerrain }
constructor TLSDrawTerrain.Init(AData: TEnhancedMemoryStream;
ALandscape: TLandscape);
var
count: Word;
begin
inherited Init(AData, ALandscape);
count := AData.ReadWord;
SetLength(FTileIDs, count);
AData.Read(FTileIDs[0], count * SizeOf(Word));
end;
procedure TLSDrawTerrain.Apply(AMapCell: TMapCell; AStatics: TStaticItemList;
AAdditionalAffectedBlocks: TBits);
begin
if Length(FTileIDs) > 0 then
AMapCell.TileID := FTileIDs[Random(Length(FTileIDs))];
end;
{ TLSDeleteStatics }
constructor TLSDeleteStatics.Init(AData: TEnhancedMemoryStream;
ALandscape: TLandscape);
var
count: Word;
begin
inherited Init(AData, ALandscape);
count := AData.ReadWord;
SetLength(FTileIDs, count);
AData.Read(FTileIDs[0], count * SizeOf(Word));
FMinZ := AData.ReadShortInt;
FMaxZ := AData.ReadShortInt;
end;
procedure TLSDeleteStatics.Apply(AMapCell: TMapCell; AStatics: TStaticItemList;
AAdditionalAffectedBlocks: TBits);
var
i, j: Integer;
static: TStaticItem;
begin
i := 0;
while i < AStatics.Count do
begin
static := AStatics[i];
if InRange(static.Z, FMinZ, FMaxZ) then
begin
if Length(FTileIDs) > 0 then
begin
for j := Low(FTileIDs) to High(FTileIDs) do
begin
if static.TileID = FTileIDs[j] - $4000 then
begin
static.Delete;
AStatics.Delete(i);
Dec(i);
Break;
end;
end;
Inc(i);
end else
begin
static.Delete;
AStatics.Delete(i);
end;
end else
Inc(i);
end;
end;
{ TLSInsertStatics }
constructor TLSInsertStatics.Init(AData: TEnhancedMemoryStream;
ALandscape: TLandscape);
var
count: Word;
begin
inherited Init(AData, ALandscape);
count := AData.ReadWord;
SetLength(FTileIDs, count);
AData.Read(FTileIDs[0], count * SizeOf(Word));
FProbability := AData.ReadByte;
FPlacementType := TStaticsPlacement(AData.ReadByte);
if FPlacementType = spFix then
FFixZ := AData.ReadShortInt;
end;
procedure TLSInsertStatics.Apply(AMapCell: TMapCell; AStatics: TStaticItemList;
AAdditionalAffectedBlocks: TBits);
var
staticItem, static: TStaticItem;
topZ, staticTop: ShortInt;
i: Integer;
begin
if (Length(FTileIDs) = 0) or (Random(100) >= FProbability) then Exit;
staticItem := TStaticItem.Create(nil, nil, 0, 0);
staticItem.X := AMapCell.X;
staticItem.Y := AMapCell.Y;
staticItem.TileID := FTileIDs[Random(Length(FTileIDs))] - $4000;
staticItem.Hue := 0;
case FPlacementType of
spTerrain:
begin
staticItem.Z := AMapCell.Z;
end;
spTop:
begin
topZ := AMapCell.Z;
for i := 0 to AStatics.Count - 1 do
begin
static := AStatics[i];
staticTop := EnsureRange(static.Z +
CEDServerInstance.Landscape.TiledataProvider.StaticTiles[static.TileID].Height,
-128, 127);
if staticTop > topZ then topZ := staticTop;
end;
end;
spFix:
begin
staticItem.Z := FFixZ;
end;
end;
AStatics.Add(staticItem);
staticItem.Owner := CEDServerInstance.Landscape.GetStaticBlock(
staticItem.X div 8, staticItem.Y div 8);
end;
end.