987 lines
26 KiB
C#
987 lines
26 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Collections.ObjectModel;
|
|
using System.IO;
|
|
using System.Reflection;
|
|
using System.Runtime.InteropServices;
|
|
using System.Threading;
|
|
using Decal.Adapter.IDQueue;
|
|
using Decal.Adapter.Messages;
|
|
using Decal.Adapter.Support;
|
|
using Decal.Adapter.Wrappers;
|
|
using Decal.Interop.Core;
|
|
using Decal.Interop.D3DService;
|
|
using Decal.Interop.DHS;
|
|
using Decal.Interop.Filters;
|
|
using Decal.Interop.Inject;
|
|
using Decal.Interop.Render;
|
|
using Microsoft.Win32;
|
|
|
|
namespace Decal.Adapter;
|
|
|
|
/// <summary>
|
|
/// Lifetime Service required for the .NET Surrogate to function.
|
|
/// </summary>
|
|
[CLSCompliant(true)]
|
|
public sealed class CoreManager : MarshalByRefObject
|
|
{
|
|
private struct sAssemblyPreloadData
|
|
{
|
|
public string AssemblyName;
|
|
|
|
public string Path;
|
|
}
|
|
|
|
private static bool myServiceRunning;
|
|
|
|
private static CoreManager myService;
|
|
|
|
private DecalCoreClass myDecal;
|
|
|
|
private ACHooksClass myHooks;
|
|
|
|
private PluginSite mySitev1;
|
|
|
|
private DecalWrapper myWrappedDecal;
|
|
|
|
private HooksWrapper myWrappedHooks;
|
|
|
|
private global::Decal.Adapter.Wrappers.HotkeySystem myDHS;
|
|
|
|
private CharacterFilter myCharacterFilter;
|
|
|
|
private WorldFilter myWorldFilter;
|
|
|
|
private global::Decal.Adapter.Wrappers.EchoFilter2 myEchoFilter;
|
|
|
|
private D3DService myD3DService;
|
|
|
|
private RenderServiceWrapper myRenderService;
|
|
|
|
private FairIDQueue myIDQueue;
|
|
|
|
private Collection<string> myPaths = new Collection<string>();
|
|
|
|
private Dictionary<AppDomain, Dictionary<string, Assembly>> myAssemblies = new Dictionary<AppDomain, Dictionary<string, Assembly>>();
|
|
|
|
private int myAssemblyPreloadCounter = 1;
|
|
|
|
private bool myAssemblyPreloadStarted;
|
|
|
|
private Dictionary<Type, FilterBase> myFilters = new Dictionary<Type, FilterBase>();
|
|
|
|
private Dictionary<string, FilterBase> myNamedFilters = new Dictionary<string, FilterBase>();
|
|
|
|
private Dictionary<Type, ServiceBase> myServices = new Dictionary<Type, ServiceBase>();
|
|
|
|
private Dictionary<string, ServiceBase> myNamedServices = new Dictionary<string, ServiceBase>();
|
|
|
|
private Dictionary<string, PluginBase> myPlugins = new Dictionary<string, PluginBase>();
|
|
|
|
private EventHandler<ItemSelectedEventArgs> myItemSelected;
|
|
|
|
private EventHandler<ItemDestroyedEventArgs> myItemDestroyed;
|
|
|
|
private EventHandler<ChatParserInterceptEventArgs> myChatParserIntercept;
|
|
|
|
private EventHandler<RegionChange3DEventArgs> myRegionChange3D;
|
|
|
|
private EventHandler<ChatTextInterceptEventArgs> myChatTextIntercept;
|
|
|
|
private EventHandler<StatusTextInterceptEventArgs> myStatusTextIntercept;
|
|
|
|
private EventHandler<MessageProcessedEventArgs> myMessageProcessed;
|
|
|
|
private EventHandler<ContainerOpenedEventArgs> myContainerOpened;
|
|
|
|
private EventHandler<ChatClickInterceptEventArgs> myChatClickIntercept;
|
|
|
|
private EventHandler<WindowMessageEventArgs> myWindowMessage;
|
|
|
|
private EventHandler<EventArgs> myFilterInitComplete;
|
|
|
|
private EventHandler<EventArgs> myServiceInitComplete;
|
|
|
|
private EventHandler<EventArgs> myPluginInitComplete;
|
|
|
|
private EventHandler<EventArgs> myFilterTermComplete;
|
|
|
|
private EventHandler<EventArgs> myServiceTermComplete;
|
|
|
|
private EventHandler<EventArgs> myPluginTermComplete;
|
|
|
|
private EventHandler<EventArgs> myRender_PreUI;
|
|
|
|
private EventHandler<AdapterMessageEventArgs> myExtensionMessage;
|
|
|
|
private AppDomain myPluginDomain;
|
|
|
|
private AppDomain myDomain;
|
|
|
|
/// <summary>
|
|
/// Returns if the service was initialized by Decal.
|
|
/// </summary>
|
|
public static bool ServiceRunning => myServiceRunning;
|
|
|
|
/// <summary>
|
|
/// Returns the Singleton instance of the Service
|
|
/// (Initializes if necessary)
|
|
/// </summary>
|
|
public static CoreManager Current
|
|
{
|
|
get
|
|
{
|
|
if (myService == null)
|
|
{
|
|
myService = new CoreManager();
|
|
}
|
|
return myService;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Tracing level for Decal.Adapter, and all loaded plugins.
|
|
/// </summary>
|
|
public static int TracingLevel => Util.TraceLevel;
|
|
|
|
/// <summary>
|
|
/// FileService (Decal.FileService)
|
|
/// </summary>
|
|
public FilterBase FileService => Filter("Decal.FileService");
|
|
|
|
/// <summary>
|
|
/// Decal Hotkey System
|
|
/// </summary>
|
|
public global::Decal.Adapter.Wrappers.HotkeySystem HotkeySystem => myDHS;
|
|
|
|
/// <summary>
|
|
/// Character Filter
|
|
/// </summary>
|
|
[CLSCompliant(false)]
|
|
public CharacterFilter CharacterFilter => myCharacterFilter;
|
|
|
|
[CLSCompliant(false)]
|
|
public WorldFilter WorldFilter => myWorldFilter;
|
|
|
|
/// <summary>
|
|
/// Direct3D Service
|
|
/// </summary>
|
|
[CLSCompliant(false)]
|
|
public global::Decal.Adapter.Wrappers.EchoFilter2 EchoFilter => myEchoFilter;
|
|
|
|
[CLSCompliant(false)]
|
|
public D3DService D3DService => myD3DService;
|
|
|
|
[CLSCompliant(false)]
|
|
public HooksWrapper Actions => myWrappedHooks;
|
|
|
|
[CLSCompliant(false)]
|
|
public DecalWrapper Decal => myWrappedDecal;
|
|
|
|
public RenderServiceWrapper RenderService => myRenderService;
|
|
|
|
public FairIDQueue IDQueue => myIDQueue;
|
|
|
|
internal AppDomain PluginDomain => myDomain;
|
|
|
|
[CLSCompliant(false)]
|
|
public event EventHandler<ItemSelectedEventArgs> ItemSelected
|
|
{
|
|
add
|
|
{
|
|
myItemSelected = (EventHandler<ItemSelectedEventArgs>)Delegate.Combine(myItemSelected, value);
|
|
}
|
|
remove
|
|
{
|
|
myItemSelected = (EventHandler<ItemSelectedEventArgs>)Delegate.Remove(myItemSelected, value);
|
|
}
|
|
}
|
|
|
|
[CLSCompliant(false)]
|
|
public event EventHandler<ItemDestroyedEventArgs> ItemDestroyed
|
|
{
|
|
add
|
|
{
|
|
myItemDestroyed = (EventHandler<ItemDestroyedEventArgs>)Delegate.Combine(myItemDestroyed, value);
|
|
}
|
|
remove
|
|
{
|
|
myItemDestroyed = (EventHandler<ItemDestroyedEventArgs>)Delegate.Remove(myItemDestroyed, value);
|
|
}
|
|
}
|
|
|
|
[CLSCompliant(false)]
|
|
public event EventHandler<ChatParserInterceptEventArgs> CommandLineText
|
|
{
|
|
add
|
|
{
|
|
myChatParserIntercept = (EventHandler<ChatParserInterceptEventArgs>)Delegate.Combine(myChatParserIntercept, value);
|
|
}
|
|
remove
|
|
{
|
|
myChatParserIntercept = (EventHandler<ChatParserInterceptEventArgs>)Delegate.Remove(myChatParserIntercept, value);
|
|
}
|
|
}
|
|
|
|
[CLSCompliant(false)]
|
|
public event EventHandler<StatusTextInterceptEventArgs> StatusBoxMessage
|
|
{
|
|
add
|
|
{
|
|
myStatusTextIntercept = (EventHandler<StatusTextInterceptEventArgs>)Delegate.Combine(myStatusTextIntercept, value);
|
|
}
|
|
remove
|
|
{
|
|
myStatusTextIntercept = (EventHandler<StatusTextInterceptEventArgs>)Delegate.Remove(myStatusTextIntercept, value);
|
|
}
|
|
}
|
|
|
|
[CLSCompliant(false)]
|
|
public event EventHandler<RegionChange3DEventArgs> RegionChange3D
|
|
{
|
|
add
|
|
{
|
|
myRegionChange3D = (EventHandler<RegionChange3DEventArgs>)Delegate.Combine(myRegionChange3D, value);
|
|
}
|
|
remove
|
|
{
|
|
myRegionChange3D = (EventHandler<RegionChange3DEventArgs>)Delegate.Remove(myRegionChange3D, value);
|
|
}
|
|
}
|
|
|
|
[CLSCompliant(false)]
|
|
public event EventHandler<ChatTextInterceptEventArgs> ChatBoxMessage
|
|
{
|
|
add
|
|
{
|
|
myChatTextIntercept = (EventHandler<ChatTextInterceptEventArgs>)Delegate.Combine(myChatTextIntercept, value);
|
|
}
|
|
remove
|
|
{
|
|
myChatTextIntercept = (EventHandler<ChatTextInterceptEventArgs>)Delegate.Remove(myChatTextIntercept, value);
|
|
}
|
|
}
|
|
|
|
[CLSCompliant(false)]
|
|
public event EventHandler<MessageProcessedEventArgs> MessageProcessed
|
|
{
|
|
add
|
|
{
|
|
myMessageProcessed = (EventHandler<MessageProcessedEventArgs>)Delegate.Combine(myMessageProcessed, value);
|
|
}
|
|
remove
|
|
{
|
|
myMessageProcessed = (EventHandler<MessageProcessedEventArgs>)Delegate.Remove(myMessageProcessed, value);
|
|
}
|
|
}
|
|
|
|
[CLSCompliant(false)]
|
|
public event EventHandler<ContainerOpenedEventArgs> ContainerOpened
|
|
{
|
|
add
|
|
{
|
|
myContainerOpened = (EventHandler<ContainerOpenedEventArgs>)Delegate.Combine(myContainerOpened, value);
|
|
}
|
|
remove
|
|
{
|
|
myContainerOpened = (EventHandler<ContainerOpenedEventArgs>)Delegate.Remove(myContainerOpened, value);
|
|
}
|
|
}
|
|
|
|
[CLSCompliant(false)]
|
|
public event EventHandler<ChatClickInterceptEventArgs> ChatNameClicked
|
|
{
|
|
add
|
|
{
|
|
myChatClickIntercept = (EventHandler<ChatClickInterceptEventArgs>)Delegate.Combine(myChatClickIntercept, value);
|
|
}
|
|
remove
|
|
{
|
|
myChatClickIntercept = (EventHandler<ChatClickInterceptEventArgs>)Delegate.Remove(myChatClickIntercept, value);
|
|
}
|
|
}
|
|
|
|
public event EventHandler<EventArgs> FilterInitComplete
|
|
{
|
|
add
|
|
{
|
|
myFilterInitComplete = (EventHandler<EventArgs>)Delegate.Combine(myFilterInitComplete, value);
|
|
}
|
|
remove
|
|
{
|
|
myFilterInitComplete = (EventHandler<EventArgs>)Delegate.Remove(myFilterInitComplete, value);
|
|
}
|
|
}
|
|
|
|
public event EventHandler<EventArgs> ServiceInitComplete
|
|
{
|
|
add
|
|
{
|
|
myServiceInitComplete = (EventHandler<EventArgs>)Delegate.Combine(myServiceInitComplete, value);
|
|
}
|
|
remove
|
|
{
|
|
myServiceInitComplete = (EventHandler<EventArgs>)Delegate.Remove(myServiceInitComplete, value);
|
|
}
|
|
}
|
|
|
|
public event EventHandler<EventArgs> PluginInitComplete
|
|
{
|
|
add
|
|
{
|
|
myPluginInitComplete = (EventHandler<EventArgs>)Delegate.Combine(myPluginInitComplete, value);
|
|
}
|
|
remove
|
|
{
|
|
myPluginInitComplete = (EventHandler<EventArgs>)Delegate.Remove(myPluginInitComplete, value);
|
|
}
|
|
}
|
|
|
|
public event EventHandler<EventArgs> FilterTermComplete
|
|
{
|
|
add
|
|
{
|
|
myFilterTermComplete = (EventHandler<EventArgs>)Delegate.Combine(myFilterTermComplete, value);
|
|
}
|
|
remove
|
|
{
|
|
myFilterTermComplete = (EventHandler<EventArgs>)Delegate.Remove(myFilterTermComplete, value);
|
|
}
|
|
}
|
|
|
|
public event EventHandler<EventArgs> ServiceTermComplete
|
|
{
|
|
add
|
|
{
|
|
myServiceTermComplete = (EventHandler<EventArgs>)Delegate.Combine(myServiceTermComplete, value);
|
|
}
|
|
remove
|
|
{
|
|
myServiceTermComplete = (EventHandler<EventArgs>)Delegate.Remove(myServiceTermComplete, value);
|
|
}
|
|
}
|
|
|
|
public event EventHandler<EventArgs> PluginTermComplete
|
|
{
|
|
add
|
|
{
|
|
myPluginTermComplete = (EventHandler<EventArgs>)Delegate.Combine(myPluginTermComplete, value);
|
|
}
|
|
remove
|
|
{
|
|
myPluginTermComplete = (EventHandler<EventArgs>)Delegate.Remove(myPluginTermComplete, value);
|
|
}
|
|
}
|
|
|
|
public event EventHandler<EventArgs> RenderFrame
|
|
{
|
|
add
|
|
{
|
|
myRender_PreUI = (EventHandler<EventArgs>)Delegate.Combine(myRender_PreUI, value);
|
|
}
|
|
remove
|
|
{
|
|
myRender_PreUI = (EventHandler<EventArgs>)Delegate.Remove(myRender_PreUI, value);
|
|
}
|
|
}
|
|
|
|
[CLSCompliant(false)]
|
|
public event EventHandler<WindowMessageEventArgs> WindowMessage
|
|
{
|
|
add
|
|
{
|
|
myWindowMessage = (EventHandler<WindowMessageEventArgs>)Delegate.Combine(myWindowMessage, value);
|
|
}
|
|
remove
|
|
{
|
|
myWindowMessage = (EventHandler<WindowMessageEventArgs>)Delegate.Remove(myWindowMessage, value);
|
|
}
|
|
}
|
|
|
|
internal event EventHandler<AdapterMessageEventArgs> ExtensionMessage
|
|
{
|
|
add
|
|
{
|
|
myExtensionMessage = (EventHandler<AdapterMessageEventArgs>)Delegate.Combine(myExtensionMessage, value);
|
|
}
|
|
remove
|
|
{
|
|
myExtensionMessage = (EventHandler<AdapterMessageEventArgs>)Delegate.Remove(myExtensionMessage, value);
|
|
}
|
|
}
|
|
|
|
private CoreManager()
|
|
{
|
|
AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
|
|
string location = System.Reflection.Assembly.GetExecutingAssembly().Location;
|
|
AddAssemblyPath(Path.GetDirectoryName(location));
|
|
myDomain = AppDomain.CurrentDomain;
|
|
Util.InitializeTracing("HKEY_LOCAL_MACHINE\\Software\\Decal\\Decal.Adapter", "Tracing", 0);
|
|
}
|
|
|
|
private Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
|
|
{
|
|
AppDomain appDomain = (AppDomain)sender;
|
|
Assembly[] assemblies = appDomain.GetAssemblies();
|
|
string text = appDomain.ApplyPolicy(args.Name);
|
|
if (string.IsNullOrEmpty(text))
|
|
{
|
|
text = args.Name;
|
|
}
|
|
Assembly[] array = assemblies;
|
|
foreach (Assembly assembly in array)
|
|
{
|
|
if (assembly.FullName == text)
|
|
{
|
|
return assembly;
|
|
}
|
|
}
|
|
if (!appDomain.IsDefaultAppDomain())
|
|
{
|
|
assemblies = myDomain.GetAssemblies();
|
|
array = assemblies;
|
|
foreach (Assembly assembly2 in array)
|
|
{
|
|
if (assembly2.FullName == text)
|
|
{
|
|
AssemblyName name = assembly2.GetName(copiedName: false);
|
|
return appDomain.Load(name);
|
|
}
|
|
}
|
|
}
|
|
string text2 = ((text.IndexOf(",") <= 0) ? text : text.Substring(0, text.IndexOf(",")));
|
|
if (!string.IsNullOrEmpty(text2))
|
|
{
|
|
text2 = text2.ToLowerInvariant();
|
|
if (string.IsNullOrEmpty(Path.GetExtension(text2)))
|
|
{
|
|
text2 += ".dll";
|
|
}
|
|
foreach (string myPath in myPaths)
|
|
{
|
|
if (File.Exists(Path.Combine(myPath, text2)))
|
|
{
|
|
AssemblyName assemblyName = new AssemblyName();
|
|
assemblyName.CodeBase = Path.Combine(myPath, text2);
|
|
return appDomain.Load(assemblyName);
|
|
}
|
|
}
|
|
}
|
|
Util.WriteLine("Assembly resolve failed for assembly:" + args.Name);
|
|
return null;
|
|
}
|
|
|
|
private void AddAssemblyPath(string path)
|
|
{
|
|
string item = path.ToLowerInvariant();
|
|
if (!myPaths.Contains(item))
|
|
{
|
|
myPaths.Add(item);
|
|
}
|
|
}
|
|
|
|
private void myDecal_InitializeComplete(eDecalComponentType myComponent)
|
|
{
|
|
Util.WriteLine("InitializeComplete for: " + myComponent);
|
|
switch (myComponent)
|
|
{
|
|
case eDecalComponentType.eService:
|
|
Message.Initialize(Path.Combine((string)Registry.GetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\Decal\\Agent", "AgentPath", ""), "messages.xml"));
|
|
if (myWrappedDecal != null)
|
|
{
|
|
try
|
|
{
|
|
if (myWrappedDecal.GetObject("services\\D3DService.Service") is CService obj)
|
|
{
|
|
myD3DService = new D3DService(obj);
|
|
}
|
|
if (myWrappedDecal.GetObject("services\\DecalRender.RenderService") is RenderService render)
|
|
{
|
|
myRenderService = new RenderServiceWrapper(render);
|
|
}
|
|
object obj2 = myWrappedDecal.GetObject("services\\DecalPlugins.InjectService\\site", DecalWrapper.IID_IUNKNOWN);
|
|
mySitev1 = obj2 as PluginSite;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Util.WriteLine("Unable to get service reference: " + ex.Message);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Util.WriteLine("Not getting services, we don't have a Decal object to call GetObject on.");
|
|
}
|
|
try
|
|
{
|
|
myIDQueue = new FairIDQueue();
|
|
}
|
|
catch (Exception ex2)
|
|
{
|
|
Util.WriteLine("Service initialization exception: " + ex2.Message);
|
|
}
|
|
Util.SafeFireEvent(this, myServiceInitComplete, new EventArgs());
|
|
break;
|
|
case eDecalComponentType.eNetworkFilter:
|
|
if (myWrappedDecal != null)
|
|
{
|
|
try
|
|
{
|
|
if (myWrappedDecal.GetObject("services\\DecalNet.NetService\\DecalFilters.World") is World obj3)
|
|
{
|
|
myWorldFilter = new WorldFilter(obj3);
|
|
}
|
|
if (myWrappedDecal.GetObject("services\\DecalNet.NetService\\DecalFilters.CharacterStats") is CharacterStats obj4)
|
|
{
|
|
myCharacterFilter = new CharacterFilter(obj4);
|
|
}
|
|
if (myWrappedDecal.GetObject("services\\DecalNet.NetService\\DecalFilters.EchoFilter2") is global::Decal.Interop.Filters.EchoFilter2 obj5)
|
|
{
|
|
myEchoFilter = new global::Decal.Adapter.Wrappers.EchoFilter2(obj5);
|
|
}
|
|
}
|
|
catch (Exception ex3)
|
|
{
|
|
Util.WriteLine("Unable to get filter reference: " + ex3.Message);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Util.WriteLine("Not getting filters, we don't have a Decal object to call GetObject on.");
|
|
}
|
|
Util.SafeFireEvent(this, myFilterInitComplete, new EventArgs());
|
|
DecrementAssemblyPreloadLockCounter();
|
|
break;
|
|
case eDecalComponentType.ePlugin:
|
|
if (myWrappedDecal.GetObject("plugins\\DHS.HotkeySystem") is global::Decal.Interop.DHS.HotkeySystem hks)
|
|
{
|
|
myDHS = new global::Decal.Adapter.Wrappers.HotkeySystem(hks);
|
|
}
|
|
myIDQueue.Start();
|
|
Util.SafeFireEvent(this, myPluginInitComplete, new EventArgs());
|
|
break;
|
|
}
|
|
}
|
|
|
|
private void myDecal_TerminateComplete(eDecalComponentType myComponent)
|
|
{
|
|
Util.WriteLine("TerminateComplete for: " + myComponent);
|
|
switch (myComponent)
|
|
{
|
|
case eDecalComponentType.eService:
|
|
if (myD3DService != null)
|
|
{
|
|
myD3DService.Dispose();
|
|
myD3DService = null;
|
|
}
|
|
if (myRenderService != null)
|
|
{
|
|
myRenderService.Dispose();
|
|
myRenderService = null;
|
|
}
|
|
if (mySitev1 != null)
|
|
{
|
|
Marshal.ReleaseComObject(mySitev1);
|
|
}
|
|
myServices.Clear();
|
|
myNamedServices.Clear();
|
|
Util.SafeFireEvent(this, myServiceTermComplete, new EventArgs());
|
|
break;
|
|
case eDecalComponentType.eNetworkFilter:
|
|
if (myWorldFilter != null)
|
|
{
|
|
myWorldFilter.Dispose();
|
|
myWorldFilter = null;
|
|
}
|
|
if (myCharacterFilter != null)
|
|
{
|
|
myCharacterFilter.Dispose();
|
|
myCharacterFilter = null;
|
|
}
|
|
if (myEchoFilter != null)
|
|
{
|
|
myEchoFilter.Dispose();
|
|
myEchoFilter = null;
|
|
}
|
|
myFilters.Clear();
|
|
myNamedFilters.Clear();
|
|
Util.SafeFireEvent(this, myFilterTermComplete, new EventArgs());
|
|
break;
|
|
case eDecalComponentType.ePlugin:
|
|
myIDQueue.Stop();
|
|
if (myDHS != null)
|
|
{
|
|
myDHS.Dispose();
|
|
myDHS = null;
|
|
}
|
|
myPlugins.Clear();
|
|
if (myPluginDomain != null)
|
|
{
|
|
lock (myAssemblies)
|
|
{
|
|
if (myAssemblies.ContainsKey(myPluginDomain))
|
|
{
|
|
myAssemblies[myPluginDomain].Clear();
|
|
myAssemblies.Remove(myPluginDomain);
|
|
}
|
|
AppDomain.Unload(myPluginDomain);
|
|
myPluginDomain = null;
|
|
}
|
|
}
|
|
Util.SafeFireEvent(this, myPluginTermComplete, new EventArgs());
|
|
break;
|
|
}
|
|
}
|
|
|
|
private void myHooks_ObjectSelected(int lGUID)
|
|
{
|
|
Util.SafeFireEvent(this, myItemSelected, new ItemSelectedEventArgs(lGUID));
|
|
}
|
|
|
|
private void myHooks_ObjectDestroyed(int lGUID)
|
|
{
|
|
Util.SafeFireEvent(this, myItemDestroyed, new ItemDestroyedEventArgs(lGUID));
|
|
}
|
|
|
|
private void myHooks_AC3DRegionChanged(int left, int top, int right, int bottom)
|
|
{
|
|
Util.SafeFireEvent(this, myRegionChange3D, new RegionChange3DEventArgs(left, top, right, bottom));
|
|
}
|
|
|
|
private void myHooks_ChatParserIntercept(string bstrText, ref bool bEat)
|
|
{
|
|
Util.SafeFireEvent(this, myChatParserIntercept, new ChatParserInterceptEventArgs(bstrText, bEat), ref bEat);
|
|
}
|
|
|
|
private void myHooks_StatusTextIntercept(string bstrText, ref bool bEat)
|
|
{
|
|
Util.SafeFireEvent(this, myStatusTextIntercept, new StatusTextInterceptEventArgs(bstrText, bEat), ref bEat);
|
|
}
|
|
|
|
private void myHooks_ChatTextIntercept(string bstrText, int lColor, int target, ref bool bEat)
|
|
{
|
|
Util.SafeFireEvent(this, myChatTextIntercept, new ChatTextInterceptEventArgs(bstrText, lColor, target, bEat), ref bEat);
|
|
}
|
|
|
|
private void myHooks_MessageProcessed(int pbData, int dwSize)
|
|
{
|
|
if (myMessageProcessed != null)
|
|
{
|
|
MessageProcessedEventArgs args = new MessageProcessedEventArgs(pbData, dwSize);
|
|
Util.SafeFireEvent(this, myMessageProcessed, args);
|
|
}
|
|
}
|
|
|
|
private void myHooks_ContainerOpened(int lGUID)
|
|
{
|
|
Util.SafeFireEvent(this, myContainerOpened, new ContainerOpenedEventArgs(lGUID));
|
|
}
|
|
|
|
private void myHooks_ChatClickIntercept(string bstrText, int id, ref bool bEat)
|
|
{
|
|
Util.SafeFireEvent(this, myChatClickIntercept, new ChatClickInterceptEventArgs(bstrText, id, bEat), ref bEat);
|
|
}
|
|
|
|
private void myHooks_RenderPreUI()
|
|
{
|
|
Util.SafeFireEvent(this, myRender_PreUI, new EventArgs());
|
|
}
|
|
|
|
internal bool FireWindowMessage(int HWND, short uMsg, int wParam, int lParam)
|
|
{
|
|
bool eaten = false;
|
|
WindowMessageEventArgs args = new WindowMessageEventArgs(HWND, uMsg, wParam, lParam);
|
|
Util.SafeFireEvent(this, myWindowMessage, args, ref eaten);
|
|
return eaten;
|
|
}
|
|
|
|
internal void FireExtensionMessage(object sender, AdapterMessageEventArgs args)
|
|
{
|
|
args.CanAddHandlers = true;
|
|
Util.SafeFireEvent(this, myExtensionMessage, args);
|
|
args.CanAddHandlers = false;
|
|
}
|
|
|
|
public FilterBase Filter(string filterName)
|
|
{
|
|
try
|
|
{
|
|
if (myNamedFilters.ContainsKey(filterName))
|
|
{
|
|
return myNamedFilters[filterName];
|
|
}
|
|
Type type = Type.GetType(filterName);
|
|
if (null != type && myFilters.ContainsKey(type))
|
|
{
|
|
return myFilters[type];
|
|
}
|
|
}
|
|
catch (Exception)
|
|
{
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public T Filter<T>() where T : FilterBase
|
|
{
|
|
try
|
|
{
|
|
if (myFilters.ContainsKey(typeof(T)))
|
|
{
|
|
return (T)myFilters[typeof(T)];
|
|
}
|
|
}
|
|
catch (Exception)
|
|
{
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public ServiceBase Service(string serviceName)
|
|
{
|
|
try
|
|
{
|
|
if (myNamedServices.ContainsKey(serviceName))
|
|
{
|
|
return myNamedServices[serviceName];
|
|
}
|
|
Type type = Type.GetType(serviceName);
|
|
if (null != type && myServices.ContainsKey(type))
|
|
{
|
|
return myServices[type];
|
|
}
|
|
}
|
|
catch (Exception)
|
|
{
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public T Service<T>() where T : ServiceBase
|
|
{
|
|
try
|
|
{
|
|
if (myServices.ContainsKey(typeof(T)))
|
|
{
|
|
return (T)myServices[typeof(T)];
|
|
}
|
|
}
|
|
catch (Exception)
|
|
{
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get Mapped Keyboard Key
|
|
/// </summary>
|
|
/// <param name="name">Name to retrive mapping for. </param>
|
|
/// <returns>Mapped Key</returns>
|
|
public int QueryKeyBoardMap(string name)
|
|
{
|
|
int result = 0;
|
|
if (mySitev1 != null)
|
|
{
|
|
result = mySitev1.QueryKeyboardMap(name);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
internal void AddFilter(FilterBase newFilter)
|
|
{
|
|
AddFilter(newFilter.ReferenceName, newFilter);
|
|
}
|
|
|
|
internal void AddFilter(string filterName, FilterBase newFilter)
|
|
{
|
|
myFilters.Add(newFilter.GetType(), newFilter);
|
|
myNamedFilters.Add(filterName, newFilter);
|
|
}
|
|
|
|
internal void AddService(ServiceBase newService)
|
|
{
|
|
AddService(newService.ReferenceName, newService);
|
|
}
|
|
|
|
internal void AddService(string serviceName, ServiceBase newService)
|
|
{
|
|
myServices.Add(newService.GetType(), newService);
|
|
myNamedServices.Add(serviceName, newService);
|
|
}
|
|
|
|
internal void AddPlugin(PluginBase newPlugin)
|
|
{
|
|
AddPlugin(newPlugin.ReferenceName, newPlugin);
|
|
}
|
|
|
|
internal void AddPlugin(string pluginName, PluginBase newPlugin)
|
|
{
|
|
myPlugins.Add(pluginName, newPlugin);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Load the Assembly requested, first checking our internal cache
|
|
/// </summary>
|
|
/// <param name="name">Assembly name to load</param>
|
|
/// <param name="path">Path to the assembly</param>
|
|
/// <returns>Loaded Assembly, from cache if already loaded</returns>
|
|
internal Assembly Assembly(string name, string path)
|
|
{
|
|
return Assembly(name, path, AppDomain.CurrentDomain);
|
|
}
|
|
|
|
internal Assembly Assembly(string name, string path, AppDomain useDomain)
|
|
{
|
|
lock (myAssemblies)
|
|
{
|
|
string text = name.ToLowerInvariant();
|
|
useDomain = myDomain;
|
|
Dictionary<string, Assembly> dictionary;
|
|
if (myAssemblies.ContainsKey(useDomain))
|
|
{
|
|
dictionary = myAssemblies[useDomain];
|
|
}
|
|
else
|
|
{
|
|
myAssemblies.Add(useDomain, new Dictionary<string, Assembly>());
|
|
dictionary = myAssemblies[useDomain];
|
|
}
|
|
if (dictionary.ContainsKey(text))
|
|
{
|
|
return dictionary[text];
|
|
}
|
|
AddAssemblyPath(path);
|
|
Assembly assembly = System.Reflection.Assembly.LoadFrom(Path.Combine(path, text));
|
|
dictionary.Add(text, assembly);
|
|
return assembly;
|
|
}
|
|
}
|
|
|
|
internal void Initialize(DecalCore pDecal)
|
|
{
|
|
Util.WriteLine("Decal.Adapter Lifetime-service Initialize Begun");
|
|
myServiceRunning = true;
|
|
Util.Write("Get Decal.. ");
|
|
myDecal = (DecalCoreClass)pDecal;
|
|
myWrappedDecal = new DecalWrapper(myDecal);
|
|
Util.WriteLine("Sink Decal Events.. ");
|
|
myDecal.InitializeComplete += myDecal_InitializeComplete;
|
|
myDecal.TerminateComplete += myDecal_TerminateComplete;
|
|
Util.Write("Get Hooks.. ");
|
|
myHooks = (ACHooksClass)myDecal.Hooks;
|
|
myWrappedHooks = new HooksWrapper(myHooks);
|
|
Util.WriteLine("Sink Hooks Events.. ");
|
|
myHooks.ChatTextIntercept += myHooks_ChatTextIntercept;
|
|
myHooks.StatusTextIntercept += myHooks_StatusTextIntercept;
|
|
myHooks.ChatParserIntercept += myHooks_ChatParserIntercept;
|
|
myHooks.AC3DRegionChanged += myHooks_AC3DRegionChanged;
|
|
myHooks.ObjectSelected += myHooks_ObjectSelected;
|
|
myHooks.ObjectDestroyed += myHooks_ObjectDestroyed;
|
|
myHooks.MessageProcessed += myHooks_MessageProcessed;
|
|
myHooks.ContainerOpened += myHooks_ContainerOpened;
|
|
myHooks.ChatClickIntercept += myHooks_ChatClickIntercept;
|
|
myHooks.RenderPreUI += myHooks_RenderPreUI;
|
|
Util.WriteLine("Decal.Adapter Lifetime-service Initiliazed");
|
|
}
|
|
|
|
internal void Terminate()
|
|
{
|
|
myDecal.InitializeComplete -= myDecal_InitializeComplete;
|
|
myDecal.TerminateComplete -= myDecal_TerminateComplete;
|
|
myHooks.ChatTextIntercept -= myHooks_ChatTextIntercept;
|
|
myHooks.StatusTextIntercept -= myHooks_StatusTextIntercept;
|
|
myHooks.ChatParserIntercept -= myHooks_ChatParserIntercept;
|
|
myHooks.AC3DRegionChanged -= myHooks_AC3DRegionChanged;
|
|
myHooks.ObjectSelected -= myHooks_ObjectSelected;
|
|
myHooks.ObjectDestroyed -= myHooks_ObjectDestroyed;
|
|
myHooks.MessageProcessed -= myHooks_MessageProcessed;
|
|
myHooks.ContainerOpened -= myHooks_ContainerOpened;
|
|
myHooks.ChatClickIntercept -= myHooks_ChatClickIntercept;
|
|
myHooks.RenderPreUI -= myHooks_RenderPreUI;
|
|
myWrappedDecal.Dispose();
|
|
myWrappedDecal = null;
|
|
Marshal.ReleaseComObject(myDecal);
|
|
myDecal = null;
|
|
myHooks = null;
|
|
myWrappedHooks.Dispose();
|
|
myWrappedHooks = null;
|
|
myService = null;
|
|
myServiceRunning = false;
|
|
}
|
|
|
|
public void IncrementAssemblyPreloadLockCounter()
|
|
{
|
|
myAssemblyPreloadCounter++;
|
|
}
|
|
|
|
public void DecrementAssemblyPreloadLockCounter()
|
|
{
|
|
myAssemblyPreloadCounter--;
|
|
if (myAssemblyPreloadCounter < 0)
|
|
{
|
|
myAssemblyPreloadCounter = 0;
|
|
}
|
|
if (myAssemblyPreloadCounter != 0 || myAssemblyPreloadStarted)
|
|
{
|
|
return;
|
|
}
|
|
myAssemblyPreloadStarted = true;
|
|
List<sAssemblyPreloadData> list = new List<sAssemblyPreloadData>();
|
|
Guid clsidAdvance = Guid.Empty;
|
|
Guid guid = new Guid("{71A69713-6593-47EC-0002-0000000DECA1}");
|
|
DecalEnum decalEnum = ((IDecalCore)Decal.Underlying).get_Configuration("Plugins", ref clsidAdvance);
|
|
try
|
|
{
|
|
while (true)
|
|
{
|
|
decalEnum.Next();
|
|
if (!decalEnum.Enabled || decalEnum.SurrogateClass != guid)
|
|
{
|
|
continue;
|
|
}
|
|
try
|
|
{
|
|
if (decalEnum.Restricted)
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
continue;
|
|
}
|
|
list.Add(new sAssemblyPreloadData
|
|
{
|
|
AssemblyName = (string)((IDecalEnum)decalEnum).get_Property("Assembly"),
|
|
Path = (string)((IDecalEnum)decalEnum).get_Property("Path")
|
|
});
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
finally
|
|
{
|
|
Marshal.ReleaseComObject(decalEnum);
|
|
}
|
|
ThreadPool.QueueUserWorkItem(AssemblyPreloadThreadProc, list);
|
|
}
|
|
|
|
internal void AssemblyPreloadThreadProc(object data)
|
|
{
|
|
if (!(data is List<sAssemblyPreloadData> list))
|
|
{
|
|
return;
|
|
}
|
|
foreach (sAssemblyPreloadData item in list)
|
|
{
|
|
try
|
|
{
|
|
Util.WriteLine("Preloading plugin assembly {0}, {1}", item.AssemblyName, item.Path);
|
|
Assembly(item.AssemblyName, item.Path, AppDomain.CurrentDomain);
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
}
|
|
}
|
|
}
|