All 5 phases of the open-source Decal rebuild: Phase 1: 14 decompiled .NET projects (Interop.*, Adapter, FileService, DecalUtil) Phase 2: 10 native DLLs rewritten as C# COM servers with matching GUIDs - DecalDat, DHS, SpellFilter, DecalInput, DecalNet, DecalFilters - Decal.Core, DecalControls, DecalRender, D3DService Phase 3: C++ shims for Inject.DLL (D3D9 hooking) and LauncherHook.DLL Phase 4: DenAgent WinForms tray application Phase 5: WiX installer and build script 25 C# projects building with 0 errors. Native C++ projects require VS 2022 + Windows SDK (x86). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
540 lines
12 KiB
C#
540 lines
12 KiB
C#
using System;
|
|
using System.ComponentModel;
|
|
using System.Drawing;
|
|
using System.Reflection;
|
|
using System.Runtime.InteropServices;
|
|
using Decal.Interop.Core;
|
|
|
|
namespace Decal.Adapter.Wrappers;
|
|
|
|
[CLSCompliant(true)]
|
|
public sealed class HooksWrapper : MarshalByRefObject, IIndexedValueProvider, IDisposable
|
|
{
|
|
private IACHooks myHooks;
|
|
|
|
private bool isDisposed;
|
|
|
|
[CLSCompliant(false)]
|
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
|
public IACHooks Underlying => myHooks;
|
|
|
|
public int BusyState => myHooks.BusyState;
|
|
|
|
public int BusyStateId => myHooks.BusyStateID;
|
|
|
|
public bool ChatState => myHooks.ChatState;
|
|
|
|
public CombatState CombatMode => (CombatState)myHooks.CombatMode;
|
|
|
|
public int CommandInterpreter => myHooks.CommandInterpreter;
|
|
|
|
public int CurrentSelection
|
|
{
|
|
get
|
|
{
|
|
return myHooks.CurrentSelection;
|
|
}
|
|
set
|
|
{
|
|
myHooks.CurrentSelection = value;
|
|
}
|
|
}
|
|
|
|
public double Heading
|
|
{
|
|
get
|
|
{
|
|
return myHooks.HeadingDegrees;
|
|
}
|
|
set
|
|
{
|
|
FaceHeading(value, bUnknown: true);
|
|
}
|
|
}
|
|
|
|
public double HeadingRadians
|
|
{
|
|
get
|
|
{
|
|
return myHooks.HeadingRadians;
|
|
}
|
|
set
|
|
{
|
|
RadianFaceHeading(value, bUnknown: true);
|
|
}
|
|
}
|
|
|
|
public int Landcell => myHooks.Landcell;
|
|
|
|
public double LocationX => myHooks.LocationX;
|
|
|
|
public double LocationY => myHooks.LocationY;
|
|
|
|
public double LocationZ => myHooks.LocationZ;
|
|
|
|
public int MaxSelectedStackCount => myHooks.MaxSelectedStackCount;
|
|
|
|
public int OpenedContainer => myHooks.OpenedContainer;
|
|
|
|
public int PointerState => myHooks.PointerState;
|
|
|
|
public int PreviousSelection
|
|
{
|
|
get
|
|
{
|
|
return myHooks.PreviousSelection;
|
|
}
|
|
set
|
|
{
|
|
myHooks.PreviousSelection = value;
|
|
}
|
|
}
|
|
|
|
public Rectangle Region3D
|
|
{
|
|
get
|
|
{
|
|
tagRECT aC3DRegionRect = myHooks.AC3DRegionRect;
|
|
return new Rectangle(aC3DRegionRect.left, aC3DRegionRect.top, aC3DRegionRect.right, aC3DRegionRect.bottom);
|
|
}
|
|
}
|
|
|
|
public Rectangle RegionWindow
|
|
{
|
|
get
|
|
{
|
|
tagRECT aCWindowRect = myHooks.ACWindowRect;
|
|
return new Rectangle(aCWindowRect.left, aCWindowRect.top, aCWindowRect.right, aCWindowRect.bottom);
|
|
}
|
|
}
|
|
|
|
public int SelectedStackCount
|
|
{
|
|
get
|
|
{
|
|
return myHooks.SelectedStackCount;
|
|
}
|
|
set
|
|
{
|
|
myHooks.SelectedStackCount = value;
|
|
}
|
|
}
|
|
|
|
public int VendorId => myHooks.VendorID;
|
|
|
|
[CLSCompliant(false)]
|
|
public HookIndexer<AttributeType> Attribute => new HookIndexer<AttributeType>(this, hookIndexType.Attribute);
|
|
|
|
[CLSCompliant(false)]
|
|
public HookIndexer<AttributeType> AttributeClicks => new HookIndexer<AttributeType>(this, hookIndexType.AttributeClicks);
|
|
|
|
[CLSCompliant(false)]
|
|
public HookIndexer<AttributeType> AttributeStart => new HookIndexer<AttributeType>(this, hookIndexType.AttributeStart);
|
|
|
|
[CLSCompliant(false)]
|
|
public HookIndexer<AttributeType> AttributeTotalXP => new HookIndexer<AttributeType>(this, hookIndexType.AttributeTotalXP);
|
|
|
|
[CLSCompliant(false)]
|
|
public HookIndexer<int> Misc => new HookIndexer<int>(this, hookIndexType.Misc);
|
|
|
|
[CLSCompliant(false)]
|
|
public HookIndexer<SkillType> Skill => new HookIndexer<SkillType>(this, hookIndexType.Skill);
|
|
|
|
[CLSCompliant(false)]
|
|
public HookIndexer<SkillType> SkillClicks => new HookIndexer<SkillType>(this, hookIndexType.SkillClicks);
|
|
|
|
[CLSCompliant(false)]
|
|
public HookIndexer<SkillType> SkillFreePoints => new HookIndexer<SkillType>(this, hookIndexType.SkillFreePoints);
|
|
|
|
[CLSCompliant(false)]
|
|
public HookIndexer<SkillType> SkillTotalXP => new HookIndexer<SkillType>(this, hookIndexType.SkillTotalXP);
|
|
|
|
[CLSCompliant(false)]
|
|
public HookIndexer<SkillType> SkillTrainLevel => new HookIndexer<SkillType>(this, hookIndexType.SkillTrainLevel);
|
|
|
|
[CLSCompliant(false)]
|
|
public HookIndexer<VitalType> Vital => new HookIndexer<VitalType>(this, hookIndexType.Vital);
|
|
|
|
[CLSCompliant(false)]
|
|
public HookIndexer<VitalType> VitalClicks => new HookIndexer<VitalType>(this, hookIndexType.VitalClicks);
|
|
|
|
[CLSCompliant(false)]
|
|
public HookIndexer<VitalType> VitalTotalXP => new HookIndexer<VitalType>(this, hookIndexType.VitalTotalXP);
|
|
|
|
internal HooksWrapper(ACHooks hooks)
|
|
{
|
|
myHooks = hooks;
|
|
}
|
|
|
|
~HooksWrapper()
|
|
{
|
|
Dispose(disposing: false);
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
Dispose(disposing: true);
|
|
GC.SuppressFinalize(this);
|
|
}
|
|
|
|
private void Dispose(bool disposing)
|
|
{
|
|
if (!isDisposed)
|
|
{
|
|
}
|
|
if (myHooks != null)
|
|
{
|
|
Marshal.ReleaseComObject(myHooks);
|
|
myHooks = null;
|
|
}
|
|
isDisposed = true;
|
|
}
|
|
|
|
public void AddChatText(string text, int color)
|
|
{
|
|
AddChatText(text, color, 0);
|
|
}
|
|
|
|
public void AddChatText(string text, int color, int target)
|
|
{
|
|
myHooks.AddChatText(text, color, target);
|
|
}
|
|
|
|
public void AddChatTextRaw(string text, int color)
|
|
{
|
|
AddChatTextRaw(text, color, 0);
|
|
}
|
|
|
|
public void AddChatTextRaw(string text, int color, int target)
|
|
{
|
|
myHooks.AddChatTextRaw(text, color, target);
|
|
}
|
|
|
|
public void AddStatusText(string text)
|
|
{
|
|
myHooks.AddStatusText(text);
|
|
}
|
|
|
|
public void ApplyItem(int useThis, int onThis)
|
|
{
|
|
myHooks.ApplyItem(useThis, onThis);
|
|
}
|
|
|
|
public void AutoWield(int item)
|
|
{
|
|
myHooks.AutoWield(item);
|
|
}
|
|
|
|
public void AutoWield(int item, int slot, int explic, int notexplic)
|
|
{
|
|
myHooks.AutoWieldEx(item, slot, explic, notexplic);
|
|
}
|
|
|
|
public void AutoWield(int item, int slot, int explic, int notexplic, int zero1, int zero2)
|
|
{
|
|
myHooks.AutoWieldRaw(item, slot, explic, notexplic, zero1, zero2);
|
|
}
|
|
|
|
public void CastSpell(int spellId, int objectId)
|
|
{
|
|
myHooks.CastSpell(spellId, objectId);
|
|
}
|
|
|
|
public void DropItem(int objectId)
|
|
{
|
|
myHooks.DropItem(objectId);
|
|
}
|
|
|
|
public bool FaceHeading(double heading, bool bUnknown)
|
|
{
|
|
return myHooks.FaceHeading((float)heading, bUnknown);
|
|
}
|
|
|
|
public bool RadianFaceHeading(double heading, bool bUnknown)
|
|
{
|
|
if (heading < 0.0)
|
|
{
|
|
throw new ArgumentOutOfRangeException("heading");
|
|
}
|
|
if (heading > Math.PI * 10.0)
|
|
{
|
|
throw new ArgumentOutOfRangeException("heading");
|
|
}
|
|
double num = heading * 180.0 / Math.PI;
|
|
return myHooks.FaceHeading((float)num, bUnknown);
|
|
}
|
|
|
|
public void FellowshipRecruit(int lObjectID)
|
|
{
|
|
myHooks.FellowshipRecruit(lObjectID);
|
|
}
|
|
|
|
public void FellowshipGrantLeader(int lObjectID)
|
|
{
|
|
myHooks.FellowshipGrantLeader(lObjectID);
|
|
}
|
|
|
|
public void FellowshipSetOpen(bool IsOpen)
|
|
{
|
|
myHooks.FellowshipSetOpen(IsOpen);
|
|
}
|
|
|
|
public void FellowshipQuit()
|
|
{
|
|
myHooks.FellowshipQuit();
|
|
}
|
|
|
|
public void FellowshipDisband()
|
|
{
|
|
myHooks.FellowshipDisband();
|
|
}
|
|
|
|
public void FellowshipDismiss(int lObjectID)
|
|
{
|
|
myHooks.FellowshipDismiss(lObjectID);
|
|
}
|
|
|
|
public void GiveItem(int lObject, int lDestination)
|
|
{
|
|
myHooks.GiveItem(lObject, lDestination);
|
|
}
|
|
|
|
public void RequestId(int objectId)
|
|
{
|
|
CoreManager.Current.IDQueue.AddToQueueForCaller(objectId, Assembly.GetCallingAssembly(), DateTime.MaxValue);
|
|
}
|
|
|
|
public void InvokeChatParser(string text)
|
|
{
|
|
myHooks.InvokeChatParser(text);
|
|
}
|
|
|
|
public bool IsValidObject(int objectId)
|
|
{
|
|
return myHooks.IsValidObject(objectId);
|
|
}
|
|
|
|
public void Logout()
|
|
{
|
|
myHooks.Logout();
|
|
}
|
|
|
|
public void MoveItem(int objectId, int packId, int slot, bool stack)
|
|
{
|
|
myHooks.MoveItem(objectId, packId, slot, stack);
|
|
}
|
|
|
|
public void MoveItem(int objectId, int destinationId)
|
|
{
|
|
myHooks.MoveItemEx(objectId, destinationId);
|
|
}
|
|
|
|
public void MoveItem(int objectId, int destinationId, int moveFlags)
|
|
{
|
|
myHooks.MoveItemExRaw(objectId, destinationId, moveFlags);
|
|
}
|
|
|
|
public void SalvagePanelAdd(int objectId)
|
|
{
|
|
myHooks.SalvagePanelAdd(objectId);
|
|
}
|
|
|
|
public void SalvagePanelSalvage()
|
|
{
|
|
myHooks.SalvagePanelSalvage();
|
|
}
|
|
|
|
public void SelectItem(int objectId)
|
|
{
|
|
myHooks.SelectItem(objectId);
|
|
}
|
|
|
|
public void SetAutorun(bool on)
|
|
{
|
|
myHooks.SetAutorun(on);
|
|
}
|
|
|
|
public void SetCombatMode(CombatState newMode)
|
|
{
|
|
myHooks.SetCombatMode((int)newMode);
|
|
}
|
|
|
|
public void SetCursorPosition(int x, int y)
|
|
{
|
|
myHooks.SetCursorPosition(x, y);
|
|
}
|
|
|
|
public void SetIdleTime(double timeout)
|
|
{
|
|
myHooks.SetIdleTime(timeout);
|
|
}
|
|
|
|
public void SpellTabAdd(int tab, int index, int spellId)
|
|
{
|
|
myHooks.SpellTabAdd(tab, index, spellId);
|
|
}
|
|
|
|
public void SpellTabDelete(int tab, int spellId)
|
|
{
|
|
myHooks.SpellTabDelete(tab, spellId);
|
|
}
|
|
|
|
public void TradeAccept()
|
|
{
|
|
myHooks.TradeAccept();
|
|
}
|
|
|
|
public void TradeAdd(int objectId)
|
|
{
|
|
myHooks.TradeAdd(objectId);
|
|
}
|
|
|
|
public IntPtr PhysicsObject(int objectId)
|
|
{
|
|
return new IntPtr(myHooks.GetPhysicsObjectPtr(objectId));
|
|
}
|
|
|
|
public IntPtr WeenieObject(int objectId)
|
|
{
|
|
return new IntPtr(myHooks.GetWeenieObjectPtr(objectId));
|
|
}
|
|
|
|
public void TradeDecline()
|
|
{
|
|
myHooks.TradeDecline();
|
|
}
|
|
|
|
public void TradeReset()
|
|
{
|
|
myHooks.TradeReset();
|
|
}
|
|
|
|
public void TradeEnd()
|
|
{
|
|
myHooks.TradeEnd();
|
|
}
|
|
|
|
public IntPtr UIElementLookup(UIElementType pUIElementType)
|
|
{
|
|
return new IntPtr(myHooks.UIElementLookup((int)pUIElementType));
|
|
}
|
|
|
|
public void UIElementMove(UIElementType pUIElementType, int x, int y)
|
|
{
|
|
myHooks.UIElementMove((int)pUIElementType, x, y);
|
|
}
|
|
|
|
public void UIElementResize(UIElementType pUIElementType, int width, int height)
|
|
{
|
|
myHooks.UIElementResize((int)pUIElementType, width, height);
|
|
}
|
|
|
|
public Rectangle UIElementRegion(UIElementType pUIElementType)
|
|
{
|
|
tagRECT tagRECT = myHooks.UIElementRegionRect((int)pUIElementType);
|
|
return new Rectangle(tagRECT.left, tagRECT.top, 1 + tagRECT.right - tagRECT.left, 1 + tagRECT.bottom - tagRECT.top);
|
|
}
|
|
|
|
public void UseItem(int objectId, int useState)
|
|
{
|
|
myHooks.UseItem(objectId, useState);
|
|
}
|
|
|
|
public void UseItem(int objectId, int useState, int useMethod)
|
|
{
|
|
myHooks.UseItemRaw(objectId, useState, useMethod);
|
|
}
|
|
|
|
public void VendorBuyAll()
|
|
{
|
|
myHooks.VendorBuyAll();
|
|
}
|
|
|
|
public void VendorAddBuyList(int templateId, int count)
|
|
{
|
|
myHooks.VendorBuyListAdd(templateId, count);
|
|
}
|
|
|
|
public void VendorClearBuyList()
|
|
{
|
|
myHooks.VendorBuyListClear();
|
|
}
|
|
|
|
public void VendorSellAll()
|
|
{
|
|
myHooks.VendorSellAll();
|
|
}
|
|
|
|
public void VendorAddSellList(int itemId)
|
|
{
|
|
myHooks.VendorSellListAdd(itemId);
|
|
}
|
|
|
|
public void VendorClearSellList()
|
|
{
|
|
myHooks.VendorSellListClear();
|
|
}
|
|
|
|
public void AddSkillExperience(SkillType skill, int experience)
|
|
{
|
|
myHooks.AddSkillExp((eSkill)skill, experience);
|
|
}
|
|
|
|
public void AddAttributeExperience(AttributeType attrib, int experience)
|
|
{
|
|
myHooks.AddAttributeExp((eAttribute)attrib, experience);
|
|
}
|
|
|
|
public void AddVitalExperience(VitalType vital, int experience)
|
|
{
|
|
myHooks.AddVitalExp((eVital)vital, experience);
|
|
}
|
|
|
|
int IIndexedValueProvider.GetIndexedObject(hookIndexType index, int item)
|
|
{
|
|
int result = 0;
|
|
switch (index)
|
|
{
|
|
case hookIndexType.Attribute:
|
|
result = ((dynamic)myHooks).get_Attribute(item);
|
|
break;
|
|
case hookIndexType.AttributeClicks:
|
|
result = ((dynamic)myHooks).get_AttributeClicks((eAttribute)item);
|
|
break;
|
|
case hookIndexType.AttributeStart:
|
|
result = ((dynamic)myHooks).get_AttributeStart((eAttribute)item);
|
|
break;
|
|
case hookIndexType.AttributeTotalXP:
|
|
result = ((dynamic)myHooks).get_AttributeTotalXP((eAttribute)item);
|
|
break;
|
|
case hookIndexType.Skill:
|
|
result = ((dynamic)myHooks).get_Skill(item);
|
|
break;
|
|
case hookIndexType.SkillClicks:
|
|
result = ((dynamic)myHooks).get_SkillClicks((eSkill)item);
|
|
break;
|
|
case hookIndexType.SkillFreePoints:
|
|
result = ((dynamic)myHooks).get_SkillFreePoints((eSkill)item);
|
|
break;
|
|
case hookIndexType.SkillTotalXP:
|
|
result = ((dynamic)myHooks).get_SkillTotalXP((eSkill)item);
|
|
break;
|
|
case hookIndexType.SkillTrainLevel:
|
|
result = (int)((dynamic)myHooks).get_SkillTrainLevel((eSkill)item);
|
|
break;
|
|
case hookIndexType.Vital:
|
|
result = ((dynamic)myHooks).get_Vital(item);
|
|
break;
|
|
case hookIndexType.VitalClicks:
|
|
result = ((dynamic)myHooks).get_VitalClicks((eVital)item);
|
|
break;
|
|
case hookIndexType.VitalTotalXP:
|
|
result = ((dynamic)myHooks).get_VitalTotalXP((eVital)item);
|
|
break;
|
|
case hookIndexType.Misc:
|
|
result = ((dynamic)myHooks).get_Misc(item);
|
|
break;
|
|
}
|
|
return result;
|
|
}
|
|
}
|