aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Caches/AssetCache.cs
diff options
context:
space:
mode:
authorSean Dague2007-07-16 15:40:11 +0000
committerSean Dague2007-07-16 15:40:11 +0000
commit2a3c79df83e800d5dfe75a1a3b140ed81da2b1d6 (patch)
treee3f80ad51736cf17e856547b1bcf956010927434 /OpenSim/Region/Caches/AssetCache.cs
parent*Trunk compiles now (diff)
downloadopensim-SC-2a3c79df83e800d5dfe75a1a3b140ed81da2b1d6.zip
opensim-SC-2a3c79df83e800d5dfe75a1a3b140ed81da2b1d6.tar.gz
opensim-SC-2a3c79df83e800d5dfe75a1a3b140ed81da2b1d6.tar.bz2
opensim-SC-2a3c79df83e800d5dfe75a1a3b140ed81da2b1d6.tar.xz
changed to native line ending encoding
Diffstat (limited to 'OpenSim/Region/Caches/AssetCache.cs')
-rw-r--r--OpenSim/Region/Caches/AssetCache.cs1338
1 files changed, 669 insertions, 669 deletions
diff --git a/OpenSim/Region/Caches/AssetCache.cs b/OpenSim/Region/Caches/AssetCache.cs
index 453edbe..8deb0a1 100644
--- a/OpenSim/Region/Caches/AssetCache.cs
+++ b/OpenSim/Region/Caches/AssetCache.cs
@@ -1,669 +1,669 @@
1/* 1/*
2* Copyright (c) Contributors, http://www.openmetaverse.org/ 2* Copyright (c) Contributors, http://www.openmetaverse.org/
3* See CONTRIBUTORS.TXT for a full list of copyright holders. 3* See CONTRIBUTORS.TXT for a full list of copyright holders.
4* 4*
5* Redistribution and use in source and binary forms, with or without 5* Redistribution and use in source and binary forms, with or without
6* modification, are permitted provided that the following conditions are met: 6* modification, are permitted provided that the following conditions are met:
7* * Redistributions of source code must retain the above copyright 7* * Redistributions of source code must retain the above copyright
8* notice, this list of conditions and the following disclaimer. 8* notice, this list of conditions and the following disclaimer.
9* * Redistributions in binary form must reproduce the above copyright 9* * Redistributions in binary form must reproduce the above copyright
10* notice, this list of conditions and the following disclaimer in the 10* notice, this list of conditions and the following disclaimer in the
11* documentation and/or other materials provided with the distribution. 11* documentation and/or other materials provided with the distribution.
12* * Neither the name of the OpenSim Project nor the 12* * Neither the name of the OpenSim Project nor the
13* names of its contributors may be used to endorse or promote products 13* names of its contributors may be used to endorse or promote products
14* derived from this software without specific prior written permission. 14* derived from this software without specific prior written permission.
15* 15*
16* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS AND ANY 16* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS AND ANY
17* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY 19* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 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 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 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 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. 25* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26* 26*
27*/ 27*/
28 28
29using System; 29using System;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using System.Reflection; 31using System.Reflection;
32using System.Threading; 32using System.Threading;
33using libsecondlife; 33using libsecondlife;
34using libsecondlife.Packets; 34using libsecondlife.Packets;
35using OpenSim.Framework.Interfaces; 35using OpenSim.Framework.Interfaces;
36using OpenSim.Framework.Types; 36using OpenSim.Framework.Types;
37 37
38namespace OpenSim.Region.Caches 38namespace OpenSim.Region.Caches
39{ 39{
40 public delegate void DownloadComplete(AssetCache.TextureSender sender); 40 public delegate void DownloadComplete(AssetCache.TextureSender sender);
41 41
42 /// <summary> 42 /// <summary>
43 /// Manages local cache of assets and their sending to viewers. 43 /// Manages local cache of assets and their sending to viewers.
44 /// </summary> 44 /// </summary>
45 public class AssetCache : IAssetReceiver 45 public class AssetCache : IAssetReceiver
46 { 46 {
47 public Dictionary<LLUUID, AssetInfo> Assets; 47 public Dictionary<LLUUID, AssetInfo> Assets;
48 public Dictionary<LLUUID, TextureImage> Textures; 48 public Dictionary<LLUUID, TextureImage> Textures;
49 49
50 public List<AssetRequest> AssetRequests = new List<AssetRequest>(); //assets ready to be sent to viewers 50 public List<AssetRequest> AssetRequests = new List<AssetRequest>(); //assets ready to be sent to viewers
51 public List<AssetRequest> TextureRequests = new List<AssetRequest>(); //textures ready to be sent 51 public List<AssetRequest> TextureRequests = new List<AssetRequest>(); //textures ready to be sent
52 52
53 public Dictionary<LLUUID, AssetRequest> RequestedAssets = new Dictionary<LLUUID, AssetRequest>(); //Assets requested from the asset server 53 public Dictionary<LLUUID, AssetRequest> RequestedAssets = new Dictionary<LLUUID, AssetRequest>(); //Assets requested from the asset server
54 public Dictionary<LLUUID, AssetRequest> RequestedTextures = new Dictionary<LLUUID, AssetRequest>(); //Textures requested from the asset server 54 public Dictionary<LLUUID, AssetRequest> RequestedTextures = new Dictionary<LLUUID, AssetRequest>(); //Textures requested from the asset server
55 55
56 public Dictionary<LLUUID, TextureSender> SendingTextures = new Dictionary<LLUUID, TextureSender>(); 56 public Dictionary<LLUUID, TextureSender> SendingTextures = new Dictionary<LLUUID, TextureSender>();
57 private IAssetServer _assetServer; 57 private IAssetServer _assetServer;
58 private Thread _assetCacheThread; 58 private Thread _assetCacheThread;
59 private LLUUID[] textureList = new LLUUID[5]; 59 private LLUUID[] textureList = new LLUUID[5];
60 60
61 /// <summary> 61 /// <summary>
62 /// 62 ///
63 /// </summary> 63 /// </summary>
64 public AssetCache(IAssetServer assetServer) 64 public AssetCache(IAssetServer assetServer)
65 { 65 {
66 Console.WriteLine("Creating Asset cache"); 66 Console.WriteLine("Creating Asset cache");
67 _assetServer = assetServer; 67 _assetServer = assetServer;
68 _assetServer.SetReceiver(this); 68 _assetServer.SetReceiver(this);
69 Assets = new Dictionary<LLUUID, AssetInfo>(); 69 Assets = new Dictionary<LLUUID, AssetInfo>();
70 Textures = new Dictionary<LLUUID, TextureImage>(); 70 Textures = new Dictionary<LLUUID, TextureImage>();
71 this._assetCacheThread = new Thread(new ThreadStart(RunAssetManager)); 71 this._assetCacheThread = new Thread(new ThreadStart(RunAssetManager));
72 this._assetCacheThread.IsBackground = true; 72 this._assetCacheThread.IsBackground = true;
73 this._assetCacheThread.Start(); 73 this._assetCacheThread.Start();
74 74
75 } 75 }
76 76
77 public AssetCache(string assetServerDLLName, string assetServerURL, string assetServerKey) 77 public AssetCache(string assetServerDLLName, string assetServerURL, string assetServerKey)
78 { 78 {
79 Console.WriteLine("Creating Asset cache"); 79 Console.WriteLine("Creating Asset cache");
80 _assetServer = this.LoadAssetDll(assetServerDLLName); 80 _assetServer = this.LoadAssetDll(assetServerDLLName);
81 _assetServer.SetServerInfo(assetServerURL, assetServerKey); 81 _assetServer.SetServerInfo(assetServerURL, assetServerKey);
82 _assetServer.SetReceiver(this); 82 _assetServer.SetReceiver(this);
83 Assets = new Dictionary<LLUUID, AssetInfo>(); 83 Assets = new Dictionary<LLUUID, AssetInfo>();
84 Textures = new Dictionary<LLUUID, TextureImage>(); 84 Textures = new Dictionary<LLUUID, TextureImage>();
85 this._assetCacheThread = new Thread(new ThreadStart(RunAssetManager)); 85 this._assetCacheThread = new Thread(new ThreadStart(RunAssetManager));
86 this._assetCacheThread.IsBackground = true; 86 this._assetCacheThread.IsBackground = true;
87 this._assetCacheThread.Start(); 87 this._assetCacheThread.Start();
88 88
89 } 89 }
90 90
91 /// <summary> 91 /// <summary>
92 /// 92 ///
93 /// </summary> 93 /// </summary>
94 public void RunAssetManager() 94 public void RunAssetManager()
95 { 95 {
96 while (true) 96 while (true)
97 { 97 {
98 try 98 try
99 { 99 {
100 //Console.WriteLine("Asset cache loop"); 100 //Console.WriteLine("Asset cache loop");
101 this.ProcessAssetQueue(); 101 this.ProcessAssetQueue();
102 this.ProcessTextureQueue(); 102 this.ProcessTextureQueue();
103 Thread.Sleep(500); 103 Thread.Sleep(500);
104 } 104 }
105 catch (Exception e) 105 catch (Exception e)
106 { 106 {
107 Console.WriteLine(e.Message); 107 Console.WriteLine(e.Message);
108 } 108 }
109 } 109 }
110 } 110 }
111 111
112 public void LoadDefaultTextureSet() 112 public void LoadDefaultTextureSet()
113 { 113 {
114 //hack: so we can give each user a set of textures 114 //hack: so we can give each user a set of textures
115 textureList[0] = new LLUUID("00000000-0000-0000-9999-000000000001"); 115 textureList[0] = new LLUUID("00000000-0000-0000-9999-000000000001");
116 textureList[1] = new LLUUID("00000000-0000-0000-9999-000000000002"); 116 textureList[1] = new LLUUID("00000000-0000-0000-9999-000000000002");
117 textureList[2] = new LLUUID("00000000-0000-0000-9999-000000000003"); 117 textureList[2] = new LLUUID("00000000-0000-0000-9999-000000000003");
118 textureList[3] = new LLUUID("00000000-0000-0000-9999-000000000004"); 118 textureList[3] = new LLUUID("00000000-0000-0000-9999-000000000004");
119 textureList[4] = new LLUUID("00000000-0000-0000-9999-000000000005"); 119 textureList[4] = new LLUUID("00000000-0000-0000-9999-000000000005");
120 120
121 for (int i = 0; i < textureList.Length; i++) 121 for (int i = 0; i < textureList.Length; i++)
122 { 122 {
123 this._assetServer.RequestAsset(textureList[i], true); 123 this._assetServer.RequestAsset(textureList[i], true);
124 } 124 }
125 125
126 } 126 }
127 127
128 public AssetBase[] CreateNewInventorySet(LLUUID agentID) 128 public AssetBase[] CreateNewInventorySet(LLUUID agentID)
129 { 129 {
130 AssetBase[] inventorySet = new AssetBase[this.textureList.Length]; 130 AssetBase[] inventorySet = new AssetBase[this.textureList.Length];
131 for (int i = 0; i < textureList.Length; i++) 131 for (int i = 0; i < textureList.Length; i++)
132 { 132 {
133 if (this.Textures.ContainsKey(textureList[i])) 133 if (this.Textures.ContainsKey(textureList[i]))
134 { 134 {
135 inventorySet[i] = this.CloneImage(agentID, this.Textures[textureList[i]]); 135 inventorySet[i] = this.CloneImage(agentID, this.Textures[textureList[i]]);
136 TextureImage image = new TextureImage(inventorySet[i]); 136 TextureImage image = new TextureImage(inventorySet[i]);
137 this.Textures.Add(image.FullID, image); 137 this.Textures.Add(image.FullID, image);
138 this._assetServer.UploadNewAsset(image); //save the asset to the asset server 138 this._assetServer.UploadNewAsset(image); //save the asset to the asset server
139 } 139 }
140 } 140 }
141 return inventorySet; 141 return inventorySet;
142 } 142 }
143 143
144 public AssetBase GetAsset(LLUUID assetID) 144 public AssetBase GetAsset(LLUUID assetID)
145 { 145 {
146 AssetBase asset = null; 146 AssetBase asset = null;
147 if (this.Textures.ContainsKey(assetID)) 147 if (this.Textures.ContainsKey(assetID))
148 { 148 {
149 asset = this.Textures[assetID]; 149 asset = this.Textures[assetID];
150 } 150 }
151 else if (this.Assets.ContainsKey(assetID)) 151 else if (this.Assets.ContainsKey(assetID))
152 { 152 {
153 asset = this.Assets[assetID]; 153 asset = this.Assets[assetID];
154 } 154 }
155 return asset; 155 return asset;
156 } 156 }
157 157
158 public void AddAsset(AssetBase asset) 158 public void AddAsset(AssetBase asset)
159 { 159 {
160 // Console.WriteLine("adding asset " + asset.FullID.ToStringHyphenated()); 160 // Console.WriteLine("adding asset " + asset.FullID.ToStringHyphenated());
161 if (asset.Type == 0) 161 if (asset.Type == 0)
162 { 162 {
163 //Console.WriteLine("which is a texture"); 163 //Console.WriteLine("which is a texture");
164 if (!this.Textures.ContainsKey(asset.FullID)) 164 if (!this.Textures.ContainsKey(asset.FullID))
165 { //texture 165 { //texture
166 TextureImage textur = new TextureImage(asset); 166 TextureImage textur = new TextureImage(asset);
167 this.Textures.Add(textur.FullID, textur); 167 this.Textures.Add(textur.FullID, textur);
168 this._assetServer.UploadNewAsset(asset); 168 this._assetServer.UploadNewAsset(asset);
169 } 169 }
170 } 170 }
171 else 171 else
172 { 172 {
173 if (!this.Assets.ContainsKey(asset.FullID)) 173 if (!this.Assets.ContainsKey(asset.FullID))
174 { 174 {
175 AssetInfo assetInf = new AssetInfo(asset); 175 AssetInfo assetInf = new AssetInfo(asset);
176 this.Assets.Add(assetInf.FullID, assetInf); 176 this.Assets.Add(assetInf.FullID, assetInf);
177 this._assetServer.UploadNewAsset(asset); 177 this._assetServer.UploadNewAsset(asset);
178 } 178 }
179 } 179 }
180 } 180 }
181 181
182 /// <summary> 182 /// <summary>
183 /// 183 ///
184 /// </summary> 184 /// </summary>
185 private void ProcessTextureQueue() 185 private void ProcessTextureQueue()
186 { 186 {
187 if (this.TextureRequests.Count == 0) 187 if (this.TextureRequests.Count == 0)
188 { 188 {
189 //no requests waiting 189 //no requests waiting
190 return; 190 return;
191 } 191 }
192 int num; 192 int num;
193 num = this.TextureRequests.Count; 193 num = this.TextureRequests.Count;
194 194
195 AssetRequest req; 195 AssetRequest req;
196 for (int i = 0; i < num; i++) 196 for (int i = 0; i < num; i++)
197 { 197 {
198 req = (AssetRequest)this.TextureRequests[i]; 198 req = (AssetRequest)this.TextureRequests[i];
199 if (!this.SendingTextures.ContainsKey(req.ImageInfo.FullID)) 199 if (!this.SendingTextures.ContainsKey(req.ImageInfo.FullID))
200 { 200 {
201 TextureSender sender = new TextureSender(req); 201 TextureSender sender = new TextureSender(req);
202 sender.OnComplete += this.TextureSent; 202 sender.OnComplete += this.TextureSent;
203 lock (this.SendingTextures) 203 lock (this.SendingTextures)
204 { 204 {
205 this.SendingTextures.Add(req.ImageInfo.FullID, sender); 205 this.SendingTextures.Add(req.ImageInfo.FullID, sender);
206 } 206 }
207 } 207 }
208 208
209 } 209 }
210 210
211 this.TextureRequests.Clear(); 211 this.TextureRequests.Clear();
212 } 212 }
213 213
214 /// <summary> 214 /// <summary>
215 /// Event handler, called by a TextureSender object to say that texture has been sent 215 /// Event handler, called by a TextureSender object to say that texture has been sent
216 /// </summary> 216 /// </summary>
217 /// <param name="sender"></param> 217 /// <param name="sender"></param>
218 public void TextureSent(TextureSender sender) 218 public void TextureSent(TextureSender sender)
219 { 219 {
220 if (this.SendingTextures.ContainsKey(sender.request.ImageInfo.FullID)) 220 if (this.SendingTextures.ContainsKey(sender.request.ImageInfo.FullID))
221 { 221 {
222 lock (this.SendingTextures) 222 lock (this.SendingTextures)
223 { 223 {
224 this.SendingTextures.Remove(sender.request.ImageInfo.FullID); 224 this.SendingTextures.Remove(sender.request.ImageInfo.FullID);
225 } 225 }
226 } 226 }
227 } 227 }
228 228
229 public void AssetReceived(AssetBase asset, bool IsTexture) 229 public void AssetReceived(AssetBase asset, bool IsTexture)
230 { 230 {
231 if (asset.FullID != LLUUID.Zero) // if it is set to zero then the asset wasn't found by the server 231 if (asset.FullID != LLUUID.Zero) // if it is set to zero then the asset wasn't found by the server
232 { 232 {
233 //check if it is a texture or not 233 //check if it is a texture or not
234 //then add to the correct cache list 234 //then add to the correct cache list
235 //then check for waiting requests for this asset/texture (in the Requested lists) 235 //then check for waiting requests for this asset/texture (in the Requested lists)
236 //and move those requests into the Requests list. 236 //and move those requests into the Requests list.
237 if (IsTexture) 237 if (IsTexture)
238 { 238 {
239 TextureImage image = new TextureImage(asset); 239 TextureImage image = new TextureImage(asset);
240 this.Textures.Add(image.FullID, image); 240 this.Textures.Add(image.FullID, image);
241 if (this.RequestedTextures.ContainsKey(image.FullID)) 241 if (this.RequestedTextures.ContainsKey(image.FullID))
242 { 242 {
243 AssetRequest req = this.RequestedTextures[image.FullID]; 243 AssetRequest req = this.RequestedTextures[image.FullID];
244 req.ImageInfo = image; 244 req.ImageInfo = image;
245 if (image.Data.LongLength > 600) 245 if (image.Data.LongLength > 600)
246 { 246 {
247 //over 600 bytes so split up file 247 //over 600 bytes so split up file
248 req.NumPackets = 1 + (int)(image.Data.Length - 600 + 999) / 1000; 248 req.NumPackets = 1 + (int)(image.Data.Length - 600 + 999) / 1000;
249 } 249 }
250 else 250 else
251 { 251 {
252 req.NumPackets = 1; 252 req.NumPackets = 1;
253 } 253 }
254 this.RequestedTextures.Remove(image.FullID); 254 this.RequestedTextures.Remove(image.FullID);
255 this.TextureRequests.Add(req); 255 this.TextureRequests.Add(req);
256 } 256 }
257 } 257 }
258 else 258 else
259 { 259 {
260 AssetInfo assetInf = new AssetInfo(asset); 260 AssetInfo assetInf = new AssetInfo(asset);
261 this.Assets.Add(assetInf.FullID, assetInf); 261 this.Assets.Add(assetInf.FullID, assetInf);
262 if (this.RequestedAssets.ContainsKey(assetInf.FullID)) 262 if (this.RequestedAssets.ContainsKey(assetInf.FullID))
263 { 263 {
264 AssetRequest req = this.RequestedAssets[assetInf.FullID]; 264 AssetRequest req = this.RequestedAssets[assetInf.FullID];
265 req.AssetInf = assetInf; 265 req.AssetInf = assetInf;
266 if (assetInf.Data.LongLength > 600) 266 if (assetInf.Data.LongLength > 600)
267 { 267 {
268 //over 600 bytes so split up file 268 //over 600 bytes so split up file
269 req.NumPackets = 1 + (int)(assetInf.Data.Length - 600 + 999) / 1000; 269 req.NumPackets = 1 + (int)(assetInf.Data.Length - 600 + 999) / 1000;
270 } 270 }
271 else 271 else
272 { 272 {
273 req.NumPackets = 1; 273 req.NumPackets = 1;
274 } 274 }
275 this.RequestedAssets.Remove(assetInf.FullID); 275 this.RequestedAssets.Remove(assetInf.FullID);
276 this.AssetRequests.Add(req); 276 this.AssetRequests.Add(req);
277 } 277 }
278 } 278 }
279 } 279 }
280 } 280 }
281 281
282 public void AssetNotFound(AssetBase asset) 282 public void AssetNotFound(AssetBase asset)
283 { 283 {
284 //the asset server had no knowledge of requested asset 284 //the asset server had no knowledge of requested asset
285 285
286 } 286 }
287 287
288 #region Assets 288 #region Assets
289 /// <summary> 289 /// <summary>
290 /// 290 ///
291 /// </summary> 291 /// </summary>
292 /// <param name="userInfo"></param> 292 /// <param name="userInfo"></param>
293 /// <param name="transferRequest"></param> 293 /// <param name="transferRequest"></param>
294 public void AddAssetRequest(IClientAPI userInfo, TransferRequestPacket transferRequest) 294 public void AddAssetRequest(IClientAPI userInfo, TransferRequestPacket transferRequest)
295 { 295 {
296 LLUUID requestID = new LLUUID(transferRequest.TransferInfo.Params, 0); 296 LLUUID requestID = new LLUUID(transferRequest.TransferInfo.Params, 0);
297 //check to see if asset is in local cache, if not we need to request it from asset server. 297 //check to see if asset is in local cache, if not we need to request it from asset server.
298 298
299 if (!this.Assets.ContainsKey(requestID)) 299 if (!this.Assets.ContainsKey(requestID))
300 { 300 {
301 //not found asset 301 //not found asset
302 // so request from asset server 302 // so request from asset server
303 if (!this.RequestedAssets.ContainsKey(requestID)) 303 if (!this.RequestedAssets.ContainsKey(requestID))
304 { 304 {
305 AssetRequest request = new AssetRequest(); 305 AssetRequest request = new AssetRequest();
306 request.RequestUser = userInfo; 306 request.RequestUser = userInfo;
307 request.RequestAssetID = requestID; 307 request.RequestAssetID = requestID;
308 request.TransferRequestID = transferRequest.TransferInfo.TransferID; 308 request.TransferRequestID = transferRequest.TransferInfo.TransferID;
309 this.RequestedAssets.Add(requestID, request); 309 this.RequestedAssets.Add(requestID, request);
310 this._assetServer.RequestAsset(requestID, false); 310 this._assetServer.RequestAsset(requestID, false);
311 } 311 }
312 return; 312 return;
313 } 313 }
314 //it is in our cache 314 //it is in our cache
315 AssetInfo asset = this.Assets[requestID]; 315 AssetInfo asset = this.Assets[requestID];
316 316
317 //work out how many packets it should be sent in 317 //work out how many packets it should be sent in
318 // and add to the AssetRequests list 318 // and add to the AssetRequests list
319 AssetRequest req = new AssetRequest(); 319 AssetRequest req = new AssetRequest();
320 req.RequestUser = userInfo; 320 req.RequestUser = userInfo;
321 req.RequestAssetID = requestID; 321 req.RequestAssetID = requestID;
322 req.TransferRequestID = transferRequest.TransferInfo.TransferID; 322 req.TransferRequestID = transferRequest.TransferInfo.TransferID;
323 req.AssetInf = asset; 323 req.AssetInf = asset;
324 324
325 if (asset.Data.LongLength > 600) 325 if (asset.Data.LongLength > 600)
326 { 326 {
327 //over 600 bytes so split up file 327 //over 600 bytes so split up file
328 req.NumPackets = 1 + (int)(asset.Data.Length - 600 + 999) / 1000; 328 req.NumPackets = 1 + (int)(asset.Data.Length - 600 + 999) / 1000;
329 } 329 }
330 else 330 else
331 { 331 {
332 req.NumPackets = 1; 332 req.NumPackets = 1;
333 } 333 }
334 334
335 this.AssetRequests.Add(req); 335 this.AssetRequests.Add(req);
336 } 336 }
337 337
338 /// <summary> 338 /// <summary>
339 /// 339 ///
340 /// </summary> 340 /// </summary>
341 private void ProcessAssetQueue() 341 private void ProcessAssetQueue()
342 { 342 {
343 if (this.AssetRequests.Count == 0) 343 if (this.AssetRequests.Count == 0)
344 { 344 {
345 //no requests waiting 345 //no requests waiting
346 return; 346 return;
347 } 347 }
348 int num; 348 int num;
349 349
350 if (this.AssetRequests.Count < 5) 350 if (this.AssetRequests.Count < 5)
351 { 351 {
352 //lower than 5 so do all of them 352 //lower than 5 so do all of them
353 num = this.AssetRequests.Count; 353 num = this.AssetRequests.Count;
354 } 354 }
355 else 355 else
356 { 356 {
357 num = 5; 357 num = 5;
358 } 358 }
359 AssetRequest req; 359 AssetRequest req;
360 for (int i = 0; i < num; i++) 360 for (int i = 0; i < num; i++)
361 { 361 {
362 req = (AssetRequest)this.AssetRequests[i]; 362 req = (AssetRequest)this.AssetRequests[i];
363 363
364 TransferInfoPacket Transfer = new TransferInfoPacket(); 364 TransferInfoPacket Transfer = new TransferInfoPacket();
365 Transfer.TransferInfo.ChannelType = 2; 365 Transfer.TransferInfo.ChannelType = 2;
366 Transfer.TransferInfo.Status = 0; 366 Transfer.TransferInfo.Status = 0;
367 Transfer.TransferInfo.TargetType = 0; 367 Transfer.TransferInfo.TargetType = 0;
368 Transfer.TransferInfo.Params = req.RequestAssetID.GetBytes(); 368 Transfer.TransferInfo.Params = req.RequestAssetID.GetBytes();
369 Transfer.TransferInfo.Size = (int)req.AssetInf.Data.Length; 369 Transfer.TransferInfo.Size = (int)req.AssetInf.Data.Length;
370 Transfer.TransferInfo.TransferID = req.TransferRequestID; 370 Transfer.TransferInfo.TransferID = req.TransferRequestID;
371 req.RequestUser.OutPacket(Transfer); 371 req.RequestUser.OutPacket(Transfer);
372 372
373 if (req.NumPackets == 1) 373 if (req.NumPackets == 1)
374 { 374 {
375 TransferPacketPacket TransferPacket = new TransferPacketPacket(); 375 TransferPacketPacket TransferPacket = new TransferPacketPacket();
376 TransferPacket.TransferData.Packet = 0; 376 TransferPacket.TransferData.Packet = 0;
377 TransferPacket.TransferData.ChannelType = 2; 377 TransferPacket.TransferData.ChannelType = 2;
378 TransferPacket.TransferData.TransferID = req.TransferRequestID; 378 TransferPacket.TransferData.TransferID = req.TransferRequestID;
379 TransferPacket.TransferData.Data = req.AssetInf.Data; 379 TransferPacket.TransferData.Data = req.AssetInf.Data;
380 TransferPacket.TransferData.Status = 1; 380 TransferPacket.TransferData.Status = 1;
381 req.RequestUser.OutPacket(TransferPacket); 381 req.RequestUser.OutPacket(TransferPacket);
382 } 382 }
383 else 383 else
384 { 384 {
385 //more than one packet so split file up , for now it can't be bigger than 2000 bytes 385 //more than one packet so split file up , for now it can't be bigger than 2000 bytes
386 TransferPacketPacket TransferPacket = new TransferPacketPacket(); 386 TransferPacketPacket TransferPacket = new TransferPacketPacket();
387 TransferPacket.TransferData.Packet = 0; 387 TransferPacket.TransferData.Packet = 0;
388 TransferPacket.TransferData.ChannelType = 2; 388 TransferPacket.TransferData.ChannelType = 2;
389 TransferPacket.TransferData.TransferID = req.TransferRequestID; 389 TransferPacket.TransferData.TransferID = req.TransferRequestID;
390 byte[] chunk = new byte[1000]; 390 byte[] chunk = new byte[1000];
391 Array.Copy(req.AssetInf.Data, chunk, 1000); 391 Array.Copy(req.AssetInf.Data, chunk, 1000);
392 TransferPacket.TransferData.Data = chunk; 392 TransferPacket.TransferData.Data = chunk;
393 TransferPacket.TransferData.Status = 0; 393 TransferPacket.TransferData.Status = 0;
394 req.RequestUser.OutPacket(TransferPacket); 394 req.RequestUser.OutPacket(TransferPacket);
395 395
396 TransferPacket = new TransferPacketPacket(); 396 TransferPacket = new TransferPacketPacket();
397 TransferPacket.TransferData.Packet = 1; 397 TransferPacket.TransferData.Packet = 1;
398 TransferPacket.TransferData.ChannelType = 2; 398 TransferPacket.TransferData.ChannelType = 2;
399 TransferPacket.TransferData.TransferID = req.TransferRequestID; 399 TransferPacket.TransferData.TransferID = req.TransferRequestID;
400 byte[] chunk1 = new byte[(req.AssetInf.Data.Length - 1000)]; 400 byte[] chunk1 = new byte[(req.AssetInf.Data.Length - 1000)];
401 Array.Copy(req.AssetInf.Data, 1000, chunk1, 0, chunk1.Length); 401 Array.Copy(req.AssetInf.Data, 1000, chunk1, 0, chunk1.Length);
402 TransferPacket.TransferData.Data = chunk1; 402 TransferPacket.TransferData.Data = chunk1;
403 TransferPacket.TransferData.Status = 1; 403 TransferPacket.TransferData.Status = 1;
404 req.RequestUser.OutPacket(TransferPacket); 404 req.RequestUser.OutPacket(TransferPacket);
405 } 405 }
406 406
407 } 407 }
408 408
409 //remove requests that have been completed 409 //remove requests that have been completed
410 for (int i = 0; i < num; i++) 410 for (int i = 0; i < num; i++)
411 { 411 {
412 this.AssetRequests.RemoveAt(0); 412 this.AssetRequests.RemoveAt(0);
413 } 413 }
414 414
415 } 415 }
416 416
417 public AssetInfo CloneAsset(LLUUID newOwner, AssetInfo sourceAsset) 417 public AssetInfo CloneAsset(LLUUID newOwner, AssetInfo sourceAsset)
418 { 418 {
419 AssetInfo newAsset = new AssetInfo(); 419 AssetInfo newAsset = new AssetInfo();
420 newAsset.Data = new byte[sourceAsset.Data.Length]; 420 newAsset.Data = new byte[sourceAsset.Data.Length];
421 Array.Copy(sourceAsset.Data, newAsset.Data, sourceAsset.Data.Length); 421 Array.Copy(sourceAsset.Data, newAsset.Data, sourceAsset.Data.Length);
422 newAsset.FullID = LLUUID.Random(); 422 newAsset.FullID = LLUUID.Random();
423 newAsset.Type = sourceAsset.Type; 423 newAsset.Type = sourceAsset.Type;
424 newAsset.InvType = sourceAsset.InvType; 424 newAsset.InvType = sourceAsset.InvType;
425 return (newAsset); 425 return (newAsset);
426 } 426 }
427 #endregion 427 #endregion
428 428
429 #region Textures 429 #region Textures
430 /// <summary> 430 /// <summary>
431 /// 431 ///
432 /// </summary> 432 /// </summary>
433 /// <param name="userInfo"></param> 433 /// <param name="userInfo"></param>
434 /// <param name="imageID"></param> 434 /// <param name="imageID"></param>
435 public void AddTextureRequest(IClientAPI userInfo, LLUUID imageID) 435 public void AddTextureRequest(IClientAPI userInfo, LLUUID imageID)
436 { 436 {
437 //Console.WriteLine("texture request for " + imageID.ToStringHyphenated()); 437 //Console.WriteLine("texture request for " + imageID.ToStringHyphenated());
438 //check to see if texture is in local cache, if not request from asset server 438 //check to see if texture is in local cache, if not request from asset server
439 if (!this.Textures.ContainsKey(imageID)) 439 if (!this.Textures.ContainsKey(imageID))
440 { 440 {
441 if (!this.RequestedTextures.ContainsKey(imageID)) 441 if (!this.RequestedTextures.ContainsKey(imageID))
442 { 442 {
443 //not is cache so request from asset server 443 //not is cache so request from asset server
444 AssetRequest request = new AssetRequest(); 444 AssetRequest request = new AssetRequest();
445 request.RequestUser = userInfo; 445 request.RequestUser = userInfo;
446 request.RequestAssetID = imageID; 446 request.RequestAssetID = imageID;
447 request.IsTextureRequest = true; 447 request.IsTextureRequest = true;
448 this.RequestedTextures.Add(imageID, request); 448 this.RequestedTextures.Add(imageID, request);
449 this._assetServer.RequestAsset(imageID, true); 449 this._assetServer.RequestAsset(imageID, true);
450 } 450 }
451 return; 451 return;
452 } 452 }
453 453
454 //Console.WriteLine("texture already in cache"); 454 //Console.WriteLine("texture already in cache");
455 TextureImage imag = this.Textures[imageID]; 455 TextureImage imag = this.Textures[imageID];
456 AssetRequest req = new AssetRequest(); 456 AssetRequest req = new AssetRequest();
457 req.RequestUser = userInfo; 457 req.RequestUser = userInfo;
458 req.RequestAssetID = imageID; 458 req.RequestAssetID = imageID;
459 req.IsTextureRequest = true; 459 req.IsTextureRequest = true;
460 req.ImageInfo = imag; 460 req.ImageInfo = imag;
461 461
462 if (imag.Data.LongLength > 600) 462 if (imag.Data.LongLength > 600)
463 { 463 {
464 //over 600 bytes so split up file 464 //over 600 bytes so split up file
465 req.NumPackets = 1 + (int)(imag.Data.Length - 600 + 999) / 1000; 465 req.NumPackets = 1 + (int)(imag.Data.Length - 600 + 999) / 1000;
466 } 466 }
467 else 467 else
468 { 468 {
469 req.NumPackets = 1; 469 req.NumPackets = 1;
470 } 470 }
471 this.TextureRequests.Add(req); 471 this.TextureRequests.Add(req);
472 } 472 }
473 473
474 public TextureImage CloneImage(LLUUID newOwner, TextureImage source) 474 public TextureImage CloneImage(LLUUID newOwner, TextureImage source)
475 { 475 {
476 TextureImage newImage = new TextureImage(); 476 TextureImage newImage = new TextureImage();
477 newImage.Data = new byte[source.Data.Length]; 477 newImage.Data = new byte[source.Data.Length];
478 Array.Copy(source.Data, newImage.Data, source.Data.Length); 478 Array.Copy(source.Data, newImage.Data, source.Data.Length);
479 //newImage.filename = source.filename; 479 //newImage.filename = source.filename;
480 newImage.FullID = LLUUID.Random(); 480 newImage.FullID = LLUUID.Random();
481 newImage.Name = source.Name; 481 newImage.Name = source.Name;
482 return (newImage); 482 return (newImage);
483 } 483 }
484 #endregion 484 #endregion
485 485
486 private IAssetServer LoadAssetDll(string dllName) 486 private IAssetServer LoadAssetDll(string dllName)
487 { 487 {
488 Assembly pluginAssembly = Assembly.LoadFrom(dllName); 488 Assembly pluginAssembly = Assembly.LoadFrom(dllName);
489 IAssetServer server = null; 489 IAssetServer server = null;
490 490
491 foreach (Type pluginType in pluginAssembly.GetTypes()) 491 foreach (Type pluginType in pluginAssembly.GetTypes())
492 { 492 {
493 if (pluginType.IsPublic) 493 if (pluginType.IsPublic)
494 { 494 {
495 if (!pluginType.IsAbstract) 495 if (!pluginType.IsAbstract)
496 { 496 {
497 Type typeInterface = pluginType.GetInterface("IAssetPlugin", true); 497 Type typeInterface = pluginType.GetInterface("IAssetPlugin", true);
498 498
499 if (typeInterface != null) 499 if (typeInterface != null)
500 { 500 {
501 IAssetPlugin plug = (IAssetPlugin)Activator.CreateInstance(pluginAssembly.GetType(pluginType.ToString())); 501 IAssetPlugin plug = (IAssetPlugin)Activator.CreateInstance(pluginAssembly.GetType(pluginType.ToString()));
502 server = plug.GetAssetServer(); 502 server = plug.GetAssetServer();
503 break; 503 break;
504 } 504 }
505 505
506 typeInterface = null; 506 typeInterface = null;
507 } 507 }
508 } 508 }
509 } 509 }
510 pluginAssembly = null; 510 pluginAssembly = null;
511 return server; 511 return server;
512 } 512 }
513 513
514 public class AssetRequest 514 public class AssetRequest
515 { 515 {
516 public IClientAPI RequestUser; 516 public IClientAPI RequestUser;
517 public LLUUID RequestAssetID; 517 public LLUUID RequestAssetID;
518 public AssetInfo AssetInf; 518 public AssetInfo AssetInf;
519 public TextureImage ImageInfo; 519 public TextureImage ImageInfo;
520 public LLUUID TransferRequestID; 520 public LLUUID TransferRequestID;
521 public long DataPointer = 0; 521 public long DataPointer = 0;
522 public int NumPackets = 0; 522 public int NumPackets = 0;
523 public int PacketCounter = 0; 523 public int PacketCounter = 0;
524 public bool IsTextureRequest; 524 public bool IsTextureRequest;
525 //public bool AssetInCache; 525 //public bool AssetInCache;
526 //public int TimeRequested; 526 //public int TimeRequested;
527 527
528 public AssetRequest() 528 public AssetRequest()
529 { 529 {
530 530
531 } 531 }
532 } 532 }
533 533
534 public class AssetInfo : AssetBase 534 public class AssetInfo : AssetBase
535 { 535 {
536 public AssetInfo() 536 public AssetInfo()
537 { 537 {
538 538
539 } 539 }
540 540
541 public AssetInfo(AssetBase aBase) 541 public AssetInfo(AssetBase aBase)
542 { 542 {
543 Data = aBase.Data; 543 Data = aBase.Data;
544 FullID = aBase.FullID; 544 FullID = aBase.FullID;
545 Type = aBase.Type; 545 Type = aBase.Type;
546 InvType = aBase.InvType; 546 InvType = aBase.InvType;
547 Name = aBase.Name; 547 Name = aBase.Name;
548 Description = aBase.Description; 548 Description = aBase.Description;
549 } 549 }
550 } 550 }
551 551
552 public class TextureImage : AssetBase 552 public class TextureImage : AssetBase
553 { 553 {
554 public TextureImage() 554 public TextureImage()
555 { 555 {
556 556
557 } 557 }
558 558
559 public TextureImage(AssetBase aBase) 559 public TextureImage(AssetBase aBase)
560 { 560 {
561 Data = aBase.Data; 561 Data = aBase.Data;
562 FullID = aBase.FullID; 562 FullID = aBase.FullID;
563 Type = aBase.Type; 563 Type = aBase.Type;
564 InvType = aBase.InvType; 564 InvType = aBase.InvType;
565 Name = aBase.Name; 565 Name = aBase.Name;
566 Description = aBase.Description; 566 Description = aBase.Description;
567 } 567 }
568 } 568 }
569 569
570 public class TextureSender 570 public class TextureSender
571 { 571 {
572 public AssetRequest request; 572 public AssetRequest request;
573 public event DownloadComplete OnComplete; 573 public event DownloadComplete OnComplete;
574 Thread m_thread; 574 Thread m_thread;
575 public TextureSender(AssetRequest req) 575 public TextureSender(AssetRequest req)
576 { 576 {
577 request = req; 577 request = req;
578 //Console.WriteLine("creating worker thread for texture " + req.ImageInfo.FullID.ToStringHyphenated()); 578 //Console.WriteLine("creating worker thread for texture " + req.ImageInfo.FullID.ToStringHyphenated());
579 //Console.WriteLine("texture data length is " + req.ImageInfo.Data.Length); 579 //Console.WriteLine("texture data length is " + req.ImageInfo.Data.Length);
580 // Console.WriteLine("in " + req.NumPackets + " packets"); 580 // Console.WriteLine("in " + req.NumPackets + " packets");
581 //ThreadPool.QueueUserWorkItem(new WaitCallback(SendTexture), new object()); 581 //ThreadPool.QueueUserWorkItem(new WaitCallback(SendTexture), new object());
582 582
583 //need some sort of custom threadpool here, as using the .net one, overloads it and stops the handling of incoming packets etc 583 //need some sort of custom threadpool here, as using the .net one, overloads it and stops the handling of incoming packets etc
584 //but don't really want to create a thread for every texture download 584 //but don't really want to create a thread for every texture download
585 m_thread = new Thread(new ThreadStart(SendTexture)); 585 m_thread = new Thread(new ThreadStart(SendTexture));
586 m_thread.IsBackground = true; 586 m_thread.IsBackground = true;
587 m_thread.Start(); 587 m_thread.Start();
588 } 588 }
589 589
590 public void SendTexture() 590 public void SendTexture()
591 { 591 {
592 //Console.WriteLine("starting to send sending texture " + request.ImageInfo.FullID.ToStringHyphenated()); 592 //Console.WriteLine("starting to send sending texture " + request.ImageInfo.FullID.ToStringHyphenated());
593 while (request.PacketCounter != request.NumPackets) 593 while (request.PacketCounter != request.NumPackets)
594 { 594 {
595 SendPacket(); 595 SendPacket();
596 Thread.Sleep(500); 596 Thread.Sleep(500);
597 } 597 }
598 598
599 //Console.WriteLine("finished sending texture " + request.ImageInfo.FullID.ToStringHyphenated()); 599 //Console.WriteLine("finished sending texture " + request.ImageInfo.FullID.ToStringHyphenated());
600 if (OnComplete != null) 600 if (OnComplete != null)
601 { 601 {
602 OnComplete(this); 602 OnComplete(this);
603 } 603 }
604 } 604 }
605 605
606 public void SendPacket() 606 public void SendPacket()
607 { 607 {
608 AssetRequest req = request; 608 AssetRequest req = request;
609 // Console.WriteLine("sending " + req.ImageInfo.FullID); 609 // Console.WriteLine("sending " + req.ImageInfo.FullID);
610 610
611 // if (req.ImageInfo.FullID == new LLUUID("00000000-0000-0000-5005-000000000005")) 611 // if (req.ImageInfo.FullID == new LLUUID("00000000-0000-0000-5005-000000000005"))
612 if (req.PacketCounter == 0) 612 if (req.PacketCounter == 0)
613 { 613 {
614 //first time for this request so send imagedata packet 614 //first time for this request so send imagedata packet
615 if (req.NumPackets == 1) 615 if (req.NumPackets == 1)
616 { 616 {
617 //only one packet so send whole file 617 //only one packet so send whole file
618 ImageDataPacket im = new ImageDataPacket(); 618 ImageDataPacket im = new ImageDataPacket();
619 im.ImageID.Packets = 1; 619 im.ImageID.Packets = 1;
620 im.ImageID.ID = req.ImageInfo.FullID; 620 im.ImageID.ID = req.ImageInfo.FullID;
621 im.ImageID.Size = (uint)req.ImageInfo.Data.Length; 621 im.ImageID.Size = (uint)req.ImageInfo.Data.Length;
622 im.ImageData.Data = req.ImageInfo.Data; 622 im.ImageData.Data = req.ImageInfo.Data;
623 im.ImageID.Codec = 2; 623 im.ImageID.Codec = 2;
624 req.RequestUser.OutPacket(im); 624 req.RequestUser.OutPacket(im);
625 req.PacketCounter++; 625 req.PacketCounter++;
626 //req.ImageInfo.l= time; 626 //req.ImageInfo.l= time;
627 //System.Console.WriteLine("sent texture: " + req.ImageInfo.FullID); 627 //System.Console.WriteLine("sent texture: " + req.ImageInfo.FullID);
628 // Console.WriteLine("sending packet 1 for " + req.ImageInfo.FullID.ToStringHyphenated()); 628 // Console.WriteLine("sending packet 1 for " + req.ImageInfo.FullID.ToStringHyphenated());
629 } 629 }
630 else 630 else
631 { 631 {
632 //more than one packet so split file up 632 //more than one packet so split file up
633 ImageDataPacket im = new ImageDataPacket(); 633 ImageDataPacket im = new ImageDataPacket();
634 im.ImageID.Packets = (ushort)req.NumPackets; 634 im.ImageID.Packets = (ushort)req.NumPackets;
635 im.ImageID.ID = req.ImageInfo.FullID; 635 im.ImageID.ID = req.ImageInfo.FullID;
636 im.ImageID.Size = (uint)req.ImageInfo.Data.Length; 636 im.ImageID.Size = (uint)req.ImageInfo.Data.Length;
637 im.ImageData.Data = new byte[600]; 637 im.ImageData.Data = new byte[600];
638 Array.Copy(req.ImageInfo.Data, 0, im.ImageData.Data, 0, 600); 638 Array.Copy(req.ImageInfo.Data, 0, im.ImageData.Data, 0, 600);
639 im.ImageID.Codec = 2; 639 im.ImageID.Codec = 2;
640 req.RequestUser.OutPacket(im); 640 req.RequestUser.OutPacket(im);
641 req.PacketCounter++; 641 req.PacketCounter++;
642 //req.ImageInfo.last_used = time; 642 //req.ImageInfo.last_used = time;
643 //System.Console.WriteLine("sent first packet of texture: 643 //System.Console.WriteLine("sent first packet of texture:
644 // Console.WriteLine("sending packet 1 for " + req.ImageInfo.FullID.ToStringHyphenated()); 644 // Console.WriteLine("sending packet 1 for " + req.ImageInfo.FullID.ToStringHyphenated());
645 } 645 }
646 } 646 }
647 else 647 else
648 { 648 {
649 //Console.WriteLine("sending packet" + req.PacketCounter + "for " + req.ImageInfo.FullID.ToStringHyphenated()); 649 //Console.WriteLine("sending packet" + req.PacketCounter + "for " + req.ImageInfo.FullID.ToStringHyphenated());
650 //send imagepacket 650 //send imagepacket
651 //more than one packet so split file up 651 //more than one packet so split file up
652 ImagePacketPacket im = new ImagePacketPacket(); 652 ImagePacketPacket im = new ImagePacketPacket();
653 im.ImageID.Packet = (ushort)req.PacketCounter; 653 im.ImageID.Packet = (ushort)req.PacketCounter;
654 im.ImageID.ID = req.ImageInfo.FullID; 654 im.ImageID.ID = req.ImageInfo.FullID;
655 int size = req.ImageInfo.Data.Length - 600 - 1000 * (req.PacketCounter - 1); 655 int size = req.ImageInfo.Data.Length - 600 - 1000 * (req.PacketCounter - 1);
656 if (size > 1000) size = 1000; 656 if (size > 1000) size = 1000;
657 im.ImageData.Data = new byte[size]; 657 im.ImageData.Data = new byte[size];
658 Array.Copy(req.ImageInfo.Data, 600 + 1000 * (req.PacketCounter - 1), im.ImageData.Data, 0, size); 658 Array.Copy(req.ImageInfo.Data, 600 + 1000 * (req.PacketCounter - 1), im.ImageData.Data, 0, size);
659 req.RequestUser.OutPacket(im); 659 req.RequestUser.OutPacket(im);
660 req.PacketCounter++; 660 req.PacketCounter++;
661 //req.ImageInfo.last_used = time; 661 //req.ImageInfo.last_used = time;
662 //System.Console.WriteLine("sent a packet of texture: "+req.image_info.FullID); 662 //System.Console.WriteLine("sent a packet of texture: "+req.image_info.FullID);
663 } 663 }
664 664
665 } 665 }
666 } 666 }
667 } 667 }
668} 668}
669 669