public bool Cross(ScenePresence agent, bool isFlying) { Scene scene = agent.Scene; Vector3 pos = agent.AbsolutePosition; Vector3 newpos = new Vector3(pos.X, pos.Y, pos.Z); uint neighbourx = scene.RegionInfo.RegionLocX; uint neighboury = scene.RegionInfo.RegionLocY; const float boundaryDistance = 1.7f; Vector3 northCross = new Vector3(0, boundaryDistance, 0); Vector3 southCross = new Vector3(0, -1 * boundaryDistance, 0); Vector3 eastCross = new Vector3(boundaryDistance, 0, 0); Vector3 westCross = new Vector3(-1 * boundaryDistance, 0, 0); // distance to edge that will trigger crossing // distance into new region to place avatar const float enterDistance = 0.5f; if (scene.TestBorderCross(pos + westCross, Cardinals.W)) { if (scene.TestBorderCross(pos + northCross, Cardinals.N)) { Border b = scene.GetCrossedBorder(pos + northCross, Cardinals.N); neighboury += (uint)(int)(b.BorderLine.Z / (int)Constants.RegionSize); } else if (scene.TestBorderCross(pos + southCross, Cardinals.S)) { Border b = scene.GetCrossedBorder(pos + southCross, Cardinals.S); if (b.TriggerRegionX == 0 && b.TriggerRegionY == 0) { neighboury--; newpos.Y = Constants.RegionSize - enterDistance; } else { agent.InTransit(); neighboury = b.TriggerRegionY; neighbourx = b.TriggerRegionX; Vector3 newposition = pos; newposition.X += (scene.RegionInfo.RegionLocX - neighbourx) * Constants.RegionSize; newposition.Y += (scene.RegionInfo.RegionLocY - neighboury) * Constants.RegionSize; agent.ControllingClient.SendAgentAlertMessage( String.Format("Moving you to region {0},{1}", neighbourx, neighboury), false); InformClientToInitateTeleportToLocation(agent, neighbourx, neighboury, newposition, scene); return true; } } Border ba = scene.GetCrossedBorder(pos + westCross, Cardinals.W); if (ba.TriggerRegionX == 0 && ba.TriggerRegionY == 0) { neighbourx--; newpos.X = Constants.RegionSize - enterDistance; } else { agent.InTransit(); neighboury = ba.TriggerRegionY; neighbourx = ba.TriggerRegionX; Vector3 newposition = pos; newposition.X += (scene.RegionInfo.RegionLocX - neighbourx) * Constants.RegionSize; newposition.Y += (scene.RegionInfo.RegionLocY - neighboury) * Constants.RegionSize; agent.ControllingClient.SendAgentAlertMessage( String.Format("Moving you to region {0},{1}", neighbourx, neighboury), false); InformClientToInitateTeleportToLocation(agent, neighbourx, neighboury, newposition, scene); return true; } } else if (scene.TestBorderCross(pos + eastCross, Cardinals.E)) { Border b = scene.GetCrossedBorder(pos + eastCross, Cardinals.E); neighbourx += (uint)(int)(b.BorderLine.Z / (int)Constants.RegionSize); newpos.X = enterDistance; if (scene.TestBorderCross(pos + southCross, Cardinals.S)) { Border ba = scene.GetCrossedBorder(pos + southCross, Cardinals.S); if (ba.TriggerRegionX == 0 && ba.TriggerRegionY == 0) { neighboury--; newpos.Y = Constants.RegionSize - enterDistance; } else { agent.InTransit(); neighboury = ba.TriggerRegionY; neighbourx = ba.TriggerRegionX; Vector3 newposition = pos; newposition.X += (scene.RegionInfo.RegionLocX - neighbourx) * Constants.RegionSize; newposition.Y += (scene.RegionInfo.RegionLocY - neighboury) * Constants.RegionSize; agent.ControllingClient.SendAgentAlertMessage( String.Format("Moving you to region {0},{1}", neighbourx, neighboury), false); InformClientToInitateTeleportToLocation(agent, neighbourx, neighboury, newposition, scene); return true; } } else if (scene.TestBorderCross(pos + northCross, Cardinals.N)) { Border c = scene.GetCrossedBorder(pos + northCross, Cardinals.N); neighboury += (uint)(int)(c.BorderLine.Z / (int)Constants.RegionSize); newpos.Y = enterDistance; } } else if (scene.TestBorderCross(pos + southCross, Cardinals.S)) { Border b = scene.GetCrossedBorder(pos + southCross, Cardinals.S); if (b.TriggerRegionX == 0 && b.TriggerRegionY == 0) { neighboury--; newpos.Y = Constants.RegionSize - enterDistance; } else { agent.InTransit(); neighboury = b.TriggerRegionY; neighbourx = b.TriggerRegionX; Vector3 newposition = pos; newposition.X += (scene.RegionInfo.RegionLocX - neighbourx) * Constants.RegionSize; newposition.Y += (scene.RegionInfo.RegionLocY - neighboury) * Constants.RegionSize; agent.ControllingClient.SendAgentAlertMessage( String.Format("Moving you to region {0},{1}", neighbourx, neighboury), false); InformClientToInitateTeleportToLocation(agent, neighbourx, neighboury, newposition, scene); return true; } } else if (scene.TestBorderCross(pos + northCross, Cardinals.N)) { Border b = scene.GetCrossedBorder(pos + northCross, Cardinals.N); neighboury += (uint)(int)(b.BorderLine.Z / (int)Constants.RegionSize); newpos.Y = enterDistance; } /* if (pos.X < boundaryDistance) //West { neighbourx--; newpos.X = Constants.RegionSize - enterDistance; } else if (pos.X > Constants.RegionSize - boundaryDistance) // East { neighbourx++; newpos.X = enterDistance; } if (pos.Y < boundaryDistance) // South { neighboury--; newpos.Y = Constants.RegionSize - enterDistance; } else if (pos.Y > Constants.RegionSize - boundaryDistance) // North { neighboury++; newpos.Y = enterDistance; } */ ulong neighbourHandle = Utils.UIntsToLong((uint)(neighbourx * Constants.RegionSize), (uint)(neighboury * Constants.RegionSize)); int x = (int)(neighbourx * Constants.RegionSize), y = (int)(neighboury * Constants.RegionSize); ExpiringCache<ulong, DateTime> r; DateTime banUntil; if (m_bannedRegions.TryGetValue(agent.ControllingClient.AgentId, out r)) { if (r.TryGetValue(neighbourHandle, out banUntil)) { if (DateTime.Now < banUntil) return false; r.Remove(neighbourHandle); } } else { r = null; } GridRegion neighbourRegion = scene.GridService.GetRegionByPosition(scene.RegionInfo.ScopeID, (int)x, (int)y); string reason; string version; if (!scene.SimulationService.QueryAccess(neighbourRegion, agent.ControllingClient.AgentId, newpos, out version, out reason)) { agent.ControllingClient.SendAlertMessage("Cannot region cross into banned parcel"); if (r == null) { r = new ExpiringCache<ulong, DateTime>(); r.Add(neighbourHandle, DateTime.Now + TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(15)); m_bannedRegions.Add(agent.ControllingClient.AgentId, r, TimeSpan.FromSeconds(45)); } else { r.Add(neighbourHandle, DateTime.Now + TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(15)); } return false; } agent.InTransit(); CrossAgentToNewRegionDelegate d = CrossAgentToNewRegionAsync; d.BeginInvoke(agent, newpos, neighbourx, neighboury, neighbourRegion, isFlying, version, CrossAgentToNewRegionCompleted, d); return true; }