try to make SOG crossings full async. Simplify some borders checking....
parent
fd79f75ba6
commit
4571e5bc3e
|
@ -3865,7 +3865,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
{
|
||||
SceneObjectPart part = (SceneObjectPart)update.Entity;
|
||||
|
||||
if (part.ParentGroup.IsDeleted)
|
||||
if (part.ParentGroup.IsDeleted || part.ParentGroup.inTransit)
|
||||
continue;
|
||||
|
||||
if (part.ParentGroup.IsAttachment)
|
||||
|
|
|
@ -1385,13 +1385,61 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
|||
|
||||
|
||||
#region Agent Crossings
|
||||
public GridRegion GetDestination(Scene scene, UUID agentID, Vector3 pos, out uint xDest, out uint yDest, out string version, out Vector3 newpos)
|
||||
|
||||
public bool checkAgentAccessToRegion(ScenePresence agent, GridRegion destiny, Vector3 position, out string version, out string reason)
|
||||
{
|
||||
string r = String.Empty;
|
||||
return GetDestination(scene, agentID, pos, out xDest, out yDest, out version, out newpos, out r);
|
||||
reason = String.Empty;
|
||||
version = String.Empty;
|
||||
|
||||
UUID agentID = agent.UUID;
|
||||
ulong destinyHandle = destiny.RegionHandle;
|
||||
|
||||
ExpiringCache<ulong, DateTime> r;
|
||||
DateTime banUntil;
|
||||
if (m_bannedRegions.TryGetValue(agentID, out r))
|
||||
{
|
||||
if (r.TryGetValue(destinyHandle, out banUntil))
|
||||
{
|
||||
if (DateTime.Now < banUntil)
|
||||
{
|
||||
reason = "Cannot connect to region";
|
||||
return false;
|
||||
}
|
||||
r.Remove(destinyHandle);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
r = null;
|
||||
}
|
||||
|
||||
Scene ascene = agent.Scene;
|
||||
|
||||
if (!ascene.SimulationService.QueryAccess(destiny, agentID, position, out version, out reason))
|
||||
{
|
||||
if (r == null)
|
||||
{
|
||||
r = new ExpiringCache<ulong, DateTime>();
|
||||
r.Add(destinyHandle, DateTime.Now + TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(30));
|
||||
|
||||
m_bannedRegions.Add(agentID, r, TimeSpan.FromSeconds(30));
|
||||
}
|
||||
else
|
||||
{
|
||||
r.Add(destinyHandle, DateTime.Now + TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(30));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public GridRegion GetDestination(Scene scene, UUID agentID, Vector3 pos, out uint xDest, out uint yDest, out string version, out Vector3 newpos, out string reason)
|
||||
public GridRegion GetDestination(Scene scene, UUID agentID, Vector3 pos, out string version, out Vector3 newpos)
|
||||
{
|
||||
string r = String.Empty;
|
||||
return GetDestination(scene, agentID, pos, out version, out newpos, out r);
|
||||
}
|
||||
|
||||
public GridRegion GetDestination(Scene scene, UUID agentID, Vector3 pos, out string version, out Vector3 newpos, out string reason)
|
||||
{
|
||||
version = String.Empty;
|
||||
reason = String.Empty;
|
||||
|
@ -1400,9 +1448,13 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
|||
// m_log.DebugFormat(
|
||||
// "[ENTITY TRANSFER MODULE]: Crossing agent {0} at pos {1} in {2}", agent.Name, pos, scene.Name);
|
||||
|
||||
uint neighbourx = scene.RegionInfo.RegionLocX;
|
||||
uint neighboury = scene.RegionInfo.RegionLocY;
|
||||
RegionInfo regInfo = scene.RegionInfo;
|
||||
|
||||
uint neighbourx = regInfo.RegionLocX;
|
||||
uint neighboury = regInfo.RegionLocY;
|
||||
const float boundaryDistance = 0.7f;
|
||||
|
||||
/*
|
||||
Vector3 northCross = new Vector3(0, boundaryDistance, 0);
|
||||
Vector3 southCross = new Vector3(0, -1 * boundaryDistance, 0);
|
||||
Vector3 eastCross = new Vector3(boundaryDistance, 0, 0);
|
||||
|
@ -1463,11 +1515,22 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
|||
|
||||
newpos.X = Util.Clamp(newpos.X, enterDistance, maxX);
|
||||
newpos.Y = Util.Clamp(newpos.Y, enterDistance, maxY);
|
||||
*/
|
||||
float regionSizeX = regInfo.RegionSizeX;
|
||||
float regionSizeY = regInfo.RegionSizeY;
|
||||
|
||||
xDest = neighbourx;
|
||||
yDest = neighboury;
|
||||
if (pos.X < boundaryDistance)
|
||||
neighbourx--;
|
||||
else if (pos.X > regionSizeX - boundaryDistance)
|
||||
neighbourx += (uint)(regionSizeX / Constants.RegionSize);
|
||||
|
||||
int x = (int)(neighbourx * Constants.RegionSize), y = (int)(neighboury * Constants.RegionSize);
|
||||
if (pos.Y < boundaryDistance)
|
||||
neighboury--;
|
||||
else if (pos.Y > regionSizeY - boundaryDistance)
|
||||
neighboury += (uint)(regionSizeY / Constants.RegionSize);
|
||||
|
||||
int x = (int)(neighbourx * Constants.RegionSize);
|
||||
int y = (int)(neighboury * Constants.RegionSize);
|
||||
|
||||
ulong neighbourHandle = Utils.UIntsToLong((uint)x, (uint)y);
|
||||
|
||||
|
@ -1489,6 +1552,28 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
|||
}
|
||||
|
||||
GridRegion neighbourRegion = scene.GridService.GetRegionByPosition(scene.RegionInfo.ScopeID, (int)x, (int)y);
|
||||
if (neighbourRegion == null)
|
||||
{
|
||||
reason = "";
|
||||
return null;
|
||||
}
|
||||
|
||||
float newRegionSizeX = neighbourRegion.RegionSizeX;
|
||||
float newRegionSizeY = neighbourRegion.RegionSizeY;
|
||||
|
||||
if (pos.X < boundaryDistance)
|
||||
newpos.X += newRegionSizeX;
|
||||
else if (pos.X > regionSizeX - boundaryDistance)
|
||||
newpos.X -= regionSizeX;
|
||||
|
||||
if (pos.Y < boundaryDistance)
|
||||
newpos.Y += newRegionSizeY;
|
||||
else if (pos.Y > regionSizeY - boundaryDistance)
|
||||
newpos.Y -= regionSizeY;
|
||||
|
||||
const float enterDistance = 0.5f;
|
||||
newpos.X = Util.Clamp(newpos.X, enterDistance, newRegionSizeX - enterDistance);
|
||||
newpos.Y = Util.Clamp(newpos.Y, enterDistance, newRegionSizeY - enterDistance);
|
||||
|
||||
if (!scene.SimulationService.QueryAccess(neighbourRegion, agentID, newpos, out version, out reason))
|
||||
{
|
||||
|
@ -1543,13 +1628,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
|||
|
||||
Vector3 pos = agent.AbsolutePosition + agent.Velocity;
|
||||
|
||||
GridRegion neighbourRegion = GetDestination(agent.Scene, agent.UUID, pos, out x, out y, out version, out newpos, out reason);
|
||||
GridRegion neighbourRegion = GetDestination(agent.Scene, agent.UUID, pos, out version, out newpos, out reason);
|
||||
if (neighbourRegion == null)
|
||||
{
|
||||
if (reason == String.Empty)
|
||||
if (reason != String.Empty)
|
||||
agent.ControllingClient.SendAlertMessage("Cannot cross to region");
|
||||
else
|
||||
agent.ControllingClient.SendAlertMessage("Cannot cross to region: " + reason);
|
||||
return agent;
|
||||
}
|
||||
|
||||
|
@ -2346,6 +2429,62 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
|||
|
||||
#region Object Transfers
|
||||
|
||||
public GridRegion GetObjectDestination(SceneObjectGroup grp, Vector3 targetPosition,out Vector3 newpos)
|
||||
{
|
||||
newpos = targetPosition;
|
||||
|
||||
Scene scene = grp.Scene;
|
||||
if (scene == null)
|
||||
return null;
|
||||
|
||||
RegionInfo srcRegionInfo = scene.RegionInfo;
|
||||
int neighbourx = (int)srcRegionInfo.RegionLocX;
|
||||
int neighboury = (int)srcRegionInfo.RegionLocY;
|
||||
float regionSizeX = srcRegionInfo.RegionSizeX;
|
||||
float regionSizeY = srcRegionInfo.RegionSizeY;
|
||||
|
||||
float edgeJitter = 0.2f;
|
||||
|
||||
if (targetPosition.X < edgeJitter)
|
||||
neighbourx--;
|
||||
else if (targetPosition.X > regionSizeX - edgeJitter)
|
||||
neighbourx += (int)(regionSizeX / Constants.RegionSize);
|
||||
|
||||
if (targetPosition.Y < edgeJitter)
|
||||
neighboury--;
|
||||
else if (targetPosition.Y > regionSizeY - edgeJitter)
|
||||
neighboury += (int)(regionSizeY / Constants.RegionSize);
|
||||
|
||||
int x = neighbourx * (int)Constants.RegionSize;
|
||||
int y = neighboury * (int)Constants.RegionSize;
|
||||
|
||||
GridRegion neighbourRegion = scene.GridService.GetRegionByPosition(scene.RegionInfo.ScopeID, (int)x, (int)y);
|
||||
if (neighbourRegion == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
float newRegionSizeX = neighbourRegion.RegionSizeX;
|
||||
float newRegionSizeY = neighbourRegion.RegionSizeY;
|
||||
|
||||
if (targetPosition.X < edgeJitter)
|
||||
newpos.X += newRegionSizeX;
|
||||
else if (targetPosition.X > regionSizeX - edgeJitter)
|
||||
newpos.X -= regionSizeX;
|
||||
|
||||
if (targetPosition.Y < edgeJitter)
|
||||
newpos.Y += newRegionSizeY;
|
||||
else if (targetPosition.Y > regionSizeY - edgeJitter)
|
||||
newpos.Y -= regionSizeY;
|
||||
|
||||
const float enterDistance = 0.2f;
|
||||
newpos.X = Util.Clamp(newpos.X, enterDistance, newRegionSizeX - enterDistance);
|
||||
newpos.Y = Util.Clamp(newpos.Y, enterDistance, newRegionSizeY - enterDistance);
|
||||
|
||||
return neighbourRegion;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Move the given scene object into a new region depending on which region its absolute position has moved
|
||||
/// into.
|
||||
|
@ -2365,23 +2504,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
|||
if (scene == null)
|
||||
return;
|
||||
|
||||
// http://wiki.secondlife.com/wiki/STATUS_DIE_AT_EDGE
|
||||
// DieAtEdge does NOT mean that objects can't cross regions.
|
||||
// It just means they die when they go off world, unless
|
||||
// RETURN_AT_EDGE is set.
|
||||
// if (grp.RootPart.DIE_AT_EDGE)
|
||||
// {
|
||||
// // We remove the object here
|
||||
// try
|
||||
// {
|
||||
// scene.DeleteSceneObject(grp, false);
|
||||
// }
|
||||
// catch (Exception)
|
||||
// {
|
||||
// m_log.Warn("[DATABASE]: exception when trying to remove the prim that crossed the border.");
|
||||
// }
|
||||
// return;
|
||||
// }
|
||||
|
||||
int thisx = (int)scene.RegionInfo.RegionLocX;
|
||||
int thisy = (int)scene.RegionInfo.RegionLocY;
|
||||
|
@ -2594,7 +2716,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
|||
/// true if the crossing itself was successful, false on failure
|
||||
/// FIMXE: we still return true if the crossing object was not successfully deleted from the originating region
|
||||
/// </returns>
|
||||
protected bool CrossPrimGroupIntoNewRegion(GridRegion destination, Vector3 newPosition, SceneObjectGroup grp, bool silent)
|
||||
public bool CrossPrimGroupIntoNewRegion(GridRegion destination, Vector3 newPosition, SceneObjectGroup grp, bool silent)
|
||||
{
|
||||
//m_log.Debug(" >>> CrossPrimGroupIntoNewRegion <<<");
|
||||
|
||||
|
|
|
@ -93,9 +93,11 @@ namespace OpenSim.Region.Framework.Interfaces
|
|||
|
||||
void EnableChildAgent(ScenePresence agent, GridRegion region);
|
||||
|
||||
GridRegion GetDestination(Scene scene, UUID agentID, Vector3 pos, out uint xDest, out uint yDest, out string version, out Vector3 newpos);
|
||||
|
||||
GridRegion GetDestination(Scene scene, UUID agentID, Vector3 pos, out string version, out Vector3 newpos);
|
||||
GridRegion GetObjectDestination(SceneObjectGroup grp, Vector3 targetPosition, out Vector3 newpos);
|
||||
bool checkAgentAccessToRegion(ScenePresence agent, GridRegion destiny, Vector3 position, out string version, out string reason);
|
||||
void Cross(SceneObjectGroup sog, Vector3 position, bool silent);
|
||||
bool CrossPrimGroupIntoNewRegion(GridRegion destination, Vector3 newPosition, SceneObjectGroup grp, bool silent);
|
||||
|
||||
ScenePresence CrossAgentToNewRegionAsync(ScenePresence agent, Vector3 pos, GridRegion neighbourRegion, bool isFlying, string version);
|
||||
|
||||
|
|
|
@ -516,6 +516,10 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
public uint ParentID;
|
||||
}
|
||||
|
||||
|
||||
public bool inTransit = false;
|
||||
public delegate SceneObjectGroup SOGCrossDelegate(SceneObjectGroup sog,Vector3 pos);
|
||||
|
||||
/// <summary>
|
||||
/// The absolute position of this scene object in the scene
|
||||
/// </summary>
|
||||
|
@ -525,8 +529,8 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
set
|
||||
{
|
||||
Vector3 val = value;
|
||||
|
||||
if (Scene != null)
|
||||
|
||||
if (Scene != null && !inTransit)
|
||||
{
|
||||
if (
|
||||
// (Scene.TestBorderCross(val - Vector3.UnitX, Cardinals.E)
|
||||
|
@ -543,130 +547,10 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
|| Scene.TestBorderCross(val, Cardinals.S))
|
||||
&& !IsAttachmentCheckFull() && (!Scene.LoadingPrims))
|
||||
{
|
||||
IEntityTransferModule entityTransfer = m_scene.RequestModuleInterface<IEntityTransferModule>();
|
||||
uint x = 0;
|
||||
uint y = 0;
|
||||
string version = String.Empty;
|
||||
Vector3 newpos = Vector3.Zero;
|
||||
OpenSim.Services.Interfaces.GridRegion destination = null;
|
||||
|
||||
if (m_rootPart.DIE_AT_EDGE || m_rootPart.RETURN_AT_EDGE)
|
||||
{
|
||||
// this should delete the grp in this case
|
||||
m_scene.CrossPrimGroupIntoNewRegion(val, this, true);
|
||||
// actually assume this sog was removed from simulation
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_rootPart.KeyframeMotion != null)
|
||||
m_rootPart.KeyframeMotion.StartCrossingCheck();
|
||||
|
||||
bool canCross = true;
|
||||
|
||||
foreach (ScenePresence av in m_linkedAvatars)
|
||||
{
|
||||
// We need to cross these agents. First, let's find
|
||||
// out if any of them can't cross for some reason.
|
||||
// We have to deny the crossing entirely if any
|
||||
// of them are banned. Alternatively, we could
|
||||
// unsit banned agents....
|
||||
|
||||
|
||||
// We set the avatar position as being the object
|
||||
// position to get the region to send to
|
||||
if ((destination = entityTransfer.GetDestination(m_scene, av.UUID, val, out x, out y, out version, out newpos)) == null)
|
||||
{
|
||||
canCross = false;
|
||||
break;
|
||||
}
|
||||
|
||||
m_log.DebugFormat("[SCENE OBJECT]: Avatar {0} needs to be crossed to {1}", av.Name, destination.RegionName);
|
||||
}
|
||||
|
||||
if (canCross)
|
||||
{
|
||||
// We unparent the SP quietly so that it won't
|
||||
// be made to stand up
|
||||
|
||||
List<avtocrossInfo> avsToCross = new List<avtocrossInfo>();
|
||||
|
||||
foreach (ScenePresence av in m_linkedAvatars)
|
||||
{
|
||||
avtocrossInfo avinfo = new avtocrossInfo();
|
||||
SceneObjectPart parentPart = m_scene.GetSceneObjectPart(av.ParentID);
|
||||
if (parentPart != null)
|
||||
av.ParentUUID = parentPart.UUID;
|
||||
|
||||
avinfo.av = av;
|
||||
avinfo.ParentID = av.ParentID;
|
||||
avsToCross.Add(avinfo);
|
||||
|
||||
av.PrevSitOffset = av.OffsetPosition;
|
||||
av.ParentID = 0;
|
||||
}
|
||||
|
||||
// m_linkedAvatars.Clear();
|
||||
m_scene.CrossPrimGroupIntoNewRegion(val, this, true);
|
||||
|
||||
// Normalize
|
||||
if (val.X >= Constants.RegionSize)
|
||||
val.X -= Constants.RegionSize;
|
||||
if (val.Y >= Constants.RegionSize)
|
||||
val.Y -= Constants.RegionSize;
|
||||
if (val.X < 0)
|
||||
val.X += Constants.RegionSize;
|
||||
if (val.Y < 0)
|
||||
val.Y += Constants.RegionSize;
|
||||
|
||||
// If it's deleted, crossing was successful
|
||||
if (IsDeleted)
|
||||
{
|
||||
// foreach (ScenePresence av in m_linkedAvatars)
|
||||
foreach (avtocrossInfo avinfo in avsToCross)
|
||||
{
|
||||
ScenePresence av = avinfo.av;
|
||||
if (!av.IsInTransit) // just in case...
|
||||
{
|
||||
m_log.DebugFormat("[SCENE OBJECT]: Crossing avatar {0} to {1}", av.Name, val);
|
||||
|
||||
av.IsInTransit = true;
|
||||
|
||||
CrossAgentToNewRegionDelegate d = entityTransfer.CrossAgentToNewRegionAsync;
|
||||
d.BeginInvoke(av, val, destination, av.Flying, version, CrossAgentToNewRegionCompleted, d);
|
||||
}
|
||||
else
|
||||
m_log.DebugFormat("[SCENE OBJECT]: Crossing avatar alreasy in transit {0} to {1}", av.Name, val);
|
||||
}
|
||||
avsToCross.Clear();
|
||||
return;
|
||||
}
|
||||
else // cross failed, put avas back ??
|
||||
{
|
||||
foreach (avtocrossInfo avinfo in avsToCross)
|
||||
{
|
||||
ScenePresence av = avinfo.av;
|
||||
av.ParentUUID = UUID.Zero;
|
||||
av.ParentID = avinfo.ParentID;
|
||||
// m_linkedAvatars.Add(av);
|
||||
}
|
||||
}
|
||||
avsToCross.Clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_rootPart.KeyframeMotion != null)
|
||||
m_rootPart.KeyframeMotion.CrossingFailure();
|
||||
|
||||
if (RootPart.PhysActor != null)
|
||||
{
|
||||
RootPart.PhysActor.CrossingFailure();
|
||||
}
|
||||
}
|
||||
Vector3 oldp = AbsolutePosition;
|
||||
val.X = Util.Clamp<float>(oldp.X, 0.5f, (float)Constants.RegionSize - 0.5f);
|
||||
val.Y = Util.Clamp<float>(oldp.Y, 0.5f, (float)Constants.RegionSize - 0.5f);
|
||||
// dont crash land StarShips
|
||||
// val.Z = Util.Clamp<float>(oldp.Z, 0.5f, 4096.0f);
|
||||
inTransit = true;
|
||||
SOGCrossDelegate d = CrossAsync;
|
||||
d.BeginInvoke(this, val, CrossAsyncCompleted, d);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -714,46 +598,197 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
part.TriggerScriptChangedEvent(Changed.POSITION);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
This seems not needed and should not be needed:
|
||||
sp absolute position depends on sit part absolute position fixed above.
|
||||
sp ParentPosition is not used anywhere.
|
||||
Since presence is sitting, viewer considers it 'linked' to root prim, so it will move/rotate it
|
||||
Sending a extra packet with avatar position is not only bandwidth waste, but may cause jitter in viewers due to UPD nature.
|
||||
|
||||
if (!m_dupeInProgress)
|
||||
{
|
||||
foreach (ScenePresence av in m_linkedAvatars)
|
||||
{
|
||||
SceneObjectPart p = m_scene.GetSceneObjectPart(av.ParentID);
|
||||
if (p != null && m_parts.TryGetValue(p.UUID, out p))
|
||||
{
|
||||
Vector3 offset = p.GetWorldPosition() - av.ParentPosition;
|
||||
av.AbsolutePosition += offset;
|
||||
// av.ParentPosition = p.GetWorldPosition(); //ParentPosition gets cleared by AbsolutePosition
|
||||
av.SendAvatarDataToAllAgents();
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
//if (m_rootPart.PhysActor != null)
|
||||
//{
|
||||
//m_rootPart.PhysActor.Position =
|
||||
//new PhysicsVector(m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y,
|
||||
//m_rootPart.GroupPosition.Z);
|
||||
//m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor);
|
||||
//}
|
||||
|
||||
if (Scene != null)
|
||||
Scene.EventManager.TriggerParcelPrimCountTainted();
|
||||
|
||||
Scene.EventManager.TriggerParcelPrimCountTainted();
|
||||
}
|
||||
}
|
||||
|
||||
public override Vector3 Velocity
|
||||
public SceneObjectGroup CrossAsync(SceneObjectGroup sog, Vector3 val)
|
||||
{
|
||||
get { return RootPart.Velocity; }
|
||||
set { RootPart.Velocity = value; }
|
||||
Scene sogScene = sog.m_scene;
|
||||
IEntityTransferModule entityTransfer = sogScene.RequestModuleInterface<IEntityTransferModule>();
|
||||
|
||||
Vector3 newpos = Vector3.Zero;
|
||||
OpenSim.Services.Interfaces.GridRegion destination = null;
|
||||
|
||||
if (sog.RootPart.DIE_AT_EDGE)
|
||||
{
|
||||
try
|
||||
{
|
||||
sogScene.DeleteSceneObject(sog, false);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
m_log.Warn("[SCENE]: exception when trying to remove the prim that crossed the border.");
|
||||
}
|
||||
return sog;
|
||||
}
|
||||
|
||||
if (sog.RootPart.RETURN_AT_EDGE)
|
||||
{
|
||||
// We remove the object here
|
||||
try
|
||||
{
|
||||
List<uint> localIDs = new List<uint>();
|
||||
localIDs.Add(sog.RootPart.LocalId);
|
||||
sogScene.AddReturn(sog.OwnerID, sog.Name, sog.AbsolutePosition,
|
||||
"Returned at region cross");
|
||||
sogScene.DeRezObjects(null, localIDs, UUID.Zero, DeRezAction.Return, UUID.Zero);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
m_log.Warn("[SCENE]: exception when trying to return the prim that crossed the border.");
|
||||
}
|
||||
return sog;
|
||||
}
|
||||
|
||||
if (sog.m_rootPart.KeyframeMotion != null)
|
||||
sog.m_rootPart.KeyframeMotion.StartCrossingCheck();
|
||||
|
||||
if (entityTransfer == null)
|
||||
return sog;
|
||||
|
||||
destination = entityTransfer.GetObjectDestination(sog, val, out newpos);
|
||||
if (destination == null)
|
||||
return sog;
|
||||
|
||||
if (sog.m_linkedAvatars.Count == 0)
|
||||
{
|
||||
entityTransfer.CrossPrimGroupIntoNewRegion(destination, newpos, sog, true);
|
||||
return sog;
|
||||
}
|
||||
|
||||
string reason = String.Empty;
|
||||
string version = String.Empty;
|
||||
|
||||
foreach (ScenePresence av in sog.m_linkedAvatars)
|
||||
{
|
||||
// We need to cross these agents. First, let's find
|
||||
// out if any of them can't cross for some reason.
|
||||
// We have to deny the crossing entirely if any
|
||||
// of them are banned. Alternatively, we could
|
||||
// unsit banned agents....
|
||||
|
||||
// We set the avatar position as being the object
|
||||
// position to get the region to send to
|
||||
if(!entityTransfer.checkAgentAccessToRegion(av, destination, newpos, out version, out reason))
|
||||
{
|
||||
return sog;
|
||||
}
|
||||
m_log.DebugFormat("[SCENE OBJECT]: Avatar {0} needs to be crossed to {1}", av.Name, destination.RegionName);
|
||||
}
|
||||
|
||||
// We unparent the SP quietly so that it won't
|
||||
// be made to stand up
|
||||
|
||||
List<avtocrossInfo> avsToCross = new List<avtocrossInfo>();
|
||||
|
||||
foreach (ScenePresence av in sog.m_linkedAvatars)
|
||||
{
|
||||
avtocrossInfo avinfo = new avtocrossInfo();
|
||||
SceneObjectPart parentPart = sogScene.GetSceneObjectPart(av.ParentID);
|
||||
if (parentPart != null)
|
||||
av.ParentUUID = parentPart.UUID;
|
||||
|
||||
avinfo.av = av;
|
||||
avinfo.ParentID = av.ParentID;
|
||||
avsToCross.Add(avinfo);
|
||||
|
||||
av.PrevSitOffset = av.OffsetPosition;
|
||||
av.ParentID = 0;
|
||||
}
|
||||
|
||||
if (entityTransfer.CrossPrimGroupIntoNewRegion(destination, newpos, sog, true))
|
||||
{
|
||||
foreach (avtocrossInfo avinfo in avsToCross)
|
||||
{
|
||||
ScenePresence av = avinfo.av;
|
||||
if (!av.IsInTransit) // just in case...
|
||||
{
|
||||
m_log.DebugFormat("[SCENE OBJECT]: Crossing avatar {0} to {1}", av.Name, val);
|
||||
|
||||
av.IsInTransit = true;
|
||||
|
||||
// CrossAgentToNewRegionDelegate d = entityTransfer.CrossAgentToNewRegionAsync;
|
||||
// d.BeginInvoke(av, val, destination, av.Flying, version, CrossAgentToNewRegionCompleted, d);
|
||||
entityTransfer.CrossAgentToNewRegionAsync(av, newpos, destination, av.Flying, version);
|
||||
if(av.IsChildAgent)
|
||||
{
|
||||
if (av.ParentUUID != UUID.Zero)
|
||||
{
|
||||
av.ClearControls();
|
||||
av.ParentPart = null;
|
||||
}
|
||||
}
|
||||
av.ParentUUID = UUID.Zero;
|
||||
// In any case
|
||||
av.IsInTransit = false;
|
||||
|
||||
m_log.DebugFormat("[SCENE OBJECT]: Crossing agent {0} {1} completed.", av.Firstname, av.Lastname);
|
||||
}
|
||||
else
|
||||
m_log.DebugFormat("[SCENE OBJECT]: Crossing avatar already in transit {0} to {1}", av.Name, val);
|
||||
}
|
||||
avsToCross.Clear();
|
||||
return sog;
|
||||
}
|
||||
else // cross failed, put avas back ??
|
||||
{
|
||||
foreach (avtocrossInfo avinfo in avsToCross)
|
||||
{
|
||||
ScenePresence av = avinfo.av;
|
||||
av.ParentUUID = UUID.Zero;
|
||||
av.ParentID = avinfo.ParentID;
|
||||
}
|
||||
}
|
||||
avsToCross.Clear();
|
||||
|
||||
return sog;
|
||||
}
|
||||
|
||||
public void CrossAsyncCompleted(IAsyncResult iar)
|
||||
{
|
||||
SOGCrossDelegate icon = (SOGCrossDelegate)iar.AsyncState;
|
||||
SceneObjectGroup sog = icon.EndInvoke(iar);
|
||||
|
||||
if (sog.IsDeleted)
|
||||
{
|
||||
sog.inTransit = false; // just in case...
|
||||
}
|
||||
else
|
||||
{
|
||||
SceneObjectPart rootp = sog.m_rootPart;
|
||||
Vector3 oldp = rootp.GroupPosition;
|
||||
oldp.X = Util.Clamp<float>(oldp.X, 0.5f, sog.m_scene.RegionInfo.RegionSizeX - 0.5f);
|
||||
oldp.Y = Util.Clamp<float>(oldp.Y, 0.5f, sog.m_scene.RegionInfo.RegionSizeY - 0.5f);
|
||||
rootp.GroupPosition = oldp;
|
||||
|
||||
SceneObjectPart[] parts = sog.m_parts.GetArray();
|
||||
|
||||
foreach (SceneObjectPart part in parts)
|
||||
{
|
||||
if (part != rootp)
|
||||
part.GroupPosition = oldp;
|
||||
}
|
||||
|
||||
foreach (ScenePresence av in sog.m_linkedAvatars)
|
||||
{
|
||||
av.sitSOGmoved();
|
||||
}
|
||||
|
||||
sog.Velocity = Vector3.Zero;
|
||||
|
||||
if (sog.m_rootPart.KeyframeMotion != null)
|
||||
sog.m_rootPart.KeyframeMotion.CrossingFailure();
|
||||
|
||||
if (sog.RootPart.PhysActor != null)
|
||||
{
|
||||
sog.RootPart.PhysActor.CrossingFailure();
|
||||
}
|
||||
|
||||
sog.inTransit = false;
|
||||
sog.ScheduleGroupForFullUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
private void CrossAgentToNewRegionCompleted(IAsyncResult iar)
|
||||
|
@ -784,6 +819,12 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
m_log.DebugFormat("[SCENE OBJECT]: Crossing agent {0} {1} completed.", agent.Firstname, agent.Lastname);
|
||||
}
|
||||
|
||||
public override Vector3 Velocity
|
||||
{
|
||||
get { return RootPart.Velocity; }
|
||||
set { RootPart.Velocity = value; }
|
||||
}
|
||||
|
||||
public override uint LocalId
|
||||
{
|
||||
get { return m_rootPart.LocalId; }
|
||||
|
@ -2620,7 +2661,7 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
// an object has been deleted from a scene before update was processed.
|
||||
// A more fundamental overhaul of the update mechanism is required to eliminate all
|
||||
// the race conditions.
|
||||
if (IsDeleted)
|
||||
if (IsDeleted || inTransit)
|
||||
return;
|
||||
|
||||
// Even temporary objects take part in physics (e.g. temp-on-rez bullets)
|
||||
|
@ -2736,7 +2777,7 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
/// </summary>
|
||||
public void SendGroupRootTerseUpdate()
|
||||
{
|
||||
if (IsDeleted)
|
||||
if (IsDeleted || inTransit)
|
||||
return;
|
||||
|
||||
RootPart.SendTerseUpdateToAllClients();
|
||||
|
@ -2755,7 +2796,7 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
/// </summary>
|
||||
public void SendGroupTerseUpdate()
|
||||
{
|
||||
if (IsDeleted)
|
||||
if (IsDeleted || inTransit)
|
||||
return;
|
||||
|
||||
if (IsAttachment)
|
||||
|
|
|
@ -1123,6 +1123,11 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
if (part == null)
|
||||
{
|
||||
m_log.ErrorFormat("[SCENE PRESENCE]: Can't find prim {0} to sit on", ParentUUID);
|
||||
ParentID = 0;
|
||||
ParentPart = null;
|
||||
PrevSitOffset = Vector3.Zero;
|
||||
ClearControls();
|
||||
IsLoggingIn = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1216,13 +1221,6 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
else
|
||||
AddToPhysicalScene(isFlying);
|
||||
|
||||
// XXX: This is to trigger any secondary teleport needed for a megaregion when the user has teleported to a
|
||||
// location outside the 'root region' (the south-west 256x256 corner). This is the earlist we can do it
|
||||
// since it requires a physics actor to be present. If it is left any later, then physics appears to reset
|
||||
// the value to a negative position which does not trigger the border cross.
|
||||
// This may not be the best location for this.
|
||||
CheckForBorderCrossing();
|
||||
|
||||
if (ForceFly)
|
||||
{
|
||||
Flying = true;
|
||||
|
@ -1231,12 +1229,18 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
{
|
||||
Flying = false;
|
||||
}
|
||||
}
|
||||
// Don't send an animation pack here, since on a region crossing this will sometimes cause a flying
|
||||
// avatar to return to the standing position in mid-air. On login it looks like this is being sent
|
||||
// elsewhere anyway
|
||||
// Animator.SendAnimPack();
|
||||
|
||||
// XXX: This is to trigger any secondary teleport needed for a megaregion when the user has teleported to a
|
||||
// location outside the 'root region' (the south-west 256x256 corner). This is the earlist we can do it
|
||||
// since it requires a physics actor to be present. If it is left any later, then physics appears to reset
|
||||
// the value to a negative position which does not trigger the border cross.
|
||||
// This may not be the best location for this.
|
||||
|
||||
|
||||
// its not
|
||||
// CheckForBorderCrossing();
|
||||
}
|
||||
|
||||
m_log.DebugFormat("[MakeRootAgent] position and physical: {0}ms", Util.EnvironmentTickCountSubtract(ts));
|
||||
m_scene.SwapRootAgentCount(false);
|
||||
|
||||
|
@ -2734,7 +2738,6 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
ParentID = 0;
|
||||
ParentPart = null;
|
||||
|
||||
|
||||
if (part.SitTargetAvatar == UUID)
|
||||
standRotation = standRotation * part.SitTargetOrientation;
|
||||
else
|
||||
|
@ -2761,12 +2764,6 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
|
||||
Vector3 standPos = sitPartWorldPosition + adjustmentForSitPose;
|
||||
|
||||
// m_log.DebugFormat(
|
||||
// "[SCENE PRESENCE]: Setting stand to pos {0}, (adjustmentForSitPosition {1}, adjustmentForSitPose {2}) rotation {3} for {4} in {5}",
|
||||
// standPos, adjustmentForSitPosition, adjustmentForSitPose, standRotation, Name, Scene.Name);
|
||||
|
||||
standPos.X = Util.Clamp<float>(standPos.X, 0.5f, (float)Constants.RegionSize - 0.5f);
|
||||
standPos.Y = Util.Clamp<float>(standPos.Y, 0.5f, (float)Constants.RegionSize - 0.5f);
|
||||
m_pos = standPos;
|
||||
}
|
||||
|
||||
|
@ -3308,6 +3305,8 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
|
||||
if (IsChildAgent == false)
|
||||
{
|
||||
CheckForBorderCrossing();
|
||||
|
||||
if (IsInTransit)
|
||||
return;
|
||||
|
||||
|
@ -3329,8 +3328,6 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
m_lastVelocity = Velocity;
|
||||
}
|
||||
|
||||
CheckForBorderCrossing();
|
||||
|
||||
CheckForSignificantMovement(); // sends update to the modules.
|
||||
}
|
||||
}
|
||||
|
@ -3847,7 +3844,7 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
protected void CheckForBorderCrossing()
|
||||
{
|
||||
// Check that we we are not a child
|
||||
if (IsChildAgent)
|
||||
if (IsChildAgent || IsInTransit)
|
||||
return;
|
||||
|
||||
// If we don't have a PhysActor, we can't cross anyway
|
||||
|
@ -3857,25 +3854,22 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
if (ParentID != 0 || PhysicsActor == null || ParentUUID != UUID.Zero)
|
||||
return;
|
||||
|
||||
if (IsInTransit)
|
||||
return;
|
||||
|
||||
Vector3 pos2 = AbsolutePosition;
|
||||
Vector3 vel = Velocity;
|
||||
int neighbor = 0;
|
||||
int[] fix = new int[2];
|
||||
|
||||
float timeStep = 0.1f;
|
||||
pos2.X = pos2.X + (vel.X * timeStep);
|
||||
pos2.Y = pos2.Y + (vel.Y * timeStep);
|
||||
pos2.Z = pos2.Z + (vel.Z * timeStep);
|
||||
|
||||
pos2.X += vel.X * timeStep;
|
||||
pos2.Y += vel.Y * timeStep;
|
||||
pos2.Z += vel.Z * timeStep;
|
||||
|
||||
// m_log.DebugFormat(
|
||||
// "[SCENE PRESENCE]: Testing border check for projected position {0} of {1} in {2}",
|
||||
// pos2, Name, Scene.Name);
|
||||
|
||||
/*
|
||||
// Checks if where it's headed exists a region
|
||||
int neighbor = 0;
|
||||
int[] fix = new int[2];
|
||||
|
||||
bool needsTransit = false;
|
||||
if (m_scene.TestBorderCross(pos2, Cardinals.W))
|
||||
{
|
||||
|
@ -3925,59 +3919,55 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
}
|
||||
|
||||
// Makes sure avatar does not end up outside region
|
||||
|
||||
if (neighbor <= 0)
|
||||
{
|
||||
if (needsTransit)
|
||||
{
|
||||
if (m_requestedSitTargetUUID == UUID.Zero)
|
||||
{
|
||||
bool isFlying = Flying;
|
||||
RemoveFromPhysicalScene();
|
||||
|
||||
Vector3 pos = AbsolutePosition;
|
||||
if (AbsolutePosition.X < 0)
|
||||
pos.X += Velocity.X * 2;
|
||||
else if (AbsolutePosition.X > Constants.RegionSize)
|
||||
pos.X -= Velocity.X * 2;
|
||||
if (AbsolutePosition.Y < 0)
|
||||
pos.Y += Velocity.Y * 2;
|
||||
else if (AbsolutePosition.Y > Constants.RegionSize)
|
||||
pos.Y -= Velocity.Y * 2;
|
||||
Velocity = Vector3.Zero;
|
||||
AbsolutePosition = pos;
|
||||
|
||||
// m_log.DebugFormat("[SCENE PRESENCE]: Prevented flyoff for {0} at {1}", Name, AbsolutePosition);
|
||||
|
||||
AddToPhysicalScene(isFlying);
|
||||
}
|
||||
CrossToNewRegionFail();
|
||||
}
|
||||
}
|
||||
else if (neighbor > 0)
|
||||
{
|
||||
if (!CrossToNewRegion())
|
||||
{
|
||||
if (m_requestedSitTargetUUID == UUID.Zero)
|
||||
{
|
||||
bool isFlying = Flying;
|
||||
RemoveFromPhysicalScene();
|
||||
|
||||
Vector3 pos = AbsolutePosition;
|
||||
if (AbsolutePosition.X < 0)
|
||||
pos.X += Velocity.X * 2;
|
||||
else if (AbsolutePosition.X > Constants.RegionSize)
|
||||
pos.X -= Velocity.X * 2;
|
||||
if (AbsolutePosition.Y < 0)
|
||||
pos.Y += Velocity.Y * 2;
|
||||
else if (AbsolutePosition.Y > Constants.RegionSize)
|
||||
pos.Y -= Velocity.Y * 2;
|
||||
Velocity = Vector3.Zero;
|
||||
AbsolutePosition = pos;
|
||||
|
||||
AddToPhysicalScene(isFlying);
|
||||
}
|
||||
CrossToNewRegionFail();
|
||||
}
|
||||
}
|
||||
*/
|
||||
bool needsTransit = false;
|
||||
|
||||
if (pos2.X < 0)
|
||||
needsTransit = true;
|
||||
else if (pos2.X > m_scene.RegionInfo.RegionSizeX)
|
||||
needsTransit = true;
|
||||
else if (pos2.Y < 0)
|
||||
needsTransit = true;
|
||||
else if (pos2.Y > m_scene.RegionInfo.RegionSizeY)
|
||||
needsTransit = true;
|
||||
|
||||
if (needsTransit)
|
||||
{
|
||||
if (!CrossToNewRegion() && m_requestedSitTargetUUID == UUID.Zero)
|
||||
{
|
||||
// we don't have entity transfer module
|
||||
Vector3 pos = AbsolutePosition;
|
||||
float px = pos.X;
|
||||
if (px < 0)
|
||||
pos.X += Velocity.X * 2;
|
||||
else if (px > m_scene.RegionInfo.RegionSizeX)
|
||||
pos.X -= Velocity.X * 2;
|
||||
|
||||
float py = pos.Y;
|
||||
if (py < 0)
|
||||
pos.Y += Velocity.Y * 2;
|
||||
else if (py > m_scene.RegionInfo.RegionSizeY)
|
||||
pos.Y -= Velocity.Y * 2;
|
||||
|
||||
Velocity = Vector3.Zero;
|
||||
AbsolutePosition = pos;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void CrossToNewRegionFail()
|
||||
|
@ -3988,14 +3978,18 @@ namespace OpenSim.Region.Framework.Scenes
|
|||
RemoveFromPhysicalScene();
|
||||
|
||||
Vector3 pos = AbsolutePosition;
|
||||
if (AbsolutePosition.X < 0)
|
||||
float px = pos.X;
|
||||
if (px < 0)
|
||||
pos.X += Velocity.X * 2;
|
||||
else if (AbsolutePosition.X > Constants.RegionSize)
|
||||
else if (px > m_scene.RegionInfo.RegionSizeX)
|
||||
pos.X -= Velocity.X * 2;
|
||||
if (AbsolutePosition.Y < 0)
|
||||
|
||||
float py = pos.Y;
|
||||
if (py < 0)
|
||||
pos.Y += Velocity.Y * 2;
|
||||
else if (AbsolutePosition.Y > Constants.RegionSize)
|
||||
else if (py > m_scene.RegionInfo.RegionSizeY)
|
||||
pos.Y -= Velocity.Y * 2;
|
||||
|
||||
Velocity = Vector3.Zero;
|
||||
AbsolutePosition = pos;
|
||||
|
||||
|
|
Loading…
Reference in New Issue