From 1c3d6249497c399e5b029c3dcffd753c682aefea Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Tue, 26 Aug 2008 22:48:48 +0200 Subject: [PATCH] - Added client side visualization of area restrictions - Added an icon to the "Region control" menu item - Changed the former TAccessLevelChangedPacket and the TLoginResponsePacket to add informations about the writeable areas - Changed OnModifyUserPacket to update clients according to new accesslevel/area restrictions - Changed OnModifyRegionPacket to update clients using that particular region - Fixed UPacketHandlers.ValidateAccess to check the region bounds according to the PtInRect function --- Client/UdmNetwork.pas | 46 ++++++++++++++++- Client/UfrmMain.lfm | 38 +++++++++++++- Client/UfrmMain.pas | 94 ++++++++++++++++++++++++++-------- Client/UfrmRegionControl.pas | 2 +- Server/UAccount.pas | 8 ++- Server/UAdminHandling.pas | 48 +++++++++++++---- Server/UClientHandling.pas | 81 +++++++++++++++++++++++------ Server/UConnectionHandling.pas | 9 ++-- Server/UPacketHandlers.pas | 6 ++- Server/cedserver.lpr | 2 +- 10 files changed, 274 insertions(+), 60 deletions(-) diff --git a/Client/UdmNetwork.pas b/Client/UdmNetwork.pas index d0a42e9..fdfe951 100644 --- a/Client/UdmNetwork.pas +++ b/Client/UdmNetwork.pas @@ -31,7 +31,8 @@ interface uses Classes, SysUtils, LResources, Forms, Controls, Dialogs, lNetComponents, lNet, - UEnhancedMemoryStream, UPacket, UEnums, ExtCtrls, dateutils; + UEnhancedMemoryStream, UPacket, UEnums, ExtCtrls, dateutils, URectList, + LCLIntf; type @@ -56,6 +57,7 @@ type FAccessLevel: TAccessLevel; FDataDir: string; FLastPacket: TDateTime; + FWriteMap: TRectList; procedure OnCanSend(ASocket: TLSocket); procedure OnConnectionHandlingPacket(ABuffer: TEnhancedMemoryStream); procedure ProcessQueue; @@ -63,9 +65,11 @@ type public property Username: string read FUsername; property AccessLevel: TAccessLevel read FAccessLevel write FAccessLevel; + function CanWrite(AX, AY: Word): Boolean; procedure Send(APacket: TPacket); procedure Disconnect; procedure CheckClose(ASender: TForm); + procedure UpdateWriteMap(AStream: TEnhancedMemoryStream); end; var @@ -98,6 +102,7 @@ begin if FSendQueue <> nil then FreeAndNil(FSendQueue); if FReceiveQueue <> nil then FreeAndNil(FReceiveQueue); if PacketHandlers[$02] <> nil then FreeAndNil(PacketHandlers[$02]); + if FWriteMap <> nil then FreeAndNil(FWriteMap); end; procedure TdmNetwork.TCPClientConnect(aSocket: TLSocket); @@ -194,6 +199,12 @@ begin width := ABuffer.ReadWord; height := ABuffer.ReadWord; ResMan.InitLandscape(width, height); + + {FWriteMap := TBits.Create(ResMan.Landscape.CellWidth * ResMan.Landscape.CellHeight); + FWriteMap.XorBits(FWriteMap); //set all to 1} + FWriteMap := TRectList.Create; + UpdateWriteMap(ABuffer); + frmMain := TfrmMain.Create(dmNetwork); frmRadarMap := TfrmRadarMap.Create(frmMain); frmLargeScaleCommand := TfrmLargeScaleCommand.Create(frmMain); @@ -309,6 +320,7 @@ begin frmMain.ApplicationProperties1.OnIdle := nil; FreeAndNil(frmMain); end; + if FWriteMap <> nil then FreeAndNil(FWriteMap); if GameResourceManager <> nil then FreeAndNil(GameResourceManager); frmInitialize.Hide; while frmLogin.ShowModal = mrOK do @@ -328,6 +340,21 @@ begin FreeAndNil(frmLogin); end; +function TdmNetwork.CanWrite(AX, AY: Word): Boolean; +var + i: Integer; + pt: TPoint; +begin + if FWriteMap.Count = 0 then Exit(True); //TODO : still too slow + + pt := Point(AX, AY); + for i := 0 to FWriteMap.Count - 1 do + if PtInRect(FWriteMap.Rects[i], pt) then + Exit(True); + + Result := False; +end; + procedure TdmNetwork.Send(APacket: TPacket); var source: TEnhancedMemoryStream; @@ -357,6 +384,23 @@ begin end; end; +procedure TdmNetwork.UpdateWriteMap(AStream: TEnhancedMemoryStream); +var + x1, y1, x2, y2: Word; + i, areaCount: Integer; +begin + FWriteMap.Clear; + areaCount := AStream.ReadWord; + for i := 0 to areaCount - 1 do + begin + x1 := AStream.ReadWord; + y1 := AStream.ReadWord; + x2 := AStream.ReadWord; + y2 := AStream.ReadWord; + FWriteMap.Add(x1, y1, x2, y2); + end; +end; + initialization {$I UdmNetwork.lrs} diff --git a/Client/UfrmMain.lfm b/Client/UfrmMain.lfm index d1cfa1a..acbbf92 100644 --- a/Client/UfrmMain.lfm +++ b/Client/UfrmMain.lfm @@ -1028,6 +1028,7 @@ object frmMain: TfrmMain TreeOptions.MiscOptions = [toFullRepaintOnResize, toInitOnSave, toToggleOnDblClick, toWheelPanning] TreeOptions.PaintOptions = [toHideSelection, toShowButtons, toShowDropmark, toThemeAware, toUseBlendedImages] OnClick = vstChatClick + OnFreeNode = vstChatFreeNode OnGetText = vstChatGetText OnPaintText = vstChatPaintText Columns = < @@ -1253,6 +1254,7 @@ object frmMain: TfrmMain end object mnuRegionControl: TMenuItem Caption = '&Region Management' + ImageIndex = 19 OnClick = mnuRegionControlClick end object mnuLargeScaleCommands: TMenuItem @@ -1309,7 +1311,7 @@ object frmMain: TfrmMain left = 264 top = 32 Bitmap = { - 4C69130000001000000010000000000000000000000000000000000000000000 + 4C69140000001000000010000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000D9A781FFD39E76FF00000000000000000000000000000000000000000000 0000000000000000000000000000ECBEA1FFE7BB9DFFE4B697FFE0B292FFDAAE @@ -1917,7 +1919,39 @@ object frmMain: TfrmMain 000000000000000000FF000000FF000000FF000000FF00000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000FF000000FF0000000000000000000000000000 - 0000000000000000000000000000 + 0000000000000000000000000000536876FF5C6A5DFF5F6D60FF5F6D60FF5F6D + 60FF5F6D60FF5F6D61FF5F6D61FF5F6D61FF5F6D61FF606D61FF606D62FF606D + 62FF606D63FF5E6A5FFF454E46FF5C6A5DFFFBFCFBFFFCFEFCFFF7FCF8FFF7FC + F8FFF7FCF8FFF8FCF8FFF7FCF9FFF8FCF8FFF8FCF8FFECF7EEFFEDF7EEFFEFF6 + EDFFEEF4ECFFEBF4EBFF5E6A5FFF5F6D60FFF7FCF8FF9DF9F9FF6CB4EDFF6271 + FEFF80E7E9FF8CF4F4FF52CDCDFFECC2A4FFDDAD8AFFEBBA97FFDDA780FFE2AB + 83FFDAA075FFD9EAD4FF616E64FF5F6D60FFF7FCF8FF8AEAEAFF72DDDEFF5665 + F0FF569FDFFF73E8E8FF46C1C1FFBBBBA5FFD0A483FFDEB08EFFD19E7AFFD6A2 + 7AFFCF9871FFD7EBD5FF626E64FF5F6D61FFF7FCF8FF9FF9F9FF85E9EAFF84D3 + FAFF525AF0FF87F2F7FF60DAD7FF98D5CAFFE0B79CFFEDC7A9FFE0B394FFE6B8 + 98FFDEAE8CFFD7ECD6FF636E64FF5F6D61FFF8FCF8FF90EAEAFF78DDDEFF81E9 + EAFF4E6BE2FF639DEEFF5ED7D7FF5BCBC9FFD4B097FFE2BA9FFFA1ADA9FF58A5 + D8FF85B1DBFF469DD0FF4E7C8CFF5F6D61FFF8FCF8FFA6F9F9FF8BE9EAFF99F8 + FAFF78D3EBFF656BFFFF77DCEAFF70DFDEFFC1C5B5FFA8C8C8FF77BEE7FFB4D2 + F0FFE5F3FFFFACD2EFFF4A89BEFF606D61FFF8FCF8FF9FF1F1FF81DDDFFF8AEA + EBFF75DEDEFF6591EEFF557EE2FF68DCDDFF5BBCC5FF80D5EDFFB2E3F9FF8BC0 + E7FFAED3F6FFC4E0FCFF669DD0FF606D62FFF8FCF8FFAFFAFAFF94EBEBFFA2F9 + FAFF8AEAEBFF95EDF3FF595FEBFF6BCFE5FF7CD4EEFFC4F6FDFF6CDDF6FF6DCA + EDFF63A3D7FF66A1D3FF617474FF606D63FFF8FCF8FFA4EBEDFF8DDFDFFF97EB + EBFF72CFB7FF74CA99FF4790BDFF79D3EEFFC7F7FDFF5FDCF5FF5BE2F7FF7AD6 + F2FF4399DFFFB1D4D9FF646F66FF616E63FFF8FCF9FFBCFBFBFF9DE7DFFF93E1 + BBFF77C997FF63BDAEFF77CBE7FFC7F7FDFF5EDCF5FF5AE1F7FF7BD4F1FF4395 + DDFF589BC3FFD0E9DBFF646F66FF616E63FFF7FBF8FF9BDEC4FF73C393FF80CF + 9FFF53AD9CFF73B9D5FFC2F6FDFF63DFF7FF5DE2F8FF79D3F0FF4395DAFF6CB8 + A4FF74C38FFFD7EFDAFF646F66FF616E64FFECF7EEFF96DBAFFF7FC99AFF63AD + A5FF7AB6D5FF90B7D1FF55C9E4FF5BDFF5FF78D0EDFF4696D9FF76C1A1FF87D0 + A0FF80CA9AFFD6EEDAFF646F66FF626E64FFEEF8EFFFA4DBBCFF8CCAA6FF4389 + AAFFE0F2FFFF549AD8FF1A7ABEFF4998C5FF3B86BFFF6074E7FF81C5A3FF8CD0 + A6FF85CAA0FFD2E9D7FF646F67FF5F6A60FFEBF5ECFFD4EDD7FFD4EED7FF2E67 + 84FF94C7F9FF91C9F9FF4185C9FF256BACFFB7D9D4FFD4E2ECFFCFE5D6FFD5ED + D9FFD8EFDCFFD5EDD9FF616C63FF454D47FF5F6A61FF636F64FF646F64FF143F + 56FF295F86FF4988BCFF4A86A7FF5D7070FF646F66FF646F66FF646F67FF646F + 67FF647067FF616C63FF474E48FF } end object pmTileList: TPopupMenu diff --git a/Client/UfrmMain.pas b/Client/UfrmMain.pas index 1b1a19a..404db5e 100644 --- a/Client/UfrmMain.pas +++ b/Client/UfrmMain.pas @@ -247,6 +247,7 @@ type Y: Integer); procedure vdtTilesScroll(Sender: TBaseVirtualTree; DeltaX, DeltaY: Integer); procedure vstChatClick(Sender: TObject); + procedure vstChatFreeNode(Sender: TBaseVirtualTree; Node: PVirtualNode); procedure vstChatGetText(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType; var CellText: WideString); procedure vstChatPaintText(Sender: TBaseVirtualTree; @@ -283,6 +284,8 @@ type procedure SetY(const AValue: Integer); procedure SetCurrentTile(const AValue: TWorldItem); procedure SetSelectedTile(const AValue: TWorldItem); + procedure SetNormalLights; inline; + procedure SetDarkLights; inline; procedure InitRender; procedure InitSize; procedure Render; @@ -1373,6 +1376,15 @@ begin edChat.SetFocus; end; +procedure TfrmMain.vstChatFreeNode(Sender: TBaseVirtualTree; Node: PVirtualNode); +var + chatInfo: PChatInfo; +begin + chatInfo := Sender.GetNodeData(Node); + chatInfo^.Sender := ''; + chatInfo^.Msg := ''; +end; + procedure TfrmMain.vstChatGetText(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType; var CellText: WideString); var @@ -1557,11 +1569,27 @@ begin FSelectedTile.OnDestroy.RegisterEvent(@TileRemoved); end; +procedure TfrmMain.SetNormalLights; +const + specular: TGLArrayf4 = (2, 2, 2, 1); + ambient: TGLArrayf4 = (1, 1, 1, 1); +begin + glLightfv(GL_LIGHT0, GL_AMBIENT, @specular); + glLightModelfv(GL_LIGHT_MODEL_AMBIENT, @ambient); +end; + +procedure TfrmMain.SetDarkLights; +const + specularDark: TGLArrayf4 = (0.5, 0.5, 0.5, 1); + ambientDark: TGLArrayf4 = (0.25, 0.25, 0.25, 1); +begin + glLightfv(GL_LIGHT0, GL_AMBIENT, @specularDark); + glLightModelfv(GL_LIGHT_MODEL_AMBIENT, @ambientDark); +end; + procedure TfrmMain.InitRender; const lightPosition: TGLArrayf4 = (-1, -1, 0.5, 0); - specular: TGLArrayf4 = (2, 2, 2, 1); - ambient: TGLArrayf4 = (1, 1, 1, 1); begin glEnable(GL_ALPHA_TEST); glAlphaFunc(GL_GREATER, 0.1); @@ -1574,8 +1602,6 @@ begin glEnable(GL_LIGHT0); glLightfv(GL_LIGHT0, GL_POSITION, @lightPosition); - glLightfv(GL_LIGHT0, GL_AMBIENT, @specular); - glLightModelfv(GL_LIGHT_MODEL_AMBIENT, @ambient); glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE); end; @@ -1612,6 +1638,8 @@ var tileRect: TRect; virtualTile: TVirtualTile; staticsFilter: TStaticFilter; + editing: Boolean; + intensity: GLfloat; procedure GetMapDrawOffset(x, y: Integer; out drawX, drawY: Single); begin @@ -1667,7 +1695,19 @@ begin (CurrentTile <> SelectedTile) and PtInRect(tileRect, Point(FX + offsetX, FY + offsetY)); - if acDraw.Checked and (singleTarget or multiTarget) then + if acSelect.Checked or dmNetwork.CanWrite(FX + offsetX, FY + offsetY) then + begin + editing := True; + intensity := 1.0; + SetNormalLights; + end else + begin + editing := False; + intensity := 0.5; + SetDarkLights; + end; + + if editing and acDraw.Checked and (singleTarget or multiTarget) then begin ghostTile := FGhostTile; if (ghostTile is TMapCell) and (not frmDrawSettings.cbForceAltitude.Checked) then @@ -1691,7 +1731,9 @@ begin for i := 0 to draw.Count - 1 do begin - if TObject(draw[i]) = virtualTile then + if not editing then + highlight := False + else if TObject(draw[i]) = virtualTile then highlight := False else if acDelete.Checked and multiTarget and (TObject(draw[i]) is TStaticItem) then highlight := True @@ -1715,8 +1757,8 @@ begin z := 0 else z := TWorldItem(draw[i]).Z; - - glColor4f(1.0, 1.0, 1.0, 1.0); + + glColor4f(intensity, intensity, intensity, 1.0); if TObject(draw[i]) = virtualTile then begin @@ -1734,7 +1776,7 @@ begin cell := TMapCell(draw[i]); {if ResMan.Tiledata.LandTiles[cell.TileID].HasFlag(tdfTranslucent) then - glColor4f(1.0, 1.0, 1.0, 0.5);} //Possible, but probably not like the OSI client + glColor4f(intensity, intensity, intensity, 0.5);} //Possible, but probably not like the OSI client mat := nil; @@ -1773,6 +1815,7 @@ begin (TObject(draw[i]) = ghostTile) then //when we have a ghosttile, only draw that, but still store the real one begin glBindTexture(GL_TEXTURE_2D, mat.Texture); + //if (not cell.Selected) and (intensity = 1.0) then if not cell.Selected then glEnable(GL_LIGHTING); normals := FLandscape.Normals[offsetX, offsetY]; @@ -1790,6 +1833,7 @@ begin glNormal3f(normals[3].X, normals[3].Y, normals[3].Z); glTexCoord2f(0, 1); glVertex2d(drawX - 22, drawY + 22 - west * 4); glEnd; + //if (not cell.Selected) and (intensity = 1.0) then if not cell.Selected then glDisable(GL_LIGHTING); end; @@ -1814,7 +1858,7 @@ begin hue := nil; if staticTileData.HasFlag(tdfTranslucent) then - glColor4f(1.0, 1.0, 1.0, 0.5); + glColor4f(intensity, intensity, intensity, 0.5); mat := FTextureManager.GetArtMaterial($4000 + staticItem.TileID, hue, (staticTileData.Flags and tdfPartialHue) = tdfPartialHue); south := mat.RealHeight; @@ -2090,6 +2134,7 @@ procedure TfrmMain.OnClientHandlingPacket(ABuffer: TEnhancedMemoryStream); var sender, msg: string; i: Integer; + accessLevel: TAccessLevel; begin case ABuffer.ReadByte of $01: //client connected @@ -2124,21 +2169,27 @@ begin msg := ABuffer.ReadStringNull; WriteChatMessage(sender, msg); end; - $07: //access level changed + $07: //access changed begin - dmNetwork.AccessLevel := TAccessLevel(ABuffer.ReadByte); - if dmNetwork.AccessLevel = alNone then + accessLevel := TAccessLevel(ABuffer.ReadByte); + dmNetwork.UpdateWriteMap(ABuffer); + + if accessLevel <> dmNetwork.AccessLevel then begin - MessageDlg('AccessLevel change', 'Your account has been locked.', mtWarning, [mbOK], 0); - mnuDisconnectClick(nil); - end else - begin - ProcessAccessLevel; - MessageDlg('AccessLevel change', Format('Your accesslevel has been changed to %s.', [GetAccessLevelString(dmNetwork.AccessLevel)]), mtWarning, [mbOK], 0); + dmNetwork.AccessLevel := accessLevel; + if accessLevel = alNone then + begin + MessageDlg('AccessLevel change', 'Your account has been locked.', mtWarning, [mbOK], 0); + mnuDisconnectClick(nil); + end else + begin + ProcessAccessLevel; + MessageDlg('AccessLevel change', Format('Your accesslevel has been changed to %s.', [GetAccessLevelString(accessLevel)]), mtWarning, [mbOK], 0); + end; end; for i := Low(FAccessChangedListeners) to High(FAccessChangedListeners) do - FAccessChangedListeners[i](dmNetwork.AccessLevel); + FAccessChangedListeners[i](accessLevel); end; end; end; @@ -2189,7 +2240,8 @@ end; function TfrmMain.CanBeModified(ATile: TWorldItem): Boolean; begin - Result := not (ATile is TVirtualTile); + Result := (not (ATile is TVirtualTile)) and + dmNetwork.CanWrite(ATile.X, ATile.Y); end; initialization diff --git a/Client/UfrmRegionControl.pas b/Client/UfrmRegionControl.pas index 39d72cc..b725bb4 100644 --- a/Client/UfrmRegionControl.pas +++ b/Client/UfrmRegionControl.pas @@ -122,7 +122,7 @@ implementation uses UGameResources, UfrmRadar, UfrmMain, UdmNetwork, UPacket, UGUIPlatformUtils, - UAdminHandling, UPacketHandlers, UConsts; + UAdminHandling, UPacketHandlers; type { TModifyRegionPacket } diff --git a/Server/UAccount.pas b/Server/UAccount.pas index b94c8f0..14e5b8c 100644 --- a/Server/UAccount.pas +++ b/Server/UAccount.pas @@ -162,7 +162,7 @@ end; procedure TAccount.Serialize(AElement: TDOMElement); var i: Integer; - child: TDOMElement; + child, regionNode: TDOMElement; begin TXmlHelper.WriteString(AElement, 'Name', FName); TXmlHelper.WriteString(AElement, 'PasswordHash', FPasswordHash); @@ -171,7 +171,11 @@ begin child := TXmlHelper.AssureElement(AElement, 'Regions'); for i := 0 to FRegions.Count -1 do if Config.Regions.Find(FRegions[i]) <> nil then //Validate if the region (still) exists - TXmlHelper.WriteString(child, 'Region', FRegions[i]); + begin + regionNode := child.OwnerDocument.CreateElement('Region'); + child.AppendChild(regionNode); + regionNode.AppendChild(regionNode.OwnerDocument.CreateTextNode(FRegions[i])); + end; end; { TAccountList } diff --git a/Server/UAdminHandling.pas b/Server/UAdminHandling.pas index 72682a4..149e17c 100644 --- a/Server/UAdminHandling.pas +++ b/Server/UAdminHandling.pas @@ -148,25 +148,24 @@ begin if password <> '' then account.PasswordHash := MD5Print(MD5String(password)); + account.AccessLevel := accessLevel; + account.Regions.Clear; for i := 0 to regionCount - 1 do account.Regions.Add(ABuffer.ReadStringNull); account.Invalidate; - if account.AccessLevel <> accessLevel then + CEDServerInstance.TCPServer.IterReset; + while CEDServerInstance.TCPServer.IterNext do begin - account.AccessLevel := accessLevel; - CEDServerInstance.TCPServer.IterReset; - while CEDServerInstance.TCPServer.IterNext do + netState := TNetState(CEDServerInstance.TCPServer.Iterator.UserData); + if (netState <> nil) and (netState.Account = account) then begin - netState := TNetState(CEDServerInstance.TCPServer.Iterator.UserData); - if (netState <> nil) and (netState.Account = account) then - begin - CEDServerInstance.SendPacket(netState, - TAccessLevelChangedPacket.Create(accessLevel)); - end; + CEDServerInstance.SendPacket(netState, + TAccessChangedPacket.Create(account)); end; end; + CEDServerInstance.SendPacket(ANetState, TModifyUserResponsePacket.Create(muModified, account)); end else @@ -238,6 +237,10 @@ var status: TModifyRegionStatus; i, areaCount: Integer; x1, y1, x2, y2: Word; + + account: TAccount; + needsUpdate: Boolean; + netState: TNetState; begin regionName := ABuffer.ReadStringNull; @@ -268,6 +271,31 @@ begin AdminBroadcast(alAdministrator, TModifyRegionResponsePacket.Create(status, region)); + + if status = mrModified then + begin + CEDServerInstance.TCPServer.IterReset; + while CEDServerInstance.TCPServer.IterNext do + begin + netState := TNetState(CEDServerInstance.TCPServer.Iterator.UserData); + if netState <> nil then + begin + account := netState.Account; + i := 0; + needsUpdate := False; + while (i < account.Regions.Count) and (not needsUpdate) do + begin + if account.Regions.Strings[i] = regionName then + needsUpdate := True; + Inc(i); + end; + + if needsUpdate then + CEDServerInstance.SendPacket(netState, + TAccessChangedPacket.Create(account)) + end; + end; + end; end; procedure OnDeleteRegionPacket(ABuffer: TEnhancedMemoryStream; diff --git a/Server/UClientHandling.pas b/Server/UClientHandling.pas index 6c70cdc..6c614ba 100644 --- a/Server/UClientHandling.pas +++ b/Server/UClientHandling.pas @@ -21,7 +21,7 @@ * CDDL HEADER END * * - * Portions Copyright 2007 Andreas Schneider + * Portions Copyright 2008 Andreas Schneider *) unit UClientHandling; @@ -31,7 +31,7 @@ interface uses Classes, SysUtils, UPacket, UPacketHandlers, UConfig, UAccount, UNetState, - UEnhancedMemoryStream, UEnums, math; + UEnhancedMemoryStream, UEnums, Math; type @@ -65,16 +65,23 @@ type constructor Create(ASender, AMessage: string); end; - { TAccessLevelChangedPacket } + { TAccessChangedPacket } - TAccessLevelChangedPacket = class(TPacket) - constructor Create(AAccessLevel: TAccessLevel); + TAccessChangedPacket = class(TPacket) + constructor Create(AAccount: TAccount); end; -procedure OnClientHandlerPacket(ABuffer: TEnhancedMemoryStream; ANetState: TNetState); -procedure OnUpdateClientPosPacket(ABuffer: TEnhancedMemoryStream; ANetState: TNetState); -procedure OnChatMessagePacket(ABuffer: TEnhancedMemoryStream; ANetState: TNetState); -procedure OnGotoClientPosPacket(ABuffer: TEnhancedMemoryStream; ANetState: TNetState); +procedure OnClientHandlerPacket(ABuffer: TEnhancedMemoryStream; + ANetState: TNetState); +procedure OnUpdateClientPosPacket(ABuffer: TEnhancedMemoryStream; + ANetState: TNetState); +procedure OnChatMessagePacket(ABuffer: TEnhancedMemoryStream; + ANetState: TNetState); +procedure OnGotoClientPosPacket(ABuffer: TEnhancedMemoryStream; + ANetState: TNetState); + +procedure WriteAccountRestrictions(AStream: TEnhancedMemoryStream; + AAccount: TAccount); var ClientPacketHandlers: array[0..$FF] of TPacketHandler; @@ -82,9 +89,10 @@ var implementation uses - UCEDServer, UPackets; + UCEDServer, UPackets, URegions; -procedure OnClientHandlerPacket(ABuffer: TEnhancedMemoryStream; ANetState: TNetState); +procedure OnClientHandlerPacket(ABuffer: TEnhancedMemoryStream; + ANetState: TNetState); var packetHandler: TPacketHandler; begin @@ -118,7 +126,46 @@ var begin account := Config.Accounts.Find(ABuffer.ReadStringNull); if account <> nil then - CEDServerInstance.SendPacket(ANetState, TSetClientPosPacket.Create(account.LastPos)); + CEDServerInstance.SendPacket(ANetState, + TSetClientPosPacket.Create(account.LastPos)); +end; + +procedure WriteAccountRestrictions(AStream: TEnhancedMemoryStream; + AAccount: TAccount); +var + areaCount: Word; + i, j, offset, newOffset: Integer; + region: TRegion; + area: TRect; +begin + offset := AStream.Position; + areaCount := 0; + AStream.WriteWord(areaCount); + + if AAccount.AccessLevel >= alAdministrator then + Exit; //Admins shouldn't have restrictions anyway + + for i := 0 to AAccount.Regions.Count - 1 do + begin + region := Config.Regions.Find(AAccount.Regions.Strings[i]); + if region <> nil then + for j := 0 to region.Areas.Count - 1 do + begin + area := region.Areas.Rects[j]; + AStream.WriteWord(area.Left); + AStream.WriteWord(area.Top); + AStream.WriteWord(area.Right); + AStream.WriteWord(area.Bottom); + Inc(areaCount); + end; + end; + if areaCount > 0 then + begin + newOffset := AStream.Position; + AStream.Position := offset; + AStream.WriteWord(areaCount); + AStream.Position := newOffset; + end; end; { TClientConnectedPacket } @@ -152,7 +199,8 @@ begin begin repeat netState := TNetState(CEDServerInstance.TCPServer.Iterator.UserData); - if (netState <> nil) and (netState <> AAvoid) and (netState.Account <> nil) then + if (netState <> nil) and (netState <> AAvoid) and + (netState.Account <> nil) then FStream.WriteStringNull(netState.Account.Name); until not CEDServerInstance.TCPServer.IterNext; end; @@ -178,13 +226,14 @@ begin FStream.WriteStringNull(AMessage); end; -{ TAccessLevelChangedPacket } +{ TAccessChangedPacket } -constructor TAccessLevelChangedPacket.Create(AAccessLevel: TAccessLevel); +constructor TAccessChangedPacket.Create(AAccount: TAccount); begin inherited Create($0C, 0); FStream.WriteByte($07); - FStream.WriteByte(Byte(AAccessLevel)); + FStream.WriteByte(Byte(AAccount.AccessLevel)); + WriteAccountRestrictions(FStream, AAccount); end; {$WARNINGS OFF} diff --git a/Server/UConnectionHandling.pas b/Server/UConnectionHandling.pas index 28a7f20..e56520d 100644 --- a/Server/UConnectionHandling.pas +++ b/Server/UConnectionHandling.pas @@ -44,7 +44,7 @@ type { TLoginResponsePacket } TLoginResponsePacket = class(TPacket) - constructor Create(AState: TLoginState; AAccessLevel: TAccessLevel = alNone); + constructor Create(AState: TLoginState; AAccount: TAccount = nil); end; { TServerStatePacket } @@ -111,7 +111,7 @@ begin begin Writeln(TimeStamp, 'Login (', username, '): ', ANetState.Socket.PeerAddress); ANetState.Account := account; - CEDServerInstance.SendPacket(ANetState, TLoginResponsePacket.Create(lsOK, account.AccessLevel)); + CEDServerInstance.SendPacket(ANetState, TLoginResponsePacket.Create(lsOK, account)); CEDServerInstance.SendPacket(ANetState, TCompressedPacket.Create( TClientListPacket.Create(ANetState))); CEDServerInstance.SendPacket(nil, TClientConnectedPacket.Create(username)); @@ -154,16 +154,17 @@ end; { TLoginResponsePacket } constructor TLoginResponsePacket.Create(AState: TLoginState; - AAccessLevel: TAccessLevel = alNone); + AAccount: TAccount = nil); begin inherited Create($02, 0); FStream.WriteByte($03); FStream.WriteByte(Byte(AState)); if AState = lsOK then begin - FStream.WriteByte(Byte(AAccessLevel)); + FStream.WriteByte(Byte(AAccount.AccessLevel)); FStream.WriteWord(Config.Map.Width); FStream.WriteWord(Config.Map.Height); + WriteAccountRestrictions(FStream, AAccount); end; end; diff --git a/Server/UPacketHandlers.pas b/Server/UPacketHandlers.pas index 0c4fd84..c859ef4 100644 --- a/Server/UPacketHandlers.pas +++ b/Server/UPacketHandlers.pas @@ -85,8 +85,10 @@ begin for j := 0 to region.Areas.Count - 1 do begin rect := region.Areas.Rects[j]; - if InRange(AX, rect.Left, rect.Right) and - InRange(AY, rect.Top, rect.Bottom) then + if (AX >= rect.Left) and + (AX < rect.Right) and + (AY >= rect.Top) and + (AY < rect.Bottom) then Exit(True); end; end; diff --git a/Server/cedserver.lpr b/Server/cedserver.lpr index 2a5b974..1ec6aa5 100644 --- a/Server/cedserver.lpr +++ b/Server/cedserver.lpr @@ -40,7 +40,7 @@ uses begin Writeln(''); - Writeln('UO CentrED Server Version ', ProductVersion); + Writeln('CentrED Server Version ', ProductVersion); Writeln('Copyright ', Copyright); //Writeln('================================'); Writeln('');