diff --git a/LibreMetaverse/GridManager.cs b/LibreMetaverse/GridManager.cs index 39a5b236..ce78d3b8 100644 --- a/LibreMetaverse/GridManager.cs +++ b/LibreMetaverse/GridManager.cs @@ -378,8 +378,10 @@ namespace OpenMetaverse internal Dictionary Regions = new Dictionary(); /// A dictionary of all the regions, indexed by region handle internal Dictionary RegionsByHandle = new Dictionary(); + /// A dictionary of regions by region handle + internal Dictionary RegionsByUUID = new Dictionary(); - private readonly GridClient Client; + private readonly GridClient Client; /// /// Constructor @@ -431,7 +433,7 @@ namespace OpenMetaverse }, NameData = { - Name = Utils.StringToBytes(regionName) + Name = Utils.StringToBytes(regionName.ToLowerInvariant()) } }; @@ -546,6 +548,23 @@ namespace OpenMetaverse /// UUID of the region to look up public void RequestRegionHandle(UUID regionID) { + ulong handle = 0; + bool found = false; + lock (RegionsByUUID) + { + found = RegionsByUUID.TryGetValue(regionID, out handle); + } + + if (found) + { + if (m_RegionHandleReply != null) + { + OnRegionHandleReply(new RegionHandleReplyEventArgs(regionID, handle)); + } + + return; + } + RegionHandleRequestPacket request = new RegionHandleRequestPacket { RequestBlock = new RegionHandleRequestPacket.RequestBlockBlock @@ -556,6 +575,62 @@ namespace OpenMetaverse Client.Network.SendPacket(request); } + /// + /// Retrieves information using the region name + /// + /// This function will block until it can find the region or gives up + /// Region Handle of requested + /// for the + /// being requested + /// Output for the fetched , + /// or empty struct if failure + /// True if the was fetched, otherwise false + public bool GetGridRegion(ulong handle, GridLayerType layer, out GridRegion region) + { + // Check if cached + if (RegionsByHandle.TryGetValue(handle, out region)) + { + return true; + } + + uint globalX, + globalY; + + Utils.LongToUInts(handle, out globalX, out globalY); + const uint regionWidthUnits = 256; + ushort gridX = (ushort)(globalX / regionWidthUnits); + ushort gridY = (ushort)(globalY / regionWidthUnits); + + // Ask the server for the name of the region anchored at the specified grid position. + AutoResetEvent regionEvent = new AutoResetEvent(false); + + GridRegion foundRegion = default(GridRegion); + bool found = false; + + void RegionCallback(object? sender, GridRegionEventArgs e) + { // See note in HandleCallback, above. + if (e.Region.RegionHandle == handle) + { + found = true; + foundRegion = e.Region; + regionEvent.Set(); + } + } + + GridRegion += RegionCallback; + RequestMapBlocks(layer, gridX, gridY, gridX, gridY, true); + regionEvent.WaitOne(Client.Settings.MAP_REQUEST_TIMEOUT, false); + GridRegion -= RegionCallback; + region = foundRegion; + + if (!found) + { + Logger.Log($"Could not find region at region handle {handle}", Helpers.LogLevel.Warning, Client); + } + + return found; + } + /// /// Retrieves information using the region name /// @@ -575,10 +650,10 @@ namespace OpenMetaverse return false; } - if (Regions.ContainsKey(name)) + if (Regions.ContainsKey(name.ToLowerInvariant())) { // We already have this GridRegion structure - region = Regions[name]; + region = Regions[name.ToLowerInvariant()]; return true; } @@ -586,7 +661,7 @@ namespace OpenMetaverse void Callback(object sender, GridRegionEventArgs e) { - if (e.Region.Name == name) + if (e.Region.Name.ToLowerInvariant() == name.ToLowerInvariant()) { regionEvent.Set(); } @@ -599,10 +674,10 @@ namespace OpenMetaverse GridRegion -= Callback; - if (Regions.ContainsKey(name)) + if (Regions.ContainsKey(name.ToLowerInvariant())) { // The region was found after our request - region = Regions[name]; + region = Regions[name.ToLowerInvariant()]; return true; } else @@ -675,7 +750,7 @@ namespace OpenMetaverse lock (Regions) { - Regions[region.Name] = region; + Regions[region.Name.ToLowerInvariant()] = region; RegionsByHandle[region.RegionHandle] = region; } @@ -861,10 +936,16 @@ namespace OpenMetaverse /// The sender /// The EventArgs object containing the packet data protected void RegionHandleReplyHandler(object sender, PacketReceivedEventArgs e) - { + { + RegionIDAndHandleReplyPacket reply = (RegionIDAndHandleReplyPacket)e.Packet; + + lock (RegionsByUUID) + { + RegionsByUUID[reply.ReplyBlock.RegionID] = reply.ReplyBlock.RegionHandle; + } + if (m_RegionHandleReply != null) { - RegionIDAndHandleReplyPacket reply = (RegionIDAndHandleReplyPacket)e.Packet; OnRegionHandleReply(new RegionHandleReplyEventArgs(reply.ReplyBlock.RegionID, reply.ReplyBlock.RegionHandle)); } }