diff options
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 | ||
28 | using System; | 28 | using System; |
29 | using System.Threading; | ||
29 | using System.Collections.Generic; | 30 | using System.Collections.Generic; |
30 | using System.Reflection; | 31 | using System.Reflection; |
31 | using OpenMetaverse; | 32 | using 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) |