feature/auto-accept-party-invites #2

Merged
KnackAtNite merged 2 commits from feature/auto-accept-party-invites into main 2026-02-21 21:28:35 +00:00
9 changed files with 200 additions and 4 deletions
Showing only changes of commit 4dcea5d7de - Show all commits
+6
View File
@@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## [1.0.4] - 2025-02-20
### Added
- **Auto-accept party invites** Option to automatically accept party invites when the inviter is on your friend list or is a member of your Free Company. Configurable toggles for friends and FC members.
## [1.0.3] - 2025-02-03
### Added
@@ -45,4 +45,22 @@ public class HSRToolsConfiguration
/// Use this to diagnose cross-world invite issues.
/// </summary>
public bool Debug { get; set; } = false;
// --- Auto-accept party invites ---
/// <summary>
/// When true, automatically accept party invites from friends and/or Free Company members
/// (based on the options below).
/// </summary>
public bool AutoAcceptEnabled { get; set; } = false;
/// <summary>
/// When true and AutoAcceptEnabled, accept party invites from players on your friend list.
/// </summary>
public bool AutoAcceptFromFriends { get; set; } = true;
/// <summary>
/// When true and AutoAcceptEnabled, accept party invites from members of your Free Company.
/// </summary>
public bool AutoAcceptFromFreeCompany { get; set; } = true;
}
+1 -1
View File
@@ -1,7 +1,7 @@
<Project Sdk="Dalamud.NET.Sdk/14.0.1">
<PropertyGroup>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Version>1.0.3.0</Version>
<Version>1.0.4.0</Version>
<Author>Knack117</Author>
<Name>HSRTools</Name>
<InternalName>HSRTools</InternalName>
+2 -2
View File
@@ -1,8 +1,8 @@
{
"Author": "Knack117",
"Name": "HSRTools",
"Punchline": "Auto-invite to party when a trigger word is said in FC, LS, CWLS, or tells.",
"Description": "Detects a user-defined trigger word in Free Company, Link Shell, Cross-World Link Shell, and tell chat, then invites the sender to your party. Works for same-world and cross-world (CWLS).",
"Punchline": "Auto-invite and auto-accept party invites from friends/FC.",
"Description": "Detects a trigger word in FC, LS, CWLS, and tells to auto-invite; optionally auto-accepts party invites from friends and FC members.",
"RepoUrl": "https://github.com/Knack117/HSRTools",
"Tags": [ "chat", "party", "invite", "automation" ],
"AcceptsFeedback": true
+9
View File
@@ -15,6 +15,7 @@ public sealed class HSRToolsPlugin : IDalamudPlugin
private readonly string _configDir;
private readonly ChatMonitorService _chatMonitorService;
private readonly AutoAcceptPartyService _autoAcceptPartyService;
private readonly ConfigWindow _configWindow;
private readonly WindowSystem _windowSystem;
private HSRToolsConfiguration _config;
@@ -32,6 +33,11 @@ public sealed class HSRToolsPlugin : IDalamudPlugin
PluginServices.PluginLog,
_config);
_autoAcceptPartyService = new AutoAcceptPartyService(
PluginServices.AddonLifecycle,
PluginServices.PluginLog,
_config);
_configWindow = new ConfigWindow(_config);
_windowSystem = new WindowSystem("HSRTools");
_windowSystem.AddWindow(_configWindow);
@@ -44,12 +50,15 @@ public sealed class HSRToolsPlugin : IDalamudPlugin
});
_chatMonitorService.SetConfiguration(_config);
_chatMonitorService.Start();
_autoAcceptPartyService.SetConfiguration(_config);
_autoAcceptPartyService.Start();
}
public void Dispose()
{
PluginServices.CommandManager.RemoveHandler("/hsr");
_chatMonitorService.Stop();
_autoAcceptPartyService.Stop();
_windowSystem.RemoveAllWindows();
SaveConfig(_configDir, _config);
}
+134
View File
@@ -0,0 +1,134 @@
using System;
using Dalamud.Game.Addon.Lifecycle;
using Dalamud.Game.Addon.Lifecycle.AddonArgTypes;
using Dalamud.Plugin.Services;
using FFXIVClientStructs.FFXIV.Client.UI.Agent;
using FFXIVClientStructs.FFXIV.Client.UI.Info;
using HSRTools.Configuration;
namespace HSRTools.Services;
/// <summary>
/// Automatically accepts party invites when the inviter is a friend or Free Company member.
/// Uses IAddonLifecycle to detect when the party invite addon opens, then checks the
/// inviter against the friend list and FC roster before accepting.
/// </summary>
public sealed class AutoAcceptPartyService
{
private const string PartyInviteAddonName = "PartyInvite";
private readonly IAddonLifecycle _addonLifecycle;
private readonly IPluginLog _log;
private HSRToolsConfiguration _config;
public AutoAcceptPartyService(IAddonLifecycle addonLifecycle, IPluginLog log, HSRToolsConfiguration config)
{
_addonLifecycle = addonLifecycle;
_log = log;
_config = config;
}
public void SetConfiguration(HSRToolsConfiguration config)
{
_config = config;
}
public void Start()
{
_addonLifecycle.RegisterListener(AddonEvent.PreSetup, PartyInviteAddonName, OnPartyInviteAddon);
}
public void Stop()
{
_addonLifecycle.UnregisterListener(AddonEvent.PreSetup, PartyInviteAddonName, OnPartyInviteAddon);
}
private void OnPartyInviteAddon(AddonEvent eventType, AddonArgs args)
{
if (!_config.AutoAcceptEnabled)
return;
if (!_config.AutoAcceptFromFriends && !_config.AutoAcceptFromFreeCompany)
return;
unsafe
{
var agent = AgentPartyInvite.Instance();
if (agent == null)
return;
var proxy = agent->InfoProxyPartyInvite;
if (proxy == null)
return;
var inviterName = proxy->InviterName.ToString();
if (string.IsNullOrWhiteSpace(inviterName))
return;
var inviterWorldId = proxy->InviterWorldId;
var isFriend = _config.AutoAcceptFromFriends && IsFriend(inviterName, inviterWorldId);
var isFcMember = _config.AutoAcceptFromFreeCompany && IsFreeCompanyMember(inviterName, inviterWorldId);
if (!isFriend && !isFcMember)
return;
var reason = isFriend && isFcMember ? "friend and FC member" : isFriend ? "friend" : "FC member";
_log.Info($"Auto-accepting party invite from {inviterName} ({reason}).");
try
{
// RespondToInvitation is on InfoProxyInvitedList (parent of InfoProxyPartyInvite)
var accepted = ((InfoProxyInvitedList*)proxy)->RespondToInvitation(inviterName, true);
if (!accepted)
_log.Warning($"Failed to auto-accept party invite from {inviterName}.");
}
catch (Exception ex)
{
_log.Error(ex, $"Error auto-accepting party invite from {inviterName}");
}
}
}
private static unsafe bool IsFriend(string characterName, ushort worldId)
{
try
{
var infoModule = InfoModule.Instance();
if (infoModule == null)
return false;
var proxy = (InfoProxyCommonList*)infoModule->GetInfoProxyById(InfoProxyId.FriendList);
if (proxy == null)
return false;
var entry = proxy->GetEntryByName(characterName, worldId);
return entry != null;
}
catch
{
return false;
}
}
private static unsafe bool IsFreeCompanyMember(string characterName, ushort worldId)
{
try
{
var infoModule = InfoModule.Instance();
if (infoModule == null)
return false;
var proxy = (InfoProxyCommonList*)infoModule->GetInfoProxyById(InfoProxyId.FreeCompanyMember);
if (proxy == null)
return false;
var entry = proxy->GetEntryByName(characterName, worldId);
return entry != null;
}
catch
{
return false;
}
}
}
+1
View File
@@ -13,4 +13,5 @@ public sealed class PluginServices
[PluginService] public static IDalamudPluginInterface PluginInterface { get; private set; } = null!;
[PluginService] public static IToastGui ToastGui { get; private set; } = null!;
[PluginService] public static ICommandManager CommandManager { get; private set; } = null!;
[PluginService] public static IAddonLifecycle AddonLifecycle { get; private set; } = null!;
}
+23
View File
@@ -15,6 +15,9 @@ public sealed class ConfigWindow : Window
private bool _monitorTell;
private bool _enabled;
private bool _debug;
private bool _autoAcceptEnabled;
private bool _autoAcceptFromFriends;
private bool _autoAcceptFromFreeCompany;
public ConfigWindow(HSRToolsConfiguration config)
: base("HSRTools Configuration", ImGuiWindowFlags.AlwaysAutoResize)
@@ -33,6 +36,9 @@ public sealed class ConfigWindow : Window
_monitorTell = _config.MonitorTell;
_enabled = _config.Enabled;
_debug = _config.Debug;
_autoAcceptEnabled = _config.AutoAcceptEnabled;
_autoAcceptFromFriends = _config.AutoAcceptFromFriends;
_autoAcceptFromFreeCompany = _config.AutoAcceptFromFreeCompany;
}
public override void Draw()
@@ -47,6 +53,9 @@ public sealed class ConfigWindow : Window
_config.MonitorTell = true;
_config.Enabled = true;
_config.Debug = false;
_config.AutoAcceptEnabled = false;
_config.AutoAcceptFromFriends = true;
_config.AutoAcceptFromFreeCompany = true;
SyncFromConfig();
}
@@ -78,5 +87,19 @@ public sealed class ConfigWindow : Window
ImGui.Separator();
if (ImGui.Checkbox("Debug logging (diagnose cross-world invite)", ref _debug))
_config.Debug = _debug;
ImGui.Separator();
ImGui.Text("Auto-accept party invites:");
ImGui.Indent();
if (ImGui.Checkbox("Auto-accept from friends and FC members", ref _autoAcceptEnabled))
_config.AutoAcceptEnabled = _autoAcceptEnabled;
if (_autoAcceptEnabled)
{
if (ImGui.Checkbox(" From friends", ref _autoAcceptFromFriends))
_config.AutoAcceptFromFriends = _autoAcceptFromFriends;
if (ImGui.Checkbox(" From Free Company members", ref _autoAcceptFromFreeCompany))
_config.AutoAcceptFromFreeCompany = _autoAcceptFromFreeCompany;
}
ImGui.Unindent();
}
}
+6 -1
View File
@@ -5,6 +5,7 @@ A [Dalamud](https://github.com/goatcorp/Dalamud) plugin for FFXIV (XIVLauncher)
## Features
- **Configurable trigger text** Set any word or phrase (e.g. `inv`, `invite`, `party`). When someone types it in a monitored channel, they are invited to your party.
- **Auto-accept party invites** Optionally automatically accept party invites when the inviter is on your friend list or is a member of your Free Company.
- **Channel selection** Choose which channels to monitor:
- Free Company
- Link Shell (18)
@@ -21,6 +22,10 @@ A [Dalamud](https://github.com/goatcorp/Dalamud) plugin for FFXIV (XIVLauncher)
For **tells**, the game provides the senders content ID and world, so invites work reliably. For **FC, LS, and CWLS**, the plugin uses the senders content ID when available (e.g. from the last message in CWLS), so cross-world invites work for CWLS and same-world for FC/LS.
### Auto-accept party invites
When enabled, the plugin detects incoming party invites and automatically accepts them if the inviter is on your friend list or is a member of your Free Company. You can toggle friends and FC members independently. The friend list and FC roster must have been opened in-game at least once for the plugin to recognize members.
## Building
1. Open `HSRTools.sln` in Visual Studio or use the command line.
@@ -35,7 +40,7 @@ For **tells**, the game provides the senders content ID and world, so invites
## Configuration
- Open the plugin config from the Dalamud plugin list (right-click HSRTools → **Settings**).
- Set the trigger text, enable/disable the plugin, choose channels, and set case sensitivity.
- Set the trigger text, enable/disable the plugin, choose channels, set case sensitivity, and configure auto-accept (friends/FC).
- Settings are saved when you close the game or disable the plugin.
## Requirements