public override sealed async Task RunAsync(IInteractionProvider provider) { provider.PressKey(key); // Use a accurate timer for measuring the time after we need to release the key. await provider.WaitAsync(duration, true); provider.ReleaseKey(key); }
public override sealed async Task RunAsync(IInteractionProvider provider) { provider.PressKey(this.key); // Use a accurate timer for measuring the time after we need to release the key. await provider.WaitAsync(this.duration, true); provider.ReleaseKey(this.key); }
public override sealed async Task RunAsync(IInteractionProvider provider) { // write the text and presses enter. if (!pauseDuration.HasValue) provider.WriteText(text); else { for (int i = 0; i < text.Length; i++) { provider.WriteText(text[i].ToString()); await provider.WaitAsync(pauseDuration.Value); } } // A CR LF (\r\n) in the above string would not have the desired effect; // instead we need to press the enter key. provider.PressKey(AbstractWindowsEnvironment.VirtualKeyShort.Enter); await provider.WaitAsync(100); provider.ReleaseKey(AbstractWindowsEnvironment.VirtualKeyShort.Enter); }
public override sealed async Task RunAsync(IInteractionProvider provider) { // Click on the "Plant Flower" button. await MouseHelpers.DoSimpleMouseClickAsync(provider, new Coordinates(76, 264), VerticalScaleAlignment.Left); await provider.WaitAsync(200); // Click on the jellybean fields. foreach (int jellybean in jellybeanCombination) { var c = new Coordinates((int)Math.Round(560 + jellybean * 60.5), 514); await MouseHelpers.DoSimpleMouseClickAsync(provider, c, VerticalScaleAlignment.Center, 100); await provider.WaitAsync(100); } await provider.WaitAsync(100); // Click on the "Plant" button. await MouseHelpers.DoSimpleMouseClickAsync(provider, new Coordinates(975, 772)); }
protected override sealed async Task FinishThrowFishingRodAsync(IInteractionProvider provider) { // Simply throw the fishing rod straight, without checking for bubbles. Coordinates coords = new Coordinates(800, 1009); var pos = provider.GetCurrentWindowPosition(); coords = pos.RelativeToAbsoluteCoordinates(pos.ScaleCoordinates(coords, MouseHelpers.ReferenceWindowSize)); provider.MoveMouse(coords); await provider.WaitAsync(300); provider.ReleaseMouseButton(); }
public static async Task DoSimpleMouseClickAsync(IInteractionProvider provider, Coordinates coords, VerticalScaleAlignment valign = VerticalScaleAlignment.Center, int buttonDownTimeout = 200) { var pos = provider.GetCurrentWindowPosition(); coords = pos.RelativeToAbsoluteCoordinates(pos.ScaleCoordinates(coords, ReferenceWindowSize, valign)); provider.MoveMouse(coords); provider.PressMouseButton(); await provider.WaitAsync(buttonDownTimeout); provider.ReleaseMouseButton(); }
public override sealed async Task RunAsync(IInteractionProvider provider) { // Click on the "Plant Flower" button. await MouseHelpers.DoSimpleMouseClickAsync(provider, new Coordinates(76, 264), VerticalScaleAlignment.Left); await provider.WaitAsync(200); // Click on the jellybean fields. foreach (int jellybean in this.jellybeanCombination) { var c = new Coordinates((int)Math.Round(560 + jellybean * 60.5), 514); await MouseHelpers.DoSimpleMouseClickAsync(provider, c, VerticalScaleAlignment.Center, 100); await provider.WaitAsync(100); } await provider.WaitAsync(100); // Click on the "Plant" button. await MouseHelpers.DoSimpleMouseClickAsync(provider, new Coordinates(975, 772)); }
protected override sealed async Task FinishCastFishingRodAsync(IInteractionProvider provider) { // Simply cast the fishing rod straight, without checking for bubbles. var coords = new Coordinates(800, 1009); var pos = provider.GetCurrentWindowPosition(); coords = pos.ScaleCoordinates(coords, MouseHelpers.ReferenceWindowSize); provider.MoveMouse(coords); await provider.WaitAsync(300); provider.ReleaseMouseButton(); }
public override sealed async Task RunAsync(IInteractionProvider provider) { // write the text and presses enter. if (!this.pauseDuration.HasValue) { provider.WriteText(this.text); } else { for (int i = 0; i < this.text.Length; i++) { provider.WriteText(this.text[i].ToString()); await provider.WaitAsync(this.pauseDuration.Value); } } // A CR LF (\r\n) in the above string would not have the desired effect; // instead we need to press the enter key. provider.PressKey(AbstractWindowsEnvironment.VirtualKeyShort.Enter); await provider.WaitAsync(100); provider.ReleaseKey(AbstractWindowsEnvironment.VirtualKeyShort.Enter); }
public static async Task DoSimpleMouseClickAsync(IInteractionProvider provider, Coordinates coords, VerticalScaleAlignment valign = VerticalScaleAlignment.Center, int buttonDownTimeout = 150) { var pos = provider.GetCurrentWindowPosition(); coords = pos.ScaleCoordinates(coords, ReferenceWindowSize, valign); provider.MoveMouse(coords); provider.PressMouseButton(); await provider.WaitAsync(buttonDownTimeout); provider.ReleaseMouseButton(); }
/// <summary> /// Clicks on the fishing rod button. /// </summary> /// <param name="provider"></param> /// <returns></returns> protected async Task StartCastFishingRodAsync(IInteractionProvider provider) { var coords = new Coordinates(800, 846); var pos = provider.GetCurrentWindowPosition(); coords = pos.ScaleCoordinates(coords, MouseHelpers.ReferenceWindowSize); // Move the mouse and press the button. provider.MoveMouse(coords); provider.PressMouseButton(); await provider.WaitAsync(300); CheckForFishErrorDialog(provider); }
public override sealed async Task RunAsync(IInteractionProvider provider) { // Click on the Speedchat Icon. Coordinates c = new Coordinates(122, 40); await MouseHelpers.DoSimpleMouseClickAsync(provider, c, VerticalScaleAlignment.Left, 100); int currentYNumber = 0; for (int i = 0; i < menuItems.Length; i++) { await provider.WaitAsync(300); currentYNumber += menuItems[i]; c = new Coordinates(xWidths[i], (40 + currentYNumber * 38)); await MouseHelpers.DoSimpleMouseClickAsync(provider, c, VerticalScaleAlignment.Left, 100); } }
public override sealed async Task RunAsync(IInteractionProvider provider) { // Click on the Speedchat Icon. var c = new Coordinates(122, 40); await MouseHelpers.DoSimpleMouseClickAsync(provider, c, VerticalScaleAlignment.Left, 100); int currentYNumber = 0; for (int i = 0; i < this.menuItems.Length; i++) { await provider.WaitAsync(300); currentYNumber += this.menuItems[i]; c = new Coordinates(xWidths[i], (40 + currentYNumber * 38)); await MouseHelpers.DoSimpleMouseClickAsync(provider, c, VerticalScaleAlignment.Left, 100); } }
public override sealed async Task RunAsync(IInteractionProvider provider) { // Cast the fishing rod OnActionInformationUpdated("Casting…"); await StartCastFishingRodAsync(provider); await FinishCastFishingRodAsync(provider); // Then, wait until we find a window displaying the caught fish // or the specified number of seconds has passed. OnActionInformationUpdated("Waiting for the fish result dialog…"); var sw = new Stopwatch(); sw.Start(); bool found = false; while (!found && sw.ElapsedMilliseconds <= this.WaitingForFishResultDialogTime) { await provider.WaitAsync(500); // Get a current screenshot. var screenshot = provider.GetCurrentWindowScreenshot(); foreach (var c in fishResultDialogCoordinates) { var cc = screenshot.WindowPosition.ScaleCoordinates( c, MouseHelpers.ReferenceWindowSize); var col = screenshot.GetPixel(cc); if (CompareColor(fishDialogColor, col, 10)) { // OK, we caught a fish, so break from the loop. found = true; break; } } } }
public override sealed async Task RunAsync(IInteractionProvider provider) { // Cast the fishing rod OnActionInformationUpdated("Casting…"); await StartCastFishingRodAsync(provider); await FinishCastFishingRodAsync(provider); // Then, wait until we find a window displaying the caught fish // or the specified number of seconds has passed. OnActionInformationUpdated("Waiting for the fish result dialog…"); Stopwatch sw = new Stopwatch(); sw.Start(); bool found = false; while (!found && sw.ElapsedMilliseconds <= WaitingForFishResultDialogTime) { await provider.WaitAsync(500); // Get a current screenshot. var screenshot = provider.GetCurrentWindowScreenshot(); foreach (Coordinates c in fishResultDialogCoordinates) { var cc = screenshot.WindowPosition.ScaleCoordinates( c, MouseHelpers.ReferenceWindowSize); var col = screenshot.GetPixel(cc); if (CompareColor(fishDialogColor, col, 10)) { // OK, we caught a fish, so break from the loop. found = true; break; } } } }
public override sealed async Task RunAsync(IInteractionProvider provider) => await provider.WaitAsync(duration);
protected override sealed async Task FinishCastFishingRodAsync(IInteractionProvider provider) { // Try to find a bubble. const string actionInformationScanning = "Scanning for fish bubbles…"; OnActionInformationUpdated(actionInformationScanning); const int scanStep = 15; Stopwatch sw = new Stopwatch(); sw.Start(); Coordinates? oldCoords = null; Coordinates? newCoords; int coordsMatchCounter = 0; while (true) { var screenshot = provider.GetCurrentWindowScreenshot(); newCoords = null; // TODO: The fish bubble detection should be changed so that it does not scan // for a specific color, but instead checks that for a point if the color is // darker than the neighbor pixels (in some distance). for (int y = spotData.Scan1.Y; y <= spotData.Scan2.Y && !newCoords.HasValue; y += scanStep) { for (int x = spotData.Scan1.X; x <= spotData.Scan2.X; x += scanStep) { var c = new Coordinates(x, y); c = screenshot.WindowPosition.ScaleCoordinates(c, MouseHelpers.ReferenceWindowSize); if (CompareColor(spotData.BubbleColor, screenshot.GetPixel(c), spotData.Tolerance)) { newCoords = new Coordinates(x + 20, y + 20); Coordinates scaledCoords = screenshot.WindowPosition.RelativeToAbsoluteCoordinates( screenshot.WindowPosition.ScaleCoordinates( newCoords.Value, MouseHelpers.ReferenceWindowSize)); OnActionInformationUpdated($"Found bubble at {scaledCoords.X}, {scaledCoords.Y}…"); break; } } } if (!newCoords.HasValue) OnActionInformationUpdated(actionInformationScanning); if (newCoords.HasValue && oldCoords.HasValue && Math.Abs(oldCoords.Value.X - newCoords.Value.X) <= scanStep && Math.Abs(oldCoords.Value.Y - newCoords.Value.Y) <= scanStep) { // The new coordinates are (nearly) the same as the previous ones. coordsMatchCounter++; } else { // Reset the counter and update the coordinates even if we currently didn't // find them. oldCoords = newCoords; coordsMatchCounter = 0; } // Now position the mouse already so that we just need to release the button. if (!newCoords.HasValue) { // If we couldn't find the bubble we use default destination x,y values. newCoords = new Coordinates(800, 1009); } else { // Calculate the destination coordinates. newCoords = new Coordinates( (int)Math.Round(800d + 120d / 429d * (800d - newCoords.Value.X) * (0.75 + (820d - newCoords.Value.Y) / 820 * 0.38)), (int)Math.Round(846d + 169d / 428d * (820d - newCoords.Value.Y)) ); } // Note: Instead of using a center position for scaling the X coordinate, // TTR seems to interpret it as being scaled from an 4/3 ratio. Therefore // we need to specify "NoAspectRatio" here. // However it could be that they will change this in the future, then // we would need to use "Center". // Note: We assume the point to click on is exactly centered. Otherwise // we would need to adjust the X coordinate accordingly. var coords = screenshot.WindowPosition.RelativeToAbsoluteCoordinates( screenshot.WindowPosition.ScaleCoordinates(newCoords.Value, MouseHelpers.ReferenceWindowSize, VerticalScaleAlignment.NoAspectRatio)); provider.MoveMouse(coords); if (coordsMatchCounter == 2) { // If we found the same coordinates two times, we assume // the bubble is not moving at the moment. break; } await provider.WaitAsync(500); // Ensure we don't wait longer than 36 seconds. if (sw.ElapsedMilliseconds >= 36000) break; } // There is no need to wait here because the mouse has already been positioned and we // waited at least 2x 500 ms at the new position, so now just release the mouse button. provider.ReleaseMouseButton(); }
public override sealed async Task RunAsync(IInteractionProvider provider) => await provider.WaitAsync(this.duration);
public override sealed async Task RunAsync(IInteractionProvider provider) { // Run the actions. int currentIdx = -1; var randomOrder = null as int[]; Func <int> getNextActionIndex; if (this.type == CompoundActionType.Sequential) { getNextActionIndex = () => (!this.loop && currentIdx + 1 == this.actionList.Count) ? -1 : currentIdx = (currentIdx + 1) % this.actionList.Count; } else if (this.type == CompoundActionType.RandomIndex) { getNextActionIndex = () => this.rng.Next(this.actionList.Count); } else { randomOrder = new int[this.actionList.Count]; getNextActionIndex = () => { if (!this.loop && currentIdx + 1 == this.actionList.Count) { return(-1); } currentIdx = (currentIdx + 1) % this.actionList.Count; if (currentIdx == 0) { // Generate a new order array. for (int i = 0; i < randomOrder.Length; i++) { randomOrder[i] = i; } for (int i = 0; i < randomOrder.Length; i++) { int rIdx = this.rng.Next(randomOrder.Length - i); int tmp = randomOrder[i]; randomOrder[i] = randomOrder[i + rIdx]; randomOrder[i + rIdx] = tmp; } } return(randomOrder[currentIdx]); }; } while (true) { int nextIdx = getNextActionIndex(); if (nextIdx == -1) { break; } OnActionInformationUpdated($"Running action {nextIdx + 1}"); while (true) { try { // Check if the simulator has already been canceled. provider.EnsureNotCanceled(); OnSubActionStartedOrStopped(nextIdx); try { await this.actionList[nextIdx].RunAsync(provider); } finally { OnSubActionStartedOrStopped(null); } // After running an action, wait. int waitInterval = this.rng.Next(this.minimumPauseDuration, this.maximumPauseDuration); OnActionInformationUpdated($"Pausing {waitInterval} ms"); await provider.WaitAsync(waitInterval); } catch (Exception ex) when(!(ex is SimulatorCanceledException)) { await provider.CheckRetryForExceptionAsync(ex); continue; } break; } } }
public override sealed async Task RunAsync(IInteractionProvider provider) { // Run the actions. int currentIdx = -1; int[] randomOrder = null; Func<int> getNextActionIndex; if (type == CompoundActionType.Sequential) getNextActionIndex = () => (!loop && currentIdx + 1 == actionList.Count) ? -1 : currentIdx = (currentIdx + 1) % actionList.Count; else if (type == CompoundActionType.RandomIndex) getNextActionIndex = () => rng.Next(actionList.Count); else { randomOrder = new int[actionList.Count]; getNextActionIndex = () => { if (!loop && currentIdx + 1 == actionList.Count) return -1; currentIdx = (currentIdx + 1) % actionList.Count; if (currentIdx == 0) { // Generate a new order array. for (int i = 0; i < randomOrder.Length; i++) randomOrder[i] = i; for (int i = 0; i < randomOrder.Length; i++) { int rIdx = rng.Next(randomOrder.Length - i); int tmp = randomOrder[i]; randomOrder[i] = randomOrder[i + rIdx]; randomOrder[i + rIdx] = tmp; } } return randomOrder[currentIdx]; }; } while (true) { // Check if the simulator has already been canceled. provider.EnsureNotCanceled(); int nextIdx = getNextActionIndex(); if (nextIdx == -1) break; OnActionInformationUpdated($"Running action {nextIdx + 1}"); OnSubActionStartedOrStopped(nextIdx); try { IAction action = actionList[nextIdx]; await action.RunAsync(provider); } finally { OnSubActionStartedOrStopped(null); } // After running an action, wait. int waitInterval = rng.Next(minimumPauseDuration, maximumPauseDuration); OnActionInformationUpdated($"Pausing {waitInterval} ms"); await provider.WaitAsync(waitInterval); } }
protected override sealed async Task FinishCastFishingRodAsync(IInteractionProvider provider) { // Try to find a bubble. const string actionInformationScanning = "Scanning for fish bubbles…"; OnActionInformationUpdated(actionInformationScanning); const int scanStep = 15; var sw = new Stopwatch(); sw.Start(); Coordinates?oldCoords = null; Coordinates?newCoords; int coordsMatchCounter = 0; while (true) { var screenshot = provider.GetCurrentWindowScreenshot(); newCoords = null; // TODO: The fish bubble detection should be changed so that it does not scan // for a specific color, but instead checks that for a point if the color is // darker than the neighbor pixels (in some distance). for (int y = this.spotData.Scan1.Y; y <= this.spotData.Scan2.Y && !newCoords.HasValue; y += scanStep) { for (int x = this.spotData.Scan1.X; x <= this.spotData.Scan2.X; x += scanStep) { var c = new Coordinates(x, y); c = screenshot.WindowPosition.ScaleCoordinates(c, MouseHelpers.ReferenceWindowSize); if (CompareColor(this.spotData.BubbleColor, screenshot.GetPixel(c), this.spotData.Tolerance)) { newCoords = new Coordinates(x + 20, y + 20); var scaledCoords = screenshot.WindowPosition.ScaleCoordinates( newCoords.Value, MouseHelpers.ReferenceWindowSize); OnActionInformationUpdated($"Found bubble at {scaledCoords.X}, {scaledCoords.Y}…"); break; } } } if (!newCoords.HasValue) { OnActionInformationUpdated(actionInformationScanning); } if (newCoords.HasValue && oldCoords.HasValue && Math.Abs(oldCoords.Value.X - newCoords.Value.X) <= scanStep && Math.Abs(oldCoords.Value.Y - newCoords.Value.Y) <= scanStep) { // The new coordinates are (nearly) the same as the previous ones. coordsMatchCounter++; } else { // Reset the counter and update the coordinates even if we currently didn't // find them. oldCoords = newCoords; coordsMatchCounter = 0; } // Now position the mouse already so that we just need to release the button. if (!newCoords.HasValue) { // If we couldn't find the bubble we use default destination x,y values. newCoords = new Coordinates(800, 1009); } else { // Calculate the destination coordinates. newCoords = new Coordinates( (int)Math.Round(800d + 120d / 429d * (800d - newCoords.Value.X) * (0.75 + (820d - newCoords.Value.Y) / 820 * 0.38)), (int)Math.Round(846d + 169d / 428d * (820d - newCoords.Value.Y)) ); } // Note: Instead of using a center position for scaling the X coordinate, // TTR seems to interpret it as being scaled from an 4/3 ratio. Therefore // we need to specify "NoAspectRatio" here. // However it could be that they will change this in the future, then // we would need to use "Center". // Note: We assume the point to click on is exactly centered. Otherwise // we would need to adjust the X coordinate accordingly. var coords = screenshot.WindowPosition.ScaleCoordinates(newCoords.Value, MouseHelpers.ReferenceWindowSize, VerticalScaleAlignment.NoAspectRatio); provider.MoveMouse(coords); if (coordsMatchCounter == 2) { // If we found the same coordinates two times, we assume // the bubble is not moving at the moment. break; } await provider.WaitAsync(500); // Ensure we don't wait longer than 36 seconds. if (sw.ElapsedMilliseconds >= 36000) { break; } } // There is no need to wait here because the mouse has already been positioned and we // waited at least 2x 500 ms at the new position, so now just release the mouse button. provider.ReleaseMouseButton(); }
/// <summary> /// Clicks on the fishing rod button. /// </summary> /// <param name="provider"></param> /// <returns></returns> protected async Task StartCastFishingRodAsync(IInteractionProvider provider) { Coordinates coords = new Coordinates(800, 846); var pos = provider.GetCurrentWindowPosition(); coords = pos.RelativeToAbsoluteCoordinates(pos.ScaleCoordinates(coords, MouseHelpers.ReferenceWindowSize)); // Move the mouse and press the button. provider.MoveMouse(coords); provider.PressMouseButton(); await provider.WaitAsync(300); CheckForFishErrorDialog(provider); }