opensim – Blame information for rev 1
?pathlinks?
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 | } |