Exemple #1
0
        public async Task <IActionResult> Edit(int id, [Bind("CritterImageId,Data")] CritterImage val)
        {
            if (val.CritterImageId != id)
            {
                return(NotFound());
            }

            this.FixNullFields(val);

            if (ModelState.IsValid)
            {
                try
                {
                    _context.Update(val);
                    await _context.SaveChangesAsync();
                }
                catch (DbUpdateConcurrencyException)
                {
                    if (!Exists(val.CritterImageId))
                    {
                        return(NotFound());
                    }
                    else
                    {
                        throw;
                    }
                }
                return(RedirectToAction(nameof(Index)));
            }

            return(View(val));
        }
Exemple #2
0
        public async Task <IActionResult> Create([Bind("CritterImageId,Data")] CritterImage val)
        {
            this.FixNullFields(val);
            if (ModelState.IsValid)
            {
                _context.Add(val);
                await _context.SaveChangesAsync();

                return(RedirectToAction(nameof(Index)));
            }

            return(View(val));
        }
Exemple #3
0
    public void RegisterCritter(Critter critter)
    {
        critters.Add(critter);
        if (critters.Count - 1 < critterColours.Length)
        {
            critter.SetColour(critterColours[critters.Count - 1]);
        }
        critter.id = critters.Count - 1;
        critterImages.Add(new RenderTexture(256, 256, 16));
        CritterImage newImage = Instantiate(critterImagePrefab, new Vector3((critter.id + 1) * 1000, 0, 0), Quaternion.identity);

        newImage.SetupImage(critterColours[critter.id], critterImages[critter.id]);
    }
Exemple #4
0
 private void FixNullFields(CritterImage val)
 {
 }
        public async Task <IActionResult> Image(int critterId, int cacheVersion, int?width, int?height, CancellationToken cancelToken)
        {
            // Limit to only processing a certain amount of image requests, to prevent the rest of the
            // website from dying when someone needs to get a lot of images.
            while (Interlocked.Read(ref _imageRequestCounter) >= MAX_IMAGE_SIMUL_REQUESTS)
            {
                await Task.Delay(IMAGE_DELAY_MS);

                cancelToken.ThrowIfCancellationRequested();
            }

            try
            {
                Interlocked.Increment(ref _imageRequestCounter);

                var critter = await this._livestock.Critter.FirstAsync(c => c.CritterId == critterId);

                // If the critter has an image, retrieve it.
                if (critter.CritterImageId != null)
                {
                    CritterImage image = null;

                    // If we need a specific size, either retrieve or create it.
                    if (width != null && height != null)
                    {
                        // Prevent exploits
                        if (width > MAX_IMAGE_RESIZE_WIDTH || height > MAX_IMAGE_RESIZE_HEIGHT)
                        {
                            return(BadRequest("Width or height was too high."));
                        }

                        if (width < 0 || height < 0)
                        {
                            return(BadRequest("Width or height cannot be negative."));
                        }

                        var variant = await this._livestock.CritterImageVariant
                                      .FirstOrDefaultAsync(v => v.CritterImageOriginalId == critter.CritterImageId &&
                                                           v.Width == width &&
                                                           v.Height == height);

                        if (variant != null)
                        {
                            return(await this.GetAndCacheImage(critter, variant.CritterImageModifiedId, cacheVersion, width, height));
                        }
                        else
                        {
                            variant = new CritterImageVariant
                            {
                                CritterImageOriginalId = critter.CritterImageId.Value,
                                Width  = width.Value,
                                Height = height.Value
                            };

                            await this._livestock.Entry(critter).Reference(c => c.CritterImage).LoadAsync();

                            image = critter.CritterImage;

                            // Resize it, then upload it so it's cached.
                            var resized = await this.ResizeImageAsyncPOOLED(image.Data, width.Value, height.Value);

                            image = new CritterImage
                            {
                                Data = resized
                            };

                            variant.CritterImageModified = image;

                            try
                            {
                                await this._livestock.CritterImage.AddAsync(image);

                                await this._livestock.CritterImageVariant.AddAsync(variant);

                                await this._livestock.SaveChangesAsync();
                            }
                            finally // I can count on one hand the amount of times I've used 'finally'.
                            {
                                // We detach the entity, since the image data shouldn't be reference anymore once it's returned.
                                // And if we set it to 'null', then we can accidentally remove the image data if we save at some point.
                                // So it's safer to just detach it, and take the performance hit of downloading a new version of it when needed.
                                this._livestock.Entry(image).State = EntityState.Detached;
                                _imageBufferPool.Return(resized);
                            }

                            return(File(image.Data, "image/png"));
                        }
                    }
                    else // Otherwise, return the original.
                    {
                        return(await this.GetAndCacheImage(critter, critter.CritterImageId.Value, cacheVersion, width, height));
                    }
                }
                else
                {
                    return(Redirect("/images/icons/default.png"));
                }
            }
            finally
            {
                Interlocked.Decrement(ref _imageRequestCounter);
            }
        }