using System; using System.Collections.Generic; using System.Text; using libsecondlife; using libsecondlife.Packets; using OpenSim.Framework; using OpenSim.Framework.Console; using OpenSim.Region.Environment.Types; using OpenSim.Region.Physics.Manager; namespace OpenSim.Region.Environment.Scenes { public class InnerScene { #region Fields public Dictionary ScenePresences; public Dictionary SceneObjects; public Dictionary Entities; public BasicQuadTreeNode QuadTree; protected RegionInfo m_regInfo; protected Scene m_parentScene; protected PermissionManager PermissionsMngr; internal object m_syncRoot = new object(); public PhysicsScene PhyScene; #endregion public InnerScene(Scene parent, RegionInfo regInfo, PermissionManager permissionsMngr) { m_parentScene = parent; m_regInfo = regInfo; PermissionsMngr = permissionsMngr; QuadTree = new BasicQuadTreeNode(null, "/0/", 0, 0, 256, 256); QuadTree.Subdivide(); QuadTree.Subdivide(); } public void Close() { ScenePresences.Clear(); SceneObjects.Clear(); Entities.Clear(); } #region Update Methods internal void UpdatePreparePhysics() { // If we are using a threaded physics engine // grab the latest scene from the engine before // trying to process it. // PhysX does this (runs in the background). if (PhyScene.IsThreaded) { PhyScene.GetResults(); } } internal void UpdateEntities() { List updateEntities = new List(Entities.Values); foreach (EntityBase entity in updateEntities) { entity.Update(); } } internal void UpdatePhysics(double elapsed) { lock (m_syncRoot) { PhyScene.Simulate((float)elapsed); } } internal void UpdateEntityMovement() { List moveEntities = new List(Entities.Values); foreach (EntityBase entity in moveEntities) { entity.UpdateMovement(); } } #endregion #region Entity Methods public void AddEntityFromStorage(SceneObjectGroup sceneObject) { sceneObject.RegionHandle = m_regInfo.RegionHandle; sceneObject.SetScene(m_parentScene); foreach (SceneObjectPart part in sceneObject.Children.Values) { part.LocalID = m_parentScene.PrimIDAllocate(); } sceneObject.UpdateParentIDs(); AddEntity(sceneObject); } public void AddEntity(SceneObjectGroup sceneObject) { if (!Entities.ContainsKey(sceneObject.UUID)) { // QuadTree.AddObject(sceneObject); Entities.Add(sceneObject.UUID, sceneObject); } } public void RemovePrim(uint localID, LLUUID avatar_deleter) { foreach (EntityBase obj in Entities.Values) { if (obj is SceneObjectGroup) { if (((SceneObjectGroup)obj).LocalId == localID) { m_parentScene.RemoveEntity((SceneObjectGroup)obj); return; } } } } public ScenePresence CreateAndAddScenePresence(IClientAPI client, bool child, AvatarWearable[] wearables, byte[] visualParams) { ScenePresence newAvatar = null; newAvatar = new ScenePresence(client, m_parentScene, m_regInfo, visualParams, wearables); newAvatar.IsChildAgent = child; if (child) { MainLog.Instance.Verbose("SCENE", m_regInfo.RegionName + ": Creating new child agent."); } else { MainLog.Instance.Verbose("SCENE", m_regInfo.RegionName + ": Creating new root agent."); MainLog.Instance.Verbose("SCENE", m_regInfo.RegionName + ": Adding Physical agent."); newAvatar.AddToPhysicalScene(); } lock (Entities) { if (!Entities.ContainsKey(client.AgentId)) { Entities.Add(client.AgentId, newAvatar); } else { Entities[client.AgentId] = newAvatar; } } lock (ScenePresences) { if (ScenePresences.ContainsKey(client.AgentId)) { ScenePresences[client.AgentId] = newAvatar; } else { ScenePresences.Add(client.AgentId, newAvatar); } } return newAvatar; } #endregion #region Get Methods /// /// Request a List of all m_scenePresences in this World /// /// public List GetScenePresences() { List result = new List(ScenePresences.Values); return result; } public List GetAvatars() { List result = GetScenePresences(delegate(ScenePresence scenePresence) { return !scenePresence.IsChildAgent; }); return result; } /// /// Request a filtered list of m_scenePresences in this World /// /// public List GetScenePresences(FilterAvatarList filter) { List result = new List(); foreach (ScenePresence avatar in ScenePresences.Values) { if (filter(avatar)) { result.Add(avatar); } } return result; } /// /// Request a Avatar by UUID /// /// /// public ScenePresence GetScenePresence(LLUUID avatarID) { if (ScenePresences.ContainsKey(avatarID)) { return ScenePresences[avatarID]; } return null; } private SceneObjectGroup GetGroupByPrim(uint localID) { foreach (EntityBase ent in Entities.Values) { if (ent is SceneObjectGroup) { if (((SceneObjectGroup)ent).HasChildPrim(localID)) return (SceneObjectGroup)ent; } } return null; } private SceneObjectGroup GetGroupByPrim(LLUUID fullID) { foreach (EntityBase ent in Entities.Values) { if (ent is SceneObjectGroup) { if (((SceneObjectGroup)ent).HasChildPrim(fullID)) return (SceneObjectGroup)ent; } } return null; } public SceneObjectPart GetSceneObjectPart(uint localID) { SceneObjectGroup group = GetGroupByPrim(localID); if (group != null) return group.GetChildPart(localID); else return null; } public SceneObjectPart GetSceneObjectPart(LLUUID fullID) { SceneObjectGroup group = GetGroupByPrim(fullID); if (group != null) return group.GetChildPart(fullID); else return null; } internal bool TryGetAvatar(LLUUID avatarId, out ScenePresence avatar) { ScenePresence presence; if (ScenePresences.TryGetValue(avatarId, out presence)) { if (!presence.IsChildAgent) { avatar = presence; return true; } } avatar = null; return false; } internal bool TryGetAvatarByName(string avatarName, out ScenePresence avatar) { foreach (ScenePresence presence in ScenePresences.Values) { if (!presence.IsChildAgent) { string name = presence.ControllingClient.FirstName + " " + presence.ControllingClient.LastName; if (String.Compare(avatarName, name, true) == 0) { avatar = presence; return true; } } } avatar = null; return false; } #endregion #region Other Methods public LLUUID ConvertLocalIDToFullID(uint localID) { SceneObjectGroup group = GetGroupByPrim(localID); if (group != null) return group.GetPartsFullID(localID); else return LLUUID.Zero; } public void SendAllSceneObjectsToClient(ScenePresence presence) { foreach (EntityBase ent in Entities.Values) { if (ent is SceneObjectGroup) { ((SceneObjectGroup)ent).ScheduleFullUpdateToAvatar(presence); } } } internal void ForEachClient(Action action) { foreach (ScenePresence presence in ScenePresences.Values) { action(presence.ControllingClient); } } #endregion #region Client Event handlers /// /// /// /// /// /// public void UpdatePrimScale(uint localID, LLVector3 scale, IClientAPI remoteClient) { SceneObjectGroup group = GetGroupByPrim(localID); if (group != null) group.Resize(scale, localID); } /// /// /// /// /// /// public void UpdatePrimSingleRotation(uint localID, LLQuaternion rot, IClientAPI remoteClient) { SceneObjectGroup group = GetGroupByPrim(localID); if (group != null) group.UpdateSingleRotation(rot, localID); } /// /// /// /// /// /// public void UpdatePrimRotation(uint localID, LLQuaternion rot, IClientAPI remoteClient) { SceneObjectGroup group = GetGroupByPrim(localID); if (group != null) group.UpdateGroupRotation(rot); } /// /// /// /// /// /// /// public void UpdatePrimRotation(uint localID, LLVector3 pos, LLQuaternion rot, IClientAPI remoteClient) { SceneObjectGroup group = GetGroupByPrim(localID); if (group != null) group.UpdateGroupRotation(pos, rot); } public void UpdatePrimSinglePosition(uint localID, LLVector3 pos, IClientAPI remoteClient) { SceneObjectGroup group = GetGroupByPrim(localID); if (group != null) group.UpdateSinglePosition(pos, localID); } /// /// /// /// /// /// public void UpdatePrimPosition(uint localID, LLVector3 pos, IClientAPI remoteClient) { SceneObjectGroup group = GetGroupByPrim(localID); if (group != null) group.UpdateGroupPosition(pos); } /// /// /// /// /// /// public void UpdatePrimTexture(uint localID, byte[] texture, IClientAPI remoteClient) { SceneObjectGroup group = GetGroupByPrim(localID); if (group != null) group.UpdateTextureEntry(localID, texture); } /// /// /// /// /// /// public void UpdatePrimFlags(uint localID, Packet packet, IClientAPI remoteClient) { SceneObjectGroup group = GetGroupByPrim(localID); if (group != null) group.UpdatePrimFlags(localID, (ushort)packet.Type, true, packet.ToBytes()); //System.Console.WriteLine("Got primupdate packet: " + packet.UsePhysics.ToString()); } public void MoveObject(LLUUID objectID, LLVector3 offset, LLVector3 pos, IClientAPI remoteClient) { if (PermissionsMngr.CanEditObject(remoteClient.AgentId, objectID)) { SceneObjectGroup group = GetGroupByPrim(objectID); if (group != null) group.GrabMovement(offset, pos, remoteClient); } } /// /// /// /// /// public void PrimName(uint primLocalID, string name) { SceneObjectGroup group = GetGroupByPrim(primLocalID); if (group != null) group.SetPartName(name, primLocalID); } /// /// /// /// /// public void PrimDescription(uint primLocalID, string description) { SceneObjectGroup group = GetGroupByPrim(primLocalID); if (group != null) group.SetPartDescription(description, primLocalID); } public void UpdateExtraParam(uint primLocalID, ushort type, bool inUse, byte[] data) { SceneObjectGroup group = GetGroupByPrim(primLocalID); if (group != null) group.UpdateExtraParam(primLocalID, type, inUse, data); } /// /// /// /// /// public void UpdatePrimShape(uint primLocalID, ObjectShapePacket.ObjectDataBlock shapeBlock) { SceneObjectGroup group = GetGroupByPrim(primLocalID); if (group != null) group.UpdateShape(shapeBlock, primLocalID); } /// /// /// /// /// public void LinkObjects(uint parentPrim, List childPrims) { SceneObjectGroup parenPrim = null; foreach (EntityBase ent in Entities.Values) { if (ent is SceneObjectGroup) { if (((SceneObjectGroup)ent).LocalId == parentPrim) { parenPrim = (SceneObjectGroup)ent; break; } } } List children = new List(); if (parenPrim != null) { for (int i = 0; i < childPrims.Count; i++) { foreach (EntityBase ent in Entities.Values) { if (ent is SceneObjectGroup) { if (((SceneObjectGroup)ent).LocalId == childPrims[i]) { children.Add((SceneObjectGroup)ent); } } } } } foreach (SceneObjectGroup sceneObj in children) { parenPrim.LinkToGroup(sceneObj); } } /// /// /// /// /// /// public void DuplicateObject(uint originalPrim, LLVector3 offset, uint flags) { SceneObjectGroup originPrim = null; foreach (EntityBase ent in Entities.Values) { if (ent is SceneObjectGroup) { if (((SceneObjectGroup)ent).LocalId == originalPrim) { originPrim = (SceneObjectGroup)ent; break; } } } if (originPrim != null) { SceneObjectGroup copy = originPrim.Copy(); copy.AbsolutePosition = copy.AbsolutePosition + offset; Entities.Add(copy.UUID, copy); copy.ScheduleGroupForFullUpdate(); } else { MainLog.Instance.Warn("client", "Attempted to duplicate nonexistant prim"); } } #endregion } }