/// <summary> /// Attempts to unlock the provided cheat. /// </summary> /// <param name="cheat">The cheat to unlock</param> private void UnlockCheat(Cheat cheat) { if (!this.LockedCheatList.Contains(cheat)) { throw new Exception("Cheat must be a locked cheat"); } AccessTokens accessTokens = SettingsViewModel.GetInstance().AccessTokens; // We need the unlocked cheat, since the locked one does not include the payload try { UnlockedCheat unlockedCheat = SqualrApi.UnlockCheat(accessTokens.AccessToken, cheat.CheatId); BrowseViewModel.GetInstance().SetCoinAmount(unlockedCheat.RemainingCoins); this.LockedCheatList.Remove(cheat); this.UnlockedCheatList.Insert(0, unlockedCheat.Cheat); LibraryViewModel.GetInstance().OnUnlock(unlockedCheat.Cheat); } catch (Exception ex) { OutputViewModel.GetInstance().Log(OutputViewModel.LogLevel.Error, "Error unlocking cheat", ex); } }
/// <summary> /// Returns a collection of regions within this region, based on the specified chunking size. /// Ex) If this region is 257 bytes, chunking with a size of 64 will return 5 new regions. /// </summary> /// <param name="chunkSize">The size to break down the region into.</param> /// <returns>A collection of regions broken down from the original region based on the chunk size.</returns> public IEnumerable <NormalizedRegion> ChunkNormalizedRegion(Int32 chunkSize) { if (chunkSize <= 0) { OutputViewModel.GetInstance().Log(OutputViewModel.LogLevel.Fatal, "Invalid chunk size specified for region"); yield break; } chunkSize = Math.Min(chunkSize, this.RegionSize); Int32 chunkCount = (this.RegionSize / chunkSize) + (this.RegionSize % chunkSize == 0 ? 0 : 1); for (Int32 index = 0; index < chunkCount; index++) { Int32 size = chunkSize; // Set size to the remainder if on the final chunk and they are not divisible evenly if (index == chunkCount - 1 && this.RegionSize > chunkSize && this.RegionSize % chunkSize != 0) { size = this.RegionSize % chunkSize; } yield return(new NormalizedRegion(this.BaseAddress.Add(chunkSize * index), size)); } }
/// <summary> /// Selects a specific game for which to view the store. /// </summary> /// <param name="game">The selected game.</param> public void SelectGame(Game game) { // Deselect current game this.IsCheatListLoading = true; this.LockedCheatList = null; this.UnlockedCheatList = null; Task.Run(() => { try { // Select new game AccessTokens accessTokens = SettingsViewModel.GetInstance().AccessTokens; StoreCheats storeCheats = SqualrApi.GetStoreCheats(accessTokens.AccessToken, game.GameId); this.LockedCheatList = new FullyObservableCollection <Cheat>(storeCheats.LockedCheats); this.UnlockedCheatList = new FullyObservableCollection <Cheat>(storeCheats.UnlockedCheats); } catch (Exception ex) { OutputViewModel.GetInstance().Log(OutputViewModel.LogLevel.Error, "Error loading cheats", ex); BrowseViewModel.GetInstance().NavigateBack(); } finally { this.IsCheatListLoading = false; } }); }
/// <summary> /// Returns a collection of regions within this region, based on the specified chunking size. /// Ex) If this region is 257 bytes, chunking with a size of 64 will return 5 new regions. /// </summary> /// <param name="chunkSize">The size to break down the region into.</param> /// <returns>A collection of regions broken down from the original region based on the chunk size.</returns> public IEnumerable <NormalizedRegion> ChunkNormalizedRegion(Int32 chunkSize) { if (chunkSize <= 0) { String error = "Invalid chunk size specified for region"; OutputViewModel.GetInstance().Log(OutputViewModel.LogLevel.Fatal, error); throw new Exception(error); } chunkSize = Math.Min(chunkSize, this.RegionSize); Int32 chunkCount = (this.RegionSize / chunkSize) + (this.RegionSize % chunkSize == 0 ? 0 : 1); NormalizedRegion[] chunks = new NormalizedRegion[chunkCount]; for (Int32 index = 0; index < chunkCount; index++) { Int32 size = chunkSize; // Set size to the remainder if on the final chunk and they are not divisible evenly if (index == chunkCount - 1 && this.RegionSize > chunkSize && this.RegionSize % chunkSize != 0) { size = this.RegionSize % chunkSize; } chunks[index] = new NormalizedRegion(this.BaseAddress.Add(chunkSize * index), size); } return(chunks); }
/// <summary> /// Create a new PeFile object. /// </summary> /// <param name="peFile">Path to a PE file.</param> public PeFile(string peFile) { FileLocation = peFile; try { if (File.Exists(this.FileLocation)) { byte[] buff = File.ReadAllBytes(peFile); Buff = buff; _structureParser = new StructureParser(Buff); _dataDirectories = new DataDirectories( Buff, ImageNtHeaders?.OptionalHeader?.DataDirectory, ImageSectionHeaders, Is32Bit ); } } catch (Exception ex) { OutputViewModel.GetInstance().Log(OutputViewModel.LogLevel.Error, "Error parsing PE header from file: " + ex.ToString()); } }
/// <summary> /// Gets an object that enables debugging of a process. /// </summary> /// <returns>An object that enables debugging of a process.</returns> public static IDebugger GetDebugger() { OperatingSystem os = Environment.OSVersion; PlatformID platformid = os.Platform; Exception ex; switch (platformid) { case PlatformID.Win32NT: case PlatformID.Win32S: case PlatformID.Win32Windows: case PlatformID.WinCE: return(windowsDebuggerInstance.Value); case PlatformID.Unix: ex = new Exception("Unix operating system is not supported"); break; case PlatformID.MacOSX: ex = new Exception("MacOSX operating system is not supported"); break; default: ex = new Exception("Unknown operating system"); break; } OutputViewModel.GetInstance().Log(OutputViewModel.LogLevel.Fatal, "Unsupported Operating System", ex); throw ex; }
/// <summary> /// Gets the base url for api calls. In development environments this will be a local endpoint. /// </summary> /// <returns>The api base url.</returns> private static String InitializeApiBase() { // Check if development environment API endpoint available try { if (!ApplicationDeployment.IsNetworkDeployed) { using (PingClient client = new PingClient()) { Uri uri = new Uri(SqualrApi.LocalHostBase); try { client.Ping(uri.GetLeftPart(UriPartial.Authority)); return(SqualrApi.LocalHostBase); } catch (Exception ex) { OutputViewModel.GetInstance().Log(OutputViewModel.LogLevel.Warn, "No local Squalr site found. Using production for API queries", ex); } } } } catch (Exception ex) { OutputViewModel.GetInstance().Log(OutputViewModel.LogLevel.Info, "Unable to detect environment for API calls.", ex); } // None found, use the actual API base return(SqualrApi.SqualrHostBase); }
/// <summary> /// Invoked when the browser is about to navigate to a new page. /// </summary> /// <param name="sender">Sending object.</param> /// <param name="e">Cancel event args.</param> private void BrowserNavigating(Object sender, NavigatingCancelEventArgs e) { if (e == null || e.Uri == null || e.Uri.AbsoluteUri == null) { return; } try { if (e.Uri.AbsoluteUri.StartsWith(TwitchLoginViewModel.LoginCallbackUrl)) { NameValueCollection queries = HttpUtility.ParseQueryString(e.Uri.Query); String code = queries["code"]; e.Cancel = true; // Pass the code from the query string to the view model command to fetch the oauth codes this.TwitchLoginViewModel.PerformLoginCommand.Execute(code); this.DialogResult = true; this.Close(); } } catch (Exception ex) { OutputViewModel.GetInstance().Log(OutputViewModel.LogLevel.Error, "Error handling web request", ex); AnalyticsService.GetInstance().SendEvent(AnalyticsService.AnalyticsAction.TwitchLogin, ex); } }
/// <summary> /// Gets or sets the graphics interface shared between client and hook /// </summary> // private IGraphicsInterface GraphicsInterface { get; set; } /// <summary> /// Gets or sets the speedhack interface shared between client and hook /// </summary> // private ISpeedHackInterface SpeedHackInterface { get; set; } /// <summary> /// Injects the hook into the specified process /// </summary> /// <param name="process">The process to inject into</param> public override void Inject(Int32 processId) { String channelName = null; // Initialize the IPC server, giving the server access to the interfaces defined here IChannel server = EasyHook.RemoteHooking.IpcCreateServer <HookClient>(ref channelName, WellKnownObjectMode.Singleton, this); try { // Inject DLL into target process EasyHook.RemoteHooking.Inject( processId, EasyHook.InjectionOptions.Default, typeof(HookServer).Assembly.Location, typeof(HookServer).Assembly.Location, channelName); } catch (Exception ex) { OutputViewModel.GetInstance().Log(OutputViewModel.LogLevel.Error, "Unable to Hook Process, some features may not be available", ex); AnalyticsService.GetInstance().SendEvent(AnalyticsService.AnalyticsAction.General, ex); } // this.GraphicsInterface = GraphicsFactory.GetGraphicsInterface(projectDirectory); // this.SpeedHackInterface = new SpeedHackInterface(); }
/// <summary> /// Runs the deactivation function in the script. /// </summary> /// <param name="scriptItem">The script to run.</param> public void RunDeactivationFunction(ScriptItem scriptItem) { // Abort the update loop try { this.ScriptObject.OnDeactivate(); OutputViewModel.GetInstance().Log(OutputViewModel.LogLevel.Info, "Script deactivated: " + scriptItem.Description?.ToString()); try { this.CancelRequest?.Cancel(); this.Task?.Wait(ScriptManager.AbortTime); } catch { } } catch (Exception ex) { OutputViewModel.GetInstance().Log(OutputViewModel.LogLevel.Error, "Error when deactivating script: " + ex.ToString()); } return; }
/// <summary> /// Adds the cheat to the selected library. /// </summary> /// <param name="cheat">The cheat to add.</param> private void AddCheatToLibrary(Cheat cheat) { if (!this.CheatsAvailable.Contains(cheat)) { OutputViewModel.GetInstance().Log(OutputViewModel.LogLevel.Error, "Unable to add cheat to library"); return; } AccessTokens accessTokens = SettingsViewModel.GetInstance().AccessTokens; try { SqualrApi.AddCheatToLibrary(accessTokens.AccessToken, this.ActiveLibrary.LibraryId, cheat.CheatId); cheat.LoadDefaultStreamSettings(); this.cheatsAvailable.Remove(cheat); this.cheatsInLibrary.Insert(0, cheat); this.RaisePropertyChanged(nameof(this.CheatsAvailable)); this.RaisePropertyChanged(nameof(this.CheatsInLibrary)); } catch (Exception ex) { OutputViewModel.GetInstance().Log(OutputViewModel.LogLevel.Error, "Error adding cheat to library", ex); } }
/// <summary> /// Deletes the selected library after prompting the user. /// </summary> private void DeleteLibrary() { if (this.ActiveLibrary == null) { OutputViewModel.GetInstance().Log(OutputViewModel.LogLevel.Error, "No library selected"); return; } MessageBoxResult result = CenteredDialogBox.Show( "Delete library '" + this.ActiveLibrary.LibraryName + "'?", "Confirm Library Delete", MessageBoxButton.YesNoCancel, MessageBoxImage.Question); if (result == MessageBoxResult.Yes) { Task.Run(() => { try { AccessTokens accessTokens = SettingsViewModel.GetInstance().AccessTokens; SqualrApi.DeleteLibrary(accessTokens?.AccessToken, this.ActiveLibrary.LibraryId); this.libraries.Remove(this.ActiveLibrary); this.ActiveLibrary = null; this.RaisePropertyChanged(nameof(this.Libraries)); this.RaisePropertyChanged(nameof(this.ActiveLibrary)); } catch (Exception ex) { OutputViewModel.GetInstance().Log(OutputViewModel.LogLevel.Error, "Error deleting library", ex); } }); } }
/// <summary> /// Starts a proxy service /// </summary> /// <param name="executableName">The executable name of the service to start</param> /// <param name="channelServerName">The channel name for IPC</param> /// <returns>The proxy service that is created</returns> private IProxyService StartProxyService(String executableName, String channelServerName) { try { // Start the proxy service EventWaitHandle processStartEvent = new EventWaitHandle(false, EventResetMode.ManualReset, ProxyCommunicator.WaitEventName); ProcessStartInfo processInfo = new ProcessStartInfo(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), executableName)); processInfo.Arguments = Process.GetCurrentProcess().Id.ToString() + " " + channelServerName + " " + ProxyCommunicator.WaitEventName; processInfo.UseShellExecute = false; processInfo.CreateNoWindow = true; Process.Start(processInfo); processStartEvent.WaitOne(); // Create connection NetNamedPipeBinding binding = new NetNamedPipeBinding(NetNamedPipeSecurityMode.None); binding.ReceiveTimeout = TimeSpan.MaxValue; binding.MaxReceivedMessageSize = Int32.MaxValue; binding.MaxBufferSize = Int32.MaxValue; EndpointAddress endpoint = new EndpointAddress(channelServerName); IProxyService proxyService = ChannelFactory <IProxyService> .CreateChannel(binding, endpoint); OutputViewModel.GetInstance().Log(OutputViewModel.LogLevel.Info, "Started proxy service: " + executableName + " over channel " + channelServerName); return(proxyService); } catch (Exception ex) { OutputViewModel.GetInstance().Log(OutputViewModel.LogLevel.Fatal, "Failed to start proxy service: " + executableName + ". This may impact Scripts and .NET explorer", ex); AnalyticsService.GetInstance().SendEvent(AnalyticsService.AnalyticsAction.General, ex); return(null); } }
/// <summary> /// Determine if the user is logged in to Twitch. /// </summary> private void UpdateLoginStatus() { this.IsLoginStatusLoading = true; try { AccessTokens accessTokens = SettingsViewModel.GetInstance().AccessTokens; if (accessTokens == null || accessTokens.AccessToken.IsNullOrEmpty()) { this.IsLoggedIn = false; return; } User user = SqualrApi.GetTwitchUser(accessTokens.AccessToken); SqualrApi.Connect(accessTokens.AccessToken); this.ActiveUser = user; this.IsLoggedIn = true; } catch (Exception ex) { OutputViewModel.GetInstance().Log(OutputViewModel.LogLevel.Warn, "Unable to log in using stored credentials", ex); this.IsLoggedIn = false; } finally { this.IsLoginStatusLoading = false; } }
/// <summary> /// Runs the activation function in the script. /// </summary> /// <param name="scriptItem">The script to run.</param> /// <returns>Returns true if the function successfully ran, otherwise false.</returns> public Boolean RunActivationFunction(ScriptItem scriptItem) { try { Assembly assembly = Assembly.Load(Compression.Decompress(Convert.FromBase64String(scriptItem.CompiledScript))); this.ScriptObject = assembly.CreateObject("*"); // Bind the deactivation function such that scripts can deactivate themselves this.ScriptObject.Deactivate = new Action(() => scriptItem.IsActivated = false); // Call OnActivate function in the script this.ScriptObject.OnActivate(); OutputViewModel.GetInstance().Log(OutputViewModel.LogLevel.Info, "Script activated: " + scriptItem.Name?.ToString()); } catch (SecurityException ex) { OutputViewModel.GetInstance().Log(OutputViewModel.LogLevel.Error, "Invalid operation in sandbox environment", ex); AnalyticsService.GetInstance().SendEvent(AnalyticsService.AnalyticsAction.General, ex); return(false); } catch (Exception ex) { OutputViewModel.GetInstance().Log(OutputViewModel.LogLevel.Error, "Unable to activate script", ex); return(false); } return(true); }
/// <summary> /// A wrapper function for the update callback. This will call the update function and update required state information. /// </summary> internal void Update() { lock (this.AccessLock) { if (!this.IsBusy) { String error = "Error in task scheduler. Attempting to update before flagging action as busy."; OutputViewModel.GetInstance().Log(OutputViewModel.LogLevel.Fatal, error); throw new Exception(error); } this.CancelRequest = new CancellationTokenSource(); Task updateTask = Task.Run( () => { try { this.OnUpdate(this.CancelRequest.Token); } catch (OperationCanceledException) { OutputViewModel.GetInstance().Log(OutputViewModel.LogLevel.Info, "Task cancelled: " + this.TaskName); } }, this.CancelRequest.Token); updateTask.Wait(); Thread.Sleep(this.UpdateInterval); this.IsBusy = false; } }
/// <summary> /// Loads and deserializes the saved layout from disk. If no layout found, the default is loaded from resources. /// </summary> /// <param name="dockManager">The docking root to which content is loaded.</param> /// <param name="resource">Resource to load the layout from. This is optional.</param> public void LoadLayoutFromResource(DockingManager dockManager, String resource) { String layoutResource = Assembly.GetEntryAssembly().GetManifestResourceNames() .FirstOrDefault(resourceName => resourceName.EndsWith(resource)); if (layoutResource.IsNullOrEmpty()) { OutputViewModel.GetInstance().Log(OutputViewModel.LogLevel.Fatal, "Unable to load layout resource."); return; } try { // Attempt to load layout from resource name using (Stream stream = Assembly.GetEntryAssembly().GetManifestResourceStream(layoutResource)) { if (stream != null) { XmlLayoutSerializer serializer = new XmlLayoutSerializer(dockManager); serializer.Deserialize(stream); } } } catch (Exception ex) { OutputViewModel.GetInstance().Log(OutputViewModel.LogLevel.Error, "Error loading layout resource", ex); } }
/// <summary> /// Gets a snapshot based on the provided mode. Will not read any memory. /// </summary> /// <param name="snapshotCreationMode">The method of snapshot retrieval.</param> /// <returns>The collected snapshot.</returns> public Snapshot GetSnapshot(SnapshotRetrievalMode snapshotCreationMode) { switch (snapshotCreationMode) { case SnapshotRetrievalMode.FromActiveSnapshot: return(this.GetActiveSnapshot()); case SnapshotRetrievalMode.FromActiveSnapshotOrPrefilter: return(this.GetActiveSnapshotCreateIfNone()); case SnapshotRetrievalMode.FromSettings: return(this.CreateSnapshotFromSettings()); case SnapshotRetrievalMode.FromUserModeMemory: return(this.CreateSnapshotFromUsermodeMemory()); case SnapshotRetrievalMode.FromModules: return(this.CreateSnapshotFromModules()); case SnapshotRetrievalMode.FromHeap: return(this.CreateSnapshotFromHeaps()); case SnapshotRetrievalMode.FromStack: throw new NotImplementedException(); default: OutputViewModel.GetInstance().Log(OutputViewModel.LogLevel.Error, "Unknown snapshot retrieval mode"); return(null); } }
/// <summary> /// Clones the script item and compiles it. /// </summary> /// <returns>The clone of the project. Returns null on compilation failure.</returns> public ScriptItem Compile() { if (this.ScriptManager == null) { this.ScriptManager = new ScriptManager(); } if (this.IsCompiled) { OutputViewModel.GetInstance().Log(OutputViewModel.LogLevel.Warn, "Script already compiled"); return(null); } try { ScriptItem clone = this.Clone() as ScriptItem; clone.Description += " - [Compiled]"; clone.isCompiled = true; clone.script = this.ScriptManager.CompileScript(clone.script); return(clone); } catch { OutputViewModel.GetInstance().Log(OutputViewModel.LogLevel.Error, "Unable to complete compile request."); return(null); } }
/// <summary> /// Prevents a default instance of the <see cref="MainViewModel" /> class from being created. /// </summary> private MainViewModel() { OutputViewModel.GetInstance().Log(OutputViewModel.LogLevel.Info, "Squalr started"); OutputViewModel.GetInstance().AddOutputMask(new OutputMask(MainViewModel.AccessTokenRegex, "access_token={{REDACTED}}")); this.DisplayChangeLogCommand = new RelayCommand(() => ChangeLogViewModel.GetInstance().DisplayChangeLog(new Content.ChangeLog().TransformText()), () => true); }
/// <summary> /// Indexer to allow the retrieval of the element at the specified index. /// </summary> /// <param name="index">The index of the pointer.</param> /// <returns>Returns the pointer at the specified index.</returns> public virtual PointerItem this[UInt64 index] { get { OutputViewModel.GetInstance().Log(OutputViewModel.LogLevel.Fatal, "Invalid discovered pointer index"); return(null); } }
/// <summary> /// Starts useful services that run in the background to assist in various operations. /// </summary> private void StartBackgroundServices() { DotNetObjectCollector.GetInstance().Start(); AddressResolver.GetInstance().Start(); AnalyticsService.GetInstance().Start(); AnalyticsService.GetInstance().SendEvent(AnalyticsService.AnalyticsAction.General, "Start"); OutputViewModel.GetInstance().Log(OutputViewModel.LogLevel.Info, "Background services started"); }
/// <summary> /// Closes a process for editing. /// </summary> public void CloseProcess() { if (this.OpenedProcess != null) { OutputViewModel.GetInstance().Log(OutputViewModel.LogLevel.Info, "Detached from target process"); } this.OpenProcess(null); }
/// <summary> /// Starts useful services that run in the background to assist in various operations. /// </summary> private void StartBackgroundServices() { SnapshotPrefilterFactory.GetSnapshotPrefilter(typeof(ChunkLinkedListPrefilter)).BeginPrefilter(); //// PointerCollector.GetInstance().Begin(); DotNetObjectCollector.GetInstance().Begin(); AddressResolver.GetInstance().Begin(); OutputViewModel.GetInstance().Log(OutputViewModel.LogLevel.Info, "Background Services Started"); }
/// <summary> /// Gets all modules in the opened process. /// </summary> /// <returns>A collection of modules in the process.</returns> public IEnumerable <NormalizedModule> GetModules() { // Query all modules in the target process IntPtr[] modulePointers = new IntPtr[0]; Int32 bytesNeeded = 0; List <NormalizedModule> modules = new List <NormalizedModule>(); if (this.SystemProcess == null) { return(modules); } try { // Determine number of modules if (!NativeMethods.EnumProcessModulesEx(this.SystemProcess.Handle, modulePointers, 0, out bytesNeeded, (UInt32)Enumerations.ModuleFilter.ListModulesAll)) { return(modules); } Int32 totalNumberofModules = bytesNeeded / IntPtr.Size; modulePointers = new IntPtr[totalNumberofModules]; if (NativeMethods.EnumProcessModulesEx(this.SystemProcess.Handle, modulePointers, bytesNeeded, out bytesNeeded, (UInt32)Enumerations.ModuleFilter.ListModulesAll)) { for (Int32 index = 0; index < totalNumberofModules; index++) { StringBuilder moduleFilePath = new StringBuilder(1024); NativeMethods.GetModuleFileNameEx(this.SystemProcess.Handle, modulePointers[index], moduleFilePath, (UInt32)moduleFilePath.Capacity); String moduleName = Path.GetFileName(moduleFilePath.ToString()); ModuleInformation moduleInformation = new ModuleInformation(); NativeMethods.GetModuleInformation(this.SystemProcess.Handle, modulePointers[index], out moduleInformation, (UInt32)(IntPtr.Size * modulePointers.Length)); // Ignore modules in 64-bit address space for WoW64 processes if (EngineCore.GetInstance().Processes.IsOpenedProcess32Bit() && moduleInformation.ModuleBase.ToUInt64() > Int32.MaxValue) { continue; } // Convert to a normalized module and add it to our list NormalizedModule module = new NormalizedModule(moduleName, moduleInformation.ModuleBase, (Int32)moduleInformation.SizeOfImage); modules.Add(module); } } } catch (Exception ex) { OutputViewModel.GetInstance().Log(OutputViewModel.LogLevel.Error, "Unable to fetch modules from selected process", ex); AnalyticsService.GetInstance().SendEvent(AnalyticsService.AnalyticsAction.General, ex); } return(modules); }
/// <summary> /// Recieves a process update. /// </summary> /// <param name="process">The newly selected process.</param>> public void Update(NormalizedProcess process) { lock (this.RegionLock) { if (this.PrefilteredSnapshot.ByteCount > 0) { this.PrefilteredSnapshot = new Snapshot(); OutputViewModel.GetInstance().Log(OutputViewModel.LogLevel.Info, "Pointer Prefilter cleared"); } } }
/// <summary> /// Recieves a process update. /// </summary> /// <param name="process">The newly selected process.</param>> public void Update(NormalizedProcess process) { lock (this.ChunkLock) { if (this.ChunkList.Count > 0) { this.ChunkList.Clear(); OutputViewModel.GetInstance().Log(OutputViewModel.LogLevel.Info, "Prefilter cleared"); } } }
/// <summary> /// Continously runs the update function in the script. /// </summary> /// <param name="scriptItem">The script to run.</param> public void RunUpdateFunction(ScriptItem scriptItem) { this.CancelRequest = new CancellationTokenSource(); try { this.Task = Task.Run( async() => { TimeSpan elapsedTime; DateTime previousTime = DateTime.Now; while (true) { DateTime currentTime = DateTime.Now; elapsedTime = currentTime - previousTime; try { // Call the update function, giving the elapsed milliseconds since the previous call ScriptObject.OnUpdate((Single)elapsedTime.TotalMilliseconds); } catch (Exception ex) { String exception = ex.ToString(); if (exception.ToString().Contains("does not contain a definition for 'OnUpdate'")) { OutputViewModel.GetInstance().Log(OutputViewModel.LogLevel.Warn, "Optional update function not executed"); } else { OutputViewModel.GetInstance().Log(OutputViewModel.LogLevel.Error, "Error running update function: " + ex.ToString()); } return; } previousTime = currentTime; // Await with cancellation await Task.Delay(ScriptManager.UpdateTime, this.CancelRequest.Token); } }, this.CancelRequest.Token); return; } catch { OutputViewModel.GetInstance().Log(OutputViewModel.LogLevel.Error, "Error executing update loop."); } }
/// <summary> /// Finds any connected gamepad devices. /// </summary> private void FindController() { try { this.DirectInput = new DirectInput(); // Find a Joystick Guid this.JoystickGuid = Guid.Empty; foreach (DeviceInstance deviceInstance in this.DirectInput.GetDevices(DeviceType.Gamepad, DeviceEnumerationFlags.AllDevices)) { this.JoystickGuid = deviceInstance.InstanceGuid; } // If Gamepad not found, look for a Joystick if (this.JoystickGuid == Guid.Empty) { foreach (DeviceInstance deviceInstance in this.DirectInput.GetDevices(DeviceType.Joystick, DeviceEnumerationFlags.AllDevices)) { this.JoystickGuid = deviceInstance.InstanceGuid; } } // If Joystick not found, throws an error if (this.JoystickGuid == Guid.Empty) { // TODO: Resort to like xInput or something here??? IDK return; } // Instantiate the joystick this.Joystick = new Joystick(this.DirectInput, this.JoystickGuid); // Query all suported ForceFeedback effects IList <EffectInfo> allEffects = this.Joystick.GetEffects(); if (allEffects != null) { foreach (EffectInfo effectInfo in allEffects) { Console.WriteLine("Effect available {0}", effectInfo.Name); } } this.Joystick.Properties.BufferSize = 128; this.Joystick.Acquire(); OutputViewModel.GetInstance().Log(OutputViewModel.LogLevel.Info, "Controller device found"); } catch (Exception ex) { OutputViewModel.GetInstance().Log(OutputViewModel.LogLevel.Warn, "No (optional) game controller found: " + ex.ToString()); } }
/// <summary> /// Export a project to separate files. /// </summary> public void ExportProject() { Task.Run(() => { // Export the project items to thier own individual files try { if (String.IsNullOrEmpty(this.ProjectFilePath) || !Directory.Exists(Path.GetDirectoryName(this.ProjectFilePath))) { OutputViewModel.GetInstance().Log(OutputViewModel.LogLevel.Info, "Please save the project before exporting"); return; } OutputViewModel.GetInstance().Log(OutputViewModel.LogLevel.Info, "Project export starting"); String folderPath = Path.Combine(Path.GetDirectoryName(this.ProjectFilePath), "Export"); Directory.CreateDirectory(folderPath); Parallel.ForEach( ProjectExplorerViewModel.GetInstance().ProjectItems, SettingsViewModel.GetInstance().ParallelSettingsFast, (projectItem) => { ProjectItem targetProjectItem = projectItem; if (targetProjectItem == null) { return; } String filePath = Path.Combine(folderPath, targetProjectItem.Name + ProjectItemStorage.ProjectFileExtension); using (FileStream fileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write)) { List <ProjectItem> newProjectRoot = new List <ProjectItem>(); newProjectRoot.Add(targetProjectItem); DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(ProjectItem[])); serializer.WriteObject(fileStream, newProjectRoot.ToArray()); } }); } catch (Exception ex) { OutputViewModel.GetInstance().Log(OutputViewModel.LogLevel.Fatal, "Unable to complete export project", ex); AnalyticsService.GetInstance().SendEvent(AnalyticsService.AnalyticsAction.General, ex); return; } OutputViewModel.GetInstance().Log(OutputViewModel.LogLevel.Info, "Project export complete"); }); }