public async Task SendItemSaleEvent(SeString name, string iconurl, uint itemId, string message, XivChatType chatType) { var applicableChannels = this.plugin.Config.ChannelConfigs.Where(x => x.Value.ChatTypes.Contains(chatType)); if (!applicableChannels.Any()) { return; } message = this.specialChars.TransformToUnicode(message); PluginLog.Information($"Retainer sold itemID: {itemId} with iconurl: {iconurl}"); this.plugin.Config.PrefixConfigs.TryGetValue(chatType, out var prefix); foreach (var channelConfig in applicableChannels) { var socketChannel = this.socketClient.GetChannel(channelConfig.Key); if (socketChannel == null) { PluginLog.Error("Could not find channel {0} for {1}", channelConfig.Key, chatType); continue; } var webhookClient = await GetOrCreateWebhookClient(socketChannel); await webhookClient.SendMessageAsync($"{prefix} {message}", username : $"Retainer sold {name}", avatarUrl : iconurl); } }
// Discover new mods. public void DiscoverMods() { NewMods.Clear(); ModDiscoveryStarted?.Invoke(); _mods.Clear(); BasePath.Refresh(); if (Valid && BasePath.Exists) { foreach (var modFolder in BasePath.EnumerateDirectories()) { var mod = LoadMod(modFolder); if (mod == null) { continue; } mod.Index = _mods.Count; _mods.Add(mod); } } ModDiscoveryFinished?.Invoke(); PluginLog.Information("Rediscovered mods."); }
private void OnResourceRequested(Utf8GamePath data, bool synchronous) { var path = Match(data.Path); if (path != null) { PluginLog.Information($"{path} was requested {( synchronous ? "synchronously." : "asynchronously." )}"); } }
public ModInfo FindModSettings(string name) { var settings = ModSettings.FirstOrDefault( x => string.Equals(x.FolderName, name, StringComparison.InvariantCultureIgnoreCase) ); #if DEBUG PluginLog.Information("finding mod {ModName} - found: {ModSettingsExist}", name, settings != null); #endif return(settings); }
private void UpgradeToVersion3() { PluginLog.Information("Upgrading configuration to version 3"); foreach (var _ in Enum.GetValues(typeof(CustomComboPreset))) #pragma warning disable CS0618 // Type or member is obsolete { _HiddenActionsBacker.Add(false); } #pragma warning restore CS0618 // Type or member is obsolete Version = 3; }
protected DivinationPlugin(DalamudPluginInterface pluginInterface) { Instance = this as TPlugin ?? throw new TypeAccessException("クラス インスタンスが型パラメータ: TPlugin と一致しません。"); IsDisposed = false; Dalamud = new DalamudApi(pluginInterface); Divination = new DivinationApi <TConfiguration, TDefinition>(Dalamud, Assembly, this); PluginLog.Information("プラグイン: {Name} の初期化に成功しました。バージョン = {Version}", Name, Divination.Version.Plugin.InformationalVersion); }
protected override void Setup64Bit(SigScanner sig) { Offset1 = sig.ScanText("75 33 48 8B 0D ?? ?? ?? ?? BA ?? 00 00 00 48 83 C1 10 E8 ?? ?? ?? ?? 83 78"); Offset2 = sig.ScanText("74 18 8B D7 48 8D 0D"); PluginLog.Information( "Offset1: [\"ffxiv_dx11.exe\"+{0}]", (Offset1.ToInt64() - Process.GetCurrentProcess().MainModule.BaseAddress.ToInt64()).ToString("X") ); PluginLog.Information( "Offset2: [\"ffxiv_dx11.exe\"+{0}]", (Offset2.ToInt64() - Process.GetCurrentProcess().MainModule.BaseAddress.ToInt64()).ToString("X") ); }
internal static void Stop() { try { currentPlayback?.Stop(); currentPlayback?.MoveToTime(new MidiTimeSpan(0)); } catch (Exception e) { PluginLog.Information("Already stopped!"); } finally { currentPlayback = null; } }
public override void Update() { if (!queue.Any()) { return; } var item = queue.Dequeue(); PluginLog.Information("Dequeue: {0}", item); var entry = parseChat(item); if (entry != null) { Plugin.pi.Framework.Gui.Chat.PrintChat(entry); } }
public void CreateWebServer() { const string prefix = "http://localhost:42069/"; ShutdownWebServer(); _webServer = new WebServer(o => o .WithUrlPrefix(prefix) .WithMode(HttpListenerMode.EmbedIO)) .WithCors(prefix) .WithWebApi("/api", m => m .WithController(() => new ModsController(this))); _webServer.StateChanged += (s, e) => PluginLog.Information($"WebServer New State - {e.NewState}"); _webServer.RunAsync(); }
public ModInfo AddModSettings(ResourceMod mod) { var entry = new ModInfo { Priority = ModSettings.Count, FolderName = mod.ModBasePath.Name, Enabled = true, Mod = mod }; #if DEBUG PluginLog.Information("creating mod settings {ModName}", entry.FolderName); #endif ModSettings.Add(entry); return(entry); }
public void Initialize(DalamudPluginInterface pluginInterface) { services = new List <Service> { new ChatService() }; pi = pluginInterface; pi.Framework.OnUpdateEvent += OnUpdate; server = new WebSocketServer(10078); foreach (var serv in services) { serv.Enable(); } server.Start(); PluginLog.Information("Loaded"); }
public void GetTarget() { string messageText = ""; float coordX = 0; float coordY = 0; float scale = 100; var target = TargetManager.Target; var territoryType = ClientState.TerritoryType; var place = DataManager.GetExcelSheet <Map>(ClientState.ClientLanguage).FirstOrDefault(m => m.TerritoryType.Row == territoryType); var placeName = place.PlaceName.Row; scale = place.SizeFactor; var placeNameRow = DataManager.GetExcelSheet <PlaceName>(ClientState.ClientLanguage).GetRow(placeName).Name; if (target != null) { coordX = (float)ToMapCoordinate(target.Position.X, scale); coordY = (float)ToMapCoordinate(target.Position.Z, scale); messageText += placeNameRow; messageText += " X:" + coordX.ToString("#0.0"); messageText += " Y:" + coordY.ToString("#0.0"); var newMapLinkMessage = new MapLinkMessage( (ushort)XivChatType.Debug, target.Name.ToString(), messageText, coordX, coordY, scale, territoryType, placeNameRow, DateTime.Now ); Config.MapLinkMessageList.Add(newMapLinkMessage); if (Config.MapLinkMessageList.Count > Config.MaxRecordings) { var tempList = Config.MapLinkMessageList.OrderBy(e => e.RecordTime); Config.MapLinkMessageList.RemoveRange(0, Config.MapLinkMessageList.Count - Config.MaxRecordings); var infoMsg = $"There are too many records, truncated to the latest {Config.MaxRecordings} records"; PluginLog.Information(infoMsg); } } }
internal static void Play() { if (currentPlayback == null) { if (!PlaylistManager.Filelist.Any()) { PluginLog.Information("empty playlist"); } try { var valueTuple = PlaylistManager.Filelist[PlaylistManager.CurrentPlaying]; currentPlayback = valueTuple.GetFilePlayback(); } catch (Exception e) { try { currentPlayback = PlaylistManager.Filelist[0].GetFilePlayback(); PlaylistManager.CurrentPlaying = 0; } catch (Exception exception) { PluginLog.Error(exception, "error when getting playback."); } } } try { if (currentPlayback?.GetCurrentTime <MidiTimeSpan>() == currentPlayback?.GetDuration <MidiTimeSpan>()) { currentPlayback?.MoveToStart(); } currentPlayback?.Start(); } catch (Exception e) { PluginLog.Error(e, "error when try to start playing, maybe the playback has been disopsed?"); } }
private void UpgradeToVersion4() { #pragma warning disable CS0612,CS0618 // Type or member is obsolete PluginLog.Information("Upgrading configuration to version 4"); foreach (LegacyCustomComboPreset legacyPreset in Enum.GetValues(typeof(LegacyCustomComboPreset))) { if (_ComboPresetsBacker.HasFlag(legacyPreset)) { int legacyPresetIndex = (int)Math.Log((long)legacyPreset, 2); CustomComboPreset preset = (CustomComboPreset)legacyPresetIndex; if (Enum.IsDefined(typeof(CustomComboPreset), preset)) { EnabledActions.Add(preset); } } } _ComboPresetsBacker = 0; _HiddenActionsBacker = null; Version = 4; #pragma warning restore CS0612,CS0618 // Type or member is obsolete }
public void Initialize(DalamudPluginInterface pluginInterface) { _pluginInterface = pluginInterface; _commandManager = new Managers.CommandManager(pluginInterface); _configuration = pluginInterface.GetPluginConfig() as GatherBuddyConfiguration ?? new GatherBuddyConfiguration(); Gatherer = new Gatherer(pluginInterface, _configuration, _commandManager); Alarms = Gatherer.Alarms; _gatherInterface = new Interface(this, pluginInterface, _configuration); _fishingTimer = new FishingTimer(_pluginInterface, _configuration, Gatherer !.FishManager); var tmp = _pluginInterface.TargetModuleScanner.GetStaticAddressFromSig("0F 84 AD 01 00 00 49 89 5B 08 4C 8D 15"); PluginLog.Information($"Doop : {tmp.ToInt64():X16} {tmp.ToInt64() - _pluginInterface.TargetModuleScanner.Module.BaseAddress.ToInt64():X16}"); var count = _pluginInterface.Data.Excel.GetSheet <Lumina.Excel.GeneratedSheets.FishParameter>().Count(f => f.IsInLog); PluginLog.Information($"Derp : {tmp.ToInt64() + count / 8:X16} {tmp.ToInt64() - _pluginInterface.TargetModuleScanner.Module.BaseAddress.ToInt64() + count / 8:X16}"); if (!Gatherer !.FishManager.GetSaveFileName(_pluginInterface).Exists) { Gatherer !.FishManager.SaveFishRecords(_pluginInterface); }
public SkipCutscene() { if (Interface.GetPluginConfig() is not Config configuration || configuration.Version == 0) { configuration = new Config { IsEnabled = true, Version = 1 } } ; _config = configuration; Address = new CutsceneAddressResolver(); Address.Setup(SigScanner); if (Address.Offset1 != IntPtr.Zero && Address.Offset2 != IntPtr.Zero) { PluginLog.Information("Cutscene Offset Found."); if (_config.IsEnabled) { SetEnabled(true); } } else { PluginLog.Error("Cutscene Offset Not Found."); PluginLog.Warning("Plugin Disabling..."); Dispose(); return; } _csp = new RNGCryptoServiceProvider(); CommandManager.AddHandler("/sc", new CommandInfo(OnCommand) { HelpMessage = "/sc: Roll your sanity check dice." }); }
// Set the mod base directory. // If its not the first time, check if it is the same directory as before. // Also checks if the directory is available and tries to create it if it is not. private void SetBaseDirectory(string newPath, bool firstTime) { if (!firstTime && string.Equals(newPath, Penumbra.Config.ModDirectory, StringComparison.InvariantCultureIgnoreCase)) { return; } if (newPath.Length == 0) { Valid = false; BasePath = new DirectoryInfo("."); } else { var newDir = new DirectoryInfo(newPath); if (!newDir.Exists) { try { Directory.CreateDirectory(newDir.FullName); newDir.Refresh(); } catch (Exception e) { PluginLog.Error($"Could not create specified mod directory {newDir.FullName}:\n{e}"); } } BasePath = newDir; Valid = Directory.Exists(newDir.FullName); if (Penumbra.Config.ModDirectory != BasePath.FullName) { PluginLog.Information("Set new mod base directory from {OldDirectory:l} to {NewDirectory:l}.", Penumbra.Config.ModDirectory, BasePath.FullName); Penumbra.Config.ModDirectory = BasePath.FullName; Penumbra.Config.Save(); } } }
private void FrameworkOnOnUpdateEvent(Framework framework) { if (this.hasLoading != true) { return; } var unitBase = (AtkUnitBase *)this._pi.Framework.Gui.GetUiObjectByName("_LocationTitle", 1); if (unitBase != null) { var loadingImage = unitBase->UldManager.NodeList[4]; var imgNode = (AtkImageNode *)loadingImage; if (loadingImage == null) { return; } var asset = imgNode->PartsList->Parts[imgNode->PartId].UldAsset; if (loadingImage->Type == NodeType.Image && imgNode != null && asset != null) { var resource = asset->AtkTexture.Resource; if (resource == null) { return; } var name = resource->TexFileResourceHandle->ResourceHandle.FileName; if (name == null) { return; } var texName = Marshal.PtrToStringAnsi(new IntPtr(name)); if (!texName.Contains("loadingimage")) { var t = unitBase->UldManager.NodeList[4]; unitBase->UldManager.NodeList[4] = unitBase->UldManager.NodeList[5]; unitBase->UldManager.NodeList[5] = t; t->Flags_2 |= 0x1; loadingImage = unitBase->UldManager.NodeList[4]; PluginLog.Information("Swapped!"); } } loadingImage->Width = (ushort)this.width; loadingImage->Height = (ushort)this.height; loadingImage->ScaleX = this.scaleX; loadingImage->ScaleY = this.scaleY; loadingImage->X = this.X; loadingImage->Y = this.Y; loadingImage->Priority = 0; loadingImage->Flags_2 |= 0x1; this.hasLoading = false; } }
private void Chat_OnChatMessage(XivChatType type, uint senderId, ref SeString sender, ref SeString message, ref bool isHandled) { if (!Config.Recording) { return; } bool hasMapLink = false; float coordX = 0; float coordY = 0; float scale = 100; MapLinkPayload maplinkPayload = null; foreach (var payload in message.Payloads) { if (payload is MapLinkPayload mapLinkload) { maplinkPayload = mapLinkload; hasMapLink = true; // float fudge = 0.05f; scale = mapLinkload.TerritoryType.Map.Value.SizeFactor; // coordX = ConvertRawPositionToMapCoordinate(mapLinkload.RawX, scale) - fudge; // coordY = ConvertRawPositionToMapCoordinate(mapLinkload.RawY, scale) - fudge; coordX = mapLinkload.XCoord; coordY = mapLinkload.YCoord; Log($"TerritoryId: {mapLinkload.TerritoryType.RowId} {mapLinkload.PlaceName} ({coordX} ,{coordY})"); } } string messageText = message.TextValue; if (hasMapLink) { var newMapLinkMessage = new MapLinkMessage( (ushort)type, sender.TextValue, messageText, coordX, coordY, scale, maplinkPayload.TerritoryType.RowId, maplinkPayload.PlaceName, DateTime.Now ); bool filteredOut = false; if (sender.TextValue.ToLower() == "sonar") { filteredOut = true; } bool alreadyInList = Config.MapLinkMessageList.Any(w => { bool sameText = w.Text == newMapLinkMessage.Text; var timeoutMin = new TimeSpan(0, Config.FilterDupTimeout, 0); if (newMapLinkMessage.RecordTime < w.RecordTime + timeoutMin) { bool sameX = (int)(w.X * 10) == (int)(newMapLinkMessage.X * 10); bool sameY = (int)(w.Y * 10) == (int)(newMapLinkMessage.Y * 10); bool sameTerritory = w.TerritoryId == newMapLinkMessage.TerritoryId; return(sameTerritory && sameX && sameY); } return(sameText); }); if (Config.FilterDuplicates && alreadyInList) { filteredOut = true; } if (!filteredOut && Config.FilteredChannels.IndexOf((ushort)type) != -1) { filteredOut = true; } if (!filteredOut) { Config.MapLinkMessageList.Add(newMapLinkMessage); if (Config.MapLinkMessageList.Count > Config.MaxRecordings) { var tempList = Config.MapLinkMessageList.OrderBy(e => e.RecordTime); Config.MapLinkMessageList.RemoveRange(0, Config.MapLinkMessageList.Count - Config.MaxRecordings); var infoMsg = $"There are too many records, truncated to the latest {Config.MaxRecordings} records"; PluginLog.Information(infoMsg); } Config.Save(); } } }
// private TitleScreenMenu _titleScreenMenu; public TitleEditPlugin( [RequiredVersion("1.0")] DalamudPluginInterface pluginInterface, [RequiredVersion("1.0")] CommandManager commandManager, [RequiredVersion("1.0")] DataManager dataManager, [RequiredVersion("1.0")] ClientState clientState, [RequiredVersion("1.0")] Framework framework, [RequiredVersion("1.0")] KeyState keyState, [RequiredVersion("1.0")] SigScanner sigScanner, [RequiredVersion("1.0")] GameGui gameGui, [RequiredVersion("1.0")] TitleScreenMenu titleScreenMenu) { PluginLog.Log("===== T I T L E E D I T ====="); _pluginInterface = pluginInterface; _commandManager = commandManager; _dataManager = dataManager; _clientState = clientState; _framework = framework; _keyState = keyState; // Load menu_icon.png from dll resources var assembly = Assembly.GetExecutingAssembly(); var resourceStream = assembly.GetManifestResourceStream("TitleEdit.menu_icon.png"); if (resourceStream != null) { var imageBytes = new byte[resourceStream.Length]; resourceStream.Read(imageBytes, 0, (int)resourceStream.Length); PluginLog.Information($"image is {imageBytes.Length} bytes"); try { var image = pluginInterface.UiBuilder.LoadImage(imageBytes); titleScreenMenu.AddEntry("Title Edit Menu", image, () => { _isImguiTitleEditOpen = true; }); } catch (Exception e) { PluginLog.Error(e, "Title Edit encountered an error loading menu icon"); } } _commandManager.AddHandler(TitleEditCommand, new CommandInfo(OnTitleEditCommand) { HelpMessage = "Display the Title Edit configuration interface." }); _configuration = pluginInterface.GetPluginConfig() as TitleEditConfiguration ?? new TitleEditConfiguration(); _configuration.Initialize(pluginInterface); _titleScreenFolder = _pluginInterface.GetPluginConfigDirectory(); if (!Directory.Exists(_titleScreenFolder)) { Directory.CreateDirectory(_titleScreenFolder); } PrepareAssets(); EnumerateTitleScreenFiles(); _territoryPaths = dataManager.GetExcelSheet <TerritoryType>() .ToDictionary(row => row.RowId, row => row); _weathers = dataManager.GetExcelSheet <Weather>() .ToDictionary(row => row.RowId, row => row.Name.ToString()); var bgms = dataManager.GetExcelSheet <BGM>() .ToDictionary(row => (ushort)row.RowId, row => row.File.ToString()); _bgmSheet = new BgmSheetManager(_titleScreenFolder, bgms); _titleEdit = new TitleEdit(sigScanner, clientState, gameGui, dataManager, _pluginInterface, _configuration, _titleScreenFolder); _titleEdit.Enable(); _pluginInterface.UiBuilder.Draw += UiBuilder_OnBuildUi; _framework.Update += CheckHotkey; _pluginInterface.UiBuilder.OpenConfigUi += () => _isImguiTitleEditOpen = true; PluginLog.Log("Init complete."); }
private byte HandleTerriChangeDetour(IntPtr a1, uint a2, byte a3, byte a4, IntPtr a5) { this.toLoadingTerri = (int)a2; PluginLog.Information($"toLoadingTerri: {this.toLoadingTerri}"); return(this.handleTerriChangeHook.Original(a1, a2, a3, a4, a5)); }
protected override void OnMessage(MessageEventArgs e) { queue.Enqueue(e.Data); PluginLog.Information("Enqueue: {0}", e.Data); }
public void Load(bool invertOrder = false) { // find the collection json var collectionPath = Path.Combine(_basePath.FullName, "collection.json"); if (File.Exists(collectionPath)) { try { ModSettings = JsonConvert.DeserializeObject <List <ModInfo> >(File.ReadAllText(collectionPath)); ModSettings = ModSettings.OrderBy(x => x.Priority).ToList(); } catch (Exception e) { PluginLog.Error($"failed to read log collection information, failed path: {collectionPath}, err: {e.Message}"); } } #if DEBUG if (ModSettings != null) { foreach (var ms in ModSettings) { PluginLog.Information( "mod: {ModName} Enabled: {Enabled} Priority: {Priority}", ms.FolderName, ms.Enabled, ms.Priority ); } } #endif ModSettings ??= new(); var foundMods = new List <string>(); foreach (var modDir in _basePath.EnumerateDirectories()) { var metaFile = modDir.EnumerateFiles().FirstOrDefault(f => f.Name == "meta.json"); if (metaFile == null) { PluginLog.LogError("mod meta is missing for resource mod: {ResourceModLocation}", modDir); continue; } var meta = JsonConvert.DeserializeObject <ModMeta>(File.ReadAllText(metaFile.FullName)); var mod = new ResourceMod { Meta = meta, ModBasePath = modDir }; var modEntry = FindOrCreateModSettings(mod); foundMods.Add(modDir.Name); mod.RefreshModFiles(); } // remove any mods from the collection we didn't find ModSettings = ModSettings.Where( x => foundMods.Any( fm => string.Equals(x.FolderName, fm, StringComparison.InvariantCultureIgnoreCase) ) ).ToList(); // if anything gets removed above, the priority ordering gets f****d, so we need to resort and reindex them otherwise BAD THINGS HAPPEN ModSettings = ModSettings.OrderBy(x => x.Priority).ToList(); var p = 0; foreach (var modSetting in ModSettings) { modSetting.Priority = p++; } // reorder the resourcemods list so we can just directly iterate EnabledMods = GetOrderedAndEnabledModList(invertOrder).ToArray(); // write the collection metadata back to disk Save(); }
public Penumbra(CharacterUtility characterUtility) { CharacterUtility = characterUtility; Framework = new FrameworkManager(); Backup.CreateBackup(PenumbraBackupFiles()); Config = Configuration.Load(); MusicManager = new MusicManager(); if (Config.DisableSoundStreaming) { MusicManager.DisableStreaming(); } ResidentResources = new ResidentResourceManager(); Redirects = new SimpleRedirectManager(); MetaFileManager = new MetaFileManager(); ResourceLoader = new ResourceLoader(this); ResourceLogger = new ResourceLogger(ResourceLoader); ModManager = new Mod.Manager(Config.ModDirectory); ModManager.DiscoverMods(); CollectionManager = new ModCollection.Manager(ModManager); ModFileSystem = ModFileSystem.Load(); ObjectReloader = new ObjectReloader(); PathResolver = new PathResolver(ResourceLoader); Dalamud.Commands.AddHandler(CommandName, new CommandInfo(OnCommand) { HelpMessage = "/penumbra - toggle ui\n/penumbra reload - reload mod file lists & discover any new mods", }); ResidentResources.Reload(); SetupInterface(out _configWindow, out _launchButton, out _windowSystem); if (Config.EnableHttpApi) { CreateWebServer(); } ResourceLoader.EnableHooks(); if (Config.EnableMods) { ResourceLoader.EnableReplacements(); PathResolver.Enable(); } if (Config.DebugMode) { ResourceLoader.EnableDebug(); _configWindow.IsOpen = true; } if (Config.EnableFullResourceLogging) { ResourceLoader.EnableFullLogging(); } ResidentResources.Reload(); Api = new PenumbraApi(this); Ipc = new PenumbraIpc(Dalamud.PluginInterface, Api); SubscribeItemLinks(); if (ImcExceptions > 0) { PluginLog.Error($"{ImcExceptions} IMC Exceptions thrown. Please repair your game files."); } else { PluginLog.Information($"Penumbra Version {Version}, Commit #{CommitHash} successfully Loaded."); } }
private async Task SocketClientOnMessageReceived(SocketMessage message) { if (message.Author.IsBot || message.Author.IsWebhook) { return; } var args = message.Content.Split(); // if it doesn't start with the bot prefix, ignore it. if (!args[0].StartsWith(this.plugin.Config.DiscordBotPrefix)) { return; } /* * // this is only needed for debugging purposes. * foreach (var s in args) * { * PluginLog.Verbose(s); * } */ PluginLog.Verbose("Received command: {0}", args[0]); try { if (args[0] == this.plugin.Config.DiscordBotPrefix + "setchannel" && await EnsureOwner(message.Author, message.Channel)) { // Are there parameters? if (args.Length == 1) { await SendGenericEmbed(message.Channel, $"You need to specify some chat kinds to use.\nCheck the ``{this.plugin.Config.DiscordBotPrefix}help`` command for more information.", "Error", EmbedColorError); return; } var kinds = args[1].Split(',').Select(x => x.ToLower()); // Is there any chat type that's not recognized? if (kinds .Any(x => XivChatTypeExtensions.TypeInfoDict.All(y => y.Value.Slug != x) && x != "any")) { PluginLog.Verbose("Could not find kinds"); await SendGenericEmbed(message.Channel, $"One or more of the chat kinds you specified could not be found.\nCheck the ``{this.plugin.Config.DiscordBotPrefix}help`` command for more information.", "Error", EmbedColorError); return; } if (!this.plugin.Config.ChannelConfigs.TryGetValue(message.Channel.Id, out var config)) { config = new DiscordChannelConfig(); } foreach (var selectedKind in kinds) { PluginLog.Verbose(selectedKind); if (selectedKind == "any") { config.SetUnique(DefaultChatTypes); } else { var chatType = XivChatTypeExtensions.GetBySlug(selectedKind); config.SetUnique(chatType); } } this.plugin.Config.ChannelConfigs[message.Channel.Id] = config; this.plugin.Config.Save(); await SendGenericEmbed(message.Channel, $"OK! This channel has been set to receive the following chat kinds:\n\n```\n{config.ChatTypes.Select(x => $"{x.GetFancyName()}").Aggregate((x, y) => x + "\n" + y)}```", "Chat kinds set", EmbedColorFine); return; } if (args[0] == this.plugin.Config.DiscordBotPrefix + "unsetchannel" && await EnsureOwner(message.Author, message.Channel)) { // Are there parameters? if (args.Length == 1) { await SendGenericEmbed(message.Channel, $"You need to specify some chat kinds to use.\nCheck the ``{this.plugin.Config.DiscordBotPrefix}help`` command for more information.", "Error", EmbedColorError); return; } var kinds = args[1].Split(',').Select(x => x.ToLower()); // Is there any chat type that's not recognized? if (kinds.Any(x => XivChatTypeExtensions.TypeInfoDict.All(y => y.Value.Slug != x) && x != "any")) { await SendGenericEmbed(message.Channel, $"One or more of the chat kinds you specified could not be found.\nCheck the ``{this.plugin.Config.DiscordBotPrefix}help`` command for more information.", "Error", EmbedColorError); return; } if (!this.plugin.Config.ChannelConfigs.TryGetValue(message.Channel.Id, out var config)) { config = new DiscordChannelConfig(); } foreach (var selectedKind in kinds) { if (selectedKind == "any") { config.UnsetUnique(DefaultChatTypes); } else { var chatType = XivChatTypeExtensions.GetBySlug(selectedKind); config.UnsetUnique(chatType); } } this.plugin.Config.ChannelConfigs[message.Channel.Id] = config; this.plugin.Config.Save(); if (config.ChatTypes.Count() == 0) { await SendGenericEmbed(message.Channel, $"All chat kinds have been removed from this channel.", "Chat Kinds unset", EmbedColorFine); } await SendGenericEmbed(message.Channel, $"OK! This channel will still receive the following chat kinds:\n\n```\n{config.ChatTypes.Select(x => $"{x.GetSlug()} - {x.GetFancyName()}").Aggregate((x, y) => x + "\n" + y)}```", "Chat kinds unset", EmbedColorFine); return; } if (args[0] == this.plugin.Config.DiscordBotPrefix + "setprefix" && await EnsureOwner(message.Author, message.Channel)) { // Are there parameters? if (args.Length < 3) { await SendGenericEmbed(message.Channel, $"You need to specify some chat kinds and a prefix to use.\nCheck the ``{this.plugin.Config.DiscordBotPrefix}help`` command for more information.", "Error", EmbedColorError); return; } var kinds = args[1].Split(',').Select(x => x.ToLower()); // Is there any chat type that's not recognized? if (kinds.Any(x => XivChatTypeExtensions.TypeInfoDict.All(y => y.Value.Slug != x) && x != "any")) { await SendGenericEmbed(message.Channel, $"One or more of the chat kinds you specified could not be found.\nCheck the ``{this.plugin.Config.DiscordBotPrefix}help`` command for more information.", "Error", EmbedColorError); return; } if (args[2] == "none") { args[2] = string.Empty; } foreach (var selectedKind in kinds) { var type = XivChatTypeExtensions.GetBySlug(selectedKind); this.plugin.Config.PrefixConfigs[type] = args[2]; } this.plugin.Config.Save(); await SendGenericEmbed(message.Channel, $"OK! The following prefixes are set:\n\n```\n{this.plugin.Config.PrefixConfigs.Select(x => $"{x.Key.GetFancyName()} - {x.Value}").Aggregate((x, y) => x + "\n" + y)}```", "Prefix set", EmbedColorFine); return; } if (args[0] == this.plugin.Config.DiscordBotPrefix + "unsetprefix" && await EnsureOwner(message.Author, message.Channel)) { // Are there parameters? if (args.Length < 2) { await SendGenericEmbed(message.Channel, $"You need to specify some chat kinds and a prefix to use.\nCheck the ``{this.plugin.Config.DiscordBotPrefix}help`` command for more information.", "Error", EmbedColorError); return; } var kinds = args[1].Split(',').Select(x => x.ToLower()); // Is there any chat type that's not recognized? if (kinds.Any(x => XivChatTypeExtensions.TypeInfoDict.All(y => y.Value.Slug != x) && x != "any")) { await SendGenericEmbed(message.Channel, $"One or more of the chat kinds you specified could not be found.\nCheck the ``{this.plugin.Config.DiscordBotPrefix}help`` command for more information.", "Error", EmbedColorError); return; } foreach (var selectedKind in kinds) { var type = XivChatTypeExtensions.GetBySlug(selectedKind); this.plugin.Config.PrefixConfigs.Remove(type); } this.plugin.Config.Save(); if (this.plugin.Config.PrefixConfigs.Count() == 0) { await SendGenericEmbed(message.Channel, $"All prefixes have been removed.", "Prefix unset", EmbedColorFine); } else // this doesn't seem to trigger when there's only one entry left. I don't know why. { await SendGenericEmbed(message.Channel, $"OK! The prefix for {XivChatTypeExtensions.GetBySlug(args[2])} has been removed.\n\n" + $"The following prefixes are still set:\n\n```\n{this.plugin.Config.PrefixConfigs.Select(x => $"{x.Key.GetFancyName()} - {x.Value}").Aggregate((x, y) => x + "\n" + y)}```", "Prefix unset", EmbedColorFine); } return; } if (args[0] == this.plugin.Config.DiscordBotPrefix + "setchattypename" && await EnsureOwner(message.Author, message.Channel)) { // Are there parameters? if (args.Length < 3) { await SendGenericEmbed(message.Channel, $"You need to specify one or more chat kinds and a custom name.\nCheck the ``{this.plugin.Config.DiscordBotPrefix}help`` command for more information.", "Error", EmbedColorError); return; } var kinds = args[1].Split(',').Select(x => x.ToLower()); var chatChannelOverride = string.Join(" ", args.Skip(2)).Trim('"'); // PluginLog.Information($"arg1: {args[1]}; arg2: {chatChannelOverride}"); // Is there any chat type that's not recognized? if (kinds.Any(x => XivChatTypeExtensions.TypeInfoDict.All(y => y.Value.Slug != x) && x != "any")) { await SendGenericEmbed(message.Channel, $"One or more of the chat kinds you specified could not be found.\nCheck the ``{this.plugin.Config.DiscordBotPrefix}help`` command for more information.", "Error", EmbedColorError); return; } if (chatChannelOverride == "none") { foreach (var selectedKind in kinds) { var type = XivChatTypeExtensions.GetBySlug(selectedKind); this.plugin.Config.CustomSlugsConfigs[type] = type.GetSlug(); } await SendGenericEmbed(message.Channel, $"OK! The following custom chat type names have been set:\n\n```\n{this.plugin.Config.CustomSlugsConfigs.Select(x => $"{x.Key.GetFancyName()} - {x.Value}").Aggregate((x, y) => x + "\n" + y)}```", "Custom chat type set", EmbedColorFine); } else { foreach (var selectedKind in kinds) { var type = XivChatTypeExtensions.GetBySlug(selectedKind); this.plugin.Config.CustomSlugsConfigs[type] = chatChannelOverride; } await SendGenericEmbed(message.Channel, $"OK! The following custom chat type names have been set:\n\n```\n{this.plugin.Config.CustomSlugsConfigs.Select(x => $"{x.Key.GetFancyName()} - {x.Value}").Aggregate((x, y) => x + "\n" + y)}```", "Custom chat type set", EmbedColorFine); } this.plugin.Config.Save(); return; } if (args[0] == this.plugin.Config.DiscordBotPrefix + "unsetchattypename" && await EnsureOwner(message.Author, message.Channel)) { // Are there parameters? if (args.Length < 2) { await SendGenericEmbed(message.Channel, $"One or more of the chat kinds you specified could not be found.\nCheck the ``{this.plugin.Config.DiscordBotPrefix}help`` command for more information.", "Error", EmbedColorError); return; } var kinds = args[1].Split(',').Select(x => x.ToLower()); PluginLog.Information($"Unsetting custom type name for arg1: {args[1]}"); // Is there any chat type that's not recognized? if (kinds.Any(x => XivChatTypeExtensions.TypeInfoDict.All(y => y.Value.Slug != x) && x != "any")) { await SendGenericEmbed(message.Channel, $"One or more of the chat kinds you specified could not be found.\nCheck the ``{this.plugin.Config.DiscordBotPrefix}help`` command for more information.", "Error", EmbedColorError); return; } foreach (var selectedKind in kinds) { var type = XivChatTypeExtensions.GetBySlug(selectedKind); this.plugin.Config.CustomSlugsConfigs[type] = type.GetSlug(); } await SendGenericEmbed(message.Channel, $"OK! The following custom chat type names have been set:\n\n```\n{this.plugin.Config.CustomSlugsConfigs.Select(x => $"{x.Key.GetFancyName()} - {x.Value}").Aggregate((x, y) => x + "\n" + y)}```", "Custom chat type unset", EmbedColorFine); this.plugin.Config.Save(); return; } if (args[0] == this.plugin.Config.DiscordBotPrefix + "setduplicatems" && await EnsureOwner(message.Author, message.Channel)) { // Are there parameters? if (args.Length == 1) { await SendGenericEmbed(message.Channel, $"You need to specify a number in milliseconds to use.\nCheck the ``{this.plugin.Config.DiscordBotPrefix}help`` command for more information.", "Error", EmbedColorError); return; } var kinds = args[1].Split(',').Select(x => x.ToLower()); // Make sure that it's a number (or assume it is) int newDelay = int.Parse(args[1]); this.plugin.Config.DuplicateCheckMS = newDelay; this.plugin.Config.Save(); await SendGenericEmbed(message.Channel, $"OK! Any messages with the same content within the last **{newDelay}** milliseconds will be skipped, preventing duplicate posts.", "Duplicate Message Check", EmbedColorFine); return; } if (args[0] == this.plugin.Config.DiscordBotPrefix + "toggledf" && await EnsureOwner(message.Author, message.Channel)) { if (!this.plugin.Config.ChannelConfigs.TryGetValue(message.Channel.Id, out var config)) { config = new DiscordChannelConfig(); } config.IsContentFinder = !config.IsContentFinder; this.plugin.Config.ChannelConfigs[message.Channel.Id] = config; this.plugin.Config.Save(); await SendGenericEmbed(message.Channel, $"OK! This channel has been {(config.IsContentFinder ? "enabled" : "disabled")} from receiving Duty Finder notifications.", "Duty Finder set", EmbedColorFine); return; } if (args[0] == this.plugin.Config.DiscordBotPrefix + "setcfprefix" && await EnsureOwner(message.Author, message.Channel)) { // Are there parameters? if (args.Length < 2) { await SendGenericEmbed(message.Channel, $"You need to specify a prefix to use, or type \"none\" if you want to remove it.\nCheck the ``{this.plugin.Config.DiscordBotPrefix}help`` command for more information.", "Error", EmbedColorError); return; } if (args[1] == "none") { args[1] = string.Empty; } this.plugin.Config.CFPrefixConfig = args[1]; this.plugin.Config.Save(); await SendGenericEmbed(message.Channel, $"OK! The following prefix was set:\n\n```\n{this.plugin.Config.CFPrefixConfig}```", "Prefix set", EmbedColorFine); return; } if (args[0] == this.plugin.Config.DiscordBotPrefix + "listchannel" && await EnsureOwner(message.Author, message.Channel)) { if (!this.plugin.Config.ChannelConfigs.TryGetValue(message.Channel.Id, out var config)) { await SendGenericEmbed(message.Channel, $"You didn't set up any channel kinds for this channel yet.\nPlease use the ``{this.plugin.Config.DiscordBotPrefix}setchannel`` command to do this.", "Error", EmbedColorError); return; } if (config == null || config.ChatTypes.Count == 0) { await SendGenericEmbed(message.Channel, $"There are no channel kinds set for this channel right now.\nPlease use the ``{this.plugin.Config.DiscordBotPrefix}setchannel`` command to do this.", "Error", EmbedColorFine); return; } await SendGenericEmbed(message.Channel, $"OK! This channel has been set to receive the following chat kinds:\n\n```\n{config.ChatTypes.Select(x => $"{x.GetFancyName()}").Aggregate((x, y) => x + "\n" + y)}```", "Chat kinds set", EmbedColorFine); return; } if (args[0] == this.plugin.Config.DiscordBotPrefix + "help") { PluginLog.Verbose("Help time"); var builder = new EmbedBuilder() .WithTitle("Discord Bridge Help") .WithDescription("You can use the following commands to set up the Discord bridge.") .WithColor(new Color(EmbedColorFine)) .AddField($"{this.plugin.Config.DiscordBotPrefix}setchannel", "Select, which kinds of chat should arrive in this channel.\n" + $"Format: ``{this.plugin.Config.DiscordBotPrefix}setchannel <kind1,kind2,...>``\n\n" + $"See [this link for a list of all available chat kinds]({Constant.KindListLink}) or type ``any`` to enable it for all regular chat messages.") //$"The following chat kinds are available:\n```all - All regular chat\n{XivChatTypeExtensions.TypeInfoDict.Select(x => $"{x.Value.Slug} - {x.Value.FancyName}").Aggregate((x, y) => x + "\n" + y)}```") .AddField($"{this.plugin.Config.DiscordBotPrefix}unsetchannel", "Works like the previous command, but removes kinds of chat from the list of kinds that are sent to this channel.") .AddField($"{this.plugin.Config.DiscordBotPrefix}listchannel", "List all chat kinds that are sent to this channel.") .AddField($"{this.plugin.Config.DiscordBotPrefix}toggledf", "Enable or disable sending duty finder updates to this channel.") .AddField($"{this.plugin.Config.DiscordBotPrefix}setduplicatems", "Set time in milliseconds that the bot will check to see if any past messages were the same. Default is 0 ms.") .AddField($"{this.plugin.Config.DiscordBotPrefix}setprefix", "Set a prefix for chat kinds. " + $"This can be an emoji or a string that will be prepended to every chat message that will arrive with this chat kind. " + $"You can also set it to `none` if you want to remove it.\n" + $"Format: ``{this.plugin.Config.DiscordBotPrefix}setchannel <kind1,kind2,...> <prefix>``") .AddField($"{this.plugin.Config.DiscordBotPrefix}setcfprefix", "Set a prefix for duty finder posts. " + $"You can also set it to `none` if you want to remove it.\n" + $"Format: ``{this.plugin.Config.DiscordBotPrefix}setcfprefix <prefix>``") .AddField($"{this.plugin.Config.DiscordBotPrefix}setchattypename ", "Set custom text for chat kinds. " + $"This can be an emoji or a string that will replace the short name of a chat kind for every chat message that will arrive with this chat kind. " + $"You can also set it to `none` if you want to remove it.\n" + $"Format: ``{this.plugin.Config.DiscordBotPrefix}setchattypename <kind1,kind2,...> <custom text>``") .AddField($"{this.plugin.Config.DiscordBotPrefix}unsetprefix", "Remove prefix set for a chat kind. \n" + $"Format: ``{this.plugin.Config.DiscordBotPrefix}unsetprefix <kind>``") .AddField($"{this.plugin.Config.DiscordBotPrefix}unsetchattypename", "Remove custom name for a chat kind. \n" + $"Format: ``{this.plugin.Config.DiscordBotPrefix}unsetchattypename <kind>``") .AddField("Need more help?", $"You can [read the full step-by-step guide]({Constant.HelpLink}) or [join our Discord server]({Constant.DiscordJoinLink}) to ask for help.") .WithFooter(footer => { footer .WithText("Dalamud Discord Bridge") .WithIconUrl(Constant.LogoLink); }) .WithThumbnailUrl(Constant.LogoLink); var embed = builder.Build(); var m = await message.Channel.SendMessageAsync( null, embed : embed) .ConfigureAwait(false); ; PluginLog.Verbose(m.Id.ToString()); return; } } catch (Exception ex) { PluginLog.Error(ex, "Could not handle incoming Discord message."); } }
private int PrintIconPathDetour(IntPtr pathPtr, int iconId, int hq, int lang) { var r = this.printIconHook.Original(pathPtr, iconId, hq, lang); var terriRegion = this.terris.FirstOrDefault(x => x.PlaceNameRegionIcon == iconId); if (terriRegion != null) { PluginLog.Information($"LoadIcon: {iconId} detected for r:{terriRegion.RowId} with toLoadingTerri:{this.toLoadingTerri}"); try { if (this.toLoadingTerri == -1) { PluginLog.Information($"toLoadingImage not set!"); this.hasLoading = false; return(r); } if (this.cfcs.Any(x => x.ContentLinkType == 1 && x.TerritoryType.Row == this.toLoadingTerri)) { PluginLog.Information("Is InstanceContent zone!"); this.hasLoading = false; return(r); } var terriZone = this.terris.FirstOrDefault(x => x.RowId == this.toLoadingTerri); if (terriZone == null) { PluginLog.Information($"terriZone null!"); this.hasLoading = false; return(r); } if (terriZone.PlaceNameRegionIcon != terriRegion.PlaceNameRegionIcon) { PluginLog.Information($"Mismatch: {terriZone.RowId} {terriRegion.RowId}"); this.hasLoading = false; return(r); } var loading = this.loadings.FirstOrDefault(x => x.RowId == terriZone.LoadingImage); if (loading == null) { PluginLog.Information($"LoadingImage null!"); this.hasLoading = false; return(r); } SafeMemory.WriteString(pathPtr, $"ui/loadingimage/{loading.Name}_hr1.tex"); PluginLog.Information($"Replacing icon for territory {terriRegion.RowId}"); this.hasLoading = true; } catch (Exception ex) { PluginLog.Error(ex, "Could not replace loading image."); } } return(r); }