aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs')
-rw-r--r--OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs277
1 files changed, 212 insertions, 65 deletions
diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
index 9f7ff7f..bfbbcf8 100644
--- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
@@ -32,23 +32,45 @@ using Nini.Config;
32using OpenMetaverse; 32using OpenMetaverse;
33using OpenSim.Framework; 33using OpenSim.Framework;
34 34
35using System.Threading;
36using System.Timers;
37using System.Collections.Generic;
38
35using OpenSim.Region.Framework.Interfaces; 39using OpenSim.Region.Framework.Interfaces;
36using OpenSim.Region.Framework.Scenes; 40using OpenSim.Region.Framework.Scenes;
37using OpenSim.Services.Interfaces; 41using OpenSim.Services.Interfaces;
38 42
39namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory 43namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
40{ 44{
41 public class AvatarFactoryModule : IRegionModule 45 public class AvatarFactoryModule : IAvatarFactory, IRegionModule
42 { 46 {
43 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
44 private static readonly byte[] BAKE_INDICES = new byte[] { 8, 9, 10, 11, 19, 20 };
45 private Scene m_scene = null; 48 private Scene m_scene = null;
46 49
47 private bool m_startAnimationSet = false; 50 private int m_savetime = 5; // seconds to wait before saving changed appearance
51 private int m_sendtime = 2; // seconds to wait before sending changed appearance
52
53 private int m_checkTime = 500; // milliseconds to wait between checks for appearance updates
54 private System.Timers.Timer m_updateTimer = new System.Timers.Timer();
55 private Dictionary<UUID,long> m_savequeue = new Dictionary<UUID,long>();
56 private Dictionary<UUID,long> m_sendqueue = new Dictionary<UUID,long>();
48 57
49 public void Initialise(Scene scene, IConfigSource source) 58 #region RegionModule Members
59
60 public void Initialise(Scene scene, IConfigSource config)
50 { 61 {
62 scene.RegisterModuleInterface<IAvatarFactory>(this);
51 scene.EventManager.OnNewClient += NewClient; 63 scene.EventManager.OnNewClient += NewClient;
64
65 if (config != null)
66 {
67 IConfig sconfig = config.Configs["Startup"];
68 if (sconfig != null)
69 {
70 m_savetime = Convert.ToInt32(sconfig.GetString("DelayBeforeAppearanceSave",Convert.ToString(m_savetime)));
71 m_sendtime = Convert.ToInt32(sconfig.GetString("DelayBeforeAppearanceSend",Convert.ToString(m_sendtime)));
72 }
73 }
52 74
53 if (m_scene == null) 75 if (m_scene == null)
54 m_scene = scene; 76 m_scene = scene;
@@ -56,6 +78,10 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
56 78
57 public void PostInitialise() 79 public void PostInitialise()
58 { 80 {
81 m_updateTimer.Enabled = false;
82 m_updateTimer.AutoReset = true;
83 m_updateTimer.Interval = m_checkTime; // 500 milliseconds wait to start async ops
84 m_updateTimer.Elapsed += new ElapsedEventHandler(HandleAppearanceUpdateTimer);
59 } 85 }
60 86
61 public void Close() 87 public void Close()
@@ -84,6 +110,36 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
84 // client.OnAvatarNowWearing -= AvatarIsWearing; 110 // client.OnAvatarNowWearing -= AvatarIsWearing;
85 } 111 }
86 112
113 #endregion
114
115 public bool ValidateBakedTextureCache(IClientAPI client)
116 {
117 ScenePresence sp = m_scene.GetScenePresence(client.AgentId);
118 if (sp == null)
119 {
120 m_log.WarnFormat("[AVFACTORY] SetAppearance unable to find presence for {0}",client.AgentId);
121 return false;
122 }
123
124 bool cached = true;
125
126 // Process the texture entry
127 for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++)
128 {
129 int idx = AvatarAppearance.BAKE_INDICES[i];
130 Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[idx];
131 if (face != null && face.TextureID != AppearanceManager.DEFAULT_AVATAR_TEXTURE)
132 if (! CheckBakedTextureAsset(client,face.TextureID,idx))
133 {
134 sp.Appearance.Texture.FaceTextures[idx] = null;
135 cached = false;
136 }
137 }
138
139 return cached;
140 }
141
142
87 /// <summary> 143 /// <summary>
88 /// Set appearance data (textureentry and slider settings) received from the client 144 /// Set appearance data (textureentry and slider settings) received from the client
89 /// </summary> 145 /// </summary>
@@ -91,6 +147,10 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
91 /// <param name="visualParam"></param> 147 /// <param name="visualParam"></param>
92 public void SetAppearance(IClientAPI client, Primitive.TextureEntry textureEntry, byte[] visualParams) 148 public void SetAppearance(IClientAPI client, Primitive.TextureEntry textureEntry, byte[] visualParams)
93 { 149 {
150// DEBUG ON
151 m_log.WarnFormat("[AVFACTORY] SetAppearance for {0}",client.AgentId);
152// DEBUG OFF
153
94 ScenePresence sp = m_scene.GetScenePresence(client.AgentId); 154 ScenePresence sp = m_scene.GetScenePresence(client.AgentId);
95 if (sp == null) 155 if (sp == null)
96 { 156 {
@@ -98,85 +158,179 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
98 return; 158 return;
99 } 159 }
100 160
101// DEBUG ON
102 m_log.WarnFormat("[AVFACTORY] SetAppearance for {0}",client.AgentId);
103// DEBUG OFF
104
105/*
106 if (m_physicsActor != null)
107 {
108 if (!IsChildAgent)
109 {
110 // This may seem like it's redundant, remove the avatar from the physics scene
111 // just to add it back again, but it saves us from having to update
112 // 3 variables 10 times a second.
113 bool flyingTemp = m_physicsActor.Flying;
114 RemoveFromPhysicalScene();
115 //m_scene.PhysicsScene.RemoveAvatar(m_physicsActor);
116
117 //PhysicsActor = null;
118
119 AddToPhysicalScene(flyingTemp);
120 }
121 }
122*/
123 #region Bake Cache Check
124
125 bool changed = false; 161 bool changed = false;
126 162
127 // Process the texture entry 163 // Process the texture entry
128 if (textureEntry != null) 164 if (textureEntry != null)
129 { 165 {
130 for (int i = 0; i < BAKE_INDICES.Length; i++) 166 changed = sp.Appearance.SetTextureEntries(textureEntry);
131 {
132 int j = BAKE_INDICES[i];
133 Primitive.TextureEntryFace face = textureEntry.FaceTextures[j];
134 167
168 for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++)
169 {
170 int idx = AvatarAppearance.BAKE_INDICES[i];
171 Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[idx];
135 if (face != null && face.TextureID != AppearanceManager.DEFAULT_AVATAR_TEXTURE) 172 if (face != null && face.TextureID != AppearanceManager.DEFAULT_AVATAR_TEXTURE)
136 { 173 Util.FireAndForget(delegate(object o) {
137 if (m_scene.AssetService.Get(face.TextureID.ToString()) == null) 174 if (! CheckBakedTextureAsset(client,face.TextureID,idx))
138 { 175 client.SendRebakeAvatarTextures(face.TextureID);
139 m_log.WarnFormat("[AVFACTORY]: Missing baked texture {0} ({1}) for avatar {2}",face.TextureID,j,this.Name); 176 });
140 client.SendRebakeAvatarTextures(face.TextureID);
141 }
142 }
143 } 177 }
144 changed = sp.Appearance.SetTextureEntries(textureEntry);
145
146 } 178 }
147 179
148 #endregion Bake Cache Check 180 // Process the visual params, this may change height as well
149 181 if (visualParams != null)
150 changed = sp.Appearance.SetVisualParams(visualParams) || changed; 182 {
151 183 if (sp.Appearance.SetVisualParams(visualParams))
152 // If nothing changed (this happens frequently) just return 184 {
185 changed = true;
186 if (sp.Appearance.AvatarHeight > 0)
187 sp.SetHeight(sp.Appearance.AvatarHeight);
188 }
189 }
190
191 // If something changed in the appearance then queue an appearance save
153 if (changed) 192 if (changed)
193 QueueAppearanceSave(client.AgentId);
194
195 // And always queue up an appearance update to send out
196 QueueAppearanceSend(client.AgentId);
197
198 // Send the appearance back to the avatar
199 // AvatarAppearance avp = sp.Appearance;
200 // sp.ControllingClient.SendAvatarDataImmediate(sp);
201 // sp.ControllingClient.SendAppearance(avp.Owner,avp.VisualParams,avp.Texture.GetBytes());
202 }
203
204 /// <summary>
205 /// Checks for the existance of a baked texture asset and
206 /// requests the viewer rebake if the asset is not found
207 /// </summary>
208 /// <param name="client"></param>
209 /// <param name="textureID"></param>
210 /// <param name="idx"></param>
211 private bool CheckBakedTextureAsset(IClientAPI client, UUID textureID, int idx)
212 {
213 if (m_scene.AssetService.Get(textureID.ToString()) == null)
154 { 214 {
215 m_log.WarnFormat("[AVFACTORY]: Missing baked texture {0} ({1}) for avatar {2}",
216 textureID,idx,client.Name);
217 return false;
218 }
219 return true;
220 }
221
222 #region UpdateAppearanceTimer
223
224 public void QueueAppearanceSend(UUID agentid)
225 {
155// DEBUG ON 226// DEBUG ON
156 m_log.Warn("[AVFACTORY] Appearance changed"); 227 m_log.WarnFormat("[AVFACTORY] Queue appearance send for {0}",agentid);
157// DEBUG OFF 228// DEBUG OFF
158 sp.Appearance.SetAppearance(textureEntry, visualParams);
159 if (sp.Appearance.AvatarHeight > 0)
160 sp.SetHeight(sp.Appearance.AvatarHeight);
161 229
162 m_scene.AvatarService.SetAppearance(client.AgentId, sp.Appearance); 230 // 100 nanoseconds (ticks) we should wait
231 long timestamp = DateTime.Now.Ticks + Convert.ToInt64(m_sendtime * 10000000);
232 lock (m_sendqueue)
233 {
234 m_sendqueue[agentid] = timestamp;
235 m_updateTimer.Start();
163 } 236 }
237 }
238
239 public void QueueAppearanceSave(UUID agentid)
240 {
164// DEBUG ON 241// DEBUG ON
165 else 242 m_log.WarnFormat("[AVFACTORY] Queue appearance save for {0}",agentid);
166 m_log.Warn("[AVFACTORY] Appearance did not change"); 243// DEBUG OFF
167// DEBUG OFF
168 244
245 // 100 nanoseconds (ticks) we should wait
246 long timestamp = DateTime.Now.Ticks + Convert.ToInt64(m_savetime * 10000000);
247 lock (m_savequeue)
248 {
249 m_savequeue[agentid] = timestamp;
250 m_updateTimer.Start();
251 }
252 }
253
254 private void HandleAppearanceSend(UUID agentid)
255 {
256 ScenePresence sp = m_scene.GetScenePresence(agentid);
257 if (sp == null)
258 {
259 m_log.WarnFormat("[AVFACTORY] Agent {0} no longer in the scene",agentid);
260 return;
261 }
262
263// DEBUG ON
264 m_log.WarnFormat("[AVFACTORY] Handle appearance send for {0}",agentid);
265// DEBUG OFF
266
267 // Send the appearance to everyone in the scene
169 sp.SendAppearanceToAllOtherAgents(); 268 sp.SendAppearanceToAllOtherAgents();
269 sp.ControllingClient.SendAvatarDataImmediate(sp);
270
271 // Send the appearance back to the avatar
272 // AvatarAppearance avp = sp.Appearance;
273 // sp.ControllingClient.SendAppearance(avp.Owner,avp.VisualParams,avp.Texture.GetBytes());
274
275/*
276// this needs to be fixed, the flag should be on scene presence not the region module
277 // Start the animations if necessary
170 if (!m_startAnimationSet) 278 if (!m_startAnimationSet)
171 { 279 {
172 sp.Animator.UpdateMovementAnimations(); 280 sp.Animator.UpdateMovementAnimations();
173 m_startAnimationSet = true; 281 m_startAnimationSet = true;
174 } 282 }
283*/
284 }
175 285
176 client.SendAvatarDataImmediate(sp); 286 private void HandleAppearanceSave(UUID agentid)
177 client.SendAppearance(sp.Appearance.Owner,sp.Appearance.VisualParams,sp.Appearance.Texture.GetBytes()); 287 {
288 ScenePresence sp = m_scene.GetScenePresence(agentid);
289 if (sp == null)
290 {
291 m_log.WarnFormat("[AVFACTORY] Agent {0} no longer in the scene",agentid);
292 return;
293 }
294
295 m_scene.AvatarService.SetAppearance(agentid, sp.Appearance);
178 } 296 }
179 297
298 private void HandleAppearanceUpdateTimer(object sender, EventArgs ea)
299 {
300 long now = DateTime.Now.Ticks;
301
302 lock (m_sendqueue)
303 {
304 Dictionary<UUID,long> sends = new Dictionary<UUID,long>(m_sendqueue);
305 foreach (KeyValuePair<UUID,long> kvp in sends)
306 {
307 if (kvp.Value < now)
308 {
309 Util.FireAndForget(delegate(object o) { HandleAppearanceSend(kvp.Key); });
310 m_sendqueue.Remove(kvp.Key);
311 }
312 }
313 }
314
315 lock (m_savequeue)
316 {
317 Dictionary<UUID,long> saves = new Dictionary<UUID,long>(m_savequeue);
318 foreach (KeyValuePair<UUID,long> kvp in saves)
319 {
320 if (kvp.Value < now)
321 {
322 Util.FireAndForget(delegate(object o) { HandleAppearanceSave(kvp.Key); });
323 m_savequeue.Remove(kvp.Key);
324 }
325 }
326 }
327
328 if (m_savequeue.Count == 0 && m_sendqueue.Count == 0)
329 m_updateTimer.Stop();
330 }
331
332 #endregion
333
180 /// <summary> 334 /// <summary>
181 /// Tell the client for this scene presence what items it should be wearing now 335 /// Tell the client for this scene presence what items it should be wearing now
182 /// </summary> 336 /// </summary>
@@ -215,14 +369,6 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
215 369
216 AvatarAppearance avatAppearance = new AvatarAppearance(sp.Appearance); 370 AvatarAppearance avatAppearance = new AvatarAppearance(sp.Appearance);
217 371
218 //if (!TryGetAvatarAppearance(client.AgentId, out avatAppearance))
219 //{
220 // m_log.Warn("[AVFACTORY]: We didn't seem to find the appearance, falling back to ScenePresence");
221 // avatAppearance = sp.Appearance;
222 //}
223
224 //m_log.DebugFormat("[AVFACTORY]: Received wearables for {0}", client.Name);
225
226 foreach (AvatarWearingArgs.Wearable wear in e.NowWearing) 372 foreach (AvatarWearingArgs.Wearable wear in e.NowWearing)
227 { 373 {
228 if (wear.Type < AvatarWearable.MAX_WEARABLES) 374 if (wear.Type < AvatarWearable.MAX_WEARABLES)
@@ -232,10 +378,11 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
232 } 378 }
233 } 379 }
234 380
381 // This could take awhile since it needs to pull inventory
235 SetAppearanceAssets(sp.UUID, ref avatAppearance); 382 SetAppearanceAssets(sp.UUID, ref avatAppearance);
236 383
237 m_scene.AvatarService.SetAppearance(client.AgentId, avatAppearance);
238 sp.Appearance = avatAppearance; 384 sp.Appearance = avatAppearance;
385 m_scene.AvatarService.SetAppearance(client.AgentId, sp.Appearance);
239 } 386 }
240 387
241 private void SetAppearanceAssets(UUID userID, ref AvatarAppearance appearance) 388 private void SetAppearanceAssets(UUID userID, ref AvatarAppearance appearance)