opensim – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 eva 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 {
40 /// <summary>
41 /// Called by the login service
42 /// </summary>
43 /// <param name="userID"></param>
44 /// <returns></returns>
45 AvatarAppearance GetAppearance(UUID userID);
46  
47 /// <summary>
48 /// Called by everyone who can change the avatar data (so, regions)
49 /// </summary>
50 /// <param name="userID"></param>
51 /// <param name="appearance"></param>
52 /// <returns></returns>
53 bool SetAppearance(UUID userID, AvatarAppearance appearance);
54  
55 /// <summary>
56 /// Called by the login service
57 /// </summary>
58 /// <param name="userID"></param>
59 /// <returns></returns>
60 AvatarData GetAvatar(UUID userID);
61  
62 /// <summary>
63 /// Called by everyone who can change the avatar data (so, regions)
64 /// </summary>
65 /// <param name="userID"></param>
66 /// <param name="avatar"></param>
67 /// <returns></returns>
68 bool SetAvatar(UUID userID, AvatarData avatar);
69  
70 /// <summary>
71 /// Not sure if it's needed
72 /// </summary>
73 /// <param name="userID"></param>
74 /// <returns></returns>
75 bool ResetAvatar(UUID userID);
76  
77 /// <summary>
78 /// These methods raison d'etre:
79 /// No need to send the entire avatar data (SetAvatar) for changing attachments
80 /// </summary>
81 /// <param name="userID"></param>
82 /// <param name="attach"></param>
83 /// <returns></returns>
84 bool SetItems(UUID userID, string[] names, string[] values);
85 bool RemoveItems(UUID userID, string[] names);
86 }
87  
88 /// <summary>
89 /// Each region/client that uses avatars will have a data structure
90 /// of this type representing the avatars.
91 /// </summary>
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  
128 /// <summary>
129 /// </summary>
130 /// <returns></returns>
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 for (int i = 0 ; i < AvatarWearable.MAX_WEARABLES ; i++)
154 {
155 for (int j = 0 ; j < appearance.Wearables[i].Count ; j++)
156 {
157 string fieldName = String.Format("Wearable {0}:{1}", i, j);
158 Data[fieldName] = String.Format("{0}:{1}",
159 appearance.Wearables[i][j].ItemID.ToString(),
160 appearance.Wearables[i][j].AssetID.ToString());
161 }
162 }
163  
164 // Visual Params
165 string[] vps = new string[AvatarAppearance.VISUALPARAM_COUNT];
166 byte[] binary = appearance.VisualParams;
167  
168 for (int i = 0 ; i < AvatarAppearance.VISUALPARAM_COUNT ; i++)
169 {
170 vps[i] = binary[i].ToString();
171 }
172  
173 Data["VisualParams"] = String.Join(",", vps);
174  
175 // Attachments
176 List<AvatarAttachment> attachments = appearance.GetAttachments();
177 Dictionary<int, List<string>> atts = new Dictionary<int, List<string>>();
178 foreach (AvatarAttachment attach in attachments)
179 {
180 if (attach.ItemID != UUID.Zero)
181 {
182 if (!atts.ContainsKey(attach.AttachPoint))
183 atts[attach.AttachPoint] = new List<string>();
184 atts[attach.AttachPoint].Add(attach.ItemID.ToString());
185 }
186 }
187 foreach (KeyValuePair<int, List<string>> kvp in atts)
188 Data["_ap_" + kvp.Key] = string.Join(",", kvp.Value.ToArray());
189 }
190  
191 public AvatarAppearance ToAvatarAppearance()
192 {
193 AvatarAppearance appearance = new AvatarAppearance();
194  
195 if (Data.Count == 0)
196 return appearance;
197  
198 appearance.ClearWearables();
199 try
200 {
201 if (Data.ContainsKey("Serial"))
202 appearance.Serial = Int32.Parse(Data["Serial"]);
203  
204 if (Data.ContainsKey("AvatarHeight"))
205 appearance.AvatarHeight = float.Parse(Data["AvatarHeight"]);
206  
207 // Legacy Wearables
208 if (Data.ContainsKey("BodyItem"))
209 appearance.Wearables[AvatarWearable.BODY].Wear(
210 UUID.Parse(Data["BodyItem"]),
211 UUID.Parse(Data["BodyAsset"]));
212  
213 if (Data.ContainsKey("SkinItem"))
214 appearance.Wearables[AvatarWearable.SKIN].Wear(
215 UUID.Parse(Data["SkinItem"]),
216 UUID.Parse(Data["SkinAsset"]));
217  
218 if (Data.ContainsKey("HairItem"))
219 appearance.Wearables[AvatarWearable.HAIR].Wear(
220 UUID.Parse(Data["HairItem"]),
221 UUID.Parse(Data["HairAsset"]));
222  
223 if (Data.ContainsKey("EyesItem"))
224 appearance.Wearables[AvatarWearable.EYES].Wear(
225 UUID.Parse(Data["EyesItem"]),
226 UUID.Parse(Data["EyesAsset"]));
227  
228 if (Data.ContainsKey("ShirtItem"))
229 appearance.Wearables[AvatarWearable.SHIRT].Wear(
230 UUID.Parse(Data["ShirtItem"]),
231 UUID.Parse(Data["ShirtAsset"]));
232  
233 if (Data.ContainsKey("PantsItem"))
234 appearance.Wearables[AvatarWearable.PANTS].Wear(
235 UUID.Parse(Data["PantsItem"]),
236 UUID.Parse(Data["PantsAsset"]));
237  
238 if (Data.ContainsKey("ShoesItem"))
239 appearance.Wearables[AvatarWearable.SHOES].Wear(
240 UUID.Parse(Data["ShoesItem"]),
241 UUID.Parse(Data["ShoesAsset"]));
242  
243 if (Data.ContainsKey("SocksItem"))
244 appearance.Wearables[AvatarWearable.SOCKS].Wear(
245 UUID.Parse(Data["SocksItem"]),
246 UUID.Parse(Data["SocksAsset"]));
247  
248 if (Data.ContainsKey("JacketItem"))
249 appearance.Wearables[AvatarWearable.JACKET].Wear(
250 UUID.Parse(Data["JacketItem"]),
251 UUID.Parse(Data["JacketAsset"]));
252  
253 if (Data.ContainsKey("GlovesItem"))
254 appearance.Wearables[AvatarWearable.GLOVES].Wear(
255 UUID.Parse(Data["GlovesItem"]),
256 UUID.Parse(Data["GlovesAsset"]));
257  
258 if (Data.ContainsKey("UnderShirtItem"))
259 appearance.Wearables[AvatarWearable.UNDERSHIRT].Wear(
260 UUID.Parse(Data["UnderShirtItem"]),
261 UUID.Parse(Data["UnderShirtAsset"]));
262  
263 if (Data.ContainsKey("UnderPantsItem"))
264 appearance.Wearables[AvatarWearable.UNDERPANTS].Wear(
265 UUID.Parse(Data["UnderPantsItem"]),
266 UUID.Parse(Data["UnderPantsAsset"]));
267  
268 if (Data.ContainsKey("SkirtItem"))
269 appearance.Wearables[AvatarWearable.SKIRT].Wear(
270 UUID.Parse(Data["SkirtItem"]),
271 UUID.Parse(Data["SkirtAsset"]));
272  
273 if (Data.ContainsKey("VisualParams"))
274 {
275 string[] vps = Data["VisualParams"].Split(new char[] {','});
276 byte[] binary = new byte[AvatarAppearance.VISUALPARAM_COUNT];
277  
278 for (int i = 0 ; i < vps.Length && i < binary.Length ; i++)
279 binary[i] = (byte)Convert.ToInt32(vps[i]);
280  
281 appearance.VisualParams = binary;
282 }
283  
284 // New style wearables
285 foreach (KeyValuePair<string, string> _kvp in Data)
286 {
287 if (_kvp.Key.StartsWith("Wearable "))
288 {
289 string wearIndex = _kvp.Key.Substring(9);
290 string[] wearIndices = wearIndex.Split(new char[] {':'});
291 int index = Convert.ToInt32(wearIndices[0]);
292  
293 string[] ids = _kvp.Value.Split(new char[] {':'});
294 UUID itemID = new UUID(ids[0]);
295 UUID assetID = new UUID(ids[1]);
296  
297 appearance.Wearables[index].Add(itemID, assetID);
298 }
299 }
300  
301 // Attachments
302 Dictionary<string, string> attchs = new Dictionary<string, string>();
303 foreach (KeyValuePair<string, string> _kvp in Data)
304 if (_kvp.Key.StartsWith("_ap_"))
305 attchs[_kvp.Key] = _kvp.Value;
306  
307 foreach (KeyValuePair<string, string> _kvp in attchs)
308 {
309 string pointStr = _kvp.Key.Substring(4);
310 int point = 0;
311 if (!Int32.TryParse(pointStr, out point))
312 continue;
313  
314 List<string> idList = new List<string>(_kvp.Value.Split(new char[] {','}));
315  
316 appearance.SetAttachment(point, UUID.Zero, UUID.Zero);
317 foreach (string id in idList)
318 {
319 UUID uuid = UUID.Zero;
320 UUID.TryParse(id, out uuid);
321  
322 appearance.SetAttachment(point | 0x80, uuid, UUID.Zero);
323 }
324 }
325  
326 if (appearance.Wearables[AvatarWearable.BODY].Count == 0)
327 appearance.Wearables[AvatarWearable.BODY].Wear(
328 AvatarWearable.DefaultWearables[
329 AvatarWearable.BODY][0]);
330  
331 if (appearance.Wearables[AvatarWearable.SKIN].Count == 0)
332 appearance.Wearables[AvatarWearable.SKIN].Wear(
333 AvatarWearable.DefaultWearables[
334 AvatarWearable.SKIN][0]);
335  
336 if (appearance.Wearables[AvatarWearable.HAIR].Count == 0)
337 appearance.Wearables[AvatarWearable.HAIR].Wear(
338 AvatarWearable.DefaultWearables[
339 AvatarWearable.HAIR][0]);
340  
341 if (appearance.Wearables[AvatarWearable.EYES].Count == 0)
342 appearance.Wearables[AvatarWearable.EYES].Wear(
343 AvatarWearable.DefaultWearables[
344 AvatarWearable.EYES][0]);
345 }
346 catch
347 {
348 // We really should report something here, returning null
349 // will at least break the wrapper
350 return null;
351 }
352  
353 return appearance;
354 }
355 }
356 }