- Migrate config for API 15
- Migrate database for API 15
- Allow usage of new target source
- Implement first tell target option
This commit is contained in:
Infi
2026-04-30 02:59:58 +02:00
parent 68810e23c1
commit b4cb8b25ec
56 changed files with 1286 additions and 616 deletions
+5 -4
View File
@@ -4,6 +4,7 @@ using System.IO;
using System.Linq; using System.Linq;
using ChatTwo.Code; using ChatTwo.Code;
using ChatTwo.Util; using ChatTwo.Util;
using Dalamud.Game.Text;
using Dalamud.Game.Text.SeStringHandling; using Dalamud.Game.Text.SeStringHandling;
using Dalamud.Game.Text.SeStringHandling.Payloads; using Dalamud.Game.Text.SeStringHandling.Payloads;
using JetBrains.Annotations; using JetBrains.Annotations;
@@ -207,17 +208,17 @@ public class MessageStoreTest {
new TextChunk(ChunkSource.Content, new UriPayload(new Uri("https://dalamud.dev")), "chat 2 uri"), new TextChunk(ChunkSource.Content, new UriPayload(new Uri("https://dalamud.dev")), "chat 2 uri"),
]).ToList(); ]).ToList();
var chatCode = new ChatCode((XivChatType)46, XivChatRelationKind.LocalPlayer, XivChatRelationKind.EngagedEnemy);
return new Message( return new Message(
uniqId ? Guid.NewGuid() : Guid.Parse("f011343e-6a21-49e5-a6f9-238f0f1f8c2c"), uniqId ? Guid.NewGuid() : Guid.Parse("f011343e-6a21-49e5-a6f9-238f0f1f8c2c"),
receiver, receiver,
54321, 54321,
dateTime ?? DateTimeOffset.FromUnixTimeMilliseconds(1713520182440), dateTime ?? DateTimeOffset.FromUnixTimeMilliseconds(1713520182440),
new ChatCode(12345), chatCode,
ChunkUtil.ToChunks(senderSeString, ChunkSource.Sender, ChatType.Debug).ToList(), ChunkUtil.ToChunks(senderSeString, ChunkSource.Sender, ChatType.Debug).ToList(),
contentChunks, contentChunks,
senderSeString, senderSeString,
contentSeString, contentSeString,
new SortCode(ChatType.Crafting, ChatSource.AlliancePet),
extraChatId extraChatId
); );
} }
@@ -230,10 +231,10 @@ public class MessageStoreTest {
// Assert time is within 1 second // Assert time is within 1 second
var timeDifference = Math.Abs(input.Date.ToUniversalTime().Subtract(output.Date.ToUniversalTime()).TotalSeconds); var timeDifference = Math.Abs(input.Date.ToUniversalTime().Subtract(output.Date.ToUniversalTime()).TotalSeconds);
Assert.IsTrue(timeDifference < 1); Assert.IsTrue(timeDifference < 1);
Assert.AreEqual(input.Code.Raw, output.Code.Raw); Assert.AreEqual(input.Code, output.Code);
Assert.AreEqual($"{input.SenderSource.Encode():X}", $"{output.SenderSource.Encode():X}"); Assert.AreEqual($"{input.SenderSource.Encode():X}", $"{output.SenderSource.Encode():X}");
Assert.AreEqual($"{input.ContentSource.Encode():X}", $"{output.ContentSource.Encode():X}"); Assert.AreEqual($"{input.ContentSource.Encode():X}", $"{output.ContentSource.Encode():X}");
Assert.AreEqual(input.SortCode, output.SortCode); Assert.AreEqual(input.SortCodeV2, output.SortCodeV2);
Assert.AreEqual(input.ExtraChatChannel, output.ExtraChatChannel); Assert.AreEqual(input.ExtraChatChannel, output.ExtraChatChannel);
// Check chunks. // Check chunks.
+2 -10
View File
@@ -1,15 +1,7 @@
<Project Sdk="Dalamud.NET.Sdk/14.0.2"> <Project Sdk="Dalamud.NET.Sdk/15.0.0">
<PropertyGroup> <PropertyGroup>
<Version>1.34.7</Version> <Version>1.35.0</Version>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<ProduceReferenceAssembly>false</ProduceReferenceAssembly>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
<RestorePackagesWithLockFile>true</RestorePackagesWithLockFile>
<LangVersion>latest</LangVersion>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
+5 -10
View File
@@ -57,16 +57,11 @@ public enum ChunkSource
[MessagePackObject(AllowPrivate = true)] [MessagePackObject(AllowPrivate = true)]
public class TextChunk : Chunk public class TextChunk : Chunk
{ {
[Key(2)] [Key(2)] public ChatType? FallbackColour;
public ChatType? FallbackColour { get; set; } [Key(3)] public uint? Foreground;
[Key(3)] [Key(4)] public uint? Glow;
public uint? Foreground { get; set; } [Key(5)] public bool Italic;
[Key(4)] [Key(6)] public string Content;
public uint? Glow { get; set; }
[Key(5)]
public bool Italic { get; set; }
[Key(6)]
public string Content { get; set; }
private TextChunk(Chunk chunk, string content) : base(chunk.Source, chunk.Link) private TextChunk(Chunk chunk, string content) : base(chunk.Source, chunk.Link)
{ {
+35 -74
View File
@@ -1,84 +1,24 @@
using Dalamud.Game.Text;
namespace ChatTwo.Code; namespace ChatTwo.Code;
internal class ChatCode public class ChatCode
{ {
private const ushort Clear7 = ~(~0 << 7); public ChatType Type { get; }
public XivChatRelationKind Source { get; }
public XivChatRelationKind Target { get; }
internal ushort Raw { get; } public ChatCode(XivChatType type, XivChatRelationKind source, XivChatRelationKind target)
internal ChatType Type { get; }
internal ChatSource Source { get; }
internal ChatSource Target { get; }
private ChatSource SourceFrom(ushort shift) => (ChatSource) (1 << ((Raw >> shift) & 0xF));
internal ChatCode(ushort raw)
{ {
Raw = raw; Type = (ChatType)type;
Type = (ChatType) (Raw & Clear7); Source = source;
Source = SourceFrom(11); Target = target;
Target = SourceFrom(7);
} }
internal ChatType Parent() => Type switch public ChatCode(byte type, byte source, byte target)
{ : this((XivChatType)type, (XivChatRelationKind)source, (XivChatRelationKind)target) {}
ChatType.Say => ChatType.Say,
ChatType.GmSay => ChatType.Say,
ChatType.Shout => ChatType.Shout,
ChatType.GmShout => ChatType.Shout,
ChatType.TellOutgoing => ChatType.TellOutgoing,
ChatType.TellIncoming => ChatType.TellOutgoing,
ChatType.GmTell => ChatType.TellOutgoing,
ChatType.Party => ChatType.Party,
ChatType.CrossParty => ChatType.Party,
ChatType.GmParty => ChatType.Party,
ChatType.Linkshell1 => ChatType.Linkshell1,
ChatType.GmLinkshell1 => ChatType.Linkshell1,
ChatType.Linkshell2 => ChatType.Linkshell2,
ChatType.GmLinkshell2 => ChatType.Linkshell2,
ChatType.Linkshell3 => ChatType.Linkshell3,
ChatType.GmLinkshell3 => ChatType.Linkshell3,
ChatType.Linkshell4 => ChatType.Linkshell4,
ChatType.GmLinkshell4 => ChatType.Linkshell4,
ChatType.Linkshell5 => ChatType.Linkshell5,
ChatType.GmLinkshell5 => ChatType.Linkshell5,
ChatType.Linkshell6 => ChatType.Linkshell6,
ChatType.GmLinkshell6 => ChatType.Linkshell6,
ChatType.Linkshell7 => ChatType.Linkshell7,
ChatType.GmLinkshell7 => ChatType.Linkshell7,
ChatType.Linkshell8 => ChatType.Linkshell8,
ChatType.GmLinkshell8 => ChatType.Linkshell8,
ChatType.FreeCompany => ChatType.FreeCompany,
ChatType.GmFreeCompany => ChatType.FreeCompany,
ChatType.NoviceNetwork => ChatType.NoviceNetwork,
ChatType.GmNoviceNetwork => ChatType.NoviceNetwork,
ChatType.CustomEmote => ChatType.CustomEmote,
ChatType.StandardEmote => ChatType.StandardEmote,
ChatType.Yell => ChatType.Yell,
ChatType.GmYell => ChatType.Yell,
ChatType.GainBuff => ChatType.GainBuff,
ChatType.LoseBuff => ChatType.GainBuff,
ChatType.GainDebuff => ChatType.GainDebuff,
ChatType.LoseDebuff => ChatType.GainDebuff,
ChatType.System => ChatType.System,
ChatType.Alarm => ChatType.System,
ChatType.GlamourNotifications => ChatType.System,
ChatType.RetainerSale => ChatType.System,
ChatType.PeriodicRecruitmentNotification => ChatType.System,
ChatType.Sign => ChatType.System,
ChatType.Orchestrion => ChatType.System,
ChatType.MessageBook => ChatType.System,
ChatType.NpcDialogue => ChatType.NpcDialogue,
ChatType.NpcAnnouncement => ChatType.NpcDialogue,
ChatType.LootRoll => ChatType.LootRoll,
ChatType.RandomNumber => ChatType.LootRoll,
ChatType.FreeCompanyAnnouncement => ChatType.FreeCompanyAnnouncement,
ChatType.FreeCompanyLoginLogout => ChatType.FreeCompanyAnnouncement,
ChatType.PvpTeamAnnouncement => ChatType.PvpTeamAnnouncement,
ChatType.PvpTeamLoginLogout => ChatType.PvpTeamAnnouncement,
_ => Type,
};
internal bool IsBattle() public bool IsBattle()
{ {
switch (Type) switch (Type)
{ {
@@ -101,7 +41,7 @@ internal class ChatCode
} }
} }
internal bool IsPlayerMessage() public bool IsPlayerMessage()
{ {
switch (Type) switch (Type)
{ {
@@ -143,4 +83,25 @@ internal class ChatCode
return false; return false;
} }
} }
public int ToSortCodeV2()
{
return (byte)Type << 16 | (byte)Source << 8 | (byte)Target;
}
public override bool Equals(object? obj)
{
if (obj == null)
return false;
if (obj is not ChatCode code)
return false;
return GetHashCode() == code.GetHashCode();
}
public override int GetHashCode()
{
return (byte)Type << 16 | (byte)Source << 8 | (byte)Target;
}
} }
+36 -11
View File
@@ -1,17 +1,42 @@
using Dalamud.Game.Text;
namespace ChatTwo.Code; namespace ChatTwo.Code;
[Flags] [Flags]
public enum ChatSource : ushort public enum ChatSource : ushort
{ {
Self = 2, None = 0,
PartyMember = 4,
AllianceMember = 8, /// <summary>The player currently controlled by the local client.</summary>
Other = 16, LocalPlayer = 1 << XivChatRelationKind.LocalPlayer,
EngagedEnemy = 32,
UnengagedEnemy = 64, /// <summary>A player in the same 4-man or 8-man party as the local player.</summary>
FriendlyNpc = 128, PartyMember = 1 << XivChatRelationKind.PartyMember,
SelfPet = 256,
PartyPet = 512, /// <summary>A player in the same alliance raid.</summary>
AlliancePet = 1024, AllianceMember = 1 << XivChatRelationKind.AllianceMember,
OtherPet = 2048,
/// <summary>A player not in the local player's party or alliance.</summary>
OtherPlayer = 1 << XivChatRelationKind.OtherPlayer,
/// <summary>An enemy entity that is currently in combat with the player or party.</summary>
EngagedEnemy = 1 << XivChatRelationKind.EngagedEnemy,
/// <summary>An enemy entity that is not yet in combat or claimed.</summary>
UnengagedEnemy = 1 << XivChatRelationKind.UnengagedEnemy,
/// <summary>An NPC that is friendly or neutral to the player (e.g., EventNPCs).</summary>
FriendlyNpc = 1 << XivChatRelationKind.FriendlyNpc,
/// <summary>A pet (Summoner/Scholar) or companion (Chocobo) belonging to the local player.</summary>
PetOrCompanion = 1 << XivChatRelationKind.PetOrCompanion,
/// <summary>A pet or companion belonging to a member of the local player's party.</summary>
PetOrCompanionParty = 1 << XivChatRelationKind.PetOrCompanionParty,
/// <summary>A pet or companion belonging to a member of the alliance.</summary>
PetOrCompanionAlliance = 1 << XivChatRelationKind.PetOrCompanionAlliance,
/// <summary>A pet or companion belonging to a player not in the party or alliance.</summary>
PetOrCompanionOther = 1 << XivChatRelationKind.PetOrCompanionOther,
} }
+10 -10
View File
@@ -5,24 +5,24 @@ namespace ChatTwo.Code;
internal static class ChatSourceExt internal static class ChatSourceExt
{ {
internal const ChatSource All = internal const ChatSource All =
ChatSource.Self | ChatSource.PartyMember | ChatSource.AllianceMember | ChatSource.LocalPlayer | ChatSource.PartyMember | ChatSource.AllianceMember |
ChatSource.Other | ChatSource.EngagedEnemy | ChatSource.UnengagedEnemy | ChatSource.OtherPlayer | ChatSource.EngagedEnemy | ChatSource.UnengagedEnemy |
ChatSource.FriendlyNpc | ChatSource.SelfPet | ChatSource.PartyPet | ChatSource.FriendlyNpc | ChatSource.PetOrCompanion | ChatSource.PetOrCompanionParty |
ChatSource.AlliancePet | ChatSource.OtherPet; ChatSource.PetOrCompanionAlliance | ChatSource.PetOrCompanionOther;
internal static string Name(this ChatSource source) => source switch internal static string Name(this ChatSource source) => source switch
{ {
ChatSource.Self => Language.ChatSource_Self, ChatSource.LocalPlayer => Language.ChatSource_Self,
ChatSource.PartyMember => Language.ChatSource_PartyMember, ChatSource.PartyMember => Language.ChatSource_PartyMember,
ChatSource.AllianceMember => Language.ChatSource_AllianceMember, ChatSource.AllianceMember => Language.ChatSource_AllianceMember,
ChatSource.Other => Language.ChatSource_Other, ChatSource.OtherPlayer => Language.ChatSource_Other,
ChatSource.EngagedEnemy => Language.ChatSource_EngagedEnemy, ChatSource.EngagedEnemy => Language.ChatSource_EngagedEnemy,
ChatSource.UnengagedEnemy => Language.ChatSource_UnengagedEnemy, ChatSource.UnengagedEnemy => Language.ChatSource_UnengagedEnemy,
ChatSource.FriendlyNpc => Language.ChatSource_FriendlyNpc, ChatSource.FriendlyNpc => Language.ChatSource_FriendlyNpc,
ChatSource.SelfPet => Language.ChatSource_SelfPet, ChatSource.PetOrCompanion => Language.ChatSource_SelfPet,
ChatSource.PartyPet => Language.ChatSource_PartyPet, ChatSource.PetOrCompanionParty => Language.ChatSource_PartyPet,
ChatSource.AlliancePet => Language.ChatSource_AlliancePet, ChatSource.PetOrCompanionAlliance => Language.ChatSource_AlliancePet,
ChatSource.OtherPet => Language.ChatSource_OtherPet, ChatSource.PetOrCompanionOther => Language.ChatSource_OtherPet,
_ => throw new ArgumentOutOfRangeException(nameof(source), source, null), _ => throw new ArgumentOutOfRangeException(nameof(source), source, null),
}; };
} }
+59
View File
@@ -424,4 +424,63 @@ internal static class ChatTypeExt
ChatType.PvpTeamLoginLogout => true, ChatType.PvpTeamLoginLogout => true,
_ => false, _ => false,
}; };
internal static ChatType Parent(this ChatType type) => type switch
{
ChatType.Say => ChatType.Say,
ChatType.GmSay => ChatType.Say,
ChatType.Shout => ChatType.Shout,
ChatType.GmShout => ChatType.Shout,
ChatType.TellOutgoing => ChatType.TellOutgoing,
ChatType.TellIncoming => ChatType.TellOutgoing,
ChatType.GmTell => ChatType.TellOutgoing,
ChatType.Party => ChatType.Party,
ChatType.CrossParty => ChatType.Party,
ChatType.GmParty => ChatType.Party,
ChatType.Linkshell1 => ChatType.Linkshell1,
ChatType.GmLinkshell1 => ChatType.Linkshell1,
ChatType.Linkshell2 => ChatType.Linkshell2,
ChatType.GmLinkshell2 => ChatType.Linkshell2,
ChatType.Linkshell3 => ChatType.Linkshell3,
ChatType.GmLinkshell3 => ChatType.Linkshell3,
ChatType.Linkshell4 => ChatType.Linkshell4,
ChatType.GmLinkshell4 => ChatType.Linkshell4,
ChatType.Linkshell5 => ChatType.Linkshell5,
ChatType.GmLinkshell5 => ChatType.Linkshell5,
ChatType.Linkshell6 => ChatType.Linkshell6,
ChatType.GmLinkshell6 => ChatType.Linkshell6,
ChatType.Linkshell7 => ChatType.Linkshell7,
ChatType.GmLinkshell7 => ChatType.Linkshell7,
ChatType.Linkshell8 => ChatType.Linkshell8,
ChatType.GmLinkshell8 => ChatType.Linkshell8,
ChatType.FreeCompany => ChatType.FreeCompany,
ChatType.GmFreeCompany => ChatType.FreeCompany,
ChatType.NoviceNetwork => ChatType.NoviceNetwork,
ChatType.GmNoviceNetwork => ChatType.NoviceNetwork,
ChatType.CustomEmote => ChatType.CustomEmote,
ChatType.StandardEmote => ChatType.StandardEmote,
ChatType.Yell => ChatType.Yell,
ChatType.GmYell => ChatType.Yell,
ChatType.GainBuff => ChatType.GainBuff,
ChatType.LoseBuff => ChatType.GainBuff,
ChatType.GainDebuff => ChatType.GainDebuff,
ChatType.LoseDebuff => ChatType.GainDebuff,
ChatType.System => ChatType.System,
ChatType.Alarm => ChatType.System,
ChatType.GlamourNotifications => ChatType.System,
ChatType.RetainerSale => ChatType.System,
ChatType.PeriodicRecruitmentNotification => ChatType.System,
ChatType.Sign => ChatType.System,
ChatType.Orchestrion => ChatType.System,
ChatType.MessageBook => ChatType.System,
ChatType.NpcDialogue => ChatType.NpcDialogue,
ChatType.NpcAnnouncement => ChatType.NpcDialogue,
ChatType.LootRoll => ChatType.LootRoll,
ChatType.RandomNumber => ChatType.LootRoll,
ChatType.FreeCompanyAnnouncement => ChatType.FreeCompanyAnnouncement,
ChatType.FreeCompanyLoginLogout => ChatType.FreeCompanyAnnouncement,
ChatType.PvpTeamAnnouncement => ChatType.PvpTeamAnnouncement,
ChatType.PvpTeamLoginLogout => ChatType.PvpTeamAnnouncement,
_ => type,
};
} }
+21 -21
View File
@@ -80,25 +80,25 @@ internal static class InputChannelExt
InputChannel.Alliance => "/alliance", InputChannel.Alliance => "/alliance",
InputChannel.Yell => "/yell", InputChannel.Yell => "/yell",
InputChannel.Shout => "/shout", InputChannel.Shout => "/shout",
InputChannel.FreeCompany => "/freecompany", InputChannel.FreeCompany => "/fc",
InputChannel.PvpTeam => "/pvpteam", InputChannel.PvpTeam => "/pt",
InputChannel.NoviceNetwork => "/beginner", InputChannel.NoviceNetwork => "/n",
InputChannel.CrossLinkshell1 => "/cwlinkshell1", InputChannel.CrossLinkshell1 => "/cwl1",
InputChannel.CrossLinkshell2 => "/cwlinkshell2", InputChannel.CrossLinkshell2 => "/cwl2",
InputChannel.CrossLinkshell3 => "/cwlinkshell3", InputChannel.CrossLinkshell3 => "/cwl3",
InputChannel.CrossLinkshell4 => "/cwlinkshell4", InputChannel.CrossLinkshell4 => "/cwl4",
InputChannel.CrossLinkshell5 => "/cwlinkshell5", InputChannel.CrossLinkshell5 => "/cwl5",
InputChannel.CrossLinkshell6 => "/cwlinkshell6", InputChannel.CrossLinkshell6 => "/cwl6",
InputChannel.CrossLinkshell7 => "/cwlinkshell7", InputChannel.CrossLinkshell7 => "/cwl7",
InputChannel.CrossLinkshell8 => "/cwlinkshell8", InputChannel.CrossLinkshell8 => "/cwl8",
InputChannel.Linkshell1 => "/linkshell1", InputChannel.Linkshell1 => "/l1",
InputChannel.Linkshell2 => "/linkshell2", InputChannel.Linkshell2 => "/l2",
InputChannel.Linkshell3 => "/linkshell3", InputChannel.Linkshell3 => "/l3",
InputChannel.Linkshell4 => "/linkshell4", InputChannel.Linkshell4 => "/l4",
InputChannel.Linkshell5 => "/linkshell5", InputChannel.Linkshell5 => "/l5",
InputChannel.Linkshell6 => "/linkshell6", InputChannel.Linkshell6 => "/l6",
InputChannel.Linkshell7 => "/linkshell7", InputChannel.Linkshell7 => "/l7",
InputChannel.Linkshell8 => "/linkshell8", InputChannel.Linkshell8 => "/l8",
InputChannel.ExtraChatLinkshell1 => "/ecl1", InputChannel.ExtraChatLinkshell1 => "/ecl1",
InputChannel.ExtraChatLinkshell2 => "/ecl2", InputChannel.ExtraChatLinkshell2 => "/ecl2",
InputChannel.ExtraChatLinkshell3 => "/ecl3", InputChannel.ExtraChatLinkshell3 => "/ecl3",
@@ -112,7 +112,7 @@ internal static class InputChannelExt
public static IEnumerable<TextCommand>? TextCommands(this InputChannel channel) public static IEnumerable<TextCommand>? TextCommands(this InputChannel channel)
{ {
var ids = channel switch uint[] ids = channel switch
{ {
InputChannel.Tell => [104, 118], InputChannel.Tell => [104, 118],
InputChannel.Say => [102], InputChannel.Say => [102],
@@ -139,7 +139,7 @@ internal static class InputChannelExt
InputChannel.Linkshell6 => [112], InputChannel.Linkshell6 => [112],
InputChannel.Linkshell7 => [113], InputChannel.Linkshell7 => [113],
InputChannel.Linkshell8 => [114], InputChannel.Linkshell8 => [114],
_ => Array.Empty<uint>(), _ => []
}; };
if (ids.Length == 0) if (ids.Length == 0)
+66 -47
View File
@@ -12,7 +12,7 @@ using Dalamud.Bindings.ImGui;
namespace ChatTwo; namespace ChatTwo;
[Serializable] [Serializable]
internal class ConfigKeyBind public class ConfigKeyBind
{ {
public ModifierFlag Modifier; public ModifierFlag Modifier;
public VirtualKey Key; public VirtualKey Key;
@@ -31,9 +31,9 @@ internal class ConfigKeyBind
} }
[Serializable] [Serializable]
internal class Configuration : IPluginConfiguration public class Configuration : IPluginConfiguration
{ {
private const int LatestVersion = 5; private const int LatestVersion = 6;
public int Version { get; set; } = LatestVersion; public int Version { get; set; } = LatestVersion;
@@ -46,7 +46,11 @@ internal class Configuration : IPluginConfiguration
public bool HideWhenInactive; public bool HideWhenInactive;
public int InactivityHideTimeout = 10; public int InactivityHideTimeout = 10;
public bool InactivityHideActiveDuringBattle = true; public bool InactivityHideActiveDuringBattle = true;
public Dictionary<ChatType, ChatSource>? InactivityHideChannels;
[Obsolete("Use InactivityHideChannelsV2 instead")]
public Dictionary<ChatType, ChatSource> InactivityHideChannels = [];
public Dictionary<ChatType, (ChatSource, ChatSource)> InactivityHideChannelsV2 = [];
public bool InactivityHideExtraChatAll = true; public bool InactivityHideExtraChatAll = true;
public HashSet<Guid> InactivityHideExtraChatChannels = []; public HashSet<Guid> InactivityHideExtraChatChannels = [];
public bool ShowHideButton = true; public bool ShowHideButton = true;
@@ -88,18 +92,18 @@ internal class Configuration : IPluginConfiguration
public SingleFontSpec GlobalFontV2 = new() public SingleFontSpec GlobalFontV2 = new()
{ {
// dalamud only ships KR as regular, which chat2 used previously for global fonts // dalamud only ships KR as regular, which chat2 used previously for global fonts
FontId = new DalamudAssetFontAndFamilyId(DalamudAsset.NotoSansKrRegular), FontId = new DalamudAssetFontAndFamilyId(DalamudAsset.NotoSansCjkRegular),
SizePt = 12.75f, SizePt = 12.75f,
}; };
public SingleFontSpec JapaneseFontV2 = new() public SingleFontSpec JapaneseFontV2 = new()
{ {
FontId = new DalamudAssetFontAndFamilyId(DalamudAsset.NotoSansJpMedium), FontId = new DalamudAssetFontAndFamilyId(DalamudAsset.NotoSansCjkMedium),
SizePt = 12.75f, SizePt = 12.75f,
}; };
public bool ItalicEnabled; public bool ItalicEnabled;
public SingleFontSpec ItalicFontV2 = new() public SingleFontSpec ItalicFontV2 = new()
{ {
FontId = new DalamudAssetFontAndFamilyId(DalamudAsset.NotoSansKrRegular), FontId = new DalamudAssetFontAndFamilyId(DalamudAsset.NotoSansCjkRegular),
SizePt = 12.75f, SizePt = 12.75f,
}; };
@@ -122,7 +126,7 @@ internal class Configuration : IPluginConfiguration
public HashSet<string> AuthStore = []; public HashSet<string> AuthStore = [];
public int WebinterfaceMaxLinesToSend = 1000; // 1-10000 public int WebinterfaceMaxLinesToSend = 1000; // 1-10000
internal void UpdateFrom(Configuration other, bool backToOriginal) public void UpdateFrom(Configuration other, bool backToOriginal)
{ {
if (backToOriginal) if (backToOriginal)
foreach (var tab in Tabs.Where(t => t.PopOut)) foreach (var tab in Tabs.Where(t => t.PopOut))
@@ -137,7 +141,7 @@ internal class Configuration : IPluginConfiguration
HideWhenInactive = other.HideWhenInactive; HideWhenInactive = other.HideWhenInactive;
InactivityHideTimeout = other.InactivityHideTimeout; InactivityHideTimeout = other.InactivityHideTimeout;
InactivityHideActiveDuringBattle = other.InactivityHideActiveDuringBattle; InactivityHideActiveDuringBattle = other.InactivityHideActiveDuringBattle;
InactivityHideChannels = other.InactivityHideChannels?.ToDictionary(entry => entry.Key, entry => entry.Value); InactivityHideChannelsV2 = other.InactivityHideChannelsV2.ToDictionary(pair => pair.Key, pair => pair.Value);
InactivityHideExtraChatAll = other.InactivityHideExtraChatAll; InactivityHideExtraChatAll = other.InactivityHideExtraChatAll;
InactivityHideExtraChatChannels = other.InactivityHideExtraChatChannels.ToHashSet(); InactivityHideExtraChatChannels = other.InactivityHideExtraChatChannels.ToHashSet();
ShowHideButton = other.ShowHideButton; ShowHideButton = other.ShowHideButton;
@@ -195,14 +199,14 @@ internal class Configuration : IPluginConfiguration
} }
[Serializable] [Serializable]
internal enum UnreadMode public enum UnreadMode
{ {
All, All,
Unseen, Unseen,
None, None,
} }
internal static class UnreadModeExt public static class UnreadModeExt
{ {
internal static string Name(this UnreadMode mode) => mode switch internal static string Name(this UnreadMode mode) => mode switch
{ {
@@ -222,10 +226,14 @@ internal static class UnreadModeExt
} }
[Serializable] [Serializable]
internal class Tab public class Tab
{ {
public string Name = Language.Tab_DefaultName; public string Name = Language.Tab_DefaultName;
[Obsolete("Removed in favor of SelectedChannels")]
public Dictionary<ChatType, ChatSource> ChatCodes = new(); public Dictionary<ChatType, ChatSource> ChatCodes = new();
public Dictionary<ChatType, (ChatSource, ChatSource)> SelectedChannels = new();
public bool ExtraChatAll; public bool ExtraChatAll;
public HashSet<Guid> ExtraChatChannels = []; public HashSet<Guid> ExtraChatChannels = [];
@@ -249,6 +257,10 @@ internal class Tab
public bool HideInBattle; public bool HideInBattle;
public bool HideWhenInactive; public bool HideWhenInactive;
public bool IsTempTab;
public bool AllSenderMessages;
public TellTarget TellTarget = TellTarget.Empty();
[NonSerialized] public uint Unread; [NonSerialized] public uint Unread;
[NonSerialized] public uint LastSendUnread; [NonSerialized] public uint LastSendUnread;
[NonSerialized] public long LastActivity; [NonSerialized] public long LastActivity;
@@ -258,27 +270,31 @@ internal class Tab
[NonSerialized] public Guid Identifier = Guid.NewGuid(); [NonSerialized] public Guid Identifier = Guid.NewGuid();
internal bool Matches(Message message) => message.Matches(ChatCodes, ExtraChatAll, ExtraChatChannels); public bool Matches(Message message)
{
return message.Matches(SelectedChannels, ExtraChatAll, ExtraChatChannels);
}
internal void AddMessage(Message message, bool unread = true) public void AddMessage(Message message, bool unread = true)
{ {
Messages.AddPrune(message, MessageManager.MessageDisplayLimit); Messages.AddPrune(message, MessageManager.MessageDisplayLimit);
if (!unread) if (!unread)
return; return;
Unread += 1; Unread += 1;
if (message.Matches(Plugin.Config.InactivityHideChannels!, Plugin.Config.InactivityHideExtraChatAll, Plugin.Config.InactivityHideExtraChatChannels)) if (message.Matches(Plugin.Config.InactivityHideChannelsV2, Plugin.Config.InactivityHideExtraChatAll, Plugin.Config.InactivityHideExtraChatChannels))
LastActivity = Environment.TickCount64; LastActivity = Environment.TickCount64;
} }
internal void Clear() => Messages.Clear(); public void Clear()
=> Messages.Clear();
internal Tab Clone() public Tab Clone()
{ {
return new Tab return new Tab
{ {
Name = Name, Name = Name,
ChatCodes = ChatCodes.ToDictionary(entry => entry.Key, entry => entry.Value), SelectedChannels = SelectedChannels.ToDictionary(pair => pair.Key, pair => pair.Value),
ExtraChatAll = ExtraChatAll, ExtraChatAll = ExtraChatAll,
ExtraChatChannels = ExtraChatChannels.ToHashSet(), ExtraChatChannels = ExtraChatChannels.ToHashSet(),
UnreadMode = UnreadMode, UnreadMode = UnreadMode,
@@ -302,6 +318,9 @@ internal class Tab
HideInLoadingScreens = HideInLoadingScreens, HideInLoadingScreens = HideInLoadingScreens,
HideInBattle = HideInBattle, HideInBattle = HideInBattle,
HideWhenInactive = HideWhenInactive, HideWhenInactive = HideWhenInactive,
IsTempTab = IsTempTab,
AllSenderMessages = AllSenderMessages,
TellTarget = TellTarget.From(TellTarget),
}; };
} }
@@ -309,7 +328,7 @@ internal class Tab
/// MessageList provides an ordered list of messages with duplicate ID /// MessageList provides an ordered list of messages with duplicate ID
/// tracking, sorting and mutex protection. /// tracking, sorting and mutex protection.
/// </summary> /// </summary>
internal class MessageList public class MessageList
{ {
private readonly SemaphoreSlim LockSlim = new(1, 1); private readonly SemaphoreSlim LockSlim = new(1, 1);
@@ -422,7 +441,7 @@ internal class Tab
return new RLockedMessageList(LockSlim, Messages); return new RLockedMessageList(LockSlim, Messages);
} }
internal class RLockedMessageList(SemaphoreSlim lockSlim, List<Message> messages) : IReadOnlyList<Message>, IDisposable public class RLockedMessageList(SemaphoreSlim lockSlim, List<Message> messages) : IReadOnlyList<Message>, IDisposable
{ {
public IEnumerator<Message> GetEnumerator() public IEnumerator<Message> GetEnumerator()
{ {
@@ -446,31 +465,31 @@ internal class Tab
} }
} }
internal class UsedChannel public class UsedChannel
{ {
internal InputChannel Channel = InputChannel.Invalid; public InputChannel Channel = InputChannel.Invalid;
internal List<Chunk> Name = []; public List<Chunk> Name = [];
internal TellTarget? TellTarget; public TellTarget? TellTarget;
internal bool UseTempChannel; public bool UseTempChannel;
internal InputChannel TempChannel = InputChannel.Invalid; public InputChannel TempChannel = InputChannel.Invalid;
internal TellTarget? TempTellTarget; public TellTarget? TempTellTarget;
internal void ResetTempChannel() public void ResetTempChannel()
{ {
UseTempChannel = false; UseTempChannel = false;
TempTellTarget = null; TempTellTarget = null;
TempChannel = InputChannel.Invalid; TempChannel = InputChannel.Invalid;
} }
internal void SetChannel(InputChannel channel) public void SetChannel(InputChannel channel)
{ {
Channel = channel; Channel = channel;
} }
} }
[Serializable] [Serializable]
internal enum PreviewPosition public enum PreviewPosition
{ {
None, None,
Inside, Inside,
@@ -479,9 +498,9 @@ internal enum PreviewPosition
Tooltip, Tooltip,
} }
internal static class PreviewPositionExt public static class PreviewPositionExt
{ {
internal static string Name(this PreviewPosition position) => position switch public static string Name(this PreviewPosition position) => position switch
{ {
PreviewPosition.None => Language.Options_Preview_None, PreviewPosition.None => Language.Options_Preview_None,
PreviewPosition.Inside => Language.Options_Preview_Inside, PreviewPosition.Inside => Language.Options_Preview_Inside,
@@ -493,16 +512,16 @@ internal static class PreviewPositionExt
} }
[Serializable] [Serializable]
internal enum CommandHelpSide public enum CommandHelpSide
{ {
None, None,
Left, Left,
Right, Right,
} }
internal static class CommandHelpSideExt public static class CommandHelpSideExt
{ {
internal static string Name(this CommandHelpSide side) => side switch public static string Name(this CommandHelpSide side) => side switch
{ {
CommandHelpSide.None => Language.CommandHelpSide_None, CommandHelpSide.None => Language.CommandHelpSide_None,
CommandHelpSide.Left => Language.CommandHelpSide_Left, CommandHelpSide.Left => Language.CommandHelpSide_Left,
@@ -512,22 +531,22 @@ internal static class CommandHelpSideExt
} }
[Serializable] [Serializable]
internal enum KeybindMode public enum KeybindMode
{ {
Flexible, Flexible,
Strict, Strict,
} }
internal static class KeybindModeExt public static class KeybindModeExt
{ {
internal static string Name(this KeybindMode mode) => mode switch public static string Name(this KeybindMode mode) => mode switch
{ {
KeybindMode.Flexible => Language.KeybindMode_Flexible_Name, KeybindMode.Flexible => Language.KeybindMode_Flexible_Name,
KeybindMode.Strict => Language.KeybindMode_Strict_Name, KeybindMode.Strict => Language.KeybindMode_Strict_Name,
_ => throw new ArgumentOutOfRangeException(nameof(mode), mode, null), _ => throw new ArgumentOutOfRangeException(nameof(mode), mode, null),
}; };
internal static string? Tooltip(this KeybindMode mode) => mode switch public static string? Tooltip(this KeybindMode mode) => mode switch
{ {
KeybindMode.Flexible => Language.KeybindMode_Flexible_Tooltip, KeybindMode.Flexible => Language.KeybindMode_Flexible_Tooltip,
KeybindMode.Strict => Language.KeybindMode_Strict_Tooltip, KeybindMode.Strict => Language.KeybindMode_Strict_Tooltip,
@@ -536,7 +555,7 @@ internal static class KeybindModeExt
} }
[Serializable] [Serializable]
internal enum LanguageOverride public enum LanguageOverride
{ {
None, None,
ChineseSimplified, ChineseSimplified,
@@ -559,9 +578,9 @@ internal enum LanguageOverride
Swedish, Swedish,
} }
internal static class LanguageOverrideExt public static class LanguageOverrideExt
{ {
internal static string Name(this LanguageOverride mode) => mode switch public static string Name(this LanguageOverride mode) => mode switch
{ {
LanguageOverride.None => Language.LanguageOverride_None, LanguageOverride.None => Language.LanguageOverride_None,
LanguageOverride.ChineseSimplified => "简体中文", LanguageOverride.ChineseSimplified => "简体中文",
@@ -583,7 +602,7 @@ internal static class LanguageOverrideExt
_ => throw new ArgumentOutOfRangeException(nameof(mode), mode, null), _ => throw new ArgumentOutOfRangeException(nameof(mode), mode, null),
}; };
internal static string Code(this LanguageOverride mode) => mode switch public static string Code(this LanguageOverride mode) => mode switch
{ {
LanguageOverride.None => "", LanguageOverride.None => "",
LanguageOverride.ChineseSimplified => "zh-hans", LanguageOverride.ChineseSimplified => "zh-hans",
@@ -608,7 +627,7 @@ internal static class LanguageOverrideExt
[Serializable] [Serializable]
[Flags] [Flags]
internal enum ExtraGlyphRanges public enum ExtraGlyphRanges
{ {
ChineseFull = 1 << 0, ChineseFull = 1 << 0,
ChineseSimplifiedCommon = 1 << 1, ChineseSimplifiedCommon = 1 << 1,
@@ -619,9 +638,9 @@ internal enum ExtraGlyphRanges
Vietnamese = 1 << 6, Vietnamese = 1 << 6,
} }
internal static class ExtraGlyphRangesExt public static class ExtraGlyphRangesExt
{ {
internal static string Name(this ExtraGlyphRanges ranges) => ranges switch public static string Name(this ExtraGlyphRanges ranges) => ranges switch
{ {
ExtraGlyphRanges.ChineseFull => Language.ExtraGlyphRanges_ChineseFull_Name, ExtraGlyphRanges.ChineseFull => Language.ExtraGlyphRanges_ChineseFull_Name,
ExtraGlyphRanges.ChineseSimplifiedCommon => Language.ExtraGlyphRanges_ChineseSimplifiedCommon_Name, ExtraGlyphRanges.ChineseSimplifiedCommon => Language.ExtraGlyphRanges_ChineseSimplifiedCommon_Name,
@@ -633,7 +652,7 @@ internal static class ExtraGlyphRangesExt
_ => throw new ArgumentOutOfRangeException(nameof(ranges), ranges, null), _ => throw new ArgumentOutOfRangeException(nameof(ranges), ranges, null),
}; };
internal static unsafe nint Range(this ExtraGlyphRanges ranges) => ranges switch public static unsafe nint Range(this ExtraGlyphRanges ranges) => ranges switch
{ {
ExtraGlyphRanges.ChineseFull => (nint)ImGui.GetIO().Fonts.GetGlyphRangesChineseFull(), ExtraGlyphRanges.ChineseFull => (nint)ImGui.GetIO().Fonts.GetGlyphRangesChineseFull(),
ExtraGlyphRanges.ChineseSimplifiedCommon => (nint)ImGui.GetIO().Fonts.GetGlyphRangesChineseSimplifiedCommon(), ExtraGlyphRanges.ChineseSimplifiedCommon => (nint)ImGui.GetIO().Fonts.GetGlyphRangesChineseSimplifiedCommon(),
+12 -8
View File
@@ -28,24 +28,28 @@ public static class EmoteCache
private const string Top100Emotes = "{0}/emotes/shared/top?before={1}&limit=100"; private const string Top100Emotes = "{0}/emotes/shared/top?before={1}&limit=100";
private const string EmotePath = "https://cdn.betterttv.net/emote/{0}/3x"; private const string EmotePath = "https://cdn.betterttv.net/emote/{0}/3x";
private struct Top100 [Serializable]
private struct Top100()
{ {
[JsonPropertyName("emote")] [JsonPropertyName("emote")]
public Emote Emote { get; set; } public Emote Emote = default;
[JsonPropertyName("id")] [JsonPropertyName("id")]
public string Id { get; set; } public string Id = string.Empty;
} }
public struct Emote [Serializable]
public struct Emote()
{ {
[JsonPropertyName("id")] [JsonPropertyName("id")]
public string Id { get; set; } public string Id = string.Empty;
[JsonPropertyName("code")] [JsonPropertyName("code")]
public string Code { get; set; } public string Code = string.Empty;
[JsonPropertyName("imageType")] [JsonPropertyName("imageType")]
public string ImageType { get; set; } public string ImageType = string.Empty;
}; }
public enum LoadingState public enum LoadingState
{ {
+13 -8
View File
@@ -8,18 +8,18 @@ namespace ChatTwo;
public class FontManager public class FontManager
{ {
internal IFontHandle Axis { get; private set; } internal IFontHandle Axis = null!;
internal IFontHandle AxisItalic { get; private set; } internal IFontHandle AxisItalic = null!;
internal IFontHandle RegularFont { get; private set; } internal IFontHandle RegularFont = null!;
internal IFontHandle? ItalicFont { get; private set; } internal IFontHandle? ItalicFont;
internal IFontHandle FontAwesome { get; private set; } internal IFontHandle FontAwesome = null!;
internal readonly byte[] GameSymFont; internal readonly byte[] GameSymFont;
private ushort[] Ranges; private ushort[] Ranges = [];
private ushort[] JpRange; private ushort[] JpRange = [];
public static readonly HashSet<float> AxisFontSizeList = public static readonly HashSet<float> AxisFontSizeList =
[ [
@@ -69,10 +69,15 @@ public class FontManager
} }
} }
// Ingame supported ranges
var reader = new FdtReader(Plugin.DataManager.GetFile("common/font/axis_12.fdt")!.Data);
foreach (var c in reader.Glyphs)
builder.AddChar(c.Char);
// various symbols // various symbols
// French // French
// Romanian // Romanian
builder.AddText("←→↑↓《》■※☀★★☆♥♡ヅツッシ☀☁☂℃℉°♀♂♠♣♦♣♧®©™€$£♯♭♪✓√◎◆◇♦■□〇●△▽▼▲‹›≤≥<«“”─\~"); // builder.AddText("←→↑↓《》■※☀★★☆♥♡ヅツッシ☀☁☂℃℉°♀♂♠♣♦♣♧®©™€$£♯♭♪✓√◎◆◇♦■□〇●△▽▼▲‹›≤≥<«“”─\~");
builder.AddText("Œœ"); builder.AddText("Œœ");
builder.AddText("ĂăÂâÎîȘșȚț"); builder.AddText("ĂăÂâÎîȘșȚț");
+14 -14
View File
@@ -20,7 +20,7 @@ using FFXIVClientStructs.FFXIV.Component.GUI;
using InteropGenerator.Runtime; using InteropGenerator.Runtime;
using Lumina.Text.ReadOnly; using Lumina.Text.ReadOnly;
using ValueType = FFXIVClientStructs.FFXIV.Component.GUI.ValueType; using ValueType = FFXIVClientStructs.FFXIV.Component.GUI.AtkValueType;
namespace ChatTwo.GameFunctions; namespace ChatTwo.GameFunctions;
@@ -35,21 +35,21 @@ internal sealed unsafe class Chat : IDisposable
// Client::UI::AddonChatLog.OnRefresh // Client::UI::AddonChatLog.OnRefresh
[Signature("40 53 57 41 57 48 81 EC ?? ?? ?? ?? 48 8B 05 ?? ?? ?? ?? 48 33 C4 48 89 84 24 ?? ?? ?? ?? 4D 8B F8", DetourName = nameof(ChatLogRefreshDetour))] [Signature("40 53 57 41 57 48 81 EC ?? ?? ?? ?? 48 8B 05 ?? ?? ?? ?? 48 33 C4 48 89 84 24 ?? ?? ?? ?? 4D 8B F8", DetourName = nameof(ChatLogRefreshDetour))]
private Hook<ChatLogRefreshDelegate>? ChatLogRefreshHook { get; init; } private Hook<ChatLogRefreshDelegate>? ChatLogRefreshHook = null!;
private delegate byte ChatLogRefreshDelegate(nint log, ushort eventId, AtkValue* value); private delegate byte ChatLogRefreshDelegate(nint log, ushort eventId, AtkValue* value);
// Replace with CS version later // Replace with CS version later
[Signature("48 89 5C 24 ?? 55 56 57 48 81 EC ?? ?? ?? ?? 48 8B 05 ?? ?? ?? ?? 48 33 C4 48 89 84 24 ?? ?? ?? ?? 83 B9", DetourName = nameof(ContextMenuTellInForayDetour))] [Signature("48 89 5C 24 ?? 55 56 57 48 81 EC ?? ?? ?? ?? 48 8B 05 ?? ?? ?? ?? 48 33 C4 48 89 84 24 ?? ?? ?? ?? 83 B9", DetourName = nameof(ContextMenuTellInForayDetour))]
private Hook<ContextMenuTellInForayDelegate>? ContextMenuTellInForayHook { get; set; } private Hook<ContextMenuTellInForayDelegate>? ContextMenuTellInForayHook = null!;
private delegate void ContextMenuTellInForayDelegate(RaptureShellModule* module, Utf8String* playerName, Utf8String* worldName, ushort worldId, ulong accountId, ulong contentId, ushort reason); private delegate void ContextMenuTellInForayDelegate(RaptureShellModule* module, Utf8String* playerName, Utf8String* worldName, ushort worldId, ulong accountId, ulong contentId, ushort reason);
private Hook<AgentChatLog.Delegates.ChangeChannelName> ChangeChannelNameHook { get; init; } private readonly Hook<AgentChatLog.Delegates.ChangeChannelName>? ChangeChannelNameHook;
private Hook<RaptureShellModule.Delegates.ReplyInSelectedChatMode>? ReplyInSelectedChatModeHook { get; init; } private readonly Hook<RaptureShellModule.Delegates.ReplyInSelectedChatMode>? ReplyInSelectedChatModeHook;
private Hook<RaptureShellModule.Delegates.SetContextTellTarget>? SetChatLogTellTargetHook { get; init; } private readonly Hook<RaptureShellModule.Delegates.SetContextTellTarget>? SetChatLogTellTargetHook;
// Pointers // Pointers
[Signature("48 8D 35 ?? ?? ?? ?? 8B 05", ScanType = ScanType.StaticAddress)] [Signature("48 8D 1D ?? ?? ?? ?? 8B 05", ScanType = ScanType.StaticAddress)]
private readonly char* CurrentCharacter = null!; private readonly char* LastTypedCharacter = null!;
private Plugin Plugin { get; } private Plugin Plugin { get; }
@@ -64,7 +64,7 @@ internal sealed unsafe class Chat : IDisposable
private long LastPlayerNameDisplayTypeRefresh; private long LastPlayerNameDisplayTypeRefresh;
private PlayerNameDisplayType CurrentPlayerNameDisplayType = PlayerNameDisplayType.FullName; private PlayerNameDisplayType CurrentPlayerNameDisplayType = PlayerNameDisplayType.FullName;
internal Chat(Plugin plugin) public Chat(Plugin plugin)
{ {
Plugin = plugin; Plugin = plugin;
Plugin.GameInteropProvider.InitializeFromAttributes(this); Plugin.GameInteropProvider.InitializeFromAttributes(this);
@@ -131,7 +131,7 @@ internal sealed unsafe class Chat : IDisposable
// If this function ever returns 0, it returns null instead. // If this function ever returns 0, it returns null instead.
internal uint? GetChannelColor(ChatType type) internal uint? GetChannelColor(ChatType type)
{ {
var parent = new ChatCode((ushort) type).Parent(); var parent = type.Parent();
switch (parent) switch (parent)
{ {
case ChatType.Debug: case ChatType.Debug:
@@ -169,7 +169,7 @@ internal sealed unsafe class Chat : IDisposable
if (eventId != 0x31 || value == null || value->UInt is not (0x05 or 0x0C)) if (eventId != 0x31 || value == null || value->UInt is not (0x05 or 0x0C))
return ChatLogRefreshHook!.Original(log, eventId, value); return ChatLogRefreshHook!.Original(log, eventId, value);
if (Plugin.Functions.KeybindManager.DirectChat && CurrentCharacter != null) if (Plugin.Functions.KeybindManager.DirectChat && LastTypedCharacter != null)
{ {
// FIXME: this whole system sucks // FIXME: this whole system sucks
// FIXME v2: I hate everything about this, but it works // FIXME v2: I hate everything about this, but it works
@@ -177,7 +177,7 @@ internal sealed unsafe class Chat : IDisposable
{ {
string? input = null; string? input = null;
var utf8Bytes = MemoryHelper.ReadRaw((nint)CurrentCharacter+0x4, 2); var utf8Bytes = MemoryHelper.ReadRaw((nint)LastTypedCharacter+0x4, 2);
var chars = Encoding.UTF8.GetString(utf8Bytes).ToCharArray(); var chars = Encoding.UTF8.GetString(utf8Bytes).ToCharArray();
if (chars.Length == 0) if (chars.Length == 0)
return; return;
@@ -230,7 +230,7 @@ internal sealed unsafe class Chat : IDisposable
private CStringPointer ChangeChannelNameDetour(AgentChatLog* agent) private CStringPointer ChangeChannelNameDetour(AgentChatLog* agent)
{ {
var ret = ChangeChannelNameHook.Original(agent); var ret = ChangeChannelNameHook!.Original(agent);
if (agent == null) if (agent == null)
return ret; return ret;
@@ -572,6 +572,6 @@ internal sealed unsafe class Chat : IDisposable
// second before the cutscene actually starts, because the game sets // second before the cutscene actually starts, because the game sets
// the cutscene conditions before processing the skip. // the cutscene conditions before processing the skip.
var raptureAtkUnitManager = RaptureAtkUnitManager.Instance(); var raptureAtkUnitManager = RaptureAtkUnitManager.Instance();
return raptureAtkUnitManager == null || raptureAtkUnitManager->UiFlags.HasFlag(UIModule.UiFlags.Chat); return raptureAtkUnitManager == null || raptureAtkUnitManager->UiFlags.HasFlag(UiFlags.Chat);
} }
} }
+4 -3
View File
@@ -1,4 +1,5 @@
using System.Text; using System.Text;
using ChatTwo.Resources;
using Dalamud.Memory; using Dalamud.Memory;
using FFXIVClientStructs.FFXIV.Client.System.String; using FFXIVClientStructs.FFXIV.Client.System.String;
using FFXIVClientStructs.FFXIV.Client.UI; using FFXIVClientStructs.FFXIV.Client.UI;
@@ -18,13 +19,13 @@ public unsafe class ChatBox
{ {
var bytes = Encoding.UTF8.GetBytes(message); var bytes = Encoding.UTF8.GetBytes(message);
if (bytes.Length == 0) if (bytes.Length == 0)
throw new ArgumentException("message is empty", nameof(message)); throw new ArgumentException(Language.ChatBox_Error_Empty, nameof(message));
if (bytes.Length > 500) if (bytes.Length > 500)
throw new ArgumentException("message is longer than 500 bytes", nameof(message)); throw new ArgumentException(Language.ChatBox_Error_Too_Long, nameof(message));
if (message.Length != SanitiseText(message).Length) if (message.Length != SanitiseText(message).Length)
throw new ArgumentException("message contained invalid characters", nameof(message)); throw new ArgumentException(Language.ChatBox_Error_Invalid, nameof(message));
SendMessageUnsafe(bytes); SendMessageUnsafe(bytes);
} }
+3 -3
View File
@@ -14,7 +14,7 @@ using FFXIVClientStructs.FFXIV.Client.UI.Info;
using FFXIVClientStructs.FFXIV.Component.GUI; using FFXIVClientStructs.FFXIV.Component.GUI;
using Lumina.Excel; using Lumina.Excel;
using Lumina.Excel.Sheets; using Lumina.Excel.Sheets;
using ValueType = FFXIVClientStructs.FFXIV.Component.GUI.ValueType; using ValueType = FFXIVClientStructs.FFXIV.Component.GUI.AtkValueType;
namespace ChatTwo.GameFunctions; namespace ChatTwo.GameFunctions;
@@ -22,7 +22,7 @@ internal unsafe class GameFunctions : IDisposable
{ {
#region Hooks #region Hooks
[Signature("E8 ?? ?? ?? ?? 48 85 C0 0F 84 ?? ?? ?? ?? 48 8B D0 49 8D 4F", DetourName = nameof(ResolveTextCommandPlaceholderDetour))] [Signature("E8 ?? ?? ?? ?? 48 85 C0 0F 84 ?? ?? ?? ?? 48 8B D0 49 8D 4F", DetourName = nameof(ResolveTextCommandPlaceholderDetour))]
private Hook<ResolveTextCommandPlaceholderDelegate>? ResolveTextCommandPlaceholderHook { get; init; } private Hook<ResolveTextCommandPlaceholderDelegate>? ResolveTextCommandPlaceholderHook = null!;
private delegate nint ResolveTextCommandPlaceholderDelegate(nint a1, byte* placeholderText, byte a3, byte a4); private delegate nint ResolveTextCommandPlaceholderDelegate(nint a1, byte* placeholderText, byte a3, byte a4);
#endregion #endregion
@@ -132,7 +132,7 @@ internal unsafe class GameFunctions : IDisposable
agent->AddonId = addon->Id; agent->AddonId = addon->Id;
// Skips early return // Skips early return
atkStage->TooltipManager.Flag1 |= 2; atkStage->TooltipManager.TooltipType |= 2;
addon->Show(false, 15); addon->Show(false, 15);
} }
+1 -1
View File
@@ -1,7 +1,7 @@
namespace ChatTwo.GameFunctions.Types; namespace ChatTwo.GameFunctions.Types;
[Flags] [Flags]
internal enum ModifierFlag public enum ModifierFlag
{ {
None = 0, None = 0,
Shift = 1 << 0, Shift = 1 << 0,
+1 -1
View File
@@ -1,6 +1,6 @@
namespace ChatTwo.GameFunctions.Types; namespace ChatTwo.GameFunctions.Types;
internal enum TellReason public enum TellReason
{ {
Direct = 0, Direct = 0,
PartyFinder = 1, PartyFinder = 1,
+27 -9
View File
@@ -1,13 +1,17 @@
using Dalamud.Game.ClientState.Objects.SubKinds;
using FFXIVClientStructs.FFXIV.Client.Game.Character;
namespace ChatTwo.GameFunctions.Types; namespace ChatTwo.GameFunctions.Types;
internal sealed class TellTarget [Serializable]
public class TellTarget
{ {
internal string Name { get; } public string Name { get; set; }
internal ushort World { get; } public uint World { get; set; }
internal ulong ContentId { get; } public ulong ContentId { get; private set; }
internal TellReason Reason { get; } public TellReason Reason { get; private set; }
internal TellTarget(string name, ushort world, ulong contentId, TellReason reason) public TellTarget(string name, uint world, ulong contentId, TellReason reason)
{ {
Name = name; Name = name;
World = world; World = world;
@@ -15,8 +19,22 @@ internal sealed class TellTarget
Reason = reason; Reason = reason;
} }
public bool IsSet() => Name.Length > 0 && World > 0; public bool IsSet()
=> Name.Length > 0 && World > 0;
public string ToWorldString() => Sheets.WorldSheet.TryGetRow(World, out var worldRow) ? worldRow.Name.ToString() : string.Empty; public string ToWorldString()
public string ToTargetString() => $"{Name}@{ToWorldString()}"; => Sheets.WorldSheet.TryGetRow(World, out var worldRow) ? worldRow.Name.ToString() : string.Empty;
public string ToTargetString()
=> $"{Name}@{ToWorldString()}";
public unsafe void FromTarget(IPlayerCharacter target)
{
Name = target.Name.TextValue;
World = target.HomeWorld.RowId;
ContentId = ((Character*)target.Address)->ContentId;
}
public static TellTarget Empty() => new(string.Empty, 0, 0, TellReason.Direct);
public static TellTarget From(TellTarget t) => new(t.Name, t.World, t.ContentId, t.Reason);
} }
@@ -63,7 +63,7 @@ public struct MessageResponse()
{ {
[JsonProperty("id")] public Guid Id = Guid.Empty; [JsonProperty("id")] public Guid Id = Guid.Empty;
[JsonProperty("timestamp")] public string Timestamp = ""; [JsonProperty("timestamp")] public string Timestamp = "";
[JsonProperty("templates")] public MessageTemplate[] Templates; [JsonProperty("templates")] public MessageTemplate[] Templates = [];
} }
/// <summary> /// <summary>
+1 -1
View File
@@ -69,7 +69,7 @@ public class Processing
color ??= 0; color ??= 0;
var userContent = text.Content ?? string.Empty; var userContent = text.Content;
if (HostContext.Core.Plugin.ChatLogWindow.ScreenshotMode) if (HostContext.Core.Plugin.ChatLogWindow.ScreenshotMode)
{ {
if (chunk.Link is PlayerPayload playerPayload) if (chunk.Link is PlayerPayload playerPayload)
+4 -6
View File
@@ -2,8 +2,9 @@ using Dalamud.Plugin.Ipc;
namespace ChatTwo.Ipc; namespace ChatTwo.Ipc;
internal sealed class ExtraChat : IDisposable public sealed class ExtraChat : IDisposable
{ {
#pragma warning disable CS0649 // Assigned through IPC
[Serializable] [Serializable]
private struct OverrideInfo private struct OverrideInfo
{ {
@@ -11,8 +12,7 @@ internal sealed class ExtraChat : IDisposable
public ushort UiColour; public ushort UiColour;
public uint Rgba; public uint Rgba;
} }
#pragma warning restore CS0649
private Plugin Plugin { get; }
private ICallGateSubscriber<OverrideInfo, object> OverrideChannelGate { get; } private ICallGateSubscriber<OverrideInfo, object> OverrideChannelGate { get; }
private ICallGateSubscriber<Dictionary<string, uint>, Dictionary<string, uint>> ChannelCommandColoursGate { get; } private ICallGateSubscriber<Dictionary<string, uint>, Dictionary<string, uint>> ChannelCommandColoursGate { get; }
@@ -26,10 +26,8 @@ internal sealed class ExtraChat : IDisposable
private Dictionary<Guid, string> ChannelNamesInternal { get; set; } = new(); private Dictionary<Guid, string> ChannelNamesInternal { get; set; } = new();
internal IReadOnlyDictionary<Guid, string> ChannelNames => ChannelNamesInternal; internal IReadOnlyDictionary<Guid, string> ChannelNames => ChannelNamesInternal;
internal ExtraChat(Plugin plugin) internal ExtraChat()
{ {
Plugin = plugin;
OverrideChannelGate = Plugin.Interface.GetIpcSubscriber<OverrideInfo, object>("ExtraChat.OverrideChannelColour"); OverrideChannelGate = Plugin.Interface.GetIpcSubscriber<OverrideInfo, object>("ExtraChat.OverrideChannelColour");
ChannelCommandColoursGate = Plugin.Interface.GetIpcSubscriber<Dictionary<string, uint>, Dictionary<string, uint>>("ExtraChat.ChannelCommandColours"); ChannelCommandColoursGate = Plugin.Interface.GetIpcSubscriber<Dictionary<string, uint>, Dictionary<string, uint>>("ExtraChat.ChannelCommandColours");
ChannelNamesGate = Plugin.Interface.GetIpcSubscriber<Dictionary<Guid, string>, Dictionary<Guid, string>>("ExtraChat.ChannelNames"); ChannelNamesGate = Plugin.Interface.GetIpcSubscriber<Dictionary<Guid, string>, Dictionary<Guid, string>>("ExtraChat.ChannelNames");
+1 -1
View File
@@ -34,7 +34,7 @@ internal sealed class TypingIpc : IDisposable
var channelType = inputChannel.ToChatType(); var channelType = inputChannel.ToChatType();
return (InputVisible: !log.IsHidden, return (InputVisible: !log.IsHidden,
InputFocused: log.InputFocused, log.InputFocused,
HasText: log.Chat.Length > 0, HasText: log.Chat.Length > 0,
IsTyping: log is { InputFocused: true, Chat.Length: > 0 }, IsTyping: log is { InputFocused: true, Chat.Length: > 0 },
TextLength: log.Chat.Length, TextLength: log.Chat.Length,
+26 -69
View File
@@ -10,74 +10,30 @@ using FFXIVClientStructs.FFXIV.Client.UI.Agent;
namespace ChatTwo; namespace ChatTwo;
internal class SortCode public partial class Message
{ {
internal ChatType Type { get; } public Guid Id { get; } = Guid.NewGuid();
internal ChatSource Source { get; } public ulong Receiver { get; }
public ulong ContentId { get; set; }
public ulong AccountId { get; set; } // 0 if not set
public SortCode(ChatType type, ChatSource source) public DateTimeOffset Date { get; }
{ public ChatCode Code { get; }
Type = type; public List<Chunk> Sender { get; }
Source = source; public List<Chunk> Content { get; private set; }
}
internal SortCode(uint raw) public SeString SenderSource { get; }
{ public SeString ContentSource { get; }
Type = (ChatType)(raw >> 16);
Source = (ChatSource)(raw & 0xFFFF);
}
internal uint Encode() public int SortCodeV2 { get; }
{ public Guid ExtraChatChannel { get; }
return ((uint) Type << 16) | (uint) Source;
}
private bool Equals(SortCode other)
{
return Type == other.Type && Source == other.Source;
}
public override bool Equals(object? obj)
{
if (ReferenceEquals(null, obj))
return false;
if (ReferenceEquals(this, obj))
return true;
return obj.GetType() == GetType() && Equals((SortCode) obj);
}
public override int GetHashCode()
{
unchecked { return ((int) Type * 397) ^ (int) Source; }
}
}
internal partial class Message
{
internal Guid Id { get; } = Guid.NewGuid();
internal ulong Receiver { get; }
internal ulong ContentId { get; set; }
internal ulong AccountId { get; set; } // 0 if not set
internal DateTimeOffset Date { get; }
internal ChatCode Code { get; }
internal List<Chunk> Sender { get; }
internal List<Chunk> Content { get; private set; }
internal SeString SenderSource { get; }
internal SeString ContentSource { get; }
internal SortCode SortCode { get; }
internal Guid ExtraChatChannel { get; }
// Not stored in the database: // Not stored in the database:
internal int Hash { get; } public int Hash { get; }
internal Dictionary<Guid, float?> Height { get; } = new(); public Dictionary<Guid, float?> Height { get; } = new();
internal Dictionary<Guid, bool> IsVisible { get; } = new(); public Dictionary<Guid, bool> IsVisible { get; } = new();
internal Message(ulong receiver, ulong contentId, ulong accountId, ChatCode code, List<Chunk> sender, List<Chunk> content, SeString senderSource, SeString contentSource) public Message(ulong receiver, ulong contentId, ulong accountId, ChatCode code, List<Chunk> sender, List<Chunk> content, SeString senderSource, SeString contentSource)
{ {
var extraChatChannel = ExtractExtraChatChannel(contentSource); var extraChatChannel = ExtractExtraChatChannel(contentSource);
Receiver = receiver; Receiver = receiver;
@@ -89,7 +45,7 @@ internal partial class Message
Content = CheckMessageContent(content, extraChatChannel); Content = CheckMessageContent(content, extraChatChannel);
SenderSource = senderSource; SenderSource = senderSource;
ContentSource = contentSource; ContentSource = contentSource;
SortCode = new SortCode(Code.Type, Code.Source); SortCodeV2 = Code.ToSortCodeV2();
ExtraChatChannel = extraChatChannel; ExtraChatChannel = extraChatChannel;
Hash = GenerateHash(); Hash = GenerateHash();
@@ -97,7 +53,7 @@ internal partial class Message
chunk.Message = this; chunk.Message = this;
} }
internal Message(Guid id, ulong receiver, ulong contentId, DateTimeOffset date, ChatCode code, List<Chunk> sender, List<Chunk> content, SeString senderSource, SeString contentSource, SortCode sortCode, Guid extraChatChannel) public Message(Guid id, ulong receiver, ulong contentId, DateTimeOffset date, ChatCode code, List<Chunk> sender, List<Chunk> content, SeString senderSource, SeString contentSource, Guid extraChatChannel)
{ {
Id = id; Id = id;
Receiver = receiver; Receiver = receiver;
@@ -110,7 +66,7 @@ internal partial class Message
Content = content; Content = content;
SenderSource = senderSource; SenderSource = senderSource;
ContentSource = contentSource; ContentSource = contentSource;
SortCode = sortCode; SortCodeV2 = code.ToSortCodeV2();
ExtraChatChannel = extraChatChannel; ExtraChatChannel = extraChatChannel;
Hash = GenerateHash(); Hash = GenerateHash();
@@ -118,25 +74,26 @@ internal partial class Message
chunk.Message = this; chunk.Message = this;
} }
internal static Message FakeMessage(List<Chunk> content, ChatCode code) public static Message FakeMessage(List<Chunk> content, ChatCode code)
{ {
return new Message(0, 0, 0, code, [], content, new SeString(), new SeString()); return new Message(0, 0, 0, code, [], content, new SeString(), new SeString());
} }
internal bool Matches(Dictionary<ChatType, ChatSource> channels, bool allExtraChatChannels, HashSet<Guid> extraChatChannels) public bool Matches(Dictionary<ChatType, (ChatSource Source, ChatSource Target)> channels, bool allExtraChatChannels, HashSet<Guid> extraChatChannels)
{ {
if (ExtraChatChannel != Guid.Empty) if (ExtraChatChannel != Guid.Empty)
return allExtraChatChannels || extraChatChannels.Contains(ExtraChatChannel); return allExtraChatChannels || extraChatChannels.Contains(ExtraChatChannel);
var source = (ChatSource)(1 << (int)Code.Source);
var target = (ChatSource)(1 << (int)Code.Target);
return Code.Type.IsGm() return Code.Type.IsGm()
|| channels.TryGetValue(Code.Type, out var sources) || channels.TryGetValue(Code.Type, out var sources)
&& (Code.Source is 0 or (ChatSource) 1 && (Code.Source is 0 || sources.Source.HasFlag(source) || sources.Target.HasFlag(target));
|| sources.HasFlag(Code.Source));
} }
private int GenerateHash() private int GenerateHash()
{ {
var hash = SortCode.GetHashCode() var hash = SortCodeV2.GetHashCode()
^ ExtraChatChannel.GetHashCode() ^ ExtraChatChannel.GetHashCode()
^ string.Join("", Sender.Select(c => c.StringValue())).GetHashCode() ^ string.Join("", Sender.Select(c => c.StringValue())).GetHashCode()
^ string.Join("", Content.Select(c => c.StringValue())).GetHashCode(); ^ string.Join("", Content.Select(c => c.StringValue())).GetHashCode();
+18 -24
View File
@@ -4,12 +4,12 @@ using System.Text;
using ChatTwo.Code; using ChatTwo.Code;
using ChatTwo.Resources; using ChatTwo.Resources;
using ChatTwo.Util; using ChatTwo.Util;
using Dalamud.Game.Chat;
using Dalamud.Game.Text; using Dalamud.Game.Text;
using Dalamud.Game.Text.SeStringHandling; using Dalamud.Game.Text.SeStringHandling;
using Dalamud.Hooking; using Dalamud.Hooking;
using Dalamud.Interface.ImGuiNotification; using Dalamud.Interface.ImGuiNotification;
using Dalamud.Plugin.Services; using Dalamud.Plugin.Services;
using Dalamud.Utility;
using FFXIVClientStructs.FFXIV.Client.UI.Misc; using FFXIVClientStructs.FFXIV.Client.UI.Misc;
using Lumina.Text.Expressions; using Lumina.Text.Expressions;
using Lumina.Text.Payloads; using Lumina.Text.Payloads;
@@ -191,19 +191,19 @@ internal class MessageManager : IAsyncDisposable
} }
public (SeString? Sender, SeString? Message) LastMessage = (null, null); public (SeString? Sender, SeString? Message) LastMessage = (null, null);
private void ChatMessage(XivChatType type, int timestamp, SeString sender, SeString message) private void ChatMessage(IChatMessage message)
{ {
LastMessage = (sender, message); LastMessage = (message.Sender, message.Message);
var pendingMessage = new PendingMessage var pendingMessage = new PendingMessage
{ {
ReceiverId = CurrentContentId,
ContentId = 0, ContentId = 0,
AccountId = 0, AccountId = 0,
Type = type, LogKind = message.LogKind,
Timestamp = timestamp, SourceKind = message.SourceKind,
Sender = sender, TargetKind = message.TargetKind,
Content = message, Sender = message.Sender,
Content = message.Message,
}; };
// Update colour codes. // Update colour codes.
@@ -238,7 +238,7 @@ internal class MessageManager : IAsyncDisposable
private void ProcessMessage(PendingMessage pendingMessage) private void ProcessMessage(PendingMessage pendingMessage)
{ {
var chatCode = new ChatCode((ushort)pendingMessage.Type); var chatCode = new ChatCode(pendingMessage.LogKind, pendingMessage.SourceKind, pendingMessage.TargetKind);
NameFormatting? formatting = null; NameFormatting? formatting = null;
if (pendingMessage.Sender.Payloads.Count > 0) if (pendingMessage.Sender.Payloads.Count > 0)
@@ -247,15 +247,9 @@ internal class MessageManager : IAsyncDisposable
var senderChunks = new List<Chunk>(); var senderChunks = new List<Chunk>();
if (formatting is { IsPresent: true }) if (formatting is { IsPresent: true })
{ {
senderChunks.Add(new TextChunk(ChunkSource.None, null, formatting.Before) senderChunks.Add(new TextChunk(ChunkSource.None, null, formatting.Before) { FallbackColour = chatCode.Type });
{
FallbackColour = chatCode.Type,
});
senderChunks.AddRange(ChunkUtil.ToChunks(pendingMessage.Sender, ChunkSource.Sender, chatCode.Type)); senderChunks.AddRange(ChunkUtil.ToChunks(pendingMessage.Sender, ChunkSource.Sender, chatCode.Type));
senderChunks.Add(new TextChunk(ChunkSource.None, null, formatting.After) senderChunks.Add(new TextChunk(ChunkSource.None, null, formatting.After) { FallbackColour = chatCode.Type });
{
FallbackColour = chatCode.Type,
});
} }
var contentChunks = ChunkUtil.ToChunks(pendingMessage.Content, ChunkSource.Content, chatCode.Type).ToList(); var contentChunks = ChunkUtil.ToChunks(pendingMessage.Content, ChunkSource.Content, chatCode.Type).ToList();
@@ -342,12 +336,12 @@ internal class MessageManager : IAsyncDisposable
private class PendingMessage private class PendingMessage
{ {
internal ulong ReceiverId { get; set; } public ulong ContentId; // 0 if unknown
internal ulong ContentId { get; set; } // 0 if unknown public ulong AccountId; // 0 if unknown
internal ulong AccountId { get; set; } // 0 if unknown public XivChatType LogKind;
internal XivChatType Type { get; set; } public XivChatRelationKind SourceKind;
internal int Timestamp { get; set; } public XivChatRelationKind TargetKind;
internal SeString Sender { get; set; } public required SeString Sender;
internal SeString Content { get; set; } public required SeString Content;
} }
} }
+72 -32
View File
@@ -98,11 +98,11 @@ public class PayloadMessagePackFormatter : IMessagePackFormatter<Payload?>
} }
} }
public class SeStringMessagePackFormatter : IMessagePackFormatter<SeString> public class SeStringMessagePackFormatter : IMessagePackFormatter<SeString?>
{ {
public void Serialize(ref MessagePackWriter writer, SeString value, MessagePackSerializerOptions options) public void Serialize(ref MessagePackWriter writer, SeString? value, MessagePackSerializerOptions options)
{ {
options.Resolver.GetFormatter<List<Payload>>()!.Serialize(ref writer, value.Payloads, options); options.Resolver.GetFormatter<List<Payload>>()!.Serialize(ref writer, value?.Payloads ?? [], options);
} }
public SeString Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options) public SeString Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
@@ -176,6 +176,9 @@ internal class MessageStore : IDisposable
case 1: case 1:
migrationsToDo.Add(Migrate2); migrationsToDo.Add(Migrate2);
break; break;
case 2:
migrationsToDo.Add(Migrate3);
break;
} }
foreach (var migration in migrationsToDo) foreach (var migration in migrationsToDo)
@@ -227,6 +230,38 @@ internal class MessageStore : IDisposable
SetMigrationVersion(2); SetMigrationVersion(2);
} }
private void Migrate3()
{
Connection.Execute(@"
-- Migration 3: Fix log kinds to fit the new format
-- Add new ChatType, SourceKind, TargetKind (byte), SortCodeV2
-- Migrate OldChatColumn
-- ChatType = OldChatColumn & 0x7f
-- SourceKind = log2(1 << ((OldChatColumn >> 11) & 0xF))
-- TargetKind = trunc(log2(1 << ((OldChatColumn >> 7) & 0xF)))
-- Virtual SortCodeV2 = ChatType << 16 | SourceKind << 8 | TargetKind
-- Delete OldChatColumn, Virtual Channel
ALTER TABLE messages ADD COLUMN ChatType INTEGER;
CREATE INDEX IF NOT EXISTS idx_messages_chat_type ON messages (ChatType);
ALTER TABLE messages ADD COLUMN SourceKind INTEGER;
ALTER TABLE messages ADD COLUMN TargetKind INTEGER;
UPDATE messages SET
ChatType = Code & 0x7f,
SourceKind = trunc(log2(1 << ((Code >> 11) & 0xF))),
TargetKind = trunc(log2(1 << ((Code >> 7) & 0xF)))
WHERE true;
DROP INDEX idx_messages_channel;
ALTER TABLE messages DROP COLUMN Channel;
ALTER TABLE messages DROP COLUMN Code;
ALTER TABLE messages DROP COLUMN SortCode;
");
SetMigrationVersion(3);
}
private void SetMigrationVersion(int version) private void SetMigrationVersion(int version)
{ {
using var cmd = Connection.CreateCommand(); using var cmd = Connection.CreateCommand();
@@ -271,12 +306,13 @@ internal class MessageStore : IDisposable
Receiver, Receiver,
ContentId, ContentId,
Date, Date,
Code, ChatType,
SourceKind,
TargetKind,
Sender, Sender,
Content, Content,
SenderSource, SenderSource,
ContentSource, ContentSource,
SortCode,
ExtraChatChannel, ExtraChatChannel,
Deleted Deleted
) VALUES ( ) VALUES (
@@ -284,12 +320,13 @@ internal class MessageStore : IDisposable
$Receiver, $Receiver,
$ContentId, $ContentId,
$Date, $Date,
$Code, $ChatType,
$SourceKind,
$TargetKind,
$Sender, $Sender,
$Content, $Content,
$SenderSource, $SenderSource,
$ContentSource, $ContentSource,
$SortCode,
$ExtraChatChannel, $ExtraChatChannel,
false false
) )
@@ -297,27 +334,28 @@ internal class MessageStore : IDisposable
Receiver = excluded.Receiver, Receiver = excluded.Receiver,
ContentId = excluded.ContentId, ContentId = excluded.ContentId,
Date = excluded.Date, Date = excluded.Date,
Code = excluded.Code, ChatType = excluded.ChatType,
SourceKind = excluded.SourceKind,
TargetKind = excluded.TargetKind,
Sender = excluded.Sender, Sender = excluded.Sender,
Content = excluded.Content, Content = excluded.Content,
SenderSource = excluded.SenderSource, SenderSource = excluded.SenderSource,
ContentSource = excluded.ContentSource, ContentSource = excluded.ContentSource,
SortCode = excluded.SortCode,
ExtraChatChannel = excluded.ExtraChatChannel, ExtraChatChannel = excluded.ExtraChatChannel,
Deleted = false Deleted = false;
;
"; ";
cmd.Parameters.AddWithValue("$Id", message.Id); cmd.Parameters.AddWithValue("$Id", message.Id);
cmd.Parameters.AddWithValue("$Receiver", message.Receiver); cmd.Parameters.AddWithValue("$Receiver", message.Receiver);
cmd.Parameters.AddWithValue("$ContentId", message.ContentId); cmd.Parameters.AddWithValue("$ContentId", message.ContentId);
cmd.Parameters.AddWithValue("$Date", message.Date.ToUnixTimeMilliseconds()); cmd.Parameters.AddWithValue("$Date", message.Date.ToUnixTimeMilliseconds());
cmd.Parameters.AddWithValue("$Code", message.Code.Raw); cmd.Parameters.AddWithValue("$ChatType", message.Code.Type);
cmd.Parameters.AddWithValue("$SourceKind", message.Code.Source);
cmd.Parameters.AddWithValue("$TargetKind", message.Code.Target);
cmd.Parameters.AddWithValue("$Sender", MessagePackSerializer.Serialize(message.Sender, MsgPackOptions)); cmd.Parameters.AddWithValue("$Sender", MessagePackSerializer.Serialize(message.Sender, MsgPackOptions));
cmd.Parameters.AddWithValue("$Content", MessagePackSerializer.Serialize(message.Content, MsgPackOptions)); cmd.Parameters.AddWithValue("$Content", MessagePackSerializer.Serialize(message.Content, MsgPackOptions));
cmd.Parameters.AddWithValue("$SenderSource", MessagePackSerializer.Serialize(message.SenderSource, MsgPackOptions)); cmd.Parameters.AddWithValue("$SenderSource", MessagePackSerializer.Serialize(message.SenderSource, MsgPackOptions));
cmd.Parameters.AddWithValue("$ContentSource", MessagePackSerializer.Serialize(message.ContentSource, MsgPackOptions)); cmd.Parameters.AddWithValue("$ContentSource", MessagePackSerializer.Serialize(message.ContentSource, MsgPackOptions));
cmd.Parameters.AddWithValue("$SortCode", message.SortCode.Encode());
cmd.Parameters.AddWithValue("$ExtraChatChannel", message.ExtraChatChannel); cmd.Parameters.AddWithValue("$ExtraChatChannel", message.ExtraChatChannel);
cmd.ExecuteNonQuery(); cmd.ExecuteNonQuery();
@@ -350,12 +388,13 @@ internal class MessageStore : IDisposable
Receiver, Receiver,
ContentId, ContentId,
Date, Date,
Code, ChatType,
SourceKind,
TargetKind,
Sender, Sender,
Content, Content,
SenderSource, SenderSource,
ContentSource, ContentSource,
SortCode,
ExtraChatChannel ExtraChatChannel
FROM messages FROM messages
" + whereClause + @" " + whereClause + @"
@@ -387,14 +426,14 @@ internal class MessageStore : IDisposable
cmd.ExecuteNonQuery(); cmd.ExecuteNonQuery();
} }
internal long CountDateRange(DateTime after, DateTime before, IEnumerable<uint> channels, ulong? receiver = null) internal long CountDateRange(DateTime after, DateTime before, IEnumerable<byte> channels, ulong? receiver = null)
{ {
List<string> whereClauses = ["deleted = false"]; List<string> whereClauses = ["deleted = false"];
if (receiver != null) if (receiver != null)
whereClauses.Add("Receiver = $Receiver"); whereClauses.Add("Receiver = $Receiver");
whereClauses.Add("Date BETWEEN $After AND $Before"); whereClauses.Add("Date BETWEEN $After AND $Before");
whereClauses.Add($"Channel IN ({string.Join(", ", channels)})"); whereClauses.Add($"ChatType IN ({string.Join(", ", channels)})");
var whereClause = "WHERE " + string.Join(" AND ", whereClauses); var whereClause = "WHERE " + string.Join(" AND ", whereClauses);
@@ -416,14 +455,14 @@ internal class MessageStore : IDisposable
return (long) cmd.ExecuteScalar()!; return (long) cmd.ExecuteScalar()!;
} }
internal MessageEnumerator GetDateRange(DateTime after, DateTime before, IEnumerable<uint> channels, ulong? receiver = null) internal MessageEnumerator GetDateRange(DateTime after, DateTime before, IEnumerable<byte> channels, ulong? receiver = null)
{ {
List<string> whereClauses = ["deleted = false"]; List<string> whereClauses = ["deleted = false"];
if (receiver != null) if (receiver != null)
whereClauses.Add("Receiver = $Receiver"); whereClauses.Add("Receiver = $Receiver");
whereClauses.Add("Date BETWEEN $After AND $Before"); whereClauses.Add("Date BETWEEN $After AND $Before");
whereClauses.Add($"Channel IN ({string.Join(", ", channels)})"); whereClauses.Add($"ChatType IN ({string.Join(", ", channels)})");
var whereClause = $"WHERE {string.Join(" AND ", whereClauses)}"; var whereClause = $"WHERE {string.Join(" AND ", whereClauses)}";
@@ -436,12 +475,13 @@ internal class MessageStore : IDisposable
Receiver, Receiver,
ContentId, ContentId,
Date, Date,
Code, ChatType,
SourceKind,
TargetKind,
Sender, Sender,
Content, Content,
SenderSource, SenderSource,
ContentSource, ContentSource,
SortCode,
ExtraChatChannel ExtraChatChannel
FROM messages FROM messages
" + whereClause; " + whereClause;
@@ -456,14 +496,14 @@ internal class MessageStore : IDisposable
return new MessageEnumerator(cmd.ExecuteReader()); return new MessageEnumerator(cmd.ExecuteReader());
} }
internal MessageEnumerator GetPagedDateRange(DateTime after, DateTime before, IEnumerable<uint> channels, ulong? receiver = null, int page = 0) internal MessageEnumerator GetPagedDateRange(DateTime after, DateTime before, IEnumerable<byte> channels, ulong? receiver = null, int page = 0)
{ {
List<string> whereClauses = ["deleted = false"]; List<string> whereClauses = ["deleted = false"];
if (receiver != null) if (receiver != null)
whereClauses.Add("Receiver = $Receiver"); whereClauses.Add("Receiver = $Receiver");
whereClauses.Add("Date BETWEEN $After AND $Before"); whereClauses.Add("Date BETWEEN $After AND $Before");
whereClauses.Add($"Channel IN ({string.Join(", ", channels)})"); whereClauses.Add($"ChatType IN ({string.Join(", ", channels)})");
var whereClause = $"WHERE {string.Join(" AND ", whereClauses)}"; var whereClause = $"WHERE {string.Join(" AND ", whereClauses)}";
@@ -476,12 +516,13 @@ internal class MessageStore : IDisposable
Receiver, Receiver,
ContentId, ContentId,
Date, Date,
Code, ChatType,
SourceKind,
TargetKind,
Sender, Sender,
Content, Content,
SenderSource, SenderSource,
ContentSource, ContentSource,
SortCode,
ExtraChatChannel ExtraChatChannel
FROM messages FROM messages
" + whereClause + @" " + whereClause + @"
@@ -525,13 +566,12 @@ internal class MessageEnumerator(DbDataReader reader) : IEnumerable<Message>, ID
(ulong)reader.GetInt64(1), (ulong)reader.GetInt64(1),
(ulong)reader.GetInt64(2), (ulong)reader.GetInt64(2),
DateTimeOffset.FromUnixTimeMilliseconds(reader.GetInt64(3)), DateTimeOffset.FromUnixTimeMilliseconds(reader.GetInt64(3)),
new ChatCode((ushort)reader.GetInt32(4)), new ChatCode((byte)reader.GetInt32(4), (byte)reader.GetInt32(5), (byte)reader.GetInt32(6)),
MessagePackSerializer.Deserialize<List<Chunk>>(reader.GetFieldValue<byte[]>(5), MessageStore.MsgPackOptions), MessagePackSerializer.Deserialize<List<Chunk>>(reader.GetFieldValue<byte[]>(7), MessageStore.MsgPackOptions),
MessagePackSerializer.Deserialize<List<Chunk>>(reader.GetFieldValue<byte[]>(6), MessageStore.MsgPackOptions), MessagePackSerializer.Deserialize<List<Chunk>>(reader.GetFieldValue<byte[]>(8), MessageStore.MsgPackOptions),
MessagePackSerializer.Deserialize<SeString>(reader.GetFieldValue<byte[]>(7), MessageStore.MsgPackOptions), MessagePackSerializer.Deserialize<SeString>(reader.GetFieldValue<byte[]>(9), MessageStore.MsgPackOptions),
MessagePackSerializer.Deserialize<SeString>(reader.GetFieldValue<byte[]>(8), MessageStore.MsgPackOptions), MessagePackSerializer.Deserialize<SeString>(reader.GetFieldValue<byte[]>(10), MessageStore.MsgPackOptions),
new SortCode((uint)reader.GetInt32(9)), reader.GetGuid(11)
reader.GetGuid(10)
); );
} }
catch (Exception e) catch (Exception e)
+7 -7
View File
@@ -135,7 +135,7 @@ public sealed class PayloadHandler
private void ContextFooter(bool didCustomContext, Chunk chunk) private void ContextFooter(bool didCustomContext, Chunk chunk)
{ {
ImRaii.IEndObject? menu = null; ImRaii.MenuDisposable menu = default;
if (didCustomContext) if (didCustomContext)
{ {
ImGui.Separator(); ImGui.Separator();
@@ -177,7 +177,7 @@ public sealed class PayloadHandler
ImGui.TextUnformatted(message.Code.Type.Name()); ImGui.TextUnformatted(message.Code.Type.Name());
} }
menu?.Dispose(); menu.Dispose();
} }
private static string StringifyMessage(Message? message, bool withSender = false) private static string StringifyMessage(Message? message, bool withSender = false)
@@ -192,7 +192,7 @@ public sealed class PayloadHandler
.Aggregate(string.Concat); .Aggregate(string.Concat);
} }
internal void Click(Chunk chunk, Payload? payload, ImGuiMouseButton button) internal unsafe void Click(Chunk chunk, Payload? payload, ImGuiMouseButton button)
{ {
if (Plugin.Config.PlaySounds) if (Plugin.Config.PlaySounds)
UIGlobals.PlaySoundEffect(PopupSfx); UIGlobals.PlaySoundEffect(PopupSfx);
@@ -608,7 +608,7 @@ public sealed class PayloadHandler
if (world.Value.IsPublic) if (world.Value.IsPublic)
{ {
var party = Plugin.PartyList; var party = Plugin.PartyList;
var leader = (ulong?) party[(int) party.PartyLeaderIndex]?.ContentId; var leader = party[(int) party.PartyLeaderIndex]?.ContentId;
var isLeader = party.Length == 0 || Plugin.PlayerState.ContentId == leader; var isLeader = party.Length == 0 || Plugin.PlayerState.ContentId == leader;
var member = party.FirstOrDefault(member => member.Name.TextValue == player.PlayerName && member.World.RowId == world.RowId); var member = party.FirstOrDefault(member => member.Name.TextValue == player.PlayerName && member.World.RowId == world.RowId);
var isInParty = member != null; var isInParty = member != null;
@@ -640,10 +640,10 @@ public sealed class PayloadHandler
if (isInParty && member != null && (!inInstance || (inInstance && inPartyInstance))) if (isInParty && member != null && (!inInstance || (inInstance && inPartyInstance)))
{ {
if (ImGui.Selectable(Language.Context_Promote)) if (ImGui.Selectable(Language.Context_Promote))
GameFunctions.Party.Promote(player.PlayerName, (ulong) member.ContentId); GameFunctions.Party.Promote(player.PlayerName, member.ContentId);
if (ImGui.Selectable(Language.Context_KickFromParty)) if (ImGui.Selectable(Language.Context_KickFromParty))
GameFunctions.Party.Kick(player.PlayerName, (ulong) member.ContentId); GameFunctions.Party.Kick(player.PlayerName, member.ContentId);
} }
} }
@@ -743,7 +743,7 @@ public sealed class PayloadHandler
default: default:
builder.AddUiForeground(nameValue, 1); builder.AddUiForeground(nameValue, 1);
break; break;
}; }
LogWindow.DrawChunks(ChunkUtil.ToChunks(builder.BuiltString, ChunkSource.None, null).ToList(), false); LogWindow.DrawChunks(ChunkUtil.ToChunks(builder.BuiltString, ChunkSource.None, null).ToList(), false);
ImGui.Separator(); ImGui.Separator();
+50 -26
View File
@@ -19,30 +19,30 @@ namespace ChatTwo;
// ReSharper disable once ClassNeverInstantiated.Global // ReSharper disable once ClassNeverInstantiated.Global
public sealed class Plugin : IDalamudPlugin public sealed class Plugin : IDalamudPlugin
{ {
internal const string PluginName = "Chat 2"; public const string PluginName = "Chat 2";
[PluginService] internal static IPluginLog Log { get; private set; } = null!; [PluginService] public static IPluginLog Log { get; private set; } = null!;
[PluginService] internal static IDalamudPluginInterface Interface { get; private set; } = null!; [PluginService] public static IDalamudPluginInterface Interface { get; private set; } = null!;
[PluginService] internal static IChatGui ChatGui { get; private set; } = null!; [PluginService] public static IChatGui ChatGui { get; private set; } = null!;
[PluginService] internal static IClientState ClientState { get; private set; } = null!; [PluginService] public static IClientState ClientState { get; private set; } = null!;
[PluginService] internal static ICommandManager CommandManager { get; private set; } = null!; [PluginService] public static ICommandManager CommandManager { get; private set; } = null!;
[PluginService] internal static ICondition Condition { get; private set; } = null!; [PluginService] public static ICondition Condition { get; private set; } = null!;
[PluginService] internal static IDataManager DataManager { get; private set; } = null!; [PluginService] public static IDataManager DataManager { get; private set; } = null!;
[PluginService] internal static IFramework Framework { get; private set; } = null!; [PluginService] public static IFramework Framework { get; private set; } = null!;
[PluginService] internal static IGameGui GameGui { get; private set; } = null!; [PluginService] public static IGameGui GameGui { get; private set; } = null!;
[PluginService] internal static IKeyState KeyState { get; private set; } = null!; [PluginService] public static IKeyState KeyState { get; private set; } = null!;
[PluginService] internal static IObjectTable ObjectTable { get; private set; } = null!; [PluginService] public static IObjectTable ObjectTable { get; private set; } = null!;
[PluginService] internal static IPartyList PartyList { get; private set; } = null!; [PluginService] public static IPartyList PartyList { get; private set; } = null!;
[PluginService] internal static ITargetManager TargetManager { get; private set; } = null!; [PluginService] public static ITargetManager TargetManager { get; private set; } = null!;
[PluginService] internal static ITextureProvider TextureProvider { get; private set; } = null!; [PluginService] public static ITextureProvider TextureProvider { get; private set; } = null!;
[PluginService] internal static IGameInteropProvider GameInteropProvider { get; private set; } = null!; [PluginService] public static IGameInteropProvider GameInteropProvider { get; private set; } = null!;
[PluginService] internal static IGameConfig GameConfig { get; private set; } = null!; [PluginService] public static IGameConfig GameConfig { get; private set; } = null!;
[PluginService] internal static INotificationManager Notification { get; private set; } = null!; [PluginService] public static INotificationManager Notification { get; private set; } = null!;
[PluginService] internal static IAddonLifecycle AddonLifecycle { get; private set; } = null!; [PluginService] public static IAddonLifecycle AddonLifecycle { get; private set; } = null!;
[PluginService] internal static IPlayerState PlayerState { get; private set; } = null!; [PluginService] public static IPlayerState PlayerState { get; private set; } = null!;
[PluginService] internal static ISeStringEvaluator Evaluator { get; private set; } = null!; [PluginService] public static ISeStringEvaluator Evaluator { get; private set; } = null!;
internal static Configuration Config = null!; public static Configuration Config = null!;
public static FileDialogManager FileDialogManager { get; private set; } = null!; public static FileDialogManager FileDialogManager { get; private set; } = null!;
public readonly WindowSystem WindowSystem = new(PluginName); public readonly WindowSystem WindowSystem = new(PluginName);
@@ -62,7 +62,7 @@ public sealed class Plugin : IDalamudPlugin
internal TypingIpc TypingIpc { get; } internal TypingIpc TypingIpc { get; }
internal FontManager FontManager { get; } internal FontManager FontManager { get; }
internal ServerCore ServerCore { get; } public readonly ServerCore ServerCore;
internal int DeferredSaveFrames = -1; internal int DeferredSaveFrames = -1;
@@ -88,23 +88,47 @@ public sealed class Plugin : IDalamudPlugin
Config = Interface.GetPluginConfig() as Configuration ?? new Configuration(); Config = Interface.GetPluginConfig() as Configuration ?? new Configuration();
#pragma warning disable CS0618 // Type or member is obsolete
// TODO Remove after 01.07.2026
// Migrate old channel values
if (Config.Version <= 5)
{
foreach (var tab in Config.Tabs)
{
if (tab.ChatCodes.Count > 0)
{
tab.SelectedChannels = tab.ChatCodes.ToDictionary(pair => pair.Key, pair => (pair.Value, pair.Value));
tab.ChatCodes.Clear();
}
if (Config.InactivityHideChannels.Count > 0)
{
Config.InactivityHideChannelsV2 = Config.InactivityHideChannels.ToDictionary(pair => pair.Key, pair => (pair.Value, pair.Value));
Config.InactivityHideChannels.Clear();
}
Config.Version = 6;
SaveConfig();
}
}
#pragma warning restore CS0618 // Type or member is obsolete
if (Config.Tabs.Count == 0) if (Config.Tabs.Count == 0)
Config.Tabs.Add(TabsUtil.VanillaGeneral); Config.Tabs.Add(TabsUtil.VanillaGeneral);
Config.InactivityHideChannels ??= TabsUtil.AllChannels();
LanguageChanged(Interface.UiLanguage); LanguageChanged(Interface.UiLanguage);
ImGuiUtil.Initialize(this); ImGuiUtil.Initialize(this);
FileDialogManager = new FileDialogManager(); FileDialogManager = new FileDialogManager();
// Functions calls this in its ctor if the player is already logged in // Function call this in its ctor if the player is already logged in
ServerCore = new ServerCore(this); ServerCore = new ServerCore(this);
Commands = new Commands(); Commands = new Commands();
Functions = new GameFunctions.GameFunctions(this); Functions = new GameFunctions.GameFunctions(this);
Ipc = new IpcManager(); Ipc = new IpcManager();
TypingIpc = new TypingIpc(this); TypingIpc = new TypingIpc(this);
ExtraChat = new ExtraChat(this); ExtraChat = new ExtraChat();
FontManager = new FontManager(); FontManager = new FontManager();
ChatLogWindow = new ChatLogWindow(this); ChatLogWindow = new ChatLogWindow(this);
+81
View File
@@ -86,6 +86,33 @@ namespace ChatTwo.Resources {
} }
} }
/// <summary>
/// Looks up a localized string similar to message is empty.
/// </summary>
internal static string ChatBox_Error_Empty {
get {
return ResourceManager.GetString("ChatBox_Error_Empty", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to message contained invalid characters.
/// </summary>
internal static string ChatBox_Error_Invalid {
get {
return ResourceManager.GetString("ChatBox_Error_Invalid", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to message is longer than 500 bytes.
/// </summary>
internal static string ChatBox_Error_Too_Long {
get {
return ResourceManager.GetString("ChatBox_Error_Too_Long", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to Input is disabled for this tab. /// Looks up a localized string similar to Input is disabled for this tab.
/// </summary> /// </summary>
@@ -1751,6 +1778,24 @@ namespace ChatTwo.Resources {
} }
} }
/// <summary>
/// Looks up a localized string similar to Source.
/// </summary>
internal static string ImGuiUtil_ChannelSelector_Source {
get {
return ResourceManager.GetString("ImGuiUtil_ChannelSelector_Source", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Target.
/// </summary>
internal static string ImGuiUtil_ChannelSelector_Target {
get {
return ResourceManager.GetString("ImGuiUtil_ChannelSelector_Target", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to ESC to clear. /// Looks up a localized string similar to ESC to clear.
/// </summary> /// </summary>
@@ -2444,6 +2489,24 @@ namespace ChatTwo.Resources {
} }
} }
/// <summary>
/// Looks up a localized string similar to Target.
/// </summary>
internal static string Options_Header_Target {
get {
return ResourceManager.GetString("Options_Header_Target", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to This disables the channel selection and shows all messages coming from the target..
/// </summary>
internal static string Options_Help_SenderMessages {
get {
return ResourceManager.GetString("Options_Help_SenderMessages", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to Hide the in-game chat window when the plugin is active.. /// Looks up a localized string similar to Hide the in-game chat window when the plugin is active..
/// </summary> /// </summary>
@@ -3398,6 +3461,15 @@ namespace ChatTwo.Resources {
} }
} }
/// <summary>
/// Looks up a localized string similar to Show all messages send by target.
/// </summary>
internal static string Options_Tabs_SenderMessages {
get {
return ResourceManager.GetString("Options_Tabs_SenderMessages", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to Show timestamps. /// Looks up a localized string similar to Show timestamps.
/// </summary> /// </summary>
@@ -3713,6 +3785,15 @@ namespace ChatTwo.Resources {
} }
} }
/// <summary>
/// Looks up a localized string similar to Tell Exclusive.
/// </summary>
internal static string Tabs_Presets_Tell {
get {
return ResourceManager.GetString("Tabs_Presets_Tell", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to All. /// Looks up a localized string similar to All.
/// </summary> /// </summary>
+27
View File
@@ -391,6 +391,9 @@
<data name="Tabs_Presets_Event"> <data name="Tabs_Presets_Event">
<value>Event</value> <value>Event</value>
</data> </data>
<data name="Tabs_Presets_Tell">
<value>Tell Exclusive</value>
</data>
<data name="Options_Tabs_NewTab"> <data name="Options_Tabs_NewTab">
<value>Nova pestanya</value> <value>Nova pestanya</value>
</data> </data>
@@ -1144,6 +1147,9 @@
<data name="Options_Tabs_NoInput" xml:space="preserve"> <data name="Options_Tabs_NoInput" xml:space="preserve">
<value>Disable input for this channel</value> <value>Disable input for this channel</value>
</data> </data>
<data name="Options_Tabs_SenderMessages" xml:space="preserve">
<value>Show all messages send by target</value>
</data>
<data name="ChatLog_DisabledInput" xml:space="preserve"> <data name="ChatLog_DisabledInput" xml:space="preserve">
<value>Input is disabled for this tab</value> <value>Input is disabled for this tab</value>
</data> </data>
@@ -1399,4 +1405,25 @@
<data name="Webinterface_UsageNotice" xml:space="preserve"> <data name="Webinterface_UsageNotice" xml:space="preserve">
<value>Usage Notice</value> <value>Usage Notice</value>
</data> </data>
<data name="Options_Help_SenderMessages" xml:space="preserve">
<value>This disables the channel selection and shows all messages coming from the target.</value>
</data>
<data name="Options_Header_Target" xml:space="preserve">
<value>Target</value>
</data>
<data name="ChatBox_Error_Empty" xml:space="preserve">
<value>message is empty</value>
</data>
<data name="ChatBox_Error_Too_Long" xml:space="preserve">
<value>message is longer than 500 bytes</value>
</data>
<data name="ChatBox_Error_Invalid" xml:space="preserve">
<value>message contained invalid characters</value>
</data>
<data name="ImGuiUtil_ChannelSelector_Source" xml:space="preserve">
<value>Source</value>
</data>
<data name="ImGuiUtil_ChannelSelector_Target" xml:space="preserve">
<value>Target</value>
</data>
</root> </root>
+27
View File
@@ -392,6 +392,9 @@ Sie wurden gewarnt.</value>
<data name="Tabs_Presets_Event"> <data name="Tabs_Presets_Event">
<value>Ereignis</value> <value>Ereignis</value>
</data> </data>
<data name="Tabs_Presets_Tell">
<value>Tell Exclusive</value>
</data>
<data name="Options_Tabs_NewTab"> <data name="Options_Tabs_NewTab">
<value>Neuer Tab</value> <value>Neuer Tab</value>
</data> </data>
@@ -1145,6 +1148,9 @@ Sie wurden gewarnt.</value>
<data name="Options_Tabs_NoInput" xml:space="preserve"> <data name="Options_Tabs_NoInput" xml:space="preserve">
<value>Eingabe für diesen Kanal deaktivieren</value> <value>Eingabe für diesen Kanal deaktivieren</value>
</data> </data>
<data name="Options_Tabs_SenderMessages" xml:space="preserve">
<value>Show all messages send by target</value>
</data>
<data name="ChatLog_DisabledInput" xml:space="preserve"> <data name="ChatLog_DisabledInput" xml:space="preserve">
<value>Eingabe ist für diesen Tab deaktiviert</value> <value>Eingabe ist für diesen Tab deaktiviert</value>
</data> </data>
@@ -1402,4 +1408,25 @@ Nachdem du 'Aktiviert' angeklickt und auf 'Start' gedrückt hast, wird die einge
<data name="Webinterface_UsageNotice" xml:space="preserve"> <data name="Webinterface_UsageNotice" xml:space="preserve">
<value>Nutzungshinweis</value> <value>Nutzungshinweis</value>
</data> </data>
<data name="Options_Help_SenderMessages" xml:space="preserve">
<value>This disables the channel selection and shows all messages coming from the target.</value>
</data>
<data name="Options_Header_Target" xml:space="preserve">
<value>Target</value>
</data>
<data name="ChatBox_Error_Empty" xml:space="preserve">
<value>message is empty</value>
</data>
<data name="ChatBox_Error_Too_Long" xml:space="preserve">
<value>message is longer than 500 bytes</value>
</data>
<data name="ChatBox_Error_Invalid" xml:space="preserve">
<value>message contained invalid characters</value>
</data>
<data name="ImGuiUtil_ChannelSelector_Source" xml:space="preserve">
<value>Source</value>
</data>
<data name="ImGuiUtil_ChannelSelector_Target" xml:space="preserve">
<value>Target</value>
</data>
</root> </root>
+27
View File
@@ -391,6 +391,9 @@
<data name="Tabs_Presets_Event"> <data name="Tabs_Presets_Event">
<value>Evento</value> <value>Evento</value>
</data> </data>
<data name="Tabs_Presets_Tell">
<value>Tell Exclusive</value>
</data>
<data name="Options_Tabs_NewTab"> <data name="Options_Tabs_NewTab">
<value>Nueva pestaña</value> <value>Nueva pestaña</value>
</data> </data>
@@ -1144,6 +1147,9 @@
<data name="Options_Tabs_NoInput" xml:space="preserve"> <data name="Options_Tabs_NoInput" xml:space="preserve">
<value>Deshabilitar entrada para este canal</value> <value>Deshabilitar entrada para este canal</value>
</data> </data>
<data name="Options_Tabs_SenderMessages" xml:space="preserve">
<value>Show all messages send by target</value>
</data>
<data name="ChatLog_DisabledInput" xml:space="preserve"> <data name="ChatLog_DisabledInput" xml:space="preserve">
<value>La entrada está deshabilitada para esta pestaña</value> <value>La entrada está deshabilitada para esta pestaña</value>
</data> </data>
@@ -1399,4 +1405,25 @@
<data name="Webinterface_UsageNotice" xml:space="preserve"> <data name="Webinterface_UsageNotice" xml:space="preserve">
<value>Aviso de Uso</value> <value>Aviso de Uso</value>
</data> </data>
<data name="Options_Help_SenderMessages" xml:space="preserve">
<value>This disables the channel selection and shows all messages coming from the target.</value>
</data>
<data name="Options_Header_Target" xml:space="preserve">
<value>Target</value>
</data>
<data name="ChatBox_Error_Empty" xml:space="preserve">
<value>message is empty</value>
</data>
<data name="ChatBox_Error_Too_Long" xml:space="preserve">
<value>message is longer than 500 bytes</value>
</data>
<data name="ChatBox_Error_Invalid" xml:space="preserve">
<value>message contained invalid characters</value>
</data>
<data name="ImGuiUtil_ChannelSelector_Source" xml:space="preserve">
<value>Source</value>
</data>
<data name="ImGuiUtil_ChannelSelector_Target" xml:space="preserve">
<value>Target</value>
</data>
</root> </root>
+27
View File
@@ -391,6 +391,9 @@
<data name="Tabs_Presets_Event"> <data name="Tabs_Presets_Event">
<value>Evénement</value> <value>Evénement</value>
</data> </data>
<data name="Tabs_Presets_Tell">
<value>Tell Exclusive</value>
</data>
<data name="Options_Tabs_NewTab"> <data name="Options_Tabs_NewTab">
<value>Nouvel onglet</value> <value>Nouvel onglet</value>
</data> </data>
@@ -1144,6 +1147,9 @@
<data name="Options_Tabs_NoInput" xml:space="preserve"> <data name="Options_Tabs_NoInput" xml:space="preserve">
<value>Désactiver la saisie pour ce canal</value> <value>Désactiver la saisie pour ce canal</value>
</data> </data>
<data name="Options_Tabs_SenderMessages" xml:space="preserve">
<value>Show all messages send by target</value>
</data>
<data name="ChatLog_DisabledInput" xml:space="preserve"> <data name="ChatLog_DisabledInput" xml:space="preserve">
<value>La saisie est désactivée pour cet onglet</value> <value>La saisie est désactivée pour cet onglet</value>
</data> </data>
@@ -1399,4 +1405,25 @@
<data name="Webinterface_UsageNotice" xml:space="preserve"> <data name="Webinterface_UsageNotice" xml:space="preserve">
<value>Notice d'utilisation</value> <value>Notice d'utilisation</value>
</data> </data>
<data name="Options_Help_SenderMessages" xml:space="preserve">
<value>This disables the channel selection and shows all messages coming from the target.</value>
</data>
<data name="Options_Header_Target" xml:space="preserve">
<value>Target</value>
</data>
<data name="ChatBox_Error_Empty" xml:space="preserve">
<value>message is empty</value>
</data>
<data name="ChatBox_Error_Too_Long" xml:space="preserve">
<value>message is longer than 500 bytes</value>
</data>
<data name="ChatBox_Error_Invalid" xml:space="preserve">
<value>message contained invalid characters</value>
</data>
<data name="ImGuiUtil_ChannelSelector_Source" xml:space="preserve">
<value>Source</value>
</data>
<data name="ImGuiUtil_ChannelSelector_Target" xml:space="preserve">
<value>Target</value>
</data>
</root> </root>
+27
View File
@@ -391,6 +391,9 @@
<data name="Tabs_Presets_Event"> <data name="Tabs_Presets_Event">
<value>Event</value> <value>Event</value>
</data> </data>
<data name="Tabs_Presets_Tell">
<value>Tell Exclusive</value>
</data>
<data name="Options_Tabs_NewTab"> <data name="Options_Tabs_NewTab">
<value>Nuova tab</value> <value>Nuova tab</value>
</data> </data>
@@ -1144,6 +1147,9 @@
<data name="Options_Tabs_NoInput" xml:space="preserve"> <data name="Options_Tabs_NoInput" xml:space="preserve">
<value>Disable input for this channel</value> <value>Disable input for this channel</value>
</data> </data>
<data name="Options_Tabs_SenderMessages" xml:space="preserve">
<value>Show all messages send by target</value>
</data>
<data name="ChatLog_DisabledInput" xml:space="preserve"> <data name="ChatLog_DisabledInput" xml:space="preserve">
<value>Input is disabled for this tab</value> <value>Input is disabled for this tab</value>
</data> </data>
@@ -1399,4 +1405,25 @@
<data name="Webinterface_UsageNotice" xml:space="preserve"> <data name="Webinterface_UsageNotice" xml:space="preserve">
<value>Avviso Di Utilizzo</value> <value>Avviso Di Utilizzo</value>
</data> </data>
<data name="Options_Help_SenderMessages" xml:space="preserve">
<value>This disables the channel selection and shows all messages coming from the target.</value>
</data>
<data name="Options_Header_Target" xml:space="preserve">
<value>Target</value>
</data>
<data name="ChatBox_Error_Empty" xml:space="preserve">
<value>message is empty</value>
</data>
<data name="ChatBox_Error_Too_Long" xml:space="preserve">
<value>message is longer than 500 bytes</value>
</data>
<data name="ChatBox_Error_Invalid" xml:space="preserve">
<value>message contained invalid characters</value>
</data>
<data name="ImGuiUtil_ChannelSelector_Source" xml:space="preserve">
<value>Source</value>
</data>
<data name="ImGuiUtil_ChannelSelector_Target" xml:space="preserve">
<value>Target</value>
</data>
</root> </root>
+27
View File
@@ -391,6 +391,9 @@
<data name="Tabs_Presets_Event"> <data name="Tabs_Presets_Event">
<value>イベント</value> <value>イベント</value>
</data> </data>
<data name="Tabs_Presets_Tell">
<value>Tell Exclusive</value>
</data>
<data name="Options_Tabs_NewTab"> <data name="Options_Tabs_NewTab">
<value>新しいタブ</value> <value>新しいタブ</value>
</data> </data>
@@ -1144,6 +1147,9 @@
<data name="Options_Tabs_NoInput" xml:space="preserve"> <data name="Options_Tabs_NoInput" xml:space="preserve">
<value>このチャンネルの入力を無効にする</value> <value>このチャンネルの入力を無効にする</value>
</data> </data>
<data name="Options_Tabs_SenderMessages" xml:space="preserve">
<value>Show all messages send by target</value>
</data>
<data name="ChatLog_DisabledInput" xml:space="preserve"> <data name="ChatLog_DisabledInput" xml:space="preserve">
<value>このタブの入力は無効です</value> <value>このタブの入力は無効です</value>
</data> </data>
@@ -1399,4 +1405,25 @@
<data name="Webinterface_UsageNotice" xml:space="preserve"> <data name="Webinterface_UsageNotice" xml:space="preserve">
<value>使用上の注意</value> <value>使用上の注意</value>
</data> </data>
<data name="Options_Help_SenderMessages" xml:space="preserve">
<value>This disables the channel selection and shows all messages coming from the target.</value>
</data>
<data name="Options_Header_Target" xml:space="preserve">
<value>Target</value>
</data>
<data name="ChatBox_Error_Empty" xml:space="preserve">
<value>message is empty</value>
</data>
<data name="ChatBox_Error_Too_Long" xml:space="preserve">
<value>message is longer than 500 bytes</value>
</data>
<data name="ChatBox_Error_Invalid" xml:space="preserve">
<value>message contained invalid characters</value>
</data>
<data name="ImGuiUtil_ChannelSelector_Source" xml:space="preserve">
<value>Source</value>
</data>
<data name="ImGuiUtil_ChannelSelector_Target" xml:space="preserve">
<value>Target</value>
</data>
</root> </root>
+27
View File
@@ -391,6 +391,9 @@
<data name="Tabs_Presets_Event"> <data name="Tabs_Presets_Event">
<value>이벤트</value> <value>이벤트</value>
</data> </data>
<data name="Tabs_Presets_Tell">
<value>Tell Exclusive</value>
</data>
<data name="Options_Tabs_NewTab"> <data name="Options_Tabs_NewTab">
<value>새 탭</value> <value>새 탭</value>
</data> </data>
@@ -1144,6 +1147,9 @@
<data name="Options_Tabs_NoInput" xml:space="preserve"> <data name="Options_Tabs_NoInput" xml:space="preserve">
<value>이 탭에서 입력 비활성화</value> <value>이 탭에서 입력 비활성화</value>
</data> </data>
<data name="Options_Tabs_SenderMessages" xml:space="preserve">
<value>Show all messages send by target</value>
</data>
<data name="ChatLog_DisabledInput" xml:space="preserve"> <data name="ChatLog_DisabledInput" xml:space="preserve">
<value>이 탭에서 입력이 비활성화된 상태입니다.</value> <value>이 탭에서 입력이 비활성화된 상태입니다.</value>
</data> </data>
@@ -1399,4 +1405,25 @@
<data name="Webinterface_UsageNotice" xml:space="preserve"> <data name="Webinterface_UsageNotice" xml:space="preserve">
<value>Usage Notice</value> <value>Usage Notice</value>
</data> </data>
<data name="Options_Help_SenderMessages" xml:space="preserve">
<value>This disables the channel selection and shows all messages coming from the target.</value>
</data>
<data name="Options_Header_Target" xml:space="preserve">
<value>Target</value>
</data>
<data name="ChatBox_Error_Empty" xml:space="preserve">
<value>message is empty</value>
</data>
<data name="ChatBox_Error_Too_Long" xml:space="preserve">
<value>message is longer than 500 bytes</value>
</data>
<data name="ChatBox_Error_Invalid" xml:space="preserve">
<value>message contained invalid characters</value>
</data>
<data name="ImGuiUtil_ChannelSelector_Source" xml:space="preserve">
<value>Source</value>
</data>
<data name="ImGuiUtil_ChannelSelector_Target" xml:space="preserve">
<value>Target</value>
</data>
</root> </root>
+27
View File
@@ -391,6 +391,9 @@
<data name="Tabs_Presets_Event"> <data name="Tabs_Presets_Event">
<value>Evenement</value> <value>Evenement</value>
</data> </data>
<data name="Tabs_Presets_Tell">
<value>Tell Exclusive</value>
</data>
<data name="Options_Tabs_NewTab"> <data name="Options_Tabs_NewTab">
<value>Nieuw Tabblad</value> <value>Nieuw Tabblad</value>
</data> </data>
@@ -1144,6 +1147,9 @@
<data name="Options_Tabs_NoInput" xml:space="preserve"> <data name="Options_Tabs_NoInput" xml:space="preserve">
<value>Invoer voor dit kanaal uitschakelen</value> <value>Invoer voor dit kanaal uitschakelen</value>
</data> </data>
<data name="Options_Tabs_SenderMessages" xml:space="preserve">
<value>Show all messages send by target</value>
</data>
<data name="ChatLog_DisabledInput" xml:space="preserve"> <data name="ChatLog_DisabledInput" xml:space="preserve">
<value>Invoer is uitgeschakeld voor dit tabblad</value> <value>Invoer is uitgeschakeld voor dit tabblad</value>
</data> </data>
@@ -1399,4 +1405,25 @@
<data name="Webinterface_UsageNotice" xml:space="preserve"> <data name="Webinterface_UsageNotice" xml:space="preserve">
<value>Gebruiksaanwijzing</value> <value>Gebruiksaanwijzing</value>
</data> </data>
<data name="Options_Help_SenderMessages" xml:space="preserve">
<value>This disables the channel selection and shows all messages coming from the target.</value>
</data>
<data name="Options_Header_Target" xml:space="preserve">
<value>Target</value>
</data>
<data name="ChatBox_Error_Empty" xml:space="preserve">
<value>message is empty</value>
</data>
<data name="ChatBox_Error_Too_Long" xml:space="preserve">
<value>message is longer than 500 bytes</value>
</data>
<data name="ChatBox_Error_Invalid" xml:space="preserve">
<value>message contained invalid characters</value>
</data>
<data name="ImGuiUtil_ChannelSelector_Source" xml:space="preserve">
<value>Source</value>
</data>
<data name="ImGuiUtil_ChannelSelector_Target" xml:space="preserve">
<value>Target</value>
</data>
</root> </root>
+27
View File
@@ -391,6 +391,9 @@
<data name="Tabs_Presets_Event"> <data name="Tabs_Presets_Event">
<value>Evento</value> <value>Evento</value>
</data> </data>
<data name="Tabs_Presets_Tell">
<value>Tell Exclusive</value>
</data>
<data name="Options_Tabs_NewTab"> <data name="Options_Tabs_NewTab">
<value>Nova aba</value> <value>Nova aba</value>
</data> </data>
@@ -1144,6 +1147,9 @@
<data name="Options_Tabs_NoInput" xml:space="preserve"> <data name="Options_Tabs_NoInput" xml:space="preserve">
<value>Desativar a entrada para este canal</value> <value>Desativar a entrada para este canal</value>
</data> </data>
<data name="Options_Tabs_SenderMessages" xml:space="preserve">
<value>Show all messages send by target</value>
</data>
<data name="ChatLog_DisabledInput" xml:space="preserve"> <data name="ChatLog_DisabledInput" xml:space="preserve">
<value>A entrada está desativada nesta aba</value> <value>A entrada está desativada nesta aba</value>
</data> </data>
@@ -1399,4 +1405,25 @@
<data name="Webinterface_UsageNotice" xml:space="preserve"> <data name="Webinterface_UsageNotice" xml:space="preserve">
<value>Usage Notice</value> <value>Usage Notice</value>
</data> </data>
<data name="Options_Help_SenderMessages" xml:space="preserve">
<value>This disables the channel selection and shows all messages coming from the target.</value>
</data>
<data name="Options_Header_Target" xml:space="preserve">
<value>Target</value>
</data>
<data name="ChatBox_Error_Empty" xml:space="preserve">
<value>message is empty</value>
</data>
<data name="ChatBox_Error_Too_Long" xml:space="preserve">
<value>message is longer than 500 bytes</value>
</data>
<data name="ChatBox_Error_Invalid" xml:space="preserve">
<value>message contained invalid characters</value>
</data>
<data name="ImGuiUtil_ChannelSelector_Source" xml:space="preserve">
<value>Source</value>
</data>
<data name="ImGuiUtil_ChannelSelector_Target" xml:space="preserve">
<value>Target</value>
</data>
</root> </root>
+27
View File
@@ -391,6 +391,9 @@
<data name="Tabs_Presets_Event"> <data name="Tabs_Presets_Event">
<value>Event</value> <value>Event</value>
</data> </data>
<data name="Tabs_Presets_Tell">
<value>Tell Exclusive</value>
</data>
<data name="Options_Tabs_NewTab"> <data name="Options_Tabs_NewTab">
<value>New tab</value> <value>New tab</value>
</data> </data>
@@ -1144,6 +1147,9 @@
<data name="Options_Tabs_NoInput" xml:space="preserve"> <data name="Options_Tabs_NoInput" xml:space="preserve">
<value>Disable input for this channel</value> <value>Disable input for this channel</value>
</data> </data>
<data name="Options_Tabs_SenderMessages" xml:space="preserve">
<value>Show all messages send by target</value>
</data>
<data name="ChatLog_DisabledInput" xml:space="preserve"> <data name="ChatLog_DisabledInput" xml:space="preserve">
<value>Input is disabled for this tab</value> <value>Input is disabled for this tab</value>
</data> </data>
@@ -1399,4 +1405,25 @@
<data name="Webinterface_UsageNotice" xml:space="preserve"> <data name="Webinterface_UsageNotice" xml:space="preserve">
<value>Usage Notice</value> <value>Usage Notice</value>
</data> </data>
<data name="Options_Help_SenderMessages" xml:space="preserve">
<value>This disables the channel selection and shows all messages coming from the target.</value>
</data>
<data name="Options_Header_Target" xml:space="preserve">
<value>Target</value>
</data>
<data name="ChatBox_Error_Empty" xml:space="preserve">
<value>message is empty</value>
</data>
<data name="ChatBox_Error_Too_Long" xml:space="preserve">
<value>message is longer than 500 bytes</value>
</data>
<data name="ChatBox_Error_Invalid" xml:space="preserve">
<value>message contained invalid characters</value>
</data>
<data name="ImGuiUtil_ChannelSelector_Source" xml:space="preserve">
<value>Source</value>
</data>
<data name="ImGuiUtil_ChannelSelector_Target" xml:space="preserve">
<value>Target</value>
</data>
</root> </root>
+27
View File
@@ -391,6 +391,9 @@
<data name="Tabs_Presets_Event"> <data name="Tabs_Presets_Event">
<value>Eveniment</value> <value>Eveniment</value>
</data> </data>
<data name="Tabs_Presets_Tell">
<value>Tell Exclusive</value>
</data>
<data name="Options_Tabs_NewTab"> <data name="Options_Tabs_NewTab">
<value>Tab nou</value> <value>Tab nou</value>
</data> </data>
@@ -1144,6 +1147,9 @@
<data name="Options_Tabs_NoInput" xml:space="preserve"> <data name="Options_Tabs_NoInput" xml:space="preserve">
<value>Disable input for this channel</value> <value>Disable input for this channel</value>
</data> </data>
<data name="Options_Tabs_SenderMessages" xml:space="preserve">
<value>Show all messages send by target</value>
</data>
<data name="ChatLog_DisabledInput" xml:space="preserve"> <data name="ChatLog_DisabledInput" xml:space="preserve">
<value>Input is disabled for this tab</value> <value>Input is disabled for this tab</value>
</data> </data>
@@ -1399,4 +1405,25 @@
<data name="Webinterface_UsageNotice" xml:space="preserve"> <data name="Webinterface_UsageNotice" xml:space="preserve">
<value>Usage Notice</value> <value>Usage Notice</value>
</data> </data>
<data name="Options_Help_SenderMessages" xml:space="preserve">
<value>This disables the channel selection and shows all messages coming from the target.</value>
</data>
<data name="Options_Header_Target" xml:space="preserve">
<value>Target</value>
</data>
<data name="ChatBox_Error_Empty" xml:space="preserve">
<value>message is empty</value>
</data>
<data name="ChatBox_Error_Too_Long" xml:space="preserve">
<value>message is longer than 500 bytes</value>
</data>
<data name="ChatBox_Error_Invalid" xml:space="preserve">
<value>message contained invalid characters</value>
</data>
<data name="ImGuiUtil_ChannelSelector_Source" xml:space="preserve">
<value>Source</value>
</data>
<data name="ImGuiUtil_ChannelSelector_Target" xml:space="preserve">
<value>Target</value>
</data>
</root> </root>
+27
View File
@@ -391,6 +391,9 @@
<data name="Tabs_Presets_Event"> <data name="Tabs_Presets_Event">
<value>События</value> <value>События</value>
</data> </data>
<data name="Tabs_Presets_Tell">
<value>Tell Exclusive</value>
</data>
<data name="Options_Tabs_NewTab"> <data name="Options_Tabs_NewTab">
<value>Новая вкладка</value> <value>Новая вкладка</value>
</data> </data>
@@ -1144,6 +1147,9 @@
<data name="Options_Tabs_NoInput" xml:space="preserve"> <data name="Options_Tabs_NoInput" xml:space="preserve">
<value>Disable input for this channel</value> <value>Disable input for this channel</value>
</data> </data>
<data name="Options_Tabs_SenderMessages" xml:space="preserve">
<value>Show all messages send by target</value>
</data>
<data name="ChatLog_DisabledInput" xml:space="preserve"> <data name="ChatLog_DisabledInput" xml:space="preserve">
<value>Input is disabled for this tab</value> <value>Input is disabled for this tab</value>
</data> </data>
@@ -1399,4 +1405,25 @@
<data name="Webinterface_UsageNotice" xml:space="preserve"> <data name="Webinterface_UsageNotice" xml:space="preserve">
<value>Usage Notice</value> <value>Usage Notice</value>
</data> </data>
<data name="Options_Help_SenderMessages" xml:space="preserve">
<value>This disables the channel selection and shows all messages coming from the target.</value>
</data>
<data name="Options_Header_Target" xml:space="preserve">
<value>Target</value>
</data>
<data name="ChatBox_Error_Empty" xml:space="preserve">
<value>message is empty</value>
</data>
<data name="ChatBox_Error_Too_Long" xml:space="preserve">
<value>message is longer than 500 bytes</value>
</data>
<data name="ChatBox_Error_Invalid" xml:space="preserve">
<value>message contained invalid characters</value>
</data>
<data name="ImGuiUtil_ChannelSelector_Source" xml:space="preserve">
<value>Source</value>
</data>
<data name="ImGuiUtil_ChannelSelector_Target" xml:space="preserve">
<value>Target</value>
</data>
</root> </root>
+27
View File
@@ -391,6 +391,9 @@
<data name="Tabs_Presets_Event"> <data name="Tabs_Presets_Event">
<value>Event</value> <value>Event</value>
</data> </data>
<data name="Tabs_Presets_Tell">
<value>Tell Exclusive</value>
</data>
<data name="Options_Tabs_NewTab"> <data name="Options_Tabs_NewTab">
<value>Ny flik</value> <value>Ny flik</value>
</data> </data>
@@ -1144,6 +1147,9 @@
<data name="Options_Tabs_NoInput" xml:space="preserve"> <data name="Options_Tabs_NoInput" xml:space="preserve">
<value>Disable input for this channel</value> <value>Disable input for this channel</value>
</data> </data>
<data name="Options_Tabs_SenderMessages" xml:space="preserve">
<value>Show all messages send by target</value>
</data>
<data name="ChatLog_DisabledInput" xml:space="preserve"> <data name="ChatLog_DisabledInput" xml:space="preserve">
<value>Input is disabled for this tab</value> <value>Input is disabled for this tab</value>
</data> </data>
@@ -1399,4 +1405,25 @@
<data name="Webinterface_UsageNotice" xml:space="preserve"> <data name="Webinterface_UsageNotice" xml:space="preserve">
<value>Usage Notice</value> <value>Usage Notice</value>
</data> </data>
<data name="Options_Help_SenderMessages" xml:space="preserve">
<value>This disables the channel selection and shows all messages coming from the target.</value>
</data>
<data name="Options_Header_Target" xml:space="preserve">
<value>Target</value>
</data>
<data name="ChatBox_Error_Empty" xml:space="preserve">
<value>message is empty</value>
</data>
<data name="ChatBox_Error_Too_Long" xml:space="preserve">
<value>message is longer than 500 bytes</value>
</data>
<data name="ChatBox_Error_Invalid" xml:space="preserve">
<value>message contained invalid characters</value>
</data>
<data name="ImGuiUtil_ChannelSelector_Source" xml:space="preserve">
<value>Source</value>
</data>
<data name="ImGuiUtil_ChannelSelector_Target" xml:space="preserve">
<value>Target</value>
</data>
</root> </root>
+27
View File
@@ -391,6 +391,9 @@
<data name="Tabs_Presets_Event"> <data name="Tabs_Presets_Event">
<value>剧情</value> <value>剧情</value>
</data> </data>
<data name="Tabs_Presets_Tell">
<value>Tell Exclusive</value>
</data>
<data name="Options_Tabs_NewTab"> <data name="Options_Tabs_NewTab">
<value>新建标签页</value> <value>新建标签页</value>
</data> </data>
@@ -1144,6 +1147,9 @@
<data name="Options_Tabs_NoInput" xml:space="preserve"> <data name="Options_Tabs_NoInput" xml:space="preserve">
<value>禁用此频道的输入</value> <value>禁用此频道的输入</value>
</data> </data>
<data name="Options_Tabs_SenderMessages" xml:space="preserve">
<value>Show all messages send by target</value>
</data>
<data name="ChatLog_DisabledInput" xml:space="preserve"> <data name="ChatLog_DisabledInput" xml:space="preserve">
<value>此选项卡已禁用输入</value> <value>此选项卡已禁用输入</value>
</data> </data>
@@ -1399,4 +1405,25 @@
<data name="Webinterface_UsageNotice" xml:space="preserve"> <data name="Webinterface_UsageNotice" xml:space="preserve">
<value>使用须知</value> <value>使用须知</value>
</data> </data>
<data name="Options_Help_SenderMessages" xml:space="preserve">
<value>This disables the channel selection and shows all messages coming from the target.</value>
</data>
<data name="Options_Header_Target" xml:space="preserve">
<value>Target</value>
</data>
<data name="ChatBox_Error_Empty" xml:space="preserve">
<value>message is empty</value>
</data>
<data name="ChatBox_Error_Too_Long" xml:space="preserve">
<value>message is longer than 500 bytes</value>
</data>
<data name="ChatBox_Error_Invalid" xml:space="preserve">
<value>message contained invalid characters</value>
</data>
<data name="ImGuiUtil_ChannelSelector_Source" xml:space="preserve">
<value>Source</value>
</data>
<data name="ImGuiUtil_ChannelSelector_Target" xml:space="preserve">
<value>Target</value>
</data>
</root> </root>
+27
View File
@@ -391,6 +391,9 @@
<data name="Tabs_Presets_Event"> <data name="Tabs_Presets_Event">
<value>劇情</value> <value>劇情</value>
</data> </data>
<data name="Tabs_Presets_Tell">
<value>Tell Exclusive</value>
</data>
<data name="Options_Tabs_NewTab"> <data name="Options_Tabs_NewTab">
<value>新建標籤頁</value> <value>新建標籤頁</value>
</data> </data>
@@ -1145,6 +1148,9 @@
<data name="Options_Tabs_NoInput" xml:space="preserve"> <data name="Options_Tabs_NoInput" xml:space="preserve">
<value>禁用此頻道的輸入</value> <value>禁用此頻道的輸入</value>
</data> </data>
<data name="Options_Tabs_SenderMessages" xml:space="preserve">
<value>Show all messages send by target</value>
</data>
<data name="ChatLog_DisabledInput" xml:space="preserve"> <data name="ChatLog_DisabledInput" xml:space="preserve">
<value>詞選項卡已禁用輸入</value> <value>詞選項卡已禁用輸入</value>
</data> </data>
@@ -1400,4 +1406,25 @@
<data name="Webinterface_UsageNotice" xml:space="preserve"> <data name="Webinterface_UsageNotice" xml:space="preserve">
<value>Usage Notice</value> <value>Usage Notice</value>
</data> </data>
<data name="Options_Help_SenderMessages" xml:space="preserve">
<value>This disables the channel selection and shows all messages coming from the target.</value>
</data>
<data name="Options_Header_Target" xml:space="preserve">
<value>Target</value>
</data>
<data name="ChatBox_Error_Empty" xml:space="preserve">
<value>message is empty</value>
</data>
<data name="ChatBox_Error_Too_Long" xml:space="preserve">
<value>message is longer than 500 bytes</value>
</data>
<data name="ChatBox_Error_Invalid" xml:space="preserve">
<value>message contained invalid characters</value>
</data>
<data name="ImGuiUtil_ChannelSelector_Source" xml:space="preserve">
<value>Source</value>
</data>
<data name="ImGuiUtil_ChannelSelector_Target" xml:space="preserve">
<value>Target</value>
</data>
</root> </root>
+8 -3
View File
@@ -1,4 +1,5 @@
using Lumina.Excel; using Dalamud.Game.ClientState.Objects.SubKinds;
using Lumina.Excel;
using Lumina.Excel.Sheets; using Lumina.Excel.Sheets;
namespace ChatTwo; namespace ChatTwo;
@@ -8,7 +9,6 @@ public static class Sheets
public static readonly ExcelSheet<Item> ItemSheet; public static readonly ExcelSheet<Item> ItemSheet;
public static readonly ExcelSheet<World> WorldSheet; public static readonly ExcelSheet<World> WorldSheet;
public static readonly ExcelSheet<Status> StatusSheet; public static readonly ExcelSheet<Status> StatusSheet;
public static readonly ExcelSheet<UIColor> UIColorSheet;
public static readonly ExcelSheet<LogKind> LogKindSheet; public static readonly ExcelSheet<LogKind> LogKindSheet;
public static readonly ExcelSheet<LogFilter> LogFilterSheet; public static readonly ExcelSheet<LogFilter> LogFilterSheet;
public static readonly ExcelSheet<EventItem> EventItemSheet; public static readonly ExcelSheet<EventItem> EventItemSheet;
@@ -22,7 +22,6 @@ public static class Sheets
ItemSheet = Plugin.DataManager.GetExcelSheet<Item>(); ItemSheet = Plugin.DataManager.GetExcelSheet<Item>();
WorldSheet = Plugin.DataManager.GetExcelSheet<World>(); WorldSheet = Plugin.DataManager.GetExcelSheet<World>();
StatusSheet = Plugin.DataManager.GetExcelSheet<Status>(); StatusSheet = Plugin.DataManager.GetExcelSheet<Status>();
UIColorSheet = Plugin.DataManager.GetExcelSheet<UIColor>();
LogKindSheet = Plugin.DataManager.GetExcelSheet<LogKind>(); LogKindSheet = Plugin.DataManager.GetExcelSheet<LogKind>();
LogFilterSheet = Plugin.DataManager.GetExcelSheet<LogFilter>(); LogFilterSheet = Plugin.DataManager.GetExcelSheet<LogFilter>();
EventItemSheet = Plugin.DataManager.GetExcelSheet<EventItem>(); EventItemSheet = Plugin.DataManager.GetExcelSheet<EventItem>();
@@ -35,4 +34,10 @@ public static class Sheets
public static bool IsInForay() => public static bool IsInForay() =>
TerritorySheet.TryGetRow(Plugin.ClientState.TerritoryType, out var row) && TerritorySheet.TryGetRow(Plugin.ClientState.TerritoryType, out var row) &&
row.TerritoryIntendedUse.RowId is 41 or 61; row.TerritoryIntendedUse.RowId is 41 or 61;
public static IEnumerable<World> WorldsOnDatacenter(IPlayerCharacter character)
{
var dcRow = character.HomeWorld.Value.DataCenter.Value.Region.RowId;
return WorldSheet.Where(world => world.IsPublic && world.DataCenter.Value.Region.RowId == dcRow);
}
} }
+10 -4
View File
@@ -639,7 +639,6 @@ public sealed class ChatLogWindow : Window
{ {
ImGui.SetNextWindowSize(new Vector2(500 * ImGuiHelpers.GlobalScale, -1)); ImGui.SetNextWindowSize(new Vector2(500 * ImGuiHelpers.GlobalScale, -1));
using var tooltip = ImRaii.Tooltip(); using var tooltip = ImRaii.Tooltip();
if (tooltip)
Plugin.InputPreview.DrawPreview(); Plugin.InputPreview.DrawPreview();
} }
@@ -775,7 +774,7 @@ public sealed class ChatLogWindow : Window
if (!currentChannel.SequenceEqual(PreviousChannel)) if (!currentChannel.SequenceEqual(PreviousChannel))
{ {
PreviousChannel = currentChannel; PreviousChannel = currentChannel;
Plugin.ServerCore?.SendChannelSwitch(currentChannel); Plugin.ServerCore.SendChannelSwitch(currentChannel);
} }
DrawChunks(currentChannel); DrawChunks(currentChannel);
@@ -819,6 +818,12 @@ public sealed class ChatLogWindow : Window
channelNameChunks = GenerateTellTargetName(activeTab.CurrentChannel.TellTarget); channelNameChunks = GenerateTellTargetName(activeTab.CurrentChannel.TellTarget);
} }
else if (activeTab is { Channel: { } channel }) else if (activeTab is { Channel: { } channel })
{
if (channel == InputChannel.Tell && activeTab.TellTarget.IsSet())
{
channelNameChunks = GenerateTellTargetName(activeTab.TellTarget);
}
else
{ {
// We cannot lookup ExtraChat channel names from index over // We cannot lookup ExtraChat channel names from index over
// IPC so we just don't show the name if it's the tabs channel. // IPC so we just don't show the name if it's the tabs channel.
@@ -827,6 +832,7 @@ public sealed class ChatLogWindow : Window
// long name as used in the settings window. // long name as used in the settings window.
channelNameChunks = [new TextChunk(ChunkSource.None, null, channel.IsExtraChatLinkshell() ? $"ECLS [{channel.LinkshellIndex() + 1}]" : channel.ToChatType().Name())]; channelNameChunks = [new TextChunk(ChunkSource.None, null, channel.IsExtraChatLinkshell() ? $"ECLS [{channel.LinkshellIndex() + 1}]" : channel.ToChatType().Name())];
} }
}
else if (Plugin.ExtraChat.ChannelOverride is var (overrideName, _)) else if (Plugin.ExtraChat.ChannelOverride is var (overrideName, _))
{ {
// If the current channel is not an ExtraChat Linkshell add a warning for the user // If the current channel is not an ExtraChat Linkshell add a warning for the user
@@ -912,7 +918,7 @@ public sealed class ChatLogWindow : Window
playerName = HashPlayer(tellTarget.Name, tellTarget.World); playerName = HashPlayer(tellTarget.Name, tellTarget.World);
var world = Sheets.WorldSheet.TryGetRow(tellTarget.World, out var worldRow) var world = Sheets.WorldSheet.TryGetRow(tellTarget.World, out var worldRow)
? worldRow.Name.ExtractText() ? worldRow.Name.ToString()
: "???"; : "???";
return return
@@ -954,7 +960,7 @@ public sealed class ChatLogWindow : Window
if (!trimmed.StartsWith('/')) if (!trimmed.StartsWith('/'))
{ {
var target = activeTab.CurrentChannel.TempTellTarget ?? activeTab.CurrentChannel.TellTarget; var target = activeTab.TellTarget.IsSet() ? activeTab.TellTarget : activeTab.CurrentChannel.TempTellTarget ?? activeTab.CurrentChannel.TellTarget;
if (target != null) if (target != null)
{ {
// ContentId 0 is a case where we can't directly send messages, so we send a /tell formatted message and let the game handle it // ContentId 0 is a case where we can't directly send messages, so we send a /tell formatted message and let the game handle it
+13 -13
View File
@@ -35,7 +35,7 @@ public class DbViewer : Window
private int CurrentPage = 1; private int CurrentPage = 1;
private string SimpleSearchTerm = ""; private string SimpleSearchTerm = "";
private bool OnlyCurrentCharacter = true; private bool OnlyCurrentCharacter = true;
private readonly Dictionary<ChatType, ChatSource> ChatCodes; private readonly Dictionary<ChatType, (ChatSource, ChatSource)> SelectedChannels;
private bool IsProcessing; private bool IsProcessing;
private long ProcessingStart = Environment.TickCount64; private long ProcessingStart = Environment.TickCount64;
@@ -58,12 +58,12 @@ public class DbViewer : Window
public DbViewer(Plugin plugin) : base("DBViewer###chat2-dbviewer") public DbViewer(Plugin plugin) : base("DBViewer###chat2-dbviewer")
{ {
Plugin = plugin; Plugin = plugin;
ChatCodes = TabsUtil.MostlyPlayer; SelectedChannels = TabsUtil.MostlyPlayer;
DateFormat = CultureInfo.CurrentCulture.DateTimeFormat.ShortDatePattern; DateFormat = CultureInfo.CurrentCulture.DateTimeFormat.ShortDatePattern;
DateTimeFormat = "ddd, dd MMM yyy HH:mm:ss"; DateTimeFormat = "ddd, dd MMM yyy HH:mm:ss";
LastProcessed = (AfterDate, BeforeDate, CurrentPage, OnlyCurrentCharacter, ChatCodes.Count); LastProcessed = (AfterDate, BeforeDate, CurrentPage, OnlyCurrentCharacter, SelectedChannels.Count);
DateReset(); DateReset();
SizeConstraints = new WindowSizeConstraints SizeConstraints = new WindowSizeConstraints
@@ -196,7 +196,7 @@ public class DbViewer : Window
if (DateWidget.Validate(MinimalDate, ref AfterDate, ref BeforeDate)) if (DateWidget.Validate(MinimalDate, ref AfterDate, ref BeforeDate))
DateRefresh(); DateRefresh();
if (!IsProcessing && LastProcessed != (AfterDate, BeforeDate, CurrentPage, OnlyCurrentCharacter, ChatCodes.Count)) if (!IsProcessing && LastProcessed != (AfterDate, BeforeDate, CurrentPage, OnlyCurrentCharacter, SelectedChannels.Count))
{ {
// Page hasn't changed, so we reset it back to 1 // Page hasn't changed, so we reset it back to 1
if (LastProcessed.Page == CurrentPage) if (LastProcessed.Page == CurrentPage)
@@ -205,13 +205,13 @@ public class DbViewer : Window
AdjustDates(); AdjustDates();
IsProcessing = true; IsProcessing = true;
ProcessingStart = Environment.TickCount64 + 1_000; // + 1 second ProcessingStart = Environment.TickCount64 + 1_000; // + 1 second
LastProcessed = (AfterDate, BeforeDate, CurrentPage, OnlyCurrentCharacter, ChatCodes.Count); LastProcessed = (AfterDate, BeforeDate, CurrentPage, OnlyCurrentCharacter, SelectedChannels.Count);
Task.Run(() => Task.Run(() =>
{ {
try try
{ {
ulong? character = OnlyCurrentCharacter ? Plugin.PlayerState.ContentId : null; ulong? character = OnlyCurrentCharacter ? Plugin.PlayerState.ContentId : null;
var channels = ChatCodes.Select(c => (uint) c.Key).ToArray(); var channels = SelectedChannels.Select(pair => (byte) pair.Key).ToArray();
// We only want to fetch count if this is the first page // We only want to fetch count if this is the first page
if (CurrentPage == 1) if (CurrentPage == 1)
@@ -263,7 +263,7 @@ public class DbViewer : Window
ImGui.TableNextColumn(); ImGui.TableNextColumn();
var pos = ImGui.GetCursorPos(); var pos = ImGui.GetCursorPos();
ImGuiUtil.CenterText($"{message.Code.Raw}"); ImGuiUtil.CenterText($"{(byte)message.Code.Type}");
ImGui.SetCursorPos(pos); ImGui.SetCursorPos(pos);
ImGui.Dummy(columnWidth); ImGui.Dummy(columnWidth);
if (ImGui.IsItemHovered()) if (ImGui.IsItemHovered())
@@ -303,13 +303,13 @@ public class DbViewer : Window
if (type.IsGm()) if (type.IsGm())
continue; continue;
var enabled = ChatCodes.ContainsKey(type); var enabled = SelectedChannels.ContainsKey(type);
if (ImGui.Checkbox($"##{type.Name()}", ref enabled)) if (ImGui.Checkbox($"##{type.Name()}", ref enabled))
{ {
if (enabled) if (enabled)
ChatCodes[type] = ChatSourceExt.All; SelectedChannels[type] = (ChatSourceExt.All, ChatSourceExt.All);
else else
ChatCodes.Remove(type); SelectedChannels.Remove(type);
} }
ImGui.SameLine(); ImGui.SameLine();
@@ -359,7 +359,7 @@ public class DbViewer : Window
try try
{ {
ulong? character = OnlyCurrentCharacter ? Plugin.PlayerState.ContentId : null; ulong? character = OnlyCurrentCharacter ? Plugin.PlayerState.ContentId : null;
var channels = ChatCodes.Select(c => (uint)c.Key).ToArray(); var channels = SelectedChannels.Select(pair => (byte)pair.Key).ToArray();
var rangeMessageEnumerator = Plugin.MessageManager.Store.GetDateRange(AfterDate, BeforeDate, channels, character); var rangeMessageEnumerator = Plugin.MessageManager.Store.GetDateRange(AfterDate, BeforeDate, channels, character);
var messageHistory = rangeMessageEnumerator.ToArray(); var messageHistory = rangeMessageEnumerator.ToArray();
@@ -426,7 +426,7 @@ public class DbViewer : Window
{ {
try try
{ {
var channels = ChatCodes.Select(c => (uint)c.Key).ToArray(); var channels = SelectedChannels.Select(pair => (byte)pair.Key).ToArray();
var rangeMessageEnumerator = Plugin.MessageManager.Store.GetDateRange(AfterDate, BeforeDate, channels); var rangeMessageEnumerator = Plugin.MessageManager.Store.GetDateRange(AfterDate, BeforeDate, channels);
var messageHistory = rangeMessageEnumerator.ToArray(); var messageHistory = rangeMessageEnumerator.ToArray();
@@ -536,7 +536,7 @@ public class DbViewer : Window
color ??= 0; color ??= 0;
var userContent = text.Content ?? string.Empty; var userContent = text.Content;
if (Plugin.ChatLogWindow.ScreenshotMode) if (Plugin.ChatLogWindow.ScreenshotMode)
{ {
if (chunk.Link is PlayerPayload playerPayload) if (chunk.Link is PlayerPayload playerPayload)
+1 -1
View File
@@ -71,7 +71,7 @@ public partial class InputPreview : Window
AutoTranslate.ReplaceWithPayload(ref bytes); AutoTranslate.ReplaceWithPayload(ref bytes);
var chunks = ChunkUtil.ToChunks(SeString.Parse(bytes), ChunkSource.Content, ChatType.Say).ToList(); var chunks = ChunkUtil.ToChunks(SeString.Parse(bytes), ChunkSource.Content, ChatType.Say).ToList();
PreviewMessage = Message.FakeMessage(chunks, new ChatCode((ushort)XivChatType.Say)); PreviewMessage = Message.FakeMessage(chunks, new ChatCode(XivChatType.Say, 0, 0));
PreviewMessage.DecodeTextParam(); PreviewMessage.DecodeTextParam();
} }
HasEvaluation = !Plugin.Config.OnlyPreviewIf || PreviewMessage.Content.Count > 1; HasEvaluation = !Plugin.Config.OnlyPreviewIf || PreviewMessage.Content.Count > 1;
+3 -2
View File
@@ -7,6 +7,7 @@ using Dalamud.Game.Text.SeStringHandling.Payloads;
using Dalamud.Interface.ImGuiNotification; using Dalamud.Interface.ImGuiNotification;
using Dalamud.Interface.Utility.Raii; using Dalamud.Interface.Utility.Raii;
using Dalamud.Bindings.ImGui; using Dalamud.Bindings.ImGui;
using Dalamud.Game.Text;
namespace ChatTwo.Ui.SettingsTabs; namespace ChatTwo.Ui.SettingsTabs;
@@ -180,17 +181,17 @@ internal sealed class Database : ISettingsTab
.Build(); .Build();
var contentChunks = ChunkUtil.ToChunks(contentSource, ChunkSource.Content, ChatType.Debug).ToList(); var contentChunks = ChunkUtil.ToChunks(contentSource, ChunkSource.Content, ChatType.Debug).ToList();
var chatCode = new ChatCode(XivChatType.Say, 0, 0);
messages.Add(new Message( messages.Add(new Message(
Guid.NewGuid(), Guid.NewGuid(),
Plugin.MessageManager.CurrentContentId, Plugin.MessageManager.CurrentContentId,
Plugin.MessageManager.CurrentContentId, Plugin.MessageManager.CurrentContentId,
DateTimeOffset.UtcNow, DateTimeOffset.UtcNow,
new ChatCode(10), chatCode,
senderChunks, senderChunks,
contentChunks, contentChunks,
senderSource, senderSource,
contentSource, contentSource,
new SortCode(ChatType.Debug, ChatSource.Self),
Guid.Empty Guid.Empty
)); ));
} }
+5 -8
View File
@@ -1,4 +1,3 @@
using ChatTwo.Code;
using ChatTwo.Resources; using ChatTwo.Resources;
using ChatTwo.Util; using ChatTwo.Util;
using Dalamud.Interface.Utility.Raii; using Dalamud.Interface.Utility.Raii;
@@ -67,26 +66,24 @@ internal sealed class Display : ISettingsTab
using var channelTree = ImRaii.TreeNode(Language.Options_InactivityHideChannels_Name); using var channelTree = ImRaii.TreeNode(Language.Options_InactivityHideChannels_Name);
if (channelTree.Success) if (channelTree.Success)
{ {
if (ImGuiUtil.CtrlShiftButton(Language.Options_InactivityHideChannels_All_Label, if (ImGuiUtil.CtrlShiftButton(Language.Options_InactivityHideChannels_All_Label, Language.Options_InactivityHideChannels_Button_Tooltip))
Language.Options_InactivityHideChannels_Button_Tooltip))
{ {
Mutable.InactivityHideChannels = TabsUtil.AllChannels(); Mutable.InactivityHideChannelsV2 = TabsUtil.AllChannels();
Mutable.InactivityHideExtraChatAll = true; Mutable.InactivityHideExtraChatAll = true;
Mutable.InactivityHideExtraChatChannels = []; Mutable.InactivityHideExtraChatChannels = [];
} }
ImGui.SameLine(); ImGui.SameLine();
if (ImGuiUtil.CtrlShiftButton(Language.Options_InactivityHideChannels_None_Label, if (ImGuiUtil.CtrlShiftButton(Language.Options_InactivityHideChannels_None_Label, Language.Options_InactivityHideChannels_Button_Tooltip))
Language.Options_InactivityHideChannels_Button_Tooltip))
{ {
Mutable.InactivityHideChannels = new Dictionary<ChatType, ChatSource>(); Mutable.InactivityHideChannelsV2 = [];
Mutable.InactivityHideExtraChatAll = false; Mutable.InactivityHideExtraChatAll = false;
Mutable.InactivityHideExtraChatChannels = []; Mutable.InactivityHideExtraChatChannels = [];
} }
ImGui.Spacing(); ImGui.Spacing();
ImGuiUtil.ChannelSelector(Language.Options_Tabs_Channels, Mutable.InactivityHideChannels!); ImGuiUtil.ChannelSelector(Language.Options_Tabs_Channels, Mutable.InactivityHideChannelsV2);
ImGuiUtil.ExtraChatSelector(Language.Options_Tabs_ExtraChatChannels, ImGuiUtil.ExtraChatSelector(Language.Options_Tabs_ExtraChatChannels,
ref Mutable.InactivityHideExtraChatAll, Mutable.InactivityHideExtraChatChannels); ref Mutable.InactivityHideExtraChatAll, Mutable.InactivityHideExtraChatChannels);
} }
+3 -3
View File
@@ -39,7 +39,7 @@ public class Fonts : ISettingsTab
}); });
ImGui.SameLine(); ImGui.SameLine();
if (ImGui.Button("Reset##global")) if (ImGui.Button("Reset##global"))
Mutable.GlobalFontV2 = new SingleFontSpec{ FontId = new DalamudAssetFontAndFamilyId(DalamudAsset.NotoSansKrRegular), SizePt = 12.75f }; Mutable.GlobalFontV2 = new SingleFontSpec{ FontId = new DalamudAssetFontAndFamilyId(DalamudAsset.NotoSansCjkRegular), SizePt = 12.75f };
ImGuiUtil.HelpText(string.Format(Language.Options_Font_Description, Plugin.PluginName)); ImGuiUtil.HelpText(string.Format(Language.Options_Font_Description, Plugin.PluginName));
ImGuiUtil.WarningText(Language.Options_Font_Warning); ImGuiUtil.WarningText(Language.Options_Font_Warning);
@@ -54,7 +54,7 @@ public class Fonts : ISettingsTab
}); });
ImGui.SameLine(); ImGui.SameLine();
if (ImGui.Button("Reset##japanese")) if (ImGui.Button("Reset##japanese"))
Mutable.JapaneseFontV2 = new SingleFontSpec{ FontId = new DalamudAssetFontAndFamilyId(DalamudAsset.NotoSansJpMedium), SizePt = 12.75f }; Mutable.JapaneseFontV2 = new SingleFontSpec{ FontId = new DalamudAssetFontAndFamilyId(DalamudAsset.NotoSansCjkMedium), SizePt = 12.75f };
ImGuiUtil.HelpText(string.Format(Language.Options_JapaneseFont_Description, Plugin.PluginName)); ImGuiUtil.HelpText(string.Format(Language.Options_JapaneseFont_Description, Plugin.PluginName));
ImGui.Spacing(); ImGui.Spacing();
@@ -69,7 +69,7 @@ public class Fonts : ISettingsTab
if (ImGui.Button("Reset##italic")) if (ImGui.Button("Reset##italic"))
{ {
Mutable.ItalicEnabled = false; Mutable.ItalicEnabled = false;
Mutable.ItalicFontV2 = new SingleFontSpec{ FontId = new DalamudAssetFontAndFamilyId(DalamudAsset.NotoSansKrRegular), SizePt = 12.75f }; Mutable.ItalicFontV2 = new SingleFontSpec{ FontId = new DalamudAssetFontAndFamilyId(DalamudAsset.NotoSansCjkRegular), SizePt = 12.75f };
} }
ImGuiUtil.HelpText(string.Format(Language.Options_Italic_Description, Plugin.PluginName)); ImGuiUtil.HelpText(string.Format(Language.Options_Italic_Description, Plugin.PluginName));
+64 -4
View File
@@ -4,6 +4,7 @@ using ChatTwo.Util;
using Dalamud.Interface; using Dalamud.Interface;
using Dalamud.Interface.Utility.Raii; using Dalamud.Interface.Utility.Raii;
using Dalamud.Bindings.ImGui; using Dalamud.Bindings.ImGui;
using Dalamud.Game.ClientState.Objects.SubKinds;
namespace ChatTwo.Ui.SettingsTabs; namespace ChatTwo.Ui.SettingsTabs;
@@ -43,6 +44,9 @@ internal sealed class Tabs : ISettingsTab
if (ImGui.Selectable(string.Format(Language.Options_Tabs_Preset, Language.Tabs_Presets_Event))) if (ImGui.Selectable(string.Format(Language.Options_Tabs_Preset, Language.Tabs_Presets_Event)))
Mutable.Tabs.Add(TabsUtil.VanillaEvent); Mutable.Tabs.Add(TabsUtil.VanillaEvent);
if (ImGui.Selectable(string.Format(Language.Options_Tabs_Preset, Language.Tabs_Presets_Tell)))
Mutable.Tabs.Add(TabsUtil.VanillaTellExclusive);
} }
} }
@@ -122,7 +126,7 @@ internal sealed class Tabs : ISettingsTab
using (var combo = ImGuiUtil.BeginComboVertical(Language.Options_Tabs_UnreadMode, tab.UnreadMode.Name())) using (var combo = ImGuiUtil.BeginComboVertical(Language.Options_Tabs_UnreadMode, tab.UnreadMode.Name()))
{ {
if (combo) if (combo.Success)
{ {
foreach (var mode in Enum.GetValues<UnreadMode>()) foreach (var mode in Enum.GetValues<UnreadMode>())
{ {
@@ -142,8 +146,9 @@ internal sealed class Tabs : ISettingsTab
if (!tab.InputDisabled) if (!tab.InputDisabled)
{ {
var input = tab.Channel?.ToChatType().Name() ?? Language.Options_Tabs_NoInputChannel; var input = tab.Channel?.ToChatType().Name() ?? Language.Options_Tabs_NoInputChannel;
using var combo = ImGuiUtil.BeginComboVertical(Language.Options_Tabs_InputChannel, input); using (var combo = ImGuiUtil.BeginComboVertical(Language.Options_Tabs_InputChannel, input))
if (combo) {
if (combo.Success)
{ {
if (ImGui.Selectable(Language.Options_Tabs_NoInputChannel, tab.Channel == null)) if (ImGui.Selectable(Language.Options_Tabs_NoInputChannel, tab.Channel == null))
tab.Channel = null; tab.Channel = null;
@@ -154,7 +159,62 @@ internal sealed class Tabs : ISettingsTab
} }
} }
ImGuiUtil.ChannelSelector(Language.Options_Tabs_Channels, tab.ChatCodes); ImGui.Checkbox(Language.Options_Tabs_SenderMessages, ref tab.AllSenderMessages);
ImGuiUtil.HelpText(Language.Options_Help_SenderMessages);
var player = Plugin.ObjectTable.LocalPlayer;
if (tab.Channel == InputChannel.Tell && player != null)
{
var worlds = Sheets.WorldsOnDatacenter(player).OrderByDescending(world => world.DataCenter.RowId).ThenBy(world => world.Name.ToString()).ToList();
using (ImRaii.ItemWidth(ImGui.GetWindowWidth() / 3f))
{
ImGui.Text(Language.Options_Header_Target);
ImGui.SameLine();
var name = tab.TellTarget.Name;
if (ImGui.InputText("##targetInput", ref name, 21))
tab.TellTarget.Name = name;
ImGui.SameLine();
var selectedWorld = worlds.FindIndex(world => world.RowId == tab.TellTarget.World);
if (selectedWorld == -1)
selectedWorld = 0;
using (var combo = ImRaii.Combo("###player-world", worlds[selectedWorld].Name.ToString()))
{
if (combo.Success)
{
var lastDc = worlds.First().DataCenter.RowId;
foreach (var (idx, world) in worlds.Index())
{
if (ImGui.Selectable(world.Name.ToString(), selectedWorld == idx))
{
selectedWorld = idx;
tab.TellTarget.World = worlds[selectedWorld].RowId;
}
if (lastDc == world.DataCenter.RowId)
continue;
lastDc = world.DataCenter.RowId;
ImGui.Separator();
}
}
}
}
var target = (Plugin.TargetManager.SoftTarget ?? Plugin.TargetManager.Target) as IPlayerCharacter;
using (ImRaii.Disabled(target == null))
{
if (ImGui.Button("Set to target") && target != null)
tab.TellTarget.FromTarget(target);
}
}
}
ImGuiUtil.ChannelSelector(Language.Options_Tabs_Channels, tab.SelectedChannels);
ImGuiUtil.ExtraChatSelector(Language.Options_Tabs_ExtraChatChannels, ref tab.ExtraChatAll, tab.ExtraChatChannels); ImGuiUtil.ExtraChatSelector(Language.Options_Tabs_ExtraChatChannels, ref tab.ExtraChatAll, tab.ExtraChatChannels);
} }
+40 -43
View File
@@ -1,11 +1,8 @@
using System.Runtime.CompilerServices;
using ChatTwo.Code; using ChatTwo.Code;
using Dalamud.Game.Text.SeStringHandling; using Dalamud.Game.Text.SeStringHandling;
using Dalamud.Game.Text.SeStringHandling.Payloads; using Dalamud.Game.Text.SeStringHandling.Payloads;
using System.Text; using System.Text;
using Lumina.Text.Expressions;
using Lumina.Text.Payloads; using Lumina.Text.Payloads;
using Lumina.Text.ReadOnly;
using PayloadType = Dalamud.Game.Text.SeStringHandling.PayloadType; using PayloadType = Dalamud.Game.Text.SeStringHandling.PayloadType;
@@ -417,46 +414,46 @@ internal static class ChunkUtil
return BitConverter.ToUInt32(numArray, 0); return BitConverter.ToUInt32(numArray, 0);
} }
private static bool TryResolveUInt(in ReadOnlySeExpressionSpan expression, out uint value) // private static bool TryResolveUInt(in ReadOnlySeExpressionSpan expression, out uint value)
{
if (expression.TryGetUInt(out value))
return true;
if (expression.TryGetParameterExpression(out var exprType, out var operand1))
{
if (!TryResolveUInt(operand1, out var paramIndex))
return false;
if (paramIndex == 0)
return false;
paramIndex--;
if ((ExpressionType)exprType == ExpressionType.GlobalNumber)
{
value = (uint) GlobalParametersCache.GetValue((int)paramIndex);
return true;
}
// return (ExpressionType)exprType switch
// { // {
// // ExpressionType.LocalNumber => context.TryGetLNum((int)paramIndex, out value), // lnum // if (expression.TryGetUInt(out value))
// ExpressionType.GlobalNumber => (uint) GlobalParametersCache.GetValue((int)paramIndex), // gnum // return true;
// _ => false, // gstr, lstr //
// }; // if (expression.TryGetParameterExpression(out var exprType, out var operand1))
} // {
// if (!TryResolveUInt(operand1, out var paramIndex))
// return false;
//
// if (paramIndex == 0)
// return false;
//
// paramIndex--;
// if ((ExpressionType)exprType == ExpressionType.GlobalNumber)
// {
// value = (uint) GlobalParametersCache.GetValue((int)paramIndex);
// return true;
// }
// // return (ExpressionType)exprType switch
// // {
// // // ExpressionType.LocalNumber => context.TryGetLNum((int)paramIndex, out value), // lnum
// // ExpressionType.GlobalNumber => (uint) GlobalParametersCache.GetValue((int)paramIndex), // gnum
// // _ => false, // gstr, lstr
// // };
// }
//
// return false;
// }
return false; // [MethodImpl(MethodImplOptions.AggressiveInlining)]
} // private static bool TryResolveInt(in ReadOnlySeExpressionSpan expression, out int value)
// {
[MethodImpl(MethodImplOptions.AggressiveInlining)] // if (TryResolveUInt(expression, out var u32))
private static bool TryResolveInt(in ReadOnlySeExpressionSpan expression, out int value) // {
{ // value = (int)u32;
if (TryResolveUInt(expression, out var u32)) // return true;
{ // }
value = (int)u32; //
return true; // value = 0;
} // return false;
// }
value = 0;
return false;
}
} }
+3 -4
View File
@@ -4,20 +4,19 @@ using System.Numerics;
namespace ChatTwo.Util; namespace ChatTwo.Util;
internal static class ColourUtil { internal static class ColourUtil {
private static (byte r, byte g, byte b, byte a) RgbaToComponents(uint rgba) private static (byte r, byte g, byte b) RgbaToRgbComponents(uint rgba)
{ {
var r = (byte) ((rgba & 0xFF000000) >> 24); var r = (byte) ((rgba & 0xFF000000) >> 24);
var g = (byte) ((rgba & 0xFF0000) >> 16); var g = (byte) ((rgba & 0xFF0000) >> 16);
var b = (byte) ((rgba & 0xFF00) >> 8); var b = (byte) ((rgba & 0xFF00) >> 8);
var a = (byte) (rgba & 0xFF); return (r, g, b);
return (r, g, b, a);
} }
internal static uint RgbaToAbgr(uint rgba) => BinaryPrimitives.ReverseEndianness(rgba); internal static uint RgbaToAbgr(uint rgba) => BinaryPrimitives.ReverseEndianness(rgba);
internal static Vector3 RgbaToVector3(uint rgba) internal static Vector3 RgbaToVector3(uint rgba)
{ {
var (r, g, b, _) = RgbaToComponents(rgba); var (r, g, b) = RgbaToRgbComponents(rgba);
return new Vector3((float) r / 255, (float) g / 255, (float) b / 255); return new Vector3((float) r / 255, (float) g / 255, (float) b / 255);
} }
+2
View File
@@ -37,7 +37,9 @@ public class ColorPayload
{ {
return v switch return v switch
{ {
// ReSharper disable once LocalizableElement
-1 => throw new ArgumentException("Encountered premature end of input (unexpected EOF).", nameof(v)), -1 => throw new ArgumentException("Encountered premature end of input (unexpected EOF).", nameof(v)),
// ReSharper disable once LocalizableElement
0 => throw new ArgumentException("Encountered premature end of input (unexpected null character).", nameof(v)), 0 => throw new ArgumentException("Encountered premature end of input (unexpected null character).", nameof(v)),
_ => (uint)v << shift _ => (uint)v << shift
}; };
+20 -8
View File
@@ -225,7 +225,7 @@ internal static class ImGuiUtil
ImGui.TextUnformatted(text); ImGui.TextUnformatted(text);
} }
internal static ImRaii.IEndObject BeginComboVertical(string label, string previewValue, ImGuiComboFlags flags = ImGuiComboFlags.None) internal static ImRaii.ComboDisposable BeginComboVertical(string label, string previewValue, ImGuiComboFlags flags = ImGuiComboFlags.None)
{ {
ImGui.TextUnformatted(label); ImGui.TextUnformatted(label);
ImGui.SetNextItemWidth(-1); ImGui.SetNextItemWidth(-1);
@@ -542,7 +542,7 @@ internal static class ImGuiUtil
return result != 0 || key == VirtualKey.NO_KEY; return result != 0 || key == VirtualKey.NO_KEY;
} }
public static void ChannelSelector(string headerText, Dictionary<ChatType, ChatSource> chatCodes) public static void ChannelSelector(string headerText, Dictionary<ChatType, (ChatSource Source, ChatSource Target)> chatCodes)
{ {
using var channelNode = ImRaii.TreeNode(headerText); using var channelNode = ImRaii.TreeNode(headerText);
if (!channelNode.Success) if (!channelNode.Success)
@@ -563,7 +563,7 @@ internal static class ImGuiUtil
if (ImGui.Checkbox($"##{type.Name()}", ref enabled)) if (ImGui.Checkbox($"##{type.Name()}", ref enabled))
{ {
if (enabled) if (enabled)
chatCodes[type] = ChatSourceExt.All; chatCodes[type] = (ChatSourceExt.All, ChatSourceExt.All);
else else
chatCodes.Remove(type); chatCodes.Remove(type);
} }
@@ -580,12 +580,24 @@ internal static class ImGuiUtil
if (!typeNode.Success) if (!typeNode.Success)
continue; continue;
chatCodes.TryGetValue(type, out var sourcesEnum); ImGui.Text(Language.ImGuiUtil_ChannelSelector_Source);
var sources = (uint)sourcesEnum; ImGui.SameLine(400.0f * ImGuiHelpers.GlobalScale);
ImGui.Text(Language.ImGuiUtil_ChannelSelector_Target);
foreach (var source in Enum.GetValues<ChatSource>()) chatCodes.TryGetValue(type, out var sourcesEnum);
if (ImGui.CheckboxFlags(source.Name(), ref sources, (uint)source)) var sources = (uint)sourcesEnum.Source;
chatCodes[type] = (ChatSource)sources; var targets = (uint)sourcesEnum.Target;
foreach (var kind in Enum.GetValues<ChatSource>().Where(s => s != ChatSource.None))
{
if (ImGui.CheckboxFlags($"{kind.Name()}##source", ref sources, (uint)kind))
chatCodes[type] = ((ChatSource)sources, sourcesEnum.Target);
ImGui.SameLine(400.0f * ImGuiHelpers.GlobalScale);
if (ImGui.CheckboxFlags($"{kind.Name()}##target", ref targets, (uint)kind))
chatCodes[type] = (sourcesEnum.Source, (ChatSource)targets);
}
} }
} }
} }
+118 -106
View File
@@ -3,135 +3,147 @@ using ChatTwo.Resources;
namespace ChatTwo.Util; namespace ChatTwo.Util;
internal static class TabsUtil public static class TabsUtil
{ {
internal static Dictionary<ChatType, ChatSource> AllChannels() public static Dictionary<ChatType, (ChatSource, ChatSource)> AllChannels()
{ {
var channels = new Dictionary<ChatType, ChatSource>(); var channels = new Dictionary<ChatType, (ChatSource, ChatSource)>();
foreach (var chatType in Enum.GetValues<ChatType>()) foreach (var chatType in Enum.GetValues<ChatType>())
channels[chatType] = ChatSourceExt.All; channels[chatType] = (ChatSourceExt.All, ChatSourceExt.All);
return channels; return channels;
} }
internal static Tab VanillaGeneral => new() public static Tab VanillaGeneral => new()
{ {
Name = Language.Tabs_Presets_General, Name = Language.Tabs_Presets_General,
ChatCodes = new Dictionary<ChatType, ChatSource> SelectedChannels = new Dictionary<ChatType, (ChatSource, ChatSource)>
{ {
// Special // Special
[ChatType.Debug] = ChatSourceExt.All, [ChatType.Debug] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.Urgent] = ChatSourceExt.All, [ChatType.Urgent] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.Notice] = ChatSourceExt.All, [ChatType.Notice] = (ChatSourceExt.All, ChatSourceExt.All),
// Chat // Chat
[ChatType.Say] = ChatSourceExt.All, [ChatType.Say] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.Yell] = ChatSourceExt.All, [ChatType.Yell] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.Shout] = ChatSourceExt.All, [ChatType.Shout] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.TellIncoming] = ChatSourceExt.All, [ChatType.TellIncoming] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.TellOutgoing] = ChatSourceExt.All, [ChatType.TellOutgoing] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.Party] = ChatSourceExt.All, [ChatType.Party] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.CrossParty] = ChatSourceExt.All, [ChatType.CrossParty] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.Alliance] = ChatSourceExt.All, [ChatType.Alliance] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.FreeCompany] = ChatSourceExt.All, [ChatType.FreeCompany] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.PvpTeam] = ChatSourceExt.All, [ChatType.PvpTeam] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.CrossLinkshell1] = ChatSourceExt.All, [ChatType.CrossLinkshell1] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.CrossLinkshell2] = ChatSourceExt.All, [ChatType.CrossLinkshell2] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.CrossLinkshell3] = ChatSourceExt.All, [ChatType.CrossLinkshell3] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.CrossLinkshell4] = ChatSourceExt.All, [ChatType.CrossLinkshell4] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.CrossLinkshell5] = ChatSourceExt.All, [ChatType.CrossLinkshell5] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.CrossLinkshell6] = ChatSourceExt.All, [ChatType.CrossLinkshell6] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.CrossLinkshell7] = ChatSourceExt.All, [ChatType.CrossLinkshell7] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.CrossLinkshell8] = ChatSourceExt.All, [ChatType.CrossLinkshell8] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.Linkshell1] = ChatSourceExt.All, [ChatType.Linkshell1] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.Linkshell2] = ChatSourceExt.All, [ChatType.Linkshell2] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.Linkshell3] = ChatSourceExt.All, [ChatType.Linkshell3] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.Linkshell4] = ChatSourceExt.All, [ChatType.Linkshell4] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.Linkshell5] = ChatSourceExt.All, [ChatType.Linkshell5] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.Linkshell6] = ChatSourceExt.All, [ChatType.Linkshell6] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.Linkshell7] = ChatSourceExt.All, [ChatType.Linkshell7] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.Linkshell8] = ChatSourceExt.All, [ChatType.Linkshell8] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.NoviceNetwork] = ChatSourceExt.All, [ChatType.NoviceNetwork] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.StandardEmote] = ChatSourceExt.All, [ChatType.StandardEmote] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.CustomEmote] = ChatSourceExt.All, [ChatType.CustomEmote] = (ChatSourceExt.All, ChatSourceExt.All),
// Announcements // Announcements
[ChatType.System] = ChatSourceExt.All, [ChatType.System] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.GatheringSystem] = ChatSourceExt.All, [ChatType.GatheringSystem] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.Error] = ChatSourceExt.All, [ChatType.Error] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.Echo] = ChatSourceExt.All, [ChatType.Echo] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.NoviceNetworkSystem] = ChatSourceExt.All, [ChatType.NoviceNetworkSystem] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.FreeCompanyAnnouncement] = ChatSourceExt.All, [ChatType.FreeCompanyAnnouncement] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.PvpTeamAnnouncement] = ChatSourceExt.All, [ChatType.PvpTeamAnnouncement] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.FreeCompanyLoginLogout] = ChatSourceExt.All, [ChatType.FreeCompanyLoginLogout] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.PvpTeamLoginLogout] = ChatSourceExt.All, [ChatType.PvpTeamLoginLogout] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.RetainerSale] = ChatSourceExt.All, [ChatType.RetainerSale] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.NpcAnnouncement] = ChatSourceExt.All, [ChatType.NpcAnnouncement] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.LootNotice] = ChatSourceExt.All, [ChatType.LootNotice] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.Progress] = ChatSourceExt.All, [ChatType.Progress] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.LootRoll] = ChatSourceExt.All, [ChatType.LootRoll] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.Crafting] = ChatSourceExt.All, [ChatType.Crafting] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.Gathering] = ChatSource.Self, [ChatType.Gathering] = (ChatSource.LocalPlayer, ChatSource.LocalPlayer),
[ChatType.PeriodicRecruitmentNotification] = ChatSourceExt.All, [ChatType.PeriodicRecruitmentNotification] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.Sign] = ChatSourceExt.All, [ChatType.Sign] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.RandomNumber] = ChatSourceExt.All, [ChatType.RandomNumber] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.Orchestrion] = ChatSourceExt.All, [ChatType.Orchestrion] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.MessageBook] = ChatSourceExt.All, [ChatType.MessageBook] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.Alarm] = ChatSourceExt.All, [ChatType.Alarm] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.GlamourNotifications] = ChatSourceExt.All, [ChatType.GlamourNotifications] = (ChatSourceExt.All, ChatSourceExt.All),
} }
}; };
internal static Tab VanillaEvent => new() public static Tab VanillaEvent => new()
{ {
Name = Language.Tabs_Presets_Event, Name = Language.Tabs_Presets_Event,
ChatCodes = new Dictionary<ChatType, ChatSource> { [ChatType.NpcDialogue] = ChatSourceExt.All, }, SelectedChannels = new Dictionary<ChatType, (ChatSource, ChatSource)> { [ChatType.NpcDialogue] = (ChatSourceExt.All, ChatSourceExt.All), },
}; };
internal static Dictionary<ChatType, ChatSource> MostlyPlayer => new() public static Tab VanillaTellExclusive => new()
{
Name = Language.Tabs_Presets_Tell,
SelectedChannels = new Dictionary<ChatType, (ChatSource, ChatSource)>
{
[ChatType.TellIncoming] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.TellOutgoing] = (ChatSourceExt.All, ChatSourceExt.All),
},
Channel = InputChannel.Tell,
AllSenderMessages = true,
};
public static Dictionary<ChatType, (ChatSource, ChatSource)> MostlyPlayer => new()
{ {
// Special // Special
[ChatType.Debug] = ChatSourceExt.All, [ChatType.Debug] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.Urgent] = ChatSourceExt.All, [ChatType.Urgent] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.Notice] = ChatSourceExt.All, [ChatType.Notice] = (ChatSourceExt.All, ChatSourceExt.All),
// Chat // Chat
[ChatType.Say] = ChatSourceExt.All, [ChatType.Say] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.Yell] = ChatSourceExt.All, [ChatType.Yell] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.Shout] = ChatSourceExt.All, [ChatType.Shout] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.TellIncoming] = ChatSourceExt.All, [ChatType.TellIncoming] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.TellOutgoing] = ChatSourceExt.All, [ChatType.TellOutgoing] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.Party] = ChatSourceExt.All, [ChatType.Party] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.CrossParty] = ChatSourceExt.All, [ChatType.CrossParty] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.Alliance] = ChatSourceExt.All, [ChatType.Alliance] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.FreeCompany] = ChatSourceExt.All, [ChatType.FreeCompany] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.PvpTeam] = ChatSourceExt.All, [ChatType.PvpTeam] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.CrossLinkshell1] = ChatSourceExt.All, [ChatType.CrossLinkshell1] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.CrossLinkshell2] = ChatSourceExt.All, [ChatType.CrossLinkshell2] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.CrossLinkshell3] = ChatSourceExt.All, [ChatType.CrossLinkshell3] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.CrossLinkshell4] = ChatSourceExt.All, [ChatType.CrossLinkshell4] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.CrossLinkshell5] = ChatSourceExt.All, [ChatType.CrossLinkshell5] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.CrossLinkshell6] = ChatSourceExt.All, [ChatType.CrossLinkshell6] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.CrossLinkshell7] = ChatSourceExt.All, [ChatType.CrossLinkshell7] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.CrossLinkshell8] = ChatSourceExt.All, [ChatType.CrossLinkshell8] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.Linkshell1] = ChatSourceExt.All, [ChatType.Linkshell1] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.Linkshell2] = ChatSourceExt.All, [ChatType.Linkshell2] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.Linkshell3] = ChatSourceExt.All, [ChatType.Linkshell3] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.Linkshell4] = ChatSourceExt.All, [ChatType.Linkshell4] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.Linkshell5] = ChatSourceExt.All, [ChatType.Linkshell5] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.Linkshell6] = ChatSourceExt.All, [ChatType.Linkshell6] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.Linkshell7] = ChatSourceExt.All, [ChatType.Linkshell7] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.Linkshell8] = ChatSourceExt.All, [ChatType.Linkshell8] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.NoviceNetwork] = ChatSourceExt.All, [ChatType.NoviceNetwork] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.StandardEmote] = ChatSourceExt.All, [ChatType.StandardEmote] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.CustomEmote] = ChatSourceExt.All, [ChatType.CustomEmote] = (ChatSourceExt.All, ChatSourceExt.All),
// Announcements // Announcements
[ChatType.System] = ChatSourceExt.All, [ChatType.System] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.Error] = ChatSourceExt.All, [ChatType.Error] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.Echo] = ChatSourceExt.All, [ChatType.Echo] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.NoviceNetworkSystem] = ChatSourceExt.All, [ChatType.NoviceNetworkSystem] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.FreeCompanyAnnouncement] = ChatSourceExt.All, [ChatType.FreeCompanyAnnouncement] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.PvpTeamAnnouncement] = ChatSourceExt.All, [ChatType.PvpTeamAnnouncement] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.FreeCompanyLoginLogout] = ChatSourceExt.All, [ChatType.FreeCompanyLoginLogout] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.PvpTeamLoginLogout] = ChatSourceExt.All, [ChatType.PvpTeamLoginLogout] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.RandomNumber] = ChatSourceExt.All, [ChatType.RandomNumber] = (ChatSourceExt.All, ChatSourceExt.All),
[ChatType.MessageBook] = ChatSourceExt.All, [ChatType.MessageBook] = (ChatSourceExt.All, ChatSourceExt.All),
}; };
} }
+3 -3
View File
@@ -4,9 +4,9 @@
"net10.0-windows7.0": { "net10.0-windows7.0": {
"DalamudPackager": { "DalamudPackager": {
"type": "Direct", "type": "Direct",
"requested": "[14.0.2, )", "requested": "[15.0.0, )",
"resolved": "14.0.2", "resolved": "15.0.0",
"contentHash": "dQJeq+8eyHzra4Cg5eZ/3LAeS3/UpvvLriYJGSncMK9LqJ7Q4B6jwcOsxo3PfxVd15xj+IzVFxkPqIBmPQu8/w==" "contentHash": "411vwC8/X8Z/sQ2TI6v3SvOn66xFPeOjFn3Zn+h0d3Ox2t1kFm66AhDvmx/qcMwVrR+Hidxj0dadpQ2dgyXMBQ=="
}, },
"DotNet.ReproducibleBuilds": { "DotNet.ReproducibleBuilds": {
"type": "Direct", "type": "Direct",