diff options
author | Master ScienceSim | 2010-11-18 10:01:10 -0800 |
---|---|---|
committer | Melanie | 2010-11-18 19:04:50 +0000 |
commit | 8f1a79420be062ea59b3c04aacb439fb57713ac7 (patch) | |
tree | 374eca7dccda5d1bfcc3a64f38696f84e3f008a6 /OpenSim/Region/CoreModules/Avatar | |
parent | small refactor: reuse existing commandLine string rather than calling cmdline... (diff) | |
download | opensim-SC-8f1a79420be062ea59b3c04aacb439fb57713ac7.zip opensim-SC-8f1a79420be062ea59b3c04aacb439fb57713ac7.tar.gz opensim-SC-8f1a79420be062ea59b3c04aacb439fb57713ac7.tar.bz2 opensim-SC-8f1a79420be062ea59b3c04aacb439fb57713ac7.tar.xz |
Fixed appearance send for avatars with only default textures. This should fix some of the appearance problems on osgrid. Also added a transaction lock on SetAppearance. This won't prevent concurrent access to Appearance but it will at least make sure each update completes.
Signed-off-by: Melanie <melanie@t-data.com>
Diffstat (limited to 'OpenSim/Region/CoreModules/Avatar')
-rw-r--r-- | OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs | 127 |
1 files changed, 74 insertions, 53 deletions
diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs index 2dd444d..0df4585 100644 --- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs | |||
@@ -55,6 +55,8 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
55 | private Dictionary<UUID,long> m_savequeue = new Dictionary<UUID,long>(); | 55 | private Dictionary<UUID,long> m_savequeue = new Dictionary<UUID,long>(); |
56 | private Dictionary<UUID,long> m_sendqueue = new Dictionary<UUID,long>(); | 56 | private Dictionary<UUID,long> m_sendqueue = new Dictionary<UUID,long>(); |
57 | 57 | ||
58 | private object m_setAppearanceLock = new object(); | ||
59 | |||
58 | #region RegionModule Members | 60 | #region RegionModule Members |
59 | 61 | ||
60 | public void Initialise(Scene scene, IConfigSource config) | 62 | public void Initialise(Scene scene, IConfigSource config) |
@@ -69,6 +71,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
69 | { | 71 | { |
70 | m_savetime = Convert.ToInt32(sconfig.GetString("DelayBeforeAppearanceSave",Convert.ToString(m_savetime))); | 72 | m_savetime = Convert.ToInt32(sconfig.GetString("DelayBeforeAppearanceSave",Convert.ToString(m_savetime))); |
71 | m_sendtime = Convert.ToInt32(sconfig.GetString("DelayBeforeAppearanceSend",Convert.ToString(m_sendtime))); | 73 | m_sendtime = Convert.ToInt32(sconfig.GetString("DelayBeforeAppearanceSend",Convert.ToString(m_sendtime))); |
74 | // m_log.InfoFormat("[AVFACTORY] configured for {0} save and {1} send",m_savetime,m_sendtime); | ||
72 | } | 75 | } |
73 | } | 76 | } |
74 | 77 | ||
@@ -117,26 +120,28 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
117 | ScenePresence sp = m_scene.GetScenePresence(client.AgentId); | 120 | ScenePresence sp = m_scene.GetScenePresence(client.AgentId); |
118 | if (sp == null) | 121 | if (sp == null) |
119 | { | 122 | { |
120 | m_log.WarnFormat("[AVATAR FACTORY MODULE]: SetAppearance unable to find presence for {0}", client.AgentId); | 123 | m_log.WarnFormat("[AVFACTORY]: SetAppearance unable to find presence for {0}", client.AgentId); |
121 | return false; | 124 | return false; |
122 | } | 125 | } |
123 | 126 | ||
124 | bool cached = true; | 127 | bool defonly = true; // are we only using default textures |
125 | 128 | ||
126 | // Process the texture entry | 129 | // Process the texture entry |
127 | for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++) | 130 | for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++) |
128 | { | 131 | { |
129 | int idx = AvatarAppearance.BAKE_INDICES[i]; | 132 | int idx = AvatarAppearance.BAKE_INDICES[i]; |
130 | Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[idx]; | 133 | Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[idx]; |
131 | if (face != null && face.TextureID != AppearanceManager.DEFAULT_AVATAR_TEXTURE) | 134 | if (face == null || face.TextureID != AppearanceManager.DEFAULT_AVATAR_TEXTURE) |
132 | if (! CheckBakedTextureAsset(client,face.TextureID,idx)) | 135 | continue; |
133 | { | 136 | |
134 | sp.Appearance.Texture.FaceTextures[idx] = null; | 137 | defonly = false; // found a non-default texture reference |
135 | cached = false; | 138 | |
136 | } | 139 | if (! CheckBakedTextureAsset(client,face.TextureID,idx)) |
140 | return false; | ||
137 | } | 141 | } |
138 | 142 | ||
139 | return cached; | 143 | // If we only found default textures, then the appearance is not cached |
144 | return (defonly ? false : true); | ||
140 | } | 145 | } |
141 | 146 | ||
142 | /// <summary> | 147 | /// <summary> |
@@ -146,44 +151,59 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
146 | /// <param name="visualParam"></param> | 151 | /// <param name="visualParam"></param> |
147 | public void SetAppearance(IClientAPI client, Primitive.TextureEntry textureEntry, byte[] visualParams) | 152 | public void SetAppearance(IClientAPI client, Primitive.TextureEntry textureEntry, byte[] visualParams) |
148 | { | 153 | { |
149 | // m_log.WarnFormat("[AVATAR FACTORY MODULE]: SetAppearance for {0}",client.AgentId); | ||
150 | |||
151 | ScenePresence sp = m_scene.GetScenePresence(client.AgentId); | 154 | ScenePresence sp = m_scene.GetScenePresence(client.AgentId); |
152 | if (sp == null) | 155 | if (sp == null) |
153 | { | 156 | { |
154 | m_log.WarnFormat("[AVATAR FACTORY MODULE]: SetAppearance unable to find presence for {0}",client.AgentId); | 157 | m_log.WarnFormat("[AVFACTORY]: SetAppearance unable to find presence for {0}",client.AgentId); |
155 | return; | 158 | return; |
156 | } | 159 | } |
157 | 160 | ||
161 | // m_log.WarnFormat("[AVFACTORY]: Start SetAppearance for {0}",client.AgentId); | ||
162 | |||
158 | bool changed = false; | 163 | bool changed = false; |
159 | 164 | ||
160 | // Process the texture entry | 165 | // Process the texture entry transactionally, this doesn't guarantee that Appearance is |
161 | if (textureEntry != null) | 166 | // going to be handled correctly but it does serialize the updates to the appearance |
167 | lock (m_setAppearanceLock) | ||
162 | { | 168 | { |
163 | changed = sp.Appearance.SetTextureEntries(textureEntry); | 169 | if (textureEntry != null) |
164 | |||
165 | for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++) | ||
166 | { | 170 | { |
167 | int idx = AvatarAppearance.BAKE_INDICES[i]; | 171 | changed = sp.Appearance.SetTextureEntries(textureEntry); |
168 | Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[idx]; | 172 | |
169 | if (face != null && face.TextureID != AppearanceManager.DEFAULT_AVATAR_TEXTURE) | 173 | // m_log.WarnFormat("[AVFACTORY]: Prepare to check textures for {0}",client.AgentId); |
170 | Util.FireAndForget(delegate(object o) { | 174 | |
171 | if (! CheckBakedTextureAsset(client,face.TextureID,idx)) | 175 | for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++) |
172 | client.SendRebakeAvatarTextures(face.TextureID); | 176 | { |
173 | }); | 177 | int idx = AvatarAppearance.BAKE_INDICES[i]; |
178 | Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[idx]; | ||
179 | if (face != null && face.TextureID != AppearanceManager.DEFAULT_AVATAR_TEXTURE) | ||
180 | Util.FireAndForget(delegate(object o) { | ||
181 | if (! CheckBakedTextureAsset(client,face.TextureID,idx)) | ||
182 | client.SendRebakeAvatarTextures(face.TextureID); | ||
183 | }); | ||
184 | } | ||
185 | |||
186 | // m_log.WarnFormat("[AVFACTORY]: Complete texture check for {0}",client.AgentId); | ||
174 | } | 187 | } |
175 | } | ||
176 | 188 | ||
177 | // Process the visual params, this may change height as well | 189 | // Process the visual params, this may change height as well |
178 | if (visualParams != null) | 190 | if (visualParams != null) |
179 | { | ||
180 | if (sp.Appearance.SetVisualParams(visualParams)) | ||
181 | { | 191 | { |
182 | changed = true; | 192 | if (sp.Appearance.SetVisualParams(visualParams)) |
183 | if (sp.Appearance.AvatarHeight > 0) | 193 | { |
184 | sp.SetHeight(sp.Appearance.AvatarHeight); | 194 | changed = true; |
195 | if (sp.Appearance.AvatarHeight > 0) | ||
196 | sp.SetHeight(sp.Appearance.AvatarHeight); | ||
197 | } | ||
185 | } | 198 | } |
199 | |||
200 | // Send the appearance back to the avatar, not clear that this is needed | ||
201 | sp.ControllingClient.SendAvatarDataImmediate(sp); | ||
202 | // AvatarAppearance avp = sp.Appearance; | ||
203 | // sp.ControllingClient.SendAppearance(avp.Owner,avp.VisualParams,avp.Texture.GetBytes()); | ||
204 | |||
186 | } | 205 | } |
206 | |||
187 | 207 | ||
188 | // If something changed in the appearance then queue an appearance save | 208 | // If something changed in the appearance then queue an appearance save |
189 | if (changed) | 209 | if (changed) |
@@ -192,10 +212,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
192 | // And always queue up an appearance update to send out | 212 | // And always queue up an appearance update to send out |
193 | QueueAppearanceSend(client.AgentId); | 213 | QueueAppearanceSend(client.AgentId); |
194 | 214 | ||
195 | // Send the appearance back to the avatar | 215 | // m_log.WarnFormat("[AVFACTORY]: Complete SetAppearance for {0}:\n{1}",client.AgentId,sp.Appearance.ToString()); |
196 | // AvatarAppearance avp = sp.Appearance; | ||
197 | // sp.ControllingClient.SendAvatarDataImmediate(sp); | ||
198 | // sp.ControllingClient.SendAppearance(avp.Owner,avp.VisualParams,avp.Texture.GetBytes()); | ||
199 | } | 216 | } |
200 | 217 | ||
201 | /// <summary> | 218 | /// <summary> |
@@ -209,7 +226,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
209 | { | 226 | { |
210 | if (m_scene.AssetService.Get(textureID.ToString()) == null) | 227 | if (m_scene.AssetService.Get(textureID.ToString()) == null) |
211 | { | 228 | { |
212 | m_log.WarnFormat("[AVATAR FACTORY MODULE]: Missing baked texture {0} ({1}) for avatar {2}", | 229 | m_log.WarnFormat("[AVFACTORY]: Missing baked texture {0} ({1}) for avatar {2}", |
213 | textureID, idx, client.Name); | 230 | textureID, idx, client.Name); |
214 | return false; | 231 | return false; |
215 | } | 232 | } |
@@ -220,10 +237,10 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
220 | 237 | ||
221 | public void QueueAppearanceSend(UUID agentid) | 238 | public void QueueAppearanceSend(UUID agentid) |
222 | { | 239 | { |
223 | // m_log.WarnFormat("[AVATAR FACTORY MODULE]: Queue appearance send for {0}", agentid); | 240 | // m_log.WarnFormat("[AVFACTORY]: Queue appearance send for {0}", agentid); |
224 | 241 | ||
225 | // 100 nanoseconds (ticks) we should wait | 242 | // 10000 ticks per millisecond, 1000 milliseconds per second |
226 | long timestamp = DateTime.Now.Ticks + Convert.ToInt64(m_sendtime * 10000000); | 243 | long timestamp = DateTime.Now.Ticks + Convert.ToInt64(m_sendtime * 1000 * 10000); |
227 | lock (m_sendqueue) | 244 | lock (m_sendqueue) |
228 | { | 245 | { |
229 | m_sendqueue[agentid] = timestamp; | 246 | m_sendqueue[agentid] = timestamp; |
@@ -233,10 +250,10 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
233 | 250 | ||
234 | public void QueueAppearanceSave(UUID agentid) | 251 | public void QueueAppearanceSave(UUID agentid) |
235 | { | 252 | { |
236 | // m_log.WarnFormat("[AVATAR FACTORY MODULE]: Queue appearance save for {0}", agentid); | 253 | // m_log.WarnFormat("[AVFACTORY]: Queue appearance save for {0}", agentid); |
237 | 254 | ||
238 | // 100 nanoseconds (ticks) we should wait | 255 | // 10000 ticks per millisecond, 1000 milliseconds per second |
239 | long timestamp = DateTime.Now.Ticks + Convert.ToInt64(m_savetime * 10000000); | 256 | long timestamp = DateTime.Now.Ticks + Convert.ToInt64(m_savetime * 1000 * 10000); |
240 | lock (m_savequeue) | 257 | lock (m_savequeue) |
241 | { | 258 | { |
242 | m_savequeue[agentid] = timestamp; | 259 | m_savequeue[agentid] = timestamp; |
@@ -249,15 +266,15 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
249 | ScenePresence sp = m_scene.GetScenePresence(agentid); | 266 | ScenePresence sp = m_scene.GetScenePresence(agentid); |
250 | if (sp == null) | 267 | if (sp == null) |
251 | { | 268 | { |
252 | m_log.WarnFormat("[AVATAR FACTORY MODULE]: Agent {0} no longer in the scene", agentid); | 269 | m_log.WarnFormat("[AVFACTORY]: Agent {0} no longer in the scene", agentid); |
253 | return; | 270 | return; |
254 | } | 271 | } |
255 | 272 | ||
256 | // m_log.WarnFormat("[AVATAR FACTORY MODULE]: Handle appearance send for {0}", agentid); | 273 | // m_log.WarnFormat("[AVFACTORY]: Handle appearance send for {0}", agentid); |
257 | 274 | ||
258 | // Send the appearance to everyone in the scene | 275 | // Send the appearance to everyone in the scene |
259 | sp.SendAppearanceToAllOtherAgents(); | 276 | sp.SendAppearanceToAllOtherAgents(); |
260 | sp.ControllingClient.SendAvatarDataImmediate(sp); | 277 | // sp.ControllingClient.SendAvatarDataImmediate(sp); |
261 | 278 | ||
262 | // Send the appearance back to the avatar | 279 | // Send the appearance back to the avatar |
263 | // AvatarAppearance avp = sp.Appearance; | 280 | // AvatarAppearance avp = sp.Appearance; |
@@ -279,10 +296,12 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
279 | ScenePresence sp = m_scene.GetScenePresence(agentid); | 296 | ScenePresence sp = m_scene.GetScenePresence(agentid); |
280 | if (sp == null) | 297 | if (sp == null) |
281 | { | 298 | { |
282 | m_log.WarnFormat("[AVATAR FACTORY MODULE]: Agent {0} no longer in the scene", agentid); | 299 | m_log.WarnFormat("[AVFACTORY]: Agent {0} no longer in the scene", agentid); |
283 | return; | 300 | return; |
284 | } | 301 | } |
285 | 302 | ||
303 | // m_log.WarnFormat("[AVFACTORY] avatar {0} save appearance",agentid); | ||
304 | |||
286 | m_scene.AvatarService.SetAppearance(agentid, sp.Appearance); | 305 | m_scene.AvatarService.SetAppearance(agentid, sp.Appearance); |
287 | } | 306 | } |
288 | 307 | ||
@@ -330,11 +349,11 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
330 | ScenePresence sp = m_scene.GetScenePresence(client.AgentId); | 349 | ScenePresence sp = m_scene.GetScenePresence(client.AgentId); |
331 | if (sp == null) | 350 | if (sp == null) |
332 | { | 351 | { |
333 | m_log.WarnFormat("[AVATAR FACTORY MODULE]: SendWearables unable to find presence for {0}", client.AgentId); | 352 | m_log.WarnFormat("[AVFACTORY]: SendWearables unable to find presence for {0}", client.AgentId); |
334 | return; | 353 | return; |
335 | } | 354 | } |
336 | 355 | ||
337 | // m_log.WarnFormat("[AVATAR FACTORY MODULE]: Received request for wearables of {0}", client.AgentId); | 356 | // m_log.WarnFormat("[AVFACTORY]: Received request for wearables of {0}", client.AgentId); |
338 | 357 | ||
339 | client.SendWearables(sp.Appearance.Wearables, sp.Appearance.Serial++); | 358 | client.SendWearables(sp.Appearance.Wearables, sp.Appearance.Serial++); |
340 | } | 359 | } |
@@ -349,11 +368,11 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
349 | ScenePresence sp = m_scene.GetScenePresence(client.AgentId); | 368 | ScenePresence sp = m_scene.GetScenePresence(client.AgentId); |
350 | if (sp == null) | 369 | if (sp == null) |
351 | { | 370 | { |
352 | m_log.WarnFormat("[AVATAR FACTORY MODULE]: AvatarIsWearing unable to find presence for {0}", client.AgentId); | 371 | m_log.WarnFormat("[AVFACTORY]: AvatarIsWearing unable to find presence for {0}", client.AgentId); |
353 | return; | 372 | return; |
354 | } | 373 | } |
355 | 374 | ||
356 | // m_log.WarnFormat("[AVATAR FACTORY MODULE]: AvatarIsWearing called for {0}", client.AgentId); | 375 | // m_log.WarnFormat("[AVFACTORY]: AvatarIsWearing called for {0}", client.AgentId); |
357 | 376 | ||
358 | AvatarAppearance avatAppearance = new AvatarAppearance(sp.Appearance, false); | 377 | AvatarAppearance avatAppearance = new AvatarAppearance(sp.Appearance, false); |
359 | 378 | ||
@@ -368,6 +387,8 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
368 | // This could take awhile since it needs to pull inventory | 387 | // This could take awhile since it needs to pull inventory |
369 | SetAppearanceAssets(sp.UUID, ref avatAppearance); | 388 | SetAppearanceAssets(sp.UUID, ref avatAppearance); |
370 | 389 | ||
390 | // could get fancier with the locks here, but in the spirit of "last write wins" | ||
391 | // this should work correctly | ||
371 | sp.Appearance = avatAppearance; | 392 | sp.Appearance = avatAppearance; |
372 | m_scene.AvatarService.SetAppearance(client.AgentId, sp.Appearance); | 393 | m_scene.AvatarService.SetAppearance(client.AgentId, sp.Appearance); |
373 | } | 394 | } |
@@ -398,7 +419,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
398 | else | 419 | else |
399 | { | 420 | { |
400 | m_log.ErrorFormat( | 421 | m_log.ErrorFormat( |
401 | "[AVATAR FACTORY MODULE]: Can't find inventory item {0} for {1}, setting to default", | 422 | "[AVFACTORY]: Can't find inventory item {0} for {1}, setting to default", |
402 | appearance.Wearables[i][j].ItemID, (WearableType)i); | 423 | appearance.Wearables[i][j].ItemID, (WearableType)i); |
403 | 424 | ||
404 | appearance.Wearables[i].RemoveItem(appearance.Wearables[i][j].ItemID); | 425 | appearance.Wearables[i].RemoveItem(appearance.Wearables[i][j].ItemID); |
@@ -408,7 +429,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
408 | } | 429 | } |
409 | else | 430 | else |
410 | { | 431 | { |
411 | m_log.WarnFormat("[AVATAR FACTORY MODULE]: user {0} has no inventory, appearance isn't going to work", userID); | 432 | m_log.WarnFormat("[AVFACTORY]: user {0} has no inventory, appearance isn't going to work", userID); |
412 | } | 433 | } |
413 | } | 434 | } |
414 | } | 435 | } |