public void WriteRotation(Vector3 newRotation) { try { // Get the item from the structure to see when it's also invalid. var item = Marshal.ReadIntPtr(this.housingStructure + 0x18); // Ensure we have a valid pointer for the item. if (item == IntPtr.Zero) { return; } // Rotation offset from the selected item. var x = item + 0x60; var y = item + 0x64; var z = item + 0x68; var w = item + 0x6C; var q = RotationMath.ToQ(newRotation); unsafe { // Write the rotation to memory. *(float *)w = q.W; *(float *)x = q.X; *(float *)y = q.Y; *(float *)z = q.Z; } } catch (Exception ex) { PluginLog.LogError(ex, "Error occured while writing rotation."); } }
public void Initialize(DalamudPluginInterface pluginInterface) { HTTPAction.pluginInterface = pluginInterface; Configuration = pluginInterface.GetPluginConfig() as HTTPActionConfiguration ?? new HTTPActionConfiguration(); try { //var macroCallPtr = pluginInterface.TargetModuleScanner.ScanText("E8 ?? ?? ?? ?? E9 ?? ?? ?? ?? 48 8D 4D 20 49 8B D6"); var macroCallPtr = pluginInterface.TargetModuleScanner.ScanText("40 53 56 57 48 83 EC 70 48 8B 05 ?? ?? ?? ?? 48 33 C4 48 89 44 24 60 48 8B 02 49 8B F0"); //var macroBasePtr = pluginInterface.TargetModuleScanner.GetStaticAddressFromSig("48 8B 05 ?? ?? ?? ?? 48 8B D9 8B 40 14 85 C0"); macroBasePtr = Marshal.ReadIntPtr(pluginInterface.TargetModuleScanner.Module.BaseAddress + 0x1BDFEF0); macroBasePtr = Marshal.ReadIntPtr(macroBasePtr); //PluginLog.Log($"macroBasePtrC={macroBasePtr}"); macroCallHook = new Hook <MacroCallDelegate>(macroCallPtr, new MacroCallDelegate(MacroCallDetour)); macroCallHook?.Enable(); pluginInterface.CommandManager.AddHandler("/macrohttp", new Dalamud.Game.Command.CommandInfo(OnMacroCommandHandler) { HelpMessage = "Send and Execute a Macro By HTTP Requests", ShowInHelp = true }); InitMem(); hwnd = Process.GetCurrentProcess().MainWindowHandle; Port = Configuration.Port; //PluginLog.LogError($"HTTP server Started on http://localhost:{Port}!"); OnStartServer(); } catch (Exception ex) { PluginLog.LogError(ex.ToString()); } }
public PennyPincher() { configuration = PluginInterface.GetPluginConfig() as Configuration ?? new Configuration(); LoadConfig(); items = Data.GetExcelSheet <Item>(); newRequest = false; PluginInterface.UiBuilder.Draw += DrawWindow; PluginInterface.UiBuilder.OpenConfigUi += OpenConfigUi; CommandManager.AddHandler(commandName, new CommandInfo(Command) { HelpMessage = $"Opens the {Name} config menu", }); GameNetwork.NetworkMessage += OnNetworkEvent; try { var ptr = SigScanner.ScanText("E8 ?? ?? ?? ?? 48 85 C0 74 14 83 7B 44 00"); getFilePtr = Marshal.GetDelegateForFunctionPointer <GetFilePointer>(ptr); } catch (Exception e) { getFilePtr = null; PluginLog.LogError(e.ToString()); } }
/// <summary> /// Writes the position vector to memory. /// </summary> /// <param name="newPosition">Position vector to write.</param> public void WritePosition(Vector3 newPosition) { try { // Get the item from the structure to see when it's also invalid. var item = Marshal.ReadIntPtr(this.housingStructure + 0x18); // Ensure we have a valid pointer for the item. if (item == IntPtr.Zero) { return; } // Position offset from the selected item. var position = item + 0x50; unsafe { // Write the position to memory. *(Vector3 *)position = newPosition; } } catch (Exception ex) { PluginLog.LogError(ex, "Error occured while writing position."); } }
public void Initialize(DalamudPluginInterface pluginInterface) { this.pluginInterface = pluginInterface; ci = new ClientInterface(pluginInterface.TargetModuleScanner, pluginInterface.Data); try { var macroCallPtr = pluginInterface.TargetModuleScanner.ScanText("E8 ?? ?? ?? ?? E9 ?? ?? ?? ?? 48 8D 4D 28"); macroCallHook = new Hook <MacroCallDelegate>(macroCallPtr, new MacroCallDelegate(MacroCallDetour)); macroCallHook?.Enable(); pluginInterface.CommandManager.AddHandler("/nextmacro", new Dalamud.Game.Command.CommandInfo(OnMacroCommandHandler) { HelpMessage = "Executes the next macro.", ShowInHelp = true }); pluginInterface.CommandManager.AddHandler("/runmacro", new Dalamud.Game.Command.CommandInfo(OnRunMacroCommand) { HelpMessage = "Execute a macro (Not usable inside macros). - /runmacro ## [individual|shared].", ShowInHelp = true }); pluginInterface.Framework.OnUpdateEvent += FrameworkUpdate; } catch (Exception ex) { PluginLog.LogError(ex.ToString()); } }
public VolumeControls(SigScanner scanner, Action <ExpandoObject> onChange) { this.onChange = onChange; try { // I thought I'd need the user to change the settings manually once to get the the base address, // but the function is automatically called once when the player is initialized, so I'll settle for that. var setConfigurationPtr = scanner.ScanText("89 54 24 10 53 55 57 41 54 41 55 41 56 48 83 EC 48 8B C2 45 8B E0 44 8B D2 45 32 F6 44 8B C2 45 32 ED"); var setOption = Marshal.GetDelegateForFunctionPointer <SetOptionDelegate>(setConfigurationPtr); this.setOptionHook = new Hook <SetOptionDelegate>(setConfigurationPtr, new SetOptionDelegate((baseAddress, kind, value, unknown) => { BaseAddress = baseAddress; if (MasterVolume == null) { InitializeOptions(setOption); } #if DEBUG PluginLog.Log($"{baseAddress}, {kind}, {value}, {unknown}"); #endif return(this.setOptionHook.Original(baseAddress, kind, value, unknown)); })); this.setOptionHook.Enable(); } catch (Exception e) { PluginLog.LogError($"Failed to hook configuration set method! Full error:\n{e}"); } }
private async Task AddressUpdateLoop(CancellationToken token) { while (!token.IsCancellationRequested) { var lastAddress = SeAddress; try { SeAddress = this.addressDetector.GetAddress(Verbose); } catch (Exception e) { PluginLog.LogError(e, "Exception thrown in address detection function."); } if (!Equals(lastAddress, SeAddress)) { Reset = true; ResetRTT(); } else { Reset = false; } await Task.Delay(10000, token); // It's probably not that expensive, but it's not like the address is constantly changing, either. } }
private void MacroCallDetour(IntPtr a, IntPtr b) { macroCallHook?.Original(a, b); macroBasePtr = IntPtr.Zero; macroDataPtr = IntPtr.Zero; try { // Hack-y search for first macro lol var scanBack = b; var limit = 200; while (limit-- >= 0) { var macroDatHeaderCheck = Marshal.ReadInt64(scanBack, -40); if (macroDatHeaderCheck == 0x41442E4F5243414D) { macroDataPtr = scanBack; macroBasePtr = a; return; } scanBack -= 0x688; } PluginLog.LogError("Failed to find Macro[0]"); } catch (Exception ex) { PluginLog.LogError(ex.ToString()); } }
public RenderProcess(int pid, string pluginDir, DependencyManager dependencyManager) { keepAliveHandleName = $"BrowserHostRendererKeepAlive{pid}"; ipcChannelName = $"BrowserHostRendererIpcChannel{pid}"; ipc = new IpcBuffer <UpstreamIpcRequest, DownstreamIpcRequest>(ipcChannelName, request => Recieve?.Invoke(this, request)); var processArgs = new RenderProcessArguments() { ParentPid = pid, DalamudAssemblyDir = AppDomain.CurrentDomain.SetupInformation.ApplicationBase, CefAssemblyDir = dependencyManager.GetDependencyPathFor("cef"), CefCacheDir = Path.Combine(Path.GetDirectoryName(pluginDir), "cef-cache"), DxgiAdapterLuid = DxHandler.AdapterLuid, KeepAliveHandleName = keepAliveHandleName, IpcChannelName = ipcChannelName, }; process = new Process(); process.StartInfo = new ProcessStartInfo() { FileName = Path.Combine(pluginDir, "BrowserHost.Renderer.exe"), Arguments = processArgs.Serialise().Replace("\"", "\"\"\""), UseShellExecute = false, CreateNoWindow = true, RedirectStandardOutput = true, RedirectStandardError = true, }; process.OutputDataReceived += (sender, args) => PluginLog.Log($"[Render]: {args.Data}"); process.ErrorDataReceived += (sender, args) => PluginLog.LogError($"[Render]: {args.Data}"); }
protected override async Task PingLoop(CancellationToken token) { while (!token.IsCancellationRequested) { // Use decision tree to select best ping tracker try { var bestTracker = this.decisionTree.Execute(); if (!string.IsNullOrEmpty(bestTracker)) { ProcessBestResult(bestTracker); } else if (!string.IsNullOrEmpty(this.currentTracker)) { ProcessBestResult(this.currentTracker); } } catch (Exception e) { PluginLog.LogError(e, "Error in best ping tracker selection."); } await Task.Delay(3000, token); } }
private void CalculatePing(IntPtr dataPtr, ushort opcode, NetworkMessageDirection direction) { if (direction == NetworkMessageDirection.ZoneDown && opcode == this.predictedDownOpcode) { // The response packet has the same timestamp as the request packet, so we can just // take it from here instead of keeping state. var prevMs = (uint)Marshal.ReadInt32(dataPtr); if (QueryPerformanceCounter(out var nextNs)) { var nextMs = nextNs / 10000; this.pingMs = nextMs - prevMs; this.gotPing = true; if (Verbose) { PluginLog.LogDebug("Packet ping: {LastPing}ms", this.pingMs); } } else { PluginLog.LogError("Failed to call QueryPerformanceCounter! (How can this happen?)"); } } }
public static async void Hide(this GameObject a) { await Task.Run( () => { try { var addrRenderToggle = a.Address + 0x104; var renderToggle = Marshal.ReadInt32(addrRenderToggle); renderToggle |= (int)VisibilityFlags.Invisible; Marshal.WriteInt32(addrRenderToggle, renderToggle); } #if DEBUG catch (Exception ex) { PluginLog.LogError(ex.ToString()); #else catch (Exception) { // ignored #endif } }); }
private CurrencyOption GetCurrencyOption(uint itemId, string tag = null, string forceName = null) { try { if (!soldForCurrency.ContainsKey(itemId)) { soldForCurrency.Add(itemId, new HashSet <uint>()); } var sheet = data.Excel.GetSheet <Item>(); var item = sheet.GetRow(itemId); if (item == null) { return(new CurrencyOption() { Name = forceName ?? itemId.ToString(), ItemHashSet = soldForCurrency[itemId], Tag = tag?.ToLower() }); } return(new CurrencyOption() { Name = forceName ?? item.Name, ItemHashSet = soldForCurrency[itemId], Tag = tag?.ToLower() }); } catch (Exception ex) { PluginLog.Log($"Failed to get Currency Option for {itemId}"); PluginLog.LogError($"{ex}"); return(null); } }
private async void HideActor(Dalamud.Game.ClientState.Actors.Types.Actor a) { await Task.Run(async() => { try { var addrEntityType = a.Address + 0x8C; var addrRenderToggle = a.Address + 0x104; if (a is Dalamud.Game.ClientState.Actors.Types.PlayerCharacter) { Marshal.WriteByte(addrEntityType, 2); Marshal.WriteInt32(addrRenderToggle, 2050); //await Task.Delay(100); //Marshal.WriteInt32(addrRenderToggle, 0); await Task.Delay(100); Marshal.WriteByte(addrEntityType, 1); } else { Marshal.WriteInt32(addrRenderToggle, 2050); //await Task.Delay(10); //Marshal.WriteInt32(addrRenderToggle, 0); } } catch (Exception ex) { PluginLog.LogError(ex.ToString()); } }); }
private void UpdateItemList(int delay = 100) { errorLoadingItems = false; plugin.LuminaItems = null; plugin.LuminaItemsClientLanguage = pluginConfig.SelectedClientLanguage; Task.Run(async() => { await Task.Delay(delay); try { return(this.data.GetExcelSheet <Item>(pluginConfig.SelectedClientLanguage).Where(i => !string.IsNullOrEmpty(i.Name)).ToList()); } catch (Exception ex) { errorLoadingItems = true; PluginLog.LogError("Failed loading Items"); PluginLog.LogError(ex.ToString()); return(new List <Item>()); } }).ContinueWith(t => { if (errorLoadingItems) { return(plugin.LuminaItems); } forceReload = true; return(plugin.LuminaItems = t.Result); }); }
public static string FileSelect() { using var saveFileDialog = new SaveFileDialog { Filter = "PLS files (*.pls)|*.pls|XML files (*.xml)|*.xml|All files (*.*)|*.*", AddExtension = true, AutoUpgradeEnabled = true, InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), RestoreDirectory = true, ShowHelp = true, }; try { if (saveFileDialog.ShowDialog(null) != DialogResult.OK) { return(null); } } catch (Exception e) { PluginLog.LogError(e, e.Message); return(null); } return(saveFileDialog.FileName); }
private void OnFrameworkUpdate(Framework framework) { try { if (plugin.PluginInterface.ClientState.LocalPlayer == null) { return; } uint itemID; if (!searchQueue.TryDequeue(out itemID)) { return; } var uiObjectPtr = getUIObject(); if (uiObjectPtr.Equals(IntPtr.Zero)) { PluginLog.LogError("CraftingRecipeFinder: Null pointer returned from GetUIObject()"); return; } getUIAgentModule = Address.GetVirtualFunction <GetUIAgentModuleDelegate>(uiObjectPtr, 0, 34); var uiAgentModulePtr = getUIAgentModule(uiObjectPtr); if (uiAgentModulePtr.Equals(IntPtr.Zero)) { PluginLog.LogError("CraftingRecipeFinder: Null pointer returned from GetUIAgentModule()"); return; } var recipeAgentPtr = getAgentObject(uiAgentModulePtr, 22); if (recipeAgentPtr.Equals(IntPtr.Zero)) { PluginLog.LogError("CraftingRecipeFinder: Null pointer returned from GetAgentObject()"); return; } searchItemByCraftingMethod(recipeAgentPtr, itemID); } catch (NullReferenceException) { } }
public void Initialize(DalamudPluginInterface pluginInterface) { this.pi = pluginInterface; this.configuration = this.pi.GetPluginConfig() as Configuration ?? new Configuration(); this.configuration.Initialize(this.pi); this.items = this.pi.Data.GetExcelSheet <Item>(); this.newRequest = false; this.pi.CommandManager.AddHandler(commandName, new CommandInfo(OnCommand) { HelpMessage = $"Toggles {Name}. {commandName} {helpName} for additional options" }); this.pi.Framework.Network.OnNetworkMessage += OnNetworkEvent; try { var ptr = this.pi.TargetModuleScanner.ScanText("E8 ?? ?? ?? ?? 48 85 C0 74 14 83 7B 44 00"); this.getFilePtr = Marshal.GetDelegateForFunctionPointer <GetFilePointer>(ptr); } catch (Exception e) { this.getFilePtr = null; PluginLog.LogError(e.ToString()); } }
private Dictionary <string, LocalizationEntry> ReadFileWithLangCode(string langCode) { try { PluginLog.LogDebug($"Reading localization file with language code {langCode}..."); return(JsonConvert.DeserializeObject <Dictionary <string, LocalizationEntry> >( File.ReadAllText(Path.Combine( RichPresencePlugin.DalamudPluginInterface.AssemblyLocation.DirectoryName, "Resources", "loc", $"{PREFIX}{langCode}.json" )) )); } catch (Exception ex) { PluginLog.LogError(ex, $"File with language code {langCode} not loaded, using fallbacks..."); return(JsonConvert.DeserializeObject <Dictionary <string, LocalizationEntry> >( File.ReadAllText(Path.Combine( RichPresencePlugin.DalamudPluginInterface.AssemblyLocation.DirectoryName, "Resources", "loc", $"{PREFIX}{DEFAULT_DICT_LANGCODE}.json" )) )); } }
public static async void Rerender(this Actor a) { await Task.Run(async() => { try { var addrRenderToggle = a.Address + 0x104; var renderToggle = Marshal.ReadInt32(addrRenderToggle); if (a is PlayerCharacter) { renderToggle |= (int)VisibilityFlags.Invisible; Marshal.WriteInt32(addrRenderToggle, renderToggle); await Task.Delay(100); renderToggle &= ~(int)VisibilityFlags.Invisible; Marshal.WriteInt32(addrRenderToggle, renderToggle); await Task.Delay(100); } else { renderToggle |= (int)VisibilityFlags.Invisible; Marshal.WriteInt32(addrRenderToggle, renderToggle); await Task.Delay(10); renderToggle &= ~(int)VisibilityFlags.Invisible; Marshal.WriteInt32(addrRenderToggle, renderToggle); } } catch (Exception ex) { #if DEBUG PluginLog.LogError(ex.ToString()); #endif } }); }
private void InitializeProviders() { var ppType = typeof(IPlayerProvider); var assemblies = AppDomain.CurrentDomain.GetAssemblies(); var interfaces = new List <Type> { }; for (int i = 0; i < assemblies.Length; i++) { var potentiallyBad = assemblies[i]; try { interfaces.AddRange(potentiallyBad .GetTypes() .Where(type => ppType.IsAssignableFrom(type) && !type.IsInterface)); } catch (ReflectionTypeLoadException rtle) { PluginLog.LogError(rtle, rtle.Message, rtle.LoaderExceptions); PluginLog.LogError($"Error loading Assembly while searching for PlayerProviders: \"{potentiallyBad.FullName}\""); } } foreach (var playerProvider in interfaces) { PluginLog.Log("Found provider: " + playerProvider.FullName); InitializeProvider(playerProvider, (IPlayerProvider)Activator.CreateInstance(playerProvider)); } }
public static async void Render(this Actor a) { await Task.Run(() => { try { var addrRenderToggle = a.Address + 0x104; var renderToggle = Marshal.ReadInt32(addrRenderToggle); if ((renderToggle & (int)VisibilityFlags.Invisible) != (int)VisibilityFlags.Invisible && (a.ObjectKind != ObjectKind.MountType || (renderToggle & (int)VisibilityFlags.Unknown15) != (int)VisibilityFlags.Unknown15)) { return; } renderToggle &= ~(int)VisibilityFlags.Invisible; Marshal.WriteInt32(addrRenderToggle, renderToggle); } catch (Exception ex) { #if DEBUG PluginLog.LogError(ex.ToString()); #endif } }); }
protected override async Task PingLoop(CancellationToken token) { while (!token.IsCancellationRequested) { if (SeAddress != null) { try { var rtt = GetAddressLastRTT(SeAddress); var error = (WinError)Marshal.GetLastWin32Error(); Errored = error != WinError.NO_ERROR; if (!Errored) { NextRTTCalculation(rtt); } else { PluginLog.LogWarning($"Got Win32 error {error} when executing ping - this may be temporary and acceptable."); } } catch (Exception e) { Errored = true; PluginLog.LogError(e, "Error occurred when executing ping."); } } await Task.Delay(3000, token); } }
private async void HandleWindowSize() { var currentSize = ImGui.GetWindowContentRegionMax() - ImGui.GetWindowContentRegionMin(); if (currentSize == size || resizing) { return; } // If there isn't a size yet, we haven't rendered at all - boot up an inlay in the render process // TODO: Edge case - if a user _somehow_ makes the size zero, this will freak out and generate a new render inlay // TODO: Maybe consolidate the request types? dunno. var request = size == Vector2.Zero ? new NewInlayRequest() { Guid = RenderGuid, FrameTransportMode = config.FrameTransportMode, Url = inlayConfig.Url, Width = (int)currentSize.X, Height = (int)currentSize.Y, } : new ResizeInlayRequest() { Guid = RenderGuid, Width = (int)currentSize.X, Height = (int)currentSize.Y, } as DownstreamIpcRequest; resizing = true; var response = await renderProcess.Send <FrameTransportResponse>(request); if (!response.Success) { PluginLog.LogError("Texture build failure, retrying..."); resizing = false; return; } size = currentSize; resizing = false; var oldTextureHandler = textureHandler; try { textureHandler = response.Data switch { TextureHandleResponse textureHandleResponse => new SharedTextureHandler(textureHandleResponse), BitmapBufferResponse bitmapBufferResponse => new BitmapBufferTextureHandler(bitmapBufferResponse), _ => throw new Exception($"Unhandled frame transport {response.GetType().Name}"), }; } catch (Exception e) { textureRenderException = e; } if (oldTextureHandler != null) { oldTextureHandler.Dispose(); } }
public void LogError(string message, string detail_message = "") { //if (!Config.PrintError) return; var msg = $"[{Name}] {message}"; PluginLog.LogError(detail_message == "" ? msg : detail_message); ChatGui.PrintError(msg); }
public void LogError(string message) { //if (!Config.PrintError) return; var msg = $"[{Name}] {message}"; PluginLog.LogError(msg); Interface.Framework.Gui.Chat.PrintError(msg); }
//private SeString nowPlayingString; //private TextPayload currentSongPayload; public void Initialize(DalamudPluginInterface pluginInterface) { this.pi = pluginInterface; this.configuration = pluginInterface.GetPluginConfig() as Configuration ?? new Configuration(); this.configuration.Initialize(pluginInterface); this.enableFallbackPlayer = this.configuration.UseOldPlayback; this.localDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); var songlistPath = Path.Combine(this.localDir, songListFile); this.songList = new SongList(songlistPath, this.configuration, this, this); // TODO: eventually it might be nice to do this only if the fallback player isn't being used // and to add/remove it on-demand if that changes var addressResolver = new AddressResolver(); try { addressResolver.Setup(pluginInterface.TargetModuleScanner); this.bgmControl = new BGMControl(addressResolver); this.bgmControl.OnSongChanged += HandleSongChanged; this.bgmControl.OnSongChanged2 += HandleSongChanged2; this.bgmControl.StartUpdate(); } catch (Exception e) { PluginLog.LogError(e, "Failed to find BGM playback objects"); this.bgmControl?.Dispose(); this.bgmControl = null; this.enableFallbackPlayer = true; } // TODO: for new payload system // cached string so we don't have to rebuild this entire payload set each time //this.currentSongPayload = new TextPayload(""); // dummy, filled in when needed //this.nowPlayingString = new SeString(new Payload[] { // new TextPayload("Now playing "), // EmphasisItalicPayload.ItalicsOn, // this.currentSongPayload, // EmphasisItalicPayload.ItalicsOff, // new TextPayload(".") //}); // caches all the payloads - future updates will only have to reencode the song name payload // this.nowPlayingString.Encode(); pluginInterface.CommandManager.AddHandler(commandName, new CommandInfo(OnDisplayCommand) { HelpMessage = "Displays the orchestrion player, to view, change, or stop in-game BGM." }); pluginInterface.UiBuilder.OnBuildUi += Display; pluginInterface.UiBuilder.OnOpenConfigUi += (sender, args) => this.songList.SettingsVisible = true; this.songReplacementCfg = new SongReplacementList(this); }
private void RunImportTask() { _isImportRunning = true; Task.Run(async() => { var picker = new OpenFileDialog { Multiselect = true, Filter = "midi file (*.mid)|*.mid", CheckFileExists = true, Title = "Select a mid file" }; var result = await picker.ShowDialogAsync(); if (result == DialogResult.OK) { _hasError = false; foreach (var fileName in picker.FileNames) { PluginLog.Log($"-> {fileName} START"); try { //_texToolsImport = new TexToolsImport(new DirectoryInfo(_base._plugin!.Configuration!.CurrentCollection)); //_texToolsImport.ImportModPack(new FileInfo(fileName)); using (var f = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { var loaded = MidiFile.Read(f, readingSettings); //PluginLog.Log(f.Name); //PluginLog.LogDebug($"{loaded.OriginalFormat}, {loaded.TimeDivision}, Duration: {loaded.GetDuration<MetricTimeSpan>().Hours:00}:{loaded.GetDuration<MetricTimeSpan>().Minutes:00}:{loaded.GetDuration<MetricTimeSpan>().Seconds:00}:{loaded.GetDuration<MetricTimeSpan>().Milliseconds:000}"); //foreach (var chunk in loaded.Chunks) PluginLog.LogDebug($"{chunk}"); var substring = f.Name.Substring(f.Name.LastIndexOf('\\') + 1); PlaylistManager.Filelist.Add((loaded, substring.Substring(0, substring.LastIndexOf('.')))); config.Playlist.Add(fileName); } PluginLog.Log($"-> {fileName} OK!"); } catch (Exception ex) { PluginLog.LogError(ex, "Failed to import file at {0}", fileName); _hasError = true; } } //_texToolsImport = null; //_base.ReloadMods(); } _isImportRunning = false; }); }
public static string Name(this XivState condition) { if (ConditionNames.TryGetValue(condition, out string name)) { return(name); } PluginLog.LogError($"No name string found for condition '{condition.ToString()}'"); return(condition.ToString()); }
public static bool IsActive(this XivState condition, DalamudPluginInterface pi) { if (ConditionChecks.TryGetValue(condition, out var checkFunc)) { return(checkFunc(pi)); } PluginLog.LogError($"No check function found for condition '{condition.ToString()}'"); return(false); }