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.cs347
1 files changed, 261 insertions, 86 deletions
diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
index 22c8937..903e94b 100644
--- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
@@ -32,58 +32,46 @@ 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 : IAvatarFactory, IRegionModule 45 public class AvatarFactoryModule : 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);
48 private static readonly byte[] BAKE_INDICES = new byte[] { 8, 9, 10, 11, 19, 20 };
44 private Scene m_scene = null; 49 private Scene m_scene = null;
45 private static readonly AvatarAppearance def = new AvatarAppearance();
46 50
47 public bool TryGetAvatarAppearance(UUID avatarId, out AvatarAppearance appearance) 51 private static readonly int m_savetime = 5; // seconds to wait before saving changed appearance
48 { 52 private static readonly int m_sendtime = 2; // seconds to wait before sending changed appearance
49 AvatarData avatar = m_scene.AvatarService.GetAvatar(avatarId);
50 //if ((profile != null) && (profile.RootFolder != null))
51 if (avatar != null)
52 {
53 appearance = avatar.ToAvatarAppearance(avatarId);
54 return true;
55 }
56 53
57 m_log.ErrorFormat("[APPEARANCE]: Appearance not found for {0}, creating default", avatarId); 54 private static readonly int m_checkTime = 500; // milliseconds to wait between checks for appearance updates
58 appearance = CreateDefault(avatarId); 55 private System.Timers.Timer m_updateTimer = new System.Timers.Timer();
59 return false; 56 private Dictionary<UUID,long> m_savequeue = new Dictionary<UUID,long>();
60 } 57 private Dictionary<UUID,long> m_sendqueue = new Dictionary<UUID,long>();
61 58
62 private AvatarAppearance CreateDefault(UUID avatarId) 59 #region RegionModule Members
63 {
64 AvatarAppearance appearance = null;
65 AvatarWearable[] wearables;
66 byte[] visualParams;
67 GetDefaultAvatarAppearance(out wearables, out visualParams);
68 appearance = new AvatarAppearance(avatarId, wearables, visualParams);
69
70 return appearance;
71 }
72 60
73 public void Initialise(Scene scene, IConfigSource source) 61 public void Initialise(Scene scene, IConfigSource source)
74 { 62 {
75 scene.RegisterModuleInterface<IAvatarFactory>(this);
76 scene.EventManager.OnNewClient += NewClient; 63 scene.EventManager.OnNewClient += NewClient;
77 64
78 if (m_scene == null) 65 if (m_scene == null)
79 {
80 m_scene = scene; 66 m_scene = scene;
81 }
82
83 } 67 }
84 68
85 public void PostInitialise() 69 public void PostInitialise()
86 { 70 {
71 m_updateTimer.Enabled = false;
72 m_updateTimer.AutoReset = true;
73 m_updateTimer.Interval = m_checkTime; // 500 milliseconds wait to start async ops
74 m_updateTimer.Elapsed += new ElapsedEventHandler(HandleAppearanceUpdateTimer);
87 } 75 }
88 76
89 public void Close() 77 public void Close()
@@ -102,6 +90,8 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
102 90
103 public void NewClient(IClientAPI client) 91 public void NewClient(IClientAPI client)
104 { 92 {
93 client.OnRequestWearables += SendWearables;
94 client.OnSetAppearance += SetAppearance;
105 client.OnAvatarNowWearing += AvatarIsWearing; 95 client.OnAvatarNowWearing += AvatarIsWearing;
106 } 96 }
107 97
@@ -110,42 +100,211 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
110 // client.OnAvatarNowWearing -= AvatarIsWearing; 100 // client.OnAvatarNowWearing -= AvatarIsWearing;
111 } 101 }
112 102
113 public void SetAppearanceAssets(UUID userID, ref AvatarAppearance appearance) 103 #endregion
104
105 /// <summary>
106 /// Set appearance data (textureentry and slider settings) received from the client
107 /// </summary>
108 /// <param name="texture"></param>
109 /// <param name="visualParam"></param>
110 public void SetAppearance(IClientAPI client, Primitive.TextureEntry textureEntry, byte[] visualParams)
114 { 111 {
115 IInventoryService invService = m_scene.InventoryService; 112// DEBUG ON
113 m_log.WarnFormat("[AVFACTORY] SetAppearance for {0}",client.AgentId);
114// DEBUG OFF
116 115
117 if (invService.GetRootFolder(userID) != null) 116 ScenePresence sp = m_scene.GetScenePresence(client.AgentId);
117 if (sp == null)
118 { 118 {
119 for (int i = 0; i < 13; i++) 119 m_log.WarnFormat("[AVFACTORY] SetAppearance unable to find presence for {0}",client.AgentId);
120 return;
121 }
122
123 bool changed = false;
124
125 // Process the texture entry
126 if (textureEntry != null)
127 {
128 changed = sp.Appearance.SetTextureEntries(textureEntry);
129
130 for (int i = 0; i < BAKE_INDICES.Length; i++)
120 { 131 {
121 if (appearance.Wearables[i].ItemID == UUID.Zero) 132 int idx = BAKE_INDICES[i];
133 Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[idx];
134 if (face != null && face.TextureID != AppearanceManager.DEFAULT_AVATAR_TEXTURE)
135 Util.FireAndForget(delegate(object o) { CheckBakedTextureAssets(client,face.TextureID,idx); });
136 }
137 }
138
139 // Process the visual params, this may change height as well
140 if (visualParams != null)
141 {
142 if (sp.Appearance.SetVisualParams(visualParams))
143 {
144 changed = true;
145 if (sp.Appearance.AvatarHeight > 0)
146 sp.SetHeight(sp.Appearance.AvatarHeight);
147 }
148 }
149
150 // If something changed in the appearance then queue an appearance save
151 if (changed)
152 QueueAppearanceSave(client.AgentId);
153
154 // And always queue up an appearance update to send out
155 QueueAppearanceSend(client.AgentId);
156
157 // Send the appearance back to the avatar
158 AvatarAppearance avp = sp.Appearance;
159 sp.ControllingClient.SendAvatarDataImmediate(sp);
160 sp.ControllingClient.SendAppearance(avp.Owner,avp.VisualParams,avp.Texture.GetBytes());
161 }
162
163 /// <summary>
164 /// Checks for the existance of a baked texture asset and
165 /// requests the viewer rebake if the asset is not found
166 /// </summary>
167 /// <param name="client"></param>
168 /// <param name="textureID"></param>
169 /// <param name="idx"></param>
170 private void CheckBakedTextureAssets(IClientAPI client, UUID textureID, int idx)
171 {
172 if (m_scene.AssetService.Get(textureID.ToString()) == null)
173 {
174 m_log.WarnFormat("[AVFACTORY]: Missing baked texture {0} ({1}) for avatar {2}",
175 textureID,idx,client.Name);
176 client.SendRebakeAvatarTextures(textureID);
177 }
178 }
179
180 #region UpdateAppearanceTimer
181
182 public void QueueAppearanceSend(UUID agentid)
183 {
184// DEBUG ON
185 m_log.WarnFormat("[AVFACTORY] Queue appearance send for {0}",agentid);
186// DEBUG OFF
187
188 // 100 nanoseconds (ticks) we should wait
189 long timestamp = DateTime.Now.Ticks + Convert.ToInt64(m_sendtime * 10000000);
190 lock (m_sendqueue)
191 {
192 m_sendqueue[agentid] = timestamp;
193 m_updateTimer.Start();
194 }
195 }
196
197 public void QueueAppearanceSave(UUID agentid)
198 {
199// DEBUG ON
200 m_log.WarnFormat("[AVFACTORY] Queue appearance save for {0}",agentid);
201// DEBUG OFF
202
203 // 100 nanoseconds (ticks) we should wait
204 long timestamp = DateTime.Now.Ticks + Convert.ToInt64(m_savetime * 10000000);
205 lock (m_savequeue)
206 {
207 m_savequeue[agentid] = timestamp;
208 m_updateTimer.Start();
209 }
210 }
211
212 private void HandleAppearanceSend(UUID agentid)
213 {
214 ScenePresence sp = m_scene.GetScenePresence(agentid);
215 if (sp == null)
216 {
217 m_log.WarnFormat("[AVFACTORY] Agent {0} no longer in the scene",agentid);
218 return;
219 }
220
221// DEBUG ON
222 m_log.WarnFormat("[AVFACTORY] Handle appearance send for {0}\n{1}",agentid,sp.Appearance.ToString());
223// DEBUG OFF
224
225 // Send the appearance to everyone in the scene
226 sp.SendAppearanceToAllOtherAgents();
227
228 // Send the appearance back to the avatar
229 AvatarAppearance avp = sp.Appearance;
230 sp.ControllingClient.SendAvatarDataImmediate(sp);
231 sp.ControllingClient.SendAppearance(avp.Owner,avp.VisualParams,avp.Texture.GetBytes());
232
233/*
234// this needs to be fixed, the flag should be on scene presence not the region module
235 // Start the animations if necessary
236 if (!m_startAnimationSet)
237 {
238 sp.Animator.UpdateMovementAnimations();
239 m_startAnimationSet = true;
240 }
241*/
242 }
243
244 private void HandleAppearanceSave(UUID agentid)
245 {
246 ScenePresence sp = m_scene.GetScenePresence(agentid);
247 if (sp == null)
248 {
249 m_log.WarnFormat("[AVFACTORY] Agent {0} no longer in the scene",agentid);
250 return;
251 }
252
253 m_scene.AvatarService.SetAppearance(agentid, sp.Appearance);
254 }
255
256 private void HandleAppearanceUpdateTimer(object sender, EventArgs ea)
257 {
258 long now = DateTime.Now.Ticks;
259
260 lock (m_sendqueue)
261 {
262 Dictionary<UUID,long> sends = new Dictionary<UUID,long>(m_sendqueue);
263 foreach (KeyValuePair<UUID,long> kvp in sends)
264 {
265 if (kvp.Value < now)
122 { 266 {
123 appearance.Wearables[i].AssetID = UUID.Zero; 267 Util.FireAndForget(delegate(object o) { HandleAppearanceSend(kvp.Key); });
268 m_sendqueue.Remove(kvp.Key);
124 } 269 }
125 else 270 }
126 { 271 }
127 InventoryItemBase baseItem = new InventoryItemBase(appearance.Wearables[i].ItemID, userID);
128 baseItem = invService.GetItem(baseItem);
129 272
130 if (baseItem != null) 273 lock (m_savequeue)
131 { 274 {
132 appearance.Wearables[i].AssetID = baseItem.AssetID; 275 Dictionary<UUID,long> saves = new Dictionary<UUID,long>(m_savequeue);
133 } 276 foreach (KeyValuePair<UUID,long> kvp in saves)
134 else 277 {
135 { 278 if (kvp.Value < now)
136 m_log.ErrorFormat( 279 {
137 "[APPEARANCE]: Can't find inventory item {0} for {1}, setting to default", 280 Util.FireAndForget(delegate(object o) { HandleAppearanceSave(kvp.Key); });
138 appearance.Wearables[i].ItemID, (WearableType)i); 281 m_savequeue.Remove(kvp.Key);
139
140 appearance.Wearables[i].AssetID = def.Wearables[i].AssetID;
141 }
142 } 282 }
143 } 283 }
144 } 284 }
145 else 285
286 if (m_savequeue.Count == 0 && m_sendqueue.Count == 0)
287 m_updateTimer.Stop();
288 }
289
290 #endregion
291
292 /// <summary>
293 /// Tell the client for this scene presence what items it should be wearing now
294 /// </summary>
295 public void SendWearables(IClientAPI client)
296 {
297 ScenePresence sp = m_scene.GetScenePresence(client.AgentId);
298 if (sp == null)
146 { 299 {
147 m_log.WarnFormat("[APPEARANCE]: user {0} has no inventory, appearance isn't going to work", userID); 300 m_log.WarnFormat("[AVFACTORY] SendWearables unable to find presence for {0}",client.AgentId);
301 return;
148 } 302 }
303
304// DEBUG ON
305 m_log.WarnFormat("[AVFACTORY]: Received request for wearables of {0}", client.AgentId);
306// DEBUG OFF
307 client.SendWearables(sp.Appearance.Wearables,sp.Appearance.Serial++);
149 } 308 }
150 309
151 /// <summary> 310 /// <summary>
@@ -153,65 +312,81 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
153 /// </summary> 312 /// </summary>
154 /// <param name="sender"></param> 313 /// <param name="sender"></param>
155 /// <param name="e"></param> 314 /// <param name="e"></param>
156 public void AvatarIsWearing(Object sender, AvatarWearingArgs e) 315 public void AvatarIsWearing(IClientAPI client, AvatarWearingArgs e)
157 { 316 {
158 m_log.DebugFormat("[APPEARANCE]: AvatarIsWearing"); 317 ScenePresence sp = m_scene.GetScenePresence(client.AgentId);
159 318 if (sp == null)
160 IClientAPI clientView = (IClientAPI)sender;
161 ScenePresence sp = m_scene.GetScenePresence(clientView.AgentId);
162
163 if (sp == null)
164 { 319 {
165 m_log.Error("[APPEARANCE]: Avatar is child agent, ignoring AvatarIsWearing event"); 320 m_log.WarnFormat("[AVFACTORY] AvatarIsWearing unable to find presence for {0}",client.AgentId);
166 return; 321 return;
167 } 322 }
323
324// DEBUG ON
325 m_log.WarnFormat("[AVFACTORY]: AvatarIsWearing called for {0}",client.AgentId);
326// DEBUG OFF
168 327
169 AvatarAppearance avatAppearance = sp.Appearance; 328 AvatarAppearance avatAppearance = new AvatarAppearance(sp.Appearance);
170 //if (!TryGetAvatarAppearance(clientView.AgentId, out avatAppearance)) 329
330 //if (!TryGetAvatarAppearance(client.AgentId, out avatAppearance))
171 //{ 331 //{
172 // m_log.Warn("[APPEARANCE]: We didn't seem to find the appearance, falling back to ScenePresence"); 332 // m_log.Warn("[AVFACTORY]: We didn't seem to find the appearance, falling back to ScenePresence");
173 // avatAppearance = sp.Appearance; 333 // avatAppearance = sp.Appearance;
174 //} 334 //}
175 335
176 //m_log.DebugFormat("[APPEARANCE]: Received wearables for {0}", clientView.Name); 336 //m_log.DebugFormat("[AVFACTORY]: Received wearables for {0}", client.Name);
177 337
178 foreach (AvatarWearingArgs.Wearable wear in e.NowWearing) 338 foreach (AvatarWearingArgs.Wearable wear in e.NowWearing)
179 { 339 {
180 if (wear.Type < 13) 340 if (wear.Type < AvatarWearable.MAX_WEARABLES)
181 { 341 {
182 avatAppearance.Wearables[wear.Type].ItemID = wear.ItemID; 342 AvatarWearable newWearable = new AvatarWearable(wear.ItemID,UUID.Zero);
343 avatAppearance.SetWearable(wear.Type, newWearable);
183 } 344 }
184 } 345 }
185 346
186 SetAppearanceAssets(sp.UUID, ref avatAppearance); 347 SetAppearanceAssets(sp.UUID, ref avatAppearance);
187 AvatarData adata = new AvatarData(avatAppearance);
188 m_scene.AvatarService.SetAvatar(clientView.AgentId, adata);
189 348
349 m_scene.AvatarService.SetAppearance(client.AgentId, avatAppearance);
190 sp.Appearance = avatAppearance; 350 sp.Appearance = avatAppearance;
191 } 351 }
192 352
193 public static void GetDefaultAvatarAppearance(out AvatarWearable[] wearables, out byte[] visualParams) 353 private void SetAppearanceAssets(UUID userID, ref AvatarAppearance appearance)
194 { 354 {
195 visualParams = GetDefaultVisualParams(); 355 IInventoryService invService = m_scene.InventoryService;
196 wearables = AvatarWearable.DefaultWearables;
197 }
198 356
199 public void UpdateDatabase(UUID user, AvatarAppearance appearance) 357 if (invService.GetRootFolder(userID) != null)
200 { 358 {
201 //m_log.DebugFormat("[APPEARANCE]: UpdateDatabase"); 359 for (int i = 0; i < AvatarWearable.MAX_WEARABLES; i++)
202 AvatarData adata = new AvatarData(appearance); 360 {
203 m_scene.AvatarService.SetAvatar(user, adata); 361 if (appearance.Wearables[i].ItemID == UUID.Zero)
204 } 362 {
363 appearance.Wearables[i].AssetID = UUID.Zero;
364 }
365 else
366 {
367 InventoryItemBase baseItem = new InventoryItemBase(appearance.Wearables[i].ItemID, userID);
368 baseItem = invService.GetItem(baseItem);
205 369
206 private static byte[] GetDefaultVisualParams() 370 if (baseItem != null)
207 { 371 {
208 byte[] visualParams; 372 appearance.Wearables[i].AssetID = baseItem.AssetID;
209 visualParams = new byte[218]; 373 }
210 for (int i = 0; i < 218; i++) 374 else
375 {
376 m_log.ErrorFormat(
377 "[AVFACTORY]: Can't find inventory item {0} for {1}, setting to default",
378 appearance.Wearables[i].ItemID, (WearableType)i);
379
380 appearance.Wearables[i].ItemID = UUID.Zero;
381 appearance.Wearables[i].AssetID = UUID.Zero;
382 }
383 }
384 }
385 }
386 else
211 { 387 {
212 visualParams[i] = 100; 388 m_log.WarnFormat("[AVFACTORY]: user {0} has no inventory, appearance isn't going to work", userID);
213 } 389 }
214 return visualParams;
215 } 390 }
216 } 391 }
217} 392}