Skip to content
Open
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
15 changes: 10 additions & 5 deletions Visibility/Configuration/VisibilityConfiguration.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;

using Dalamud.Configuration;

using Lumina.Excel.Sheets;
using Lumina.Text.ReadOnly;

using Visibility.Handlers;
using Visibility.Utils;
using Visibility.Void;

namespace Visibility.Configuration;
Expand All @@ -29,6 +29,8 @@ public partial class VisibilityConfiguration: IPluginConfiguration

public List<VoidItem> Whitelist { get; } = [];

public List<VoidPattern> VoidPatterns { get; } = [];

[NonSerialized] public Dictionary<ulong, VoidItem> VoidDictionary = null!;
[NonSerialized] public Dictionary<ulong, VoidItem> WhitelistDictionary = null!;

Expand All @@ -49,7 +51,8 @@ public partial class VisibilityConfiguration: IPluginConfiguration
public void Init(ushort territoryType)
{
this.VoidDictionary = this.VoidList.Where(x => x.Id != 0).DistinctBy(x => x.Id).ToDictionary(x => x.Id, x => x);
this.WhitelistDictionary = this.Whitelist.Where(x => x.Id != 0).DistinctBy(x => x.Id).ToDictionary(x => x.Id, x => x);
this.WhitelistDictionary =
this.Whitelist.Where(x => x.Id != 0).DistinctBy(x => x.Id).ToDictionary(x => x.Id, x => x);
this.SettingsHandler = new SettingsHandler(this);

IEnumerable<(ushort, ReadOnlySeString)> valueTuples = Service.DataManager.GetExcelSheet<TerritoryType>()
Expand All @@ -68,7 +71,8 @@ public void Init(ushort territoryType)
}

// Allowed territory intended use IDs
private static readonly HashSet<uint> allowedTerritoryIntendedUses = [
private static readonly HashSet<uint> allowedTerritoryIntendedUses =
[
0, // Hub Cities
1, // Overworld
13, // Residential Area
Expand Down Expand Up @@ -140,6 +144,7 @@ private void HandleVersionChanges()
}

public void Save() => Service.PluginInterface.SavePluginConfig(this);
[System.Text.RegularExpressions.GeneratedRegex("<italic\\(\\d+\\)>")]
private static partial System.Text.RegularExpressions.Regex ItalicRegex();

[GeneratedRegex("<italic\\(\\d+\\)>")]
private static partial Regex ItalicRegex();
}
6 changes: 6 additions & 0 deletions Visibility/Localization.cs
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,12 @@ public string ContextMenuRemove(string name) =>
public string AdvancedOption => this.GetString("AdvancedOption", this.CurrentLanguage);
public string AdvancedOptionTooltip => this.GetString("AdvancedOptionTooltip", this.CurrentLanguage);
public string ResetToCurrentArea => this.GetString("ResetToCurrentArea", this.CurrentLanguage);

public string PatternListName => this.GetString("PatternListName", this.CurrentLanguage);
public string PatternName => this.GetString("PatternName", this.CurrentLanguage);
public string PatternDescription => this.GetString("PatternDescription", this.CurrentLanguage);
public string ActionAddPattern => this.GetString("ActionAddPattern", this.CurrentLanguage);
public string PatternOffworld => this.GetString("PatternOffworld", this.CurrentLanguage);

public SeString EntryAdded(string name, SeString entryName) =>
FormatSeString(this.GetString("EntryAdded", this.CurrentLanguage), name, entryName);
Expand Down
11 changes: 10 additions & 1 deletion Visibility/Utils/FrameworkHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
using System.Collections.Generic;

using Dalamud.Game.ClientState.Conditions;
using Dalamud.Game.ClientState.Objects.Enums;

using FFXIVClientStructs.FFXIV.Client.Game.Character;
using FFXIVClientStructs.FFXIV.Client.Game.Control;
Expand All @@ -14,6 +13,7 @@

using Visibility.Utils.EntityHandlers;

using BattleNpcSubKind = Dalamud.Game.ClientState.Objects.Enums.BattleNpcSubKind;
using ObjectKind = Dalamud.Game.ClientState.Objects.Enums.ObjectKind;

namespace Visibility.Utils;
Expand Down Expand Up @@ -287,6 +287,15 @@ public void ShowPlayer(uint id)
this.visibilityManager.MarkObjectToShow(id);
}

/// <summary>
/// Flushes the regex visibility cache and allows the visibility manager to recalculate all characters.
/// </summary>
public void ClearRegexCache()
{
this.voidListManager.ClearRegexCache();
this.visibilityManager.ClearAll();
}

/// <summary>
/// Dispose the framework handler and show all hidden entities
/// </summary>
Expand Down
22 changes: 14 additions & 8 deletions Visibility/Utils/ImGuiElements.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace Visibility.Utils;

public static class ImGuiElements
{
public static bool Checkbox(bool value, string name)
public static bool Checkbox(bool value, string name, Action<bool, bool, bool>? callback = null)
{
if (!ImGui.Checkbox($"###{name}", ref value))
{
Expand All @@ -19,24 +19,30 @@ public static bool Checkbox(bool value, string name)
Action<bool, bool, bool>? onValueChanged =
VisibilityPlugin.Instance.Configuration.SettingsHandler.GetAction(name);

if (onValueChanged == null)
if (onValueChanged != null)
{
return false;
onValueChanged(value, false, true);
VisibilityPlugin.Instance.Configuration.Save();
return true;
}

onValueChanged(value, false, true);
VisibilityPlugin.Instance.Configuration.Save();
return true;
if (callback != null)
{
callback(value, false, true);
return true;
}

return false;
}

public static bool CenteredCheckbox(bool value, string name)
public static bool CenteredCheckbox(bool value, string name, Action<bool, bool, bool>? callback = null)
{
ImGui.SetCursorPosX(
ImGui.GetCursorPosX() +
((ImGui.GetColumnWidth() + (2 * ImGui.GetStyle().FramePadding.X)) / 2) -
(2 * ImGui.GetStyle().ItemSpacing.X) - (2 * ImGui.GetStyle().CellPadding.X));

return Checkbox(value, name);
return Checkbox(value, name, callback);
}

/// <summary>
Expand Down
59 changes: 59 additions & 0 deletions Visibility/Utils/VoidListManager.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;

using FFXIVClientStructs.FFXIV.Client.Game.Character;

Expand All @@ -16,6 +17,7 @@ public class VoidListManager
private readonly Dictionary<uint, long> checkedWhitelistedObjectIds = new(capacity: 1000);
private readonly Dictionary<uint, long> voidedObjectIds = new(capacity: 1000);
private readonly Dictionary<uint, long> whitelistedObjectIds = new(capacity: 1000);
private readonly HashSet<uint> regexObjectIds = new(capacity: 1000);

/// <summary>
/// Check if an object is in the void list
Expand All @@ -25,12 +27,25 @@ public unsafe bool CheckAndProcessVoidList(Character* characterPtr)
if (this.checkedVoidedObjectIds.ContainsKey(characterPtr->GameObject.EntityId))
return this.voidedObjectIds.ContainsKey(characterPtr->GameObject.EntityId);

if (this.regexObjectIds.Contains(characterPtr->GameObject.EntityId))
return true;

if (!VisibilityPlugin.Instance.Configuration.VoidDictionary.TryGetValue(characterPtr->ContentId,
out VoidItem? voidedPlayer))
{
voidedPlayer = VisibilityPlugin.Instance.Configuration.VoidList.Find(x =>
characterPtr->GameObject.Name.StartsWith(x.NameBytes) &&
x.HomeworldId == characterPtr->HomeWorld);

if (voidedPlayer == null)
{
bool offworld = characterPtr->HomeWorld != Service.ClientState.LocalPlayer?.CurrentWorld.RowId;
if (this.IsRegexVoided(characterPtr->GameObject.NameString, offworld))
{
this.regexObjectIds.Add(characterPtr->GameObject.EntityId);
return true;
}
}
}

if (voidedPlayer != null)
Expand Down Expand Up @@ -86,6 +101,39 @@ public unsafe bool CheckAndProcessWhitelist(Character* characterPtr)
return this.whitelistedObjectIds.ContainsKey(characterPtr->GameObject.EntityId);
}

/// <summary>
/// Checks if a character should be voided by a registered regex pattern.
/// </summary>
/// <param name="name">Character name</param>
/// <param name="offworld">Is character from a world different from the current world</param>
private bool IsRegexVoided(string name, bool offworld)
{
return VisibilityPlugin.Instance.Configuration.VoidPatterns.Any(item =>
{
if (!item.Enabled)
return false;

if (item.Offworld && !offworld)
{
Service.PluginLog.Debug($"Regex Ignored: {item.Pattern} | {name} is offworld={offworld}");
return false;
}

try
{
bool match = item.Regex.IsMatch(name);
Service.PluginLog.Debug($"IsRegexVoided: {name} | {item.Pattern} | {match}");
return match;
}
catch (Exception e)
{
Service.PluginLog.Error($"Error during regex creation {item.Pattern}:\n{e}");
}

return false;
});
}

/// <summary>
/// Check if an object ID is in the void list
/// </summary>
Expand All @@ -111,6 +159,7 @@ public void RemoveChecked(uint id)
this.whitelistedObjectIds.Remove(id);
this.checkedVoidedObjectIds.Remove(id);
this.checkedWhitelistedObjectIds.Remove(id);
this.regexObjectIds.Remove(id);
}

/// <summary>
Expand All @@ -122,5 +171,15 @@ public void ClearAll()
this.checkedWhitelistedObjectIds.Clear();
this.voidedObjectIds.Clear();
this.whitelistedObjectIds.Clear();
this.regexObjectIds.Clear();
}

/// <summary>
/// Clears the regex object list and checked list to allow for redrawing of models
/// </summary>
public void ClearRegexCache()
{
this.checkedVoidedObjectIds.Clear();
this.regexObjectIds.Clear();
}
}
24 changes: 24 additions & 0 deletions Visibility/Void/VoidPattern.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using System.Text.RegularExpressions;

using Newtonsoft.Json;

namespace Visibility.Void;

[method: JsonConstructor]
public class VoidPattern(
string id,
int version,
string pattern,
string description,
bool offworld = false,
bool enabled = true)
{
public string Id { get; } = id;
public int Version { get; set; } = version;
public string Pattern { get; } = pattern;
public string Description { get; } = description;
public bool Offworld { get; set; } = offworld;
public bool Enabled { get; set; } = enabled;

[JsonIgnore] public readonly Regex Regex = new(pattern, RegexOptions.IgnoreCase | RegexOptions.Compiled);
}
19 changes: 17 additions & 2 deletions Visibility/Windows/Configuration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@ public Configuration(WindowSystem windowSystem): base($"{VisibilityPlugin.Instan
{
this.whitelistWindow = new VoidItemList(isWhitelist: true);
this.voidItemListWindow = new VoidItemList(isWhitelist: false);
this.voidPatternWindow = new VoidPatternList();

windowSystem.AddWindow(this.whitelistWindow);
windowSystem.AddWindow(this.voidItemListWindow);
windowSystem.AddWindow(this.voidPatternWindow);

this.Size = new Vector2(700 * ImGui.GetIO().FontGlobalScale, 0);
this.SizeCondition = ImGuiCond.Always;
Expand All @@ -35,6 +37,7 @@ public Configuration(WindowSystem windowSystem): base($"{VisibilityPlugin.Instan

private readonly VoidItemList whitelistWindow;
private readonly VoidItemList voidItemListWindow;
private readonly VoidPatternList voidPatternWindow;

public override void Draw()
{
Expand Down Expand Up @@ -290,7 +293,8 @@ public override void Draw()
ImGui.GetContentRegionMax().X -
ImGui.CalcTextSize(VisibilityPlugin.Instance.PluginLocalization.WhitelistName).X -
ImGui.CalcTextSize(VisibilityPlugin.Instance.PluginLocalization.VoidListName).X -
(4 * ImGui.GetStyle().FramePadding.X) -
ImGui.CalcTextSize(VisibilityPlugin.Instance.PluginLocalization.PatternListName).X -
(8 * ImGui.GetStyle().FramePadding.X) -
(ImGui.GetStyle().ItemSpacing.X * ImGui.GetIO().FontGlobalScale));

if (ImGui.Button(VisibilityPlugin.Instance.PluginLocalization.WhitelistName))
Expand All @@ -301,11 +305,22 @@ public override void Draw()
ImGui.SameLine(
ImGui.GetContentRegionMax().X -
ImGui.CalcTextSize(VisibilityPlugin.Instance.PluginLocalization.VoidListName).X -
(2 * ImGui.GetStyle().FramePadding.X));
ImGui.CalcTextSize(VisibilityPlugin.Instance.PluginLocalization.PatternListName).X -
(6 * ImGui.GetStyle().FramePadding.X));

if (ImGui.Button(VisibilityPlugin.Instance.PluginLocalization.VoidListName))
{
this.voidItemListWindow.Toggle();
}

ImGui.SameLine(
ImGui.GetContentRegionMax().X -
ImGui.CalcTextSize(VisibilityPlugin.Instance.PluginLocalization.PatternListName).X -
(2 * ImGui.GetStyle().FramePadding.X));

if (ImGui.Button(VisibilityPlugin.Instance.PluginLocalization.PatternListName))
{
this.voidPatternWindow.Toggle();
}
}
}
Loading