Merge branch 'master' into httptests
commit
18bcacdded
|
@ -26,6 +26,7 @@
|
|||
*/
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using System.Collections.Generic;
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Services.Interfaces;
|
||||
|
@ -37,54 +38,17 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
|
|||
{
|
||||
public class RegionInfoCache
|
||||
{
|
||||
private const double CACHE_EXPIRATION_SECONDS = 300.0; // 5 minutes
|
||||
private const double CACHE_EXPIRATION_SECONDS = 120; // 2 minutes opensim regions change a lot
|
||||
|
||||
// private static readonly ILog m_log =
|
||||
// LogManager.GetLogger(
|
||||
// MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
internal struct ScopedRegionUUID
|
||||
{
|
||||
public UUID m_scopeID;
|
||||
public UUID m_regionID;
|
||||
public ScopedRegionUUID(UUID scopeID, UUID regionID)
|
||||
{
|
||||
m_scopeID = scopeID;
|
||||
m_regionID = regionID;
|
||||
}
|
||||
}
|
||||
|
||||
internal struct ScopedRegionName
|
||||
{
|
||||
public UUID m_scopeID;
|
||||
public string m_name;
|
||||
public ScopedRegionName(UUID scopeID, string name)
|
||||
{
|
||||
m_scopeID = scopeID;
|
||||
m_name = name;
|
||||
}
|
||||
}
|
||||
|
||||
internal struct ScopedRegionPosition
|
||||
{
|
||||
public UUID m_scopeID;
|
||||
public ulong m_regionHandle;
|
||||
public ScopedRegionPosition(UUID scopeID, ulong handle)
|
||||
{
|
||||
m_scopeID = scopeID;
|
||||
m_regionHandle = handle;
|
||||
}
|
||||
}
|
||||
|
||||
private ExpiringCache<ScopedRegionUUID, GridRegion> m_UUIDCache;
|
||||
private ExpiringCache<ScopedRegionName, ScopedRegionUUID> m_NameCache;
|
||||
private ExpiringCache<ScopedRegionPosition, GridRegion> m_PositionCache;
|
||||
private RegionsExpiringCache m_Cache;
|
||||
|
||||
public RegionInfoCache()
|
||||
{
|
||||
m_UUIDCache = new ExpiringCache<ScopedRegionUUID, GridRegion>();
|
||||
m_NameCache = new ExpiringCache<ScopedRegionName, ScopedRegionUUID>();
|
||||
m_PositionCache = new ExpiringCache<ScopedRegionPosition, GridRegion>();
|
||||
m_Cache = new RegionsExpiringCache();
|
||||
}
|
||||
|
||||
public void Cache(GridRegion rinfo)
|
||||
|
@ -101,18 +65,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
|
|||
if (rinfo == null)
|
||||
return;
|
||||
|
||||
ScopedRegionUUID id = new ScopedRegionUUID(scopeID,regionID);
|
||||
|
||||
// Cache even null accounts
|
||||
m_UUIDCache.AddOrUpdate(id, rinfo, CACHE_EXPIRATION_SECONDS);
|
||||
if (rinfo != null)
|
||||
{
|
||||
ScopedRegionName name = new ScopedRegionName(scopeID,rinfo.RegionName);
|
||||
m_NameCache.AddOrUpdate(name, id, CACHE_EXPIRATION_SECONDS);
|
||||
|
||||
ScopedRegionPosition pos = new ScopedRegionPosition(scopeID, rinfo.RegionHandle);
|
||||
m_PositionCache.AddOrUpdate(pos, rinfo, CACHE_EXPIRATION_SECONDS);
|
||||
}
|
||||
m_Cache.AddOrUpdate(scopeID, rinfo, CACHE_EXPIRATION_SECONDS);
|
||||
}
|
||||
|
||||
public GridRegion Get(UUID scopeID, UUID regionID, out bool inCache)
|
||||
|
@ -120,8 +73,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
|
|||
inCache = false;
|
||||
|
||||
GridRegion rinfo = null;
|
||||
ScopedRegionUUID id = new ScopedRegionUUID(scopeID,regionID);
|
||||
if (m_UUIDCache.TryGetValue(id, out rinfo))
|
||||
if (m_Cache.TryGetValue(scopeID, regionID, out rinfo))
|
||||
{
|
||||
inCache = true;
|
||||
return rinfo;
|
||||
|
@ -135,8 +87,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
|
|||
inCache = false;
|
||||
|
||||
GridRegion rinfo = null;
|
||||
ScopedRegionPosition pos = new ScopedRegionPosition(scopeID, handle);
|
||||
if (m_PositionCache.TryGetValue(pos, out rinfo))
|
||||
if (m_Cache.TryGetValue(scopeID, handle, out rinfo))
|
||||
{
|
||||
inCache = true;
|
||||
return rinfo;
|
||||
|
@ -145,25 +96,450 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
|
|||
return null;
|
||||
}
|
||||
|
||||
|
||||
public GridRegion Get(UUID scopeID, string name, out bool inCache)
|
||||
{
|
||||
inCache = false;
|
||||
|
||||
ScopedRegionName sname = new ScopedRegionName(scopeID,name);
|
||||
|
||||
ScopedRegionUUID id;
|
||||
if (m_NameCache.TryGetValue(sname, out id))
|
||||
GridRegion rinfo = null;
|
||||
if (m_Cache.TryGetValue(scopeID, name, out rinfo))
|
||||
{
|
||||
GridRegion rinfo = null;
|
||||
if (m_UUIDCache.TryGetValue(id, out rinfo))
|
||||
{
|
||||
inCache = true;
|
||||
return rinfo;
|
||||
}
|
||||
inCache = true;
|
||||
return rinfo;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// following code partialy adapted from lib OpenMetaverse
|
||||
public class RegionKey : IComparable<RegionKey>
|
||||
{
|
||||
private UUID m_scopeID;
|
||||
private UUID m_RegionID;
|
||||
private DateTime m_expirationDate;
|
||||
|
||||
public RegionKey(UUID scopeID, UUID id)
|
||||
{
|
||||
m_scopeID = scopeID;
|
||||
m_RegionID = id;
|
||||
}
|
||||
|
||||
public UUID ScopeID
|
||||
{
|
||||
get { return m_scopeID; }
|
||||
}
|
||||
public DateTime ExpirationDate
|
||||
{
|
||||
get { return m_expirationDate; }
|
||||
set { m_expirationDate = value; }
|
||||
}
|
||||
|
||||
public int GetHaskCode()
|
||||
{
|
||||
int hash = m_scopeID.GetHashCode();
|
||||
hash += hash * 23 + m_RegionID.GetHashCode();
|
||||
return hash;
|
||||
}
|
||||
|
||||
public int CompareTo(RegionKey other)
|
||||
{
|
||||
return GetHashCode().CompareTo(other.GetHashCode());
|
||||
}
|
||||
}
|
||||
|
||||
public class RegionInfoByScope
|
||||
{
|
||||
private Dictionary<string, RegionKey> byname;
|
||||
private Dictionary<ulong, RegionKey> byhandle;
|
||||
|
||||
public RegionInfoByScope()
|
||||
{
|
||||
byname = new Dictionary<string, RegionKey>();
|
||||
byhandle = new Dictionary<ulong, RegionKey>();
|
||||
}
|
||||
|
||||
public RegionInfoByScope(GridRegion region, RegionKey key)
|
||||
{
|
||||
byname = new Dictionary<string, RegionKey>();
|
||||
byhandle = new Dictionary<ulong, RegionKey>();
|
||||
|
||||
byname[region.RegionName] = key;
|
||||
byhandle[region.RegionHandle] = key;
|
||||
}
|
||||
|
||||
public void AddRegion(GridRegion region, RegionKey key)
|
||||
{
|
||||
if(byname == null)
|
||||
byname = new Dictionary<string, RegionKey>();
|
||||
if(byhandle == null)
|
||||
byhandle = new Dictionary<ulong, RegionKey>();
|
||||
|
||||
byname[region.RegionName] = key;
|
||||
byhandle[region.RegionHandle] = key;
|
||||
}
|
||||
|
||||
public void RemoveRegion(GridRegion region)
|
||||
{
|
||||
if(byname != null)
|
||||
byname.Remove(region.RegionName);
|
||||
if(byhandle != null)
|
||||
byhandle.Remove(region.RegionHandle);
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
if(byname != null)
|
||||
byname.Clear();
|
||||
if(byhandle != null)
|
||||
byhandle.Clear();
|
||||
byname = null;
|
||||
byhandle = null;
|
||||
}
|
||||
|
||||
public RegionKey get(string name)
|
||||
{
|
||||
if(byname == null || !byname.ContainsKey(name))
|
||||
return null;
|
||||
return byname[name];
|
||||
}
|
||||
|
||||
public RegionKey get(ulong handle)
|
||||
{
|
||||
if(byhandle == null || !byhandle.ContainsKey(handle))
|
||||
return null;
|
||||
return byhandle[handle];
|
||||
}
|
||||
|
||||
public int Count()
|
||||
{
|
||||
if(byname == null)
|
||||
return 0;
|
||||
else
|
||||
return byname.Count;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class RegionsExpiringCache
|
||||
{
|
||||
const double CACHE_PURGE_HZ = 60;
|
||||
const int MAX_LOCK_WAIT = 5000; // milliseconds
|
||||
|
||||
/// <summary>For thread safety</summary>
|
||||
object syncRoot = new object();
|
||||
/// <summary>For thread safety</summary>
|
||||
object isPurging = new object();
|
||||
|
||||
Dictionary<RegionKey, GridRegion> timedStorage = new Dictionary<RegionKey, GridRegion>();
|
||||
Dictionary<UUID, RegionInfoByScope> InfobyScope = new Dictionary<UUID, RegionInfoByScope>();
|
||||
private System.Timers.Timer timer = new System.Timers.Timer(TimeSpan.FromSeconds(CACHE_PURGE_HZ).TotalMilliseconds);
|
||||
|
||||
public RegionsExpiringCache()
|
||||
{
|
||||
timer.Elapsed += PurgeCache;
|
||||
timer.Start();
|
||||
}
|
||||
|
||||
public bool Add(UUID scope, GridRegion region, double expirationSeconds)
|
||||
{
|
||||
if (!Monitor.TryEnter(syncRoot, MAX_LOCK_WAIT))
|
||||
throw new ApplicationException("Lock could not be acquired after " + MAX_LOCK_WAIT + "ms");
|
||||
|
||||
RegionKey key = new RegionKey(scope , region.RegionID);
|
||||
|
||||
try
|
||||
{
|
||||
if (timedStorage.ContainsKey(key))
|
||||
return false;
|
||||
|
||||
key.ExpirationDate = DateTime.UtcNow + TimeSpan.FromSeconds(expirationSeconds);
|
||||
timedStorage.Add(key, region);
|
||||
|
||||
RegionInfoByScope ris = null;
|
||||
if(!InfobyScope.TryGetValue(scope, out ris) || ris == null)
|
||||
{
|
||||
ris = new RegionInfoByScope(region, key);
|
||||
InfobyScope[scope] = ris;
|
||||
}
|
||||
else
|
||||
ris.AddRegion(region, key);
|
||||
|
||||
return true;
|
||||
}
|
||||
finally { Monitor.Exit(syncRoot);}
|
||||
}
|
||||
|
||||
public bool AddOrUpdate(UUID scope, GridRegion region, double expirationSeconds)
|
||||
{
|
||||
if (!Monitor.TryEnter(syncRoot, MAX_LOCK_WAIT))
|
||||
throw new ApplicationException("Lock could not be acquired after " + MAX_LOCK_WAIT + "ms");
|
||||
|
||||
try
|
||||
{
|
||||
RegionKey key = new RegionKey(scope, region.RegionID);
|
||||
key.ExpirationDate = DateTime.UtcNow + TimeSpan.FromSeconds(expirationSeconds);
|
||||
|
||||
if (timedStorage.ContainsKey(key))
|
||||
{
|
||||
timedStorage.Remove(key);
|
||||
timedStorage.Add(key, region);
|
||||
|
||||
if(!InfobyScope.ContainsKey(scope))
|
||||
{
|
||||
RegionInfoByScope ris = new RegionInfoByScope(region, key);
|
||||
InfobyScope[scope] = ris;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
timedStorage.Add(key, region);
|
||||
RegionInfoByScope ris = null;
|
||||
if(!InfobyScope.TryGetValue(scope, out ris) || ris == null)
|
||||
{
|
||||
ris = new RegionInfoByScope(region,key);
|
||||
InfobyScope[scope] = ris;
|
||||
}
|
||||
else
|
||||
ris.AddRegion(region,key);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
finally { Monitor.Exit(syncRoot); }
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
if (!Monitor.TryEnter(syncRoot, MAX_LOCK_WAIT))
|
||||
throw new ApplicationException("Lock could not be acquired after " + MAX_LOCK_WAIT + "ms");
|
||||
try
|
||||
{
|
||||
timedStorage.Clear();
|
||||
InfobyScope.Clear();
|
||||
}
|
||||
finally { Monitor.Exit(syncRoot); }
|
||||
}
|
||||
|
||||
public bool Contains(UUID scope, GridRegion region)
|
||||
{
|
||||
RegionKey key = new RegionKey(scope, region.RegionID);
|
||||
return Contains(key);
|
||||
}
|
||||
|
||||
public bool Contains(RegionKey key)
|
||||
{
|
||||
if (!Monitor.TryEnter(syncRoot, MAX_LOCK_WAIT))
|
||||
throw new ApplicationException("Lock could not be acquired after " + MAX_LOCK_WAIT + "ms");
|
||||
try
|
||||
{
|
||||
return timedStorage.ContainsKey(key);
|
||||
}
|
||||
finally { Monitor.Exit(syncRoot); }
|
||||
}
|
||||
|
||||
public int Count
|
||||
{
|
||||
get
|
||||
{
|
||||
return timedStorage.Count;
|
||||
}
|
||||
}
|
||||
|
||||
public bool Remove(UUID scope, GridRegion region)
|
||||
{
|
||||
RegionKey key = new RegionKey(scope, region.RegionID);
|
||||
|
||||
if (!Monitor.TryEnter(syncRoot, MAX_LOCK_WAIT))
|
||||
throw new ApplicationException("Lock could not be acquired after " + MAX_LOCK_WAIT + "ms");
|
||||
try
|
||||
{
|
||||
if (timedStorage.ContainsKey(key))
|
||||
{
|
||||
RegionInfoByScope ris = null;
|
||||
if(InfobyScope.TryGetValue(scope, out ris) && ris != null)
|
||||
{
|
||||
GridRegion r = timedStorage[key];
|
||||
if(r != null)
|
||||
ris.RemoveRegion(r);
|
||||
if(ris.Count() == 0)
|
||||
InfobyScope.Remove(scope);
|
||||
}
|
||||
timedStorage.Remove(key);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
finally { Monitor.Exit(syncRoot); }
|
||||
}
|
||||
|
||||
public bool TryGetValue(RegionKey key, out GridRegion value)
|
||||
{
|
||||
if (!Monitor.TryEnter(syncRoot, MAX_LOCK_WAIT))
|
||||
throw new ApplicationException("Lock could not be acquired after " + MAX_LOCK_WAIT + "ms");
|
||||
try
|
||||
{
|
||||
if (timedStorage.ContainsKey(key))
|
||||
{
|
||||
value = timedStorage[key];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
finally { Monitor.Exit(syncRoot); }
|
||||
|
||||
value = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool TryGetValue(UUID scope, UUID id, out GridRegion value)
|
||||
{
|
||||
if (!Monitor.TryEnter(syncRoot, MAX_LOCK_WAIT))
|
||||
throw new ApplicationException("Lock could not be acquired after " + MAX_LOCK_WAIT + "ms");
|
||||
try
|
||||
{
|
||||
RegionKey rk = new RegionKey(scope, id);
|
||||
if(timedStorage.ContainsKey(rk))
|
||||
{
|
||||
value = timedStorage[rk];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
finally { Monitor.Exit(syncRoot); }
|
||||
|
||||
value = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool TryGetValue(UUID scope, string name, out GridRegion value)
|
||||
{
|
||||
if (!Monitor.TryEnter(syncRoot, MAX_LOCK_WAIT))
|
||||
throw new ApplicationException("Lock could not be acquired after " + MAX_LOCK_WAIT + "ms");
|
||||
try
|
||||
{
|
||||
value = null;
|
||||
RegionInfoByScope ris = null;
|
||||
if(!InfobyScope.TryGetValue(scope, out ris) || ris == null)
|
||||
return false;
|
||||
|
||||
RegionKey key = ris.get(name);
|
||||
if(key == null)
|
||||
return false;
|
||||
|
||||
if(timedStorage.ContainsKey(key))
|
||||
{
|
||||
value = timedStorage[key];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
finally { Monitor.Exit(syncRoot); }
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool TryGetValue(UUID scope, ulong handle, out GridRegion value)
|
||||
{
|
||||
if (!Monitor.TryEnter(syncRoot, MAX_LOCK_WAIT))
|
||||
throw new ApplicationException("Lock could not be acquired after " + MAX_LOCK_WAIT + "ms");
|
||||
try
|
||||
{
|
||||
value = null;
|
||||
RegionInfoByScope ris = null;
|
||||
if(!InfobyScope.TryGetValue(scope, out ris) || ris == null)
|
||||
return false;
|
||||
|
||||
RegionKey key = ris.get(handle);
|
||||
if(key == null)
|
||||
return false;
|
||||
|
||||
if(timedStorage.ContainsKey(key))
|
||||
{
|
||||
value = timedStorage[key];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
finally { Monitor.Exit(syncRoot); }
|
||||
|
||||
value = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool Update(UUID scope, GridRegion region, double expirationSeconds)
|
||||
{
|
||||
if (!Monitor.TryEnter(syncRoot, MAX_LOCK_WAIT))
|
||||
throw new ApplicationException("Lock could not be acquired after " + MAX_LOCK_WAIT + "ms");
|
||||
|
||||
RegionKey key = new RegionKey(scope, region.RegionID);
|
||||
try
|
||||
{
|
||||
if (!timedStorage.ContainsKey(key))
|
||||
return false;
|
||||
|
||||
timedStorage.Remove(key);
|
||||
key.ExpirationDate = DateTime.UtcNow + TimeSpan.FromSeconds(expirationSeconds);
|
||||
timedStorage.Add(key, region);
|
||||
return true;
|
||||
}
|
||||
finally { Monitor.Exit(syncRoot); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Purges expired objects from the cache. Called automatically by the purge timer.
|
||||
/// </summary>
|
||||
private void PurgeCache(object sender, System.Timers.ElapsedEventArgs e)
|
||||
{
|
||||
// Only let one thread purge at once - a buildup could cause a crash
|
||||
// This could cause the purge to be delayed while there are lots of read/write ops
|
||||
// happening on the cache
|
||||
if (!Monitor.TryEnter(isPurging))
|
||||
return;
|
||||
|
||||
DateTime signalTime = DateTime.UtcNow;
|
||||
|
||||
try
|
||||
{
|
||||
// If we fail to acquire a lock on the synchronization root after MAX_LOCK_WAIT, skip this purge cycle
|
||||
if (!Monitor.TryEnter(syncRoot, MAX_LOCK_WAIT))
|
||||
return;
|
||||
try
|
||||
{
|
||||
OpenMetaverse.Lazy<List<object>> expiredItems = new OpenMetaverse.Lazy<List<object>>();
|
||||
|
||||
foreach (RegionKey timedKey in timedStorage.Keys)
|
||||
{
|
||||
if (timedKey.ExpirationDate < signalTime)
|
||||
{
|
||||
// Mark the object for purge
|
||||
expiredItems.Value.Add(timedKey);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
RegionInfoByScope ris;
|
||||
if (expiredItems.IsValueCreated)
|
||||
{
|
||||
foreach (RegionKey key in expiredItems.Value)
|
||||
{
|
||||
ris = null;
|
||||
if(InfobyScope.TryGetValue(key.ScopeID, out ris) && ris != null)
|
||||
{
|
||||
GridRegion r = timedStorage[key];
|
||||
if(r != null)
|
||||
ris.RemoveRegion(r);
|
||||
|
||||
if(ris.Count() == 0)
|
||||
InfobyScope.Remove(key.ScopeID);
|
||||
}
|
||||
timedStorage.Remove(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
finally { Monitor.Exit(syncRoot); }
|
||||
}
|
||||
finally { Monitor.Exit(isPurging); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6394,64 +6394,61 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
|||
{
|
||||
m_host.AddScriptLPS(1);
|
||||
|
||||
// edge will be used to pass the Region Coordinates offset
|
||||
// we want to check for a neighboring sim
|
||||
LSL_Vector edge = new LSL_Vector(0, 0, 0);
|
||||
if(dir.x == 0.0 && dir.y == 0.0)
|
||||
return 1; // SL wiki
|
||||
|
||||
float rsx = World.RegionInfo.RegionSizeX;
|
||||
float rsy = World.RegionInfo.RegionSizeY;
|
||||
|
||||
// can understand what sl does if position is not in region, so do something :)
|
||||
float px = (float)Util.Clamp(pos.x, 0.5, rsx - 0.5);
|
||||
float py = (float)Util.Clamp(pos.y, 0.5, rsy - 0.5);
|
||||
|
||||
float ex, ey;
|
||||
|
||||
if (dir.x == 0)
|
||||
{
|
||||
if (dir.y == 0)
|
||||
{
|
||||
// Direction vector is 0,0 so return
|
||||
// false since we're staying in the sim
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Y is the only valid direction
|
||||
edge.y = dir.y / Math.Abs(dir.y) * (World.RegionInfo.RegionSizeY / Constants.RegionSize);
|
||||
}
|
||||
ex = px;
|
||||
ey = dir.y > 0.0 ? rsy + 1.0f : -1.0f;
|
||||
}
|
||||
else if(dir.y == 0.0f)
|
||||
{
|
||||
ex = dir.x > 0 ? rsx + 1.0f : -1.0f;
|
||||
ey = py;
|
||||
}
|
||||
else
|
||||
{
|
||||
LSL_Float mag;
|
||||
if (dir.x > 0)
|
||||
{
|
||||
mag = (World.RegionInfo.RegionSizeX - pos.x) / dir.x;
|
||||
}
|
||||
float dx = (float) dir.x;
|
||||
float dy = (float) dir.y;
|
||||
|
||||
float t1 = dx * dx + dy * dy;
|
||||
dx /= t1;
|
||||
dy /= t1;
|
||||
|
||||
if(dx > 0)
|
||||
t1 = (rsx + 1f - px)/dx;
|
||||
else
|
||||
{
|
||||
mag = (pos.x/dir.x);
|
||||
}
|
||||
t1 = -(px + 1f)/dx;
|
||||
|
||||
mag = Math.Abs(mag);
|
||||
|
||||
edge.y = pos.y + (dir.y * mag);
|
||||
|
||||
if (edge.y > World.RegionInfo.RegionSizeY || edge.y < 0)
|
||||
{
|
||||
// Y goes out of bounds first
|
||||
edge.y = dir.y / Math.Abs(dir.y) * (World.RegionInfo.RegionSizeY / Constants.RegionSize);
|
||||
}
|
||||
float t2;
|
||||
if(dy > 0)
|
||||
t2 = (rsy + 1f - py)/dy;
|
||||
else
|
||||
{
|
||||
// X goes out of bounds first or its a corner exit
|
||||
edge.y = 0;
|
||||
edge.x = dir.x / Math.Abs(dir.x) * (World.RegionInfo.RegionSizeY / Constants.RegionSize);
|
||||
}
|
||||
t2 = -(py + 1f)/dy;
|
||||
|
||||
if(t1 > t2)
|
||||
t1 = t2;
|
||||
|
||||
ex = px + t1 * dx;
|
||||
ey = py + t1 * dy;
|
||||
}
|
||||
|
||||
List<GridRegion> neighbors = World.GridService.GetNeighbours(World.RegionInfo.ScopeID, World.RegionInfo.RegionID);
|
||||
|
||||
uint neighborX = World.RegionInfo.RegionLocX + (uint)edge.x;
|
||||
uint neighborY = World.RegionInfo.RegionLocY + (uint)edge.y;
|
||||
|
||||
foreach (GridRegion sri in neighbors)
|
||||
{
|
||||
if (sri.RegionCoordX == neighborX && sri.RegionCoordY == neighborY)
|
||||
return 0;
|
||||
}
|
||||
ex += World.RegionInfo.WorldLocX;
|
||||
ey += World.RegionInfo.WorldLocY;
|
||||
|
||||
if(World.GridService.GetRegionByPosition(World.RegionInfo.ScopeID, (int)ex, (int)ey) != null)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue