Skip to content

Commit 9089a50

Browse files
committed
[Packet viewer] Added creature text as a database diff processor
1 parent 4d9bd3d commit 9089a50

File tree

8 files changed

+239
-25
lines changed

8 files changed

+239
-25
lines changed
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
using System;
2+
using System.Windows.Input;
3+
using Avalonia;
4+
using Avalonia.Controls;
5+
using Avalonia.Input;
6+
7+
namespace WDE.Common.Avalonia.Controls
8+
{
9+
/***
10+
* This is KeyBinding that forwards the gesture to the focused TextBox first
11+
*/
12+
public class BetterKeyBinding : KeyBinding, ICommand
13+
{
14+
public static readonly StyledProperty<ICommand> CustomCommandProperty = AvaloniaProperty.Register<KeyBinding, ICommand>(nameof (CustomCommand));
15+
16+
public ICommand CustomCommand
17+
{
18+
get => GetValue(CustomCommandProperty);
19+
set => SetValue(CustomCommandProperty, value);
20+
}
21+
22+
public BetterKeyBinding()
23+
{
24+
Command = this;
25+
}
26+
27+
public bool CanExecute(object? parameter)
28+
{
29+
return CustomCommand.CanExecute(parameter);
30+
}
31+
32+
public void Execute(object? parameter)
33+
{
34+
if (FocusManager.Instance.Current is TextBox tb)
35+
{
36+
var ev = new KeyEventArgs()
37+
{
38+
Key = Gesture.Key,
39+
KeyModifiers = Gesture.KeyModifiers,
40+
RoutedEvent = InputElement.KeyDownEvent
41+
};
42+
tb.RaiseEvent(ev);
43+
if (!ev.Handled)
44+
CustomCommand.Execute(parameter);
45+
}
46+
else
47+
CustomCommand.Execute(parameter);
48+
}
49+
50+
public event EventHandler? CanExecuteChanged
51+
{
52+
add => CustomCommand.CanExecuteChanged += value;
53+
remove => CustomCommand.CanExecuteChanged -= value;
54+
}
55+
}
56+
}
Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Threading.Tasks;
3+
using Prism.Ioc;
34
using WDE.Common.Types;
45
using WDE.Module.Attributes;
56
using WDE.PacketViewer.Processing.Processors;
@@ -9,17 +10,34 @@ namespace WDE.PacketViewer.Processing.ProcessorProviders
910
[AutoRegister]
1011
public class CreatureTextDumperProvider : IPacketDumperProvider
1112
{
12-
private readonly Func<CreatureTextDumper> creator;
13+
private readonly IContainerProvider containerProvider;
1314

14-
public CreatureTextDumperProvider(Func<CreatureTextDumper> creator)
15+
public CreatureTextDumperProvider(IContainerProvider containerProvider)
1516
{
16-
this.creator = creator;
17+
this.containerProvider = containerProvider;
1718
}
1819
public string Name => "Creature text";
1920
public string Description => "Generate all creature texts with emotes and sounds";
2021
public string Extension => "sql";
2122
public ImageUri? Image { get; } = new ImageUri("icons/chat_big.png");
2223
public Task<IPacketTextDumper> CreateDumper() =>
23-
Task.FromResult<IPacketTextDumper>(creator());
24+
Task.FromResult<IPacketTextDumper>(containerProvider.Resolve<CreatureTextDumper>((typeof(bool), false)));
25+
}
26+
27+
[AutoRegister]
28+
public class CreatureTextDiffDumperProvider : IPacketDumperProvider
29+
{
30+
private readonly IContainerProvider containerProvider;
31+
32+
public CreatureTextDiffDumperProvider(IContainerProvider containerProvider)
33+
{
34+
this.containerProvider = containerProvider;
35+
}
36+
public string Name => "Creature text (diff)";
37+
public string Description => "Generate all creature texts with emotes and sounds, as a diff with current texts in the database";
38+
public string Extension => "sql";
39+
public ImageUri? Image { get; } = new ImageUri("icons/chat_diff_big.png");
40+
public Task<IPacketTextDumper> CreateDumper() =>
41+
Task.FromResult<IPacketTextDumper>(containerProvider.Resolve<CreatureTextDumper>((typeof(bool), true)));
2442
}
2543
}

WDE.PacketViewer/Processing/Processors/CreatureTextDumper.cs

Lines changed: 127 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using System;
12
using System.Collections.Generic;
23
using System.Linq;
34
using System.Threading.Tasks;
@@ -10,20 +11,94 @@ namespace WDE.PacketViewer.Processing.Processors
1011
{
1112
public class CreatureTextDumper : PacketProcessor<bool>, ITwoStepPacketBoolProcessor, IPacketTextDumper
1213
{
14+
private class TextEntry : IEquatable<TextEntry>
15+
{
16+
public byte GroupId;
17+
public byte Id;
18+
public float Probability;
19+
public CreatureTextRange Range;
20+
public uint Duration;
21+
public readonly CreatureTextType Type;
22+
public readonly uint Language;
23+
public readonly uint Emote;
24+
public readonly uint Sound;
25+
public readonly string Text;
26+
public bool IsInSniffText { get; set; }
27+
public bool IsInDatabaseText { get; set; }
28+
public uint BroadcastTextId { get; set; }
29+
30+
public string? Comment;
31+
32+
public TextEntry(string text, CreatureTextType type, uint language, uint emote, uint sound)
33+
{
34+
Text = text;
35+
Type = type;
36+
Language = language;
37+
Emote = emote;
38+
Sound = sound;
39+
Probability = 100;
40+
Range = CreatureTextRange.Normal;
41+
IsInSniffText = true;
42+
IsInDatabaseText = false;
43+
}
44+
45+
public TextEntry(ICreatureText text)
46+
{
47+
IsInSniffText = false;
48+
IsInDatabaseText = true;
49+
Text = text.Text ?? "";
50+
Type = text.Type;
51+
Language = text.Language;
52+
Emote = text.Emote;
53+
Sound = text.Sound;
54+
GroupId = text.GroupId;
55+
Probability = text.Probability;
56+
Duration = text.Duration;
57+
Range = text.TextRange;
58+
Id = text.Id;
59+
BroadcastTextId = text.BroadcastTextId;
60+
Comment = text.Comment;
61+
}
62+
63+
public bool Equals(TextEntry? other)
64+
{
65+
if (ReferenceEquals(null, other)) return false;
66+
if (ReferenceEquals(this, other)) return true;
67+
return Type == other.Type && Language == other.Language && Emote == other.Emote && Sound == other.Sound && Text == other.Text;
68+
}
69+
70+
public override bool Equals(object? obj)
71+
{
72+
if (ReferenceEquals(null, obj)) return false;
73+
if (ReferenceEquals(this, obj)) return true;
74+
if (obj.GetType() != this.GetType()) return false;
75+
return Equals((TextEntry)obj);
76+
}
77+
78+
public override int GetHashCode()
79+
{
80+
return HashCode.Combine((int)Type, Language, Emote, Sound, Text);
81+
}
82+
}
83+
1384
private class State
1485
{
15-
public Dictionary<string, (int groupdId, int type, int language, int emote, uint sound)> texts = new();
86+
public HashSet<TextEntry> texts = new();
1687
}
1788

1889
private readonly IChatEmoteSoundProcessor chatEmoteSoundProcessor;
1990
private readonly IDatabaseProvider databaseProvider;
91+
private readonly bool asDiff;
2092

2193
private readonly Dictionary<uint, State> perEntryState = new();
2294

23-
public CreatureTextDumper(IChatEmoteSoundProcessor chatEmoteSoundProcessor, IDatabaseProvider databaseProvider)
95+
public CreatureTextDumper(IChatEmoteSoundProcessor chatEmoteSoundProcessor,
96+
IDatabaseProvider databaseProvider,
97+
bool asDiff)
2498
{
2599
this.chatEmoteSoundProcessor = chatEmoteSoundProcessor;
26100
this.databaseProvider = databaseProvider;
101+
this.asDiff = asDiff;
27102
}
28103

29104
private State GetState(UniversalGuid guid)
@@ -44,20 +119,48 @@ protected override bool Process(PacketBase basePacket, PacketChat packet)
44119
var sound = chatEmoteSoundProcessor.GetSoundForChat(basePacket);
45120

46121
var state = GetState(packet.Sender);
47-
48-
if (state.texts.ContainsKey(packet.Text))
49-
return false;
50-
51-
state.texts[packet.Text] = (state.texts.Count, packet.Type, packet.Language, emote ?? 0, sound ?? 0);
52-
return true;
122+
123+
var entry = new TextEntry(packet.Text, (CreatureTextType)packet.Type, (uint)packet.Language, (uint)(emote ?? 0), sound ?? 0)
124+
{
125+
GroupId = (byte)state.texts.Count,
126+
Id = 0,
127+
};
128+
return state.texts.Add(entry);
53129
}
54130

55131
public async Task<string> Generate()
56132
{
57133
var trans = Queries.BeginTransaction();
58-
trans.Comment("Warning!! This SQL will override current texts");
134+
if (!asDiff)
135+
trans.Comment("Warning!! This SQL will override current texts");
59136
foreach (var entry in perEntryState)
60137
{
138+
int maxId = -1;
139+
if (asDiff)
140+
{
141+
var existing = await databaseProvider.GetCreatureTextsByEntry(entry.Key);
142+
foreach (var text in existing)
143+
{
144+
if (text.Text == null)
145+
continue;
146+
var databaseEntry = new TextEntry(text);
147+
if (entry.Value.texts.TryGetValue(databaseEntry, out var sniffEntry))
148+
{
149+
entry.Value.texts.Remove(sniffEntry);
150+
databaseEntry.IsInSniffText = true;
151+
}
152+
entry.Value.texts.Add(databaseEntry);
153+
maxId = Math.Max(maxId, text.GroupId);
154+
}
155+
}
156+
157+
foreach (var sniffText in entry.Value.texts.Where(t => t.IsInSniffText && !t.IsInDatabaseText))
158+
{
159+
sniffText.BroadcastTextId =
160+
(await databaseProvider.GetBroadcastTextByTextAsync(sniffText.Text))?.Id ?? 0;
161+
sniffText.GroupId = (byte)(++maxId);
162+
}
163+
61164
var template = databaseProvider.GetCreatureTemplate(entry.Key);
62165
if (template != null)
63166
trans.Comment(template.Name);
@@ -66,18 +169,24 @@ public async Task<string> Generate()
66169
.Delete();
67170
trans.Table("creature_text")
68171
.BulkInsert(entry.Value.texts
172+
.OrderBy(t => t.GroupId)
173+
.ThenBy(t => t.Id)
69174
.Select(text => new
70175
{
71176
CreatureID = entry.Key,
72-
GroupID = text.Value.groupdId,
73-
ID = 0,
74-
Text = text.Key,
75-
Type = text.Value.type,
76-
Language = text.Value.language,
77-
Probability = 100,
78-
Emote = text.Value.emote,
79-
Sound = text.Value.sound,
80-
BroadcastTextId = databaseProvider.GetBroadcastTextByText(text.Key)?.Id ?? 0
177+
GroupID = text.GroupId,
178+
ID = text.Id,
179+
Text = text.Text,
180+
Type = (uint)text.Type,
181+
Language = text.Language,
182+
Probability = text.Probability,
183+
Duration = text.Duration,
184+
TextRange = (uint)text.Range,
185+
Emote = text.Emote,
186+
Sound = text.Sound,
187+
BroadcastTextId = text.BroadcastTextId,
188+
comment = text.Comment ?? template?.Name ?? "",
189+
__comment = !text.IsInSniffText ? "not in sniff" : null
81190
}));
82191
trans.BlankLine();
83192
}

WDE.PacketViewer/Processing/Processors/Utils/ChatEmoteSoundProcessor.cs

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.Linq;
34
using WDE.Module.Attributes;
45
using WowPacketParser.Proto;
56
using WowPacketParser.Proto.Processing;
@@ -93,19 +94,49 @@ protected override bool Process(PacketBase basePacket, PacketChat packet)
9394

9495
protected override bool Process(PacketBase basePacket, PacketPlayObjectSound packet)
9596
{
96-
Get(packet.Source).LastSound = (basePacket, packet.Sound);
97+
var state = Get(packet.Source);
98+
if (state.LastChat.HasValue &&
99+
!chatPacketIdToSound.ContainsKey(state.LastChat.Value.packet.Number) &&
100+
HasJustHappened(state.LastChat?.packet, basePacket))
101+
{
102+
var chatId = state.LastChat!.Value.packet.Number;
103+
chatPacketIdToSound[chatId] = packet.Sound;
104+
soundPacketIdToChatPacketId[basePacket.Number] = chatId;
105+
}
106+
else
107+
Get(packet.Source).LastSound = (basePacket, packet.Sound);
97108
return true;
98109
}
99110

100111
protected override bool Process(PacketBase basePacket, PacketPlaySound packet)
101112
{
102-
Get(packet.Source).LastSound = (basePacket, packet.Sound);
113+
var state = Get(packet.Source);
114+
if (state.LastChat.HasValue &&
115+
!chatPacketIdToSound.ContainsKey(state.LastChat.Value.packet.Number) &&
116+
HasJustHappened(state.LastChat?.packet, basePacket))
117+
{
118+
var chatId = state.LastChat!.Value.packet.Number;
119+
chatPacketIdToSound[chatId] = packet.Sound;
120+
soundPacketIdToChatPacketId[basePacket.Number] = chatId;
121+
}
122+
else
123+
Get(packet.Source).LastSound = (basePacket, packet.Sound);
103124
return true;
104125
}
105126

106127
protected override bool Process(PacketBase basePacket, PacketEmote packet)
107128
{
108-
Get(packet.Sender).LastEmote = (basePacket, packet.Emote);
129+
var state = Get(packet.Sender);
130+
if (state.LastChat.HasValue &&
131+
!chatPacketIdToEmote.ContainsKey(state.LastChat.Value.packet.Number) &&
132+
HasJustHappened(state.LastChat?.packet, basePacket))
133+
{
134+
var chatId = state.LastChat!.Value.packet.Number;
135+
chatPacketIdToEmote[chatId] = packet.Emote;
136+
emotePacketIdToChatPacketId[basePacket.Number] = chatId;
137+
}
138+
else
139+
state.LastEmote = (basePacket, packet.Emote);
109140
return true;
110141
}
111142

WoWDatabaseEditor/Icons/chat_diff.png

865 Bytes
Loading
1.25 KB
Loading
1.25 KB
Loading
1.98 KB
Loading

0 commit comments

Comments
 (0)