From d9cc908471922a1239bb8a757e07084072852982 Mon Sep 17 00:00:00 2001
From: Charles Krinke
Date: Sat, 16 Aug 2008 19:20:14 +0000
Subject: Mantis#1965. Thank you kindly, HomerHorwitz for a patch that: Places
touched: - Added two events for in-packets to LLCLientView:
RegionHandleRequest and ParcelInfoRequest - Added sending of two
out-packets to LLCLientView: RegionIDAndHandleReply and ParcelInfoReply. -
Scene handles the RegionHandleRequest, LandManagementModule the
ParcelInfoRequest - Added inter-region request for LandData by RegionHandle
and local position. This was implemented as XML-RPC request. The returned
LandData isn't complete, it only contains the data necessary for answering
the ParcelInfoRequest - Added new CAPS (0009) for RemoteParcelRequest and
some methods for LandData handling to LandManagementModule - Added methods
for fake parcelID creation and parsing to Util - Fixed missing implementation
of interface methods. - Added new file:
OpenSim/Framework/Communications/Capabilities/LLSDRemoteParcelResponse.cs
NOTE: This is part of the patch, too. Due to the many places touched, I would
consider this patch as experimental.
---
.../Modules/World/Land/LandManagementModule.cs | 120 ++++++++++++++++++++-
.../Environment/Modules/World/NPC/NPCAvatar.cs | 12 +++
OpenSim/Region/Environment/Scenes/Scene.cs | 18 ++++
.../Scenes/SceneCommunicationService.cs | 16 ++-
4 files changed, 164 insertions(+), 2 deletions(-)
(limited to 'OpenSim/Region/Environment')
diff --git a/OpenSim/Region/Environment/Modules/World/Land/LandManagementModule.cs b/OpenSim/Region/Environment/Modules/World/Land/LandManagementModule.cs
index 92eda80..46f108e 100644
--- a/OpenSim/Region/Environment/Modules/World/Land/LandManagementModule.cs
+++ b/OpenSim/Region/Environment/Modules/World/Land/LandManagementModule.cs
@@ -26,19 +26,30 @@
*/
using System;
+using System.Collections;
using System.Collections.Generic;
+using System.Reflection;
using libsecondlife;
+using log4net;
using Nini.Config;
using OpenSim.Region.Environment.Interfaces;
using OpenSim.Region.Environment.Scenes;
using OpenSim.Framework;
+using OpenSim.Framework.Servers;
+using OpenSim.Framework.Communications.Capabilities;
using OpenSim.Region.Physics.Manager;
using Axiom.Math;
+using Caps = OpenSim.Framework.Communications.Capabilities.Caps;
namespace OpenSim.Region.Environment.Modules.World.Land
{
public class LandManagementModule : IRegionModule
{
+ private static readonly ILog m_log =
+ LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+
+ private static readonly string remoteParcelRequestPath = "0009/";
+
private LandChannel landChannel;
private Scene m_scene;
@@ -75,6 +86,7 @@ namespace OpenSim.Region.Environment.Modules.World.Land
m_scene.EventManager.OnSetAllowForcefulBan += this.SetAllowedForcefulBans;
m_scene.EventManager.OnRequestParcelPrimCountUpdate += this.PerformParcelPrimCountUpdate;
m_scene.EventManager.OnParcelPrimCountTainted += this.SetPrimsTainted;
+ m_scene.EventManager.OnRegisterCaps += this.OnRegisterCaps;
lock (m_scene)
{
@@ -95,7 +107,7 @@ namespace OpenSim.Region.Environment.Modules.World.Land
client.OnParcelAccessListUpdateRequest += new ParcelAccessListUpdateRequest(handleParcelAccessUpdateRequest);
client.OnParcelAbandonRequest += new ParcelAbandonRequest(handleParcelAbandonRequest);
client.OnParcelReclaim += new ParcelReclaim(handleParcelReclaim);
-
+ client.OnParcelInfoRequest += new ParcelInfoRequest(handleParcelInfo);
if (m_scene.Entities.ContainsKey(client.AgentId))
{
SendLandUpdate((ScenePresence)m_scene.Entities[client.AgentId], true);
@@ -1084,6 +1096,112 @@ namespace OpenSim.Region.Environment.Modules.World.Land
public void setSimulatorObjectMaxOverride(overrideSimulatorMaxPrimCountDelegate overrideDel)
{
}
+
+ #region CAPS handler
+ private void OnRegisterCaps(LLUUID agentID, Caps caps)
+ {
+ string capsBase = "/CAPS/" + caps.CapsObjectPath;
+ caps.RegisterHandler("RemoteParcelRequest",
+ new RestStreamHandler("POST", capsBase + remoteParcelRequestPath,
+ delegate(string request, string path, string param,
+ OSHttpRequest httpRequest, OSHttpResponse httpResponse)
+ {
+ return RemoteParcelRequest(request, path, param, agentID, caps);
+ }));
+ }
+
+ // we cheat here: As we don't have (and want) a grid-global parcel-store, we can't return the
+ // "real" parcelID, because we wouldn't be able to map that to the region the parcel belongs to.
+ // So, we create a "fake" parcelID by using the regionHandle (64 bit), and the local (integer) x
+ // and y coordinate (each 8 bit), encoded in a LLUUID (128 bit).
+ //
+ // Request format:
+ //
+ //
+ //
+ private string RemoteParcelRequest(string request, string path, string param, LLUUID agentID, Caps caps)
+ {
+ LLUUID parcelID = LLUUID.Zero;
+ try
+ {
+ Hashtable hash = new Hashtable();
+ hash = (Hashtable)LLSD.LLSDDeserialize(Helpers.StringToField(request));
+ if(hash.ContainsKey("region_id") && hash.ContainsKey("location"))
+ {
+ LLUUID regionID = (LLUUID)hash["region_id"];
+ ArrayList list = (ArrayList)hash["location"];
+ uint x = (uint)(double)list[0];
+ uint y = (uint)(double)list[1];
+ if(hash.ContainsKey("region_handle"))
+ {
+ // if you do a "About Landmark" on a landmark a second time, the viewer sends the
+ // region_handle it got earlier via RegionHandleRequest
+ ulong regionHandle = Helpers.BytesToUInt64((byte[])hash["region_handle"]);
+ parcelID = Util.BuildFakeParcelID(regionHandle, x, y);
+ }
+ else if(regionID == m_scene.RegionInfo.RegionID)
+ {
+ // a parcel request for a local parcel => no need to query the grid
+ parcelID = Util.BuildFakeParcelID(m_scene.RegionInfo.RegionHandle, x, y);
+ }
+ else
+ {
+ // a parcel request for a parcel in another region. Ask the grid about the region
+ RegionInfo info = m_scene.CommsManager.GridService.RequestNeighbourInfo(regionID);
+ if(info != null) parcelID = Util.BuildFakeParcelID(info.RegionHandle, x, y);
+ }
+ }
+ }
+ catch (LLSD.LLSDParseException e)
+ {
+ m_log.ErrorFormat("[LAND] Fetch error: {0}", e.Message);
+ m_log.ErrorFormat("[LAND] ... in request {0}", request);
+ }
+ catch(InvalidCastException)
+ {
+ m_log.ErrorFormat("[LAND] Wrong type in request {0}", request);
+ }
+
+ LLSDRemoteParcelResponse response = new LLSDRemoteParcelResponse();
+ response.parcel_id = parcelID;
+ m_log.DebugFormat("[LAND] got parcelID {0}", parcelID);
+
+ return LLSDHelpers.SerialiseLLSDReply(response);
+ }
+
+ #endregion
+
+ private void handleParcelInfo(IClientAPI remoteClient, LLUUID parcelID)
+ {
+ if(parcelID == LLUUID.Zero) return;
+
+ // assume we've got the parcelID we just computed in RemoteParcelRequest
+ ulong regionHandle;
+ uint x, y;
+ Util.ParseFakeParcelID(parcelID, out regionHandle, out x, out y);
+ m_log.DebugFormat("[LAND] got parcelinfo request for regionHandle {0}, x/y {1}/{2}", regionHandle, x, y);
+
+ LandData landData;
+ if(regionHandle == m_scene.RegionInfo.RegionHandle) landData = this.GetLandObject(x, y).landData;
+ else landData = m_scene.CommsManager.GridService.RequestLandData(regionHandle, x, y);
+
+ if(landData != null)
+ {
+ // we need to transfer the fake parcelID, not the one in landData, so the viewer can match it to the landmark.
+ m_log.Debug("[LAND] got parcelinfo; sending");
+ remoteClient.SendParcelInfo(m_scene.RegionInfo, landData, parcelID, x, y);
+ }
+ else m_log.Debug("[LAND] got no parcelinfo; not sending");
+ }
}
}
diff --git a/OpenSim/Region/Environment/Modules/World/NPC/NPCAvatar.cs b/OpenSim/Region/Environment/Modules/World/NPC/NPCAvatar.cs
index 5853b87..7b05027 100644
--- a/OpenSim/Region/Environment/Modules/World/NPC/NPCAvatar.cs
+++ b/OpenSim/Region/Environment/Modules/World/NPC/NPCAvatar.cs
@@ -302,6 +302,10 @@ namespace OpenSim.Region.Environment.Modules.World.NPC
public event UpdateVector OnAutoPilotGo;
public event TerrainUnacked OnUnackedTerrain;
+
+ public event RegionHandleRequest OnRegionHandleRequest;
+ public event ParcelInfoRequest OnParcelInfoRequest;
+
#pragma warning restore 67
#endregion
@@ -832,5 +836,13 @@ namespace OpenSim.Region.Environment.Modules.World.NPC
public void SendClearFollowCamProperties (LLUUID objectID)
{
}
+
+ public void SendRegionHandle (LLUUID regoinID, ulong handle)
+ {
+ }
+
+ public void SendParcelInfo (RegionInfo info, LandData land, LLUUID parcelID, uint x, uint y)
+ {
+ }
}
}
diff --git a/OpenSim/Region/Environment/Scenes/Scene.cs b/OpenSim/Region/Environment/Scenes/Scene.cs
index 2e89e4b..9b0b53a 100644
--- a/OpenSim/Region/Environment/Scenes/Scene.cs
+++ b/OpenSim/Region/Environment/Scenes/Scene.cs
@@ -2170,6 +2170,8 @@ namespace OpenSim.Region.Environment.Scenes
client.OnScriptReset += ProcessScriptReset;
client.OnGetScriptRunning += GetScriptRunning;
client.OnSetScriptRunning += SetScriptRunning;
+
+ client.OnRegionHandleRequest += RegionHandleRequest;
client.OnUnackedTerrain += TerrainUnAcked;
@@ -2502,6 +2504,7 @@ namespace OpenSim.Region.Environment.Scenes
m_sceneGridService.OnRemoveKnownRegionFromAvatar += HandleRemoveKnownRegionsFromAvatar;
m_sceneGridService.OnLogOffUser += HandleLogOffUserFromGrid;
m_sceneGridService.KillObject += SendKillObject;
+ m_sceneGridService.OnGetLandData += GetLandData;
}
///
@@ -2518,6 +2521,7 @@ namespace OpenSim.Region.Environment.Scenes
m_sceneGridService.OnExpectUser -= NewUserConnection;
m_sceneGridService.OnAvatarCrossingIntoRegion -= AgentCrossing;
m_sceneGridService.OnCloseAgentConnection -= CloseConnection;
+ m_sceneGridService.OnGetLandData -= GetLandData;
m_sceneGridService.Close();
}
@@ -3436,6 +3440,12 @@ namespace OpenSim.Region.Environment.Scenes
return LandChannel.GetLandObject(x, y).landData;
}
+ public LandData GetLandData(uint x, uint y)
+ {
+ m_log.DebugFormat("[SCENE] returning land for {0},{1}", x, y);
+ return LandChannel.GetLandObject((int)x, (int)y).landData;
+ }
+
public void SetLandMusicURL(float x, float y, string url)
{
ILandObject land = LandChannel.GetLandObject(x, y);
@@ -3833,6 +3843,14 @@ namespace OpenSim.Region.Environment.Scenes
// client.SendParcelMediaCommand((uint)(4), ParcelMediaCommandEnum.Play, 0);
// });
}
+
+ public void RegionHandleRequest(IClientAPI client, LLUUID regionID)
+ {
+ RegionInfo info;
+ if(regionID == RegionInfo.RegionID) info = RegionInfo;
+ else info = CommsManager.GridService.RequestNeighbourInfo(regionID);
+ if(info != null) client.SendRegionHandle(regionID, info.RegionHandle);
+ }
public void TerrainUnAcked(IClientAPI client, int patchX, int patchY)
diff --git a/OpenSim/Region/Environment/Scenes/SceneCommunicationService.cs b/OpenSim/Region/Environment/Scenes/SceneCommunicationService.cs
index 008d67a..35a7434 100644
--- a/OpenSim/Region/Environment/Scenes/SceneCommunicationService.cs
+++ b/OpenSim/Region/Environment/Scenes/SceneCommunicationService.cs
@@ -59,7 +59,8 @@ namespace OpenSim.Region.Environment.Scenes
public event ChildAgentUpdate OnChildAgentUpdate;
public event RemoveKnownRegionsFromAvatarList OnRemoveKnownRegionFromAvatar;
public event LogOffUser OnLogOffUser;
-
+ public event GetLandData OnGetLandData;
+
private AgentCrossing handlerAvatarCrossingIntoRegion = null; // OnAvatarCrossingIntoRegion;
private ExpectUserDelegate handlerExpectUser = null; // OnExpectUser;
private ExpectPrimDelegate handlerExpectPrim = null; // OnExpectPrim;
@@ -69,6 +70,7 @@ namespace OpenSim.Region.Environment.Scenes
private ChildAgentUpdate handlerChildAgentUpdate = null; // OnChildAgentUpdate;
private RemoveKnownRegionsFromAvatarList handlerRemoveKnownRegionFromAvatar = null; // OnRemoveKnownRegionFromAvatar;
private LogOffUser handlerLogOffUser = null;
+ private GetLandData handlerGetLandData = null; // OnGetLandData
public KillObjectDelegate KillObject;
public string _debugRegionName = String.Empty;
@@ -108,6 +110,7 @@ namespace OpenSim.Region.Environment.Scenes
regionCommsHost.OnRegionUp += newRegionUp;
regionCommsHost.OnChildAgentUpdate += ChildAgentUpdate;
regionCommsHost.OnLogOffUser += GridLogOffUser;
+ regionCommsHost.OnGetLandData += FetchLandData;
}
else
{
@@ -131,6 +134,7 @@ namespace OpenSim.Region.Environment.Scenes
regionCommsHost.OnExpectPrim -= IncomingPrimCrossing;
regionCommsHost.OnAvatarCrossingIntoRegion -= AgentCrossing;
regionCommsHost.OnCloseAgentConnection -= CloseConnection;
+ regionCommsHost.OnGetLandData -= FetchLandData;
m_commsProvider.GridService.DeregisterRegion(m_regionInfo);
regionCommsHost = null;
}
@@ -227,6 +231,16 @@ namespace OpenSim.Region.Environment.Scenes
return false;
}
+ protected LandData FetchLandData(uint x, uint y)
+ {
+ handlerGetLandData = OnGetLandData;
+ if (handlerGetLandData != null)
+ {
+ return handlerGetLandData(x, y);
+ }
+ return null;
+ }
+
#endregion
#region Inform Client of Neighbours
--
cgit v1.1