feat(chat): port retail client command families
Expand the typed client-command boundary across travel, character queries, local UI and layout controls, AFK and consent, emotes, friends, squelch and filters, and fill-components. Preserve retail packet layouts and queue ownership, import the confirmation dialog, and keep authoritative social state in Core. Co-Authored-By: Codex <codex@openai.com>
This commit is contained in:
parent
5a45a7ac7f
commit
9ea579bdd0
47 changed files with 6659 additions and 99 deletions
|
|
@ -162,7 +162,8 @@ public sealed class SettingsStore
|
|||
ShowHelm: ReadBool(gp, "showHelm", d.ShowHelm),
|
||||
ShowCloak: ReadBool(gp, "showCloak", d.ShowCloak),
|
||||
LockUI: ReadBool(gp, "lockUI", d.LockUI),
|
||||
UseMouseTurning: ReadBool(gp, "useMouseTurning", d.UseMouseTurning));
|
||||
UseMouseTurning: ReadBool(gp, "useMouseTurning", d.UseMouseTurning),
|
||||
AcceptLootPermits: ReadBool(gp, "acceptLootPermits", d.AcceptLootPermits));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
|
@ -419,6 +420,70 @@ public sealed class SettingsStore
|
|||
WriteMutableRoot(root);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Load one window from a user-named retail <c>@saveui</c> profile.
|
||||
/// Named profiles are intentionally independent of character and screen
|
||||
/// resolution, matching retail's portable UI files.
|
||||
/// </summary>
|
||||
public UiWindowLayout? LoadNamedWindowLayout(
|
||||
string profileName,
|
||||
string windowName,
|
||||
UiWindowLayout fallback)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(profileName);
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(windowName);
|
||||
if (!File.Exists(_path)) return null;
|
||||
|
||||
try
|
||||
{
|
||||
var root = JsonNode.Parse(File.ReadAllText(_path)) as JsonObject;
|
||||
JsonObject? node = root?["namedWindowLayouts"]?[profileName]?[windowName] as JsonObject;
|
||||
return node is null
|
||||
? null
|
||||
: new UiWindowLayout(
|
||||
ReadNodeFloat(node, "x", fallback.X),
|
||||
ReadNodeFloat(node, "y", fallback.Y),
|
||||
ReadNodeFloat(node, "width", fallback.Width),
|
||||
ReadNodeFloat(node, "height", fallback.Height),
|
||||
ReadNodeBool(node, "visible", fallback.Visible),
|
||||
ReadNodeBool(node, "collapsed", fallback.Collapsed),
|
||||
ReadNodeBool(node, "maximized", fallback.Maximized));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"settings: failed to load named window layout from {_path}: {ex.Message}");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Save one window to a user-named retail <c>@saveui</c> profile.</summary>
|
||||
public void SaveNamedWindowLayout(
|
||||
string profileName,
|
||||
string windowName,
|
||||
UiWindowLayout layout)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(profileName);
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(windowName);
|
||||
|
||||
JsonObject root = LoadMutableRoot();
|
||||
JsonObject profiles = GetOrCreateObject(root, "namedWindowLayouts");
|
||||
JsonObject profile = GetOrCreateObject(profiles, profileName);
|
||||
profile[windowName] = SerializeWindowLayout(layout);
|
||||
root["version"] = CurrentSchemaVersion;
|
||||
WriteMutableRoot(root);
|
||||
}
|
||||
|
||||
private static JsonObject SerializeWindowLayout(UiWindowLayout layout) => new()
|
||||
{
|
||||
["x"] = layout.X,
|
||||
["y"] = layout.Y,
|
||||
["width"] = layout.Width,
|
||||
["height"] = layout.Height,
|
||||
["visible"] = layout.Visible,
|
||||
["collapsed"] = layout.Collapsed,
|
||||
["maximized"] = layout.Maximized,
|
||||
};
|
||||
|
||||
private JsonObject LoadMutableRoot()
|
||||
{
|
||||
var dir = Path.GetDirectoryName(_path);
|
||||
|
|
@ -481,6 +546,7 @@ public sealed class SettingsStore
|
|||
=> new(StringComparer.Ordinal)
|
||||
{
|
||||
["advancedCombatUI"] = g.AdvancedCombatUI,
|
||||
["acceptLootPermits"] = g.AcceptLootPermits,
|
||||
["allowGive"] = g.AllowGive,
|
||||
["autoRepeatAttack"] = g.AutoRepeatAttack,
|
||||
["autoTarget"] = g.AutoTarget,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue