diff --git a/Client/UPackets.pas b/Client/UPackets.pas index 7b23718..a6581ea 100644 --- a/Client/UPackets.pas +++ b/Client/UPackets.pas @@ -1,330 +1,375 @@ -(* - * 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 2007 Andreas Schneider - *) -unit UPackets; - -interface - -uses - Classes, dzlib, UEnhancedMemoryStream, UPacket, UMap, UStatics; - -type - TBlockCoords = packed record - X: Word; - Y: Word; - end; - TBlockCoordsArray = array of TBlockCoords; - - { TCompressedPacket } - - TCompressedPacket = class(TPacket) - constructor Create(APacket: TPacket); - end; - - { TLoginRequestPacket } - - TLoginRequestPacket = class(TPacket) - constructor Create(AUsername, APassword: string); - end; - - { TQuitPacket } - - TQuitPacket = class(TPacket) - constructor Create; - end; - - { TRequestBlocksPacket } - - TRequestBlocksPacket = class(TPacket) - constructor Create(ACoords: TBlockCoordsArray); - end; - - { TFreeBlockPacket } - - TFreeBlockPacket = class(TPacket) - constructor Create(AX, AY: Word); - end; - - { TDrawMapPacket } - - TDrawMapPacket = class(TPacket) - constructor Create(AX, AY: Word; AZ: ShortInt; ATileID: Word); - end; - - { TInsertStaticPacket } - - TInsertStaticPacket = class(TPacket) - constructor Create(AX, AY: Word; AZ: ShortInt; ATileID: Word; AHue: Word); - end; - - { TDeleteStaticPacket } - - TDeleteStaticPacket = class(TPacket) - constructor Create(AStaticItem: TStaticItem); - end; - - { TElevateStaticPacket } - - TElevateStaticPacket = class(TPacket) - constructor Create(AStaticItem: TStaticItem; ANewZ: ShortInt); - end; - - { TMoveStaticPacket } - - TMoveStaticPacket = class(TPacket) - constructor Create(AStaticItem: TStaticItem; ANewX, ANewY: Word); - end; - - { THueStaticPacket } - - THueStaticPacket = class(TPacket) - constructor Create(AStaticItem: TStaticItem; ANewHue: Word); - end; - - { TUpdateClientPosPacket } - - TUpdateClientPosPacket = class(TPacket) - constructor Create(AX, AY: Word); - end; - - { TChatMessagePacket } - - TChatMessagePacket = class(TPacket) - constructor Create(AMessage: string); - end; - - { TGotoClientPosPacket } - - TGotoClientPosPacket = class(TPacket) - constructor Create(AUsername: string); - end; - - { TRequestRadarChecksumPacket } - - TRequestRadarChecksumPacket = class(TPacket) - constructor Create; - end; - - { TRequestRadarMapPacket } - - TRequestRadarMapPacket = class(TPacket) - constructor Create; - end; - - { TNoOpPacket } - - TNoOpPacket = class(TPacket) - constructor Create; - end; - -implementation - -{ TCompressedPacket } - -constructor TCompressedPacket.Create(APacket: TPacket); -var - compBuffer: TEnhancedMemoryStream; - compStream: TCompressionStream; - sourceStream: TStream; -begin - inherited Create($01, 0); - compBuffer := TEnhancedMemoryStream.Create; - compStream := TCompressionStream.Create(clMax, compBuffer); - sourceStream := APacket.Stream; - compStream.CopyFrom(sourceStream, 0); - compStream.Free; - FStream.WriteCardinal(sourceStream.Size); - FStream.CopyFrom(compBuffer, 0); - compBuffer.Free; - APacket.Free; -end; - -{ TLoginRequestPacket } - -constructor TLoginRequestPacket.Create(AUsername, APassword: string); -begin - inherited Create($02, 0); - FStream.WriteByte($03); - FStream.WriteStringNull(AUsername); - FStream.WriteStringNull(APassword); -end; - -{ TQuitPacket } - -constructor TQuitPacket.Create; -begin - inherited Create($02, 0); - FStream.WriteByte($05); -end; - -{ TRequestBlocksPacket } - -constructor TRequestBlocksPacket.Create(ACoords: TBlockCoordsArray); -var - i: Integer; -begin - inherited Create($04, 0); - FStream.Write(ACoords[0], Length(ACoords) * SizeOf(TBlockCoords)); -end; - -{ TFreeBlockPacket } - -constructor TFreeBlockPacket.Create(AX, AY: Word); -begin - inherited Create($05, 5); - FStream.WriteWord(AX); - FStream.WriteWord(AY); -end; - -{ TDrawMapPacket } - -constructor TDrawMapPacket.Create(AX, AY: Word; AZ: ShortInt; ATileID: Word); -begin - inherited Create($06, 8); - FStream.WriteWord(AX); - FStream.WriteWord(AY); - FStream.WriteShortInt(AZ); - FStream.WriteWord(ATileID); -end; - -{ TInsertStaticPacket } - -constructor TInsertStaticPacket.Create(AX, AY: Word; AZ: ShortInt; - ATileID: Word; AHue: Word); -begin - inherited Create($07, 10); - FStream.WriteWord(AX); - FStream.WriteWord(AY); - FStream.WriteShortInt(AZ); - FStream.WriteWord(ATileID); - FStream.WriteWord(AHue); -end; - -{ TDeleteStaticPacket } - -constructor TDeleteStaticPacket.Create(AStaticItem: TStaticItem); -begin - inherited Create($08, 10); - FStream.WriteWord(AStaticItem.X); - FStream.WriteWord(AStaticItem.Y); - FStream.WriteShortInt(AStaticItem.Z); - FStream.WriteWord(AStaticItem.TileID); - FStream.WriteWord(AStaticItem.Hue); -end; - -{ TElevateStaticPacket } - -constructor TElevateStaticPacket.Create(AStaticItem: TStaticItem; ANewZ: ShortInt); -begin - inherited Create($09, 11); - FStream.WriteWord(AStaticItem.X); - FStream.WriteWord(AStaticItem.Y); - FStream.WriteShortInt(AStaticItem.Z); - FStream.WriteWord(AStaticItem.TileID); - FStream.WriteWord(AStaticItem.Hue); - FStream.WriteShortInt(ANewZ); -end; - -{ TMoveStaticPacket } - -constructor TMoveStaticPacket.Create(AStaticItem: TStaticItem; ANewX, - ANewY: Word); -begin - inherited Create($0A, 14); - FStream.WriteWord(AStaticItem.X); - FStream.WriteWord(AStaticItem.Y); - FStream.WriteShortInt(AStaticItem.Z); - FStream.WriteWord(AStaticItem.TileID); - FStream.WriteWord(AStaticItem.Hue); - FStream.WriteWord(ANewX); - FStream.WriteWord(ANewY); -end; - -{ THueStaticPacket } - -constructor THueStaticPacket.Create(AStaticItem: TStaticItem; ANewHue: Word); -begin - inherited Create($0B, 12); - FStream.WriteWord(AStaticItem.X); - FStream.WriteWord(AStaticItem.Y); - FStream.WriteShortInt(AStaticItem.Z); - FStream.WriteWord(AStaticItem.TileID); - FStream.WriteWord(AStaticItem.Hue); - FStream.WriteWord(ANewHue); -end; - -{ TUpdateClientPosPacket } - -constructor TUpdateClientPosPacket.Create(AX, AY: Word); -begin - inherited Create($0C, 0); - FStream.WriteByte($04); - FStream.WriteWord(AX); - FStream.WriteWord(AY); -end; - -{ TChatMessagePacket } - -constructor TChatMessagePacket.Create(AMessage: string); -begin - inherited Create($0C, 0); - FStream.WriteByte($05); - FStream.WriteStringNull(AMessage); -end; - -{ TGotoClientPosPacket } - -constructor TGotoClientPosPacket.Create(AUsername: string); -begin - inherited Create($0C, 0); - FStream.WriteByte($06); - FStream.WriteStringNull(AUsername); -end; - -{ TRequestRadarChecksumPacket } - -constructor TRequestRadarChecksumPacket.Create; -begin - inherited Create($0D, 2); - FStream.WriteByte($01); -end; - -{ TRequestRadarMapPacket } - -constructor TRequestRadarMapPacket.Create; -begin - inherited Create($0D, 2); - FStream.WriteByte($02); -end; - -{ TNoOpPacket } - -constructor TNoOpPacket.Create; -begin - inherited Create($FF, 1); -end; - -end. - +(* + * 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 UPackets; + +interface + +uses + Classes, dzlib, UEnhancedMemoryStream, UPacket, UMap, UStatics; + +type + TBlockCoords = packed record + X: Word; + Y: Word; + end; + TBlockCoordsArray = array of TBlockCoords; + + { TCompressedPacket } + + TCompressedPacket = class(TPacket) + constructor Create(APacket: TPacket); + end; + + { TLoginRequestPacket } + + TLoginRequestPacket = class(TPacket) + constructor Create(AUsername, APassword: string); + end; + + { TQuitPacket } + + TQuitPacket = class(TPacket) + constructor Create; + end; + + { TRequestBlocksPacket } + + TRequestBlocksPacket = class(TPacket) + constructor Create(ACoords: TBlockCoordsArray); + end; + + { TFreeBlockPacket } + + TFreeBlockPacket = class(TPacket) + constructor Create(AX, AY: Word); + end; + + { TDrawMapPacket } + + TDrawMapPacket = class(TPacket) + constructor Create(AX, AY: Word; AZ: ShortInt; ATileID: Word); + end; + + { TStaticPacket } + + TStaticPacket = class(TPacket) + protected + procedure WriteStaticItem(AStaticItem: TStaticItem); + end; + + { TInsertStaticPacket } + + TInsertStaticPacket = class(TPacket) + constructor Create(AX, AY: Word; AZ: ShortInt; ATileID: Word; AHue: Word); + end; + + { TDeleteStaticPacket } + + TDeleteStaticPacket = class(TStaticPacket) + constructor Create(AStaticItem: TStaticItem); + end; + + { TElevateStaticPacket } + + TElevateStaticPacket = class(TStaticPacket) + constructor Create(AStaticItem: TStaticItem; ANewZ: ShortInt); + constructor Create(AX, AY: Word; AZ: ShortInt; ATileID: Word; AHue: Word; + ANewZ: Word); + end; + + { TMoveStaticPacket } + + TMoveStaticPacket = class(TStaticPacket) + constructor Create(AStaticItem: TStaticItem; ANewX, ANewY: Word); + constructor Create(AX, AY: Word; AZ: ShortInt; ATileID: Word; AHue: Word; + ANewX, ANewY: Word); + end; + + { THueStaticPacket } + + THueStaticPacket = class(TStaticPacket) + constructor Create(AStaticItem: TStaticItem; ANewHue: Word); + constructor Create(AX, AY: Word; AZ: ShortInt; ATileID: Word; AHue: Word; + ANewHue: Word); + end; + + { TUpdateClientPosPacket } + + TUpdateClientPosPacket = class(TPacket) + constructor Create(AX, AY: Word); + end; + + { TChatMessagePacket } + + TChatMessagePacket = class(TPacket) + constructor Create(AMessage: string); + end; + + { TGotoClientPosPacket } + + TGotoClientPosPacket = class(TPacket) + constructor Create(AUsername: string); + end; + + { TRequestRadarChecksumPacket } + + TRequestRadarChecksumPacket = class(TPacket) + constructor Create; + end; + + { TRequestRadarMapPacket } + + TRequestRadarMapPacket = class(TPacket) + constructor Create; + end; + + { TNoOpPacket } + + TNoOpPacket = class(TPacket) + constructor Create; + end; + +implementation + +{ TCompressedPacket } + +constructor TCompressedPacket.Create(APacket: TPacket); +var + compBuffer: TEnhancedMemoryStream; + compStream: TCompressionStream; + sourceStream: TStream; +begin + inherited Create($01, 0); + compBuffer := TEnhancedMemoryStream.Create; + compStream := TCompressionStream.Create(clMax, compBuffer); + sourceStream := APacket.Stream; + compStream.CopyFrom(sourceStream, 0); + compStream.Free; + FStream.WriteCardinal(sourceStream.Size); + FStream.CopyFrom(compBuffer, 0); + compBuffer.Free; + APacket.Free; +end; + +{ TLoginRequestPacket } + +constructor TLoginRequestPacket.Create(AUsername, APassword: string); +begin + inherited Create($02, 0); + FStream.WriteByte($03); + FStream.WriteStringNull(AUsername); + FStream.WriteStringNull(APassword); +end; + +{ TQuitPacket } + +constructor TQuitPacket.Create; +begin + inherited Create($02, 0); + FStream.WriteByte($05); +end; + +{ TRequestBlocksPacket } + +constructor TRequestBlocksPacket.Create(ACoords: TBlockCoordsArray); +var + i: Integer; +begin + inherited Create($04, 0); + FStream.Write(ACoords[0], Length(ACoords) * SizeOf(TBlockCoords)); +end; + +{ TFreeBlockPacket } + +constructor TFreeBlockPacket.Create(AX, AY: Word); +begin + inherited Create($05, 5); + FStream.WriteWord(AX); + FStream.WriteWord(AY); +end; + +{ TDrawMapPacket } + +constructor TDrawMapPacket.Create(AX, AY: Word; AZ: ShortInt; ATileID: Word); +begin + inherited Create($06, 8); + FStream.WriteWord(AX); + FStream.WriteWord(AY); + FStream.WriteShortInt(AZ); + FStream.WriteWord(ATileID); +end; + +{ TStaticPacket } + +procedure TStaticPacket.WriteStaticItem(AStaticItem: TStaticItem); +begin + FStream.WriteWord(AStaticItem.X); + FStream.WriteWord(AStaticItem.Y); + FStream.WriteShortInt(AStaticItem.Z); + FStream.WriteWord(AStaticItem.TileID); + FStream.WriteWord(AStaticItem.Hue); +end; + +{ TInsertStaticPacket } + +constructor TInsertStaticPacket.Create(AX, AY: Word; AZ: ShortInt; + ATileID: Word; AHue: Word); +begin + inherited Create($07, 10); + FStream.WriteWord(AX); + FStream.WriteWord(AY); + FStream.WriteShortInt(AZ); + FStream.WriteWord(ATileID); + FStream.WriteWord(AHue); +end; + +{ TDeleteStaticPacket } + +constructor TDeleteStaticPacket.Create(AStaticItem: TStaticItem); +begin + inherited Create($08, 10); + WriteStaticItem(AStaticItem); +end; + +{ TElevateStaticPacket } + +constructor TElevateStaticPacket.Create(AStaticItem: TStaticItem; ANewZ: ShortInt); +begin + inherited Create($09, 11); + WriteStaticItem(AStaticItem); + FStream.WriteShortInt(ANewZ); +end; + +constructor TElevateStaticPacket.Create(AX, AY: Word; AZ: ShortInt; + ATileID: Word; AHue: Word; ANewZ: Word); +begin + inherited Create($09, 11); + FStream.WriteWord(AX); + FStream.WriteWord(AY); + FStream.WriteShortInt(AZ); + FStream.WriteWord(ATileID); + FStream.WriteWord(AHue); + FStream.WriteShortInt(ANewZ); +end; + +{ TMoveStaticPacket } + +constructor TMoveStaticPacket.Create(AStaticItem: TStaticItem; ANewX, + ANewY: Word); +begin + inherited Create($0A, 14); + WriteStaticItem(AStaticItem); + FStream.WriteWord(ANewX); + FStream.WriteWord(ANewY); +end; + +constructor TMoveStaticPacket.Create(AX, AY: Word; AZ: ShortInt; ATileID: Word; + AHue: Word; ANewX, ANewY: Word); +begin + inherited Create($0A, 14); + FStream.WriteWord(AX); + FStream.WriteWord(AY); + FStream.WriteShortInt(AZ); + FStream.WriteWord(ATileID); + FStream.WriteWord(AHue); + FStream.WriteWord(ANewX); + FStream.WriteWord(ANewY); +end; + +{ THueStaticPacket } + +constructor THueStaticPacket.Create(AStaticItem: TStaticItem; ANewHue: Word); +begin + inherited Create($0B, 12); + WriteStaticItem(AStaticItem); + FStream.WriteWord(ANewHue); +end; + +constructor THueStaticPacket.Create(AX, AY: Word; AZ: ShortInt; ATileID: Word; + AHue: Word; ANewHue: Word); +begin + inherited Create($0B, 12); + FStream.WriteWord(AX); + FStream.WriteWord(AY); + FStream.WriteShortInt(AZ); + FStream.WriteWord(ATileID); + FStream.WriteWord(AHue); + FStream.WriteWord(ANewHue); +end; + +{ TUpdateClientPosPacket } + +constructor TUpdateClientPosPacket.Create(AX, AY: Word); +begin + inherited Create($0C, 0); + FStream.WriteByte($04); + FStream.WriteWord(AX); + FStream.WriteWord(AY); +end; + +{ TChatMessagePacket } + +constructor TChatMessagePacket.Create(AMessage: string); +begin + inherited Create($0C, 0); + FStream.WriteByte($05); + FStream.WriteStringNull(AMessage); +end; + +{ TGotoClientPosPacket } + +constructor TGotoClientPosPacket.Create(AUsername: string); +begin + inherited Create($0C, 0); + FStream.WriteByte($06); + FStream.WriteStringNull(AUsername); +end; + +{ TRequestRadarChecksumPacket } + +constructor TRequestRadarChecksumPacket.Create; +begin + inherited Create($0D, 2); + FStream.WriteByte($01); +end; + +{ TRequestRadarMapPacket } + +constructor TRequestRadarMapPacket.Create; +begin + inherited Create($0D, 2); + FStream.WriteByte($02); +end; + +{ TNoOpPacket } + +constructor TNoOpPacket.Create; +begin + inherited Create($FF, 1); +end; + +end. + diff --git a/Client/UfrmMain.lfm b/Client/UfrmMain.lfm index fc4f26e..7be316f 100644 --- a/Client/UfrmMain.lfm +++ b/Client/UfrmMain.lfm @@ -915,29 +915,29 @@ object frmMain: TfrmMain ShowHint = True Style = tbsCheck end - object tbSeparator2: TToolButton - Left = 178 + object tbSeparator3: TToolButton + Left = 209 Top = 2 - Width = 15 - Caption = 'tbSeparator2' + Width = 16 + Caption = 'tbSeparator3' Style = tbsDivider end object tbBoundaries: TToolButton - Left = 193 + Left = 225 Top = 2 Action = acBoundaries ParentShowHint = False ShowHint = True end - object tbSeparator3: TToolButton - Left = 262 + object tbSeparator4: TToolButton + Left = 294 Top = 2 - Width = 15 - Caption = 'tbSeparator3' + Width = 17 + Caption = 'tbSeparator4' Style = tbsDivider end object tbTerrain: TToolButton - Left = 277 + Left = 311 Hint = 'Show Terrain' Top = 2 Caption = 'Terrain' @@ -949,7 +949,7 @@ object frmMain: TfrmMain OnClick = tbTerrainClick end object tbStatics: TToolButton - Left = 300 + Left = 334 Hint = 'Show Statics' Top = 2 Caption = 'Statics' @@ -960,15 +960,15 @@ object frmMain: TfrmMain Style = tbsCheck OnClick = tbStaticsClick end - object tbSeparator4: TToolButton - Left = 369 + object tbSeparator5: TToolButton + Left = 403 Top = 2 - Width = 15 - Caption = 'tbSeparator4' + Width = 17 + Caption = 'tbSeparator5' Style = tbsDivider end object tbRadarMap: TToolButton - Left = 384 + Left = 420 Hint = 'Radar Map' Top = 2 Caption = 'Radar Map' @@ -978,29 +978,41 @@ object frmMain: TfrmMain OnClick = tbRadarMapClick end object tbVirtualLayer: TToolButton - Left = 216 + Left = 248 Top = 2 Action = acVirtualLayer end object tbFilter: TToolButton - Left = 239 + Left = 271 Top = 2 Action = acFilter Style = tbsCheck OnMouseMove = tbFilterMouseMove end object tbFlat: TToolButton - Left = 346 + Left = 380 Top = 2 Action = acFlat Style = tbsCheck end object tbNoDraw: TToolButton - Left = 323 + Left = 357 Top = 2 Action = acNoDraw Style = tbsCheck end + object tbSeparator2: TToolButton + Left = 178 + Top = 2 + Width = 8 + Caption = 'tbSeparator2' + Style = tbsDivider + end + object tbUndo: TToolButton + Left = 186 + Top = 2 + Action = acUndo + end end object pnlChatHeader: TPanel AnchorSideLeft.Control = pnlChat @@ -1419,7 +1431,7 @@ object frmMain: TfrmMain left = 264 top = 32 Bitmap = { - 4C69140000001000000010000000000000000000000000000000000000000000 + 4C69150000001000000010000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000D9A781FFD39E76FF00000000000000000000000000000000000000000000 0000000000000000000000000000ECBEA1FFE7BB9DFFE4B697FFE0B292FFDAAE @@ -2059,7 +2071,39 @@ object frmMain: TfrmMain 84FF94C7F9FF91C9F9FF4185C9FF256BACFFB7D9D4FFD4E2ECFFCFE5D6FFD5ED D9FFD8EFDCFFD5EDD9FF616C63FF454D47FF5F6A61FF636F64FF646F64FF143F 56FF295F86FF4988BCFF4A86A7FF5D7070FF646F66FF646F66FF646F67FF646F - 67FF647067FF616C63FF474E48FF + 67FF647067FF616C63FF474E48FFFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF0066C472FF64C270FF62BF + 6EFF60BC6BFF5DB868FF5BB565FF58B162FD55AC5FEA52A85BB74FA358704B9F + 541DFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF0064C170FFA6DBB0FFA6DA + AFFFA3D9ADFFA2D8ABFF9FD7A8FF9CD5A5FF94D09DFF83C58CFF6CB474FF4799 + 50B044944C39FFFFFF00FFFFFF00FFFFFF00FFFFFF0062BE6DFFA5DAAEFFA2D8 + ACFFA1D8AAFF9ED6A7FF9CD5A5FF99D4A2FF97D29FFF8CCD95FF91CF99FF73B8 + 7BFF408F47B03C8A431DFFFFFF00FFFFFF00FFFFFF005FBA6AFF5CB667FF59B3 + 64FF56AE60FF53AA5DFF50A659FF4DA156FF68B170FF88C890FF8DCC95FF8BCB + 92FF5DA564FF38853F70FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF0046974E8F42924AE281C388FF7DC4 + 85FF6EB375FF357F3BB7FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF003E8D458F64AB6BFF7FC4 + 86FF79BE81FF317A36EAFFFFFF00FFFFFF00FFFFFF00FFFFFF0052A85B034FA3 + 587BFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF003A87418F61A867FF7BC2 + 82FF76BC7CFF2D7532EAFFFFFF00FFFFFF00FFFFFF00FFFFFF004EA3579F4B9E + 53D2FFFFFF00FFFFFF00FFFFFF00FFFFFF003A86408F36813CE275BB7BFF70BD + 77FF63AB69FF2A702EB7FFFFFF00FFFFFF00FFFFFF004DA2569367B16FFF64AD + 6BFF43944BFF408F47FF3C8A43FF398540FF549D5AFF74BA7AFF79C17FFF77BF + 7DFF4A914FFF266B2B70FFFFFF00FFFFFF004DA1568A66B06EFF8ACA92FF89CA + 90FF86C88DFF83C68AFF80C587FF7EC384FF7BC281FF6DBB74FF76BE7CFF59A0 + 5DFF266B2AB02367271DFFFFFF00FFFFFF00499C518462AC6AFF85C88DFF85C7 + 8BFF82C688FF7FC486FF7CC282FF79C180FF71B978FF5FA865FF49914EFF256A + 2AB023662739FFFFFF00FFFFFF00FFFFFF00FFFFFF00429149905AA462FF58A1 + 5EFF37833EFF347E3AFF317A36FF2E7533FF2B712FEA286D2CB7256929702266 + 261DFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF003A87419C3782 + 3DD2FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF0036813C03337D + 3978FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00 } end object pmTileList: TPopupMenu @@ -2530,6 +2574,15 @@ object frmMain: TfrmMain ImageIndex = 18 OnExecute = acNoDrawExecute end + object acUndo: TAction + Category = 'Tools' + Caption = 'Undo' + Enabled = False + Hint = 'Undo last set of changes' + ImageIndex = 20 + OnExecute = acUndoExecute + ShortCut = 16474 + end end object tmGrabTileInfo: TTimer Enabled = False diff --git a/Client/UfrmMain.pas b/Client/UfrmMain.pas index 692d1a2..4630df5 100644 --- a/Client/UfrmMain.pas +++ b/Client/UfrmMain.pas @@ -33,8 +33,8 @@ uses Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, Menus, ComCtrls, OpenGLContext, GL, GLU, UGameResources, ULandscape, ExtCtrls, StdCtrls, Spin, UEnums, VirtualTrees, Buttons, UMulBlock, UWorldItem, math, - LCLIntf, UOverlayUI, UStatics, UEnhancedMemoryStream, ActnList, - ImagingClasses, dateutils, UPlatformTypes, UMap; + LCLIntf, UOverlayUI, UStatics, UEnhancedMemoryStream, ActnList, fgl, + ImagingClasses, dateutils, UPlatformTypes, UMap, UPacket; type TAccessChangedListener = procedure(AAccessLevel: TAccessLevel) of object; @@ -42,6 +42,7 @@ type TScreenBufferStates = set of TScreenBufferState; TGhostTile = class(TStaticItem); + TPacketList = specialize TFPGObjectList; { TfrmMain } @@ -56,6 +57,7 @@ type acFilter: TAction; acFlat: TAction; acNoDraw: TAction; + acUndo: TAction; acVirtualLayer: TAction; ActionList1: TActionList; ApplicationProperties1: TApplicationProperties; @@ -128,11 +130,13 @@ type tbFlat: TToolButton; tbNoDraw: TToolButton; tmTileHint: TTimer; + tbSeparator2: TToolButton; + tbUndo: TToolButton; tsLocations: TTabSheet; tbSetHue: TToolButton; tmGrabTileInfo: TTimer; tmMovement: TTimer; - tbSeparator4: TToolButton; + tbSeparator5: TToolButton; tbRadarMap: TToolButton; tbVirtualLayer: TToolButton; tsClients: TTabSheet; @@ -144,9 +148,9 @@ type tbMoveTile: TToolButton; tbElevateTile: TToolButton; tbDeleteTile: TToolButton; - tbSeparator2: TToolButton; - tbBoundaries: TToolButton; tbSeparator3: TToolButton; + tbBoundaries: TToolButton; + tbSeparator4: TToolButton; tbTerrain: TToolButton; tbStatics: TToolButton; tsTiles: TTabSheet; @@ -164,6 +168,7 @@ type procedure acMoveExecute(Sender: TObject); procedure acNoDrawExecute(Sender: TObject); procedure acSelectExecute(Sender: TObject); + procedure acUndoExecute(Sender: TObject); procedure acVirtualLayerExecute(Sender: TObject); procedure ApplicationProperties1Idle(Sender: TObject; var Done: Boolean); procedure btnAddLocationClick(Sender: TObject); @@ -288,6 +293,7 @@ type FAccessChangedListeners: array of TAccessChangedListener; FRepaintNeeded: Boolean; FSelection: TRect; + FUndoList: TPacketList; { Methods } procedure BuildTileList; function ConfirmAction: Boolean; @@ -543,7 +549,7 @@ var targetRect: TRect; offsetX, offsetY: Integer; tile: TWorldItem; - tileX, tileY: Word; + tileX, tileY, newX, newY: Word; targetTiles: TWorldItemList; targetTile: TWorldItem; begin @@ -569,6 +575,7 @@ begin if (not acSelect.Checked) and (targetTile <> nil) and (SelectedTile <> nil) then begin targetRect := GetSelectedRect; + FUndoList.Clear; if (SelectedTile = targetTile) or ConfirmAction then begin @@ -579,16 +586,23 @@ begin begin map := FLandscape.MapCell[tileX, tileY]; if map.IsGhost then + begin + FUndoList.Add(TDrawMapPacket.Create(tileX, tileY, map.RawZ, + map.RawTileID)); dmNetwork.Send(TDrawMapPacket.Create(tileX, tileY, map.Z, map.TileID)); + end; end; for i := 0 to FVirtualTiles.Count - 1 do begin tile := FVirtualTiles[i]; if tile is TGhostTile then + begin dmNetwork.Send(TInsertStaticPacket.Create(tile.X, tile.Y, tile.Z, tile.TileID, TGhostTile(tile).Hue)); + FUndoList.Add(TDeleteStaticPacket.Create(TGhostTile(tile))); + end; end; end else if (SelectedTile <> targetTile) or targetTile.CanBeEdited then begin @@ -623,9 +637,12 @@ begin if tile is TStaticItem then begin + newX := EnsureRange(tile.X + offsetX, 0, FLandscape.CellWidth - 1); + newY := EnsureRange(tile.Y + offsetY, 0, FLandscape.CellHeight - 1); + FUndoList.Add(TMoveStaticPacket.Create(newX, newY, tile.Z, + tile.TileID, TStaticItem(tile).Hue, tile.X, tile.Y)); dmNetwork.Send(TMoveStaticPacket.Create(TStaticItem(tile), - EnsureRange(tile.X + offsetX, 0, FLandscape.CellWidth - 1), - EnsureRange(tile.Y + offsetY, 0, FLandscape.CellHeight - 1))); + newX, newY)); end; end; end else if acElevate.Checked then //***** Elevate tile *****// @@ -644,10 +661,14 @@ begin begin if frmElevateSettings.cbRandomHeight.Checked then Inc(z, Random(frmElevateSettings.seRandomHeight.Value)); - dmNetwork.Send(TDrawMapPacket.Create(tile.X, tile.Y, - z, tile.TileID)); + FUndoList.Add(TDrawMapPacket.Create(tile.X, tile.Y, tile.Z, + tile.TileID)); + dmNetwork.Send(TDrawMapPacket.Create(tile.X, tile.Y, z, + tile.TileID)); end else begin + FUndoList.Add(TElevateStaticPacket.Create(tile.X, tile.Y, + z, tile.TileID, TStaticItem(tile).Hue, tile.Z)); dmNetwork.Send(TElevateStaticPacket.Create(TStaticItem(tile), z)); end; end; @@ -658,7 +679,11 @@ begin tile := targetTiles.Items[i]; if tile is TStaticItem then + begin + FUndoList.Add(TInsertStaticPacket.Create(tile.X, tile.Y, + tile.Z, tile.TileID, TStaticItem(tile).Hue)); dmNetwork.Send(TDeleteStaticPacket.Create(TStaticItem(tile))); + end; end; end else if acHue.Checked then //***** Hue tile *****// begin @@ -669,6 +694,9 @@ begin if (tile is TStaticItem) and (TStaticItem(tile).Hue <> frmHueSettings.lbHue.ItemIndex) then begin + FUndoList.Add(THueStaticPacket.Create(tile.X, tile.Y, tile.Z, + tile.TileID, frmHueSettings.lbHue.ItemIndex, + TStaticItem(tile).Hue)); dmNetwork.Send(THueStaticPacket.Create(TStaticItem(tile), frmHueSettings.lbHue.ItemIndex)); end; @@ -680,6 +708,7 @@ begin end; end; end; + acUndo.Enabled := FUndoList.Count > 0; SelectedTile := nil; FRepaintNeeded := True; end; @@ -771,6 +800,7 @@ begin virtualLayerGraphic.Free; FVirtualTiles := TWorldItemList.Create(True); + FUndoList := TPacketList.Create(True); FRandomPresetLocation := IncludeTrailingPathDelimiter(ExtractFilePath( Application.ExeName)) + 'RandomPresets' + PathDelim; @@ -893,6 +923,19 @@ begin ProcessToolState; end; +procedure TfrmMain.acUndoExecute(Sender: TObject); +var + i: Integer; +begin + for i := FUndoList.Count - 1 downto 0 do + begin + dmNetwork.Send(FUndoList[i]); + FUndoList[i] := nil; + end; + FUndoList.Clear; + acUndo.Enabled := False; +end; + procedure TfrmMain.acVirtualLayerExecute(Sender: TObject); begin frmVirtualLayer.Show; @@ -1044,6 +1087,7 @@ begin FreeAndNil(FOverlayUI); FreeAndNil(FVLayerMaterial); FreeAndNil(FVirtualTiles); + FreeAndNil(FUndoList); RegisterPacketHandler($0C, nil); end; @@ -2211,7 +2255,6 @@ begin FLandscape.FillDrawList(FScreenBuffer, FX + FLowOffsetX, FY + FLowOffsetY, FRangeX, FRangeY, tbTerrain.Down, tbStatics.Down, acNoDraw.Checked, FVirtualTiles); - //TODO : ghost tile //Pre-process the buffer blockInfo := nil; @@ -2327,7 +2370,6 @@ procedure TfrmMain.UpdateSelection; if tileInfo <> nil then begin - //TODO Update Ghost Tile if tileInfo^.ID < $4000 then begin cell := FLandscape.MapCell[AX, AY];