aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/CoreModules
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/CoreModules')
-rw-r--r--OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs99
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs3
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs355
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs623
-rw-r--r--OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs350
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveUtils.cs82
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs15
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs244
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs15
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Profile/BasicProfileModule.cs173
-rw-r--r--OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs35
-rw-r--r--OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs58
-rw-r--r--OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs34
-rw-r--r--OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs84
-rw-r--r--OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs112
-rw-r--r--OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs98
-rw-r--r--OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml1
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsIn/Hypergrid/HypergridServiceInConnectorModule.cs4
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsIn/MapImage/MapImageServiceInConnectorModule.cs111
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RegionInfoCache.cs137
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RemoteGridServiceConnector.cs34
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs23
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs242
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs3
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs8
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs2
-rw-r--r--OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs41
-rw-r--r--OpenSim/Region/CoreModules/World/Warp3DMap/MapImageModule.cs12
-rw-r--r--OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs97
29 files changed, 2790 insertions, 305 deletions
diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
index 7cba702..9ef5bc9 100644
--- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
+++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
@@ -64,13 +64,13 @@ namespace Flotsam.RegionModules.AssetCache
64 private bool m_Enabled; 64 private bool m_Enabled;
65 65
66 private const string m_ModuleName = "FlotsamAssetCache"; 66 private const string m_ModuleName = "FlotsamAssetCache";
67 private const string m_DefaultCacheDirectory = m_ModuleName; 67 private const string m_DefaultCacheDirectory = "./assetcache";
68 private string m_CacheDirectory = m_DefaultCacheDirectory; 68 private string m_CacheDirectory = m_DefaultCacheDirectory;
69 69
70 private readonly List<char> m_InvalidChars = new List<char>(); 70 private readonly List<char> m_InvalidChars = new List<char>();
71 71
72 private int m_LogLevel = 0; 72 private int m_LogLevel = 0;
73 private ulong m_HitRateDisplay = 1; // How often to display hit statistics, given in requests 73 private ulong m_HitRateDisplay = 100; // How often to display hit statistics, given in requests
74 74
75 private static ulong m_Requests; 75 private static ulong m_Requests;
76 private static ulong m_RequestsForInprogress; 76 private static ulong m_RequestsForInprogress;
@@ -87,14 +87,14 @@ namespace Flotsam.RegionModules.AssetCache
87#endif 87#endif
88 88
89 private ExpiringCache<string, AssetBase> m_MemoryCache; 89 private ExpiringCache<string, AssetBase> m_MemoryCache;
90 private bool m_MemoryCacheEnabled = true; 90 private bool m_MemoryCacheEnabled = false;
91 91
92 // Expiration is expressed in hours. 92 // Expiration is expressed in hours.
93 private const double m_DefaultMemoryExpiration = 1.0; 93 private const double m_DefaultMemoryExpiration = 2;
94 private const double m_DefaultFileExpiration = 48; 94 private const double m_DefaultFileExpiration = 48;
95 private TimeSpan m_MemoryExpiration = TimeSpan.FromHours(m_DefaultMemoryExpiration); 95 private TimeSpan m_MemoryExpiration = TimeSpan.FromHours(m_DefaultMemoryExpiration);
96 private TimeSpan m_FileExpiration = TimeSpan.FromHours(m_DefaultFileExpiration); 96 private TimeSpan m_FileExpiration = TimeSpan.FromHours(m_DefaultFileExpiration);
97 private TimeSpan m_FileExpirationCleanupTimer = TimeSpan.FromHours(m_DefaultFileExpiration); 97 private TimeSpan m_FileExpirationCleanupTimer = TimeSpan.FromHours(0.166);
98 98
99 private static int m_CacheDirectoryTiers = 1; 99 private static int m_CacheDirectoryTiers = 1;
100 private static int m_CacheDirectoryTierLen = 3; 100 private static int m_CacheDirectoryTierLen = 3;
@@ -141,26 +141,38 @@ namespace Flotsam.RegionModules.AssetCache
141 IConfig assetConfig = source.Configs["AssetCache"]; 141 IConfig assetConfig = source.Configs["AssetCache"];
142 if (assetConfig == null) 142 if (assetConfig == null)
143 { 143 {
144 m_log.Warn("[FLOTSAM ASSET CACHE]: AssetCache missing from OpenSim.ini, using defaults."); 144 m_log.Warn(
145 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Cache Directory", m_DefaultCacheDirectory); 145 "[FLOTSAM ASSET CACHE]: AssetCache section missing from config (not copied config-include/FlotsamCache.ini.example? Using defaults.");
146 return;
147 } 146 }
147 else
148 {
149 m_CacheDirectory = assetConfig.GetString("CacheDirectory", m_DefaultCacheDirectory);
148 150
149 m_CacheDirectory = assetConfig.GetString("CacheDirectory", m_DefaultCacheDirectory); 151 m_MemoryCacheEnabled = assetConfig.GetBoolean("MemoryCacheEnabled", m_MemoryCacheEnabled);
150 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Cache Directory", m_CacheDirectory); 152 m_MemoryExpiration = TimeSpan.FromHours(assetConfig.GetDouble("MemoryCacheTimeout", m_DefaultMemoryExpiration));
153
154 #if WAIT_ON_INPROGRESS_REQUESTS
155 m_WaitOnInprogressTimeout = assetConfig.GetInt("WaitOnInprogressTimeout", 3000);
156 #endif
157
158 m_LogLevel = assetConfig.GetInt("LogLevel", m_LogLevel);
159 m_HitRateDisplay = (ulong)assetConfig.GetLong("HitRateDisplay", (long)m_HitRateDisplay);
151 160
152 m_MemoryCacheEnabled = assetConfig.GetBoolean("MemoryCacheEnabled", false); 161 m_FileExpiration = TimeSpan.FromHours(assetConfig.GetDouble("FileCacheTimeout", m_DefaultFileExpiration));
153 m_MemoryExpiration = TimeSpan.FromHours(assetConfig.GetDouble("MemoryCacheTimeout", m_DefaultMemoryExpiration)); 162 m_FileExpirationCleanupTimer
163 = TimeSpan.FromHours(
164 assetConfig.GetDouble("FileCleanupTimer", m_FileExpirationCleanupTimer.TotalHours));
154 165
155#if WAIT_ON_INPROGRESS_REQUESTS 166 m_CacheDirectoryTiers = assetConfig.GetInt("CacheDirectoryTiers", m_CacheDirectoryTiers);
156 m_WaitOnInprogressTimeout = assetConfig.GetInt("WaitOnInprogressTimeout", 3000); 167 m_CacheDirectoryTierLen = assetConfig.GetInt("CacheDirectoryTierLength", m_CacheDirectoryTierLen);
157#endif 168
169 m_CacheWarnAt = assetConfig.GetInt("CacheWarnAt", m_CacheWarnAt);
170
171 m_DeepScanBeforePurge = assetConfig.GetBoolean("DeepScanBeforePurge", m_DeepScanBeforePurge);
172 }
158 173
159 m_LogLevel = assetConfig.GetInt("LogLevel", 0); 174 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Cache Directory {0}", m_CacheDirectory);
160 m_HitRateDisplay = (ulong)assetConfig.GetInt("HitRateDisplay", 1000);
161 175
162 m_FileExpiration = TimeSpan.FromHours(assetConfig.GetDouble("FileCacheTimeout", m_DefaultFileExpiration));
163 m_FileExpirationCleanupTimer = TimeSpan.FromHours(assetConfig.GetDouble("FileCleanupTimer", m_DefaultFileExpiration));
164 if ((m_FileExpiration > TimeSpan.Zero) && (m_FileExpirationCleanupTimer > TimeSpan.Zero)) 176 if ((m_FileExpiration > TimeSpan.Zero) && (m_FileExpirationCleanupTimer > TimeSpan.Zero))
165 { 177 {
166 m_CacheCleanTimer = new System.Timers.Timer(m_FileExpirationCleanupTimer.TotalMilliseconds); 178 m_CacheCleanTimer = new System.Timers.Timer(m_FileExpirationCleanupTimer.TotalMilliseconds);
@@ -170,7 +182,6 @@ namespace Flotsam.RegionModules.AssetCache
170 m_CacheCleanTimer.Start(); 182 m_CacheCleanTimer.Start();
171 } 183 }
172 184
173 m_CacheDirectoryTiers = assetConfig.GetInt("CacheDirectoryTiers", 1);
174 if (m_CacheDirectoryTiers < 1) 185 if (m_CacheDirectoryTiers < 1)
175 { 186 {
176 m_CacheDirectoryTiers = 1; 187 m_CacheDirectoryTiers = 1;
@@ -180,7 +191,6 @@ namespace Flotsam.RegionModules.AssetCache
180 m_CacheDirectoryTiers = 3; 191 m_CacheDirectoryTiers = 3;
181 } 192 }
182 193
183 m_CacheDirectoryTierLen = assetConfig.GetInt("CacheDirectoryTierLength", 3);
184 if (m_CacheDirectoryTierLen < 1) 194 if (m_CacheDirectoryTierLen < 1)
185 { 195 {
186 m_CacheDirectoryTierLen = 1; 196 m_CacheDirectoryTierLen = 1;
@@ -190,14 +200,10 @@ namespace Flotsam.RegionModules.AssetCache
190 m_CacheDirectoryTierLen = 4; 200 m_CacheDirectoryTierLen = 4;
191 } 201 }
192 202
193 m_CacheWarnAt = assetConfig.GetInt("CacheWarnAt", 30000); 203 MainConsole.Instance.Commands.AddCommand(Name, true, "fcache status", "fcache status", "Display cache status", HandleConsoleCommand);
194 204 MainConsole.Instance.Commands.AddCommand(Name, true, "fcache clear", "fcache clear [file] [memory]", "Remove all assets in the cache. If file or memory is specified then only this cache is cleared.", HandleConsoleCommand);
195 m_DeepScanBeforePurge = assetConfig.GetBoolean("DeepScanBeforePurge", false); 205 MainConsole.Instance.Commands.AddCommand(Name, true, "fcache assets", "fcache assets", "Attempt a deep scan and cache of all assets in all scenes", HandleConsoleCommand);
196 206 MainConsole.Instance.Commands.AddCommand(Name, true, "fcache expire", "fcache expire <datetime>", "Purge cached assets older then the specified date/time", HandleConsoleCommand);
197 MainConsole.Instance.Commands.AddCommand(this.Name, true, "fcache status", "fcache status", "Display cache status", HandleConsoleCommand);
198 MainConsole.Instance.Commands.AddCommand(this.Name, true, "fcache clear", "fcache clear [file] [memory]", "Remove all assets in the file and/or memory cache", HandleConsoleCommand);
199 MainConsole.Instance.Commands.AddCommand(this.Name, true, "fcache assets", "fcache assets", "Attempt a deep scan and cache of all assets in all scenes", HandleConsoleCommand);
200 MainConsole.Instance.Commands.AddCommand(this.Name, true, "fcache expire", "fcache expire <datetime>", "Purge cached assets older then the specified date/time", HandleConsoleCommand);
201 } 207 }
202 } 208 }
203 } 209 }
@@ -732,24 +738,39 @@ namespace Flotsam.RegionModules.AssetCache
732 break; 738 break;
733 739
734 case "clear": 740 case "clear":
735 if (cmdparams.Length < 3) 741 if (cmdparams.Length < 2)
736 { 742 {
737 m_log.Warn("[FLOTSAM ASSET CACHE] Please specify memory and/or file cache."); 743 m_log.Warn("[FLOTSAM ASSET CACHE] Usage is fcache clear [file] [memory]");
738 break; 744 break;
739 } 745 }
746
747 bool clearMemory = false, clearFile = false;
748
749 if (cmdparams.Length == 2)
750 {
751 clearMemory = true;
752 clearFile = true;
753 }
740 foreach (string s in cmdparams) 754 foreach (string s in cmdparams)
741 { 755 {
742 if (s.ToLower() == "memory") 756 if (s.ToLower() == "memory")
743 { 757 clearMemory = true;
744 m_MemoryCache.Clear();
745 m_log.Info("[FLOTSAM ASSET CACHE] Memory cache cleared.");
746 }
747 else if (s.ToLower() == "file") 758 else if (s.ToLower() == "file")
748 { 759 clearFile = true;
749 ClearFileCache();
750 m_log.Info("[FLOTSAM ASSET CACHE] File cache cleared.");
751 }
752 } 760 }
761
762 if (clearMemory)
763 {
764 m_MemoryCache.Clear();
765 m_log.Info("[FLOTSAM ASSET CACHE] Memory cache cleared.");
766 }
767
768 if (clearFile)
769 {
770 ClearFileCache();
771 m_log.Info("[FLOTSAM ASSET CACHE] File cache cleared.");
772 }
773
753 break; 774 break;
754 775
755 776
diff --git a/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs b/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs
index ded8743..8a16582 100644
--- a/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs
@@ -124,7 +124,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Dialog
124 124
125 ScenePresence sp = m_scene.GetScenePresence(avatarID); 125 ScenePresence sp = m_scene.GetScenePresence(avatarID);
126 if (sp != null) 126 if (sp != null)
127 sp.ControllingClient.SendDialog(objectName, objectID, ownerFirstName, ownerLastName, message, textureID, ch, buttonlabels); 127 sp.ControllingClient.SendDialog(
128 objectName, objectID, ownerID, ownerFirstName, ownerLastName, message, textureID, ch, buttonlabels);
128 } 129 }
129 130
130 public void SendUrlToUser( 131 public void SendUrlToUser(
diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
index 0cd05e3..c8167c5 100644
--- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
@@ -49,6 +49,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
49{ 49{
50 public class FriendsModule : ISharedRegionModule, IFriendsModule 50 public class FriendsModule : ISharedRegionModule, IFriendsModule
51 { 51 {
52 protected bool m_Enabled = false;
53
52 protected class UserFriendData 54 protected class UserFriendData
53 { 55 {
54 public UUID PrincipalID; 56 public UUID PrincipalID;
@@ -67,7 +69,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
67 } 69 }
68 } 70 }
69 71
70 private static readonly FriendInfo[] EMPTY_FRIENDS = new FriendInfo[0]; 72 protected static readonly FriendInfo[] EMPTY_FRIENDS = new FriendInfo[0];
71 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 73 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
72 74
73 protected List<Scene> m_Scenes = new List<Scene>(); 75 protected List<Scene> m_Scenes = new List<Scene>();
@@ -130,8 +132,25 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
130 } 132 }
131 } 133 }
132 134
135 #region ISharedRegionModule
133 public void Initialise(IConfigSource config) 136 public void Initialise(IConfigSource config)
134 { 137 {
138 IConfig moduleConfig = config.Configs["Modules"];
139 if (moduleConfig != null)
140 {
141 string name = moduleConfig.GetString("FriendsModule", "FriendsModule");
142 if (name == Name)
143 {
144 InitModule(config);
145
146 m_Enabled = true;
147 m_log.InfoFormat("[FRIENDS MODULE]: {0} enabled.", Name);
148 }
149 }
150 }
151
152 protected void InitModule(IConfigSource config)
153 {
135 IConfig friendsConfig = config.Configs["Friends"]; 154 IConfig friendsConfig = config.Configs["Friends"];
136 if (friendsConfig != null) 155 if (friendsConfig != null)
137 { 156 {
@@ -153,7 +172,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
153 m_log.Error("[FRIENDS]: No Connector defined in section Friends, or failed to load, cannot continue"); 172 m_log.Error("[FRIENDS]: No Connector defined in section Friends, or failed to load, cannot continue");
154 throw new Exception("Connector load error"); 173 throw new Exception("Connector load error");
155 } 174 }
156
157 } 175 }
158 176
159 public void PostInitialise() 177 public void PostInitialise()
@@ -164,8 +182,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
164 { 182 {
165 } 183 }
166 184
167 public void AddRegion(Scene scene) 185 public virtual void AddRegion(Scene scene)
168 { 186 {
187 if (!m_Enabled)
188 return;
189 m_log.DebugFormat("[FRIENDS MODULE]: AddRegion on {0}", Name);
190
169 m_Scenes.Add(scene); 191 m_Scenes.Add(scene);
170 scene.RegisterModuleInterface<IFriendsModule>(this); 192 scene.RegisterModuleInterface<IFriendsModule>(this);
171 193
@@ -181,10 +203,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
181 203
182 public void RemoveRegion(Scene scene) 204 public void RemoveRegion(Scene scene)
183 { 205 {
206 if (!m_Enabled)
207 return;
208
184 m_Scenes.Remove(scene); 209 m_Scenes.Remove(scene);
185 } 210 }
186 211
187 public string Name 212 public virtual string Name
188 { 213 {
189 get { return "FriendsModule"; } 214 get { return "FriendsModule"; }
190 } 215 }
@@ -194,13 +219,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
194 get { return null; } 219 get { return null; }
195 } 220 }
196 221
197 public uint GetFriendPerms(UUID principalID, UUID friendID) 222 #endregion
223
224 public virtual uint GetFriendPerms(UUID principalID, UUID friendID)
198 { 225 {
199 FriendInfo[] friends = GetFriends(principalID); 226 FriendInfo[] friends = GetFriends(principalID);
200 foreach (FriendInfo fi in friends) 227 FriendInfo finfo = GetFriend(friends, friendID);
228 if (finfo != null)
201 { 229 {
202 if (fi.Friend == friendID.ToString()) 230 return (uint)finfo.TheirFlags;
203 return (uint)fi.TheirFlags;
204 } 231 }
205 232
206 return 0; 233 return 0;
@@ -214,30 +241,34 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
214 client.OnTerminateFriendship += OnTerminateFriendship; 241 client.OnTerminateFriendship += OnTerminateFriendship;
215 client.OnGrantUserRights += OnGrantUserRights; 242 client.OnGrantUserRights += OnGrantUserRights;
216 243
217 // Asynchronously fetch the friends list or increment the refcount for the existing 244 Util.FireAndForget(delegate { FetchFriendslist(client); });
218 // friends list 245 }
219 Util.FireAndForget( 246
220 delegate(object o) 247 /// Fetch the friends list or increment the refcount for the existing
248 /// friends list
249 /// Returns true if the list was fetched, false if it wasn't
250 protected virtual bool FetchFriendslist(IClientAPI client)
251 {
252 UUID agentID = client.AgentId;
253 lock (m_Friends)
254 {
255 UserFriendData friendsData;
256 if (m_Friends.TryGetValue(agentID, out friendsData))
221 { 257 {
222 lock (m_Friends) 258 friendsData.Refcount++;
223 { 259 return false;
224 UserFriendData friendsData; 260 }
225 if (m_Friends.TryGetValue(client.AgentId, out friendsData)) 261 else
226 { 262 {
227 friendsData.Refcount++; 263 friendsData = new UserFriendData();
228 } 264 friendsData.PrincipalID = agentID;
229 else 265 friendsData.Friends = GetFriendsFromService(client);
230 { 266 friendsData.Refcount = 1;
231 friendsData = new UserFriendData();
232 friendsData.PrincipalID = client.AgentId;
233 friendsData.Friends = FriendsService.GetFriends(client.AgentId);
234 friendsData.Refcount = 1;
235 267
236 m_Friends[client.AgentId] = friendsData; 268 m_Friends[agentID] = friendsData;
237 } 269 return true;
238 }
239 } 270 }
240 ); 271 }
241 } 272 }
242 273
243 private void OnClientClosed(UUID agentID, Scene scene) 274 private void OnClientClosed(UUID agentID, Scene scene)
@@ -263,14 +294,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
263 294
264 private void OnMakeRootAgent(ScenePresence sp) 295 private void OnMakeRootAgent(ScenePresence sp)
265 { 296 {
266 UUID agentID = sp.ControllingClient.AgentId; 297 RefetchFriends(sp.ControllingClient);
267 UpdateFriendsCache(agentID);
268 } 298 }
269 299
270 private void OnClientLogin(IClientAPI client) 300 private void OnClientLogin(IClientAPI client)
271 { 301 {
272 UUID agentID = client.AgentId; 302 UUID agentID = client.AgentId;
273 303
304 //m_log.DebugFormat("[XXX]: OnClientLogin!");
274 // Inform the friends that this user is online 305 // Inform the friends that this user is online
275 StatusChange(agentID, true); 306 StatusChange(agentID, true);
276 307
@@ -279,7 +310,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
279 m_NeedsListOfFriends.Add(agentID); 310 m_NeedsListOfFriends.Add(agentID);
280 } 311 }
281 312
282 public void SendFriendsOnlineIfNeeded(IClientAPI client) 313 public virtual bool SendFriendsOnlineIfNeeded(IClientAPI client)
283 { 314 {
284 UUID agentID = client.AgentId; 315 UUID agentID = client.AgentId;
285 316
@@ -287,7 +318,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
287 lock (m_NeedsListOfFriends) 318 lock (m_NeedsListOfFriends)
288 { 319 {
289 if (!m_NeedsListOfFriends.Remove(agentID)) 320 if (!m_NeedsListOfFriends.Remove(agentID))
290 return; 321 return false;
291 } 322 }
292 323
293 // Send the friends online 324 // Send the friends online
@@ -313,10 +344,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
313 foreach (string fid in outstanding) 344 foreach (string fid in outstanding)
314 { 345 {
315 UUID fromAgentID; 346 UUID fromAgentID;
316 if (!UUID.TryParse(fid, out fromAgentID)) 347 string firstname = "Unknown", lastname = "User";
348 if (!GetAgentInfo(client.Scene.RegionInfo.ScopeID, fid, out fromAgentID, out firstname, out lastname))
349 {
350 m_log.DebugFormat("[FRIENDS MODULE]: skipping malformed friend {0}", fid);
317 continue; 351 continue;
318 352 }
319 UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(client.Scene.RegionInfo.ScopeID, fromAgentID);
320 353
321 PresenceInfo presence = null; 354 PresenceInfo presence = null;
322 PresenceInfo[] presences = PresenceService.GetAgents(new string[] { fid }); 355 PresenceInfo[] presences = PresenceService.GetAgents(new string[] { fid });
@@ -326,13 +359,37 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
326 im.offline = 0; 359 im.offline = 0;
327 360
328 im.fromAgentID = fromAgentID.Guid; 361 im.fromAgentID = fromAgentID.Guid;
329 im.fromAgentName = account.FirstName + " " + account.LastName; 362 im.fromAgentName = firstname + " " + lastname;
330 im.offline = (byte)((presence == null) ? 1 : 0); 363 im.offline = (byte)((presence == null) ? 1 : 0);
331 im.imSessionID = im.fromAgentID; 364 im.imSessionID = im.fromAgentID;
365 im.message = FriendshipMessage(fid);
332 366
333 // Finally 367 // Finally
334 LocalFriendshipOffered(agentID, im); 368 LocalFriendshipOffered(agentID, im);
335 } 369 }
370
371 return true;
372 }
373
374 protected virtual string FriendshipMessage(string friendID)
375 {
376 return "Will you be my friend?";
377 }
378
379 protected virtual bool GetAgentInfo(UUID scopeID, string fid, out UUID agentID, out string first, out string last)
380 {
381 first = "Unknown"; last = "User";
382 if (!UUID.TryParse(fid, out agentID))
383 return false;
384
385 UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(scopeID, agentID);
386 if (account != null)
387 {
388 first = account.FirstName;
389 last = account.LastName;
390 }
391
392 return true;
336 } 393 }
337 394
338 List<UUID> GetOnlineFriends(UUID userID) 395 List<UUID> GetOnlineFriends(UUID userID)
@@ -348,19 +405,22 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
348 } 405 }
349 406
350 if (friendList.Count > 0) 407 if (friendList.Count > 0)
351 { 408 GetOnlineFriends(userID, friendList, online);
352 PresenceInfo[] presence = PresenceService.GetAgents(friendList.ToArray());
353 foreach (PresenceInfo pi in presence)
354 {
355 UUID presenceID;
356 if (UUID.TryParse(pi.UserID, out presenceID))
357 online.Add(presenceID);
358 }
359 }
360 409
361 return online; 410 return online;
362 } 411 }
363 412
413 protected virtual void GetOnlineFriends(UUID userID, List<string> friendList, /*collector*/ List<UUID> online)
414 {
415 PresenceInfo[] presence = PresenceService.GetAgents(friendList.ToArray());
416 foreach (PresenceInfo pi in presence)
417 {
418 UUID presenceID;
419 if (UUID.TryParse(pi.UserID, out presenceID))
420 online.Add(presenceID);
421 }
422 }
423
364 /// <summary> 424 /// <summary>
365 /// Find the client for a ID 425 /// Find the client for a ID
366 /// </summary> 426 /// </summary>
@@ -415,51 +475,51 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
415 Util.FireAndForget( 475 Util.FireAndForget(
416 delegate 476 delegate
417 { 477 {
418 foreach (FriendInfo fi in friendList) 478 m_log.DebugFormat("[FRIENDS MODULE]: Notifying {0} friends", friendList.Count);
419 { 479 // Notify about this user status
420 //m_log.DebugFormat("[FRIENDS]: Notifying {0}", fi.PrincipalID); 480 StatusNotify(friendList, agentID, online);
421 // Notify about this user status
422 StatusNotify(fi, agentID, online);
423 }
424 } 481 }
425 ); 482 );
426 } 483 }
427 } 484 }
428 485
429 private void StatusNotify(FriendInfo friend, UUID userID, bool online) 486 protected virtual void StatusNotify(List<FriendInfo> friendList, UUID userID, bool online)
430 { 487 {
431 UUID friendID; 488 foreach (FriendInfo friend in friendList)
432 if (UUID.TryParse(friend.Friend, out friendID))
433 { 489 {
434 // Try local 490 UUID friendID;
435 if (LocalStatusNotification(userID, friendID, online)) 491 if (UUID.TryParse(friend.Friend, out friendID))
436 return;
437
438 // The friend is not here [as root]. Let's forward.
439 PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { friendID.ToString() });
440 if (friendSessions != null && friendSessions.Length > 0)
441 { 492 {
442 PresenceInfo friendSession = null; 493 // Try local
443 foreach (PresenceInfo pinfo in friendSessions) 494 if (LocalStatusNotification(userID, friendID, online))
444 if (pinfo.RegionID != UUID.Zero) // let's guard against sessions-gone-bad 495 return;
445 {
446 friendSession = pinfo;
447 break;
448 }
449 496
450 if (friendSession != null) 497 // The friend is not here [as root]. Let's forward.
498 PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { friendID.ToString() });
499 if (friendSessions != null && friendSessions.Length > 0)
451 { 500 {
452 GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID); 501 PresenceInfo friendSession = null;
453 //m_log.DebugFormat("[FRIENDS]: Remote Notify to region {0}", region.RegionName); 502 foreach (PresenceInfo pinfo in friendSessions)
454 m_FriendsSimConnector.StatusNotify(region, userID, friendID, online); 503 if (pinfo.RegionID != UUID.Zero) // let's guard against sessions-gone-bad
504 {
505 friendSession = pinfo;
506 break;
507 }
508
509 if (friendSession != null)
510 {
511 GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID);
512 //m_log.DebugFormat("[FRIENDS]: Remote Notify to region {0}", region.RegionName);
513 m_FriendsSimConnector.StatusNotify(region, userID, friendID, online);
514 }
455 } 515 }
456 }
457 516
458 // Friend is not online. Ignore. 517 // Friend is not online. Ignore.
459 } 518 }
460 else 519 else
461 { 520 {
462 m_log.WarnFormat("[FRIENDS]: Error parsing friend ID {0}", friend.Friend); 521 m_log.WarnFormat("[FRIENDS]: Error parsing friend ID {0}", friend.Friend);
522 }
463 } 523 }
464 } 524 }
465 525
@@ -475,7 +535,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
475 535
476 // This user wants to be friends with the other user. 536 // This user wants to be friends with the other user.
477 // Let's add the relation backwards, in case the other is not online 537 // Let's add the relation backwards, in case the other is not online
478 FriendsService.StoreFriend(friendID, principalID.ToString(), 0); 538 StoreBackwards(friendID, principalID);
479 539
480 // Now let's ask the other user to be friends with this user 540 // Now let's ask the other user to be friends with this user
481 ForwardFriendshipOffer(principalID, friendID, im); 541 ForwardFriendshipOffer(principalID, friendID, im);
@@ -487,11 +547,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
487 // !!!!!!!! This is a hack so that we don't have to keep state (transactionID/imSessionID) 547 // !!!!!!!! This is a hack so that we don't have to keep state (transactionID/imSessionID)
488 // We stick this agent's ID as imSession, so that it's directly available on the receiving end 548 // We stick this agent's ID as imSession, so that it's directly available on the receiving end
489 im.imSessionID = im.fromAgentID; 549 im.imSessionID = im.fromAgentID;
550 im.fromAgentName = GetFriendshipRequesterName(agentID);
490 551
491 // Try the local sim 552 // Try the local sim
492 UserAccount account = UserAccountService.GetUserAccount(UUID.Zero, agentID);
493 im.fromAgentName = (account == null) ? "Unknown" : account.FirstName + " " + account.LastName;
494
495 if (LocalFriendshipOffered(friendID, im)) 553 if (LocalFriendshipOffered(friendID, im))
496 return; 554 return;
497 555
@@ -509,12 +567,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
509 // If the prospective friend is not online, he'll get the message upon login. 567 // If the prospective friend is not online, he'll get the message upon login.
510 } 568 }
511 569
570 protected virtual string GetFriendshipRequesterName(UUID agentID)
571 {
572 UserAccount account = UserAccountService.GetUserAccount(UUID.Zero, agentID);
573 return (account == null) ? "Unknown" : account.FirstName + " " + account.LastName;
574 }
575
512 private void OnApproveFriendRequest(IClientAPI client, UUID agentID, UUID friendID, List<UUID> callingCardFolders) 576 private void OnApproveFriendRequest(IClientAPI client, UUID agentID, UUID friendID, List<UUID> callingCardFolders)
513 { 577 {
514 m_log.DebugFormat("[FRIENDS]: {0} accepted friendship from {1}", agentID, friendID); 578 m_log.DebugFormat("[FRIENDS]: {0} accepted friendship from {1}", agentID, friendID);
515 579
516 FriendsService.StoreFriend(agentID, friendID.ToString(), 1); 580 StoreFriendships(agentID, friendID);
517 FriendsService.StoreFriend(friendID, agentID.ToString(), 1);
518 581
519 ICallingCardModule ccm = client.Scene.RequestModuleInterface<ICallingCardModule>(); 582 ICallingCardModule ccm = client.Scene.RequestModuleInterface<ICallingCardModule>();
520 if (ccm != null) 583 if (ccm != null)
@@ -523,7 +586,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
523 } 586 }
524 587
525 // Update the local cache 588 // Update the local cache
526 UpdateFriendsCache(agentID); 589 RefetchFriends(client);
527 590
528 // 591 //
529 // Notify the friend 592 // Notify the friend
@@ -554,8 +617,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
554 { 617 {
555 m_log.DebugFormat("[FRIENDS]: {0} denied friendship to {1}", agentID, friendID); 618 m_log.DebugFormat("[FRIENDS]: {0} denied friendship to {1}", agentID, friendID);
556 619
557 FriendsService.Delete(agentID, friendID.ToString()); 620 DeleteFriendship(agentID, friendID);
558 FriendsService.Delete(friendID, agentID.ToString());
559 621
560 // 622 //
561 // Notify the friend 623 // Notify the friend
@@ -582,11 +644,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
582 644
583 private void OnTerminateFriendship(IClientAPI client, UUID agentID, UUID exfriendID) 645 private void OnTerminateFriendship(IClientAPI client, UUID agentID, UUID exfriendID)
584 { 646 {
585 FriendsService.Delete(agentID, exfriendID.ToString()); 647 if (!DeleteFriendship(agentID, exfriendID))
586 FriendsService.Delete(exfriendID, agentID.ToString()); 648 client.SendAlertMessage("Unable to terminate friendship on this sim.");
587 649
588 // Update local cache 650 // Update local cache
589 UpdateFriendsCache(agentID); 651 RefetchFriends(client);
590 652
591 client.SendTerminateFriend(exfriendID); 653 client.SendTerminateFriend(exfriendID);
592 654
@@ -612,23 +674,25 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
612 674
613 private void OnGrantUserRights(IClientAPI remoteClient, UUID requester, UUID target, int rights) 675 private void OnGrantUserRights(IClientAPI remoteClient, UUID requester, UUID target, int rights)
614 { 676 {
677 m_log.DebugFormat("[FRIENDS MODULE]: User {0} changing rights to {1} for friend {2}", requester, rights, target);
678
615 FriendInfo[] friends = GetFriends(remoteClient.AgentId); 679 FriendInfo[] friends = GetFriends(remoteClient.AgentId);
616 if (friends.Length == 0) 680 if (friends.Length == 0)
681 {
617 return; 682 return;
683 }
618 684
619 m_log.DebugFormat("[FRIENDS MODULE]: User {0} changing rights to {1} for friend {2}", requester, rights, target);
620 // Let's find the friend in this user's friend list 685 // Let's find the friend in this user's friend list
621 FriendInfo friend = null; 686 FriendInfo friend = GetFriend(friends, target);
622 foreach (FriendInfo fi in friends)
623 {
624 if (fi.Friend == target.ToString())
625 friend = fi;
626 }
627 687
628 if (friend != null) // Found it 688 if (friend != null) // Found it
629 { 689 {
630 // Store it on the DB 690 // Store it on the DB
631 FriendsService.StoreFriend(requester, target.ToString(), rights); 691 if (!StoreRights(requester, target, rights))
692 {
693 remoteClient.SendAlertMessage("Unable to grant rights.");
694 return;
695 }
632 696
633 // Store it in the local cache 697 // Store it in the local cache
634 int myFlags = friend.MyFlags; 698 int myFlags = friend.MyFlags;
@@ -658,6 +722,18 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
658 } 722 }
659 } 723 }
660 } 724 }
725 else
726 m_log.DebugFormat("[FRIENDS MODULE]: friend {0} not found for {1}", target, requester);
727 }
728
729 protected virtual FriendInfo GetFriend(FriendInfo[] friends, UUID friendID)
730 {
731 foreach (FriendInfo fi in friends)
732 {
733 if (fi.Friend == friendID.ToString())
734 return fi;
735 }
736 return null;
661 } 737 }
662 738
663 #region Local 739 #region Local
@@ -693,7 +769,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
693 769
694 770
695 // Update the local cache 771 // Update the local cache
696 UpdateFriendsCache(friendID); 772 RefetchFriends(friendClient);
697 773
698 // we're done 774 // we're done
699 return true; 775 return true;
@@ -726,7 +802,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
726 // the friend in this sim as root agent 802 // the friend in this sim as root agent
727 friendClient.SendTerminateFriend(exfriendID); 803 friendClient.SendTerminateFriend(exfriendID);
728 // update local cache 804 // update local cache
729 UpdateFriendsCache(exfriendID); 805 RefetchFriends(friendClient);
730 // we're done 806 // we're done
731 return true; 807 return true;
732 } 808 }
@@ -756,15 +832,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
756 } 832 }
757 833
758 // Update local cache 834 // Update local cache
759 lock (m_Friends) 835 UpdateLocalCache(userID, friendID, rights);
760 {
761 FriendInfo[] friends = GetFriends(friendID);
762 foreach (FriendInfo finfo in friends)
763 {
764 if (finfo.Friend == userID.ToString())
765 finfo.TheirFlags = rights;
766 }
767 }
768 836
769 return true; 837 return true;
770 } 838 }
@@ -775,10 +843,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
775 843
776 public bool LocalStatusNotification(UUID userID, UUID friendID, bool online) 844 public bool LocalStatusNotification(UUID userID, UUID friendID, bool online)
777 { 845 {
846 m_log.DebugFormat("[FRIENDS]: Local Status Notify {0} that user {1} is {2}", friendID, userID, online);
778 IClientAPI friendClient = LocateClientObject(friendID); 847 IClientAPI friendClient = LocateClientObject(friendID);
779 if (friendClient != null) 848 if (friendClient != null)
780 { 849 {
781 //m_log.DebugFormat("[FRIENDS]: Local Status Notify {0} that user {1} is {2}", friendID, userID, online);
782 // the friend in this sim as root agent 850 // the friend in this sim as root agent
783 if (online) 851 if (online)
784 friendClient.SendAgentOnline(new UUID[] { userID }); 852 friendClient.SendAgentOnline(new UUID[] { userID });
@@ -793,7 +861,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
793 861
794 #endregion 862 #endregion
795 863
796 private FriendInfo[] GetFriends(UUID agentID) 864 #region Get / Set friends in several flavours
865 /// <summary>
866 /// Get friends from local cache only
867 /// </summary>
868 /// <param name="agentID"></param>
869 /// <returns></returns>
870 protected FriendInfo[] GetFriends(UUID agentID)
797 { 871 {
798 UserFriendData friendsData; 872 UserFriendData friendsData;
799 873
@@ -806,14 +880,63 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
806 return EMPTY_FRIENDS; 880 return EMPTY_FRIENDS;
807 } 881 }
808 882
809 private void UpdateFriendsCache(UUID agentID) 883 /// <summary>
884 /// Update loca cache only
885 /// </summary>
886 /// <param name="userID"></param>
887 /// <param name="friendID"></param>
888 /// <param name="rights"></param>
889 protected void UpdateLocalCache(UUID userID, UUID friendID, int rights)
890 {
891 // Update local cache
892 lock (m_Friends)
893 {
894 FriendInfo[] friends = GetFriends(friendID);
895 FriendInfo finfo = GetFriend(friends, userID);
896 finfo.TheirFlags = rights;
897 }
898 }
899
900 protected virtual FriendInfo[] GetFriendsFromService(IClientAPI client)
901 {
902 return FriendsService.GetFriends(client.AgentId);
903 }
904
905 private void RefetchFriends(IClientAPI client)
810 { 906 {
907 UUID agentID = client.AgentId;
811 lock (m_Friends) 908 lock (m_Friends)
812 { 909 {
813 UserFriendData friendsData; 910 UserFriendData friendsData;
814 if (m_Friends.TryGetValue(agentID, out friendsData)) 911 if (m_Friends.TryGetValue(agentID, out friendsData))
815 friendsData.Friends = FriendsService.GetFriends(agentID); 912 friendsData.Friends = GetFriendsFromService(client);
816 } 913 }
817 } 914 }
915
916 protected virtual bool StoreRights(UUID agentID, UUID friendID, int rights)
917 {
918 FriendsService.StoreFriend(agentID.ToString(), friendID.ToString(), rights);
919 return true;
920 }
921
922 protected virtual void StoreBackwards(UUID friendID, UUID agentID)
923 {
924 FriendsService.StoreFriend(friendID.ToString(), agentID.ToString(), 0);
925 }
926
927 protected virtual void StoreFriendships(UUID agentID, UUID friendID)
928 {
929 FriendsService.StoreFriend(agentID.ToString(), friendID.ToString(), 1);
930 FriendsService.StoreFriend(friendID.ToString(), agentID.ToString(), 1);
931 }
932
933 protected virtual bool DeleteFriendship(UUID agentID, UUID exfriendID)
934 {
935 FriendsService.Delete(agentID, exfriendID.ToString());
936 FriendsService.Delete(exfriendID, agentID.ToString());
937 return true;
938 }
939
940 #endregion
818 } 941 }
819} 942}
diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs
new file mode 100644
index 0000000..dda67f9
--- /dev/null
+++ b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs
@@ -0,0 +1,623 @@
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;
32using System.Threading;
33
34using log4net;
35using Nini.Config;
36using Nwc.XmlRpc;
37using Mono.Addins;
38using OpenMetaverse;
39using OpenSim.Framework;
40using OpenSim.Region.Framework.Interfaces;
41using OpenSim.Region.Framework.Scenes;
42using OpenSim.Services.Interfaces;
43using OpenSim.Services.Connectors.Hypergrid;
44using FriendInfo = OpenSim.Services.Interfaces.FriendInfo;
45using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo;
46using GridRegion = OpenSim.Services.Interfaces.GridRegion;
47
48namespace OpenSim.Region.CoreModules.Avatar.Friends
49{
50 public class HGFriendsModule : FriendsModule, ISharedRegionModule, IFriendsModule, IFriendsSimConnector
51 {
52 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
53
54 #region ISharedRegionModule
55 public override string Name
56 {
57 get { return "HGFriendsModule"; }
58 }
59
60 public override void AddRegion(Scene scene)
61 {
62 if (!m_Enabled)
63 return;
64
65 base.AddRegion(scene);
66 scene.RegisterModuleInterface<IFriendsSimConnector>(this);
67 }
68
69 #endregion
70
71 #region IFriendsSimConnector
72
73 /// <summary>
74 /// Notify the user that the friend's status changed
75 /// </summary>
76 /// <param name="userID">user to be notified</param>
77 /// <param name="friendID">friend whose status changed</param>
78 /// <param name="online">status</param>
79 /// <returns></returns>
80 public bool StatusNotify(UUID friendID, UUID userID, bool online)
81 {
82 return LocalStatusNotification(friendID, userID, online);
83 }
84
85 #endregion
86
87 protected override bool FetchFriendslist(IClientAPI client)
88 {
89 if (base.FetchFriendslist(client))
90 {
91 UUID agentID = client.AgentId;
92 // we do this only for the root agent
93 if (m_Friends[agentID].Refcount == 1)
94 {
95 // We need to preload the user management cache with the names
96 // of foreign friends, just like we do with SOPs' creators
97 foreach (FriendInfo finfo in m_Friends[agentID].Friends)
98 {
99 if (finfo.TheirFlags != -1)
100 {
101 UUID id;
102 if (!UUID.TryParse(finfo.Friend, out id))
103 {
104 string url = string.Empty, first = string.Empty, last = string.Empty, tmp = string.Empty;
105 if (Util.ParseUniversalUserIdentifier(finfo.Friend, out id, out url, out first, out last, out tmp))
106 {
107 IUserManagement uMan = m_Scenes[0].RequestModuleInterface<IUserManagement>();
108 uMan.AddUser(id, url + ";" + first + " " + last);
109 }
110 }
111 }
112 }
113 return true;
114 }
115 }
116 return false;
117 }
118
119 public override bool SendFriendsOnlineIfNeeded(IClientAPI client)
120 {
121 if (base.SendFriendsOnlineIfNeeded(client))
122 {
123 AgentCircuitData aCircuit = ((Scene)client.Scene).AuthenticateHandler.GetAgentCircuitData(client.AgentId);
124 if (aCircuit != null && (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0)
125 {
126 UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(client.Scene.RegionInfo.ScopeID, client.AgentId);
127 if (account == null) // foreign
128 {
129 FriendInfo[] friends = GetFriends(client.AgentId);
130 foreach (FriendInfo f in friends)
131 {
132 client.SendChangeUserRights(new UUID(f.Friend), client.AgentId, f.TheirFlags);
133 }
134 }
135 }
136 }
137 return false;
138 }
139
140 protected override void GetOnlineFriends(UUID userID, List<string> friendList, /*collector*/ List<UUID> online)
141 {
142 List<string> fList = new List<string>();
143 foreach (string s in friendList)
144 fList.Add(s.Substring(0, 36));
145
146 PresenceInfo[] presence = PresenceService.GetAgents(fList.ToArray());
147 foreach (PresenceInfo pi in presence)
148 {
149 UUID presenceID;
150 if (UUID.TryParse(pi.UserID, out presenceID))
151 online.Add(presenceID);
152 }
153 }
154
155 //protected override void GetOnlineFriends(UUID userID, List<string> friendList, /*collector*/ List<UUID> online)
156 //{
157 // // Let's single out the UUIs
158 // List<string> localFriends = new List<string>();
159 // List<string> foreignFriends = new List<string>();
160 // string tmp = string.Empty;
161
162 // foreach (string s in friendList)
163 // {
164 // UUID id;
165 // if (UUID.TryParse(s, out id))
166 // localFriends.Add(s);
167 // else if (Util.ParseUniversalUserIdentifier(s, out id, out tmp, out tmp, out tmp, out tmp))
168 // {
169 // foreignFriends.Add(s);
170 // // add it here too, who knows maybe the foreign friends happens to be on this grid
171 // localFriends.Add(id.ToString());
172 // }
173 // }
174
175 // // OK, see who's present on this grid
176 // List<string> toBeRemoved = new List<string>();
177 // PresenceInfo[] presence = PresenceService.GetAgents(localFriends.ToArray());
178 // foreach (PresenceInfo pi in presence)
179 // {
180 // UUID presenceID;
181 // if (UUID.TryParse(pi.UserID, out presenceID))
182 // {
183 // online.Add(presenceID);
184 // foreach (string s in foreignFriends)
185 // if (s.StartsWith(pi.UserID))
186 // toBeRemoved.Add(s);
187 // }
188 // }
189
190 // foreach (string s in toBeRemoved)
191 // foreignFriends.Remove(s);
192
193 // // OK, let's send this up the stack, and leave a closure here
194 // // collecting online friends in other grids
195 // Util.FireAndForget(delegate { CollectOnlineFriendsElsewhere(userID, foreignFriends); });
196
197 //}
198
199 //private void CollectOnlineFriendsElsewhere(UUID userID, List<string> foreignFriends)
200 //{
201 // // let's divide the friends on a per-domain basis
202 // Dictionary<string, List<string>> friendsPerDomain = new Dictionary<string, List<string>>();
203 // foreach (string friend in foreignFriends)
204 // {
205 // UUID friendID;
206 // if (!UUID.TryParse(friend, out friendID))
207 // {
208 // // it's a foreign friend
209 // string url = string.Empty, tmp = string.Empty;
210 // if (Util.ParseUniversalUserIdentifier(friend, out friendID, out url, out tmp, out tmp, out tmp))
211 // {
212 // if (!friendsPerDomain.ContainsKey(url))
213 // friendsPerDomain[url] = new List<string>();
214 // friendsPerDomain[url].Add(friend);
215 // }
216 // }
217 // }
218
219 // // Now, call those worlds
220
221 // foreach (KeyValuePair<string, List<string>> kvp in friendsPerDomain)
222 // {
223 // List<string> ids = new List<string>();
224 // foreach (string f in kvp.Value)
225 // ids.Add(f);
226 // UserAgentServiceConnector uConn = new UserAgentServiceConnector(kvp.Key);
227 // List<UUID> online = uConn.GetOnlineFriends(userID, ids);
228 // // Finally send the notifications to the user
229 // // this whole process may take a while, so let's check at every
230 // // iteration that the user is still here
231 // IClientAPI client = LocateClientObject(userID);
232 // if (client != null)
233 // client.SendAgentOnline(online.ToArray());
234 // else
235 // break;
236 // }
237
238 //}
239
240 protected override void StatusNotify(List<FriendInfo> friendList, UUID userID, bool online)
241 {
242 // First, let's divide the friends on a per-domain basis
243 Dictionary<string, List<FriendInfo>> friendsPerDomain = new Dictionary<string, List<FriendInfo>>();
244 foreach (FriendInfo friend in friendList)
245 {
246 UUID friendID;
247 if (UUID.TryParse(friend.Friend, out friendID))
248 {
249 if (!friendsPerDomain.ContainsKey("local"))
250 friendsPerDomain["local"] = new List<FriendInfo>();
251 friendsPerDomain["local"].Add(friend);
252 }
253 else
254 {
255 // it's a foreign friend
256 string url = string.Empty, tmp = string.Empty;
257 if (Util.ParseUniversalUserIdentifier(friend.Friend, out friendID, out url, out tmp, out tmp, out tmp))
258 {
259 // Let's try our luck in the local sim. Who knows, maybe it's here
260 if (LocalStatusNotification(userID, friendID, online))
261 continue;
262
263 if (!friendsPerDomain.ContainsKey(url))
264 friendsPerDomain[url] = new List<FriendInfo>();
265 friendsPerDomain[url].Add(friend);
266 }
267 }
268 }
269
270 // For the local friends, just call the base method
271 // Let's do this first of all
272 if (friendsPerDomain.ContainsKey("local"))
273 base.StatusNotify(friendsPerDomain["local"], userID, online);
274
275 foreach (KeyValuePair<string, List<FriendInfo>> kvp in friendsPerDomain)
276 {
277 if (kvp.Key != "local")
278 {
279 // For the others, call the user agent service
280 List<string> ids = new List<string>();
281 foreach (FriendInfo f in kvp.Value)
282 ids.Add(f.Friend);
283 UserAgentServiceConnector uConn = new UserAgentServiceConnector(kvp.Key);
284 List<UUID> friendsOnline = uConn.StatusNotification(ids, userID, online);
285
286 if (online && friendsOnline.Count > 0)
287 {
288 IClientAPI client = LocateClientObject(userID);
289 if (client != null)
290 client.SendAgentOnline(friendsOnline.ToArray());
291 }
292 }
293 }
294 }
295
296 protected override bool GetAgentInfo(UUID scopeID, string fid, out UUID agentID, out string first, out string last)
297 {
298 first = "Unknown"; last = "User";
299 if (base.GetAgentInfo(scopeID, fid, out agentID, out first, out last))
300 return true;
301
302 // fid is not a UUID...
303 string url = string.Empty, tmp = string.Empty;
304 if (Util.ParseUniversalUserIdentifier(fid, out agentID, out url, out first, out last, out tmp))
305 {
306 IUserManagement userMan = m_Scenes[0].RequestModuleInterface<IUserManagement>();
307 userMan.AddUser(agentID, first, last, url);
308
309 return true;
310 }
311 return false;
312 }
313
314 protected override string GetFriendshipRequesterName(UUID agentID)
315 {
316 // For the time being we assume that HG friendship requests can only happen
317 // when avies are on the same region.
318 IClientAPI client = LocateClientObject(agentID);
319 if (client != null)
320 return client.FirstName + " " + client.LastName;
321 else
322 return base.GetFriendshipRequesterName(agentID);
323 }
324
325 protected override string FriendshipMessage(string friendID)
326 {
327 UUID id;
328 if (UUID.TryParse(friendID, out id))
329 return base.FriendshipMessage(friendID);
330
331 return "Please confirm this friendship you made while you were away.";
332 }
333
334 protected override FriendInfo GetFriend(FriendInfo[] friends, UUID friendID)
335 {
336 foreach (FriendInfo fi in friends)
337 {
338 if (fi.Friend.StartsWith(friendID.ToString()))
339 return fi;
340 }
341 return null;
342 }
343
344
345 protected override FriendInfo[] GetFriendsFromService(IClientAPI client)
346 {
347 UserAccount account1 = UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, client.AgentId);
348 if (account1 != null)
349 return base.GetFriendsFromService(client);
350
351 FriendInfo[] finfos = new FriendInfo[0];
352 // Foreigner
353 AgentCircuitData agentClientCircuit = ((Scene)(client.Scene)).AuthenticateHandler.GetAgentCircuitData(client.CircuitCode);
354 if (agentClientCircuit != null)
355 {
356 string agentUUI = Util.ProduceUserUniversalIdentifier(agentClientCircuit);
357
358 finfos = FriendsService.GetFriends(agentUUI);
359 m_log.DebugFormat("[HGFRIENDS MODULE]: Fetched {0} local friends for visitor {1}", finfos.Length, agentUUI);
360 }
361 return finfos;
362 }
363
364 protected override bool StoreRights(UUID agentID, UUID friendID, int rights)
365 {
366 UserAccount account1 = UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, agentID);
367 UserAccount account2 = UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, friendID);
368 // Are they both local users?
369 if (account1 != null && account2 != null)
370 {
371 // local grid users
372 return base.StoreRights(agentID, friendID, rights);
373 }
374
375 if (account1 != null) // agent is local, friend is foreigner
376 {
377 FriendInfo[] finfos = GetFriends(agentID);
378 FriendInfo finfo = GetFriend(finfos, friendID);
379 if (finfo != null)
380 {
381 FriendsService.StoreFriend(agentID.ToString(), finfo.Friend, rights);
382 return true;
383 }
384 }
385
386 if (account2 != null) // agent is foreigner, friend is local
387 {
388 string agentUUI = GetUUI(friendID, agentID);
389 if (agentUUI != string.Empty)
390 {
391 FriendsService.StoreFriend(agentUUI, friendID.ToString(), rights);
392 return true;
393 }
394 }
395
396 return false;
397
398 }
399
400 protected override void StoreBackwards(UUID friendID, UUID agentID)
401 {
402 UserAccount account1 = UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, agentID);
403 UserAccount account2 = UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, friendID);
404 // Are they both local users?
405 if (account1 != null && account2 != null)
406 {
407 // local grid users
408 m_log.DebugFormat("[HGFRIENDS MODULE]: Users are both local");
409 base.StoreBackwards(friendID, agentID);
410 return;
411 }
412
413 // no provision for this temporary friendship state
414 //FriendsService.StoreFriend(friendID.ToString(), agentID.ToString(), 0);
415 }
416
417 protected override void StoreFriendships(UUID agentID, UUID friendID)
418 {
419 UserAccount agentAccount = UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, agentID);
420 UserAccount friendAccount = UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, friendID);
421 // Are they both local users?
422 if (agentAccount != null && friendAccount != null)
423 {
424 // local grid users
425 m_log.DebugFormat("[HGFRIENDS MODULE]: Users are both local");
426 base.StoreFriendships(agentID, friendID);
427 return;
428 }
429
430 // ok, at least one of them is foreigner, let's get their data
431 IClientAPI agentClient = LocateClientObject(agentID);
432 IClientAPI friendClient = LocateClientObject(friendID);
433 AgentCircuitData agentClientCircuit = null;
434 AgentCircuitData friendClientCircuit = null;
435 string agentUUI = string.Empty;
436 string friendUUI = string.Empty;
437 string agentFriendService = string.Empty;
438 string friendFriendService = string.Empty;
439
440 if (agentClient != null)
441 {
442 agentClientCircuit = ((Scene)(agentClient.Scene)).AuthenticateHandler.GetAgentCircuitData(agentClient.CircuitCode);
443 agentUUI = Util.ProduceUserUniversalIdentifier(agentClientCircuit);
444 agentFriendService = agentClientCircuit.ServiceURLs["FriendsServerURI"].ToString();
445 }
446 if (friendClient != null)
447 {
448 friendClientCircuit = ((Scene)(friendClient.Scene)).AuthenticateHandler.GetAgentCircuitData(friendClient.CircuitCode);
449 friendUUI = Util.ProduceUserUniversalIdentifier(friendClientCircuit);
450 friendFriendService = friendClientCircuit.ServiceURLs["FriendsServerURI"].ToString();
451 }
452
453 m_log.DebugFormat("[HGFRIENDS MODULE] HG Friendship! thisUUI={0}; friendUUI={1}; foreignThisFriendService={2}; foreignFriendFriendService={3}",
454 agentUUI, friendUUI, agentFriendService, friendFriendService);
455
456 // Generate a random 8-character hex number that will sign this friendship
457 string secret = UUID.Random().ToString().Substring(0, 8);
458
459 if (agentAccount != null) // agent is local, 'friend' is foreigner
460 {
461 // This may happen when the agent returned home, in which case the friend is not there
462 // We need to look for its information in the friends list itself
463 bool confirming = false;
464 if (friendUUI == string.Empty)
465 {
466 FriendInfo[] finfos = GetFriends(agentID);
467 foreach (FriendInfo finfo in finfos)
468 {
469 if (finfo.TheirFlags == -1)
470 {
471 if (finfo.Friend.StartsWith(friendID.ToString()))
472 {
473 friendUUI = finfo.Friend;
474 confirming = true;
475 }
476 }
477 }
478 }
479
480 // If it's confirming the friendship, we already have the full friendUUI with the secret
481 string theFriendUUID = confirming ? friendUUI : friendUUI + ";" + secret;
482
483 // store in the local friends service a reference to the foreign friend
484 FriendsService.StoreFriend(agentID.ToString(), theFriendUUID, 1);
485 // and also the converse
486 FriendsService.StoreFriend(theFriendUUID, agentID.ToString(), 1);
487
488 if (!confirming && friendClientCircuit != null)
489 {
490 // store in the foreign friends service a reference to the local agent
491 HGFriendsServicesConnector friendsConn = new HGFriendsServicesConnector(friendFriendService, friendClientCircuit.SessionID, friendClientCircuit.ServiceSessionID);
492 friendsConn.NewFriendship(friendID, agentUUI + ";" + secret);
493 }
494 }
495 else if (friendAccount != null) // 'friend' is local, agent is foreigner
496 {
497 // store in the local friends service a reference to the foreign agent
498 FriendsService.StoreFriend(friendID.ToString(), agentUUI + ";" + secret, 1);
499 // and also the converse
500 FriendsService.StoreFriend(agentUUI + ";" + secret, friendID.ToString(), 1);
501
502 if (agentClientCircuit != null)
503 {
504 // store in the foreign friends service a reference to the local agent
505 HGFriendsServicesConnector friendsConn = new HGFriendsServicesConnector(agentFriendService, agentClientCircuit.SessionID, agentClientCircuit.ServiceSessionID);
506 friendsConn.NewFriendship(agentID, friendUUI + ";" + secret);
507 }
508 }
509 else // They're both foreigners!
510 {
511 HGFriendsServicesConnector friendsConn;
512 if (agentClientCircuit != null)
513 {
514 friendsConn = new HGFriendsServicesConnector(agentFriendService, agentClientCircuit.SessionID, agentClientCircuit.ServiceSessionID);
515 friendsConn.NewFriendship(agentID, friendUUI + ";" + secret);
516 }
517 if (friendClientCircuit != null)
518 {
519 friendsConn = new HGFriendsServicesConnector(friendFriendService, friendClientCircuit.SessionID, friendClientCircuit.ServiceSessionID);
520 friendsConn.NewFriendship(friendID, agentUUI + ";" + secret);
521 }
522 }
523 // my brain hurts now
524 }
525
526 protected override bool DeleteFriendship(UUID agentID, UUID exfriendID)
527 {
528 UserAccount agentAccount = UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, agentID);
529 UserAccount friendAccount = UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, exfriendID);
530 // Are they both local users?
531 if (agentAccount != null && friendAccount != null)
532 {
533 // local grid users
534 return base.DeleteFriendship(agentID, exfriendID);
535 }
536
537 // ok, at least one of them is foreigner, let's get their data
538 string agentUUI = string.Empty;
539 string friendUUI = string.Empty;
540
541 if (agentAccount != null) // agent is local, 'friend' is foreigner
542 {
543 // We need to look for its information in the friends list itself
544 FriendInfo[] finfos = GetFriends(agentID);
545 FriendInfo finfo = GetFriend(finfos, exfriendID);
546 if (finfo != null)
547 {
548 friendUUI = finfo.Friend;
549
550 // delete in the local friends service the reference to the foreign friend
551 FriendsService.Delete(agentID, friendUUI);
552 // and also the converse
553 FriendsService.Delete(friendUUI, agentID.ToString());
554
555 // notify the exfriend's service
556 Util.FireAndForget(delegate { Delete(exfriendID, agentID, friendUUI); });
557
558 m_log.DebugFormat("[HGFRIENDS MODULE]: {0} terminated {1}", agentID, friendUUI);
559 return true;
560 }
561 }
562 else if (friendAccount != null) // agent is foreigner, 'friend' is local
563 {
564 agentUUI = GetUUI(exfriendID, agentID);
565
566 if (agentUUI != string.Empty)
567 {
568 // delete in the local friends service the reference to the foreign agent
569 FriendsService.Delete(exfriendID, agentUUI);
570 // and also the converse
571 FriendsService.Delete(agentUUI, exfriendID.ToString());
572
573 // notify the agent's service?
574 Util.FireAndForget(delegate { Delete(agentID, exfriendID, agentUUI); });
575
576 m_log.DebugFormat("[HGFRIENDS MODULE]: {0} terminated {1}", agentUUI, exfriendID);
577 return true;
578 }
579 }
580 //else They're both foreigners! Can't handle this
581
582 return false;
583 }
584
585 private string GetUUI(UUID localUser, UUID foreignUser)
586 {
587 // Let's see if the user is here by any chance
588 FriendInfo[] finfos = GetFriends(localUser);
589 if (finfos != EMPTY_FRIENDS) // friend is here, cool
590 {
591 FriendInfo finfo = GetFriend(finfos, foreignUser);
592 if (finfo != null)
593 {
594 return finfo.Friend;
595 }
596 }
597 else // user is not currently on this sim, need to get from the service
598 {
599 finfos = FriendsService.GetFriends(localUser);
600 foreach (FriendInfo finfo in finfos)
601 {
602 if (finfo.Friend.StartsWith(foreignUser.ToString())) // found it!
603 {
604 return finfo.Friend;
605 }
606 }
607 }
608 return string.Empty;
609 }
610
611 private void Delete(UUID foreignUser, UUID localUser, string uui)
612 {
613 UUID id;
614 string url = string.Empty, secret = string.Empty, tmp = string.Empty;
615 if (Util.ParseUniversalUserIdentifier(uui, out id, out url, out tmp, out tmp, out secret))
616 {
617 m_log.DebugFormat("[HGFRIENDS MODULE]: Deleting friendship from {0}", url);
618 HGFriendsServicesConnector friendConn = new HGFriendsServicesConnector(url);
619 friendConn.DeleteFriendship(foreignUser, localUser, secret);
620 }
621 }
622 }
623}
diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs
new file mode 100644
index 0000000..7753c25
--- /dev/null
+++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs
@@ -0,0 +1,350 @@
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;
29using System.Collections.Generic;
30using System.Net;
31using System.Reflection;
32using log4net;
33using Nini.Config;
34using Nwc.XmlRpc;
35using Mono.Addins;
36using OpenMetaverse;
37using OpenSim.Framework;
38using OpenSim.Region.Framework.Interfaces;
39using OpenSim.Region.Framework.Scenes;
40using GridRegion = OpenSim.Services.Interfaces.GridRegion;
41using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo;
42using OpenSim.Services.Interfaces;
43using OpenSim.Services.Connectors.InstantMessage;
44using OpenSim.Services.Connectors.Hypergrid;
45using OpenSim.Server.Handlers.Hypergrid;
46
47namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
48{
49 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")]
50 public class HGMessageTransferModule : ISharedRegionModule, IMessageTransferModule, IInstantMessageSimConnector
51 {
52 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
53
54 protected bool m_Enabled = false;
55 protected List<Scene> m_Scenes = new List<Scene>();
56
57 protected IInstantMessage m_IMService;
58 protected Dictionary<UUID, object> m_UserLocationMap = new Dictionary<UUID, object>();
59
60 public event UndeliveredMessage OnUndeliveredMessage;
61
62 IUserManagement m_uMan;
63 IUserManagement UserManagementModule
64 {
65 get
66 {
67 if (m_uMan == null)
68 m_uMan = m_Scenes[0].RequestModuleInterface<IUserManagement>();
69 return m_uMan;
70 }
71 }
72
73 public virtual void Initialise(IConfigSource config)
74 {
75 IConfig cnf = config.Configs["Messaging"];
76 if (cnf != null && cnf.GetString(
77 "MessageTransferModule", "MessageTransferModule") != Name)
78 {
79 m_log.Debug("[HG MESSAGE TRANSFER]: Disabled by configuration");
80 return;
81 }
82
83 InstantMessageServerConnector imServer = new InstantMessageServerConnector(config, MainServer.Instance, this);
84 m_IMService = imServer.GetService();
85 m_Enabled = true;
86 }
87
88 public virtual void AddRegion(Scene scene)
89 {
90 if (!m_Enabled)
91 return;
92
93 lock (m_Scenes)
94 {
95 m_log.DebugFormat("[HG MESSAGE TRANSFER]: Message transfer module {0} active", Name);
96 scene.RegisterModuleInterface<IMessageTransferModule>(this);
97 m_Scenes.Add(scene);
98 }
99 }
100
101 public virtual void PostInitialise()
102 {
103 if (!m_Enabled)
104 return;
105
106 }
107
108 public virtual void RegionLoaded(Scene scene)
109 {
110 }
111
112 public virtual void RemoveRegion(Scene scene)
113 {
114 if (!m_Enabled)
115 return;
116
117 lock (m_Scenes)
118 {
119 m_Scenes.Remove(scene);
120 }
121 }
122
123 public virtual void Close()
124 {
125 }
126
127 public virtual string Name
128 {
129 get { return "HGMessageTransferModule"; }
130 }
131
132 public virtual Type ReplaceableInterface
133 {
134 get { return null; }
135 }
136
137 public void SendInstantMessage(GridInstantMessage im, MessageResultNotification result)
138 {
139 UUID toAgentID = new UUID(im.toAgentID);
140
141 // Try root avatar only first
142 foreach (Scene scene in m_Scenes)
143 {
144 if (scene.Entities.ContainsKey(toAgentID) &&
145 scene.Entities[toAgentID] is ScenePresence)
146 {
147// m_log.DebugFormat(
148// "[INSTANT MESSAGE]: Looking for root agent {0} in {1}",
149// toAgentID.ToString(), scene.RegionInfo.RegionName);
150
151 ScenePresence user = (ScenePresence) scene.Entities[toAgentID];
152 if (!user.IsChildAgent)
153 {
154 // Local message
155// m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to root agent {0} {1}", user.Name, toAgentID);
156 user.ControllingClient.SendInstantMessage(im);
157
158 // Message sent
159 result(true);
160 return;
161 }
162 }
163 }
164
165 // try child avatar second
166 foreach (Scene scene in m_Scenes)
167 {
168// m_log.DebugFormat(
169// "[INSTANT MESSAGE]: Looking for child of {0} in {1}", toAgentID, scene.RegionInfo.RegionName);
170
171 if (scene.Entities.ContainsKey(toAgentID) &&
172 scene.Entities[toAgentID] is ScenePresence)
173 {
174 // Local message
175 ScenePresence user = (ScenePresence) scene.Entities[toAgentID];
176
177// m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to child agent {0} {1}", user.Name, toAgentID);
178 user.ControllingClient.SendInstantMessage(im);
179
180 // Message sent
181 result(true);
182 return;
183 }
184 }
185
186// m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to {0} via XMLRPC", im.toAgentID);
187 // Is the user a local user?
188 UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, toAgentID);
189 string url = string.Empty;
190 bool foreigner = false;
191 if (account == null) // foreign user
192 {
193 url = UserManagementModule.GetUserServerURL(toAgentID, "IMServerURI");
194 foreigner = true;
195 }
196
197 Util.FireAndForget(delegate
198 {
199 bool success = false;
200 if (foreigner && url == string.Empty) // we don't know about this user
201 {
202 string recipientUUI = TryGetRecipientUUI(new UUID(im.fromAgentID), toAgentID);
203 m_log.DebugFormat("[HG MESSAGE TRANSFER]: Got UUI {0}", recipientUUI);
204 if (recipientUUI != string.Empty)
205 {
206 UUID id; string u = string.Empty, first = string.Empty, last = string.Empty, secret = string.Empty;
207 if (Util.ParseUniversalUserIdentifier(recipientUUI, out id, out u, out first, out last, out secret))
208 {
209 success = m_IMService.OutgoingInstantMessage(im, u, true);
210 if (success)
211 UserManagementModule.AddUser(toAgentID, u + ";" + first + " " + last);
212 }
213 }
214 }
215 else
216 success = m_IMService.OutgoingInstantMessage(im, url, foreigner);
217
218 if (!success && !foreigner)
219 HandleUndeliveredMessage(im, result);
220 else
221 result(success);
222 });
223
224 return;
225 }
226
227 protected bool SendIMToScene(GridInstantMessage gim, UUID toAgentID)
228 {
229 bool successful = false;
230 foreach (Scene scene in m_Scenes)
231 {
232 if (scene.Entities.ContainsKey(toAgentID) &&
233 scene.Entities[toAgentID] is ScenePresence)
234 {
235 ScenePresence user =
236 (ScenePresence)scene.Entities[toAgentID];
237
238 if (!user.IsChildAgent)
239 {
240 scene.EventManager.TriggerIncomingInstantMessage(gim);
241 successful = true;
242 }
243 }
244 }
245 if (!successful)
246 {
247 // If the message can't be delivered to an agent, it
248 // is likely to be a group IM. On a group IM, the
249 // imSessionID = toAgentID = group id. Raise the
250 // unhandled IM event to give the groups module
251 // a chance to pick it up. We raise that in a random
252 // scene, since the groups module is shared.
253 //
254 m_Scenes[0].EventManager.TriggerUnhandledInstantMessage(gim);
255 }
256
257 return successful;
258 }
259
260 protected void HandleUndeliveredMessage(GridInstantMessage im, MessageResultNotification result)
261 {
262 UndeliveredMessage handlerUndeliveredMessage = OnUndeliveredMessage;
263
264 // If this event has handlers, then an IM from an agent will be
265 // considered delivered. This will suppress the error message.
266 //
267 if (handlerUndeliveredMessage != null)
268 {
269 handlerUndeliveredMessage(im);
270 if (im.dialog == (byte)InstantMessageDialog.MessageFromAgent)
271 result(true);
272 else
273 result(false);
274 return;
275 }
276
277 //m_log.DebugFormat("[INSTANT MESSAGE]: Undeliverable");
278 result(false);
279 }
280
281 private string TryGetRecipientUUI(UUID fromAgent, UUID toAgent)
282 {
283 // Let's call back the fromAgent's user agent service
284 // Maybe that service knows about the toAgent
285 IClientAPI client = LocateClientObject(fromAgent);
286 if (client != null)
287 {
288 AgentCircuitData circuit = m_Scenes[0].AuthenticateHandler.GetAgentCircuitData(client.AgentId);
289 if (circuit != null)
290 {
291 if (circuit.ServiceURLs.ContainsKey("HomeURI"))
292 {
293 string uasURL = circuit.ServiceURLs["HomeURI"].ToString();
294 m_log.DebugFormat("[HG MESSAGE TRANSFER]: getting UUI of user {0} from {1}", toAgent, uasURL);
295 UserAgentServiceConnector uasConn = new UserAgentServiceConnector(uasURL);
296 return uasConn.GetUUI(fromAgent, toAgent);
297 }
298 }
299 }
300
301 return string.Empty;
302 }
303
304
305 /// <summary>
306 /// Find the scene for an agent
307 /// </summary>
308 private Scene GetClientScene(UUID agentId)
309 {
310 lock (m_Scenes)
311 {
312 foreach (Scene scene in m_Scenes)
313 {
314 ScenePresence presence = scene.GetScenePresence(agentId);
315 if (presence != null && !presence.IsChildAgent)
316 return scene;
317 }
318 }
319
320 return null;
321 }
322
323 /// <summary>
324 /// Find the client for a ID
325 /// </summary>
326 public IClientAPI LocateClientObject(UUID agentID)
327 {
328 Scene scene = GetClientScene(agentID);
329 if (scene != null)
330 {
331 ScenePresence presence = scene.GetScenePresence(agentID);
332 if (presence != null)
333 return presence.ControllingClient;
334 }
335
336 return null;
337 }
338
339 #region IInstantMessageSimConnector
340 public bool SendInstantMessage(GridInstantMessage im)
341 {
342 //m_log.DebugFormat("[XXX] Hook SendInstantMessage {0}", im.message);
343 UUID agentID = new UUID(im.toAgentID);
344 return SendIMToScene(im, agentID);
345 }
346 #endregion
347
348
349 }
350}
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveUtils.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveUtils.cs
index 47e34dc..0d90a15 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveUtils.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveUtils.cs
@@ -149,14 +149,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
149 149
150 /// <summary> 150 /// <summary>
151 /// Find an item given a PATH_DELIMITOR delimited path starting from the user's root folder. 151 /// Find an item given a PATH_DELIMITOR delimited path starting from the user's root folder.
152 /// 152 /// </summary>
153 /// <remarks>
153 /// This method does not handle paths that contain multiple delimitors 154 /// This method does not handle paths that contain multiple delimitors
154 /// 155 ///
155 /// FIXME: We do not yet handle situations where folders or items have the same name. We could handle this by some 156 /// FIXME: We do not yet handle situations where folders or items have the same name. We could handle this by some
156 /// XPath like expression 157 /// XPath like expression
157 /// 158 ///
158 /// FIXME: Delimitors which occur in names themselves are not currently escapable. 159 /// FIXME: Delimitors which occur in names themselves are not currently escapable.
159 /// </summary> 160 /// </remarks>
160 /// 161 ///
161 /// <param name="inventoryService"> 162 /// <param name="inventoryService">
162 /// Inventory service to query 163 /// Inventory service to query
@@ -178,32 +179,66 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
178 179
179 return FindItemByPath(inventoryService, rootFolder, path); 180 return FindItemByPath(inventoryService, rootFolder, path);
180 } 181 }
181 182
182 /// <summary> 183 /// <summary>
183 /// Find an item given a PATH_DELIMITOR delimited path starting from this folder. 184 /// Find an item given a PATH_DELIMITOR delimited path starting from this folder.
184 /// 185 /// </summary>
185 /// This method does not handle paths that contain multiple delimitors 186 /// <remarks>
187 /// This method does not handle paths that contain multiple delimiters
186 /// 188 ///
187 /// FIXME: We do not yet handle situations where folders or items have the same name. We could handle this by some 189 /// FIXME: We do not yet handle situations where folders or items have the same name. We could handle this by some
188 /// XPath like expression 190 /// XPath like expression
189 /// 191 ///
190 /// FIXME: Delimitors which occur in names themselves are not currently escapable. 192 /// FIXME: Delimitors which occur in names themselves are not currently escapable.
191 /// </summary> 193 /// </remarks>
192 /// 194 ///
193 /// <param name="inventoryService"> 195 /// <param name="inventoryService">Inventory service to query</param>
194 /// Inventory service to query 196 /// <param name="startFolder">The folder from which the path starts</param>
195 /// </param> 197 /// <param name="path">The path to the required item.</param>
196 /// <param name="startFolder">
197 /// The folder from which the path starts
198 /// </param>
199 /// <param name="path">
200 /// <param name="path">
201 /// The path to the required item.
202 /// </param>
203 /// <returns>null if the item is not found</returns> 198 /// <returns>null if the item is not found</returns>
204 public static InventoryItemBase FindItemByPath( 199 public static InventoryItemBase FindItemByPath(
205 IInventoryService inventoryService, InventoryFolderBase startFolder, string path) 200 IInventoryService inventoryService, InventoryFolderBase startFolder, string path)
206 { 201 {
202 List<InventoryItemBase> foundItems = FindItemsByPath(inventoryService, startFolder, path);
203
204 if (foundItems.Count != 0)
205 return foundItems[0];
206 else
207 return null;
208 }
209
210 public static List<InventoryItemBase> FindItemsByPath(
211 IInventoryService inventoryService, UUID userId, string path)
212 {
213 InventoryFolderBase rootFolder = inventoryService.GetRootFolder(userId);
214
215 if (null == rootFolder)
216 return new List<InventoryItemBase>();
217
218 return FindItemsByPath(inventoryService, rootFolder, path);
219 }
220
221 /// <summary>
222 /// Find items that match a given PATH_DELIMITOR delimited path starting from this folder.
223 /// </summary>
224 /// <remarks>
225 /// This method does not handle paths that contain multiple delimiters
226 ///
227 /// FIXME: We do not yet handle situations where folders or items have the same name. We could handle this by some
228 /// XPath like expression
229 ///
230 /// FIXME: Delimitors which occur in names themselves are not currently escapable.
231 /// </remarks>
232 ///
233 /// <param name="inventoryService">Inventory service to query</param>
234 /// <param name="startFolder">The folder from which the path starts</param>
235 /// <param name="path">The path to the required item.</param>
236 /// <returns>The items that were found with this path. An empty list if no items were found.</returns>
237 public static List<InventoryItemBase> FindItemsByPath(
238 IInventoryService inventoryService, InventoryFolderBase startFolder, string path)
239 {
240 List<InventoryItemBase> foundItems = new List<InventoryItemBase>();
241
207 // If the path isn't just / then trim any starting extraneous slashes 242 // If the path isn't just / then trim any starting extraneous slashes
208 path = path.TrimStart(new char[] { PATH_DELIMITER }); 243 path = path.TrimStart(new char[] { PATH_DELIMITER });
209 244
@@ -215,11 +250,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
215 if (components.Length == 1) 250 if (components.Length == 1)
216 { 251 {
217// m_log.DebugFormat( 252// m_log.DebugFormat(
218// "FOUND SINGLE COMPONENT [{0}]. Looking for this in [{1}] {2}", 253// "FOUND SINGLE COMPONENT [{0}]. Looking for this in [{1}] {2}",
219// components[0], startFolder.Name, startFolder.ID); 254// components[0], startFolder.Name, startFolder.ID);
220 255
221 List<InventoryItemBase> items = inventoryService.GetFolderItems(startFolder.Owner, startFolder.ID); 256 List<InventoryItemBase> items = inventoryService.GetFolderItems(startFolder.Owner, startFolder.ID);
222 257
223// m_log.DebugFormat("[INVENTORY ARCHIVE UTILS]: Found {0} items in FindItemByPath()", items.Count); 258// m_log.DebugFormat("[INVENTORY ARCHIVE UTILS]: Found {0} items in FindItemByPath()", items.Count);
224 259
225 foreach (InventoryItemBase item in items) 260 foreach (InventoryItemBase item in items)
@@ -227,24 +262,23 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
227// m_log.DebugFormat("[INVENTORY ARCHIVE UTILS]: Inspecting item {0} {1}", item.Name, item.ID); 262// m_log.DebugFormat("[INVENTORY ARCHIVE UTILS]: Inspecting item {0} {1}", item.Name, item.ID);
228 263
229 if (item.Name == components[0]) 264 if (item.Name == components[0])
230 return item; 265 foundItems.Add(item);
231 } 266 }
232 } 267 }
233 else 268 else
234 { 269 {
235// m_log.DebugFormat("FOUND COMPONENTS [{0}] and [{1}]", components[0], components[1]); 270// m_log.DebugFormat("FOUND COMPONENTS [{0}] and [{1}]", components[0], components[1]);
236 271
237 InventoryCollection contents = inventoryService.GetFolderContent(startFolder.Owner, startFolder.ID); 272 InventoryCollection contents = inventoryService.GetFolderContent(startFolder.Owner, startFolder.ID);
238 273
239 foreach (InventoryFolderBase folder in contents.Folders) 274 foreach (InventoryFolderBase folder in contents.Folders)
240 { 275 {
241 if (folder.Name == components[0]) 276 if (folder.Name == components[0])
242 return FindItemByPath(inventoryService, folder, components[1]); 277 foundItems.AddRange(FindItemsByPath(inventoryService, folder, components[1]));
243 } 278 }
244 } 279 }
245 280
246 // We didn't find an item or intermediate folder with the given name 281 return foundItems;
247 return null;
248 } 282 }
249 283
250 /// <summary> 284 /// <summary>
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs
index e043caa..63fde07 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs
@@ -146,6 +146,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
146 146
147 protected void SaveInvItem(InventoryItemBase inventoryItem, string path, Dictionary<string, object> options, IUserAccountService userAccountService) 147 protected void SaveInvItem(InventoryItemBase inventoryItem, string path, Dictionary<string, object> options, IUserAccountService userAccountService)
148 { 148 {
149 if (options.ContainsKey("verbose"))
150 m_log.InfoFormat(
151 "[INVENTORY ARCHIVER]: Saving item {0} {1} with asset {2}",
152 inventoryItem.ID, inventoryItem.Name, inventoryItem.AssetID);
153
149 string filename = path + CreateArchiveItemName(inventoryItem); 154 string filename = path + CreateArchiveItemName(inventoryItem);
150 155
151 // Record the creator of this item for user record purposes (which might go away soon) 156 // Record the creator of this item for user record purposes (which might go away soon)
@@ -154,7 +159,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
154 string serialization = UserInventoryItemSerializer.Serialize(inventoryItem, options, userAccountService); 159 string serialization = UserInventoryItemSerializer.Serialize(inventoryItem, options, userAccountService);
155 m_archiveWriter.WriteFile(filename, serialization); 160 m_archiveWriter.WriteFile(filename, serialization);
156 161
157 if (SaveAssets) 162 AssetType itemAssetType = (AssetType)inventoryItem.AssetType;
163
164 // Don't chase down link asset items as they actually point to their target item IDs rather than an asset
165 if (SaveAssets && itemAssetType != AssetType.Link && itemAssetType != AssetType.LinkFolder)
158 m_assetGatherer.GatherAssetUuids(inventoryItem.AssetID, (AssetType)inventoryItem.AssetType, m_assetUuids); 166 m_assetGatherer.GatherAssetUuids(inventoryItem.AssetID, (AssetType)inventoryItem.AssetType, m_assetUuids);
159 } 167 }
160 168
@@ -246,10 +254,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
246 254
247 // The path may point to an item instead 255 // The path may point to an item instead
248 if (inventoryFolder == null) 256 if (inventoryFolder == null)
249 {
250 inventoryItem = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, rootFolder, m_invPath); 257 inventoryItem = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, rootFolder, m_invPath);
251 //inventoryItem = m_userInfo.RootFolder.FindItemByPath(m_invPath);
252 }
253 258
254 if (null == inventoryFolder && null == inventoryItem) 259 if (null == inventoryFolder && null == inventoryItem)
255 { 260 {
@@ -441,4 +446,4 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
441 return s; 446 return s;
442 } 447 }
443 } 448 }
444} \ No newline at end of file 449}
diff --git a/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs b/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs
new file mode 100644
index 0000000..c82cfd2
--- /dev/null
+++ b/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs
@@ -0,0 +1,244 @@
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 log4net;
32using Nini.Config;
33using OpenMetaverse;
34using Mono.Addins;
35
36using OpenSim.Framework;
37using OpenSim.Region.Framework.Interfaces;
38using OpenSim.Region.Framework.Scenes;
39using OpenSim.Services.Connectors.Hypergrid;
40
41using GridRegion = OpenSim.Services.Interfaces.GridRegion;
42
43namespace OpenSim.Region.CoreModules.Avatar.Lure
44{
45 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")]
46 public class HGLureModule : ISharedRegionModule
47 {
48 private static readonly ILog m_log = LogManager.GetLogger(
49 MethodBase.GetCurrentMethod().DeclaringType);
50
51 private readonly List<Scene> m_scenes = new List<Scene>();
52
53 private IMessageTransferModule m_TransferModule = null;
54 private bool m_Enabled = false;
55
56 private string m_ThisGridURL;
57
58 private ExpiringCache<UUID, GridInstantMessage> m_PendingLures = new ExpiringCache<UUID, GridInstantMessage>();
59
60 public void Initialise(IConfigSource config)
61 {
62 if (config.Configs["Messaging"] != null)
63 {
64 if (config.Configs["Messaging"].GetString("LureModule", string.Empty) == "HGLureModule")
65 {
66 m_Enabled = true;
67
68 m_ThisGridURL = config.Configs["Messaging"].GetString("Gatekeeper", string.Empty);
69 m_log.DebugFormat("[LURE MODULE]: {0} enabled", Name);
70 }
71 }
72 }
73
74 public void AddRegion(Scene scene)
75 {
76 if (!m_Enabled)
77 return;
78
79 lock (m_scenes)
80 {
81 m_scenes.Add(scene);
82 scene.EventManager.OnIncomingInstantMessage += OnIncomingInstantMessage;
83 scene.EventManager.OnNewClient += OnNewClient;
84 }
85 }
86
87 public void RegionLoaded(Scene scene)
88 {
89 if (!m_Enabled)
90 return;
91
92 if (m_TransferModule == null)
93 {
94 m_TransferModule =
95 scene.RequestModuleInterface<IMessageTransferModule>();
96
97 if (m_TransferModule == null)
98 {
99 m_log.Error("[LURE MODULE]: No message transfer module, lures will not work!");
100
101 m_Enabled = false;
102 m_scenes.Clear();
103 scene.EventManager.OnNewClient -= OnNewClient;
104 scene.EventManager.OnIncomingInstantMessage -= OnIncomingInstantMessage;
105 }
106 }
107
108 }
109
110 public void RemoveRegion(Scene scene)
111 {
112 if (!m_Enabled)
113 return;
114
115 lock (m_scenes)
116 {
117 m_scenes.Remove(scene);
118 scene.EventManager.OnNewClient -= OnNewClient;
119 scene.EventManager.OnIncomingInstantMessage -= OnIncomingInstantMessage;
120 }
121 }
122
123 void OnNewClient(IClientAPI client)
124 {
125 client.OnInstantMessage += OnInstantMessage;
126 client.OnStartLure += OnStartLure;
127 client.OnTeleportLureRequest += OnTeleportLureRequest;
128 }
129
130 public void PostInitialise()
131 {
132 }
133
134 public void Close()
135 {
136 }
137
138 public string Name
139 {
140 get { return "HGLureModule"; }
141 }
142
143 public Type ReplaceableInterface
144 {
145 get { return null; }
146 }
147
148 void OnInstantMessage(IClientAPI client, GridInstantMessage im)
149 {
150 }
151
152 void OnIncomingInstantMessage(GridInstantMessage im)
153 {
154 if (im.dialog == (byte)InstantMessageDialog.RequestTeleport)
155 {
156 UUID sessionID = new UUID(im.imSessionID);
157 m_log.DebugFormat("[HG LURE MODULE]: RequestTeleport sessionID={0}, regionID={1}, message={2}", im.imSessionID, im.RegionID, im.message);
158 m_PendingLures.Add(sessionID, im, 7200); // 2 hours
159
160 // Forward. We do this, because the IM module explicitly rejects
161 // IMs of this type
162 if (m_TransferModule != null)
163 m_TransferModule.SendInstantMessage(im, delegate(bool success) { });
164
165 }
166 }
167
168 public void OnStartLure(byte lureType, string message, UUID targetid, IClientAPI client)
169 {
170 if (!(client.Scene is Scene))
171 return;
172
173 Scene scene = (Scene)(client.Scene);
174 ScenePresence presence = scene.GetScenePresence(client.AgentId);
175
176 message += "@" + m_ThisGridURL;
177
178 m_log.DebugFormat("[HG LURE MODULE]: TP invite with message {0}", message);
179
180 GridInstantMessage m = new GridInstantMessage(scene, client.AgentId,
181 client.FirstName+" "+client.LastName, targetid,
182 (byte)InstantMessageDialog.RequestTeleport, false,
183 message, UUID.Random(), false, presence.AbsolutePosition,
184 new Byte[0]);
185 m.RegionID = client.Scene.RegionInfo.RegionID.Guid;
186
187 if (m_TransferModule != null)
188 {
189 m_TransferModule.SendInstantMessage(m,
190 delegate(bool success) { });
191 }
192 }
193
194 public void OnTeleportLureRequest(UUID lureID, uint teleportFlags, IClientAPI client)
195 {
196 if (!(client.Scene is Scene))
197 return;
198
199 Scene scene = (Scene)(client.Scene);
200
201 GridInstantMessage im = null;
202 if (m_PendingLures.TryGetValue(lureID, out im))
203 {
204 m_PendingLures.Remove(lureID);
205 Lure(client, teleportFlags, im);
206 }
207 else
208 m_log.DebugFormat("[HG LURE MODULE]: pending lure {0} not found", lureID);
209
210 }
211
212 private void Lure(IClientAPI client, uint teleportflags, GridInstantMessage im)
213 {
214 Scene scene = (Scene)(client.Scene);
215 GridRegion region = scene.GridService.GetRegionByUUID(scene.RegionInfo.ScopeID, new UUID(im.RegionID));
216 if (region != null)
217 scene.RequestTeleportLocation(client, region.RegionHandle, im.Position + new Vector3(0.5f, 0.5f, 0f), Vector3.UnitX, teleportflags);
218 else // we don't have that region here. Check if it's HG
219 {
220 string[] parts = im.message.Split(new char[] { '@' });
221 if (parts.Length > 1)
222 {
223 string url = parts[parts.Length - 1]; // the last part
224 if (url.Trim(new char[] {'/'}) != m_ThisGridURL.Trim(new char[] {'/'}))
225 {
226 m_log.DebugFormat("[HG LURE MODULE]: Luring agent to grid {0} region {1} position {2}", url, im.RegionID, im.Position);
227 GatekeeperServiceConnector gConn = new GatekeeperServiceConnector();
228 GridRegion gatekeeper = new GridRegion();
229 gatekeeper.ServerURI = url;
230 GridRegion finalDestination = gConn.GetHyperlinkRegion(gatekeeper, new UUID(im.RegionID));
231 if (finalDestination != null)
232 {
233 ScenePresence sp = scene.GetScenePresence(client.AgentId);
234 IEntityTransferModule transferMod = scene.RequestModuleInterface<IEntityTransferModule>();
235 IEventQueue eq = sp.Scene.RequestModuleInterface<IEventQueue>();
236 if (transferMod != null && sp != null && eq != null)
237 transferMod.DoTeleport(sp, gatekeeper, finalDestination, im.Position + new Vector3(0.5f, 0.5f, 0f), Vector3.UnitX, teleportflags, eq);
238 }
239 }
240 }
241 }
242 }
243 }
244}
diff --git a/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs b/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs
index a12b57a..dcfdf8f 100644
--- a/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs
@@ -45,16 +45,19 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure
45 private readonly List<Scene> m_scenes = new List<Scene>(); 45 private readonly List<Scene> m_scenes = new List<Scene>();
46 46
47 private IMessageTransferModule m_TransferModule = null; 47 private IMessageTransferModule m_TransferModule = null;
48 private bool m_Enabled = true; 48 private bool m_Enabled = false;
49 49
50 public void Initialise(IConfigSource config) 50 public void Initialise(IConfigSource config)
51 { 51 {
52 if (config.Configs["Messaging"] != null) 52 if (config.Configs["Messaging"] != null)
53 { 53 {
54 if (config.Configs["Messaging"].GetString( 54 if (config.Configs["Messaging"].GetString(
55 "LureModule", "LureModule") != 55 "LureModule", "LureModule") ==
56 "LureModule") 56 "LureModule")
57 m_Enabled = false; 57 {
58 m_Enabled = true;
59 m_log.DebugFormat("[LURE MODULE]: {0} enabled", Name);
60 }
58 } 61 }
59 } 62 }
60 63
@@ -74,6 +77,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure
74 77
75 public void RegionLoaded(Scene scene) 78 public void RegionLoaded(Scene scene)
76 { 79 {
80 if (!m_Enabled)
81 return;
82
77 if (m_TransferModule == null) 83 if (m_TransferModule == null)
78 { 84 {
79 m_TransferModule = 85 m_TransferModule =
@@ -96,6 +102,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure
96 102
97 public void RemoveRegion(Scene scene) 103 public void RemoveRegion(Scene scene)
98 { 104 {
105 if (!m_Enabled)
106 return;
107
99 lock (m_scenes) 108 lock (m_scenes)
100 { 109 {
101 m_scenes.Remove(scene); 110 m_scenes.Remove(scene);
diff --git a/OpenSim/Region/CoreModules/Avatar/Profile/BasicProfileModule.cs b/OpenSim/Region/CoreModules/Avatar/Profile/BasicProfileModule.cs
new file mode 100644
index 0000000..079e1b6
--- /dev/null
+++ b/OpenSim/Region/CoreModules/Avatar/Profile/BasicProfileModule.cs
@@ -0,0 +1,173 @@
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;
29using System.Collections.Generic;
30using System.Globalization;
31using System.Reflection;
32
33using OpenMetaverse;
34using log4net;
35using Nini.Config;
36using Mono.Addins;
37
38using OpenSim.Framework;
39using OpenSim.Region.Framework.Interfaces;
40using OpenSim.Region.Framework.Scenes;
41using OpenSim.Services.Interfaces;
42
43namespace OpenSim.Region.CoreModules.Avatar.Profile
44{
45 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")]
46 public class BasicProfileModule : ISharedRegionModule
47 {
48 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
49
50 //
51 // Module vars
52 //
53 private List<Scene> m_Scenes = new List<Scene>();
54 private bool m_Enabled = false;
55
56 #region ISharedRegionModule
57
58 public void Initialise(IConfigSource config)
59 {
60 if (config.Configs["Profile"] != null)
61 {
62 if (config.Configs["Profile"].GetString("Module", string.Empty) != "BasicProfileModule")
63 return;
64 }
65
66 m_log.DebugFormat("[PROFILE MODULE]: Basic Profile Module enabled");
67 m_Enabled = true;
68
69 }
70
71 public void AddRegion(Scene scene)
72 {
73 if (!m_Enabled)
74 return;
75
76 lock (m_Scenes)
77 {
78 if (!m_Scenes.Contains(scene))
79 {
80 m_Scenes.Add(scene);
81 // Hook up events
82 scene.EventManager.OnNewClient += OnNewClient;
83 }
84 }
85 }
86
87 public void RegionLoaded(Scene scene)
88 {
89 if (!m_Enabled)
90 return;
91 }
92
93 public void RemoveRegion(Scene scene)
94 {
95 if (!m_Enabled)
96 return;
97
98 lock (m_Scenes)
99 {
100 m_Scenes.Remove(scene);
101 }
102 }
103
104 public void PostInitialise()
105 {
106 }
107
108 public void Close()
109 {
110 }
111
112 public string Name
113 {
114 get { return "BasicProfileModule"; }
115 }
116
117 public Type ReplaceableInterface
118 {
119 get { return null; }
120 }
121
122 #endregion
123
124 /// New Client Event Handler
125 private void OnNewClient(IClientAPI client)
126 {
127 //Profile
128 client.OnRequestAvatarProperties += RequestAvatarProperties;
129 }
130
131 public void RequestAvatarProperties(IClientAPI remoteClient, UUID avatarID)
132 {
133 IScene s = remoteClient.Scene;
134 if (!(s is Scene))
135 return;
136
137 Scene scene = (Scene)s;
138
139 string profileUrl = String.Empty;
140 string aboutText = String.Empty;
141 string firstLifeAboutText = String.Empty;
142 UUID image = UUID.Zero;
143 UUID firstLifeImage = UUID.Zero;
144 UUID partner = UUID.Zero;
145 uint wantMask = 0;
146 string wantText = String.Empty;
147 uint skillsMask = 0;
148 string skillsText = String.Empty;
149 string languages = String.Empty;
150
151 Byte[] charterMember = Utils.StringToBytes("Avatar");
152
153 profileUrl = "No profile data";
154 aboutText = string.Empty;
155 firstLifeAboutText = string.Empty;
156 image = UUID.Zero;
157 firstLifeImage = UUID.Zero;
158 partner = UUID.Zero;
159
160 remoteClient.SendAvatarProperties(avatarID, aboutText,
161 Util.ToDateTime(0).ToString(
162 "M/d/yyyy", CultureInfo.InvariantCulture),
163 charterMember, firstLifeAboutText,
164 (uint)(0 & 0xff),
165 firstLifeImage, image, profileUrl, partner);
166
167 //Viewer expects interest data when it asks for properties.
168 remoteClient.SendAvatarInterestsReply(avatarID, wantMask, wantText,
169 skillsMask, skillsText, languages);
170 }
171
172 }
173} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
index 1fb346e..02efcd8 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
@@ -52,6 +52,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
52 52
53 protected bool m_Enabled = false; 53 protected bool m_Enabled = false;
54 protected Scene m_aScene; 54 protected Scene m_aScene;
55 protected List<Scene> m_Scenes = new List<Scene>();
55 protected List<UUID> m_agentsInTransit; 56 protected List<UUID> m_agentsInTransit;
56 private ExpiringCache<UUID, ExpiringCache<ulong, DateTime>> m_bannedRegions = 57 private ExpiringCache<UUID, ExpiringCache<ulong, DateTime>> m_bannedRegions =
57 new ExpiringCache<UUID, ExpiringCache<ulong, DateTime>>(); 58 new ExpiringCache<UUID, ExpiringCache<ulong, DateTime>>();
@@ -96,13 +97,15 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
96 if (m_aScene == null) 97 if (m_aScene == null)
97 m_aScene = scene; 98 m_aScene = scene;
98 99
100 m_Scenes.Add(scene);
99 scene.RegisterModuleInterface<IEntityTransferModule>(this); 101 scene.RegisterModuleInterface<IEntityTransferModule>(this);
100 scene.EventManager.OnNewClient += OnNewClient; 102 scene.EventManager.OnNewClient += OnNewClient;
101 } 103 }
102 104
103 protected virtual void OnNewClient(IClientAPI client) 105 protected virtual void OnNewClient(IClientAPI client)
104 { 106 {
105 client.OnTeleportHomeRequest += TeleportHomeFired; 107 client.OnTeleportHomeRequest += TriggerTeleportHome;
108 client.OnTeleportLandmarkRequest += RequestTeleportLandmark;
106 } 109 }
107 110
108 public virtual void Close() 111 public virtual void Close()
@@ -118,6 +121,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
118 return; 121 return;
119 if (scene == m_aScene) 122 if (scene == m_aScene)
120 m_aScene = null; 123 m_aScene = null;
124
125 m_Scenes.Remove(scene);
121 } 126 }
122 127
123 public virtual void RegionLoaded(Scene scene) 128 public virtual void RegionLoaded(Scene scene)
@@ -127,7 +132,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
127 132
128 } 133 }
129 134
130
131 #endregion 135 #endregion
132 136
133 #region Agent Teleports 137 #region Agent Teleports
@@ -249,7 +253,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
249 } 253 }
250 } 254 }
251 255
252 protected void DoTeleport(ScenePresence sp, GridRegion reg, GridRegion finalDestination, Vector3 position, Vector3 lookAt, uint teleportFlags, IEventQueue eq) 256 public void DoTeleport(ScenePresence sp, GridRegion reg, GridRegion finalDestination, Vector3 position, Vector3 lookAt, uint teleportFlags, IEventQueue eq)
253 { 257 {
254 if (reg == null || finalDestination == null) 258 if (reg == null || finalDestination == null)
255 { 259 {
@@ -557,9 +561,32 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
557 561
558 #endregion 562 #endregion
559 563
564 #region Landmark Teleport
565 /// <summary>
566 /// Tries to teleport agent to landmark.
567 /// </summary>
568 /// <param name="remoteClient"></param>
569 /// <param name="regionHandle"></param>
570 /// <param name="position"></param>
571 public virtual void RequestTeleportLandmark(IClientAPI remoteClient, AssetLandmark lm)
572 {
573 GridRegion info = m_aScene.GridService.GetRegionByUUID(UUID.Zero, lm.RegionID);
574
575 if (info == null)
576 {
577 // can't find the region: Tell viewer and abort
578 remoteClient.SendTeleportFailed("The teleport destination could not be found.");
579 return;
580 }
581 ((Scene)(remoteClient.Scene)).RequestTeleportLocation(remoteClient, info.RegionHandle, lm.Position,
582 Vector3.Zero, (uint)(Constants.TeleportFlags.SetLastToTarget | Constants.TeleportFlags.ViaLandmark));
583 }
584
585 #endregion
586
560 #region Teleport Home 587 #region Teleport Home
561 588
562 public void TeleportHomeFired(UUID id, IClientAPI client) 589 public virtual void TriggerTeleportHome(UUID id, IClientAPI client)
563 { 590 {
564 TeleportHome(id, client); 591 TeleportHome(id, client);
565 } 592 }
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs
index 1ccbcfd..8858ad5 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs
@@ -86,7 +86,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
86 86
87 protected override void OnNewClient(IClientAPI client) 87 protected override void OnNewClient(IClientAPI client)
88 { 88 {
89 client.OnTeleportHomeRequest += TeleportHomeFired; 89 client.OnTeleportHomeRequest += TriggerTeleportHome;
90 client.OnTeleportLandmarkRequest += RequestTeleportLandmark;
90 client.OnConnectionClosed += new Action<IClientAPI>(OnConnectionClosed); 91 client.OnConnectionClosed += new Action<IClientAPI>(OnConnectionClosed);
91 } 92 }
92 93
@@ -146,8 +147,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
146 { 147 {
147 base.AgentHasMovedAway(sp, logout); 148 base.AgentHasMovedAway(sp, logout);
148 if (logout) 149 if (logout)
150 {
149 // Log them out of this grid 151 // Log them out of this grid
150 m_aScene.PresenceService.LogoutAgent(sp.ControllingClient.SessionId); 152 m_aScene.PresenceService.LogoutAgent(sp.ControllingClient.SessionId);
153 }
151 } 154 }
152 155
153 protected override bool CreateAgent(ScenePresence sp, GridRegion reg, GridRegion finalDestination, AgentCircuitData agentCircuit, uint teleportFlags, out string reason, out bool logout) 156 protected override bool CreateAgent(ScenePresence sp, GridRegion reg, GridRegion finalDestination, AgentCircuitData agentCircuit, uint teleportFlags, out string reason, out bool logout)
@@ -178,7 +181,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
178 return m_aScene.SimulationService.CreateAgent(reg, agentCircuit, teleportFlags, out reason); 181 return m_aScene.SimulationService.CreateAgent(reg, agentCircuit, teleportFlags, out reason);
179 } 182 }
180 183
181 public void TeleportHomeFired(UUID id, IClientAPI client) 184 public void TriggerTeleportHome(UUID id, IClientAPI client)
182 { 185 {
183 TeleportHome(id, client); 186 TeleportHome(id, client);
184 } 187 }
@@ -233,6 +236,57 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
233 DoTeleport(sp, homeGatekeeper, finalDestination, position, lookAt, (uint)(Constants.TeleportFlags.SetLastToTarget | Constants.TeleportFlags.ViaHome), eq); 236 DoTeleport(sp, homeGatekeeper, finalDestination, position, lookAt, (uint)(Constants.TeleportFlags.SetLastToTarget | Constants.TeleportFlags.ViaHome), eq);
234 return true; 237 return true;
235 } 238 }
239
240 /// <summary>
241 /// Tries to teleport agent to landmark.
242 /// </summary>
243 /// <param name="remoteClient"></param>
244 /// <param name="regionHandle"></param>
245 /// <param name="position"></param>
246 public override void RequestTeleportLandmark(IClientAPI remoteClient, AssetLandmark lm)
247 {
248 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Teleporting agent via landmark to {0} region {1} position {2}",
249 (lm.Gatekeeper == string.Empty) ? "local" : lm.Gatekeeper, lm.RegionID, lm.Position);
250 if (lm.Gatekeeper == string.Empty)
251 {
252 base.RequestTeleportLandmark(remoteClient, lm);
253 return;
254 }
255
256 GridRegion info = m_aScene.GridService.GetRegionByUUID(UUID.Zero, lm.RegionID);
257
258 // Local region?
259 if (info != null)
260 {
261 ((Scene)(remoteClient.Scene)).RequestTeleportLocation(remoteClient, info.RegionHandle, lm.Position,
262 Vector3.Zero, (uint)(Constants.TeleportFlags.SetLastToTarget | Constants.TeleportFlags.ViaLandmark));
263 return;
264 }
265 else
266 {
267 // Foreign region
268 Scene scene = (Scene)(remoteClient.Scene);
269 GatekeeperServiceConnector gConn = new GatekeeperServiceConnector();
270 GridRegion gatekeeper = new GridRegion();
271 gatekeeper.ServerURI = lm.Gatekeeper;
272 GridRegion finalDestination = gConn.GetHyperlinkRegion(gatekeeper, new UUID(lm.RegionID));
273 if (finalDestination != null)
274 {
275 ScenePresence sp = scene.GetScenePresence(remoteClient.AgentId);
276 IEntityTransferModule transferMod = scene.RequestModuleInterface<IEntityTransferModule>();
277 IEventQueue eq = sp.Scene.RequestModuleInterface<IEventQueue>();
278 if (transferMod != null && sp != null && eq != null)
279 transferMod.DoTeleport(sp, gatekeeper, finalDestination, lm.Position,
280 Vector3.UnitX, (uint)(Constants.TeleportFlags.SetLastToTarget | Constants.TeleportFlags.ViaLandmark), eq);
281 }
282
283 }
284
285 // can't find the region: Tell viewer and abort
286 remoteClient.SendTeleportFailed("The teleport destination could not be found.");
287
288 }
289
236 #endregion 290 #endregion
237 291
238 #region IUserAgentVerificationModule 292 #region IUserAgentVerificationModule
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs
index 52791cb..49d484b 100644
--- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs
@@ -56,6 +56,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
56 56
57 private string m_ProfileServerURI; 57 private string m_ProfileServerURI;
58 private bool m_OutboundPermission; 58 private bool m_OutboundPermission;
59 private string m_ThisGatekeeper;
59 60
60// private bool m_Initialized = false; 61// private bool m_Initialized = false;
61 62
@@ -85,6 +86,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
85 { 86 {
86 m_ProfileServerURI = thisModuleConfig.GetString("ProfileServerURI", string.Empty); 87 m_ProfileServerURI = thisModuleConfig.GetString("ProfileServerURI", string.Empty);
87 m_OutboundPermission = thisModuleConfig.GetBoolean("OutboundPermission", true); 88 m_OutboundPermission = thisModuleConfig.GetBoolean("OutboundPermission", true);
89 m_ThisGatekeeper = thisModuleConfig.GetString("Gatekeeper", string.Empty);
88 } 90 }
89 else 91 else
90 m_log.Warn("[HG INVENTORY ACCESS MODULE]: HGInventoryAccessModule configs not found. ProfileServerURI not set!"); 92 m_log.Warn("[HG INVENTORY ACCESS MODULE]: HGInventoryAccessModule configs not found. ProfileServerURI not set!");
@@ -110,7 +112,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
110 public void UploadInventoryItem(UUID avatarID, UUID assetID, string name, int userlevel) 112 public void UploadInventoryItem(UUID avatarID, UUID assetID, string name, int userlevel)
111 { 113 {
112 string userAssetServer = string.Empty; 114 string userAssetServer = string.Empty;
113 if (IsForeignUser(avatarID, out userAssetServer) && m_OutboundPermission) 115 if (IsForeignUser(avatarID, out userAssetServer) && userAssetServer != string.Empty && m_OutboundPermission)
114 { 116 {
115 Util.FireAndForget(delegate { m_assMapper.Post(assetID, avatarID, userAssetServer); }); 117 Util.FireAndForget(delegate { m_assMapper.Post(assetID, avatarID, userAssetServer); });
116 } 118 }
@@ -119,6 +121,24 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
119 #endregion 121 #endregion
120 122
121 #region Overrides of Basic Inventory Access methods 123 #region Overrides of Basic Inventory Access methods
124
125 protected override string GenerateLandmark(ScenePresence presence, out string prefix, out string suffix)
126 {
127 UserAccount account = m_Scene.UserAccountService.GetUserAccount(m_Scene.RegionInfo.ScopeID, presence.UUID);
128 if (account == null)
129 prefix = "HG ";
130 else
131 prefix = string.Empty;
132 suffix = " @ " + m_ThisGatekeeper;
133 Vector3 pos = presence.AbsolutePosition;
134 return String.Format("Landmark version 2\nregion_id {0}\nlocal_pos {1} {2} {3}\nregion_handle {4}\ngatekeeper {5}\n",
135 presence.Scene.RegionInfo.RegionID,
136 pos.X, pos.Y, pos.Z,
137 presence.RegionHandle,
138 m_ThisGatekeeper);
139 }
140
141
122 /// 142 ///
123 /// CapsUpdateInventoryItemAsset 143 /// CapsUpdateInventoryItemAsset
124 /// 144 ///
@@ -180,10 +200,10 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
180 public override void TransferInventoryAssets(InventoryItemBase item, UUID sender, UUID receiver) 200 public override void TransferInventoryAssets(InventoryItemBase item, UUID sender, UUID receiver)
181 { 201 {
182 string userAssetServer = string.Empty; 202 string userAssetServer = string.Empty;
183 if (IsForeignUser(sender, out userAssetServer)) 203 if (IsForeignUser(sender, out userAssetServer) && userAssetServer != string.Empty)
184 m_assMapper.Get(item.AssetID, sender, userAssetServer); 204 m_assMapper.Get(item.AssetID, sender, userAssetServer);
185 205
186 if (IsForeignUser(receiver, out userAssetServer) && m_OutboundPermission) 206 if (IsForeignUser(receiver, out userAssetServer) && userAssetServer != string.Empty && m_OutboundPermission)
187 m_assMapper.Post(item.AssetID, receiver, userAssetServer); 207 m_assMapper.Post(item.AssetID, receiver, userAssetServer);
188 } 208 }
189 209
@@ -203,9 +223,15 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
203 if (aCircuit.ServiceURLs.ContainsKey("AssetServerURI")) 223 if (aCircuit.ServiceURLs.ContainsKey("AssetServerURI"))
204 { 224 {
205 assetServerURL = aCircuit.ServiceURLs["AssetServerURI"].ToString(); 225 assetServerURL = aCircuit.ServiceURLs["AssetServerURI"].ToString();
206 assetServerURL = assetServerURL.Trim(new char[] { '/' }); return true; 226 assetServerURL = assetServerURL.Trim(new char[] { '/' });
207 } 227 }
208 } 228 }
229 else
230 {
231 assetServerURL = UserManagementModule.GetUserServerURL(userID, "AssetServerURI");
232 assetServerURL = assetServerURL.Trim(new char[] { '/' });
233 }
234 return true;
209 } 235 }
210 236
211 return false; 237 return false;
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
index 184b223..7bad814 100644
--- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
@@ -30,6 +30,7 @@ using System.Collections.Generic;
30using System.Net; 30using System.Net;
31using System.Xml; 31using System.Xml;
32using System.Reflection; 32using System.Reflection;
33using System.Text;
33using System.Threading; 34using System.Threading;
34 35
35using OpenSim.Framework; 36using OpenSim.Framework;
@@ -128,7 +129,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
128 129
129 protected virtual void OnNewClient(IClientAPI client) 130 protected virtual void OnNewClient(IClientAPI client)
130 { 131 {
131 132 client.OnCreateNewInventoryItem += CreateNewInventoryItem;
132 } 133 }
133 134
134 public virtual void Close() 135 public virtual void Close()
@@ -157,6 +158,87 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
157 #region Inventory Access 158 #region Inventory Access
158 159
159 /// <summary> 160 /// <summary>
161 /// Create a new inventory item. Called when the client creates a new item directly within their
162 /// inventory (e.g. by selecting a context inventory menu option).
163 /// </summary>
164 /// <param name="remoteClient"></param>
165 /// <param name="transactionID"></param>
166 /// <param name="folderID"></param>
167 /// <param name="callbackID"></param>
168 /// <param name="description"></param>
169 /// <param name="name"></param>
170 /// <param name="invType"></param>
171 /// <param name="type"></param>
172 /// <param name="wearableType"></param>
173 /// <param name="nextOwnerMask"></param>
174 public void CreateNewInventoryItem(IClientAPI remoteClient, UUID transactionID, UUID folderID,
175 uint callbackID, string description, string name, sbyte invType,
176 sbyte assetType,
177 byte wearableType, uint nextOwnerMask, int creationDate)
178 {
179 m_log.DebugFormat("[AGENT INVENTORY]: Received request to create inventory item {0} in folder {1}", name, folderID);
180
181 if (!m_Scene.Permissions.CanCreateUserInventory(invType, remoteClient.AgentId))
182 return;
183
184 InventoryFolderBase f = new InventoryFolderBase(folderID, remoteClient.AgentId);
185 InventoryFolderBase folder = m_Scene.InventoryService.GetFolder(f);
186
187 if (folder == null || folder.Owner != remoteClient.AgentId)
188 return;
189
190 if (transactionID == UUID.Zero)
191 {
192 ScenePresence presence;
193 if (m_Scene.TryGetScenePresence(remoteClient.AgentId, out presence))
194 {
195 byte[] data = null;
196
197 if (invType == (sbyte)InventoryType.Landmark && presence != null)
198 {
199 string suffix = string.Empty, prefix = string.Empty;
200 string strdata = GenerateLandmark(presence, out prefix, out suffix);
201 data = Encoding.ASCII.GetBytes(strdata);
202 name = prefix + name;
203 description += suffix;
204 }
205
206 AssetBase asset = m_Scene.CreateAsset(name, description, assetType, data, remoteClient.AgentId);
207 m_Scene.AssetService.Store(asset);
208
209 m_Scene.CreateNewInventoryItem(remoteClient, remoteClient.AgentId.ToString(), string.Empty, folderID, asset.Name, 0, callbackID, asset, invType, nextOwnerMask, creationDate);
210 }
211 else
212 {
213 m_log.ErrorFormat(
214 "ScenePresence for agent uuid {0} unexpectedly not found in CreateNewInventoryItem",
215 remoteClient.AgentId);
216 }
217 }
218 else
219 {
220 IAgentAssetTransactions agentTransactions = m_Scene.RequestModuleInterface<IAgentAssetTransactions>();
221 if (agentTransactions != null)
222 {
223 agentTransactions.HandleItemCreationFromTransaction(
224 remoteClient, transactionID, folderID, callbackID, description,
225 name, invType, assetType, wearableType, nextOwnerMask);
226 }
227 }
228 }
229
230 protected virtual string GenerateLandmark(ScenePresence presence, out string prefix, out string suffix)
231 {
232 prefix = string.Empty;
233 suffix = string.Empty;
234 Vector3 pos = presence.AbsolutePosition;
235 return String.Format("Landmark version 2\nregion_id {0}\nlocal_pos {1} {2} {3}\nregion_handle {4}\n",
236 presence.Scene.RegionInfo.RegionID,
237 pos.X, pos.Y, pos.Z,
238 presence.RegionHandle);
239 }
240
241 /// <summary>
160 /// Capability originating call to update the asset of an item in an agent's inventory 242 /// Capability originating call to update the asset of an item in an agent's inventory
161 /// </summary> 243 /// </summary>
162 /// <param name="remoteClient"></param> 244 /// <param name="remoteClient"></param>
diff --git a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs
index 4cc6905..accd094 100644
--- a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs
@@ -30,11 +30,13 @@ using System.IO;
30using System.Reflection; 30using System.Reflection;
31 31
32using OpenSim.Framework; 32using OpenSim.Framework;
33using OpenSim.Framework.Console;
33 34
34using OpenSim.Region.Framework; 35using OpenSim.Region.Framework;
35using OpenSim.Region.Framework.Interfaces; 36using OpenSim.Region.Framework.Interfaces;
36using OpenSim.Region.Framework.Scenes; 37using OpenSim.Region.Framework.Scenes;
37using OpenSim.Services.Interfaces; 38using OpenSim.Services.Interfaces;
39using OpenSim.Services.Connectors.Hypergrid;
38 40
39using OpenMetaverse; 41using OpenMetaverse;
40using log4net; 42using log4net;
@@ -47,7 +49,8 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
47 public UUID Id; 49 public UUID Id;
48 public string FirstName; 50 public string FirstName;
49 public string LastName; 51 public string LastName;
50 public string ProfileURL; 52 public string HomeURL;
53 public Dictionary<string, object> ServerURLs;
51 } 54 }
52 55
53 public class UserManagementModule : ISharedRegionModule, IUserManagement 56 public class UserManagementModule : ISharedRegionModule, IUserManagement
@@ -78,6 +81,14 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
78 // } 81 // }
79 // } 82 // }
80 //} 83 //}
84 MainConsole.Instance.Commands.AddCommand("grid", true,
85 "show names",
86 "show names",
87 "Show the bindings between user UUIDs and user names",
88 String.Empty,
89 HandleShowUsers);
90
91
81 } 92 }
82 93
83 public bool IsSharedModule 94 public bool IsSharedModule
@@ -101,6 +112,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
101 112
102 scene.RegisterModuleInterface<IUserManagement>(this); 113 scene.RegisterModuleInterface<IUserManagement>(this);
103 scene.EventManager.OnNewClient += new EventManager.OnNewClientDelegate(EventManager_OnNewClient); 114 scene.EventManager.OnNewClient += new EventManager.OnNewClientDelegate(EventManager_OnNewClient);
115 scene.EventManager.OnPrimsLoaded += new EventManager.PrimsLoaded(EventManager_OnPrimsLoaded);
104 } 116 }
105 117
106 public void RemoveRegion(Scene scene) 118 public void RemoveRegion(Scene scene)
@@ -109,18 +121,12 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
109 m_Scenes.Remove(scene); 121 m_Scenes.Remove(scene);
110 } 122 }
111 123
112 public void RegionLoaded(Scene scene) 124 public void RegionLoaded(Scene s)
113 { 125 {
114 } 126 }
115 127
116 public void PostInitialise() 128 public void PostInitialise()
117 { 129 {
118 foreach (Scene s in m_Scenes)
119 {
120 // let's sniff all the user names referenced by objects in the scene
121 m_log.DebugFormat("[USER MANAGEMENT MODULE]: Caching creators' data from {0} ({1} objects)...", s.RegionInfo.RegionName, s.GetEntities().Length);
122 s.ForEachSOG(delegate(SceneObjectGroup sog) { CacheCreators(sog); });
123 }
124 } 130 }
125 131
126 public void Close() 132 public void Close()
@@ -134,6 +140,14 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
134 140
135 #region Event Handlers 141 #region Event Handlers
136 142
143 void EventManager_OnPrimsLoaded(Scene s)
144 {
145 // let's sniff all the user names referenced by objects in the scene
146 m_log.DebugFormat("[USER MANAGEMENT MODULE]: Caching creators' data from {0} ({1} objects)...", s.RegionInfo.RegionName, s.GetEntities().Length);
147 s.ForEachSOG(delegate(SceneObjectGroup sog) { CacheCreators(sog); });
148 }
149
150
137 void EventManager_OnNewClient(IClientAPI client) 151 void EventManager_OnNewClient(IClientAPI client)
138 { 152 {
139 client.OnNameFromUUIDRequest += new UUIDNameRequest(HandleUUIDNameRequest); 153 client.OnNameFromUUIDRequest += new UUIDNameRequest(HandleUUIDNameRequest);
@@ -150,6 +164,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
150 string[] names = GetUserNames(uuid); 164 string[] names = GetUserNames(uuid);
151 if (names.Length == 2) 165 if (names.Length == 2)
152 { 166 {
167 //m_log.DebugFormat("[XXX] HandleUUIDNameRequest {0} is {1} {2}", uuid, names[0], names[1]);
153 remote_client.SendNameReply(uuid, names[0], names[1]); 168 remote_client.SendNameReply(uuid, names[0], names[1]);
154 } 169 }
155 170
@@ -210,6 +225,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
210 225
211 public string GetUserName(UUID uuid) 226 public string GetUserName(UUID uuid)
212 { 227 {
228 //m_log.DebugFormat("[XXX] GetUserName {0}", uuid);
213 string[] names = GetUserNames(uuid); 229 string[] names = GetUserNames(uuid);
214 if (names.Length == 2) 230 if (names.Length == 2)
215 { 231 {
@@ -222,6 +238,60 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
222 return "(hippos)"; 238 return "(hippos)";
223 } 239 }
224 240
241 public string GetUserHomeURL(UUID userID)
242 {
243 if (m_UserCache.ContainsKey(userID))
244 return m_UserCache[userID].HomeURL;
245
246 return string.Empty;
247 }
248
249 public string GetUserServerURL(UUID userID, string serverType)
250 {
251 if (m_UserCache.ContainsKey(userID))
252 {
253 UserData userdata = m_UserCache[userID];
254 if (userdata.ServerURLs != null && userdata.ServerURLs.ContainsKey(serverType) && userdata.ServerURLs[serverType] != null)
255 return userdata.ServerURLs[serverType].ToString();
256
257 if (userdata.HomeURL != string.Empty)
258 {
259 UserAgentServiceConnector uConn = new UserAgentServiceConnector(userdata.HomeURL);
260 userdata.ServerURLs = uConn.GetServerURLs(userID);
261 if (userdata.ServerURLs != null && userdata.ServerURLs.ContainsKey(serverType) && userdata.ServerURLs[serverType] != null)
262 return userdata.ServerURLs[serverType].ToString();
263 }
264 }
265
266 return string.Empty;
267 }
268
269 public string GetUserUUI(UUID userID)
270 {
271 UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, userID);
272 if (account != null)
273 return userID.ToString();
274
275 if (m_UserCache.ContainsKey(userID))
276 {
277 UserData ud = m_UserCache[userID];
278 string homeURL = ud.HomeURL;
279 string first = ud.FirstName, last = ud.LastName;
280 if (ud.LastName.StartsWith("@"))
281 {
282 string[] parts = ud.FirstName.Split('.');
283 if (parts.Length >= 2)
284 {
285 first = parts[0];
286 last = parts[1];
287 }
288 return userID + ";" + homeURL + ";" + first + " " + last;
289 }
290 }
291
292 return userID.ToString();
293 }
294
225 public void AddUser(UUID id, string creatorData) 295 public void AddUser(UUID id, string creatorData)
226 { 296 {
227 if (m_UserCache.ContainsKey(id)) 297 if (m_UserCache.ContainsKey(id))
@@ -247,13 +317,13 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
247 string[] parts = creatorData.Split(';'); 317 string[] parts = creatorData.Split(';');
248 if (parts.Length >= 1) 318 if (parts.Length >= 1)
249 { 319 {
250 user.ProfileURL = parts[0]; 320 user.HomeURL = parts[0];
251 try 321 try
252 { 322 {
253 Uri uri = new Uri(parts[0]); 323 Uri uri = new Uri(parts[0]);
254 user.LastName = "@" + uri.Authority; 324 user.LastName = "@" + uri.Authority;
255 } 325 }
256 catch 326 catch (UriFormatException)
257 { 327 {
258 m_log.DebugFormat("[SCENE]: Unable to parse Uri {0}", parts[0]); 328 m_log.DebugFormat("[SCENE]: Unable to parse Uri {0}", parts[0]);
259 user.LastName = "@unknown"; 329 user.LastName = "@unknown";
@@ -272,7 +342,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
272 lock (m_UserCache) 342 lock (m_UserCache)
273 m_UserCache[id] = user; 343 m_UserCache[id] = user;
274 344
275 m_log.DebugFormat("[USER MANAGEMENT MODULE]: Added user {0} {1} {2} {3}", user.Id, user.FirstName, user.LastName, user.ProfileURL); 345 m_log.DebugFormat("[USER MANAGEMENT MODULE]: Added user {0} {1} {2} {3}", user.Id, user.FirstName, user.LastName, user.HomeURL);
276 } 346 }
277 347
278 public void AddUser(UUID uuid, string first, string last, string profileURL) 348 public void AddUser(UUID uuid, string first, string last, string profileURL)
@@ -311,5 +381,25 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
311 //} 381 //}
312 382
313 #endregion IUserManagement 383 #endregion IUserManagement
384
385 private void HandleShowUsers(string module, string[] cmd)
386 {
387 if (m_UserCache.Count == 0)
388 {
389 MainConsole.Instance.Output("No users not found");
390 return;
391 }
392
393 MainConsole.Instance.Output("UUID User Name");
394 MainConsole.Instance.Output("-----------------------------------------------------------------------------");
395 foreach (KeyValuePair<UUID, UserData> kvp in m_UserCache)
396 {
397 MainConsole.Instance.Output(String.Format("{0} {1} {2}",
398 kvp.Key, kvp.Value.FirstName, kvp.Value.LastName));
399 }
400 return;
401 }
402
403
314 } 404 }
315} 405}
diff --git a/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs b/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs
index 5ab334f..0c60391 100644
--- a/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs
+++ b/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs
@@ -25,6 +25,7 @@
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 System;
28using System.Collections.Generic; 29using System.Collections.Generic;
29using System.Reflection; 30using System.Reflection;
30using log4net; 31using log4net;
@@ -40,7 +41,10 @@ namespace OpenSim.Region.CoreModules.Hypergrid
40{ 41{
41 public class HGWorldMapModule : WorldMapModule 42 public class HGWorldMapModule : WorldMapModule
42 { 43 {
43 //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 44 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
45
46 // Remember the map area that each client has been exposed to in this region
47 private Dictionary<UUID, List<MapBlockData>> m_SeenMapBlocks = new Dictionary<UUID, List<MapBlockData>>();
44 48
45 #region INonSharedRegionModule Members 49 #region INonSharedRegionModule Members
46 50
@@ -51,6 +55,13 @@ namespace OpenSim.Region.CoreModules.Hypergrid
51 m_Enabled = true; 55 m_Enabled = true;
52 } 56 }
53 57
58 public override void AddRegion(Scene scene)
59 {
60 base.AddRegion(scene);
61
62 scene.EventManager.OnClientClosed += new EventManager.ClientClosed(EventManager_OnClientClosed);
63 }
64
54 public override string Name 65 public override string Name
55 { 66 {
56 get { return "HGWorldMap"; } 67 get { return "HGWorldMap"; }
@@ -58,47 +69,70 @@ namespace OpenSim.Region.CoreModules.Hypergrid
58 69
59 #endregion 70 #endregion
60 71
61 protected override void GetAndSendBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag) 72 void EventManager_OnClientClosed(UUID clientID, Scene scene)
62 { 73 {
63 List<MapBlockData> mapBlocks = new List<MapBlockData>(); 74 ScenePresence sp = scene.GetScenePresence(clientID);
64 List<GridRegion> regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID, 75 if (sp != null)
65 minX * (int)Constants.RegionSize, maxX * (int)Constants.RegionSize,
66 minY * (int)Constants.RegionSize, maxY * (int)Constants.RegionSize);
67
68 foreach (GridRegion r in regions)
69 { 76 {
70 MapBlockData block = new MapBlockData(); 77 if (m_SeenMapBlocks.ContainsKey(clientID))
71 MapBlockFromGridRegion(block, r); 78 {
72 mapBlocks.Add(block); 79 List<MapBlockData> mapBlocks = m_SeenMapBlocks[clientID];
73 } 80 foreach (MapBlockData b in mapBlocks)
74 81 {
75 // Different from super 82 b.Name = string.Empty;
76 FillInMap(mapBlocks, minX, minY, maxX, maxY); 83 b.Access = 254; // means 'simulator is offline'. We need this because the viewer ignores 255's
77 // 84 }
78 85
79 remoteClient.SendMapBlock(mapBlocks, 0); 86 m_log.DebugFormat("[HG MAP]: Reseting {0} blocks", mapBlocks.Count);
87 sp.ControllingClient.SendMapBlock(mapBlocks, 0);
88 m_SeenMapBlocks.Remove(clientID);
89 }
90 }
80 } 91 }
81 92
82 93 protected override List<MapBlockData> GetAndSendBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag)
83 private void FillInMap(List<MapBlockData> mapBlocks, int minX, int minY, int maxX, int maxY)
84 { 94 {
85 for (int x = minX; x <= maxX; x++) 95 List<MapBlockData> mapBlocks = base.GetAndSendBlocks(remoteClient, minX, minY, maxX, maxY, flag);
96 lock (m_SeenMapBlocks)
86 { 97 {
87 for (int y = minY; y <= maxY; y++) 98 if (!m_SeenMapBlocks.ContainsKey(remoteClient.AgentId))
88 { 99 {
89 MapBlockData mblock = mapBlocks.Find(delegate(MapBlockData mb) { return ((mb.X == x) && (mb.Y == y)); }); 100 m_SeenMapBlocks.Add(remoteClient.AgentId, mapBlocks);
90 if (mblock == null) 101 }
91 { 102 else
92 mblock = new MapBlockData(); 103 {
93 mblock.X = (ushort)x; 104 List<MapBlockData> seen = m_SeenMapBlocks[remoteClient.AgentId];
94 mblock.Y = (ushort)y; 105 List<MapBlockData> newBlocks = new List<MapBlockData>();
95 mblock.Name = ""; 106 foreach (MapBlockData b in mapBlocks)
96 mblock.Access = 254; // means 'simulator is offline'. We need this because the viewer ignores 255's 107 if (seen.Find(delegate(MapBlockData bdata) { return bdata.X == b.X && bdata.Y == b.Y; }) == null)
97 mblock.MapImageId = UUID.Zero; 108 newBlocks.Add(b);
98 mapBlocks.Add(mblock); 109 seen.AddRange(newBlocks);
99 }
100 } 110 }
101 } 111 }
112
113 return mapBlocks;
114 }
115
116 }
117
118 class MapArea
119 {
120 public int minX;
121 public int minY;
122 public int maxX;
123 public int maxY;
124
125 public MapArea(int mix, int miy, int max, int may)
126 {
127 minX = mix;
128 minY = miy;
129 maxX = max;
130 maxY = may;
131 }
132
133 public void Print()
134 {
135 Console.WriteLine(String.Format(" --> Area is minX={0} minY={1} minY={2} maxY={3}", minX, minY, maxY, maxY));
102 } 136 }
103 } 137 }
104} 138}
diff --git a/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml b/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml
index 8a6735f..e22fd38 100644
--- a/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml
+++ b/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml
@@ -24,6 +24,7 @@
24 <RegionModule id="UrlModule" type="OpenSim.Region.CoreModules.Scripting.LSLHttp.UrlModule" /> 24 <RegionModule id="UrlModule" type="OpenSim.Region.CoreModules.Scripting.LSLHttp.UrlModule" />
25 <RegionModule id="Chat" type="OpenSim.Region.CoreModules.Avatar.Chat.ChatModule" /> 25 <RegionModule id="Chat" type="OpenSim.Region.CoreModules.Avatar.Chat.ChatModule" />
26 <RegionModule id="FriendsModule" type="OpenSim.Region.CoreModules.Avatar.Friends.FriendsModule" /> 26 <RegionModule id="FriendsModule" type="OpenSim.Region.CoreModules.Avatar.Friends.FriendsModule" />
27 <RegionModule id="HGFriendsModule" type="OpenSim.Region.CoreModules.Avatar.Friends.HGFriendsModule" />
27 <RegionModule id="PresenceModule" type="OpenSim.Region.CoreModules.Avatar.InstantMessage.PresenceModule" /> 28 <RegionModule id="PresenceModule" type="OpenSim.Region.CoreModules.Avatar.InstantMessage.PresenceModule" />
28 <RegionModule id="MuteListModule" type="OpenSim.Region.CoreModules.Avatar.InstantMessage.MuteListModule" /> 29 <RegionModule id="MuteListModule" type="OpenSim.Region.CoreModules.Avatar.InstantMessage.MuteListModule" />
29 <RegionModule id="OfflineMessageModule" type="OpenSim.Region.CoreModules.Avatar.InstantMessage.OfflineMessageModule" /> 30 <RegionModule id="OfflineMessageModule" type="OpenSim.Region.CoreModules.Avatar.InstantMessage.OfflineMessageModule" />
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Hypergrid/HypergridServiceInConnectorModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Hypergrid/HypergridServiceInConnectorModule.cs
index d2343c9..a5b5637 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Hypergrid/HypergridServiceInConnectorModule.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Hypergrid/HypergridServiceInConnectorModule.cs
@@ -113,8 +113,10 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Hypergrid
113 ISimulationService simService = scene.RequestModuleInterface<ISimulationService>(); 113 ISimulationService simService = scene.RequestModuleInterface<ISimulationService>();
114 m_HypergridHandler = new GatekeeperServiceInConnector(m_Config, MainServer.Instance, simService); 114 m_HypergridHandler = new GatekeeperServiceInConnector(m_Config, MainServer.Instance, simService);
115 115
116 new UserAgentServerConnector(m_Config, MainServer.Instance); 116 IFriendsSimConnector friendsConn = scene.RequestModuleInterface<IFriendsSimConnector>();
117 new UserAgentServerConnector(m_Config, MainServer.Instance, friendsConn);
117 new HeloServiceInConnector(m_Config, MainServer.Instance, "HeloService"); 118 new HeloServiceInConnector(m_Config, MainServer.Instance, "HeloService");
119 new HGFriendsServerConnector(m_Config, MainServer.Instance, "HGFriendsService");
118 } 120 }
119 scene.RegisterModuleInterface<IGatekeeperService>(m_HypergridHandler.GateKeeper); 121 scene.RegisterModuleInterface<IGatekeeperService>(m_HypergridHandler.GateKeeper);
120 } 122 }
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsIn/MapImage/MapImageServiceInConnectorModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsIn/MapImage/MapImageServiceInConnectorModule.cs
new file mode 100644
index 0000000..b570155
--- /dev/null
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsIn/MapImage/MapImageServiceInConnectorModule.cs
@@ -0,0 +1,111 @@
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.Collections.Generic;
31using log4net;
32using Mono.Addins;
33using Nini.Config;
34using OpenSim.Framework;
35using OpenSim.Region.Framework.Scenes;
36using OpenSim.Region.Framework.Interfaces;
37using OpenSim.Server.Base;
38using OpenSim.Server.Handlers.Base;
39using OpenSim.Server.Handlers.MapImage;
40using OpenSim.Services.Interfaces;
41
42namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.MapImage
43{
44 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")]
45 public class MapImageServiceInConnectorModule : ISharedRegionModule
46 {
47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
48 private static bool m_Enabled = false;
49
50 private IConfigSource m_Config;
51 bool m_Registered = false;
52
53 #region IRegionModule interface
54
55 public void Initialise(IConfigSource config)
56 {
57 m_Config = config;
58 IConfig moduleConfig = config.Configs["Modules"];
59 if (moduleConfig != null)
60 {
61 m_Enabled = moduleConfig.GetBoolean("MapImageServiceInConnector", false);
62 if (m_Enabled)
63 {
64 m_log.Info("[MAP SERVICE IN CONNECTOR]: MapImage Service In Connector enabled");
65 new MapGetServiceConnector(m_Config, MainServer.Instance, "MapImageService");
66 }
67
68 }
69
70 }
71
72 public void PostInitialise()
73 {
74 }
75
76 public void Close()
77 {
78 }
79
80 public Type ReplaceableInterface
81 {
82 get { return null; }
83 }
84
85 public string Name
86 {
87 get { return "MapImageServiceIn"; }
88 }
89
90 public void AddRegion(Scene scene)
91 {
92 if (!m_Enabled)
93 return;
94 }
95
96 public void RemoveRegion(Scene scene)
97 {
98 if (!m_Enabled)
99 return;
100 }
101
102 public void RegionLoaded(Scene scene)
103 {
104 if (!m_Enabled)
105 return;
106 }
107
108 #endregion
109
110 }
111}
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RegionInfoCache.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RegionInfoCache.cs
new file mode 100644
index 0000000..786e0b5
--- /dev/null
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RegionInfoCache.cs
@@ -0,0 +1,137 @@
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.Reflection;
29using System.Collections.Generic;
30using OpenSim.Framework;
31using OpenSim.Services.Interfaces;
32using OpenMetaverse;
33using log4net;
34using GridRegion = OpenSim.Services.Interfaces.GridRegion;
35
36namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
37{
38 public class RegionInfoCache
39 {
40 private const double CACHE_EXPIRATION_SECONDS = 300.0; // 5 minutes
41
42// private static readonly ILog m_log =
43// LogManager.GetLogger(
44// MethodBase.GetCurrentMethod().DeclaringType);
45
46 internal struct ScopedRegionUUID
47 {
48 public UUID m_scopeID;
49 public UUID m_regionID;
50 public ScopedRegionUUID(UUID scopeID, UUID regionID)
51 {
52 m_scopeID = scopeID;
53 m_regionID = regionID;
54 }
55 }
56
57 internal struct ScopedRegionName
58 {
59 public UUID m_scopeID;
60 public string m_name;
61 public ScopedRegionName(UUID scopeID, string name)
62 {
63 m_scopeID = scopeID;
64 m_name = name;
65 }
66 }
67
68 private ExpiringCache<ScopedRegionUUID, GridRegion> m_UUIDCache;
69 private ExpiringCache<ScopedRegionName, ScopedRegionUUID> m_NameCache;
70
71 public RegionInfoCache()
72 {
73 m_UUIDCache = new ExpiringCache<ScopedRegionUUID, GridRegion>();
74 m_NameCache = new ExpiringCache<ScopedRegionName, ScopedRegionUUID>();
75 }
76
77 public void Cache(GridRegion rinfo)
78 {
79 if (rinfo != null)
80 this.Cache(rinfo.ScopeID,rinfo.RegionID,rinfo);
81 }
82
83 public void Cache(UUID scopeID, UUID regionID, GridRegion rinfo)
84 {
85 // for now, do not cache negative results; this is because
86 // we need to figure out how to handle regions coming online
87 // in a timely way
88 if (rinfo == null)
89 return;
90
91 ScopedRegionUUID id = new ScopedRegionUUID(scopeID,regionID);
92
93 // Cache even null accounts
94 m_UUIDCache.AddOrUpdate(id, rinfo, CACHE_EXPIRATION_SECONDS);
95 if (rinfo != null)
96 {
97 ScopedRegionName name = new ScopedRegionName(scopeID,rinfo.RegionName);
98 m_NameCache.AddOrUpdate(name, id, CACHE_EXPIRATION_SECONDS);
99 }
100 }
101
102 public GridRegion Get(UUID scopeID, UUID regionID, out bool inCache)
103 {
104 inCache = false;
105
106 GridRegion rinfo = null;
107 ScopedRegionUUID id = new ScopedRegionUUID(scopeID,regionID);
108 if (m_UUIDCache.TryGetValue(id, out rinfo))
109 {
110 inCache = true;
111 return rinfo;
112 }
113
114 return null;
115 }
116
117 public GridRegion Get(UUID scopeID, string name, out bool inCache)
118 {
119 inCache = false;
120
121 ScopedRegionName sname = new ScopedRegionName(scopeID,name);
122
123 ScopedRegionUUID id;
124 if (m_NameCache.TryGetValue(sname, out id))
125 {
126 GridRegion rinfo = null;
127 if (m_UUIDCache.TryGetValue(id, out rinfo))
128 {
129 inCache = true;
130 return rinfo;
131 }
132 }
133
134 return null;
135 }
136 }
137}
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RemoteGridServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RemoteGridServiceConnector.cs
index 33cc838..6f364ae 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RemoteGridServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RemoteGridServiceConnector.cs
@@ -53,6 +53,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
53 private IGridService m_LocalGridService; 53 private IGridService m_LocalGridService;
54 private IGridService m_RemoteGridService; 54 private IGridService m_RemoteGridService;
55 55
56 private RegionInfoCache m_RegionInfoCache = new RegionInfoCache();
57
56 public RemoteGridServicesConnector() 58 public RemoteGridServicesConnector()
57 { 59 {
58 } 60 }
@@ -169,10 +171,16 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
169 171
170 public GridRegion GetRegionByUUID(UUID scopeID, UUID regionID) 172 public GridRegion GetRegionByUUID(UUID scopeID, UUID regionID)
171 { 173 {
172 GridRegion rinfo = m_LocalGridService.GetRegionByUUID(scopeID, regionID); 174 bool inCache = false;
175 GridRegion rinfo = m_RegionInfoCache.Get(scopeID,regionID,out inCache);
176 if (inCache)
177 return rinfo;
178
179 rinfo = m_LocalGridService.GetRegionByUUID(scopeID, regionID);
173 if (rinfo == null) 180 if (rinfo == null)
174 rinfo = m_RemoteGridService.GetRegionByUUID(scopeID, regionID); 181 rinfo = m_RemoteGridService.GetRegionByUUID(scopeID, regionID);
175 182
183 m_RegionInfoCache.Cache(scopeID,regionID,rinfo);
176 return rinfo; 184 return rinfo;
177 } 185 }
178 186
@@ -187,10 +195,17 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
187 195
188 public GridRegion GetRegionByName(UUID scopeID, string regionName) 196 public GridRegion GetRegionByName(UUID scopeID, string regionName)
189 { 197 {
190 GridRegion rinfo = m_LocalGridService.GetRegionByName(scopeID, regionName); 198 bool inCache = false;
199 GridRegion rinfo = m_RegionInfoCache.Get(scopeID,regionName, out inCache);
200 if (inCache)
201 return rinfo;
202
203 rinfo = m_LocalGridService.GetRegionByName(scopeID, regionName);
191 if (rinfo == null) 204 if (rinfo == null)
192 rinfo = m_RemoteGridService.GetRegionByName(scopeID, regionName); 205 rinfo = m_RemoteGridService.GetRegionByName(scopeID, regionName);
193 206
207 // can't cache negative results for name lookups
208 m_RegionInfoCache.Cache(rinfo);
194 return rinfo; 209 return rinfo;
195 } 210 }
196 211
@@ -204,8 +219,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
204 { 219 {
205 //m_log.DebugFormat("[REMOTE GRID CONNECTOR]: Remote GetRegionsByName {0} found {1} regions", name, grinfo.Count); 220 //m_log.DebugFormat("[REMOTE GRID CONNECTOR]: Remote GetRegionsByName {0} found {1} regions", name, grinfo.Count);
206 foreach (GridRegion r in grinfo) 221 foreach (GridRegion r in grinfo)
222 {
223 m_RegionInfoCache.Cache(r);
207 if (rinfo.Find(delegate(GridRegion gr) { return gr.RegionID == r.RegionID; }) == null) 224 if (rinfo.Find(delegate(GridRegion gr) { return gr.RegionID == r.RegionID; }) == null)
208 rinfo.Add(r); 225 rinfo.Add(r);
226 }
209 } 227 }
210 228
211 return rinfo; 229 return rinfo;
@@ -221,8 +239,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
221 { 239 {
222 //m_log.DebugFormat("[REMOTE GRID CONNECTOR]: Remote GetRegionRange {0} found {1} regions", name, grinfo.Count); 240 //m_log.DebugFormat("[REMOTE GRID CONNECTOR]: Remote GetRegionRange {0} found {1} regions", name, grinfo.Count);
223 foreach (GridRegion r in grinfo) 241 foreach (GridRegion r in grinfo)
242 {
243 m_RegionInfoCache.Cache(r);
224 if (rinfo.Find(delegate(GridRegion gr) { return gr.RegionID == r.RegionID; }) == null) 244 if (rinfo.Find(delegate(GridRegion gr) { return gr.RegionID == r.RegionID; }) == null)
225 rinfo.Add(r); 245 rinfo.Add(r);
246 }
226 } 247 }
227 248
228 return rinfo; 249 return rinfo;
@@ -238,8 +259,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
238 { 259 {
239 //m_log.DebugFormat("[REMOTE GRID CONNECTOR]: Remote GetDefaultRegions {0} found {1} regions", name, grinfo.Count); 260 //m_log.DebugFormat("[REMOTE GRID CONNECTOR]: Remote GetDefaultRegions {0} found {1} regions", name, grinfo.Count);
240 foreach (GridRegion r in grinfo) 261 foreach (GridRegion r in grinfo)
262 {
263 m_RegionInfoCache.Cache(r);
241 if (rinfo.Find(delegate(GridRegion gr) { return gr.RegionID == r.RegionID; }) == null) 264 if (rinfo.Find(delegate(GridRegion gr) { return gr.RegionID == r.RegionID; }) == null)
242 rinfo.Add(r); 265 rinfo.Add(r);
266 }
243 } 267 }
244 268
245 return rinfo; 269 return rinfo;
@@ -255,8 +279,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
255 { 279 {
256 //m_log.DebugFormat("[REMOTE GRID CONNECTOR]: Remote GetFallbackRegions {0} found {1} regions", name, grinfo.Count); 280 //m_log.DebugFormat("[REMOTE GRID CONNECTOR]: Remote GetFallbackRegions {0} found {1} regions", name, grinfo.Count);
257 foreach (GridRegion r in grinfo) 281 foreach (GridRegion r in grinfo)
282 {
283 m_RegionInfoCache.Cache(r);
258 if (rinfo.Find(delegate(GridRegion gr) { return gr.RegionID == r.RegionID; }) == null) 284 if (rinfo.Find(delegate(GridRegion gr) { return gr.RegionID == r.RegionID; }) == null)
259 rinfo.Add(r); 285 rinfo.Add(r);
286 }
260 } 287 }
261 288
262 return rinfo; 289 return rinfo;
@@ -272,8 +299,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
272 { 299 {
273 //m_log.DebugFormat("[REMOTE GRID CONNECTOR]: Remote GetHyperlinks {0} found {1} regions", name, grinfo.Count); 300 //m_log.DebugFormat("[REMOTE GRID CONNECTOR]: Remote GetHyperlinks {0} found {1} regions", name, grinfo.Count);
274 foreach (GridRegion r in grinfo) 301 foreach (GridRegion r in grinfo)
302 {
303 m_RegionInfoCache.Cache(r);
275 if (rinfo.Find(delegate(GridRegion gr) { return gr.RegionID == r.RegionID; }) == null) 304 if (rinfo.Find(delegate(GridRegion gr) { return gr.RegionID == r.RegionID; }) == null)
276 rinfo.Add(r); 305 rinfo.Add(r);
306 }
277 } 307 }
278 308
279 return rinfo; 309 return rinfo;
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs
index 3f63db3..698fd56 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs
@@ -58,6 +58,17 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
58 58
59 private List<Scene> m_Scenes = new List<Scene>(); 59 private List<Scene> m_Scenes = new List<Scene>();
60 60
61 protected IUserManagement m_UserManagement;
62 protected IUserManagement UserManagementModule
63 {
64 get
65 {
66 if (m_UserManagement == null)
67 m_UserManagement = m_Scenes[0].RequestModuleInterface<IUserManagement>();
68 return m_UserManagement;
69 }
70 }
71
61 public Type ReplaceableInterface 72 public Type ReplaceableInterface
62 { 73 {
63 get { return null; } 74 get { return null; }
@@ -207,6 +218,18 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
207 } 218 }
208 } 219 }
209 } 220 }
221 if (sp == null)
222 {
223 inventoryURL = UserManagementModule.GetUserServerURL(userID, "InventoryServerURI");
224 if (inventoryURL != null && inventoryURL != string.Empty)
225 {
226 inventoryURL = inventoryURL.Trim(new char[] { '/' });
227 m_InventoryURLs.Add(userID, inventoryURL);
228 m_log.DebugFormat("[HG INVENTORY CONNECTOR]: Added {0} to the cache of inventory URLs", inventoryURL);
229 }
230
231 }
232
210 } 233 }
211 } 234 }
212 235
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs
new file mode 100644
index 0000000..e224670
--- /dev/null
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs
@@ -0,0 +1,242 @@
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.Net;
32using System.IO;
33using System.Timers;
34using System.Drawing;
35using System.Drawing.Imaging;
36
37using log4net;
38using Mono.Addins;
39using Nini.Config;
40using OpenSim.Framework;
41using OpenSim.Region.Framework.Interfaces;
42using OpenSim.Region.Framework.Scenes;
43using OpenSim.Services.Interfaces;
44using OpenSim.Server.Base;
45using OpenMetaverse;
46using OpenMetaverse.StructuredData;
47
48namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage
49{
50 /// <summary>
51 /// </summary>
52 /// <remarks>
53 /// </remarks>
54
55 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")]
56 public class MapImageServiceModule : ISharedRegionModule
57 {
58 private static readonly ILog m_log =
59 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
60
61 private bool m_enabled = false;
62 private IMapImageService m_MapService;
63
64 private string m_serverUrl = String.Empty;
65 private Dictionary<UUID, Scene> m_scenes = new Dictionary<UUID, Scene>();
66
67 private int m_refreshtime = 0;
68 private int m_lastrefresh = 0;
69 private System.Timers.Timer m_refreshTimer = new System.Timers.Timer();
70
71 #region ISharedRegionModule
72
73 public Type ReplaceableInterface { get { return null; } }
74 public string Name { get { return "MapImageServiceModule"; } }
75 public void RegionLoaded(Scene scene) { }
76 public void Close() { }
77 public void PostInitialise() { }
78
79
80 ///<summary>
81 ///
82 ///</summary>
83 public void Initialise(IConfigSource source)
84 {
85 IConfig moduleConfig = source.Configs["Modules"];
86 if (moduleConfig != null)
87 {
88 string name = moduleConfig.GetString("MapImageService", "");
89 if (name != Name)
90 return;
91 }
92
93 IConfig config = source.Configs["MapImageService"];
94 if (config == null)
95 return;
96
97 int refreshminutes = Convert.ToInt32(config.GetString("RefreshTime"));
98 if (refreshminutes <= 0)
99 {
100 m_log.WarnFormat("[MAP IMAGE SERVICE MODULE]: No refresh time given in config. Module disabled.");
101 return;
102 }
103
104 m_refreshtime = refreshminutes * 60 * 1000; // convert from minutes to ms
105
106 string service = config.GetString("LocalServiceModule", string.Empty);
107 if (service == string.Empty)
108 {
109 m_log.WarnFormat("[MAP IMAGE SERVICE MODULE]: No service dll given in config. Unable to proceed.");
110 return;
111 }
112
113 Object[] args = new Object[] { source };
114 m_MapService = ServerUtils.LoadPlugin<IMapImageService>(service, args);
115 if (m_MapService == null)
116 {
117 m_log.WarnFormat("[MAP IMAGE SERVICE MODULE]: Unable to load LocalServiceModule from {0}. MapService module disabled. Please fix the configuration.", service);
118 return;
119 }
120
121 m_refreshTimer.Enabled = true;
122 m_refreshTimer.AutoReset = true;
123 m_refreshTimer.Interval = m_refreshtime;
124 m_refreshTimer.Elapsed += new ElapsedEventHandler(HandleMaptileRefresh);
125
126 m_log.InfoFormat("[MAP IMAGE SERVICE MODULE]: enabled with refresh time {0}min and service object {1}",
127 refreshminutes, service);
128
129 m_enabled = true;
130 }
131
132 ///<summary>
133 ///
134 ///</summary>
135
136
137 ///<summary>
138 ///
139 ///</summary>
140 public void AddRegion(Scene scene)
141 {
142 if (! m_enabled)
143 return;
144
145 // Every shared region module has to maintain an indepedent list of
146 // currently running regions
147 lock (m_scenes)
148 m_scenes[scene.RegionInfo.RegionID] = scene;
149
150 scene.EventManager.OnPrimsLoaded += new EventManager.PrimsLoaded(EventManager_OnPrimsLoaded);
151 }
152
153 ///<summary>
154 ///
155 ///</summary>
156 public void RemoveRegion(Scene scene)
157 {
158 if (! m_enabled)
159 return;
160
161 lock (m_scenes)
162 m_scenes.Remove(scene.RegionInfo.RegionID);
163 }
164
165 #endregion ISharedRegionModule
166
167 void EventManager_OnPrimsLoaded(Scene s)
168 {
169 UploadMapTile(s);
170 }
171
172
173 ///<summary>
174 ///
175 ///</summary>
176 private void HandleMaptileRefresh(object sender, EventArgs ea)
177 {
178 // this approach is a bit convoluted becase we want to wait for the
179 // first upload to happen on startup but after all the objects are
180 // loaded and initialized
181 if (m_lastrefresh > 0 && Util.EnvironmentTickCountSubtract(m_lastrefresh) < m_refreshtime)
182 return;
183
184 m_log.DebugFormat("[MAP IMAGE SERVICE MODULE]: map refresh!");
185 lock (m_scenes)
186 {
187 foreach (IScene scene in m_scenes.Values)
188 {
189 try
190 {
191 UploadMapTile(scene);
192 }
193 catch (Exception ex)
194 {
195 m_log.WarnFormat("[MAP IMAGE SERVICE MODULE]: something bad happened {0}", ex.Message);
196 }
197 }
198 }
199
200 m_lastrefresh = Util.EnvironmentTickCount();
201 }
202
203 ///<summary>
204 ///
205 ///</summary>
206 private void UploadMapTile(IScene scene)
207 {
208 m_log.DebugFormat("[MAP IMAGE SERVICE MODULE]: upload maptile for {0}", scene.RegionInfo.RegionName);
209
210 // Create a JPG map tile and upload it to the AddMapTile API
211 byte[] jpgData = Utils.EmptyBytes;
212 IMapImageGenerator tileGenerator = scene.RequestModuleInterface<IMapImageGenerator>();
213 if (tileGenerator == null)
214 {
215 m_log.Warn("[MAP IMAGE SERVICE MODULE]: Cannot upload PNG map tile without an ImageGenerator");
216 return;
217 }
218
219 using (Image mapTile = tileGenerator.CreateMapTile())
220 {
221 using (MemoryStream stream = new MemoryStream())
222 {
223 mapTile.Save(stream, ImageFormat.Jpeg);
224 jpgData = stream.ToArray();
225 }
226 }
227
228 if (jpgData == Utils.EmptyBytes)
229 {
230 m_log.WarnFormat("[MAP IMAGE SERVICE MODULE]: Tile image generation failed");
231 return;
232 }
233
234 string reason = string.Empty;
235 if (!m_MapService.AddMapTile((int)scene.RegionInfo.RegionLocX, (int)scene.RegionInfo.RegionLocY, jpgData, out reason))
236 {
237 m_log.DebugFormat("[MAP IMAGE SERVICE MODULE]: Unable to upload tile image for {0} at {1}-{2}: {3}",
238 scene.RegionInfo.RegionName, scene.RegionInfo.RegionLocX, scene.RegionInfo.RegionLocY, reason);
239 }
240 }
241 }
242} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
index d11d677..f85a917 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
@@ -506,6 +506,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
506 currentRegionSettings.Elevation2SE = loadedRegionSettings.Elevation2SE; 506 currentRegionSettings.Elevation2SE = loadedRegionSettings.Elevation2SE;
507 currentRegionSettings.Elevation2SW = loadedRegionSettings.Elevation2SW; 507 currentRegionSettings.Elevation2SW = loadedRegionSettings.Elevation2SW;
508 currentRegionSettings.FixedSun = loadedRegionSettings.FixedSun; 508 currentRegionSettings.FixedSun = loadedRegionSettings.FixedSun;
509 currentRegionSettings.SunPosition = loadedRegionSettings.SunPosition;
509 currentRegionSettings.ObjectBonus = loadedRegionSettings.ObjectBonus; 510 currentRegionSettings.ObjectBonus = loadedRegionSettings.ObjectBonus;
510 currentRegionSettings.RestrictPushing = loadedRegionSettings.RestrictPushing; 511 currentRegionSettings.RestrictPushing = loadedRegionSettings.RestrictPushing;
511 currentRegionSettings.TerrainLowerLimit = loadedRegionSettings.TerrainLowerLimit; 512 currentRegionSettings.TerrainLowerLimit = loadedRegionSettings.TerrainLowerLimit;
@@ -518,6 +519,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver
518 currentRegionSettings.WaterHeight = loadedRegionSettings.WaterHeight; 519 currentRegionSettings.WaterHeight = loadedRegionSettings.WaterHeight;
519 520
520 currentRegionSettings.Save(); 521 currentRegionSettings.Save();
522
523 m_scene.TriggerEstateSunUpdate();
521 524
522 IEstateModule estateModule = m_scene.RequestModuleInterface<IEstateModule>(); 525 IEstateModule estateModule = m_scene.RequestModuleInterface<IEstateModule>();
523 526
diff --git a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs
index 5da1656..f8f3713 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs
@@ -198,11 +198,11 @@ namespace OpenSim.Region.CoreModules.World.Archiver
198 m_log.ErrorFormat( 198 m_log.ErrorFormat(
199 "[ARCHIVER]: (... {0} more not shown)", uuids.Count - MAX_UUID_DISPLAY_ON_TIMEOUT); 199 "[ARCHIVER]: (... {0} more not shown)", uuids.Count - MAX_UUID_DISPLAY_ON_TIMEOUT);
200 200
201 m_log.Error("[ARCHIVER]: OAR save aborted. PLEASE DO NOT USE THIS OAR, IT WILL BE INCOMPLETE."); 201 m_log.Error("[ARCHIVER]: Archive save aborted. PLEASE DO NOT USE THIS ARCHIVE, IT WILL BE INCOMPLETE.");
202 } 202 }
203 catch (Exception e) 203 catch (Exception e)
204 { 204 {
205 m_log.ErrorFormat("[ARCHIVER]: Timeout handler exception {0}", e); 205 m_log.ErrorFormat("[ARCHIVER]: Timeout handler exception {0}{1}", e.Message, e.StackTrace);
206 } 206 }
207 finally 207 finally
208 { 208 {
@@ -230,6 +230,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver
230 /// <param name="asset"></param> 230 /// <param name="asset"></param>
231 public void AssetRequestCallback(string id, object sender, AssetBase asset) 231 public void AssetRequestCallback(string id, object sender, AssetBase asset)
232 { 232 {
233 Culture.SetCurrentCulture();
234
233 try 235 try
234 { 236 {
235 lock (this) 237 lock (this)
@@ -289,6 +291,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver
289 /// </summary> 291 /// </summary>
290 protected void PerformAssetsRequestCallback(object o) 292 protected void PerformAssetsRequestCallback(object o)
291 { 293 {
294 Culture.SetCurrentCulture();
295
292 try 296 try
293 { 297 {
294 m_assetsRequestCallback(m_foundAssetUuids, m_notFoundAssetUuids); 298 m_assetsRequestCallback(m_foundAssetUuids, m_notFoundAssetUuids);
diff --git a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs
index 34e2e23..6ba3459 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs
@@ -440,6 +440,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
440 rs.Elevation2SE = 9.2; 440 rs.Elevation2SE = 9.2;
441 rs.Elevation2SW = 2.1; 441 rs.Elevation2SW = 2.1;
442 rs.FixedSun = true; 442 rs.FixedSun = true;
443 rs.SunPosition = 12.0;
443 rs.ObjectBonus = 1.4; 444 rs.ObjectBonus = 1.4;
444 rs.RestrictPushing = true; 445 rs.RestrictPushing = true;
445 rs.TerrainLowerLimit = 0.4; 446 rs.TerrainLowerLimit = 0.4;
@@ -485,6 +486,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
485 Assert.That(loadedRs.Elevation2SE, Is.EqualTo(9.2)); 486 Assert.That(loadedRs.Elevation2SE, Is.EqualTo(9.2));
486 Assert.That(loadedRs.Elevation2SW, Is.EqualTo(2.1)); 487 Assert.That(loadedRs.Elevation2SW, Is.EqualTo(2.1));
487 Assert.That(loadedRs.FixedSun, Is.True); 488 Assert.That(loadedRs.FixedSun, Is.True);
489 Assert.AreEqual(12.0, loadedRs.SunPosition);
488 Assert.That(loadedRs.ObjectBonus, Is.EqualTo(1.4)); 490 Assert.That(loadedRs.ObjectBonus, Is.EqualTo(1.4));
489 Assert.That(loadedRs.RestrictPushing, Is.True); 491 Assert.That(loadedRs.RestrictPushing, Is.True);
490 Assert.That(loadedRs.TerrainLowerLimit, Is.EqualTo(0.4)); 492 Assert.That(loadedRs.TerrainLowerLimit, Is.EqualTo(0.4));
diff --git a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
index a098ff6..43b37c7 100644
--- a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
+++ b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
@@ -548,18 +548,18 @@ namespace OpenSim.Region.CoreModules.World.Permissions
548 548
549 // libomv will moan about PrimFlags.ObjectYouOfficer being 549 // libomv will moan about PrimFlags.ObjectYouOfficer being
550 // deprecated 550 // deprecated
551 #pragma warning disable 0612 551#pragma warning disable 0612
552 objflags &= (uint) 552 objflags &= (uint)
553 ~(PrimFlags.ObjectCopy | // Tells client you can copy the object 553 ~(PrimFlags.ObjectCopy | // Tells client you can copy the object
554 PrimFlags.ObjectModify | // tells client you can modify the object 554 PrimFlags.ObjectModify | // tells client you can modify the object
555 PrimFlags.ObjectMove | // tells client that you can move the object (only, no mod) 555 PrimFlags.ObjectMove | // tells client that you can move the object (only, no mod)
556 PrimFlags.ObjectTransfer | // tells the client that you can /take/ the object if you don't own it 556 PrimFlags.ObjectTransfer | // tells the client that you can /take/ the object if you don't own it
557 PrimFlags.ObjectYouOwner | // Tells client that you're the owner of the object 557 PrimFlags.ObjectYouOwner | // Tells client that you're the owner of the object
558 PrimFlags.ObjectAnyOwner | // Tells client that someone owns the object 558 PrimFlags.ObjectAnyOwner | // Tells client that someone owns the object
559 PrimFlags.ObjectOwnerModify | // Tells client that you're the owner of the object 559 PrimFlags.ObjectOwnerModify | // Tells client that you're the owner of the object
560 PrimFlags.ObjectYouOfficer // Tells client that you've got group object editing permission. Used when ObjectGroupOwned is set 560 PrimFlags.ObjectYouOfficer // Tells client that you've got group object editing permission. Used when ObjectGroupOwned is set
561 ); 561 );
562 #pragma warning restore 0612 562#pragma warning restore 0612
563 563
564 // Creating the three ObjectFlags options for this method to choose from. 564 // Creating the three ObjectFlags options for this method to choose from.
565 // Customize the OwnerMask 565 // Customize the OwnerMask
@@ -576,22 +576,27 @@ namespace OpenSim.Region.CoreModules.World.Permissions
576 576
577 if (m_bypassPermissions) 577 if (m_bypassPermissions)
578 return objectOwnerMask; 578 return objectOwnerMask;
579 579
580 // Object owners should be able to edit their own content 580 // Object owners should be able to edit their own content
581 if (user == objectOwner) 581 if (user == objectOwner)
582 return objectOwnerMask; 582 return objectOwnerMask;
583 583
584 if (IsFriendWithPerms(user, objectOwner)) 584 if (IsFriendWithPerms(user, objectOwner))
585 {
585 return objectOwnerMask; 586 return objectOwnerMask;
586 587 }
587 // Estate users should be able to edit anything in the sim if RegionOwnerIsGod is set 588 // Estate users should be able to edit anything in the sim if RegionOwnerIsGod is set
588 if (m_RegionOwnerIsGod && IsEstateManager(user) && !IsAdministrator(objectOwner)) 589 if (m_RegionOwnerIsGod && IsEstateManager(user) && !IsAdministrator(objectOwner))
590 {
589 return objectOwnerMask; 591 return objectOwnerMask;
592 }
590 593
591 // Admin should be able to edit anything in the sim (including admin objects) 594 // Admin should be able to edit anything in the sim (including admin objects)
592 if (IsAdministrator(user)) 595 if (IsAdministrator(user))
596 {
593 return objectOwnerMask; 597 return objectOwnerMask;
594 598 }
599
595 // Users should be able to edit what is over their land. 600 // Users should be able to edit what is over their land.
596 Vector3 taskPos = task.AbsolutePosition; 601 Vector3 taskPos = task.AbsolutePosition;
597 ILandObject parcel = m_scene.LandChannel.GetLandObject(taskPos.X, taskPos.Y); 602 ILandObject parcel = m_scene.LandChannel.GetLandObject(taskPos.X, taskPos.Y);
@@ -599,13 +604,15 @@ namespace OpenSim.Region.CoreModules.World.Permissions
599 { 604 {
600 // Admin objects should not be editable by the above 605 // Admin objects should not be editable by the above
601 if (!IsAdministrator(objectOwner)) 606 if (!IsAdministrator(objectOwner))
607 {
602 return objectOwnerMask; 608 return objectOwnerMask;
609 }
603 } 610 }
604 611
605 // Group permissions 612 // Group permissions
606 if ((task.GroupID != UUID.Zero) && IsGroupMember(task.GroupID, user, 0)) 613 if ((task.GroupID != UUID.Zero) && IsGroupMember(task.GroupID, user, 0))
607 return objectGroupMask | objectEveryoneMask; 614 return objectGroupMask | objectEveryoneMask;
608 615
609 return objectEveryoneMask; 616 return objectEveryoneMask;
610 } 617 }
611 618
@@ -673,7 +680,6 @@ namespace OpenSim.Region.CoreModules.World.Permissions
673 // 680 //
674 // Nobody but the object owner can set permissions on an object 681 // Nobody but the object owner can set permissions on an object
675 // 682 //
676
677 if (locked && (!IsAdministrator(currentUser)) && denyOnLocked) 683 if (locked && (!IsAdministrator(currentUser)) && denyOnLocked)
678 { 684 {
679 return false; 685 return false;
@@ -704,6 +710,11 @@ namespace OpenSim.Region.CoreModules.World.Permissions
704 // Return immediately, so that the administrator can shares group objects 710 // Return immediately, so that the administrator can shares group objects
705 return true; 711 return true;
706 } 712 }
713
714 // Friends with benefits should be able to edit the objects too
715 if (IsFriendWithPerms(currentUser, objectOwner))
716 // Return immediately, so that the administrator can share objects with friends
717 return true;
707 718
708 // Users should be able to edit what is over their land. 719 // Users should be able to edit what is over their land.
709 ILandObject parcel = m_scene.LandChannel.GetLandObject(group.AbsolutePosition.X, group.AbsolutePosition.Y); 720 ILandObject parcel = m_scene.LandChannel.GetLandObject(group.AbsolutePosition.X, group.AbsolutePosition.Y);
diff --git a/OpenSim/Region/CoreModules/World/Warp3DMap/MapImageModule.cs b/OpenSim/Region/CoreModules/World/Warp3DMap/MapImageModule.cs
index 6eb57eb..6163fd1 100644
--- a/OpenSim/Region/CoreModules/World/Warp3DMap/MapImageModule.cs
+++ b/OpenSim/Region/CoreModules/World/Warp3DMap/MapImageModule.cs
@@ -52,7 +52,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
52 public class Warp3DImageModule : IMapImageGenerator, INonSharedRegionModule 52 public class Warp3DImageModule : IMapImageGenerator, INonSharedRegionModule
53 { 53 {
54 private static readonly UUID TEXTURE_METADATA_MAGIC = new UUID("802dc0e0-f080-4931-8b57-d1be8611c4f3"); 54 private static readonly UUID TEXTURE_METADATA_MAGIC = new UUID("802dc0e0-f080-4931-8b57-d1be8611c4f3");
55 private static readonly Color4 WATER_COLOR = new Color4(29, 71, 95, 216); 55 private static readonly Color4 WATER_COLOR = new Color4(29, 72, 96, 216);
56 56
57 private static readonly ILog m_log = 57 private static readonly ILog m_log =
58 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 58 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
@@ -61,7 +61,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
61 private IRendering m_primMesher; 61 private IRendering m_primMesher;
62 private IConfigSource m_config; 62 private IConfigSource m_config;
63 private Dictionary<UUID, Color4> m_colors = new Dictionary<UUID, Color4>(); 63 private Dictionary<UUID, Color4> m_colors = new Dictionary<UUID, Color4>();
64 private bool m_useAntiAliasing = true; // TODO: Make this a config option 64 private bool m_useAntiAliasing = false; // TODO: Make this a config option
65 private bool m_Enabled = false; 65 private bool m_Enabled = false;
66 66
67 #region IRegionModule Members 67 #region IRegionModule Members
@@ -192,8 +192,8 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
192 192
193 #endregion Camera 193 #endregion Camera
194 194
195 renderer.Scene.addLight("Light1", new warp_Light(new warp_Vector(0.2f, 0.2f, 1f), 0xffffff, 320, 80)); 195 renderer.Scene.addLight("Light1", new warp_Light(new warp_Vector(1.0f, 0.5f, 1f), 0xffffff, 0, 320, 40));
196 renderer.Scene.addLight("Light2", new warp_Light(new warp_Vector(-1f, -1f, 1f), 0xffffff, 100, 40)); 196 renderer.Scene.addLight("Light2", new warp_Light(new warp_Vector(-1f, -1f, 1f), 0xffffff, 0, 100, 40));
197 197
198 CreateWater(renderer); 198 CreateWater(renderer);
199 CreateTerrain(renderer, textureTerrain); 199 CreateTerrain(renderer, textureTerrain);
@@ -237,6 +237,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
237 renderer.Scene.sceneobject("Water").setPos(127.5f, waterHeight, 127.5f); 237 renderer.Scene.sceneobject("Water").setPos(127.5f, waterHeight, 127.5f);
238 238
239 renderer.AddMaterial("WaterColor", ConvertColor(WATER_COLOR)); 239 renderer.AddMaterial("WaterColor", ConvertColor(WATER_COLOR));
240 renderer.Scene.material("WaterColor").setReflectivity(0); // match water color with standard map module thanks lkalif
240 renderer.Scene.material("WaterColor").setTransparency((byte)((1f - WATER_COLOR.A) * 255f)); 241 renderer.Scene.material("WaterColor").setTransparency((byte)((1f - WATER_COLOR.A) * 255f));
241 renderer.SetObjectMaterial("Water", "WaterColor"); 242 renderer.SetObjectMaterial("Water", "WaterColor");
242 } 243 }
@@ -322,6 +323,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
322 warp_Material material = new warp_Material(texture); 323 warp_Material material = new warp_Material(texture);
323 material.setReflectivity(50); 324 material.setReflectivity(50);
324 renderer.Scene.addMaterial("TerrainColor", material); 325 renderer.Scene.addMaterial("TerrainColor", material);
326 renderer.Scene.material("TerrainColor").setReflectivity(0); // reduces tile seams a bit thanks lkalif
325 renderer.SetObjectMaterial("Terrain", "TerrainColor"); 327 renderer.SetObjectMaterial("Terrain", "TerrainColor");
326 } 328 }
327 329
@@ -653,4 +655,4 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
653 return result; 655 return result;
654 } 656 }
655 } 657 }
656} 658} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
index cd40c5d..ca5529d9 100644
--- a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
+++ b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
@@ -208,52 +208,65 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
208 //m_log.DebugFormat("[MAPLAYER]: path: {0}, param: {1}, agent:{2}", 208 //m_log.DebugFormat("[MAPLAYER]: path: {0}, param: {1}, agent:{2}",
209 // path, param, agentID.ToString()); 209 // path, param, agentID.ToString());
210 210
211 // this is here because CAPS map requests work even beyond the 10,000 limit. 211 // There is a major hack going on in this method. The viewer doesn't request
212 ScenePresence avatarPresence = null; 212 // map blocks (RequestMapBlocks) above 2048. That means that if we don't hack,
213 213 // grids above that cell don't have a map at all. So, here's the hack: we wait
214 m_scene.TryGetScenePresence(agentID, out avatarPresence); 214 // for this CAP request to come, and we inject the map blocks at this point.
215 215 // In a normal scenario, this request simply sends back the MapLayer (the blue color).
216 if (avatarPresence != null) 216 // In the hacked scenario, it also sends the map blocks via UDP.
217 //
218 // 6/8/2011 -- I'm adding an explicit 2048 check, so that we never forget that there is
219 // a hack here, and so that regions below 4096 don't get spammed with unnecessary map blocks.
220
221 if (m_scene.RegionInfo.RegionLocX >= 2048 || m_scene.RegionInfo.RegionLocY >= 2048)
217 { 222 {
218 bool lookup = false; 223 ScenePresence avatarPresence = null;
219 224
220 lock (cachedMapBlocks) 225 m_scene.TryGetScenePresence(agentID, out avatarPresence);
221 {
222 if (cachedMapBlocks.Count > 0 && ((cachedTime + 1800) > Util.UnixTimeSinceEpoch()))
223 {
224 List<MapBlockData> mapBlocks;
225 226
226 mapBlocks = cachedMapBlocks; 227 if (avatarPresence != null)
227 avatarPresence.ControllingClient.SendMapBlock(mapBlocks, 0);
228 }
229 else
230 {
231 lookup = true;
232 }
233 }
234 if (lookup)
235 { 228 {
236 List<MapBlockData> mapBlocks = new List<MapBlockData>(); ; 229 bool lookup = false;
237 230
238 List<GridRegion> regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID, 231 lock (cachedMapBlocks)
239 (int)(m_scene.RegionInfo.RegionLocX - 8) * (int)Constants.RegionSize,
240 (int)(m_scene.RegionInfo.RegionLocX + 8) * (int)Constants.RegionSize,
241 (int)(m_scene.RegionInfo.RegionLocY - 8) * (int)Constants.RegionSize,
242 (int)(m_scene.RegionInfo.RegionLocY + 8) * (int)Constants.RegionSize);
243 foreach (GridRegion r in regions)
244 { 232 {
245 MapBlockData block = new MapBlockData(); 233 if (cachedMapBlocks.Count > 0 && ((cachedTime + 1800) > Util.UnixTimeSinceEpoch()))
246 MapBlockFromGridRegion(block, r); 234 {
247 mapBlocks.Add(block); 235 List<MapBlockData> mapBlocks;
236
237 mapBlocks = cachedMapBlocks;
238 avatarPresence.ControllingClient.SendMapBlock(mapBlocks, 0);
239 }
240 else
241 {
242 lookup = true;
243 }
248 } 244 }
249 avatarPresence.ControllingClient.SendMapBlock(mapBlocks, 0); 245 if (lookup)
246 {
247 List<MapBlockData> mapBlocks = new List<MapBlockData>(); ;
248
249 List<GridRegion> regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID,
250 (int)(m_scene.RegionInfo.RegionLocX - 8) * (int)Constants.RegionSize,
251 (int)(m_scene.RegionInfo.RegionLocX + 8) * (int)Constants.RegionSize,
252 (int)(m_scene.RegionInfo.RegionLocY - 8) * (int)Constants.RegionSize,
253 (int)(m_scene.RegionInfo.RegionLocY + 8) * (int)Constants.RegionSize);
254 foreach (GridRegion r in regions)
255 {
256 MapBlockData block = new MapBlockData();
257 MapBlockFromGridRegion(block, r);
258 mapBlocks.Add(block);
259 }
260 avatarPresence.ControllingClient.SendMapBlock(mapBlocks, 0);
250 261
251 lock (cachedMapBlocks) 262 lock (cachedMapBlocks)
252 cachedMapBlocks = mapBlocks; 263 cachedMapBlocks = mapBlocks;
253 264
254 cachedTime = Util.UnixTimeSinceEpoch(); 265 cachedTime = Util.UnixTimeSinceEpoch();
266 }
255 } 267 }
256 } 268 }
269
257 LLSDMapLayerResponse mapResponse = new LLSDMapLayerResponse(); 270 LLSDMapLayerResponse mapResponse = new LLSDMapLayerResponse();
258 mapResponse.LayerData.Array.Add(GetOSDMapLayerResponse()); 271 mapResponse.LayerData.Array.Add(GetOSDMapLayerResponse());
259 return mapResponse.ToString(); 272 return mapResponse.ToString();
@@ -823,7 +836,10 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
823 block.Access = 254; // means 'simulator is offline' 836 block.Access = 254; // means 'simulator is offline'
824 response.Add(block); 837 response.Add(block);
825 } 838 }
826 remoteClient.SendMapBlock(response, 0); 839 if ((flag & 2) == 2) // V2 !!!
840 remoteClient.SendMapBlock(response, 2);
841 else
842 remoteClient.SendMapBlock(response, 0);
827 } 843 }
828 else 844 else
829 { 845 {
@@ -832,7 +848,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
832 } 848 }
833 } 849 }
834 850
835 protected virtual void GetAndSendBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag) 851 protected virtual List<MapBlockData> GetAndSendBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag)
836 { 852 {
837 List<MapBlockData> mapBlocks = new List<MapBlockData>(); 853 List<MapBlockData> mapBlocks = new List<MapBlockData>();
838 List<GridRegion> regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID, 854 List<GridRegion> regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID,
@@ -846,7 +862,12 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
846 MapBlockFromGridRegion(block, r); 862 MapBlockFromGridRegion(block, r);
847 mapBlocks.Add(block); 863 mapBlocks.Add(block);
848 } 864 }
849 remoteClient.SendMapBlock(mapBlocks, 0); 865 if ((flag & 2) == 2) // V2 !!!
866 remoteClient.SendMapBlock(mapBlocks, 2);
867 else
868 remoteClient.SendMapBlock(mapBlocks, 0);
869
870 return mapBlocks;
850 } 871 }
851 872
852 protected void MapBlockFromGridRegion(MapBlockData block, GridRegion r) 873 protected void MapBlockFromGridRegion(MapBlockData block, GridRegion r)