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); }
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 Vector3 pos = _avatar.ScenePresence.AbsolutePosition; if (_avatar.TransitArgs.Type == TransitType.OutboundCrossing && _avatar.TransitArgs.RideOnGroup == null) { Vector3 backVel = -_avatar.ScenePresence.Velocity; RollbackActions.Push(() => { Vector3 newpos = pos + (backVel * 2.0f); // Check if "bounce back leaves region". If so, don't apply bounce. if (!Util.IsValidRegionXY(newpos)) newpos = pos; // just limit current pos to valid. 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 ready to leave the region if (!_avatar.ScenePresence.IsFullyInRegion) { // _avatar.ScenePresence.ControllingClient.SendAlertMessage("Can not move to a new region, until established in the current region"); throw new InvalidOperationException("An avatar can not begin transition to a new region until established in the current region"); } //assert that the dest region is available and this avatar has an established connection to that region 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 neighbor region while the connections are still being established"); } //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); }