OpenSimMirror/OpenSim/Region/OptionalModules/ContentManagementSystem/ContentManagementEntity.cs

376 lines
16 KiB
C#

/*
* 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 OpenSimulator 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.Drawing;
using OpenMetaverse;
using Nini.Config;
using OpenSim.Framework;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;
using OpenSim.Region.Framework.Scenes.Serialization;
using OpenSim.Region.Physics.Manager;
using log4net;
namespace OpenSim.Region.OptionalModules.ContentManagement
{
public class ContentManagementEntity : MetaEntity
{
#region Static Fields
// static float TimeToDiff = 0;
// static float TimeToCreateEntities = 0;
#endregion Static Fields
#region Fields
protected Dictionary<UUID, AuraMetaEntity> m_AuraEntities = new Dictionary<UUID, AuraMetaEntity>();
protected Dictionary<UUID, BeamMetaEntity> m_BeamEntities = new Dictionary<UUID, BeamMetaEntity>();
// The LinkNum of parts in m_Entity and m_UnchangedEntity are the same though UUID and LocalId are different.
// This can come in handy.
protected SceneObjectGroup m_UnchangedEntity = null;
/// <value>
/// Should be set to true when there is a difference between m_UnchangedEntity and the corresponding scene object group in the scene entity list.
/// </value>
bool DiffersFromSceneGroup = false;
#endregion Fields
#region Constructors
public ContentManagementEntity(SceneObjectGroup Unchanged, bool physics)
: base(Unchanged, false)
{
m_UnchangedEntity = Unchanged.Copy(Unchanged.RootPart.OwnerID, Unchanged.RootPart.GroupID, false);
}
public ContentManagementEntity(string objectXML, Scene scene, bool physics)
: base(objectXML, scene, false)
{
m_UnchangedEntity = SceneObjectSerializer.FromXml2Format(objectXML);
}
#endregion Constructors
#region Public Properties
public SceneObjectGroup UnchangedEntity
{
get { return m_UnchangedEntity; }
}
#endregion Public Properties
#region Private Methods
/// <summary>
/// Check if an entitybase list (like that returned by scene.GetEntities()) contains a group with the rootpart uuid that matches the current uuid.
/// </summary>
private bool ContainsKey(List<EntityBase> list, UUID uuid)
{
foreach (EntityBase part in list)
if (part.UUID == uuid)
return true;
return false;
}
private SceneObjectGroup GetGroupByUUID(System.Collections.Generic.List<EntityBase> list, UUID uuid)
{
foreach (EntityBase ent in list)
{
if (ent is SceneObjectGroup)
if (ent.UUID == uuid)
return (SceneObjectGroup)ent;
}
return null;
}
#endregion Private Methods
#region Public Methods
/// <summary>
/// Search for a corresponding group UUID in the scene. If not found, then the revisioned group this CMEntity represents has been deleted. Mark the metaentity appropriately.
/// If a matching UUID is found in a scene object group, compare the two for differences. If differences exist, Mark the metaentity appropriately.
/// </summary>
public void FindDifferences()
{
System.Collections.Generic.List<EntityBase> sceneEntityList = m_Entity.Scene.GetEntities();
DiffersFromSceneGroup = false;
// if group is not contained in scene's list
if (!ContainsKey(sceneEntityList, m_UnchangedEntity.UUID))
{
foreach (SceneObjectPart part in m_UnchangedEntity.Children.Values)
{
// if scene list no longer contains this part, display translucent part and mark with red aura
if (!ContainsKey(sceneEntityList, part.UUID))
{
// if already displaying a red aura over part, make sure its red
if (m_AuraEntities.ContainsKey(part.UUID))
{
m_AuraEntities[part.UUID].SetAura(new Vector3(254,0,0), part.Scale);
}
else
{
AuraMetaEntity auraGroup = new AuraMetaEntity(m_Entity.Scene,
part.GetWorldPosition(),
MetaEntity.TRANSLUCENT,
new Vector3(254,0,0),
part.Scale
);
m_AuraEntities.Add(part.UUID, auraGroup);
}
SceneObjectPart metaPart = m_Entity.GetLinkNumPart(part.LinkNum);
SetPartTransparency(metaPart, MetaEntity.TRANSLUCENT);
}
// otherwise, scene will not contain the part. note: a group can not remove a part without changing group id
}
// a deleted part has no where to point a beam particle system,
// if a metapart had a particle system (maybe it represented a moved part) remove it
if (m_BeamEntities.ContainsKey(m_UnchangedEntity.RootPart.UUID))
{
m_BeamEntities[m_UnchangedEntity.RootPart.UUID].HideFromAll();
m_BeamEntities.Remove(m_UnchangedEntity.RootPart.UUID);
}
DiffersFromSceneGroup = true;
}
// if scene list does contain group, compare each part in group for differences and display beams and auras appropriately
else
{
MarkWithDifferences((SceneObjectGroup)GetGroupByUUID(sceneEntityList, m_UnchangedEntity.UUID));
}
}
/// <summary>
/// Check if the revisioned scene object group that this CMEntity is based off of contains a child with the given UUID.
/// </summary>
public bool HasChildPrim(UUID uuid)
{
if (m_UnchangedEntity.Children.ContainsKey(uuid))
return true;
return false;
}
/// <summary>
/// Check if the revisioned scene object group that this CMEntity is based off of contains a child with the given LocalId.
/// </summary>
public bool HasChildPrim(uint localID)
{
foreach (SceneObjectPart part in m_UnchangedEntity.Children.Values)
if (part.LocalId == localID)
return true;
return false;
}
public override void Hide(IClientAPI client)
{
base.Hide(client);
foreach (MetaEntity group in m_AuraEntities.Values)
group.Hide(client);
foreach (MetaEntity group in m_BeamEntities.Values)
group.Hide(client);
}
public override void HideFromAll()
{
base.HideFromAll();
foreach (MetaEntity group in m_AuraEntities.Values)
group.HideFromAll();
foreach (MetaEntity group in m_BeamEntities.Values)
group.HideFromAll();
}
/// <summary>
/// Returns true if there was a change between meta entity and the entity group, false otherwise.
/// If true is returned, it is assumed the metaentity's appearance has changed to reflect the difference (though clients haven't been updated).
/// </summary>
public bool MarkWithDifferences(SceneObjectGroup sceneEntityGroup)
{
SceneObjectPart sceneEntityPart;
SceneObjectPart metaEntityPart;
Diff differences;
bool changed = false;
// Use "UnchangedEntity" to do comparisons because its text, transparency, and other attributes will be just as the user
// had originally saved.
// m_Entity will NOT necessarily be the same entity as the user had saved.
foreach (SceneObjectPart UnchangedPart in m_UnchangedEntity.Children.Values)
{
//This is the part that we use to show changes.
metaEntityPart = m_Entity.GetLinkNumPart(UnchangedPart.LinkNum);
if (sceneEntityGroup.Children.ContainsKey(UnchangedPart.UUID))
{
sceneEntityPart = sceneEntityGroup.Children[UnchangedPart.UUID];
differences = Difference.FindDifferences(UnchangedPart, sceneEntityPart);
if (differences != Diff.NONE)
metaEntityPart.Text = "CHANGE: " + differences.ToString();
if (differences != 0)
{
// Root Part that has been modified
if ((differences&Diff.POSITION) > 0)
{
// If the position of any part has changed, make sure the RootPart of the
// meta entity is pointing with a beam particle system
if (m_BeamEntities.ContainsKey(m_UnchangedEntity.RootPart.UUID))
{
m_BeamEntities[m_UnchangedEntity.RootPart.UUID].HideFromAll();
m_BeamEntities.Remove(m_UnchangedEntity.RootPart.UUID);
}
BeamMetaEntity beamGroup = new BeamMetaEntity(m_Entity.Scene,
m_UnchangedEntity.RootPart.GetWorldPosition(),
MetaEntity.TRANSLUCENT,
sceneEntityPart,
new Vector3(0,0,254)
);
m_BeamEntities.Add(m_UnchangedEntity.RootPart.UUID, beamGroup);
}
if (m_AuraEntities.ContainsKey(UnchangedPart.UUID))
{
m_AuraEntities[UnchangedPart.UUID].HideFromAll();
m_AuraEntities.Remove(UnchangedPart.UUID);
}
AuraMetaEntity auraGroup = new AuraMetaEntity(m_Entity.Scene,
UnchangedPart.GetWorldPosition(),
MetaEntity.TRANSLUCENT,
new Vector3(0,0,254),
UnchangedPart.Scale
);
m_AuraEntities.Add(UnchangedPart.UUID, auraGroup);
SetPartTransparency(metaEntityPart, MetaEntity.TRANSLUCENT);
DiffersFromSceneGroup = true;
}
else // no differences between scene part and meta part
{
if (m_BeamEntities.ContainsKey(m_UnchangedEntity.RootPart.UUID))
{
m_BeamEntities[m_UnchangedEntity.RootPart.UUID].HideFromAll();
m_BeamEntities.Remove(m_UnchangedEntity.RootPart.UUID);
}
if (m_AuraEntities.ContainsKey(UnchangedPart.UUID))
{
m_AuraEntities[UnchangedPart.UUID].HideFromAll();
m_AuraEntities.Remove(UnchangedPart.UUID);
}
SetPartTransparency(metaEntityPart, MetaEntity.NONE);
}
}
else //The entity currently in the scene is missing parts from the metaentity saved, so mark parts red as deleted.
{
if (m_AuraEntities.ContainsKey(UnchangedPart.UUID))
{
m_AuraEntities[UnchangedPart.UUID].HideFromAll();
m_AuraEntities.Remove(UnchangedPart.UUID);
}
AuraMetaEntity auraGroup = new AuraMetaEntity(m_Entity.Scene,
UnchangedPart.GetWorldPosition(),
MetaEntity.TRANSLUCENT,
new Vector3(254,0,0),
UnchangedPart.Scale
);
m_AuraEntities.Add(UnchangedPart.UUID, auraGroup);
SetPartTransparency(metaEntityPart, MetaEntity.TRANSLUCENT);
DiffersFromSceneGroup = true;
}
}
return changed;
}
public void SendFullAuraUpdate(IClientAPI client)
{
if (DiffersFromSceneGroup)
{
foreach (AuraMetaEntity group in m_AuraEntities.Values)
group.SendFullUpdate(client);
}
}
public void SendFullAuraUpdateToAll()
{
if (DiffersFromSceneGroup)
{
foreach (AuraMetaEntity group in m_AuraEntities.Values)
group.SendFullUpdateToAll();
}
}
public void SendFullBeamUpdate(IClientAPI client)
{
if (DiffersFromSceneGroup)
{
foreach (BeamMetaEntity group in m_BeamEntities.Values)
group.SendFullUpdate(client);
}
}
public void SendFullBeamUpdateToAll()
{
if (DiffersFromSceneGroup)
{
foreach (BeamMetaEntity group in m_BeamEntities.Values)
group.SendFullUpdateToAll();
}
}
public void SendFullDiffUpdate(IClientAPI client)
{
FindDifferences();
if (DiffersFromSceneGroup)
{
SendFullUpdate(client);
SendFullAuraUpdate(client);
SendFullBeamUpdate(client);
}
}
public void SendFullDiffUpdateToAll()
{
FindDifferences();
if (DiffersFromSceneGroup)
{
SendFullUpdateToAll();
SendFullAuraUpdateToAll();
SendFullBeamUpdateToAll();
}
}
#endregion Public Methods
}
}