* Optimized sending of terrain data

* Send terrain data in a spiral pattern instead of a typewriter pattern (placeholder until terrain data becomes part of the interest list management)
* Added a debug line when resent packets are being sent
prioritization
John Hurliman 2009-10-19 18:50:31 -07:00
parent fdce1be3db
commit 0a6ea33ac8
2 changed files with 180 additions and 155 deletions

View File

@ -45,7 +45,7 @@ using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Scenes;
using OpenSim.Region.Framework.Scenes.Hypergrid; using OpenSim.Region.Framework.Scenes.Hypergrid;
using OpenSim.Services.Interfaces; using OpenSim.Services.Interfaces;
using Timer=System.Timers.Timer; using Timer = System.Timers.Timer;
using AssetLandmark = OpenSim.Framework.AssetLandmark; using AssetLandmark = OpenSim.Framework.AssetLandmark;
using Nini.Config; using Nini.Config;
@ -342,7 +342,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
protected UUID m_activeGroupID; protected UUID m_activeGroupID;
protected string m_activeGroupName = String.Empty; protected string m_activeGroupName = String.Empty;
protected ulong m_activeGroupPowers; protected ulong m_activeGroupPowers;
protected Dictionary<UUID,ulong> m_groupPowers = new Dictionary<UUID, ulong>(); protected Dictionary<UUID, ulong> m_groupPowers = new Dictionary<UUID, ulong>();
protected int m_terrainCheckerCount; protected int m_terrainCheckerCount;
protected uint m_agentFOVCounter; protected uint m_agentFOVCounter;
@ -621,7 +621,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
} }
// Sound // Sound
public void SoundTrigger(UUID soundId, UUID owerid, UUID Objectid,UUID ParentId,float Gain, Vector3 Position,UInt64 Handle) public void SoundTrigger(UUID soundId, UUID owerid, UUID Objectid, UUID ParentId, float Gain, Vector3 Position, UInt64 Handle)
{ {
} }
@ -800,32 +800,55 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// <param name="o"></param> /// <param name="o"></param>
private void DoSendLayerData(object o) private void DoSendLayerData(object o)
{ {
float[] map = (float[])o; float[] map = LLHeightFieldMoronize((float[])o);
try try
{ {
for (int y = 0; y < 16; y++) //for (int y = 0; y < 16; y++)
{
// For some terrains, sending more than one terrain patch at once results in a libsecondlife exception
// see http://opensimulator.org/mantis/view.php?id=1662
//for (int x = 0; x < 16; x += 4)
//{ //{
// SendLayerPacket(map, y, x); // for (int x = 0; x < 16; x++)
// Thread.Sleep(150); // {
// SendLayerData(x, y, map);
// }
//} //}
for (int x = 0; x < 16; x++)
{ // Send LayerData in a spiral pattern. Fun!
SendLayerData(x, y, LLHeightFieldMoronize(map)); SendLayerTopRight(map, 0, 0, 15, 15);
Thread.Sleep(35);
}
}
} }
catch (Exception e) catch (Exception e)
{ {
m_log.Warn("[CLIENT]: ClientView.API.cs: SendLayerData() - Failed with exception " + e); m_log.Error("[CLIENT]: SendLayerData() Failed with exception: " + e.Message, e);
} }
} }
private void SendLayerTopRight(float[] map, int x1, int y1, int x2, int y2)
{
// Row
for (int i = x1; i <= x2; i++)
SendLayerData(i, y1, map);
// Column
for (int j = y1 + 1; j <= y2; j++)
SendLayerData(x2, j, map);
if (x2 - x1 > 0)
SendLayerBottomLeft(map, x1, y1 + 1, x2 - 1, y2);
}
void SendLayerBottomLeft(float[] map, int x1, int y1, int x2, int y2)
{
// Row in reverse
for (int i = x2; i >= x1; i--)
SendLayerData(i, y2, map);
// Column in reverse
for (int j = y2 - 1; j >= y1; j--)
SendLayerData(x1, j, map);
if (x2 - x1 > 0)
SendLayerTopRight(map, x1 + 1, y1, x2, y2 - 1);
}
/// <summary> /// <summary>
/// Sends a set of four patches (x, x+1, ..., x+3) to the client /// Sends a set of four patches (x, x+1, ..., x+3) to the client
/// </summary> /// </summary>
@ -854,22 +877,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP
{ {
try try
{ {
int[] patches = new int[1]; int[] patches = new int[] { py * 16 + px };
int patchx, patchy; float[] heightmap = (map.Length == 65536) ?
patchx = px; map :
patchy = py; LLHeightFieldMoronize(map);
patches[0] = patchx + 0 + patchy * 16; LayerDataPacket layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches);
layerpack.Header.Reliable = true;
LayerDataPacket layerpack = TerrainCompressor.CreateLandPacket(((map.Length==65536)? map : LLHeightFieldMoronize(map)), patches);
layerpack.Header.Zerocoded = true;
OutPacket(layerpack, ThrottleOutPacketType.Land); OutPacket(layerpack, ThrottleOutPacketType.Land);
} }
catch (Exception e) catch (Exception e)
{ {
m_log.Warn("[client]: ClientView.API.cs: SendLayerData() - Failed with exception " + e.ToString()); m_log.Error("[CLIENT]: SendLayerData() Failed with exception: " + e.Message, e);
} }
} }
@ -898,7 +918,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
Array.Copy(map, i * (int)Constants.RegionSize, returnmap, i * 256, 256); Array.Copy(map, i * (int)Constants.RegionSize, returnmap, i * 256, 256);
} }
//Array.Copy(map,0,returnmap,0,(map.Length < 65536)? map.Length : 65536); //Array.Copy(map,0,returnmap,0,(map.Length < 65536)? map.Length : 65536);
return returnmap; return returnmap;
@ -1017,7 +1036,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
return agentData; return agentData;
agentData.CapsPath = capsModule.GetCapsPath(m_agentId); agentData.CapsPath = capsModule.GetCapsPath(m_agentId);
agentData.ChildrenCapSeeds = new Dictionary<ulong,string>(capsModule.GetChildrenSeeds(m_agentId)); agentData.ChildrenCapSeeds = new Dictionary<ulong, string>(capsModule.GetChildrenSeeds(m_agentId));
return agentData; return agentData;
} }
@ -3100,9 +3119,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
awb.ItemID = wearables[i].ItemID; awb.ItemID = wearables[i].ItemID;
aw.WearableData[i] = awb; aw.WearableData[i] = awb;
// m_log.DebugFormat( // m_log.DebugFormat(
// "[APPEARANCE]: Sending wearable item/asset {0} {1} (index {2}) for {3}", // "[APPEARANCE]: Sending wearable item/asset {0} {1} (index {2}) for {3}",
// awb.ItemID, awb.AssetID, i, Name); // awb.ItemID, awb.AssetID, i, Name);
} }
OutPacket(aw, ThrottleOutPacketType.Task); OutPacket(aw, ThrottleOutPacketType.Task);
@ -3817,7 +3836,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
public void SendBannedUserList(UUID invoice, EstateBan[] bl, uint estateID) public void SendBannedUserList(UUID invoice, EstateBan[] bl, uint estateID)
{ {
List<UUID>BannedUsers = new List<UUID>(); List<UUID> BannedUsers = new List<UUID>();
for (int i = 0; i < bl.Length; i++) for (int i = 0; i < bl.Length; i++)
{ {
@ -4448,7 +4467,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
private bool HandleMoneyTransferRequest(IClientAPI sender, Packet Pack) private bool HandleMoneyTransferRequest(IClientAPI sender, Packet Pack)
{ {
MoneyTransferRequestPacket money = (MoneyTransferRequestPacket) Pack; MoneyTransferRequestPacket money = (MoneyTransferRequestPacket)Pack;
// validate the agent owns the agentID and sessionID // validate the agent owns the agentID and sessionID
if (money.MoneyData.SourceID == sender.AgentId && money.AgentData.AgentID == sender.AgentId && if (money.MoneyData.SourceID == sender.AgentId && money.AgentData.AgentID == sender.AgentId &&
money.AgentData.SessionID == sender.SessionId) money.AgentData.SessionID == sender.SessionId)
@ -4469,7 +4488,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
private bool HandleParcelBuyRequest(IClientAPI sender, Packet Pack) private bool HandleParcelBuyRequest(IClientAPI sender, Packet Pack)
{ {
ParcelBuyPacket parcel = (ParcelBuyPacket) Pack; ParcelBuyPacket parcel = (ParcelBuyPacket)Pack;
if (parcel.AgentData.AgentID == AgentId && parcel.AgentData.SessionID == SessionId) if (parcel.AgentData.AgentID == AgentId && parcel.AgentData.SessionID == SessionId)
{ {
ParcelBuy handlerParcelBuy = OnParcelBuy; ParcelBuy handlerParcelBuy = OnParcelBuy;
@ -4505,7 +4524,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
public bool HandleGenericMessage(IClientAPI sender, Packet pack) public bool HandleGenericMessage(IClientAPI sender, Packet pack)
{ {
GenericMessagePacket gmpack = (GenericMessagePacket) pack; GenericMessagePacket gmpack = (GenericMessagePacket)pack;
if (m_genericPacketHandlers.Count == 0) return false; if (m_genericPacketHandlers.Count == 0) return false;
if (gmpack.AgentData.SessionID != SessionId) return false; if (gmpack.AgentData.SessionID != SessionId) return false;
@ -4773,7 +4792,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
UpdateVector handlerUpdatePrimScale = OnUpdatePrimScale; UpdateVector handlerUpdatePrimScale = OnUpdatePrimScale;
if (handlerUpdatePrimScale != null) if (handlerUpdatePrimScale != null)
{ {
// m_log.Debug("new scale is " + scale4.X + " , " + scale4.Y + " , " + scale4.Z); // m_log.Debug("new scale is " + scale4.X + " , " + scale4.Y + " , " + scale4.Z);
handlerUpdatePrimScale(localId, scale4, this); handlerUpdatePrimScale(localId, scale4, this);
} }
break; break;
@ -4835,7 +4854,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
UpdateVector handlerUpdatePrimGroupScale = OnUpdatePrimGroupScale; UpdateVector handlerUpdatePrimGroupScale = OnUpdatePrimGroupScale;
if (handlerUpdatePrimGroupScale != null) if (handlerUpdatePrimGroupScale != null)
{ {
// m_log.Debug("new scale is " + scale7.X + " , " + scale7.Y + " , " + scale7.Z); // m_log.Debug("new scale is " + scale7.X + " , " + scale7.Y + " , " + scale7.Z);
handlerUpdatePrimGroupScale(localId, scale7, this); handlerUpdatePrimGroupScale(localId, scale7, this);
} }
break; break;
@ -5318,7 +5337,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
break; break;
case PacketType.DeRezObject: case PacketType.DeRezObject:
DeRezObjectPacket DeRezPacket = (DeRezObjectPacket) Pack; DeRezObjectPacket DeRezPacket = (DeRezObjectPacket)Pack;
#region Packet Session and User Check #region Packet Session and User Check
if (m_checkPackets) if (m_checkPackets)
@ -6096,7 +6115,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
ObjectExtraParams handlerUpdateExtraParams = OnUpdateExtraParams; ObjectExtraParams handlerUpdateExtraParams = OnUpdateExtraParams;
if (handlerUpdateExtraParams != null) if (handlerUpdateExtraParams != null)
{ {
for (int i = 0 ; i < extraPar.ObjectData.Length ; i++) for (int i = 0; i < extraPar.ObjectData.Length; i++)
{ {
handlerUpdateExtraParams(m_agentId, extraPar.ObjectData[i].ObjectLocalID, handlerUpdateExtraParams(m_agentId, extraPar.ObjectData[i].ObjectLocalID,
extraPar.ObjectData[i].ParamType, extraPar.ObjectData[i].ParamType,
@ -6816,7 +6835,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
if (ti.OwnerID != AgentId) if (ti.OwnerID != AgentId)
break; break;
if ((ti.CurrentPermissions & ((uint)PermissionMask.Modify| (uint)PermissionMask.Copy | (uint)PermissionMask.Transfer)) != ((uint)PermissionMask.Modify| (uint)PermissionMask.Copy | (uint)PermissionMask.Transfer)) if ((ti.CurrentPermissions & ((uint)PermissionMask.Modify | (uint)PermissionMask.Copy | (uint)PermissionMask.Transfer)) != ((uint)PermissionMask.Modify | (uint)PermissionMask.Copy | (uint)PermissionMask.Transfer))
break; break;
if (ti.AssetID != requestID) if (ti.AssetID != requestID)
@ -8022,21 +8041,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP
convertParamStringToBool(messagePacket.ParamList[7].Parameter), convertParamStringToBool(messagePacket.ParamList[8].Parameter)); convertParamStringToBool(messagePacket.ParamList[7].Parameter), convertParamStringToBool(messagePacket.ParamList[8].Parameter));
} }
break; break;
// case "texturebase": // case "texturebase":
// if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) // if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false))
// { // {
// foreach (EstateOwnerMessagePacket.ParamListBlock block in messagePacket.ParamList) // foreach (EstateOwnerMessagePacket.ParamListBlock block in messagePacket.ParamList)
// { // {
// string s = Utils.BytesToString(block.Parameter); // string s = Utils.BytesToString(block.Parameter);
// string[] splitField = s.Split(' '); // string[] splitField = s.Split(' ');
// if (splitField.Length == 2) // if (splitField.Length == 2)
// { // {
// UUID tempUUID = new UUID(splitField[1]); // UUID tempUUID = new UUID(splitField[1]);
// OnSetEstateTerrainBaseTexture(this, Convert.ToInt16(splitField[0]), tempUUID); // OnSetEstateTerrainBaseTexture(this, Convert.ToInt16(splitField[0]), tempUUID);
// } // }
// } // }
// } // }
// break; // break;
case "texturedetail": case "texturedetail":
if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false))
{ {
@ -8628,8 +8647,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
MapItemRequest handlerMapItemRequest = OnMapItemRequest; MapItemRequest handlerMapItemRequest = OnMapItemRequest;
if (handlerMapItemRequest != null) if (handlerMapItemRequest != null)
{ {
handlerMapItemRequest(this,mirpk.AgentData.Flags, mirpk.AgentData.EstateID, handlerMapItemRequest(this, mirpk.AgentData.Flags, mirpk.AgentData.EstateID,
mirpk.AgentData.Godlike,mirpk.RequestData.ItemType, mirpk.AgentData.Godlike, mirpk.RequestData.ItemType,
mirpk.RequestData.RegionHandle); mirpk.RequestData.RegionHandle);
} }
@ -9037,7 +9056,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
groupMembersRequestPacket.GroupData.RequestID; groupMembersRequestPacket.GroupData.RequestID;
groupMembersReply.GroupData.MemberCount = memberCount; groupMembersReply.GroupData.MemberCount = memberCount;
for (int i = 0 ; i < blockCount ; i++) for (int i = 0; i < blockCount; i++)
{ {
GroupMembersData m = members[0]; GroupMembersData m = members[0];
members.RemoveAt(0); members.RemoveAt(0);
@ -9174,7 +9193,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
groupRoleMembersReply.MemberData = groupRoleMembersReply.MemberData =
new GroupRoleMembersReplyPacket.MemberDataBlock[pairs]; new GroupRoleMembersReplyPacket.MemberDataBlock[pairs];
for (int i = 0 ; i < pairs ; i++) for (int i = 0; i < pairs; i++)
{ {
GroupRoleMembersData d = mappings[0]; GroupRoleMembersData d = mappings[0];
mappings.RemoveAt(0); mappings.RemoveAt(0);
@ -9301,7 +9320,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
ParcelDeedToGroup handlerParcelDeedToGroup = OnParcelDeedToGroup; ParcelDeedToGroup handlerParcelDeedToGroup = OnParcelDeedToGroup;
if (handlerParcelDeedToGroup != null) if (handlerParcelDeedToGroup != null)
{ {
handlerParcelDeedToGroup(parcelDeedToGroup.Data.LocalID, parcelDeedToGroup.Data.GroupID,this); handlerParcelDeedToGroup(parcelDeedToGroup.Data.LocalID, parcelDeedToGroup.Data.GroupID, this);
} }
} }
@ -9935,7 +9954,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
{ {
ParcelMediaCommandMessagePacket commandMessagePacket = new ParcelMediaCommandMessagePacket(); ParcelMediaCommandMessagePacket commandMessagePacket = new ParcelMediaCommandMessagePacket();
commandMessagePacket.CommandBlock.Flags = flags; commandMessagePacket.CommandBlock.Flags = flags;
commandMessagePacket.CommandBlock.Command =(uint) command; commandMessagePacket.CommandBlock.Command = (uint)command;
commandMessagePacket.CommandBlock.Time = time; commandMessagePacket.CommandBlock.Time = time;
OutPacket(commandMessagePacket, ThrottleOutPacketType.Unknown); OutPacket(commandMessagePacket, ThrottleOutPacketType.Unknown);
@ -9963,7 +9982,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
#region Camera #region Camera
public void SendSetFollowCamProperties (UUID objectID, SortedDictionary<int, float> parameters) public void SendSetFollowCamProperties(UUID objectID, SortedDictionary<int, float> parameters)
{ {
SetFollowCamPropertiesPacket packet = (SetFollowCamPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.SetFollowCamProperties); SetFollowCamPropertiesPacket packet = (SetFollowCamPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.SetFollowCamProperties);
packet.ObjectData.ObjectID = objectID; packet.ObjectData.ObjectID = objectID;
@ -9981,7 +10000,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
OutPacket(packet, ThrottleOutPacketType.Task); OutPacket(packet, ThrottleOutPacketType.Task);
} }
public void SendClearFollowCamProperties (UUID objectID) public void SendClearFollowCamProperties(UUID objectID)
{ {
ClearFollowCamPropertiesPacket packet = (ClearFollowCamPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ClearFollowCamProperties); ClearFollowCamPropertiesPacket packet = (ClearFollowCamPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ClearFollowCamProperties);
packet.ObjectData.ObjectID = objectID; packet.ObjectData.ObjectID = objectID;
@ -10381,7 +10400,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
#endregion #endregion
#region LookupItem #region LookupItem
private struct LookupItem { private struct LookupItem
{
internal MinHeap<MinHeapItem> Heap; internal MinHeap<MinHeapItem> Heap;
internal IHandle Handle; internal IHandle Handle;
} }

View File

@ -372,8 +372,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
public void ResendUnacked(LLUDPClient udpClient) public void ResendUnacked(LLUDPClient udpClient)
{ {
if (udpClient.IsConnected && udpClient.NeedAcks.Count > 0) if (!udpClient.IsConnected)
{ return;
// Disconnect an agent if no packets are received for some time // Disconnect an agent if no packets are received for some time
//FIXME: Make 60 an .ini setting //FIXME: Make 60 an .ini setting
if (Environment.TickCount - udpClient.TickLastPacketReceived > 1000 * 60) if (Environment.TickCount - udpClient.TickLastPacketReceived > 1000 * 60)
@ -384,11 +385,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
return; return;
} }
if (udpClient.NeedAcks.Count > 0)
{
// Get a list of all of the packets that have been sitting unacked longer than udpClient.RTO // Get a list of all of the packets that have been sitting unacked longer than udpClient.RTO
List<OutgoingPacket> expiredPackets = udpClient.NeedAcks.GetExpiredPackets(udpClient.RTO); List<OutgoingPacket> expiredPackets = udpClient.NeedAcks.GetExpiredPackets(udpClient.RTO);
if (expiredPackets != null) if (expiredPackets != null)
{ {
m_log.Debug("[LLUDPSERVER]: Resending " + expiredPackets.Count + " packets to " + udpClient.AgentID);
// Resend packets // Resend packets
for (int i = 0; i < expiredPackets.Count; i++) for (int i = 0; i < expiredPackets.Count; i++)
{ {