Пример #1
0
        public override async Task StateEntry()
        {
            //no matter what happens at this point we want to make sure the avatar doesnt try to immediately recross should we have
            //a failure. bounce them off the border
            if (_avatar.TransitArgs.Type == TransitType.OutboundCrossing && _avatar.TransitArgs.RideOnGroup == null)
            {
                Vector3 backVel = -_avatar.ScenePresence.Velocity;
                RollbackActions.Push(() =>
                {
                    Vector3 newpos = _avatar.ScenePresence.AbsolutePosition + (backVel * 2.0f);
                    Util.ForceValidRegionXYZ(ref newpos);
                    _avatar.ScenePresence.AbsolutePosition = newpos;
                });
            }

            //assert that this avatar is fully in this region before beginning a send
            if (_avatar.ScenePresence.Connection.State != OpenSim.Framework.AvatarConnectionState.Established)
            {
                throw new InvalidOperationException("An avatar can not begin transition to a new region while already in transit");
            }

            //assert that this avatar is not currently establishing connections to other regions
            if (_avatar.ScenePresence.RemotePresences.HasConnectionsEstablishing())
            {
//                _avatar.ScenePresence.ControllingClient.SendAlertMessage("Can not move to a new region, connections are still being established");
                throw new InvalidOperationException("An avatar can not begin transition to a new region while connections are being established to neighbor regions");
            }

            //if we're riding on a prim, wait for the all clear before moving on
            if (_avatar.TransitArgs.RideOnPart != null)
            {
                bool success = await _avatar.WaitForRemoteObjectCreation();

                if (!success)
                {
                    _avatar.ScenePresence.ControllingClient.SendAlertMessage("Unable to create object in remote region");
                    throw new SendAvatarException("Remote object creation failed");
                }
            }

            //listeners to this event will stop all traffic and suspend physics for the avatar
            //there is nothing else we need to do in this state
            await _avatar.TriggerOnTransitStageChanged(TransitStage.SendBegin, _avatar.RideOnPrims);

            RollbackActions.Push(() =>
            {
                var task = _avatar.TriggerOnTransitStageChanged(TransitStage.SendError, _avatar.RideOnPrims);
                task.Wait();
            });

            var nextState = new SendAvatarState(_avatar, this);
            await _avatar.SetNewState(nextState);
        }
Пример #2
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);
        }