Beispiel #1
0
        public RequestResult <string> Play()
        {
            List <PlayerInfo> players = profile.PlayerData;

            for (int i = 0; i < players.Count; i++)
            {
                players[i].PlayerID = i;
            }
            RequestResult <String> result = new RequestResult <String>();

            List <HandlerContext> contexts = new List <HandlerContext>();

            for (int i = 0; i < players.Count; i++)
            {
                PlayerInfo player = players[i];

                HandlerContext context = handlerManager.HandlerData.CreateContext(profile, player, hasKeyboardPlayer);
                contexts.Add(context);

                context.PlayerID = player.PlayerID;

                List <HandlerModule> modules = player.Modules;
                for (int j = 0; j < modules.Count; j++)
                {
                    modules[j].PrePlayPlayer(i, context);
                }
            }

            // get all the SymlinkData from each players IOModule
            // and start the StartGame application to symlink them
            List <SymlinkGameData> symData = new List <SymlinkGameData>();

            for (int i = 0; i < players.Count; i++)
            {
                PlayerInfo      player = players[i];
                IOModule        mod    = GetModule <IOModule>(player);
                SymlinkGameData data   = mod.SymlinkData;
                symData.Add(data);
            }
            StartGameData symStartData = StartGameUtil.BuildSymlinkGameData(symData.ToArray());

            // check if we need to kill mutexes
            bool killingMutexes = false;

            if (handlerManager.HandlerData.KillMutex?.Length > 0)
            {
                // need to also kill mutexes
                killingMutexes = true;
                StartGameData scanKillData = StartGameUtil.BuildScanKillMutexData(Path.GetFileNameWithoutExtension(userGame.ExePath), players.Count, handlerManager.HandlerData.KillMutex);
                StartGameUtil.RunMultipleTasks(new StartGameData[] { symStartData, scanKillData }, true);

                // wait for confirmation file that the folders were symlinked
                // (RunMultipleTasks doesnt wait for process to finish)
                string dataFile = StartGameUtil.GetStartDataPath();
                for (; ;)
                {
                    if (File.Exists(dataFile))
                    {
                        try {
                            string txt = File.ReadAllText(dataFile);
                            bool   res;
                            if (bool.TryParse(txt, out res))
                            {
                                break;
                            }
                        } catch {
                        }
                    }
                    Thread.Sleep(250);
                }
                File.Delete(dataFile);
            }
            else
            {
                // just symlink the folders
                StartGameUtil.RunPreBuiltData(symStartData, true);
            }

            for (int i = 0; i < players.Count; i++)
            {
                PlayerInfo     player  = players[i];
                HandlerContext context = contexts[i];
                handlerManager.Play(context, player);

                List <HandlerModule> modules = player.Modules;
                for (int j = 0; j < modules.Count; j++)
                {
                    modules[j].PlayPlayer(i, context);
                }

                Thread.Sleep(TimeSpan.FromMilliseconds(handlerManager.HandlerData.PauseBetweenStarts));

                IGameProcessModule procModule = GetModule <IGameProcessModule>(player);
                if (handlerManager.HandlerData.WaitFullWindowLoad)
                {
                    for (; ;)
                    {
                        Thread.Sleep(100);

                        // check for window status
                        if (procModule.HasWindowSetup(player))
                        {
                            break;
                        }
                    }
                }

                if (killingMutexes)
                {
                    // wait for StartGame confirmation that mutexes were killed
                    string dataFile = StartGameUtil.GetStartDataPath();
                    for (; ;)
                    {
                        if (File.Exists(dataFile))
                        {
                            try {
                                string txt = File.ReadAllText(dataFile);
                                bool   res;
                                if (bool.TryParse(txt, out res))
                                {
                                    break;
                                }
                            } catch {
                            }
                        }
                        Thread.Sleep(250);
                    }
                    File.Delete(dataFile);
                }
            }

            return(result);
        }
Beispiel #2
0
        public override void PrePlayPlayer(int index, HandlerContext context)
        {
            nucleusRootFolder = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);

            tempDir = GameManager.GetTempFolder(handlerData);

            exeFolder     = Path.GetDirectoryName(userGame.ExePath);
            rootFolder    = exeFolder;
            workingFolder = exeFolder;

            if (!string.IsNullOrEmpty(handlerData.ExecutablePath))
            {
                rootFolder = StringUtil.ReplaceCaseInsensitive(exeFolder, handlerData.ExecutablePath.ToLower(), "");
            }
            if (!string.IsNullOrEmpty(handlerData.WorkingFolder))
            {
                rootFolder    = StringUtil.ReplaceCaseInsensitive(exeFolder, handlerData.WorkingFolder.ToLower(), "");
                workingFolder = Path.Combine(exeFolder, handlerData.WorkingFolder.ToLower());
            }

            if (handlerData.SymlinkGame || handlerData.HardcopyGame)
            {
                List <string> dirExclusions  = new List <string>();
                List <string> fileExclusions = new List <string>();
                List <string> fileCopies     = new List <string>();

                // symlink the game folder (and not the bin folder, if we have one)
                linkFolder = Path.Combine(tempDir, "Instance" + index);

                try {
                    if (Directory.Exists(linkFolder))
                    {
                        Directory.Delete(linkFolder, true);
                    }
                } catch { }

                Directory.CreateDirectory(linkFolder);

                linkWorkingDir = linkFolder;

                if (string.IsNullOrEmpty(handlerData.ExecutablePath))
                {
                    linkedExePath = Path.Combine(linkWorkingDir, Path.GetFileName(this.userGame.ExePath));
                    if (!string.IsNullOrEmpty(handlerData.WorkingFolder))
                    {
                        linkWorkingDir = Path.Combine(linkFolder, handlerData.WorkingFolder);
                        dirExclusions.Add(handlerData.WorkingFolder);
                    }
                }
                else
                {
                    dirExclusions.Add(handlerData.ExecutablePath);
                    linkedExePath = Path.Combine(linkWorkingDir, handlerData.ExecutablePath, Path.GetFileName(this.userGame.ExePath));

                    if (!string.IsNullOrEmpty(handlerData.WorkingFolder))
                    {
                        linkWorkingDir = Path.Combine(linkFolder, handlerData.WorkingFolder);
                        dirExclusions.Add(handlerData.WorkingFolder);
                    }
                    else
                    {
                        linkWorkingDir = Path.Combine(linkFolder, handlerData.ExecutablePath);
                    }
                }

                // some games have save files inside their game folder, so we need to access them inside the loop
                handlerData.RegisterAdditional(Folder.InstancedGameFolder.ToString(), linkFolder);

                if (handlerData.Hook.CustomDllEnabled)
                {
                    fileExclusions.Add("xinput1_3.dll");
                    fileExclusions.Add("ncoop.ini");
                }
                if (!handlerData.SymlinkExe)
                {
                    fileCopies.Add(handlerData.ExecutableName.ToLower());
                }

                // additional ignored files by the generic info
                if (handlerData.FileSymlinkExclusions != null)
                {
                    string[] symlinkExclusions = handlerData.FileSymlinkExclusions;
                    for (int k = 0; k < symlinkExclusions.Length; k++)
                    {
                        string s = symlinkExclusions[k];
                        // make sure it's lower case
                        fileExclusions.Add(s.ToLower());
                    }
                }
                if (handlerData.FileSymlinkCopyInstead != null)
                {
                    string[] fileSymlinkCopyInstead = handlerData.FileSymlinkCopyInstead;
                    for (int k = 0; k < fileSymlinkCopyInstead.Length; k++)
                    {
                        string s = fileSymlinkCopyInstead[k];
                        // make sure it's lower case
                        fileCopies.Add(s.ToLower());
                    }
                }
                if (handlerData.DirSymlinkExclusions != null)
                {
                    string[] symlinkExclusions = handlerData.DirSymlinkExclusions;
                    for (int k = 0; k < symlinkExclusions.Length; k++)
                    {
                        string s = symlinkExclusions[k];
                        // make sure it's lower case
                        dirExclusions.Add(s.ToLower());
                    }
                }

                string[] fileExclusionsArr = fileExclusions.ToArray();
                string[] fileCopiesArr     = fileCopies.ToArray();

                if (handlerData.HardcopyGame)
                {
                    // copy the directory
                    int exitCode;
                    FileUtil.CopyDirectory(rootFolder, new DirectoryInfo(rootFolder), linkFolder, out exitCode, dirExclusions.ToArray(), fileExclusionsArr, true);
                }
                else
                {
                    SymlinkGameData symData = new SymlinkGameData();
                    symData.SourcePath      = rootFolder;
                    symData.DestinationPath = linkFolder;
                    symData.DirExclusions   = dirExclusions.ToArray();
                    symData.FileExclusions  = fileExclusionsArr;
                    symData.FileCopies      = fileCopiesArr;
                    SymlinkData             = symData;

                    //int exitCode;
                    //WinDirectoryUtil.LinkDirectory(rootFolder, new DirectoryInfo(rootFolder), linkFolder, out exitCode, dirExclusions.ToArray(), fileExclusionsArr, fileCopiesArr, true);
                }
            }
            else
            {
                linkedExePath  = userGame.ExePath;
                linkWorkingDir = rootFolder;
                linkFolder     = workingFolder;
            }

            context.InstancedExePath     = linkedExePath;
            context.InstallFolder        = exeFolder;
            context.InstanceFolder       = linkFolder;
            context.InstancedWorkingPath = linkWorkingDir;
        }
Beispiel #3
0
        private static void ExecuteTask(StartGameData data)
        {
            switch (data.Task)
            {
            case GameStarterTask.StartGame: {
                string gamePath       = data.Parameters[0];
                string gameArgs       = data.Parameters[1];
                string gameWorkingDir = data.Parameters[2];

                ConsoleU.WriteLine($"Start game: EXE: {gamePath} ARGS: {gameArgs} WORKDIR: {gameWorkingDir}", Palette.Feedback);
                StartGame(gamePath, gameArgs, gameWorkingDir);
            }
            break;

            case GameStarterTask.KillMutex: {
                Log.WriteLine($"Kill Mutex Task");
                string   procId  = data.Parameters[0];
                string[] mutexes = new string[data.Parameters.Length - 1];
                for (int j = 1; j < data.Parameters.Length; j++)
                {
                    string m = data.Parameters[j];
                    mutexes[j - 1] = m;
                }
                KillMutex(procId, mutexes);
                WriteToDataFile(Assembly.GetEntryAssembly().Location, true.ToString());
            }
            break;

            case GameStarterTask.RenameMutex: {
                Log.WriteLine($"Rename Mutex Task");
                string   procId  = data.Parameters[0];
                string[] mutexes = new string[data.Parameters.Length - 1];
                for (int j = 1; j < data.Parameters.Length; j++)
                {
                    string m = data.Parameters[j];
                    mutexes[j - 1] = m;
                }
                KillMutex(procId, mutexes);
                WriteToDataFile(Assembly.GetEntryAssembly().Location, true.ToString());
            }
            break;

            case GameStarterTask.ScanKillMutex: {
                Log.WriteLine($"Scan Kill Mutex");

                List <int> processIds = new List <int>();

                for (int j = 0; j < data.Parameters.Length; j++)
                {
                    string        scanMutexDataRaw = data.Parameters[j];
                    ScanMutexData scanMutex        = JsonConvert.DeserializeObject <ScanMutexData>(scanMutexDataRaw);
                    Log.WriteLine($"Kill Mutex for process {scanMutex.ProcessName}");

                    for (; ;)
                    {
                        Process[] procs = Process.GetProcessesByName(scanMutex.ProcessName);
                        if (procs == null || procs.Length == 0)
                        {
                            Thread.Sleep(250);
                        }
                        else
                        {
                            // kill mutexes
                            bool killedMutexes = false;
                            for (int k = 0; k < procs.Length; k++)
                            {
                                Process p = procs[k];
                                if (processIds.Contains(p.Id))
                                {
                                    continue;
                                }

                                // start other process, as the mutexes are only truly killed
                                // when the process is ended
                                if (scanMutex.ShouldRename)
                                {
                                    StartGameUtil.RenameMutex(p, scanMutex.Mutexes);
                                }
                                else
                                {
                                    StartGameUtil.KillMutex(p, scanMutex.Mutexes);
                                }
                                //KillMutex(p.Id.ToString(), scanMutex.Mutexes);
                                processIds.Add(p.Id);
                                killedMutexes = true;
                                break;
                            }

                            if (killedMutexes)
                            {
                                Log.WriteLine($"Killed all mutexes for process {scanMutex.ProcessName}");
                                WriteToDataFile(Assembly.GetEntryAssembly().Location, true.ToString());
                                break;
                            }
                        }
                    }
                }
            }
            break;

            case GameStarterTask.MultipleTasks: {
                Log.WriteLine($"Multiple tasks");
                for (int j = 0; j < data.Parameters.Length; j++)
                {
                    string        taskDataRaw = data.Parameters[j];
                    StartGameData taskData    = JsonConvert.DeserializeObject <StartGameData>(taskDataRaw);

                    Log.WriteLine($"Executing task {j + 1}");
                    ExecuteTask(taskData);
                }
            }
            break;

            case GameStarterTask.QueryMutex: {
                string   procId  = data.Parameters[0];
                string[] mutexes = new string[data.Parameters.Length - 1];
                for (int j = 1; j < data.Parameters.Length; j++)
                {
                    string m = data.Parameters[j];
                    mutexes[j - 1] = m;
                }
            }
            break;

            case GameStarterTask.ListMonitors:
                break;

            case GameStarterTask.ScanGames: {
                // initialize game manager to read available handlers
                GameManager gameManager = new GameManager();

                List <string> games = new List <string>();
                for (int j = 0; j < data.Parameters.Length; j++)
                {
                    string driveName = data.Parameters[j];
                    //SearchStorageInfo info = JsonConvert.DeserializeObject<SearchStorageInfo>(storageData);
                    DriveInfo drive = new DriveInfo(driveName);

                    if (!drive.IsReady)
                    {
                        continue;
                    }

                    Log.WriteLine($"> Searching drive {drive.Name} for game executables");

                    Dictionary <ulong, FileNameAndParentFrn> allExes = new Dictionary <ulong, FileNameAndParentFrn>();
                    MFTReader mft = new MFTReader();
                    mft.Drive = drive.RootDirectory.FullName;

                    // TODO: search only for specific games?
                    mft.EnumerateVolume(out allExes, new string[] { ".exe" });

                    foreach (KeyValuePair <UInt64, FileNameAndParentFrn> entry in allExes)
                    {
                        FileNameAndParentFrn file = (FileNameAndParentFrn)entry.Value;

                        string name  = file.Name;
                        string lower = name.ToLower();

                        string path = mft.GetFullPath(file);
                        if (path.Contains("$Recycle.Bin") ||
                            path.Contains(@"\Instance"))
                        {
                            // noope
                            continue;
                        }

                        if (GameManager.Instance.AnyGame(lower))
                        {
                            Log.WriteLine($"Found game at path: {path}");
                            games.Add(path);
                        }
                    }
                }

                WriteToDataFile(Assembly.GetEntryAssembly().Location, JsonConvert.SerializeObject(games));
            }
            break;

            case GameStarterTask.SymlinkFolders:
                for (int j = 0; j < data.Parameters.Length; j++)
                {
                    string symData = data.Parameters[j];
                    Log.WriteLine($"Symlink game instance {j + 1}");

                    SymlinkGameData gameData = JsonConvert.DeserializeObject <SymlinkGameData>(symData);
                    int             exitCode;
                    WinDirectoryUtil.LinkDirectory(gameData.SourcePath, new DirectoryInfo(gameData.SourcePath), gameData.DestinationPath, out exitCode, gameData.DirExclusions, gameData.FileExclusions, gameData.FileCopies, true);
                }
                WriteToDataFile(Assembly.GetEntryAssembly().Location, true.ToString());
                break;
            }
        }