Exemplo n.º 1
0
        public override async Task StateEntry()
        {
            await _avatar.TriggerOnTransitStageChanged(TransitStage.SendEstablishChildPresence, _avatar.RideOnPrims);

            SimpleRegionInfo destination = _avatar.TransitArgs.DestinationRegion;

            //do we have a presence on the destination?
            if (!_avatar.ScenePresence.RemotePresences.HasPresenceOnRegion(destination.RegionHandle))
            {
                //no, we need to establish a new presence
                Tuple <EstablishPresenceResult, string> result =
                    await _avatar.ScenePresence.RemotePresences.EstablishPresenceOnRegionLocked(destination, false, true);

                if (result.Item1 != EstablishPresenceResult.Success)
                {
                    //something broke
                    _avatar.ScenePresence.ControllingClient.SendAlertMessage(
                        "Unable to complete transfer to new region: " + result.Item2);

                    throw new SendAvatarException(
                              String.Format("Could not establish presence on remote region: {0}", result.Item2));
                }

                RollbackActions.Push(() => { _avatar.ScenePresence.RemotePresences.DropRemotePresenceLocked(destination, true).Wait(); });
            }

            AvatarRemotePresence remotePresence = null;

            _avatar.ScenePresence.RemotePresences.TryGetRemotePresenceLocked(destination.RegionHandle,
                                                                             (AvatarRemotePresence pres) =>
            {
                remotePresence = pres;
            }
                                                                             );

            if (remotePresence == null)
            {
                //something is horked
                throw new SendAvatarException(
                          String.Format("Presence could not be established on new region for {0}", _avatar.ScenePresence.Name));
            }

            //we have a presence now, we can send the child agent update
            await _avatar.TriggerOnTransitStageChanged(TransitStage.SendAvatarHandoff, _avatar.RideOnPrims);

            //the ChildAgentUpdate below will always stop attachment scripts to transmit their state
            //if anything from this point on fails, we need to start the scripts running again
            RollbackActions.Push(() =>
            {
                List <SceneObjectGroup> attachments = _avatar.ScenePresence.GetAttachments();
                foreach (var att in attachments)
                {
                    att.EndTransit(false);
                }
            }
                                 );

            // Invoke the agent2 entry point
            ChildAgentUpdate2Response rc = this.SendChildAgentUpdate2();

            switch (rc)
            {
            case ChildAgentUpdate2Response.Ok:
                break;      // continue normally

            case ChildAgentUpdate2Response.AccessDenied:
                throw new SendAvatarException(
                          String.Format("Region entry denied for {0}", _avatar.ScenePresence.Name));

            case ChildAgentUpdate2Response.MethodNotAvailalble:
                throw new SendAvatarException(
                          String.Format("Region change not available for {0}", _avatar.ScenePresence.Name));

            case ChildAgentUpdate2Response.Error:
            default:
                throw new SendAvatarException(
                          String.Format("Region change failed for {0}", _avatar.ScenePresence.Name));
            }

            //this avatar is now considered a child agent
            _avatar.ScenePresence.MakeChildAgent(_avatar.TransitArgs.DestinationRegion.RegionHandle);

            //if there is a failure, we will need to restore the user as a root agent
            Vector3 restorePos = _avatar.ScenePresence.AbsolutePosition;

            Util.ForceValidRegionXY(ref restorePos);

            RollbackActions.Push(() => { _avatar.ScenePresence.MakeRootAgent(restorePos); });

            //the user is ready to be transfered
            IEventQueue eq = _avatar.ScenePresence.Scene.RequestModuleInterface <IEventQueue>();

            bool eventWasQueued = false;

            switch (_avatar.TransitArgs.Type)
            {
            case TransitType.OutboundCrossing:
                eventWasQueued = eq.CrossRegion(_avatar.TransitArgs.DestinationRegion.RegionHandle,
                                                _avatar.TransitArgs.LocationInDestination,
                                                _avatar.ScenePresence.Velocity,
                                                _avatar.TransitArgs.DestinationRegion.ExternalEndPoint,
                                                remotePresence.PresenceInfo.FullCapsSeedURL,
                                                _avatar.ScenePresence.UUID,
                                                _avatar.ScenePresence.ControllingClient.SessionId);
                break;

            case TransitType.OutboundTeleport:
                eventWasQueued = eq.TeleportFinishEvent(_avatar.TransitArgs.DestinationRegion.RegionHandle,
                                                        13,
                                                        _avatar.TransitArgs.DestinationRegion.ExternalEndPoint,
                                                        4,
                                                        (uint)_avatar.TransitArgs.TeleportFlags,
                                                        remotePresence.PresenceInfo.FullCapsSeedURL,
                                                        _avatar.ScenePresence.UUID);
                break;

            default:
                throw new SendAvatarException(String.Format("Invalid transit type {0} for sending avatar {1}",
                                                            _avatar.TransitArgs.Type));
            }

            if (!eventWasQueued)
            {
                throw new SendAvatarException(String.Format("Unable to enqueue transfer event for {0}",
                                                            _avatar.ScenePresence.Name));
            }

            //wait for confirmation of avatar on the other side
            await _avatar.WaitForRelease();

            //matching endtransit for all attachments
            List <SceneObjectGroup> sentAttachments = _avatar.ScenePresence.GetAttachments();

            foreach (var att in sentAttachments)
            {
                att.EndTransit(true);
            }

            _avatar.ScenePresence.AttachmentsCrossedToNewRegion();

            //unsit the SP if appropriate
            if (_avatar.TransitArgs.RideOnPart != null)
            {
                _avatar.TransitArgs.RideOnPart.RemoveSeatedAvatar(_avatar.ScenePresence, false);
            }

            //this avatar is history.
            _avatar.ScenePresence.Reset(_avatar.TransitArgs.DestinationRegion);

            _avatar.ScenePresence.Scene.EventManager.TriggerAvatarLeavingRegion(_avatar.ScenePresence,
                                                                                _avatar.TransitArgs.DestinationRegion);
        }
Exemplo n.º 2
0
        private async Task<Tuple<EstablishPresenceResult, string>> DoEstablishPresenceOnRegion(SimpleRegionInfo region, AvatarRemotePresence initPresence)
        {
            Tuple<EstablishPresenceResult, string> establishResult;

            try
            {
                establishResult = await this.LaunchNewEstablishChildTask(initPresence, region);
            }
            catch (Exception e)
            {
                establishResult = new Tuple<EstablishPresenceResult, string>(EstablishPresenceResult.ErrorInformingRegion, e.Message);
            }

            bool failure = false;

            TryGetRemotePresenceLocked(region.RegionHandle, (AvatarRemotePresence presence) =>
            {
                //success, change the status of the task
                if (presence != null)
                {
                    if (establishResult.Item1 == EstablishPresenceResult.Success)
                    {
                        presence.State = RemotePresenceState.ViewerWait;
                    }
                    else
                    {
                        //failure contacting other region
                        _remotePresences.Remove(region.RegionHandle);
                        failure = true;
                    }
                }
                else
                {
                    failure = true;

                    //hmm, someone stole this presence from us
                    _log.ErrorFormat("[REMOTEPRESENCE]: Unable to update child presence established to {0} for {1}. Child presence missing.", establishResult, _sp.Name);
                    establishResult = Tuple.Create(EstablishPresenceResult.ConnectionAborted, "Connection was aborted");
                }
            });

            if (failure)
            {
                return establishResult;
            }

            //now we need to call out to the remote region to wait for the SP to be set up
            bool waitSuccess = await WaitForScenePresenceEstablished(region);

            Tuple<EstablishPresenceResult, string> result = null;

            TryGetRemotePresenceLocked(region.RegionHandle, (AvatarRemotePresence presence) =>
            {
                //success, change the status of the task
                if (presence != null)
                {
                    if (waitSuccess)
                    {
                        presence.State = RemotePresenceState.Established;
                        result = Tuple.Create(EstablishPresenceResult.Success, String.Empty);
                    }
                    else
                    {
                        //failure waiting for SP
                        _remotePresences.Remove(region.RegionHandle);
                        result = Tuple.Create(EstablishPresenceResult.ClientWaitTimeout, "Destination region never received a connection from the viewer");
                    }
                }
                else
                {
                    //hmm, someone stole this presence from us
                    _log.ErrorFormat("[REMOTEPRESENCE]: Unable to update child presence established to {0} for {1}. Child presence missing.", establishResult, _sp.Name);
                    result = Tuple.Create(EstablishPresenceResult.ConnectionAborted, "Connection was aborted");
                }
            });

            return result;
        }
Exemplo n.º 3
0
        private Task<Tuple<EstablishPresenceResult, string>> LaunchNewEstablishChildTask(AvatarRemotePresence presence, SimpleRegionInfo region)
        {
            AgentCircuitData agent = _sp.ControllingClient.RequestClientInfo();
            agent.BaseFolder = UUID.Zero;
            agent.InventoryFolder = UUID.Zero;
            agent.startpos = Scene.DEFAULT_CHILD_AGENT_POS;
            agent.child = true;
            agent.CapsPath = presence.PresenceInfo.CapsPath;

            return _scene.SceneGridService.EstablishChildConnectionToRegionAsync(_sp, agent, region);
        }
Exemplo n.º 4
0
        /// <summary>
        /// Attempts to establish a presence on the given region
        /// </summary>
        /// <param name="region">The region we want to establish a child presence on</param>
        /// <param name="forceReestablish">Whether to force a reestablishment even if we already think we have a remote presence</param>
        /// <param name="isFarPresence">Is this presence intentionally far away? Eg. The beginning of a remote teleport</param>
        /// <returns></returns>
        private async Task<Tuple<EstablishPresenceResult, string>> EstablishPresenceOnRegion(SimpleRegionInfo region, bool forceReestablish, bool isFarPresence)
        {
            Task<Tuple<EstablishPresenceResult, string>> establishTask = null;
            bool presenceExisted = false;

            //check if we already have or are waiting on an establish
            TryGetRemotePresenceLocked(region.RegionHandle, (AvatarRemotePresence presence) =>
            {
                if (presence != null && !forceReestablish)
                {
                    //we have a presence
                    //if it is established just return
                    if (presence.State == RemotePresenceState.Established)
                    {
                        presenceExisted = true;
                    }
                    else
                    {
                        //if not, we can await the existing callback
                        establishTask = presence.EstablishTask;
                    }
                }
                else
                {
                    //we have no presence and we're not waiting for a callback
                    //begin an async establish and await a callback

                    presence = new AvatarRemotePresence
                    {
                        PresenceInfo = new RemotePresenceInfo { RegionInfo = region, CapsPath = CapsUtil.GetRandomCapsObjectPath() },
                        IsFarPresence = isFarPresence,
                        State = RemotePresenceState.Establishing
                    };

                    if (_remotePresences.ContainsKey(region.RegionHandle))
                        _remotePresences.Remove(region.RegionHandle);
                    _remotePresences.Add(region.RegionHandle, presence);

                    establishTask = DoEstablishPresenceOnRegion(region, presence);
                    presence.EstablishTask = establishTask;
                }
            });

            //nothing to do, we're already established
            if (presenceExisted) return Tuple.Create(EstablishPresenceResult.Success, String.Empty);

            return await establishTask;
        }