- 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
This commit is contained in:
2008-08-26 22:48:48 +02:00
parent 91af86a294
commit 1c3d624949
10 changed files with 274 additions and 60 deletions

View File

@@ -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 }

View File

@@ -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;

View File

@@ -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}

View File

@@ -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;

View File

@@ -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;

View File

@@ -40,7 +40,7 @@ uses
begin
Writeln('');
Writeln('UO CentrED Server Version ', ProductVersion);
Writeln('CentrED Server Version ', ProductVersion);
Writeln('Copyright ', Copyright);
//Writeln('================================');
Writeln('');