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