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: + // + // + // location + // + // 1.23 + // 45..6 + // 78.9 + // + // region_id + // xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + // + // + 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