mirror of
https://github.com/goatcorp/Dalamud.git
synced 2025-12-12 18:27:23 +01:00
Merge branch 'master' into master
This commit is contained in:
commit
2a9e395805
41 changed files with 716 additions and 1223 deletions
|
|
@ -14,10 +14,10 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Label="Feature">
|
<PropertyGroup Label="Feature">
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
<AssemblyVersion>4.8.5.0</AssemblyVersion>
|
<AssemblyVersion>4.8.8.0</AssemblyVersion>
|
||||||
<FileVersion>4.8.5.0</FileVersion>
|
<FileVersion>4.8.8.0</FileVersion>
|
||||||
<Description>XIVLauncher addon injection</Description>
|
<Description>XIVLauncher addon injection</Description>
|
||||||
<Version>4.8.5.0</Version>
|
<Version>4.8.8.0</Version>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||||
<DocumentationFile></DocumentationFile>
|
<DocumentationFile></DocumentationFile>
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,8 @@ using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace Dalamud.Injector {
|
namespace Dalamud.Injector {
|
||||||
internal static class Program {
|
internal static class Program {
|
||||||
|
static private Process process = null;
|
||||||
|
|
||||||
private static void Main(string[] args) {
|
private static void Main(string[] args) {
|
||||||
#if !DEBUG
|
#if !DEBUG
|
||||||
AppDomain.CurrentDomain.UnhandledException += delegate(object sender, UnhandledExceptionEventArgs eventArgs)
|
AppDomain.CurrentDomain.UnhandledException += delegate(object sender, UnhandledExceptionEventArgs eventArgs)
|
||||||
|
|
@ -25,9 +27,10 @@ namespace Dalamud.Injector {
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
var pid = int.Parse(args[0]);
|
var pid = -1;
|
||||||
|
if (args.Length == 1) {
|
||||||
Process process = null;
|
pid = int.Parse(args[0]);
|
||||||
|
}
|
||||||
|
|
||||||
switch (pid) {
|
switch (pid) {
|
||||||
case -1:
|
case -1:
|
||||||
|
|
@ -45,10 +48,12 @@ namespace Dalamud.Injector {
|
||||||
}
|
}
|
||||||
|
|
||||||
DalamudStartInfo startInfo;
|
DalamudStartInfo startInfo;
|
||||||
if (args.Length == 1) {
|
if (args.Length <= 1) {
|
||||||
startInfo = GetDefaultStartInfo();
|
startInfo = GetDefaultStartInfo();
|
||||||
Console.WriteLine("\nA Dalamud start info was not found in the program arguments. One has been generated for you.");
|
Console.WriteLine("\nA Dalamud start info was not found in the program arguments. One has been generated for you.");
|
||||||
Console.WriteLine("\nCopy the following contents into the program arguments:");
|
Console.WriteLine("\nCopy the following contents into the program arguments:");
|
||||||
|
Console.WriteLine();
|
||||||
|
Console.WriteLine(Convert.ToBase64String(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(startInfo))));
|
||||||
} else {
|
} else {
|
||||||
startInfo = JsonConvert.DeserializeObject<DalamudStartInfo>(Encoding.UTF8.GetString(Convert.FromBase64String(args[1])));
|
startInfo = JsonConvert.DeserializeObject<DalamudStartInfo>(Encoding.UTF8.GetString(Convert.FromBase64String(args[1])));
|
||||||
}
|
}
|
||||||
|
|
@ -80,6 +85,7 @@ namespace Dalamud.Injector {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static DalamudStartInfo GetDefaultStartInfo() {
|
private static DalamudStartInfo GetDefaultStartInfo() {
|
||||||
|
var ffxivDir = Path.GetDirectoryName(process.MainModule.FileName);
|
||||||
var startInfo = new DalamudStartInfo {
|
var startInfo = new DalamudStartInfo {
|
||||||
WorkingDirectory = null,
|
WorkingDirectory = null,
|
||||||
ConfigurationPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) +
|
ConfigurationPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) +
|
||||||
|
|
@ -89,7 +95,7 @@ namespace Dalamud.Injector {
|
||||||
DefaultPluginDirectory = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) +
|
DefaultPluginDirectory = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) +
|
||||||
@"\XIVLauncher\devPlugins",
|
@"\XIVLauncher\devPlugins",
|
||||||
|
|
||||||
GameVersion = File.ReadAllText(@"C:\Program Files (x86)\SquareEnix\FINAL FANTASY XIV - A Realm Reborn\game\ffxivgame.ver"),
|
GameVersion = File.ReadAllText(Path.Combine(ffxivDir, "ffxivgame.ver")),
|
||||||
Language = ClientLanguage.English
|
Language = ClientLanguage.English
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,14 +27,25 @@ namespace Dalamud
|
||||||
|
|
||||||
public Dictionary<int, PreferredRole> PreferredRoleReminders { get; set; }
|
public Dictionary<int, PreferredRole> PreferredRoleReminders { get; set; }
|
||||||
|
|
||||||
|
public string LanguageOverride { get; set; }
|
||||||
|
|
||||||
public string LastVersion { get; set; }
|
public string LastVersion { get; set; }
|
||||||
|
|
||||||
|
[JsonIgnore]
|
||||||
|
public string ConfigPath;
|
||||||
|
|
||||||
public static DalamudConfiguration Load(string path) {
|
public static DalamudConfiguration Load(string path) {
|
||||||
return JsonConvert.DeserializeObject<DalamudConfiguration>(File.ReadAllText(path));
|
var deserialized = JsonConvert.DeserializeObject<DalamudConfiguration>(File.ReadAllText(path));
|
||||||
|
deserialized.ConfigPath = path;
|
||||||
|
|
||||||
|
return deserialized;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Save(string path) {
|
/// <summary>
|
||||||
File.WriteAllText(path, JsonConvert.SerializeObject(this, Formatting.Indented));
|
/// Save the configuration at the path it was loaded from.
|
||||||
|
/// </summary>
|
||||||
|
public void Save() {
|
||||||
|
File.WriteAllText(this.ConfigPath, JsonConvert.SerializeObject(this, Formatting.Indented));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,10 @@ using Dalamud.Game.Network;
|
||||||
using Dalamud.Interface;
|
using Dalamud.Interface;
|
||||||
using Dalamud.Plugin;
|
using Dalamud.Plugin;
|
||||||
using ImGuiNET;
|
using ImGuiNET;
|
||||||
|
using Newtonsoft.Json;
|
||||||
using Serilog;
|
using Serilog;
|
||||||
|
using Serilog.Core;
|
||||||
|
using Serilog.Events;
|
||||||
|
|
||||||
namespace Dalamud {
|
namespace Dalamud {
|
||||||
public sealed class Dalamud : IDisposable {
|
public sealed class Dalamud : IDisposable {
|
||||||
|
|
@ -36,13 +39,13 @@ namespace Dalamud {
|
||||||
|
|
||||||
public readonly Framework Framework;
|
public readonly Framework Framework;
|
||||||
|
|
||||||
public readonly CommandManager CommandManager;
|
public CommandManager CommandManager { get; private set; }
|
||||||
|
|
||||||
public readonly ChatHandlers ChatHandlers;
|
public ChatHandlers ChatHandlers { get; private set; }
|
||||||
|
|
||||||
public readonly NetworkHandlers NetworkHandlers;
|
public NetworkHandlers NetworkHandlers { get; private set; }
|
||||||
|
|
||||||
public readonly DiscordBotManager BotManager;
|
public DiscordBotManager BotManager { get; private set; }
|
||||||
|
|
||||||
public PluginManager PluginManager { get; private set; }
|
public PluginManager PluginManager { get; private set; }
|
||||||
public PluginRepository PluginRepository { get; private set; }
|
public PluginRepository PluginRepository { get; private set; }
|
||||||
|
|
@ -50,31 +53,29 @@ namespace Dalamud {
|
||||||
public readonly ClientState ClientState;
|
public readonly ClientState ClientState;
|
||||||
|
|
||||||
public readonly DalamudStartInfo StartInfo;
|
public readonly DalamudStartInfo StartInfo;
|
||||||
|
private readonly LoggingLevelSwitch loggingLevelSwitch;
|
||||||
|
|
||||||
public readonly DalamudConfiguration Configuration;
|
public readonly DalamudConfiguration Configuration;
|
||||||
|
|
||||||
private readonly WinSockHandlers WinSock2;
|
private readonly WinSockHandlers WinSock2;
|
||||||
|
|
||||||
public readonly InterfaceManager InterfaceManager;
|
public InterfaceManager InterfaceManager { get; private set; }
|
||||||
|
|
||||||
public readonly DataManager Data;
|
public DataManager Data { get; private set; }
|
||||||
|
|
||||||
private AntiDebug antiDebug;
|
|
||||||
|
|
||||||
|
|
||||||
private Localization localizationMgr;
|
private Localization localizationMgr;
|
||||||
|
|
||||||
|
public bool IsReady { get; private set; }
|
||||||
|
|
||||||
private readonly string assemblyVersion = Assembly.GetAssembly(typeof(ChatHandlers)).GetName().Version.ToString();
|
private readonly string assemblyVersion = Assembly.GetAssembly(typeof(ChatHandlers)).GetName().Version.ToString();
|
||||||
|
|
||||||
public Dalamud(DalamudStartInfo info) {
|
public Dalamud(DalamudStartInfo info, LoggingLevelSwitch loggingLevelSwitch) {
|
||||||
this.StartInfo = info;
|
this.StartInfo = info;
|
||||||
|
this.loggingLevelSwitch = loggingLevelSwitch;
|
||||||
this.localizationMgr = new Localization(this.StartInfo.WorkingDirectory);
|
|
||||||
this.localizationMgr.SetupWithUiCulture();
|
|
||||||
|
|
||||||
this.Configuration = DalamudConfiguration.Load(info.ConfigurationPath);
|
this.Configuration = DalamudConfiguration.Load(info.ConfigurationPath);
|
||||||
|
|
||||||
this.baseDirectory = info.WorkingDirectory;
|
this.baseDirectory = info.WorkingDirectory;
|
||||||
|
|
||||||
this.unloadSignal = new ManualResetEvent(false);
|
this.unloadSignal = new ManualResetEvent(false);
|
||||||
|
|
@ -86,50 +87,61 @@ namespace Dalamud {
|
||||||
// Initialize game subsystem
|
// Initialize game subsystem
|
||||||
this.Framework = new Framework(this.SigScanner, this);
|
this.Framework = new Framework(this.SigScanner, this);
|
||||||
|
|
||||||
// Initialize managers. Basically handlers for the logic
|
|
||||||
this.CommandManager = new CommandManager(this, info.Language);
|
|
||||||
SetupCommands();
|
|
||||||
|
|
||||||
this.ChatHandlers = new ChatHandlers(this);
|
|
||||||
this.NetworkHandlers = new NetworkHandlers(this, this.Configuration.OptOutMbCollection);
|
|
||||||
|
|
||||||
this.Data = new DataManager(this.StartInfo.Language);
|
|
||||||
this.Data.Initialize();
|
|
||||||
|
|
||||||
this.ClientState = new ClientState(this, info, this.SigScanner);
|
this.ClientState = new ClientState(this, info, this.SigScanner);
|
||||||
|
|
||||||
this.BotManager = new DiscordBotManager(this, this.Configuration.DiscordFeatureConfig);
|
|
||||||
|
|
||||||
this.WinSock2 = new WinSockHandlers();
|
this.WinSock2 = new WinSockHandlers();
|
||||||
|
|
||||||
try {
|
AssetManager.EnsureAssets(this.baseDirectory).ContinueWith(async task => {
|
||||||
this.InterfaceManager = new InterfaceManager(this, this.SigScanner);
|
this.localizationMgr = new Localization(this.StartInfo.WorkingDirectory);
|
||||||
this.InterfaceManager.OnDraw += BuildDalamudUi;
|
if (!string.IsNullOrEmpty(this.Configuration.LanguageOverride)) {
|
||||||
} catch (Exception e) {
|
this.localizationMgr.SetupWithLangCode(this.Configuration.LanguageOverride);
|
||||||
Log.Information(e, "Could not init interface.");
|
} else {
|
||||||
}
|
this.localizationMgr.SetupWithUiCulture();
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
this.InterfaceManager = new InterfaceManager(this, this.SigScanner);
|
||||||
|
this.InterfaceManager.OnDraw += BuildDalamudUi;
|
||||||
|
|
||||||
|
this.InterfaceManager.Enable();
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.Information(e, "Could not init interface.");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Data = new DataManager(this.StartInfo.Language);
|
||||||
|
await this.Data.Initialize(this.baseDirectory);
|
||||||
|
|
||||||
|
this.NetworkHandlers = new NetworkHandlers(this, this.Configuration.OptOutMbCollection);
|
||||||
|
|
||||||
|
// Initialize managers. Basically handlers for the logic
|
||||||
|
this.CommandManager = new CommandManager(this, info.Language);
|
||||||
|
SetupCommands();
|
||||||
|
|
||||||
|
this.ChatHandlers = new ChatHandlers(this);
|
||||||
|
|
||||||
|
// Discord Bot Manager
|
||||||
|
this.BotManager = new DiscordBotManager(this, this.Configuration.DiscordFeatureConfig);
|
||||||
|
this.BotManager.Start();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
this.PluginManager = new PluginManager(this, this.StartInfo.PluginDirectory, this.StartInfo.DefaultPluginDirectory);
|
||||||
|
this.PluginManager.LoadPlugins();
|
||||||
|
|
||||||
|
this.PluginRepository = new PluginRepository(PluginManager, this.StartInfo.PluginDirectory, this.StartInfo.GameVersion);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Log.Error(ex, "Plugin load failed.");
|
||||||
|
}
|
||||||
|
|
||||||
|
IsReady = true;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Start() {
|
public void Start() {
|
||||||
try {
|
|
||||||
this.InterfaceManager?.Enable();
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.Information("Could not enable interface.");
|
|
||||||
}
|
|
||||||
|
|
||||||
this.Framework.Enable();
|
this.Framework.Enable();
|
||||||
this.ClientState.Enable();
|
this.ClientState.Enable();
|
||||||
|
|
||||||
this.BotManager.Start();
|
|
||||||
|
|
||||||
try {
|
|
||||||
this.PluginManager = new PluginManager(this, this.StartInfo.PluginDirectory, this.StartInfo.DefaultPluginDirectory);
|
|
||||||
this.PluginManager.LoadPlugins();
|
|
||||||
|
|
||||||
PluginRepository = new PluginRepository(PluginManager, this.StartInfo.PluginDirectory, this.StartInfo.GameVersion);
|
|
||||||
} catch (Exception ex) {
|
|
||||||
Log.Error(ex, "Plugin load failed.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Unload() {
|
public void Unload() {
|
||||||
|
|
@ -145,7 +157,7 @@ namespace Dalamud {
|
||||||
// due to rendering happening on another thread, where a plugin might receive
|
// due to rendering happening on another thread, where a plugin might receive
|
||||||
// a render call after it has been disposed, which can crash if it attempts to
|
// a render call after it has been disposed, which can crash if it attempts to
|
||||||
// use any resources that it freed in its own Dispose method
|
// use any resources that it freed in its own Dispose method
|
||||||
this.InterfaceManager.Dispose();
|
this.InterfaceManager?.Dispose();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
@ -166,8 +178,6 @@ namespace Dalamud {
|
||||||
this.WinSock2.Dispose();
|
this.WinSock2.Dispose();
|
||||||
|
|
||||||
this.SigScanner.Dispose();
|
this.SigScanner.Dispose();
|
||||||
|
|
||||||
this.antiDebug?.Dispose();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Interface
|
#region Interface
|
||||||
|
|
@ -180,8 +190,6 @@ namespace Dalamud {
|
||||||
private bool isImguiDrawDevMenu = false;
|
private bool isImguiDrawDevMenu = false;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
private bool isAntiDebugEnabled = false;
|
|
||||||
|
|
||||||
private bool isImguiDrawLogWindow = false;
|
private bool isImguiDrawLogWindow = false;
|
||||||
private bool isImguiDrawDataWindow = false;
|
private bool isImguiDrawDataWindow = false;
|
||||||
private bool isImguiDrawPluginWindow = false;
|
private bool isImguiDrawPluginWindow = false;
|
||||||
|
|
@ -207,6 +215,18 @@ namespace Dalamud {
|
||||||
this.logWindow = new DalamudLogWindow();
|
this.logWindow = new DalamudLogWindow();
|
||||||
this.isImguiDrawLogWindow = true;
|
this.isImguiDrawLogWindow = true;
|
||||||
}
|
}
|
||||||
|
if (ImGui.BeginMenu("Set log level..."))
|
||||||
|
{
|
||||||
|
foreach (var logLevel in Enum.GetValues(typeof(LogEventLevel)).Cast<LogEventLevel>()) {
|
||||||
|
if (ImGui.MenuItem(logLevel + "##logLevelSwitch", "", this.loggingLevelSwitch.MinimumLevel == logLevel))
|
||||||
|
{
|
||||||
|
this.loggingLevelSwitch.MinimumLevel = logLevel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.EndMenu();
|
||||||
|
}
|
||||||
|
ImGui.Separator();
|
||||||
if (ImGui.MenuItem("Open Data window"))
|
if (ImGui.MenuItem("Open Data window"))
|
||||||
{
|
{
|
||||||
this.dataWindow = new DalamudDataWindow(this);
|
this.dataWindow = new DalamudDataWindow(this);
|
||||||
|
|
@ -220,15 +240,8 @@ namespace Dalamud {
|
||||||
this.isImguiDrawCreditsWindow = true;
|
this.isImguiDrawCreditsWindow = true;
|
||||||
}
|
}
|
||||||
ImGui.MenuItem("Draw ImGui demo", "", ref this.isImguiDrawDemoWindow);
|
ImGui.MenuItem("Draw ImGui demo", "", ref this.isImguiDrawDemoWindow);
|
||||||
ImGui.Separator();
|
if (ImGui.MenuItem("Dump ImGui info"))
|
||||||
if (ImGui.MenuItem("Enable AntiDebug", "", ref this.isAntiDebugEnabled)) {
|
OnDebugImInfoCommand(null, null);
|
||||||
if (this.isAntiDebugEnabled) {
|
|
||||||
this.antiDebug = new AntiDebug();
|
|
||||||
this.antiDebug.Enable();
|
|
||||||
} else {
|
|
||||||
this.antiDebug?.Dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ImGui.Separator();
|
ImGui.Separator();
|
||||||
if (ImGui.MenuItem("Unload Dalamud"))
|
if (ImGui.MenuItem("Unload Dalamud"))
|
||||||
{
|
{
|
||||||
|
|
@ -395,7 +408,7 @@ namespace Dalamud {
|
||||||
|
|
||||||
CommandManager.AddHandler("/xlitem", new CommandInfo(OnItemLinkCommand)
|
CommandManager.AddHandler("/xlitem", new CommandInfo(OnItemLinkCommand)
|
||||||
{
|
{
|
||||||
HelpMessage = Loc.Localize("DalamudItemLinkHelp", "Link an item by name. Usage: /xlitem <Item name>. For matching an item exactly, use /xlitem +<Item name>")
|
HelpMessage = Loc.Localize("DalamudItemLinkHelp", "Open a window you can use to link any specific item to chat.")
|
||||||
});
|
});
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
|
|
@ -424,6 +437,17 @@ namespace Dalamud {
|
||||||
this.CommandManager.AddHandler("/xlcredits", new CommandInfo(OnOpenCreditsCommand) {
|
this.CommandManager.AddHandler("/xlcredits", new CommandInfo(OnOpenCreditsCommand) {
|
||||||
HelpMessage = Loc.Localize("DalamudCreditsHelp", "Opens the credits for dalamud.")
|
HelpMessage = Loc.Localize("DalamudCreditsHelp", "Opens the credits for dalamud.")
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.CommandManager.AddHandler("/xllanguage", new CommandInfo(OnSetLanguageCommand)
|
||||||
|
{
|
||||||
|
HelpMessage = Loc.Localize("DalamudLanguageHelp", "Set the language for the in-game addon and plugins that support it.")
|
||||||
|
});
|
||||||
|
|
||||||
|
this.CommandManager.AddHandler("/imdebug", new CommandInfo(OnDebugImInfoCommand)
|
||||||
|
{
|
||||||
|
HelpMessage = "ImGui DEBUG",
|
||||||
|
ShowInHelp = false
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnUnloadCommand(string command, string arguments) {
|
private void OnUnloadCommand(string command, string arguments) {
|
||||||
|
|
@ -476,7 +500,7 @@ namespace Dalamud {
|
||||||
|
|
||||||
this.Configuration.BadWords.Add(arguments);
|
this.Configuration.BadWords.Add(arguments);
|
||||||
|
|
||||||
this.Configuration.Save(this.StartInfo.ConfigurationPath);
|
this.Configuration.Save();
|
||||||
|
|
||||||
Framework.Gui.Chat.Print(string.Format(Loc.Localize("DalamudMuted", "Muted \"{0}\"."), arguments));
|
Framework.Gui.Chat.Print(string.Format(Loc.Localize("DalamudMuted", "Muted \"{0}\"."), arguments));
|
||||||
}
|
}
|
||||||
|
|
@ -490,7 +514,7 @@ namespace Dalamud {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.Configuration.Save(this.StartInfo.ConfigurationPath);
|
this.Configuration.Save();
|
||||||
|
|
||||||
foreach (var word in this.Configuration.BadWords) Framework.Gui.Chat.Print($"\"{word}\"");
|
foreach (var word in this.Configuration.BadWords) Framework.Gui.Chat.Print($"\"{word}\"");
|
||||||
}
|
}
|
||||||
|
|
@ -501,7 +525,7 @@ namespace Dalamud {
|
||||||
|
|
||||||
this.Configuration.BadWords.RemoveAll(x => x == arguments);
|
this.Configuration.BadWords.RemoveAll(x => x == arguments);
|
||||||
|
|
||||||
this.Configuration.Save(this.StartInfo.ConfigurationPath);
|
this.Configuration.Save();
|
||||||
|
|
||||||
Framework.Gui.Chat.Print(string.Format(Loc.Localize("DalamudUnmuted", "Unmuted \"{0}\"."), arguments));
|
Framework.Gui.Chat.Print(string.Format(Loc.Localize("DalamudUnmuted", "Unmuted \"{0}\"."), arguments));
|
||||||
}
|
}
|
||||||
|
|
@ -534,7 +558,7 @@ namespace Dalamud {
|
||||||
private bool isImguiDrawItemSearchWindow;
|
private bool isImguiDrawItemSearchWindow;
|
||||||
|
|
||||||
private void OnItemLinkCommand(string command, string arguments) {
|
private void OnItemLinkCommand(string command, string arguments) {
|
||||||
this.itemSearchCommandWindow = new ItemSearchWindow(this.Data, new UiBuilder(this.InterfaceManager, "ItemSearcher"));
|
this.itemSearchCommandWindow = new ItemSearchWindow(this.Data, new UiBuilder(this.InterfaceManager, "ItemSearcher"), false);
|
||||||
this.itemSearchCommandWindow.OnItemChosen += (sender, item) => {
|
this.itemSearchCommandWindow.OnItemChosen += (sender, item) => {
|
||||||
var hexData = new byte[] {
|
var hexData = new byte[] {
|
||||||
0x02, 0x13, 0x06, 0xFE, 0xFF, 0xF3, 0xF3, 0xF3, 0x03, 0x02, 0x27, 0x07, 0x03, 0xF2, 0x3A, 0x2F,
|
0x02, 0x13, 0x06, 0xFE, 0xFF, 0xF3, 0xF3, 0xF3, 0x03, 0x02, 0x27, 0x07, 0x03, 0xF2, 0x3A, 0x2F,
|
||||||
|
|
@ -597,7 +621,7 @@ namespace Dalamud {
|
||||||
|
|
||||||
Framework.Gui.Chat.Print($"Set bonus notifications for {argParts[0]}({rouletteIndex}) to {role}");
|
Framework.Gui.Chat.Print($"Set bonus notifications for {argParts[0]}({rouletteIndex}) to {role}");
|
||||||
Framework.Gui.Chat.Print(string.Format(Loc.Localize("DalamudBonusSet", "Set bonus notifications for {0}({1}) to {2}"), argParts[0], rouletteIndex, role));
|
Framework.Gui.Chat.Print(string.Format(Loc.Localize("DalamudBonusSet", "Set bonus notifications for {0}({1}) to {2}"), argParts[0], rouletteIndex, role));
|
||||||
this.Configuration.Save(this.StartInfo.ConfigurationPath);
|
this.Configuration.Save();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
@ -610,6 +634,28 @@ namespace Dalamud {
|
||||||
this.isImguiDrawDevMenu = true;
|
this.isImguiDrawDevMenu = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnDebugImInfoCommand(string command, string arguments) {
|
||||||
|
var io = this.InterfaceManager.LastImGuiIoPtr;
|
||||||
|
var info = $"WantCaptureKeyboard: {io.WantCaptureKeyboard}\n";
|
||||||
|
info += $"WantCaptureMouse: {io.WantCaptureMouse}\n";
|
||||||
|
info += $"WantSetMousePos: {io.WantSetMousePos}\n";
|
||||||
|
info += $"WantTextInput: {io.WantTextInput}\n";
|
||||||
|
info += $"WantSaveIniSettings: {io.WantSaveIniSettings}\n";
|
||||||
|
info += $"BackendFlags: {(int) io.BackendFlags}\n";
|
||||||
|
info += $"DeltaTime: {io.DeltaTime}\n";
|
||||||
|
info += $"DisplaySize: {io.DisplaySize.X} {io.DisplaySize.Y}\n";
|
||||||
|
info += $"Framerate: {io.Framerate}\n";
|
||||||
|
info += $"MetricsActiveWindows: {io.MetricsActiveWindows}\n";
|
||||||
|
info += $"MetricsRenderWindows: {io.MetricsRenderWindows}\n";
|
||||||
|
info += $"MousePos: {io.MousePos.X} {io.MousePos.Y}\n";
|
||||||
|
info += $"MouseClicked: {io.MouseClicked}\n";
|
||||||
|
info += $"MouseDown: {io.MouseDown}\n";
|
||||||
|
info += $"NavActive: {io.NavActive}\n";
|
||||||
|
info += $"NavVisible: {io.NavVisible}\n";
|
||||||
|
|
||||||
|
Log.Information(info);
|
||||||
|
}
|
||||||
|
|
||||||
private void OnOpenInstallerCommand(string command, string arguments) {
|
private void OnOpenInstallerCommand(string command, string arguments) {
|
||||||
this.pluginWindow = new PluginInstallerWindow(this.PluginManager, PluginRepository, this.StartInfo.GameVersion);
|
this.pluginWindow = new PluginInstallerWindow(this.PluginManager, PluginRepository, this.StartInfo.GameVersion);
|
||||||
this.isImguiDrawPluginWindow = true;
|
this.isImguiDrawPluginWindow = true;
|
||||||
|
|
@ -624,6 +670,19 @@ namespace Dalamud {
|
||||||
this.isImguiDrawCreditsWindow = true;
|
this.isImguiDrawCreditsWindow = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnSetLanguageCommand(string command, string arguments)
|
||||||
|
{
|
||||||
|
if (Localization.ApplicableLangCodes.Contains(arguments.ToLower())) {
|
||||||
|
this.localizationMgr.SetupWithLangCode(arguments.ToLower());
|
||||||
|
this.Configuration.LanguageOverride = arguments.ToLower();
|
||||||
|
} else {
|
||||||
|
this.localizationMgr.SetupWithUiCulture();
|
||||||
|
this.Configuration.LanguageOverride = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Configuration.Save();
|
||||||
|
}
|
||||||
|
|
||||||
private int RouletteSlugToKey(string slug) => slug.ToLower() switch {
|
private int RouletteSlugToKey(string slug) => slug.ToLower() switch {
|
||||||
"leveling" => 1,
|
"leveling" => 1,
|
||||||
"506070" => 2,
|
"506070" => 2,
|
||||||
|
|
|
||||||
|
|
@ -14,9 +14,9 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Label="Feature">
|
<PropertyGroup Label="Feature">
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
<AssemblyVersion>4.8.5.0</AssemblyVersion>
|
<AssemblyVersion>4.8.8.0</AssemblyVersion>
|
||||||
<Version>4.8.5.0</Version>
|
<Version>4.8.8.0</Version>
|
||||||
<FileVersion>4.8.5.0</FileVersion>
|
<FileVersion>4.8.8.0</FileVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup Label="Resources">
|
<ItemGroup Label="Resources">
|
||||||
<None Include="$(SolutionDir)/Resources/**/*" CopyToOutputDirectory="PreserveNewest" Visible="false" />
|
<None Include="$(SolutionDir)/Resources/**/*" CopyToOutputDirectory="PreserveNewest" Visible="false" />
|
||||||
|
|
@ -79,26 +79,5 @@
|
||||||
<None Update="NotoSansCJKjp-Medium.otf">
|
<None Update="NotoSansCJKjp-Medium.otf">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</None>
|
</None>
|
||||||
<None Update="UIRes\loc\dalamud\dalamud_de.json">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
</None>
|
|
||||||
<None Update="UIRes\loc\dalamud\dalamud_es.json">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
</None>
|
|
||||||
<None Update="UIRes\loc\dalamud\dalamud_fr.json">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
</None>
|
|
||||||
<None Update="UIRes\loc\dalamud\dalamud_it.json">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
</None>
|
|
||||||
<None Update="UIRes\loc\dalamud\dalamud_ja.json">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
</None>
|
|
||||||
<None Update="UIRes\logo.png">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
</None>
|
|
||||||
<None Update="UIRes\NotoSansCJKjp-Medium.otf">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
</None>
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
||||||
|
|
@ -22,8 +22,6 @@ namespace Dalamud.Data
|
||||||
/// This class provides data for Dalamud-internal features, but can also be used by plugins if needed.
|
/// This class provides data for Dalamud-internal features, but can also be used by plugins if needed.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class DataManager {
|
public class DataManager {
|
||||||
private const string DataBaseUrl = "https://goaaats.github.io/ffxiv/tools/launcher/addons/Hooks/Data/";
|
|
||||||
|
|
||||||
public ReadOnlyDictionary<string, ushort> ServerOpCodes { get; private set; }
|
public ReadOnlyDictionary<string, ushort> ServerOpCodes { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -53,20 +51,14 @@ namespace Dalamud.Data
|
||||||
this.language = language;
|
this.language = language;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task Initialize()
|
public async Task Initialize(string baseDir)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Log.Verbose("Starting data download...");
|
Log.Verbose("Starting data download...");
|
||||||
|
|
||||||
using var client = new HttpClient()
|
|
||||||
{
|
|
||||||
BaseAddress = new Uri(DataBaseUrl)
|
|
||||||
};
|
|
||||||
|
|
||||||
var opCodeDict =
|
var opCodeDict =
|
||||||
JsonConvert.DeserializeObject<Dictionary<string, ushort>>(
|
JsonConvert.DeserializeObject<Dictionary<string, ushort>>(File.ReadAllText(Path.Combine(baseDir, "UIRes", "serveropcode.json")));
|
||||||
await client.GetStringAsync(DataBaseUrl + "serveropcode.json"));
|
|
||||||
this.ServerOpCodes = new ReadOnlyDictionary<string, ushort>(opCodeDict);
|
this.ServerOpCodes = new ReadOnlyDictionary<string, ushort>(opCodeDict);
|
||||||
|
|
||||||
Log.Verbose("Loaded {0} ServerOpCodes.", opCodeDict.Count);
|
Log.Verbose("Loaded {0} ServerOpCodes.", opCodeDict.Count);
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ using Dalamud.Interface;
|
||||||
using EasyHook;
|
using EasyHook;
|
||||||
using Serilog;
|
using Serilog;
|
||||||
using Serilog.Core;
|
using Serilog.Core;
|
||||||
|
using Serilog.Events;
|
||||||
|
|
||||||
namespace Dalamud {
|
namespace Dalamud {
|
||||||
public sealed class EntryPoint : IEntryPoint {
|
public sealed class EntryPoint : IEntryPoint {
|
||||||
|
|
@ -15,7 +16,8 @@ namespace Dalamud {
|
||||||
|
|
||||||
public void Run(RemoteHooking.IContext ctx, DalamudStartInfo info) {
|
public void Run(RemoteHooking.IContext ctx, DalamudStartInfo info) {
|
||||||
// Setup logger
|
// Setup logger
|
||||||
Log.Logger = NewLogger(info.WorkingDirectory);
|
var (logger, levelSwitch) = NewLogger(info.WorkingDirectory);
|
||||||
|
Log.Logger = logger;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Log.Information("Initializing a session..");
|
Log.Information("Initializing a session..");
|
||||||
|
|
@ -28,7 +30,7 @@ namespace Dalamud {
|
||||||
AppDomain.CurrentDomain.UnhandledException += OnUnhandledException;
|
AppDomain.CurrentDomain.UnhandledException += OnUnhandledException;
|
||||||
TaskScheduler.UnobservedTaskException += OnUnobservedTaskException;
|
TaskScheduler.UnobservedTaskException += OnUnobservedTaskException;
|
||||||
|
|
||||||
using var dalamud = new Dalamud(info);
|
using var dalamud = new Dalamud(info, levelSwitch);
|
||||||
Log.Information("Starting a session..");
|
Log.Information("Starting a session..");
|
||||||
|
|
||||||
// Run session
|
// Run session
|
||||||
|
|
@ -44,18 +46,24 @@ namespace Dalamud {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Logger NewLogger(string baseDirectory) {
|
private (Logger logger, LoggingLevelSwitch levelSwitch) NewLogger(string baseDirectory) {
|
||||||
var logPath = Path.Combine(baseDirectory, "dalamud.txt");
|
var logPath = Path.Combine(baseDirectory, "dalamud.txt");
|
||||||
|
|
||||||
return new LoggerConfiguration()
|
var levelSwitch = new LoggingLevelSwitch();
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
levelSwitch.MinimumLevel = LogEventLevel.Verbose;
|
||||||
|
#else
|
||||||
|
levelSwitch.MinimumLevel = LogEventLevel.Information;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
var newLogger = new LoggerConfiguration()
|
||||||
.WriteTo.Async(a => a.File(logPath))
|
.WriteTo.Async(a => a.File(logPath))
|
||||||
.WriteTo.EventSink()
|
.WriteTo.EventSink()
|
||||||
#if DEBUG
|
.MinimumLevel.ControlledBy(levelSwitch)
|
||||||
.MinimumLevel.Verbose()
|
|
||||||
#else
|
|
||||||
.MinimumLevel.Information()
|
|
||||||
#endif
|
|
||||||
.CreateLogger();
|
.CreateLogger();
|
||||||
|
|
||||||
|
return (newLogger, levelSwitch);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnUnhandledException(object sender, UnhandledExceptionEventArgs arg) {
|
private void OnUnhandledException(object sender, UnhandledExceptionEventArgs arg) {
|
||||||
|
|
|
||||||
181
Dalamud/Game/Chat/SeIconChar.cs
Normal file
181
Dalamud/Game/Chat/SeIconChar.cs
Normal file
|
|
@ -0,0 +1,181 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Dalamud.Game.Chat
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Special unicode characters with game-related symbols that work both in-game and in any dalamud window.
|
||||||
|
/// </summary>
|
||||||
|
public enum SeIconChar {
|
||||||
|
BotanistSprout = 0xE034,
|
||||||
|
ItemLevel = 0xE033,
|
||||||
|
AutoTranslateOpen = 0xE040,
|
||||||
|
AutoTranslateClose = 0xE041,
|
||||||
|
HighQuality = 0xE03C,
|
||||||
|
Clock = 0xE031,
|
||||||
|
Gil = 0xE049,
|
||||||
|
Hyadelyn = 0xE048,
|
||||||
|
|
||||||
|
MouseNoClick = 0xE050,
|
||||||
|
MouseLeftClick = 0xE051,
|
||||||
|
MouseRightClick = 0xE052,
|
||||||
|
MouseBothClick = 0xE053,
|
||||||
|
MouseWheel = 0xE054,
|
||||||
|
Mouse1 = 0xE055,
|
||||||
|
Mouse2 = 0xE056,
|
||||||
|
Mouse3 = 0xE057,
|
||||||
|
Mouse4 = 0xE058,
|
||||||
|
Mouse5 = 0xE059,
|
||||||
|
|
||||||
|
LevelEn = 0xE06A,
|
||||||
|
LevelDe = 0xE06B,
|
||||||
|
LevelFr = 0xE06C,
|
||||||
|
|
||||||
|
Experience = 0xE0BC,
|
||||||
|
ExperienceFilled = 0xE0BD,
|
||||||
|
|
||||||
|
TimeAm = 0xE06D,
|
||||||
|
TimePm = 0xE06E,
|
||||||
|
|
||||||
|
ArrowRight = 0xE06F,
|
||||||
|
ArrowDown = 0xE035,
|
||||||
|
|
||||||
|
Number0 = 0xE060,
|
||||||
|
Number1 = 0xE061,
|
||||||
|
Number2 = 0xE062,
|
||||||
|
Number3 = 0xE063,
|
||||||
|
Number4 = 0xE064,
|
||||||
|
Number5 = 0xE065,
|
||||||
|
Number6 = 0xE066,
|
||||||
|
Number7 = 0xE067,
|
||||||
|
Number8 = 0xE068,
|
||||||
|
Number9 = 0xE069,
|
||||||
|
|
||||||
|
BoxedNumber0 = 0xE08F,
|
||||||
|
BoxedNumber1 = 0xE090,
|
||||||
|
BoxedNumber2 = 0xE091,
|
||||||
|
BoxedNumber3 = 0xE092,
|
||||||
|
BoxedNumber4 = 0xE093,
|
||||||
|
BoxedNumber5 = 0xE094,
|
||||||
|
BoxedNumber6 = 0xE095,
|
||||||
|
BoxedNumber7 = 0xE096,
|
||||||
|
BoxedNumber8 = 0xE097,
|
||||||
|
BoxedNumber9 = 0xE098,
|
||||||
|
BoxedNumber10 = 0xE099,
|
||||||
|
BoxedNumber11 = 0xE09A,
|
||||||
|
BoxedNumber12 = 0xE09B,
|
||||||
|
BoxedNumber13 = 0xE09C,
|
||||||
|
BoxedNumber14 = 0xE09D,
|
||||||
|
BoxedNumber15 = 0xE09E,
|
||||||
|
BoxedNumber16 = 0xE09F,
|
||||||
|
BoxedNumber17 = 0xE0A0,
|
||||||
|
BoxedNumber18 = 0xE0A1,
|
||||||
|
BoxedNumber19 = 0xE0A2,
|
||||||
|
BoxedNumber20 = 0xE0A3,
|
||||||
|
BoxedNumber21 = 0xE0A4,
|
||||||
|
BoxedNumber22 = 0xE0A5,
|
||||||
|
BoxedNumber23 = 0xE0A6,
|
||||||
|
BoxedNumber24 = 0xE0A7,
|
||||||
|
BoxedNumber25 = 0xE0A8,
|
||||||
|
BoxedNumber26 = 0xE0A9,
|
||||||
|
BoxedNumber27 = 0xE0AA,
|
||||||
|
BoxedNumber28 = 0xE0AB,
|
||||||
|
BoxedNumber29 = 0xE0AC,
|
||||||
|
BoxedNumber30 = 0xE0AD,
|
||||||
|
BoxedNumber31 = 0xE0AE,
|
||||||
|
|
||||||
|
BoxedPlus = 0xE0AF,
|
||||||
|
BoxedQuestionMark = 0xE070,
|
||||||
|
BoxedStar = 0xE0C0,
|
||||||
|
|
||||||
|
BoxedRoman1 = 0xE0C1,
|
||||||
|
BoxedRoman2 = 0xE0C2,
|
||||||
|
BoxedRoman3 = 0xE0C3,
|
||||||
|
BoxedRoman4 = 0xE0C4,
|
||||||
|
BoxedRoman5 = 0xE0C5,
|
||||||
|
BoxedRoman6 = 0xE0C6,
|
||||||
|
|
||||||
|
BoxedLetterA = 0xE071,
|
||||||
|
BoxedLetterB = 0xE072,
|
||||||
|
BoxedLetterC = 0xE073,
|
||||||
|
BoxedLetterD = 0xE074,
|
||||||
|
BoxedLetterE = 0xE075,
|
||||||
|
BoxedLetterF = 0xE076,
|
||||||
|
BoxedLetterG = 0xE077,
|
||||||
|
BoxedLetterH = 0xE078,
|
||||||
|
BoxedLetterI = 0xE079,
|
||||||
|
BoxedLetterJ = 0xE07A,
|
||||||
|
BoxedLetterK = 0xE07B,
|
||||||
|
BoxedLetterL = 0xE07C,
|
||||||
|
BoxedLetterM = 0xE07D,
|
||||||
|
BoxedLetterN = 0xE07E,
|
||||||
|
BoxedLetterO = 0xE07F,
|
||||||
|
BoxedLetterP = 0xE080,
|
||||||
|
BoxedLetterQ = 0xE081,
|
||||||
|
BoxedLetterR = 0xE082,
|
||||||
|
BoxedLetterS = 0xE083,
|
||||||
|
BoxedLetterT = 0xE084,
|
||||||
|
BoxedLetterU = 0xE085,
|
||||||
|
BoxedLetterV = 0xE086,
|
||||||
|
BoxedLetterW = 0xE087,
|
||||||
|
BoxedLetterX = 0xE088,
|
||||||
|
BoxedLetterY = 0xE089,
|
||||||
|
BoxedLetterZ = 0xE08A,
|
||||||
|
|
||||||
|
Circle = 0xE04A,
|
||||||
|
Square = 0xE04B,
|
||||||
|
Cross = 0xE04C,
|
||||||
|
Triangle = 0xE04D,
|
||||||
|
Hexagon = 0xE042,
|
||||||
|
Prohibited = 0xE043,
|
||||||
|
|
||||||
|
|
||||||
|
Dice = 0xE03E,
|
||||||
|
Debuff = 0xE05B,
|
||||||
|
Buff = 0xE05C,
|
||||||
|
CrossWorld = 0xE05D,
|
||||||
|
|
||||||
|
EurekaLevel = 0xE03A,
|
||||||
|
|
||||||
|
LinkMarker = 0xE0BB,
|
||||||
|
|
||||||
|
Glamoured = 0xE03B,
|
||||||
|
GlamouredDyed = 0xE04E,
|
||||||
|
|
||||||
|
QuestSync = 0xE0BE,
|
||||||
|
QuestRepeatable = 0xE0BF,
|
||||||
|
|
||||||
|
ImeHiragana = 0xE020,
|
||||||
|
ImeKatakana = 0xE021,
|
||||||
|
ImeAlphanumeric = 0xE022,
|
||||||
|
ImeKatakanaHalfWidth = 0xE023,
|
||||||
|
ImeAlphanumericHalfWidth = 0xE024,
|
||||||
|
|
||||||
|
Instance1 = 0xE0B1,
|
||||||
|
Instance2 = 0xE0B2,
|
||||||
|
Instance3 = 0xE0B3,
|
||||||
|
Instance4 = 0xE0B4,
|
||||||
|
Instance5 = 0xE0B5,
|
||||||
|
Instance6 = 0xE0B6,
|
||||||
|
Instance7 = 0xE0B7,
|
||||||
|
Instance8 = 0xE0B8,
|
||||||
|
Instance9 = 0xE0B9,
|
||||||
|
InstanceMerged = 0xE0BA,
|
||||||
|
|
||||||
|
LocalTimeEn = 0xE0D0,
|
||||||
|
ServerTimeEn = 0xE0D1,
|
||||||
|
EorzeaTimeEn = 0xE0D2,
|
||||||
|
LocalTimeDe = 0xE0D3,
|
||||||
|
ServerTimeDe = 0xE0D4,
|
||||||
|
EorzeaTimeDe = 0xE0D5,
|
||||||
|
LocalTimeFr = 0xE0D6,
|
||||||
|
ServerTimeFr = 0xE0D7,
|
||||||
|
EorzeaTimeFr = 0xE0D8,
|
||||||
|
LocalTimeJa = 0xE0D9,
|
||||||
|
ServerTimeJa = 0xE0DA,
|
||||||
|
EorzeaTimeJa = 0xE0DB,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -5,6 +5,13 @@ using System.Linq;
|
||||||
using Dalamud.Game.Chat.SeStringHandling.Payloads;
|
using Dalamud.Game.Chat.SeStringHandling.Payloads;
|
||||||
using Serilog;
|
using Serilog;
|
||||||
|
|
||||||
|
// TODOs:
|
||||||
|
// - refactor integer handling now that we have multiple packed types
|
||||||
|
// - common construction/property design for subclasses
|
||||||
|
// - lumina DI
|
||||||
|
// - design for handling raw values vs resolved values, both for input and output
|
||||||
|
// - wrapper class(es) for handling of composite links in chat (item, map etc) and formatting operations
|
||||||
|
|
||||||
namespace Dalamud.Game.Chat.SeStringHandling
|
namespace Dalamud.Game.Chat.SeStringHandling
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -148,6 +155,7 @@ namespace Dalamud.Game.Chat.SeStringHandling
|
||||||
Int16 = 0xF2,
|
Int16 = 0xF2,
|
||||||
Int16Packed = 0xF4, // seen in map links, seemingly 2 8-bit values packed into 2 bytes with only one marker
|
Int16Packed = 0xF4, // seen in map links, seemingly 2 8-bit values packed into 2 bytes with only one marker
|
||||||
Int24Special = 0xF6, // unsure how different form Int24 - used for hq items that add 1 million, also used for normal 24-bit values in map links
|
Int24Special = 0xF6, // unsure how different form Int24 - used for hq items that add 1 million, also used for normal 24-bit values in map links
|
||||||
|
Int24Packed = 0xFC, // used in map links- sometimes short+byte, sometimes... not??
|
||||||
Int24 = 0xFA,
|
Int24 = 0xFA,
|
||||||
Int32 = 0xFE
|
Int32 = 0xFE
|
||||||
}
|
}
|
||||||
|
|
@ -189,6 +197,8 @@ namespace Dalamud.Game.Chat.SeStringHandling
|
||||||
|
|
||||||
case IntegerType.Int24Special:
|
case IntegerType.Int24Special:
|
||||||
// Fallthrough - same logic
|
// Fallthrough - same logic
|
||||||
|
case IntegerType.Int24Packed:
|
||||||
|
// fallthrough again
|
||||||
case IntegerType.Int24:
|
case IntegerType.Int24:
|
||||||
{
|
{
|
||||||
var v = 0;
|
var v = 0;
|
||||||
|
|
@ -267,6 +277,7 @@ namespace Dalamud.Game.Chat.SeStringHandling
|
||||||
var type = bytes.Length switch
|
var type = bytes.Length switch
|
||||||
{
|
{
|
||||||
4 => IntegerType.Int32,
|
4 => IntegerType.Int32,
|
||||||
|
3 => IntegerType.Int24Packed,
|
||||||
2 => IntegerType.Int16Packed,
|
2 => IntegerType.Int16Packed,
|
||||||
_ => throw new NotSupportedException()
|
_ => throw new NotSupportedException()
|
||||||
};
|
};
|
||||||
|
|
@ -276,17 +287,32 @@ namespace Dalamud.Game.Chat.SeStringHandling
|
||||||
|
|
||||||
protected (uint, uint) GetPackedIntegers(BinaryReader input)
|
protected (uint, uint) GetPackedIntegers(BinaryReader input)
|
||||||
{
|
{
|
||||||
|
// HACK - this was already a hack, but the addition of Int24Packed made it even worse
|
||||||
|
// All of this should be redone/removed at some point
|
||||||
|
|
||||||
|
var marker = (IntegerType)input.ReadByte();
|
||||||
|
input.BaseStream.Position--;
|
||||||
|
|
||||||
var value = GetInteger(input);
|
var value = GetInteger(input);
|
||||||
if (value > 0xFFFF)
|
|
||||||
|
if (marker == IntegerType.Int24Packed)
|
||||||
{
|
{
|
||||||
return ((uint)((value & 0xFFFF0000) >> 16), (uint)(value & 0xFFFF));
|
return ((uint)((value & 0xFFFF00) >> 8), (uint)(value & 0xFF));
|
||||||
}
|
}
|
||||||
else if (value > 0xFF)
|
// this used to be the catchall before Int24Packed; leave it for now to ensure we handle all encodings
|
||||||
|
else // if (marker == IntegerType.Int16Packed || marker == IntegerType.Int32)
|
||||||
{
|
{
|
||||||
return ((uint)((value & 0xFF00) >> 8), (uint)(value & 0xFF));
|
if (value > 0xFFFF)
|
||||||
|
{
|
||||||
|
return ((uint)((value & 0xFFFF0000) >> 16), (uint)(value & 0xFFFF));
|
||||||
|
}
|
||||||
|
else if (value > 0xFF)
|
||||||
|
{
|
||||||
|
return ((uint)((value & 0xFF00) >> 8), (uint)(value & 0xFF));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// unsure if there are other cases, like "odd" pairings of 2+1 bytes etc
|
// unsure if there are other cases
|
||||||
throw new NotSupportedException();
|
throw new NotSupportedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -65,15 +65,34 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
|
||||||
//}
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return $"{Type} - TerritoryTypeId: {TerritoryTypeId}, MapId: {MapId}, RawX: {RawX}, RawY: {RawY}";
|
||||||
|
}
|
||||||
|
|
||||||
protected override void ProcessChunkImpl(BinaryReader reader, long endOfStream)
|
protected override void ProcessChunkImpl(BinaryReader reader, long endOfStream)
|
||||||
{
|
{
|
||||||
(TerritoryTypeId, MapId) = GetPackedIntegers(reader);
|
// for debugging for now
|
||||||
RawX = (uint)GetInteger(reader);
|
var oldPos = reader.BaseStream.Position;
|
||||||
RawY = (uint)GetInteger(reader);
|
var bytes = reader.ReadBytes((int)(endOfStream - reader.BaseStream.Position));
|
||||||
// the Z coordinate is never in this chunk, just the text (if applicable)
|
reader.BaseStream.Position = oldPos;
|
||||||
|
|
||||||
// seems to always be FF 01
|
try
|
||||||
reader.ReadBytes(2);
|
{
|
||||||
|
(TerritoryTypeId, MapId) = GetPackedIntegers(reader);
|
||||||
|
RawX = (uint)GetInteger(reader);
|
||||||
|
RawY = (uint)GetInteger(reader);
|
||||||
|
// the Z coordinate is never in this chunk, just the text (if applicable)
|
||||||
|
|
||||||
|
// seems to always be FF 01
|
||||||
|
reader.ReadBytes(2);
|
||||||
|
}
|
||||||
|
catch (NotSupportedException)
|
||||||
|
{
|
||||||
|
Serilog.Log.Information($"Unsupported map bytes {BitConverter.ToString(bytes).Replace("-", " ")}");
|
||||||
|
// we still want to break here for now, or we'd just throw again later
|
||||||
|
throw;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#region ugliness
|
#region ugliness
|
||||||
|
|
|
||||||
|
|
@ -119,7 +119,7 @@ namespace Dalamud.Game {
|
||||||
});
|
});
|
||||||
|
|
||||||
this.dalamud.Configuration.LastVersion = assemblyVersion;
|
this.dalamud.Configuration.LastVersion = assemblyVersion;
|
||||||
this.dalamud.Configuration.Save(this.dalamud.StartInfo.ConfigurationPath);
|
this.dalamud.Configuration.Save();
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using Dalamud.Game.ClientState.Actors.Types;
|
using Dalamud.Game.ClientState.Actors.Types;
|
||||||
|
|
@ -11,9 +12,10 @@ namespace Dalamud.Game.ClientState.Actors {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This collection represents the currently spawned FFXIV actors.
|
/// This collection represents the currently spawned FFXIV actors.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class ActorTable : ICollection, IDisposable {
|
public class ActorTable : IReadOnlyCollection<Actor>, ICollection, IDisposable {
|
||||||
|
|
||||||
#region temporary imports for crash workaround
|
#region temporary imports for crash workaround
|
||||||
|
|
||||||
[DllImport("kernel32.dll", SetLastError = true)]
|
[DllImport("kernel32.dll", SetLastError = true)]
|
||||||
static extern bool ReadProcessMemory(
|
static extern bool ReadProcessMemory(
|
||||||
IntPtr hProcess,
|
IntPtr hProcess,
|
||||||
|
|
@ -21,6 +23,7 @@ namespace Dalamud.Game.ClientState.Actors {
|
||||||
IntPtr lpBuffer,
|
IntPtr lpBuffer,
|
||||||
int dwSize,
|
int dwSize,
|
||||||
out IntPtr lpNumberOfBytesRead);
|
out IntPtr lpNumberOfBytesRead);
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
private ClientStateAddressResolver Address { get; }
|
private ClientStateAddressResolver Address { get; }
|
||||||
|
|
@ -42,7 +45,8 @@ namespace Dalamud.Game.ClientState.Actors {
|
||||||
Address = addressResolver;
|
Address = addressResolver;
|
||||||
this.dalamud = dalamud;
|
this.dalamud = dalamud;
|
||||||
|
|
||||||
this.someActorTableAccessHook = new Hook<SomeActorTableAccessDelegate>(Address.SomeActorTableAccess, new SomeActorTableAccessDelegate(SomeActorTableAccessDetour), this);
|
this.someActorTableAccessHook = new Hook<SomeActorTableAccessDelegate>(
|
||||||
|
Address.SomeActorTableAccess, new SomeActorTableAccessDelegate(SomeActorTableAccessDetour), this);
|
||||||
|
|
||||||
Log.Verbose("Actor table address {ActorTable}", Address.ViewportActorTable);
|
Log.Verbose("Actor table address {ActorTable}", Address.ViewportActorTable);
|
||||||
}
|
}
|
||||||
|
|
@ -74,15 +78,14 @@ namespace Dalamud.Game.ClientState.Actors {
|
||||||
if (!this.isReady)
|
if (!this.isReady)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
if (this.someActorTableAccessHook != null)
|
if (this.someActorTableAccessHook != null) {
|
||||||
{
|
|
||||||
this.someActorTableAccessHook.Dispose();
|
this.someActorTableAccessHook.Dispose();
|
||||||
this.someActorTableAccessHook = null;
|
this.someActorTableAccessHook = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (index >= Length)
|
if (index >= Length)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
var tblIndex = this.realActorTablePtr + 8 + index * 8;
|
var tblIndex = this.realActorTablePtr + 8 + index * 8;
|
||||||
|
|
||||||
var offset = Marshal.ReadIntPtr(tblIndex);
|
var offset = Marshal.ReadIntPtr(tblIndex);
|
||||||
|
|
@ -94,9 +97,8 @@ namespace Dalamud.Game.ClientState.Actors {
|
||||||
|
|
||||||
// FIXME: hack workaround for trying to access the player on logout, after the main object has been deleted
|
// FIXME: hack workaround for trying to access the player on logout, after the main object has been deleted
|
||||||
var sz = Marshal.SizeOf(typeof(Structs.Actor));
|
var sz = Marshal.SizeOf(typeof(Structs.Actor));
|
||||||
var actorMem = Marshal.AllocHGlobal(sz); // we arguably could just reuse this
|
var actorMem = Marshal.AllocHGlobal(sz); // we arguably could just reuse this
|
||||||
if (!ReadProcessMemory(Process.GetCurrentProcess().Handle, offset, actorMem, sz, out _))
|
if (!ReadProcessMemory(Process.GetCurrentProcess().Handle, offset, actorMem, sz, out _)) {
|
||||||
{
|
|
||||||
Log.Debug("ActorTable - ReadProcessMemory failed: likely player deletion during logout");
|
Log.Debug("ActorTable - ReadProcessMemory failed: likely player deletion during logout");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
@ -106,17 +108,16 @@ namespace Dalamud.Game.ClientState.Actors {
|
||||||
|
|
||||||
//Log.Debug("ActorTable[{0}]: {1} - {2} - {3}", index, tblIndex.ToString("X"), offset.ToString("X"),
|
//Log.Debug("ActorTable[{0}]: {1} - {2} - {3}", index, tblIndex.ToString("X"), offset.ToString("X"),
|
||||||
// actorStruct.ObjectKind.ToString());
|
// actorStruct.ObjectKind.ToString());
|
||||||
|
|
||||||
switch (actorStruct.ObjectKind)
|
switch (actorStruct.ObjectKind) {
|
||||||
{
|
case ObjectKind.Player: return new PlayerCharacter(offset, actorStruct, this.dalamud);
|
||||||
case ObjectKind.Player: return new PlayerCharacter(actorStruct, this.dalamud);
|
case ObjectKind.BattleNpc: return new BattleNpc(offset, actorStruct, this.dalamud);
|
||||||
case ObjectKind.BattleNpc: return new BattleNpc(actorStruct, this.dalamud);
|
default: return new Actor(offset, actorStruct, this.dalamud);
|
||||||
default: return new Actor(actorStruct, this.dalamud);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ActorTableEnumerator : IEnumerator {
|
private class ActorTableEnumerator : IEnumerator<Actor> {
|
||||||
private readonly ActorTable table;
|
private readonly ActorTable table;
|
||||||
|
|
||||||
private int currentIndex;
|
private int currentIndex;
|
||||||
|
|
@ -134,18 +135,29 @@ namespace Dalamud.Game.ClientState.Actors {
|
||||||
this.currentIndex = 0;
|
this.currentIndex = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public object Current => this.table[this.currentIndex];
|
public Actor Current => this.table[this.currentIndex];
|
||||||
|
|
||||||
|
object IEnumerator.Current => Current;
|
||||||
|
|
||||||
|
// Required by IEnumerator<T> even though we have nothing we want to dispose here.
|
||||||
|
public void Dispose() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerator GetEnumerator() {
|
public IEnumerator<Actor> GetEnumerator() {
|
||||||
return new ActorTableEnumerator(this);
|
return new ActorTableEnumerator(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IEnumerator IEnumerable.GetEnumerator() {
|
||||||
|
return GetEnumerator();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The amount of currently spawned actors.
|
/// The amount of currently spawned actors.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int Length => !this.isReady ? 0 : Marshal.ReadInt32(this.realActorTablePtr);
|
public int Length => !this.isReady ? 0 : Marshal.ReadInt32(this.realActorTablePtr);
|
||||||
|
|
||||||
|
int IReadOnlyCollection<Actor>.Count => Length;
|
||||||
|
|
||||||
int ICollection.Count => Length;
|
int ICollection.Count => Length;
|
||||||
|
|
||||||
bool ICollection.IsSynchronized => false;
|
bool ICollection.IsSynchronized => false;
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
namespace Dalamud.Game.ClientState.Actors.Types {
|
namespace Dalamud.Game.ClientState.Actors.Types {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This class represents a basic FFXIV actor.
|
/// This class represents a basic FFXIV actor.
|
||||||
|
|
@ -10,14 +12,21 @@ namespace Dalamud.Game.ClientState.Actors.Types {
|
||||||
|
|
||||||
protected Dalamud dalamud;
|
protected Dalamud dalamud;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The address of this actor in memory.
|
||||||
|
/// </summary>
|
||||||
|
public readonly IntPtr Address;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initialize a representation of a basic FFXIV actor.
|
/// Initialize a representation of a basic FFXIV actor.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="actorStruct">The memory representation of the base actor.</param>
|
/// <param name="actorStruct">The memory representation of the base actor.</param>
|
||||||
/// <param name="dalamud">A dalamud reference needed to access game data in Resolvers.</param>
|
/// <param name="dalamud">A dalamud reference needed to access game data in Resolvers.</param>
|
||||||
public Actor(Structs.Actor actorStruct, Dalamud dalamud) {
|
/// <param name="address">The address of this actor in memory.</param>
|
||||||
|
public Actor(IntPtr address, Structs.Actor actorStruct, Dalamud dalamud) {
|
||||||
this.actorStruct = actorStruct;
|
this.actorStruct = actorStruct;
|
||||||
this.dalamud = dalamud;
|
this.dalamud = dalamud;
|
||||||
|
this.Address = address;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
using System;
|
||||||
using Dalamud.Game.ClientState.Actors.Resolvers;
|
using Dalamud.Game.ClientState.Actors.Resolvers;
|
||||||
|
|
||||||
namespace Dalamud.Game.ClientState.Actors.Types {
|
namespace Dalamud.Game.ClientState.Actors.Types {
|
||||||
|
|
@ -10,7 +11,8 @@ namespace Dalamud.Game.ClientState.Actors.Types {
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="actorStruct">The memory representation of the base actor.</param>
|
/// <param name="actorStruct">The memory representation of the base actor.</param>
|
||||||
/// <param name="dalamud">A dalamud reference needed to access game data in Resolvers.</param>
|
/// <param name="dalamud">A dalamud reference needed to access game data in Resolvers.</param>
|
||||||
protected Chara(Structs.Actor actorStruct, Dalamud dalamud) : base(actorStruct, dalamud) { }
|
/// <param name="address">The address of this actor in memory.</param>
|
||||||
|
protected Chara(IntPtr address, Structs.Actor actorStruct, Dalamud dalamud) : base(address, actorStruct, dalamud) { }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The level of this Chara.
|
/// The level of this Chara.
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
namespace Dalamud.Game.ClientState.Actors.Types.NonPlayer {
|
namespace Dalamud.Game.ClientState.Actors.Types.NonPlayer {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This class represents a battle NPC.
|
/// This class represents a battle NPC.
|
||||||
|
|
@ -8,7 +10,8 @@ namespace Dalamud.Game.ClientState.Actors.Types.NonPlayer {
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="actorStruct">The memory representation of the base actor.</param>
|
/// <param name="actorStruct">The memory representation of the base actor.</param>
|
||||||
/// <param name="dalamud">A dalamud reference needed to access game data in Resolvers.</param>
|
/// <param name="dalamud">A dalamud reference needed to access game data in Resolvers.</param>
|
||||||
public BattleNpc(Structs.Actor actorStruct, Dalamud dalamud) : base(actorStruct, dalamud) { }
|
/// <param name="address">The address of this actor in memory.</param>
|
||||||
|
public BattleNpc(IntPtr address, Structs.Actor actorStruct, Dalamud dalamud) : base(address, actorStruct, dalamud) { }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The BattleNpc <see cref="BattleNpcSubKind" /> of this BattleNpc.
|
/// The BattleNpc <see cref="BattleNpcSubKind" /> of this BattleNpc.
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
namespace Dalamud.Game.ClientState.Actors.Types.NonPlayer {
|
namespace Dalamud.Game.ClientState.Actors.Types.NonPlayer {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This class represents a NPC.
|
/// This class represents a NPC.
|
||||||
|
|
@ -8,11 +10,17 @@ namespace Dalamud.Game.ClientState.Actors.Types.NonPlayer {
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="actorStruct">The memory representation of the base actor.</param>
|
/// <param name="actorStruct">The memory representation of the base actor.</param>
|
||||||
/// <param name="dalamud">A dalamud reference needed to access game data in Resolvers.</param>
|
/// <param name="dalamud">A dalamud reference needed to access game data in Resolvers.</param>
|
||||||
protected Npc(Structs.Actor actorStruct, Dalamud dalamud) : base(actorStruct, dalamud) { }
|
/// <param name="address">The address of this actor in memory.</param>
|
||||||
|
protected Npc(IntPtr address, Structs.Actor actorStruct, Dalamud dalamud) : base(address, actorStruct, dalamud) { }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The data ID of the NPC linking to their respective game data.
|
/// The data ID of the NPC linking to their respective game data.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int DataId => this.actorStruct.DataId;
|
public int DataId => this.actorStruct.DataId;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The name ID of the NPC linking to their respective game data.
|
||||||
|
/// </summary>
|
||||||
|
public int NameId => this.actorStruct.NameId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
using System;
|
||||||
using Dalamud.Game.ClientState.Actors.Resolvers;
|
using Dalamud.Game.ClientState.Actors.Resolvers;
|
||||||
using SharpDX.Text;
|
using SharpDX.Text;
|
||||||
|
|
||||||
|
|
@ -11,7 +12,8 @@ namespace Dalamud.Game.ClientState.Actors.Types {
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="actorStruct">The memory representation of the base actor.</param>
|
/// <param name="actorStruct">The memory representation of the base actor.</param>
|
||||||
/// <param name="dalamud">A dalamud reference needed to access game data in Resolvers.</param>
|
/// <param name="dalamud">A dalamud reference needed to access game data in Resolvers.</param>
|
||||||
public PlayerCharacter(Structs.Actor actorStruct, Dalamud dalamud) : base(actorStruct, dalamud) { }
|
/// <param name="address">The address of this actor in memory.</param>
|
||||||
|
public PlayerCharacter(IntPtr address, Structs.Actor actorStruct, Dalamud dalamud) : base(address, actorStruct, dalamud) { }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The current <see cref="World">world</see> of the character.
|
/// The current <see cref="World">world</see> of the character.
|
||||||
|
|
|
||||||
|
|
@ -24,10 +24,10 @@ namespace Dalamud.Game.ClientState.Structs
|
||||||
[FieldOffset(145)] public byte PlayerTargetStatus; // This is some kind of enum
|
[FieldOffset(145)] public byte PlayerTargetStatus; // This is some kind of enum
|
||||||
[FieldOffset(146)] public byte YalmDistanceFromPlayer2; // and the other is z distance
|
[FieldOffset(146)] public byte YalmDistanceFromPlayer2; // and the other is z distance
|
||||||
[FieldOffset(160)] public Position3 Position;
|
[FieldOffset(160)] public Position3 Position;
|
||||||
|
[FieldOffset(0x17F8)] public int TargetActorId;
|
||||||
// This field can't be correctly aligned, so we have to cut it manually.
|
// This field can't be correctly aligned, so we have to cut it manually.
|
||||||
[FieldOffset(0x17d0)] [MarshalAs(UnmanagedType.ByValArray, SizeConst = 7)] public byte[] CompanyTag;
|
[FieldOffset(0x17d0)] [MarshalAs(UnmanagedType.ByValArray, SizeConst = 7)] public byte[] CompanyTag;
|
||||||
[FieldOffset(0x17F8)] public int TargetActorId;
|
[FieldOffset(0x1868)] public int NameId;
|
||||||
[FieldOffset(0x1884)] public byte CurrentWorld;
|
[FieldOffset(0x1884)] public byte CurrentWorld;
|
||||||
[FieldOffset(0x1886)] public byte HomeWorld;
|
[FieldOffset(0x1886)] public byte HomeWorld;
|
||||||
[FieldOffset(6328)] public int CurrentHp;
|
[FieldOffset(6328)] public int CurrentHp;
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ namespace Dalamud.Game.ClientState.Structs.JobGauge {
|
||||||
public struct BRDGauge {
|
public struct BRDGauge {
|
||||||
[FieldOffset(0)] public short SongTimer;
|
[FieldOffset(0)] public short SongTimer;
|
||||||
[FieldOffset(2)] public byte NumSongStacks;
|
[FieldOffset(2)] public byte NumSongStacks;
|
||||||
|
[FieldOffset(3)] public byte SoulVoiceValue;
|
||||||
[FieldOffset(4)] public CurrentSong ActiveSong;
|
[FieldOffset(4)] public CurrentSong ActiveSong;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,39 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Dalamud.Hooking;
|
|
||||||
using EasyHook;
|
|
||||||
using Serilog;
|
|
||||||
|
|
||||||
namespace Dalamud.Game.Internal
|
|
||||||
{
|
|
||||||
class AntiDebug : IDisposable
|
|
||||||
{
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Winapi)]
|
|
||||||
private delegate bool IsDebuggerPresentDelegate();
|
|
||||||
|
|
||||||
private Hook<IsDebuggerPresentDelegate> debuggerPresentHook;
|
|
||||||
|
|
||||||
public AntiDebug() {
|
|
||||||
this.debuggerPresentHook = new Hook<IsDebuggerPresentDelegate>(LocalHook.GetProcAddress("Kernel32", "IsDebuggerPresent"),
|
|
||||||
new IsDebuggerPresentDelegate(IsDebuggerPresentDetour));
|
|
||||||
|
|
||||||
Log.Verbose("IsDebuggerPresent address {IsDebuggerPresent}", this.debuggerPresentHook.Address);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Enable() {
|
|
||||||
this.debuggerPresentHook.Enable();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose() {
|
|
||||||
this.debuggerPresentHook.Disable();
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool IsDebuggerPresentDetour() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace Dalamud.Game.Internal {
|
namespace Dalamud.Game.Internal {
|
||||||
|
|
@ -35,7 +35,7 @@ namespace Dalamud.Game.Internal {
|
||||||
// Do nothing
|
// Do nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
protected T GetVirtualFunction<T>(IntPtr address, int vtableOffset, int count) where T : class {
|
public T GetVirtualFunction<T>(IntPtr address, int vtableOffset, int count) where T : class {
|
||||||
// Get vtable
|
// Get vtable
|
||||||
var vtable = Marshal.ReadIntPtr(address, vtableOffset);
|
var vtable = Marshal.ReadIntPtr(address, vtableOffset);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using Dalamud.Game.Chat;
|
using Dalamud.Game.Chat.SeStringHandling.Payloads;
|
||||||
using Dalamud.Hooking;
|
using Dalamud.Hooking;
|
||||||
using Serilog;
|
using Serilog;
|
||||||
|
|
||||||
|
|
@ -22,6 +22,18 @@ namespace Dalamud.Game.Internal.Gui {
|
||||||
private delegate IntPtr HandleItemOutDelegate(IntPtr hoverState, IntPtr a2, IntPtr a3, ulong a4);
|
private delegate IntPtr HandleItemOutDelegate(IntPtr hoverState, IntPtr a2, IntPtr a3, ulong a4);
|
||||||
private readonly Hook<HandleItemOutDelegate> handleItemOutHook;
|
private readonly Hook<HandleItemOutDelegate> handleItemOutHook;
|
||||||
|
|
||||||
|
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||||
|
private delegate IntPtr GetUIObjectDelegate();
|
||||||
|
private readonly GetUIObjectDelegate getUIObject;
|
||||||
|
|
||||||
|
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
|
||||||
|
private delegate IntPtr GetUIMapObjectDelegate(IntPtr UIObject);
|
||||||
|
private GetUIMapObjectDelegate getUIMapObject;
|
||||||
|
|
||||||
|
[UnmanagedFunctionPointer(CallingConvention.ThisCall, CharSet = CharSet.Ansi)]
|
||||||
|
private delegate bool OpenMapWithFlagDelegate(IntPtr UIMapObject, string flag);
|
||||||
|
private OpenMapWithFlagDelegate openMapWithFlag;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The item ID that is currently hovered by the player. 0 when no item is hovered.
|
/// The item ID that is currently hovered by the player. 0 when no item is hovered.
|
||||||
/// If > 1.000.000, subtract 1.000.000 and treat it as HQ
|
/// If > 1.000.000, subtract 1.000.000 and treat it as HQ
|
||||||
|
|
@ -43,6 +55,7 @@ namespace Dalamud.Game.Internal.Gui {
|
||||||
Log.Verbose("SetGlobalBgm address {Address}", Address.SetGlobalBgm);
|
Log.Verbose("SetGlobalBgm address {Address}", Address.SetGlobalBgm);
|
||||||
Log.Verbose("HandleItemHover address {Address}", Address.HandleItemHover);
|
Log.Verbose("HandleItemHover address {Address}", Address.HandleItemHover);
|
||||||
Log.Verbose("HandleItemOut address {Address}", Address.HandleItemOut);
|
Log.Verbose("HandleItemOut address {Address}", Address.HandleItemOut);
|
||||||
|
Log.Verbose("GetUIObject address {Address}", Address.GetUIObject);
|
||||||
|
|
||||||
Chat = new ChatGui(Address.ChatManager, scanner, dalamud);
|
Chat = new ChatGui(Address.ChatManager, scanner, dalamud);
|
||||||
|
|
||||||
|
|
@ -59,6 +72,8 @@ namespace Dalamud.Game.Internal.Gui {
|
||||||
new Hook<HandleItemOutDelegate>(Address.HandleItemOut,
|
new Hook<HandleItemOutDelegate>(Address.HandleItemOut,
|
||||||
new HandleItemOutDelegate(HandleItemOutDetour),
|
new HandleItemOutDelegate(HandleItemOutDetour),
|
||||||
this);
|
this);
|
||||||
|
|
||||||
|
this.getUIObject = Marshal.GetDelegateForFunctionPointer<GetUIObjectDelegate>(Address.GetUIObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
private IntPtr HandleSetGlobalBgmDetour(UInt16 bgmKey, byte a2, UInt32 a3, UInt32 a4, UInt32 a5, byte a6) {
|
private IntPtr HandleSetGlobalBgmDetour(UInt16 bgmKey, byte a2, UInt32 a3, UInt32 a4, UInt32 a5, byte a6) {
|
||||||
|
|
@ -111,6 +126,39 @@ namespace Dalamud.Game.Internal.Gui {
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool OpenMapWithMapLink(MapLinkPayload mapLink)
|
||||||
|
{
|
||||||
|
var uiObjectPtr = getUIObject();
|
||||||
|
|
||||||
|
if (uiObjectPtr.Equals(IntPtr.Zero))
|
||||||
|
{
|
||||||
|
Log.Error("OpenMapWithMapLink: Null pointer returned from getUIObject()");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
getUIMapObject =
|
||||||
|
Address.GetVirtualFunction<GetUIMapObjectDelegate>(uiObjectPtr, 0, 8);
|
||||||
|
|
||||||
|
|
||||||
|
var uiMapObjectPtr = this.getUIMapObject(uiObjectPtr);
|
||||||
|
|
||||||
|
if (uiMapObjectPtr.Equals(IntPtr.Zero))
|
||||||
|
{
|
||||||
|
Log.Error("OpenMapWithMapLink: Null pointer returned from GetUIMapObject()");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
openMapWithFlag =
|
||||||
|
Address.GetVirtualFunction<OpenMapWithFlagDelegate>(uiMapObjectPtr, 0, 63);
|
||||||
|
|
||||||
|
var mapLinkString =
|
||||||
|
$"m:{mapLink.TerritoryTypeId},{mapLink.MapId},{unchecked((int)mapLink.RawX)},{unchecked((int)mapLink.RawY)}";
|
||||||
|
|
||||||
|
Log.Debug($"OpenMapWithMapLink: Opening Map Link: {mapLinkString}");
|
||||||
|
|
||||||
|
return this.openMapWithFlag(uiMapObjectPtr, mapLinkString);
|
||||||
|
}
|
||||||
|
|
||||||
public void SetBgm(ushort bgmKey) => this.setGlobalBgmHook.Original(bgmKey, 0, 0, 0, 0, 0);
|
public void SetBgm(ushort bgmKey) => this.setGlobalBgmHook.Original(bgmKey, 0, 0, 0, 0, 0);
|
||||||
|
|
||||||
public void Enable() {
|
public void Enable() {
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ namespace Dalamud.Game.Internal.Gui {
|
||||||
public IntPtr SetGlobalBgm { get; private set; }
|
public IntPtr SetGlobalBgm { get; private set; }
|
||||||
public IntPtr HandleItemHover { get; set; }
|
public IntPtr HandleItemHover { get; set; }
|
||||||
public IntPtr HandleItemOut { get; set; }
|
public IntPtr HandleItemOut { get; set; }
|
||||||
|
public IntPtr GetUIObject { get; private set; }
|
||||||
|
|
||||||
public GameGuiAddressResolver(IntPtr baseAddress) {
|
public GameGuiAddressResolver(IntPtr baseAddress) {
|
||||||
BaseAddress = baseAddress;
|
BaseAddress = baseAddress;
|
||||||
|
|
@ -29,6 +30,7 @@ namespace Dalamud.Game.Internal.Gui {
|
||||||
SetGlobalBgm = sig.ScanText("4C 8B 15 ?? ?? ?? ?? 4D 85 D2 74 58");
|
SetGlobalBgm = sig.ScanText("4C 8B 15 ?? ?? ?? ?? 4D 85 D2 74 58");
|
||||||
HandleItemHover = sig.ScanText("E8 ?? ?? ?? ?? 48 8B 5C 24 ?? 48 89 AE ?? ?? ?? ??");
|
HandleItemHover = sig.ScanText("E8 ?? ?? ?? ?? 48 8B 5C 24 ?? 48 89 AE ?? ?? ?? ??");
|
||||||
HandleItemOut = sig.ScanText("48 89 5C 24 ?? 57 48 83 EC 20 48 8B FA 48 8B D9 4D");
|
HandleItemOut = sig.ScanText("48 89 5C 24 ?? 57 48 83 EC 20 48 8B FA 48 8B D9 4D");
|
||||||
|
GetUIObject = sig.ScanText("E8 ?? ?? ?? ?? 48 8B C8 48 8B 10 FF 52 40 80 88 ?? ?? ?? ?? 01 E9");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
68
Dalamud/Interface/AssetManager.cs
Normal file
68
Dalamud/Interface/AssetManager.cs
Normal file
|
|
@ -0,0 +1,68 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Serilog;
|
||||||
|
|
||||||
|
namespace Dalamud.Interface
|
||||||
|
{
|
||||||
|
class AssetManager {
|
||||||
|
private const string AssetStoreUrl = "https://goatcorp.github.io/DalamudAssets/";
|
||||||
|
|
||||||
|
private static readonly Dictionary<string, string> AssetDictionary = new Dictionary<string, string> {
|
||||||
|
{AssetStoreUrl + "UIRes/serveropcode.json", "UIRes/serveropcode.json" },
|
||||||
|
{AssetStoreUrl + "UIRes/NotoSansCJKjp-Medium.otf", "UIRes/NotoSansCJKjp-Medium.otf" },
|
||||||
|
{AssetStoreUrl + "UIRes/logo.png", "UIRes/logo.png" },
|
||||||
|
{AssetStoreUrl + "UIRes/loc/dalamud/dalamud_de.json", "UIRes/loc/dalamud/dalamud_de.json" },
|
||||||
|
{AssetStoreUrl + "UIRes/loc/dalamud/dalamud_es.json", "UIRes/loc/dalamud/dalamud_es.json" },
|
||||||
|
{AssetStoreUrl + "UIRes/loc/dalamud/dalamud_fr.json", "UIRes/loc/dalamud/dalamud_fr.json" },
|
||||||
|
{AssetStoreUrl + "UIRes/loc/dalamud/dalamud_it.json", "UIRes/loc/dalamud/dalamud_it.json" },
|
||||||
|
{AssetStoreUrl + "UIRes/loc/dalamud/dalamud_ja.json", "UIRes/loc/dalamud/dalamud_ja.json" },
|
||||||
|
{"https://img.finalfantasyxiv.com/lds/pc/global/fonts/FFXIV_Lodestone_SSF.ttf", "UIRes/gamesym.ttf" }
|
||||||
|
};
|
||||||
|
|
||||||
|
public static async Task EnsureAssets(string baseDir) {
|
||||||
|
using var client = new HttpClient();
|
||||||
|
|
||||||
|
var assetVerRemote = await client.GetStringAsync(AssetStoreUrl + "version");
|
||||||
|
|
||||||
|
var assetVerPath = Path.Combine(baseDir, "assetver");
|
||||||
|
var assetVerLocal = "0";
|
||||||
|
if (File.Exists(assetVerPath))
|
||||||
|
assetVerLocal = File.ReadAllText(assetVerPath);
|
||||||
|
|
||||||
|
var forceRedownload = assetVerLocal != assetVerRemote;
|
||||||
|
if (forceRedownload)
|
||||||
|
Log.Information("Assets need redownload");
|
||||||
|
|
||||||
|
Log.Verbose("Starting asset download");
|
||||||
|
|
||||||
|
foreach (var entry in AssetDictionary) {
|
||||||
|
var filePath = Path.Combine(baseDir, entry.Value);
|
||||||
|
|
||||||
|
Directory.CreateDirectory(Path.GetDirectoryName(filePath));
|
||||||
|
|
||||||
|
if (!File.Exists(filePath) || forceRedownload) {
|
||||||
|
Log.Verbose("Downloading {0} to {1}...", entry.Key, entry.Value);
|
||||||
|
try {
|
||||||
|
File.WriteAllBytes(filePath, await client.GetByteArrayAsync(entry.Key));
|
||||||
|
} catch (Exception ex) {
|
||||||
|
// If another game is running, we don't want to just fail in here
|
||||||
|
Log.Error(ex, "Could not download asset.");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
File.WriteAllText(assetVerPath, assetVerRemote);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
Log.Error(ex, "Could not write asset version.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -22,6 +22,7 @@ attick
|
||||||
Aida-Enna
|
Aida-Enna
|
||||||
perchbird
|
perchbird
|
||||||
Wintermute
|
Wintermute
|
||||||
|
fmauNeko
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
|
using Dalamud.Game.Chat;
|
||||||
using Dalamud.Game.ClientState.Actors.Types;
|
using Dalamud.Game.ClientState.Actors.Types;
|
||||||
using Dalamud.Game.ClientState.Actors.Types.NonPlayer;
|
using Dalamud.Game.ClientState.Actors.Types.NonPlayer;
|
||||||
using ImGuiNET;
|
using ImGuiNET;
|
||||||
|
|
@ -45,8 +46,8 @@ namespace Dalamud.Interface
|
||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
var copy = ImGui.Button("Copy all");
|
var copy = ImGui.Button("Copy all");
|
||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
ImGui.Combo("Data kind", ref this.currentKind, new[] {"ServerOpCode", "ContentFinderCondition", "State"},
|
ImGui.Combo("Data kind", ref this.currentKind, new[] {"ServerOpCode", "ContentFinderCondition", "State", "Font Test"},
|
||||||
3);
|
4);
|
||||||
|
|
||||||
ImGui.BeginChild("scrolling", new Vector2(0, 0), false, ImGuiWindowFlags.HorizontalScrollbar);
|
ImGui.BeginChild("scrolling", new Vector2(0, 0), false, ImGuiWindowFlags.HorizontalScrollbar);
|
||||||
|
|
||||||
|
|
@ -81,16 +82,16 @@ namespace Dalamud.Interface
|
||||||
stateString += $"HomeWorldName: {this.dalamud.ClientState.LocalPlayer.HomeWorld.GameData.Name}\n";
|
stateString += $"HomeWorldName: {this.dalamud.ClientState.LocalPlayer.HomeWorld.GameData.Name}\n";
|
||||||
stateString += $"LocalCID: {this.dalamud.ClientState.LocalContentId:X}\n";
|
stateString += $"LocalCID: {this.dalamud.ClientState.LocalContentId:X}\n";
|
||||||
stateString += $"LastLinkedItem: {this.dalamud.Framework.Gui.Chat.LastLinkedItemId.ToString()}\n";
|
stateString += $"LastLinkedItem: {this.dalamud.Framework.Gui.Chat.LastLinkedItemId.ToString()}\n";
|
||||||
stateString += $"TerritoryType: {this.dalamud.ClientState.TerritoryType}\n";
|
stateString += $"TerritoryType: {this.dalamud.ClientState.TerritoryType}\n\n";
|
||||||
|
|
||||||
for (var i = 0; i < this.dalamud.ClientState.Actors.Length; i++) {
|
for (var i = 0; i < this.dalamud.ClientState.Actors.Length; i++) {
|
||||||
var actor = this.dalamud.ClientState.Actors[i];
|
var actor = this.dalamud.ClientState.Actors[i];
|
||||||
|
|
||||||
stateString +=
|
stateString +=
|
||||||
$" -> {i} - {actor.Name} - {actor.Position.X} {actor.Position.Y} {actor.Position.Z}\n";
|
$"{actor.Address.ToInt64():X}:{actor.ActorId:X}[{i}] - {actor.ObjectKind} - {actor.Name} - {actor.Position.X} {actor.Position.Y} {actor.Position.Z}\n";
|
||||||
|
|
||||||
if (actor is Npc npc)
|
if (actor is Npc npc)
|
||||||
stateString += $" DataId: {npc.DataId}\n";
|
stateString += $" DataId: {npc.DataId} NameId:{npc.NameId}\n";
|
||||||
|
|
||||||
if (actor is Chara chara)
|
if (actor is Chara chara)
|
||||||
stateString +=
|
stateString +=
|
||||||
|
|
@ -105,6 +106,14 @@ namespace Dalamud.Interface
|
||||||
ImGui.TextUnformatted(stateString);
|
ImGui.TextUnformatted(stateString);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 3:
|
||||||
|
var specialChars = string.Empty;
|
||||||
|
for (var i = 0xE020; i <= 0xE0DB; i++) {
|
||||||
|
specialChars += $"0x{i:X} - {(SeIconChar) i} - {(char) i}\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.TextUnformatted(specialChars);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
ImGui.TextUnformatted("Data not ready.");
|
ImGui.TextUnformatted("Data not ready.");
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,8 @@ namespace Dalamud.Interface
|
||||||
private delegate void InstallRTSSHook();
|
private delegate void InstallRTSSHook();
|
||||||
private string rtssPath;
|
private string rtssPath;
|
||||||
|
|
||||||
|
public ImGuiIOPtr LastImGuiIoPtr;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This event gets called by a plugin UiBuilder when read
|
/// This event gets called by a plugin UiBuilder when read
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -198,7 +200,7 @@ namespace Dalamud.Interface
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private IntPtr PresentDetour(IntPtr swapChain, uint syncInterval, uint presentFlags)
|
private unsafe IntPtr PresentDetour(IntPtr swapChain, uint syncInterval, uint presentFlags)
|
||||||
{
|
{
|
||||||
if (this.scene == null)
|
if (this.scene == null)
|
||||||
{
|
{
|
||||||
|
|
@ -207,11 +209,31 @@ namespace Dalamud.Interface
|
||||||
this.scene.OnBuildUI += Display;
|
this.scene.OnBuildUI += Display;
|
||||||
this.scene.OnNewInputFrame += OnNewInputFrame;
|
this.scene.OnNewInputFrame += OnNewInputFrame;
|
||||||
|
|
||||||
|
ImFontConfigPtr fontConfig = ImGuiNative.ImFontConfig_ImFontConfig();
|
||||||
|
fontConfig.MergeMode = true;
|
||||||
|
fontConfig.PixelSnapH = true;
|
||||||
|
|
||||||
var fontPathJp = Path.Combine(this.dalamud.StartInfo.WorkingDirectory, "UIRes", "NotoSansCJKjp-Medium.otf");
|
var fontPathJp = Path.Combine(this.dalamud.StartInfo.WorkingDirectory, "UIRes", "NotoSansCJKjp-Medium.otf");
|
||||||
ImGui.GetIO().Fonts.AddFontFromFileTTF(fontPathJp, 17.0f, null, ImGui.GetIO().Fonts.GetGlyphRangesJapanese());
|
ImGui.GetIO().Fonts.AddFontFromFileTTF(fontPathJp, 17.0f, null, ImGui.GetIO().Fonts.GetGlyphRangesJapanese());
|
||||||
|
|
||||||
|
var fontPathGame = Path.Combine(this.dalamud.StartInfo.WorkingDirectory, "UIRes", "gamesym.ttf");
|
||||||
|
Log.Verbose(fontPathGame);
|
||||||
|
|
||||||
|
var rangeHandle = GCHandle.Alloc(new ushort[]
|
||||||
|
{
|
||||||
|
0xE020,
|
||||||
|
0xE0DB,
|
||||||
|
0
|
||||||
|
}, GCHandleType.Pinned);
|
||||||
|
|
||||||
|
|
||||||
|
ImGui.GetIO().Fonts.AddFontFromFileTTF(fontPathGame, 17.0f, fontConfig, rangeHandle.AddrOfPinnedObject());
|
||||||
|
|
||||||
ImGui.GetIO().Fonts.Build();
|
ImGui.GetIO().Fonts.Build();
|
||||||
|
|
||||||
|
fontConfig.Destroy();
|
||||||
|
rangeHandle.Free();
|
||||||
|
|
||||||
ImGui.GetStyle().GrabRounding = 3f;
|
ImGui.GetStyle().GrabRounding = 3f;
|
||||||
ImGui.GetStyle().FrameRounding = 4f;
|
ImGui.GetStyle().FrameRounding = 4f;
|
||||||
ImGui.GetStyle().WindowRounding = 4f;
|
ImGui.GetStyle().WindowRounding = 4f;
|
||||||
|
|
@ -297,7 +319,8 @@ namespace Dalamud.Interface
|
||||||
// they will see both cursors.
|
// they will see both cursors.
|
||||||
// Doing this here because it's somewhat application-specific behavior
|
// Doing this here because it's somewhat application-specific behavior
|
||||||
//ImGui.GetIO().MouseDrawCursor = ImGui.GetIO().WantCaptureMouse;
|
//ImGui.GetIO().MouseDrawCursor = ImGui.GetIO().WantCaptureMouse;
|
||||||
this.lastWantCapture = ImGui.GetIO().WantCaptureMouse;
|
this.LastImGuiIoPtr = ImGui.GetIO();
|
||||||
|
this.lastWantCapture = this.LastImGuiIoPtr.WantCaptureMouse;
|
||||||
|
|
||||||
OnDraw?.Invoke();
|
OnDraw?.Invoke();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ namespace Dalamud.Interface
|
||||||
{
|
{
|
||||||
private readonly DataManager data;
|
private readonly DataManager data;
|
||||||
private readonly UiBuilder builder;
|
private readonly UiBuilder builder;
|
||||||
|
private readonly bool closeOnChoose;
|
||||||
|
|
||||||
private string lastSearchText = string.Empty;
|
private string lastSearchText = string.Empty;
|
||||||
private string searchText = string.Empty;
|
private string searchText = string.Empty;
|
||||||
|
|
@ -40,14 +41,16 @@ namespace Dalamud.Interface
|
||||||
|
|
||||||
public event EventHandler<Item> OnItemChosen;
|
public event EventHandler<Item> OnItemChosen;
|
||||||
|
|
||||||
public ItemSearchWindow(DataManager data, UiBuilder builder) {
|
public ItemSearchWindow(DataManager data, UiBuilder builder, bool closeOnChoose = true) {
|
||||||
this.data = data;
|
this.data = data;
|
||||||
this.builder = builder;
|
this.builder = builder;
|
||||||
|
this.closeOnChoose = closeOnChoose;
|
||||||
|
|
||||||
while (!data.IsDataReady)
|
while (!data.IsDataReady)
|
||||||
Thread.Sleep(1);
|
Thread.Sleep(1);
|
||||||
|
|
||||||
this.luminaItems = this.data.GetExcelSheet<Item>().GetRows();
|
|
||||||
|
Task.Run(() => this.data.GetExcelSheet<Item>().GetRows()).ContinueWith(t => this.luminaItems = t.Result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Draw() {
|
public bool Draw() {
|
||||||
|
|
@ -95,56 +98,69 @@ namespace Dalamud.Interface
|
||||||
|
|
||||||
ImGui.PushStyleVar(ImGuiStyleVar.ItemSpacing, new Vector2(0, 0));
|
ImGui.PushStyleVar(ImGuiStyleVar.ItemSpacing, new Vector2(0, 0));
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(this.searchText) || this.currentKind != 0) {
|
if (this.luminaItems != null) {
|
||||||
if (this.lastSearchText != this.searchText || this.lastKind != this.currentKind) {
|
if (!string.IsNullOrEmpty(this.searchText) || this.currentKind != 0)
|
||||||
this.lastSearchText = this.searchText;
|
{
|
||||||
this.lastKind = this.currentKind;
|
if (this.lastSearchText != this.searchText || this.lastKind != this.currentKind)
|
||||||
|
{
|
||||||
|
this.lastSearchText = this.searchText;
|
||||||
|
this.lastKind = this.currentKind;
|
||||||
|
|
||||||
this.searchCancelTokenSource?.Cancel();
|
this.searchCancelTokenSource?.Cancel();
|
||||||
|
|
||||||
this.searchCancelTokenSource = new CancellationTokenSource();
|
this.searchCancelTokenSource = new CancellationTokenSource();
|
||||||
|
|
||||||
var asyncEnum = this.luminaItems.ToAsyncEnumerable();
|
var asyncEnum = this.luminaItems.ToAsyncEnumerable();
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(this.searchText)) {
|
if (!string.IsNullOrEmpty(this.searchText))
|
||||||
Log.Debug("Searching for " + this.searchText);
|
{
|
||||||
asyncEnum = asyncEnum.Where(
|
Log.Debug("Searching for " + this.searchText);
|
||||||
x => (x.Name.ToLower().Contains(this.searchText.ToLower()) ||
|
asyncEnum = asyncEnum.Where(
|
||||||
int.TryParse(this.searchText, out var parsedId) &&
|
x => (x.Name.ToLower().Contains(this.searchText.ToLower()) ||
|
||||||
parsedId == x.RowId));
|
int.TryParse(this.searchText, out var parsedId) &&
|
||||||
|
parsedId == x.RowId));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.currentKind != 0)
|
||||||
|
{
|
||||||
|
Log.Debug("Searching for C" + this.currentKind);
|
||||||
|
asyncEnum = asyncEnum.Where(x => x.ItemSearchCategory == this.currentKind);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.selectedItemIndex = -1;
|
||||||
|
this.selectedItemTex?.Dispose();
|
||||||
|
this.selectedItemTex = null;
|
||||||
|
|
||||||
|
this.searchTask = asyncEnum.ToListAsync(this.searchCancelTokenSource.Token);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.currentKind != 0) {
|
if (this.searchTask.IsCompletedSuccessfully)
|
||||||
Log.Debug("Searching for C" + this.currentKind);
|
{
|
||||||
asyncEnum = asyncEnum.Where(x => x.ItemSearchCategory == this.currentKind);
|
for (var i = 0; i < this.searchTask.Result.Count; i++)
|
||||||
|
{
|
||||||
|
if (ImGui.Selectable(this.searchTask.Result[i].Name, this.selectedItemIndex == i))
|
||||||
|
{
|
||||||
|
this.selectedItemIndex = i;
|
||||||
|
|
||||||
|
var iconTex = this.data.GetIcon(this.searchTask.Result[i].Icon);
|
||||||
|
this.selectedItemTex?.Dispose();
|
||||||
|
this.selectedItemTex =
|
||||||
|
this.builder.LoadImageRaw(iconTex.GetRgbaImageData(), iconTex.Header.Width,
|
||||||
|
iconTex.Header.Height, 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ImGui.TextColored(new Vector4(0.86f, 0.86f, 0.86f, 1.00f), Loc.Localize("DalamudItemSelectHint", "Type to start searching..."));
|
||||||
|
|
||||||
this.selectedItemIndex = -1;
|
this.selectedItemIndex = -1;
|
||||||
this.selectedItemTex?.Dispose();
|
this.selectedItemTex?.Dispose();
|
||||||
this.selectedItemTex = null;
|
this.selectedItemTex = null;
|
||||||
|
|
||||||
this.searchTask = asyncEnum.ToListAsync(this.searchCancelTokenSource.Token);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.searchTask.IsCompletedSuccessfully) {
|
|
||||||
for (var i = 0; i < this.searchTask.Result.Count; i++) {
|
|
||||||
if (ImGui.Selectable(this.searchTask.Result[i].Name, this.selectedItemIndex == i)) {
|
|
||||||
this.selectedItemIndex = i;
|
|
||||||
|
|
||||||
var iconTex = this.data.GetIcon(this.searchTask.Result[i].Icon);
|
|
||||||
this.selectedItemTex?.Dispose();
|
|
||||||
this.selectedItemTex =
|
|
||||||
this.builder.LoadImageRaw(iconTex.GetRgbaImageData(), iconTex.Header.Width,
|
|
||||||
iconTex.Header.Height, 4);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ImGui.TextColored(new Vector4(0.86f, 0.86f, 0.86f, 1.00f), Loc.Localize("DalamudItemSelectHint", "Type to start searching..."));
|
ImGui.TextColored(new Vector4(0.86f, 0.86f, 0.86f, 1.00f), Loc.Localize("DalamudItemSelectLoading", "Loading item list..."));
|
||||||
|
|
||||||
this.selectedItemIndex = -1;
|
|
||||||
this.selectedItemTex?.Dispose();
|
|
||||||
this.selectedItemTex = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui.PopStyleVar();
|
ImGui.PopStyleVar();
|
||||||
|
|
@ -153,8 +169,20 @@ namespace Dalamud.Interface
|
||||||
|
|
||||||
if (ImGui.Button(Loc.Localize("Choose", "Choose"))) {
|
if (ImGui.Button(Loc.Localize("Choose", "Choose"))) {
|
||||||
OnItemChosen?.Invoke(this, this.searchTask.Result[this.selectedItemIndex]);
|
OnItemChosen?.Invoke(this, this.searchTask.Result[this.selectedItemIndex]);
|
||||||
this.selectedItemTex?.Dispose();
|
|
||||||
isOpen = false;
|
if (this.closeOnChoose) {
|
||||||
|
this.selectedItemTex?.Dispose();
|
||||||
|
isOpen = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.closeOnChoose) {
|
||||||
|
ImGui.SameLine();
|
||||||
|
if (ImGui.Button(Loc.Localize("Close", "Close")))
|
||||||
|
{
|
||||||
|
this.selectedItemTex?.Dispose();
|
||||||
|
isOpen = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui.End();
|
ImGui.End();
|
||||||
|
|
|
||||||
|
|
@ -95,7 +95,7 @@ namespace Dalamud.Interface
|
||||||
try {
|
try {
|
||||||
OnBuildUi?.Invoke();
|
OnBuildUi?.Invoke();
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
Log.Error("[{0}] UiBuilder OnBuildUi caught exception");
|
Log.Error(ex, "[{0}] UiBuilder OnBuildUi caught exception", this.namespaceName);
|
||||||
OnBuildUi = null;
|
OnBuildUi = null;
|
||||||
OnOpenConfigUi = null;
|
OnOpenConfigUi = null;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,11 @@ namespace Dalamud
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetupWithLangCode(string langCode) {
|
public void SetupWithLangCode(string langCode) {
|
||||||
|
if (langCode.ToLower() == "en") {
|
||||||
|
Loc.SetupWithFallbacks();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Loc.Setup(File.ReadAllText(Path.Combine(this.workingDirectory, "UIRes", "loc", "dalamud", $"dalamud_{langCode}.json")));
|
Loc.Setup(File.ReadAllText(Path.Combine(this.workingDirectory, "UIRes", "loc", "dalamud", $"dalamud_{langCode}.json")));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ namespace Dalamud.Plugin
|
||||||
{
|
{
|
||||||
public class PluginRepository
|
public class PluginRepository
|
||||||
{
|
{
|
||||||
private const string PluginRepoBaseUrl = "https://goaaats.github.io/DalamudPlugins/";
|
private const string PluginRepoBaseUrl = "https://goatcorp.github.io/DalamudPlugins/";
|
||||||
|
|
||||||
private PluginManager manager;
|
private PluginManager manager;
|
||||||
private string pluginDirectory;
|
private string pluginDirectory;
|
||||||
|
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 71 KiB |
Binary file not shown.
|
|
@ -1,194 +0,0 @@
|
||||||
{
|
|
||||||
"DalamudUnloadHelp": {
|
|
||||||
"message": "Entläd das XIVLauncher In-Game-Addon.",
|
|
||||||
"description": "Dalamud.SetupCommands"
|
|
||||||
},
|
|
||||||
"DalamudPluginReloadHelp": {
|
|
||||||
"message": "Läd alle Plugins neu.",
|
|
||||||
"description": "Dalamud.SetupCommands"
|
|
||||||
},
|
|
||||||
"DalamudPrintChatHelp": {
|
|
||||||
"message": "Gibt eine Nachricht im Chat aus.",
|
|
||||||
"description": "Dalamud.SetupCommands"
|
|
||||||
},
|
|
||||||
"DalamudCmdInfoHelp": {
|
|
||||||
"message": "Zeigt eine Liste aller verfügbaren Textkommandos an.",
|
|
||||||
"description": "Dalamud.SetupCommands"
|
|
||||||
},
|
|
||||||
"DalamudMuteHelp": {
|
|
||||||
"message": "Gib ein Wort oder einen Satz ein, der nicht im Chat auftauchen soll. Nutzung: /xlmute <word or sentence>",
|
|
||||||
"description": "Dalamud.SetupCommands"
|
|
||||||
},
|
|
||||||
"DalamudMuteListHelp": {
|
|
||||||
"message": "Listet stummgeschaltete Worte oder Sätze auf.",
|
|
||||||
"description": "Dalamud.SetupCommands"
|
|
||||||
},
|
|
||||||
"DalamudUnmuteHelp": {
|
|
||||||
"message": "Löscht ein Wort oder einen Satz von der Liste der stummgeschalteten Worte. Nutzung: /xlunmute <word or sentence>",
|
|
||||||
"description": "Dalamud.SetupCommands"
|
|
||||||
},
|
|
||||||
"DalamudLastLinkHelp": {
|
|
||||||
"message": "Öffnet den zuletzt im Chat geposteten Link in deinem Browser.",
|
|
||||||
"description": "Dalamud.SetupCommands"
|
|
||||||
},
|
|
||||||
"DalamudBotJoinHelp": {
|
|
||||||
"message": "Füge den XIVLauncher Discord-Bot zu einem deiner Server hinzu.",
|
|
||||||
"description": "Dalamud.SetupCommands"
|
|
||||||
},
|
|
||||||
"DalamudBgmSetHelp": {
|
|
||||||
"message": "Setzt die Hintergrundmusik im Spiel. Nutzung: /xlbgmset <BGM ID>",
|
|
||||||
"description": "Dalamud.SetupCommands"
|
|
||||||
},
|
|
||||||
"DalamudItemLinkHelp": {
|
|
||||||
"message": "Verlinkt den angegebenen Gegenstand. Nutzung: /xlitem <Item name>. Um den exakten Namen anzugeben, nutze /xlitem +<Item name>",
|
|
||||||
"description": "Dalamud.SetupCommands"
|
|
||||||
},
|
|
||||||
"DalamudBonusHelp": {
|
|
||||||
"message": "Sende eine Benachrichtigung, wenn ein Zufallsinhalt einen Bonus für die Rolle hast, die du angibst. Nutzung: /xlbonus <roulette name> <role name>",
|
|
||||||
"description": "Dalamud.SetupCommands"
|
|
||||||
},
|
|
||||||
"DalamudDevMenuHelp": {
|
|
||||||
"message": "Öffne das dev-Menü DEBUG",
|
|
||||||
"description": "Dalamud.SetupCommands"
|
|
||||||
},
|
|
||||||
"DalamudInstallerHelp": {
|
|
||||||
"message": "Öffnet den Plugin-Installer",
|
|
||||||
"description": "Dalamud.SetupCommands"
|
|
||||||
},
|
|
||||||
"DalamudCreditsHelp": {
|
|
||||||
"message": "Öffnet die Liste der Mitwirkenden",
|
|
||||||
"description": "Dalamud.SetupCommands"
|
|
||||||
},
|
|
||||||
"DalamudCmdHelpAvailable": {
|
|
||||||
"message": "Verfügbare Kommandos:",
|
|
||||||
"description": "Dalamud.OnHelpCommand"
|
|
||||||
},
|
|
||||||
"DalamudMuted": {
|
|
||||||
"message": "\"{0}\" stummgeschaltet.",
|
|
||||||
"description": "Dalamud.OnBadWordsAddCommand"
|
|
||||||
},
|
|
||||||
"DalamudNoneMuted": {
|
|
||||||
"message": "Keine stummgeschalteten Wörte oder Sätze.",
|
|
||||||
"description": "Dalamud.OnBadWordsListCommand"
|
|
||||||
},
|
|
||||||
"DalamudUnmuted": {
|
|
||||||
"message": "\"{0}\" freigegeben.",
|
|
||||||
"description": "Dalamud.OnBadWordsRemoveCommand"
|
|
||||||
},
|
|
||||||
"DalamudNoLastLink": {
|
|
||||||
"message": "Keinen Link gefunden...",
|
|
||||||
"description": "Dalamud.OnLastLinkCommand"
|
|
||||||
},
|
|
||||||
"DalamudOpeningLink": {
|
|
||||||
"message": "{0} wird geöffnet",
|
|
||||||
"description": "Dalamud.OnLastLinkCommand"
|
|
||||||
},
|
|
||||||
"DalamudBotNotSetup": {
|
|
||||||
"message": "Der XIVLauncher Discord-Bot wurde nicht korrekt eingestellt. Bitte prüfe die Einstellungen und unser FAQ.",
|
|
||||||
"description": "Dalamud.OnBotJoinCommand"
|
|
||||||
},
|
|
||||||
"DalamudChannelNotSetup": {
|
|
||||||
"message": "Du hast keinen Discord-Kanal für diese Notifikationen eingestellt - du wirst sie also nur im Chat erhalten.\nUm einen Kanal einzustellen, nutze bitte die XIVLauncher-Einstellungen.",
|
|
||||||
"description": "Dalamud.OnRouletteBonusNotifyCommand"
|
|
||||||
},
|
|
||||||
"DalamudBonusSet": {
|
|
||||||
"message": "Bonus-Notifikationen für {0}({1}) auf {2} gesetzt",
|
|
||||||
"description": "Dalamud.OnRouletteBonusNotifyCommand"
|
|
||||||
},
|
|
||||||
"DalamudInvalidArguments": {
|
|
||||||
"message": "Parameter nicht erkannt.",
|
|
||||||
"description": "Dalamud.OnRouletteBonusNotifyCommand"
|
|
||||||
},
|
|
||||||
"DalamudBonusPossibleValues": {
|
|
||||||
"message": "Mögliche Werte für Zufallsinhalte: leveling, 506070, msq, guildhests, expert, trials, mentor, alliance, normal\nMögliche Werte für Rollen: tank, dps, healer, all, none/reset",
|
|
||||||
"description": "Dalamud.OnRouletteBonusNotifyCommand"
|
|
||||||
},
|
|
||||||
"DalamudItemNotFound": {
|
|
||||||
"message": "Gegenstand konnte nicht gefunden werden.",
|
|
||||||
"description": "<<OnItemLinkCommand>b__0>d.MoveNext"
|
|
||||||
},
|
|
||||||
"InstallerHeader": {
|
|
||||||
"message": "Plugin-Installer",
|
|
||||||
"description": "PluginInstallerWindow.Draw"
|
|
||||||
},
|
|
||||||
"InstallerHint": {
|
|
||||||
"message": "Dieses Fenster erlaubt es dir, Plugins zu installieren.\nSie werden von Drittanbietern entwickelt.",
|
|
||||||
"description": "PluginInstallerWindow.Draw"
|
|
||||||
},
|
|
||||||
"InstallerLoading": {
|
|
||||||
"message": "Plugins werden geladen...",
|
|
||||||
"description": "PluginInstallerWindow.Draw"
|
|
||||||
},
|
|
||||||
"InstallerDownloadFailed": {
|
|
||||||
"message": "Download fehlgeschlagen.",
|
|
||||||
"description": "PluginInstallerWindow.Draw"
|
|
||||||
},
|
|
||||||
"InstallerInstalled": {
|
|
||||||
"message": " (installiert)",
|
|
||||||
"description": "PluginInstallerWindow.Draw"
|
|
||||||
},
|
|
||||||
"InstallerInProgress": {
|
|
||||||
"message": "Wird installiert...",
|
|
||||||
"description": "PluginInstallerWindow.Draw"
|
|
||||||
},
|
|
||||||
"InstallerDisable": {
|
|
||||||
"message": "Deaktivieren",
|
|
||||||
"description": "PluginInstallerWindow.Draw"
|
|
||||||
},
|
|
||||||
"InstallerOpenConfig": {
|
|
||||||
"message": "Einstellungen öffnen",
|
|
||||||
"description": "PluginInstallerWindow.Draw"
|
|
||||||
},
|
|
||||||
"InstallerUpdating": {
|
|
||||||
"message": "Wird aktualisiert...",
|
|
||||||
"description": "PluginInstallerWindow.Draw"
|
|
||||||
},
|
|
||||||
"InstallerUpdateComplete": {
|
|
||||||
"message": "{0} Plugins aktualisiert!",
|
|
||||||
"description": "PluginInstallerWindow.Draw"
|
|
||||||
},
|
|
||||||
"InstallerNoUpdates": {
|
|
||||||
"message": "Keine Aktualisierungen gefunden!",
|
|
||||||
"description": "PluginInstallerWindow.Draw"
|
|
||||||
},
|
|
||||||
"InstallerUpdatePlugins": {
|
|
||||||
"message": "Plugins aktualisieren",
|
|
||||||
"description": "PluginInstallerWindow.Draw"
|
|
||||||
},
|
|
||||||
"Close": {
|
|
||||||
"message": "Schließen",
|
|
||||||
"description": "PluginInstallerWindow.Draw"
|
|
||||||
},
|
|
||||||
"InstallerError": {
|
|
||||||
"message": "Installation fehlgeschlagen",
|
|
||||||
"description": "PluginInstallerWindow.Draw"
|
|
||||||
},
|
|
||||||
"InstallerErrorHint": {
|
|
||||||
"message": "Der Plugin-Installer konnte die Operation nicht erfolgreich beenden.\nBitte starte das Spiel neu und melde diesen Fehler auf unserem Discord-Server.",
|
|
||||||
"description": "PluginInstallerWindow.Draw"
|
|
||||||
},
|
|
||||||
"OK": {
|
|
||||||
"message": "OK",
|
|
||||||
"description": "PluginInstallerWindow.Draw"
|
|
||||||
},
|
|
||||||
"DalamudWelcome": {
|
|
||||||
"message": "XIVLauncher In-Game-Addon v{0} geladen.",
|
|
||||||
"description": "ChatHandlers.OnChatMessage"
|
|
||||||
},
|
|
||||||
"DalamudPluginLoaded": {
|
|
||||||
"message": " 》 {0} v{1} geladen.",
|
|
||||||
"description": "ChatHandlers.OnChatMessage"
|
|
||||||
},
|
|
||||||
"DalamudUpdated": {
|
|
||||||
"message": "Das In-Game-Addon wurde aktualisiert oder neu installiert. Bitte prüfe unseren Discord-Server für weitere Informationen!",
|
|
||||||
"description": "ChatHandlers.OnChatMessage"
|
|
||||||
},
|
|
||||||
"DalamudPluginUpdateRequired": {
|
|
||||||
"message": "Eines oder mehrere deiner Plugins müssen aktualisiert werden. Bitte nutze das /xlplugins-Kommando, um sie zu aktualisieren.",
|
|
||||||
"description": "ChatHandlers.OnChatMessage"
|
|
||||||
},
|
|
||||||
"DalamudPluginUpdateCheckFail": {
|
|
||||||
"message": "Konnte nicht auf Plugin-Aktualisierungen prüfen.",
|
|
||||||
"description": "ChatHandlers.OnChatMessage"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,194 +0,0 @@
|
||||||
{
|
|
||||||
"DalamudUnloadHelp": {
|
|
||||||
"message": "Decarga el extra In-Game de XIVLauncher.",
|
|
||||||
"description": "Dalamud.SetupCommands"
|
|
||||||
},
|
|
||||||
"DalamudPluginReloadHelp": {
|
|
||||||
"message": "Recarga todos de los plugins.",
|
|
||||||
"description": "Dalamud.SetupCommands"
|
|
||||||
},
|
|
||||||
"DalamudPrintChatHelp": {
|
|
||||||
"message": "Publica al chat.",
|
|
||||||
"description": "Dalamud.SetupCommands"
|
|
||||||
},
|
|
||||||
"DalamudCmdInfoHelp": {
|
|
||||||
"message": "Muestre la lista de los comandos disponibles.",
|
|
||||||
"description": "Dalamud.SetupCommands"
|
|
||||||
},
|
|
||||||
"DalamudMuteHelp": {
|
|
||||||
"message": "Bloquea una palabra u oración que aperecer en el chat. Uso: /xlmute <palabra u oración>",
|
|
||||||
"description": "Dalamud.SetupCommands"
|
|
||||||
},
|
|
||||||
"DalamudMuteListHelp": {
|
|
||||||
"message": "Enumera las palabras u oraciónes qué están bloqueadas.",
|
|
||||||
"description": "Dalamud.SetupCommands"
|
|
||||||
},
|
|
||||||
"DalamudUnmuteHelp": {
|
|
||||||
"message": "Desbloquea una palabra u oración. Uso: /xlunmute <palabra u oración>",
|
|
||||||
"description": "Dalamud.SetupCommands"
|
|
||||||
},
|
|
||||||
"DalamudLastLinkHelp": {
|
|
||||||
"message": "Abre el enlace anterior en su navegador por defecto.",
|
|
||||||
"description": "Dalamud.SetupCommands"
|
|
||||||
},
|
|
||||||
"DalamudBotJoinHelp": {
|
|
||||||
"message": "Agrega el bot Discord de XIVLauncher que ha configurado a su servidor.",
|
|
||||||
"description": "Dalamud.SetupCommands"
|
|
||||||
},
|
|
||||||
"DalamudBgmSetHelp": {
|
|
||||||
"message": "Configura la música ambiental del juego. Uso: /xlbgmset <BGM ID>",
|
|
||||||
"description": "Dalamud.SetupCommands"
|
|
||||||
},
|
|
||||||
"DalamudItemLinkHelp": {
|
|
||||||
"message": "Enlaza un artículo por nombre. Uso: /xlitem <nombre del artículo>. Para emperejando un artículo exactamente, utiliza /xlitem +<nombre del artículo>",
|
|
||||||
"description": "Dalamud.SetupCommands"
|
|
||||||
},
|
|
||||||
"DalamudBonusHelp": {
|
|
||||||
"message": "Notifícase cuando una ruleta tenga un extra que usted especifica. Ejecútalo sin parametres para más información. Uso: /xlbonus <nombre de ruleta> <nombre del papel>",
|
|
||||||
"description": "Dalamud.SetupCommands"
|
|
||||||
},
|
|
||||||
"DalamudDevMenuHelp": {
|
|
||||||
"message": "Dibuja el menú dev DEBUG",
|
|
||||||
"description": "Dalamud.SetupCommands"
|
|
||||||
},
|
|
||||||
"DalamudInstallerHelp": {
|
|
||||||
"message": "Abre el instalador de plugins",
|
|
||||||
"description": "Dalamud.SetupCommands"
|
|
||||||
},
|
|
||||||
"DalamudCreditsHelp": {
|
|
||||||
"message": "Abra los méritos de Dalamud.",
|
|
||||||
"description": "Dalamud.SetupCommands"
|
|
||||||
},
|
|
||||||
"DalamudCmdHelpAvailable": {
|
|
||||||
"message": "Comandos disponibles:",
|
|
||||||
"description": "Dalamud.OnHelpCommand"
|
|
||||||
},
|
|
||||||
"DalamudMuted": {
|
|
||||||
"message": "Ha bloqueado \"{0}\".",
|
|
||||||
"description": "Dalamud.OnBadWordsAddCommand"
|
|
||||||
},
|
|
||||||
"DalamudNoneMuted": {
|
|
||||||
"message": "No hay palabras u oraciónes qué están bloqueadas.",
|
|
||||||
"description": "Dalamud.OnBadWordsListCommand"
|
|
||||||
},
|
|
||||||
"DalamudUnmuted": {
|
|
||||||
"message": "Ha desbloqueado \"{0}\".",
|
|
||||||
"description": "Dalamud.OnBadWordsRemoveCommand"
|
|
||||||
},
|
|
||||||
"DalamudNoLastLink": {
|
|
||||||
"message": "No hay un enlace anterior...",
|
|
||||||
"description": "Dalamud.OnLastLinkCommand"
|
|
||||||
},
|
|
||||||
"DalamudOpeningLink": {
|
|
||||||
"message": "Está abriendo {0}",
|
|
||||||
"description": "Dalamud.OnLastLinkCommand"
|
|
||||||
},
|
|
||||||
"DalamudBotNotSetup": {
|
|
||||||
"message": "El bot Discord de XIVLauncher no configuría corecto o no pudo conectar a Discord. Por favor revisa los ajustes y el FAQ.",
|
|
||||||
"description": "Dalamud.OnBotJoinCommand"
|
|
||||||
},
|
|
||||||
"DalamudChannelNotSetup": {
|
|
||||||
"message": "No configuría un canal Discord para estos notificaciónes - solo recibirá en el chat. Para que lo configura, por favor utiliza los ajustes de XIVLauncher en el juego.",
|
|
||||||
"description": "Dalamud.OnRouletteBonusNotifyCommand"
|
|
||||||
},
|
|
||||||
"DalamudBonusSet": {
|
|
||||||
"message": "Configura notificaciónes bonus para {0}({1}) a {2}",
|
|
||||||
"description": "Dalamud.OnRouletteBonusNotifyCommand"
|
|
||||||
},
|
|
||||||
"DalamudInvalidArguments": {
|
|
||||||
"message": "Hay argumentes que no reconocido.",
|
|
||||||
"description": "Dalamud.OnRouletteBonusNotifyCommand"
|
|
||||||
},
|
|
||||||
"DalamudBonusPossibleValues": {
|
|
||||||
"message": "Valores posibles para ruleta: leveling, 506070, msq, guildhests, expert, trials, mentor, alliance, normal\nValores posibles para rol: tank, dps, healer, all, none/reset",
|
|
||||||
"description": "Dalamud.OnRouletteBonusNotifyCommand"
|
|
||||||
},
|
|
||||||
"DalamudItemNotFound": {
|
|
||||||
"message": "No pudo encuentra el artículo.",
|
|
||||||
"description": "<<OnItemLinkCommand>b__0>d.MoveNext"
|
|
||||||
},
|
|
||||||
"InstallerHeader": {
|
|
||||||
"message": "Instalador de Plugins",
|
|
||||||
"description": "PluginInstallerWindow.Draw"
|
|
||||||
},
|
|
||||||
"InstallerHint": {
|
|
||||||
"message": "Esta ventana permite que instalar y elimnar los plugins en el juego.\nFueron hechos por desarrolladores terceros.",
|
|
||||||
"description": "PluginInstallerWindow.Draw"
|
|
||||||
},
|
|
||||||
"InstallerLoading": {
|
|
||||||
"message": "Está cargando los plugins...",
|
|
||||||
"description": "PluginInstallerWindow.Draw"
|
|
||||||
},
|
|
||||||
"InstallerDownloadFailed": {
|
|
||||||
"message": "La descarga falló.",
|
|
||||||
"description": "PluginInstallerWindow.Draw"
|
|
||||||
},
|
|
||||||
"InstallerInstalled": {
|
|
||||||
"message": " (instalado)",
|
|
||||||
"description": "PluginInstallerWindow.Draw"
|
|
||||||
},
|
|
||||||
"InstallerInProgress": {
|
|
||||||
"message": "Instalación en curso...",
|
|
||||||
"description": "PluginInstallerWindow.Draw"
|
|
||||||
},
|
|
||||||
"InstallerDisable": {
|
|
||||||
"message": "Desactiva",
|
|
||||||
"description": "PluginInstallerWindow.Draw"
|
|
||||||
},
|
|
||||||
"InstallerOpenConfig": {
|
|
||||||
"message": "Abre Configuración",
|
|
||||||
"description": "PluginInstallerWindow.Draw"
|
|
||||||
},
|
|
||||||
"InstallerUpdating": {
|
|
||||||
"message": "Actualizando...",
|
|
||||||
"description": "PluginInstallerWindow.Draw"
|
|
||||||
},
|
|
||||||
"InstallerUpdateComplete": {
|
|
||||||
"message": "¡{0} plugins han actualizado!",
|
|
||||||
"description": "PluginInstallerWindow.Draw"
|
|
||||||
},
|
|
||||||
"InstallerNoUpdates": {
|
|
||||||
"message": "¡No hay actualizaciónes!",
|
|
||||||
"description": "PluginInstallerWindow.Draw"
|
|
||||||
},
|
|
||||||
"InstallerUpdatePlugins": {
|
|
||||||
"message": "Actualiza plugins",
|
|
||||||
"description": "PluginInstallerWindow.Draw"
|
|
||||||
},
|
|
||||||
"Close": {
|
|
||||||
"message": "Cierra",
|
|
||||||
"description": "PluginInstallerWindow.Draw"
|
|
||||||
},
|
|
||||||
"InstallerError": {
|
|
||||||
"message": "El instalador falló",
|
|
||||||
"description": "PluginInstallerWindow.Draw"
|
|
||||||
},
|
|
||||||
"InstallerErrorHint": {
|
|
||||||
"message": "El instalador de plugins corrió a una problema, o el plugin está incompatible.\nPor favor reinicia el juego y informa el error en neustro Discord.",
|
|
||||||
"description": "PluginInstallerWindow.Draw"
|
|
||||||
},
|
|
||||||
"OK": {
|
|
||||||
"message": "OK",
|
|
||||||
"description": "PluginInstallerWindow.Draw"
|
|
||||||
},
|
|
||||||
"DalamudWelcome": {
|
|
||||||
"message": "El extra In-Game v{0} de XIVLauncher ha cargado.",
|
|
||||||
"description": "ChatHandlers.OnChatMessage"
|
|
||||||
},
|
|
||||||
"DalamudPluginLoaded": {
|
|
||||||
"message": " 》 {0} v{1} ha cargado.",
|
|
||||||
"description": "ChatHandlers.OnChatMessage"
|
|
||||||
},
|
|
||||||
"DalamudUpdated": {
|
|
||||||
"message": "¡El extra In-Game había actualizado o reinstalado con éxito! Por favor comproba el Discord para un changelog completo.",
|
|
||||||
"description": "ChatHandlers.OnChatMessage"
|
|
||||||
},
|
|
||||||
"DalamudPluginUpdateRequired": {
|
|
||||||
"message": "Uno o más de sus plugins deben habar actualizado. ¡Por favor utiliza el comando /xlplugins para los actualizan!",
|
|
||||||
"description": "ChatHandlers.OnChatMessage"
|
|
||||||
},
|
|
||||||
"DalamudPluginUpdateCheckFail": {
|
|
||||||
"message": "No pudo buscar para actualizaciónes de los plugins.",
|
|
||||||
"description": "ChatHandlers.OnChatMessage"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,194 +0,0 @@
|
||||||
{
|
|
||||||
"DalamudUnloadHelp": {
|
|
||||||
"message": "Désactive l'addon in-game de XIVLauncher.",
|
|
||||||
"description": "Dalamud.SetupCommands"
|
|
||||||
},
|
|
||||||
"DalamudPluginReloadHelp": {
|
|
||||||
"message": "Recharge tous les plugins.",
|
|
||||||
"description": "Dalamud.SetupCommands"
|
|
||||||
},
|
|
||||||
"DalamudPrintChatHelp": {
|
|
||||||
"message": "Afficher dans le chat.",
|
|
||||||
"description": "Dalamud.SetupCommands"
|
|
||||||
},
|
|
||||||
"DalamudCmdInfoHelp": {
|
|
||||||
"message": "Montre la liste des commandes disponibles.",
|
|
||||||
"description": "Dalamud.SetupCommands"
|
|
||||||
},
|
|
||||||
"DalamudMuteHelp": {
|
|
||||||
"message": "Met en sourdine un mot ou une phrase dans le chat. Utilisation : /xlmute <mot ou phrase>",
|
|
||||||
"description": "Dalamud.SetupCommands"
|
|
||||||
},
|
|
||||||
"DalamudMuteListHelp": {
|
|
||||||
"message": "Liste les mots ou phrases en sourdine.",
|
|
||||||
"description": "Dalamud.SetupCommands"
|
|
||||||
},
|
|
||||||
"DalamudUnmuteHelp": {
|
|
||||||
"message": "Ré-affiche un mot ou une phrase. Utilisation : /xlunmute <mot ou phrase>",
|
|
||||||
"description": "Dalamud.SetupCommands"
|
|
||||||
},
|
|
||||||
"DalamudLastLinkHelp": {
|
|
||||||
"message": "Ouvre le dernier lien affiché dans le chat dans votre navigateur par défaut.",
|
|
||||||
"description": "Dalamud.SetupCommands"
|
|
||||||
},
|
|
||||||
"DalamudBotJoinHelp": {
|
|
||||||
"message": "Ajoute le bot discord XIVLauncher que vous avez configuré à votre serveur.",
|
|
||||||
"description": "Dalamud.SetupCommands"
|
|
||||||
},
|
|
||||||
"DalamudBgmSetHelp": {
|
|
||||||
"message": "Définit la musique de fond. Utilisation : /xlbgmset <BGM ID>",
|
|
||||||
"description": "Dalamud.SetupCommands"
|
|
||||||
},
|
|
||||||
"DalamudItemLinkHelp": {
|
|
||||||
"message": "Envoie le lien d'un objet grâce à son nom. Utilisation : /xlitem <Nom de l'objet>. Pour trouver un objet précis, utilisez /xlitem +<Nom de l'objet>",
|
|
||||||
"description": "Dalamud.SetupCommands"
|
|
||||||
},
|
|
||||||
"DalamudBonusHelp": {
|
|
||||||
"message": "Informe lorsque une mission aléatoire possède le bonus spécifié. Exécuter sans paramètres pour plus d'infos. Utilisation : /xlbonus <nom de la mission aléatoire> <nom du rôle>",
|
|
||||||
"description": "Dalamud.SetupCommands"
|
|
||||||
},
|
|
||||||
"DalamudDevMenuHelp": {
|
|
||||||
"message": "Fait sortir le menu dev DEBUG",
|
|
||||||
"description": "Dalamud.SetupCommands"
|
|
||||||
},
|
|
||||||
"DalamudInstallerHelp": {
|
|
||||||
"message": "Ouvrir l’installateur de plugins",
|
|
||||||
"description": "Dalamud.SetupCommands"
|
|
||||||
},
|
|
||||||
"DalamudCreditsHelp": {
|
|
||||||
"message": "Ouvre la liste des participants.",
|
|
||||||
"description": "Dalamud.SetupCommands"
|
|
||||||
},
|
|
||||||
"DalamudCmdHelpAvailable": {
|
|
||||||
"message": "Commandes disponibles :",
|
|
||||||
"description": "Dalamud.OnHelpCommand"
|
|
||||||
},
|
|
||||||
"DalamudMuted": {
|
|
||||||
"message": "\"{0}\" est mis en sourdine.",
|
|
||||||
"description": "Dalamud.OnBadWordsAddCommand"
|
|
||||||
},
|
|
||||||
"DalamudNoneMuted": {
|
|
||||||
"message": "Pas de mots ou phrases en sourdine.",
|
|
||||||
"description": "Dalamud.OnBadWordsListCommand"
|
|
||||||
},
|
|
||||||
"DalamudUnmuted": {
|
|
||||||
"message": "\"{0}\" est de nouveau visible.",
|
|
||||||
"description": "Dalamud.OnBadWordsRemoveCommand"
|
|
||||||
},
|
|
||||||
"DalamudNoLastLink": {
|
|
||||||
"message": "Il n'y a pas de lien...",
|
|
||||||
"description": "Dalamud.OnLastLinkCommand"
|
|
||||||
},
|
|
||||||
"DalamudOpeningLink": {
|
|
||||||
"message": "Ouverture de {0}",
|
|
||||||
"description": "Dalamud.OnLastLinkCommand"
|
|
||||||
},
|
|
||||||
"DalamudBotNotSetup": {
|
|
||||||
"message": "Le bot discord XIVLauncher n'a pas été configuré correctement ou ne peut pas se connecter à discord. Veuillez vérifier les paramètres et la FAQ.",
|
|
||||||
"description": "Dalamud.OnBotJoinCommand"
|
|
||||||
},
|
|
||||||
"DalamudChannelNotSetup": {
|
|
||||||
"message": "Vous n'avez pas configuré de canal discord pour ces notifications - vous les recevrez uniquement dans le chat. Pour ce faire, veuillez utiliser les paramètres \"In-game\" dans XIVLauncher.",
|
|
||||||
"description": "Dalamud.OnRouletteBonusNotifyCommand"
|
|
||||||
},
|
|
||||||
"DalamudBonusSet": {
|
|
||||||
"message": "Définit les notifications de bonus pour {0}({1}) à {2}",
|
|
||||||
"description": "Dalamud.OnRouletteBonusNotifyCommand"
|
|
||||||
},
|
|
||||||
"DalamudInvalidArguments": {
|
|
||||||
"message": "Arguments non-reconnus.",
|
|
||||||
"description": "Dalamud.OnRouletteBonusNotifyCommand"
|
|
||||||
},
|
|
||||||
"DalamudBonusPossibleValues": {
|
|
||||||
"message": "Valeurs possibles pour mission aléatoire : leveling, 506070, msq, guildhests, expert, trials, mentor, alliance, normal\nValeurs possibles pour rôle : tank, dps, healer, all, none/reset",
|
|
||||||
"description": "Dalamud.OnRouletteBonusNotifyCommand"
|
|
||||||
},
|
|
||||||
"DalamudItemNotFound": {
|
|
||||||
"message": "L'objet n'a pas pu être trouvé.",
|
|
||||||
"description": "<<OnItemLinkCommand>b__0>d.MoveNext"
|
|
||||||
},
|
|
||||||
"InstallerHeader": {
|
|
||||||
"message": "Installateur de Plugin",
|
|
||||||
"description": "PluginInstallerWindow.Draw"
|
|
||||||
},
|
|
||||||
"InstallerHint": {
|
|
||||||
"message": "Cette fenêtre vous autorise à installer ou retirer des plugins en jeu.\nIls sont créés par des développeurs tiers.",
|
|
||||||
"description": "PluginInstallerWindow.Draw"
|
|
||||||
},
|
|
||||||
"InstallerLoading": {
|
|
||||||
"message": "Chargement des plugins...",
|
|
||||||
"description": "PluginInstallerWindow.Draw"
|
|
||||||
},
|
|
||||||
"InstallerDownloadFailed": {
|
|
||||||
"message": "Le téléchargement a échoué.",
|
|
||||||
"description": "PluginInstallerWindow.Draw"
|
|
||||||
},
|
|
||||||
"InstallerInstalled": {
|
|
||||||
"message": " (installé)",
|
|
||||||
"description": "PluginInstallerWindow.Draw"
|
|
||||||
},
|
|
||||||
"InstallerInProgress": {
|
|
||||||
"message": "Installation en cours...",
|
|
||||||
"description": "PluginInstallerWindow.Draw"
|
|
||||||
},
|
|
||||||
"InstallerDisable": {
|
|
||||||
"message": "Désactiver",
|
|
||||||
"description": "PluginInstallerWindow.Draw"
|
|
||||||
},
|
|
||||||
"InstallerOpenConfig": {
|
|
||||||
"message": "Ouvrir la configuration",
|
|
||||||
"description": "PluginInstallerWindow.Draw"
|
|
||||||
},
|
|
||||||
"InstallerUpdating": {
|
|
||||||
"message": "Mise à jour...",
|
|
||||||
"description": "PluginInstallerWindow.Draw"
|
|
||||||
},
|
|
||||||
"InstallerUpdateComplete": {
|
|
||||||
"message": "{0} plugin(s) mis à jour !",
|
|
||||||
"description": "PluginInstallerWindow.Draw"
|
|
||||||
},
|
|
||||||
"InstallerNoUpdates": {
|
|
||||||
"message": "Pas de mise à jour trouvée !",
|
|
||||||
"description": "PluginInstallerWindow.Draw"
|
|
||||||
},
|
|
||||||
"InstallerUpdatePlugins": {
|
|
||||||
"message": "Mettre à jour les plugins",
|
|
||||||
"description": "PluginInstallerWindow.Draw"
|
|
||||||
},
|
|
||||||
"Close": {
|
|
||||||
"message": "Fermer",
|
|
||||||
"description": "PluginInstallerWindow.Draw"
|
|
||||||
},
|
|
||||||
"InstallerError": {
|
|
||||||
"message": "Échec de l'installation",
|
|
||||||
"description": "PluginInstallerWindow.Draw"
|
|
||||||
},
|
|
||||||
"InstallerErrorHint": {
|
|
||||||
"message": "L'installateur de plugins a rencontré un problème ou le plugin est incompatible.\nVeuillez redémarrer le jeu et rapporter cette erreur sur notre discord.",
|
|
||||||
"description": "PluginInstallerWindow.Draw"
|
|
||||||
},
|
|
||||||
"OK": {
|
|
||||||
"message": "OK",
|
|
||||||
"description": "PluginInstallerWindow.Draw"
|
|
||||||
},
|
|
||||||
"DalamudWelcome": {
|
|
||||||
"message": "Addon en jeu XIVLauncher v{0} chargé.",
|
|
||||||
"description": "ChatHandlers.OnChatMessage"
|
|
||||||
},
|
|
||||||
"DalamudPluginLoaded": {
|
|
||||||
"message": " 》 {0} v{1} chargé.",
|
|
||||||
"description": "ChatHandlers.OnChatMessage"
|
|
||||||
},
|
|
||||||
"DalamudUpdated": {
|
|
||||||
"message": "L'addon en jeu à été mis à jour ou réinstallé avec succès ! Veuillez consulter le discord pour plus d'informations.",
|
|
||||||
"description": "ChatHandlers.OnChatMessage"
|
|
||||||
},
|
|
||||||
"DalamudPluginUpdateRequired": {
|
|
||||||
"message": "Un ou plusieurs plugins ne sont plus à jour. Veuillez utiliser la commande en jeu /xlplugins pour les mettre à jour !",
|
|
||||||
"description": "ChatHandlers.OnChatMessage"
|
|
||||||
},
|
|
||||||
"DalamudPluginUpdateCheckFail": {
|
|
||||||
"message": "Impossible de vérifier les mises à jour des plugins.",
|
|
||||||
"description": "ChatHandlers.OnChatMessage"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,194 +0,0 @@
|
||||||
{
|
|
||||||
"DalamudUnloadHelp": {
|
|
||||||
"message": "Disattiva l'addon in gioco di XIVLauncher.",
|
|
||||||
"description": "Dalamud.SetupCommands"
|
|
||||||
},
|
|
||||||
"DalamudPluginReloadHelp": {
|
|
||||||
"message": "Ricarica tutti i plugin.",
|
|
||||||
"description": "Dalamud.SetupCommands"
|
|
||||||
},
|
|
||||||
"DalamudPrintChatHelp": {
|
|
||||||
"message": "Stampa in chat.",
|
|
||||||
"description": "Dalamud.SetupCommands"
|
|
||||||
},
|
|
||||||
"DalamudCmdInfoHelp": {
|
|
||||||
"message": "Mostra lista dei comandi disponibili.",
|
|
||||||
"description": "Dalamud.SetupCommands"
|
|
||||||
},
|
|
||||||
"DalamudMuteHelp": {
|
|
||||||
"message": "Proibisci a una parola o a una frase di apparire in chat. Uso: /xlmute <parola o frase>",
|
|
||||||
"description": "Dalamud.SetupCommands"
|
|
||||||
},
|
|
||||||
"DalamudMuteListHelp": {
|
|
||||||
"message": "Elenca parole e frasi proibite.",
|
|
||||||
"description": "Dalamud.SetupCommands"
|
|
||||||
},
|
|
||||||
"DalamudUnmuteHelp": {
|
|
||||||
"message": "Permetti a una parola o a una frase di apparire in chat. Uso: /xlunmute <parola o frase>",
|
|
||||||
"description": "Dalamud.SetupCommands"
|
|
||||||
},
|
|
||||||
"DalamudLastLinkHelp": {
|
|
||||||
"message": "Apri il link piú recente della chat nel tuo browser predefinito.",
|
|
||||||
"description": "Dalamud.SetupCommands"
|
|
||||||
},
|
|
||||||
"DalamudBotJoinHelp": {
|
|
||||||
"message": "Aggiungi al tuo server il bot Discord di XIVLauncher che hai impostato.",
|
|
||||||
"description": "Dalamud.SetupCommands"
|
|
||||||
},
|
|
||||||
"DalamudBgmSetHelp": {
|
|
||||||
"message": "Imposta la musica di sottofondo del gioco. Uso: /xlbgmset <ID Musica>",
|
|
||||||
"description": "Dalamud.SetupCommands"
|
|
||||||
},
|
|
||||||
"DalamudItemLinkHelp": {
|
|
||||||
"message": "Linka un oggetto per nome. Uso: /xlitem <Nome oggetto>. Per abbinare un oggetto specifico, usa /xlitem +<Nome oggetto>",
|
|
||||||
"description": "Dalamud.SetupCommands"
|
|
||||||
},
|
|
||||||
"DalamudBonusHelp": {
|
|
||||||
"message": "Notificami quando una roulette contiene un bonus specifico. Esegui senza parametri aggiuntivi per maggiori informazioni. Uso: /xlbonus <Nome roulette> <Nome ruolo>",
|
|
||||||
"description": "Dalamud.SetupCommands"
|
|
||||||
},
|
|
||||||
"DalamudDevMenuHelp": {
|
|
||||||
"message": "Mostra menu sviluppatore DEBUG",
|
|
||||||
"description": "Dalamud.SetupCommands"
|
|
||||||
},
|
|
||||||
"DalamudInstallerHelp": {
|
|
||||||
"message": "Apri l'installatore dei plugin",
|
|
||||||
"description": "Dalamud.SetupCommands"
|
|
||||||
},
|
|
||||||
"DalamudCreditsHelp": {
|
|
||||||
"message": "Apri i titoli di coda per dalamud.",
|
|
||||||
"description": "Dalamud.SetupCommands"
|
|
||||||
},
|
|
||||||
"DalamudCmdHelpAvailable": {
|
|
||||||
"message": "Comandi disponibili:",
|
|
||||||
"description": "Dalamud.OnHelpCommand"
|
|
||||||
},
|
|
||||||
"DalamudMuted": {
|
|
||||||
"message": "Silenziato \"{0}\".",
|
|
||||||
"description": "Dalamud.OnBadWordsAddCommand"
|
|
||||||
},
|
|
||||||
"DalamudNoneMuted": {
|
|
||||||
"message": "Nessuna parola o frase proibita.",
|
|
||||||
"description": "Dalamud.OnBadWordsListCommand"
|
|
||||||
},
|
|
||||||
"DalamudUnmuted": {
|
|
||||||
"message": "Riattivato \"{0}\".",
|
|
||||||
"description": "Dalamud.OnBadWordsRemoveCommand"
|
|
||||||
},
|
|
||||||
"DalamudNoLastLink": {
|
|
||||||
"message": "Nessun link recente...",
|
|
||||||
"description": "Dalamud.OnLastLinkCommand"
|
|
||||||
},
|
|
||||||
"DalamudOpeningLink": {
|
|
||||||
"message": "Aprendo {0}",
|
|
||||||
"description": "Dalamud.OnLastLinkCommand"
|
|
||||||
},
|
|
||||||
"DalamudBotNotSetup": {
|
|
||||||
"message": "Il bot Discord di XIVLauncher non è stato impostato correttamente o non ha potuto connettersi a Discord. Per favore controlla le impostazioni e le FAQ.",
|
|
||||||
"description": "Dalamud.OnBotJoinCommand"
|
|
||||||
},
|
|
||||||
"DalamudChannelNotSetup": {
|
|
||||||
"message": "Non hai impostato un canale Discord per queste notifiche - Per fare ció, utilizza le impostazioni di gioco di XIVLauncher. Al momento, riceverai le notifiche solo nella chat.",
|
|
||||||
"description": "Dalamud.OnRouletteBonusNotifyCommand"
|
|
||||||
},
|
|
||||||
"DalamudBonusSet": {
|
|
||||||
"message": "Impostate notifiche bonus per {0}({1} a {2})",
|
|
||||||
"description": "Dalamud.OnRouletteBonusNotifyCommand"
|
|
||||||
},
|
|
||||||
"DalamudInvalidArguments": {
|
|
||||||
"message": "Argomenti non risconosciuti.",
|
|
||||||
"description": "Dalamud.OnRouletteBonusNotifyCommand"
|
|
||||||
},
|
|
||||||
"DalamudBonusPossibleValues": {
|
|
||||||
"message": "Possibili valori per la roulette: leveling, 506070, msq, guildhests, expert, trials, mentor, alliance, normal\nPossibili valori per i ruoli: tank, dps, healer, all, none/reset",
|
|
||||||
"description": "Dalamud.OnRouletteBonusNotifyCommand"
|
|
||||||
},
|
|
||||||
"DalamudItemNotFound": {
|
|
||||||
"message": "Oggetto non trovato.",
|
|
||||||
"description": "<<OnItemLinkCommand>b__0>d.MoveNext"
|
|
||||||
},
|
|
||||||
"InstallerHeader": {
|
|
||||||
"message": "Installatore Plugin",
|
|
||||||
"description": "PluginInstallerWindow.Draw"
|
|
||||||
},
|
|
||||||
"InstallerHint": {
|
|
||||||
"message": "Questa finestra ti permette di installare e rimuovere i plugin di gioco.\nSono sviluppati da terze parti.",
|
|
||||||
"description": "PluginInstallerWindow.Draw"
|
|
||||||
},
|
|
||||||
"InstallerLoading": {
|
|
||||||
"message": "Caricamento plugins...",
|
|
||||||
"description": "PluginInstallerWindow.Draw"
|
|
||||||
},
|
|
||||||
"InstallerDownloadFailed": {
|
|
||||||
"message": "Download fallito.",
|
|
||||||
"description": "PluginInstallerWindow.Draw"
|
|
||||||
},
|
|
||||||
"InstallerInstalled": {
|
|
||||||
"message": " (installato)",
|
|
||||||
"description": "PluginInstallerWindow.Draw"
|
|
||||||
},
|
|
||||||
"InstallerInProgress": {
|
|
||||||
"message": "Installazione in corso...",
|
|
||||||
"description": "PluginInstallerWindow.Draw"
|
|
||||||
},
|
|
||||||
"InstallerDisable": {
|
|
||||||
"message": "Disabilita",
|
|
||||||
"description": "PluginInstallerWindow.Draw"
|
|
||||||
},
|
|
||||||
"InstallerOpenConfig": {
|
|
||||||
"message": "Apri configurazione",
|
|
||||||
"description": "PluginInstallerWindow.Draw"
|
|
||||||
},
|
|
||||||
"InstallerUpdating": {
|
|
||||||
"message": "Aggiornamento...",
|
|
||||||
"description": "PluginInstallerWindow.Draw"
|
|
||||||
},
|
|
||||||
"InstallerUpdateComplete": {
|
|
||||||
"message": "{0} plugins aggiornati!",
|
|
||||||
"description": "PluginInstallerWindow.Draw"
|
|
||||||
},
|
|
||||||
"InstallerNoUpdates": {
|
|
||||||
"message": "Nessun aggiornamento trovato!",
|
|
||||||
"description": "PluginInstallerWindow.Draw"
|
|
||||||
},
|
|
||||||
"InstallerUpdatePlugins": {
|
|
||||||
"message": "Aggiorna plugins",
|
|
||||||
"description": "PluginInstallerWindow.Draw"
|
|
||||||
},
|
|
||||||
"Close": {
|
|
||||||
"message": "Chiudi",
|
|
||||||
"description": "PluginInstallerWindow.Draw"
|
|
||||||
},
|
|
||||||
"InstallerError": {
|
|
||||||
"message": "Installazione fallita",
|
|
||||||
"description": "PluginInstallerWindow.Draw"
|
|
||||||
},
|
|
||||||
"InstallerErrorHint": {
|
|
||||||
"message": "L'installatore ha riscontrato dei problemi o il plugin é incompatibile.\nRiavvia il gioco e segnalaci questo errore sul nostro Discord.",
|
|
||||||
"description": "PluginInstallerWindow.Draw"
|
|
||||||
},
|
|
||||||
"OK": {
|
|
||||||
"message": "OK",
|
|
||||||
"description": "PluginInstallerWindow.Draw"
|
|
||||||
},
|
|
||||||
"DalamudWelcome": {
|
|
||||||
"message": "XIVLauncher addon in gioco v{0} caricato.",
|
|
||||||
"description": "ChatHandlers.OnChatMessage"
|
|
||||||
},
|
|
||||||
"DalamudPluginLoaded": {
|
|
||||||
"message": " 》 {0} v{1} caricato.",
|
|
||||||
"description": "ChatHandlers.OnChatMessage"
|
|
||||||
},
|
|
||||||
"DalamudUpdated": {
|
|
||||||
"message": "L'addon in gioco è stato aggiornato o reinstallato con successo! Controlla su Discord per un changelog completo.",
|
|
||||||
"description": "ChatHandlers.OnChatMessage"
|
|
||||||
},
|
|
||||||
"DalamudPluginUpdateRequired": {
|
|
||||||
"message": "Uno o piú dei tuoi plugins necessita un aggiornamento. Usa il comando /xlplugins in gioco per aggiornarli!",
|
|
||||||
"description": "ChatHandlers.OnChatMessage"
|
|
||||||
},
|
|
||||||
"DalamudPluginUpdateCheckFail": {
|
|
||||||
"message": "Non è stato possibile controllare gli aggiornamenti dei plugin.",
|
|
||||||
"description": "ChatHandlers.OnChatMessage"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,194 +0,0 @@
|
||||||
{
|
|
||||||
"DalamudUnloadHelp": {
|
|
||||||
"message": "XIVLauncher In-Game アドオンをアンロードします。",
|
|
||||||
"description": "Dalamud.SetupCommands"
|
|
||||||
},
|
|
||||||
"DalamudPluginReloadHelp": {
|
|
||||||
"message": "全てのプラグインをリロードします。",
|
|
||||||
"description": "Dalamud.SetupCommands"
|
|
||||||
},
|
|
||||||
"DalamudPrintChatHelp": {
|
|
||||||
"message": "チャットに出力する。",
|
|
||||||
"description": "Dalamud.SetupCommands"
|
|
||||||
},
|
|
||||||
"DalamudCmdInfoHelp": {
|
|
||||||
"message": "利用可能なコマンド一覧を表示します。",
|
|
||||||
"description": "Dalamud.SetupCommands"
|
|
||||||
},
|
|
||||||
"DalamudMuteHelp": {
|
|
||||||
"message": "チャットに表示される単語や文章をミュートします。 利用法: /xlmute <単語 または、文章>",
|
|
||||||
"description": "Dalamud.SetupCommands"
|
|
||||||
},
|
|
||||||
"DalamudMuteListHelp": {
|
|
||||||
"message": "ミュートされた単語または文章の一覧を表示します。",
|
|
||||||
"description": "Dalamud.SetupCommands"
|
|
||||||
},
|
|
||||||
"DalamudUnmuteHelp": {
|
|
||||||
"message": "単語または文章のミュートを解除します。利用法: /xlunmute <単語 または、文章>",
|
|
||||||
"description": "Dalamud.SetupCommands"
|
|
||||||
},
|
|
||||||
"DalamudLastLinkHelp": {
|
|
||||||
"message": "デフォルトブラウザで直前に投稿したリンクを開きます。",
|
|
||||||
"description": "Dalamud.SetupCommands"
|
|
||||||
},
|
|
||||||
"DalamudBotJoinHelp": {
|
|
||||||
"message": "設定した XIVLauncher の Discord ボットを自分のサーバーへ追加します。",
|
|
||||||
"description": "Dalamud.SetupCommands"
|
|
||||||
},
|
|
||||||
"DalamudBgmSetHelp": {
|
|
||||||
"message": "ゲームBGMを設定します。利用法: /xlbgmset <BGM ID>",
|
|
||||||
"description": "Dalamud.SetupCommands"
|
|
||||||
},
|
|
||||||
"DalamudItemLinkHelp": {
|
|
||||||
"message": "アイテムを名前でリンクします。使用法: /xlitem <アイテム名> アイテム名を完全一致したい場合: /xlitem +<アイテム名>",
|
|
||||||
"description": "Dalamud.SetupCommands"
|
|
||||||
},
|
|
||||||
"DalamudBonusHelp": {
|
|
||||||
"message": "ルーレットに指定したボーナスがある場合に通知します。詳細はパラメータなしで実行してください。使用法: /xlbonus <ルーレット名> <ロール名>",
|
|
||||||
"description": "Dalamud.SetupCommands"
|
|
||||||
},
|
|
||||||
"DalamudDevMenuHelp": {
|
|
||||||
"message": "DEBUG 開発メニューを表示します。",
|
|
||||||
"description": "Dalamud.SetupCommands"
|
|
||||||
},
|
|
||||||
"DalamudInstallerHelp": {
|
|
||||||
"message": "プラグインインストーラを開きます",
|
|
||||||
"description": "Dalamud.SetupCommands"
|
|
||||||
},
|
|
||||||
"DalamudCreditsHelp": {
|
|
||||||
"message": "Dalamud のクレジットを開きます。",
|
|
||||||
"description": "Dalamud.SetupCommands"
|
|
||||||
},
|
|
||||||
"DalamudCmdHelpAvailable": {
|
|
||||||
"message": "利用可能なコマンド:",
|
|
||||||
"description": "Dalamud.OnHelpCommand"
|
|
||||||
},
|
|
||||||
"DalamudMuted": {
|
|
||||||
"message": "\"{0}\" をミュートしました。",
|
|
||||||
"description": "Dalamud.OnBadWordsAddCommand"
|
|
||||||
},
|
|
||||||
"DalamudNoneMuted": {
|
|
||||||
"message": "ミュートされている単語または、文章はありません。",
|
|
||||||
"description": "Dalamud.OnBadWordsListCommand"
|
|
||||||
},
|
|
||||||
"DalamudUnmuted": {
|
|
||||||
"message": "\"{0}\" のミュートを解除しました。",
|
|
||||||
"description": "Dalamud.OnBadWordsRemoveCommand"
|
|
||||||
},
|
|
||||||
"DalamudNoLastLink": {
|
|
||||||
"message": "直前のリンクがありません……",
|
|
||||||
"description": "Dalamud.OnLastLinkCommand"
|
|
||||||
},
|
|
||||||
"DalamudOpeningLink": {
|
|
||||||
"message": "{0} を開いています。",
|
|
||||||
"description": "Dalamud.OnLastLinkCommand"
|
|
||||||
},
|
|
||||||
"DalamudBotNotSetup": {
|
|
||||||
"message": "XIVLauncher の Discordボットが正しく設定されていないか、Discord に接続できませんでした。設定やFAQをご確認ください。",
|
|
||||||
"description": "Dalamud.OnBotJoinCommand"
|
|
||||||
},
|
|
||||||
"DalamudChannelNotSetup": {
|
|
||||||
"message": "通知用の Discord チャンネルを設定していません (チャットでのみ受信できます)。Discord で通知を受け取るには、XIVLauncher の In-Game 設定をしてください。",
|
|
||||||
"description": "Dalamud.OnRouletteBonusNotifyCommand"
|
|
||||||
},
|
|
||||||
"DalamudBonusSet": {
|
|
||||||
"message": "{0}({1}) のボーナス通知を {2} に設定します",
|
|
||||||
"description": "Dalamud.OnRouletteBonusNotifyCommand"
|
|
||||||
},
|
|
||||||
"DalamudInvalidArguments": {
|
|
||||||
"message": "認識できないパラメータです。",
|
|
||||||
"description": "Dalamud.OnRouletteBonusNotifyCommand"
|
|
||||||
},
|
|
||||||
"DalamudBonusPossibleValues": {
|
|
||||||
"message": "ルーレットの可能な入力:leveling, 506070, msq, guildhests, expert, trials, mentor, alliance, normal\nロールの可能な入力:tank, dps, healer, all, none/reset",
|
|
||||||
"description": "Dalamud.OnRouletteBonusNotifyCommand"
|
|
||||||
},
|
|
||||||
"DalamudItemNotFound": {
|
|
||||||
"message": "アイテムを見つけられませんでした。",
|
|
||||||
"description": "<<OnItemLinkCommand>b__0>d.MoveNext"
|
|
||||||
},
|
|
||||||
"InstallerHeader": {
|
|
||||||
"message": "プラグインインストーラ",
|
|
||||||
"description": "PluginInstallerWindow.Draw"
|
|
||||||
},
|
|
||||||
"InstallerHint": {
|
|
||||||
"message": "このウィンドウでは、In-Game プラグインのインストールと削除を行うことができます。\nこれらはサードパーティの開発者によって作られたものです。",
|
|
||||||
"description": "PluginInstallerWindow.Draw"
|
|
||||||
},
|
|
||||||
"InstallerLoading": {
|
|
||||||
"message": "プラグインをロード中……",
|
|
||||||
"description": "PluginInstallerWindow.Draw"
|
|
||||||
},
|
|
||||||
"InstallerDownloadFailed": {
|
|
||||||
"message": "ダウンロードが失敗しました。",
|
|
||||||
"description": "PluginInstallerWindow.Draw"
|
|
||||||
},
|
|
||||||
"InstallerInstalled": {
|
|
||||||
"message": " (導入済み)",
|
|
||||||
"description": "PluginInstallerWindow.Draw"
|
|
||||||
},
|
|
||||||
"InstallerInProgress": {
|
|
||||||
"message": "インストール中……",
|
|
||||||
"description": "PluginInstallerWindow.Draw"
|
|
||||||
},
|
|
||||||
"InstallerDisable": {
|
|
||||||
"message": "無効化",
|
|
||||||
"description": "PluginInstallerWindow.Draw"
|
|
||||||
},
|
|
||||||
"InstallerOpenConfig": {
|
|
||||||
"message": "設定を開く",
|
|
||||||
"description": "PluginInstallerWindow.Draw"
|
|
||||||
},
|
|
||||||
"InstallerUpdating": {
|
|
||||||
"message": "アップデートしています……",
|
|
||||||
"description": "PluginInstallerWindow.Draw"
|
|
||||||
},
|
|
||||||
"InstallerUpdateComplete": {
|
|
||||||
"message": "{0} のプラグインが更新されました!",
|
|
||||||
"description": "PluginInstallerWindow.Draw"
|
|
||||||
},
|
|
||||||
"InstallerNoUpdates": {
|
|
||||||
"message": "アップデートが見つかりませんでした!",
|
|
||||||
"description": "PluginInstallerWindow.Draw"
|
|
||||||
},
|
|
||||||
"InstallerUpdatePlugins": {
|
|
||||||
"message": "プラグインをアップデートする",
|
|
||||||
"description": "PluginInstallerWindow.Draw"
|
|
||||||
},
|
|
||||||
"Close": {
|
|
||||||
"message": "閉じる",
|
|
||||||
"description": "PluginInstallerWindow.Draw"
|
|
||||||
},
|
|
||||||
"InstallerError": {
|
|
||||||
"message": "インストールが失敗しました",
|
|
||||||
"description": "PluginInstallerWindow.Draw"
|
|
||||||
},
|
|
||||||
"InstallerErrorHint": {
|
|
||||||
"message": "プラグインのインストーラに問題が発生したか、プラグインとの互換性がありません。\nゲームを再起動して、このエラーを私たちのディスコードで報告してください。",
|
|
||||||
"description": "PluginInstallerWindow.Draw"
|
|
||||||
},
|
|
||||||
"OK": {
|
|
||||||
"message": "OK",
|
|
||||||
"description": "PluginInstallerWindow.Draw"
|
|
||||||
},
|
|
||||||
"DalamudWelcome": {
|
|
||||||
"message": "XIVLauncher In-Game アドオン v{0} がロードされました.",
|
|
||||||
"description": "ChatHandlers.OnChatMessage"
|
|
||||||
},
|
|
||||||
"DalamudPluginLoaded": {
|
|
||||||
"message": " 》 {0} v{1} がロードされました。",
|
|
||||||
"description": "ChatHandlers.OnChatMessage"
|
|
||||||
},
|
|
||||||
"DalamudUpdated": {
|
|
||||||
"message": "In-Game アドオンの更新または、再インストールに成功しました。詳細な変更履歴はDiscordで確認してください。",
|
|
||||||
"description": "ChatHandlers.OnChatMessage"
|
|
||||||
},
|
|
||||||
"DalamudPluginUpdateRequired": {
|
|
||||||
"message": "いくつかのプラグインで更新が必要です。/xlplugins コマンドを使用して、プラグインを更新してください。",
|
|
||||||
"description": "ChatHandlers.OnChatMessage"
|
|
||||||
},
|
|
||||||
"DalamudPluginUpdateCheckFail": {
|
|
||||||
"message": "プラグインの更新を確認できませんでした。",
|
|
||||||
"description": "ChatHandlers.OnChatMessage"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 266 KiB |
|
|
@ -6,11 +6,11 @@
|
||||||
|
|
||||||
Dalamud is a plugin development framework for FINAL FANTASY XIV that provides access to game data and native interoperability with the game itself to add functionality and quality-of-life.
|
Dalamud is a plugin development framework for FINAL FANTASY XIV that provides access to game data and native interoperability with the game itself to add functionality and quality-of-life.
|
||||||
|
|
||||||
It is meant to be used in conjunction with [FFXIVQuickLauncher](https://github.com/goaaats/FFXIVQuickLauncher).
|
It is meant to be used in conjunction with [FFXIVQuickLauncher](https://github.com/goatcorp/FFXIVQuickLauncher).
|
||||||
|
|
||||||
## Plugin development
|
## Plugin development
|
||||||
Dalamud features a growing API for in-game plugin development with game data and chat access and overlays.
|
Dalamud features a growing API for in-game plugin development with game data and chat access and overlays.
|
||||||
Please see the [API documentation](https://goaaats.github.io/Dalamud/api/index.html) for more details.
|
Please see the [API documentation](https://goatcorp.github.io/Dalamud/api/index.html) for more details.
|
||||||
|
|
||||||
If you need any support regarding the API or usage of Dalamud, please [join our discord server](https://discord.gg/3NMcUV5).
|
If you need any support regarding the API or usage of Dalamud, please [join our discord server](https://discord.gg/3NMcUV5).
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
Subproject commit b096e5b2e9826525394a0c00b987aad1f2c4eccb
|
Subproject commit aaa037938d6fe835a15542a3451d12108e3f83b6
|
||||||
Loading…
Add table
Add a link
Reference in a new issue