From 49af6b53e74123ccebdbd411d456cb8bae528d61 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Sun, 26 Jan 2014 19:32:28 -0800 Subject: varregion: enable teleporting to a varregion by clicking on the map and pressing the 'teleport' button. This commit adds returning region map info for all the subregions of a varregion. This also handles the selection of the extra region and then the displacement of the postion so the teleport is to the correct location. --- OpenSim/Framework/MapBlockData.cs | 18 ++ OpenSim/Framework/MapItemReplyStruct.cs | 33 ++++ .../EntityTransfer/EntityTransferModule.cs | 31 ++- .../CoreModules/World/LegacyMap/MapImageModule.cs | 2 +- .../CoreModules/World/WorldMap/WorldMapModule.cs | 217 +++++++++++++-------- .../Server/Handlers/Grid/GridServerPostHandler.cs | 3 +- 6 files changed, 221 insertions(+), 83 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Framework/MapBlockData.cs b/OpenSim/Framework/MapBlockData.cs index 2298ac5..4bee499 100644 --- a/OpenSim/Framework/MapBlockData.cs +++ b/OpenSim/Framework/MapBlockData.cs @@ -27,6 +27,7 @@ using System; using OpenMetaverse; +using OpenMetaverse.StructuredData; namespace OpenSim.Framework { @@ -40,9 +41,26 @@ namespace OpenSim.Framework public byte WaterHeight; public ushort X; public ushort Y; + public ushort SizeX; + public ushort SizeY; public MapBlockData() { } + + public OSDMap ToOSD() + { + OSDMap map = new OSDMap(); + map["X"] = X; + map["Y"] = Y; + map["SizeX"] = SizeX; + map["SizeY"] = SizeY; + map["Name"] = Name; + map["Access"] = Access; + map["RegionFlags"] = RegionFlags; + map["WaterHeight"] = WaterHeight; + map["MapImageID"] = MapImageId; + return map; + } } } diff --git a/OpenSim/Framework/MapItemReplyStruct.cs b/OpenSim/Framework/MapItemReplyStruct.cs index 58011bd..c8693ae 100644 --- a/OpenSim/Framework/MapItemReplyStruct.cs +++ b/OpenSim/Framework/MapItemReplyStruct.cs @@ -26,6 +26,7 @@ */ using OpenMetaverse; +using OpenMetaverse.StructuredData; namespace OpenSim.Framework { @@ -37,5 +38,37 @@ namespace OpenSim.Framework public int Extra; public int Extra2; public string name; + + public mapItemReply(uint pX, uint pY, UUID pId, string pName, int pExt1, int pExt2) + { + x = pX; + y = pY; + id = pId; + name = pName; + Extra = pExt1; + Extra2 = pExt2; + } + + public OSDMap ToOSD() + { + OSDMap map = new OSDMap(); + map["X"] = OSD.FromInteger((int)x); + map["Y"] = OSD.FromInteger((int)y); + map["ID"] = OSD.FromUUID(id); + map["Name"] = OSD.FromString(name); + map["Extra"] = OSD.FromInteger(Extra); + map["Extra2"] = OSD.FromInteger(Extra2); + return map; + } + + public void FromOSD(OSDMap map) + { + x = (uint) map["X"].AsInteger(); + y = (uint) map["Y"].AsInteger(); + id = map["ID"].AsUUID(); + Extra = map["Extra"].AsInteger(); + Extra2 = map["Extra2"].AsInteger(); + name = map["Name"].AsString(); + } } } diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index 85e8159..a038f73 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs @@ -523,9 +523,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer ScenePresence sp, ulong regionHandle, Vector3 position, Vector3 lookAt, uint teleportFlags, out GridRegion finalDestination) { - uint x = 0, y = 0; - Util.RegionHandleToWorldLoc(regionHandle, out x, out y); - GridRegion reg = Scene.GridService.GetRegionByPosition(sp.Scene.RegionInfo.ScopeID, (int)x, (int)y); + // Get destination region taking into account that the address could be an offset + // region inside a varregion. + GridRegion reg = GetTeleportDestinationRegion(sp.Scene.GridService, sp.Scene.RegionInfo.ScopeID, regionHandle, ref position); if (reg != null) { @@ -588,6 +588,31 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer } } + // The teleport address could be an address in a subregion of a larger varregion. + // Find the real base region and adjust the teleport location to account for the + // larger region. + private GridRegion GetTeleportDestinationRegion(IGridService gridService, UUID scope, ulong regionHandle, ref Vector3 position) + { + uint x = 0, y = 0; + Util.RegionHandleToWorldLoc(regionHandle, out x, out y); + + // Compute the world location we're teleporting to + double worldX = (double)x + position.X; + double worldY = (double)y + position.Y; + + // Find the region that contains the position + GridRegion reg = GetRegionContainingWorldLocation(gridService, scope, worldX, worldY); + + if (reg != null) + { + // modify the position for the offset into the actual region returned + position.X += x - reg.RegionLocX; + position.Y += y - reg.RegionLocY; + } + + return reg; + } + // Nothing to validate here protected virtual bool ValidateGenericConditions(ScenePresence sp, GridRegion reg, GridRegion finalDestination, uint teleportFlags, out string reason) { diff --git a/OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs b/OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs index 81d1a4a..1dad8ba 100644 --- a/OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs +++ b/OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs @@ -549,7 +549,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap z_localIDs.Add(part.LocalId); z_sortheights.Add(pos.Z); - for (int wx = mapdrawstartX; wx < mapdrawendX; wx++) + // for (int wx = mapdrawstartX; wx < mapdrawendX; wx++) // { // for (wy = mapdrawstartY; wy < mapdrawendY; wy++) // { diff --git a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs index b472038..f57be83 100644 --- a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs +++ b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs @@ -59,8 +59,8 @@ namespace OpenSim.Region.CoreModules.World.WorldMap [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "WorldMapModule")] public class WorldMapModule : INonSharedRegionModule, IWorldMapModule { - private static readonly ILog m_log = - LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private static string LogHeader = "[WORLD MAP]"; private static readonly string DEFAULT_WORLD_MAP_EXPORT_PATH = "exportmap.jpg"; private static readonly UUID STOP_UUID = UUID.Random(); @@ -290,8 +290,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap (int)Util.RegionToWorldLoc(m_scene.RegionInfo.RegionLocY + 8) ); foreach (GridRegion r in regions) { - MapBlockData block = new MapBlockData(); - MapBlockFromGridRegion(block, r, 0); + MapBlockData block = MapBlockFromGridRegion(r, 0); mapBlocks.Add(block); } avatarPresence.ControllingClient.SendMapBlock(mapBlocks, 0); @@ -412,23 +411,22 @@ namespace OpenSim.Region.CoreModules.World.WorldMap uint xstart = 0; uint ystart = 0; Util.RegionHandleToWorldLoc(m_scene.RegionInfo.RegionHandle, out xstart, out ystart); - if (itemtype == 6) // Service 6 right now (MAP_ITEM_AGENTS_LOCATION; green dots) + if (itemtype == (int)GridItemType.AgentLocations) { if (regionhandle == 0 || regionhandle == m_scene.RegionInfo.RegionHandle) { - // Local Map Item Request + // Just requesting map info about the current, local region int tc = Environment.TickCount; List mapitems = new List(); mapItemReply mapitem = new mapItemReply(); if (m_scene.GetRootAgentCount() <= 1) { - mapitem = new mapItemReply(); - mapitem.x = (uint)(xstart + 1); - mapitem.y = (uint)(ystart + 1); - mapitem.id = UUID.Zero; - mapitem.name = Util.Md5Hash(m_scene.RegionInfo.RegionName + tc.ToString()); - mapitem.Extra = 0; - mapitem.Extra2 = 0; + mapitem = new mapItemReply( + xstart + 1, + ystart + 1, + UUID.Zero, + Util.Md5Hash(m_scene.RegionInfo.RegionName + tc.ToString()), + 0, 0); mapitems.Add(mapitem); } else @@ -438,13 +436,12 @@ namespace OpenSim.Region.CoreModules.World.WorldMap // Don't send a green dot for yourself if (sp.UUID != remoteClient.AgentId) { - mapitem = new mapItemReply(); - mapitem.x = (uint)(xstart + sp.AbsolutePosition.X); - mapitem.y = (uint)(ystart + sp.AbsolutePosition.Y); - mapitem.id = UUID.Zero; - mapitem.name = Util.Md5Hash(m_scene.RegionInfo.RegionName + tc.ToString()); - mapitem.Extra = 1; - mapitem.Extra2 = 0; + mapitem = new mapItemReply( + xstart + (uint)sp.AbsolutePosition.X, + ystart + (uint)sp.AbsolutePosition.Y, + UUID.Zero, + Util.Md5Hash(m_scene.RegionInfo.RegionName + tc.ToString()), + 1, 0); mapitems.Add(mapitem); } }); @@ -459,7 +456,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap RequestMapItems("",remoteClient.AgentId,flags,EstateID,godlike,itemtype,regionhandle); } } - else if (itemtype == 7) // Service 7 (MAP_ITEM_LAND_FOR_SALE) + else if (itemtype == (int)GridItemType.LandForSale) // Service 7 (MAP_ITEM_LAND_FOR_SALE) { if (regionhandle == 0 || regionhandle == m_scene.RegionInfo.RegionHandle) { @@ -489,14 +486,14 @@ namespace OpenSim.Region.CoreModules.World.WorldMap float x = (min.X+max.X)/2; float y = (min.Y+max.Y)/2; - mapitem = new mapItemReply(); - mapitem.x = (uint)(xstart + x); - mapitem.y = (uint)(ystart + y); - // mapitem.z = (uint)m_scene.GetGroundHeight(x,y); - mapitem.id = parcel.GlobalID; - mapitem.name = parcel.Name; - mapitem.Extra = parcel.Area; - mapitem.Extra2 = parcel.SalePrice; + mapitem = new mapItemReply( + xstart + (uint)x, + ystart + (uint)y, + parcel.GlobalID, + parcel.Name, + parcel.Area, + parcel.SalePrice + ); mapitems.Add(mapitem); } } @@ -511,7 +508,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap RequestMapItems("",remoteClient.AgentId,flags,EstateID,godlike,itemtype,regionhandle); } } - else if (itemtype == 1) // Service 1 (MAP_ITEM_TELEHUB) + else if (itemtype == (int)GridItemType.Telehub) // Service 1 (MAP_ITEM_TELEHUB) { if (regionhandle == 0 || regionhandle == m_scene.RegionInfo.RegionHandle) { @@ -521,13 +518,14 @@ namespace OpenSim.Region.CoreModules.World.WorldMap SceneObjectGroup sog = m_scene.GetSceneObjectGroup(m_scene.RegionInfo.RegionSettings.TelehubObject); if (sog != null) { - mapitem = new mapItemReply(); - mapitem.x = (uint)(xstart + sog.AbsolutePosition.X); - mapitem.y = (uint)(ystart + sog.AbsolutePosition.Y); - mapitem.id = UUID.Zero; - mapitem.name = sog.Name; - mapitem.Extra = 0; // color (not used) - mapitem.Extra2 = 0; // 0 = telehub / 1 = infohub + mapitem = new mapItemReply( + xstart + (uint)sog.AbsolutePosition.X, + ystart + (uint)sog.AbsolutePosition.Y, + UUID.Zero, + sog.Name, + 0, // color (not used) + 0 // 0 = telehub / 1 = infohub + ); mapitems.Add(mapitem); remoteClient.SendMapItemReply(mapitems.ToArray(), itemtype, flags); @@ -677,19 +675,14 @@ namespace OpenSim.Region.CoreModules.World.WorldMap { OSDMap mapitem = (OSDMap)itemarray[i]; mapItemReply mi = new mapItemReply(); - mi.x = (uint)mapitem["X"].AsInteger(); - mi.y = (uint)mapitem["Y"].AsInteger(); - mi.id = mapitem["ID"].AsUUID(); - mi.Extra = mapitem["Extra"].AsInteger(); - mi.Extra2 = mapitem["Extra2"].AsInteger(); - mi.name = mapitem["Name"].AsString(); + mi.FromOSD(mapitem); returnitems.Add(mi); } av.ControllingClient.SendMapItemReply(returnitems.ToArray(), mrs.itemtype, mrs.flags); } // Service 7 (MAP_ITEM_LAND_FOR_SALE) - uint itemtype = 7; + uint itemtype = (uint)GridItemType.LandForSale; if (response.ContainsKey(itemtype.ToString())) { @@ -699,19 +692,14 @@ namespace OpenSim.Region.CoreModules.World.WorldMap { OSDMap mapitem = (OSDMap)itemarray[i]; mapItemReply mi = new mapItemReply(); - mi.x = (uint)mapitem["X"].AsInteger(); - mi.y = (uint)mapitem["Y"].AsInteger(); - mi.id = mapitem["ID"].AsUUID(); - mi.Extra = mapitem["Extra"].AsInteger(); - mi.Extra2 = mapitem["Extra2"].AsInteger(); - mi.name = mapitem["Name"].AsString(); + mi.FromOSD(mapitem); returnitems.Add(mi); } av.ControllingClient.SendMapItemReply(returnitems.ToArray(), itemtype, mrs.flags); } // Service 1 (MAP_ITEM_TELEHUB) - itemtype = 1; + itemtype = (uint)GridItemType.Telehub; if (response.ContainsKey(itemtype.ToString())) { @@ -721,12 +709,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap { OSDMap mapitem = (OSDMap)itemarray[i]; mapItemReply mi = new mapItemReply(); - mi.x = (uint)mapitem["X"].AsInteger(); - mi.y = (uint)mapitem["Y"].AsInteger(); - mi.id = mapitem["ID"].AsUUID(); - mi.Extra = mapitem["Extra"].AsInteger(); - mi.Extra2 = mapitem["Extra2"].AsInteger(); - mi.name = mapitem["Name"].AsString(); + mi.FromOSD(mapitem); returnitems.Add(mi); } av.ControllingClient.SendMapItemReply(returnitems.ToArray(), itemtype, mrs.flags); @@ -1008,7 +991,6 @@ namespace OpenSim.Region.CoreModules.World.WorldMap /// public virtual void RequestMapBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag) { - //m_log.ErrorFormat("[YYY] RequestMapBlocks {0}={1}={2}={3} {4}", minX, minY, maxX, maxY, flag); if ((flag & 0x10000) != 0) // user clicked on qthe map a tile that isn't visible { List response = new List(); @@ -1020,6 +1002,8 @@ namespace OpenSim.Region.CoreModules.World.WorldMap (int)Util.RegionToWorldLoc((uint)minX), (int)Util.RegionToWorldLoc((uint)maxX), (int)Util.RegionToWorldLoc((uint)minY), (int)Util.RegionToWorldLoc((uint)maxY) ); + m_log.DebugFormat("[WORLD MAP MODULE] RequestMapBlocks min=<{0},{1}>, max=<{2},{3}>, flag={4}, cntFound={5}", + minX, minY, maxX, maxY, flag.ToString("X"), regions.Count); if (regions != null) { foreach (GridRegion r in regions) @@ -1028,9 +1012,11 @@ namespace OpenSim.Region.CoreModules.World.WorldMap && r.RegionLocY == Util.RegionToWorldLoc((uint)minY) ) { // found it => add it to response - MapBlockData block = new MapBlockData(); - MapBlockFromGridRegion(block, r, flag); - response.Add(block); + // Version 2 viewers can handle the larger regions + if ((flag & 2) == 2) + response.AddRange(Map2BlockFromGridRegion(r, flag)); + else + response.Add(MapBlockFromGridRegion(r, flag)); break; } } @@ -1042,7 +1028,8 @@ namespace OpenSim.Region.CoreModules.World.WorldMap MapBlockData block = new MapBlockData(); block.X = (ushort)minX; block.Y = (ushort)minY; - block.Access = 254; // means 'simulator is offline' + block.Access = (byte)SimAccess.Down; // means 'simulator is offline' + // block.Access = (byte)SimAccess.NonExistant; response.Add(block); } // The lower 16 bits are an unsigned int16 @@ -1061,37 +1048,110 @@ namespace OpenSim.Region.CoreModules.World.WorldMap List regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID, (int)Util.RegionToWorldLoc((uint)(minX - 4)), (int)Util.RegionToWorldLoc((uint)(maxX + 4)), (int)Util.RegionToWorldLoc((uint)(minY - 4)), (int)Util.RegionToWorldLoc((uint)(maxY + 4)) ); + m_log.DebugFormat("{0} GetAndSendBlocks. min=<{1},{2}>, max=<{3},{4}>, cntFound={5}", + LogHeader, minX, minY, maxX, maxY, regions.Count); foreach (GridRegion r in regions) { - MapBlockData block = new MapBlockData(); - MapBlockFromGridRegion(block, r, flag); - mapBlocks.Add(block); + // Version 2 viewers can handle the larger regions + if ((flag & 2) == 2) + mapBlocks.AddRange(Map2BlockFromGridRegion(r, flag)); + else + mapBlocks.Add(MapBlockFromGridRegion(r, flag)); } remoteClient.SendMapBlock(mapBlocks, flag & 0xffff); return mapBlocks; } - protected void MapBlockFromGridRegion(MapBlockData block, GridRegion r, uint flag) + // Fill a passed MapBlockData from a GridRegion + protected MapBlockData MapBlockFromGridRegion(GridRegion r, uint flag) { + MapBlockData block = new MapBlockData(); + block.Access = r.Access; switch (flag & 0xffff) { - case 0: - block.MapImageId = r.TerrainImage; - break; - case 2: - block.MapImageId = r.ParcelImage; - break; - default: - block.MapImageId = UUID.Zero; - break; + case 0: + block.MapImageId = r.TerrainImage; + break; + case 2: + block.MapImageId = r.ParcelImage; + break; + default: + block.MapImageId = UUID.Zero; + break; } block.Name = r.RegionName; block.X = (ushort)Util.WorldToRegionLoc((uint)r.RegionLocX); block.Y = (ushort)Util.WorldToRegionLoc((uint)r.RegionLocY); + block.SizeX = (ushort) r.RegionSizeX; + block.SizeY = (ushort) r.RegionSizeY; + + return block; } + protected List Map2BlockFromGridRegion(GridRegion r, uint flag) + { + List blocks = new List(); + MapBlockData block = new MapBlockData(); + if (r == null) + { + block.Access = (byte)SimAccess.Down; + block.MapImageId = UUID.Zero; + blocks.Add(block); + } + else + { + block.Access = r.Access; + switch (flag & 0xffff) + { + case 0: + block.MapImageId = r.TerrainImage; + break; + case 2: + block.MapImageId = r.ParcelImage; + break; + default: + block.MapImageId = UUID.Zero; + break; + } + block.Name = r.RegionName; + block.X = (ushort)(r.RegionLocX / Constants.RegionSize); + block.Y = (ushort)(r.RegionLocY / Constants.RegionSize); + block.SizeX = (ushort)r.RegionSizeX; + block.SizeY = (ushort)r.RegionSizeY; + blocks.Add(block); + // If these are larger than legacy regions, create fake map entries for the covered + // regions. The map system only does legacy sized regions so we have to fake map + // entries for all the covered regions. + if (r.RegionSizeX > Constants.RegionSize || r.RegionSizeY > Constants.RegionSize) + { + for (int x = 0; x < r.RegionSizeX / Constants.RegionSize; x++) + { + for (int y = 0; y < r.RegionSizeY / Constants.RegionSize; y++) + { + if (x == 0 && y == 0) + continue; + block = new MapBlockData + { + Access = r.Access, + MapImageId = r.TerrainImage, + Name = r.RegionName, + X = (ushort)((r.RegionLocX / Constants.RegionSize) + x), + Y = (ushort)((r.RegionLocY / Constants.RegionSize) + y), + SizeX = (ushort)r.RegionSizeX, + SizeY = (ushort)r.RegionSizeY + }; + //Child piece, so ignore it + blocks.Add(block); + } + } + } + } + return blocks; + } + + public Hashtable OnHTTPThrottled(Hashtable keysvals) { Hashtable reply = new Hashtable(); @@ -1229,8 +1289,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap foreach (GridRegion r in regions) { - MapBlockData mapBlock = new MapBlockData(); - MapBlockFromGridRegion(mapBlock, r, 0); + MapBlockData mapBlock = MapBlockFromGridRegion(r, 0); AssetBase texAsset = m_scene.AssetService.Get(mapBlock.MapImageId.ToString()); if (texAsset != null) @@ -1291,7 +1350,9 @@ namespace OpenSim.Region.CoreModules.World.WorldMap uint xstart = 0; uint ystart = 0; - Utils.LongToUInts(m_scene.RegionInfo.RegionHandle,out xstart,out ystart); + Util.RegionHandleToWorldLoc(m_scene.RegionInfo.RegionHandle,out xstart,out ystart); + // m_log.DebugFormat("{0} HandleRemoteMapItemRequest. loc=<{1},{2}>", + // LogHeader, Util.WorldToRegionLoc(xstart), Util.WorldToRegionLoc(ystart)); // Service 6 (MAP_ITEM_AGENTS_LOCATION; green dots) diff --git a/OpenSim/Server/Handlers/Grid/GridServerPostHandler.cs b/OpenSim/Server/Handlers/Grid/GridServerPostHandler.cs index c63b409..16d9b7d 100644 --- a/OpenSim/Server/Handlers/Grid/GridServerPostHandler.cs +++ b/OpenSim/Server/Handlers/Grid/GridServerPostHandler.cs @@ -48,6 +48,7 @@ namespace OpenSim.Server.Handlers.Grid public class GridServerPostHandler : BaseStreamHandler { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private static string LogHeader = "[GRID HANDLER]"; private IGridService m_GridService; @@ -281,8 +282,8 @@ namespace OpenSim.Server.Handlers.Grid else m_log.WarnFormat("[GRID HANDLER]: no Y in request to get region by position"); + // m_log.DebugFormat("{0} GetRegionByPosition: loc=<{1},{2}>", LogHeader, x, y); GridRegion rinfo = m_GridService.GetRegionByPosition(scopeID, x, y); - //m_log.DebugFormat("[GRID HANDLER]: neighbours for region {0}: {1}", regionID, rinfos.Count); Dictionary result = new Dictionary(); if (rinfo == null) -- cgit v1.1