Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement SaveExistingSpawns and lookup of existing spawns #809

Merged
merged 5 commits into from
Dec 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions WowPacketParser/App.config
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,13 @@
-->
<add key="SaveTempSpawns" value="false"/>

<!--
Option: SaveExistingSpawns
Description: Spawn spawns which are already existing in db (compared by entry, position) or comment them in sql
Default: "false" (comment existing spawns in sql)
-->
<add key="SaveExistingSpawns" value="false"/>

<!--
Option: SkipOnlyVerifiedBuildUpdateRows
Description: Ship only VerifiedBuild row in update querys
Expand Down
1 change: 1 addition & 0 deletions WowPacketParser/Misc/Settings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ public static class Settings
public static readonly ulong SQLOutputFlag = GetSQLOutputFlag();
public static readonly bool SQLOrderByKey = Conf.GetBoolean("SqlOrderByKey", false);
public static readonly bool SaveTempSpawns = Conf.GetBoolean("SaveTempSpawns", false);
public static readonly bool SaveExistingSpawns = Conf.GetBoolean("SaveExistingSpawns", false);
public static readonly bool SkipOnlyVerifiedBuildUpdateRows = Conf.GetBoolean("SkipOnlyVerifiedBuildUpdateRows", false);
public static readonly bool SkipRowsWithFallbackValues = Conf.GetBoolean("SkipRowsWithFallbackValues", true);
public static readonly bool IgnoreZeroValues = Conf.GetBoolean("IgnoreZeroValues", false);
Expand Down
4 changes: 2 additions & 2 deletions WowPacketParser/SQL/Builder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -175,9 +175,9 @@ private static List<TargetedDatabase> GetExpectedTargetDatabasesForExpansion(Cli
case ClientType.Legion:
return new List<TargetedDatabase> { TargetedDatabase.Legion };
case ClientType.BattleForAzeroth: // == ClientType.Classic
return new List<TargetedDatabase> { TargetedDatabase.BattleForAzeroth, TargetedDatabase.Classic };
return new List<TargetedDatabase> { TargetedDatabase.BattleForAzeroth, TargetedDatabase.Classic, TargetedDatabase.TheBurningCrusade };
case ClientType.Shadowlands: // == ClientType.BurningCrusadeClassic
return new List<TargetedDatabase> { TargetedDatabase.Shadowlands, TargetedDatabase.Classic, TargetedDatabase.WotlkClassic };
return new List<TargetedDatabase> { TargetedDatabase.Shadowlands, TargetedDatabase.Classic, TargetedDatabase.WotlkClassic, TargetedDatabase.TheBurningCrusade };
case ClientType.Dragonflight:
return new List<TargetedDatabase> { TargetedDatabase.Dragonflight, TargetedDatabase.WotlkClassic };
default:
Expand Down
71 changes: 69 additions & 2 deletions WowPacketParser/SQL/Builders/Spawns.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ namespace WowPacketParser.SQL.Builders
[BuilderClass]
public static class Spawns
{
public static bool FloatComparison(float x, float y, float precision)
{
return Math.Abs(x - y) < precision;
}

private static bool GetTransportMap(WoWObject @object, out int mapId)
{
mapId = -1;
Expand All @@ -30,7 +35,7 @@ private static bool GetTransportMap(WoWObject @object, out int mapId)
if (transport.Type != ObjectType.GameObject)
return false;

if (SQLConnector.Enabled)
if (SQLConnector.Enabled && Settings.TargetedDatabase != TargetedDatabase.TheBurningCrusade)
{
var transportTemplates = SQLDatabase.Get(new RowList<GameObjectTemplate> { new GameObjectTemplate { Entry = (uint)transport.ObjectData.EntryID } });
if (transportTemplates.Count == 0)
Expand Down Expand Up @@ -63,6 +68,25 @@ public static string Creature(Dictionary<WowGuid, Unit> units)
? units.Values.GroupBy(u => u, new SpawnComparer()).Select(x => x.First())
: units.Values.ToList();


if (!Settings.SaveExistingSpawns && SQLConnector.Enabled)
{
var spawnsDb = SQLDatabase.GetCreatures(new RowList<CreatureDB>());
var precision = 0.02f; // warning - some zones shifted by 0.2 in some cases between later expansions
foreach (var creature in unitList)
{
var existingCreature = spawnsDb.Where(p => p.Data.ID == (uint)creature.ObjectData.EntryID
&& p.Data.Map == creature.Map
&& FloatComparison((float)p.Data.PosX, creature.Movement.Position.X, precision)
&& FloatComparison((float)p.Data.PosY, creature.Movement.Position.Y, precision)
&& FloatComparison((float)p.Data.PosZ, creature.Movement.Position.Z, precision)
&& FloatComparison((float)p.Data.Orientation, creature.Movement.Orientation, precision)).FirstOrDefault();

if (existingCreature != null)
creature.ExistingDatabaseSpawn = true;
}
}

foreach (var creature in unitList)
{
Row<Creature> row = new Row<Creature>();
Expand Down Expand Up @@ -255,6 +279,16 @@ public static string Creature(Dictionary<WowGuid, Unit> units)
addonRow.Comment += " - !!! might be temporary spawn !!!";
}
}
else if (creature.IsExistingSpawn() && !Settings.SaveExistingSpawns)
{
row.CommentOut = true;
row.Comment += " - !!! already present in database !!!";
if (Settings.SQLOutputFlag.HasAnyFlagBit(SQLOutput.creature_addon))
{
addonRow.CommentOut = true;
addonRow.Comment += " - !!! already present in database !!!";
}
}
else if (creature.IsOnTransport() && badTransport)
{
row.CommentOut = true;
Expand Down Expand Up @@ -314,6 +348,29 @@ public static string GameObject(Dictionary<WowGuid, GameObject> gameObjects)
? gameObjects.Values.GroupBy(g => g, new SpawnComparer()).Select(x => x.First())
: gameObjects.Values.ToList();

if (!Settings.SaveExistingSpawns && SQLConnector.Enabled)
{
var spawnsDb = SQLDatabase.GetGameObjects(new RowList<GameObjectDB>());
var precision = 0.02f; // warning - some zones shifted by 0.2 in some cases between later expansions
foreach (var go in gobList)
{
var staticRot = go.GetStaticRotation();
var existingGo = spawnsDb.Where(p => p.Data.ID == (uint)go.ObjectData.EntryID
&& p.Data.Map == go.Map
&& FloatComparison((float)p.Data.PosX, go.Movement.Position.X, precision)
&& FloatComparison((float)p.Data.PosY, go.Movement.Position.Y, precision)
&& FloatComparison((float)p.Data.PosZ, go.Movement.Position.Z, precision)
&& FloatComparison((float)p.Data.Orientation, go.Movement.Orientation, precision)
&& FloatComparison((float)p.Data.Rot0, staticRot.X, precision)
&& FloatComparison((float)p.Data.Rot1, staticRot.Y, precision)
&& (FloatComparison((float)p.Data.Rot2, staticRot.Z, precision) || FloatComparison((float)p.Data.Rot2, -staticRot.Z, precision))
&& (FloatComparison((float)p.Data.Rot3, staticRot.W, precision) || FloatComparison((float)p.Data.Rot3, -staticRot.W, precision))).FirstOrDefault();

if (existingGo != null)
go.ExistingDatabaseSpawn = true;
}
}

foreach (var go in gobList)
{
Row<GameObjectModel> row = new Row<GameObjectModel>();
Expand Down Expand Up @@ -456,6 +513,16 @@ public static string GameObject(Dictionary<WowGuid, GameObject> gameObjects)
addonRow.Comment += " - !!! might be temporary spawn !!!";
}
}
else if (go.IsExistingSpawn() && !Settings.SaveExistingSpawns)
{
row.CommentOut = true;
row.Comment += " - !!! already present in database !!!";
if (Settings.SQLOutputFlag.HasAnyFlagBit(SQLOutput.gameobject_addon))
{
addonRow.CommentOut = true;
addonRow.Comment += " - !!! already present in database !!!";
}
}
else if (go.IsTransport())
{
row.CommentOut = true;
Expand All @@ -482,7 +549,7 @@ public static string GameObject(Dictionary<WowGuid, GameObject> gameObjects)
}

if (count == 0)
return String.Empty;
return string.Empty;

StringBuilder result = new StringBuilder();
// delete query for GUIDs
Expand Down
12 changes: 10 additions & 2 deletions WowPacketParser/SQL/QueryBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -238,8 +238,16 @@ public string Build()

foreach (var field in fields)
{
fieldNames.Append(field.Item1);
fieldNames.Append(SQLUtil.CommaSeparator);
if (field.Item2.FieldType == typeof(decimal))
{
fieldNames.Append($"round({field.Item1}, 20)");
fieldNames.Append(SQLUtil.CommaSeparator);
}
else
{
fieldNames.Append(field.Item1);
fieldNames.Append(SQLUtil.CommaSeparator);
}
}
fieldNames.Remove(fieldNames.Length - 2, 2); // remove last ", "

Expand Down
115 changes: 112 additions & 3 deletions WowPacketParser/SQL/SQLDatabase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,9 @@ private static void LoadBroadcastText()
query = "SELECT ID, LanguageID, Text, Text1, EmoteID1, EmoteID2, EmoteID3, EmoteDelay1, EmoteDelay2, EmoteDelay3, SoundEntriesID, EmotesID, Flags " +
$"FROM {Settings.TDBDatabase}.broadcast_text;";

if (Settings.TargetedDatabase == TargetedDatabase.TheBurningCrusade)
return;

using (var command = SQLConnector.CreateCommand(query))
{
if (command == null)
Expand Down Expand Up @@ -203,6 +206,10 @@ private static void LoadPointsOfinterest()
string query =
"SELECT ID, PositionX, PositionY, Icon, Flags, Importance, Name " +
$"FROM {Settings.TDBDatabase}.points_of_interest ORDER BY ID;";

if (Settings.TargetedDatabase == TargetedDatabase.TheBurningCrusade)
query = $"SELECT entry AS ID, x AS PositionX, y AS PositionY, icon AS Icon, flags AS Flags, data AS Importance, icon_name AS Name FROM {Settings.TDBDatabase}.points_of_interest ORDER BY entry;";

using (var command = SQLConnector.CreateCommand(query))
{
if (command == null)
Expand Down Expand Up @@ -230,6 +237,9 @@ private static void LoadPointsOfinterest()

private static void LoadCreatureEquipment()
{
if (Settings.TargetedDatabase == TargetedDatabase.TheBurningCrusade)
return;

string columns = "CreatureID, ID, ItemID1, ItemID2, ItemID3, VerifiedBuild";
if (Settings.TargetedDatabase >= TargetedDatabase.Legion)
columns += ", AppearanceModID1, ItemVisual1, AppearanceModID2, ItemVisual2, AppearanceModID3, ItemVisual3";
Expand Down Expand Up @@ -277,6 +287,9 @@ private static void LoadCreatureEquipment()

private static void LoadNPCTexts()
{
if (Settings.TargetedDatabase == TargetedDatabase.TheBurningCrusade)
return;

string columns = "ID, BroadcastTextID0, BroadcastTextID1, BroadcastTextID2, BroadcastTextID3, BroadcastTextID4, BroadcastTextID5, BroadcastTextID6, BroadcastTextID7";
string query = $"SELECT {columns} FROM {Settings.TDBDatabase}.npc_text";

Expand Down Expand Up @@ -304,6 +317,9 @@ private static void LoadNPCTexts()

private static void LoadGossipMenuNPCTexts()
{
if (Settings.TargetedDatabase == TargetedDatabase.TheBurningCrusade)
return;

string columns = "MenuID, TextID";
string query = $"SELECT {columns} FROM {Settings.TDBDatabase}.gossip_menu";

Expand All @@ -328,12 +344,18 @@ private static void LoadGossipMenuNPCTexts()

private static void LoadWorldStates()
{
if (Settings.TargetedDatabase != TargetedDatabase.Cataclysm && (Settings.TargetedDatabase < TargetedDatabase.Shadowlands || Settings.TargetedDatabase >= TargetedDatabase.Classic))
if (Settings.TargetedDatabase != TargetedDatabase.Cataclysm && Settings.TargetedDatabase != TargetedDatabase.TheBurningCrusade && (Settings.TargetedDatabase < TargetedDatabase.Shadowlands || Settings.TargetedDatabase >= TargetedDatabase.Classic))
return;

string columns = "`ID`, `Comment`";
string query = $"SELECT {columns} FROM {Settings.TDBDatabase}.world_state";

if (Settings.TargetedDatabase == TargetedDatabase.TheBurningCrusade)
{
columns = "`Id`, `Name`";
query = $"SELECT {columns} FROM {Settings.TDBDatabase}.worldstate_name";
}

using (var command = SQLConnector.CreateCommand(query))
{
if (command == null)
Expand All @@ -353,6 +375,12 @@ private static void LoadWorldStates()

private static void LoadNameData()
{
string questQuery = $"SELECT `ID`, `LogTitle` FROM {Settings.TDBDatabase}.quest_template;";
if (Settings.TargetedDatabase == TargetedDatabase.TheBurningCrusade)
{
questQuery = $"SELECT `entry`, `Title` FROM {Settings.TDBDatabase}.quest_template;";
}

// Unit
NameStores.Add(StoreNameType.Unit, GetDict<int, string>(
$"SELECT `entry`, `name` FROM {Settings.TDBDatabase}.creature_template;"));
Expand All @@ -362,8 +390,7 @@ private static void LoadNameData()
$"SELECT `entry`, `name` FROM {Settings.TDBDatabase}.gameobject_template;"));

// Quest
NameStores.Add(StoreNameType.Quest, GetDict<int, string>(
$"SELECT `ID`, `LogTitle` FROM {Settings.TDBDatabase}.quest_template;"));
NameStores.Add(StoreNameType.Quest, GetDict<int, string>(questQuery));

// Item - Cataclysm and above have ItemSparse.db2
if (Settings.TargetedDatabase <= TargetedDatabase.WrathOfTheLichKing)
Expand Down Expand Up @@ -460,6 +487,88 @@ public static RowList<T> Get<T>(RowList<T> rowList = null, string database = nul
return result;
}

public static RowList<CreatureDB> GetCreatures(RowList<CreatureDB> rowList = null, string database = null)
{
if (!SQLConnector.Enabled)
return null;

if (!SQLUtil.IsTableVisible<CreatureDB>())
return null;

var result = new RowList<CreatureDB>();

using (var command = SQLConnector.CreateCommand(new SQLSelect<CreatureDB>(rowList, database).Build()))
{
if (command == null)
return null;

var fields = SQLUtil.GetFields<CreatureDB>();
var fieldsCount = fields.Select(f => f.Item3.First().Count).Sum();
using (MySqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
var creature = new CreatureDB();

creature.DbGuid = reader.GetUInt32(0);
creature.ID = reader.GetUInt32(1);
creature.Map = reader.GetUInt32(2);
creature.PosX = reader.GetDecimal(3);
creature.PosY = reader.GetDecimal(4);
creature.PosZ = reader.GetDecimal(5);
creature.Orientation = reader.GetDecimal(6);

result.Add(creature);
}
}
}

return result;
}

public static RowList<GameObjectDB> GetGameObjects(RowList<GameObjectDB> rowList = null, string database = null)
{
if (!SQLConnector.Enabled)
return null;

if (!SQLUtil.IsTableVisible<GameObjectDB>())
return null;

var result = new RowList<GameObjectDB>();

using (var command = SQLConnector.CreateCommand(new SQLSelect<GameObjectDB>(rowList, database).Build()))
{
if (command == null)
return null;

var fields = SQLUtil.GetFields<GameObjectDB>();
var fieldsCount = fields.Select(f => f.Item3.First().Count).Sum();
using (MySqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
var go = new GameObjectDB();

go.DbGuid = reader.GetUInt32(0);
go.ID = reader.GetUInt32(1);
go.Map = reader.GetUInt32(2);
go.PosX = reader.GetDecimal(3);
go.PosY = reader.GetDecimal(4);
go.PosZ = reader.GetDecimal(5);
go.Orientation = reader.GetDecimal(6);
go.Rot0 = reader.GetDecimal(7);
go.Rot1 = reader.GetDecimal(8);
go.Rot2 = reader.GetDecimal(9);
go.Rot3 = reader.GetDecimal(10);

result.Add(go);
}
}
}

return result;
}

public static uint GetNPCTextIDByMenuIDAndBroadcastText(int menuId, uint broadcastTextID)
{
if (!BroadcastToNPCTexts.TryGetValue(broadcastTextID, out var npcTextsByBroadcast))
Expand Down
23 changes: 23 additions & 0 deletions WowPacketParser/Store/Objects/CreatureDB.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using WowPacketParser.SQL;

namespace WowPacketParser.Store.Objects
{
[DBTableName("creature")]
public sealed record CreatureDB : IDataModel
{
[DBFieldName("guid", true)]
public uint DbGuid;
[DBFieldName("id")]
public uint ID;
[DBFieldName("map")]
public uint Map;
[DBFieldName("position_x")]
public decimal PosX;
[DBFieldName("position_y")]
public decimal PosY;
[DBFieldName("position_z")]
public decimal PosZ;
[DBFieldName("orientation")]
public decimal Orientation;
}
}
Loading