aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim')
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs106
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneGraph.cs264
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs22
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs8
4 files changed, 244 insertions, 156 deletions
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
index ffe6fe9..fba5090 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
@@ -352,6 +352,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
352 private IHyperAssetService m_hyperAssets; 352 private IHyperAssetService m_hyperAssets;
353 private const bool m_checkPackets = true; 353 private const bool m_checkPackets = true;
354 354
355 private Timer m_propertiesPacketTimer;
356 private List<ObjectPropertiesPacket.ObjectDataBlock> m_propertiesBlocks = new List<ObjectPropertiesPacket.ObjectDataBlock>();
357
355 #endregion Class Members 358 #endregion Class Members
356 359
357 #region Properties 360 #region Properties
@@ -433,6 +436,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
433 m_udpClient.OnQueueEmpty += HandleQueueEmpty; 436 m_udpClient.OnQueueEmpty += HandleQueueEmpty;
434 m_udpClient.OnPacketStats += PopulateStats; 437 m_udpClient.OnPacketStats += PopulateStats;
435 438
439 m_propertiesPacketTimer = new Timer(100);
440 m_propertiesPacketTimer.Elapsed += ProcessObjectPropertiesPacket;
441
436 RegisterLocalPacketHandlers(); 442 RegisterLocalPacketHandlers();
437 } 443 }
438 444
@@ -3579,42 +3585,88 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3579 string ItemDescription, uint OwnerMask, uint NextOwnerMask, uint GroupMask, uint EveryoneMask, 3585 string ItemDescription, uint OwnerMask, uint NextOwnerMask, uint GroupMask, uint EveryoneMask,
3580 uint BaseMask, byte saleType, int salePrice) 3586 uint BaseMask, byte saleType, int salePrice)
3581 { 3587 {
3582 ObjectPropertiesPacket proper = (ObjectPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ObjectProperties); 3588 //ObjectPropertiesPacket proper = (ObjectPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ObjectProperties);
3583 // TODO: don't create new blocks if recycling an old packet 3589 // TODO: don't create new blocks if recycling an old packet
3584 3590
3585 proper.ObjectData = new ObjectPropertiesPacket.ObjectDataBlock[1]; 3591 ObjectPropertiesPacket.ObjectDataBlock block =
3586 proper.ObjectData[0] = new ObjectPropertiesPacket.ObjectDataBlock(); 3592 new ObjectPropertiesPacket.ObjectDataBlock();
3587 proper.ObjectData[0].ItemID = ItemID; 3593
3588 proper.ObjectData[0].CreationDate = CreationDate; 3594 block.ItemID = ItemID;
3589 proper.ObjectData[0].CreatorID = CreatorUUID; 3595 block.CreationDate = CreationDate;
3590 proper.ObjectData[0].FolderID = FolderUUID; 3596 block.CreatorID = CreatorUUID;
3591 proper.ObjectData[0].FromTaskID = FromTaskUUID; 3597 block.FolderID = FolderUUID;
3592 proper.ObjectData[0].GroupID = GroupUUID; 3598 block.FromTaskID = FromTaskUUID;
3593 proper.ObjectData[0].InventorySerial = InventorySerial; 3599 block.GroupID = GroupUUID;
3594 3600 block.InventorySerial = InventorySerial;
3595 proper.ObjectData[0].LastOwnerID = LastOwnerUUID; 3601
3602 block.LastOwnerID = LastOwnerUUID;
3596 // proper.ObjectData[0].LastOwnerID = UUID.Zero; 3603 // proper.ObjectData[0].LastOwnerID = UUID.Zero;
3597 3604
3598 proper.ObjectData[0].ObjectID = ObjectUUID; 3605 block.ObjectID = ObjectUUID;
3599 if (OwnerUUID == GroupUUID) 3606 if (OwnerUUID == GroupUUID)
3600 proper.ObjectData[0].OwnerID = UUID.Zero; 3607 block.OwnerID = UUID.Zero;
3601 else 3608 else
3602 proper.ObjectData[0].OwnerID = OwnerUUID; 3609 block.OwnerID = OwnerUUID;
3603 proper.ObjectData[0].TouchName = Util.StringToBytes256(TouchTitle); 3610 block.TouchName = Util.StringToBytes256(TouchTitle);
3604 proper.ObjectData[0].TextureID = TextureID; 3611 block.TextureID = TextureID;
3605 proper.ObjectData[0].SitName = Util.StringToBytes256(SitTitle); 3612 block.SitName = Util.StringToBytes256(SitTitle);
3606 proper.ObjectData[0].Name = Util.StringToBytes256(ItemName); 3613 block.Name = Util.StringToBytes256(ItemName);
3607 proper.ObjectData[0].Description = Util.StringToBytes256(ItemDescription); 3614 block.Description = Util.StringToBytes256(ItemDescription);
3608 proper.ObjectData[0].OwnerMask = OwnerMask; 3615 block.OwnerMask = OwnerMask;
3609 proper.ObjectData[0].NextOwnerMask = NextOwnerMask; 3616 block.NextOwnerMask = NextOwnerMask;
3610 proper.ObjectData[0].GroupMask = GroupMask; 3617 block.GroupMask = GroupMask;
3611 proper.ObjectData[0].EveryoneMask = EveryoneMask; 3618 block.EveryoneMask = EveryoneMask;
3612 proper.ObjectData[0].BaseMask = BaseMask; 3619 block.BaseMask = BaseMask;
3613 // proper.ObjectData[0].AggregatePerms = 53; 3620 // proper.ObjectData[0].AggregatePerms = 53;
3614 // proper.ObjectData[0].AggregatePermTextures = 0; 3621 // proper.ObjectData[0].AggregatePermTextures = 0;
3615 // proper.ObjectData[0].AggregatePermTexturesOwner = 0; 3622 // proper.ObjectData[0].AggregatePermTexturesOwner = 0;
3616 proper.ObjectData[0].SaleType = saleType; 3623 block.SaleType = saleType;
3617 proper.ObjectData[0].SalePrice = salePrice; 3624 block.SalePrice = salePrice;
3625
3626 lock (m_propertiesPacketTimer)
3627 {
3628 m_propertiesBlocks.Add(block);
3629
3630 int length = 0;
3631 foreach (ObjectPropertiesPacket.ObjectDataBlock b in m_propertiesBlocks)
3632 {
3633 length += b.Length;
3634 }
3635 if (length > 1100) // FIXME: use real MTU
3636 {
3637 ProcessObjectPropertiesPacket(null, null);
3638 m_propertiesPacketTimer.Stop();
3639 return;
3640 }
3641
3642 m_propertiesPacketTimer.Stop();
3643 m_propertiesPacketTimer.Start();
3644 }
3645
3646 //proper.Header.Zerocoded = true;
3647 //OutPacket(proper, ThrottleOutPacketType.Task);
3648 }
3649
3650 private void ProcessObjectPropertiesPacket(Object sender, ElapsedEventArgs e)
3651 {
3652 ObjectPropertiesPacket proper = (ObjectPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ObjectProperties);
3653
3654 lock (m_propertiesPacketTimer)
3655 {
3656 m_propertiesPacketTimer.Stop();
3657
3658 proper.ObjectData = new ObjectPropertiesPacket.ObjectDataBlock[m_propertiesBlocks.Count];
3659
3660 int index = 0;
3661
3662 foreach (ObjectPropertiesPacket.ObjectDataBlock b in m_propertiesBlocks)
3663 {
3664 proper.ObjectData[index++] = b;
3665 }
3666
3667 m_propertiesBlocks.Clear();
3668 }
3669
3618 proper.Header.Zerocoded = true; 3670 proper.Header.Zerocoded = true;
3619 OutPacket(proper, ThrottleOutPacketType.Task); 3671 OutPacket(proper, ThrottleOutPacketType.Task);
3620 } 3672 }
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index 2fdb48d..f74fd5d 100644
--- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
@@ -26,6 +26,7 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Threading;
29using System.Collections.Generic; 30using System.Collections.Generic;
30using System.Reflection; 31using System.Reflection;
31using OpenMetaverse; 32using OpenMetaverse;
@@ -96,6 +97,8 @@ namespace OpenSim.Region.Framework.Scenes
96 protected internal Dictionary<UUID, SceneObjectGroup> SceneObjectGroupsByFullID = new Dictionary<UUID, SceneObjectGroup>(); 97 protected internal Dictionary<UUID, SceneObjectGroup> SceneObjectGroupsByFullID = new Dictionary<UUID, SceneObjectGroup>();
97 private readonly Object m_dictionary_lock = new Object(); 98 private readonly Object m_dictionary_lock = new Object();
98 99
100 private Object m_updateLock = new Object();
101
99 #endregion 102 #endregion
100 103
101 protected internal SceneGraph(Scene parent, RegionInfo regInfo) 104 protected internal SceneGraph(Scene parent, RegionInfo regInfo)
@@ -369,6 +372,9 @@ namespace OpenSim.Region.Framework.Scenes
369 /// </summary> 372 /// </summary>
370 protected internal void UpdateObjectGroups() 373 protected internal void UpdateObjectGroups()
371 { 374 {
375 if (!Monitor.TryEnter(m_updateLock))
376 return;
377
372 List<SceneObjectGroup> updates; 378 List<SceneObjectGroup> updates;
373 379
374 // Some updates add more updates to the updateList. 380 // Some updates add more updates to the updateList.
@@ -395,6 +401,7 @@ namespace OpenSim.Region.Framework.Scenes
395 "[INNER SCENE]: Failed to update {0}, {1} - {2}", sog.Name, sog.UUID, e); 401 "[INNER SCENE]: Failed to update {0}, {1} - {2}", sog.Name, sog.UUID, e);
396 } 402 }
397 } 403 }
404 Monitor.Exit(m_updateLock);
398 } 405 }
399 406
400 protected internal void AddPhysicalPrim(int number) 407 protected internal void AddPhysicalPrim(int number)
@@ -1555,55 +1562,65 @@ namespace OpenSim.Region.Framework.Scenes
1555 /// <param name="childPrims"></param> 1562 /// <param name="childPrims"></param>
1556 protected internal void LinkObjects(IClientAPI client, uint parentPrimId, List<uint> childPrimIds) 1563 protected internal void LinkObjects(IClientAPI client, uint parentPrimId, List<uint> childPrimIds)
1557 { 1564 {
1558 SceneObjectGroup parentGroup = GetGroupByPrim(parentPrimId); 1565 Monitor.Enter(m_updateLock);
1559 1566 try
1560 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>();
1561 if (parentGroup != null)
1562 { 1567 {
1563 // We do this in reverse to get the link order of the prims correct 1568 SceneObjectGroup parentGroup = GetGroupByPrim(parentPrimId);
1564 for (int i = childPrimIds.Count - 1; i >= 0; i--) 1569
1570 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>();
1571 if (parentGroup != null)
1565 { 1572 {
1566 SceneObjectGroup child = GetGroupByPrim(childPrimIds[i]); 1573 // We do this in reverse to get the link order of the prims correct
1567 if (child != null) 1574 for (int i = childPrimIds.Count - 1; i >= 0; i--)
1568 { 1575 {
1569 // Make sure no child prim is set for sale 1576 SceneObjectGroup child = GetGroupByPrim(childPrimIds[i]);
1570 // So that, on delink, no prims are unwittingly 1577 if (child != null)
1571 // left for sale and sold off 1578 {
1572 child.RootPart.ObjectSaleType = 0; 1579 // Make sure no child prim is set for sale
1573 child.RootPart.SalePrice = 10; 1580 // So that, on delink, no prims are unwittingly
1574 childGroups.Add(child); 1581 // left for sale and sold off
1582 child.RootPart.ObjectSaleType = 0;
1583 child.RootPart.SalePrice = 10;
1584 childGroups.Add(child);
1585 }
1575 } 1586 }
1576 } 1587 }
1577 } 1588 else
1578 else 1589 {
1579 { 1590 return; // parent is null so not in this region
1580 return; // parent is null so not in this region 1591 }
1581 }
1582 1592
1583 foreach (SceneObjectGroup child in childGroups) 1593 foreach (SceneObjectGroup child in childGroups)
1584 { 1594 {
1585 parentGroup.LinkToGroup(child); 1595 parentGroup.LinkToGroup(child);
1586 1596
1587 // this is here so physics gets updated! 1597 // this is here so physics gets updated!
1588 // Don't remove! Bad juju! Stay away! or fix physics! 1598 // Don't remove! Bad juju! Stay away! or fix physics!
1589 child.AbsolutePosition = child.AbsolutePosition; 1599 child.AbsolutePosition = child.AbsolutePosition;
1590 } 1600 }
1591 1601
1592 // We need to explicitly resend the newly link prim's object properties since no other actions 1602 // We need to explicitly resend the newly link prim's object properties since no other actions
1593 // occur on link to invoke this elsewhere (such as object selection) 1603 // occur on link to invoke this elsewhere (such as object selection)
1594 parentGroup.RootPart.AddFlag(PrimFlags.CreateSelected); 1604 parentGroup.RootPart.AddFlag(PrimFlags.CreateSelected);
1595 parentGroup.TriggerScriptChangedEvent(Changed.LINK); 1605 parentGroup.TriggerScriptChangedEvent(Changed.LINK);
1596 1606 parentGroup.HasGroupChanged = true;
1597 if (client != null) 1607 parentGroup.ScheduleGroupForFullUpdate();
1598 { 1608
1599 parentGroup.GetProperties(client); 1609// if (client != null)
1610// {
1611// parentGroup.GetProperties(client);
1612// }
1613// else
1614// {
1615// foreach (ScenePresence p in GetScenePresences())
1616// {
1617// parentGroup.GetProperties(p.ControllingClient);
1618// }
1619// }
1600 } 1620 }
1601 else 1621 finally
1602 { 1622 {
1603 foreach (ScenePresence p in GetScenePresences()) 1623 Monitor.Exit(m_updateLock);
1604 {
1605 parentGroup.GetProperties(p.ControllingClient);
1606 }
1607 } 1624 }
1608 } 1625 }
1609 1626
@@ -1618,109 +1635,120 @@ namespace OpenSim.Region.Framework.Scenes
1618 1635
1619 protected internal void DelinkObjects(List<uint> primIds, bool sendEvents) 1636 protected internal void DelinkObjects(List<uint> primIds, bool sendEvents)
1620 { 1637 {
1621 List<SceneObjectPart> childParts = new List<SceneObjectPart>(); 1638 Monitor.Enter(m_updateLock);
1622 List<SceneObjectPart> rootParts = new List<SceneObjectPart>(); 1639 try
1623 List<SceneObjectGroup> affectedGroups = new List<SceneObjectGroup>();
1624 // Look them all up in one go, since that is comparatively expensive
1625 //
1626 foreach (uint primID in primIds)
1627 { 1640 {
1628 SceneObjectPart part = m_parentScene.GetSceneObjectPart(primID); 1641 List<SceneObjectPart> childParts = new List<SceneObjectPart>();
1629 if (part != null) 1642 List<SceneObjectPart> rootParts = new List<SceneObjectPart>();
1643 List<SceneObjectGroup> affectedGroups = new List<SceneObjectGroup>();
1644 // Look them all up in one go, since that is comparatively expensive
1645 //
1646 foreach (uint primID in primIds)
1630 { 1647 {
1631 if (part.LinkNum < 2) // Root or single 1648 SceneObjectPart part = m_parentScene.GetSceneObjectPart(primID);
1632 rootParts.Add(part); 1649 if (part != null)
1650 {
1651 if (part.ParentGroup.Children.Count != 1) // Skip single
1652 {
1653 if (part.LinkNum < 2) // Root
1654 rootParts.Add(part);
1655 else
1656 childParts.Add(part);
1657
1658 SceneObjectGroup group = part.ParentGroup;
1659 if (!affectedGroups.Contains(group))
1660 affectedGroups.Add(group);
1661 }
1662 }
1633 else 1663 else
1634 childParts.Add(part); 1664 {
1635 1665 m_log.ErrorFormat("Viewer requested unlink of nonexistent part {0}", primID);
1636 SceneObjectGroup group = part.ParentGroup; 1666 }
1637 if (!affectedGroups.Contains(group))
1638 affectedGroups.Add(group);
1639 } 1667 }
1640 else 1668
1669 foreach (SceneObjectPart child in childParts)
1641 { 1670 {
1642 m_log.ErrorFormat("Viewer requested unlink of nonexistent part {0}", primID); 1671 // Unlink all child parts from their groups
1672 //
1673 child.ParentGroup.DelinkFromGroup(child, sendEvents);
1643 } 1674 }
1644 }
1645
1646 foreach (SceneObjectPart child in childParts)
1647 {
1648 // Unlink all child parts from their groups
1649 //
1650 child.ParentGroup.DelinkFromGroup(child, sendEvents);
1651 }
1652
1653 foreach (SceneObjectPart root in rootParts)
1654 {
1655 // In most cases, this will run only one time, and the prim
1656 // will be a solo prim
1657 // However, editing linked parts and unlinking may be different
1658 //
1659 SceneObjectGroup group = root.ParentGroup;
1660 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Children.Values);
1661 int numChildren = group.Children.Count;
1662 1675
1663 // If there are prims left in a link set, but the root is 1676 foreach (SceneObjectPart root in rootParts)
1664 // slated for unlink, we need to do this
1665 //
1666 if (numChildren != 1)
1667 { 1677 {
1668 // Unlink the remaining set 1678 // In most cases, this will run only one time, and the prim
1679 // will be a solo prim
1680 // However, editing linked parts and unlinking may be different
1669 // 1681 //
1670 bool sendEventsToRemainder = true; 1682 SceneObjectGroup group = root.ParentGroup;
1671 if (numChildren > 1) 1683 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Children.Values);
1672 sendEventsToRemainder = false; 1684 int numChildren = group.Children.Count;
1673
1674 foreach (SceneObjectPart p in newSet)
1675 {
1676 if (p != group.RootPart)
1677 group.DelinkFromGroup(p, sendEventsToRemainder);
1678 }
1679 1685
1680 // If there is more than one prim remaining, we 1686 // If there are prims left in a link set, but the root is
1681 // need to re-link 1687 // slated for unlink, we need to do this
1682 // 1688 //
1683 if (numChildren > 2) 1689 if (numChildren != 1)
1684 { 1690 {
1685 // Remove old root 1691 // Unlink the remaining set
1686 // 1692 //
1687 if (newSet.Contains(root)) 1693 bool sendEventsToRemainder = true;
1688 newSet.Remove(root); 1694 if (numChildren > 1)
1695 sendEventsToRemainder = false;
1689 1696
1690 // Preserve link ordering 1697 foreach (SceneObjectPart p in newSet)
1691 //
1692 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1693 { 1698 {
1694 return a.LinkNum.CompareTo(b.LinkNum); 1699 if (p != group.RootPart)
1695 }); 1700 group.DelinkFromGroup(p, sendEventsToRemainder);
1701 }
1696 1702
1697 // Determine new root 1703 // If there is more than one prim remaining, we
1704 // need to re-link
1698 // 1705 //
1699 SceneObjectPart newRoot = newSet[0]; 1706 if (numChildren > 2)
1700 newSet.RemoveAt(0); 1707 {
1708 // Remove old root
1709 //
1710 if (newSet.Contains(root))
1711 newSet.Remove(root);
1712
1713 // Preserve link ordering
1714 //
1715 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1716 {
1717 return a.LinkNum.CompareTo(b.LinkNum);
1718 });
1701 1719
1702 List<uint> linkIDs = new List<uint>(); 1720 // Determine new root
1721 //
1722 SceneObjectPart newRoot = newSet[0];
1723 newSet.RemoveAt(0);
1703 1724
1704 foreach (SceneObjectPart newChild in newSet) 1725 List<uint> linkIDs = new List<uint>();
1705 { 1726
1706 newChild.UpdateFlag = 0; 1727 foreach (SceneObjectPart newChild in newSet)
1707 linkIDs.Add(newChild.LocalId); 1728 {
1708 } 1729 newChild.UpdateFlag = 0;
1730 linkIDs.Add(newChild.LocalId);
1731 }
1709 1732
1710 LinkObjects(null, newRoot.LocalId, linkIDs); 1733 LinkObjects(null, newRoot.LocalId, linkIDs);
1711 if (!affectedGroups.Contains(newRoot.ParentGroup)) 1734 if (!affectedGroups.Contains(newRoot.ParentGroup))
1712 affectedGroups.Add(newRoot.ParentGroup); 1735 affectedGroups.Add(newRoot.ParentGroup);
1736 }
1713 } 1737 }
1714 } 1738 }
1715 }
1716 1739
1717 // Finally, trigger events in the roots 1740 // Finally, trigger events in the roots
1718 // 1741 //
1719 foreach (SceneObjectGroup g in affectedGroups) 1742 foreach (SceneObjectGroup g in affectedGroups)
1743 {
1744 g.TriggerScriptChangedEvent(Changed.LINK);
1745 g.HasGroupChanged = true; // Persist
1746 g.ScheduleGroupForFullUpdate();
1747 }
1748 }
1749 finally
1720 { 1750 {
1721 g.TriggerScriptChangedEvent(Changed.LINK); 1751 Monitor.Exit(m_updateLock);
1722 g.HasGroupChanged = true; // Persist
1723 g.ScheduleGroupForFullUpdate();
1724 } 1752 }
1725 } 1753 }
1726 1754
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index 6badaf5..cb87212 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -2114,14 +2114,14 @@ namespace OpenSim.Region.Framework.Scenes
2114 public void LinkToGroup(SceneObjectGroup objectGroup) 2114 public void LinkToGroup(SceneObjectGroup objectGroup)
2115 { 2115 {
2116 // Make sure we have sent any pending unlinks or stuff. 2116 // Make sure we have sent any pending unlinks or stuff.
2117 if (objectGroup.RootPart.UpdateFlag > 0) 2117 //if (objectGroup.RootPart.UpdateFlag > 0)
2118 { 2118 //{
2119 m_log.WarnFormat( 2119 // m_log.WarnFormat(
2120 "[SCENE OBJECT GROUP]: Forcing send of linkset {0}, {1} to {2}, {3} as its still waiting.", 2120 // "[SCENE OBJECT GROUP]: Forcing send of linkset {0}, {1} to {2}, {3} as its still waiting.",
2121 objectGroup.RootPart.Name, objectGroup.RootPart.UUID, RootPart.Name, RootPart.UUID); 2121 // objectGroup.RootPart.Name, objectGroup.RootPart.UUID, RootPart.Name, RootPart.UUID);
2122 2122
2123 objectGroup.RootPart.SendScheduledUpdates(); 2123 // objectGroup.RootPart.SendScheduledUpdates();
2124 } 2124 //}
2125 2125
2126// m_log.DebugFormat( 2126// m_log.DebugFormat(
2127// "[SCENE OBJECT GROUP]: Linking group with root part {0}, {1} to group with root part {2}, {3}", 2127// "[SCENE OBJECT GROUP]: Linking group with root part {0}, {1} to group with root part {2}, {3}",
@@ -2207,8 +2207,8 @@ namespace OpenSim.Region.Framework.Scenes
2207 // unmoved prims! 2207 // unmoved prims!
2208 ResetChildPrimPhysicsPositions(); 2208 ResetChildPrimPhysicsPositions();
2209 2209
2210 HasGroupChanged = true; 2210 //HasGroupChanged = true;
2211 ScheduleGroupForFullUpdate(); 2211 //ScheduleGroupForFullUpdate();
2212 } 2212 }
2213 2213
2214 /// <summary> 2214 /// <summary>
@@ -2299,8 +2299,8 @@ namespace OpenSim.Region.Framework.Scenes
2299 2299
2300 linkPart.Rezzed = RootPart.Rezzed; 2300 linkPart.Rezzed = RootPart.Rezzed;
2301 2301
2302 HasGroupChanged = true; 2302 //HasGroupChanged = true;
2303 ScheduleGroupForFullUpdate(); 2303 //ScheduleGroupForFullUpdate();
2304 } 2304 }
2305 2305
2306 /// <summary> 2306 /// <summary>
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index d235bac..9a905f1 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -3523,6 +3523,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3523 { 3523 {
3524 parentPrim.DelinkFromGroup(part.LocalId, true); 3524 parentPrim.DelinkFromGroup(part.LocalId, true);
3525 } 3525 }
3526 parentPrim.HasGroupChanged = true;
3527 parentPrim.ScheduleGroupForFullUpdate();
3526 parentPrim.TriggerScriptChangedEvent(Changed.LINK); 3528 parentPrim.TriggerScriptChangedEvent(Changed.LINK);
3527 3529
3528 if (parts.Count > 0) 3530 if (parts.Count > 0)
@@ -3534,6 +3536,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3534 part.UpdateFlag = 0; 3536 part.UpdateFlag = 0;
3535 newRoot.ParentGroup.LinkToGroup(part.ParentGroup); 3537 newRoot.ParentGroup.LinkToGroup(part.ParentGroup);
3536 } 3538 }
3539 newRoot.ParentGroup.HasGroupChanged = true;
3540 newRoot.ParentGroup.ScheduleGroupForFullUpdate();
3537 } 3541 }
3538 } 3542 }
3539 else 3543 else
@@ -3542,6 +3546,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3542 return; 3546 return;
3543 3547
3544 parentPrim.DelinkFromGroup(childPrim.LocalId, true); 3548 parentPrim.DelinkFromGroup(childPrim.LocalId, true);
3549 parentPrim.HasGroupChanged = true;
3550 parentPrim.ScheduleGroupForFullUpdate();
3545 parentPrim.TriggerScriptChangedEvent(Changed.LINK); 3551 parentPrim.TriggerScriptChangedEvent(Changed.LINK);
3546 } 3552 }
3547 } 3553 }
@@ -3561,6 +3567,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3561 parentPrim.DelinkFromGroup(part.LocalId, true); 3567 parentPrim.DelinkFromGroup(part.LocalId, true);
3562 parentPrim.TriggerScriptChangedEvent(Changed.LINK); 3568 parentPrim.TriggerScriptChangedEvent(Changed.LINK);
3563 } 3569 }
3570 parentPrim.HasGroupChanged = true;
3571 parentPrim.ScheduleGroupForFullUpdate();
3564 } 3572 }
3565 3573
3566 public LSL_String llGetLinkKey(int linknum) 3574 public LSL_String llGetLinkKey(int linknum)