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.
varregion
Robert Adams 2014-01-26 19:32:28 -08:00
parent 13a9d5409c
commit 49af6b53e7
6 changed files with 221 additions and 83 deletions

View File

@ -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;
}
}
}

View File

@ -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();
}
}
}

View File

@ -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)
{

View File

@ -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++)
// {

View File

@ -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<mapItemReply> mapitems = new List<mapItemReply>();
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
/// <param name="maxY"></param>
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<MapBlockData> response = new List<MapBlockData>();
@ -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<GridRegion> 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<MapBlockData> Map2BlockFromGridRegion(GridRegion r, uint flag)
{
List<MapBlockData> blocks = new List<MapBlockData>();
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)

View File

@ -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<string, object> result = new Dictionary<string, object>();
if (rinfo == null)