diff options
Diffstat (limited to '')
-rw-r--r-- | AssetManagement.cs | 460 |
1 files changed, 460 insertions, 0 deletions
diff --git a/AssetManagement.cs b/AssetManagement.cs new file mode 100644 index 0000000..adc8bd5 --- /dev/null +++ b/AssetManagement.cs | |||
@@ -0,0 +1,460 @@ | |||
1 | /* | ||
2 | * | ||
3 | Copyright (c) OpenSim project, http://sim.opensecondlife.org/ | ||
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 <organization> 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 <copyright holder> ``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 <copyright holder> 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 | |||
29 | using System; | ||
30 | using System.Collections.Generic; | ||
31 | using libsecondlife; | ||
32 | using System.Collections; | ||
33 | using libsecondlife.Packets; | ||
34 | using libsecondlife.AssetSystem; | ||
35 | using System.IO; | ||
36 | |||
37 | namespace OpenSim | ||
38 | { | ||
39 | /// <summary> | ||
40 | /// Asset and Image management | ||
41 | /// </summary> | ||
42 | public class AssetManagement | ||
43 | { | ||
44 | public Dictionary<libsecondlife.LLUUID,AssetInfo> Assets; | ||
45 | public Dictionary<libsecondlife.LLUUID,TextureImage> Textures; | ||
46 | |||
47 | public ArrayList AssetRequests=new ArrayList(); //should change to a generic | ||
48 | public ArrayList TextureRequests=new ArrayList(); | ||
49 | // public ArrayList uploads=new ArrayList(); | ||
50 | private Server server; | ||
51 | public InventoryManager InventoryManager; | ||
52 | private System.Text.Encoding enc = System.Text.Encoding.ASCII; | ||
53 | |||
54 | /// <summary> | ||
55 | /// | ||
56 | /// </summary> | ||
57 | /// <param name="server"></param> | ||
58 | public AssetManagement(Server server) | ||
59 | { | ||
60 | this.server=server; | ||
61 | Textures=new Dictionary<libsecondlife.LLUUID,TextureImage> (); | ||
62 | Assets=new Dictionary<libsecondlife.LLUUID,AssetInfo> (); | ||
63 | this.initialise(); | ||
64 | } | ||
65 | |||
66 | /// <summary> | ||
67 | /// | ||
68 | /// </summary> | ||
69 | private void initialise() | ||
70 | { | ||
71 | //Shape and skin base assets | ||
72 | AssetInfo Asset=new AssetInfo(); | ||
73 | Asset.filename="base_shape.dat"; | ||
74 | Asset.Full_ID=new LLUUID("66c41e39-38f9-f75a-024e-585989bfab73"); | ||
75 | this.LoadAsset(Asset); | ||
76 | this.Assets.Add(Asset.Full_ID,Asset); | ||
77 | |||
78 | Asset=new AssetInfo(); | ||
79 | Asset.filename="base_skin.dat"; | ||
80 | Asset.Full_ID=new LLUUID("e0ee49b5a4184df8d3c9a65361fe7f49"); | ||
81 | this.LoadAsset(Asset); | ||
82 | this.Assets.Add(Asset.Full_ID,Asset); | ||
83 | |||
84 | //our test images | ||
85 | //Change these filenames to images you want to use. | ||
86 | TextureImage Image=new TextureImage(); | ||
87 | Image.filename="testpic2.jp2"; | ||
88 | Image.Full_ID=new LLUUID("00000000-0000-0000-5005-000000000005"); | ||
89 | Image.Name="test Texture"; | ||
90 | this.LoadImage(Image); | ||
91 | this.Textures.Add(Image.Full_ID,Image); | ||
92 | |||
93 | Image=new TextureImage(); | ||
94 | Image.filename="map_base.jp2"; | ||
95 | Image.Full_ID=new LLUUID("00000000-0000-0000-7007-000000000006"); | ||
96 | this.LoadImage(Image); | ||
97 | this.Textures.Add(Image.Full_ID,Image); | ||
98 | |||
99 | Image=new TextureImage(); | ||
100 | Image.filename="map1.jp2"; | ||
101 | Image.Full_ID=new LLUUID("00000000-0000-0000-7009-000000000008"); | ||
102 | this.LoadImage(Image); | ||
103 | this.Textures.Add(Image.Full_ID,Image); | ||
104 | } | ||
105 | |||
106 | /// <summary> | ||
107 | /// | ||
108 | /// </summary> | ||
109 | /// <param name="UserInfo"></param> | ||
110 | /// <param name="AssetID"></param> | ||
111 | /// <param name="TransferRequest"></param> | ||
112 | #region AssetRegion | ||
113 | |||
114 | public void AddAssetRequest(User_Agent_info UserInfo, LLUUID AssetID, TransferRequestPacket TransferRequest) | ||
115 | { | ||
116 | |||
117 | if(!this.Assets.ContainsKey(AssetID)) | ||
118 | { | ||
119 | //not found asset | ||
120 | return; | ||
121 | } | ||
122 | AssetInfo info=this.Assets[AssetID]; | ||
123 | //for now as it will be only skin or shape request just send back the asset | ||
124 | TransferInfoPacket Transfer=new TransferInfoPacket(); | ||
125 | Transfer.TransferInfo.ChannelType=2; | ||
126 | Transfer.TransferInfo.Status=0; | ||
127 | Transfer.TransferInfo.TargetType=0; | ||
128 | Transfer.TransferInfo.Params=TransferRequest.TransferInfo.Params; | ||
129 | Transfer.TransferInfo.Size=info.data.Length; | ||
130 | Transfer.TransferInfo.TransferID=TransferRequest.TransferInfo.TransferID; | ||
131 | |||
132 | server.SendPacket(Transfer,true,UserInfo); | ||
133 | |||
134 | TransferPacketPacket TransferPacket=new TransferPacketPacket(); | ||
135 | TransferPacket.TransferData.Packet=0; | ||
136 | TransferPacket.TransferData.ChannelType=2; | ||
137 | TransferPacket.TransferData.TransferID=TransferRequest.TransferInfo.TransferID; | ||
138 | if(info.data.Length>1000) //but needs to be less than 2000 at the moment | ||
139 | { | ||
140 | byte[] chunk=new byte[1000]; | ||
141 | Array.Copy(info.data,chunk,1000); | ||
142 | TransferPacket.TransferData.Data=chunk; | ||
143 | TransferPacket.TransferData.Status=0; | ||
144 | server.SendPacket(TransferPacket,true,UserInfo); | ||
145 | |||
146 | TransferPacket=new TransferPacketPacket(); | ||
147 | TransferPacket.TransferData.Packet=1; | ||
148 | TransferPacket.TransferData.ChannelType=2; | ||
149 | TransferPacket.TransferData.TransferID=TransferRequest.TransferInfo.TransferID; | ||
150 | byte[] chunk1=new byte[(info.data.Length-1000)]; | ||
151 | Array.Copy(info.data,1000,chunk1,0,chunk1.Length); | ||
152 | TransferPacket.TransferData.Data=chunk1; | ||
153 | TransferPacket.TransferData.Status=1; | ||
154 | server.SendPacket(TransferPacket,true,UserInfo); | ||
155 | } | ||
156 | else | ||
157 | { | ||
158 | TransferPacket.TransferData.Status=1; //last packet? so set to 1 | ||
159 | TransferPacket.TransferData.Data=info.data; | ||
160 | server.SendPacket(TransferPacket,true,UserInfo); | ||
161 | } | ||
162 | |||
163 | } | ||
164 | |||
165 | public void CreateNewInventorySet(ref AvatarData Avata,User_Agent_info UserInfo) | ||
166 | { | ||
167 | //Create Folders | ||
168 | LLUUID BaseFolder=Avata.BaseFolder; | ||
169 | InventoryManager.CreateNewFolder(UserInfo,Avata.InventoryFolder); | ||
170 | InventoryManager.CreateNewFolder(UserInfo, BaseFolder); | ||
171 | |||
172 | //Give a copy of default shape | ||
173 | AssetInfo Base=this.Assets[new LLUUID("66c41e39-38f9-f75a-024e-585989bfab73")]; | ||
174 | AssetInfo Shape=this.CloneAsset(UserInfo.AgentID,Base); | ||
175 | |||
176 | Shape.filename=""; | ||
177 | Shape.Name="Default Shape"; | ||
178 | Shape.Description="Default Shape"; | ||
179 | Shape.InvType=18; | ||
180 | Shape.Type=libsecondlife.AssetSystem.Asset.ASSET_TYPE_WEARABLE_BODY; | ||
181 | |||
182 | byte[] Agentid=enc.GetBytes(UserInfo.AgentID.ToStringHyphenated()); | ||
183 | Array.Copy(Agentid,0,Shape.data,294,Agentid.Length); | ||
184 | this.Assets.Add(Shape.Full_ID,Shape); | ||
185 | |||
186 | Avata.Wearables[0].ItemID=InventoryManager.AddToInventory(UserInfo,BaseFolder,Shape); | ||
187 | Avata.Wearables[0].AssetID=Shape.Full_ID; | ||
188 | |||
189 | //Give copy of default skin | ||
190 | Base=this.Assets[new LLUUID("e0ee49b5a4184df8d3c9a65361fe7f49")]; | ||
191 | AssetInfo Skin=this.CloneAsset(UserInfo.AgentID,Base); | ||
192 | |||
193 | Skin.filename=""; | ||
194 | Skin.Name="Default Skin"; | ||
195 | Skin.Description="Default Skin"; | ||
196 | Skin.InvType=18; | ||
197 | Skin.Type=libsecondlife.AssetSystem.Asset.ASSET_TYPE_WEARABLE_BODY; | ||
198 | |||
199 | Array.Copy(Agentid,0,Skin.data,238,Agentid.Length); | ||
200 | this.Assets.Add(Skin.Full_ID,Skin); | ||
201 | |||
202 | Avata.Wearables[1].ItemID=InventoryManager.AddToInventory(UserInfo,BaseFolder,Skin); | ||
203 | Avata.Wearables[1].AssetID=Skin.Full_ID; | ||
204 | |||
205 | //give a copy of test texture | ||
206 | TextureImage Texture=this.CloneImage(UserInfo.AgentID,Textures[new LLUUID("00000000-0000-0000-5005-000000000005")]); | ||
207 | this.Textures.Add(Texture.Full_ID,Texture); | ||
208 | InventoryManager.AddToInventory(UserInfo,BaseFolder,Texture); | ||
209 | |||
210 | } | ||
211 | |||
212 | |||
213 | private void LoadAsset(AssetInfo info) | ||
214 | { | ||
215 | //should request Asset from storage manager | ||
216 | //but for now read from file | ||
217 | |||
218 | string data_path = System.AppDomain.CurrentDomain.BaseDirectory + @"\assets\"; | ||
219 | string filename=data_path+@info.filename; | ||
220 | FileInfo fInfo = new FileInfo(filename); | ||
221 | |||
222 | long numBytes = fInfo.Length; | ||
223 | |||
224 | FileStream fStream = new FileStream(filename, FileMode.Open, FileAccess.Read); | ||
225 | byte[] idata=new byte[numBytes]; | ||
226 | BinaryReader br = new BinaryReader(fStream); | ||
227 | idata= br.ReadBytes((int)numBytes); | ||
228 | br.Close(); | ||
229 | fStream.Close(); | ||
230 | info.data=idata; | ||
231 | info.loaded=true; | ||
232 | } | ||
233 | |||
234 | public AssetInfo CloneAsset(LLUUID NewOwner, AssetInfo SourceAsset) | ||
235 | { | ||
236 | AssetInfo NewAsset=new AssetInfo(); | ||
237 | NewAsset.data=new byte[SourceAsset.data.Length]; | ||
238 | Array.Copy(SourceAsset.data,NewAsset.data,SourceAsset.data.Length); | ||
239 | NewAsset.Full_ID=LLUUID.Random(); | ||
240 | NewAsset.Type=SourceAsset.Type; | ||
241 | NewAsset.InvType=SourceAsset.InvType; | ||
242 | return(NewAsset); | ||
243 | } | ||
244 | #endregion | ||
245 | |||
246 | #region TextureRegion | ||
247 | public void AddTextureRequest(User_Agent_info user, LLUUID image_id) | ||
248 | { | ||
249 | |||
250 | if(!this.Textures.ContainsKey(image_id)) | ||
251 | { | ||
252 | //not found image so send back image not in data base message | ||
253 | ImageNotInDatabasePacket im_not=new ImageNotInDatabasePacket(); | ||
254 | im_not.ImageID.ID=image_id; | ||
255 | server.SendPacket(im_not,true,user); | ||
256 | return; | ||
257 | } | ||
258 | TextureImage imag=this.Textures[image_id]; | ||
259 | TextureRequest req=new TextureRequest(); | ||
260 | req.RequestUser=user; | ||
261 | req.RequestImage=image_id; | ||
262 | req.image_info=imag; | ||
263 | |||
264 | if(imag.data.LongLength>1000) //should be bigger or smaller? | ||
265 | { | ||
266 | //over 1000 bytes so split up file | ||
267 | req.num_packets=(int)imag.data.LongLength/1000; | ||
268 | req.num_packets++; | ||
269 | } | ||
270 | else | ||
271 | { | ||
272 | req.num_packets=1; | ||
273 | } | ||
274 | |||
275 | this.TextureRequests.Add(req); | ||
276 | |||
277 | } | ||
278 | |||
279 | public void AddTexture(LLUUID image_id, string name, byte[] data) | ||
280 | { | ||
281 | |||
282 | } | ||
283 | public void DoWork(ulong time) | ||
284 | { | ||
285 | if(this.TextureRequests.Count==0) | ||
286 | { | ||
287 | //no requests waiting | ||
288 | return; | ||
289 | } | ||
290 | int num; | ||
291 | //should be running in its own thread but for now is called by timer | ||
292 | if(this.TextureRequests.Count<5) | ||
293 | { | ||
294 | //lower than 5 so do all of them | ||
295 | num=this.TextureRequests.Count; | ||
296 | } | ||
297 | else | ||
298 | { | ||
299 | num=5; | ||
300 | } | ||
301 | TextureRequest req; | ||
302 | for(int i=0; i<num; i++) | ||
303 | { | ||
304 | req=(TextureRequest)this.TextureRequests[i]; | ||
305 | |||
306 | if(req.packet_counter==0) | ||
307 | { | ||
308 | //first time for this request so send imagedata packet | ||
309 | if(req.num_packets==1) | ||
310 | { | ||
311 | //only one packet so send whole file | ||
312 | ImageDataPacket im=new ImageDataPacket(); | ||
313 | im.ImageID.Packets=1; | ||
314 | im.ImageID.ID=req.image_info.Full_ID; | ||
315 | im.ImageID.Size=(uint)req.image_info.data.Length; | ||
316 | im.ImageData.Data=req.image_info.data; | ||
317 | im.ImageID.Codec=2; | ||
318 | server.SendPacket(im,true,req.RequestUser); | ||
319 | req.packet_counter++; | ||
320 | req.image_info.last_used=time; | ||
321 | System.Console.WriteLine("sent texture: "+req.image_info.Full_ID); | ||
322 | } | ||
323 | else | ||
324 | { | ||
325 | //more than one packet so split file up | ||
326 | } | ||
327 | } | ||
328 | else | ||
329 | { | ||
330 | //send imagepacket | ||
331 | |||
332 | } | ||
333 | } | ||
334 | |||
335 | //remove requests that have been completed | ||
336 | for(int i=0; i<num; i++) | ||
337 | { | ||
338 | req=(TextureRequest)this.TextureRequests[i]; | ||
339 | if(req.packet_counter==req.num_packets) | ||
340 | { | ||
341 | this.TextureRequests.Remove(req); | ||
342 | } | ||
343 | } | ||
344 | } | ||
345 | |||
346 | public void RecieveTexture(Packet pack) | ||
347 | { | ||
348 | |||
349 | } | ||
350 | |||
351 | private void LoadImage(TextureImage im) | ||
352 | { | ||
353 | //should request Image from StorageManager | ||
354 | //but for now read from file | ||
355 | |||
356 | string data_path=System.AppDomain.CurrentDomain.BaseDirectory + @"\textures\"; | ||
357 | string filename=data_path+@im.filename; | ||
358 | FileInfo fInfo = new FileInfo(filename); | ||
359 | |||
360 | long numBytes = fInfo.Length; | ||
361 | |||
362 | FileStream fStream = new FileStream(filename, FileMode.Open, FileAccess.Read); | ||
363 | byte[] idata=new byte[numBytes]; | ||
364 | BinaryReader br = new BinaryReader(fStream); | ||
365 | idata= br.ReadBytes((int)numBytes); | ||
366 | br.Close(); | ||
367 | fStream.Close(); | ||
368 | im.data=idata; | ||
369 | im.loaded=true; | ||
370 | } | ||
371 | |||
372 | public TextureImage CloneImage(LLUUID NewOwner,TextureImage Source) | ||
373 | { | ||
374 | TextureImage NewImage=new TextureImage(); | ||
375 | NewImage.data=new byte[Source.data.Length]; | ||
376 | Array.Copy(Source.data,NewImage.data,Source.data.Length); | ||
377 | NewImage.filename=Source.filename; | ||
378 | NewImage.Full_ID=LLUUID.Random(); | ||
379 | NewImage.Name=Source.Name; | ||
380 | return(NewImage); | ||
381 | } | ||
382 | |||
383 | #endregion | ||
384 | } | ||
385 | |||
386 | public class AssetRequest | ||
387 | { | ||
388 | public User_Agent_info RequestUser; | ||
389 | public LLUUID RequestImage; | ||
390 | public AssetInfo asset_inf; | ||
391 | public long data_pointer=0; | ||
392 | public int num_packets=0; | ||
393 | public int packet_counter=0; | ||
394 | |||
395 | public AssetRequest() | ||
396 | { | ||
397 | |||
398 | } | ||
399 | } | ||
400 | public class AssetInfo:AssetBase | ||
401 | { | ||
402 | //public byte[] data; | ||
403 | //public LLUUID Full_ID; | ||
404 | public string filename; | ||
405 | public bool loaded; | ||
406 | public ulong last_used; //need to add a tick/time counter and keep record | ||
407 | // of how often images are requested to unload unused ones. | ||
408 | |||
409 | public AssetInfo() | ||
410 | { | ||
411 | |||
412 | } | ||
413 | } | ||
414 | |||
415 | public class AssetBase | ||
416 | { | ||
417 | public byte[] data; | ||
418 | public LLUUID Full_ID; | ||
419 | public sbyte Type; | ||
420 | public sbyte InvType; | ||
421 | public string Name; | ||
422 | public string Description; | ||
423 | |||
424 | public AssetBase() | ||
425 | { | ||
426 | |||
427 | } | ||
428 | } | ||
429 | public class TextureRequest | ||
430 | { | ||
431 | public User_Agent_info RequestUser; | ||
432 | public LLUUID RequestImage; | ||
433 | public TextureImage image_info; | ||
434 | public long data_pointer=0; | ||
435 | public int num_packets=0; | ||
436 | public int packet_counter=0; | ||
437 | |||
438 | public TextureRequest() | ||
439 | { | ||
440 | |||
441 | } | ||
442 | } | ||
443 | public class TextureImage: AssetBase | ||
444 | { | ||
445 | //public byte[] data; | ||
446 | //public LLUUID Full_ID; | ||
447 | //public string name; | ||
448 | public string filename; | ||
449 | public bool loaded; | ||
450 | public ulong last_used; //need to add a tick/time counter and keep record | ||
451 | // of how often images are requested to unload unused ones. | ||
452 | |||
453 | public TextureImage() | ||
454 | { | ||
455 | |||
456 | } | ||
457 | } | ||
458 | |||
459 | |||
460 | } | ||