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; })); }
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); } } } }
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]); } } } } } } }
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()); } }
public Game(IPlayer player) { TurnNumber = 0; _locations = new GameLocations(this); _events = new GameEvents(); CurrentPhase = new NotStarted(this); _players = new List <IPlayer>(); _startingPlayer = player; }
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]); } }
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); } } }
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]); } } }
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); } } }
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, }); }