Skip to content

Commit

Permalink
usable version
Browse files Browse the repository at this point in the history
  • Loading branch information
chalkos committed Aug 2, 2021
1 parent 13130d1 commit 1dba386
Show file tree
Hide file tree
Showing 22 changed files with 1,411 additions and 0 deletions.
10 changes: 10 additions & 0 deletions Data/Marketbuddy.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"Author": "Chalkos",
"Name": "Marketbuddy",
"Description": "Helper for your day-to-day market operations",
"InternalName": "Marketbuddy",
"AssemblyVersion": "0.1.0.0",
"RepoUrl": "https://github.com/chalkos/Marketbuddy",
"ApplicableVersion": "any",
"DalamudApiLevel": 3
}
Binary file added Data/NotoSansCJKjp-Medium.otf
Binary file not shown.
Binary file added Data/gamesym.ttf
Binary file not shown.
Binary file added Data/goat.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
31 changes: 31 additions & 0 deletions Marketbuddy.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.29709.97
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Marketbuddy", "Marketbuddy\Marketbuddy.csproj", "{13C812E9-0D42-4B95-8646-40EEBF30636F}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UIDev", "UIDev\UIDev.csproj", "{4FEC9558-EB25-419F-B86E-51B8CFDA32B7}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{13C812E9-0D42-4B95-8646-40EEBF30636F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{13C812E9-0D42-4B95-8646-40EEBF30636F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{13C812E9-0D42-4B95-8646-40EEBF30636F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{13C812E9-0D42-4B95-8646-40EEBF30636F}.Release|Any CPU.Build.0 = Release|Any CPU
{4FEC9558-EB25-419F-B86E-51B8CFDA32B7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4FEC9558-EB25-419F-B86E-51B8CFDA32B7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4FEC9558-EB25-419F-B86E-51B8CFDA32B7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4FEC9558-EB25-419F-B86E-51B8CFDA32B7}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {B17E85B1-5F60-4440-9F9A-3DDE877E8CDF}
EndGlobalSection
EndGlobal
30 changes: 30 additions & 0 deletions Marketbuddy/Common/CloseButtons.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using Dalamud.Plugin;
using FFXIVClientStructs.FFXIV.Client.UI;
using FFXIVClientStructs.FFXIV.Component.GUI;
using System;
using System.Collections.Generic;
using System.Text;

namespace Marketbuddy.Common
{
internal static class CloseButtons
{
private static Dictionary<string, int> closeButtonIndexes = new Dictionary<string, int>()
{
{"ItemSearchResult", 6 },
};

internal static unsafe AtkComponentNode* getCloseButton(AtkUnitBase* addon)
{
int index;
string name = Encoding.UTF8.GetString(addon->Name, 16);
if (name != "ItemSearchResult" || !closeButtonIndexes.TryGetValue(name, out index))
return null;

AtkUldManager uldMgr = addon->WindowNode->Component->UldManager;
var ret = (uldMgr.NodeListCount > index ? uldMgr.NodeList[index]->GetComponent()->OwnerNode : null);
PluginLog.Information($"Got button for {name}({(UInt64)addon:X}) from nodes[{index}] with addr: {(UInt64)ret:X}");
return ret;
}
}
}
190 changes: 190 additions & 0 deletions Marketbuddy/Common/Common.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using Dalamud.Game;
using Dalamud.Game.Text.SeStringHandling;
using Dalamud.Hooking;
using Dalamud.Plugin;
using FFXIVClientStructs.Attributes;
using FFXIVClientStructs.FFXIV.Client.System.String;
using FFXIVClientStructs.FFXIV.Component.GUI;
using WindowsInput;
using WindowsInput.Native;

namespace Marketbuddy.Common
{
// based on https://github.com/Caraxi/SimpleTweaksPlugin/blob/main/Helper/Common.cs
// and https://github.com/daemitus/ClickLib/blob/master/ClickLib/ClickBase.cs
internal unsafe class Commons : IDisposable
{
public static DalamudPluginInterface PluginInterface { get; private set; }

public static SigScanner Scanner => PluginInterface.TargetModuleScanner;

public static List<IHookWrapper> HookList = new();

private InputSimulator InputSimulator;

protected delegate void ReceiveEventDelegate(IntPtr addon, EventType evt, uint a3, IntPtr a4, IntPtr a5);

public Commons(DalamudPluginInterface pluginInterface)
{
PluginInterface = pluginInterface;
InputSimulator = new InputSimulator();
}

public void Dispose()
{
foreach (var hook in HookList.Where(hook => !hook.IsDisposed))
{
if (hook.IsEnabled)
hook.Disable();
hook.Dispose();
}
HookList.Clear();
}

public void pressEsc()
{
InputSimulator.Keyboard.KeyPress(VirtualKeyCode.ESCAPE);
}

public void WriteSeString(byte** startPtr, IntPtr alloc, SeString seString)
{
if (startPtr == null) return;
var start = *startPtr;
if (start == null) return;
if (start == (byte*)alloc) return;
WriteSeString((byte*)alloc, seString);
*startPtr = (byte*)alloc;
}

public SeString ReadSeString(byte** startPtr)
{
if (startPtr == null) return null;
var start = *startPtr;
if (start == null) return null;
return ReadSeString(start);
}

public SeString ReadSeString(byte* ptr)
{
var offset = 0;
while (true)
{
var b = *(ptr + offset);
if (b == 0)
{
break;
}
offset += 1;
}
var bytes = new byte[offset];
Marshal.Copy(new IntPtr(ptr), bytes, 0, offset);
return PluginInterface.SeStringManager.Parse(bytes);
}

public void WriteSeString(byte* dst, SeString s)
{
var bytes = s.Encode();
for (var i = 0; i < bytes.Length; i++)
{
*(dst + i) = bytes[i];
}
*(dst + bytes.Length) = 0;
}

public SeString ReadSeString(Utf8String xivString)
{
var len = (int)(xivString.BufUsed > int.MaxValue ? int.MaxValue : xivString.BufUsed);
var bytes = new byte[len];
Marshal.Copy(new IntPtr(xivString.StringPtr), bytes, 0, len);
return PluginInterface.SeStringManager.Parse(bytes);
}

public void WriteSeString(Utf8String xivString, SeString s)
{
var bytes = s.Encode();
int i;
xivString.BufUsed = 0;
for (i = 0; i < bytes.Length && i < xivString.BufSize - 1; i++)
{
*(xivString.StringPtr + i) = bytes[i];
xivString.BufUsed++;
}
*(xivString.StringPtr + i) = 0;
}

public static HookWrapper<T> Hook<T>(string signature, T detour, bool enable = true, int addressOffset = 0) where T : Delegate
{
var addr = Scanner.ScanText(signature);
PluginLog.Information("hooking function at {add}", addr);
var h = new Hook<T>(addr + addressOffset, detour);
var wh = new HookWrapper<T>(h);
if (enable) wh.Enable();
HookList.Add(wh);
return wh;
}

public static void OpenBrowser(string url)
{
Process.Start(new ProcessStartInfo { FileName = url, UseShellExecute = true });
}
protected unsafe ReceiveEventDelegate GetReceiveEventDelegate(AtkEventListener* eventListener)
{
var receiveEventAddress = new IntPtr(eventListener->vfunc[2]);
return Marshal.GetDelegateForFunctionPointer<ReceiveEventDelegate>(receiveEventAddress);
}

internal unsafe void SendClick(IntPtr arg1, EventType arg2, uint arg3, void* target) => SendClick(arg1, arg2, arg3, target, IntPtr.Zero);

internal unsafe void SendClick(IntPtr arg1, EventType arg2, uint arg3, void* target, IntPtr arg5)
{
var receiveEvent = GetReceiveEventDelegate((AtkEventListener*)arg1);

var arg4 = Marshal.AllocHGlobal(0x40);
for (var i = 0; i < 0x40; i++)
Marshal.WriteByte(arg4, i, 0);

Marshal.WriteIntPtr(arg4, 0x8, new IntPtr(target));
Marshal.WriteIntPtr(arg4, 0x10, arg1);

if (arg5 == IntPtr.Zero)
{
arg5 = Marshal.AllocHGlobal(0x40);
for (var i = 0; i < 0x40; i++)
Marshal.WriteByte(arg5, i, 0);
}

receiveEvent(arg1, arg2, arg3, arg4, arg5);

Marshal.FreeHGlobal(arg4);
Marshal.FreeHGlobal(arg5);
}

public static Task<T> StartSTATask<T>(Func<T> func)
{
var tcs = new TaskCompletionSource<T>();
var thread = new Thread(() =>
{
try
{
var result = func();
tcs.SetResult(result);
}
catch (Exception e)
{
tcs.SetException(e);
}
});
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
return tcs.Task;
}
}
}
88 changes: 88 additions & 0 deletions Marketbuddy/Common/EventType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Marketbuddy.Common
{
public enum EventType : ushort
{
NORMAL = 1,
NORMAL_MAX = 2,
MOUSE_DOWN = 3,
MOUSE_UP = 4,
MOUSE_MOVE = 5,
MOUSE_ROLL_OVER = 6,
MOUSE_ROLL_OUT = 7,
MOUSE_WHEEL = 8,
MOUSE_CLICK = 9,
MOUSE_DOUBLE_CLICK = 10,
MOUSE_MAX = 11,
INPUT = 12,
INPUT_KEY = 13,
INPUT_MAX = 14,
PAD = 15,
PAD_MAX = 16,
FOCUS_IN = 17,
FOCUS_OUT = 18,
FOCUS_MAX = 19,
RESIZE = 20,
RESIZE_MAX = 21,
BUTTON_PRESS = 22,
BUTTON_CLICK = 23,
BUTTON_MAX = 24,
CHANGE = 25,
CHANGE_MAX = 26,
SLIDER_CHANGE = 27,
SLIDER_CHANGE_END = 28,
LIST_ITEM_PRESS = 29,
LIST_ITEM_UP = 30,
LIST_ITEM_ROLL_OVER = 31,
LIST_ITEM_ROLL_OUT = 32,
LIST_ITEM_CLICK = 33,
LIST_ITEM_DOUBLE_CLICK = 34,
LIST_INDEX_CHANGE = 35,
LIST_FOCUS_CHANGE = 36,
LIST_ITEM_CANCEL = 37,
LIST_ITEM_PICKUP_START = 38,
LIST_ITEM_PICKUP_END = 39,
LIST_ITEM_EXCHANGE = 40,
LIST_TREE_EXPAND = 41,
LIST_MAX = 42,
DDL_LIST_OPEN = 43,
DDL_LIST_CLOSE = 44,
DD_DRAG_START = 45,
DD_DRAG_END = 46,
DD_DROP = 47,
DD_DROP_EXCHANGE = 48,
DD_DROP_NOTICE = 49,
DD_ROLL_OVER = 50,
DD_ROLL_OUT = 51,
DD_DROP_STAGE = 52,
DD_EXECUTE = 53,
ICON_TEXT_ROLL_OVER = 54,
ICON_TEXT_ROLL_OUT = 55,
ICON_TEXT_CLICK = 56,
DIALOGUE_CLOSE = 57,
DIALOGUE_SUBMIT = 58,
TIMER = 59,
TIMER_COMPLETE = 60,
SIMPLETWEEN_UPDATE = 61,
SIMPLETWEEN_COMPLETE = 62,
SETUP_ADDON = 63,
UNIT_BASE_OVER = 64,
UNIT_BASE_OUT = 65,
UNIT_SCALE_CHANEGED = 66,
UNIT_RESOLUTION_SCALE_CHANEGED = 67,
TIMELINE_STATECHANGE = 68,
WORDLINK_CLICK = 69,
WORDLINK_ROLL_OVER = 70,
WORDLINK_ROLL_OUT = 71,
CHANGE_TEXT = 72,
COMPONENT_IN = 73,
COMPONENT_OUT = 74,
COMPONENT_SCROLL = 75,
COMPONENT_FOCUSED = 76, // Maybe
}
}
Loading

0 comments on commit 1dba386

Please sign in to comment.