diff --git a/OpenSim/Framework/Communications/CommunicationsManager.cs b/OpenSim/Framework/Communications/CommunicationsManager.cs index a45e23622d..5be73345d9 100644 --- a/OpenSim/Framework/Communications/CommunicationsManager.cs +++ b/OpenSim/Framework/Communications/CommunicationsManager.cs @@ -125,9 +125,7 @@ namespace OpenSim.Framework.Communications { return invService; } - } - return null; } } @@ -139,7 +137,6 @@ namespace OpenSim.Framework.Communications host = m_defaultInventoryHost; } - lock (m_inventoryServices) { foreach (IInventoryServices service in m_inventoryServices) diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs index bb44eb99aa..a835598a1e 100644 --- a/OpenSim/Framework/IClientAPI.cs +++ b/OpenSim/Framework/IClientAPI.cs @@ -299,6 +299,9 @@ namespace OpenSim.Framework public delegate void GetScriptRunning(IClientAPI remoteClient, LLUUID objectID, LLUUID itemID); public delegate void SetScriptRunning(IClientAPI remoteClient, LLUUID objectID, LLUUID itemID, bool running); + + public delegate void TerrainUnacked(IClientAPI remoteClient, int patchX, int patchY); + #endregion public interface IClientAPI @@ -501,6 +504,8 @@ namespace OpenSim.Framework event SetScriptRunning OnSetScriptRunning; event UpdateVector OnAutoPilotGo; + event TerrainUnacked OnUnackedTerrain; + // [Obsolete("IClientAPI.OutPacket SHOULD NOT EXIST outside of LLClientView please refactor appropriately.")] void OutPacket(Packet newPack, ThrottleOutPacketType packType); void SendWearables(AvatarWearable[] wearables, int serial); @@ -521,6 +526,8 @@ namespace OpenSim.Framework void SendLayerData(float[] map); void SendLayerData(int px, int py, float[] map); + void SendLayerData(int px, int py, float[] map, bool track); + void MoveAgentIntoRegion(RegionInfo regInfo, LLVector3 pos, LLVector3 look); void InformClientOfNeighbour(ulong neighbourHandle, IPEndPoint neighbourExternalEndPoint); AgentCircuitData RequestClientInfo(); @@ -554,13 +561,13 @@ namespace OpenSim.Framework LLVector3 pos, LLVector3 vel, LLVector3 acc, LLQuaternion rotation, LLVector3 rvel, uint flags, LLUUID objectID, LLUUID ownerID, string text, byte[] color, uint parentID, byte[] particleSystem, - byte clickAction, byte[] textureanim, bool attachment, uint AttachPoint, LLUUID AssetId, LLUUID SoundId, double SoundVolume, byte SoundFlags, double SoundRadius); + byte clickAction, byte[] textureanim, bool attachment, uint AttachPoint, LLUUID AssetId, LLUUID SoundId, double SoundVolume, byte SoundFlags, double SoundRadius, bool track); void SendPrimitiveToClient(ulong regionHandle, ushort timeDilation, uint localID, PrimitiveBaseShape primShape, LLVector3 pos, LLVector3 vel, LLVector3 acc, LLQuaternion rotation, LLVector3 rvel, uint flags, LLUUID objectID, LLUUID ownerID, string text, byte[] color, - uint parentID, byte[] particleSystem, byte clickAction); + uint parentID, byte[] particleSystem, byte clickAction, bool track); void SendPrimTerseUpdate(ulong regionHandle, ushort timeDilation, uint localID, LLVector3 position, LLQuaternion rotation, LLVector3 velocity, LLVector3 rotationalvelocity, byte state, LLUUID AssetId); diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index 2c05097e44..c9fc83a4c8 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -118,6 +118,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP private Dictionary m_defaultAnimations = new Dictionary(); + private LLPacketTracker m_packetTracker; + /* protected variables */ protected static Dictionary PacketHandlers = @@ -282,6 +284,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP private SetScriptRunning handlerSetScriptRunning = null; private UpdateVector handlerAutoPilotGo = null; + private TerrainUnacked handlerUnackedTerrain = null; + + //** + /* Properties */ public LLUUID SecureSessionId @@ -377,6 +383,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP public LLClientView(EndPoint remoteEP, IScene scene, AssetCache assetCache, LLPacketServer packServer, AgentCircuitManager authenSessions, LLUUID agentId, LLUUID sessionId, uint circuitCode, EndPoint proxyEP) { + m_packetTracker = new LLPacketTracker(this); + m_moneyBalance = 1000; m_channelVersion = Helpers.StringToField(scene.GetSimulatorVersion()); @@ -410,6 +418,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP RegisterLocalPacketHandlers(); + m_clientThread = new Thread(new ThreadStart(AuthUser)); m_clientThread.Name = "ClientThread"; m_clientThread.IsBackground = true; @@ -654,6 +663,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP # endregion + protected int m_terrainCheckerCount = 0; /// /// Event handler for check client timer /// checks to ensure that the client is still connected @@ -685,7 +695,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_probesWithNoIngressPackets = 0; m_lastPacketsReceived = m_packetsReceived; } + //SendPacketStats(); + m_packetTracker.Process(); + + if (m_terrainCheckerCount >= 4) + { + m_packetTracker.TerrainPacketCheck(); + // m_packetTracker.PrimPacketCheck(); + m_terrainCheckerCount = -1; + } + m_terrainCheckerCount++; } # region Setup @@ -934,6 +954,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP public event SetScriptRunning OnSetScriptRunning; public event UpdateVector OnAutoPilotGo; + public event TerrainUnacked OnUnackedTerrain; + #region Scene/Avatar to Client /// @@ -1083,29 +1105,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP public virtual void SendLayerData(float[] map) { ThreadPool.QueueUserWorkItem(new WaitCallback(DoSendLayerData), (object)map); - //try - //{ - // int[] patches = new int[4]; - - // for (int y = 0; y < 16; y++) - // { - // for (int x = 0; x < 16; x += 4) - // { - // patches[0] = x + 0 + y * 16; - // patches[1] = x + 1 + y * 16; - // patches[2] = x + 2 + y * 16; - // patches[3] = x + 3 + y * 16; - - // Packet layerpack = LLClientView.TerrainManager.CreateLandPacket(map, patches); - // OutPacket(layerpack, ThrottleOutPacketType.Land); - // } - // } - //} - //catch (Exception e) - //{ - // m_log.Warn("[client]: " + - // "ClientView.API.cs: SendLayerData() - Failed with exception " + e.ToString()); - //} + } /// @@ -1165,6 +1165,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// Patch coordinate (y) 0..15 /// heightmap public void SendLayerData(int px, int py, float[] map) + { + SendLayerData(px, py, map, true); + } + + public void SendLayerData(int px, int py, float[] map, bool track) { try { @@ -1177,6 +1182,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP LayerDataPacket layerpack = LLClientView.TerrainManager.CreateLandPacket(map, patches); layerpack.Header.Zerocoded = true; + + if (track) + { + layerpack.Header.Sequence = NextSeqNum(); + m_packetTracker.TrackTerrainPacket(layerpack.Header.Sequence, px, py); + } + OutPacket(layerpack, ThrottleOutPacketType.Land); } catch (Exception e) @@ -2297,14 +2309,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP ulong regionHandle, ushort timeDilation, uint localID, PrimitiveBaseShape primShape, LLVector3 pos, LLVector3 vel, LLVector3 acc, LLQuaternion rotation, LLVector3 rvel, uint flags, LLUUID objectID, LLUUID ownerID, string text, byte[] color, - uint parentID, byte[] particleSystem, byte clickAction) + uint parentID, byte[] particleSystem, byte clickAction, bool track) { byte[] textureanim = new byte[0]; SendPrimitiveToClient(regionHandle, timeDilation, localID, primShape, pos, vel, acc, rotation, rvel, flags, objectID, ownerID, text, color, parentID, particleSystem, - clickAction, textureanim, false, (uint)0, LLUUID.Zero, LLUUID.Zero, 0, 0, 0); + clickAction, textureanim, false, (uint)0, LLUUID.Zero, LLUUID.Zero, 0, 0, 0, track); } public void SendPrimitiveToClient( @@ -2312,8 +2324,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP LLVector3 pos, LLVector3 velocity, LLVector3 acceleration, LLQuaternion rotation, LLVector3 rotational_velocity, uint flags, LLUUID objectID, LLUUID ownerID, string text, byte[] color, uint parentID, byte[] particleSystem, - byte clickAction, byte[] textureanim, bool attachment, uint AttachPoint, LLUUID AssetId, LLUUID SoundId, double SoundGain, byte SoundFlags, double SoundRadius) + byte clickAction, byte[] textureanim, bool attachment, uint AttachPoint, LLUUID AssetId, LLUUID SoundId, double SoundGain, byte SoundFlags, double SoundRadius, bool track) { + if (rotation.X == rotation.Y && rotation.Y == rotation.Z && rotation.Z == rotation.W && rotation.W == 0) rotation = LLQuaternion.Identity; @@ -2396,6 +2409,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP outPacket.ObjectData[0].TextureAnim = textureanim; } outPacket.Header.Zerocoded = true; + + if (track) + { + outPacket.Header.Sequence = NextSeqNum(); + m_packetTracker.TrackPrimPacket(outPacket.Header.Sequence, objectID); + } + OutPacket(outPacket, ThrottleOutPacketType.Task); } @@ -3816,7 +3836,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (!Pack.Header.Resent) { - Pack.Header.Sequence = NextSeqNum(); + if (Pack.Header.Sequence == 0) + { + Pack.Header.Sequence = NextSeqNum(); + } if (Pack.Header.Reliable) //DIRTY HACK { @@ -3878,13 +3901,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP { foreach (uint ackedPacketId in NewPack.Header.AckList) { - Packet ackedPacket; - - if (m_needAck.TryGetValue(ackedPacketId, out ackedPacket)) - { - m_unAckedBytes -= ackedPacket.ToBytes().Length; - m_needAck.Remove(ackedPacketId); - } + RemovePacketFromNeedAckList(ackedPacketId); } } } @@ -3899,12 +3916,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP foreach (PacketAckPacket.PacketsBlock block in ackPacket.Packets) { uint ackedPackId = block.ID; - Packet ackedPacket; - if (m_needAck.TryGetValue(ackedPackId, out ackedPacket)) - { - m_unAckedBytes -= ackedPacket.ToBytes().Length; - m_needAck.Remove(ackedPackId); - } + RemovePacketFromNeedAckList(ackedPackId); } } } @@ -3926,6 +3938,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP } } + private void RemovePacketFromNeedAckList(uint ackedPackId) + { + Packet ackedPacket; + if (m_needAck.TryGetValue(ackedPackId, out ackedPacket)) + { + m_unAckedBytes -= ackedPacket.ToBytes().Length; + m_needAck.Remove(ackedPackId); + + m_packetTracker.PacketAck(ackedPackId); + } + } + /// /// The dreaded OutPacket. This should only be called from withink the ClientStack itself right now /// This is the entry point for simulator packets to go out to the client. @@ -4037,6 +4061,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP SendAcks(); ResendUnacked(); SendPacketStats(); + // TerrainPacketTrack(); } /// @@ -4053,6 +4078,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP } } + /// /// Emties out the old packets in the packet duplication tracking table. /// @@ -4092,6 +4118,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP #endregion + public void TriggerTerrainUnackedEvent(int patchX, int patchY) + { + handlerUnackedTerrain = OnUnackedTerrain; + if (handlerUnackedTerrain != null) + { + handlerUnackedTerrain(this, patchX, patchY); + } + } + // Previously ClientView.ProcessPackets public bool AddMoney(int debit) diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLPacketTracker.cs b/OpenSim/Region/ClientStack/LindenUDP/LLPacketTracker.cs new file mode 100644 index 0000000000..e775a67d4e --- /dev/null +++ b/OpenSim/Region/ClientStack/LindenUDP/LLPacketTracker.cs @@ -0,0 +1,234 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading; +using libsecondlife; + +namespace OpenSim.Region.ClientStack.LindenUDP +{ + + public class LLPacketTracker + { + public delegate void PacketAcked(uint sequenceNumber); + public event PacketAcked OnPacketAcked; + + protected List m_beenAcked = new List(); + + protected TerrainPacketTracker[,] m_sentTerrainPackets = new TerrainPacketTracker[16, 16]; + protected Dictionary m_sendPrimPackets = new Dictionary(); + + protected LLClientView m_parentClient; + + public LLPacketTracker(LLClientView parent) + { + m_parentClient = parent; + OnPacketAcked += TerrainPacketAcked; + //OnPacketAcked += PrimPacketAcked; + } + + public void PacketAck(uint sequenceNumber) + { + lock (m_beenAcked) + { + m_beenAcked.Add(sequenceNumber); + } + } + + public void TrackTerrainPacket(uint sequenceNumber, int patchX, int patchY) + { + TerrainPacketTracker tracker = new TerrainPacketTracker(); + tracker.X = patchX; + tracker.Y = patchY; + tracker.SeqNumber = sequenceNumber; + tracker.TimeSent = DateTime.Now; + lock (m_sentTerrainPackets) + { + m_sentTerrainPackets[patchX, patchY] = tracker; + } + } + + public void TrackPrimPacket(uint sequenceNumber, LLUUID primID) + { + PrimPacketTracker tracker = new PrimPacketTracker(); + tracker.PrimID = primID; + tracker.TimeSent = DateTime.Now; + tracker.SeqNumber = sequenceNumber; + lock (m_sendPrimPackets) + { + m_sendPrimPackets[primID] = tracker; + } + } + + public void TerrainPacketCheck() + { + DateTime now = DateTime.Now; + List resendList = new List(); + lock (m_sentTerrainPackets) + { + for (int y = 0; y < 16; y++) + { + for (int x = 0; x < 16; x++) + { + if (m_sentTerrainPackets[x, y] != null) + { + TerrainPacketTracker tracker = m_sentTerrainPackets[x, y]; + if ((now - tracker.TimeSent) > TimeSpan.FromMinutes(1)) + { + tracker.TimeSent = now; + m_sentTerrainPackets[x, y] = null; + resendList.Add(tracker); + } + } + } + } + } + + foreach (TerrainPacketTracker tracker in resendList) + { + m_parentClient.TriggerTerrainUnackedEvent(tracker.X, tracker.Y); + } + } + + public void PrimPacketCheck() + { + DateTime now = DateTime.Now; + List resendList = new List(); + List ackedList = new List(); + + lock (m_sendPrimPackets) + { + foreach (PrimPacketTracker tracker in m_sendPrimPackets.Values) + { + if (tracker.Acked) + { + ackedList.Add(tracker); + } + else if (((now - tracker.TimeSent) > TimeSpan.FromMinutes(1)) && (!tracker.Acked)) + { + resendList.Add(tracker); + } + } + } + + foreach (PrimPacketTracker tracker in resendList) + { + lock (m_sendPrimPackets) + { + m_sendPrimPackets.Remove(tracker.PrimID); + } + //call event + Console.WriteLine("Prim packet not acked, " + tracker.PrimID.ToString()); + } + + + RemovePrimTrackers(ackedList); + } + + public void PrimTrackerCleanup() + { + List ackedList = new List(); + + lock (m_sendPrimPackets) + { + foreach (PrimPacketTracker tracker in m_sendPrimPackets.Values) + { + if (tracker.Acked) + { + ackedList.Add(tracker); + } + } + } + Thread.Sleep(15); //give a little bit of time for other code to access list before we lock it again + + RemovePrimTrackers(ackedList); + } + + protected void RemovePrimTrackers(List ackedList) + { + lock (m_sendPrimPackets) + { + foreach (PrimPacketTracker tracker in ackedList) + { + m_sendPrimPackets.Remove(tracker.PrimID); + } + } + } + + protected void TerrainPacketAcked(uint sequence) + { + lock (m_sentTerrainPackets) + { + for (int y = 0; y < 16; y++) + { + for (int x = 0; x < 16; x++) + { + if (m_sentTerrainPackets[x, y] != null) + { + if (m_sentTerrainPackets[x, y].SeqNumber == sequence) + { + m_sentTerrainPackets[x, y] = null; + return; + } + } + } + } + } + } + + protected void PrimPacketAcked(uint sequence) + { + lock (m_sendPrimPackets) + { + foreach (PrimPacketTracker tracker in m_sendPrimPackets.Values) + { + if (tracker.SeqNumber == sequence) + { + tracker.Acked = true; + break; + } + } + } + } + + public void Process() + { + List ackedPackets = null; + lock (m_beenAcked) + { + ackedPackets = new List(m_beenAcked); + m_beenAcked.Clear(); + } + + if (ackedPackets != null) + { + foreach (uint packetId in ackedPackets) + { + if (OnPacketAcked != null) + { + OnPacketAcked(packetId); + } + } + } + + // ackedPackets.Clear(); + ackedPackets = null; + } + + public class TerrainPacketTracker + { + public uint SeqNumber = 0; + public int X; + public int Y; + public DateTime TimeSent; + + } + + public class PrimPacketTracker + { + public uint SeqNumber = 0; + public DateTime TimeSent; + public LLUUID PrimID; + public bool Acked = false; + } + } +} diff --git a/OpenSim/Region/Environment/Modules/World/NPC/NPCAvatar.cs b/OpenSim/Region/Environment/Modules/World/NPC/NPCAvatar.cs index 040b9b7bf4..574bc63f2d 100644 --- a/OpenSim/Region/Environment/Modules/World/NPC/NPCAvatar.cs +++ b/OpenSim/Region/Environment/Modules/World/NPC/NPCAvatar.cs @@ -296,6 +296,8 @@ namespace OpenSim.Region.Environment.Modules.World.NPC public event GetScriptRunning OnGetScriptRunning; public event SetScriptRunning OnSetScriptRunning; public event UpdateVector OnAutoPilotGo; + + public event TerrainUnacked OnUnackedTerrain; #pragma warning restore 67 #endregion @@ -438,6 +440,9 @@ namespace OpenSim.Region.Environment.Modules.World.NPC public virtual void SendLayerData(int px, int py, float[] map) { } + public virtual void SendLayerData(int px, int py, float[] map, bool track) + { + } public virtual void MoveAgentIntoRegion(RegionInfo regInfo, LLVector3 pos, LLVector3 look) { @@ -513,7 +518,7 @@ namespace OpenSim.Region.Environment.Modules.World.NPC LLVector3 acc, LLQuaternion rotation, LLVector3 rvel, uint flags, LLUUID objectID, LLUUID ownerID, string text, byte[] color, uint parentID, - byte[] particleSystem, byte clickAction) + byte[] particleSystem, byte clickAction, bool track) { } public virtual void SendPrimitiveToClient(ulong regionHandle, ushort timeDilation, uint localID, @@ -522,7 +527,7 @@ namespace OpenSim.Region.Environment.Modules.World.NPC LLUUID objectID, LLUUID ownerID, string text, byte[] color, uint parentID, byte[] particleSystem, byte clickAction, byte[] textureanimation, - bool attachment, uint AttachmentPoint, LLUUID AssetId, LLUUID SoundId, double SoundVolume, byte SoundFlags, double SoundRadius) + bool attachment, uint AttachmentPoint, LLUUID AssetId, LLUUID SoundId, double SoundVolume, byte SoundFlags, double SoundRadius, bool track) { } public virtual void SendPrimTerseUpdate(ulong regionHandle, ushort timeDilation, uint localID, diff --git a/OpenSim/Region/Environment/Scenes/Scene.cs b/OpenSim/Region/Environment/Scenes/Scene.cs index f602e9fbb3..c2398b6ac3 100644 --- a/OpenSim/Region/Environment/Scenes/Scene.cs +++ b/OpenSim/Region/Environment/Scenes/Scene.cs @@ -2084,6 +2084,8 @@ namespace OpenSim.Region.Environment.Scenes client.OnGetScriptRunning += GetScriptRunning; client.OnSetScriptRunning += SetScriptRunning; + client.OnUnackedTerrain += TerrainUnAcked; + // EventManager.TriggerOnNewClient(client); } @@ -3703,5 +3705,12 @@ namespace OpenSim.Region.Environment.Scenes // client.SendParcelMediaCommand((uint)(4), ParcelMediaCommandEnum.Play, 0); // }); } + + + public void TerrainUnAcked(IClientAPI client, int patchX, int patchY) + { + //Console.WriteLine("Terrain packet unacked, resending patch: " + patchX + " , " + patchY); + client.SendLayerData(patchX, patchY, Heightmap.GetFloatsSerialised()); + } } } diff --git a/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs b/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs index 156310b9e9..253a83efad 100644 --- a/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs @@ -2085,7 +2085,7 @@ namespace OpenSim.Region.Environment.Scenes remoteClient.SendPrimitiveToClient(m_regionHandle, (ushort)(m_parentGroup.GetTimeDilation() * (float)ushort.MaxValue), LocalId, m_shape, lPos, Velocity, Acceleration, RotationOffset, RotationalVelocity, clientFlags, m_uuid, _ownerID, m_text, color, _parentID, m_particleSystem, m_clickAction, m_TextureAnimation, m_IsAttachment, - m_attachmentPoint,fromAssetID, Sound, SoundGain, SoundFlags, SoundRadius); + m_attachmentPoint,fromAssetID, Sound, SoundGain, SoundFlags, SoundRadius, false); } /// diff --git a/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs b/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs index 6179ccf373..c975df5ee6 100644 --- a/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs +++ b/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs @@ -202,6 +202,8 @@ namespace OpenSim.Region.Examples.SimpleModule public event SetScriptRunning OnSetScriptRunning; public event UpdateVector OnAutoPilotGo; + public event TerrainUnacked OnUnackedTerrain; + #pragma warning restore 67 private LLUUID myID = LLUUID.Random(); @@ -352,6 +354,9 @@ namespace OpenSim.Region.Examples.SimpleModule public virtual void SendLayerData(int px, int py, float[] map) { } + public virtual void SendLayerData(int px, int py, float[] map, bool track) + { + } public virtual void MoveAgentIntoRegion(RegionInfo regInfo, LLVector3 pos, LLVector3 look) { @@ -427,7 +432,7 @@ namespace OpenSim.Region.Examples.SimpleModule LLVector3 acc, LLQuaternion rotation, LLVector3 rvel, uint flags, LLUUID objectID, LLUUID ownerID, string text, byte[] color, uint parentID, - byte[] particleSystem, byte clickAction) + byte[] particleSystem, byte clickAction, bool track) { } public virtual void SendPrimitiveToClient(ulong regionHandle, ushort timeDilation, uint localID, @@ -436,7 +441,7 @@ namespace OpenSim.Region.Examples.SimpleModule LLUUID objectID, LLUUID ownerID, string text, byte[] color, uint parentID, byte[] particleSystem, byte clickAction, byte[] textureanimation, - bool attachment, uint AttachmentPoint, LLUUID AssetId, LLUUID SoundId, double SoundVolume, byte SoundFlags, double SoundRadius) + bool attachment, uint AttachmentPoint, LLUUID AssetId, LLUUID SoundId, double SoundVolume, byte SoundFlags, double SoundRadius, bool track) { } public virtual void SendPrimTerseUpdate(ulong regionHandle, ushort timeDilation, uint localID,