aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--OpenSim/Addons/Groups/ForeignImporter.cs77
-rw-r--r--OpenSim/Addons/Groups/GroupsExtendedData.cs509
-rw-r--r--OpenSim/Addons/Groups/GroupsMessagingModule.cs594
-rw-r--r--OpenSim/Addons/Groups/GroupsModule.cs1467
-rw-r--r--OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnector.cs289
-rw-r--r--OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs717
-rw-r--r--OpenSim/Addons/Groups/Hypergrid/HGGroupsServiceRobustConnector.cs443
-rw-r--r--OpenSim/Addons/Groups/IGroupsServicesConnector.cs118
-rw-r--r--OpenSim/Addons/Groups/Local/GroupsServiceLocalConnectorModule.cs347
-rw-r--r--OpenSim/Addons/Groups/Properties/AssemblyInfo.cs36
-rw-r--r--OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnector.cs642
-rw-r--r--OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnectorModule.cs437
-rw-r--r--OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs760
-rw-r--r--OpenSim/Addons/Groups/RemoteConnectorCacheWrapper.cs824
-rw-r--r--OpenSim/Addons/Groups/Service/GroupsService.cs1014
-rw-r--r--OpenSim/Addons/Groups/Service/GroupsServiceBase.cs84
-rw-r--r--OpenSim/Addons/Groups/Service/HGGroupsService.cs353
-rw-r--r--OpenSim/Addons/OfflineIM/OfflineIMRegionModule.cs267
-rw-r--r--OpenSim/Addons/OfflineIM/Properties/AssemblyInfo.cs36
-rw-r--r--OpenSim/Addons/OfflineIM/Remote/OfflineIMServiceRemoteConnector.cs143
-rw-r--r--OpenSim/Addons/OfflineIM/Remote/OfflineIMServiceRobustConnector.cs215
-rw-r--r--OpenSim/Addons/OfflineIM/Service/OfflineIMService.cs131
-rw-r--r--OpenSim/Addons/OfflineIM/Service/OfflineIMServiceBase.cs83
-rw-r--r--OpenSim/ApplicationPlugins/LoadRegions/Properties/AssemblyInfo.cs1
-rw-r--r--OpenSim/ApplicationPlugins/RegionModulesController/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/ApplicationPlugins/RemoteController/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Capabilities/Handlers/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Data/IGroupsData.cs144
-rw-r--r--OpenSim/Data/IOfflineIMData.cs49
-rw-r--r--OpenSim/Data/MSSQL/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Data/MySQL/MySQLGenericTableHandler.cs60
-rw-r--r--OpenSim/Data/MySQL/MySQLGroupsData.cs484
-rw-r--r--OpenSim/Data/MySQL/MySQLOfflineIMData.cs62
-rw-r--r--OpenSim/Data/MySQL/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Data/MySQL/Resources/IM_Store.migrations24
-rw-r--r--OpenSim/Data/MySQL/Resources/os_groups_Store.migrations115
-rw-r--r--OpenSim/Data/Null/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Data/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Data/SQLite/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Framework/AssemblyInfo.cs1
-rw-r--r--OpenSim/Framework/AssetLoader/Filesystem/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Framework/Communications/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Framework/Configuration/HTTP/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Framework/Configuration/XML/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Framework/Console/ConsoleUtil.cs8
-rw-r--r--OpenSim/Framework/Monitoring/AssetStatsCollector.cs26
-rw-r--r--OpenSim/Framework/Monitoring/BaseStatsCollector.cs7
-rw-r--r--OpenSim/Framework/Monitoring/Interfaces/IStatsCollector.cs9
-rw-r--r--OpenSim/Framework/Monitoring/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs21
-rwxr-xr-xOpenSim/Framework/Monitoring/Stats/CounterStat.cs211
-rw-r--r--OpenSim/Framework/Monitoring/Stats/Stat.cs24
-rw-r--r--OpenSim/Framework/Monitoring/UserStatsCollector.cs18
-rw-r--r--OpenSim/Framework/RegionLoader/Filesystem/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Framework/RegionLoader/Web/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Framework/Serialization/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Framework/Servers/HttpServer/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Framework/Util.cs22
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs2
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs8
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs13
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs4
-rw-r--r--OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs9
-rwxr-xr-xOpenSim/Region/CoreModules/Framework/Statistics/Logging/LogWriter.cs13
-rw-r--r--OpenSim/Region/CoreModules/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs10
-rw-r--r--OpenSim/Region/DataSnapshot/DataSnapshotManager.cs13
-rw-r--r--OpenSim/Region/DataSnapshot/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs1
-rw-r--r--OpenSim/Region/Framework/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs6
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/Appearance/AppearanceInfoModule.cs2
-rw-r--r--OpenSim/Region/OptionalModules/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStore.cs28
-rw-r--r--OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs32
-rw-r--r--OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs38
-rw-r--r--OpenSim/Region/OptionalModules/Scripting/JsonStore/Tests/JsonStoreScriptModuleTests.cs22
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSAPIUnman.cs102
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs231
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSApiTemplate.cs27
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs7
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSConstraint6Dof.cs16
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs13
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs6
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs4
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs4
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSParam.cs705
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs121
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSScene.cs54
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs2
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt22
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/Physics/ConvexDecompositionDotNet/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/Physics/Meshing/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/RegionCombinerModule/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs12
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/CodeTools/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Instance/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/UserStatistics/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Server/Base/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Server/Handlers/Grid/GridInfoHandlers.cs20
-rw-r--r--OpenSim/Server/Handlers/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Services/AssetService/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Services/AuthenticationService/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Services/AuthorizationService/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Services/AvatarService/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Services/Base/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Services/Connectors/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Services/FreeswitchService/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Services/Friends/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Services/GridService/HypergridLinker.cs4
-rw-r--r--OpenSim/Services/GridService/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Services/HypergridService/GatekeeperService.cs3
-rw-r--r--OpenSim/Services/HypergridService/HGInventoryService.cs5
-rw-r--r--OpenSim/Services/HypergridService/HGSuitcaseInventoryService.cs3
-rw-r--r--OpenSim/Services/HypergridService/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Services/HypergridService/UserAgentService.cs11
-rw-r--r--OpenSim/Services/Interfaces/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Services/InventoryService/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Services/LLLoginService/LLLoginService.cs17
-rw-r--r--OpenSim/Services/LLLoginService/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Services/MapImageService/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Services/PresenceService/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Services/UserAccountService/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Tools/Compiler/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Tools/Configger/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Tools/pCampBot/Properties/AssemblyInfo.cs2
-rw-r--r--bin/OpenSim.ini.example74
-rw-r--r--bin/Robust.HG.ini.example84
-rw-r--r--bin/Robust.ini.example35
-rw-r--r--bin/config-include/StandaloneCommon.ini.example30
-rwxr-xr-xbin/lib32/BulletSim.dllbin546816 -> 570368 bytes
-rwxr-xr-xbin/lib32/libBulletSim.sobin1700826 -> 1751260 bytes
-rwxr-xr-xbin/lib64/BulletSim.dllbin694784 -> 720896 bytes
-rwxr-xr-xbin/lib64/libBulletSim.sobin1843498 -> 1908442 bytes
-rw-r--r--prebuild.xml98
141 files changed, 12111 insertions, 780 deletions
diff --git a/OpenSim/Addons/Groups/ForeignImporter.cs b/OpenSim/Addons/Groups/ForeignImporter.cs
new file mode 100644
index 0000000..788d21d
--- /dev/null
+++ b/OpenSim/Addons/Groups/ForeignImporter.cs
@@ -0,0 +1,77 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30
31using OpenSim.Framework;
32using OpenSim.Region.Framework.Interfaces;
33
34namespace OpenSim.Groups
35{
36 public class ForeignImporter
37 {
38 IUserManagement m_UserManagement;
39 public ForeignImporter(IUserManagement uman)
40 {
41 m_UserManagement = uman;
42 }
43
44 public GroupMembersData ConvertGroupMembersData(ExtendedGroupMembersData _m)
45 {
46 GroupMembersData m = new GroupMembersData();
47 m.AcceptNotices = _m.AcceptNotices;
48 m.AgentPowers = _m.AgentPowers;
49 m.Contribution = _m.Contribution;
50 m.IsOwner = _m.IsOwner;
51 m.ListInProfile = _m.ListInProfile;
52 m.OnlineStatus = _m.OnlineStatus;
53 m.Title = _m.Title;
54
55 string url = string.Empty, first = string.Empty, last = string.Empty, tmp = string.Empty;
56 Util.ParseUniversalUserIdentifier(_m.AgentID, out m.AgentID, out url, out first, out last, out tmp);
57 if (url != string.Empty)
58 m_UserManagement.AddUser(m.AgentID, first, last, url);
59
60 return m;
61 }
62
63 public GroupRoleMembersData ConvertGroupRoleMembersData(ExtendedGroupRoleMembersData _rm)
64 {
65 GroupRoleMembersData rm = new GroupRoleMembersData();
66 rm.RoleID = _rm.RoleID;
67
68 string url = string.Empty, first = string.Empty, last = string.Empty, tmp = string.Empty;
69 Util.ParseUniversalUserIdentifier(_rm.MemberID, out rm.MemberID, out url, out first, out last, out tmp);
70 if (url != string.Empty)
71 m_UserManagement.AddUser(rm.MemberID, first, last, url);
72
73 return rm;
74 }
75
76 }
77}
diff --git a/OpenSim/Addons/Groups/GroupsExtendedData.cs b/OpenSim/Addons/Groups/GroupsExtendedData.cs
new file mode 100644
index 0000000..6f4db28
--- /dev/null
+++ b/OpenSim/Addons/Groups/GroupsExtendedData.cs
@@ -0,0 +1,509 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30
31using OpenSim.Framework;
32using OpenMetaverse;
33
34namespace OpenSim.Groups
35{
36 public class ExtendedGroupRecord : GroupRecord
37 {
38 public int MemberCount;
39 public int RoleCount;
40 public string ServiceLocation;
41 public string FounderUUI;
42 }
43
44 public class ExtendedGroupMembershipData : GroupMembershipData
45 {
46 public string AccessToken;
47 }
48
49 public class ExtendedGroupMembersData
50 {
51 // This is the only difference: this is a string
52 public string AgentID;
53 public int Contribution;
54 public string OnlineStatus;
55 public ulong AgentPowers;
56 public string Title;
57 public bool IsOwner;
58 public bool ListInProfile;
59 public bool AcceptNotices;
60 public string AccessToken;
61 }
62
63 public class ExtendedGroupRoleMembersData
64 {
65 public UUID RoleID;
66 // This is the only difference: this is a string
67 public string MemberID;
68
69 }
70
71 public struct ExtendedGroupNoticeData
72 {
73 public UUID NoticeID;
74 public uint Timestamp;
75 public string FromName;
76 public string Subject;
77 public bool HasAttachment;
78 public byte AttachmentType;
79 public string AttachmentName;
80 public UUID AttachmentItemID;
81 public string AttachmentOwnerID;
82
83 public GroupNoticeData ToGroupNoticeData()
84 {
85 GroupNoticeData n = new GroupNoticeData();
86 n.FromName = this.FromName;
87 n.AssetType = this.AttachmentType;
88 n.HasAttachment = this.HasAttachment;
89 n.NoticeID = this.NoticeID;
90 n.Subject = this.Subject;
91 n.Timestamp = this.Timestamp;
92
93 return n;
94 }
95 }
96
97 public class GroupsDataUtils
98 {
99 public static string Sanitize(string s)
100 {
101 return s == null ? string.Empty : s;
102 }
103
104 public static Dictionary<string, object> GroupRecord(ExtendedGroupRecord grec)
105 {
106 Dictionary<string, object> dict = new Dictionary<string, object>();
107 if (grec == null)
108 return dict;
109
110 dict["AllowPublish"] = grec.AllowPublish.ToString();
111 dict["Charter"] = Sanitize(grec.Charter);
112 dict["FounderID"] = grec.FounderID.ToString();
113 dict["FounderUUI"] = Sanitize(grec.FounderUUI);
114 dict["GroupID"] = grec.GroupID.ToString();
115 dict["GroupName"] = Sanitize(grec.GroupName);
116 dict["InsigniaID"] = grec.GroupPicture.ToString();
117 dict["MaturePublish"] = grec.MaturePublish.ToString();
118 dict["MembershipFee"] = grec.MembershipFee.ToString();
119 dict["OpenEnrollment"] = grec.OpenEnrollment.ToString();
120 dict["OwnerRoleID"] = grec.OwnerRoleID.ToString();
121 dict["ServiceLocation"] = Sanitize(grec.ServiceLocation);
122 dict["ShownInList"] = grec.ShowInList.ToString();
123 dict["MemberCount"] = grec.MemberCount.ToString();
124 dict["RoleCount"] = grec.RoleCount.ToString();
125
126 return dict;
127 }
128
129 public static ExtendedGroupRecord GroupRecord(Dictionary<string, object> dict)
130 {
131 if (dict == null)
132 return null;
133
134 ExtendedGroupRecord grec = new ExtendedGroupRecord();
135 if (dict.ContainsKey("AllowPublish") && dict["AllowPublish"] != null)
136 grec.AllowPublish = bool.Parse(dict["AllowPublish"].ToString());
137
138 if (dict.ContainsKey("Charter") && dict["Charter"] != null)
139 grec.Charter = dict["Charter"].ToString();
140 else
141 grec.Charter = string.Empty;
142
143 if (dict.ContainsKey("FounderID") && dict["FounderID"] != null)
144 grec.FounderID = UUID.Parse(dict["FounderID"].ToString());
145
146 if (dict.ContainsKey("FounderUUI") && dict["FounderUUI"] != null)
147 grec.FounderUUI = dict["FounderUUI"].ToString();
148 else
149 grec.FounderUUI = string.Empty;
150
151 if (dict.ContainsKey("GroupID") && dict["GroupID"] != null)
152 grec.GroupID = UUID.Parse(dict["GroupID"].ToString());
153
154 if (dict.ContainsKey("GroupName") && dict["GroupName"] != null)
155 grec.GroupName = dict["GroupName"].ToString();
156 else
157 grec.GroupName = string.Empty;
158
159 if (dict.ContainsKey("InsigniaID") && dict["InsigniaID"] != null)
160 grec.GroupPicture = UUID.Parse(dict["InsigniaID"].ToString());
161
162 if (dict.ContainsKey("MaturePublish") && dict["MaturePublish"] != null)
163 grec.MaturePublish = bool.Parse(dict["MaturePublish"].ToString());
164
165 if (dict.ContainsKey("MembershipFee") && dict["MembershipFee"] != null)
166 grec.MembershipFee = Int32.Parse(dict["MembershipFee"].ToString());
167
168 if (dict.ContainsKey("OpenEnrollment") && dict["OpenEnrollment"] != null)
169 grec.OpenEnrollment = bool.Parse(dict["OpenEnrollment"].ToString());
170
171 if (dict.ContainsKey("OwnerRoleID") && dict["OwnerRoleID"] != null)
172 grec.OwnerRoleID = UUID.Parse(dict["OwnerRoleID"].ToString());
173
174 if (dict.ContainsKey("ServiceLocation") && dict["ServiceLocation"] != null)
175 grec.ServiceLocation = dict["ServiceLocation"].ToString();
176 else
177 grec.GroupName = string.Empty;
178
179 if (dict.ContainsKey("ShownInList") && dict["ShownInList"] != null)
180 grec.ShowInList = bool.Parse(dict["ShownInList"].ToString());
181
182 if (dict.ContainsKey("MemberCount") && dict["MemberCount"] != null)
183 grec.MemberCount = Int32.Parse(dict["MemberCount"].ToString());
184
185 if (dict.ContainsKey("RoleCount") && dict["RoleCount"] != null)
186 grec.RoleCount = Int32.Parse(dict["RoleCount"].ToString());
187
188 return grec;
189 }
190
191 public static Dictionary<string, object> GroupMembershipData(ExtendedGroupMembershipData membership)
192 {
193 Dictionary<string, object> dict = new Dictionary<string, object>();
194 if (membership == null)
195 return dict;
196
197 dict["AcceptNotices"] = membership.AcceptNotices.ToString();
198 dict["AccessToken"] = Sanitize(membership.AccessToken);
199 dict["Active"] = membership.Active.ToString();
200 dict["ActiveRole"] = membership.ActiveRole.ToString();
201 dict["AllowPublish"] = membership.AllowPublish.ToString();
202 dict["Charter"] = Sanitize(membership.Charter);
203 dict["Contribution"] = membership.Contribution.ToString();
204 dict["FounderID"] = membership.FounderID.ToString();
205 dict["GroupID"] = membership.GroupID.ToString();
206 dict["GroupName"] = Sanitize(membership.GroupName);
207 dict["GroupPicture"] = membership.GroupPicture.ToString();
208 dict["GroupPowers"] = membership.GroupPowers.ToString();
209 dict["GroupTitle"] = Sanitize(membership.GroupTitle);
210 dict["ListInProfile"] = membership.ListInProfile.ToString();
211 dict["MaturePublish"] = membership.MaturePublish.ToString();
212 dict["MembershipFee"] = membership.MembershipFee.ToString();
213 dict["OpenEnrollment"] = membership.OpenEnrollment.ToString();
214 dict["ShowInList"] = membership.ShowInList.ToString();
215
216 return dict;
217 }
218
219 public static ExtendedGroupMembershipData GroupMembershipData(Dictionary<string, object> dict)
220 {
221 if (dict == null)
222 return null;
223
224 ExtendedGroupMembershipData membership = new ExtendedGroupMembershipData();
225
226 if (dict.ContainsKey("AcceptNotices") && dict["AcceptNotices"] != null)
227 membership.AcceptNotices = bool.Parse(dict["AcceptNotices"].ToString());
228
229 if (dict.ContainsKey("AccessToken") && dict["AccessToken"] != null)
230 membership.AccessToken = dict["AccessToken"].ToString();
231 else
232 membership.AccessToken = string.Empty;
233
234 if (dict.ContainsKey("Active") && dict["Active"] != null)
235 membership.Active = bool.Parse(dict["Active"].ToString());
236
237 if (dict.ContainsKey("ActiveRole") && dict["ActiveRole"] != null)
238 membership.ActiveRole = UUID.Parse(dict["ActiveRole"].ToString());
239
240 if (dict.ContainsKey("AllowPublish") && dict["AllowPublish"] != null)
241 membership.AllowPublish = bool.Parse(dict["AllowPublish"].ToString());
242
243 if (dict.ContainsKey("Charter") && dict["Charter"] != null)
244 membership.Charter = dict["Charter"].ToString();
245 else
246 membership.Charter = string.Empty;
247
248 if (dict.ContainsKey("Contribution") && dict["Contribution"] != null)
249 membership.Contribution = Int32.Parse(dict["Contribution"].ToString());
250
251 if (dict.ContainsKey("FounderID") && dict["FounderID"] != null)
252 membership.FounderID = UUID.Parse(dict["FounderID"].ToString());
253
254 if (dict.ContainsKey("GroupID") && dict["GroupID"] != null)
255 membership.GroupID = UUID.Parse(dict["GroupID"].ToString());
256
257 if (dict.ContainsKey("GroupName") && dict["GroupName"] != null)
258 membership.GroupName = dict["GroupName"].ToString();
259 else
260 membership.GroupName = string.Empty;
261
262 if (dict.ContainsKey("GroupPicture") && dict["GroupPicture"] != null)
263 membership.GroupPicture = UUID.Parse(dict["GroupPicture"].ToString());
264
265 if (dict.ContainsKey("GroupPowers") && dict["GroupPowers"] != null)
266 membership.GroupPowers = UInt64.Parse(dict["GroupPowers"].ToString());
267
268 if (dict.ContainsKey("GroupTitle") && dict["GroupTitle"] != null)
269 membership.GroupTitle = dict["GroupTitle"].ToString();
270 else
271 membership.GroupTitle = string.Empty;
272
273 if (dict.ContainsKey("ListInProfile") && dict["ListInProfile"] != null)
274 membership.ListInProfile = bool.Parse(dict["ListInProfile"].ToString());
275
276 if (dict.ContainsKey("MaturePublish") && dict["MaturePublish"] != null)
277 membership.MaturePublish = bool.Parse(dict["MaturePublish"].ToString());
278
279 if (dict.ContainsKey("MembershipFee") && dict["MembershipFee"] != null)
280 membership.MembershipFee = Int32.Parse(dict["MembershipFee"].ToString());
281
282 if (dict.ContainsKey("OpenEnrollment") && dict["OpenEnrollment"] != null)
283 membership.OpenEnrollment = bool.Parse(dict["OpenEnrollment"].ToString());
284
285 if (dict.ContainsKey("ShowInList") && dict["ShowInList"] != null)
286 membership.ShowInList = bool.Parse(dict["ShowInList"].ToString());
287
288 return membership;
289 }
290
291 public static Dictionary<string, object> GroupMembersData(ExtendedGroupMembersData member)
292 {
293 Dictionary<string, object> dict = new Dictionary<string, object>();
294
295 dict["AcceptNotices"] = member.AcceptNotices.ToString();
296 dict["AccessToken"] = Sanitize(member.AccessToken);
297 dict["AgentID"] = Sanitize(member.AgentID);
298 dict["AgentPowers"] = member.AgentPowers.ToString();
299 dict["Contribution"] = member.Contribution.ToString();
300 dict["IsOwner"] = member.IsOwner.ToString();
301 dict["ListInProfile"] = member.ListInProfile.ToString();
302 dict["OnlineStatus"] = Sanitize(member.OnlineStatus);
303 dict["Title"] = Sanitize(member.Title);
304
305 return dict;
306 }
307
308 public static ExtendedGroupMembersData GroupMembersData(Dictionary<string, object> dict)
309 {
310 ExtendedGroupMembersData member = new ExtendedGroupMembersData();
311
312 if (dict == null)
313 return member;
314
315 if (dict.ContainsKey("AcceptNotices") && dict["AcceptNotices"] != null)
316 member.AcceptNotices = bool.Parse(dict["AcceptNotices"].ToString());
317
318 if (dict.ContainsKey("AccessToken") && dict["AccessToken"] != null)
319 member.AccessToken = Sanitize(dict["AccessToken"].ToString());
320 else
321 member.AccessToken = string.Empty;
322
323 if (dict.ContainsKey("AgentID") && dict["AgentID"] != null)
324 member.AgentID = Sanitize(dict["AgentID"].ToString());
325 else
326 member.AgentID = UUID.Zero.ToString();
327
328 if (dict.ContainsKey("AgentPowers") && dict["AgentPowers"] != null)
329 member.AgentPowers = UInt64.Parse(dict["AgentPowers"].ToString());
330
331 if (dict.ContainsKey("Contribution") && dict["Contribution"] != null)
332 member.Contribution = Int32.Parse(dict["Contribution"].ToString());
333
334 if (dict.ContainsKey("IsOwner") && dict["IsOwner"] != null)
335 member.IsOwner = bool.Parse(dict["IsOwner"].ToString());
336
337 if (dict.ContainsKey("ListInProfile") && dict["ListInProfile"] != null)
338 member.ListInProfile = bool.Parse(dict["ListInProfile"].ToString());
339
340 if (dict.ContainsKey("OnlineStatus") && dict["OnlineStatus"] != null)
341 member.OnlineStatus = Sanitize(dict["OnlineStatus"].ToString());
342 else
343 member.OnlineStatus = string.Empty;
344
345 if (dict.ContainsKey("Title") && dict["Title"] != null)
346 member.Title = Sanitize(dict["Title"].ToString());
347 else
348 member.Title = string.Empty;
349
350 return member;
351 }
352
353 public static Dictionary<string, object> GroupRolesData(GroupRolesData role)
354 {
355 Dictionary<string, object> dict = new Dictionary<string, object>();
356
357 dict["Description"] = Sanitize(role.Description);
358 dict["Members"] = role.Members.ToString();
359 dict["Name"] = Sanitize(role.Name);
360 dict["Powers"] = role.Powers.ToString();
361 dict["RoleID"] = role.RoleID.ToString();
362 dict["Title"] = Sanitize(role.Title);
363
364 return dict;
365 }
366
367 public static GroupRolesData GroupRolesData(Dictionary<string, object> dict)
368 {
369 GroupRolesData role = new GroupRolesData();
370
371 if (dict == null)
372 return role;
373
374 if (dict.ContainsKey("Description") && dict["Description"] != null)
375 role.Description = Sanitize(dict["Description"].ToString());
376 else
377 role.Description = string.Empty;
378
379 if (dict.ContainsKey("Members") && dict["Members"] != null)
380 role.Members = Int32.Parse(dict["Members"].ToString());
381
382 if (dict.ContainsKey("Name") && dict["Name"] != null)
383 role.Name = Sanitize(dict["Name"].ToString());
384 else
385 role.Name = string.Empty;
386
387 if (dict.ContainsKey("Powers") && dict["Powers"] != null)
388 role.Powers = UInt64.Parse(dict["Powers"].ToString());
389
390 if (dict.ContainsKey("Title") && dict["Title"] != null)
391 role.Title = Sanitize(dict["Title"].ToString());
392 else
393 role.Title = string.Empty;
394
395 if (dict.ContainsKey("RoleID") && dict["RoleID"] != null)
396 role.RoleID = UUID.Parse(dict["RoleID"].ToString());
397
398 return role;
399 }
400
401 public static Dictionary<string, object> GroupRoleMembersData(ExtendedGroupRoleMembersData rmember)
402 {
403 Dictionary<string, object> dict = new Dictionary<string, object>();
404
405 dict["RoleID"] = rmember.RoleID.ToString();
406 dict["MemberID"] = rmember.MemberID;
407 return dict;
408 }
409
410 public static ExtendedGroupRoleMembersData GroupRoleMembersData(Dictionary<string, object> dict)
411 {
412 ExtendedGroupRoleMembersData rmember = new ExtendedGroupRoleMembersData();
413
414 if (dict.ContainsKey("RoleID") && dict["RoleID"] != null)
415 rmember.RoleID = new UUID(dict["RoleID"].ToString());
416
417 if (dict.ContainsKey("MemberID") && dict["MemberID"] != null)
418 rmember.MemberID = dict["MemberID"].ToString();
419
420 return rmember;
421 }
422
423 public static Dictionary<string, object> GroupInviteInfo(GroupInviteInfo invite)
424 {
425 Dictionary<string, object> dict = new Dictionary<string, object>();
426
427 dict["InviteID"] = invite.InviteID.ToString();
428 dict["GroupID"] = invite.GroupID.ToString();
429 dict["RoleID"] = invite.RoleID.ToString();
430 dict["AgentID"] = invite.AgentID;
431
432 return dict;
433 }
434
435 public static GroupInviteInfo GroupInviteInfo(Dictionary<string, object> dict)
436 {
437 if (dict == null)
438 return null;
439
440 GroupInviteInfo invite = new GroupInviteInfo();
441
442 invite.InviteID = new UUID(dict["InviteID"].ToString());
443 invite.GroupID = new UUID(dict["GroupID"].ToString());
444 invite.RoleID = new UUID(dict["RoleID"].ToString());
445 invite.AgentID = Sanitize(dict["AgentID"].ToString());
446
447 return invite;
448 }
449
450 public static Dictionary<string, object> GroupNoticeData(ExtendedGroupNoticeData notice)
451 {
452 Dictionary<string, object> dict = new Dictionary<string, object>();
453
454 dict["NoticeID"] = notice.NoticeID.ToString();
455 dict["Timestamp"] = notice.Timestamp.ToString();
456 dict["FromName"] = Sanitize(notice.FromName);
457 dict["Subject"] = Sanitize(notice.Subject);
458 dict["HasAttachment"] = notice.HasAttachment.ToString();
459 dict["AttachmentItemID"] = notice.AttachmentItemID.ToString();
460 dict["AttachmentName"] = Sanitize(notice.AttachmentName);
461 dict["AttachmentType"] = notice.AttachmentType.ToString();
462 dict["AttachmentOwnerID"] = Sanitize(notice.AttachmentOwnerID);
463
464 return dict;
465 }
466
467 public static ExtendedGroupNoticeData GroupNoticeData(Dictionary<string, object> dict)
468 {
469 ExtendedGroupNoticeData notice = new ExtendedGroupNoticeData();
470
471 if (dict == null)
472 return notice;
473
474 notice.NoticeID = new UUID(dict["NoticeID"].ToString());
475 notice.Timestamp = UInt32.Parse(dict["Timestamp"].ToString());
476 notice.FromName = Sanitize(dict["FromName"].ToString());
477 notice.Subject = Sanitize(dict["Subject"].ToString());
478 notice.HasAttachment = bool.Parse(dict["HasAttachment"].ToString());
479 notice.AttachmentItemID = new UUID(dict["AttachmentItemID"].ToString());
480 notice.AttachmentName = dict["AttachmentName"].ToString();
481 notice.AttachmentType = byte.Parse(dict["AttachmentType"].ToString());
482 notice.AttachmentOwnerID = dict["AttachmentOwnerID"].ToString();
483
484 return notice;
485 }
486
487 public static Dictionary<string, object> GroupNoticeInfo(GroupNoticeInfo notice)
488 {
489 Dictionary<string, object> dict = GroupNoticeData(notice.noticeData);
490
491 dict["GroupID"] = notice.GroupID.ToString();
492 dict["Message"] = Sanitize(notice.Message);
493
494 return dict;
495 }
496
497 public static GroupNoticeInfo GroupNoticeInfo(Dictionary<string, object> dict)
498 {
499 GroupNoticeInfo notice = new GroupNoticeInfo();
500
501 notice.noticeData = GroupNoticeData(dict);
502 notice.GroupID = new UUID(dict["GroupID"].ToString());
503 notice.Message = Sanitize(dict["Message"].ToString());
504
505 return notice;
506 }
507 }
508
509}
diff --git a/OpenSim/Addons/Groups/GroupsMessagingModule.cs b/OpenSim/Addons/Groups/GroupsMessagingModule.cs
new file mode 100644
index 0000000..d172d48
--- /dev/null
+++ b/OpenSim/Addons/Groups/GroupsMessagingModule.cs
@@ -0,0 +1,594 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Linq;
31using System.Reflection;
32using log4net;
33using Mono.Addins;
34using Nini.Config;
35using OpenMetaverse;
36using OpenMetaverse.StructuredData;
37using OpenSim.Framework;
38using OpenSim.Region.Framework.Interfaces;
39using OpenSim.Region.Framework.Scenes;
40using OpenSim.Services.Interfaces;
41using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo;
42
43namespace OpenSim.Groups
44{
45 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GroupsMessagingModule")]
46 public class GroupsMessagingModule : ISharedRegionModule, IGroupsMessagingModule
47 {
48 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
49
50 private List<Scene> m_sceneList = new List<Scene>();
51 private IPresenceService m_presenceService;
52
53 private IMessageTransferModule m_msgTransferModule = null;
54
55 private IGroupsServicesConnector m_groupData = null;
56
57 // Config Options
58 private bool m_groupMessagingEnabled = false;
59 private bool m_debugEnabled = true;
60
61 /// <summary>
62 /// If enabled, module only tries to send group IMs to online users by querying cached presence information.
63 /// </summary>
64 private bool m_messageOnlineAgentsOnly;
65
66 /// <summary>
67 /// Cache for online users.
68 /// </summary>
69 /// <remarks>
70 /// Group ID is key, presence information for online members is value.
71 /// Will only be non-null if m_messageOnlineAgentsOnly = true
72 /// We cache here so that group messages don't constantly have to re-request the online user list to avoid
73 /// attempted expensive sending of messages to offline users.
74 /// The tradeoff is that a user that comes online will not receive messages consistently from all other users
75 /// until caches have updated.
76 /// Therefore, we set the cache expiry to just 20 seconds.
77 /// </remarks>
78 private ExpiringCache<UUID, PresenceInfo[]> m_usersOnlineCache;
79
80 private int m_usersOnlineCacheExpirySeconds = 20;
81
82 #region Region Module interfaceBase Members
83
84 public void Initialise(IConfigSource config)
85 {
86 IConfig groupsConfig = config.Configs["Groups"];
87
88 if (groupsConfig == null)
89 // Do not run this module by default.
90 return;
91
92 // if groups aren't enabled, we're not needed.
93 // if we're not specified as the connector to use, then we're not wanted
94 if ((groupsConfig.GetBoolean("Enabled", false) == false)
95 || (groupsConfig.GetString("MessagingModule", "") != Name))
96 {
97 m_groupMessagingEnabled = false;
98 return;
99 }
100
101 m_groupMessagingEnabled = groupsConfig.GetBoolean("MessagingEnabled", true);
102
103 if (!m_groupMessagingEnabled)
104 return;
105
106 m_messageOnlineAgentsOnly = groupsConfig.GetBoolean("MessageOnlineUsersOnly", false);
107
108 if (m_messageOnlineAgentsOnly)
109 m_usersOnlineCache = new ExpiringCache<UUID, PresenceInfo[]>();
110
111 m_debugEnabled = groupsConfig.GetBoolean("DebugEnabled", true);
112
113 m_log.InfoFormat(
114 "[Groups.Messaging]: GroupsMessagingModule enabled with MessageOnlineOnly = {0}, DebugEnabled = {1}",
115 m_messageOnlineAgentsOnly, m_debugEnabled);
116 }
117
118 public void AddRegion(Scene scene)
119 {
120 if (!m_groupMessagingEnabled)
121 return;
122
123 scene.RegisterModuleInterface<IGroupsMessagingModule>(this);
124 m_sceneList.Add(scene);
125
126 scene.EventManager.OnNewClient += OnNewClient;
127 scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage;
128 scene.EventManager.OnClientLogin += OnClientLogin;
129 }
130
131 public void RegionLoaded(Scene scene)
132 {
133 if (!m_groupMessagingEnabled)
134 return;
135
136 if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
137
138 m_groupData = scene.RequestModuleInterface<IGroupsServicesConnector>();
139
140 // No groups module, no groups messaging
141 if (m_groupData == null)
142 {
143 m_log.Error("[Groups.Messaging]: Could not get IGroupsServicesConnector, GroupsMessagingModule is now disabled.");
144 RemoveRegion(scene);
145 return;
146 }
147
148 m_msgTransferModule = scene.RequestModuleInterface<IMessageTransferModule>();
149
150 // No message transfer module, no groups messaging
151 if (m_msgTransferModule == null)
152 {
153 m_log.Error("[Groups.Messaging]: Could not get MessageTransferModule");
154 RemoveRegion(scene);
155 return;
156 }
157
158 if (m_presenceService == null)
159 m_presenceService = scene.PresenceService;
160
161 }
162
163 public void RemoveRegion(Scene scene)
164 {
165 if (!m_groupMessagingEnabled)
166 return;
167
168 if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
169
170 m_sceneList.Remove(scene);
171 scene.EventManager.OnNewClient -= OnNewClient;
172 scene.EventManager.OnIncomingInstantMessage -= OnGridInstantMessage;
173 scene.EventManager.OnClientLogin -= OnClientLogin;
174 scene.UnregisterModuleInterface<IGroupsMessagingModule>(this);
175 }
176
177 public void Close()
178 {
179 if (!m_groupMessagingEnabled)
180 return;
181
182 if (m_debugEnabled) m_log.Debug("[Groups.Messaging]: Shutting down GroupsMessagingModule module.");
183
184 m_sceneList.Clear();
185
186 m_groupData = null;
187 m_msgTransferModule = null;
188 }
189
190 public Type ReplaceableInterface
191 {
192 get { return null; }
193 }
194
195 public string Name
196 {
197 get { return "Groups Messaging Module V2"; }
198 }
199
200 public void PostInitialise()
201 {
202 // NoOp
203 }
204
205 #endregion
206
207
208 /// <summary>
209 /// Not really needed, but does confirm that the group exists.
210 /// </summary>
211 public bool StartGroupChatSession(UUID agentID, UUID groupID)
212 {
213 if (m_debugEnabled)
214 m_log.DebugFormat("[Groups.Messaging]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
215
216 GroupRecord groupInfo = m_groupData.GetGroupRecord(agentID.ToString(), groupID, null);
217
218 if (groupInfo != null)
219 {
220 return true;
221 }
222 else
223 {
224 return false;
225 }
226 }
227
228 public void SendMessageToGroup(GridInstantMessage im, UUID groupID)
229 {
230 List<GroupMembersData> groupMembers = m_groupData.GetGroupMembers(new UUID(im.fromAgentID).ToString(), groupID);
231 int groupMembersCount = groupMembers.Count;
232
233 if (m_messageOnlineAgentsOnly)
234 {
235 string[] t1 = groupMembers.ConvertAll<string>(gmd => gmd.AgentID.ToString()).ToArray();
236
237 // We cache in order not to overwhlem the presence service on large grids with many groups. This does
238 // mean that members coming online will not see all group members until after m_usersOnlineCacheExpirySeconds has elapsed.
239 // (assuming this is the same across all grid simulators).
240 PresenceInfo[] onlineAgents;
241 if (!m_usersOnlineCache.TryGetValue(groupID, out onlineAgents))
242 {
243 onlineAgents = m_presenceService.GetAgents(t1);
244 m_usersOnlineCache.Add(groupID, onlineAgents, m_usersOnlineCacheExpirySeconds);
245 }
246
247 HashSet<string> onlineAgentsUuidSet = new HashSet<string>();
248 Array.ForEach<PresenceInfo>(onlineAgents, pi => onlineAgentsUuidSet.Add(pi.UserID));
249
250 groupMembers = groupMembers.Where(gmd => onlineAgentsUuidSet.Contains(gmd.AgentID.ToString())).ToList();
251
252 // if (m_debugEnabled)
253// m_log.DebugFormat(
254// "[Groups.Messaging]: SendMessageToGroup called for group {0} with {1} visible members, {2} online",
255// groupID, groupMembersCount, groupMembers.Count());
256 }
257 else
258 {
259 if (m_debugEnabled)
260 m_log.DebugFormat(
261 "[Groups.Messaging]: SendMessageToGroup called for group {0} with {1} visible members",
262 groupID, groupMembers.Count);
263 }
264
265 int requestStartTick = Environment.TickCount;
266
267 foreach (GroupMembersData member in groupMembers)
268 {
269 if (m_groupData.hasAgentDroppedGroupChatSession(member.AgentID.ToString(), groupID))
270 {
271 // Don't deliver messages to people who have dropped this session
272 if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: {0} has dropped session, not delivering to them", member.AgentID);
273 continue;
274 }
275
276 // Copy Message
277 GridInstantMessage msg = new GridInstantMessage();
278 msg.imSessionID = groupID.Guid;
279 msg.fromAgentName = im.fromAgentName;
280 msg.message = im.message;
281 msg.dialog = im.dialog;
282 msg.offline = im.offline;
283 msg.ParentEstateID = im.ParentEstateID;
284 msg.Position = im.Position;
285 msg.RegionID = im.RegionID;
286 msg.binaryBucket = im.binaryBucket;
287 msg.timestamp = (uint)Util.UnixTimeSinceEpoch();
288
289 msg.fromAgentID = im.fromAgentID;
290 msg.fromGroup = true;
291
292 msg.toAgentID = member.AgentID.Guid;
293
294 IClientAPI client = GetActiveClient(member.AgentID);
295 if (client == null)
296 {
297 // If they're not local, forward across the grid
298 if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: Delivering to {0} via Grid", member.AgentID);
299 m_msgTransferModule.SendInstantMessage(msg, delegate(bool success) { });
300 }
301 else
302 {
303 // Deliver locally, directly
304 if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: Passing to ProcessMessageFromGroupSession to deliver to {0} locally", client.Name);
305 ProcessMessageFromGroupSession(msg);
306 }
307 }
308
309 // Temporary for assessing how long it still takes to send messages to large online groups.
310 if (m_messageOnlineAgentsOnly)
311 m_log.DebugFormat(
312 "[Groups.Messaging]: SendMessageToGroup for group {0} with {1} visible members, {2} online took {3}ms",
313 groupID, groupMembersCount, groupMembers.Count(), Environment.TickCount - requestStartTick);
314 }
315
316 #region SimGridEventHandlers
317
318 void OnClientLogin(IClientAPI client)
319 {
320 if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: OnInstantMessage registered for {0}", client.Name);
321 }
322
323 private void OnNewClient(IClientAPI client)
324 {
325 if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: OnInstantMessage registered for {0}", client.Name);
326
327 client.OnInstantMessage += OnInstantMessage;
328 }
329
330 private void OnGridInstantMessage(GridInstantMessage msg)
331 {
332 // The instant message module will only deliver messages of dialog types:
333 // MessageFromAgent, StartTyping, StopTyping, MessageFromObject
334 //
335 // Any other message type will not be delivered to a client by the
336 // Instant Message Module
337
338
339 if (m_debugEnabled)
340 {
341 m_log.DebugFormat("[Groups.Messaging]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
342
343 DebugGridInstantMessage(msg);
344 }
345
346 // Incoming message from a group
347 if ((msg.fromGroup == true) &&
348 ((msg.dialog == (byte)InstantMessageDialog.SessionSend)
349 || (msg.dialog == (byte)InstantMessageDialog.SessionAdd)
350 || (msg.dialog == (byte)InstantMessageDialog.SessionDrop)))
351 {
352 ProcessMessageFromGroupSession(msg);
353 }
354 }
355
356 private void ProcessMessageFromGroupSession(GridInstantMessage msg)
357 {
358 if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: Session message from {0} going to agent {1}", msg.fromAgentName, msg.toAgentID);
359
360 UUID AgentID = new UUID(msg.fromAgentID);
361 UUID GroupID = new UUID(msg.imSessionID);
362
363 switch (msg.dialog)
364 {
365 case (byte)InstantMessageDialog.SessionAdd:
366 m_groupData.AgentInvitedToGroupChatSession(AgentID.ToString(), GroupID);
367 break;
368
369 case (byte)InstantMessageDialog.SessionDrop:
370 m_groupData.AgentDroppedFromGroupChatSession(AgentID.ToString(), GroupID);
371 break;
372
373 case (byte)InstantMessageDialog.SessionSend:
374 if (!m_groupData.hasAgentDroppedGroupChatSession(AgentID.ToString(), GroupID)
375 && !m_groupData.hasAgentBeenInvitedToGroupChatSession(AgentID.ToString(), GroupID)
376 )
377 {
378 // Agent not in session and hasn't dropped from session
379 // Add them to the session for now, and Invite them
380 m_groupData.AgentInvitedToGroupChatSession(AgentID.ToString(), GroupID);
381
382 UUID toAgentID = new UUID(msg.toAgentID);
383 IClientAPI activeClient = GetActiveClient(toAgentID);
384 if (activeClient != null)
385 {
386 GroupRecord groupInfo = m_groupData.GetGroupRecord(UUID.Zero.ToString(), GroupID, null);
387 if (groupInfo != null)
388 {
389 if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: Sending chatterbox invite instant message");
390
391 // Force? open the group session dialog???
392 // and simultanously deliver the message, so we don't need to do a seperate client.SendInstantMessage(msg);
393 IEventQueue eq = activeClient.Scene.RequestModuleInterface<IEventQueue>();
394 eq.ChatterboxInvitation(
395 GroupID
396 , groupInfo.GroupName
397 , new UUID(msg.fromAgentID)
398 , msg.message
399 , new UUID(msg.toAgentID)
400 , msg.fromAgentName
401 , msg.dialog
402 , msg.timestamp
403 , msg.offline == 1
404 , (int)msg.ParentEstateID
405 , msg.Position
406 , 1
407 , new UUID(msg.imSessionID)
408 , msg.fromGroup
409 , OpenMetaverse.Utils.StringToBytes(groupInfo.GroupName)
410 );
411
412 eq.ChatterBoxSessionAgentListUpdates(
413 new UUID(GroupID)
414 , new UUID(msg.fromAgentID)
415 , new UUID(msg.toAgentID)
416 , false //canVoiceChat
417 , false //isModerator
418 , false //text mute
419 );
420 }
421 }
422 }
423 else if (!m_groupData.hasAgentDroppedGroupChatSession(AgentID.ToString(), GroupID))
424 {
425 // User hasn't dropped, so they're in the session,
426 // maybe we should deliver it.
427 IClientAPI client = GetActiveClient(new UUID(msg.toAgentID));
428 if (client != null)
429 {
430 // Deliver locally, directly
431 if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: Delivering to {0} locally", client.Name);
432 client.SendInstantMessage(msg);
433 }
434 else
435 {
436 m_log.WarnFormat("[Groups.Messaging]: Received a message over the grid for a client that isn't here: {0}", msg.toAgentID);
437 }
438 }
439 break;
440
441 default:
442 m_log.WarnFormat("[Groups.Messaging]: I don't know how to proccess a {0} message.", ((InstantMessageDialog)msg.dialog).ToString());
443 break;
444 }
445 }
446
447 #endregion
448
449
450 #region ClientEvents
451 private void OnInstantMessage(IClientAPI remoteClient, GridInstantMessage im)
452 {
453 if (m_debugEnabled)
454 {
455 m_log.DebugFormat("[Groups.Messaging]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
456
457 DebugGridInstantMessage(im);
458 }
459
460 // Start group IM session
461 if ((im.dialog == (byte)InstantMessageDialog.SessionGroupStart))
462 {
463 if (m_debugEnabled) m_log.InfoFormat("[Groups.Messaging]: imSessionID({0}) toAgentID({1})", im.imSessionID, im.toAgentID);
464
465 UUID GroupID = new UUID(im.imSessionID);
466 UUID AgentID = new UUID(im.fromAgentID);
467
468 GroupRecord groupInfo = m_groupData.GetGroupRecord(UUID.Zero.ToString(), GroupID, null);
469
470 if (groupInfo != null)
471 {
472 m_groupData.AgentInvitedToGroupChatSession(AgentID.ToString(), GroupID);
473
474 ChatterBoxSessionStartReplyViaCaps(remoteClient, groupInfo.GroupName, GroupID);
475
476 IEventQueue queue = remoteClient.Scene.RequestModuleInterface<IEventQueue>();
477 queue.ChatterBoxSessionAgentListUpdates(
478 GroupID
479 , AgentID
480 , new UUID(im.toAgentID)
481 , false //canVoiceChat
482 , false //isModerator
483 , false //text mute
484 );
485 }
486 }
487
488 // Send a message from locally connected client to a group
489 if ((im.dialog == (byte)InstantMessageDialog.SessionSend))
490 {
491 UUID GroupID = new UUID(im.imSessionID);
492 UUID AgentID = new UUID(im.fromAgentID);
493
494 if (m_debugEnabled)
495 m_log.DebugFormat("[Groups.Messaging]: Send message to session for group {0} with session ID {1}", GroupID, im.imSessionID.ToString());
496
497 //If this agent is sending a message, then they want to be in the session
498 m_groupData.AgentInvitedToGroupChatSession(AgentID.ToString(), GroupID);
499
500 SendMessageToGroup(im, GroupID);
501 }
502 }
503
504 #endregion
505
506 void ChatterBoxSessionStartReplyViaCaps(IClientAPI remoteClient, string groupName, UUID groupID)
507 {
508 if (m_debugEnabled) m_log.DebugFormat("[Groups.Messaging]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
509
510 OSDMap moderatedMap = new OSDMap(4);
511 moderatedMap.Add("voice", OSD.FromBoolean(false));
512
513 OSDMap sessionMap = new OSDMap(4);
514 sessionMap.Add("moderated_mode", moderatedMap);
515 sessionMap.Add("session_name", OSD.FromString(groupName));
516 sessionMap.Add("type", OSD.FromInteger(0));
517 sessionMap.Add("voice_enabled", OSD.FromBoolean(false));
518
519 OSDMap bodyMap = new OSDMap(4);
520 bodyMap.Add("session_id", OSD.FromUUID(groupID));
521 bodyMap.Add("temp_session_id", OSD.FromUUID(groupID));
522 bodyMap.Add("success", OSD.FromBoolean(true));
523 bodyMap.Add("session_info", sessionMap);
524
525 IEventQueue queue = remoteClient.Scene.RequestModuleInterface<IEventQueue>();
526
527 if (queue != null)
528 {
529 queue.Enqueue(queue.BuildEvent("ChatterBoxSessionStartReply", bodyMap), remoteClient.AgentId);
530 }
531 }
532
533 private void DebugGridInstantMessage(GridInstantMessage im)
534 {
535 // Don't log any normal IMs (privacy!)
536 if (m_debugEnabled && im.dialog != (byte)InstantMessageDialog.MessageFromAgent)
537 {
538 m_log.WarnFormat("[Groups.Messaging]: IM: fromGroup({0})", im.fromGroup ? "True" : "False");
539 m_log.WarnFormat("[Groups.Messaging]: IM: Dialog({0})", ((InstantMessageDialog)im.dialog).ToString());
540 m_log.WarnFormat("[Groups.Messaging]: IM: fromAgentID({0})", im.fromAgentID.ToString());
541 m_log.WarnFormat("[Groups.Messaging]: IM: fromAgentName({0})", im.fromAgentName.ToString());
542 m_log.WarnFormat("[Groups.Messaging]: IM: imSessionID({0})", im.imSessionID.ToString());
543 m_log.WarnFormat("[Groups.Messaging]: IM: message({0})", im.message.ToString());
544 m_log.WarnFormat("[Groups.Messaging]: IM: offline({0})", im.offline.ToString());
545 m_log.WarnFormat("[Groups.Messaging]: IM: toAgentID({0})", im.toAgentID.ToString());
546 m_log.WarnFormat("[Groups.Messaging]: IM: binaryBucket({0})", OpenMetaverse.Utils.BytesToHexString(im.binaryBucket, "BinaryBucket"));
547 }
548 }
549
550 #region Client Tools
551
552 /// <summary>
553 /// Try to find an active IClientAPI reference for agentID giving preference to root connections
554 /// </summary>
555 private IClientAPI GetActiveClient(UUID agentID)
556 {
557 if (m_debugEnabled) m_log.WarnFormat("[Groups.Messaging]: Looking for local client {0}", agentID);
558
559 IClientAPI child = null;
560
561 // Try root avatar first
562 foreach (Scene scene in m_sceneList)
563 {
564 ScenePresence sp = scene.GetScenePresence(agentID);
565 if (sp != null)
566 {
567 if (!sp.IsChildAgent)
568 {
569 if (m_debugEnabled) m_log.WarnFormat("[Groups.Messaging]: Found root agent for client : {0}", sp.ControllingClient.Name);
570 return sp.ControllingClient;
571 }
572 else
573 {
574 if (m_debugEnabled) m_log.WarnFormat("[Groups.Messaging]: Found child agent for client : {0}", sp.ControllingClient.Name);
575 child = sp.ControllingClient;
576 }
577 }
578 }
579
580 // If we didn't find a root, then just return whichever child we found, or null if none
581 if (child == null)
582 {
583 if (m_debugEnabled) m_log.WarnFormat("[Groups.Messaging]: Could not find local client for agent : {0}", agentID);
584 }
585 else
586 {
587 if (m_debugEnabled) m_log.WarnFormat("[Groups.Messaging]: Returning child agent for client : {0}", child.Name);
588 }
589 return child;
590 }
591
592 #endregion
593 }
594}
diff --git a/OpenSim/Addons/Groups/GroupsModule.cs b/OpenSim/Addons/Groups/GroupsModule.cs
new file mode 100644
index 0000000..10bfa8f
--- /dev/null
+++ b/OpenSim/Addons/Groups/GroupsModule.cs
@@ -0,0 +1,1467 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Reflection;
31using System.Timers;
32using log4net;
33using Mono.Addins;
34using Nini.Config;
35using OpenMetaverse;
36using OpenMetaverse.StructuredData;
37using OpenSim.Framework;
38using OpenSim.Region.Framework.Interfaces;
39using OpenSim.Region.Framework.Scenes;
40using OpenSim.Services.Interfaces;
41using DirFindFlags = OpenMetaverse.DirectoryManager.DirFindFlags;
42
43namespace OpenSim.Groups
44{
45 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GroupsModule")]
46 public class GroupsModule : ISharedRegionModule, IGroupsModule
47 {
48 /// <summary>
49 /// </summary>
50
51 private static readonly ILog m_log =
52 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
53
54 private List<Scene> m_sceneList = new List<Scene>();
55
56 private IMessageTransferModule m_msgTransferModule = null;
57
58 private IGroupsServicesConnector m_groupData = null;
59 private IUserManagement m_UserManagement;
60
61 // Configuration settings
62 private bool m_groupsEnabled = false;
63 private bool m_groupNoticesEnabled = true;
64 private bool m_debugEnabled = false;
65 private int m_levelGroupCreate = 0;
66
67 #region Region Module interfaceBase Members
68
69 public void Initialise(IConfigSource config)
70 {
71 IConfig groupsConfig = config.Configs["Groups"];
72
73 if (groupsConfig == null)
74 {
75 // Do not run this module by default.
76 return;
77 }
78 else
79 {
80 m_groupsEnabled = groupsConfig.GetBoolean("Enabled", false);
81 if (!m_groupsEnabled)
82 {
83 return;
84 }
85
86 if (groupsConfig.GetString("Module", "Default") != Name)
87 {
88 m_groupsEnabled = false;
89
90 return;
91 }
92
93 m_log.InfoFormat("[Groups]: Initializing {0}", this.Name);
94
95 m_groupNoticesEnabled = groupsConfig.GetBoolean("NoticesEnabled", true);
96 m_debugEnabled = groupsConfig.GetBoolean("DebugEnabled", false);
97 m_levelGroupCreate = groupsConfig.GetInt("LevelGroupCreate", 0);
98 }
99 }
100
101 public void AddRegion(Scene scene)
102 {
103 if (m_groupsEnabled)
104 {
105 scene.RegisterModuleInterface<IGroupsModule>(this);
106 scene.AddCommand(
107 "debug",
108 this,
109 "debug groups verbose",
110 "debug groups verbose <true|false>",
111 "This setting turns on very verbose groups debugging",
112 HandleDebugGroupsVerbose);
113 }
114 }
115
116 private void HandleDebugGroupsVerbose(object modules, string[] args)
117 {
118 if (args.Length < 4)
119 {
120 MainConsole.Instance.Output("Usage: debug groups verbose <true|false>");
121 return;
122 }
123
124 bool verbose = false;
125 if (!bool.TryParse(args[3], out verbose))
126 {
127 MainConsole.Instance.Output("Usage: debug groups verbose <true|false>");
128 return;
129 }
130
131 m_debugEnabled = verbose;
132
133 MainConsole.Instance.OutputFormat("{0} verbose logging set to {1}", Name, m_debugEnabled);
134 }
135
136 public void RegionLoaded(Scene scene)
137 {
138 if (!m_groupsEnabled)
139 return;
140
141 if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
142
143 scene.EventManager.OnNewClient += OnNewClient;
144 scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage;
145 // The InstantMessageModule itself doesn't do this,
146 // so lets see if things explode if we don't do it
147 // scene.EventManager.OnClientClosed += OnClientClosed;
148
149 if (m_groupData == null)
150 {
151 m_groupData = scene.RequestModuleInterface<IGroupsServicesConnector>();
152
153 // No Groups Service Connector, then nothing works...
154 if (m_groupData == null)
155 {
156 m_groupsEnabled = false;
157 m_log.Error("[Groups]: Could not get IGroupsServicesConnector");
158 RemoveRegion(scene);
159 return;
160 }
161 }
162
163 if (m_msgTransferModule == null)
164 {
165 m_msgTransferModule = scene.RequestModuleInterface<IMessageTransferModule>();
166
167 // No message transfer module, no notices, group invites, rejects, ejects, etc
168 if (m_msgTransferModule == null)
169 {
170 m_log.Warn("[Groups]: Could not get MessageTransferModule");
171 }
172 }
173
174 if (m_UserManagement == null)
175 {
176 m_UserManagement = scene.RequestModuleInterface<IUserManagement>();
177 if (m_UserManagement == null)
178 m_log.Warn("[Groups]: Could not get UserManagementModule");
179 }
180
181 lock (m_sceneList)
182 {
183 m_sceneList.Add(scene);
184 }
185
186
187 }
188
189 public void RemoveRegion(Scene scene)
190 {
191 if (!m_groupsEnabled)
192 return;
193
194 if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
195
196 scene.EventManager.OnNewClient -= OnNewClient;
197 scene.EventManager.OnIncomingInstantMessage -= OnGridInstantMessage;
198
199 lock (m_sceneList)
200 {
201 m_sceneList.Remove(scene);
202 }
203 }
204
205 public void Close()
206 {
207 if (!m_groupsEnabled)
208 return;
209
210 if (m_debugEnabled) m_log.Debug("[Groups]: Shutting down Groups module.");
211 }
212
213 public Type ReplaceableInterface
214 {
215 get { return null; }
216 }
217
218 public string Name
219 {
220 get { return "Groups Module V2"; }
221 }
222
223 public void PostInitialise()
224 {
225 // NoOp
226 }
227
228 #endregion
229
230 #region EventHandlers
231 private void OnNewClient(IClientAPI client)
232 {
233 if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
234
235 client.OnUUIDGroupNameRequest += HandleUUIDGroupNameRequest;
236 client.OnAgentDataUpdateRequest += OnAgentDataUpdateRequest;
237 client.OnDirFindQuery += OnDirFindQuery;
238 client.OnRequestAvatarProperties += OnRequestAvatarProperties;
239
240 // Used for Notices and Group Invites/Accept/Reject
241 client.OnInstantMessage += OnInstantMessage;
242
243 // Send client their groups information.
244 SendAgentGroupDataUpdate(client, client.AgentId);
245 }
246
247 private void OnRequestAvatarProperties(IClientAPI remoteClient, UUID avatarID)
248 {
249 if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
250
251 //GroupMembershipData[] avatarGroups = m_groupData.GetAgentGroupMemberships(GetRequestingAgentID(remoteClient), avatarID).ToArray();
252 GroupMembershipData[] avatarGroups = GetProfileListedGroupMemberships(remoteClient, avatarID);
253 remoteClient.SendAvatarGroupsReply(avatarID, avatarGroups);
254 }
255
256 /*
257 * This becomes very problematic in a shared module. In a shared module you may have more then one
258 * reference to IClientAPI's, one for 0 or 1 root connections, and 0 or more child connections.
259 * The OnClientClosed event does not provide anything to indicate which one of those should be closed
260 * nor does it provide what scene it was from so that the specific reference can be looked up.
261 * The InstantMessageModule.cs does not currently worry about unregistering the handles,
262 * and it should be an issue, since it's the client that references us not the other way around
263 * , so as long as we don't keep a reference to the client laying around, the client can still be GC'ed
264 private void OnClientClosed(UUID AgentId)
265 {
266 if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
267
268 lock (m_ActiveClients)
269 {
270 if (m_ActiveClients.ContainsKey(AgentId))
271 {
272 IClientAPI client = m_ActiveClients[AgentId];
273 client.OnUUIDGroupNameRequest -= HandleUUIDGroupNameRequest;
274 client.OnAgentDataUpdateRequest -= OnAgentDataUpdateRequest;
275 client.OnDirFindQuery -= OnDirFindQuery;
276 client.OnInstantMessage -= OnInstantMessage;
277
278 m_ActiveClients.Remove(AgentId);
279 }
280 else
281 {
282 if (m_debugEnabled) m_log.WarnFormat("[Groups]: Client closed that wasn't registered here.");
283 }
284
285
286 }
287 }
288 */
289
290 void OnDirFindQuery(IClientAPI remoteClient, UUID queryID, string queryText, uint queryFlags, int queryStart)
291 {
292 if (((DirFindFlags)queryFlags & DirFindFlags.Groups) == DirFindFlags.Groups)
293 {
294 if (m_debugEnabled)
295 m_log.DebugFormat(
296 "[Groups]: {0} called with queryText({1}) queryFlags({2}) queryStart({3})",
297 System.Reflection.MethodBase.GetCurrentMethod().Name, queryText, (DirFindFlags)queryFlags, queryStart);
298
299 // TODO: This currently ignores pretty much all the query flags including Mature and sort order
300 remoteClient.SendDirGroupsReply(queryID, m_groupData.FindGroups(GetRequestingAgentIDStr(remoteClient), queryText).ToArray());
301 }
302
303 }
304
305 private void OnAgentDataUpdateRequest(IClientAPI remoteClient, UUID dataForAgentID, UUID sessionID)
306 {
307 if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
308
309 UUID activeGroupID = UUID.Zero;
310 string activeGroupTitle = string.Empty;
311 string activeGroupName = string.Empty;
312 ulong activeGroupPowers = (ulong)GroupPowers.None;
313
314 GroupMembershipData membership = m_groupData.GetAgentActiveMembership(GetRequestingAgentIDStr(remoteClient), dataForAgentID.ToString());
315 if (membership != null)
316 {
317 activeGroupID = membership.GroupID;
318 activeGroupTitle = membership.GroupTitle;
319 activeGroupPowers = membership.GroupPowers;
320 }
321
322 SendAgentDataUpdate(remoteClient, dataForAgentID, activeGroupID, activeGroupName, activeGroupPowers, activeGroupTitle);
323
324 SendScenePresenceUpdate(dataForAgentID, activeGroupTitle);
325 }
326
327 private void HandleUUIDGroupNameRequest(UUID GroupID, IClientAPI remoteClient)
328 {
329 if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
330
331 string GroupName;
332
333 GroupRecord group = m_groupData.GetGroupRecord(GetRequestingAgentIDStr(remoteClient), GroupID, null);
334 if (group != null)
335 {
336 GroupName = group.GroupName;
337 }
338 else
339 {
340 GroupName = "Unknown";
341 }
342
343 remoteClient.SendGroupNameReply(GroupID, GroupName);
344 }
345
346 private void OnInstantMessage(IClientAPI remoteClient, GridInstantMessage im)
347 {
348 if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
349
350 m_log.DebugFormat("[Groups]: IM From {0} to {1} msg {2} type {3}", im.fromAgentID, im.toAgentID, im.message, (InstantMessageDialog)im.dialog);
351 // Group invitations
352 if ((im.dialog == (byte)InstantMessageDialog.GroupInvitationAccept) || (im.dialog == (byte)InstantMessageDialog.GroupInvitationDecline))
353 {
354 UUID inviteID = new UUID(im.imSessionID);
355 GroupInviteInfo inviteInfo = m_groupData.GetAgentToGroupInvite(GetRequestingAgentIDStr(remoteClient), inviteID);
356
357 if (inviteInfo == null)
358 {
359 if (m_debugEnabled) m_log.WarnFormat("[Groups]: Received an Invite IM for an invite that does not exist {0}.", inviteID);
360 return;
361 }
362
363 //m_log.DebugFormat("[XXX]: Invite is for Agent {0} to Group {1}.", inviteInfo.AgentID, inviteInfo.GroupID);
364
365 UUID fromAgentID = new UUID(im.fromAgentID);
366 UUID invitee = UUID.Zero;
367 string tmp = string.Empty;
368 Util.ParseUniversalUserIdentifier(inviteInfo.AgentID, out invitee, out tmp, out tmp, out tmp, out tmp);
369 if ((inviteInfo != null) && (fromAgentID == invitee))
370 {
371 // Accept
372 if (im.dialog == (byte)InstantMessageDialog.GroupInvitationAccept)
373 {
374 //m_log.DebugFormat("[XXX]: Received an accept invite notice.");
375
376 // and the sessionid is the role
377 string reason = string.Empty;
378 if (!m_groupData.AddAgentToGroup(GetRequestingAgentIDStr(remoteClient), invitee.ToString(), inviteInfo.GroupID, inviteInfo.RoleID, string.Empty, out reason))
379 remoteClient.SendAgentAlertMessage("Unable to add you to the group: " + reason, false);
380 else
381 {
382 GridInstantMessage msg = new GridInstantMessage();
383 msg.imSessionID = UUID.Zero.Guid;
384 msg.fromAgentID = UUID.Zero.Guid;
385 msg.toAgentID = invitee.Guid;
386 msg.timestamp = (uint)Util.UnixTimeSinceEpoch();
387 msg.fromAgentName = "Groups";
388 msg.message = string.Format("You have been added to the group.");
389 msg.dialog = (byte)OpenMetaverse.InstantMessageDialog.MessageBox;
390 msg.fromGroup = false;
391 msg.offline = (byte)0;
392 msg.ParentEstateID = 0;
393 msg.Position = Vector3.Zero;
394 msg.RegionID = UUID.Zero.Guid;
395 msg.binaryBucket = new byte[0];
396
397 OutgoingInstantMessage(msg, invitee);
398
399 UpdateAllClientsWithGroupInfo(invitee);
400 }
401
402 m_groupData.RemoveAgentToGroupInvite(GetRequestingAgentIDStr(remoteClient), inviteID);
403
404 }
405
406 // Reject
407 if (im.dialog == (byte)InstantMessageDialog.GroupInvitationDecline)
408 {
409 if (m_debugEnabled) m_log.DebugFormat("[Groups]: Received a reject invite notice.");
410 m_groupData.RemoveAgentToGroupInvite(GetRequestingAgentIDStr(remoteClient), inviteID);
411
412 m_groupData.RemoveAgentFromGroup(GetRequestingAgentIDStr(remoteClient), inviteInfo.AgentID, inviteInfo.GroupID);
413 }
414 }
415 }
416
417 // Group notices
418 if ((im.dialog == (byte)InstantMessageDialog.GroupNotice))
419 {
420 if (!m_groupNoticesEnabled)
421 {
422 return;
423 }
424
425 UUID GroupID = new UUID(im.toAgentID);
426 if (m_groupData.GetGroupRecord(GetRequestingAgentIDStr(remoteClient), GroupID, null) != null)
427 {
428 UUID NoticeID = UUID.Random();
429 string Subject = im.message.Substring(0, im.message.IndexOf('|'));
430 string Message = im.message.Substring(Subject.Length + 1);
431
432 InventoryItemBase item = null;
433 bool hasAttachment = false;
434
435 if (im.binaryBucket.Length >= 1 && im.binaryBucket[0] > 0)
436 {
437 hasAttachment = true;
438 string binBucket = OpenMetaverse.Utils.BytesToString(im.binaryBucket);
439 binBucket = binBucket.Remove(0, 14).Trim();
440
441 OSD binBucketOSD = OSDParser.DeserializeLLSDXml(binBucket);
442 if (binBucketOSD is OSDMap)
443 {
444 OSDMap binBucketMap = (OSDMap)binBucketOSD;
445
446 UUID itemID = binBucketMap["item_id"].AsUUID();
447 UUID ownerID = binBucketMap["owner_id"].AsUUID();
448 item = new InventoryItemBase(itemID, ownerID);
449 item = m_sceneList[0].InventoryService.GetItem(item);
450 }
451 else
452 m_log.DebugFormat("[Groups]: Received OSD with unexpected type: {0}", binBucketOSD.GetType());
453 }
454
455 if (m_groupData.AddGroupNotice(GetRequestingAgentIDStr(remoteClient), GroupID, NoticeID, im.fromAgentName, Subject, Message,
456 hasAttachment,
457 (byte)(item == null ? 0 : item.AssetType),
458 item == null ? null : item.Name,
459 item == null ? UUID.Zero : item.ID,
460 item == null ? UUID.Zero.ToString() : item.Owner.ToString()))
461 {
462 if (OnNewGroupNotice != null)
463 {
464 OnNewGroupNotice(GroupID, NoticeID);
465 }
466
467 // Send notice out to everyone that wants notices
468 // Build notice IIM
469 GridInstantMessage msg = CreateGroupNoticeIM(UUID.Zero, NoticeID, (byte)OpenMetaverse.InstantMessageDialog.GroupNotice);
470 foreach (GroupMembersData member in m_groupData.GetGroupMembers(GetRequestingAgentIDStr(remoteClient), GroupID))
471 {
472 if (member.AcceptNotices)
473 {
474 msg.toAgentID = member.AgentID.Guid;
475 OutgoingInstantMessage(msg, member.AgentID);
476 }
477 }
478 }
479 }
480 }
481
482 if (im.dialog == (byte)InstantMessageDialog.GroupNoticeInventoryAccepted)
483 {
484 if (im.binaryBucket.Length < 16) // Invalid
485 return;
486
487 //// 16 bytes are the UUID. Maybe.
488 UUID folderID = new UUID(im.binaryBucket, 0);
489 UUID noticeID = new UUID(im.imSessionID);
490
491 GroupNoticeInfo notice = m_groupData.GetGroupNotice(remoteClient.AgentId.ToString(), noticeID);
492 if (notice != null)
493 {
494 UUID giver = new UUID(im.toAgentID);
495 string tmp = string.Empty;
496 Util.ParseUniversalUserIdentifier(notice.noticeData.AttachmentOwnerID, out giver, out tmp, out tmp, out tmp, out tmp);
497
498 m_log.DebugFormat("[Groups]: Giving inventory from {0} to {1}", giver, remoteClient.AgentId);
499 InventoryItemBase itemCopy = ((Scene)(remoteClient.Scene)).GiveInventoryItem(remoteClient.AgentId,
500 giver, notice.noticeData.AttachmentItemID);
501
502 if (itemCopy == null)
503 {
504 remoteClient.SendAgentAlertMessage("Can't find item to give. Nothing given.", false);
505 return;
506 }
507
508 remoteClient.SendInventoryItemCreateUpdate(itemCopy, 0);
509 }
510
511 }
512
513 // Interop, received special 210 code for ejecting a group member
514 // this only works within the comms servers domain, and won't work hypergrid
515 // TODO:FIXME: Use a presense server of some kind to find out where the
516 // client actually is, and try contacting that region directly to notify them,
517 // or provide the notification via xmlrpc update queue
518 if ((im.dialog == 210))
519 {
520 // This is sent from the region that the ejectee was ejected from
521 // if it's being delivered here, then the ejectee is here
522 // so we need to send local updates to the agent.
523
524 UUID ejecteeID = new UUID(im.toAgentID);
525
526 im.dialog = (byte)InstantMessageDialog.MessageFromAgent;
527 OutgoingInstantMessage(im, ejecteeID);
528
529 IClientAPI ejectee = GetActiveClient(ejecteeID);
530 if (ejectee != null)
531 {
532 UUID groupID = new UUID(im.imSessionID);
533 ejectee.SendAgentDropGroup(groupID);
534 }
535 }
536 }
537
538 private void OnGridInstantMessage(GridInstantMessage msg)
539 {
540 if (m_debugEnabled) m_log.InfoFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
541
542 // Trigger the above event handler
543 OnInstantMessage(null, msg);
544
545 // If a message from a group arrives here, it may need to be forwarded to a local client
546 if (msg.fromGroup == true)
547 {
548 switch (msg.dialog)
549 {
550 case (byte)InstantMessageDialog.GroupInvitation:
551 case (byte)InstantMessageDialog.GroupNotice:
552 UUID toAgentID = new UUID(msg.toAgentID);
553 IClientAPI localClient = GetActiveClient(toAgentID);
554 if (localClient != null)
555 {
556 localClient.SendInstantMessage(msg);
557 }
558 break;
559 }
560 }
561 }
562
563 #endregion
564
565 #region IGroupsModule Members
566
567 public event NewGroupNotice OnNewGroupNotice;
568
569 public GroupRecord GetGroupRecord(UUID GroupID)
570 {
571 return m_groupData.GetGroupRecord(UUID.Zero.ToString(), GroupID, null);
572 }
573
574 public GroupRecord GetGroupRecord(string name)
575 {
576 return m_groupData.GetGroupRecord(UUID.Zero.ToString(), UUID.Zero, name);
577 }
578
579 public void ActivateGroup(IClientAPI remoteClient, UUID groupID)
580 {
581 if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
582
583 m_groupData.SetAgentActiveGroup(GetRequestingAgentIDStr(remoteClient), GetRequestingAgentIDStr(remoteClient), groupID);
584
585 // Changing active group changes title, active powers, all kinds of things
586 // anyone who is in any region that can see this client, should probably be
587 // updated with new group info. At a minimum, they should get ScenePresence
588 // updated with new title.
589 UpdateAllClientsWithGroupInfo(remoteClient.AgentId);
590 }
591
592 /// <summary>
593 /// Get the Role Titles for an Agent, for a specific group
594 /// </summary>
595 public List<GroupTitlesData> GroupTitlesRequest(IClientAPI remoteClient, UUID groupID)
596 {
597 if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
598
599 List<GroupRolesData> agentRoles = m_groupData.GetAgentGroupRoles(GetRequestingAgentIDStr(remoteClient), GetRequestingAgentIDStr(remoteClient), groupID);
600 GroupMembershipData agentMembership = m_groupData.GetAgentGroupMembership(GetRequestingAgentIDStr(remoteClient), GetRequestingAgentIDStr(remoteClient), groupID);
601
602 List<GroupTitlesData> titles = new List<GroupTitlesData>();
603 foreach (GroupRolesData role in agentRoles)
604 {
605 GroupTitlesData title = new GroupTitlesData();
606 title.Name = role.Name;
607 if (agentMembership != null)
608 {
609 title.Selected = agentMembership.ActiveRole == role.RoleID;
610 }
611 title.UUID = role.RoleID;
612
613 titles.Add(title);
614 }
615
616 return titles;
617 }
618
619 public List<GroupMembersData> GroupMembersRequest(IClientAPI remoteClient, UUID groupID)
620 {
621 if (m_debugEnabled)
622 m_log.DebugFormat(
623 "[Groups]: GroupMembersRequest called for {0} from client {1}", groupID, remoteClient.Name);
624
625 List<GroupMembersData> data = m_groupData.GetGroupMembers(GetRequestingAgentIDStr(remoteClient), groupID);
626
627 if (m_debugEnabled)
628 {
629 foreach (GroupMembersData member in data)
630 {
631 m_log.DebugFormat("[Groups]: Member({0}) - IsOwner({1})", member.AgentID, member.IsOwner);
632 }
633 }
634
635 return data;
636
637 }
638
639 public List<GroupRolesData> GroupRoleDataRequest(IClientAPI remoteClient, UUID groupID)
640 {
641 if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
642
643 List<GroupRolesData> data = m_groupData.GetGroupRoles(GetRequestingAgentIDStr(remoteClient), groupID);
644
645 return data;
646 }
647
648 public List<GroupRoleMembersData> GroupRoleMembersRequest(IClientAPI remoteClient, UUID groupID)
649 {
650 if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
651
652 List<GroupRoleMembersData> data = m_groupData.GetGroupRoleMembers(GetRequestingAgentIDStr(remoteClient), groupID);
653
654 if (m_debugEnabled)
655 {
656 foreach (GroupRoleMembersData member in data)
657 {
658 m_log.DebugFormat("[Groups]: Member({0}) - Role({1})", member.MemberID, member.RoleID);
659 }
660 }
661 return data;
662 }
663
664 public GroupProfileData GroupProfileRequest(IClientAPI remoteClient, UUID groupID)
665 {
666 if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
667
668 GroupProfileData profile = new GroupProfileData();
669
670 // just to get the OwnerRole...
671 ExtendedGroupRecord groupInfo = m_groupData.GetGroupRecord(GetRequestingAgentIDStr(remoteClient), groupID, string.Empty);
672 GroupMembershipData memberInfo = m_groupData.GetAgentGroupMembership(GetRequestingAgentIDStr(remoteClient), GetRequestingAgentIDStr(remoteClient), groupID);
673 if (groupInfo != null)
674 {
675 profile.AllowPublish = groupInfo.AllowPublish;
676 profile.Charter = groupInfo.Charter;
677 profile.FounderID = groupInfo.FounderID;
678 profile.GroupID = groupID;
679 profile.GroupMembershipCount = groupInfo.MemberCount;
680 profile.GroupRolesCount = groupInfo.RoleCount;
681 profile.InsigniaID = groupInfo.GroupPicture;
682 profile.MaturePublish = groupInfo.MaturePublish;
683 profile.MembershipFee = groupInfo.MembershipFee;
684 profile.Money = 0;
685 profile.Name = groupInfo.GroupName;
686 profile.OpenEnrollment = groupInfo.OpenEnrollment;
687 profile.OwnerRole = groupInfo.OwnerRoleID;
688 profile.ShowInList = groupInfo.ShowInList;
689 }
690 if (memberInfo != null)
691 {
692 profile.MemberTitle = memberInfo.GroupTitle;
693 profile.PowersMask = memberInfo.GroupPowers;
694 }
695
696 return profile;
697 }
698
699 public GroupMembershipData[] GetMembershipData(UUID agentID)
700 {
701 if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
702
703 return m_groupData.GetAgentGroupMemberships(UUID.Zero.ToString(), agentID.ToString()).ToArray();
704 }
705
706 public GroupMembershipData GetMembershipData(UUID groupID, UUID agentID)
707 {
708 if (m_debugEnabled)
709 m_log.DebugFormat(
710 "[Groups]: {0} called with groupID={1}, agentID={2}",
711 System.Reflection.MethodBase.GetCurrentMethod().Name, groupID, agentID);
712
713 return m_groupData.GetAgentGroupMembership(UUID.Zero.ToString(), agentID.ToString(), groupID);
714 }
715
716 public void UpdateGroupInfo(IClientAPI remoteClient, UUID groupID, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, bool allowPublish, bool maturePublish)
717 {
718 if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
719
720 // Note: Permissions checking for modification rights is handled by the Groups Server/Service
721 string reason = string.Empty;
722 if (!m_groupData.UpdateGroup(GetRequestingAgentIDStr(remoteClient), groupID, charter, showInList, insigniaID, membershipFee,
723 openEnrollment, allowPublish, maturePublish, out reason))
724 remoteClient.SendAgentAlertMessage(reason, false);
725 }
726
727 public void SetGroupAcceptNotices(IClientAPI remoteClient, UUID groupID, bool acceptNotices, bool listInProfile)
728 {
729 // Note: Permissions checking for modification rights is handled by the Groups Server/Service
730 if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
731
732 m_groupData.UpdateMembership(GetRequestingAgentIDStr(remoteClient), GetRequestingAgentIDStr(remoteClient), groupID, acceptNotices, listInProfile);
733 }
734
735 public UUID CreateGroup(IClientAPI remoteClient, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, bool allowPublish, bool maturePublish)
736 {
737 if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called in {1}", System.Reflection.MethodBase.GetCurrentMethod().Name, remoteClient.Scene.RegionInfo.RegionName);
738
739 if (m_groupData.GetGroupRecord(GetRequestingAgentIDStr(remoteClient), UUID.Zero, name) != null)
740 {
741 remoteClient.SendCreateGroupReply(UUID.Zero, false, "A group with the same name already exists.");
742 return UUID.Zero;
743 }
744
745 // check user level
746 ScenePresence avatar = null;
747 Scene scene = (Scene)remoteClient.Scene;
748 scene.TryGetScenePresence(remoteClient.AgentId, out avatar);
749
750 if (avatar != null)
751 {
752 if (avatar.UserLevel < m_levelGroupCreate)
753 {
754 remoteClient.SendCreateGroupReply(UUID.Zero, false, String.Format("Insufficient permissions to create a group. Requires level {0}", m_levelGroupCreate));
755 return UUID.Zero;
756 }
757 }
758
759 // check funds
760 // is there is a money module present ?
761 IMoneyModule money = scene.RequestModuleInterface<IMoneyModule>();
762 if (money != null)
763 {
764 // do the transaction, that is if the agent has got sufficient funds
765 if (!money.AmountCovered(remoteClient.AgentId, money.GroupCreationCharge)) {
766 remoteClient.SendCreateGroupReply(UUID.Zero, false, "Insufficient funds to create a group.");
767 return UUID.Zero;
768 }
769 money.ApplyCharge(remoteClient.AgentId, money.GroupCreationCharge, "Group Creation");
770 }
771 string reason = string.Empty;
772 UUID groupID = m_groupData.CreateGroup(remoteClient.AgentId, name, charter, showInList, insigniaID, membershipFee, openEnrollment,
773 allowPublish, maturePublish, remoteClient.AgentId, out reason);
774
775 if (groupID != UUID.Zero)
776 {
777 remoteClient.SendCreateGroupReply(groupID, true, "Group created successfullly");
778
779 // Update the founder with new group information.
780 SendAgentGroupDataUpdate(remoteClient, GetRequestingAgentID(remoteClient));
781 }
782 else
783 remoteClient.SendCreateGroupReply(groupID, false, reason);
784
785 return groupID;
786 }
787
788 public GroupNoticeData[] GroupNoticesListRequest(IClientAPI remoteClient, UUID groupID)
789 {
790 if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
791
792 // ToDo: check if agent is a member of group and is allowed to see notices?
793
794 List<ExtendedGroupNoticeData> notices = m_groupData.GetGroupNotices(GetRequestingAgentIDStr(remoteClient), groupID);
795 List<GroupNoticeData> os_notices = new List<GroupNoticeData>();
796 foreach (ExtendedGroupNoticeData n in notices)
797 {
798 GroupNoticeData osn = n.ToGroupNoticeData();
799 os_notices.Add(osn);
800 }
801
802 return os_notices.ToArray();
803 }
804
805 /// <summary>
806 /// Get the title of the agent's current role.
807 /// </summary>
808 public string GetGroupTitle(UUID avatarID)
809 {
810 if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
811
812 GroupMembershipData membership = m_groupData.GetAgentActiveMembership(UUID.Zero.ToString(), avatarID.ToString());
813 if (membership != null)
814 {
815 return membership.GroupTitle;
816 }
817 return string.Empty;
818 }
819
820 /// <summary>
821 /// Change the current Active Group Role for Agent
822 /// </summary>
823 public void GroupTitleUpdate(IClientAPI remoteClient, UUID groupID, UUID titleRoleID)
824 {
825 if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
826
827 m_groupData.SetAgentActiveGroupRole(GetRequestingAgentIDStr(remoteClient), GetRequestingAgentIDStr(remoteClient), groupID, titleRoleID);
828
829 // TODO: Not sure what all is needed here, but if the active group role change is for the group
830 // the client currently has set active, then we need to do a scene presence update too
831 // if (m_groupData.GetAgentActiveMembership(GetRequestingAgentID(remoteClient)).GroupID == GroupID)
832
833 UpdateAllClientsWithGroupInfo(GetRequestingAgentID(remoteClient));
834 }
835
836
837 public void GroupRoleUpdate(IClientAPI remoteClient, UUID groupID, UUID roleID, string name, string description, string title, ulong powers, byte updateType)
838 {
839 if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
840
841 // Security Checks are handled in the Groups Service.
842
843 switch ((OpenMetaverse.GroupRoleUpdate)updateType)
844 {
845 case OpenMetaverse.GroupRoleUpdate.Create:
846 string reason = string.Empty;
847 if (!m_groupData.AddGroupRole(GetRequestingAgentIDStr(remoteClient), groupID, UUID.Random(), name, description, title, powers, out reason))
848 remoteClient.SendAgentAlertMessage("Unable to create role: " + reason, false);
849 break;
850
851 case OpenMetaverse.GroupRoleUpdate.Delete:
852 m_groupData.RemoveGroupRole(GetRequestingAgentIDStr(remoteClient), groupID, roleID);
853 break;
854
855 case OpenMetaverse.GroupRoleUpdate.UpdateAll:
856 case OpenMetaverse.GroupRoleUpdate.UpdateData:
857 case OpenMetaverse.GroupRoleUpdate.UpdatePowers:
858 if (m_debugEnabled)
859 {
860 GroupPowers gp = (GroupPowers)powers;
861 m_log.DebugFormat("[Groups]: Role ({0}) updated with Powers ({1}) ({2})", name, powers.ToString(), gp.ToString());
862 }
863 m_groupData.UpdateGroupRole(GetRequestingAgentIDStr(remoteClient), groupID, roleID, name, description, title, powers);
864 break;
865
866 case OpenMetaverse.GroupRoleUpdate.NoUpdate:
867 default:
868 // No Op
869 break;
870
871 }
872
873 // TODO: This update really should send out updates for everyone in the role that just got changed.
874 SendAgentGroupDataUpdate(remoteClient, GetRequestingAgentID(remoteClient));
875 }
876
877 public void GroupRoleChanges(IClientAPI remoteClient, UUID groupID, UUID roleID, UUID memberID, uint changes)
878 {
879 if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
880 // Todo: Security check
881
882 switch (changes)
883 {
884 case 0:
885 // Add
886 m_groupData.AddAgentToGroupRole(GetRequestingAgentIDStr(remoteClient), memberID.ToString(), groupID, roleID);
887
888 break;
889 case 1:
890 // Remove
891 m_groupData.RemoveAgentFromGroupRole(GetRequestingAgentIDStr(remoteClient), memberID.ToString(), groupID, roleID);
892
893 break;
894 default:
895 m_log.ErrorFormat("[Groups]: {0} does not understand changes == {1}", System.Reflection.MethodBase.GetCurrentMethod().Name, changes);
896 break;
897 }
898
899 // TODO: This update really should send out updates for everyone in the role that just got changed.
900 SendAgentGroupDataUpdate(remoteClient, GetRequestingAgentID(remoteClient));
901 }
902
903 public void GroupNoticeRequest(IClientAPI remoteClient, UUID groupNoticeID)
904 {
905 if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called for notice {1}", System.Reflection.MethodBase.GetCurrentMethod().Name, groupNoticeID);
906
907 //GroupRecord groupInfo = m_groupData.GetGroupRecord(GetRequestingAgentID(remoteClient), data.GroupID, null);
908
909 GridInstantMessage msg = CreateGroupNoticeIM(remoteClient.AgentId, groupNoticeID, (byte)InstantMessageDialog.GroupNoticeRequested);
910 //GridInstantMessage msg = new GridInstantMessage();
911 //msg.imSessionID = UUID.Zero.Guid;
912 //msg.fromAgentID = data.GroupID.Guid;
913 //msg.toAgentID = GetRequestingAgentID(remoteClient).Guid;
914 //msg.timestamp = (uint)Util.UnixTimeSinceEpoch();
915 //msg.fromAgentName = "Group Notice : " + groupInfo == null ? "Unknown" : groupInfo.GroupName;
916 //msg.message = data.noticeData.Subject + "|" + data.Message;
917 //msg.dialog = (byte)OpenMetaverse.InstantMessageDialog.GroupNoticeRequested;
918 //msg.fromGroup = true;
919 //msg.offline = (byte)0;
920 //msg.ParentEstateID = 0;
921 //msg.Position = Vector3.Zero;
922 //msg.RegionID = UUID.Zero.Guid;
923 //msg.binaryBucket = data.BinaryBucket;
924
925 OutgoingInstantMessage(msg, GetRequestingAgentID(remoteClient));
926 }
927
928 public GridInstantMessage CreateGroupNoticeIM(UUID agentID, UUID groupNoticeID, byte dialog)
929 {
930 if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
931
932 GridInstantMessage msg = new GridInstantMessage();
933 byte[] bucket;
934
935 msg.imSessionID = groupNoticeID.Guid;
936 msg.toAgentID = agentID.Guid;
937 msg.dialog = dialog;
938 // msg.dialog = (byte)OpenMetaverse.InstantMessageDialog.GroupNotice;
939 msg.fromGroup = true;
940 msg.offline = (byte)0;
941 msg.ParentEstateID = 0;
942 msg.Position = Vector3.Zero;
943 msg.RegionID = UUID.Zero.Guid;
944
945 GroupNoticeInfo info = m_groupData.GetGroupNotice(agentID.ToString(), groupNoticeID);
946 if (info != null)
947 {
948 msg.fromAgentID = info.GroupID.Guid;
949 msg.timestamp = info.noticeData.Timestamp;
950 msg.fromAgentName = info.noticeData.FromName;
951 msg.message = info.noticeData.Subject + "|" + info.Message;
952 if (info.noticeData.HasAttachment)
953 {
954 byte[] name = System.Text.Encoding.UTF8.GetBytes(info.noticeData.AttachmentName);
955 bucket = new byte[19 + name.Length];
956 bucket[0] = 1; // has attachment?
957 bucket[1] = info.noticeData.AttachmentType; // attachment type
958 name.CopyTo(bucket, 18);
959 }
960 else
961 {
962 bucket = new byte[19];
963 bucket[0] = 0; // Has att?
964 bucket[1] = 0; // type
965 bucket[18] = 0; // null terminated
966 }
967
968 info.GroupID.ToBytes(bucket, 2);
969 msg.binaryBucket = bucket;
970 }
971 else
972 {
973 m_log.DebugFormat("[Groups]: Group Notice {0} not found, composing empty message.", groupNoticeID);
974 msg.fromAgentID = UUID.Zero.Guid;
975 msg.timestamp = (uint)Util.UnixTimeSinceEpoch(); ;
976 msg.fromAgentName = string.Empty;
977 msg.message = string.Empty;
978 msg.binaryBucket = new byte[0];
979 }
980
981 return msg;
982 }
983
984 public void SendAgentGroupDataUpdate(IClientAPI remoteClient)
985 {
986 if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
987
988 // Send agent information about his groups
989 SendAgentGroupDataUpdate(remoteClient, GetRequestingAgentID(remoteClient));
990 }
991
992 public void JoinGroupRequest(IClientAPI remoteClient, UUID groupID)
993 {
994 if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
995
996 string reason = string.Empty;
997 // Should check to see if OpenEnrollment, or if there's an outstanding invitation
998 if (m_groupData.AddAgentToGroup(GetRequestingAgentIDStr(remoteClient), GetRequestingAgentIDStr(remoteClient), groupID, UUID.Zero, string.Empty, out reason))
999 {
1000
1001 remoteClient.SendJoinGroupReply(groupID, true);
1002
1003 // Should this send updates to everyone in the group?
1004 SendAgentGroupDataUpdate(remoteClient, GetRequestingAgentID(remoteClient));
1005 }
1006 else
1007 remoteClient.SendJoinGroupReply(groupID, false);
1008 }
1009
1010 public void LeaveGroupRequest(IClientAPI remoteClient, UUID groupID)
1011 {
1012 if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
1013
1014 m_groupData.RemoveAgentFromGroup(GetRequestingAgentIDStr(remoteClient), GetRequestingAgentIDStr(remoteClient), groupID);
1015
1016 remoteClient.SendLeaveGroupReply(groupID, true);
1017
1018 remoteClient.SendAgentDropGroup(groupID);
1019
1020 // SL sends out notifcations to the group messaging session that the person has left
1021 // Should this also update everyone who is in the group?
1022 SendAgentGroupDataUpdate(remoteClient, GetRequestingAgentID(remoteClient));
1023 }
1024
1025 public void EjectGroupMemberRequest(IClientAPI remoteClient, UUID groupID, UUID ejecteeID)
1026 {
1027 EjectGroupMember(remoteClient, GetRequestingAgentID(remoteClient), groupID, ejecteeID);
1028 }
1029
1030 public void EjectGroupMember(IClientAPI remoteClient, UUID agentID, UUID groupID, UUID ejecteeID)
1031 {
1032 if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
1033
1034 // Todo: Security check?
1035 m_groupData.RemoveAgentFromGroup(agentID.ToString(), ejecteeID.ToString(), groupID);
1036
1037 string agentName;
1038 RegionInfo regionInfo;
1039
1040 // remoteClient provided or just agentID?
1041 if (remoteClient != null)
1042 {
1043 agentName = remoteClient.Name;
1044 regionInfo = remoteClient.Scene.RegionInfo;
1045 remoteClient.SendEjectGroupMemberReply(agentID, groupID, true);
1046 }
1047 else
1048 {
1049 IClientAPI client = GetActiveClient(agentID);
1050
1051 if (client != null)
1052 {
1053 agentName = client.Name;
1054 regionInfo = client.Scene.RegionInfo;
1055 client.SendEjectGroupMemberReply(agentID, groupID, true);
1056 }
1057 else
1058 {
1059 regionInfo = m_sceneList[0].RegionInfo;
1060 UserAccount acc = m_sceneList[0].UserAccountService.GetUserAccount(regionInfo.ScopeID, agentID);
1061
1062 if (acc != null)
1063 {
1064 agentName = acc.FirstName + " " + acc.LastName;
1065 }
1066 else
1067 {
1068 agentName = "Unknown member";
1069 }
1070 }
1071 }
1072
1073 GroupRecord groupInfo = m_groupData.GetGroupRecord(agentID.ToString(), groupID, null);
1074
1075 UserAccount account = m_sceneList[0].UserAccountService.GetUserAccount(regionInfo.ScopeID, ejecteeID);
1076 if ((groupInfo == null) || (account == null))
1077 {
1078 return;
1079 }
1080
1081 // Send Message to Ejectee
1082 GridInstantMessage msg = new GridInstantMessage();
1083
1084 msg.imSessionID = UUID.Zero.Guid;
1085 msg.fromAgentID = agentID.Guid;
1086 // msg.fromAgentID = info.GroupID;
1087 msg.toAgentID = ejecteeID.Guid;
1088 //msg.timestamp = (uint)Util.UnixTimeSinceEpoch();
1089 msg.timestamp = 0;
1090 msg.fromAgentName = agentName;
1091 msg.message = string.Format("You have been ejected from '{1}' by {0}.", agentName, groupInfo.GroupName);
1092 msg.dialog = (byte)OpenMetaverse.InstantMessageDialog.MessageFromAgent;
1093 msg.fromGroup = false;
1094 msg.offline = (byte)0;
1095 msg.ParentEstateID = 0;
1096 msg.Position = Vector3.Zero;
1097 msg.RegionID = regionInfo.RegionID.Guid;
1098 msg.binaryBucket = new byte[0];
1099 OutgoingInstantMessage(msg, ejecteeID);
1100
1101 // Message to ejector
1102 // Interop, received special 210 code for ejecting a group member
1103 // this only works within the comms servers domain, and won't work hypergrid
1104 // TODO:FIXME: Use a presense server of some kind to find out where the
1105 // client actually is, and try contacting that region directly to notify them,
1106 // or provide the notification via xmlrpc update queue
1107
1108 msg = new GridInstantMessage();
1109 msg.imSessionID = UUID.Zero.Guid;
1110 msg.fromAgentID = agentID.Guid;
1111 msg.toAgentID = agentID.Guid;
1112 msg.timestamp = 0;
1113 msg.fromAgentName = agentName;
1114 if (account != null)
1115 {
1116 msg.message = string.Format("{2} has been ejected from '{1}' by {0}.", agentName, groupInfo.GroupName, account.FirstName + " " + account.LastName);
1117 }
1118 else
1119 {
1120 msg.message = string.Format("{2} has been ejected from '{1}' by {0}.", agentName, groupInfo.GroupName, "Unknown member");
1121 }
1122 msg.dialog = (byte)210; //interop
1123 msg.fromGroup = false;
1124 msg.offline = (byte)0;
1125 msg.ParentEstateID = 0;
1126 msg.Position = Vector3.Zero;
1127 msg.RegionID = regionInfo.RegionID.Guid;
1128 msg.binaryBucket = new byte[0];
1129 OutgoingInstantMessage(msg, agentID);
1130
1131
1132 // SL sends out messages to everyone in the group
1133 // Who all should receive updates and what should they be updated with?
1134 UpdateAllClientsWithGroupInfo(ejecteeID);
1135 }
1136
1137 public void InviteGroupRequest(IClientAPI remoteClient, UUID groupID, UUID invitedAgentID, UUID roleID)
1138 {
1139 InviteGroup(remoteClient, GetRequestingAgentID(remoteClient), groupID, invitedAgentID, roleID);
1140 }
1141
1142 public void InviteGroup(IClientAPI remoteClient, UUID agentID, UUID groupID, UUID invitedAgentID, UUID roleID)
1143 {
1144 if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
1145
1146 string agentName = m_UserManagement.GetUserName(agentID);
1147 RegionInfo regionInfo = m_sceneList[0].RegionInfo;
1148
1149 GroupRecord group = m_groupData.GetGroupRecord(agentID.ToString(), groupID, null);
1150 if (group == null)
1151 {
1152 m_log.DebugFormat("[Groups]: No such group {0}", groupID);
1153 return;
1154 }
1155
1156 // Todo: Security check, probably also want to send some kind of notification
1157 UUID InviteID = UUID.Random();
1158
1159 if (m_groupData.AddAgentToGroupInvite(agentID.ToString(), InviteID, groupID, roleID, invitedAgentID.ToString()))
1160 {
1161 if (m_msgTransferModule != null)
1162 {
1163 Guid inviteUUID = InviteID.Guid;
1164
1165 GridInstantMessage msg = new GridInstantMessage();
1166
1167 msg.imSessionID = inviteUUID;
1168
1169 // msg.fromAgentID = agentID.Guid;
1170 msg.fromAgentID = groupID.Guid;
1171 msg.toAgentID = invitedAgentID.Guid;
1172 //msg.timestamp = (uint)Util.UnixTimeSinceEpoch();
1173 msg.timestamp = 0;
1174 msg.fromAgentName = agentName;
1175 msg.message = string.Format("{0} has invited you to join a group called {1}. There is no cost to join this group.", agentName, group.GroupName);
1176 msg.dialog = (byte)OpenMetaverse.InstantMessageDialog.GroupInvitation;
1177 msg.fromGroup = true;
1178 msg.offline = (byte)0;
1179 msg.ParentEstateID = 0;
1180 msg.Position = Vector3.Zero;
1181 msg.RegionID = regionInfo.RegionID.Guid;
1182 msg.binaryBucket = new byte[20];
1183
1184 OutgoingInstantMessage(msg, invitedAgentID);
1185 }
1186 }
1187 }
1188
1189 #endregion
1190
1191 #region Client/Update Tools
1192
1193 /// <summary>
1194 /// Try to find an active IClientAPI reference for agentID giving preference to root connections
1195 /// </summary>
1196 private IClientAPI GetActiveClient(UUID agentID)
1197 {
1198 IClientAPI child = null;
1199
1200 // Try root avatar first
1201 foreach (Scene scene in m_sceneList)
1202 {
1203 ScenePresence sp = scene.GetScenePresence(agentID);
1204 if (sp != null)
1205 {
1206 if (!sp.IsChildAgent)
1207 {
1208 return sp.ControllingClient;
1209 }
1210 else
1211 {
1212 child = sp.ControllingClient;
1213 }
1214 }
1215 }
1216
1217 // If we didn't find a root, then just return whichever child we found, or null if none
1218 return child;
1219 }
1220
1221 /// <summary>
1222 /// Send 'remoteClient' the group membership 'data' for agent 'dataForAgentID'.
1223 /// </summary>
1224 private void SendGroupMembershipInfoViaCaps(IClientAPI remoteClient, UUID dataForAgentID, GroupMembershipData[] data)
1225 {
1226 if (m_debugEnabled) m_log.InfoFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
1227
1228 OSDArray AgentData = new OSDArray(1);
1229 OSDMap AgentDataMap = new OSDMap(1);
1230 AgentDataMap.Add("AgentID", OSD.FromUUID(dataForAgentID));
1231 AgentData.Add(AgentDataMap);
1232
1233
1234 OSDArray GroupData = new OSDArray(data.Length);
1235 OSDArray NewGroupData = new OSDArray(data.Length);
1236
1237 foreach (GroupMembershipData membership in data)
1238 {
1239 if (GetRequestingAgentID(remoteClient) != dataForAgentID)
1240 {
1241 if (!membership.ListInProfile)
1242 {
1243 // If we're sending group info to remoteclient about another agent,
1244 // filter out groups the other agent doesn't want to share.
1245 continue;
1246 }
1247 }
1248
1249 OSDMap GroupDataMap = new OSDMap(6);
1250 OSDMap NewGroupDataMap = new OSDMap(1);
1251
1252 GroupDataMap.Add("GroupID", OSD.FromUUID(membership.GroupID));
1253 GroupDataMap.Add("GroupPowers", OSD.FromULong(membership.GroupPowers));
1254 GroupDataMap.Add("AcceptNotices", OSD.FromBoolean(membership.AcceptNotices));
1255 GroupDataMap.Add("GroupInsigniaID", OSD.FromUUID(membership.GroupPicture));
1256 GroupDataMap.Add("Contribution", OSD.FromInteger(membership.Contribution));
1257 GroupDataMap.Add("GroupName", OSD.FromString(membership.GroupName));
1258 NewGroupDataMap.Add("ListInProfile", OSD.FromBoolean(membership.ListInProfile));
1259
1260 GroupData.Add(GroupDataMap);
1261 NewGroupData.Add(NewGroupDataMap);
1262 }
1263
1264 OSDMap llDataStruct = new OSDMap(3);
1265 llDataStruct.Add("AgentData", AgentData);
1266 llDataStruct.Add("GroupData", GroupData);
1267 llDataStruct.Add("NewGroupData", NewGroupData);
1268
1269 if (m_debugEnabled)
1270 {
1271 m_log.InfoFormat("[Groups]: {0}", OSDParser.SerializeJsonString(llDataStruct));
1272 }
1273
1274 IEventQueue queue = remoteClient.Scene.RequestModuleInterface<IEventQueue>();
1275
1276 if (queue != null)
1277 {
1278 queue.Enqueue(queue.BuildEvent("AgentGroupDataUpdate", llDataStruct), GetRequestingAgentID(remoteClient));
1279 }
1280
1281 }
1282
1283 private void SendScenePresenceUpdate(UUID AgentID, string Title)
1284 {
1285 if (m_debugEnabled) m_log.DebugFormat("[Groups]: Updating scene title for {0} with title: {1}", AgentID, Title);
1286
1287 ScenePresence presence = null;
1288
1289 foreach (Scene scene in m_sceneList)
1290 {
1291 presence = scene.GetScenePresence(AgentID);
1292 if (presence != null)
1293 {
1294 if (presence.Grouptitle != Title)
1295 {
1296 presence.Grouptitle = Title;
1297
1298 if (! presence.IsChildAgent)
1299 presence.SendAvatarDataToAllAgents();
1300 }
1301 }
1302 }
1303 }
1304
1305 /// <summary>
1306 /// Send updates to all clients who might be interested in groups data for dataForClientID
1307 /// </summary>
1308 private void UpdateAllClientsWithGroupInfo(UUID dataForClientID)
1309 {
1310 if (m_debugEnabled) m_log.InfoFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
1311
1312 // TODO: Probably isn't nessesary to update every client in every scene.
1313 // Need to examine client updates and do only what's nessesary.
1314 lock (m_sceneList)
1315 {
1316 foreach (Scene scene in m_sceneList)
1317 {
1318 scene.ForEachClient(delegate(IClientAPI client) { SendAgentGroupDataUpdate(client, dataForClientID); });
1319 }
1320 }
1321 }
1322
1323 /// <summary>
1324 /// Update remoteClient with group information about dataForAgentID
1325 /// </summary>
1326 private void SendAgentGroupDataUpdate(IClientAPI remoteClient, UUID dataForAgentID)
1327 {
1328 if (m_debugEnabled) m_log.InfoFormat("[Groups]: {0} called for {1}", System.Reflection.MethodBase.GetCurrentMethod().Name, remoteClient.Name);
1329
1330 // TODO: All the client update functions need to be reexamined because most do too much and send too much stuff
1331
1332 OnAgentDataUpdateRequest(remoteClient, dataForAgentID, UUID.Zero);
1333
1334 // Need to send a group membership update to the client
1335 // UDP version doesn't seem to behave nicely. But we're going to send it out here
1336 // with an empty group membership to hopefully remove groups being displayed due
1337 // to the core Groups Stub
1338 //remoteClient.SendGroupMembership(new GroupMembershipData[0]);
1339
1340 GroupMembershipData[] membershipArray = GetProfileListedGroupMemberships(remoteClient, dataForAgentID);
1341 SendGroupMembershipInfoViaCaps(remoteClient, dataForAgentID, membershipArray);
1342 //remoteClient.SendAvatarGroupsReply(dataForAgentID, membershipArray);
1343 if (remoteClient.AgentId == dataForAgentID)
1344 remoteClient.RefreshGroupMembership();
1345 }
1346
1347 /// <summary>
1348 /// Get a list of groups memberships for the agent that are marked "ListInProfile"
1349 /// (unless that agent has a godLike aspect, in which case get all groups)
1350 /// </summary>
1351 /// <param name="dataForAgentID"></param>
1352 /// <returns></returns>
1353 private GroupMembershipData[] GetProfileListedGroupMemberships(IClientAPI requestingClient, UUID dataForAgentID)
1354 {
1355 List<GroupMembershipData> membershipData = m_groupData.GetAgentGroupMemberships(requestingClient.AgentId.ToString(), dataForAgentID.ToString());
1356 GroupMembershipData[] membershipArray;
1357
1358 // cScene and property accessor 'isGod' are in support of the opertions to bypass 'hidden' group attributes for
1359 // those with a GodLike aspect.
1360 Scene cScene = (Scene)requestingClient.Scene;
1361 bool isGod = cScene.Permissions.IsGod(requestingClient.AgentId);
1362
1363 if (isGod)
1364 {
1365 membershipArray = membershipData.ToArray();
1366 }
1367 else
1368 {
1369 if (requestingClient.AgentId != dataForAgentID)
1370 {
1371 Predicate<GroupMembershipData> showInProfile = delegate(GroupMembershipData membership)
1372 {
1373 return membership.ListInProfile;
1374 };
1375
1376 membershipArray = membershipData.FindAll(showInProfile).ToArray();
1377 }
1378 else
1379 {
1380 membershipArray = membershipData.ToArray();
1381 }
1382 }
1383
1384 if (m_debugEnabled)
1385 {
1386 m_log.InfoFormat("[Groups]: Get group membership information for {0} requested by {1}", dataForAgentID, requestingClient.AgentId);
1387 foreach (GroupMembershipData membership in membershipArray)
1388 {
1389 m_log.InfoFormat("[Groups]: {0} :: {1} - {2} - {3}", dataForAgentID, membership.GroupName, membership.GroupTitle, membership.GroupPowers);
1390 }
1391 }
1392
1393 return membershipArray;
1394 }
1395
1396
1397 private void SendAgentDataUpdate(IClientAPI remoteClient, UUID dataForAgentID, UUID activeGroupID, string activeGroupName, ulong activeGroupPowers, string activeGroupTitle)
1398 {
1399 if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
1400
1401 // TODO: All the client update functions need to be reexamined because most do too much and send too much stuff
1402 UserAccount account = m_sceneList[0].UserAccountService.GetUserAccount(remoteClient.Scene.RegionInfo.ScopeID, dataForAgentID);
1403 string firstname, lastname;
1404 if (account != null)
1405 {
1406 firstname = account.FirstName;
1407 lastname = account.LastName;
1408 }
1409 else
1410 {
1411 firstname = "Unknown";
1412 lastname = "Unknown";
1413 }
1414
1415 remoteClient.SendAgentDataUpdate(dataForAgentID, activeGroupID, firstname,
1416 lastname, activeGroupPowers, activeGroupName,
1417 activeGroupTitle);
1418 }
1419
1420 #endregion
1421
1422 #region IM Backed Processes
1423
1424 private void OutgoingInstantMessage(GridInstantMessage msg, UUID msgTo)
1425 {
1426 if (m_debugEnabled) m_log.InfoFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
1427
1428 IClientAPI localClient = GetActiveClient(msgTo);
1429 if (localClient != null)
1430 {
1431 if (m_debugEnabled) m_log.InfoFormat("[Groups]: MsgTo ({0}) is local, delivering directly", localClient.Name);
1432 localClient.SendInstantMessage(msg);
1433 }
1434 else if (m_msgTransferModule != null)
1435 {
1436 if (m_debugEnabled) m_log.InfoFormat("[Groups]: MsgTo ({0}) is not local, delivering via TransferModule", msgTo);
1437 m_msgTransferModule.SendInstantMessage(msg, delegate(bool success) { if (m_debugEnabled) m_log.DebugFormat("[Groups]: Message Sent: {0}", success?"Succeeded":"Failed"); });
1438 }
1439 }
1440
1441 public void NotifyChange(UUID groupID)
1442 {
1443 // Notify all group members of a chnge in group roles and/or
1444 // permissions
1445 //
1446 }
1447
1448 #endregion
1449
1450 private string GetRequestingAgentIDStr(IClientAPI client)
1451 {
1452 return GetRequestingAgentID(client).ToString();
1453 }
1454
1455 private UUID GetRequestingAgentID(IClientAPI client)
1456 {
1457 UUID requestingAgentID = UUID.Zero;
1458 if (client != null)
1459 {
1460 requestingAgentID = client.AgentId;
1461 }
1462 return requestingAgentID;
1463 }
1464
1465 }
1466
1467}
diff --git a/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnector.cs b/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnector.cs
new file mode 100644
index 0000000..59fec6f
--- /dev/null
+++ b/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnector.cs
@@ -0,0 +1,289 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Linq;
31using System.Reflection;
32using System.Text;
33
34using OpenSim.Framework;
35using OpenSim.Server.Base;
36
37using OpenMetaverse;
38using log4net;
39
40namespace OpenSim.Groups
41{
42 public class GroupsServiceHGConnector
43 {
44 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
45
46 private string m_ServerURI;
47 private object m_Lock = new object();
48
49 public GroupsServiceHGConnector(string url)
50 {
51 m_ServerURI = url;
52 if (!m_ServerURI.EndsWith("/"))
53 m_ServerURI += "/";
54
55 m_log.DebugFormat("[Groups.HGConnector]: Groups server at {0}", m_ServerURI);
56 }
57
58 public bool CreateProxy(string RequestingAgentID, string AgentID, string accessToken, UUID groupID, string url, string name, out string reason)
59 {
60 reason = string.Empty;
61
62 Dictionary<string, object> sendData = new Dictionary<string,object>();
63 sendData["RequestingAgentID"] = RequestingAgentID;
64 sendData["AgentID"] = AgentID.ToString();
65 sendData["AccessToken"] = accessToken;
66 sendData["GroupID"] = groupID.ToString();
67 sendData["Location"] = url;
68 sendData["Name"] = name;
69 Dictionary<string, object> ret = MakeRequest("POSTGROUP", sendData);
70
71 if (ret == null)
72 return false;
73
74 if (!ret.ContainsKey("RESULT"))
75 return false;
76
77 if (ret["RESULT"].ToString().ToLower() != "true")
78 {
79 reason = ret["REASON"].ToString();
80 return false;
81 }
82
83 return true;
84
85 }
86
87 public void RemoveAgentFromGroup(string AgentID, UUID GroupID, string token)
88 {
89 Dictionary<string, object> sendData = new Dictionary<string, object>();
90 sendData["AgentID"] = AgentID;
91 sendData["GroupID"] = GroupID.ToString();
92 sendData["AccessToken"] = GroupsDataUtils.Sanitize(token);
93 MakeRequest("REMOVEAGENTFROMGROUP", sendData);
94 }
95
96 public ExtendedGroupRecord GetGroupRecord(string RequestingAgentID, UUID GroupID, string GroupName, string token)
97 {
98 if (GroupID == UUID.Zero && (GroupName == null || (GroupName != null && GroupName == string.Empty)))
99 return null;
100
101 Dictionary<string, object> sendData = new Dictionary<string, object>();
102 if (GroupID != UUID.Zero)
103 sendData["GroupID"] = GroupID.ToString();
104 if (GroupName != null && GroupName != string.Empty)
105 sendData["Name"] = GroupsDataUtils.Sanitize(GroupName);
106
107 sendData["RequestingAgentID"] = RequestingAgentID;
108 sendData["AccessToken"] = GroupsDataUtils.Sanitize(token);
109
110 Dictionary<string, object> ret = MakeRequest("GETGROUP", sendData);
111
112 if (ret == null)
113 return null;
114
115 if (!ret.ContainsKey("RESULT"))
116 return null;
117
118 if (ret["RESULT"].ToString() == "NULL")
119 return null;
120
121 return GroupsDataUtils.GroupRecord((Dictionary<string, object>)ret["RESULT"]);
122 }
123
124 public List<ExtendedGroupMembersData> GetGroupMembers(string RequestingAgentID, UUID GroupID, string token)
125 {
126 List<ExtendedGroupMembersData> members = new List<ExtendedGroupMembersData>();
127
128 Dictionary<string, object> sendData = new Dictionary<string, object>();
129 sendData["GroupID"] = GroupID.ToString();
130 sendData["RequestingAgentID"] = RequestingAgentID;
131 sendData["AccessToken"] = GroupsDataUtils.Sanitize(token);
132 Dictionary<string, object> ret = MakeRequest("GETGROUPMEMBERS", sendData);
133
134 if (ret == null)
135 return members;
136
137 if (!ret.ContainsKey("RESULT"))
138 return members;
139
140 if (ret["RESULT"].ToString() == "NULL")
141 return members;
142 foreach (object v in ((Dictionary<string, object>)ret["RESULT"]).Values)
143 {
144 ExtendedGroupMembersData m = GroupsDataUtils.GroupMembersData((Dictionary<string, object>)v);
145 members.Add(m);
146 }
147
148 return members;
149 }
150
151 public List<GroupRolesData> GetGroupRoles(string RequestingAgentID, UUID GroupID, string token)
152 {
153 List<GroupRolesData> roles = new List<GroupRolesData>();
154
155 Dictionary<string, object> sendData = new Dictionary<string, object>();
156 sendData["GroupID"] = GroupID.ToString();
157 sendData["RequestingAgentID"] = RequestingAgentID;
158 sendData["AccessToken"] = GroupsDataUtils.Sanitize(token);
159 Dictionary<string, object> ret = MakeRequest("GETGROUPROLES", sendData);
160
161 if (ret == null)
162 return roles;
163
164 if (!ret.ContainsKey("RESULT"))
165 return roles;
166
167 if (ret["RESULT"].ToString() == "NULL")
168 return roles;
169 foreach (object v in ((Dictionary<string, object>)ret["RESULT"]).Values)
170 {
171 GroupRolesData m = GroupsDataUtils.GroupRolesData((Dictionary<string, object>)v);
172 roles.Add(m);
173 }
174
175 return roles;
176 }
177
178 public List<ExtendedGroupRoleMembersData> GetGroupRoleMembers(string RequestingAgentID, UUID GroupID, string token)
179 {
180 List<ExtendedGroupRoleMembersData> rmembers = new List<ExtendedGroupRoleMembersData>();
181
182 Dictionary<string, object> sendData = new Dictionary<string, object>();
183 sendData["GroupID"] = GroupID.ToString();
184 sendData["RequestingAgentID"] = RequestingAgentID;
185 sendData["AccessToken"] = GroupsDataUtils.Sanitize(token);
186 Dictionary<string, object> ret = MakeRequest("GETROLEMEMBERS", sendData);
187
188 if (ret == null)
189 return rmembers;
190
191 if (!ret.ContainsKey("RESULT"))
192 return rmembers;
193
194 if (ret["RESULT"].ToString() == "NULL")
195 return rmembers;
196
197 foreach (object v in ((Dictionary<string, object>)ret["RESULT"]).Values)
198 {
199 ExtendedGroupRoleMembersData m = GroupsDataUtils.GroupRoleMembersData((Dictionary<string, object>)v);
200 rmembers.Add(m);
201 }
202
203 return rmembers;
204 }
205
206 public bool AddNotice(string RequestingAgentID, UUID groupID, UUID noticeID, string fromName, string subject, string message,
207 bool hasAttachment, byte attType, string attName, UUID attItemID, string attOwnerID)
208 {
209 Dictionary<string, object> sendData = new Dictionary<string, object>();
210 sendData["GroupID"] = groupID.ToString();
211 sendData["NoticeID"] = noticeID.ToString();
212 sendData["FromName"] = GroupsDataUtils.Sanitize(fromName);
213 sendData["Subject"] = GroupsDataUtils.Sanitize(subject);
214 sendData["Message"] = GroupsDataUtils.Sanitize(message);
215 sendData["HasAttachment"] = hasAttachment.ToString();
216 if (hasAttachment)
217 {
218 sendData["AttachmentType"] = attType.ToString();
219 sendData["AttachmentName"] = attName.ToString();
220 sendData["AttachmentItemID"] = attItemID.ToString();
221 sendData["AttachmentOwnerID"] = attOwnerID;
222 }
223 sendData["RequestingAgentID"] = RequestingAgentID;
224
225 Dictionary<string, object> ret = MakeRequest("ADDNOTICE", sendData);
226
227 if (ret == null)
228 return false;
229
230 if (!ret.ContainsKey("RESULT"))
231 return false;
232
233 if (ret["RESULT"].ToString().ToLower() != "true")
234 return false;
235
236 return true;
237 }
238
239 public bool VerifyNotice(UUID noticeID, UUID groupID)
240 {
241 Dictionary<string, object> sendData = new Dictionary<string, object>();
242 sendData["NoticeID"] = noticeID.ToString();
243 sendData["GroupID"] = groupID.ToString();
244 Dictionary<string, object> ret = MakeRequest("VERIFYNOTICE", sendData);
245
246 if (ret == null)
247 return false;
248
249 if (!ret.ContainsKey("RESULT"))
250 return false;
251
252 if (ret["RESULT"].ToString().ToLower() != "true")
253 return false;
254
255 return true;
256 }
257
258 //
259 //
260 //
261 //
262 //
263
264 #region Make Request
265
266 private Dictionary<string, object> MakeRequest(string method, Dictionary<string, object> sendData)
267 {
268 sendData["METHOD"] = method;
269
270 string reply = string.Empty;
271 lock (m_Lock)
272 reply = SynchronousRestFormsRequester.MakeRequest("POST",
273 m_ServerURI + "hg-groups",
274 ServerUtils.BuildQueryString(sendData));
275
276 //m_log.DebugFormat("[XXX]: reply was {0}", reply);
277
278 if (reply == string.Empty || reply == null)
279 return null;
280
281 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(
282 reply);
283
284 return replyData;
285 }
286 #endregion
287
288 }
289}
diff --git a/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs b/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs
new file mode 100644
index 0000000..f670272
--- /dev/null
+++ b/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs
@@ -0,0 +1,717 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Linq;
31using System.Reflection;
32using System.Text;
33
34using OpenSim.Framework;
35using OpenSim.Framework.Servers;
36using OpenSim.Region.Framework.Scenes;
37using OpenSim.Region.Framework.Interfaces;
38using OpenSim.Services.Interfaces;
39
40using OpenMetaverse;
41using Mono.Addins;
42using log4net;
43using Nini.Config;
44
45namespace OpenSim.Groups
46{
47 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GroupsServiceHGConnectorModule")]
48 public class GroupsServiceHGConnectorModule : ISharedRegionModule, IGroupsServicesConnector
49 {
50 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
51
52 private bool m_Enabled = false;
53 private IGroupsServicesConnector m_LocalGroupsConnector;
54 private string m_LocalGroupsServiceLocation;
55 private IUserManagement m_UserManagement;
56 private IOfflineIMService m_OfflineIM;
57 private IMessageTransferModule m_Messaging;
58 private List<Scene> m_Scenes;
59 private ForeignImporter m_ForeignImporter;
60 private string m_ServiceLocation;
61 private IConfigSource m_Config;
62
63 private Dictionary<string, GroupsServiceHGConnector> m_NetworkConnectors = new Dictionary<string, GroupsServiceHGConnector>();
64 private RemoteConnectorCacheWrapper m_CacheWrapper; // for caching info of external group services
65
66 #region ISharedRegionModule
67
68 public void Initialise(IConfigSource config)
69 {
70 IConfig groupsConfig = config.Configs["Groups"];
71 if (groupsConfig == null)
72 return;
73
74 if ((groupsConfig.GetBoolean("Enabled", false) == false)
75 || (groupsConfig.GetString("ServicesConnectorModule", string.Empty) != Name))
76 {
77 return;
78 }
79
80 m_Config = config;
81 m_ServiceLocation = groupsConfig.GetString("LocalService", "local"); // local or remote
82 m_LocalGroupsServiceLocation = groupsConfig.GetString("GroupsExternalURI", "http://127.0.0.1");
83 m_Scenes = new List<Scene>();
84
85 m_Enabled = true;
86
87 m_log.DebugFormat("[Groups]: Initializing {0} with LocalService {1}", this.Name, m_ServiceLocation);
88 }
89
90 public string Name
91 {
92 get { return "Groups HG Service Connector"; }
93 }
94
95 public Type ReplaceableInterface
96 {
97 get { return null; }
98 }
99
100 public void AddRegion(Scene scene)
101 {
102 if (!m_Enabled)
103 return;
104
105 m_log.DebugFormat("[Groups]: Registering {0} with {1}", this.Name, scene.RegionInfo.RegionName);
106 scene.RegisterModuleInterface<IGroupsServicesConnector>(this);
107 m_Scenes.Add(scene);
108
109 scene.EventManager.OnNewClient += OnNewClient;
110 }
111
112 public void RemoveRegion(Scene scene)
113 {
114 if (!m_Enabled)
115 return;
116
117 scene.UnregisterModuleInterface<IGroupsServicesConnector>(this);
118 m_Scenes.Remove(scene);
119 }
120
121 public void RegionLoaded(Scene scene)
122 {
123 if (!m_Enabled)
124 return;
125
126 if (m_UserManagement == null)
127 {
128 m_UserManagement = scene.RequestModuleInterface<IUserManagement>();
129 m_OfflineIM = scene.RequestModuleInterface<IOfflineIMService>();
130 m_Messaging = scene.RequestModuleInterface<IMessageTransferModule>();
131 m_ForeignImporter = new ForeignImporter(m_UserManagement);
132
133 if (m_ServiceLocation.Equals("local"))
134 {
135 m_LocalGroupsConnector = new GroupsServiceLocalConnectorModule(m_Config, m_UserManagement);
136 // Also, if local, create the endpoint for the HGGroupsService
137 new HGGroupsServiceRobustConnector(m_Config, MainServer.Instance, string.Empty,
138 scene.RequestModuleInterface<IOfflineIMService>(), scene.RequestModuleInterface<IUserAccountService>());
139
140 }
141 else
142 m_LocalGroupsConnector = new GroupsServiceRemoteConnectorModule(m_Config, m_UserManagement);
143
144 m_CacheWrapper = new RemoteConnectorCacheWrapper(m_UserManagement);
145 }
146
147 }
148
149 public void PostInitialise()
150 {
151 }
152
153 public void Close()
154 {
155 }
156
157 #endregion
158
159 private void OnNewClient(IClientAPI client)
160 {
161 client.OnCompleteMovementToRegion += OnCompleteMovementToRegion;
162 }
163
164 void OnCompleteMovementToRegion(IClientAPI client, bool arg2)
165 {
166 object sp = null;
167 if (client.Scene.TryGetScenePresence(client.AgentId, out sp))
168 {
169 if (sp is ScenePresence && ((ScenePresence)sp).PresenceType != PresenceType.Npc)
170 {
171 AgentCircuitData aCircuit = ((ScenePresence)sp).Scene.AuthenticateHandler.GetAgentCircuitData(client.AgentId);
172 if (aCircuit != null && (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0 &&
173 m_OfflineIM != null && m_Messaging != null)
174 {
175 List<GridInstantMessage> ims = m_OfflineIM.GetMessages(aCircuit.AgentID);
176 if (ims != null && ims.Count > 0)
177 foreach (GridInstantMessage im in ims)
178 m_Messaging.SendInstantMessage(im, delegate(bool success) { });
179 }
180 }
181 }
182 }
183
184 #region IGroupsServicesConnector
185
186 public UUID CreateGroup(UUID RequestingAgentID, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment,
187 bool allowPublish, bool maturePublish, UUID founderID, out string reason)
188 {
189 m_log.DebugFormat("[Groups]: Creating group {0}", name);
190 reason = string.Empty;
191 if (m_UserManagement.IsLocalGridUser(RequestingAgentID))
192 return m_LocalGroupsConnector.CreateGroup(RequestingAgentID, name, charter, showInList, insigniaID,
193 membershipFee, openEnrollment, allowPublish, maturePublish, founderID, out reason);
194 else
195 {
196 reason = "Only local grid users are allowed to create a new group";
197 return UUID.Zero;
198 }
199 }
200
201 public bool UpdateGroup(string RequestingAgentID, UUID groupID, string charter, bool showInList, UUID insigniaID, int membershipFee,
202 bool openEnrollment, bool allowPublish, bool maturePublish, out string reason)
203 {
204 reason = string.Empty;
205 string url = string.Empty;
206 string name = string.Empty;
207 if (IsLocal(groupID, out url, out name))
208 return m_LocalGroupsConnector.UpdateGroup(AgentUUI(RequestingAgentID), groupID, charter, showInList, insigniaID, membershipFee,
209 openEnrollment, allowPublish, maturePublish, out reason);
210 else
211 {
212 reason = "Changes to remote group not allowed. Please go to the group's original world.";
213 return false;
214 }
215 }
216
217 public ExtendedGroupRecord GetGroupRecord(string RequestingAgentID, UUID GroupID, string GroupName)
218 {
219 string url = string.Empty;
220 string name = string.Empty;
221 if (IsLocal(GroupID, out url, out name))
222 return m_LocalGroupsConnector.GetGroupRecord(AgentUUI(RequestingAgentID), GroupID, GroupName);
223 else if (url != string.Empty)
224 {
225 ExtendedGroupMembershipData membership = m_LocalGroupsConnector.GetAgentGroupMembership(RequestingAgentID, RequestingAgentID, GroupID);
226 string accessToken = string.Empty;
227 if (membership != null)
228 accessToken = membership.AccessToken;
229 else
230 return null;
231
232 GroupsServiceHGConnector c = GetConnector(url);
233 if (c != null)
234 {
235 ExtendedGroupRecord grec = m_CacheWrapper.GetGroupRecord(RequestingAgentID, GroupID, GroupName, delegate
236 {
237 return c.GetGroupRecord(AgentUUIForOutside(RequestingAgentID), GroupID, GroupName, accessToken);
238 });
239
240 if (grec != null)
241 ImportForeigner(grec.FounderUUI);
242 return grec;
243 }
244 }
245
246 return null;
247 }
248
249 public List<DirGroupsReplyData> FindGroups(string RequestingAgentID, string search)
250 {
251 return m_LocalGroupsConnector.FindGroups(AgentUUI(RequestingAgentID), search);
252 }
253
254 public List<GroupMembersData> GetGroupMembers(string RequestingAgentID, UUID GroupID)
255 {
256 string url = string.Empty, gname = string.Empty;
257 if (IsLocal(GroupID, out url, out gname))
258 return m_LocalGroupsConnector.GetGroupMembers(AgentUUI(RequestingAgentID), GroupID);
259 else if (!string.IsNullOrEmpty(url))
260 {
261 ExtendedGroupMembershipData membership = m_LocalGroupsConnector.GetAgentGroupMembership(RequestingAgentID, RequestingAgentID, GroupID);
262 string accessToken = string.Empty;
263 if (membership != null)
264 accessToken = membership.AccessToken;
265 else
266 return null;
267
268 GroupsServiceHGConnector c = GetConnector(url);
269 if (c != null)
270 {
271 return m_CacheWrapper.GetGroupMembers(RequestingAgentID, GroupID, delegate
272 {
273 return c.GetGroupMembers(AgentUUIForOutside(RequestingAgentID), GroupID, accessToken);
274 });
275
276 }
277 }
278 return new List<GroupMembersData>();
279 }
280
281 public bool AddGroupRole(string RequestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers, out string reason)
282 {
283 reason = string.Empty;
284 string url = string.Empty, gname = string.Empty;
285
286 if (IsLocal(groupID, out url, out gname))
287 return m_LocalGroupsConnector.AddGroupRole(AgentUUI(RequestingAgentID), groupID, roleID, name, description, title, powers, out reason);
288 else
289 {
290 reason = "Operation not allowed outside this group's origin world.";
291 return false;
292 }
293 }
294
295 public bool UpdateGroupRole(string RequestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers)
296 {
297 string url = string.Empty, gname = string.Empty;
298
299 if (IsLocal(groupID, out url, out gname))
300 return m_LocalGroupsConnector.UpdateGroupRole(AgentUUI(RequestingAgentID), groupID, roleID, name, description, title, powers);
301 else
302 {
303 return false;
304 }
305
306 }
307
308 public void RemoveGroupRole(string RequestingAgentID, UUID groupID, UUID roleID)
309 {
310 string url = string.Empty, gname = string.Empty;
311
312 if (IsLocal(groupID, out url, out gname))
313 m_LocalGroupsConnector.RemoveGroupRole(AgentUUI(RequestingAgentID), groupID, roleID);
314 else
315 {
316 return;
317 }
318 }
319
320 public List<GroupRolesData> GetGroupRoles(string RequestingAgentID, UUID groupID)
321 {
322 string url = string.Empty, gname = string.Empty;
323
324 if (IsLocal(groupID, out url, out gname))
325 return m_LocalGroupsConnector.GetGroupRoles(AgentUUI(RequestingAgentID), groupID);
326 else if (!string.IsNullOrEmpty(url))
327 {
328 ExtendedGroupMembershipData membership = m_LocalGroupsConnector.GetAgentGroupMembership(RequestingAgentID, RequestingAgentID, groupID);
329 string accessToken = string.Empty;
330 if (membership != null)
331 accessToken = membership.AccessToken;
332 else
333 return null;
334
335 GroupsServiceHGConnector c = GetConnector(url);
336 if (c != null)
337 {
338 return m_CacheWrapper.GetGroupRoles(RequestingAgentID, groupID, delegate
339 {
340 return c.GetGroupRoles(AgentUUIForOutside(RequestingAgentID), groupID, accessToken);
341 });
342
343 }
344 }
345
346 return new List<GroupRolesData>();
347 }
348
349 public List<GroupRoleMembersData> GetGroupRoleMembers(string RequestingAgentID, UUID groupID)
350 {
351 string url = string.Empty, gname = string.Empty;
352
353 if (IsLocal(groupID, out url, out gname))
354 return m_LocalGroupsConnector.GetGroupRoleMembers(AgentUUI(RequestingAgentID), groupID);
355 else if (!string.IsNullOrEmpty(url))
356 {
357 ExtendedGroupMembershipData membership = m_LocalGroupsConnector.GetAgentGroupMembership(RequestingAgentID, RequestingAgentID, groupID);
358 string accessToken = string.Empty;
359 if (membership != null)
360 accessToken = membership.AccessToken;
361 else
362 return null;
363
364 GroupsServiceHGConnector c = GetConnector(url);
365 if (c != null)
366 {
367 return m_CacheWrapper.GetGroupRoleMembers(RequestingAgentID, groupID, delegate
368 {
369 return c.GetGroupRoleMembers(AgentUUIForOutside(RequestingAgentID), groupID, accessToken);
370 });
371
372 }
373 }
374
375 return new List<GroupRoleMembersData>();
376 }
377
378 public bool AddAgentToGroup(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID, string token, out string reason)
379 {
380 string url = string.Empty;
381 string name = string.Empty;
382 reason = string.Empty;
383
384 UUID uid = new UUID(AgentID);
385 if (IsLocal(GroupID, out url, out name))
386 {
387 if (m_UserManagement.IsLocalGridUser(uid)) // local user
388 {
389 // normal case: local group, local user
390 return m_LocalGroupsConnector.AddAgentToGroup(AgentUUI(RequestingAgentID), AgentUUI(AgentID), GroupID, RoleID, token, out reason);
391 }
392 else // local group, foreign user
393 {
394 // the user is accepting the invitation, or joining, where the group resides
395 token = UUID.Random().ToString();
396 bool success = m_LocalGroupsConnector.AddAgentToGroup(AgentUUI(RequestingAgentID), AgentUUI(AgentID), GroupID, RoleID, token, out reason);
397
398 if (success)
399 {
400 url = m_UserManagement.GetUserServerURL(uid, "GroupsServerURI");
401 if (url == string.Empty)
402 {
403 reason = "User doesn't have a groups server";
404 return false;
405 }
406
407 GroupsServiceHGConnector c = GetConnector(url);
408 if (c != null)
409 return c.CreateProxy(AgentUUI(RequestingAgentID), AgentID, token, GroupID, m_LocalGroupsServiceLocation, name, out reason);
410 }
411 }
412 }
413 else if (m_UserManagement.IsLocalGridUser(uid)) // local user
414 {
415 // foreign group, local user. She's been added already by the HG service.
416 // Let's just check
417 if (m_LocalGroupsConnector.GetAgentGroupMembership(AgentUUI(RequestingAgentID), AgentUUI(AgentID), GroupID) != null)
418 return true;
419 }
420
421 reason = "Operation not allowed outside this group's origin world";
422 return false;
423 }
424
425
426 public void RemoveAgentFromGroup(string RequestingAgentID, string AgentID, UUID GroupID)
427 {
428 string url = string.Empty, name = string.Empty;
429 if (!IsLocal(GroupID, out url, out name) && url != string.Empty)
430 {
431 ExtendedGroupMembershipData membership = m_LocalGroupsConnector.GetAgentGroupMembership(AgentUUI(RequestingAgentID), AgentUUI(AgentID), GroupID);
432 if (membership != null)
433 {
434 GroupsServiceHGConnector c = GetConnector(url);
435 if (c != null)
436 c.RemoveAgentFromGroup(AgentUUIForOutside(AgentID), GroupID, membership.AccessToken);
437 }
438 }
439
440 // remove from local service
441 m_LocalGroupsConnector.RemoveAgentFromGroup(AgentUUI(RequestingAgentID), AgentUUI(AgentID), GroupID);
442 }
443
444 public bool AddAgentToGroupInvite(string RequestingAgentID, UUID inviteID, UUID groupID, UUID roleID, string agentID)
445 {
446 string url = string.Empty, gname = string.Empty;
447
448 if (IsLocal(groupID, out url, out gname))
449 return m_LocalGroupsConnector.AddAgentToGroupInvite(AgentUUI(RequestingAgentID), inviteID, groupID, roleID, AgentUUI(agentID));
450 else
451 return false;
452 }
453
454 public GroupInviteInfo GetAgentToGroupInvite(string RequestingAgentID, UUID inviteID)
455 {
456 return m_LocalGroupsConnector.GetAgentToGroupInvite(AgentUUI(RequestingAgentID), inviteID); ;
457 }
458
459 public void RemoveAgentToGroupInvite(string RequestingAgentID, UUID inviteID)
460 {
461 m_LocalGroupsConnector.RemoveAgentToGroupInvite(AgentUUI(RequestingAgentID), inviteID);
462 }
463
464 public void AddAgentToGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID)
465 {
466 string url = string.Empty, gname = string.Empty;
467
468 if (IsLocal(GroupID, out url, out gname))
469 m_LocalGroupsConnector.AddAgentToGroupRole(AgentUUI(RequestingAgentID), AgentUUI(AgentID), GroupID, RoleID);
470
471 }
472
473 public void RemoveAgentFromGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID)
474 {
475 string url = string.Empty, gname = string.Empty;
476
477 if (IsLocal(GroupID, out url, out gname))
478 m_LocalGroupsConnector.RemoveAgentFromGroupRole(AgentUUI(RequestingAgentID), AgentUUI(AgentID), GroupID, RoleID);
479 }
480
481 public List<GroupRolesData> GetAgentGroupRoles(string RequestingAgentID, string AgentID, UUID GroupID)
482 {
483 string url = string.Empty, gname = string.Empty;
484
485 if (IsLocal(GroupID, out url, out gname))
486 return m_LocalGroupsConnector.GetAgentGroupRoles(AgentUUI(RequestingAgentID), AgentUUI(AgentID), GroupID);
487 else
488 return new List<GroupRolesData>();
489 }
490
491 public void SetAgentActiveGroup(string RequestingAgentID, string AgentID, UUID GroupID)
492 {
493 string url = string.Empty, gname = string.Empty;
494
495 if (IsLocal(GroupID, out url, out gname))
496 m_LocalGroupsConnector.SetAgentActiveGroup(AgentUUI(RequestingAgentID), AgentUUI(AgentID), GroupID);
497 }
498
499 public ExtendedGroupMembershipData GetAgentActiveMembership(string RequestingAgentID, string AgentID)
500 {
501 return m_LocalGroupsConnector.GetAgentActiveMembership(AgentUUI(RequestingAgentID), AgentUUI(AgentID));
502 }
503
504 public void SetAgentActiveGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID)
505 {
506 string url = string.Empty, gname = string.Empty;
507
508 if (IsLocal(GroupID, out url, out gname))
509 m_LocalGroupsConnector.SetAgentActiveGroupRole(AgentUUI(RequestingAgentID), AgentUUI(AgentID), GroupID, RoleID);
510 }
511
512 public void UpdateMembership(string RequestingAgentID, string AgentID, UUID GroupID, bool AcceptNotices, bool ListInProfile)
513 {
514 m_LocalGroupsConnector.UpdateMembership(AgentUUI(RequestingAgentID), AgentUUI(AgentID), GroupID, AcceptNotices, ListInProfile);
515 }
516
517 public ExtendedGroupMembershipData GetAgentGroupMembership(string RequestingAgentID, string AgentID, UUID GroupID)
518 {
519 string url = string.Empty, gname = string.Empty;
520
521 if (IsLocal(GroupID, out url, out gname))
522 return m_LocalGroupsConnector.GetAgentGroupMembership(AgentUUI(RequestingAgentID), AgentUUI(AgentID), GroupID);
523 else
524 return null;
525 }
526
527 public List<GroupMembershipData> GetAgentGroupMemberships(string RequestingAgentID, string AgentID)
528 {
529 return m_LocalGroupsConnector.GetAgentGroupMemberships(AgentUUI(RequestingAgentID), AgentUUI(AgentID));
530 }
531
532 public bool AddGroupNotice(string RequestingAgentID, UUID groupID, UUID noticeID, string fromName, string subject, string message,
533 bool hasAttachment, byte attType, string attName, UUID attItemID, string attOwnerID)
534 {
535 string url = string.Empty, gname = string.Empty;
536
537 if (IsLocal(groupID, out url, out gname))
538 {
539 if (m_LocalGroupsConnector.AddGroupNotice(AgentUUI(RequestingAgentID), groupID, noticeID, fromName, subject, message,
540 hasAttachment, attType, attName, attItemID, AgentUUI(attOwnerID)))
541 {
542 // then send the notice to every grid for which there are members in this group
543 List<GroupMembersData> members = m_LocalGroupsConnector.GetGroupMembers(AgentUUI(RequestingAgentID), groupID);
544 List<string> urls = new List<string>();
545 foreach (GroupMembersData m in members)
546 {
547 UUID userID = UUID.Zero;
548 if (!m_UserManagement.IsLocalGridUser(m.AgentID))
549 {
550 string gURL = m_UserManagement.GetUserServerURL(m.AgentID, "GroupsServerURI");
551 if (!urls.Contains(gURL))
552 urls.Add(gURL);
553 }
554 }
555
556 // so we have the list of urls to send the notice to
557 // this may take a long time...
558 Util.FireAndForget(delegate
559 {
560 foreach (string u in urls)
561 {
562 GroupsServiceHGConnector c = GetConnector(u);
563 if (c != null)
564 {
565 c.AddNotice(AgentUUIForOutside(RequestingAgentID), groupID, noticeID, fromName, subject, message,
566 hasAttachment, attType, attName, attItemID, AgentUUIForOutside(attOwnerID));
567 }
568 }
569 });
570
571 return true;
572 }
573
574 return false;
575 }
576 else
577 return false;
578 }
579
580 public GroupNoticeInfo GetGroupNotice(string RequestingAgentID, UUID noticeID)
581 {
582 GroupNoticeInfo notice = m_LocalGroupsConnector.GetGroupNotice(AgentUUI(RequestingAgentID), noticeID);
583
584 if (notice != null && notice.noticeData.HasAttachment && notice.noticeData.AttachmentOwnerID != null)
585 ImportForeigner(notice.noticeData.AttachmentOwnerID);
586
587 return notice;
588 }
589
590 public List<ExtendedGroupNoticeData> GetGroupNotices(string RequestingAgentID, UUID GroupID)
591 {
592 return m_LocalGroupsConnector.GetGroupNotices(AgentUUI(RequestingAgentID), GroupID);
593 }
594
595 public void ResetAgentGroupChatSessions(string agentID)
596 {
597 }
598
599 public bool hasAgentBeenInvitedToGroupChatSession(string agentID, UUID groupID)
600 {
601 return false;
602 }
603
604 public bool hasAgentDroppedGroupChatSession(string agentID, UUID groupID)
605 {
606 return false;
607 }
608
609 public void AgentDroppedFromGroupChatSession(string agentID, UUID groupID)
610 {
611 }
612
613 public void AgentInvitedToGroupChatSession(string agentID, UUID groupID)
614 {
615 }
616
617 #endregion
618
619 #region hypergrid groups
620
621 private string AgentUUI(string AgentIDStr)
622 {
623 UUID AgentID = UUID.Zero;
624 try
625 {
626 AgentID = new UUID(AgentIDStr);
627 }
628 catch (FormatException)
629 {
630 return AgentID.ToString();
631 }
632
633 if (m_UserManagement.IsLocalGridUser(AgentID))
634 return AgentID.ToString();
635
636 AgentCircuitData agent = null;
637 foreach (Scene scene in m_Scenes)
638 {
639 agent = scene.AuthenticateHandler.GetAgentCircuitData(AgentID);
640 if (agent != null)
641 break;
642 }
643 if (agent == null) // oops
644 return AgentID.ToString();
645
646 return Util.ProduceUserUniversalIdentifier(agent);
647 }
648
649 private string AgentUUIForOutside(string AgentIDStr)
650 {
651 UUID AgentID = UUID.Zero;
652 try
653 {
654 AgentID = new UUID(AgentIDStr);
655 }
656 catch (FormatException)
657 {
658 return AgentID.ToString();
659 }
660
661 AgentCircuitData agent = null;
662 foreach (Scene scene in m_Scenes)
663 {
664 agent = scene.AuthenticateHandler.GetAgentCircuitData(AgentID);
665 if (agent != null)
666 break;
667 }
668 if (agent == null) // oops
669 return AgentID.ToString();
670
671 return Util.ProduceUserUniversalIdentifier(agent);
672 }
673
674 private UUID ImportForeigner(string uID)
675 {
676 UUID userID = UUID.Zero;
677 string url = string.Empty, first = string.Empty, last = string.Empty, tmp = string.Empty;
678 if (Util.ParseUniversalUserIdentifier(uID, out userID, out url, out first, out last, out tmp))
679 m_UserManagement.AddUser(userID, first, last, url);
680
681 return userID;
682 }
683
684 private bool IsLocal(UUID groupID, out string serviceLocation, out string name)
685 {
686 serviceLocation = string.Empty;
687 name = string.Empty;
688 ExtendedGroupRecord group = m_LocalGroupsConnector.GetGroupRecord(UUID.Zero.ToString(), groupID, string.Empty);
689 if (group == null)
690 {
691 //m_log.DebugFormat("[XXX]: IsLocal? group {0} not found -- no.", groupID);
692 return false;
693 }
694
695 serviceLocation = group.ServiceLocation;
696 name = group.GroupName;
697 bool isLocal = (group.ServiceLocation == string.Empty);
698 //m_log.DebugFormat("[XXX]: IsLocal? {0}", isLocal);
699 return isLocal;
700 }
701
702 private GroupsServiceHGConnector GetConnector(string url)
703 {
704 lock (m_NetworkConnectors)
705 {
706 if (m_NetworkConnectors.ContainsKey(url))
707 return m_NetworkConnectors[url];
708
709 GroupsServiceHGConnector c = new GroupsServiceHGConnector(url);
710 m_NetworkConnectors[url] = c;
711 }
712
713 return m_NetworkConnectors[url];
714 }
715 #endregion
716 }
717}
diff --git a/OpenSim/Addons/Groups/Hypergrid/HGGroupsServiceRobustConnector.cs b/OpenSim/Addons/Groups/Hypergrid/HGGroupsServiceRobustConnector.cs
new file mode 100644
index 0000000..0e71c72
--- /dev/null
+++ b/OpenSim/Addons/Groups/Hypergrid/HGGroupsServiceRobustConnector.cs
@@ -0,0 +1,443 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Reflection;
30using System.Text;
31using System.Xml;
32using System.Collections.Generic;
33using System.IO;
34using Nini.Config;
35using OpenSim.Framework;
36using OpenSim.Server.Base;
37using OpenSim.Services.Interfaces;
38using OpenSim.Framework.Servers.HttpServer;
39using OpenSim.Server.Handlers.Base;
40using log4net;
41using OpenMetaverse;
42
43namespace OpenSim.Groups
44{
45 public class HGGroupsServiceRobustConnector : ServiceConnector
46 {
47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
48
49 private HGGroupsService m_GroupsService;
50 private string m_HomeURI = string.Empty;
51 private string m_ConfigName = "Groups";
52
53 // Called by Robust shell
54 public HGGroupsServiceRobustConnector(IConfigSource config, IHttpServer server, string configName) :
55 this(config, server, configName, null, null)
56 {
57 }
58
59 // Called by the sim-bound module
60 public HGGroupsServiceRobustConnector(IConfigSource config, IHttpServer server, string configName, IOfflineIMService im, IUserAccountService users) :
61 base(config, server, configName)
62 {
63 if (configName != String.Empty)
64 m_ConfigName = configName;
65
66 m_log.DebugFormat("[Groups.RobustHGConnector]: Starting with config name {0}", m_ConfigName);
67
68 string homeURI = Util.GetConfigVarWithDefaultSection(config, "HomeURI", m_ConfigName); //cnf.GetString("HomeURI", string.Empty);
69 if (homeURI == string.Empty)
70 throw new Exception(String.Format("[Groups.RobustHGConnector]: please provide the HomeURI [Startup] or in section {0}", m_ConfigName));
71
72 IConfig cnf = config.Configs[m_ConfigName];
73 if (cnf == null)
74 throw new Exception(String.Format("[Groups.RobustHGConnector]: {0} section does not exist", m_ConfigName));
75
76 if (im == null)
77 {
78 string imDll = cnf.GetString("OfflineIMService", string.Empty);
79 if (imDll == string.Empty)
80 throw new Exception(String.Format("[Groups.RobustHGConnector]: please provide OfflineIMService in section {0}", m_ConfigName));
81
82 Object[] args = new Object[] { config };
83 im = ServerUtils.LoadPlugin<IOfflineIMService>(imDll, args);
84 }
85
86 if (users == null)
87 {
88 string usersDll = cnf.GetString("UserAccountService", string.Empty);
89 if (usersDll == string.Empty)
90 throw new Exception(String.Format("[Groups.RobustHGConnector]: please provide UserAccountService in section {0}", m_ConfigName));
91
92 Object[] args = new Object[] { config };
93 users = ServerUtils.LoadPlugin<IUserAccountService>(usersDll, args);
94 }
95
96 m_GroupsService = new HGGroupsService(config, im, users, homeURI);
97
98 server.AddStreamHandler(new HGGroupsServicePostHandler(m_GroupsService));
99 }
100
101 }
102
103 public class HGGroupsServicePostHandler : BaseStreamHandler
104 {
105 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
106
107 private HGGroupsService m_GroupsService;
108
109 public HGGroupsServicePostHandler(HGGroupsService service) :
110 base("POST", "/hg-groups")
111 {
112 m_GroupsService = service;
113 }
114
115 public override byte[] Handle(string path, Stream requestData,
116 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
117 {
118 StreamReader sr = new StreamReader(requestData);
119 string body = sr.ReadToEnd();
120 sr.Close();
121 body = body.Trim();
122
123 //m_log.DebugFormat("[XXX]: query String: {0}", body);
124
125 try
126 {
127 Dictionary<string, object> request =
128 ServerUtils.ParseQueryString(body);
129
130 if (!request.ContainsKey("METHOD"))
131 return FailureResult();
132
133 string method = request["METHOD"].ToString();
134 request.Remove("METHOD");
135
136 m_log.DebugFormat("[Groups.RobustHGConnector]: {0}", method);
137 switch (method)
138 {
139 case "POSTGROUP":
140 return HandleAddGroupProxy(request);
141 case "REMOVEAGENTFROMGROUP":
142 return HandleRemoveAgentFromGroup(request);
143 case "GETGROUP":
144 return HandleGetGroup(request);
145 case "ADDNOTICE":
146 return HandleAddNotice(request);
147 case "VERIFYNOTICE":
148 return HandleVerifyNotice(request);
149 case "GETGROUPMEMBERS":
150 return HandleGetGroupMembers(request);
151 case "GETGROUPROLES":
152 return HandleGetGroupRoles(request);
153 case "GETROLEMEMBERS":
154 return HandleGetRoleMembers(request);
155
156 }
157 m_log.DebugFormat("[Groups.RobustHGConnector]: unknown method request: {0}", method);
158 }
159 catch (Exception e)
160 {
161 m_log.DebugFormat("[Groups.RobustHGConnector]: Exception {0}", e.StackTrace);
162 }
163
164 return FailureResult();
165 }
166
167 byte[] HandleAddGroupProxy(Dictionary<string, object> request)
168 {
169 Dictionary<string, object> result = new Dictionary<string, object>();
170
171 if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("GroupID")
172 || !request.ContainsKey("AgentID")
173 || !request.ContainsKey("AccessToken") || !request.ContainsKey("Location"))
174 NullResult(result, "Bad network data");
175
176 else
177 {
178 string RequestingAgentID = request["RequestingAgentID"].ToString();
179 string agentID = request["AgentID"].ToString();
180 UUID groupID = new UUID(request["GroupID"].ToString());
181 string accessToken = request["AccessToken"].ToString();
182 string location = request["Location"].ToString();
183 string name = string.Empty;
184 if (request.ContainsKey("Name"))
185 name = request["Name"].ToString();
186
187 string reason = string.Empty;
188 bool success = m_GroupsService.CreateGroupProxy(RequestingAgentID, agentID, accessToken, groupID, location, name, out reason);
189 result["REASON"] = reason;
190 result["RESULT"] = success.ToString();
191 }
192
193 string xmlString = ServerUtils.BuildXmlResponse(result);
194
195 //m_log.DebugFormat("[XXX]: resp string: {0}", xmlString);
196 return Util.UTF8NoBomEncoding.GetBytes(xmlString);
197 }
198
199 byte[] HandleRemoveAgentFromGroup(Dictionary<string, object> request)
200 {
201 Dictionary<string, object> result = new Dictionary<string, object>();
202
203 if (!request.ContainsKey("AccessToken") || !request.ContainsKey("AgentID") ||
204 !request.ContainsKey("GroupID"))
205 NullResult(result, "Bad network data");
206 else
207 {
208 UUID groupID = new UUID(request["GroupID"].ToString());
209 string agentID = request["AgentID"].ToString();
210 string token = request["AccessToken"].ToString();
211 string reason = string.Empty;
212
213 m_GroupsService.RemoveAgentFromGroup(agentID, agentID, groupID, token);
214 }
215
216 //m_log.DebugFormat("[XXX]: resp string: {0}", xmlString);
217 result["RESULT"] = "true";
218 return Util.UTF8NoBomEncoding.GetBytes(ServerUtils.BuildXmlResponse(result));
219 }
220
221 byte[] HandleGetGroup(Dictionary<string, object> request)
222 {
223 Dictionary<string, object> result = new Dictionary<string, object>();
224
225 if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("AccessToken"))
226 NullResult(result, "Bad network data");
227 else
228 {
229 string RequestingAgentID = request["RequestingAgentID"].ToString();
230 string token = request["AccessToken"].ToString();
231
232 UUID groupID = UUID.Zero;
233 string groupName = string.Empty;
234
235 if (request.ContainsKey("GroupID"))
236 groupID = new UUID(request["GroupID"].ToString());
237 if (request.ContainsKey("Name"))
238 groupName = request["Name"].ToString();
239
240 ExtendedGroupRecord grec = m_GroupsService.GetGroupRecord(RequestingAgentID, groupID, groupName, token);
241 if (grec == null)
242 NullResult(result, "Group not found");
243 else
244 result["RESULT"] = GroupsDataUtils.GroupRecord(grec);
245 }
246
247 string xmlString = ServerUtils.BuildXmlResponse(result);
248
249 //m_log.DebugFormat("[XXX]: resp string: {0}", xmlString);
250 return Util.UTF8NoBomEncoding.GetBytes(xmlString);
251 }
252
253 byte[] HandleGetGroupMembers(Dictionary<string, object> request)
254 {
255 Dictionary<string, object> result = new Dictionary<string, object>();
256
257 if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("GroupID") || !request.ContainsKey("AccessToken"))
258 NullResult(result, "Bad network data");
259 else
260 {
261 UUID groupID = new UUID(request["GroupID"].ToString());
262 string requestingAgentID = request["RequestingAgentID"].ToString();
263 string token = request["AccessToken"].ToString();
264
265 List<ExtendedGroupMembersData> members = m_GroupsService.GetGroupMembers(requestingAgentID, groupID, token);
266 if (members == null || (members != null && members.Count == 0))
267 {
268 NullResult(result, "No members");
269 }
270 else
271 {
272 Dictionary<string, object> dict = new Dictionary<string, object>();
273 int i = 0;
274 foreach (ExtendedGroupMembersData m in members)
275 {
276 dict["m-" + i++] = GroupsDataUtils.GroupMembersData(m);
277 }
278
279 result["RESULT"] = dict;
280 }
281 }
282
283 string xmlString = ServerUtils.BuildXmlResponse(result);
284
285 //m_log.DebugFormat("[XXX]: resp string: {0}", xmlString);
286 return Util.UTF8NoBomEncoding.GetBytes(xmlString);
287 }
288
289 byte[] HandleGetGroupRoles(Dictionary<string, object> request)
290 {
291 Dictionary<string, object> result = new Dictionary<string, object>();
292
293 if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("GroupID") || !request.ContainsKey("AccessToken"))
294 NullResult(result, "Bad network data");
295 else
296 {
297 UUID groupID = new UUID(request["GroupID"].ToString());
298 string requestingAgentID = request["RequestingAgentID"].ToString();
299 string token = request["AccessToken"].ToString();
300
301 List<GroupRolesData> roles = m_GroupsService.GetGroupRoles(requestingAgentID, groupID, token);
302 if (roles == null || (roles != null && roles.Count == 0))
303 {
304 NullResult(result, "No members");
305 }
306 else
307 {
308 Dictionary<string, object> dict = new Dictionary<string, object>();
309 int i = 0;
310 foreach (GroupRolesData r in roles)
311 dict["r-" + i++] = GroupsDataUtils.GroupRolesData(r);
312
313 result["RESULT"] = dict;
314 }
315 }
316
317 string xmlString = ServerUtils.BuildXmlResponse(result);
318
319 //m_log.DebugFormat("[XXX]: resp string: {0}", xmlString);
320 return Util.UTF8NoBomEncoding.GetBytes(xmlString);
321 }
322
323 byte[] HandleGetRoleMembers(Dictionary<string, object> request)
324 {
325 Dictionary<string, object> result = new Dictionary<string, object>();
326
327 if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("GroupID") || !request.ContainsKey("AccessToken"))
328 NullResult(result, "Bad network data");
329 else
330 {
331 UUID groupID = new UUID(request["GroupID"].ToString());
332 string requestingAgentID = request["RequestingAgentID"].ToString();
333 string token = request["AccessToken"].ToString();
334
335 List<ExtendedGroupRoleMembersData> rmembers = m_GroupsService.GetGroupRoleMembers(requestingAgentID, groupID, token);
336 if (rmembers == null || (rmembers != null && rmembers.Count == 0))
337 {
338 NullResult(result, "No members");
339 }
340 else
341 {
342 Dictionary<string, object> dict = new Dictionary<string, object>();
343 int i = 0;
344 foreach (ExtendedGroupRoleMembersData rm in rmembers)
345 dict["rm-" + i++] = GroupsDataUtils.GroupRoleMembersData(rm);
346
347 result["RESULT"] = dict;
348 }
349 }
350
351 string xmlString = ServerUtils.BuildXmlResponse(result);
352
353 //m_log.DebugFormat("[XXX]: resp string: {0}", xmlString);
354 return Util.UTF8NoBomEncoding.GetBytes(xmlString);
355 }
356
357 byte[] HandleAddNotice(Dictionary<string, object> request)
358 {
359 Dictionary<string, object> result = new Dictionary<string, object>();
360
361 if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("GroupID") || !request.ContainsKey("NoticeID") ||
362 !request.ContainsKey("FromName") || !request.ContainsKey("Subject") || !request.ContainsKey("Message") ||
363 !request.ContainsKey("HasAttachment"))
364 NullResult(result, "Bad network data");
365
366 else
367 {
368
369 bool hasAtt = bool.Parse(request["HasAttachment"].ToString());
370 byte attType = 0;
371 string attName = string.Empty;
372 string attOwner = string.Empty;
373 UUID attItem = UUID.Zero;
374 if (request.ContainsKey("AttachmentType"))
375 attType = byte.Parse(request["AttachmentType"].ToString());
376 if (request.ContainsKey("AttachmentName"))
377 attName = request["AttachmentType"].ToString();
378 if (request.ContainsKey("AttachmentItemID"))
379 attItem = new UUID(request["AttachmentItemID"].ToString());
380 if (request.ContainsKey("AttachmentOwnerID"))
381 attOwner = request["AttachmentOwnerID"].ToString();
382
383 bool success = m_GroupsService.AddNotice(request["RequestingAgentID"].ToString(), new UUID(request["GroupID"].ToString()),
384 new UUID(request["NoticeID"].ToString()), request["FromName"].ToString(), request["Subject"].ToString(),
385 request["Message"].ToString(), hasAtt, attType, attName, attItem, attOwner);
386
387 result["RESULT"] = success.ToString();
388 }
389
390 string xmlString = ServerUtils.BuildXmlResponse(result);
391
392 //m_log.DebugFormat("[XXX]: resp string: {0}", xmlString);
393 return Util.UTF8NoBomEncoding.GetBytes(xmlString);
394 }
395
396 byte[] HandleVerifyNotice(Dictionary<string, object> request)
397 {
398 Dictionary<string, object> result = new Dictionary<string, object>();
399
400 if (!request.ContainsKey("NoticeID") || !request.ContainsKey("GroupID"))
401 NullResult(result, "Bad network data");
402
403 else
404 {
405 UUID noticeID = new UUID(request["NoticeID"].ToString());
406 UUID groupID = new UUID(request["GroupID"].ToString());
407
408 bool success = m_GroupsService.VerifyNotice(noticeID, groupID);
409 //m_log.DebugFormat("[XXX]: VerifyNotice returned {0}", success);
410 result["RESULT"] = success.ToString();
411 }
412
413 string xmlString = ServerUtils.BuildXmlResponse(result);
414
415 //m_log.DebugFormat("[XXX]: resp string: {0}", xmlString);
416 return Util.UTF8NoBomEncoding.GetBytes(xmlString);
417 }
418
419 //
420 //
421 //
422 //
423 //
424
425 #region Helpers
426
427 private void NullResult(Dictionary<string, object> result, string reason)
428 {
429 result["RESULT"] = "NULL";
430 result["REASON"] = reason;
431 }
432
433 private byte[] FailureResult()
434 {
435 Dictionary<string, object> result = new Dictionary<string, object>();
436 NullResult(result, "Unknown method");
437 string xmlString = ServerUtils.BuildXmlResponse(result);
438 return Util.UTF8NoBomEncoding.GetBytes(xmlString);
439 }
440
441 #endregion
442 }
443}
diff --git a/OpenSim/Addons/Groups/IGroupsServicesConnector.cs b/OpenSim/Addons/Groups/IGroupsServicesConnector.cs
new file mode 100644
index 0000000..73deb7a
--- /dev/null
+++ b/OpenSim/Addons/Groups/IGroupsServicesConnector.cs
@@ -0,0 +1,118 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using OpenMetaverse;
31using OpenSim.Framework;
32
33namespace OpenSim.Groups
34{
35 public interface IGroupsServicesConnector
36 {
37 UUID CreateGroup(UUID RequestingAgentID, string name, string charter, bool showInList, UUID insigniaID, int membershipFee,
38 bool openEnrollment, bool allowPublish, bool maturePublish, UUID founderID, out string reason);
39 bool UpdateGroup(string RequestingAgentID, UUID groupID, string charter, bool showInList, UUID insigniaID, int membershipFee,
40 bool openEnrollment, bool allowPublish, bool maturePublish, out string reason);
41 ExtendedGroupRecord GetGroupRecord(string RequestingAgentID, UUID GroupID, string GroupName);
42 List<DirGroupsReplyData> FindGroups(string RequestingAgentID, string search);
43 List<GroupMembersData> GetGroupMembers(string RequestingAgentID, UUID GroupID);
44
45 bool AddGroupRole(string RequestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers, out string reason);
46 bool UpdateGroupRole(string RequestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers);
47 void RemoveGroupRole(string RequestingAgentID, UUID groupID, UUID roleID);
48 List<GroupRolesData> GetGroupRoles(string RequestingAgentID, UUID GroupID);
49 List<GroupRoleMembersData> GetGroupRoleMembers(string RequestingAgentID, UUID GroupID);
50
51 bool AddAgentToGroup(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID, string token, out string reason);
52 void RemoveAgentFromGroup(string RequestingAgentID, string AgentID, UUID GroupID);
53
54 bool AddAgentToGroupInvite(string RequestingAgentID, UUID inviteID, UUID groupID, UUID roleID, string agentID);
55 GroupInviteInfo GetAgentToGroupInvite(string RequestingAgentID, UUID inviteID);
56 void RemoveAgentToGroupInvite(string RequestingAgentID, UUID inviteID);
57
58 void AddAgentToGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID);
59 void RemoveAgentFromGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID);
60 List<GroupRolesData> GetAgentGroupRoles(string RequestingAgentID, string AgentID, UUID GroupID);
61
62 void SetAgentActiveGroup(string RequestingAgentID, string AgentID, UUID GroupID);
63 ExtendedGroupMembershipData GetAgentActiveMembership(string RequestingAgentID, string AgentID);
64
65 void SetAgentActiveGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID);
66 void UpdateMembership(string RequestingAgentID, string AgentID, UUID GroupID, bool AcceptNotices, bool ListInProfile);
67
68 /// <summary>
69 /// Get information about a specific group to which the user belongs.
70 /// </summary>
71 /// <param name="RequestingAgentID">The agent requesting the information.</param>
72 /// <param name="AgentID">The agent requested.</param>
73 /// <param name="GroupID">The group requested.</param>
74 /// <returns>
75 /// If the user is a member of the group then the data structure is returned. If not, then null is returned.
76 /// </returns>
77 ExtendedGroupMembershipData GetAgentGroupMembership(string RequestingAgentID, string AgentID, UUID GroupID);
78
79 /// <summary>
80 /// Get information about the groups to which a user belongs.
81 /// </summary>
82 /// <param name="RequestingAgentID">The agent requesting the information.</param>
83 /// <param name="AgentID">The agent requested.</param>
84 /// <returns>
85 /// Information about the groups to which the user belongs. If the user belongs to no groups then an empty
86 /// list is returned.
87 /// </returns>
88 List<GroupMembershipData> GetAgentGroupMemberships(string RequestingAgentID, string AgentID);
89
90 bool AddGroupNotice(string RequestingAgentID, UUID groupID, UUID noticeID, string fromName, string subject, string message,
91 bool hasAttachment, byte attType, string attName, UUID attItemID, string attOwnerID);
92 GroupNoticeInfo GetGroupNotice(string RequestingAgentID, UUID noticeID);
93 List<ExtendedGroupNoticeData> GetGroupNotices(string RequestingAgentID, UUID GroupID);
94
95 void ResetAgentGroupChatSessions(string agentID);
96 bool hasAgentBeenInvitedToGroupChatSession(string agentID, UUID groupID);
97 bool hasAgentDroppedGroupChatSession(string agentID, UUID groupID);
98 void AgentDroppedFromGroupChatSession(string agentID, UUID groupID);
99 void AgentInvitedToGroupChatSession(string agentID, UUID groupID);
100
101 }
102
103 public class GroupInviteInfo
104 {
105 public UUID GroupID = UUID.Zero;
106 public UUID RoleID = UUID.Zero;
107 public string AgentID = string.Empty;
108 public UUID InviteID = UUID.Zero;
109 }
110
111 public class GroupNoticeInfo
112 {
113 public ExtendedGroupNoticeData noticeData = new ExtendedGroupNoticeData();
114 public UUID GroupID = UUID.Zero;
115 public string Message = string.Empty;
116 }
117
118}
diff --git a/OpenSim/Addons/Groups/Local/GroupsServiceLocalConnectorModule.cs b/OpenSim/Addons/Groups/Local/GroupsServiceLocalConnectorModule.cs
new file mode 100644
index 0000000..905bc91
--- /dev/null
+++ b/OpenSim/Addons/Groups/Local/GroupsServiceLocalConnectorModule.cs
@@ -0,0 +1,347 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Linq;
31using System.Reflection;
32using System.Text;
33
34using OpenSim.Framework;
35using OpenSim.Region.Framework.Scenes;
36using OpenSim.Region.Framework.Interfaces;
37
38using OpenMetaverse;
39using Mono.Addins;
40using log4net;
41using Nini.Config;
42
43namespace OpenSim.Groups
44{
45 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GroupsServiceLocalConnectorModule")]
46 public class GroupsServiceLocalConnectorModule : ISharedRegionModule, IGroupsServicesConnector
47 {
48 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
49
50 private bool m_Enabled = false;
51 private GroupsService m_GroupsService;
52 private IUserManagement m_UserManagement;
53 private List<Scene> m_Scenes;
54 private ForeignImporter m_ForeignImporter;
55
56 #region constructors
57 public GroupsServiceLocalConnectorModule()
58 {
59 }
60
61 public GroupsServiceLocalConnectorModule(IConfigSource config, IUserManagement uman)
62 {
63 Init(config);
64 m_UserManagement = uman;
65 m_ForeignImporter = new ForeignImporter(uman);
66 }
67 #endregion
68
69 private void Init(IConfigSource config)
70 {
71 m_GroupsService = new GroupsService(config);
72 m_Scenes = new List<Scene>();
73 }
74
75 #region ISharedRegionModule
76
77 public void Initialise(IConfigSource config)
78 {
79 IConfig groupsConfig = config.Configs["Groups"];
80 if (groupsConfig == null)
81 return;
82
83 if ((groupsConfig.GetBoolean("Enabled", false) == false)
84 || (groupsConfig.GetString("ServicesConnectorModule", string.Empty) != Name))
85 {
86 return;
87 }
88
89 Init(config);
90 m_Enabled = true;
91
92 m_log.DebugFormat("[Groups]: Initializing {0}", this.Name);
93 }
94
95 public string Name
96 {
97 get { return "Groups Local Service Connector"; }
98 }
99
100 public Type ReplaceableInterface
101 {
102 get { return null; }
103 }
104
105 public void AddRegion(Scene scene)
106 {
107 if (!m_Enabled)
108 return;
109
110 m_log.DebugFormat("[Groups]: Registering {0} with {1}", this.Name, scene.RegionInfo.RegionName);
111 scene.RegisterModuleInterface<IGroupsServicesConnector>(this);
112 m_Scenes.Add(scene);
113 }
114
115 public void RemoveRegion(Scene scene)
116 {
117 if (!m_Enabled)
118 return;
119
120 scene.UnregisterModuleInterface<IGroupsServicesConnector>(this);
121 m_Scenes.Remove(scene);
122 }
123
124 public void RegionLoaded(Scene scene)
125 {
126 if (!m_Enabled)
127 return;
128
129 if (m_UserManagement == null)
130 {
131 m_UserManagement = scene.RequestModuleInterface<IUserManagement>();
132 m_ForeignImporter = new ForeignImporter(m_UserManagement);
133 }
134 }
135
136 public void PostInitialise()
137 {
138 }
139
140 public void Close()
141 {
142 }
143
144 #endregion
145
146 #region IGroupsServicesConnector
147
148 public UUID CreateGroup(UUID RequestingAgentID, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment,
149 bool allowPublish, bool maturePublish, UUID founderID, out string reason)
150 {
151 m_log.DebugFormat("[Groups]: Creating group {0}", name);
152 reason = string.Empty;
153 return m_GroupsService.CreateGroup(RequestingAgentID.ToString(), name, charter, showInList, insigniaID,
154 membershipFee, openEnrollment, allowPublish, maturePublish, founderID, out reason);
155 }
156
157 public bool UpdateGroup(string RequestingAgentID, UUID groupID, string charter, bool showInList, UUID insigniaID, int membershipFee,
158 bool openEnrollment, bool allowPublish, bool maturePublish, out string reason)
159 {
160 reason = string.Empty;
161 m_GroupsService.UpdateGroup(RequestingAgentID, groupID, charter, showInList, insigniaID, membershipFee, openEnrollment, allowPublish, maturePublish);
162 return true;
163 }
164
165 public ExtendedGroupRecord GetGroupRecord(string RequestingAgentID, UUID GroupID, string GroupName)
166 {
167 if (GroupID != UUID.Zero)
168 return m_GroupsService.GetGroupRecord(RequestingAgentID, GroupID);
169 else if (GroupName != null)
170 return m_GroupsService.GetGroupRecord(RequestingAgentID, GroupName);
171
172 return null;
173 }
174
175 public List<DirGroupsReplyData> FindGroups(string RequestingAgentID, string search)
176 {
177 return m_GroupsService.FindGroups(RequestingAgentID, search);
178 }
179
180 public List<GroupMembersData> GetGroupMembers(string RequestingAgentID, UUID GroupID)
181 {
182 List<ExtendedGroupMembersData> _members = m_GroupsService.GetGroupMembers(RequestingAgentID, GroupID);
183 if (_members != null && _members.Count > 0)
184 {
185 List<GroupMembersData> members = _members.ConvertAll<GroupMembersData>(new Converter<ExtendedGroupMembersData, GroupMembersData>(m_ForeignImporter.ConvertGroupMembersData));
186 return members;
187 }
188
189 return new List<GroupMembersData>();
190 }
191
192 public bool AddGroupRole(string RequestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers, out string reason)
193 {
194 return m_GroupsService.AddGroupRole(RequestingAgentID, groupID, roleID, name, description, title, powers, out reason);
195 }
196
197 public bool UpdateGroupRole(string RequestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers)
198 {
199 return m_GroupsService.UpdateGroupRole(RequestingAgentID, groupID, roleID, name, description, title, powers);
200 }
201
202 public void RemoveGroupRole(string RequestingAgentID, UUID groupID, UUID roleID)
203 {
204 m_GroupsService.RemoveGroupRole(RequestingAgentID, groupID, roleID);
205 }
206
207 public List<GroupRolesData> GetGroupRoles(string RequestingAgentID, UUID GroupID)
208 {
209 return m_GroupsService.GetGroupRoles(RequestingAgentID, GroupID);
210 }
211
212 public List<GroupRoleMembersData> GetGroupRoleMembers(string RequestingAgentID, UUID GroupID)
213 {
214 List<ExtendedGroupRoleMembersData> _rm = m_GroupsService.GetGroupRoleMembers(RequestingAgentID, GroupID);
215 if (_rm != null && _rm.Count > 0)
216 {
217 List<GroupRoleMembersData> rm = _rm.ConvertAll<GroupRoleMembersData>(new Converter<ExtendedGroupRoleMembersData, GroupRoleMembersData>(m_ForeignImporter.ConvertGroupRoleMembersData));
218 return rm;
219 }
220
221 return new List<GroupRoleMembersData>();
222
223 }
224
225 public bool AddAgentToGroup(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID, string token, out string reason)
226 {
227 return m_GroupsService.AddAgentToGroup(RequestingAgentID, AgentID, GroupID, RoleID, token, out reason);
228 }
229
230 public void RemoveAgentFromGroup(string RequestingAgentID, string AgentID, UUID GroupID)
231 {
232 m_GroupsService.RemoveAgentFromGroup(RequestingAgentID, AgentID, GroupID);
233 }
234
235 public bool AddAgentToGroupInvite(string RequestingAgentID, UUID inviteID, UUID groupID, UUID roleID, string agentID)
236 {
237 return m_GroupsService.AddAgentToGroupInvite(RequestingAgentID, inviteID, groupID, roleID, agentID);
238 }
239
240 public GroupInviteInfo GetAgentToGroupInvite(string RequestingAgentID, UUID inviteID)
241 {
242 return m_GroupsService.GetAgentToGroupInvite(RequestingAgentID, inviteID); ;
243 }
244
245 public void RemoveAgentToGroupInvite(string RequestingAgentID, UUID inviteID)
246 {
247 m_GroupsService.RemoveAgentToGroupInvite(RequestingAgentID, inviteID);
248 }
249
250 public void AddAgentToGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID)
251 {
252 m_GroupsService.AddAgentToGroupRole(RequestingAgentID, AgentID, GroupID, RoleID);
253 }
254
255 public void RemoveAgentFromGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID)
256 {
257 m_GroupsService.RemoveAgentFromGroupRole(RequestingAgentID, AgentID, GroupID, RoleID);
258 }
259
260 public List<GroupRolesData> GetAgentGroupRoles(string RequestingAgentID, string AgentID, UUID GroupID)
261 {
262 return m_GroupsService.GetAgentGroupRoles(RequestingAgentID, AgentID, GroupID);
263 }
264
265 public void SetAgentActiveGroup(string RequestingAgentID, string AgentID, UUID GroupID)
266 {
267 m_GroupsService.SetAgentActiveGroup(RequestingAgentID, AgentID, GroupID);
268 }
269
270 public ExtendedGroupMembershipData GetAgentActiveMembership(string RequestingAgentID, string AgentID)
271 {
272 return m_GroupsService.GetAgentActiveMembership(RequestingAgentID, AgentID);
273 }
274
275 public void SetAgentActiveGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID)
276 {
277 m_GroupsService.SetAgentActiveGroupRole(RequestingAgentID, AgentID, GroupID, RoleID);
278 }
279
280 public void UpdateMembership(string RequestingAgentID, string AgentID, UUID GroupID, bool AcceptNotices, bool ListInProfile)
281 {
282 m_GroupsService.UpdateMembership(RequestingAgentID, AgentID, GroupID, AcceptNotices, ListInProfile);
283 }
284
285 public ExtendedGroupMembershipData GetAgentGroupMembership(string RequestingAgentID, string AgentID, UUID GroupID)
286 {
287 return m_GroupsService.GetAgentGroupMembership(RequestingAgentID, AgentID, GroupID); ;
288 }
289
290 public List<GroupMembershipData> GetAgentGroupMemberships(string RequestingAgentID, string AgentID)
291 {
292 return m_GroupsService.GetAgentGroupMemberships(RequestingAgentID, AgentID);
293 }
294
295 public bool AddGroupNotice(string RequestingAgentID, UUID groupID, UUID noticeID, string fromName, string subject, string message,
296 bool hasAttachment, byte attType, string attName, UUID attItemID, string attOwnerID)
297 {
298 return m_GroupsService.AddGroupNotice(RequestingAgentID, groupID, noticeID, fromName, subject, message,
299 hasAttachment, attType, attName, attItemID, attOwnerID);
300 }
301
302 public GroupNoticeInfo GetGroupNotice(string RequestingAgentID, UUID noticeID)
303 {
304 GroupNoticeInfo notice = m_GroupsService.GetGroupNotice(RequestingAgentID, noticeID);
305
306 //if (notice != null && notice.noticeData.HasAttachment && notice.noticeData.AttachmentOwnerID != null)
307 //{
308 // UUID userID = UUID.Zero;
309 // string url = string.Empty, first = string.Empty, last = string.Empty, tmp = string.Empty;
310 // Util.ParseUniversalUserIdentifier(notice.noticeData.AttachmentOwnerID, out userID, out url, out first, out last, out tmp);
311 // if (url != string.Empty)
312 // m_UserManagement.AddUser(userID, first, last, url);
313 //}
314
315 return notice;
316 }
317
318 public List<ExtendedGroupNoticeData> GetGroupNotices(string RequestingAgentID, UUID GroupID)
319 {
320 return m_GroupsService.GetGroupNotices(RequestingAgentID, GroupID);
321 }
322
323 public void ResetAgentGroupChatSessions(string agentID)
324 {
325 }
326
327 public bool hasAgentBeenInvitedToGroupChatSession(string agentID, UUID groupID)
328 {
329 return false;
330 }
331
332 public bool hasAgentDroppedGroupChatSession(string agentID, UUID groupID)
333 {
334 return false;
335 }
336
337 public void AgentDroppedFromGroupChatSession(string agentID, UUID groupID)
338 {
339 }
340
341 public void AgentInvitedToGroupChatSession(string agentID, UUID groupID)
342 {
343 }
344
345 #endregion
346 }
347}
diff --git a/OpenSim/Addons/Groups/Properties/AssemblyInfo.cs b/OpenSim/Addons/Groups/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..5ccd7fe
--- /dev/null
+++ b/OpenSim/Addons/Groups/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
1using System.Reflection;
2using System.Runtime.CompilerServices;
3using System.Runtime.InteropServices;
4using Mono.Addins;
5
6// General Information about an assembly is controlled through the following
7// set of attributes. Change these attribute values to modify the information
8// associated with an assembly.
9[assembly: AssemblyTitle("OpenSim.Addons.Groups")]
10[assembly: AssemblyDescription("")]
11[assembly: AssemblyConfiguration("")]
12[assembly: AssemblyCompany("http://opensimulator.org")]
13[assembly: AssemblyProduct("OpenSim.Addons.Groups")]
14[assembly: AssemblyCopyright("Copyright (c) OpenSimulator.org Developers")]
15[assembly: AssemblyTrademark("")]
16[assembly: AssemblyCulture("")]
17
18// Setting ComVisible to false makes the types in this assembly not visible
19// to COM components. If you need to access a type in this assembly from
20// COM, set the ComVisible attribute to true on that type.
21[assembly: ComVisible(false)]
22
23// The following GUID is for the ID of the typelib if this project is exposed to COM
24[assembly: Guid("313d4865-d179-4735-9b5a-fe74885878b2")]
25
26// Version information for an assembly consists of the following four values:
27//
28// Major Version
29// Minor Version
30// Build Number
31// Revision
32//
33[assembly: AssemblyVersion("0.7.6.*")]
34
35[assembly: Addin("OpenSim.Groups", "0.1")]
36[assembly: AddinDependency("OpenSim", "0.5")]
diff --git a/OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnector.cs b/OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnector.cs
new file mode 100644
index 0000000..04328c9
--- /dev/null
+++ b/OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnector.cs
@@ -0,0 +1,642 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Linq;
31using System.Reflection;
32using System.Text;
33
34using OpenSim.Framework;
35using OpenSim.Server.Base;
36
37using OpenMetaverse;
38using log4net;
39
40namespace OpenSim.Groups
41{
42 public class GroupsServiceRemoteConnector
43 {
44 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
45
46 private string m_ServerURI;
47 private object m_Lock = new object();
48
49 public GroupsServiceRemoteConnector(string url)
50 {
51 m_ServerURI = url;
52 if (!m_ServerURI.EndsWith("/"))
53 m_ServerURI += "/";
54
55 m_log.DebugFormat("[Groups.RemoteConnector]: Groups server at {0}", m_ServerURI);
56 }
57
58 public ExtendedGroupRecord CreateGroup(string RequestingAgentID, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment,
59 bool allowPublish, bool maturePublish, UUID founderID, out string reason)
60 {
61 reason = string.Empty;
62
63 ExtendedGroupRecord rec = new ExtendedGroupRecord();
64 rec.AllowPublish = allowPublish;
65 rec.Charter = charter;
66 rec.FounderID = founderID;
67 rec.GroupName = name;
68 rec.GroupPicture = insigniaID;
69 rec.MaturePublish = maturePublish;
70 rec.MembershipFee = membershipFee;
71 rec.OpenEnrollment = openEnrollment;
72 rec.ShowInList = showInList;
73
74 Dictionary<string, object> sendData = GroupsDataUtils.GroupRecord(rec);
75 sendData["RequestingAgentID"] = RequestingAgentID;
76 sendData["OP"] = "ADD";
77 Dictionary<string, object> ret = MakeRequest("PUTGROUP", sendData);
78
79 if (ret == null)
80 return null;
81
82 if (ret["RESULT"].ToString() == "NULL")
83 {
84 reason = ret["REASON"].ToString();
85 return null;
86 }
87
88 return GroupsDataUtils.GroupRecord((Dictionary<string, object>)ret["RESULT"]);
89
90 }
91
92 public ExtendedGroupRecord UpdateGroup(string RequestingAgentID, UUID groupID, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, bool allowPublish, bool maturePublish)
93 {
94 ExtendedGroupRecord rec = new ExtendedGroupRecord();
95 rec.AllowPublish = allowPublish;
96 rec.Charter = charter;
97 rec.GroupPicture = insigniaID;
98 rec.MaturePublish = maturePublish;
99 rec.GroupID = groupID;
100 rec.MembershipFee = membershipFee;
101 rec.OpenEnrollment = openEnrollment;
102 rec.ShowInList = showInList;
103
104 Dictionary<string, object> sendData = GroupsDataUtils.GroupRecord(rec);
105 sendData["RequestingAgentID"] = RequestingAgentID;
106 sendData["OP"] = "UPDATE";
107 Dictionary<string, object> ret = MakeRequest("PUTGROUP", sendData);
108
109 if (ret == null || (ret != null && ret["RESULT"].ToString() == "NULL"))
110 return null;
111
112 return GroupsDataUtils.GroupRecord((Dictionary<string, object>)ret["RESULT"]);
113 }
114
115 public ExtendedGroupRecord GetGroupRecord(string RequestingAgentID, UUID GroupID, string GroupName)
116 {
117 if (GroupID == UUID.Zero && (GroupName == null || (GroupName != null && GroupName == string.Empty)))
118 return null;
119
120 Dictionary<string, object> sendData = new Dictionary<string, object>();
121 if (GroupID != UUID.Zero)
122 sendData["GroupID"] = GroupID.ToString();
123 if (GroupName != null && GroupName != string.Empty)
124 sendData["Name"] = GroupsDataUtils.Sanitize(GroupName);
125
126 sendData["RequestingAgentID"] = RequestingAgentID;
127
128 Dictionary<string, object> ret = MakeRequest("GETGROUP", sendData);
129
130 if (ret == null || (ret != null && ret["RESULT"].ToString() == "NULL"))
131 return null;
132
133 return GroupsDataUtils.GroupRecord((Dictionary<string, object>)ret["RESULT"]);
134 }
135
136 public GroupMembershipData AddAgentToGroup(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID, string token, out string reason)
137 {
138 reason = string.Empty;
139
140 Dictionary<string, object> sendData = new Dictionary<string,object>();
141 sendData["AgentID"] = AgentID;
142 sendData["GroupID"] = GroupID.ToString();
143 sendData["RoleID"] = RoleID.ToString();
144 sendData["RequestingAgentID"] = RequestingAgentID;
145 sendData["AccessToken"] = token;
146 Dictionary<string, object> ret = MakeRequest("ADDAGENTTOGROUP", sendData);
147
148 if (ret == null)
149 return null;
150
151 if (!ret.ContainsKey("RESULT"))
152 return null;
153
154 if (ret["RESULT"].ToString() == "NULL")
155 {
156 reason = ret["REASON"].ToString();
157 return null;
158 }
159
160 return GroupsDataUtils.GroupMembershipData((Dictionary<string, object>)ret["RESULT"]);
161
162 }
163
164 public void RemoveAgentFromGroup(string RequestingAgentID, string AgentID, UUID GroupID)
165 {
166 Dictionary<string, object> sendData = new Dictionary<string, object>();
167 sendData["AgentID"] = AgentID;
168 sendData["GroupID"] = GroupID.ToString();
169 sendData["RequestingAgentID"] = RequestingAgentID;
170 MakeRequest("REMOVEAGENTFROMGROUP", sendData);
171 }
172
173 public ExtendedGroupMembershipData GetMembership(string RequestingAgentID, string AgentID, UUID GroupID)
174 {
175 Dictionary<string, object> sendData = new Dictionary<string, object>();
176 sendData["AgentID"] = AgentID;
177 if (GroupID != UUID.Zero)
178 sendData["GroupID"] = GroupID.ToString();
179 sendData["RequestingAgentID"] = RequestingAgentID;
180 Dictionary<string, object> ret = MakeRequest("GETMEMBERSHIP", sendData);
181
182 if (ret == null)
183 return null;
184
185 if (!ret.ContainsKey("RESULT"))
186 return null;
187
188 if (ret["RESULT"].ToString() == "NULL")
189 return null;
190
191 return GroupsDataUtils.GroupMembershipData((Dictionary<string, object>)ret["RESULT"]);
192 }
193
194 public List<GroupMembershipData> GetMemberships(string RequestingAgentID, string AgentID)
195 {
196 List<GroupMembershipData> memberships = new List<GroupMembershipData>();
197
198 Dictionary<string, object> sendData = new Dictionary<string, object>();
199 sendData["AgentID"] = AgentID;
200 sendData["ALL"] = "true";
201 sendData["RequestingAgentID"] = RequestingAgentID;
202 Dictionary<string, object> ret = MakeRequest("GETMEMBERSHIP", sendData);
203
204 if (ret == null)
205 return memberships;
206
207 if (!ret.ContainsKey("RESULT"))
208 return memberships;
209
210 if (ret["RESULT"].ToString() == "NULL")
211 return memberships;
212
213 foreach (object v in ((Dictionary<string, object>)ret["RESULT"]).Values)
214 {
215 GroupMembershipData m = GroupsDataUtils.GroupMembershipData((Dictionary<string, object>)v);
216 memberships.Add(m);
217 }
218
219 return memberships;
220 }
221
222 public List<ExtendedGroupMembersData> GetGroupMembers(string RequestingAgentID, UUID GroupID)
223 {
224 List<ExtendedGroupMembersData> members = new List<ExtendedGroupMembersData>();
225
226 Dictionary<string, object> sendData = new Dictionary<string, object>();
227 sendData["GroupID"] = GroupID.ToString();
228 sendData["RequestingAgentID"] = RequestingAgentID;
229 Dictionary<string, object> ret = MakeRequest("GETGROUPMEMBERS", sendData);
230
231 if (ret == null)
232 return members;
233
234 if (!ret.ContainsKey("RESULT"))
235 return members;
236
237 if (ret["RESULT"].ToString() == "NULL")
238 return members;
239 foreach (object v in ((Dictionary<string, object>)ret["RESULT"]).Values)
240 {
241 ExtendedGroupMembersData m = GroupsDataUtils.GroupMembersData((Dictionary<string, object>)v);
242 members.Add(m);
243 }
244
245 return members;
246 }
247
248 public bool AddGroupRole(string RequestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers, out string reason)
249 {
250 reason = string.Empty;
251
252 Dictionary<string, object> sendData = new Dictionary<string, object>();
253 sendData["GroupID"] = groupID.ToString();
254 sendData["RoleID"] = roleID.ToString();
255 sendData["Name"] = GroupsDataUtils.Sanitize(name);
256 sendData["Description"] = GroupsDataUtils.Sanitize(description);
257 sendData["Title"] = GroupsDataUtils.Sanitize(title);
258 sendData["Powers"] = powers.ToString();
259 sendData["RequestingAgentID"] = RequestingAgentID;
260 sendData["OP"] = "ADD";
261 Dictionary<string, object> ret = MakeRequest("PUTROLE", sendData);
262
263 if (ret == null)
264 return false;
265
266 if (!ret.ContainsKey("RESULT"))
267 return false;
268
269 if (ret["RESULT"].ToString().ToLower() != "true")
270 {
271 reason = ret["REASON"].ToString();
272 return false;
273 }
274
275 return true;
276 }
277
278 public bool UpdateGroupRole(string RequestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers)
279 {
280 Dictionary<string, object> sendData = new Dictionary<string, object>();
281 sendData["GroupID"] = groupID.ToString();
282 sendData["RoleID"] = roleID.ToString();
283 sendData["Name"] = GroupsDataUtils.Sanitize(name);
284 sendData["Description"] = GroupsDataUtils.Sanitize(description);
285 sendData["Title"] = GroupsDataUtils.Sanitize(title);
286 sendData["Powers"] = powers.ToString();
287 sendData["RequestingAgentID"] = RequestingAgentID;
288 sendData["OP"] = "UPDATE";
289 Dictionary<string, object> ret = MakeRequest("PUTROLE", sendData);
290
291 if (ret == null)
292 return false;
293
294 if (!ret.ContainsKey("RESULT"))
295 return false;
296
297 if (ret["RESULT"].ToString().ToLower() != "true")
298 return false;
299
300 return true;
301 }
302
303 public void RemoveGroupRole(string RequestingAgentID, UUID groupID, UUID roleID)
304 {
305 Dictionary<string, object> sendData = new Dictionary<string, object>();
306 sendData["GroupID"] = groupID.ToString();
307 sendData["RoleID"] = roleID.ToString();
308 sendData["RequestingAgentID"] = RequestingAgentID;
309 MakeRequest("REMOVEROLE", sendData);
310 }
311
312 public List<GroupRolesData> GetGroupRoles(string RequestingAgentID, UUID GroupID)
313 {
314 List<GroupRolesData> roles = new List<GroupRolesData>();
315
316 Dictionary<string, object> sendData = new Dictionary<string, object>();
317 sendData["GroupID"] = GroupID.ToString();
318 sendData["RequestingAgentID"] = RequestingAgentID;
319 Dictionary<string, object> ret = MakeRequest("GETGROUPROLES", sendData);
320
321 if (ret == null)
322 return roles;
323
324 if (!ret.ContainsKey("RESULT"))
325 return roles;
326
327 if (ret["RESULT"].ToString() == "NULL")
328 return roles;
329 foreach (object v in ((Dictionary<string, object>)ret["RESULT"]).Values)
330 {
331 GroupRolesData m = GroupsDataUtils.GroupRolesData((Dictionary<string, object>)v);
332 roles.Add(m);
333 }
334
335 return roles;
336 }
337
338 public List<ExtendedGroupRoleMembersData> GetGroupRoleMembers(string RequestingAgentID, UUID GroupID)
339 {
340 List<ExtendedGroupRoleMembersData> rmembers = new List<ExtendedGroupRoleMembersData>();
341
342 Dictionary<string, object> sendData = new Dictionary<string, object>();
343 sendData["GroupID"] = GroupID.ToString();
344 sendData["RequestingAgentID"] = RequestingAgentID;
345 Dictionary<string, object> ret = MakeRequest("GETROLEMEMBERS", sendData);
346
347 if (ret == null)
348 return rmembers;
349
350 if (!ret.ContainsKey("RESULT"))
351 return rmembers;
352
353 if (ret["RESULT"].ToString() == "NULL")
354 return rmembers;
355
356 foreach (object v in ((Dictionary<string, object>)ret["RESULT"]).Values)
357 {
358 ExtendedGroupRoleMembersData m = GroupsDataUtils.GroupRoleMembersData((Dictionary<string, object>)v);
359 rmembers.Add(m);
360 }
361
362 return rmembers;
363 }
364
365 public bool AddAgentToGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID)
366 {
367 Dictionary<string, object> sendData = new Dictionary<string, object>();
368 sendData["AgentID"] = AgentID.ToString();
369 sendData["GroupID"] = GroupID.ToString();
370 sendData["RoleID"] = RoleID.ToString();
371 sendData["RequestingAgentID"] = RequestingAgentID;
372 sendData["OP"] = "ADD";
373
374 Dictionary<string, object> ret = MakeRequest("AGENTROLE", sendData);
375
376 if (ret == null)
377 return false;
378
379 if (!ret.ContainsKey("RESULT"))
380 return false;
381
382 if (ret["RESULT"].ToString().ToLower() != "true")
383 return false;
384
385 return true;
386 }
387
388 public bool RemoveAgentFromGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID)
389 {
390 Dictionary<string, object> sendData = new Dictionary<string, object>();
391 sendData["AgentID"] = AgentID.ToString();
392 sendData["GroupID"] = GroupID.ToString();
393 sendData["RoleID"] = RoleID.ToString();
394 sendData["RequestingAgentID"] = RequestingAgentID;
395 sendData["OP"] = "DELETE";
396
397 Dictionary<string, object> ret = MakeRequest("AGENTROLE", sendData);
398
399 if (ret == null)
400 return false;
401
402 if (!ret.ContainsKey("RESULT"))
403 return false;
404
405 if (ret["RESULT"].ToString().ToLower() != "true")
406 return false;
407
408 return true;
409 }
410
411 public List<GroupRolesData> GetAgentGroupRoles(string RequestingAgentID, string AgentID, UUID GroupID)
412 {
413 List<GroupRolesData> roles = new List<GroupRolesData>();
414
415 Dictionary<string, object> sendData = new Dictionary<string, object>();
416 sendData["AgentID"] = AgentID.ToString();
417 sendData["GroupID"] = GroupID.ToString();
418 sendData["RequestingAgentID"] = RequestingAgentID;
419 Dictionary<string, object> ret = MakeRequest("GETAGENTROLES", sendData);
420
421 if (ret == null)
422 return roles;
423
424 if (!ret.ContainsKey("RESULT"))
425 return roles;
426
427 if (ret["RESULT"].ToString() == "NULL")
428 return roles;
429
430 foreach (object v in ((Dictionary<string, object>)ret["RESULT"]).Values)
431 {
432 GroupRolesData m = GroupsDataUtils.GroupRolesData((Dictionary<string, object>)v);
433 roles.Add(m);
434 }
435
436 return roles;
437 }
438
439 public GroupMembershipData SetAgentActiveGroup(string RequestingAgentID, string AgentID, UUID GroupID)
440 {
441 Dictionary<string, object> sendData = new Dictionary<string, object>();
442 sendData["AgentID"] = AgentID.ToString();
443 sendData["GroupID"] = GroupID.ToString();
444 sendData["RequestingAgentID"] = RequestingAgentID;
445 sendData["OP"] = "GROUP";
446
447 Dictionary<string, object> ret = MakeRequest("SETACTIVE", sendData);
448
449 if (ret == null)
450 return null;
451
452 if (!ret.ContainsKey("RESULT"))
453 return null;
454
455 if (ret["RESULT"].ToString() == "NULL")
456 return null;
457
458 return GroupsDataUtils.GroupMembershipData((Dictionary<string, object>)ret["RESULT"]);
459 }
460
461 public void SetAgentActiveGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID)
462 {
463 Dictionary<string, object> sendData = new Dictionary<string, object>();
464 sendData["AgentID"] = AgentID.ToString();
465 sendData["GroupID"] = GroupID.ToString();
466 sendData["RoleID"] = RoleID.ToString();
467 sendData["RequestingAgentID"] = RequestingAgentID;
468 sendData["OP"] = "ROLE";
469
470 MakeRequest("SETACTIVE", sendData);
471 }
472
473 public void UpdateMembership(string RequestingAgentID, string AgentID, UUID GroupID, bool AcceptNotices, bool ListInProfile)
474 {
475 Dictionary<string, object> sendData = new Dictionary<string, object>();
476 sendData["AgentID"] = AgentID.ToString();
477 sendData["GroupID"] = GroupID.ToString();
478 sendData["AcceptNotices"] = AcceptNotices.ToString();
479 sendData["ListInProfile"] = ListInProfile.ToString();
480 sendData["RequestingAgentID"] = RequestingAgentID;
481 MakeRequest("UPDATEMEMBERSHIP", sendData);
482 }
483
484 public bool AddAgentToGroupInvite(string RequestingAgentID, UUID inviteID, UUID groupID, UUID roleID, string agentID)
485 {
486 Dictionary<string, object> sendData = new Dictionary<string, object>();
487 sendData["InviteID"] = inviteID.ToString();
488 sendData["GroupID"] = groupID.ToString();
489 sendData["RoleID"] = roleID.ToString();
490 sendData["AgentID"] = agentID.ToString();
491 sendData["RequestingAgentID"] = RequestingAgentID;
492 sendData["OP"] = "ADD";
493
494 Dictionary<string, object> ret = MakeRequest("INVITE", sendData);
495
496 if (ret == null)
497 return false;
498
499 if (!ret.ContainsKey("RESULT"))
500 return false;
501
502 if (ret["RESULT"].ToString().ToLower() != "true") // it may return "NULL"
503 return false;
504
505 return true;
506 }
507
508 public GroupInviteInfo GetAgentToGroupInvite(string RequestingAgentID, UUID inviteID)
509 {
510 Dictionary<string, object> sendData = new Dictionary<string, object>();
511 sendData["InviteID"] = inviteID.ToString();
512 sendData["RequestingAgentID"] = RequestingAgentID;
513 sendData["OP"] = "GET";
514
515 Dictionary<string, object> ret = MakeRequest("INVITE", sendData);
516
517 if (ret == null)
518 return null;
519
520 if (!ret.ContainsKey("RESULT"))
521 return null;
522
523 if (ret["RESULT"].ToString() == "NULL")
524 return null;
525
526 return GroupsDataUtils.GroupInviteInfo((Dictionary<string, object>)ret["RESULT"]);
527 }
528
529 public void RemoveAgentToGroupInvite(string RequestingAgentID, UUID inviteID)
530 {
531 Dictionary<string, object> sendData = new Dictionary<string, object>();
532 sendData["InviteID"] = inviteID.ToString();
533 sendData["RequestingAgentID"] = RequestingAgentID;
534 sendData["OP"] = "DELETE";
535
536 MakeRequest("INVITE", sendData);
537 }
538
539 public bool AddGroupNotice(string RequestingAgentID, UUID groupID, UUID noticeID, string fromName, string subject, string message,
540 bool hasAttachment, byte attType, string attName, UUID attItemID, string attOwnerID)
541 {
542 Dictionary<string, object> sendData = new Dictionary<string, object>();
543 sendData["GroupID"] = groupID.ToString();
544 sendData["NoticeID"] = noticeID.ToString();
545 sendData["FromName"] = GroupsDataUtils.Sanitize(fromName);
546 sendData["Subject"] = GroupsDataUtils.Sanitize(subject);
547 sendData["Message"] = GroupsDataUtils.Sanitize(message);
548 sendData["HasAttachment"] = hasAttachment.ToString();
549 if (hasAttachment)
550 {
551 sendData["AttachmentType"] = attType.ToString();
552 sendData["AttachmentName"] = attName.ToString();
553 sendData["AttachmentItemID"] = attItemID.ToString();
554 sendData["AttachmentOwnerID"] = attOwnerID;
555 }
556 sendData["RequestingAgentID"] = RequestingAgentID;
557
558 Dictionary<string, object> ret = MakeRequest("ADDNOTICE", sendData);
559
560 if (ret == null)
561 return false;
562
563 if (!ret.ContainsKey("RESULT"))
564 return false;
565
566 if (ret["RESULT"].ToString().ToLower() != "true")
567 return false;
568
569 return true;
570 }
571
572 public GroupNoticeInfo GetGroupNotice(string RequestingAgentID, UUID noticeID)
573 {
574 Dictionary<string, object> sendData = new Dictionary<string, object>();
575 sendData["NoticeID"] = noticeID.ToString();
576 sendData["RequestingAgentID"] = RequestingAgentID;
577
578 Dictionary<string, object> ret = MakeRequest("GETNOTICES", sendData);
579
580 if (ret == null)
581 return null;
582
583 if (!ret.ContainsKey("RESULT"))
584 return null;
585
586 if (ret["RESULT"].ToString() == "NULL")
587 return null;
588
589 return GroupsDataUtils.GroupNoticeInfo((Dictionary<string, object>)ret["RESULT"]);
590 }
591
592 public List<ExtendedGroupNoticeData> GetGroupNotices(string RequestingAgentID, UUID GroupID)
593 {
594 List<ExtendedGroupNoticeData> notices = new List<ExtendedGroupNoticeData>();
595
596 Dictionary<string, object> sendData = new Dictionary<string, object>();
597 sendData["GroupID"] = GroupID.ToString();
598 sendData["RequestingAgentID"] = RequestingAgentID;
599 Dictionary<string, object> ret = MakeRequest("GETNOTICES", sendData);
600
601 if (ret == null)
602 return notices;
603
604 if (!ret.ContainsKey("RESULT"))
605 return notices;
606
607 if (ret["RESULT"].ToString() == "NULL")
608 return notices;
609
610 foreach (object v in ((Dictionary<string, object>)ret["RESULT"]).Values)
611 {
612 ExtendedGroupNoticeData m = GroupsDataUtils.GroupNoticeData((Dictionary<string, object>)v);
613 notices.Add(m);
614 }
615
616 return notices;
617 }
618
619 #region Make Request
620
621 private Dictionary<string, object> MakeRequest(string method, Dictionary<string, object> sendData)
622 {
623 sendData["METHOD"] = method;
624
625 string reply = string.Empty;
626 lock (m_Lock)
627 reply = SynchronousRestFormsRequester.MakeRequest("POST",
628 m_ServerURI + "groups",
629 ServerUtils.BuildQueryString(sendData));
630
631 if (reply == string.Empty)
632 return null;
633
634 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(
635 reply);
636
637 return replyData;
638 }
639 #endregion
640
641 }
642}
diff --git a/OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnectorModule.cs b/OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnectorModule.cs
new file mode 100644
index 0000000..d1c02db
--- /dev/null
+++ b/OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnectorModule.cs
@@ -0,0 +1,437 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Linq;
31using System.Reflection;
32using System.Threading;
33using System.Text;
34
35using OpenSim.Framework;
36using OpenSim.Region.Framework.Scenes;
37using OpenSim.Region.Framework.Interfaces;
38using OpenSim.Server.Base;
39
40using OpenMetaverse;
41using Mono.Addins;
42using log4net;
43using Nini.Config;
44
45namespace OpenSim.Groups
46{
47 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GroupsServiceRemoteConnectorModule")]
48 public class GroupsServiceRemoteConnectorModule : ISharedRegionModule, IGroupsServicesConnector
49 {
50 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
51
52 private bool m_Enabled = false;
53 private GroupsServiceRemoteConnector m_GroupsService;
54 private IUserManagement m_UserManagement;
55 private List<Scene> m_Scenes;
56
57 private RemoteConnectorCacheWrapper m_CacheWrapper;
58
59 #region constructors
60 public GroupsServiceRemoteConnectorModule()
61 {
62 }
63
64 public GroupsServiceRemoteConnectorModule(IConfigSource config, IUserManagement uman)
65 {
66 Init(config);
67 m_UserManagement = uman;
68 m_CacheWrapper = new RemoteConnectorCacheWrapper(m_UserManagement);
69
70 }
71 #endregion
72
73 private void Init(IConfigSource config)
74 {
75 IConfig groupsConfig = config.Configs["Groups"];
76 string url = groupsConfig.GetString("GroupsServerURI", string.Empty);
77 if (url == string.Empty)
78 {
79 m_log.WarnFormat("[Groups.RemoteConnector]: Groups server URL not provided. Groups will not work.");
80 return;
81 }
82
83 m_GroupsService = new GroupsServiceRemoteConnector(url);
84 m_Scenes = new List<Scene>();
85
86 }
87
88 #region ISharedRegionModule
89
90 public void Initialise(IConfigSource config)
91 {
92 IConfig groupsConfig = config.Configs["Groups"];
93 if (groupsConfig == null)
94 return;
95
96 if ((groupsConfig.GetBoolean("Enabled", false) == false)
97 || (groupsConfig.GetString("ServicesConnectorModule", string.Empty) != Name))
98 {
99 return;
100 }
101
102 Init(config);
103
104 m_Enabled = true;
105 m_log.DebugFormat("[Groups.RemoteConnector]: Initializing {0}", this.Name);
106 }
107
108 public string Name
109 {
110 get { return "Groups Remote Service Connector"; }
111 }
112
113 public Type ReplaceableInterface
114 {
115 get { return null; }
116 }
117
118 public void AddRegion(Scene scene)
119 {
120 if (!m_Enabled)
121 return;
122
123 m_log.DebugFormat("[Groups.RemoteConnector]: Registering {0} with {1}", this.Name, scene.RegionInfo.RegionName);
124 scene.RegisterModuleInterface<IGroupsServicesConnector>(this);
125 m_Scenes.Add(scene);
126 }
127
128 public void RemoveRegion(Scene scene)
129 {
130 if (!m_Enabled)
131 return;
132
133 scene.UnregisterModuleInterface<IGroupsServicesConnector>(this);
134 m_Scenes.Remove(scene);
135 }
136
137 public void RegionLoaded(Scene scene)
138 {
139 if (!m_Enabled)
140 return;
141
142 if (m_UserManagement == null)
143 {
144 m_UserManagement = scene.RequestModuleInterface<IUserManagement>();
145 m_CacheWrapper = new RemoteConnectorCacheWrapper(m_UserManagement);
146 }
147 }
148
149 public void PostInitialise()
150 {
151 }
152
153 public void Close()
154 {
155 }
156
157 #endregion
158
159 #region IGroupsServicesConnector
160
161 public UUID CreateGroup(UUID RequestingAgentID, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment,
162 bool allowPublish, bool maturePublish, UUID founderID, out string reason)
163 {
164 m_log.DebugFormat("[Groups.RemoteConnector]: Creating group {0}", name);
165 string r = string.Empty;
166
167 UUID groupID = m_CacheWrapper.CreateGroup(RequestingAgentID, delegate
168 {
169 return m_GroupsService.CreateGroup(RequestingAgentID.ToString(), name, charter, showInList, insigniaID,
170 membershipFee, openEnrollment, allowPublish, maturePublish, founderID, out r);
171 });
172
173 reason = r;
174 return groupID;
175 }
176
177 public bool UpdateGroup(string RequestingAgentID, UUID groupID, string charter, bool showInList, UUID insigniaID, int membershipFee,
178 bool openEnrollment, bool allowPublish, bool maturePublish, out string reason)
179 {
180 string r = string.Empty;
181
182 bool success = m_CacheWrapper.UpdateGroup(groupID, delegate
183 {
184 return m_GroupsService.UpdateGroup(RequestingAgentID, groupID, charter, showInList, insigniaID, membershipFee, openEnrollment, allowPublish, maturePublish);
185 });
186
187 reason = r;
188 return success;
189 }
190
191 public ExtendedGroupRecord GetGroupRecord(string RequestingAgentID, UUID GroupID, string GroupName)
192 {
193 if (GroupID == UUID.Zero && (GroupName == null || GroupName != null && GroupName == string.Empty))
194 return null;
195
196 return m_CacheWrapper.GetGroupRecord(RequestingAgentID,GroupID,GroupName, delegate
197 {
198 return m_GroupsService.GetGroupRecord(RequestingAgentID, GroupID, GroupName);
199 });
200 }
201
202 public List<DirGroupsReplyData> FindGroups(string RequestingAgentID, string search)
203 {
204 // TODO!
205 return new List<DirGroupsReplyData>();
206 }
207
208 public bool AddAgentToGroup(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID, string token, out string reason)
209 {
210 string agentFullID = AgentID;
211 m_log.DebugFormat("[Groups.RemoteConnector]: Add agent {0} to group {1}", agentFullID, GroupID);
212 string r = string.Empty;
213
214 bool success = m_CacheWrapper.AddAgentToGroup(RequestingAgentID, AgentID, GroupID, delegate
215 {
216 return m_GroupsService.AddAgentToGroup(RequestingAgentID, agentFullID, GroupID, RoleID, token, out r);
217 });
218
219 reason = r;
220 return success;
221 }
222
223 public void RemoveAgentFromGroup(string RequestingAgentID, string AgentID, UUID GroupID)
224 {
225 m_CacheWrapper.RemoveAgentFromGroup(RequestingAgentID, AgentID, GroupID, delegate
226 {
227 m_GroupsService.RemoveAgentFromGroup(RequestingAgentID, AgentID, GroupID);
228 });
229
230 }
231
232 public void SetAgentActiveGroup(string RequestingAgentID, string AgentID, UUID GroupID)
233 {
234 m_CacheWrapper.SetAgentActiveGroup(AgentID, delegate
235 {
236 return m_GroupsService.SetAgentActiveGroup(RequestingAgentID, AgentID, GroupID);
237 });
238 }
239
240 public ExtendedGroupMembershipData GetAgentActiveMembership(string RequestingAgentID, string AgentID)
241 {
242 return m_CacheWrapper.GetAgentActiveMembership(AgentID, delegate
243 {
244 return m_GroupsService.GetMembership(RequestingAgentID, AgentID, UUID.Zero);
245 });
246 }
247
248 public ExtendedGroupMembershipData GetAgentGroupMembership(string RequestingAgentID, string AgentID, UUID GroupID)
249 {
250 return m_CacheWrapper.GetAgentGroupMembership(AgentID, GroupID, delegate
251 {
252 return m_GroupsService.GetMembership(RequestingAgentID, AgentID, GroupID);
253 });
254 }
255
256 public List<GroupMembershipData> GetAgentGroupMemberships(string RequestingAgentID, string AgentID)
257 {
258 return m_CacheWrapper.GetAgentGroupMemberships(AgentID, delegate
259 {
260 return m_GroupsService.GetMemberships(RequestingAgentID, AgentID);
261 });
262 }
263
264
265 public List<GroupMembersData> GetGroupMembers(string RequestingAgentID, UUID GroupID)
266 {
267 return m_CacheWrapper.GetGroupMembers(RequestingAgentID, GroupID, delegate
268 {
269 return m_GroupsService.GetGroupMembers(RequestingAgentID, GroupID);
270 });
271 }
272
273 public bool AddGroupRole(string RequestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers, out string reason)
274 {
275 string r = string.Empty;
276 bool success = m_CacheWrapper.AddGroupRole(roleID, description, name, powers, title, delegate
277 {
278 return m_GroupsService.AddGroupRole(RequestingAgentID, groupID, roleID, name, description, title, powers, out r);
279 });
280
281 reason = r;
282 return success;
283 }
284
285 public bool UpdateGroupRole(string RequestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers)
286 {
287 return m_CacheWrapper.UpdateGroupRole(groupID, roleID, name, description, title, powers, delegate
288 {
289 return m_GroupsService.UpdateGroupRole(RequestingAgentID, groupID, roleID, name, description, title, powers);
290 });
291 }
292
293 public void RemoveGroupRole(string RequestingAgentID, UUID groupID, UUID roleID)
294 {
295 m_CacheWrapper.RemoveGroupRole(RequestingAgentID, groupID, roleID, delegate
296 {
297 m_GroupsService.RemoveGroupRole(RequestingAgentID, groupID, roleID);
298 });
299 }
300
301 public List<GroupRolesData> GetGroupRoles(string RequestingAgentID, UUID GroupID)
302 {
303 return m_CacheWrapper.GetGroupRoles(RequestingAgentID, GroupID, delegate
304 {
305 return m_GroupsService.GetGroupRoles(RequestingAgentID, GroupID);
306 });
307 }
308
309 public List<GroupRoleMembersData> GetGroupRoleMembers(string RequestingAgentID, UUID GroupID)
310 {
311 return m_CacheWrapper.GetGroupRoleMembers(RequestingAgentID, GroupID, delegate
312 {
313 return m_GroupsService.GetGroupRoleMembers(RequestingAgentID, GroupID);
314 });
315 }
316
317 public void AddAgentToGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID)
318 {
319 m_CacheWrapper.AddAgentToGroupRole(RequestingAgentID, AgentID, GroupID, RoleID, delegate
320 {
321 return m_GroupsService.AddAgentToGroupRole(RequestingAgentID, AgentID, GroupID, RoleID);
322 });
323 }
324
325 public void RemoveAgentFromGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID)
326 {
327 m_CacheWrapper.RemoveAgentFromGroupRole(RequestingAgentID, AgentID, GroupID, RoleID, delegate
328 {
329 return m_GroupsService.RemoveAgentFromGroupRole(RequestingAgentID, AgentID, GroupID, RoleID);
330 });
331 }
332
333 public List<GroupRolesData> GetAgentGroupRoles(string RequestingAgentID, string AgentID, UUID GroupID)
334 {
335 return m_CacheWrapper.GetAgentGroupRoles(RequestingAgentID, AgentID, GroupID, delegate
336 {
337 return m_GroupsService.GetAgentGroupRoles(RequestingAgentID, AgentID, GroupID); ;
338 });
339 }
340
341 public void SetAgentActiveGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID)
342 {
343 m_CacheWrapper.SetAgentActiveGroupRole(AgentID, GroupID, delegate
344 {
345 m_GroupsService.SetAgentActiveGroupRole(RequestingAgentID, AgentID, GroupID, RoleID);
346 });
347 }
348
349 public void UpdateMembership(string RequestingAgentID, string AgentID, UUID GroupID, bool AcceptNotices, bool ListInProfile)
350 {
351 m_CacheWrapper.UpdateMembership(AgentID, GroupID, AcceptNotices, ListInProfile, delegate
352 {
353 m_GroupsService.UpdateMembership(RequestingAgentID, AgentID, GroupID, AcceptNotices, ListInProfile);
354 });
355 }
356
357 public bool AddAgentToGroupInvite(string RequestingAgentID, UUID inviteID, UUID groupID, UUID roleID, string agentID)
358 {
359 return m_GroupsService.AddAgentToGroupInvite(RequestingAgentID, inviteID, groupID, roleID, agentID);
360 }
361
362 public GroupInviteInfo GetAgentToGroupInvite(string RequestingAgentID, UUID inviteID)
363 {
364 return m_GroupsService.GetAgentToGroupInvite(RequestingAgentID, inviteID);
365 }
366
367 public void RemoveAgentToGroupInvite(string RequestingAgentID, UUID inviteID)
368 {
369 m_GroupsService.RemoveAgentToGroupInvite(RequestingAgentID, inviteID);
370 }
371
372 public bool AddGroupNotice(string RequestingAgentID, UUID groupID, UUID noticeID, string fromName, string subject, string message,
373 bool hasAttachment, byte attType, string attName, UUID attItemID, string attOwnerID)
374 {
375 GroupNoticeInfo notice = new GroupNoticeInfo();
376 notice.GroupID = groupID;
377 notice.Message = message;
378 notice.noticeData = new ExtendedGroupNoticeData();
379 notice.noticeData.AttachmentItemID = attItemID;
380 notice.noticeData.AttachmentName = attName;
381 notice.noticeData.AttachmentOwnerID = attOwnerID.ToString();
382 notice.noticeData.AttachmentType = attType;
383 notice.noticeData.FromName = fromName;
384 notice.noticeData.HasAttachment = hasAttachment;
385 notice.noticeData.NoticeID = noticeID;
386 notice.noticeData.Subject = subject;
387 notice.noticeData.Timestamp = (uint)Util.UnixTimeSinceEpoch();
388
389 return m_CacheWrapper.AddGroupNotice(groupID, noticeID, notice, delegate
390 {
391 return m_GroupsService.AddGroupNotice(RequestingAgentID, groupID, noticeID, fromName, subject, message,
392 hasAttachment, attType, attName, attItemID, attOwnerID);
393 });
394 }
395
396 public GroupNoticeInfo GetGroupNotice(string RequestingAgentID, UUID noticeID)
397 {
398 return m_CacheWrapper.GetGroupNotice(noticeID, delegate
399 {
400 return m_GroupsService.GetGroupNotice(RequestingAgentID, noticeID);
401 });
402 }
403
404 public List<ExtendedGroupNoticeData> GetGroupNotices(string RequestingAgentID, UUID GroupID)
405 {
406 return m_CacheWrapper.GetGroupNotices(GroupID, delegate
407 {
408 return m_GroupsService.GetGroupNotices(RequestingAgentID, GroupID);
409 });
410 }
411
412 public void ResetAgentGroupChatSessions(string agentID)
413 {
414 }
415
416 public bool hasAgentBeenInvitedToGroupChatSession(string agentID, UUID groupID)
417 {
418 return false;
419 }
420
421 public bool hasAgentDroppedGroupChatSession(string agentID, UUID groupID)
422 {
423 return false;
424 }
425
426 public void AgentDroppedFromGroupChatSession(string agentID, UUID groupID)
427 {
428 }
429
430 public void AgentInvitedToGroupChatSession(string agentID, UUID groupID)
431 {
432 }
433
434 #endregion
435 }
436
437}
diff --git a/OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs b/OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs
new file mode 100644
index 0000000..8c257ed
--- /dev/null
+++ b/OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs
@@ -0,0 +1,760 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Reflection;
30using System.Text;
31using System.Xml;
32using System.Collections.Generic;
33using System.IO;
34using Nini.Config;
35using OpenSim.Framework;
36using OpenSim.Server.Base;
37using OpenSim.Services.Interfaces;
38using OpenSim.Framework.Servers.HttpServer;
39using OpenSim.Server.Handlers.Base;
40using log4net;
41using OpenMetaverse;
42
43namespace OpenSim.Groups
44{
45 public class GroupsServiceRobustConnector : ServiceConnector
46 {
47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
48
49 private GroupsService m_GroupsService;
50 private string m_ConfigName = "Groups";
51
52 public GroupsServiceRobustConnector(IConfigSource config, IHttpServer server, string configName) :
53 base(config, server, configName)
54 {
55 if (configName != String.Empty)
56 m_ConfigName = configName;
57
58 m_log.DebugFormat("[Groups.RobustConnector]: Starting with config name {0}", m_ConfigName);
59
60 m_GroupsService = new GroupsService(config);
61
62 server.AddStreamHandler(new GroupsServicePostHandler(m_GroupsService));
63 }
64 }
65
66 public class GroupsServicePostHandler : BaseStreamHandler
67 {
68 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
69
70 private GroupsService m_GroupsService;
71
72 public GroupsServicePostHandler(GroupsService service) :
73 base("POST", "/groups")
74 {
75 m_GroupsService = service;
76 }
77
78 public override byte[] Handle(string path, Stream requestData,
79 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
80 {
81 StreamReader sr = new StreamReader(requestData);
82 string body = sr.ReadToEnd();
83 sr.Close();
84 body = body.Trim();
85
86 //m_log.DebugFormat("[XXX]: query String: {0}", body);
87
88 try
89 {
90 Dictionary<string, object> request =
91 ServerUtils.ParseQueryString(body);
92
93 if (!request.ContainsKey("METHOD"))
94 return FailureResult();
95
96 string method = request["METHOD"].ToString();
97 request.Remove("METHOD");
98
99 m_log.DebugFormat("[Groups.Handler]: {0}", method);
100 switch (method)
101 {
102 case "PUTGROUP":
103 return HandleAddOrUpdateGroup(request);
104 case "GETGROUP":
105 return HandleGetGroup(request);
106 case "ADDAGENTTOGROUP":
107 return HandleAddAgentToGroup(request);
108 case "REMOVEAGENTFROMGROUP":
109 return HandleRemoveAgentFromGroup(request);
110 case "GETMEMBERSHIP":
111 return HandleGetMembership(request);
112 case "GETGROUPMEMBERS":
113 return HandleGetGroupMembers(request);
114 case "PUTROLE":
115 return HandlePutRole(request);
116 case "REMOVEROLE":
117 return HandleRemoveRole(request);
118 case "GETGROUPROLES":
119 return HandleGetGroupRoles(request);
120 case "GETROLEMEMBERS":
121 return HandleGetRoleMembers(request);
122 case "AGENTROLE":
123 return HandleAgentRole(request);
124 case "GETAGENTROLES":
125 return HandleGetAgentRoles(request);
126 case "SETACTIVE":
127 return HandleSetActive(request);
128 case "UPDATEMEMBERSHIP":
129 return HandleUpdateMembership(request);
130 case "INVITE":
131 return HandleInvite(request);
132 case "ADDNOTICE":
133 return HandleAddNotice(request);
134 case "GETNOTICES":
135 return HandleGetNotices(request);
136 }
137 m_log.DebugFormat("[GROUPS HANDLER]: unknown method request: {0}", method);
138 }
139 catch (Exception e)
140 {
141 m_log.DebugFormat("[GROUPS HANDLER]: Exception {0}", e.StackTrace);
142 }
143
144 return FailureResult();
145 }
146
147 byte[] HandleAddOrUpdateGroup(Dictionary<string, object> request)
148 {
149 Dictionary<string, object> result = new Dictionary<string, object>();
150
151 ExtendedGroupRecord grec = GroupsDataUtils.GroupRecord(request);
152 if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("OP"))
153 NullResult(result, "Bad network data");
154
155 else
156 {
157 string RequestingAgentID = request["RequestingAgentID"].ToString();
158 string reason = string.Empty;
159 string op = request["OP"].ToString();
160 if (op == "ADD")
161 {
162 grec.GroupID = m_GroupsService.CreateGroup(RequestingAgentID, grec.GroupName, grec.Charter, grec.ShowInList, grec.GroupPicture, grec.MembershipFee,
163 grec.OpenEnrollment, grec.AllowPublish, grec.MaturePublish, grec.FounderID, out reason);
164
165 }
166 else if (op == "UPDATE")
167 {
168 m_GroupsService.UpdateGroup(RequestingAgentID, grec.GroupID, grec.Charter, grec.ShowInList, grec.GroupPicture, grec.MembershipFee,
169 grec.OpenEnrollment, grec.AllowPublish, grec.MaturePublish);
170
171 }
172
173 grec = m_GroupsService.GetGroupRecord(RequestingAgentID, grec.GroupID);
174 if (grec == null)
175 NullResult(result, "Internal Error");
176 else
177 result["RESULT"] = GroupsDataUtils.GroupRecord(grec);
178 }
179
180 string xmlString = ServerUtils.BuildXmlResponse(result);
181
182 //m_log.DebugFormat("[XXX]: resp string: {0}", xmlString);
183 return Util.UTF8NoBomEncoding.GetBytes(xmlString);
184 }
185
186 byte[] HandleGetGroup(Dictionary<string, object> request)
187 {
188 Dictionary<string, object> result = new Dictionary<string, object>();
189
190 if (!request.ContainsKey("RequestingAgentID"))
191 NullResult(result, "Bad network data");
192 else
193 {
194 string RequestingAgentID = request["RequestingAgentID"].ToString();
195 ExtendedGroupRecord grec = null;
196 if (request.ContainsKey("GroupID"))
197 {
198 UUID groupID = new UUID(request["GroupID"].ToString());
199 grec = m_GroupsService.GetGroupRecord(RequestingAgentID, groupID);
200 }
201 else if (request.ContainsKey("Name"))
202 {
203 string name = request["Name"].ToString();
204 grec = m_GroupsService.GetGroupRecord(RequestingAgentID, name);
205 }
206
207 if (grec == null)
208 NullResult(result, "Group not found");
209 else
210 result["RESULT"] = GroupsDataUtils.GroupRecord(grec);
211 }
212
213 string xmlString = ServerUtils.BuildXmlResponse(result);
214
215 //m_log.DebugFormat("[XXX]: resp string: {0}", xmlString);
216 return Util.UTF8NoBomEncoding.GetBytes(xmlString);
217 }
218
219 byte[] HandleAddAgentToGroup(Dictionary<string, object> request)
220 {
221 Dictionary<string, object> result = new Dictionary<string, object>();
222
223 if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("AgentID") ||
224 !request.ContainsKey("GroupID") || !request.ContainsKey("RoleID"))
225 NullResult(result, "Bad network data");
226 else
227 {
228 UUID groupID = new UUID(request["GroupID"].ToString());
229 UUID roleID = new UUID(request["RoleID"].ToString());
230 string agentID = request["AgentID"].ToString();
231 string requestingAgentID = request["RequestingAgentID"].ToString();
232 string token = string.Empty;
233 string reason = string.Empty;
234
235 if (request.ContainsKey("AccessToken"))
236 token = request["AccessToken"].ToString();
237
238 if (!m_GroupsService.AddAgentToGroup(requestingAgentID, agentID, groupID, roleID, token, out reason))
239 NullResult(result, reason);
240 else
241 {
242 GroupMembershipData membership = m_GroupsService.GetAgentGroupMembership(requestingAgentID, agentID, groupID);
243 if (membership == null)
244 NullResult(result, "Internal error");
245 else
246 result["RESULT"] = GroupsDataUtils.GroupMembershipData((ExtendedGroupMembershipData)membership);
247 }
248 }
249
250 string xmlString = ServerUtils.BuildXmlResponse(result);
251
252 //m_log.DebugFormat("[XXX]: resp string: {0}", xmlString);
253 return Util.UTF8NoBomEncoding.GetBytes(xmlString);
254 }
255
256 byte[] HandleRemoveAgentFromGroup(Dictionary<string, object> request)
257 {
258 Dictionary<string, object> result = new Dictionary<string, object>();
259
260 if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("AgentID") || !request.ContainsKey("GroupID"))
261 NullResult(result, "Bad network data");
262 else
263 {
264 UUID groupID = new UUID(request["GroupID"].ToString());
265 string agentID = request["AgentID"].ToString();
266 string requestingAgentID = request["RequestingAgentID"].ToString();
267 string reason = string.Empty;
268
269 m_GroupsService.RemoveAgentFromGroup(requestingAgentID, agentID, groupID);
270 }
271
272 //m_log.DebugFormat("[XXX]: resp string: {0}", xmlString);
273 result["RESULT"] = "true";
274 return Util.UTF8NoBomEncoding.GetBytes(ServerUtils.BuildXmlResponse(result));
275 }
276
277 byte[] HandleGetMembership(Dictionary<string, object> request)
278 {
279 Dictionary<string, object> result = new Dictionary<string, object>();
280
281 if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("AgentID"))
282 NullResult(result, "Bad network data");
283 else
284 {
285 string agentID = request["AgentID"].ToString();
286 UUID groupID = UUID.Zero;
287 if (request.ContainsKey("GroupID"))
288 groupID = new UUID(request["GroupID"].ToString());
289 string requestingAgentID = request["RequestingAgentID"].ToString();
290 bool all = request.ContainsKey("ALL");
291
292 if (!all)
293 {
294 ExtendedGroupMembershipData membership = null;
295 if (groupID == UUID.Zero)
296 {
297 membership = m_GroupsService.GetAgentActiveMembership(requestingAgentID, agentID);
298 }
299 else
300 {
301 membership = m_GroupsService.GetAgentGroupMembership(requestingAgentID, agentID, groupID);
302 }
303
304 if (membership == null)
305 NullResult(result, "No such membership");
306 else
307 result["RESULT"] = GroupsDataUtils.GroupMembershipData(membership);
308 }
309 else
310 {
311 List<GroupMembershipData> memberships = m_GroupsService.GetAgentGroupMemberships(requestingAgentID, agentID);
312 if (memberships == null || (memberships != null && memberships.Count == 0))
313 {
314 NullResult(result, "No memberships");
315 }
316 else
317 {
318 Dictionary<string, object> dict = new Dictionary<string, object>();
319 int i = 0;
320 foreach (GroupMembershipData m in memberships)
321 dict["m-" + i++] = GroupsDataUtils.GroupMembershipData((ExtendedGroupMembershipData)m);
322
323 result["RESULT"] = dict;
324 }
325 }
326 }
327
328 string xmlString = ServerUtils.BuildXmlResponse(result);
329
330 //m_log.DebugFormat("[XXX]: resp string: {0}", xmlString);
331 return Util.UTF8NoBomEncoding.GetBytes(xmlString);
332 }
333
334 byte[] HandleGetGroupMembers(Dictionary<string, object> request)
335 {
336 Dictionary<string, object> result = new Dictionary<string, object>();
337
338 if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("GroupID"))
339 NullResult(result, "Bad network data");
340 else
341 {
342 UUID groupID = new UUID(request["GroupID"].ToString());
343 string requestingAgentID = request["RequestingAgentID"].ToString();
344
345 List<ExtendedGroupMembersData> members = m_GroupsService.GetGroupMembers(requestingAgentID, groupID);
346 if (members == null || (members != null && members.Count == 0))
347 {
348 NullResult(result, "No members");
349 }
350 else
351 {
352 Dictionary<string, object> dict = new Dictionary<string, object>();
353 int i = 0;
354 foreach (ExtendedGroupMembersData m in members)
355 {
356 dict["m-" + i++] = GroupsDataUtils.GroupMembersData(m);
357 }
358
359 result["RESULT"] = dict;
360 }
361 }
362
363 string xmlString = ServerUtils.BuildXmlResponse(result);
364
365 //m_log.DebugFormat("[XXX]: resp string: {0}", xmlString);
366 return Util.UTF8NoBomEncoding.GetBytes(xmlString);
367 }
368
369 byte[] HandlePutRole(Dictionary<string, object> request)
370 {
371 Dictionary<string, object> result = new Dictionary<string, object>();
372
373 if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("GroupID") || !request.ContainsKey("RoleID") ||
374 !request.ContainsKey("Name") || !request.ContainsKey("Descrption") || !request.ContainsKey("Title") ||
375 !request.ContainsKey("Powers") || !request.ContainsKey("OP"))
376 NullResult(result, "Bad network data");
377
378 else
379 {
380 string op = request["OP"].ToString();
381 string reason = string.Empty;
382
383 bool success = false;
384 if (op == "ADD")
385 success = m_GroupsService.AddGroupRole(request["RequestingAgentID"].ToString(), new UUID(request["GroupID"].ToString()),
386 new UUID(request["RoleID"].ToString()), request["Name"].ToString(), request["Description"].ToString(),
387 request["Title"].ToString(), UInt64.Parse(request["Powers"].ToString()), out reason);
388
389 else if (op == "UPDATE")
390 success = m_GroupsService.UpdateGroupRole(request["RequestingAgentID"].ToString(), new UUID(request["GroupID"].ToString()),
391 new UUID(request["RoleID"].ToString()), request["Name"].ToString(), request["Description"].ToString(),
392 request["Title"].ToString(), UInt64.Parse(request["Powers"].ToString()));
393
394 result["RESULT"] = success.ToString();
395 }
396
397 string xmlString = ServerUtils.BuildXmlResponse(result);
398
399 //m_log.DebugFormat("[XXX]: resp string: {0}", xmlString);
400 return Util.UTF8NoBomEncoding.GetBytes(xmlString);
401 }
402
403 byte[] HandleRemoveRole(Dictionary<string, object> request)
404 {
405 Dictionary<string, object> result = new Dictionary<string, object>();
406
407 if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("GroupID") || !request.ContainsKey("RoleID"))
408 NullResult(result, "Bad network data");
409
410 else
411 {
412 m_GroupsService.RemoveGroupRole(request["RequestingAgentID"].ToString(), new UUID(request["GroupID"].ToString()),
413 new UUID(request["RoleID"].ToString()));
414 result["RESULT"] = "true";
415 }
416
417 //m_log.DebugFormat("[XXX]: resp string: {0}", xmlString);
418 return Util.UTF8NoBomEncoding.GetBytes(ServerUtils.BuildXmlResponse(result));
419 }
420
421 byte[] HandleGetGroupRoles(Dictionary<string, object> request)
422 {
423 Dictionary<string, object> result = new Dictionary<string, object>();
424
425 if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("GroupID"))
426 NullResult(result, "Bad network data");
427 else
428 {
429 UUID groupID = new UUID(request["GroupID"].ToString());
430 string requestingAgentID = request["RequestingAgentID"].ToString();
431
432 List<GroupRolesData> roles = m_GroupsService.GetGroupRoles(requestingAgentID, groupID);
433 if (roles == null || (roles != null && roles.Count == 0))
434 {
435 NullResult(result, "No members");
436 }
437 else
438 {
439 Dictionary<string, object> dict = new Dictionary<string, object>();
440 int i = 0;
441 foreach (GroupRolesData r in roles)
442 dict["r-" + i++] = GroupsDataUtils.GroupRolesData(r);
443
444 result["RESULT"] = dict;
445 }
446 }
447
448 string xmlString = ServerUtils.BuildXmlResponse(result);
449
450 //m_log.DebugFormat("[XXX]: resp string: {0}", xmlString);
451 return Util.UTF8NoBomEncoding.GetBytes(xmlString);
452 }
453
454 byte[] HandleGetRoleMembers(Dictionary<string, object> request)
455 {
456 Dictionary<string, object> result = new Dictionary<string, object>();
457
458 if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("GroupID"))
459 NullResult(result, "Bad network data");
460 else
461 {
462 UUID groupID = new UUID(request["GroupID"].ToString());
463 string requestingAgentID = request["RequestingAgentID"].ToString();
464
465 List<ExtendedGroupRoleMembersData> rmembers = m_GroupsService.GetGroupRoleMembers(requestingAgentID, groupID);
466 if (rmembers == null || (rmembers != null && rmembers.Count == 0))
467 {
468 NullResult(result, "No members");
469 }
470 else
471 {
472 Dictionary<string, object> dict = new Dictionary<string, object>();
473 int i = 0;
474 foreach (ExtendedGroupRoleMembersData rm in rmembers)
475 dict["rm-" + i++] = GroupsDataUtils.GroupRoleMembersData(rm);
476
477 result["RESULT"] = dict;
478 }
479 }
480
481 string xmlString = ServerUtils.BuildXmlResponse(result);
482
483 //m_log.DebugFormat("[XXX]: resp string: {0}", xmlString);
484 return Util.UTF8NoBomEncoding.GetBytes(xmlString);
485 }
486
487 byte[] HandleAgentRole(Dictionary<string, object> request)
488 {
489 Dictionary<string, object> result = new Dictionary<string, object>();
490
491 if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("GroupID") || !request.ContainsKey("RoleID") ||
492 !request.ContainsKey("AgentID") || !request.ContainsKey("OP"))
493 NullResult(result, "Bad network data");
494
495 else
496 {
497 string op = request["OP"].ToString();
498 string reason = string.Empty;
499
500 bool success = false;
501 if (op == "ADD")
502 success = m_GroupsService.AddAgentToGroupRole(request["RequestingAgentID"].ToString(), request["AgentID"].ToString(),
503 new UUID(request["GroupID"].ToString()), new UUID(request["RoleID"].ToString()));
504
505 else if (op == "DELETE")
506 success = m_GroupsService.RemoveAgentFromGroupRole(request["RequestingAgentID"].ToString(), request["AgentID"].ToString(),
507 new UUID(request["GroupID"].ToString()), new UUID(request["RoleID"].ToString()));
508
509 result["RESULT"] = success.ToString();
510 }
511
512 string xmlString = ServerUtils.BuildXmlResponse(result);
513
514 //m_log.DebugFormat("[XXX]: resp string: {0}", xmlString);
515 return Util.UTF8NoBomEncoding.GetBytes(xmlString);
516 }
517
518 byte[] HandleGetAgentRoles(Dictionary<string, object> request)
519 {
520 Dictionary<string, object> result = new Dictionary<string, object>();
521
522 if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("GroupID") || !request.ContainsKey("AgentID"))
523 NullResult(result, "Bad network data");
524 else
525 {
526 UUID groupID = new UUID(request["GroupID"].ToString());
527 string agentID = request["AgentID"].ToString();
528 string requestingAgentID = request["RequestingAgentID"].ToString();
529
530 List<GroupRolesData> roles = m_GroupsService.GetAgentGroupRoles(requestingAgentID, agentID, groupID);
531 if (roles == null || (roles != null && roles.Count == 0))
532 {
533 NullResult(result, "No members");
534 }
535 else
536 {
537 Dictionary<string, object> dict = new Dictionary<string, object>();
538 int i = 0;
539 foreach (GroupRolesData r in roles)
540 dict["r-" + i++] = GroupsDataUtils.GroupRolesData(r);
541
542 result["RESULT"] = dict;
543 }
544 }
545
546 string xmlString = ServerUtils.BuildXmlResponse(result);
547
548 //m_log.DebugFormat("[XXX]: resp string: {0}", xmlString);
549 return Util.UTF8NoBomEncoding.GetBytes(xmlString);
550 }
551
552 byte[] HandleSetActive(Dictionary<string, object> request)
553 {
554 Dictionary<string, object> result = new Dictionary<string, object>();
555
556 if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("GroupID") ||
557 !request.ContainsKey("AgentID") || !request.ContainsKey("OP"))
558 {
559 NullResult(result, "Bad network data");
560 string xmlString = ServerUtils.BuildXmlResponse(result);
561 return Util.UTF8NoBomEncoding.GetBytes(xmlString);
562 }
563 else
564 {
565 string op = request["OP"].ToString();
566 string reason = string.Empty;
567
568 if (op == "GROUP")
569 {
570 ExtendedGroupMembershipData group = m_GroupsService.SetAgentActiveGroup(request["RequestingAgentID"].ToString(),
571 request["AgentID"].ToString(), new UUID(request["GroupID"].ToString()));
572
573 if (group == null)
574 NullResult(result, "Internal error");
575 else
576 result["RESULT"] = GroupsDataUtils.GroupMembershipData(group);
577
578 string xmlString = ServerUtils.BuildXmlResponse(result);
579
580 //m_log.DebugFormat("[XXX]: resp string: {0}", xmlString);
581 return Util.UTF8NoBomEncoding.GetBytes(xmlString);
582
583 }
584 else if (op == "ROLE" && request.ContainsKey("RoleID"))
585 {
586 m_GroupsService.SetAgentActiveGroupRole(request["RequestingAgentID"].ToString(), request["AgentID"].ToString(),
587 new UUID(request["GroupID"].ToString()), new UUID(request["RoleID"].ToString()));
588 result["RESULT"] = "true";
589 }
590
591 return Util.UTF8NoBomEncoding.GetBytes(ServerUtils.BuildXmlResponse(result));
592 }
593
594 }
595
596 byte[] HandleUpdateMembership(Dictionary<string, object> request)
597 {
598 Dictionary<string, object> result = new Dictionary<string, object>();
599
600 if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("AgentID") || !request.ContainsKey("GroupID") ||
601 !request.ContainsKey("AcceptNotices") || !request.ContainsKey("ListInProfile"))
602 NullResult(result, "Bad network data");
603
604 else
605 {
606 m_GroupsService.UpdateMembership(request["RequestingAgentID"].ToString(), request["AgentID"].ToString(), new UUID(request["GroupID"].ToString()),
607 bool.Parse(request["AcceptNotices"].ToString()), bool.Parse(request["ListInProfile"].ToString()));
608
609 result["RESULT"] = "true";
610 }
611
612 //m_log.DebugFormat("[XXX]: resp string: {0}", xmlString);
613 return Util.UTF8NoBomEncoding.GetBytes(ServerUtils.BuildXmlResponse(result));
614 }
615
616 byte[] HandleInvite(Dictionary<string, object> request)
617 {
618 Dictionary<string, object> result = new Dictionary<string, object>();
619
620 if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("InviteID"))
621 {
622 NullResult(result, "Bad network data");
623 string xmlString = ServerUtils.BuildXmlResponse(result);
624 return Util.UTF8NoBomEncoding.GetBytes(xmlString);
625 }
626 else
627 {
628 string op = request["OP"].ToString();
629 string reason = string.Empty;
630
631 if (op == "ADD" && request.ContainsKey("GroupID") && request.ContainsKey("RoleID") && request.ContainsKey("AgentID"))
632 {
633 bool success = m_GroupsService.AddAgentToGroupInvite(request["RequestingAgentID"].ToString(),
634 new UUID(request["InviteID"].ToString()), new UUID(request["GroupID"].ToString()),
635 new UUID(request["RoleID"].ToString()), request["AgentID"].ToString());
636
637 result["RESULT"] = success.ToString();
638 return Util.UTF8NoBomEncoding.GetBytes(ServerUtils.BuildXmlResponse(result));
639
640 }
641 else if (op == "DELETE")
642 {
643 m_GroupsService.RemoveAgentToGroupInvite(request["RequestingAgentID"].ToString(), new UUID(request["InviteID"].ToString()));
644 result["RESULT"] = "true";
645 return Util.UTF8NoBomEncoding.GetBytes(ServerUtils.BuildXmlResponse(result));
646 }
647 else if (op == "GET")
648 {
649 GroupInviteInfo invite = m_GroupsService.GetAgentToGroupInvite(request["RequestingAgentID"].ToString(),
650 new UUID(request["InviteID"].ToString()));
651
652 result["RESULT"] = GroupsDataUtils.GroupInviteInfo(invite);
653 return Util.UTF8NoBomEncoding.GetBytes(ServerUtils.BuildXmlResponse(result));
654 }
655
656 NullResult(result, "Bad OP in request");
657 return Util.UTF8NoBomEncoding.GetBytes(ServerUtils.BuildXmlResponse(result));
658 }
659
660 }
661
662 byte[] HandleAddNotice(Dictionary<string, object> request)
663 {
664 Dictionary<string, object> result = new Dictionary<string, object>();
665
666 if (!request.ContainsKey("RequestingAgentID") || !request.ContainsKey("GroupID") || !request.ContainsKey("NoticeID") ||
667 !request.ContainsKey("FromName") || !request.ContainsKey("Subject") || !request.ContainsKey("Message") ||
668 !request.ContainsKey("HasAttachment"))
669 NullResult(result, "Bad network data");
670
671 else
672 {
673
674 bool hasAtt = bool.Parse(request["HasAttachment"].ToString());
675 byte attType = 0;
676 string attName = string.Empty;
677 string attOwner = string.Empty;
678 UUID attItem = UUID.Zero;
679 if (request.ContainsKey("AttachmentType"))
680 attType = byte.Parse(request["AttachmentType"].ToString());
681 if (request.ContainsKey("AttachmentName"))
682 attName = request["AttachmentName"].ToString();
683 if (request.ContainsKey("AttachmentItemID"))
684 attItem = new UUID(request["AttachmentItemID"].ToString());
685 if (request.ContainsKey("AttachmentOwnerID"))
686 attOwner = request["AttachmentOwnerID"].ToString();
687
688 bool success = m_GroupsService.AddGroupNotice(request["RequestingAgentID"].ToString(), new UUID(request["GroupID"].ToString()),
689 new UUID(request["NoticeID"].ToString()), request["FromName"].ToString(), request["Subject"].ToString(),
690 request["Message"].ToString(), hasAtt, attType, attName, attItem, attOwner);
691
692 result["RESULT"] = success.ToString();
693 }
694
695 string xmlString = ServerUtils.BuildXmlResponse(result);
696
697 //m_log.DebugFormat("[XXX]: resp string: {0}", xmlString);
698 return Util.UTF8NoBomEncoding.GetBytes(xmlString);
699 }
700
701 byte[] HandleGetNotices(Dictionary<string, object> request)
702 {
703 Dictionary<string, object> result = new Dictionary<string, object>();
704
705 if (!request.ContainsKey("RequestingAgentID"))
706 NullResult(result, "Bad network data");
707
708 else if (request.ContainsKey("NoticeID")) // just one
709 {
710 GroupNoticeInfo notice = m_GroupsService.GetGroupNotice(request["RequestingAgentID"].ToString(), new UUID(request["NoticeID"].ToString()));
711
712 if (notice == null)
713 NullResult(result, "NO such notice");
714 else
715 result["RESULT"] = GroupsDataUtils.GroupNoticeInfo(notice);
716
717 }
718 else if (request.ContainsKey("GroupID")) // all notices for group
719 {
720 List<ExtendedGroupNoticeData> notices = m_GroupsService.GetGroupNotices(request["RequestingAgentID"].ToString(), new UUID(request["GroupID"].ToString()));
721
722 if (notices == null || (notices != null && notices.Count == 0))
723 NullResult(result, "No notices");
724 else
725 {
726 Dictionary<string, object> dict = new Dictionary<string, object>();
727 int i = 0;
728 foreach (ExtendedGroupNoticeData n in notices)
729 dict["n-" + i++] = GroupsDataUtils.GroupNoticeData(n);
730
731 result["RESULT"] = dict;
732 }
733
734 }
735 else
736 NullResult(result, "Bad OP in request");
737
738 string xmlString = ServerUtils.BuildXmlResponse(result);
739 return Util.UTF8NoBomEncoding.GetBytes(xmlString);
740 }
741
742
743 #region Helpers
744
745 private void NullResult(Dictionary<string, object> result, string reason)
746 {
747 result["RESULT"] = "NULL";
748 result["REASON"] = reason;
749 }
750
751 private byte[] FailureResult()
752 {
753 Dictionary<string, object> result = new Dictionary<string, object>();
754 NullResult(result, "Unknown method");
755 string xmlString = ServerUtils.BuildXmlResponse(result);
756 return Util.UTF8NoBomEncoding.GetBytes(xmlString);
757 }
758 #endregion
759 }
760}
diff --git a/OpenSim/Addons/Groups/RemoteConnectorCacheWrapper.cs b/OpenSim/Addons/Groups/RemoteConnectorCacheWrapper.cs
new file mode 100644
index 0000000..f789626
--- /dev/null
+++ b/OpenSim/Addons/Groups/RemoteConnectorCacheWrapper.cs
@@ -0,0 +1,824 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Reflection;
31using System.Threading;
32
33using OpenSim.Framework;
34using OpenSim.Region.Framework.Interfaces;
35
36using OpenMetaverse;
37
38namespace OpenSim.Groups
39{
40 public delegate ExtendedGroupRecord GroupRecordDelegate();
41 public delegate GroupMembershipData GroupMembershipDelegate();
42 public delegate List<GroupMembershipData> GroupMembershipListDelegate();
43 public delegate List<ExtendedGroupMembersData> GroupMembersListDelegate();
44 public delegate List<GroupRolesData> GroupRolesListDelegate();
45 public delegate List<ExtendedGroupRoleMembersData> RoleMembersListDelegate();
46 public delegate GroupNoticeInfo NoticeDelegate();
47 public delegate List<ExtendedGroupNoticeData> NoticeListDelegate();
48 public delegate void VoidDelegate();
49 public delegate bool BooleanDelegate();
50
51 public class RemoteConnectorCacheWrapper
52 {
53 private ForeignImporter m_ForeignImporter;
54
55 private Dictionary<string, bool> m_ActiveRequests = new Dictionary<string, bool>();
56 private const int GROUPS_CACHE_TIMEOUT = 5 * 60; // 5 minutes
57
58 // This all important cache cahces objects of different types:
59 // group-<GroupID> or group-<Name> => ExtendedGroupRecord
60 // active-<AgentID> => GroupMembershipData
61 // membership-<AgentID>-<GroupID> => GroupMembershipData
62 // memberships-<AgentID> => List<GroupMembershipData>
63 // members-<RequestingAgentID>-<GroupID> => List<ExtendedGroupMembersData>
64 // role-<RoleID> => GroupRolesData
65 // roles-<GroupID> => List<GroupRolesData> ; all roles in the group
66 // roles-<GroupID>-<AgentID> => List<GroupRolesData> ; roles that the agent has
67 // rolemembers-<RequestingAgentID>-<GroupID> => List<ExtendedGroupRoleMembersData>
68 // notice-<noticeID> => GroupNoticeInfo
69 // notices-<GroupID> => List<ExtendedGroupNoticeData>
70 private ExpiringCache<string, object> m_Cache = new ExpiringCache<string, object>();
71
72 public RemoteConnectorCacheWrapper(IUserManagement uman)
73 {
74 m_ForeignImporter = new ForeignImporter(uman);
75 }
76
77 public UUID CreateGroup(UUID RequestingAgentID, GroupRecordDelegate d)
78 {
79 //m_log.DebugFormat("[Groups.RemoteConnector]: Creating group {0}", name);
80 //reason = string.Empty;
81
82 //ExtendedGroupRecord group = m_GroupsService.CreateGroup(RequestingAgentID.ToString(), name, charter, showInList, insigniaID,
83 // membershipFee, openEnrollment, allowPublish, maturePublish, founderID, out reason);
84 ExtendedGroupRecord group = d();
85
86 if (group == null)
87 return UUID.Zero;
88
89 if (group.GroupID != UUID.Zero)
90 lock (m_Cache)
91 {
92 m_Cache.Add("group-" + group.GroupID.ToString(), group, GROUPS_CACHE_TIMEOUT);
93 if (m_Cache.Contains("memberships-" + RequestingAgentID.ToString()))
94 m_Cache.Remove("memberships-" + RequestingAgentID.ToString());
95 }
96
97 return group.GroupID;
98 }
99
100 public bool UpdateGroup(UUID groupID, GroupRecordDelegate d)
101 {
102 //reason = string.Empty;
103 //ExtendedGroupRecord group = m_GroupsService.UpdateGroup(RequestingAgentID, groupID, charter, showInList, insigniaID, membershipFee, openEnrollment, allowPublish, maturePublish);
104 ExtendedGroupRecord group = d();
105
106 if (group != null && group.GroupID != UUID.Zero)
107 lock (m_Cache)
108 m_Cache.AddOrUpdate("group-" + group.GroupID.ToString(), group, GROUPS_CACHE_TIMEOUT);
109 return true;
110 }
111
112 public ExtendedGroupRecord GetGroupRecord(string RequestingAgentID, UUID GroupID, string GroupName, GroupRecordDelegate d)
113 {
114 //if (GroupID == UUID.Zero && (GroupName == null || GroupName != null && GroupName == string.Empty))
115 // return null;
116
117 object group = null;
118 bool firstCall = false;
119 string cacheKey = "group-";
120 if (GroupID != UUID.Zero)
121 cacheKey += GroupID.ToString();
122 else
123 cacheKey += GroupName;
124
125 //m_log.DebugFormat("[XXX]: GetGroupRecord {0}", cacheKey);
126
127 while (true)
128 {
129 lock (m_Cache)
130 {
131 if (m_Cache.TryGetValue(cacheKey, out group))
132 {
133 //m_log.DebugFormat("[XXX]: GetGroupRecord {0} cached!", cacheKey);
134 return (ExtendedGroupRecord)group;
135 }
136
137 // not cached
138 if (!m_ActiveRequests.ContainsKey(cacheKey))
139 {
140 m_ActiveRequests.Add(cacheKey, true);
141 firstCall = true;
142 }
143 }
144
145 if (firstCall)
146 {
147 //group = m_GroupsService.GetGroupRecord(RequestingAgentID, GroupID, GroupName);
148 group = d();
149
150 lock (m_Cache)
151 {
152 m_Cache.AddOrUpdate(cacheKey, group, GROUPS_CACHE_TIMEOUT);
153 m_ActiveRequests.Remove(cacheKey);
154 return (ExtendedGroupRecord)group;
155 }
156 }
157 else
158 Thread.Sleep(50);
159 }
160 }
161
162 public bool AddAgentToGroup(string RequestingAgentID, string AgentID, UUID GroupID, GroupMembershipDelegate d)
163 {
164 GroupMembershipData membership = d();
165 if (membership == null)
166 return false;
167
168 lock (m_Cache)
169 {
170 // first, remove everything! add a user is a heavy-duty op
171 m_Cache.Clear();
172
173 m_Cache.AddOrUpdate("active-" + AgentID.ToString(), membership, GROUPS_CACHE_TIMEOUT);
174 m_Cache.AddOrUpdate("membership-" + AgentID.ToString() + "-" + GroupID.ToString(), membership, GROUPS_CACHE_TIMEOUT);
175 }
176
177
178 return true;
179 }
180
181 public void RemoveAgentFromGroup(string RequestingAgentID, string AgentID, UUID GroupID, VoidDelegate d)
182 {
183 d();
184
185 lock (m_Cache)
186 {
187 string cacheKey = "active-" + AgentID.ToString();
188 if (m_Cache.Contains(cacheKey))
189 m_Cache.Remove(cacheKey);
190
191 cacheKey = "memberships-" + AgentID.ToString();
192 if (m_Cache.Contains(cacheKey))
193 m_Cache.Remove(cacheKey);
194
195 cacheKey = "membership-" + AgentID.ToString() + "-" + GroupID.ToString();
196 if (m_Cache.Contains(cacheKey))
197 m_Cache.Remove(cacheKey);
198
199 cacheKey = "members-" + RequestingAgentID.ToString() + "-" + GroupID.ToString();
200 if (m_Cache.Contains(cacheKey))
201 m_Cache.Remove(cacheKey);
202
203 cacheKey = "roles-" + "-" + GroupID.ToString() + "-" + AgentID.ToString();
204 if (m_Cache.Contains(cacheKey))
205 m_Cache.Remove(cacheKey);
206 }
207 }
208
209 public void SetAgentActiveGroup(string AgentID, GroupMembershipDelegate d)
210 {
211 GroupMembershipData activeGroup = d();
212 if (activeGroup != null)
213 {
214 string cacheKey = "active-" + AgentID.ToString();
215 lock (m_Cache)
216 if (m_Cache.Contains(cacheKey))
217 m_Cache.AddOrUpdate(cacheKey, activeGroup, GROUPS_CACHE_TIMEOUT);
218 }
219 }
220
221 public ExtendedGroupMembershipData GetAgentActiveMembership(string AgentID, GroupMembershipDelegate d)
222 {
223 object membership = null;
224 bool firstCall = false;
225 string cacheKey = "active-" + AgentID.ToString();
226
227 //m_log.DebugFormat("[XXX]: GetAgentActiveMembership {0}", cacheKey);
228
229 while (true)
230 {
231 lock (m_Cache)
232 {
233 if (m_Cache.TryGetValue(cacheKey, out membership))
234 {
235 //m_log.DebugFormat("[XXX]: GetAgentActiveMembership {0} cached!", cacheKey);
236 return (ExtendedGroupMembershipData)membership;
237 }
238
239 // not cached
240 if (!m_ActiveRequests.ContainsKey(cacheKey))
241 {
242 m_ActiveRequests.Add(cacheKey, true);
243 firstCall = true;
244 }
245 }
246
247 if (firstCall)
248 {
249 membership = d();
250
251 lock (m_Cache)
252 {
253 m_Cache.AddOrUpdate(cacheKey, membership, GROUPS_CACHE_TIMEOUT);
254 m_ActiveRequests.Remove(cacheKey);
255 return (ExtendedGroupMembershipData)membership;
256 }
257 }
258 else
259 Thread.Sleep(50);
260 }
261
262 }
263
264 public ExtendedGroupMembershipData GetAgentGroupMembership(string AgentID, UUID GroupID, GroupMembershipDelegate d)
265 {
266 object membership = null;
267 bool firstCall = false;
268 string cacheKey = "membership-" + AgentID.ToString() + "-" + GroupID.ToString();
269
270 //m_log.DebugFormat("[XXX]: GetAgentGroupMembership {0}", cacheKey);
271
272 while (true)
273 {
274 lock (m_Cache)
275 {
276 if (m_Cache.TryGetValue(cacheKey, out membership))
277 {
278 //m_log.DebugFormat("[XXX]: GetAgentGroupMembership {0}", cacheKey);
279 return (ExtendedGroupMembershipData)membership;
280 }
281
282 // not cached
283 if (!m_ActiveRequests.ContainsKey(cacheKey))
284 {
285 m_ActiveRequests.Add(cacheKey, true);
286 firstCall = true;
287 }
288 }
289
290 if (firstCall)
291 {
292 membership = d();
293 lock (m_Cache)
294 {
295 m_Cache.AddOrUpdate(cacheKey, membership, GROUPS_CACHE_TIMEOUT);
296 m_ActiveRequests.Remove(cacheKey);
297 return (ExtendedGroupMembershipData)membership;
298 }
299 }
300 else
301 Thread.Sleep(50);
302 }
303 }
304
305 public List<GroupMembershipData> GetAgentGroupMemberships(string AgentID, GroupMembershipListDelegate d)
306 {
307 object memberships = null;
308 bool firstCall = false;
309 string cacheKey = "memberships-" + AgentID.ToString();
310
311 //m_log.DebugFormat("[XXX]: GetAgentGroupMemberships {0}", cacheKey);
312
313 while (true)
314 {
315 lock (m_Cache)
316 {
317 if (m_Cache.TryGetValue(cacheKey, out memberships))
318 {
319 //m_log.DebugFormat("[XXX]: GetAgentGroupMemberships {0} cached!", cacheKey);
320 return (List<GroupMembershipData>)memberships;
321 }
322
323 // not cached
324 if (!m_ActiveRequests.ContainsKey(cacheKey))
325 {
326 m_ActiveRequests.Add(cacheKey, true);
327 firstCall = true;
328 }
329 }
330
331 if (firstCall)
332 {
333 memberships = d();
334 lock (m_Cache)
335 {
336 m_Cache.AddOrUpdate(cacheKey, memberships, GROUPS_CACHE_TIMEOUT);
337 m_ActiveRequests.Remove(cacheKey);
338 return (List<GroupMembershipData>)memberships;
339 }
340 }
341 else
342 Thread.Sleep(50);
343 }
344 }
345
346 public List<GroupMembersData> GetGroupMembers(string RequestingAgentID, UUID GroupID, GroupMembersListDelegate d)
347 {
348 object members = null;
349 bool firstCall = false;
350 // we need to key in also on the requester, because different ppl have different view privileges
351 string cacheKey = "members-" + RequestingAgentID.ToString() + "-" + GroupID.ToString();
352
353 //m_log.DebugFormat("[XXX]: GetGroupMembers {0}", cacheKey);
354
355 while (true)
356 {
357 lock (m_Cache)
358 {
359 if (m_Cache.TryGetValue(cacheKey, out members))
360 {
361 List<ExtendedGroupMembersData> xx = (List<ExtendedGroupMembersData>)members;
362 return xx.ConvertAll<GroupMembersData>(new Converter<ExtendedGroupMembersData, GroupMembersData>(m_ForeignImporter.ConvertGroupMembersData));
363 }
364
365 // not cached
366 if (!m_ActiveRequests.ContainsKey(cacheKey))
367 {
368 m_ActiveRequests.Add(cacheKey, true);
369 firstCall = true;
370 }
371 }
372
373 if (firstCall)
374 {
375 List<ExtendedGroupMembersData> _members = d();
376
377 if (_members != null && _members.Count > 0)
378 members = _members.ConvertAll<GroupMembersData>(new Converter<ExtendedGroupMembersData, GroupMembersData>(m_ForeignImporter.ConvertGroupMembersData));
379 else
380 members = new List<GroupMembersData>();
381
382 lock (m_Cache)
383 {
384 //m_Cache.AddOrUpdate(cacheKey, members, GROUPS_CACHE_TIMEOUT);
385 m_Cache.AddOrUpdate(cacheKey, _members, GROUPS_CACHE_TIMEOUT);
386 m_ActiveRequests.Remove(cacheKey);
387
388 return (List<GroupMembersData>)members;
389 }
390 }
391 else
392 Thread.Sleep(50);
393 }
394 }
395
396 public bool AddGroupRole(UUID roleID, string description, string name, ulong powers, string title, BooleanDelegate d)
397 {
398 if (d())
399 {
400 GroupRolesData role = new GroupRolesData();
401 role.Description = description;
402 role.Members = 0;
403 role.Name = name;
404 role.Powers = powers;
405 role.RoleID = roleID;
406 role.Title = title;
407
408 lock (m_Cache)
409 m_Cache.AddOrUpdate("role-" + roleID.ToString(), role, GROUPS_CACHE_TIMEOUT);
410
411 return true;
412 }
413
414 return false;
415 }
416
417 public bool UpdateGroupRole(UUID groupID, UUID roleID, string name, string description, string title, ulong powers, BooleanDelegate d)
418 {
419 if (d())
420 {
421 object role;
422 lock (m_Cache)
423 if (m_Cache.TryGetValue("role-" + roleID.ToString(), out role))
424 {
425 GroupRolesData r = (GroupRolesData)role;
426 r.Description = description;
427 r.Name = name;
428 r.Powers = powers;
429 r.Title = title;
430
431 m_Cache.Update("role-" + roleID.ToString(), r, GROUPS_CACHE_TIMEOUT);
432 }
433 return true;
434 }
435 else
436 {
437 lock (m_Cache)
438 {
439 if (m_Cache.Contains("role-" + roleID.ToString()))
440 m_Cache.Remove("role-" + roleID.ToString());
441
442 // also remove these lists, because they will have an outdated role
443 if (m_Cache.Contains("roles-" + groupID.ToString()))
444 m_Cache.Remove("roles-" + groupID.ToString());
445
446 }
447
448 return false;
449 }
450 }
451
452 public void RemoveGroupRole(string RequestingAgentID, UUID groupID, UUID roleID, VoidDelegate d)
453 {
454 d();
455
456 lock (m_Cache)
457 {
458 if (m_Cache.Contains("role-" + roleID.ToString()))
459 m_Cache.Remove("role-" + roleID.ToString());
460
461 // also remove the list, because it will have an removed role
462 if (m_Cache.Contains("roles-" + groupID.ToString()))
463 m_Cache.Remove("roles-" + groupID.ToString());
464
465 if (m_Cache.Contains("roles-" + groupID.ToString() + "-" + RequestingAgentID.ToString()))
466 m_Cache.Remove("roles-" + groupID.ToString() + "-" + RequestingAgentID.ToString());
467
468 if (m_Cache.Contains("rolemembers-" + RequestingAgentID.ToString() + "-" + groupID.ToString()))
469 m_Cache.Remove("rolemembers-" + RequestingAgentID.ToString() + "-" + groupID.ToString());
470 }
471 }
472
473 public List<GroupRolesData> GetGroupRoles(string RequestingAgentID, UUID GroupID, GroupRolesListDelegate d)
474 {
475 object roles = null;
476 bool firstCall = false;
477 string cacheKey = "roles-" + GroupID.ToString();
478
479 while (true)
480 {
481 lock (m_Cache)
482 {
483 if (m_Cache.TryGetValue(cacheKey, out roles))
484 return (List<GroupRolesData>)roles;
485
486 // not cached
487 if (!m_ActiveRequests.ContainsKey(cacheKey))
488 {
489 m_ActiveRequests.Add(cacheKey, true);
490 firstCall = true;
491 }
492 }
493
494 if (firstCall)
495 {
496 roles = d();
497 if (roles != null)
498 {
499 lock (m_Cache)
500 {
501 m_Cache.AddOrUpdate(cacheKey, roles, GROUPS_CACHE_TIMEOUT);
502 m_ActiveRequests.Remove(cacheKey);
503 return (List<GroupRolesData>)roles;
504 }
505 }
506 }
507 else
508 Thread.Sleep(50);
509 }
510 }
511
512 public List<GroupRoleMembersData> GetGroupRoleMembers(string RequestingAgentID, UUID GroupID, RoleMembersListDelegate d)
513 {
514 object rmembers = null;
515 bool firstCall = false;
516 // we need to key in also on the requester, because different ppl have different view privileges
517 string cacheKey = "rolemembers-" + RequestingAgentID.ToString() + "-" + GroupID.ToString();
518
519 //m_log.DebugFormat("[XXX]: GetGroupRoleMembers {0}", cacheKey);
520 while (true)
521 {
522 lock (m_Cache)
523 {
524 if (m_Cache.TryGetValue(cacheKey, out rmembers))
525 {
526 List<ExtendedGroupRoleMembersData> xx = (List<ExtendedGroupRoleMembersData>)rmembers;
527 return xx.ConvertAll<GroupRoleMembersData>(m_ForeignImporter.ConvertGroupRoleMembersData);
528 }
529
530 // not cached
531 if (!m_ActiveRequests.ContainsKey(cacheKey))
532 {
533 m_ActiveRequests.Add(cacheKey, true);
534 firstCall = true;
535 }
536 }
537
538 if (firstCall)
539 {
540 List<ExtendedGroupRoleMembersData> _rmembers = d();
541
542 if (_rmembers != null && _rmembers.Count > 0)
543 rmembers = _rmembers.ConvertAll<GroupRoleMembersData>(new Converter<ExtendedGroupRoleMembersData, GroupRoleMembersData>(m_ForeignImporter.ConvertGroupRoleMembersData));
544 else
545 rmembers = new List<GroupRoleMembersData>();
546
547 lock (m_Cache)
548 {
549 // For some strange reason, when I cache the list of GroupRoleMembersData,
550 // it gets emptied out. The TryGet gets an empty list...
551 //m_Cache.AddOrUpdate(cacheKey, rmembers, GROUPS_CACHE_TIMEOUT);
552 // Caching the list of ExtendedGroupRoleMembersData doesn't show that issue
553 // I don't get it.
554 m_Cache.AddOrUpdate(cacheKey, _rmembers, GROUPS_CACHE_TIMEOUT);
555 m_ActiveRequests.Remove(cacheKey);
556 return (List<GroupRoleMembersData>)rmembers;
557 }
558 }
559 else
560 Thread.Sleep(50);
561 }
562 }
563
564 public void AddAgentToGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID, BooleanDelegate d)
565 {
566 if (d())
567 {
568 lock (m_Cache)
569 {
570 // update the cached role
571 string cacheKey = "role-" + RoleID.ToString();
572 object obj;
573 if (m_Cache.TryGetValue(cacheKey, out obj))
574 {
575 GroupRolesData r = (GroupRolesData)obj;
576 r.Members++;
577 }
578
579 // add this agent to the list of role members
580 cacheKey = "rolemembers-" + RequestingAgentID.ToString() + "-" + GroupID.ToString();
581 if (m_Cache.TryGetValue(cacheKey, out obj))
582 {
583 try
584 {
585 // This may throw an exception, in which case the agentID is not a UUID but a full ID
586 // In that case, let's just remove the whoe things from the cache
587 UUID id = new UUID(AgentID);
588 List<ExtendedGroupRoleMembersData> xx = (List<ExtendedGroupRoleMembersData>)obj;
589 List<GroupRoleMembersData> rmlist = xx.ConvertAll<GroupRoleMembersData>(m_ForeignImporter.ConvertGroupRoleMembersData);
590 GroupRoleMembersData rm = new GroupRoleMembersData();
591 rm.MemberID = id;
592 rm.RoleID = RoleID;
593 rmlist.Add(rm);
594 }
595 catch
596 {
597 m_Cache.Remove(cacheKey);
598 }
599 }
600
601 // Remove the cached info about this agent's roles
602 // because we don't have enough local info about the new role
603 cacheKey = "roles-" + GroupID.ToString() + "-" + AgentID.ToString();
604 if (m_Cache.Contains(cacheKey))
605 m_Cache.Remove(cacheKey);
606
607 }
608 }
609 }
610
611 public void RemoveAgentFromGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID, BooleanDelegate d)
612 {
613 if (d())
614 {
615 lock (m_Cache)
616 {
617 // update the cached role
618 string cacheKey = "role-" + RoleID.ToString();
619 object obj;
620 if (m_Cache.TryGetValue(cacheKey, out obj))
621 {
622 GroupRolesData r = (GroupRolesData)obj;
623 r.Members--;
624 }
625
626 cacheKey = "roles-" + GroupID.ToString() + "-" + AgentID.ToString();
627 if (m_Cache.Contains(cacheKey))
628 m_Cache.Remove(cacheKey);
629
630 cacheKey = "rolemembers-" + RequestingAgentID.ToString() + "-" + GroupID.ToString();
631 if (m_Cache.Contains(cacheKey))
632 m_Cache.Remove(cacheKey);
633 }
634 }
635 }
636
637 public List<GroupRolesData> GetAgentGroupRoles(string RequestingAgentID, string AgentID, UUID GroupID, GroupRolesListDelegate d)
638 {
639 object roles = null;
640 bool firstCall = false;
641 string cacheKey = "roles-" + GroupID.ToString() + "-" + AgentID.ToString();
642
643 //m_log.DebugFormat("[XXX]: GetAgentGroupRoles {0}", cacheKey);
644
645 while (true)
646 {
647 lock (m_Cache)
648 {
649 if (m_Cache.TryGetValue(cacheKey, out roles))
650 {
651 //m_log.DebugFormat("[XXX]: GetAgentGroupRoles {0} cached!", cacheKey);
652 return (List<GroupRolesData>)roles;
653 }
654
655 // not cached
656 if (!m_ActiveRequests.ContainsKey(cacheKey))
657 {
658 m_ActiveRequests.Add(cacheKey, true);
659 firstCall = true;
660 }
661 }
662
663 if (firstCall)
664 {
665 roles = d();
666 lock (m_Cache)
667 {
668 m_Cache.AddOrUpdate(cacheKey, roles, GROUPS_CACHE_TIMEOUT);
669 m_ActiveRequests.Remove(cacheKey);
670 return (List<GroupRolesData>)roles;
671 }
672 }
673 else
674 Thread.Sleep(50);
675 }
676 }
677
678 public void SetAgentActiveGroupRole(string AgentID, UUID GroupID, VoidDelegate d)
679 {
680 d();
681
682 lock (m_Cache)
683 {
684 // Invalidate cached info, because it has ActiveRoleID and Powers
685 string cacheKey = "membership-" + AgentID.ToString() + "-" + GroupID.ToString();
686 if (m_Cache.Contains(cacheKey))
687 m_Cache.Remove(cacheKey);
688
689 cacheKey = "memberships-" + AgentID.ToString();
690 if (m_Cache.Contains(cacheKey))
691 m_Cache.Remove(cacheKey);
692 }
693 }
694
695 public void UpdateMembership(string AgentID, UUID GroupID, bool AcceptNotices, bool ListInProfile, VoidDelegate d)
696 {
697 d();
698
699 lock (m_Cache)
700 {
701 string cacheKey = "membership-" + AgentID.ToString() + "-" + GroupID.ToString();
702 if (m_Cache.Contains(cacheKey))
703 m_Cache.Remove(cacheKey);
704
705 cacheKey = "memberships-" + AgentID.ToString();
706 if (m_Cache.Contains(cacheKey))
707 m_Cache.Remove(cacheKey);
708
709 cacheKey = "active-" + AgentID.ToString();
710 object m = null;
711 if (m_Cache.TryGetValue(cacheKey, out m))
712 {
713 GroupMembershipData membership = (GroupMembershipData)m;
714 membership.ListInProfile = ListInProfile;
715 membership.AcceptNotices = AcceptNotices;
716 }
717 }
718 }
719
720 public bool AddGroupNotice(UUID groupID, UUID noticeID, GroupNoticeInfo notice, BooleanDelegate d)
721 {
722 if (d())
723 {
724 lock (m_Cache)
725 {
726 m_Cache.AddOrUpdate("notice-" + noticeID.ToString(), notice, GROUPS_CACHE_TIMEOUT);
727 string cacheKey = "notices-" + groupID.ToString();
728 if (m_Cache.Contains(cacheKey))
729 m_Cache.Remove(cacheKey);
730
731 }
732
733 return true;
734 }
735
736 return false;
737 }
738
739 public GroupNoticeInfo GetGroupNotice(UUID noticeID, NoticeDelegate d)
740 {
741 object notice = null;
742 bool firstCall = false;
743 string cacheKey = "notice-" + noticeID.ToString();
744
745 //m_log.DebugFormat("[XXX]: GetAgentGroupRoles {0}", cacheKey);
746
747 while (true)
748 {
749 lock (m_Cache)
750 {
751 if (m_Cache.TryGetValue(cacheKey, out notice))
752 {
753 return (GroupNoticeInfo)notice;
754 }
755
756 // not cached
757 if (!m_ActiveRequests.ContainsKey(cacheKey))
758 {
759 m_ActiveRequests.Add(cacheKey, true);
760 firstCall = true;
761 }
762 }
763
764 if (firstCall)
765 {
766 GroupNoticeInfo _notice = d();
767
768 lock (m_Cache)
769 {
770 m_Cache.AddOrUpdate(cacheKey, _notice, GROUPS_CACHE_TIMEOUT);
771 m_ActiveRequests.Remove(cacheKey);
772 return _notice;
773 }
774 }
775 else
776 Thread.Sleep(50);
777 }
778 }
779
780 public List<ExtendedGroupNoticeData> GetGroupNotices(UUID GroupID, NoticeListDelegate d)
781 {
782 object notices = null;
783 bool firstCall = false;
784 string cacheKey = "notices-" + GroupID.ToString();
785
786 //m_log.DebugFormat("[XXX]: GetGroupNotices {0}", cacheKey);
787
788 while (true)
789 {
790 lock (m_Cache)
791 {
792 if (m_Cache.TryGetValue(cacheKey, out notices))
793 {
794 //m_log.DebugFormat("[XXX]: GetGroupNotices {0} cached!", cacheKey);
795 return (List<ExtendedGroupNoticeData>)notices;
796 }
797
798 // not cached
799 if (!m_ActiveRequests.ContainsKey(cacheKey))
800 {
801 m_ActiveRequests.Add(cacheKey, true);
802 firstCall = true;
803 }
804 }
805
806 if (firstCall)
807 {
808 notices = d();
809
810 lock (m_Cache)
811 {
812 m_Cache.AddOrUpdate(cacheKey, notices, GROUPS_CACHE_TIMEOUT);
813 m_ActiveRequests.Remove(cacheKey);
814 return (List<ExtendedGroupNoticeData>)notices;
815 }
816 }
817 else
818 Thread.Sleep(50);
819 }
820 }
821
822
823 }
824}
diff --git a/OpenSim/Addons/Groups/Service/GroupsService.cs b/OpenSim/Addons/Groups/Service/GroupsService.cs
new file mode 100644
index 0000000..fc567dd
--- /dev/null
+++ b/OpenSim/Addons/Groups/Service/GroupsService.cs
@@ -0,0 +1,1014 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Reflection;
31using System.Timers;
32using log4net;
33using Nini.Config;
34
35using OpenMetaverse;
36using OpenSim.Data;
37using OpenSim.Framework;
38using OpenSim.Services.Interfaces;
39
40namespace OpenSim.Groups
41{
42 public class GroupsService : GroupsServiceBase
43 {
44 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
45
46 public const GroupPowers DefaultEveryonePowers = GroupPowers.AllowSetHome |
47 GroupPowers.Accountable |
48 GroupPowers.JoinChat |
49 GroupPowers.AllowVoiceChat |
50 GroupPowers.ReceiveNotices |
51 GroupPowers.StartProposal |
52 GroupPowers.VoteOnProposal;
53
54 public const GroupPowers OwnerPowers = GroupPowers.Accountable |
55 GroupPowers.AllowEditLand |
56 GroupPowers.AllowFly |
57 GroupPowers.AllowLandmark |
58 GroupPowers.AllowRez |
59 GroupPowers.AllowSetHome |
60 GroupPowers.AllowVoiceChat |
61 GroupPowers.AssignMember |
62 GroupPowers.AssignMemberLimited |
63 GroupPowers.ChangeActions |
64 GroupPowers.ChangeIdentity |
65 GroupPowers.ChangeMedia |
66 GroupPowers.ChangeOptions |
67 GroupPowers.CreateRole |
68 GroupPowers.DeedObject |
69 GroupPowers.DeleteRole |
70 GroupPowers.Eject |
71 GroupPowers.FindPlaces |
72 GroupPowers.Invite |
73 GroupPowers.JoinChat |
74 GroupPowers.LandChangeIdentity |
75 GroupPowers.LandDeed |
76 GroupPowers.LandDivideJoin |
77 GroupPowers.LandEdit |
78 GroupPowers.LandEjectAndFreeze |
79 GroupPowers.LandGardening |
80 GroupPowers.LandManageAllowed |
81 GroupPowers.LandManageBanned |
82 GroupPowers.LandManagePasses |
83 GroupPowers.LandOptions |
84 GroupPowers.LandRelease |
85 GroupPowers.LandSetSale |
86 GroupPowers.ModerateChat |
87 GroupPowers.ObjectManipulate |
88 GroupPowers.ObjectSetForSale |
89 GroupPowers.ReceiveNotices |
90 GroupPowers.RemoveMember |
91 GroupPowers.ReturnGroupOwned |
92 GroupPowers.ReturnGroupSet |
93 GroupPowers.ReturnNonGroup |
94 GroupPowers.RoleProperties |
95 GroupPowers.SendNotices |
96 GroupPowers.SetLandingPoint |
97 GroupPowers.StartProposal |
98 GroupPowers.VoteOnProposal;
99
100 #region Daily Cleanup
101
102 private Timer m_CleanupTimer;
103
104 public GroupsService(IConfigSource config, string configName)
105 : base(config, configName)
106 {
107 }
108
109 public GroupsService(IConfigSource config)
110 : this(config, string.Empty)
111 {
112 // Once a day
113 m_CleanupTimer = new Timer(24 * 60 * 60 * 1000);
114 m_CleanupTimer.AutoReset = true;
115 m_CleanupTimer.Elapsed += new ElapsedEventHandler(m_CleanupTimer_Elapsed);
116 m_CleanupTimer.Enabled = true;
117 m_CleanupTimer.Start();
118 }
119
120 private void m_CleanupTimer_Elapsed(object sender, ElapsedEventArgs e)
121 {
122 m_Database.DeleteOldNotices();
123 m_Database.DeleteOldInvites();
124 }
125
126 #endregion
127
128 public UUID CreateGroup(string RequestingAgentID, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment,
129 bool allowPublish, bool maturePublish, UUID founderID, out string reason)
130 {
131 reason = string.Empty;
132
133 // Create the group
134 GroupData data = new GroupData();
135 data.GroupID = UUID.Random();
136 data.Data = new Dictionary<string, string>();
137 data.Data["Name"] = name;
138 data.Data["Charter"] = charter;
139 data.Data["InsigniaID"] = insigniaID.ToString();
140 data.Data["FounderID"] = founderID.ToString();
141 data.Data["MembershipFee"] = membershipFee.ToString();
142 data.Data["OpenEnrollment"] = openEnrollment ? "1" : "0";
143 data.Data["ShowInList"] = showInList ? "1" : "0";
144 data.Data["AllowPublish"] = allowPublish ? "1" : "0";
145 data.Data["MaturePublish"] = maturePublish ? "1" : "0";
146 data.Data["OwnerRoleID"] = UUID.Random().ToString();
147
148 if (!m_Database.StoreGroup(data))
149 return UUID.Zero;
150
151 // Create Everyone role
152 _AddOrUpdateGroupRole(RequestingAgentID, data.GroupID, UUID.Zero, "Everyone", "Everyone in the group", "Member of " + name, (ulong)DefaultEveryonePowers, true);
153
154 // Create Owner role
155 UUID roleID = UUID.Random();
156 _AddOrUpdateGroupRole(RequestingAgentID, data.GroupID, roleID, "Owners", "Owners of the group", "Owner of " + name, (ulong)OwnerPowers, true);
157
158 // Add founder to group
159 _AddAgentToGroup(RequestingAgentID, founderID.ToString(), data.GroupID, roleID);
160
161 return data.GroupID;
162 }
163
164 public void UpdateGroup(string RequestingAgentID, UUID groupID, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, bool allowPublish, bool maturePublish)
165 {
166 GroupData data = m_Database.RetrieveGroup(groupID);
167 if (data == null)
168 return;
169
170 // Check perms
171 if (!HasPower(RequestingAgentID, groupID, GroupPowers.ChangeActions))
172 {
173 m_log.DebugFormat("[Groups]: ({0}) Attempt at updating group {1} denied because of lack of permission", RequestingAgentID, groupID);
174 return;
175 }
176
177 data.GroupID = groupID;
178 data.Data["Charter"] = charter;
179 data.Data["ShowInList"] = showInList ? "1" : "0";
180 data.Data["InsigniaID"] = insigniaID.ToString();
181 data.Data["MembershipFee"] = membershipFee.ToString();
182 data.Data["OpenEnrollment"] = openEnrollment ? "1" : "0";
183 data.Data["AllowPublish"] = allowPublish ? "1" : "0";
184 data.Data["MaturePublish"] = maturePublish ? "1" : "0";
185
186 m_Database.StoreGroup(data);
187
188 }
189
190 public ExtendedGroupRecord GetGroupRecord(string RequestingAgentID, UUID GroupID)
191 {
192 GroupData data = m_Database.RetrieveGroup(GroupID);
193
194 return _GroupDataToRecord(data);
195 }
196
197 public ExtendedGroupRecord GetGroupRecord(string RequestingAgentID, string GroupName)
198 {
199 GroupData data = m_Database.RetrieveGroup(GroupName);
200
201 return _GroupDataToRecord(data);
202 }
203
204 public List<DirGroupsReplyData> FindGroups(string RequestingAgentID, string search)
205 {
206 List<DirGroupsReplyData> groups = new List<DirGroupsReplyData>();
207
208 GroupData[] data = m_Database.RetrieveGroups(search);
209
210 if (data != null && data.Length > 0)
211 {
212 foreach (GroupData d in data)
213 {
214 // Don't list group proxies
215 if (d.Data.ContainsKey("Location") && d.Data["Location"] != string.Empty)
216 continue;
217
218 DirGroupsReplyData g = new DirGroupsReplyData();
219 g.groupID = d.GroupID;
220
221 if (d.Data.ContainsKey("Name"))
222 g.groupName = d.Data["Name"];
223 else
224 m_log.DebugFormat("[Groups]: Key Name not found");
225
226 g.members = m_Database.MemberCount(d.GroupID);
227
228 groups.Add(g);
229 }
230 }
231
232 return groups;
233 }
234
235 public List<ExtendedGroupMembersData> GetGroupMembers(string RequestingAgentID, UUID GroupID)
236 {
237 List<ExtendedGroupMembersData> members = new List<ExtendedGroupMembersData>();
238
239 GroupData group = m_Database.RetrieveGroup(GroupID);
240 if (group == null)
241 return members;
242
243 UUID ownerRoleID = new UUID(group.Data["OwnerRoleID"]);
244
245 RoleData[] roles = m_Database.RetrieveRoles(GroupID);
246 if (roles == null)
247 // something wrong with this group
248 return members;
249 List<RoleData> rolesList = new List<RoleData>(roles);
250
251 // Is the requester a member of the group?
252 bool isInGroup = false;
253 if (m_Database.RetrieveMember(GroupID, RequestingAgentID) != null)
254 isInGroup = true;
255
256 if (!isInGroup) // reduce the roles to the visible ones
257 rolesList = rolesList.FindAll(r => (UInt64.Parse(r.Data["Powers"]) & (ulong)GroupPowers.MemberVisible) != 0);
258
259 MembershipData[] datas = m_Database.RetrieveMembers(GroupID);
260 if (datas == null || (datas != null && datas.Length == 0))
261 return members;
262
263 // OK, we have everything we need
264
265 foreach (MembershipData d in datas)
266 {
267 RoleMembershipData[] rolememberships = m_Database.RetrieveMemberRoles(GroupID, d.PrincipalID);
268 List<RoleMembershipData> rolemembershipsList = new List<RoleMembershipData>(rolememberships);
269
270 ExtendedGroupMembersData m = new ExtendedGroupMembersData();
271
272 // What's this person's current role in the group?
273 UUID selectedRole = new UUID(d.Data["SelectedRoleID"]);
274 RoleData selected = rolesList.Find(r => r.RoleID == selectedRole);
275
276 if (selected != null)
277 {
278 m.Title = selected.Data["Title"];
279 m.AgentPowers = UInt64.Parse(selected.Data["Powers"]);
280
281 m.AgentID = d.PrincipalID;
282 m.AcceptNotices = d.Data["AcceptNotices"] == "1" ? true : false;
283 m.Contribution = Int32.Parse(d.Data["Contribution"]);
284 m.ListInProfile = d.Data["ListInProfile"] == "1" ? true : false;
285
286 // Is this person an owner of the group?
287 m.IsOwner = (rolemembershipsList.Find(r => r.RoleID == ownerRoleID) != null) ? true : false;
288
289 members.Add(m);
290 }
291 }
292
293 return members;
294 }
295
296 public bool AddGroupRole(string RequestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers, out string reason)
297 {
298 reason = string.Empty;
299 // check that the requesting agent has permissions to add role
300 if (!HasPower(RequestingAgentID, groupID, GroupPowers.CreateRole))
301 {
302 m_log.DebugFormat("[Groups]: ({0}) Attempt at creating role in group {1} denied because of lack of permission", RequestingAgentID, groupID);
303 reason = "Insufficient permission to create role";
304 return false;
305 }
306
307 return _AddOrUpdateGroupRole(RequestingAgentID, groupID, roleID, name, description, title, powers, true);
308
309 }
310
311 public bool UpdateGroupRole(string RequestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers)
312 {
313 // check perms
314 if (!HasPower(RequestingAgentID, groupID, GroupPowers.ChangeActions))
315 {
316 m_log.DebugFormat("[Groups]: ({0}) Attempt at changing role in group {1} denied because of lack of permission", RequestingAgentID, groupID);
317 return false;
318 }
319
320 return _AddOrUpdateGroupRole(RequestingAgentID, groupID, roleID, name, description, title, powers, false);
321 }
322
323 public void RemoveGroupRole(string RequestingAgentID, UUID groupID, UUID roleID)
324 {
325 // check perms
326 if (!HasPower(RequestingAgentID, groupID, GroupPowers.DeleteRole))
327 {
328 m_log.DebugFormat("[Groups]: ({0}) Attempt at deleting role from group {1} denied because of lack of permission", RequestingAgentID, groupID);
329 return;
330 }
331
332 // Can't delete Everyone and Owners roles
333 if (roleID == UUID.Zero)
334 {
335 m_log.DebugFormat("[Groups]: Attempt at deleting Everyone role from group {0} denied", groupID);
336 return;
337 }
338
339 GroupData group = m_Database.RetrieveGroup(groupID);
340 if (group == null)
341 {
342 m_log.DebugFormat("[Groups]: Attempt at deleting role from non-existing group {0}", groupID);
343 return;
344 }
345
346 if (roleID == new UUID(group.Data["OwnerRoleID"]))
347 {
348 m_log.DebugFormat("[Groups]: Attempt at deleting Owners role from group {0} denied", groupID);
349 return;
350 }
351
352 _RemoveGroupRole(groupID, roleID);
353 }
354
355 public List<GroupRolesData> GetGroupRoles(string RequestingAgentID, UUID GroupID)
356 {
357 // TODO: check perms
358 return _GetGroupRoles(GroupID);
359 }
360
361 public List<ExtendedGroupRoleMembersData> GetGroupRoleMembers(string RequestingAgentID, UUID GroupID)
362 {
363 // TODO: check perms
364
365 // Is the requester a member of the group?
366 bool isInGroup = false;
367 if (m_Database.RetrieveMember(GroupID, RequestingAgentID) != null)
368 isInGroup = true;
369
370 return _GetGroupRoleMembers(GroupID, isInGroup);
371 }
372
373 public bool AddAgentToGroup(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID, string token, out string reason)
374 {
375 reason = string.Empty;
376
377 _AddAgentToGroup(RequestingAgentID, AgentID, GroupID, RoleID, token);
378
379 return true;
380 }
381
382 public void RemoveAgentFromGroup(string RequestingAgentID, string AgentID, UUID GroupID)
383 {
384 // check perms
385 if (RequestingAgentID != AgentID && !HasPower(RequestingAgentID, GroupID, GroupPowers.Eject))
386 return;
387
388 _RemoveAgentFromGroup(RequestingAgentID, AgentID, GroupID);
389 }
390
391 public bool AddAgentToGroupInvite(string RequestingAgentID, UUID inviteID, UUID groupID, UUID roleID, string agentID)
392 {
393 // Check whether the invitee is already a member of the group
394 MembershipData m = m_Database.RetrieveMember(groupID, agentID);
395 if (m != null)
396 return false;
397
398 // Check permission to invite
399 if (!HasPower(RequestingAgentID, groupID, GroupPowers.Invite))
400 {
401 m_log.DebugFormat("[Groups]: ({0}) Attempt at inviting to group {1} denied because of lack of permission", RequestingAgentID, groupID);
402 return false;
403 }
404
405 // Check whether there are pending invitations and delete them
406 InvitationData invite = m_Database.RetrieveInvitation(groupID, agentID);
407 if (invite != null)
408 m_Database.DeleteInvite(invite.InviteID);
409
410 invite = new InvitationData();
411 invite.InviteID = inviteID;
412 invite.PrincipalID = agentID;
413 invite.GroupID = groupID;
414 invite.RoleID = roleID;
415 invite.Data = new Dictionary<string, string>();
416
417 return m_Database.StoreInvitation(invite);
418 }
419
420 public GroupInviteInfo GetAgentToGroupInvite(string RequestingAgentID, UUID inviteID)
421 {
422 InvitationData data = m_Database.RetrieveInvitation(inviteID);
423
424 if (data == null)
425 return null;
426
427 GroupInviteInfo inviteInfo = new GroupInviteInfo();
428 inviteInfo.AgentID = data.PrincipalID;
429 inviteInfo.GroupID = data.GroupID;
430 inviteInfo.InviteID = data.InviteID;
431 inviteInfo.RoleID = data.RoleID;
432
433 return inviteInfo;
434 }
435
436 public void RemoveAgentToGroupInvite(string RequestingAgentID, UUID inviteID)
437 {
438 m_Database.DeleteInvite(inviteID);
439 }
440
441 public bool AddAgentToGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID)
442 {
443 //if (!m_Database.CheckOwnerRole(RequestingAgentID, GroupID, RoleID))
444 // return;
445
446 // check permissions
447 bool limited = HasPower(RequestingAgentID, GroupID, GroupPowers.AssignMemberLimited);
448 bool unlimited = HasPower(RequestingAgentID, GroupID, GroupPowers.AssignMember) | IsOwner(RequestingAgentID, GroupID);
449 if (!limited || !unlimited)
450 {
451 m_log.DebugFormat("[Groups]: ({0}) Attempt at assigning {1} to role {2} denied because of lack of permission", RequestingAgentID, AgentID, RoleID);
452 return false;
453 }
454
455 // AssignMemberLimited means that the person can assign another person to the same roles that she has in the group
456 if (!unlimited && limited)
457 {
458 // check whether person's has this role
459 RoleMembershipData rolemembership = m_Database.RetrieveRoleMember(GroupID, RoleID, AgentID);
460 if (rolemembership == null)
461 {
462 m_log.DebugFormat("[Groups]: ({0}) Attempt at assigning {1} to role {2} denied because of limited permission", RequestingAgentID, AgentID, RoleID);
463 return false;
464 }
465 }
466
467 _AddAgentToGroupRole(RequestingAgentID, AgentID, GroupID, RoleID);
468
469 return true;
470 }
471
472 public bool RemoveAgentFromGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID)
473 {
474 // Don't remove from Everyone role!
475 if (RoleID == UUID.Zero)
476 return false;
477
478 // check permissions
479 bool unlimited = HasPower(RequestingAgentID, GroupID, GroupPowers.AssignMember) || IsOwner(RequestingAgentID, GroupID);
480 if (!unlimited)
481 {
482 m_log.DebugFormat("[Groups]: ({0}) Attempt at removing {1} from role {2} denied because of lack of permission", RequestingAgentID, AgentID, RoleID);
483 return false;
484 }
485
486 RoleMembershipData rolemember = m_Database.RetrieveRoleMember(GroupID, RoleID, AgentID);
487
488 if (rolemember == null)
489 return false;
490
491 m_Database.DeleteRoleMember(rolemember);
492
493 // Find another role for this person
494 UUID newRoleID = UUID.Zero; // Everyone
495 RoleMembershipData[] rdata = m_Database.RetrieveMemberRoles(GroupID, AgentID);
496 if (rdata != null)
497 foreach (RoleMembershipData r in rdata)
498 {
499 if (r.RoleID != UUID.Zero)
500 {
501 newRoleID = r.RoleID;
502 break;
503 }
504 }
505
506 MembershipData member = m_Database.RetrieveMember(GroupID, AgentID);
507 if (member != null)
508 {
509 member.Data["SelectedRoleID"] = newRoleID.ToString();
510 m_Database.StoreMember(member);
511 }
512
513 return true;
514 }
515
516 public List<GroupRolesData> GetAgentGroupRoles(string RequestingAgentID, string AgentID, UUID GroupID)
517 {
518 List<GroupRolesData> roles = new List<GroupRolesData>();
519 // TODO: check permissions
520
521 RoleMembershipData[] data = m_Database.RetrieveMemberRoles(GroupID, AgentID);
522 if (data == null || (data != null && data.Length ==0))
523 return roles;
524
525 foreach (RoleMembershipData d in data)
526 {
527 RoleData rdata = m_Database.RetrieveRole(GroupID, d.RoleID);
528 if (rdata == null) // hippos
529 continue;
530
531 GroupRolesData r = new GroupRolesData();
532 r.Name = rdata.Data["Name"];
533 r.Powers = UInt64.Parse(rdata.Data["Powers"]);
534 r.RoleID = rdata.RoleID;
535 r.Title = rdata.Data["Title"];
536
537 roles.Add(r);
538 }
539
540 return roles;
541 }
542
543 public ExtendedGroupMembershipData SetAgentActiveGroup(string RequestingAgentID, string AgentID, UUID GroupID)
544 {
545 // TODO: check perms
546 PrincipalData principal = new PrincipalData();
547 principal.PrincipalID = AgentID;
548 principal.ActiveGroupID = GroupID;
549 m_Database.StorePrincipal(principal);
550
551 return GetAgentGroupMembership(RequestingAgentID, AgentID, GroupID);
552 }
553
554 public ExtendedGroupMembershipData GetAgentActiveMembership(string RequestingAgentID, string AgentID)
555 {
556 // 1. get the principal data for the active group
557 PrincipalData principal = m_Database.RetrievePrincipal(AgentID);
558 if (principal == null)
559 return null;
560
561 return GetAgentGroupMembership(RequestingAgentID, AgentID, principal.ActiveGroupID);
562 }
563
564 public ExtendedGroupMembershipData GetAgentGroupMembership(string RequestingAgentID, string AgentID, UUID GroupID)
565 {
566 return GetAgentGroupMembership(RequestingAgentID, AgentID, GroupID, null);
567 }
568
569 private ExtendedGroupMembershipData GetAgentGroupMembership(string RequestingAgentID, string AgentID, UUID GroupID, MembershipData membership)
570 {
571 // 2. get the active group
572 GroupData group = m_Database.RetrieveGroup(GroupID);
573 if (group == null)
574 return null;
575
576 // 3. get the membership info if we don't have it already
577 if (membership == null)
578 {
579 membership = m_Database.RetrieveMember(group.GroupID, AgentID);
580 if (membership == null)
581 return null;
582 }
583
584 // 4. get the active role
585 UUID activeRoleID = new UUID(membership.Data["SelectedRoleID"]);
586 RoleData role = m_Database.RetrieveRole(group.GroupID, activeRoleID);
587
588 ExtendedGroupMembershipData data = new ExtendedGroupMembershipData();
589 data.AcceptNotices = membership.Data["AcceptNotices"] == "1" ? true : false;
590 data.AccessToken = membership.Data["AccessToken"];
591 data.Active = true;
592 data.ActiveRole = activeRoleID;
593 data.AllowPublish = group.Data["AllowPublish"] == "1" ? true : false;
594 data.Charter = group.Data["Charter"];
595 data.Contribution = Int32.Parse(membership.Data["Contribution"]);
596 data.FounderID = new UUID(group.Data["FounderID"]);
597 data.GroupID = new UUID(group.GroupID);
598 data.GroupName = group.Data["Name"];
599 data.GroupPicture = new UUID(group.Data["InsigniaID"]);
600 if (role != null)
601 {
602 data.GroupPowers = UInt64.Parse(role.Data["Powers"]);
603 data.GroupTitle = role.Data["Title"];
604 }
605 data.ListInProfile = membership.Data["ListInProfile"] == "1" ? true : false;
606 data.MaturePublish = group.Data["MaturePublish"] == "1" ? true : false;
607 data.MembershipFee = Int32.Parse(group.Data["MembershipFee"]);
608 data.OpenEnrollment = group.Data["OpenEnrollment"] == "1" ? true : false;
609 data.ShowInList = group.Data["ShowInList"] == "1" ? true : false;
610
611 return data;
612 }
613
614 public List<GroupMembershipData> GetAgentGroupMemberships(string RequestingAgentID, string AgentID)
615 {
616 List<GroupMembershipData> memberships = new List<GroupMembershipData>();
617
618 // 1. Get all the groups that this person is a member of
619 MembershipData[] mdata = m_Database.RetrieveMemberships(AgentID);
620
621 if (mdata == null || (mdata != null && mdata.Length == 0))
622 return memberships;
623
624 foreach (MembershipData d in mdata)
625 {
626 GroupMembershipData gmember = GetAgentGroupMembership(RequestingAgentID, AgentID, d.GroupID, d);
627 if (gmember != null)
628 {
629 memberships.Add(gmember);
630 //m_log.DebugFormat("[XXX]: Member of {0} as {1}", gmember.GroupName, gmember.GroupTitle);
631 //Util.PrintCallStack();
632 }
633 }
634
635 return memberships;
636 }
637
638 public void SetAgentActiveGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID)
639 {
640 MembershipData data = m_Database.RetrieveMember(GroupID, AgentID);
641 if (data == null)
642 return;
643
644 data.Data["SelectedRoleID"] = RoleID.ToString();
645 m_Database.StoreMember(data);
646 }
647
648 public void UpdateMembership(string RequestingAgentID, string AgentID, UUID GroupID, bool AcceptNotices, bool ListInProfile)
649 {
650 // TODO: check perms
651
652 MembershipData membership = m_Database.RetrieveMember(GroupID, AgentID);
653 if (membership == null)
654 return;
655
656 membership.Data["AcceptNotices"] = AcceptNotices ? "1" : "0";
657 membership.Data["ListInProfile"] = ListInProfile ? "1" : "0";
658
659 m_Database.StoreMember(membership);
660 }
661
662 public bool AddGroupNotice(string RequestingAgentID, UUID groupID, UUID noticeID, string fromName, string subject, string message,
663 bool hasAttachment, byte attType, string attName, UUID attItemID, string attOwnerID)
664 {
665 // Check perms
666 if (!HasPower(RequestingAgentID, groupID, GroupPowers.SendNotices))
667 {
668 m_log.DebugFormat("[Groups]: ({0}) Attempt at sending notice to group {1} denied because of lack of permission", RequestingAgentID, groupID);
669 return false;
670 }
671
672 return _AddNotice(groupID, noticeID, fromName, subject, message, hasAttachment, attType, attName, attItemID, attOwnerID);
673 }
674
675 public GroupNoticeInfo GetGroupNotice(string RequestingAgentID, UUID noticeID)
676 {
677 NoticeData data = m_Database.RetrieveNotice(noticeID);
678
679 if (data == null)
680 return null;
681
682 return _NoticeDataToInfo(data);
683 }
684
685 public List<ExtendedGroupNoticeData> GetGroupNotices(string RequestingAgentID, UUID groupID)
686 {
687 NoticeData[] data = m_Database.RetrieveNotices(groupID);
688 List<ExtendedGroupNoticeData> infos = new List<ExtendedGroupNoticeData>();
689
690 if (data == null || (data != null && data.Length == 0))
691 return infos;
692
693 foreach (NoticeData d in data)
694 {
695 ExtendedGroupNoticeData info = _NoticeDataToData(d);
696 infos.Add(info);
697 }
698
699 return infos;
700 }
701
702 public void ResetAgentGroupChatSessions(string agentID)
703 {
704 }
705
706 public bool hasAgentBeenInvitedToGroupChatSession(string agentID, UUID groupID)
707 {
708 return false;
709 }
710
711 public bool hasAgentDroppedGroupChatSession(string agentID, UUID groupID)
712 {
713 return false;
714 }
715
716 public void AgentDroppedFromGroupChatSession(string agentID, UUID groupID)
717 {
718 }
719
720 public void AgentInvitedToGroupChatSession(string agentID, UUID groupID)
721 {
722 }
723
724 #region Actions without permission checks
725
726 private void _AddAgentToGroup(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID)
727 {
728 _AddAgentToGroup(RequestingAgentID, AgentID, GroupID, RoleID, string.Empty);
729 }
730
731 public void _RemoveAgentFromGroup(string RequestingAgentID, string AgentID, UUID GroupID)
732 {
733 // 1. Delete membership
734 m_Database.DeleteMember(GroupID, AgentID);
735
736 // 2. Remove from rolememberships
737 m_Database.DeleteMemberAllRoles(GroupID, AgentID);
738
739 // 3. if it was active group, inactivate it
740 PrincipalData principal = m_Database.RetrievePrincipal(AgentID);
741 if (principal != null && principal.ActiveGroupID == GroupID)
742 {
743 principal.ActiveGroupID = UUID.Zero;
744 m_Database.StorePrincipal(principal);
745 }
746 }
747
748 protected void _AddAgentToGroup(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID, string accessToken)
749 {
750 // Check if it's already there
751 MembershipData data = m_Database.RetrieveMember(GroupID, AgentID);
752 if (data != null)
753 return;
754
755 // Add the membership
756 data = new MembershipData();
757 data.PrincipalID = AgentID;
758 data.GroupID = GroupID;
759 data.Data = new Dictionary<string, string>();
760 data.Data["SelectedRoleID"] = RoleID.ToString();
761 data.Data["Contribution"] = "0";
762 data.Data["ListInProfile"] = "1";
763 data.Data["AcceptNotices"] = "1";
764 data.Data["AccessToken"] = accessToken;
765
766 m_Database.StoreMember(data);
767
768 // Add principal to everyone role
769 _AddAgentToGroupRole(RequestingAgentID, AgentID, GroupID, UUID.Zero);
770
771 // Add principal to role, if different from everyone role
772 if (RoleID != UUID.Zero)
773 _AddAgentToGroupRole(RequestingAgentID, AgentID, GroupID, RoleID);
774
775 // Make thit this active group
776 PrincipalData pdata = new PrincipalData();
777 pdata.PrincipalID = AgentID;
778 pdata.ActiveGroupID = GroupID;
779 m_Database.StorePrincipal(pdata);
780
781 }
782
783 private bool _AddOrUpdateGroupRole(string RequestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers, bool add)
784 {
785 RoleData data = m_Database.RetrieveRole(groupID, roleID);
786
787 if (add && data != null) // it already exists, can't create
788 return false;
789
790 if (!add && data == null) // it deosn't exist, can't update
791 return false;
792
793 if (add)
794 data = new RoleData();
795
796 data.GroupID = groupID;
797 data.RoleID = roleID;
798 data.Data = new Dictionary<string, string>();
799 data.Data["Name"] = name;
800 data.Data["Description"] = description;
801 data.Data["Title"] = title;
802 data.Data["Powers"] = powers.ToString();
803
804 return m_Database.StoreRole(data);
805 }
806
807 private void _RemoveGroupRole(UUID groupID, UUID roleID)
808 {
809 m_Database.DeleteRole(groupID, roleID);
810 }
811
812 private void _AddAgentToGroupRole(string RequestingAgentID, string AgentID, UUID GroupID, UUID RoleID)
813 {
814 RoleMembershipData data = m_Database.RetrieveRoleMember(GroupID, RoleID, AgentID);
815 if (data != null)
816 return;
817
818 data = new RoleMembershipData();
819 data.GroupID = GroupID;
820 data.PrincipalID = AgentID;
821 data.RoleID = RoleID;
822 m_Database.StoreRoleMember(data);
823
824 // Make it the SelectedRoleID
825 MembershipData membership = m_Database.RetrieveMember(GroupID, AgentID);
826 if (membership == null)
827 {
828 m_log.DebugFormat("[Groups]: ({0}) No such member {0} in group {1}", AgentID, GroupID);
829 return;
830 }
831
832 membership.Data["SelectedRoleID"] = RoleID.ToString();
833 m_Database.StoreMember(membership);
834
835 }
836
837 private List<GroupRolesData> _GetGroupRoles(UUID groupID)
838 {
839 List<GroupRolesData> roles = new List<GroupRolesData>();
840
841 RoleData[] data = m_Database.RetrieveRoles(groupID);
842
843 if (data == null || (data != null && data.Length == 0))
844 return roles;
845
846 foreach (RoleData d in data)
847 {
848 GroupRolesData r = new GroupRolesData();
849 r.Description = d.Data["Description"];
850 r.Members = m_Database.RoleMemberCount(groupID, d.RoleID);
851 r.Name = d.Data["Name"];
852 r.Powers = UInt64.Parse(d.Data["Powers"]);
853 r.RoleID = d.RoleID;
854 r.Title = d.Data["Title"];
855
856 roles.Add(r);
857 }
858
859 return roles;
860 }
861
862 private List<ExtendedGroupRoleMembersData> _GetGroupRoleMembers(UUID GroupID, bool isInGroup)
863 {
864 List<ExtendedGroupRoleMembersData> rmembers = new List<ExtendedGroupRoleMembersData>();
865
866 RoleData[] rdata = new RoleData[0];
867 if (!isInGroup)
868 {
869 rdata = m_Database.RetrieveRoles(GroupID);
870 if (rdata == null || (rdata != null && rdata.Length == 0))
871 return rmembers;
872 }
873 List<RoleData> rlist = new List<RoleData>(rdata);
874 if (!isInGroup)
875 rlist = rlist.FindAll(r => (UInt64.Parse(r.Data["Powers"]) & (ulong)GroupPowers.MemberVisible) != 0);
876
877 RoleMembershipData[] data = m_Database.RetrieveRolesMembers(GroupID);
878
879 if (data == null || (data != null && data.Length == 0))
880 return rmembers;
881
882 foreach (RoleMembershipData d in data)
883 {
884 if (!isInGroup)
885 {
886 RoleData rd = rlist.Find(_r => _r.RoleID == d.RoleID); // visible role
887 if (rd == null)
888 continue;
889 }
890
891 ExtendedGroupRoleMembersData r = new ExtendedGroupRoleMembersData();
892 r.MemberID = d.PrincipalID;
893 r.RoleID = d.RoleID;
894
895 rmembers.Add(r);
896 }
897
898 return rmembers;
899 }
900
901 protected bool _AddNotice(UUID groupID, UUID noticeID, string fromName, string subject, string message,
902 bool hasAttachment, byte attType, string attName, UUID attItemID, string attOwnerID)
903 {
904 NoticeData data = new NoticeData();
905 data.GroupID = groupID;
906 data.NoticeID = noticeID;
907 data.Data = new Dictionary<string, string>();
908 data.Data["FromName"] = fromName;
909 data.Data["Subject"] = subject;
910 data.Data["Message"] = message;
911 data.Data["HasAttachment"] = hasAttachment ? "1" : "0";
912 if (hasAttachment)
913 {
914 data.Data["AttachmentType"] = attType.ToString();
915 data.Data["AttachmentName"] = attName;
916 data.Data["AttachmentItemID"] = attItemID.ToString();
917 data.Data["AttachmentOwnerID"] = attOwnerID;
918 }
919 data.Data["TMStamp"] = ((uint)Util.UnixTimeSinceEpoch()).ToString();
920
921 return m_Database.StoreNotice(data);
922 }
923
924 #endregion
925
926 #region structure translations
927 ExtendedGroupRecord _GroupDataToRecord(GroupData data)
928 {
929 if (data == null)
930 return null;
931
932 ExtendedGroupRecord rec = new ExtendedGroupRecord();
933 rec.AllowPublish = data.Data["AllowPublish"] == "1" ? true : false;
934 rec.Charter = data.Data["Charter"];
935 rec.FounderID = new UUID(data.Data["FounderID"]);
936 rec.GroupID = data.GroupID;
937 rec.GroupName = data.Data["Name"];
938 rec.GroupPicture = new UUID(data.Data["InsigniaID"]);
939 rec.MaturePublish = data.Data["MaturePublish"] == "1" ? true : false;
940 rec.MembershipFee = Int32.Parse(data.Data["MembershipFee"]);
941 rec.OpenEnrollment = data.Data["OpenEnrollment"] == "1" ? true : false;
942 rec.OwnerRoleID = new UUID(data.Data["OwnerRoleID"]);
943 rec.ShowInList = data.Data["ShowInList"] == "1" ? true : false;
944 rec.ServiceLocation = data.Data["Location"];
945 rec.MemberCount = m_Database.MemberCount(data.GroupID);
946 rec.RoleCount = m_Database.RoleCount(data.GroupID);
947
948 return rec;
949 }
950
951 GroupNoticeInfo _NoticeDataToInfo(NoticeData data)
952 {
953 GroupNoticeInfo notice = new GroupNoticeInfo();
954 notice.GroupID = data.GroupID;
955 notice.Message = data.Data["Message"];
956 notice.noticeData = _NoticeDataToData(data);
957
958 return notice;
959 }
960
961 ExtendedGroupNoticeData _NoticeDataToData(NoticeData data)
962 {
963 ExtendedGroupNoticeData notice = new ExtendedGroupNoticeData();
964 notice.FromName = data.Data["FromName"];
965 notice.NoticeID = data.NoticeID;
966 notice.Subject = data.Data["Subject"];
967 notice.Timestamp = uint.Parse((string)data.Data["TMStamp"]);
968 notice.HasAttachment = data.Data["HasAttachment"] == "1" ? true : false;
969 if (notice.HasAttachment)
970 {
971 notice.AttachmentName = data.Data["AttachmentName"];
972 notice.AttachmentItemID = new UUID(data.Data["AttachmentItemID"].ToString());
973 notice.AttachmentType = byte.Parse(data.Data["AttachmentType"].ToString());
974 notice.AttachmentOwnerID = data.Data["AttachmentOwnerID"].ToString();
975 }
976
977
978 return notice;
979 }
980
981 #endregion
982
983 #region permissions
984 private bool HasPower(string agentID, UUID groupID, GroupPowers power)
985 {
986 RoleMembershipData[] rmembership = m_Database.RetrieveMemberRoles(groupID, agentID);
987 if (rmembership == null || (rmembership != null && rmembership.Length == 0))
988 return false;
989
990 foreach (RoleMembershipData rdata in rmembership)
991 {
992 RoleData role = m_Database.RetrieveRole(groupID, rdata.RoleID);
993 if ( (UInt64.Parse(role.Data["Powers"]) & (ulong)power) != 0 )
994 return true;
995 }
996 return false;
997 }
998
999 private bool IsOwner(string agentID, UUID groupID)
1000 {
1001 GroupData group = m_Database.RetrieveGroup(groupID);
1002 if (group == null)
1003 return false;
1004
1005 RoleMembershipData rmembership = m_Database.RetrieveRoleMember(groupID, new UUID(group.Data["OwnerRoleID"]), agentID);
1006 if (rmembership == null)
1007 return false;
1008
1009 return true;
1010 }
1011 #endregion
1012
1013 }
1014}
diff --git a/OpenSim/Addons/Groups/Service/GroupsServiceBase.cs b/OpenSim/Addons/Groups/Service/GroupsServiceBase.cs
new file mode 100644
index 0000000..2611a3d
--- /dev/null
+++ b/OpenSim/Addons/Groups/Service/GroupsServiceBase.cs
@@ -0,0 +1,84 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Reflection;
30using Nini.Config;
31using OpenSim.Framework;
32using OpenSim.Data;
33using OpenSim.Services.Interfaces;
34using OpenSim.Services.Base;
35
36namespace OpenSim.Groups
37{
38 public class GroupsServiceBase : ServiceBase
39 {
40 protected IGroupsData m_Database = null;
41
42 public GroupsServiceBase(IConfigSource config, string cName)
43 : base(config)
44 {
45 string dllName = String.Empty;
46 string connString = String.Empty;
47 string realm = "os_groups";
48 string configName = (cName == string.Empty) ? "Groups" : cName;
49
50 //
51 // Try reading the [DatabaseService] section, if it exists
52 //
53 IConfig dbConfig = config.Configs["DatabaseService"];
54 if (dbConfig != null)
55 {
56 if (dllName == String.Empty)
57 dllName = dbConfig.GetString("StorageProvider", String.Empty);
58 if (connString == String.Empty)
59 connString = dbConfig.GetString("ConnectionString", String.Empty);
60 }
61
62 //
63 // [Groups] section overrides [DatabaseService], if it exists
64 //
65 IConfig groupsConfig = config.Configs[configName];
66 if (groupsConfig != null)
67 {
68 dllName = groupsConfig.GetString("StorageProvider", dllName);
69 connString = groupsConfig.GetString("ConnectionString", connString);
70 realm = groupsConfig.GetString("Realm", realm);
71 }
72
73 //
74 // We tried, but this doesn't exist. We can't proceed.
75 //
76 if (dllName.Equals(String.Empty))
77 throw new Exception("No StorageProvider configured");
78
79 m_Database = LoadPlugin<IGroupsData>(dllName, new Object[] { connString, realm });
80 if (m_Database == null)
81 throw new Exception("Could not find a storage interface in the given module " + dllName);
82 }
83 }
84} \ No newline at end of file
diff --git a/OpenSim/Addons/Groups/Service/HGGroupsService.cs b/OpenSim/Addons/Groups/Service/HGGroupsService.cs
new file mode 100644
index 0000000..9d7961c
--- /dev/null
+++ b/OpenSim/Addons/Groups/Service/HGGroupsService.cs
@@ -0,0 +1,353 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Reflection;
31using System.Timers;
32using log4net;
33using Nini.Config;
34
35using OpenMetaverse;
36using OpenSim.Data;
37using OpenSim.Framework;
38using OpenSim.Services.Interfaces;
39
40namespace OpenSim.Groups
41{
42 public class HGGroupsService : GroupsService
43 {
44 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
45
46 private IOfflineIMService m_OfflineIM;
47 private IUserAccountService m_UserAccounts;
48 private string m_HomeURI;
49
50 public HGGroupsService(IConfigSource config, IOfflineIMService im, IUserAccountService users, string homeURI)
51 : base(config, string.Empty)
52 {
53 m_OfflineIM = im;
54 m_UserAccounts = users;
55 m_HomeURI = homeURI;
56 if (!m_HomeURI.EndsWith("/"))
57 m_HomeURI += "/";
58 }
59
60
61 #region HG specific operations
62
63 public bool CreateGroupProxy(string RequestingAgentID, string agentID, string accessToken, UUID groupID, string serviceLocation, string name, out string reason)
64 {
65 reason = string.Empty;
66 Uri uri = null;
67 try
68 {
69 uri = new Uri(serviceLocation);
70 }
71 catch (UriFormatException)
72 {
73 reason = "Bad location for group proxy";
74 return false;
75 }
76
77 // Check if it already exists
78 GroupData grec = m_Database.RetrieveGroup(groupID);
79 if (grec == null ||
80 (grec != null && grec.Data["Location"] != string.Empty && grec.Data["Location"].ToLower() != serviceLocation.ToLower()))
81 {
82 // Create the group
83 grec = new GroupData();
84 grec.GroupID = groupID;
85 grec.Data = new Dictionary<string, string>();
86 grec.Data["Name"] = name + " @ " + uri.Authority;
87 grec.Data["Location"] = serviceLocation;
88 grec.Data["Charter"] = string.Empty;
89 grec.Data["InsigniaID"] = UUID.Zero.ToString();
90 grec.Data["FounderID"] = UUID.Zero.ToString();
91 grec.Data["MembershipFee"] = "0";
92 grec.Data["OpenEnrollment"] = "0";
93 grec.Data["ShowInList"] = "0";
94 grec.Data["AllowPublish"] = "0";
95 grec.Data["MaturePublish"] = "0";
96 grec.Data["OwnerRoleID"] = UUID.Zero.ToString();
97
98
99 if (!m_Database.StoreGroup(grec))
100 return false;
101 }
102
103 if (grec.Data["Location"] == string.Empty)
104 {
105 reason = "Cannot add proxy membership to non-proxy group";
106 return false;
107 }
108
109 UUID uid = UUID.Zero;
110 string url = string.Empty, first = string.Empty, last = string.Empty, tmp = string.Empty;
111 Util.ParseUniversalUserIdentifier(RequestingAgentID, out uid, out url, out first, out last, out tmp);
112 string fromName = first + "." + last + "@" + url;
113
114 // Invite to group again
115 InviteToGroup(fromName, groupID, new UUID(agentID), grec.Data["Name"]);
116
117 // Stick the proxy membership in the DB already
118 // we'll delete it if the agent declines the invitation
119 MembershipData membership = new MembershipData();
120 membership.PrincipalID = agentID;
121 membership.GroupID = groupID;
122 membership.Data = new Dictionary<string, string>();
123 membership.Data["SelectedRoleID"] = UUID.Zero.ToString();
124 membership.Data["Contribution"] = "0";
125 membership.Data["ListInProfile"] = "1";
126 membership.Data["AcceptNotices"] = "1";
127 membership.Data["AccessToken"] = accessToken;
128
129 m_Database.StoreMember(membership);
130
131 return true;
132 }
133
134 public void RemoveAgentFromGroup(string RequestingAgentID, string AgentID, UUID GroupID, string token)
135 {
136 // check the token
137 MembershipData membership = m_Database.RetrieveMember(GroupID, AgentID);
138 if (membership != null)
139 {
140 if (token != string.Empty && token.Equals(membership.Data["AccessToken"]))
141 RemoveAgentFromGroup(RequestingAgentID, AgentID, GroupID);
142 else
143 m_log.DebugFormat("[Groups.HGGroupsService]: access token {0} did not match stored one {1}", token, membership.Data["AccessToken"]);
144 }
145 else
146 m_log.DebugFormat("[Groups.HGGroupsService]: membership not found for {0}", AgentID);
147 }
148
149 public ExtendedGroupRecord GetGroupRecord(string RequestingAgentID, UUID GroupID, string groupName, string token)
150 {
151 // check the token
152 if (!VerifyToken(GroupID, RequestingAgentID, token))
153 return null;
154
155 ExtendedGroupRecord grec;
156 if (GroupID == UUID.Zero)
157 grec = GetGroupRecord(RequestingAgentID, groupName);
158 else
159 grec = GetGroupRecord(RequestingAgentID, GroupID);
160
161 if (grec != null)
162 FillFounderUUI(grec);
163
164 return grec;
165 }
166
167 public List<ExtendedGroupMembersData> GetGroupMembers(string RequestingAgentID, UUID GroupID, string token)
168 {
169 if (!VerifyToken(GroupID, RequestingAgentID, token))
170 return new List<ExtendedGroupMembersData>();
171
172 List<ExtendedGroupMembersData> members = GetGroupMembers(RequestingAgentID, GroupID);
173
174 // convert UUIDs to UUIs
175 members.ForEach(delegate (ExtendedGroupMembersData m)
176 {
177 if (m.AgentID.ToString().Length == 36) // UUID
178 {
179 UserAccount account = m_UserAccounts.GetUserAccount(UUID.Zero, new UUID(m.AgentID));
180 if (account != null)
181 m.AgentID = Util.UniversalIdentifier(account.PrincipalID, account.FirstName, account.LastName, m_HomeURI);
182 }
183 });
184
185 return members;
186 }
187
188 public List<GroupRolesData> GetGroupRoles(string RequestingAgentID, UUID GroupID, string token)
189 {
190 if (!VerifyToken(GroupID, RequestingAgentID, token))
191 return new List<GroupRolesData>();
192
193 return GetGroupRoles(RequestingAgentID, GroupID);
194 }
195
196 public List<ExtendedGroupRoleMembersData> GetGroupRoleMembers(string RequestingAgentID, UUID GroupID, string token)
197 {
198 if (!VerifyToken(GroupID, RequestingAgentID, token))
199 return new List<ExtendedGroupRoleMembersData>();
200
201 List<ExtendedGroupRoleMembersData> rolemembers = GetGroupRoleMembers(RequestingAgentID, GroupID);
202
203 // convert UUIDs to UUIs
204 rolemembers.ForEach(delegate(ExtendedGroupRoleMembersData m)
205 {
206 if (m.MemberID.ToString().Length == 36) // UUID
207 {
208 UserAccount account = m_UserAccounts.GetUserAccount(UUID.Zero, new UUID(m.MemberID));
209 if (account != null)
210 m.MemberID = Util.UniversalIdentifier(account.PrincipalID, account.FirstName, account.LastName, m_HomeURI);
211 }
212 });
213
214 return rolemembers;
215 }
216
217 public bool AddNotice(string RequestingAgentID, UUID groupID, UUID noticeID, string fromName, string subject, string message,
218 bool hasAttachment, byte attType, string attName, UUID attItemID, string attOwnerID)
219 {
220 // check that the group proxy exists
221 ExtendedGroupRecord grec = GetGroupRecord(RequestingAgentID, groupID);
222 if (grec == null)
223 {
224 m_log.DebugFormat("[Groups.HGGroupsService]: attempt at adding notice to non-existent group proxy");
225 return false;
226 }
227
228 // check that the group is remote
229 if (grec.ServiceLocation == string.Empty)
230 {
231 m_log.DebugFormat("[Groups.HGGroupsService]: attempt at adding notice to local (non-proxy) group");
232 return false;
233 }
234
235 // check that there isn't already a notice with the same ID
236 if (GetGroupNotice(RequestingAgentID, noticeID) != null)
237 {
238 m_log.DebugFormat("[Groups.HGGroupsService]: a notice with the same ID already exists", grec.ServiceLocation);
239 return false;
240 }
241
242 // This has good intentions (security) but it will potentially DDS the origin...
243 // We'll need to send a proof along with the message. Maybe encrypt the message
244 // using key pairs
245 //
246 //// check that the notice actually exists in the origin
247 //GroupsServiceHGConnector c = new GroupsServiceHGConnector(grec.ServiceLocation);
248 //if (!c.VerifyNotice(noticeID, groupID))
249 //{
250 // m_log.DebugFormat("[Groups.HGGroupsService]: notice does not exist at origin {0}", grec.ServiceLocation);
251 // return false;
252 //}
253
254 // ok, we're good!
255 return _AddNotice(groupID, noticeID, fromName, subject, message, hasAttachment, attType, attName, attItemID, attOwnerID);
256 }
257
258 public bool VerifyNotice(UUID noticeID, UUID groupID)
259 {
260 GroupNoticeInfo notice = GetGroupNotice(string.Empty, noticeID);
261
262 if (notice == null)
263 return false;
264
265 if (notice.GroupID != groupID)
266 return false;
267
268 return true;
269 }
270
271 #endregion
272
273 private void InviteToGroup(string fromName, UUID groupID, UUID invitedAgentID, string groupName)
274 {
275 // Todo: Security check, probably also want to send some kind of notification
276 UUID InviteID = UUID.Random();
277
278 if (AddAgentToGroupInvite(InviteID, groupID, invitedAgentID.ToString()))
279 {
280 Guid inviteUUID = InviteID.Guid;
281
282 GridInstantMessage msg = new GridInstantMessage();
283
284 msg.imSessionID = inviteUUID;
285
286 // msg.fromAgentID = agentID.Guid;
287 msg.fromAgentID = groupID.Guid;
288 msg.toAgentID = invitedAgentID.Guid;
289 //msg.timestamp = (uint)Util.UnixTimeSinceEpoch();
290 msg.timestamp = 0;
291 msg.fromAgentName = fromName;
292 msg.message = string.Format("Please confirm your acceptance to join group {0}.", groupName);
293 msg.dialog = (byte)OpenMetaverse.InstantMessageDialog.GroupInvitation;
294 msg.fromGroup = true;
295 msg.offline = (byte)0;
296 msg.ParentEstateID = 0;
297 msg.Position = Vector3.Zero;
298 msg.RegionID = UUID.Zero.Guid;
299 msg.binaryBucket = new byte[20];
300
301 string reason = string.Empty;
302 m_OfflineIM.StoreMessage(msg, out reason);
303
304 }
305 }
306
307 private bool AddAgentToGroupInvite(UUID inviteID, UUID groupID, string agentID)
308 {
309 // Check whether the invitee is already a member of the group
310 MembershipData m = m_Database.RetrieveMember(groupID, agentID);
311 if (m != null)
312 return false;
313
314 // Check whether there are pending invitations and delete them
315 InvitationData invite = m_Database.RetrieveInvitation(groupID, agentID);
316 if (invite != null)
317 m_Database.DeleteInvite(invite.InviteID);
318
319 invite = new InvitationData();
320 invite.InviteID = inviteID;
321 invite.PrincipalID = agentID;
322 invite.GroupID = groupID;
323 invite.RoleID = UUID.Zero;
324 invite.Data = new Dictionary<string, string>();
325
326 return m_Database.StoreInvitation(invite);
327 }
328
329 private void FillFounderUUI(ExtendedGroupRecord grec)
330 {
331 UserAccount account = m_UserAccounts.GetUserAccount(UUID.Zero, grec.FounderID);
332 if (account != null)
333 grec.FounderUUI = Util.UniversalIdentifier(account.PrincipalID, account.FirstName, account.LastName, m_HomeURI);
334 }
335
336 private bool VerifyToken(UUID groupID, string agentID, string token)
337 {
338 // check the token
339 MembershipData membership = m_Database.RetrieveMember(groupID, agentID);
340 if (membership != null)
341 {
342 if (token != string.Empty && token.Equals(membership.Data["AccessToken"]))
343 return true;
344 else
345 m_log.DebugFormat("[Groups.HGGroupsService]: access token {0} did not match stored one {1}", token, membership.Data["AccessToken"]);
346 }
347 else
348 m_log.DebugFormat("[Groups.HGGroupsService]: membership not found for {0}", agentID);
349
350 return false;
351 }
352 }
353}
diff --git a/OpenSim/Addons/OfflineIM/OfflineIMRegionModule.cs b/OpenSim/Addons/OfflineIM/OfflineIMRegionModule.cs
new file mode 100644
index 0000000..050ebd2
--- /dev/null
+++ b/OpenSim/Addons/OfflineIM/OfflineIMRegionModule.cs
@@ -0,0 +1,267 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27using System;
28using System.Collections.Generic;
29using System.Reflection;
30using log4net;
31using Mono.Addins;
32using Nini.Config;
33using OpenMetaverse;
34using OpenSim.Framework;
35using OpenSim.Framework.Servers;
36using OpenSim.Framework.Client;
37using OpenSim.Region.Framework.Interfaces;
38using OpenSim.Region.Framework.Scenes;
39using OpenSim.Services.Interfaces;
40
41namespace OpenSim.OfflineIM
42{
43 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "OfflineIMConnectorModule")]
44 public class OfflineIMRegionModule : ISharedRegionModule, IOfflineIMService
45 {
46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
47
48 private bool m_Enabled = false;
49 private List<Scene> m_SceneList = new List<Scene>();
50 IMessageTransferModule m_TransferModule = null;
51 private bool m_ForwardOfflineGroupMessages = true;
52
53 private IOfflineIMService m_OfflineIMService;
54
55 public void Initialise(IConfigSource config)
56 {
57 IConfig cnf = config.Configs["Messaging"];
58 if (cnf == null)
59 return;
60 if (cnf != null && cnf.GetString("OfflineMessageModule", string.Empty) != Name)
61 return;
62
63 m_Enabled = true;
64
65 string serviceLocation = cnf.GetString("OfflineMessageURL", string.Empty);
66 if (serviceLocation == string.Empty)
67 m_OfflineIMService = new OfflineIMService(config);
68 else
69 m_OfflineIMService = new OfflineIMServiceRemoteConnector(serviceLocation);
70
71 m_ForwardOfflineGroupMessages = cnf.GetBoolean("ForwardOfflineGroupMessages", m_ForwardOfflineGroupMessages);
72 m_log.DebugFormat("[OfflineIM.V2]: Offline messages enabled by {0}", Name);
73 }
74
75 public void AddRegion(Scene scene)
76 {
77 if (!m_Enabled)
78 return;
79
80 scene.RegisterModuleInterface<IOfflineIMService>(this);
81 m_SceneList.Add(scene);
82 scene.EventManager.OnNewClient += OnNewClient;
83 }
84
85 public void RegionLoaded(Scene scene)
86 {
87 if (!m_Enabled)
88 return;
89
90 if (m_TransferModule == null)
91 {
92 m_TransferModule = scene.RequestModuleInterface<IMessageTransferModule>();
93 if (m_TransferModule == null)
94 {
95 scene.EventManager.OnNewClient -= OnNewClient;
96
97 m_SceneList.Clear();
98
99 m_log.Error("[OfflineIM.V2]: No message transfer module is enabled. Disabling offline messages");
100 }
101 m_TransferModule.OnUndeliveredMessage += UndeliveredMessage;
102 }
103 }
104
105 public void RemoveRegion(Scene scene)
106 {
107 if (!m_Enabled)
108 return;
109
110 m_SceneList.Remove(scene);
111 scene.EventManager.OnNewClient -= OnNewClient;
112 m_TransferModule.OnUndeliveredMessage -= UndeliveredMessage;
113
114 scene.ForEachClient(delegate(IClientAPI client)
115 {
116 client.OnRetrieveInstantMessages -= RetrieveInstantMessages;
117 client.OnMuteListRequest -= OnMuteListRequest;
118 });
119 }
120
121 public void PostInitialise()
122 {
123 }
124
125 public string Name
126 {
127 get { return "Offline Message Module V2"; }
128 }
129
130 public Type ReplaceableInterface
131 {
132 get { return null; }
133 }
134
135 public void Close()
136 {
137 m_SceneList.Clear();
138 }
139
140 private Scene FindScene(UUID agentID)
141 {
142 foreach (Scene s in m_SceneList)
143 {
144 ScenePresence presence = s.GetScenePresence(agentID);
145 if (presence != null && !presence.IsChildAgent)
146 return s;
147 }
148 return null;
149 }
150
151 private IClientAPI FindClient(UUID agentID)
152 {
153 foreach (Scene s in m_SceneList)
154 {
155 ScenePresence presence = s.GetScenePresence(agentID);
156 if (presence != null && !presence.IsChildAgent)
157 return presence.ControllingClient;
158 }
159 return null;
160 }
161
162 private void OnNewClient(IClientAPI client)
163 {
164 client.OnRetrieveInstantMessages += RetrieveInstantMessages;
165 client.OnMuteListRequest += OnMuteListRequest;
166 }
167
168 private void RetrieveInstantMessages(IClientAPI client)
169 {
170 m_log.DebugFormat("[OfflineIM.V2]: Retrieving stored messages for {0}", client.AgentId);
171
172 List<GridInstantMessage> msglist = m_OfflineIMService.GetMessages(client.AgentId);
173
174 if (msglist == null)
175 m_log.DebugFormat("[OfflineIM.V2]: WARNING null message list.");
176
177 foreach (GridInstantMessage im in msglist)
178 {
179 if (im.dialog == (byte)InstantMessageDialog.InventoryOffered)
180 // send it directly or else the item will be given twice
181 client.SendInstantMessage(im);
182 else
183 {
184 // Send through scene event manager so all modules get a chance
185 // to look at this message before it gets delivered.
186 //
187 // Needed for proper state management for stored group
188 // invitations
189 //
190 Scene s = FindScene(client.AgentId);
191 if (s != null)
192 s.EventManager.TriggerIncomingInstantMessage(im);
193 }
194 }
195 }
196
197 // Apparently this is needed in order for the viewer to request the IMs.
198 private void OnMuteListRequest(IClientAPI client, uint crc)
199 {
200 m_log.DebugFormat("[OfflineIM.V2] Got mute list request for crc {0}", crc);
201 string filename = "mutes" + client.AgentId.ToString();
202
203 IXfer xfer = client.Scene.RequestModuleInterface<IXfer>();
204 if (xfer != null)
205 {
206 xfer.AddNewFile(filename, new Byte[0]);
207 client.SendMuteListUpdate(filename);
208 }
209 }
210
211 private void UndeliveredMessage(GridInstantMessage im)
212 {
213 if (im.dialog != (byte)InstantMessageDialog.MessageFromObject &&
214 im.dialog != (byte)InstantMessageDialog.MessageFromAgent &&
215 im.dialog != (byte)InstantMessageDialog.GroupNotice &&
216 im.dialog != (byte)InstantMessageDialog.GroupInvitation &&
217 im.dialog != (byte)InstantMessageDialog.InventoryOffered)
218 {
219 return;
220 }
221
222 if (!m_ForwardOfflineGroupMessages)
223 {
224 if (im.dialog == (byte)InstantMessageDialog.GroupNotice ||
225 im.dialog == (byte)InstantMessageDialog.GroupInvitation)
226 return;
227 }
228
229 Scene scene = FindScene(new UUID(im.fromAgentID));
230 if (scene == null)
231 scene = m_SceneList[0];
232
233 string reason = string.Empty;
234 bool success = m_OfflineIMService.StoreMessage(im, out reason);
235
236 if (im.dialog == (byte)InstantMessageDialog.MessageFromAgent)
237 {
238 IClientAPI client = FindClient(new UUID(im.fromAgentID));
239 if (client == null)
240 return;
241
242 client.SendInstantMessage(new GridInstantMessage(
243 null, new UUID(im.toAgentID),
244 "System", new UUID(im.fromAgentID),
245 (byte)InstantMessageDialog.MessageFromAgent,
246 "User is not logged in. " +
247 (success ? "Message saved." : "Message not saved: " + reason),
248 false, new Vector3()));
249 }
250 }
251
252 #region IOfflineIM
253
254 public List<GridInstantMessage> GetMessages(UUID principalID)
255 {
256 return m_OfflineIMService.GetMessages(principalID);
257 }
258
259 public bool StoreMessage(GridInstantMessage im, out string reason)
260 {
261 return m_OfflineIMService.StoreMessage(im, out reason);
262 }
263
264 #endregion
265 }
266}
267
diff --git a/OpenSim/Addons/OfflineIM/Properties/AssemblyInfo.cs b/OpenSim/Addons/OfflineIM/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..ffe8a3e
--- /dev/null
+++ b/OpenSim/Addons/OfflineIM/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
1using System.Reflection;
2using System.Runtime.CompilerServices;
3using System.Runtime.InteropServices;
4using Mono.Addins;
5
6// General Information about an assembly is controlled through the following
7// set of attributes. Change these attribute values to modify the information
8// associated with an assembly.
9[assembly: AssemblyTitle("OpenSim.Addons.OfflineIM")]
10[assembly: AssemblyDescription("")]
11[assembly: AssemblyConfiguration("")]
12[assembly: AssemblyCompany("http://opensimulator.org")]
13[assembly: AssemblyProduct("OpenSim.Addons.OfflineIM")]
14[assembly: AssemblyCopyright("Copyright (c) OpenSimulator.org Developers")]
15[assembly: AssemblyTrademark("")]
16[assembly: AssemblyCulture("")]
17
18// Setting ComVisible to false makes the types in this assembly not visible
19// to COM components. If you need to access a type in this assembly from
20// COM, set the ComVisible attribute to true on that type.
21[assembly: ComVisible(false)]
22
23// The following GUID is for the ID of the typelib if this project is exposed to COM
24[assembly: Guid("a16a9905-4393-4872-9fca-4c81bedbd9f2")]
25
26// Version information for an assembly consists of the following four values:
27//
28// Major Version
29// Minor Version
30// Build Number
31// Revision
32//
33[assembly: AssemblyVersion("0.7.6.*")]
34
35[assembly: Addin("OpenSim.OfflineIM", "0.1")]
36[assembly: AddinDependency("OpenSim", "0.5")]
diff --git a/OpenSim/Addons/OfflineIM/Remote/OfflineIMServiceRemoteConnector.cs b/OpenSim/Addons/OfflineIM/Remote/OfflineIMServiceRemoteConnector.cs
new file mode 100644
index 0000000..69feb76
--- /dev/null
+++ b/OpenSim/Addons/OfflineIM/Remote/OfflineIMServiceRemoteConnector.cs
@@ -0,0 +1,143 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Linq;
31using System.Reflection;
32using System.Text;
33
34using OpenSim.Framework;
35using OpenSim.Server.Base;
36using OpenSim.Services.Interfaces;
37
38using OpenMetaverse;
39using log4net;
40using Nini.Config;
41
42namespace OpenSim.OfflineIM
43{
44 public class OfflineIMServiceRemoteConnector : IOfflineIMService
45 {
46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
47
48 private string m_ServerURI = string.Empty;
49 private object m_Lock = new object();
50
51 public OfflineIMServiceRemoteConnector(string url)
52 {
53 m_ServerURI = url;
54 m_log.DebugFormat("[OfflineIM.V2.RemoteConnector]: Offline IM server at {0}", m_ServerURI);
55 }
56
57 public OfflineIMServiceRemoteConnector(IConfigSource config)
58 {
59 IConfig cnf = config.Configs["Messaging"];
60 if (cnf == null)
61 {
62 m_log.WarnFormat("[OfflineIM.V2.RemoteConnector]: Missing Messaging configuration");
63 return;
64 }
65
66 m_ServerURI = cnf.GetString("OfflineMessageURL", string.Empty);
67
68 }
69
70 #region IOfflineIMService
71 public List<GridInstantMessage> GetMessages(UUID principalID)
72 {
73 List<GridInstantMessage> ims = new List<GridInstantMessage>();
74
75 Dictionary<string, object> sendData = new Dictionary<string, object>();
76 sendData["PrincipalID"] = principalID;
77 Dictionary<string, object> ret = MakeRequest("GET", sendData);
78
79 if (ret == null)
80 return ims;
81
82 if (!ret.ContainsKey("RESULT"))
83 return ims;
84
85 if (ret["RESULT"].ToString() == "NULL")
86 return ims;
87
88 foreach (object v in ((Dictionary<string, object>)ret["RESULT"]).Values)
89 {
90 GridInstantMessage m = OfflineIMDataUtils.GridInstantMessage((Dictionary<string, object>)v);
91 ims.Add(m);
92 }
93
94 return ims;
95 }
96
97 public bool StoreMessage(GridInstantMessage im, out string reason)
98 {
99 reason = string.Empty;
100 Dictionary<string, object> sendData = OfflineIMDataUtils.GridInstantMessage(im);
101
102 Dictionary<string, object> ret = MakeRequest("STORE", sendData);
103
104 if (ret == null)
105 {
106 reason = "Bad response from server";
107 return false;
108 }
109
110 string result = ret["RESULT"].ToString();
111 if (result == "NULL" || result.ToLower() == "false")
112 {
113 reason = ret["REASON"].ToString();
114 return false;
115 }
116
117 return true;
118 }
119
120 #endregion
121
122
123 #region Make Request
124
125 private Dictionary<string, object> MakeRequest(string method, Dictionary<string, object> sendData)
126 {
127 sendData["METHOD"] = method;
128
129 string reply = string.Empty;
130 lock (m_Lock)
131 reply = SynchronousRestFormsRequester.MakeRequest("POST",
132 m_ServerURI + "/offlineim",
133 ServerUtils.BuildQueryString(sendData));
134
135 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(
136 reply);
137
138 return replyData;
139 }
140 #endregion
141
142 }
143}
diff --git a/OpenSim/Addons/OfflineIM/Remote/OfflineIMServiceRobustConnector.cs b/OpenSim/Addons/OfflineIM/Remote/OfflineIMServiceRobustConnector.cs
new file mode 100644
index 0000000..2b3a01d
--- /dev/null
+++ b/OpenSim/Addons/OfflineIM/Remote/OfflineIMServiceRobustConnector.cs
@@ -0,0 +1,215 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Reflection;
30using System.Text;
31using System.Xml;
32using System.Collections.Generic;
33using System.IO;
34using Nini.Config;
35using OpenSim.Framework;
36using OpenSim.Server.Base;
37using OpenSim.Services.Interfaces;
38using OpenSim.Framework.Servers.HttpServer;
39using OpenSim.Server.Handlers.Base;
40using log4net;
41using OpenMetaverse;
42
43namespace OpenSim.OfflineIM
44{
45 public class OfflineIMServiceRobustConnector : ServiceConnector
46 {
47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
48
49 private IOfflineIMService m_OfflineIMService;
50 private string m_ConfigName = "Messaging";
51
52 public OfflineIMServiceRobustConnector(IConfigSource config, IHttpServer server, string configName) :
53 base(config, server, configName)
54 {
55 if (configName != String.Empty)
56 m_ConfigName = configName;
57
58 m_log.DebugFormat("[OfflineIM.V2.RobustConnector]: Starting with config name {0}", m_ConfigName);
59
60 m_OfflineIMService = new OfflineIMService(config);
61
62 server.AddStreamHandler(new OfflineIMServicePostHandler(m_OfflineIMService));
63 }
64 }
65
66 public class OfflineIMServicePostHandler : BaseStreamHandler
67 {
68 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
69
70 private IOfflineIMService m_OfflineIMService;
71
72 public OfflineIMServicePostHandler(IOfflineIMService service) :
73 base("POST", "/offlineim")
74 {
75 m_OfflineIMService = service;
76 }
77
78 public override byte[] Handle(string path, Stream requestData,
79 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
80 {
81 StreamReader sr = new StreamReader(requestData);
82 string body = sr.ReadToEnd();
83 sr.Close();
84 body = body.Trim();
85
86 //m_log.DebugFormat("[XXX]: query String: {0}", body);
87
88 try
89 {
90 Dictionary<string, object> request =
91 ServerUtils.ParseQueryString(body);
92
93 if (!request.ContainsKey("METHOD"))
94 return FailureResult();
95
96 string method = request["METHOD"].ToString();
97 request.Remove("METHOD");
98
99 m_log.DebugFormat("[OfflineIM.V2.Handler]: {0}", method);
100 switch (method)
101 {
102 case "GET":
103 return HandleGet(request);
104 case "STORE":
105 return HandleStore(request);
106 }
107 m_log.DebugFormat("[OFFLINE IM HANDLER]: unknown method request: {0}", method);
108 }
109 catch (Exception e)
110 {
111 m_log.DebugFormat("[OFFLINE IM HANDLER]: Exception {0}", e.StackTrace);
112 }
113
114 return FailureResult();
115 }
116
117 byte[] HandleStore(Dictionary<string, object> request)
118 {
119 Dictionary<string, object> result = new Dictionary<string, object>();
120
121 GridInstantMessage im = OfflineIMDataUtils.GridInstantMessage(request);
122
123 string reason = string.Empty;
124
125 bool success = m_OfflineIMService.StoreMessage(im, out reason);
126
127 result["RESULT"] = success.ToString();
128 if (!success)
129 result["REASON"] = reason;
130
131 string xmlString = ServerUtils.BuildXmlResponse(result);
132
133 //m_log.DebugFormat("[XXX]: resp string: {0}", xmlString);
134 return Util.UTF8NoBomEncoding.GetBytes(xmlString);
135 }
136
137 byte[] HandleGet(Dictionary<string, object> request)
138 {
139 Dictionary<string, object> result = new Dictionary<string, object>();
140
141 if (!request.ContainsKey("PrincipalID"))
142 NullResult(result, "Bad network data");
143 else
144 {
145 UUID principalID = new UUID(request["PrincipalID"].ToString());
146 List<GridInstantMessage> ims = m_OfflineIMService.GetMessages(principalID);
147
148 Dictionary<string, object> dict = new Dictionary<string, object>();
149 int i = 0;
150 foreach (GridInstantMessage m in ims)
151 dict["im-" + i++] = OfflineIMDataUtils.GridInstantMessage(m);
152
153 result["RESULT"] = dict;
154 }
155
156 string xmlString = ServerUtils.BuildXmlResponse(result);
157
158 //m_log.DebugFormat("[XXX]: resp string: {0}", xmlString);
159 return Util.UTF8NoBomEncoding.GetBytes(xmlString);
160 }
161
162 #region Helpers
163
164 private void NullResult(Dictionary<string, object> result, string reason)
165 {
166 result["RESULT"] = "NULL";
167 result["REASON"] = reason;
168 }
169
170 private byte[] FailureResult()
171 {
172 return BoolResult(false);
173 }
174
175 private byte[] SuccessResult()
176 {
177 return BoolResult(true);
178 }
179
180 private byte[] BoolResult(bool value)
181 {
182 XmlDocument doc = new XmlDocument();
183
184 XmlNode xmlnode = doc.CreateNode(XmlNodeType.XmlDeclaration,
185 "", "");
186
187 doc.AppendChild(xmlnode);
188
189 XmlElement rootElement = doc.CreateElement("", "ServerResponse",
190 "");
191
192 doc.AppendChild(rootElement);
193
194 XmlElement result = doc.CreateElement("", "RESULT", "");
195 result.AppendChild(doc.CreateTextNode(value.ToString()));
196
197 rootElement.AppendChild(result);
198
199 return DocToBytes(doc);
200 }
201
202 private byte[] DocToBytes(XmlDocument doc)
203 {
204 MemoryStream ms = new MemoryStream();
205 XmlTextWriter xw = new XmlTextWriter(ms, null);
206 xw.Formatting = Formatting.Indented;
207 doc.WriteTo(xw);
208 xw.Flush();
209
210 return ms.ToArray();
211 }
212
213 #endregion
214 }
215}
diff --git a/OpenSim/Addons/OfflineIM/Service/OfflineIMService.cs b/OpenSim/Addons/OfflineIM/Service/OfflineIMService.cs
new file mode 100644
index 0000000..6ba022c
--- /dev/null
+++ b/OpenSim/Addons/OfflineIM/Service/OfflineIMService.cs
@@ -0,0 +1,131 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.IO;
31using System.Reflection;
32using System.Runtime.Serialization;
33using System.Text;
34using System.Timers;
35using System.Xml;
36using System.Xml.Serialization;
37using log4net;
38using Nini.Config;
39
40using OpenMetaverse;
41using OpenSim.Data;
42using OpenSim.Framework;
43using OpenSim.Services.Interfaces;
44
45namespace OpenSim.OfflineIM
46{
47 public class OfflineIMService : OfflineIMServiceBase, IOfflineIMService
48 {
49 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
50 private const int MAX_IM = 25;
51
52 private XmlSerializer m_serializer;
53 private static bool m_Initialized = false;
54
55 public OfflineIMService(IConfigSource config)
56 : base(config)
57 {
58 m_serializer = new XmlSerializer(typeof(GridInstantMessage));
59 if (!m_Initialized)
60 {
61 m_Database.DeleteOld();
62 m_Initialized = true;
63 }
64 }
65
66 public List<GridInstantMessage> GetMessages(UUID principalID)
67 {
68 List<GridInstantMessage> ims = new List<GridInstantMessage>();
69
70 OfflineIMData[] messages = m_Database.Get("PrincipalID", principalID.ToString());
71
72 if (messages == null || (messages != null && messages.Length == 0))
73 return ims;
74
75 foreach (OfflineIMData m in messages)
76 {
77 using (MemoryStream mstream = new MemoryStream(Encoding.UTF8.GetBytes(m.Data["Message"])))
78 {
79 GridInstantMessage im = (GridInstantMessage)m_serializer.Deserialize(mstream);
80 ims.Add(im);
81 }
82 }
83
84 // Then, delete them
85 m_Database.Delete("PrincipalID", principalID.ToString());
86
87 return ims;
88 }
89
90 public bool StoreMessage(GridInstantMessage im, out string reason)
91 {
92 reason = string.Empty;
93
94 // TODO Check limits
95 UUID principalID = new UUID(im.toAgentID);
96 long count = m_Database.GetCount("PrincipalID", principalID.ToString());
97 if (count >= MAX_IM)
98 {
99 reason = "Number of offline IMs has maxed out";
100 return false;
101 }
102
103 string imXml = string.Empty;
104 using (MemoryStream mstream = new MemoryStream())
105 {
106 XmlWriterSettings settings = new XmlWriterSettings();
107 settings.Encoding = Encoding.UTF8;
108
109 using (XmlWriter writer = XmlWriter.Create(mstream, settings))
110 {
111 m_serializer.Serialize(writer, im);
112 writer.Flush();
113
114 mstream.Position = 0;
115 using (StreamReader sreader = new StreamReader(mstream))
116 {
117 imXml = sreader.ReadToEnd();
118 }
119 }
120 }
121
122 OfflineIMData data = new OfflineIMData();
123 data.PrincipalID = principalID;
124 data.Data = new Dictionary<string, string>();
125 data.Data["Message"] = imXml;
126
127 return m_Database.Store(data);
128
129 }
130 }
131}
diff --git a/OpenSim/Addons/OfflineIM/Service/OfflineIMServiceBase.cs b/OpenSim/Addons/OfflineIM/Service/OfflineIMServiceBase.cs
new file mode 100644
index 0000000..3376be4
--- /dev/null
+++ b/OpenSim/Addons/OfflineIM/Service/OfflineIMServiceBase.cs
@@ -0,0 +1,83 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27using System;
28using System.Collections.Generic;
29using System.Reflection;
30using Nini.Config;
31using OpenSim.Framework;
32using OpenSim.Data;
33using OpenSim.Services.Interfaces;
34using OpenSim.Services.Base;
35
36namespace OpenSim.OfflineIM
37{
38 public class OfflineIMServiceBase : ServiceBase
39 {
40 protected IOfflineIMData m_Database = null;
41
42 public OfflineIMServiceBase(IConfigSource config)
43 : base(config)
44 {
45 string dllName = String.Empty;
46 string connString = String.Empty;
47 string realm = "im_offline";
48
49 //
50 // Try reading the [DatabaseService] section, if it exists
51 //
52 IConfig dbConfig = config.Configs["DatabaseService"];
53 if (dbConfig != null)
54 {
55 if (dllName == String.Empty)
56 dllName = dbConfig.GetString("StorageProvider", String.Empty);
57 if (connString == String.Empty)
58 connString = dbConfig.GetString("ConnectionString", String.Empty);
59 }
60
61 //
62 // [Messaging] section overrides [DatabaseService], if it exists
63 //
64 IConfig imConfig = config.Configs["Messaging"];
65 if (imConfig != null)
66 {
67 dllName = imConfig.GetString("StorageProvider", dllName);
68 connString = imConfig.GetString("ConnectionString", connString);
69 realm = imConfig.GetString("Realm", realm);
70 }
71
72 //
73 // We tried, but this doesn't exist. We can't proceed.
74 //
75 if (dllName.Equals(String.Empty))
76 throw new Exception("No StorageProvider configured");
77
78 m_Database = LoadPlugin<IOfflineIMData>(dllName, new Object[] { connString, realm });
79 if (m_Database == null)
80 throw new Exception("Could not find a storage interface in the given module " + dllName);
81 }
82 }
83}
diff --git a/OpenSim/ApplicationPlugins/LoadRegions/Properties/AssemblyInfo.cs b/OpenSim/ApplicationPlugins/LoadRegions/Properties/AssemblyInfo.cs
index b81c1e5..1b6a3e1 100644
--- a/OpenSim/ApplicationPlugins/LoadRegions/Properties/AssemblyInfo.cs
+++ b/OpenSim/ApplicationPlugins/LoadRegions/Properties/AssemblyInfo.cs
@@ -63,4 +63,3 @@ using System.Runtime.InteropServices;
63// [assembly: AssemblyVersion("0.7.6.*")] 63// [assembly: AssemblyVersion("0.7.6.*")]
64 64
65[assembly : AssemblyVersion("0.7.6.*")] 65[assembly : AssemblyVersion("0.7.6.*")]
66[assembly : AssemblyFileVersion("0.6.5.0")] \ No newline at end of file
diff --git a/OpenSim/ApplicationPlugins/RegionModulesController/Properties/AssemblyInfo.cs b/OpenSim/ApplicationPlugins/RegionModulesController/Properties/AssemblyInfo.cs
index be6054d..5683a72 100644
--- a/OpenSim/ApplicationPlugins/RegionModulesController/Properties/AssemblyInfo.cs
+++ b/OpenSim/ApplicationPlugins/RegionModulesController/Properties/AssemblyInfo.cs
@@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33
diff --git a/OpenSim/ApplicationPlugins/RemoteController/Properties/AssemblyInfo.cs b/OpenSim/ApplicationPlugins/RemoteController/Properties/AssemblyInfo.cs
index 3ec7a13..a9d3f74 100644
--- a/OpenSim/ApplicationPlugins/RemoteController/Properties/AssemblyInfo.cs
+++ b/OpenSim/ApplicationPlugins/RemoteController/Properties/AssemblyInfo.cs
@@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33
diff --git a/OpenSim/Capabilities/Handlers/Properties/AssemblyInfo.cs b/OpenSim/Capabilities/Handlers/Properties/AssemblyInfo.cs
index 4ff5fe1..f8f63f4 100644
--- a/OpenSim/Capabilities/Handlers/Properties/AssemblyInfo.cs
+++ b/OpenSim/Capabilities/Handlers/Properties/AssemblyInfo.cs
@@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33
diff --git a/OpenSim/Data/IGroupsData.cs b/OpenSim/Data/IGroupsData.cs
new file mode 100644
index 0000000..c11e649
--- /dev/null
+++ b/OpenSim/Data/IGroupsData.cs
@@ -0,0 +1,144 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System.Collections.Generic;
29using OpenSim.Data;
30using OpenMetaverse;
31
32namespace OpenSim.Data
33{
34 public class GroupData
35 {
36 public UUID GroupID;
37 public Dictionary<string, string> Data;
38 }
39
40 public class MembershipData
41 {
42 public UUID GroupID;
43 public string PrincipalID;
44 public Dictionary<string, string> Data;
45 }
46
47 public class RoleData
48 {
49 public UUID GroupID;
50 public UUID RoleID;
51 public Dictionary<string, string> Data;
52 }
53
54 public class RoleMembershipData
55 {
56 public UUID GroupID;
57 public UUID RoleID;
58 public string PrincipalID;
59 }
60
61 public class PrincipalData
62 {
63 public string PrincipalID;
64 public UUID ActiveGroupID;
65 }
66
67 public class InvitationData
68 {
69 public UUID InviteID;
70 public UUID GroupID;
71 public UUID RoleID;
72 public string PrincipalID;
73 public Dictionary<string, string> Data;
74 }
75
76 public class NoticeData
77 {
78 public UUID GroupID;
79 public UUID NoticeID;
80 public Dictionary<string, string> Data;
81 }
82
83
84 public interface IGroupsData
85 {
86 // groups table
87 bool StoreGroup(GroupData data);
88 GroupData RetrieveGroup(UUID groupID);
89 GroupData RetrieveGroup(string name);
90 GroupData[] RetrieveGroups(string pattern);
91 bool DeleteGroup(UUID groupID);
92 int GroupsCount();
93
94 // membership table
95 MembershipData RetrieveMember(UUID groupID, string pricipalID);
96 MembershipData[] RetrieveMembers(UUID groupID);
97 MembershipData[] RetrieveMemberships(string pricipalID);
98 bool StoreMember(MembershipData data);
99 bool DeleteMember(UUID groupID, string pricipalID);
100 int MemberCount(UUID groupID);
101
102 // roles table
103 bool StoreRole(RoleData data);
104 RoleData RetrieveRole(UUID groupID, UUID roleID);
105 RoleData[] RetrieveRoles(UUID groupID);
106 bool DeleteRole(UUID groupID, UUID roleID);
107 int RoleCount(UUID groupID);
108
109 // rolememberhip table
110 RoleMembershipData[] RetrieveRolesMembers(UUID groupID);
111 RoleMembershipData[] RetrieveRoleMembers(UUID groupID, UUID roleID);
112 RoleMembershipData[] RetrieveMemberRoles(UUID groupID, string principalID);
113 RoleMembershipData RetrieveRoleMember(UUID groupID, UUID roleID, string principalID);
114 int RoleMemberCount(UUID groupID, UUID roleID);
115 bool StoreRoleMember(RoleMembershipData data);
116 bool DeleteRoleMember(RoleMembershipData data);
117 bool DeleteMemberAllRoles(UUID groupID, string principalID);
118
119 // principals table
120 bool StorePrincipal(PrincipalData data);
121 PrincipalData RetrievePrincipal(string principalID);
122 bool DeletePrincipal(string principalID);
123
124 // invites table
125 bool StoreInvitation(InvitationData data);
126 InvitationData RetrieveInvitation(UUID inviteID);
127 InvitationData RetrieveInvitation(UUID groupID, string principalID);
128 bool DeleteInvite(UUID inviteID);
129 void DeleteOldInvites();
130
131 // notices table
132 bool StoreNotice(NoticeData data);
133 NoticeData RetrieveNotice(UUID noticeID);
134 NoticeData[] RetrieveNotices(UUID groupID);
135 bool DeleteNotice(UUID noticeID);
136 void DeleteOldNotices();
137
138 // combinations
139 MembershipData RetrievePrincipalGroupMembership(string principalID, UUID groupID);
140 MembershipData[] RetrievePrincipalGroupMemberships(string principalID);
141
142 // Misc
143 }
144}
diff --git a/OpenSim/Data/IOfflineIMData.cs b/OpenSim/Data/IOfflineIMData.cs
new file mode 100644
index 0000000..e780304
--- /dev/null
+++ b/OpenSim/Data/IOfflineIMData.cs
@@ -0,0 +1,49 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System.Collections.Generic;
29using OpenSim.Data;
30using OpenMetaverse;
31
32namespace OpenSim.Data
33{
34 public class OfflineIMData
35 {
36 public UUID PrincipalID;
37 public Dictionary<string, string> Data;
38 }
39
40
41 public interface IOfflineIMData
42 {
43 OfflineIMData[] Get(string field, string val);
44 long GetCount(string field, string key);
45 bool Store(OfflineIMData data);
46 bool Delete(string field, string val);
47 void DeleteOld();
48 }
49}
diff --git a/OpenSim/Data/MSSQL/Properties/AssemblyInfo.cs b/OpenSim/Data/MSSQL/Properties/AssemblyInfo.cs
index 4e96be8..9bc580e 100644
--- a/OpenSim/Data/MSSQL/Properties/AssemblyInfo.cs
+++ b/OpenSim/Data/MSSQL/Properties/AssemblyInfo.cs
@@ -62,4 +62,4 @@ using System.Runtime.InteropServices;
62// by using the '*' as shown below: 62// by using the '*' as shown below:
63 63
64[assembly : AssemblyVersion("0.7.6.*")] 64[assembly : AssemblyVersion("0.7.6.*")]
65[assembly : AssemblyFileVersion("0.6.5.0")] 65
diff --git a/OpenSim/Data/MySQL/MySQLGenericTableHandler.cs b/OpenSim/Data/MySQL/MySQLGenericTableHandler.cs
index f6731c0..dc657c8 100644
--- a/OpenSim/Data/MySQL/MySQLGenericTableHandler.cs
+++ b/OpenSim/Data/MySQL/MySQLGenericTableHandler.cs
@@ -306,5 +306,65 @@ namespace OpenSim.Data.MySQL
306 return ExecuteNonQuery(cmd) > 0; 306 return ExecuteNonQuery(cmd) > 0;
307 } 307 }
308 } 308 }
309
310 public long GetCount(string field, string key)
311 {
312 return GetCount(new string[] { field }, new string[] { key });
313 }
314
315 public long GetCount(string[] fields, string[] keys)
316 {
317 if (fields.Length != keys.Length)
318 return 0;
319
320 List<string> terms = new List<string>();
321
322 using (MySqlCommand cmd = new MySqlCommand())
323 {
324 for (int i = 0; i < fields.Length; i++)
325 {
326 cmd.Parameters.AddWithValue(fields[i], keys[i]);
327 terms.Add("`" + fields[i] + "` = ?" + fields[i]);
328 }
329
330 string where = String.Join(" and ", terms.ToArray());
331
332 string query = String.Format("select count(*) from {0} where {1}",
333 m_Realm, where);
334
335 cmd.CommandText = query;
336
337 Object result = DoQueryScalar(cmd);
338
339 return Convert.ToInt64(result);
340 }
341 }
342
343 public long GetCount(string where)
344 {
345 using (MySqlCommand cmd = new MySqlCommand())
346 {
347 string query = String.Format("select count(*) from {0} where {1}",
348 m_Realm, where);
349
350 cmd.CommandText = query;
351
352 object result = DoQueryScalar(cmd);
353
354 return Convert.ToInt64(result);
355 }
356 }
357
358 public object DoQueryScalar(MySqlCommand cmd)
359 {
360 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
361 {
362 dbcon.Open();
363 cmd.Connection = dbcon;
364
365 return cmd.ExecuteScalar();
366 }
367 }
368
309 } 369 }
310} 370}
diff --git a/OpenSim/Data/MySQL/MySQLGroupsData.cs b/OpenSim/Data/MySQL/MySQLGroupsData.cs
new file mode 100644
index 0000000..2a1bd6c
--- /dev/null
+++ b/OpenSim/Data/MySQL/MySQLGroupsData.cs
@@ -0,0 +1,484 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using System.Reflection;
32
33using OpenSim.Framework;
34using OpenSim.Data.MySQL;
35
36using OpenMetaverse;
37using MySql.Data.MySqlClient;
38
39namespace OpenSim.Data.MySQL
40{
41 public class MySQLGroupsData : IGroupsData
42 {
43 private MySqlGroupsGroupsHandler m_Groups;
44 private MySqlGroupsMembershipHandler m_Membership;
45 private MySqlGroupsRolesHandler m_Roles;
46 private MySqlGroupsRoleMembershipHandler m_RoleMembership;
47 private MySqlGroupsInvitesHandler m_Invites;
48 private MySqlGroupsNoticesHandler m_Notices;
49 private MySqlGroupsPrincipalsHandler m_Principals;
50
51 public MySQLGroupsData(string connectionString, string realm)
52 {
53 m_Groups = new MySqlGroupsGroupsHandler(connectionString, realm + "_groups", realm + "_Store");
54 m_Membership = new MySqlGroupsMembershipHandler(connectionString, realm + "_membership");
55 m_Roles = new MySqlGroupsRolesHandler(connectionString, realm + "_roles");
56 m_RoleMembership = new MySqlGroupsRoleMembershipHandler(connectionString, realm + "_rolemembership");
57 m_Invites = new MySqlGroupsInvitesHandler(connectionString, realm + "_invites");
58 m_Notices = new MySqlGroupsNoticesHandler(connectionString, realm + "_notices");
59 m_Principals = new MySqlGroupsPrincipalsHandler(connectionString, realm + "_principals");
60 }
61
62 #region groups table
63 public bool StoreGroup(GroupData data)
64 {
65 return m_Groups.Store(data);
66 }
67
68 public GroupData RetrieveGroup(UUID groupID)
69 {
70 GroupData[] groups = m_Groups.Get("GroupID", groupID.ToString());
71 if (groups.Length > 0)
72 return groups[0];
73
74 return null;
75 }
76
77 public GroupData RetrieveGroup(string name)
78 {
79 GroupData[] groups = m_Groups.Get("Name", name);
80 if (groups.Length > 0)
81 return groups[0];
82
83 return null;
84 }
85
86 public GroupData[] RetrieveGroups(string pattern)
87 {
88 if (string.IsNullOrEmpty(pattern))
89 pattern = "1 ORDER BY Name LIMIT 100";
90 else
91 pattern = string.Format("Name LIKE %{0}% ORDER BY Name LIMIT 100", pattern);
92
93 return m_Groups.Get(pattern);
94 }
95
96 public bool DeleteGroup(UUID groupID)
97 {
98 return m_Groups.Delete("GroupID", groupID.ToString());
99 }
100
101 public int GroupsCount()
102 {
103 return (int)m_Groups.GetCount("Location=\"\"");
104 }
105
106 #endregion
107
108 #region membership table
109 public MembershipData[] RetrieveMembers(UUID groupID)
110 {
111 return m_Membership.Get("GroupID", groupID.ToString());
112 }
113
114 public MembershipData RetrieveMember(UUID groupID, string pricipalID)
115 {
116 MembershipData[] m = m_Membership.Get(new string[] { "GroupID", "PrincipalID" },
117 new string[] { groupID.ToString(), pricipalID });
118 if (m != null && m.Length > 0)
119 return m[0];
120
121 return null;
122 }
123
124 public MembershipData[] RetrieveMemberships(string pricipalID)
125 {
126 return m_Membership.Get("PrincipalID", pricipalID.ToString());
127 }
128
129 public bool StoreMember(MembershipData data)
130 {
131 return m_Membership.Store(data);
132 }
133
134 public bool DeleteMember(UUID groupID, string pricipalID)
135 {
136 return m_Membership.Delete(new string[] { "GroupID", "PrincipalID" },
137 new string[] { groupID.ToString(), pricipalID });
138 }
139
140 public int MemberCount(UUID groupID)
141 {
142 return (int)m_Membership.GetCount("GroupID", groupID.ToString());
143 }
144 #endregion
145
146 #region roles table
147 public bool StoreRole(RoleData data)
148 {
149 return m_Roles.Store(data);
150 }
151
152 public RoleData RetrieveRole(UUID groupID, UUID roleID)
153 {
154 RoleData[] data = m_Roles.Get(new string[] { "GroupID", "RoleID" },
155 new string[] { groupID.ToString(), roleID.ToString() });
156
157 if (data != null && data.Length > 0)
158 return data[0];
159
160 return null;
161 }
162
163 public RoleData[] RetrieveRoles(UUID groupID)
164 {
165 //return m_Roles.RetrieveRoles(groupID);
166 return m_Roles.Get("GroupID", groupID.ToString());
167 }
168
169 public bool DeleteRole(UUID groupID, UUID roleID)
170 {
171 return m_Roles.Delete(new string[] { "GroupID", "RoleID" },
172 new string[] { groupID.ToString(), roleID.ToString() });
173 }
174
175 public int RoleCount(UUID groupID)
176 {
177 return (int)m_Roles.GetCount("GroupID", groupID.ToString());
178 }
179
180
181 #endregion
182
183 #region rolememberhip table
184 public RoleMembershipData[] RetrieveRolesMembers(UUID groupID)
185 {
186 RoleMembershipData[] data = m_RoleMembership.Get("GroupID", groupID.ToString());
187
188 return data;
189 }
190
191 public RoleMembershipData[] RetrieveRoleMembers(UUID groupID, UUID roleID)
192 {
193 RoleMembershipData[] data = m_RoleMembership.Get(new string[] { "GroupID", "RoleID" },
194 new string[] { groupID.ToString(), roleID.ToString() });
195
196 return data;
197 }
198
199 public RoleMembershipData[] RetrieveMemberRoles(UUID groupID, string principalID)
200 {
201 RoleMembershipData[] data = m_RoleMembership.Get(new string[] { "GroupID", "PrincipalID" },
202 new string[] { groupID.ToString(), principalID.ToString() });
203
204 return data;
205 }
206
207 public RoleMembershipData RetrieveRoleMember(UUID groupID, UUID roleID, string principalID)
208 {
209 RoleMembershipData[] data = m_RoleMembership.Get(new string[] { "GroupID", "RoleID", "PrincipalID" },
210 new string[] { groupID.ToString(), roleID.ToString(), principalID.ToString() });
211
212 if (data != null && data.Length > 0)
213 return data[0];
214
215 return null;
216 }
217
218 public int RoleMemberCount(UUID groupID, UUID roleID)
219 {
220 return (int)m_RoleMembership.GetCount(new string[] { "GroupID", "RoleID" },
221 new string[] { groupID.ToString(), roleID.ToString() });
222 }
223
224 public bool StoreRoleMember(RoleMembershipData data)
225 {
226 return m_RoleMembership.Store(data);
227 }
228
229 public bool DeleteRoleMember(RoleMembershipData data)
230 {
231 return m_RoleMembership.Delete(new string[] { "GroupID", "RoleID", "PrincipalID"},
232 new string[] { data.GroupID.ToString(), data.RoleID.ToString(), data.PrincipalID });
233 }
234
235 public bool DeleteMemberAllRoles(UUID groupID, string principalID)
236 {
237 return m_RoleMembership.Delete(new string[] { "GroupID", "PrincipalID" },
238 new string[] { groupID.ToString(), principalID });
239 }
240
241 #endregion
242
243 #region principals table
244 public bool StorePrincipal(PrincipalData data)
245 {
246 return m_Principals.Store(data);
247 }
248
249 public PrincipalData RetrievePrincipal(string principalID)
250 {
251 PrincipalData[] p = m_Principals.Get("PrincipalID", principalID);
252 if (p != null && p.Length > 0)
253 return p[0];
254
255 return null;
256 }
257
258 public bool DeletePrincipal(string principalID)
259 {
260 return m_Principals.Delete("PrincipalID", principalID);
261 }
262 #endregion
263
264 #region invites table
265
266 public bool StoreInvitation(InvitationData data)
267 {
268 return m_Invites.Store(data);
269 }
270
271 public InvitationData RetrieveInvitation(UUID inviteID)
272 {
273 InvitationData[] invites = m_Invites.Get("InviteID", inviteID.ToString());
274
275 if (invites != null && invites.Length > 0)
276 return invites[0];
277
278 return null;
279 }
280
281 public InvitationData RetrieveInvitation(UUID groupID, string principalID)
282 {
283 InvitationData[] invites = m_Invites.Get(new string[] { "GroupID", "PrincipalID" },
284 new string[] { groupID.ToString(), principalID });
285
286 if (invites != null && invites.Length > 0)
287 return invites[0];
288
289 return null;
290 }
291
292 public bool DeleteInvite(UUID inviteID)
293 {
294 return m_Invites.Delete("InviteID", inviteID.ToString());
295 }
296
297 public void DeleteOldInvites()
298 {
299 m_Invites.DeleteOld();
300 }
301
302 #endregion
303
304 #region notices table
305
306 public bool StoreNotice(NoticeData data)
307 {
308 return m_Notices.Store(data);
309 }
310
311 public NoticeData RetrieveNotice(UUID noticeID)
312 {
313 NoticeData[] notices = m_Notices.Get("NoticeID", noticeID.ToString());
314
315 if (notices != null && notices.Length > 0)
316 return notices[0];
317
318 return null;
319 }
320
321 public NoticeData[] RetrieveNotices(UUID groupID)
322 {
323 NoticeData[] notices = m_Notices.Get("GroupID", groupID.ToString());
324
325 return notices;
326 }
327
328 public bool DeleteNotice(UUID noticeID)
329 {
330 return m_Notices.Delete("NoticeID", noticeID.ToString());
331 }
332
333 public void DeleteOldNotices()
334 {
335 m_Notices.DeleteOld();
336 }
337
338 #endregion
339
340 #region combinations
341 public MembershipData RetrievePrincipalGroupMembership(string principalID, UUID groupID)
342 {
343 // TODO
344 return null;
345 }
346 public MembershipData[] RetrievePrincipalGroupMemberships(string principalID)
347 {
348 // TODO
349 return null;
350 }
351
352 #endregion
353 }
354
355 public class MySqlGroupsGroupsHandler : MySQLGenericTableHandler<GroupData>
356 {
357 protected override Assembly Assembly
358 {
359 // WARNING! Moving migrations to this assembly!!!
360 get { return GetType().Assembly; }
361 }
362
363 public MySqlGroupsGroupsHandler(string connectionString, string realm, string store)
364 : base(connectionString, realm, store)
365 {
366 }
367
368 }
369
370 public class MySqlGroupsMembershipHandler : MySQLGenericTableHandler<MembershipData>
371 {
372 protected override Assembly Assembly
373 {
374 // WARNING! Moving migrations to this assembly!!!
375 get { return GetType().Assembly; }
376 }
377
378 public MySqlGroupsMembershipHandler(string connectionString, string realm)
379 : base(connectionString, realm, string.Empty)
380 {
381 }
382
383 }
384
385 public class MySqlGroupsRolesHandler : MySQLGenericTableHandler<RoleData>
386 {
387 protected override Assembly Assembly
388 {
389 // WARNING! Moving migrations to this assembly!!!
390 get { return GetType().Assembly; }
391 }
392
393 public MySqlGroupsRolesHandler(string connectionString, string realm)
394 : base(connectionString, realm, string.Empty)
395 {
396 }
397
398 }
399
400 public class MySqlGroupsRoleMembershipHandler : MySQLGenericTableHandler<RoleMembershipData>
401 {
402 protected override Assembly Assembly
403 {
404 // WARNING! Moving migrations to this assembly!!!
405 get { return GetType().Assembly; }
406 }
407
408 public MySqlGroupsRoleMembershipHandler(string connectionString, string realm)
409 : base(connectionString, realm, string.Empty)
410 {
411 }
412
413 }
414
415 public class MySqlGroupsInvitesHandler : MySQLGenericTableHandler<InvitationData>
416 {
417 protected override Assembly Assembly
418 {
419 // WARNING! Moving migrations to this assembly!!!
420 get { return GetType().Assembly; }
421 }
422
423 public MySqlGroupsInvitesHandler(string connectionString, string realm)
424 : base(connectionString, realm, string.Empty)
425 {
426 }
427
428 public void DeleteOld()
429 {
430 uint now = (uint)Util.UnixTimeSinceEpoch();
431
432 using (MySqlCommand cmd = new MySqlCommand())
433 {
434 cmd.CommandText = String.Format("delete from {0} where TMStamp < ?tstamp", m_Realm);
435 cmd.Parameters.AddWithValue("?tstamp", now - 14 * 24 * 60 * 60); // > 2 weeks old
436
437 ExecuteNonQuery(cmd);
438 }
439
440 }
441 }
442
443 public class MySqlGroupsNoticesHandler : MySQLGenericTableHandler<NoticeData>
444 {
445 protected override Assembly Assembly
446 {
447 // WARNING! Moving migrations to this assembly!!!
448 get { return GetType().Assembly; }
449 }
450
451 public MySqlGroupsNoticesHandler(string connectionString, string realm)
452 : base(connectionString, realm, string.Empty)
453 {
454 }
455
456 public void DeleteOld()
457 {
458 uint now = (uint)Util.UnixTimeSinceEpoch();
459
460 using (MySqlCommand cmd = new MySqlCommand())
461 {
462 cmd.CommandText = String.Format("delete from {0} where TMStamp < ?tstamp", m_Realm);
463 cmd.Parameters.AddWithValue("?tstamp", now - 14 * 24 * 60 * 60); // > 2 weeks old
464
465 ExecuteNonQuery(cmd);
466 }
467
468 }
469 }
470
471 public class MySqlGroupsPrincipalsHandler : MySQLGenericTableHandler<PrincipalData>
472 {
473 protected override Assembly Assembly
474 {
475 // WARNING! Moving migrations to this assembly!!!
476 get { return GetType().Assembly; }
477 }
478
479 public MySqlGroupsPrincipalsHandler(string connectionString, string realm)
480 : base(connectionString, realm, string.Empty)
481 {
482 }
483 }
484}
diff --git a/OpenSim/Data/MySQL/MySQLOfflineIMData.cs b/OpenSim/Data/MySQL/MySQLOfflineIMData.cs
new file mode 100644
index 0000000..252f358
--- /dev/null
+++ b/OpenSim/Data/MySQL/MySQLOfflineIMData.cs
@@ -0,0 +1,62 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using System.Reflection;
32
33using OpenSim.Framework;
34using OpenSim.Data.MySQL;
35
36using OpenMetaverse;
37using MySql.Data.MySqlClient;
38
39namespace OpenSim.Data.MySQL
40{
41 public class MySQLOfflineIMData : MySQLGenericTableHandler<OfflineIMData>, IOfflineIMData
42 {
43 public MySQLOfflineIMData(string connectionString, string realm)
44 : base(connectionString, realm, "IM_Store")
45 {
46 }
47
48 public void DeleteOld()
49 {
50 uint now = (uint)Util.UnixTimeSinceEpoch();
51
52 using (MySqlCommand cmd = new MySqlCommand())
53 {
54 cmd.CommandText = String.Format("delete from {0} where TMStamp < ?tstamp", m_Realm);
55 cmd.Parameters.AddWithValue("?tstamp", now - 14 * 24 * 60 * 60); // > 2 weeks old
56
57 ExecuteNonQuery(cmd);
58 }
59
60 }
61 }
62}
diff --git a/OpenSim/Data/MySQL/Properties/AssemblyInfo.cs b/OpenSim/Data/MySQL/Properties/AssemblyInfo.cs
index 7bfa28d..1146d92 100644
--- a/OpenSim/Data/MySQL/Properties/AssemblyInfo.cs
+++ b/OpenSim/Data/MySQL/Properties/AssemblyInfo.cs
@@ -62,4 +62,4 @@ using System.Runtime.InteropServices;
62// by using the '*' as shown below: 62// by using the '*' as shown below:
63 63
64[assembly : AssemblyVersion("0.7.6.*")] 64[assembly : AssemblyVersion("0.7.6.*")]
65[assembly : AssemblyFileVersion("0.6.5.0")] 65
diff --git a/OpenSim/Data/MySQL/Resources/IM_Store.migrations b/OpenSim/Data/MySQL/Resources/IM_Store.migrations
new file mode 100644
index 0000000..7cfcd43
--- /dev/null
+++ b/OpenSim/Data/MySQL/Resources/IM_Store.migrations
@@ -0,0 +1,24 @@
1:VERSION 1 # --------------------------
2
3BEGIN;
4
5CREATE TABLE `im_offline` (
6 `ID` MEDIUMINT NOT NULL AUTO_INCREMENT,
7 `PrincipalID` char(36) NOT NULL default '',
8 `Message` text NOT NULL,
9 `TMStamp` timestamp NOT NULL,
10 PRIMARY KEY (`ID`),
11 KEY `PrincipalID` (`PrincipalID`)
12) ENGINE=MyISAM;
13
14COMMIT;
15
16:VERSION 2 # --------------------------
17
18BEGIN;
19
20INSERT INTO `im_offline` SELECT * from `diva_im_offline`;
21DROP TABLE `diva_im_offline`;
22DELETE FROM `migrations` WHERE name='diva_im_Store';
23
24COMMIT; \ No newline at end of file
diff --git a/OpenSim/Data/MySQL/Resources/os_groups_Store.migrations b/OpenSim/Data/MySQL/Resources/os_groups_Store.migrations
new file mode 100644
index 0000000..9e6f1c1
--- /dev/null
+++ b/OpenSim/Data/MySQL/Resources/os_groups_Store.migrations
@@ -0,0 +1,115 @@
1:VERSION 1 # --------------------------
2
3BEGIN;
4
5CREATE TABLE `os_groups_groups` (
6 `GroupID` char(36) NOT NULL default '',
7 `Location` varchar(255) NOT NULL default '',
8 `Name` varchar(255) NOT NULL default '',
9 `Charter` text NOT NULL,
10 `InsigniaID` char(36) NOT NULL default '',
11 `FounderID` char(36) NOT NULL default '',
12 `MembershipFee` int(11) NOT NULL default '0',
13 `OpenEnrollment` varchar(255) NOT NULL default '',
14 `ShowInList` int(4) NOT NULL default '0',
15 `AllowPublish` int(4) NOT NULL default '0',
16 `MaturePublish` int(4) NOT NULL default '0',
17 `OwnerRoleID` char(36) NOT NULL default '',
18 PRIMARY KEY (`GroupID`),
19 UNIQUE KEY `Name` (`Name`),
20 FULLTEXT KEY `Name_2` (`Name`)
21) ENGINE=MyISAM;
22
23
24CREATE TABLE `os_groups_membership` (
25 `GroupID`char(36) NOT NULL default '',
26 `PrincipalID` VARCHAR(255) NOT NULL default '',
27 `SelectedRoleID` char(36) NOT NULL default '',
28 `Contribution` int(11) NOT NULL default '0',
29 `ListInProfile` int(4) NOT NULL default '1',
30 `AcceptNotices` int(4) NOT NULL default '1',
31 `AccessToken` char(36) NOT NULL default '',
32 PRIMARY KEY (`GroupID`,`PrincipalID`),
33 KEY `PrincipalID` (`PrincipalID`)
34) ENGINE=MyISAM;
35
36
37CREATE TABLE `os_groups_roles` (
38 `GroupID` char(36) NOT NULL default '',
39 `RoleID` char(36) NOT NULL default '',
40 `Name` varchar(255) NOT NULL default '',
41 `Description` varchar(255) NOT NULL default '',
42 `Title` varchar(255) NOT NULL default '',
43 `Powers` bigint(20) unsigned NOT NULL default '0',
44 PRIMARY KEY (`GroupID`,`RoleID`),
45 KEY `GroupID` (`GroupID`)
46) ENGINE=MyISAM;
47
48
49CREATE TABLE `os_groups_rolemembership` (
50 `GroupID` char(36) NOT NULL default '',
51 `RoleID` char(36) NOT NULL default '',
52 `PrincipalID` VARCHAR(255) NOT NULL default '',
53 PRIMARY KEY (`GroupID`,`RoleID`,`PrincipalID`),
54 KEY `PrincipalID` (`PrincipalID`)
55) ENGINE=MyISAM;
56
57
58CREATE TABLE `os_groups_invites` (
59 `InviteID` char(36) NOT NULL default '',
60 `GroupID` char(36) NOT NULL default '',
61 `RoleID` char(36) NOT NULL default '',
62 `PrincipalID` VARCHAR(255) NOT NULL default '',
63 `TMStamp` timestamp NOT NULL,
64 PRIMARY KEY (`InviteID`),
65 UNIQUE KEY `PrincipalGroup` (`GroupID`,`PrincipalID`)
66) ENGINE=MyISAM;
67
68
69CREATE TABLE `os_groups_notices` (
70 `GroupID` char(36) NOT NULL default '',
71 `NoticeID` char(36) NOT NULL default '',
72 `TMStamp` int(10) unsigned NOT NULL default '0',
73 `FromName` varchar(255) NOT NULL default '',
74 `Subject` varchar(255) NOT NULL default '',
75 `Message` text NOT NULL,
76 `HasAttachment` int(4) NOT NULL default '0',
77 `AttachmentType` int(4) NOT NULL default '0',
78 `AttachmentName` varchar(128) NOT NULL default '',
79 `AttachmentItemID` char(36) NOT NULL default '',
80 `AttachmentOwnerID` varchar(255) NOT NULL default '',
81 PRIMARY KEY (`NoticeID`),
82 KEY `GroupID` (`GroupID`),
83 KEY `TMStamp` (`TMStamp`)
84) ENGINE=MyISAM;
85
86CREATE TABLE `os_groups_principals` (
87 `PrincipalID` VARCHAR(255) NOT NULL default '',
88 `ActiveGroupID` char(36) NOT NULL default '',
89 PRIMARY KEY (`PrincipalID`)
90) ENGINE=MyISAM;
91
92COMMIT;
93
94:VERSION 2 # --------------------------
95
96BEGIN;
97
98INSERT INTO `os_groups_groups` SELECT * from `diva_groups_groups`;
99DROP TABLE `diva_groups_groups`;
100INSERT INTO `os_groups_membership` SELECT * from `diva_groups_membership`;
101DROP TABLE `diva_groups_membership`;
102INSERT INTO `os_groups_roles` SELECT * from `diva_groups_roles`;
103DROP TABLE `diva_groups_roles`;
104INSERT INTO `os_groups_rolemembership` SELECT * from `diva_groups_rolemembership`;
105DROP TABLE `diva_groups_rolemembership`;
106INSERT INTO `os_groups_invites` SELECT * from `diva_groups_invites`;
107DROP TABLE `diva_groups_invites`;
108INSERT INTO `os_groups_notices` SELECT * from `diva_groups_notices`;
109DROP TABLE `diva_groups_notices`;
110INSERT INTO `os_groups_principals` SELECT * from `diva_groups_principals`;
111DROP TABLE `diva_groups_principals`;
112
113DELETE FROM `migrations` WHERE name='diva_im_Store';
114
115COMMIT; \ No newline at end of file
diff --git a/OpenSim/Data/Null/Properties/AssemblyInfo.cs b/OpenSim/Data/Null/Properties/AssemblyInfo.cs
index 3931b3d..1e02c31 100644
--- a/OpenSim/Data/Null/Properties/AssemblyInfo.cs
+++ b/OpenSim/Data/Null/Properties/AssemblyInfo.cs
@@ -62,4 +62,4 @@ using System.Runtime.InteropServices;
62// by using the '*' as shown below: 62// by using the '*' as shown below:
63 63
64[assembly : AssemblyVersion("0.7.6.*")] 64[assembly : AssemblyVersion("0.7.6.*")]
65[assembly : AssemblyFileVersion("0.6.5.0")] 65
diff --git a/OpenSim/Data/Properties/AssemblyInfo.cs b/OpenSim/Data/Properties/AssemblyInfo.cs
index 9f342ad..a85f473 100644
--- a/OpenSim/Data/Properties/AssemblyInfo.cs
+++ b/OpenSim/Data/Properties/AssemblyInfo.cs
@@ -62,4 +62,4 @@ using System.Runtime.InteropServices;
62// by using the '*' as shown below: 62// by using the '*' as shown below:
63 63
64[assembly : AssemblyVersion("0.7.6.*")] 64[assembly : AssemblyVersion("0.7.6.*")]
65[assembly : AssemblyFileVersion("0.6.5.0")] 65
diff --git a/OpenSim/Data/SQLite/Properties/AssemblyInfo.cs b/OpenSim/Data/SQLite/Properties/AssemblyInfo.cs
index ba52f82..992982c 100644
--- a/OpenSim/Data/SQLite/Properties/AssemblyInfo.cs
+++ b/OpenSim/Data/SQLite/Properties/AssemblyInfo.cs
@@ -62,4 +62,4 @@ using System.Runtime.InteropServices;
62// by using the '*' as shown below: 62// by using the '*' as shown below:
63 63
64[assembly : AssemblyVersion("0.7.6.*")] 64[assembly : AssemblyVersion("0.7.6.*")]
65[assembly : AssemblyFileVersion("0.6.5.0")] 65
diff --git a/OpenSim/Framework/AssemblyInfo.cs b/OpenSim/Framework/AssemblyInfo.cs
index b3db56c..d6b4e6a 100644
--- a/OpenSim/Framework/AssemblyInfo.cs
+++ b/OpenSim/Framework/AssemblyInfo.cs
@@ -60,4 +60,3 @@ using System.Runtime.InteropServices;
60// 60//
61 61
62[assembly : AssemblyVersion("0.7.6.*")] 62[assembly : AssemblyVersion("0.7.6.*")]
63[assembly : AssemblyFileVersion("0.6.5.0")] \ No newline at end of file
diff --git a/OpenSim/Framework/AssetLoader/Filesystem/Properties/AssemblyInfo.cs b/OpenSim/Framework/AssetLoader/Filesystem/Properties/AssemblyInfo.cs
index 077244d..feffa26 100644
--- a/OpenSim/Framework/AssetLoader/Filesystem/Properties/AssemblyInfo.cs
+++ b/OpenSim/Framework/AssetLoader/Filesystem/Properties/AssemblyInfo.cs
@@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33
diff --git a/OpenSim/Framework/Communications/Properties/AssemblyInfo.cs b/OpenSim/Framework/Communications/Properties/AssemblyInfo.cs
index cf575ac..df8eb52 100644
--- a/OpenSim/Framework/Communications/Properties/AssemblyInfo.cs
+++ b/OpenSim/Framework/Communications/Properties/AssemblyInfo.cs
@@ -62,4 +62,4 @@ using System.Runtime.InteropServices;
62// by using the '*' as shown below: 62// by using the '*' as shown below:
63 63
64[assembly : AssemblyVersion("0.7.6.*")] 64[assembly : AssemblyVersion("0.7.6.*")]
65[assembly : AssemblyFileVersion("0.6.5.0")] 65
diff --git a/OpenSim/Framework/Configuration/HTTP/Properties/AssemblyInfo.cs b/OpenSim/Framework/Configuration/HTTP/Properties/AssemblyInfo.cs
index c3b6227..3ef9682 100644
--- a/OpenSim/Framework/Configuration/HTTP/Properties/AssemblyInfo.cs
+++ b/OpenSim/Framework/Configuration/HTTP/Properties/AssemblyInfo.cs
@@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33
diff --git a/OpenSim/Framework/Configuration/XML/Properties/AssemblyInfo.cs b/OpenSim/Framework/Configuration/XML/Properties/AssemblyInfo.cs
index b0d2d67..cbdffeb 100644
--- a/OpenSim/Framework/Configuration/XML/Properties/AssemblyInfo.cs
+++ b/OpenSim/Framework/Configuration/XML/Properties/AssemblyInfo.cs
@@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33
diff --git a/OpenSim/Framework/Console/ConsoleUtil.cs b/OpenSim/Framework/Console/ConsoleUtil.cs
index dff956a..97a86a8 100644
--- a/OpenSim/Framework/Console/ConsoleUtil.cs
+++ b/OpenSim/Framework/Console/ConsoleUtil.cs
@@ -49,14 +49,14 @@ namespace OpenSim.Framework.Console
49 = @"Each component of the coord is comma separated. There must be no spaces between the commas. 49 = @"Each component of the coord is comma separated. There must be no spaces between the commas.
50 If you don't care about the z component you can simply omit it. 50 If you don't care about the z component you can simply omit it.
51 If you don't care about the x or y components then you can leave them blank (though a comma is still required) 51 If you don't care about the x or y components then you can leave them blank (though a comma is still required)
52 If you want to specify the maxmimum value of a component then you can use ~ instead of a number 52 If you want to specify the maximum value of a component then you can use ~ instead of a number
53 If you want to specify the minimum value of a component then you can use -~ instead of a number 53 If you want to specify the minimum value of a component then you can use -~ instead of a number
54 e.g. 54 e.g.
55 delete object pos 20,20,20 to 40,40,40 55 show object pos 20,20,20 to 40,40,40
56 delete object pos 20,20 to 40,40 56 delete object pos 20,20 to 40,40
57 delete object pos ,20,20 to ,40,40 57 show object pos ,20,20 to ,40,40
58 delete object pos ,,30 to ,,~ 58 delete object pos ,,30 to ,,~
59 delete object pos ,,-~ to ,,30"; 59 show object pos ,,-~ to ,,30";
60 60
61 public const string MinRawConsoleVectorValue = "-~"; 61 public const string MinRawConsoleVectorValue = "-~";
62 public const string MaxRawConsoleVectorValue = "~"; 62 public const string MaxRawConsoleVectorValue = "~";
diff --git a/OpenSim/Framework/Monitoring/AssetStatsCollector.cs b/OpenSim/Framework/Monitoring/AssetStatsCollector.cs
index 2a4d45b..6a0f676 100644
--- a/OpenSim/Framework/Monitoring/AssetStatsCollector.cs
+++ b/OpenSim/Framework/Monitoring/AssetStatsCollector.cs
@@ -28,6 +28,8 @@
28using System; 28using System;
29using System.Timers; 29using System.Timers;
30 30
31using OpenMetaverse.StructuredData;
32
31namespace OpenSim.Framework.Monitoring 33namespace OpenSim.Framework.Monitoring
32{ 34{
33 /// <summary> 35 /// <summary>
@@ -100,5 +102,29 @@ Asset requests yesterday : {3} ({4} per hour) of which {5} were not found",
100 AssetRequestsToday, assetRequestsTodayPerHour, AssetRequestsNotFoundToday, 102 AssetRequestsToday, assetRequestsTodayPerHour, AssetRequestsNotFoundToday,
101 AssetRequestsYesterday, assetRequestsYesterdayPerHour, AssetRequestsNotFoundYesterday); 103 AssetRequestsYesterday, assetRequestsYesterdayPerHour, AssetRequestsNotFoundYesterday);
102 } 104 }
105
106 public override string XReport(string uptime, string version)
107 {
108 return OSDParser.SerializeJsonString(OReport(uptime, version));
109 }
110
111 public override OSDMap OReport(string uptime, string version)
112 {
113 double elapsedHours = (DateTime.Now - startTime).TotalHours;
114 if (elapsedHours <= 0) { elapsedHours = 1; } // prevent divide by zero
115
116 long assetRequestsTodayPerHour = (long)Math.Round(AssetRequestsToday / elapsedHours);
117 long assetRequestsYesterdayPerHour = (long)Math.Round(AssetRequestsYesterday / 24.0);
118
119 OSDMap ret = new OSDMap();
120 ret.Add("AssetRequestsToday", OSD.FromLong(AssetRequestsToday));
121 ret.Add("AssetRequestsTodayPerHour", OSD.FromLong(assetRequestsTodayPerHour));
122 ret.Add("AssetRequestsNotFoundToday", OSD.FromLong(AssetRequestsNotFoundToday));
123 ret.Add("AssetRequestsYesterday", OSD.FromLong(AssetRequestsYesterday));
124 ret.Add("AssetRequestsYesterdayPerHour", OSD.FromLong(assetRequestsYesterdayPerHour));
125 ret.Add("AssetRequestsNotFoundYesterday", OSD.FromLong(assetRequestsNotFoundYesterday));
126
127 return ret;
128 }
103 } 129 }
104} 130}
diff --git a/OpenSim/Framework/Monitoring/BaseStatsCollector.cs b/OpenSim/Framework/Monitoring/BaseStatsCollector.cs
index 446e3c0..23dba09 100644
--- a/OpenSim/Framework/Monitoring/BaseStatsCollector.cs
+++ b/OpenSim/Framework/Monitoring/BaseStatsCollector.cs
@@ -80,5 +80,12 @@ namespace OpenSim.Framework.Monitoring
80 { 80 {
81 return (string) Math.Round(GC.GetTotalMemory(false) / 1024.0 / 1024.0).ToString() ; 81 return (string) Math.Round(GC.GetTotalMemory(false) / 1024.0 / 1024.0).ToString() ;
82 } 82 }
83
84 public virtual OSDMap OReport(string uptime, string version)
85 {
86 OSDMap ret = new OSDMap();
87 ret.Add("TotalMemory", new OSDReal(Math.Round(GC.GetTotalMemory(false) / 1024.0 / 1024.0)));
88 return ret;
89 }
83 } 90 }
84} 91}
diff --git a/OpenSim/Framework/Monitoring/Interfaces/IStatsCollector.cs b/OpenSim/Framework/Monitoring/Interfaces/IStatsCollector.cs
index 99f75e3..40df562 100644
--- a/OpenSim/Framework/Monitoring/Interfaces/IStatsCollector.cs
+++ b/OpenSim/Framework/Monitoring/Interfaces/IStatsCollector.cs
@@ -25,6 +25,8 @@
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28using OpenMetaverse.StructuredData;
29
28namespace OpenSim.Framework.Monitoring 30namespace OpenSim.Framework.Monitoring
29{ 31{
30 /// <summary> 32 /// <summary>
@@ -45,5 +47,12 @@ namespace OpenSim.Framework.Monitoring
45 /// A <see cref="System.String"/> 47 /// A <see cref="System.String"/>
46 /// </returns> 48 /// </returns>
47 string XReport(string uptime, string version); 49 string XReport(string uptime, string version);
50
51 /// <summary>
52 /// Report back collected statistical information as an OSDMap of key/values
53 /// </summary>
54 /// <returns>
55 /// </returns>
56 OSDMap OReport(string uptime, string version);
48 } 57 }
49} 58}
diff --git a/OpenSim/Framework/Monitoring/Properties/AssemblyInfo.cs b/OpenSim/Framework/Monitoring/Properties/AssemblyInfo.cs
index bb83db1..36678bb 100644
--- a/OpenSim/Framework/Monitoring/Properties/AssemblyInfo.cs
+++ b/OpenSim/Framework/Monitoring/Properties/AssemblyInfo.cs
@@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33
diff --git a/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs b/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs
index 3765efb..109a58f 100644
--- a/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs
+++ b/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs
@@ -405,6 +405,15 @@ Asset service request failures: {3}" + Environment.NewLine,
405 /// <returns></returns> 405 /// <returns></returns>
406 public override string XReport(string uptime, string version) 406 public override string XReport(string uptime, string version)
407 { 407 {
408 return OSDParser.SerializeJsonString(OReport(uptime, version));
409 }
410
411 /// <summary>
412 /// Report back collected statistical information as an OSDMap
413 /// </summary>
414 /// <returns></returns>
415 public override OSDMap OReport(string uptime, string version)
416 {
408 OSDMap args = new OSDMap(30); 417 OSDMap args = new OSDMap(30);
409// args["AssetsInCache"] = OSD.FromString (String.Format ("{0:0.##}", AssetsInCache)); 418// args["AssetsInCache"] = OSD.FromString (String.Format ("{0:0.##}", AssetsInCache));
410// args["TimeAfterCacheMiss"] = OSD.FromString (String.Format ("{0:0.##}", 419// args["TimeAfterCacheMiss"] = OSD.FromString (String.Format ("{0:0.##}",
@@ -442,13 +451,11 @@ Asset service request failures: {3}" + Environment.NewLine,
442 args["Uptime"] = OSD.FromString (uptime); 451 args["Uptime"] = OSD.FromString (uptime);
443 args["Version"] = OSD.FromString (version); 452 args["Version"] = OSD.FromString (version);
444 453
445 string strBuffer = ""; 454 return args;
446 strBuffer = OSDParser.SerializeJsonString(args);
447
448 return strBuffer;
449 } 455 }
450 } 456 }
451 457
458
452 /// <summary> 459 /// <summary>
453 /// Pull packet queue stats from packet queues and report 460 /// Pull packet queue stats from packet queues and report
454 /// </summary> 461 /// </summary>
@@ -474,5 +481,11 @@ Asset service request failures: {3}" + Environment.NewLine,
474 { 481 {
475 return ""; 482 return "";
476 } 483 }
484
485 public OSDMap OReport(string uptime, string version)
486 {
487 OSDMap ret = new OSDMap();
488 return ret;
489 }
477 } 490 }
478} 491}
diff --git a/OpenSim/Framework/Monitoring/Stats/CounterStat.cs b/OpenSim/Framework/Monitoring/Stats/CounterStat.cs
new file mode 100755
index 0000000..d81f182
--- /dev/null
+++ b/OpenSim/Framework/Monitoring/Stats/CounterStat.cs
@@ -0,0 +1,211 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Linq;
31using System.Text;
32
33using OpenMetaverse.StructuredData;
34
35namespace OpenSim.Framework.Monitoring
36{
37// Create a time histogram of events. The histogram is built in a wrap-around
38// array of equally distributed buckets.
39// For instance, a minute long histogram of second sized buckets would be:
40// new EventHistogram(60, 1000)
41public class EventHistogram
42{
43 private int m_timeBase;
44 private int m_numBuckets;
45 private int m_bucketMilliseconds;
46 private int m_lastBucket;
47 private int m_totalHistogramMilliseconds;
48 private long[] m_histogram;
49 private object histoLock = new object();
50
51 public EventHistogram(int numberOfBuckets, int millisecondsPerBucket)
52 {
53 m_numBuckets = numberOfBuckets;
54 m_bucketMilliseconds = millisecondsPerBucket;
55 m_totalHistogramMilliseconds = m_numBuckets * m_bucketMilliseconds;
56
57 m_histogram = new long[m_numBuckets];
58 Zero();
59 m_lastBucket = 0;
60 m_timeBase = Util.EnvironmentTickCount();
61 }
62
63 public void Event()
64 {
65 this.Event(1);
66 }
67
68 // Record an event at time 'now' in the histogram.
69 public void Event(int cnt)
70 {
71 lock (histoLock)
72 {
73 // The time as displaced from the base of the histogram
74 int bucketTime = Util.EnvironmentTickCountSubtract(m_timeBase);
75
76 // If more than the total time of the histogram, we just start over
77 if (bucketTime > m_totalHistogramMilliseconds)
78 {
79 Zero();
80 m_lastBucket = 0;
81 m_timeBase = Util.EnvironmentTickCount();
82 }
83 else
84 {
85 // To which bucket should we add this event?
86 int bucket = bucketTime / m_bucketMilliseconds;
87
88 // Advance m_lastBucket to the new bucket. Zero any buckets skipped over.
89 while (bucket != m_lastBucket)
90 {
91 // Zero from just after the last bucket to the new bucket or the end
92 for (int jj = m_lastBucket + 1; jj <= Math.Min(bucket, m_numBuckets - 1); jj++)
93 {
94 m_histogram[jj] = 0;
95 }
96 m_lastBucket = bucket;
97 // If the new bucket is off the end, wrap around to the beginning
98 if (bucket > m_numBuckets)
99 {
100 bucket -= m_numBuckets;
101 m_lastBucket = 0;
102 m_histogram[m_lastBucket] = 0;
103 m_timeBase += m_totalHistogramMilliseconds;
104 }
105 }
106 }
107 m_histogram[m_lastBucket] += cnt;
108 }
109 }
110
111 // Get a copy of the current histogram
112 public long[] GetHistogram()
113 {
114 long[] ret = new long[m_numBuckets];
115 lock (histoLock)
116 {
117 int indx = m_lastBucket + 1;
118 for (int ii = 0; ii < m_numBuckets; ii++, indx++)
119 {
120 if (indx >= m_numBuckets)
121 indx = 0;
122 ret[ii] = m_histogram[indx];
123 }
124 }
125 return ret;
126 }
127
128 // Get a copy of the current histogram
129 public OSDArray GetHistogramAsOSDArray()
130 {
131 OSDArray ret = new OSDArray(m_numBuckets);
132 lock (histoLock)
133 {
134 int indx = m_lastBucket + 1;
135 for (int ii = 0; ii < m_numBuckets; ii++, indx++)
136 {
137 if (indx >= m_numBuckets)
138 indx = 0;
139 ret[ii] = OSD.FromLong(m_histogram[indx]);
140 }
141 }
142 return ret;
143 }
144
145 // Zero out the histogram
146 public void Zero()
147 {
148 lock (histoLock)
149 {
150 for (int ii = 0; ii < m_numBuckets; ii++)
151 m_histogram[ii] = 0;
152 }
153 }
154}
155
156// A statistic that wraps a counter.
157// Built this way mostly so histograms and history can be created.
158public class CounterStat : Stat
159{
160 private SortedDictionary<string, EventHistogram> m_histograms;
161 private object counterLock = new object();
162
163 public CounterStat(
164 string shortName,
165 string name,
166 string description,
167 string unitName,
168 string category,
169 string container,
170 StatVerbosity verbosity)
171 : base(shortName, name, description, unitName, category, container, StatType.Push, null, verbosity)
172 {
173 m_histograms = new SortedDictionary<string, EventHistogram>();
174 }
175
176 // Histograms are presumably added at intialization time and the list does not change thereafter.
177 // Thus no locking of the histogram list.
178 public void AddHistogram(string histoName, EventHistogram histo)
179 {
180 m_histograms.Add(histoName, histo);
181 }
182
183 public delegate void ProcessHistogram(string name, EventHistogram histo);
184 public void ForEachHistogram(ProcessHistogram process)
185 {
186 foreach (KeyValuePair<string, EventHistogram> kvp in m_histograms)
187 {
188 process(kvp.Key, kvp.Value);
189 }
190 }
191
192 public void Event()
193 {
194 this.Event(1);
195 }
196
197 // Count the underlying counter.
198 public void Event(int cnt)
199 {
200 lock (counterLock)
201 {
202 base.Value += cnt;
203
204 foreach (EventHistogram histo in m_histograms.Values)
205 {
206 histo.Event(cnt);
207 }
208 }
209 }
210}
211}
diff --git a/OpenSim/Framework/Monitoring/Stats/Stat.cs b/OpenSim/Framework/Monitoring/Stats/Stat.cs
index f91251b..c8d9174 100644
--- a/OpenSim/Framework/Monitoring/Stats/Stat.cs
+++ b/OpenSim/Framework/Monitoring/Stats/Stat.cs
@@ -29,12 +29,14 @@ using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Text; 30using System.Text;
31 31
32using OpenMetaverse.StructuredData;
33
32namespace OpenSim.Framework.Monitoring 34namespace OpenSim.Framework.Monitoring
33{ 35{
34 /// <summary> 36 /// <summary>
35 /// Holds individual statistic details 37 /// Holds individual statistic details
36 /// </summary> 38 /// </summary>
37 public class Stat 39 public class Stat : IDisposable
38 { 40 {
39 /// <summary> 41 /// <summary>
40 /// Category of this stat (e.g. cache, scene, etc). 42 /// Category of this stat (e.g. cache, scene, etc).
@@ -181,6 +183,12 @@ namespace OpenSim.Framework.Monitoring
181 Verbosity = verbosity; 183 Verbosity = verbosity;
182 } 184 }
183 185
186 // IDisposable.Dispose()
187 public virtual void Dispose()
188 {
189 return;
190 }
191
184 /// <summary> 192 /// <summary>
185 /// Record a value in the sample set. 193 /// Record a value in the sample set.
186 /// </summary> 194 /// </summary>
@@ -210,6 +218,20 @@ namespace OpenSim.Framework.Monitoring
210 return sb.ToString(); 218 return sb.ToString();
211 } 219 }
212 220
221 public virtual OSDMap ToOSDMap()
222 {
223 OSDMap ret = new OSDMap();
224 ret.Add("Category", OSD.FromString(Category));
225 ret.Add("Container", OSD.FromString(Container));
226 ret.Add("ShortName", OSD.FromString(ShortName));
227 ret.Add("Name", OSD.FromString(Name));
228 ret.Add("Description", OSD.FromString(Description));
229 ret.Add("UnitName", OSD.FromString(UnitName));
230 ret.Add("Value", OSD.FromReal(Value));
231
232 return ret;
233 }
234
213 protected void AppendMeasuresOfInterest(StringBuilder sb) 235 protected void AppendMeasuresOfInterest(StringBuilder sb)
214 { 236 {
215 if ((MeasuresOfInterest & MeasuresOfInterest.AverageChangeOverTime) 237 if ((MeasuresOfInterest & MeasuresOfInterest.AverageChangeOverTime)
diff --git a/OpenSim/Framework/Monitoring/UserStatsCollector.cs b/OpenSim/Framework/Monitoring/UserStatsCollector.cs
index e89c8e6..81e0fa4 100644
--- a/OpenSim/Framework/Monitoring/UserStatsCollector.cs
+++ b/OpenSim/Framework/Monitoring/UserStatsCollector.cs
@@ -27,6 +27,8 @@
27 27
28using System.Timers; 28using System.Timers;
29 29
30using OpenMetaverse.StructuredData;
31
30namespace OpenSim.Framework.Monitoring 32namespace OpenSim.Framework.Monitoring
31{ 33{
32 /// <summary> 34 /// <summary>
@@ -88,5 +90,21 @@ namespace OpenSim.Framework.Monitoring
88 Logouts total : {3}", 90 Logouts total : {3}",
89 SuccessfulLogins, SuccessfulLoginsToday, SuccessfulLoginsYesterday, Logouts); 91 SuccessfulLogins, SuccessfulLoginsToday, SuccessfulLoginsYesterday, Logouts);
90 } 92 }
93
94 public override string XReport(string uptime, string version)
95 {
96 return OSDParser.SerializeJsonString(OReport(uptime, version));
97 }
98
99 public override OSDMap OReport(string uptime, string version)
100 {
101 OSDMap ret = new OSDMap();
102 ret.Add("SuccessfulLogins", OSD.FromInteger(SuccessfulLogins));
103 ret.Add("SuccessfulLoginsToday", OSD.FromInteger(SuccessfulLoginsToday));
104 ret.Add("SuccessfulLoginsYesterday", OSD.FromInteger(SuccessfulLoginsYesterday));
105 ret.Add("Logouts", OSD.FromInteger(Logouts));
106
107 return ret;
108 }
91 } 109 }
92} 110}
diff --git a/OpenSim/Framework/RegionLoader/Filesystem/Properties/AssemblyInfo.cs b/OpenSim/Framework/RegionLoader/Filesystem/Properties/AssemblyInfo.cs
index f836350..d4806f1 100644
--- a/OpenSim/Framework/RegionLoader/Filesystem/Properties/AssemblyInfo.cs
+++ b/OpenSim/Framework/RegionLoader/Filesystem/Properties/AssemblyInfo.cs
@@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33
diff --git a/OpenSim/Framework/RegionLoader/Web/Properties/AssemblyInfo.cs b/OpenSim/Framework/RegionLoader/Web/Properties/AssemblyInfo.cs
index 72fa679..1541a5b 100644
--- a/OpenSim/Framework/RegionLoader/Web/Properties/AssemblyInfo.cs
+++ b/OpenSim/Framework/RegionLoader/Web/Properties/AssemblyInfo.cs
@@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33
diff --git a/OpenSim/Framework/Serialization/Properties/AssemblyInfo.cs b/OpenSim/Framework/Serialization/Properties/AssemblyInfo.cs
index 7a122da..a8dff93 100644
--- a/OpenSim/Framework/Serialization/Properties/AssemblyInfo.cs
+++ b/OpenSim/Framework/Serialization/Properties/AssemblyInfo.cs
@@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33
diff --git a/OpenSim/Framework/Servers/HttpServer/Properties/AssemblyInfo.cs b/OpenSim/Framework/Servers/HttpServer/Properties/AssemblyInfo.cs
index 386be2d..8e592c1 100644
--- a/OpenSim/Framework/Servers/HttpServer/Properties/AssemblyInfo.cs
+++ b/OpenSim/Framework/Servers/HttpServer/Properties/AssemblyInfo.cs
@@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33
diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs
index 0545365..724e38b 100644
--- a/OpenSim/Framework/Util.cs
+++ b/OpenSim/Framework/Util.cs
@@ -875,7 +875,7 @@ namespace OpenSim.Framework
875 return FileName; 875 return FileName;
876 } 876 }
877 877
878 // Nini (config) related Methods 878 #region Nini (config) related Methods
879 public static IConfigSource ConvertDataRowToXMLConfig(DataRow row, string fileName) 879 public static IConfigSource ConvertDataRowToXMLConfig(DataRow row, string fileName)
880 { 880 {
881 if (!File.Exists(fileName)) 881 if (!File.Exists(fileName))
@@ -898,6 +898,26 @@ namespace OpenSim.Framework
898 } 898 }
899 } 899 }
900 900
901 public static string GetConfigVarWithDefaultSection(IConfigSource config, string varname, string section)
902 {
903 // First, check the Startup section, the default section
904 IConfig cnf = config.Configs["Startup"];
905 if (cnf == null)
906 return string.Empty;
907 string val = cnf.GetString(varname, string.Empty);
908
909 // Then check for an overwrite of the default in the given section
910 if (!string.IsNullOrEmpty(section))
911 {
912 cnf = config.Configs[section];
913 if (cnf != null)
914 val = cnf.GetString(varname, val);
915 }
916
917 return val;
918 }
919 #endregion
920
901 public static float Clip(float x, float min, float max) 921 public static float Clip(float x, float min, float max)
902 { 922 {
903 return Math.Min(Math.Max(x, min), max); 923 return Math.Min(Math.Max(x, min), max);
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
index d7d4708..9b945f4 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
@@ -1445,7 +1445,7 @@ namespace OpenSim.Region.ClientStack.Linden
1445 string param, IOSHttpRequest httpRequest, 1445 string param, IOSHttpRequest httpRequest,
1446 IOSHttpResponse httpResponse) 1446 IOSHttpResponse httpResponse)
1447 { 1447 {
1448 OSDMap req = (OSDMap)OSDParser.DeserializeLLSDXml(request); 1448// OSDMap req = (OSDMap)OSDParser.DeserializeLLSDXml(request);
1449 OSDMap resp = new OSDMap(); 1449 OSDMap resp = new OSDMap();
1450 1450
1451 OSDMap accessPrefs = new OSDMap(); 1451 OSDMap accessPrefs = new OSDMap();
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/Properties/AssemblyInfo.cs b/OpenSim/Region/ClientStack/Linden/Caps/Properties/AssemblyInfo.cs
index d29a001..595d01a 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/Properties/AssemblyInfo.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/Properties/AssemblyInfo.cs
@@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs
index fcac182..79d56c4 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs
@@ -56,8 +56,8 @@ namespace OpenSim.Region.ClientStack.Linden
56 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "RegionConsoleModule")] 56 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "RegionConsoleModule")]
57 public class RegionConsoleModule : INonSharedRegionModule, IRegionConsole 57 public class RegionConsoleModule : INonSharedRegionModule, IRegionConsole
58 { 58 {
59 private static readonly ILog m_log = 59// private static readonly ILog m_log =
60 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 60// LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
61 61
62 private Scene m_scene; 62 private Scene m_scene;
63 private IEventQueue m_eventQueue; 63 private IEventQueue m_eventQueue;
@@ -164,8 +164,8 @@ namespace OpenSim.Region.ClientStack.Linden
164 164
165 public class ConsoleHandler : BaseStreamHandler 165 public class ConsoleHandler : BaseStreamHandler
166 { 166 {
167 private static readonly ILog m_log = 167// private static readonly ILog m_log =
168 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 168// LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
169 169
170 private RegionConsoleModule m_consoleModule; 170 private RegionConsoleModule m_consoleModule;
171 private UUID m_agentID; 171 private UUID m_agentID;
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
index f1fe6e1..cc4d014 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
@@ -3892,6 +3892,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3892 { 3892 {
3893 part.Shape.LightEntry = false; 3893 part.Shape.LightEntry = false;
3894 } 3894 }
3895
3896 if (part.Shape != null && (part.Shape.SculptType == (byte)SculptType.Mesh))
3897 {
3898 // Ensure that mesh has at least 8 valid faces
3899 part.Shape.ProfileBegin = 12500;
3900 part.Shape.ProfileEnd = 0;
3901 part.Shape.ProfileHollow = 27500;
3902 }
3895 } 3903 }
3896 } 3904 }
3897 3905
@@ -12448,6 +12456,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12448 return String.Empty; 12456 return String.Empty;
12449 } 12457 }
12450 12458
12459 public OSDMap OReport(string uptime, string version)
12460 {
12461 return new OSDMap();
12462 }
12463
12451 /// <summary> 12464 /// <summary>
12452 /// Make an asset request to the asset service in response to a client request. 12465 /// Make an asset request to the asset service in response to a client request.
12453 /// </summary> 12466 /// </summary>
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Properties/AssemblyInfo.cs b/OpenSim/Region/ClientStack/Linden/UDP/Properties/AssemblyInfo.cs
index 8f9dad3..98ef72f 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/Properties/AssemblyInfo.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/Properties/AssemblyInfo.cs
@@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33
diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
index 208bc9e..864f33e 100644
--- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
@@ -1090,7 +1090,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
1090 } 1090 }
1091 1091
1092 bool bakedTextureValid = m_scene.AvatarFactory.ValidateBakedTextureCache(sp); 1092 bool bakedTextureValid = m_scene.AvatarFactory.ValidateBakedTextureCache(sp);
1093 outputAction("{0} baked appearance texture is {1}", sp.Name, bakedTextureValid ? "OK" : "corrupt"); 1093 outputAction("{0} baked appearance texture is {1}", sp.Name, bakedTextureValid ? "OK" : "incomplete");
1094 } 1094 }
1095 } 1095 }
1096} 1096}
diff --git a/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs b/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs
index 232a4fe..784a788 100644
--- a/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs
@@ -65,7 +65,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure
65 { 65 {
66 m_Enabled = true; 66 m_Enabled = true;
67 67
68 m_ThisGridURL = config.Configs["Messaging"].GetString("Gatekeeper", string.Empty); 68 m_ThisGridURL = Util.GetConfigVarWithDefaultSection(config, "GatekeeperURI", "Messaging");
69 // Legacy. Remove soon!
70 m_ThisGridURL = config.Configs["Messaging"].GetString("Gatekeeper", m_ThisGridURL);
69 m_log.DebugFormat("[LURE MODULE]: {0} enabled", Name); 71 m_log.DebugFormat("[LURE MODULE]: {0} enabled", Name);
70 } 72 }
71 } 73 }
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs
index 964efda..c439ea8 100644
--- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs
@@ -88,12 +88,11 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
88 IConfig thisModuleConfig = source.Configs["HGInventoryAccessModule"]; 88 IConfig thisModuleConfig = source.Configs["HGInventoryAccessModule"];
89 if (thisModuleConfig != null) 89 if (thisModuleConfig != null)
90 { 90 {
91 // legacy configuration [obsolete] 91 m_HomeURI = Util.GetConfigVarWithDefaultSection(source, "HomeURI", "HGInventoryAccessModule");
92 m_HomeURI = thisModuleConfig.GetString("ProfileServerURI", string.Empty);
93 // preferred
94 m_HomeURI = thisModuleConfig.GetString("HomeURI", m_HomeURI);
95 m_OutboundPermission = thisModuleConfig.GetBoolean("OutboundPermission", true); 92 m_OutboundPermission = thisModuleConfig.GetBoolean("OutboundPermission", true);
96 m_ThisGatekeeper = thisModuleConfig.GetString("Gatekeeper", string.Empty); 93 m_ThisGatekeeper = Util.GetConfigVarWithDefaultSection(source, "GatekeeperURI", "HGInventoryAccessModule");
94 // Legacy. Renove soon!
95 m_ThisGatekeeper = thisModuleConfig.GetString("Gatekeeper", m_ThisGatekeeper);
97 m_RestrictInventoryAccessAbroad = thisModuleConfig.GetBoolean("RestrictInventoryAccessAbroad", true); 96 m_RestrictInventoryAccessAbroad = thisModuleConfig.GetBoolean("RestrictInventoryAccessAbroad", true);
98 } 97 }
99 else 98 else
diff --git a/OpenSim/Region/CoreModules/Framework/Statistics/Logging/LogWriter.cs b/OpenSim/Region/CoreModules/Framework/Statistics/Logging/LogWriter.cs
index fd8d5e3..3c8e0ef 100755
--- a/OpenSim/Region/CoreModules/Framework/Statistics/Logging/LogWriter.cs
+++ b/OpenSim/Region/CoreModules/Framework/Statistics/Logging/LogWriter.cs
@@ -52,6 +52,7 @@ namespace OpenSim.Region.CoreModules.Framework.Statistics.Logging
52 private TimeSpan m_logFileLife; 52 private TimeSpan m_logFileLife;
53 private DateTime m_logFileEndTime; 53 private DateTime m_logFileEndTime;
54 private Object m_logFileWriteLock = new Object(); 54 private Object m_logFileWriteLock = new Object();
55 private bool m_flushWrite;
55 56
56 // set externally when debugging. If let 'null', this does not write any error messages. 57 // set externally when debugging. If let 'null', this does not write any error messages.
57 public ILog ErrorLogger = null; 58 public ILog ErrorLogger = null;
@@ -73,7 +74,9 @@ namespace OpenSim.Region.CoreModules.Framework.Statistics.Logging
73 /// <param name="dir">The directory to create the log file in. May be 'null' for default.</param> 74 /// <param name="dir">The directory to create the log file in. May be 'null' for default.</param>
74 /// <param name="headr">The characters that begin the log file name. May be 'null' for default.</param> 75 /// <param name="headr">The characters that begin the log file name. May be 'null' for default.</param>
75 /// <param name="maxFileTime">Maximum age of a log file in minutes. If zero, will set default.</param> 76 /// <param name="maxFileTime">Maximum age of a log file in minutes. If zero, will set default.</param>
76 public LogWriter(string dir, string headr, int maxFileTime) 77 /// <param name="flushWrite">Whether to do a flush after every log write. Best left off but
78 /// if one is looking for a crash, this is a good thing to turn on.</param>
79 public LogWriter(string dir, string headr, int maxFileTime, bool flushWrite)
77 { 80 {
78 m_logDirectory = dir == null ? "." : dir; 81 m_logDirectory = dir == null ? "." : dir;
79 82
@@ -86,8 +89,14 @@ namespace OpenSim.Region.CoreModules.Framework.Statistics.Logging
86 m_logFileLife = new TimeSpan(0, m_logMaxFileTimeMin, 0); 89 m_logFileLife = new TimeSpan(0, m_logMaxFileTimeMin, 0);
87 m_logFileEndTime = DateTime.Now + m_logFileLife; 90 m_logFileEndTime = DateTime.Now + m_logFileLife;
88 91
92 m_flushWrite = flushWrite;
93
89 Enabled = true; 94 Enabled = true;
90 } 95 }
96 // Constructor that assumes flushWrite is off.
97 public LogWriter(string dir, string headr, int maxFileTime) : this(dir, headr, maxFileTime, false)
98 {
99 }
91 100
92 public void Dispose() 101 public void Dispose()
93 { 102 {
@@ -153,6 +162,8 @@ namespace OpenSim.Region.CoreModules.Framework.Statistics.Logging
153 buff.Append(line); 162 buff.Append(line);
154 buff.Append("\r\n"); 163 buff.Append("\r\n");
155 m_logFile.Write(buff.ToString()); 164 m_logFile.Write(buff.ToString());
165 if (m_flushWrite)
166 m_logFile.Flush();
156 } 167 }
157 } 168 }
158 } 169 }
diff --git a/OpenSim/Region/CoreModules/Properties/AssemblyInfo.cs b/OpenSim/Region/CoreModules/Properties/AssemblyInfo.cs
index f6353f9..bfe0383 100644
--- a/OpenSim/Region/CoreModules/Properties/AssemblyInfo.cs
+++ b/OpenSim/Region/CoreModules/Properties/AssemblyInfo.cs
@@ -31,7 +31,7 @@ using Mono.Addins;
31// Revision 31// Revision
32// 32//
33[assembly: AssemblyVersion("0.7.6.*")] 33[assembly: AssemblyVersion("0.7.6.*")]
34[assembly: AssemblyFileVersion("1.0.0.0")] 34
35 35
36[assembly: Addin("OpenSim.Region.CoreModules", "0.1")] 36[assembly: Addin("OpenSim.Region.CoreModules", "0.1")]
37[assembly: AddinDependency("OpenSim", "0.5")] 37[assembly: AddinDependency("OpenSim", "0.5")]
diff --git a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs
index 9fc2daf..28db407 100644
--- a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs
+++ b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs
@@ -416,7 +416,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
416 416
417 if (!ConsoleUtil.TryParseConsoleMinVector(rawConsoleStartVector, out startVector)) 417 if (!ConsoleUtil.TryParseConsoleMinVector(rawConsoleStartVector, out startVector))
418 { 418 {
419 m_console.OutputFormat("Error: Start vector {0} does not have a valid format", rawConsoleStartVector); 419 m_console.OutputFormat("Error: Start vector '{0}' does not have a valid format", rawConsoleStartVector);
420 return; 420 return;
421 } 421 }
422 422
@@ -425,7 +425,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
425 425
426 if (!ConsoleUtil.TryParseConsoleMaxVector(rawConsoleEndVector, out endVector)) 426 if (!ConsoleUtil.TryParseConsoleMaxVector(rawConsoleEndVector, out endVector))
427 { 427 {
428 m_console.OutputFormat("Error: End vector {0} does not have a valid format", rawConsoleEndVector); 428 m_console.OutputFormat("Error: End vector '{0}' does not have a valid format", rawConsoleEndVector);
429 return; 429 return;
430 } 430 }
431 431
@@ -896,17 +896,17 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
896 896
897 if (!ConsoleUtil.TryParseConsoleMinVector(rawConsoleStartVector, out startVector)) 897 if (!ConsoleUtil.TryParseConsoleMinVector(rawConsoleStartVector, out startVector))
898 { 898 {
899 m_console.OutputFormat("Error: Start vector {0} does not have a valid format", rawConsoleStartVector); 899 m_console.OutputFormat("Error: Start vector '{0}' does not have a valid format", rawConsoleStartVector);
900 endVector = Vector3.Zero; 900 endVector = Vector3.Zero;
901 901
902 return false; 902 return false;
903 } 903 }
904 904
905 string rawConsoleEndVector = rawComponents.Skip(1).Take(1).Single(); 905 string rawConsoleEndVector = rawComponents.Skip(2).Take(1).Single();
906 906
907 if (!ConsoleUtil.TryParseConsoleMaxVector(rawConsoleEndVector, out endVector)) 907 if (!ConsoleUtil.TryParseConsoleMaxVector(rawConsoleEndVector, out endVector))
908 { 908 {
909 m_console.OutputFormat("Error: End vector {0} does not have a valid format", rawConsoleEndVector); 909 m_console.OutputFormat("Error: End vector '{0}' does not have a valid format", rawConsoleEndVector);
910 return false; 910 return false;
911 } 911 }
912 912
diff --git a/OpenSim/Region/DataSnapshot/DataSnapshotManager.cs b/OpenSim/Region/DataSnapshot/DataSnapshotManager.cs
index 5e62f23..13d9d31 100644
--- a/OpenSim/Region/DataSnapshot/DataSnapshotManager.cs
+++ b/OpenSim/Region/DataSnapshot/DataSnapshotManager.cs
@@ -113,9 +113,16 @@ namespace OpenSim.Region.DataSnapshot
113 try 113 try
114 { 114 {
115 m_enabled = config.Configs["DataSnapshot"].GetBoolean("index_sims", m_enabled); 115 m_enabled = config.Configs["DataSnapshot"].GetBoolean("index_sims", m_enabled);
116 IConfig conf = config.Configs["GridService"]; 116 string gatekeeper = Util.GetConfigVarWithDefaultSection(config, "GatekeeperURI", "GridService");
117 if (conf != null) 117 // Legacy. Remove soon!
118 m_gridinfo.Add("gatekeeperURL", conf.GetString("Gatekeeper", String.Empty)); 118 if (string.IsNullOrEmpty(gatekeeper))
119 {
120 IConfig conf = config.Configs["GridService"];
121 if (conf != null)
122 gatekeeper = conf.GetString("Gatekeeper", gatekeeper);
123 }
124 if (!string.IsNullOrEmpty(gatekeeper))
125 m_gridinfo.Add("gatekeeperURL", gatekeeper);
119 126
120 m_gridinfo.Add( 127 m_gridinfo.Add(
121 "name", config.Configs["DataSnapshot"].GetString("gridname", "the lost continent of hippo")); 128 "name", config.Configs["DataSnapshot"].GetString("gridname", "the lost continent of hippo"));
diff --git a/OpenSim/Region/DataSnapshot/Properties/AssemblyInfo.cs b/OpenSim/Region/DataSnapshot/Properties/AssemblyInfo.cs
index 0f083c7..0e7df07 100644
--- a/OpenSim/Region/DataSnapshot/Properties/AssemblyInfo.cs
+++ b/OpenSim/Region/DataSnapshot/Properties/AssemblyInfo.cs
@@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33
diff --git a/OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs b/OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs
index b40d24f..345f01b 100644
--- a/OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs
@@ -51,7 +51,6 @@ namespace OpenSim.Region.Framework.Interfaces
51 51
52 JsonStoreNodeType GetPathType(UUID storeID, string path); 52 JsonStoreNodeType GetPathType(UUID storeID, string path);
53 bool TestStore(UUID storeID); 53 bool TestStore(UUID storeID);
54 bool TestPath(UUID storeID, string path, bool useJson);
55 54
56 bool SetValue(UUID storeID, string path, string value, bool useJson); 55 bool SetValue(UUID storeID, string path, string value, bool useJson);
57 bool RemoveValue(UUID storeID, string path); 56 bool RemoveValue(UUID storeID, string path);
diff --git a/OpenSim/Region/Framework/Properties/AssemblyInfo.cs b/OpenSim/Region/Framework/Properties/AssemblyInfo.cs
index 2a5828e..167c248 100644
--- a/OpenSim/Region/Framework/Properties/AssemblyInfo.cs
+++ b/OpenSim/Region/Framework/Properties/AssemblyInfo.cs
@@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index a57e0d1..9bc9c2d 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -2075,7 +2075,11 @@ namespace OpenSim.Region.Framework.Scenes
2075 // Get terrain height for sub-region in a megaregion if necessary 2075 // Get terrain height for sub-region in a megaregion if necessary
2076 int X = (int)((m_scene.RegionInfo.RegionLocX * Constants.RegionSize) + pos.X); 2076 int X = (int)((m_scene.RegionInfo.RegionLocX * Constants.RegionSize) + pos.X);
2077 int Y = (int)((m_scene.RegionInfo.RegionLocY * Constants.RegionSize) + pos.Y); 2077 int Y = (int)((m_scene.RegionInfo.RegionLocY * Constants.RegionSize) + pos.Y);
2078 UUID target_regionID = m_scene.GridService.GetRegionByPosition(m_scene.RegionInfo.ScopeID, X, Y).RegionID; 2078 GridRegion target_region = m_scene.GridService.GetRegionByPosition(m_scene.RegionInfo.ScopeID, X, Y);
2079 // If X and Y is NaN, target_region will be null
2080 if (target_region == null)
2081 return;
2082 UUID target_regionID = target_region.RegionID;
2079 Scene targetScene = m_scene; 2083 Scene targetScene = m_scene;
2080 2084
2081 if (!SceneManager.Instance.TryGetScene(target_regionID, out targetScene)) 2085 if (!SceneManager.Instance.TryGetScene(target_regionID, out targetScene))
diff --git a/OpenSim/Region/OptionalModules/Avatar/Appearance/AppearanceInfoModule.cs b/OpenSim/Region/OptionalModules/Avatar/Appearance/AppearanceInfoModule.cs
index d718a2f..fa35f0f 100644
--- a/OpenSim/Region/OptionalModules/Avatar/Appearance/AppearanceInfoModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/Appearance/AppearanceInfoModule.cs
@@ -222,7 +222,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Appearance
222 { 222 {
223 bool bakedTextureValid = scene.AvatarFactory.ValidateBakedTextureCache(sp); 223 bool bakedTextureValid = scene.AvatarFactory.ValidateBakedTextureCache(sp);
224 MainConsole.Instance.OutputFormat( 224 MainConsole.Instance.OutputFormat(
225 "{0} baked appearance texture is {1}", sp.Name, bakedTextureValid ? "OK" : "corrupt"); 225 "{0} baked appearance texture is {1}", sp.Name, bakedTextureValid ? "OK" : "incomplete");
226 } 226 }
227 ); 227 );
228 } 228 }
diff --git a/OpenSim/Region/OptionalModules/Properties/AssemblyInfo.cs b/OpenSim/Region/OptionalModules/Properties/AssemblyInfo.cs
index 0065531..70bda72 100644
--- a/OpenSim/Region/OptionalModules/Properties/AssemblyInfo.cs
+++ b/OpenSim/Region/OptionalModules/Properties/AssemblyInfo.cs
@@ -31,7 +31,7 @@ using Mono.Addins;
31// Revision 31// Revision
32// 32//
33[assembly: AssemblyVersion("0.7.6.*")] 33[assembly: AssemblyVersion("0.7.6.*")]
34[assembly: AssemblyFileVersion("1.0.0.0")] 34
35 35
36[assembly: Addin("OpenSim.Region.OptionalModules", "0.1")] 36[assembly: Addin("OpenSim.Region.OptionalModules", "0.1")]
37[assembly: AddinDependency("OpenSim", "0.5")] 37[assembly: AddinDependency("OpenSim", "0.5")]
diff --git a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStore.cs b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStore.cs
index ca3989a..40adba1 100644
--- a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStore.cs
+++ b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStore.cs
@@ -84,11 +84,11 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
84 protected static Regex m_PathComponent = new Regex("\\.({[^}]+}|\\[[0-9]+\\]|\\[\\+\\])"); 84 protected static Regex m_PathComponent = new Regex("\\.({[^}]+}|\\[[0-9]+\\]|\\[\\+\\])");
85 85
86 // extract the internals of an array reference 86 // extract the internals of an array reference
87 protected static Regex m_SimpleArrayPattern = new Regex("\\[([0-9]+)\\]"); 87 protected static Regex m_SimpleArrayPattern = new Regex("^\\[([0-9]+)\\]$");
88 protected static Regex m_ArrayPattern = new Regex("\\[([0-9]+|\\+)\\]"); 88 protected static Regex m_ArrayPattern = new Regex("^\\[([0-9]+|\\+)\\]$");
89 89
90 // extract the internals of a has reference 90 // extract the internals of a has reference
91 protected static Regex m_HashPattern = new Regex("{([^}]+)}"); 91 protected static Regex m_HashPattern = new Regex("^{([^}]+)}$");
92 92
93 // ----------------------------------------------------------------- 93 // -----------------------------------------------------------------
94 /// <summary> 94 /// <summary>
@@ -173,28 +173,6 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
173 /// 173 ///
174 /// </summary> 174 /// </summary>
175 // ----------------------------------------------------------------- 175 // -----------------------------------------------------------------
176 public bool TestPath(string expr, bool useJson)
177 {
178 Stack<string> path;
179 if (! ParsePathExpression(expr,out path))
180 return false;
181
182 OSD result = ProcessPathExpression(ValueStore,path);
183
184 if (result == null)
185 return false;
186
187 if (useJson || OSDBaseType(result.Type))
188 return true;
189
190 return false;
191 }
192
193 // -----------------------------------------------------------------
194 /// <summary>
195 ///
196 /// </summary>
197 // -----------------------------------------------------------------
198 public int ArrayLength(string expr) 176 public int ArrayLength(string expr)
199 { 177 {
200 Stack<string> path; 178 Stack<string> path;
diff --git a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs
index fb35068..e78a2f4 100644
--- a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs
+++ b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs
@@ -302,38 +302,6 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
302 /// 302 ///
303 /// </summary> 303 /// </summary>
304 // ----------------------------------------------------------------- 304 // -----------------------------------------------------------------
305 public bool TestPath(UUID storeID, string path, bool useJson)
306 {
307 if (! m_enabled) return false;
308
309 JsonStore map = null;
310 lock (m_JsonValueStore)
311 {
312 if (! m_JsonValueStore.TryGetValue(storeID,out map))
313 {
314 m_log.InfoFormat("[JsonStore] Missing store {0}",storeID);
315 return false;
316 }
317 }
318
319 try
320 {
321 lock (map)
322 return map.TestPath(path,useJson);
323 }
324 catch (Exception e)
325 {
326 m_log.Error(string.Format("[JsonStore]: Path test failed for {0} in {1}", path, storeID), e);
327 }
328
329 return false;
330 }
331
332 // -----------------------------------------------------------------
333 /// <summary>
334 ///
335 /// </summary>
336 // -----------------------------------------------------------------
337 public bool SetValue(UUID storeID, string path, string value, bool useJson) 305 public bool SetValue(UUID storeID, string path, string value, bool useJson)
338 { 306 {
339 if (! m_enabled) return false; 307 if (! m_enabled) return false;
diff --git a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs
index ef08c05..e13eb56 100644
--- a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs
+++ b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs
@@ -168,32 +168,6 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
168 { 168 {
169 m_comms.RegisterScriptInvocations(this); 169 m_comms.RegisterScriptInvocations(this);
170 m_comms.RegisterConstants(this); 170 m_comms.RegisterConstants(this);
171
172 // m_comms.RegisterScriptInvocation(this, "JsonCreateStore");
173 // m_comms.RegisterScriptInvocation(this, "JsonAttachObjectStore");
174 // m_comms.RegisterScriptInvocation(this, "JsonDestroyStore");
175 // m_comms.RegisterScriptInvocation(this, "JsonTestStore");
176
177 // m_comms.RegisterScriptInvocation(this, "JsonReadNotecard");
178 // m_comms.RegisterScriptInvocation(this, "JsonWriteNotecard");
179
180 // m_comms.RegisterScriptInvocation(this, "JsonTestPathList");
181 // m_comms.RegisterScriptInvocation(this, "JsonTestPath");
182 // m_comms.RegisterScriptInvocation(this, "JsonTestPathJson");
183
184 // m_comms.RegisterScriptInvocation(this, "JsonGetValue");
185 // m_comms.RegisterScriptInvocation(this, "JsonGetValueJson");
186
187 // m_comms.RegisterScriptInvocation(this, "JsonTakeValue");
188 // m_comms.RegisterScriptInvocation(this, "JsonTakeValueJson");
189
190 // m_comms.RegisterScriptInvocation(this, "JsonReadValue");
191 // m_comms.RegisterScriptInvocation(this, "JsonReadValueJson");
192
193 // m_comms.RegisterScriptInvocation(this, "JsonSetValue");
194 // m_comms.RegisterScriptInvocation(this, "JsonSetValueJson");
195
196 // m_comms.RegisterScriptInvocation(this, "JsonRemoveValue");
197 } 171 }
198 catch (Exception e) 172 catch (Exception e)
199 { 173 {
@@ -341,18 +315,6 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
341 return (int)m_store.GetPathType(storeID,path); 315 return (int)m_store.GetPathType(storeID,path);
342 } 316 }
343 317
344 [ScriptInvocation]
345 public int JsonTestPath(UUID hostID, UUID scriptID, UUID storeID, string path)
346 {
347 return m_store.TestPath(storeID,path,false) ? 1 : 0;
348 }
349
350 [ScriptInvocation]
351 public int JsonTestPathJson(UUID hostID, UUID scriptID, UUID storeID, string path)
352 {
353 return m_store.TestPath(storeID,path,true) ? 1 : 0;
354 }
355
356 // ----------------------------------------------------------------- 318 // -----------------------------------------------------------------
357 /// <summary> 319 /// <summary>
358 /// 320 ///
diff --git a/OpenSim/Region/OptionalModules/Scripting/JsonStore/Tests/JsonStoreScriptModuleTests.cs b/OpenSim/Region/OptionalModules/Scripting/JsonStore/Tests/JsonStoreScriptModuleTests.cs
index 3d9ad16..b64dbd4 100644
--- a/OpenSim/Region/OptionalModules/Scripting/JsonStore/Tests/JsonStoreScriptModuleTests.cs
+++ b/OpenSim/Region/OptionalModules/Scripting/JsonStore/Tests/JsonStoreScriptModuleTests.cs
@@ -158,8 +158,8 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore.Tests
158 158
159 Assert.That(dsrv, Is.EqualTo(1)); 159 Assert.That(dsrv, Is.EqualTo(1));
160 160
161 int tprv = (int)InvokeOp("JsonTestPath", storeId, "Hello"); 161 int tprv = (int)InvokeOp("JsonGetPathType", storeId, "Hello");
162 Assert.That(tprv, Is.EqualTo(0)); 162 Assert.That(tprv, Is.EqualTo(JsonStoreScriptModule.JSON_TYPE_UNDEF));
163 } 163 }
164 164
165 [Test] 165 [Test]
@@ -277,8 +277,8 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore.Tests
277 int returnValue = (int)InvokeOp( "JsonRemoveValue", storeId, "Hello"); 277 int returnValue = (int)InvokeOp( "JsonRemoveValue", storeId, "Hello");
278 Assert.That(returnValue, Is.EqualTo(1)); 278 Assert.That(returnValue, Is.EqualTo(1));
279 279
280 int result = (int)InvokeOp("JsonTestPath", storeId, "Hello"); 280 int result = (int)InvokeOp("JsonGetPathType", storeId, "Hello");
281 Assert.That(result, Is.EqualTo(0)); 281 Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_TYPE_UNDEF));
282 282
283 string returnValue2 = (string)InvokeOp("JsonGetValue", storeId, "Hello"); 283 string returnValue2 = (string)InvokeOp("JsonGetValue", storeId, "Hello");
284 Assert.That(returnValue2, Is.EqualTo("")); 284 Assert.That(returnValue2, Is.EqualTo(""));
@@ -291,8 +291,8 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore.Tests
291 int returnValue = (int)InvokeOp( "JsonRemoveValue", storeId, "Hello"); 291 int returnValue = (int)InvokeOp( "JsonRemoveValue", storeId, "Hello");
292 Assert.That(returnValue, Is.EqualTo(1)); 292 Assert.That(returnValue, Is.EqualTo(1));
293 293
294 int result = (int)InvokeOp("JsonTestPath", storeId, "Hello"); 294 int result = (int)InvokeOp("JsonGetPathType", storeId, "Hello");
295 Assert.That(result, Is.EqualTo(0)); 295 Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_TYPE_UNDEF));
296 296
297 string returnValue2 = (string)InvokeOp("JsonGetJson", storeId, "Hello"); 297 string returnValue2 = (string)InvokeOp("JsonGetJson", storeId, "Hello");
298 Assert.That(returnValue2, Is.EqualTo("")); 298 Assert.That(returnValue2, Is.EqualTo(""));
@@ -306,11 +306,11 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore.Tests
306 int returnValue = (int)InvokeOp( "JsonRemoveValue", storeId, "Hello[0]"); 306 int returnValue = (int)InvokeOp( "JsonRemoveValue", storeId, "Hello[0]");
307 Assert.That(returnValue, Is.EqualTo(1)); 307 Assert.That(returnValue, Is.EqualTo(1));
308 308
309 int result = (int)InvokeOp("JsonTestPath", storeId, "Hello[0]"); 309 int result = (int)InvokeOp("JsonGetPathType", storeId, "Hello[0]");
310 Assert.That(result, Is.EqualTo(1)); 310 Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_TYPE_VALUE));
311 311
312 result = (int)InvokeOp("JsonTestPath", storeId, "Hello[1]"); 312 result = (int)InvokeOp("JsonGetPathType", storeId, "Hello[1]");
313 Assert.That(result, Is.EqualTo(0)); 313 Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_TYPE_UNDEF));
314 314
315 string stringReturnValue = (string)InvokeOp("JsonGetValue", storeId, "Hello[0]"); 315 string stringReturnValue = (string)InvokeOp("JsonGetValue", storeId, "Hello[0]");
316 Assert.That(stringReturnValue, Is.EqualTo("value2")); 316 Assert.That(stringReturnValue, Is.EqualTo("value2"));
@@ -400,7 +400,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore.Tests
400// } 400// }
401 401
402 [Test] 402 [Test]
403 public void TestGetArrayLength() 403 public void TestJsonGetArrayLength()
404 { 404 {
405 TestHelpers.InMethod(); 405 TestHelpers.InMethod();
406// TestHelpers.EnableLogging(); 406// TestHelpers.EnableLogging();
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSAPIUnman.cs b/OpenSim/Region/Physics/BulletSPlugin/BSAPIUnman.cs
index ae54499..3a27d2c 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSAPIUnman.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSAPIUnman.cs
@@ -438,6 +438,28 @@ public override BulletConstraint Create6DofConstraintToPoint(BulletWorld world,
438 joinPoint, useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies)); 438 joinPoint, useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies));
439} 439}
440 440
441public override BulletConstraint Create6DofConstraintFixed(BulletWorld world, BulletBody obj1,
442 Vector3 frameInBloc, Quaternion frameInBrot,
443 bool useLinearReferenceFrameB, bool disableCollisionsBetweenLinkedBodies)
444{
445 BulletWorldUnman worldu = world as BulletWorldUnman;
446 BulletBodyUnman bodyu1 = obj1 as BulletBodyUnman;
447 return new BulletConstraintUnman(BSAPICPP.Create6DofConstraintFixed2(worldu.ptr, bodyu1.ptr,
448 frameInBloc, frameInBrot, useLinearReferenceFrameB, disableCollisionsBetweenLinkedBodies));
449}
450
451public override BulletConstraint Create6DofSpringConstraint(BulletWorld world, BulletBody obj1, BulletBody obj2,
452 Vector3 frame1loc, Quaternion frame1rot,
453 Vector3 frame2loc, Quaternion frame2rot,
454 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies)
455{
456 BulletWorldUnman worldu = world as BulletWorldUnman;
457 BulletBodyUnman bodyu1 = obj1 as BulletBodyUnman;
458 BulletBodyUnman bodyu2 = obj2 as BulletBodyUnman;
459 return new BulletConstraintUnman(BSAPICPP.Create6DofSpringConstraint2(worldu.ptr, bodyu1.ptr, bodyu2.ptr, frame1loc, frame1rot,
460 frame2loc, frame2rot, useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies));
461}
462
441public override BulletConstraint CreateHingeConstraint(BulletWorld world, BulletBody obj1, BulletBody obj2, 463public override BulletConstraint CreateHingeConstraint(BulletWorld world, BulletBody obj1, BulletBody obj2,
442 Vector3 pivotinA, Vector3 pivotinB, 464 Vector3 pivotinA, Vector3 pivotinB,
443 Vector3 axisInA, Vector3 axisInB, 465 Vector3 axisInA, Vector3 axisInB,
@@ -450,6 +472,52 @@ public override BulletConstraint CreateHingeConstraint(BulletWorld world, Bullet
450 pivotinA, pivotinB, axisInA, axisInB, useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies)); 472 pivotinA, pivotinB, axisInA, axisInB, useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies));
451} 473}
452 474
475public override BulletConstraint CreateSliderConstraint(BulletWorld world, BulletBody obj1, BulletBody obj2,
476 Vector3 frame1loc, Quaternion frame1rot,
477 Vector3 frame2loc, Quaternion frame2rot,
478 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies)
479{
480 BulletWorldUnman worldu = world as BulletWorldUnman;
481 BulletBodyUnman bodyu1 = obj1 as BulletBodyUnman;
482 BulletBodyUnman bodyu2 = obj2 as BulletBodyUnman;
483 return new BulletConstraintUnman(BSAPICPP.CreateSliderConstraint2(worldu.ptr, bodyu1.ptr, bodyu2.ptr, frame1loc, frame1rot,
484 frame2loc, frame2rot, useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies));
485}
486
487public override BulletConstraint CreateConeTwistConstraint(BulletWorld world, BulletBody obj1, BulletBody obj2,
488 Vector3 frame1loc, Quaternion frame1rot,
489 Vector3 frame2loc, Quaternion frame2rot,
490 bool disableCollisionsBetweenLinkedBodies)
491{
492 BulletWorldUnman worldu = world as BulletWorldUnman;
493 BulletBodyUnman bodyu1 = obj1 as BulletBodyUnman;
494 BulletBodyUnman bodyu2 = obj2 as BulletBodyUnman;
495 return new BulletConstraintUnman(BSAPICPP.CreateConeTwistConstraint2(worldu.ptr, bodyu1.ptr, bodyu2.ptr, frame1loc, frame1rot,
496 frame2loc, frame2rot, disableCollisionsBetweenLinkedBodies));
497}
498
499public override BulletConstraint CreateGearConstraint(BulletWorld world, BulletBody obj1, BulletBody obj2,
500 Vector3 axisInA, Vector3 axisInB,
501 float ratio, bool disableCollisionsBetweenLinkedBodies)
502{
503 BulletWorldUnman worldu = world as BulletWorldUnman;
504 BulletBodyUnman bodyu1 = obj1 as BulletBodyUnman;
505 BulletBodyUnman bodyu2 = obj2 as BulletBodyUnman;
506 return new BulletConstraintUnman(BSAPICPP.CreateGearConstraint2(worldu.ptr, bodyu1.ptr, bodyu2.ptr, axisInA, axisInB,
507 ratio, disableCollisionsBetweenLinkedBodies));
508}
509
510public override BulletConstraint CreatePoint2PointConstraint(BulletWorld world, BulletBody obj1, BulletBody obj2,
511 Vector3 pivotInA, Vector3 pivotInB,
512 bool disableCollisionsBetweenLinkedBodies)
513{
514 BulletWorldUnman worldu = world as BulletWorldUnman;
515 BulletBodyUnman bodyu1 = obj1 as BulletBodyUnman;
516 BulletBodyUnman bodyu2 = obj2 as BulletBodyUnman;
517 return new BulletConstraintUnman(BSAPICPP.CreatePoint2PointConstraint2(worldu.ptr, bodyu1.ptr, bodyu2.ptr, pivotInA, pivotInB,
518 disableCollisionsBetweenLinkedBodies));
519}
520
453public override void SetConstraintEnable(BulletConstraint constrain, float numericTrueFalse) 521public override void SetConstraintEnable(BulletConstraint constrain, float numericTrueFalse)
454{ 522{
455 BulletConstraintUnman constrainu = constrain as BulletConstraintUnman; 523 BulletConstraintUnman constrainu = constrain as BulletConstraintUnman;
@@ -1426,12 +1494,46 @@ public static extern IntPtr Create6DofConstraintToPoint2(IntPtr world, IntPtr ob
1426 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies); 1494 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies);
1427 1495
1428[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 1496[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1497public static extern IntPtr Create6DofConstraintFixed2(IntPtr world, IntPtr obj1,
1498 Vector3 frameInBloc, Quaternion frameInBrot,
1499 bool useLinearReferenceFrameB, bool disableCollisionsBetweenLinkedBodies);
1500
1501[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1502public static extern IntPtr Create6DofSpringConstraint2(IntPtr world, IntPtr obj1, IntPtr obj2,
1503 Vector3 frame1loc, Quaternion frame1rot,
1504 Vector3 frame2loc, Quaternion frame2rot,
1505 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies);
1506
1507[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1429public static extern IntPtr CreateHingeConstraint2(IntPtr world, IntPtr obj1, IntPtr obj2, 1508public static extern IntPtr CreateHingeConstraint2(IntPtr world, IntPtr obj1, IntPtr obj2,
1430 Vector3 pivotinA, Vector3 pivotinB, 1509 Vector3 pivotinA, Vector3 pivotinB,
1431 Vector3 axisInA, Vector3 axisInB, 1510 Vector3 axisInA, Vector3 axisInB,
1432 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies); 1511 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies);
1433 1512
1434[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 1513[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1514public static extern IntPtr CreateSliderConstraint2(IntPtr world, IntPtr obj1, IntPtr obj2,
1515 Vector3 frameInAloc, Quaternion frameInArot,
1516 Vector3 frameInBloc, Quaternion frameInBrot,
1517 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies);
1518
1519[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1520public static extern IntPtr CreateConeTwistConstraint2(IntPtr world, IntPtr obj1, IntPtr obj2,
1521 Vector3 frameInAloc, Quaternion frameInArot,
1522 Vector3 frameInBloc, Quaternion frameInBrot,
1523 bool disableCollisionsBetweenLinkedBodies);
1524
1525[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1526public static extern IntPtr CreateGearConstraint2(IntPtr world, IntPtr obj1, IntPtr obj2,
1527 Vector3 axisInA, Vector3 axisInB,
1528 float ratio, bool disableCollisionsBetweenLinkedBodies);
1529
1530[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1531public static extern IntPtr CreatePoint2PointConstraint2(IntPtr world, IntPtr obj1, IntPtr obj2,
1532 Vector3 pivotInA, Vector3 pivotInB,
1533 bool disableCollisionsBetweenLinkedBodies);
1534
1535
1536[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1435public static extern void SetConstraintEnable2(IntPtr constrain, float numericTrueFalse); 1537public static extern void SetConstraintEnable2(IntPtr constrain, float numericTrueFalse);
1436 1538
1437[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 1539[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs b/OpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs
index 39e62dd..6fc10e9 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs
@@ -559,8 +559,9 @@ private sealed class BulletConstraintXNA : BulletConstraint
559 } 559 }
560 560
561 561
562 //BulletSimAPI.Create6DofConstraint(m_world.ptr, m_body1.ptr, m_body2.ptr,frame1, frame1rot,frame2, frame2rot,useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies)); 562 public override BulletConstraint Create6DofConstraint(BulletWorld pWorld, BulletBody pBody1, BulletBody pBody2,
563 public override BulletConstraint Create6DofConstraint(BulletWorld pWorld, BulletBody pBody1, BulletBody pBody2, Vector3 pframe1, Quaternion pframe1rot, Vector3 pframe2, Quaternion pframe2rot, bool puseLinearReferenceFrameA, bool pdisableCollisionsBetweenLinkedBodies) 563 Vector3 pframe1, Quaternion pframe1rot, Vector3 pframe2, Quaternion pframe2rot,
564 bool puseLinearReferenceFrameA, bool pdisableCollisionsBetweenLinkedBodies)
564 565
565 { 566 {
566 DiscreteDynamicsWorld world = (pWorld as BulletWorldXNA).world; 567 DiscreteDynamicsWorld world = (pWorld as BulletWorldXNA).world;
@@ -584,7 +585,24 @@ private sealed class BulletConstraintXNA : BulletConstraint
584 return new BulletConstraintXNA(consttr); 585 return new BulletConstraintXNA(consttr);
585 } 586 }
586 587
587 588 public override BulletConstraint Create6DofConstraintFixed(BulletWorld pWorld, BulletBody pBody1,
589 Vector3 pframe1, Quaternion pframe1rot,
590 bool pUseLinearReferenceFrameB, bool pdisableCollisionsBetweenLinkedBodies)
591 {
592 DiscreteDynamicsWorld world = (pWorld as BulletWorldXNA).world;
593 RigidBody body1 = (pBody1 as BulletBodyXNA).rigidBody;
594 IndexedVector3 frame1v = new IndexedVector3(pframe1.X, pframe1.Y, pframe1.Z);
595 IndexedQuaternion frame1rot = new IndexedQuaternion(pframe1rot.X, pframe1rot.Y, pframe1rot.Z, pframe1rot.W);
596 IndexedMatrix frame1 = IndexedMatrix.CreateFromQuaternion(frame1rot);
597 frame1._origin = frame1v;
598
599 Generic6DofConstraint consttr = new Generic6DofConstraint(body1, ref frame1, pUseLinearReferenceFrameB);
600 consttr.CalculateTransforms();
601 world.AddConstraint(consttr,pdisableCollisionsBetweenLinkedBodies);
602
603 return new BulletConstraintXNA(consttr);
604 }
605
588 /// <summary> 606 /// <summary>
589 /// 607 ///
590 /// </summary> 608 /// </summary>
@@ -1133,8 +1151,8 @@ private sealed class BulletConstraintXNA : BulletConstraint
1133 p.numberOfSolverIterations = o[0].numberOfSolverIterations; 1151 p.numberOfSolverIterations = o[0].numberOfSolverIterations;
1134 1152
1135 p.linksetImplementation = BSParam.LinksetImplementation; 1153 p.linksetImplementation = BSParam.LinksetImplementation;
1136 p.linkConstraintUseFrameOffset = BSParam.LinkConstraintUseFrameOffset; 1154 p.linkConstraintUseFrameOffset = BSParam.NumericBool(BSParam.LinkConstraintUseFrameOffset);
1137 p.linkConstraintEnableTransMotor = BSParam.LinkConstraintEnableTransMotor; 1155 p.linkConstraintEnableTransMotor = BSParam.NumericBool(BSParam.LinkConstraintEnableTransMotor);
1138 p.linkConstraintTransMotorMaxVel = BSParam.LinkConstraintTransMotorMaxVel; 1156 p.linkConstraintTransMotorMaxVel = BSParam.LinkConstraintTransMotorMaxVel;
1139 p.linkConstraintTransMotorMaxForce = BSParam.LinkConstraintTransMotorMaxForce; 1157 p.linkConstraintTransMotorMaxForce = BSParam.LinkConstraintTransMotorMaxForce;
1140 p.linkConstraintERP = BSParam.LinkConstraintERP; 1158 p.linkConstraintERP = BSParam.LinkConstraintERP;
@@ -1443,129 +1461,130 @@ private sealed class BulletConstraintXNA : BulletConstraint
1443 1461
1444 public BSPhysicsShapeType BSShapeTypeFromBroadPhaseNativeType(BroadphaseNativeTypes pin) 1462 public BSPhysicsShapeType BSShapeTypeFromBroadPhaseNativeType(BroadphaseNativeTypes pin)
1445 { 1463 {
1464 BSPhysicsShapeType ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
1446 switch (pin) 1465 switch (pin)
1447 { 1466 {
1448 case BroadphaseNativeTypes.BOX_SHAPE_PROXYTYPE: 1467 case BroadphaseNativeTypes.BOX_SHAPE_PROXYTYPE:
1449 return BSPhysicsShapeType.SHAPE_BOX; 1468 ret = BSPhysicsShapeType.SHAPE_BOX;
1450 break; 1469 break;
1451 case BroadphaseNativeTypes.TRIANGLE_SHAPE_PROXYTYPE: 1470 case BroadphaseNativeTypes.TRIANGLE_SHAPE_PROXYTYPE:
1452 return BSPhysicsShapeType.SHAPE_UNKNOWN; 1471 ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
1453 break; 1472 break;
1454 1473
1455 case BroadphaseNativeTypes.TETRAHEDRAL_SHAPE_PROXYTYPE: 1474 case BroadphaseNativeTypes.TETRAHEDRAL_SHAPE_PROXYTYPE:
1456 return BSPhysicsShapeType.SHAPE_UNKNOWN; 1475 ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
1457 break; 1476 break;
1458 case BroadphaseNativeTypes.CONVEX_TRIANGLEMESH_SHAPE_PROXYTYPE: 1477 case BroadphaseNativeTypes.CONVEX_TRIANGLEMESH_SHAPE_PROXYTYPE:
1459 return BSPhysicsShapeType.SHAPE_MESH; 1478 ret = BSPhysicsShapeType.SHAPE_MESH;
1460 break; 1479 break;
1461 case BroadphaseNativeTypes.CONVEX_HULL_SHAPE_PROXYTYPE: 1480 case BroadphaseNativeTypes.CONVEX_HULL_SHAPE_PROXYTYPE:
1462 return BSPhysicsShapeType.SHAPE_HULL; 1481 ret = BSPhysicsShapeType.SHAPE_HULL;
1463 break; 1482 break;
1464 case BroadphaseNativeTypes.CONVEX_POINT_CLOUD_SHAPE_PROXYTYPE: 1483 case BroadphaseNativeTypes.CONVEX_POINT_CLOUD_SHAPE_PROXYTYPE:
1465 return BSPhysicsShapeType.SHAPE_UNKNOWN; 1484 ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
1466 break; 1485 break;
1467 case BroadphaseNativeTypes.CUSTOM_POLYHEDRAL_SHAPE_TYPE: 1486 case BroadphaseNativeTypes.CUSTOM_POLYHEDRAL_SHAPE_TYPE:
1468 return BSPhysicsShapeType.SHAPE_UNKNOWN; 1487 ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
1469 break; 1488 break;
1470 //implicit convex shapes 1489 //implicit convex shapes
1471 case BroadphaseNativeTypes.IMPLICIT_CONVEX_SHAPES_START_HERE: 1490 case BroadphaseNativeTypes.IMPLICIT_CONVEX_SHAPES_START_HERE:
1472 return BSPhysicsShapeType.SHAPE_UNKNOWN; 1491 ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
1473 break; 1492 break;
1474 case BroadphaseNativeTypes.SPHERE_SHAPE_PROXYTYPE: 1493 case BroadphaseNativeTypes.SPHERE_SHAPE_PROXYTYPE:
1475 return BSPhysicsShapeType.SHAPE_SPHERE; 1494 ret = BSPhysicsShapeType.SHAPE_SPHERE;
1476 break; 1495 break;
1477 case BroadphaseNativeTypes.MULTI_SPHERE_SHAPE_PROXYTYPE: 1496 case BroadphaseNativeTypes.MULTI_SPHERE_SHAPE_PROXYTYPE:
1478 return BSPhysicsShapeType.SHAPE_UNKNOWN; 1497 ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
1479 break; 1498 break;
1480 case BroadphaseNativeTypes.CAPSULE_SHAPE_PROXYTYPE: 1499 case BroadphaseNativeTypes.CAPSULE_SHAPE_PROXYTYPE:
1481 return BSPhysicsShapeType.SHAPE_CAPSULE; 1500 ret = BSPhysicsShapeType.SHAPE_CAPSULE;
1482 break; 1501 break;
1483 case BroadphaseNativeTypes.CONE_SHAPE_PROXYTYPE: 1502 case BroadphaseNativeTypes.CONE_SHAPE_PROXYTYPE:
1484 return BSPhysicsShapeType.SHAPE_CONE; 1503 ret = BSPhysicsShapeType.SHAPE_CONE;
1485 break; 1504 break;
1486 case BroadphaseNativeTypes.CONVEX_SHAPE_PROXYTYPE: 1505 case BroadphaseNativeTypes.CONVEX_SHAPE_PROXYTYPE:
1487 return BSPhysicsShapeType.SHAPE_UNKNOWN; 1506 ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
1488 break; 1507 break;
1489 case BroadphaseNativeTypes.CYLINDER_SHAPE_PROXYTYPE: 1508 case BroadphaseNativeTypes.CYLINDER_SHAPE_PROXYTYPE:
1490 return BSPhysicsShapeType.SHAPE_CYLINDER; 1509 ret = BSPhysicsShapeType.SHAPE_CYLINDER;
1491 break; 1510 break;
1492 case BroadphaseNativeTypes.UNIFORM_SCALING_SHAPE_PROXYTYPE: 1511 case BroadphaseNativeTypes.UNIFORM_SCALING_SHAPE_PROXYTYPE:
1493 return BSPhysicsShapeType.SHAPE_UNKNOWN; 1512 ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
1494 break; 1513 break;
1495 case BroadphaseNativeTypes.MINKOWSKI_SUM_SHAPE_PROXYTYPE: 1514 case BroadphaseNativeTypes.MINKOWSKI_SUM_SHAPE_PROXYTYPE:
1496 return BSPhysicsShapeType.SHAPE_UNKNOWN; 1515 ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
1497 break; 1516 break;
1498 case BroadphaseNativeTypes.MINKOWSKI_DIFFERENCE_SHAPE_PROXYTYPE: 1517 case BroadphaseNativeTypes.MINKOWSKI_DIFFERENCE_SHAPE_PROXYTYPE:
1499 return BSPhysicsShapeType.SHAPE_UNKNOWN; 1518 ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
1500 break; 1519 break;
1501 case BroadphaseNativeTypes.BOX_2D_SHAPE_PROXYTYPE: 1520 case BroadphaseNativeTypes.BOX_2D_SHAPE_PROXYTYPE:
1502 return BSPhysicsShapeType.SHAPE_UNKNOWN; 1521 ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
1503 break; 1522 break;
1504 case BroadphaseNativeTypes.CONVEX_2D_SHAPE_PROXYTYPE: 1523 case BroadphaseNativeTypes.CONVEX_2D_SHAPE_PROXYTYPE:
1505 return BSPhysicsShapeType.SHAPE_UNKNOWN; 1524 ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
1506 break; 1525 break;
1507 case BroadphaseNativeTypes.CUSTOM_CONVEX_SHAPE_TYPE: 1526 case BroadphaseNativeTypes.CUSTOM_CONVEX_SHAPE_TYPE:
1508 return BSPhysicsShapeType.SHAPE_UNKNOWN; 1527 ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
1509 break; 1528 break;
1510 //concave shape 1529 //concave shape
1511 case BroadphaseNativeTypes.CONCAVE_SHAPES_START_HERE: 1530 case BroadphaseNativeTypes.CONCAVE_SHAPES_START_HERE:
1512 return BSPhysicsShapeType.SHAPE_UNKNOWN; 1531 ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
1513 break; 1532 break;
1514 //keep all the convex shapetype below here, for the check IsConvexShape in broadphase proxy! 1533 //keep all the convex shapetype below here, for the check IsConvexShape in broadphase proxy!
1515 case BroadphaseNativeTypes.TRIANGLE_MESH_SHAPE_PROXYTYPE: 1534 case BroadphaseNativeTypes.TRIANGLE_MESH_SHAPE_PROXYTYPE:
1516 return BSPhysicsShapeType.SHAPE_MESH; 1535 ret = BSPhysicsShapeType.SHAPE_MESH;
1517 break; 1536 break;
1518 case BroadphaseNativeTypes.SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE: 1537 case BroadphaseNativeTypes.SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE:
1519 return BSPhysicsShapeType.SHAPE_MESH; 1538 ret = BSPhysicsShapeType.SHAPE_MESH;
1520 break; 1539 break;
1521 ///used for demo integration FAST/Swift collision library and Bullet 1540 ///used for demo integration FAST/Swift collision library and Bullet
1522 case BroadphaseNativeTypes.FAST_CONCAVE_MESH_PROXYTYPE: 1541 case BroadphaseNativeTypes.FAST_CONCAVE_MESH_PROXYTYPE:
1523 return BSPhysicsShapeType.SHAPE_MESH; 1542 ret = BSPhysicsShapeType.SHAPE_MESH;
1524 break; 1543 break;
1525 //terrain 1544 //terrain
1526 case BroadphaseNativeTypes.TERRAIN_SHAPE_PROXYTYPE: 1545 case BroadphaseNativeTypes.TERRAIN_SHAPE_PROXYTYPE:
1527 return BSPhysicsShapeType.SHAPE_HEIGHTMAP; 1546 ret = BSPhysicsShapeType.SHAPE_HEIGHTMAP;
1528 break; 1547 break;
1529 ///Used for GIMPACT Trimesh integration 1548 ///Used for GIMPACT Trimesh integration
1530 case BroadphaseNativeTypes.GIMPACT_SHAPE_PROXYTYPE: 1549 case BroadphaseNativeTypes.GIMPACT_SHAPE_PROXYTYPE:
1531 return BSPhysicsShapeType.SHAPE_MESH; 1550 ret = BSPhysicsShapeType.SHAPE_MESH;
1532 break; 1551 break;
1533 ///Multimaterial mesh 1552 ///Multimaterial mesh
1534 case BroadphaseNativeTypes.MULTIMATERIAL_TRIANGLE_MESH_PROXYTYPE: 1553 case BroadphaseNativeTypes.MULTIMATERIAL_TRIANGLE_MESH_PROXYTYPE:
1535 return BSPhysicsShapeType.SHAPE_MESH; 1554 ret = BSPhysicsShapeType.SHAPE_MESH;
1536 break; 1555 break;
1537 1556
1538 case BroadphaseNativeTypes.EMPTY_SHAPE_PROXYTYPE: 1557 case BroadphaseNativeTypes.EMPTY_SHAPE_PROXYTYPE:
1539 return BSPhysicsShapeType.SHAPE_UNKNOWN; 1558 ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
1540 break; 1559 break;
1541 case BroadphaseNativeTypes.STATIC_PLANE_PROXYTYPE: 1560 case BroadphaseNativeTypes.STATIC_PLANE_PROXYTYPE:
1542 return BSPhysicsShapeType.SHAPE_GROUNDPLANE; 1561 ret = BSPhysicsShapeType.SHAPE_GROUNDPLANE;
1543 break; 1562 break;
1544 case BroadphaseNativeTypes.CUSTOM_CONCAVE_SHAPE_TYPE: 1563 case BroadphaseNativeTypes.CUSTOM_CONCAVE_SHAPE_TYPE:
1545 return BSPhysicsShapeType.SHAPE_UNKNOWN; 1564 ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
1546 break; 1565 break;
1547 case BroadphaseNativeTypes.CONCAVE_SHAPES_END_HERE: 1566 case BroadphaseNativeTypes.CONCAVE_SHAPES_END_HERE:
1548 return BSPhysicsShapeType.SHAPE_UNKNOWN; 1567 ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
1549 break; 1568 break;
1550 1569
1551 case BroadphaseNativeTypes.COMPOUND_SHAPE_PROXYTYPE: 1570 case BroadphaseNativeTypes.COMPOUND_SHAPE_PROXYTYPE:
1552 return BSPhysicsShapeType.SHAPE_COMPOUND; 1571 ret = BSPhysicsShapeType.SHAPE_COMPOUND;
1553 break; 1572 break;
1554 1573
1555 case BroadphaseNativeTypes.SOFTBODY_SHAPE_PROXYTYPE: 1574 case BroadphaseNativeTypes.SOFTBODY_SHAPE_PROXYTYPE:
1556 return BSPhysicsShapeType.SHAPE_MESH; 1575 ret = BSPhysicsShapeType.SHAPE_MESH;
1557 break; 1576 break;
1558 case BroadphaseNativeTypes.HFFLUID_SHAPE_PROXYTYPE: 1577 case BroadphaseNativeTypes.HFFLUID_SHAPE_PROXYTYPE:
1559 return BSPhysicsShapeType.SHAPE_UNKNOWN; 1578 ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
1560 break; 1579 break;
1561 case BroadphaseNativeTypes.HFFLUID_BUOYANT_CONVEX_SHAPE_PROXYTYPE: 1580 case BroadphaseNativeTypes.HFFLUID_BUOYANT_CONVEX_SHAPE_PROXYTYPE:
1562 return BSPhysicsShapeType.SHAPE_UNKNOWN; 1581 ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
1563 break; 1582 break;
1564 case BroadphaseNativeTypes.INVALID_SHAPE_PROXYTYPE: 1583 case BroadphaseNativeTypes.INVALID_SHAPE_PROXYTYPE:
1565 return BSPhysicsShapeType.SHAPE_UNKNOWN; 1584 ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
1566 break; 1585 break;
1567 } 1586 }
1568 return BSPhysicsShapeType.SHAPE_UNKNOWN; 1587 return ret;
1569 } 1588 }
1570 1589
1571 public override void RemoveChildShapeFromCompoundShape(BulletShape cShape, BulletShape removeShape) { /* TODO */ } 1590 public override void RemoveChildShapeFromCompoundShape(BulletShape cShape, BulletShape removeShape) { /* TODO */ }
@@ -1579,7 +1598,39 @@ private sealed class BulletConstraintXNA : BulletConstraint
1579 return new BulletShapeXNA(m_planeshape, BSPhysicsShapeType.SHAPE_GROUNDPLANE); 1598 return new BulletShapeXNA(m_planeshape, BSPhysicsShapeType.SHAPE_GROUNDPLANE);
1580 } 1599 }
1581 1600
1582 public override BulletConstraint CreateHingeConstraint(BulletWorld pWorld, BulletBody pBody1, BulletBody pBody2, Vector3 ppivotInA, Vector3 ppivotInB, Vector3 paxisInA, Vector3 paxisInB, bool puseLinearReferenceFrameA, bool pdisableCollisionsBetweenLinkedBodies) 1601 public override BulletConstraint Create6DofSpringConstraint(BulletWorld pWorld, BulletBody pBody1, BulletBody pBody2,
1602 Vector3 pframe1, Quaternion pframe1rot, Vector3 pframe2, Quaternion pframe2rot,
1603 bool puseLinearReferenceFrameA, bool pdisableCollisionsBetweenLinkedBodies)
1604
1605 {
1606 Generic6DofSpringConstraint constrain = null;
1607 DiscreteDynamicsWorld world = (pWorld as BulletWorldXNA).world;
1608 RigidBody body1 = (pBody1 as BulletBodyXNA).rigidBody;
1609 RigidBody body2 = (pBody2 as BulletBodyXNA).rigidBody;
1610 if (body1 != null && body2 != null)
1611 {
1612 IndexedVector3 frame1v = new IndexedVector3(pframe1.X, pframe1.Y, pframe1.Z);
1613 IndexedQuaternion frame1rot = new IndexedQuaternion(pframe1rot.X, pframe1rot.Y, pframe1rot.Z, pframe1rot.W);
1614 IndexedMatrix frame1 = IndexedMatrix.CreateFromQuaternion(frame1rot);
1615 frame1._origin = frame1v;
1616
1617 IndexedVector3 frame2v = new IndexedVector3(pframe2.X, pframe2.Y, pframe2.Z);
1618 IndexedQuaternion frame2rot = new IndexedQuaternion(pframe2rot.X, pframe2rot.Y, pframe2rot.Z, pframe2rot.W);
1619 IndexedMatrix frame2 = IndexedMatrix.CreateFromQuaternion(frame2rot);
1620 frame2._origin = frame1v;
1621
1622 constrain = new Generic6DofSpringConstraint(body1, body2, ref frame1, ref frame2, puseLinearReferenceFrameA);
1623 world.AddConstraint(constrain, pdisableCollisionsBetweenLinkedBodies);
1624
1625 constrain.CalculateTransforms();
1626 }
1627
1628 return new BulletConstraintXNA(constrain);
1629 }
1630
1631 public override BulletConstraint CreateHingeConstraint(BulletWorld pWorld, BulletBody pBody1, BulletBody pBody2,
1632 Vector3 ppivotInA, Vector3 ppivotInB, Vector3 paxisInA, Vector3 paxisInB,
1633 bool puseLinearReferenceFrameA, bool pdisableCollisionsBetweenLinkedBodies)
1583 { 1634 {
1584 HingeConstraint constrain = null; 1635 HingeConstraint constrain = null;
1585 DiscreteDynamicsWorld world = (pWorld as BulletWorldXNA).world; 1636 DiscreteDynamicsWorld world = (pWorld as BulletWorldXNA).world;
@@ -1591,6 +1642,100 @@ private sealed class BulletConstraintXNA : BulletConstraint
1591 IndexedVector3 pivotInB = new IndexedVector3(ppivotInB.X, ppivotInB.Y, ppivotInB.Z); 1642 IndexedVector3 pivotInB = new IndexedVector3(ppivotInB.X, ppivotInB.Y, ppivotInB.Z);
1592 IndexedVector3 axisInA = new IndexedVector3(paxisInA.X, paxisInA.Y, paxisInA.Z); 1643 IndexedVector3 axisInA = new IndexedVector3(paxisInA.X, paxisInA.Y, paxisInA.Z);
1593 IndexedVector3 axisInB = new IndexedVector3(paxisInB.X, paxisInB.Y, paxisInB.Z); 1644 IndexedVector3 axisInB = new IndexedVector3(paxisInB.X, paxisInB.Y, paxisInB.Z);
1645 constrain = new HingeConstraint(rb1, rb2, ref pivotInA, ref pivotInB, ref axisInA, ref axisInB, puseLinearReferenceFrameA);
1646 world.AddConstraint(constrain, pdisableCollisionsBetweenLinkedBodies);
1647 }
1648 return new BulletConstraintXNA(constrain);
1649 }
1650
1651 public override BulletConstraint CreateSliderConstraint(BulletWorld pWorld, BulletBody pBody1, BulletBody pBody2,
1652 Vector3 pframe1, Quaternion pframe1rot,
1653 Vector3 pframe2, Quaternion pframe2rot,
1654 bool puseLinearReferenceFrameA, bool pdisableCollisionsBetweenLinkedBodies)
1655 {
1656 SliderConstraint constrain = null;
1657 DiscreteDynamicsWorld world = (pWorld as BulletWorldXNA).world;
1658 RigidBody rb1 = (pBody1 as BulletBodyXNA).rigidBody;
1659 RigidBody rb2 = (pBody2 as BulletBodyXNA).rigidBody;
1660 if (rb1 != null && rb2 != null)
1661 {
1662 IndexedVector3 frame1v = new IndexedVector3(pframe1.X, pframe1.Y, pframe1.Z);
1663 IndexedQuaternion frame1rot = new IndexedQuaternion(pframe1rot.X, pframe1rot.Y, pframe1rot.Z, pframe1rot.W);
1664 IndexedMatrix frame1 = IndexedMatrix.CreateFromQuaternion(frame1rot);
1665 frame1._origin = frame1v;
1666
1667 IndexedVector3 frame2v = new IndexedVector3(pframe2.X, pframe2.Y, pframe2.Z);
1668 IndexedQuaternion frame2rot = new IndexedQuaternion(pframe2rot.X, pframe2rot.Y, pframe2rot.Z, pframe2rot.W);
1669 IndexedMatrix frame2 = IndexedMatrix.CreateFromQuaternion(frame2rot);
1670 frame2._origin = frame1v;
1671
1672 constrain = new SliderConstraint(rb1, rb2, ref frame1, ref frame2, puseLinearReferenceFrameA);
1673 world.AddConstraint(constrain, pdisableCollisionsBetweenLinkedBodies);
1674 }
1675 return new BulletConstraintXNA(constrain);
1676 }
1677
1678 public override BulletConstraint CreateConeTwistConstraint(BulletWorld pWorld, BulletBody pBody1, BulletBody pBody2,
1679 Vector3 pframe1, Quaternion pframe1rot,
1680 Vector3 pframe2, Quaternion pframe2rot,
1681 bool pdisableCollisionsBetweenLinkedBodies)
1682 {
1683 ConeTwistConstraint constrain = null;
1684 DiscreteDynamicsWorld world = (pWorld as BulletWorldXNA).world;
1685 RigidBody rb1 = (pBody1 as BulletBodyXNA).rigidBody;
1686 RigidBody rb2 = (pBody2 as BulletBodyXNA).rigidBody;
1687 if (rb1 != null && rb2 != null)
1688 {
1689 IndexedVector3 frame1v = new IndexedVector3(pframe1.X, pframe1.Y, pframe1.Z);
1690 IndexedQuaternion frame1rot = new IndexedQuaternion(pframe1rot.X, pframe1rot.Y, pframe1rot.Z, pframe1rot.W);
1691 IndexedMatrix frame1 = IndexedMatrix.CreateFromQuaternion(frame1rot);
1692 frame1._origin = frame1v;
1693
1694 IndexedVector3 frame2v = new IndexedVector3(pframe2.X, pframe2.Y, pframe2.Z);
1695 IndexedQuaternion frame2rot = new IndexedQuaternion(pframe2rot.X, pframe2rot.Y, pframe2rot.Z, pframe2rot.W);
1696 IndexedMatrix frame2 = IndexedMatrix.CreateFromQuaternion(frame2rot);
1697 frame2._origin = frame1v;
1698
1699 constrain = new ConeTwistConstraint(rb1, rb2, ref frame1, ref frame2);
1700 world.AddConstraint(constrain, pdisableCollisionsBetweenLinkedBodies);
1701 }
1702 return new BulletConstraintXNA(constrain);
1703 }
1704
1705 public override BulletConstraint CreateGearConstraint(BulletWorld pWorld, BulletBody pBody1, BulletBody pBody2,
1706 Vector3 paxisInA, Vector3 paxisInB,
1707 float pratio, bool pdisableCollisionsBetweenLinkedBodies)
1708 {
1709 Generic6DofConstraint constrain = null;
1710 /* BulletXNA does not have a gear constraint
1711 GearConstraint constrain = null;
1712 DiscreteDynamicsWorld world = (pWorld as BulletWorldXNA).world;
1713 RigidBody rb1 = (pBody1 as BulletBodyXNA).rigidBody;
1714 RigidBody rb2 = (pBody2 as BulletBodyXNA).rigidBody;
1715 if (rb1 != null && rb2 != null)
1716 {
1717 IndexedVector3 axis1 = new IndexedVector3(paxisInA.X, paxisInA.Y, paxisInA.Z);
1718 IndexedVector3 axis2 = new IndexedVector3(paxisInB.X, paxisInB.Y, paxisInB.Z);
1719 constrain = new GearConstraint(rb1, rb2, ref axis1, ref axis2, pratio);
1720 world.AddConstraint(constrain, pdisableCollisionsBetweenLinkedBodies);
1721 }
1722 */
1723 return new BulletConstraintXNA(constrain);
1724 }
1725
1726 public override BulletConstraint CreatePoint2PointConstraint(BulletWorld pWorld, BulletBody pBody1, BulletBody pBody2,
1727 Vector3 ppivotInA, Vector3 ppivotInB,
1728 bool pdisableCollisionsBetweenLinkedBodies)
1729 {
1730 Point2PointConstraint constrain = null;
1731 DiscreteDynamicsWorld world = (pWorld as BulletWorldXNA).world;
1732 RigidBody rb1 = (pBody1 as BulletBodyXNA).rigidBody;
1733 RigidBody rb2 = (pBody2 as BulletBodyXNA).rigidBody;
1734 if (rb1 != null && rb2 != null)
1735 {
1736 IndexedVector3 pivotInA = new IndexedVector3(ppivotInA.X, ppivotInA.Y, ppivotInA.Z);
1737 IndexedVector3 pivotInB = new IndexedVector3(ppivotInB.X, ppivotInB.Y, ppivotInB.Z);
1738 constrain = new Point2PointConstraint(rb1, rb2, ref pivotInA, ref pivotInB);
1594 world.AddConstraint(constrain, pdisableCollisionsBetweenLinkedBodies); 1739 world.AddConstraint(constrain, pdisableCollisionsBetweenLinkedBodies);
1595 } 1740 }
1596 return new BulletConstraintXNA(constrain); 1741 return new BulletConstraintXNA(constrain);
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSApiTemplate.cs b/OpenSim/Region/Physics/BulletSPlugin/BSApiTemplate.cs
index 3f83ef0..5765b0d 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSApiTemplate.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSApiTemplate.cs
@@ -365,11 +365,38 @@ public abstract BulletConstraint Create6DofConstraintToPoint(BulletWorld world,
365 Vector3 joinPoint, 365 Vector3 joinPoint,
366 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies); 366 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies);
367 367
368public abstract BulletConstraint Create6DofConstraintFixed(BulletWorld world, BulletBody obj1,
369 Vector3 frameInBloc, Quaternion frameInBrot,
370 bool useLinearReferenceFrameB, bool disableCollisionsBetweenLinkedBodies);
371
372public abstract BulletConstraint Create6DofSpringConstraint(BulletWorld world, BulletBody obj1, BulletBody obj2,
373 Vector3 frame1loc, Quaternion frame1rot,
374 Vector3 frame2loc, Quaternion frame2rot,
375 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies);
376
368public abstract BulletConstraint CreateHingeConstraint(BulletWorld world, BulletBody obj1, BulletBody obj2, 377public abstract BulletConstraint CreateHingeConstraint(BulletWorld world, BulletBody obj1, BulletBody obj2,
369 Vector3 pivotinA, Vector3 pivotinB, 378 Vector3 pivotinA, Vector3 pivotinB,
370 Vector3 axisInA, Vector3 axisInB, 379 Vector3 axisInA, Vector3 axisInB,
371 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies); 380 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies);
372 381
382public abstract BulletConstraint CreateSliderConstraint(BulletWorld world, BulletBody obj1, BulletBody obj2,
383 Vector3 frameInAloc, Quaternion frameInArot,
384 Vector3 frameInBloc, Quaternion frameInBrot,
385 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies);
386
387public abstract BulletConstraint CreateConeTwistConstraint(BulletWorld world, BulletBody obj1, BulletBody obj2,
388 Vector3 frameInAloc, Quaternion frameInArot,
389 Vector3 frameInBloc, Quaternion frameInBrot,
390 bool disableCollisionsBetweenLinkedBodies);
391
392public abstract BulletConstraint CreateGearConstraint(BulletWorld world, BulletBody obj1, BulletBody obj2,
393 Vector3 axisInA, Vector3 axisInB,
394 float ratio, bool disableCollisionsBetweenLinkedBodies);
395
396public abstract BulletConstraint CreatePoint2PointConstraint(BulletWorld world, BulletBody obj1, BulletBody obj2,
397 Vector3 pivotInA, Vector3 pivotInB,
398 bool disableCollisionsBetweenLinkedBodies);
399
373public abstract void SetConstraintEnable(BulletConstraint constrain, float numericTrueFalse); 400public abstract void SetConstraintEnable(BulletConstraint constrain, float numericTrueFalse);
374 401
375public abstract void SetConstraintNumSolverIterations(BulletConstraint constrain, float iterations); 402public abstract void SetConstraintNumSolverIterations(BulletConstraint constrain, float iterations);
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
index 8dca7c6..1f186c3 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
@@ -443,6 +443,7 @@ public sealed class BSCharacter : BSPhysObject
443 PhysicsScene.TaintedObject("BSCharacter.setPosition", delegate() 443 PhysicsScene.TaintedObject("BSCharacter.setPosition", delegate()
444 { 444 {
445 DetailLog("{0},BSCharacter.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); 445 DetailLog("{0},BSCharacter.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation);
446 PositionSanityCheck();
446 ForcePosition = _position; 447 ForcePosition = _position;
447 }); 448 });
448 } 449 }
@@ -456,7 +457,6 @@ public sealed class BSCharacter : BSPhysObject
456 _position = value; 457 _position = value;
457 if (PhysBody.HasPhysicalBody) 458 if (PhysBody.HasPhysicalBody)
458 { 459 {
459 PositionSanityCheck();
460 PhysicsScene.PE.SetTranslation(PhysBody, _position, _orientation); 460 PhysicsScene.PE.SetTranslation(PhysBody, _position, _orientation);
461 } 461 }
462 } 462 }
@@ -512,9 +512,8 @@ public sealed class BSCharacter : BSPhysObject
512 // just assign to "Position" because of potential call loops. 512 // just assign to "Position" because of potential call loops.
513 PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.PositionSanityCheck", delegate() 513 PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.PositionSanityCheck", delegate()
514 { 514 {
515 DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation); 515 DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation);
516 if (PhysBody.HasPhysicalBody) 516 ForcePosition = _position;
517 PhysicsScene.PE.SetTranslation(PhysBody, _position, _orientation);
518 }); 517 });
519 ret = true; 518 ret = true;
520 } 519 }
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint6Dof.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint6Dof.cs
index ecb1b32..476a0e5 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint6Dof.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint6Dof.cs
@@ -57,6 +57,7 @@ public sealed class BSConstraint6Dof : BSConstraint
57 obj1.ID, obj1.AddrString, obj2.ID, obj2.AddrString); 57 obj1.ID, obj1.AddrString, obj2.ID, obj2.AddrString);
58 } 58 }
59 59
60 // 6 Dof constraint based on a midpoint between the two constrained bodies
60 public BSConstraint6Dof(BulletWorld world, BulletBody obj1, BulletBody obj2, 61 public BSConstraint6Dof(BulletWorld world, BulletBody obj1, BulletBody obj2,
61 Vector3 joinPoint, 62 Vector3 joinPoint,
62 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies) 63 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies)
@@ -94,6 +95,21 @@ public sealed class BSConstraint6Dof : BSConstraint
94 } 95 }
95 } 96 }
96 97
98 // A 6 Dof constraint that is fixed in the world and constrained to a on-the-fly created static object
99 public BSConstraint6Dof(BulletWorld world, BulletBody obj1, Vector3 frameInBloc, Quaternion frameInBrot,
100 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies)
101 : base(world)
102 {
103 m_body1 = obj1;
104 m_body2 = obj1; // Look out for confusion down the road
105 m_constraint = PhysicsScene.PE.Create6DofConstraintFixed(m_world, m_body1,
106 frameInBloc, frameInBrot,
107 useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies);
108 m_enabled = true;
109 world.physicsScene.DetailLog("{0},BS6DofConstraint,createFixed,wID={1},rID={2},rBody={3}",
110 BSScene.DetailLogZero, world.worldID, obj1.ID, obj1.AddrString);
111 }
112
97 public bool SetFrames(Vector3 frameA, Quaternion frameArot, Vector3 frameB, Quaternion frameBrot) 113 public bool SetFrames(Vector3 frameA, Quaternion frameArot, Vector3 frameB, Quaternion frameBrot)
98 { 114 {
99 bool ret = false; 115 bool ret = false;
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs
index 2aeff25..5c8d94e 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs
@@ -117,8 +117,7 @@ public sealed class BSConstraintCollection : IDisposable
117 if (this.TryGetConstraint(body1, body2, out constrain)) 117 if (this.TryGetConstraint(body1, body2, out constrain))
118 { 118 {
119 // remove the constraint from our collection 119 // remove the constraint from our collection
120 RemoveAndDestroyConstraint(constrain); 120 ret = RemoveAndDestroyConstraint(constrain);
121 ret = true;
122 } 121 }
123 } 122 }
124 123
@@ -126,17 +125,19 @@ public sealed class BSConstraintCollection : IDisposable
126 } 125 }
127 126
128 // The constraint MUST exist in the collection 127 // The constraint MUST exist in the collection
128 // Could be called if the constraint was previously removed.
129 // Return 'true' if the constraint was actually removed and disposed.
129 public bool RemoveAndDestroyConstraint(BSConstraint constrain) 130 public bool RemoveAndDestroyConstraint(BSConstraint constrain)
130 { 131 {
132 bool removed = false;
131 lock (m_constraints) 133 lock (m_constraints)
132 { 134 {
133 // remove the constraint from our collection 135 // remove the constraint from our collection
134 m_constraints.Remove(constrain); 136 removed = m_constraints.Remove(constrain);
135 } 137 }
136 // tell the engine that all its structures need to be freed 138 // Dispose() is safe to call multiple times
137 constrain.Dispose(); 139 constrain.Dispose();
138 // we destroyed something 140 return removed;
139 return true;
140 } 141 }
141 142
142 // Remove all constraints that reference the passed body. 143 // Remove all constraints that reference the passed body.
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
index 41d353a..e6933f9 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
@@ -144,7 +144,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
144 enableAngularVerticalAttraction = true; 144 enableAngularVerticalAttraction = true;
145 enableAngularDeflection = false; 145 enableAngularDeflection = false;
146 enableAngularBanking = false; 146 enableAngularBanking = false;
147 if (BSParam.VehicleDebuggingEnabled != ConfigurationParameters.numericFalse) 147 if (BSParam.VehicleDebuggingEnabled)
148 { 148 {
149 enableAngularVerticalAttraction = true; 149 enableAngularVerticalAttraction = true;
150 enableAngularDeflection = false; 150 enableAngularDeflection = false;
@@ -607,8 +607,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin
607 // TODO: possibly set AngularFactor and LinearFactor for the type of vehicle. 607 // TODO: possibly set AngularFactor and LinearFactor for the type of vehicle.
608 // Maybe compute linear and angular factor and damping from params. 608 // Maybe compute linear and angular factor and damping from params.
609 PhysicsScene.PE.SetAngularDamping(Prim.PhysBody, BSParam.VehicleAngularDamping); 609 PhysicsScene.PE.SetAngularDamping(Prim.PhysBody, BSParam.VehicleAngularDamping);
610 PhysicsScene.PE.SetLinearFactor(Prim.PhysBody, BSParam.VehicleLinearFactorV); 610 PhysicsScene.PE.SetLinearFactor(Prim.PhysBody, BSParam.VehicleLinearFactor);
611 PhysicsScene.PE.SetAngularFactorV(Prim.PhysBody, BSParam.VehicleAngularFactorV); 611 PhysicsScene.PE.SetAngularFactorV(Prim.PhysBody, BSParam.VehicleAngularFactor);
612 612
613 // Vehicles report collision events so we know when it's on the ground 613 // Vehicles report collision events so we know when it's on the ground
614 PhysicsScene.PE.AddToCollisionFlags(Prim.PhysBody, CollisionFlags.BS_VEHICLE_COLLISIONS); 614 PhysicsScene.PE.AddToCollisionFlags(Prim.PhysBody, CollisionFlags.BS_VEHICLE_COLLISIONS);
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs
index 4ce58c7..e05562a 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs
@@ -485,8 +485,8 @@ public sealed class BSLinksetCompound : BSLinkset
485 } 485 }
486 OMV.Vector3 offsetPos = (cPrim.RawPosition - LinksetRoot.RawPosition) * invRootOrientation - centerDisplacement; 486 OMV.Vector3 offsetPos = (cPrim.RawPosition - LinksetRoot.RawPosition) * invRootOrientation - centerDisplacement;
487 OMV.Quaternion offsetRot = cPrim.RawOrientation * invRootOrientation; 487 OMV.Quaternion offsetRot = cPrim.RawOrientation * invRootOrientation;
488 PhysicsScene.PE.AddChildShapeToCompoundShape(LinksetRoot.PhysShape, cPrim.PhysShape, offsetPos, offsetRot); 488 PhysicsScene.PE.AddChildShapeToCompoundShape(LinksetRoot.PhysShape, cPrim.PhysShape, offsetPos, offsetRot);
489 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addNonNative,indx={1},rShape={2},cShape={3},offPos={4},offRot={5}", 489 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addNonNative,indx={1},rShape={2},cShape={3},offPos={4},offRot={5}",
490 LinksetRoot.LocalID, memberIndex, LinksetRoot.PhysShape, cPrim.PhysShape, offsetPos, offsetRot); 490 LinksetRoot.LocalID, memberIndex, LinksetRoot.PhysShape, cPrim.PhysShape, offsetPos, offsetRot);
491 491
492 } 492 }
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs
index cc814d1..6d252ca 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs
@@ -223,8 +223,8 @@ public sealed class BSLinksetConstraints : BSLinkset
223 constrain.SetAngularLimits(OMV.Vector3.Zero, OMV.Vector3.Zero); 223 constrain.SetAngularLimits(OMV.Vector3.Zero, OMV.Vector3.Zero);
224 224
225 // tweek the constraint to increase stability 225 // tweek the constraint to increase stability
226 constrain.UseFrameOffset(BSParam.BoolNumeric(BSParam.LinkConstraintUseFrameOffset)); 226 constrain.UseFrameOffset(BSParam.LinkConstraintUseFrameOffset);
227 constrain.TranslationalLimitMotor(BSParam.BoolNumeric(BSParam.LinkConstraintEnableTransMotor), 227 constrain.TranslationalLimitMotor(BSParam.LinkConstraintEnableTransMotor,
228 BSParam.LinkConstraintTransMotorMaxVel, 228 BSParam.LinkConstraintTransMotorMaxVel,
229 BSParam.LinkConstraintTransMotorMaxForce); 229 BSParam.LinkConstraintTransMotorMaxForce);
230 constrain.SetCFMAndERP(BSParam.LinkConstraintCFM, BSParam.LinkConstraintERP); 230 constrain.SetCFMAndERP(BSParam.LinkConstraintCFM, BSParam.LinkConstraintERP);
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs b/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs
index 329169f..dc57b67 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs
@@ -37,6 +37,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin
37{ 37{
38public static class BSParam 38public static class BSParam
39{ 39{
40 private static string LogHeader = "[BULLETSIM PARAMETERS]";
41
40 // Level of Detail values kept as float because that's what the Meshmerizer wants 42 // Level of Detail values kept as float because that's what the Meshmerizer wants
41 public static float MeshLOD { get; private set; } 43 public static float MeshLOD { get; private set; }
42 public static float MeshCircularLOD { get; private set; } 44 public static float MeshCircularLOD { get; private set; }
@@ -44,6 +46,8 @@ public static class BSParam
44 public static float MeshMegaPrimThreshold { get; private set; } 46 public static float MeshMegaPrimThreshold { get; private set; }
45 public static float SculptLOD { get; private set; } 47 public static float SculptLOD { get; private set; }
46 48
49 public static int CrossingFailuresBeforeOutOfBounds { get; private set; }
50
47 public static float MinimumObjectMass { get; private set; } 51 public static float MinimumObjectMass { get; private set; }
48 public static float MaximumObjectMass { get; private set; } 52 public static float MaximumObjectMass { get; private set; }
49 public static float MaxLinearVelocity { get; private set; } 53 public static float MaxLinearVelocity { get; private set; }
@@ -71,24 +75,23 @@ public static class BSParam
71 public static float TerrainRestitution { get; private set; } 75 public static float TerrainRestitution { get; private set; }
72 public static float TerrainCollisionMargin { get; private set; } 76 public static float TerrainCollisionMargin { get; private set; }
73 77
74 public static float DefaultFriction; 78 public static float DefaultFriction { get; private set; }
75 public static float DefaultDensity; 79 public static float DefaultDensity { get; private set; }
76 public static float DefaultRestitution; 80 public static float DefaultRestitution { get; private set; }
77 public static float CollisionMargin; 81 public static float CollisionMargin { get; private set; }
78 public static float Gravity; 82 public static float Gravity { get; private set; }
79 83
80 // Physics Engine operation 84 // Physics Engine operation
81 public static float MaxPersistantManifoldPoolSize; 85 public static float MaxPersistantManifoldPoolSize { get; private set; }
82 public static float MaxCollisionAlgorithmPoolSize; 86 public static float MaxCollisionAlgorithmPoolSize { get; private set; }
83 public static float ShouldDisableContactPoolDynamicAllocation; 87 public static bool ShouldDisableContactPoolDynamicAllocation { get; private set; }
84 public static float ShouldForceUpdateAllAabbs; 88 public static bool ShouldForceUpdateAllAabbs { get; private set; }
85 public static float ShouldRandomizeSolverOrder; 89 public static bool ShouldRandomizeSolverOrder { get; private set; }
86 public static float ShouldSplitSimulationIslands; 90 public static bool ShouldSplitSimulationIslands { get; private set; }
87 public static float ShouldEnableFrictionCaching; 91 public static bool ShouldEnableFrictionCaching { get; private set; }
88 public static float NumberOfSolverIterations; 92 public static float NumberOfSolverIterations { get; private set; }
89 public static bool UseSingleSidedMeshes { get { return UseSingleSidedMeshesF != ConfigurationParameters.numericFalse; } } 93 public static bool UseSingleSidedMeshes { get; private set; }
90 public static float UseSingleSidedMeshesF; 94 public static float GlobalContactBreakingThreshold { get; private set; }
91 public static float GlobalContactBreakingThreshold;
92 95
93 // Avatar parameters 96 // Avatar parameters
94 public static float AvatarFriction { get; private set; } 97 public static float AvatarFriction { get; private set; }
@@ -112,16 +115,15 @@ public static class BSParam
112 public static float VehicleAngularDamping { get; private set; } 115 public static float VehicleAngularDamping { get; private set; }
113 public static float VehicleFriction { get; private set; } 116 public static float VehicleFriction { get; private set; }
114 public static float VehicleRestitution { get; private set; } 117 public static float VehicleRestitution { get; private set; }
115 public static float VehicleLinearFactor { get; private set; } 118 public static Vector3 VehicleLinearFactor { get; private set; }
116 public static Vector3 VehicleLinearFactorV { get; private set; } 119 public static Vector3 VehicleAngularFactor { get; private set; }
117 public static float VehicleAngularFactor { get; private set; }
118 public static Vector3 VehicleAngularFactorV { get; private set; }
119 public static float VehicleGroundGravityFudge { get; private set; } 120 public static float VehicleGroundGravityFudge { get; private set; }
120 public static float VehicleDebuggingEnabled { get; private set; } 121 public static bool VehicleDebuggingEnabled { get; private set; }
121 122
123 // Linkset implementation parameters
122 public static float LinksetImplementation { get; private set; } 124 public static float LinksetImplementation { get; private set; }
123 public static float LinkConstraintUseFrameOffset { get; private set; } 125 public static bool LinkConstraintUseFrameOffset { get; private set; }
124 public static float LinkConstraintEnableTransMotor { get; private set; } 126 public static bool LinkConstraintEnableTransMotor { get; private set; }
125 public static float LinkConstraintTransMotorMaxVel { get; private set; } 127 public static float LinkConstraintTransMotorMaxVel { get; private set; }
126 public static float LinkConstraintTransMotorMaxForce { get; private set; } 128 public static float LinkConstraintTransMotorMaxForce { get; private set; }
127 public static float LinkConstraintERP { get; private set; } 129 public static float LinkConstraintERP { get; private set; }
@@ -141,40 +143,106 @@ public static class BSParam
141 public const float MinRestitution = 0f; 143 public const float MinRestitution = 0f;
142 public const float MaxRestitution = 1f; 144 public const float MaxRestitution = 1f;
143 145
144 // =========================================================================== 146 // =====================================================================================
145 public delegate void ParamUser(BSScene scene, IConfig conf, string paramName, float val); 147 // =====================================================================================
146 public delegate float ParamGet(BSScene scene);
147 public delegate void ParamSet(BSScene scene, string paramName, uint localID, float val);
148 public delegate void SetOnObject(BSScene scene, BSPhysObject obj, float val);
149 148
150 public struct ParameterDefn 149 // Base parameter definition that gets and sets parameter values via a string
150 public abstract class ParameterDefnBase
151 { 151 {
152 public string name; // string name of the parameter 152 public string name; // string name of the parameter
153 public string desc; // a short description of what the parameter means 153 public string desc; // a short description of what the parameter means
154 public float defaultValue; // default value if not specified anywhere else 154 public ParameterDefnBase(string pName, string pDesc)
155 public ParamUser userParam; // get the value from the configuration file 155 {
156 public ParamGet getter; // return the current value stored for this parameter 156 name = pName;
157 public ParamSet setter; // set the current value for this parameter 157 desc = pDesc;
158 public SetOnObject onObject; // set the value on an object in the physical domain 158 }
159 public ParameterDefn(string n, string d, float v, ParamUser u, ParamGet g, ParamSet s) 159 // Set the parameter value to the default
160 public abstract void AssignDefault(BSScene s);
161 // Get the value as a string
162 public abstract string GetValue(BSScene s);
163 // Set the value to this string value
164 public abstract void SetValue(BSScene s, string valAsString);
165 // set the value on a particular object (usually sets in physics engine)
166 public abstract void SetOnObject(BSScene s, BSPhysObject obj);
167 public abstract bool HasSetOnObject { get; }
168 }
169
170 // Specific parameter definition for a parameter of a specific type.
171 public delegate T PGetValue<T>(BSScene s);
172 public delegate void PSetValue<T>(BSScene s, T val);
173 public delegate void PSetOnObject<T>(BSScene scene, BSPhysObject obj);
174 public sealed class ParameterDefn<T> : ParameterDefnBase
175 {
176 T defaultValue;
177 PSetValue<T> setter;
178 PGetValue<T> getter;
179 PSetOnObject<T> objectSet;
180 public ParameterDefn(string pName, string pDesc, T pDefault, PGetValue<T> pGetter, PSetValue<T> pSetter)
181 : base(pName, pDesc)
160 { 182 {
161 name = n; 183 defaultValue = pDefault;
162 desc = d; 184 setter = pSetter;
163 defaultValue = v; 185 getter = pGetter;
164 userParam = u; 186 objectSet = null;
165 getter = g;
166 setter = s;
167 onObject = null;
168 } 187 }
169 public ParameterDefn(string n, string d, float v, ParamUser u, ParamGet g, ParamSet s, SetOnObject o) 188 public ParameterDefn(string pName, string pDesc, T pDefault, PGetValue<T> pGetter, PSetValue<T> pSetter, PSetOnObject<T> pObjSetter)
189 : base(pName, pDesc)
170 { 190 {
171 name = n; 191 defaultValue = pDefault;
172 desc = d; 192 setter = pSetter;
173 defaultValue = v; 193 getter = pGetter;
174 userParam = u; 194 objectSet = pObjSetter;
175 getter = g; 195 }
176 setter = s; 196 public override void AssignDefault(BSScene s)
177 onObject = o; 197 {
198 setter(s, defaultValue);
199 }
200 public override string GetValue(BSScene s)
201 {
202 return String.Format("{0}", getter(s));
203 }
204 public override void SetValue(BSScene s, string valAsString)
205 {
206 // Get the generic type of the setter
207 Type genericType = setter.GetType().GetGenericArguments()[0];
208 // Find the 'Parse' method on that type
209 System.Reflection.MethodInfo parser = null;
210 try
211 {
212 parser = genericType.GetMethod("Parse", new Type[] { typeof(String) } );
213 }
214 catch (Exception e)
215 {
216 s.Logger.ErrorFormat("{0} Exception getting parser for type '{1}': {2}", LogHeader, genericType, e);
217 parser = null;
218 }
219 if (parser != null)
220 {
221 // Parse the input string
222 try
223 {
224 T setValue = (T)parser.Invoke(genericType, new Object[] { valAsString });
225 setter(s, setValue);
226 // s.Logger.DebugFormat("{0} Parameter {1} = {2}", LogHeader, name, setValue);
227 }
228 catch
229 {
230 s.Logger.ErrorFormat("{0} Failed parsing parameter value '{1}' as type '{2}'", LogHeader, valAsString, genericType);
231 }
232 }
233 else
234 {
235 s.Logger.ErrorFormat("{0} Could not find parameter parser for type '{1}'", LogHeader, genericType);
236 }
237 }
238 public override bool HasSetOnObject
239 {
240 get { return objectSet != null; }
241 }
242 public override void SetOnObject(BSScene s, BSPhysObject obj)
243 {
244 if (objectSet != null)
245 objectSet(s, obj);
178 } 246 }
179 } 247 }
180 248
@@ -184,462 +252,380 @@ public static class BSParam
184 // location somewhere in the program and make an entry in this table with the 252 // location somewhere in the program and make an entry in this table with the
185 // getters and setters. 253 // getters and setters.
186 // It is easiest to find an existing definition and copy it. 254 // It is easiest to find an existing definition and copy it.
187 // Parameter values are floats. Booleans are converted to a floating value.
188 // 255 //
189 // A ParameterDefn() takes the following parameters: 256 // A ParameterDefn<T>() takes the following parameters:
190 // -- the text name of the parameter. This is used for console input and ini file. 257 // -- the text name of the parameter. This is used for console input and ini file.
191 // -- a short text description of the parameter. This shows up in the console listing. 258 // -- a short text description of the parameter. This shows up in the console listing.
192 // -- a default value (float) 259 // -- a default value
193 // -- a delegate for fetching the parameter from the ini file. 260 // -- a delegate for getting the value
194 // Should handle fetching the right type from the ini file and converting it. 261 // -- a delegate for setting the value
195 // -- a delegate for getting the value as a float
196 // -- a delegate for setting the value from a float
197 // -- an optional delegate to update the value in the world. Most often used to 262 // -- an optional delegate to update the value in the world. Most often used to
198 // push the new value to an in-world object. 263 // push the new value to an in-world object.
199 // 264 //
200 // The single letter parameters for the delegates are: 265 // The single letter parameters for the delegates are:
201 // s = BSScene 266 // s = BSScene
202 // o = BSPhysObject 267 // o = BSPhysObject
203 // p = string parameter name
204 // l = localID of referenced object
205 // v = value (float) 268 // v = value (float)
206 // cf = parameter configuration class (for fetching values from ini file) 269 private static ParameterDefnBase[] ParameterDefinitions =
207 private static ParameterDefn[] ParameterDefinitions =
208 { 270 {
209 new ParameterDefn("MeshSculptedPrim", "Whether to create meshes for sculpties", 271 new ParameterDefn<bool>("MeshSculptedPrim", "Whether to create meshes for sculpties",
210 ConfigurationParameters.numericTrue, 272 true,
211 (s,cf,p,v) => { ShouldMeshSculptedPrim = cf.GetBoolean(p, BSParam.BoolNumeric(v)); }, 273 (s) => { return ShouldMeshSculptedPrim; },
212 (s) => { return BSParam.NumericBool(ShouldMeshSculptedPrim); }, 274 (s,v) => { ShouldMeshSculptedPrim = v; } ),
213 (s,p,l,v) => { ShouldMeshSculptedPrim = BSParam.BoolNumeric(v); } ), 275 new ParameterDefn<bool>("ForceSimplePrimMeshing", "If true, only use primitive meshes for objects",
214 new ParameterDefn("ForceSimplePrimMeshing", "If true, only use primitive meshes for objects", 276 false,
215 ConfigurationParameters.numericFalse, 277 (s) => { return ShouldForceSimplePrimMeshing; },
216 (s,cf,p,v) => { ShouldForceSimplePrimMeshing = cf.GetBoolean(p, BSParam.BoolNumeric(v)); }, 278 (s,v) => { ShouldForceSimplePrimMeshing = v; } ),
217 (s) => { return BSParam.NumericBool(ShouldForceSimplePrimMeshing); }, 279 new ParameterDefn<bool>("UseHullsForPhysicalObjects", "If true, create hulls for physical objects",
218 (s,p,l,v) => { ShouldForceSimplePrimMeshing = BSParam.BoolNumeric(v); } ), 280 true,
219 new ParameterDefn("UseHullsForPhysicalObjects", "If true, create hulls for physical objects", 281 (s) => { return ShouldUseHullsForPhysicalObjects; },
220 ConfigurationParameters.numericTrue, 282 (s,v) => { ShouldUseHullsForPhysicalObjects = v; } ),
221 (s,cf,p,v) => { ShouldUseHullsForPhysicalObjects = cf.GetBoolean(p, BSParam.BoolNumeric(v)); }, 283 new ParameterDefn<bool>("ShouldRemoveZeroWidthTriangles", "If true, remove degenerate triangles from meshes",
222 (s) => { return BSParam.NumericBool(ShouldUseHullsForPhysicalObjects); }, 284 true,
223 (s,p,l,v) => { ShouldUseHullsForPhysicalObjects = BSParam.BoolNumeric(v); } ), 285 (s) => { return ShouldRemoveZeroWidthTriangles; },
224 new ParameterDefn("ShouldRemoveZeroWidthTriangles", "If true, remove degenerate triangles from meshes", 286 (s,v) => { ShouldRemoveZeroWidthTriangles = v; } ),
225 ConfigurationParameters.numericTrue, 287
226 (s,cf,p,v) => { ShouldRemoveZeroWidthTriangles = cf.GetBoolean(p, BSParam.BoolNumeric(v)); }, 288 new ParameterDefn<int>("CrossingFailuresBeforeOutOfBounds", "How forgiving we are about getting into adjactent regions",
227 (s) => { return BSParam.NumericBool(ShouldRemoveZeroWidthTriangles); }, 289 5,
228 (s,p,l,v) => { ShouldRemoveZeroWidthTriangles = BSParam.BoolNumeric(v); } ), 290 (s) => { return CrossingFailuresBeforeOutOfBounds; },
229 291 (s,v) => { CrossingFailuresBeforeOutOfBounds = v; } ),
230 new ParameterDefn("MeshLevelOfDetail", "Level of detail to render meshes (32, 16, 8 or 4. 32=most detailed)", 292
293 new ParameterDefn<float>("MeshLevelOfDetail", "Level of detail to render meshes (32, 16, 8 or 4. 32=most detailed)",
231 32f, 294 32f,
232 (s,cf,p,v) => { MeshLOD = (float)cf.GetInt(p, (int)v); },
233 (s) => { return MeshLOD; }, 295 (s) => { return MeshLOD; },
234 (s,p,l,v) => { MeshLOD = v; } ), 296 (s,v) => { MeshLOD = v; } ),
235 new ParameterDefn("MeshLevelOfDetailCircular", "Level of detail for prims with circular cuts or shapes", 297 new ParameterDefn<float>("MeshLevelOfDetailCircular", "Level of detail for prims with circular cuts or shapes",
236 32f, 298 32f,
237 (s,cf,p,v) => { MeshCircularLOD = (float)cf.GetInt(p, (int)v); },
238 (s) => { return MeshCircularLOD; }, 299 (s) => { return MeshCircularLOD; },
239 (s,p,l,v) => { MeshCircularLOD = v; } ), 300 (s,v) => { MeshCircularLOD = v; } ),
240 new ParameterDefn("MeshLevelOfDetailMegaPrimThreshold", "Size (in meters) of a mesh before using MeshMegaPrimLOD", 301 new ParameterDefn<float>("MeshLevelOfDetailMegaPrimThreshold", "Size (in meters) of a mesh before using MeshMegaPrimLOD",
241 10f, 302 10f,
242 (s,cf,p,v) => { MeshMegaPrimThreshold = (float)cf.GetInt(p, (int)v); },
243 (s) => { return MeshMegaPrimThreshold; }, 303 (s) => { return MeshMegaPrimThreshold; },
244 (s,p,l,v) => { MeshMegaPrimThreshold = v; } ), 304 (s,v) => { MeshMegaPrimThreshold = v; } ),
245 new ParameterDefn("MeshLevelOfDetailMegaPrim", "Level of detail to render meshes larger than threshold meters", 305 new ParameterDefn<float>("MeshLevelOfDetailMegaPrim", "Level of detail to render meshes larger than threshold meters",
246 32f, 306 32f,
247 (s,cf,p,v) => { MeshMegaPrimLOD = (float)cf.GetInt(p, (int)v); },
248 (s) => { return MeshMegaPrimLOD; }, 307 (s) => { return MeshMegaPrimLOD; },
249 (s,p,l,v) => { MeshMegaPrimLOD = v; } ), 308 (s,v) => { MeshMegaPrimLOD = v; } ),
250 new ParameterDefn("SculptLevelOfDetail", "Level of detail to render sculpties (32, 16, 8 or 4. 32=most detailed)", 309 new ParameterDefn<float>("SculptLevelOfDetail", "Level of detail to render sculpties (32, 16, 8 or 4. 32=most detailed)",
251 32f, 310 32f,
252 (s,cf,p,v) => { SculptLOD = (float)cf.GetInt(p, (int)v); },
253 (s) => { return SculptLOD; }, 311 (s) => { return SculptLOD; },
254 (s,p,l,v) => { SculptLOD = v; } ), 312 (s,v) => { SculptLOD = v; } ),
255 313
256 new ParameterDefn("MaxSubStep", "In simulation step, maximum number of substeps", 314 new ParameterDefn<int>("MaxSubStep", "In simulation step, maximum number of substeps",
257 10f, 315 10,
258 (s,cf,p,v) => { s.m_maxSubSteps = cf.GetInt(p, (int)v); }, 316 (s) => { return s.m_maxSubSteps; },
259 (s) => { return (float)s.m_maxSubSteps; }, 317 (s,v) => { s.m_maxSubSteps = (int)v; } ),
260 (s,p,l,v) => { s.m_maxSubSteps = (int)v; } ), 318 new ParameterDefn<float>("FixedTimeStep", "In simulation step, seconds of one substep (1/60)",
261 new ParameterDefn("FixedTimeStep", "In simulation step, seconds of one substep (1/60)",
262 1f / 60f, 319 1f / 60f,
263 (s,cf,p,v) => { s.m_fixedTimeStep = cf.GetFloat(p, v); }, 320 (s) => { return s.m_fixedTimeStep; },
264 (s) => { return (float)s.m_fixedTimeStep; }, 321 (s,v) => { s.m_fixedTimeStep = v; } ),
265 (s,p,l,v) => { s.m_fixedTimeStep = v; } ), 322 new ParameterDefn<float>("NominalFrameRate", "The base frame rate we claim",
266 new ParameterDefn("NominalFrameRate", "The base frame rate we claim",
267 55f, 323 55f,
268 (s,cf,p,v) => { s.NominalFrameRate = cf.GetInt(p, (int)v); }, 324 (s) => { return s.NominalFrameRate; },
269 (s) => { return (float)s.NominalFrameRate; }, 325 (s,v) => { s.NominalFrameRate = (int)v; } ),
270 (s,p,l,v) => { s.NominalFrameRate = (int)v; } ), 326 new ParameterDefn<int>("MaxCollisionsPerFrame", "Max collisions returned at end of each frame",
271 new ParameterDefn("MaxCollisionsPerFrame", "Max collisions returned at end of each frame", 327 2048,
272 2048f, 328 (s) => { return s.m_maxCollisionsPerFrame; },
273 (s,cf,p,v) => { s.m_maxCollisionsPerFrame = cf.GetInt(p, (int)v); }, 329 (s,v) => { s.m_maxCollisionsPerFrame = (int)v; } ),
274 (s) => { return (float)s.m_maxCollisionsPerFrame; }, 330 new ParameterDefn<int>("MaxUpdatesPerFrame", "Max updates returned at end of each frame",
275 (s,p,l,v) => { s.m_maxCollisionsPerFrame = (int)v; } ), 331 8000,
276 new ParameterDefn("MaxUpdatesPerFrame", "Max updates returned at end of each frame", 332 (s) => { return s.m_maxUpdatesPerFrame; },
277 8000f, 333 (s,v) => { s.m_maxUpdatesPerFrame = (int)v; } ),
278 (s,cf,p,v) => { s.m_maxUpdatesPerFrame = cf.GetInt(p, (int)v); }, 334
279 (s) => { return (float)s.m_maxUpdatesPerFrame; }, 335 new ParameterDefn<float>("MinObjectMass", "Minimum object mass (0.0001)",
280 (s,p,l,v) => { s.m_maxUpdatesPerFrame = (int)v; } ),
281
282 new ParameterDefn("MinObjectMass", "Minimum object mass (0.0001)",
283 0.0001f, 336 0.0001f,
284 (s,cf,p,v) => { MinimumObjectMass = cf.GetFloat(p, v); },
285 (s) => { return MinimumObjectMass; }, 337 (s) => { return MinimumObjectMass; },
286 (s,p,l,v) => { MinimumObjectMass = v; } ), 338 (s,v) => { MinimumObjectMass = v; } ),
287 new ParameterDefn("MaxObjectMass", "Maximum object mass (10000.01)", 339 new ParameterDefn<float>("MaxObjectMass", "Maximum object mass (10000.01)",
288 10000.01f, 340 10000.01f,
289 (s,cf,p,v) => { MaximumObjectMass = cf.GetFloat(p, v); },
290 (s) => { return MaximumObjectMass; }, 341 (s) => { return MaximumObjectMass; },
291 (s,p,l,v) => { MaximumObjectMass = v; } ), 342 (s,v) => { MaximumObjectMass = v; } ),
292 new ParameterDefn("MaxLinearVelocity", "Maximum velocity magnitude that can be assigned to an object", 343 new ParameterDefn<float>("MaxLinearVelocity", "Maximum velocity magnitude that can be assigned to an object",
293 1000.0f, 344 1000.0f,
294 (s,cf,p,v) => { MaxLinearVelocity = cf.GetFloat(p, v); },
295 (s) => { return MaxLinearVelocity; }, 345 (s) => { return MaxLinearVelocity; },
296 (s,p,l,v) => { MaxLinearVelocity = v; } ), 346 (s,v) => { MaxLinearVelocity = v; } ),
297 new ParameterDefn("MaxAngularVelocity", "Maximum rotational velocity magnitude that can be assigned to an object", 347 new ParameterDefn<float>("MaxAngularVelocity", "Maximum rotational velocity magnitude that can be assigned to an object",
298 1000.0f, 348 1000.0f,
299 (s,cf,p,v) => { MaxAngularVelocity = cf.GetFloat(p, v); },
300 (s) => { return MaxAngularVelocity; }, 349 (s) => { return MaxAngularVelocity; },
301 (s,p,l,v) => { MaxAngularVelocity = v; } ), 350 (s,v) => { MaxAngularVelocity = v; } ),
302 // LL documentation says thie number should be 20f for llApplyImpulse and 200f for llRezObject 351 // LL documentation says thie number should be 20f for llApplyImpulse and 200f for llRezObject
303 new ParameterDefn("MaxAddForceMagnitude", "Maximum force that can be applied by llApplyImpulse (SL says 20f)", 352 new ParameterDefn<float>("MaxAddForceMagnitude", "Maximum force that can be applied by llApplyImpulse (SL says 20f)",
304 20000.0f, 353 20000.0f,
305 (s,cf,p,v) => { MaxAddForceMagnitude = cf.GetFloat(p, v); },
306 (s) => { return MaxAddForceMagnitude; }, 354 (s) => { return MaxAddForceMagnitude; },
307 (s,p,l,v) => { MaxAddForceMagnitude = v; } ), 355 (s,v) => { MaxAddForceMagnitude = v; } ),
308 // Density is passed around as 100kg/m3. This scales that to 1kg/m3. 356 // Density is passed around as 100kg/m3. This scales that to 1kg/m3.
309 new ParameterDefn("DensityScaleFactor", "Conversion for simulator/viewer density (100kg/m3) to physical density (1kg/m3)", 357 new ParameterDefn<float>("DensityScaleFactor", "Conversion for simulator/viewer density (100kg/m3) to physical density (1kg/m3)",
310 0.01f, 358 0.01f,
311 (s,cf,p,v) => { DensityScaleFactor = cf.GetFloat(p, v); },
312 (s) => { return DensityScaleFactor; }, 359 (s) => { return DensityScaleFactor; },
313 (s,p,l,v) => { DensityScaleFactor = v; } ), 360 (s,v) => { DensityScaleFactor = v; } ),
314 361
315 new ParameterDefn("PID_D", "Derivitive factor for motion smoothing", 362 new ParameterDefn<float>("PID_D", "Derivitive factor for motion smoothing",
316 2200f, 363 2200f,
317 (s,cf,p,v) => { PID_D = cf.GetFloat(p, v); },
318 (s) => { return (float)PID_D; }, 364 (s) => { return (float)PID_D; },
319 (s,p,l,v) => { PID_D = v; } ), 365 (s,v) => { PID_D = v; } ),
320 new ParameterDefn("PID_P", "Parameteric factor for motion smoothing", 366 new ParameterDefn<float>("PID_P", "Parameteric factor for motion smoothing",
321 900f, 367 900f,
322 (s,cf,p,v) => { PID_P = cf.GetFloat(p, v); },
323 (s) => { return (float)PID_P; }, 368 (s) => { return (float)PID_P; },
324 (s,p,l,v) => { PID_P = v; } ), 369 (s,v) => { PID_P = v; } ),
325 370
326 new ParameterDefn("DefaultFriction", "Friction factor used on new objects", 371 new ParameterDefn<float>("DefaultFriction", "Friction factor used on new objects",
327 0.2f, 372 0.2f,
328 (s,cf,p,v) => { DefaultFriction = cf.GetFloat(p, v); },
329 (s) => { return DefaultFriction; }, 373 (s) => { return DefaultFriction; },
330 (s,p,l,v) => { DefaultFriction = v; s.UnmanagedParams[0].defaultFriction = v; } ), 374 (s,v) => { DefaultFriction = v; s.UnmanagedParams[0].defaultFriction = v; } ),
331 new ParameterDefn("DefaultDensity", "Density for new objects" , 375 new ParameterDefn<float>("DefaultDensity", "Density for new objects" ,
332 10.000006836f, // Aluminum g/cm3 376 10.000006836f, // Aluminum g/cm3
333 (s,cf,p,v) => { DefaultDensity = cf.GetFloat(p, v); },
334 (s) => { return DefaultDensity; }, 377 (s) => { return DefaultDensity; },
335 (s,p,l,v) => { DefaultDensity = v; s.UnmanagedParams[0].defaultDensity = v; } ), 378 (s,v) => { DefaultDensity = v; s.UnmanagedParams[0].defaultDensity = v; } ),
336 new ParameterDefn("DefaultRestitution", "Bouncyness of an object" , 379 new ParameterDefn<float>("DefaultRestitution", "Bouncyness of an object" ,
337 0f, 380 0f,
338 (s,cf,p,v) => { DefaultRestitution = cf.GetFloat(p, v); },
339 (s) => { return DefaultRestitution; }, 381 (s) => { return DefaultRestitution; },
340 (s,p,l,v) => { DefaultRestitution = v; s.UnmanagedParams[0].defaultRestitution = v; } ), 382 (s,v) => { DefaultRestitution = v; s.UnmanagedParams[0].defaultRestitution = v; } ),
341 new ParameterDefn("CollisionMargin", "Margin around objects before collisions are calculated (must be zero!)", 383 new ParameterDefn<float>("CollisionMargin", "Margin around objects before collisions are calculated (must be zero!)",
342 0.04f, 384 0.04f,
343 (s,cf,p,v) => { CollisionMargin = cf.GetFloat(p, v); },
344 (s) => { return CollisionMargin; }, 385 (s) => { return CollisionMargin; },
345 (s,p,l,v) => { CollisionMargin = v; s.UnmanagedParams[0].collisionMargin = v; } ), 386 (s,v) => { CollisionMargin = v; s.UnmanagedParams[0].collisionMargin = v; } ),
346 new ParameterDefn("Gravity", "Vertical force of gravity (negative means down)", 387 new ParameterDefn<float>("Gravity", "Vertical force of gravity (negative means down)",
347 -9.80665f, 388 -9.80665f,
348 (s,cf,p,v) => { Gravity = cf.GetFloat(p, v); },
349 (s) => { return Gravity; }, 389 (s) => { return Gravity; },
350 (s,p,l,v) => { Gravity = v; s.UnmanagedParams[0].gravity = v; }, 390 (s,v) => { Gravity = v; s.UnmanagedParams[0].gravity = v; },
351 (s,o,v) => { s.PE.SetGravity(o.PhysBody, new Vector3(0f,0f,v)); } ), 391 (s,o) => { s.PE.SetGravity(o.PhysBody, new Vector3(0f,0f,Gravity)); } ),
352 392
353 393
354 new ParameterDefn("LinearDamping", "Factor to damp linear movement per second (0.0 - 1.0)", 394 new ParameterDefn<float>("LinearDamping", "Factor to damp linear movement per second (0.0 - 1.0)",
355 0f, 395 0f,
356 (s,cf,p,v) => { LinearDamping = cf.GetFloat(p, v); },
357 (s) => { return LinearDamping; }, 396 (s) => { return LinearDamping; },
358 (s,p,l,v) => { LinearDamping = v; }, 397 (s,v) => { LinearDamping = v; },
359 (s,o,v) => { s.PE.SetDamping(o.PhysBody, v, AngularDamping); } ), 398 (s,o) => { s.PE.SetDamping(o.PhysBody, LinearDamping, AngularDamping); } ),
360 new ParameterDefn("AngularDamping", "Factor to damp angular movement per second (0.0 - 1.0)", 399 new ParameterDefn<float>("AngularDamping", "Factor to damp angular movement per second (0.0 - 1.0)",
361 0f, 400 0f,
362 (s,cf,p,v) => { AngularDamping = cf.GetFloat(p, v); },
363 (s) => { return AngularDamping; }, 401 (s) => { return AngularDamping; },
364 (s,p,l,v) => { AngularDamping = v; }, 402 (s,v) => { AngularDamping = v; },
365 (s,o,v) => { s.PE.SetDamping(o.PhysBody, LinearDamping, v); } ), 403 (s,o) => { s.PE.SetDamping(o.PhysBody, LinearDamping, AngularDamping); } ),
366 new ParameterDefn("DeactivationTime", "Seconds before considering an object potentially static", 404 new ParameterDefn<float>("DeactivationTime", "Seconds before considering an object potentially static",
367 0.2f, 405 0.2f,
368 (s,cf,p,v) => { DeactivationTime = cf.GetFloat(p, v); },
369 (s) => { return DeactivationTime; }, 406 (s) => { return DeactivationTime; },
370 (s,p,l,v) => { DeactivationTime = v; }, 407 (s,v) => { DeactivationTime = v; },
371 (s,o,v) => { s.PE.SetDeactivationTime(o.PhysBody, v); } ), 408 (s,o) => { s.PE.SetDeactivationTime(o.PhysBody, DeactivationTime); } ),
372 new ParameterDefn("LinearSleepingThreshold", "Seconds to measure linear movement before considering static", 409 new ParameterDefn<float>("LinearSleepingThreshold", "Seconds to measure linear movement before considering static",
373 0.8f, 410 0.8f,
374 (s,cf,p,v) => { LinearSleepingThreshold = cf.GetFloat(p, v); },
375 (s) => { return LinearSleepingThreshold; }, 411 (s) => { return LinearSleepingThreshold; },
376 (s,p,l,v) => { LinearSleepingThreshold = v;}, 412 (s,v) => { LinearSleepingThreshold = v;},
377 (s,o,v) => { s.PE.SetSleepingThresholds(o.PhysBody, v, v); } ), 413 (s,o) => { s.PE.SetSleepingThresholds(o.PhysBody, LinearSleepingThreshold, AngularSleepingThreshold); } ),
378 new ParameterDefn("AngularSleepingThreshold", "Seconds to measure angular movement before considering static", 414 new ParameterDefn<float>("AngularSleepingThreshold", "Seconds to measure angular movement before considering static",
379 1.0f, 415 1.0f,
380 (s,cf,p,v) => { AngularSleepingThreshold = cf.GetFloat(p, v); },
381 (s) => { return AngularSleepingThreshold; }, 416 (s) => { return AngularSleepingThreshold; },
382 (s,p,l,v) => { AngularSleepingThreshold = v;}, 417 (s,v) => { AngularSleepingThreshold = v;},
383 (s,o,v) => { s.PE.SetSleepingThresholds(o.PhysBody, v, v); } ), 418 (s,o) => { s.PE.SetSleepingThresholds(o.PhysBody, LinearSleepingThreshold, AngularSleepingThreshold); } ),
384 new ParameterDefn("CcdMotionThreshold", "Continuious collision detection threshold (0 means no CCD)" , 419 new ParameterDefn<float>("CcdMotionThreshold", "Continuious collision detection threshold (0 means no CCD)" ,
385 0.0f, // set to zero to disable 420 0.0f, // set to zero to disable
386 (s,cf,p,v) => { CcdMotionThreshold = cf.GetFloat(p, v); },
387 (s) => { return CcdMotionThreshold; }, 421 (s) => { return CcdMotionThreshold; },
388 (s,p,l,v) => { CcdMotionThreshold = v;}, 422 (s,v) => { CcdMotionThreshold = v;},
389 (s,o,v) => { s.PE.SetCcdMotionThreshold(o.PhysBody, v); } ), 423 (s,o) => { s.PE.SetCcdMotionThreshold(o.PhysBody, CcdMotionThreshold); } ),
390 new ParameterDefn("CcdSweptSphereRadius", "Continuious collision detection test radius" , 424 new ParameterDefn<float>("CcdSweptSphereRadius", "Continuious collision detection test radius" ,
391 0.2f, 425 0.2f,
392 (s,cf,p,v) => { CcdSweptSphereRadius = cf.GetFloat(p, v); },
393 (s) => { return CcdSweptSphereRadius; }, 426 (s) => { return CcdSweptSphereRadius; },
394 (s,p,l,v) => { CcdSweptSphereRadius = v;}, 427 (s,v) => { CcdSweptSphereRadius = v;},
395 (s,o,v) => { s.PE.SetCcdSweptSphereRadius(o.PhysBody, v); } ), 428 (s,o) => { s.PE.SetCcdSweptSphereRadius(o.PhysBody, CcdSweptSphereRadius); } ),
396 new ParameterDefn("ContactProcessingThreshold", "Distance above which contacts can be discarded (0 means no discard)" , 429 new ParameterDefn<float>("ContactProcessingThreshold", "Distance above which contacts can be discarded (0 means no discard)" ,
397 0.0f, 430 0.0f,
398 (s,cf,p,v) => { ContactProcessingThreshold = cf.GetFloat(p, v); },
399 (s) => { return ContactProcessingThreshold; }, 431 (s) => { return ContactProcessingThreshold; },
400 (s,p,l,v) => { ContactProcessingThreshold = v;}, 432 (s,v) => { ContactProcessingThreshold = v;},
401 (s,o,v) => { s.PE.SetContactProcessingThreshold(o.PhysBody, v); } ), 433 (s,o) => { s.PE.SetContactProcessingThreshold(o.PhysBody, ContactProcessingThreshold); } ),
402 434
403 new ParameterDefn("TerrainImplementation", "Type of shape to use for terrain (0=heightmap, 1=mesh)", 435 new ParameterDefn<float>("TerrainImplementation", "Type of shape to use for terrain (0=heightmap, 1=mesh)",
404 (float)BSTerrainPhys.TerrainImplementation.Mesh, 436 (float)BSTerrainPhys.TerrainImplementation.Mesh,
405 (s,cf,p,v) => { TerrainImplementation = cf.GetFloat(p,v); },
406 (s) => { return TerrainImplementation; }, 437 (s) => { return TerrainImplementation; },
407 (s,p,l,v) => { TerrainImplementation = v; } ), 438 (s,v) => { TerrainImplementation = v; } ),
408 new ParameterDefn("TerrainFriction", "Factor to reduce movement against terrain surface" , 439 new ParameterDefn<float>("TerrainFriction", "Factor to reduce movement against terrain surface" ,
409 0.3f, 440 0.3f,
410 (s,cf,p,v) => { TerrainFriction = cf.GetFloat(p, v); },
411 (s) => { return TerrainFriction; }, 441 (s) => { return TerrainFriction; },
412 (s,p,l,v) => { TerrainFriction = v; /* TODO: set on real terrain */} ), 442 (s,v) => { TerrainFriction = v; /* TODO: set on real terrain */} ),
413 new ParameterDefn("TerrainHitFraction", "Distance to measure hit collisions" , 443 new ParameterDefn<float>("TerrainHitFraction", "Distance to measure hit collisions" ,
414 0.8f, 444 0.8f,
415 (s,cf,p,v) => { TerrainHitFraction = cf.GetFloat(p, v); },
416 (s) => { return TerrainHitFraction; }, 445 (s) => { return TerrainHitFraction; },
417 (s,p,l,v) => { TerrainHitFraction = v; /* TODO: set on real terrain */ } ), 446 (s,v) => { TerrainHitFraction = v; /* TODO: set on real terrain */ } ),
418 new ParameterDefn("TerrainRestitution", "Bouncyness" , 447 new ParameterDefn<float>("TerrainRestitution", "Bouncyness" ,
419 0f, 448 0f,
420 (s,cf,p,v) => { TerrainRestitution = cf.GetFloat(p, v); },
421 (s) => { return TerrainRestitution; }, 449 (s) => { return TerrainRestitution; },
422 (s,p,l,v) => { TerrainRestitution = v; /* TODO: set on real terrain */ } ), 450 (s,v) => { TerrainRestitution = v; /* TODO: set on real terrain */ } ),
423 new ParameterDefn("TerrainCollisionMargin", "Margin where collision checking starts" , 451 new ParameterDefn<float>("TerrainCollisionMargin", "Margin where collision checking starts" ,
424 0.08f, 452 0.08f,
425 (s,cf,p,v) => { TerrainCollisionMargin = cf.GetFloat(p, v); },
426 (s) => { return TerrainCollisionMargin; }, 453 (s) => { return TerrainCollisionMargin; },
427 (s,p,l,v) => { TerrainCollisionMargin = v; /* TODO: set on real terrain */ } ), 454 (s,v) => { TerrainCollisionMargin = v; /* TODO: set on real terrain */ } ),
428 455
429 new ParameterDefn("AvatarFriction", "Factor to reduce movement against an avatar. Changed on avatar recreation.", 456 new ParameterDefn<float>("AvatarFriction", "Factor to reduce movement against an avatar. Changed on avatar recreation.",
430 0.2f, 457 0.2f,
431 (s,cf,p,v) => { AvatarFriction = cf.GetFloat(p, v); },
432 (s) => { return AvatarFriction; }, 458 (s) => { return AvatarFriction; },
433 (s,p,l,v) => { AvatarFriction = v; } ), 459 (s,v) => { AvatarFriction = v; } ),
434 new ParameterDefn("AvatarStandingFriction", "Avatar friction when standing. Changed on avatar recreation.", 460 new ParameterDefn<float>("AvatarStandingFriction", "Avatar friction when standing. Changed on avatar recreation.",
435 0.95f, 461 0.95f,
436 (s,cf,p,v) => { AvatarStandingFriction = cf.GetFloat(p, v); },
437 (s) => { return AvatarStandingFriction; }, 462 (s) => { return AvatarStandingFriction; },
438 (s,p,l,v) => { AvatarStandingFriction = v; } ), 463 (s,v) => { AvatarStandingFriction = v; } ),
439 new ParameterDefn("AvatarAlwaysRunFactor", "Speed multiplier if avatar is set to always run", 464 new ParameterDefn<float>("AvatarAlwaysRunFactor", "Speed multiplier if avatar is set to always run",
440 1.3f, 465 1.3f,
441 (s,cf,p,v) => { AvatarAlwaysRunFactor = cf.GetFloat(p, v); },
442 (s) => { return AvatarAlwaysRunFactor; }, 466 (s) => { return AvatarAlwaysRunFactor; },
443 (s,p,l,v) => { AvatarAlwaysRunFactor = v; } ), 467 (s,v) => { AvatarAlwaysRunFactor = v; } ),
444 new ParameterDefn("AvatarDensity", "Density of an avatar. Changed on avatar recreation.", 468 new ParameterDefn<float>("AvatarDensity", "Density of an avatar. Changed on avatar recreation.",
445 3.5f, 469 3.5f,
446 (s,cf,p,v) => { AvatarDensity = cf.GetFloat(p, v); },
447 (s) => { return AvatarDensity; }, 470 (s) => { return AvatarDensity; },
448 (s,p,l,v) => { AvatarDensity = v; } ), 471 (s,v) => { AvatarDensity = v; } ),
449 new ParameterDefn("AvatarRestitution", "Bouncyness. Changed on avatar recreation.", 472 new ParameterDefn<float>("AvatarRestitution", "Bouncyness. Changed on avatar recreation.",
450 0f, 473 0f,
451 (s,cf,p,v) => { AvatarRestitution = cf.GetFloat(p, v); },
452 (s) => { return AvatarRestitution; }, 474 (s) => { return AvatarRestitution; },
453 (s,p,l,v) => { AvatarRestitution = v; } ), 475 (s,v) => { AvatarRestitution = v; } ),
454 new ParameterDefn("AvatarCapsuleWidth", "The distance between the sides of the avatar capsule", 476 new ParameterDefn<float>("AvatarCapsuleWidth", "The distance between the sides of the avatar capsule",
455 0.6f, 477 0.6f,
456 (s,cf,p,v) => { AvatarCapsuleWidth = cf.GetFloat(p, v); },
457 (s) => { return AvatarCapsuleWidth; }, 478 (s) => { return AvatarCapsuleWidth; },
458 (s,p,l,v) => { AvatarCapsuleWidth = v; } ), 479 (s,v) => { AvatarCapsuleWidth = v; } ),
459 new ParameterDefn("AvatarCapsuleDepth", "The distance between the front and back of the avatar capsule", 480 new ParameterDefn<float>("AvatarCapsuleDepth", "The distance between the front and back of the avatar capsule",
460 0.45f, 481 0.45f,
461 (s,cf,p,v) => { AvatarCapsuleDepth = cf.GetFloat(p, v); },
462 (s) => { return AvatarCapsuleDepth; }, 482 (s) => { return AvatarCapsuleDepth; },
463 (s,p,l,v) => { AvatarCapsuleDepth = v; } ), 483 (s,v) => { AvatarCapsuleDepth = v; } ),
464 new ParameterDefn("AvatarCapsuleHeight", "Default height of space around avatar", 484 new ParameterDefn<float>("AvatarCapsuleHeight", "Default height of space around avatar",
465 1.5f, 485 1.5f,
466 (s,cf,p,v) => { AvatarCapsuleHeight = cf.GetFloat(p, v); },
467 (s) => { return AvatarCapsuleHeight; }, 486 (s) => { return AvatarCapsuleHeight; },
468 (s,p,l,v) => { AvatarCapsuleHeight = v; } ), 487 (s,v) => { AvatarCapsuleHeight = v; } ),
469 new ParameterDefn("AvatarContactProcessingThreshold", "Distance from capsule to check for collisions", 488 new ParameterDefn<float>("AvatarContactProcessingThreshold", "Distance from capsule to check for collisions",
470 0.1f, 489 0.1f,
471 (s,cf,p,v) => { AvatarContactProcessingThreshold = cf.GetFloat(p, v); },
472 (s) => { return AvatarContactProcessingThreshold; }, 490 (s) => { return AvatarContactProcessingThreshold; },
473 (s,p,l,v) => { AvatarContactProcessingThreshold = v; } ), 491 (s,v) => { AvatarContactProcessingThreshold = v; } ),
474 new ParameterDefn("AvatarStepHeight", "Height of a step obstacle to consider step correction", 492 new ParameterDefn<float>("AvatarStepHeight", "Height of a step obstacle to consider step correction",
475 0.3f, 493 0.3f,
476 (s,cf,p,v) => { AvatarStepHeight = cf.GetFloat(p, v); },
477 (s) => { return AvatarStepHeight; }, 494 (s) => { return AvatarStepHeight; },
478 (s,p,l,v) => { AvatarStepHeight = v; } ), 495 (s,v) => { AvatarStepHeight = v; } ),
479 new ParameterDefn("AvatarStepApproachFactor", "Factor to control angle of approach to step (0=straight on)", 496 new ParameterDefn<float>("AvatarStepApproachFactor", "Factor to control angle of approach to step (0=straight on)",
480 0.6f, 497 0.6f,
481 (s,cf,p,v) => { AvatarStepApproachFactor = cf.GetFloat(p, v); },
482 (s) => { return AvatarStepApproachFactor; }, 498 (s) => { return AvatarStepApproachFactor; },
483 (s,p,l,v) => { AvatarStepApproachFactor = v; } ), 499 (s,v) => { AvatarStepApproachFactor = v; } ),
484 new ParameterDefn("AvatarStepForceFactor", "Controls the amount of force up applied to step up onto a step", 500 new ParameterDefn<float>("AvatarStepForceFactor", "Controls the amount of force up applied to step up onto a step",
485 2.0f, 501 2.0f,
486 (s,cf,p,v) => { AvatarStepForceFactor = cf.GetFloat(p, v); },
487 (s) => { return AvatarStepForceFactor; }, 502 (s) => { return AvatarStepForceFactor; },
488 (s,p,l,v) => { AvatarStepForceFactor = v; } ), 503 (s,v) => { AvatarStepForceFactor = v; } ),
489 504
490 new ParameterDefn("VehicleMaxLinearVelocity", "Maximum velocity magnitude that can be assigned to a vehicle", 505 new ParameterDefn<float>("VehicleMaxLinearVelocity", "Maximum velocity magnitude that can be assigned to a vehicle",
491 1000.0f, 506 1000.0f,
492 (s,cf,p,v) => { VehicleMaxLinearVelocity = cf.GetFloat(p, v); },
493 (s) => { return (float)VehicleMaxLinearVelocity; }, 507 (s) => { return (float)VehicleMaxLinearVelocity; },
494 (s,p,l,v) => { VehicleMaxLinearVelocity = v; VehicleMaxLinearVelocitySq = v * v; } ), 508 (s,v) => { VehicleMaxLinearVelocity = v; VehicleMaxLinearVelocitySq = v * v; } ),
495 new ParameterDefn("VehicleMaxAngularVelocity", "Maximum rotational velocity magnitude that can be assigned to a vehicle", 509 new ParameterDefn<float>("VehicleMaxAngularVelocity", "Maximum rotational velocity magnitude that can be assigned to a vehicle",
496 12.0f, 510 12.0f,
497 (s,cf,p,v) => { VehicleMaxAngularVelocity = cf.GetFloat(p, v); },
498 (s) => { return (float)VehicleMaxAngularVelocity; }, 511 (s) => { return (float)VehicleMaxAngularVelocity; },
499 (s,p,l,v) => { VehicleMaxAngularVelocity = v; VehicleMaxAngularVelocitySq = v * v; } ), 512 (s,v) => { VehicleMaxAngularVelocity = v; VehicleMaxAngularVelocitySq = v * v; } ),
500 new ParameterDefn("VehicleAngularDamping", "Factor to damp vehicle angular movement per second (0.0 - 1.0)", 513 new ParameterDefn<float>("VehicleAngularDamping", "Factor to damp vehicle angular movement per second (0.0 - 1.0)",
501 0.0f, 514 0.0f,
502 (s,cf,p,v) => { VehicleAngularDamping = cf.GetFloat(p, v); },
503 (s) => { return VehicleAngularDamping; }, 515 (s) => { return VehicleAngularDamping; },
504 (s,p,l,v) => { VehicleAngularDamping = v; } ), 516 (s,v) => { VehicleAngularDamping = v; } ),
505 new ParameterDefn("VehicleLinearFactor", "Fraction of physical linear changes applied to vehicle (0.0 - 1.0)", 517 new ParameterDefn<Vector3>("VehicleLinearFactor", "Fraction of physical linear changes applied to vehicle (<0,0,0> to <1,1,1>)",
506 1.0f, 518 new Vector3(1f, 1f, 1f),
507 (s,cf,p,v) => { VehicleLinearFactor = cf.GetFloat(p, v); },
508 (s) => { return VehicleLinearFactor; }, 519 (s) => { return VehicleLinearFactor; },
509 (s,p,l,v) => { VehicleLinearFactor = v; VehicleLinearFactorV = new Vector3(v, v, v); } ), 520 (s,v) => { VehicleLinearFactor = v; } ),
510 new ParameterDefn("VehicleAngularFactor", "Fraction of physical angular changes applied to vehicle (0.0 - 1.0)", 521 new ParameterDefn<Vector3>("VehicleAngularFactor", "Fraction of physical angular changes applied to vehicle (<0,0,0> to <1,1,1>)",
511 1.0f, 522 new Vector3(1f, 1f, 1f),
512 (s,cf,p,v) => { VehicleAngularFactor = cf.GetFloat(p, v); },
513 (s) => { return VehicleAngularFactor; }, 523 (s) => { return VehicleAngularFactor; },
514 (s,p,l,v) => { VehicleAngularFactor = v; VehicleAngularFactorV = new Vector3(v, v, v); } ), 524 (s,v) => { VehicleAngularFactor = v; } ),
515 new ParameterDefn("VehicleFriction", "Friction of vehicle on the ground (0.0 - 1.0)", 525 new ParameterDefn<float>("VehicleFriction", "Friction of vehicle on the ground (0.0 - 1.0)",
516 0.0f, 526 0.0f,
517 (s,cf,p,v) => { VehicleFriction = cf.GetFloat(p, v); },
518 (s) => { return VehicleFriction; }, 527 (s) => { return VehicleFriction; },
519 (s,p,l,v) => { VehicleFriction = v; } ), 528 (s,v) => { VehicleFriction = v; } ),
520 new ParameterDefn("VehicleRestitution", "Bouncyness factor for vehicles (0.0 - 1.0)", 529 new ParameterDefn<float>("VehicleRestitution", "Bouncyness factor for vehicles (0.0 - 1.0)",
521 0.0f, 530 0.0f,
522 (s,cf,p,v) => { VehicleRestitution = cf.GetFloat(p, v); },
523 (s) => { return VehicleRestitution; }, 531 (s) => { return VehicleRestitution; },
524 (s,p,l,v) => { VehicleRestitution = v; } ), 532 (s,v) => { VehicleRestitution = v; } ),
525 new ParameterDefn("VehicleGroundGravityFudge", "Factor to multiple gravity if a ground vehicle is probably on the ground (0.0 - 1.0)", 533 new ParameterDefn<float>("VehicleGroundGravityFudge", "Factor to multiple gravity if a ground vehicle is probably on the ground (0.0 - 1.0)",
526 0.2f, 534 0.2f,
527 (s,cf,p,v) => { VehicleGroundGravityFudge = cf.GetFloat(p, v); },
528 (s) => { return VehicleGroundGravityFudge; }, 535 (s) => { return VehicleGroundGravityFudge; },
529 (s,p,l,v) => { VehicleGroundGravityFudge = v; } ), 536 (s,v) => { VehicleGroundGravityFudge = v; } ),
530 new ParameterDefn("VehicleDebuggingEnable", "Turn on/off vehicle debugging", 537 new ParameterDefn<bool>("VehicleDebuggingEnable", "Turn on/off vehicle debugging",
531 ConfigurationParameters.numericFalse, 538 false,
532 (s,cf,p,v) => { VehicleDebuggingEnabled = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); },
533 (s) => { return VehicleDebuggingEnabled; }, 539 (s) => { return VehicleDebuggingEnabled; },
534 (s,p,l,v) => { VehicleDebuggingEnabled = v; } ), 540 (s,v) => { VehicleDebuggingEnabled = v; } ),
535 541
536 new ParameterDefn("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default of 4096)", 542 new ParameterDefn<float>("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default of 4096)",
537 0f, 543 0f,
538 (s,cf,p,v) => { MaxPersistantManifoldPoolSize = cf.GetFloat(p, v); },
539 (s) => { return MaxPersistantManifoldPoolSize; }, 544 (s) => { return MaxPersistantManifoldPoolSize; },
540 (s,p,l,v) => { MaxPersistantManifoldPoolSize = v; s.UnmanagedParams[0].maxPersistantManifoldPoolSize = v; } ), 545 (s,v) => { MaxPersistantManifoldPoolSize = v; s.UnmanagedParams[0].maxPersistantManifoldPoolSize = v; } ),
541 new ParameterDefn("MaxCollisionAlgorithmPoolSize", "Number of collisions pooled (0 means default of 4096)", 546 new ParameterDefn<float>("MaxCollisionAlgorithmPoolSize", "Number of collisions pooled (0 means default of 4096)",
542 0f, 547 0f,
543 (s,cf,p,v) => { MaxCollisionAlgorithmPoolSize = cf.GetFloat(p, v); },
544 (s) => { return MaxCollisionAlgorithmPoolSize; }, 548 (s) => { return MaxCollisionAlgorithmPoolSize; },
545 (s,p,l,v) => { MaxCollisionAlgorithmPoolSize = v; s.UnmanagedParams[0].maxCollisionAlgorithmPoolSize = v; } ), 549 (s,v) => { MaxCollisionAlgorithmPoolSize = v; s.UnmanagedParams[0].maxCollisionAlgorithmPoolSize = v; } ),
546 new ParameterDefn("ShouldDisableContactPoolDynamicAllocation", "Enable to allow large changes in object count", 550 new ParameterDefn<bool>("ShouldDisableContactPoolDynamicAllocation", "Enable to allow large changes in object count",
547 ConfigurationParameters.numericFalse, 551 false,
548 (s,cf,p,v) => { ShouldDisableContactPoolDynamicAllocation = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); },
549 (s) => { return ShouldDisableContactPoolDynamicAllocation; }, 552 (s) => { return ShouldDisableContactPoolDynamicAllocation; },
550 (s,p,l,v) => { ShouldDisableContactPoolDynamicAllocation = v; s.UnmanagedParams[0].shouldDisableContactPoolDynamicAllocation = v; } ), 553 (s,v) => { ShouldDisableContactPoolDynamicAllocation = v;
551 new ParameterDefn("ShouldForceUpdateAllAabbs", "Enable to recomputer AABBs every simulator step", 554 s.UnmanagedParams[0].shouldDisableContactPoolDynamicAllocation = NumericBool(v); } ),
552 ConfigurationParameters.numericFalse, 555 new ParameterDefn<bool>("ShouldForceUpdateAllAabbs", "Enable to recomputer AABBs every simulator step",
553 (s,cf,p,v) => { ShouldForceUpdateAllAabbs = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); }, 556 false,
554 (s) => { return ShouldForceUpdateAllAabbs; }, 557 (s) => { return ShouldForceUpdateAllAabbs; },
555 (s,p,l,v) => { ShouldForceUpdateAllAabbs = v; s.UnmanagedParams[0].shouldForceUpdateAllAabbs = v; } ), 558 (s,v) => { ShouldForceUpdateAllAabbs = v; s.UnmanagedParams[0].shouldForceUpdateAllAabbs = NumericBool(v); } ),
556 new ParameterDefn("ShouldRandomizeSolverOrder", "Enable for slightly better stacking interaction", 559 new ParameterDefn<bool>("ShouldRandomizeSolverOrder", "Enable for slightly better stacking interaction",
557 ConfigurationParameters.numericTrue, 560 true,
558 (s,cf,p,v) => { ShouldRandomizeSolverOrder = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); },
559 (s) => { return ShouldRandomizeSolverOrder; }, 561 (s) => { return ShouldRandomizeSolverOrder; },
560 (s,p,l,v) => { ShouldRandomizeSolverOrder = v; s.UnmanagedParams[0].shouldRandomizeSolverOrder = v; } ), 562 (s,v) => { ShouldRandomizeSolverOrder = v; s.UnmanagedParams[0].shouldRandomizeSolverOrder = NumericBool(v); } ),
561 new ParameterDefn("ShouldSplitSimulationIslands", "Enable splitting active object scanning islands", 563 new ParameterDefn<bool>("ShouldSplitSimulationIslands", "Enable splitting active object scanning islands",
562 ConfigurationParameters.numericTrue, 564 true,
563 (s,cf,p,v) => { ShouldSplitSimulationIslands = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); },
564 (s) => { return ShouldSplitSimulationIslands; }, 565 (s) => { return ShouldSplitSimulationIslands; },
565 (s,p,l,v) => { ShouldSplitSimulationIslands = v; s.UnmanagedParams[0].shouldSplitSimulationIslands = v; } ), 566 (s,v) => { ShouldSplitSimulationIslands = v; s.UnmanagedParams[0].shouldSplitSimulationIslands = NumericBool(v); } ),
566 new ParameterDefn("ShouldEnableFrictionCaching", "Enable friction computation caching", 567 new ParameterDefn<bool>("ShouldEnableFrictionCaching", "Enable friction computation caching",
567 ConfigurationParameters.numericTrue, 568 true,
568 (s,cf,p,v) => { ShouldEnableFrictionCaching = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); },
569 (s) => { return ShouldEnableFrictionCaching; }, 569 (s) => { return ShouldEnableFrictionCaching; },
570 (s,p,l,v) => { ShouldEnableFrictionCaching = v; s.UnmanagedParams[0].shouldEnableFrictionCaching = v; } ), 570 (s,v) => { ShouldEnableFrictionCaching = v; s.UnmanagedParams[0].shouldEnableFrictionCaching = NumericBool(v); } ),
571 new ParameterDefn("NumberOfSolverIterations", "Number of internal iterations (0 means default)", 571 new ParameterDefn<float>("NumberOfSolverIterations", "Number of internal iterations (0 means default)",
572 0f, // zero says use Bullet default 572 0f, // zero says use Bullet default
573 (s,cf,p,v) => { NumberOfSolverIterations = cf.GetFloat(p, v); },
574 (s) => { return NumberOfSolverIterations; }, 573 (s) => { return NumberOfSolverIterations; },
575 (s,p,l,v) => { NumberOfSolverIterations = v; s.UnmanagedParams[0].numberOfSolverIterations = v; } ), 574 (s,v) => { NumberOfSolverIterations = v; s.UnmanagedParams[0].numberOfSolverIterations = v; } ),
576 new ParameterDefn("UseSingleSidedMeshes", "Whether to compute collisions based on single sided meshes.", 575 new ParameterDefn<bool>("UseSingleSidedMeshes", "Whether to compute collisions based on single sided meshes.",
577 ConfigurationParameters.numericTrue, 576 true,
578 (s,cf,p,v) => { UseSingleSidedMeshesF = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); }, 577 (s) => { return UseSingleSidedMeshes; },
579 (s) => { return UseSingleSidedMeshesF; }, 578 (s,v) => { UseSingleSidedMeshes = v; s.UnmanagedParams[0].useSingleSidedMeshes = NumericBool(v); } ),
580 (s,p,l,v) => { UseSingleSidedMeshesF = v; s.UnmanagedParams[0].useSingleSidedMeshes = v; } ), 579 new ParameterDefn<float>("GlobalContactBreakingThreshold", "Amount of shape radius before breaking a collision contact (0 says Bullet default (0.2))",
581 new ParameterDefn("GlobalContactBreakingThreshold", "Amount of shape radius before breaking a collision contact (0 says Bullet default (0.2))",
582 0f, 580 0f,
583 (s,cf,p,v) => { GlobalContactBreakingThreshold = cf.GetFloat(p, v); },
584 (s) => { return GlobalContactBreakingThreshold; }, 581 (s) => { return GlobalContactBreakingThreshold; },
585 (s,p,l,v) => { GlobalContactBreakingThreshold = v; s.UnmanagedParams[0].globalContactBreakingThreshold = v; } ), 582 (s,v) => { GlobalContactBreakingThreshold = v; s.UnmanagedParams[0].globalContactBreakingThreshold = v; } ),
586 583
587 new ParameterDefn("LinksetImplementation", "Type of linkset implementation (0=Constraint, 1=Compound, 2=Manual)", 584 new ParameterDefn<float>("LinksetImplementation", "Type of linkset implementation (0=Constraint, 1=Compound, 2=Manual)",
588 (float)BSLinkset.LinksetImplementation.Compound, 585 (float)BSLinkset.LinksetImplementation.Compound,
589 (s,cf,p,v) => { LinksetImplementation = cf.GetFloat(p,v); },
590 (s) => { return LinksetImplementation; }, 586 (s) => { return LinksetImplementation; },
591 (s,p,l,v) => { LinksetImplementation = v; } ), 587 (s,v) => { LinksetImplementation = v; } ),
592 new ParameterDefn("LinkConstraintUseFrameOffset", "For linksets built with constraints, enable frame offsetFor linksets built with constraints, enable frame offset.", 588 new ParameterDefn<bool>("LinkConstraintUseFrameOffset", "For linksets built with constraints, enable frame offsetFor linksets built with constraints, enable frame offset.",
593 ConfigurationParameters.numericFalse, 589 false,
594 (s,cf,p,v) => { LinkConstraintUseFrameOffset = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); },
595 (s) => { return LinkConstraintUseFrameOffset; }, 590 (s) => { return LinkConstraintUseFrameOffset; },
596 (s,p,l,v) => { LinkConstraintUseFrameOffset = v; } ), 591 (s,v) => { LinkConstraintUseFrameOffset = v; } ),
597 new ParameterDefn("LinkConstraintEnableTransMotor", "Whether to enable translational motor on linkset constraints", 592 new ParameterDefn<bool>("LinkConstraintEnableTransMotor", "Whether to enable translational motor on linkset constraints",
598 ConfigurationParameters.numericTrue, 593 true,
599 (s,cf,p,v) => { LinkConstraintEnableTransMotor = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); },
600 (s) => { return LinkConstraintEnableTransMotor; }, 594 (s) => { return LinkConstraintEnableTransMotor; },
601 (s,p,l,v) => { LinkConstraintEnableTransMotor = v; } ), 595 (s,v) => { LinkConstraintEnableTransMotor = v; } ),
602 new ParameterDefn("LinkConstraintTransMotorMaxVel", "Maximum velocity to be applied by translational motor in linkset constraints", 596 new ParameterDefn<float>("LinkConstraintTransMotorMaxVel", "Maximum velocity to be applied by translational motor in linkset constraints",
603 5.0f, 597 5.0f,
604 (s,cf,p,v) => { LinkConstraintTransMotorMaxVel = cf.GetFloat(p, v); },
605 (s) => { return LinkConstraintTransMotorMaxVel; }, 598 (s) => { return LinkConstraintTransMotorMaxVel; },
606 (s,p,l,v) => { LinkConstraintTransMotorMaxVel = v; } ), 599 (s,v) => { LinkConstraintTransMotorMaxVel = v; } ),
607 new ParameterDefn("LinkConstraintTransMotorMaxForce", "Maximum force to be applied by translational motor in linkset constraints", 600 new ParameterDefn<float>("LinkConstraintTransMotorMaxForce", "Maximum force to be applied by translational motor in linkset constraints",
608 0.1f, 601 0.1f,
609 (s,cf,p,v) => { LinkConstraintTransMotorMaxForce = cf.GetFloat(p, v); },
610 (s) => { return LinkConstraintTransMotorMaxForce; }, 602 (s) => { return LinkConstraintTransMotorMaxForce; },
611 (s,p,l,v) => { LinkConstraintTransMotorMaxForce = v; } ), 603 (s,v) => { LinkConstraintTransMotorMaxForce = v; } ),
612 new ParameterDefn("LinkConstraintCFM", "Amount constraint can be violated. 0=no violation, 1=infinite. Default=0.1", 604 new ParameterDefn<float>("LinkConstraintCFM", "Amount constraint can be violated. 0=no violation, 1=infinite. Default=0.1",
613 0.1f, 605 0.1f,
614 (s,cf,p,v) => { LinkConstraintCFM = cf.GetFloat(p, v); },
615 (s) => { return LinkConstraintCFM; }, 606 (s) => { return LinkConstraintCFM; },
616 (s,p,l,v) => { LinkConstraintCFM = v; } ), 607 (s,v) => { LinkConstraintCFM = v; } ),
617 new ParameterDefn("LinkConstraintERP", "Amount constraint is corrected each tick. 0=none, 1=all. Default = 0.2", 608 new ParameterDefn<float>("LinkConstraintERP", "Amount constraint is corrected each tick. 0=none, 1=all. Default = 0.2",
618 0.1f, 609 0.1f,
619 (s,cf,p,v) => { LinkConstraintERP = cf.GetFloat(p, v); },
620 (s) => { return LinkConstraintERP; }, 610 (s) => { return LinkConstraintERP; },
621 (s,p,l,v) => { LinkConstraintERP = v; } ), 611 (s,v) => { LinkConstraintERP = v; } ),
622 new ParameterDefn("LinkConstraintSolverIterations", "Number of solver iterations when computing constraint. (0 = Bullet default)", 612 new ParameterDefn<float>("LinkConstraintSolverIterations", "Number of solver iterations when computing constraint. (0 = Bullet default)",
623 40, 613 40,
624 (s,cf,p,v) => { LinkConstraintSolverIterations = cf.GetFloat(p, v); },
625 (s) => { return LinkConstraintSolverIterations; }, 614 (s) => { return LinkConstraintSolverIterations; },
626 (s,p,l,v) => { LinkConstraintSolverIterations = v; } ), 615 (s,v) => { LinkConstraintSolverIterations = v; } ),
627 616
628 new ParameterDefn("PhysicsMetricFrames", "Frames between outputting detailed phys metrics. (0 is off)", 617 new ParameterDefn<int>("PhysicsMetricFrames", "Frames between outputting detailed phys metrics. (0 is off)",
629 0f, 618 0,
630 (s,cf,p,v) => { s.PhysicsMetricDumpFrames = cf.GetFloat(p, (int)v); }, 619 (s) => { return s.PhysicsMetricDumpFrames; },
631 (s) => { return (float)s.PhysicsMetricDumpFrames; }, 620 (s,v) => { s.PhysicsMetricDumpFrames = v; } ),
632 (s,p,l,v) => { s.PhysicsMetricDumpFrames = (int)v; } ), 621 new ParameterDefn<float>("ResetBroadphasePool", "Setting this is any value resets the broadphase collision pool",
633 new ParameterDefn("ResetBroadphasePool", "Setting this is any value resets the broadphase collision pool",
634 0f, 622 0f,
635 (s,cf,p,v) => { ; },
636 (s) => { return 0f; }, 623 (s) => { return 0f; },
637 (s,p,l,v) => { BSParam.ResetBroadphasePoolTainted(s, v); } ), 624 (s,v) => { BSParam.ResetBroadphasePoolTainted(s, v); } ),
638 new ParameterDefn("ResetConstraintSolver", "Setting this is any value resets the constraint solver", 625 new ParameterDefn<float>("ResetConstraintSolver", "Setting this is any value resets the constraint solver",
639 0f, 626 0f,
640 (s,cf,p,v) => { ; },
641 (s) => { return 0f; }, 627 (s) => { return 0f; },
642 (s,p,l,v) => { BSParam.ResetConstraintSolverTainted(s, v); } ), 628 (s,v) => { BSParam.ResetConstraintSolverTainted(s, v); } ),
643 }; 629 };
644 630
645 // Convert a boolean to our numeric true and false values 631 // Convert a boolean to our numeric true and false values
@@ -658,13 +644,13 @@ public static class BSParam
658 // ParameterDefn structure. 644 // ParameterDefn structure.
659 // Case does not matter as names are compared after converting to lower case. 645 // Case does not matter as names are compared after converting to lower case.
660 // Returns 'false' if the parameter is not found. 646 // Returns 'false' if the parameter is not found.
661 internal static bool TryGetParameter(string paramName, out ParameterDefn defn) 647 internal static bool TryGetParameter(string paramName, out ParameterDefnBase defn)
662 { 648 {
663 bool ret = false; 649 bool ret = false;
664 ParameterDefn foundDefn = new ParameterDefn(); 650 ParameterDefnBase foundDefn = null;
665 string pName = paramName.ToLower(); 651 string pName = paramName.ToLower();
666 652
667 foreach (ParameterDefn parm in ParameterDefinitions) 653 foreach (ParameterDefnBase parm in ParameterDefinitions)
668 { 654 {
669 if (pName == parm.name.ToLower()) 655 if (pName == parm.name.ToLower())
670 { 656 {
@@ -680,18 +666,18 @@ public static class BSParam
680 // Pass through the settable parameters and set the default values 666 // Pass through the settable parameters and set the default values
681 internal static void SetParameterDefaultValues(BSScene physicsScene) 667 internal static void SetParameterDefaultValues(BSScene physicsScene)
682 { 668 {
683 foreach (ParameterDefn parm in ParameterDefinitions) 669 foreach (ParameterDefnBase parm in ParameterDefinitions)
684 { 670 {
685 parm.setter(physicsScene, parm.name, PhysParameterEntry.APPLY_TO_NONE, parm.defaultValue); 671 parm.AssignDefault(physicsScene);
686 } 672 }
687 } 673 }
688 674
689 // Get user set values out of the ini file. 675 // Get user set values out of the ini file.
690 internal static void SetParameterConfigurationValues(BSScene physicsScene, IConfig cfg) 676 internal static void SetParameterConfigurationValues(BSScene physicsScene, IConfig cfg)
691 { 677 {
692 foreach (ParameterDefn parm in ParameterDefinitions) 678 foreach (ParameterDefnBase parm in ParameterDefinitions)
693 { 679 {
694 parm.userParam(physicsScene, cfg, parm.name, parm.defaultValue); 680 parm.SetValue(physicsScene, cfg.GetString(parm.name, parm.GetValue(physicsScene)));
695 } 681 }
696 } 682 }
697 683
@@ -706,17 +692,21 @@ public static class BSParam
706 List<PhysParameterEntry> entries = new List<PhysParameterEntry>(); 692 List<PhysParameterEntry> entries = new List<PhysParameterEntry>();
707 for (int ii = 0; ii < ParameterDefinitions.Length; ii++) 693 for (int ii = 0; ii < ParameterDefinitions.Length; ii++)
708 { 694 {
709 ParameterDefn pd = ParameterDefinitions[ii]; 695 ParameterDefnBase pd = ParameterDefinitions[ii];
710 entries.Add(new PhysParameterEntry(pd.name, pd.desc)); 696 entries.Add(new PhysParameterEntry(pd.name, pd.desc));
711 } 697 }
712 698
713 // make the list alphabetical for estetic reasons 699 // make the list alphabetical for ease of finding anything
714 entries.Sort((ppe1, ppe2) => { return ppe1.name.CompareTo(ppe2.name); }); 700 entries.Sort((ppe1, ppe2) => { return ppe1.name.CompareTo(ppe2.name); });
715 701
716 SettableParameters = entries.ToArray(); 702 SettableParameters = entries.ToArray();
717 } 703 }
718 } 704 }
719 705
706 // =====================================================================
707 // =====================================================================
708 // There are parameters that, when set, cause things to happen in the physics engine.
709 // This causes the broadphase collision cache to be cleared.
720 private static void ResetBroadphasePoolTainted(BSScene pPhysScene, float v) 710 private static void ResetBroadphasePoolTainted(BSScene pPhysScene, float v)
721 { 711 {
722 BSScene physScene = pPhysScene; 712 BSScene physScene = pPhysScene;
@@ -726,6 +716,7 @@ public static class BSParam
726 }); 716 });
727 } 717 }
728 718
719 // This causes the constraint solver cache to be cleared and reset.
729 private static void ResetConstraintSolverTainted(BSScene pPhysScene, float v) 720 private static void ResetConstraintSolverTainted(BSScene pPhysScene, float v)
730 { 721 {
731 BSScene physScene = pPhysScene; 722 BSScene physScene = pPhysScene;
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
index 0323b0d..4dff927 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
@@ -70,6 +70,8 @@ public class BSPrim : BSPhysObject
70 private bool _kinematic; 70 private bool _kinematic;
71 private float _buoyancy; 71 private float _buoyancy;
72 72
73 private int CrossingFailures { get; set; }
74
73 public BSDynamics VehicleController { get; private set; } 75 public BSDynamics VehicleController { get; private set; }
74 76
75 private BSVMotor _targetMotor; 77 private BSVMotor _targetMotor;
@@ -197,7 +199,20 @@ public class BSPrim : BSPhysObject
197 { 199 {
198 get { return _isSelected; } 200 get { return _isSelected; }
199 } 201 }
200 public override void CrossingFailure() { return; } 202
203 public override void CrossingFailure()
204 {
205 CrossingFailures++;
206 if (CrossingFailures > BSParam.CrossingFailuresBeforeOutOfBounds)
207 {
208 base.RaiseOutOfBounds(RawPosition);
209 }
210 else if (CrossingFailures == BSParam.CrossingFailuresBeforeOutOfBounds)
211 {
212 m_log.WarnFormat("{0} Too many crossing failures for {1}", LogHeader, Name);
213 }
214 return;
215 }
201 216
202 // link me to the specified parent 217 // link me to the specified parent
203 public override void link(PhysicsActor obj) { 218 public override void link(PhysicsActor obj) {
@@ -239,50 +254,98 @@ public class BSPrim : BSPhysObject
239 }); 254 });
240 } 255 }
241 256
257 bool TryExperimentalLockAxisCode = false;
258 BSConstraint LockAxisConstraint = null;
242 public override void LockAngularMotion(OMV.Vector3 axis) 259 public override void LockAngularMotion(OMV.Vector3 axis)
243 { 260 {
244 DetailLog("{0},BSPrim.LockAngularMotion,call,axis={1}", LocalID, axis); 261 DetailLog("{0},BSPrim.LockAngularMotion,call,axis={1}", LocalID, axis);
245 262
263 // "1" means free, "0" means locked
246 OMV.Vector3 locking = new OMV.Vector3(1f, 1f, 1f); 264 OMV.Vector3 locking = new OMV.Vector3(1f, 1f, 1f);
247 if (axis.X != 1) locking.X = 0f; 265 if (axis.X != 1) locking.X = 0f;
248 if (axis.Y != 1) locking.Y = 0f; 266 if (axis.Y != 1) locking.Y = 0f;
249 if (axis.Z != 1) locking.Z = 0f; 267 if (axis.Z != 1) locking.Z = 0f;
250 LockedAxis = locking; 268 LockedAxis = locking;
251 269
252 /* Not implemented yet 270 if (TryExperimentalLockAxisCode && LockedAxis != LockedAxisFree)
253 if (LockedAxis != LockedAxisFree)
254 { 271 {
255 // Something is locked so start the thingy that keeps that axis from changing 272 // Lock that axis by creating a 6DOF constraint that has one end in the world and
256 RegisterPreUpdatePropertyAction("BSPrim.LockAngularMotion", delegate(ref EntityProperties entprop) 273 // the other in the object.
274 // http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?p=20817
275 // http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?p=26380
276
277 PhysicsScene.TaintedObject("BSPrim.LockAngularMotion", delegate()
257 { 278 {
258 if (LockedAxis != LockedAxisFree) 279 CleanUpLockAxisPhysicals(true /* inTaintTime */);
280
281 BSConstraint6Dof axisConstrainer = new BSConstraint6Dof(PhysicsScene.World, PhysBody,
282 OMV.Vector3.Zero, OMV.Quaternion.Inverse(RawOrientation),
283 true /* useLinearReferenceFrameB */, true /* disableCollisionsBetweenLinkedBodies */);
284 LockAxisConstraint = axisConstrainer;
285 PhysicsScene.Constraints.AddConstraint(LockAxisConstraint);
286
287 // The constraint is tied to the world and oriented to the prim.
288
289 // Free to move linearly
290 OMV.Vector3 linearLow = OMV.Vector3.Zero;
291 OMV.Vector3 linearHigh = PhysicsScene.TerrainManager.DefaultRegionSize;
292 axisConstrainer.SetLinearLimits(linearLow, linearHigh);
293
294 // Angular with some axis locked
295 float f2PI = (float)Math.PI * 2f;
296 OMV.Vector3 angularLow = new OMV.Vector3(-f2PI, -f2PI, -f2PI);
297 OMV.Vector3 angularHigh = new OMV.Vector3(f2PI, f2PI, f2PI);
298 if (LockedAxis.X != 1f)
259 { 299 {
260 if (IsPhysicallyActive) 300 angularLow.X = 0f;
261 { 301 angularHigh.X = 0f;
262 // Bullet can lock axis but it only works for global axis.
263 // Check if this prim is aligned on global axis and use Bullet's
264 // system if so.
265
266 ForceOrientation = entprop.Rotation;
267 ForceRotationalVelocity = entprop.RotationalVelocity;
268 }
269 } 302 }
270 else 303 if (LockedAxis.Y != 1f)
304 {
305 angularLow.Y = 0f;
306 angularHigh.Y = 0f;
307 }
308 if (LockedAxis.Z != 1f)
271 { 309 {
272 UnRegisterPreUpdatePropertyAction("BSPrim.LockAngularMotion"); 310 angularLow.Z = 0f;
311 angularHigh.Z = 0f;
273 } 312 }
313 axisConstrainer.SetAngularLimits(angularLow, angularHigh);
314
315 DetailLog("{0},BSPrim.LockAngularMotion,create,linLow={1},linHi={2},angLow={3},angHi={4}",
316 LocalID, linearLow, linearHigh, angularLow, angularHigh);
274 317
318 // Constants from one of the posts mentioned above and used in Bullet's ConstraintDemo.
319 axisConstrainer.TranslationalLimitMotor(true /* enable */, 5.0f, 0.1f);
320
321 axisConstrainer.RecomputeConstraintVariables(RawMass);
275 }); 322 });
276 } 323 }
277 else 324 else
278 { 325 {
279 // Everything seems unlocked 326 // Everything seems unlocked
280 UnRegisterPreUpdatePropertyAction("BSPrim.LockAngularMotion"); 327 CleanUpLockAxisPhysicals(false /* inTaintTime */);
281 } 328 }
282 */
283 329
284 return; 330 return;
285 } 331 }
332 // Get rid of any constraint built for LockAxis
333 // Most often the constraint is removed when the constraint collection is cleaned for this prim.
334 private void CleanUpLockAxisPhysicals(bool inTaintTime)
335 {
336 if (LockAxisConstraint != null)
337 {
338 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.CleanUpLockAxisPhysicals", delegate()
339 {
340 if (LockAxisConstraint != null)
341 {
342 PhysicsScene.Constraints.RemoveAndDestroyConstraint(LockAxisConstraint);
343 LockAxisConstraint = null;
344 DetailLog("{0},BSPrim.CleanUpLockAxisPhysicals,destroyingConstraint", LocalID);
345 }
346 });
347 }
348 }
286 349
287 public override OMV.Vector3 RawPosition 350 public override OMV.Vector3 RawPosition
288 { 351 {
@@ -762,6 +825,7 @@ public class BSPrim : BSPhysObject
762 SetObjectDynamic(true); 825 SetObjectDynamic(true);
763 // whether phys-to-static or static-to-phys, the object is not moving. 826 // whether phys-to-static or static-to-phys, the object is not moving.
764 ZeroMotion(true); 827 ZeroMotion(true);
828
765 }); 829 });
766 } 830 }
767 } 831 }
@@ -885,6 +949,8 @@ public class BSPrim : BSPhysObject
885 949
886 // For good measure, make sure the transform is set through to the motion state 950 // For good measure, make sure the transform is set through to the motion state
887 ForcePosition = _position; 951 ForcePosition = _position;
952 ForceVelocity = _velocity;
953 ForceRotationalVelocity = _rotationalVelocity;
888 954
889 // A dynamic object has mass 955 // A dynamic object has mass
890 UpdatePhysicalMassProperties(RawMass, false); 956 UpdatePhysicalMassProperties(RawMass, false);
@@ -1064,15 +1130,19 @@ public class BSPrim : BSPhysObject
1064 _buoyancy = value; 1130 _buoyancy = value;
1065 // DetailLog("{0},BSPrim.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy); 1131 // DetailLog("{0},BSPrim.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
1066 // Force the recalculation of the various inertia,etc variables in the object 1132 // Force the recalculation of the various inertia,etc variables in the object
1067 DetailLog("{0},BSPrim.ForceBuoyancy,buoy={1},mass={2}", LocalID, _buoyancy, _mass); 1133 UpdatePhysicalMassProperties(RawMass, true);
1068 UpdatePhysicalMassProperties(_mass, true); 1134 DetailLog("{0},BSPrim.ForceBuoyancy,buoy={1},mass={2},grav={3}", LocalID, _buoyancy, RawMass, Gravity);
1069 ActivateIfPhysical(false); 1135 ActivateIfPhysical(false);
1070 } 1136 }
1071 } 1137 }
1072 1138
1073 // Used for MoveTo 1139 // Used for MoveTo
1074 public override OMV.Vector3 PIDTarget { 1140 public override OMV.Vector3 PIDTarget {
1075 set { _PIDTarget = value; } 1141 set
1142 {
1143 // TODO: add a sanity check -- don't move more than a region or something like that.
1144 _PIDTarget = value;
1145 }
1076 } 1146 }
1077 public override float PIDTau { 1147 public override float PIDTau {
1078 set { _PIDTau = value; } 1148 set { _PIDTau = value; }
@@ -1126,7 +1196,9 @@ public class BSPrim : BSPhysObject
1126 } 1196 }
1127 else 1197 else
1128 { 1198 {
1129 ForcePosition = movePosition; 1199 _position = movePosition;
1200 PositionSanityCheck(true /* intaintTime */);
1201 ForcePosition = _position;
1130 } 1202 }
1131 DetailLog("{0},BSPrim.PIDTarget,move,fromPos={1},movePos={2}", LocalID, origPosition, movePosition); 1203 DetailLog("{0},BSPrim.PIDTarget,move,fromPos={1},movePos={2}", LocalID, origPosition, movePosition);
1132 }); 1204 });
@@ -1303,6 +1375,7 @@ public class BSPrim : BSPhysObject
1303 { 1375 {
1304 if (PhysBody.HasPhysicalBody) 1376 if (PhysBody.HasPhysicalBody)
1305 { 1377 {
1378 DetailLog("{0},BSPrim.AddAngularForce,taint,angForce={1}", LocalID, angForce);
1306 PhysicsScene.PE.ApplyTorque(PhysBody, angForce); 1379 PhysicsScene.PE.ApplyTorque(PhysBody, angForce);
1307 ActivateIfPhysical(false); 1380 ActivateIfPhysical(false);
1308 } 1381 }
@@ -1667,7 +1740,7 @@ public class BSPrim : BSPhysObject
1667 // _velocity = entprop.Velocity; 1740 // _velocity = entprop.Velocity;
1668 // DEBUG DEBUG DEBUG -- smooth velocity changes a bit. The simulator seems to be 1741 // DEBUG DEBUG DEBUG -- smooth velocity changes a bit. The simulator seems to be
1669 // very sensitive to velocity changes. 1742 // very sensitive to velocity changes.
1670 if (!entprop.Velocity.ApproxEquals(_velocity, 0.1f)) 1743 if (entprop.Velocity == OMV.Vector3.Zero || !entprop.Velocity.ApproxEquals(_velocity, 0.1f))
1671 _velocity = entprop.Velocity; 1744 _velocity = entprop.Velocity;
1672 _acceleration = entprop.Acceleration; 1745 _acceleration = entprop.Acceleration;
1673 _rotationalVelocity = entprop.RotationalVelocity; 1746 _rotationalVelocity = entprop.RotationalVelocity;
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
index 05722b8..e6aefd5 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
@@ -161,7 +161,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
161 private int m_physicsLoggingFileMinutes; 161 private int m_physicsLoggingFileMinutes;
162 private bool m_physicsLoggingDoFlush; 162 private bool m_physicsLoggingDoFlush;
163 private bool m_physicsPhysicalDumpEnabled; 163 private bool m_physicsPhysicalDumpEnabled;
164 public float PhysicsMetricDumpFrames { get; set; } 164 public int PhysicsMetricDumpFrames { get; set; }
165 // 'true' of the vehicle code is to log lots of details 165 // 'true' of the vehicle code is to log lots of details
166 public bool VehicleLoggingEnabled { get; private set; } 166 public bool VehicleLoggingEnabled { get; private set; }
167 public bool VehiclePhysicalLoggingEnabled { get; private set; } 167 public bool VehiclePhysicalLoggingEnabled { get; private set; }
@@ -542,7 +542,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
542 collidersCount = 0; 542 collidersCount = 0;
543 } 543 }
544 544
545 if ((m_simulationStep % PhysicsMetricDumpFrames) == 0) 545 if (PhysicsMetricDumpFrames != 0 && ((m_simulationStep % PhysicsMetricDumpFrames) == 0))
546 PE.DumpPhysicsStatistics(World); 546 PE.DumpPhysicsStatistics(World);
547 547
548 // Get a value for 'now' so all the collision and update routines don't have to get their own. 548 // Get a value for 'now' so all the collision and update routines don't have to get their own.
@@ -880,38 +880,14 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
880 { 880 {
881 bool ret = false; 881 bool ret = false;
882 882
883 float valf = 0f; 883 BSParam.ParameterDefnBase theParam;
884 if (val.ToLower() == "true")
885 {
886 valf = PhysParameterEntry.NUMERIC_TRUE;
887 }
888 else
889 {
890 if (val.ToLower() == "false")
891 {
892 valf = PhysParameterEntry.NUMERIC_FALSE;
893 }
894 else
895 {
896 try
897 {
898 valf = float.Parse(val);
899 }
900 catch
901 {
902 valf = 0f;
903 }
904 }
905 }
906
907 BSParam.ParameterDefn theParam;
908 if (BSParam.TryGetParameter(parm, out theParam)) 884 if (BSParam.TryGetParameter(parm, out theParam))
909 { 885 {
910 // Set the value in the C# code 886 // Set the value in the C# code
911 theParam.setter(this, parm, localID, valf); 887 theParam.SetValue(this, val);
912 888
913 // Optionally set the parameter in the unmanaged code 889 // Optionally set the parameter in the unmanaged code
914 if (theParam.onObject != null) 890 if (theParam.HasSetOnObject)
915 { 891 {
916 // update all the localIDs specified 892 // update all the localIDs specified
917 // If the local ID is APPLY_TO_NONE, just change the default value 893 // If the local ID is APPLY_TO_NONE, just change the default value
@@ -923,16 +899,16 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
923 case PhysParameterEntry.APPLY_TO_NONE: 899 case PhysParameterEntry.APPLY_TO_NONE:
924 // This will cause a call into the physical world if some operation is specified (SetOnObject). 900 // This will cause a call into the physical world if some operation is specified (SetOnObject).
925 objectIDs.Add(TERRAIN_ID); 901 objectIDs.Add(TERRAIN_ID);
926 TaintedUpdateParameter(parm, objectIDs, valf); 902 TaintedUpdateParameter(parm, objectIDs, val);
927 break; 903 break;
928 case PhysParameterEntry.APPLY_TO_ALL: 904 case PhysParameterEntry.APPLY_TO_ALL:
929 lock (PhysObjects) objectIDs = new List<uint>(PhysObjects.Keys); 905 lock (PhysObjects) objectIDs = new List<uint>(PhysObjects.Keys);
930 TaintedUpdateParameter(parm, objectIDs, valf); 906 TaintedUpdateParameter(parm, objectIDs, val);
931 break; 907 break;
932 default: 908 default:
933 // setting only one localID 909 // setting only one localID
934 objectIDs.Add(localID); 910 objectIDs.Add(localID);
935 TaintedUpdateParameter(parm, objectIDs, valf); 911 TaintedUpdateParameter(parm, objectIDs, val);
936 break; 912 break;
937 } 913 }
938 } 914 }
@@ -943,22 +919,22 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
943 } 919 }
944 920
945 // schedule the actual updating of the paramter to when the phys engine is not busy 921 // schedule the actual updating of the paramter to when the phys engine is not busy
946 private void TaintedUpdateParameter(string parm, List<uint> lIDs, float val) 922 private void TaintedUpdateParameter(string parm, List<uint> lIDs, string val)
947 { 923 {
948 float xval = val; 924 string xval = val;
949 List<uint> xlIDs = lIDs; 925 List<uint> xlIDs = lIDs;
950 string xparm = parm; 926 string xparm = parm;
951 TaintedObject("BSScene.UpdateParameterSet", delegate() { 927 TaintedObject("BSScene.UpdateParameterSet", delegate() {
952 BSParam.ParameterDefn thisParam; 928 BSParam.ParameterDefnBase thisParam;
953 if (BSParam.TryGetParameter(xparm, out thisParam)) 929 if (BSParam.TryGetParameter(xparm, out thisParam))
954 { 930 {
955 if (thisParam.onObject != null) 931 if (thisParam.HasSetOnObject)
956 { 932 {
957 foreach (uint lID in xlIDs) 933 foreach (uint lID in xlIDs)
958 { 934 {
959 BSPhysObject theObject = null; 935 BSPhysObject theObject = null;
960 if (PhysObjects.TryGetValue(lID, out theObject)) 936 if (PhysObjects.TryGetValue(lID, out theObject))
961 thisParam.onObject(this, theObject, xval); 937 thisParam.SetOnObject(this, theObject);
962 } 938 }
963 } 939 }
964 } 940 }
@@ -971,10 +947,10 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
971 { 947 {
972 string val = String.Empty; 948 string val = String.Empty;
973 bool ret = false; 949 bool ret = false;
974 BSParam.ParameterDefn theParam; 950 BSParam.ParameterDefnBase theParam;
975 if (BSParam.TryGetParameter(parm, out theParam)) 951 if (BSParam.TryGetParameter(parm, out theParam))
976 { 952 {
977 val = theParam.getter(this).ToString(); 953 val = theParam.GetValue(this);
978 ret = true; 954 ret = true;
979 } 955 }
980 value = val; 956 value = val;
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
index 096b300..2e54a93 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
@@ -568,7 +568,7 @@ public sealed class BSShapeCollection : IDisposable
568 { 568 {
569 569
570 newShape = PhysicsScene.PE.BuildCapsuleShape(PhysicsScene.World, 1f, 1f, prim.Scale); 570 newShape = PhysicsScene.PE.BuildCapsuleShape(PhysicsScene.World, 1f, 1f, prim.Scale);
571 if (DDetail) DetailLog("{0},BSShapeCollection.BuiletPhysicalNativeShape,capsule,scale={1}", prim.LocalID, prim.Scale); 571 if (DDetail) DetailLog("{0},BSShapeCollection.BuildPhysicalNativeShape,capsule,scale={1}", prim.LocalID, prim.Scale);
572 } 572 }
573 else 573 else
574 { 574 {
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt b/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt
index bda7c47..49718c4 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt
+++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt
@@ -1,17 +1,16 @@
1CURRENT PRIORITIES 1CURRENT PRIORITIES
2================================================= 2=================================================
3One sided meshes? Should terrain be built into a closed shape?
4 When meshes get partially wedged into the terrain, they cannot push themselves out.
5 It is possible that Bullet processes collisions whether entering or leaving a mesh.
6 Ref: http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4869
7Deleting a linkset while standing on the root will leave the physical shape of the root behind. 3Deleting a linkset while standing on the root will leave the physical shape of the root behind.
8 Not sure if it is because standing on it. Done with large prim linksets. 4 Not sure if it is because standing on it. Done with large prim linksets.
9Terrain detail: double terrain mesh detail
10Vehicle angular vertical attraction 5Vehicle angular vertical attraction
11vehicle angular banking 6vehicle angular banking
12Center-of-gravity 7Center-of-gravity
13Vehicle angular deflection 8Vehicle angular deflection
14 Preferred orientation angular correction fix 9 Preferred orientation angular correction fix
10Enable vehicle border crossings (at least as poorly as ODE)
11 Terrain skirts
12 Avatar created in previous region and not new region when crossing border
13 Vehicle recreated in new sim at small Z value (offset from root value?) (DONE)
15when should angular and linear motor targets be zeroed? when selected? 14when should angular and linear motor targets be zeroed? when selected?
16 Need a vehicle.clear()? Or an 'else' in prestep if not physical. 15 Need a vehicle.clear()? Or an 'else' in prestep if not physical.
17Teravus llMoveToTarget script debug 16Teravus llMoveToTarget script debug
@@ -26,14 +25,16 @@ Avatar movement
26 flying into a wall doesn't stop avatar who keeps appearing to move through the obstacle (DONE) 25 flying into a wall doesn't stop avatar who keeps appearing to move through the obstacle (DONE)
27 walking up stairs is not calibrated correctly (stairs out of Kepler cabin) 26 walking up stairs is not calibrated correctly (stairs out of Kepler cabin)
28 avatar capsule rotation completed (NOT DONE - Bullet's capsule shape is not the solution) 27 avatar capsule rotation completed (NOT DONE - Bullet's capsule shape is not the solution)
29Enable vehicle border crossings (at least as poorly as ODE)
30 Terrain skirts
31 Avatar created in previous region and not new region when crossing border
32 Vehicle recreated in new sim at small Z value (offset from root value?) (DONE)
33Vehicle script tuning/debugging 28Vehicle script tuning/debugging
34 Avanti speed script 29 Avanti speed script
35 Weapon shooter script 30 Weapon shooter script
36Add material densities to the material types 31Move material definitions (friction, ...) into simulator.
32Add material densities to the material types.
33Terrain detail: double terrain mesh detail
34One sided meshes? Should terrain be built into a closed shape?
35 When meshes get partially wedged into the terrain, they cannot push themselves out.
36 It is possible that Bullet processes collisions whether entering or leaving a mesh.
37 Ref: http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4869
37 38
38VEHICLES TODO LIST: 39VEHICLES TODO LIST:
39================================================= 40=================================================
@@ -65,6 +66,7 @@ Vehicle attributes are not restored when a vehicle is rezzed on region creation
65 66
66GENERAL TODO LIST: 67GENERAL TODO LIST:
67================================================= 68=================================================
69Add a sanity check for PIDTarget location.
68Level-of-detail for mesh creation. Prims with circular interiors require lod of 32. 70Level-of-detail for mesh creation. Prims with circular interiors require lod of 32.
69 Is much saved with lower LODs? At the moment, all set to 32. 71 Is much saved with lower LODs? At the moment, all set to 32.
70Collisions are inconsistant: arrows are supposed to hit and report collision. Often don't. 72Collisions are inconsistant: arrows are supposed to hit and report collision. Often don't.
diff --git a/OpenSim/Region/Physics/BulletSPlugin/Properties/AssemblyInfo.cs b/OpenSim/Region/Physics/BulletSPlugin/Properties/AssemblyInfo.cs
index d240c71..02b03a8 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/Properties/AssemblyInfo.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/Properties/AssemblyInfo.cs
@@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33
diff --git a/OpenSim/Region/Physics/ConvexDecompositionDotNet/Properties/AssemblyInfo.cs b/OpenSim/Region/Physics/ConvexDecompositionDotNet/Properties/AssemblyInfo.cs
index cafd7f4..f611b9a 100644
--- a/OpenSim/Region/Physics/ConvexDecompositionDotNet/Properties/AssemblyInfo.cs
+++ b/OpenSim/Region/Physics/ConvexDecompositionDotNet/Properties/AssemblyInfo.cs
@@ -33,4 +33,4 @@ using System.Runtime.InteropServices;
33// by using the '*' as shown below: 33// by using the '*' as shown below:
34// [assembly: AssemblyVersion("1.0.*")] 34// [assembly: AssemblyVersion("1.0.*")]
35[assembly: AssemblyVersion("0.7.6.*")] 35[assembly: AssemblyVersion("0.7.6.*")]
36[assembly: AssemblyFileVersion("1.0.0.0")] 36
diff --git a/OpenSim/Region/Physics/Meshing/Properties/AssemblyInfo.cs b/OpenSim/Region/Physics/Meshing/Properties/AssemblyInfo.cs
index bd70296..3de061a 100644
--- a/OpenSim/Region/Physics/Meshing/Properties/AssemblyInfo.cs
+++ b/OpenSim/Region/Physics/Meshing/Properties/AssemblyInfo.cs
@@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33
diff --git a/OpenSim/Region/RegionCombinerModule/Properties/AssemblyInfo.cs b/OpenSim/Region/RegionCombinerModule/Properties/AssemblyInfo.cs
index ca945b5..86a3101 100644
--- a/OpenSim/Region/RegionCombinerModule/Properties/AssemblyInfo.cs
+++ b/OpenSim/Region/RegionCombinerModule/Properties/AssemblyInfo.cs
@@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
index 6ff6b00..d64e6d7 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
@@ -2172,9 +2172,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2172 CheckThreatLevel(ThreatLevel.Moderate, "osGetGridHomeURI"); 2172 CheckThreatLevel(ThreatLevel.Moderate, "osGetGridHomeURI");
2173 m_host.AddScriptLPS(1); 2173 m_host.AddScriptLPS(1);
2174 2174
2175 string HomeURI = String.Empty;
2176 IConfigSource config = m_ScriptEngine.ConfigSource; 2175 IConfigSource config = m_ScriptEngine.ConfigSource;
2176 string HomeURI = Util.GetConfigVarWithDefaultSection(config, "HomeURI", string.Empty);
2177 2177
2178 if (!string.IsNullOrEmpty(HomeURI))
2179 return HomeURI;
2180
2181 // Legacy. Remove soon!
2178 if (config.Configs["LoginService"] != null) 2182 if (config.Configs["LoginService"] != null)
2179 HomeURI = config.Configs["LoginService"].GetString("SRV_HomeURI", HomeURI); 2183 HomeURI = config.Configs["LoginService"].GetString("SRV_HomeURI", HomeURI);
2180 2184
@@ -2189,9 +2193,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2189 CheckThreatLevel(ThreatLevel.Moderate, "osGetGridGatekeeperURI"); 2193 CheckThreatLevel(ThreatLevel.Moderate, "osGetGridGatekeeperURI");
2190 m_host.AddScriptLPS(1); 2194 m_host.AddScriptLPS(1);
2191 2195
2192 string gatekeeperURI = String.Empty;
2193 IConfigSource config = m_ScriptEngine.ConfigSource; 2196 IConfigSource config = m_ScriptEngine.ConfigSource;
2197 string gatekeeperURI = Util.GetConfigVarWithDefaultSection(config, "GatekeeperURI", string.Empty);
2198
2199 if (!string.IsNullOrEmpty(gatekeeperURI))
2200 return gatekeeperURI;
2194 2201
2202 // Legacy. Remove soon!
2195 if (config.Configs["GridService"] != null) 2203 if (config.Configs["GridService"] != null)
2196 gatekeeperURI = config.Configs["GridService"].GetString("Gatekeeper", gatekeeperURI); 2204 gatekeeperURI = config.Configs["GridService"].GetString("Gatekeeper", gatekeeperURI);
2197 2205
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Properties/AssemblyInfo.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Properties/AssemblyInfo.cs
index 3c01eec..6d218a6 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Properties/AssemblyInfo.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Properties/AssemblyInfo.cs
@@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33
diff --git a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Properties/AssemblyInfo.cs b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Properties/AssemblyInfo.cs
index fd37753..5b5c4fd 100644
--- a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Properties/AssemblyInfo.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Properties/AssemblyInfo.cs
@@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33
diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/Properties/AssemblyInfo.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/Properties/AssemblyInfo.cs
index 74747a2..48964b6 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Instance/Properties/AssemblyInfo.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Instance/Properties/AssemblyInfo.cs
@@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33
diff --git a/OpenSim/Region/ScriptEngine/XEngine/Properties/AssemblyInfo.cs b/OpenSim/Region/ScriptEngine/XEngine/Properties/AssemblyInfo.cs
index a887171..f0640da 100644
--- a/OpenSim/Region/ScriptEngine/XEngine/Properties/AssemblyInfo.cs
+++ b/OpenSim/Region/ScriptEngine/XEngine/Properties/AssemblyInfo.cs
@@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33
diff --git a/OpenSim/Region/UserStatistics/Properties/AssemblyInfo.cs b/OpenSim/Region/UserStatistics/Properties/AssemblyInfo.cs
index caa6d4e..1fff12a 100644
--- a/OpenSim/Region/UserStatistics/Properties/AssemblyInfo.cs
+++ b/OpenSim/Region/UserStatistics/Properties/AssemblyInfo.cs
@@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33
diff --git a/OpenSim/Server/Base/Properties/AssemblyInfo.cs b/OpenSim/Server/Base/Properties/AssemblyInfo.cs
index 8b45564..b4732b8 100644
--- a/OpenSim/Server/Base/Properties/AssemblyInfo.cs
+++ b/OpenSim/Server/Base/Properties/AssemblyInfo.cs
@@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33
diff --git a/OpenSim/Server/Handlers/Grid/GridInfoHandlers.cs b/OpenSim/Server/Handlers/Grid/GridInfoHandlers.cs
index 965a54e..35f86c5 100644
--- a/OpenSim/Server/Handlers/Grid/GridInfoHandlers.cs
+++ b/OpenSim/Server/Handlers/Grid/GridInfoHandlers.cs
@@ -170,14 +170,6 @@ namespace OpenSim.Server.Handlers.Grid
170 public string JsonGetGridInfoMethod(string request, string path, string param, 170 public string JsonGetGridInfoMethod(string request, string path, string param,
171 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 171 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
172 { 172 {
173 string HomeURI = String.Empty;
174 IConfig cfg = m_Config.Configs["LoginService"];
175
176 if (null != cfg)
177 {
178 HomeURI = cfg.GetString("SRV_HomeURI", HomeURI);
179 }
180
181 OSDMap map = new OSDMap(); 173 OSDMap map = new OSDMap();
182 174
183 foreach (string k in _info.Keys) 175 foreach (string k in _info.Keys)
@@ -185,9 +177,19 @@ namespace OpenSim.Server.Handlers.Grid
185 map[k] = OSD.FromString(_info[k].ToString()); 177 map[k] = OSD.FromString(_info[k].ToString());
186 } 178 }
187 179
180 string HomeURI = Util.GetConfigVarWithDefaultSection(m_Config, "HomeURI", string.Empty);
181
188 if (!String.IsNullOrEmpty(HomeURI)) 182 if (!String.IsNullOrEmpty(HomeURI))
183 map["home"] = OSD.FromString(HomeURI);
184 else // Legacy. Remove soon!
189 { 185 {
190 map["home"] = OSD.FromString(HomeURI); 186 IConfig cfg = m_Config.Configs["LoginService"];
187
188 if (null != cfg)
189 HomeURI = cfg.GetString("SRV_HomeURI", HomeURI);
190
191 if (!String.IsNullOrEmpty(HomeURI))
192 map["home"] = OSD.FromString(HomeURI);
191 } 193 }
192 194
193 return OSDParser.SerializeJsonString(map).ToString(); 195 return OSDParser.SerializeJsonString(map).ToString();
diff --git a/OpenSim/Server/Handlers/Properties/AssemblyInfo.cs b/OpenSim/Server/Handlers/Properties/AssemblyInfo.cs
index d72d36a..3295ffd 100644
--- a/OpenSim/Server/Handlers/Properties/AssemblyInfo.cs
+++ b/OpenSim/Server/Handlers/Properties/AssemblyInfo.cs
@@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33
diff --git a/OpenSim/Services/AssetService/Properties/AssemblyInfo.cs b/OpenSim/Services/AssetService/Properties/AssemblyInfo.cs
index b57052c..50ee033 100644
--- a/OpenSim/Services/AssetService/Properties/AssemblyInfo.cs
+++ b/OpenSim/Services/AssetService/Properties/AssemblyInfo.cs
@@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33
diff --git a/OpenSim/Services/AuthenticationService/Properties/AssemblyInfo.cs b/OpenSim/Services/AuthenticationService/Properties/AssemblyInfo.cs
index 99c46ec..435852da 100644
--- a/OpenSim/Services/AuthenticationService/Properties/AssemblyInfo.cs
+++ b/OpenSim/Services/AuthenticationService/Properties/AssemblyInfo.cs
@@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33
diff --git a/OpenSim/Services/AuthorizationService/Properties/AssemblyInfo.cs b/OpenSim/Services/AuthorizationService/Properties/AssemblyInfo.cs
index 33e48d3..8db1671 100644
--- a/OpenSim/Services/AuthorizationService/Properties/AssemblyInfo.cs
+++ b/OpenSim/Services/AuthorizationService/Properties/AssemblyInfo.cs
@@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33
diff --git a/OpenSim/Services/AvatarService/Properties/AssemblyInfo.cs b/OpenSim/Services/AvatarService/Properties/AssemblyInfo.cs
index 8b0214a..138d4cd 100644
--- a/OpenSim/Services/AvatarService/Properties/AssemblyInfo.cs
+++ b/OpenSim/Services/AvatarService/Properties/AssemblyInfo.cs
@@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33
diff --git a/OpenSim/Services/Base/Properties/AssemblyInfo.cs b/OpenSim/Services/Base/Properties/AssemblyInfo.cs
index 2825a88..84a40f0 100644
--- a/OpenSim/Services/Base/Properties/AssemblyInfo.cs
+++ b/OpenSim/Services/Base/Properties/AssemblyInfo.cs
@@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33
diff --git a/OpenSim/Services/Connectors/Properties/AssemblyInfo.cs b/OpenSim/Services/Connectors/Properties/AssemblyInfo.cs
index 73fc72c..8b18afb 100644
--- a/OpenSim/Services/Connectors/Properties/AssemblyInfo.cs
+++ b/OpenSim/Services/Connectors/Properties/AssemblyInfo.cs
@@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33
diff --git a/OpenSim/Services/FreeswitchService/Properties/AssemblyInfo.cs b/OpenSim/Services/FreeswitchService/Properties/AssemblyInfo.cs
index fdd4b69..b488b36 100644
--- a/OpenSim/Services/FreeswitchService/Properties/AssemblyInfo.cs
+++ b/OpenSim/Services/FreeswitchService/Properties/AssemblyInfo.cs
@@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33
diff --git a/OpenSim/Services/Friends/Properties/AssemblyInfo.cs b/OpenSim/Services/Friends/Properties/AssemblyInfo.cs
index cb624f0..b11d07d 100644
--- a/OpenSim/Services/Friends/Properties/AssemblyInfo.cs
+++ b/OpenSim/Services/Friends/Properties/AssemblyInfo.cs
@@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33
diff --git a/OpenSim/Services/GridService/HypergridLinker.cs b/OpenSim/Services/GridService/HypergridLinker.cs
index 073197f..3e7c556 100644
--- a/OpenSim/Services/GridService/HypergridLinker.cs
+++ b/OpenSim/Services/GridService/HypergridLinker.cs
@@ -128,7 +128,9 @@ namespace OpenSim.Services.GridService
128 128
129 m_MapTileDirectory = gridConfig.GetString("MapTileDirectory", "maptiles"); 129 m_MapTileDirectory = gridConfig.GetString("MapTileDirectory", "maptiles");
130 130
131 m_ThisGatekeeper = gridConfig.GetString("Gatekeeper", string.Empty); 131 m_ThisGatekeeper = Util.GetConfigVarWithDefaultSection(config, "GatekeeperURI", "GridService");
132 // Legacy. Remove soon!
133 m_ThisGatekeeper = gridConfig.GetString("Gatekeeper", m_ThisGatekeeper);
132 try 134 try
133 { 135 {
134 m_ThisGatekeeperURI = new Uri(m_ThisGatekeeper); 136 m_ThisGatekeeperURI = new Uri(m_ThisGatekeeper);
diff --git a/OpenSim/Services/GridService/Properties/AssemblyInfo.cs b/OpenSim/Services/GridService/Properties/AssemblyInfo.cs
index 09084d3..b1e5e12 100644
--- a/OpenSim/Services/GridService/Properties/AssemblyInfo.cs
+++ b/OpenSim/Services/GridService/Properties/AssemblyInfo.cs
@@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33
diff --git a/OpenSim/Services/HypergridService/GatekeeperService.cs b/OpenSim/Services/HypergridService/GatekeeperService.cs
index 7b84d55..21f363c 100644
--- a/OpenSim/Services/HypergridService/GatekeeperService.cs
+++ b/OpenSim/Services/HypergridService/GatekeeperService.cs
@@ -96,7 +96,8 @@ namespace OpenSim.Services.HypergridService
96 UUID.TryParse(scope, out m_ScopeID); 96 UUID.TryParse(scope, out m_ScopeID);
97 //m_WelcomeMessage = serverConfig.GetString("WelcomeMessage", "Welcome to OpenSim!"); 97 //m_WelcomeMessage = serverConfig.GetString("WelcomeMessage", "Welcome to OpenSim!");
98 m_AllowTeleportsToAnyRegion = serverConfig.GetBoolean("AllowTeleportsToAnyRegion", true); 98 m_AllowTeleportsToAnyRegion = serverConfig.GetBoolean("AllowTeleportsToAnyRegion", true);
99 m_ExternalName = serverConfig.GetString("ExternalName", string.Empty); 99 m_ExternalName = Util.GetConfigVarWithDefaultSection(config, "GatekeeperURI", "GatekeeperService");
100 m_ExternalName = serverConfig.GetString("ExternalName", m_ExternalName);
100 if (m_ExternalName != string.Empty && !m_ExternalName.EndsWith("/")) 101 if (m_ExternalName != string.Empty && !m_ExternalName.EndsWith("/"))
101 m_ExternalName = m_ExternalName + "/"; 102 m_ExternalName = m_ExternalName + "/";
102 103
diff --git a/OpenSim/Services/HypergridService/HGInventoryService.cs b/OpenSim/Services/HypergridService/HGInventoryService.cs
index 2e9bd40..a9661f4 100644
--- a/OpenSim/Services/HypergridService/HGInventoryService.cs
+++ b/OpenSim/Services/HypergridService/HGInventoryService.cs
@@ -81,10 +81,7 @@ namespace OpenSim.Services.HypergridService
81 if (m_UserAccountService == null) 81 if (m_UserAccountService == null)
82 throw new Exception(String.Format("Unable to create UserAccountService from {0}", userAccountsDll)); 82 throw new Exception(String.Format("Unable to create UserAccountService from {0}", userAccountsDll));
83 83
84 // legacy configuration [obsolete] 84 m_HomeURL = Util.GetConfigVarWithDefaultSection(config, "HomeURI", m_ConfigName);
85 m_HomeURL = invConfig.GetString("ProfileServerURI", string.Empty);
86 // Preferred
87 m_HomeURL = invConfig.GetString("HomeURI", m_HomeURL);
88 85
89 m_Cache = UserAccountCache.CreateUserAccountCache(m_UserAccountService); 86 m_Cache = UserAccountCache.CreateUserAccountCache(m_UserAccountService);
90 } 87 }
diff --git a/OpenSim/Services/HypergridService/HGSuitcaseInventoryService.cs b/OpenSim/Services/HypergridService/HGSuitcaseInventoryService.cs
index 784f136..dd546b8 100644
--- a/OpenSim/Services/HypergridService/HGSuitcaseInventoryService.cs
+++ b/OpenSim/Services/HypergridService/HGSuitcaseInventoryService.cs
@@ -96,8 +96,7 @@ namespace OpenSim.Services.HypergridService
96 if (m_AvatarService == null) 96 if (m_AvatarService == null)
97 throw new Exception(String.Format("Unable to create m_AvatarService from {0}", avatarDll)); 97 throw new Exception(String.Format("Unable to create m_AvatarService from {0}", avatarDll));
98 98
99 // Preferred 99 m_HomeURL = Util.GetConfigVarWithDefaultSection(config, "HomeURI", m_ConfigName);
100 m_HomeURL = invConfig.GetString("HomeURI", m_HomeURL);
101 100
102// m_Cache = UserAccountCache.CreateUserAccountCache(m_UserAccountService); 101// m_Cache = UserAccountCache.CreateUserAccountCache(m_UserAccountService);
103 } 102 }
diff --git a/OpenSim/Services/HypergridService/Properties/AssemblyInfo.cs b/OpenSim/Services/HypergridService/Properties/AssemblyInfo.cs
index fe1889d..8d66f1b 100644
--- a/OpenSim/Services/HypergridService/Properties/AssemblyInfo.cs
+++ b/OpenSim/Services/HypergridService/Properties/AssemblyInfo.cs
@@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33
diff --git a/OpenSim/Services/HypergridService/UserAgentService.cs b/OpenSim/Services/HypergridService/UserAgentService.cs
index 416ad16..c810b35 100644
--- a/OpenSim/Services/HypergridService/UserAgentService.cs
+++ b/OpenSim/Services/HypergridService/UserAgentService.cs
@@ -131,12 +131,17 @@ namespace OpenSim.Services.HypergridService
131 LoadDomainExceptionsFromConfig(serverConfig, "AllowExcept", m_TripsAllowedExceptions); 131 LoadDomainExceptionsFromConfig(serverConfig, "AllowExcept", m_TripsAllowedExceptions);
132 LoadDomainExceptionsFromConfig(serverConfig, "DisallowExcept", m_TripsDisallowedExceptions); 132 LoadDomainExceptionsFromConfig(serverConfig, "DisallowExcept", m_TripsDisallowedExceptions);
133 133
134 m_GridName = serverConfig.GetString("ExternalName", string.Empty); 134 m_GridName = Util.GetConfigVarWithDefaultSection(config, "GatekeeperURI", "UserAgentService");
135 if (m_GridName == string.Empty) 135 if (string.IsNullOrEmpty(m_GridName)) // Legacy. Remove soon.
136 { 136 {
137 serverConfig = config.Configs["GatekeeperService"];
138 m_GridName = serverConfig.GetString("ExternalName", string.Empty); 137 m_GridName = serverConfig.GetString("ExternalName", string.Empty);
138 if (m_GridName == string.Empty)
139 {
140 serverConfig = config.Configs["GatekeeperService"];
141 m_GridName = serverConfig.GetString("ExternalName", string.Empty);
142 }
139 } 143 }
144
140 if (!m_GridName.EndsWith("/")) 145 if (!m_GridName.EndsWith("/"))
141 m_GridName = m_GridName + "/"; 146 m_GridName = m_GridName + "/";
142 147
diff --git a/OpenSim/Services/Interfaces/Properties/AssemblyInfo.cs b/OpenSim/Services/Interfaces/Properties/AssemblyInfo.cs
index 669e0b8..47ece75 100644
--- a/OpenSim/Services/Interfaces/Properties/AssemblyInfo.cs
+++ b/OpenSim/Services/Interfaces/Properties/AssemblyInfo.cs
@@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33
diff --git a/OpenSim/Services/InventoryService/Properties/AssemblyInfo.cs b/OpenSim/Services/InventoryService/Properties/AssemblyInfo.cs
index 0870065..bfae81f 100644
--- a/OpenSim/Services/InventoryService/Properties/AssemblyInfo.cs
+++ b/OpenSim/Services/InventoryService/Properties/AssemblyInfo.cs
@@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33
diff --git a/OpenSim/Services/LLLoginService/LLLoginService.cs b/OpenSim/Services/LLLoginService/LLLoginService.cs
index cbb6e6c..88e9eef 100644
--- a/OpenSim/Services/LLLoginService/LLLoginService.cs
+++ b/OpenSim/Services/LLLoginService/LLLoginService.cs
@@ -110,7 +110,7 @@ namespace OpenSim.Services.LLLoginService
110 m_RequireInventory = m_LoginServerConfig.GetBoolean("RequireInventory", true); 110 m_RequireInventory = m_LoginServerConfig.GetBoolean("RequireInventory", true);
111 m_AllowRemoteSetLoginLevel = m_LoginServerConfig.GetBoolean("AllowRemoteSetLoginLevel", false); 111 m_AllowRemoteSetLoginLevel = m_LoginServerConfig.GetBoolean("AllowRemoteSetLoginLevel", false);
112 m_MinLoginLevel = m_LoginServerConfig.GetInt("MinLoginLevel", 0); 112 m_MinLoginLevel = m_LoginServerConfig.GetInt("MinLoginLevel", 0);
113 m_GatekeeperURL = m_LoginServerConfig.GetString("GatekeeperURI", string.Empty); 113 m_GatekeeperURL = Util.GetConfigVarWithDefaultSection(config, "GatekeeperURI", "LoginService");
114 m_MapTileURL = m_LoginServerConfig.GetString("MapTileURL", string.Empty); 114 m_MapTileURL = m_LoginServerConfig.GetString("MapTileURL", string.Empty);
115 m_ProfileURL = m_LoginServerConfig.GetString("ProfileServerURL", string.Empty); 115 m_ProfileURL = m_LoginServerConfig.GetString("ProfileServerURL", string.Empty);
116 m_OpenIDURL = m_LoginServerConfig.GetString("OpenIDServerURL", String.Empty); 116 m_OpenIDURL = m_LoginServerConfig.GetString("OpenIDServerURL", String.Empty);
@@ -969,14 +969,25 @@ namespace OpenSim.Services.LLLoginService
969 // or fixing critical issues 969 // or fixing critical issues
970 // 970 //
971 if (cmd.Length > 2) 971 if (cmd.Length > 2)
972 Int32.TryParse(cmd[2], out m_MinLoginLevel); 972 {
973 if (Int32.TryParse(cmd[2], out m_MinLoginLevel))
974 MainConsole.Instance.OutputFormat("Set minimum login level to {0}", m_MinLoginLevel);
975 else
976 MainConsole.Instance.OutputFormat("ERROR: {0} is not a valid login level", cmd[2]);
977 }
973 break; 978 break;
974 case "reset": 979
980 case "reset":
975 m_MinLoginLevel = 0; 981 m_MinLoginLevel = 0;
982 MainConsole.Instance.OutputFormat("Reset min login level to {0}", m_MinLoginLevel);
976 break; 983 break;
984
977 case "text": 985 case "text":
978 if (cmd.Length > 2) 986 if (cmd.Length > 2)
987 {
979 m_WelcomeMessage = cmd[2]; 988 m_WelcomeMessage = cmd[2];
989 MainConsole.Instance.OutputFormat("Login welcome message set to '{0}'", m_WelcomeMessage);
990 }
980 break; 991 break;
981 } 992 }
982 } 993 }
diff --git a/OpenSim/Services/LLLoginService/Properties/AssemblyInfo.cs b/OpenSim/Services/LLLoginService/Properties/AssemblyInfo.cs
index 3ac8af7..0a6daee 100644
--- a/OpenSim/Services/LLLoginService/Properties/AssemblyInfo.cs
+++ b/OpenSim/Services/LLLoginService/Properties/AssemblyInfo.cs
@@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33
diff --git a/OpenSim/Services/MapImageService/Properties/AssemblyInfo.cs b/OpenSim/Services/MapImageService/Properties/AssemblyInfo.cs
index 69adf73..19936e5 100644
--- a/OpenSim/Services/MapImageService/Properties/AssemblyInfo.cs
+++ b/OpenSim/Services/MapImageService/Properties/AssemblyInfo.cs
@@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33
diff --git a/OpenSim/Services/PresenceService/Properties/AssemblyInfo.cs b/OpenSim/Services/PresenceService/Properties/AssemblyInfo.cs
index 040bbe0..5d433df 100644
--- a/OpenSim/Services/PresenceService/Properties/AssemblyInfo.cs
+++ b/OpenSim/Services/PresenceService/Properties/AssemblyInfo.cs
@@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33
diff --git a/OpenSim/Services/UserAccountService/Properties/AssemblyInfo.cs b/OpenSim/Services/UserAccountService/Properties/AssemblyInfo.cs
index 576ccce..e7d2d6f 100644
--- a/OpenSim/Services/UserAccountService/Properties/AssemblyInfo.cs
+++ b/OpenSim/Services/UserAccountService/Properties/AssemblyInfo.cs
@@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33
diff --git a/OpenSim/Tools/Compiler/Properties/AssemblyInfo.cs b/OpenSim/Tools/Compiler/Properties/AssemblyInfo.cs
index b98e2d2..088be45 100644
--- a/OpenSim/Tools/Compiler/Properties/AssemblyInfo.cs
+++ b/OpenSim/Tools/Compiler/Properties/AssemblyInfo.cs
@@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33
diff --git a/OpenSim/Tools/Configger/Properties/AssemblyInfo.cs b/OpenSim/Tools/Configger/Properties/AssemblyInfo.cs
index 89aafa3..0348628 100644
--- a/OpenSim/Tools/Configger/Properties/AssemblyInfo.cs
+++ b/OpenSim/Tools/Configger/Properties/AssemblyInfo.cs
@@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33
diff --git a/OpenSim/Tools/pCampBot/Properties/AssemblyInfo.cs b/OpenSim/Tools/pCampBot/Properties/AssemblyInfo.cs
index c4d278a..78f3603 100644
--- a/OpenSim/Tools/pCampBot/Properties/AssemblyInfo.cs
+++ b/OpenSim/Tools/pCampBot/Properties/AssemblyInfo.cs
@@ -30,4 +30,4 @@ using System.Runtime.InteropServices;
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.7.6.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33
diff --git a/bin/OpenSim.ini.example b/bin/OpenSim.ini.example
index 7e7b231..c8c5ed3 100644
--- a/bin/OpenSim.ini.example
+++ b/bin/OpenSim.ini.example
@@ -342,6 +342,21 @@
342 ;; - "Imprudence 1.3.1" has access 342 ;; - "Imprudence 1.3.1" has access
343 ; BannedViewerList = 343 ; BannedViewerList =
344 344
345 ;# {HomeURI} {Hypergrid} {The Home URL of this world} {}
346 ;; If this is a standalone world, this is the address of this instance.
347 ;; If this is a grided simulator, this is the address of the external robust server that
348 ;; runs the UserAgentsService.
349 ;; For example http://myworld.com:9000 or http://myworld.com:8002
350 ;; This is a default that can be overwritten in some sections.
351 ; HomeURI = "http://127.0.0.1:9000"
352
353 ;# {GatekeeperURI} {Hypergrid} {The URL of the gatekeeper of this world} {}
354 ;; If this is a standalone world, this is the address of this instance.
355 ;; If this is a grided simulator, this is the address of the external robust server
356 ;; that runs the Gatekeeper service.
357 ;; For example http://myworld.com:9000 or http://myworld.com:8002
358 ;; This is a default that can be overwritten in some sections.
359 ; GatekeeperURI = "http://127.0.0.1:9000"
345 360
346[Estates] 361[Estates]
347 ; If these values are commented out then the user will be asked for estate details when required (this is the normal case). 362 ; If these values are commented out then the user will be asked for estate details when required (this is the normal case).
@@ -527,14 +542,20 @@
527 542
528 543
529[Messaging] 544[Messaging]
530 ;# {OfflineMessageModule} {} {Module to use for offline message storage} {OfflineMessageModule *} 545 ;# {OfflineMessageModule} {} {Module to use for offline message storage} {OfflineMessageModule "Offline Message Module V2" *}
531 ;; Module to handle offline messaging. The core module requires an external 546 ;; Module to handle offline messaging. The core module requires an external
532 ;; web service to do this. See OpenSim wiki. 547 ;; web service to do this. See OpenSim wiki.
533 ; OfflineMessageModule = OfflineMessageModule 548 ; OfflineMessageModule = OfflineMessageModule
549 ;; Or, alternatively, use this one, which works for both standalones and grids
550 ; OfflineMessageModule = "Offline Message Module V2"
534 551
535 ;# {OfflineMessageURL} {OfflineMessageModule:OfflineMessageModule} {URL of offline messaging service} {} 552 ;# {OfflineMessageURL} {OfflineMessageModule:OfflineMessageModule Offline Message Module V2:Offline Message Module V2} {URL of offline messaging service} {}
536 ;; URL of web service for offline message storage 553 ;; URL of web service for offline message storage. Leave it commented if your service is local to the sim.
537 ; OfflineMessageURL = http://yourserver/Offline.php 554 ; OfflineMessageURL = http://yourserver/Offline.php or http://yourrobustserver:8003
555
556 ;# {StorageProvider} {Offline Message Module V2:Offline Message Module V2} {DLL that provides the storage interface} {OpenSim.Data.MySQL.dll}
557 ;; For standalones, this is the storage dll.
558 ; StorageProvider = OpenSim.Data.MySQL.dll
538 559
539 ;# {MuteListModule} {OfflineMessageModule:OfflineMessageModule} {} {} MuteListModule 560 ;# {MuteListModule} {OfflineMessageModule:OfflineMessageModule} {} {} MuteListModule
540 ;; Mute list handler (not yet implemented). MUST BE SET to allow offline 561 ;; Mute list handler (not yet implemented). MUST BE SET to allow offline
@@ -921,33 +942,48 @@
921 ;; Enables the groups module 942 ;; Enables the groups module
922 ; Enabled = false 943 ; Enabled = false
923 944
924 ;# {Module} {Enabled:true} {Groups module to use? (Use GroupsModule to use Flotsam/Simian)} {} Default 945 ;# {Module} {Enabled:true} {Groups module to use? (Use GroupsModule to use Flotsam/Simian)} {Default "Groups Module V2"} Default
925 ;; This is the current groups stub in Region.CoreModules.Avatar.Groups. 946 ;; The default module can use a PHP XmlRpc server from the Flotsam project at
926 ;; All the other settings below only really apply to the Flotsam/SimianGrid
927 ;; GroupsModule.
928 ;; This module can use a PHP XmlRpc server from the Flotsam project at
929 ;; http://code.google.com/p/flotsam/ 947 ;; http://code.google.com/p/flotsam/
930 ;; or from the SimianGrid project at http://code.google.com/p/openmetaverse 948 ;; or from the SimianGrid project at http://code.google.com/p/openmetaverse
931 ; Module = Default 949 ; Module = Default
950 ;; or... use Groups Module V2, which works for standalones and robust grids
951 ; Module = "Groups Module V2"
932 952
933 ;# {MessagingEnabled} {Module:GroupsModule} {Is groups messaging enabled?} {true false} true 953 ;# {StorageProvider} {Module:Groups Module V2} {The DLL that provides the storage for V2} {OpenSim.Data.MySQL.dll}
934 ; MessagingEnabled = true 954 ; StorageProvider = OpenSim.Data.MySQL.dll
935 955
936 ;# {MessagingModule} {MessagingEnabled:true} {Module to use for groups messaging} {GroupsMessagingModule} GroupsMessagingModule 956 ;# {ServicesConnectorModule} {Module:GroupsModule Module:Groups Module V2} {Service connector to use for groups} {XmlRpcGroupsServicesConnector SimianGroupsServicesConnector "Groups Local Service Connector" "Groups Remote Service Connector" "Groups HG Service Connector"} XmlRpcGroupsServicesConnector
937 ; MessagingModule = GroupsMessagingModule
938
939 ;# {ServicesConnectorModule} {Module:GroupsModule} {Service connector to use for groups} {XmlRpcGroupsServicesConnector SimianGroupsServicesConnector} XmlRpcGroupsServicesConnector
940 ;; Service connectors to the Groups Service as used in the GroupsModule. Select one depending on 957 ;; Service connectors to the Groups Service as used in the GroupsModule. Select one depending on
941 ;; whether you're using a Flotsam XmlRpc backend or a SimianGrid backend 958 ;; whether you're using a Flotsam XmlRpc backend or a SimianGrid backend or several flavours of V2, Hypergrided or not, standalone or grided.
942 ; ServicesConnectorModule = XmlRpcGroupsServicesConnector 959 ; ServicesConnectorModule = XmlRpcGroupsServicesConnector
943 960
944 ;# {GroupsServerURI} {Module:GroupsModule} {Groups Server URI} {} 961 ;# {LocalService} {ServicesConnectorModule:Groups HG Service Connector} {Is the group service in this process or elsewhere?} {local remote} local
945 ;; URI for the groups services 962 ;; Used for V2 in HG only. If standalone, set this to local; if grided sim, set this to remote
963 ; LocalService = local
964
965 ;# {GroupsServerURI} {Module:GroupsModule (ServicesConnectorModule:Groups Remote Service Connector or (ServicesConnectorModule:Groups HG Service Connector and LocalService:remote))} {Groups Server URI} {}
966 ;; URI for the groups services of this grid
946 ;; e.g. http://yourxmlrpcserver.com/xmlrpc.php for Flotsam XmlRpc 967 ;; e.g. http://yourxmlrpcserver.com/xmlrpc.php for Flotsam XmlRpc
947 ;; or http://mygridserver.com:82/Grid/ for SimianGrid 968 ;; or http://mygridserver.com:82/Grid/ for SimianGrid
969 ;; or http:://mygridserver.com:8003 for robust, V2
948 ; GroupsServerURI = "" 970 ; GroupsServerURI = ""
949 971
950 ;# {NoticesEnabled} {Module:GroupsModule} {Enable group notices?} {true false} true 972 ;# {HomeURI} {ServicesConnectorModule:Groups HG Service Connector} {What's the home address of this world?} {}
973 ;; Used for V2 in HG only. For example
974 ;; http://mygridserver.com:9000 or http://mygridserver.com:8002
975 ;; If you have this set under [Startup], no need to set it here, leave it commented
976 ; HomeURI = ""
977
978 ;# {MessagingEnabled} {Module:GroupsModule Module:Groups Module V2} {Is groups messaging enabled?} {true false} true
979 ; MessagingEnabled = true
980
981 ;# {MessagingModule} {MessagingEnabled:true} {Module to use for groups messaging} {GroupsMessagingModule "Groups Messaging Module V2"} GroupsMessagingModule
982 ; MessagingModule = GroupsMessagingModule
983 ;; or use V2 for Groups V2
984 ; MessagingModule = "Groups Messaging Module V2"
985
986 ;# {NoticesEnabled} {Module:GroupsModule Module:Groups Module V2} {Enable group notices?} {true false} true
951 ;; Enable Group Notices 987 ;; Enable Group Notices
952 ; NoticesEnabled = true 988 ; NoticesEnabled = true
953 989
diff --git a/bin/Robust.HG.ini.example b/bin/Robust.HG.ini.example
index c7d4b7f..274132e 100644
--- a/bin/Robust.HG.ini.example
+++ b/bin/Robust.HG.ini.example
@@ -22,17 +22,31 @@
22; * 22; *
23[Startup] 23[Startup]
24 24
25; Plugin Registry Location 25 ; Plugin Registry Location
26; Set path to directory for plugin registry. Information 26 ; Set path to directory for plugin registry. Information
27; about the registered repositories and installed plugins 27 ; about the registered repositories and installed plugins
28; will be stored here 28 ; will be stored here
29; The Robust.exe process must hvae R/W access to the location 29 ; The Robust.exe process must hvae R/W access to the location
30RegistryLocation = "." 30 RegistryLocation = "."
31 31
32; Modular configurations 32 ; Modular configurations
33; Set path to directory for modular ini files... 33 ; Set path to directory for modular ini files...
34; The Robust.exe process must hvae R/W access to the location 34 ; The Robust.exe process must hvae R/W access to the location
35ConfigDirectory = "/home/opensim/etc/Configs" 35 ConfigDirectory = "/home/opensim/etc/Configs"
36
37 ;# {HomeURI} {Hypergrid} {The Home URL of this world} {}
38 ;; This is the address of the external robust server that
39 ;; runs the UserAgentsService, possibly this server.
40 ;; For example http://myworld.com:8002
41 ;; This is a default that can be overwritten in some sections.
42 ; HomeURI = "http://127.0.0.1:8002"
43
44 ;# {GatekeeperURI} {Hypergrid} {The URL of the gatekeeper of this world} {}
45 ;; This is the address of the external robust server
46 ;; that runs the Gatekeeper service, possibly this server.
47 ;; For example http://myworld.com:8002
48 ;; This is a default that can be overwritten in some sections.
49 ; GatekeeperURI = "http://127.0.0.1:8002"
36 50
37[ServiceList] 51[ServiceList]
38 52
@@ -51,6 +65,10 @@ GridUserServiceConnector = "8003/OpenSim.Server.Handlers.dll:GridUserServiceConn
51FriendsServiceConnector = "8003/OpenSim.Server.Handlers.dll:FriendsServiceConnector" 65FriendsServiceConnector = "8003/OpenSim.Server.Handlers.dll:FriendsServiceConnector"
52MapAddServiceConnector = "8003/OpenSim.Server.Handlers.dll:MapAddServiceConnector" 66MapAddServiceConnector = "8003/OpenSim.Server.Handlers.dll:MapAddServiceConnector"
53MapGetServiceConnector = "8002/OpenSim.Server.Handlers.dll:MapGetServiceConnector" 67MapGetServiceConnector = "8002/OpenSim.Server.Handlers.dll:MapGetServiceConnector"
68;; Uncomment this if you want offline IM to work
69; OfflineIMServiceConnector = "8003/OpenSim.Addons.OfflineIM.dll:OfflineIMServiceRobustConnector"
70;; Uncomment this if you want Groups V2 to work
71; GroupsServiceConnector = "8003/OpenSim.Addons.Groups.dll:GroupsServiceRobustConnector"
54 72
55;; Additions for Hypergrid 73;; Additions for Hypergrid
56 74
@@ -61,6 +79,8 @@ HGFriendsServerConnector = "8002/OpenSim.Server.Handlers.dll:HGFriendsServerConn
61InstantMessageServerConnector = "8002/OpenSim.Server.Handlers.dll:InstantMessageServerConnector" 79InstantMessageServerConnector = "8002/OpenSim.Server.Handlers.dll:InstantMessageServerConnector"
62HGInventoryServiceConnector = "HGInventoryService@8002/OpenSim.Server.Handlers.dll:XInventoryInConnector" 80HGInventoryServiceConnector = "HGInventoryService@8002/OpenSim.Server.Handlers.dll:XInventoryInConnector"
63HGAssetServiceConnector = "HGAssetService@8002/OpenSim.Server.Handlers.dll:AssetServiceConnector" 81HGAssetServiceConnector = "HGAssetService@8002/OpenSim.Server.Handlers.dll:AssetServiceConnector"
82;; Uncomment this if you want Groups V2, HG to work
83; HGGroupsServiceConnector = "8002/Diva.Groups.dll:HGGroupsServiceRobustConnector"
64 84
65;; Additions for other add-on modules. For example: 85;; Additions for other add-on modules. For example:
66;; WifiServerConnector = "8002/Diva.Wifi.dll:WifiServerConnector" 86;; WifiServerConnector = "8002/Diva.Wifi.dll:WifiServerConnector"
@@ -149,7 +169,8 @@ HGAssetServiceConnector = "HGAssetService@8002/OpenSim.Server.Handlers.dll:Asset
149 ;; Allow Hyperlinks to be created at the console 169 ;; Allow Hyperlinks to be created at the console
150 HypergridLinker = true 170 HypergridLinker = true
151 171
152 Gatekeeper = "http://127.0.0.1:8002" 172 ;; If you have this set under [Startup], no need to set it here, leave it commented
173 ; GatekeeperURI = "http://127.0.0.1:8002"
153 174
154 175
155; * This is the configuration for the freeswitch server in grid mode 176; * This is the configuration for the freeswitch server in grid mode
@@ -303,8 +324,8 @@ HGAssetServiceConnector = "HGAssetService@8002/OpenSim.Server.Handlers.dll:Asset
303 ; HasProxy = false 324 ; HasProxy = false
304 325
305 ; Defaults for the users, if none is specified in the useraccounts table entry (ServiceURLs) 326 ; Defaults for the users, if none is specified in the useraccounts table entry (ServiceURLs)
306 ; CHANGE THIS 327 ;; If you have Gatekeeper set under [Startup], no need to set it here, leave it commented
307 GatekeeperURI = "http://127.0.0.1:8002" 328 ; GatekeeperURI = "http://127.0.0.1:8002"
308 329
309 SRV_HomeURI = "http://127.0.0.1:8002" 330 SRV_HomeURI = "http://127.0.0.1:8002"
310 SRV_InventoryServerURI = "http://127.0.0.1:8002" 331 SRV_InventoryServerURI = "http://127.0.0.1:8002"
@@ -411,8 +432,8 @@ HGAssetServiceConnector = "HGAssetService@8002/OpenSim.Server.Handlers.dll:Asset
411 AuthenticationService = "OpenSim.Services.Connectors.dll:AuthenticationServicesConnector" 432 AuthenticationService = "OpenSim.Services.Connectors.dll:AuthenticationServicesConnector"
412 SimulationService ="OpenSim.Services.Connectors.dll:SimulationServiceConnector" 433 SimulationService ="OpenSim.Services.Connectors.dll:SimulationServiceConnector"
413 ; how does the outside world reach me? This acts as public key too. 434 ; how does the outside world reach me? This acts as public key too.
414 ; CHANGE THIS 435 ;; If you have GatekeeperURI set under [Startup], no need to set it here, leave it commented
415 ExternalName = "http://127.0.0.1:8002" 436 ; ExternalName = "http://127.0.0.1:8002"
416 437
417 ; Does this grid allow incoming links to any region in it? 438 ; Does this grid allow incoming links to any region in it?
418 ; If false, HG TPs happen only to the Default regions specified in [GridService] section 439 ; If false, HG TPs happen only to the Default regions specified in [GridService] section
@@ -505,7 +526,9 @@ HGAssetServiceConnector = "HGAssetService@8002/OpenSim.Server.Handlers.dll:Asset
505 526
506 UserAccountsService = "OpenSim.Services.UserAccountService.dll:UserAccountService" 527 UserAccountsService = "OpenSim.Services.UserAccountService.dll:UserAccountService"
507 AvatarService = "OpenSim.Services.AvatarService.dll:AvatarService" 528 AvatarService = "OpenSim.Services.AvatarService.dll:AvatarService"
508 HomeURI = "http://127.0.0.1:8002" 529
530 ;; Can overwrite the default in [Startup], but probably shouldn't
531 ; HomeURI = "http://127.0.0.1:8002"
509 532
510; * The interface that local users get when they are in other grids. 533; * The interface that local users get when they are in other grids.
511; * This restricts the access that the rest of the world has to 534; * This restricts the access that the rest of the world has to
@@ -514,7 +537,9 @@ HGAssetServiceConnector = "HGAssetService@8002/OpenSim.Server.Handlers.dll:Asset
514[HGAssetService] 537[HGAssetService]
515 LocalServiceModule = "OpenSim.Services.HypergridService.dll:HGAssetService" 538 LocalServiceModule = "OpenSim.Services.HypergridService.dll:HGAssetService"
516 UserAccountsService = "OpenSim.Services.UserAccountService.dll:UserAccountService" 539 UserAccountsService = "OpenSim.Services.UserAccountService.dll:UserAccountService"
517 HomeURI = "http://127.0.0.1:8002" 540
541 ;; Can overwrite the default in [Startup], but probably shouldn't
542 ; HomeURI = "http://127.0.0.1:8002"
518 543
519 ;; The asset types that this grid can export to / import from other grids. 544 ;; The asset types that this grid can export to / import from other grids.
520 ;; Comma separated. 545 ;; Comma separated.
@@ -545,15 +570,16 @@ HGAssetServiceConnector = "HGAssetService@8002/OpenSim.Server.Handlers.dll:Asset
545 InGatekeeper = True 570 InGatekeeper = True
546 571
547[Messaging] 572[Messaging]
548 ; If you have an Offline IM server, set the vars in this section, so that 573 ; OfflineIM
549 ; incomming IMs to local users from foreign grids can be saved 574 OfflineIMService = "OpenSim.Addons.OfflineIM.dll:OfflineIMService"
550 ; 575
551 ;# {OfflineMessageURL} {OfflineMessageModule:OfflineMessageModule} {URL of offline messaging service} {} 576[Groups]
552 ;; URL of web service for offline message storage 577 ;; for the HG Groups service
553 ; OfflineMessageURL = http://yourserver/Offline.php 578 OfflineIMService = "OpenSim.Addons.OfflineIM.dll:OfflineIMService"
554 579 UserAccountService = "OpenSim.Services.UserAccountService.dll:UserAccountService"
555 ;; Control whether group messages are forwarded to offline users. 580
556 ;; Default is true. 581 ;; What is the HomeURI of users associated with this grid?
557 ;; This applies to the core groups module (Flotsam) only. 582 ;; Can overwrite the default in [Startup], but probably shouldn't
558 ; ForwardOfflineGroupMessages = true 583 ; HomeURI = "http://127.0.0.1:8002"
584
559 585
diff --git a/bin/Robust.ini.example b/bin/Robust.ini.example
index bc5cbcc..ecbed1f 100644
--- a/bin/Robust.ini.example
+++ b/bin/Robust.ini.example
@@ -14,18 +14,18 @@
14; * 14; *
15[Startup] 15[Startup]
16 16
17; Plugin Registry Location 17 ; Plugin Registry Location
18; Set path to directory for plugin registry. Information 18 ; Set path to directory for plugin registry. Information
19; about the registered repositories and installed plugins 19 ; about the registered repositories and installed plugins
20; will be stored here 20 ; will be stored here
21; The Robust.exe process must hvae R/W access to the location 21 ; The Robust.exe process must hvae R/W access to the location
22RegistryLocation = "." 22 RegistryLocation = "."
23 23
24 24
25; Modular configurations 25 ; Modular configurations
26; Set path to directory for modular ini files... 26 ; Set path to directory for modular ini files...
27; The Robust.exe process must hvae R/W access to the location 27 ; The Robust.exe process must hvae R/W access to the location
28ConfigDirectory = "/home/opensim/etc/Configs" 28 ConfigDirectory = "/home/opensim/etc/Configs"
29 29
30[ServiceList] 30[ServiceList]
31AssetServiceConnector = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector" 31AssetServiceConnector = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector"
@@ -43,6 +43,11 @@ GridUserServiceConnector = "8003/OpenSim.Server.Handlers.dll:GridUserServiceConn
43FriendsServiceConnector = "8003/OpenSim.Server.Handlers.dll:FriendsServiceConnector" 43FriendsServiceConnector = "8003/OpenSim.Server.Handlers.dll:FriendsServiceConnector"
44MapAddServiceConnector = "8003/OpenSim.Server.Handlers.dll:MapAddServiceConnector" 44MapAddServiceConnector = "8003/OpenSim.Server.Handlers.dll:MapAddServiceConnector"
45MapGetServiceConnector = "8002/OpenSim.Server.Handlers.dll:MapGetServiceConnector" 45MapGetServiceConnector = "8002/OpenSim.Server.Handlers.dll:MapGetServiceConnector"
46;; Uncomment this if you want offline IM to work
47;OfflineIMServiceConnector = "8003/OpenSim.Addons.OfflineIM.dll:OfflineIMServiceRobustConnector"
48;; Uncomment this if you want Groups V2 to work
49;GroupsServiceConnector = "8003/OpenSim.Addons.Groups.dll:GroupsServiceRobustConnector"
50
46 51
47; * This is common for all services, it's the network setup for the entire 52; * This is common for all services, it's the network setup for the entire
48; * server instance, if none is specified above 53; * server instance, if none is specified above
@@ -256,7 +261,12 @@ MapGetServiceConnector = "8002/OpenSim.Server.Handlers.dll:MapGetServiceConnecto
256 LibraryService = "OpenSim.Services.InventoryService.dll:LibraryService" 261 LibraryService = "OpenSim.Services.InventoryService.dll:LibraryService"
257 FriendsService = "OpenSim.Services.FriendsService.dll:FriendsService" 262 FriendsService = "OpenSim.Services.FriendsService.dll:FriendsService"
258 263
259 ;; Ask co-operative viewers to use a different currency name 264 ; The minimum user level required for a user to be able to login. 0 by default
265 ; If you disable a particular user's account then you can set their login level below this number.
266 ; You can also change this level from the console though these changes will not be persisted.
267 ; MinLoginLevel = 0
268
269 ; Ask co-operative viewers to use a different currency name
260 ;Currency = "" 270 ;Currency = ""
261 271
262 WelcomeMessage = "Welcome, Avatar!" 272 WelcomeMessage = "Welcome, Avatar!"
@@ -329,6 +339,9 @@ MapGetServiceConnector = "8002/OpenSim.Server.Handlers.dll:MapGetServiceConnecto
329 ; HasProxy = false 339 ; HasProxy = false
330 340
331 341
342[Messaging]
343 ; OfflineIM
344 OfflineIMService = "OpenSim.Addons.OfflineIM.dll:OfflineIMService"
332 345
333[GridInfoService] 346[GridInfoService]
334 ; These settings are used to return information on a get_grid_info call. 347 ; These settings are used to return information on a get_grid_info call.
diff --git a/bin/config-include/StandaloneCommon.ini.example b/bin/config-include/StandaloneCommon.ini.example
index f28de43..3129078 100644
--- a/bin/config-include/StandaloneCommon.ini.example
+++ b/bin/config-include/StandaloneCommon.ini.example
@@ -64,8 +64,8 @@
64 Region_Welcome_Area = "DefaultRegion, FallbackRegion" 64 Region_Welcome_Area = "DefaultRegion, FallbackRegion"
65 65
66 ; === HG ONLY === 66 ; === HG ONLY ===
67 ;; change this to the address of your simulator 67 ;; If you have this set under [Startup], no need to set it here, leave it commented
68 Gatekeeper="http://127.0.0.1:9000" 68 ; GatekeeperURI="http://127.0.0.1:9000"
69 69
70[LibraryModule] 70[LibraryModule]
71 ; Set this if you want to change the name of the OpenSim Library 71 ; Set this if you want to change the name of the OpenSim Library
@@ -73,7 +73,8 @@
73 73
74[LoginService] 74[LoginService]
75 WelcomeMessage = "Welcome, Avatar!" 75 WelcomeMessage = "Welcome, Avatar!"
76 GatekeeperURI = "http://127.0.0.1:9000" 76 ;; If you have Gatekeeper set under [Startup], no need to set it here, leave it commented
77 ; GatekeeperURI = "http://127.0.0.1:9000"
77 78
78 SRV_HomeURI = "http://127.0.0.1:9000" 79 SRV_HomeURI = "http://127.0.0.1:9000"
79 SRV_InventoryServerURI = "http://127.0.0.1:9000" 80 SRV_InventoryServerURI = "http://127.0.0.1:9000"
@@ -85,6 +86,11 @@
85 ;; For Viewer 2 86 ;; For Viewer 2
86 MapTileURL = "http://127.0.0.1:9000/" 87 MapTileURL = "http://127.0.0.1:9000/"
87 88
89 ; The minimum user level required for a user to be able to login. 0 by default
90 ; If you disable a particular user's account then you can set their login level below this number.
91 ; You can also change this level from the console though these changes will not be persisted.
92 ; MinLoginLevel = 0
93
88 ;; Ask co-operative viewers to use a different currency name 94 ;; Ask co-operative viewers to use a different currency name
89 ;Currency = "" 95 ;Currency = ""
90 96
@@ -213,7 +219,8 @@
213;; HG configurations 219;; HG configurations
214;; 220;;
215[GatekeeperService] 221[GatekeeperService]
216 ExternalName = "http://127.0.0.1:9000" 222 ;; If you have GatekeeperURI set under [Startup], no need to set it here, leave it commented
223 ; ExternalName = "http://127.0.0.1:9000"
217 224
218 ; Does this grid allow incoming links to any region in it? 225 ; Does this grid allow incoming links to any region in it?
219 ; If false, HG TPs happen only to the Default regions specified in [GridService] section 226 ; If false, HG TPs happen only to the Default regions specified in [GridService] section
@@ -269,10 +276,12 @@
269 ; AllowExcept_Level_200 = "http://griefer.com:8002, http://enemy.com:8002" 276 ; AllowExcept_Level_200 = "http://griefer.com:8002, http://enemy.com:8002"
270 277
271[HGInventoryService] 278[HGInventoryService]
272 HomeURI = "http://127.0.0.1:9000" 279 ;; If you have this set under [Startup], no need to set it here, leave it commented
280 ; HomeURI = "http://127.0.0.1:9000"
273 281
274[HGAssetService] 282[HGAssetService]
275 HomeURI = "http://127.0.0.1:9000" 283 ;; If you have this set under [Startup], no need to set it here, leave it commented
284 ; HomeURI = "http://127.0.0.1:9000"
276 285
277 ;; The asset types that this grid can export to / import from other grids. 286 ;; The asset types that this grid can export to / import from other grids.
278 ;; Comma separated. 287 ;; Comma separated.
@@ -288,8 +297,9 @@
288 297
289 298
290[HGInventoryAccessModule] 299[HGInventoryAccessModule]
291 HomeURI = "http://127.0.0.1:9000" 300 ;; If you have these set under [Startup], no need to set it here, leave it commented
292 Gatekeeper = "http://127.0.0.1:9000" 301 ; HomeURI = "http://127.0.0.1:9000"
302 ; GatekeeperURI = "http://127.0.0.1:9000"
293 303
294 ;; If you want to protect your assets from being copied by foreign visitors 304 ;; If you want to protect your assets from being copied by foreign visitors
295 ;; uncomment the next line. You may want to do this on sims that have licensed content. 305 ;; uncomment the next line. You may want to do this on sims that have licensed content.
@@ -306,8 +316,8 @@
306 316
307[Messaging] 317[Messaging]
308 ; === HG ONLY === 318 ; === HG ONLY ===
309 ;; change this to the address of your simulator 319 ;; If you have this set under [Startup], no need to set it here, leave it commented
310 Gatekeeper = "http://127.0.0.1:9000" 320 ; GatekeeperURI = "http://127.0.0.1:9000"
311 321
312 322
313[EntityTransfer] 323[EntityTransfer]
diff --git a/bin/lib32/BulletSim.dll b/bin/lib32/BulletSim.dll
index e7a8a41..689b34f 100755
--- a/bin/lib32/BulletSim.dll
+++ b/bin/lib32/BulletSim.dll
Binary files differ
diff --git a/bin/lib32/libBulletSim.so b/bin/lib32/libBulletSim.so
index 4bf23a6..b8c813e 100755
--- a/bin/lib32/libBulletSim.so
+++ b/bin/lib32/libBulletSim.so
Binary files differ
diff --git a/bin/lib64/BulletSim.dll b/bin/lib64/BulletSim.dll
index 63ac1a9..33c4d08 100755
--- a/bin/lib64/BulletSim.dll
+++ b/bin/lib64/BulletSim.dll
Binary files differ
diff --git a/bin/lib64/libBulletSim.so b/bin/lib64/libBulletSim.so
index 422681e..79207fe 100755
--- a/bin/lib64/libBulletSim.so
+++ b/bin/lib64/libBulletSim.so
Binary files differ
diff --git a/prebuild.xml b/prebuild.xml
index 2bee760..8296daa 100644
--- a/prebuild.xml
+++ b/prebuild.xml
@@ -2647,6 +2647,104 @@
2647 </Match> 2647 </Match>
2648 </Files> 2648 </Files>
2649 </Project> 2649 </Project>
2650
2651 <!-- Addons -->
2652
2653 <Project frameworkVersion="v3_5" name="OpenSim.Addons.OfflineIM" path="OpenSim/Addons/OfflineIM" type="Library">
2654 <Configuration name="Debug">
2655 <Options>
2656 <OutputPath>../../../bin/</OutputPath>
2657 </Options>
2658 </Configuration>
2659 <Configuration name="Release">
2660 <Options>
2661 <OutputPath>../../../bin/</OutputPath>
2662 </Options>
2663 </Configuration>
2664
2665 <ReferencePath>../../../bin/</ReferencePath>
2666 <Reference name="System"/>
2667 <Reference name="System.Core"/>
2668 <Reference name="System.Data"/>
2669 <Reference name="System.Web"/>
2670 <Reference name="System.Xml"/>
2671
2672 <Reference name="Nini" path="../../../bin/"/>
2673 <Reference name="Mono.Addins" path="../../../bin/"/>
2674 <Reference name="MySql.Data" path="../../../bin/"/>
2675 <Reference name="log4net" path="../../../bin/"/>
2676 <Reference name="OpenMetaverse" path="../../../bin/"/>
2677 <Reference name="OpenMetaverseTypes" path="../../../bin/"/>
2678
2679 <Reference name="OpenSim.Framework"/>
2680 <Reference name="OpenSim.Data"/>
2681 <Reference name="OpenSim.Data.MySQL"/>
2682 <Reference name="OpenSim.Framework.Servers.HttpServer"/>
2683 <Reference name="OpenSim.Services.Base"/>
2684 <Reference name="OpenSim.Services.Interfaces"/>
2685 <Reference name="OpenSim.Region.Framework"/>
2686 <Reference name="OpenSim.Server.Base"/>
2687 <Reference name="OpenSim.Server.Handlers"/>
2688
2689 <!-- To allow regions to have mono addins -->
2690 <Reference name="Mono.Addins" path="../../../bin/" />
2691
2692 <Files>
2693 <Match pattern="*.cs" recurse="true">
2694 <Exclude pattern="Tests" />
2695 </Match>
2696 <Match buildAction="EmbeddedResource" path="Resources" pattern="*.migrations"/>
2697 </Files>
2698 </Project>
2699
2700 <Project frameworkVersion="v3_5" name="OpenSim.Addons.Groups" path="OpenSim/Addons/Groups" type="Library">
2701 <Configuration name="Debug">
2702 <Options>
2703 <OutputPath>../../../bin/</OutputPath>
2704 </Options>
2705 </Configuration>
2706 <Configuration name="Release">
2707 <Options>
2708 <OutputPath>../../../bin/</OutputPath>
2709 </Options>
2710 </Configuration>
2711
2712 <ReferencePath>../../../bin/</ReferencePath>
2713 <Reference name="System"/>
2714 <Reference name="System.Core"/>
2715 <Reference name="System.Data"/>
2716 <Reference name="System.Web"/>
2717 <Reference name="System.Xml"/>
2718
2719 <Reference name="Nini" path="../../../bin/"/>
2720 <Reference name="Mono.Addins" path="../../../bin/"/>
2721 <Reference name="log4net" path="../../../bin/"/>
2722 <Reference name="OpenMetaverse" path="../../../bin/"/>
2723 <Reference name="OpenMetaverseTypes" path="../../../bin/"/>
2724 <Reference name="OpenMetaverse.StructuredData" path="../../../bin/"/>
2725
2726 <Reference name="OpenSim.Framework"/>
2727 <Reference name="OpenSim.Data"/>
2728 <Reference name="OpenSim.Framework.Servers"/>
2729 <Reference name="OpenSim.Framework.Servers.HttpServer"/>
2730 <Reference name="OpenSim.Services.Base"/>
2731 <Reference name="OpenSim.Services.Interfaces"/>
2732 <Reference name="OpenSim.Region.Framework"/>
2733 <Reference name="OpenSim.Server.Base"/>
2734 <Reference name="OpenSim.Server.Handlers"/>
2735
2736 <!-- To allow regions to have mono addins -->
2737 <Reference name="Mono.Addins" path="../../../bin/" />
2738
2739 <Files>
2740 <Match pattern="*.cs" recurse="true">
2741 <Exclude pattern="Tests" />
2742 </Match>
2743 <Match buildAction="EmbeddedResource" path="Resources" pattern="*.migrations"/>
2744 </Files>
2745
2746 </Project>
2747
2650 2748
2651 <!-- Tools --> 2749 <!-- Tools -->
2652 2750