OpenSim
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros
IAvatarService.cs
Go to the documentation of this file.
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 OpenSimulator 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 using System;
29 using System.Collections;
30 using System.Collections.Generic;
31 
32 using OpenSim.Framework;
33 
34 using OpenMetaverse;
35 
36 namespace OpenSim.Services.Interfaces
37 {
38  public interface IAvatarService
39  {
45  AvatarAppearance GetAppearance(UUID userID);
46 
53  bool SetAppearance(UUID userID, AvatarAppearance appearance);
54 
60  AvatarData GetAvatar(UUID userID);
61 
68  bool SetAvatar(UUID userID, AvatarData avatar);
69 
75  bool ResetAvatar(UUID userID);
76 
84  bool SetItems(UUID userID, string[] names, string[] values);
85  bool RemoveItems(UUID userID, string[] names);
86  }
87 
92  public class AvatarData
93  {
94  // This pretty much determines which name/value pairs will be
95  // present below. The name/value pair describe a part of
96  // the avatar. For SL avatars, these would be "shape", "texture1",
97  // etc. For other avatars, they might be "mesh", "skin", etc.
98  // The value portion is a URL that is expected to resolve to an
99  // asset of the type required by the handler for that field.
100  // It is required that regions can access these URLs. Allowing
101  // direct access by a viewer is not required, and, if provided,
102  // may be read-only. A "naked" UUID can be used to refer to an
103  // asset int he current region's asset service, which is not
104  // portable, but allows legacy appearance to continue to
105  // function. Closed, LL-based grids will never need URLs here.
106 
107  public int AvatarType;
108  public Dictionary<string,string> Data;
109 
110  public AvatarData()
111  {
112  }
113 
114  public AvatarData(Dictionary<string, object> kvp)
115  {
116  Data = new Dictionary<string, string>();
117 
118  if (kvp.ContainsKey("AvatarType"))
119  Int32.TryParse(kvp["AvatarType"].ToString(), out AvatarType);
120 
121  foreach (KeyValuePair<string, object> _kvp in kvp)
122  {
123  if (_kvp.Value != null)
124  Data[_kvp.Key] = _kvp.Value.ToString();
125  }
126  }
127 
131  public Dictionary<string, object> ToKeyValuePairs()
132  {
133  Dictionary<string, object> result = new Dictionary<string, object>();
134 
135  result["AvatarType"] = AvatarType.ToString();
136  foreach (KeyValuePair<string, string> _kvp in Data)
137  {
138  if (_kvp.Value != null)
139  result[_kvp.Key] = _kvp.Value;
140  }
141  return result;
142  }
143 
144  public AvatarData(AvatarAppearance appearance)
145  {
146  AvatarType = 1; // SL avatars
147  Data = new Dictionary<string, string>();
148 
149  Data["Serial"] = appearance.Serial.ToString();
150  // Wearables
151  Data["AvatarHeight"] = appearance.AvatarHeight.ToString();
152 
153  // TODO: With COF, is this even needed?
154  for (int i = 0 ; i < AvatarWearable.LEGACY_VERSION_MAX_WEARABLES ; i++)
155  {
156  for (int j = 0 ; j < appearance.Wearables[i].Count ; j++)
157  {
158  string fieldName = String.Format("Wearable {0}:{1}", i, j);
159  Data[fieldName] = String.Format("{0}:{1}",
160  appearance.Wearables[i][j].ItemID.ToString(),
161  appearance.Wearables[i][j].AssetID.ToString());
162  }
163  }
164 
165  // Visual Params
166  //string[] vps = new string[AvatarAppearance.VISUALPARAM_COUNT];
167  //byte[] binary = appearance.VisualParams;
168 
169  // for (int i = 0 ; i < AvatarAppearance.VISUALPARAM_COUNT ; i++)
170 
171  byte[] binary = appearance.VisualParams;
172  string[] vps = new string[binary.Length];
173 
174  for (int i = 0; i < binary.Length; i++)
175  {
176  vps[i] = binary[i].ToString();
177  }
178 
179  Data["VisualParams"] = String.Join(",", vps);
180 
181  // Attachments
182  List<AvatarAttachment> attachments = appearance.GetAttachments();
183  Dictionary<int, List<string>> atts = new Dictionary<int, List<string>>();
184  foreach (AvatarAttachment attach in attachments)
185  {
186  if (attach.ItemID != UUID.Zero)
187  {
188  if (!atts.ContainsKey(attach.AttachPoint))
189  atts[attach.AttachPoint] = new List<string>();
190  atts[attach.AttachPoint].Add(attach.ItemID.ToString());
191  }
192  }
193  foreach (KeyValuePair<int, List<string>> kvp in atts)
194  Data["_ap_" + kvp.Key] = string.Join(",", kvp.Value.ToArray());
195  }
196 
198  {
199  AvatarAppearance appearance = new AvatarAppearance();
200 
201  if (Data.Count == 0)
202  return appearance;
203 
204  appearance.ClearWearables();
205  try
206  {
207  if (Data.ContainsKey("Serial"))
208  appearance.Serial = Int32.Parse(Data["Serial"]);
209 
210  if (Data.ContainsKey("AvatarHeight"))
211  {
212  float h = float.Parse(Data["AvatarHeight"]);
213  if( h == 0f)
214  h = 1.9f;
215  appearance.SetSize(new Vector3(0.45f, 0.6f, h ));
216 // appearance.AvatarHeight = float.Parse(Data["AvatarHeight"]);
217  }
218 
219  // Legacy Wearables
220  if (Data.ContainsKey("BodyItem"))
221  appearance.Wearables[AvatarWearable.BODY].Wear(
222  UUID.Parse(Data["BodyItem"]),
223  UUID.Parse(Data["BodyAsset"]));
224 
225  if (Data.ContainsKey("SkinItem"))
226  appearance.Wearables[AvatarWearable.SKIN].Wear(
227  UUID.Parse(Data["SkinItem"]),
228  UUID.Parse(Data["SkinAsset"]));
229 
230  if (Data.ContainsKey("HairItem"))
231  appearance.Wearables[AvatarWearable.HAIR].Wear(
232  UUID.Parse(Data["HairItem"]),
233  UUID.Parse(Data["HairAsset"]));
234 
235  if (Data.ContainsKey("EyesItem"))
236  appearance.Wearables[AvatarWearable.EYES].Wear(
237  UUID.Parse(Data["EyesItem"]),
238  UUID.Parse(Data["EyesAsset"]));
239 
240  if (Data.ContainsKey("ShirtItem"))
241  appearance.Wearables[AvatarWearable.SHIRT].Wear(
242  UUID.Parse(Data["ShirtItem"]),
243  UUID.Parse(Data["ShirtAsset"]));
244 
245  if (Data.ContainsKey("PantsItem"))
246  appearance.Wearables[AvatarWearable.PANTS].Wear(
247  UUID.Parse(Data["PantsItem"]),
248  UUID.Parse(Data["PantsAsset"]));
249 
250  if (Data.ContainsKey("ShoesItem"))
251  appearance.Wearables[AvatarWearable.SHOES].Wear(
252  UUID.Parse(Data["ShoesItem"]),
253  UUID.Parse(Data["ShoesAsset"]));
254 
255  if (Data.ContainsKey("SocksItem"))
256  appearance.Wearables[AvatarWearable.SOCKS].Wear(
257  UUID.Parse(Data["SocksItem"]),
258  UUID.Parse(Data["SocksAsset"]));
259 
260  if (Data.ContainsKey("JacketItem"))
261  appearance.Wearables[AvatarWearable.JACKET].Wear(
262  UUID.Parse(Data["JacketItem"]),
263  UUID.Parse(Data["JacketAsset"]));
264 
265  if (Data.ContainsKey("GlovesItem"))
266  appearance.Wearables[AvatarWearable.GLOVES].Wear(
267  UUID.Parse(Data["GlovesItem"]),
268  UUID.Parse(Data["GlovesAsset"]));
269 
270  if (Data.ContainsKey("UnderShirtItem"))
272  UUID.Parse(Data["UnderShirtItem"]),
273  UUID.Parse(Data["UnderShirtAsset"]));
274 
275  if (Data.ContainsKey("UnderPantsItem"))
277  UUID.Parse(Data["UnderPantsItem"]),
278  UUID.Parse(Data["UnderPantsAsset"]));
279 
280  if (Data.ContainsKey("SkirtItem"))
281  appearance.Wearables[AvatarWearable.SKIRT].Wear(
282  UUID.Parse(Data["SkirtItem"]),
283  UUID.Parse(Data["SkirtAsset"]));
284 
285  if (Data.ContainsKey("VisualParams"))
286  {
287  string[] vps = Data["VisualParams"].Split(new char[] {','});
288  //byte[] binary = new byte[AvatarAppearance.VISUALPARAM_COUNT];
289 
290  //for (int i = 0 ; i < vps.Length && i < binary.Length ; i++)
291  byte[] binary = new byte[vps.Length];
292 
293  for (int i = 0; i < vps.Length; i++)
294  binary[i] = (byte)Convert.ToInt32(vps[i]);
295 
296  appearance.VisualParams = binary;
297  }
298 
299  // New style wearables
300  foreach (KeyValuePair<string, string> _kvp in Data)
301  {
302  if (_kvp.Key.StartsWith("Wearable "))
303  {
304  string wearIndex = _kvp.Key.Substring(9);
305  string[] wearIndices = wearIndex.Split(new char[] {':'});
306  int index = Convert.ToInt32(wearIndices[0]);
307 
308  string[] ids = _kvp.Value.Split(new char[] {':'});
309  UUID itemID = new UUID(ids[0]);
310  UUID assetID = new UUID(ids[1]);
311 
312  appearance.Wearables[index].Add(itemID, assetID);
313  }
314  }
315 
316  // Attachments
317  Dictionary<string, string> attchs = new Dictionary<string, string>();
318  foreach (KeyValuePair<string, string> _kvp in Data)
319  if (_kvp.Key.StartsWith("_ap_"))
320  attchs[_kvp.Key] = _kvp.Value;
321 
322  foreach (KeyValuePair<string, string> _kvp in attchs)
323  {
324  string pointStr = _kvp.Key.Substring(4);
325  int point = 0;
326  if (!Int32.TryParse(pointStr, out point))
327  continue;
328 
329  List<string> idList = new List<string>(_kvp.Value.Split(new char[] {','}));
330 
331  appearance.SetAttachment(point, UUID.Zero, UUID.Zero);
332  foreach (string id in idList)
333  {
334  UUID uuid = UUID.Zero;
335  UUID.TryParse(id, out uuid);
336 
337  appearance.SetAttachment(point | 0x80, uuid, UUID.Zero);
338  }
339  }
340 
341  if (appearance.Wearables[AvatarWearable.BODY].Count == 0)
342  appearance.Wearables[AvatarWearable.BODY].Wear(
343  AvatarWearable.DefaultWearables[
344  AvatarWearable.BODY][0]);
345 
346  if (appearance.Wearables[AvatarWearable.SKIN].Count == 0)
347  appearance.Wearables[AvatarWearable.SKIN].Wear(
348  AvatarWearable.DefaultWearables[
349  AvatarWearable.SKIN][0]);
350 
351  if (appearance.Wearables[AvatarWearable.HAIR].Count == 0)
352  appearance.Wearables[AvatarWearable.HAIR].Wear(
353  AvatarWearable.DefaultWearables[
354  AvatarWearable.HAIR][0]);
355 
356  if (appearance.Wearables[AvatarWearable.EYES].Count == 0)
357  appearance.Wearables[AvatarWearable.EYES].Wear(
358  AvatarWearable.DefaultWearables[
359  AvatarWearable.EYES][0]);
360 
361  }
362  catch
363  {
364  // We really should report something here, returning null
365  // will at least break the wrapper
366  return null;
367  }
368 
369  return appearance;
370  }
371  }
372 }
void Wear(WearableItem item)
Contains the Avatar's Appearance and methods to manipulate the appearance.
Dictionary< string, object > ToKeyValuePairs()
AvatarData(Dictionary< string, object > kvp)
virtual AvatarWearable[] Wearables
AvatarData(AvatarAppearance appearance)
Each region/client that uses avatars will have a data structure of this type representing the avatars...
delegate void SetAppearance(IClientAPI remoteClient, Primitive.TextureEntry textureEntry, byte[] visualParams, Vector3 AvSize, WearableCacheItem[] CacheItems)
Dictionary< string, string > Data
static readonly int UNDERSHIRT
static readonly int UNDERPANTS