/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSim Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Threading;
using OpenMetaverse;
using log4net;
using OpenSim.Framework;
using OpenSim.Framework.Communications.Cache;
using OpenSim.Region.Environment.Interfaces;
namespace OpenSim.Region.Environment.Scenes
{
public abstract class SceneBase : IScene
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
#region Events
public event restart OnRestart;
#endregion
#region Fields
///
/// The last allocated local prim id. When a new local id is requested, the next number in the sequence is
/// dispensed.
///
protected uint m_lastAllocatedLocalId = 720000;
private readonly Mutex _primAllocateMutex = new Mutex(false);
private readonly ClientManager m_clientManager = new ClientManager();
public ClientManager ClientManager
{
get { return m_clientManager; }
}
protected ulong m_regionHandle;
protected string m_regionName;
protected RegionInfo m_regInfo;
//public TerrainEngine Terrain;
public ITerrainChannel Heightmap;
///
/// Allows retrieval of land information for this scene.
///
public ILandChannel LandChannel;
///
/// Manage events that occur in this scene (avatar movement, script rez, etc.). Commonly used by region modules
/// to subscribe to scene events.
///
public EventManager EventManager
{
get { return m_eventManager; }
}
protected EventManager m_eventManager;
protected ScenePermissions m_permissions;
public ScenePermissions Permissions
{
get { return m_permissions; }
}
protected string m_datastore;
private AssetCache m_assetCache;
public AssetCache AssetCache
{
get { return m_assetCache; }
set { m_assetCache = value; }
}
protected RegionStatus m_regStatus;
public RegionStatus Region_Status
{
get { return m_regStatus; }
set { m_regStatus = value; }
}
#endregion
#region Update Methods
///
/// Normally called once every frame/tick to let the world preform anything required (like running the physics simulation)
///
public abstract void Update();
#endregion
#region Terrain Methods
///
/// Loads the World heightmap
///
public abstract void LoadWorldMap();
///
/// Send the region heightmap to the client
///
/// Client to send to
public virtual void SendLayerData(IClientAPI RemoteClient)
{
RemoteClient.SendLayerData(Heightmap.GetFloatsSerialised());
}
#endregion
#region Add/Remove Agent/Avatar
///
/// Register the new client with the scene. The client starts off as a child agent - the later agent crossing
/// will promote it to a root agent during login.
///
///
/// Remove a client from the scene
///
///
public abstract void RemoveClient(UUID agentID);
public abstract void CloseAllAgents(uint circuitcode);
#endregion
///
///
///
///
public virtual RegionInfo RegionInfo
{
get { return m_regInfo; }
}
#region admin stuff
///
/// Region Restart - Seconds till restart.
///
///
public virtual void Restart(int seconds)
{
m_log.Error("[REGION]: passing Restart Message up the namespace");
restart handlerPhysicsCrash = OnRestart;
if (handlerPhysicsCrash != null)
handlerPhysicsCrash(RegionInfo);
}
public virtual bool PresenceChildStatus(UUID avatarID)
{
return false;
}
public abstract bool OtherRegionUp(RegionInfo thisRegion);
public virtual string GetSimulatorVersion()
{
return "OpenSimulator Server";
}
#endregion
#region Shutdown
///
/// Tidy before shutdown
///
public virtual void Close()
{
try
{
EventManager.TriggerShutdown();
}
catch (Exception e)
{
m_log.Error("[SCENE]: SceneBase.cs: Close() - Failed with exception " + e.ToString());
}
}
#endregion
///
/// XXX These two methods are very temporary
/// XXX Diva: this is really truly horrible; must...move...to...LL client...stack...
///
protected Dictionary capsPaths = new Dictionary();
protected Dictionary> childrenSeeds = new Dictionary>();
public string GetCapsPath(UUID agentId)
{
if (capsPaths.ContainsKey(agentId))
{
return capsPaths[agentId];
}
return null;
}
public Dictionary GetChildrenSeeds(UUID agentID)
{
Dictionary seeds = null;
if (childrenSeeds.TryGetValue(agentID, out seeds))
return seeds;
return new Dictionary();
}
public void DropChildSeed(UUID agentID, ulong handle)
{
Dictionary seeds;
if (childrenSeeds.TryGetValue(agentID, out seeds))
{
seeds.Remove(handle);
}
}
public string GetChildSeed(UUID agentID, ulong handle)
{
Dictionary seeds;
if (childrenSeeds.TryGetValue(agentID, out seeds))
{
return seeds[handle];
}
return null;
}
public void SetChildrenSeed(UUID agentID, Dictionary value)
{
//Console.WriteLine(" !!! Setting child seeds in {0} to {1}", RegionInfo.RegionName, value.Count);
childrenSeeds[agentID] = value;
}
public void DumpChildrenSeeds(UUID agentID)
{
Console.WriteLine("================ ChildrenSeed {0} ================", RegionInfo.RegionName);
foreach (KeyValuePair kvp in childrenSeeds[agentID])
{
uint x, y;
Utils.LongToUInts(kvp.Key, out x, out y);
x = x / Constants.RegionSize;
y = y / Constants.RegionSize;
Console.WriteLine(" >> {0}, {1}: {2}", x, y, kvp.Value);
}
}
///
/// Returns a new unallocated local ID
///
/// A brand new local ID
protected internal uint AllocateLocalId()
{
uint myID;
_primAllocateMutex.WaitOne();
myID = ++m_lastAllocatedLocalId;
_primAllocateMutex.ReleaseMutex();
return myID;
}
public virtual T RequestModuleInterface()
{
return default(T);
}
public virtual T[] RequestModuleInterfaces()
{
return new T[] { default(T) };
}
}
}