protected override void GetAndSendBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag)
        {
            List<MapBlockData> mapBlocks = new List<MapBlockData>();
            List<GridRegion> regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID,
                minX * (int)Constants.RegionSize, maxX * (int)Constants.RegionSize, 
                minY * (int)Constants.RegionSize, maxY * (int)Constants.RegionSize);

            foreach (GridRegion r in regions)
            {
                MapBlockData block = new MapBlockData();
                MapBlockFromGridRegion(block, r);
                mapBlocks.Add(block);
            }

            // Different from super
            FillInMap(mapBlocks, minX, minY, maxX, maxY);
            //

            remoteClient.SendMapBlock(mapBlocks, 0);
        }
예제 #2
0
 private void FillInMap(List<MapBlockData> mapBlocks, int minX, int minY, int maxX, int maxY)
 {
     for (int x = minX; x <= maxX; x++)
     {
         for (int y = minY; y <= maxY; y++)
         {
             MapBlockData mblock = mapBlocks.Find(delegate(MapBlockData mb) { return ((mb.X == x) && (mb.Y == y)); });
             if (mblock == null)
             {
                 mblock = new MapBlockData();
                 mblock.X = (ushort)x;
                 mblock.Y = (ushort)y;
                 mblock.Name = "";
                 mblock.Access = 254; // not here???
                 mblock.MapImageId = UUID.Zero;
                 mapBlocks.Add(mblock);
             }
         }
     }
 }
예제 #3
0
        private void OnMapNameRequest (IClientAPI remoteClient, string mapName, uint flags)
        {
            if (mapName.Length < 1)
            {
                remoteClient.SendAlertMessage("Use a search string with at least 1 character");
                return;
            }

            bool TryCoordsSearch = false;
            int XCoord = 0;
            int YCoord = 0;

            string[] splitSearch = mapName.Split(',');
            if (splitSearch.Length != 1)
            {
                if (splitSearch[1].StartsWith (" "))
                    splitSearch[1] = splitSearch[1].Remove (0, 1);
                if (int.TryParse(splitSearch[0], out XCoord) && int.TryParse(splitSearch[1], out YCoord))
                    TryCoordsSearch = true;
            }

            List<MapBlockData> blocks = new List<MapBlockData>();

            List<GridRegion> regionInfos = m_scene.GridService.GetRegionsByName(UUID.Zero, mapName, 20);
            if (TryCoordsSearch)
            {
                GridRegion region = m_scene.GridService.GetRegionByPosition(m_scene.RegionInfo.ScopeID, (int)(XCoord * Constants.RegionSize), (int)(YCoord * Constants.RegionSize));
                if (region != null)
                {
                    region.RegionName = mapName + " - " + region.RegionName;
                    regionInfos.Add (region);
                }
            }
            List<GridRegion> allRegions = new List<GridRegion> ();
            foreach (GridRegion region in regionInfos)
            {
                //Add the found in search region first
                if (!allRegions.Contains (region))
                {
                    allRegions.Add (region);
                    blocks.Add (SearchMapBlockFromGridRegion (region));
                }
                //Then send surrounding regions
                List<GridRegion> regions = m_scene.GridService.GetRegionRange (m_scene.RegionInfo.ScopeID,
                    (region.RegionLocX - (4 * (int)Constants.RegionSize)),
                    (region.RegionLocX + (4 * (int)Constants.RegionSize)),
                    (region.RegionLocY - (4 * (int)Constants.RegionSize)),
                    (region.RegionLocY + (4 * (int)Constants.RegionSize)));
                if (regions != null)
                {
                    foreach (GridRegion r in regions)
                    {
                        if (!allRegions.Contains (region))
                        {
                            allRegions.Add (region);
                            blocks.Add (SearchMapBlockFromGridRegion (r));

                        }
                    }
                }
            }

            // final block, closing the search result
            MapBlockData data = new MapBlockData();
            data.Agents = 0;
            data.Access = 255;
            data.MapImageID = UUID.Zero;
            data.Name = mapName;
            data.RegionFlags = 0;
            data.WaterHeight = 0; // not used
            data.X = 0;
            data.Y = 0;
            blocks.Add(data);

            remoteClient.SendMapBlock (blocks, flags);
        }
예제 #4
0
        /// <summary>
        /// Export the world map
        /// </summary>
        /// <param name="fileName"></param>
        public void HandleExportWorldMapConsoleCommand(string module, string[] cmdparams)
        {
            if (m_scene.ConsoleScene() == null)
            {
                // FIXME: If console region is root then this will be printed by every module.  Currently, there is no
                // way to prevent this, short of making the entire module shared (which is complete overkill).
                // One possibility is to return a bool to signal whether the module has completely handled the command
                m_log.InfoFormat("[WORLD MAP]: Please change to a specific region in order to export its world map");
                return;
            }

            if (m_scene.ConsoleScene() != m_scene)
                return;

            string exportPath;

            if (cmdparams.Length > 1)
                exportPath = cmdparams[1];
            else
                exportPath = DEFAULT_WORLD_MAP_EXPORT_PATH;

            m_log.InfoFormat(
                "[WORLD MAP]: Exporting world map for {0} to {1}", m_scene.RegionInfo.RegionName, exportPath);

            List<MapBlockData> mapBlocks = new List<MapBlockData>();
            List<GridRegion> regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID,
                    (int)(m_scene.RegionInfo.RegionLocX - 9) * (int)Constants.RegionSize,
                    (int)(m_scene.RegionInfo.RegionLocX + 9) * (int)Constants.RegionSize,
                    (int)(m_scene.RegionInfo.RegionLocY - 9) * (int)Constants.RegionSize,
                    (int)(m_scene.RegionInfo.RegionLocY + 9) * (int)Constants.RegionSize);
            List<AssetBase> textures = new List<AssetBase>();
            List<Image> bitImages = new List<Image>();

            foreach (GridRegion r in regions)
            {
                MapBlockData mapBlock = new MapBlockData();
                MapBlockFromGridRegion(mapBlock, r);
                AssetBase texAsset = m_scene.AssetService.Get(mapBlock.MapImageId.ToString());

                if (texAsset != null)
                {
                    textures.Add(texAsset);
                }
                //else
                //{
                //    // WHAT?!? This doesn't seem right. Commenting (diva)
                //    texAsset = m_scene.AssetService.Get(mapBlock.MapImageId.ToString());
                //    if (texAsset != null)
                //    {
                //        textures.Add(texAsset);
                //    }
                //}
            }

            foreach (AssetBase asset in textures)
            {
                ManagedImage managedImage;
                Image image;

                if (OpenJPEG.DecodeToImage(asset.Data, out managedImage, out image))
                    bitImages.Add(image);
            }

            Bitmap mapTexture = new Bitmap(2560, 2560);
            Graphics g = Graphics.FromImage(mapTexture);
            SolidBrush sea = new SolidBrush(Color.DarkBlue);
            g.FillRectangle(sea, 0, 0, 2560, 2560);

            for (int i = 0; i < mapBlocks.Count; i++)
            {
                ushort x = (ushort)((mapBlocks[i].X - m_scene.RegionInfo.RegionLocX) + 10);
                ushort y = (ushort)((mapBlocks[i].Y - m_scene.RegionInfo.RegionLocY) + 10);
                g.DrawImage(bitImages[i], (x * 128), 2560 - (y * 128), 128, 128); // y origin is top
            }

            mapTexture.Save(exportPath, ImageFormat.Jpeg);

            m_log.InfoFormat(
                "[WORLD MAP]: Successfully exported world map for {0} to {1}",
                m_scene.RegionInfo.RegionName, exportPath);
        }
예제 #5
0
 protected virtual void GetAndSendBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag)
 {
     List<MapBlockData> mapBlocks = new List<MapBlockData>();
     List<GridRegion> regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID,
         (minX - 4) * (int)Constants.RegionSize, 
         (maxX + 4) * (int)Constants.RegionSize,
         (minY - 4) * (int)Constants.RegionSize,
         (maxY + 4) * (int)Constants.RegionSize);
     foreach (GridRegion r in regions)
     {
         MapBlockData block = new MapBlockData();
         MapBlockFromGridRegion(block, r);
         mapBlocks.Add(block);
     }
     remoteClient.SendMapBlock(mapBlocks, flag);
 }
예제 #6
0
        /// <summary>
        /// Callback for a map layer request
        /// </summary>
        /// <param name="request"></param>
        /// <param name="path"></param>
        /// <param name="param"></param>
        /// <param name="agentID"></param>
        /// <param name="caps"></param>
        /// <returns></returns>
        public string MapLayerRequest(string request, string path, string param,
                                      UUID agentID, Caps caps)
        {
            //try
            //{
                //m_log.DebugFormat("[MAPLAYER]: request: {0}, path: {1}, param: {2}, agent:{3}",
                                  //request, path, param,agentID.ToString());

            // this is here because CAPS map requests work even beyond the 10,000 limit.
            ScenePresence avatarPresence = null;

            m_scene.TryGetScenePresence(agentID, out avatarPresence);

            if (avatarPresence != null)
            {
                bool lookup = false;

                lock (cachedMapBlocks)
                {
                    if (cachedMapBlocks.Count > 0 && ((cachedTime + 1800) > Util.UnixTimeSinceEpoch()))
                    {
                        List<MapBlockData> mapBlocks;

                        mapBlocks = cachedMapBlocks;
                        avatarPresence.ControllingClient.SendMapBlock(mapBlocks, 0);
                    }
                    else
                    {
                        lookup = true;
                    }
                }
                if (lookup)
                {
                    List<MapBlockData> mapBlocks = new List<MapBlockData>(); ;

                    List<GridRegion> regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID,
                        (int)(m_scene.RegionInfo.RegionLocX - 8) * (int)Constants.RegionSize,
                        (int)(m_scene.RegionInfo.RegionLocX + 8) * (int)Constants.RegionSize,
                        (int)(m_scene.RegionInfo.RegionLocY - 8) * (int)Constants.RegionSize,
                        (int)(m_scene.RegionInfo.RegionLocY + 8) * (int)Constants.RegionSize);
                    foreach (GridRegion r in regions)
                    {
                        MapBlockData block = new MapBlockData();
                        MapBlockFromGridRegion(block, r);
                        mapBlocks.Add(block);
                    }
                    avatarPresence.ControllingClient.SendMapBlock(mapBlocks, 0);

                    lock (cachedMapBlocks)
                        cachedMapBlocks = mapBlocks;

                    cachedTime = Util.UnixTimeSinceEpoch();
                }
            }
            LLSDMapLayerResponse mapResponse = new LLSDMapLayerResponse();
            mapResponse.LayerData.Array.Add(GetOSDMapLayerResponse());
            return mapResponse.ToString();
        }
예제 #7
0
        private void RequestNonVisibleMapTile(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag)
        {
            List<MapBlockData> response = new List<MapBlockData>();

            // this should return one mapblock at most. But make sure: Look whether the one we requested is in there
            List<MapBlockData> mapBlocks = m_scene.SceneGridService.RequestNeighbourMapBlocks(minX, minY, maxX, maxY);
            if (mapBlocks != null)
            {
                foreach (MapBlockData block in mapBlocks)
                {
                    if (block.X == minX && block.Y == minY)
                    {
                        // found it => add it to response
                        response.Add(block);
                        break;
                    }
                }
            }

            if (response.Count == 0)
            {
                // response still empty => couldn't find the map-tile the user clicked on => tell the client
                MapBlockData block = new MapBlockData();
                block.X = (ushort)minX;
                block.Y = (ushort)minY;
                block.Access = 254; // == not there
                response.Add(block);
            }
            //(flag & 0x10000) != 0 is sent by v2 viewers, and it expects flag 2 back
            remoteClient.SendMapBlock(response, flag & 0xffff);
        }
예제 #8
0
        /// <summary>
        /// Requests map blocks in area of minX, maxX, minY, MaxY in world cordinates
        /// </summary>
        /// <param name="minX"></param>
        /// <param name="minY"></param>
        /// <param name="maxX"></param>
        /// <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>();

                // this should return one mapblock at most. It is triggered by a click
                // on an unloaded square.
                // But make sure: Look whether the one we requested is in there
                List<GridRegion> regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID,
                    minX * (int)Constants.RegionSize, 
                    maxX * (int)Constants.RegionSize, 
                    minY * (int)Constants.RegionSize, 
                    maxY * (int)Constants.RegionSize);

                if (regions != null)
                {
                    foreach (GridRegion r in regions)
                    {
                        if ((r.RegionLocX == minX * (int)Constants.RegionSize) && 
                            (r.RegionLocY == minY * (int)Constants.RegionSize))
                        {
                            // found it => add it to response
                            MapBlockData block = new MapBlockData();
                            MapBlockFromGridRegion(block, r, flag);
                            response.Add(block);
                            break;
                        }
                    }
                }

                if (response.Count == 0)
                {
                    // response still empty => couldn't find the map-tile the user clicked on => tell the client
                    MapBlockData block = new MapBlockData();
                    block.X = (ushort)minX;
                    block.Y = (ushort)minY;
                    block.Access = 254; // means 'simulator is offline'
                    response.Add(block);
                }
                // The lower 16 bits are an unsigned int16
                remoteClient.SendMapBlock(response, flag & 0xffff);
            }
            else
            {
                // normal mapblock request. Use the provided values
                GetAndSendBlocks(remoteClient, minX, minY, maxX, maxY, flag);
            }
        }
예제 #9
0
 protected void MapBlockFromGridRegion(MapBlockData block, GridRegion r, uint flag)
 {
     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);
 }
예제 #10
0
        private void OnMapNameRequest(IClientAPI remoteClient, string mapName, uint flags)
        {
            if (mapName.Length < 3)
            {
                remoteClient.SendAlertMessage("Use a search string with at least 3 characters");
                return;
            }

//m_log.DebugFormat("MAP NAME=({0})", mapName);
            
            // try to fetch from GridServer
            List<GridRegion> regionInfos = m_scene.GridService.GetRegionsByName(m_scene.RegionInfo.ScopeID, mapName, 20);
            if (regionInfos.Count == 0)
                remoteClient.SendAlertMessage("Hyperlink could not be established.");

            m_log.DebugFormat("[MAPSEARCHMODULE]: search {0} returned {1} regions. Flags={2}", mapName, regionInfos.Count, flags);
            List<MapBlockData> blocks = new List<MapBlockData>();

            MapBlockData data;
            if (regionInfos.Count > 0)
            {
                foreach (GridRegion info in regionInfos)
                {
                    data = new MapBlockData();
                    data.Agents = 0;
                    data.Access = info.Access;
                    if (flags == 2) // V2 sends this
                        data.MapImageId = UUID.Zero; 
                    else
                        data.MapImageId = info.TerrainImage;
                    data.Name = info.RegionName;
                    data.RegionFlags = 0; // TODO not used?
                    data.WaterHeight = 0; // not used
                    data.X = (ushort)(info.RegionLocX / Constants.RegionSize);
                    data.Y = (ushort)(info.RegionLocY / Constants.RegionSize);
                    blocks.Add(data);
                }
            }

            // final block, closing the search result
            data = new MapBlockData();
            data.Agents = 0;
            data.Access = 255;
            data.MapImageId = UUID.Zero;
            data.Name = ""; // mapName;
            data.RegionFlags = 0;
            data.WaterHeight = 0; // not used
            data.X = 0;
            data.Y = 0;
            blocks.Add(data);

            // flags are agent flags sent from the viewer.
            // they have different values depending on different viewers, apparently
            remoteClient.SendMapBlock(blocks, flags);
        }
예제 #11
0
        private void OnMapNameRequest(IClientAPI remoteClient, string mapName, uint flags)
        {
            List<MapBlockData> blocks = new List<MapBlockData>();
            MapBlockData data;
            if (mapName.Length < 3 || (mapName.EndsWith("#") && mapName.Length < 4))
            {
                // final block, closing the search result
                AddFinalBlock(blocks);

                // flags are agent flags sent from the viewer.
                // they have different values depending on different viewers, apparently
                remoteClient.SendMapBlock(blocks, flags);
                remoteClient.SendAlertMessage("Use a search string with at least 3 characters");
                return;
            }


            //m_log.DebugFormat("MAP NAME=({0})", mapName);

            // Hack to get around the fact that ll V3 now drops the port from the
            // map name. See https://jira.secondlife.com/browse/VWR-28570
            //
            // Caller, use this magic form instead:
            // secondlife://http|!!mygrid.com|8002|Region+Name/128/128
            // or url encode if possible.
            // the hacks we do with this viewer...
            //
            string mapNameOrig = mapName;
            if (mapName.Contains("|"))
                mapName = mapName.Replace('|', ':');
            if (mapName.Contains("+"))
                mapName = mapName.Replace('+', ' ');
            if (mapName.Contains("!"))
                mapName = mapName.Replace('!', '/');
            
            // try to fetch from GridServer
            List<GridRegion> regionInfos = m_scene.GridService.GetRegionsByName(m_scene.RegionInfo.ScopeID, mapName, 20);

            m_log.DebugFormat("[MAPSEARCHMODULE]: search {0} returned {1} regions. Flags={2}", mapName, regionInfos.Count, flags);
            if (regionInfos.Count > 0)
            {
                foreach (GridRegion info in regionInfos)
                {
                    data = new MapBlockData();
                    data.Agents = 0;
                    data.Access = info.Access;
                    if (flags == 2) // V2 sends this
                        data.MapImageId = UUID.Zero; 
                    else
                        data.MapImageId = info.TerrainImage;
                    // ugh! V2-3 is very sensitive about the result being
                    // exactly the same as the requested name
                    if (regionInfos.Count == 1 && mapNameOrig.Contains("|") || mapNameOrig.Contains("+"))
                        data.Name = mapNameOrig;
                    else
                        data.Name = info.RegionName;
                    data.RegionFlags = 0; // TODO not used?
                    data.WaterHeight = 0; // not used
                    data.X = (ushort)(info.RegionLocX / Constants.RegionSize);
                    data.Y = (ushort)(info.RegionLocY / Constants.RegionSize);
                    blocks.Add(data);
                }
            }

            // final block, closing the search result
            AddFinalBlock(blocks);

            // flags are agent flags sent from the viewer.
            // they have different values depending on different viewers, apparently
            remoteClient.SendMapBlock(blocks, flags);

            // send extra user messages for V3
            // because the UI is very confusing
            // while we don't fix the hard-coded urls
            if (flags == 2) 
            {
                if (regionInfos.Count == 0)
                    remoteClient.SendAlertMessage("No regions found with that name.");
                else if (regionInfos.Count == 1)
                    remoteClient.SendAlertMessage("Region found!");
            }
        }
 private void FillInMap(List<MapBlockData> mapBlocks, int minX, int minY, int maxX, int maxY)
 {
     for (int x = minX; x <= maxX; x++)
     {
         for (int y = minY; y <= maxY; y++)
         {
             MapBlockData mblock = mapBlocks.Find(delegate(MapBlockData mb) { return ((mb.X == x) && (mb.Y == y)); });
             if (mblock == null)
             {
                 mblock = new MapBlockData();
                 mblock.X = (ushort)x;
                 mblock.Y = (ushort)y;
                 mblock.Name = "";
                 mblock.Access = 254; // means 'simulator is offline'. We need this because the viewer ignores 255's
                 mblock.MapImageId = UUID.Zero;
                 mapBlocks.Add(mblock);
             }
         }
     }
 }
예제 #13
0
        protected override List<MapBlockData> GetAndSendBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag)
        {
            List<MapBlockData> mapBlocks = new List<MapBlockData>();
            List<GridRegion> regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID,
                minX * (int)Constants.RegionSize, maxX * (int)Constants.RegionSize, 
                minY * (int)Constants.RegionSize, maxY * (int)Constants.RegionSize);

            foreach (GridRegion r in regions)
            {
                uint x = 0, y = 0;
                long handle = 0;
                if (r.RegionSecret != null && r.RegionSecret != string.Empty)
                {
                    if (long.TryParse(r.RegionSecret, out handle))
                    {
                        Utils.LongToUInts((ulong)handle, out x, out y);
                        x = x / Constants.RegionSize;
                        y = y / Constants.RegionSize;
                    }
                }

                if (handle == 0 || 
                    // Check the distance from the current region
                    (handle != 0 && Math.Abs((int)(x - m_scene.RegionInfo.RegionLocX)) < 4096 && Math.Abs((int)(y - m_scene.RegionInfo.RegionLocY)) < 4096))
                {
                    MapBlockData block = new MapBlockData();
                    MapBlockFromGridRegion(block, r);
                    mapBlocks.Add(block);
                }
            }

            // Different from super
            FillInMap(mapBlocks, minX, minY, maxX, maxY);
            //

            remoteClient.SendMapBlock(mapBlocks, 0);

            return mapBlocks;
        }
        public void Teleport(ScenePresence sp, ulong regionHandle, Vector3 position, Vector3 lookAt, uint teleportFlags)
        {
            if (!sp.Scene.Permissions.CanTeleport(sp.UUID))
                return;

            IEventQueue eq = sp.Scene.RequestModuleInterface<IEventQueue>();

            // Reset animations; the viewer does that in teleports.
            sp.Animator.ResetAnimations();

            try
            {
                if (regionHandle == sp.Scene.RegionInfo.RegionHandle)
                {
                    m_log.DebugFormat(
                        "[ENTITY TRANSFER MODULE]: RequestTeleportToLocation {0} within {1}",
                        position, sp.Scene.RegionInfo.RegionName);

                    // Teleport within the same region
                    if (IsOutsideRegion(sp.Scene, position) || position.Z < 0)
                    {
                        Vector3 emergencyPos = new Vector3(128, 128, 128);

                        m_log.WarnFormat(
                            "[ENTITY TRANSFER MODULE]: RequestTeleportToLocation() was given an illegal position of {0} for avatar {1}, {2}.  Substituting {3}",
                            position, sp.Name, sp.UUID, emergencyPos);
                        position = emergencyPos;
                    }

                    // TODO: Get proper AVG Height
                    float localAVHeight = 1.56f;
                    float posZLimit = 22;

                    // TODO: Check other Scene HeightField
                    if (position.X > 0 && position.X <= (int)Constants.RegionSize && position.Y > 0 && position.Y <= (int)Constants.RegionSize)
                    {
                        posZLimit = (float)sp.Scene.Heightmap[(int)position.X, (int)position.Y];
                    }

                    float newPosZ = posZLimit + localAVHeight;
                    if (posZLimit >= (position.Z - (localAVHeight / 2)) && !(Single.IsInfinity(newPosZ) || Single.IsNaN(newPosZ)))
                    {
                        position.Z = newPosZ;
                    }

                    // Only send this if the event queue is null
                    if (eq == null)
                        sp.ControllingClient.SendTeleportLocationStart();

                    sp.ControllingClient.SendLocalTeleport(position, lookAt, teleportFlags);
                    sp.Teleport(position);
                }
                else // Another region possibly in another simulator
                {
                    uint x = 0, y = 0;
                    Utils.LongToUInts(regionHandle, out x, out y);
                    GridRegion reg = m_aScene.GridService.GetRegionByPosition(sp.Scene.RegionInfo.ScopeID, (int)x, (int)y);

                    if (reg != null)
                    {
                        GridRegion finalDestination = GetFinalDestination(reg);
                        if (finalDestination == null)
                        {
                            m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Final destination is having problems. Unable to teleport agent.");
                            sp.ControllingClient.SendTeleportFailed("Problem at destination");
                            return;
                        }
                        m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Final destination is x={0} y={1} uuid={2}",
                            finalDestination.RegionLocX / Constants.RegionSize, finalDestination.RegionLocY / Constants.RegionSize, finalDestination.RegionID);

                        //
                        // This is it
                        //
                        DoTeleport(sp, reg, finalDestination, position, lookAt, teleportFlags, eq);
                        //
                        //
                        //
                    }
                    else
                    {
                        // TP to a place that doesn't exist (anymore)
                        // Inform the viewer about that
                        sp.ControllingClient.SendTeleportFailed("The region you tried to teleport to doesn't exist anymore");

                        // and set the map-tile to '(Offline)'
                        uint regX, regY;
                        Utils.LongToUInts(regionHandle, out regX, out regY);

                        MapBlockData block = new MapBlockData();
                        block.X = (ushort)(regX / Constants.RegionSize);
                        block.Y = (ushort)(regY / Constants.RegionSize);
                        block.Access = 254; // == not there

                        List<MapBlockData> blocks = new List<MapBlockData>();
                        blocks.Add(block);
                        sp.ControllingClient.SendMapBlock(blocks, 0);
                    }
                }
            }
            catch (Exception e)
            {
                m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Exception on teleport: {0}\n{1}", e.Message, e.StackTrace);
                sp.ControllingClient.SendTeleportFailed("Internal error");
            }
        }
예제 #15
0
        /// <summary>
        /// Teleports the agent to a different region.
        /// </summary>
        /// <param name='sp'></param>
        /// <param name='regionHandle'>/param>
        /// <param name='position'></param>
        /// <param name='lookAt'></param>
        /// <param name='teleportFlags'></param>
        /// <param name='finalDestination'></param>
        private void TeleportAgentToDifferentRegion(
            ScenePresence sp, ulong regionHandle, Vector3 position,
            Vector3 lookAt, uint teleportFlags, out GridRegion finalDestination)
        {
            uint x = 0, y = 0;
            Utils.LongToUInts(regionHandle, out x, out y);
            GridRegion reg = Scene.GridService.GetRegionByPosition(sp.Scene.RegionInfo.ScopeID, (int)x, (int)y);

            if (reg != null)
            {
                finalDestination = GetFinalDestination(reg);

                if (finalDestination == null)
                {
                    m_log.WarnFormat(
                        "[ENTITY TRANSFER MODULE]: Final destination is having problems. Unable to teleport {0} {1}",
                        sp.Name, sp.UUID);

                    sp.ControllingClient.SendTeleportFailed("Problem at destination");
                    return;
                }

                // Check that these are not the same coordinates
                if (finalDestination.RegionLocX == sp.Scene.RegionInfo.RegionLocX &&
                    finalDestination.RegionLocY == sp.Scene.RegionInfo.RegionLocY)
                {
                    // Can't do. Viewer crashes
                    sp.ControllingClient.SendTeleportFailed("Space warp! You would crash. Move to a different region and try again.");
                    return;
                }

                // Validate assorted conditions
                string reason = string.Empty;
                if (!ValidateGenericConditions(sp, reg, finalDestination, teleportFlags, out reason))
                {
                    sp.ControllingClient.SendTeleportFailed(reason);
                    return;
                }

                //
                // This is it
                //
                DoTeleportInternal(sp, reg, finalDestination, position, lookAt, teleportFlags);
                //
                //
                //
            }
            else
            {
                finalDestination = null;

                // TP to a place that doesn't exist (anymore)
                // Inform the viewer about that
                sp.ControllingClient.SendTeleportFailed("The region you tried to teleport to doesn't exist anymore");

                // and set the map-tile to '(Offline)'
                uint regX, regY;
                Utils.LongToUInts(regionHandle, out regX, out regY);

                MapBlockData block = new MapBlockData();
                block.X = (ushort)(regX / Constants.RegionSize);
                block.Y = (ushort)(regY / Constants.RegionSize);
                block.Access = 254; // == not there

                List<MapBlockData> blocks = new List<MapBlockData>();
                blocks.Add(block);
                sp.ControllingClient.SendMapBlock(blocks, 0);
            }
        }
예제 #16
0
        /// <summary>
        /// Teleports the agent to a different region.
        /// </summary>
        /// <param name='sp'></param>
        /// <param name='regionHandle'>/param>
        /// <param name='position'></param>
        /// <param name='lookAt'></param>
        /// <param name='teleportFlags'></param>
        /// <param name='finalDestination'></param>
        private void TeleportAgentToDifferentRegion(
            ScenePresence sp, ulong regionHandle, Vector3 position,
            Vector3 lookAt, uint teleportFlags, out GridRegion finalDestination)
        {
            // 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)
            {
                string homeURI = Scene.GetAgentHomeURI(sp.ControllingClient.AgentId);

                string message;
                finalDestination = GetFinalDestination(reg, sp.ControllingClient.AgentId, homeURI, out message);

                if (finalDestination == null)
                {
                    m_log.WarnFormat( "{0} Final destination is having problems. Unable to teleport {1} {2}: {3}",
                                            LogHeader, sp.Name, sp.UUID, message);

                    sp.ControllingClient.SendTeleportFailed(message);
                    return;
                }

                // Check that these are not the same coordinates
                if (finalDestination.RegionLocX == sp.Scene.RegionInfo.RegionLocX &&
                    finalDestination.RegionLocY == sp.Scene.RegionInfo.RegionLocY)
                {
                    // Can't do. Viewer crashes
                    sp.ControllingClient.SendTeleportFailed("Space warp! You would crash. Move to a different region and try again.");
                    return;
                }

                // Validate assorted conditions
                string reason = string.Empty;
                if (!ValidateGenericConditions(sp, reg, finalDestination, teleportFlags, out reason))
                {
                    sp.ControllingClient.SendTeleportFailed(reason);
                    return;
                }

                if (message != null)
                    sp.ControllingClient.SendAgentAlertMessage(message, true);

                //
                // This is it
                //
                DoTeleportInternal(sp, reg, finalDestination, position, lookAt, teleportFlags);
                //
                //
                //
            }
            else
            {
                finalDestination = null;

                // TP to a place that doesn't exist (anymore)
                // Inform the viewer about that
                sp.ControllingClient.SendTeleportFailed("The region you tried to teleport to doesn't exist anymore");

                // and set the map-tile to '(Offline)'
                uint regX, regY;
                Util.RegionHandleToRegionLoc(regionHandle, out regX, out regY);

                MapBlockData block = new MapBlockData();
                block.X = (ushort)regX;
                block.Y = (ushort)regY;
                block.Access = (byte)SimAccess.Down;

                List<MapBlockData> blocks = new List<MapBlockData>();
                blocks.Add(block);
                sp.ControllingClient.SendMapBlock(blocks, 0);
            }
        }
예제 #17
0
 private void AddFinalBlock(List<MapBlockData> blocks)
 {
         // final block, closing the search result
         MapBlockData data = new MapBlockData();
         data.Agents = 0;
         data.Access = (byte)SimAccess.NonExistent;
         data.MapImageId = UUID.Zero;
         data.Name = "";
         data.RegionFlags = 0;
         data.WaterHeight = 0; // not used
         data.X = 0;
         data.Y = 0;
         blocks.Add(data);
 }
예제 #18
0
        public virtual void Teleport(IScenePresence sp, ulong regionHandle, Vector3 position, Vector3 lookAt, uint teleportFlags)
        {
            int x = 0, y = 0;
            Util.UlongToInts(regionHandle, out x, out y);

            GridRegion reg = sp.Scene.GridService.GetRegionByPosition (sp.Scene.RegionInfo.ScopeID, x, y);
            
            if (reg == null)
            {
                List<GridRegion> regions = sp.Scene.GridService.GetRegionRange (sp.Scene.RegionInfo.ScopeID, x - 8192, x + 8192, y - 8192, y + 8192);
                foreach (GridRegion r in regions)
                {
                    if (r.RegionLocX <= x && r.RegionLocX + r.RegionSizeX > x &&
                        r.RegionLocY <= y && r.RegionLocY + r.RegionSizeY > y)
                    {
                        reg = r;
                        position.X += x - reg.RegionLocX;
                        position.Y += y - reg.RegionLocY;
                        break;
                    }
                }
                if (reg == null)
                {
                    // TP to a place that doesn't exist (anymore)
                    // Inform the viewer about that
                    sp.ControllingClient.SendTeleportFailed ("The region you tried to teleport to doesn't exist anymore");

                    // and set the map-tile to '(Offline)'
                    int regX, regY;
                    Util.UlongToInts (regionHandle, out regX, out regY);

                    MapBlockData block = new MapBlockData ();
                    block.X = (ushort)(regX / Constants.RegionSize);
                    block.Y = (ushort)(regY / Constants.RegionSize);
                    block.Access = 254; // == not there

                    List<MapBlockData> blocks = new List<MapBlockData> ();
                    blocks.Add (block);
                    sp.ControllingClient.SendMapBlock (blocks, 0);
                    return;
                }
            }
            Teleport(sp, reg, position, lookAt, teleportFlags);
        }
예제 #19
0
        /// <summary>
        /// Callback for a map layer request
        /// </summary>
        /// <param name="request"></param>
        /// <param name="path"></param>
        /// <param name="param"></param>
        /// <param name="agentID"></param>
        /// <param name="caps"></param>
        /// <returns></returns>
        public string MapLayerRequest(string request, string path, string param,
                                      UUID agentID, Caps caps)
        {
            //try
            //
            //m_log.DebugFormat("[MAPLAYER]: path: {0}, param: {1}, agent:{2}",
            //                  path, param, agentID.ToString());

            // There is a major hack going on in this method. The viewer doesn't request
            // map blocks (RequestMapBlocks) above 2048. That means that if we don't hack,
            // grids above that cell don't have a map at all. So, here's the hack: we wait
            // for this CAP request to come, and we inject the map blocks at this point. 
            // In a normal scenario, this request simply sends back the MapLayer (the blue color).
            // In the hacked scenario, it also sends the map blocks via UDP.
            //
            // 6/8/2011 -- I'm adding an explicit 2048 check, so that we never forget that there is
            // a hack here, and so that regions below 4096 don't get spammed with unnecessary map blocks.

            if (m_scene.RegionInfo.RegionLocX >= 2048 || m_scene.RegionInfo.RegionLocY >= 2048)
            {
                ScenePresence avatarPresence = null;

                m_scene.TryGetScenePresence(agentID, out avatarPresence);

                if (avatarPresence != null)
                {
                    bool lookup = false;

                    lock (cachedMapBlocks)
                    {
                        if (cachedMapBlocks.Count > 0 && ((cachedTime + 1800) > Util.UnixTimeSinceEpoch()))
                        {
                            List<MapBlockData> mapBlocks;

                            mapBlocks = cachedMapBlocks;
                            avatarPresence.ControllingClient.SendMapBlock(mapBlocks, 0);
                        }
                        else
                        {
                            lookup = true;
                        }
                    }
                    if (lookup)
                    {
                        List<MapBlockData> mapBlocks = new List<MapBlockData>(); ;

                        List<GridRegion> regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID,
                            (int)(m_scene.RegionInfo.RegionLocX - 8) * (int)Constants.RegionSize,
                            (int)(m_scene.RegionInfo.RegionLocX + 8) * (int)Constants.RegionSize,
                            (int)(m_scene.RegionInfo.RegionLocY - 8) * (int)Constants.RegionSize,
                            (int)(m_scene.RegionInfo.RegionLocY + 8) * (int)Constants.RegionSize);
                        foreach (GridRegion r in regions)
                        {
                            MapBlockData block = new MapBlockData();
                            MapBlockFromGridRegion(block, r, 0);
                            mapBlocks.Add(block);
                        }
                        avatarPresence.ControllingClient.SendMapBlock(mapBlocks, 0);

                        lock (cachedMapBlocks)
                            cachedMapBlocks = mapBlocks;

                        cachedTime = Util.UnixTimeSinceEpoch();
                    }
                }
            }

            LLSDMapLayerResponse mapResponse = new LLSDMapLayerResponse();
            mapResponse.LayerData.Array.Add(GetOSDMapLayerResponse());
            return mapResponse.ToString();
        }
        /// <summary>
        /// Requests map blocks in area of minX, maxX, minY, MaxY in world cordinates
        /// </summary>
        /// <param name="minX"></param>
        /// <param name="minY"></param>
        /// <param name="maxX"></param>
        /// <param name="maxY"></param>
        public virtual void RequestMapBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag)
        {
            if ((flag & 0x10000) != 0)  // user clicked on the map a tile that isn't visible
            {
                List<MapBlockData> response = new List<MapBlockData>();

                // this should return one mapblock at most. But make sure: Look whether the one we requested is in there
                List<MapBlockData> mapBlocks = m_scene.SceneGridService.RequestNeighbourMapBlocks(minX, minY, maxX, maxY);
                if (mapBlocks != null)
                {
                    foreach (MapBlockData block in mapBlocks)
                    {
                        if (block.X == minX && block.Y == minY)
                        {
                            // found it => add it to response
                            response.Add(block);
                            break;
                        }
                    }
                }

                if (response.Count == 0)
                {
                    // response still empty => couldn't find the map-tile the user clicked on => tell the client
                    MapBlockData block = new MapBlockData();
                    block.X = (ushort)minX;
                    block.Y = (ushort)minY;
                    block.Access = 254; // == not there
                    response.Add(block);
                }
                remoteClient.SendMapBlock(response, 0);
            }
            else
            {
                // normal mapblock request. Use the provided values
                GetAndSendBlocks(remoteClient, minX, minY, maxX, maxY, flag);
            }
        }
예제 #21
0
        private void OnMapNameRequest(IClientAPI remoteClient, string mapName)
        {
            if (mapName.Length < 3)
            {
                remoteClient.SendAlertMessage("Use a search string with at least 3 characters");
                return;
            }
            
            // try to fetch from GridServer
            List<GridRegion> regionInfos = m_scene.GridService.GetRegionsByName(UUID.Zero, mapName, 20);
            if (regionInfos == null)
            {
                m_log.Warn("[MAPSEARCHMODULE]: RequestNamedRegions returned null. Old gridserver?");
                // service wasn't available; maybe still an old GridServer. Try the old API, though it will return only one region
                regionInfos = new List<GridRegion>();
                GridRegion info = m_scene.GridService.GetRegionByName(UUID.Zero, mapName);
                if (info != null) regionInfos.Add(info);
            }

            List<MapBlockData> blocks = new List<MapBlockData>();

            MapBlockData data;
            if (regionInfos.Count > 0)
            {
                foreach (GridRegion info in regionInfos)
                {
                    data = new MapBlockData();
                    data.Agents = 0;
                    data.Access = info.Access;
                    data.MapImageID = info.TerrainImage;
                    data.Name = info.RegionName;
                    data.RegionFlags = 0;
                    data.WaterHeight = 0; // not used
                    data.X = (ushort)(info.RegionLocX / Constants.RegionSize);
                    data.Y = (ushort)(info.RegionLocY / Constants.RegionSize);
                    blocks.Add(data);
                }
            }

            // final block, closing the search result
            data = new MapBlockData();
            data.Agents = 0;
            data.Access = 255;
            data.MapImageID = UUID.Zero;
            data.Name = mapName;
            data.RegionFlags = 0;
            data.WaterHeight = 0; // not used
            data.X = 0;
            data.Y = 0;
            blocks.Add(data);

            remoteClient.SendMapBlock(blocks, 2);
        }
        private void OnMapNameRequest(IClientAPI remoteClient, string mapName)
        {
            if (mapName.Length < 3)
            {
                remoteClient.SendAlertMessage("Use a search string with at least 3 characters");
                return;
            }
            
            // try to fetch from GridServer
            List<GridRegion> regionInfos = m_scene.GridService.GetRegionsByName(m_scene.RegionInfo.ScopeID, mapName, 20);
            if (regionInfos == null)
            {
                m_log.Warn("[MAPSEARCHMODULE]: RequestNamedRegions returned null. Old gridserver?");
                // service wasn't available; maybe still an old GridServer. Try the old API, though it will return only one region
                regionInfos = new List<GridRegion>();
                GridRegion info = m_scene.GridService.GetRegionByName(m_scene.RegionInfo.ScopeID, mapName);
                if (info != null) 
                    regionInfos.Add(info);
            }
            else if (regionInfos.Count == 0 && mapName.StartsWith("http://"))
                remoteClient.SendAlertMessage("Hyperlink could not be established.");

            m_log.DebugFormat("[MAPSEARCHMODULE]: search {0} returned {1} regions", mapName, regionInfos.Count);
            List<MapBlockData> blocks = new List<MapBlockData>();

            MapBlockData data;
            if (regionInfos.Count > 0)
            {
                foreach (GridRegion info in regionInfos)
                {
                    data = new MapBlockData();
                    data.Agents = 0;
                    data.Access = info.Access;
                    data.MapImageId = UUID.Zero; // could use info.TerrainImage but it seems to break viewer2
                    data.Name = info.RegionName;
                    data.RegionFlags = 0; // TODO not used?
                    data.WaterHeight = 0; // not used
                    data.X = (ushort)(info.RegionLocX / Constants.RegionSize);
                    data.Y = (ushort)(info.RegionLocY / Constants.RegionSize);
                    blocks.Add(data);
                }
            }

            // final block, closing the search result
            data = new MapBlockData();
            data.Agents = 0;
            data.Access = 255;
            data.MapImageId = UUID.Zero;
            data.Name = ""; // mapName;
            data.RegionFlags = 0;
            data.WaterHeight = 0; // not used
            data.X = 0;
            data.Y = 0;
            blocks.Add(data);

            // not sure what the flags do here, but seems to be necessary
            // to set to "2" for viewer 2
            remoteClient.SendMapBlock(blocks, 2);
        }
예제 #23
0
파일: MapCAPS.cs 프로젝트: kow/Aurora-Sim
 protected MapBlockData TerrainBlockFromGridRegion(GridRegion r)
 {
     MapBlockData block = new MapBlockData();
     if (r == null)
     {
         block.Access = (byte)SimAccess.Down;
         block.MapImageID = UUID.Zero;
         return block;
     }
     block.Access = r.Access;
     block.MapImageID = r.TerrainMapImage;
     block.Name = r.RegionName;
     block.X = (ushort)(r.RegionLocX / Constants.RegionSize);
     block.Y = (ushort)(r.RegionLocY / Constants.RegionSize);
     return block;
 }
        /// <summary>
        /// Try to teleport an agent to a new region.
        /// </summary>
        /// <param name="remoteClient"></param>
        /// <param name="RegionHandle"></param>
        /// <param name="position"></param>
        /// <param name="lookAt"></param>
        /// <param name="flags"></param>
        public virtual void RequestTeleportToLocation(ScenePresence avatar, ulong regionHandle, Vector3 position,
                                                      Vector3 lookAt, uint teleportFlags)
        {
            if (!avatar.Scene.Permissions.CanTeleport(avatar.UUID))
                return;

            bool destRegionUp = true;

            IEventQueue eq = avatar.Scene.RequestModuleInterface<IEventQueue>();

            // Reset animations; the viewer does that in teleports.
            avatar.Animator.ResetAnimations();

            if (regionHandle == m_regionInfo.RegionHandle)
            {
                m_log.DebugFormat(
                    "[SCENE COMMUNICATION SERVICE]: RequestTeleportToLocation {0} within {1}",
                    position, m_regionInfo.RegionName);

                // Teleport within the same region
                if (IsOutsideRegion(avatar.Scene, position) || position.Z < 0)
                {
                    Vector3 emergencyPos = new Vector3(128, 128, 128);

                    m_log.WarnFormat(
                        "[SCENE COMMUNICATION SERVICE]: RequestTeleportToLocation() was given an illegal position of {0} for avatar {1}, {2}.  Substituting {3}",
                        position, avatar.Name, avatar.UUID, emergencyPos);
                    position = emergencyPos;
                }

                // TODO: Get proper AVG Height
                float localAVHeight = 1.56f;
                float posZLimit = 22;

                // TODO: Check other Scene HeightField
                if (position.X > 0 && position.X <= (int)Constants.RegionSize && position.Y > 0 && position.Y <=(int)Constants.RegionSize)
                {
                    posZLimit = (float) avatar.Scene.Heightmap[(int) position.X, (int) position.Y];
                }

                float newPosZ = posZLimit + localAVHeight;
                if (posZLimit >= (position.Z - (localAVHeight / 2)) && !(Single.IsInfinity(newPosZ) || Single.IsNaN(newPosZ)))
                {
                    position.Z = newPosZ;
                }

                // Only send this if the event queue is null
                if (eq == null)
                    avatar.ControllingClient.SendTeleportLocationStart();
                
                avatar.ControllingClient.SendLocalTeleport(position, lookAt, teleportFlags);
                avatar.Teleport(position);
            }
            else
            {
                uint x = 0, y = 0;
                Utils.LongToUInts(regionHandle, out x, out y);
                GridRegion reg = m_scene.GridService.GetRegionByPosition(m_scene.RegionInfo.ScopeID, (int)x, (int)y);

                if (reg != null)
                {
                    m_log.DebugFormat(
                        "[SCENE COMMUNICATION SERVICE]: RequestTeleportToLocation to {0} in {1}", 
                        position, reg.RegionName);
                    
                    if (eq == null)
                        avatar.ControllingClient.SendTeleportLocationStart();

                    // Let's do DNS resolution only once in this process, please!
                    // This may be a costly operation. The reg.ExternalEndPoint field is not a passive field,
                    // it's actually doing a lot of work.
                    IPEndPoint endPoint = reg.ExternalEndPoint;
                    if (endPoint.Address == null)
                    {
                        // Couldn't resolve the name. Can't TP, because the viewer wants IP addresses.
                        destRegionUp = false;
                    }

                    if (destRegionUp)
                    {
                        uint newRegionX = (uint)(reg.RegionHandle >> 40);
                        uint newRegionY = (((uint)(reg.RegionHandle)) >> 8);
                        uint oldRegionX = (uint)(m_regionInfo.RegionHandle >> 40);
                        uint oldRegionY = (((uint)(m_regionInfo.RegionHandle)) >> 8);

                        // Fixing a bug where teleporting while sitting results in the avatar ending up removed from
                        // both regions
                        if (avatar.ParentID != (uint)0)
                            avatar.StandUp();
                        
                        if (!avatar.ValidateAttachments())
                        {
                            avatar.ControllingClient.SendTeleportFailed("Inconsistent attachment state");
                            return;
                        }

                        // the avatar.Close below will clear the child region list. We need this below for (possibly)
                        // closing the child agents, so save it here (we need a copy as it is Clear()-ed).
                        //List<ulong> childRegions = new List<ulong>(avatar.GetKnownRegionList());
                        // Compared to ScenePresence.CrossToNewRegion(), there's no obvious code to handle a teleport
                        // failure at this point (unlike a border crossing failure).  So perhaps this can never fail
                        // once we reach here...
                        //avatar.Scene.RemoveCapsHandler(avatar.UUID);

                        string capsPath = String.Empty;
                        AgentCircuitData agentCircuit = avatar.ControllingClient.RequestClientInfo();
                        agentCircuit.BaseFolder = UUID.Zero;
                        agentCircuit.InventoryFolder = UUID.Zero;
                        agentCircuit.startpos = position;
                        agentCircuit.child = true;
                        
                        if (Util.IsOutsideView(oldRegionX, newRegionX, oldRegionY, newRegionY))
                        {
                            // brand new agent, let's create a new caps seed
                            agentCircuit.CapsPath = CapsUtil.GetRandomCapsObjectPath();
                        }

                        string reason = String.Empty;

                        // Let's create an agent there if one doesn't exist yet. 
                        //if (!m_commsProvider.InterRegion.InformRegionOfChildAgent(reg.RegionHandle, agentCircuit))
                        if (!m_interregionCommsOut.SendCreateChildAgent(reg.RegionHandle, agentCircuit, teleportFlags, out reason))
                        {
                            avatar.ControllingClient.SendTeleportFailed(String.Format("Destination is not accepting teleports: {0}",
                                                                                      reason));
                            return;
                        }

                        // OK, it got this agent. Let's close some child agents
                        avatar.CloseChildAgents(newRegionX, newRegionY);

                        if (Util.IsOutsideView(oldRegionX, newRegionX, oldRegionY, newRegionY))
                        {
                            #region IP Translation for NAT
                            IClientIPEndpoint ipepClient;
                            if (avatar.ClientView.TryGet(out ipepClient))
                            {
                                capsPath
                                    = "http://"
                                      + NetworkUtil.GetHostFor(ipepClient.EndPoint, reg.ExternalHostName)
                                      + ":"
                                      + reg.HttpPort
                                      + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath);
                            }
                            else
                            {
                                capsPath
                                    = "http://"
                                      + reg.ExternalHostName
                                      + ":"
                                      + reg.HttpPort
                                      + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath);
                            }
                            #endregion

                            if (eq != null)
                            {
                                #region IP Translation for NAT
                                // Uses ipepClient above
                                if (avatar.ClientView.TryGet(out ipepClient))
                                {
                                    endPoint.Address = NetworkUtil.GetIPFor(ipepClient.EndPoint, endPoint.Address);
                                }
                                #endregion

                                eq.EnableSimulator(reg.RegionHandle, endPoint, avatar.UUID);

                                // ES makes the client send a UseCircuitCode message to the destination, 
                                // which triggers a bunch of things there.
                                // So let's wait
                                Thread.Sleep(2000);

                                eq.EstablishAgentCommunication(avatar.UUID, endPoint, capsPath);
                            }
                            else
                            {
                                avatar.ControllingClient.InformClientOfNeighbour(reg.RegionHandle, endPoint);
                            }
                        }
                        else
                        {
                            agentCircuit.CapsPath = avatar.Scene.CapsModule.GetChildSeed(avatar.UUID, reg.RegionHandle);
                            capsPath = "http://" + reg.ExternalHostName + ":" + reg.HttpPort
                                        + "/CAPS/" + agentCircuit.CapsPath + "0000/";
                        }

                        // Expect avatar crossing is a heavy-duty function at the destination.
                        // That is where MakeRoot is called, which fetches appearance and inventory.
                        // Plus triggers OnMakeRoot, which spawns a series of asynchronous updates.
                        //m_commsProvider.InterRegion.ExpectAvatarCrossing(reg.RegionHandle, avatar.ControllingClient.AgentId,
                        //                                                      position, false);

                        //{
                        //    avatar.ControllingClient.SendTeleportFailed("Problem with destination.");
                        //    // We should close that agent we just created over at destination...
                        //    List<ulong> lst = new List<ulong>();
                        //    lst.Add(reg.RegionHandle);
                        //    SendCloseChildAgentAsync(avatar.UUID, lst);
                        //    return;
                        //}

                        SetInTransit(avatar.UUID);
                        // Let's send a full update of the agent. This is a synchronous call.
                        AgentData agent = new AgentData();
                        avatar.CopyTo(agent);
                        agent.Position = position;
                        agent.CallbackURI = "http://" + m_regionInfo.ExternalHostName + ":" + m_regionInfo.HttpPort + 
                            "/agent/" + avatar.UUID.ToString() + "/" + avatar.Scene.RegionInfo.RegionHandle.ToString() + "/release/";

                        m_interregionCommsOut.SendChildAgentUpdate(reg.RegionHandle, agent);

                        m_log.DebugFormat(
                            "[CAPS]: Sending new CAPS seed url {0} to client {1}", capsPath, avatar.UUID);

                        
                        if (eq != null)
                        {
                            eq.TeleportFinishEvent(reg.RegionHandle, 13, endPoint,
                                                   0, teleportFlags, capsPath, avatar.UUID);
                        }
                        else
                        {
                            avatar.ControllingClient.SendRegionTeleport(reg.RegionHandle, 13, endPoint, 4,
                                                                        teleportFlags, capsPath);
                        }

                        // TeleportFinish makes the client send CompleteMovementIntoRegion (at the destination), which
                        // trigers a whole shebang of things there, including MakeRoot. So let's wait for confirmation
                        // that the client contacted the destination before we send the attachments and close things here.
                        if (!WaitForCallback(avatar.UUID))
                        {
                            // Client never contacted destination. Let's restore everything back
                            avatar.ControllingClient.SendTeleportFailed("Problems connecting to destination.");

                            ResetFromTransit(avatar.UUID);
                            
                            // Yikes! We should just have a ref to scene here.
                            avatar.Scene.InformClientOfNeighbours(avatar);

                            // Finally, kill the agent we just created at the destination.
                            m_interregionCommsOut.SendCloseAgent(reg.RegionHandle, avatar.UUID);

                            return;
                        }

                        // Can't go back from here
                        if (KiPrimitive != null)
                        {
                            KiPrimitive(avatar.LocalId);
                        }

                        avatar.MakeChildAgent();

                        // CrossAttachmentsIntoNewRegion is a synchronous call. We shouldn't need to wait after it
                        avatar.CrossAttachmentsIntoNewRegion(reg.RegionHandle, true);

                        // Finally, let's close this previously-known-as-root agent, when the jump is outside the view zone

                        if (Util.IsOutsideView(oldRegionX, newRegionX, oldRegionY, newRegionY))
                        {
                            Thread.Sleep(5000);
                            avatar.Close();
                            CloseConnection(avatar.UUID);
                        }
                        else
                            // now we have a child agent in this region. 
                            avatar.Reset();


                        // if (teleport success) // seems to be always success here
                        // the user may change their profile information in other region,
                        // so the userinfo in UserProfileCache is not reliable any more, delete it
                        if (avatar.Scene.NeedSceneCacheClear(avatar.UUID))
                        {
                            m_commsProvider.UserProfileCacheService.RemoveUser(avatar.UUID);
                            m_log.DebugFormat(
                                "[SCENE COMMUNICATION SERVICE]: User {0} is going to another region, profile cache removed",
                                avatar.UUID);
                        }
                    }
                    else
                    {
                        avatar.ControllingClient.SendTeleportFailed("Remote Region appears to be down");
                    }
                }
                else
                {
                    // TP to a place that doesn't exist (anymore)
                    // Inform the viewer about that
                    avatar.ControllingClient.SendTeleportFailed("The region you tried to teleport to doesn't exist anymore");
                    
                    // and set the map-tile to '(Offline)'
                    uint regX, regY;
                    Utils.LongToUInts(regionHandle, out regX, out regY);
                    
                    MapBlockData block = new MapBlockData();
                    block.X = (ushort)(regX / Constants.RegionSize);
                    block.Y = (ushort)(regY / Constants.RegionSize);
                    block.Access = 254; // == not there
                    
                    List<MapBlockData> blocks = new List<MapBlockData>();
                    blocks.Add(block);
                    avatar.ControllingClient.SendMapBlock(blocks, 0);
                }
            }
        }
예제 #25
0
        /// <summary>
        /// Requests map blocks in area of minX, maxX, minY, MaxY in world cordinates
        /// </summary>
        /// <param name="minX"></param>
        /// <param name="minY"></param>
        /// <param name="maxX"></param>
        /// <param name="maxY"></param>
        public virtual void RequestMapBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag)
        {
            if ((flag & 0x10000) != 0)  // user clicked on the map a tile that isn't visible
            {
                List<MapBlockData> response = new List<MapBlockData>();

                // this should return one mapblock at most. 
                // (diva note: why?? in that case we should GetRegionByPosition)
                // But make sure: Look whether the one we requested is in there
                List<GridRegion> regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID,
                    minX * (int)Constants.RegionSize, 
                    maxX * (int)Constants.RegionSize, 
                    minY * (int)Constants.RegionSize, 
                    maxY * (int)Constants.RegionSize);

                if (regions != null)
                {
                    foreach (GridRegion r in regions)
                    {
                        if ((r.RegionLocX == minX * (int)Constants.RegionSize) && 
                            (r.RegionLocY == minY * (int)Constants.RegionSize))
                        {
                            // found it => add it to response
                            MapBlockData block = new MapBlockData();
                            MapBlockFromGridRegion(block, r);
                            response.Add(block);
                            break;
                        }
                    }
                }

                if (response.Count == 0)
                {
                    // response still empty => couldn't find the map-tile the user clicked on => tell the client
                    MapBlockData block = new MapBlockData();
                    block.X = (ushort)minX;
                    block.Y = (ushort)minY;
                    block.Access = 254; // == not there
                    response.Add(block);
                }
                remoteClient.SendMapBlock(response, 0);
            }
            else
            {
                // normal mapblock request. Use the provided values
                GetAndSendBlocks(remoteClient, minX, minY, maxX, maxY, flag);
            }
        }
예제 #26
0
        // Fill a passed MapBlockData from a GridRegion
        public 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;
            }
            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;
        }
예제 #27
0
 protected void MapBlockFromGridRegion(MapBlockData block, GridRegion r)
 {
     block.Access = r.Access;
     block.MapImageId = r.TerrainImage;
     block.Name = r.RegionName;
     block.X = (ushort)(r.RegionLocX / Constants.RegionSize);
     block.Y = (ushort)(r.RegionLocY / Constants.RegionSize);
 }
예제 #28
0
 public 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);
     }
     return blocks;
 }
        public void Teleport(ScenePresence sp, ulong regionHandle, Vector3 position, Vector3 lookAt, uint teleportFlags)
        {
            if (!sp.Scene.Permissions.CanTeleport(sp.UUID))
                return;

            IEventQueue eq = sp.Scene.RequestModuleInterface<IEventQueue>();

            // Reset animations; the viewer does that in teleports.
            sp.Animator.ResetAnimations();

            try
            {
                if (regionHandle == sp.Scene.RegionInfo.RegionHandle)
                {
                    m_log.DebugFormat(
                        "[ENTITY TRANSFER MODULE]: RequestTeleportToLocation {0} within {1}",
                        position, sp.Scene.RegionInfo.RegionName);

                    // Teleport within the same region
                    if (IsOutsideRegion(sp.Scene, position) || position.Z < 0)
                    {
                        Vector3 emergencyPos = new Vector3(128, 128, 128);

                        m_log.WarnFormat(
                            "[ENTITY TRANSFER MODULE]: RequestTeleportToLocation() was given an illegal position of {0} for avatar {1}, {2}.  Substituting {3}",
                            position, sp.Name, sp.UUID, emergencyPos);
                        position = emergencyPos;
                    }

                    // TODO: Get proper AVG Height
                    float localAVHeight = 1.56f;
                    float posZLimit = 22;

                    // TODO: Check other Scene HeightField
                    if (position.X > 0 && position.X <= (int)Constants.RegionSize && position.Y > 0 && position.Y <= (int)Constants.RegionSize)
                    {
                        posZLimit = (float)sp.Scene.Heightmap[(int)position.X, (int)position.Y];
                    }

                    float newPosZ = posZLimit + localAVHeight;
                    if (posZLimit >= (position.Z - (localAVHeight / 2)) && !(Single.IsInfinity(newPosZ) || Single.IsNaN(newPosZ)))
                    {
                        position.Z = newPosZ;
                    }

                    sp.ControllingClient.SendTeleportStart(teleportFlags);

                    sp.ControllingClient.SendLocalTeleport(position, lookAt, teleportFlags);
                    sp.Teleport(position);

                    foreach (SceneObjectGroup grp in sp.GetAttachments())
                    {
                        if (grp.IsDeleted)
                            sp.Scene.EventManager.TriggerOnScriptChangedEvent(grp.LocalId, (uint)Changed.TELEPORT);
                    }
                }
                else // Another region possibly in another simulator
                {
                    uint x = 0, y = 0;
                    Utils.LongToUInts(regionHandle, out x, out y);
                    GridRegion reg = m_aScene.GridService.GetRegionByPosition(sp.Scene.RegionInfo.ScopeID, (int)x, (int)y);

                    if (reg != null)
                    {
                        GridRegion finalDestination = GetFinalDestination(reg);
                        if (finalDestination == null)
                        {
                            m_log.WarnFormat("[ENTITY TRANSFER MODULE]: Final destination is having problems. Unable to teleport agent.");
                            sp.ControllingClient.SendTeleportFailed("Problem at destination");
                            return;
                        }

                        uint curX = 0, curY = 0;
                        Utils.LongToUInts(sp.Scene.RegionInfo.RegionHandle, out curX, out curY);
                        int curCellX = (int)(curX / Constants.RegionSize);
                        int curCellY = (int)(curY / Constants.RegionSize);
                        int destCellX = (int)(finalDestination.RegionLocX / Constants.RegionSize);
                        int destCellY = (int)(finalDestination.RegionLocY / Constants.RegionSize);

//                        m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Source co-ords are x={0} y={1}", curRegionX, curRegionY);
//
//                        m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Final dest is x={0} y={1} {2}@{3}",
//                            destRegionX, destRegionY, finalDestination.RegionID, finalDestination.ServerURI);

                        // Check that these are not the same coordinates
                        if (finalDestination.RegionLocX == sp.Scene.RegionInfo.RegionLocX &&
                            finalDestination.RegionLocY == sp.Scene.RegionInfo.RegionLocY)
                        {
                            // Can't do. Viewer crashes
                            sp.ControllingClient.SendTeleportFailed("Space warp! You would crash. Move to a different region and try again.");
                            return;
                        }

                        if (Math.Abs(curCellX - destCellX) > MaxTransferDistance || Math.Abs(curCellY - destCellY) > MaxTransferDistance)
                        {
                            sp.ControllingClient.SendTeleportFailed(
                                string.Format(
                                  "Can't teleport to {0} ({1},{2}) from {3} ({4},{5}), destination is more than {6} regions way",
                                  finalDestination.RegionName, destCellX, destCellY,
                                  sp.Scene.RegionInfo.RegionName, curCellX, curCellY,
                                  MaxTransferDistance));

                            return;
                        }

                        //
                        // This is it
                        //
                        DoTeleport(sp, reg, finalDestination, position, lookAt, teleportFlags, eq);
                        //
                        //
                        //
                    }
                    else
                    {
                        // TP to a place that doesn't exist (anymore)
                        // Inform the viewer about that
                        sp.ControllingClient.SendTeleportFailed("The region you tried to teleport to doesn't exist anymore");

                        // and set the map-tile to '(Offline)'
                        uint regX, regY;
                        Utils.LongToUInts(regionHandle, out regX, out regY);

                        MapBlockData block = new MapBlockData();
                        block.X = (ushort)(regX / Constants.RegionSize);
                        block.Y = (ushort)(regY / Constants.RegionSize);
                        block.Access = 254; // == not there

                        List<MapBlockData> blocks = new List<MapBlockData>();
                        blocks.Add(block);
                        sp.ControllingClient.SendMapBlock(blocks, 0);
                    }
                }
            }
            catch (Exception e)
            {
                m_log.WarnFormat("[ENTITY TRANSFER MODULE]: Exception on teleport: {0} {1}", e.Message, e.StackTrace);
                sp.ControllingClient.SendTeleportFailed("Internal error");
            }
        }
예제 #30
0
        /// <summary>
        /// Requests map blocks in area of minX, maxX, minY, MaxY in world cordinates
        /// </summary>
        /// <param name="minX"></param>
        /// <param name="minY"></param>
        /// <param name="maxX"></param>
        /// <param name="maxY"></param>
        public virtual void RequestMapBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag)
        {
            if ((flag & 0x10000) != 0)  // user clicked on qthe map a tile that isn't visible
            {
                List<MapBlockData> response = new List<MapBlockData>();

                // this should return one mapblock at most. It is triggered by a click
                // on an unloaded square.
                // But make sure: Look whether the one we requested is in there
                List<GridRegion> regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID,
                                    (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)
                    {
                        if (r.RegionLocX == Util.RegionToWorldLoc((uint)minX)
                            && r.RegionLocY == Util.RegionToWorldLoc((uint)minY) )
                        {
                            // found it => add it to response
                            // Version 2 viewers can handle the larger regions
                            if ((flag & 2) == 2)
                                response.AddRange(Map2BlockFromGridRegion(r, flag));
                            else
                                response.Add(MapBlockFromGridRegion(r, flag));
                            break;
                        }
                    }
                }

                if (response.Count == 0)
                {
                    // response still empty => couldn't find the map-tile the user clicked on => tell the client
                    MapBlockData block = new MapBlockData();
                    block.X = (ushort)minX;
                    block.Y = (ushort)minY;
                    block.Access = (byte)SimAccess.Down; // means 'simulator is offline'
                    // block.Access = (byte)SimAccess.NonExistent;
                    response.Add(block);
                }
                // The lower 16 bits are an unsigned int16
                remoteClient.SendMapBlock(response, flag & 0xffff);
            }
            else
            {
                // normal mapblock request. Use the provided values
                GetAndSendBlocks(remoteClient, minX, minY, maxX, maxY, flag);
            }
        }