Browse Source

Upload the latest and greatest

Gwyneth Llewelyn 3 years ago
parent
commit
6ade61d685
100 changed files with 6953 additions and 1428 deletions
  1. 6 6
      OpenSim/Addons/Groups/GroupsModule.cs
  2. 85 159
      OpenSim/Addons/Groups/RemoteConnectorCacheWrapper.cs
  3. 10 6
      OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs
  4. 51 39
      OpenSim/Data/Tests/RegionTests.cs
  5. 1 0
      OpenSim/Framework/AgentCircuitManager.cs
  6. 5 0
      OpenSim/Framework/GridInfo.cs
  7. 31 55
      OpenSim/Framework/Monitoring/JobEngine.cs
  8. 0 4
      OpenSim/Framework/Monitoring/WorkManager.cs
  9. 189 0
      OpenSim/Framework/ObjectJobEngine.cs
  10. 36 4
      OpenSim/Framework/Serialization/External/RegionSettingsSerializer.cs
  11. 1 1
      OpenSim/Framework/Serialization/Tests/RegionSettingsSerializerTests.cs
  12. 39 0
      OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
  13. 49 81
      OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs
  14. 1 1
      OpenSim/Framework/Servers/HttpServer/SimpleBaseRequestHandler.cs
  15. 1 2
      OpenSim/Framework/Util.cs
  16. 1 1
      OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
  17. 13 50
      OpenSim/Region/ClientStack/Linden/Caps/GetAssetsModule.cs
  18. 16 50
      OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs
  19. 17 6
      OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
  20. 6 9
      OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
  21. 1 3
      OpenSim/Region/CoreModules/Framework/ServiceThrottle/ServiceThrottleModule.cs
  22. 253 28
      OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs
  23. 205 215
      OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs
  24. 33 44
      OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/RegionAssetConnectorModule.cs
  25. 3 1
      OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
  26. 1 1
      OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs
  27. 1 1
      OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs
  28. 15 9
      OpenSim/Region/CoreModules/World/LightShare/EnvironmentModule.cs
  29. 63 73
      OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
  30. 31 13
      OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
  31. 141 148
      OpenSim/Region/Framework/Scenes/Scene.cs
  32. 1 1
      OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
  33. 40 33
      OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
  34. 1 5
      OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
  35. 32 37
      OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs
  36. 39 35
      OpenSim/Region/PhysicsModules/ubOde/ODEMeshWorker.cs
  37. 0 5
      OpenSim/Region/PhysicsModules/ubOde/ODEScene.cs
  38. 7 3
      OpenSim/Region/PhysicsModules/ubOdeMeshing/Meshmerizer.cs
  39. 1 1
      OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs
  40. 23 24
      OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs
  41. 31 30
      OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
  42. 112 6
      OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
  43. 9 27
      OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/Dataserver.cs
  44. 204 0
      OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/ScriptTimer.cs
  45. 8 3
      OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
  46. 27 13
      OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs
  47. 15 0
      OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
  48. 7 8
      OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
  49. 3 3
      OpenSim/Region/ScriptEngine/XEngine/ScriptEngineConsoleCommands.cs
  50. 20 24
      OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
  51. 37 19
      OpenSim/Server/Handlers/Profiles/UserProfilesHandlers.cs
  52. 4 4
      OpenSim/Server/Handlers/Simulation/AgentHandlers.cs
  53. 13 11
      OpenSim/Services/HypergridService/UserAgentService.cs
  54. 2 1
      OpenSim/Services/Interfaces/IUserManagement.cs
  55. 4 0
      ThirdParty/SmartThreadPool/STPEventWaitHandle.cs
  56. 10 9
      ThirdParty/SmartThreadPool/SmartThreadPool.cs
  57. 6 0
      ThirdParty/SmartThreadPool/WorkItem.cs
  58. 1 1
      ThirdParty/SmartThreadPool/WorkItemsGroup.cs
  59. 37 81
      ThirdParty/SmartThreadPool/WorkItemsQueue.cs
  60. 4477 0
      bin/586dd99c-b06d-4c2c-85e8-9cdbca339aa0.xml
  61. BIN
      bin/MAP-1a95e448-df46-45d2-8182-559ce0c27a5a.png
  62. BIN
      bin/MAP-1dba66ba-a66f-40f1-9159-44e2778230a0.png
  63. BIN
      bin/MAP-36083b8f-e6d9-44ad-8ed2-cc7fa1b2abeb.png
  64. BIN
      bin/MAP-49b83350-5540-11de-8a39-0800200c9a66.png
  65. BIN
      bin/MAP-5110d730-9f03-11de-8a39-0800200c9a66.png
  66. BIN
      bin/MAP-5e560eb0-9f03-11de-8a39-0800200c9a66.png
  67. BIN
      bin/MAP-63e7cac9-9f38-4855-bcea-988883578c1c.png
  68. BIN
      bin/MAP-68beb460-0dfc-456e-a233-ba939b07c55b.png
  69. BIN
      bin/MAP-6b9e2599-c083-4172-8582-c6c51547c503.png
  70. BIN
      bin/MAP-81695b2d-ab0c-4c12-9bcc-30e962b7ddfc.png
  71. BIN
      bin/MAP-86e4dd4d-6830-41b1-bd1a-44e980c2e67a.png
  72. BIN
      bin/MAP-95f6dca0-99fe-11de-8a39-0800200c9a66.png
  73. BIN
      bin/MAP-99605855-7e20-4721-9bd5-6dcb0f29f70e.png
  74. BIN
      bin/MAP-99b7db71-57bb-4669-80cf-d6d28ab4fd7c.png
  75. BIN
      bin/MAP-a68a4cd2-bcdb-45f0-a793-f202f2347935.png
  76. BIN
      bin/MAP-c1de8dea-caa7-453e-aba7-e823b22768fc.png
  77. BIN
      bin/MAP-cd0af1d7-9adc-4898-98ec-b4593f986451.png
  78. BIN
      bin/MAP-d0c7a2ab-a565-41fa-8a24-2b5bd0664a2b.png
  79. BIN
      bin/MAP-d1a5701b-2fcf-48a7-a420-6966bbf138c1.png
  80. BIN
      bin/MAP-d468609c-8b8e-4505-8c12-8110c15d51d4.png
  81. BIN
      bin/MAP-db95bbe0-533c-11de-8a39-0800200c9a66.png
  82. BIN
      bin/MAP-e53b7c60-a452-11e1-b3dd-0800200c9a66.png
  83. BIN
      bin/MAP-ea329ae9-0f31-462f-bcd9-b19daae22516.png
  84. BIN
      bin/MAP-eb24d66c-5d8a-4592-bf36-e4d5116bc13e.png
  85. BIN
      bin/MAP-f154dd20-a558-11df-981c-0800200c9a66.png
  86. 71 0
      bin/OpenSim.exe.config
  87. 28 0
      bin/OpenSim.ini.example
  88. 1 0
      bin/ROBUST.pid
  89. 5 5
      bin/Robust.exe.config
  90. 24 1
      bin/ScriptSyntax.xml
  91. 28 14
      bin/assets/SettingsAssetSet/SettingsAssetSet.xml
  92. BIN
      bin/assets/SettingsAssetSet/Textures/Altocumulus_Clouds.j2c
  93. BIN
      bin/assets/SettingsAssetSet/Textures/Cumulonimbus_Clouds.j2c
  94. BIN
      bin/assets/SettingsAssetSet/Textures/Layered_Clouds.j2c
  95. BIN
      bin/assets/SettingsAssetSet/Water/DefaultWater.dat
  96. 235 0
      bin/config-include/osslDefaultEnable.ini
  97. 1 0
      bin/http_404.html.example
  98. 14 10
      bin/inventory/SettingsLibrary/Folders.xml
  99. 70 4
      bin/inventory/SettingsLibrary/Items.xml
  100. BIN
      bin/lib64/libode-x86_64.so

+ 6 - 6
OpenSim/Addons/Groups/GroupsModule.cs

@@ -1080,9 +1080,8 @@ namespace OpenSim.Groups
             msg.imSessionID = groupNoticeID.Guid;
             msg.toAgentID = agentID.Guid;
             msg.dialog = dialog;
-            // msg.dialog = (byte)OpenMetaverse.InstantMessageDialog.GroupNotice;
             msg.fromGroup = true;
-            msg.offline = (byte)0;
+            msg.offline = (byte)1;
             msg.ParentEstateID = 0;
             msg.Position = Vector3.Zero;
             msg.RegionID = UUID.Zero.Guid;
@@ -1094,23 +1093,24 @@ namespace OpenSim.Groups
                 msg.timestamp = info.noticeData.Timestamp;
                 msg.fromAgentName = info.noticeData.FromName;
                 msg.message = info.noticeData.Subject + "|" + info.Message;
+
                 if (info.noticeData.HasAttachment)
                 {
                     byte[] name = System.Text.Encoding.UTF8.GetBytes(info.noticeData.AttachmentName);
                     bucket = new byte[19 + name.Length];
                     bucket[0] = 1; // has attachment?
                     bucket[1] = info.noticeData.AttachmentType; // attachment type
-                    info.GroupID.ToBytes(bucket, 2);
                     name.CopyTo(bucket, 18);
                 }
                 else
                 {
                     bucket = new byte[19];
-                    bucket[0] = 0; // Has att?
-                    bucket[1] = 0; // type
-                    bucket[18] = 0; // null terminated
+                    bucket[0] = 0;      //No attachment
+                    bucket[1] = 0;      //Attachment type
+                    bucket[18] = 0;     //NUL terminate name
                 }
 
+                info.GroupID.ToBytes(bucket, 2);
                 msg.binaryBucket = bucket;
             }
             else

+ 85 - 159
OpenSim/Addons/Groups/RemoteConnectorCacheWrapper.cs

@@ -51,12 +51,12 @@ namespace OpenSim.Groups
 
     public class RemoteConnectorCacheWrapper
     {
-        private ForeignImporter m_ForeignImporter;
-
-        private Dictionary<string, bool> m_ActiveRequests = new Dictionary<string, bool>();
         private const int GROUPS_CACHE_TIMEOUT = 1 * 60; // 1 minutes
 
-        // This all important cache cahces objects of different types:
+        private ForeignImporter m_ForeignImporter;
+        private HashSet<string> m_ActiveRequests = new HashSet<string>();
+
+        // This all important cache caches objects of different types:
         // group-<GroupID> or group-<Name>          => ExtendedGroupRecord
         // active-<AgentID>                         => GroupMembershipData
         // membership-<AgentID>-<GroupID>           => GroupMembershipData
@@ -68,7 +68,7 @@ namespace OpenSim.Groups
         // rolemembers-<RequestingAgentID>-<GroupID> => List<ExtendedGroupRoleMembersData>
         // notice-<noticeID>                        => GroupNoticeInfo
         // notices-<GroupID>                        => List<ExtendedGroupNoticeData>
-        private ExpiringCache<string, object> m_Cache = new ExpiringCache<string, object>();
+        private ExpiringCacheOS<string, object> m_Cache = new ExpiringCacheOS<string, object>(30000);
 
         public RemoteConnectorCacheWrapper(IUserManagement uman)
         {
@@ -88,13 +88,10 @@ namespace OpenSim.Groups
                 return UUID.Zero;
 
             if (group.GroupID != UUID.Zero)
-                lock (m_Cache)
-                {
-                    m_Cache.Add("group-" + group.GroupID.ToString(), group, GROUPS_CACHE_TIMEOUT);
-                    if (m_Cache.Contains("memberships-" + RequestingAgentID.ToString()))
-                        m_Cache.Remove("memberships-" + RequestingAgentID.ToString());
-                }
-
+            {
+                m_Cache.AddOrUpdate("group-" + group.GroupID.ToString(), group, GROUPS_CACHE_TIMEOUT);
+                m_Cache.Remove("memberships-" + RequestingAgentID.ToString());
+            }
             return group.GroupID;
         }
 
@@ -105,8 +102,8 @@ namespace OpenSim.Groups
             ExtendedGroupRecord group = d();
 
             if (group != null && group.GroupID != UUID.Zero)
-                lock (m_Cache)
-                    m_Cache.AddOrUpdate("group-" + group.GroupID.ToString(), group, GROUPS_CACHE_TIMEOUT);
+                m_Cache.AddOrUpdate("group-" + group.GroupID.ToString(), group, GROUPS_CACHE_TIMEOUT);
+
             return true;
         }
 
@@ -136,9 +133,9 @@ namespace OpenSim.Groups
                     }
 
                     // not cached
-                    if (!m_ActiveRequests.ContainsKey(cacheKey))
+                    if (!m_ActiveRequests.Contains(cacheKey))
                     {
-                        m_ActiveRequests.Add(cacheKey, true);
+                        m_ActiveRequests.Add(cacheKey);
                         firstCall = true;
                     }
                 }
@@ -180,8 +177,6 @@ namespace OpenSim.Groups
                 m_Cache.AddOrUpdate("active-" + AgentID.ToString(), membership, GROUPS_CACHE_TIMEOUT);
                 m_Cache.AddOrUpdate("membership-" + AgentID.ToString() + "-" + GroupID.ToString(), membership, GROUPS_CACHE_TIMEOUT);
             }
-
-
             return true;
         }
 
@@ -189,37 +184,29 @@ namespace OpenSim.Groups
         {
             d();
 
-            lock (m_Cache)
-            {
-                string cacheKey = "active-" + AgentID.ToString();
-                if (m_Cache.Contains(cacheKey))
-                    m_Cache.Remove(cacheKey);
+            string AgentIDToString = AgentID.ToString();
+            string cacheKey = "active-" + AgentIDToString;
+            m_Cache.Remove(cacheKey);
 
-                cacheKey = "memberships-" + AgentID.ToString();
-                if (m_Cache.Contains(cacheKey))
-                    m_Cache.Remove(cacheKey);
+            cacheKey = "memberships-" + AgentIDToString;
+            m_Cache.Remove(cacheKey);
 
-                cacheKey = "membership-" + AgentID.ToString() + "-" + GroupID.ToString();
-                if (m_Cache.Contains(cacheKey))
-                    m_Cache.Remove(cacheKey);
+            string GroupIDToString = GroupID.ToString();
+            cacheKey = "membership-" + AgentIDToString + "-" + GroupIDToString;
+            m_Cache.Remove(cacheKey);
 
-                cacheKey = "members-" + RequestingAgentID.ToString() + "-" + GroupID.ToString();
-                if (m_Cache.Contains(cacheKey))
-                    m_Cache.Remove(cacheKey);
+            cacheKey = "members-" + RequestingAgentID.ToString() + "-" + GroupIDToString;
+            m_Cache.Remove(cacheKey);
 
-                cacheKey = "roles-" + "-" + GroupID.ToString() + "-" + AgentID.ToString();
-                if (m_Cache.Contains(cacheKey))
-                    m_Cache.Remove(cacheKey);
-            }
+            cacheKey = "roles-" + "-" + GroupIDToString + "-" + AgentIDToString;
+            m_Cache.Remove(cacheKey);
         }
 
         public void SetAgentActiveGroup(string AgentID, GroupMembershipDelegate d)
         {
             GroupMembershipData activeGroup = d();
             string cacheKey = "active-" + AgentID.ToString();
-            lock (m_Cache)
-                if (m_Cache.Contains(cacheKey))
-                    m_Cache.AddOrUpdate(cacheKey, activeGroup, GROUPS_CACHE_TIMEOUT);
+            m_Cache.AddOrUpdate(cacheKey, activeGroup, GROUPS_CACHE_TIMEOUT);
         }
 
         public ExtendedGroupMembershipData GetAgentActiveMembership(string AgentID, GroupMembershipDelegate d)
@@ -241,9 +228,9 @@ namespace OpenSim.Groups
                     }
 
                     // not cached
-                    if (!m_ActiveRequests.ContainsKey(cacheKey))
+                    if (!m_ActiveRequests.Contains(cacheKey))
                     {
-                        m_ActiveRequests.Add(cacheKey, true);
+                       m_ActiveRequests.Add(cacheKey);
                         firstCall = true;
                     }
                 }
@@ -253,12 +240,8 @@ namespace OpenSim.Groups
                     try
                     {
                         membership = d();
-
-                        lock (m_Cache)
-                        {
-                            m_Cache.AddOrUpdate(cacheKey, membership, GROUPS_CACHE_TIMEOUT);
-                            return (ExtendedGroupMembershipData)membership;
-                        }
+                        m_Cache.AddOrUpdate(cacheKey, membership, GROUPS_CACHE_TIMEOUT);
+                        return (ExtendedGroupMembershipData)membership;
                     }
                     finally
                     {
@@ -290,9 +273,9 @@ namespace OpenSim.Groups
                     }
 
                     // not cached
-                    if (!m_ActiveRequests.ContainsKey(cacheKey))
+                    if (!m_ActiveRequests.Contains(cacheKey))
                     {
-                        m_ActiveRequests.Add(cacheKey, true);
+                       m_ActiveRequests.Add(cacheKey);
                         firstCall = true;
                     }
                 }
@@ -302,11 +285,8 @@ namespace OpenSim.Groups
                     try
                     {
                         membership = d();
-                        lock (m_Cache)
-                        {
-                            m_Cache.AddOrUpdate(cacheKey, membership, GROUPS_CACHE_TIMEOUT);
-                            return (ExtendedGroupMembershipData)membership;
-                        }
+                        m_Cache.AddOrUpdate(cacheKey, membership, GROUPS_CACHE_TIMEOUT);
+                        return (ExtendedGroupMembershipData)membership;
                     }
                     finally
                     {
@@ -337,9 +317,9 @@ namespace OpenSim.Groups
                     }
 
                     // not cached
-                    if (!m_ActiveRequests.ContainsKey(cacheKey))
+                    if (!m_ActiveRequests.Contains(cacheKey))
                     {
-                        m_ActiveRequests.Add(cacheKey, true);
+                       m_ActiveRequests.Add(cacheKey);
                         firstCall = true;
                     }
                 }
@@ -349,11 +329,8 @@ namespace OpenSim.Groups
                     try
                     {
                         memberships = d();
-                        lock (m_Cache)
-                        {
-                            m_Cache.AddOrUpdate(cacheKey, memberships, GROUPS_CACHE_TIMEOUT);
-                            return (List<GroupMembershipData>)memberships;
-                        }
+                        m_Cache.AddOrUpdate(cacheKey, memberships, GROUPS_CACHE_TIMEOUT);
+                        return (List<GroupMembershipData>)memberships;
                     }
                     finally
                     {
@@ -385,9 +362,9 @@ namespace OpenSim.Groups
                     }
 
                     // not cached
-                    if (!m_ActiveRequests.ContainsKey(cacheKey))
+                    if (!m_ActiveRequests.Contains(cacheKey))
                     {
-                        m_ActiveRequests.Add(cacheKey, true);
+                       m_ActiveRequests.Add(cacheKey);
                         firstCall = true;
                     }
                 }
@@ -403,13 +380,8 @@ namespace OpenSim.Groups
                         else
                             members = new List<GroupMembersData>();
 
-                        lock (m_Cache)
-                        {
-                            //m_Cache.AddOrUpdate(cacheKey, members, GROUPS_CACHE_TIMEOUT);
-                            m_Cache.AddOrUpdate(cacheKey, _members, GROUPS_CACHE_TIMEOUT);
-
-                            return (List<GroupMembersData>)members;
-                        }
+                        m_Cache.AddOrUpdate(cacheKey, _members, GROUPS_CACHE_TIMEOUT);
+                        return (List<GroupMembersData>)members;
                     }
                     finally
                     {
@@ -433,16 +405,10 @@ namespace OpenSim.Groups
                 role.RoleID = roleID;
                 role.Title = title;
 
-                lock (m_Cache)
-                {
-                    m_Cache.AddOrUpdate("role-" + roleID.ToString(), role, GROUPS_CACHE_TIMEOUT);
+                m_Cache.AddOrUpdate("role-" + roleID.ToString(), role, GROUPS_CACHE_TIMEOUT);
 
                     // also remove this list
-                    if (m_Cache.Contains("roles-" + groupID.ToString()))
-                        m_Cache.Remove("roles-" + groupID.ToString());
-
-                }
-
+                m_Cache.Remove("roles-" + groupID.ToString());
                 return true;
             }
 
@@ -463,22 +429,15 @@ namespace OpenSim.Groups
                         r.Powers = powers;
                         r.Title = title;
 
-                        m_Cache.Update("role-" + roleID.ToString(), r, GROUPS_CACHE_TIMEOUT);
+                        m_Cache.AddOrUpdate("role-" + roleID.ToString(), r, GROUPS_CACHE_TIMEOUT);
                     }
                 return true;
             }
             else
             {
-                lock (m_Cache)
-                {
-                    if (m_Cache.Contains("role-" + roleID.ToString()))
-                        m_Cache.Remove("role-" + roleID.ToString());
-
-                    // also remove these lists, because they will have an outdated role
-                    if (m_Cache.Contains("roles-" + groupID.ToString()))
-                        m_Cache.Remove("roles-" + groupID.ToString());
-
-                }
+                m_Cache.Remove("role-" + roleID.ToString());
+                // also remove these lists, because they will have an outdated role
+                m_Cache.Remove("roles-" + groupID.ToString());
 
                 return false;
             }
@@ -490,18 +449,11 @@ namespace OpenSim.Groups
 
             lock (m_Cache)
             {
-                if (m_Cache.Contains("role-" + roleID.ToString()))
-                    m_Cache.Remove("role-" + roleID.ToString());
-
+                m_Cache.Remove("role-" + roleID.ToString());
                 // also remove the list, because it will have an removed role
-                if (m_Cache.Contains("roles-" + groupID.ToString()))
-                    m_Cache.Remove("roles-" + groupID.ToString());
-
-                if (m_Cache.Contains("roles-" + groupID.ToString() + "-" + RequestingAgentID.ToString()))
-                    m_Cache.Remove("roles-" + groupID.ToString() + "-" + RequestingAgentID.ToString());
-
-                if (m_Cache.Contains("rolemembers-" + RequestingAgentID.ToString() + "-" + groupID.ToString()))
-                    m_Cache.Remove("rolemembers-" + RequestingAgentID.ToString() + "-" + groupID.ToString());
+                m_Cache.Remove("roles-" + groupID.ToString());
+                m_Cache.Remove("roles-" + groupID.ToString() + "-" + RequestingAgentID.ToString());
+                m_Cache.Remove("rolemembers-" + RequestingAgentID.ToString() + "-" + groupID.ToString());
             }
         }
 
@@ -519,9 +471,9 @@ namespace OpenSim.Groups
                         return (List<GroupRolesData>)roles;
 
                     // not cached
-                    if (!m_ActiveRequests.ContainsKey(cacheKey))
+                    if (!m_ActiveRequests.Contains(cacheKey))
                     {
-                        m_ActiveRequests.Add(cacheKey, true);
+                       m_ActiveRequests.Add(cacheKey);
                         firstCall = true;
                     }
                 }
@@ -533,11 +485,8 @@ namespace OpenSim.Groups
                         roles = d();
                         if (roles != null)
                         {
-                            lock (m_Cache)
-                            {
-                                m_Cache.AddOrUpdate(cacheKey, roles, GROUPS_CACHE_TIMEOUT);
-                                return (List<GroupRolesData>)roles;
-                            }
+                            m_Cache.AddOrUpdate(cacheKey, roles, GROUPS_CACHE_TIMEOUT);
+                            return (List<GroupRolesData>)roles;
                         }
                     }
                     finally
@@ -569,9 +518,9 @@ namespace OpenSim.Groups
                     }
 
                     // not cached
-                    if (!m_ActiveRequests.ContainsKey(cacheKey))
+                    if (!m_ActiveRequests.Contains(cacheKey))
                     {
-                        m_ActiveRequests.Add(cacheKey, true);
+                       m_ActiveRequests.Add(cacheKey);
                         firstCall = true;
                     }
                 }
@@ -587,16 +536,13 @@ namespace OpenSim.Groups
                         else
                             rmembers = new List<GroupRoleMembersData>();
 
-                        lock (m_Cache)
-                        {
-                            // For some strange reason, when I cache the list of GroupRoleMembersData,
-                            // it gets emptied out. The TryGet gets an empty list...
-                            //m_Cache.AddOrUpdate(cacheKey, rmembers, GROUPS_CACHE_TIMEOUT);
-                            // Caching the list of ExtendedGroupRoleMembersData doesn't show that issue
-                            // I don't get it.
-                            m_Cache.AddOrUpdate(cacheKey, _rmembers, GROUPS_CACHE_TIMEOUT);
-                            return (List<GroupRoleMembersData>)rmembers;
-                        }
+                        // For some strange reason, when I cache the list of GroupRoleMembersData,
+                        // it gets emptied out. The TryGet gets an empty list...
+                        //m_Cache.AddOrUpdate(cacheKey, rmembers, GROUPS_CACHE_TIMEOUT);
+                        // Caching the list of ExtendedGroupRoleMembersData doesn't show that issue
+                        // I don't get it.
+                        m_Cache.AddOrUpdate(cacheKey, _rmembers, GROUPS_CACHE_TIMEOUT);
+                        return (List<GroupRoleMembersData>)rmembers;
                     }
                     finally
                     {
@@ -671,12 +617,10 @@ namespace OpenSim.Groups
                     }
 
                     cacheKey = "roles-" + GroupID.ToString() + "-" + AgentID.ToString();
-                    if (m_Cache.Contains(cacheKey))
-                        m_Cache.Remove(cacheKey);
+                     m_Cache.Remove(cacheKey);
 
                     cacheKey = "rolemembers-" + RequestingAgentID.ToString() + "-" + GroupID.ToString();
-                    if (m_Cache.Contains(cacheKey))
-                        m_Cache.Remove(cacheKey);
+                    m_Cache.Remove(cacheKey);
                 }
             }
         }
@@ -700,9 +644,9 @@ namespace OpenSim.Groups
                     }
 
                     // not cached
-                    if (!m_ActiveRequests.ContainsKey(cacheKey))
+                    if (!m_ActiveRequests.Contains(cacheKey))
                     {
-                        m_ActiveRequests.Add(cacheKey, true);
+                       m_ActiveRequests.Add(cacheKey);
                         firstCall = true;
                     }
                 }
@@ -712,12 +656,8 @@ namespace OpenSim.Groups
                     try
                     {
                         roles = d();
-                        lock (m_Cache)
-                        {
-                            m_Cache.AddOrUpdate(cacheKey, roles, GROUPS_CACHE_TIMEOUT);
-                            m_ActiveRequests.Remove(cacheKey);
-                            return (List<GroupRolesData>)roles;
-                        }
+                        m_Cache.AddOrUpdate(cacheKey, roles, GROUPS_CACHE_TIMEOUT);
+                        return (List<GroupRolesData>)roles;
                     }
                     finally
                     {
@@ -737,12 +677,10 @@ namespace OpenSim.Groups
             {
                 // Invalidate cached info, because it has ActiveRoleID and Powers
                 string cacheKey = "membership-" + AgentID.ToString() + "-" + GroupID.ToString();
-                if (m_Cache.Contains(cacheKey))
-                    m_Cache.Remove(cacheKey);
+                m_Cache.Remove(cacheKey);
 
                 cacheKey = "memberships-" + AgentID.ToString();
-                if (m_Cache.Contains(cacheKey))
-                    m_Cache.Remove(cacheKey);
+                m_Cache.Remove(cacheKey);
             }
         }
 
@@ -757,8 +695,7 @@ namespace OpenSim.Groups
                     m_Cache.Remove(cacheKey);
 
                 cacheKey = "memberships-" + AgentID.ToString();
-                if (m_Cache.Contains(cacheKey))
-                    m_Cache.Remove(cacheKey);
+                m_Cache.Remove(cacheKey);
 
                 cacheKey = "active-" + AgentID.ToString();
                 object m = null;
@@ -775,14 +712,9 @@ namespace OpenSim.Groups
         {
             if (d())
             {
-                lock (m_Cache)
-                {
-                    m_Cache.AddOrUpdate("notice-" + noticeID.ToString(), notice, GROUPS_CACHE_TIMEOUT);
-                    string cacheKey = "notices-" + groupID.ToString();
-                    if (m_Cache.Contains(cacheKey))
-                        m_Cache.Remove(cacheKey);
-
-                }
+                m_Cache.AddOrUpdate("notice-" + noticeID.ToString(), notice, GROUPS_CACHE_TIMEOUT);
+                string cacheKey = "notices-" + groupID.ToString();
+                m_Cache.Remove(cacheKey);
 
                 return true;
             }
@@ -808,9 +740,9 @@ namespace OpenSim.Groups
                     }
 
                     // not cached
-                    if (!m_ActiveRequests.ContainsKey(cacheKey))
+                    if (!m_ActiveRequests.Contains(cacheKey))
                     {
-                        m_ActiveRequests.Add(cacheKey, true);
+                       m_ActiveRequests.Add(cacheKey);
                         firstCall = true;
                     }
                 }
@@ -821,11 +753,8 @@ namespace OpenSim.Groups
                     {
                         GroupNoticeInfo _notice = d();
 
-                        lock (m_Cache)
-                        {
-                            m_Cache.AddOrUpdate(cacheKey, _notice, GROUPS_CACHE_TIMEOUT);
-                            return _notice;
-                        }
+                        m_Cache.AddOrUpdate(cacheKey, _notice, GROUPS_CACHE_TIMEOUT);
+                        return _notice;
                     }
                     finally
                     {
@@ -856,9 +785,9 @@ namespace OpenSim.Groups
                     }
 
                     // not cached
-                    if (!m_ActiveRequests.ContainsKey(cacheKey))
+                    if (!m_ActiveRequests.Contains(cacheKey))
                     {
-                        m_ActiveRequests.Add(cacheKey, true);
+                       m_ActiveRequests.Add(cacheKey);
                         firstCall = true;
                     }
                 }
@@ -869,11 +798,8 @@ namespace OpenSim.Groups
                     {
                         notices = d();
 
-                        lock (m_Cache)
-                        {
-                            m_Cache.AddOrUpdate(cacheKey, notices, GROUPS_CACHE_TIMEOUT);
-                            return (List<ExtendedGroupNoticeData>)notices;
-                        }
+                        m_Cache.AddOrUpdate(cacheKey, notices, GROUPS_CACHE_TIMEOUT);
+                        return (List<ExtendedGroupNoticeData>)notices;
                     }
                     finally
                     {

+ 10 - 6
OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs

@@ -1744,13 +1744,14 @@ namespace OpenSim.ApplicationPlugins.RemoteController
                 //}
 
                 if (requestData.Contains("home"))
-                {
                     options["home"] = (string)requestData["home"];
-                }
 
-                if ((string)requestData["noassets"] == "true")
+                if (requestData.Contains("noassets"))
                 {
-                    options["noassets"] = (string)requestData["noassets"] ;
+                    string tmp = (string)requestData["noassets"];
+                    if (!string.IsNullOrWhiteSpace(tmp) &&
+                        (tmp.Equals("true", StringComparison.InvariantCultureIgnoreCase) || tmp.Equals("1")))
+                        options["noassets"] = true;
                 }
 
                 if (requestData.Contains("perm"))
@@ -1758,9 +1759,12 @@ namespace OpenSim.ApplicationPlugins.RemoteController
                     options["checkPermissions"] = (string)requestData["perm"];
                 }
 
-                if ((string)requestData["all"] == "true")
+                if (requestData.Contains("all"))
                 {
-                    options["all"] = (string)requestData["all"];
+                    string tmp = (string)requestData["all"];
+                    if (!string.IsNullOrWhiteSpace(tmp) &&
+                        (tmp.Equals("true", StringComparison.InvariantCultureIgnoreCase) || tmp.Equals("1")))
+                        options["all"] = true;
                 }
 
                 IRegionArchiverModule archiver = scene.RequestModuleInterface<IRegionArchiverModule>();

+ 51 - 39
OpenSim/Data/Tests/RegionTests.cs

@@ -255,7 +255,7 @@ namespace OpenSim.Data.Tests
             creator = UUID.Random();
             uint iserial = (uint)random.Next();
             TaskInventoryDictionary dic = new TaskInventoryDictionary();
-            uint objf = (uint) random.Next();
+            uint objf = (uint) random.Next() & (uint)~(PrimFlags.Touch | PrimFlags.Money | PrimFlags.AllowInventoryDrop);
             uuid = prim4;
             uint localid = localID+1;
             localID = localID + 1;
@@ -272,6 +272,7 @@ namespace OpenSim.Data.Tests
             Vector3 groupos = new Vector3(random.Next(100000),random.Next(100000),random.Next(100000));
             Vector3 offset = new Vector3(random.Next(100000),random.Next(100000),random.Next(100000));
             Quaternion rotoff = new Quaternion(random.Next(1),random.Next(1),random.Next(1),random.Next(1));
+            rotoff.Normalize();
             Vector3 velocity = new Vector3(random.Next(100000),random.Next(100000),random.Next(100000));
             Vector3 angvelo = new Vector3(random.Next(100000),random.Next(100000),random.Next(100000));
             Vector3 accel = new Vector3(random.Next(100000),random.Next(100000),random.Next(100000));
@@ -291,10 +292,12 @@ namespace OpenSim.Data.Tests
             pbshap.ProfileHollow = ushort.MaxValue;
             Vector3 scale = new Vector3(random.Next(100000),random.Next(100000),random.Next(100000));
 
-            RegionInfo regionInfo = new RegionInfo();
-            regionInfo.RegionID = region3;
-            regionInfo.RegionLocX = 0;
-            regionInfo.RegionLocY = 0;
+            RegionInfo regionInfo = new RegionInfo()
+            {
+                RegionID = region3,
+                RegionLocX = 0,
+                RegionLocY = 0
+            };
 
             SceneObjectPart sop = new SceneObjectPart();
             SceneObjectGroup sog = new SceneObjectGroup(sop);
@@ -334,7 +337,7 @@ namespace OpenSim.Data.Tests
             Assert.That(localid,Is.EqualTo(sop.LocalId), "Assert.That(localid,Is.EqualTo(sop.LocalId))");
             Assert.That(groupos,Is.EqualTo(sop.GroupPosition), "Assert.That(groupos,Is.EqualTo(sop.GroupPosition))");
             Assert.That(name,Is.EqualTo(sop.Name), "Assert.That(name,Is.EqualTo(sop.Name))");
-            Assert.That(rotoff,Is.EqualTo(sop.RotationOffset), "Assert.That(rotoff,Is.EqualTo(sop.RotationOffset))");
+            Assert.That(rotoff, new QuaternionToleranceConstraint(sop.RotationOffset, 0.001), "Assert.That(rotoff,Is.EqualTo(sop.RotationOffset))");
             Assert.That(uuid,Is.EqualTo(sop.UUID), "Assert.That(uuid,Is.EqualTo(sop.UUID))");
             Assert.That(creator,Is.EqualTo(sop.CreatorID), "Assert.That(creator,Is.EqualTo(sop.CreatorID))");
             // Modified in-class
@@ -445,7 +448,8 @@ namespace OpenSim.Data.Tests
             DateTime rezzed = new DateTime(2005, 07, 15);
             Vector3 groupos = new Vector3(random.Next(100000),random.Next(100000),random.Next(100000));
             Vector3 offset = new Vector3(random.Next(100000),random.Next(100000),random.Next(100000));
-            Quaternion rotoff = new Quaternion(random.Next(100000),random.Next(100000),random.Next(100000),random.Next(100000));
+            Quaternion rotoff = new Quaternion(random.Next(100),random.Next(100),random.Next(100),random.Next(100));
+            rotoff.Normalize();
             Vector3 velocity = new Vector3(random.Next(100000),random.Next(100000),random.Next(100000));
             Vector3 angvelo = new Vector3(random.Next(100000),random.Next(100000),random.Next(100000));
             Vector3 accel = new Vector3(random.Next(100000),random.Next(100000),random.Next(100000));
@@ -499,7 +503,7 @@ namespace OpenSim.Data.Tests
             Assert.That(regionh,Is.EqualTo(p.RegionHandle), "Assert.That(regionh,Is.EqualTo(p.RegionHandle))");
             Assert.That(groupos,Is.EqualTo(p.GroupPosition), "Assert.That(groupos,Is.EqualTo(p.GroupPosition))");
             Assert.That(name,Is.EqualTo(p.Name), "Assert.That(name,Is.EqualTo(p.Name))");
-            Assert.That(rotoff,Is.EqualTo(p.RotationOffset), "Assert.That(rotoff,Is.EqualTo(p.RotationOffset))");
+            Assert.That(rotoff, new QuaternionToleranceConstraint(p.RotationOffset, 0.001), "Assert.That(rotoff,Is.EqualTo(p.RotationOffset))");
             Assert.That(creator,Is.EqualTo(p.CreatorID), "Assert.That(creator,Is.EqualTo(p.CreatorID))");
             Assert.That(dic,Is.EqualTo(p.TaskInventory), "Assert.That(dic,Is.EqualTo(p.TaskInventory))");
             Assert.That(name,Is.EqualTo(p.Name), "Assert.That(name,Is.EqualTo(p.Name))");
@@ -538,7 +542,8 @@ namespace OpenSim.Data.Tests
                 SceneObjectPart sop = NewSOP(("Test SOP " + i.ToString()),tmp);
                 Vector3 groupos = new Vector3(random.Next(100000),random.Next(100000),random.Next(100000));
                 Vector3 offset = new Vector3(random.Next(100000),random.Next(100000),random.Next(100000));
-                Quaternion rotoff = new Quaternion(random.Next(100000),random.Next(100000),random.Next(100000),random.Next(100000));
+                Quaternion rotoff = new Quaternion(random.Next(1000),random.Next(1000),random.Next(1000),random.Next(1000));
+                rotoff.Normalize();
                 Vector3 velocity = new Vector3(random.Next(100000),random.Next(100000),random.Next(100000));
                 Vector3 angvelo = new Vector3(random.Next(100000),random.Next(100000),random.Next(100000));
                 Vector3 accel = new Vector3(random.Next(100000),random.Next(100000),random.Next(100000));
@@ -555,14 +560,13 @@ namespace OpenSim.Data.Tests
             }
 
             db.StoreObject(sog, region4);
-
             SceneObjectGroup retsog = FindSOG("Test SOG", region4);
             SceneObjectPart[] parts = retsog.Parts;
             for (int i = 0; i < 30; i++)
             {
                 SceneObjectPart cursop = mydic[parts[i].UUID];
                 Assert.That(cursop.GroupPosition,Is.EqualTo(parts[i].GroupPosition), "Assert.That(cursop.GroupPosition,Is.EqualTo(parts[i].GroupPosition))");
-                Assert.That(cursop.RotationOffset,Is.EqualTo(parts[i].RotationOffset), "Assert.That(cursop.RotationOffset,Is.EqualTo(parts[i].RotationOffset))");
+                Assert.That(cursop.RotationOffset, new QuaternionToleranceConstraint(parts[i].RotationOffset, 0.001), "Assert.That(rotoff,Is.EqualTo(p.RotationOffset))");
                 Assert.That(cursop.OffsetPosition,Is.EqualTo(parts[i].OffsetPosition), "Assert.That(cursop.OffsetPosition,Is.EqualTo(parts[i].OffsetPosition))");
                 Assert.That(cursop.Velocity,Is.EqualTo(parts[i].Velocity), "Assert.That(cursop.Velocity,Is.EqualTo(parts[i].Velocity))");
                 Assert.That(cursop.AngularVelocity,Is.EqualTo(parts[i].AngularVelocity), "Assert.That(cursop.AngularVelocity,Is.EqualTo(parts[i].AngularVelocity))");
@@ -1064,19 +1068,23 @@ namespace OpenSim.Data.Tests
         //
         private SceneObjectGroup NewSOG(string name, UUID uuid, UUID regionId)
         {
-            RegionInfo regionInfo = new RegionInfo();
-            regionInfo.RegionID = regionId;
-            regionInfo.RegionLocX = 0;
-            regionInfo.RegionLocY = 0;
+            RegionInfo regionInfo = new RegionInfo
+            {
+                RegionID = regionId,
+                RegionLocX = 0,
+                RegionLocY = 0
+            };
 
-            SceneObjectPart sop = new SceneObjectPart();
-            sop.Name = name;
-            sop.Description = name;
-            sop.Text = RandomName();
-            sop.SitName = RandomName();
-            sop.TouchName = RandomName();
-            sop.UUID = uuid;
-            sop.Shape = PrimitiveBaseShape.Default;
+            SceneObjectPart sop = new SceneObjectPart
+            {
+                Name = name,
+                Description = name,
+                Text = RandomName(),
+                SitName = RandomName(),
+                TouchName = RandomName(),
+                UUID = uuid,
+                Shape = PrimitiveBaseShape.Default
+            };
 
             SceneObjectGroup sog = new SceneObjectGroup(sop);
 
@@ -1085,14 +1093,16 @@ namespace OpenSim.Data.Tests
 
         private SceneObjectPart NewSOP(string name, UUID uuid)
         {
-            SceneObjectPart sop = new SceneObjectPart();
-            sop.Name = name;
-            sop.Description = name;
-            sop.Text = RandomName();
-            sop.SitName = RandomName();
-            sop.TouchName = RandomName();
-            sop.UUID = uuid;
-            sop.Shape = PrimitiveBaseShape.Default;
+            SceneObjectPart sop = new SceneObjectPart
+            {
+                Name = name,
+                Description = name,
+                Text = RandomName(),
+                SitName = RandomName(),
+                TouchName = RandomName(),
+                UUID = uuid,
+                Shape = PrimitiveBaseShape.Default
+            };
             return sop;
         }
 
@@ -1100,14 +1110,16 @@ namespace OpenSim.Data.Tests
 
         private InventoryItemBase NewItem(UUID id, UUID parent, UUID owner, string name, UUID asset)
         {
-            InventoryItemBase i = new InventoryItemBase();
-            i.ID = id;
-            i.Folder = parent;
-            i.Owner = owner;
-            i.CreatorId = owner.ToString();
-            i.Name = name;
-            i.Description = name;
-            i.AssetID = asset;
+            InventoryItemBase i = new InventoryItemBase
+            {
+                ID = id,
+                Folder = parent,
+                Owner = owner,
+                CreatorId = owner.ToString(),
+                Name = name,
+                Description = name,
+                AssetID = asset
+            };
             return i;
         }
 

+ 1 - 0
OpenSim/Framework/AgentCircuitManager.cs

@@ -95,6 +95,7 @@ namespace OpenSim.Framework
 
         public virtual void AddNewCircuit(uint circuitCode, AgentCircuitData agentData)
         {
+            agentData.circuitcode = circuitCode;
             RemoveCircuit(agentData.AgentID); // no duplications
             m_agentCircuits[circuitCode] = agentData;
             m_agentCircuitsByUUID[agentData.AgentID] = agentData;

+ 5 - 0
OpenSim/Framework/GridInfo.cs

@@ -145,6 +145,11 @@ namespace OpenSim.Framework
             get { return Flags == OSHTTPURIFlags.None ? "" : URI + "/";}
         }
 
+        public string HostAndPort
+        {
+            get { return (Flags == OSHTTPURIFlags.None) ? "" : Host + ":" + Port.ToString(); }
+        }
+
         public int CompareTo(OSHTTPURI other)
         {
             if (Port == other.Port && ((Flags & other.Flags) & OSHTTPURIFlags.ValidHost) != 0)

+ 31 - 55
OpenSim/Framework/Monitoring/JobEngine.cs

@@ -51,25 +51,11 @@ namespace OpenSim.Framework.Monitoring
         /// </summary>
         public bool IsRunning { get; private set; }
 
-        /// <summary>
-        /// The current job that the engine is running.
-        /// </summary>
-        /// <remarks>
-        /// Will be null if no job is currently running.
-        /// </remarks>
-        private Job m_currentJob;
-        public Job CurrentJob { get { return m_currentJob;} }
-
         /// <summary>
         /// Number of jobs waiting to be processed.
         /// </summary>
         public int JobsWaiting { get { return m_jobQueue.Count; } }
 
-        /// <summary>
-        /// The timeout in milliseconds to wait for at least one event to be written when the recorder is stopping.
-        /// </summary>
-        public int RequestProcessTimeoutOnStop { get; set; }
-
         /// <summary>
         /// Controls whether we need to warn in the log about exceeding the max queue size.
         /// </summary>
@@ -84,15 +70,16 @@ namespace OpenSim.Framework.Monitoring
         private CancellationTokenSource m_cancelSource;
 
         private int m_timeout = -1;
+        private int m_concurrency = 1;
 
-        private bool m_threadRunnig = false;
+        private int m_numberThreads = 0;
 
-        public JobEngine(string name, string loggingName, int timeout = -1)
+        public JobEngine(string name, string loggingName, int timeout = -1, int concurrency = 1)
         {
             Name = name;
             LoggingName = loggingName;
             m_timeout = timeout;
-            RequestProcessTimeoutOnStop = 5000;
+            m_concurrency = concurrency;
         }
 
         public void Start()
@@ -101,12 +88,10 @@ namespace OpenSim.Framework.Monitoring
             {
                 if (IsRunning)
                     return;
-
+                if(m_concurrency < 1)
+                    m_concurrency = 1;
                 IsRunning = true;
-
                 m_cancelSource = new CancellationTokenSource();
-                //WorkManager.RunInThreadPool(ProcessRequests, null, Name, false);
-                //m_threadRunnig = true;
             }
         }
 
@@ -122,10 +107,10 @@ namespace OpenSim.Framework.Monitoring
                     m_log.DebugFormat("[JobEngine] Stopping {0}", Name);
 
                     IsRunning = false;
-                    if(m_threadRunnig)
+                    if(m_numberThreads > 0)
                     {
                         m_cancelSource.Cancel();
-                        m_threadRunnig = false;
+                        Thread.Yield();
                     }
                 }
                 finally
@@ -198,22 +183,21 @@ namespace OpenSim.Framework.Monitoring
         /// </param>
         public bool QueueJob(Job job)
         {
-            lock(JobLock)
-            {
-                if(!IsRunning)
-                    return false;
-                
-                if(!m_threadRunnig)
-                {
-                     WorkManager.RunInThreadPool(ProcessRequests, null, Name, false);
-                     m_threadRunnig = true;
-                }
-            }
+            if (!IsRunning)
+                return false;
 
             if (m_jobQueue.Count < m_jobQueue.BoundedCapacity)
             {
                 m_jobQueue.Add(job);
 
+                lock (JobLock)
+                {
+                    if (m_numberThreads < m_concurrency && m_numberThreads < m_jobQueue.Count)
+                    {
+                        Util.FireAndForget(ProcessRequests, null, Name, false);
+                        ++m_numberThreads;
+                    }
+                }
                 if (!m_warnOverMaxQueue)
                     m_warnOverMaxQueue = true;
 
@@ -233,24 +217,15 @@ namespace OpenSim.Framework.Monitoring
             }
         }
 
-        private void ProcessRequests(Object o)
+        private void ProcessRequests(object o)
         {
-            while(IsRunning)
+            Job currentJob;
+            while (IsRunning)
             {
                 try
                 {
-                    if(!m_jobQueue.TryTake(out m_currentJob, m_timeout, m_cancelSource.Token))
-                    {
-                        lock(JobLock)
-                            m_threadRunnig = false;
+                    if(!m_jobQueue.TryTake(out currentJob, m_timeout, m_cancelSource.Token))
                         break;
-                    }
-                }
-                catch (OperationCanceledException)
-                {
-                    m_log.DebugFormat("[JobEngine] {0} Canceled ignoring {1} jobs in queue",
-                        Name, m_jobQueue.Count);
-                    break;
                 }
                 catch
                 {
@@ -258,25 +233,26 @@ namespace OpenSim.Framework.Monitoring
                 }
 
                 if(LogLevel >= 1)
-                    m_log.DebugFormat("[{0}]: Processing job {1}",LoggingName,m_currentJob.Name);
+                    m_log.DebugFormat("[{0}]: Processing job {1}",LoggingName,currentJob.Name);
 
                 try
                 {
-                    m_currentJob.Action();
+                    currentJob.Action();
                 }
                 catch(Exception e)
                 {
-                    m_log.Error(
-                        string.Format(
-                        "[{0}]: Job {1} failed, continuing.  Exception  ",LoggingName,m_currentJob.Name),e);
+                    m_log.ErrorFormat(
+                        "[{0}]: Job {1} failed, continuing.  Exception {2}",LoggingName, currentJob.Name, e);
                 }
 
                 if(LogLevel >= 1)
-                    m_log.DebugFormat("[{0}]: Processed job {1}",LoggingName,m_currentJob.Name);
+                    m_log.DebugFormat("[{0}]: Processed job {1}",LoggingName,currentJob.Name);
 
-                m_currentJob.Action = null;
-                m_currentJob = null;
+                currentJob.Action = null;
+                currentJob = null;
             }
+            lock (JobLock)
+                --m_numberThreads;
         }
 
         public class Job

+ 0 - 4
OpenSim/Framework/Monitoring/WorkManager.cs

@@ -225,10 +225,6 @@ namespace OpenSim.Framework.Monitoring
             else if (subCommand == "status")
             {
                 MainConsole.Instance.Output("Job engine running: {0}", JobEngine.IsRunning);
-
-                JobEngine.Job job = JobEngine.CurrentJob;
-                MainConsole.Instance.Output("Current job {0}", job != null ? job.Name : "none");
-
                 MainConsole.Instance.Output(
                     "Jobs waiting: {0}", JobEngine.IsRunning ? JobEngine.JobsWaiting.ToString() : "n/a");
                 MainConsole.Instance.Output("Log Level: {0}", JobEngine.LogLevel);

+ 189 - 0
OpenSim/Framework/ObjectJobEngine.cs

@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of the OpenSimulator Project nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// A pool of jobs or workitems with same method (callback) but diferent argument (as object) to run in main threadpool
+// can have up to m_concurrency number of execution threads
+// it will hold each thread up to m_threadsHoldtime ms waiting for more work, before releasing it back to the pool.
+
+using System;
+using System.Collections.Concurrent;
+using System.Reflection;
+using System.Threading;
+using log4net;
+
+namespace OpenSim.Framework
+{
+    public class ObjectJobEngine : IDisposable
+    {
+        private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+
+        private readonly object m_mainLock = new object();
+        private readonly string m_name;
+        private readonly int m_threadsHoldtime;
+        private readonly int m_concurrency = 1;
+
+        private BlockingCollection<object> m_jobQueue;
+        private CancellationTokenSource m_cancelSource;
+        private WaitCallback m_callback;
+        private int m_numberThreads = 0;
+        private bool m_isRunning;
+
+        public ObjectJobEngine(WaitCallback callback, string name, int threadsHoldtime = 1000, int concurrency = 1)
+        {
+            m_name = name;
+            m_threadsHoldtime = threadsHoldtime;
+
+            if (concurrency < 1)
+                m_concurrency = 1;
+            else
+                m_concurrency = concurrency;
+
+            if (callback !=  null)
+            {
+                m_callback = callback;
+                m_jobQueue = new BlockingCollection<object>();
+                m_cancelSource = new CancellationTokenSource();
+                m_isRunning = true;
+            }
+        }
+
+        ~ObjectJobEngine()
+        {
+            Dispose(false);
+        }
+
+        public void Dispose()
+        {
+            Dispose(true);
+            GC.SuppressFinalize(this);
+        }
+
+        private void Dispose(bool disposing)
+        {
+            lock(m_mainLock)
+            {
+                if (!m_isRunning)
+                    return;
+                m_isRunning = false;
+
+                m_cancelSource.Cancel();
+            }
+
+            if (m_numberThreads > 0)
+            {
+                int cntr = 100;
+                while (m_numberThreads > 0 && --cntr > 0)
+                    Thread.Yield();
+            }
+
+            if (m_jobQueue != null)
+            {
+                m_jobQueue.Dispose();
+                m_jobQueue = null;
+            }
+            if (m_cancelSource != null)
+            {
+                m_cancelSource.Dispose();
+                m_cancelSource = null;
+            }
+            m_callback = null;
+        }
+
+        /// <summary>
+        /// Number of jobs waiting to be processed.
+        /// </summary>
+        public int Count { get { return m_jobQueue == null ? 0 : m_jobQueue.Count; } }
+
+        public void Cancel()
+        {
+            if (!m_isRunning || m_jobQueue == null || m_jobQueue.Count == 0)
+                return;
+            try
+            {
+                while(m_jobQueue.TryTake(out object dummy));
+                m_cancelSource.Cancel();
+            }
+            catch { }
+        }
+
+        /// <summary>
+        /// Queue the job for processing.
+        /// </summary>
+        /// <returns><c>true</c>, if job was queued, <c>false</c> otherwise.</returns>
+        /// <param name="job">The job</param>
+        /// </param>
+        public bool Enqueue(object o)
+        {
+            if (!m_isRunning)
+                return false;
+
+            m_jobQueue?.Add(o);
+
+            lock (m_mainLock)
+            {
+                if (m_numberThreads < m_concurrency && m_numberThreads < m_jobQueue.Count)
+                {
+                    Util.FireAndForget(ProcessRequests, null, m_name, false);
+                    ++m_numberThreads;
+                }
+            }
+            return true;
+        }
+
+        private void ProcessRequests(object o)
+        {
+            object obj;
+            while (m_isRunning)
+            {
+                try
+                {
+                    if(!m_jobQueue.TryTake(out obj, m_threadsHoldtime, m_cancelSource.Token))
+                        break;
+                }
+                catch
+                {
+                    break;
+                }
+
+                if(!m_isRunning || m_callback == null)
+                    break;
+                try
+                {
+                    m_callback.Invoke(obj);
+                    obj = null;
+                }
+                catch (Exception e)
+                {
+                    m_log.ErrorFormat(
+                        "[ObjectJob {0}]: Job failed, continuing.  Exception {1}",m_name, e);
+                }
+            }
+            lock (m_mainLock)
+                --m_numberThreads;
+        }
+    }
+}

+ 36 - 4
OpenSim/Framework/Serialization/External/RegionSettingsSerializer.cs

@@ -44,21 +44,25 @@ namespace OpenSim.Framework.Serialization.External
         /// Deserialize settings
         /// </summary>
         /// <param name="serializedSettings"></param>
+        /// <param name="regionEnv"></param>
+        /// <param name="estateSettings">The Estate Settings stored in the archive will be merged into this object</param>
         /// <returns></returns>
         /// <exception cref="System.Xml.XmlException"></exception>
-        public static RegionSettings Deserialize(byte[] serializedSettings, out ViewerEnvironment regionEnv)
+        public static RegionSettings Deserialize(byte[] serializedSettings, out ViewerEnvironment regionEnv, EstateSettings estateSettings)
         {
             // encoding is wrong. old oars seem to be on utf-16
-            return Deserialize(Encoding.ASCII.GetString(serializedSettings, 0, serializedSettings.Length), out regionEnv);
+            return Deserialize(Encoding.ASCII.GetString(serializedSettings, 0, serializedSettings.Length), out regionEnv, estateSettings);
         }
 
         /// <summary>
         /// Deserialize settings
         /// </summary>
         /// <param name="serializedSettings"></param>
+        /// <param name="regionEnv"></param>
+        /// <param name="estateSettings">The Estate Settings stored in the archive will be merged into this object</param>
         /// <returns></returns>
         /// <exception cref="System.Xml.XmlException"></exception>
-        public static RegionSettings Deserialize(string serializedSettings, out ViewerEnvironment regionEnv)
+        public static RegionSettings Deserialize(string serializedSettings, out ViewerEnvironment regionEnv, EstateSettings estateSettings)
         {
             RegionSettings settings = new RegionSettings();
             regionEnv = null;
@@ -237,13 +241,36 @@ namespace OpenSim.Framework.Serialization.External
                 }
             }
 
+            if (xtr.IsStartElement("Estate"))
+            {
+                if (xtr.IsEmptyElement)
+                    xtr.Read();
+                else
+                {
+                    xtr.ReadStartElement("Estate");
+                    while (xtr.Read() && xtr.NodeType != XmlNodeType.EndElement)
+                    {
+                        switch (xtr.Name)
+                        {
+                            case "AllowDirectTeleport":
+                                estateSettings.AllowDirectTeleport = bool.Parse(xtr.ReadElementContentAsString());
+                                break;
+                            case "AllowEnvironmentOverride":
+                                estateSettings.AllowEnvironmentOverride = bool.Parse(xtr.ReadElementContentAsString());
+                                break;
+                        }
+                    }
+                    xtr.ReadEndElement();
+                }
+            }
+
             xtr.Close();
             sr.Close();
 
             return settings;
         }
 
-        public static string Serialize(RegionSettings settings, ViewerEnvironment RegionEnv)
+        public static string Serialize(RegionSettings settings, ViewerEnvironment RegionEnv, EstateSettings estateSettings)
         {
             StringWriter sw = new StringWriter();
             XmlTextWriter xtw = new XmlTextWriter(sw);
@@ -308,6 +335,11 @@ namespace OpenSim.Framework.Serialization.External
                 xtw.WriteEndElement();
             }
 
+            xtw.WriteStartElement("Estate");
+            xtw.WriteElementString("AllowDirectTeleport", estateSettings.AllowDirectTeleport.ToString());
+            xtw.WriteElementString("AllowEnvironmentOverride", estateSettings.AllowEnvironmentOverride.ToString());
+            xtw.WriteEndElement();
+
             xtw.WriteEndElement();
 
             xtw.Close();

+ 1 - 1
OpenSim/Framework/Serialization/Tests/RegionSettingsSerializerTests.cs

@@ -130,7 +130,7 @@ namespace OpenSim.Framework.Serialization.Tests
             TestHelpers.InMethod();
 //            log4net.Config.XmlConfigurator.Configure();
 
-            RegionSettings deserRs = RegionSettingsSerializer.Deserialize(m_serializedRs, out ViewerEnvironment dummy);
+            RegionSettings deserRs = RegionSettingsSerializer.Deserialize(m_serializedRs, out ViewerEnvironment dummy, new EstateSettings());
             Assert.That(deserRs, Is.Not.Null);
             Assert.That(deserRs.TerrainTexture2, Is.EqualTo(m_rs.TerrainTexture2));
             Assert.That(deserRs.DisablePhysics, Is.EqualTo(m_rs.DisablePhysics));

+ 39 - 0
OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs

@@ -650,6 +650,8 @@ namespace OpenSim.Framework.Servers.HttpServer
 
             IRequestHandler requestHandler = null;
 
+            byte[] responseData = null;
+
             try
             {
                 // OpenSim.Framework.WebUtil.OSHeaderRequestID
@@ -671,6 +673,7 @@ namespace OpenSim.Framework.Servers.HttpServer
                         request.InputStream.Dispose();
 
                     requestEndTick = Environment.TickCount;
+                    responseData = response.RawBuffer;
                     response.Send();
                     return;
                 }
@@ -692,6 +695,7 @@ namespace OpenSim.Framework.Servers.HttpServer
                             request.InputStream.Dispose();
 
                         requestEndTick = Environment.TickCount;
+                        responseData = response.RawBuffer;
                         response.Send();
                         return;
                     }
@@ -736,6 +740,7 @@ namespace OpenSim.Framework.Servers.HttpServer
                         request.InputStream.Dispose();
 
                     requestEndTick = Environment.TickCount;
+                    responseData = response.RawBuffer;
                     response.Send();
                     return;
                 }
@@ -744,11 +749,15 @@ namespace OpenSim.Framework.Servers.HttpServer
 
                 if (TryGetSimpleStreamHandler(path, out ISimpleStreamHandler hdr))
                 {
+                    if (DebugLevel >= 3)
+                        LogIncomingToStreamHandler(request, hdr);
+
                     hdr.Handle(request, response);
                     if (request.InputStream != null && request.InputStream.CanRead)
                         request.InputStream.Dispose();
 
                     requestEndTick = Environment.TickCount;
+                    responseData = response.RawBuffer;
                     response.Send();
                     return;
                 }
@@ -898,6 +907,7 @@ namespace OpenSim.Framework.Servers.HttpServer
                 requestEndTick = Environment.TickCount;
 
                 buffer = null;
+                responseData = response.RawBuffer;
                 response.Send();
             }
             catch (SocketException e)
@@ -921,6 +931,7 @@ namespace OpenSim.Framework.Servers.HttpServer
                 try
                 {
                     response.StatusCode =(int)HttpStatusCode.InternalServerError;
+                    responseData = response.RawBuffer;
                     response.Send();
                 }
                 catch {}
@@ -951,6 +962,19 @@ namespace OpenSim.Framework.Servers.HttpServer
                         Port,
                         tickdiff);
                 }
+
+                if ((DebugLevel >= 5) && (responseData != null))
+                {
+                    string output = Encoding.UTF8.GetString(responseData);
+                    if (DebugLevel == 5)
+                    {
+                        if (output.Length > WebUtil.MaxRequestDiagLength)
+                            output = output.Substring(0, WebUtil.MaxRequestDiagLength) + "...";
+                    }
+                    m_log.DebugFormat("[LOGHTTP] RESPONSE {0}: {1}", RequestNumber, output);
+                }
+
+                responseData = null;
             }
         }
 
@@ -970,6 +994,21 @@ namespace OpenSim.Framework.Servers.HttpServer
                 LogIncomingInDetail(request);
         }
 
+        private void LogIncomingToStreamHandler(OSHttpRequest request, ISimpleStreamHandler requestHandler)
+        {
+            m_log.DebugFormat(
+                "[LOGHTTP] HTTP IN {0} :{1} stream handler {2} {3} {4} from {5}",
+                RequestNumber,
+                Port,
+                request.HttpMethod,
+                request.Url.PathAndQuery,
+                requestHandler.Name,
+                request.RemoteIPEndPoint);
+
+            if (DebugLevel >= 5)
+                LogIncomingInDetail(request);
+        }
+
         private void LogIncomingToContentTypeHandler(OSHttpRequest request)
         {
             m_log.DebugFormat(

+ 49 - 81
OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs

@@ -41,11 +41,10 @@ namespace OpenSim.Framework.Servers.HttpServer
     {
         private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
 
-        private BlockingCollection<PollServiceHttpRequest> m_requests = new BlockingCollection<PollServiceHttpRequest>();
         private ConcurrentQueue<PollServiceHttpRequest> m_retryRequests = new ConcurrentQueue<PollServiceHttpRequest>();
 
-        private uint m_WorkerThreadCount = 0;
-        private Thread[] m_workerThreads;
+        private int m_WorkerThreadCount = 0;
+        private ObjectJobEngine m_workerPool;
         private Thread m_retrysThread;
 
         private bool m_running = false;
@@ -53,8 +52,7 @@ namespace OpenSim.Framework.Servers.HttpServer
         public PollServiceRequestManager(
             bool performResponsesAsync, uint pWorkerThreadCount, int pTimeout)
         {
-            m_WorkerThreadCount = pWorkerThreadCount;
-            m_workerThreads = new Thread[m_WorkerThreadCount];
+            m_WorkerThreadCount = (int)pWorkerThreadCount;
         }
 
         public void Start()
@@ -62,22 +60,10 @@ namespace OpenSim.Framework.Servers.HttpServer
             if(m_running)
                 return;
             m_running = true;
-            //startup worker threads
-            for (uint i = 0; i < m_WorkerThreadCount; i++)
-            {
-                m_workerThreads[i]
-                    = WorkManager.StartThread(
-                        PoolWorkerJob,
-                        string.Format("PollServiceWorkerThread {0}", i),
-                        ThreadPriority.Normal,
-                        true,
-                        false,
-                        null,
-                        int.MaxValue);
-            }
+            m_workerPool = new ObjectJobEngine(PoolWorkerJob, "PollServiceWorker", 4000, m_WorkerThreadCount);
 
             m_retrysThread = WorkManager.StartThread(
-                this.CheckRetries,
+                CheckRetries,
                 string.Format("PollServiceWatcherThread"),
                 ThreadPriority.Normal,
                 true,
@@ -95,7 +81,7 @@ namespace OpenSim.Framework.Servers.HttpServer
         public void Enqueue(PollServiceHttpRequest req)
         {
             if(m_running)
-                m_requests.Add(req);
+                m_workerPool.Enqueue(req);
         }
 
         private void CheckRetries()
@@ -106,7 +92,7 @@ namespace OpenSim.Framework.Servers.HttpServer
                 Thread.Sleep(100);
                 Watchdog.UpdateThread();
                 while (m_running && m_retryRequests.TryDequeue(out preq))
-                    m_requests.Add(preq);
+                    m_workerPool.Enqueue(preq);
             }
         }
 
@@ -119,96 +105,78 @@ namespace OpenSim.Framework.Servers.HttpServer
 
             Thread.Sleep(100); // let the world move
 
-            foreach (Thread t in m_workerThreads)
-                Watchdog.AbortThread(t.ManagedThreadId);
-
-            PollServiceHttpRequest req;
             try
             {
-                while (m_retryRequests.TryDequeue(out req))
+                while (m_retryRequests.TryDequeue(out PollServiceHttpRequest req))
                     req.DoHTTPstop();
             }
             catch
             {
             }
 
-            try
-            {
-                while(m_requests.TryTake(out req, 0))
-                    req.DoHTTPstop();
-            }
-            catch
-            {
-            }
-            m_requests.Dispose();
+            int count = 10;
+            while(-- count > 0 && m_workerPool.Count > 0)
+                Thread.Sleep(100);
+
+            m_workerPool.Dispose();
+            m_workerPool = null;
         }
 
         // work threads
 
-        private void PoolWorkerJob()
+        private void PoolWorkerJob(object o)
         {
-            PollServiceHttpRequest req;
-            while (m_running)
+            PollServiceHttpRequest req = o as PollServiceHttpRequest;
+            if(req == null)
+                return;
+            try
             {
-                try
+                if (!req.Request.Context.CanSend())
                 {
-                    req = null;
-                    if (!m_requests.TryTake(out req, 4500) || req == null)
-                    {
-                        Watchdog.UpdateThread();
-                        continue;
-                    }
+                    req.PollServiceArgs.Drop(req.RequestID, req.PollServiceArgs.Id);
+                    return;
+                }
 
-                    Watchdog.UpdateThread();
+                if(!m_running)
+                {
+                    req.DoHTTPstop();
+                    return;
+                }
 
-                    if (!req.Request.Context.CanSend())
-                    {
-                        req.PollServiceArgs.Drop(req.RequestID, req.PollServiceArgs.Id);
-                        continue;
-                    }
+                if (req.Request.Context.IsSending())
+                {
+                    ReQueueEvent(req);
+                    return;
+                }
 
-                    if (req.Request.Context.IsSending())
+                if (req.PollServiceArgs.HasEvents(req.RequestID, req.PollServiceArgs.Id))
+                {
+                    try
                     {
-                        ReQueueEvent(req);
-                        continue;
+                        Hashtable responsedata = req.PollServiceArgs.GetEvents(req.RequestID, req.PollServiceArgs.Id);
+                        req.DoHTTPGruntWork(responsedata);
                     }
-
-                    if (req.PollServiceArgs.HasEvents(req.RequestID, req.PollServiceArgs.Id))
+                    catch { }
+                }
+                else
+                {
+                    if ((Environment.TickCount - req.RequestTime) > req.PollServiceArgs.TimeOutms)
                     {
                         try
                         {
-                            Hashtable responsedata = req.PollServiceArgs.GetEvents(req.RequestID, req.PollServiceArgs.Id);
-                            req.DoHTTPGruntWork(responsedata);
+                            req.DoHTTPGruntWork(req.PollServiceArgs.NoEvents(req.RequestID, req.PollServiceArgs.Id));
                         }
                         catch { }
                     }
                     else
                     {
-                        if ((Environment.TickCount - req.RequestTime) > req.PollServiceArgs.TimeOutms)
-                        {
-                            try
-                            {
-                                req.DoHTTPGruntWork(req.PollServiceArgs.NoEvents(req.RequestID, req.PollServiceArgs.Id));
-                            }
-                            catch { }
-                        }
-                        else
-                        {
-                            ReQueueEvent(req);
-                        }
+                        ReQueueEvent(req);
                     }
                 }
-                catch (ThreadAbortException)
-                {
-                    Thread.ResetAbort();
-                    // Shouldn't set this to 'false', the normal shutdown should cause things to exit
-                    // but robust is still not normal neither is mono
-                    m_running = false;
-                }
-                catch (Exception e)
-                {
-                    m_log.ErrorFormat("Exception in poll service thread: " + e.ToString());
-                }
+            }
+            catch (Exception e)
+            {
+                m_log.ErrorFormat("Exception in poll service thread: " + e.ToString());
             }
         }
     }

+ 1 - 1
OpenSim/Framework/Servers/HttpServer/SimpleBaseRequestHandler.cs

@@ -39,7 +39,7 @@ namespace OpenSim.Framework.Servers.HttpServer
 
         public int RequestsHandled { get; protected set; }
 
-        private readonly string m_path;
+        protected string m_path;
 
         public string Name { get; private set; }
 

+ 1 - 2
OpenSim/Framework/Util.cs

@@ -3114,7 +3114,6 @@ namespace OpenSim.Framework
                     finally
                     {
                         Interlocked.Decrement(ref numRunningThreadFuncs);
-                        threadInfo.Ended();
                         activeThreads.TryRemove(threadFuncNum, out ThreadInfo dummy);
                         if (loggingEnabled && threadInfo.LogThread)
                             m_log.DebugFormat("Exit threadfunc {0} ({1})", threadFuncNum, FormatDuration(threadInfo.Elapsed()));
@@ -3125,7 +3124,7 @@ namespace OpenSim.Framework
                 };
             }
 
-            long numQueued = Interlocked.Increment(ref numQueuedThreadFuncs);
+            Interlocked.Increment(ref numQueuedThreadFuncs);
             try
             {
                 threadInfo.LogThread = false;

+ 1 - 1
OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs

@@ -2288,7 +2288,7 @@ namespace OpenSim.Region.ClientStack.Linden
             NameValueCollection query = httpRequest.QueryString;
             string[] ids = query.GetValues("ids");
 
-            Dictionary<UUID,string> names = m_UserManager.GetUsersNames(ids, m_scopeID);
+            Dictionary<UUID,string> names = m_UserManager.GetKnownUserNames(ids, m_scopeID);
             osUTF8 lsl = LLSDxmlEncode2.Start(names.Count * 256 + 256);
             LLSDxmlEncode2.AddMap(lsl);
             int ct = 0;

+ 13 - 50
OpenSim/Region/ClientStack/Linden/Caps/GetAssetsModule.cs

@@ -77,9 +77,8 @@ namespace OpenSim.Region.ClientStack.Linden
 
         private static IAssetService m_assetService = null;
         private static GetAssetsHandler m_getAssetHandler;
-        private static Thread[] m_workerThreads = null;
+        private static ObjectJobEngine m_workerpool = null;
         private static int m_NumberScenes = 0;
-        private static BlockingCollection<APollRequest> m_queue = new BlockingCollection<APollRequest>();
         private static object m_loadLock = new object();
         protected IUserManagement m_UserManagement = null;
 
@@ -158,37 +157,17 @@ namespace OpenSim.Region.ClientStack.Linden
 
                 m_NumberScenes++;
 
-                if (m_workerThreads == null)
-                {
-                    m_workerThreads = new Thread[3];
-                    for (uint i = 0; i < 3; i++)
-                    {
-                        m_workerThreads[i] = WorkManager.StartThread(DoAssetRequests,
-                                String.Format("GetCapsAssetWorker{0}", i),
-                                ThreadPriority.Normal,
-                                true,
-                                false,
-                                null,
-                                int.MaxValue);
-                    }
-                }
+                if (m_workerpool == null)
+                    m_workerpool = new ObjectJobEngine(DoAssetRequests, "GetCapsAssetWorker", 1000, 3);
             }
         }
 
         public void Close()
         {
-            if(m_NumberScenes <= 0 && m_workerThreads != null)
+            if(m_NumberScenes <= 0 && m_workerpool != null)
             {
-                m_log.DebugFormat("[GetAssetsModule] Closing");
-                foreach (Thread t in m_workerThreads)
-                    Watchdog.AbortThread(t.ManagedThreadId);
-                // This will fail on region shutdown. Its harmless.
-                // Prevent red ink.
-                try
-                {
-                    m_queue.Dispose();
-                }
-                catch {}
+                m_workerpool.Dispose();
+                m_workerpool = null;
             }
         }
 
@@ -196,29 +175,13 @@ namespace OpenSim.Region.ClientStack.Linden
 
         #endregion
 
-        private static void DoAssetRequests()
+        private static void DoAssetRequests(object o)
         {
-            try
-            {
-                while (m_NumberScenes > 0)
-                {
-                    APollRequest poolreq;
-                    if (m_queue.TryTake(out poolreq, 4500))
-                    {
-                        if (m_NumberScenes <= 0)
-                            break;
-                        Watchdog.UpdateThread();
-                        if (poolreq.reqID != UUID.Zero)
-                            poolreq.thepoll.Process(poolreq);
-                        poolreq = null;
-                    }
-                    Watchdog.UpdateThread();
-                }
-            }
-            catch (ThreadAbortException)
-            {
-                Thread.ResetAbort();
-            }
+            if (m_NumberScenes <= 0)
+                return;
+            APollRequest poolreq = o as APollRequest;
+            if (poolreq != null && poolreq.reqID != UUID.Zero)
+                poolreq.thepoll.Process(poolreq);
         }
 
         private class PollServiceAssetEventArgs : PollServiceEventArgs
@@ -299,7 +262,7 @@ namespace OpenSim.Region.ClientStack.Linden
                     reqinfo.reqID = requestID;
                     reqinfo.request = request;
 
-                    m_queue.Add(reqinfo);
+                    m_workerpool.Enqueue(reqinfo);
                     return null;
                 };
 

+ 16 - 50
OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs

@@ -98,9 +98,7 @@ namespace OpenSim.Region.ClientStack.Linden
 
         private static FetchInvDescHandler m_webFetchHandler;
 
-        private static Thread[] m_workerThreads = null;
-
-        private static BlockingCollection<APollRequest> m_queue = new BlockingCollection<APollRequest>();
+        private static ObjectJobEngine m_workerpool = null;
 
         private static int m_NumberScenes = 0;
 
@@ -142,12 +140,13 @@ namespace OpenSim.Region.ClientStack.Linden
             if (!m_Enabled)
                 return;
 
+            m_NumberScenes--;
+
             Scene.EventManager.OnRegisterCaps -= RegisterCaps;
 
             StatsManager.DeregisterStat(s_processedRequestsStat);
             StatsManager.DeregisterStat(s_queuedRequestsStat);
 
-            m_NumberScenes--;
             Scene = null;
         }
 
@@ -181,7 +180,7 @@ namespace OpenSim.Region.ClientStack.Linden
                         "httpfetch",
                         StatType.Pull,
                         MeasuresOfInterest.AverageChangeOverTime,
-                        stat => { stat.Value = m_queue.Count; },
+                        stat => { stat.Value = m_workerpool.Count; },
                         StatVerbosity.Debug);
 
             StatsManager.RegisterStat(s_processedRequestsStat);
@@ -200,22 +199,8 @@ namespace OpenSim.Region.ClientStack.Linden
 
             m_NumberScenes++;
 
-            int nworkers = 2; // was 2
-            if (ProcessQueuedRequestsAsync && m_workerThreads == null)
-            {
-                m_workerThreads = new Thread[nworkers];
-
-                for (uint i = 0; i < nworkers; i++)
-                {
-                    m_workerThreads[i] = WorkManager.StartThread(DoInventoryRequests,
-                            String.Format("InventoryWorkerThread{0}", i),
-                            ThreadPriority.Normal,
-                            true,
-                            true,
-                            null,
-                            int.MaxValue);
-                }
-            }
+            if (ProcessQueuedRequestsAsync && m_workerpool == null)
+                m_workerpool = new ObjectJobEngine(DoInventoryRequests, "InventoryWorker",2000,2);
         }
 
         public void PostInitialise()
@@ -229,13 +214,10 @@ namespace OpenSim.Region.ClientStack.Linden
 
             if (ProcessQueuedRequestsAsync)
             {
-                if (m_NumberScenes <= 0 && m_workerThreads != null)
+                if (m_NumberScenes <= 0 && m_workerpool != null)
                 {
-                    m_log.DebugFormat("[WebFetchInvDescModule] Closing");
-                    foreach (Thread t in m_workerThreads)
-                        Watchdog.AbortThread(t.ManagedThreadId);
-
-                    m_workerThreads = null;
+                    m_workerpool.Dispose();
+                    m_workerpool = null;
                     m_badRequests.Dispose();
                     m_badRequests = null;
                 }
@@ -303,7 +285,7 @@ namespace OpenSim.Region.ClientStack.Linden
                     reqinfo.thepoll = this;
                     reqinfo.reqID = requestID;
                     reqinfo.request = request;
-                    m_queue.Add(reqinfo);
+                    m_workerpool.Enqueue(reqinfo);
                     return null;
                 };
 
@@ -399,29 +381,13 @@ namespace OpenSim.Region.ClientStack.Linden
             }
         }
 
-        private static void DoInventoryRequests()
+        private static void DoInventoryRequests(object o)
         {
-            bool running = true;
-            while (running)
-            {
-                try
-                {
-                    APollRequest poolreq;
-                    if (m_queue.TryTake(out poolreq, 4500))
-                    {
-                        Watchdog.UpdateThread();
-                        if (poolreq.thepoll != null)
-                            poolreq.thepoll.Process(poolreq);
-                        poolreq = null;
-                    }
-                    Watchdog.UpdateThread();
-                }
-                catch (ThreadAbortException)
-                {
-                    Thread.ResetAbort();
-                    running = false;
-                }
-            }
+            if(m_NumberScenes <= 0)
+                return;
+            APollRequest poolreq = o as APollRequest;
+            if (poolreq != null && poolreq.thepoll != null)
+                poolreq.thepoll.Process(poolreq);
         }
     }
 }

+ 17 - 6
OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs

@@ -545,7 +545,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
 
             RegisterLocalPacketHandlers();
             string name = string.Format("AsyncInUDP-{0}",m_agentId.ToString());
-            m_asyncPacketProcess = new JobEngine(name, name, 10000);
+            m_asyncPacketProcess = new JobEngine(name, name, 5000);
             IsActive = true;
 
             m_supportViewerCache = m_udpServer.SupportViewerObjectsCache;
@@ -3240,6 +3240,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
             OutPacket(viewertime, ThrottleOutPacketType.Task);
         }
 
+
+
         public void SendViewerEffect(ViewerEffectPacket.EffectBlock[] effectBlocks)
         {
             ViewerEffectPacket packet = (ViewerEffectPacket)PacketPool.Instance.GetPacket(PacketType.ViewerEffect);
@@ -4207,6 +4209,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
 
         public void SendClassifiedInfoReply(UUID classifiedID, UUID creatorID, uint creationDate, uint expirationDate, uint category, string name, string description, UUID parcelID, uint parentEstate, UUID snapshotID, string simName, Vector3 globalPos, string parcelName, byte classifiedFlags, int price)
         {
+            // fix classifiedFlags maturity
+            if((classifiedFlags & 0x4e) == 0) // if none
+                classifiedFlags |= 0x4; // pg
+
             ClassifiedInfoReplyPacket cr =
                     (ClassifiedInfoReplyPacket)PacketPool.Instance.GetPacket(
                     PacketType.ClassifiedInfoReply);
@@ -8340,7 +8346,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
         {
             if(OnAgentUpdate == null)
             {
-                PacketPool.Instance.ReturnPacket(packet);
+                //PacketPool.Instance.ReturnPacket(packet);
                 return;
             }
 
@@ -8349,7 +8355,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
 
             if (x.AgentID != AgentId || x.SessionID != SessionId)
             {
-                PacketPool.Instance.ReturnPacket(packet);
+                //PacketPool.Instance.ReturnPacket(packet);
                 return;
             }
 
@@ -8362,7 +8368,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
             {
                 // throttle reset is done at MoveAgentIntoRegion()
                 // called by scenepresence on completemovement
-                PacketPool.Instance.ReturnPacket(packet);
+                //PacketPool.Instance.ReturnPacket(packet);
                 return;
             }
 
@@ -8416,7 +8422,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
             if(movement && camera)
                 m_thisAgentUpdateArgs.lastUpdateTS = now;
 
-            PacketPool.Instance.ReturnPacket(packet);
+            //PacketPool.Instance.ReturnPacket(packet);
         }
 
         private void HandleMoneyTransferRequest(Packet Pack)
@@ -12330,6 +12336,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
             if (classifiedInfoUpdate.AgentData.SessionID != SessionId || classifiedInfoUpdate.AgentData.AgentID != AgentId)
                 return;
 
+            // fix classifiedFlags maturity
+            byte classifiedFlags = classifiedInfoUpdate.Data.ClassifiedFlags;
+            if ((classifiedFlags & 0x4e) == 0) // if none
+                classifiedFlags |= 0x4; // pg
+
             OnClassifiedInfoUpdate?.Invoke(
                         classifiedInfoUpdate.Data.ClassifiedID,
                         classifiedInfoUpdate.Data.Category,
@@ -12342,7 +12353,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
                         classifiedInfoUpdate.Data.SnapshotID,
                         new Vector3(
                             classifiedInfoUpdate.Data.PosGlobal),
-                        classifiedInfoUpdate.Data.ClassifiedFlags,
+                        classifiedFlags,
                         classifiedInfoUpdate.Data.PriceForListing,
                         this);
         }

+ 6 - 9
OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs

@@ -540,7 +540,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
 
             OqrEngine = new JobEngine(
                     string.Format("Outgoing Queue Refill Engine ({0})", Scene.Name),
-                    "OUTGOING QUEUE REFILL ENGINE");
+                    "OUTGOING QUEUE REFILL ENGINE", 2000);
 
             StatsManager.RegisterStat(
                 new Stat(
@@ -1225,7 +1225,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
 //            m_log.DebugFormat(
 //                "[LLUDPSERVER]: Packet received from {0} in {1}", buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName);
 
-            LLUDPClient udpClient = null;
             Packet packet = null;
             int packetEnd = buffer.DataLength - 1;
             IPEndPoint endPoint = (IPEndPoint)buffer.RemoteEndPoint;
@@ -1307,9 +1306,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
 
             #region Packet to Client Mapping
 
-            // If there is already a client for this endpoint, don't process UseCircuitCode
-            IClientAPI client = null;
-            if (!Scene.TryGetClient(endPoint, out client) || !(client is LLClientView))
+            // usecircuitcode handling
+            if (!Scene.TryGetClient(endPoint, out IClientAPI client) || !(client is LLClientView))
             {
                 // UseCircuitCode handling
                 if (packet.Type == PacketType.UseCircuitCode)
@@ -1363,7 +1361,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
                 return;
             }
 
-            udpClient = ((LLClientView)client).UDPClient;
+            LLUDPClient udpClient = ((LLClientView)client).UDPClient;
 
             if (!udpClient.IsConnected)
             {
@@ -1631,10 +1629,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
                     "[LLUDPSERVER]: Handling UseCircuitCode request for circuit {0} to {1} from IP {2}",
                     uccp.CircuitCode.Code, Scene.RegionInfo.RegionName, endPoint);
 
-                AuthenticateResponse sessionInfo;
-                if (IsClientAuthorized(uccp, out sessionInfo))
+                if (IsClientAuthorized(uccp, out AuthenticateResponse sessionInfo))
                 {
-                    AgentCircuitData aCircuit = Scene.AuthenticateHandler.GetAgentCircuitData(uccp.CircuitCode.Code);
+                    AgentCircuitData aCircuit = m_circuitManager.GetAgentCircuitData(uccp.CircuitCode.Code);
 
                     // Begin the process of adding the client to the simulator
                     client

+ 1 - 3
OpenSim/Region/CoreModules/Framework/ServiceThrottle/ServiceThrottleModule.cs

@@ -54,9 +54,7 @@ namespace OpenSim.Region.CoreModules.Framework
 
         public void Initialise(IConfigSource config)
         {
-            m_processorJobEngine = new JobEngine(
-                "ServiceThrottle","ServiceThrottle");
-            m_processorJobEngine.RequestProcessTimeoutOnStop = 31000; // many webrequests have 30s expire
+            m_processorJobEngine = new JobEngine("ServiceThrottle","ServiceThrottle", 5000, 2);
             m_processorJobEngine.Start();
         }
 

+ 253 - 28
OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs

@@ -409,22 +409,253 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
 
         public virtual Dictionary<UUID,string> GetUsersNames(string[] ids, UUID scopeID)
         {
-            Dictionary<UUID,string> ret = new Dictionary<UUID,string>();
+            var ret = new Dictionary<UUID,string>();
             if(m_Scenes.Count <= 0)
                 return ret;
 
-            UserData userdata = new UserData();
-            UUID uuid = UUID.Zero;
-            foreach(string id in ids)
+            List<string> missing = new List<string>(ids.Length);
+            var untried = new Dictionary<UUID, UserData>();
+            foreach (string id in ids)
             {
-                if(UUID.TryParse(id, out uuid))
+                if(!UUID.TryParse(id, out UUID uuid) || uuid == UUID.Zero)
+                    continue;
+
+                if (m_userCacheByID.TryGetValue(uuid, out UserData userdata))
                 {
-                    if (GetUser(uuid, out userdata))
-                        ret[uuid] = userdata.FirstName + " " + userdata.LastName;
+                    string name = userdata.FirstName + " " + userdata.LastName;
+                    if (userdata.HasGridUserTried)
+                    {
+                        ret[uuid] = name;
+                        continue;
+                    }
+                    untried[uuid] = userdata;
+                }
+                missing.Add(id);
+            }
+
+            if(missing.Count == 0)
+                return ret;
+
+            ids = null;
+
+            List<UserAccount> accounts = m_userAccountService.GetUserAccounts(scopeID, missing);
+            if (accounts.Count != 0)
+            {
+                foreach (UserAccount uac in accounts)
+                {
+                    if (uac != null)
+                    {
+                        string name = uac.FirstName + " " + uac.LastName;
+                        UUID id = uac.PrincipalID;
+
+                        var userdata = new UserData();
+                        userdata.Id = id;
+                        userdata.FirstName = uac.FirstName;
+                        userdata.LastName = uac.LastName;
+                        userdata.HomeURL = string.Empty;
+                        userdata.IsUnknownUser = false;
+                        userdata.IsLocal = true;
+                        userdata.HasGridUserTried = true;
+                        m_userCacheByID.Add(id, userdata, 1800000);
+
+                        ret[id] = name;
+                        missing.Remove(id.ToString()); // slowww
+                        untried.Remove(id);
+                    }
+                }
+            }
+
+            if (missing.Count == 0 || m_gridUserService == null)
+                return ret;
+
+            GridUserInfo[] pinfos = m_gridUserService.GetGridUserInfo(missing.ToArray());
+            if (pinfos.Length > 0)
+            {
+                foreach (GridUserInfo uInfo in pinfos)
+                {
+                    if (uInfo != null && uInfo.UserID.Length >= 36)
+                    {
+                        string url, first, last, tmp;
+                        UUID u;
+                        if (uInfo.UserID.Length >= 36 && Util.ParseUniversalUserIdentifier(uInfo.UserID, out u, out url, out first, out last, out tmp))
+                        {
+                            bool isvalid = CheckUrl(url, out bool islocal, out OSHHTPHost host);
+                            var userdata = new UserData();
+                            userdata.Id = u;
+                            if (isvalid)
+                            {
+                                if (islocal)
+                                {
+                                    userdata.FirstName = first;
+                                    userdata.LastName = last;
+                                    userdata.HomeURL = string.Empty;
+                                    userdata.IsLocal = true;
+                                }
+                                else
+                                {
+                                    userdata.FirstName = first.Replace(" ", ".") + "." + last.Replace(" ", ".");
+                                    userdata.HomeURL = host.URI;
+                                    userdata.LastName = "@" + host.HostAndPort;
+                                    userdata.IsLocal = false;
+                                }
+                                userdata.IsUnknownUser = false;
+                                userdata.HasGridUserTried = true;
+                                m_userCacheByID.Add(u, userdata, 1800000);
+
+                                string name = userdata.FirstName + " " + userdata.LastName;
+                                ret[u] = name;
+                                missing.Remove(u.ToString());
+                                untried.Remove(u);
+                            }
+                        }
+                        else
+                            m_log.DebugFormat("[USER MANAGEMENT MODULE]: Unable to parse UUI {0}", uInfo.UserID);
+                    }
+                }
+            }
+
+            // add the untried in cache
+            if (untried.Count > 0)
+            {
+                foreach (UserData ud in untried.Values)
+                {
+                    UUID id = ud.Id;
+                    ud.HasGridUserTried = true;
+                    m_userCacheByID.Add(id, ud, 1800000);
+
+                    ret[id] = ud.FirstName + " " + ud.LastName;
+                    missing.Remove(id.ToString());
+                }
+            }
+
+            // add the UMMthings ( not sure we should)
+            if (missing.Count > 0)
+            {
+                foreach (string id in missing)
+                {
+                    if (UUID.TryParse(id, out UUID uuid))
+                        ret[uuid] = "Unknown UserUMMAU43";
+                }
+            }
+
+            return ret;
+        }
+
+        public virtual Dictionary<UUID, string> GetKnownUserNames(string[] ids, UUID scopeID)
+        {
+            var ret = new Dictionary<UUID, string>();
+            if (m_Scenes.Count <= 0)
+                return ret;
+
+            List<string> missing = new List<string>(ids.Length);
+            var untried = new Dictionary<UUID, UserData>();
+            foreach (string id in ids)
+            {
+                if (!UUID.TryParse(id, out UUID uuid) || uuid == UUID.Zero)
+                    continue;
+
+                if (m_userCacheByID.TryGetValue(uuid, out UserData userdata))
+                {
+                    if (userdata.HasGridUserTried)
+                    {
+                        if(!userdata.IsUnknownUser)
+                            ret[uuid] = userdata.FirstName + " " + userdata.LastName;
+                        continue;
+                    }
                     else
-                        ret[uuid] = "Unknown " + uuid.ToString() + "UMM1";
+                        untried[uuid] = userdata;
+                }
+                missing.Add(id);
+            }
+
+            if (missing.Count == 0)
+                return ret;
+
+            ids = null;
+
+            List<UserAccount> accounts = m_userAccountService.GetUserAccounts(scopeID, missing);
+            if (accounts.Count != 0)
+            {
+                foreach (UserAccount uac in accounts)
+                {
+                    if (uac != null)
+                    {
+                        UUID id = uac.PrincipalID;
+
+                        var userdata = new UserData();
+                        userdata.Id = id;
+                        userdata.FirstName = uac.FirstName;
+                        userdata.LastName = uac.LastName;
+                        userdata.HomeURL = string.Empty;
+                        userdata.IsUnknownUser = false;
+                        userdata.IsLocal = true;
+                        userdata.HasGridUserTried = true;
+                        m_userCacheByID.Add(id, userdata, 1800000);
+
+                        ret[id] = uac.FirstName + " " + uac.LastName;
+                        missing.Remove(id.ToString()); // slowww
+                        untried.Remove(id);
+                    }
+                }
+            }
+
+            if (missing.Count == 0 || m_gridUserService == null)
+                return ret;
+
+            GridUserInfo[] pinfos = m_gridUserService.GetGridUserInfo(missing.ToArray());
+            missing = null;
+            if (pinfos.Length > 0)
+            {
+                foreach (GridUserInfo uInfo in pinfos)
+                {
+                    if (uInfo != null && uInfo.UserID.Length >= 36)
+                    {
+                        string url, first, last, tmp;
+                        UUID uuid;
+                        if (Util.ParseUniversalUserIdentifier(uInfo.UserID, out uuid, out url, out first, out last, out tmp))
+                        {
+                            bool isvalid = CheckUrl(url, out bool islocal, out OSHHTPHost host);
+                            var userdata = new UserData();
+                            userdata.Id = uuid;
+                            if (isvalid)
+                            {
+                                if (islocal)
+                                {
+                                    userdata.FirstName = first;
+                                    userdata.LastName = last;
+                                    userdata.HomeURL = string.Empty;
+                                    userdata.IsLocal = true;
+                                }
+                                else
+                                {
+                                    userdata.FirstName = first.Replace(" ", ".") + "." + last.Replace(" ", ".");
+                                    userdata.HomeURL = host.URI;
+                                    userdata.LastName = "@" + host.HostAndPort;
+                                    userdata.IsLocal = false;
+                                }
+
+                                userdata.IsUnknownUser = false;
+                                userdata.HasGridUserTried = true;
+                                m_userCacheByID.Add(uuid, userdata, 1800000);
+
+                                string name = userdata.FirstName + " " + userdata.LastName;
+                                untried.Remove(uuid);
+                                ret[uuid] = name;
+                            }
+                        }
+                        else
+                            m_log.DebugFormat("[USER MANAGEMENT MODULE]: Unable to parse UUI {0}", uInfo.UserID);
+                    }
                 }
             }
+
+            foreach(UserData ud in untried.Values)
+            {
+                ud.HasGridUserTried = true;
+                m_userCacheByID.Add(ud.Id, ud, 1800000);
+                if(!ud.IsUnknownUser)
+                    ret[ud.Id] = ud.FirstName + " " + ud.LastName;
+            }
             return ret;
         }
 
@@ -602,27 +833,23 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
 
         public virtual bool GetUserUUI(UUID userID, out string uui)
         {
-            bool result = GetUser(userID, out UserData ud);
-
-            if (ud != null)
+            if (GetUser(userID, out UserData ud) && ud != null)
             {
-                string homeURL = ud.HomeURL;
-                string first = ud.FirstName, last = ud.LastName;
                 if (ud.LastName.StartsWith("@"))
                 {
                     string[] parts = ud.FirstName.Split('.');
                     if (parts.Length >= 2)
-                    {
-                        first = parts[0];
-                        last = parts[1];
-                    }
-                    uui = userID + ";" + homeURL + ";" + first + " " + last;
-                    return result;
+                        uui = userID.ToString() + ";" + ud.HomeURL + ";" + parts[0] + " " + parts[1];
+                    else
+                        uui = userID.ToString() + ";" + ud.HomeURL + ";" + ud.FirstName + " " + ud.LastName;
                 }
+                else
+                    uui = userID.ToString();
+                return true;
             }
 
             uui = userID.ToString();
-            return result;
+            return false;
         }
 
         #region Cache Management
@@ -859,9 +1086,10 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
             oldUser.HasGridUserTried = false;
             oldUser.IsUnknownUser = false;
 
-            if (CheckUrl(homeURL, out bool local, out OSHHTPHost host))
+            OSHTTPURI homeuri = new OSHTTPURI(homeURL);
+            if (homeuri.IsValidHost)
             {
-                if (local)
+                if (m_thisGridInfo.IsLocalGrid(homeuri.URL) == 1) // local
                 {
                     oldUser.FirstName = firstname;
                     oldUser.LastName = lastname;
@@ -872,8 +1100,8 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
                 else
                 {
                     oldUser.FirstName = firstname + "." + lastname.Replace(" ", ".");
-                    oldUser.LastName = "@" + host.HostAndPort;
-                    oldUser.HomeURL = host.URI;
+                    oldUser.LastName = "@" + homeuri.HostAndPort;
+                    oldUser.HomeURL = homeuri.URL;
                     oldUser.IsLocal = false;
                 }
             }
@@ -961,10 +1189,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
 
         protected virtual void HandleResetUserCache(string module, string[] cmd)
         {
-            lock(m_userCacheByID)
-            {
-                m_userCacheByID.Clear();
-            }
+            m_userCacheByID.Clear();
         }
 
         protected virtual void HandleShowUser(string module, string[] cmd)

+ 205 - 215
OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs

@@ -30,20 +30,16 @@ using System.Collections.Generic;
 using System.Collections.Concurrent;
 using System.IO;
 using System.Net;
-using System.Net.Mail;
 using System.Net.Security;
-using System.Text;
-using System.Threading;
 using System.Security.Cryptography.X509Certificates;
+using System.Threading;
 using Nini.Config;
 using OpenMetaverse;
 using OpenSim.Framework;
-using OpenSim.Framework.Servers;
-using OpenSim.Framework.Servers.HttpServer;
+using OpenSim.Framework.Monitoring;
 using OpenSim.Region.Framework.Interfaces;
 using OpenSim.Region.Framework.Scenes;
 using Mono.Addins;
-using Amib.Threading;
 
 /*****************************************************
  *
@@ -52,46 +48,136 @@ using Amib.Threading;
  * Implements the llHttpRequest and http_response
  * callback.
  *
-  * **************************************************/
+ * This is a non shared module with shared static parts
+ * **************************************************/
 
 namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
 {
     [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "HttpRequestModule")]
-    public class HttpRequestModule : ISharedRegionModule, IHttpRequestModule
+    public class HttpRequestModule : INonSharedRegionModule, IHttpRequestModule
     {
+        private struct ThrottleData
+        {
+            public double lastTime;
+            public float control;
+        }
+
         // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
 
-        private readonly object m_httpListLock = new object();
-        private int m_httpTimeout = 30000;
-        private readonly string m_name = "HttpScriptRequests";
+        private static readonly object m_mainLock = new object();
+        private static int m_numberScenes;
+        private static int m_httpTimeout = 30000;
+        private static readonly string m_name = "HttpScriptRequests";
 
-        private OutboundUrlFilter m_outboundUrlFilter;
-        private string m_proxyurl = "";
-        private string m_proxyexcepts = "";
+        private static OutboundUrlFilter m_outboundUrlFilter;
+        private static string m_proxyurl = "";
+        private static string m_proxyexcepts = "";
 
-        private float m_primPerSec = 1.0f;
-        private float m_primBurst = 3.0f;
-        private float m_primOwnerPerSec = 25.0f;
-        private float m_primOwnerBurst = 5.0f;
+        private static float m_primPerSec = 1.0f;
+        private static float m_primBurst = 3.0f;
+        private static float m_primOwnerPerSec = 25.0f;
+        private static float m_primOwnerBurst = 5.0f;
 
-        private struct ThrottleData
+        public static JobEngine m_jobEngine = null;
+        private static Dictionary<UUID, HttpRequestClass> m_pendingRequests;
+
+        //this are per region/module
+        private readonly ConcurrentQueue<HttpRequestClass> m_CompletedRequests = new ConcurrentQueue<HttpRequestClass>();
+        private readonly ConcurrentDictionary<uint, ThrottleData> m_RequestsThrottle = new ConcurrentDictionary<uint, ThrottleData>();
+        private readonly ConcurrentDictionary<UUID, ThrottleData> m_OwnerRequestsThrottle = new ConcurrentDictionary<UUID, ThrottleData>();
+
+
+        public HttpRequestModule()
         {
-            public double lastTime;
-            public float count;
         }
 
-        // <request id, HttpRequestClass>
-        private Dictionary<UUID, HttpRequestClass> m_pendingRequests;
-        private ConcurrentQueue<HttpRequestClass> m_CompletedRequests;
-        private ConcurrentDictionary<uint, ThrottleData> m_RequestsThrottle;
-        private ConcurrentDictionary<UUID, ThrottleData> m_OwnerRequestsThrottle;
+        #region INonSharedRegionModule Members
 
-        public static SmartThreadPool ThreadPool = null;
+        public void Initialise(IConfigSource config)
+        {
+            lock (m_mainLock)
+            {
+                // shared items
+                if (m_jobEngine == null)
+                {
+                    m_proxyurl = config.Configs["Startup"].GetString("HttpProxy");
+                    m_proxyexcepts = config.Configs["Startup"].GetString("HttpProxyExceptions");
 
-        public HttpRequestModule()
+                    HttpRequestClass.HttpBodyMaxLenMAX = config.Configs["Network"].GetInt("HttpBodyMaxLenMAX", 16384);
+
+                    m_outboundUrlFilter = new OutboundUrlFilter("Script HTTP request module", config);
+
+                    int maxThreads = 8;
+                    IConfig httpConfig = config.Configs["ScriptsHttpRequestModule"];
+                    if (httpConfig != null)
+                    {
+                        maxThreads = httpConfig.GetInt("MaxPoolThreads", maxThreads);
+                        m_primBurst = httpConfig.GetFloat("PrimRequestsBurst", m_primBurst);
+                        m_primPerSec = httpConfig.GetFloat("PrimRequestsPerSec", m_primPerSec);
+                        m_primOwnerBurst = httpConfig.GetFloat("PrimOwnerRequestsBurst", m_primOwnerBurst);
+                        m_primOwnerPerSec = httpConfig.GetFloat("PrimOwnerRequestsPerSec", m_primOwnerPerSec);
+                        m_httpTimeout = httpConfig.GetInt("RequestsTimeOut", m_httpTimeout);
+                        if (m_httpTimeout > 60000)
+                            m_httpTimeout = 60000;
+                        else if (m_httpTimeout < 200)
+                            m_httpTimeout = 200;
+                    }
+
+                    m_pendingRequests = new Dictionary<UUID, HttpRequestClass>();
+
+                    m_jobEngine = new JobEngine("ScriptsHttpReq", "ScriptsHttpReq", 2000, maxThreads);
+                    m_jobEngine.Start();
+                }
+            }
+        }
+
+        public void AddRegion(Scene scene)
+        {
+            scene.RegisterModuleInterface<IHttpRequestModule>(this);
+            Interlocked.Increment(ref m_numberScenes);
+        }
+
+        public void RemoveRegion(Scene scene)
+        {
+            scene.UnregisterModuleInterface<IHttpRequestModule>(this);
+        }
+
+        public void PostInitialise()
+        {
+        }
+
+        public void RegionLoaded(Scene scene)
+        {
+        }
+
+        public void Close()
+        {
+            int n = Interlocked.Decrement(ref m_numberScenes);
+            if (n == 0)
+            {
+                lock(m_mainLock)
+                {
+                    if (m_jobEngine != null)
+                    {
+                        m_jobEngine.Stop();
+                        m_jobEngine = null;
+                    }
+                }
+            }
+        }
+
+        public string Name
         {
+            get { return m_name; }
         }
 
+        public Type ReplaceableInterface
+        {
+            get { return null; }
+        }
+
+        #endregion
+
         #region IHttpRequestModule Members
 
         public UUID MakeHttpRequest(string url, string parameters, string body)
@@ -110,20 +196,25 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
                 th.lastTime = now;
 
                 float add = (float)(m_primPerSec * delta);
-                th.count += add;
-                if (th.count > m_primBurst)
-                    th.count = m_primBurst;
-
-                ret = th.count > 0;
-                if (ret)
-                    th.count--;
+                th.control += add;
+                if (th.control > m_primBurst)
+                {
+                    th.control = m_primBurst - 1;
+                    ret = true;
+                }
+                else
+                {
+                    ret = th.control > 0;
+                    if (ret)
+                        th.control--;
+                }
             }
             else
             {
                 th = new ThrottleData()
                 {
                     lastTime = now,
-                    count = m_primBurst - 1
+                    control = m_primBurst - 1,
                 };
                 ret = true;
             }
@@ -138,20 +229,22 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
                 th.lastTime = now;
 
                 float add = (float)(m_primOwnerPerSec * delta);
-                th.count += add;
-                if (th.count > m_primOwnerBurst)
-                    th.count = m_primOwnerBurst;
-
-                ret = th.count > 0;
-                if (ret)
-                    th.count--;
+                th.control += add;
+                if (th.control > m_primOwnerBurst)
+                    th.control = m_primOwnerBurst - 1;
+                else
+                {
+                    ret = th.control > 0;
+                    if (ret)
+                        th.control--;
+                }
             }
             else
             {
                 th = new ThrottleData()
                 {
                     lastTime = now,
-                    count = m_primOwnerBurst - 1
+                    control = m_primBurst - 1
                 };
             }
             m_OwnerRequestsThrottle[ownerID] = th;
@@ -262,7 +355,7 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
             // Same number as default HttpWebRequest.MaximumAutomaticRedirections
             htc.MaxRedirects = 50;
 
-            lock (m_httpListLock)
+            lock (m_mainLock)
                 m_pendingRequests.Add(reqID, htc);
 
             htc.Process();
@@ -279,10 +372,10 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
             return m_outboundUrlFilter.CheckAllowed(url);
         }
 
-        public void StopHttpRequest(uint m_localID, UUID m_itemID)
+        public void StopHttpRequest(uint localID, UUID m_itemID)
         {
             List<UUID> toremove = new List<UUID>();
-            lock (m_httpListLock)
+            lock (m_mainLock)
             {
                 foreach (HttpRequestClass tmpReq in m_pendingRequests.Values)
                 {
@@ -295,6 +388,11 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
                 foreach(UUID id in toremove)
                     m_pendingRequests.Remove(id);
             }
+            if (m_RequestsThrottle.TryGetValue(localID, out ThrottleData th))
+            {
+                if (th.control + m_primOwnerPerSec * (Util.GetTimeStamp() - th.lastTime) >= m_primBurst)
+                    m_RequestsThrottle.TryRemove(localID, out ThrottleData dummy);
+            }
         }
 
         /*
@@ -307,12 +405,11 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
         */
         public void GotCompletedRequest(HttpRequestClass req)
         {
-            lock (m_httpListLock)
+            lock (m_mainLock)
             {
-                if (req.Removed)
-                    return;
                 m_pendingRequests.Remove(req.ReqID);
-                m_CompletedRequests.Enqueue(req);
+                if (!req.Removed)
+                    m_CompletedRequests.Enqueue(req);
             }
         }
 
@@ -326,7 +423,7 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
 
         public void RemoveCompletedRequest(UUID reqId)
         {
-            lock (m_httpListLock)
+            lock (m_mainLock)
             {
                 if (m_pendingRequests.TryGetValue(reqId, out HttpRequestClass tmpReq))
                 {
@@ -337,91 +434,6 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
         }
 
         #endregion
-
-        #region ISharedRegionModule Members
-
-        public void Initialise(IConfigSource config)
-        {
-            m_proxyurl = config.Configs["Startup"].GetString("HttpProxy");
-            m_proxyexcepts = config.Configs["Startup"].GetString("HttpProxyExceptions");
-
-            HttpRequestClass.HttpBodyMaxLenMAX = config.Configs["Network"].GetInt("HttpBodyMaxLenMAX", 16384);
-
-            m_outboundUrlFilter = new OutboundUrlFilter("Script HTTP request module", config);
-
-            int maxThreads = 8;
-            IConfig httpConfig = config.Configs["ScriptsHttpRequestModule"];
-            if (httpConfig != null)
-            {
-                maxThreads = httpConfig.GetInt("MaxPoolThreads", maxThreads);
-                m_primBurst = httpConfig.GetFloat("PrimRequestsBurst", m_primBurst);
-                m_primPerSec = httpConfig.GetFloat("PrimRequestsPerSec", m_primPerSec);
-                m_primOwnerBurst = httpConfig.GetFloat("PrimOwnerRequestsBurst", m_primOwnerBurst);
-                m_primOwnerPerSec = httpConfig.GetFloat("PrimOwnerRequestsPerSec", m_primOwnerPerSec);
-                m_httpTimeout = httpConfig.GetInt("RequestsTimeOut", m_httpTimeout);
-                if(m_httpTimeout > 60000)
-                    m_httpTimeout = 60000;
-                else if(m_httpTimeout < 200)
-                    m_httpTimeout = 200;
-            }
-
-            m_pendingRequests = new Dictionary<UUID, HttpRequestClass>();
-            m_CompletedRequests = new ConcurrentQueue<HttpRequestClass>();
-            m_RequestsThrottle = new ConcurrentDictionary<uint, ThrottleData>();
-            m_OwnerRequestsThrottle = new ConcurrentDictionary<UUID, ThrottleData>();
-
-            // First instance sets this up for all sims
-            if (ThreadPool == null)
-            {
-                STPStartInfo startInfo = new STPStartInfo()
-                {
-                    IdleTimeout = 2000,
-                    MaxWorkerThreads = maxThreads,
-                    MinWorkerThreads = 0,
-                    ThreadPriority = ThreadPriority.Normal,
-                    StartSuspended = true,
-                    ThreadPoolName = "ScriptsHttpReq"
-                };
-
-                ThreadPool = new SmartThreadPool(startInfo);
-                ThreadPool.Start();
-            }
-        }
-
-        public void AddRegion(Scene scene)
-        {
-            scene.RegisterModuleInterface<IHttpRequestModule>(this);
-        }
-
-        public void RemoveRegion(Scene scene)
-        {
-            scene.UnregisterModuleInterface<IHttpRequestModule>(this);
-        }
-
-        public void PostInitialise()
-        {
-        }
-
-        public void RegionLoaded(Scene scene)
-        {
-        }
-
-        public void Close()
-        {
-            ThreadPool.Shutdown();
-        }
-
-        public string Name
-        {
-            get { return m_name; }
-        }
-
-        public Type ReplaceableInterface
-        {
-            get { return null; }
-        }
-
-        #endregion
     }
 
     public class HttpRequestClass : IServiceRequest
@@ -441,7 +453,7 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
         public HttpRequestModule RequestModule { get; set; }
 
         public bool Finished { get; private set;}
-        public bool Removed{ get; set;}
+        public bool Removed;
 
         public static int HttpBodyMaxLenMAX = 16384;
 
@@ -451,7 +463,6 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
         public string HttpMIMEType = "text/plain;charset=utf-8";
         public int HttpTimeout;
         public bool HttpVerifyCert = true;
-        public IWorkItemResult WorkItem = null;
 
         //public bool HttpVerboseThrottle = true; // not implemented
         public List<string> HttpCustomHeaders = null;
@@ -477,7 +488,6 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
 
         public string OutboundBody;
 
-        public HttpWebRequest Request;
         public string ResponseBody;
         public List<string> ResponseMetadata;
         public Dictionary<string, string> ResponseHeaders;
@@ -486,13 +496,7 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
 
         public void Process()
         {
-            WorkItem = HttpRequestModule.ThreadPool.QueueWorkItem(new WorkItemCallback(StpSendWrapper), null);
-        }
-
-        private object StpSendWrapper(object o)
-        {
-            SendRequest();
-            return null;
+            HttpRequestModule.m_jobEngine?.QueueJob("", SendRequest);
         }
 
         public static bool ValidateServerCertificate(
@@ -506,22 +510,11 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
             if (sender is HttpWebRequest)
             {
                 HttpWebRequest Request = sender as HttpWebRequest;
-                ServicePoint sp = Request.ServicePoint;
-
                 // We don't case about encryption, get out of here
                 if (Request.Headers.Get("NoVerifyCert") != null)
-                {
                     return true;
-                }
-
-                // If there was an upstream cert verification error, bail
-                if ((((int)sslPolicyErrors) & ~4) != 0)
-                    return false;
-
-                return true;
             }
 
-            // If it's not HTTP, trust .NET to check it
             if ((((int)sslPolicyErrors) & ~4) != 0)
                 return false;
 
@@ -538,12 +531,9 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
             if(Removed)
                  return;
 
+            HttpWebRequest Request;
             HttpWebResponse response = null;
             Stream resStream = null;
-            byte[] buf = new byte[HttpBodyMaxLenMAX + 16];
-            string tempString = null;
-            int count = 0;
-
             try
             {
                 Request = (HttpWebRequest)WebRequest.Create(Url);
@@ -601,6 +591,9 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
                     else
                         Request.Headers[entry.Key] = entry.Value;
 
+                if (Removed)
+                    return;
+
                 // Encode outbound data
                 if (!string.IsNullOrEmpty(OutboundBody))
                 {
@@ -609,8 +602,12 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
                     Request.ContentLength = data.Length;
                     using (Stream bstream = Request.GetRequestStream())
                         bstream.Write(data, 0, data.Length);
+                    data = null;
                 }
 
+                if (Removed)
+                    return;
+
                 try
                 {
                     // execute the request
@@ -625,8 +622,14 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
                     response = (HttpWebResponse)e.Response;
                 }
 
+                if (Removed)
+                    return;
+
                 Status = (int)response.StatusCode;
 
+                byte[] buf = new byte[HttpBodyMaxLenMAX + 16];
+                int count = 0;
+
                 resStream = response.GetResponseStream();
                 int totalBodyBytes = 0;
                 int maxBytes = HttpBodyMaxLen;
@@ -646,7 +649,7 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
 
                 if(totalBodyBytes > 0)
                 {
-                    tempString = Util.UTF8.GetString(buf, 0, totalBodyBytes);
+                    string tempString = Util.UTF8.GetString(buf, 0, totalBodyBytes);
                     ResponseBody = tempString.Replace("\r", "");
                 }
                 else
@@ -689,75 +692,62 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
                 if (response != null)
                     response.Close();
 
-                // We need to resubmit
-                if (
-                    (Status == (int)HttpStatusCode.MovedPermanently
-                        || Status == (int)HttpStatusCode.Found
-                        || Status == (int)HttpStatusCode.SeeOther
-                        || Status == (int)HttpStatusCode.TemporaryRedirect))
+                if(!Removed)
                 {
-                    if (Redirects >= MaxRedirects)
+                    // We need to resubmit ?
+                    if (Status == (int)HttpStatusCode.MovedPermanently ||
+                            Status == (int)HttpStatusCode.Found ||
+                            Status == (int)HttpStatusCode.SeeOther ||
+                            Status == (int)HttpStatusCode.TemporaryRedirect)
                     {
-                        Status = 499;//.ClientErrorJoker;
-                        ResponseBody = "Number of redirects exceeded max redirects";
-                        WorkItem = null;
-                        RequestModule.GotCompletedRequest(this);
-                    }
-                    else
-                    {
-                        string location = response.Headers["Location"];
-
-                        if (location == null)
-                        {
-                            Status = 499;//ClientErrorJoker;
-                            ResponseBody = "HTTP redirect code but no location header";
-                            WorkItem = null;
-                            RequestModule.GotCompletedRequest(this);
-                        }
-                        else if (!RequestModule.CheckAllowed(new Uri(location)))
+                        if (Redirects >= MaxRedirects)
                         {
-                            Status = 499;//ClientErrorJoker;
-                            ResponseBody = "URL from HTTP redirect blocked: " + location;
-                            WorkItem = null;
+                            Status = 499;//.ClientErrorJoker;
+                            ResponseBody = "Number of redirects exceeded max redirects";
                             RequestModule.GotCompletedRequest(this);
                         }
                         else
                         {
-                            Status = 0;
-                            Url = response.Headers["Location"];
-                            Redirects++;
-                            ResponseBody = null;
+                            string location = response.Headers["Location"];
 
-//                            m_log.DebugFormat("Redirecting to [{0}]", Url);
+                            if (location == null)
+                            {
+                                Status = 499;//ClientErrorJoker;
+                                ResponseBody = "HTTP redirect code but no location header";
+                                RequestModule.GotCompletedRequest(this);
+                            }
+                            else if (!RequestModule.CheckAllowed(new Uri(location)))
+                            {
+                                Status = 499;//ClientErrorJoker;
+                                ResponseBody = "URL from HTTP redirect blocked: " + location;
+                                RequestModule.GotCompletedRequest(this);
+                            }
+                            else
+                            {
+                                Status = 0;
+                                Url = location;
+                                Redirects++;
+                                ResponseBody = null;
 
-                            Process();
+                                //m_log.DebugFormat("Redirecting to [{0}]", Url);
+
+                                Process();
+                            }
                         }
                     }
-                }
-                else
-                {
-                    WorkItem = null;
-                    if (ResponseBody == null)
-                        ResponseBody = String.Empty;
-                    RequestModule.GotCompletedRequest(this);
+                    else
+                    {
+                        if (ResponseBody == null)
+                            ResponseBody = string.Empty;
+                        RequestModule.GotCompletedRequest(this);
+                    }
                 }
             }
         }
 
         public void Stop()
         {
-            try
-            {
-                Removed = true;
-                if(WorkItem == null)
-                    return;
-
-                if (!WorkItem.Cancel())
-                    WorkItem.Cancel(true);
-            }
-            catch (Exception)
-            {
-            }
+            Removed = true;
         }
     }
 }

+ 33 - 44
OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/RegionAssetConnectorModule.cs

@@ -70,7 +70,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset
         //private bool m_inRetries;
 
         private Dictionary<string, List<AssetRetrievedEx>> m_AssetHandlers = new Dictionary<string, List<AssetRetrievedEx>>();
-        private Thread[] m_fetchThreads;
+
+        private ObjectJobEngine m_requestQueue;
 
         public Type ReplaceableInterface
         {
@@ -134,20 +135,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset
                             m_AssetPerms = new AssetPermissions(hgConfig);
                     }
 
-                    //m_sendRetries = new List<AssetBase>[MAXSENDRETRIESLEN];
-                    //m_sendCachedRetries = new List<string>[MAXSENDRETRIESLEN];
-
-                    //m_retryTimer = new System.Timers.Timer();
-                    //m_retryTimer.Elapsed += new ElapsedEventHandler(retryCheck);
-                    //m_retryTimer.AutoReset = true;
-                    //m_retryTimer.Interval = 60000;
-
-                    m_fetchThreads = new Thread[2];
-
-                    for (int i = 0; i < m_fetchThreads.Length; i++)
-                    {
-                        m_fetchThreads[i] = WorkManager.StartThread(AssetRequestProcessor, string.Format("GetAssetsWorker{0}", i));
-                    }
+                    m_requestQueue = new ObjectJobEngine(AssetRequestProcessor, "GetAssetsWorkers", 2000, 2);
                     m_Enabled = true;
                     m_log.Info("[REGIONASSETCONNECTOR]: enabled");
                 }
@@ -160,6 +148,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset
 
         public void Close()
         {
+            if (!m_Enabled)
+                return;
+
+            m_requestQueue.Dispose();
+            m_requestQueue = null;
         }
 
         public void AddRegion(Scene scene)
@@ -341,7 +334,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset
             return null;
         }
 
-        public virtual bool Get(string id, object sender, AssetRetrieved handler)
+        public virtual bool Get(string id, object sender, AssetRetrieved callBack)
         {
             AssetBase asset = null;
             if (m_Cache != null)
@@ -354,7 +347,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset
             {
                 lock (m_AssetHandlers)
                 {
-                    AssetRetrievedEx handlerEx = new AssetRetrievedEx(delegate (AssetBase _asset) { handler(id, sender, _asset); });
+                    AssetRetrievedEx handlerEx = new AssetRetrievedEx(delegate (AssetBase _asset) { callBack(id, sender, _asset); });
 
                     List<AssetRetrievedEx> handlers;
                     if (m_AssetHandlers.TryGetValue(id, out handlers))
@@ -368,55 +361,51 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset
                     handlers.Add(handlerEx);
 
                     m_AssetHandlers.Add(id, handlers);
-                    m_requestQueue.Add(id);
+                    m_requestQueue.Enqueue(id);
                 }
             }
             else
             {
                 if (asset != null && (asset.Data == null || asset.Data.Length == 0))
                     asset = null;
-                handler(id, sender, asset);
+                callBack(id, sender, asset);
             }
             return true;
         }
 
-        private BlockingCollection<string> m_requestQueue = new BlockingCollection<string>();
-        private void AssetRequestProcessor()
+        private void AssetRequestProcessor(object o)
         {
-            while (true)
+            string id = o as string;
+            if(id == null)
+                return;
+
+            try
             {
-                if (!m_requestQueue.TryTake(out string id, 4500) || id == null)
+                AssetBase a = Get(id);
+                List<AssetRetrievedEx> handlers;
+                lock (m_AssetHandlers)
                 {
-                    Watchdog.UpdateThread();
-                    continue;
+                    handlers = m_AssetHandlers[id];
+                    m_AssetHandlers.Remove(id);
                 }
 
-                Watchdog.UpdateThread();
-                try
+                if (handlers != null)
                 {
-                    AssetBase a = Get(id);
-                    List<AssetRetrievedEx> handlers;
-                    lock (m_AssetHandlers)
+                    Util.FireAndForget(x =>
                     {
-                        handlers = m_AssetHandlers[id];
-                        m_AssetHandlers.Remove(id);
-                    }
-
-                    if (handlers != null)
-                    {
-                        Util.FireAndForget(x =>
+                        foreach (AssetRetrievedEx h in handlers)
                         {
-                            foreach (AssetRetrievedEx h in handlers)
+                            try
                             {
-                                try { h.Invoke(a); }
-                                catch { }
+                                h.Invoke(a);
                             }
-                            handlers.Clear();
-                        });
-                    }
+                            catch { }
+                        }
+                        handlers.Clear();
+                    });
                 }
-                catch { }
             }
+            catch { }
         }
 
         public bool[] AssetsExist(string[] ids)

+ 3 - 1
OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs

@@ -1044,7 +1044,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
             ViewerEnvironment regionEnv = null;
             try
             {
-                loadedRegionSettings = RegionSettingsSerializer.Deserialize(data, out regionEnv);
+                loadedRegionSettings = RegionSettingsSerializer.Deserialize(data, out regionEnv, scene.RegionInfo.EstateSettings);
             }
             catch (Exception e)
             {
@@ -1104,6 +1104,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver
             currentRegionSettings.CacheID = UUID.Random();
             currentRegionSettings.Save();
 
+            scene.EstateDataServiceSafe?.StoreEstateSettings(scene.RegionInfo.EstateSettings);
+
             IEstateModule estateModule = scene.RequestModuleInterface<IEstateModule>();
             if (estateModule != null)
                 estateModule.sendRegionHandshakeToAll();

+ 1 - 1
OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs

@@ -579,7 +579,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
             // Write out region settings
             string settingsPath = String.Format("{0}{1}{2}.xml",
                 regionDir, ArchiveConstants.SETTINGS_PATH, scene.RegionInfo.RegionName);
-            m_archiveWriter.WriteFile(settingsPath, RegionSettingsSerializer.Serialize(scene.RegionInfo.RegionSettings, scene.RegionEnvironment));
+            m_archiveWriter.WriteFile(settingsPath, RegionSettingsSerializer.Serialize(scene.RegionInfo.RegionSettings, scene.RegionEnvironment, scene.RegionInfo.EstateSettings));
 
             m_log.InfoFormat("[ARCHIVER]: Adding parcel settings to archive.");
 

+ 1 - 1
OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs

@@ -657,7 +657,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
             rs.TelehubObject = UUID.Parse("00000000-0000-0000-0000-111111111111");
             rs.AddSpawnPoint(SpawnPoint.Parse("1,-2,0.33"));
 
-            tar.WriteFile(ArchiveConstants.SETTINGS_PATH + "region1.xml", RegionSettingsSerializer.Serialize(rs, null));
+            tar.WriteFile(ArchiveConstants.SETTINGS_PATH + "region1.xml", RegionSettingsSerializer.Serialize(rs, null, new EstateSettings()));
 
             tar.Close();
 

+ 15 - 9
OpenSim/Region/CoreModules/World/LightShare/EnvironmentModule.cs

@@ -65,10 +65,10 @@ namespace OpenSim.Region.CoreModules.World.LightShare
         private ILandChannel m_landChannel;
 
         private static ViewerEnvironment m_DefaultEnv = null;
-        // 1/1 night day ratio
-        //private static readonly string m_defaultDayAssetID = "5646d39e-d3d7-6aff-ed71-30fc87d64a91";
-        // 3/1 night day ratio
-        private static string m_defaultDayAssetID = "5646d39e-d3d7-6aff-ed71-30fc87d64a92";
+        // 1/1 day-to-night ratio
+        //private static readonly string m_defaultDayAssetID = "5646d39e-d3d7-6aff-ed71-30fc87d64a91";  // Default Daycycle
+        // 3/1 day-to-night ratio
+        private static string m_defaultDayAssetID = "5646d39e-d3d7-6aff-ed71-30fc87d64a92";             // Default Daycycle (More Daylight)
         private static UUID m_defaultDayAssetUUID = new UUID("5646d39e-d3d7-6aff-ed71-30fc87d64a92");
         //private static string m_defaultSkyAssetID = "3ae23978-ac82-bcf3-a9cb-ba6e52dcb9ad";
         private static UUID m_defaultSkyAssetUUID = new UUID("3ae23978-ac82-bcf3-a9cb-ba6e52dcb9ad");
@@ -168,10 +168,10 @@ namespace OpenSim.Region.CoreModules.World.LightShare
                         m_DefaultEnv = new ViewerEnvironment();
                         m_DefaultEnv.CycleFromOSD(oenv);
                     }
-                    catch ( Exception e)
+                    catch (Exception e)
                     {
                         m_DefaultEnv = null;
-                        m_log.WarnFormat("[Environment {0}]: failed to decode default environment asset: {1}", m_scene.Name, e.Message);
+                        m_log.Warn(string.Format("[Environment {0}] failed to decode default environment asset ", m_scene.Name), e);
                     }
                 }
             }
@@ -185,16 +185,22 @@ namespace OpenSim.Region.CoreModules.World.LightShare
                 {
                     OSD oenv = OSDParser.Deserialize(senv);
                     ViewerEnvironment VEnv = new ViewerEnvironment();
-                    if(oenv is OSDArray)
+                    if (oenv is OSDArray)
+                    {
                         VEnv.FromWLOSD(oenv);
+                        StoreOnRegion(VEnv);
+                        m_log.InfoFormat("[Environment {0}] migrated WindLight environment settings to EEP", m_scene.Name);
+                    }
                     else
+                    {
                         VEnv.FromOSD(oenv);
+                    }
                     scene.RegionEnvironment = VEnv;
                     m_regionEnvVersion = VEnv.version;
                 }
                 catch (Exception e)
                 {
-                    m_log.ErrorFormat("[Environment {0}] failed to load initial Environment {1}", m_scene.Name, e.Message);
+                    m_log.Error(string.Format("[Environment {0}] failed to load initial Environment ", m_scene.Name), e);
                     scene.RegionEnvironment = null;
                     m_regionEnvVersion = -1;
                 }
@@ -246,7 +252,7 @@ namespace OpenSim.Region.CoreModules.World.LightShare
             }
             catch (Exception e)
             {
-                m_log.ErrorFormat("[Environment {0}] failed to store Environment {1}", m_scene.Name, e.Message);
+                m_log.Error(string.Format("[Environment {0}] failed to store Environment ", m_scene.Name), e);
             }
         }
 

+ 63 - 73
OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs

@@ -80,7 +80,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
         protected volatile bool m_Enabled = false;
 
         private ManualResetEvent m_mapBlockRequestEvent = new ManualResetEvent(false);
-        private BlockingCollection<MapRequestState> m_mapItemsRequests = new BlockingCollection<MapRequestState>();
+        private ObjectJobEngine m_mapItemsRequests;
         private readonly Dictionary<UUID, Queue<MapBlockRequestData>> m_mapBlockRequests = new Dictionary<UUID, Queue<MapBlockRequestData>>();
 
         private readonly List<MapBlockData> cachedMapBlocks = new List<MapBlockData>();
@@ -357,7 +357,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
             if (!m_threadsRunning)
             {
                 m_threadsRunning = true;
-                WorkManager.StartThread(MapItemsprocess, string.Format("MapItems ({0})", m_regionName));
+                m_mapItemsRequests = new ObjectJobEngine(MapItemsprocess,string.Format("MapItems ({0})", m_regionName));
                 WorkManager.StartThread(MapBlocksProcess, string.Format("MapBlocks ({0})", m_regionName));
             }
         }
@@ -369,7 +369,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
         {
             m_threadsRunning = false;
             m_mapBlockRequestEvent.Set();
-            m_mapItemsRequests.Add(null);
+            m_mapItemsRequests.Dispose();
         }
 
         public virtual void HandleMapItemRequest(IClientAPI remoteClient, uint flags,
@@ -638,97 +638,78 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
         /// <summary>
         /// Processing thread main() loop for doing remote mapitem requests
         /// </summary>
-        public void MapItemsprocess()
+        public void MapItemsprocess(object o)
         {
+            if (m_scene == null || !m_threadsRunning)
+                return;
+
             const int MAX_ASYNC_REQUESTS = 5;
             ScenePresence av = null;
-            MapRequestState st = null;
+            MapRequestState st = o as MapRequestState;
+
+            if (st == null || st.agentID == UUID.Zero)
+                return;
+
+            if (m_blacklistedregions.ContainsKey(st.regionhandle))
+                return;
+            if (!m_scene.TryGetScenePresence(st.agentID, out av))
+                return;
+            if (av == null || av.IsChildAgent || av.IsDeleted || av.IsInTransit)
+                return;
 
             try
             {
-                while (true)
+                if (m_cachedRegionMapItemsResponses.TryGetValue(st.regionhandle, out OSDMap responseMap))
                 {
-                    av = null;
-                    st = null;
-
-                    m_mapItemsRequests.TryTake(out st, 4500);
-                    Watchdog.UpdateThread();
-
-                    if (m_scene == null || !m_threadsRunning)
-                        break;
-
-                    if (st == null || st.agentID == UUID.Zero)
-                        continue;
-
-                    if(!m_scene.TryGetScenePresence(st.agentID, out av))
-                        continue;
-                    if (av == null || av.IsChildAgent || av.IsDeleted || av.IsInTransit)
-                        continue;
-
-                    if(m_blacklistedregions.ContainsKey(st.regionhandle))
-                        continue;
-
-                    if (m_cachedRegionMapItemsResponses.TryGetValue(st.regionhandle, out OSDMap responseMap))
+                    if (responseMap != null)
                     {
-                        if (responseMap != null)
+                        if (responseMap.ContainsKey(st.itemtype.ToString()))
                         {
-                            if (responseMap.ContainsKey(st.itemtype.ToString()))
+                            List<mapItemReply> returnitems = new List<mapItemReply>();
+                            OSDArray itemarray = (OSDArray)responseMap[st.itemtype.ToString()];
+                            for (int i = 0; i < itemarray.Count; i++)
                             {
-                                List<mapItemReply> returnitems = new List<mapItemReply>();
-                                OSDArray itemarray = (OSDArray)responseMap[st.itemtype.ToString()];
-                                for (int i = 0; i < itemarray.Count; i++)
-                                {
-                                    OSDMap mapitem = (OSDMap)itemarray[i];
-                                    mapItemReply mi = new mapItemReply();
-                                    mi.x = (uint)mapitem["X"].AsInteger();
-                                    mi.y = (uint)mapitem["Y"].AsInteger();
-                                    mi.id = mapitem["ID"].AsUUID();
-                                    mi.Extra = mapitem["Extra"].AsInteger();
-                                    mi.Extra2 = mapitem["Extra2"].AsInteger();
-                                    mi.name = mapitem["Name"].AsString();
-                                    returnitems.Add(mi);
-                                }
-                                av.ControllingClient.SendMapItemReply(returnitems.ToArray(), st.itemtype, st.flags & 0xffff);
+                                OSDMap mapitem = (OSDMap)itemarray[i];
+                                mapItemReply mi = new mapItemReply();
+                                mi.x = (uint)mapitem["X"].AsInteger();
+                                mi.y = (uint)mapitem["Y"].AsInteger();
+                                mi.id = mapitem["ID"].AsUUID();
+                                mi.Extra = mapitem["Extra"].AsInteger();
+                                mi.Extra2 = mapitem["Extra2"].AsInteger();
+                                mi.name = mapitem["Name"].AsString();
+                                returnitems.Add(mi);
                             }
-                        }
-                        else
-                        {
-                            m_mapItemsRequests.Add(st);
-                            if(m_mapItemsRequests.Count<3)
-                                Thread.Sleep(100);
-                            if (m_scene == null || !m_threadsRunning)
-                                    break;
+                            av.ControllingClient.SendMapItemReply(returnitems.ToArray(), st.itemtype, st.flags & 0xffff);
                         }
                     }
                     else
                     {
-                        m_cachedRegionMapItemsResponses.AddOrUpdate(st.regionhandle, null, expireResponsesTime); //  a bit more time for the access
-
-                        // nothig for region, fire a request
-                        Interlocked.Increment(ref nAsyncRequests);
-                        MapRequestState rst = st;
-                        Util.FireAndForget(x =>
-                        {
-                            RequestMapItemsAsync(rst);
-                        });
+                        m_mapItemsRequests.Enqueue(st);
+                        if (m_mapItemsRequests.Count < 3)
+                            Thread.Sleep(100);
                     }
+                }
+                else
+                {
+                    m_cachedRegionMapItemsResponses.AddOrUpdate(st.regionhandle, null, expireResponsesTime); //  a bit more time for the access
 
-                    while (nAsyncRequests >= MAX_ASYNC_REQUESTS) // hit the break
+                    // nothig for region, fire a request
+                    Interlocked.Increment(ref nAsyncRequests);
+                    MapRequestState rst = st;
+                    Util.FireAndForget(x =>
                     {
-                        Thread.Sleep(100);
-                        if (m_scene == null || !m_threadsRunning)
-                            break;
-                        Watchdog.UpdateThread();
-                    }
+                        RequestMapItemsAsync(rst);
+                    });
+                }
+
+                while (nAsyncRequests >= MAX_ASYNC_REQUESTS) // hit the break
+                {
+                    Thread.Sleep(100);
                     if (m_scene == null || !m_threadsRunning)
                         break;
                 }
             }
-            catch
-            {
-            }
-
-            Watchdog.RemoveThread();
+            catch { }
         }
 
         /// <summary>
@@ -742,6 +723,9 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
         /// <param name="regionhandle">Region we're looking up</param>
         public void RequestMapItems(UUID id, uint flags, uint EstateID, bool godlike, uint itemtype, ulong regionhandle)
         {
+            if(!m_threadsRunning)
+                return;
+
             MapRequestState st = new MapRequestState();
             st.agentID = id;
             st.flags = flags;
@@ -749,7 +733,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
             st.godlike = godlike;
             st.itemtype = itemtype;
             st.regionhandle = regionhandle;
-            m_mapItemsRequests.Add(st);
+            m_mapItemsRequests.Enqueue(st);
         }
 
         private static readonly uint[] itemTypesForcedSend = new uint[] { 6, 1, 7, 10 }; // green dots, infohub, land sells
@@ -1576,6 +1560,12 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
             }
         }
 
+        public void DeregisterMap()
+        {
+            //if (m_mapImageServiceModule != null)
+            //    m_mapImageServiceModule.RemoveMapTiles(m_scene);
+        }
+
         private void GenerateMaptile(Bitmap mapbmp)
         {
             bool needRegionSave = false;

+ 31 - 13
OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs

@@ -314,16 +314,22 @@ namespace OpenSim.Region.Framework.Scenes
             // the client handles rez correctly
             obj.ObjectGrabHandler(localID, offsetPos, remoteClient);
 
+            uint partLocalId = part.LocalId;
             // If the touched prim handles touches, deliver it
             if ((part.ScriptEvents & scriptEvents.touch_start) != 0)
-                EventManager.TriggerObjectGrab(part.LocalId, 0, offsetPos, remoteClient, surfaceArg);
+            {
+                EventManager.TriggerObjectGrab(partLocalId, 0, offsetPos, remoteClient, surfaceArg);
+                if(!part.PassTouches)
+                    return;
+            }
 
             // Deliver to the root prim if the touched prim doesn't handle touches
             // or if we're meant to pass on touches anyway.
-            if (((part.ScriptEvents & scriptEvents.touch_start) == 0) ||
-                (part.PassTouches && (part.LocalId != obj.RootPart.LocalId)))
+
+            uint rootLocalId = obj.RootPart.LocalId;
+            if (partLocalId != rootLocalId &&  (obj.RootPart.ScriptEvents & scriptEvents.touch_start) != 0)
             {
-                EventManager.TriggerObjectGrab(obj.RootPart.LocalId, part.LocalId, offsetPos, remoteClient, surfaceArg);
+                EventManager.TriggerObjectGrab(rootLocalId, partLocalId, offsetPos, remoteClient, surfaceArg);
             }
         }
 
@@ -355,14 +361,21 @@ namespace OpenSim.Region.Framework.Scenes
 
             Vector3 grabOffset = pos - part.AbsolutePosition;
             // If the touched prim handles touches, deliver it
+            uint partLocalId = part.LocalId;
             if ((part.ScriptEvents & scriptEvents.touch) != 0)
-                EventManager.TriggerObjectGrabbing(part.LocalId, 0, grabOffset, remoteClient, surfaceArg);
+            {
+                EventManager.TriggerObjectGrabbing(partLocalId, 0, grabOffset, remoteClient, surfaceArg);
+                if(!part.PassTouches)
+                    return;
+            }
 
+            uint rootLocalId = group.RootPart.LocalId;
             // Deliver to the root prim if the touched prim doesn't handle touches
             // or if we're meant to pass on touches anyway.
-            if (((part.ScriptEvents & scriptEvents.touch) == 0) ||
-                (part.PassTouches && (part.LocalId != group.RootPart.LocalId)))
-                EventManager.TriggerObjectGrabbing(group.RootPart.LocalId, part.LocalId, grabOffset, remoteClient, surfaceArg);
+            if (partLocalId != rootLocalId && (group.RootPart.ScriptEvents & scriptEvents.touch) != 0)
+            {
+                EventManager.TriggerObjectGrabbing(rootLocalId, partLocalId, grabOffset, remoteClient, surfaceArg);
+            }
         }
 
         public virtual void ProcessObjectDeGrab(uint localID, IClientAPI remoteClient, List<SurfaceTouchEventArgs> surfaceArgs)
@@ -377,14 +390,19 @@ namespace OpenSim.Region.Framework.Scenes
             if (surfaceArgs != null && surfaceArgs.Count > 0)
                 surfaceArg = surfaceArgs[0];
 
+            uint partLocalId = part.LocalId;
             // If the touched prim handles touches, deliver it
             if ((part.ScriptEvents & scriptEvents.touch_end) != 0)
-                EventManager.TriggerObjectDeGrab(part.LocalId, 0, remoteClient, surfaceArg);
-            // if not or PassTouchs, send it also to root.
-            if (((part.ScriptEvents & scriptEvents.touch_end) == 0) ||
-                (part.PassTouches && (part.LocalId != grp.RootPart.LocalId)))
             {
-                EventManager.TriggerObjectDeGrab(grp.RootPart.LocalId, part.LocalId, remoteClient, surfaceArg);
+                EventManager.TriggerObjectDeGrab(partLocalId, 0, remoteClient, surfaceArg);
+                if(!part.PassTouches)
+                    return;
+            }
+
+            uint rootPartLocalId = grp.RootPart.LocalId;
+            if (partLocalId != rootPartLocalId && (grp.RootPart.ScriptEvents & scriptEvents.touch_end) != 0)
+            {
+                EventManager.TriggerObjectDeGrab(rootPartLocalId, partLocalId, remoteClient, surfaceArg);
             }
         }
 

+ 141 - 148
OpenSim/Region/Framework/Scenes/Scene.cs

@@ -126,7 +126,7 @@ namespace OpenSim.Region.Framework.Scenes
         private bool m_physicsEnabled;
 
         /// <summary>
-        /// If false then scripts are not enabled on the smiulator
+        /// If false then scripts are not enabled on the simulator
         /// </summary>
         public bool ScriptsEnabled
         {
@@ -556,7 +556,7 @@ namespace OpenSim.Region.Framework.Scenes
             {
                 if (m_EstateDataService == null)
                 {
-                    m_EstateDataService = RequestModuleInterface<IEstateDataService>();
+                    m_EstateDataService = EstateDataServiceSafe;
 
                     if (m_EstateDataService == null)
                     {
@@ -568,6 +568,22 @@ namespace OpenSim.Region.Framework.Scenes
             }
         }
 
+        /// <summary>
+        /// Similar to 'EstateDataService', but if the service isn't found returns null instead of throwing an exception.
+        /// </summary>
+        public IEstateDataService EstateDataServiceSafe
+        {
+            get
+            {
+                if (m_EstateDataService == null)
+                {
+                    m_EstateDataService = RequestModuleInterface<IEstateDataService>();
+                }
+
+                return m_EstateDataService;
+            }
+        }
+
         public IAssetService AssetService
         {
             get
@@ -1067,9 +1083,8 @@ namespace OpenSim.Region.Framework.Scenes
 
                 string[] possibleAccessControlConfigSections = new string[] { "Startup", "AccessControl"};
 
-                string grant
-                    = Util.GetConfigVarFromSections<string>(
-                        config, "AllowedClients", possibleAccessControlConfigSections, string.Empty);
+                string grant = Util.GetConfigVarFromSections<string>(
+                    config, "AllowedClients", possibleAccessControlConfigSections, string.Empty);
 
                 if (grant.Length > 0)
                 {
@@ -1079,9 +1094,7 @@ namespace OpenSim.Region.Framework.Scenes
                     }
                 }
 
-                grant
-                    = Util.GetConfigVarFromSections<string>(
-                        config, "DeniedClients", possibleAccessControlConfigSections, String.Empty);
+                grant = Util.GetConfigVarFromSections<string>(config, "DeniedClients", possibleAccessControlConfigSections, String.Empty);
                 // Deal with the mess of someone having used a different word at some point
                 if (grant == String.Empty)
                     grant = Util.GetConfigVarFromSections<string>(
@@ -1672,23 +1685,25 @@ namespace OpenSim.Region.Framework.Scenes
 
         public override void Update(int frames)
         {
-            long? endFrame = null;
+            long endFrame;
 
             if (frames >= 0)
                 endFrame = Frame + frames;
+            else
+                endFrame = long.MaxValue;
 
             float physicsFPS = 0f;
             float frameTimeMS = FrameTime * 1000.0f;
 
             int previousFrameTick;
 
-            double tmpMS;
-            double tmpMS2;
+            double lastMS;
+            double nowMS;
             double framestart;
             float sleepMS;
             float sleepError = 0;
 
-            while (!m_shuttingDown && ((endFrame == null && Active) || Frame < endFrame))
+            while (!m_shuttingDown && ((endFrame == long.MaxValue && Active) || Frame < endFrame))
             {
                 framestart = Util.GetTimeStampMS();
                 ++Frame;
@@ -1703,7 +1718,7 @@ namespace OpenSim.Region.Framework.Scenes
 
                     // Apply taints in terrain module to terrain in physics scene
 
-                    tmpMS = Util.GetTimeStampMS();
+                    lastMS = Util.GetTimeStampMS();
 
                     if (Frame % 4 == 0)
                     {
@@ -1715,47 +1730,44 @@ namespace OpenSim.Region.Framework.Scenes
                         UpdateTerrain();
                     }
 
-                    tmpMS2 = Util.GetTimeStampMS();
-                    terrainMS = (float)(tmpMS2 - tmpMS);
-                    tmpMS = tmpMS2;
+                    nowMS = Util.GetTimeStampMS();
+                    terrainMS = (float)(nowMS - lastMS);
+                    lastMS = nowMS;
 
                     if (PhysicsEnabled && Frame % m_update_physics == 0)
                         m_sceneGraph.UpdatePreparePhysics();
 
-                    tmpMS2 = Util.GetTimeStampMS();
-                    physicsMS2 = (float)(tmpMS2 - tmpMS);
-                    tmpMS = tmpMS2;
+                    nowMS = Util.GetTimeStampMS();
+                    physicsMS2 = (float)(nowMS - lastMS);
+                    lastMS = nowMS;
 
 /*
                     // Apply any pending avatar force input to the avatar's velocity
                     if (Frame % m_update_entitymovement == 0)
                         m_sceneGraph.UpdateScenePresenceMovement();
 */
-                    if (Frame % (m_update_coarse_locations) == 0 && !m_sendingCoarseLocations)
+                    if (!m_sendingCoarseLocations && GetNumberOfClients() > 0 && Frame % m_update_coarse_locations == 0)
                     {
-                        if(GetNumberOfClients() > 0)
-                        {
-                            m_sendingCoarseLocations = true;
-                            WorkManager.RunInThreadPool(
-                                delegate
+                        m_sendingCoarseLocations = true;
+                        WorkManager.RunInThreadPool(
+                            delegate
+                            {
+                                SceneGraph.GetCoarseLocations(out List<Vector3> coarseLocations, out List<UUID> avatarUUIDs, 60);
+                                // Send coarse locations to clients
+                                ForEachScenePresence(delegate(ScenePresence presence)
                                 {
-                                    SceneGraph.GetCoarseLocations(out List<Vector3> coarseLocations, out List<UUID> avatarUUIDs, 60);
-                                    // Send coarse locations to clients
-                                    ForEachScenePresence(delegate(ScenePresence presence)
-                                    {
-                                        if(!presence.IsNPC)
-                                            presence.SendCoarseLocations(coarseLocations, avatarUUIDs);
-                                    });
-                                    m_sendingCoarseLocations = false; 
-                                }, null, string.Format("SendCoarseLocations ({0})", Name));
-                        }
+                                    if(!presence.IsNPC)
+                                        presence.SendCoarseLocations(coarseLocations, avatarUUIDs);
+                                });
+                                m_sendingCoarseLocations = false; 
+                            }, null, string.Format("SendCoarseLocations ({0})", Name));
                     }
 
                     // Get the simulation frame time that the avatar force input
                     // took
-                    tmpMS2 = Util.GetTimeStampMS();
-                    agentMS = (float)(tmpMS2 - tmpMS);
-                    tmpMS = tmpMS2;
+                    nowMS = Util.GetTimeStampMS();
+                    agentMS = (float)(nowMS - lastMS);
+                    lastMS = nowMS;
 
                     // Perform the main physics update.  This will do the actual work of moving objects and avatars according to their
                     // velocity
@@ -1765,10 +1777,11 @@ namespace OpenSim.Region.Framework.Scenes
                             physicsFPS = m_sceneGraph.UpdatePhysics(FrameTime);
                     }
 
-                    tmpMS2 = Util.GetTimeStampMS();
-                    physicsMS = (float)(tmpMS2 - tmpMS);
-                    tmpMS = tmpMS2;
+                    nowMS = Util.GetTimeStampMS();
+                    physicsMS = (float)(nowMS - lastMS);
+                    lastMS = nowMS;
 
+                    //CheckKFM(FrameTime);
                     // Check if any objects have reached their targets
                     CheckAtTargets();
 
@@ -1777,18 +1790,18 @@ namespace OpenSim.Region.Framework.Scenes
                     if (Frame % m_update_objects == 0)
                         m_sceneGraph.UpdateObjectGroups();
 
-                    tmpMS2 = Util.GetTimeStampMS();
-                    otherMS = (float)(tmpMS2 - tmpMS);
-                    tmpMS = tmpMS2;
+                    nowMS = Util.GetTimeStampMS();
+                    otherMS = (float)(nowMS - lastMS);
+                    lastMS = nowMS;
 
                     // Run through all ScenePresences looking for updates
                     // Presence updates and queued object updates for each presence are sent to clients
                     if (Frame % m_update_presences == 0)
                         m_sceneGraph.UpdatePresences();
 
-                    tmpMS2 = Util.GetTimeStampMS();
-                    agentMS += (float)(tmpMS2 - tmpMS);
-                    tmpMS = tmpMS2;
+                    nowMS = Util.GetTimeStampMS();
+                    agentMS += (float)(nowMS - lastMS);
+                    lastMS = nowMS;
 
                     // Delete temp-on-rez stuff
                     if (Frame % m_update_temp_cleaning == 0 && !m_cleaningTemps)
@@ -1796,27 +1809,27 @@ namespace OpenSim.Region.Framework.Scenes
                         m_cleaningTemps = true;
                         WorkManager.RunInThreadPool(
                             delegate { CleanTempObjects(); m_cleaningTemps = false; }, null, string.Format("CleanTempObjects ({0})", Name));
-                        tmpMS2 = Util.GetTimeStampMS();
-                        tempOnRezMS = (float)(tmpMS2 - tmpMS); // bad.. counts the FireAndForget, not CleanTempObjects
-                        tmpMS = tmpMS2;
+                        nowMS = Util.GetTimeStampMS();
+                        tempOnRezMS = (float)(nowMS - lastMS); // bad.. counts the FireAndForget, not CleanTempObjects
+                        lastMS = nowMS;
                     }
 
                     if (Frame % m_update_events == 0)
                     {
                         UpdateEvents();
 
-                        tmpMS2 = Util.GetTimeStampMS();
-                        eventMS = (float)(tmpMS2 - tmpMS);
-                        tmpMS = tmpMS2;
+                        nowMS = Util.GetTimeStampMS();
+                        eventMS = (float)(nowMS - lastMS);
+                        lastMS = nowMS;
                     }
 
                     if (PeriodicBackup && Frame % m_update_backup == 0)
                     {
                         UpdateStorageBackup();
 
-                        tmpMS2 = Util.GetTimeStampMS();
-                        backupMS = (float)(tmpMS2 - tmpMS);
-                        tmpMS = tmpMS2;
+                        nowMS = Util.GetTimeStampMS();
+                        backupMS = (float)(nowMS - lastMS);
+                        lastMS = nowMS;
                     }
 
                     //if (Frame % m_update_land == 0)
@@ -1898,33 +1911,33 @@ namespace OpenSim.Region.Framework.Scenes
 
                 otherMS += tempOnRezMS + eventMS + backupMS + terrainMS + landMS;
 
-                tmpMS = Util.GetTimeStampMS();
+                lastMS = Util.GetTimeStampMS();
 
                 previousFrameTick = m_lastFrameTick;
-                m_lastFrameTick = (int)(tmpMS + 0.5);
+                m_lastFrameTick = (int)(lastMS + 0.5);
 
                 // estimate sleep time
-                tmpMS2 = tmpMS - framestart;
-                tmpMS2 = (double)frameTimeMS - tmpMS2 - sleepError;
+                nowMS = lastMS - framestart;
+                nowMS = (double)frameTimeMS - nowMS - sleepError;
 
                 // reuse frameMS as temporary
-                frameMS = (float)tmpMS2;
+                frameMS = (float)nowMS;
 
                 // sleep if we can
-                if (tmpMS2 > 0)
+                if (nowMS > 0)
                     {
-                    Thread.Sleep((int)(tmpMS2 + 0.5));
+                    Thread.Sleep((int)(nowMS + 0.5));
 
-                    tmpMS2 = Util.GetTimeStampMS();
-                    sleepMS = (float)(tmpMS2 - tmpMS);
+                    nowMS = Util.GetTimeStampMS();
+                    sleepMS = (float)(nowMS - lastMS);
                     sleepError = sleepMS - frameMS;
                     Util.Clamp(sleepError, 0.0f, 20f);
-                    frameMS = (float)(tmpMS2 - framestart);
+                    frameMS = (float)(nowMS - framestart);
                     }
                 else
                     {
-                    tmpMS2 = Util.GetTimeStampMS();
-                    frameMS = (float)(tmpMS2 - framestart);
+                    nowMS = Util.GetTimeStampMS();
+                    frameMS = (float)(nowMS - framestart);
                     sleepMS = 0.0f;
                     sleepError = 0.0f;
                     }
@@ -1934,11 +1947,6 @@ namespace OpenSim.Region.Framework.Scenes
                 StatsReporter.AddFrameStats(TimeDilation, physicsFPS, agentMS,
                              physicsMS + physicsMS2, otherMS , sleepMS, frameMS, scriptTimeMS);
 
-
-
-                // if (Frame%m_update_avatars == 0)
-                //   UpdateInWorldTime();
-
           // Optionally warn if a frame takes double the amount of time that it should.
                 if (DebugUpdates
                     && Util.EnvironmentTickCountSubtract(
@@ -3165,9 +3173,7 @@ namespace OpenSim.Region.Framework.Scenes
             // In the future this can be relieved once locking per agent (not necessarily on AgentCircuitData) is improved.
             lock (aCircuit)
             {
-                vialogin
-                    = (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0
-                        || (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0;
+                vialogin = (aCircuit.teleportFlags & (uint)(Constants.TeleportFlags.ViaHGLogin | Constants.TeleportFlags.ViaLogin)) != 0;
 
                 CheckHeartbeat();
 
@@ -3184,6 +3190,7 @@ namespace OpenSim.Region.Framework.Scenes
                     SubscribeToClientEvents(client);
 
                     sp = m_sceneGraph.CreateAndAddChildScenePresence(client, aCircuit.Appearance, type);
+                    aCircuit.Appearance = null;
 
                     sp.TeleportFlags = (TPFlags)aCircuit.teleportFlags;
 
@@ -3812,11 +3819,6 @@ namespace OpenSim.Region.Framework.Scenes
 
                     m_sceneGraph.removeUserCount(!isChildAgent);
 
-                    // TODO: We shouldn't use closeChildAgents here - it's being used by the NPC module to stop
-                    // unnecessary operations.  This should go away once NPCs have no accompanying IClientAPI
-                    if (closeChildAgents && CapsModule != null)
-                        CapsModule.RemoveCaps(agentID, avatar.ControllingClient.CircuitCode);
-
                     if (closeChildAgents && !isChildAgent)
                     {
                         List<ulong> regions = avatar.KnownRegionHandles;
@@ -3869,10 +3871,14 @@ namespace OpenSim.Region.Framework.Scenes
                         // Always clean these structures up so that any failure above doesn't cause them to remain in the
                         // scene with possibly bad effects (e.g. continually timing out on unacked packets and triggering
                         // the same cleanup exception continually.
-                        m_authenticateHandler.RemoveCircuit(agentID);
+                        m_authenticateHandler.RemoveCircuit(acd);
                         m_sceneGraph.RemoveScenePresence(agentID);
                         m_clientManager.Remove(agentID);
-
+                        if (m_capsModule != null)
+                        {
+                            if(avatar == null || !avatar.IsNPC)
+                                m_capsModule.RemoveCaps(agentID, acd.circuitcode);
+                        }
                         avatar.Dispose();
                     }
                     catch (Exception e)
@@ -4062,9 +4068,8 @@ namespace OpenSim.Region.Framework.Scenes
 
                 // We need to ensure that we are not already removing the scene presence before we ask it not to be
                 // closed.
-                if (sp != null && !sp.IsDeleted && sp.IsChildAgent
-                    && (sp.LifecycleState == ScenePresenceState.Running
-                        || sp.LifecycleState == ScenePresenceState.PreRemove))
+                if (sp != null && !sp.IsDeleted && sp.IsChildAgent &&
+                    (sp.LifecycleState == ScenePresenceState.Running || sp.LifecycleState == ScenePresenceState.PreRemove))
                 {
                     m_log.DebugFormat(
                         "[SCENE]: Reusing existing child scene presence for {0}, state {1} in {2}",
@@ -4164,7 +4169,7 @@ namespace OpenSim.Region.Framework.Scenes
                     checkTeleHub = vialogin
                         || (TelehubAllowLandmarks == true ? false : ((teleportFlags & (uint)(TPFlags.ViaLandmark | TPFlags.ViaLocation)) != 0));
 
-                if (!CheckLandPositionAccess(acd.AgentID, true, checkTeleHub, acd.startpos, out reason))
+                if (!CheckLandPositionAccess(acd.AgentID, true, checkTeleHub, false, acd.startpos, out reason))
                 {
                     m_authenticateHandler.RemoveCircuit(acd);
                     return false;
@@ -4256,10 +4261,10 @@ namespace OpenSim.Region.Framework.Scenes
                         Name, (acd.child ? "child" : "root"), acd.firstname, acd.lastname,
                         acd.AgentID, acd.circuitcode);
 
-                    if (CapsModule != null)
+                    if (m_capsModule != null)
                     {
-                        CapsModule.SetAgentCapsSeeds(acd);
-                        CapsModule.CreateCaps(acd.AgentID, acd.circuitcode);
+                        m_capsModule.SetAgentCapsSeeds(acd);
+                        m_capsModule.CreateCaps(acd.AgentID, acd.circuitcode);
                     }
                 }
                 else
@@ -4272,10 +4277,10 @@ namespace OpenSim.Region.Framework.Scenes
                             "[SCENE]: Adjusting known seeds for existing agent {0} in {1}",
                             acd.AgentID, RegionInfo.RegionName);
 
-                        if (CapsModule != null)
+                        if (m_capsModule != null)
                         {
-                            CapsModule.SetAgentCapsSeeds(acd);
-                            CapsModule.CreateCaps(acd.AgentID, acd.circuitcode);
+                            m_capsModule.SetAgentCapsSeeds(acd);
+                            m_capsModule.CreateCaps(acd.AgentID, acd.circuitcode);
                         }
 
                         sp.AdjustKnownSeeds();
@@ -4288,9 +4293,9 @@ namespace OpenSim.Region.Framework.Scenes
                 CacheUserName(null, acd);
             }
 
-            if (CapsModule != null)
+            if (m_capsModule != null)
             {
-                CapsModule.ActivateCaps(acd.circuitcode);
+                m_capsModule.ActivateCaps(acd.circuitcode);
             }
 
             return true;
@@ -4376,16 +4381,14 @@ namespace OpenSim.Region.Framework.Scenes
         /// also return a reason.</returns>
         public virtual bool VerifyUserPresence(AgentCircuitData agent, out string reason)
         {
-            reason = String.Empty;
-
-            IPresenceService presence = RequestModuleInterface<IPresenceService>();
-            if (presence == null)
+            IPresenceService presencesvc = RequestModuleInterface<IPresenceService>();
+            if (presencesvc == null)
             {
                 reason = String.Format("Failed to verify user presence in the grid for {0} {1} in region {2}. Presence service does not exist.", agent.firstname, agent.lastname, RegionInfo.RegionName);
                 return false;
             }
 
-            OpenSim.Services.Interfaces.PresenceInfo pinfo = presence.GetAgent(agent.SessionID);
+            OpenSim.Services.Interfaces.PresenceInfo pinfo = presencesvc.GetAgent(agent.SessionID);
 
             if (pinfo == null)
             {
@@ -4393,6 +4396,13 @@ namespace OpenSim.Region.Framework.Scenes
                 return false;
             }
 
+            if(pinfo.UserID != agent.AgentID.ToString())
+            {
+                reason = String.Format("Failed to verify user presence in the grid for {0} {1}, access denied to region {2}.", agent.firstname, agent.lastname, RegionInfo.RegionName);
+                return false;
+            }
+
+            reason = string.Empty;
             return true;
         }
 
@@ -4403,9 +4413,10 @@ namespace OpenSim.Region.Framework.Scenes
         /// <param name="reason">outputs the reason to this string</param>
         /// <returns>True if the region accepts this agent.  False if it does not.  False will
         /// also return a reason.</returns>
+
         protected virtual bool AuthorizeUser(AgentCircuitData agent, bool bypassAccessControl, out string reason)
         {
-            reason = String.Empty;
+            reason = string.Empty;
 
             if (!m_strictAccessControl)
                 return true;
@@ -4443,7 +4454,7 @@ namespace OpenSim.Region.Framework.Scenes
                 {
                     m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist",
                             agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName);
-                    reason = String.Format("Denied access to region {0}: You have been banned from that region.",
+                    reason = string.Format("Denied access to region {0}: You have been banned from that region.",
                             RegionInfo.RegionName);
                     return false;
                 }
@@ -4840,22 +4851,22 @@ Label_GroupsDone:
                     // and since they don't get cleaned up they will stick
                     // around until region restart. So, if there is no SP,
                     // remove the client as well.
-                    if (m_authenticateHandler != null)
-                        m_authenticateHandler.RemoveCircuit(agentID);
-
+                    bool ret = false;
                     if (m_clientManager.TryGetValue(agentID, out IClientAPI client))
                     {
-                        m_clientManager.Remove(agentID);
-                        if (CapsModule != null)
-                            CapsModule.RemoveCaps(agentID, 0);
+                        client.Close(force, force);
                         m_log.DebugFormat( "[SCENE]: Dead client for agent ID {0} was cleaned up in {1}", agentID, Name);
-                        return true;
+                        ret = true;
                     }
-                    m_log.DebugFormat(
-                        "[SCENE]: Called CloseClient() with agent ID {0} but no such presence is in {1}",
-                        agentID, Name);
 
-                    return false;
+                    // need to try this again, bc client close may had not done it
+                    if (m_authenticateHandler != null)
+                        m_authenticateHandler.RemoveCircuit(agentID);
+                    m_clientManager.Remove(agentID);
+                    if (m_capsModule != null)
+                        m_capsModule.RemoveCaps(agentID, 0);
+
+                    return ret;
                 }
 
                 if (sp.LifecycleState != ScenePresenceState.Running && sp.LifecycleState != ScenePresenceState.PreRemove)
@@ -6152,49 +6163,19 @@ Environment.Exit(1);
                 return false;
             }
 
-            bool isAdmin = Permissions.IsAdministrator(agentID);
-            bool isManager = Permissions.IsEstateManager(agentID);
-
             // FIXME: Root agent count is currently known to be inaccurate.  This forces a recount before we check.
             // However, the long term fix is to make sure root agent count is always accurate.
             m_sceneGraph.RecalculateStats();
 
-            int num = m_sceneGraph.GetRootAgentCount();
-
-            if (num >= RegionInfo.RegionSettings.AgentLimit)
-            {
-                if (!(isAdmin || isManager))
-                {
-                    reason = "The region is full";
-
-                    m_log.DebugFormat(
-                        "[SCENE]: Denying presence with id {0} entry into {1} since region is at agent limit of {2}",
-                        agentID, RegionInfo.RegionName, RegionInfo.RegionSettings.AgentLimit);
-
-                    return false;
-                }
-            }
-
-            ScenePresence presence = GetScenePresence(agentID);
-            IClientAPI client = null;
-            AgentCircuitData aCircuit = null;
-
-            if (presence != null)
-            {
-                client = presence.ControllingClient;
-                if (client != null)
-                    aCircuit = client.RequestClientInfo();
-            }
-
-            // We may be called before there is a presence or a client.
+            AgentCircuitData aCircuit = m_authenticateHandler.GetAgentCircuitData(agentID);
             // Fake AgentCircuitData to keep IAuthorizationModule smiling
             if (aCircuit == null)
             {
                 aCircuit = new AgentCircuitData()
                 {
                     AgentID = agentID,
-                    firstname = String.Empty,
-                    lastname = String.Empty
+                    firstname = string.Empty,
+                    lastname = string.Empty
                 };
             }
 
@@ -6216,11 +6197,11 @@ Environment.Exit(1);
 
             // last check aditional land access restrictions and relocations
             // if crossing (viaTeleport false) check only the specified parcel
-            return CheckLandPositionAccess(agentID, viaTeleport, true, position, out reason);
+            return CheckLandPositionAccess(agentID, viaTeleport, true, true, position, out reason);
         }
 
         // check access to land.
-        public bool CheckLandPositionAccess(UUID agentID, bool NotCrossing, bool checkTeleHub, Vector3 position, out string reason)
+        public bool CheckLandPositionAccess(UUID agentID, bool NotCrossing, bool checkTeleHub, bool checkRegionAgentCount, Vector3 position, out string reason)
         {
             reason = string.Empty;
 
@@ -6237,6 +6218,18 @@ Environment.Exit(1);
             if(isManager)
                 return true;
 
+            int num = m_sceneGraph.GetRootAgentCount();
+            if (num >= RegionInfo.RegionSettings.AgentLimit)
+            {
+                reason = "The region is full";
+
+                m_log.DebugFormat(
+                    "[SCENE]: Denying presence with id {0} entry into {1} since region is at agent limit of {2}",
+                    agentID, RegionInfo.RegionName, RegionInfo.RegionSettings.AgentLimit);
+
+                return false;
+            }
+
             if (NotCrossing)
             {
                 if (!RegionInfo.EstateSettings.AllowDirectTeleport)

+ 1 - 1
OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs

@@ -1060,7 +1060,7 @@ namespace OpenSim.Region.Framework.Scenes
             inTransit = true;
             
             PhysicsActor pa = RootPart.PhysActor;
-            if(pa == null  || RootPart.KeyframeMotion != null /*|| m_sittingAvatars.Count == 0*/)
+            if(/*pa == null  ||*/ RootPart.KeyframeMotion != null /*|| m_sittingAvatars.Count == 0*/)
             {
                 inTransit = false;
                 return -1;

+ 40 - 33
OpenSim/Region/Framework/Scenes/SceneObjectPart.cs

@@ -262,14 +262,14 @@ namespace OpenSim.Region.Framework.Scenes
         {
             get
             {
-                return (Flags & (PrimFlags)primFlagVolumeDetect) != 0;
+                return (m_flags & (PrimFlags)primFlagVolumeDetect) != 0;
             }
             set
             {
                 if(value)
-                    Flags |= (PrimFlags)primFlagVolumeDetect;
+                    m_flags |= (PrimFlags)primFlagVolumeDetect;
                 else
-                    Flags &= (PrimFlags)(~primFlagVolumeDetect);
+                    m_flags &= (PrimFlags)(~primFlagVolumeDetect);
             }
         }
 
@@ -295,8 +295,6 @@ namespace OpenSim.Region.Framework.Scenes
 
         public bool IgnoreUndoUpdate = false;
 
-        public PrimFlags LocalFlags;
-
         private float m_damage = -1.0f;
         private byte[] m_TextureAnimation;
         private byte m_clickAction;
@@ -327,6 +325,7 @@ namespace OpenSim.Region.Framework.Scenes
 
         protected SceneObjectGroup m_parentGroup;
         protected byte[] m_particleSystem = Utils.EmptyBytes;
+        protected double m_particleSystemExpire = -1;
         protected ulong m_regionHandle;
         protected Quaternion m_rotationOffset = Quaternion.Identity;
         protected PrimitiveBaseShape m_shape;
@@ -434,7 +433,7 @@ namespace OpenSim.Region.Framework.Scenes
             AngularVelocity = Vector3.Zero;
             Acceleration = Vector3.Zero;
             APIDActive = false;
-            Flags = 0;
+            m_flags = 0;
             CreateSelected = false;
             TrimPermissions();
             AggregateInnerPerms();
@@ -495,6 +494,7 @@ namespace OpenSim.Region.Framework.Scenes
         private uint _everyoneMask = (uint)PermissionMask.None;
         private uint _nextOwnerMask = (uint)(PermissionMask.Move | PermissionMask.Transfer);
         private PrimFlags m_flags = PrimFlags.None;
+        private PrimFlags m_localFlags = PrimFlags.None;
         private DateTime m_expires;
         private DateTime m_rezzed;
         private bool m_createSelected = false;
@@ -736,7 +736,15 @@ namespace OpenSim.Region.Framework.Scenes
 
         public Byte[] ParticleSystem
         {
-            get { return m_particleSystem; }
+            get
+            {
+                if(m_particleSystemExpire > 0 && Util.GetTimeStamp() > m_particleSystemExpire)
+                {
+                    m_particleSystemExpire = -1;
+                    m_particleSystem = new byte[0];
+                }
+                return m_particleSystem;
+            }
             set { m_particleSystem = value; }
         }
 
@@ -774,9 +782,9 @@ namespace OpenSim.Region.Framework.Scenes
             get
             {
                 // If this is a linkset, we don't want the physics engine mucking up our group position here.
-                PhysicsActor actor = PhysActor;
                 if (_parentID == 0)
                 {
+                    PhysicsActor actor = PhysActor;
                     if (actor != null)
                         m_groupPosition = actor.Position;
                     return m_groupPosition;
@@ -916,6 +924,7 @@ namespace OpenSim.Region.Framework.Scenes
             {
 //                StoreUndoState();
                 m_rotationOffset = value;
+                m_rotationOffset.Normalize();
 
                 PhysicsActor actor = PhysActor;
                 if (actor != null)
@@ -1421,7 +1430,7 @@ namespace OpenSim.Region.Framework.Scenes
             set
             {
                 //m_log.DebugFormat("[SOP]: Setting flags for {0} {1} to {2}", UUID, Name, value);
-                m_flags = value;
+                m_flags = value & ~(PrimFlags.Touch | PrimFlags.Money | PrimFlags.AllowInventoryDrop);
             }
         }
 
@@ -1693,7 +1702,7 @@ namespace OpenSim.Region.Framework.Scenes
                 else
                     cost = 0.1f;
 
-                if ((Flags & PrimFlags.Physics) != 0)
+                if ((m_flags & PrimFlags.Physics) != 0)
                     cost *= (1.0f + 0.01333f * Scale.LengthSquared()); // 0.01333 == 0.04/3
                 return cost;
             }
@@ -1719,7 +1728,7 @@ namespace OpenSim.Region.Framework.Scenes
             get
             {
                 // ignoring scripts. Don't like considering them for this
-                if((Flags & PrimFlags.Physics) != 0)
+                if((m_flags & PrimFlags.Physics) != 0)
                     return 1.0f;
 
                 return 0.5f;
@@ -1763,7 +1772,7 @@ namespace OpenSim.Region.Framework.Scenes
                     {
                         if(oldv == (byte)PhysShapeType.none)
                         {
-                            ApplyPhysics((uint)Flags, VolumeDetectActive, false);
+                            ApplyPhysics((uint)m_flags, VolumeDetectActive, false);
                             UpdatePhysicsSubscribedEvents();
                         }
                     }
@@ -1941,8 +1950,12 @@ namespace OpenSim.Region.Framework.Scenes
             // m_log.Debug("Aprev: " + prevflag.ToString() + " curr: " + Flags.ToString());
         }
 
-        public void AddNewParticleSystem(Primitive.ParticleSystem pSystem)
+        public void AddNewParticleSystem(Primitive.ParticleSystem pSystem, bool expire)
         {
+            if(expire && pSystem.MaxAge > 0.0001)
+                m_particleSystemExpire = Util.GetTimeStamp() + pSystem.MaxAge + 0.1;
+            else
+                m_particleSystemExpire = -1;
             m_particleSystem = pSystem.GetBytes();
         }
 
@@ -2173,7 +2186,7 @@ namespace OpenSim.Region.Framework.Scenes
             dupe.Velocity = Velocity;
             dupe.Acceleration = Acceleration;
             dupe.AngularVelocity = AngularVelocity;
-            dupe.Flags = Flags;
+            dupe.m_flags = m_flags;
 
             dupe.OwnershipCost = OwnershipCost;
             dupe.ObjectSaleType = ObjectSaleType;
@@ -2226,7 +2239,7 @@ namespace OpenSim.Region.Framework.Scenes
 
             if (userExposed)
             {
-                bool UsePhysics = ((dupe.Flags & PrimFlags.Physics) != 0);
+                bool UsePhysics = ((dupe.m_flags & PrimFlags.Physics) != 0);
                 dupe.DoPhysicsPropertyUpdate(UsePhysics, true);
             }
 
@@ -2414,7 +2427,7 @@ namespace OpenSim.Region.Framework.Scenes
                         }
                     }
 
-                    bool phan = ((Flags & PrimFlags.Phantom) != 0);
+                    bool phan = ((m_flags & PrimFlags.Phantom) != 0);
                     if (pa.Phantom != phan)
                         pa.Phantom = phan;
 
@@ -2447,7 +2460,7 @@ namespace OpenSim.Region.Framework.Scenes
             SceneObjectPart part = SceneObjectSerializer.Xml2ToSOP(xmlReader);
 
             // for tempOnRez objects, we have to fix the Expire date.
-            if ((part.Flags & PrimFlags.TemporaryOnRez) != 0)
+            if ((part.m_flags & PrimFlags.TemporaryOnRez) != 0)
                 part.ResetExpire();
 
             return part;
@@ -2503,7 +2516,7 @@ namespace OpenSim.Region.Framework.Scenes
 
         public uint GetEffectiveObjectFlags()
         {
-            uint eff = (uint)Flags | (uint)LocalFlags;
+            uint eff = (uint)(m_flags | m_localFlags);
             if(m_inventory == null || m_inventory.Count == 0)
                 eff |= (uint)PrimFlags.InventoryEmpty;
             return eff;
@@ -3042,10 +3055,10 @@ namespace OpenSim.Region.Framework.Scenes
         public void RemFlag(PrimFlags flag)
         {
             // PrimFlags prevflag = Flags;
-            if ((Flags & flag) != 0)
+            if ((m_flags & flag) != 0)
             {
                 //m_log.Debug("Removing flag: " + ((PrimFlags)flag).ToString());
-                Flags &= ~flag;
+                m_flags &= ~flag;
             }
             //m_log.Debug("prev: " + prevflag.ToString() + " curr: " + Flags.ToString());
             //ScheduleFullUpdate();
@@ -4087,7 +4100,6 @@ namespace OpenSim.Region.Framework.Scenes
             else
             {
                 osUTF8Text = new osUTF8(text, 254);
-
                 if (ParentGroup != null && !osUTF8Text.Equals(old))
                 {
                     ParentGroup.HasGroupChanged = true;
@@ -4783,9 +4795,9 @@ namespace OpenSim.Region.Framework.Scenes
         /// <param name="SetVD"></param>
         public void UpdatePrimFlags(bool UsePhysics, bool SetTemporary, bool SetPhantom, bool SetVD, bool building)
         {
-            bool wasUsingPhysics = ((Flags & PrimFlags.Physics) != 0);
-            bool wasTemporary = ((Flags & PrimFlags.TemporaryOnRez) != 0);
-            bool wasPhantom = ((Flags & PrimFlags.Phantom) != 0);
+            bool wasUsingPhysics = ((m_flags & PrimFlags.Physics) != 0);
+            bool wasTemporary = ((m_flags & PrimFlags.TemporaryOnRez) != 0);
+            bool wasPhantom = ((m_flags & PrimFlags.Phantom) != 0);
             bool wasVD = VolumeDetectActive;
 
             if ((UsePhysics == wasUsingPhysics) && (wasTemporary == SetTemporary) && (wasPhantom == SetPhantom) && (SetVD == wasVD))
@@ -5276,7 +5288,7 @@ namespace OpenSim.Region.Framework.Scenes
 
             pa.OnCollisionUpdate -= PhysicsCollision;
 
-            bool hassound = (!VolumeDetectActive && CollisionSoundType >= 0 && ((Flags & PrimFlags.Physics) != 0));
+            bool hassound = (!VolumeDetectActive && CollisionSoundType >= 0 && ((m_flags & PrimFlags.Physics) != 0));
 
             scriptEvents CombinedEvents = AggregatedScriptEvents;
 
@@ -5287,7 +5299,7 @@ namespace OpenSim.Region.Framework.Scenes
             // submit to this part case
             if (VolumeDetectActive)
                 CombinedEvents &= PhyscicsVolumeDtcSubsEvents;
-            else if ((Flags & PrimFlags.Phantom) != 0)
+            else if ((m_flags & PrimFlags.Phantom) != 0)
                 CombinedEvents &= PhyscicsPhantonSubsEvents;
             else
                 CombinedEvents &= PhysicsNeededSubsEvents;
@@ -5321,12 +5333,7 @@ namespace OpenSim.Region.Framework.Scenes
             }
 
             uint objectflagupdate = 0;
-
-            if (
-                ((AggregatedScriptEvents & scriptEvents.touch) != 0) ||
-                ((AggregatedScriptEvents & scriptEvents.touch_end) != 0) ||
-                ((AggregatedScriptEvents & scriptEvents.touch_start) != 0)
-                )
+            if ((AggregatedScriptEvents & scriptEvents.anytouch) != 0 )
             {
                 objectflagupdate |= (uint) PrimFlags.Touch;
             }
@@ -5341,7 +5348,7 @@ namespace OpenSim.Region.Framework.Scenes
                 objectflagupdate |= (uint) PrimFlags.AllowInventoryDrop;
             }
 
-            LocalFlags = (PrimFlags)objectflagupdate;
+            m_localFlags = (PrimFlags)objectflagupdate;
 
             if (ParentGroup != null && ParentGroup.RootPart == this)
             {

+ 1 - 5
OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs

@@ -200,11 +200,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
 
         private bool hasTouchEvents(SceneObjectPart part)
         {
-            if ((part.ScriptEvents & scriptEvents.touch) != 0 ||
-                (part.ScriptEvents & scriptEvents.touch_start) != 0 ||
-                (part.ScriptEvents & scriptEvents.touch_end) != 0)
-                return true;
-            return false;
+           return (part.ScriptEvents & scriptEvents.anytouch) != 0;
         }
 
         public void InstantMessage(UUID target, string message)

+ 32 - 37
OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs

@@ -185,21 +185,23 @@ namespace OpenSim.Region.OptionalModules.World.NPC
                 return UUID.Zero;
             }
 
-            npcAvatar.CircuitCode = (uint)Util.RandomClass.Next(0,
-                    int.MaxValue);
+            agentID = npcAvatar.AgentId;
+            uint circuit = (uint)Util.RandomClass.Next(0, int.MaxValue);
+            npcAvatar.CircuitCode = circuit;
 
-//            m_log.DebugFormat(
-//                "[NPC MODULE]: Creating NPC {0} {1} {2}, owner={3}, senseAsAgent={4} at {5} in {6}",
-//                firstname, lastname, npcAvatar.AgentId, owner, senseAsAgent, position, scene.RegionInfo.RegionName);
+            //m_log.DebugFormat(
+            //    "[NPC MODULE]: Creating NPC {0} {1} {2}, owner={3}, senseAsAgent={4} at {5} in {6}",
+            //    firstname, lastname, npcAvatar.AgentId, owner, senseAsAgent, position, scene.RegionInfo.RegionName);
 
-            AgentCircuitData acd = new AgentCircuitData();
-            acd.AgentID = npcAvatar.AgentId;
-            acd.firstname = firstname;
-            acd.lastname = lastname;
-            acd.ServiceURLs = new Dictionary<string, object>();
-
-            AvatarAppearance npcAppearance = new AvatarAppearance(appearance, true);
-            acd.Appearance = npcAppearance;
+            AgentCircuitData acd = new AgentCircuitData()
+            {
+                circuitcode = circuit,
+                AgentID = agentID,
+                firstname = firstname,
+                lastname = lastname,
+                ServiceURLs = new Dictionary<string, object>(),
+                Appearance = new AvatarAppearance(appearance, true)
+            };
 
             /*
             for (int i = 0;
@@ -212,32 +214,25 @@ namespace OpenSim.Region.OptionalModules.World.NPC
             }
             */
 
-//            ManualResetEvent ev = new ManualResetEvent(false);
+            lock (m_avatars)
+            {
+                scene.AuthenticateHandler.AddNewCircuit(acd);
+                scene.AddNewAgent(npcAvatar, PresenceType.Npc);
 
-//            Util.FireAndForget(delegate(object x) {
-                lock (m_avatars)
+                if (scene.TryGetScenePresence(agentID, out ScenePresence sp))
                 {
-                    scene.AuthenticateHandler.AddNewCircuit(npcAvatar.CircuitCode, acd);
-                    scene.AddNewAgent(npcAvatar, PresenceType.Npc);
-
-                    if (scene.TryGetScenePresence(npcAvatar.AgentId, out ScenePresence sp))
-                    {
-                        npcAvatar.Born = born;
-                        npcAvatar.ActiveGroupId = groupID;
-                        sp.CompleteMovement(npcAvatar, false);
-                        sp.Grouptitle = groupTitle;
-                        m_avatars.Add(npcAvatar.AgentId, npcAvatar);
-//                        m_log.DebugFormat("[NPC MODULE]: Created NPC {0} {1}", npcAvatar.AgentId, sp.Name);
-                    }
+                    npcAvatar.Born = born;
+                    npcAvatar.ActiveGroupId = groupID;
+                    sp.CompleteMovement(npcAvatar, false);
+                    sp.Grouptitle = groupTitle;
+                    m_avatars.Add(agentID, npcAvatar);
+                    //m_log.DebugFormat("[NPC MODULE]: Created NPC {0} {1}", npcAvatar.AgentId, sp.Name);
                 }
-//                ev.Set();
-//            });
-
-//            ev.WaitOne();
+            }
 
 //            m_log.DebugFormat("[NPC MODULE]: Created NPC with id {0}", npcAvatar.AgentId);
 
-            return npcAvatar.AgentId;
+            return agentID;
         }
 
         public bool MoveToTarget(UUID agentID, Scene scene, Vector3 pos,
@@ -253,10 +248,10 @@ namespace OpenSim.Region.OptionalModules.World.NPC
                         if (sp.IsSatOnObject || sp.SitGround)
                             return false;
 
-//                        m_log.DebugFormat(
-//                                "[NPC MODULE]: Moving {0} to {1} in {2}, noFly {3}, landAtTarget {4}",
-//                                sp.Name, pos, scene.RegionInfo.RegionName,
-//                                noFly, landAtTarget);
+                    //m_log.DebugFormat(
+                    //        "[NPC MODULE]: Moving {0} to {1} in {2}, noFly {3}, landAtTarget {4}",
+                    //        sp.Name, pos, scene.RegionInfo.RegionName,
+                    //        noFly, landAtTarget);
 
                         sp.MoveToTarget(pos, noFly, landAtTarget, running);
 

+ 39 - 35
OpenSim/Region/PhysicsModules/ubOde/ODEMeshWorker.cs

@@ -4,7 +4,6 @@
 
 using System;
 using System.Collections.Concurrent;
-using System.Threading;
 using OpenSim.Framework;
 using OpenSim.Region.PhysicsModules.SharedBase;
 using log4net;
@@ -65,19 +64,20 @@ namespace OpenSim.Region.PhysicsModule.ubOde
 
     public class ODEMeshWorker
     {
-        private ILog m_log;
-        private ODEScene m_scene;
-        private IMesher m_mesher;
+        private readonly ILog m_log;
+        private readonly ODEScene m_scene;
+        private readonly IMesher m_mesher;
 
         public bool meshSculptedPrim = true;
         public float meshSculptLOD = 32;
         public float MeshSculptphysicalLOD = 32;
         public float MinSizeToMeshmerize = 0.1f;
 
-        private BlockingCollection<ODEPhysRepData> workQueue = new BlockingCollection<ODEPhysRepData>();
+        //private static ObjectJobEngine<ODEPhysRepData> workQueue;
+        private ObjectJobEngine workQueue;
         private bool m_running;
 
-        private Thread m_thread;
+        private readonly object m_threadLock = new object();
 
         public ODEMeshWorker(ODEScene pScene, ILog pLog, IMesher pMesher, IConfig pConfig)
         {
@@ -93,38 +93,41 @@ namespace OpenSim.Region.PhysicsModule.ubOde
                 MeshSculptphysicalLOD = pConfig.GetFloat("mesh_physical_lod", MeshSculptphysicalLOD);
             }
             m_running = true;
-            m_thread = new Thread(DoWork);
-            m_thread.Name = "OdeMeshWorker";
-            m_thread.Start();
+            Util.FireAndForget(DoCacheExpire, null, "OdeCacheExpire", false);
+            lock(m_threadLock)
+            {
+                if(workQueue == null)
+                    workQueue = new ObjectJobEngine(DoWork, "OdeMeshWorker");
+            }
         }
 
-        private void DoWork()
+        private void DoCacheExpire(object o)
         {
             m_mesher.ExpireFileCache();
-            ODEPhysRepData nextRep;
+        }
 
-            while(m_running)
+        private void Enqueue(ODEPhysRepData rep)
+        {
+            workQueue.Enqueue(rep);
+        }
+
+        private void DoWork(object rep)
+        {
+            ODEPhysRepData nextRep = rep as ODEPhysRepData;
+            if (m_running && nextRep != null && m_scene.haveActor(nextRep.actor))
             {
-                workQueue.TryTake(out nextRep, -1);
-                if(!m_running)
-                    return;
-                if (nextRep == null)
-                    continue;
-                if (m_scene.haveActor(nextRep.actor))
+                switch (nextRep.comand)
                 {
-                    switch (nextRep.comand)
-                    {
-                        case meshWorkerCmnds.changefull:
-                        case meshWorkerCmnds.changeshapetype:
-                        case meshWorkerCmnds.changesize:
-                            GetMesh(nextRep);
-                            if (CreateActorPhysRep(nextRep) && m_scene.haveActor(nextRep.actor))
-                                m_scene.AddChange(nextRep.actor, changes.PhysRepData, nextRep);
-                            break;
-                        case meshWorkerCmnds.getmesh:
-                            DoRepDataGetMesh(nextRep);
-                            break;
-                    }
+                    case meshWorkerCmnds.changefull:
+                    case meshWorkerCmnds.changeshapetype:
+                    case meshWorkerCmnds.changesize:
+                        GetMesh(nextRep);
+                        if (CreateActorPhysRep(nextRep) && m_scene.haveActor(nextRep.actor))
+                            m_scene.AddChange(nextRep.actor, changes.PhysRepData, nextRep);
+                        break;
+                    case meshWorkerCmnds.getmesh:
+                        DoRepDataGetMesh(nextRep);
+                        break;
                 }
             }
         }
@@ -133,8 +136,9 @@ namespace OpenSim.Region.PhysicsModule.ubOde
         {
             try
             {
-                m_thread.Abort();
- //               workQueue.Dispose();
+                m_running = false;
+                workQueue.Dispose();
+                workQueue = null;
             }
             catch
             {
@@ -191,7 +195,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde
                 repData.meshState = MeshState.loadingAsset;
 
                 repData.comand = meshWorkerCmnds.getmesh;
-                workQueue.Add(repData);
+                Enqueue(repData);
             }
         }
 
@@ -237,7 +241,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde
                 if (needsMeshing(repData)) // no need for pbs now?
                 {
                     repData.comand = meshWorkerCmnds.changefull;
-                    workQueue.Add(repData);
+                    Enqueue(repData);
                 }
             }
             else

+ 0 - 5
OpenSim/Region/PhysicsModules/ubOde/ODEScene.cs

@@ -1118,11 +1118,6 @@ namespace OpenSim.Region.PhysicsModule.ubOde
             get { return m_timeDilation; }
         }
 
-        public override bool SupportsNINJAJoints
-        {
-            get { return false; }
-        }
-
         #region Add/Remove Entities
 
         public override PhysicsActor AddAvatar(string avName, Vector3 position, Vector3 velocity, Vector3 size, bool isFlying)

+ 7 - 3
OpenSim/Region/PhysicsModules/ubOdeMeshing/Meshmerizer.cs

@@ -1408,24 +1408,28 @@ namespace OpenSim.Region.PhysicsModule.ubODEMeshing
             }
         }
 
+        private static DateTime lastExpireTime = DateTime.MinValue;
         public void ExpireFileCache()
         {
             if (!doCacheExpire)
                 return;
 
-            string controlfile = System.IO.Path.Combine(cachePath, cacheControlFilename);
-
             lock (diskLock)
             {
                 try
                 {
+                    DateTime now = DateTime.UtcNow;
+                    if(now.Subtract(lastExpireTime).TotalMinutes < 10.0)
+                        return;
+                    lastExpireTime = now;
+                    string controlfile = System.IO.Path.Combine(cachePath, cacheControlFilename);
                     if (File.Exists(controlfile))
                     {
                         int ndeleted = 0;
                         int totalfiles = 0;
                         int ndirs = 0;
                         DateTime OlderTime = File.GetLastAccessTimeUtc(controlfile) - CacheExpire;
-                        File.SetLastAccessTimeUtc(controlfile, DateTime.UtcNow);
+                        File.SetLastAccessTimeUtc(controlfile, now);
 
                         foreach (string dir in Directory.GetDirectories(cachePath))
                         {

+ 1 - 1
OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs

@@ -201,7 +201,7 @@ namespace OpenSim.Region.ScriptEngine.Interfaces
         /// Process the next event queued for this script instance.
         /// </summary>
         /// <returns></returns>
-        object EventProcessor();
+        void EventProcessor();
 
         int EventTime();
 

+ 23 - 24
OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs

@@ -36,7 +36,7 @@ using OpenSim.Region.Framework.Interfaces;
 using OpenSim.Region.ScriptEngine.Interfaces;
 using OpenSim.Region.ScriptEngine.Shared;
 using OpenSim.Region.ScriptEngine.Shared.Api.Plugins;
-using Timer=OpenSim.Region.ScriptEngine.Shared.Api.Plugins.Timer;
+using ScriptTimer=OpenSim.Region.ScriptEngine.Shared.Api.Plugins.ScriptTimer;
 using System.Reflection;
 using log4net;
 
@@ -68,8 +68,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
 
         private static Dictionary<IScriptEngine, Dataserver> m_Dataserver =
                 new Dictionary<IScriptEngine, Dataserver>();
-        private static Dictionary<IScriptEngine, Timer> m_Timer =
-                new Dictionary<IScriptEngine, Timer>();
+        private static Dictionary<IScriptEngine, ScriptTimer> m_ScriptTimer =
+                new Dictionary<IScriptEngine, ScriptTimer>();
         private static Dictionary<IScriptEngine, Listener> m_Listener =
                 new Dictionary<IScriptEngine, Listener>();
         private static Dictionary<IScriptEngine, HttpRequest> m_HttpRequest =
@@ -88,12 +88,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
             }
         }
 
-        public Timer TimerPlugin
+        public ScriptTimer TimerPlugin
         {
             get
             {
                 lock (staticLock)
-                    return m_Timer[m_ScriptEngine];
+                    return m_ScriptTimer[m_ScriptEngine];
             }
         }
 
@@ -161,8 +161,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
                 // Create instances of all plugins
                 if (!m_Dataserver.ContainsKey(m_ScriptEngine))
                     m_Dataserver[m_ScriptEngine] = new Dataserver(this);
-                if (!m_Timer.ContainsKey(m_ScriptEngine))
-                    m_Timer[m_ScriptEngine] = new Timer(this);
+                if (!m_ScriptTimer.ContainsKey(m_ScriptEngine))
+                    m_ScriptTimer[m_ScriptEngine] = new ScriptTimer(this);
                 if (!m_HttpRequest.ContainsKey(m_ScriptEngine))
                     m_HttpRequest[m_ScriptEngine] = new HttpRequest(this);
                 if (!m_Listener.ContainsKey(m_ScriptEngine))
@@ -247,20 +247,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
         {
             lock (staticLock)
             {
-                // Check HttpRequests
-                try { m_HttpRequest[m_ScriptEngines[0]].CheckHttpRequests(); } catch {}
-
                 // Check XMLRPCRequests
                 try { m_XmlRequest[m_ScriptEngines[0]].CheckXMLRPCRequests(); } catch {}
 
                 foreach (IScriptEngine s in m_ScriptEngines)
                 {
+                    // Check HttpRequests
+                    try { m_HttpRequest[s].CheckHttpRequests(); } catch { }
+
                     // Check Listeners
                     try { m_Listener[s].CheckListeners(); } catch {}
-                    
 
-                    // Check timers
-                    try { m_Timer[s].CheckTimerEvents(); } catch {}
+                    // Check ScriptTimers
+                    try { m_ScriptTimer[s].CheckTimerEvents(); } catch {}
 
                     // Check Sensors
                     try { m_SensorRepeat[s].CheckSenseRepeaterEvents(); } catch {}
@@ -286,8 +285,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
                 // Remove dataserver events
                 m_Dataserver[engine].RemoveEvents(localID, itemID);
 
-                // Remove from: Timers
-                m_Timer[engine].UnSetTimerEvents(localID, itemID);
+                // Remove from: ScriptTimers
+                m_ScriptTimer[engine].UnSetTimerEvents(localID, itemID);
 
                 if(engine.World != null)
                 {
@@ -367,16 +366,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
         }
 
         /// <summary>
-        /// Get the timer plugin for this script engine.
+        /// Get the ScriptTimer plugin for this script engine.
         /// </summary>
         /// <param name="engine"></param>
         /// <returns></returns>
-        public static Timer GetTimerPlugin(IScriptEngine engine)
+        public static ScriptTimer GetTimerPlugin(IScriptEngine engine)
         {
             lock (staticLock)
             {
-                if (m_Timer.ContainsKey(engine))
-                    return m_Timer[engine];
+                if (m_ScriptTimer.ContainsKey(engine))
+                    return m_ScriptTimer[engine];
                 else
                     return null;
             }
@@ -412,12 +411,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
                     data.AddRange(listeners);
                 }
 
-                Object[] timers=m_Timer[engine].GetSerializationData(itemID);
-                if (timers.Length > 0)
+                Object[] ScriptTimers=m_ScriptTimer[engine].GetSerializationData(itemID);
+                if (ScriptTimers.Length > 0)
                 {
                     data.Add("timer");
-                    data.Add(timers.Length);
-                    data.AddRange(timers);
+                    data.Add(ScriptTimers.Length);
+                    data.AddRange(ScriptTimers);
                 }
 
                 Object[] sensors = m_SensorRepeat[engine].GetSerializationData(itemID);
@@ -460,7 +459,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
                                                         hostID, item);
                             break;
                         case "timer":
-                            m_Timer[engine].CreateFromData(localID, itemID,
+                            m_ScriptTimer[engine].CreateFromData(localID, itemID,
                                                         hostID, item);
                             break;
                         case "sensor":

+ 31 - 30
OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs

@@ -7493,7 +7493,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
             SetParticleSystem(m_host, rules, "llParticleSystem");
         }
 
-        private void SetParticleSystem(SceneObjectPart part, LSL_List rules, string originFunc)
+        public void SetParticleSystem(SceneObjectPart part, LSL_List rules, string originFunc, bool expire = false)
         {
             if (rules.Length == 0)
             {
@@ -7522,7 +7522,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
                     }
                     switch (psystype)
                     {
-                        case (int)ScriptBaseClass.PSYS_PART_FLAGS:
+                        case ScriptBaseClass.PSYS_PART_FLAGS:
                             try
                             {
                                 prules.PartDataFlags = (Primitive.ParticleSystem.ParticleDataFlags)(uint)rules.GetLSLIntegerItem(i + 1);
@@ -7534,7 +7534,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
                             }
                             break;
 
-                        case (int)ScriptBaseClass.PSYS_PART_START_COLOR:
+                        case ScriptBaseClass.PSYS_PART_START_COLOR:
                             try
                             {
                                 tempv = rules.GetVector3Item(i + 1);
@@ -7549,7 +7549,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
                             prules.PartStartColor.B = (float)tempv.z;
                             break;
 
-                        case (int)ScriptBaseClass.PSYS_PART_START_ALPHA:
+                        case ScriptBaseClass.PSYS_PART_START_ALPHA:
                             try
                             {
                                 tempf = (float)rules.GetLSLFloatItem(i + 1);
@@ -7562,7 +7562,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
                             prules.PartStartColor.A = tempf;
                             break;
 
-                        case (int)ScriptBaseClass.PSYS_PART_END_COLOR:
+                        case ScriptBaseClass.PSYS_PART_END_COLOR:
                             try
                             {
                                 tempv = rules.GetVector3Item(i + 1);
@@ -7577,7 +7577,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
                             prules.PartEndColor.B = (float)tempv.z;
                             break;
 
-                        case (int)ScriptBaseClass.PSYS_PART_END_ALPHA:
+                        case ScriptBaseClass.PSYS_PART_END_ALPHA:
                             try
                             {
                                 tempf = (float)rules.GetLSLFloatItem(i + 1);
@@ -7590,7 +7590,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
                             prules.PartEndColor.A = tempf;
                             break;
 
-                        case (int)ScriptBaseClass.PSYS_PART_START_SCALE:
+                        case ScriptBaseClass.PSYS_PART_START_SCALE:
                             try
                             {
                                 tempv = rules.GetVector3Item(i + 1);
@@ -7604,7 +7604,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
                             prules.PartStartScaleY = validParticleScale((float)tempv.y);
                             break;
 
-                        case (int)ScriptBaseClass.PSYS_PART_END_SCALE:
+                        case ScriptBaseClass.PSYS_PART_END_SCALE:
                             try
                             {
                                 tempv = rules.GetVector3Item(i + 1);
@@ -7618,7 +7618,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
                             prules.PartEndScaleY = validParticleScale((float)tempv.y);
                             break;
 
-                        case (int)ScriptBaseClass.PSYS_PART_MAX_AGE:
+                        case ScriptBaseClass.PSYS_PART_MAX_AGE:
                             try
                             {
                                 tempf = (float)rules.GetLSLFloatItem(i + 1);
@@ -7631,7 +7631,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
                             prules.PartMaxAge = tempf;
                             break;
 
-                        case (int)ScriptBaseClass.PSYS_SRC_ACCEL:
+                        case ScriptBaseClass.PSYS_SRC_ACCEL:
                             try
                             {
                                 tempv = rules.GetVector3Item(i + 1);
@@ -7646,7 +7646,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
                             prules.PartAcceleration.Z = (float)tempv.z;
                             break;
 
-                        case (int)ScriptBaseClass.PSYS_SRC_PATTERN:
+                        case ScriptBaseClass.PSYS_SRC_PATTERN:
                             try
                             {
                                 tmpi = (int)rules.GetLSLIntegerItem(i + 1);
@@ -7663,7 +7663,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
                         // PSYS_SRC_OUTERANGLE and PSYS_SRC_ANGLE_END also use the same variable. The
                         // client tells the difference between the two by looking at the 0x02 bit in
                         // the PartFlags variable.
-                        case (int)ScriptBaseClass.PSYS_SRC_INNERANGLE:
+                        case ScriptBaseClass.PSYS_SRC_INNERANGLE:
                             try
                             {
                                 tempf = (float)rules.GetLSLFloatItem(i + 1);
@@ -7677,7 +7677,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
                             prules.PartFlags &= 0xFFFFFFFD; // Make sure new angle format is off.
                             break;
 
-                        case (int)ScriptBaseClass.PSYS_SRC_OUTERANGLE:
+                        case ScriptBaseClass.PSYS_SRC_OUTERANGLE:
                             try
                             {
                                 tempf = (float)rules.GetLSLFloatItem(i + 1);
@@ -7691,7 +7691,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
                             prules.PartFlags &= 0xFFFFFFFD; // Make sure new angle format is off.
                             break;
 
-                        case (int)ScriptBaseClass.PSYS_PART_BLEND_FUNC_SOURCE:
+                        case ScriptBaseClass.PSYS_PART_BLEND_FUNC_SOURCE:
                             try
                             {
                                 tmpi = (int)rules.GetLSLIntegerItem(i + 1);
@@ -7704,7 +7704,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
                             prules.BlendFuncSource = (byte)tmpi;
                             break;
 
-                        case (int)ScriptBaseClass.PSYS_PART_BLEND_FUNC_DEST:
+                        case ScriptBaseClass.PSYS_PART_BLEND_FUNC_DEST:
                             try
                             {
                                 tmpi = (int)rules.GetLSLIntegerItem(i + 1);
@@ -7717,7 +7717,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
                             prules.BlendFuncDest = (byte)tmpi;
                             break;
 
-                        case (int)ScriptBaseClass.PSYS_PART_START_GLOW:
+                        case ScriptBaseClass.PSYS_PART_START_GLOW:
                             try
                             {
                                 tempf = (float)rules.GetLSLFloatItem(i + 1);
@@ -7730,7 +7730,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
                             prules.PartStartGlow = (float)tempf;
                             break;
 
-                        case (int)ScriptBaseClass.PSYS_PART_END_GLOW:
+                        case ScriptBaseClass.PSYS_PART_END_GLOW:
                             try
                             {
                                 tempf = (float)rules.GetLSLFloatItem(i + 1);
@@ -7743,7 +7743,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
                             prules.PartEndGlow = (float)tempf;
                             break;
 
-                        case (int)ScriptBaseClass.PSYS_SRC_TEXTURE:
+                        case ScriptBaseClass.PSYS_SRC_TEXTURE:
                             try
                             {
                                 prules.Texture = ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, rules.GetLSLStringItem(i + 1));
@@ -7755,7 +7755,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
                             }
                             break;
 
-                        case (int)ScriptBaseClass.PSYS_SRC_BURST_RATE:
+                        case ScriptBaseClass.PSYS_SRC_BURST_RATE:
                             try
                             {
                                 tempf = (float)rules.GetLSLFloatItem(i + 1);
@@ -7768,7 +7768,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
                             prules.BurstRate = (float)tempf;
                             break;
 
-                        case (int)ScriptBaseClass.PSYS_SRC_BURST_PART_COUNT:
+                        case ScriptBaseClass.PSYS_SRC_BURST_PART_COUNT:
                             try
                             {
                                 prules.BurstPartCount = (byte)(int)rules.GetLSLIntegerItem(i + 1);
@@ -7780,7 +7780,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
                             }
                             break;
 
-                        case (int)ScriptBaseClass.PSYS_SRC_BURST_RADIUS:
+                        case ScriptBaseClass.PSYS_SRC_BURST_RADIUS:
                             try
                             {
                                 tempf = (float)rules.GetLSLFloatItem(i + 1);
@@ -7793,7 +7793,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
                             prules.BurstRadius = (float)tempf;
                             break;
 
-                        case (int)ScriptBaseClass.PSYS_SRC_BURST_SPEED_MIN:
+                        case ScriptBaseClass.PSYS_SRC_BURST_SPEED_MIN:
                             try
                             {
                                 tempf = (float)rules.GetLSLFloatItem(i + 1);
@@ -7806,7 +7806,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
                             prules.BurstSpeedMin = (float)tempf;
                             break;
 
-                        case (int)ScriptBaseClass.PSYS_SRC_BURST_SPEED_MAX:
+                        case ScriptBaseClass.PSYS_SRC_BURST_SPEED_MAX:
                             try
                             {
                                 tempf = (float)rules.GetLSLFloatItem(i + 1);
@@ -7819,7 +7819,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
                             prules.BurstSpeedMax = (float)tempf;
                             break;
 
-                        case (int)ScriptBaseClass.PSYS_SRC_MAX_AGE:
+                        case ScriptBaseClass.PSYS_SRC_MAX_AGE:
                             try
                             {
                                 tempf = (float)rules.GetLSLFloatItem(i + 1);
@@ -7832,7 +7832,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
                             prules.MaxAge = (float)tempf;
                             break;
 
-                        case (int)ScriptBaseClass.PSYS_SRC_TARGET_KEY:
+                        case ScriptBaseClass.PSYS_SRC_TARGET_KEY:
                             UUID key = UUID.Zero;
                             if (UUID.TryParse(rules.Data[i + 1].ToString(), out key))
                             {
@@ -7844,7 +7844,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
                             }
                             break;
 
-                        case (int)ScriptBaseClass.PSYS_SRC_OMEGA:
+                        case ScriptBaseClass.PSYS_SRC_OMEGA:
                             // AL: This is an assumption, since it is the only thing that would match.
                             try
                             {
@@ -7860,7 +7860,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
                             prules.AngularVelocity.Z = (float)tempv.z;
                             break;
 
-                        case (int)ScriptBaseClass.PSYS_SRC_ANGLE_BEGIN:
+                        case ScriptBaseClass.PSYS_SRC_ANGLE_BEGIN:
                             try
                             {
                                 tempf = (float)rules.GetLSLFloatItem(i + 1);
@@ -7874,7 +7874,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
                             prules.PartFlags |= 0x02; // Set new angle format.
                             break;
 
-                        case (int)ScriptBaseClass.PSYS_SRC_ANGLE_END:
+                        case ScriptBaseClass.PSYS_SRC_ANGLE_END:
                             try
                             {
                                 tempf = (float)rules.GetLSLFloatItem(i + 1);
@@ -7892,8 +7892,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
                 }
                 prules.CRC = 1;
 
-                part.AddNewParticleSystem(prules);
-                part.ParentGroup.HasGroupChanged = true;
+                part.AddNewParticleSystem(prules, expire);
+                if(!expire || prules.MaxAge != 0 || prules.MaxAge > 300)
+                    part.ParentGroup.HasGroupChanged = true;
             }
             part.SendFullUpdateToAllClients();
         }

+ 112 - 6
OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs

@@ -4268,6 +4268,34 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
             m_LSL_Api.DetachFromAvatar();
         }
 
+        private bool listObjToInt(object p, out int i)
+        {
+            try
+            {
+                if (p is LSL_Integer)
+                    i = (LSL_Integer)p;
+                else if (p is int)
+                    i = (int)p;
+                else if (p is uint)
+                    i = (int)(uint)p;
+                else if (p is string)
+                    return int.TryParse((string)p, out i);
+                else if (p is LSL_String)
+                    return int.TryParse((string)(LSL_String)p, out i);
+                else
+                {
+                    i = 0;
+                    return false;
+                }
+                return true;
+            }
+            catch
+            {
+                i = 0;
+                return false;
+            }
+        }
+
         public LSL_List osGetNumberOfAttachments(LSL_Key avatar, LSL_List attachmentPoints)
         {
             CheckThreatLevel(ThreatLevel.Moderate, "osGetNumberOfAttachments");
@@ -4278,12 +4306,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
             {
                 foreach (object point in attachmentPoints.Data)
                 {
-                    LSL_Integer ipoint = new LSL_Integer(
-                        (point is LSL_Integer || point is int || point is uint) ?
-                            (int)point :
-                            0
-                    );
-                    resp.Add(ipoint);
+                    listObjToInt(point, out int ipoint);
+                    resp.Add(new LSL_Integer(ipoint));
                     if (ipoint == 0)
                     {
                         // indicates zero attachments
@@ -6020,5 +6044,87 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
             m_envModule.WindlightRefresh(transition);
             return 1;
         }
+
+        public void osParticleSystem(LSL_List rules)
+        {
+            m_host.AddScriptLPS(1);
+
+            InitLSL();
+            if (m_LSL_Api != null)
+                m_LSL_Api.SetParticleSystem(m_host, rules, "osParticleSystem", true);
+        }
+
+        public void osLinkParticleSystem(LSL_Integer linknumber, LSL_List rules)
+        {
+            InitLSL();
+            if (m_LSL_Api != null)
+            {
+                List<SceneObjectPart> parts = m_LSL_Api.GetLinkParts(linknumber);
+
+                foreach (SceneObjectPart part in parts)
+                {
+                    m_LSL_Api.SetParticleSystem(part, rules, "osLinkParticleSystem", true);
+                }
+            }
+        }
+
+        public LSL_Integer osNpcLookAt(LSL_Key npckey, LSL_Integer ltype, LSL_Key objkey, LSL_Vector offset)
+        {
+            if (World.GetNumberOfClients() == 0)
+                return 0;
+
+            if (ltype < 0 || ltype > ScriptBaseClass.NPCLOOKAT_CLEAR)
+                return -1;
+
+            if (!UUID.TryParse(npckey, out UUID npc))
+                return -2;
+
+            ScenePresence npcSP = World.GetScenePresence(npc);
+            if((npcSP == null) || !npcSP.IsNPC)
+                return -3;
+
+            if (!UUID.TryParse(objkey, out UUID obj))
+                return -4;
+
+            if(obj != UUID.Zero)
+            {
+                ScenePresence objSP = World.GetScenePresence(obj);
+                if(objSP == null)
+                {
+                    SceneObjectPart objSOP = World.GetSceneObjectPart(obj);
+                    if(objSOP == null)
+                        return -5;
+                }
+            }
+
+            byte[] data = new byte[57];
+            npc.ToBytes(data, 0);
+            obj.ToBytes(data, 16);
+            Vector3d vd = new Vector3d(offset.x, offset.y, offset.z);
+            vd.ToBytes(data, 32);
+            data[56] = (byte)(int)ltype;
+
+            OpenMetaverse.Packets.ViewerEffectPacket.EffectBlock effect = new OpenMetaverse.Packets.ViewerEffectPacket.EffectBlock();
+            effect.AgentID = npc;
+            effect.Color = new byte[4];
+            effect.Duration = 0;
+            effect.ID = UUID.Random();
+            effect.Type = 14;
+            effect.TypeData = data;
+
+            OpenMetaverse.Packets.ViewerEffectPacket.EffectBlock[] effectblock = new OpenMetaverse.Packets.ViewerEffectPacket.EffectBlock[1];
+            effectblock[0] = effect;
+
+            World.ForEachScenePresence(
+             sp =>
+             {
+                if(!sp.IsNPC && !sp.IsDeleted)
+                {
+                    sp.ControllingClient.SendViewerEffect(effectblock);
+                }
+             });
+
+            return 0;
+        }
     }
 }

+ 9 - 27
OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/Dataserver.cs

@@ -26,20 +26,15 @@
  */
 
 using System;
-using System.Collections;
 using System.Collections.Generic;
-using System.Threading;
 using OpenMetaverse;
-using Amib.Threading;
-using OpenSim.Region.ScriptEngine.Shared;
-using OpenSim.Region.ScriptEngine.Shared.Api;
-using Action = System.Action;
+using OpenSim.Framework;
 
 namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
 {
     public class Dataserver
     {
-        private SmartThreadPool m_ThreadPool;
+        private ObjectJobEngine m_WorkPool;
 
         public AsyncCommandManager m_CmdManager;
 
@@ -57,17 +52,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
         public Dataserver(AsyncCommandManager CmdManager)
         {
             m_CmdManager = CmdManager;
-
-            STPStartInfo startInfo = new STPStartInfo();
-            startInfo.ThreadPoolName = "ScriptV";
-            startInfo.IdleTimeout = 1000;
-            startInfo.MaxWorkerThreads = 4;
-            startInfo.MinWorkerThreads = 0;
-            startInfo.ThreadPriority = ThreadPriority.Normal;
-            startInfo.StartSuspended = true;
-
-            m_ThreadPool = new SmartThreadPool(startInfo);
-            m_ThreadPool.Start();
+            m_WorkPool = new ObjectJobEngine(ProcessActions, "ScriptDataServer", 1000, 4);
         }
 
         private class DataserverRequest
@@ -150,7 +135,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
 
                 DataserverRequests[identifier] = ds;
                 if (action != null)
-                    m_ThreadPool.QueueWorkItem((WorkItemCallback)ProcessActions, identifier);
+                    m_WorkPool.Enqueue(identifier);
 
                 return ds.ID;
             }
@@ -176,28 +161,27 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
 
                 DataserverRequests[identifier] = ds;
                 if (action != null)
-                    m_ThreadPool.QueueWorkItem((WorkItemCallback)ProcessActions, identifier);
+                    m_WorkPool.Enqueue(identifier);
 
                 return ds.ID;
             }
         }
 
-
-        public object ProcessActions(object st)
+        public void ProcessActions(object st)
         {
             string id = st as string;
             if(string.IsNullOrEmpty(id))
-                return null;
+                return;
 
             DataserverRequest ds = null;
             lock (DataserverRequests)
             {
                 if (!DataserverRequests.TryGetValue(id, out ds))
-                    return null;
+                    return;
             }
 
             if (ds == null || ds.action == null)
-                return null;
+                return;
             try
             {
                 ds.action.Invoke(ds.handle);
@@ -210,8 +194,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
                 if (DataserverRequests.TryGetValue(id, out ds))
                     DataserverRequests.Remove(id);
             }
-
-            return null;
         }
 
         //legacy ?

+ 204 - 0
OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/ScriptTimer.cs

@@ -0,0 +1,204 @@
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of the OpenSimulator Project nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+using System;
+using System.Collections.Generic;
+using OpenMetaverse;
+
+namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
+{
+    public class ScriptTimer
+    {
+        public class TimerInfo
+        {
+            public uint localID;
+            public UUID itemID;
+            //public double interval;
+            public long interval;
+            //public DateTime next;
+            public long next;
+
+            public TimerInfo Clone()
+            {
+                return (TimerInfo)this.MemberwiseClone();
+            }
+        }
+
+        public AsyncCommandManager m_CmdManager;
+
+        public int TimersCount
+        {
+            get
+            {
+                lock (TimerListLock)
+                    return Timers.Count;
+            }
+        }
+
+        public ScriptTimer(AsyncCommandManager CmdManager)
+        {
+            m_CmdManager = CmdManager;
+        }
+
+        //
+        // TIMER
+        //
+        static private string MakeTimerKey(uint localID, UUID itemID)
+        {
+            return localID.ToString() + itemID.ToString();
+        }
+
+        private Dictionary<string,TimerInfo> Timers = new Dictionary<string,TimerInfo>();
+        private object TimerListLock = new object();
+
+        public void SetTimerEvent(uint m_localID, UUID m_itemID, double sec)
+        {
+            if (sec == 0) // Disabling timer
+            {
+                UnSetTimerEvents(m_localID, m_itemID);
+                return;
+            }
+
+            // Add to timer
+            TimerInfo ts = new TimerInfo();
+            ts.localID = m_localID;
+            ts.itemID = m_itemID;
+            ts.interval = Convert.ToInt64(sec * 10000000); // How many 100 nanoseconds (ticks) should we wait
+            //       2193386136332921 ticks
+            //       219338613 seconds
+
+            //ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval);
+            ts.next = DateTime.Now.Ticks + ts.interval;
+
+            string key = MakeTimerKey(m_localID, m_itemID);
+            lock (TimerListLock)
+            {
+                // Adds if timer doesn't exist, otherwise replaces with new timer
+                Timers[key] = ts;
+            }
+        }
+
+        public void UnSetTimerEvents(uint m_localID, UUID m_itemID)
+        {
+            // Remove from timer
+            string key = MakeTimerKey(m_localID, m_itemID);
+            lock (TimerListLock)
+            {
+                if (Timers.TryGetValue(key, out TimerInfo ts))
+                {
+                    m_CmdManager.m_ScriptEngine.CancelScriptEvent(ts.itemID, "timer");
+                    Timers.Remove(key);
+                }
+            }
+        }
+
+        public void CheckTimerEvents()
+        {
+            // Nothing to do here?
+            if (Timers.Count == 0)
+                return;
+
+            List<TimerInfo> tvals;
+            lock (TimerListLock)
+            {
+                // Go through all timers
+                tvals = new List<TimerInfo>(Timers.Values);
+            }
+
+            foreach (TimerInfo ts in tvals)
+            {
+                // Time has passed?
+                if (ts.next < DateTime.Now.Ticks)
+                {
+                    //m_log.Debug("Time has passed: Now: " + DateTime.Now.Ticks + ", Passed: " + ts.next);
+                    // Add it to queue
+                    m_CmdManager.m_ScriptEngine.PostScriptEvent(ts.itemID,
+                            new EventParams("timer", new Object[0],
+                            new DetectParams[0]));
+                    // set next interval
+
+                    //ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval);
+                    ts.next = DateTime.Now.Ticks + ts.interval;
+                }
+            }
+        }
+
+        public Object[] GetSerializationData(UUID itemID)
+        {
+            List<Object> data = new List<Object>();
+
+            lock (TimerListLock)
+            {
+                Dictionary<string, TimerInfo>.ValueCollection tvals = Timers.Values;
+                foreach (TimerInfo ts in tvals)
+                {
+                    if (ts.itemID == itemID)
+                    {
+                        data.Add(ts.interval);
+                        data.Add(ts.next-DateTime.Now.Ticks);
+                    }
+                }
+            }
+            return data.ToArray();
+        }
+
+        public void CreateFromData(uint localID, UUID itemID, UUID objectID,
+                                   Object[] data)
+        {
+            int idx = 0;
+
+            while (idx < data.Length)
+            {
+                TimerInfo ts = new TimerInfo();
+
+                ts.localID = localID;
+                ts.itemID = itemID;
+                ts.interval = (long)data[idx];
+                ts.next = DateTime.Now.Ticks + (long)data[idx+1];
+                idx += 2;
+
+                lock (TimerListLock)
+                {
+                    Timers.Add(MakeTimerKey(localID, itemID), ts);
+                }
+            }
+        }
+
+        public List<TimerInfo> GetTimersInfo()
+        {
+            List<TimerInfo> retList = new List<TimerInfo>();
+
+            lock (TimerListLock)
+            {
+                foreach (TimerInfo i in Timers.Values)
+                    retList.Add(i.Clone());
+            }
+
+            return retList;
+        }
+    }
+}

+ 8 - 3
OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs

@@ -576,15 +576,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
         vector osGetLinkStandTarget(LSL_Integer linkNumber);
         LSL_Integer osClearObjectAnimations();
 
-        LSL_Float osGetApparentTime();
+        LSL_Float  osGetApparentTime();
         LSL_String osGetApparentTimeString(LSL_Integer format24);
-        LSL_Float osGetApparentRegionTime();
+        LSL_Float  osGetApparentRegionTime();
         LSL_String osGetApparentRegionTimeString(LSL_Integer format24);
 
         LSL_Integer osReplaceAgentEnvironment(LSL_Key agentkey, LSL_Integer transition, LSL_String daycycle);
         LSL_Integer osReplaceParcelEnvironment(LSL_Integer transition, LSL_String daycycle);
         LSL_Integer osReplaceRegionEnvironment(LSL_Integer transition, LSL_String daycycle,
-           LSL_Float daylen, LSL_Float dayoffset, LSL_Float altitude1, LSL_Float altitude2, LSL_Float altitude3);
+          LSL_Float daylen, LSL_Float dayoffset, LSL_Float altitude1, LSL_Float altitude2, LSL_Float altitude3);
         LSL_Integer osResetEnvironment(LSL_Integer parcelOrRegion, LSL_Integer transition);
+
+        void osParticleSystem(LSL_List rules);
+        void osLinkParticleSystem(LSL_Integer linknumber, LSL_List rules);
+
+        LSL_Integer osNpcLookAt(LSL_Key npckey, LSL_Integer type, LSL_Key objkey, vector offset);
     }
 }

+ 27 - 13
OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs

@@ -35,7 +35,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
     public partial class ScriptBaseClass
     {
         // SCRIPTS CONSTANTS
-        public static readonly LSLInteger OS_APIVERSION = 16;
+        public static readonly LSLInteger OS_APIVERSION = 17;
 
         public static readonly LSLInteger TRUE = 1;
         public static readonly LSLInteger FALSE = 0;
@@ -73,19 +73,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
         public const int CONTROL_ML_LBUTTON = 1073741824;
 
         //Permissions
-        public const int PERMISSION_DEBIT = 2;
-        public const int PERMISSION_TAKE_CONTROLS = 4;
-        public const int PERMISSION_REMAP_CONTROLS = 8;
-        public const int PERMISSION_TRIGGER_ANIMATION = 16;
-        public const int PERMISSION_ATTACH = 32;
-        public const int PERMISSION_RELEASE_OWNERSHIP = 64;
-        public const int PERMISSION_CHANGE_LINKS = 128;
-        public const int PERMISSION_CHANGE_JOINTS = 256;
-        public const int PERMISSION_CHANGE_PERMISSIONS = 512;
-        public const int PERMISSION_TRACK_CAMERA = 1024;
-        public const int PERMISSION_CONTROL_CAMERA = 2048;
-        public const int PERMISSION_TELEPORT = 4096;
+        public const int PERMISSION_DEBIT = 0x02;
+        public const int PERMISSION_TAKE_CONTROLS = 0x04;
+        public const int PERMISSION_REMAP_CONTROLS = 0x08;
+        public const int PERMISSION_TRIGGER_ANIMATION = 0x010;
+        public const int PERMISSION_ATTACH = 0x20;
+        public const int PERMISSION_RELEASE_OWNERSHIP = 0x40;
+        public const int PERMISSION_CHANGE_LINKS = 0x80;
+        public const int PERMISSION_CHANGE_JOINTS = 0x100;
+        public const int PERMISSION_CHANGE_PERMISSIONS = 0x200;
+        public const int PERMISSION_TRACK_CAMERA = 0x400;
+        public const int PERMISSION_CONTROL_CAMERA = 0x800;
+        public const int PERMISSION_TELEPORT = 0x1000;
+        public const int PERMISSION_SILENT_ESTATE_MANAGEMENT = 0x4000;
         public const int PERMISSION_OVERRIDE_ANIMATIONS = 0x8000;
+        public const int PERMISSION_RETURN_OBJECTS = 0x10000;
 
         public const int AGENT_FLYING = 0x1;
         //ApiDesc The agent has attachments
@@ -975,5 +977,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
         // llTargetedEmail
         public const int TARGETED_EMAIL_ROOT_CREATOR = 1;
         public const int TARGETED_EMAIL_OBJECT_OWNER = 2;
+
+        public const int NPCLOOKAT_NONE = 0;
+        public const int NPCLOOKAT_IDLE = 1;
+        public const int NPCLOOKAT_LISTEN = 2;
+        public const int NPCLOOKAT_FREELOOK = 3;
+        public const int NPCLOOKAT_RESPOND = 4;
+        public const int NPCLOOKAT_HOVER = 5;
+        public const int NPCLOOKAT_CONVERSATION = 6;
+        public const int NPCLOOKAT_SELECT = 7;
+        public const int NPCLOOKAT_FOCUS = 8;
+        public const int NPCLOOKAT_MOUSELOOK = 9;
+        public const int NPCLOOKAT_CLEAR = 10;
     }
 }

+ 15 - 0
OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs

@@ -1533,5 +1533,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
         {
             return m_OSSL_Functions.osResetEnvironment(parcelOrRegion, transition);
         }
+
+        public void osParticleSystem(LSL_List rules)
+        {
+            m_OSSL_Functions.osParticleSystem(rules);
+        }
+
+        public void osLinkParticleSystem(LSL_Integer linknumber, LSL_List rules)
+        {
+            m_OSSL_Functions.osLinkParticleSystem(linknumber, rules);
+        }
+
+        public LSL_Integer osNpcLookAt(LSL_Key npckey, LSL_Integer type, LSL_Key objkey, vector offset)
+        {
+            return m_OSSL_Functions.osNpcLookAt(npckey, type, objkey, offset);
+        }
     }
 }

+ 7 - 8
OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs

@@ -783,24 +783,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
         /// Process the next event queued for this script
         /// </summary>
         /// <returns></returns>
-        public object EventProcessor()
+        public void EventProcessor()
         {
             // We check here as the thread stopping this instance from running may itself hold the m_Script lock.
             if (!Running)
-                return 0;
+                return;
 
             lock (m_Script)
             {
 //                m_log.DebugFormat("[XEngine]: EventProcessor() invoked for {0}.{1}", PrimName, ScriptName);
 
                 if (Suspended)
-                    return 0;
+                    return;
 
                 ExecutionTimer.Restart();
 
                 try
                 {
-                    return EventProcessorInt();
+                    EventProcessorInt();
+                    return;
                 }
                 finally
                 {
@@ -811,7 +812,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
             }
         }
 
-        private object EventProcessorInt()
+        private void EventProcessorInt()
         {
             EventParams data = null;
 
@@ -829,7 +830,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
                     {
                         m_CurrentWorkItem = null;
                     }
-                    return 0;
+                    return;
                 }
 
                 if (data.EventName == "timer")
@@ -1052,8 +1053,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
             }
 
             m_DetectParams = null;
-
-            return 0;
         }
 
         public int EventTime()

+ 3 - 3
OpenSim/Region/ScriptEngine/XEngine/ScriptEngineConsoleCommands.cs

@@ -97,7 +97,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
             if (!IsSceneSelected())
                 return;
 
-            Timer timerPlugin = AsyncCommandManager.GetTimerPlugin(m_engine);
+            ScriptTimer timerPlugin = AsyncCommandManager.GetTimerPlugin(m_engine);
 
             if (timerPlugin == null)
             {
@@ -105,7 +105,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
                 return;
             }
 
-            List<Timer.TimerInfo> timersInfo = timerPlugin.GetTimersInfo();
+            List<ScriptTimer.TimerInfo> timersInfo = timerPlugin.GetTimersInfo();
 
             ConsoleDisplayTable cdt = new ConsoleDisplayTable();
             cdt.AddColumn("Part local ID", 13);
@@ -113,7 +113,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
             cdt.AddColumn("Interval", 10);
             cdt.AddColumn("Next", 8);
 
-            foreach (Timer.TimerInfo t in timersInfo)
+            foreach (ScriptTimer.TimerInfo t in timersInfo)
             {
                 // Convert from 100 ns ticks back to seconds
                 cdt.AddRow(t.localID, t.itemID, (double)t.interval / 10000000, t.next);

+ 20 - 24
OpenSim/Region/ScriptEngine/XEngine/XEngine.cs

@@ -55,7 +55,7 @@ using OpenSim.Region.ScriptEngine.Shared.Api;
 using OpenSim.Region.ScriptEngine.Shared.Api.Plugins;
 using OpenSim.Region.ScriptEngine.Shared.ScriptBase;
 using OpenSim.Region.ScriptEngine.XEngine.ScriptBase;
-using Timer = OpenSim.Region.ScriptEngine.Shared.Api.Plugins.Timer;
+using ScritTimer = OpenSim.Region.ScriptEngine.Shared.Api.Plugins.ScriptTimer;
 
 using ScriptCompileQueue = OpenSim.Framework.LocklessQueue<object[]>;
 
@@ -599,7 +599,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
             Dataserver ds = AsyncCommandManager.GetDataserverPlugin(this);
             sb.AppendFormat("Dataserver requests        : {0}\n", ds != null ? ds.DataserverRequestsCount : 0);
 
-            Timer t = AsyncCommandManager.GetTimerPlugin(this);
+            ScritTimer t = AsyncCommandManager.GetTimerPlugin(this);
             sb.AppendFormat("Timers                     : {0}\n", t != null ? t.TimersCount : 0);
 
             Listener l = AsyncCommandManager.GetListenerPlugin(this);
@@ -801,14 +801,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine
 
             if (m_SleepTime > 0)
             {
-                m_ThreadPool.QueueWorkItem(new WorkItemCallback(this.DoMaintenance),
-                                           new Object[]{ m_SleepTime });
+                m_ThreadPool.QueueWorkItem(DoMaintenance, new object[]{ m_SleepTime });
             }
 
             if (m_SaveTime > 0)
             {
-                m_ThreadPool.QueueWorkItem(new WorkItemCallback(this.DoBackup),
-                                           new Object[] { m_SaveTime });
+                m_ThreadPool.QueueWorkItem(DoBackup, new object[] { m_SaveTime });
             }
         }
 
@@ -876,8 +874,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
             }
 
             if (saveTime > 0)
-                m_ThreadPool.QueueWorkItem(new WorkItemCallback(this.DoBackup),
-                                           new Object[] { saveTime });
+                m_ThreadPool.QueueWorkItem(DoBackup, new object[] { saveTime });
 
             return 0;
         }
@@ -904,8 +901,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
 
             System.Threading.Thread.Sleep(sleepTime);
 
-            m_ThreadPool.QueueWorkItem(new WorkItemCallback(this.DoMaintenance),
-                                       new Object[]{ sleepTime });
+            m_ThreadPool.QueueWorkItem(DoMaintenance, new object[]{ sleepTime });
 
             return 0;
         }
@@ -1690,15 +1686,17 @@ namespace OpenSim.Region.ScriptEngine.XEngine
         {
             m_MaxScriptQueue = maxScriptQueue;
 
-            STPStartInfo startInfo = new STPStartInfo();
-            startInfo.ThreadPoolName = "XEngine";
-            startInfo.IdleTimeout = idleTimeout * 1000; // convert to seconds as stated in .ini
-            startInfo.MaxWorkerThreads = maxThreads;
-            startInfo.MinWorkerThreads = minThreads;
-            startInfo.ThreadPriority = threadPriority;;
-            startInfo.MaxStackSize = stackSize;
-            startInfo.StartSuspended = true;
-
+            STPStartInfo startInfo = new STPStartInfo()
+            {
+                ThreadPoolName = "XEngine",
+                IdleTimeout = idleTimeout * 1000, // convert to seconds as stated in .ini
+                MaxWorkerThreads = maxThreads,
+                MinWorkerThreads = minThreads,
+                ThreadPriority = threadPriority,
+                MaxStackSize = stackSize,
+                SuppressFlow = true,
+                StartSuspended = true
+            };
             m_ThreadPool = new SmartThreadPool(startInfo);
         }
 
@@ -1707,9 +1705,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
         //
         public IScriptWorkItem QueueEventHandler(object parms)
         {
-            return new XWorkItem(m_ThreadPool.QueueWorkItem(
-                                     new WorkItemCallback(this.ProcessEventHandler),
-                                     parms));
+            return new XWorkItem(m_ThreadPool.QueueWorkItem((WaitCallback)ProcessEventHandler,parms));
         }
 
         /// <summary>
@@ -1717,7 +1713,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
         /// </summary>
         /// <param name="parms"></param>
         /// <returns></returns>
-        private object ProcessEventHandler(object parms)
+        private void ProcessEventHandler(object parms)
         {
             Culture.SetCurrentCulture();
 
@@ -1725,7 +1721,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
 
 //            m_log.DebugFormat("[XEngine]: Processing event for {0}", instance);
 
-            return instance.EventProcessor();
+            instance.EventProcessor();
         }
 
         /// <summary>

+ 37 - 19
OpenSim/Server/Handlers/Profiles/UserProfilesHandlers.cs

@@ -93,7 +93,8 @@ namespace OpenSim.Server.Handlers
 
         public bool ClassifiedUpdate(OSDMap json, ref JsonRpcResponse response)
         {
-            if(!json.ContainsKey("params"))
+            OSD tmpParams;
+            if(!json.TryGetValue("params", out tmpParams) || !(tmpParams is OSDMap))
             {
                 response.Error.Code = ErrorCode.ParseError;
                 response.Error.Message = "Error parsing classified update request";
@@ -103,9 +104,15 @@ namespace OpenSim.Server.Handlers
 
             string result = string.Empty;
             UserClassifiedAdd ad = new UserClassifiedAdd();
-            object Ad = (object)ad;
-            OSD.DeserializeMembers(ref Ad, (OSDMap)json["params"]);
-            if(Service.ClassifiedUpdate(ad, ref result))
+            object Ad = ad;
+            OSD.DeserializeMembers(ref Ad, (OSDMap)tmpParams);
+            //If no maturity bits are set, set PG maturity bit. This works
+            // around a viewer bug. It simplifies the ability to search ads
+            // based on maturity level. 0x4e is bits 1 (old viewers mature), 2 (pg), 3 (Mature) and 6 (Adult).
+            if ((ad.Flags & 0x4e) == 0)
+                ad.Flags |= 0x04;
+
+            if (Service.ClassifiedUpdate(ad, ref result))
             {
                 response.Result = OSD.SerializeMembers(ad);
                 return true;
@@ -138,7 +145,8 @@ namespace OpenSim.Server.Handlers
 
         public bool ClassifiedInfoRequest(OSDMap json, ref JsonRpcResponse response)
         {
-            if(!json.ContainsKey("params"))
+            OSD tmpParams;
+            if (!json.TryGetValue("params", out tmpParams) || !(tmpParams is OSDMap))
             {
                 response.Error.Code = ErrorCode.ParseError;
                 response.Error.Message = "no parameters supplied";
@@ -149,9 +157,14 @@ namespace OpenSim.Server.Handlers
             string result = string.Empty;
             UserClassifiedAdd ad = new UserClassifiedAdd();
             object Ad = (object)ad;
-            OSD.DeserializeMembers(ref Ad, (OSDMap)json["params"]);
+            OSD.DeserializeMembers(ref Ad, (OSDMap)tmpParams);
             if(Service.ClassifiedInfoRequest(ref ad, ref result))
             {
+                //If no maturity bits are set, set PG maturity bit. This works
+                // around a viewer bug. It simplifies the ability to search ads
+                // based on maturity level. 0x4e is bits 1 (old viewers mature), 2 (pg), 3 (Mature) and 6 (Adult).
+                if ((ad.Flags & 0x4e) == 0)
+                    ad.Flags |= 0x04;
                 response.Result = OSD.SerializeMembers(ad);
                 return true;
             }
@@ -165,17 +178,17 @@ namespace OpenSim.Server.Handlers
         #region Picks
         public bool AvatarPicksRequest(OSDMap json, ref JsonRpcResponse response)
         {
-            if(!json.ContainsKey("params"))
+            OSD tmpParams;
+            if (!json.TryGetValue("params", out tmpParams) || !(tmpParams is OSDMap))
             {
                 response.Error.Code = ErrorCode.ParseError;
                 m_log.DebugFormat ("Avatar Picks Request");
                 return false;
             }
 
-            OSDMap request = (OSDMap)json["params"];
+            OSDMap request = (OSDMap)tmpParams;
             UUID creatorId = new UUID(request["creatorId"].AsString());
 
-
             OSDArray data = (OSDArray) Service.AvatarPicksRequest(creatorId);
             response.Result = data;
 
@@ -184,7 +197,8 @@ namespace OpenSim.Server.Handlers
 
         public bool PickInfoRequest(OSDMap json, ref JsonRpcResponse response)
         {
-            if(!json.ContainsKey("params"))
+            OSD tmpParams;
+            if (!json.TryGetValue("params", out tmpParams) || !(tmpParams is OSDMap))
             {
                 response.Error.Code = ErrorCode.ParseError;
                 response.Error.Message = "no parameters supplied";
@@ -195,7 +209,7 @@ namespace OpenSim.Server.Handlers
             string result = string.Empty;
             UserProfilePick pick = new UserProfilePick();
             object Pick = (object)pick;
-            OSD.DeserializeMembers(ref Pick, (OSDMap)json["params"]);
+            OSD.DeserializeMembers(ref Pick, (OSDMap)tmpParams);
             if(Service.PickInfoRequest(ref pick, ref result))
             {
                 response.Result = OSD.SerializeMembers(pick);
@@ -209,7 +223,8 @@ namespace OpenSim.Server.Handlers
 
         public bool PicksUpdate(OSDMap json, ref JsonRpcResponse response)
         {
-            if(!json.ContainsKey("params"))
+            OSD tmpParams;
+            if (!json.TryGetValue("params", out tmpParams) || !(tmpParams is OSDMap))
             {
                 response.Error.Code = ErrorCode.ParseError;
                 response.Error.Message = "no parameters supplied";
@@ -220,7 +235,7 @@ namespace OpenSim.Server.Handlers
             string result = string.Empty;
             UserProfilePick pick = new UserProfilePick();
             object Pick = (object)pick;
-            OSD.DeserializeMembers(ref Pick, (OSDMap)json["params"]);
+            OSD.DeserializeMembers(ref Pick, (OSDMap)tmpParams);
             if(Service.PicksUpdate(ref pick, ref result))
             {
                 response.Result = OSD.SerializeMembers(pick);
@@ -235,14 +250,15 @@ namespace OpenSim.Server.Handlers
 
         public bool PicksDelete(OSDMap json, ref JsonRpcResponse response)
         {
-            if(!json.ContainsKey("params"))
+            OSD tmpParams;
+            if (!json.TryGetValue("params", out tmpParams) || !(tmpParams is OSDMap))
             {
                 response.Error.Code = ErrorCode.ParseError;
                 m_log.DebugFormat ("Avatar Picks Delete Request");
                 return false;
             }
 
-            OSDMap request = (OSDMap)json["params"];
+            OSDMap request = tmpParams as OSDMap;
             UUID pickId = new UUID(request["pickId"].AsString());
             if(Service.PicksDelete(pickId))
                 return true;
@@ -256,7 +272,8 @@ namespace OpenSim.Server.Handlers
         #region Notes
         public bool AvatarNotesRequest(OSDMap json, ref JsonRpcResponse response)
         {
-            if(!json.ContainsKey("params"))
+            OSD tmpParams;
+            if (!json.TryGetValue("params", out tmpParams) || !(tmpParams is OSDMap))
             {
                 response.Error.Code = ErrorCode.ParseError;
                 response.Error.Message = "Params missing";
@@ -266,7 +283,7 @@ namespace OpenSim.Server.Handlers
 
             UserProfileNotes note = new UserProfileNotes();
             object Note = (object)note;
-            OSD.DeserializeMembers(ref Note, (OSDMap)json["params"]);
+            OSD.DeserializeMembers(ref Note, (OSDMap)tmpParams);
             if(Service.AvatarNotesRequest(ref note))
             {
                 response.Result = OSD.SerializeMembers(note);
@@ -280,7 +297,8 @@ namespace OpenSim.Server.Handlers
 
         public bool NotesUpdate(OSDMap json, ref JsonRpcResponse response)
         {
-            if(!json.ContainsKey("params"))
+            OSD tmpParams;
+            if (!json.TryGetValue("params", out tmpParams) || !(tmpParams is OSDMap))
             {
                 response.Error.Code = ErrorCode.ParseError;
                 response.Error.Message = "No parameters";
@@ -291,7 +309,7 @@ namespace OpenSim.Server.Handlers
             string result = string.Empty;
             UserProfileNotes note = new UserProfileNotes();
             object Notes = (object) note;
-            OSD.DeserializeMembers(ref Notes, (OSDMap)json["params"]);
+            OSD.DeserializeMembers(ref Notes, (OSDMap)tmpParams);
             if(Service.NotesUpdate(ref note, ref result))
             {
                 response.Result = OSD.SerializeMembers(note);

+ 4 - 4
OpenSim/Server/Handlers/Simulation/AgentHandlers.cs

@@ -455,8 +455,7 @@ namespace OpenSim.Server.Handlers.Simulation
 
             resp["features"] = featuresWanted;
 
-            if(result)
-                httpResponse.KeepAlive = true;
+            httpResponse.KeepAlive = result;
 
             // We must preserve defaults here, otherwise a false "success" will not be put into the JSON map!
             httpResponse.RawBuffer = Util.UTF8.GetBytes(OSDParser.SerializeJsonString(resp, true));
@@ -539,7 +538,7 @@ namespace OpenSim.Server.Handlers.Simulation
             OSDMap resp = new OSDMap(2);
             string reason = string.Empty;
 
-            bool result = CreateAgent(source, gatekeeper, destination, aCircuit, data.flags, data.fromLogin, ctx, out reason);
+            bool result = CreateAgent(source, gatekeeper, destination, aCircuit, data.flags, ctx, out reason);
 
             resp["reason"] = OSD.FromString(reason);
             resp["success"] = OSD.FromBoolean(result);
@@ -548,6 +547,7 @@ namespace OpenSim.Server.Handlers.Simulation
 
             httpResponse.StatusCode = (int)HttpStatusCode.OK;
             httpResponse.RawBuffer = Util.UTF8.GetBytes(OSDParser.SerializeJsonString(resp));
+            httpResponse.KeepAlive = (data.flags & (uint)(TeleportFlags.ViaLogin | TeleportFlags.ViaHGLogin)) != (uint)TeleportFlags.ViaLogin;
         }
 
         protected virtual AgentDestinationData CreateAgentDestinationData()
@@ -586,7 +586,7 @@ namespace OpenSim.Server.Handlers.Simulation
 
         // subclasses can override this
         protected virtual bool CreateAgent(GridRegion source, GridRegion gatekeeper, GridRegion destination,
-            AgentCircuitData aCircuit, uint teleportFlags, bool fromLogin, EntityTransferContext ctx, out string reason)
+            AgentCircuitData aCircuit, uint teleportFlags, EntityTransferContext ctx, out string reason)
         {
             reason = string.Empty;
             bool ret = m_SimulationService.CreateAgent(source, destination, aCircuit, teleportFlags, ctx, out reason);

+ 13 - 11
OpenSim/Services/HypergridService/UserAgentService.cs

@@ -644,19 +644,21 @@ namespace OpenSim.Services.HypergridService
                 return targetUserID.ToString() + ";" + m_GridName + ";" + account.FirstName + " " + account.LastName ;
 
             // Let's try the list of friends
-            FriendInfo[] friends = m_FriendsService.GetFriends(userID);
-            if (friends != null && friends.Length > 0)
+            if(m_FriendsService != null)
             {
-                foreach (FriendInfo f in friends)
-                    if (f.Friend.StartsWith(targetUserID.ToString()))
-                    {
-                        // Let's remove the secret
-                        UUID id; string tmp = string.Empty, secret = string.Empty;
-                        if (Util.ParseUniversalUserIdentifier(f.Friend, out id, out tmp, out tmp, out tmp, out secret))
-                            return f.Friend.Replace(secret, "0");
-                    }
+                FriendInfo[] friends = m_FriendsService.GetFriends(userID);
+                if (friends != null && friends.Length > 0)
+                {
+                    foreach (FriendInfo f in friends)
+                        if (f.Friend.StartsWith(targetUserID.ToString()))
+                        {
+                            // Let's remove the secret
+                            UUID id; string tmp = string.Empty, secret = string.Empty;
+                            if (Util.ParseUniversalUserIdentifier(f.Friend, out id, out tmp, out tmp, out tmp, out secret))
+                                return f.Friend.Replace(secret, "0");
+                        }
+                }
             }
-
             return string.Empty;
         }
 

+ 2 - 1
OpenSim/Services/Interfaces/IUserManagement.cs

@@ -46,7 +46,8 @@ namespace OpenSim.Framework
         bool GetUserUUI(UUID userID, out string uui);
         string GetUserServerURL(UUID uuid, string serverType);
         string GetUserServerURL(UUID uuid, string serverType, out bool failedWeb);
-        Dictionary<UUID,string> GetUsersNames(string[] ids, UUID scopeID);
+        Dictionary<UUID, string> GetUsersNames(string[] ids, UUID scopeID);
+        Dictionary<UUID, string> GetKnownUserNames(string[] ids, UUID scopeID);
         void UserWebFailed(UUID id);
 
         /// <summary>

+ 4 - 0
ThirdParty/SmartThreadPool/STPEventWaitHandle.cs

@@ -7,21 +7,25 @@ namespace Amib.Threading.Internal
     {
         public const int WaitTimeout = Timeout.Infinite;
 
+        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
         internal static bool WaitAll(WaitHandle[] waitHandles, int millisecondsTimeout, bool exitContext)
         {
             return WaitHandle.WaitAll(waitHandles, millisecondsTimeout, exitContext);
         }
 
+        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
         internal static int WaitAny(WaitHandle[] waitHandles)
         {
             return WaitHandle.WaitAny(waitHandles);
         }
 
+        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
         internal static int WaitAny(WaitHandle[] waitHandles, int millisecondsTimeout, bool exitContext)
         {
             return WaitHandle.WaitAny(waitHandles, millisecondsTimeout, exitContext);
         }
 
+        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
         internal static bool WaitOne(WaitHandle waitHandle, int millisecondsTimeout, bool exitContext)
         {
             return waitHandle.WaitOne(millisecondsTimeout, exitContext);

+ 10 - 9
ThirdParty/SmartThreadPool/SmartThreadPool.cs

@@ -665,6 +665,7 @@ namespace Amib.Threading
             // of the dictionary.
             CurrentThreadEntry = _workerThreads[Thread.CurrentThread];
 
+            bool informedCompleted = false;
             FireOnThreadInitialization();
 
             try
@@ -676,10 +677,6 @@ namespace Amib.Threading
                 // Process until shutdown.
                 while (!_shutdown)
                 {
-                    // Update the last time this thread was seen alive.
-                    // It's good for debugging.
-                    CurrentThreadEntry.IAmAlive();
-
                     // The following block handles the when the MaxWorkerThreads has been
                     // incremented by the user at run-time.
                     // Double lock for quit.
@@ -694,18 +691,17 @@ namespace Amib.Threading
                                 // more threads will quit and the thread pool will go
                                 // below the lower limit.
                                 InformCompleted();
+                                informedCompleted = true;
                                 break;
                             }
                         }
                     }
 
+                    CurrentThreadEntry.IAmAlive();
+
                     // Wait for a work item, shutdown, or timeout
                     WorkItem workItem = Dequeue();
 
-                    // Update the last time this thread was seen alive.
-                    // It's good for debugging.
-                    CurrentThreadEntry.IAmAlive();
-
                     // On timeout or shut down.
                     if (workItem == null)
                     {
@@ -721,6 +717,7 @@ namespace Amib.Threading
                                     // more threads will quit and the thread pool will go
                                     // below the lower limit.
                                     InformCompleted();
+                                    informedCompleted = true;
                                     break;
                                 }
                             }
@@ -728,6 +725,8 @@ namespace Amib.Threading
                         continue;
                     }
 
+                    CurrentThreadEntry.IAmAlive();
+
                     try
                     {
                         // Initialize the value to false
@@ -817,8 +816,10 @@ namespace Amib.Threading
             }
             finally
             {
-                InformCompleted();
+                if(!informedCompleted)
+                    InformCompleted();
                 FireOnThreadTermination();
+                _workItemsQueue.CloseThreadWaiter();
             }
         }
 

+ 6 - 0
ThirdParty/SmartThreadPool/WorkItem.cs

@@ -987,6 +987,12 @@ namespace Amib.Threading.Internal
                 _callerContext = null;
             }
 
+            if(_workItemCompleted != null)
+            {
+                _workItemCompleted.Dispose();
+                _workItemCompleted = null;
+            }
+
             if (_workItemInfo.DisposeOfStateObjects)
             {
                 IDisposable disp = _state as IDisposable;

+ 1 - 1
ThirdParty/SmartThreadPool/WorkItemsGroup.cs

@@ -335,7 +335,7 @@ namespace Amib.Threading.Internal
                 {
                     if (_workItemsInStpQueue < _concurrency)
                     {
-                        WorkItem nextWorkItem = _workItemsQueue.Dequeue() as WorkItem;
+                        WorkItem nextWorkItem = _workItemsQueue.Dequeue();
                         try
                         {
                             _stp.Enqueue(nextWorkItem);

+ 37 - 81
ThirdParty/SmartThreadPool/WorkItemsQueue.cs

@@ -36,22 +36,6 @@ namespace Amib.Threading.Internal
         [ThreadStatic]
         private static WaiterEntry _waiterEntry;
 
-
-        /// <summary>
-        /// Each thread in the thread pool keeps its own waiter entry.
-        /// </summary>
-        private static WaiterEntry CurrentWaiterEntry
-        {
-            get
-            {
-                return _waiterEntry;
-            }
-            set
-            {
-                _waiterEntry = value;
-            }
-        }
-
         /// <summary>
         /// A flag that indicates if the WorkItemsQueue has been disposed.
         /// </summary>
@@ -95,13 +79,11 @@ namespace Amib.Threading.Internal
         {
             // A work item cannot be null, since null is used in the
             // WaitForWorkItem() method to indicate timeout or cancel
-            if (null == workItem)
+            if (workItem == null)
             {
                 throw new ArgumentNullException("workItem", "workItem cannot be null");
             }
 
-            bool enqueue = true;
-
             // First check if there is a waiter waiting for work item. During 
             // the check, timed out waiters are ignored. If there is no 
             // waiter then the work item is queued.
@@ -110,9 +92,7 @@ namespace Amib.Threading.Internal
                 ValidateNotDisposed();
 
                 if (!_isWorkItemsQueueActive)
-                {
                     return false;
-                }
 
                 while (_waitersCount > 0)
                 {
@@ -121,21 +101,24 @@ namespace Amib.Threading.Internal
 
                     // Signal the waiter. On success break the loop
                     if (waiterEntry.Signal(workItem))
-                    {
-                        enqueue = false;
-                        break;
-                    }
+                        return true;
                 }
 
-                if (enqueue)
-                {
-                    // Enqueue the work item
-                    _workItems.Enqueue(workItem);
-                }
+                // Enqueue the work item
+                _workItems.Enqueue(workItem);
             }
             return true;
         }
 
+        public void CloseThreadWaiter()
+        {
+            if(_waiterEntry != null)
+            {
+                _waiterEntry.Close();
+                _waiterEntry = null;
+            }
+        }
+
 
         /// <summary>
         /// Waits for a work item or exits on timeout or cancel
@@ -158,17 +141,13 @@ namespace Amib.Threading.Internal
             // didn't get a work item.
 
             WaiterEntry waiterEntry;
-            WorkItem workItem = null;
             lock (this)
             {
                 ValidateNotDisposed();
 
                 // If there are waiting work items then take one and return.
                 if (_workItems.Count > 0)
-                {
-                    workItem = _workItems.Dequeue();
-                    return workItem;
-                }
+                    return _workItems.Dequeue();
 
                 // No waiting work items ...
 
@@ -193,43 +172,26 @@ namespace Amib.Threading.Internal
 
             lock (this)
             {
-                // success is true if it got a work item.
-                bool success = (0 == index);
-
-                // The timeout variable is used only for readability.
-                // (We treat cancel as timeout)
-                bool timeout = !success;
-
                 // On timeout update the waiterEntry that it is timed out
-                if (timeout)
+                if (index != 0)
                 {
                     // The Timeout() fails if the waiter has already been signaled
-                    timeout = waiterEntry.Timeout();
-
                     // On timeout remove the waiter from the queue.
                     // Note that the complexity is O(1).
-                    if (timeout)
+                    if (waiterEntry.Timeout())
                     {
                         RemoveWaiter(waiterEntry, false);
+                        return null;
                     }
-
-                    // Again readability
-                    success = !timeout;
                 }
 
                 // On success return the work item
-                if (success)
-                {
-                    workItem = waiterEntry.WorkItem;
+                WorkItem workItem = waiterEntry.WorkItem;
+                if (workItem == null)
+                    workItem = _workItems.Dequeue();
 
-                    if (null == workItem)
-                    {
-                        workItem = _workItems.Dequeue();
-                    }
-                }
+                return workItem;
             }
-            // On failure return null.
-            return workItem;
         }
 
         /// <summary>
@@ -300,12 +262,13 @@ namespace Amib.Threading.Internal
         /// objects each thread has its own WaiterEntry object.
         private static WaiterEntry GetThreadWaiterEntry()
         {
-            if (null == CurrentWaiterEntry)
+            if (_waiterEntry == null)
             {
-                CurrentWaiterEntry = new WaiterEntry();
+                _waiterEntry = new WaiterEntry();
             }
-            CurrentWaiterEntry.Reset();
-            return CurrentWaiterEntry;
+            else
+                _waiterEntry.Reset();
+            return _waiterEntry;
         }
 
         #region Waiters stack methods
@@ -325,7 +288,6 @@ namespace Amib.Threading.Internal
             {
                 _headWaiterEntry._nextWaiterEntry = newWaiterEntry;
                 newWaiterEntry._prevWaiterEntry = _headWaiterEntry;
-
             }
             // If the stack is not empty then put newWaiterEntry as the new head 
             // of the stack.
@@ -363,7 +325,7 @@ namespace Amib.Threading.Internal
 
             // Update the new stack head
             _headWaiterEntry._nextWaiterEntry = newHeadWaiterEntry;
-            if (null != newHeadWaiterEntry)
+            if (newHeadWaiterEntry != null)
             {
                 newHeadWaiterEntry._prevWaiterEntry = _headWaiterEntry;
             }
@@ -381,43 +343,38 @@ namespace Amib.Threading.Internal
         {
             // Store the prev entry in the list
             WaiterEntry prevWaiterEntry = waiterEntry._prevWaiterEntry;
+            waiterEntry._prevWaiterEntry = null;
 
             // Store the next entry in the list
             WaiterEntry nextWaiterEntry = waiterEntry._nextWaiterEntry;
+            waiterEntry._nextWaiterEntry = null;
 
-            // A flag to indicate if we need to decrement the waiters count.
+            // popDecrement indicate if we need to decrement the waiters count.
             // If we got here from PopWaiter then we must decrement.
             // If we got here from PushWaiter then we decrement only if
             // the waiter was already in the stack.
-            bool decrementCounter = popDecrement;
-
-            // Null the waiter's entry links
-            waiterEntry._prevWaiterEntry = null;
-            waiterEntry._nextWaiterEntry = null;
 
             // If the waiter entry had a prev link then update it.
             // It also means that the waiter is already in the list and we
             // need to decrement the waiters count.
-            if (null != prevWaiterEntry)
+            if (prevWaiterEntry != null)
             {
                 prevWaiterEntry._nextWaiterEntry = nextWaiterEntry;
-                decrementCounter = true;
+                popDecrement = true;
             }
 
             // If the waiter entry had a next link then update it.
             // It also means that the waiter is already in the list and we
             // need to decrement the waiters count.
-            if (null != nextWaiterEntry)
+            if (nextWaiterEntry != null)
             {
                 nextWaiterEntry._prevWaiterEntry = prevWaiterEntry;
-                decrementCounter = true;
+                popDecrement = true;
             }
 
             // Decrement the waiters count if needed
-            if (decrementCounter)
-            {
+            if (popDecrement)
                 --_waitersCount;
-            }
         }
 
         #endregion
@@ -434,7 +391,6 @@ namespace Amib.Threading.Internal
             /// <summary>
             /// Event to signal the waiter that it got the work item.
             /// </summary>
-            //private AutoResetEvent _waitHandle = new AutoResetEvent(false);
             private AutoResetEvent _waitHandle = new AutoResetEvent(false);
 
             /// <summary>
@@ -466,7 +422,6 @@ namespace Amib.Threading.Internal
 
             public WaiterEntry()
             {
-                Reset();
             }
 
             #endregion
@@ -544,6 +499,7 @@ namespace Amib.Threading.Internal
             /// </summary>
             public void Close()
             {
+                _workItem = null;
                 if (null != _waitHandle)
                 {
                     _waitHandle.Close();
@@ -562,8 +518,8 @@ namespace Amib.Threading.Internal
                     if (!_isDisposed)
                     {
                         Close();
+                        _isDisposed = true;
                     }
-                    _isDisposed = true;
                 }
             }
 

+ 4477 - 0
bin/586dd99c-b06d-4c2c-85e8-9cdbca339aa0.xml

@@ -0,0 +1,4477 @@
+<SceneObjectGroup>
+  <RootPart>
+    <SceneObjectPart xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+      <AllowedDrop>false</AllowedDrop>
+      <CreatorID>
+        <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+      </CreatorID>
+      <FolderID>
+        <UUID>586dd99c-b06d-4c2c-85e8-9cdbca339aa0</UUID>
+      </FolderID>
+      <InventorySerial>0</InventorySerial>
+      <UUID>
+        <UUID>586dd99c-b06d-4c2c-85e8-9cdbca339aa0</UUID>
+      </UUID>
+      <LocalId>656849163</LocalId>
+      <Name>chimney</Name>
+      <Material>3</Material>
+      <PassTouches>false</PassTouches>
+      <PassCollisions>false</PassCollisions>
+      <RegionHandle>4008819395804416</RegionHandle>
+      <ScriptAccessPin>0</ScriptAccessPin>
+      <GroupPosition>
+        <X>192.3722</X>
+        <Y>185.4859</Y>
+        <Z>53.20147</Z>
+      </GroupPosition>
+      <OffsetPosition>
+        <X>0</X>
+        <Y>0</Y>
+        <Z>0</Z>
+      </OffsetPosition>
+      <RotationOffset>
+        <X>-0.4776486</X>
+        <Y>0.4318344</Y>
+        <Z>-0.3226687</Z>
+        <W>0.6937261</W>
+      </RotationOffset>
+      <Velocity>
+        <X>0</X>
+        <Y>0</Y>
+        <Z>0</Z>
+      </Velocity>
+      <AngularVelocity>
+        <X>0</X>
+        <Y>0</Y>
+        <Z>0</Z>
+      </AngularVelocity>
+      <Acceleration>
+        <X>0</X>
+        <Y>0</Y>
+        <Z>0</Z>
+      </Acceleration>
+      <Description>(No Description)</Description>
+      <Color>
+        <R>0</R>
+        <G>0</G>
+        <B>0</B>
+        <A>255</A>
+      </Color>
+      <Text />
+      <SitName />
+      <TouchName />
+      <LinkNum>1</LinkNum>
+      <ClickAction>0</ClickAction>
+      <Shape>
+        <ProfileCurve>48</ProfileCurve>
+        <TextureEntry>h+/Ie5QJSpCReMgdt5xI9AAAAAAAAAAAgD8AAACAPwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==</TextureEntry>
+        <ExtraParams>ATAAEQAAAKXyxa3SlEhkjI3JNqIEaf0F</ExtraParams>
+        <PathBegin>0</PathBegin>
+        <PathCurve>32</PathCurve>
+        <PathEnd>0</PathEnd>
+        <PathRadiusOffset>0</PathRadiusOffset>
+        <PathRevolutions>0</PathRevolutions>
+        <PathScaleX>100</PathScaleX>
+        <PathScaleY>150</PathScaleY>
+        <PathShearX>0</PathShearX>
+        <PathShearY>0</PathShearY>
+        <PathSkew>0</PathSkew>
+        <PathTaperX>0</PathTaperX>
+        <PathTaperY>0</PathTaperY>
+        <PathTwist>0</PathTwist>
+        <PathTwistBegin>0</PathTwistBegin>
+        <PCode>9</PCode>
+        <ProfileBegin>0</ProfileBegin>
+        <ProfileEnd>0</ProfileEnd>
+        <ProfileHollow>0</ProfileHollow>
+        <State>0</State>
+        <LastAttachPoint>0</LastAttachPoint>
+        <ProfileShape>Circle</ProfileShape>
+        <HollowShape>Triangle</HollowShape>
+        <SculptTexture>
+          <UUID>a5f2c5ad-d294-4864-8c8d-c936a20469fd</UUID>
+        </SculptTexture>
+        <SculptType>5</SculptType>
+        <FlexiSoftness>0</FlexiSoftness>
+        <FlexiTension>0</FlexiTension>
+        <FlexiDrag>0</FlexiDrag>
+        <FlexiGravity>0</FlexiGravity>
+        <FlexiWind>0</FlexiWind>
+        <FlexiForceX>0</FlexiForceX>
+        <FlexiForceY>0</FlexiForceY>
+        <FlexiForceZ>0</FlexiForceZ>
+        <LightColorR>0</LightColorR>
+        <LightColorG>0</LightColorG>
+        <LightColorB>0</LightColorB>
+        <LightColorA>1</LightColorA>
+        <LightRadius>0</LightRadius>
+        <LightCutoff>0</LightCutoff>
+        <LightFalloff>0</LightFalloff>
+        <LightIntensity>1</LightIntensity>
+        <FlexiEntry>false</FlexiEntry>
+        <LightEntry>false</LightEntry>
+        <SculptEntry>true</SculptEntry>
+      </Shape>
+      <Scale>
+        <X>0.09730455</X>
+        <Y>0.06544048</Y>
+        <Z>3.212147</Z>
+      </Scale>
+      <SitTargetOrientation>
+        <X>0</X>
+        <Y>0</Y>
+        <Z>0</Z>
+        <W>1</W>
+      </SitTargetOrientation>
+      <SitTargetPosition>
+        <X>0</X>
+        <Y>0</Y>
+        <Z>0</Z>
+      </SitTargetPosition>
+      <SitTargetPositionLL>
+        <X>0</X>
+        <Y>0</Y>
+        <Z>0</Z>
+      </SitTargetPositionLL>
+      <SitTargetOrientationLL>
+        <X>0</X>
+        <Y>0</Y>
+        <Z>0</Z>
+        <W>1</W>
+      </SitTargetOrientationLL>
+      <ParentID>0</ParentID>
+      <CreationDate>1614974861</CreationDate>
+      <Category>0</Category>
+      <SalePrice>0</SalePrice>
+      <ObjectSaleType>0</ObjectSaleType>
+      <OwnershipCost>0</OwnershipCost>
+      <GroupID>
+        <UUID>5f1ea2fb-d489-44ce-a41d-a8d2a18c343c</UUID>
+      </GroupID>
+      <OwnerID>
+        <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+      </OwnerID>
+      <LastOwnerID>
+        <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+      </LastOwnerID>
+      <RezzerID>
+        <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+      </RezzerID>
+      <BaseMask>647168</BaseMask>
+      <OwnerMask>647168</OwnerMask>
+      <GroupMask>0</GroupMask>
+      <EveryoneMask>0</EveryoneMask>
+      <NextOwnerMask>532480</NextOwnerMask>
+      <Flags>None</Flags>
+      <CollisionSound>
+        <UUID>00000000-0000-0000-0000-000000000000</UUID>
+      </CollisionSound>
+      <CollisionSoundVolume>0</CollisionSoundVolume>
+      <MediaUrl />
+      <AttachedPos>
+        <X>0</X>
+        <Y>0</Y>
+        <Z>0</Z>
+      </AttachedPos>
+      <TextureAnimation></TextureAnimation>
+      <ParticleSystem></ParticleSystem>
+      <PayPrice0>-2</PayPrice0>
+      <PayPrice1>-2</PayPrice1>
+      <PayPrice2>-2</PayPrice2>
+      <PayPrice3>-2</PayPrice3>
+      <PayPrice4>-2</PayPrice4>
+      <Buoyancy>0</Buoyancy>
+      <Force>
+        <X>0</X>
+        <Y>0</Y>
+        <Z>0</Z>
+      </Force>
+      <Torque>
+        <X>0</X>
+        <Y>0</Y>
+        <Z>0</Z>
+      </Torque>
+      <VolumeDetectActive>false</VolumeDetectActive>
+      <PhysicsShapeType>0</PhysicsShapeType>
+      <CameraEyeOffset>
+        <X>0</X>
+        <Y>0</Y>
+        <Z>0</Z>
+      </CameraEyeOffset>
+      <CameraAtOffset>
+        <X>0</X>
+        <Y>0</Y>
+        <Z>0</Z>
+      </CameraAtOffset>
+      <SoundID>
+        <UUID>00000000-0000-0000-0000-000000000000</UUID>
+      </SoundID>
+      <SoundGain>0</SoundGain>
+      <SoundFlags>0</SoundFlags>
+      <SoundRadius>0</SoundRadius>
+      <SoundQueueing>false</SoundQueueing>
+    </SceneObjectPart>
+  </RootPart>
+  <OtherParts>
+    <Part>
+      <SceneObjectPart xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+        <AllowedDrop>false</AllowedDrop>
+        <CreatorID>
+          <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+        </CreatorID>
+        <FolderID>
+          <UUID>37b3a641-85c6-4918-8d41-b0d79b7891d3</UUID>
+        </FolderID>
+        <InventorySerial>0</InventorySerial>
+        <UUID>
+          <UUID>37b3a641-85c6-4918-8d41-b0d79b7891d3</UUID>
+        </UUID>
+        <LocalId>656849164</LocalId>
+        <Name>chimney#1</Name>
+        <Material>3</Material>
+        <PassTouches>false</PassTouches>
+        <PassCollisions>false</PassCollisions>
+        <RegionHandle>4008819395804416</RegionHandle>
+        <ScriptAccessPin>0</ScriptAccessPin>
+        <GroupPosition>
+          <X>192.3722</X>
+          <Y>185.4859</Y>
+          <Z>53.20147</Z>
+        </GroupPosition>
+        <OffsetPosition>
+          <X>-0.2194808</X>
+          <Y>0.06708845</Y>
+          <Z>-0.0007649387</Z>
+        </OffsetPosition>
+        <RotationOffset>
+          <X>3.576278E-07</X>
+          <Y>-3.129243E-07</Y>
+          <Z>6.407497E-07</Z>
+          <W>1</W>
+        </RotationOffset>
+        <Velocity>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </Velocity>
+        <AngularVelocity>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </AngularVelocity>
+        <Acceleration>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </Acceleration>
+        <Description />
+        <Color>
+          <R>0</R>
+          <G>0</G>
+          <B>0</B>
+          <A>255</A>
+        </Color>
+        <Text />
+        <SitName />
+        <TouchName />
+        <LinkNum>2</LinkNum>
+        <ClickAction>0</ClickAction>
+        <Shape>
+          <ProfileCurve>48</ProfileCurve>
+          <TextureEntry>h+/Ie5QJSpCReMgdt5xI9AAAAAAAAAAAgD8AAACAPwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==</TextureEntry>
+          <ExtraParams>ATAAEQAAAM2RONqZLEjnliIqcD5FfTgF</ExtraParams>
+          <PathBegin>0</PathBegin>
+          <PathCurve>32</PathCurve>
+          <PathEnd>0</PathEnd>
+          <PathRadiusOffset>0</PathRadiusOffset>
+          <PathRevolutions>0</PathRevolutions>
+          <PathScaleX>100</PathScaleX>
+          <PathScaleY>150</PathScaleY>
+          <PathShearX>0</PathShearX>
+          <PathShearY>0</PathShearY>
+          <PathSkew>0</PathSkew>
+          <PathTaperX>0</PathTaperX>
+          <PathTaperY>0</PathTaperY>
+          <PathTwist>0</PathTwist>
+          <PathTwistBegin>0</PathTwistBegin>
+          <PCode>9</PCode>
+          <ProfileBegin>0</ProfileBegin>
+          <ProfileEnd>0</ProfileEnd>
+          <ProfileHollow>0</ProfileHollow>
+          <State>0</State>
+          <LastAttachPoint>0</LastAttachPoint>
+          <ProfileShape>Circle</ProfileShape>
+          <HollowShape>Triangle</HollowShape>
+          <SculptTexture>
+            <UUID>cd9138da-992c-48e7-9622-2a703e457d38</UUID>
+          </SculptTexture>
+          <SculptType>5</SculptType>
+          <FlexiSoftness>0</FlexiSoftness>
+          <FlexiTension>0</FlexiTension>
+          <FlexiDrag>0</FlexiDrag>
+          <FlexiGravity>0</FlexiGravity>
+          <FlexiWind>0</FlexiWind>
+          <FlexiForceX>0</FlexiForceX>
+          <FlexiForceY>0</FlexiForceY>
+          <FlexiForceZ>0</FlexiForceZ>
+          <LightColorR>0</LightColorR>
+          <LightColorG>0</LightColorG>
+          <LightColorB>0</LightColorB>
+          <LightColorA>1</LightColorA>
+          <LightRadius>0</LightRadius>
+          <LightCutoff>0</LightCutoff>
+          <LightFalloff>0</LightFalloff>
+          <LightIntensity>1</LightIntensity>
+          <FlexiEntry>false</FlexiEntry>
+          <LightEntry>false</LightEntry>
+          <SculptEntry>true</SculptEntry>
+        </Shape>
+        <Scale>
+          <X>0.0975092</X>
+          <Y>0.06620637</Y>
+          <Z>3.209846</Z>
+        </Scale>
+        <SitTargetOrientation>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+          <W>1</W>
+        </SitTargetOrientation>
+        <SitTargetPosition>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </SitTargetPosition>
+        <SitTargetPositionLL>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </SitTargetPositionLL>
+        <SitTargetOrientationLL>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+          <W>1</W>
+        </SitTargetOrientationLL>
+        <ParentID>656849163</ParentID>
+        <CreationDate>1614974861</CreationDate>
+        <Category>0</Category>
+        <SalePrice>0</SalePrice>
+        <ObjectSaleType>0</ObjectSaleType>
+        <OwnershipCost>0</OwnershipCost>
+        <GroupID>
+          <UUID>5f1ea2fb-d489-44ce-a41d-a8d2a18c343c</UUID>
+        </GroupID>
+        <OwnerID>
+          <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+        </OwnerID>
+        <LastOwnerID>
+          <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+        </LastOwnerID>
+        <RezzerID>
+          <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+        </RezzerID>
+        <BaseMask>647168</BaseMask>
+        <OwnerMask>647168</OwnerMask>
+        <GroupMask>0</GroupMask>
+        <EveryoneMask>0</EveryoneMask>
+        <NextOwnerMask>532480</NextOwnerMask>
+        <Flags>None</Flags>
+        <CollisionSound>
+          <UUID>00000000-0000-0000-0000-000000000000</UUID>
+        </CollisionSound>
+        <CollisionSoundVolume>0</CollisionSoundVolume>
+        <MediaUrl />
+        <AttachedPos>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </AttachedPos>
+        <TextureAnimation></TextureAnimation>
+        <ParticleSystem></ParticleSystem>
+        <PayPrice0>-2</PayPrice0>
+        <PayPrice1>-2</PayPrice1>
+        <PayPrice2>-2</PayPrice2>
+        <PayPrice3>-2</PayPrice3>
+        <PayPrice4>-2</PayPrice4>
+        <Buoyancy>0</Buoyancy>
+        <Force>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </Force>
+        <Torque>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </Torque>
+        <VolumeDetectActive>false</VolumeDetectActive>
+        <PhysicsShapeType>0</PhysicsShapeType>
+        <CameraEyeOffset>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </CameraEyeOffset>
+        <CameraAtOffset>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </CameraAtOffset>
+        <SoundID>
+          <UUID>00000000-0000-0000-0000-000000000000</UUID>
+        </SoundID>
+        <SoundGain>0</SoundGain>
+        <SoundFlags>0</SoundFlags>
+        <SoundRadius>0</SoundRadius>
+        <SoundQueueing>false</SoundQueueing>
+      </SceneObjectPart>
+    </Part>
+    <Part>
+      <SceneObjectPart xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+        <AllowedDrop>false</AllowedDrop>
+        <CreatorID>
+          <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+        </CreatorID>
+        <FolderID>
+          <UUID>6e8d6b14-1943-4d38-bd8f-ef05f5884b9a</UUID>
+        </FolderID>
+        <InventorySerial>0</InventorySerial>
+        <UUID>
+          <UUID>6e8d6b14-1943-4d38-bd8f-ef05f5884b9a</UUID>
+        </UUID>
+        <LocalId>656849165</LocalId>
+        <Name>chimney#2</Name>
+        <Material>3</Material>
+        <PassTouches>false</PassTouches>
+        <PassCollisions>false</PassCollisions>
+        <RegionHandle>4008819395804416</RegionHandle>
+        <ScriptAccessPin>0</ScriptAccessPin>
+        <GroupPosition>
+          <X>192.3722</X>
+          <Y>185.4859</Y>
+          <Z>53.20147</Z>
+        </GroupPosition>
+        <OffsetPosition>
+          <X>-0.6779671</X>
+          <Y>0.2080188</Y>
+          <Z>-0.001229737</Z>
+        </OffsetPosition>
+        <RotationOffset>
+          <X>4.768373E-07</X>
+          <Y>-1.370907E-06</Y>
+          <Z>1.832843E-06</Z>
+          <W>1</W>
+        </RotationOffset>
+        <Velocity>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </Velocity>
+        <AngularVelocity>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </AngularVelocity>
+        <Acceleration>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </Acceleration>
+        <Description />
+        <Color>
+          <R>0</R>
+          <G>0</G>
+          <B>0</B>
+          <A>255</A>
+        </Color>
+        <Text />
+        <SitName />
+        <TouchName />
+        <LinkNum>3</LinkNum>
+        <ClickAction>0</ClickAction>
+        <Shape>
+          <ProfileCurve>48</ProfileCurve>
+          <TextureEntry>h+/Ie5QJSpCReMgdt5xI9AAAAAAAAAAAgD8AAACAPwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==</TextureEntry>
+          <ExtraParams>ATAAEQAAAGt4xPLR4UShhtXfwP8Wq90F</ExtraParams>
+          <PathBegin>0</PathBegin>
+          <PathCurve>32</PathCurve>
+          <PathEnd>0</PathEnd>
+          <PathRadiusOffset>0</PathRadiusOffset>
+          <PathRevolutions>0</PathRevolutions>
+          <PathScaleX>100</PathScaleX>
+          <PathScaleY>150</PathScaleY>
+          <PathShearX>0</PathShearX>
+          <PathShearY>0</PathShearY>
+          <PathSkew>0</PathSkew>
+          <PathTaperX>0</PathTaperX>
+          <PathTaperY>0</PathTaperY>
+          <PathTwist>0</PathTwist>
+          <PathTwistBegin>0</PathTwistBegin>
+          <PCode>9</PCode>
+          <ProfileBegin>0</ProfileBegin>
+          <ProfileEnd>0</ProfileEnd>
+          <ProfileHollow>0</ProfileHollow>
+          <State>0</State>
+          <LastAttachPoint>0</LastAttachPoint>
+          <ProfileShape>Circle</ProfileShape>
+          <HollowShape>Triangle</HollowShape>
+          <SculptTexture>
+            <UUID>6b78c4f2-d1e1-44a1-86d5-dfc0ff16abdd</UUID>
+          </SculptTexture>
+          <SculptType>5</SculptType>
+          <FlexiSoftness>0</FlexiSoftness>
+          <FlexiTension>0</FlexiTension>
+          <FlexiDrag>0</FlexiDrag>
+          <FlexiGravity>0</FlexiGravity>
+          <FlexiWind>0</FlexiWind>
+          <FlexiForceX>0</FlexiForceX>
+          <FlexiForceY>0</FlexiForceY>
+          <FlexiForceZ>0</FlexiForceZ>
+          <LightColorR>0</LightColorR>
+          <LightColorG>0</LightColorG>
+          <LightColorB>0</LightColorB>
+          <LightColorA>1</LightColorA>
+          <LightRadius>0</LightRadius>
+          <LightCutoff>0</LightCutoff>
+          <LightFalloff>0</LightFalloff>
+          <LightIntensity>1</LightIntensity>
+          <FlexiEntry>false</FlexiEntry>
+          <LightEntry>false</LightEntry>
+          <SculptEntry>true</SculptEntry>
+        </Shape>
+        <Scale>
+          <X>0.09757739</X>
+          <Y>0.06647031</Y>
+          <Z>3.206532</Z>
+        </Scale>
+        <SitTargetOrientation>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+          <W>1</W>
+        </SitTargetOrientation>
+        <SitTargetPosition>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </SitTargetPosition>
+        <SitTargetPositionLL>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </SitTargetPositionLL>
+        <SitTargetOrientationLL>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+          <W>1</W>
+        </SitTargetOrientationLL>
+        <ParentID>656849163</ParentID>
+        <CreationDate>1614974861</CreationDate>
+        <Category>0</Category>
+        <SalePrice>0</SalePrice>
+        <ObjectSaleType>0</ObjectSaleType>
+        <OwnershipCost>0</OwnershipCost>
+        <GroupID>
+          <UUID>5f1ea2fb-d489-44ce-a41d-a8d2a18c343c</UUID>
+        </GroupID>
+        <OwnerID>
+          <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+        </OwnerID>
+        <LastOwnerID>
+          <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+        </LastOwnerID>
+        <RezzerID>
+          <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+        </RezzerID>
+        <BaseMask>647168</BaseMask>
+        <OwnerMask>647168</OwnerMask>
+        <GroupMask>0</GroupMask>
+        <EveryoneMask>0</EveryoneMask>
+        <NextOwnerMask>532480</NextOwnerMask>
+        <Flags>None</Flags>
+        <CollisionSound>
+          <UUID>00000000-0000-0000-0000-000000000000</UUID>
+        </CollisionSound>
+        <CollisionSoundVolume>0</CollisionSoundVolume>
+        <MediaUrl />
+        <AttachedPos>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </AttachedPos>
+        <TextureAnimation></TextureAnimation>
+        <ParticleSystem></ParticleSystem>
+        <PayPrice0>-2</PayPrice0>
+        <PayPrice1>-2</PayPrice1>
+        <PayPrice2>-2</PayPrice2>
+        <PayPrice3>-2</PayPrice3>
+        <PayPrice4>-2</PayPrice4>
+        <Buoyancy>0</Buoyancy>
+        <Force>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </Force>
+        <Torque>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </Torque>
+        <VolumeDetectActive>false</VolumeDetectActive>
+        <PhysicsShapeType>0</PhysicsShapeType>
+        <CameraEyeOffset>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </CameraEyeOffset>
+        <CameraAtOffset>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </CameraAtOffset>
+        <SoundID>
+          <UUID>00000000-0000-0000-0000-000000000000</UUID>
+        </SoundID>
+        <SoundGain>0</SoundGain>
+        <SoundFlags>0</SoundFlags>
+        <SoundRadius>0</SoundRadius>
+        <SoundQueueing>false</SoundQueueing>
+      </SceneObjectPart>
+    </Part>
+    <Part>
+      <SceneObjectPart xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+        <AllowedDrop>false</AllowedDrop>
+        <CreatorID>
+          <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+        </CreatorID>
+        <FolderID>
+          <UUID>bf91be7c-5f87-461f-b52d-5b9f2816c3e7</UUID>
+        </FolderID>
+        <InventorySerial>0</InventorySerial>
+        <UUID>
+          <UUID>bf91be7c-5f87-461f-b52d-5b9f2816c3e7</UUID>
+        </UUID>
+        <LocalId>656849166</LocalId>
+        <Name>chimney#3</Name>
+        <Material>3</Material>
+        <PassTouches>false</PassTouches>
+        <PassCollisions>false</PassCollisions>
+        <RegionHandle>4008819395804416</RegionHandle>
+        <ScriptAccessPin>0</ScriptAccessPin>
+        <GroupPosition>
+          <X>192.3722</X>
+          <Y>185.4859</Y>
+          <Z>53.20147</Z>
+        </GroupPosition>
+        <OffsetPosition>
+          <X>-1.132295</X>
+          <Y>0.3477313</Y>
+          <Z>-0.002440205</Z>
+        </OffsetPosition>
+        <RotationOffset>
+          <X>3.72529E-07</X>
+          <Y>-7.301568E-07</Y>
+          <Z>5.513429E-07</Z>
+          <W>1</W>
+        </RotationOffset>
+        <Velocity>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </Velocity>
+        <AngularVelocity>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </AngularVelocity>
+        <Acceleration>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </Acceleration>
+        <Description />
+        <Color>
+          <R>0</R>
+          <G>0</G>
+          <B>0</B>
+          <A>255</A>
+        </Color>
+        <Text />
+        <SitName />
+        <TouchName />
+        <LinkNum>4</LinkNum>
+        <ClickAction>0</ClickAction>
+        <Shape>
+          <ProfileCurve>48</ProfileCurve>
+          <TextureEntry>h+/Ie5QJSpCReMgdt5xI9AAAAAAAAAAAgD8AAACAPwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==</TextureEntry>
+          <ExtraParams>ATAAEQAAACOa4j1sM0TAvhIl5Tfwy3UF</ExtraParams>
+          <PathBegin>0</PathBegin>
+          <PathCurve>32</PathCurve>
+          <PathEnd>0</PathEnd>
+          <PathRadiusOffset>0</PathRadiusOffset>
+          <PathRevolutions>0</PathRevolutions>
+          <PathScaleX>100</PathScaleX>
+          <PathScaleY>150</PathScaleY>
+          <PathShearX>0</PathShearX>
+          <PathShearY>0</PathShearY>
+          <PathSkew>0</PathSkew>
+          <PathTaperX>0</PathTaperX>
+          <PathTaperY>0</PathTaperY>
+          <PathTwist>0</PathTwist>
+          <PathTwistBegin>0</PathTwistBegin>
+          <PCode>9</PCode>
+          <ProfileBegin>0</ProfileBegin>
+          <ProfileEnd>0</ProfileEnd>
+          <ProfileHollow>0</ProfileHollow>
+          <State>0</State>
+          <LastAttachPoint>0</LastAttachPoint>
+          <ProfileShape>Circle</ProfileShape>
+          <HollowShape>Triangle</HollowShape>
+          <SculptTexture>
+            <UUID>239ae23d-6c33-44c0-be12-25e537f0cb75</UUID>
+          </SculptTexture>
+          <SculptType>5</SculptType>
+          <FlexiSoftness>0</FlexiSoftness>
+          <FlexiTension>0</FlexiTension>
+          <FlexiDrag>0</FlexiDrag>
+          <FlexiGravity>0</FlexiGravity>
+          <FlexiWind>0</FlexiWind>
+          <FlexiForceX>0</FlexiForceX>
+          <FlexiForceY>0</FlexiForceY>
+          <FlexiForceZ>0</FlexiForceZ>
+          <LightColorR>0</LightColorR>
+          <LightColorG>0</LightColorG>
+          <LightColorB>0</LightColorB>
+          <LightColorA>1</LightColorA>
+          <LightRadius>0</LightRadius>
+          <LightCutoff>0</LightCutoff>
+          <LightFalloff>0</LightFalloff>
+          <LightIntensity>1</LightIntensity>
+          <FlexiEntry>false</FlexiEntry>
+          <LightEntry>false</LightEntry>
+          <SculptEntry>true</SculptEntry>
+        </Shape>
+        <Scale>
+          <X>0.09761782</X>
+          <Y>0.06662145</Y>
+          <Z>3.201808</Z>
+        </Scale>
+        <SitTargetOrientation>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+          <W>1</W>
+        </SitTargetOrientation>
+        <SitTargetPosition>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </SitTargetPosition>
+        <SitTargetPositionLL>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </SitTargetPositionLL>
+        <SitTargetOrientationLL>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+          <W>1</W>
+        </SitTargetOrientationLL>
+        <ParentID>656849163</ParentID>
+        <CreationDate>1614974861</CreationDate>
+        <Category>0</Category>
+        <SalePrice>0</SalePrice>
+        <ObjectSaleType>0</ObjectSaleType>
+        <OwnershipCost>0</OwnershipCost>
+        <GroupID>
+          <UUID>5f1ea2fb-d489-44ce-a41d-a8d2a18c343c</UUID>
+        </GroupID>
+        <OwnerID>
+          <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+        </OwnerID>
+        <LastOwnerID>
+          <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+        </LastOwnerID>
+        <RezzerID>
+          <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+        </RezzerID>
+        <BaseMask>647168</BaseMask>
+        <OwnerMask>647168</OwnerMask>
+        <GroupMask>0</GroupMask>
+        <EveryoneMask>0</EveryoneMask>
+        <NextOwnerMask>532480</NextOwnerMask>
+        <Flags>None</Flags>
+        <CollisionSound>
+          <UUID>00000000-0000-0000-0000-000000000000</UUID>
+        </CollisionSound>
+        <CollisionSoundVolume>0</CollisionSoundVolume>
+        <MediaUrl />
+        <AttachedPos>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </AttachedPos>
+        <TextureAnimation></TextureAnimation>
+        <ParticleSystem></ParticleSystem>
+        <PayPrice0>-2</PayPrice0>
+        <PayPrice1>-2</PayPrice1>
+        <PayPrice2>-2</PayPrice2>
+        <PayPrice3>-2</PayPrice3>
+        <PayPrice4>-2</PayPrice4>
+        <Buoyancy>0</Buoyancy>
+        <Force>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </Force>
+        <Torque>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </Torque>
+        <VolumeDetectActive>false</VolumeDetectActive>
+        <PhysicsShapeType>0</PhysicsShapeType>
+        <CameraEyeOffset>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </CameraEyeOffset>
+        <CameraAtOffset>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </CameraAtOffset>
+        <SoundID>
+          <UUID>00000000-0000-0000-0000-000000000000</UUID>
+        </SoundID>
+        <SoundGain>0</SoundGain>
+        <SoundFlags>0</SoundFlags>
+        <SoundRadius>0</SoundRadius>
+        <SoundQueueing>false</SoundQueueing>
+      </SceneObjectPart>
+    </Part>
+    <Part>
+      <SceneObjectPart xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+        <AllowedDrop>false</AllowedDrop>
+        <CreatorID>
+          <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+        </CreatorID>
+        <FolderID>
+          <UUID>68d8d528-bb04-4332-8492-b3e1af9377cc</UUID>
+        </FolderID>
+        <InventorySerial>0</InventorySerial>
+        <UUID>
+          <UUID>68d8d528-bb04-4332-8492-b3e1af9377cc</UUID>
+        </UUID>
+        <LocalId>656849167</LocalId>
+        <Name>chimney#4</Name>
+        <Material>3</Material>
+        <PassTouches>false</PassTouches>
+        <PassCollisions>false</PassCollisions>
+        <RegionHandle>4008819395804416</RegionHandle>
+        <ScriptAccessPin>0</ScriptAccessPin>
+        <GroupPosition>
+          <X>192.3722</X>
+          <Y>185.4859</Y>
+          <Z>53.20147</Z>
+        </GroupPosition>
+        <OffsetPosition>
+          <X>-1.37856</X>
+          <Y>0.4236739</Y>
+          <Z>-0.006925707</Z>
+        </OffsetPosition>
+        <RotationOffset>
+          <X>-4.768369E-07</X>
+          <Y>-1.788138E-07</Y>
+          <Z>2.980231E-08</Z>
+          <W>1</W>
+        </RotationOffset>
+        <Velocity>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </Velocity>
+        <AngularVelocity>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </AngularVelocity>
+        <Acceleration>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </Acceleration>
+        <Description />
+        <Color>
+          <R>0</R>
+          <G>0</G>
+          <B>0</B>
+          <A>255</A>
+        </Color>
+        <Text />
+        <SitName />
+        <TouchName />
+        <LinkNum>5</LinkNum>
+        <ClickAction>0</ClickAction>
+        <Shape>
+          <ProfileCurve>48</ProfileCurve>
+          <TextureEntry>h+/Ie5QJSpCReMgdt5xI9AAAAAAAAAAAgD8AAACAPwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==</TextureEntry>
+          <ExtraParams>ATAAEQAAAPUS4ryy/EY3uhT9vK1l1B0F</ExtraParams>
+          <PathBegin>0</PathBegin>
+          <PathCurve>32</PathCurve>
+          <PathEnd>0</PathEnd>
+          <PathRadiusOffset>0</PathRadiusOffset>
+          <PathRevolutions>0</PathRevolutions>
+          <PathScaleX>100</PathScaleX>
+          <PathScaleY>150</PathScaleY>
+          <PathShearX>0</PathShearX>
+          <PathShearY>0</PathShearY>
+          <PathSkew>0</PathSkew>
+          <PathTaperX>0</PathTaperX>
+          <PathTaperY>0</PathTaperY>
+          <PathTwist>0</PathTwist>
+          <PathTwistBegin>0</PathTwistBegin>
+          <PCode>9</PCode>
+          <ProfileBegin>0</ProfileBegin>
+          <ProfileEnd>0</ProfileEnd>
+          <ProfileHollow>0</ProfileHollow>
+          <State>0</State>
+          <LastAttachPoint>0</LastAttachPoint>
+          <ProfileShape>Circle</ProfileShape>
+          <HollowShape>Triangle</HollowShape>
+          <SculptTexture>
+            <UUID>f512e2bc-b2fc-4637-ba14-fdbcad65d41d</UUID>
+          </SculptTexture>
+          <SculptType>5</SculptType>
+          <FlexiSoftness>0</FlexiSoftness>
+          <FlexiTension>0</FlexiTension>
+          <FlexiDrag>0</FlexiDrag>
+          <FlexiGravity>0</FlexiGravity>
+          <FlexiWind>0</FlexiWind>
+          <FlexiForceX>0</FlexiForceX>
+          <FlexiForceY>0</FlexiForceY>
+          <FlexiForceZ>0</FlexiForceZ>
+          <LightColorR>0</LightColorR>
+          <LightColorG>0</LightColorG>
+          <LightColorB>0</LightColorB>
+          <LightColorA>1</LightColorA>
+          <LightRadius>0</LightRadius>
+          <LightCutoff>0</LightCutoff>
+          <LightFalloff>0</LightFalloff>
+          <LightIntensity>1</LightIntensity>
+          <FlexiEntry>false</FlexiEntry>
+          <LightEntry>false</LightEntry>
+          <SculptEntry>true</SculptEntry>
+        </Shape>
+        <Scale>
+          <X>0.09753246</X>
+          <Y>0.06630227</Y>
+          <Z>3.20399</Z>
+        </Scale>
+        <SitTargetOrientation>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+          <W>1</W>
+        </SitTargetOrientation>
+        <SitTargetPosition>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </SitTargetPosition>
+        <SitTargetPositionLL>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </SitTargetPositionLL>
+        <SitTargetOrientationLL>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+          <W>1</W>
+        </SitTargetOrientationLL>
+        <ParentID>656849163</ParentID>
+        <CreationDate>1614974861</CreationDate>
+        <Category>0</Category>
+        <SalePrice>0</SalePrice>
+        <ObjectSaleType>0</ObjectSaleType>
+        <OwnershipCost>0</OwnershipCost>
+        <GroupID>
+          <UUID>5f1ea2fb-d489-44ce-a41d-a8d2a18c343c</UUID>
+        </GroupID>
+        <OwnerID>
+          <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+        </OwnerID>
+        <LastOwnerID>
+          <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+        </LastOwnerID>
+        <RezzerID>
+          <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+        </RezzerID>
+        <BaseMask>647168</BaseMask>
+        <OwnerMask>647168</OwnerMask>
+        <GroupMask>0</GroupMask>
+        <EveryoneMask>0</EveryoneMask>
+        <NextOwnerMask>532480</NextOwnerMask>
+        <Flags>None</Flags>
+        <CollisionSound>
+          <UUID>00000000-0000-0000-0000-000000000000</UUID>
+        </CollisionSound>
+        <CollisionSoundVolume>0</CollisionSoundVolume>
+        <MediaUrl />
+        <AttachedPos>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </AttachedPos>
+        <TextureAnimation></TextureAnimation>
+        <ParticleSystem></ParticleSystem>
+        <PayPrice0>-2</PayPrice0>
+        <PayPrice1>-2</PayPrice1>
+        <PayPrice2>-2</PayPrice2>
+        <PayPrice3>-2</PayPrice3>
+        <PayPrice4>-2</PayPrice4>
+        <Buoyancy>0</Buoyancy>
+        <Force>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </Force>
+        <Torque>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </Torque>
+        <VolumeDetectActive>false</VolumeDetectActive>
+        <PhysicsShapeType>0</PhysicsShapeType>
+        <CameraEyeOffset>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </CameraEyeOffset>
+        <CameraAtOffset>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </CameraAtOffset>
+        <SoundID>
+          <UUID>00000000-0000-0000-0000-000000000000</UUID>
+        </SoundID>
+        <SoundGain>0</SoundGain>
+        <SoundFlags>0</SoundFlags>
+        <SoundRadius>0</SoundRadius>
+        <SoundQueueing>false</SoundQueueing>
+      </SceneObjectPart>
+    </Part>
+    <Part>
+      <SceneObjectPart xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+        <AllowedDrop>false</AllowedDrop>
+        <CreatorID>
+          <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+        </CreatorID>
+        <FolderID>
+          <UUID>e4e46b78-6642-43f2-b485-f2443bd43d8f</UUID>
+        </FolderID>
+        <InventorySerial>0</InventorySerial>
+        <UUID>
+          <UUID>e4e46b78-6642-43f2-b485-f2443bd43d8f</UUID>
+        </UUID>
+        <LocalId>656849168</LocalId>
+        <Name>chimney#5</Name>
+        <Material>3</Material>
+        <PassTouches>false</PassTouches>
+        <PassCollisions>false</PassCollisions>
+        <RegionHandle>4008819395804416</RegionHandle>
+        <ScriptAccessPin>0</ScriptAccessPin>
+        <GroupPosition>
+          <X>192.3722</X>
+          <Y>185.4859</Y>
+          <Z>53.20147</Z>
+        </GroupPosition>
+        <OffsetPosition>
+          <X>-0.4480716</X>
+          <Y>0.138057</Y>
+          <Z>0.001414697</Z>
+        </OffsetPosition>
+        <RotationOffset>
+          <X>-4.619359E-07</X>
+          <Y>-8.046626E-07</Y>
+          <Z>1.013279E-06</Z>
+          <W>1</W>
+        </RotationOffset>
+        <Velocity>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </Velocity>
+        <AngularVelocity>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </AngularVelocity>
+        <Acceleration>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </Acceleration>
+        <Description />
+        <Color>
+          <R>0</R>
+          <G>0</G>
+          <B>0</B>
+          <A>255</A>
+        </Color>
+        <Text />
+        <SitName />
+        <TouchName />
+        <LinkNum>6</LinkNum>
+        <ClickAction>0</ClickAction>
+        <Shape>
+          <ProfileCurve>48</ProfileCurve>
+          <TextureEntry>h+/Ie5QJSpCReMgdt5xI9AAAAAAAAAAAgD8AAACAPwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==</TextureEntry>
+          <ExtraParams>ATAAEQAAAGxDf66v00cKtNe8v6iUVMwF</ExtraParams>
+          <PathBegin>0</PathBegin>
+          <PathCurve>32</PathCurve>
+          <PathEnd>0</PathEnd>
+          <PathRadiusOffset>0</PathRadiusOffset>
+          <PathRevolutions>0</PathRevolutions>
+          <PathScaleX>100</PathScaleX>
+          <PathScaleY>150</PathScaleY>
+          <PathShearX>0</PathShearX>
+          <PathShearY>0</PathShearY>
+          <PathSkew>0</PathSkew>
+          <PathTaperX>0</PathTaperX>
+          <PathTaperY>0</PathTaperY>
+          <PathTwist>0</PathTwist>
+          <PathTwistBegin>0</PathTwistBegin>
+          <PCode>9</PCode>
+          <ProfileBegin>0</ProfileBegin>
+          <ProfileEnd>0</ProfileEnd>
+          <ProfileHollow>0</ProfileHollow>
+          <State>0</State>
+          <LastAttachPoint>0</LastAttachPoint>
+          <ProfileShape>Circle</ProfileShape>
+          <HollowShape>Triangle</HollowShape>
+          <SculptTexture>
+            <UUID>6c437fae-afd3-470a-b4d7-bcbfa89454cc</UUID>
+          </SculptTexture>
+          <SculptType>5</SculptType>
+          <FlexiSoftness>0</FlexiSoftness>
+          <FlexiTension>0</FlexiTension>
+          <FlexiDrag>0</FlexiDrag>
+          <FlexiGravity>0</FlexiGravity>
+          <FlexiWind>0</FlexiWind>
+          <FlexiForceX>0</FlexiForceX>
+          <FlexiForceY>0</FlexiForceY>
+          <FlexiForceZ>0</FlexiForceZ>
+          <LightColorR>0</LightColorR>
+          <LightColorG>0</LightColorG>
+          <LightColorB>0</LightColorB>
+          <LightColorA>1</LightColorA>
+          <LightRadius>0</LightRadius>
+          <LightCutoff>0</LightCutoff>
+          <LightFalloff>0</LightFalloff>
+          <LightIntensity>1</LightIntensity>
+          <FlexiEntry>false</FlexiEntry>
+          <LightEntry>false</LightEntry>
+          <SculptEntry>true</SculptEntry>
+        </Shape>
+        <Scale>
+          <X>0.09719545</X>
+          <Y>0.06504537</Y>
+          <Z>3.206156</Z>
+        </Scale>
+        <SitTargetOrientation>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+          <W>1</W>
+        </SitTargetOrientation>
+        <SitTargetPosition>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </SitTargetPosition>
+        <SitTargetPositionLL>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </SitTargetPositionLL>
+        <SitTargetOrientationLL>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+          <W>1</W>
+        </SitTargetOrientationLL>
+        <ParentID>656849163</ParentID>
+        <CreationDate>1614974861</CreationDate>
+        <Category>0</Category>
+        <SalePrice>0</SalePrice>
+        <ObjectSaleType>0</ObjectSaleType>
+        <OwnershipCost>0</OwnershipCost>
+        <GroupID>
+          <UUID>5f1ea2fb-d489-44ce-a41d-a8d2a18c343c</UUID>
+        </GroupID>
+        <OwnerID>
+          <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+        </OwnerID>
+        <LastOwnerID>
+          <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+        </LastOwnerID>
+        <RezzerID>
+          <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+        </RezzerID>
+        <BaseMask>647168</BaseMask>
+        <OwnerMask>647168</OwnerMask>
+        <GroupMask>0</GroupMask>
+        <EveryoneMask>0</EveryoneMask>
+        <NextOwnerMask>532480</NextOwnerMask>
+        <Flags>None</Flags>
+        <CollisionSound>
+          <UUID>00000000-0000-0000-0000-000000000000</UUID>
+        </CollisionSound>
+        <CollisionSoundVolume>0</CollisionSoundVolume>
+        <MediaUrl />
+        <AttachedPos>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </AttachedPos>
+        <TextureAnimation></TextureAnimation>
+        <ParticleSystem></ParticleSystem>
+        <PayPrice0>-2</PayPrice0>
+        <PayPrice1>-2</PayPrice1>
+        <PayPrice2>-2</PayPrice2>
+        <PayPrice3>-2</PayPrice3>
+        <PayPrice4>-2</PayPrice4>
+        <Buoyancy>0</Buoyancy>
+        <Force>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </Force>
+        <Torque>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </Torque>
+        <VolumeDetectActive>false</VolumeDetectActive>
+        <PhysicsShapeType>0</PhysicsShapeType>
+        <CameraEyeOffset>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </CameraEyeOffset>
+        <CameraAtOffset>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </CameraAtOffset>
+        <SoundID>
+          <UUID>00000000-0000-0000-0000-000000000000</UUID>
+        </SoundID>
+        <SoundGain>0</SoundGain>
+        <SoundFlags>0</SoundFlags>
+        <SoundRadius>0</SoundRadius>
+        <SoundQueueing>false</SoundQueueing>
+      </SceneObjectPart>
+    </Part>
+    <Part>
+      <SceneObjectPart xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+        <AllowedDrop>false</AllowedDrop>
+        <CreatorID>
+          <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+        </CreatorID>
+        <FolderID>
+          <UUID>429193e8-f27e-4899-9a2a-af4b3956f74a</UUID>
+        </FolderID>
+        <InventorySerial>0</InventorySerial>
+        <UUID>
+          <UUID>429193e8-f27e-4899-9a2a-af4b3956f74a</UUID>
+        </UUID>
+        <LocalId>656849169</LocalId>
+        <Name>chimney#6</Name>
+        <Material>3</Material>
+        <PassTouches>false</PassTouches>
+        <PassCollisions>false</PassCollisions>
+        <RegionHandle>4008819395804416</RegionHandle>
+        <ScriptAccessPin>0</ScriptAccessPin>
+        <GroupPosition>
+          <X>192.3722</X>
+          <Y>185.4859</Y>
+          <Z>53.20147</Z>
+        </GroupPosition>
+        <OffsetPosition>
+          <X>-0.9030173</X>
+          <Y>0.2768701</Y>
+          <Z>-0.005361262</Z>
+        </OffsetPosition>
+        <RotationOffset>
+          <X>8.642672E-07</X>
+          <Y>-5.513429E-07</Y>
+          <Z>4.470348E-07</Z>
+          <W>1</W>
+        </RotationOffset>
+        <Velocity>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </Velocity>
+        <AngularVelocity>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </AngularVelocity>
+        <Acceleration>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </Acceleration>
+        <Description />
+        <Color>
+          <R>0</R>
+          <G>0</G>
+          <B>0</B>
+          <A>255</A>
+        </Color>
+        <Text />
+        <SitName />
+        <TouchName />
+        <LinkNum>7</LinkNum>
+        <ClickAction>0</ClickAction>
+        <Shape>
+          <ProfileCurve>48</ProfileCurve>
+          <TextureEntry>h+/Ie5QJSpCReMgdt5xI9AAAAAAAAAAAgD8AAACAPwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==</TextureEntry>
+          <ExtraParams>ATAAEQAAAHxUAW2NJkktqIY9iOH/d98F</ExtraParams>
+          <PathBegin>0</PathBegin>
+          <PathCurve>32</PathCurve>
+          <PathEnd>0</PathEnd>
+          <PathRadiusOffset>0</PathRadiusOffset>
+          <PathRevolutions>0</PathRevolutions>
+          <PathScaleX>100</PathScaleX>
+          <PathScaleY>150</PathScaleY>
+          <PathShearX>0</PathShearX>
+          <PathShearY>0</PathShearY>
+          <PathSkew>0</PathSkew>
+          <PathTaperX>0</PathTaperX>
+          <PathTaperY>0</PathTaperY>
+          <PathTwist>0</PathTwist>
+          <PathTwistBegin>0</PathTwistBegin>
+          <PCode>9</PCode>
+          <ProfileBegin>0</ProfileBegin>
+          <ProfileEnd>0</ProfileEnd>
+          <ProfileHollow>0</ProfileHollow>
+          <State>0</State>
+          <LastAttachPoint>0</LastAttachPoint>
+          <ProfileShape>Circle</ProfileShape>
+          <HollowShape>Triangle</HollowShape>
+          <SculptTexture>
+            <UUID>7c54016d-8d26-492d-a886-3d88e1ff77df</UUID>
+          </SculptTexture>
+          <SculptType>5</SculptType>
+          <FlexiSoftness>0</FlexiSoftness>
+          <FlexiTension>0</FlexiTension>
+          <FlexiDrag>0</FlexiDrag>
+          <FlexiGravity>0</FlexiGravity>
+          <FlexiWind>0</FlexiWind>
+          <FlexiForceX>0</FlexiForceX>
+          <FlexiForceY>0</FlexiForceY>
+          <FlexiForceZ>0</FlexiForceZ>
+          <LightColorR>0</LightColorR>
+          <LightColorG>0</LightColorG>
+          <LightColorB>0</LightColorB>
+          <LightColorA>1</LightColorA>
+          <LightRadius>0</LightRadius>
+          <LightCutoff>0</LightCutoff>
+          <LightFalloff>0</LightFalloff>
+          <LightIntensity>1</LightIntensity>
+          <FlexiEntry>false</FlexiEntry>
+          <LightEntry>false</LightEntry>
+          <SculptEntry>true</SculptEntry>
+        </Shape>
+        <Scale>
+          <X>0.09777185</X>
+          <Y>0.06719667</Y>
+          <Z>3.20947</Z>
+        </Scale>
+        <SitTargetOrientation>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+          <W>1</W>
+        </SitTargetOrientation>
+        <SitTargetPosition>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </SitTargetPosition>
+        <SitTargetPositionLL>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </SitTargetPositionLL>
+        <SitTargetOrientationLL>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+          <W>1</W>
+        </SitTargetOrientationLL>
+        <ParentID>656849163</ParentID>
+        <CreationDate>1614974861</CreationDate>
+        <Category>0</Category>
+        <SalePrice>0</SalePrice>
+        <ObjectSaleType>0</ObjectSaleType>
+        <OwnershipCost>0</OwnershipCost>
+        <GroupID>
+          <UUID>5f1ea2fb-d489-44ce-a41d-a8d2a18c343c</UUID>
+        </GroupID>
+        <OwnerID>
+          <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+        </OwnerID>
+        <LastOwnerID>
+          <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+        </LastOwnerID>
+        <RezzerID>
+          <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+        </RezzerID>
+        <BaseMask>647168</BaseMask>
+        <OwnerMask>647168</OwnerMask>
+        <GroupMask>0</GroupMask>
+        <EveryoneMask>0</EveryoneMask>
+        <NextOwnerMask>532480</NextOwnerMask>
+        <Flags>None</Flags>
+        <CollisionSound>
+          <UUID>00000000-0000-0000-0000-000000000000</UUID>
+        </CollisionSound>
+        <CollisionSoundVolume>0</CollisionSoundVolume>
+        <MediaUrl />
+        <AttachedPos>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </AttachedPos>
+        <TextureAnimation></TextureAnimation>
+        <ParticleSystem></ParticleSystem>
+        <PayPrice0>-2</PayPrice0>
+        <PayPrice1>-2</PayPrice1>
+        <PayPrice2>-2</PayPrice2>
+        <PayPrice3>-2</PayPrice3>
+        <PayPrice4>-2</PayPrice4>
+        <Buoyancy>0</Buoyancy>
+        <Force>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </Force>
+        <Torque>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </Torque>
+        <VolumeDetectActive>false</VolumeDetectActive>
+        <PhysicsShapeType>0</PhysicsShapeType>
+        <CameraEyeOffset>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </CameraEyeOffset>
+        <CameraAtOffset>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </CameraAtOffset>
+        <SoundID>
+          <UUID>00000000-0000-0000-0000-000000000000</UUID>
+        </SoundID>
+        <SoundGain>0</SoundGain>
+        <SoundFlags>0</SoundFlags>
+        <SoundRadius>0</SoundRadius>
+        <SoundQueueing>false</SoundQueueing>
+      </SceneObjectPart>
+    </Part>
+    <Part>
+      <SceneObjectPart xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+        <AllowedDrop>false</AllowedDrop>
+        <CreatorID>
+          <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+        </CreatorID>
+        <FolderID>
+          <UUID>85efdd3d-b1ca-4909-9ed6-d402ab78edec</UUID>
+        </FolderID>
+        <InventorySerial>0</InventorySerial>
+        <UUID>
+          <UUID>85efdd3d-b1ca-4909-9ed6-d402ab78edec</UUID>
+        </UUID>
+        <LocalId>656849170</LocalId>
+        <Name>chimney#7</Name>
+        <Material>3</Material>
+        <PassTouches>false</PassTouches>
+        <PassCollisions>false</PassCollisions>
+        <RegionHandle>4008819395804416</RegionHandle>
+        <ScriptAccessPin>0</ScriptAccessPin>
+        <GroupPosition>
+          <X>192.3722</X>
+          <Y>185.4859</Y>
+          <Z>53.20147</Z>
+        </GroupPosition>
+        <OffsetPosition>
+          <X>-0.3939021</X>
+          <Y>0.1439624</Y>
+          <Z>0.02700207</Z>
+        </OffsetPosition>
+        <RotationOffset>
+          <X>0.3992663</X>
+          <Y>-0.5051889</Y>
+          <Z>0.433439</Z>
+          <W>0.6304771</W>
+        </RotationOffset>
+        <Velocity>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </Velocity>
+        <AngularVelocity>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </AngularVelocity>
+        <Acceleration>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </Acceleration>
+        <Description />
+        <Color>
+          <R>0</R>
+          <G>0</G>
+          <B>0</B>
+          <A>255</A>
+        </Color>
+        <Text />
+        <SitName />
+        <TouchName />
+        <LinkNum>8</LinkNum>
+        <ClickAction>0</ClickAction>
+        <Shape>
+          <ProfileCurve>48</ProfileCurve>
+          <TextureEntry>h+/Ie5QJSpCReMgdt5xI9AAAAAAAAAAAgD8AAACAPwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==</TextureEntry>
+          <ExtraParams>ATAAEQAAAHnOjVn/KEodqMxlvNH+KmcF</ExtraParams>
+          <PathBegin>0</PathBegin>
+          <PathCurve>32</PathCurve>
+          <PathEnd>0</PathEnd>
+          <PathRadiusOffset>0</PathRadiusOffset>
+          <PathRevolutions>0</PathRevolutions>
+          <PathScaleX>100</PathScaleX>
+          <PathScaleY>150</PathScaleY>
+          <PathShearX>0</PathShearX>
+          <PathShearY>0</PathShearY>
+          <PathSkew>0</PathSkew>
+          <PathTaperX>0</PathTaperX>
+          <PathTaperY>0</PathTaperY>
+          <PathTwist>0</PathTwist>
+          <PathTwistBegin>0</PathTwistBegin>
+          <PCode>9</PCode>
+          <ProfileBegin>0</ProfileBegin>
+          <ProfileEnd>0</ProfileEnd>
+          <ProfileHollow>0</ProfileHollow>
+          <State>0</State>
+          <LastAttachPoint>0</LastAttachPoint>
+          <ProfileShape>Circle</ProfileShape>
+          <HollowShape>Triangle</HollowShape>
+          <SculptTexture>
+            <UUID>79ce8d59-ff28-4a1d-a8cc-65bcd1fe2a67</UUID>
+          </SculptTexture>
+          <SculptType>5</SculptType>
+          <FlexiSoftness>0</FlexiSoftness>
+          <FlexiTension>0</FlexiTension>
+          <FlexiDrag>0</FlexiDrag>
+          <FlexiGravity>0</FlexiGravity>
+          <FlexiWind>0</FlexiWind>
+          <FlexiForceX>0</FlexiForceX>
+          <FlexiForceY>0</FlexiForceY>
+          <FlexiForceZ>0</FlexiForceZ>
+          <LightColorR>0</LightColorR>
+          <LightColorG>0</LightColorG>
+          <LightColorB>0</LightColorB>
+          <LightColorA>1</LightColorA>
+          <LightRadius>0</LightRadius>
+          <LightCutoff>0</LightCutoff>
+          <LightFalloff>0</LightFalloff>
+          <LightIntensity>1</LightIntensity>
+          <FlexiEntry>false</FlexiEntry>
+          <LightEntry>false</LightEntry>
+          <SculptEntry>true</SculptEntry>
+        </Shape>
+        <Scale>
+          <X>3.298019</X>
+          <Y>2.354757</Y>
+          <Z>0.545938</Z>
+        </Scale>
+        <SitTargetOrientation>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+          <W>1</W>
+        </SitTargetOrientation>
+        <SitTargetPosition>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </SitTargetPosition>
+        <SitTargetPositionLL>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </SitTargetPositionLL>
+        <SitTargetOrientationLL>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+          <W>1</W>
+        </SitTargetOrientationLL>
+        <ParentID>656849163</ParentID>
+        <CreationDate>1614974861</CreationDate>
+        <Category>0</Category>
+        <SalePrice>0</SalePrice>
+        <ObjectSaleType>0</ObjectSaleType>
+        <OwnershipCost>0</OwnershipCost>
+        <GroupID>
+          <UUID>5f1ea2fb-d489-44ce-a41d-a8d2a18c343c</UUID>
+        </GroupID>
+        <OwnerID>
+          <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+        </OwnerID>
+        <LastOwnerID>
+          <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+        </LastOwnerID>
+        <RezzerID>
+          <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+        </RezzerID>
+        <BaseMask>647168</BaseMask>
+        <OwnerMask>647168</OwnerMask>
+        <GroupMask>0</GroupMask>
+        <EveryoneMask>0</EveryoneMask>
+        <NextOwnerMask>532480</NextOwnerMask>
+        <Flags>None</Flags>
+        <CollisionSound>
+          <UUID>00000000-0000-0000-0000-000000000000</UUID>
+        </CollisionSound>
+        <CollisionSoundVolume>0</CollisionSoundVolume>
+        <MediaUrl />
+        <AttachedPos>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </AttachedPos>
+        <TextureAnimation></TextureAnimation>
+        <ParticleSystem></ParticleSystem>
+        <PayPrice0>-2</PayPrice0>
+        <PayPrice1>-2</PayPrice1>
+        <PayPrice2>-2</PayPrice2>
+        <PayPrice3>-2</PayPrice3>
+        <PayPrice4>-2</PayPrice4>
+        <Buoyancy>0</Buoyancy>
+        <Force>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </Force>
+        <Torque>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </Torque>
+        <VolumeDetectActive>false</VolumeDetectActive>
+        <PhysicsShapeType>0</PhysicsShapeType>
+        <CameraEyeOffset>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </CameraEyeOffset>
+        <CameraAtOffset>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </CameraAtOffset>
+        <SoundID>
+          <UUID>00000000-0000-0000-0000-000000000000</UUID>
+        </SoundID>
+        <SoundGain>0</SoundGain>
+        <SoundFlags>0</SoundFlags>
+        <SoundRadius>0</SoundRadius>
+        <SoundQueueing>false</SoundQueueing>
+      </SceneObjectPart>
+    </Part>
+    <Part>
+      <SceneObjectPart xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+        <AllowedDrop>false</AllowedDrop>
+        <CreatorID>
+          <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+        </CreatorID>
+        <FolderID>
+          <UUID>19364569-1022-443e-a26e-72dc2a8c0a1d</UUID>
+        </FolderID>
+        <InventorySerial>0</InventorySerial>
+        <UUID>
+          <UUID>19364569-1022-443e-a26e-72dc2a8c0a1d</UUID>
+        </UUID>
+        <LocalId>656849171</LocalId>
+        <Name>chimney#8</Name>
+        <Material>3</Material>
+        <PassTouches>false</PassTouches>
+        <PassCollisions>false</PassCollisions>
+        <RegionHandle>4008819395804416</RegionHandle>
+        <ScriptAccessPin>0</ScriptAccessPin>
+        <GroupPosition>
+          <X>192.3722</X>
+          <Y>185.4859</Y>
+          <Z>53.20147</Z>
+        </GroupPosition>
+        <OffsetPosition>
+          <X>0.2292231</X>
+          <Y>-0.07052802</Y>
+          <Z>-0.002538951</Z>
+        </OffsetPosition>
+        <RotationOffset>
+          <X>-1.057982E-06</X>
+          <Y>-1.490115E-07</Y>
+          <Z>1.490115E-08</Z>
+          <W>1</W>
+        </RotationOffset>
+        <Velocity>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </Velocity>
+        <AngularVelocity>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </AngularVelocity>
+        <Acceleration>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </Acceleration>
+        <Description />
+        <Color>
+          <R>0</R>
+          <G>0</G>
+          <B>0</B>
+          <A>255</A>
+        </Color>
+        <Text />
+        <SitName />
+        <TouchName />
+        <LinkNum>9</LinkNum>
+        <ClickAction>0</ClickAction>
+        <Shape>
+          <ProfileCurve>48</ProfileCurve>
+          <TextureEntry>h+/Ie5QJSpCReMgdt5xI9AAAAAAAAAAAgD8AAACAPwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==</TextureEntry>
+          <ExtraParams>ATAAEQAAANpId60CD02/hLW7d6YcJVwF</ExtraParams>
+          <PathBegin>0</PathBegin>
+          <PathCurve>32</PathCurve>
+          <PathEnd>0</PathEnd>
+          <PathRadiusOffset>0</PathRadiusOffset>
+          <PathRevolutions>0</PathRevolutions>
+          <PathScaleX>100</PathScaleX>
+          <PathScaleY>150</PathScaleY>
+          <PathShearX>0</PathShearX>
+          <PathShearY>0</PathShearY>
+          <PathSkew>0</PathSkew>
+          <PathTaperX>0</PathTaperX>
+          <PathTaperY>0</PathTaperY>
+          <PathTwist>0</PathTwist>
+          <PathTwistBegin>0</PathTwistBegin>
+          <PCode>9</PCode>
+          <ProfileBegin>0</ProfileBegin>
+          <ProfileEnd>0</ProfileEnd>
+          <ProfileHollow>0</ProfileHollow>
+          <State>0</State>
+          <LastAttachPoint>0</LastAttachPoint>
+          <ProfileShape>Circle</ProfileShape>
+          <HollowShape>Triangle</HollowShape>
+          <SculptTexture>
+            <UUID>da4877ad-020f-4dbf-84b5-bb77a61c255c</UUID>
+          </SculptTexture>
+          <SculptType>5</SculptType>
+          <FlexiSoftness>0</FlexiSoftness>
+          <FlexiTension>0</FlexiTension>
+          <FlexiDrag>0</FlexiDrag>
+          <FlexiGravity>0</FlexiGravity>
+          <FlexiWind>0</FlexiWind>
+          <FlexiForceX>0</FlexiForceX>
+          <FlexiForceY>0</FlexiForceY>
+          <FlexiForceZ>0</FlexiForceZ>
+          <LightColorR>0</LightColorR>
+          <LightColorG>0</LightColorG>
+          <LightColorB>0</LightColorB>
+          <LightColorA>1</LightColorA>
+          <LightRadius>0</LightRadius>
+          <LightCutoff>0</LightCutoff>
+          <LightFalloff>0</LightFalloff>
+          <LightIntensity>1</LightIntensity>
+          <FlexiEntry>false</FlexiEntry>
+          <LightEntry>false</LightEntry>
+          <SculptEntry>true</SculptEntry>
+        </Shape>
+        <Scale>
+          <X>0.09732011</X>
+          <Y>0.06549789</Y>
+          <Z>3.223294</Z>
+        </Scale>
+        <SitTargetOrientation>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+          <W>1</W>
+        </SitTargetOrientation>
+        <SitTargetPosition>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </SitTargetPosition>
+        <SitTargetPositionLL>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </SitTargetPositionLL>
+        <SitTargetOrientationLL>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+          <W>1</W>
+        </SitTargetOrientationLL>
+        <ParentID>656849163</ParentID>
+        <CreationDate>1614974861</CreationDate>
+        <Category>0</Category>
+        <SalePrice>0</SalePrice>
+        <ObjectSaleType>0</ObjectSaleType>
+        <OwnershipCost>0</OwnershipCost>
+        <GroupID>
+          <UUID>5f1ea2fb-d489-44ce-a41d-a8d2a18c343c</UUID>
+        </GroupID>
+        <OwnerID>
+          <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+        </OwnerID>
+        <LastOwnerID>
+          <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+        </LastOwnerID>
+        <RezzerID>
+          <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+        </RezzerID>
+        <BaseMask>647168</BaseMask>
+        <OwnerMask>647168</OwnerMask>
+        <GroupMask>0</GroupMask>
+        <EveryoneMask>0</EveryoneMask>
+        <NextOwnerMask>532480</NextOwnerMask>
+        <Flags>None</Flags>
+        <CollisionSound>
+          <UUID>00000000-0000-0000-0000-000000000000</UUID>
+        </CollisionSound>
+        <CollisionSoundVolume>0</CollisionSoundVolume>
+        <MediaUrl />
+        <AttachedPos>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </AttachedPos>
+        <TextureAnimation></TextureAnimation>
+        <ParticleSystem></ParticleSystem>
+        <PayPrice0>-2</PayPrice0>
+        <PayPrice1>-2</PayPrice1>
+        <PayPrice2>-2</PayPrice2>
+        <PayPrice3>-2</PayPrice3>
+        <PayPrice4>-2</PayPrice4>
+        <Buoyancy>0</Buoyancy>
+        <Force>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </Force>
+        <Torque>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </Torque>
+        <VolumeDetectActive>false</VolumeDetectActive>
+        <PhysicsShapeType>0</PhysicsShapeType>
+        <CameraEyeOffset>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </CameraEyeOffset>
+        <CameraAtOffset>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </CameraAtOffset>
+        <SoundID>
+          <UUID>00000000-0000-0000-0000-000000000000</UUID>
+        </SoundID>
+        <SoundGain>0</SoundGain>
+        <SoundFlags>0</SoundFlags>
+        <SoundRadius>0</SoundRadius>
+        <SoundQueueing>false</SoundQueueing>
+      </SceneObjectPart>
+    </Part>
+    <Part>
+      <SceneObjectPart xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+        <AllowedDrop>false</AllowedDrop>
+        <CreatorID>
+          <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+        </CreatorID>
+        <FolderID>
+          <UUID>1ba9e6aa-3157-405e-8b41-bfa411d0dc11</UUID>
+        </FolderID>
+        <InventorySerial>0</InventorySerial>
+        <UUID>
+          <UUID>1ba9e6aa-3157-405e-8b41-bfa411d0dc11</UUID>
+        </UUID>
+        <LocalId>656849172</LocalId>
+        <Name>chimney#9</Name>
+        <Material>3</Material>
+        <PassTouches>false</PassTouches>
+        <PassCollisions>false</PassCollisions>
+        <RegionHandle>4008819395804416</RegionHandle>
+        <ScriptAccessPin>0</ScriptAccessPin>
+        <GroupPosition>
+          <X>192.3722</X>
+          <Y>185.4859</Y>
+          <Z>53.20147</Z>
+        </GroupPosition>
+        <OffsetPosition>
+          <X>0.4840323</X>
+          <Y>1.179269</Y>
+          <Z>-1.699032</Z>
+        </OffsetPosition>
+        <RotationOffset>
+          <X>0.3992664</X>
+          <Y>-0.5051888</Y>
+          <Z>0.4334387</Z>
+          <W>0.6304774</W>
+        </RotationOffset>
+        <Velocity>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </Velocity>
+        <AngularVelocity>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </AngularVelocity>
+        <Acceleration>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </Acceleration>
+        <Description />
+        <Color>
+          <R>0</R>
+          <G>0</G>
+          <B>0</B>
+          <A>255</A>
+        </Color>
+        <Text />
+        <SitName />
+        <TouchName />
+        <LinkNum>10</LinkNum>
+        <ClickAction>0</ClickAction>
+        <Shape>
+          <ProfileCurve>48</ProfileCurve>
+          <TextureEntry>Ry6MgBGgRBGudB5ZNCtsbAHiYjvY939FL6jOso90WtLkAAAAAAAAAACAPwAAAIA/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA</TextureEntry>
+          <ExtraParams>ATAAEQAAAL9eJHIycUIHsuxiEOfrNNwF</ExtraParams>
+          <PathBegin>0</PathBegin>
+          <PathCurve>32</PathCurve>
+          <PathEnd>0</PathEnd>
+          <PathRadiusOffset>0</PathRadiusOffset>
+          <PathRevolutions>0</PathRevolutions>
+          <PathScaleX>100</PathScaleX>
+          <PathScaleY>150</PathScaleY>
+          <PathShearX>0</PathShearX>
+          <PathShearY>0</PathShearY>
+          <PathSkew>0</PathSkew>
+          <PathTaperX>0</PathTaperX>
+          <PathTaperY>0</PathTaperY>
+          <PathTwist>0</PathTwist>
+          <PathTwistBegin>0</PathTwistBegin>
+          <PCode>9</PCode>
+          <ProfileBegin>0</ProfileBegin>
+          <ProfileEnd>0</ProfileEnd>
+          <ProfileHollow>27500</ProfileHollow>
+          <State>0</State>
+          <LastAttachPoint>0</LastAttachPoint>
+          <ProfileShape>Circle</ProfileShape>
+          <HollowShape>Triangle</HollowShape>
+          <SculptTexture>
+            <UUID>bf5e2472-3271-4207-b2ec-6210e7eb34dc</UUID>
+          </SculptTexture>
+          <SculptType>5</SculptType>
+          <FlexiSoftness>0</FlexiSoftness>
+          <FlexiTension>0</FlexiTension>
+          <FlexiDrag>0</FlexiDrag>
+          <FlexiGravity>0</FlexiGravity>
+          <FlexiWind>0</FlexiWind>
+          <FlexiForceX>0</FlexiForceX>
+          <FlexiForceY>0</FlexiForceY>
+          <FlexiForceZ>0</FlexiForceZ>
+          <LightColorR>0</LightColorR>
+          <LightColorG>0</LightColorG>
+          <LightColorB>0</LightColorB>
+          <LightColorA>1</LightColorA>
+          <LightRadius>0</LightRadius>
+          <LightCutoff>0</LightCutoff>
+          <LightFalloff>0</LightFalloff>
+          <LightIntensity>1</LightIntensity>
+          <FlexiEntry>false</FlexiEntry>
+          <LightEntry>false</LightEntry>
+          <SculptEntry>true</SculptEntry>
+        </Shape>
+        <Scale>
+          <X>0.1123862</X>
+          <Y>0.7297896</Y>
+          <Z>1.93197</Z>
+        </Scale>
+        <SitTargetOrientation>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+          <W>1</W>
+        </SitTargetOrientation>
+        <SitTargetPosition>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </SitTargetPosition>
+        <SitTargetPositionLL>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </SitTargetPositionLL>
+        <SitTargetOrientationLL>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+          <W>1</W>
+        </SitTargetOrientationLL>
+        <ParentID>656849163</ParentID>
+        <CreationDate>1614974861</CreationDate>
+        <Category>0</Category>
+        <SalePrice>0</SalePrice>
+        <ObjectSaleType>0</ObjectSaleType>
+        <OwnershipCost>0</OwnershipCost>
+        <GroupID>
+          <UUID>5f1ea2fb-d489-44ce-a41d-a8d2a18c343c</UUID>
+        </GroupID>
+        <OwnerID>
+          <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+        </OwnerID>
+        <LastOwnerID>
+          <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+        </LastOwnerID>
+        <RezzerID>
+          <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+        </RezzerID>
+        <BaseMask>647168</BaseMask>
+        <OwnerMask>647168</OwnerMask>
+        <GroupMask>0</GroupMask>
+        <EveryoneMask>0</EveryoneMask>
+        <NextOwnerMask>532480</NextOwnerMask>
+        <Flags>None</Flags>
+        <CollisionSound>
+          <UUID>00000000-0000-0000-0000-000000000000</UUID>
+        </CollisionSound>
+        <CollisionSoundVolume>0</CollisionSoundVolume>
+        <MediaUrl />
+        <AttachedPos>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </AttachedPos>
+        <TextureAnimation></TextureAnimation>
+        <ParticleSystem></ParticleSystem>
+        <PayPrice0>-2</PayPrice0>
+        <PayPrice1>-2</PayPrice1>
+        <PayPrice2>-2</PayPrice2>
+        <PayPrice3>-2</PayPrice3>
+        <PayPrice4>-2</PayPrice4>
+        <Buoyancy>0</Buoyancy>
+        <Force>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </Force>
+        <Torque>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </Torque>
+        <VolumeDetectActive>false</VolumeDetectActive>
+        <PhysicsShapeType>0</PhysicsShapeType>
+        <CameraEyeOffset>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </CameraEyeOffset>
+        <CameraAtOffset>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </CameraAtOffset>
+        <SoundID>
+          <UUID>00000000-0000-0000-0000-000000000000</UUID>
+        </SoundID>
+        <SoundGain>0</SoundGain>
+        <SoundFlags>0</SoundFlags>
+        <SoundRadius>0</SoundRadius>
+        <SoundQueueing>false</SoundQueueing>
+      </SceneObjectPart>
+    </Part>
+    <Part>
+      <SceneObjectPart xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+        <AllowedDrop>false</AllowedDrop>
+        <CreatorID>
+          <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+        </CreatorID>
+        <FolderID>
+          <UUID>788cc750-253b-4da6-a9f5-47361c985b8a</UUID>
+        </FolderID>
+        <InventorySerial>0</InventorySerial>
+        <UUID>
+          <UUID>788cc750-253b-4da6-a9f5-47361c985b8a</UUID>
+        </UUID>
+        <LocalId>656849173</LocalId>
+        <Name>chimney#10</Name>
+        <Material>3</Material>
+        <PassTouches>false</PassTouches>
+        <PassCollisions>false</PassCollisions>
+        <RegionHandle>4008819395804416</RegionHandle>
+        <ScriptAccessPin>0</ScriptAccessPin>
+        <GroupPosition>
+          <X>192.3722</X>
+          <Y>185.4859</Y>
+          <Z>53.20147</Z>
+        </GroupPosition>
+        <OffsetPosition>
+          <X>0.2152564</X>
+          <Y>0.2546893</Y>
+          <Z>-1.566718</Z>
+        </OffsetPosition>
+        <RotationOffset>
+          <X>0.3992662</X>
+          <Y>-0.5051889</Y>
+          <Z>0.433439</Z>
+          <W>0.6304772</W>
+        </RotationOffset>
+        <Velocity>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </Velocity>
+        <AngularVelocity>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </AngularVelocity>
+        <Acceleration>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </Acceleration>
+        <Description />
+        <Color>
+          <R>0</R>
+          <G>0</G>
+          <B>0</B>
+          <A>255</A>
+        </Color>
+        <Text />
+        <SitName />
+        <TouchName />
+        <LinkNum>11</LinkNum>
+        <ClickAction>0</ClickAction>
+        <Shape>
+          <ProfileCurve>48</ProfileCurve>
+          <TextureEntry>4mI72Pd/RS+ozrKPdFrS5AAAAAAAAAAAgD8AAACAPwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==</TextureEntry>
+          <ExtraParams>ATAAEQAAADreHE7/S0lDkN5QE5v0CKsF</ExtraParams>
+          <PathBegin>0</PathBegin>
+          <PathCurve>32</PathCurve>
+          <PathEnd>0</PathEnd>
+          <PathRadiusOffset>0</PathRadiusOffset>
+          <PathRevolutions>0</PathRevolutions>
+          <PathScaleX>100</PathScaleX>
+          <PathScaleY>150</PathScaleY>
+          <PathShearX>0</PathShearX>
+          <PathShearY>0</PathShearY>
+          <PathSkew>0</PathSkew>
+          <PathTaperX>0</PathTaperX>
+          <PathTaperY>0</PathTaperY>
+          <PathTwist>0</PathTwist>
+          <PathTwistBegin>0</PathTwistBegin>
+          <PCode>9</PCode>
+          <ProfileBegin>0</ProfileBegin>
+          <ProfileEnd>0</ProfileEnd>
+          <ProfileHollow>0</ProfileHollow>
+          <State>0</State>
+          <LastAttachPoint>0</LastAttachPoint>
+          <ProfileShape>Circle</ProfileShape>
+          <HollowShape>Triangle</HollowShape>
+          <SculptTexture>
+            <UUID>3ade1c4e-ff4b-4943-90de-50139bf408ab</UUID>
+          </SculptTexture>
+          <SculptType>5</SculptType>
+          <FlexiSoftness>0</FlexiSoftness>
+          <FlexiTension>0</FlexiTension>
+          <FlexiDrag>0</FlexiDrag>
+          <FlexiGravity>0</FlexiGravity>
+          <FlexiWind>0</FlexiWind>
+          <FlexiForceX>0</FlexiForceX>
+          <FlexiForceY>0</FlexiForceY>
+          <FlexiForceZ>0</FlexiForceZ>
+          <LightColorR>0</LightColorR>
+          <LightColorG>0</LightColorG>
+          <LightColorB>0</LightColorB>
+          <LightColorA>1</LightColorA>
+          <LightRadius>0</LightRadius>
+          <LightCutoff>0</LightCutoff>
+          <LightFalloff>0</LightFalloff>
+          <LightIntensity>1</LightIntensity>
+          <FlexiEntry>false</FlexiEntry>
+          <LightEntry>false</LightEntry>
+          <SculptEntry>true</SculptEntry>
+        </Shape>
+        <Scale>
+          <X>0.1531409</X>
+          <Y>1.227246</Y>
+          <Z>0.23785</Z>
+        </Scale>
+        <SitTargetOrientation>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+          <W>1</W>
+        </SitTargetOrientation>
+        <SitTargetPosition>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </SitTargetPosition>
+        <SitTargetPositionLL>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </SitTargetPositionLL>
+        <SitTargetOrientationLL>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+          <W>1</W>
+        </SitTargetOrientationLL>
+        <ParentID>656849163</ParentID>
+        <CreationDate>1614974861</CreationDate>
+        <Category>0</Category>
+        <SalePrice>0</SalePrice>
+        <ObjectSaleType>0</ObjectSaleType>
+        <OwnershipCost>0</OwnershipCost>
+        <GroupID>
+          <UUID>5f1ea2fb-d489-44ce-a41d-a8d2a18c343c</UUID>
+        </GroupID>
+        <OwnerID>
+          <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+        </OwnerID>
+        <LastOwnerID>
+          <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+        </LastOwnerID>
+        <RezzerID>
+          <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+        </RezzerID>
+        <BaseMask>647168</BaseMask>
+        <OwnerMask>647168</OwnerMask>
+        <GroupMask>0</GroupMask>
+        <EveryoneMask>0</EveryoneMask>
+        <NextOwnerMask>532480</NextOwnerMask>
+        <Flags>None</Flags>
+        <CollisionSound>
+          <UUID>00000000-0000-0000-0000-000000000000</UUID>
+        </CollisionSound>
+        <CollisionSoundVolume>0</CollisionSoundVolume>
+        <MediaUrl />
+        <AttachedPos>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </AttachedPos>
+        <TextureAnimation></TextureAnimation>
+        <ParticleSystem></ParticleSystem>
+        <PayPrice0>-2</PayPrice0>
+        <PayPrice1>-2</PayPrice1>
+        <PayPrice2>-2</PayPrice2>
+        <PayPrice3>-2</PayPrice3>
+        <PayPrice4>-2</PayPrice4>
+        <Buoyancy>0</Buoyancy>
+        <Force>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </Force>
+        <Torque>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </Torque>
+        <VolumeDetectActive>false</VolumeDetectActive>
+        <PhysicsShapeType>0</PhysicsShapeType>
+        <CameraEyeOffset>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </CameraEyeOffset>
+        <CameraAtOffset>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </CameraAtOffset>
+        <SoundID>
+          <UUID>00000000-0000-0000-0000-000000000000</UUID>
+        </SoundID>
+        <SoundGain>0</SoundGain>
+        <SoundFlags>0</SoundFlags>
+        <SoundRadius>0</SoundRadius>
+        <SoundQueueing>false</SoundQueueing>
+      </SceneObjectPart>
+    </Part>
+    <Part>
+      <SceneObjectPart xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+        <AllowedDrop>false</AllowedDrop>
+        <CreatorID>
+          <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+        </CreatorID>
+        <FolderID>
+          <UUID>4ef3cd2c-70b9-4c1a-85cf-d45a2f1dfc22</UUID>
+        </FolderID>
+        <InventorySerial>0</InventorySerial>
+        <UUID>
+          <UUID>4ef3cd2c-70b9-4c1a-85cf-d45a2f1dfc22</UUID>
+        </UUID>
+        <LocalId>656849174</LocalId>
+        <Name>chimney#11</Name>
+        <Material>3</Material>
+        <PassTouches>false</PassTouches>
+        <PassCollisions>false</PassCollisions>
+        <RegionHandle>4008819395804416</RegionHandle>
+        <ScriptAccessPin>0</ScriptAccessPin>
+        <GroupPosition>
+          <X>192.3722</X>
+          <Y>185.4859</Y>
+          <Z>53.20147</Z>
+        </GroupPosition>
+        <OffsetPosition>
+          <X>0.4976274</X>
+          <Y>1.209043</Y>
+          <Z>-1.667094</Z>
+        </OffsetPosition>
+        <RotationOffset>
+          <X>0.3992665</X>
+          <Y>-0.5051886</Y>
+          <Z>0.4334386</Z>
+          <W>0.6304775</W>
+        </RotationOffset>
+        <Velocity>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </Velocity>
+        <AngularVelocity>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </AngularVelocity>
+        <Acceleration>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </Acceleration>
+        <Description />
+        <Color>
+          <R>0</R>
+          <G>0</G>
+          <B>0</B>
+          <A>255</A>
+        </Color>
+        <Text />
+        <SitName />
+        <TouchName />
+        <LinkNum>12</LinkNum>
+        <ClickAction>0</ClickAction>
+        <Shape>
+          <ProfileCurve>48</ProfileCurve>
+          <TextureEntry>4mI72Pd/RS+ozrKPdFrS5AAAAAAAAAAAgD8AAACAPwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==</TextureEntry>
+          <ExtraParams>ATAAEQAAAGhvUzzkJEGyk8n45P16q/YF</ExtraParams>
+          <PathBegin>0</PathBegin>
+          <PathCurve>32</PathCurve>
+          <PathEnd>0</PathEnd>
+          <PathRadiusOffset>0</PathRadiusOffset>
+          <PathRevolutions>0</PathRevolutions>
+          <PathScaleX>100</PathScaleX>
+          <PathScaleY>150</PathScaleY>
+          <PathShearX>0</PathShearX>
+          <PathShearY>0</PathShearY>
+          <PathSkew>0</PathSkew>
+          <PathTaperX>0</PathTaperX>
+          <PathTaperY>0</PathTaperY>
+          <PathTwist>0</PathTwist>
+          <PathTwistBegin>0</PathTwistBegin>
+          <PCode>9</PCode>
+          <ProfileBegin>0</ProfileBegin>
+          <ProfileEnd>0</ProfileEnd>
+          <ProfileHollow>0</ProfileHollow>
+          <State>0</State>
+          <LastAttachPoint>0</LastAttachPoint>
+          <ProfileShape>Circle</ProfileShape>
+          <HollowShape>Triangle</HollowShape>
+          <SculptTexture>
+            <UUID>686f533c-e424-41b2-93c9-f8e4fd7aabf6</UUID>
+          </SculptTexture>
+          <SculptType>5</SculptType>
+          <FlexiSoftness>0</FlexiSoftness>
+          <FlexiTension>0</FlexiTension>
+          <FlexiDrag>0</FlexiDrag>
+          <FlexiGravity>0</FlexiGravity>
+          <FlexiWind>0</FlexiWind>
+          <FlexiForceX>0</FlexiForceX>
+          <FlexiForceY>0</FlexiForceY>
+          <FlexiForceZ>0</FlexiForceZ>
+          <LightColorR>0</LightColorR>
+          <LightColorG>0</LightColorG>
+          <LightColorB>0</LightColorB>
+          <LightColorA>1</LightColorA>
+          <LightRadius>0</LightRadius>
+          <LightCutoff>0</LightCutoff>
+          <LightFalloff>0</LightFalloff>
+          <LightIntensity>1</LightIntensity>
+          <FlexiEntry>false</FlexiEntry>
+          <LightEntry>false</LightEntry>
+          <SculptEntry>true</SculptEntry>
+        </Shape>
+        <Scale>
+          <X>0.07253622</X>
+          <Y>0.726343</Y>
+          <Z>1.93177</Z>
+        </Scale>
+        <SitTargetOrientation>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+          <W>1</W>
+        </SitTargetOrientation>
+        <SitTargetPosition>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </SitTargetPosition>
+        <SitTargetPositionLL>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </SitTargetPositionLL>
+        <SitTargetOrientationLL>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+          <W>1</W>
+        </SitTargetOrientationLL>
+        <ParentID>656849163</ParentID>
+        <CreationDate>1614974861</CreationDate>
+        <Category>0</Category>
+        <SalePrice>0</SalePrice>
+        <ObjectSaleType>0</ObjectSaleType>
+        <OwnershipCost>0</OwnershipCost>
+        <GroupID>
+          <UUID>5f1ea2fb-d489-44ce-a41d-a8d2a18c343c</UUID>
+        </GroupID>
+        <OwnerID>
+          <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+        </OwnerID>
+        <LastOwnerID>
+          <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+        </LastOwnerID>
+        <RezzerID>
+          <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+        </RezzerID>
+        <BaseMask>647168</BaseMask>
+        <OwnerMask>647168</OwnerMask>
+        <GroupMask>0</GroupMask>
+        <EveryoneMask>0</EveryoneMask>
+        <NextOwnerMask>532480</NextOwnerMask>
+        <Flags>None</Flags>
+        <CollisionSound>
+          <UUID>00000000-0000-0000-0000-000000000000</UUID>
+        </CollisionSound>
+        <CollisionSoundVolume>0</CollisionSoundVolume>
+        <MediaUrl />
+        <AttachedPos>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </AttachedPos>
+        <TextureAnimation></TextureAnimation>
+        <ParticleSystem></ParticleSystem>
+        <PayPrice0>-2</PayPrice0>
+        <PayPrice1>-2</PayPrice1>
+        <PayPrice2>-2</PayPrice2>
+        <PayPrice3>-2</PayPrice3>
+        <PayPrice4>-2</PayPrice4>
+        <Buoyancy>0</Buoyancy>
+        <Force>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </Force>
+        <Torque>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </Torque>
+        <VolumeDetectActive>false</VolumeDetectActive>
+        <PhysicsShapeType>0</PhysicsShapeType>
+        <CameraEyeOffset>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </CameraEyeOffset>
+        <CameraAtOffset>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </CameraAtOffset>
+        <SoundID>
+          <UUID>00000000-0000-0000-0000-000000000000</UUID>
+        </SoundID>
+        <SoundGain>0</SoundGain>
+        <SoundFlags>0</SoundFlags>
+        <SoundRadius>0</SoundRadius>
+        <SoundQueueing>false</SoundQueueing>
+      </SceneObjectPart>
+    </Part>
+    <Part>
+      <SceneObjectPart xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+        <AllowedDrop>false</AllowedDrop>
+        <CreatorID>
+          <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+        </CreatorID>
+        <FolderID>
+          <UUID>4c58754f-d293-4766-91dc-725c9549d110</UUID>
+        </FolderID>
+        <InventorySerial>0</InventorySerial>
+        <UUID>
+          <UUID>4c58754f-d293-4766-91dc-725c9549d110</UUID>
+        </UUID>
+        <LocalId>656849175</LocalId>
+        <Name>chimney#12</Name>
+        <Material>3</Material>
+        <PassTouches>false</PassTouches>
+        <PassCollisions>false</PassCollisions>
+        <RegionHandle>4008819395804416</RegionHandle>
+        <ScriptAccessPin>0</ScriptAccessPin>
+        <GroupPosition>
+          <X>192.3722</X>
+          <Y>185.4859</Y>
+          <Z>53.20147</Z>
+        </GroupPosition>
+        <OffsetPosition>
+          <X>-1.387109</X>
+          <Y>-1.117188</Y>
+          <Z>1.313267</Z>
+        </OffsetPosition>
+        <RotationOffset>
+          <X>0.3872716</X>
+          <Y>-0.5144414</Y>
+          <Z>0.4481503</Z>
+          <W>0.6201065</W>
+        </RotationOffset>
+        <Velocity>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </Velocity>
+        <AngularVelocity>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </AngularVelocity>
+        <Acceleration>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </Acceleration>
+        <Description />
+        <Color>
+          <R>0</R>
+          <G>0</G>
+          <B>0</B>
+          <A>255</A>
+        </Color>
+        <Text />
+        <SitName />
+        <TouchName />
+        <LinkNum>13</LinkNum>
+        <ClickAction>0</ClickAction>
+        <Shape>
+          <ProfileCurve>48</ProfileCurve>
+          <TextureEntry>4mI72Pd/RS+ozrKPdFrS5AAAAAAAAAAAgD8AAACAPwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==</TextureEntry>
+          <ExtraParams>ATAAEQAAAIHQAY/WikkzistGyDSDFEcF</ExtraParams>
+          <PathBegin>0</PathBegin>
+          <PathCurve>32</PathCurve>
+          <PathEnd>0</PathEnd>
+          <PathRadiusOffset>0</PathRadiusOffset>
+          <PathRevolutions>0</PathRevolutions>
+          <PathScaleX>100</PathScaleX>
+          <PathScaleY>150</PathScaleY>
+          <PathShearX>0</PathShearX>
+          <PathShearY>0</PathShearY>
+          <PathSkew>0</PathSkew>
+          <PathTaperX>0</PathTaperX>
+          <PathTaperY>0</PathTaperY>
+          <PathTwist>0</PathTwist>
+          <PathTwistBegin>0</PathTwistBegin>
+          <PCode>9</PCode>
+          <ProfileBegin>0</ProfileBegin>
+          <ProfileEnd>0</ProfileEnd>
+          <ProfileHollow>0</ProfileHollow>
+          <State>0</State>
+          <LastAttachPoint>0</LastAttachPoint>
+          <ProfileShape>Circle</ProfileShape>
+          <HollowShape>Triangle</HollowShape>
+          <SculptTexture>
+            <UUID>81d0018f-d68a-4933-8acb-46c834831447</UUID>
+          </SculptTexture>
+          <SculptType>5</SculptType>
+          <FlexiSoftness>0</FlexiSoftness>
+          <FlexiTension>0</FlexiTension>
+          <FlexiDrag>0</FlexiDrag>
+          <FlexiGravity>0</FlexiGravity>
+          <FlexiWind>0</FlexiWind>
+          <FlexiForceX>0</FlexiForceX>
+          <FlexiForceY>0</FlexiForceY>
+          <FlexiForceZ>0</FlexiForceZ>
+          <LightColorR>0</LightColorR>
+          <LightColorG>0</LightColorG>
+          <LightColorB>0</LightColorB>
+          <LightColorA>1</LightColorA>
+          <LightRadius>0</LightRadius>
+          <LightCutoff>0</LightCutoff>
+          <LightFalloff>0</LightFalloff>
+          <LightIntensity>1</LightIntensity>
+          <FlexiEntry>false</FlexiEntry>
+          <LightEntry>false</LightEntry>
+          <SculptEntry>true</SculptEntry>
+        </Shape>
+        <Scale>
+          <X>0.4000056</X>
+          <Y>0.07465271</Y>
+          <Z>0.0542078</Z>
+        </Scale>
+        <SitTargetOrientation>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+          <W>1</W>
+        </SitTargetOrientation>
+        <SitTargetPosition>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </SitTargetPosition>
+        <SitTargetPositionLL>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </SitTargetPositionLL>
+        <SitTargetOrientationLL>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+          <W>1</W>
+        </SitTargetOrientationLL>
+        <ParentID>656849163</ParentID>
+        <CreationDate>1614974861</CreationDate>
+        <Category>0</Category>
+        <SalePrice>0</SalePrice>
+        <ObjectSaleType>0</ObjectSaleType>
+        <OwnershipCost>0</OwnershipCost>
+        <GroupID>
+          <UUID>5f1ea2fb-d489-44ce-a41d-a8d2a18c343c</UUID>
+        </GroupID>
+        <OwnerID>
+          <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+        </OwnerID>
+        <LastOwnerID>
+          <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+        </LastOwnerID>
+        <RezzerID>
+          <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+        </RezzerID>
+        <BaseMask>647168</BaseMask>
+        <OwnerMask>647168</OwnerMask>
+        <GroupMask>0</GroupMask>
+        <EveryoneMask>0</EveryoneMask>
+        <NextOwnerMask>532480</NextOwnerMask>
+        <Flags>None</Flags>
+        <CollisionSound>
+          <UUID>00000000-0000-0000-0000-000000000000</UUID>
+        </CollisionSound>
+        <CollisionSoundVolume>0</CollisionSoundVolume>
+        <MediaUrl />
+        <AttachedPos>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </AttachedPos>
+        <TextureAnimation></TextureAnimation>
+        <ParticleSystem></ParticleSystem>
+        <PayPrice0>-2</PayPrice0>
+        <PayPrice1>-2</PayPrice1>
+        <PayPrice2>-2</PayPrice2>
+        <PayPrice3>-2</PayPrice3>
+        <PayPrice4>-2</PayPrice4>
+        <Buoyancy>0</Buoyancy>
+        <Force>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </Force>
+        <Torque>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </Torque>
+        <VolumeDetectActive>false</VolumeDetectActive>
+        <PhysicsShapeType>0</PhysicsShapeType>
+        <CameraEyeOffset>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </CameraEyeOffset>
+        <CameraAtOffset>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </CameraAtOffset>
+        <SoundID>
+          <UUID>00000000-0000-0000-0000-000000000000</UUID>
+        </SoundID>
+        <SoundGain>0</SoundGain>
+        <SoundFlags>0</SoundFlags>
+        <SoundRadius>0</SoundRadius>
+        <SoundQueueing>false</SoundQueueing>
+      </SceneObjectPart>
+    </Part>
+    <Part>
+      <SceneObjectPart xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+        <AllowedDrop>false</AllowedDrop>
+        <CreatorID>
+          <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+        </CreatorID>
+        <FolderID>
+          <UUID>47e450d9-e048-42c8-9a60-c6273464dec1</UUID>
+        </FolderID>
+        <InventorySerial>0</InventorySerial>
+        <UUID>
+          <UUID>47e450d9-e048-42c8-9a60-c6273464dec1</UUID>
+        </UUID>
+        <LocalId>656849176</LocalId>
+        <Name>chimney#13</Name>
+        <Material>3</Material>
+        <PassTouches>false</PassTouches>
+        <PassCollisions>false</PassCollisions>
+        <RegionHandle>4008819395804416</RegionHandle>
+        <ScriptAccessPin>0</ScriptAccessPin>
+        <GroupPosition>
+          <X>192.3722</X>
+          <Y>185.4859</Y>
+          <Z>53.20147</Z>
+        </GroupPosition>
+        <OffsetPosition>
+          <X>-1.063974</X>
+          <Y>-0.2197517</Y>
+          <Z>1.155216</Z>
+        </OffsetPosition>
+        <RotationOffset>
+          <X>0.3872715</X>
+          <Y>-0.5144415</Y>
+          <Z>0.4481505</Z>
+          <W>0.6201064</W>
+        </RotationOffset>
+        <Velocity>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </Velocity>
+        <AngularVelocity>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </AngularVelocity>
+        <Acceleration>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </Acceleration>
+        <Description />
+        <Color>
+          <R>0</R>
+          <G>0</G>
+          <B>0</B>
+          <A>255</A>
+        </Color>
+        <Text />
+        <SitName />
+        <TouchName />
+        <LinkNum>14</LinkNum>
+        <ClickAction>0</ClickAction>
+        <Shape>
+          <ProfileCurve>48</ProfileCurve>
+          <TextureEntry>IbeBKBCuSaae15Mwj5sGoAAAAAAAAAAAgD8AAACAPwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==</TextureEntry>
+          <ExtraParams>ATAAEQAAALHhTRblXE8cnEgGbDBN1fIF</ExtraParams>
+          <PathBegin>0</PathBegin>
+          <PathCurve>32</PathCurve>
+          <PathEnd>0</PathEnd>
+          <PathRadiusOffset>0</PathRadiusOffset>
+          <PathRevolutions>0</PathRevolutions>
+          <PathScaleX>100</PathScaleX>
+          <PathScaleY>150</PathScaleY>
+          <PathShearX>0</PathShearX>
+          <PathShearY>0</PathShearY>
+          <PathSkew>0</PathSkew>
+          <PathTaperX>0</PathTaperX>
+          <PathTaperY>0</PathTaperY>
+          <PathTwist>0</PathTwist>
+          <PathTwistBegin>0</PathTwistBegin>
+          <PCode>9</PCode>
+          <ProfileBegin>0</ProfileBegin>
+          <ProfileEnd>0</ProfileEnd>
+          <ProfileHollow>0</ProfileHollow>
+          <State>0</State>
+          <LastAttachPoint>0</LastAttachPoint>
+          <ProfileShape>Circle</ProfileShape>
+          <HollowShape>Triangle</HollowShape>
+          <SculptTexture>
+            <UUID>b1e14d16-e55c-4f1c-9c48-066c304dd5f2</UUID>
+          </SculptTexture>
+          <SculptType>5</SculptType>
+          <FlexiSoftness>0</FlexiSoftness>
+          <FlexiTension>0</FlexiTension>
+          <FlexiDrag>0</FlexiDrag>
+          <FlexiGravity>0</FlexiGravity>
+          <FlexiWind>0</FlexiWind>
+          <FlexiForceX>0</FlexiForceX>
+          <FlexiForceY>0</FlexiForceY>
+          <FlexiForceZ>0</FlexiForceZ>
+          <LightColorR>0</LightColorR>
+          <LightColorG>0</LightColorG>
+          <LightColorB>0</LightColorB>
+          <LightColorA>1</LightColorA>
+          <LightRadius>0</LightRadius>
+          <LightCutoff>0</LightCutoff>
+          <LightFalloff>0</LightFalloff>
+          <LightIntensity>1</LightIntensity>
+          <FlexiEntry>false</FlexiEntry>
+          <LightEntry>false</LightEntry>
+          <SculptEntry>true</SculptEntry>
+        </Shape>
+        <Scale>
+          <X>1.002</X>
+          <Y>0.9999997</Y>
+          <Z>1.60001</Z>
+        </Scale>
+        <SitTargetOrientation>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+          <W>1</W>
+        </SitTargetOrientation>
+        <SitTargetPosition>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </SitTargetPosition>
+        <SitTargetPositionLL>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </SitTargetPositionLL>
+        <SitTargetOrientationLL>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+          <W>1</W>
+        </SitTargetOrientationLL>
+        <ParentID>656849163</ParentID>
+        <CreationDate>1614974861</CreationDate>
+        <Category>0</Category>
+        <SalePrice>0</SalePrice>
+        <ObjectSaleType>0</ObjectSaleType>
+        <OwnershipCost>0</OwnershipCost>
+        <GroupID>
+          <UUID>5f1ea2fb-d489-44ce-a41d-a8d2a18c343c</UUID>
+        </GroupID>
+        <OwnerID>
+          <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+        </OwnerID>
+        <LastOwnerID>
+          <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+        </LastOwnerID>
+        <RezzerID>
+          <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+        </RezzerID>
+        <BaseMask>647168</BaseMask>
+        <OwnerMask>647168</OwnerMask>
+        <GroupMask>0</GroupMask>
+        <EveryoneMask>0</EveryoneMask>
+        <NextOwnerMask>532480</NextOwnerMask>
+        <Flags>None</Flags>
+        <CollisionSound>
+          <UUID>00000000-0000-0000-0000-000000000000</UUID>
+        </CollisionSound>
+        <CollisionSoundVolume>0</CollisionSoundVolume>
+        <MediaUrl />
+        <AttachedPos>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </AttachedPos>
+        <TextureAnimation></TextureAnimation>
+        <ParticleSystem></ParticleSystem>
+        <PayPrice0>-2</PayPrice0>
+        <PayPrice1>-2</PayPrice1>
+        <PayPrice2>-2</PayPrice2>
+        <PayPrice3>-2</PayPrice3>
+        <PayPrice4>-2</PayPrice4>
+        <Buoyancy>0</Buoyancy>
+        <Force>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </Force>
+        <Torque>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </Torque>
+        <VolumeDetectActive>false</VolumeDetectActive>
+        <PhysicsShapeType>0</PhysicsShapeType>
+        <CameraEyeOffset>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </CameraEyeOffset>
+        <CameraAtOffset>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </CameraAtOffset>
+        <SoundID>
+          <UUID>00000000-0000-0000-0000-000000000000</UUID>
+        </SoundID>
+        <SoundGain>0</SoundGain>
+        <SoundFlags>0</SoundFlags>
+        <SoundRadius>0</SoundRadius>
+        <SoundQueueing>false</SoundQueueing>
+      </SceneObjectPart>
+    </Part>
+    <Part>
+      <SceneObjectPart xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+        <AllowedDrop>false</AllowedDrop>
+        <CreatorID>
+          <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+        </CreatorID>
+        <FolderID>
+          <UUID>7b513270-bac4-43ae-a485-599e01a09d8c</UUID>
+        </FolderID>
+        <InventorySerial>0</InventorySerial>
+        <UUID>
+          <UUID>7b513270-bac4-43ae-a485-599e01a09d8c</UUID>
+        </UUID>
+        <LocalId>656849177</LocalId>
+        <Name>chimney#14</Name>
+        <Material>3</Material>
+        <PassTouches>false</PassTouches>
+        <PassCollisions>false</PassCollisions>
+        <RegionHandle>4008819395804416</RegionHandle>
+        <ScriptAccessPin>0</ScriptAccessPin>
+        <GroupPosition>
+          <X>192.3722</X>
+          <Y>185.4859</Y>
+          <Z>53.20147</Z>
+        </GroupPosition>
+        <OffsetPosition>
+          <X>-0.07897377</X>
+          <Y>1.214271</Y>
+          <Z>-0.1336055</Z>
+        </OffsetPosition>
+        <RotationOffset>
+          <X>0.3992663</X>
+          <Y>-0.5051889</Y>
+          <Z>0.433439</Z>
+          <W>0.6304771</W>
+        </RotationOffset>
+        <Velocity>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </Velocity>
+        <AngularVelocity>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </AngularVelocity>
+        <Acceleration>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </Acceleration>
+        <Description />
+        <Color>
+          <R>0</R>
+          <G>0</G>
+          <B>0</B>
+          <A>255</A>
+        </Color>
+        <Text />
+        <SitName />
+        <TouchName />
+        <LinkNum>15</LinkNum>
+        <ClickAction>0</ClickAction>
+        <Shape>
+          <ProfileCurve>48</ProfileCurve>
+          <TextureEntry>1Fjp8DqXRI6yImytqUwRJAIXt5MY2thPWZxznnDyfg6HAeJiO9j3f0UvqM6yj3Ra0uQAAAAAAAAAAIA/AAAAgD8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</TextureEntry>
+          <ExtraParams>ATAAEQAAAE7SIwVjhUCxs1xzquhLVjMF</ExtraParams>
+          <PathBegin>0</PathBegin>
+          <PathCurve>16</PathCurve>
+          <PathEnd>0</PathEnd>
+          <PathRadiusOffset>0</PathRadiusOffset>
+          <PathRevolutions>0</PathRevolutions>
+          <PathScaleX>100</PathScaleX>
+          <PathScaleY>100</PathScaleY>
+          <PathShearX>0</PathShearX>
+          <PathShearY>0</PathShearY>
+          <PathSkew>0</PathSkew>
+          <PathTaperX>0</PathTaperX>
+          <PathTaperY>0</PathTaperY>
+          <PathTwist>0</PathTwist>
+          <PathTwistBegin>0</PathTwistBegin>
+          <PCode>9</PCode>
+          <ProfileBegin>0</ProfileBegin>
+          <ProfileEnd>0</ProfileEnd>
+          <ProfileHollow>0</ProfileHollow>
+          <State>0</State>
+          <LastAttachPoint>0</LastAttachPoint>
+          <ProfileShape>Circle</ProfileShape>
+          <HollowShape>Triangle</HollowShape>
+          <SculptTexture>
+            <UUID>4ed22305-6385-40b1-b35c-73aae84b5633</UUID>
+          </SculptTexture>
+          <SculptType>5</SculptType>
+          <FlexiSoftness>0</FlexiSoftness>
+          <FlexiTension>0</FlexiTension>
+          <FlexiDrag>0</FlexiDrag>
+          <FlexiGravity>0</FlexiGravity>
+          <FlexiWind>0</FlexiWind>
+          <FlexiForceX>0</FlexiForceX>
+          <FlexiForceY>0</FlexiForceY>
+          <FlexiForceZ>0</FlexiForceZ>
+          <LightColorR>0</LightColorR>
+          <LightColorG>0</LightColorG>
+          <LightColorB>0</LightColorB>
+          <LightColorA>1</LightColorA>
+          <LightRadius>0</LightRadius>
+          <LightCutoff>0</LightCutoff>
+          <LightFalloff>0</LightFalloff>
+          <LightIntensity>1</LightIntensity>
+          <FlexiEntry>false</FlexiEntry>
+          <LightEntry>false</LightEntry>
+          <SculptEntry>true</SculptEntry>
+        </Shape>
+        <Scale>
+          <X>3.416009</X>
+          <Y>2.365175</Y>
+          <Z>2.921128</Z>
+        </Scale>
+        <SitTargetOrientation>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+          <W>1</W>
+        </SitTargetOrientation>
+        <SitTargetPosition>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </SitTargetPosition>
+        <SitTargetPositionLL>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </SitTargetPositionLL>
+        <SitTargetOrientationLL>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+          <W>1</W>
+        </SitTargetOrientationLL>
+        <ParentID>656849163</ParentID>
+        <CreationDate>1614974861</CreationDate>
+        <Category>0</Category>
+        <SalePrice>0</SalePrice>
+        <ObjectSaleType>0</ObjectSaleType>
+        <OwnershipCost>0</OwnershipCost>
+        <GroupID>
+          <UUID>5f1ea2fb-d489-44ce-a41d-a8d2a18c343c</UUID>
+        </GroupID>
+        <OwnerID>
+          <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+        </OwnerID>
+        <LastOwnerID>
+          <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+        </LastOwnerID>
+        <RezzerID>
+          <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+        </RezzerID>
+        <BaseMask>647168</BaseMask>
+        <OwnerMask>647168</OwnerMask>
+        <GroupMask>0</GroupMask>
+        <EveryoneMask>0</EveryoneMask>
+        <NextOwnerMask>532480</NextOwnerMask>
+        <Flags>None</Flags>
+        <CollisionSound>
+          <UUID>00000000-0000-0000-0000-000000000000</UUID>
+        </CollisionSound>
+        <CollisionSoundVolume>0</CollisionSoundVolume>
+        <MediaUrl />
+        <AttachedPos>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </AttachedPos>
+        <TextureAnimation></TextureAnimation>
+        <ParticleSystem></ParticleSystem>
+        <PayPrice0>-2</PayPrice0>
+        <PayPrice1>-2</PayPrice1>
+        <PayPrice2>-2</PayPrice2>
+        <PayPrice3>-2</PayPrice3>
+        <PayPrice4>-2</PayPrice4>
+        <Buoyancy>0</Buoyancy>
+        <Force>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </Force>
+        <Torque>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </Torque>
+        <VolumeDetectActive>false</VolumeDetectActive>
+        <PhysicsShapeType>0</PhysicsShapeType>
+        <CameraEyeOffset>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </CameraEyeOffset>
+        <CameraAtOffset>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </CameraAtOffset>
+        <SoundID>
+          <UUID>00000000-0000-0000-0000-000000000000</UUID>
+        </SoundID>
+        <SoundGain>0</SoundGain>
+        <SoundFlags>0</SoundFlags>
+        <SoundRadius>0</SoundRadius>
+        <SoundQueueing>false</SoundQueueing>
+      </SceneObjectPart>
+    </Part>
+    <Part>
+      <SceneObjectPart xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+        <AllowedDrop>false</AllowedDrop>
+        <CreatorID>
+          <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+        </CreatorID>
+        <FolderID>
+          <UUID>59e49893-6d85-46d0-9f19-c63a9112c8d8</UUID>
+        </FolderID>
+        <InventorySerial>0</InventorySerial>
+        <UUID>
+          <UUID>59e49893-6d85-46d0-9f19-c63a9112c8d8</UUID>
+        </UUID>
+        <LocalId>656849178</LocalId>
+        <Name>chimney#15</Name>
+        <Material>3</Material>
+        <PassTouches>false</PassTouches>
+        <PassCollisions>false</PassCollisions>
+        <RegionHandle>4008819395804416</RegionHandle>
+        <ScriptAccessPin>0</ScriptAccessPin>
+        <GroupPosition>
+          <X>192.3722</X>
+          <Y>185.4859</Y>
+          <Z>53.20147</Z>
+        </GroupPosition>
+        <OffsetPosition>
+          <X>0.1546262</X>
+          <Y>1.581869</Y>
+          <Z>-1.819055</Z>
+        </OffsetPosition>
+        <RotationOffset>
+          <X>0.3992662</X>
+          <Y>-0.5051888</Y>
+          <Z>0.4334387</Z>
+          <W>0.6304774</W>
+        </RotationOffset>
+        <Velocity>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </Velocity>
+        <AngularVelocity>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </AngularVelocity>
+        <Acceleration>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </Acceleration>
+        <Description />
+        <Color>
+          <R>0</R>
+          <G>0</G>
+          <B>0</B>
+          <A>255</A>
+        </Color>
+        <Text />
+        <SitName />
+        <TouchName />
+        <LinkNum>16</LinkNum>
+        <ClickAction>0</ClickAction>
+        <Shape>
+          <ProfileCurve>48</ProfileCurve>
+          <TextureEntry>fE4GqCkwTTadRmMXGTuCpgAAAAAAAAAAgD8AAACAPwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==</TextureEntry>
+          <ExtraParams>ATAAEQAAAODSSHPRwkowoJcIOaldbYEF</ExtraParams>
+          <PathBegin>0</PathBegin>
+          <PathCurve>32</PathCurve>
+          <PathEnd>0</PathEnd>
+          <PathRadiusOffset>0</PathRadiusOffset>
+          <PathRevolutions>0</PathRevolutions>
+          <PathScaleX>100</PathScaleX>
+          <PathScaleY>150</PathScaleY>
+          <PathShearX>0</PathShearX>
+          <PathShearY>0</PathShearY>
+          <PathSkew>0</PathSkew>
+          <PathTaperX>0</PathTaperX>
+          <PathTaperY>0</PathTaperY>
+          <PathTwist>0</PathTwist>
+          <PathTwistBegin>0</PathTwistBegin>
+          <PCode>9</PCode>
+          <ProfileBegin>0</ProfileBegin>
+          <ProfileEnd>0</ProfileEnd>
+          <ProfileHollow>0</ProfileHollow>
+          <State>0</State>
+          <LastAttachPoint>0</LastAttachPoint>
+          <ProfileShape>Circle</ProfileShape>
+          <HollowShape>Triangle</HollowShape>
+          <SculptTexture>
+            <UUID>e0d24873-d1c2-4a30-a097-0839a95d6d81</UUID>
+          </SculptTexture>
+          <SculptType>5</SculptType>
+          <FlexiSoftness>0</FlexiSoftness>
+          <FlexiTension>0</FlexiTension>
+          <FlexiDrag>0</FlexiDrag>
+          <FlexiGravity>0</FlexiGravity>
+          <FlexiWind>0</FlexiWind>
+          <FlexiForceX>0</FlexiForceX>
+          <FlexiForceY>0</FlexiForceY>
+          <FlexiForceZ>0</FlexiForceZ>
+          <LightColorR>0</LightColorR>
+          <LightColorG>0</LightColorG>
+          <LightColorB>0</LightColorB>
+          <LightColorA>1</LightColorA>
+          <LightRadius>0</LightRadius>
+          <LightCutoff>0</LightCutoff>
+          <LightFalloff>0</LightFalloff>
+          <LightIntensity>1</LightIntensity>
+          <FlexiEntry>false</FlexiEntry>
+          <LightEntry>false</LightEntry>
+          <SculptEntry>true</SculptEntry>
+        </Shape>
+        <Scale>
+          <X>0.1449002</X>
+          <Y>0.2241422</Y>
+          <Z>1.427019</Z>
+        </Scale>
+        <SitTargetOrientation>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+          <W>1</W>
+        </SitTargetOrientation>
+        <SitTargetPosition>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </SitTargetPosition>
+        <SitTargetPositionLL>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </SitTargetPositionLL>
+        <SitTargetOrientationLL>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+          <W>1</W>
+        </SitTargetOrientationLL>
+        <ParentID>656849163</ParentID>
+        <CreationDate>1614974861</CreationDate>
+        <Category>0</Category>
+        <SalePrice>0</SalePrice>
+        <ObjectSaleType>0</ObjectSaleType>
+        <OwnershipCost>0</OwnershipCost>
+        <GroupID>
+          <UUID>5f1ea2fb-d489-44ce-a41d-a8d2a18c343c</UUID>
+        </GroupID>
+        <OwnerID>
+          <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+        </OwnerID>
+        <LastOwnerID>
+          <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+        </LastOwnerID>
+        <RezzerID>
+          <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+        </RezzerID>
+        <BaseMask>647168</BaseMask>
+        <OwnerMask>647168</OwnerMask>
+        <GroupMask>0</GroupMask>
+        <EveryoneMask>0</EveryoneMask>
+        <NextOwnerMask>532480</NextOwnerMask>
+        <Flags>None</Flags>
+        <CollisionSound>
+          <UUID>00000000-0000-0000-0000-000000000000</UUID>
+        </CollisionSound>
+        <CollisionSoundVolume>0</CollisionSoundVolume>
+        <MediaUrl />
+        <AttachedPos>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </AttachedPos>
+        <TextureAnimation></TextureAnimation>
+        <ParticleSystem></ParticleSystem>
+        <PayPrice0>-2</PayPrice0>
+        <PayPrice1>-2</PayPrice1>
+        <PayPrice2>-2</PayPrice2>
+        <PayPrice3>-2</PayPrice3>
+        <PayPrice4>-2</PayPrice4>
+        <Buoyancy>0</Buoyancy>
+        <Force>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </Force>
+        <Torque>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </Torque>
+        <VolumeDetectActive>false</VolumeDetectActive>
+        <PhysicsShapeType>0</PhysicsShapeType>
+        <CameraEyeOffset>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </CameraEyeOffset>
+        <CameraAtOffset>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </CameraAtOffset>
+        <SoundID>
+          <UUID>00000000-0000-0000-0000-000000000000</UUID>
+        </SoundID>
+        <SoundGain>0</SoundGain>
+        <SoundFlags>0</SoundFlags>
+        <SoundRadius>0</SoundRadius>
+        <SoundQueueing>false</SoundQueueing>
+      </SceneObjectPart>
+    </Part>
+    <Part>
+      <SceneObjectPart xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+        <AllowedDrop>false</AllowedDrop>
+        <CreatorID>
+          <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+        </CreatorID>
+        <FolderID>
+          <UUID>9cb8823e-29b6-4806-8fcc-ed3190d1c09f</UUID>
+        </FolderID>
+        <InventorySerial>0</InventorySerial>
+        <UUID>
+          <UUID>9cb8823e-29b6-4806-8fcc-ed3190d1c09f</UUID>
+        </UUID>
+        <LocalId>656849179</LocalId>
+        <Name>chimney#16</Name>
+        <Material>3</Material>
+        <PassTouches>false</PassTouches>
+        <PassCollisions>false</PassCollisions>
+        <RegionHandle>4008819395804416</RegionHandle>
+        <ScriptAccessPin>0</ScriptAccessPin>
+        <GroupPosition>
+          <X>192.3722</X>
+          <Y>185.4859</Y>
+          <Z>53.20147</Z>
+        </GroupPosition>
+        <OffsetPosition>
+          <X>-0.1070914</X>
+          <Y>0.7544513</Y>
+          <Z>-1.636925</Z>
+        </OffsetPosition>
+        <RotationOffset>
+          <X>0.3992659</X>
+          <Y>-0.505189</Y>
+          <Z>0.4334392</Z>
+          <W>0.630477</W>
+        </RotationOffset>
+        <Velocity>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </Velocity>
+        <AngularVelocity>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </AngularVelocity>
+        <Acceleration>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </Acceleration>
+        <Description />
+        <Color>
+          <R>0</R>
+          <G>0</G>
+          <B>0</B>
+          <A>255</A>
+        </Color>
+        <Text />
+        <SitName />
+        <TouchName />
+        <LinkNum>17</LinkNum>
+        <ClickAction>0</ClickAction>
+        <Shape>
+          <ProfileCurve>48</ProfileCurve>
+          <TextureEntry>ssVeVY8UTMCZcSDK3Uhq1AAAAAAAAAAAgD8AAACAPwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==</TextureEntry>
+          <ExtraParams>ATAAEQAAAEBNR4XaF0SZtydXo4dTdAQF</ExtraParams>
+          <PathBegin>0</PathBegin>
+          <PathCurve>32</PathCurve>
+          <PathEnd>0</PathEnd>
+          <PathRadiusOffset>0</PathRadiusOffset>
+          <PathRevolutions>0</PathRevolutions>
+          <PathScaleX>100</PathScaleX>
+          <PathScaleY>150</PathScaleY>
+          <PathShearX>0</PathShearX>
+          <PathShearY>0</PathShearY>
+          <PathSkew>0</PathSkew>
+          <PathTaperX>0</PathTaperX>
+          <PathTaperY>0</PathTaperY>
+          <PathTwist>0</PathTwist>
+          <PathTwistBegin>0</PathTwistBegin>
+          <PCode>9</PCode>
+          <ProfileBegin>0</ProfileBegin>
+          <ProfileEnd>0</ProfileEnd>
+          <ProfileHollow>0</ProfileHollow>
+          <State>0</State>
+          <LastAttachPoint>0</LastAttachPoint>
+          <ProfileShape>Circle</ProfileShape>
+          <HollowShape>Triangle</HollowShape>
+          <SculptTexture>
+            <UUID>404d4785-da17-4499-b727-57a387537404</UUID>
+          </SculptTexture>
+          <SculptType>5</SculptType>
+          <FlexiSoftness>0</FlexiSoftness>
+          <FlexiTension>0</FlexiTension>
+          <FlexiDrag>0</FlexiDrag>
+          <FlexiGravity>0</FlexiGravity>
+          <FlexiWind>0</FlexiWind>
+          <FlexiForceX>0</FlexiForceX>
+          <FlexiForceY>0</FlexiForceY>
+          <FlexiForceZ>0</FlexiForceZ>
+          <LightColorR>0</LightColorR>
+          <LightColorG>0</LightColorG>
+          <LightColorB>0</LightColorB>
+          <LightColorA>1</LightColorA>
+          <LightRadius>0</LightRadius>
+          <LightCutoff>0</LightCutoff>
+          <LightFalloff>0</LightFalloff>
+          <LightIntensity>1</LightIntensity>
+          <FlexiEntry>false</FlexiEntry>
+          <LightEntry>false</LightEntry>
+          <SculptEntry>true</SculptEntry>
+        </Shape>
+        <Scale>
+          <X>0.1098487</X>
+          <Y>0.2130898</Y>
+          <Z>0.2271633</Z>
+        </Scale>
+        <SitTargetOrientation>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+          <W>1</W>
+        </SitTargetOrientation>
+        <SitTargetPosition>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </SitTargetPosition>
+        <SitTargetPositionLL>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </SitTargetPositionLL>
+        <SitTargetOrientationLL>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+          <W>1</W>
+        </SitTargetOrientationLL>
+        <ParentID>656849163</ParentID>
+        <CreationDate>1614974861</CreationDate>
+        <Category>0</Category>
+        <SalePrice>0</SalePrice>
+        <ObjectSaleType>0</ObjectSaleType>
+        <OwnershipCost>0</OwnershipCost>
+        <GroupID>
+          <UUID>5f1ea2fb-d489-44ce-a41d-a8d2a18c343c</UUID>
+        </GroupID>
+        <OwnerID>
+          <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+        </OwnerID>
+        <LastOwnerID>
+          <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+        </LastOwnerID>
+        <RezzerID>
+          <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+        </RezzerID>
+        <BaseMask>647168</BaseMask>
+        <OwnerMask>647168</OwnerMask>
+        <GroupMask>0</GroupMask>
+        <EveryoneMask>0</EveryoneMask>
+        <NextOwnerMask>532480</NextOwnerMask>
+        <Flags>None</Flags>
+        <CollisionSound>
+          <UUID>00000000-0000-0000-0000-000000000000</UUID>
+        </CollisionSound>
+        <CollisionSoundVolume>0</CollisionSoundVolume>
+        <MediaUrl />
+        <AttachedPos>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </AttachedPos>
+        <TextureAnimation></TextureAnimation>
+        <ParticleSystem></ParticleSystem>
+        <PayPrice0>-2</PayPrice0>
+        <PayPrice1>-2</PayPrice1>
+        <PayPrice2>-2</PayPrice2>
+        <PayPrice3>-2</PayPrice3>
+        <PayPrice4>-2</PayPrice4>
+        <Buoyancy>0</Buoyancy>
+        <Force>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </Force>
+        <Torque>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </Torque>
+        <VolumeDetectActive>false</VolumeDetectActive>
+        <PhysicsShapeType>0</PhysicsShapeType>
+        <CameraEyeOffset>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </CameraEyeOffset>
+        <CameraAtOffset>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </CameraAtOffset>
+        <SoundID>
+          <UUID>00000000-0000-0000-0000-000000000000</UUID>
+        </SoundID>
+        <SoundGain>0</SoundGain>
+        <SoundFlags>0</SoundFlags>
+        <SoundRadius>0</SoundRadius>
+        <SoundQueueing>false</SoundQueueing>
+      </SceneObjectPart>
+    </Part>
+    <Part>
+      <SceneObjectPart xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+        <AllowedDrop>false</AllowedDrop>
+        <CreatorID>
+          <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+        </CreatorID>
+        <FolderID>
+          <UUID>2b3cb91e-e0eb-4383-b1c5-e029157c15b9</UUID>
+        </FolderID>
+        <InventorySerial>0</InventorySerial>
+        <UUID>
+          <UUID>2b3cb91e-e0eb-4383-b1c5-e029157c15b9</UUID>
+        </UUID>
+        <LocalId>656849180</LocalId>
+        <Name>chimney#17</Name>
+        <Material>3</Material>
+        <PassTouches>false</PassTouches>
+        <PassCollisions>false</PassCollisions>
+        <RegionHandle>4008819395804416</RegionHandle>
+        <ScriptAccessPin>0</ScriptAccessPin>
+        <GroupPosition>
+          <X>192.3722</X>
+          <Y>185.4859</Y>
+          <Z>53.20147</Z>
+        </GroupPosition>
+        <OffsetPosition>
+          <X>-1.360836</X>
+          <Y>-1.032051</Y>
+          <Z>1.297825</Z>
+        </OffsetPosition>
+        <RotationOffset>
+          <X>0.3872715</X>
+          <Y>-0.5144415</Y>
+          <Z>0.4481505</Z>
+          <W>0.6201063</W>
+        </RotationOffset>
+        <Velocity>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </Velocity>
+        <AngularVelocity>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </AngularVelocity>
+        <Acceleration>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </Acceleration>
+        <Description />
+        <Color>
+          <R>0</R>
+          <G>0</G>
+          <B>0</B>
+          <A>255</A>
+        </Color>
+        <Text />
+        <SitName />
+        <TouchName />
+        <LinkNum>18</LinkNum>
+        <ClickAction>0</ClickAction>
+        <Shape>
+          <ProfileCurve>48</ProfileCurve>
+          <TextureEntry>4mI72Pd/RS+ozrKPdFrS5AAAAAAAAAAAgD8AAACAPwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==</TextureEntry>
+          <ExtraParams>ATAAEQAAADgFTCCdFE7Hg0ji7r2zF1AF</ExtraParams>
+          <PathBegin>0</PathBegin>
+          <PathCurve>32</PathCurve>
+          <PathEnd>0</PathEnd>
+          <PathRadiusOffset>0</PathRadiusOffset>
+          <PathRevolutions>0</PathRevolutions>
+          <PathScaleX>100</PathScaleX>
+          <PathScaleY>150</PathScaleY>
+          <PathShearX>0</PathShearX>
+          <PathShearY>0</PathShearY>
+          <PathSkew>0</PathSkew>
+          <PathTaperX>0</PathTaperX>
+          <PathTaperY>0</PathTaperY>
+          <PathTwist>0</PathTwist>
+          <PathTwistBegin>0</PathTwistBegin>
+          <PCode>9</PCode>
+          <ProfileBegin>0</ProfileBegin>
+          <ProfileEnd>0</ProfileEnd>
+          <ProfileHollow>0</ProfileHollow>
+          <State>0</State>
+          <LastAttachPoint>0</LastAttachPoint>
+          <ProfileShape>Circle</ProfileShape>
+          <HollowShape>Triangle</HollowShape>
+          <SculptTexture>
+            <UUID>38054c20-9d14-4ec7-8348-e2eebdb31750</UUID>
+          </SculptTexture>
+          <SculptType>5</SculptType>
+          <FlexiSoftness>0</FlexiSoftness>
+          <FlexiTension>0</FlexiTension>
+          <FlexiDrag>0</FlexiDrag>
+          <FlexiGravity>0</FlexiGravity>
+          <FlexiWind>0</FlexiWind>
+          <FlexiForceX>0</FlexiForceX>
+          <FlexiForceY>0</FlexiForceY>
+          <FlexiForceZ>0</FlexiForceZ>
+          <LightColorR>0</LightColorR>
+          <LightColorG>0</LightColorG>
+          <LightColorB>0</LightColorB>
+          <LightColorA>1</LightColorA>
+          <LightRadius>0</LightRadius>
+          <LightCutoff>0</LightCutoff>
+          <LightFalloff>0</LightFalloff>
+          <LightIntensity>1</LightIntensity>
+          <FlexiEntry>false</FlexiEntry>
+          <LightEntry>false</LightEntry>
+          <SculptEntry>true</SculptEntry>
+        </Shape>
+        <Scale>
+          <X>0.4000002</X>
+          <Y>0.4169287</Y>
+          <Z>0.1519399</Z>
+        </Scale>
+        <SitTargetOrientation>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+          <W>1</W>
+        </SitTargetOrientation>
+        <SitTargetPosition>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </SitTargetPosition>
+        <SitTargetPositionLL>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </SitTargetPositionLL>
+        <SitTargetOrientationLL>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+          <W>1</W>
+        </SitTargetOrientationLL>
+        <ParentID>656849163</ParentID>
+        <CreationDate>1614974861</CreationDate>
+        <Category>0</Category>
+        <SalePrice>0</SalePrice>
+        <ObjectSaleType>0</ObjectSaleType>
+        <OwnershipCost>0</OwnershipCost>
+        <GroupID>
+          <UUID>5f1ea2fb-d489-44ce-a41d-a8d2a18c343c</UUID>
+        </GroupID>
+        <OwnerID>
+          <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+        </OwnerID>
+        <LastOwnerID>
+          <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+        </LastOwnerID>
+        <RezzerID>
+          <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+        </RezzerID>
+        <BaseMask>647168</BaseMask>
+        <OwnerMask>647168</OwnerMask>
+        <GroupMask>0</GroupMask>
+        <EveryoneMask>0</EveryoneMask>
+        <NextOwnerMask>532480</NextOwnerMask>
+        <Flags>None</Flags>
+        <CollisionSound>
+          <UUID>00000000-0000-0000-0000-000000000000</UUID>
+        </CollisionSound>
+        <CollisionSoundVolume>0</CollisionSoundVolume>
+        <MediaUrl />
+        <AttachedPos>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </AttachedPos>
+        <TextureAnimation></TextureAnimation>
+        <ParticleSystem></ParticleSystem>
+        <PayPrice0>-2</PayPrice0>
+        <PayPrice1>-2</PayPrice1>
+        <PayPrice2>-2</PayPrice2>
+        <PayPrice3>-2</PayPrice3>
+        <PayPrice4>-2</PayPrice4>
+        <Buoyancy>0</Buoyancy>
+        <Force>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </Force>
+        <Torque>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </Torque>
+        <VolumeDetectActive>false</VolumeDetectActive>
+        <PhysicsShapeType>0</PhysicsShapeType>
+        <CameraEyeOffset>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </CameraEyeOffset>
+        <CameraAtOffset>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </CameraAtOffset>
+        <SoundID>
+          <UUID>00000000-0000-0000-0000-000000000000</UUID>
+        </SoundID>
+        <SoundGain>0</SoundGain>
+        <SoundFlags>0</SoundFlags>
+        <SoundRadius>0</SoundRadius>
+        <SoundQueueing>false</SoundQueueing>
+      </SceneObjectPart>
+    </Part>
+    <Part>
+      <SceneObjectPart xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+        <AllowedDrop>false</AllowedDrop>
+        <CreatorID>
+          <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+        </CreatorID>
+        <FolderID>
+          <UUID>c91e4ec6-4cd3-4748-b26e-78224700ca88</UUID>
+        </FolderID>
+        <InventorySerial>0</InventorySerial>
+        <UUID>
+          <UUID>c91e4ec6-4cd3-4748-b26e-78224700ca88</UUID>
+        </UUID>
+        <LocalId>656849181</LocalId>
+        <Name>chimney#18</Name>
+        <Material>3</Material>
+        <PassTouches>false</PassTouches>
+        <PassCollisions>false</PassCollisions>
+        <RegionHandle>4008819395804416</RegionHandle>
+        <ScriptAccessPin>0</ScriptAccessPin>
+        <GroupPosition>
+          <X>192.3722</X>
+          <Y>185.4859</Y>
+          <Z>53.20147</Z>
+        </GroupPosition>
+        <OffsetPosition>
+          <X>-0.1209307</X>
+          <Y>0.5349486</Y>
+          <Z>-1.604157</Z>
+        </OffsetPosition>
+        <RotationOffset>
+          <X>0.399266</X>
+          <Y>-0.505189</Y>
+          <Z>0.4334392</Z>
+          <W>0.6304771</W>
+        </RotationOffset>
+        <Velocity>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </Velocity>
+        <AngularVelocity>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </AngularVelocity>
+        <Acceleration>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </Acceleration>
+        <Description />
+        <Color>
+          <R>0</R>
+          <G>0</G>
+          <B>0</B>
+          <A>255</A>
+        </Color>
+        <Text />
+        <SitName />
+        <TouchName />
+        <LinkNum>19</LinkNum>
+        <ClickAction>0</ClickAction>
+        <Shape>
+          <ProfileCurve>48</ProfileCurve>
+          <TextureEntry>ssVeVY8UTMCZcSDK3Uhq1AAAAAAAAAAAgD8AAACAPwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==</TextureEntry>
+          <ExtraParams>ATAAEQAAAO2kiRGEfECzrunj6boHwHkF</ExtraParams>
+          <PathBegin>0</PathBegin>
+          <PathCurve>32</PathCurve>
+          <PathEnd>0</PathEnd>
+          <PathRadiusOffset>0</PathRadiusOffset>
+          <PathRevolutions>0</PathRevolutions>
+          <PathScaleX>100</PathScaleX>
+          <PathScaleY>150</PathScaleY>
+          <PathShearX>0</PathShearX>
+          <PathShearY>0</PathShearY>
+          <PathSkew>0</PathSkew>
+          <PathTaperX>0</PathTaperX>
+          <PathTaperY>0</PathTaperY>
+          <PathTwist>0</PathTwist>
+          <PathTwistBegin>0</PathTwistBegin>
+          <PCode>9</PCode>
+          <ProfileBegin>0</ProfileBegin>
+          <ProfileEnd>0</ProfileEnd>
+          <ProfileHollow>0</ProfileHollow>
+          <State>0</State>
+          <LastAttachPoint>0</LastAttachPoint>
+          <ProfileShape>Circle</ProfileShape>
+          <HollowShape>Triangle</HollowShape>
+          <SculptTexture>
+            <UUID>eda48911-847c-40b3-aee9-e3e9ba07c079</UUID>
+          </SculptTexture>
+          <SculptType>5</SculptType>
+          <FlexiSoftness>0</FlexiSoftness>
+          <FlexiTension>0</FlexiTension>
+          <FlexiDrag>0</FlexiDrag>
+          <FlexiGravity>0</FlexiGravity>
+          <FlexiWind>0</FlexiWind>
+          <FlexiForceX>0</FlexiForceX>
+          <FlexiForceY>0</FlexiForceY>
+          <FlexiForceZ>0</FlexiForceZ>
+          <LightColorR>0</LightColorR>
+          <LightColorG>0</LightColorG>
+          <LightColorB>0</LightColorB>
+          <LightColorA>1</LightColorA>
+          <LightRadius>0</LightRadius>
+          <LightCutoff>0</LightCutoff>
+          <LightFalloff>0</LightFalloff>
+          <LightIntensity>1</LightIntensity>
+          <FlexiEntry>false</FlexiEntry>
+          <LightEntry>false</LightEntry>
+          <SculptEntry>true</SculptEntry>
+        </Shape>
+        <Scale>
+          <X>0.1059241</X>
+          <Y>0.1127209</Y>
+          <Z>0.2263305</Z>
+        </Scale>
+        <SitTargetOrientation>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+          <W>1</W>
+        </SitTargetOrientation>
+        <SitTargetPosition>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </SitTargetPosition>
+        <SitTargetPositionLL>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </SitTargetPositionLL>
+        <SitTargetOrientationLL>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+          <W>1</W>
+        </SitTargetOrientationLL>
+        <ParentID>656849163</ParentID>
+        <CreationDate>1614974861</CreationDate>
+        <Category>0</Category>
+        <SalePrice>0</SalePrice>
+        <ObjectSaleType>0</ObjectSaleType>
+        <OwnershipCost>0</OwnershipCost>
+        <GroupID>
+          <UUID>5f1ea2fb-d489-44ce-a41d-a8d2a18c343c</UUID>
+        </GroupID>
+        <OwnerID>
+          <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+        </OwnerID>
+        <LastOwnerID>
+          <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+        </LastOwnerID>
+        <RezzerID>
+          <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+        </RezzerID>
+        <BaseMask>647168</BaseMask>
+        <OwnerMask>647168</OwnerMask>
+        <GroupMask>0</GroupMask>
+        <EveryoneMask>0</EveryoneMask>
+        <NextOwnerMask>532480</NextOwnerMask>
+        <Flags>None</Flags>
+        <CollisionSound>
+          <UUID>00000000-0000-0000-0000-000000000000</UUID>
+        </CollisionSound>
+        <CollisionSoundVolume>0</CollisionSoundVolume>
+        <MediaUrl />
+        <AttachedPos>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </AttachedPos>
+        <TextureAnimation></TextureAnimation>
+        <ParticleSystem></ParticleSystem>
+        <PayPrice0>-2</PayPrice0>
+        <PayPrice1>-2</PayPrice1>
+        <PayPrice2>-2</PayPrice2>
+        <PayPrice3>-2</PayPrice3>
+        <PayPrice4>-2</PayPrice4>
+        <Buoyancy>0</Buoyancy>
+        <Force>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </Force>
+        <Torque>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </Torque>
+        <VolumeDetectActive>false</VolumeDetectActive>
+        <PhysicsShapeType>0</PhysicsShapeType>
+        <CameraEyeOffset>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </CameraEyeOffset>
+        <CameraAtOffset>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </CameraAtOffset>
+        <SoundID>
+          <UUID>00000000-0000-0000-0000-000000000000</UUID>
+        </SoundID>
+        <SoundGain>0</SoundGain>
+        <SoundFlags>0</SoundFlags>
+        <SoundRadius>0</SoundRadius>
+        <SoundQueueing>false</SoundQueueing>
+      </SceneObjectPart>
+    </Part>
+    <Part>
+      <SceneObjectPart xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+        <AllowedDrop>false</AllowedDrop>
+        <CreatorID>
+          <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+        </CreatorID>
+        <FolderID>
+          <UUID>65de6405-5c2a-4979-88b9-21ad3d7a8b00</UUID>
+        </FolderID>
+        <InventorySerial>0</InventorySerial>
+        <UUID>
+          <UUID>65de6405-5c2a-4979-88b9-21ad3d7a8b00</UUID>
+        </UUID>
+        <LocalId>656849182</LocalId>
+        <Name>chimney#19</Name>
+        <Material>3</Material>
+        <PassTouches>false</PassTouches>
+        <PassCollisions>false</PassCollisions>
+        <RegionHandle>4008819395804416</RegionHandle>
+        <ScriptAccessPin>0</ScriptAccessPin>
+        <GroupPosition>
+          <X>192.3722</X>
+          <Y>185.4859</Y>
+          <Z>53.20147</Z>
+        </GroupPosition>
+        <OffsetPosition>
+          <X>0.746119</X>
+          <Y>2.129539</Y>
+          <Z>-1.877752</Z>
+        </OffsetPosition>
+        <RotationOffset>
+          <X>0.3992662</X>
+          <Y>-0.5051888</Y>
+          <Z>0.4334387</Z>
+          <W>0.6304772</W>
+        </RotationOffset>
+        <Velocity>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </Velocity>
+        <AngularVelocity>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </AngularVelocity>
+        <Acceleration>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </Acceleration>
+        <Description />
+        <Color>
+          <R>0</R>
+          <G>0</G>
+          <B>0</B>
+          <A>255</A>
+        </Color>
+        <Text />
+        <SitName />
+        <TouchName />
+        <LinkNum>20</LinkNum>
+        <ClickAction>0</ClickAction>
+        <Shape>
+          <ProfileCurve>48</ProfileCurve>
+          <TextureEntry>4mI72Pd/RS+ozrKPdFrS5AAAAAAAAAAAgD8AAACAPwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==</TextureEntry>
+          <ExtraParams>ATAAEQAAAAlygkdcwkeKktfbYNvW4zUF</ExtraParams>
+          <PathBegin>0</PathBegin>
+          <PathCurve>32</PathCurve>
+          <PathEnd>0</PathEnd>
+          <PathRadiusOffset>0</PathRadiusOffset>
+          <PathRevolutions>0</PathRevolutions>
+          <PathScaleX>100</PathScaleX>
+          <PathScaleY>150</PathScaleY>
+          <PathShearX>0</PathShearX>
+          <PathShearY>0</PathShearY>
+          <PathSkew>0</PathSkew>
+          <PathTaperX>0</PathTaperX>
+          <PathTaperY>0</PathTaperY>
+          <PathTwist>0</PathTwist>
+          <PathTwistBegin>0</PathTwistBegin>
+          <PCode>9</PCode>
+          <ProfileBegin>0</ProfileBegin>
+          <ProfileEnd>0</ProfileEnd>
+          <ProfileHollow>0</ProfileHollow>
+          <State>0</State>
+          <LastAttachPoint>0</LastAttachPoint>
+          <ProfileShape>Circle</ProfileShape>
+          <HollowShape>Triangle</HollowShape>
+          <SculptTexture>
+            <UUID>09728247-5cc2-478a-92d7-db60dbd6e335</UUID>
+          </SculptTexture>
+          <SculptType>5</SculptType>
+          <FlexiSoftness>0</FlexiSoftness>
+          <FlexiTension>0</FlexiTension>
+          <FlexiDrag>0</FlexiDrag>
+          <FlexiGravity>0</FlexiGravity>
+          <FlexiWind>0</FlexiWind>
+          <FlexiForceX>0</FlexiForceX>
+          <FlexiForceY>0</FlexiForceY>
+          <FlexiForceZ>0</FlexiForceZ>
+          <LightColorR>0</LightColorR>
+          <LightColorG>0</LightColorG>
+          <LightColorB>0</LightColorB>
+          <LightColorA>1</LightColorA>
+          <LightRadius>0</LightRadius>
+          <LightCutoff>0</LightCutoff>
+          <LightFalloff>0</LightFalloff>
+          <LightIntensity>1</LightIntensity>
+          <FlexiEntry>false</FlexiEntry>
+          <LightEntry>false</LightEntry>
+          <SculptEntry>true</SculptEntry>
+        </Shape>
+        <Scale>
+          <X>0.19945</X>
+          <Y>0.7049644</Y>
+          <Z>0.149362</Z>
+        </Scale>
+        <SitTargetOrientation>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+          <W>1</W>
+        </SitTargetOrientation>
+        <SitTargetPosition>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </SitTargetPosition>
+        <SitTargetPositionLL>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </SitTargetPositionLL>
+        <SitTargetOrientationLL>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+          <W>1</W>
+        </SitTargetOrientationLL>
+        <ParentID>656849163</ParentID>
+        <CreationDate>1614974861</CreationDate>
+        <Category>0</Category>
+        <SalePrice>0</SalePrice>
+        <ObjectSaleType>0</ObjectSaleType>
+        <OwnershipCost>0</OwnershipCost>
+        <GroupID>
+          <UUID>5f1ea2fb-d489-44ce-a41d-a8d2a18c343c</UUID>
+        </GroupID>
+        <OwnerID>
+          <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+        </OwnerID>
+        <LastOwnerID>
+          <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+        </LastOwnerID>
+        <RezzerID>
+          <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+        </RezzerID>
+        <BaseMask>647168</BaseMask>
+        <OwnerMask>647168</OwnerMask>
+        <GroupMask>0</GroupMask>
+        <EveryoneMask>0</EveryoneMask>
+        <NextOwnerMask>532480</NextOwnerMask>
+        <Flags>None</Flags>
+        <CollisionSound>
+          <UUID>00000000-0000-0000-0000-000000000000</UUID>
+        </CollisionSound>
+        <CollisionSoundVolume>0</CollisionSoundVolume>
+        <MediaUrl />
+        <AttachedPos>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </AttachedPos>
+        <TextureAnimation></TextureAnimation>
+        <ParticleSystem></ParticleSystem>
+        <PayPrice0>-2</PayPrice0>
+        <PayPrice1>-2</PayPrice1>
+        <PayPrice2>-2</PayPrice2>
+        <PayPrice3>-2</PayPrice3>
+        <PayPrice4>-2</PayPrice4>
+        <Buoyancy>0</Buoyancy>
+        <Force>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </Force>
+        <Torque>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </Torque>
+        <VolumeDetectActive>false</VolumeDetectActive>
+        <PhysicsShapeType>0</PhysicsShapeType>
+        <CameraEyeOffset>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </CameraEyeOffset>
+        <CameraAtOffset>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </CameraAtOffset>
+        <SoundID>
+          <UUID>00000000-0000-0000-0000-000000000000</UUID>
+        </SoundID>
+        <SoundGain>0</SoundGain>
+        <SoundFlags>0</SoundFlags>
+        <SoundRadius>0</SoundRadius>
+        <SoundQueueing>false</SoundQueueing>
+      </SceneObjectPart>
+    </Part>
+    <Part>
+      <SceneObjectPart xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+        <AllowedDrop>false</AllowedDrop>
+        <CreatorID>
+          <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+        </CreatorID>
+        <FolderID>
+          <UUID>17893e3f-6b58-4b13-baef-0b85d836cdb6</UUID>
+        </FolderID>
+        <InventorySerial>0</InventorySerial>
+        <UUID>
+          <UUID>17893e3f-6b58-4b13-baef-0b85d836cdb6</UUID>
+        </UUID>
+        <LocalId>656849183</LocalId>
+        <Name>chimney#20</Name>
+        <Material>3</Material>
+        <PassTouches>false</PassTouches>
+        <PassCollisions>false</PassCollisions>
+        <RegionHandle>4008819395804416</RegionHandle>
+        <ScriptAccessPin>0</ScriptAccessPin>
+        <GroupPosition>
+          <X>192.3722</X>
+          <Y>185.4859</Y>
+          <Z>53.20147</Z>
+        </GroupPosition>
+        <OffsetPosition>
+          <X>0.9185292</X>
+          <Y>1.150629</Y>
+          <Z>-1.714547</Z>
+        </OffsetPosition>
+        <RotationOffset>
+          <X>0.3992661</X>
+          <Y>-0.5051889</Y>
+          <Z>0.433439</Z>
+          <W>0.6304772</W>
+        </RotationOffset>
+        <Velocity>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </Velocity>
+        <AngularVelocity>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </AngularVelocity>
+        <Acceleration>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </Acceleration>
+        <Description />
+        <Color>
+          <R>0</R>
+          <G>0</G>
+          <B>0</B>
+          <A>255</A>
+        </Color>
+        <Text />
+        <SitName />
+        <TouchName />
+        <LinkNum>21</LinkNum>
+        <ClickAction>0</ClickAction>
+        <Shape>
+          <ProfileCurve>48</ProfileCurve>
+          <TextureEntry>4mI72Pd/RS+ozrKPdFrS5AAAAAAAAAAAgD8AAACAPwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==</TextureEntry>
+          <ExtraParams>ATAAEQAAAFk3I/HJHEmmjI8kDYrBYL0F</ExtraParams>
+          <PathBegin>0</PathBegin>
+          <PathCurve>32</PathCurve>
+          <PathEnd>0</PathEnd>
+          <PathRadiusOffset>0</PathRadiusOffset>
+          <PathRevolutions>0</PathRevolutions>
+          <PathScaleX>100</PathScaleX>
+          <PathScaleY>150</PathScaleY>
+          <PathShearX>0</PathShearX>
+          <PathShearY>0</PathShearY>
+          <PathSkew>0</PathSkew>
+          <PathTaperX>0</PathTaperX>
+          <PathTaperY>0</PathTaperY>
+          <PathTwist>0</PathTwist>
+          <PathTwistBegin>0</PathTwistBegin>
+          <PCode>9</PCode>
+          <ProfileBegin>0</ProfileBegin>
+          <ProfileEnd>0</ProfileEnd>
+          <ProfileHollow>0</ProfileHollow>
+          <State>0</State>
+          <LastAttachPoint>0</LastAttachPoint>
+          <ProfileShape>Circle</ProfileShape>
+          <HollowShape>Triangle</HollowShape>
+          <SculptTexture>
+            <UUID>593723f1-c91c-49a6-8c8f-240d8ac160bd</UUID>
+          </SculptTexture>
+          <SculptType>5</SculptType>
+          <FlexiSoftness>0</FlexiSoftness>
+          <FlexiTension>0</FlexiTension>
+          <FlexiDrag>0</FlexiDrag>
+          <FlexiGravity>0</FlexiGravity>
+          <FlexiWind>0</FlexiWind>
+          <FlexiForceX>0</FlexiForceX>
+          <FlexiForceY>0</FlexiForceY>
+          <FlexiForceZ>0</FlexiForceZ>
+          <LightColorR>0</LightColorR>
+          <LightColorG>0</LightColorG>
+          <LightColorB>0</LightColorB>
+          <LightColorA>1</LightColorA>
+          <LightRadius>0</LightRadius>
+          <LightCutoff>0</LightCutoff>
+          <LightFalloff>0</LightFalloff>
+          <LightIntensity>1</LightIntensity>
+          <FlexiEntry>false</FlexiEntry>
+          <LightEntry>false</LightEntry>
+          <SculptEntry>true</SculptEntry>
+        </Shape>
+        <Scale>
+          <X>0.1942144</X>
+          <Y>0.2396929</Y>
+          <Z>1.948992</Z>
+        </Scale>
+        <SitTargetOrientation>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+          <W>1</W>
+        </SitTargetOrientation>
+        <SitTargetPosition>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </SitTargetPosition>
+        <SitTargetPositionLL>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </SitTargetPositionLL>
+        <SitTargetOrientationLL>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+          <W>1</W>
+        </SitTargetOrientationLL>
+        <ParentID>656849163</ParentID>
+        <CreationDate>1614974861</CreationDate>
+        <Category>0</Category>
+        <SalePrice>0</SalePrice>
+        <ObjectSaleType>0</ObjectSaleType>
+        <OwnershipCost>0</OwnershipCost>
+        <GroupID>
+          <UUID>5f1ea2fb-d489-44ce-a41d-a8d2a18c343c</UUID>
+        </GroupID>
+        <OwnerID>
+          <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+        </OwnerID>
+        <LastOwnerID>
+          <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+        </LastOwnerID>
+        <RezzerID>
+          <UUID>ede7d00a-57fd-4942-8b7a-81364751a0f6</UUID>
+        </RezzerID>
+        <BaseMask>647168</BaseMask>
+        <OwnerMask>647168</OwnerMask>
+        <GroupMask>0</GroupMask>
+        <EveryoneMask>0</EveryoneMask>
+        <NextOwnerMask>532480</NextOwnerMask>
+        <Flags>None</Flags>
+        <CollisionSound>
+          <UUID>00000000-0000-0000-0000-000000000000</UUID>
+        </CollisionSound>
+        <CollisionSoundVolume>0</CollisionSoundVolume>
+        <MediaUrl />
+        <AttachedPos>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </AttachedPos>
+        <TextureAnimation></TextureAnimation>
+        <ParticleSystem></ParticleSystem>
+        <PayPrice0>-2</PayPrice0>
+        <PayPrice1>-2</PayPrice1>
+        <PayPrice2>-2</PayPrice2>
+        <PayPrice3>-2</PayPrice3>
+        <PayPrice4>-2</PayPrice4>
+        <Buoyancy>0</Buoyancy>
+        <Force>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </Force>
+        <Torque>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </Torque>
+        <VolumeDetectActive>false</VolumeDetectActive>
+        <PhysicsShapeType>0</PhysicsShapeType>
+        <CameraEyeOffset>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </CameraEyeOffset>
+        <CameraAtOffset>
+          <X>0</X>
+          <Y>0</Y>
+          <Z>0</Z>
+        </CameraAtOffset>
+        <SoundID>
+          <UUID>00000000-0000-0000-0000-000000000000</UUID>
+        </SoundID>
+        <SoundGain>0</SoundGain>
+        <SoundFlags>0</SoundFlags>
+        <SoundRadius>0</SoundRadius>
+        <SoundQueueing>false</SoundQueueing>
+      </SceneObjectPart>
+    </Part>
+  </OtherParts>
+</SceneObjectGroup>

BIN
bin/MAP-1a95e448-df46-45d2-8182-559ce0c27a5a.png


BIN
bin/MAP-1dba66ba-a66f-40f1-9159-44e2778230a0.png


BIN
bin/MAP-36083b8f-e6d9-44ad-8ed2-cc7fa1b2abeb.png


BIN
bin/MAP-49b83350-5540-11de-8a39-0800200c9a66.png


BIN
bin/MAP-5110d730-9f03-11de-8a39-0800200c9a66.png


BIN
bin/MAP-5e560eb0-9f03-11de-8a39-0800200c9a66.png


BIN
bin/MAP-63e7cac9-9f38-4855-bcea-988883578c1c.png


BIN
bin/MAP-68beb460-0dfc-456e-a233-ba939b07c55b.png


BIN
bin/MAP-6b9e2599-c083-4172-8582-c6c51547c503.png


BIN
bin/MAP-81695b2d-ab0c-4c12-9bcc-30e962b7ddfc.png


BIN
bin/MAP-86e4dd4d-6830-41b1-bd1a-44e980c2e67a.png


BIN
bin/MAP-95f6dca0-99fe-11de-8a39-0800200c9a66.png


BIN
bin/MAP-99605855-7e20-4721-9bd5-6dcb0f29f70e.png


BIN
bin/MAP-99b7db71-57bb-4669-80cf-d6d28ab4fd7c.png


BIN
bin/MAP-a68a4cd2-bcdb-45f0-a793-f202f2347935.png


BIN
bin/MAP-c1de8dea-caa7-453e-aba7-e823b22768fc.png


BIN
bin/MAP-cd0af1d7-9adc-4898-98ec-b4593f986451.png


BIN
bin/MAP-d0c7a2ab-a565-41fa-8a24-2b5bd0664a2b.png


BIN
bin/MAP-d1a5701b-2fcf-48a7-a420-6966bbf138c1.png


BIN
bin/MAP-d468609c-8b8e-4505-8c12-8110c15d51d4.png


BIN
bin/MAP-db95bbe0-533c-11de-8a39-0800200c9a66.png


BIN
bin/MAP-e53b7c60-a452-11e1-b3dd-0800200c9a66.png


BIN
bin/MAP-ea329ae9-0f31-462f-bcd9-b19daae22516.png


BIN
bin/MAP-eb24d66c-5d8a-4592-bf36-e4d5116bc13e.png


BIN
bin/MAP-f154dd20-a558-11df-981c-0800200c9a66.png


+ 71 - 0
bin/OpenSim.exe.config

@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<configuration>
+  <configSections>
+    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net" />
+  </configSections>
+  <runtime>
+    <loadFromRemoteSources enabled="true" />
+  </runtime>
+  <appSettings>
+  </appSettings>
+  
+  <log4net>
+    <appender name="Console" type="OpenSim.Framework.Console.OpenSimAppender, OpenSim.Framework.Console">
+      <filter type="log4net.Filter.LoggerMatchFilter">
+        <loggerToMatch value="special"/>
+        <acceptOnMatch value="false"/>
+      </filter>
+      <layout type="log4net.Layout.PatternLayout">
+        <conversionPattern value="%date{HH:mm:ss} - %message" />
+        <!-- console log with milliseconds.  Useful for debugging -->
+<!--        <conversionPattern value="%date{HH:mm:ss.fff} - %message" /> -->
+      </layout>
+    </appender>
+
+<!-- If you want automatic log-rolling then use RollingFileAppender instead of FileAppender:
+    <appender name="LogFileAppender" type="log4net.Appender.RollingFileAppender">
+      <file value="log/OpenSim.log" />
+      <rollingStyle value="Date" />
+      <datePattern value="'.'yyyy-MM-dd"/>
+      ...
+-->
+
+    <appender name="LogFileAppender" type="log4net.Appender.FileAppender">
+      <file value="OpenSim.log" />
+      <appendToFile value="true" />
+      <filter type="log4net.Filter.LoggerMatchFilter">
+        <loggerToMatch value="special"/>
+        <acceptOnMatch value="false"/>
+      </filter>
+      <layout type="log4net.Layout.PatternLayout">
+        <!-- <conversionPattern value="%date %-5level (%thread) - %logger %message%newline" /> -->
+        <conversionPattern value="%date %-5level %message%newline" />
+      </layout>
+    </appender>
+
+    <appender name="StatsLogFileAppender" type="log4net.Appender.FileAppender">
+      <file value="OpenSimStats.log"/>
+      <appendToFile value="true" />
+      <layout type="log4net.Layout.PatternLayout">
+        <conversionPattern value="%date - %message%newline" />
+      </layout>
+    </appender>
+
+    <root>
+      <level value="DEBUG" />
+      <appender-ref ref="Console" />
+      <appender-ref ref="LogFileAppender" />
+    </root>
+
+    <!-- Independently control logging level for per region module loading -->
+    <logger name="OpenSim.ApplicationPlugins.RegionModulesController.RegionModulesControllerPlugin">
+      <level value="INFO"/>
+    </logger>
+
+    <!-- used for stats recording -->
+    <logger name="special.StatsLogger">
+      <appender-ref ref="StatsLogFileAppender"/>
+    </logger>
+
+  </log4net>
+</configuration>

+ 28 - 0
bin/OpenSim.ini.example

@@ -943,6 +943,34 @@
 	;; ignore its extensions (subset of original XMRengine), those are still undefined.
     ; Enabled = false
 
+    ;; llSetTimerEvent minimum value. Default 0.5s, 0.05s whould be more resonable
+    ; MinTimerInterval = 0.5
+
+    ;# {ScriptDelayFactor} {} {Multiplier for scripting delays} {} 1.0
+    ;; Sets the multiplier for the scripting delays
+    ; ScriptDelayFactor = 1.0
+
+    ;# {ScriptDistanceLimitFactor} {} {Multiplier for 10.0m distance limits?} {}
+    ;; The factor the 10 m distances limits are multiplied by
+    ; ScriptDistanceLimitFactor = 1.0
+
+    ;# {NotecardLineReadCharsMax} {} {Maximum length of notecard line?} {} 255
+    ;; Maximum length of notecard line read
+    ;; Increasing this to large values potentially opens
+    ;; up the system to malicious scripters
+    ; NotecardLineReadCharsMax = 255
+
+    ;# {SensorMaxRange} {} {Sensor range} {} 96.0
+    ;; Sensor settings
+    ; SensorMaxRange = 96.0
+    ;# {SensorMaxResults} {} {Max sensor results returned?} {}
+    ; SensorMaxResults = 16
+
+    ;# {ScriptEnginesPath} {} {Path to script assemblies} {} ScriptEngines
+    ;; Path to script engine assemblies
+    ;; Default is ./bin/ScriptEngines
+    ; ScriptEnginesPath = "ScriptEngines"
+
 
 [XEngine]
     ;# {Enabled} {} {Enable the XEngine scripting engine?} {true false} true

+ 1 - 0
bin/ROBUST.pid

@@ -0,0 +1 @@
+3846

+ 5 - 5
bin/Robust.exe.config

@@ -20,17 +20,17 @@
       </layout>
     </appender>
 
-<!-- If you want automatic log-rolling then use RollingFileAppender instead of FileAppender:
+<!-- If you want automatic log-rolling then use RollingFileAppender instead of FileAppender: -->
     <appender name="LogFileAppender" type="log4net.Appender.RollingFileAppender">
       <file value="log/Robust.log" />
       <rollingStyle value="Date" />
       <datePattern value="'.'yyyy-MM-dd"/>
-      ...
--->
-
+<!--
     <appender name="LogFileAppender" type="log4net.Appender.FileAppender">
-      <file value="Robust.log" />
+      <file value="Robust.log" /> -->
       <appendToFile value="true" />
+      <maximumFileSize value="1000KB" />
+      <maxSizeRollBackups value="2" /> 
       <filter type="log4net.Filter.LoggerMatchFilter">
         <loggerToMatch value="special"/>
         <acceptOnMatch value="false"/>

+ 24 - 1
bin/ScriptSyntax.xml

@@ -1,4 +1,4 @@
-cd5e081a-b88a-07b6-21a5-612aab0b3398
+727420c2-45b3-4627-8c6e-5c478e6a736e
 <llsd><map><key>llsd-lsl-syntax-version</key><integer>2</integer>
 <key>controls</key>
 <map>
@@ -7196,6 +7196,16 @@ cd5e081a-b88a-07b6-21a5-612aab0b3398
    <map><key>notecard</key><map><key>type</key><string>string</string></map></map>
   </array>
  </map>
+ <key>osNpcLookAt</key>
+ <map>
+  <key>arguments</key><array>
+   <map><key>npc</key><map><key>type</key><string>key</string></map></map>
+   <map><key>type</key><map><key>type</key><string>integer</string></map></map>
+   <map><key>target</key><map><key>type</key><string>key</string></map></map>
+   <map><key>offset</key><map><key>type</key><string>vector</string></map></map>
+  </array>
+  <key>tooltip</key><string>Makes an NPC look at a target. Other effects besides looking are also supported.</string>
+ </map>
  <key>osNpcMoveTo</key>
  <map>
   <key>arguments</key><array>
@@ -7449,6 +7459,19 @@ cd5e081a-b88a-07b6-21a5-612aab0b3398
    <map><key>daycycle</key><map><key>type</key><string>string</string></map></map>
   </array>
  </map>
+ <key>osReplaceRegionEnvironment</key>
+ <map>
+  <key>return</key><string>integer</string>
+  <key>arguments</key><array>
+   <map><key>transition</key><map><key>type</key><string>integer</string></map></map>
+   <map><key>daycycle</key><map><key>type</key><string>string</string></map></map>
+   <map><key>daylen</key><map><key>type</key><string>float</string></map></map>
+   <map><key>dayoffset</key><map><key>type</key><string>float</string></map></map>
+   <map><key>altitude1</key><map><key>type</key><string>float</string></map></map>
+   <map><key>altitude2</key><map><key>type</key><string>float</string></map></map>
+   <map><key>altitude3</key><map><key>type</key><string>float</string></map></map>
+  </array>
+ </map>
  <key>osReplaceString</key>
  <map>
   <key>return</key><string>string</string>

+ 28 - 14
bin/assets/SettingsAssetSet/SettingsAssetSet.xml

@@ -1,11 +1,10 @@
 <Nini>
-  <Section Name="Default Daycycle(3/1)">
+  <Section Name="Default Daycycle (More Daylight)">
     <Key Name="assetID" Value="5646d39e-d3d7-6aff-ed71-30fc87d64a92" />
-    <Key Name="name" Value="Default Daycycle(3/1)" />
+    <Key Name="name" Value="Default Daycycle (More Daylight)" />
     <Key Name="assetType" Value="56" />
     <Key Name="fileName" Value="DefaultDaycycle31.dat" />
   </Section>
-  
   <Section Name="Default Daycycle">
     <Key Name="assetID" Value="5646d39e-d3d7-6aff-ed71-30fc87d64a91" />
     <Key Name="name" Value="Default Daycycle" />
@@ -19,35 +18,24 @@
     <Key Name="assetType" Value="56" />
     <Key Name="fileName" Value="DefaultSky.dat" />
   </Section>
-
-  <Section Name="Default Water">
-    <Key Name="assetID" Value="59d1a851-47e7-0e5f-1ed7-6b715154f41a" />
-    <Key Name="name" Value="Default Water" />
-    <Key Name="assetType" Value="56" />
-    <Key Name="fileName" Value="DefaultWater.dat" />
-  </Section>
-
   <Section Name="Sunrise">
     <Key Name="assetID" Value="01e41537-ff51-2f1f-8ef7-17e4df760bfb" />
     <Key Name="name" Value="Sunrise" />
     <Key Name="assetType" Value="56" />
     <Key Name="fileName" Value="Sunrise.dat" />
   </Section>
-
   <Section Name="Midday">
     <Key Name="assetID" Value="6c83e853-e7f8-cad7-8ee6-5f31c453721c" />
     <Key Name="name" Value="Midday" />
     <Key Name="assetType" Value="56" />
     <Key Name="fileName" Value="Midday.dat" />
   </Section>
-
   <Section Name="Sunset">
     <Key Name="assetID" Value="084e26cd-a900-28e8-08d0-64a9de5c15e2" />
     <Key Name="name" Value="Sunset" />
     <Key Name="assetType" Value="56" />
     <Key Name="fileName" Value="Sunset.dat" />
   </Section>
-
   <Section Name="Midnight">
     <Key Name="assetID" Value="8a01b97a-cb20-c1ea-ac63-f7ea84ad0090" />
     <Key Name="name" Value="Midnight" />
@@ -55,5 +43,31 @@
     <Key Name="fileName" Value="Midnight.dat" />
   </Section>
 
+  <Section Name="Default Water">
+    <Key Name="assetID" Value="59d1a851-47e7-0e5f-1ed7-6b715154f41a" />
+    <Key Name="name" Value="Default Water" />
+    <Key Name="assetType" Value="56" />
+    <Key Name="fileName" Value="Water/DefaultWater.dat" />
+  </Section>
+
+  <Section Name="Altocumulus Clouds">
+    <Key Name="assetID" Value="ffc4de4a-9845-41c1-9f9f-762a059d0bdc" />
+    <Key Name="name" Value="Altocumulus Clouds" />
+    <Key Name="assetType" Value="0" />
+    <Key Name="fileName" Value="Textures/Altocumulus_Clouds.j2c" />
+  </Section>
+  <Section Name="Cumulonimbus Clouds">
+    <Key Name="assetID" Value="a3ee7f3c-dc2e-4526-9d7c-67824959c6f6" />
+    <Key Name="name" Value="Cumulonimbus Clouds" />
+    <Key Name="assetType" Value="0" />
+    <Key Name="fileName" Value="Textures/Cumulonimbus_Clouds.j2c" />
+  </Section>
+  <Section Name="Layered Clouds">
+    <Key Name="assetID" Value="6e500a99-8831-47d2-b2a8-2e725396d449" />
+    <Key Name="name" Value="Layered Clouds" />
+    <Key Name="assetType" Value="0" />
+    <Key Name="fileName" Value="Textures/Layered_Clouds.j2c" />
+  </Section>
+
 </Nini>
 

BIN
bin/assets/SettingsAssetSet/Textures/Altocumulus_Clouds.j2c


BIN
bin/assets/SettingsAssetSet/Textures/Cumulonimbus_Clouds.j2c


BIN
bin/assets/SettingsAssetSet/Textures/Layered_Clouds.j2c


BIN
bin/assets/SettingsAssetSet/Water/DefaultWater.dat


+ 235 - 0
bin/config-include/osslDefaultEnable.ini

@@ -0,0 +1,235 @@
+; Enable OSSL functions.
+; Including this file in a region's set of INI files, causes the OpenSimulator
+;   specific functions to be enabled.
+; See http://opensimulator.org/wiki/Category:OSSL_Functions for a description of OSSL functions
+; do not edit this file.
+; copy the line you want to change and paste it on osslEnable.ini, then change there
+
+
+[OSSL]
+  ; Allow the use of os* functions (some are always available)
+  AllowOSFunctions = true
+
+  ; Allow the user of mod* functions.  This allows a script to pass messages
+  ;   to a region module via the modSendCommand() function and is used by some
+  ;   modules to extend the scripting language.
+  AllowMODFunctions = true
+
+  ; Allow the use of LightShare functions.
+  ; The setting enable_windlight = true must also be enabled in the [LightShare] section.
+  AllowLightShareFunctions = true
+
+  ; Send function permission error to owner if true, to all if false
+  PermissionErrorToOwner = false
+  
+  ; Function Threat level
+  ; Several functions have a predefined threat level, one of:  None, VeryLow, Low, Moderate, High, VeryHigh, Severe.
+  ; See http://opensimulator.org/wiki/Threat_level for more information on these levels.
+  ; Blanket enabling the ossl functions is dangerous and we do not recommend setting higher
+  ;   than 'Low' unless you have a high level of trust in all the users that can run scripts
+  ;   in your simulator.  It is safer to explicitly allow certain types of user to run
+  ;   higher threat level OSSL functions, as detailed later on.
+  ; This setting defines the highest level allowed to execute
+  OSFunctionThreatLevel = VeryLow
+
+  ; The threat level can be replaced by more detailed rules by lines of the form
+  ; Allow_FunctionName = parameters
+  ; To use the default threat level coment the respective line
+  ; parameters can be:
+  ; 'false' disables the function.
+  ; 'true' enables for everyone
+  ;  or to enable for individuals or groups, set it to a comma separated list. This checks
+  ;    against the owner of the object containing the script.
+  ;    The comma separated entries in the list may be one of:
+  ;           "GRID_GOD" -- enable for users with UserLevel >= 200
+  ;           "GOD" -- enable for users with rights to be god (local or grid)
+  ;           "ACTIVE_GOD" -- enable for users that are present and with active god power
+  ;           "ESTATE_MANAGER" -- enable for estate manager
+  ;           "ESTATE_OWNER" -- enable for estate owner
+  ;           "PARCEL_OWNER" -- enable for parcel owner
+  ;           "PARCEL_GROUP_MEMBER" -- enable for any member of the parcel group
+  ;           uuid -- enable for specified ID (may be avatar or group ID)
+  ;    from this we can also create macros that can be include in the list as
+  ;    ${OSSL|macroname} see examples below
+
+  ; parcel macros
+  ; Allowing ossl functions for anyone owning a parcel can be dangerous especially if
+  ;    a region is selling or otherwise giving away parcel ownership. By default, parcel
+  ;    ownership or group membership does not enable OSSL functions. Uncomment the
+  ;    appropriate line below to allow parcel ownership and groups to do restricted
+  ;    OSSL functions. It might be better to check the list below and edit the ones
+  ;    to enable individually.
+  osslParcelO = ""
+  osslParcelOG = ""
+  ; osslParcelO = "PARCEL_OWNER,"
+  ; osslParcelOG = "PARCEL_GROUP_MEMBER,PARCEL_OWNER,"
+
+  ; NPC macros
+  ; These can be mis-used so limit use to those you can trust.
+  osslNPC = ${OSSL|osslParcelOG}ESTATE_MANAGER,ESTATE_OWNER
+  
+  ; The threat level also can be replaced by lines of the form
+  ; Creators__FunctionName = comma separated list of UUIDs
+  ; this will enable the function for users that are the script creators and owners of the prim
+
+
+  ; *************************************************
+
+  ; ThreatLevel  None
+  Allow_osGetAgents =               ${OSSL|osslParcelOG}ESTATE_MANAGER,ESTATE_OWNER
+  Allow_osGetAvatarList =           ${OSSL|osslParcelOG}ESTATE_MANAGER,ESTATE_OWNER
+  ;Allow_osGetGender =               true
+  ;Allow_osGetHealth =               true
+  ;Allow_osGetHealRate =             true
+  Allow_osGetNPCList =              ${OSSL|osslParcelOG}ESTATE_MANAGER,ESTATE_OWNER
+  ;Allow_osGetRezzingObject =        true
+  ;Allow_osGetSunParam =             true
+  Allow_osNpcGetOwner =             ${OSSL|osslNPC}
+  Allow_osSetSunParam =             ESTATE_MANAGER,ESTATE_OWNER
+  Allow_osTeleportOwner =           ${OSSL|osslParcelOG}ESTATE_MANAGER,ESTATE_OWNER
+  ;Allow_osWindActiveModelPluginName = true
+
+  ; ThreatLevel  Nuisance
+  Allow_osSetEstateSunSettings =    ESTATE_MANAGER,ESTATE_OWNER
+  Allow_osSetRegionSunSettings =    ESTATE_MANAGER,ESTATE_OWNER
+
+  ; ThreatLevel  VeryLow
+  Allow_osEjectFromGroup =          ${OSSL|osslParcelOG}ESTATE_MANAGER,ESTATE_OWNER
+  Allow_osForceBreakAllLinks =      ${OSSL|osslParcelOG}ESTATE_MANAGER,ESTATE_OWNER
+  Allow_osForceBreakLink =          ${OSSL|osslParcelOG}ESTATE_MANAGER,ESTATE_OWNER
+  Allow_osGetWindParam =            true
+  Allow_osInviteToGroup =           ${OSSL|osslParcelOG}ESTATE_MANAGER,ESTATE_OWNER
+  Allow_osReplaceString =           true
+  Allow_osSetDynamicTextureData =       ${OSSL|osslParcelOG}ESTATE_MANAGER,ESTATE_OWNER
+  Allow_osSetDynamicTextureDataFace =   ${OSSL|osslParcelOG}ESTATE_MANAGER,ESTATE_OWNER
+  Allow_osSetDynamicTextureDataBlend =  ${OSSL|osslParcelOG}ESTATE_MANAGER,ESTATE_OWNER
+  Allow_osSetDynamicTextureDataBlendFace = ${OSSL|osslParcelOG}ESTATE_MANAGER,ESTATE_OWNER
+  Allow_osSetParcelMediaURL =       ${OSSL|osslParcelOG}ESTATE_MANAGER,ESTATE_OWNER
+  Allow_osSetParcelMusicURL =       ${OSSL|osslParcelOG}ESTATE_MANAGER,ESTATE_OWNER
+  Allow_osSetParcelSIPAddress =     ${OSSL|osslParcelOG}ESTATE_MANAGER,ESTATE_OWNER
+  Allow_osSetPrimFloatOnWater =     true
+  Allow_osSetWindParam =            ${OSSL|osslParcelOG}ESTATE_MANAGER,ESTATE_OWNER
+  Allow_osTerrainFlush =            ESTATE_MANAGER,ESTATE_OWNER
+  Allow_osUnixTimeToTimestamp =     true
+
+  ; ThreatLevel  Low
+  Allow_osAvatarName2Key =          ${OSSL|osslParcelO}ESTATE_MANAGER,ESTATE_OWNER
+  Allow_osFormatString =            true
+  Allow_osKey2Name =                ${OSSL|osslParcelO}ESTATE_MANAGER,ESTATE_OWNER
+  Allow_osListenRegex =             true
+  Allow_osLoadedCreationDate =      ${OSSL|osslParcelOG}ESTATE_MANAGER,ESTATE_OWNER
+  Allow_osLoadedCreationID =        ${OSSL|osslParcelOG}ESTATE_MANAGER,ESTATE_OWNER
+  Allow_osLoadedCreationTime =      ${OSSL|osslParcelOG}ESTATE_MANAGER,ESTATE_OWNER
+  Allow_osMessageObject =           ${OSSL|osslParcelOG}ESTATE_MANAGER,ESTATE_OWNER
+  Allow_osRegexIsMatch =            true
+  Allow_osGetAvatarHomeURI =        ${OSSL|osslParcelOG}ESTATE_MANAGER,ESTATE_OWNER
+  Allow_osNpcSetProfileAbout =      ${OSSL|osslNPC}
+  Allow_osNpcSetProfileImage =      ${OSSL|osslNPC}
+  Allow_osDie =                     ${OSSL|osslParcelOG}ESTATE_MANAGER,ESTATE_OWNER
+
+  ; ThreatLevel  Moderate
+  Allow_osDetectedCountry =         ${OSSL|osslParcelO}ESTATE_MANAGER,ESTATE_OWNER
+  Allow_osDropAttachment =          ${OSSL|osslParcelO}ESTATE_MANAGER,ESTATE_OWNER
+  Allow_osDropAttachmentAt =        ${OSSL|osslParcelO}ESTATE_MANAGER,ESTATE_OWNER
+  Allow_osGetAgentCountry =         ${OSSL|osslParcelO}ESTATE_MANAGER,ESTATE_OWNER
+  Allow_osGetGridCustom =           ${OSSL|osslParcelO}ESTATE_MANAGER,ESTATE_OWNER
+  Allow_osGetGridGatekeeperURI =    ${OSSL|osslParcelO}ESTATE_MANAGER,ESTATE_OWNER
+  Allow_osGetGridHomeURI =          ${OSSL|osslParcelO}ESTATE_MANAGER,ESTATE_OWNER
+  Allow_osGetGridLoginURI =         ${OSSL|osslParcelO}ESTATE_MANAGER,ESTATE_OWNER
+  Allow_osGetGridName =             true
+  Allow_osGetGridNick =             true
+  Allow_osGetNumberOfAttachments =  ${OSSL|osslParcelO}ESTATE_MANAGER,ESTATE_OWNER
+  Allow_osGetRegionStats =          ${OSSL|osslParcelO}ESTATE_MANAGER,ESTATE_OWNER
+  Allow_osGetSimulatorMemory =      ${OSSL|osslParcelO}ESTATE_MANAGER,ESTATE_OWNER
+  Allow_osGetSimulatorMemoryKB =    ${OSSL|osslParcelO}ESTATE_MANAGER,ESTATE_OWNER
+  Allow_osMessageAttachments =      ${OSSL|osslParcelO}ESTATE_MANAGER,ESTATE_OWNER
+  Allow_osReplaceAgentEnvironment = ${OSSL|osslParcelO}ESTATE_MANAGER,ESTATE_OWNER
+  Allow_osSetSpeed =                ${OSSL|osslParcelO}ESTATE_MANAGER,ESTATE_OWNER
+  Allow_osSetOwnerSpeed =           ${OSSL|osslParcelO}ESTATE_MANAGER,ESTATE_OWNER
+  Allow_osRequestURL =              ${OSSL|osslParcelO}ESTATE_MANAGER,ESTATE_OWNER
+  Allow_osRequestSecureURL =        ${OSSL|osslParcelO}ESTATE_MANAGER,ESTATE_OWNER
+
+  ; ThreatLevel High
+  Allow_osCauseDamage =             ${OSSL|osslParcelO}ESTATE_MANAGER,ESTATE_OWNER
+  Allow_osCauseHealing =            ${OSSL|osslParcelO}ESTATE_MANAGER,ESTATE_OWNER
+  Allow_osSetHealth =               ${OSSL|osslParcelO}ESTATE_MANAGER,ESTATE_OWNER
+  Allow_osSetHealRate =             ${OSSL|osslParcelO}ESTATE_MANAGER,ESTATE_OWNER
+  Allow_osForceAttachToAvatar =     ${OSSL|osslParcelO}ESTATE_MANAGER,ESTATE_OWNER
+  Allow_osForceAttachToAvatarFromInventory = ${OSSL|osslParcelO}ESTATE_MANAGER,ESTATE_OWNER
+  Allow_osForceCreateLink =         ${OSSL|osslParcelO}ESTATE_MANAGER,ESTATE_OWNER
+  Allow_osForceDropAttachment =     ${OSSL|osslParcelO}ESTATE_MANAGER,ESTATE_OWNER
+  Allow_osForceDropAttachmentAt =   ${OSSL|osslParcelO}ESTATE_MANAGER,ESTATE_OWNER
+  Allow_osGetLinkPrimitiveParams =  ${OSSL|osslParcelO}ESTATE_MANAGER,ESTATE_OWNER
+  Allow_osGetPhysicsEngineType =    true
+  Allow_osGetRegionMapTexture =     ${OSSL|osslParcelO}ESTATE_MANAGER,ESTATE_OWNER
+  Allow_osGetScriptEngineName =     true
+  Allow_osGetSimulatorVersion =     true
+  Allow_osMakeNotecard =            ${OSSL|osslParcelO}ESTATE_MANAGER,ESTATE_OWNER
+  Allow_osMatchString =             true
+  Allow_osNpcCreate =               ${OSSL|osslNPC}
+  Allow_osNpcGetPos =               ${OSSL|osslNPC}
+  Allow_osNpcGetRot =               ${OSSL|osslNPC}
+  Allow_osNpcLoadAppearance =       ${OSSL|osslNPC}
+  Allow_osNpcMoveTo =               ${OSSL|osslNPC}
+  Allow_osNpcMoveToTarget =         ${OSSL|osslNPC}
+  Allow_osNpcPlayAnimation =        ${OSSL|osslNPC}
+  Allow_osNpcRemove =               ${OSSL|osslNPC}
+  Allow_osNpcSaveAppearance =       ${OSSL|osslNPC}
+  Allow_osNpcSay =                  ${OSSL|osslNPC}
+  Allow_osNpcSayTo =                ${OSSL|osslNPC}
+  Allow_osNpcSetRot =               ${OSSL|osslNPC}
+  Allow_osNpcShout =                ${OSSL|osslNPC}
+  Allow_osNpcSit =                  ${OSSL|osslNPC}
+  Allow_osNpcStand =                ${OSSL|osslNPC}
+  Allow_osNpcStopAnimation =        ${OSSL|osslNPC}
+  Allow_osNpcStopMoveToTarget =     ${OSSL|osslNPC}
+  Allow_osNpcTouch =                ${OSSL|osslNPC}
+  Allow_osNpcWhisper =              ${OSSL|osslNPC}
+  Allow_osOwnerSaveAppearance =     ${OSSL|osslParcelO}ESTATE_MANAGER,ESTATE_OWNER
+  Allow_osParcelJoin =              ESTATE_MANAGER,ESTATE_OWNER
+  Allow_osParcelSubdivide =         ESTATE_MANAGER,ESTATE_OWNER
+  Allow_osRegionRestart =           ESTATE_MANAGER,ESTATE_OWNER
+  Allow_osRegionNotice =            ESTATE_MANAGER,ESTATE_OWNER
+  Allow_osSetProjectionParams =     ${OSSL|osslParcelOG}ESTATE_MANAGER,ESTATE_OWNER
+  Allow_osSetRegionWaterHeight =    ESTATE_MANAGER,ESTATE_OWNER
+  Allow_osSetTerrainHeight =        ESTATE_MANAGER,ESTATE_OWNER
+  Allow_osSetTerrainTexture =       ESTATE_MANAGER,ESTATE_OWNER
+  Allow_osSetTerrainTextureHeight = ESTATE_MANAGER,ESTATE_OWNER
+
+  ; ThreatLevel  VeryHigh
+  Allow_osAgentSaveAppearance =     ESTATE_MANAGER,ESTATE_OWNER
+  ; Warning: The next function allows scripts to force animations on avatars without the user giving permission.
+  ;   Enabling this can allow forced animations which can trigger traumatic episodes in vulnerable populations.
+  ;   Similar things can be said for several of the 'force' functions. Enable with care and control.
+  ; Some of these were added as early functionality for NPCs. This has been replaced with the NPC functions.
+  Allow_osAvatarPlayAnimation =     false
+  Allow_osAvatarStopAnimation =     false
+  Allow_osForceAttachToOtherAvatarFromInventory = false
+  Allow_osForceDetachFromAvatar =   false
+  Allow_osForceOtherSit =           false
+  ; The notecard functions can cause a lot of load on the region if over used
+  Allow_osGetNotecard =             ${OSSL|osslParcelO}ESTATE_MANAGER,ESTATE_OWNER
+  Allow_osGetNotecardLine =         ${OSSL|osslParcelO}ESTATE_MANAGER,ESTATE_OWNER
+  Allow_osGetNumberOfNotecardLines = ${OSSL|osslParcelO}ESTATE_MANAGER,ESTATE_OWNER
+  Allow_osSetDynamicTextureURL =    ESTATE_MANAGER,ESTATE_OWNER
+  Allow_osSetDynamicTextureURLBlend = ESTATE_MANAGER,ESTATE_OWNER
+  Allow_osSetDynamicTextureURLBlendFace = ESTATE_MANAGER,ESTATE_OWNER
+  Allow_osSetRot  =                 false
+  Allow_osSetParcelDetails =        ${OSSL|osslParcelO}ESTATE_MANAGER,ESTATE_OWNER
+
+  ; ThreatLevel  Severe
+  Allow_osConsoleCommand =          false
+  Allow_osKickAvatar =              ${OSSL|osslParcelO}ESTATE_MANAGER,ESTATE_OWNER
+  Allow_osTeleportAgent =           ${OSSL|osslParcelO}ESTATE_MANAGER,ESTATE_OWNER
+  Allow_osTeleportObject =          ${OSSL|osslParcelO}ESTATE_MANAGER,ESTATE_OWNER
+
+  ; ThreatLevel  Severe with additional internal restrictions
+  Allow_osGetAgentIP =              true   ; always restricted to Administrators (true or false to disable)
+  Allow_osSetContentType =          false
+
+
+; Always available
+; see http://opensimulator.org/wiki/Category:OSSL_Functions
+
+;; do no remove this line
+Include-osslEnable = "config-include/osslEnable.ini"

+ 1 - 0
bin/http_404.html.example

@@ -0,0 +1 @@
+<HTML><HEAD><TITLE>404 Page not found</TITLE><BODY><BR /><H1>Ooops!</H1><P>The page you requested has been obsconded with by knomes. Find hippos quick!</P></BODY></HTML>

+ 14 - 10
bin/inventory/SettingsLibrary/Folders.xml

@@ -1,28 +1,32 @@
 <Nini>
-
-  
   <Section Name="Settings Library">
     <Key Name="folderID" Value="00000112-000f-0000-0000-000100bba025"/>
     <Key Name="parentFolderID" Value="00000112-000f-0000-0000-000100bba000"/>
     <Key Name="name" Value="Settings Library"/>
-    <Key Name="type" Value="25"/>
+    <Key Name="type" Value="56"/>
   </Section>
   <Section Name="Water">
     <Key Name="folderID" Value="25000112-000f-0000-0000-000100bba025"/>
     <Key Name="parentFolderID" Value="00000112-000f-0000-0000-000100bba025"/>
     <Key Name="name" Value="Water"/>
-    <Key Name="type" Value="25"/>
+    <Key Name="type" Value="-1"/>
   </Section>
-  <Section Name="Sky">
+  <Section Name="Skies">
     <Key Name="folderID" Value="25100112-000f-0000-0000-000100bba025"/>
     <Key Name="parentFolderID" Value="00000112-000f-0000-0000-000100bba025"/>
-    <Key Name="name" Value="Sky"/>
-    <Key Name="type" Value="25"/>
+    <Key Name="name" Value="Skies"/>
+    <Key Name="type" Value="-1"/>
   </Section>
-  <Section Name="Daycycle">
+  <Section Name="Days">
     <Key Name="folderID" Value="25200112-000f-0000-0000-000100bba025"/>
     <Key Name="parentFolderID" Value="00000112-000f-0000-0000-000100bba025"/>
-    <Key Name="name" Value="Daycycle"/>
-    <Key Name="type" Value="25"/>
+    <Key Name="name" Value="Days"/>
+    <Key Name="type" Value="-1"/>
+  </Section>
+  <Section Name="Textures">
+    <Key Name="folderID" Value="bb567e1a-12cf-4ffc-9bcd-cd55c72d27e7"/>
+    <Key Name="parentFolderID" Value="00000112-000f-0000-0000-000100bba025"/>
+    <Key Name="name" Value="Textures"/>
+    <Key Name="type" Value="0"/>
   </Section>
 </Nini>

+ 70 - 4
bin/inventory/SettingsLibrary/Items.xml

@@ -16,19 +16,19 @@
     <Key Name="inventoryID" Value="25210112-000f-0000-0000-000100bba025" />
     <Key Name="assetID" Value="5646d39e-d3d7-6aff-ed71-30fc87d64a91" />
     <Key Name="folderID" Value="25200112-000f-0000-0000-000100bba025"/>
-    <Key Name="description" Value="Default Daycycle with equal night and day durations" />
+    <Key Name="description" Value="Default Daycycle with equal day and night durations" />
     <Key Name="name" Value="Default Daycycle" />
     <Key Name="assetType" Value="56" />
     <Key Name="inventoryType" Value="25" />
 	<Key Name="flags" Value="2" />
   </Section>
   
-  <Section Name="Default Daycycle(3/1)">
+  <Section Name="Default Daycycle (More Daylight)">
     <Key Name="inventoryID" Value="25210112-000f-0001-0000-000100bba125" />
     <Key Name="assetID" Value="5646d39e-d3d7-6aff-ed71-30fc87d64a92" />
     <Key Name="folderID" Value="25200112-000f-0000-0000-000100bba025"/>
-    <Key Name="description" Value="Default Daycycle 3 to 1 day/night duration ratio" />
-    <Key Name="name" Value="Default Daycycle(3/1)" />
+    <Key Name="description" Value="Default Daycycle with a 3 to 1 day/night ratio" />
+    <Key Name="name" Value="Default Daycycle (More Daylight)" />
     <Key Name="assetType" Value="56" />
     <Key Name="inventoryType" Value="25" />
 	<Key Name="flags" Value="2" />
@@ -78,4 +78,70 @@
 	<Key Name="flags" Value="0" />
   </Section>
 
+  <Section Name="Default Water">
+    <Key Name="inventoryID" Value="87d94cf4-bfcd-46d5-bd50-17130a000001" />
+    <Key Name="assetID" Value="59d1a851-47e7-0e5f-1ed7-6b715154f41a" />
+    <Key Name="folderID" Value="25000112-000f-0000-0000-000100bba025"/>
+    <Key Name="description" Value="" />
+    <Key Name="name" Value="Default Water" />
+    <Key Name="assetType" Value="56" />
+    <Key Name="inventoryType" Value="25" />
+	<Key Name="flags" Value="1" />
+  </Section>
+
+  <Section Name="Default Clouds">
+    <Key Name="inventoryID" Value="02385379-afb8-48b3-8848-47c8333fed2d" />
+    <Key Name="assetID" Value="1dc1368f-e8fe-f02d-a08d-9d9f11c1af6b" />
+    <Key Name="folderID" Value="bb567e1a-12cf-4ffc-9bcd-cd55c72d27e7"/>
+    <Key Name="description" Value="" />
+    <Key Name="name" Value="Default Clouds" />
+    <Key Name="assetType" Value="0" />
+    <Key Name="inventoryType" Value="0" />
+  </Section>
+  <Section Name="Altocumulus Clouds">
+    <Key Name="inventoryID" Value="a860475e-6234-40b8-b5b1-3df8fb1d3049" />
+    <Key Name="assetID" Value="ffc4de4a-9845-41c1-9f9f-762a059d0bdc" />
+    <Key Name="folderID" Value="bb567e1a-12cf-4ffc-9bcd-cd55c72d27e7"/>
+    <Key Name="description" Value="" />
+    <Key Name="name" Value="Altocumulus Clouds" />
+    <Key Name="assetType" Value="0" />
+    <Key Name="inventoryType" Value="0" />
+  </Section>
+  <Section Name="Cumulonimbus Clouds">
+    <Key Name="inventoryID" Value="eccad7d7-45e0-408d-b50e-a932603d34f9" />
+    <Key Name="assetID" Value="a3ee7f3c-dc2e-4526-9d7c-67824959c6f6" />
+    <Key Name="folderID" Value="bb567e1a-12cf-4ffc-9bcd-cd55c72d27e7"/>
+    <Key Name="description" Value="" />
+    <Key Name="name" Value="Cumulonimbus Clouds" />
+    <Key Name="assetType" Value="0" />
+    <Key Name="inventoryType" Value="0" />
+  </Section>
+  <Section Name="Layered Clouds">
+    <Key Name="inventoryID" Value="72b43d50-4c00-4344-adb3-b07934743320" />
+    <Key Name="assetID" Value="6e500a99-8831-47d2-b2a8-2e725396d449" />
+    <Key Name="folderID" Value="bb567e1a-12cf-4ffc-9bcd-cd55c72d27e7"/>
+    <Key Name="description" Value="" />
+    <Key Name="name" Value="Layered Clouds" />
+    <Key Name="assetType" Value="0" />
+    <Key Name="inventoryType" Value="0" />
+  </Section>
+  <Section Name="Default Water Normal">
+    <Key Name="inventoryID" Value="03816023-8ec9-4a87-9195-3640893c7ff7" />
+    <Key Name="assetID" Value="822ded49-9a6c-f61c-cb89-6df54f42cdf4" />
+    <Key Name="folderID" Value="bb567e1a-12cf-4ffc-9bcd-cd55c72d27e7"/>
+    <Key Name="description" Value="" />
+    <Key Name="name" Value="Default Water Normal" />
+    <Key Name="assetType" Value="0" />
+    <Key Name="inventoryType" Value="0" />
+  </Section>
+  <Section Name="Default Moon">
+    <Key Name="inventoryID" Value="c2d885cd-d477-4afb-ba51-08c6a13df6f7" />
+    <Key Name="assetID" Value="d07f6eed-b96a-47cd-b51d-400ad4a1c428" />
+    <Key Name="folderID" Value="bb567e1a-12cf-4ffc-9bcd-cd55c72d27e7"/>
+    <Key Name="description" Value="" />
+    <Key Name="name" Value="Default Moon" />
+    <Key Name="assetType" Value="0" />
+    <Key Name="inventoryType" Value="0" />
+  </Section>
+
 </Nini>

BIN
bin/lib64/libode-x86_64.so


Some files were not shown because too many files changed in this diff