/// <summary> /// Handles the Image Data packet, which includes the ID, and Size of the image, /// along with the first block of data for the image. If the image is small enough /// there will be no additional packets. /// </summary> /// <param name="packet"></param> /// <param name="simulator"></param> public void ImageDataCallbackHandler(Packet packet, Simulator simulator) { #if DEBUG_PACKETS slClient.DebugLog(packet); #endif ImageDataPacket reply = (ImageDataPacket)packet; LLUUID ImageID = reply.ImageID.ID; // unused? ushort Packets = reply.ImageID.Packets; uint Size = reply.ImageID.Size; byte[] Data = reply.ImageData.Data; // Lookup the request that this packet is for TransferRequest tr; lock (htDownloadRequests) { if (htDownloadRequests.ContainsKey(ImageID)) { tr = htDownloadRequests[ImageID]; } else { // Received a packet for an image we didn't request... return; } } // Initialize the request so that it's data buffer is the right size for the image tr.Size = Size; tr.AssetData = new byte[tr.Size]; tr.BaseDataReceived = Data.Length; // Copy the first block of image data into the request. Buffer.BlockCopy(Data, 0, tr.AssetData, (int)tr.Received, Data.Length); tr.Received += (uint)Data.Length; // Mark that the TransferRequest has received this header packet tr.ReceivedHeaderPacket.Set(); tr.TimeOfLastPacket = Helpers.GetUnixTime(); // last time we recevied a packet for this request // If we've gotten all the data, mark it completed. if (tr.Received >= tr.Size) { tr.Status = true; tr.Completed.Set(); // Fire off image downloaded event CacheImage(ImageID, tr.AssetData); FireImageRetrieved(ImageID, tr.AssetData, false); } }
private void SendImageFirstPart(ushort packetCount, byte[] imageData) { ImageDataPacket packet = new ImageDataPacket(); packet.ImageID.ID = TextureID; packet.ImageID.Packets = packetCount; packet.ImageID.Size = (uint)m_asset.Length; packet.ImageID.Codec = (byte)ImageCodec.J2C; packet.ImageData.Data = imageData; m_udp.SendPacket(m_agent, packet, ThrottleCategory.Texture, false); }
/// <summary> /// Handles the Image Data packet, which includes the ID, and Size of the image, /// along with the first block of data for the image. If the image is small enough /// there will be no additional packets. /// </summary> /// <param name="packet"></param> /// <param name="simulator"></param> public void ImageDataCallbackHandler(Packet packet, Simulator simulator) { #if DEBUG_PACKETS Console.WriteLine(packet); #endif ImageDataPacket reply = (ImageDataPacket)packet; LLUUID ImageID = reply.ImageID.ID; ushort Packets = reply.ImageID.Packets; uint Size = reply.ImageID.Size; byte[] Data = reply.ImageData.Data; // Lookup the request that this packet is for TransferRequest tr; lock (htDownloadRequests) { try { tr = htDownloadRequests[ImageID]; } catch (Exception e) { // Received a packet for an image we didn't request... return; } } // Initialize the request so that it's data buffer is the right size for the image tr.Size = Size; tr.AssetData = new byte[tr.Size]; tr.BaseDataReceived = Data.Length; // Copy the first block of image data into the request. Array.Copy(Data, 0, tr.AssetData, tr.Received, Data.Length); tr.Received += (uint)Data.Length; // Mark that the TransferRequest has received this header packet tr.ReceivedHeaderPacket.Set(); // If we've gotten all the data, mark it completed. if (tr.Received >= tr.Size) { tr.Status = true; tr.Completed.Set(); // Fire off image downloaded event CacheImage(ImageID, tr.AssetData); FireImageRetrieved(ImageID, tr.AssetData, false); } }
public void SendImageFirstPart(ushort numParts, UUID ImageUUID, uint ImageSize, byte[] ImageData, byte imageCodec) { ImageDataPacket im = new ImageDataPacket(); im.Header.Reliable = false; im.ImageID.Packets = numParts; im.ImageID.ID = ImageUUID; if (ImageSize > 0) { im.ImageID.Size = ImageSize; } im.ImageData.Data = ImageData; im.ImageID.Codec = imageCodec; im.Header.Zerocoded = true; sentdatapkt.Add(im); }
/// <summary> /// Handles the Image Data packet which includes the ID and Size of the image, /// along with the first block of data for the image. If the image is small enough /// there will be no additional packets /// </summary> private void ImageDataHandler(Packet packet, Simulator simulator) { ImageDataPacket data = (ImageDataPacket)packet; ImageDownload transfer = null; lock (Transfers) { if (Transfers.ContainsKey(data.ImageID.ID)) { transfer = (ImageDownload)Transfers[data.ImageID.ID]; //Client.DebugLog("Received first " + data.ImageData.Data.Length + " bytes for image " + // data.ImageID.ID.ToString()); transfer.Codec = data.ImageID.Codec; transfer.PacketCount = data.ImageID.Packets; transfer.Size = (int)data.ImageID.Size; transfer.AssetData = new byte[transfer.Size]; transfer.AssetType = AssetType.Texture; Buffer.BlockCopy(data.ImageData.Data, 0, transfer.AssetData, 0, data.ImageData.Data.Length); transfer.InitialDataSize = data.ImageData.Data.Length; transfer.Transferred += data.ImageData.Data.Length; // Check if we downloaded the full image if (transfer.Transferred >= transfer.Size) { Transfers.Remove(transfer.ID); transfer.Success = true; } } } if (transfer != null) { transfer.HeaderReceivedEvent.Set(); if (OnImageReceived != null && transfer.Transferred >= transfer.Size) { try { OnImageReceived(transfer, new AssetTexture(transfer.AssetData)); } catch (Exception e) { Client.Log(e.ToString(), Helpers.LogLevel.Error); } } } }
void RequestImageHandler(Packet packet, Agent agent) { RequestImagePacket request = (RequestImagePacket)packet; foreach (RequestImagePacket.RequestImageBlock block in request.RequestImage) { //ImageNotInDatabasePacket missing = new ImageNotInDatabasePacket(); //missing.ImageID.ID = block.Image; //agent.SendPacket(missing); ImageDataPacket imageData = new ImageDataPacket(); imageData.ImageData.Data = OpenJPEG.EncodeFromImage(DefaultImage, true); imageData.ImageID.ID = block.Image; imageData.ImageID.Codec = 1; imageData.ImageID.Packets = 1; imageData.ImageID.Size = (uint)imageData.ImageData.Data.Length; agent.SendPacket(imageData); } }
/// <summary> /// Handle the initial ImageDataPacket sent from the simulator /// </summary> /// <param name="sender">The sender</param> /// <param name="e">The EventArgs object containing the packet data</param> protected void ImageDataHandler(object sender, PacketReceivedEventArgs e) { ImageDataPacket data = (ImageDataPacket)e.Packet; TaskInfo task; if (TryGetTransferValue(data.ImageID.ID, out task)) { // reset the timeout interval since we got data task.Transfer.TimeSinceLastPacket = 0; lock (task.Transfer) if (task.Transfer.Size == 0) { task.Transfer.Codec = (ImageCodec)data.ImageID.Codec; task.Transfer.PacketCount = data.ImageID.Packets; task.Transfer.Size = (int)data.ImageID.Size; task.Transfer.AssetData = new byte[task.Transfer.Size]; task.Transfer.AssetType = AssetType.Texture; task.Transfer.PacketsSeen = new SortedList <ushort, ushort>(); Buffer.BlockCopy(data.ImageData.Data, 0, task.Transfer.AssetData, 0, data.ImageData.Data.Length); task.Transfer.InitialDataSize = data.ImageData.Data.Length; task.Transfer.Transferred += data.ImageData.Data.Length; } task.Transfer.HeaderReceivedEvent.Set(); if (task.Transfer.Transferred >= task.Transfer.Size) { #if DEBUG_TIMING DateTime stopTime = DateTime.UtcNow; TimeSpan requestDuration = stopTime - task.StartTime; TimeSpan networkDuration = stopTime - task.NetworkTime; TotalTime += requestDuration; NetworkTime += networkDuration; TotalBytes += task.Transfer.Size; Logger.Log( String.Format( "Transfer Complete {0} [{1}] Total Request Time: {2}, Download Time {3}, Network {4}Kb/sec, Image Size {5} bytes", task.RequestID, task.RequestSlot, requestDuration, networkDuration, Math.Round(task.Transfer.Size / networkDuration.TotalSeconds / 60, 2), task.Transfer.Size), Helpers.LogLevel.Debug); #endif task.Transfer.Success = true; RemoveTransfer(task.RequestID); resetEvents[task.RequestSlot].Set(); _Client.Assets.Cache.SaveAssetToCache(task.RequestID, task.Transfer.AssetData); foreach (TextureDownloadCallback callback in task.Callbacks) { callback(TextureRequestState.Finished, new AssetTexture(task.RequestID, task.Transfer.AssetData)); } _Client.Assets.FireImageProgressEvent(task.RequestID, task.Transfer.Transferred, task.Transfer.Size); } else { if (task.ReportProgress) { foreach (TextureDownloadCallback callback in task.Callbacks) { callback(TextureRequestState.Progress, new AssetTexture(task.RequestID, task.Transfer.AssetData)); } } _Client.Assets.FireImageProgressEvent(task.RequestID, task.Transfer.Transferred, task.Transfer.Size); } } }
void SendTexture(Agent agent, AssetTexture texture, int discardLevel, int packet, float priority) { ImageDownload download = new ImageDownload(texture, agent, discardLevel, priority, packet); Logger.DebugLog(String.Format( "[Periscope] Starting new texture transfer for {0}, DiscardLevel: {1}, Priority: {2}, Start: {3}, End: {4}, Total: {5}", texture.AssetID, discardLevel, priority, download.CurrentPacket, download.StopPacket, download.TexturePacketCount())); // Send initial data ImageDataPacket data = new ImageDataPacket(); data.ImageID.Codec = (byte)ImageCodec.J2C; data.ImageID.ID = download.Texture.AssetID; data.ImageID.Packets = (ushort)download.TexturePacketCount(); data.ImageID.Size = (uint)download.Texture.AssetData.Length; // The first bytes of the image are always sent in the ImageData packet data.ImageData = new ImageDataPacket.ImageDataBlock(); int imageDataSize = (download.Texture.AssetData.Length >= ImageDownload.FIRST_IMAGE_PACKET_SIZE) ? ImageDownload.FIRST_IMAGE_PACKET_SIZE : download.Texture.AssetData.Length; try { data.ImageData.Data = new byte[imageDataSize]; Buffer.BlockCopy(download.Texture.AssetData, 0, data.ImageData.Data, 0, imageDataSize); } catch (Exception ex) { Logger.Log(String.Format("{0}: imageDataSize={1}", ex.Message, imageDataSize), Helpers.LogLevel.Error); } server.UDP.SendPacket(agent.Avatar.ID, data, PacketCategory.Texture); // Check if ImagePacket packets need to be sent to complete this transfer if (download.CurrentPacket <= download.StopPacket) { // Insert this download into the dictionary lock (currentDownloads) currentDownloads[texture.AssetID] = download; // Send all of the remaining packets ThreadPool.QueueUserWorkItem( delegate(object obj) { while (download.CurrentPacket <= download.StopPacket) { if (download.Priority == 0.0f && download.DiscardLevel == -1) break; lock (download) { int imagePacketSize = (download.CurrentPacket == download.TexturePacketCount() - 1) ? download.LastPacketSize() : ImageDownload.IMAGE_PACKET_SIZE; ImagePacketPacket transfer = new ImagePacketPacket(); transfer.ImageID.ID = texture.AssetID; transfer.ImageID.Packet = (ushort)download.CurrentPacket; transfer.ImageData.Data = new byte[imagePacketSize]; try { Buffer.BlockCopy(download.Texture.AssetData, download.CurrentBytePosition(), transfer.ImageData.Data, 0, imagePacketSize); } catch (Exception ex) { Logger.Log(String.Format( "{0}: CurrentBytePosition()={1}, AssetData.Length={2} imagePacketSize={3}", ex.Message, download.CurrentBytePosition(), download.Texture.AssetData.Length, imagePacketSize), Helpers.LogLevel.Error); } server.UDP.SendPacket(agent.Avatar.ID, transfer, PacketCategory.Texture); ++download.CurrentPacket; } } Logger.DebugLog("Completed image transfer for " + texture.AssetID.ToString()); // Transfer is complete, remove the reference lock (currentDownloads) currentDownloads.Remove(texture.AssetID); } ); } }
void RequestImageHandler(Packet packet, Agent agent) { RequestImagePacket request = (RequestImagePacket)packet; for (int i = 0; i < request.RequestImage.Length; i++) { RequestImagePacket.RequestImageBlock block = request.RequestImage[i]; ImageDownload download; bool downloadFound = CurrentDownloads.TryGetValue(block.Image, out download); if (downloadFound) { lock (download) { if (block.DiscardLevel == -1 && block.DownloadPriority == 0.0f) { Logger.DebugLog(String.Format("Image download {0} is aborting", block.Image)); } else { if (block.DiscardLevel < download.DiscardLevel) { Logger.DebugLog(String.Format("Image download {0} is changing from DiscardLevel {1} to {2}", block.Image, download.DiscardLevel, block.DiscardLevel)); } if (block.DownloadPriority != download.Priority) { Logger.DebugLog(String.Format("Image download {0} is changing from Priority {1} to {2}", block.Image, download.Priority, block.DownloadPriority)); } if (block.Packet != download.CurrentPacket) { Logger.DebugLog(String.Format("Image download {0} is changing from Packet {1} to {2}", block.Image, download.CurrentPacket, block.Packet)); } } // Update download download.Update(block.DiscardLevel, block.DownloadPriority, (int)block.Packet); } } else if (block.DiscardLevel == -1 && block.DownloadPriority == 0.0f) { // Aborting a download we are not tracking, ignore Logger.DebugLog(String.Format("Aborting an image download for untracked image " + block.Image.ToString())); } else { bool bake = ((ImageType)block.Type == ImageType.Baked); // New download, check if we have this image Asset asset; if (server.Assets.TryGetAsset(block.Image, out asset) && asset is AssetTexture) { download = new ImageDownload((AssetTexture)asset, block.DiscardLevel, block.DownloadPriority, (int)block.Packet); Logger.DebugLog(String.Format( "Starting new download for {0}, DiscardLevel: {1}, Priority: {2}, Start: {3}, End: {4}, Total: {5}", block.Image, block.DiscardLevel, block.DownloadPriority, download.CurrentPacket, download.StopPacket, download.TexturePacketCount())); // Send initial data ImageDataPacket data = new ImageDataPacket(); data.ImageID.Codec = (byte)ImageCodec.J2C; data.ImageID.ID = download.Texture.AssetID; data.ImageID.Packets = (ushort)download.TexturePacketCount(); data.ImageID.Size = (uint)download.Texture.AssetData.Length; // The first bytes of the image are always sent in the ImageData packet data.ImageData = new ImageDataPacket.ImageDataBlock(); int imageDataSize = (download.Texture.AssetData.Length >= ImageDownload.FIRST_IMAGE_PACKET_SIZE) ? ImageDownload.FIRST_IMAGE_PACKET_SIZE : download.Texture.AssetData.Length; data.ImageData.Data = new byte[imageDataSize]; Buffer.BlockCopy(download.Texture.AssetData, 0, data.ImageData.Data, 0, imageDataSize); server.UDP.SendPacket(agent.AgentID, data, PacketCategory.Texture); // Check if ImagePacket packets need to be sent to complete this transfer if (download.CurrentPacket <= download.StopPacket) { // Insert this download into the dictionary lock (CurrentDownloads) CurrentDownloads[block.Image] = download; // Send all of the remaining packets ThreadPool.QueueUserWorkItem( delegate(object obj) { while (download.CurrentPacket <= download.StopPacket) { if (download.Priority == 0.0f && download.DiscardLevel == -1) { break; } lock (download) { int imagePacketSize = (download.CurrentPacket == download.TexturePacketCount() - 1) ? download.LastPacketSize() : ImageDownload.IMAGE_PACKET_SIZE; ImagePacketPacket transfer = new ImagePacketPacket(); transfer.ImageID.ID = block.Image; transfer.ImageID.Packet = (ushort)download.CurrentPacket; transfer.ImageData.Data = new byte[imagePacketSize]; Buffer.BlockCopy(download.Texture.AssetData, download.CurrentBytePosition(), transfer.ImageData.Data, 0, imagePacketSize); server.UDP.SendPacket(agent.AgentID, transfer, PacketCategory.Texture); ++download.CurrentPacket; } } Logger.DebugLog("Completed image transfer for " + block.Image.ToString()); // Transfer is complete, remove the reference lock (CurrentDownloads) CurrentDownloads.Remove(block.Image); } ); } } else { Logger.Log("Request for a missing texture " + block.Image.ToString(), Helpers.LogLevel.Warning); ImageNotInDatabasePacket notfound = new ImageNotInDatabasePacket(); notfound.ImageID.ID = block.Image; server.UDP.SendPacket(agent.AgentID, notfound, PacketCategory.Texture); } } } }
/// <summary> /// /// </summary> private void ProcessTextureQueue() { if (this.TextureRequests.Count == 0) { //no requests waiting return; } int num; if (this.TextureRequests.Count < 5) { //lower than 5 so do all of them num = this.TextureRequests.Count; } else { num = 5; } AssetRequest req; for (int i = 0; i < num; i++) { req = (AssetRequest)this.TextureRequests[i]; if (req.PacketCounter != req.NumPackets) { // if (req.ImageInfo.FullID == new LLUUID("00000000-0000-0000-5005-000000000005")) if (req.PacketCounter == 0) { //first time for this request so send imagedata packet if (req.NumPackets == 1) { //only one packet so send whole file ImageDataPacket im = new ImageDataPacket(); im.ImageID.Packets = 1; im.ImageID.ID = req.ImageInfo.FullID; im.ImageID.Size = (uint)req.ImageInfo.Data.Length; im.ImageData.Data = req.ImageInfo.Data; im.ImageID.Codec = 2; req.RequestUser.OutPacket(im); req.PacketCounter++; //req.ImageInfo.l= time; //System.Console.WriteLine("sent texture: "+req.image_info.FullID); } else { //more than one packet so split file up ImageDataPacket im = new ImageDataPacket(); im.ImageID.Packets = (ushort)req.NumPackets; im.ImageID.ID = req.ImageInfo.FullID; im.ImageID.Size = (uint)req.ImageInfo.Data.Length; im.ImageData.Data = new byte[600]; Array.Copy(req.ImageInfo.Data, 0, im.ImageData.Data, 0, 600); im.ImageID.Codec = 2; req.RequestUser.OutPacket(im); req.PacketCounter++; //req.ImageInfo.last_used = time; //System.Console.WriteLine("sent first packet of texture: } } else { //send imagepacket //more than one packet so split file up ImagePacketPacket im = new ImagePacketPacket(); im.ImageID.Packet = (ushort)req.PacketCounter; im.ImageID.ID = req.ImageInfo.FullID; int size = req.ImageInfo.Data.Length - 600 - 1000 * (req.PacketCounter - 1); if (size > 1000) size = 1000; im.ImageData.Data = new byte[size]; Array.Copy(req.ImageInfo.Data, 600 + 1000 * (req.PacketCounter - 1), im.ImageData.Data, 0, size); req.RequestUser.OutPacket(im); req.PacketCounter++; //req.ImageInfo.last_used = time; //System.Console.WriteLine("sent a packet of texture: "+req.image_info.FullID); } } } //remove requests that have been completed int count = 0; for (int i = 0; i < num; i++) { if (this.TextureRequests.Count > count) { req = (AssetRequest)this.TextureRequests[count]; if (req.PacketCounter == req.NumPackets) { this.TextureRequests.Remove(req); } else { count++; } } } }
public void SendImageFirstPart(ushort numParts, UUID ImageUUID, uint ImageSize, byte[] ImageData, byte imageCodec) { ImageDataPacket im = new ImageDataPacket(); im.Header.Reliable = true; im.ImageID.Packets = numParts; im.ImageID.ID = ImageUUID; if (ImageSize > 0) im.ImageID.Size = ImageSize; im.ImageData.Data = ImageData; im.ImageID.Codec = imageCodec; im.Header.Zerocoded = true; //OutPacket(im, ThrottleOutPacketType.Texture); proxy.InjectPacket(im, Direction.Incoming); }
private Packet ImageDataHandler(Packet packet, IPEndPoint simulator) { if (form.getEnabled()) { ImageDataPacket data = (ImageDataPacket)packet; //(ImageCodec)data.ImageID.Codec; byte[] data2 = new byte[(int)data.ImageID.Size]; Buffer.BlockCopy(data.ImageData.Data, 0, data2, 0, data.ImageData.Data.Length); //we now have it in data... /* * data += 8; * S32 xsiz = ntohl(((U32*)data)[0]); * S32 ysiz = ntohl(((U32*)data)[1]); * S32 xosiz = ntohl(((U32*)data)[2]); * S32 yosiz = ntohl(((U32*)data)[3]); * S32 xtsiz = ntohl(((U32*)data)[4]); * S32 ytsiz = ntohl(((U32*)data)[5]); * //S32 xtosiz = ntohl(((U32*)data)[6]); * //S32 ytosiz = ntohl(((U32*)data)[7]); * if(xsiz < 16 || xsiz > 2048 || ysiz < 16 || ysiz > 2048) { */ byte[] four = new byte[4]; bool flag = false; for (int location = 8; location < 30; location += 4) { Buffer.BlockCopy(data2, location, four, 0, 4); int size = BitConverter.ToInt32(ReadBytes(four, 4), 0); if (flag) { Console.WriteLine("Loc = " + location.ToString() + "| IMAGE SIZE = " + size.ToString()); } if (location == 16 || location == 20) { //seem to always be zero if (size != 0) { //SendUserAlert("Well, i really don't think you are ever suposed to get this error... so.. remeber this key and send it to me"); flag = true; } } else { if (IsPowerOfTwo((uint)size) && size <= 2048 && size >= 1) { ///cool } else { flag = true; } } } if (flag) { //SendUserAlert("We Got a evil Image\nIts key is " + data.ImageID.ID.ToString()); frame.SendUserAlert("Possible Image Crash Prevented"); ImageNotInDatabasePacket no = new ImageNotInDatabasePacket(); no.ImageID.ID = data.ImageID.ID; proxy.InjectPacket(no, Direction.Incoming); return(null); } } return(packet); }
/// <summary> /// /// </summary> private void ProcessTextureQueue() { if (this.TextureRequests.Count == 0) { //no requests waiting return; } int num; if (this.TextureRequests.Count < 5) { //lower than 5 so do all of them num = this.TextureRequests.Count; } else { num = 5; } AssetRequest req; for (int i = 0; i < num; i++) { req = (AssetRequest)this.TextureRequests[i]; if (req.PacketCounter != req.NumPackets) { // if (req.ImageInfo.FullID == new LLUUID("00000000-0000-0000-5005-000000000005")) if (req.PacketCounter == 0) { //first time for this request so send imagedata packet if (req.NumPackets == 1) { //only one packet so send whole file ImageDataPacket im = new ImageDataPacket(); im.ImageID.Packets = 1; im.ImageID.ID = req.ImageInfo.FullID; im.ImageID.Size = (uint)req.ImageInfo.Data.Length; im.ImageData.Data = req.ImageInfo.Data; im.ImageID.Codec = 2; req.RequestUser.OutPacket(im); req.PacketCounter++; //req.ImageInfo.l= time; //System.Console.WriteLine("sent texture: "+req.image_info.FullID); } else { //more than one packet so split file up ImageDataPacket im = new ImageDataPacket(); im.ImageID.Packets = (ushort)req.NumPackets; im.ImageID.ID = req.ImageInfo.FullID; im.ImageID.Size = (uint)req.ImageInfo.Data.Length; im.ImageData.Data = new byte[600]; Array.Copy(req.ImageInfo.Data, 0, im.ImageData.Data, 0, 600); im.ImageID.Codec = 2; req.RequestUser.OutPacket(im); req.PacketCounter++; //req.ImageInfo.last_used = time; //System.Console.WriteLine("sent first packet of texture: } } else { //send imagepacket //more than one packet so split file up ImagePacketPacket im = new ImagePacketPacket(); im.ImageID.Packet = (ushort)req.PacketCounter; im.ImageID.ID = req.ImageInfo.FullID; int size = req.ImageInfo.Data.Length - 600 - 1000 * (req.PacketCounter - 1); if (size > 1000) { size = 1000; } im.ImageData.Data = new byte[size]; Array.Copy(req.ImageInfo.Data, 600 + 1000 * (req.PacketCounter - 1), im.ImageData.Data, 0, size); req.RequestUser.OutPacket(im); req.PacketCounter++; //req.ImageInfo.last_used = time; //System.Console.WriteLine("sent a packet of texture: "+req.image_info.FullID); } } } //remove requests that have been completed int count = 0; for (int i = 0; i < num; i++) { if (this.TextureRequests.Count > count) { req = (AssetRequest)this.TextureRequests[count]; if (req.PacketCounter == req.NumPackets) { this.TextureRequests.Remove(req); } else { count++; } } } }