New configuration format
This commit is contained in:
parent
4be0bdf637
commit
b0de113ad2
80
Pal.Client/Configuration/AccountConfigurationV7.cs
Normal file
80
Pal.Client/Configuration/AccountConfigurationV7.cs
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
using Dalamud.Logging;
|
||||||
|
|
||||||
|
namespace Pal.Client.Configuration
|
||||||
|
{
|
||||||
|
public class AccountConfigurationV7 : IAccountConfiguration
|
||||||
|
{
|
||||||
|
[JsonConstructor]
|
||||||
|
public AccountConfigurationV7()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public AccountConfigurationV7(string server, Guid accountId)
|
||||||
|
{
|
||||||
|
Server = server;
|
||||||
|
EncryptedId = EncryptAccountId(accountId);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Obsolete("for V1 import")]
|
||||||
|
public AccountConfigurationV7(string server, string accountId)
|
||||||
|
{
|
||||||
|
Server = server;
|
||||||
|
|
||||||
|
if (accountId.StartsWith("s:"))
|
||||||
|
EncryptedId = accountId;
|
||||||
|
else if (Guid.TryParse(accountId, out Guid guid))
|
||||||
|
EncryptedId = EncryptAccountId(guid);
|
||||||
|
else
|
||||||
|
throw new InvalidOperationException("invalid account id format");
|
||||||
|
}
|
||||||
|
|
||||||
|
public string EncryptedId { get; init; } = null!;
|
||||||
|
|
||||||
|
public string Server { get; set; } = null!;
|
||||||
|
|
||||||
|
[JsonIgnore] public bool IsUsable => DecryptAccountId(EncryptedId) != null;
|
||||||
|
|
||||||
|
[JsonIgnore] public Guid AccountId => DecryptAccountId(EncryptedId) ?? throw new InvalidOperationException();
|
||||||
|
|
||||||
|
public List<string> CachedRoles { get; set; } = new();
|
||||||
|
|
||||||
|
private Guid? DecryptAccountId(string id)
|
||||||
|
{
|
||||||
|
if (Guid.TryParse(id, out Guid guid) && guid != Guid.Empty)
|
||||||
|
return guid;
|
||||||
|
|
||||||
|
if (!id.StartsWith("s:"))
|
||||||
|
throw new InvalidOperationException("invalid prefix");
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
byte[] guidBytes = ProtectedData.Unprotect(Convert.FromBase64String(id.Substring(2)),
|
||||||
|
ConfigurationData.Entropy, DataProtectionScope.CurrentUser);
|
||||||
|
return new Guid(guidBytes);
|
||||||
|
}
|
||||||
|
catch (CryptographicException e)
|
||||||
|
{
|
||||||
|
PluginLog.Verbose(e, $"Could not load account id {id}");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string EncryptAccountId(Guid g)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
byte[] guidBytes = ProtectedData.Protect(g.ToByteArray(), ConfigurationData.Entropy,
|
||||||
|
DataProtectionScope.CurrentUser);
|
||||||
|
return $"s:{Convert.ToBase64String(guidBytes)}";
|
||||||
|
}
|
||||||
|
catch (CryptographicException)
|
||||||
|
{
|
||||||
|
return g.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
7
Pal.Client/Configuration/ConfigurationData.cs
Normal file
7
Pal.Client/Configuration/ConfigurationData.cs
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
namespace Pal.Client.Configuration
|
||||||
|
{
|
||||||
|
internal static class ConfigurationData
|
||||||
|
{
|
||||||
|
internal static readonly byte[] Entropy = { 0x22, 0x4b, 0xe7, 0x21, 0x44, 0x83, 0x69, 0x55, 0x80, 0x38 };
|
||||||
|
}
|
||||||
|
}
|
108
Pal.Client/Configuration/ConfigurationManager.cs
Normal file
108
Pal.Client/Configuration/ConfigurationManager.cs
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.Json;
|
||||||
|
using Dalamud.Logging;
|
||||||
|
using Dalamud.Plugin;
|
||||||
|
using ImGuiNET;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using JsonSerializer = System.Text.Json.JsonSerializer;
|
||||||
|
|
||||||
|
namespace Pal.Client.Configuration
|
||||||
|
{
|
||||||
|
internal class ConfigurationManager
|
||||||
|
{
|
||||||
|
private readonly DalamudPluginInterface _pluginInterface;
|
||||||
|
|
||||||
|
public ConfigurationManager(DalamudPluginInterface pluginInterface)
|
||||||
|
{
|
||||||
|
_pluginInterface = pluginInterface;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string ConfigPath => Path.Join(_pluginInterface.GetPluginConfigDirectory(), "palace-pal.config.json");
|
||||||
|
|
||||||
|
#pragma warning disable CS0612
|
||||||
|
#pragma warning disable CS0618
|
||||||
|
public void Migrate()
|
||||||
|
{
|
||||||
|
if (_pluginInterface.ConfigFile.Exists)
|
||||||
|
{
|
||||||
|
PluginLog.Information("Migrating config file from v1-v6 format");
|
||||||
|
|
||||||
|
ConfigurationV1 configurationV1 =
|
||||||
|
JsonConvert.DeserializeObject<ConfigurationV1>(
|
||||||
|
File.ReadAllText(_pluginInterface.ConfigFile.FullName)) ?? new ConfigurationV1();
|
||||||
|
configurationV1.Migrate();
|
||||||
|
configurationV1.Save();
|
||||||
|
|
||||||
|
var v7 = MigrateToV7(configurationV1);
|
||||||
|
Save(v7);
|
||||||
|
|
||||||
|
File.Move(_pluginInterface.ConfigFile.FullName, _pluginInterface.ConfigFile.FullName + ".old", true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public IPalacePalConfiguration Load()
|
||||||
|
{
|
||||||
|
return JsonSerializer.Deserialize<ConfigurationV7>(File.ReadAllText(ConfigPath, Encoding.UTF8)) ??
|
||||||
|
new ConfigurationV7();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Save(IConfigurationInConfigDirectory config)
|
||||||
|
{
|
||||||
|
File.WriteAllText(ConfigPath,
|
||||||
|
JsonSerializer.Serialize(config, config.GetType(), new JsonSerializerOptions { WriteIndented = true }),
|
||||||
|
Encoding.UTF8);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ConfigurationV7 MigrateToV7(ConfigurationV1 v1)
|
||||||
|
{
|
||||||
|
ConfigurationV7 v7 = new()
|
||||||
|
{
|
||||||
|
Version = 7,
|
||||||
|
FirstUse = v1.FirstUse,
|
||||||
|
Mode = v1.Mode,
|
||||||
|
BetaKey = v1.BetaKey,
|
||||||
|
|
||||||
|
DeepDungeons = new DeepDungeonConfiguration
|
||||||
|
{
|
||||||
|
Traps = new MarkerConfiguration
|
||||||
|
{
|
||||||
|
Show = v1.ShowTraps,
|
||||||
|
Color = ImGui.ColorConvertFloat4ToU32(v1.TrapColor),
|
||||||
|
Fill = false
|
||||||
|
},
|
||||||
|
HoardCoffers = new MarkerConfiguration
|
||||||
|
{
|
||||||
|
Show = v1.ShowHoard,
|
||||||
|
Color = ImGui.ColorConvertFloat4ToU32(v1.HoardColor),
|
||||||
|
Fill = false
|
||||||
|
},
|
||||||
|
SilverCoffers = new MarkerConfiguration
|
||||||
|
{
|
||||||
|
Show = v1.ShowSilverCoffers,
|
||||||
|
Color = ImGui.ColorConvertFloat4ToU32(v1.SilverCofferColor),
|
||||||
|
Fill = v1.FillSilverCoffers
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
foreach (var (server, oldAccount) in v1.Accounts)
|
||||||
|
{
|
||||||
|
string? accountId = oldAccount.Id;
|
||||||
|
if (string.IsNullOrEmpty(accountId))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
IAccountConfiguration newAccount = v7.CreateAccount(server, accountId);
|
||||||
|
newAccount.CachedRoles = oldAccount.CachedRoles.ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO Migrate ImportHistory
|
||||||
|
|
||||||
|
return v7;
|
||||||
|
}
|
||||||
|
#pragma warning restore CS0618
|
||||||
|
#pragma warning restore CS0612
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,4 @@
|
|||||||
using Dalamud.Configuration;
|
using Dalamud.Logging;
|
||||||
using Dalamud.Logging;
|
|
||||||
using ECommons.Schedulers;
|
using ECommons.Schedulers;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Pal.Client.Scheduled;
|
using Pal.Client.Scheduled;
|
||||||
@ -9,15 +8,13 @@ using System.Collections.Generic;
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using System.Security.Cryptography;
|
|
||||||
using Pal.Client.Extensions;
|
using Pal.Client.Extensions;
|
||||||
|
|
||||||
namespace Pal.Client
|
namespace Pal.Client.Configuration
|
||||||
{
|
{
|
||||||
public class Configuration : IPluginConfiguration
|
[Obsolete]
|
||||||
|
public class ConfigurationV1
|
||||||
{
|
{
|
||||||
private static readonly byte[] Entropy = { 0x22, 0x4b, 0xe7, 0x21, 0x44, 0x83, 0x69, 0x55, 0x80, 0x38 };
|
|
||||||
|
|
||||||
public int Version { get; set; } = 6;
|
public int Version { get; set; } = 6;
|
||||||
|
|
||||||
#region Saved configuration values
|
#region Saved configuration values
|
||||||
@ -55,7 +52,6 @@ namespace Pal.Client
|
|||||||
public string BetaKey { get; set; } = "";
|
public string BetaKey { get; set; } = "";
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#pragma warning disable CS0612 // Type or member is obsolete
|
|
||||||
public void Migrate()
|
public void Migrate()
|
||||||
{
|
{
|
||||||
if (Version == 1)
|
if (Version == 1)
|
||||||
@ -78,7 +74,7 @@ namespace Pal.Client
|
|||||||
|
|
||||||
Accounts = AccountIds.ToDictionary(x => x.Key, x => new AccountInfo
|
Accounts = AccountIds.ToDictionary(x => x.Key, x => new AccountInfo
|
||||||
{
|
{
|
||||||
Id = x.Value
|
Id = x.Value.ToString() // encryption happens in V7 migration at latest
|
||||||
});
|
});
|
||||||
Version = 3;
|
Version = 3;
|
||||||
Save();
|
Save();
|
||||||
@ -140,108 +136,23 @@ namespace Pal.Client
|
|||||||
Save();
|
Save();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#pragma warning restore CS0612 // Type or member is obsolete
|
|
||||||
|
|
||||||
public void Save()
|
public void Save()
|
||||||
{
|
{
|
||||||
Service.PluginInterface.SavePluginConfig(this);
|
File.WriteAllText(Service.PluginInterface.ConfigFile.FullName, JsonConvert.SerializeObject(this, Formatting.Indented, new JsonSerializerSettings
|
||||||
|
{
|
||||||
|
TypeNameAssemblyFormatHandling = TypeNameAssemblyFormatHandling.Simple,
|
||||||
|
TypeNameHandling = TypeNameHandling.Objects
|
||||||
|
}));
|
||||||
Service.Plugin.EarlyEventQueue.Enqueue(new QueuedConfigUpdate());
|
Service.Plugin.EarlyEventQueue.Enqueue(new QueuedConfigUpdate());
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum EMode
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Fetches trap locations from remote server.
|
|
||||||
/// </summary>
|
|
||||||
Online = 1,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Only shows traps found by yourself uisng a pomander of sight.
|
|
||||||
/// </summary>
|
|
||||||
Offline = 2,
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum ERenderer
|
|
||||||
{
|
|
||||||
/// <see cref="Rendering.SimpleRenderer"/>
|
|
||||||
Simple = 0,
|
|
||||||
|
|
||||||
/// <see cref="Rendering.SplatoonRenderer"/>
|
|
||||||
Splatoon = 1,
|
|
||||||
}
|
|
||||||
|
|
||||||
public class AccountInfo
|
public class AccountInfo
|
||||||
{
|
{
|
||||||
[JsonConverter(typeof(AccountIdConverter))]
|
public string? Id { get; set; }
|
||||||
public Guid? Id { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This is taken from the JWT, and is only refreshed on a successful login.
|
|
||||||
///
|
|
||||||
/// If you simply reload the plugin without any server interaction, this doesn't change.
|
|
||||||
///
|
|
||||||
/// This has no impact on what roles the JWT actually contains, but is just to make it
|
|
||||||
/// easier to draw a consistent UI. The server will still reject unauthorized calls.
|
|
||||||
/// </summary>
|
|
||||||
public List<string> CachedRoles { get; set; } = new();
|
public List<string> CachedRoles { get; set; } = new();
|
||||||
}
|
}
|
||||||
|
|
||||||
public class AccountIdConverter : JsonConverter
|
|
||||||
{
|
|
||||||
public override bool CanConvert(Type objectType) => true;
|
|
||||||
|
|
||||||
public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer)
|
|
||||||
{
|
|
||||||
if (reader.TokenType == JsonToken.String)
|
|
||||||
{
|
|
||||||
string? text = reader.Value?.ToString();
|
|
||||||
if (string.IsNullOrEmpty(text))
|
|
||||||
return null;
|
|
||||||
|
|
||||||
if (Guid.TryParse(text, out Guid guid) && guid != Guid.Empty)
|
|
||||||
return guid;
|
|
||||||
|
|
||||||
if (text.StartsWith("s:"))
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
byte[] guidBytes = ProtectedData.Unprotect(Convert.FromBase64String(text.Substring(2)), Entropy, DataProtectionScope.CurrentUser);
|
|
||||||
return new Guid(guidBytes);
|
|
||||||
}
|
|
||||||
catch (CryptographicException e)
|
|
||||||
{
|
|
||||||
PluginLog.Error(e, "Could not load account id");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
throw new JsonSerializationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer)
|
|
||||||
{
|
|
||||||
if (value == null)
|
|
||||||
{
|
|
||||||
writer.WriteNull();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Guid g = (Guid)value;
|
|
||||||
string text;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
byte[] guidBytes = ProtectedData.Protect(g.ToByteArray(), Entropy, DataProtectionScope.CurrentUser);
|
|
||||||
text = $"s:{Convert.ToBase64String(guidBytes)}";
|
|
||||||
}
|
|
||||||
catch (CryptographicException)
|
|
||||||
{
|
|
||||||
text = g.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
writer.WriteValue(text);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class ImportHistoryEntry
|
public class ImportHistoryEntry
|
||||||
{
|
{
|
||||||
public Guid Id { get; set; }
|
public Guid Id { get; set; }
|
48
Pal.Client/Configuration/ConfigurationV7.cs
Normal file
48
Pal.Client/Configuration/ConfigurationV7.cs
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace Pal.Client.Configuration;
|
||||||
|
|
||||||
|
public class ConfigurationV7 : IPalacePalConfiguration, IConfigurationInConfigDirectory
|
||||||
|
{
|
||||||
|
public int Version { get; set; } = 7;
|
||||||
|
|
||||||
|
public bool FirstUse { get; set; } = true;
|
||||||
|
public EMode Mode { get; set; }
|
||||||
|
public string BetaKey { get; init; } = "";
|
||||||
|
|
||||||
|
public DeepDungeonConfiguration DeepDungeons { get; set; } = new();
|
||||||
|
public RendererConfiguration Renderer { get; set; } = new();
|
||||||
|
public List<AccountConfigurationV7> Accounts { get; set; } = new();
|
||||||
|
|
||||||
|
[JsonIgnore]
|
||||||
|
[Obsolete]
|
||||||
|
public List<ConfigurationV1.ImportHistoryEntry> ImportHistory { get; set; } = new();
|
||||||
|
|
||||||
|
public IAccountConfiguration CreateAccount(string server, Guid accountId)
|
||||||
|
{
|
||||||
|
var account = new AccountConfigurationV7(server, accountId);
|
||||||
|
Accounts.Add(account);
|
||||||
|
return account;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Obsolete("for V1 import")]
|
||||||
|
internal IAccountConfiguration CreateAccount(string server, string accountId)
|
||||||
|
{
|
||||||
|
var account = new AccountConfigurationV7(server, accountId);
|
||||||
|
Accounts.Add(account);
|
||||||
|
return account;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IAccountConfiguration? FindAccount(string server)
|
||||||
|
{
|
||||||
|
return Accounts.FirstOrDefault(a => a.Server == server && a.IsUsable);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveAccount(string server)
|
||||||
|
{
|
||||||
|
Accounts.RemoveAll(a => a.Server == server && a.IsUsable);
|
||||||
|
}
|
||||||
|
}
|
15
Pal.Client/Configuration/EMode.cs
Normal file
15
Pal.Client/Configuration/EMode.cs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
namespace Pal.Client.Configuration
|
||||||
|
{
|
||||||
|
public enum EMode
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Fetches trap locations from remote server.
|
||||||
|
/// </summary>
|
||||||
|
Online = 1,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Only shows traps found by yourself uisng a pomander of sight.
|
||||||
|
/// </summary>
|
||||||
|
Offline = 2,
|
||||||
|
}
|
||||||
|
}
|
11
Pal.Client/Configuration/ERenderer.cs
Normal file
11
Pal.Client/Configuration/ERenderer.cs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
namespace Pal.Client.Configuration
|
||||||
|
{
|
||||||
|
public enum ERenderer
|
||||||
|
{
|
||||||
|
/// <see cref="Rendering.SimpleRenderer"/>
|
||||||
|
Simple = 0,
|
||||||
|
|
||||||
|
/// <see cref="Rendering.SplatoonRenderer"/>
|
||||||
|
Splatoon = 1,
|
||||||
|
}
|
||||||
|
}
|
89
Pal.Client/Configuration/IPalacePalConfiguration.cs
Normal file
89
Pal.Client/Configuration/IPalacePalConfiguration.cs
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Numerics;
|
||||||
|
using ImGuiNET;
|
||||||
|
|
||||||
|
namespace Pal.Client.Configuration
|
||||||
|
{
|
||||||
|
public interface IVersioned
|
||||||
|
{
|
||||||
|
int Version { get; set; }
|
||||||
|
}
|
||||||
|
public interface IConfigurationInConfigDirectory : IVersioned
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface IPalacePalConfiguration : IConfigurationInConfigDirectory
|
||||||
|
{
|
||||||
|
bool FirstUse { get; set; }
|
||||||
|
EMode Mode { get; set; }
|
||||||
|
string BetaKey { get; }
|
||||||
|
|
||||||
|
DeepDungeonConfiguration DeepDungeons { get; set; }
|
||||||
|
RendererConfiguration Renderer { get; set; }
|
||||||
|
|
||||||
|
[Obsolete]
|
||||||
|
List<ConfigurationV1.ImportHistoryEntry> ImportHistory { get; }
|
||||||
|
|
||||||
|
IAccountConfiguration CreateAccount(string server, Guid accountId);
|
||||||
|
IAccountConfiguration? FindAccount(string server);
|
||||||
|
void RemoveAccount(string server);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class DeepDungeonConfiguration
|
||||||
|
{
|
||||||
|
public MarkerConfiguration Traps { get; set; } = new()
|
||||||
|
{
|
||||||
|
Show = true,
|
||||||
|
Color = ImGui.ColorConvertFloat4ToU32(new Vector4(1, 0, 0, 0.4f)),
|
||||||
|
OnlyVisibleAfterPomander = true,
|
||||||
|
Fill = false
|
||||||
|
};
|
||||||
|
|
||||||
|
public MarkerConfiguration HoardCoffers { get; set; } = new()
|
||||||
|
{
|
||||||
|
Show = true,
|
||||||
|
Color = ImGui.ColorConvertFloat4ToU32(new Vector4(0, 1, 1, 0.4f)),
|
||||||
|
OnlyVisibleAfterPomander = true,
|
||||||
|
Fill = false
|
||||||
|
};
|
||||||
|
|
||||||
|
public MarkerConfiguration SilverCoffers { get; set; } = new()
|
||||||
|
{
|
||||||
|
Show = false,
|
||||||
|
Color = ImGui.ColorConvertFloat4ToU32(new Vector4(1, 1, 1, 0.4f)),
|
||||||
|
OnlyVisibleAfterPomander = false,
|
||||||
|
Fill = true
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public class MarkerConfiguration
|
||||||
|
{
|
||||||
|
public bool Show { get; set; }
|
||||||
|
public uint Color { get; set; }
|
||||||
|
public bool OnlyVisibleAfterPomander { get; set; }
|
||||||
|
public bool Fill { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class RendererConfiguration
|
||||||
|
{
|
||||||
|
public ERenderer SelectedRenderer { get; set; } = ERenderer.Splatoon;
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface IAccountConfiguration
|
||||||
|
{
|
||||||
|
public bool IsUsable { get; }
|
||||||
|
public string Server { get; }
|
||||||
|
public Guid AccountId { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This is taken from the JWT, and is only refreshed on a successful login.
|
||||||
|
///
|
||||||
|
/// If you simply reload the plugin without any server interaction, this doesn't change.
|
||||||
|
///
|
||||||
|
/// This has no impact on what roles the JWT actually contains, but is just to make it
|
||||||
|
/// easier to draw a consistent UI. The server will still reject unauthorized calls.
|
||||||
|
/// </summary>
|
||||||
|
public List<string> CachedRoles { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -11,6 +11,7 @@ using System.Threading;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Pal.Client.Extensions;
|
using Pal.Client.Extensions;
|
||||||
using Pal.Client.Properties;
|
using Pal.Client.Properties;
|
||||||
|
using Pal.Client.Configuration;
|
||||||
|
|
||||||
namespace Pal.Client.Net
|
namespace Pal.Client.Net
|
||||||
{
|
{
|
||||||
@ -18,7 +19,7 @@ namespace Pal.Client.Net
|
|||||||
{
|
{
|
||||||
private async Task<(bool Success, string Error)> TryConnect(CancellationToken cancellationToken, ILoggerFactory? loggerFactory = null, bool retry = true)
|
private async Task<(bool Success, string Error)> TryConnect(CancellationToken cancellationToken, ILoggerFactory? loggerFactory = null, bool retry = true)
|
||||||
{
|
{
|
||||||
if (Service.Configuration.Mode != Configuration.EMode.Online)
|
if (Service.Configuration.Mode != EMode.Online)
|
||||||
{
|
{
|
||||||
PluginLog.Debug("TryConnect: Not Online, not attempting to establish a connection");
|
PluginLog.Debug("TryConnect: Not Online, not attempting to establish a connection");
|
||||||
return (false, Localization.ConnectionError_NotOnline);
|
return (false, Localization.ConnectionError_NotOnline);
|
||||||
@ -46,19 +47,20 @@ namespace Pal.Client.Net
|
|||||||
cancellationToken.ThrowIfCancellationRequested();
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
var accountClient = new AccountService.AccountServiceClient(_channel);
|
var accountClient = new AccountService.AccountServiceClient(_channel);
|
||||||
if (AccountId == null)
|
IAccountConfiguration? configuredAccount = Service.Configuration.FindAccount(RemoteUrl);
|
||||||
|
if (configuredAccount == null)
|
||||||
{
|
{
|
||||||
PluginLog.Information($"TryConnect: No account information saved for {RemoteUrl}, creating new account");
|
PluginLog.Information($"TryConnect: No account information saved for {RemoteUrl}, creating new account");
|
||||||
var createAccountReply = await accountClient.CreateAccountAsync(new CreateAccountRequest(), headers: UnauthorizedHeaders(), deadline: DateTime.UtcNow.AddSeconds(10), cancellationToken: cancellationToken);
|
var createAccountReply = await accountClient.CreateAccountAsync(new CreateAccountRequest(), headers: UnauthorizedHeaders(), deadline: DateTime.UtcNow.AddSeconds(10), cancellationToken: cancellationToken);
|
||||||
if (createAccountReply.Success)
|
if (createAccountReply.Success)
|
||||||
{
|
{
|
||||||
Account = new Configuration.AccountInfo
|
if (Guid.TryParse(createAccountReply.AccountId, out Guid accountId))
|
||||||
{
|
throw new InvalidOperationException("invalid account id returned");
|
||||||
Id = Guid.Parse(createAccountReply.AccountId),
|
|
||||||
};
|
|
||||||
PluginLog.Information($"TryConnect: Account created with id {FormattedPartialAccountId}");
|
|
||||||
|
|
||||||
Service.Configuration.Save();
|
configuredAccount = Service.Configuration.CreateAccount(RemoteUrl, accountId);
|
||||||
|
PluginLog.Information($"TryConnect: Account created with id {accountId.ToPartialId()}");
|
||||||
|
|
||||||
|
Service.ConfigurationManager.Save(Service.Configuration);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -74,27 +76,24 @@ namespace Pal.Client.Net
|
|||||||
|
|
||||||
cancellationToken.ThrowIfCancellationRequested();
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
if (AccountId == null)
|
// ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract
|
||||||
|
if (configuredAccount == null)
|
||||||
{
|
{
|
||||||
PluginLog.Warning("TryConnect: No account id to login with");
|
PluginLog.Warning("TryConnect: No account to login with");
|
||||||
return (false, Localization.ConnectionError_CreateAccountReturnedNoId);
|
return (false, Localization.ConnectionError_CreateAccountReturnedNoId);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_loginInfo.IsValid)
|
if (!_loginInfo.IsValid)
|
||||||
{
|
{
|
||||||
PluginLog.Information($"TryConnect: Logging in with account id {FormattedPartialAccountId}");
|
PluginLog.Information($"TryConnect: Logging in with account id {configuredAccount.AccountId.ToPartialId()}");
|
||||||
LoginReply loginReply = await accountClient.LoginAsync(new LoginRequest { AccountId = AccountId?.ToString() }, headers: UnauthorizedHeaders(), deadline: DateTime.UtcNow.AddSeconds(10), cancellationToken: cancellationToken);
|
LoginReply loginReply = await accountClient.LoginAsync(new LoginRequest { AccountId = configuredAccount.AccountId.ToString() }, headers: UnauthorizedHeaders(), deadline: DateTime.UtcNow.AddSeconds(10), cancellationToken: cancellationToken);
|
||||||
if (loginReply.Success)
|
if (loginReply.Success)
|
||||||
{
|
{
|
||||||
PluginLog.Information($"TryConnect: Login successful with account id: {FormattedPartialAccountId}");
|
PluginLog.Information($"TryConnect: Login successful with account id: {configuredAccount.AccountId.ToPartialId()}");
|
||||||
_loginInfo = new LoginInfo(loginReply.AuthToken);
|
_loginInfo = new LoginInfo(loginReply.AuthToken);
|
||||||
|
|
||||||
var account = Account;
|
configuredAccount.CachedRoles = _loginInfo.Claims?.Roles.ToList() ?? new List<string>();
|
||||||
if (account != null)
|
Service.ConfigurationManager.Save(Service.Configuration);
|
||||||
{
|
|
||||||
account.CachedRoles = _loginInfo.Claims?.Roles.ToList() ?? new List<string>();
|
|
||||||
Service.Configuration.Save();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -102,8 +101,8 @@ namespace Pal.Client.Net
|
|||||||
_loginInfo = new LoginInfo(null);
|
_loginInfo = new LoginInfo(null);
|
||||||
if (loginReply.Error == LoginError.InvalidAccountId)
|
if (loginReply.Error == LoginError.InvalidAccountId)
|
||||||
{
|
{
|
||||||
Account = null;
|
Service.Configuration.RemoveAccount(RemoteUrl);
|
||||||
Service.Configuration.Save();
|
Service.ConfigurationManager.Save(Service.Configuration);
|
||||||
if (retry)
|
if (retry)
|
||||||
{
|
{
|
||||||
PluginLog.Information("TryConnect: Attempting connection retry without account id");
|
PluginLog.Information("TryConnect: Attempting connection retry without account id");
|
||||||
|
@ -59,7 +59,7 @@ namespace Pal.Client.Net
|
|||||||
if (Service.Configuration.Mode != Configuration.EMode.Online)
|
if (Service.Configuration.Mode != Configuration.EMode.Online)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
var account = Account;
|
var account = Service.Configuration.FindAccount(RemoteUrl);
|
||||||
return account == null || account.CachedRoles.Contains(role);
|
return account == null || account.CachedRoles.Contains(role);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,16 +2,19 @@
|
|||||||
using Grpc.Net.Client;
|
using Grpc.Net.Client;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using Pal.Client.Extensions;
|
using Pal.Client.Extensions;
|
||||||
|
using Pal.Client.Configuration;
|
||||||
|
|
||||||
namespace Pal.Client.Net
|
namespace Pal.Client.Net
|
||||||
{
|
{
|
||||||
internal partial class RemoteApi : IDisposable
|
internal partial class RemoteApi : IDisposable
|
||||||
{
|
{
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
public static string RemoteUrl { get; } = "http://localhost:5145";
|
public const string RemoteUrl = "http://localhost:5145";
|
||||||
#else
|
#else
|
||||||
public static string RemoteUrl { get; } = "https://pal.μ.tv";
|
public const string RemoteUrl = "https://pal.μ.tv";
|
||||||
#endif
|
#endif
|
||||||
private readonly string _userAgent = $"{typeof(RemoteApi).Assembly.GetName().Name?.Replace(" ", "")}/{typeof(RemoteApi).Assembly.GetName().Version?.ToString(2)}";
|
private readonly string _userAgent = $"{typeof(RemoteApi).Assembly.GetName().Name?.Replace(" ", "")}/{typeof(RemoteApi).Assembly.GetName().Version?.ToString(2)}";
|
||||||
|
|
||||||
@ -21,24 +24,6 @@ namespace Pal.Client.Net
|
|||||||
private LoginInfo _loginInfo = new(null);
|
private LoginInfo _loginInfo = new(null);
|
||||||
private bool _warnedAboutUpgrade;
|
private bool _warnedAboutUpgrade;
|
||||||
|
|
||||||
public Configuration.AccountInfo? Account
|
|
||||||
{
|
|
||||||
get => Service.Configuration.Accounts.TryGetValue(RemoteUrl, out Configuration.AccountInfo? accountInfo) ? accountInfo : null;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (value != null)
|
|
||||||
Service.Configuration.Accounts[RemoteUrl] = value;
|
|
||||||
else
|
|
||||||
Service.Configuration.Accounts.Remove(RemoteUrl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Guid? AccountId => Account?.Id;
|
|
||||||
|
|
||||||
public string? PartialAccountId => Account?.Id?.ToPartialId();
|
|
||||||
|
|
||||||
private string FormattedPartialAccountId => PartialAccountId ?? "[no account id]";
|
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
PluginLog.Debug("Disposing gRPC channel");
|
PluginLog.Debug("Disposing gRPC channel");
|
||||||
|
@ -27,6 +27,9 @@ using System.Threading.Tasks;
|
|||||||
using Pal.Client.Extensions;
|
using Pal.Client.Extensions;
|
||||||
using Pal.Client.Properties;
|
using Pal.Client.Properties;
|
||||||
using ECommons;
|
using ECommons;
|
||||||
|
using ECommons.Schedulers;
|
||||||
|
using Pal.Client.Configuration;
|
||||||
|
using Pal.Client.Net;
|
||||||
|
|
||||||
namespace Pal.Client
|
namespace Pal.Client
|
||||||
{
|
{
|
||||||
@ -71,8 +74,10 @@ namespace Pal.Client
|
|||||||
|
|
||||||
pluginInterface.Create<Service>();
|
pluginInterface.Create<Service>();
|
||||||
Service.Plugin = this;
|
Service.Plugin = this;
|
||||||
Service.Configuration = (Configuration?)pluginInterface.GetPluginConfig() ?? pluginInterface.Create<Configuration>()!;
|
|
||||||
Service.Configuration.Migrate();
|
Service.ConfigurationManager = new(pluginInterface);
|
||||||
|
Service.ConfigurationManager.Migrate();
|
||||||
|
Service.Configuration = Service.ConfigurationManager.Load();
|
||||||
|
|
||||||
ResetRenderer();
|
ResetRenderer();
|
||||||
|
|
||||||
@ -146,7 +151,7 @@ namespace Pal.Client
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
configWindow.IsOpen = true;
|
configWindow.IsOpen = true;
|
||||||
configWindow.TestConnection();
|
var _ = new TickScheduler(() => configWindow.TestConnection());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
@ -196,6 +201,7 @@ namespace Pal.Client
|
|||||||
Service.Framework.Update -= OnFrameworkUpdate;
|
Service.Framework.Update -= OnFrameworkUpdate;
|
||||||
Service.Chat.ChatMessage -= OnChatMessage;
|
Service.Chat.ChatMessage -= OnChatMessage;
|
||||||
|
|
||||||
|
Service.WindowSystem.GetWindow<ConfigWindow>()?.Dispose();
|
||||||
Service.WindowSystem.RemoveAllWindows();
|
Service.WindowSystem.RemoveAllWindows();
|
||||||
|
|
||||||
Service.RemoteApi.Dispose();
|
Service.RemoteApi.Dispose();
|
||||||
@ -318,7 +324,7 @@ namespace Pal.Client
|
|||||||
var currentFloorMarkers = currentFloor.Markers;
|
var currentFloorMarkers = currentFloor.Markers;
|
||||||
|
|
||||||
bool updateSeenMarkers = false;
|
bool updateSeenMarkers = false;
|
||||||
var partialAccountId = Service.RemoteApi.PartialAccountId;
|
var partialAccountId = Service.Configuration.FindAccount(RemoteApi.RemoteUrl)?.AccountId.ToPartialId();
|
||||||
foreach (var visibleMarker in visibleMarkers)
|
foreach (var visibleMarker in visibleMarkers)
|
||||||
{
|
{
|
||||||
Marker? knownMarker = currentFloorMarkers.SingleOrDefault(x => x == visibleMarker);
|
Marker? knownMarker = currentFloorMarkers.SingleOrDefault(x => x == visibleMarker);
|
||||||
@ -343,7 +349,7 @@ namespace Pal.Client
|
|||||||
saveMarkers = true;
|
saveMarkers = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!recreateLayout && currentFloorMarkers.Count > 0 && (config.OnlyVisibleTrapsAfterPomander || config.OnlyVisibleHoardAfterPomander))
|
if (!recreateLayout && currentFloorMarkers.Count > 0 && (config.DeepDungeons.Traps.OnlyVisibleAfterPomander || config.DeepDungeons.HoardCoffers.OnlyVisibleAfterPomander))
|
||||||
{
|
{
|
||||||
|
|
||||||
try
|
try
|
||||||
@ -399,15 +405,15 @@ namespace Pal.Client
|
|||||||
List<IRenderElement> elements = new();
|
List<IRenderElement> elements = new();
|
||||||
foreach (var marker in currentFloorMarkers)
|
foreach (var marker in currentFloorMarkers)
|
||||||
{
|
{
|
||||||
if (marker.Seen || config.Mode == Configuration.EMode.Online || marker is { WasImported: true, Imports.Count: > 0 })
|
if (marker.Seen || config.Mode == EMode.Online || marker is { WasImported: true, Imports.Count: > 0 })
|
||||||
{
|
{
|
||||||
if (marker.Type == Marker.EType.Trap && config.ShowTraps)
|
if (marker.Type == Marker.EType.Trap)
|
||||||
{
|
{
|
||||||
CreateRenderElement(marker, elements, DetermineColor(marker, visibleMarkers));
|
CreateRenderElement(marker, elements, DetermineColor(marker, visibleMarkers), config.DeepDungeons.Traps);
|
||||||
}
|
}
|
||||||
else if (marker.Type == Marker.EType.Hoard && config.ShowHoard)
|
else if (marker.Type == Marker.EType.Hoard)
|
||||||
{
|
{
|
||||||
CreateRenderElement(marker, elements, DetermineColor(marker, visibleMarkers));
|
CreateRenderElement(marker, elements, DetermineColor(marker, visibleMarkers), config.DeepDungeons.HoardCoffers);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -436,9 +442,9 @@ namespace Pal.Client
|
|||||||
{
|
{
|
||||||
EphemeralMarkers.Add(marker);
|
EphemeralMarkers.Add(marker);
|
||||||
|
|
||||||
if (marker.Type == Marker.EType.SilverCoffer && config.ShowSilverCoffers)
|
if (marker.Type == Marker.EType.SilverCoffer && config.DeepDungeons.SilverCoffers.Show)
|
||||||
{
|
{
|
||||||
CreateRenderElement(marker, elements, DetermineColor(marker, visibleMarkers), config.FillSilverCoffers);
|
CreateRenderElement(marker, elements, DetermineColor(marker, visibleMarkers), config.DeepDungeons.SilverCoffers);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -453,12 +459,12 @@ namespace Pal.Client
|
|||||||
{
|
{
|
||||||
switch (marker.Type)
|
switch (marker.Type)
|
||||||
{
|
{
|
||||||
case Marker.EType.Trap when PomanderOfSight == PomanderState.Inactive || !Service.Configuration.OnlyVisibleTrapsAfterPomander || visibleMarkers.Any(x => x == marker):
|
case Marker.EType.Trap when PomanderOfSight == PomanderState.Inactive || !Service.Configuration.DeepDungeons.Traps.OnlyVisibleAfterPomander || visibleMarkers.Any(x => x == marker):
|
||||||
return ImGui.ColorConvertFloat4ToU32(Service.Configuration.TrapColor);
|
return Service.Configuration.DeepDungeons.Traps.Color;
|
||||||
case Marker.EType.Hoard when PomanderOfIntuition == PomanderState.Inactive || !Service.Configuration.OnlyVisibleHoardAfterPomander || visibleMarkers.Any(x => x == marker):
|
case Marker.EType.Hoard when PomanderOfIntuition == PomanderState.Inactive || !Service.Configuration.DeepDungeons.HoardCoffers.OnlyVisibleAfterPomander || visibleMarkers.Any(x => x == marker):
|
||||||
return ImGui.ColorConvertFloat4ToU32(Service.Configuration.HoardColor);
|
return Service.Configuration.DeepDungeons.HoardCoffers.Color;
|
||||||
case Marker.EType.SilverCoffer:
|
case Marker.EType.SilverCoffer:
|
||||||
return ImGui.ColorConvertFloat4ToU32(Service.Configuration.SilverCofferColor);
|
return Service.Configuration.DeepDungeons.SilverCoffers.Color;
|
||||||
case Marker.EType.Trap:
|
case Marker.EType.Trap:
|
||||||
case Marker.EType.Hoard:
|
case Marker.EType.Hoard:
|
||||||
return ColorInvisible;
|
return ColorInvisible;
|
||||||
@ -467,9 +473,12 @@ namespace Pal.Client
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CreateRenderElement(Marker marker, List<IRenderElement> elements, uint color, bool fill = false)
|
private void CreateRenderElement(Marker marker, List<IRenderElement> elements, uint color, MarkerConfiguration config)
|
||||||
{
|
{
|
||||||
var element = Renderer.CreateElement(marker.Type, marker.Position, color, fill);
|
if (!config.Show)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var element = Renderer.CreateElement(marker.Type, marker.Position, color, config.Fill);
|
||||||
marker.RenderElement = element;
|
marker.RenderElement = element;
|
||||||
elements.Add(element);
|
elements.Add(element);
|
||||||
}
|
}
|
||||||
@ -651,15 +660,15 @@ namespace Pal.Client
|
|||||||
|
|
||||||
internal void ResetRenderer()
|
internal void ResetRenderer()
|
||||||
{
|
{
|
||||||
if (Renderer is SplatoonRenderer && Service.Configuration.Renderer == Configuration.ERenderer.Splatoon)
|
if (Renderer is SplatoonRenderer && Service.Configuration.Renderer.SelectedRenderer == ERenderer.Splatoon)
|
||||||
return;
|
return;
|
||||||
else if (Renderer is SimpleRenderer && Service.Configuration.Renderer == Configuration.ERenderer.Simple)
|
else if (Renderer is SimpleRenderer && Service.Configuration.Renderer.SelectedRenderer == ERenderer.Simple)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (Renderer is IDisposable disposable)
|
if (Renderer is IDisposable disposable)
|
||||||
disposable.Dispose();
|
disposable.Dispose();
|
||||||
|
|
||||||
if (Service.Configuration.Renderer == Configuration.ERenderer.Splatoon)
|
if (Service.Configuration.Renderer.SelectedRenderer == ERenderer.Splatoon)
|
||||||
Renderer = new SplatoonRenderer(Service.PluginInterface, this);
|
Renderer = new SplatoonRenderer(Service.PluginInterface, this);
|
||||||
else
|
else
|
||||||
Renderer = new SimpleRenderer();
|
Renderer = new SimpleRenderer();
|
||||||
|
@ -120,7 +120,7 @@ namespace Pal.Client.Rendering
|
|||||||
{
|
{
|
||||||
case Marker.EType.Hoard:
|
case Marker.EType.Hoard:
|
||||||
// ignore distance if this is a found hoard coffer
|
// ignore distance if this is a found hoard coffer
|
||||||
if (Service.Plugin.PomanderOfIntuition == Plugin.PomanderState.Active && Service.Configuration.OnlyVisibleHoardAfterPomander)
|
if (Service.Plugin.PomanderOfIntuition == Plugin.PomanderState.Active && Service.Configuration.DeepDungeons.HoardCoffers.OnlyVisibleAfterPomander)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
goto case Marker.EType.Trap;
|
goto case Marker.EType.Trap;
|
||||||
|
@ -8,6 +8,7 @@ using System.Linq;
|
|||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using Pal.Client.Extensions;
|
using Pal.Client.Extensions;
|
||||||
using Pal.Client.Properties;
|
using Pal.Client.Properties;
|
||||||
|
using Pal.Client.Configuration;
|
||||||
|
|
||||||
namespace Pal.Client.Scheduled
|
namespace Pal.Client.Scheduled
|
||||||
{
|
{
|
||||||
@ -46,14 +47,14 @@ namespace Pal.Client.Scheduled
|
|||||||
}
|
}
|
||||||
|
|
||||||
config.ImportHistory.RemoveAll(hist => oldExportIds.Contains(hist.Id) || hist.Id == _exportId);
|
config.ImportHistory.RemoveAll(hist => oldExportIds.Contains(hist.Id) || hist.Id == _exportId);
|
||||||
config.ImportHistory.Add(new Configuration.ImportHistoryEntry
|
config.ImportHistory.Add(new ConfigurationV1.ImportHistoryEntry
|
||||||
{
|
{
|
||||||
Id = _exportId,
|
Id = _exportId,
|
||||||
RemoteUrl = _export.ServerUrl,
|
RemoteUrl = _export.ServerUrl,
|
||||||
ExportedAt = _export.CreatedAt.ToDateTime(),
|
ExportedAt = _export.CreatedAt.ToDateTime(),
|
||||||
ImportedAt = DateTime.UtcNow,
|
ImportedAt = DateTime.UtcNow,
|
||||||
});
|
});
|
||||||
config.Save();
|
Service.ConfigurationManager.Save(config);
|
||||||
|
|
||||||
recreateLayout = true;
|
recreateLayout = true;
|
||||||
saveMarkers = true;
|
saveMarkers = true;
|
||||||
|
@ -3,6 +3,8 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Pal.Client.Extensions;
|
||||||
|
using Pal.Client.Net;
|
||||||
using static Pal.Client.Plugin;
|
using static Pal.Client.Plugin;
|
||||||
|
|
||||||
namespace Pal.Client.Scheduled
|
namespace Pal.Client.Scheduled
|
||||||
@ -45,7 +47,7 @@ namespace Pal.Client.Scheduled
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case SyncType.MarkSeen:
|
case SyncType.MarkSeen:
|
||||||
var partialAccountId = Service.RemoteApi.PartialAccountId;
|
var partialAccountId = Service.Configuration.FindAccount(RemoteApi.RemoteUrl)?.AccountId.ToPartialId();
|
||||||
if (partialAccountId == null)
|
if (partialAccountId == null)
|
||||||
break;
|
break;
|
||||||
foreach (var remoteMarker in remoteMarkers)
|
foreach (var remoteMarker in remoteMarkers)
|
||||||
|
@ -8,6 +8,7 @@ using Dalamud.Game.Gui;
|
|||||||
using Dalamud.Interface.Windowing;
|
using Dalamud.Interface.Windowing;
|
||||||
using Dalamud.IoC;
|
using Dalamud.IoC;
|
||||||
using Dalamud.Plugin;
|
using Dalamud.Plugin;
|
||||||
|
using Pal.Client.Configuration;
|
||||||
using Pal.Client.Net;
|
using Pal.Client.Net;
|
||||||
|
|
||||||
namespace Pal.Client
|
namespace Pal.Client
|
||||||
@ -27,7 +28,8 @@ namespace Pal.Client
|
|||||||
internal static Plugin Plugin { get; set; } = null!;
|
internal static Plugin Plugin { get; set; } = null!;
|
||||||
internal static WindowSystem WindowSystem { get; } = new(typeof(Service).AssemblyQualifiedName);
|
internal static WindowSystem WindowSystem { get; } = new(typeof(Service).AssemblyQualifiedName);
|
||||||
internal static RemoteApi RemoteApi { get; } = new();
|
internal static RemoteApi RemoteApi { get; } = new();
|
||||||
internal static Configuration Configuration { get; set; } = null!;
|
internal static ConfigurationManager ConfigurationManager { get; set; } = null!;
|
||||||
|
internal static IPalacePalConfiguration Configuration { get; set; } = null!;
|
||||||
internal static Hooks Hooks { get; set; } = null!;
|
internal static Hooks Hooks { get; set; } = null!;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -69,7 +69,7 @@ namespace Pal.Client.Windows
|
|||||||
{
|
{
|
||||||
config.Mode = (Configuration.EMode)_choice;
|
config.Mode = (Configuration.EMode)_choice;
|
||||||
config.FirstUse = false;
|
config.FirstUse = false;
|
||||||
config.Save();
|
Service.ConfigurationManager.Save(config);
|
||||||
|
|
||||||
IsOpen = false;
|
IsOpen = false;
|
||||||
}
|
}
|
||||||
|
@ -19,23 +19,18 @@ using System.Text;
|
|||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Pal.Client.Properties;
|
using Pal.Client.Properties;
|
||||||
|
using Pal.Client.Configuration;
|
||||||
|
|
||||||
namespace Pal.Client.Windows
|
namespace Pal.Client.Windows
|
||||||
{
|
{
|
||||||
internal class ConfigWindow : Window, ILanguageChanged
|
internal class ConfigWindow : Window, ILanguageChanged, IDisposable
|
||||||
{
|
{
|
||||||
private const string WindowId = "###PalPalaceConfig";
|
private const string WindowId = "###PalPalaceConfig";
|
||||||
private int _mode;
|
private int _mode;
|
||||||
private int _renderer;
|
private int _renderer;
|
||||||
private bool _showTraps;
|
private ConfigurableMarker _trapConfig = new();
|
||||||
private Vector4 _trapColor;
|
private ConfigurableMarker _hoardConfig = new();
|
||||||
private bool _onlyVisibleTrapsAfterPomander;
|
private ConfigurableMarker _silverConfig = new();
|
||||||
private bool _showHoard;
|
|
||||||
private Vector4 _hoardColor;
|
|
||||||
private bool _onlyVisibleHoardAfterPomander;
|
|
||||||
private bool _showSilverCoffers;
|
|
||||||
private Vector4 _silverCofferColor;
|
|
||||||
private bool _fillSilverCoffers;
|
|
||||||
|
|
||||||
private string? _connectionText;
|
private string? _connectionText;
|
||||||
private bool _switchToCommunityTab;
|
private bool _switchToCommunityTab;
|
||||||
@ -67,20 +62,19 @@ namespace Pal.Client.Windows
|
|||||||
WindowName = $"{Localization.Palace_Pal} v{version}{WindowId}";
|
WindowName = $"{Localization.Palace_Pal} v{version}{WindowId}";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
_testConnectionCts?.Cancel();
|
||||||
|
}
|
||||||
|
|
||||||
public override void OnOpen()
|
public override void OnOpen()
|
||||||
{
|
{
|
||||||
var config = Service.Configuration;
|
var config = Service.Configuration;
|
||||||
_mode = (int)config.Mode;
|
_mode = (int)config.Mode;
|
||||||
_renderer = (int)config.Renderer;
|
_renderer = (int)config.Renderer.SelectedRenderer;
|
||||||
_showTraps = config.ShowTraps;
|
_trapConfig = new ConfigurableMarker(config.DeepDungeons.Traps);
|
||||||
_trapColor = config.TrapColor;
|
_hoardConfig = new ConfigurableMarker(config.DeepDungeons.HoardCoffers);
|
||||||
_onlyVisibleTrapsAfterPomander = config.OnlyVisibleTrapsAfterPomander;
|
_silverConfig = new ConfigurableMarker(config.DeepDungeons.SilverCoffers);
|
||||||
_showHoard = config.ShowHoard;
|
|
||||||
_hoardColor = config.HoardColor;
|
|
||||||
_onlyVisibleHoardAfterPomander = config.OnlyVisibleHoardAfterPomander;
|
|
||||||
_showSilverCoffers = config.ShowSilverCoffers;
|
|
||||||
_silverCofferColor = config.SilverCofferColor;
|
|
||||||
_fillSilverCoffers = config.FillSilverCoffers;
|
|
||||||
_connectionText = null;
|
_connectionText = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -113,18 +107,13 @@ namespace Pal.Client.Windows
|
|||||||
if (save || saveAndClose)
|
if (save || saveAndClose)
|
||||||
{
|
{
|
||||||
var config = Service.Configuration;
|
var config = Service.Configuration;
|
||||||
config.Mode = (Configuration.EMode)_mode;
|
config.Mode = (EMode)_mode;
|
||||||
config.Renderer = (Configuration.ERenderer)_renderer;
|
config.Renderer.SelectedRenderer = (ERenderer)_renderer;
|
||||||
config.ShowTraps = _showTraps;
|
config.DeepDungeons.Traps = _trapConfig.Build();
|
||||||
config.TrapColor = _trapColor;
|
config.DeepDungeons.HoardCoffers = _hoardConfig.Build();
|
||||||
config.OnlyVisibleTrapsAfterPomander = _onlyVisibleTrapsAfterPomander;
|
config.DeepDungeons.SilverCoffers = _silverConfig.Build();
|
||||||
config.ShowHoard = _showHoard;
|
|
||||||
config.HoardColor = _hoardColor;
|
Service.ConfigurationManager.Save(config);
|
||||||
config.OnlyVisibleHoardAfterPomander = _onlyVisibleHoardAfterPomander;
|
|
||||||
config.ShowSilverCoffers = _showSilverCoffers;
|
|
||||||
config.SilverCofferColor = _silverCofferColor;
|
|
||||||
config.FillSilverCoffers = _fillSilverCoffers;
|
|
||||||
config.Save();
|
|
||||||
|
|
||||||
if (saveAndClose)
|
if (saveAndClose)
|
||||||
IsOpen = false;
|
IsOpen = false;
|
||||||
@ -135,12 +124,12 @@ namespace Pal.Client.Windows
|
|||||||
{
|
{
|
||||||
if (ImGui.BeginTabItem($"{Localization.ConfigTab_DeepDungeons}###TabDeepDungeons"))
|
if (ImGui.BeginTabItem($"{Localization.ConfigTab_DeepDungeons}###TabDeepDungeons"))
|
||||||
{
|
{
|
||||||
ImGui.Checkbox(Localization.Config_Traps_Show, ref _showTraps);
|
ImGui.Checkbox(Localization.Config_Traps_Show, ref _trapConfig.Show);
|
||||||
ImGui.Indent();
|
ImGui.Indent();
|
||||||
ImGui.BeginDisabled(!_showTraps);
|
ImGui.BeginDisabled(!_trapConfig.Show);
|
||||||
ImGui.Spacing();
|
ImGui.Spacing();
|
||||||
ImGui.ColorEdit4(Localization.Config_Traps_Color, ref _trapColor, ImGuiColorEditFlags.NoInputs);
|
ImGui.ColorEdit4(Localization.Config_Traps_Color, ref _trapConfig.Color, ImGuiColorEditFlags.NoInputs);
|
||||||
ImGui.Checkbox(Localization.Config_Traps_HideImpossible, ref _onlyVisibleTrapsAfterPomander);
|
ImGui.Checkbox(Localization.Config_Traps_HideImpossible, ref _trapConfig.OnlyVisibleAfterPomander);
|
||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
ImGuiComponents.HelpMarker(Localization.Config_Traps_HideImpossible_ToolTip);
|
ImGuiComponents.HelpMarker(Localization.Config_Traps_HideImpossible_ToolTip);
|
||||||
ImGui.EndDisabled();
|
ImGui.EndDisabled();
|
||||||
@ -148,12 +137,12 @@ namespace Pal.Client.Windows
|
|||||||
|
|
||||||
ImGui.Separator();
|
ImGui.Separator();
|
||||||
|
|
||||||
ImGui.Checkbox(Localization.Config_HoardCoffers_Show, ref _showHoard);
|
ImGui.Checkbox(Localization.Config_HoardCoffers_Show, ref _hoardConfig.Show);
|
||||||
ImGui.Indent();
|
ImGui.Indent();
|
||||||
ImGui.BeginDisabled(!_showHoard);
|
ImGui.BeginDisabled(!_hoardConfig.Show);
|
||||||
ImGui.Spacing();
|
ImGui.Spacing();
|
||||||
ImGui.ColorEdit4(Localization.Config_HoardCoffers_Color, ref _hoardColor, ImGuiColorEditFlags.NoInputs);
|
ImGui.ColorEdit4(Localization.Config_HoardCoffers_Color, ref _hoardConfig.Color, ImGuiColorEditFlags.NoInputs);
|
||||||
ImGui.Checkbox(Localization.Config_HoardCoffers_HideImpossible, ref _onlyVisibleHoardAfterPomander);
|
ImGui.Checkbox(Localization.Config_HoardCoffers_HideImpossible, ref _hoardConfig.OnlyVisibleAfterPomander);
|
||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
ImGuiComponents.HelpMarker(Localization.Config_HoardCoffers_HideImpossible_ToolTip);
|
ImGuiComponents.HelpMarker(Localization.Config_HoardCoffers_HideImpossible_ToolTip);
|
||||||
ImGui.EndDisabled();
|
ImGui.EndDisabled();
|
||||||
@ -161,13 +150,13 @@ namespace Pal.Client.Windows
|
|||||||
|
|
||||||
ImGui.Separator();
|
ImGui.Separator();
|
||||||
|
|
||||||
ImGui.Checkbox(Localization.Config_SilverCoffer_Show, ref _showSilverCoffers);
|
ImGui.Checkbox(Localization.Config_SilverCoffer_Show, ref _silverConfig.Show);
|
||||||
ImGuiComponents.HelpMarker(Localization.Config_SilverCoffers_ToolTip);
|
ImGuiComponents.HelpMarker(Localization.Config_SilverCoffers_ToolTip);
|
||||||
ImGui.Indent();
|
ImGui.Indent();
|
||||||
ImGui.BeginDisabled(!_showSilverCoffers);
|
ImGui.BeginDisabled(!_silverConfig.Show);
|
||||||
ImGui.Spacing();
|
ImGui.Spacing();
|
||||||
ImGui.ColorEdit4(Localization.Config_SilverCoffer_Color, ref _silverCofferColor, ImGuiColorEditFlags.NoInputs);
|
ImGui.ColorEdit4(Localization.Config_SilverCoffer_Color, ref _silverConfig.Color, ImGuiColorEditFlags.NoInputs);
|
||||||
ImGui.Checkbox(Localization.Config_SilverCoffer_Filled, ref _fillSilverCoffers);
|
ImGui.Checkbox(Localization.Config_SilverCoffer_Filled, ref _silverConfig.Fill);
|
||||||
ImGui.EndDisabled();
|
ImGui.EndDisabled();
|
||||||
ImGui.Unindent();
|
ImGui.Unindent();
|
||||||
|
|
||||||
@ -190,13 +179,13 @@ namespace Pal.Client.Windows
|
|||||||
ImGui.TextWrapped(Localization.Explanation_3);
|
ImGui.TextWrapped(Localization.Explanation_3);
|
||||||
ImGui.TextWrapped(Localization.Explanation_4);
|
ImGui.TextWrapped(Localization.Explanation_4);
|
||||||
|
|
||||||
ImGui.RadioButton(Localization.Config_UploadMyDiscoveries_ShowOtherTraps, ref _mode, (int)Configuration.EMode.Online);
|
ImGui.RadioButton(Localization.Config_UploadMyDiscoveries_ShowOtherTraps, ref _mode, (int)EMode.Online);
|
||||||
ImGui.RadioButton(Localization.Config_NeverUploadDiscoveries_ShowMyTraps, ref _mode, (int)Configuration.EMode.Offline);
|
ImGui.RadioButton(Localization.Config_NeverUploadDiscoveries_ShowMyTraps, ref _mode, (int)EMode.Offline);
|
||||||
saveAndClose = ImGui.Button(Localization.SaveAndClose);
|
saveAndClose = ImGui.Button(Localization.SaveAndClose);
|
||||||
|
|
||||||
ImGui.Separator();
|
ImGui.Separator();
|
||||||
|
|
||||||
ImGui.BeginDisabled(Service.Configuration.Mode != Configuration.EMode.Online);
|
ImGui.BeginDisabled(Service.Configuration.Mode != EMode.Online);
|
||||||
if (ImGui.Button(Localization.Config_TestConnection))
|
if (ImGui.Button(Localization.Config_TestConnection))
|
||||||
TestConnection();
|
TestConnection();
|
||||||
|
|
||||||
@ -294,8 +283,8 @@ namespace Pal.Client.Windows
|
|||||||
if (ImGui.BeginTabItem($"{Localization.ConfigTab_Renderer}###TabRenderer"))
|
if (ImGui.BeginTabItem($"{Localization.ConfigTab_Renderer}###TabRenderer"))
|
||||||
{
|
{
|
||||||
ImGui.Text(Localization.Config_SelectRenderBackend);
|
ImGui.Text(Localization.Config_SelectRenderBackend);
|
||||||
ImGui.RadioButton($"{Localization.Config_Renderer_Splatoon} ({Localization.Config_Renderer_Splatoon_Hint})", ref _renderer, (int)Configuration.ERenderer.Splatoon);
|
ImGui.RadioButton($"{Localization.Config_Renderer_Splatoon} ({Localization.Config_Renderer_Splatoon_Hint})", ref _renderer, (int)ERenderer.Splatoon);
|
||||||
ImGui.RadioButton($"{Localization.Config_Renderer_Simple} ({Localization.Config_Renderer_Simple_Hint})", ref _renderer, (int)Configuration.ERenderer.Simple);
|
ImGui.RadioButton($"{Localization.Config_Renderer_Simple} ({Localization.Config_Renderer_Simple_Hint})", ref _renderer, (int)ERenderer.Simple);
|
||||||
|
|
||||||
ImGui.Separator();
|
ImGui.Separator();
|
||||||
|
|
||||||
@ -307,7 +296,7 @@ namespace Pal.Client.Windows
|
|||||||
ImGui.Text(Localization.Config_Splatoon_Test);
|
ImGui.Text(Localization.Config_Splatoon_Test);
|
||||||
ImGui.BeginDisabled(!(Service.Plugin.Renderer is IDrawDebugItems));
|
ImGui.BeginDisabled(!(Service.Plugin.Renderer is IDrawDebugItems));
|
||||||
if (ImGui.Button(Localization.Config_Splatoon_DrawCircles))
|
if (ImGui.Button(Localization.Config_Splatoon_DrawCircles))
|
||||||
(Service.Plugin.Renderer as IDrawDebugItems)?.DrawDebugItems(_trapColor, _hoardColor);
|
(Service.Plugin.Renderer as IDrawDebugItems)?.DrawDebugItems(_trapConfig.Color, _hoardConfig.Color);
|
||||||
ImGui.EndDisabled();
|
ImGui.EndDisabled();
|
||||||
|
|
||||||
ImGui.EndTabItem();
|
ImGui.EndTabItem();
|
||||||
@ -328,17 +317,17 @@ namespace Pal.Client.Windows
|
|||||||
ImGui.Indent();
|
ImGui.Indent();
|
||||||
if (plugin.FloorMarkers.TryGetValue(plugin.LastTerritory, out var currentFloor))
|
if (plugin.FloorMarkers.TryGetValue(plugin.LastTerritory, out var currentFloor))
|
||||||
{
|
{
|
||||||
if (_showTraps)
|
if (_trapConfig.Show)
|
||||||
{
|
{
|
||||||
int traps = currentFloor.Markers.Count(x => x.Type == Marker.EType.Trap);
|
int traps = currentFloor.Markers.Count(x => x.Type == Marker.EType.Trap);
|
||||||
ImGui.Text($"{traps} known trap{(traps == 1 ? "" : "s")}");
|
ImGui.Text($"{traps} known trap{(traps == 1 ? "" : "s")}");
|
||||||
}
|
}
|
||||||
if (_showHoard)
|
if (_hoardConfig.Show)
|
||||||
{
|
{
|
||||||
int hoardCoffers = currentFloor.Markers.Count(x => x.Type == Marker.EType.Hoard);
|
int hoardCoffers = currentFloor.Markers.Count(x => x.Type == Marker.EType.Hoard);
|
||||||
ImGui.Text($"{hoardCoffers} known hoard coffer{(hoardCoffers == 1 ? "" : "s")}");
|
ImGui.Text($"{hoardCoffers} known hoard coffer{(hoardCoffers == 1 ? "" : "s")}");
|
||||||
}
|
}
|
||||||
if (_showSilverCoffers)
|
if (_silverConfig.Show)
|
||||||
{
|
{
|
||||||
int silverCoffers = plugin.EphemeralMarkers.Count(x => x.Type == Marker.EType.SilverCoffer);
|
int silverCoffers = plugin.EphemeralMarkers.Count(x => x.Type == Marker.EType.SilverCoffer);
|
||||||
ImGui.Text($"{silverCoffers} silver coffer{(silverCoffers == 1 ? "" : "s")} visible on current floor");
|
ImGui.Text($"{silverCoffers} silver coffer{(silverCoffers == 1 ? "" : "s")} visible on current floor");
|
||||||
@ -440,5 +429,36 @@ namespace Pal.Client.Windows
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class ConfigurableMarker
|
||||||
|
{
|
||||||
|
public bool Show;
|
||||||
|
public Vector4 Color;
|
||||||
|
public bool OnlyVisibleAfterPomander;
|
||||||
|
public bool Fill;
|
||||||
|
|
||||||
|
public ConfigurableMarker()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConfigurableMarker(MarkerConfiguration config)
|
||||||
|
{
|
||||||
|
Show = config.Show;
|
||||||
|
Color = ImGui.ColorConvertU32ToFloat4(config.Color);
|
||||||
|
OnlyVisibleAfterPomander = config.OnlyVisibleAfterPomander;
|
||||||
|
Fill = config.Fill;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MarkerConfiguration Build()
|
||||||
|
{
|
||||||
|
return new MarkerConfiguration
|
||||||
|
{
|
||||||
|
Show = Show,
|
||||||
|
Color = ImGui.ColorConvertFloat4ToU32(Color),
|
||||||
|
OnlyVisibleAfterPomander = OnlyVisibleAfterPomander,
|
||||||
|
Fill = Fill
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user