Exemplo n.º 1
0
        internal static bool PlayOriginalGame(GameIndex game, bool playMP = false)
        {
            (bool success, string gameExe, string gamePath) =
                CheckAndReturnFinalGameExeAndGamePath(game, playingOriginalGame: true, playMP);
            if (!success)
            {
                return(false);
            }
            Paths.CreateOrClearTempPath(Paths.StubCommTemp);

            if (game is GameIndex.Thief1 or GameIndex.Thief2)
            {
                GameConfigFiles.FixCharacterDetailLine(gamePath);
            }
            SetUsAsSelector(game, gamePath, PlaySource.OriginalGame);

#if !ReleaseBeta && !ReleasePublic
            string args = Config.ForceWindowed ? "+force_windowed" : "";
#else
            string args = "";
#endif
            string workingPath = Config.GetGamePath(game);
            var    sv          = GetSteamValues(game, playMP);
            if (sv.Success)
            {
                (_, gameExe, workingPath, args) = sv;
            }

            WriteStubCommFile(null, gamePath, originalT3: game == GameIndex.Thief3);

            StartExe(gameExe, workingPath, args);

            return(true);
        }
Exemplo n.º 2
0
        internal static bool OpenFMInEditor(FanMission fm)
        {
            #region Checks (specific to DromEd)

            // This should never happen because our menu item is supposed to be hidden for Thief 3 FMs.
            if (!GameIsDark(fm.Game))
            {
                Log("FM game type is not a Dark Engine game.\r\n" +
                    "FM: " + (!fm.Archive.IsEmpty() ? fm.Archive : fm.InstalledDir) + "\r\n" +
                    "fm.Game was: " + fm.Game, stackTrace: true);
                Dialogs.ShowError(ErrorText.FMGameTypeIsNotDark);
                return(false);
            }

            GameIndex gameIndex = GameToGameIndex(fm.Game);

            string gamePath = Config.GetGamePath(gameIndex);
            if (gamePath.IsEmpty())
            {
                Log("Game path is empty for " + gameIndex, stackTrace: true);
                Dialogs.ShowError(gameIndex + ":\r\n" + ErrorText.GamePathEmpty);
                return(false);
            }

            string editorExe = Config.GetEditorExe_FromDisk(gameIndex);
            if (editorExe.IsEmpty())
            {
                Log("Editor executable not found.\r\n" +
                    "FM:" + (!fm.Archive.IsEmpty() ? fm.Archive : fm.InstalledDir) + "\r\n" +
                    "Editor executable: " + editorExe);
                Dialogs.ShowError(fm.Game == Game.SS2
                    ? LText.AlertMessages.ShockEd_ExecutableNotFound
                    : LText.AlertMessages.DromEd_ExecutableNotFound);
                return(false);
            }

            #endregion

            // Just in case, and for consistency
            Paths.CreateOrClearTempPath(Paths.StubCommTemp);

            if (gameIndex is GameIndex.Thief1 or GameIndex.Thief2)
            {
                GameConfigFiles.FixCharacterDetailLine(gamePath);
            }
            // We don't need to do this here, right?
            SetUsAsSelector(gameIndex, gamePath, PlaySource.Editor);

            // Since we don't use the stub currently, set this here
            // NOTE: DromEd game mode doesn't even work for me anymore. Black screen no matter what. So I can't test if we need languages.
            GameConfigFiles.SetCamCfgLanguage(gamePath, "");

            // Why not
            GenerateMissFlagFileIfRequired(fm);

            // We don't need the stub for DromEd, cause we don't need to pass anything except the fm folder
            StartExe(editorExe, gamePath, "-fm=\"" + fm.InstalledDir + "\"");

            return(true);
        }
Exemplo n.º 3
0
        public IActionResult SearchGames(string searchPattern)
        {
            //Matching all letters to lowercase (the same thing is happening to game title during comparison)
            searchPattern = searchPattern.ToLower();

            var games = _games.GetAll();

            if (!string.IsNullOrEmpty(searchPattern))
            {
                games = games.Where(game => game.Title.ToLower().Contains(searchPattern));
            }

            var listingResults = games
                                 .Select(result => new Game
            {
                Id          = result.Id,
                ImageUrl    = result.ImageUrl,
                Title       = result.Title,
                Genre       = result.Genre,
                ReleaseYear = result.ReleaseYear,
                Rating      = result.Rating,
                Platform    = result.Platform
            });

            var modelGames = listingResults.ToList();
            var model      = new GameIndex
            {
                Games = modelGames
            };

            return(View(model));
        }
Exemplo n.º 4
0
        GetDarkFMLanguage(GameIndex game, string fmArchive, string fmInstalledDir)
        {
            string sLanguage;
            bool   bForceLanguage;

            var(_, fmLanguage, _, _, _) = GameConfigFiles.GetInfoFromCamModIni(Config.GetGamePath(game), out _, langOnly: true);

            // bForceLanguage gets set to something specific in every possible case, effectively meaning the
            // fm_language_forced value is always ignored. Weird, but FMSel's code does exactly this, so meh?
            // NOTE: Although I'm using FMSel from ND 1.26 as a reference, ND 1.27's is exactly the same.
            string fmInstPath = Path.Combine(Config.GetFMInstallPath(game), fmInstalledDir);

            if (!fmLanguage.IsEmpty())
            {
                var fmSupportedLangs = GetFMSupportedLanguages(fmArchive, fmInstPath, earlyOutOnEnglish: false);
                if (fmSupportedLangs.ContainsI(fmLanguage))
                {
                    // FMSel doesn't set this because it's already getting it from the game meaning it's set
                    // already, but we have to set it ourselves because we're getting it manually
                    sLanguage = fmLanguage;

                    bForceLanguage = true;
                }
                else
                {
                    // language not supported, use fallback
                    sLanguage      = fmSupportedLangs.Count > 0 ? fmSupportedLangs[0] : "";
                    bForceLanguage = false;
                }
            }
            else
            {
                /*
                 * So, if I'm reading the API notes right, it looks like NewDark actually picks the right language
                 * automatically if it can find it in DARKINST.CFG. We set sLanguage to either:
                 * -force that language to be used if it's available (otherwise we use the below crappily-guessed
                 * fallback), or
                 * -give it a crappily-guessed fallback value so that if NewDark can't find a language, we at least
                 * have SOMETHING to give it so text won't be blank, even though it's likely it'll be the wrong
                 * language if it isn't English.
                 */

                // FMSel's comment:
                // determine FM default language (used if the FM doesn't support the language set in dark by the "language" cfg var)

                // FMSel's comment:
                // determine if FM has languages defined, if it does and english is among them, then english is the fallback
                // if english is not among them then pick another, if no languages are found then no fallback language will
                // be defined

                var langs = GetFMSupportedLanguages(fmArchive, fmInstPath, earlyOutOnEnglish: true);

                // Use first available language (which will be English if English is available)
                sLanguage      = langs.Count == 0 ? "" : langs[0];
                bForceLanguage = false;
            }

            return(sLanguage, bForceLanguage);
        }
 internal static string GetLocalizedGamePlayOriginalText(GameIndex gameIndex)
 {
     return
         (gameIndex == GameIndex.Thief1 ? Misc.LText.PlayOriginalGameMenu.Thief1_PlayOriginal:
          gameIndex == GameIndex.Thief2 ? Misc.LText.PlayOriginalGameMenu.Thief2_PlayOriginal:
          gameIndex == GameIndex.Thief3 ? Misc.LText.PlayOriginalGameMenu.Thief3_PlayOriginal:
          Misc.LText.PlayOriginalGameMenu.SystemShock2_PlayOriginal);
 }
 internal static string GetLocalizedGameNameColon(GameIndex gameIndex)
 {
     return
         (gameIndex == GameIndex.Thief1 ? Misc.LText.Global.Thief1_Colon:
          gameIndex == GameIndex.Thief2 ? Misc.LText.Global.Thief2_Colon:
          gameIndex == GameIndex.Thief3 ? Misc.LText.Global.Thief3_Colon:
          Misc.LText.Global.SystemShock2_Colon);
 }
 internal static string GetShortLocalizedGameName(GameIndex gameIndex)
 {
     return
         (gameIndex == GameIndex.Thief1 ? Misc.LText.Global.Thief1_Short:
          gameIndex == GameIndex.Thief2 ? Misc.LText.Global.Thief2_Short:
          gameIndex == GameIndex.Thief3 ? Misc.LText.Global.Thief3_Short:
          Misc.LText.Global.SystemShock2_Short);
 }
Exemplo n.º 8
0
        //public IActionResult Index()
        //{
        //    var gameModels = _games.GetAll();

        //    var listingResults = gameModels
        //        .Select(result => new Game
        //        {
        //            Id = result.Id,
        //            ImageUrl = result.ImageUrl,
        //            Title = result.Title,
        //            Genre = result.Genre,
        //            ReleaseYear = result.ReleaseYear,
        //            Rating = result.Rating,
        //            Platform = result.Platform

        //        });

        //    var model = new GameIndex()
        //    {
        //        Games = listingResults
        //    };

        //    return View(model);
        //}


        public IActionResult Index(string sortOption)
        {
            var gameModels = _games.GetAll();

            var listingResults = gameModels
                                 .Select(result => new Game
            {
                Id          = result.Id,
                ImageUrl    = result.ImageUrl,
                Title       = result.Title,
                Genre       = result.Genre,
                ReleaseYear = result.ReleaseYear,
                Rating      = result.Rating,
                Platform    = result.Platform
            });

            var modelGames = listingResults.ToList();
            var model      = new GameIndex
            {
                Games = modelGames
            };

            switch (sortOption)
            {
            case "Title":
                model.Games = modelGames.OrderBy(game => game.Title);
                break;

            case "Genre":
                model.Games = modelGames.OrderBy(game => game.Genre);
                break;

            case "Platform":
                model.Games = modelGames.OrderBy(game => game.Rating);
                break;

            case "ReleaseYear":
                model.Games = modelGames.OrderByDescending(game => game.ReleaseYear);
                break;

            case "Rating":
                model.Games = modelGames.OrderByDescending(game => game.Rating);
                break;

            default:
                model.Games = modelGames;
                break;
            }

            return(View(model));
        }
Exemplo n.º 9
0
        /// <summary>
        /// Remove our footprints from any config files we may have temporarily stomped on.
        /// If it fails, oh well. It's no worse than before, we just end up with ourselves as the loader,
        /// and the user will get a message about that if they start the game later.
        /// </summary>
        /// <param name="perGameGoFlags">
        /// An array of bools, of length <see cref="SupportedGameCount"/>. Each bool says whether to go ahead and
        /// do the reset work for that game. If false, we skip it.
        /// </param>
        // @CAN_RUN_BEFORE_VIEW_INIT
        internal static void ResetGameConfigTempChanges(bool[]?perGameGoFlags = null)
        {
            AssertR(perGameGoFlags == null || perGameGoFlags.Length == SupportedGameCount,
                    nameof(perGameGoFlags) + " length does not match " + nameof(SupportedGameCount));

            for (int i = 0; i < SupportedGameCount; i++)
            {
                GameIndex gameIndex = (GameIndex)i;
                string    gameExe   = Config.GetGameExe(gameIndex);
                try
                {
                    if ((perGameGoFlags == null || perGameGoFlags[i]) &&
                        // Only try to un-stomp the configs for the game if the game was actually specified
                        !gameExe.IsWhiteSpace())
                    {
                        // For Dark, we need to know if the game exe itself actually exists.
                        if (GameIsDark(gameIndex) && File.Exists(gameExe))
                        {
                            string gamePath = Config.GetGamePath(gameIndex);
                            SetCamCfgLanguage(gamePath, "");
                            SetDarkFMSelector(gameIndex, gamePath, resetSelector: true);
                            if (gameIndex is GameIndex.Thief1 or GameIndex.Thief2)
                            {
                                FixCharacterDetailLine(gamePath);
                            }
                        }
                        else
                        {
                            // For Thief 3, we actually just want to know if SneakyOptions.ini exists. The game
                            // itself existing is not technically a requirement.
                            string soIni = Paths.GetSneakyOptionsIni();
                            if (!soIni.IsEmpty() && File.Exists(soIni))
                            {
                                SetT3FMSelector(resetSelector: true);
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    Log("Exception trying to unset temp config values\r\n" +
                        "GameIndex: " + gameIndex + "\r\n" +
                        "GameExe: " + gameExe,
                        ex);

                    Dialogs.ShowError("Error attempting to restore previous game config file settings.\r\n" +
                                      "Game: " + gameIndex + "\r\n" +
                                      "Game exe: " + gameExe);
                }
            }
        }
Exemplo n.º 10
0
        CheckAndReturnFinalGameExeAndGamePath(GameIndex gameIndex, bool playingOriginalGame, bool playMP = false)
        {
            var failed = (Success : false, GameExe : "", GamePath : "");

            string gameName = GetLocalizedGameName(gameIndex);

            string gameExe = Config.GetGameExe(gameIndex);

            #region Fail if game path is blank

            string gamePath = Config.GetGamePath(gameIndex);
            if (gamePath.IsEmpty())
            {
                Log("Game path is empty for " + gameIndex, stackTrace: true);
                Dialogs.ShowError(gameName + ":\r\n" + ErrorText.GamePathEmpty);
                return(failed);
            }

            #endregion

            if (playMP)
            {
                gameExe = Path.Combine(gamePath, Paths.T2MPExe);
            }

            #region Exe: Fail if blank or not found

            if (gameExe.IsEmpty() || !File.Exists(gameExe))
            {
                string exeNotFoundMessage = playingOriginalGame
                    ? LText.AlertMessages.Play_ExecutableNotFound
                    : LText.AlertMessages.Play_ExecutableNotFoundFM;
                Dialogs.ShowError(gameName + ":\r\n" + exeNotFoundMessage);
                return(failed);
            }

            #endregion

            #region Exe: Fail if already running

            if (GameIsRunning(gameExe, checkAllGames: true))
            {
                Dialogs.ShowAlert(LText.AlertMessages.Play_AnyGameIsRunning, LText.AlertMessages.Alert);
                return(failed);
            }

            #endregion

            return(true, gameExe, gamePath);
        }
Exemplo n.º 11
0
        /*
         * I'm not completely comfortable putting these in here... They're sort of in a no-man's land between
         * belonging here or belonging outside.
         * Arguments for being in here:
         * -They depend on the game paths which are in here
         * -They conceptually go with the other Get*Exe() methods
         * Arguments for being outside:
         * -The actual filenames at the end of their paths are constants from the static paths class
         * -They access the file system, which feels a bit weird for a config object to do. I feel like the methods
         * in here should all be "instant" and operate on memory only and not do weird things you don't expect.
         * (that's the main reason for my discomfort really)
         *
         * I'm just going to append "_FromDisk" to their names, document them, and call it serviceable.
         */

        /// <summary>
        /// Returns the full path of the editor for <paramref name="game"/> if and only if it exists on disk.
        /// Otherwise, returns the empty string. It will also return the empty string if <paramref name="game"/>
        /// is not Dark.
        /// </summary>
        /// <param name="game"></param>
        /// <returns></returns>
        internal string GetEditorExe_FromDisk(GameIndex game)
        {
            string gamePath;

            if (!GameIsDark(game) || (gamePath = GetGamePath(game)).IsEmpty())
            {
                return("");
            }

            string exe = game == GameIndex.SS2 ? Paths.ShockEdExe : Paths.DromEdExe;

            return(TryCombineFilePathAndCheckExistence(gamePath, exe, out string fullPathExe)
                ? fullPathExe
                : "");
        }
Exemplo n.º 12
0
        private void AutodetectGameIni(GameIndex game, TextBox textBox)
        {
            string iniFile = ImportType == ImportType.NewDarkLoader ? Paths.NewDarkLoaderIni : Paths.FMSelIni;

            string fmsPath = Config.GetFMInstallPath(game);

            if (fmsPath.IsWhiteSpace())
            {
                textBox.Text = "";
            }
            else
            {
                textBox.Text = TryCombineFilePathAndCheckExistence(fmsPath, iniFile, out string iniFileFull)
                    ? iniFileFull
                    : "";
            }
        }
Exemplo n.º 13
0
 public void SetGameIdx(int idx)
 {
     if (idx < 0 || idx > 3)
     {
         Debug.LogError("idx范围超过 SetGameIdx " + idx);
         idx = 0;
     }
     if ((int)mGameIdx != idx)
     {
         mGameIdx = (GameIndex)idx;
         ResetData();
     }
     else
     {
         mGameIdx = (GameIndex)idx;
     }
     // mTitle.text = LocalizationManager.Instance.GetValue(titleList[idx]);
     mTitle.SetKey(titleList[idx]);
     ViewManager.ReplaceView(objList[idx], gameObject.name);
 }
Exemplo n.º 14
0
        internal static string GetEditorExe(GameIndex game)
        {
            if (!GameIsDark(game))
            {
                return("");
            }

            string gamePath = Config.GetGamePath(game);

            if (gamePath.IsEmpty())
            {
                return("");
            }

            string exe = game == SS2 ? Paths.ShockEdExe : Paths.DromEdExe;

            return(TryCombineFilePathAndCheckExistence(gamePath, exe, out string fullPathExe)
                ? fullPathExe
                : "");
        }
Exemplo n.º 15
0
        private static void SetUsAsSelector(GameIndex game, string gamePath, PlaySource playSource)
        {
            bool success = GameIsDark(game)
                ? GameConfigFiles.SetDarkFMSelector(game, gamePath)
                : GameConfigFiles.SetT3FMSelector();

            if (!success)
            {
                Log("Unable to set us as the selector for " + Config.GetGameExe(game) + " (" +
                    (GameIsDark(game) ? nameof(GameConfigFiles.SetDarkFMSelector) : nameof(GameConfigFiles.SetT3FMSelector)) +
                    " returned false)\r\n" +
                    "Source: " + playSource,
                    stackTrace: true);

                Dialogs.ShowError(
                    "Failed to set AngelLoader as the FM selector.\r\n\r\n" +
                    "Game: " + game + "\r\n" +
                    "Game exe: " + Config.GetGameExe(game) + "\r\n" +
                    "Source: " + playSource + "\r\n" +
                    "");
            }
        }
Exemplo n.º 16
0
        GetSteamValues(GameIndex game, bool playMP)
        {
            // Multiplayer means starting Thief2MP.exe, so we can't really run it through Steam because Steam
            // will start Thief2.exe
            if (!playMP &&
                !GetGameSteamId(game).IsEmpty() && Config.GetUseSteamSwitch(game) &&
                Config.LaunchGamesWithSteam && !Config.SteamExe.IsEmpty() && File.Exists(Config.SteamExe))
            {
                string?workingPath = Path.GetDirectoryName(Config.SteamExe);

                if (workingPath.IsEmpty())
                {
                    return(false, "", "", "");
                }

                string args = "-applaunch " + GetGameSteamId(game);

                return(true, Config.SteamExe, workingPath, args);
            }
            else
            {
                return(false, "", "", "");
            }
        }
Exemplo n.º 17
0
 internal string GetFMInstallPath(GameIndex index) => FMInstallPaths[(uint)index];
Exemplo n.º 18
0
 internal void SetGamePath(GameIndex index, string value) => GamePaths[(uint)index] = value;
Exemplo n.º 19
0
 internal string GetGamePath(GameIndex index) => GamePaths[(uint)index];
Exemplo n.º 20
0
 internal void SetGameExe(GameIndex index, string value) => GameExes[(uint)index] = value;
Exemplo n.º 21
0
 internal string GetGameExe(GameIndex index) => GameExes[(uint)index];
Exemplo n.º 22
0
 internal void SetStartupAlwaysStartSelector(GameIndex index, bool value) => StartupAlwaysStartSelector[(uint)index] = value;
Exemplo n.º 23
0
 internal bool GetStartupAlwaysStartSelector(GameIndex index) => StartupAlwaysStartSelector[(uint)index];
Exemplo n.º 24
0
 internal void SetStartupFMSelectorLines(GameIndex index, List <string> value) => StartupFMSelectorLines[(uint)index] = value;
Exemplo n.º 25
0
 internal List <string> GetStartupFMSelectorLines(GameIndex index) => StartupFMSelectorLines[(uint)index];
Exemplo n.º 26
0
 internal void SetUseSteamSwitch(GameIndex index, bool value) => UseSteamSwitches[(uint)index] = value;
Exemplo n.º 27
0
 internal bool GetUseSteamSwitch(GameIndex index) => UseSteamSwitches[(uint)index];
Exemplo n.º 28
0
 internal void SetGameEditorDetected(GameIndex index, bool value) => GameEditorDetected[(uint)index] = value;
Exemplo n.º 29
0
        internal static Error TryGetGameVersion(GameIndex game, out string version)
        {
            version = "";

            string gameExe = GameIsDark(game) ? Config.GetGameExe(game) : Path.Combine(Config.GetGamePath(Thief3), "Sneaky.dll");

            if (gameExe.IsWhiteSpace())
            {
                return(Error.GameExeNotSpecified);
            }
            if (!File.Exists(gameExe))
            {
                return(Error.GameExeNotFound);
            }

            FileStream?  fs = null;
            BinaryReader?br = null;

            try
            {
                fs = new FileStream(gameExe, FileMode.Open, FileAccess.Read);
                br = new BinaryReader(fs, Encoding.ASCII, leaveOpen: false);

                long streamLen = br.BaseStream.Length;

                if (streamLen > int.MaxValue)
                {
                    return(Error.ExeIsLargerThanInt);
                }

                // Search starting at 88% through the file: 91% (average location) plus some wiggle room (fastest)
                long pos       = GetValueFromPercent(88.0d, streamLen);
                long byteCount = streamLen - pos;
                br.BaseStream.Position = pos;
                byte[] bytes = new byte[byteCount];
                br.Read(bytes, 0, (int)byteCount);
                int verIndex = bytes.IndexOfByteSequence(ProductVersionBytes);

                // Fallback: search the whole file - still fast, but not as fast
                if (verIndex == -1)
                {
                    br.BaseStream.Position = 0;
                    bytes = new byte[streamLen];
                    br.Read(bytes, 0, (int)streamLen);
                    verIndex = bytes.IndexOfByteSequence(ProductVersionBytes);
                    if (verIndex == -1)
                    {
                        return(Error.GameVersionNotFound);
                    }
                }

                // Init with non-null values so we don't start out with two nulls and early-out before we do anything
                byte[] null2 = { 255, 255 };
                for (int i = verIndex + ProductVersionBytes.Length; i < bytes.Length; i++)
                {
                    if (null2[0] == '\0' && null2[1] == '\0')
                    {
                        break;
                    }
                    null2[0] = null2[1];
                    null2[1] = bytes[i];
                    if (bytes[i] > 0)
                    {
                        version += ((char)bytes[i]).ToString();
                    }
                }
            }
            catch (Exception ex)
            {
                Log("Exception reading/searching game exe for version string", ex);
                version = "";
                return(Error.GameExeReadFailed);
            }
            finally
            {
                br?.Dispose();
                fs?.Dispose();
            }

            return(Error.None);
        }
Exemplo n.º 30
0
 internal void SetFMInstallPath(GameIndex index, string value) => FMInstallPaths[(uint)index] = value;