mirror of
https://github.com/goatcorp/Dalamud.git
synced 2025-12-13 12:14:16 +01:00
Merge branch 'master' into sestring_payloads_refactor
This commit is contained in:
commit
67baa81dbe
27 changed files with 623 additions and 268 deletions
|
|
@ -1,41 +1,46 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup Label="Target">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<TargetFramework>net48</TargetFramework>
|
||||
<LangVersion>8.0</LangVersion>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Build">
|
||||
<OutputType>Exe</OutputType>
|
||||
<OutputPath>$(SolutionDir)/bin</OutputPath>
|
||||
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>Portable</DebugType>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Feature">
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<AssemblyVersion>4.9.2.0</AssemblyVersion>
|
||||
<FileVersion>4.9.2.0</FileVersion>
|
||||
<Description>XIVLauncher addon injection</Description>
|
||||
<Version>4.9.2.0</Version>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||
<DocumentationFile></DocumentationFile>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
|
||||
<PackageIcon></PackageIcon>
|
||||
<PackageIconUrl />
|
||||
<ApplicationIcon>dalamud.ico</ApplicationIcon>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="EasyHook" Version="2.7.6270" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.2" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Dalamud\Dalamud.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Target">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<TargetFramework>net48</TargetFramework>
|
||||
<LangVersion>8.0</LangVersion>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Build">
|
||||
<OutputType>Exe</OutputType>
|
||||
<OutputPath>$(SolutionDir)/bin</OutputPath>
|
||||
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>Portable</DebugType>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Feature">
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<AssemblyVersion>4.9.3.0</AssemblyVersion>
|
||||
<FileVersion>4.9.3.0</FileVersion>
|
||||
<Description>XIVLauncher addon injection</Description>
|
||||
<Version>4.9.3.0</Version>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||
<DocumentationFile></DocumentationFile>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)'=='Release'">
|
||||
<AppOutputBase>$(MSBuildProjectDirectory)\</AppOutputBase>
|
||||
<PathMap>$(AppOutputBase)=C:\goatsoft\companysecrets\injector\</PathMap>
|
||||
<Deterministic>true</Deterministic>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
|
||||
<PackageIcon></PackageIcon>
|
||||
<PackageIconUrl />
|
||||
<ApplicationIcon>dalamud.ico</ApplicationIcon>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="EasyHook" Version="2.7.6270" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.2" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Dalamud\Dalamud.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -241,11 +241,7 @@ namespace Dalamud {
|
|||
this.isImguiDrawDataWindow = true;
|
||||
}
|
||||
if (ImGui.MenuItem("Open Credits window")) {
|
||||
var logoGraphic =
|
||||
this.InterfaceManager.LoadImage(
|
||||
Path.Combine(this.StartInfo.WorkingDirectory, "UIRes", "logo.png"));
|
||||
this.creditsWindow = new DalamudCreditsWindow(logoGraphic, this.Framework);
|
||||
this.isImguiDrawCreditsWindow = true;
|
||||
OnOpenCreditsCommand(null, null);
|
||||
}
|
||||
ImGui.MenuItem("Draw ImGui demo", "", ref this.isImguiDrawDemoWindow);
|
||||
if (ImGui.MenuItem("Dump ImGui info"))
|
||||
|
|
@ -662,7 +658,7 @@ namespace Dalamud {
|
|||
var logoGraphic =
|
||||
this.InterfaceManager.LoadImage(
|
||||
Path.Combine(this.StartInfo.WorkingDirectory, "UIRes", "logo.png"));
|
||||
this.creditsWindow = new DalamudCreditsWindow(logoGraphic, this.Framework);
|
||||
this.creditsWindow = new DalamudCreditsWindow(this, logoGraphic, this.Framework);
|
||||
this.isImguiDrawCreditsWindow = true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,79 +1,73 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup Label="Target">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<TargetFramework>net472</TargetFramework>
|
||||
<LangVersion>8.0</LangVersion>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Build">
|
||||
<OutputType>Library</OutputType>
|
||||
<OutputPath></OutputPath>
|
||||
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>Portable</DebugType>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Feature">
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<AssemblyVersion>4.9.2.0</AssemblyVersion>
|
||||
<Version>4.9.2.0</Version>
|
||||
<FileVersion>4.9.2.0</FileVersion>
|
||||
</PropertyGroup>
|
||||
<ItemGroup Label="Resources">
|
||||
<None Include="$(SolutionDir)/Resources/**/*" CopyToOutputDirectory="PreserveNewest" Visible="false" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
<DocumentationFile>$(SolutionDir)\bin\Dalamud.xml</DocumentationFile>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<DocumentationFile>$(SolutionDir)\bin\Dalamud.xml</DocumentationFile>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||
<DocumentationFile>$(SolutionDir)\bin\Dalamud.xml</DocumentationFile>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<DocumentationFile>$(SolutionDir)bin\Dalamud.xml</DocumentationFile>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Remove="Resources\**" />
|
||||
<EmbeddedResource Remove="Resources\**" />
|
||||
<None Remove="Resources\**" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="CheapLoc" Version="1.1.3" />
|
||||
<PackageReference Include="JetBrains.Annotations" Version="2020.1.0" />
|
||||
<PackageReference Include="Lumina" Version="1.1.1" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.2" />
|
||||
<PackageReference Include="PropertyChanged.Fody" Version="2.6.1" />
|
||||
<PackageReference Include="Serilog" Version="2.6.0" />
|
||||
<PackageReference Include="Serilog.Sinks.Async" Version="1.1.0" />
|
||||
<PackageReference Include="Serilog.Sinks.File" Version="4.0.0" />
|
||||
<PackageReference Include="EasyHook" Version="2.7.6270" />
|
||||
<PackageReference Include="SharpDX.Desktop" Version="4.2.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System.Net.Http" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Update="Properties\Resources.Designer.cs">
|
||||
<DesignTime>True</DesignTime>
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Update="Properties\Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\lib\Discord.Net\src\Discord.Net.Rest\Discord.Net.Rest.csproj" />
|
||||
<ProjectReference Include="..\lib\Discord.Net\src\Discord.Net.WebSocket\Discord.Net.WebSocket.csproj" />
|
||||
<ProjectReference Include="..\lib\ImGuiScene\deps\ImGui.NET\src\ImGui.NET-472\ImGui.NET-472.csproj" />
|
||||
<ProjectReference Include="..\lib\ImGuiScene\deps\SDL2-CS\SDL2-CS.csproj" />
|
||||
<ProjectReference Include="..\lib\ImGuiScene\ImGuiScene\ImGuiScene.csproj" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Target">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<TargetFramework>net472</TargetFramework>
|
||||
<LangVersion>8.0</LangVersion>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Build">
|
||||
<OutputType>Library</OutputType>
|
||||
<OutputPath></OutputPath>
|
||||
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>Portable</DebugType>
|
||||
<DocumentationFile>$(SolutionDir)\bin\Dalamud.xml</DocumentationFile>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Feature">
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<AssemblyVersion>4.9.3.0</AssemblyVersion>
|
||||
<Version>4.9.3.0</Version>
|
||||
<FileVersion>4.9.3.0</FileVersion>
|
||||
</PropertyGroup>
|
||||
<ItemGroup Label="Resources">
|
||||
<None Include="$(SolutionDir)/Resources/**/*" CopyToOutputDirectory="PreserveNewest" Visible="false" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)'=='Release'">
|
||||
<AppOutputBase>$(MSBuildProjectDirectory)\</AppOutputBase>
|
||||
<PathMap>$(AppOutputBase)=C:\goatsoft\companysecrets\dalamud\</PathMap>
|
||||
<Deterministic>true</Deterministic>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Remove="Resources\**" />
|
||||
<EmbeddedResource Remove="Resources\**" />
|
||||
<None Remove="Resources\**" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="CheapLoc" Version="1.1.3" />
|
||||
<PackageReference Include="JetBrains.Annotations" Version="2020.1.0" />
|
||||
<PackageReference Include="Lumina" Version="1.1.1" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.2" />
|
||||
<PackageReference Include="PropertyChanged.Fody" Version="2.6.1" />
|
||||
<PackageReference Include="Serilog" Version="2.6.0" />
|
||||
<PackageReference Include="Serilog.Sinks.Async" Version="1.1.0" />
|
||||
<PackageReference Include="Serilog.Sinks.File" Version="4.0.0" />
|
||||
<PackageReference Include="EasyHook" Version="2.7.6270" />
|
||||
<PackageReference Include="SharpDX.Desktop" Version="4.2.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System.Net.Http" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Update="Properties\Resources.Designer.cs">
|
||||
<DesignTime>True</DesignTime>
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Update="Properties\Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\lib\Discord.Net\src\Discord.Net.Rest\Discord.Net.Rest.csproj" />
|
||||
<ProjectReference Include="..\lib\Discord.Net\src\Discord.Net.WebSocket\Discord.Net.WebSocket.csproj" />
|
||||
<ProjectReference Include="..\lib\ImGuiScene\deps\ImGui.NET\src\ImGui.NET-472\ImGui.NET-472.csproj" />
|
||||
<ProjectReference Include="..\lib\ImGuiScene\deps\SDL2-CS\SDL2-CS.csproj" />
|
||||
<ProjectReference Include="..\lib\ImGuiScene\ImGuiScene\ImGuiScene.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -22,7 +22,14 @@ namespace Dalamud.Data
|
|||
/// This class provides data for Dalamud-internal features, but can also be used by plugins if needed.
|
||||
/// </summary>
|
||||
public class DataManager {
|
||||
/// <summary>
|
||||
/// OpCodes sent by the server to the client.
|
||||
/// </summary>
|
||||
public ReadOnlyDictionary<string, ushort> ServerOpCodes { get; private set; }
|
||||
/// <summary>
|
||||
/// OpCodes sent by the client to the server.
|
||||
/// </summary>
|
||||
public ReadOnlyDictionary<string, ushort> ClientOpCodes { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// An <see cref="ExcelModule"/> object which gives access to any of the game's sheet data.
|
||||
|
|
@ -55,13 +62,19 @@ namespace Dalamud.Data
|
|||
{
|
||||
try
|
||||
{
|
||||
Log.Verbose("Starting data download...");
|
||||
Log.Verbose("Starting data load...");
|
||||
|
||||
var opCodeDict =
|
||||
var zoneOpCodeDict =
|
||||
JsonConvert.DeserializeObject<Dictionary<string, ushort>>(File.ReadAllText(Path.Combine(baseDir, "UIRes", "serveropcode.json")));
|
||||
this.ServerOpCodes = new ReadOnlyDictionary<string, ushort>(opCodeDict);
|
||||
ServerOpCodes = new ReadOnlyDictionary<string, ushort>(zoneOpCodeDict);
|
||||
|
||||
Log.Verbose("Loaded {0} ServerOpCodes.", opCodeDict.Count);
|
||||
Log.Verbose("Loaded {0} ServerOpCodes.", zoneOpCodeDict.Count);
|
||||
|
||||
var clientOpCodeDict =
|
||||
JsonConvert.DeserializeObject<Dictionary<string, ushort>>(File.ReadAllText(Path.Combine(baseDir, "UIRes", "clientopcode.json")));
|
||||
ClientOpCodes = new ReadOnlyDictionary<string, ushort>(clientOpCodeDict);
|
||||
|
||||
Log.Verbose("Loaded {0} ClientOpCodes.", clientOpCodeDict.Count);
|
||||
|
||||
|
||||
var luminaOptions = new LuminaOptions
|
||||
|
|
|
|||
|
|
@ -214,7 +214,7 @@ namespace Dalamud.DiscordBot {
|
|||
var avatarUrl = string.Empty;
|
||||
var lodestoneId = string.Empty;
|
||||
|
||||
if (!this.config.DisableEmbeds) {
|
||||
if (!this.config.DisableEmbeds && !string.IsNullOrEmpty(senderName)) {
|
||||
var searchResult = await GetCharacterInfo(senderName, senderWorld);
|
||||
|
||||
lodestoneId = searchResult.LodestoneId;
|
||||
|
|
|
|||
41
Dalamud/Game/ClientState/Actors/CustomizeIndex.cs
Normal file
41
Dalamud/Game/ClientState/Actors/CustomizeIndex.cs
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Dalamud.Game.ClientState.Actors
|
||||
{
|
||||
/// <summary>
|
||||
/// This enum describes the indices of the Customize array.
|
||||
/// </summary>
|
||||
// TODO: This may need some rework since it may not be entirely accurate (stolen from Sapphire)
|
||||
public enum CustomizeIndex {
|
||||
Race = 0x00,
|
||||
Gender = 0x01,
|
||||
Tribe = 0x04,
|
||||
Height = 0x03,
|
||||
ModelType = 0x02, // Au Ra: changes horns/tails, everything else: seems to drastically change appearance (flip between two sets, odd/even numbers). sometimes retains hairstyle and other features
|
||||
FaceType = 0x05,
|
||||
HairStyle = 0x06,
|
||||
HasHighlights = 0x07, // negative to enable, positive to disable
|
||||
SkinColor = 0x08,
|
||||
EyeColor = 0x09, // color of character's right eye
|
||||
HairColor = 0x0A, // main color
|
||||
HairColor2 = 0x0B, // highlights color
|
||||
FaceFeatures = 0x0C, // seems to be a toggle, (-odd and +even for large face covering), opposite for small
|
||||
FaceFeaturesColor = 0x0D,
|
||||
Eyebrows = 0x0E,
|
||||
EyeColor2 = 0x0F, // color of character's left eye
|
||||
EyeShape = 0x10,
|
||||
NoseShape = 0x11,
|
||||
JawShape = 0x12,
|
||||
LipStyle = 0x13, // lip colour depth and shape (negative values around -120 darker/more noticeable, positive no colour)
|
||||
LipColor = 0x14,
|
||||
RaceFeatureSize = 0x15,
|
||||
RaceFeatureType = 0x16, // negative or out of range tail shapes for race result in no tail (e.g. Au Ra has max of 4 tail shapes), incorrect value can crash client
|
||||
BustSize = 0x17, // char creator allows up to max of 100, i set to 127 cause who wouldnt but no visible difference
|
||||
Facepaint = 0x18,
|
||||
FacepaintColor = 0x19,
|
||||
}
|
||||
}
|
||||
|
|
@ -6,5 +6,17 @@ namespace Dalamud.Game.ClientState.Actors {
|
|||
public float X;
|
||||
public float Z;
|
||||
public float Y;
|
||||
|
||||
/// <summary>
|
||||
/// Convert this Position3 to a System.Numerics.Vector3
|
||||
/// </summary>
|
||||
/// <param name="pos">Position to convert.</param>
|
||||
public static implicit operator System.Numerics.Vector3(Position3 pos) => new System.Numerics.Vector3(pos.X, pos.Y, pos.Z);
|
||||
|
||||
/// <summary>
|
||||
/// Convert this Position3 to a SharpDX.Vector3
|
||||
/// </summary>
|
||||
/// <param name="pos">Position to convert.</param>
|
||||
public static implicit operator SharpDX.Vector3(Position3 pos) => new SharpDX.Vector3(pos.X, pos.Z, pos.Y);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,6 +34,12 @@ namespace Dalamud.Game.ClientState.Actors.Types {
|
|||
/// </summary>
|
||||
public Position3 Position => this.actorStruct.Position;
|
||||
|
||||
/// <summary>
|
||||
/// Rotation of this <see cref="Actor"/>.<br/>
|
||||
/// This ranges from -pi to pi radians.
|
||||
/// </summary>
|
||||
public float Rotation => this.actorStruct.Rotation;
|
||||
|
||||
/// <summary>
|
||||
/// Displayname of this <see cref="Actor">Actor</see>.
|
||||
/// </summary>
|
||||
|
|
@ -49,5 +55,15 @@ namespace Dalamud.Game.ClientState.Actors.Types {
|
|||
/// possible values.
|
||||
/// </summary>
|
||||
public ObjectKind ObjectKind => this.actorStruct.ObjectKind;
|
||||
|
||||
/// <summary>
|
||||
/// The X distance from the local player in yalms.
|
||||
/// </summary>
|
||||
public byte YalmDistanceX => this.actorStruct.YalmDistanceFromPlayerX;
|
||||
|
||||
/// <summary>
|
||||
/// The Y distance from the local player in yalms.
|
||||
/// </summary>
|
||||
public byte YalmDistanceY => this.actorStruct.YalmDistanceFromPlayerY;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,6 +42,11 @@ namespace Dalamud.Game.ClientState.Actors.Types {
|
|||
/// <summary>
|
||||
/// The maximum MP of this Chara.
|
||||
/// </summary>
|
||||
public int MaxMp => this.actorStruct.MaxMp;
|
||||
public int MaxMp => 10000; // Currently hardcoded because the value in actorStruct is very questionable.
|
||||
|
||||
/// <summary>
|
||||
/// Byte array describing the visual appearance of this Chara. Indexed by <see cref="CustomizeIndex"/>.
|
||||
/// </summary>
|
||||
public byte[] Customize => this.actorStruct.Customize;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,29 +13,42 @@ namespace Dalamud.Game.ClientState.Structs
|
|||
/// </summary>
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
public struct Actor {
|
||||
[FieldOffset(0x30)] [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 30)] public string Name;
|
||||
[FieldOffset(0x30)] [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 30)]
|
||||
public string Name;
|
||||
|
||||
[FieldOffset(116)] public int ActorId;
|
||||
[FieldOffset(128)] public int DataId;
|
||||
[FieldOffset(132)] public int OwnerId;
|
||||
[FieldOffset(140)] public ObjectKind ObjectKind;
|
||||
[FieldOffset(141)] public byte SubKind;
|
||||
[FieldOffset(142)] public bool IsFriendly;
|
||||
[FieldOffset(144)] public byte YalmDistanceFromPlayer1; // Demo says one of these is x distance
|
||||
[FieldOffset(144)] public byte YalmDistanceFromPlayerX; // Demo says one of these is x distance
|
||||
[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 YalmDistanceFromPlayerY; // and the other is z distance
|
||||
[FieldOffset(160)] public Position3 Position;
|
||||
[FieldOffset(176)] public float Rotation; // Rotation around the vertical axis (yaw), from -pi to pi radians
|
||||
|
||||
[FieldOffset(0x17B8)] [MarshalAs(UnmanagedType.ByValArray, SizeConst = 28)] public byte[] Customize;
|
||||
|
||||
[FieldOffset(0x17F8)] public int TargetActorId;
|
||||
|
||||
// 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(0x1868)] public int NameId;
|
||||
[FieldOffset(0x1884)] public byte CurrentWorld;
|
||||
[FieldOffset(0x1886)] public byte HomeWorld;
|
||||
[FieldOffset(6328)] public int CurrentHp;
|
||||
[FieldOffset(6332)] public int MaxHp;
|
||||
[FieldOffset(6336)] public int CurrentMp;
|
||||
[FieldOffset(6340)] public int MaxMp;
|
||||
[FieldOffset(0x1898)] public int CurrentHp;
|
||||
[FieldOffset(0x189C)] public int MaxHp;
|
||||
[FieldOffset(0x18A0)] public int CurrentMp;
|
||||
// This value is weird. It seems to change semi-randomly between 0 and 10k, definitely
|
||||
// in response to mp-using events, but it doesn't often have a value and the changing seems
|
||||
// somewhat arbitrary.
|
||||
[FieldOffset(0x18AA)] public int MaxMp;
|
||||
[FieldOffset(6358)] public byte ClassJob;
|
||||
[FieldOffset(6360)] public byte Level;
|
||||
[FieldOffset(0x1958)][MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)] public StatusEffect[] UIStatusEffects;
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
18
Dalamud/Game/ClientState/Structs/StatusEffect.cs
Normal file
18
Dalamud/Game/ClientState/Structs/StatusEffect.cs
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Dalamud.Game.ClientState.Structs
|
||||
{
|
||||
/// <summary>
|
||||
/// Native memory representation of a FFXIV status effect.
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct StatusEffect
|
||||
{
|
||||
public short EffectId;
|
||||
public byte StackCount;
|
||||
public byte Param;
|
||||
public float Duration;
|
||||
public int OwnerId;
|
||||
}
|
||||
}
|
||||
|
|
@ -65,7 +65,7 @@ namespace Dalamud.Game.Internal {
|
|||
|
||||
Gui = new GameGui(Address.GuiManager, scanner, dalamud);
|
||||
|
||||
Network = new GameNetwork(dalamud, scanner);
|
||||
Network = new GameNetwork(scanner);
|
||||
|
||||
//Resource = new ResourceManager(dalamud, scanner);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ using System.Runtime.InteropServices;
|
|||
using Dalamud.Game.Chat.SeStringHandling.Payloads;
|
||||
using Dalamud.Hooking;
|
||||
using Serilog;
|
||||
using SharpDX;
|
||||
|
||||
namespace Dalamud.Game.Internal.Gui {
|
||||
public sealed class GameGui : IDisposable {
|
||||
|
|
@ -34,6 +35,14 @@ namespace Dalamud.Game.Internal.Gui {
|
|||
private delegate bool OpenMapWithFlagDelegate(IntPtr UIMapObject, string flag);
|
||||
private OpenMapWithFlagDelegate openMapWithFlag;
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
internal delegate IntPtr GetMatrixSingletonDelegate();
|
||||
internal readonly GetMatrixSingletonDelegate getMatrixSingleton;
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
|
||||
private unsafe delegate IntPtr ScreenToWorldNativeDelegate(float *camPosition, float *clipCoords, float rayDistance, float *worldCoords, float *unknown);
|
||||
private readonly ScreenToWorldNativeDelegate screenToWorldNative;
|
||||
|
||||
/// <summary>
|
||||
/// 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
|
||||
|
|
@ -74,6 +83,12 @@ namespace Dalamud.Game.Internal.Gui {
|
|||
this);
|
||||
|
||||
this.getUIObject = Marshal.GetDelegateForFunctionPointer<GetUIObjectDelegate>(Address.GetUIObject);
|
||||
|
||||
this.getMatrixSingleton =
|
||||
Marshal.GetDelegateForFunctionPointer<GetMatrixSingletonDelegate>(Address.GetMatrixSingleton);
|
||||
|
||||
this.screenToWorldNative =
|
||||
Marshal.GetDelegateForFunctionPointer<ScreenToWorldNativeDelegate>(Address.ScreenToWorld);
|
||||
}
|
||||
|
||||
private IntPtr HandleSetGlobalBgmDetour(UInt16 bgmKey, byte a2, UInt32 a3, UInt32 a4, UInt32 a5, byte a6) {
|
||||
|
|
@ -126,6 +141,11 @@ namespace Dalamud.Game.Internal.Gui {
|
|||
return retVal;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Opens the in-game map with a flag on the location of the parameter
|
||||
/// </summary>
|
||||
/// <param name="mapLink">Link to the map to be opened</param>
|
||||
/// <returns>True if there were no errors and it could open the map</returns>
|
||||
public bool OpenMapWithMapLink(MapLinkPayload mapLink)
|
||||
{
|
||||
var uiObjectPtr = getUIObject();
|
||||
|
|
@ -158,6 +178,45 @@ namespace Dalamud.Game.Internal.Gui {
|
|||
return this.openMapWithFlag(uiMapObjectPtr, mapLinkString);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts in-world coordinates to screen coordinates (upper left corner origin).
|
||||
/// </summary>
|
||||
/// <param name="worldPos">Coordinates in the world</param>
|
||||
/// <param name="screenPos">Converted coordinates</param>
|
||||
/// <returns>True if worldPos corresponds to a position in front of the camera</returns>
|
||||
public bool WorldToScreen(Vector3 worldPos, out Vector2 screenPos)
|
||||
{
|
||||
// Get base object with matrices
|
||||
var matrixSingleton = this.getMatrixSingleton();
|
||||
|
||||
// Read current ViewProjectionMatrix plus game window size
|
||||
var viewProjectionMatrix = new Matrix();
|
||||
float width, height;
|
||||
unsafe {
|
||||
var rawMatrix = (float*) (matrixSingleton + 0x1b4).ToPointer();
|
||||
|
||||
for (var i = 0; i < 16; i++, rawMatrix += 1) {
|
||||
viewProjectionMatrix[i] = *rawMatrix;
|
||||
}
|
||||
|
||||
width = *rawMatrix;
|
||||
height = *(rawMatrix + 1);
|
||||
}
|
||||
|
||||
Vector3.Transform( ref worldPos, ref viewProjectionMatrix, out Vector3 pCoords);
|
||||
|
||||
screenPos = new Vector2(pCoords.X / pCoords.Z, pCoords.Y / pCoords.Z);
|
||||
|
||||
screenPos.X = 0.5f * width * (screenPos.X + 1f);
|
||||
screenPos.Y = 0.5f * height * (1f - screenPos.Y);
|
||||
|
||||
return pCoords.Z > 0;
|
||||
}
|
||||
|
||||
public Vector3 ScreenToWorld(Vector2 screenCoords) {
|
||||
return new Vector3();
|
||||
}
|
||||
|
||||
public void SetBgm(ushort bgmKey) => this.setGlobalBgmHook.Original(bgmKey, 0, 0, 0, 0, 0);
|
||||
|
||||
public void Enable() {
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@ namespace Dalamud.Game.Internal.Gui {
|
|||
public IntPtr HandleItemHover { get; set; }
|
||||
public IntPtr HandleItemOut { get; set; }
|
||||
public IntPtr GetUIObject { get; private set; }
|
||||
public IntPtr GetMatrixSingleton { get; private set; }
|
||||
public IntPtr ScreenToWorld { get; private set; }
|
||||
|
||||
public GameGuiAddressResolver(IntPtr baseAddress) {
|
||||
BaseAddress = baseAddress;
|
||||
|
|
@ -31,6 +33,8 @@ namespace Dalamud.Game.Internal.Gui {
|
|||
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");
|
||||
GetUIObject = sig.ScanText("E8 ?? ?? ?? ?? 48 8B C8 48 8B 10 FF 52 40 80 88 ?? ?? ?? ?? 01 E9");
|
||||
GetMatrixSingleton = sig.ScanText("E8 ?? ?? ?? ?? 48 8D 4C 24 ?? 48 89 4c 24 ?? 4C 8D 4D ?? 4C 8D 44 24 ??");
|
||||
ScreenToWorld = sig.ScanText("48 83 EC 48 48 8B 05 ?? ?? ?? ?? 4D 8B D1");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,55 +4,73 @@ using System.Runtime.CompilerServices;
|
|||
using System.Runtime.InteropServices;
|
||||
using Dalamud.Hooking;
|
||||
using Serilog;
|
||||
using SharpDX.DXGI;
|
||||
|
||||
namespace Dalamud.Game.Internal.Network {
|
||||
public sealed class GameNetwork : IDisposable {
|
||||
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
|
||||
private delegate void ProcessZonePacketDelegate(IntPtr a, IntPtr b, IntPtr dataPtr);
|
||||
#region Hooks
|
||||
|
||||
private readonly Hook<ProcessZonePacketDelegate> processZonePacketHook;
|
||||
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
|
||||
private delegate void ProcessZonePacketDownDelegate(IntPtr a, uint targetId, IntPtr dataPtr);
|
||||
private readonly Hook<ProcessZonePacketDownDelegate> processZonePacketDownHook;
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
|
||||
private delegate byte ProcessZonePacketUpDelegate(IntPtr a1, IntPtr dataPtr, IntPtr a3, byte a4);
|
||||
private readonly Hook<ProcessZonePacketUpDelegate> processZonePacketUpHook;
|
||||
|
||||
#endregion
|
||||
|
||||
private GameNetworkAddressResolver Address { get; }
|
||||
private IntPtr baseAddress;
|
||||
|
||||
public delegate void OnZonePacketDelegate(IntPtr dataPtr);
|
||||
public delegate void OnNetworkMessageDelegate(IntPtr dataPtr, ushort opCode, uint targetId, NetworkMessageDirection direction);
|
||||
|
||||
/// <summary>
|
||||
/// Event that is called when a network message is sent/received.
|
||||
/// </summary>
|
||||
public OnNetworkMessageDelegate OnNetworkMessage;
|
||||
|
||||
public OnZonePacketDelegate OnZonePacket;
|
||||
|
||||
private readonly Dalamud dalamud;
|
||||
|
||||
private readonly Queue<byte[]> zoneInjectQueue = new Queue<byte[]>();
|
||||
|
||||
public GameNetwork(Dalamud dalamud, SigScanner scanner) {
|
||||
this.dalamud = dalamud;
|
||||
public GameNetwork(SigScanner scanner) {
|
||||
Address = new GameNetworkAddressResolver();
|
||||
Address.Setup(scanner);
|
||||
|
||||
Log.Verbose("===== G A M E N E T W O R K =====");
|
||||
Log.Verbose("ProcessZonePacket address {ProcessZonePacket}", Address.ProcessZonePacket);
|
||||
Log.Verbose("ProcessZonePacketDown address {ProcessZonePacketDown}", Address.ProcessZonePacketDown);
|
||||
Log.Verbose("ProcessZonePacketUp address {ProcessZonePacketUp}", Address.ProcessZonePacketUp);
|
||||
|
||||
this.processZonePacketHook =
|
||||
new Hook<ProcessZonePacketDelegate>(Address.ProcessZonePacket,
|
||||
new ProcessZonePacketDelegate(ProcessZonePacketDetour),
|
||||
this.processZonePacketDownHook =
|
||||
new Hook<ProcessZonePacketDownDelegate>(Address.ProcessZonePacketDown,
|
||||
new ProcessZonePacketDownDelegate(ProcessZonePacketDownDetour),
|
||||
this);
|
||||
|
||||
this.processZonePacketUpHook =
|
||||
new Hook<ProcessZonePacketUpDelegate>(Address.ProcessZonePacketUp,
|
||||
new ProcessZonePacketUpDelegate(ProcessZonePacketUpDetour),
|
||||
this);
|
||||
}
|
||||
|
||||
public void Enable() {
|
||||
this.processZonePacketHook.Enable();
|
||||
this.processZonePacketDownHook.Enable();
|
||||
this.processZonePacketUpHook.Enable();
|
||||
}
|
||||
|
||||
public void Dispose() {
|
||||
this.processZonePacketHook.Dispose();
|
||||
this.processZonePacketDownHook.Dispose();
|
||||
this.processZonePacketUpHook.Dispose();
|
||||
}
|
||||
|
||||
private void ProcessZonePacketDetour(IntPtr a, IntPtr b, IntPtr dataPtr) {
|
||||
private void ProcessZonePacketDownDetour(IntPtr a, uint targetId, IntPtr dataPtr) {
|
||||
this.baseAddress = a;
|
||||
|
||||
// Call events
|
||||
this.OnZonePacket?.Invoke(dataPtr);
|
||||
|
||||
try {
|
||||
this.processZonePacketHook.Original(a, b, dataPtr);
|
||||
// Call events
|
||||
this.OnNetworkMessage?.Invoke(dataPtr + 0x10, (ushort) Marshal.ReadInt16(dataPtr, 2), targetId, NetworkMessageDirection.ZoneDown);
|
||||
|
||||
this.processZonePacketDownHook.Original(a, targetId, dataPtr);
|
||||
} catch (Exception ex) {
|
||||
string header;
|
||||
try {
|
||||
|
|
@ -63,12 +81,45 @@ namespace Dalamud.Game.Internal.Network {
|
|||
header = "failed";
|
||||
}
|
||||
|
||||
Log.Error(ex, "Exception on ProcessZonePacket hook. Header: " + header);
|
||||
Log.Error(ex, "Exception on ProcessZonePacketDown hook. Header: " + header);
|
||||
|
||||
this.processZonePacketHook.Original(a, b, dataPtr);
|
||||
this.processZonePacketDownHook.Original(a, targetId, dataPtr);
|
||||
}
|
||||
}
|
||||
|
||||
private byte ProcessZonePacketUpDetour(IntPtr a1, IntPtr dataPtr, IntPtr a3, byte a4) {
|
||||
|
||||
try
|
||||
{
|
||||
// Call events
|
||||
this.OnNetworkMessage?.Invoke(dataPtr + 0x20, (ushort) Marshal.ReadInt16(dataPtr), 0x0, NetworkMessageDirection.ZoneUp);
|
||||
|
||||
var op = Marshal.ReadInt16(dataPtr);
|
||||
var length = Marshal.ReadInt16(dataPtr, 8);
|
||||
|
||||
Log.Verbose("[ZONEUP] op: {0} len: {1}", op.ToString("X"), length);
|
||||
Util.DumpMemory(dataPtr + 0x20, length);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
string header;
|
||||
try
|
||||
{
|
||||
var data = new byte[32];
|
||||
Marshal.Copy(dataPtr, data, 0, 32);
|
||||
header = BitConverter.ToString(data);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
header = "failed";
|
||||
}
|
||||
|
||||
Log.Error(ex, "Exception on ProcessZonePacketUp hook. Header: " + header);
|
||||
}
|
||||
|
||||
return this.processZonePacketUpHook.Original(a1, dataPtr, a3, a4);
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
public void InjectZoneProtoPacket(byte[] data) {
|
||||
this.zoneInjectQueue.Enqueue(data);
|
||||
|
|
@ -102,7 +153,7 @@ namespace Dalamud.Game.Internal.Network {
|
|||
Marshal.Copy(packetData, 0, unmanagedPacketData, packetData.Length);
|
||||
|
||||
if (this.baseAddress != IntPtr.Zero) {
|
||||
this.processZonePacketHook.Original(this.baseAddress, IntPtr.Zero, unmanagedPacketData);
|
||||
this.processZonePacketDownHook.Original(this.baseAddress, 0, unmanagedPacketData);
|
||||
}
|
||||
|
||||
Marshal.FreeHGlobal(unmanagedPacketData);
|
||||
|
|
|
|||
|
|
@ -2,12 +2,15 @@ using System;
|
|||
|
||||
namespace Dalamud.Game.Internal.Network {
|
||||
public sealed class GameNetworkAddressResolver : BaseAddressResolver {
|
||||
public IntPtr ProcessZonePacket { get; private set; }
|
||||
|
||||
public IntPtr ProcessZonePacketDown { get; private set; }
|
||||
public IntPtr ProcessZonePacketUp { get; private set; }
|
||||
|
||||
protected override void Setup64Bit(SigScanner sig) {
|
||||
//ProcessZonePacket = sig.ScanText("48 89 74 24 18 57 48 83 EC 50 8B F2 49 8B F8 41 0F B7 50 02 8B CE E8 ?? ?? 7A FF 0F B7 57 02 8D 42 89 3D 5F 02 00 00 0F 87 60 01 00 00 4C 8D 05");
|
||||
//ProcessZonePacket = sig.ScanText("48 89 74 24 18 57 48 83 EC 50 8B F2 49 8B F8 41 0F B7 50 02 8B CE E8 ?? ?? 73 FF 0F B7 57 02 8D 42 ?? 3D ?? ?? 00 00 0F 87 60 01 00 00 4C 8D 05");
|
||||
ProcessZonePacket = sig.ScanText("48 89 74 24 ?? 57 48 83 EC 50 8B FA 49 8B F0");
|
||||
ProcessZonePacketDown = sig.ScanText("48 89 74 24 ?? 57 48 83 EC 50 8B FA 49 8B F0");
|
||||
ProcessZonePacketUp =
|
||||
sig.ScanText("48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 57 41 56 41 57 48 83 EC 70 8B 81 ?? ?? ?? ??");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
6
Dalamud/Game/Internal/Network/NetworkMessageDirection.cs
Normal file
6
Dalamud/Game/Internal/Network/NetworkMessageDirection.cs
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
namespace Dalamud.Game.Internal.Network {
|
||||
public enum NetworkMessageDirection {
|
||||
ZoneDown,
|
||||
ZoneUp
|
||||
}
|
||||
}
|
||||
|
|
@ -5,6 +5,7 @@ using System.Linq;
|
|||
using System.Runtime.InteropServices;
|
||||
using System.Threading.Tasks;
|
||||
using Dalamud.Data.TransientSheet;
|
||||
using Dalamud.Game.Internal.Network;
|
||||
using Dalamud.Game.Network.MarketBoardUploaders;
|
||||
using Dalamud.Game.Network.Structures;
|
||||
using Dalamud.Game.Network.Universalis.MarketBoardUploaders;
|
||||
|
|
@ -32,22 +33,23 @@ namespace Dalamud.Game.Network {
|
|||
|
||||
this.uploader = new UniversalisMarketBoardUploader(dalamud);
|
||||
|
||||
dalamud.Framework.Network.OnZonePacket += OnZonePacket;
|
||||
dalamud.Framework.Network.OnNetworkMessage += OnNetworkMessage;
|
||||
|
||||
}
|
||||
|
||||
private void OnZonePacket(IntPtr dataPtr) {
|
||||
if (!this.dalamud.Data.IsDataReady)
|
||||
private void OnNetworkMessage(IntPtr dataPtr, ushort opCode, uint targetId, NetworkMessageDirection direction) {
|
||||
if (direction != NetworkMessageDirection.ZoneDown)
|
||||
return;
|
||||
|
||||
var opCode = (ushort) Marshal.ReadInt16(dataPtr, 2);
|
||||
if (!this.dalamud.Data.IsDataReady)
|
||||
return;
|
||||
|
||||
if (opCode == this.dalamud.Data.ServerOpCodes["CfNotifyPop"]) {
|
||||
var data = new byte[64];
|
||||
Marshal.Copy(dataPtr, data, 0, 64);
|
||||
|
||||
var notifyType = data[16];
|
||||
var contentFinderConditionId = BitConverter.ToUInt16(data, 36);
|
||||
var notifyType = data[0];
|
||||
var contentFinderConditionId = BitConverter.ToUInt16(data, 0x14);
|
||||
|
||||
if (notifyType != 3)
|
||||
return;
|
||||
|
|
@ -65,14 +67,16 @@ namespace Dalamud.Game.Network {
|
|||
contentFinderCondition.Image = 112324;
|
||||
}
|
||||
|
||||
var flashInfo = new NativeFunctions.FLASHWINFO();
|
||||
flashInfo.cbSize = (uint) Marshal.SizeOf<NativeFunctions.FLASHWINFO>();
|
||||
flashInfo.uCount = uint.MaxValue;
|
||||
flashInfo.dwTimeout = 0;
|
||||
flashInfo.dwFlags = NativeFunctions.FlashWindow.FLASHW_TRAY |
|
||||
NativeFunctions.FlashWindow.FLASHW_TIMERNOFG;
|
||||
flashInfo.hwnd = Process.GetCurrentProcess().MainWindowHandle;
|
||||
NativeFunctions.FlashWindowEx(ref flashInfo);
|
||||
if (!NativeFunctions.ApplicationIsActivated()) {
|
||||
var flashInfo = new NativeFunctions.FLASHWINFO();
|
||||
flashInfo.cbSize = (uint)Marshal.SizeOf<NativeFunctions.FLASHWINFO>();
|
||||
flashInfo.uCount = uint.MaxValue;
|
||||
flashInfo.dwTimeout = 0;
|
||||
flashInfo.dwFlags = NativeFunctions.FlashWindow.FLASHW_ALL |
|
||||
NativeFunctions.FlashWindow.FLASHW_TIMERNOFG;
|
||||
flashInfo.hwnd = Process.GetCurrentProcess().MainWindowHandle;
|
||||
NativeFunctions.FlashWindowEx(ref flashInfo);
|
||||
}
|
||||
|
||||
Task.Run(async () => {
|
||||
this.dalamud.Framework.Gui.Chat.Print("Duty pop: " + contentFinderCondition.Name);
|
||||
|
|
@ -97,8 +101,8 @@ namespace Dalamud.Game.Network {
|
|||
|
||||
Task.Run(async () => {
|
||||
for (var rouletteIndex = 1; rouletteIndex < 11; rouletteIndex++) {
|
||||
var currentRoleKey = data[16 + rouletteIndex];
|
||||
var prevRoleKey = this.lastPreferredRole[16 + rouletteIndex];
|
||||
var currentRoleKey = data[rouletteIndex];
|
||||
var prevRoleKey = this.lastPreferredRole[rouletteIndex];
|
||||
|
||||
Log.Verbose("CfPreferredRole: {0} - {1} => {2}", rouletteIndex, prevRoleKey, currentRoleKey);
|
||||
|
||||
|
|
@ -139,8 +143,8 @@ namespace Dalamud.Game.Network {
|
|||
|
||||
if (!this.optOutMbUploads) {
|
||||
if (opCode == this.dalamud.Data.ServerOpCodes["MarketBoardItemRequestStart"]) {
|
||||
var catalogId = (uint) Marshal.ReadInt32(dataPtr + 0x10);
|
||||
var amount = Marshal.ReadByte(dataPtr + 0x1B);
|
||||
var catalogId = (uint) Marshal.ReadInt32(dataPtr);
|
||||
var amount = Marshal.ReadByte(dataPtr + 0xB);
|
||||
|
||||
this.marketBoardRequests.Add(new MarketBoardItemRequest {
|
||||
CatalogId = catalogId,
|
||||
|
|
@ -154,7 +158,7 @@ namespace Dalamud.Game.Network {
|
|||
}
|
||||
|
||||
if (opCode == this.dalamud.Data.ServerOpCodes["MarketBoardOfferings"]) {
|
||||
var listing = MarketBoardCurrentOfferings.Read(dataPtr + 0x10);
|
||||
var listing = MarketBoardCurrentOfferings.Read(dataPtr);
|
||||
|
||||
var request =
|
||||
this.marketBoardRequests.LastOrDefault(
|
||||
|
|
@ -209,7 +213,7 @@ namespace Dalamud.Game.Network {
|
|||
}
|
||||
|
||||
if (opCode == this.dalamud.Data.ServerOpCodes["MarketBoardHistory"]) {
|
||||
var listing = MarketBoardHistory.Read(dataPtr + 0x10);
|
||||
var listing = MarketBoardHistory.Read(dataPtr);
|
||||
|
||||
var request = this.marketBoardRequests.LastOrDefault(r => r.CatalogId == listing.CatalogId);
|
||||
|
||||
|
|
@ -232,7 +236,7 @@ namespace Dalamud.Game.Network {
|
|||
|
||||
if (opCode == this.dalamud.Data.ServerOpCodes["MarketTaxRates"])
|
||||
{
|
||||
var taxes = MarketTaxRates.Read(dataPtr + 0x10);
|
||||
var taxes = MarketTaxRates.Read(dataPtr);
|
||||
|
||||
Log.Verbose("MarketTaxRates: limsa#{0} grid#{1} uldah#{2} ish#{3} kugane#{4} cr#{5}",
|
||||
taxes.LimsaLominsaTax, taxes.GridaniaTax, taxes.UldahTax, taxes.IshgardTax, taxes.KuganeTax, taxes.CrystariumTax);
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ namespace Dalamud.Interface
|
|||
|
||||
private static readonly Dictionary<string, string> AssetDictionary = new Dictionary<string, string> {
|
||||
{AssetStoreUrl + "UIRes/serveropcode.json", "UIRes/serveropcode.json" },
|
||||
{AssetStoreUrl + "UIRes/clientopcode.json", "UIRes/clientopcode.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" },
|
||||
|
|
@ -27,17 +28,6 @@ namespace Dalamud.Interface
|
|||
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) {
|
||||
|
|
@ -45,7 +35,7 @@ namespace Dalamud.Interface
|
|||
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(filePath));
|
||||
|
||||
if (!File.Exists(filePath) || forceRedownload) {
|
||||
if (!File.Exists(filePath)) {
|
||||
Log.Verbose("Downloading {0} to {1}...", entry.Key, entry.Value);
|
||||
try {
|
||||
File.WriteAllBytes(filePath, await client.GetByteArrayAsync(entry.Key));
|
||||
|
|
@ -53,16 +43,8 @@ namespace Dalamud.Interface
|
|||
// 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.");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using Dalamud.Game.Internal;
|
||||
using ImGuiNET;
|
||||
|
|
@ -7,10 +8,10 @@ using ImGuiScene;
|
|||
namespace Dalamud.Interface
|
||||
{
|
||||
class DalamudCreditsWindow : IDisposable {
|
||||
private string creditsText = @$"
|
||||
private const string CreditsTextTempl = @"
|
||||
Dalamud
|
||||
A FFXIV Hooking Framework
|
||||
Version {typeof(Dalamud).Assembly.GetName().Version}
|
||||
Version {0}
|
||||
|
||||
|
||||
created by:
|
||||
|
|
@ -44,6 +45,11 @@ gucciBane
|
|||
|
||||
|
||||
|
||||
Your plugins were made by:
|
||||
|
||||
{1}
|
||||
|
||||
|
||||
Special thanks:
|
||||
|
||||
Adam
|
||||
|
|
@ -64,14 +70,23 @@ Contribute at: https://github.com/goaaats/Dalamud
|
|||
Thank you for using XIVLauncher!
|
||||
";
|
||||
|
||||
private readonly Dalamud dalamud;
|
||||
private TextureWrap logoTexture;
|
||||
private Framework framework;
|
||||
|
||||
public DalamudCreditsWindow(TextureWrap logoTexture, Framework framework) {
|
||||
private string creditsText;
|
||||
|
||||
public DalamudCreditsWindow(Dalamud dalamud, TextureWrap logoTexture, Framework framework) {
|
||||
this.dalamud = dalamud;
|
||||
this.logoTexture = logoTexture;
|
||||
this.framework = framework;
|
||||
|
||||
framework.Gui.SetBgm(132);
|
||||
|
||||
var pluginCredits = dalamud.PluginManager.Plugins.Where(x => x.Definition != null).Aggregate(string.Empty, (current, plugin) => current + $"{plugin.Definition.Name} by {plugin.Definition.Author}\n");
|
||||
|
||||
this.creditsText =
|
||||
string.Format(CreditsTextTempl, typeof(Dalamud).Assembly.GetName().Version, pluginCredits);
|
||||
}
|
||||
|
||||
public void Dispose() {
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using Dalamud.Game.Chat;
|
||||
|
|
@ -17,6 +18,9 @@ namespace Dalamud.Interface
|
|||
|
||||
private int currentKind;
|
||||
|
||||
private bool drawActors = false;
|
||||
private float maxActorDrawDistance = 20;
|
||||
|
||||
public DalamudDataWindow(Dalamud dalamud) {
|
||||
this.dalamud = dalamud;
|
||||
|
||||
|
|
@ -84,6 +88,9 @@ namespace Dalamud.Interface
|
|||
stateString += $"LastLinkedItem: {this.dalamud.Framework.Gui.Chat.LastLinkedItemId.ToString()}\n";
|
||||
stateString += $"TerritoryType: {this.dalamud.ClientState.TerritoryType}\n\n";
|
||||
|
||||
ImGui.Checkbox("Draw actors on screen", ref this.drawActors);
|
||||
ImGui.SliderFloat("Draw Distance", ref this.maxActorDrawDistance, 2f, 40f);
|
||||
|
||||
for (var i = 0; i < this.dalamud.ClientState.Actors.Length; i++) {
|
||||
var actor = this.dalamud.ClientState.Actors[i];
|
||||
|
||||
|
|
@ -91,18 +98,36 @@ namespace Dalamud.Interface
|
|||
continue;
|
||||
|
||||
stateString +=
|
||||
$"{actor.Address.ToInt64():X}:{actor.ActorId:X}[{i}] - {actor.ObjectKind} - {actor.Name} - {actor.Position.X} {actor.Position.Y} {actor.Position.Z}\n";
|
||||
$"{actor.Address.ToInt64():X}:{actor.ActorId:X}[{i}] - {actor.ObjectKind} - {actor.Name} - X{actor.Position.X} Y{actor.Position.Y} Z{actor.Position.Z} D{actor.YalmDistanceX} R{actor.Rotation}\n";
|
||||
|
||||
if (actor is Npc npc)
|
||||
stateString += $" DataId: {npc.DataId} NameId:{npc.NameId}\n";
|
||||
|
||||
if (actor is Chara chara)
|
||||
stateString +=
|
||||
$" Level: {chara.Level} ClassJob: {chara.ClassJob.GameData.Name} CHP: {chara.CurrentHp} MHP: {chara.MaxHp} CMP: {chara.CurrentMp} MMP: {chara.MaxMp}\n";
|
||||
$" Level: {chara.Level} ClassJob: {chara.ClassJob.GameData.Name} CHP: {chara.CurrentHp} MHP: {chara.MaxHp} CMP: {chara.CurrentMp} MMP: {chara.MaxMp}\n Customize: {BitConverter.ToString(chara.Customize).Replace("-", " ")}\n";
|
||||
|
||||
if (actor is PlayerCharacter pc)
|
||||
stateString +=
|
||||
$" HomeWorld: {pc.HomeWorld.GameData.Name} CurrentWorld: {pc.CurrentWorld.GameData.Name} FC: {pc.CompanyTag}\n";
|
||||
|
||||
if (this.drawActors && this.dalamud.Framework.Gui.WorldToScreen(actor.Position, out var screenCoords)) {
|
||||
ImGui.PushID("ActorWindow" + i);
|
||||
ImGui.SetNextWindowPos(new Vector2(screenCoords.X, screenCoords.Y));
|
||||
|
||||
if (actor.YalmDistanceX > this.maxActorDrawDistance)
|
||||
continue;
|
||||
|
||||
ImGui.SetNextWindowBgAlpha(Math.Max(1f - (actor.YalmDistanceX / this.maxActorDrawDistance), 0.2f));
|
||||
if (ImGui.Begin("Actor" + i,
|
||||
ImGuiWindowFlags.NoDecoration | ImGuiWindowFlags.AlwaysAutoResize |
|
||||
ImGuiWindowFlags.NoSavedSettings | ImGuiWindowFlags.NoMove | ImGuiWindowFlags.NoMouseInputs |
|
||||
ImGuiWindowFlags.NoFocusOnAppearing | ImGuiWindowFlags.NoNav)) {
|
||||
ImGui.Text($"{actor.Address.ToInt64():X}:{actor.ActorId:X}[{i}] - {actor.ObjectKind} - {actor.Name}");
|
||||
ImGui.End();
|
||||
}
|
||||
ImGui.PopID();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -54,11 +54,15 @@ namespace Dalamud.Interface
|
|||
|
||||
public ImGuiIOPtr LastImGuiIoPtr;
|
||||
|
||||
public Action OnBuildFonts;
|
||||
private bool isRebuildingFonts = false;
|
||||
|
||||
/// <summary>
|
||||
/// This event gets called by a plugin UiBuilder when read
|
||||
/// </summary>
|
||||
public event RawDX11Scene.BuildUIDelegate OnDraw;
|
||||
|
||||
|
||||
public InterfaceManager(Dalamud dalamud, SigScanner scanner)
|
||||
{
|
||||
this.dalamud = dalamud;
|
||||
|
|
@ -200,7 +204,18 @@ namespace Dalamud.Interface
|
|||
return null;
|
||||
}
|
||||
|
||||
private unsafe IntPtr PresentDetour(IntPtr swapChain, uint syncInterval, uint presentFlags)
|
||||
// Sets up a deferred invocation of font rebuilding, before the next render frame
|
||||
public void RebuildFonts()
|
||||
{
|
||||
// don't invoke this multiple times per frame, in case multiple plugins call it
|
||||
if (!this.isRebuildingFonts)
|
||||
{
|
||||
this.isRebuildingFonts = true;
|
||||
this.scene.OnNewRenderFrame += RebuildFontsInternal;
|
||||
}
|
||||
}
|
||||
|
||||
private IntPtr PresentDetour(IntPtr swapChain, uint syncInterval, uint presentFlags)
|
||||
{
|
||||
if (this.scene == null)
|
||||
{
|
||||
|
|
@ -209,30 +224,7 @@ namespace Dalamud.Interface
|
|||
this.scene.OnBuildUI += Display;
|
||||
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");
|
||||
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();
|
||||
|
||||
fontConfig.Destroy();
|
||||
rangeHandle.Free();
|
||||
SetupFonts();
|
||||
|
||||
ImGui.GetStyle().GrabRounding = 3f;
|
||||
ImGui.GetStyle().FrameRounding = 4f;
|
||||
|
|
@ -268,6 +260,49 @@ namespace Dalamud.Interface
|
|||
return this.presentHook.Original(swapChain, syncInterval, presentFlags);
|
||||
}
|
||||
|
||||
private unsafe void SetupFonts()
|
||||
{
|
||||
ImGui.GetIO().Fonts.Clear();
|
||||
|
||||
ImFontConfigPtr fontConfig = ImGuiNative.ImFontConfig_ImFontConfig();
|
||||
fontConfig.MergeMode = true;
|
||||
fontConfig.PixelSnapH = true;
|
||||
|
||||
var fontPathJp = Path.Combine(this.dalamud.StartInfo.WorkingDirectory, "UIRes", "NotoSansCJKjp-Medium.otf");
|
||||
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());
|
||||
|
||||
OnBuildFonts?.Invoke();
|
||||
|
||||
ImGui.GetIO().Fonts.Build();
|
||||
|
||||
fontConfig.Destroy();
|
||||
rangeHandle.Free();
|
||||
}
|
||||
|
||||
// This is intended to only be called as a handler attached to scene.OnNewRenderFrame
|
||||
private void RebuildFontsInternal()
|
||||
{
|
||||
SetupFonts();
|
||||
|
||||
this.scene.OnNewRenderFrame -= RebuildFontsInternal;
|
||||
this.scene.InvalidateFonts();
|
||||
|
||||
this.isRebuildingFonts = false;
|
||||
}
|
||||
|
||||
private IntPtr ResizeBuffersDetour(IntPtr swapChain, uint bufferCount, uint width, uint height, uint newFormat, uint swapChainFlags)
|
||||
{
|
||||
Log.Verbose($"Calling resizebuffers {bufferCount} {width} {height} {newFormat} {swapChainFlags}");
|
||||
|
|
|
|||
|
|
@ -70,6 +70,27 @@ namespace Dalamud.Interface
|
|||
public TextureWrap LoadImageRaw(byte[] imageData, int width, int height, int numChannels) =>
|
||||
this.interfaceManager.LoadImageRaw(imageData, width, height, numChannels);
|
||||
|
||||
/// <summary>
|
||||
/// An event that is called any time ImGui fonts need to be rebuilt.<br/>
|
||||
/// Any ImFontPtr objects that you store <strong>can be invalidated</strong> when fonts are rebuilt
|
||||
/// (at any time), so you should both reload your custom fonts and restore those
|
||||
/// pointers inside this handler.<br/>
|
||||
/// <strong>PLEASE remove this handler inside Dipose, or when you no longer need your fonts!</strong>
|
||||
/// </summary>
|
||||
public Action OnBuildFonts
|
||||
{
|
||||
get { return this.interfaceManager.OnBuildFonts; }
|
||||
set { this.interfaceManager.OnBuildFonts = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Call this to queue a rebuild of the font atlas.<br/>
|
||||
/// This will invoke any <see cref="OnBuildFonts"/> handlers and ensure that any loaded fonts are
|
||||
/// ready to be used on the next UI frame.
|
||||
/// </summary>
|
||||
public void RebuildFonts() =>
|
||||
this.interfaceManager.RebuildFonts();
|
||||
|
||||
/// <summary>
|
||||
/// Event that is fired when the plugin should open its configuration interface.
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
|
@ -58,6 +59,28 @@ namespace Dalamud
|
|||
|
||||
#endregion
|
||||
|
||||
/// <summary>Returns true if the current application has focus, false otherwise</summary>
|
||||
public static bool ApplicationIsActivated()
|
||||
{
|
||||
var activatedHandle = GetForegroundWindow();
|
||||
if (activatedHandle == IntPtr.Zero)
|
||||
{
|
||||
return false; // No window is currently activated
|
||||
}
|
||||
|
||||
var procId = Process.GetCurrentProcess().Id;
|
||||
int activeProcId;
|
||||
GetWindowThreadProcessId(activatedHandle, out activeProcId);
|
||||
|
||||
return activeProcId == procId;
|
||||
}
|
||||
|
||||
[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
|
||||
private static extern IntPtr GetForegroundWindow();
|
||||
|
||||
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
|
||||
private static extern int GetWindowThreadProcessId(IntPtr handle, out int processId);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
public static extern bool FlashWindowEx(ref FLASHWINFO pwfi);
|
||||
|
|
|
|||
|
|
@ -58,14 +58,15 @@ namespace Dalamud.Plugin
|
|||
}
|
||||
}
|
||||
|
||||
public bool InstallPlugin(PluginDefinition definition) {
|
||||
public bool InstallPlugin(PluginDefinition definition, bool enableAfterInstall = true) {
|
||||
try
|
||||
{
|
||||
var outputDir = new DirectoryInfo(Path.Combine(this.pluginDirectory, definition.InternalName, definition.AssemblyVersion));
|
||||
var dllFile = new FileInfo(Path.Combine(outputDir.FullName, $"{definition.InternalName}.dll"));
|
||||
var disabledFile = new FileInfo(Path.Combine(outputDir.FullName, ".disabled"));
|
||||
var wasDisabled = disabledFile.Exists;
|
||||
|
||||
if (dllFile.Exists)
|
||||
if (dllFile.Exists && enableAfterInstall)
|
||||
{
|
||||
if (disabledFile.Exists)
|
||||
disabledFile.Delete();
|
||||
|
|
@ -73,9 +74,17 @@ namespace Dalamud.Plugin
|
|||
return this.manager.LoadPluginFromAssembly(dllFile, false);
|
||||
}
|
||||
|
||||
if (outputDir.Exists)
|
||||
outputDir.Delete(true);
|
||||
outputDir.Create();
|
||||
if (dllFile.Exists && !enableAfterInstall) {
|
||||
return true;
|
||||
}
|
||||
|
||||
try {
|
||||
if (outputDir.Exists)
|
||||
outputDir.Delete(true);
|
||||
outputDir.Create();
|
||||
} catch {
|
||||
// ignored, since the plugin may be loaded already
|
||||
}
|
||||
|
||||
var path = Path.GetTempFileName();
|
||||
Log.Information("Downloading plugin to {0}", path);
|
||||
|
|
@ -86,6 +95,11 @@ namespace Dalamud.Plugin
|
|||
|
||||
ZipFile.ExtractToDirectory(path, outputDir.FullName);
|
||||
|
||||
if (wasDisabled || !enableAfterInstall) {
|
||||
disabledFile.Create();
|
||||
return true;
|
||||
}
|
||||
|
||||
return this.manager.LoadPluginFromAssembly(dllFile, false);
|
||||
}
|
||||
catch (Exception e)
|
||||
|
|
@ -145,6 +159,12 @@ namespace Dalamud.Plugin
|
|||
|
||||
if (!dryRun)
|
||||
{
|
||||
var wasEnabled =
|
||||
this.manager.Plugins.Where(x => x.Definition != null).Any(
|
||||
x => x.Definition.InternalName == info.InternalName); ;
|
||||
|
||||
Log.Verbose("wasEnabled: {0}", wasEnabled);
|
||||
|
||||
// Try to disable plugin if it is loaded
|
||||
try
|
||||
{
|
||||
|
|
@ -153,7 +173,7 @@ namespace Dalamud.Plugin
|
|||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(ex, "Plugin disable failed");
|
||||
hasError = true;
|
||||
//hasError = true;
|
||||
}
|
||||
|
||||
try {
|
||||
|
|
@ -165,10 +185,10 @@ namespace Dalamud.Plugin
|
|||
disabledFile.Create();
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
Log.Error(ex, "Plugin disable failed");
|
||||
Log.Error(ex, "Plugin disable old versions failed");
|
||||
}
|
||||
|
||||
var installSuccess = InstallPlugin(remoteInfo);
|
||||
var installSuccess = InstallPlugin(remoteInfo, wasEnabled);
|
||||
|
||||
if (installSuccess)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,19 +1,21 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Serilog;
|
||||
|
||||
namespace Dalamud
|
||||
{
|
||||
static class Util
|
||||
{
|
||||
public static string ByteArrayToHex(byte[] bytes, int offset = 0, int bytesPerLine = 16)
|
||||
{
|
||||
if (bytes == null)
|
||||
{
|
||||
return String.Empty;
|
||||
}
|
||||
namespace Dalamud {
|
||||
internal static class Util {
|
||||
public static void DumpMemory(IntPtr offset, int len = 512) {
|
||||
var data = new byte[len];
|
||||
Marshal.Copy(offset, data, 0, len);
|
||||
Log.Information(ByteArrayToHex(data));
|
||||
}
|
||||
|
||||
public static string ByteArrayToHex(byte[] bytes, int offset = 0, int bytesPerLine = 16) {
|
||||
if (bytes == null) return string.Empty;
|
||||
|
||||
var hexChars = "0123456789ABCDEF".ToCharArray();
|
||||
|
||||
|
|
@ -26,8 +28,7 @@ namespace Dalamud
|
|||
|
||||
var sb = new StringBuilder(numLines * lineLength);
|
||||
|
||||
for (var i = 0; i < bytes.Length; i += bytesPerLine)
|
||||
{
|
||||
for (var i = 0; i < bytes.Length; i += bytesPerLine) {
|
||||
var h = i + offset;
|
||||
|
||||
line[0] = hexChars[(h >> 28) & 0xF];
|
||||
|
|
@ -42,25 +43,18 @@ namespace Dalamud
|
|||
var hexColumn = offsetBlock;
|
||||
var charColumn = byteBlock;
|
||||
|
||||
for (var j = 0; j < bytesPerLine; j++)
|
||||
{
|
||||
if (j > 0 && (j & 7) == 0)
|
||||
{
|
||||
hexColumn++;
|
||||
}
|
||||
for (var j = 0; j < bytesPerLine; j++) {
|
||||
if (j > 0 && (j & 7) == 0) hexColumn++;
|
||||
|
||||
if (i + j >= bytes.Length)
|
||||
{
|
||||
if (i + j >= bytes.Length) {
|
||||
line[hexColumn] = ' ';
|
||||
line[hexColumn + 1] = ' ';
|
||||
line[charColumn] = ' ';
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
var by = bytes[i + j];
|
||||
line[hexColumn] = hexChars[(@by >> 4) & 0xF];
|
||||
line[hexColumn + 1] = hexChars[@by & 0xF];
|
||||
line[charColumn] = @by < 32 ? '.' : (char)@by;
|
||||
line[hexColumn] = hexChars[(by >> 4) & 0xF];
|
||||
line[hexColumn + 1] = hexChars[by & 0xF];
|
||||
line[charColumn] = by < 32 ? '.' : (char) by;
|
||||
}
|
||||
|
||||
hexColumn += 3;
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit aaa037938d6fe835a15542a3451d12108e3f83b6
|
||||
Subproject commit d5b9345dc1463d746b832843bd7c81b753d4e5b0
|
||||
Loading…
Add table
Add a link
Reference in a new issue