aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/CoreModules/Framework
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/CoreModules/Framework')
-rw-r--r--OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs1602
-rw-r--r--OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs273
-rw-r--r--OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs200
-rw-r--r--OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs207
-rw-r--r--OpenSim/Region/CoreModules/Framework/InventoryAccess/HGUuidGatherer.cs57
-rw-r--r--OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs655
-rw-r--r--OpenSim/Region/CoreModules/Framework/Library/LibraryModule.cs52
-rw-r--r--OpenSim/Region/CoreModules/Framework/Library/LocalInventoryService.cs6
8 files changed, 3036 insertions, 16 deletions
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
new file mode 100644
index 0000000..80c0af8
--- /dev/null
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
@@ -0,0 +1,1602 @@
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.Net;
31using System.Reflection;
32using System.Threading;
33
34using OpenSim.Framework;
35using OpenSim.Framework.Capabilities;
36using OpenSim.Framework.Client;
37using OpenSim.Region.Framework.Interfaces;
38using OpenSim.Region.Framework.Scenes;
39using OpenSim.Services.Interfaces;
40
41using GridRegion = OpenSim.Services.Interfaces.GridRegion;
42
43using OpenMetaverse;
44using log4net;
45using Nini.Config;
46
47namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
48{
49 public class EntityTransferModule : ISharedRegionModule, IEntityTransferModule
50 {
51 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
52
53 protected bool m_Enabled = false;
54 protected Scene m_aScene;
55 protected List<UUID> m_agentsInTransit;
56
57 #region ISharedRegionModule
58
59 public Type ReplaceableInterface
60 {
61 get { return null; }
62 }
63
64 public virtual string Name
65 {
66 get { return "BasicEntityTransferModule"; }
67 }
68
69 public virtual void Initialise(IConfigSource source)
70 {
71 IConfig moduleConfig = source.Configs["Modules"];
72 if (moduleConfig != null)
73 {
74 string name = moduleConfig.GetString("EntityTransferModule", "");
75 if (name == Name)
76 {
77 m_agentsInTransit = new List<UUID>();
78 m_Enabled = true;
79 m_log.InfoFormat("[ENTITY TRANSFER MODULE]: {0} enabled.", Name);
80 }
81 }
82 }
83
84 public virtual void PostInitialise()
85 {
86 }
87
88 public virtual void AddRegion(Scene scene)
89 {
90 if (!m_Enabled)
91 return;
92
93 if (m_aScene == null)
94 m_aScene = scene;
95
96 scene.RegisterModuleInterface<IEntityTransferModule>(this);
97 scene.EventManager.OnNewClient += OnNewClient;
98 }
99
100 protected virtual void OnNewClient(IClientAPI client)
101 {
102 client.OnTeleportHomeRequest += TeleportHome;
103 }
104
105 public virtual void Close()
106 {
107 if (!m_Enabled)
108 return;
109 }
110
111
112 public virtual void RemoveRegion(Scene scene)
113 {
114 if (!m_Enabled)
115 return;
116 if (scene == m_aScene)
117 m_aScene = null;
118 }
119
120 public virtual void RegionLoaded(Scene scene)
121 {
122 if (!m_Enabled)
123 return;
124
125 }
126
127
128 #endregion
129
130 #region Agent Teleports
131
132 public void Teleport(ScenePresence sp, ulong regionHandle, Vector3 position, Vector3 lookAt, uint teleportFlags)
133 {
134 if (!sp.Scene.Permissions.CanTeleport(sp.UUID))
135 return;
136
137 IEventQueue eq = sp.Scene.RequestModuleInterface<IEventQueue>();
138
139 // Reset animations; the viewer does that in teleports.
140 sp.Animator.ResetAnimations();
141
142 try
143 {
144 if (regionHandle == sp.Scene.RegionInfo.RegionHandle)
145 {
146 m_log.DebugFormat(
147 "[ENTITY TRANSFER MODULE]: RequestTeleportToLocation {0} within {1}",
148 position, sp.Scene.RegionInfo.RegionName);
149
150 // Teleport within the same region
151 if (IsOutsideRegion(sp.Scene, position) || position.Z < 0)
152 {
153 Vector3 emergencyPos = new Vector3(128, 128, 128);
154
155 m_log.WarnFormat(
156 "[ENTITY TRANSFER MODULE]: RequestTeleportToLocation() was given an illegal position of {0} for avatar {1}, {2}. Substituting {3}",
157 position, sp.Name, sp.UUID, emergencyPos);
158 position = emergencyPos;
159 }
160
161 // TODO: Get proper AVG Height
162 float localAVHeight = 1.56f;
163 float posZLimit = 22;
164
165 // TODO: Check other Scene HeightField
166 if (position.X > 0 && position.X <= (int)Constants.RegionSize && position.Y > 0 && position.Y <= (int)Constants.RegionSize)
167 {
168 posZLimit = (float)sp.Scene.Heightmap[(int)position.X, (int)position.Y];
169 }
170
171 float newPosZ = posZLimit + localAVHeight;
172 if (posZLimit >= (position.Z - (localAVHeight / 2)) && !(Single.IsInfinity(newPosZ) || Single.IsNaN(newPosZ)))
173 {
174 position.Z = newPosZ;
175 }
176
177 // Only send this if the event queue is null
178 if (eq == null)
179 sp.ControllingClient.SendTeleportLocationStart();
180
181 sp.ControllingClient.SendLocalTeleport(position, lookAt, teleportFlags);
182 sp.Teleport(position);
183 }
184 else // Another region possibly in another simulator
185 {
186 uint x = 0, y = 0;
187 Utils.LongToUInts(regionHandle, out x, out y);
188 GridRegion reg = m_aScene.GridService.GetRegionByPosition(sp.Scene.RegionInfo.ScopeID, (int)x, (int)y);
189
190 if (reg != null)
191 {
192 GridRegion finalDestination = GetFinalDestination(reg);
193 if (finalDestination == null)
194 {
195 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Final destination is having problems. Unable to teleport agent.");
196 sp.ControllingClient.SendTeleportFailed("Problem at destination");
197 return;
198 }
199 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Final destination is x={0} y={1} uuid={2}",
200 finalDestination.RegionLocX / Constants.RegionSize, finalDestination.RegionLocY / Constants.RegionSize, finalDestination.RegionID);
201
202 //
203 // This is it
204 //
205 DoTeleport(sp, reg, finalDestination, position, lookAt, teleportFlags, eq);
206 //
207 //
208 //
209 }
210 else
211 {
212 // TP to a place that doesn't exist (anymore)
213 // Inform the viewer about that
214 sp.ControllingClient.SendTeleportFailed("The region you tried to teleport to doesn't exist anymore");
215
216 // and set the map-tile to '(Offline)'
217 uint regX, regY;
218 Utils.LongToUInts(regionHandle, out regX, out regY);
219
220 MapBlockData block = new MapBlockData();
221 block.X = (ushort)(regX / Constants.RegionSize);
222 block.Y = (ushort)(regY / Constants.RegionSize);
223 block.Access = 254; // == not there
224
225 List<MapBlockData> blocks = new List<MapBlockData>();
226 blocks.Add(block);
227 sp.ControllingClient.SendMapBlock(blocks, 0);
228 }
229 }
230 }
231 catch (Exception e)
232 {
233 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Exception on teleport: {0}\n{1}", e.Message, e.StackTrace);
234 sp.ControllingClient.SendTeleportFailed("Internal error");
235 }
236 }
237
238 protected void DoTeleport(ScenePresence sp, GridRegion reg, GridRegion finalDestination, Vector3 position, Vector3 lookAt, uint teleportFlags, IEventQueue eq)
239 {
240 if (reg == null || finalDestination == null)
241 {
242 sp.ControllingClient.SendTeleportFailed("Unable to locate destination");
243 return;
244 }
245
246 m_log.DebugFormat(
247 "[ENTITY TRANSFER MODULE]: Request Teleport to {0}:{1}:{2}/{3}",
248 reg.ExternalHostName, reg.HttpPort, finalDestination.RegionName, position);
249
250 uint newRegionX = (uint)(reg.RegionHandle >> 40);
251 uint newRegionY = (((uint)(reg.RegionHandle)) >> 8);
252 uint oldRegionX = (uint)(sp.Scene.RegionInfo.RegionHandle >> 40);
253 uint oldRegionY = (((uint)(sp.Scene.RegionInfo.RegionHandle)) >> 8);
254
255 ulong destinationHandle = finalDestination.RegionHandle;
256
257 if (eq == null)
258 sp.ControllingClient.SendTeleportLocationStart();
259
260 // Let's do DNS resolution only once in this process, please!
261 // This may be a costly operation. The reg.ExternalEndPoint field is not a passive field,
262 // it's actually doing a lot of work.
263 IPEndPoint endPoint = finalDestination.ExternalEndPoint;
264 if (endPoint.Address != null)
265 {
266 // Fixing a bug where teleporting while sitting results in the avatar ending up removed from
267 // both regions
268 if (sp.ParentID != (uint)0)
269 sp.StandUp();
270
271 if (!sp.ValidateAttachments())
272 {
273 sp.ControllingClient.SendTeleportFailed("Inconsistent attachment state");
274 return;
275 }
276
277 // the avatar.Close below will clear the child region list. We need this below for (possibly)
278 // closing the child agents, so save it here (we need a copy as it is Clear()-ed).
279 //List<ulong> childRegions = new List<ulong>(avatar.GetKnownRegionList());
280 // Compared to ScenePresence.CrossToNewRegion(), there's no obvious code to handle a teleport
281 // failure at this point (unlike a border crossing failure). So perhaps this can never fail
282 // once we reach here...
283 //avatar.Scene.RemoveCapsHandler(avatar.UUID);
284
285 string capsPath = String.Empty;
286
287 AgentCircuitData currentAgentCircuit = sp.Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode);
288 AgentCircuitData agentCircuit = sp.ControllingClient.RequestClientInfo();
289 agentCircuit.startpos = position;
290 agentCircuit.child = true;
291 agentCircuit.Appearance = sp.Appearance;
292 if (currentAgentCircuit != null)
293 agentCircuit.ServiceURLs = currentAgentCircuit.ServiceURLs;
294
295 if (NeedsNewAgent(oldRegionX, newRegionX, oldRegionY, newRegionY))
296 {
297 // brand new agent, let's create a new caps seed
298 agentCircuit.CapsPath = CapsUtil.GetRandomCapsObjectPath();
299 }
300
301 string reason = String.Empty;
302
303 // Let's create an agent there if one doesn't exist yet.
304 if (!CreateAgent(sp, reg, finalDestination, agentCircuit, teleportFlags, out reason))
305 {
306 sp.ControllingClient.SendTeleportFailed(String.Format("Destination refused: {0}",
307 reason));
308 return;
309 }
310
311 // OK, it got this agent. Let's close some child agents
312 sp.CloseChildAgents(newRegionX, newRegionY);
313
314 if (NeedsNewAgent(oldRegionX, newRegionX, oldRegionY, newRegionY))
315 {
316 #region IP Translation for NAT
317 IClientIPEndpoint ipepClient;
318 if (sp.ClientView.TryGet(out ipepClient))
319 {
320 capsPath
321 = "http://"
322 + NetworkUtil.GetHostFor(ipepClient.EndPoint, finalDestination.ExternalHostName)
323 + ":"
324 + finalDestination.HttpPort
325 + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath);
326 }
327 else
328 {
329 capsPath
330 = "http://"
331 + finalDestination.ExternalHostName
332 + ":"
333 + finalDestination.HttpPort
334 + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath);
335 }
336 #endregion
337
338 if (eq != null)
339 {
340 #region IP Translation for NAT
341 // Uses ipepClient above
342 if (sp.ClientView.TryGet(out ipepClient))
343 {
344 endPoint.Address = NetworkUtil.GetIPFor(ipepClient.EndPoint, endPoint.Address);
345 }
346 #endregion
347
348 eq.EnableSimulator(destinationHandle, endPoint, sp.UUID);
349
350 // ES makes the client send a UseCircuitCode message to the destination,
351 // which triggers a bunch of things there.
352 // So let's wait
353 Thread.Sleep(200);
354
355 eq.EstablishAgentCommunication(sp.UUID, endPoint, capsPath);
356
357 }
358 else
359 {
360 sp.ControllingClient.InformClientOfNeighbour(destinationHandle, endPoint);
361 }
362 }
363 else
364 {
365 agentCircuit.CapsPath = sp.Scene.CapsModule.GetChildSeed(sp.UUID, reg.RegionHandle);
366 capsPath = "http://" + finalDestination.ExternalHostName + ":" + finalDestination.HttpPort
367 + "/CAPS/" + agentCircuit.CapsPath + "0000/";
368 }
369
370 // Expect avatar crossing is a heavy-duty function at the destination.
371 // That is where MakeRoot is called, which fetches appearance and inventory.
372 // Plus triggers OnMakeRoot, which spawns a series of asynchronous updates.
373 //m_commsProvider.InterRegion.ExpectAvatarCrossing(reg.RegionHandle, avatar.ControllingClient.AgentId,
374 // position, false);
375
376 //{
377 // avatar.ControllingClient.SendTeleportFailed("Problem with destination.");
378 // // We should close that agent we just created over at destination...
379 // List<ulong> lst = new List<ulong>();
380 // lst.Add(reg.RegionHandle);
381 // SendCloseChildAgentAsync(avatar.UUID, lst);
382 // return;
383 //}
384
385 SetInTransit(sp.UUID);
386
387 // Let's send a full update of the agent. This is a synchronous call.
388 AgentData agent = new AgentData();
389 sp.CopyTo(agent);
390 agent.Position = position;
391 SetCallbackURL(agent, sp.Scene.RegionInfo);
392
393 UpdateAgent(reg, finalDestination, agent);
394
395 m_log.DebugFormat(
396 "[ENTITY TRANSFER MODULE]: Sending new CAPS seed url {0} to client {1}", capsPath, sp.UUID);
397
398
399 if (eq != null)
400 {
401 eq.TeleportFinishEvent(destinationHandle, 13, endPoint,
402 0, teleportFlags, capsPath, sp.UUID);
403 }
404 else
405 {
406 sp.ControllingClient.SendRegionTeleport(destinationHandle, 13, endPoint, 4,
407 teleportFlags, capsPath);
408 }
409
410 // TeleportFinish makes the client send CompleteMovementIntoRegion (at the destination), which
411 // trigers a whole shebang of things there, including MakeRoot. So let's wait for confirmation
412 // that the client contacted the destination before we send the attachments and close things here.
413 if (!WaitForCallback(sp.UUID))
414 {
415 // Client never contacted destination. Let's restore everything back
416 sp.ControllingClient.SendTeleportFailed("Problems connecting to destination.");
417
418 ResetFromTransit(sp.UUID);
419
420 // Yikes! We should just have a ref to scene here.
421 //sp.Scene.InformClientOfNeighbours(sp);
422 EnableChildAgents(sp);
423
424 // Finally, kill the agent we just created at the destination.
425 m_aScene.SimulationService.CloseAgent(finalDestination, sp.UUID);
426
427 return;
428 }
429
430
431 // CrossAttachmentsIntoNewRegion is a synchronous call. We shouldn't need to wait after it
432 CrossAttachmentsIntoNewRegion(finalDestination, sp, true);
433
434 KillEntity(sp.Scene, sp.LocalId);
435
436 sp.MakeChildAgent();
437 // Finally, let's close this previously-known-as-root agent, when the jump is outside the view zone
438
439 if (NeedsClosing(oldRegionX, newRegionX, oldRegionY, newRegionY, reg))
440 {
441 Thread.Sleep(5000);
442 sp.Close();
443 sp.Scene.IncomingCloseAgent(sp.UUID);
444 }
445 else
446 // now we have a child agent in this region.
447 sp.Reset();
448
449
450 // REFACTORING PROBLEM. Well, not a problem, but this method is HORRIBLE!
451 if (sp.Scene.NeedSceneCacheClear(sp.UUID))
452 {
453 m_log.DebugFormat(
454 "[ENTITY TRANSFER MODULE]: User {0} is going to another region, profile cache removed",
455 sp.UUID);
456 }
457 }
458 else
459 {
460 sp.ControllingClient.SendTeleportFailed("Remote Region appears to be down");
461 }
462 }
463
464
465 protected virtual bool CreateAgent(ScenePresence sp, GridRegion reg, GridRegion finalDestination, AgentCircuitData agentCircuit, uint teleportFlags, out string reason)
466 {
467 return m_aScene.SimulationService.CreateAgent(finalDestination, agentCircuit, teleportFlags, out reason);
468 }
469
470 protected virtual bool UpdateAgent(GridRegion reg, GridRegion finalDestination, AgentData agent)
471 {
472 return m_aScene.SimulationService.UpdateAgent(finalDestination, agent);
473 }
474
475 protected virtual void SetCallbackURL(AgentData agent, RegionInfo region)
476 {
477 agent.CallbackURI = "http://" + region.ExternalHostName + ":" + region.HttpPort +
478 "/agent/" + agent.AgentID.ToString() + "/" + region.RegionID.ToString() + "/release/";
479
480 }
481
482 protected void KillEntity(Scene scene, uint localID)
483 {
484 scene.SendKillObject(localID);
485 }
486
487 protected virtual GridRegion GetFinalDestination(GridRegion region)
488 {
489 return region;
490 }
491
492 protected virtual bool NeedsNewAgent(uint oldRegionX, uint newRegionX, uint oldRegionY, uint newRegionY)
493 {
494 return Util.IsOutsideView(oldRegionX, newRegionX, oldRegionY, newRegionY);
495 }
496
497 protected virtual bool NeedsClosing(uint oldRegionX, uint newRegionX, uint oldRegionY, uint newRegionY, GridRegion reg)
498 {
499 return Util.IsOutsideView(oldRegionX, newRegionX, oldRegionY, newRegionY);
500 }
501
502 protected virtual bool IsOutsideRegion(Scene s, Vector3 pos)
503 {
504
505 if (s.TestBorderCross(pos, Cardinals.N))
506 return true;
507 if (s.TestBorderCross(pos, Cardinals.S))
508 return true;
509 if (s.TestBorderCross(pos, Cardinals.E))
510 return true;
511 if (s.TestBorderCross(pos, Cardinals.W))
512 return true;
513
514 return false;
515 }
516
517
518 #endregion
519
520 #region Teleport Home
521
522 public virtual void TeleportHome(UUID id, IClientAPI client)
523 {
524 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Request to teleport {0} {1} home", client.FirstName, client.LastName);
525
526 OpenSim.Services.Interfaces.PresenceInfo pinfo = m_aScene.PresenceService.GetAgent(client.SessionId);
527
528 if (pinfo != null)
529 {
530 GridRegion regionInfo = m_aScene.GridService.GetRegionByUUID(UUID.Zero, pinfo.HomeRegionID);
531 if (regionInfo == null)
532 {
533 // can't find the Home region: Tell viewer and abort
534 client.SendTeleportFailed("Your home region could not be found.");
535 return;
536 }
537 // a little eekie that this goes back to Scene and with a forced cast, will fix that at some point...
538 ((Scene)(client.Scene)).RequestTeleportLocation(
539 client, regionInfo.RegionHandle, pinfo.HomePosition, pinfo.HomeLookAt,
540 (uint)(Constants.TeleportFlags.SetLastToTarget | Constants.TeleportFlags.ViaHome));
541 }
542 }
543
544 #endregion
545
546
547 #region Agent Crossings
548
549 public void Cross(ScenePresence agent, bool isFlying)
550 {
551 Scene scene = agent.Scene;
552 Vector3 pos = agent.AbsolutePosition;
553 Vector3 newpos = new Vector3(pos.X, pos.Y, pos.Z);
554 uint neighbourx = scene.RegionInfo.RegionLocX;
555 uint neighboury = scene.RegionInfo.RegionLocY;
556 const float boundaryDistance = 1.7f;
557 Vector3 northCross = new Vector3(0, boundaryDistance, 0);
558 Vector3 southCross = new Vector3(0, -1 * boundaryDistance, 0);
559 Vector3 eastCross = new Vector3(boundaryDistance, 0, 0);
560 Vector3 westCross = new Vector3(-1 * boundaryDistance, 0, 0);
561
562 // distance to edge that will trigger crossing
563
564
565 // distance into new region to place avatar
566 const float enterDistance = 0.5f;
567
568 if (scene.TestBorderCross(pos + westCross, Cardinals.W))
569 {
570 if (scene.TestBorderCross(pos + northCross, Cardinals.N))
571 {
572 Border b = scene.GetCrossedBorder(pos + northCross, Cardinals.N);
573 neighboury += (uint)(int)(b.BorderLine.Z / (int)Constants.RegionSize);
574 }
575 else if (scene.TestBorderCross(pos + southCross, Cardinals.S))
576 {
577 Border b = scene.GetCrossedBorder(pos + southCross, Cardinals.S);
578 if (b.TriggerRegionX == 0 && b.TriggerRegionY == 0)
579 {
580 neighboury--;
581 newpos.Y = Constants.RegionSize - enterDistance;
582 }
583 else
584 {
585 neighboury = b.TriggerRegionY;
586 neighbourx = b.TriggerRegionX;
587
588 Vector3 newposition = pos;
589 newposition.X += (scene.RegionInfo.RegionLocX - neighbourx) * Constants.RegionSize;
590 newposition.Y += (scene.RegionInfo.RegionLocY - neighboury) * Constants.RegionSize;
591 agent.ControllingClient.SendAgentAlertMessage(
592 String.Format("Moving you to region {0},{1}", neighbourx, neighboury), false);
593 InformClientToInitateTeleportToLocation(agent, neighbourx, neighboury, newposition, scene);
594 return;
595 }
596 }
597
598 Border ba = scene.GetCrossedBorder(pos + westCross, Cardinals.W);
599 if (ba.TriggerRegionX == 0 && ba.TriggerRegionY == 0)
600 {
601 neighbourx--;
602 newpos.X = Constants.RegionSize - enterDistance;
603 }
604 else
605 {
606 neighboury = ba.TriggerRegionY;
607 neighbourx = ba.TriggerRegionX;
608
609
610 Vector3 newposition = pos;
611 newposition.X += (scene.RegionInfo.RegionLocX - neighbourx) * Constants.RegionSize;
612 newposition.Y += (scene.RegionInfo.RegionLocY - neighboury) * Constants.RegionSize;
613 agent.ControllingClient.SendAgentAlertMessage(
614 String.Format("Moving you to region {0},{1}", neighbourx, neighboury), false);
615 InformClientToInitateTeleportToLocation(agent, neighbourx, neighboury, newposition, scene);
616
617
618 return;
619 }
620
621 }
622 else if (scene.TestBorderCross(pos + eastCross, Cardinals.E))
623 {
624 Border b = scene.GetCrossedBorder(pos + eastCross, Cardinals.E);
625 neighbourx += (uint)(int)(b.BorderLine.Z / (int)Constants.RegionSize);
626 newpos.X = enterDistance;
627
628 if (scene.TestBorderCross(pos + southCross, Cardinals.S))
629 {
630 Border ba = scene.GetCrossedBorder(pos + southCross, Cardinals.S);
631 if (ba.TriggerRegionX == 0 && ba.TriggerRegionY == 0)
632 {
633 neighboury--;
634 newpos.Y = Constants.RegionSize - enterDistance;
635 }
636 else
637 {
638 neighboury = ba.TriggerRegionY;
639 neighbourx = ba.TriggerRegionX;
640 Vector3 newposition = pos;
641 newposition.X += (scene.RegionInfo.RegionLocX - neighbourx) * Constants.RegionSize;
642 newposition.Y += (scene.RegionInfo.RegionLocY - neighboury) * Constants.RegionSize;
643 agent.ControllingClient.SendAgentAlertMessage(
644 String.Format("Moving you to region {0},{1}", neighbourx, neighboury), false);
645 InformClientToInitateTeleportToLocation(agent, neighbourx, neighboury, newposition, scene);
646 return;
647 }
648 }
649 else if (scene.TestBorderCross(pos + northCross, Cardinals.N))
650 {
651 Border c = scene.GetCrossedBorder(pos + northCross, Cardinals.N);
652 neighboury += (uint)(int)(c.BorderLine.Z / (int)Constants.RegionSize);
653 newpos.Y = enterDistance;
654 }
655
656
657 }
658 else if (scene.TestBorderCross(pos + southCross, Cardinals.S))
659 {
660 Border b = scene.GetCrossedBorder(pos + southCross, Cardinals.S);
661 if (b.TriggerRegionX == 0 && b.TriggerRegionY == 0)
662 {
663 neighboury--;
664 newpos.Y = Constants.RegionSize - enterDistance;
665 }
666 else
667 {
668 neighboury = b.TriggerRegionY;
669 neighbourx = b.TriggerRegionX;
670 Vector3 newposition = pos;
671 newposition.X += (scene.RegionInfo.RegionLocX - neighbourx) * Constants.RegionSize;
672 newposition.Y += (scene.RegionInfo.RegionLocY - neighboury) * Constants.RegionSize;
673 agent.ControllingClient.SendAgentAlertMessage(
674 String.Format("Moving you to region {0},{1}", neighbourx, neighboury), false);
675 InformClientToInitateTeleportToLocation(agent, neighbourx, neighboury, newposition, scene);
676 return;
677 }
678 }
679 else if (scene.TestBorderCross(pos + northCross, Cardinals.N))
680 {
681
682 Border b = scene.GetCrossedBorder(pos + northCross, Cardinals.N);
683 neighboury += (uint)(int)(b.BorderLine.Z / (int)Constants.RegionSize);
684 newpos.Y = enterDistance;
685 }
686
687 /*
688
689 if (pos.X < boundaryDistance) //West
690 {
691 neighbourx--;
692 newpos.X = Constants.RegionSize - enterDistance;
693 }
694 else if (pos.X > Constants.RegionSize - boundaryDistance) // East
695 {
696 neighbourx++;
697 newpos.X = enterDistance;
698 }
699
700 if (pos.Y < boundaryDistance) // South
701 {
702 neighboury--;
703 newpos.Y = Constants.RegionSize - enterDistance;
704 }
705 else if (pos.Y > Constants.RegionSize - boundaryDistance) // North
706 {
707 neighboury++;
708 newpos.Y = enterDistance;
709 }
710 */
711
712 CrossAgentToNewRegionDelegate d = CrossAgentToNewRegionAsync;
713 d.BeginInvoke(agent, newpos, neighbourx, neighboury, isFlying, CrossAgentToNewRegionCompleted, d);
714
715 }
716
717
718 public delegate void InformClientToInitateTeleportToLocationDelegate(ScenePresence agent, uint regionX, uint regionY,
719 Vector3 position,
720 Scene initiatingScene);
721
722 private void InformClientToInitateTeleportToLocation(ScenePresence agent, uint regionX, uint regionY, Vector3 position, Scene initiatingScene)
723 {
724
725 // This assumes that we know what our neighbors are.
726
727 InformClientToInitateTeleportToLocationDelegate d = InformClientToInitiateTeleportToLocationAsync;
728 d.BeginInvoke(agent, regionX, regionY, position, initiatingScene,
729 InformClientToInitiateTeleportToLocationCompleted,
730 d);
731 }
732
733 public void InformClientToInitiateTeleportToLocationAsync(ScenePresence agent, uint regionX, uint regionY, Vector3 position,
734 Scene initiatingScene)
735 {
736 Thread.Sleep(10000);
737 IMessageTransferModule im = initiatingScene.RequestModuleInterface<IMessageTransferModule>();
738 if (im != null)
739 {
740 UUID gotoLocation = Util.BuildFakeParcelID(
741 Util.UIntsToLong(
742 (regionX *
743 (uint)Constants.RegionSize),
744 (regionY *
745 (uint)Constants.RegionSize)),
746 (uint)(int)position.X,
747 (uint)(int)position.Y,
748 (uint)(int)position.Z);
749 GridInstantMessage m = new GridInstantMessage(initiatingScene, UUID.Zero,
750 "Region", agent.UUID,
751 (byte)InstantMessageDialog.GodLikeRequestTeleport, false,
752 "", gotoLocation, false, new Vector3(127, 0, 0),
753 new Byte[0]);
754 im.SendInstantMessage(m, delegate(bool success)
755 {
756 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Client Initiating Teleport sending IM success = {0}", success);
757 });
758
759 }
760 }
761
762 private void InformClientToInitiateTeleportToLocationCompleted(IAsyncResult iar)
763 {
764 InformClientToInitateTeleportToLocationDelegate icon =
765 (InformClientToInitateTeleportToLocationDelegate)iar.AsyncState;
766 icon.EndInvoke(iar);
767 }
768
769 public delegate ScenePresence CrossAgentToNewRegionDelegate(ScenePresence agent, Vector3 pos, uint neighbourx, uint neighboury, bool isFlying);
770
771 /// <summary>
772 /// This Closes child agents on neighboring regions
773 /// Calls an asynchronous method to do so.. so it doesn't lag the sim.
774 /// </summary>
775 protected ScenePresence CrossAgentToNewRegionAsync(ScenePresence agent, Vector3 pos, uint neighbourx, uint neighboury, bool isFlying)
776 {
777 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Crossing agent {0} {1} to {2}-{3}", agent.Firstname, agent.Lastname, neighbourx, neighboury);
778
779 Scene m_scene = agent.Scene;
780 ulong neighbourHandle = Utils.UIntsToLong((uint)(neighbourx * Constants.RegionSize), (uint)(neighboury * Constants.RegionSize));
781
782 int x = (int)(neighbourx * Constants.RegionSize), y = (int)(neighboury * Constants.RegionSize);
783 GridRegion neighbourRegion = m_scene.GridService.GetRegionByPosition(m_scene.RegionInfo.ScopeID, (int)x, (int)y);
784
785 if (neighbourRegion != null && agent.ValidateAttachments())
786 {
787 pos = pos + (agent.Velocity);
788
789 SetInTransit(agent.UUID);
790 AgentData cAgent = new AgentData();
791 agent.CopyTo(cAgent);
792 cAgent.Position = pos;
793 if (isFlying)
794 cAgent.ControlFlags |= (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY;
795 cAgent.CallbackURI = "http://" + m_scene.RegionInfo.ExternalHostName + ":" + m_scene.RegionInfo.HttpPort +
796 "/agent/" + agent.UUID.ToString() + "/" + m_scene.RegionInfo.RegionID.ToString() + "/release/";
797
798 m_scene.SimulationService.UpdateAgent(neighbourRegion, cAgent);
799
800 // Next, let's close the child agent connections that are too far away.
801 agent.CloseChildAgents(neighbourx, neighboury);
802
803 //AgentCircuitData circuitdata = m_controllingClient.RequestClientInfo();
804 agent.ControllingClient.RequestClientInfo();
805
806 //m_log.Debug("BEFORE CROSS");
807 //Scene.DumpChildrenSeeds(UUID);
808 //DumpKnownRegions();
809 string agentcaps;
810 if (!agent.KnownRegions.TryGetValue(neighbourRegion.RegionHandle, out agentcaps))
811 {
812 m_log.ErrorFormat("[ENTITY TRANSFER MODULE]: No ENTITY TRANSFER MODULE information for region handle {0}, exiting CrossToNewRegion.",
813 neighbourRegion.RegionHandle);
814 return agent;
815 }
816 // TODO Should construct this behind a method
817 string capsPath =
818 "http://" + neighbourRegion.ExternalHostName + ":" + neighbourRegion.HttpPort
819 + "/CAPS/" + agentcaps /*circuitdata.CapsPath*/ + "0000/";
820
821 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Sending new CAPS seed url {0} to client {1}", capsPath, agent.UUID);
822
823 IEventQueue eq = agent.Scene.RequestModuleInterface<IEventQueue>();
824 if (eq != null)
825 {
826 eq.CrossRegion(neighbourHandle, pos, agent.Velocity, neighbourRegion.ExternalEndPoint,
827 capsPath, agent.UUID, agent.ControllingClient.SessionId);
828 }
829 else
830 {
831 agent.ControllingClient.CrossRegion(neighbourHandle, pos, agent.Velocity, neighbourRegion.ExternalEndPoint,
832 capsPath);
833 }
834
835 if (!WaitForCallback(agent.UUID))
836 {
837 m_log.Debug("[ENTITY TRANSFER MODULE]: Callback never came in crossing agent");
838 ResetFromTransit(agent.UUID);
839
840 // Yikes! We should just have a ref to scene here.
841 //agent.Scene.InformClientOfNeighbours(agent);
842 EnableChildAgents(agent);
843
844 return agent;
845 }
846
847 agent.MakeChildAgent();
848 // now we have a child agent in this region. Request all interesting data about other (root) agents
849 agent.SendInitialFullUpdateToAllClients();
850
851 CrossAttachmentsIntoNewRegion(neighbourRegion, agent, true);
852
853 // m_scene.SendKillObject(m_localId);
854
855 agent.Scene.NotifyMyCoarseLocationChange();
856 // the user may change their profile information in other region,
857 // so the userinfo in UserProfileCache is not reliable any more, delete it
858 // REFACTORING PROBLEM. Well, not a problem, but this method is HORRIBLE!
859 if (agent.Scene.NeedSceneCacheClear(agent.UUID))
860 {
861 m_log.DebugFormat(
862 "[ENTITY TRANSFER MODULE]: User {0} is going to another region", agent.UUID);
863 }
864 }
865
866 //m_log.Debug("AFTER CROSS");
867 //Scene.DumpChildrenSeeds(UUID);
868 //DumpKnownRegions();
869 return agent;
870 }
871
872 private void CrossAgentToNewRegionCompleted(IAsyncResult iar)
873 {
874 CrossAgentToNewRegionDelegate icon = (CrossAgentToNewRegionDelegate)iar.AsyncState;
875 ScenePresence agent = icon.EndInvoke(iar);
876
877 // If the cross was successful, this agent is a child agent
878 if (agent.IsChildAgent)
879 agent.Reset();
880 else // Not successful
881 agent.RestoreInCurrentScene();
882
883 // In any case
884 agent.NotInTransit();
885
886 //m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Crossing agent {0} {1} completed.", agent.Firstname, agent.Lastname);
887 }
888
889 #endregion
890
891 #region Enable Child Agent
892 /// <summary>
893 /// This informs a single neighboring region about agent "avatar".
894 /// Calls an asynchronous method to do so.. so it doesn't lag the sim.
895 /// </summary>
896 public void EnableChildAgent(ScenePresence sp, GridRegion region)
897 {
898 AgentCircuitData agent = sp.ControllingClient.RequestClientInfo();
899 agent.BaseFolder = UUID.Zero;
900 agent.InventoryFolder = UUID.Zero;
901 agent.startpos = new Vector3(128, 128, 70);
902 agent.child = true;
903 agent.Appearance = sp.Appearance;
904
905 InformClientOfNeighbourDelegate d = InformClientOfNeighbourAsync;
906 d.BeginInvoke(sp, agent, region, region.ExternalEndPoint, true,
907 InformClientOfNeighbourCompleted,
908 d);
909 }
910 #endregion
911
912 #region Enable Child Agents
913
914 private delegate void InformClientOfNeighbourDelegate(
915 ScenePresence avatar, AgentCircuitData a, GridRegion reg, IPEndPoint endPoint, bool newAgent);
916
917 /// <summary>
918 /// This informs all neighboring regions about agent "avatar".
919 /// Calls an asynchronous method to do so.. so it doesn't lag the sim.
920 /// </summary>
921 public void EnableChildAgents(ScenePresence sp)
922 {
923 List<GridRegion> neighbours = new List<GridRegion>();
924 RegionInfo m_regionInfo = sp.Scene.RegionInfo;
925
926 if (m_regionInfo != null)
927 {
928 neighbours = RequestNeighbours(sp.Scene, m_regionInfo.RegionLocX, m_regionInfo.RegionLocY);
929 }
930 else
931 {
932 m_log.Debug("[ENTITY TRANSFER MODULE]: m_regionInfo was null in EnableChildAgents, is this a NPC?");
933 }
934
935 /// We need to find the difference between the new regions where there are no child agents
936 /// and the regions where there are already child agents. We only send notification to the former.
937 List<ulong> neighbourHandles = NeighbourHandles(neighbours); // on this region
938 neighbourHandles.Add(sp.Scene.RegionInfo.RegionHandle); // add this region too
939 List<ulong> previousRegionNeighbourHandles;
940
941 if (sp.Scene.CapsModule != null)
942 {
943 previousRegionNeighbourHandles =
944 new List<ulong>(sp.Scene.CapsModule.GetChildrenSeeds(sp.UUID).Keys);
945 }
946 else
947 {
948 previousRegionNeighbourHandles = new List<ulong>();
949 }
950
951 List<ulong> newRegions = NewNeighbours(neighbourHandles, previousRegionNeighbourHandles);
952 List<ulong> oldRegions = OldNeighbours(neighbourHandles, previousRegionNeighbourHandles);
953
954 //Dump("Current Neighbors", neighbourHandles);
955 //Dump("Previous Neighbours", previousRegionNeighbourHandles);
956 //Dump("New Neighbours", newRegions);
957 //Dump("Old Neighbours", oldRegions);
958
959 /// Update the scene presence's known regions here on this region
960 sp.DropOldNeighbours(oldRegions);
961
962 /// Collect as many seeds as possible
963 Dictionary<ulong, string> seeds;
964 if (sp.Scene.CapsModule != null)
965 seeds
966 = new Dictionary<ulong, string>(sp.Scene.CapsModule.GetChildrenSeeds(sp.UUID));
967 else
968 seeds = new Dictionary<ulong, string>();
969
970 //m_log.Debug(" !!! No. of seeds: " + seeds.Count);
971 if (!seeds.ContainsKey(sp.Scene.RegionInfo.RegionHandle))
972 seeds.Add(sp.Scene.RegionInfo.RegionHandle, sp.ControllingClient.RequestClientInfo().CapsPath);
973
974 /// Create the necessary child agents
975 List<AgentCircuitData> cagents = new List<AgentCircuitData>();
976 foreach (GridRegion neighbour in neighbours)
977 {
978 if (neighbour.RegionHandle != sp.Scene.RegionInfo.RegionHandle)
979 {
980
981 AgentCircuitData currentAgentCircuit = sp.Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode);
982 AgentCircuitData agent = sp.ControllingClient.RequestClientInfo();
983 agent.BaseFolder = UUID.Zero;
984 agent.InventoryFolder = UUID.Zero;
985 agent.startpos = new Vector3(128, 128, 70);
986 agent.child = true;
987 agent.Appearance = sp.Appearance;
988 if (currentAgentCircuit != null)
989 agent.ServiceURLs = currentAgentCircuit.ServiceURLs;
990
991 if (newRegions.Contains(neighbour.RegionHandle))
992 {
993 agent.CapsPath = CapsUtil.GetRandomCapsObjectPath();
994 sp.AddNeighbourRegion(neighbour.RegionHandle, agent.CapsPath);
995 seeds.Add(neighbour.RegionHandle, agent.CapsPath);
996 }
997 else
998 agent.CapsPath = sp.Scene.CapsModule.GetChildSeed(sp.UUID, neighbour.RegionHandle);
999
1000 cagents.Add(agent);
1001 }
1002 }
1003
1004 /// Update all child agent with everyone's seeds
1005 foreach (AgentCircuitData a in cagents)
1006 {
1007 a.ChildrenCapSeeds = new Dictionary<ulong, string>(seeds);
1008 }
1009
1010 if (sp.Scene.CapsModule != null)
1011 {
1012 sp.Scene.CapsModule.SetChildrenSeed(sp.UUID, seeds);
1013 }
1014 sp.KnownRegions = seeds;
1015 //avatar.Scene.DumpChildrenSeeds(avatar.UUID);
1016 //avatar.DumpKnownRegions();
1017
1018 bool newAgent = false;
1019 int count = 0;
1020 foreach (GridRegion neighbour in neighbours)
1021 {
1022 //m_log.WarnFormat("--> Going to send child agent to {0}", neighbour.RegionName);
1023 // Don't do it if there's already an agent in that region
1024 if (newRegions.Contains(neighbour.RegionHandle))
1025 newAgent = true;
1026 else
1027 newAgent = false;
1028
1029 if (neighbour.RegionHandle != sp.Scene.RegionInfo.RegionHandle)
1030 {
1031 InformClientOfNeighbourDelegate d = InformClientOfNeighbourAsync;
1032 try
1033 {
1034 d.BeginInvoke(sp, cagents[count], neighbour, neighbour.ExternalEndPoint, newAgent,
1035 InformClientOfNeighbourCompleted,
1036 d);
1037 }
1038
1039 catch (ArgumentOutOfRangeException)
1040 {
1041 m_log.ErrorFormat(
1042 "[ENTITY TRANSFER MODULE]: Neighbour Regions response included the current region in the neighbor list. The following region will not display to the client: {0} for region {1} ({2}, {3}).",
1043 neighbour.ExternalHostName,
1044 neighbour.RegionHandle,
1045 neighbour.RegionLocX,
1046 neighbour.RegionLocY);
1047 }
1048 catch (Exception e)
1049 {
1050 m_log.ErrorFormat(
1051 "[ENTITY TRANSFER MODULE]: Could not resolve external hostname {0} for region {1} ({2}, {3}). {4}",
1052 neighbour.ExternalHostName,
1053 neighbour.RegionHandle,
1054 neighbour.RegionLocX,
1055 neighbour.RegionLocY,
1056 e);
1057
1058 // FIXME: Okay, even though we've failed, we're still going to throw the exception on,
1059 // since I don't know what will happen if we just let the client continue
1060
1061 // XXX: Well, decided to swallow the exception instead for now. Let us see how that goes.
1062 // throw e;
1063
1064 }
1065 }
1066 count++;
1067 }
1068 }
1069
1070 private void InformClientOfNeighbourCompleted(IAsyncResult iar)
1071 {
1072 InformClientOfNeighbourDelegate icon = (InformClientOfNeighbourDelegate)iar.AsyncState;
1073 icon.EndInvoke(iar);
1074 //m_log.WarnFormat(" --> InformClientOfNeighbourCompleted");
1075 }
1076
1077 /// <summary>
1078 /// Async component for informing client of which neighbours exist
1079 /// </summary>
1080 /// <remarks>
1081 /// This needs to run asynchronously, as a network timeout may block the thread for a long while
1082 /// </remarks>
1083 /// <param name="remoteClient"></param>
1084 /// <param name="a"></param>
1085 /// <param name="regionHandle"></param>
1086 /// <param name="endPoint"></param>
1087 private void InformClientOfNeighbourAsync(ScenePresence sp, AgentCircuitData a, GridRegion reg,
1088 IPEndPoint endPoint, bool newAgent)
1089 {
1090 // Let's wait just a little to give time to originating regions to catch up with closing child agents
1091 // after a cross here
1092 Thread.Sleep(500);
1093
1094 Scene m_scene = sp.Scene;
1095
1096 uint x, y;
1097 Utils.LongToUInts(reg.RegionHandle, out x, out y);
1098 x = x / Constants.RegionSize;
1099 y = y / Constants.RegionSize;
1100 m_log.Info("[ENTITY TRANSFER MODULE]: Starting to inform client about neighbour " + x + ", " + y + "(" + endPoint.ToString() + ")");
1101
1102 string capsPath = "http://" + reg.ExternalHostName + ":" + reg.HttpPort
1103 + "/CAPS/" + a.CapsPath + "0000/";
1104
1105 string reason = String.Empty;
1106
1107
1108 bool regionAccepted = m_scene.SimulationService.CreateAgent(reg, a, 0, out reason); // m_interregionCommsOut.SendCreateChildAgent(reg.RegionHandle, a, 0, out reason);
1109
1110 if (regionAccepted && newAgent)
1111 {
1112 IEventQueue eq = sp.Scene.RequestModuleInterface<IEventQueue>();
1113 if (eq != null)
1114 {
1115 #region IP Translation for NAT
1116 IClientIPEndpoint ipepClient;
1117 if (sp.ClientView.TryGet(out ipepClient))
1118 {
1119 endPoint.Address = NetworkUtil.GetIPFor(ipepClient.EndPoint, endPoint.Address);
1120 }
1121 #endregion
1122
1123 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: {0} is sending {1} EnableSimulator for neighbor region {2} @ {3} " +
1124 "and EstablishAgentCommunication with seed cap {4}",
1125 m_scene.RegionInfo.RegionName, sp.Name, reg.RegionName, reg.RegionHandle, capsPath);
1126
1127 eq.EnableSimulator(reg.RegionHandle, endPoint, sp.UUID);
1128 eq.EstablishAgentCommunication(sp.UUID, endPoint, capsPath);
1129 }
1130 else
1131 {
1132 sp.ControllingClient.InformClientOfNeighbour(reg.RegionHandle, endPoint);
1133 // TODO: make Event Queue disablable!
1134 }
1135
1136 m_log.Info("[ENTITY TRANSFER MODULE]: Completed inform client about neighbour " + endPoint.ToString());
1137
1138 }
1139
1140 }
1141
1142 protected List<GridRegion> RequestNeighbours(Scene pScene, uint pRegionLocX, uint pRegionLocY)
1143 {
1144 RegionInfo m_regionInfo = pScene.RegionInfo;
1145
1146 Border[] northBorders = pScene.NorthBorders.ToArray();
1147 Border[] southBorders = pScene.SouthBorders.ToArray();
1148 Border[] eastBorders = pScene.EastBorders.ToArray();
1149 Border[] westBorders = pScene.WestBorders.ToArray();
1150
1151 // Legacy one region. Provided for simplicity while testing the all inclusive method in the else statement.
1152 if (northBorders.Length <= 1 && southBorders.Length <= 1 && eastBorders.Length <= 1 && westBorders.Length <= 1)
1153 {
1154 return pScene.GridService.GetNeighbours(m_regionInfo.ScopeID, m_regionInfo.RegionID);
1155 }
1156 else
1157 {
1158 Vector2 extent = Vector2.Zero;
1159 for (int i = 0; i < eastBorders.Length; i++)
1160 {
1161 extent.X = (eastBorders[i].BorderLine.Z > extent.X) ? eastBorders[i].BorderLine.Z : extent.X;
1162 }
1163 for (int i = 0; i < northBorders.Length; i++)
1164 {
1165 extent.Y = (northBorders[i].BorderLine.Z > extent.Y) ? northBorders[i].BorderLine.Z : extent.Y;
1166 }
1167
1168 // Loss of fraction on purpose
1169 extent.X = ((int)extent.X / (int)Constants.RegionSize) + 1;
1170 extent.Y = ((int)extent.Y / (int)Constants.RegionSize) + 1;
1171
1172 int startX = (int)(pRegionLocX - 1) * (int)Constants.RegionSize;
1173 int startY = (int)(pRegionLocY - 1) * (int)Constants.RegionSize;
1174
1175 int endX = ((int)pRegionLocX + (int)extent.X) * (int)Constants.RegionSize;
1176 int endY = ((int)pRegionLocY + (int)extent.Y) * (int)Constants.RegionSize;
1177
1178 List<GridRegion> neighbours = pScene.GridService.GetRegionRange(m_regionInfo.ScopeID, startX, endX, startY, endY);
1179 neighbours.RemoveAll(delegate(GridRegion r) { return r.RegionID == m_regionInfo.RegionID; });
1180
1181 return neighbours;
1182 }
1183 }
1184
1185 private List<ulong> NewNeighbours(List<ulong> currentNeighbours, List<ulong> previousNeighbours)
1186 {
1187 return currentNeighbours.FindAll(delegate(ulong handle) { return !previousNeighbours.Contains(handle); });
1188 }
1189
1190 // private List<ulong> CommonNeighbours(List<ulong> currentNeighbours, List<ulong> previousNeighbours)
1191 // {
1192 // return currentNeighbours.FindAll(delegate(ulong handle) { return previousNeighbours.Contains(handle); });
1193 // }
1194
1195 private List<ulong> OldNeighbours(List<ulong> currentNeighbours, List<ulong> previousNeighbours)
1196 {
1197 return previousNeighbours.FindAll(delegate(ulong handle) { return !currentNeighbours.Contains(handle); });
1198 }
1199
1200 private List<ulong> NeighbourHandles(List<GridRegion> neighbours)
1201 {
1202 List<ulong> handles = new List<ulong>();
1203 foreach (GridRegion reg in neighbours)
1204 {
1205 handles.Add(reg.RegionHandle);
1206 }
1207 return handles;
1208 }
1209
1210 private void Dump(string msg, List<ulong> handles)
1211 {
1212 m_log.InfoFormat("-------------- HANDLE DUMP ({0}) ---------", msg);
1213 foreach (ulong handle in handles)
1214 {
1215 uint x, y;
1216 Utils.LongToUInts(handle, out x, out y);
1217 x = x / Constants.RegionSize;
1218 y = y / Constants.RegionSize;
1219 m_log.InfoFormat("({0}, {1})", x, y);
1220 }
1221 }
1222
1223 #endregion
1224
1225
1226 #region Agent Arrived
1227 public void AgentArrivedAtDestination(UUID id)
1228 {
1229 //m_log.Debug(" >>> ReleaseAgent called <<< ");
1230 ResetFromTransit(id);
1231 }
1232
1233 #endregion
1234
1235 #region Object Transfers
1236 /// <summary>
1237 /// Move the given scene object into a new region depending on which region its absolute position has moved
1238 /// into.
1239 ///
1240 /// This method locates the new region handle and offsets the prim position for the new region
1241 /// </summary>
1242 /// <param name="attemptedPosition">the attempted out of region position of the scene object</param>
1243 /// <param name="grp">the scene object that we're crossing</param>
1244 public void Cross(SceneObjectGroup grp, Vector3 attemptedPosition, bool silent)
1245 {
1246 if (grp == null)
1247 return;
1248 if (grp.IsDeleted)
1249 return;
1250
1251 Scene scene = grp.Scene;
1252 if (scene == null)
1253 return;
1254
1255 if (grp.RootPart.DIE_AT_EDGE)
1256 {
1257 // We remove the object here
1258 try
1259 {
1260 scene.DeleteSceneObject(grp, false);
1261 }
1262 catch (Exception)
1263 {
1264 m_log.Warn("[DATABASE]: exception when trying to remove the prim that crossed the border.");
1265 }
1266 return;
1267 }
1268
1269 int thisx = (int)scene.RegionInfo.RegionLocX;
1270 int thisy = (int)scene.RegionInfo.RegionLocY;
1271 Vector3 EastCross = new Vector3(0.1f, 0, 0);
1272 Vector3 WestCross = new Vector3(-0.1f, 0, 0);
1273 Vector3 NorthCross = new Vector3(0, 0.1f, 0);
1274 Vector3 SouthCross = new Vector3(0, -0.1f, 0);
1275
1276
1277 // use this if no borders were crossed!
1278 ulong newRegionHandle
1279 = Util.UIntsToLong((uint)((thisx) * Constants.RegionSize),
1280 (uint)((thisy) * Constants.RegionSize));
1281
1282 Vector3 pos = attemptedPosition;
1283
1284 int changeX = 1;
1285 int changeY = 1;
1286
1287 if (scene.TestBorderCross(attemptedPosition + WestCross, Cardinals.W))
1288 {
1289 if (scene.TestBorderCross(attemptedPosition + SouthCross, Cardinals.S))
1290 {
1291
1292 Border crossedBorderx = scene.GetCrossedBorder(attemptedPosition + WestCross, Cardinals.W);
1293
1294 if (crossedBorderx.BorderLine.Z > 0)
1295 {
1296 pos.X = ((pos.X + crossedBorderx.BorderLine.Z));
1297 changeX = (int)(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize);
1298 }
1299 else
1300 pos.X = ((pos.X + Constants.RegionSize));
1301
1302 Border crossedBordery = scene.GetCrossedBorder(attemptedPosition + SouthCross, Cardinals.S);
1303 //(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize)
1304
1305 if (crossedBordery.BorderLine.Z > 0)
1306 {
1307 pos.Y = ((pos.Y + crossedBordery.BorderLine.Z));
1308 changeY = (int)(crossedBordery.BorderLine.Z / (int)Constants.RegionSize);
1309 }
1310 else
1311 pos.Y = ((pos.Y + Constants.RegionSize));
1312
1313
1314
1315 newRegionHandle
1316 = Util.UIntsToLong((uint)((thisx - changeX) * Constants.RegionSize),
1317 (uint)((thisy - changeY) * Constants.RegionSize));
1318 // x - 1
1319 // y - 1
1320 }
1321 else if (scene.TestBorderCross(attemptedPosition + NorthCross, Cardinals.N))
1322 {
1323 Border crossedBorderx = scene.GetCrossedBorder(attemptedPosition + WestCross, Cardinals.W);
1324
1325 if (crossedBorderx.BorderLine.Z > 0)
1326 {
1327 pos.X = ((pos.X + crossedBorderx.BorderLine.Z));
1328 changeX = (int)(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize);
1329 }
1330 else
1331 pos.X = ((pos.X + Constants.RegionSize));
1332
1333
1334 Border crossedBordery = scene.GetCrossedBorder(attemptedPosition + SouthCross, Cardinals.S);
1335 //(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize)
1336
1337 if (crossedBordery.BorderLine.Z > 0)
1338 {
1339 pos.Y = ((pos.Y + crossedBordery.BorderLine.Z));
1340 changeY = (int)(crossedBordery.BorderLine.Z / (int)Constants.RegionSize);
1341 }
1342 else
1343 pos.Y = ((pos.Y + Constants.RegionSize));
1344
1345 newRegionHandle
1346 = Util.UIntsToLong((uint)((thisx - changeX) * Constants.RegionSize),
1347 (uint)((thisy + changeY) * Constants.RegionSize));
1348 // x - 1
1349 // y + 1
1350 }
1351 else
1352 {
1353 Border crossedBorderx = scene.GetCrossedBorder(attemptedPosition + WestCross, Cardinals.W);
1354
1355 if (crossedBorderx.BorderLine.Z > 0)
1356 {
1357 pos.X = ((pos.X + crossedBorderx.BorderLine.Z));
1358 changeX = (int)(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize);
1359 }
1360 else
1361 pos.X = ((pos.X + Constants.RegionSize));
1362
1363 newRegionHandle
1364 = Util.UIntsToLong((uint)((thisx - changeX) * Constants.RegionSize),
1365 (uint)(thisy * Constants.RegionSize));
1366 // x - 1
1367 }
1368 }
1369 else if (scene.TestBorderCross(attemptedPosition + EastCross, Cardinals.E))
1370 {
1371 if (scene.TestBorderCross(attemptedPosition + SouthCross, Cardinals.S))
1372 {
1373
1374 pos.X = ((pos.X - Constants.RegionSize));
1375 Border crossedBordery = scene.GetCrossedBorder(attemptedPosition + SouthCross, Cardinals.S);
1376 //(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize)
1377
1378 if (crossedBordery.BorderLine.Z > 0)
1379 {
1380 pos.Y = ((pos.Y + crossedBordery.BorderLine.Z));
1381 changeY = (int)(crossedBordery.BorderLine.Z / (int)Constants.RegionSize);
1382 }
1383 else
1384 pos.Y = ((pos.Y + Constants.RegionSize));
1385
1386
1387 newRegionHandle
1388 = Util.UIntsToLong((uint)((thisx + changeX) * Constants.RegionSize),
1389 (uint)((thisy - changeY) * Constants.RegionSize));
1390 // x + 1
1391 // y - 1
1392 }
1393 else if (scene.TestBorderCross(attemptedPosition + NorthCross, Cardinals.N))
1394 {
1395 pos.X = ((pos.X - Constants.RegionSize));
1396 pos.Y = ((pos.Y - Constants.RegionSize));
1397 newRegionHandle
1398 = Util.UIntsToLong((uint)((thisx + changeX) * Constants.RegionSize),
1399 (uint)((thisy + changeY) * Constants.RegionSize));
1400 // x + 1
1401 // y + 1
1402 }
1403 else
1404 {
1405 pos.X = ((pos.X - Constants.RegionSize));
1406 newRegionHandle
1407 = Util.UIntsToLong((uint)((thisx + changeX) * Constants.RegionSize),
1408 (uint)(thisy * Constants.RegionSize));
1409 // x + 1
1410 }
1411 }
1412 else if (scene.TestBorderCross(attemptedPosition + SouthCross, Cardinals.S))
1413 {
1414 Border crossedBordery = scene.GetCrossedBorder(attemptedPosition + SouthCross, Cardinals.S);
1415 //(crossedBorderx.BorderLine.Z / (int)Constants.RegionSize)
1416
1417 if (crossedBordery.BorderLine.Z > 0)
1418 {
1419 pos.Y = ((pos.Y + crossedBordery.BorderLine.Z));
1420 changeY = (int)(crossedBordery.BorderLine.Z / (int)Constants.RegionSize);
1421 }
1422 else
1423 pos.Y = ((pos.Y + Constants.RegionSize));
1424
1425 newRegionHandle
1426 = Util.UIntsToLong((uint)(thisx * Constants.RegionSize), (uint)((thisy - changeY) * Constants.RegionSize));
1427 // y - 1
1428 }
1429 else if (scene.TestBorderCross(attemptedPosition + NorthCross, Cardinals.N))
1430 {
1431
1432 pos.Y = ((pos.Y - Constants.RegionSize));
1433 newRegionHandle
1434 = Util.UIntsToLong((uint)(thisx * Constants.RegionSize), (uint)((thisy + changeY) * Constants.RegionSize));
1435 // y + 1
1436 }
1437
1438 // Offset the positions for the new region across the border
1439 Vector3 oldGroupPosition = grp.RootPart.GroupPosition;
1440 grp.OffsetForNewRegion(pos);
1441
1442 // If we fail to cross the border, then reset the position of the scene object on that border.
1443 uint x = 0, y = 0;
1444 Utils.LongToUInts(newRegionHandle, out x, out y);
1445 GridRegion destination = scene.GridService.GetRegionByPosition(UUID.Zero, (int)x, (int)y);
1446 if (destination != null && !CrossPrimGroupIntoNewRegion(destination, grp, silent))
1447 {
1448 grp.OffsetForNewRegion(oldGroupPosition);
1449 grp.ScheduleGroupForFullUpdate();
1450 }
1451 }
1452
1453
1454 /// <summary>
1455 /// Move the given scene object into a new region
1456 /// </summary>
1457 /// <param name="newRegionHandle"></param>
1458 /// <param name="grp">Scene Object Group that we're crossing</param>
1459 /// <returns>
1460 /// true if the crossing itself was successful, false on failure
1461 /// FIMXE: we still return true if the crossing object was not successfully deleted from the originating region
1462 /// </returns>
1463 protected bool CrossPrimGroupIntoNewRegion(GridRegion destination, SceneObjectGroup grp, bool silent)
1464 {
1465 //m_log.Debug(" >>> CrossPrimGroupIntoNewRegion <<<");
1466
1467 bool successYN = false;
1468 grp.RootPart.UpdateFlag = 0;
1469 //int primcrossingXMLmethod = 0;
1470
1471 if (destination != null)
1472 {
1473 //string objectState = grp.GetStateSnapshot();
1474
1475 //successYN
1476 // = m_sceneGridService.PrimCrossToNeighboringRegion(
1477 // newRegionHandle, grp.UUID, m_serialiser.SaveGroupToXml2(grp), primcrossingXMLmethod);
1478 //if (successYN && (objectState != "") && m_allowScriptCrossings)
1479 //{
1480 // successYN = m_sceneGridService.PrimCrossToNeighboringRegion(
1481 // newRegionHandle, grp.UUID, objectState, 100);
1482 //}
1483
1484 //// And the new channel...
1485 //if (m_interregionCommsOut != null)
1486 // successYN = m_interregionCommsOut.SendCreateObject(newRegionHandle, grp, true);
1487 if (m_aScene.SimulationService != null)
1488 successYN = m_aScene.SimulationService.CreateObject(destination, grp, true);
1489
1490 if (successYN)
1491 {
1492 // We remove the object here
1493 try
1494 {
1495 grp.Scene.DeleteSceneObject(grp, silent);
1496 }
1497 catch (Exception e)
1498 {
1499 m_log.ErrorFormat(
1500 "[ENTITY TRANSFER MODULE]: Exception deleting the old object left behind on a border crossing for {0}, {1}",
1501 grp, e);
1502 }
1503 }
1504 else
1505 {
1506 if (!grp.IsDeleted)
1507 {
1508 if (grp.RootPart.PhysActor != null)
1509 {
1510 grp.RootPart.PhysActor.CrossingFailure();
1511 }
1512 }
1513
1514 m_log.ErrorFormat("[ENTITY TRANSFER MODULE]: Prim crossing failed for {0}", grp);
1515 }
1516 }
1517 else
1518 {
1519 m_log.Error("[ENTITY TRANSFER MODULE]: destination was unexpectedly null in Scene.CrossPrimGroupIntoNewRegion()");
1520 }
1521
1522 return successYN;
1523 }
1524
1525 protected bool CrossAttachmentsIntoNewRegion(GridRegion destination, ScenePresence sp, bool silent)
1526 {
1527 List<SceneObjectGroup> m_attachments = sp.Attachments;
1528 lock (m_attachments)
1529 {
1530 // Validate
1531 foreach (SceneObjectGroup gobj in m_attachments)
1532 {
1533 if (gobj == null || gobj.IsDeleted)
1534 return false;
1535 }
1536
1537 foreach (SceneObjectGroup gobj in m_attachments)
1538 {
1539 // If the prim group is null then something must have happened to it!
1540 if (gobj != null && gobj.RootPart != null)
1541 {
1542 // Set the parent localID to 0 so it transfers over properly.
1543 gobj.RootPart.SetParentLocalId(0);
1544 gobj.AbsolutePosition = gobj.RootPart.AttachedPos;
1545 gobj.RootPart.IsAttachment = false;
1546 //gobj.RootPart.LastOwnerID = gobj.GetFromAssetID();
1547 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Sending attachment {0} to region {1}", gobj.UUID, destination.RegionName);
1548 CrossPrimGroupIntoNewRegion(destination, gobj, silent);
1549 }
1550 }
1551 m_attachments.Clear();
1552
1553 return true;
1554 }
1555 }
1556
1557 #endregion
1558
1559 #region Misc
1560
1561 protected bool WaitForCallback(UUID id)
1562 {
1563 int count = 200;
1564 while (m_agentsInTransit.Contains(id) && count-- > 0)
1565 {
1566 //m_log.Debug(" >>> Waiting... " + count);
1567 Thread.Sleep(100);
1568 }
1569
1570 if (count > 0)
1571 return true;
1572 else
1573 return false;
1574 }
1575
1576 protected void SetInTransit(UUID id)
1577 {
1578 lock (m_agentsInTransit)
1579 {
1580 if (!m_agentsInTransit.Contains(id))
1581 m_agentsInTransit.Add(id);
1582 }
1583 }
1584
1585 protected bool ResetFromTransit(UUID id)
1586 {
1587 lock (m_agentsInTransit)
1588 {
1589 if (m_agentsInTransit.Contains(id))
1590 {
1591 m_agentsInTransit.Remove(id);
1592 return true;
1593 }
1594 }
1595 return false;
1596 }
1597
1598
1599 #endregion
1600
1601 }
1602}
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs
new file mode 100644
index 0000000..28593fc
--- /dev/null
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs
@@ -0,0 +1,273 @@
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;
31
32using OpenSim.Framework;
33using OpenSim.Region.Framework.Interfaces;
34using OpenSim.Region.Framework.Scenes;
35using OpenSim.Services.Connectors.Hypergrid;
36using OpenSim.Services.Interfaces;
37using OpenSim.Server.Base;
38
39using GridRegion = OpenSim.Services.Interfaces.GridRegion;
40
41using OpenMetaverse;
42using log4net;
43using Nini.Config;
44
45namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
46{
47 public class HGEntityTransferModule : EntityTransferModule, ISharedRegionModule, IEntityTransferModule, IUserAgentVerificationModule
48 {
49 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
50
51 private bool m_Initialized = false;
52
53 private GatekeeperServiceConnector m_GatekeeperConnector;
54
55 #region ISharedRegionModule
56
57 public override string Name
58 {
59 get { return "HGEntityTransferModule"; }
60 }
61
62 public override void Initialise(IConfigSource source)
63 {
64 IConfig moduleConfig = source.Configs["Modules"];
65 if (moduleConfig != null)
66 {
67 string name = moduleConfig.GetString("EntityTransferModule", "");
68 if (name == Name)
69 {
70 m_agentsInTransit = new List<UUID>();
71
72 m_Enabled = true;
73 m_log.InfoFormat("[HG ENTITY TRANSFER MODULE]: {0} enabled.", Name);
74 }
75 }
76 }
77
78 public override void AddRegion(Scene scene)
79 {
80 base.AddRegion(scene);
81 if (m_Enabled)
82 {
83 scene.RegisterModuleInterface<IUserAgentVerificationModule>(this);
84 }
85 }
86
87 protected override void OnNewClient(IClientAPI client)
88 {
89 client.OnTeleportHomeRequest += TeleportHome;
90 client.OnConnectionClosed += new Action<IClientAPI>(OnConnectionClosed);
91 }
92
93
94 public override void RegionLoaded(Scene scene)
95 {
96 base.RegionLoaded(scene);
97 if (m_Enabled)
98 if (!m_Initialized)
99 {
100 m_GatekeeperConnector = new GatekeeperServiceConnector(scene.AssetService);
101 m_Initialized = true;
102 }
103
104 }
105 public override void RemoveRegion(Scene scene)
106 {
107 base.AddRegion(scene);
108 if (m_Enabled)
109 {
110 scene.UnregisterModuleInterface<IUserAgentVerificationModule>(this);
111 }
112 }
113
114
115 #endregion
116
117 #region HG overrides of IEntiryTransferModule
118
119 protected override GridRegion GetFinalDestination(GridRegion region)
120 {
121 int flags = m_aScene.GridService.GetRegionFlags(m_aScene.RegionInfo.ScopeID, region.RegionID);
122 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: region {0} flags: {1}", region.RegionID, flags);
123 if ((flags & (int)OpenSim.Data.RegionFlags.Hyperlink) != 0)
124 {
125 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Destination region {0} is hyperlink", region.RegionID);
126 return m_GatekeeperConnector.GetHyperlinkRegion(region, region.RegionID);
127 }
128 return region;
129 }
130
131 protected override bool NeedsClosing(uint oldRegionX, uint newRegionX, uint oldRegionY, uint newRegionY, GridRegion reg)
132 {
133 if (base.NeedsClosing(oldRegionX, newRegionX, oldRegionY, newRegionY, reg))
134 return true;
135
136 int flags = m_aScene.GridService.GetRegionFlags(m_aScene.RegionInfo.ScopeID, reg.RegionID);
137 if (flags == -1 /* no region in DB */ || (flags & (int)OpenSim.Data.RegionFlags.Hyperlink) != 0)
138 return true;
139
140 return false;
141 }
142
143 protected override bool CreateAgent(ScenePresence sp, GridRegion reg, GridRegion finalDestination, AgentCircuitData agentCircuit, uint teleportFlags, out string reason)
144 {
145 reason = string.Empty;
146 int flags = m_aScene.GridService.GetRegionFlags(m_aScene.RegionInfo.ScopeID, reg.RegionID);
147 if (flags == -1 /* no region in DB */ || (flags & (int)OpenSim.Data.RegionFlags.Hyperlink) != 0)
148 {
149 // this user is going to another grid
150 if (agentCircuit.ServiceURLs.ContainsKey("HomeURI"))
151 {
152 string userAgentDriver = agentCircuit.ServiceURLs["HomeURI"].ToString();
153 IUserAgentService connector = new UserAgentServiceConnector(userAgentDriver);
154 bool success = connector.LoginAgentToGrid(agentCircuit, reg, finalDestination, out reason);
155 if (success)
156 // Log them out of this grid
157 m_aScene.PresenceService.LogoutAgent(agentCircuit.SessionID, sp.AbsolutePosition, sp.Lookat);
158
159 return success;
160 }
161 else
162 {
163 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Agent does not have a HomeURI address");
164 return false;
165 }
166 }
167
168 return m_aScene.SimulationService.CreateAgent(reg, agentCircuit, teleportFlags, out reason);
169 }
170
171 public override void TeleportHome(UUID id, IClientAPI client)
172 {
173 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Request to teleport {0} {1} home", client.FirstName, client.LastName);
174
175 // Let's find out if this is a foreign user or a local user
176 UserAccount account = m_aScene.UserAccountService.GetUserAccount(m_aScene.RegionInfo.ScopeID, id);
177 if (account != null)
178 {
179 // local grid user
180 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: User is local");
181 base.TeleportHome(id, client);
182 return;
183 }
184
185 // Foreign user wants to go home
186 //
187 AgentCircuitData aCircuit = ((Scene)(client.Scene)).AuthenticateHandler.GetAgentCircuitData(client.CircuitCode);
188 if (aCircuit == null || (aCircuit != null && !aCircuit.ServiceURLs.ContainsKey("HomeURI")))
189 {
190 client.SendTeleportFailed("Your information has been lost");
191 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Unable to locate agent's gateway information");
192 return;
193 }
194
195 IUserAgentService userAgentService = new UserAgentServiceConnector(aCircuit.ServiceURLs["HomeURI"].ToString());
196 Vector3 position = Vector3.UnitY, lookAt = Vector3.UnitY;
197 GridRegion finalDestination = userAgentService.GetHomeRegion(aCircuit.AgentID, out position, out lookAt);
198 if (finalDestination == null)
199 {
200 client.SendTeleportFailed("Your home region could not be found");
201 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Agent's home region not found");
202 return;
203 }
204
205 ScenePresence sp = ((Scene)(client.Scene)).GetScenePresence(client.AgentId);
206 if (sp == null)
207 {
208 client.SendTeleportFailed("Internal error");
209 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Agent not found in the scene where it is supposed to be");
210 return;
211 }
212
213 IEventQueue eq = sp.Scene.RequestModuleInterface<IEventQueue>();
214 GridRegion homeGatekeeper = MakeRegion(aCircuit);
215
216 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: teleporting user {0} {1} home to {2} via {3}:{4}:{5}",
217 aCircuit.firstname, aCircuit.lastname, finalDestination.RegionName, homeGatekeeper.ExternalHostName, homeGatekeeper.HttpPort, homeGatekeeper.RegionName);
218
219 DoTeleport(sp, homeGatekeeper, finalDestination, position, lookAt, (uint)(Constants.TeleportFlags.SetLastToTarget | Constants.TeleportFlags.ViaHome), eq);
220 }
221 #endregion
222
223 #region IUserAgentVerificationModule
224
225 public bool VerifyClient(AgentCircuitData aCircuit, string token)
226 {
227 if (aCircuit.ServiceURLs.ContainsKey("HomeURI"))
228 {
229 string url = aCircuit.ServiceURLs["HomeURI"].ToString();
230 IUserAgentService security = new UserAgentServiceConnector(url);
231 return security.VerifyClient(aCircuit.SessionID, token);
232 }
233
234 return false;
235 }
236
237 void OnConnectionClosed(IClientAPI obj)
238 {
239 if (obj.IsLoggingOut)
240 {
241 AgentCircuitData aCircuit = ((Scene)(obj.Scene)).AuthenticateHandler.GetAgentCircuitData(obj.CircuitCode);
242
243 if (aCircuit.ServiceURLs.ContainsKey("HomeURI"))
244 {
245 string url = aCircuit.ServiceURLs["HomeURI"].ToString();
246 IUserAgentService security = new UserAgentServiceConnector(url);
247 security.LogoutAgent(obj.AgentId, obj.SessionId);
248 //m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Sent logout call to UserAgentService @ {0}", url);
249 }
250 else
251 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: HomeURI not found for agent {0} logout", obj.AgentId);
252 }
253 }
254
255 #endregion
256
257 private GridRegion MakeRegion(AgentCircuitData aCircuit)
258 {
259 GridRegion region = new GridRegion();
260
261 Uri uri = null;
262 if (!aCircuit.ServiceURLs.ContainsKey("HomeURI") ||
263 (aCircuit.ServiceURLs.ContainsKey("HomeURI") && !Uri.TryCreate(aCircuit.ServiceURLs["HomeURI"].ToString(), UriKind.Absolute, out uri)))
264 return null;
265
266 region.ExternalHostName = uri.Host;
267 region.HttpPort = (uint)uri.Port;
268 region.RegionName = string.Empty;
269 region.InternalEndPoint = new System.Net.IPEndPoint(System.Net.IPAddress.Parse("0.0.0.0"), (int)0);
270 return region;
271 }
272 }
273}
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs
new file mode 100644
index 0000000..664f38d
--- /dev/null
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs
@@ -0,0 +1,200 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Reflection;
31using System.Threading;
32using log4net;
33using OpenMetaverse;
34using OpenSim.Framework;
35
36using OpenSim.Region.Framework.Scenes;
37using OpenSim.Region.Framework.Scenes.Serialization;
38using OpenSim.Region.Framework.Interfaces;
39using OpenSim.Services.Interfaces;
40
41//using HyperGrid.Framework;
42//using OpenSim.Region.Communications.Hypergrid;
43
44namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
45{
46 public class HGAssetMapper
47 {
48 #region Fields
49 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
50
51 // This maps between inventory server urls and inventory server clients
52// private Dictionary<string, InventoryClient> m_inventoryServers = new Dictionary<string, InventoryClient>();
53
54 private Scene m_scene;
55
56 #endregion
57
58 #region Constructor
59
60 public HGAssetMapper(Scene scene)
61 {
62 m_scene = scene;
63 }
64
65 #endregion
66
67 #region Internal functions
68
69 public AssetBase FetchAsset(string url, UUID assetID)
70 {
71 AssetBase asset = m_scene.AssetService.Get(url + "/" + assetID.ToString());
72
73 if (asset != null)
74 {
75 m_log.DebugFormat("[HG ASSET MAPPER]: Copied asset {0} from {1} to local asset server. ", asset.ID, url);
76 return asset;
77 }
78 return null;
79 }
80
81 public bool PostAsset(string url, AssetBase asset)
82 {
83 if (asset != null)
84 {
85 // See long comment in AssetCache.AddAsset
86 if (!asset.Temporary || asset.Local)
87 {
88 // We need to copy the asset into a new asset, because
89 // we need to set its ID to be URL+UUID, so that the
90 // HGAssetService dispatches it to the remote grid.
91 // It's not pretty, but the best that can be done while
92 // not having a global naming infrastructure
93 AssetBase asset1 = new AssetBase(asset.FullID, asset.Name, asset.Type, asset.Metadata.CreatorID);
94 Copy(asset, asset1);
95 try
96 {
97 asset1.ID = url + "/" + asset.ID;
98 }
99 catch
100 {
101 m_log.Warn("[HG ASSET MAPPER]: Oops.");
102 }
103
104 m_scene.AssetService.Store(asset1);
105 m_log.DebugFormat("[HG ASSET MAPPER]: Posted copy of asset {0} from local asset server to {1}", asset1.ID, url);
106 }
107 return true;
108 }
109 else
110 m_log.Warn("[HG ASSET MAPPER]: Tried to post asset to remote server, but asset not in local cache.");
111
112 return false;
113 }
114
115 private void Copy(AssetBase from, AssetBase to)
116 {
117 to.Data = from.Data;
118 to.Description = from.Description;
119 to.FullID = from.FullID;
120 to.ID = from.ID;
121 to.Local = from.Local;
122 to.Name = from.Name;
123 to.Temporary = from.Temporary;
124 to.Type = from.Type;
125
126 }
127
128 // TODO: unused
129 // private void Dump(Dictionary<UUID, bool> lst)
130 // {
131 // m_log.Debug("XXX -------- UUID DUMP ------- XXX");
132 // foreach (KeyValuePair<UUID, bool> kvp in lst)
133 // m_log.Debug(" >> " + kvp.Key + " (texture? " + kvp.Value + ")");
134 // m_log.Debug("XXX -------- UUID DUMP ------- XXX");
135 // }
136
137 #endregion
138
139
140 #region Public interface
141
142 public void Get(UUID assetID, UUID ownerID, string userAssetURL)
143 {
144 // Get the item from the remote asset server onto the local AssetCache
145 // and place an entry in m_assetMap
146
147 m_log.Debug("[HG ASSET MAPPER]: Fetching object " + assetID + " from asset server " + userAssetURL);
148 AssetBase asset = FetchAsset(userAssetURL, assetID);
149
150 if (asset != null)
151 {
152 // OK, now fetch the inside.
153 Dictionary<UUID, int> ids = new Dictionary<UUID, int>();
154 HGUuidGatherer uuidGatherer = new HGUuidGatherer(this, m_scene.AssetService, userAssetURL);
155 uuidGatherer.GatherAssetUuids(asset.FullID, (AssetType)asset.Type, ids);
156 foreach (UUID uuid in ids.Keys)
157 FetchAsset(userAssetURL, uuid);
158
159 m_log.DebugFormat("[HG ASSET MAPPER]: Successfully fetched asset {0} from asset server {1}", asset.ID, userAssetURL);
160
161 }
162 else
163 m_log.Warn("[HG ASSET MAPPER]: Could not fetch asset from remote asset server " + userAssetURL);
164 }
165
166
167 public void Post(UUID assetID, UUID ownerID, string userAssetURL)
168 {
169 // Post the item from the local AssetCache onto the remote asset server
170 // and place an entry in m_assetMap
171
172 m_log.Debug("[HG ASSET MAPPER]: Posting object " + assetID + " to asset server " + userAssetURL);
173 AssetBase asset = m_scene.AssetService.Get(assetID.ToString());
174 if (asset != null)
175 {
176 Dictionary<UUID, int> ids = new Dictionary<UUID, int>();
177 HGUuidGatherer uuidGatherer = new HGUuidGatherer(this, m_scene.AssetService, string.Empty);
178 uuidGatherer.GatherAssetUuids(asset.FullID, (AssetType)asset.Type, ids);
179 foreach (UUID uuid in ids.Keys)
180 {
181 asset = m_scene.AssetService.Get(uuid.ToString());
182 if (asset == null)
183 m_log.DebugFormat("[HG ASSET MAPPER]: Could not find asset {0}", uuid);
184 else
185 PostAsset(userAssetURL, asset);
186 }
187
188 // maybe all pieces got there...
189 m_log.DebugFormat("[HG ASSET MAPPER]: Successfully posted item {0} to asset server {1}", assetID, userAssetURL);
190
191 }
192 else
193 m_log.DebugFormat("[HG ASSET MAPPER]: Something wrong with asset {0}, it could not be found", assetID);
194
195 }
196
197 #endregion
198
199 }
200}
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs
new file mode 100644
index 0000000..25f5154
--- /dev/null
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs
@@ -0,0 +1,207 @@
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;
31
32using OpenSim.Framework;
33using OpenSim.Region.Framework.Interfaces;
34using OpenSim.Region.Framework.Scenes;
35using OpenSim.Services.Connectors.Hypergrid;
36using OpenSim.Services.Interfaces;
37using OpenSim.Server.Base;
38
39using GridRegion = OpenSim.Services.Interfaces.GridRegion;
40
41using OpenMetaverse;
42using log4net;
43using Nini.Config;
44
45namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
46{
47 public class HGInventoryAccessModule : BasicInventoryAccessModule, INonSharedRegionModule, IInventoryAccessModule
48 {
49 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
50
51 private static HGAssetMapper m_assMapper;
52 public static HGAssetMapper AssetMapper
53 {
54 get { return m_assMapper; }
55 }
56
57 private bool m_Initialized = false;
58
59 #region INonSharedRegionModule
60
61 public override string Name
62 {
63 get { return "HGInventoryAccessModule"; }
64 }
65
66 public override void Initialise(IConfigSource source)
67 {
68 IConfig moduleConfig = source.Configs["Modules"];
69 if (moduleConfig != null)
70 {
71 string name = moduleConfig.GetString("InventoryAccessModule", "");
72 if (name == Name)
73 {
74 m_Enabled = true;
75 m_log.InfoFormat("[HG INVENTORY ACCESS MODULE]: {0} enabled.", Name);
76 }
77 }
78 }
79
80 public override void AddRegion(Scene scene)
81 {
82 if (!m_Enabled)
83 return;
84
85 base.AddRegion(scene);
86 m_assMapper = new HGAssetMapper(scene);
87 scene.EventManager.OnNewInventoryItemUploadComplete += UploadInventoryItem;
88
89 }
90
91 #endregion
92
93 #region Event handlers
94
95 public void UploadInventoryItem(UUID avatarID, UUID assetID, string name, int userlevel)
96 {
97 string userAssetServer = string.Empty;
98 if (IsForeignUser(avatarID, out userAssetServer))
99 {
100 m_assMapper.Post(assetID, avatarID, userAssetServer);
101 }
102 }
103
104 #endregion
105
106 #region Overrides of Basic Inventory Access methods
107 ///
108 /// CapsUpdateInventoryItemAsset
109 ///
110 public override UUID CapsUpdateInventoryItemAsset(IClientAPI remoteClient, UUID itemID, byte[] data)
111 {
112 UUID newAssetID = base.CapsUpdateInventoryItemAsset(remoteClient, itemID, data);
113
114 UploadInventoryItem(remoteClient.AgentId, newAssetID, "", 0);
115
116 return newAssetID;
117 }
118
119 ///
120 /// DeleteToInventory
121 ///
122 public override UUID DeleteToInventory(DeRezAction action, UUID folderID, SceneObjectGroup objectGroup, IClientAPI remoteClient)
123 {
124 UUID assetID = base.DeleteToInventory(action, folderID, objectGroup, remoteClient);
125
126 if (!assetID.Equals(UUID.Zero))
127 {
128 UploadInventoryItem(remoteClient.AgentId, assetID, "", 0);
129 }
130 else
131 m_log.Debug("[HGScene]: Scene.Inventory did not create asset");
132
133 return assetID;
134 }
135
136 ///
137 /// RezObject
138 ///
139 public override SceneObjectGroup RezObject(IClientAPI remoteClient, UUID itemID, Vector3 RayEnd, Vector3 RayStart,
140 UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection,
141 bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment)
142 {
143 m_log.DebugFormat("[HGScene] RezObject itemID={0} fromTaskID={1}", itemID, fromTaskID);
144
145 //if (fromTaskID.Equals(UUID.Zero))
146 //{
147 InventoryItemBase item = new InventoryItemBase(itemID);
148 item.Owner = remoteClient.AgentId;
149 item = m_Scene.InventoryService.GetItem(item);
150 //if (item == null)
151 //{ // Fetch the item
152 // item = new InventoryItemBase();
153 // item.Owner = remoteClient.AgentId;
154 // item.ID = itemID;
155 // item = m_assMapper.Get(item, userInfo.RootFolder.ID, userInfo);
156 //}
157 string userAssetServer = string.Empty;
158 if (item != null && IsForeignUser(remoteClient.AgentId, out userAssetServer))
159 {
160 m_assMapper.Get(item.AssetID, remoteClient.AgentId, userAssetServer);
161
162 }
163 //}
164
165 // OK, we're done fetching. Pass it up to the default RezObject
166 return base.RezObject(remoteClient, itemID, RayEnd, RayStart, RayTargetID, BypassRayCast, RayEndIsIntersection,
167 RezSelected, RemoveItem, fromTaskID, attachment);
168
169 }
170
171 public override void TransferInventoryAssets(InventoryItemBase item, UUID sender, UUID receiver)
172 {
173 string userAssetServer = string.Empty;
174 if (IsForeignUser(sender, out userAssetServer))
175 m_assMapper.Get(item.AssetID, sender, userAssetServer);
176
177 if (IsForeignUser(receiver, out userAssetServer))
178 m_assMapper.Post(item.AssetID, receiver, userAssetServer);
179 }
180
181 #endregion
182
183 public bool IsForeignUser(UUID userID, out string assetServerURL)
184 {
185 assetServerURL = string.Empty;
186 UserAccount account = null;
187 if (m_Scene.UserAccountService != null)
188 account = m_Scene.UserAccountService.GetUserAccount(m_Scene.RegionInfo.ScopeID, userID);
189
190 if (account == null) // foreign
191 {
192 ScenePresence sp = null;
193 if (m_Scene.TryGetAvatar(userID, out sp))
194 {
195 AgentCircuitData aCircuit = m_Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode);
196 if (aCircuit.ServiceURLs.ContainsKey("AssetServerURI"))
197 {
198 assetServerURL = aCircuit.ServiceURLs["AssetServerURI"].ToString();
199 assetServerURL = assetServerURL.Trim(new char[] { '/' }); return true;
200 }
201 }
202 }
203
204 return false;
205 }
206 }
207}
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGUuidGatherer.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGUuidGatherer.cs
new file mode 100644
index 0000000..fcb544f
--- /dev/null
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGUuidGatherer.cs
@@ -0,0 +1,57 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30
31using OpenSim.Framework;
32using OpenSim.Region.Framework.Scenes;
33using OpenSim.Services.Interfaces;
34using OpenMetaverse;
35
36namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
37{
38 public class HGUuidGatherer : UuidGatherer
39 {
40 protected string m_assetServerURL;
41 protected HGAssetMapper m_assetMapper;
42
43 public HGUuidGatherer(HGAssetMapper assMap, IAssetService assetCache, string assetServerURL) : base(assetCache)
44 {
45 m_assetMapper = assMap;
46 m_assetServerURL = assetServerURL;
47 }
48
49 protected override AssetBase GetAsset(UUID uuid)
50 {
51 if (string.Empty == m_assetServerURL)
52 return m_assetCache.Get(uuid.ToString());
53 else
54 return m_assetMapper.FetchAsset(m_assetServerURL, uuid);
55 }
56 }
57}
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
new file mode 100644
index 0000000..e0df288
--- /dev/null
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
@@ -0,0 +1,655 @@
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.Net;
31using System.Reflection;
32using System.Threading;
33
34using OpenSim.Framework;
35using OpenSim.Framework.Capabilities;
36using OpenSim.Framework.Client;
37using OpenSim.Region.Framework.Interfaces;
38using OpenSim.Region.Framework.Scenes;
39using OpenSim.Region.Framework.Scenes.Serialization;
40using OpenSim.Services.Interfaces;
41
42using GridRegion = OpenSim.Services.Interfaces.GridRegion;
43
44using OpenMetaverse;
45using log4net;
46using Nini.Config;
47
48namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
49{
50 public class BasicInventoryAccessModule : INonSharedRegionModule, IInventoryAccessModule
51 {
52 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
53
54 protected bool m_Enabled = false;
55 protected Scene m_Scene;
56
57 #region INonSharedRegionModule
58
59 public Type ReplaceableInterface
60 {
61 get { return null; }
62 }
63
64 public virtual string Name
65 {
66 get { return "BasicInventoryAccessModule"; }
67 }
68
69 public virtual void Initialise(IConfigSource source)
70 {
71 IConfig moduleConfig = source.Configs["Modules"];
72 if (moduleConfig != null)
73 {
74 string name = moduleConfig.GetString("InventoryAccessModule", "");
75 if (name == Name)
76 {
77 m_Enabled = true;
78 m_log.InfoFormat("[INVENTORY ACCESS MODULE]: {0} enabled.", Name);
79 }
80 }
81 }
82
83 public virtual void PostInitialise()
84 {
85 }
86
87 public virtual void AddRegion(Scene scene)
88 {
89 if (!m_Enabled)
90 return;
91
92 m_Scene = scene;
93
94 scene.RegisterModuleInterface<IInventoryAccessModule>(this);
95 scene.EventManager.OnNewClient += OnNewClient;
96 }
97
98 protected virtual void OnNewClient(IClientAPI client)
99 {
100
101 }
102
103 public virtual void Close()
104 {
105 if (!m_Enabled)
106 return;
107 }
108
109
110 public virtual void RemoveRegion(Scene scene)
111 {
112 if (!m_Enabled)
113 return;
114 m_Scene = null;
115 }
116
117 public virtual void RegionLoaded(Scene scene)
118 {
119 if (!m_Enabled)
120 return;
121
122 }
123
124 #endregion
125
126 #region Inventory Access
127
128 /// <summary>
129 /// Capability originating call to update the asset of an item in an agent's inventory
130 /// </summary>
131 /// <param name="remoteClient"></param>
132 /// <param name="itemID"></param>
133 /// <param name="data"></param>
134 /// <returns></returns>
135 public virtual UUID CapsUpdateInventoryItemAsset(IClientAPI remoteClient, UUID itemID, byte[] data)
136 {
137 InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId);
138 item = m_Scene.InventoryService.GetItem(item);
139
140 if (item != null)
141 {
142 if ((InventoryType)item.InvType == InventoryType.Notecard)
143 {
144 if (!m_Scene.Permissions.CanEditNotecard(itemID, UUID.Zero, remoteClient.AgentId))
145 {
146 remoteClient.SendAgentAlertMessage("Insufficient permissions to edit notecard", false);
147 return UUID.Zero;
148 }
149
150 remoteClient.SendAgentAlertMessage("Notecard saved", false);
151 }
152 else if ((InventoryType)item.InvType == InventoryType.LSL)
153 {
154 if (!m_Scene.Permissions.CanEditScript(itemID, UUID.Zero, remoteClient.AgentId))
155 {
156 remoteClient.SendAgentAlertMessage("Insufficient permissions to edit script", false);
157 return UUID.Zero;
158 }
159
160 remoteClient.SendAgentAlertMessage("Script saved", false);
161 }
162
163 AssetBase asset =
164 CreateAsset(item.Name, item.Description, (sbyte)item.AssetType, data, remoteClient.AgentId.ToString());
165 item.AssetID = asset.FullID;
166 m_Scene.AssetService.Store(asset);
167
168 m_Scene.InventoryService.UpdateItem(item);
169
170 // remoteClient.SendInventoryItemCreateUpdate(item);
171 return (asset.FullID);
172 }
173 else
174 {
175 m_log.ErrorFormat(
176 "[AGENT INVENTORY]: Could not find item {0} for caps inventory update",
177 itemID);
178 }
179
180 return UUID.Zero;
181 }
182
183 /// <summary>
184 /// Delete a scene object from a scene and place in the given avatar's inventory.
185 /// Returns the UUID of the newly created asset.
186 /// </summary>
187 /// <param name="action"></param>
188 /// <param name="folderID"></param>
189 /// <param name="objectGroup"></param>
190 /// <param name="remoteClient"> </param>
191 public virtual UUID DeleteToInventory(DeRezAction action, UUID folderID,
192 SceneObjectGroup objectGroup, IClientAPI remoteClient)
193 {
194 UUID assetID = UUID.Zero;
195
196 Vector3 inventoryStoredPosition = new Vector3
197 (((objectGroup.AbsolutePosition.X > (int)Constants.RegionSize)
198 ? 250
199 : objectGroup.AbsolutePosition.X)
200 ,
201 (objectGroup.AbsolutePosition.X > (int)Constants.RegionSize)
202 ? 250
203 : objectGroup.AbsolutePosition.X,
204 objectGroup.AbsolutePosition.Z);
205
206 Vector3 originalPosition = objectGroup.AbsolutePosition;
207
208 objectGroup.AbsolutePosition = inventoryStoredPosition;
209
210 string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(objectGroup);
211
212 objectGroup.AbsolutePosition = originalPosition;
213
214 // Get the user info of the item destination
215 //
216 UUID userID = UUID.Zero;
217
218 if (action == DeRezAction.Take || action == DeRezAction.TakeCopy ||
219 action == DeRezAction.SaveToExistingUserInventoryItem)
220 {
221 // Take or take copy require a taker
222 // Saving changes requires a local user
223 //
224 if (remoteClient == null)
225 return UUID.Zero;
226
227 userID = remoteClient.AgentId;
228 }
229 else
230 {
231 // All returns / deletes go to the object owner
232 //
233
234 userID = objectGroup.RootPart.OwnerID;
235 }
236
237 if (userID == UUID.Zero) // Can't proceed
238 {
239 return UUID.Zero;
240 }
241
242 // If we're returning someone's item, it goes back to the
243 // owner's Lost And Found folder.
244 // Delete is treated like return in this case
245 // Deleting your own items makes them go to trash
246 //
247
248 InventoryFolderBase folder = null;
249 InventoryItemBase item = null;
250
251 if (DeRezAction.SaveToExistingUserInventoryItem == action)
252 {
253 item = new InventoryItemBase(objectGroup.RootPart.FromUserInventoryItemID, userID);
254 item = m_Scene.InventoryService.GetItem(item);
255
256 //item = userInfo.RootFolder.FindItem(
257 // objectGroup.RootPart.FromUserInventoryItemID);
258
259 if (null == item)
260 {
261 m_log.DebugFormat(
262 "[AGENT INVENTORY]: Object {0} {1} scheduled for save to inventory has already been deleted.",
263 objectGroup.Name, objectGroup.UUID);
264 return UUID.Zero;
265 }
266 }
267 else
268 {
269 // Folder magic
270 //
271 if (action == DeRezAction.Delete)
272 {
273 // Deleting someone else's item
274 //
275
276
277 if (remoteClient == null ||
278 objectGroup.OwnerID != remoteClient.AgentId)
279 {
280 // Folder skeleton may not be loaded and we
281 // have to wait for the inventory to find
282 // the destination folder
283 //
284 folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder);
285 }
286 else
287 {
288 // Assume inventory skeleton was loaded during login
289 // and all folders can be found
290 //
291 folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.TrashFolder);
292 }
293 }
294 else if (action == DeRezAction.Return)
295 {
296
297 // Dump to lost + found unconditionally
298 //
299 folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder);
300 }
301
302 if (folderID == UUID.Zero && folder == null)
303 {
304 if (action == DeRezAction.Delete)
305 {
306 // Deletes go to trash by default
307 //
308 folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.TrashFolder);
309 }
310 else
311 {
312 // Catch all. Use lost & found
313 //
314
315 folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder);
316 }
317 }
318
319 if (folder == null) // None of the above
320 {
321 //folder = userInfo.RootFolder.FindFolder(folderID);
322 folder = new InventoryFolderBase(folderID);
323
324 if (folder == null) // Nowhere to put it
325 {
326 return UUID.Zero;
327 }
328 }
329
330 item = new InventoryItemBase();
331 item.CreatorId = objectGroup.RootPart.CreatorID.ToString();
332 item.ID = UUID.Random();
333 item.InvType = (int)InventoryType.Object;
334 item.Folder = folder.ID;
335 item.Owner = userID;
336 }
337
338 AssetBase asset = CreateAsset(
339 objectGroup.GetPartName(objectGroup.RootPart.LocalId),
340 objectGroup.GetPartDescription(objectGroup.RootPart.LocalId),
341 (sbyte)AssetType.Object,
342 Utils.StringToBytes(sceneObjectXml),
343 objectGroup.OwnerID.ToString());
344 m_Scene.AssetService.Store(asset);
345 assetID = asset.FullID;
346
347 if (DeRezAction.SaveToExistingUserInventoryItem == action)
348 {
349 item.AssetID = asset.FullID;
350 m_Scene.InventoryService.UpdateItem(item);
351 }
352 else
353 {
354 item.AssetID = asset.FullID;
355
356 if (remoteClient != null && (remoteClient.AgentId != objectGroup.RootPart.OwnerID) && m_Scene.Permissions.PropagatePermissions())
357 {
358 uint perms = objectGroup.GetEffectivePermissions();
359 uint nextPerms = (perms & 7) << 13;
360 if ((nextPerms & (uint)PermissionMask.Copy) == 0)
361 perms &= ~(uint)PermissionMask.Copy;
362 if ((nextPerms & (uint)PermissionMask.Transfer) == 0)
363 perms &= ~(uint)PermissionMask.Transfer;
364 if ((nextPerms & (uint)PermissionMask.Modify) == 0)
365 perms &= ~(uint)PermissionMask.Modify;
366
367 item.BasePermissions = perms & objectGroup.RootPart.NextOwnerMask;
368 item.CurrentPermissions = item.BasePermissions;
369 item.NextPermissions = objectGroup.RootPart.NextOwnerMask;
370 item.EveryOnePermissions = objectGroup.RootPart.EveryoneMask & objectGroup.RootPart.NextOwnerMask;
371 item.GroupPermissions = objectGroup.RootPart.GroupMask & objectGroup.RootPart.NextOwnerMask;
372 item.CurrentPermissions |= 8; // Slam!
373 }
374 else
375 {
376 item.BasePermissions = objectGroup.GetEffectivePermissions();
377 item.CurrentPermissions = objectGroup.GetEffectivePermissions();
378 item.NextPermissions = objectGroup.RootPart.NextOwnerMask;
379 item.EveryOnePermissions = objectGroup.RootPart.EveryoneMask;
380 item.GroupPermissions = objectGroup.RootPart.GroupMask;
381
382 item.CurrentPermissions |= 8; // Slam!
383 }
384
385 // TODO: add the new fields (Flags, Sale info, etc)
386 item.CreationDate = Util.UnixTimeSinceEpoch();
387 item.Description = asset.Description;
388 item.Name = asset.Name;
389 item.AssetType = asset.Type;
390
391 m_Scene.InventoryService.AddItem(item);
392
393 if (remoteClient != null && item.Owner == remoteClient.AgentId)
394 {
395 remoteClient.SendInventoryItemCreateUpdate(item, 0);
396 }
397 else
398 {
399 ScenePresence notifyUser = m_Scene.GetScenePresence(item.Owner);
400 if (notifyUser != null)
401 {
402 notifyUser.ControllingClient.SendInventoryItemCreateUpdate(item, 0);
403 }
404 }
405 }
406
407 return assetID;
408 }
409
410
411 /// <summary>
412 /// Rez an object into the scene from the user's inventory
413 /// </summary>
414 /// <param name="remoteClient"></param>
415 /// <param name="itemID"></param>
416 /// <param name="RayEnd"></param>
417 /// <param name="RayStart"></param>
418 /// <param name="RayTargetID"></param>
419 /// <param name="BypassRayCast"></param>
420 /// <param name="RayEndIsIntersection"></param>
421 /// <param name="RezSelected"></param>
422 /// <param name="RemoveItem"></param>
423 /// <param name="fromTaskID"></param>
424 /// <param name="attachment"></param>
425 /// <returns>The SceneObjectGroup rezzed or null if rez was unsuccessful.</returns>
426 public virtual SceneObjectGroup RezObject(IClientAPI remoteClient, UUID itemID, Vector3 RayEnd, Vector3 RayStart,
427 UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection,
428 bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment)
429 {
430 // Work out position details
431 byte bRayEndIsIntersection = (byte)0;
432
433 if (RayEndIsIntersection)
434 {
435 bRayEndIsIntersection = (byte)1;
436 }
437 else
438 {
439 bRayEndIsIntersection = (byte)0;
440 }
441
442 Vector3 scale = new Vector3(0.5f, 0.5f, 0.5f);
443
444
445 Vector3 pos = m_Scene.GetNewRezLocation(
446 RayStart, RayEnd, RayTargetID, Quaternion.Identity,
447 BypassRayCast, bRayEndIsIntersection, true, scale, false);
448
449 // Rez object
450 InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId);
451 item = m_Scene.InventoryService.GetItem(item);
452
453 if (item != null)
454 {
455 AssetBase rezAsset = m_Scene.AssetService.Get(item.AssetID.ToString());
456
457 if (rezAsset != null)
458 {
459 UUID itemId = UUID.Zero;
460
461 // If we have permission to copy then link the rezzed object back to the user inventory
462 // item that it came from. This allows us to enable 'save object to inventory'
463 if (!m_Scene.Permissions.BypassPermissions())
464 {
465 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == (uint)PermissionMask.Copy)
466 {
467 itemId = item.ID;
468 }
469 }
470 else
471 {
472 // Brave new fullperm world
473 //
474 itemId = item.ID;
475 }
476
477 string xmlData = Utils.BytesToString(rezAsset.Data);
478 SceneObjectGroup group
479 = SceneObjectSerializer.FromOriginalXmlFormat(itemId, xmlData);
480
481 if (!m_Scene.Permissions.CanRezObject(
482 group.Children.Count, remoteClient.AgentId, pos)
483 && !attachment)
484 {
485 // The client operates in no fail mode. It will
486 // have already removed the item from the folder
487 // if it's no copy.
488 // Put it back if it's not an attachment
489 //
490 if (((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) && (!attachment))
491 remoteClient.SendBulkUpdateInventory(item);
492 return null;
493 }
494
495 group.ResetIDs();
496
497 if (attachment)
498 {
499 group.RootPart.ObjectFlags |= (uint)PrimFlags.Phantom;
500 group.RootPart.IsAttachment = true;
501 }
502
503 m_Scene.AddNewSceneObject(group, true);
504
505 // m_log.InfoFormat("ray end point for inventory rezz is {0} {1} {2} ", RayEnd.X, RayEnd.Y, RayEnd.Z);
506 // if attachment we set it's asset id so object updates can reflect that
507 // if not, we set it's position in world.
508 if (!attachment)
509 {
510 float offsetHeight = 0;
511 pos = m_Scene.GetNewRezLocation(
512 RayStart, RayEnd, RayTargetID, Quaternion.Identity,
513 BypassRayCast, bRayEndIsIntersection, true, group.GetAxisAlignedBoundingBox(out offsetHeight), false);
514 pos.Z += offsetHeight;
515 group.AbsolutePosition = pos;
516 // m_log.InfoFormat("rezx point for inventory rezz is {0} {1} {2} and offsetheight was {3}", pos.X, pos.Y, pos.Z, offsetHeight);
517
518 }
519 else
520 {
521 group.SetFromItemID(itemID);
522 }
523
524 SceneObjectPart rootPart = null;
525 try
526 {
527 rootPart = group.GetChildPart(group.UUID);
528 }
529 catch (NullReferenceException)
530 {
531 string isAttachment = "";
532
533 if (attachment)
534 isAttachment = " Object was an attachment";
535
536 m_log.Error("[AGENT INVENTORY]: Error rezzing ItemID: " + itemID + " object has no rootpart." + isAttachment);
537 }
538
539 // Since renaming the item in the inventory does not affect the name stored
540 // in the serialization, transfer the correct name from the inventory to the
541 // object itself before we rez.
542 rootPart.Name = item.Name;
543 rootPart.Description = item.Description;
544
545 List<SceneObjectPart> partList = new List<SceneObjectPart>(group.Children.Values);
546
547 group.SetGroup(remoteClient.ActiveGroupId, remoteClient);
548 if (rootPart.OwnerID != item.Owner)
549 {
550 //Need to kill the for sale here
551 rootPart.ObjectSaleType = 0;
552 rootPart.SalePrice = 10;
553
554 if (m_Scene.Permissions.PropagatePermissions())
555 {
556 if ((item.CurrentPermissions & 8) != 0)
557 {
558 foreach (SceneObjectPart part in partList)
559 {
560 part.EveryoneMask = item.EveryOnePermissions;
561 part.NextOwnerMask = item.NextPermissions;
562 part.GroupMask = 0; // DO NOT propagate here
563 }
564 }
565 group.ApplyNextOwnerPermissions();
566 }
567 }
568
569 foreach (SceneObjectPart part in partList)
570 {
571 if (part.OwnerID != item.Owner)
572 {
573 part.LastOwnerID = part.OwnerID;
574 part.OwnerID = item.Owner;
575 part.Inventory.ChangeInventoryOwner(item.Owner);
576 }
577 else if (((item.CurrentPermissions & 8) != 0) && (!attachment)) // Slam!
578 {
579 part.EveryoneMask = item.EveryOnePermissions;
580 part.NextOwnerMask = item.NextPermissions;
581
582 part.GroupMask = 0; // DO NOT propagate here
583 }
584 }
585
586 rootPart.TrimPermissions();
587
588 if (!attachment)
589 {
590 if (group.RootPart.Shape.PCode == (byte)PCode.Prim)
591 {
592 group.ClearPartAttachmentData();
593 }
594 }
595
596 if (!attachment)
597 {
598 // Fire on_rez
599 group.CreateScriptInstances(0, true, m_Scene.DefaultScriptEngine, 0);
600
601 rootPart.ScheduleFullUpdate();
602 }
603
604 if (!m_Scene.Permissions.BypassPermissions())
605 {
606 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
607 {
608 // If this is done on attachments, no
609 // copy ones will be lost, so avoid it
610 //
611 if (!attachment)
612 {
613 List<UUID> uuids = new List<UUID>();
614 uuids.Add(item.ID);
615 m_Scene.InventoryService.DeleteItems(item.Owner, uuids);
616 }
617 }
618 }
619
620 return rootPart.ParentGroup;
621 }
622 }
623
624 return null;
625 }
626
627 public virtual void TransferInventoryAssets(InventoryItemBase item, UUID sender, UUID receiver)
628 {
629 }
630
631 #endregion
632
633 #region Misc
634
635 /// <summary>
636 /// Create a new asset data structure.
637 /// </summary>
638 /// <param name="name"></param>
639 /// <param name="description"></param>
640 /// <param name="invType"></param>
641 /// <param name="assetType"></param>
642 /// <param name="data"></param>
643 /// <returns></returns>
644 private AssetBase CreateAsset(string name, string description, sbyte assetType, byte[] data, string creatorID)
645 {
646 AssetBase asset = new AssetBase(UUID.Random(), name, assetType, creatorID);
647 asset.Description = description;
648 asset.Data = (data == null) ? new byte[1] : data;
649
650 return asset;
651 }
652
653 #endregion
654 }
655}
diff --git a/OpenSim/Region/CoreModules/Framework/Library/LibraryModule.cs b/OpenSim/Region/CoreModules/Framework/Library/LibraryModule.cs
index 13f58bd..e37da9f 100644
--- a/OpenSim/Region/CoreModules/Framework/Library/LibraryModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/Library/LibraryModule.cs
@@ -31,12 +31,13 @@ using System.Reflection;
31 31
32using OpenSim.Framework; 32using OpenSim.Framework;
33using OpenSim.Framework.Communications; 33using OpenSim.Framework.Communications;
34using OpenSim.Framework.Communications.Cache; 34
35using OpenSim.Region.CoreModules.Avatar.Inventory.Archiver; 35using OpenSim.Region.CoreModules.Avatar.Inventory.Archiver;
36using OpenSim.Region.Framework; 36using OpenSim.Region.Framework;
37using OpenSim.Region.Framework.Interfaces; 37using OpenSim.Region.Framework.Interfaces;
38using OpenSim.Region.Framework.Scenes; 38using OpenSim.Region.Framework.Scenes;
39using OpenSim.Services.Interfaces; 39using OpenSim.Services.Interfaces;
40using OpenSim.Server.Base;
40 41
41using OpenMetaverse; 42using OpenMetaverse;
42using log4net; 43using log4net;
@@ -53,6 +54,8 @@ namespace OpenSim.Region.CoreModules.Framework.Library
53 private string m_LibraryName = "OpenSim Library"; 54 private string m_LibraryName = "OpenSim Library";
54 private Scene m_Scene; 55 private Scene m_Scene;
55 56
57 private ILibraryService m_Library;
58
56 #region ISharedRegionModule 59 #region ISharedRegionModule
57 60
58 public void Initialise(IConfigSource config) 61 public void Initialise(IConfigSource config)
@@ -60,9 +63,22 @@ namespace OpenSim.Region.CoreModules.Framework.Library
60 m_Enabled = config.Configs["Modules"].GetBoolean("LibraryModule", m_Enabled); 63 m_Enabled = config.Configs["Modules"].GetBoolean("LibraryModule", m_Enabled);
61 if (m_Enabled) 64 if (m_Enabled)
62 { 65 {
63 IConfig libConfig = config.Configs["LibraryModule"]; 66 IConfig libConfig = config.Configs["LibraryService"];
64 if (libConfig != null) 67 if (libConfig != null)
65 m_LibraryName = libConfig.GetString("LibraryName", m_LibraryName); 68 {
69 string dllName = libConfig.GetString("LocalServiceModule", string.Empty);
70 m_log.Debug("[LIBRARY MODULE]: Library service dll is " + dllName);
71 if (dllName != string.Empty)
72 {
73 Object[] args = new Object[] { config };
74 m_Library = ServerUtils.LoadPlugin<ILibraryService>(dllName, args);
75 }
76 }
77 }
78 if (m_Library == null)
79 {
80 m_log.Warn("[LIBRARY MODULE]: No local library service. Module will be disabled.");
81 m_Enabled = false;
66 } 82 }
67 } 83 }
68 84
@@ -91,10 +107,15 @@ namespace OpenSim.Region.CoreModules.Framework.Library
91 { 107 {
92 m_Scene = scene; 108 m_Scene = scene;
93 } 109 }
110 scene.RegisterModuleInterface<ILibraryService>(m_Library);
94 } 111 }
95 112
96 public void RemoveRegion(Scene scene) 113 public void RemoveRegion(Scene scene)
97 { 114 {
115 if (!m_Enabled)
116 return;
117
118 scene.UnregisterModuleInterface<ILibraryService>(m_Library);
98 } 119 }
99 120
100 public void RegionLoaded(Scene scene) 121 public void RegionLoaded(Scene scene)
@@ -127,27 +148,23 @@ namespace OpenSim.Region.CoreModules.Framework.Library
127 148
128 protected void LoadLibrariesFromArchives() 149 protected void LoadLibrariesFromArchives()
129 { 150 {
130 InventoryFolderImpl lib = m_Scene.CommsManager.UserProfileCacheService.LibraryRoot; 151 InventoryFolderImpl lib = m_Library.LibraryRootFolder;
131 if (lib == null) 152 if (lib == null)
132 { 153 {
133 m_log.Debug("[LIBRARY MODULE]: No library. Ignoring Library Module"); 154 m_log.Debug("[LIBRARY MODULE]: No library. Ignoring Library Module");
134 return; 155 return;
135 } 156 }
136 157
137 lib.Name = m_LibraryName;
138
139 RegionInfo regInfo = new RegionInfo(); 158 RegionInfo regInfo = new RegionInfo();
140 Scene m_MockScene = new Scene(regInfo); 159 Scene m_MockScene = new Scene(regInfo);
141 m_MockScene.CommsManager = m_Scene.CommsManager; 160 LocalInventoryService invService = new LocalInventoryService(lib);
142 LocalInventoryService invService = new LocalInventoryService((LibraryRootFolder)lib);
143 m_MockScene.RegisterModuleInterface<IInventoryService>(invService); 161 m_MockScene.RegisterModuleInterface<IInventoryService>(invService);
144 m_MockScene.RegisterModuleInterface<IAssetService>(m_Scene.AssetService); 162 m_MockScene.RegisterModuleInterface<IAssetService>(m_Scene.AssetService);
145 163
146 UserProfileData profile = new UserProfileData(); 164 UserAccount uinfo = new UserAccount(lib.Owner);
147 profile.FirstName = "OpenSim"; 165 uinfo.FirstName = "OpenSim";
148 profile.ID = lib.Owner; 166 uinfo.LastName = "Library";
149 profile.SurName = "Library"; 167 uinfo.ServiceURLs = new Dictionary<string, object>();
150 CachedUserInfo uinfo = new CachedUserInfo(invService, profile);
151 168
152 foreach (string iarFileName in Directory.GetFiles(pathToLibraries, "*.iar")) 169 foreach (string iarFileName in Directory.GetFiles(pathToLibraries, "*.iar"))
153 { 170 {
@@ -175,6 +192,15 @@ namespace OpenSim.Region.CoreModules.Framework.Library
175 m_log.DebugFormat("[LIBRARY MODULE]: Exception when processing archive {0}: {1}", iarFileName, e.Message); 192 m_log.DebugFormat("[LIBRARY MODULE]: Exception when processing archive {0}: {1}", iarFileName, e.Message);
176 } 193 }
177 } 194 }
195
196 }
197
198 private void DumpLibrary()
199 {
200 InventoryFolderImpl lib = m_Library.LibraryRootFolder;
201
202 m_log.DebugFormat(" - folder {0}", lib.Name);
203 DumpFolder(lib);
178 } 204 }
179// 205//
180// private void DumpLibrary() 206// private void DumpLibrary()
diff --git a/OpenSim/Region/CoreModules/Framework/Library/LocalInventoryService.cs b/OpenSim/Region/CoreModules/Framework/Library/LocalInventoryService.cs
index 2c95b5a..49589fd 100644
--- a/OpenSim/Region/CoreModules/Framework/Library/LocalInventoryService.cs
+++ b/OpenSim/Region/CoreModules/Framework/Library/LocalInventoryService.cs
@@ -29,7 +29,7 @@ using System.Collections.Generic;
29using System.Reflection; 29using System.Reflection;
30 30
31using OpenSim.Framework; 31using OpenSim.Framework;
32using OpenSim.Framework.Communications.Cache; 32
33using OpenSim.Services.Interfaces; 33using OpenSim.Services.Interfaces;
34 34
35using OpenMetaverse; 35using OpenMetaverse;
@@ -41,9 +41,9 @@ namespace OpenSim.Region.CoreModules.Framework.Library
41 { 41 {
42 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 42 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
43 43
44 private LibraryRootFolder m_Library; 44 private InventoryFolderImpl m_Library;
45 45
46 public LocalInventoryService(LibraryRootFolder lib) 46 public LocalInventoryService(InventoryFolderImpl lib)
47 { 47 {
48 m_Library = lib; 48 m_Library = lib;
49 } 49 }