Skip to content

Commit

Permalink
[Packet viewer] Added creature text as a database diff processor
Browse files Browse the repository at this point in the history
  • Loading branch information
BAndysc committed Sep 28, 2021
1 parent 6d58dc4 commit 3169473
Show file tree
Hide file tree
Showing 8 changed files with 239 additions and 25 deletions.
56 changes: 56 additions & 0 deletions WDE.Common.Avalonia/Controls/BetterKeyBinding.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
using System;
using System.Windows.Input;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Input;

namespace WDE.Common.Avalonia.Controls
{
/***
* This is KeyBinding that forwards the gesture to the focused TextBox first
*/
public class BetterKeyBinding : KeyBinding, ICommand
{
public static readonly StyledProperty<ICommand> CustomCommandProperty = AvaloniaProperty.Register<KeyBinding, ICommand>(nameof (CustomCommand));

public ICommand CustomCommand
{
get => GetValue(CustomCommandProperty);
set => SetValue(CustomCommandProperty, value);
}

public BetterKeyBinding()
{
Command = this;
}

public bool CanExecute(object? parameter)
{
return CustomCommand.CanExecute(parameter);
}

public void Execute(object? parameter)
{
if (FocusManager.Instance.Current is TextBox tb)
{
var ev = new KeyEventArgs()
{
Key = Gesture.Key,
KeyModifiers = Gesture.KeyModifiers,
RoutedEvent = InputElement.KeyDownEvent
};
tb.RaiseEvent(ev);
if (!ev.Handled)
CustomCommand.Execute(parameter);
}
else
CustomCommand.Execute(parameter);
}

public event EventHandler? CanExecuteChanged
{
add => CustomCommand.CanExecuteChanged += value;
remove => CustomCommand.CanExecuteChanged -= value;
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Threading.Tasks;
using Prism.Ioc;
using WDE.Common.Types;
using WDE.Module.Attributes;
using WDE.PacketViewer.Processing.Processors;
Expand All @@ -9,17 +10,34 @@ namespace WDE.PacketViewer.Processing.ProcessorProviders
[AutoRegister]
public class CreatureTextDumperProvider : IPacketDumperProvider
{
private readonly Func<CreatureTextDumper> creator;
private readonly IContainerProvider containerProvider;

public CreatureTextDumperProvider(Func<CreatureTextDumper> creator)
public CreatureTextDumperProvider(IContainerProvider containerProvider)
{
this.creator = creator;
this.containerProvider = containerProvider;
}
public string Name => "Creature text";
public string Description => "Generate all creature texts with emotes and sounds";
public string Extension => "sql";
public ImageUri? Image { get; } = new ImageUri("icons/chat_big.png");
public Task<IPacketTextDumper> CreateDumper() =>
Task.FromResult<IPacketTextDumper>(creator());
Task.FromResult<IPacketTextDumper>(containerProvider.Resolve<CreatureTextDumper>((typeof(bool), false)));
}

[AutoRegister]
public class CreatureTextDiffDumperProvider : IPacketDumperProvider
{
private readonly IContainerProvider containerProvider;

public CreatureTextDiffDumperProvider(IContainerProvider containerProvider)
{
this.containerProvider = containerProvider;
}
public string Name => "Creature text (diff)";
public string Description => "Generate all creature texts with emotes and sounds, as a diff with current texts in the database";
public string Extension => "sql";
public ImageUri? Image { get; } = new ImageUri("icons/chat_diff_big.png");
public Task<IPacketTextDumper> CreateDumper() =>
Task.FromResult<IPacketTextDumper>(containerProvider.Resolve<CreatureTextDumper>((typeof(bool), true)));
}
}
145 changes: 127 additions & 18 deletions WDE.PacketViewer/Processing/Processors/CreatureTextDumper.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
Expand All @@ -10,20 +11,94 @@ namespace WDE.PacketViewer.Processing.Processors
{
public class CreatureTextDumper : PacketProcessor<bool>, ITwoStepPacketBoolProcessor, IPacketTextDumper
{
private class TextEntry : IEquatable<TextEntry>
{
public byte GroupId;
public byte Id;
public float Probability;
public CreatureTextRange Range;
public uint Duration;
public readonly CreatureTextType Type;
public readonly uint Language;
public readonly uint Emote;
public readonly uint Sound;
public readonly string Text;
public bool IsInSniffText { get; set; }
public bool IsInDatabaseText { get; set; }
public uint BroadcastTextId { get; set; }

public string? Comment;

public TextEntry(string text, CreatureTextType type, uint language, uint emote, uint sound)
{
Text = text;
Type = type;
Language = language;
Emote = emote;
Sound = sound;
Probability = 100;
Range = CreatureTextRange.Normal;
IsInSniffText = true;
IsInDatabaseText = false;
}

public TextEntry(ICreatureText text)
{
IsInSniffText = false;
IsInDatabaseText = true;
Text = text.Text ?? "";
Type = text.Type;
Language = text.Language;
Emote = text.Emote;
Sound = text.Sound;
GroupId = text.GroupId;
Probability = text.Probability;
Duration = text.Duration;
Range = text.TextRange;
Id = text.Id;
BroadcastTextId = text.BroadcastTextId;
Comment = text.Comment;
}

public bool Equals(TextEntry? other)
{
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
return Type == other.Type && Language == other.Language && Emote == other.Emote && Sound == other.Sound && Text == other.Text;
}

public override bool Equals(object? obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
return Equals((TextEntry)obj);
}

public override int GetHashCode()
{
return HashCode.Combine((int)Type, Language, Emote, Sound, Text);
}
}

private class State
{
public Dictionary<string, (int groupdId, int type, int language, int emote, uint sound)> texts = new();
public HashSet<TextEntry> texts = new();
}

private readonly IChatEmoteSoundProcessor chatEmoteSoundProcessor;
private readonly IDatabaseProvider databaseProvider;
private readonly bool asDiff;

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

public CreatureTextDumper(IChatEmoteSoundProcessor chatEmoteSoundProcessor, IDatabaseProvider databaseProvider)
public CreatureTextDumper(IChatEmoteSoundProcessor chatEmoteSoundProcessor,
IDatabaseProvider databaseProvider,
bool asDiff)
{
this.chatEmoteSoundProcessor = chatEmoteSoundProcessor;
this.databaseProvider = databaseProvider;
this.asDiff = asDiff;
}

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

var state = GetState(packet.Sender);

if (state.texts.ContainsKey(packet.Text))
return false;

state.texts[packet.Text] = (state.texts.Count, packet.Type, packet.Language, emote ?? 0, sound ?? 0);
return true;

var entry = new TextEntry(packet.Text, (CreatureTextType)packet.Type, (uint)packet.Language, (uint)(emote ?? 0), sound ?? 0)
{
GroupId = (byte)state.texts.Count,
Id = 0,
};
return state.texts.Add(entry);
}

public async Task<string> Generate()
{
var trans = Queries.BeginTransaction();
trans.Comment("Warning!! This SQL will override current texts");
if (!asDiff)
trans.Comment("Warning!! This SQL will override current texts");
foreach (var entry in perEntryState)
{
int maxId = -1;
if (asDiff)
{
var existing = await databaseProvider.GetCreatureTextsByEntry(entry.Key);
foreach (var text in existing)
{
if (text.Text == null)
continue;
var databaseEntry = new TextEntry(text);
if (entry.Value.texts.TryGetValue(databaseEntry, out var sniffEntry))
{
entry.Value.texts.Remove(sniffEntry);
databaseEntry.IsInSniffText = true;
}
entry.Value.texts.Add(databaseEntry);
maxId = Math.Max(maxId, text.GroupId);
}
}

foreach (var sniffText in entry.Value.texts.Where(t => t.IsInSniffText && !t.IsInDatabaseText))
{
sniffText.BroadcastTextId =
(await databaseProvider.GetBroadcastTextByTextAsync(sniffText.Text))?.Id ?? 0;
sniffText.GroupId = (byte)(++maxId);
}

var template = databaseProvider.GetCreatureTemplate(entry.Key);
if (template != null)
trans.Comment(template.Name);
Expand All @@ -66,18 +169,24 @@ public async Task<string> Generate()
.Delete();
trans.Table("creature_text")
.BulkInsert(entry.Value.texts
.OrderBy(t => t.GroupId)
.ThenBy(t => t.Id)
.Select(text => new
{
CreatureID = entry.Key,
GroupID = text.Value.groupdId,
ID = 0,
Text = text.Key,
Type = text.Value.type,
Language = text.Value.language,
Probability = 100,
Emote = text.Value.emote,
Sound = text.Value.sound,
BroadcastTextId = databaseProvider.GetBroadcastTextByText(text.Key)?.Id ?? 0
GroupID = text.GroupId,
ID = text.Id,
Text = text.Text,
Type = (uint)text.Type,
Language = text.Language,
Probability = text.Probability,
Duration = text.Duration,
TextRange = (uint)text.Range,
Emote = text.Emote,
Sound = text.Sound,
BroadcastTextId = text.BroadcastTextId,
comment = text.Comment ?? template?.Name ?? "",
__comment = !text.IsInSniffText ? "not in sniff" : null
}));
trans.BlankLine();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using WDE.Module.Attributes;
using WowPacketParser.Proto;
using WowPacketParser.Proto.Processing;
Expand Down Expand Up @@ -93,19 +94,49 @@ protected override bool Process(PacketBase basePacket, PacketChat packet)

protected override bool Process(PacketBase basePacket, PacketPlayObjectSound packet)
{
Get(packet.Source).LastSound = (basePacket, packet.Sound);
var state = Get(packet.Source);
if (state.LastChat.HasValue &&
!chatPacketIdToSound.ContainsKey(state.LastChat.Value.packet.Number) &&
HasJustHappened(state.LastChat?.packet, basePacket))
{
var chatId = state.LastChat!.Value.packet.Number;
chatPacketIdToSound[chatId] = packet.Sound;
soundPacketIdToChatPacketId[basePacket.Number] = chatId;
}
else
Get(packet.Source).LastSound = (basePacket, packet.Sound);
return true;
}

protected override bool Process(PacketBase basePacket, PacketPlaySound packet)
{
Get(packet.Source).LastSound = (basePacket, packet.Sound);
var state = Get(packet.Source);
if (state.LastChat.HasValue &&
!chatPacketIdToSound.ContainsKey(state.LastChat.Value.packet.Number) &&
HasJustHappened(state.LastChat?.packet, basePacket))
{
var chatId = state.LastChat!.Value.packet.Number;
chatPacketIdToSound[chatId] = packet.Sound;
soundPacketIdToChatPacketId[basePacket.Number] = chatId;
}
else
Get(packet.Source).LastSound = (basePacket, packet.Sound);
return true;
}

protected override bool Process(PacketBase basePacket, PacketEmote packet)
{
Get(packet.Sender).LastEmote = (basePacket, packet.Emote);
var state = Get(packet.Sender);
if (state.LastChat.HasValue &&
!chatPacketIdToEmote.ContainsKey(state.LastChat.Value.packet.Number) &&
HasJustHappened(state.LastChat?.packet, basePacket))
{
var chatId = state.LastChat!.Value.packet.Number;
chatPacketIdToEmote[chatId] = packet.Emote;
emotePacketIdToChatPacketId[basePacket.Number] = chatId;
}
else
state.LastEmote = (basePacket, packet.Emote);
return true;
}

Expand Down
Binary file added WoWDatabaseEditor/Icons/chat_diff.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added WoWDatabaseEditor/Icons/[email protected]
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added WoWDatabaseEditor/Icons/chat_diff_big.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added WoWDatabaseEditor/Icons/[email protected]
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 3169473

Please sign in to comment.