From 877e423ad3235a9bdfcb3883c15d980829df5b7a Mon Sep 17 00:00:00 2001 From: CarnifexOptimus <156172553+CarnifexOptimus@users.noreply.github.com> Date: Sat, 15 Feb 2025 13:46:43 +0100 Subject: [PATCH] sqlite database no longer embedded but in plugin directory --- BossMod/BossModReborn.csproj | 5 +- .../DeepDungeon => }/DDTrapsData.sqlite3 | Bin BossMod/Framework/Plugin.cs | 2 + .../Modules/Global/DeepDungeon/AutoClear.cs | 124 +++++++++--------- BossMod/Modules/Global/DeepDungeon/Config.cs | 2 +- 5 files changed, 68 insertions(+), 65 deletions(-) rename BossMod/{Modules/Global/DeepDungeon => }/DDTrapsData.sqlite3 (100%) diff --git a/BossMod/BossModReborn.csproj b/BossMod/BossModReborn.csproj index 2262b938b..2f892e1b3 100644 --- a/BossMod/BossModReborn.csproj +++ b/BossMod/BossModReborn.csproj @@ -55,6 +55,7 @@ + @@ -105,7 +106,6 @@ PreserveNewest - @@ -119,5 +119,8 @@ PreserveNewest + + PreserveNewest + diff --git a/BossMod/Modules/Global/DeepDungeon/DDTrapsData.sqlite3 b/BossMod/DDTrapsData.sqlite3 similarity index 100% rename from BossMod/Modules/Global/DeepDungeon/DDTrapsData.sqlite3 rename to BossMod/DDTrapsData.sqlite3 diff --git a/BossMod/Framework/Plugin.cs b/BossMod/Framework/Plugin.cs index fe908d624..5ca8cf9be 100644 --- a/BossMod/Framework/Plugin.cs +++ b/BossMod/Framework/Plugin.cs @@ -108,6 +108,8 @@ public unsafe Plugin(IDalamudPluginInterface dalamud, ICommandManager commandMan dalamud.UiBuilder.Draw += DrawUI; dalamud.UiBuilder.OpenMainUi += () => OpenConfigUI(); dalamud.UiBuilder.OpenConfigUi += () => OpenConfigUI(); + + Global.DeepDungeon.DDTrapsData.Initialize(dalamud); } public void Dispose() diff --git a/BossMod/Modules/Global/DeepDungeon/AutoClear.cs b/BossMod/Modules/Global/DeepDungeon/AutoClear.cs index 9c8af37a5..60d1f4c6c 100644 --- a/BossMod/Modules/Global/DeepDungeon/AutoClear.cs +++ b/BossMod/Modules/Global/DeepDungeon/AutoClear.cs @@ -142,7 +142,6 @@ protected override void Dispose(bool disposing) _subscriptions.Dispose(); _obstacles.Dispose(); base.Dispose(disposing); - DDTrapsData.CleanupTemporaryDatabase(); } protected virtual void OnCastStarted(Actor actor) { } @@ -393,8 +392,13 @@ public override void CalculateAIHints(int playerSlot, Actor player, AIHints hint if (!Config.Enable || Palace.IsBossFloor || BetweenFloors) return; - foreach (var (w, rot) in Walls) - hints.AddForbiddenZone(ShapeDistance.Rect(w.Position, (rot ? 90f : 0f).Degrees(), w.Depth, w.Depth, 20)); + var countWalls = Walls.Count; + for (var i = 0; i < countWalls; ++i) + { + var wall = Walls[i]; + var w = wall.Wall; + hints.AddForbiddenZone(ShapeDistance.Rect(w.Position, (wall.Rotated ? 90f : 0f).Degrees(), w.Depth, w.Depth, 20f)); + } HandleFloorPathfind(player, hints); DrawAOEs(playerSlot, player, hints); @@ -461,17 +465,19 @@ public override void CalculateAIHints(int playerSlot, Actor player, AIHints hint if (Config.TrapHints && _trapsHidden) { - var count = _trapsCurrentZone.Count; - var traps = new List>(count); + var countTraps = _trapsCurrentZone.Count; + var traps = new List>(countTraps); - foreach (var trap in _trapsCurrentZone) + for (var i = 0; i < countTraps; ++i) { + var trap = _trapsCurrentZone[i]; if (trap.InCircle(player.Position, 30f)) { var shouldIgnore = false; - foreach (var b in IgnoreTraps) + var countIgnoreTraps = IgnoreTraps.Count; + for (var j = 0; i < countIgnoreTraps; ++j) { - if (b.AlmostEqual(trap, 1f)) + if (IgnoreTraps[i].AlmostEqual(trap, 1f)) { shouldIgnore = true; break; @@ -562,8 +568,10 @@ void pickBetterTarget(Actor t) bestTarget = t; } - foreach (var pp in hints.PotentialTargets) + var counttargets = hints.PotentialTargets.Count; + for (var i = 0; i < counttargets; ++i) { + var pp = hints.PotentialTargets[i]; // enemy is petrified, any damage will kill if (pp.Actor.FindStatus((uint)SID.StoneCurse)?.ExpireAt > World.FutureTime(1.5d)) pickBetterTarget(pp.Actor); @@ -573,10 +581,26 @@ void pickBetterTarget(Actor t) pickBetterTarget(pp.Actor); // if player does not have a target, prioritize everything so that AI picks one - skip dangerous enemies - else if (shouldTargetMobs && !pp.Actor.Statuses.Any(s => IsDangerousOutOfCombatStatus(s.ID))) - pickBetterTarget(pp.Actor); - } + else if (shouldTargetMobs) + { + var hasDangerousStatus = false; + var len = pp.Actor.Statuses.Length; + ref var statuses = ref pp.Actor.Statuses; + for (var j = 0; j < len; ++j) + { + if (IsDangerousOutOfCombatStatus(statuses[j].ID)) + { + hasDangerousStatus = true; + break; + } + } + if (!hasDangerousStatus) + { + pickBetterTarget(pp.Actor); + } + } + } hints.ForcedTarget = bestTarget; } @@ -831,72 +855,46 @@ private static bool IsBlocked(Bitmap map, Vector2 point, Vector2 origin, float m return false; } - private Stream GetEmbeddedResource(string name) => Assembly.GetExecutingAssembly().GetManifestResourceStream($"BossModReborn.Modules.Global.DeepDungeon.{name}") ?? throw new InvalidDataException($"Missing embedded resource {name}"); + private Stream GetEmbeddedResource(string name) => Assembly.GetExecutingAssembly().GetManifestResourceStream($"BossModReborn.Modules.Global.DeepDungeon.{name}")!; } -static class DDTrapsData +public static class DDTrapsData { - private const string EmbeddedDbResourceName = "BossModReborn.Modules.Global.DeepDungeon.DDTrapsData.sqlite3"; - private static string? _tempDbFilePath; + private static string? _path; - private static string GetTempDbFilePath() + public static void Initialize(Dalamud.Plugin.IDalamudPluginInterface dalamud) { - if (_tempDbFilePath != null) - { - return _tempDbFilePath; - } - - var tempFileName = Path.GetTempFileName() + ".sqlite3"; - _tempDbFilePath = tempFileName; - - using (var resourceStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(EmbeddedDbResourceName)) - { - if (resourceStream == null) - { - throw new FileNotFoundException($"Embedded resource '{EmbeddedDbResourceName}' not found."); - } - - using var fileStream = new FileStream(tempFileName, FileMode.Create, FileAccess.Write); - resourceStream.CopyTo(fileStream); - } - return tempFileName; + _path = Path.Combine(dalamud.AssemblyLocation.DirectoryName!, "DDTrapsData.sqlite3"); } - + // TODO: find a better solution, performance does not seem that good and creates a copy of SQLite.Interop.dll in temp folder for some reason which does not automatically get cleaned up public static List GetTrapLocationsForZone(uint zone) { List locations = []; - var tempDbPath = GetTempDbFilePath(); - using (var connection = new SQLiteConnection($"Data Source={tempDbPath};Version=3;Read Only=True;")) + try { - connection.Open(); + using (var connection = new SQLiteConnection($"Data Source={_path}")) + { + connection.Open(); - var command = connection.CreateCommand(); - command.CommandText = @"select X,Z from Locations where Type = 1 and TerritoryType = $tt"; - command.Parameters.AddWithValue("$tt", zone); + var command = connection.CreateCommand(); + command.CommandText = @"select X,Z from Locations where Type = 1 and TerritoryType = $tt"; + command.Parameters.AddWithValue("$tt", zone); - using var reader = command.ExecuteReader(); - while (reader.Read()) - { - var x = reader.GetFloat(0); - var z = reader.GetFloat(1); - locations.Add(new(x, z)); + using var reader = command.ExecuteReader(); + while (reader.Read()) + { + var x = reader.GetFloat(0); + var z = reader.GetFloat(1); + locations.Add(new(x, z)); + } } - } - return locations; - } - public static void CleanupTemporaryDatabase() - { - if (_tempDbFilePath != null) + return locations; + } + catch (SQLiteException e) { - var baseTempPath = Path.GetFileNameWithoutExtension(_tempDbFilePath); - var tempDirPath = Path.GetDirectoryName(_tempDbFilePath) ?? ""; - - string[] extensions = [".sqlite3", ".sqlite3-shm", ".sqlite3-wal", ""]; - - for (var i = 0; i < 4; ++i) - File.Delete(Path.Combine(tempDirPath, baseTempPath + extensions[i])); + Service.Log($"unable to load traps for zone ${zone}: ${e}"); + return []; } - _tempDbFilePath = null; } } diff --git a/BossMod/Modules/Global/DeepDungeon/Config.cs b/BossMod/Modules/Global/DeepDungeon/Config.cs index 75993cf94..6f23bc124 100644 --- a/BossMod/Modules/Global/DeepDungeon/Config.cs +++ b/BossMod/Modules/Global/DeepDungeon/Config.cs @@ -19,7 +19,7 @@ public enum ClearBehavior public bool Enable = true; [PropertyDisplay("Enable minimap")] public bool EnableMinimap = true; - [PropertyDisplay("Try to avoid traps", tooltip: "Avoid known trap locations sourced from PalacePal data. Does not need PalacePal installed since data is embedded into BMR. (Traps revealed by a Pomander of Sight will always be avoided regardless of this setting.)")] + [PropertyDisplay("Try to avoid traps", tooltip: "Avoid known trap locations sourced from PalacePal data. Does not need PalacePal installed since data is included in BMR. (Traps revealed by a Pomander of Sight will always be avoided regardless of this setting.)")] public bool TrapHints = true; [PropertyDisplay("Automatically navigate to Cairn of Passage")] public bool AutoPassage = true;