diff options
Diffstat (limited to 'OpenSim/Region/OptionalModules/ContentManagementSystem')
15 files changed, 3602 insertions, 0 deletions
diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/AuraMetaEntity.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/AuraMetaEntity.cs new file mode 100644 index 0000000..d4acc34 --- /dev/null +++ b/OpenSim/Region/OptionalModules/ContentManagementSystem/AuraMetaEntity.cs | |||
@@ -0,0 +1,161 @@ | |||
1 | /* | ||
2 | * Copyright (c) Contributors, http://opensimulator.org/ | ||
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions are met: | ||
7 | * * Redistributions of source code must retain the above copyright | ||
8 | * notice, this list of conditions and the following disclaimer. | ||
9 | * * Redistributions in binary form must reproduce the above copyright | ||
10 | * notice, this list of conditions and the following disclaimer in the | ||
11 | * documentation and/or other materials provided with the distribution. | ||
12 | * * Neither the name of the OpenSim Project nor the | ||
13 | * names of its contributors may be used to endorse or promote products | ||
14 | * derived from this software without specific prior written permission. | ||
15 | * | ||
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | */ | ||
27 | |||
28 | #region Header | ||
29 | |||
30 | // AuraMetaEntity.cs created with MonoDevelop | ||
31 | // User: bongiojp at 3:03 PMĀ 8/6/2008 | ||
32 | // | ||
33 | // To change standard headers go to Edit->Preferences->Coding->Standard Headers | ||
34 | // | ||
35 | |||
36 | #endregion Header | ||
37 | |||
38 | using System; | ||
39 | using System.Collections.Generic; | ||
40 | using System.Drawing; | ||
41 | |||
42 | using OpenMetaverse; | ||
43 | |||
44 | using Nini.Config; | ||
45 | |||
46 | using OpenSim.Framework; | ||
47 | using OpenSim.Region.Framework.Interfaces; | ||
48 | using OpenSim.Region.Framework.Scenes; | ||
49 | using OpenSim.Region.Physics.Manager; | ||
50 | |||
51 | using log4net; | ||
52 | |||
53 | namespace OpenSim.Region.OptionalModules.ContentManagement | ||
54 | { | ||
55 | public class AuraMetaEntity : PointMetaEntity | ||
56 | { | ||
57 | #region Constructors | ||
58 | |||
59 | //transparency of root part, NOT particle system. Should probably add support for changing particle system transparency. | ||
60 | public AuraMetaEntity(Scene scene, Vector3 groupPos, float transparency, Vector3 color, Vector3 scale) | ||
61 | : base(scene, groupPos, transparency) | ||
62 | { | ||
63 | SetAura(color, scale); | ||
64 | } | ||
65 | |||
66 | public AuraMetaEntity(Scene scene, UUID uuid, Vector3 groupPos, float transparency, Vector3 color, Vector3 scale) | ||
67 | : base(scene, uuid, groupPos, transparency) | ||
68 | { | ||
69 | SetAura(color, scale); | ||
70 | } | ||
71 | |||
72 | #endregion Constructors | ||
73 | |||
74 | #region Private Methods | ||
75 | |||
76 | private float Average(Vector3 values) | ||
77 | { | ||
78 | return (values.X + values.Y + values.Z)/3f; | ||
79 | } | ||
80 | |||
81 | #endregion Private Methods | ||
82 | |||
83 | #region Public Methods | ||
84 | |||
85 | public void SetAura(Vector3 color, Vector3 scale) | ||
86 | { | ||
87 | SetAura(color, Average(scale) * 2.0f); | ||
88 | } | ||
89 | |||
90 | public void SetAura(Vector3 color, float radius) | ||
91 | { | ||
92 | SceneObjectPart From = m_Entity.RootPart; | ||
93 | |||
94 | //m_log.Debug("[META ENTITY] BEFORE: radius = " + radius); | ||
95 | float burstRadius = 0.1f; | ||
96 | Primitive.ParticleSystem.SourcePattern patternFlags = Primitive.ParticleSystem.SourcePattern.None; | ||
97 | float age = 1.5f; | ||
98 | float burstRate = 0.4f; | ||
99 | if (radius >= 8.0f) | ||
100 | { | ||
101 | //float sizeOfObject = radius / 2.0f; | ||
102 | burstRadius = (radius - 8.0f)/3f; | ||
103 | burstRate = 1.5f; | ||
104 | radius = 7.99f; | ||
105 | patternFlags = Primitive.ParticleSystem.SourcePattern.Explode; | ||
106 | age = 4.0f; | ||
107 | } | ||
108 | SetAura(From, color, radius, burstRadius, age, burstRate, patternFlags); | ||
109 | } | ||
110 | |||
111 | public void SetAura(SceneObjectPart From, Vector3 color, float radius, float burstRadius, float age, float burstRate, Primitive.ParticleSystem.SourcePattern patternFlags) | ||
112 | { | ||
113 | Primitive.ParticleSystem prules = new Primitive.ParticleSystem(); | ||
114 | //prules.PartDataFlags = Primitive.ParticleSystem.ParticleDataFlags.Emissive | | ||
115 | // Primitive.ParticleSystem.ParticleDataFlags.FollowSrc; //PSYS_PART_FLAGS | ||
116 | //prules.PartDataFlags = Primitive.ParticleSystem.ParticleDataFlags.Beam | | ||
117 | // Primitive.ParticleSystem.ParticleDataFlags.TargetPos; | ||
118 | prules.PartStartColor.R = color.X; //PSYS_PART_START_COLOR | ||
119 | prules.PartStartColor.G = color.Y; | ||
120 | prules.PartStartColor.B = color.Z; | ||
121 | prules.PartStartColor.A = 0.5f; //PSYS_PART_START_ALPHA, transparency | ||
122 | prules.PartEndColor.R = color.X; //PSYS_PART_END_COLOR | ||
123 | prules.PartEndColor.G = color.Y; | ||
124 | prules.PartEndColor.B = color.Z; | ||
125 | prules.PartEndColor.A = 0.5f; //PSYS_PART_END_ALPHA, transparency | ||
126 | /*prules.PartStartScaleX = 0.5f; //PSYS_PART_START_SCALE | ||
127 | prules.PartStartScaleY = 0.5f; | ||
128 | prules.PartEndScaleX = 0.5f; //PSYS_PART_END_SCALE | ||
129 | prules.PartEndScaleY = 0.5f; | ||
130 | */ | ||
131 | prules.PartStartScaleX = radius; //PSYS_PART_START_SCALE | ||
132 | prules.PartStartScaleY = radius; | ||
133 | prules.PartEndScaleX = radius; //PSYS_PART_END_SCALE | ||
134 | prules.PartEndScaleY = radius; | ||
135 | prules.PartMaxAge = age; //PSYS_PART_MAX_AGE | ||
136 | prules.PartAcceleration.X = 0.0f; //PSYS_SRC_ACCEL | ||
137 | prules.PartAcceleration.Y = 0.0f; | ||
138 | prules.PartAcceleration.Z = 0.0f; | ||
139 | prules.Pattern = patternFlags; //PSYS_SRC_PATTERN | ||
140 | //prules.Texture = UUID.Zero;//= UUID //PSYS_SRC_TEXTURE, default used if blank | ||
141 | prules.BurstRate = burstRate; //PSYS_SRC_BURST_RATE | ||
142 | prules.BurstPartCount = 2; //PSYS_SRC_BURST_PART_COUNT | ||
143 | //prules.BurstRadius = radius; //PSYS_SRC_BURST_RADIUS | ||
144 | prules.BurstRadius = burstRadius; //PSYS_SRC_BURST_RADIUS | ||
145 | prules.BurstSpeedMin = 0.001f; //PSYS_SRC_BURST_SPEED_MIN | ||
146 | prules.BurstSpeedMax = 0.001f; //PSYS_SRC_BURST_SPEED_MAX | ||
147 | prules.MaxAge = 0.0f; //PSYS_SRC_MAX_AGE | ||
148 | //prules.Target = To; //PSYS_SRC_TARGET_KEY | ||
149 | prules.AngularVelocity.X = 0.0f; //PSYS_SRC_OMEGA | ||
150 | prules.AngularVelocity.Y = 0.0f; | ||
151 | prules.AngularVelocity.Z = 0.0f; | ||
152 | prules.InnerAngle = 0.0f; //PSYS_SRC_ANGLE_BEGIN | ||
153 | prules.OuterAngle = 0.0f; //PSYS_SRC_ANGLE_END | ||
154 | |||
155 | prules.CRC = 1; //activates the particle system?? | ||
156 | From.AddNewParticleSystem(prules); | ||
157 | } | ||
158 | |||
159 | #endregion Public Methods | ||
160 | } | ||
161 | } | ||
diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/BeamMetaEntity.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/BeamMetaEntity.cs new file mode 100644 index 0000000..c0a0603 --- /dev/null +++ b/OpenSim/Region/OptionalModules/ContentManagementSystem/BeamMetaEntity.cs | |||
@@ -0,0 +1,139 @@ | |||
1 | /* | ||
2 | * Copyright (c) Contributors, http://opensimulator.org/ | ||
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions are met: | ||
7 | * * Redistributions of source code must retain the above copyright | ||
8 | * notice, this list of conditions and the following disclaimer. | ||
9 | * * Redistributions in binary form must reproduce the above copyright | ||
10 | * notice, this list of conditions and the following disclaimer in the | ||
11 | * documentation and/or other materials provided with the distribution. | ||
12 | * * Neither the name of the OpenSim Project nor the | ||
13 | * names of its contributors may be used to endorse or promote products | ||
14 | * derived from this software without specific prior written permission. | ||
15 | * | ||
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | */ | ||
27 | |||
28 | #region Header | ||
29 | |||
30 | // BeamMetaEntity.cs created with MonoDevelop | ||
31 | // User: bongiojp at 3:03 PMĀ 8/6/2008 | ||
32 | // | ||
33 | // To change standard headers go to Edit->Preferences->Coding->Standard Headers | ||
34 | // | ||
35 | |||
36 | #endregion Header | ||
37 | |||
38 | using System; | ||
39 | using System.Collections.Generic; | ||
40 | using System.Drawing; | ||
41 | |||
42 | using OpenMetaverse; | ||
43 | |||
44 | using Nini.Config; | ||
45 | |||
46 | using OpenSim.Framework; | ||
47 | using OpenSim.Region.Framework.Interfaces; | ||
48 | using OpenSim.Region.Framework.Scenes; | ||
49 | using OpenSim.Region.Physics.Manager; | ||
50 | |||
51 | using log4net; | ||
52 | |||
53 | namespace OpenSim.Region.OptionalModules.ContentManagement | ||
54 | { | ||
55 | public class BeamMetaEntity : PointMetaEntity | ||
56 | { | ||
57 | #region Constructors | ||
58 | |||
59 | public BeamMetaEntity(Scene scene, Vector3 groupPos, float transparency, SceneObjectPart To, Vector3 color) | ||
60 | : base(scene, groupPos, transparency) | ||
61 | { | ||
62 | SetBeamToUUID(To, color); | ||
63 | } | ||
64 | |||
65 | public BeamMetaEntity(Scene scene, UUID uuid, Vector3 groupPos, float transparency, SceneObjectPart To, Vector3 color) | ||
66 | : base(scene, uuid, groupPos, transparency) | ||
67 | { | ||
68 | SetBeamToUUID(To, color); | ||
69 | } | ||
70 | |||
71 | #endregion Constructors | ||
72 | |||
73 | #region Public Methods | ||
74 | |||
75 | public void SetBeamToUUID(SceneObjectPart To, Vector3 color) | ||
76 | { | ||
77 | SceneObjectPart From = m_Entity.RootPart; | ||
78 | //Scale size of particles to distance objects are apart (for better visibility) | ||
79 | Vector3 FromPos = From.GetWorldPosition(); | ||
80 | Vector3 ToPos = From.GetWorldPosition(); | ||
81 | // UUID toUUID = To.UUID; | ||
82 | float distance = (float) (Math.Sqrt(Math.Pow(FromPos.X-ToPos.X, 2) + | ||
83 | Math.Pow(FromPos.X-ToPos.Y, 2) + | ||
84 | Math.Pow(FromPos.X-ToPos.Z, 2) | ||
85 | ) | ||
86 | ); | ||
87 | //float rate = (float) (distance/4f); | ||
88 | float rate = 0.5f; | ||
89 | float scale = (float) (distance/128f); | ||
90 | float speed = (float) (2.0f - distance/128f); | ||
91 | |||
92 | SetBeamToUUID(From, To, color, rate, scale, speed); | ||
93 | } | ||
94 | |||
95 | public void SetBeamToUUID(SceneObjectPart From, SceneObjectPart To, Vector3 color, float rate, float scale, float speed) | ||
96 | { | ||
97 | Primitive.ParticleSystem prules = new Primitive.ParticleSystem(); | ||
98 | //prules.PartDataFlags = Primitive.ParticleSystem.ParticleDataFlags.Emissive | | ||
99 | // Primitive.ParticleSystem.ParticleDataFlags.FollowSrc; //PSYS_PART_FLAGS | ||
100 | prules.PartDataFlags = Primitive.ParticleSystem.ParticleDataFlags.Beam | | ||
101 | Primitive.ParticleSystem.ParticleDataFlags.TargetPos; | ||
102 | prules.PartStartColor.R = color.X; //PSYS_PART_START_COLOR | ||
103 | prules.PartStartColor.G = color.Y; | ||
104 | prules.PartStartColor.B = color.Z; | ||
105 | prules.PartStartColor.A = 1.0f; //PSYS_PART_START_ALPHA, transparency | ||
106 | prules.PartEndColor.R = color.X; //PSYS_PART_END_COLOR | ||
107 | prules.PartEndColor.G = color.Y; | ||
108 | prules.PartEndColor.B = color.Z; | ||
109 | prules.PartEndColor.A = 1.0f; //PSYS_PART_END_ALPHA, transparency | ||
110 | prules.PartStartScaleX = scale; //PSYS_PART_START_SCALE | ||
111 | prules.PartStartScaleY = scale; | ||
112 | prules.PartEndScaleX = scale; //PSYS_PART_END_SCALE | ||
113 | prules.PartEndScaleY = scale; | ||
114 | prules.PartMaxAge = 1.0f; //PSYS_PART_MAX_AGE | ||
115 | prules.PartAcceleration.X = 0.0f; //PSYS_SRC_ACCEL | ||
116 | prules.PartAcceleration.Y = 0.0f; | ||
117 | prules.PartAcceleration.Z = 0.0f; | ||
118 | //prules.Pattern = Primitive.ParticleSystem.SourcePattern.Explode; //PSYS_SRC_PATTERN | ||
119 | //prules.Texture = UUID.Zero;//= UUID //PSYS_SRC_TEXTURE, default used if blank | ||
120 | prules.BurstRate = rate; //PSYS_SRC_BURST_RATE | ||
121 | prules.BurstPartCount = 1; //PSYS_SRC_BURST_PART_COUNT | ||
122 | prules.BurstRadius = 0.5f; //PSYS_SRC_BURST_RADIUS | ||
123 | prules.BurstSpeedMin = speed; //PSYS_SRC_BURST_SPEED_MIN | ||
124 | prules.BurstSpeedMax = speed; //PSYS_SRC_BURST_SPEED_MAX | ||
125 | prules.MaxAge = 0.0f; //PSYS_SRC_MAX_AGE | ||
126 | prules.Target = To.UUID; //PSYS_SRC_TARGET_KEY | ||
127 | prules.AngularVelocity.X = 0.0f; //PSYS_SRC_OMEGA | ||
128 | prules.AngularVelocity.Y = 0.0f; | ||
129 | prules.AngularVelocity.Z = 0.0f; | ||
130 | prules.InnerAngle = 0.0f; //PSYS_SRC_ANGLE_BEGIN | ||
131 | prules.OuterAngle = 0.0f; //PSYS_SRC_ANGLE_END | ||
132 | |||
133 | prules.CRC = 1; //activates the particle system?? | ||
134 | From.AddNewParticleSystem(prules); | ||
135 | } | ||
136 | |||
137 | #endregion Public Methods | ||
138 | } | ||
139 | } | ||
diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/CMController.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/CMController.cs new file mode 100644 index 0000000..80989a7 --- /dev/null +++ b/OpenSim/Region/OptionalModules/ContentManagementSystem/CMController.cs | |||
@@ -0,0 +1,757 @@ | |||
1 | ļ»æ/* | ||
2 | * Copyright (c) Contributors, http://opensimulator.org/ | ||
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions are met: | ||
7 | * * Redistributions of source code must retain the above copyright | ||
8 | * notice, this list of conditions and the following disclaimer. | ||
9 | * * Redistributions in binary form must reproduce the above copyright | ||
10 | * notice, this list of conditions and the following disclaimer in the | ||
11 | * documentation and/or other materials provided with the distribution. | ||
12 | * * Neither the name of the OpenSim Project nor the | ||
13 | * names of its contributors may be used to endorse or promote products | ||
14 | * derived from this software without specific prior written permission. | ||
15 | * | ||
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | */ | ||
27 | |||
28 | #region Header | ||
29 | |||
30 | // CMController.cs | ||
31 | // User: bongiojp | ||
32 | // | ||
33 | |||
34 | #endregion Header | ||
35 | |||
36 | using System; | ||
37 | using System.Collections; | ||
38 | using System.Collections.Generic; | ||
39 | using System.Diagnostics; | ||
40 | using System.Threading; | ||
41 | |||
42 | using OpenMetaverse; | ||
43 | |||
44 | using OpenSim; | ||
45 | using OpenSim.Framework; | ||
46 | using OpenSim.Region.Framework.Interfaces; | ||
47 | using OpenSim.Region.Framework.Scenes; | ||
48 | using OpenSim.Region.Physics.Manager; | ||
49 | |||
50 | using log4net; | ||
51 | |||
52 | namespace OpenSim.Region.OptionalModules.ContentManagement | ||
53 | { | ||
54 | /// <summary> | ||
55 | /// The controller in a Model-View-Controller framework. This controller catches actions by the avatars, creates work packets, loops through these work packets in a separate thread, | ||
56 | /// then dictates to the model how the data should change and dictates to the view which data should be displayed. The main mechanism for interaction is through the simchat system. | ||
57 | /// </summary> | ||
58 | public class CMController | ||
59 | { | ||
60 | #region Static Fields | ||
61 | |||
62 | private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); | ||
63 | |||
64 | /// <value> | ||
65 | /// The queue that keeps track of which actions have happened. The MainLoop thread eats through this queue. | ||
66 | /// </value> | ||
67 | private static OpenSim.Framework.BlockingQueue<Work> m_WorkQueue = new OpenSim.Framework.BlockingQueue<Work>(); | ||
68 | |||
69 | #endregion Static Fields | ||
70 | |||
71 | #region Fields | ||
72 | |||
73 | //bool init = false; | ||
74 | int m_channel = -1; | ||
75 | |||
76 | /// <value> | ||
77 | /// The estate module is used to identify which clients are estateManagers. Presently, the controller only pays attention to estate managers. | ||
78 | /// </value> | ||
79 | IEstateModule m_estateModule = null; | ||
80 | |||
81 | //These have to be global variables, threading doesn't allow for passing parameters. (Used in MainLoop) | ||
82 | CMModel m_model = null; | ||
83 | |||
84 | /// <value> | ||
85 | /// A list of all the scenes that should be revisioned. Controller is the only class that keeps track of all scenes in the region. | ||
86 | /// </value> | ||
87 | Hashtable m_sceneList = Hashtable.Synchronized(new Hashtable()); | ||
88 | State m_state = State.NONE; | ||
89 | Thread m_thread = null; | ||
90 | CMView m_view = null; | ||
91 | |||
92 | #endregion Fields | ||
93 | |||
94 | #region Constructors | ||
95 | |||
96 | /// <summary> | ||
97 | /// Initializes a work thread with an initial scene. Additional scenes should be added through the RegisterNewRegion method. | ||
98 | /// </summary> | ||
99 | /// <param name="model"> | ||
100 | /// <see cref="CMModel"/> | ||
101 | /// </param> | ||
102 | /// <param name="view"> | ||
103 | /// <see cref="CMView"/> | ||
104 | /// </param> | ||
105 | /// <param name="scene"> | ||
106 | /// The first scene to keep track of. <see cref="Scene"/> | ||
107 | /// </param> | ||
108 | /// <param name="channel"> | ||
109 | /// The simchat channel number to listen to for instructions <see cref="System.Int32"/> | ||
110 | /// </param> | ||
111 | public CMController(CMModel model, CMView view, Scene scene, int channel) | ||
112 | { | ||
113 | m_model = model; m_view = view; m_channel = channel; | ||
114 | RegisterNewRegion(scene); | ||
115 | Initialize(model, view, scene, channel); | ||
116 | } | ||
117 | |||
118 | #endregion Constructors | ||
119 | |||
120 | #region Private Methods | ||
121 | |||
122 | //------------------------------------------------ EVENTS ----------------------------------------------------// | ||
123 | // private void AvatarEnteringParcel(ScenePresence avatar, int localLandID, LLUUID regionID) | ||
124 | // { | ||
125 | // } | ||
126 | |||
127 | /// <summary> | ||
128 | /// Searches in all scenes for a SceneObjectGroup that contains a part with a specific localID. If found, the object is returned. Else null is returned. | ||
129 | /// </summary> | ||
130 | private SceneObjectGroup GetGroupByPrim(uint localID) | ||
131 | { | ||
132 | foreach (Object currScene in m_sceneList.Values) | ||
133 | { | ||
134 | foreach (EntityBase ent in ((Scene)currScene).GetEntities()) | ||
135 | { | ||
136 | if (ent is SceneObjectGroup) | ||
137 | { | ||
138 | if (((SceneObjectGroup)ent).HasChildPrim(localID)) | ||
139 | return (SceneObjectGroup)ent; | ||
140 | } | ||
141 | } | ||
142 | } | ||
143 | return null; | ||
144 | } | ||
145 | |||
146 | private void Initialize(CMModel model, CMView view, Scene scene, int channel) | ||
147 | { | ||
148 | lock (this) | ||
149 | { | ||
150 | m_estateModule = scene.RequestModuleInterface<IEstateModule>(); | ||
151 | m_thread = new Thread(MainLoop); | ||
152 | m_thread.Name = "Content Management"; | ||
153 | m_thread.IsBackground = true; | ||
154 | m_thread.Start(); | ||
155 | ThreadTracker.Add(m_thread); | ||
156 | m_state = State.NONE; | ||
157 | } | ||
158 | } | ||
159 | |||
160 | /// <summary> | ||
161 | /// Run in a thread of its own. A endless loop that consumes (or blocks on) and work queue. Thw work queue is filled through client actions. | ||
162 | /// </summary> | ||
163 | private void MainLoop() | ||
164 | { | ||
165 | try | ||
166 | { | ||
167 | CMModel model = m_model; CMView view = m_view; int channel = m_channel; | ||
168 | Work currentJob = new Work(); | ||
169 | while (true) | ||
170 | { | ||
171 | currentJob = m_WorkQueue.Dequeue(); | ||
172 | m_log.Debug("[CONTENT MANAGEMENT] MAIN LOOP -- DeQueued a request"); | ||
173 | m_log.Debug("[CONTENT MANAGEMENT] MAIN LOOP -- Work type: " + currentJob.Type); | ||
174 | switch (currentJob.Type) | ||
175 | { | ||
176 | case WorkType.NONE: | ||
177 | break; | ||
178 | case WorkType.OBJECTATTRIBUTECHANGE: | ||
179 | ObjectAttributeChanged(model, view, currentJob.LocalId); | ||
180 | break; | ||
181 | case WorkType.PRIMITIVEADDED: | ||
182 | PrimitiveAdded(model, view, currentJob); | ||
183 | break; | ||
184 | case WorkType.OBJECTDUPLICATED: | ||
185 | ObjectDuplicated(model, view, currentJob.LocalId); | ||
186 | break; | ||
187 | case WorkType.OBJECTKILLED: | ||
188 | ObjectKilled(model, view, (SceneObjectGroup) currentJob.Data1); | ||
189 | break; | ||
190 | case WorkType.UNDODID: | ||
191 | UndoDid(model, view, currentJob.UUID); | ||
192 | break; | ||
193 | case WorkType.NEWCLIENT: | ||
194 | NewClient(view, (IClientAPI) currentJob.Data1); | ||
195 | break; | ||
196 | case WorkType.SIMCHAT: | ||
197 | m_log.Debug("[CONTENT MANAGEMENT] MAIN LOOP -- Message received: " + ((OSChatMessage) currentJob.Data1).Message); | ||
198 | SimChat(model, view, (OSChatMessage) currentJob.Data1, channel); | ||
199 | break; | ||
200 | default: | ||
201 | m_log.Debug("[CONTENT MANAGEMENT] MAIN LOOP -- uuuuuuuuuh, what?"); | ||
202 | break; | ||
203 | } | ||
204 | } | ||
205 | } | ||
206 | catch (Exception e) | ||
207 | { | ||
208 | // TODO: Let users in the sim and those entering it and possibly an external watchdog know what has happened | ||
209 | m_log.ErrorFormat( | ||
210 | "[CONTENT MANAGEMENT]: Content management thread terminating with exception. PLEASE REBOOT YOUR SIM - CONTENT MANAGEMENT WILL NOT BE AVAILABLE UNTIL YOU DO. Exception is {0}", | ||
211 | e); | ||
212 | } | ||
213 | } | ||
214 | |||
215 | /// <summary> | ||
216 | /// Only called by the MainLoop. Updates the view of a new client with metaentities if diff-mode is currently enabled. | ||
217 | /// </summary> | ||
218 | private void NewClient(CMView view, IClientAPI client) | ||
219 | { | ||
220 | if ((m_state & State.SHOWING_CHANGES) > 0) | ||
221 | view.SendMetaEntitiesToNewClient(client); | ||
222 | } | ||
223 | |||
224 | /// <summary> | ||
225 | /// Only called by the MainLoop. | ||
226 | /// </summary> | ||
227 | private void ObjectAttributeChanged(CMModel model, CMView view, uint LocalId) | ||
228 | { | ||
229 | SceneObjectGroup group = null; | ||
230 | if ((m_state & State.SHOWING_CHANGES) > 0) | ||
231 | { | ||
232 | group = GetGroupByPrim(LocalId); | ||
233 | if (group != null) | ||
234 | { | ||
235 | view.DisplayAuras(model.UpdateNormalEntityEffects(group)); //Might be a normal entity (green aura) | ||
236 | m_view.DisplayMetaEntity(group.UUID); //Might be a meta entity (blue aura) | ||
237 | } | ||
238 | } | ||
239 | } | ||
240 | |||
241 | /// <summary> | ||
242 | /// Only called by the MainLoop. Displays new green auras over the newly created part when a part is shift copied. | ||
243 | /// </summary> | ||
244 | private void ObjectDuplicated(CMModel model, CMView view, uint localId) | ||
245 | { | ||
246 | if ((m_state & State.SHOWING_CHANGES) > 0) | ||
247 | view.DisplayAuras(model.CheckForNewEntitiesMissingAuras(GetGroupByPrim(localId).Scene)); | ||
248 | } | ||
249 | |||
250 | /// <summary> | ||
251 | /// Only called by the MainLoop. | ||
252 | /// </summary> | ||
253 | private void ObjectKilled(CMModel model, CMView view, SceneObjectGroup group) | ||
254 | { | ||
255 | if ((m_state & State.SHOWING_CHANGES) > 0) | ||
256 | { | ||
257 | view.RemoveOrUpdateDeletedEntity(group); | ||
258 | model.RemoveOrUpdateDeletedEntity(group); | ||
259 | } | ||
260 | } | ||
261 | |||
262 | /// <summary> | ||
263 | /// Only called by the MainLoop. | ||
264 | /// </summary> | ||
265 | private void PrimitiveAdded(CMModel model, CMView view, Work currentJob) | ||
266 | { | ||
267 | if ((m_state & State.SHOWING_CHANGES) > 0) | ||
268 | { | ||
269 | foreach (Object scene in m_sceneList.Values) | ||
270 | m_view.DisplayAuras(model.CheckForNewEntitiesMissingAuras((Scene) scene)); | ||
271 | } | ||
272 | } | ||
273 | |||
274 | /// <summary> | ||
275 | /// Only called by the MainLoop. | ||
276 | /// </summary> | ||
277 | private void UndoDid(CMModel model, CMView view, UUID uuid) | ||
278 | { | ||
279 | if ((m_state & State.SHOWING_CHANGES) > 0) | ||
280 | { | ||
281 | ContentManagementEntity ent = model.FindMetaEntityAffectedByUndo(uuid); | ||
282 | if (ent != null) | ||
283 | view.DisplayEntity(ent); | ||
284 | } | ||
285 | } | ||
286 | |||
287 | #endregion Private Methods | ||
288 | |||
289 | #region Protected Methods | ||
290 | |||
291 | protected void GroupBeingDeleted(SceneObjectGroup group) | ||
292 | { | ||
293 | m_log.Debug("[CONTENT MANAGEMENT] Something was deleted!!!"); | ||
294 | Work moreWork = new Work(); | ||
295 | moreWork.Type = WorkType.OBJECTKILLED; | ||
296 | moreWork.Data1 = group.Copy(); | ||
297 | m_WorkQueue.Enqueue(moreWork); | ||
298 | } | ||
299 | |||
300 | protected void ObjectDuplicated(uint localID, Vector3 offset, uint dupeFlags, UUID AgentID, UUID GroupID) | ||
301 | { | ||
302 | Work moreWork = new Work(); | ||
303 | moreWork.Type = WorkType.OBJECTDUPLICATED; | ||
304 | moreWork.LocalId = localID; | ||
305 | m_WorkQueue.Enqueue(moreWork); | ||
306 | m_log.Debug("[CONTENT MANAGEMENT] dup queue"); | ||
307 | } | ||
308 | |||
309 | protected void ObjectDuplicatedOnRay(uint localID, uint dupeFlags, UUID AgentID, UUID GroupID, | ||
310 | UUID RayTargetObj, Vector3 RayEnd, Vector3 RayStart, | ||
311 | bool BypassRaycast, bool RayEndIsIntersection, bool CopyCenters, bool CopyRotates) | ||
312 | { | ||
313 | Work moreWork = new Work(); | ||
314 | moreWork.Type = WorkType.OBJECTDUPLICATED; | ||
315 | moreWork.LocalId = localID; | ||
316 | m_WorkQueue.Enqueue(moreWork); | ||
317 | m_log.Debug("[CONTENT MANAGEMENT] dup queue"); | ||
318 | } | ||
319 | |||
320 | protected void OnNewClient(IClientAPI client) | ||
321 | { | ||
322 | Work moreWork = new Work(); | ||
323 | moreWork.Type = WorkType.NEWCLIENT; | ||
324 | moreWork.Data1 = client; | ||
325 | m_WorkQueue.Enqueue(moreWork); | ||
326 | m_log.Debug("[CONTENT MANAGEMENT] new client"); | ||
327 | } | ||
328 | |||
329 | protected void OnUnDid(IClientAPI remoteClient, UUID primId) | ||
330 | { | ||
331 | Work moreWork = new Work(); | ||
332 | moreWork.Type = WorkType.UNDODID; | ||
333 | moreWork.UUID = primId; | ||
334 | m_WorkQueue.Enqueue(moreWork); | ||
335 | m_log.Debug("[CONTENT MANAGEMENT] undid"); | ||
336 | } | ||
337 | |||
338 | /// <summary> | ||
339 | /// Takes a list of scenes and forms a new orderd list according to the proximity of scenes to the second argument. | ||
340 | /// </summary> | ||
341 | protected static System.Collections.Generic.List<Scene> ScenesInOrderOfProximity(Hashtable sceneList, Scene scene) | ||
342 | { | ||
343 | int somethingAddedToList = 1; | ||
344 | System.Collections.Generic.List<Scene> newList = new List<Scene>(); | ||
345 | newList.Add(scene); | ||
346 | |||
347 | if (!sceneList.ContainsValue(scene)) | ||
348 | { | ||
349 | foreach (Object sceneObj in sceneList) | ||
350 | newList.Add((Scene) sceneObj); | ||
351 | return newList; | ||
352 | } | ||
353 | |||
354 | while (somethingAddedToList > 0) | ||
355 | { | ||
356 | somethingAddedToList = 0; | ||
357 | for (int i = 0; i < newList.Count; i++) | ||
358 | { | ||
359 | foreach (Object sceneObj in sceneList.Values) | ||
360 | { | ||
361 | if (newList[i].CheckNeighborRegion(((Scene)sceneObj).RegionInfo) && (!newList.Contains((Scene)sceneObj))) | ||
362 | { | ||
363 | newList.Add((Scene)sceneObj); | ||
364 | somethingAddedToList++; | ||
365 | } | ||
366 | } | ||
367 | } | ||
368 | } | ||
369 | |||
370 | foreach (Object sceneObj in sceneList.Values) | ||
371 | if (!newList.Contains((Scene)sceneObj)) | ||
372 | newList.Add((Scene)sceneObj); | ||
373 | |||
374 | return newList; | ||
375 | } | ||
376 | |||
377 | //This is stupid, the same information is contained in the first and second argument | ||
378 | protected void SimChatSent(Object x, OSChatMessage e) | ||
379 | { | ||
380 | m_log.Debug("[CONTENT MANAGEMENT] SIMCHAT SENT !!!!!!!"); | ||
381 | m_log.Debug("[CONTENT MANAGEMENT] message was: " + e.Message); | ||
382 | Work moreWork = new Work(); | ||
383 | moreWork.Type = WorkType.SIMCHAT; | ||
384 | moreWork.Data1 = e; | ||
385 | m_WorkQueue.Enqueue(moreWork); | ||
386 | } | ||
387 | |||
388 | /// <summary> | ||
389 | /// Adds extra handlers to a number of events so that the controller can produce work based on the client's actions. | ||
390 | /// </summary> | ||
391 | protected void StartManaging(IClientAPI client) | ||
392 | { | ||
393 | m_log.Debug("[CONTENT MANAGEMENT] Registering channel with chat services."); | ||
394 | // client.OnChatFromClient += SimChatSent; | ||
395 | //init = true; | ||
396 | |||
397 | OnNewClient(client); | ||
398 | |||
399 | m_log.Debug("[CONTENT MANAGEMENT] Adding handlers to client."); | ||
400 | client.OnUpdatePrimScale += UpdateSingleScale; | ||
401 | client.OnUpdatePrimGroupScale += UpdateMultipleScale; | ||
402 | client.OnUpdatePrimGroupPosition += UpdateMultiplePosition; | ||
403 | client.OnUpdatePrimSinglePosition += UpdateSinglePosition; | ||
404 | client.OnUpdatePrimGroupRotation += UpdateMultipleRotation; | ||
405 | client.OnUpdatePrimSingleRotation += UpdateSingleRotation; | ||
406 | client.OnAddPrim += UpdateNewParts; | ||
407 | client.OnObjectDuplicate += ObjectDuplicated; | ||
408 | client.OnObjectDuplicateOnRay += ObjectDuplicatedOnRay; | ||
409 | client.OnUndo += OnUnDid; | ||
410 | //client.OnUpdatePrimGroupMouseRotation += m_innerScene.UpdatePrimRotation; | ||
411 | } | ||
412 | |||
413 | /// <summary> | ||
414 | /// | ||
415 | /// </summary> | ||
416 | protected void StopManaging(UUID clientUUID) | ||
417 | { | ||
418 | foreach (Object sceneobj in m_sceneList.Values) | ||
419 | { | ||
420 | ScenePresence presence = ((Scene)sceneobj).GetScenePresence(clientUUID); | ||
421 | if (presence != null) | ||
422 | { | ||
423 | IClientAPI client = presence.ControllingClient; | ||
424 | m_log.Debug("[CONTENT MANAGEMENT] Unregistering channel with chat services."); | ||
425 | // client.OnChatFromViewer -= SimChatSent; | ||
426 | |||
427 | m_log.Debug("[CONTENT MANAGEMENT] Removing handlers to client"); | ||
428 | client.OnUpdatePrimScale -= UpdateSingleScale; | ||
429 | client.OnUpdatePrimGroupScale -= UpdateMultipleScale; | ||
430 | client.OnUpdatePrimGroupPosition -= UpdateMultiplePosition; | ||
431 | client.OnUpdatePrimSinglePosition -= UpdateSinglePosition; | ||
432 | client.OnUpdatePrimGroupRotation -= UpdateMultipleRotation; | ||
433 | client.OnUpdatePrimSingleRotation -= UpdateSingleRotation; | ||
434 | client.OnAddPrim -= UpdateNewParts; | ||
435 | client.OnObjectDuplicate -= ObjectDuplicated; | ||
436 | client.OnObjectDuplicateOnRay -= ObjectDuplicatedOnRay; | ||
437 | client.OnUndo -= OnUnDid; | ||
438 | //client.OnUpdatePrimGroupMouseRotation += m_innerScene.UpdatePrimRotation; | ||
439 | return; | ||
440 | } | ||
441 | } | ||
442 | } | ||
443 | |||
444 | protected void UpdateMultiplePosition(uint localID, Vector3 pos, IClientAPI remoteClient) | ||
445 | { | ||
446 | Work moreWork = new Work(); | ||
447 | moreWork.Type = WorkType.OBJECTATTRIBUTECHANGE; | ||
448 | moreWork.LocalId = localID; | ||
449 | m_WorkQueue.Enqueue(moreWork); | ||
450 | m_log.Debug("[CONTENT MANAGEMENT] pos"); | ||
451 | } | ||
452 | |||
453 | protected void UpdateMultipleRotation(uint localID, Quaternion rot, IClientAPI remoteClient) | ||
454 | { | ||
455 | Work moreWork = new Work(); | ||
456 | moreWork.Type = WorkType.OBJECTATTRIBUTECHANGE; | ||
457 | moreWork.LocalId = localID; | ||
458 | m_WorkQueue.Enqueue(moreWork); | ||
459 | m_log.Debug("[CONTENT MANAGEMENT] rot"); | ||
460 | } | ||
461 | |||
462 | protected void UpdateMultipleScale(uint localID, Vector3 scale, IClientAPI remoteClient) | ||
463 | { | ||
464 | Work moreWork = new Work(); | ||
465 | moreWork.Type = WorkType.OBJECTATTRIBUTECHANGE; | ||
466 | moreWork.LocalId = localID; | ||
467 | m_WorkQueue.Enqueue(moreWork); | ||
468 | m_log.Debug("[CONTENT MANAGEMENT]scale"); | ||
469 | } | ||
470 | |||
471 | protected void UpdateNewParts(UUID ownerID, UUID groupID, Vector3 RayEnd, Quaternion rot, PrimitiveBaseShape shape, | ||
472 | byte bypassRaycast, Vector3 RayStart, UUID RayTargetID, | ||
473 | byte RayEndIsIntersection) | ||
474 | { | ||
475 | Work moreWork = new Work(); | ||
476 | moreWork.Type = WorkType.PRIMITIVEADDED; | ||
477 | moreWork.UUID = ownerID; | ||
478 | m_WorkQueue.Enqueue(moreWork); | ||
479 | m_log.Debug("[CONTENT MANAGEMENT] new parts"); | ||
480 | } | ||
481 | |||
482 | protected void UpdateSinglePosition(uint localID, Vector3 pos, IClientAPI remoteClient) | ||
483 | { | ||
484 | Work moreWork = new Work(); | ||
485 | moreWork.Type = WorkType.OBJECTATTRIBUTECHANGE; | ||
486 | moreWork.LocalId = localID; | ||
487 | m_WorkQueue.Enqueue(moreWork); | ||
488 | m_log.Debug("[CONTENT MANAGEMENT] move"); | ||
489 | } | ||
490 | |||
491 | /// <summary> | ||
492 | /// | ||
493 | /// </summary> | ||
494 | protected void UpdateSingleRotation(uint localID, Quaternion rot, IClientAPI remoteClient) | ||
495 | { | ||
496 | Work moreWork = new Work(); | ||
497 | moreWork.Type = WorkType.OBJECTATTRIBUTECHANGE; | ||
498 | moreWork.LocalId = localID; | ||
499 | m_WorkQueue.Enqueue(moreWork); | ||
500 | m_log.Debug("[CONTENT MANAGEMENT] rot"); | ||
501 | } | ||
502 | |||
503 | protected void UpdateSingleScale(uint localID, Vector3 scale, IClientAPI remoteClient) | ||
504 | { | ||
505 | Work moreWork = new Work(); | ||
506 | moreWork.Type = WorkType.OBJECTATTRIBUTECHANGE; | ||
507 | moreWork.LocalId = localID; | ||
508 | m_WorkQueue.Enqueue(moreWork); | ||
509 | m_log.Debug("[CONTENT MANAGEMENT] scale"); | ||
510 | } | ||
511 | |||
512 | /// <summary> | ||
513 | /// Only called from within the SimChat method. | ||
514 | /// </summary> | ||
515 | protected void commit(string message, Scene scene, CMModel model, CMView view) | ||
516 | { | ||
517 | System.Collections.Generic.List<Scene> proximitySceneList = ScenesInOrderOfProximity(m_sceneList, scene); | ||
518 | |||
519 | string[] args = message.Split(new char[] {' '}); | ||
520 | |||
521 | char[] logMessage = {' '}; | ||
522 | if (args.Length > 1) | ||
523 | { | ||
524 | logMessage = new char[message.Length - (args[0].Length)]; | ||
525 | message.CopyTo(args[0].Length, logMessage, 0, message.Length - (args[0].Length)); | ||
526 | } | ||
527 | |||
528 | m_log.Debug("[CONTENT MANAGEMENT] Saving terrain and objects of region."); | ||
529 | foreach (Scene currScene in proximitySceneList) | ||
530 | { | ||
531 | model.CommitRegion(currScene, new String(logMessage)); | ||
532 | view.SendSimChatMessage(scene, "Region Saved Successfully: " + currScene.RegionInfo.RegionName); | ||
533 | } | ||
534 | |||
535 | view.SendSimChatMessage(scene, "Successfully saved all regions."); | ||
536 | m_state |= State.DIRTY; | ||
537 | |||
538 | if ((m_state & State.SHOWING_CHANGES) > 0) //DISPLAY NEW CHANGES INSTEAD OF OLD CHANGES | ||
539 | { | ||
540 | view.SendSimChatMessage(scene, "Updating differences between new revision and current environment."); | ||
541 | //Hide objects from users and Forget about them | ||
542 | view.HideAllMetaEntities(); | ||
543 | view.HideAllAuras(); | ||
544 | model.DeleteAllMetaObjects(); | ||
545 | |||
546 | //Recreate them from backend files | ||
547 | foreach (Scene currScene in proximitySceneList) | ||
548 | { | ||
549 | model.UpdateCMEntities(currScene); | ||
550 | view.SendSimChatMessage(scene, "Finished updating differences between current scene and last revision: " + currScene.RegionInfo.RegionName); | ||
551 | } | ||
552 | |||
553 | //Display new objects to users1 | ||
554 | view.DisplayRecentChanges(); | ||
555 | view.SendSimChatMessage(scene, "Finished updating for DIFF-MODE."); | ||
556 | m_state &= ~(State.DIRTY); | ||
557 | m_state |= State.SHOWING_CHANGES; | ||
558 | } | ||
559 | } | ||
560 | |||
561 | /// <summary> | ||
562 | /// Only called from within the SimChat method. | ||
563 | /// </summary> | ||
564 | protected void diffmode(Scene scene, CMModel model, CMView view) | ||
565 | { | ||
566 | System.Collections.Generic.List<Scene> proximitySceneList = ScenesInOrderOfProximity(m_sceneList, scene); | ||
567 | |||
568 | if ((m_state & State.SHOWING_CHANGES) > 0) // TURN OFF | ||
569 | { | ||
570 | view.SendSimChatMessage(scene, "Hiding all meta objects."); | ||
571 | view.HideAllMetaEntities(); | ||
572 | view.HideAllAuras(); | ||
573 | view.SendSimChatMessage(scene, "Diff-mode = OFF"); | ||
574 | |||
575 | m_state &= ~State.SHOWING_CHANGES; | ||
576 | return; | ||
577 | } | ||
578 | else // TURN ON | ||
579 | { | ||
580 | if ((m_state & State.DIRTY) != 0 || m_state == State.NONE) | ||
581 | { | ||
582 | view.SendSimChatMessage(scene, "Hiding meta objects and replacing with latest revision"); | ||
583 | //Hide objects from users and Forget about them | ||
584 | view.HideAllMetaEntities(); | ||
585 | view.HideAllAuras(); | ||
586 | model.DeleteAllMetaObjects(); | ||
587 | //Recreate them from backend files | ||
588 | foreach (Object currScene in m_sceneList.Values) | ||
589 | model.UpdateCMEntities((Scene) currScene); | ||
590 | } | ||
591 | else if ((m_state & State.DIRTY) != 0) { | ||
592 | view.SendSimChatMessage(scene, "Forming list of meta entities with latest revision"); | ||
593 | foreach (Scene currScene in proximitySceneList) | ||
594 | model.UpdateCMEntities(currScene); | ||
595 | } | ||
596 | |||
597 | view.SendSimChatMessage(scene, "Displaying differences between last revision and current environment"); | ||
598 | foreach (Scene currScene in proximitySceneList) | ||
599 | model.CheckForNewEntitiesMissingAuras(currScene); | ||
600 | view.DisplayRecentChanges(); | ||
601 | |||
602 | view.SendSimChatMessage(scene, "Diff-mode = ON"); | ||
603 | m_state |= State.SHOWING_CHANGES; | ||
604 | m_state &= ~State.DIRTY; | ||
605 | } | ||
606 | } | ||
607 | |||
608 | /// <summary> | ||
609 | /// Only called from within the SimChat method. Hides all auras and meta entities, | ||
610 | /// retrieves the current scene object list with the most recent revision retrieved from the model for each scene, | ||
611 | /// then lets the view update the clients of the new objects. | ||
612 | /// </summary> | ||
613 | protected void rollback(Scene scene, CMModel model, CMView view) | ||
614 | { | ||
615 | if ((m_state & State.SHOWING_CHANGES) > 0) | ||
616 | { | ||
617 | view.HideAllAuras(); | ||
618 | view.HideAllMetaEntities(); | ||
619 | } | ||
620 | |||
621 | System.Collections.Generic.List<Scene> proximitySceneList = ScenesInOrderOfProximity(m_sceneList, scene); | ||
622 | foreach (Scene currScene in proximitySceneList) | ||
623 | model.RollbackRegion(currScene); | ||
624 | |||
625 | if ((m_state & State.DIRTY) != 0) | ||
626 | { | ||
627 | model.DeleteAllMetaObjects(); | ||
628 | foreach (Scene currScene in proximitySceneList) | ||
629 | model.UpdateCMEntities(currScene); | ||
630 | } | ||
631 | |||
632 | if ((m_state & State.SHOWING_CHANGES) > 0) | ||
633 | view.DisplayRecentChanges(); | ||
634 | } | ||
635 | |||
636 | #endregion Protected Methods | ||
637 | |||
638 | #region Public Methods | ||
639 | |||
640 | /// <summary> | ||
641 | /// Register a new scene object to keep track of for revisioning. Starts the controller monitoring actions of clients within the given scene. | ||
642 | /// </summary> | ||
643 | /// <param name="scene"> | ||
644 | /// A <see cref="Scene"/> | ||
645 | /// </param> | ||
646 | public void RegisterNewRegion(Scene scene) | ||
647 | { | ||
648 | m_sceneList.Add(scene.RegionInfo.RegionID, scene); | ||
649 | |||
650 | m_log.Debug("[CONTENT MANAGEMENT] Registering new region: " + scene.RegionInfo.RegionID); | ||
651 | m_log.Debug("[CONTENT MANAGEMENT] Initializing Content Management System."); | ||
652 | |||
653 | scene.EventManager.OnNewClient += StartManaging; | ||
654 | scene.EventManager.OnChatFromClient += SimChatSent; | ||
655 | scene.EventManager.OnRemovePresence += StopManaging; | ||
656 | // scene.EventManager.OnAvatarEnteringNewParcel += AvatarEnteringParcel; | ||
657 | scene.EventManager.OnObjectBeingRemovedFromScene += GroupBeingDeleted; | ||
658 | } | ||
659 | |||
660 | /// <summary> | ||
661 | /// Only called by the MainLoop. Takes the message from a user sent to the channel and executes the proper command. | ||
662 | /// </summary> | ||
663 | public void SimChat(CMModel model, CMView view, OSChatMessage e, int channel) | ||
664 | { | ||
665 | if (e.Channel != channel) | ||
666 | return; | ||
667 | if (e.Sender == null) | ||
668 | return; | ||
669 | |||
670 | m_log.Debug("[CONTENT MANAGEMENT] Message received: " + e.Message); | ||
671 | |||
672 | IClientAPI client = e.Sender; | ||
673 | Scene scene = (Scene) e.Scene; | ||
674 | string message = e.Message; | ||
675 | string[] args = e.Message.Split(new char[] {' '}); | ||
676 | |||
677 | ScenePresence avatar = scene.GetScenePresence(client.AgentId); | ||
678 | |||
679 | if (!(m_estateModule.IsManager(avatar.UUID))) | ||
680 | { | ||
681 | m_log.Debug("[CONTENT MANAGEMENT] Message sent from non Estate Manager ... ignoring."); | ||
682 | view.SendSimChatMessage(scene, "You must be an estate manager to perform that action."); | ||
683 | return; | ||
684 | } | ||
685 | |||
686 | switch (args[0]) | ||
687 | { | ||
688 | case "ci": | ||
689 | case "commit": | ||
690 | commit(message, scene, model, view); | ||
691 | break; | ||
692 | case "dm": | ||
693 | case "diff-mode": | ||
694 | diffmode(scene, model, view); | ||
695 | break; | ||
696 | case "rb": | ||
697 | case "rollback": | ||
698 | rollback(scene, model, view); | ||
699 | break; | ||
700 | case "help": | ||
701 | m_view.DisplayHelpMenu(scene); | ||
702 | break; | ||
703 | default: | ||
704 | view.SendSimChatMessage(scene, "Command not found: " + args[0]); | ||
705 | break; | ||
706 | } | ||
707 | } | ||
708 | |||
709 | #endregion Public Methods | ||
710 | |||
711 | #region Other | ||
712 | |||
713 | /// <value> | ||
714 | /// Used to keep track of whether a list has been produced yet and whether that list is up-to-date compard to latest revision on disk. | ||
715 | /// </value> | ||
716 | [Flags] | ||
717 | private enum State | ||
718 | { | ||
719 | NONE = 0, | ||
720 | DIRTY = 1, // The meta entities may not correctly represent the last revision. | ||
721 | SHOWING_CHANGES = 1<<1 // The meta entities are being shown to user. | ||
722 | } | ||
723 | |||
724 | /// <value> | ||
725 | /// The structure that defines the basic unit of work which is produced when a user sends commands to the ContentMangaementSystem. | ||
726 | /// </value> | ||
727 | private struct Work | ||
728 | { | ||
729 | #region Fields | ||
730 | |||
731 | public Object Data1; //Just space for holding data. | ||
732 | public Object Data2; //Just more space for holding data. | ||
733 | public uint LocalId; //Convenient | ||
734 | public WorkType Type; | ||
735 | public UUID UUID; //Convenient | ||
736 | |||
737 | #endregion Fields | ||
738 | } | ||
739 | |||
740 | /// <value> | ||
741 | /// Identifies what the data in struct Work should be used for. | ||
742 | /// </value> | ||
743 | private enum WorkType | ||
744 | { | ||
745 | NONE, | ||
746 | OBJECTATTRIBUTECHANGE, | ||
747 | PRIMITIVEADDED, | ||
748 | OBJECTDUPLICATED, | ||
749 | OBJECTKILLED, | ||
750 | UNDODID, | ||
751 | NEWCLIENT, | ||
752 | SIMCHAT | ||
753 | } | ||
754 | |||
755 | #endregion Other | ||
756 | } | ||
757 | } | ||
diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/CMEntityCollection.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/CMEntityCollection.cs new file mode 100644 index 0000000..d5cf596 --- /dev/null +++ b/OpenSim/Region/OptionalModules/ContentManagementSystem/CMEntityCollection.cs | |||
@@ -0,0 +1,193 @@ | |||
1 | /* | ||
2 | * Copyright (c) Contributors, http://opensimulator.org/ | ||
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions are met: | ||
7 | * * Redistributions of source code must retain the above copyright | ||
8 | * notice, this list of conditions and the following disclaimer. | ||
9 | * * Redistributions in binary form must reproduce the above copyright | ||
10 | * notice, this list of conditions and the following disclaimer in the | ||
11 | * documentation and/or other materials provided with the distribution. | ||
12 | * * Neither the name of the OpenSim Project nor the | ||
13 | * names of its contributors may be used to endorse or promote products | ||
14 | * derived from this software without specific prior written permission. | ||
15 | * | ||
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | */ | ||
27 | |||
28 | #region Header | ||
29 | |||
30 | // CMEntityCollection.cs created with MonoDevelop | ||
31 | // User: bongiojp at 10:09 AMĀ 7/7/2008 | ||
32 | // | ||
33 | // Creates, Deletes, Stores ContentManagementEntities | ||
34 | // | ||
35 | |||
36 | #endregion Header | ||
37 | |||
38 | using System; | ||
39 | using System.Collections; | ||
40 | using System.Collections.Generic; | ||
41 | using System.Threading; | ||
42 | |||
43 | using OpenMetaverse; | ||
44 | |||
45 | using Nini.Config; | ||
46 | |||
47 | using OpenSim; | ||
48 | using OpenSim.Framework; | ||
49 | using OpenSim.Region.Framework.Interfaces; | ||
50 | using OpenSim.Region.Framework.Scenes; | ||
51 | using OpenSim.Region.Physics.Manager; | ||
52 | |||
53 | using log4net; | ||
54 | |||
55 | namespace OpenSim.Region.OptionalModules.ContentManagement | ||
56 | { | ||
57 | public class CMEntityCollection | ||
58 | { | ||
59 | #region Fields | ||
60 | |||
61 | // private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); | ||
62 | // Any ContentManagementEntities that represent old versions of current SceneObjectGroups or | ||
63 | // old versions of deleted SceneObjectGroups will be stored in this hash table. | ||
64 | // The UUID keys are from the SceneObjectGroup RootPart UUIDs | ||
65 | protected Hashtable m_CMEntityHash = Hashtable.Synchronized(new Hashtable()); //UUID to ContentManagementEntity | ||
66 | |||
67 | // SceneObjectParts that have not been revisioned will be given green auras stored in this hashtable | ||
68 | // The UUID keys are from the SceneObjectPart that they are supposed to be on. | ||
69 | protected Hashtable m_NewlyCreatedEntityAura = Hashtable.Synchronized(new Hashtable()); //UUID to AuraMetaEntity | ||
70 | |||
71 | #endregion Fields | ||
72 | |||
73 | #region Constructors | ||
74 | |||
75 | public CMEntityCollection() | ||
76 | { | ||
77 | } | ||
78 | |||
79 | #endregion Constructors | ||
80 | |||
81 | #region Public Properties | ||
82 | |||
83 | public Hashtable Auras | ||
84 | { | ||
85 | get {return m_NewlyCreatedEntityAura; } | ||
86 | } | ||
87 | |||
88 | public Hashtable Entities | ||
89 | { | ||
90 | get { return m_CMEntityHash; } | ||
91 | } | ||
92 | |||
93 | #endregion Public Properties | ||
94 | |||
95 | #region Public Methods | ||
96 | |||
97 | public bool AddAura(ContentManagementEntity aura) | ||
98 | { | ||
99 | if (m_NewlyCreatedEntityAura.ContainsKey(aura.UUID)) | ||
100 | return false; | ||
101 | m_NewlyCreatedEntityAura.Add(aura.UUID, aura); | ||
102 | return true; | ||
103 | } | ||
104 | |||
105 | public bool AddEntity(ContentManagementEntity ent) | ||
106 | { | ||
107 | if (m_CMEntityHash.ContainsKey(ent.UUID)) | ||
108 | return false; | ||
109 | m_CMEntityHash.Add(ent.UUID, ent); | ||
110 | return true; | ||
111 | } | ||
112 | |||
113 | // Check if there are SceneObjectGroups in the list that do not have corresponding ContentManagementGroups in the CMEntityHash | ||
114 | public System.Collections.ArrayList CheckForMissingEntities(System.Collections.Generic.List<EntityBase> currList) | ||
115 | { | ||
116 | System.Collections.ArrayList missingList = new System.Collections.ArrayList(); | ||
117 | SceneObjectGroup temp = null; | ||
118 | foreach (EntityBase currObj in currList) | ||
119 | { | ||
120 | if (!(currObj is SceneObjectGroup)) | ||
121 | continue; | ||
122 | temp = (SceneObjectGroup) currObj; | ||
123 | |||
124 | if (m_CMEntityHash.ContainsKey(temp.UUID)) | ||
125 | { | ||
126 | foreach (SceneObjectPart part in temp.Children.Values) | ||
127 | if (!((ContentManagementEntity)m_CMEntityHash[temp.UUID]).HasChildPrim(part.UUID)) | ||
128 | missingList.Add(part); | ||
129 | } | ||
130 | else //Entire group is missing from revision. (and is a new part in region) | ||
131 | { | ||
132 | foreach (SceneObjectPart part in temp.Children.Values) | ||
133 | missingList.Add(part); | ||
134 | } | ||
135 | } | ||
136 | return missingList; | ||
137 | } | ||
138 | |||
139 | public void ClearAll() | ||
140 | { | ||
141 | m_CMEntityHash.Clear(); | ||
142 | m_NewlyCreatedEntityAura.Clear(); | ||
143 | } | ||
144 | |||
145 | // Old uuid and new sceneobjectgroup | ||
146 | public AuraMetaEntity CreateAuraForNewlyCreatedEntity(SceneObjectPart part) | ||
147 | { | ||
148 | AuraMetaEntity ent = new AuraMetaEntity(part.ParentGroup.Scene, | ||
149 | part.GetWorldPosition(), | ||
150 | MetaEntity.TRANSLUCENT, | ||
151 | new Vector3(0,254,0), | ||
152 | part.Scale | ||
153 | ); | ||
154 | m_NewlyCreatedEntityAura.Add(part.UUID, ent); | ||
155 | return ent; | ||
156 | } | ||
157 | |||
158 | // Old uuid and new sceneobjectgroup | ||
159 | public ContentManagementEntity CreateNewEntity(SceneObjectGroup group) | ||
160 | { | ||
161 | ContentManagementEntity ent = new ContentManagementEntity(group, false); | ||
162 | m_CMEntityHash.Add(group.UUID, ent); | ||
163 | return ent; | ||
164 | } | ||
165 | |||
166 | public ContentManagementEntity CreateNewEntity(String xml, Scene scene) | ||
167 | { | ||
168 | ContentManagementEntity ent = new ContentManagementEntity(xml, scene, false); | ||
169 | if (ent == null) | ||
170 | return null; | ||
171 | m_CMEntityHash.Add(ent.UnchangedEntity.UUID, ent); | ||
172 | return ent; | ||
173 | } | ||
174 | |||
175 | public bool RemoveEntity(UUID uuid) | ||
176 | { | ||
177 | if (!m_CMEntityHash.ContainsKey(uuid)) | ||
178 | return false; | ||
179 | m_CMEntityHash.Remove(uuid); | ||
180 | return true; | ||
181 | } | ||
182 | |||
183 | public bool RemoveNewlyCreatedEntityAura(UUID uuid) | ||
184 | { | ||
185 | if (!m_NewlyCreatedEntityAura.ContainsKey(uuid)) | ||
186 | return false; | ||
187 | m_NewlyCreatedEntityAura.Remove(uuid); | ||
188 | return true; | ||
189 | } | ||
190 | |||
191 | #endregion Public Methods | ||
192 | } | ||
193 | } | ||
diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/CMModel.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/CMModel.cs new file mode 100644 index 0000000..761dca9 --- /dev/null +++ b/OpenSim/Region/OptionalModules/ContentManagementSystem/CMModel.cs | |||
@@ -0,0 +1,362 @@ | |||
1 | ļ»æ/* | ||
2 | * Copyright (c) Contributors, http://opensimulator.org/ | ||
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions are met: | ||
7 | * * Redistributions of source code must retain the above copyright | ||
8 | * notice, this list of conditions and the following disclaimer. | ||
9 | * * Redistributions in binary form must reproduce the above copyright | ||
10 | * notice, this list of conditions and the following disclaimer in the | ||
11 | * documentation and/or other materials provided with the distribution. | ||
12 | * * Neither the name of the OpenSim Project nor the | ||
13 | * names of its contributors may be used to endorse or promote products | ||
14 | * derived from this software without specific prior written permission. | ||
15 | * | ||
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | */ | ||
27 | |||
28 | #region Header | ||
29 | |||
30 | // CMModel.cs | ||
31 | // User: bongiojp | ||
32 | // | ||
33 | // | ||
34 | |||
35 | #endregion Header | ||
36 | |||
37 | using System; | ||
38 | using System.Collections; | ||
39 | using System.Collections.Generic; | ||
40 | using System.Diagnostics; | ||
41 | |||
42 | using OpenMetaverse; | ||
43 | |||
44 | using OpenSim; | ||
45 | using OpenSim.Framework; | ||
46 | using OpenSim.Region.Framework.Interfaces; | ||
47 | using OpenSim.Region.Framework.Scenes; | ||
48 | using OpenSim.Region.Physics.Manager; | ||
49 | |||
50 | using log4net; | ||
51 | |||
52 | namespace OpenSim.Region.OptionalModules.ContentManagement | ||
53 | { | ||
54 | public class CMModel | ||
55 | { | ||
56 | #region Static Fields | ||
57 | |||
58 | static float TimeToUpdate = 0; | ||
59 | static float TimeToConvertXml = 0; | ||
60 | private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); | ||
61 | |||
62 | #endregion Static Fields | ||
63 | |||
64 | #region Fields | ||
65 | |||
66 | /// <value> | ||
67 | /// The class that contains all auras and metaentities used in the CMS. | ||
68 | /// </value> | ||
69 | CMEntityCollection m_MetaEntityCollection = new CMEntityCollection(); | ||
70 | IContentDatabase m_database = null; | ||
71 | |||
72 | #endregion Fields | ||
73 | |||
74 | #region Constructors | ||
75 | |||
76 | public CMModel() | ||
77 | { | ||
78 | } | ||
79 | |||
80 | #endregion Constructors | ||
81 | |||
82 | #region Public Properties | ||
83 | |||
84 | public CMEntityCollection MetaEntityCollection | ||
85 | { | ||
86 | get { return m_MetaEntityCollection; } | ||
87 | } | ||
88 | |||
89 | #endregion Public Properties | ||
90 | |||
91 | #region Public Methods | ||
92 | |||
93 | /// <summary> | ||
94 | /// Compares the scene's object group list to the list of meta entities. If there is an object group that does not have a corresponding meta entity | ||
95 | /// it is a new part that must have a green aura (for diff mode). | ||
96 | /// Returns list of ContentManagementEntities | ||
97 | /// </summary> | ||
98 | public ArrayList CheckForNewEntitiesMissingAuras(Scene scene) | ||
99 | { | ||
100 | ArrayList missingList = null; | ||
101 | ArrayList newList = new ArrayList(); | ||
102 | |||
103 | m_log.Debug("[CONTENT MANAGEMENT] Checking for new scene object parts in scene: " + scene.RegionInfo.RegionName); | ||
104 | |||
105 | //Check if the current scene has groups not included in the current list of MetaEntities | ||
106 | //If so, then the current scene's parts that are new should be marked green. | ||
107 | missingList = m_MetaEntityCollection.CheckForMissingEntities(scene.GetEntities()); | ||
108 | |||
109 | foreach (Object missingPart in missingList) | ||
110 | { | ||
111 | if (m_MetaEntityCollection.Auras.ContainsKey(((SceneObjectPart)missingPart).UUID)) | ||
112 | continue; | ||
113 | newList.Add(m_MetaEntityCollection.CreateAuraForNewlyCreatedEntity((SceneObjectPart)missingPart)); | ||
114 | } | ||
115 | m_log.Info("Number of missing objects found: " + newList.Count); | ||
116 | return newList; | ||
117 | } | ||
118 | |||
119 | /// <summary> | ||
120 | /// Uses the database to serialize all current scene objects into xml and save into a database with an accompanying log message. | ||
121 | /// </summary> | ||
122 | public void CommitRegion(Scene scene, String logMessage) | ||
123 | { | ||
124 | m_log.Debug("[CONTENT MANAG] saving " + scene.RegionInfo.RegionName + " with log message: " + logMessage + " length of message: " + logMessage.Length); | ||
125 | m_database.SaveRegion(scene.RegionInfo.RegionID, scene.RegionInfo.RegionName, logMessage); | ||
126 | m_log.Debug("[CONTENT MANAG] the region name we are dealing with heeeeeeeere: " + scene.RegionInfo.RegionName ); | ||
127 | } | ||
128 | |||
129 | public void DeleteAllMetaObjects() | ||
130 | { | ||
131 | m_MetaEntityCollection.ClearAll(); | ||
132 | } | ||
133 | |||
134 | public ContentManagementEntity FindMetaEntityAffectedByUndo(UUID uuid) | ||
135 | { | ||
136 | ContentManagementEntity ent = GetMetaGroupByPrim(uuid); | ||
137 | return ent; | ||
138 | } | ||
139 | |||
140 | //-------------------------------- HELPERS --------------------------------------------------------------------// | ||
141 | public ContentManagementEntity GetMetaGroupByPrim(UUID uuid) | ||
142 | { | ||
143 | foreach (Object ent in m_MetaEntityCollection.Entities.Values) | ||
144 | { | ||
145 | if (((ContentManagementEntity)ent).HasChildPrim(uuid)) | ||
146 | return (ContentManagementEntity)ent; | ||
147 | } | ||
148 | return null; | ||
149 | } | ||
150 | |||
151 | public void Initialise(string database) | ||
152 | { | ||
153 | if (database == "FileSystemDatabase") | ||
154 | m_database = new FileSystemDatabase(); | ||
155 | else if (database == "GitDatabase") | ||
156 | m_database = new GitDatabase(); | ||
157 | } | ||
158 | |||
159 | public void InitialiseDatabase(Scene scene, string dir) | ||
160 | { | ||
161 | m_database.Initialise(scene, dir); | ||
162 | } | ||
163 | |||
164 | /// <summary> | ||
165 | /// Should be called just once to finish initializing the database. | ||
166 | /// </summary> | ||
167 | public void PostInitialise() | ||
168 | { | ||
169 | m_database.PostInitialise(); | ||
170 | } | ||
171 | |||
172 | /// <summary> | ||
173 | /// Removes the green aura when an a new scene object group is deleted. | ||
174 | /// </summary> | ||
175 | public void RemoveOrUpdateDeletedEntity(SceneObjectGroup group) | ||
176 | { | ||
177 | // Deal with new parts not revisioned that have been deleted. | ||
178 | foreach (SceneObjectPart part in group.Children.Values) | ||
179 | if (m_MetaEntityCollection.Auras.ContainsKey(part.UUID)) | ||
180 | m_MetaEntityCollection.RemoveNewlyCreatedEntityAura(part.UUID); | ||
181 | } | ||
182 | |||
183 | /// <summary> | ||
184 | /// Retrieves the latest revision of a region in xml form, | ||
185 | /// converts it to scene object groups and scene presences, | ||
186 | /// swaps the current scene's entity list with the revision's list. | ||
187 | /// Note: Since deleted objects while | ||
188 | /// </summary> | ||
189 | public void RollbackRegion(Scene scene) | ||
190 | { | ||
191 | System.Collections.ArrayList xmllist = null; | ||
192 | SceneObjectGroup temp = null; | ||
193 | System.Collections.Hashtable deleteListUUIDs = new Hashtable(); | ||
194 | // Dictionary<LLUUID, EntityBase> SearchList = new Dictionary<LLUUID,EntityBase>(); | ||
195 | Dictionary<UUID, EntityBase> ReplacementList = new Dictionary<UUID,EntityBase>(); | ||
196 | int revision = m_database.GetMostRecentRevision(scene.RegionInfo.RegionID); | ||
197 | // EntityBase[] searchArray; | ||
198 | |||
199 | xmllist = m_database.GetRegionObjectXMLList(scene.RegionInfo.RegionID, revision); | ||
200 | if (xmllist == null) | ||
201 | { | ||
202 | m_log.Info("[CMMODEL]: Region (" + scene.RegionInfo.RegionID + ") does not have given revision number (" + revision + ")."); | ||
203 | return; | ||
204 | } | ||
205 | |||
206 | m_log.Info("[CMMODEL]: Region (" + scene.RegionInfo.RegionID + ") revision number (" + revision + ")."); | ||
207 | m_log.Info("[CMMODEL]: Scene Objects = " + xmllist.Count); | ||
208 | m_log.Info("[CMMODEL]: Converting scene entities list to specified revision."); | ||
209 | |||
210 | m_log.ErrorFormat("[CMMODEL]: 1"); | ||
211 | |||
212 | foreach (string xml in xmllist) | ||
213 | { | ||
214 | try{ | ||
215 | temp = new SceneObjectGroup(xml); | ||
216 | temp.SetScene(scene); | ||
217 | foreach (SceneObjectPart part in temp.Children.Values) | ||
218 | part.RegionHandle = scene.RegionInfo.RegionHandle; | ||
219 | ReplacementList.Add(temp.UUID, (EntityBase)temp); | ||
220 | } | ||
221 | catch(Exception e) | ||
222 | { | ||
223 | m_log.Info("[CMMODEL]: Error while creating replacement list for rollback: " + e); | ||
224 | } | ||
225 | } | ||
226 | |||
227 | //If in scene but not in revision and not a client, remove them | ||
228 | while (true) | ||
229 | { | ||
230 | try | ||
231 | { | ||
232 | foreach (EntityBase entity in scene.GetEntities()) | ||
233 | { | ||
234 | if (entity == null) | ||
235 | continue; | ||
236 | |||
237 | if (entity is ScenePresence) | ||
238 | { | ||
239 | ReplacementList.Add(entity.UUID, entity); | ||
240 | continue; | ||
241 | } | ||
242 | else //if (!ReplacementList.ContainsKey(entity.UUID)) | ||
243 | deleteListUUIDs.Add(entity.UUID, 0); | ||
244 | } | ||
245 | } | ||
246 | catch(Exception e) | ||
247 | { | ||
248 | m_log.ErrorFormat("[CMMODEL]: " + e); | ||
249 | deleteListUUIDs.Clear(); | ||
250 | ReplacementList.Clear(); | ||
251 | continue; | ||
252 | } | ||
253 | break; | ||
254 | } | ||
255 | |||
256 | foreach (UUID uuid in deleteListUUIDs.Keys) | ||
257 | { | ||
258 | try | ||
259 | { | ||
260 | // I thought that the DeleteGroup() function would handle all of this, but it doesn't. I'm not sure WHAT it handles. | ||
261 | ((SceneObjectGroup)scene.Entities[uuid]).DetachFromBackup(); | ||
262 | scene.PhysicsScene.RemovePrim(((SceneObjectGroup)scene.Entities[uuid]).RootPart.PhysActor); | ||
263 | scene.SendKillObject(scene.Entities[uuid].LocalId); | ||
264 | scene.m_sceneGraph.DeleteSceneObject(uuid, false); | ||
265 | ((SceneObjectGroup)scene.Entities[uuid]).DeleteGroup(false); | ||
266 | } | ||
267 | catch(Exception e) | ||
268 | { | ||
269 | m_log.ErrorFormat("[CMMODEL]: Error while removing objects from scene: " + e); | ||
270 | } | ||
271 | } | ||
272 | |||
273 | lock (scene) | ||
274 | { | ||
275 | scene.Entities.Clear(); | ||
276 | |||
277 | foreach (KeyValuePair<UUID,EntityBase> kvp in ReplacementList) | ||
278 | { | ||
279 | scene.Entities.Add(kvp.Value); | ||
280 | } | ||
281 | } | ||
282 | |||
283 | foreach (EntityBase ent in ReplacementList.Values) | ||
284 | { | ||
285 | try | ||
286 | { | ||
287 | if (!(ent is SceneObjectGroup)) | ||
288 | continue; | ||
289 | |||
290 | if ((((SceneObjectGroup)ent).RootPart.GetEffectiveObjectFlags() & (uint) PrimFlags.Phantom) == 0) | ||
291 | ((SceneObjectGroup)ent).ApplyPhysics(true); | ||
292 | ((SceneObjectGroup)ent).AttachToBackup(); | ||
293 | ((SceneObjectGroup)ent).HasGroupChanged = true; // If not true, then attaching to backup does nothing because no change is detected. | ||
294 | ((SceneObjectGroup)ent).ScheduleGroupForFullUpdate(); | ||
295 | } | ||
296 | catch(Exception e) | ||
297 | { | ||
298 | m_log.ErrorFormat("[CMMODEL]: Error while attaching new scene entities to backup and scheduling for a full update: " + e); | ||
299 | } | ||
300 | } | ||
301 | m_log.Info("[CMMODEL]: Scheduling a backup of new scene object groups to backup."); | ||
302 | scene.Backup(); | ||
303 | } | ||
304 | |||
305 | /// <summary> | ||
306 | /// Downloads the latest revision of the given scene and converts the xml file to CMEntities. After this method, the view can find the differences | ||
307 | /// and display the differences to clients. | ||
308 | /// </summary> | ||
309 | public void UpdateCMEntities(Scene scene) | ||
310 | { | ||
311 | Stopwatch x = new Stopwatch(); | ||
312 | x.Start(); | ||
313 | |||
314 | System.Collections.ArrayList xmllist = null; | ||
315 | m_log.Debug("[CONTENT MANAGEMENT] Retrieving object xml files for region: " + scene.RegionInfo.RegionID); | ||
316 | xmllist = m_database.GetRegionObjectXMLList(scene.RegionInfo.RegionID); | ||
317 | m_log.Info("[FSDB]: got list"); | ||
318 | if (xmllist == null) | ||
319 | return; | ||
320 | |||
321 | Stopwatch y = new Stopwatch(); | ||
322 | y.Start(); | ||
323 | foreach (string xml in xmllist) | ||
324 | m_MetaEntityCollection.CreateNewEntity(xml, scene); | ||
325 | y.Stop(); | ||
326 | TimeToConvertXml += y.ElapsedMilliseconds; | ||
327 | m_log.Info("[FileSystemDatabase] Time spent converting xml to metaentities for " + scene.RegionInfo.RegionName + ": " + y.ElapsedMilliseconds); | ||
328 | m_log.Info("[FileSystemDatabase] Time spent converting xml to metaentities so far: " + TimeToConvertXml); | ||
329 | |||
330 | m_log.Info("[FSDB]: checking for new scene object parts missing green auras and create the auras"); | ||
331 | CheckForNewEntitiesMissingAuras(scene); | ||
332 | |||
333 | x.Stop(); | ||
334 | TimeToUpdate += x.ElapsedMilliseconds; | ||
335 | m_log.Info("[FileSystemDatabase] Time spent Updating entity list for " + scene.RegionInfo.RegionName + ": " + x.ElapsedMilliseconds); | ||
336 | m_log.Info("[FileSystemDatabase] Time spent Updating so far: " + TimeToUpdate); | ||
337 | } | ||
338 | |||
339 | /// <summary> | ||
340 | /// Detects if a scene object group from the scene list has moved or changed scale. The green aura | ||
341 | /// that surrounds the object is then moved or scaled with the group. | ||
342 | /// </summary> | ||
343 | public System.Collections.ArrayList UpdateNormalEntityEffects(SceneObjectGroup group) | ||
344 | { | ||
345 | System.Collections.ArrayList auraList = new System.Collections.ArrayList(); | ||
346 | if (group == null) | ||
347 | return null; | ||
348 | foreach (SceneObjectPart part in group.Children.Values) | ||
349 | { | ||
350 | if (m_MetaEntityCollection.Auras.ContainsKey(part.UUID)) | ||
351 | { | ||
352 | ((AuraMetaEntity)m_MetaEntityCollection.Auras[part.UUID]).SetAura(new Vector3(0,254,0), part.Scale); | ||
353 | ((AuraMetaEntity)m_MetaEntityCollection.Auras[part.UUID]).RootPart.GroupPosition = part.GetWorldPosition(); | ||
354 | auraList.Add((AuraMetaEntity)m_MetaEntityCollection.Auras[part.UUID]); | ||
355 | } | ||
356 | } | ||
357 | return auraList; | ||
358 | } | ||
359 | |||
360 | #endregion Public Methods | ||
361 | } | ||
362 | } | ||
diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/CMView.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/CMView.cs new file mode 100644 index 0000000..a1a4d94 --- /dev/null +++ b/OpenSim/Region/OptionalModules/ContentManagementSystem/CMView.cs | |||
@@ -0,0 +1,206 @@ | |||
1 | /* | ||
2 | * Copyright (c) Contributors, http://opensimulator.org/ | ||
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions are met: | ||
7 | * * Redistributions of source code must retain the above copyright | ||
8 | * notice, this list of conditions and the following disclaimer. | ||
9 | * * Redistributions in binary form must reproduce the above copyright | ||
10 | * notice, this list of conditions and the following disclaimer in the | ||
11 | * documentation and/or other materials provided with the distribution. | ||
12 | * * Neither the name of the OpenSim Project nor the | ||
13 | * names of its contributors may be used to endorse or promote products | ||
14 | * derived from this software without specific prior written permission. | ||
15 | * | ||
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | */ | ||
27 | |||
28 | #region Header | ||
29 | |||
30 | // CMView.cs created with MonoDevelop | ||
31 | // User: bongiojp at 11:57 AMĀ 7/3/2008 | ||
32 | // | ||
33 | // To change standard headers go to Edit->Preferences->Coding->Standard Headers | ||
34 | // | ||
35 | |||
36 | #endregion Header | ||
37 | |||
38 | using System; | ||
39 | using System.Collections; | ||
40 | using System.Collections.Generic; | ||
41 | |||
42 | using OpenMetaverse; | ||
43 | |||
44 | using OpenSim; | ||
45 | using OpenSim.Framework; | ||
46 | using OpenSim.Region.Framework.Interfaces; | ||
47 | using OpenSim.Region.Framework.Scenes; | ||
48 | using OpenSim.Region.Physics.Manager; | ||
49 | |||
50 | using log4net; | ||
51 | |||
52 | namespace OpenSim.Region.OptionalModules.ContentManagement | ||
53 | { | ||
54 | public class CMView | ||
55 | { | ||
56 | #region Static Fields | ||
57 | |||
58 | private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); | ||
59 | |||
60 | #endregion Static Fields | ||
61 | |||
62 | #region Fields | ||
63 | |||
64 | CMModel m_model = null; | ||
65 | |||
66 | #endregion Fields | ||
67 | |||
68 | #region Constructors | ||
69 | |||
70 | public CMView() | ||
71 | { | ||
72 | } | ||
73 | |||
74 | #endregion Constructors | ||
75 | |||
76 | #region Public Methods | ||
77 | |||
78 | // Auras To | ||
79 | public void DisplayAuras(CMEntityCollection auraCollection) | ||
80 | { | ||
81 | foreach (Object ent in auraCollection.Auras.Values) | ||
82 | ((AuraMetaEntity)ent).SendFullUpdateToAll(); | ||
83 | } | ||
84 | |||
85 | // Auras To Client | ||
86 | public void DisplayAuras(CMEntityCollection auraCollection, IClientAPI client) | ||
87 | { | ||
88 | foreach (Object ent in auraCollection.Auras.Values) | ||
89 | ((AuraMetaEntity)ent).SendFullUpdate(client); | ||
90 | } | ||
91 | |||
92 | // Auras from List To ALL | ||
93 | public void DisplayAuras(ArrayList list) | ||
94 | { | ||
95 | foreach (Object ent in list) | ||
96 | { | ||
97 | m_log.Debug("[CONTENT MANAGEMENT] displaying new aura riiiiiiiiiiiight NOW"); | ||
98 | ((AuraMetaEntity)ent).SendFullUpdateToAll(); | ||
99 | } | ||
100 | } | ||
101 | |||
102 | // Entities to ALL | ||
103 | public void DisplayEntities(CMEntityCollection entityCollection) | ||
104 | { | ||
105 | foreach (Object ent in entityCollection.Entities.Values) | ||
106 | ((ContentManagementEntity)ent).SendFullDiffUpdateToAll(); | ||
107 | } | ||
108 | |||
109 | // Entities to Client | ||
110 | public void DisplayEntities(CMEntityCollection entityCollection, IClientAPI client) | ||
111 | { | ||
112 | foreach (Object ent in entityCollection.Entities.Values) | ||
113 | ((ContentManagementEntity)ent).SendFullDiffUpdate(client); | ||
114 | } | ||
115 | |||
116 | // Entities from List to ALL | ||
117 | public void DisplayEntities(ArrayList list) | ||
118 | { | ||
119 | foreach (Object ent in list) | ||
120 | ((ContentManagementEntity)ent).SendFullDiffUpdateToAll(); | ||
121 | } | ||
122 | |||
123 | // Entity to ALL | ||
124 | public void DisplayEntity(ContentManagementEntity ent) | ||
125 | { | ||
126 | ent.SendFullDiffUpdateToAll(); | ||
127 | } | ||
128 | |||
129 | public void DisplayHelpMenu(Scene scene) | ||
130 | { | ||
131 | string menu = "Menu:\n"; | ||
132 | menu += "commit (ci) - saves current state of the region to a database on the server\n"; | ||
133 | menu += "diff-mode (dm) - displays those aspects of region that have not been saved but changed since the very last revision. Will dynamically update as you change environment.\n"; | ||
134 | SendSimChatMessage(scene, menu); | ||
135 | } | ||
136 | |||
137 | public void DisplayMetaEntity(UUID uuid) | ||
138 | { | ||
139 | ContentManagementEntity group = m_model.GetMetaGroupByPrim(uuid); | ||
140 | if (group != null) | ||
141 | group.SendFullDiffUpdateToAll(); | ||
142 | } | ||
143 | |||
144 | /// <summary> | ||
145 | /// update all clients of red/green/blue auras and meta entities that the model knows about. | ||
146 | /// </summary> | ||
147 | public void DisplayRecentChanges() | ||
148 | { | ||
149 | m_log.Debug("[CONTENT MANAGEMENT] Sending update to clients for " + m_model.MetaEntityCollection.Entities.Count + " objects."); | ||
150 | DisplayEntities(m_model.MetaEntityCollection); | ||
151 | DisplayAuras(m_model.MetaEntityCollection); | ||
152 | } | ||
153 | |||
154 | public void Hide(ContentManagementEntity ent) | ||
155 | { | ||
156 | ent.HideFromAll(); | ||
157 | } | ||
158 | |||
159 | public void HideAllAuras() | ||
160 | { | ||
161 | foreach (Object obj in m_model.MetaEntityCollection.Auras.Values) | ||
162 | ((MetaEntity)obj).HideFromAll(); | ||
163 | } | ||
164 | |||
165 | public void HideAllMetaEntities() | ||
166 | { | ||
167 | foreach (Object obj in m_model.MetaEntityCollection.Entities.Values) | ||
168 | ((ContentManagementEntity)obj).HideFromAll(); | ||
169 | } | ||
170 | |||
171 | public void Initialise(CMModel model) | ||
172 | { | ||
173 | m_model = model; | ||
174 | } | ||
175 | |||
176 | /// <summary> | ||
177 | /// Figures out if the part deleted was a new scene object part or a revisioned part that's been deleted. | ||
178 | /// If it's a new scene object, any green aura attached to it is deleted. | ||
179 | /// If a revisioned part is deleted, a new full update is sent to the environment of the meta entity, which will | ||
180 | /// figure out that there should be a red aura and not a blue aura/beam. | ||
181 | /// </summary> | ||
182 | public void RemoveOrUpdateDeletedEntity(SceneObjectGroup group) | ||
183 | { | ||
184 | // Deal with revisioned parts that have been deleted. | ||
185 | if (m_model.MetaEntityCollection.Entities.ContainsKey(group.UUID)) | ||
186 | ((ContentManagementEntity)m_model.MetaEntityCollection.Entities[group.UUID]).SendFullDiffUpdateToAll(); | ||
187 | |||
188 | // Deal with new parts not revisioned that have been deleted. | ||
189 | foreach (SceneObjectPart part in group.Children.Values) | ||
190 | if (m_model.MetaEntityCollection.Auras.ContainsKey(part.UUID)) | ||
191 | ((AuraMetaEntity)m_model.MetaEntityCollection.Auras[part.UUID]).HideFromAll(); | ||
192 | } | ||
193 | |||
194 | public void SendMetaEntitiesToNewClient(IClientAPI client) | ||
195 | { | ||
196 | } | ||
197 | |||
198 | public void SendSimChatMessage(Scene scene, string message) | ||
199 | { | ||
200 | scene.SimChat(Utils.StringToBytes(message), | ||
201 | ChatTypeEnum.Broadcast, 0, new Vector3(0,0,0), "Content Manager", UUID.Zero, false); | ||
202 | } | ||
203 | |||
204 | #endregion Public Methods | ||
205 | } | ||
206 | } | ||
diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/ContentManagementEntity.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/ContentManagementEntity.cs new file mode 100644 index 0000000..4d65038 --- /dev/null +++ b/OpenSim/Region/OptionalModules/ContentManagementSystem/ContentManagementEntity.cs | |||
@@ -0,0 +1,383 @@ | |||
1 | ļ»æ/* | ||
2 | * Copyright (c) Contributors, http://opensimulator.org/ | ||
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions are met: | ||
7 | * * Redistributions of source code must retain the above copyright | ||
8 | * notice, this list of conditions and the following disclaimer. | ||
9 | * * Redistributions in binary form must reproduce the above copyright | ||
10 | * notice, this list of conditions and the following disclaimer in the | ||
11 | * documentation and/or other materials provided with the distribution. | ||
12 | * * Neither the name of the OpenSim Project nor the | ||
13 | * names of its contributors may be used to endorse or promote products | ||
14 | * derived from this software without specific prior written permission. | ||
15 | * | ||
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | */ | ||
27 | |||
28 | #region Header | ||
29 | |||
30 | // ContentManagementEntity.cs | ||
31 | // User: bongiojp | ||
32 | // | ||
33 | // | ||
34 | |||
35 | #endregion Header | ||
36 | |||
37 | using System; | ||
38 | using System.Collections.Generic; | ||
39 | using System.Drawing; | ||
40 | |||
41 | using OpenMetaverse; | ||
42 | |||
43 | using Nini.Config; | ||
44 | |||
45 | using OpenSim.Framework; | ||
46 | using OpenSim.Region.Framework.Interfaces; | ||
47 | using OpenSim.Region.Framework.Scenes; | ||
48 | using OpenSim.Region.Physics.Manager; | ||
49 | |||
50 | using log4net; | ||
51 | |||
52 | namespace OpenSim.Region.OptionalModules.ContentManagement | ||
53 | { | ||
54 | public class ContentManagementEntity : MetaEntity | ||
55 | { | ||
56 | #region Static Fields | ||
57 | |||
58 | // static float TimeToDiff = 0; | ||
59 | // static float TimeToCreateEntities = 0; | ||
60 | |||
61 | #endregion Static Fields | ||
62 | |||
63 | #region Fields | ||
64 | |||
65 | protected Dictionary<UUID, AuraMetaEntity> m_AuraEntities = new Dictionary<UUID, AuraMetaEntity>(); | ||
66 | protected Dictionary<UUID, BeamMetaEntity> m_BeamEntities = new Dictionary<UUID, BeamMetaEntity>(); | ||
67 | |||
68 | // The LinkNum of parts in m_Entity and m_UnchangedEntity are the same though UUID and LocalId are different. | ||
69 | // This can come in handy. | ||
70 | protected SceneObjectGroup m_UnchangedEntity = null; | ||
71 | |||
72 | /// <value> | ||
73 | /// Should be set to true when there is a difference between m_UnchangedEntity and the corresponding scene object group in the scene entity list. | ||
74 | /// </value> | ||
75 | bool DiffersFromSceneGroup = false; | ||
76 | |||
77 | #endregion Fields | ||
78 | |||
79 | #region Constructors | ||
80 | |||
81 | public ContentManagementEntity(SceneObjectGroup Unchanged, bool physics) | ||
82 | : base(Unchanged, false) | ||
83 | { | ||
84 | m_UnchangedEntity = Unchanged.Copy(Unchanged.RootPart.OwnerID, Unchanged.RootPart.GroupID, false); | ||
85 | } | ||
86 | |||
87 | public ContentManagementEntity(string objectXML, Scene scene, bool physics) | ||
88 | : base(objectXML, scene, false) | ||
89 | { | ||
90 | m_UnchangedEntity = new SceneObjectGroup(objectXML); | ||
91 | } | ||
92 | |||
93 | #endregion Constructors | ||
94 | |||
95 | #region Public Properties | ||
96 | |||
97 | public SceneObjectGroup UnchangedEntity | ||
98 | { | ||
99 | get { return m_UnchangedEntity; } | ||
100 | } | ||
101 | |||
102 | #endregion Public Properties | ||
103 | |||
104 | #region Private Methods | ||
105 | |||
106 | /// <summary> | ||
107 | /// Check if an entitybase list (like that returned by scene.GetEntities()) contains a group with the rootpart uuid that matches the current uuid. | ||
108 | /// </summary> | ||
109 | private bool ContainsKey(List<EntityBase> list, UUID uuid) | ||
110 | { | ||
111 | foreach (EntityBase part in list) | ||
112 | if (part.UUID == uuid) | ||
113 | return true; | ||
114 | return false; | ||
115 | } | ||
116 | |||
117 | private SceneObjectGroup GetGroupByUUID(System.Collections.Generic.List<EntityBase> list, UUID uuid) | ||
118 | { | ||
119 | foreach (EntityBase ent in list) | ||
120 | { | ||
121 | if (ent is SceneObjectGroup) | ||
122 | if (ent.UUID == uuid) | ||
123 | return (SceneObjectGroup)ent; | ||
124 | } | ||
125 | return null; | ||
126 | } | ||
127 | |||
128 | #endregion Private Methods | ||
129 | |||
130 | #region Public Methods | ||
131 | |||
132 | /// <summary> | ||
133 | /// 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. | ||
134 | /// If a matching UUID is found in a scene object group, compare the two for differences. If differences exist, Mark the metaentity appropriately. | ||
135 | /// </summary> | ||
136 | public void FindDifferences() | ||
137 | { | ||
138 | System.Collections.Generic.List<EntityBase> sceneEntityList = m_Entity.Scene.GetEntities(); | ||
139 | DiffersFromSceneGroup = false; | ||
140 | // if group is not contained in scene's list | ||
141 | if (!ContainsKey(sceneEntityList, m_UnchangedEntity.UUID)) | ||
142 | { | ||
143 | foreach (SceneObjectPart part in m_UnchangedEntity.Children.Values) | ||
144 | { | ||
145 | // if scene list no longer contains this part, display translucent part and mark with red aura | ||
146 | if (!ContainsKey(sceneEntityList, part.UUID)) | ||
147 | { | ||
148 | // if already displaying a red aura over part, make sure its red | ||
149 | if (m_AuraEntities.ContainsKey(part.UUID)) | ||
150 | { | ||
151 | m_AuraEntities[part.UUID].SetAura(new Vector3(254,0,0), part.Scale); | ||
152 | } | ||
153 | else | ||
154 | { | ||
155 | AuraMetaEntity auraGroup = new AuraMetaEntity(m_Entity.Scene, | ||
156 | part.GetWorldPosition(), | ||
157 | MetaEntity.TRANSLUCENT, | ||
158 | new Vector3(254,0,0), | ||
159 | part.Scale | ||
160 | ); | ||
161 | m_AuraEntities.Add(part.UUID, auraGroup); | ||
162 | } | ||
163 | SceneObjectPart metaPart = m_Entity.GetLinkNumPart(part.LinkNum); | ||
164 | SetPartTransparency(metaPart, MetaEntity.TRANSLUCENT); | ||
165 | } | ||
166 | // otherwise, scene will not contain the part. note: a group can not remove a part without changing group id | ||
167 | } | ||
168 | |||
169 | // a deleted part has no where to point a beam particle system, | ||
170 | // if a metapart had a particle system (maybe it represented a moved part) remove it | ||
171 | if (m_BeamEntities.ContainsKey(m_UnchangedEntity.RootPart.UUID)) | ||
172 | { | ||
173 | m_BeamEntities[m_UnchangedEntity.RootPart.UUID].HideFromAll(); | ||
174 | m_BeamEntities.Remove(m_UnchangedEntity.RootPart.UUID); | ||
175 | } | ||
176 | |||
177 | DiffersFromSceneGroup = true; | ||
178 | } | ||
179 | // if scene list does contain group, compare each part in group for differences and display beams and auras appropriately | ||
180 | else | ||
181 | { | ||
182 | MarkWithDifferences((SceneObjectGroup)GetGroupByUUID(sceneEntityList, m_UnchangedEntity.UUID)); | ||
183 | } | ||
184 | } | ||
185 | |||
186 | /// <summary> | ||
187 | /// Check if the revisioned scene object group that this CMEntity is based off of contains a child with the given UUID. | ||
188 | /// </summary> | ||
189 | public bool HasChildPrim(UUID uuid) | ||
190 | { | ||
191 | if (m_UnchangedEntity.Children.ContainsKey(uuid)) | ||
192 | return true; | ||
193 | return false; | ||
194 | } | ||
195 | |||
196 | /// <summary> | ||
197 | /// Check if the revisioned scene object group that this CMEntity is based off of contains a child with the given LocalId. | ||
198 | /// </summary> | ||
199 | public bool HasChildPrim(uint localID) | ||
200 | { | ||
201 | foreach (SceneObjectPart part in m_UnchangedEntity.Children.Values) | ||
202 | if (part.LocalId == localID) | ||
203 | return true; | ||
204 | return false; | ||
205 | } | ||
206 | |||
207 | public override void Hide(IClientAPI client) | ||
208 | { | ||
209 | base.Hide(client); | ||
210 | foreach (MetaEntity group in m_AuraEntities.Values) | ||
211 | group.Hide(client); | ||
212 | foreach (MetaEntity group in m_BeamEntities.Values) | ||
213 | group.Hide(client); | ||
214 | } | ||
215 | |||
216 | public override void HideFromAll() | ||
217 | { | ||
218 | base.HideFromAll(); | ||
219 | foreach (MetaEntity group in m_AuraEntities.Values) | ||
220 | group.HideFromAll(); | ||
221 | foreach (MetaEntity group in m_BeamEntities.Values) | ||
222 | group.HideFromAll(); | ||
223 | } | ||
224 | |||
225 | /// <summary> | ||
226 | /// Returns true if there was a change between meta entity and the entity group, false otherwise. | ||
227 | /// If true is returned, it is assumed the metaentity's appearance has changed to reflect the difference (though clients haven't been updated). | ||
228 | /// </summary> | ||
229 | public bool MarkWithDifferences(SceneObjectGroup sceneEntityGroup) | ||
230 | { | ||
231 | SceneObjectPart sceneEntityPart; | ||
232 | SceneObjectPart metaEntityPart; | ||
233 | Diff differences; | ||
234 | bool changed = false; | ||
235 | |||
236 | // Use "UnchangedEntity" to do comparisons because its text, transparency, and other attributes will be just as the user | ||
237 | // had originally saved. | ||
238 | // m_Entity will NOT necessarily be the same entity as the user had saved. | ||
239 | foreach (SceneObjectPart UnchangedPart in m_UnchangedEntity.Children.Values) | ||
240 | { | ||
241 | //This is the part that we use to show changes. | ||
242 | metaEntityPart = m_Entity.GetLinkNumPart(UnchangedPart.LinkNum); | ||
243 | if (sceneEntityGroup.Children.ContainsKey(UnchangedPart.UUID)) | ||
244 | { | ||
245 | sceneEntityPart = sceneEntityGroup.Children[UnchangedPart.UUID]; | ||
246 | differences = Difference.FindDifferences(UnchangedPart, sceneEntityPart); | ||
247 | if (differences != Diff.NONE) | ||
248 | metaEntityPart.Text = "CHANGE: " + differences.ToString(); | ||
249 | if (differences != 0) | ||
250 | { | ||
251 | // Root Part that has been modified | ||
252 | if ((differences&Diff.POSITION) > 0) | ||
253 | { | ||
254 | // If the position of any part has changed, make sure the RootPart of the | ||
255 | // meta entity is pointing with a beam particle system | ||
256 | if (m_BeamEntities.ContainsKey(m_UnchangedEntity.RootPart.UUID)) | ||
257 | { | ||
258 | m_BeamEntities[m_UnchangedEntity.RootPart.UUID].HideFromAll(); | ||
259 | m_BeamEntities.Remove(m_UnchangedEntity.RootPart.UUID); | ||
260 | } | ||
261 | BeamMetaEntity beamGroup = new BeamMetaEntity(m_Entity.Scene, | ||
262 | m_UnchangedEntity.RootPart.GetWorldPosition(), | ||
263 | MetaEntity.TRANSLUCENT, | ||
264 | sceneEntityPart, | ||
265 | new Vector3(0,0,254) | ||
266 | ); | ||
267 | m_BeamEntities.Add(m_UnchangedEntity.RootPart.UUID, beamGroup); | ||
268 | } | ||
269 | |||
270 | if (m_AuraEntities.ContainsKey(UnchangedPart.UUID)) | ||
271 | { | ||
272 | m_AuraEntities[UnchangedPart.UUID].HideFromAll(); | ||
273 | m_AuraEntities.Remove(UnchangedPart.UUID); | ||
274 | } | ||
275 | AuraMetaEntity auraGroup = new AuraMetaEntity(m_Entity.Scene, | ||
276 | UnchangedPart.GetWorldPosition(), | ||
277 | MetaEntity.TRANSLUCENT, | ||
278 | new Vector3(0,0,254), | ||
279 | UnchangedPart.Scale | ||
280 | ); | ||
281 | m_AuraEntities.Add(UnchangedPart.UUID, auraGroup); | ||
282 | SetPartTransparency(metaEntityPart, MetaEntity.TRANSLUCENT); | ||
283 | |||
284 | DiffersFromSceneGroup = true; | ||
285 | } | ||
286 | else // no differences between scene part and meta part | ||
287 | { | ||
288 | if (m_BeamEntities.ContainsKey(m_UnchangedEntity.RootPart.UUID)) | ||
289 | { | ||
290 | m_BeamEntities[m_UnchangedEntity.RootPart.UUID].HideFromAll(); | ||
291 | m_BeamEntities.Remove(m_UnchangedEntity.RootPart.UUID); | ||
292 | } | ||
293 | if (m_AuraEntities.ContainsKey(UnchangedPart.UUID)) | ||
294 | { | ||
295 | m_AuraEntities[UnchangedPart.UUID].HideFromAll(); | ||
296 | m_AuraEntities.Remove(UnchangedPart.UUID); | ||
297 | } | ||
298 | SetPartTransparency(metaEntityPart, MetaEntity.NONE); | ||
299 | } | ||
300 | } | ||
301 | else //The entity currently in the scene is missing parts from the metaentity saved, so mark parts red as deleted. | ||
302 | { | ||
303 | if (m_AuraEntities.ContainsKey(UnchangedPart.UUID)) | ||
304 | { | ||
305 | m_AuraEntities[UnchangedPart.UUID].HideFromAll(); | ||
306 | m_AuraEntities.Remove(UnchangedPart.UUID); | ||
307 | } | ||
308 | AuraMetaEntity auraGroup = new AuraMetaEntity(m_Entity.Scene, | ||
309 | UnchangedPart.GetWorldPosition(), | ||
310 | MetaEntity.TRANSLUCENT, | ||
311 | new Vector3(254,0,0), | ||
312 | UnchangedPart.Scale | ||
313 | ); | ||
314 | m_AuraEntities.Add(UnchangedPart.UUID, auraGroup); | ||
315 | SetPartTransparency(metaEntityPart, MetaEntity.TRANSLUCENT); | ||
316 | |||
317 | DiffersFromSceneGroup = true; | ||
318 | } | ||
319 | } | ||
320 | return changed; | ||
321 | } | ||
322 | |||
323 | public void SendFullAuraUpdate(IClientAPI client) | ||
324 | { | ||
325 | if (DiffersFromSceneGroup) | ||
326 | { | ||
327 | foreach (AuraMetaEntity group in m_AuraEntities.Values) | ||
328 | group.SendFullUpdate(client); | ||
329 | } | ||
330 | } | ||
331 | |||
332 | public void SendFullAuraUpdateToAll() | ||
333 | { | ||
334 | if (DiffersFromSceneGroup) | ||
335 | { | ||
336 | foreach (AuraMetaEntity group in m_AuraEntities.Values) | ||
337 | group.SendFullUpdateToAll(); | ||
338 | } | ||
339 | } | ||
340 | |||
341 | public void SendFullBeamUpdate(IClientAPI client) | ||
342 | { | ||
343 | if (DiffersFromSceneGroup) | ||
344 | { | ||
345 | foreach (BeamMetaEntity group in m_BeamEntities.Values) | ||
346 | group.SendFullUpdate(client); | ||
347 | } | ||
348 | } | ||
349 | |||
350 | public void SendFullBeamUpdateToAll() | ||
351 | { | ||
352 | if (DiffersFromSceneGroup) | ||
353 | { | ||
354 | foreach (BeamMetaEntity group in m_BeamEntities.Values) | ||
355 | group.SendFullUpdateToAll(); | ||
356 | } | ||
357 | } | ||
358 | |||
359 | public void SendFullDiffUpdate(IClientAPI client) | ||
360 | { | ||
361 | FindDifferences(); | ||
362 | if (DiffersFromSceneGroup) | ||
363 | { | ||
364 | SendFullUpdate(client); | ||
365 | SendFullAuraUpdate(client); | ||
366 | SendFullBeamUpdate(client); | ||
367 | } | ||
368 | } | ||
369 | |||
370 | public void SendFullDiffUpdateToAll() | ||
371 | { | ||
372 | FindDifferences(); | ||
373 | if (DiffersFromSceneGroup) | ||
374 | { | ||
375 | SendFullUpdateToAll(); | ||
376 | SendFullAuraUpdateToAll(); | ||
377 | SendFullBeamUpdateToAll(); | ||
378 | } | ||
379 | } | ||
380 | |||
381 | #endregion Public Methods | ||
382 | } | ||
383 | } | ||
diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/ContentManagementModule.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/ContentManagementModule.cs new file mode 100644 index 0000000..21bc8b2 --- /dev/null +++ b/OpenSim/Region/OptionalModules/ContentManagementSystem/ContentManagementModule.cs | |||
@@ -0,0 +1,163 @@ | |||
1 | ļ»æ/* | ||
2 | * Copyright (c) Contributors, http://opensimulator.org/ | ||
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions are met: | ||
7 | * * Redistributions of source code must retain the above copyright | ||
8 | * notice, this list of conditions and the following disclaimer. | ||
9 | * * Redistributions in binary form must reproduce the above copyright | ||
10 | * notice, this list of conditions and the following disclaimer in the | ||
11 | * documentation and/or other materials provided with the distribution. | ||
12 | * * Neither the name of the OpenSim Project nor the | ||
13 | * names of its contributors may be used to endorse or promote products | ||
14 | * derived from this software without specific prior written permission. | ||
15 | * | ||
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | */ | ||
27 | |||
28 | #region Header | ||
29 | |||
30 | // ContentManagementModule.cs | ||
31 | // User: bongiojp | ||
32 | |||
33 | #endregion Header | ||
34 | |||
35 | using System; | ||
36 | using System.Collections.Generic; | ||
37 | using System.Threading; | ||
38 | |||
39 | using OpenMetaverse; | ||
40 | |||
41 | using Nini.Config; | ||
42 | |||
43 | using OpenSim; | ||
44 | using OpenSim.Framework; | ||
45 | using OpenSim.Region.Framework.Interfaces; | ||
46 | using OpenSim.Region.Framework.Scenes; | ||
47 | using OpenSim.Region.Physics.Manager; | ||
48 | |||
49 | using log4net; | ||
50 | |||
51 | namespace OpenSim.Region.OptionalModules.ContentManagement | ||
52 | { | ||
53 | public class ContentManagementModule : IRegionModule | ||
54 | { | ||
55 | #region Static Fields | ||
56 | |||
57 | private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); | ||
58 | |||
59 | #endregion Static Fields | ||
60 | |||
61 | #region Fields | ||
62 | |||
63 | bool initialised = false; | ||
64 | CMController m_control = null; | ||
65 | bool m_enabled = false; | ||
66 | CMModel m_model = null; | ||
67 | bool m_posted = false; | ||
68 | CMView m_view = null; | ||
69 | |||
70 | #endregion Fields | ||
71 | |||
72 | #region Public Properties | ||
73 | |||
74 | public bool IsSharedModule | ||
75 | { | ||
76 | get { return true; } | ||
77 | } | ||
78 | |||
79 | public string Name | ||
80 | { | ||
81 | get { return "ContentManagementModule"; } | ||
82 | } | ||
83 | |||
84 | #endregion Public Properties | ||
85 | |||
86 | #region Public Methods | ||
87 | |||
88 | public void Close() | ||
89 | { | ||
90 | } | ||
91 | |||
92 | public void Initialise(Scene scene, IConfigSource source) | ||
93 | { | ||
94 | string databaseDir = "./"; | ||
95 | string database = "FileSystemDatabase"; | ||
96 | int channel = 345; | ||
97 | try | ||
98 | { | ||
99 | if (source.Configs["CMS"] == null) | ||
100 | return; | ||
101 | |||
102 | m_enabled = source.Configs["CMS"].GetBoolean("enabled", false); | ||
103 | databaseDir = source.Configs["CMS"].GetString("directory", databaseDir); | ||
104 | database = source.Configs["CMS"].GetString("database", database); | ||
105 | channel = source.Configs["CMS"].GetInt("channel", channel); | ||
106 | |||
107 | if (database != "FileSystemDatabase" && database != "GitDatabase") | ||
108 | { | ||
109 | m_log.ErrorFormat("[Content Management]: The Database attribute must be defined as either FileSystemDatabase or GitDatabase"); | ||
110 | m_enabled = false; | ||
111 | } | ||
112 | } | ||
113 | catch (Exception e) | ||
114 | { | ||
115 | m_log.ErrorFormat("[Content Management]: Exception thrown while reading parameters from configuration file. Message: " + e); | ||
116 | m_enabled = false; | ||
117 | } | ||
118 | |||
119 | if (!m_enabled) | ||
120 | { | ||
121 | m_log.Info("[Content Management]: Content Management System is not Enabled."); | ||
122 | return; | ||
123 | } | ||
124 | |||
125 | lock (this) | ||
126 | { | ||
127 | if (!initialised) //only init once | ||
128 | { | ||
129 | m_view = new CMView(); | ||
130 | m_model = new CMModel(); | ||
131 | m_control = new CMController(m_model, m_view, scene, channel); | ||
132 | m_model.Initialise(database); | ||
133 | m_view.Initialise(m_model); | ||
134 | |||
135 | initialised = true; | ||
136 | m_model.InitialiseDatabase(scene, databaseDir); | ||
137 | } | ||
138 | else | ||
139 | { | ||
140 | m_model.InitialiseDatabase(scene, databaseDir); | ||
141 | m_control.RegisterNewRegion(scene); | ||
142 | } | ||
143 | } | ||
144 | } | ||
145 | |||
146 | public void PostInitialise() | ||
147 | { | ||
148 | if (! m_enabled) | ||
149 | return; | ||
150 | |||
151 | lock (this) | ||
152 | { | ||
153 | if (!m_posted) //only post once | ||
154 | { | ||
155 | m_model.PostInitialise(); | ||
156 | m_posted = true; | ||
157 | } | ||
158 | } | ||
159 | } | ||
160 | |||
161 | #endregion Public Methods | ||
162 | } | ||
163 | } | ||
diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/FileSystemDatabase.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/FileSystemDatabase.cs new file mode 100644 index 0000000..6a50906 --- /dev/null +++ b/OpenSim/Region/OptionalModules/ContentManagementSystem/FileSystemDatabase.cs | |||
@@ -0,0 +1,317 @@ | |||
1 | ļ»æ/* | ||
2 | * Copyright (c) Contributors, http://opensimulator.org/ | ||
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions are met: | ||
7 | * * Redistributions of source code must retain the above copyright | ||
8 | * notice, this list of conditions and the following disclaimer. | ||
9 | * * Redistributions in binary form must reproduce the above copyright | ||
10 | * notice, this list of conditions and the following disclaimer in the | ||
11 | * documentation and/or other materials provided with the distribution. | ||
12 | * * Neither the name of the OpenSim Project nor the | ||
13 | * names of its contributors may be used to endorse or promote products | ||
14 | * derived from this software without specific prior written permission. | ||
15 | * | ||
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | */ | ||
27 | |||
28 | #region Header | ||
29 | |||
30 | // FileSystemDatabase.cs | ||
31 | // User: bongiojp | ||
32 | |||
33 | #endregion Header | ||
34 | |||
35 | using System; | ||
36 | using System.Collections.Generic; | ||
37 | using System.Diagnostics; | ||
38 | using System.IO; | ||
39 | using Slash = System.IO.Path; | ||
40 | using System.Reflection; | ||
41 | using System.Xml; | ||
42 | |||
43 | using OpenMetaverse; | ||
44 | |||
45 | using Nini.Config; | ||
46 | |||
47 | using OpenSim.Framework; | ||
48 | using OpenSim.Region.Framework.Interfaces; | ||
49 | using OpenSim.Region.Framework.Scenes; | ||
50 | using OpenSim.Region.CoreModules.World.Serialiser; | ||
51 | using OpenSim.Region.CoreModules.World.Terrain; | ||
52 | using OpenSim.Region.Physics.Manager; | ||
53 | |||
54 | using log4net; | ||
55 | |||
56 | namespace OpenSim.Region.OptionalModules.ContentManagement | ||
57 | { | ||
58 | public class FileSystemDatabase : IContentDatabase | ||
59 | { | ||
60 | #region Static Fields | ||
61 | |||
62 | public static float TimeToDownload = 0; | ||
63 | public static float TimeToSave = 0; | ||
64 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||
65 | |||
66 | #endregion Static Fields | ||
67 | |||
68 | #region Fields | ||
69 | |||
70 | private string m_repodir = null; | ||
71 | private Dictionary<UUID, Scene> m_scenes = new Dictionary<UUID, Scene>(); | ||
72 | private Dictionary<UUID, IRegionSerialiserModule> m_serialiser = new Dictionary<UUID, IRegionSerialiserModule>(); | ||
73 | |||
74 | #endregion Fields | ||
75 | |||
76 | #region Constructors | ||
77 | |||
78 | public FileSystemDatabase() | ||
79 | { | ||
80 | } | ||
81 | |||
82 | #endregion Constructors | ||
83 | |||
84 | #region Private Methods | ||
85 | |||
86 | // called by postinitialise | ||
87 | private void CreateDirectory() | ||
88 | { | ||
89 | string scenedir; | ||
90 | if (!Directory.Exists(m_repodir)) | ||
91 | Directory.CreateDirectory(m_repodir); | ||
92 | |||
93 | foreach (UUID region in m_scenes.Keys) | ||
94 | { | ||
95 | scenedir = m_repodir + Slash.DirectorySeparatorChar + region + Slash.DirectorySeparatorChar; | ||
96 | if (!Directory.Exists(scenedir)) | ||
97 | Directory.CreateDirectory(scenedir); | ||
98 | } | ||
99 | } | ||
100 | |||
101 | // called by postinitialise | ||
102 | private void SetupSerialiser() | ||
103 | { | ||
104 | if (m_serialiser.Count == 0) | ||
105 | { | ||
106 | foreach (UUID region in m_scenes.Keys) | ||
107 | { | ||
108 | m_serialiser.Add(region, m_scenes[region].RequestModuleInterface<IRegionSerialiserModule>()); | ||
109 | } | ||
110 | } | ||
111 | } | ||
112 | |||
113 | #endregion Private Methods | ||
114 | |||
115 | #region Public Methods | ||
116 | |||
117 | public int GetMostRecentRevision(UUID regionid) | ||
118 | { | ||
119 | return NumOfRegionRev(regionid); | ||
120 | } | ||
121 | |||
122 | public string GetRegionObjectHeightMap(UUID regionid) | ||
123 | { | ||
124 | String filename = m_repodir + Slash.DirectorySeparatorChar + regionid + | ||
125 | Slash.DirectorySeparatorChar + "heightmap.r32"; | ||
126 | FileStream fs = new FileStream( filename, FileMode.Open); | ||
127 | StreamReader sr = new StreamReader(fs); | ||
128 | String result = sr.ReadToEnd(); | ||
129 | sr.Close(); | ||
130 | fs.Close(); | ||
131 | return result; | ||
132 | } | ||
133 | |||
134 | public string GetRegionObjectHeightMap(UUID regionid, int revision) | ||
135 | { | ||
136 | String filename = m_repodir + Slash.DirectorySeparatorChar + regionid + | ||
137 | Slash.DirectorySeparatorChar + "heightmap.r32"; | ||
138 | FileStream fs = new FileStream( filename, FileMode.Open); | ||
139 | StreamReader sr = new StreamReader(fs); | ||
140 | String result = sr.ReadToEnd(); | ||
141 | sr.Close(); | ||
142 | fs.Close(); | ||
143 | return result; | ||
144 | } | ||
145 | |||
146 | public System.Collections.ArrayList GetRegionObjectXMLList(UUID regionid, int revision) | ||
147 | { | ||
148 | System.Collections.ArrayList objectList = new System.Collections.ArrayList(); | ||
149 | string filename = m_repodir + Slash.DirectorySeparatorChar + regionid + Slash.DirectorySeparatorChar + | ||
150 | + revision + Slash.DirectorySeparatorChar + "objects.xml"; | ||
151 | XmlDocument doc = new XmlDocument(); | ||
152 | XmlNode rootNode; | ||
153 | //int primCount = 0; | ||
154 | //SceneObjectGroup obj = null; | ||
155 | |||
156 | if (File.Exists(filename)) | ||
157 | { | ||
158 | XmlTextReader reader = new XmlTextReader(filename); | ||
159 | reader.WhitespaceHandling = WhitespaceHandling.None; | ||
160 | doc.Load(reader); | ||
161 | reader.Close(); | ||
162 | rootNode = doc.FirstChild; | ||
163 | foreach (XmlNode aPrimNode in rootNode.ChildNodes) | ||
164 | { | ||
165 | objectList.Add(aPrimNode.OuterXml); | ||
166 | } | ||
167 | return objectList; | ||
168 | } | ||
169 | return null; | ||
170 | } | ||
171 | |||
172 | public System.Collections.ArrayList GetRegionObjectXMLList(UUID regionid) | ||
173 | { | ||
174 | int revision = NumOfRegionRev(regionid); | ||
175 | m_log.Info("[FSDB]: found revisions:" + revision); | ||
176 | System.Collections.ArrayList xmlList = new System.Collections.ArrayList(); | ||
177 | string filename = m_repodir + Slash.DirectorySeparatorChar + regionid + Slash.DirectorySeparatorChar + | ||
178 | + revision + Slash.DirectorySeparatorChar + "objects.xml"; | ||
179 | XmlDocument doc = new XmlDocument(); | ||
180 | XmlNode rootNode; | ||
181 | |||
182 | m_log.Info("[FSDB]: Checking if " + filename + " exists."); | ||
183 | if (File.Exists(filename)) | ||
184 | { | ||
185 | Stopwatch x = new Stopwatch(); | ||
186 | x.Start(); | ||
187 | |||
188 | XmlTextReader reader = new XmlTextReader(filename); | ||
189 | reader.WhitespaceHandling = WhitespaceHandling.None; | ||
190 | doc.Load(reader); | ||
191 | reader.Close(); | ||
192 | rootNode = doc.FirstChild; | ||
193 | |||
194 | foreach (XmlNode aPrimNode in rootNode.ChildNodes) | ||
195 | { | ||
196 | xmlList.Add(aPrimNode.OuterXml); | ||
197 | } | ||
198 | |||
199 | x.Stop(); | ||
200 | TimeToDownload += x.ElapsedMilliseconds; | ||
201 | m_log.Info("[FileSystemDatabase] Time spent retrieving xml files so far: " + TimeToDownload); | ||
202 | |||
203 | return xmlList; | ||
204 | } | ||
205 | return null; | ||
206 | } | ||
207 | |||
208 | public void Initialise(Scene scene, string dir) | ||
209 | { | ||
210 | lock (this) | ||
211 | { | ||
212 | if (m_repodir == null) | ||
213 | m_repodir = dir; | ||
214 | } | ||
215 | lock (m_scenes) | ||
216 | m_scenes.Add(scene.RegionInfo.RegionID, scene); | ||
217 | } | ||
218 | |||
219 | public System.Collections.Generic.SortedDictionary<string, string> ListOfRegionRevisions(UUID regionid) | ||
220 | { | ||
221 | SortedDictionary<string, string> revisionDict = new SortedDictionary<string,string>(); | ||
222 | |||
223 | string scenedir = m_repodir + Slash.DirectorySeparatorChar + regionid + Slash.DirectorySeparatorChar; | ||
224 | string[] directories = Directory.GetDirectories(scenedir); | ||
225 | |||
226 | FileStream fs = null; | ||
227 | StreamReader sr = null; | ||
228 | String logMessage = ""; | ||
229 | String logLocation = ""; | ||
230 | foreach (string revisionDir in directories) | ||
231 | { | ||
232 | try | ||
233 | { | ||
234 | logLocation = revisionDir + Slash.DirectorySeparatorChar + "log"; | ||
235 | fs = new FileStream( logLocation, FileMode.Open); | ||
236 | sr = new StreamReader(fs); | ||
237 | logMessage = sr.ReadToEnd(); | ||
238 | sr.Close(); | ||
239 | fs.Close(); | ||
240 | revisionDict.Add(revisionDir, logMessage); | ||
241 | } | ||
242 | catch (Exception) | ||
243 | { | ||
244 | } | ||
245 | } | ||
246 | |||
247 | return revisionDict; | ||
248 | } | ||
249 | |||
250 | public int NumOfRegionRev(UUID regionid) | ||
251 | { | ||
252 | string scenedir = m_repodir + Slash.DirectorySeparatorChar + regionid + Slash.DirectorySeparatorChar; | ||
253 | m_log.Info("[FSDB]: Reading scene dir: " + scenedir); | ||
254 | string[] directories = Directory.GetDirectories(scenedir); | ||
255 | return directories.Length; | ||
256 | } | ||
257 | |||
258 | // Run once and only once. | ||
259 | public void PostInitialise() | ||
260 | { | ||
261 | SetupSerialiser(); | ||
262 | |||
263 | m_log.Info("[FSDB]: Creating repository in " + m_repodir + "."); | ||
264 | CreateDirectory(); | ||
265 | } | ||
266 | |||
267 | public void SaveRegion(UUID regionid, string regionName, string logMessage) | ||
268 | { | ||
269 | m_log.Info("[FSDB]: ..............................."); | ||
270 | string scenedir = m_repodir + Slash.DirectorySeparatorChar + regionid + Slash.DirectorySeparatorChar; | ||
271 | |||
272 | m_log.Info("[FSDB]: checking if scene directory exists: " + scenedir); | ||
273 | if (!Directory.Exists(scenedir)) | ||
274 | Directory.CreateDirectory(scenedir); | ||
275 | |||
276 | int newRevisionNum = GetMostRecentRevision(regionid)+1; | ||
277 | string revisiondir = scenedir + newRevisionNum + Slash.DirectorySeparatorChar; | ||
278 | |||
279 | m_log.Info("[FSDB]: checking if revision directory exists: " + revisiondir); | ||
280 | if (!Directory.Exists(revisiondir)) | ||
281 | Directory.CreateDirectory(revisiondir); | ||
282 | |||
283 | try { | ||
284 | Stopwatch x = new Stopwatch(); | ||
285 | x.Start(); | ||
286 | if (m_scenes.ContainsKey(regionid)) | ||
287 | { | ||
288 | m_serialiser[regionid].SerialiseRegion(m_scenes[regionid], revisiondir); | ||
289 | } | ||
290 | x.Stop(); | ||
291 | TimeToSave += x.ElapsedMilliseconds; | ||
292 | m_log.Info("[FileSystemDatabase] Time spent serialising regions to files on disk for " + regionName + ": " + x.ElapsedMilliseconds); | ||
293 | m_log.Info("[FileSystemDatabase] Time spent serialising regions to files on disk so far: " + TimeToSave); | ||
294 | } | ||
295 | catch (Exception e) | ||
296 | { | ||
297 | m_log.ErrorFormat("[FSDB]: Serialisation of region failed: " + e); | ||
298 | return; | ||
299 | } | ||
300 | |||
301 | try { | ||
302 | // Finish by writing log message. | ||
303 | FileStream file = new FileStream(revisiondir + "log", FileMode.Create, FileAccess.ReadWrite); | ||
304 | StreamWriter sw = new StreamWriter(file); | ||
305 | sw.Write(logMessage); | ||
306 | sw.Close(); | ||
307 | } | ||
308 | catch (Exception e) | ||
309 | { | ||
310 | m_log.ErrorFormat("[FSDB]: Failed trying to save log file " + e); | ||
311 | return; | ||
312 | } | ||
313 | } | ||
314 | |||
315 | #endregion Public Methods | ||
316 | } | ||
317 | } | ||
diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/GitDatabase.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/GitDatabase.cs new file mode 100644 index 0000000..d24747c --- /dev/null +++ b/OpenSim/Region/OptionalModules/ContentManagementSystem/GitDatabase.cs | |||
@@ -0,0 +1,167 @@ | |||
1 | ļ»æ/* | ||
2 | * Copyright (c) Contributors, http://opensimulator.org/ | ||
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions are met: | ||
7 | * * Redistributions of source code must retain the above copyright | ||
8 | * notice, this list of conditions and the following disclaimer. | ||
9 | * * Redistributions in binary form must reproduce the above copyright | ||
10 | * notice, this list of conditions and the following disclaimer in the | ||
11 | * documentation and/or other materials provided with the distribution. | ||
12 | * * Neither the name of the OpenSim Project nor the | ||
13 | * names of its contributors may be used to endorse or promote products | ||
14 | * derived from this software without specific prior written permission. | ||
15 | * | ||
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | */ | ||
27 | |||
28 | #region Header | ||
29 | |||
30 | // GitDatabase.cs | ||
31 | // | ||
32 | // | ||
33 | // | ||
34 | |||
35 | #endregion Header | ||
36 | |||
37 | using System; | ||
38 | using System.Collections.Generic; | ||
39 | using System.IO; | ||
40 | using Slash = System.IO.Path; | ||
41 | using System.Reflection; | ||
42 | using System.Xml; | ||
43 | |||
44 | using OpenMetaverse; | ||
45 | |||
46 | using Nini.Config; | ||
47 | |||
48 | using OpenSim.Framework; | ||
49 | using OpenSim.Region.Framework.Interfaces; | ||
50 | using OpenSim.Region.Framework.Scenes; | ||
51 | using OpenSim.Region.CoreModules.World.Serialiser; | ||
52 | using OpenSim.Region.CoreModules.World.Terrain; | ||
53 | using OpenSim.Region.Physics.Manager; | ||
54 | |||
55 | using log4net; | ||
56 | |||
57 | namespace OpenSim.Region.OptionalModules.ContentManagement | ||
58 | { | ||
59 | /// <summary> | ||
60 | /// Just a stub :-( | ||
61 | /// </summary> | ||
62 | public class GitDatabase : IContentDatabase | ||
63 | { | ||
64 | #region Constructors | ||
65 | |||
66 | public GitDatabase() | ||
67 | { | ||
68 | } | ||
69 | |||
70 | #endregion Constructors | ||
71 | |||
72 | #region Public Methods | ||
73 | |||
74 | public SceneObjectGroup GetMostRecentObjectRevision(UUID id) | ||
75 | { | ||
76 | return null; | ||
77 | } | ||
78 | |||
79 | public int GetMostRecentRevision(UUID regionid) | ||
80 | { | ||
81 | return 0; | ||
82 | } | ||
83 | |||
84 | public SceneObjectGroup GetObjectRevision(UUID id, int revision) | ||
85 | { | ||
86 | return null; | ||
87 | } | ||
88 | |||
89 | public System.Collections.ArrayList GetObjectsFromRegion(UUID regionid, int revision) | ||
90 | { | ||
91 | return null; | ||
92 | } | ||
93 | |||
94 | public string GetRegionObjectHeightMap(UUID regionid) | ||
95 | { | ||
96 | return null; | ||
97 | } | ||
98 | |||
99 | public string GetRegionObjectHeightMap(UUID regionid, int revision) | ||
100 | { | ||
101 | return null; | ||
102 | } | ||
103 | |||
104 | public string GetRegionObjectXML(UUID regionid) | ||
105 | { | ||
106 | return null; | ||
107 | } | ||
108 | |||
109 | public string GetRegionObjectXML(UUID regionid, int revision) | ||
110 | { | ||
111 | return null; | ||
112 | } | ||
113 | |||
114 | public System.Collections.ArrayList GetRegionObjectXMLList(UUID regionid) | ||
115 | { | ||
116 | return null; | ||
117 | } | ||
118 | |||
119 | public System.Collections.ArrayList GetRegionObjectXMLList(UUID regionid, int revision) | ||
120 | { | ||
121 | return null; | ||
122 | } | ||
123 | |||
124 | public bool InRepository(UUID id) | ||
125 | { | ||
126 | return false; | ||
127 | } | ||
128 | |||
129 | public void Initialise(Scene scene, String dir) | ||
130 | { | ||
131 | } | ||
132 | |||
133 | public System.Collections.Generic.SortedDictionary<string, string> ListOfObjectRevisions(UUID id) | ||
134 | { | ||
135 | return null; | ||
136 | } | ||
137 | |||
138 | public System.Collections.Generic.SortedDictionary<string, string> ListOfRegionRevisions(UUID id) | ||
139 | { | ||
140 | return null; | ||
141 | } | ||
142 | |||
143 | public int NumOfObjectRev(UUID id) | ||
144 | { | ||
145 | return 0; | ||
146 | } | ||
147 | |||
148 | public int NumOfRegionRev(UUID regionid) | ||
149 | { | ||
150 | return 0; | ||
151 | } | ||
152 | |||
153 | public void PostInitialise() | ||
154 | { | ||
155 | } | ||
156 | |||
157 | public void SaveObject(SceneObjectGroup entity) | ||
158 | { | ||
159 | } | ||
160 | |||
161 | public void SaveRegion(UUID regionid, string regionName, string logMessage) | ||
162 | { | ||
163 | } | ||
164 | |||
165 | #endregion Public Methods | ||
166 | } | ||
167 | } | ||
diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/IContentDatabase.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/IContentDatabase.cs new file mode 100644 index 0000000..7a25fa5 --- /dev/null +++ b/OpenSim/Region/OptionalModules/ContentManagementSystem/IContentDatabase.cs | |||
@@ -0,0 +1,94 @@ | |||
1 | ļ»æ/* | ||
2 | * Copyright (c) Contributors, http://opensimulator.org/ | ||
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions are met: | ||
7 | * * Redistributions of source code must retain the above copyright | ||
8 | * notice, this list of conditions and the following disclaimer. | ||
9 | * * Redistributions in binary form must reproduce the above copyright | ||
10 | * notice, this list of conditions and the following disclaimer in the | ||
11 | * documentation and/or other materials provided with the distribution. | ||
12 | * * Neither the name of the OpenSim Project nor the | ||
13 | * names of its contributors may be used to endorse or promote products | ||
14 | * derived from this software without specific prior written permission. | ||
15 | * | ||
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | */ | ||
27 | |||
28 | #region Header | ||
29 | |||
30 | // IContentDatabase.cs | ||
31 | // User: bongiojp | ||
32 | // | ||
33 | // | ||
34 | // | ||
35 | |||
36 | #endregion Header | ||
37 | |||
38 | using System; | ||
39 | using OpenMetaverse; | ||
40 | using OpenSim.Region.Framework.Scenes; | ||
41 | using Nini.Config; | ||
42 | |||
43 | namespace OpenSim.Region.OptionalModules.ContentManagement | ||
44 | { | ||
45 | public interface IContentDatabase | ||
46 | { | ||
47 | #region Methods | ||
48 | |||
49 | /// <summary> | ||
50 | /// Returns the most recent revision number of a region. | ||
51 | /// </summary> | ||
52 | int GetMostRecentRevision(UUID regionid); | ||
53 | |||
54 | string GetRegionObjectHeightMap(UUID regionid); | ||
55 | |||
56 | string GetRegionObjectHeightMap(UUID regionid, int revision); | ||
57 | |||
58 | /// <summary> | ||
59 | /// Retrieves the xml that describes each individual object from the last revision or specific revision of the given region. | ||
60 | /// </summary> | ||
61 | System.Collections.ArrayList GetRegionObjectXMLList(UUID regionid); | ||
62 | |||
63 | System.Collections.ArrayList GetRegionObjectXMLList(UUID regionid, int revision); | ||
64 | |||
65 | /// <summary> | ||
66 | /// Similar to the IRegionModule function. This is the function to be called before attempting to interface with the database. | ||
67 | /// Initialise should be called one for each region to be contained in the database. The directory should be the full path | ||
68 | /// to the repository and will only be defined once, regardless of how many times the method is called. | ||
69 | /// </summary> | ||
70 | void Initialise(Scene scene, String dir); | ||
71 | |||
72 | /// <summary> | ||
73 | /// Returns a list of the revision numbers and corresponding log messages for a given region. | ||
74 | /// </summary> | ||
75 | System.Collections.Generic.SortedDictionary<string, string> ListOfRegionRevisions(UUID id); | ||
76 | |||
77 | /// <summary> | ||
78 | /// Returns the total number of revisions saved for a specific region. | ||
79 | /// </summary> | ||
80 | int NumOfRegionRev(UUID regionid); | ||
81 | |||
82 | /// <summary> | ||
83 | /// Should be called once after Initialise has been called. | ||
84 | /// </summary> | ||
85 | void PostInitialise(); | ||
86 | |||
87 | /// <summary> | ||
88 | /// Saves the Region terrain map and objects within the region as xml to the database. | ||
89 | /// </summary> | ||
90 | void SaveRegion(UUID regionid, string regionName, string logMessage); | ||
91 | |||
92 | #endregion Methods | ||
93 | } | ||
94 | } | ||
diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/MetaEntity.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/MetaEntity.cs new file mode 100644 index 0000000..63c74e1 --- /dev/null +++ b/OpenSim/Region/OptionalModules/ContentManagementSystem/MetaEntity.cs | |||
@@ -0,0 +1,274 @@ | |||
1 | ļ»æ/* | ||
2 | * Copyright (c) Contributors, http://opensimulator.org/ | ||
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions are met: | ||
7 | * * Redistributions of source code must retain the above copyright | ||
8 | * notice, this list of conditions and the following disclaimer. | ||
9 | * * Redistributions in binary form must reproduce the above copyright | ||
10 | * notice, this list of conditions and the following disclaimer in the | ||
11 | * documentation and/or other materials provided with the distribution. | ||
12 | * * Neither the name of the OpenSim Project nor the | ||
13 | * names of its contributors may be used to endorse or promote products | ||
14 | * derived from this software without specific prior written permission. | ||
15 | * | ||
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | */ | ||
27 | |||
28 | #region Header | ||
29 | |||
30 | // MetaEntity.cs | ||
31 | // User: bongiojp | ||
32 | // | ||
33 | // TODO: | ||
34 | // Create a physics manager to the meta object if there isn't one or the object knows of no scene but the user wants physics enabled. | ||
35 | |||
36 | #endregion Header | ||
37 | |||
38 | using System; | ||
39 | using System.Collections.Generic; | ||
40 | using System.Drawing; | ||
41 | |||
42 | using OpenMetaverse; | ||
43 | |||
44 | using Nini.Config; | ||
45 | |||
46 | using OpenSim.Framework; | ||
47 | using OpenSim.Region.Framework.Interfaces; | ||
48 | using OpenSim.Region.Framework.Scenes; | ||
49 | using OpenSim.Region.Physics.Manager; | ||
50 | |||
51 | using log4net; | ||
52 | |||
53 | namespace OpenSim.Region.OptionalModules.ContentManagement | ||
54 | { | ||
55 | public class MetaEntity | ||
56 | { | ||
57 | #region Constants | ||
58 | |||
59 | public const float INVISIBLE = .95f; | ||
60 | |||
61 | // Settings for transparency of metaentity | ||
62 | public const float NONE = 0f; | ||
63 | public const float TRANSLUCENT = .5f; | ||
64 | |||
65 | #endregion Constants | ||
66 | |||
67 | #region Static Fields | ||
68 | |||
69 | protected static readonly ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); | ||
70 | |||
71 | #endregion Static Fields | ||
72 | |||
73 | #region Fields | ||
74 | |||
75 | protected SceneObjectGroup m_Entity = null; // The scene object group that represents this meta entity. | ||
76 | protected uint m_metaLocalid; | ||
77 | |||
78 | #endregion Fields | ||
79 | |||
80 | #region Constructors | ||
81 | |||
82 | public MetaEntity() | ||
83 | { | ||
84 | } | ||
85 | |||
86 | /// <summary> | ||
87 | /// Makes a new meta entity by copying the given scene object group. | ||
88 | /// The physics boolean is just a stub right now. | ||
89 | /// </summary> | ||
90 | public MetaEntity(SceneObjectGroup orig, bool physics) | ||
91 | { | ||
92 | m_Entity = orig.Copy(orig.RootPart.OwnerID, orig.RootPart.GroupID, false); | ||
93 | Initialize(physics); | ||
94 | } | ||
95 | |||
96 | /// <summary> | ||
97 | /// Takes an XML description of a scene object group and converts it to a meta entity. | ||
98 | /// </summary> | ||
99 | public MetaEntity(string objectXML, Scene scene, bool physics) | ||
100 | { | ||
101 | m_Entity = new SceneObjectGroup(objectXML); | ||
102 | m_Entity.SetScene(scene); | ||
103 | Initialize(physics); | ||
104 | } | ||
105 | |||
106 | #endregion Constructors | ||
107 | |||
108 | #region Public Properties | ||
109 | |||
110 | public Dictionary<UUID, SceneObjectPart> Children | ||
111 | { | ||
112 | get { return m_Entity.Children; } | ||
113 | set { m_Entity.Children = value; } | ||
114 | } | ||
115 | |||
116 | public uint LocalId | ||
117 | { | ||
118 | get { return m_Entity.LocalId; } | ||
119 | set { m_Entity.LocalId = value; } | ||
120 | } | ||
121 | |||
122 | public SceneObjectGroup ObjectGroup | ||
123 | { | ||
124 | get { return m_Entity; } | ||
125 | } | ||
126 | |||
127 | public int PrimCount | ||
128 | { | ||
129 | get { return m_Entity.PrimCount; } | ||
130 | } | ||
131 | |||
132 | public SceneObjectPart RootPart | ||
133 | { | ||
134 | get { return m_Entity.RootPart; } | ||
135 | } | ||
136 | |||
137 | public Scene Scene | ||
138 | { | ||
139 | get { return m_Entity.Scene; } | ||
140 | } | ||
141 | |||
142 | public UUID UUID | ||
143 | { | ||
144 | get { return m_Entity.UUID; } | ||
145 | set { m_Entity.UUID = value; } | ||
146 | } | ||
147 | |||
148 | #endregion Public Properties | ||
149 | |||
150 | #region Protected Methods | ||
151 | |||
152 | // The metaentity objectgroup must have unique localids as well as unique uuids. | ||
153 | // localids are used by the client to refer to parts. | ||
154 | // uuids are sent to the client and back to the server to identify parts on the server side. | ||
155 | /// <summary> | ||
156 | /// Changes localids and uuids of m_Entity. | ||
157 | /// </summary> | ||
158 | protected void Initialize(bool physics) | ||
159 | { | ||
160 | //make new uuids | ||
161 | Dictionary<UUID, SceneObjectPart> parts = new Dictionary<UUID, SceneObjectPart>(); | ||
162 | foreach (SceneObjectPart part in m_Entity.Children.Values) | ||
163 | { | ||
164 | part.ResetIDs(part.LinkNum); | ||
165 | parts.Add(part.UUID, part); | ||
166 | } | ||
167 | |||
168 | //finalize | ||
169 | m_Entity.RootPart.PhysActor = null; | ||
170 | m_Entity.Children = parts; | ||
171 | } | ||
172 | |||
173 | #endregion Protected Methods | ||
174 | |||
175 | #region Public Methods | ||
176 | |||
177 | /// <summary> | ||
178 | /// Hides the metaentity from a single client. | ||
179 | /// </summary> | ||
180 | public virtual void Hide(IClientAPI client) | ||
181 | { | ||
182 | //This deletes the group without removing from any databases. | ||
183 | //This is important because we are not IN any database. | ||
184 | //m_Entity.FakeDeleteGroup(); | ||
185 | foreach (SceneObjectPart part in m_Entity.Children.Values) | ||
186 | client.SendKillObject(m_Entity.RegionHandle, part.LocalId); | ||
187 | } | ||
188 | |||
189 | /// <summary> | ||
190 | /// Sends a kill object message to all clients, effectively "hiding" the metaentity even though it's still on the server. | ||
191 | /// </summary> | ||
192 | public virtual void HideFromAll() | ||
193 | { | ||
194 | foreach (SceneObjectPart part in m_Entity.Children.Values) | ||
195 | m_Entity.Scene.ClientManager.ForEachClient(delegate(IClientAPI controller) | ||
196 | { controller.SendKillObject(m_Entity.RegionHandle, part.LocalId); } | ||
197 | ); | ||
198 | } | ||
199 | |||
200 | public void SendFullUpdate(IClientAPI client) | ||
201 | { | ||
202 | // Not sure what clientFlags should be but 0 seems to work | ||
203 | SendFullUpdate(client, 0); | ||
204 | } | ||
205 | |||
206 | public void SendFullUpdate(IClientAPI client, uint clientFlags) | ||
207 | { | ||
208 | m_Entity.SendFullUpdateToClient(client); | ||
209 | } | ||
210 | |||
211 | public void SendFullUpdateToAll() | ||
212 | { | ||
213 | m_Entity.Scene.ClientManager.ForEachClient(delegate(IClientAPI controller) | ||
214 | { m_Entity.SendFullUpdateToClient(controller); } | ||
215 | ); | ||
216 | } | ||
217 | |||
218 | /// <summary> | ||
219 | /// Makes a single SceneObjectPart see through. | ||
220 | /// </summary> | ||
221 | /// <param name="part"> | ||
222 | /// A <see cref="SceneObjectPart"/> | ||
223 | /// The part to make see through | ||
224 | /// </param> | ||
225 | /// <param name="transparencyAmount"> | ||
226 | /// A <see cref="System.Single"/> | ||
227 | /// The degree of transparency to imbue the part with, 0f being solid and .95f being invisible. | ||
228 | /// </param> | ||
229 | public static void SetPartTransparency(SceneObjectPart part, float transparencyAmount) | ||
230 | { | ||
231 | Primitive.TextureEntry tex = null; | ||
232 | Color4 texcolor; | ||
233 | try | ||
234 | { | ||
235 | tex = part.Shape.Textures; | ||
236 | texcolor = new Color4(); | ||
237 | } | ||
238 | catch(Exception) | ||
239 | { | ||
240 | //m_log.ErrorFormat("[Content Management]: Exception thrown while accessing textures of scene object: " + e); | ||
241 | return; | ||
242 | } | ||
243 | |||
244 | for (uint i = 0; i < tex.FaceTextures.Length; i++) | ||
245 | { | ||
246 | try { | ||
247 | if (tex.FaceTextures[i] != null) | ||
248 | { | ||
249 | texcolor = tex.FaceTextures[i].RGBA; | ||
250 | texcolor.A = transparencyAmount; | ||
251 | tex.FaceTextures[i].RGBA = texcolor; | ||
252 | } | ||
253 | } | ||
254 | catch (Exception) | ||
255 | { | ||
256 | //m_log.ErrorFormat("[Content Management]: Exception thrown while accessing different face textures of object: " + e); | ||
257 | continue; | ||
258 | } | ||
259 | } | ||
260 | try { | ||
261 | texcolor = tex.DefaultTexture.RGBA; | ||
262 | texcolor.A = transparencyAmount; | ||
263 | tex.DefaultTexture.RGBA = texcolor; | ||
264 | part.Shape.TextureEntry = tex.ToBytes(); | ||
265 | } | ||
266 | catch (Exception) | ||
267 | { | ||
268 | //m_log.Info("[Content Management]: Exception thrown while accessing default face texture of object: " + e); | ||
269 | } | ||
270 | } | ||
271 | |||
272 | #endregion Public Methods | ||
273 | } | ||
274 | } | ||
diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/PointMetaEntity.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/PointMetaEntity.cs new file mode 100644 index 0000000..22f09fd --- /dev/null +++ b/OpenSim/Region/OptionalModules/ContentManagementSystem/PointMetaEntity.cs | |||
@@ -0,0 +1,116 @@ | |||
1 | /* | ||
2 | * Copyright (c) Contributors, http://opensimulator.org/ | ||
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions are met: | ||
7 | * * Redistributions of source code must retain the above copyright | ||
8 | * notice, this list of conditions and the following disclaimer. | ||
9 | * * Redistributions in binary form must reproduce the above copyright | ||
10 | * notice, this list of conditions and the following disclaimer in the | ||
11 | * documentation and/or other materials provided with the distribution. | ||
12 | * * Neither the name of the OpenSim Project nor the | ||
13 | * names of its contributors may be used to endorse or promote products | ||
14 | * derived from this software without specific prior written permission. | ||
15 | * | ||
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | */ | ||
27 | |||
28 | #region Header | ||
29 | |||
30 | // PointMetaEntity.cs created with MonoDevelop | ||
31 | // User: bongiojp at 3:03 PMĀ 8/6/2008 | ||
32 | // | ||
33 | // To change standard headers go to Edit->Preferences->Coding->Standard Headers | ||
34 | // | ||
35 | |||
36 | #endregion Header | ||
37 | |||
38 | using System; | ||
39 | using System.Collections.Generic; | ||
40 | using System.Drawing; | ||
41 | |||
42 | using OpenMetaverse; | ||
43 | |||
44 | using Nini.Config; | ||
45 | |||
46 | using OpenSim.Framework; | ||
47 | using OpenSim.Region.Framework.Interfaces; | ||
48 | using OpenSim.Region.Framework.Scenes; | ||
49 | using OpenSim.Region.Physics.Manager; | ||
50 | |||
51 | using log4net; | ||
52 | |||
53 | namespace OpenSim.Region.OptionalModules.ContentManagement | ||
54 | { | ||
55 | public class PointMetaEntity : MetaEntity | ||
56 | { | ||
57 | #region Constructors | ||
58 | |||
59 | public PointMetaEntity(Scene scene, Vector3 groupPos, float transparency) | ||
60 | : base() | ||
61 | { | ||
62 | CreatePointEntity(scene, UUID.Random(), groupPos); | ||
63 | SetPartTransparency(m_Entity.RootPart, transparency); | ||
64 | } | ||
65 | |||
66 | public PointMetaEntity(Scene scene, UUID uuid, Vector3 groupPos, float transparency) | ||
67 | : base() | ||
68 | { | ||
69 | CreatePointEntity(scene, uuid, groupPos); | ||
70 | SetPartTransparency(m_Entity.RootPart, transparency); | ||
71 | } | ||
72 | |||
73 | #endregion Constructors | ||
74 | |||
75 | #region Private Methods | ||
76 | |||
77 | private void CreatePointEntity(Scene scene, UUID uuid, Vector3 groupPos) | ||
78 | { | ||
79 | SceneObjectGroup x = new SceneObjectGroup(); | ||
80 | SceneObjectPart y = new SceneObjectPart(); | ||
81 | |||
82 | //Initialize part | ||
83 | y.Name = "Very Small Point"; | ||
84 | y.RegionHandle = scene.RegionInfo.RegionHandle; | ||
85 | y.CreationDate = (Int32) (DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds; | ||
86 | y.OwnerID = UUID.Zero; | ||
87 | y.CreatorID = UUID.Zero; | ||
88 | y.LastOwnerID = UUID.Zero; | ||
89 | y.UUID = uuid; | ||
90 | |||
91 | y.Shape = PrimitiveBaseShape.CreateBox(); | ||
92 | y.Scale = new Vector3(0.01f,0.01f,0.01f); | ||
93 | y.LastOwnerID = UUID.Zero; | ||
94 | y.GroupPosition = groupPos; | ||
95 | y.OffsetPosition = new Vector3(0, 0, 0); | ||
96 | y.RotationOffset = new Quaternion(0,0,0,0); | ||
97 | y.Velocity = new Vector3(0, 0, 0); | ||
98 | y.RotationalVelocity = new Vector3(0, 0, 0); | ||
99 | y.AngularVelocity = new Vector3(0, 0, 0); | ||
100 | y.Acceleration = new Vector3(0, 0, 0); | ||
101 | |||
102 | y.Flags = 0; | ||
103 | y.TrimPermissions(); | ||
104 | |||
105 | //Initialize group and add part as root part | ||
106 | x.SetScene(scene); | ||
107 | x.SetRootPart(y); | ||
108 | x.RegionHandle = scene.RegionInfo.RegionHandle; | ||
109 | x.SetScene(scene); | ||
110 | |||
111 | m_Entity = x; | ||
112 | } | ||
113 | |||
114 | #endregion Private Methods | ||
115 | } | ||
116 | } | ||
diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/README b/OpenSim/Region/OptionalModules/ContentManagementSystem/README new file mode 100644 index 0000000..1a69fef --- /dev/null +++ b/OpenSim/Region/OptionalModules/ContentManagementSystem/README | |||
@@ -0,0 +1,52 @@ | |||
1 | This module is meant to be built alone and not added to the Opensim code base. References are made to required dlls through a | ||
2 | reference file, ContentManagement.mdp. Originally, for development, this project was contained in the Opensim/Region/Modules/ | ||
3 | directory. | ||
4 | |||
5 | To compile: nant | ||
6 | To use: Copy ContentManagement.dll into the bin directory of your Opensim build. You should find many other dlls in the same directory. | ||
7 | |||
8 | |||
9 | -------------------------------------------------------------------------------------------------------------------- | ||
10 | To build the libgit.so file: | ||
11 | |||
12 | #Download GIT git repository | ||
13 | $ git clone git://git2.kernel.org/pub/OpenSim/Region/Environment/Modules/ContentManagementSystem/scm/git/git.git | ||
14 | $ cd git | ||
15 | |||
16 | #Compile GIT | ||
17 | #Note that we are adding two extra flags to pass to gcc while compiling (-c and -fPIC) | ||
18 | $ autoconf | ||
19 | $ ./configure | ||
20 | $ CFLAGS="-g -O2 -Wall -c -fPIC" make | ||
21 | |||
22 | #Copy necessary object files (and some not so necessary) to their own directory for shared object file creation | ||
23 | $ mkdir ../libgit-objects | ||
24 | $ cp builtin*.o ../libgit-objects | ||
25 | $ cp xdiff/*.o ../libgit-objects | ||
26 | $ cp libgit.a ../libgit-objects | ||
27 | |||
28 | #Remove the main symbol from any object files (like git.o) | ||
29 | $ cd ../libgit-objects | ||
30 | $ strip -N main *.o | ||
31 | |||
32 | #Uncompress the plumbing objects from archive created by git | ||
33 | $ ar x libgit.a | ||
34 | |||
35 | #Create shared object file from all objects (including the zlib library) | ||
36 | $ ld -shared -soname libgit.so.1 -o libgit.so.1.5.6.3 -lc -lz *.o | ||
37 | |||
38 | |||
39 | #You can also just copy the following commands into a file and run as a script inside the git directory | ||
40 | |||
41 | make clean | ||
42 | autoconf | ||
43 | ./configure | ||
44 | CFLAGS="-g -O2 -Wall -c -fPIC" make | ||
45 | mkdir libgit-objects | ||
46 | cp builtin*.o libgit-objects | ||
47 | cp xdiff/*.o libgit-objects | ||
48 | cp libgit.a libgit-objects | ||
49 | cd libgit-objects | ||
50 | strip -N main *.o | ||
51 | ar x libgit.a | ||
52 | ld -shared -soname libgit.so.1 -o libgit.so.1.5.6.3 -lc -lz *.o \ No newline at end of file | ||
diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/SceneObjectGroupDiff.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/SceneObjectGroupDiff.cs new file mode 100644 index 0000000..8957e8f --- /dev/null +++ b/OpenSim/Region/OptionalModules/ContentManagementSystem/SceneObjectGroupDiff.cs | |||
@@ -0,0 +1,218 @@ | |||
1 | ļ»æ/* | ||
2 | * Copyright (c) Contributors, http://opensimulator.org/ | ||
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions are met: | ||
7 | * * Redistributions of source code must retain the above copyright | ||
8 | * notice, this list of conditions and the following disclaimer. | ||
9 | * * Redistributions in binary form must reproduce the above copyright | ||
10 | * notice, this list of conditions and the following disclaimer in the | ||
11 | * documentation and/or other materials provided with the distribution. | ||
12 | * * Neither the name of the OpenSim Project nor the | ||
13 | * names of its contributors may be used to endorse or promote products | ||
14 | * derived from this software without specific prior written permission. | ||
15 | * | ||
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | */ | ||
27 | |||
28 | #region Header | ||
29 | |||
30 | // SceneObjectGroupDiff.cs | ||
31 | // User: bongiojp | ||
32 | |||
33 | #endregion Header | ||
34 | |||
35 | using System; | ||
36 | using System.Collections.Generic; | ||
37 | using System.Diagnostics; | ||
38 | using System.Drawing; | ||
39 | |||
40 | using OpenMetaverse; | ||
41 | |||
42 | using Nini.Config; | ||
43 | |||
44 | using OpenSim.Framework; | ||
45 | using OpenSim.Region.Framework.Interfaces; | ||
46 | using OpenSim.Region.Framework.Scenes; | ||
47 | using OpenSim.Region.Physics.Manager; | ||
48 | |||
49 | using log4net; | ||
50 | |||
51 | namespace OpenSim.Region.OptionalModules.ContentManagement | ||
52 | { | ||
53 | #region Enumerations | ||
54 | |||
55 | [Flags] | ||
56 | public enum Diff | ||
57 | { | ||
58 | NONE = 0, | ||
59 | FACECOLOR = 1, | ||
60 | SHAPE = 1<<1, | ||
61 | MATERIAL = 1<<2, | ||
62 | TEXTURE = 1<<3, | ||
63 | SCALE = 1<<4, | ||
64 | POSITION = 1<<5, | ||
65 | OFFSETPOSITION = 1<<6, | ||
66 | ROTATIONOFFSET = 1<<7, | ||
67 | ROTATIONALVELOCITY = 1<<8, | ||
68 | ACCELERATION = 1<<9, | ||
69 | ANGULARVELOCITY = 1<<10, | ||
70 | VELOCITY = 1<<11, | ||
71 | OBJECTOWNER = 1<<12, | ||
72 | PERMISSIONS = 1<<13, | ||
73 | DESCRIPTION = 1<<14, | ||
74 | NAME = 1<<15, | ||
75 | SCRIPT = 1<<16, | ||
76 | CLICKACTION = 1<<17, | ||
77 | PARTICLESYSTEM = 1<<18, | ||
78 | GLOW = 1<<19, | ||
79 | SALEPRICE = 1<<20, | ||
80 | SITNAME = 1<<21, | ||
81 | SITTARGETORIENTATION = 1<<22, | ||
82 | SITTARGETPOSITION = 1<<23, | ||
83 | TEXT = 1<<24, | ||
84 | TOUCHNAME = 1<<25 | ||
85 | } | ||
86 | |||
87 | #endregion Enumerations | ||
88 | |||
89 | public static class Difference | ||
90 | { | ||
91 | #region Static Fields | ||
92 | |||
93 | static float TimeToDiff = 0; | ||
94 | // private static readonly ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); | ||
95 | |||
96 | #endregion Static Fields | ||
97 | |||
98 | #region Private Methods | ||
99 | |||
100 | private static bool AreQuaternionsEquivalent(Quaternion first, Quaternion second) | ||
101 | { | ||
102 | Vector3 firstVector = llRot2Euler(first); | ||
103 | Vector3 secondVector = llRot2Euler(second); | ||
104 | return AreVectorsEquivalent(firstVector, secondVector); | ||
105 | } | ||
106 | |||
107 | private static bool AreVectorsEquivalent(Vector3 first, Vector3 second) | ||
108 | { | ||
109 | if (TruncateSignificant(first.X, 2) == TruncateSignificant(second.X, 2) | ||
110 | && TruncateSignificant(first.Y, 2) == TruncateSignificant(second.Y, 2) | ||
111 | && TruncateSignificant(first.Z, 2) == TruncateSignificant(second.Z, 2) | ||
112 | ) | ||
113 | return true; | ||
114 | else | ||
115 | return false; | ||
116 | } | ||
117 | |||
118 | // Taken from Region/ScriptEngine/Common/LSL_BuiltIn_Commands.cs | ||
119 | private static double NormalizeAngle(double angle) | ||
120 | { | ||
121 | angle = angle % (Math.PI * 2); | ||
122 | if (angle < 0) angle = angle + Math.PI * 2; | ||
123 | return angle; | ||
124 | } | ||
125 | |||
126 | private static int TruncateSignificant(float num, int digits) | ||
127 | { | ||
128 | return (int) Math.Ceiling((Math.Truncate(num * 10 * digits)/10*digits)); | ||
129 | // return (int) ((num * (10*digits))/10*digits); | ||
130 | } | ||
131 | |||
132 | // Taken from Region/ScriptEngine/Common/LSL_BuiltIn_Commands.cs | ||
133 | // Also changed the original function from LSL_Types to LL types | ||
134 | private static Vector3 llRot2Euler(Quaternion r) | ||
135 | { | ||
136 | Quaternion t = new Quaternion(r.X * r.X, r.Y * r.Y, r.Z * r.Z, r.W * r.W); | ||
137 | double m = (t.X + t.Y + t.Z + t.W); | ||
138 | if (m == 0) return new Vector3(); | ||
139 | double n = 2 * (r.Y * r.W + r.X * r.Z); | ||
140 | double p = m * m - n * n; | ||
141 | if (p > 0) | ||
142 | return new Vector3((float)NormalizeAngle(Math.Atan2(2.0 * (r.X * r.W - r.Y * r.Z), (-t.X - t.Y + t.Z + t.W))), | ||
143 | (float)NormalizeAngle(Math.Atan2(n, Math.Sqrt(p))), | ||
144 | (float)NormalizeAngle(Math.Atan2(2.0 * (r.Z * r.W - r.X * r.Y), (t.X - t.Y - t.Z + t.W)))); | ||
145 | else if (n > 0) | ||
146 | return new Vector3(0.0f, (float)(Math.PI / 2), (float)NormalizeAngle(Math.Atan2((r.Z * r.W + r.X * r.Y), 0.5 - t.X - t.Z))); | ||
147 | else | ||
148 | return new Vector3(0.0f, (float)(-Math.PI / 2), (float)NormalizeAngle(Math.Atan2((r.Z * r.W + r.X * r.Y), 0.5 - t.X - t.Z))); | ||
149 | } | ||
150 | |||
151 | #endregion Private Methods | ||
152 | |||
153 | #region Public Methods | ||
154 | |||
155 | /// <summary> | ||
156 | /// Compares the attributes (Vectors, Quaternions, Strings, etc.) between two scene object parts | ||
157 | /// and returns a Diff bitmask which details what the differences are. | ||
158 | /// </summary> | ||
159 | public static Diff FindDifferences(SceneObjectPart first, SceneObjectPart second) | ||
160 | { | ||
161 | Stopwatch x = new Stopwatch(); | ||
162 | x.Start(); | ||
163 | |||
164 | Diff result = 0; | ||
165 | |||
166 | // VECTOR COMPARISONS | ||
167 | if (!AreVectorsEquivalent(first.Acceleration, second.Acceleration)) | ||
168 | result |= Diff.ACCELERATION; | ||
169 | if (!AreVectorsEquivalent(first.AbsolutePosition, second.AbsolutePosition)) | ||
170 | result |= Diff.POSITION; | ||
171 | if (!AreVectorsEquivalent(first.AngularVelocity, second.AngularVelocity)) | ||
172 | result |= Diff.ANGULARVELOCITY; | ||
173 | if (!AreVectorsEquivalent(first.OffsetPosition, second.OffsetPosition)) | ||
174 | result |= Diff.OFFSETPOSITION; | ||
175 | if (!AreVectorsEquivalent(first.RotationalVelocity, second.RotationalVelocity)) | ||
176 | result |= Diff.ROTATIONALVELOCITY; | ||
177 | if (!AreVectorsEquivalent(first.Scale, second.Scale)) | ||
178 | result |= Diff.SCALE; | ||
179 | if (!AreVectorsEquivalent(first.Velocity, second.Velocity)) | ||
180 | result |= Diff.VELOCITY; | ||
181 | |||
182 | |||
183 | // QUATERNION COMPARISONS | ||
184 | if (!AreQuaternionsEquivalent(first.RotationOffset, second.RotationOffset)) | ||
185 | result |= Diff.ROTATIONOFFSET; | ||
186 | |||
187 | |||
188 | // MISC COMPARISONS (UUID, Byte) | ||
189 | if (first.ClickAction != second.ClickAction) | ||
190 | result |= Diff.CLICKACTION; | ||
191 | if (first.ObjectOwner != second.ObjectOwner) | ||
192 | result |= Diff.OBJECTOWNER; | ||
193 | |||
194 | |||
195 | // STRING COMPARISONS | ||
196 | if (first.Description != second.Description) | ||
197 | result |= Diff.DESCRIPTION; | ||
198 | if (first.Material != second.Material) | ||
199 | result |= Diff.MATERIAL; | ||
200 | if (first.Name != second.Name) | ||
201 | result |= Diff.NAME; | ||
202 | if (first.SitName != second.SitName) | ||
203 | result |= Diff.SITNAME; | ||
204 | if (first.Text != second.Text) | ||
205 | result |= Diff.TEXT; | ||
206 | if (first.TouchName != second.TouchName) | ||
207 | result |= Diff.TOUCHNAME; | ||
208 | |||
209 | x.Stop(); | ||
210 | TimeToDiff += x.ElapsedMilliseconds; | ||
211 | //m_log.Info("[DIFFERENCES] Time spent diffing objects so far" + TimeToDiff); | ||
212 | |||
213 | return result; | ||
214 | } | ||
215 | |||
216 | #endregion Public Methods | ||
217 | } | ||
218 | } | ||