Example #1
0
        public void Lock_Contend_LockDelay()
        {
            var client = new ConsulClient();

            const string keyName = "test/lock/contendlockdelay";

            const int contenderPool = 3;

            var acquired = new System.Collections.Concurrent.ConcurrentDictionary<int, bool>();
            using (var cts = new CancellationTokenSource())
            {
                cts.CancelAfter((contenderPool + 1) * (int)Lock.DefaultLockWaitTime.TotalMilliseconds);

                Parallel.For(0, contenderPool, new ParallelOptions { MaxDegreeOfParallelism = contenderPool, CancellationToken = cts.Token }, (v) =>
                {
                    var lockKey = (Lock)client.CreateLock(keyName);
                    lockKey.Acquire(CancellationToken.None);
                    if (lockKey.IsHeld)
                    {
                        Assert.True(acquired.TryAdd(v, lockKey.IsHeld));
                        client.Session.Destroy(lockKey.LockSession);
                    }
                });
            }
            for (var i = 0; i < contenderPool; i++)
            {
                bool didContend = false;
                if (acquired.TryGetValue(i, out didContend))
                {
                    Assert.True(didContend);
                }
                else
                {
                    Assert.True(false, "Contender " + i.ToString() + " did not acquire the lock");
                }
            }
        }
Example #2
0
        private void OnPulish(Message message)
        {
            message.Track("node publish message");
            if (!SubscriberCenter.IsSubscribers(message.Consumers) && message.Mode == ReceiveMode.Eq)
            {
                message.Track("match consumers start");
                ISubscriber subs = mLocalSubscriberCenter.Find(message.Consumers);
                message.Track("match consumers completed");
                if (subs != null)
                {
                    ProcessingMessage();
                    message.Track("publish to " + message.Consumers + subs.GetType());
                    subs.Process(this, message);
                    message.Track("publish to " + message.Consumers + " completed!");
                    ProcessedMessage();
                    return;
                }
                subs = mRemoteSubscriberCenter.Find(message.Consumers);
                if (subs != null)
                {
                    ProcessingMessage();
                    message.Track("publish to " + message.Consumers + subs.GetType());
                    subs.Process(this, message);
                    message.Track("publish to " + message.Consumers + " completed!");
                    ProcessedMessage();
                    return;
                }
                string error = string.Format("[{0}] subscriber not fount!", message.Consumers);
                message.ProcessError(new SRException(error));
                Loger.Process(LogType.ERROR, error);
            }
            else
            {
                SubscriberCenter.SearchResult localresult = null, remotresult = null;
                mLocalSubscriberCache.TryGetValue(message.Consumers, out localresult);
                mRemoteSubscriberCache.TryGetValue(message.Consumers, out remotresult);
                message.Track("match consumers start");
                if (localresult == null || localresult.Version != mLocalSubscriberCenter.Version)
                {
                    localresult         = new SubscriberCenter.SearchResult();
                    localresult.Version = mLocalSubscriberCenter.Version;
                    mLocalSubscriberCenter.Find(message, localresult.Items);
                    mLocalSubscriberCache[message.Consumers] = localresult;
                }
                if (remotresult == null || remotresult.Version != mRemoteSubscriberCenter.Version)
                {
                    remotresult         = new SubscriberCenter.SearchResult();
                    remotresult.Version = mRemoteSubscriberCenter.Version;
                    mRemoteSubscriberCenter.Find(message, remotresult.Items);
                    mRemoteSubscriberCache[message.Consumers] = remotresult;
                }
                IList <ISubscriber> local = localresult.Items;
                IList <ISubscriber> remote = remotresult.Items;
                message.Track("match consumers completed");
                if (local.Count == 0 && remote.Count == 0)
                {
                    string error = string.Format("[{0}] subscriber not fount!", message.Consumers);
                    message.ProcessError(new SRException(error));
                    Loger.Process(LogType.ERROR, error);
                    return;
                }
                ISubscriber item;
                for (int i = 0; i < local.Count; i++)
                {
                    item = local[i];
                    if (message.Pulisher == item.Name)
                    {
                        continue;
                    }
                    ProcessingMessage();
                    Message sendMsg = message.Copy();
                    sendMsg.Consumers = item.Name;

                    sendMsg.Mode = ReceiveMode.Eq;
                    message.Track("publish to " + sendMsg.Consumers + item.GetType());
                    item.Process(this, sendMsg);
                    ProcessedMessage();
                    message.Track("publish to " + sendMsg.Consumers + " completed!");
                }
                for (int i = 0; i < remote.Count; i++)
                {
                    item = remote[i];
                    ProcessingMessage();
                    Message sendMsg = message.Copy();
                    sendMsg.Consumers = item.Name;
                    sendMsg.Mode      = ReceiveMode.Eq;
                    message.Track("publish to " + sendMsg.Consumers + item.GetType());
                    item.Process(this, sendMsg);
                    message.Track("publish to " + sendMsg.Consumers + " completed!");
                    ProcessedMessage();
                }
            }
        }
        public string NewSNO(IDbAccess iDb, string tableName, string colName, List <SerialChunk> chunks)
        {
            ValiAndPreDealPara(tableName, colName, chunks);
            string key     = GeneSNOKey(tableName, colName, chunks);
            object lockobj = GetSNOLock(tableName, colName, chunks);

            lock (lockobj)
            {
                DateTime now = DateTime.Now;
                object   obj;
                bool     b = ht_SNO_nos.TryGetValue(key, out obj);

                string      cycleModel     = "";   //序列体循环模式
                SerialChunk Serialchunk    = null; //序列块
                SerialChunk Datechunk      = null; //日期循环块
                int         NoStart        = 0;    //序列块开始索引
                int         NoLen          = -1;   //序列块长度
                int         SerialTotalLen = 0;    //序列体总长度
                int         DateStart      = 0;    //日期块开始索引
                int         DateLen        = 0;    //日期块长度
                int         max            = -1;   //有效的最大序列码
                //第一次循环检查
                for (int i = 0; i < chunks.Count; i++)
                {
                    var chunk = chunks[i];
                    if (chunk.Type == "SerialNo")
                    {
                        Serialchunk = chunk;
                        cycleModel  = chunk.CycleModel;
                        for (int ii = 0; ii < chunks.Count; ii++)
                        {
                            var chu = chunks[ii];
                            if (chu.Type != "SerialNo")
                            {
                                NoStart        += chu.Len;
                                SerialTotalLen += chu.Len;
                            }
                            else
                            {
                                if (chu.Varlen)
                                {
                                    //如果序列块变长的
                                    NoLen          = -1;
                                    SerialTotalLen = -1;
                                }
                                else
                                {
                                    //序列块是定长的
                                    NoLen           = chu.Len;
                                    SerialTotalLen += chu.Len;
                                }
                            }
                        }
                    }
                    else if (chunk.Type == "DateTime" && chunk.Incyle)
                    {
                        Datechunk = chunk;
                        DateLen   = chunk.Len;
                        for (int ii = 0; ii < i; ii++)
                        {
                            var chu = chunks[ii];
                            DateStart += chu.Len;
                        }
                    }
                }
                if (!b)
                {
                    //缓存中没有当前类型的编号
                    string likeStr = "";//去后台查询已经存在的匹配编号时用

                    //第二次循环开始生成匹配串
                    for (int j = 0; j < chunks.Count; j++)
                    {
                        var chunk = chunks[j];
                        if (chunk.Type == "Text")
                        {
                            likeStr += chunk.TextVal;
                        }
                        else if (chunk.Type == "SerialNo")
                        {
                            if (chunk.Varlen)
                            {
                                likeStr += "%";
                            }
                            else
                            {
                                for (int i = 0; i < chunk.Len; i++)
                                {
                                    likeStr += "_";
                                }
                            }
                        }
                        else if (chunk.Type == "DateTime")
                        {
                            if (cycleModel == "none" || string.IsNullOrWhiteSpace(cycleModel))
                            {
                                //序列码不循环
                                for (int i = 0; i < chunk.Len; i++)
                                {
                                    likeStr += "_";
                                }
                            }
                            else
                            {
                                //序列码循环
                                if (!chunk.Incyle)
                                {
                                    //当前日期不在循环中
                                    for (int i = 0; i < chunk.Len; i++)
                                    {
                                        likeStr += "_";
                                    }
                                }
                                else
                                {
                                    //当前日期在循环中
                                    string str = now.ToString(chunk.DateFormate);
                                    if (str.Length != chunk.Len)
                                    {
                                        throw new Exception("格式化当前日期后的长度与制定的日期块所占长度不一致:[" + str + "][" + chunk.Len + "]");
                                    }
                                    likeStr += now.ToString(chunk.DateFormate);
                                }
                            }
                        }
                    }

                    //根据生成的序列号匹配串去后台查找相近的编号
                    string    sql = string.Format("select distinct {0} from {1} where {0} like '{2}'", colName, tableName, likeStr);
                    DataTable dt  = iDb.GetDataTable(sql);

                    max = FindMaxSerialNo(cycleModel, dt, now, Serialchunk, NoStart, NoLen, Datechunk, DateStart, DateLen);
                }
                else
                {
                    //缓存中有当前类型的编号
                    DataTable dt = new DataTable();
                    dt.Columns.Add(new DataColumn());
                    DataRow row = dt.NewRow();
                    row[0] = obj.ToString();
                    dt.Rows.Add(row);
                    max = FindMaxSerialNo(cycleModel, dt, now, Serialchunk, NoStart, NoLen, Datechunk, DateStart, DateLen);
                }
                //根据已经找到的有效最大序列码进行编号的自动生成
                string res = "";
                for (int j = 0; j < chunks.Count; j++)
                {
                    var chunk = chunks[j];
                    if (chunk.Type == "Text")
                    {
                        res += chunk.TextVal;
                    }
                    else if (chunk.Type == "SerialNo")
                    {
                        string no = "";
                        if (max == -1)
                        {
                            no = chunk.Start.ToString();
                            if (!chunk.Varlen)
                            {
                                no = no.PadLeft(chunk.Len, '0');
                            }
                        }
                        else
                        {
                            no = (max + chunk.Incr).ToString();
                            if (!chunk.Varlen)
                            {
                                no = no.PadLeft(chunk.Len, '0');
                            }
                        }
                        if (!chunk.Varlen)
                        {
                            if (no.Length != chunk.Len)
                            {
                                throw new Exception("生成的序列码和指定的序列码的长度不一致[" + no.ToString() + "][" + chunk.Len + "]!");
                            }
                        }
                        res += no;
                    }
                    else if (chunk.Type == "DateTime")
                    {
                        string dtstr = now.ToString(chunk.DateFormate);
                        if (dtstr.Length != chunk.Len)
                        {
                            throw new Exception("生成的日期块的长度与指定的长度不一致[" + dtstr + "][" + chunk.Len + "]!");
                        }
                        res += dtstr;
                    }
                }
                if (ht_SNO_nos.TryGetValue(key, out obj))
                {
                    ht_SNO_nos[key] = res;
                }
                else
                {
                    ht_SNO_nos.TryAdd(key, res);
                }
                return(res);
            }
        }
Example #4
0
            public List <Vector3D> FindPath(Actor actor, Vector3D Start, Vector3D Destination)
            {
                _baseX = 0; _baseY = 0; // reset to 0

                // Should only be null first time a path is requested.
                if (_curScene == null)
                {
                    _curScene = actor.CurrentScene;
                    if (!listOfPathFinderInstances.TryGetValue(_curScene.SceneSNO.Id, out mPathFinder)) // Attempts to pull the pathfinder which matches the scenes SNO from the patherlist
                    {
                        mPathFinder = new PathFinderFast(_curScene.NavMesh.WalkGrid);                   // Create a new pather, using the current scenes grid.
                        listOfPathFinderInstances.TryAdd(_curScene.SceneSNO.Id, mPathFinder);           // add it to our patherlist, with the SNO as key.
                    }

                    InitPathFinder();
                }

                // Checks if our path start location is inside current scene, if it isnt, we reset curScene and set mPathfinder to the corrent grid.
                if (!_curScene.Bounds.IntersectsWith(new System.Windows.Rect(Start.X, Start.Y, 1, 1)))
                {
                    _curScene = actor.CurrentScene;
                    if (!listOfPathFinderInstances.TryGetValue(_curScene.SceneSNO.Id, out mPathFinder))
                    {
                        mPathFinder = new PathFinderFast(_curScene.NavMesh.WalkGrid);
                        listOfPathFinderInstances.TryAdd(_curScene.SceneSNO.Id, mPathFinder);
                    }

                    InitPathFinder();
                }

                _baseX = _curScene.Position.X; //Our base location for working out world > SceneLocal coordinates.
                _baseY = _curScene.Position.Y;

                // Path's start and destination are both in same scene.
                if (_curScene.Bounds.IntersectsWith(new System.Windows.Rect(Destination.X, Destination.Y, 1, 1)))
                {
                    _destScene = _curScene;
                }
                else
                {
                    //Builds a new grid on the fly containing both the start and destination scenes. This is not really optimal, but its a trade off.
                    // Keeping grids Scene based means they can be used cross game even when laid out different in a seperate world. This keeps memory usage down substantially.
                    // Also limited to a max distance of scene > scene. Again this keeps memory usage low.
                    _destScene  = _curScene.World.QuadTree.Query <Scene>(new System.Windows.Rect(Destination.X, Destination.Y, 1, 1)).FirstOrDefault();
                    mPathFinder = new PathFinderFast(BuildOutOfSceneGrid(_curScene, _destScene, ref _baseX, ref _baseY));
                    InitPathFinder();
                }
                //2.5f is because Scene navmesh's are based on 96x96 for a 240x240 scene - Darklotus
                _startSceneLocal.X       = (int)((Start.X - _baseX) / 2.5f);
                _startSceneLocal.Y       = (int)((Start.Y - _baseY) / 2.5f);
                _destinationSceneLocal.X = (int)((Destination.X - _baseX) / 2.5f);
                _destinationSceneLocal.Y = (int)((Destination.Y - _baseY) / 2.5f);
                //Possibily add a check to ensure start/dest local coords are valid. Unneeded so far.

                nodePathList = mPathFinder.FindPath(_startSceneLocal, _destinationSceneLocal); // The actual pathfind request, the path is found here.

                vectorPathList.Clear();                                                        // Clear the previous path.

                if (nodePathList == null)
                {
                    return(vectorPathList);
                }                                                   // No Path Found.
                if (nodePathList.Count < 1)
                {
                    return(vectorPathList);
                }                                                      // Safety net Incase start/dest are the same.

                for (int i = 0; i < nodePathList.Count; i++)
                {
                    // Convert the path into world coordinates for use in Movement.
                    // TODO Objectpool maybe?
                    vectorPathList.Insert(0, new Vector3D(nodePathList[i].X * 2.5f + _baseX, nodePathList[i].Y * 2.5f + _baseY, 0));
                }
                return(vectorPathList);
            }
Example #5
0
        /// <summary>
        /// Prepares a ROM for deployment to a Locutus device.
        /// </summary>
        /// <param name="rom">The ROM being prepared.</param>
        /// <param name="updateMode">Specifies the behavior of the LUIGI file generation.</param>
        /// <returns>The fully qualified path of the prepared output data file to deploy to Locutus.</returns>
        public static string PrepareForDeployment(this IRom rom, LuigiGenerationMode updateMode)
        {
#if REPORT_PERFORMANCE
#if RECORD_PREPARE_FOR_DEPLOYMENT_VISITS
            int visits;
            if (PrepareForDeploymentVisits.TryGetValue(rom.RomPath, out visits))
            {
                PrepareForDeploymentVisits[rom.RomPath] = ++visits;
            }
            else
            {
                PrepareForDeploymentVisits[rom.RomPath] = 1;
            }
#endif // RECORD_PREPARE_FOR_DEPLOYMENT_VISITS
            var stopwatch = System.Diagnostics.Stopwatch.StartNew();
            try
            {
                var stopwatch2 = System.Diagnostics.Stopwatch.StartNew();
#endif // REPORT_PERFORMANCE
            rom.Validate();
#if REPORT_PERFORMANCE
            stopwatch2.Stop();
            _accumulatedPrepareValidateTime += stopwatch2.Elapsed;
#endif // REPORT_PERFORMANCE
            if ((updateMode == LuigiGenerationMode.Passthrough) && (rom.Format == RomFormat.Luigi))
            {
                return(rom.RomPath);
            }
#if REPORT_PERFORMANCE
            stopwatch2.Restart();
            var stopwatch3 = System.Diagnostics.Stopwatch.StartNew();
#endif // REPORT_PERFORMANCE
            var jzIntvConfiguration = SingleInstanceApplication.Instance.GetConfiguration <INTV.JzIntv.Model.Configuration>();
            var converterApps       = jzIntvConfiguration.GetConverterApps(rom, RomFormat.Luigi);
            if (!converterApps.Any())
            {
                converterApps = new[] { new Tuple <string, RomFormat>(JustCopy, RomFormat.Luigi) };
            }
            var converterApp = converterApps.First(); // rom.GetConverterApp(jzIntvConfiguration);
            if ((converterApp.Item1 != JustCopy) && (string.IsNullOrEmpty(converterApp.Item1) || !System.IO.File.Exists(converterApp.Item1)) && (rom.Format != RomFormat.Luigi))
            {
                var message = string.Format(System.Globalization.CultureInfo.CurrentCulture, Resources.Strings.RomToLuigiFailed_ConversionToolNotFound_Error_Format, converterApp);
                throw new LuigiFileGenerationException(message, Resources.Strings.RomToLuigiFailed_ConversionToolNotFound_Error_Description);
            }
#if REPORT_PERFORMANCE
            stopwatch3.Stop();
            _accumulatedPrepareConverterAppsTime += stopwatch3.Elapsed;
            stopwatch3.Restart();
#endif // REPORT_PERFORMANCE
            var romStagingArea   = SingleInstanceApplication.Instance.GetConfiguration <Configuration>().RomsStagingAreaPath;
            var stagingAreaPath  = rom.GetStagingAreaPath(romStagingArea);
            var cachedRomPath    = rom.GetCachedRomFilePath(stagingAreaPath);
            var cachedConfigPath = rom.GetCachedConfigFilePath(stagingAreaPath);
            var luigiFile        = rom.GetOutputFilePath(stagingAreaPath, ProgramFileKind.LuigiFile);
#if REPORT_PERFORMANCE
            stopwatch3.Stop();
            _accumulatedPrepareStagingTime += stopwatch3.Elapsed;
            stopwatch3.Restart();
#endif // REPORT_PERFORMANCE

            bool createLuigiFile = true;
            bool changed;
            bool isSourceFileInCache = rom.IsInCache(stagingAreaPath, out changed);
#if REPORT_PERFORMANCE
            stopwatch3.Stop();
            _accumulatedPrepareCacheLookupTime += stopwatch3.Elapsed;
#endif // REPORT_PERFORMANCE

#if REPORT_PERFORMANCE
            stopwatch2.Stop();
            _accumulatedPrepareSetupTime += stopwatch2.Elapsed;

            stopwatch2.Restart();
#endif // REPORT_PERFORMANCE
            var luigiHeader = rom.GetLuigiHeader();
            if (luigiHeader != null)
            {
                // If the given ROM is already a LUIGI file, see if we can determine whether it's already in our cache.
#if REPORT_OLD_LUIGI_FILES
                System.Diagnostics.Debug.Assert(luigiHeader.Version > 0, "Really, you've got some OLD LUIGI files. Delete them.");
#endif // REPORT_OLD_LUIGI_FILES
                var crc24 = INTV.Core.Utility.Crc24.OfFile(rom.RomPath);
                var size  = new System.IO.FileInfo(rom.RomPath).Length;
                var entry = CacheIndex.Find(crc24, (uint)size);
                isSourceFileInCache = entry != null;
                if (isSourceFileInCache)
                {
                    // Cases have been found in which, by moving files around on disk, the staging area path can change.
                    // The result of this, though, is that the *new* path in the cache is different than the extant one
                    // found in the cache. In this case, if the entry's location is different than the newly computed
                    // one, ignore the cache entry and make a new one by acting as if the file is not in the cache.
                    // FIXME This is a lazy fix. A better fix would be to remove the cached files and existing cache
                    // entry and re-add this new one. Or patch up the existing entry. Hell, maybe scrap the entire cache
                    // altogether as it's a bit of a bug farm and creating LUIGI files isn't all *that* expensive.
                    var stagingDirectory   = System.IO.Path.GetFileName(stagingAreaPath);
                    var stagingPathChanged = !entry.LuigiPath.StartsWith(stagingDirectory);
                    if (stagingPathChanged)
                    {
                        isSourceFileInCache = false;
                    }
                    else
                    {
                        luigiFile     = System.IO.Path.Combine(romStagingArea, entry.LuigiPath);
                        cachedRomPath = System.IO.Path.Combine(romStagingArea, entry.RomPath);
                        if (!string.IsNullOrEmpty(entry.CfgPath))
                        {
                            cachedConfigPath = System.IO.Path.Combine(romStagingArea, entry.CfgPath);
                        }
                    }
                }
            }
#if REPORT_PERFORMANCE
            stopwatch2.Stop();
            _accumulatedPrepareLuigiHeaderTime += stopwatch2.Elapsed;

            stopwatch2.Restart();
#endif // REPORT_PERFORMANCE

            if (isSourceFileInCache)
            {
                createLuigiFile = changed || !System.IO.File.Exists(luigiFile);
            }
            if (!isSourceFileInCache || changed)
            {
                cachedRomPath.ClearReadOnlyAttribute();
                cachedConfigPath.ClearReadOnlyAttribute();
                System.IO.File.Copy(rom.RomPath, cachedRomPath, true);
                if (!string.IsNullOrWhiteSpace(cachedConfigPath) && !string.IsNullOrEmpty(rom.ConfigPath) && System.IO.File.Exists(rom.ConfigPath) && (rom.ConfigPath != rom.RomPath))
                {
                    System.IO.File.Copy(rom.ConfigPath, cachedConfigPath, true);
                }
                else if ((string.IsNullOrEmpty(rom.ConfigPath) || !System.IO.File.Exists(rom.ConfigPath)) && System.IO.File.Exists(cachedConfigPath))
                {
                    // The ROM's configuration file path doesn't exist, but there's one in the cache. Remove it.
                    FileUtilities.DeleteFile(cachedConfigPath, false, 2);
                    cachedConfigPath = null; // this is OK, because the ClearReadOnlyAttribute() extension method is null-safe
                }
                cachedRomPath.ClearReadOnlyAttribute();
                cachedConfigPath.ClearReadOnlyAttribute();
            }
#if REPORT_PERFORMANCE
            stopwatch2.Stop();
            _accumulatedPrepareCachedChangedTime += stopwatch2.Elapsed;

            stopwatch2.Restart();
#endif // REPORT_PERFORMANCE

            if (createLuigiFile || ((updateMode == LuigiGenerationMode.FeatureUpdate) || (updateMode == LuigiGenerationMode.Reset)))
            {
                var argument = "\"" + cachedRomPath + "\"" + " \"" + luigiFile + "\"";
                var result   = -1;
                if (JustCopy == converterApp.Item1)
                {
                    System.IO.File.Copy(rom.RomPath, luigiFile, true);
                    result = 0;
                }
                else
                {
                    result = INTV.Shared.Utility.RunExternalProgram.Call(converterApp.Item1, argument, stagingAreaPath);
                }
                if (result == 0)
                {
                    if (!System.IO.File.Exists(luigiFile))
                    {
                        var message = string.Format(System.Globalization.CultureInfo.CurrentCulture, Resources.Strings.RomToLuigiFailed_OutputFileNotFound_Error_Format, rom.RomPath, System.IO.Path.GetFileNameWithoutExtension(luigiFile));
                        throw new LuigiFileGenerationException(message, Resources.Strings.RomToLuigiFailed_OutputFileNotFound_Error_Description_Format);
                    }
                    else if ((new System.IO.FileInfo(luigiFile)).Length > Device.TotalRAMSize)
                    {
                        var message = string.Format(System.Globalization.CultureInfo.CurrentCulture, Resources.Strings.RomToLuigiFailed_TooLarge_Error_Message_Format, rom.RomPath, luigiFile);
                        throw new LuigiFileGenerationException(message, Resources.Strings.RomToLuigiFailed_TooLarge_Description);
                    }

                    var description = INTV.Shared.Model.Program.ProgramCollection.Roms.FirstOrDefault(d => rom.IsEquivalentTo(d.Rom, RomComparerStrict.Default));
                    if (description != null)
                    {
                        LuigiFeatureFlags features = LuigiFeatureFlags.None;
#if DEBUG
                        var complainAboutOldLuigiFile = false;
#endif // DEBUG
                        luigiHeader = LuigiFileHeader.GetHeader(luigiFile);
                        features    = description.Features.LuigiFeaturesLo;
#if DEBUG
                        var isRecognizedRom     = !description.Features.GeneralFeatures.HasFlag(GeneralFeatures.UnrecognizedRom);
                        var hasFlagsFromCfgFile = luigiHeader.Features.HasFlag(LuigiFeatureFlags.FeatureFlagsExplicitlySet);
                        complainAboutOldLuigiFile = isRecognizedRom && hasFlagsFromCfgFile && ((luigiHeader.Features & ~LuigiFeatureFlags.FeatureFlagsExplicitlySet) != features);
#endif // DEBUG
#if DEBUG
                        if (complainAboutOldLuigiFile)
                        {
                            var message = "Known ROM has explicit flags from utility that are different than those set by LUI:\n\n";
                            message += "  LUI: " + features + "\n";
                            message += "  Utility: " + (luigiHeader.Features & ~LuigiFeatureFlags.FeatureFlagsExplicitlySet);
                            INTV.Shared.View.OSMessageBox.Show(message, "Feature Flags Inconsistency");
                        }
#endif // DEBUG
                        if (luigiHeader.WouldModifyFeatures(features, updateMode == LuigiGenerationMode.FeatureUpdate))
                        {
                            using (var file = System.IO.File.Open(luigiFile, System.IO.FileMode.Open, System.IO.FileAccess.ReadWrite))
                            {
                                luigiHeader.UpdateFeatures(features, updateMode == LuigiGenerationMode.FeatureUpdate);
                                file.Seek(0, System.IO.SeekOrigin.Begin);
                                luigiHeader.Serialize(new Core.Utility.BinaryWriter(file));
                            }
                        }
                    }
                    try
                    {
                        var cacheIndexEntry = new CacheIndexEntry(rom, cachedRomPath);
                        CacheIndex.Instance.AddEntry(cacheIndexEntry);
                    }
                    catch (Exception e)
                    {
                        var message = string.Format(System.Globalization.CultureInfo.CurrentCulture, Resources.Strings.PrepareForDeployment_ErrorCreatingCacheEntryFormat, rom.RomPath);
                        throw new LuigiFileGenerationException(message, e.Message, e);
                    }
                }
                else
                {
                    var message     = string.Format(System.Globalization.CultureInfo.CurrentCulture, Resources.Strings.RomToLuigiFailed_InvalidOperation_Error_Message_Format, result);
                    var description = string.Format(System.Globalization.CultureInfo.CurrentCulture, Resources.Strings.RomToLuigiFailed_Error_Description_Format, converterApp);
                    throw new LuigiFileGenerationException(message, description);
                }
            }
            else
            {
                // If this is a different ROM that produces the same LUIGI, add an entry.
                var crc24 = INTV.Core.Utility.Crc24.OfFile(luigiFile);
                var size  = (uint)(new System.IO.FileInfo(luigiFile)).Length;
                if (CacheIndex.Find(crc24, size) == null)
                {
                    try
                    {
                        var cacheIndexEntry = new CacheIndexEntry(rom, cachedRomPath);
                        CacheIndex.Instance.AddEntry(cacheIndexEntry);
                    }
                    catch (Exception e)
                    {
                        var message = string.Format(System.Globalization.CultureInfo.CurrentCulture, Resources.Strings.PrepareForDeployment_ErrorCreatingCacheEntryFormat, rom.RomPath);
                        throw new LuigiFileGenerationException(message, e.Message, e);
                    }
                }
            }
            ////catch (System.IO.PathTooLongException e)
            ////catch (System.IO.IOException e)
            ////catch (UnauthorizedAccessException e)
            ////catch (InvalidOperationException e)
            ////catch (LuigiFileGenerationException e)
#if REPORT_PERFORMANCE
            stopwatch2.Stop();
            _accumulatedPrepareLuigiUpdateTime += stopwatch2.Elapsed;
#endif // REPORT_PERFORMANCE

            if (string.IsNullOrEmpty(luigiFile) || !System.IO.File.Exists(luigiFile))
            {
                var message     = string.Format(System.Globalization.CultureInfo.CurrentCulture, Resources.Strings.RomToLuigiFailed_Error_Description_Format, rom);
                var description = string.Format(System.Globalization.CultureInfo.CurrentCulture, Resources.Strings.RomToLuigiFailed_InvalidOutputFileFormat, luigiFile);
                throw new LuigiFileGenerationException(message, description);
            }

#if REPORT_PERFORMANCE
            stopwatch.Stop();
#endif // REPORT_PERFORMANCE
            return(luigiFile);

#if REPORT_PERFORMANCE
        }

        finally
        {
            stopwatch.Stop();
            _accumulatedPrepareTime += stopwatch.Elapsed;
        }
#endif // REPORT_PERFORMANCE
        }
 public int GetIntegerValue(double x, double y) =>
 _RealGrassland.TryGetValue(Mars.Interfaces.Environment.Position.CreatePosition(x, y), out var value) ? Convert.ToInt32(value) : 0;