Esempio n. 1
0
 static async Task <int> Main(string[] args)
 {
     return(await Parser.Default.ParseArguments(args, typeof(RunPatcherPipelineInstructions))
            .MapResult(
                async(RunPatcherPipelineInstructions settings) =>
     {
         try
         {
             // Locate data folder
             if (string.IsNullOrWhiteSpace(settings.DataFolderPath))
             {
                 if (!GameLocations.TryGetGameFolder(settings.GameRelease, out var gameFolder))
                 {
                     throw new DirectoryNotFoundException("Could not find game folder automatically");
                 }
                 settings.DataFolderPath = Path.Combine(gameFolder, "Data");
             }
             await Commands.Run(settings, CancellationToken.None, new ConsoleReporter());
         }
         catch (Exception ex)
         {
             System.Console.Error.WriteLine(ex);
             return -1;
         }
         return 0;
     },
                async _ =>
     {
         return -1;
     }));
 }
Esempio n. 2
0
        public void TestWarningMessages()
        {
            GameLocations gameLocations = new GameLocations(1, new Random(1));

            //Move to every hazard in the cave and the wumpus, move one room off, and make sure the warning message contains what it should
            for (int i = 1; i < 6; i++)
            {
                gameLocations.Teleport(gameLocations.GetLocationInfo()[i]);
                gameLocations.ChangePlayerLocation(gameLocations.GetPlayerRoomInfo().TunnelLocations()[0]);
                if (i == 1)
                {
                    Assert.IsTrue(gameLocations.GetWarningMessages().Contains("I smell a wumpus"));
                    Debug.WriteLine(1);
                }
                else
                {
                    if (i <= 3 && i >= 2)
                    {
                        Assert.IsTrue(gameLocations.GetWarningMessages().Contains("Bats Nearby"));
                    }
                    else
                    {
                        Assert.IsTrue(gameLocations.GetWarningMessages().Contains("I feel a draft"));
                        Debug.WriteLine(1);
                    }
                }
            }
        }
Esempio n. 3
0
 public void TestHazardLocations()
 {
     for (int i = 0; i < 1000; i++)
     {
         GameLocations gameLocations = new GameLocations(1, new Random(i));
         for (int j = 0; j < 6; j++)
         {
             //Make sure everything is in a valid room
             Assert.IsTrue(gameLocations.GetLocationInfo()[j] <= 29 && gameLocations.GetLocationInfo()[j] >= 0);
             if (j == 0)
             {
                 //Make sure nothing is in the player's room
                 for (int k = 1; k < 6; k++)
                 {
                     Assert.IsFalse(gameLocations.GetLocationInfo()[j] == gameLocations.GetLocationInfo()[k]);
                 }
             }
             else
             {
                 if (j != 1)
                 {
                     //Make sure all hazards are in a different room
                     for (int k = 2; k < 6; k++)
                     {
                         if (k != j)
                         {
                             Assert.IsFalse(gameLocations.GetLocationInfo()[j] == gameLocations.GetLocationInfo()[k]);
                         }
                     }
                 }
             }
         }
     }
 }
Esempio n. 4
0
 public void TestConstructer()
 {
     //Make a new gameLocations for every map and make sure it works
     for (int i = 1; i <= 5; i++)
     {
         GameLocations gameLocations = new GameLocations(i, new Random());
     }
 }
Esempio n. 5
0
 public Game(IPlayer player)
 {
     TurnNumber      = 0;
     _locations      = new GameLocations(this);
     _events         = new GameEvents();
     CurrentPhase    = new NotStarted(this);
     _players        = new List <IPlayer>();
     _startingPlayer = player;
 }
Esempio n. 6
0
 public void TestWumpusMovement()
 {
     //Call the moveWumpusFromPlayer command and make sure the Wumpus isn't in the same room
     for (int i = 0; i < 10000; i++)
     {
         GameLocations gameLocations     = new GameLocations(1, new Random(i));
         int           oldWumpusLocation = gameLocations.GetLocationInfo()[1];
         gameLocations.MoveWumpusFromPlayer();
         Assert.AreNotEqual(oldWumpusLocation, gameLocations.GetLocationInfo()[1]);
     }
 }
Esempio n. 7
0
 public void TestPits()
 {
     //For each pit, move the player to it, resolve the encounter, and make sure the ending positions are within the correct bounds
     for (int i = 0; i < 2; i++)
     {
         for (int j = 0; j < 1000; j++)
         {
             GameLocations gameLocations       = new GameLocations(1, new Random());
             int           startPlayerLocation = gameLocations.GetLocationInfo()[0];
             gameLocations.Teleport(gameLocations.GetLocationInfo()[4 + i]);
             gameLocations.ResolvePits();
             Assert.AreEqual(startPlayerLocation, gameLocations.GetLocationInfo()[0]);
             Assert.AreNotEqual(gameLocations.GetLocationInfo()[0], gameLocations.GetLocationInfo()[4 + i]);
             Assert.IsTrue(gameLocations.GetLocationInfo()[0] <= 29 && gameLocations.GetLocationInfo()[0] >= 0);
         }
     }
 }
Esempio n. 8
0
        public void TestShootArrow()
        {
            GameLocations gameLocations = new GameLocations(1, new Random());

            //Move to a room adjacent to the wumpus and machine-gun a non-wumpus room until it moves
            gameLocations.Teleport(gameLocations.GetLocationInfo()[1]);
            int oldWumpusRoom = gameLocations.GetLocationInfo()[1];

            gameLocations.ChangePlayerLocation(gameLocations.GetPlayerRoomInfo().TunnelLocations()[0]);
            for (int k = 0; k < gameLocations.GetPlayerRoomInfo().ToRoomLocations().Length; k++)
            {
                if (gameLocations.GetPlayerRoomInfo().ToRoomLocations()[k] - 1 != gameLocations.GetLocationInfo()[1])
                {
                    while (oldWumpusRoom == gameLocations.GetLocationInfo()[1])
                    {
                        gameLocations.ShootArrow(gameLocations.GetPlayerRoomInfo().TunnelLocations()[k]);
                    }
                    k = gameLocations.GetPlayerRoomInfo().ToRoomLocations().Length;
                    Assert.AreNotEqual(oldWumpusRoom, gameLocations.GetLocationInfo()[1]);
                }
            }
            //Machine-gun the wumpus and make sure it dosen't move
            gameLocations.Teleport(gameLocations.GetLocationInfo()[1]);
            oldWumpusRoom = gameLocations.GetLocationInfo()[1];
            gameLocations.ChangePlayerLocation(gameLocations.GetPlayerRoomInfo().GetTunnelInfo(gameLocations.GetPlayerRoomInfo().TunnelLocations()[0]).GetDirection());
            for (int k = 0; k < gameLocations.GetPlayerRoomInfo().ToRoomLocations().Length; k++)
            {
                if (gameLocations.GetPlayerRoomInfo().ToRoomLocations()[k] - 1 == gameLocations.GetLocationInfo()[1])
                {
                    for (int i = 0; i < 1000; i++)
                    {
                        gameLocations.ShootArrow(gameLocations.GetPlayerRoomInfo().TunnelLocations()[k]);
                    }
                    k = gameLocations.GetPlayerRoomInfo().ToRoomLocations().Length;
                    Assert.AreEqual(oldWumpusRoom, gameLocations.GetLocationInfo()[1]);
                }
            }
        }
Esempio n. 9
0
        public void TestMovement()
        {
            GameLocations gameLocations = new GameLocations(1, new Random());

            //In every room, try to walk through every direction, and make sure it leads to the right place
            for (int i = 0; i < 30; i++)
            {
                gameLocations.Teleport(i);
                for (int j = 0; j < 5; j++)
                {
                    int expected = expected = gameLocations.GetLocationInfo()[0];
                    for (int k = 0; k < gameLocations.GetPlayerRoomInfo().TunnelLocations().Length; k++)
                    {
                        if (gameLocations.GetPlayerRoomInfo().TunnelLocations()[k] == j)
                        {
                            expected = gameLocations.GetPlayerRoomInfo().GetTunnelInfo(j).GetToRoom() - 1;
                        }
                    }
                    gameLocations.ChangePlayerLocation(j);
                    Assert.AreEqual(expected, gameLocations.GetLocationInfo()[0]);
                    gameLocations.Teleport(i);
                }
            }
        }
Esempio n. 10
0
        public ProfileVM(ConfigurationVM parent, GameRelease?release = null, string?id = null)
        {
            ID      = id ?? Guid.NewGuid().ToString();
            Config  = parent;
            Release = release ?? GameRelease.Oblivion;
            AddGitPatcherCommand      = ReactiveCommand.Create(() => SetInitializer(new GitPatcherInitVM(this)));
            AddSolutionPatcherCommand = ReactiveCommand.Create(() => SetInitializer(new SolutionPatcherInitVM(this)));
            AddCliPatcherCommand      = ReactiveCommand.Create(() => SetInitializer(new CliPatcherInitVM(this)));
            AddSnippetPatcherCommand  = ReactiveCommand.Create(() => SetPatcherForInitialConfiguration(new CodeSnippetPatcherVM(this)));

            ProfileDirectory = Path.Combine(Execution.Paths.WorkingDirectory, ID);
            WorkingDirectory = Execution.Paths.ProfileWorkingDirectory(ID);

            var dataFolderResult = this.WhenAnyValue(x => x.DataPathOverride)
                                   .Select(path =>
            {
                if (path != null)
                {
                    return(Observable.Return(GetResponse <string> .Succeed(path)));
                }
                Log.Logger.Information("Starting to locate data folder");
                return(this.WhenAnyValue(x => x.Release)
                       .ObserveOn(RxApp.TaskpoolScheduler)
                       .Select(x =>
                {
                    try
                    {
                        if (!GameLocations.TryGetGameFolder(x, out var gameFolder))
                        {
                            return GetResponse <string> .Fail("Could not automatically locate Data folder.  Run Steam/GoG/etc once to properly register things.");
                        }
                        return GetResponse <string> .Succeed(Path.Combine(gameFolder, "Data"));
                    }
                    catch (Exception ex)
                    {
                        return GetResponse <string> .Fail(string.Empty, ex);
                    }
                }));
            })
                                   .Switch()
                                   // Watch folder for existance
                                   .Select(x =>
            {
                if (x.Failed)
                {
                    return(Observable.Return(x));
                }
                return(Noggog.ObservableExt.WatchFile(x.Value)
                       .StartWith(Unit.Default)
                       .Select(_ =>
                {
                    if (Directory.Exists(x.Value))
                    {
                        return x;
                    }
                    return GetResponse <string> .Fail($"Data folder did not exist: {x.Value}");
                }));
            })
                                   .Switch()
                                   .StartWith(GetResponse <string> .Fail("Data folder uninitialized"))
                                   .Replay(1)
                                   .RefCount();

            _DataFolder = dataFolderResult
                          .Select(x => x.Value)
                          .ToGuiProperty <string>(this, nameof(DataFolder), string.Empty);

            dataFolderResult
            .Subscribe(d =>
            {
                if (d.Failed)
                {
                    Log.Logger.Error($"Could not locate data folder: {d.Reason}");
                }
                else
                {
                    Log.Logger.Information($"Data Folder: {d.Value}");
                }
            })
            .DisposeWith(this);

            var loadOrderResult = Observable.CombineLatest(
                this.WhenAnyValue(x => x.Release),
                dataFolderResult,
                (release, dataFolder) => (release, dataFolder))
                                  .ObserveOn(RxApp.TaskpoolScheduler)
                                  .Select(x =>
            {
                if (x.dataFolder.Failed)
                {
                    return(Results: Observable.Empty <IChangeSet <LoadOrderEntryVM> >(), State: Observable.Return(ErrorResponse.Fail("Data folder not set")));
                }
                Log.Logger.Error($"Getting live load order for {x.release} -> {x.dataFolder.Value}");
                var liveLo = Mutagen.Bethesda.LoadOrder.GetLiveLoadOrder(x.release, x.dataFolder.Value, out var errors)
                             .Transform(listing => new LoadOrderEntryVM(listing, x.dataFolder.Value))
                             .DisposeMany();
                return(Results: liveLo, State: errors);
            })
                                  .StartWith((Results: Observable.Empty <IChangeSet <LoadOrderEntryVM> >(), State: Observable.Return(ErrorResponse.Fail("Load order uninitialized"))))
                                  .Replay(1)
                                  .RefCount();

            LoadOrder = loadOrderResult
                        .Select(x => x.Results)
                        .Switch()
                        .AsObservableList();

            loadOrderResult.Select(lo => lo.State)
            .Switch()
            .Subscribe(loErr =>
            {
                if (loErr.Succeeded)
                {
                    Log.Logger.Information($"Load order location successful");
                }
                else
                {
                    Log.Logger.Information($"Load order location error: {loErr.Reason}");
                }
            })
            .DisposeWith(this);

            _LargeOverallError = Observable.CombineLatest(
                dataFolderResult,
                loadOrderResult
                .Select(x => x.State)
                .Switch(),
                Patchers.Connect()
                .ObserveOnGui()
                .FilterOnObservable(p => p.WhenAnyValue(x => x.IsOn), scheduler: RxApp.MainThreadScheduler)
                .QueryWhenChanged(q => q)
                .StartWith(Noggog.ListExt.Empty <PatcherVM>()),
                Patchers.Connect()
                .ObserveOnGui()
                .FilterOnObservable(p => Observable.CombineLatest(
                                        p.WhenAnyValue(x => x.IsOn),
                                        p.WhenAnyValue(x => x.State.IsHaltingError),
                                        (on, halting) => on && halting),
                                    scheduler: RxApp.MainThreadScheduler)
                .QueryWhenChanged(q => q)
                .StartWith(Noggog.ListExt.Empty <PatcherVM>()),
                LoadOrder.Connect()
                .ObserveOnGui()
                .FilterOnObservable(
                    x => x.WhenAnyValue(y => y.Exists)
                    .DistinctUntilChanged()
                    .Select(x => !x),
                    scheduler: RxApp.MainThreadScheduler)
                .QueryWhenChanged(q => q)
                .StartWith(Noggog.ListExt.Empty <LoadOrderEntryVM>())
                .Throttle(TimeSpan.FromMilliseconds(200), RxApp.MainThreadScheduler),
                (dataFolder, loadOrder, enabledPatchers, erroredEnabledPatchers, missingMods) =>
            {
                if (enabledPatchers.Count == 0)
                {
                    return(GetResponse <PatcherVM> .Fail("There are no enabled patchers to run."));
                }
                if (!dataFolder.Succeeded)
                {
                    return(dataFolder.BubbleFailure <PatcherVM>());
                }
                if (!loadOrder.Succeeded)
                {
                    return(loadOrder.BubbleFailure <PatcherVM>());
                }
                if (missingMods.Count > 0)
                {
                    return(GetResponse <PatcherVM> .Fail($"Load order had mods that were missing:{Environment.NewLine}{string.Join(Environment.NewLine, missingMods.Select(x => x.Listing.ModKey))}"));
                }
                if (erroredEnabledPatchers.Count > 0)
                {
                    var errPatcher = erroredEnabledPatchers.First();
                    return(GetResponse <PatcherVM> .Fail(errPatcher, $"\"{errPatcher.DisplayName}\" has a blocking error: {errPatcher.State.RunnableState.Reason}"));
                }
                return(GetResponse <PatcherVM> .Succeed(null !));
            })
        public static void RunPatch(IPatcherState <ISkyrimMod, ISkyrimModGetter> state)
        {
            /*
             * TO DO:
             * check if exceeding 254 plugin load and warn
             * clean up, tighten up
             * custom binarywrite, to flag output as esl and stop the dummy Synthesis.esp being created
             */


            //create hash set to hold mods we want
            var modKeySet = new HashSet <ModKey>();


            //check if ActionSpeed.esp is in load order
            var mk = ModKey.FromNameAndExtension("ActionSpeed.esp");

            if (!state.LoadOrder.ContainsKey(mk))
            {
                //warning if not, stops patch
                System.Console.WriteLine($"Please add {mk} to your load order");
                return;
            }

            //adds ActionSpeed.esp to your loader as a master, as it is required by zEdit
            //patcher and this loader will not catch it otherwise. saves a manual click in zedit
            else
            {
                modKeySet.Add(mk);
            }


            // got it, carrying on
            System.Console.WriteLine($"{mk} found! Loading...");


            //detect npc records in mods, adds mods containing those records to set
            foreach (var npcGetter in state.LoadOrder.PriorityOrder.Npc().WinningOverrides())
            {
                var modKey     = npcGetter.FormKey.ModKey;
                var linkedKeys = npcGetter.ContainedFormLinks.Select(l => l.FormKey.ModKey);

                //add keys to our hashset
                modKeySet.Add(modKey);
                modKeySet.Add(linkedKeys);
            }

            //make sure we get mods that make overrides to npc records
            foreach (var npcGetter in state.LoadOrder.PriorityOrder.Npc().WinningContextOverrides())
            {
                //add keys to our hashset
                modKeySet.Add(npcGetter.ModKey);
            }

            //removes null mod names that may have been gathered
            modKeySet.Remove(ModKey.Null);

            //list collected masters
            foreach (ModKey key in modKeySet)
            {
                System.Console.WriteLine(key);
            }

            //shows total number of mods we're going to have as masters
            System.Console.WriteLine("\n" + "\n" + $"Adding {modKeySet.Count} masters to loader.");

            //getting the Skyrim data path to dump our created HeartSeekerLoader.esp, will be co-opted by mod organizer anyhow
            if (!GameLocations.TryGetGameFolder(GameRelease.SkyrimSE, out var gamePath))
            {
                throw new ArgumentException("Game folder can not be located automatically");
            }
            var dataPath = Path.Combine(gamePath, "Data");

            //gets modkey from the load order
            var myLoadOrder = state.LoadOrder.Select(loadKey => loadKey.Key);

            //takes the set of mods we've collected and adds them as masters to the esp
            state.PatchMod.ModHeader.MasterReferences.AddRange(
                modKeySet.Select(m => new MasterReference()
            {
                Master = m
            }));


            //special output of our esp to get around synthesis default, dummy synthesis esp still created
            state.PatchMod.WriteToBinary(
                Path.Combine(dataPath, "ActionSpeedLoader.esp"),
                new BinaryWriteParameters()
            {
                // Don't modify the content of the masters list with what records we have inside
                MastersListContent = MastersListContentOption.NoCheck,

                // Order the masters to match load order
                //old load order getter config
                MastersListOrdering = new MastersListOrderingByLoadOrder(myLoadOrder),
                //new mutagen 0.21.3, i've not got working yet
                //MastersListOrdering = new BinaryWriteParameters.MastersListOrderingByLoadOrder(state.LoadOrder),
                //Ignore default Synthesis.esp mod output name
                ModKey = ModKeyOption.NoCheck,
            });
        }