Merge branch 'master' into StatusEffects

This commit is contained in:
Penn Oser 2020-09-08 19:29:38 -05:00
commit fc5a816594
27 changed files with 229 additions and 183 deletions

View file

@ -14,10 +14,10 @@
</PropertyGroup> </PropertyGroup>
<PropertyGroup Label="Feature"> <PropertyGroup Label="Feature">
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<AssemblyVersion>5.1.0.4</AssemblyVersion> <AssemblyVersion>5.1.0.5</AssemblyVersion>
<FileVersion>5.1.0.4</FileVersion> <FileVersion>5.1.0.5</FileVersion>
<Description>XIVLauncher addon injection</Description> <Description>XIVLauncher addon injection</Description>
<Version>5.1.0.4</Version> <Version>5.1.0.5</Version>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<DocumentationFile></DocumentationFile> <DocumentationFile></DocumentationFile>

View file

@ -18,17 +18,6 @@ namespace Dalamud
public List<string> BadWords { get; set; } public List<string> BadWords { get; set; }
public enum PreferredRole
{
None,
All,
Tank,
Dps,
Healer
}
public Dictionary<int, PreferredRole> PreferredRoleReminders { get; set; }
public bool DutyFinderTaskbarFlash { get; set; } = true; public bool DutyFinderTaskbarFlash { get; set; } = true;
public bool DutyFinderChatMessage { get; set; } = true; public bool DutyFinderChatMessage { get; set; } = true;

View file

@ -4,6 +4,7 @@ using System.Diagnostics;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
using System.Numerics;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
@ -179,7 +180,7 @@ namespace Dalamud {
public void Start() { public void Start() {
#if DEBUG #if DEBUG
ReplaceExceptionHandler(); //ReplaceExceptionHandler();
#endif #endif
} }
@ -249,6 +250,31 @@ namespace Dalamud {
private void BuildDalamudUi() private void BuildDalamudUi()
{ {
if (!this.isImguiDrawDevMenu && !ClientState.Condition.Any())
{
ImGui.PushStyleColor(ImGuiCol.Button, new Vector4(0, 0, 0, 0));
ImGui.PushStyleColor(ImGuiCol.ButtonActive, new Vector4(0, 0, 0, 0));
ImGui.PushStyleColor(ImGuiCol.ButtonHovered, new Vector4(0, 0, 0, 0));
ImGui.PushStyleColor(ImGuiCol.Text, new Vector4(0, 0, 0, 1));
ImGui.PushStyleColor(ImGuiCol.TextSelectedBg, new Vector4(0, 0, 0, 1));
ImGui.PushStyleColor(ImGuiCol.Border, new Vector4(0, 0, 0, 1));
ImGui.PushStyleColor(ImGuiCol.BorderShadow, new Vector4(0, 0, 0, 1));
ImGui.PushStyleColor(ImGuiCol.WindowBg, new Vector4(0, 0, 0, 1));
ImGui.SetNextWindowPos(new Vector2(0, 0), ImGuiCond.Always);
ImGui.SetNextWindowBgAlpha(1);
if (ImGui.Begin("DevMenu Opener", ImGuiWindowFlags.AlwaysAutoResize | ImGuiWindowFlags.NoBackground | ImGuiWindowFlags.NoDecoration | ImGuiWindowFlags.NoMove | ImGuiWindowFlags.NoScrollbar | ImGuiWindowFlags.NoResize | ImGuiWindowFlags.NoSavedSettings))
{
if (ImGui.Button("###devMenuOpener", new Vector2(40, 25)))
this.isImguiDrawDevMenu = true;
ImGui.End();
}
ImGui.PopStyleColor(5);
}
if (this.isImguiDrawDevMenu) if (this.isImguiDrawDevMenu)
{ {
if (ImGui.BeginMainMenuBar()) if (ImGui.BeginMainMenuBar())
@ -515,10 +541,6 @@ namespace Dalamud {
}); });
#endif #endif
CommandManager.AddHandler("/xlbonus", new CommandInfo(OnRouletteBonusNotifyCommand) {
HelpMessage = Loc.Localize("DalamudBonusHelp", "Notify when a roulette has a bonus you specified. Run without parameters for more info. Usage: /xlbonus <roulette name> <role name>")
});
CommandManager.AddHandler("/xldev", new CommandInfo(OnDebugDrawDevMenu) { CommandManager.AddHandler("/xldev", new CommandInfo(OnDebugDrawDevMenu) {
HelpMessage = Loc.Localize("DalamudDevMenuHelp", "Draw dev menu DEBUG"), HelpMessage = Loc.Localize("DalamudDevMenuHelp", "Draw dev menu DEBUG"),
ShowInHelp = false ShowInHelp = false
@ -669,46 +691,6 @@ namespace Dalamud {
} }
#endif #endif
private void OnRouletteBonusNotifyCommand(string command, string arguments)
{
if (this.Configuration.DiscordFeatureConfig.CfPreferredRoleChannel == null)
Framework.Gui.Chat.PrintError(Loc.Localize("DalamudChannelNotSetup", "You have not set up a discord channel for these notifications - you will only receive them in chat. To do this, please use the XIVLauncher in-game settings."));
if (string.IsNullOrEmpty(arguments))
goto InvalidArgs;
var argParts = arguments.Split();
if (argParts.Length < 2)
goto InvalidArgs;
if (this.Configuration.PreferredRoleReminders == null)
this.Configuration.PreferredRoleReminders = new Dictionary<int, DalamudConfiguration.PreferredRole>();
var rouletteIndex = RouletteSlugToKey(argParts[0]);
if (rouletteIndex == 0)
goto InvalidArgs;
if (!Enum.TryParse(argParts[1].First().ToString().ToUpper() + argParts[1].ToLower().Substring(1), out DalamudConfiguration.PreferredRole role))
goto InvalidArgs;
if (this.Configuration.PreferredRoleReminders.ContainsKey(rouletteIndex))
this.Configuration.PreferredRoleReminders[rouletteIndex] = role;
else
this.Configuration.PreferredRoleReminders.Add(rouletteIndex, role);
this.Framework.Gui.Chat.Print($"Set bonus notifications for {argParts[0]}({rouletteIndex}) to {role}");
this.Framework.Gui.Chat.Print(string.Format(Loc.Localize("DalamudBonusSet", "Set bonus notifications for {0}({1}) to {2}"), argParts[0], rouletteIndex, role));
this.Configuration.Save();
return;
InvalidArgs:
this.Framework.Gui.Chat.PrintError(Loc.Localize("DalamudInvalidArguments", "Unrecognized arguments."));
this.Framework.Gui.Chat.Print(Loc.Localize("DalamudBonusPossibleValues", "Possible values for roulette: leveling, 506070, msq, guildhests, expert, trials, mentor, alliance, normal\nPossible values for role: tank, dps, healer, all, none/reset"));
}
private void OnDebugDrawDevMenu(string command, string arguments) { private void OnDebugDrawDevMenu(string command, string arguments) {
this.isImguiDrawDevMenu = !this.isImguiDrawDevMenu; this.isImguiDrawDevMenu = !this.isImguiDrawDevMenu;
} }
@ -789,27 +771,5 @@ namespace Dalamud {
} }
}); });
} }
private int RouletteSlugToKey(string slug) => slug.ToLower() switch {
"leveling" => 1,
"506070" => 2,
"msq" => 3,
"guildhests" => 4,
"expert" => 5,
"trials" => 6,
"mentor" => 8,
"alliance" => 9,
"normal" => 10,
_ => 0
};
private DalamudConfiguration.PreferredRole RoleNameToPreferredRole(string name) => name.ToLower() switch
{
"Tank" => DalamudConfiguration.PreferredRole.Tank,
"Healer" => DalamudConfiguration.PreferredRole.Healer,
"Dps" => DalamudConfiguration.PreferredRole.Dps,
"All" => DalamudConfiguration.PreferredRole.All,
_ => DalamudConfiguration.PreferredRole.None
};
} }
} }

View file

@ -15,9 +15,9 @@
</PropertyGroup> </PropertyGroup>
<PropertyGroup Label="Feature"> <PropertyGroup Label="Feature">
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<AssemblyVersion>5.1.0.4</AssemblyVersion> <AssemblyVersion>5.1.0.5</AssemblyVersion>
<Version>5.1.0.4</Version> <Version>5.1.0.5</Version>
<FileVersion>5.1.0.4</FileVersion> <FileVersion>5.1.0.5</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" />

View file

@ -51,7 +51,7 @@ namespace Dalamud.Game.Chat.SeStringHandling
/// <summary> /// <summary>
/// The Lumina instance to use for any necessary data lookups. /// The Lumina instance to use for any necessary data lookups.
/// </summary> /// </summary>
protected DataManager DataResolver; public DataManager DataResolver;
// private for now, since subclasses shouldn't interact with this // private for now, since subclasses shouldn't interact with this
// To force-invalidate it, Dirty can be set to true // To force-invalidate it, Dirty can be set to true

View file

@ -6,6 +6,7 @@ using System.IO;
using System.Linq; using System.Linq;
using Dalamud.Data; using Dalamud.Data;
using Dalamud.Data.TransientSheet; using Dalamud.Data.TransientSheet;
using Newtonsoft.Json;
namespace Dalamud.Game.Chat.SeStringHandling.Payloads namespace Dalamud.Game.Chat.SeStringHandling.Payloads
{ {
@ -34,7 +35,10 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
} }
} }
[JsonProperty]
private uint group; private uint group;
[JsonProperty]
private uint key; private uint key;
internal AutoTranslatePayload() { } internal AutoTranslatePayload() { }

View file

@ -5,6 +5,7 @@ using System.Linq;
using System.Text; using System.Text;
using Dalamud.Data; using Dalamud.Data;
using Lumina.Excel.GeneratedSheets; using Lumina.Excel.GeneratedSheets;
using Newtonsoft.Json;
namespace Dalamud.Game.Chat.SeStringHandling.Payloads namespace Dalamud.Game.Chat.SeStringHandling.Payloads
{ {
@ -22,6 +23,7 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
/// <remarks> /// <remarks>
/// Value is evaluated lazily and cached. /// Value is evaluated lazily and cached.
/// </remarks> /// </remarks>
[JsonIgnore]
public Item Item public Item Item
{ {
get get
@ -57,8 +59,10 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
/// <summary> /// <summary>
/// Whether or not this item link is for a high-quality version of the item. /// Whether or not this item link is for a high-quality version of the item.
/// </summary> /// </summary>
[JsonProperty]
public bool IsHQ { get; private set; } = false; public bool IsHQ { get; private set; } = false;
[JsonProperty]
private uint itemId; private uint itemId;
internal ItemPayload() { } internal ItemPayload() { }

View file

@ -3,6 +3,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using Dalamud.Data; using Dalamud.Data;
using Newtonsoft.Json;
namespace Dalamud.Game.Chat.SeStringHandling.Payloads namespace Dalamud.Game.Chat.SeStringHandling.Payloads
{ {
@ -20,6 +21,7 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
/// <remarks> /// <remarks>
/// Value is evaluated lazily and cached. /// Value is evaluated lazily and cached.
/// </remarks> /// </remarks>
[JsonIgnore]
public Map Map public Map Map
{ {
get get
@ -36,6 +38,7 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
/// <remarks> /// <remarks>
/// Value is evaluated lazily and cached. /// Value is evaluated lazily and cached.
/// </remarks> /// </remarks>
[JsonIgnore]
public TerritoryType TerritoryType public TerritoryType TerritoryType
{ {
get get
@ -70,6 +73,7 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
/// <summary> /// <summary>
/// The readable y-coordinate position for this map link. This value is approximate and unrounded. /// The readable y-coordinate position for this map link. This value is approximate and unrounded.
/// </summary> /// </summary>
[JsonIgnore]
public float YCoord public float YCoord
{ {
get get
@ -82,6 +86,7 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
/// The printable map coordinates for this link. This value tries to match the in-game printable text as closely as possible /// The printable map coordinates for this link. This value tries to match the in-game printable text as closely as possible
/// but is an approximation and may be slightly off for some positions. /// but is an approximation and may be slightly off for some positions.
/// </summary> /// </summary>
[JsonIgnore]
public string CoordinateString public string CoordinateString
{ {
get get
@ -102,6 +107,7 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
/// <summary> /// <summary>
/// The region name for this map link. This corresponds to the upper zone name found in the actual in-game map UI. eg, "La Noscea" /// The region name for this map link. This corresponds to the upper zone name found in the actual in-game map UI. eg, "La Noscea"
/// </summary> /// </summary>
[JsonIgnore]
public string PlaceNameRegion public string PlaceNameRegion
{ {
get get
@ -115,6 +121,7 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
/// <summary> /// <summary>
/// The place name for this map link. This corresponds to the lower zone name found in the actual in-game map UI. eg, "Limsa Lominsa Upper Decks" /// The place name for this map link. This corresponds to the lower zone name found in the actual in-game map UI. eg, "Limsa Lominsa Upper Decks"
/// </summary> /// </summary>
[JsonIgnore]
public string PlaceName public string PlaceName
{ {
get get
@ -129,7 +136,10 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
/// </summary> /// </summary>
public string DataString => $"m:{TerritoryType.RowId},{Map.RowId},{RawX},{RawY}"; public string DataString => $"m:{TerritoryType.RowId},{Map.RowId},{RawX},{RawY}";
[JsonProperty]
private uint territoryTypeId; private uint territoryTypeId;
[JsonProperty]
private uint mapId; private uint mapId;
// there is no Z; it's purely in the text payload where applicable // there is no Z; it's purely in the text payload where applicable

View file

@ -4,6 +4,7 @@ using System.Collections.Generic;
using System.IO; using System.IO;
using System.Text; using System.Text;
using Dalamud.Data; using Dalamud.Data;
using Newtonsoft.Json;
namespace Dalamud.Game.Chat.SeStringHandling.Payloads namespace Dalamud.Game.Chat.SeStringHandling.Payloads
{ {
@ -14,10 +15,12 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
{ {
public override PayloadType Type => PayloadType.Player; public override PayloadType Type => PayloadType.Player;
[JsonProperty]
private string playerName; private string playerName;
/// <summary> /// <summary>
/// The player's displayed name. This does not contain the server name. /// The player's displayed name. This does not contain the server name.
/// </summary> /// </summary>
[JsonIgnore]
public string PlayerName public string PlayerName
{ {
get { return this.playerName; } get { return this.playerName; }
@ -35,6 +38,7 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
/// <remarks> /// <remarks>
/// Value is evaluated lazily and cached. /// Value is evaluated lazily and cached.
/// </remarks> /// </remarks>
[JsonIgnore]
public World World public World World
{ {
get get
@ -48,8 +52,10 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
/// A text representation of this player link matching how it might appear in-game. /// A text representation of this player link matching how it might appear in-game.
/// The world name will always be present. /// The world name will always be present.
/// </summary> /// </summary>
[JsonIgnore]
public string DisplayedName => $"{PlayerName}{(char)SeIconChar.CrossWorld}{World.Name}"; public string DisplayedName => $"{PlayerName}{(char)SeIconChar.CrossWorld}{World.Name}";
[JsonProperty]
private uint serverId; private uint serverId;
internal PlayerPayload() { } internal PlayerPayload() { }

View file

@ -1,3 +1,4 @@
using Newtonsoft.Json;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
@ -20,6 +21,7 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
public override PayloadType Type => PayloadType.Unknown; public override PayloadType Type => PayloadType.Unknown;
[JsonProperty]
private byte[] data; private byte[] data;
// this is a bit different from the underlying data // this is a bit different from the underlying data
// We need to store just the chunk data for decode to behave nicely, but when reading data out // We need to store just the chunk data for decode to behave nicely, but when reading data out
@ -28,6 +30,7 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
/// The entire payload byte sequence for this payload. /// The entire payload byte sequence for this payload.
/// The returned data is a clone and modifications will not be persisted. /// The returned data is a clone and modifications will not be persisted.
/// </summary> /// </summary>
[JsonIgnore]
public byte[] Data public byte[] Data
{ {
get get
@ -38,8 +41,10 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
} }
} }
[JsonProperty]
private byte chunkType; private byte chunkType;
[JsonConstructor]
internal RawPayload(byte chunkType) internal RawPayload(byte chunkType)
{ {
this.chunkType = chunkType; this.chunkType = chunkType;

View file

@ -3,6 +3,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using Dalamud.Data; using Dalamud.Data;
using Newtonsoft.Json;
namespace Dalamud.Game.Chat.SeStringHandling.Payloads namespace Dalamud.Game.Chat.SeStringHandling.Payloads
{ {
@ -20,6 +21,7 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
/// <remarks> /// <remarks>
/// Value is evaluated lazily and cached. /// Value is evaluated lazily and cached.
/// </remarks> /// </remarks>
[JsonIgnore]
public Status Status public Status Status
{ {
get get
@ -29,6 +31,7 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
} }
} }
[JsonProperty]
private uint statusId; private uint statusId;
internal StatusPayload() { } internal StatusPayload() { }

View file

@ -1,3 +1,4 @@
using Newtonsoft.Json;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
@ -13,11 +14,13 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
public override PayloadType Type => PayloadType.RawText; public override PayloadType Type => PayloadType.RawText;
// allow modifying the text of existing payloads on the fly // allow modifying the text of existing payloads on the fly
[JsonProperty]
private string text; private string text;
/// <summary> /// <summary>
/// The text contained in this payload. /// The text contained in this payload.
/// This may contain SE's special unicode characters. /// This may contain SE's special unicode characters.
/// </summary> /// </summary>
[JsonIgnore]
public string Text public string Text
{ {
get { return this.text; } get { return this.text; }

View file

@ -3,6 +3,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using Dalamud.Data; using Dalamud.Data;
using Newtonsoft.Json;
namespace Dalamud.Game.Chat.SeStringHandling.Payloads namespace Dalamud.Game.Chat.SeStringHandling.Payloads
{ {
@ -31,6 +32,7 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
/// <remarks> /// <remarks>
/// Value is evaluated lazily and cached. /// Value is evaluated lazily and cached.
/// </remarks> /// </remarks>
[JsonIgnore]
public UIColor UIColor public UIColor UIColor
{ {
get get
@ -43,6 +45,7 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
/// <summary> /// <summary>
/// The color key used as a lookup in the UIColor table for this foreground color. /// The color key used as a lookup in the UIColor table for this foreground color.
/// </summary> /// </summary>
[JsonIgnore]
public ushort ColorKey public ushort ColorKey
{ {
get { return this.colorKey; } get { return this.colorKey; }
@ -57,6 +60,7 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
/// <summary> /// <summary>
/// The Red/Green/Blue values for this foreground color, encoded as a typical hex color. /// The Red/Green/Blue values for this foreground color, encoded as a typical hex color.
/// </summary> /// </summary>
[JsonIgnore]
public uint RGB public uint RGB
{ {
get get
@ -65,6 +69,7 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
} }
} }
[JsonProperty]
private ushort colorKey; private ushort colorKey;
internal UIForegroundPayload() { } internal UIForegroundPayload() { }

View file

@ -3,6 +3,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using Dalamud.Data; using Dalamud.Data;
using Newtonsoft.Json;
namespace Dalamud.Game.Chat.SeStringHandling.Payloads namespace Dalamud.Game.Chat.SeStringHandling.Payloads
{ {
@ -31,6 +32,7 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
/// <remarks> /// <remarks>
/// Value is evaluated lazily and cached. /// Value is evaluated lazily and cached.
/// </remarks> /// </remarks>
[JsonIgnore]
public UIColor UIColor public UIColor UIColor
{ {
get get
@ -43,6 +45,7 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
/// <summary> /// <summary>
/// The color key used as a lookup in the UIColor table for this glow color. /// The color key used as a lookup in the UIColor table for this glow color.
/// </summary> /// </summary>
[JsonIgnore]
public ushort ColorKey public ushort ColorKey
{ {
get { return this.colorKey; } get { return this.colorKey; }
@ -57,6 +60,7 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
/// <summary> /// <summary>
/// The Red/Green/Blue values for this glow color, encoded as a typical hex color. /// The Red/Green/Blue values for this glow color, encoded as a typical hex color.
/// </summary> /// </summary>
[JsonIgnore]
public uint RGB public uint RGB
{ {
get get
@ -65,6 +69,7 @@ namespace Dalamud.Game.Chat.SeStringHandling.Payloads
} }
} }
[JsonProperty]
private ushort colorKey; private ushort colorKey;
internal UIGlowPayload() { } internal UIGlowPayload() { }

View file

@ -3,7 +3,9 @@ using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using Dalamud.Data;
using Dalamud.Game.Chat.SeStringHandling.Payloads; using Dalamud.Game.Chat.SeStringHandling.Payloads;
using Newtonsoft.Json;
namespace Dalamud.Game.Chat.SeStringHandling namespace Dalamud.Game.Chat.SeStringHandling
{ {
@ -38,6 +40,7 @@ namespace Dalamud.Game.Chat.SeStringHandling
/// Creates a new SeString from an ordered list of payloads. /// Creates a new SeString from an ordered list of payloads.
/// </summary> /// </summary>
/// <param name="payloads">The Payload objects to make up this string.</param> /// <param name="payloads">The Payload objects to make up this string.</param>
[JsonConstructor]
public SeString(List<Payload> payloads) public SeString(List<Payload> payloads)
{ {
Payloads = payloads; Payloads = payloads;
@ -100,5 +103,42 @@ namespace Dalamud.Game.Chat.SeStringHandling
return messageBytes.ToArray(); return messageBytes.ToArray();
} }
/// <summary>
/// Serializes the SeString to json
/// </summary>
/// <returns>An json representation of this object</returns>
public string ToJson()
{
return JsonConvert.SerializeObject(this, Formatting.Indented, new JsonSerializerSettings()
{
PreserveReferencesHandling = PreserveReferencesHandling.Objects,
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
TypeNameHandling = TypeNameHandling.Auto
});
}
/// <summary>
/// Creates a SeString from a json. (For testing - not recommended for production use.)
/// </summary>
/// <param name="json">A serialized SeString produced by ToJson() <see cref="ToJson"/></param>
/// <param name="dataManager">An initialized instance of DataManager for Lumina queries.</param>
/// <returns>A SeString initialized with values from the json</returns>
public static SeString FromJson(string json, DataManager dataManager)
{
var s = JsonConvert.DeserializeObject<SeString>(json, new JsonSerializerSettings
{
PreserveReferencesHandling = PreserveReferencesHandling.Objects,
TypeNameHandling = TypeNameHandling.Auto,
ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor
});
foreach(var payload in s.Payloads)
{
payload.DataResolver = dataManager;
}
return s;
}
} }
} }

View file

@ -92,6 +92,7 @@ namespace Dalamud.Game.ClientState.Actors {
return actorStruct.ObjectKind switch { return actorStruct.ObjectKind switch {
ObjectKind.Player => new PlayerCharacter(offset, actorStruct, this.dalamud), ObjectKind.Player => new PlayerCharacter(offset, actorStruct, this.dalamud),
ObjectKind.BattleNpc => new BattleNpc(offset, actorStruct, this.dalamud), ObjectKind.BattleNpc => new BattleNpc(offset, actorStruct, this.dalamud),
ObjectKind.EventObj => new EventObj(offset, actorStruct, this.dalamud),
_ => new Actor(offset, actorStruct, this.dalamud) _ => new Actor(offset, actorStruct, this.dalamud)
}; };
} }

View file

@ -0,0 +1,21 @@
using System;
namespace Dalamud.Game.ClientState.Actors.Types.NonPlayer {
/// <summary>
/// This class represents an EventObj.
/// </summary>
public class EventObj : Actor {
/// <summary>
/// Set up a new EventObj with the provided memory representation.
/// </summary>
/// <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="address">The address of this actor in memory.</param>
public EventObj(IntPtr address, Structs.Actor actorStruct, Dalamud dalamud) : base(address, actorStruct, dalamud) { }
/// <summary>
/// The data ID of the NPC linking to their respective game data.
/// </summary>
public int DataId => this.actorStruct.DataId;
}
}

View file

@ -22,8 +22,6 @@ namespace Dalamud.Game.Network {
private readonly bool optOutMbUploads; private readonly bool optOutMbUploads;
private readonly IMarketBoardUploader uploader; private readonly IMarketBoardUploader uploader;
private byte[] lastPreferredRole;
public delegate Task CfPop(ContentFinderCondition cfc); public delegate Task CfPop(ContentFinderCondition cfc);
public event CfPop ProcessCfPop; public event CfPop ProcessCfPop;
@ -90,60 +88,6 @@ namespace Dalamud.Game.Network {
return; return;
} }
if (opCode == this.dalamud.Data.ServerOpCodes["CfPreferredRole"]) {
if (this.dalamud.Configuration.PreferredRoleReminders == null)
return;
var data = new byte[64];
Marshal.Copy(dataPtr, data, 0, 32);
if (this.lastPreferredRole == null) {
this.lastPreferredRole = data;
return;
}
Task.Run(async () => {
for (var rouletteIndex = 1; rouletteIndex < 11; rouletteIndex++) {
var currentRoleKey = data[rouletteIndex];
var prevRoleKey = this.lastPreferredRole[rouletteIndex];
Log.Verbose("CfPreferredRole: {0} - {1} => {2}", rouletteIndex, prevRoleKey, currentRoleKey);
if (currentRoleKey != prevRoleKey) {
var rouletteName = rouletteIndex switch {
1 => "Duty Roulette: Leveling",
2 => "Duty Roulette: Level 50/60/70 Dungeons",
3 => "Duty Roulette: Main Scenario",
4 => "Duty Roulette: Guildhests",
5 => "Duty Roulette: Expert",
6 => "Duty Roulette: Trials",
8 => "Duty Roulette: Mentor",
9 => "Duty Roulette: Alliance Raids",
10 => "Duty Roulette: Normal Raids",
_ => "Unknown ContentRoulette"
};
var prevRoleName = RoleKeyToPreferredRole(prevRoleKey);
var currentRoleName = RoleKeyToPreferredRole(currentRoleKey);
if (!this.dalamud.Configuration.PreferredRoleReminders.TryGetValue(rouletteIndex, out var roleToCheck))
return;
if (roleToCheck == DalamudConfiguration.PreferredRole.All || currentRoleName != roleToCheck)
return;
this.dalamud.Framework.Gui.Chat.Print($"Roulette bonus for {rouletteName} changed: {prevRoleName} => {currentRoleName}");
if (this.dalamud.BotManager.IsConnected)
await this.dalamud.BotManager.ProcessCfPreferredRoleChange(rouletteName, prevRoleName.ToString(), currentRoleName.ToString());
}
}
this.lastPreferredRole = data;
});
return;
}
if (!this.optOutMbUploads) { if (!this.optOutMbUploads) {
if (opCode == this.dalamud.Data.ServerOpCodes["MarketBoardItemRequestStart"]) { if (opCode == this.dalamud.Data.ServerOpCodes["MarketBoardItemRequestStart"]) {
var catalogId = (uint) Marshal.ReadInt32(dataPtr); var catalogId = (uint) Marshal.ReadInt32(dataPtr);
@ -235,6 +179,19 @@ namespace Dalamud.Game.Network {
request.History.AddRange(listing.HistoryListings); request.History.AddRange(listing.HistoryListings);
Log.Verbose("Added history for item#{0}", listing.CatalogId); Log.Verbose("Added history for item#{0}", listing.CatalogId);
if (request.AmountToArrive == 0) {
Log.Verbose("Request had 0 amount, uploading now");
try
{
Task.Run(() => this.uploader.Upload(request));
}
catch (Exception ex)
{
Log.Error(ex, "Market Board data upload failed.");
}
}
} }
if (opCode == this.dalamud.Data.ServerOpCodes["MarketTaxRates"]) if (opCode == this.dalamud.Data.ServerOpCodes["MarketTaxRates"])
@ -254,14 +211,5 @@ namespace Dalamud.Game.Network {
} }
} }
} }
private DalamudConfiguration.PreferredRole RoleKeyToPreferredRole(int key) => key switch
{
1 => DalamudConfiguration.PreferredRole.Tank,
2 => DalamudConfiguration.PreferredRole.Dps,
3 => DalamudConfiguration.PreferredRole.Dps,
4 => DalamudConfiguration.PreferredRole.Healer,
_ => DalamudConfiguration.PreferredRole.None
};
} }
} }

View file

@ -24,6 +24,9 @@ namespace Dalamud.Interface
{AssetStoreUrl + "UIRes/loc/dalamud/dalamud_fr.json", "UIRes/loc/dalamud/dalamud_fr.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_it.json", "UIRes/loc/dalamud/dalamud_it.json" },
{AssetStoreUrl + "UIRes/loc/dalamud/dalamud_ja.json", "UIRes/loc/dalamud/dalamud_ja.json" }, {AssetStoreUrl + "UIRes/loc/dalamud/dalamud_ja.json", "UIRes/loc/dalamud/dalamud_ja.json" },
{AssetStoreUrl + "UIRes/loc/dalamud/dalamud_ko.json", "UIRes/loc/dalamud/dalamud_ko.json" },
{AssetStoreUrl + "UIRes/loc/dalamud/dalamud_no.json", "UIRes/loc/dalamud/dalamud_no.json" },
{AssetStoreUrl + "UIRes/loc/dalamud/dalamud_ru.json", "UIRes/loc/dalamud/dalamud_ru.json" },
{"https://img.finalfantasyxiv.com/lds/pc/global/fonts/FFXIV_Lodestone_SSF.ttf", "UIRes/gamesym.ttf" } {"https://img.finalfantasyxiv.com/lds/pc/global/fonts/FFXIV_Lodestone_SSF.ttf", "UIRes/gamesym.ttf" }
}; };

View file

@ -11,13 +11,13 @@ namespace Dalamud.Interface {
private readonly Dalamud dalamud; private readonly Dalamud dalamud;
private string assemblyVersion = Util.AssemblyVersion; private string assemblyVersion = Util.AssemblyVersion;
private const bool WarrantsChangelog = false; private const bool WarrantsChangelog = true;
private const string ChangeLog = private const string ChangeLog =
@"* All plugin windows now hide together with the in-game UI when you toggle it. @"* The /xlbonus command was removed - it has been remade as the ""Adventurer in Need"" plugin by Caraxi and is way better now. Please check it out!
You can change this behaviour with /xlsettings under the ""Look&Feel"" tab. * Plugin UI is now also hidden when in GPose or in a cutscene. You can disable this in the /xlsettings window.
* The ""Item hovering"" feature, which was previously broken due to patch 5.3 is now working again. * Universalis will now be updated when a shown item has no listings.
* Added some extra infos about the state of the addon to the log, so we can help you better in case you encounter crashes. * Updated the localization files
* Added this changelog window."; * Added Norwegian, Korean and Russian localization - thanks a lot to all of our translators, especially Ridge, Hibiya and xDarkOne! If you wish to join the effort, please check our #translations channel.";
public DalamudChangelogWindow(Dalamud dalamud) { public DalamudChangelogWindow(Dalamud dalamud) {
this.dalamud = dalamud; this.dalamud = dalamud;

View file

@ -34,13 +34,29 @@ Pohky
Localization by: Localization by:
Truci Airiel
fmauNeko Akira
Roy area402
karashiiro Ridge
availuzje
CBMaca
Delaene
fang2hou
Miu Miu
fmauNeko
qtBxi qtBxi
N30n014 JasonLucas
karashiiro
hibiya
sayumizumi
N30N014
Neocrow
OhagiYamada
xDarkOne
Truci
Roy
xenris
Xorus

View file

@ -99,8 +99,8 @@ namespace Dalamud.Interface
ImGui.Dummy(new Vector2(10f, 10f)); ImGui.Dummy(new Vector2(10f, 10f));
ImGui.Checkbox(Loc.Localize("DalamudSettingToggleUiHide", "Hide plugin UI when the game UI is hidden"), ref this.doToggleUiHide); ImGui.Checkbox(Loc.Localize("DalamudSettingToggleUiHide", "Hide plugin UI when the game UI is hidden and during cutscenes and gpose"), ref this.doToggleUiHide);
ImGui.TextColored(this.hintTextColor, Loc.Localize("DalamudSettingToggleUiHideHint", "Check this box to hide any open windows by plugins when toggling the game overlay.")); ImGui.TextColored(this.hintTextColor, Loc.Localize("DalamudSettingToggleUiHideHint", "Check this box to hide any open windows by plugins when toggling the game overlay, or upon entering gpose or a cutscene."));
ImGui.EndTabItem(); ImGui.EndTabItem();
} }

View file

@ -6,6 +6,7 @@ using System.Linq;
using System.Numerics; using System.Numerics;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Text; using System.Text;
using System.Threading;
using CheapLoc; using CheapLoc;
using Dalamud.Game; using Dalamud.Game;
using Dalamud.Game.Internal.DXGI; using Dalamud.Game.Internal.DXGI;
@ -207,9 +208,13 @@ namespace Dalamud.Interface
// Sets up a deferred invocation of font rebuilding, before the next render frame // Sets up a deferred invocation of font rebuilding, before the next render frame
public void RebuildFonts() public void RebuildFonts()
{ {
Log.Verbose("[FONT] RebuildFonts() called");
// don't invoke this multiple times per frame, in case multiple plugins call it // don't invoke this multiple times per frame, in case multiple plugins call it
if (!this.isRebuildingFonts) if (!this.isRebuildingFonts)
{ {
Log.Verbose("[FONT] RebuildFonts() trigger");
this.isRebuildingFonts = true; this.isRebuildingFonts = true;
this.scene.OnNewRenderFrame += RebuildFontsInternal; this.scene.OnNewRenderFrame += RebuildFontsInternal;
} }
@ -300,10 +305,18 @@ namespace Dalamud.Interface
}, GCHandleType.Pinned); }, GCHandleType.Pinned);
IconFont = ImGui.GetIO().Fonts.AddFontFromFileTTF(fontPathIcon, 17.0f, null, iconRangeHandle.AddrOfPinnedObject()); IconFont = ImGui.GetIO().Fonts.AddFontFromFileTTF(fontPathIcon, 17.0f, null, iconRangeHandle.AddrOfPinnedObject());
Log.Verbose("[FONT] Invoke OnBuildFonts");
this.OnBuildFonts?.Invoke(); this.OnBuildFonts?.Invoke();
Log.Verbose("[FONT] OnBuildFonts OK!");
for (var i = 0; i < ImGui.GetIO().Fonts.Fonts.Size; i++) {
Log.Verbose("{0} - {1}", i, ImGui.GetIO().Fonts.Fonts[i].GetDebugName());
}
ImGui.GetIO().Fonts.Build(); ImGui.GetIO().Fonts.Build();
Log.Verbose("[FONT] Fonts built!");
fontConfig.Destroy(); fontConfig.Destroy();
japaneseRangeHandle.Free(); japaneseRangeHandle.Free();
gameRangeHandle.Free(); gameRangeHandle.Free();
@ -313,11 +326,15 @@ namespace Dalamud.Interface
// This is intended to only be called as a handler attached to scene.OnNewRenderFrame // This is intended to only be called as a handler attached to scene.OnNewRenderFrame
private void RebuildFontsInternal() private void RebuildFontsInternal()
{ {
Log.Verbose("[FONT] RebuildFontsInternal() called");
SetupFonts(); SetupFonts();
Log.Verbose("[FONT] RebuildFontsInternal() detaching");
this.scene.OnNewRenderFrame -= RebuildFontsInternal; this.scene.OnNewRenderFrame -= RebuildFontsInternal;
this.scene.InvalidateFonts(); this.scene.InvalidateFonts();
Log.Verbose("[FONT] Font Rebuild OK!");
this.isRebuildingFonts = false; this.isRebuildingFonts = false;
} }

View file

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Dalamud.Game.ClientState;
using Dalamud.Game.Internal.Gui; using Dalamud.Game.Internal.Gui;
using ImGuiNET; using ImGuiNET;
using ImGuiScene; using ImGuiScene;
@ -38,9 +39,12 @@ namespace Dalamud.Interface
/// </summary> /// </summary>
public bool DisableAutomaticUiHide { get; set; } = false; public bool DisableAutomaticUiHide { get; set; } = false;
private readonly InterfaceManager interfaceManager; private bool CutsceneOrGposeActive => this.dalamud.ClientState != null && this.dalamud.ClientState.Condition[ConditionFlag.OccupiedInCutSceneEvent] ||
private readonly GameGui gameGui; this.dalamud.ClientState.Condition[ConditionFlag.WatchingCutscene] ||
private readonly DalamudConfiguration config; this.dalamud.ClientState.Condition[ConditionFlag.WatchingCutscene78];
private Dalamud dalamud;
#if DEBUG #if DEBUG
internal static bool DoStats { get; set; } = true; internal static bool DoStats { get; set; } = true;
#else #else
@ -56,13 +60,11 @@ namespace Dalamud.Interface
/// </summary> /// </summary>
/// <param name="interfaceManager">The interface manager to register on.</param> /// <param name="interfaceManager">The interface manager to register on.</param>
/// <param name="namespaceName">The plugin namespace.</param> /// <param name="namespaceName">The plugin namespace.</param>
internal UiBuilder(InterfaceManager interfaceManager, GameGui gameGui, DalamudConfiguration config, string namespaceName) { internal UiBuilder(Dalamud dalamud, string namespaceName) {
this.namespaceName = namespaceName; this.namespaceName = namespaceName;
this.interfaceManager = interfaceManager; this.dalamud = dalamud;
this.gameGui = gameGui; this.dalamud.InterfaceManager.OnDraw += OnDraw;
this.config = config;
this.interfaceManager.OnDraw += OnDraw;
this.stopwatch = new System.Diagnostics.Stopwatch(); this.stopwatch = new System.Diagnostics.Stopwatch();
} }
@ -70,7 +72,7 @@ namespace Dalamud.Interface
/// Unregister the UiBuilder. Do not call this in plugin code. /// Unregister the UiBuilder. Do not call this in plugin code.
/// </summary> /// </summary>
public void Dispose() { public void Dispose() {
this.interfaceManager.OnDraw -= OnDraw; this.dalamud.InterfaceManager.OnDraw -= OnDraw;
} }
/// <summary> /// <summary>
@ -79,7 +81,7 @@ namespace Dalamud.Interface
/// <param name="filePath">The full filepath to the image.</param> /// <param name="filePath">The full filepath to the image.</param>
/// <returns>A <see cref="TextureWrap"/> object wrapping the created image. Use <see cref="TextureWrap.ImGuiHandle"/> inside ImGui.Image()</returns> /// <returns>A <see cref="TextureWrap"/> object wrapping the created image. Use <see cref="TextureWrap.ImGuiHandle"/> inside ImGui.Image()</returns>
public TextureWrap LoadImage(string filePath) => public TextureWrap LoadImage(string filePath) =>
this.interfaceManager.LoadImage(filePath); this.dalamud.InterfaceManager.LoadImage(filePath);
/// <summary> /// <summary>
/// Loads an image from a byte stream, such as a png downloaded into memory. /// Loads an image from a byte stream, such as a png downloaded into memory.
@ -87,7 +89,7 @@ namespace Dalamud.Interface
/// <param name="imageData">A byte array containing the raw image data.</param> /// <param name="imageData">A byte array containing the raw image data.</param>
/// <returns>A <see cref="TextureWrap"/> object wrapping the created image. Use <see cref="TextureWrap.ImGuiHandle"/> inside ImGui.Image()</returns> /// <returns>A <see cref="TextureWrap"/> object wrapping the created image. Use <see cref="TextureWrap.ImGuiHandle"/> inside ImGui.Image()</returns>
public TextureWrap LoadImage(byte[] imageData) => public TextureWrap LoadImage(byte[] imageData) =>
this.interfaceManager.LoadImage(imageData); this.dalamud.InterfaceManager.LoadImage(imageData);
/// <summary> /// <summary>
/// Loads an image from raw unformatted pixel data, with no type or header information. To load formatted data, use <see cref="LoadImage(byte[])"/>. /// Loads an image from raw unformatted pixel data, with no type or header information. To load formatted data, use <see cref="LoadImage(byte[])"/>.
@ -98,7 +100,7 @@ namespace Dalamud.Interface
/// <param name="numChannels">The number of channels (bytes per pixel) of the image contained in <paramref name="imageData"/>. This should usually be 4.</param> /// <param name="numChannels">The number of channels (bytes per pixel) of the image contained in <paramref name="imageData"/>. This should usually be 4.</param>
/// <returns>A <see cref="TextureWrap"/> object wrapping the created image. Use <see cref="TextureWrap.ImGuiHandle"/> inside ImGui.Image()</returns> /// <returns>A <see cref="TextureWrap"/> object wrapping the created image. Use <see cref="TextureWrap.ImGuiHandle"/> inside ImGui.Image()</returns>
public TextureWrap LoadImageRaw(byte[] imageData, int width, int height, int numChannels) => public TextureWrap LoadImageRaw(byte[] imageData, int width, int height, int numChannels) =>
this.interfaceManager.LoadImageRaw(imageData, width, height, numChannels); this.dalamud.InterfaceManager.LoadImageRaw(imageData, width, height, numChannels);
/// <summary> /// <summary>
/// An event that is called any time ImGui fonts need to be rebuilt.<br/> /// An event that is called any time ImGui fonts need to be rebuilt.<br/>
@ -109,8 +111,8 @@ namespace Dalamud.Interface
/// </summary> /// </summary>
public Action OnBuildFonts public Action OnBuildFonts
{ {
get { return this.interfaceManager.OnBuildFonts; } get { return this.dalamud.InterfaceManager.OnBuildFonts; }
set { this.interfaceManager.OnBuildFonts = value; } set { this.dalamud.InterfaceManager.OnBuildFonts = value; }
} }
/// <summary> /// <summary>
@ -118,8 +120,11 @@ namespace Dalamud.Interface
/// This will invoke any <see cref="OnBuildFonts"/> handlers and ensure that any loaded fonts are /// This will invoke any <see cref="OnBuildFonts"/> handlers and ensure that any loaded fonts are
/// ready to be used on the next UI frame. /// ready to be used on the next UI frame.
/// </summary> /// </summary>
public void RebuildFonts() => public void RebuildFonts()
this.interfaceManager.RebuildFonts(); {
Log.Verbose("[FONT] {0} plugin is initiating FONT REBUILD", this.namespaceName);
this.dalamud.InterfaceManager.RebuildFonts();
}
/// <summary> /// <summary>
/// Event that is fired when the plugin should open its configuration interface. /// Event that is fired when the plugin should open its configuration interface.
@ -130,7 +135,7 @@ namespace Dalamud.Interface
private void OnDraw() { private void OnDraw() {
if (this.gameGui.GameUiHidden && this.config.ToggleUiHide && !DisableAutomaticUiHide) if ((this.dalamud.Framework.Gui.GameUiHidden || CutsceneOrGposeActive) && this.dalamud.Configuration.ToggleUiHide && !DisableAutomaticUiHide)
return; return;
ImGui.PushID(this.namespaceName); ImGui.PushID(this.namespaceName);

View file

@ -13,7 +13,7 @@ namespace Dalamud
class Localization { class Localization {
private readonly string workingDirectory; private readonly string workingDirectory;
public static readonly string[] ApplicableLangCodes = { "de", "ja", "fr", "it", "es" }; public static readonly string[] ApplicableLangCodes = { "de", "ja", "fr", "it", "es", "ko", "no", "ru" };
public Localization(string workingDirectory) { public Localization(string workingDirectory) {
this.workingDirectory = workingDirectory; this.workingDirectory = workingDirectory;

View file

@ -75,7 +75,7 @@ namespace Dalamud.Plugin
this.CommandManager = dalamud.CommandManager; this.CommandManager = dalamud.CommandManager;
this.Framework = dalamud.Framework; this.Framework = dalamud.Framework;
this.ClientState = dalamud.ClientState; this.ClientState = dalamud.ClientState;
this.UiBuilder = new UiBuilder(dalamud.InterfaceManager, dalamud.Framework.Gui, dalamud.Configuration, pluginName); this.UiBuilder = new UiBuilder(dalamud, pluginName);
this.TargetModuleScanner = dalamud.SigScanner; this.TargetModuleScanner = dalamud.SigScanner;
this.Data = dalamud.Data; this.Data = dalamud.Data;
this.SeStringManager = dalamud.SeStringManager; this.SeStringManager = dalamud.SeStringManager;

View file

@ -57,7 +57,8 @@ namespace Dalamud.Plugin
ImGuiWindowFlags.NoCollapse | ImGuiWindowFlags.NoResize | ImGuiWindowFlags.NoScrollbar); ImGuiWindowFlags.NoCollapse | ImGuiWindowFlags.NoResize | ImGuiWindowFlags.NoScrollbar);
ImGui.Text(Loc.Localize("InstallerHint", "This window allows you install and remove in-game plugins.\nThey are made by third-party developers.")); ImGui.Text(Loc.Localize("InstallerHint", "This window allows you install and remove in-game plugins.\nThey are made by third-party developers."));
ImGui.SameLine(); ImGui.SameLine(ImGui.GetWindowWidth() - 250);
ImGui.SetNextItemWidth(240);
ImGui.InputTextWithHint("###XPlPluginInstaller_Search", Loc.Localize("InstallerSearch", "Search"), ref this.searchText, 100); ImGui.InputTextWithHint("###XPlPluginInstaller_Search", Loc.Localize("InstallerSearch", "Search"), ref this.searchText, 100);
ImGui.Separator(); ImGui.Separator();