Esempio n. 1
0
        public List <PositionKey> VisibleTiles(int dx, int dy, int width, int height, ref HashSet <PositionKey> exclude)
        {
            var tlLoc = ScreenToCanvas(dx, dy);
            var brLoc = ScreenToCanvas(dx + width, dy + height);

            if (double.IsNaN(tlLoc.X) || double.IsNaN(brLoc.X))
            {
                throw new Exception("ScreenToCanvas gave an invalid result");
            }

            var result = new List <PositionKey>();
            var tlPos  = tlLoc.TilePosition ?? throw new Exception("TL tile position lookup failed");
            var brPos  = brLoc.TilePosition ?? throw new Exception("BR tile position lookup failed");

            for (int y = tlPos.Y; y <= brPos.Y; y++)
            {
                for (int x = tlPos.X; x <= brPos.X; x++)
                {
                    var pk = new PositionKey(x, y);
                    if (exclude?.Contains(pk) == true)
                    {
                        exclude.Remove(pk);
                        continue;
                    }
                    result.Add(new PositionKey(x, y));
                }
            }

            return(result);
        }
Esempio n. 2
0
    public override void Init()
    {
        PositionKey found = PlanetSave.PNJs.Find(p => new Vector3(p.x, p.y, p.z) == transform.position);

        IDname = found.key;

        NPCWrap npcText = ResourcesManager.Instance.NPCs.objects.Find(npc => npc.ID == IDname);

        if (npcText != null)
        {
            _txtInfo = npcText;
        }

        budgetComponent = new BudgetComponent(IDname);
        if (GameManager.PARTY_TYPE == EPartyType.SAVE)
        {
            List <BudgetsSave> saves;
            ArrayExtensions.ToList(PlanetSave.GameStateSave.Budgets, out saves);
            BudgetsSave save = saves.Find(s => s.npcName == IDname);
            if (save != null)
            {
                budgetComponent.budget     = save.budget;
                budgetComponent.Investment = save.investment;
            }
        }
        if (InventoryPlayer.Instance)
        {
            CatchGivedObject();
        }
    }
Esempio n. 3
0
        public void GetPositionByKey_Multitrades_ChangeSide()
        {
            var service = new PositionCacheService();

            service.SubmitOrder(new Order()
            {
                OrderType        = Common.OrderType.Buy,
                SecurityMasterId = 1,
                Portfolio        = "TraderX",
                Price            = 100M,
                Quantity         = 100
            });

            service.SubmitOrder(new Order()
            {
                OrderType        = Common.OrderType.Sell,
                SecurityMasterId = 1,
                Portfolio        = "TraderX",
                Price            = 200.00M,
                Quantity         = 200
            });

            var pos = service.GetPositionByKey(PositionKey.Create("TraderX", 1));

            Assert.IsTrue(pos.IsShort);
        }
Esempio n. 4
0
        private async Task OnMessageReceived(MqttApplicationMessageReceivedEventArgs e)
        {
            var payload = e.ApplicationMessage.ConvertPayloadToString();

            Console.WriteLine($"Message arrived: {e.ApplicationMessage.Topic} - {payload}");

            var messageKey = new PositionKey
            {
                topic = e.ApplicationMessage.Topic
            };
            var messageValue = JsonConvert.DeserializeObject <VehiclePosition>(payload);
            var message      = new Message <PositionKey, PositionValue>
            {
                Key   = messageKey,
                Value = messageValue.VP
            };

            try
            {
                var result = await _producer.ProduceAsync(KafkaTopic, message);
            }
            catch (Exception exception)
            {
                System.Console.WriteLine($"Error producing message: {exception}");
            }
        }
Esempio n. 5
0
        /// <summary>
        /// Adds the tiles.
        /// </summary>
        /// <param name="tls">The tls.</param>
        public void AddTiles(ITileCollection tls)
        {
            if (tls == null)
            {
                throw new ArgumentNullException(nameof(tls));
            }
            List <TileMask> ts = (List <TileMask>)tls.GetEnumerable();
            int             px;
            int             py;
            PositionKey     pk;

            foreach (TileMask t in ts)
            {
                px = t.X / CellSize;
                py = t.Y / CellSize;
                if (px >= 0 && py >= 0 && px < Width && py < Height)
                {
                    pk = new PositionKey((uint)px, (uint)py);
                    if (!tiles.ContainsKey(pk))
                    {
                        tiles.Add(pk, new List <TileMask>());
                    }
                    tiles[pk].Add(t);
                }
            }
        }
Esempio n. 6
0
        public void GetPositionByKey_Multitrades_ValidQuantity()
        {
            var service = new PositionCacheService();

            service.SubmitOrder(new Order()
            {
                OrderType        = Common.OrderType.Buy,
                SecurityMasterId = 1,
                Portfolio        = "TraderX",
                Price            = 100.45M,
                Quantity         = 100
            });

            service.SubmitOrder(new Order()
            {
                OrderType        = Common.OrderType.Buy,
                SecurityMasterId = 1,
                Portfolio        = "TraderX",
                Price            = 200.00M,
                Quantity         = 100
            });

            var pos = service.GetPositionByKey(PositionKey.Create("TraderX", 1));

            Assert.AreEqual(200, pos.Quantity);
        }
Esempio n. 7
0
 public CachedTile([NotNull] Panel container, PositionKey key, double x, double y)
 {
     _key     = key;
     _x       = x;
     _y       = y;
     State    = TileState.Locked;
     UiCanvas = Win2dCanvasManager.Employ(container, this, x, y);
 }
Esempio n. 8
0
        /// <summary>
        /// Tiles the on area.
        /// </summary>
        /// <param name="x">The x.</param>
        /// <param name="y">The y.</param>
        /// <param name="width">The width.</param>
        /// <param name="height">The height.</param>
        /// <returns>An ITileCollection.</returns>
        public ITileCollection TilesOnArea(int x, int y, int width, int height)
        {
            uint px = (uint)(x / CellSize);
            uint py = (uint)(y / CellSize);
            int  w  = width / CellSize;
            int  h  = height / CellSize;

            if (width < 2 && height < 2)
            {
                PositionKey pk = new PositionKey(px, py);
                if (tiles.ContainsKey(pk))
                {
                    TileMaskCollection ret = new TileMaskCollection(BytesPerColor);
                    foreach (TileMask selT in tiles[pk])
                    {
                        ret.Add(selT);
                    }
                    return(ret);
                }
                else
                {
                    return(null);
                }
            }

            IEnumerable filtered = tiles.Where(kvp =>
            {
                if (kvp.Key.X < px)
                {
                    return(false);
                }
                if (kvp.Key.Y < py)
                {
                    return(false);
                }
                if (kvp.Key.X >= w + px)
                {
                    return(false);
                }
                if (kvp.Key.Y >= h + py)
                {
                    return(false);
                }
                return(true);
            });

            TileMaskCollection t = new TileMaskCollection(BytesPerColor);

            foreach (KeyValuePair <PositionKey, List <TileMask> > kvp in filtered)
            {
                foreach (TileMask selT in kvp.Value)
                {
                    t.Add(selT);
                }
            }

            return(t);
        }
Esempio n. 9
0
        /// <summary>
        /// Sets the kickoff position for (player, direction).
        /// </summary>
        private void setAttackPosition(int playerNumber, DirectionType playingDirection, Position position, double direction)
        {
            var key   = new PositionKey(playerNumber, playingDirection);
            var value = new PositionValue {
                position = position, direction = direction
            };

            this.attackPositions[key] = value;
        }
Esempio n. 10
0
        /// <summary>
        /// Canvas to screen position. DOES NOT calculate for zoom
        /// </summary>
        public void CanvasToScreen(PositionKey tilePos, out float x, out float y)
        {
            if (tilePos == null)
            {
                x = 0; y = 0;
                return;
            }

            x = (tilePos.X * TileImageSize) - (int)X;
            y = (tilePos.Y * TileImageSize) - (int)Y;
        }
Esempio n. 11
0
        public void CentreOn(PositionKey pos)
        {
            if (pos == null)
            {
                return;
            }

            X = (pos.X * TileImageSize);
            Y = (pos.Y * TileImageSize);

            X -= _displayContainer.ActualWidth / 2;
            Y -= _displayContainer.ActualHeight / 2;

            Invalidate();
        }
Esempio n. 12
0
        private void CentreOnPin(object selectedItem)
        {
            if (!(selectedItem is ListViewItem item))
            {
                return;
            }
            if (!(item.Tag is InfoPin pin))
            {
                return;
            }

            var pos = PositionKey.Parse(pin.Id);

            _view?.CentreOn(pos);
        }
Esempio n. 13
0
        public void GetPositionByKey_InValidPortFolio()
        {
            var service = new PositionCacheService();

            service.SubmitOrder(new Order()
            {
                OrderType        = Common.OrderType.Buy,
                SecurityMasterId = 1,
                Portfolio        = "TraderX",
                Price            = 100.45M,
                Quantity         = 100
            });

            var pos = service.GetPositionByKey(PositionKey.Create("Trader", 1));

            Assert.IsNull(pos);
        }
Esempio n. 14
0
        /// <summary>
        /// Load a tile from the store, and add it to the display container and dictionary
        /// If no tile is available in the store at this position, we put an empty proxy in place.
        /// </summary>
        private void AddToCache(PositionKey key)
        {
            if (key == null)
            {
                return;
            }

            var pos  = VisualRectangleNative(key);
            var tile = new CachedTile(_displayContainer, key, pos.X, pos.Y); // calls down to "Win2dCanvasManager.Employ"

            tile.SetState(TileState.Locked);

            lock (_reflowLock)
            {
                _tileCache.Add(key, tile);
                _loadQueue.Enqueue(tile);
            }
        }
Esempio n. 15
0
    public void UpdateScrubTime(float scrubTime)
    {
        while (lastScrubFrame > 0 && scrubTrack[lastScrubFrame - 1].clockTime > scrubTime)
        {
            --lastScrubFrame;
        }

        if (lastScrubFrame == 0 || lastScrubFrame == (numScrubFrames - 1))
        {
            transform.position = scrubTrack[lastScrubFrame].position;
        }
        else
        {
            PositionKey k0    = scrubTrack[lastScrubFrame];
            PositionKey k1    = scrubTrack[lastScrubFrame + 1];
            float       tSpan = k1.clockTime - k0.clockTime;
            float       t     = (scrubTime - k0.clockTime) / tSpan;

            transform.position = Vector3.Lerp(k0.position, k1.position, t);
        }
    }
Esempio n. 16
0
        private bool PrepareTileForDraw([NotNull] PositionKey key, out CachedTile tile)
        {
            lock (_reflowLock)
            {
                if (!_tileCache.ContainsKey(key))
                {
                    var pos     = VisualRectangleNative(key);
                    var newTile = new CachedTile(_displayContainer, key, pos.X, pos.Y); // calls down to "Win2dCanvasManager.Employ"
                    newTile.AllocateEmptyImage();
                    _tileCache.Add(key, newTile);
                }

                tile = _tileCache[key];
            }
            if (tile == null)
            {
                Logging.WriteLogMessage("Tile cache returned null after being populated!");
                return(false); // should never happen
            }
            if (tile.State == TileState.Locked)
            {
                Logging.WriteLogMessage("Tried to write to a locked tile");
                return(false);
            }

            var dst = tile.GetTileData();

            if (dst == null)
            {
                tile.AllocateEmptyImage();
                dst = tile.GetTileData();
            }

            if (dst == null)
            {
                throw new Exception("Tile data is missing, even after allocation");
            }
            return(true);
        }
Esempio n. 17
0
        /// <summary>
        /// Removes the tiles.
        /// </summary>
        public void RemoveTiles()
        {
            if (selection == null)
            {
                return;
            }
            uint            px;
            uint            py;
            PositionKey     pk;
            List <TileMask> tml;

            foreach (TileMask t in selection.GetEnumerable())
            {
                px = (uint)t.X;
                py = (uint)t.Y;

                pk = new PositionKey(px, py);

                tml = tiles[pk];
                tml.Remove(t);
            }
            selection = null;
        }
Esempio n. 18
0
        /// <summary>
        /// Draw an entire image onto the canvas, scaled to fit in the given rectangle.
        /// Expects screen-space co-ordinates.
        /// <para></para>
        /// Returns false if any of the tiles couldn't be written to
        /// </summary>
        public bool ImportBytesScaled(RawImageInterleaved_UInt8 img, int left, int top, int right, int bottom)
        {
            if (img == null)
            {
                return(false);
            }
            if (left >= right || top >= bottom)
            {
                return(true);
            }

            var tl = ScreenToCanvas(left, top);
            var br = ScreenToCanvas(right, bottom);

            var tileLeft   = tl.TilePosition?.X ?? throw new Exception("Invalid tile calculation");
            var tileTop    = tl.TilePosition.Y;
            var tileRight  = br.TilePosition?.X ?? throw new Exception("Invalid tile calculation");
            var tileBottom = br.TilePosition.Y;

            double targetNativeTop    = ((double)tileTop * TileImageSize) + tl.Y;
            double targetNativeBottom = ((double)tileBottom * TileImageSize) + br.Y;
            double targetNativeLeft   = ((double)tileLeft * TileImageSize) + tl.X;
            double targetNativeRight  = ((double)tileRight * TileImageSize) + br.X;

            double scale_x = img.Width / (targetNativeRight - targetNativeLeft);
            double scale_y = img.Height / (targetNativeBottom - targetNativeTop);

            // scan through the tiles we cover, and scale segments to fit.
            for (int ty = tileTop; ty <= tileBottom; ty++)
            {
                // see if we're at the top or bottom of the tiles covered
                var localNativeTop    = (double)ty * TileImageSize;
                var localNativeBottom = ((double)ty + 1) * TileImageSize;
                var tgtTop            = (localNativeTop < targetNativeTop) ? tl.Y : 0;
                var tgtHeight         = (localNativeBottom > targetNativeBottom) ? br.Y : TileImageSize;
                tgtHeight -= tgtTop;

                for (int tx = tileLeft; tx <= tileRight; tx++)
                {
                    // see if we're at the left or right of the tiles covered
                    var localNativeLeft  = (double)tx * TileImageSize;
                    var localNativeRight = ((double)tx + 1) * TileImageSize;
                    var tgtLeft          = (localNativeLeft < targetNativeLeft) ? tl.X : 0;
                    var tgtWidth         = (localNativeRight > targetNativeRight) ? br.X : TileImageSize;
                    tgtWidth -= tgtLeft;

                    // calculate what area of the image to use
                    var imgLeft = localNativeLeft - targetNativeLeft;
                    var imgTop  = localNativeTop - targetNativeTop;
                    if (imgLeft < 0)
                    {
                        imgLeft = 0;
                    }
                    if (imgTop < 0)
                    {
                        imgTop = 0;
                    }

                    // Ensure the tile is ready to be drawn on:
                    var key = new PositionKey(tx, ty);
                    var ok  = PrepareTileForDraw(key, out var tile);
                    if (!ok)
                    {
                        Logging.WriteLogMessage($"Preparing tile failed: {tx}, {ty}");
                        return(false);
                    }

                    // This could be kicked out to threads?:
                    var changed = AlphaMapImageToTileScaled(img, tile,
                                                            imageArea: new Quad(imgLeft, imgTop, tgtWidth * scale_x, tgtHeight * scale_y),
                                                            tileArea: new Quad(tgtLeft, tgtTop, tgtWidth, tgtHeight)
                                                            );

                    if (changed)
                    {
                        _lastChangedTiles.Add(key);
                        tile.Invalidate();
                        tile.SetState(TileState.Ready);
                        ThreadPool.UnsafeQueueUserWorkItem(xkey => { WriteTileToBackingStoreSync((PositionKey)xkey, tile); }, key);
                    }
                }
            }
            return(true);
        }
Esempio n. 19
0
        /// <summary>
        /// Returns the default position for (player, direction).
        /// </summary>
        private PositionValue getAttackPosition(int playerNumber, DirectionType playingDirection)
        {
            var key = new PositionKey(playerNumber, playingDirection);

            return(this.attackPositions[key]);
        }
Esempio n. 20
0
        /// <summary>
        /// Get the crew set-up(s) that would be worth the highest Score
        /// </summary>
        internal void GetIdealCrew(Dictionary <string, CrewMember> crewMembers, string managerName)
        {
            if (PositionCount == 0)
            {
                return;
            }

            //remove CrewMembers that are currently resting
            var availableCrew = crewMembers.Where(cm => cm.Value.RestCount <= 0).ToDictionary(ac => ac.Key, ac => ac.Value);

            //if there are not enough active CrewMembers to race,do not perform the rest of the method
            if (availableCrew.Count < PositionCount)
            {
                return;
            }

            var positionKey = new PositionKey();

            //get the combined score of mood, manager opinion and position rating for every crewmember in every position
            var positionCrewCombos = new Dictionary <PositionKey, int>();

            var positionNames = new List <string>();

            foreach (var position in Positions)
            {
                positionNames.Add(position.ToString());
                foreach (var cm in availableCrew)
                {
                    positionKey.Position = position.ToString();
                    positionKey.Crew     = cm.Key;
                    positionCrewCombos.Add(positionKey, GetPositionRating(cm.Value, position, managerName));
                }
            }
            //get every crewmember combination (unordered)
            var sortedCrew = availableCrew.Keys.OrderBy(c => c).ToList();
            var crewCombos = GetPermutations(sortedCrew, PositionCount - 1).ToList();
            //get the combined average opinion for every combination
            var crewOpinions       = new Dictionary <string, int>();
            var crewMaxScores      = new Dictionary <List <string>, int>();
            var crewPositionScores = new Dictionary <PositionKey, int>();

            foreach (var possibleCrew in crewCombos)
            {
                var crewComboKey = string.Concat(possibleCrew.ToArray());
                var opinionTotal = possibleCrew.Sum(c => availableCrew[c].GetOpinionRating(possibleCrew));
                crewOpinions.Add(crewComboKey, opinionTotal);
                //get every position rating for every crewmember in this combination in every position
                crewPositionScores.Clear();
                positionNames.ForEach(pn => possibleCrew.ForEach(pc =>
                {
                    positionKey.Position = pn;
                    positionKey.Crew     = pc;
                    crewPositionScores.Add(positionKey, positionCrewCombos[positionKey]);
                }));
                crewMaxScores.Add(possibleCrew, crewPositionScores.Values.OrderByDescending(v => v).Take(positionNames.Count).Sum() + opinionTotal);
            }
            var bestScore     = 0;
            var bestCrew      = new List <List <string> >(crewCombos.Count);
            var crewMaxSorted = crewMaxScores.OrderByDescending(m => m.Value).ToList();

            //for each possible combination
            foreach (var possibleCrew in crewMaxSorted)
            {
                //if the combined total of the top scores and highest possible opinion could beat the current top score, continue. Otherwise, this combination can never have the best combination, so stop
                if (possibleCrew.Value >= bestScore)
                {
                    //get every position rating for every crewmember in this combination in every position
                    crewPositionScores.Clear();
                    positionNames.ForEach(pn => possibleCrew.Key.ForEach(pc =>
                    {
                        positionKey.Position = pn;
                        positionKey.Crew     = pc;
                        crewPositionScores.Add(positionKey, positionCrewCombos[positionKey]);
                    }));
                    //sort these position ratings from highest to lowest
                    crewPositionScores = crewPositionScores.OrderByDescending(cps => cps.Value).ToDictionary(cps => cps.Key, cps => cps.Value);
                    //find the combined average opinion for this combination
                    var opinionScore = crewOpinions[string.Concat(possibleCrew.Key.ToArray())];
                    //if the highest score in each position plus the highest possible opinion is lower than the best score so far, stop this loop
                    if (positionNames.Select(pn => crewPositionScores.First(cps => cps.Key.Position == pn).Value).Sum() + opinionScore < bestScore)
                    {
                        continue;
                    }
                    //if the highest score for each crewmember plus the highest possible opinion is lower than the best score so far, stop this loop
                    if (possibleCrew.Key.Select(pc => crewPositionScores.First(cps => cps.Key.Crew == pc).Value).Sum() + opinionScore < bestScore)
                    {
                        continue;
                    }
                    //get every combination in every order for these crewmembers
                    var combos = GetOrderedPermutations(possibleCrew.Key, positionNames.Count - 1);
                    //for each combination
                    foreach (var combo in combos)
                    {
                        var score = 0;
                        //assign crew members to their positions and get the score for this set-up
                        for (var i = 0; i < combo.Count; i++)
                        {
                            positionKey.Position = positionNames[i];
                            positionKey.Crew     = combo[i];
                            score += crewPositionScores[positionKey];
                        }
                        //add the combined average opinion for this combination
                        score += opinionScore;
                        //if the score for this set-up is higher or equal than the current highest
                        if (score >= bestScore)
                        {
                            //if the set-up has a higher score, clear the current list
                            if (score > bestScore)
                            {
                                bestCrew.Clear();
                                bestScore = score;
                            }
                            //add this set-up to the list of best crews
                            bestCrew.Add(combo);
                        }
                    }
                }
            }
            //for each of the best crews, create a list of kvp of the crewmembers and their position/mood/manager opinion scores
            var idealCrew = new List <List <CrewMember> >();

            foreach (var crew in bestCrew)
            {
                var positionedCrew = new List <CrewMember>();
                for (var i = 0; i < crew.Count; i++)
                {
                    positionKey.Position = positionNames[i];
                    positionKey.Crew     = crew[i];
                    positionedCrew.Add(availableCrew[crew[i]]);
                }
                idealCrew.Add(positionedCrew);
            }
            var nearestIdealMatch = UpdateIdealScore(idealCrew);

            if (nearestIdealMatch.Count != 0)
            {
                FindAssignmentMistakes(nearestIdealMatch, managerName);
            }
        }
Esempio n. 21
0
 private Quad VisualRectangleNative(PositionKey tile)
 {
     CanvasToScreen(tile, out var x, out var y);
     return(new Quad((int)x, (int)y, TileImageSize, TileImageSize));
 }
Esempio n. 22
0
        private void WriteTileToBackingStoreSync(PositionKey key, CachedTile tile)
        {
            if (key == null)
            {
                return;
            }

            if (tile == null)
            {
                return;
            }
            if (tile.State == TileState.Locked)
            {
                return;
            }


            var red   = RawDataPool.Capture();
            var green = RawDataPool.Capture();
            var blue  = RawDataPool.Capture();

            try
            {
                var name = key.ToString();

                if (tile.ImageIsBlank())
                {
                    _tileStore.Delete(name, "img");
                    tile.SetState(TileState.Empty);
                }
                else
                {
                    var packed = tile.GetTileData();
                    if (packed == null)
                    {
                        return;
                    }

                    var end = TileImageSize * TileImageSize;
                    for (int i = 0; i < end; i++)
                    {
                        blue[i]  = packed[4 * i + 0];
                        green[i] = packed[4 * i + 1];
                        red[i]   = packed[4 * i + 2];
                    }

                    using (var ms = new MemoryStream())
                    {
                        WaveletCompress.Compress(red, green, blue, tile.Width, tile.Height).WriteToStream(ms);
                        ms.Seek(0, SeekOrigin.Begin);
                        var ok = _tileStore.Store(name, "img", ms);

                        if (ok.IsFailure)
                        {
                            throw new Exception("Storage error: DB might be corrupt.", ok.FailureCause);
                        }
                    }
                }
            }
            finally
            {
                RawDataPool.Release(red);
                RawDataPool.Release(green);
                RawDataPool.Release(blue);
            }
        }
Esempio n. 23
0
        private void LoadTileDataSync(PositionKey key, ICachedTile tile)
        {
            var red   = RawDataPool.Capture();
            var green = RawDataPool.Capture();
            var blue  = RawDataPool.Capture();

            try
            {
                if (key == null || tile == null)
                {
                    return;
                }

                var name = key.ToString();
                var res  = _tileStore.Exists(name);
                if (res.IsFailure)
                {
                    tile.SetState(TileState.Empty);
                    return;
                }

                var version = res.ResultData?.CurrentVersion ?? 1;
                var img     = _tileStore.Read(name, "img", version);

                if (img.IsFailure || img.ResultData == null)
                {
                    tile.SetState(TileState.Empty);
                    return;
                }

                var fileData = InterleavedFile.ReadFromStream(img.ResultData);
                if (fileData != null)
                {
                    WaveletCompress.Decompress(fileData, red, green, blue, 1);
                }

                tile.EnsureDataReady();
                var packed = tile.GetTileData() ?? throw new Exception("Byte pool allocation failed");

                var end = TileImageSize * TileImageSize;
                for (int i = 0; i < end; i++)
                {
                    packed[4 * i + 0] = blue[i];
                    packed[4 * i + 1] = green[i];
                    packed[4 * i + 2] = red[i];

                    if (blue[i] >= 254 && green[i] >= 254 && red[i] >= 254)
                    {
                        packed[4 * i + 3] = 0;
                    }
                    else
                    {
                        packed[4 * i + 3] = 255;
                    }
                }

                tile.SetState(TileState.Ready);
            }
            catch (Exception ex)
            {
                Logging.WriteLogMessage("Failed to load tile data\r\n" + ex);
                tile?.MarkCorrupted();
            }
            finally {
                RawDataPool.Release(red);
                RawDataPool.Release(green);
                RawDataPool.Release(blue);
            }
        }