Yes
This commit is contained in:
398
submodules/ECommonsLite/.gitignore
vendored
Normal file
398
submodules/ECommonsLite/.gitignore
vendored
Normal file
@@ -0,0 +1,398 @@
|
||||
## Ignore Visual Studio temporary files, build results, and
|
||||
## files generated by popular Visual Studio add-ons.
|
||||
##
|
||||
## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore
|
||||
|
||||
# User-specific files
|
||||
*.rsuser
|
||||
*.suo
|
||||
*.user
|
||||
*.userosscache
|
||||
*.sln.docstates
|
||||
|
||||
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||
*.userprefs
|
||||
|
||||
# Mono auto generated files
|
||||
mono_crash.*
|
||||
|
||||
# Build results
|
||||
[Dd]ebug/
|
||||
[Dd]ebugPublic/
|
||||
[Rr]elease/
|
||||
[Rr]eleases/
|
||||
x64/
|
||||
x86/
|
||||
[Ww][Ii][Nn]32/
|
||||
[Aa][Rr][Mm]/
|
||||
[Aa][Rr][Mm]64/
|
||||
bld/
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
[Ll]og/
|
||||
[Ll]ogs/
|
||||
|
||||
# Visual Studio 2015/2017 cache/options directory
|
||||
.vs/
|
||||
# Uncomment if you have tasks that create the project's static files in wwwroot
|
||||
#wwwroot/
|
||||
|
||||
# Visual Studio 2017 auto generated files
|
||||
Generated\ Files/
|
||||
|
||||
# MSTest test Results
|
||||
[Tt]est[Rr]esult*/
|
||||
[Bb]uild[Ll]og.*
|
||||
|
||||
# NUnit
|
||||
*.VisualState.xml
|
||||
TestResult.xml
|
||||
nunit-*.xml
|
||||
|
||||
# Build Results of an ATL Project
|
||||
[Dd]ebugPS/
|
||||
[Rr]eleasePS/
|
||||
dlldata.c
|
||||
|
||||
# Benchmark Results
|
||||
BenchmarkDotNet.Artifacts/
|
||||
|
||||
# .NET Core
|
||||
project.lock.json
|
||||
project.fragment.lock.json
|
||||
artifacts/
|
||||
|
||||
# ASP.NET Scaffolding
|
||||
ScaffoldingReadMe.txt
|
||||
|
||||
# StyleCop
|
||||
StyleCopReport.xml
|
||||
|
||||
# Files built by Visual Studio
|
||||
*_i.c
|
||||
*_p.c
|
||||
*_h.h
|
||||
*.ilk
|
||||
*.meta
|
||||
*.obj
|
||||
*.iobj
|
||||
*.pch
|
||||
*.pdb
|
||||
*.ipdb
|
||||
*.pgc
|
||||
*.pgd
|
||||
*.rsp
|
||||
*.sbr
|
||||
*.tlb
|
||||
*.tli
|
||||
*.tlh
|
||||
*.tmp
|
||||
*.tmp_proj
|
||||
*_wpftmp.csproj
|
||||
*.log
|
||||
*.tlog
|
||||
*.vspscc
|
||||
*.vssscc
|
||||
.builds
|
||||
*.pidb
|
||||
*.svclog
|
||||
*.scc
|
||||
|
||||
# Chutzpah Test files
|
||||
_Chutzpah*
|
||||
|
||||
# Visual C++ cache files
|
||||
ipch/
|
||||
*.aps
|
||||
*.ncb
|
||||
*.opendb
|
||||
*.opensdf
|
||||
*.sdf
|
||||
*.cachefile
|
||||
*.VC.db
|
||||
*.VC.VC.opendb
|
||||
|
||||
# Visual Studio profiler
|
||||
*.psess
|
||||
*.vsp
|
||||
*.vspx
|
||||
*.sap
|
||||
|
||||
# Visual Studio Trace Files
|
||||
*.e2e
|
||||
|
||||
# TFS 2012 Local Workspace
|
||||
$tf/
|
||||
|
||||
# Guidance Automation Toolkit
|
||||
*.gpState
|
||||
|
||||
# ReSharper is a .NET coding add-in
|
||||
_ReSharper*/
|
||||
*.[Rr]e[Ss]harper
|
||||
*.DotSettings.user
|
||||
|
||||
# TeamCity is a build add-in
|
||||
_TeamCity*
|
||||
|
||||
# DotCover is a Code Coverage Tool
|
||||
*.dotCover
|
||||
|
||||
# AxoCover is a Code Coverage Tool
|
||||
.axoCover/*
|
||||
!.axoCover/settings.json
|
||||
|
||||
# Coverlet is a free, cross platform Code Coverage Tool
|
||||
coverage*.json
|
||||
coverage*.xml
|
||||
coverage*.info
|
||||
|
||||
# Visual Studio code coverage results
|
||||
*.coverage
|
||||
*.coveragexml
|
||||
|
||||
# NCrunch
|
||||
_NCrunch_*
|
||||
.*crunch*.local.xml
|
||||
nCrunchTemp_*
|
||||
|
||||
# MightyMoose
|
||||
*.mm.*
|
||||
AutoTest.Net/
|
||||
|
||||
# Web workbench (sass)
|
||||
.sass-cache/
|
||||
|
||||
# Installshield output folder
|
||||
[Ee]xpress/
|
||||
|
||||
# DocProject is a documentation generator add-in
|
||||
DocProject/buildhelp/
|
||||
DocProject/Help/*.HxT
|
||||
DocProject/Help/*.HxC
|
||||
DocProject/Help/*.hhc
|
||||
DocProject/Help/*.hhk
|
||||
DocProject/Help/*.hhp
|
||||
DocProject/Help/Html2
|
||||
DocProject/Help/html
|
||||
|
||||
# Click-Once directory
|
||||
publish/
|
||||
|
||||
# Publish Web Output
|
||||
*.[Pp]ublish.xml
|
||||
*.azurePubxml
|
||||
# Note: Comment the next line if you want to checkin your web deploy settings,
|
||||
# but database connection strings (with potential passwords) will be unencrypted
|
||||
*.pubxml
|
||||
*.publishproj
|
||||
|
||||
# Microsoft Azure Web App publish settings. Comment the next line if you want to
|
||||
# checkin your Azure Web App publish settings, but sensitive information contained
|
||||
# in these scripts will be unencrypted
|
||||
PublishScripts/
|
||||
|
||||
# NuGet Packages
|
||||
*.nupkg
|
||||
# NuGet Symbol Packages
|
||||
*.snupkg
|
||||
# The packages folder can be ignored because of Package Restore
|
||||
**/[Pp]ackages/*
|
||||
# except build/, which is used as an MSBuild target.
|
||||
!**/[Pp]ackages/build/
|
||||
# Uncomment if necessary however generally it will be regenerated when needed
|
||||
#!**/[Pp]ackages/repositories.config
|
||||
# NuGet v3's project.json files produces more ignorable files
|
||||
*.nuget.props
|
||||
*.nuget.targets
|
||||
|
||||
# Microsoft Azure Build Output
|
||||
csx/
|
||||
*.build.csdef
|
||||
|
||||
# Microsoft Azure Emulator
|
||||
ecf/
|
||||
rcf/
|
||||
|
||||
# Windows Store app package directories and files
|
||||
AppPackages/
|
||||
BundleArtifacts/
|
||||
Package.StoreAssociation.xml
|
||||
_pkginfo.txt
|
||||
*.appx
|
||||
*.appxbundle
|
||||
*.appxupload
|
||||
|
||||
# Visual Studio cache files
|
||||
# files ending in .cache can be ignored
|
||||
*.[Cc]ache
|
||||
# but keep track of directories ending in .cache
|
||||
!?*.[Cc]ache/
|
||||
|
||||
# Others
|
||||
ClientBin/
|
||||
~$*
|
||||
*~
|
||||
*.dbmdl
|
||||
*.dbproj.schemaview
|
||||
*.jfm
|
||||
*.pfx
|
||||
*.publishsettings
|
||||
orleans.codegen.cs
|
||||
|
||||
# Including strong name files can present a security risk
|
||||
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
|
||||
#*.snk
|
||||
|
||||
# Since there are multiple workflows, uncomment next line to ignore bower_components
|
||||
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
|
||||
#bower_components/
|
||||
|
||||
# RIA/Silverlight projects
|
||||
Generated_Code/
|
||||
|
||||
# Backup & report files from converting an old project file
|
||||
# to a newer Visual Studio version. Backup files are not needed,
|
||||
# because we have git ;-)
|
||||
_UpgradeReport_Files/
|
||||
Backup*/
|
||||
UpgradeLog*.XML
|
||||
UpgradeLog*.htm
|
||||
ServiceFabricBackup/
|
||||
*.rptproj.bak
|
||||
|
||||
# SQL Server files
|
||||
*.mdf
|
||||
*.ldf
|
||||
*.ndf
|
||||
|
||||
# Business Intelligence projects
|
||||
*.rdl.data
|
||||
*.bim.layout
|
||||
*.bim_*.settings
|
||||
*.rptproj.rsuser
|
||||
*- [Bb]ackup.rdl
|
||||
*- [Bb]ackup ([0-9]).rdl
|
||||
*- [Bb]ackup ([0-9][0-9]).rdl
|
||||
|
||||
# Microsoft Fakes
|
||||
FakesAssemblies/
|
||||
|
||||
# GhostDoc plugin setting file
|
||||
*.GhostDoc.xml
|
||||
|
||||
# Node.js Tools for Visual Studio
|
||||
.ntvs_analysis.dat
|
||||
node_modules/
|
||||
|
||||
# Visual Studio 6 build log
|
||||
*.plg
|
||||
|
||||
# Visual Studio 6 workspace options file
|
||||
*.opt
|
||||
|
||||
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
|
||||
*.vbw
|
||||
|
||||
# Visual Studio 6 auto-generated project file (contains which files were open etc.)
|
||||
*.vbp
|
||||
|
||||
# Visual Studio 6 workspace and project file (working project files containing files to include in project)
|
||||
*.dsw
|
||||
*.dsp
|
||||
|
||||
# Visual Studio 6 technical files
|
||||
*.ncb
|
||||
*.aps
|
||||
|
||||
# Visual Studio LightSwitch build output
|
||||
**/*.HTMLClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/ModelManifest.xml
|
||||
**/*.Server/GeneratedArtifacts
|
||||
**/*.Server/ModelManifest.xml
|
||||
_Pvt_Extensions
|
||||
|
||||
# Paket dependency manager
|
||||
.paket/paket.exe
|
||||
paket-files/
|
||||
|
||||
# FAKE - F# Make
|
||||
.fake/
|
||||
|
||||
# CodeRush personal settings
|
||||
.cr/personal
|
||||
|
||||
# Python Tools for Visual Studio (PTVS)
|
||||
__pycache__/
|
||||
*.pyc
|
||||
|
||||
# Cake - Uncomment if you are using it
|
||||
# tools/**
|
||||
# !tools/packages.config
|
||||
|
||||
# Tabs Studio
|
||||
*.tss
|
||||
|
||||
# Telerik's JustMock configuration file
|
||||
*.jmconfig
|
||||
|
||||
# BizTalk build output
|
||||
*.btp.cs
|
||||
*.btm.cs
|
||||
*.odx.cs
|
||||
*.xsd.cs
|
||||
|
||||
# OpenCover UI analysis results
|
||||
OpenCover/
|
||||
|
||||
# Azure Stream Analytics local run output
|
||||
ASALocalRun/
|
||||
|
||||
# MSBuild Binary and Structured Log
|
||||
*.binlog
|
||||
|
||||
# NVidia Nsight GPU debugger configuration file
|
||||
*.nvuser
|
||||
|
||||
# MFractors (Xamarin productivity tool) working folder
|
||||
.mfractor/
|
||||
|
||||
# Local History for Visual Studio
|
||||
.localhistory/
|
||||
|
||||
# Visual Studio History (VSHistory) files
|
||||
.vshistory/
|
||||
|
||||
# BeatPulse healthcheck temp database
|
||||
healthchecksdb
|
||||
|
||||
# Backup folder for Package Reference Convert tool in Visual Studio 2017
|
||||
MigrationBackup/
|
||||
|
||||
# Ionide (cross platform F# VS Code tools) working folder
|
||||
.ionide/
|
||||
|
||||
# Fody - auto-generated XML schema
|
||||
FodyWeavers.xsd
|
||||
|
||||
# VS Code files for those working on multiple tools
|
||||
.vscode/*
|
||||
!.vscode/settings.json
|
||||
!.vscode/tasks.json
|
||||
!.vscode/launch.json
|
||||
!.vscode/extensions.json
|
||||
*.code-workspace
|
||||
|
||||
# Local History for Visual Studio Code
|
||||
.history/
|
||||
|
||||
# Windows Installer files from build outputs
|
||||
*.cab
|
||||
*.msi
|
||||
*.msix
|
||||
*.msm
|
||||
*.msp
|
||||
|
||||
# JetBrains Rider
|
||||
*.sln.iml
|
||||
25
submodules/ECommonsLite/ECommonsLite.sln
Normal file
25
submodules/ECommonsLite/ECommonsLite.sln
Normal file
@@ -0,0 +1,25 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.10.35004.147
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ECommonsLite", "ECommonsLite\ECommonsLite.csproj", "{2F14DE07-8C8C-44D0-950B-60D2E942EF50}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x64 = Debug|x64
|
||||
Release|x64 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{2F14DE07-8C8C-44D0-950B-60D2E942EF50}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{2F14DE07-8C8C-44D0-950B-60D2E942EF50}.Debug|x64.Build.0 = Debug|x64
|
||||
{2F14DE07-8C8C-44D0-950B-60D2E942EF50}.Release|x64.ActiveCfg = Release|x64
|
||||
{2F14DE07-8C8C-44D0-950B-60D2E942EF50}.Release|x64.Build.0 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {CBF7B859-9282-49CD-9D29-E09FB3480574}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
35
submodules/ECommonsLite/ECommonsLite/DalamudServices/Svc.cs
Normal file
35
submodules/ECommonsLite/ECommonsLite/DalamudServices/Svc.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
using Dalamud.Game;
|
||||
using Dalamud.Game.ClientState.Objects;
|
||||
using Dalamud.IoC;
|
||||
using Dalamud.Plugin;
|
||||
using Dalamud.Plugin.Services;
|
||||
using ECommonsLite.Logging;
|
||||
using System;
|
||||
|
||||
namespace ECommonsLite.DalamudServices;
|
||||
#nullable disable
|
||||
|
||||
public class Svc
|
||||
{
|
||||
[PluginService] public static IDalamudPluginInterface PluginInterface { get; private set; }
|
||||
[PluginService] public static IFramework Framework { get; private set; }
|
||||
[PluginService] public static IPluginLog Log { get; private set; }
|
||||
|
||||
internal static bool IsInitialized = false;
|
||||
public static void Init(IDalamudPluginInterface pi)
|
||||
{
|
||||
if(IsInitialized)
|
||||
{
|
||||
PluginLog.Debug("Services already initialized, skipping");
|
||||
}
|
||||
IsInitialized = true;
|
||||
try
|
||||
{
|
||||
pi.Create<Svc>();
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
ex.Log();
|
||||
}
|
||||
}
|
||||
}
|
||||
12
submodules/ECommonsLite/ECommonsLite/ECommonsLite.csproj
Normal file
12
submodules/ECommonsLite/ECommonsLite/ECommonsLite.csproj
Normal file
@@ -0,0 +1,12 @@
|
||||
<Project Sdk="Dalamud.NET.Sdk/13.0.0">
|
||||
|
||||
<PropertyGroup>
|
||||
<NoWarn>CS1591;CA1401;CS0649;CS8632;CS0414;CS0169;IDE1006;CS0419</NoWarn>
|
||||
<Optimize>True</Optimize>
|
||||
<IsTrimmable>false</IsTrimmable>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<Use_DalamudPackager>false</Use_DalamudPackager>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
38
submodules/ECommonsLite/ECommonsLite/ECommonsLiteMain.cs
Normal file
38
submodules/ECommonsLite/ECommonsLite/ECommonsLiteMain.cs
Normal file
@@ -0,0 +1,38 @@
|
||||
using Dalamud.Plugin;
|
||||
using ECommonsLite.DalamudServices;
|
||||
using ECommonsLite.EzIpcManager;
|
||||
using ECommonsLite.Logging;
|
||||
using Serilog.Events;
|
||||
using System.Reflection;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace ECommonsLite;
|
||||
|
||||
public static class ECommonsLiteMain
|
||||
{
|
||||
public static IDalamudPlugin Instance = null;
|
||||
public static bool Disposed { get; private set; } = false;
|
||||
//test
|
||||
public static void Init(IDalamudPluginInterface pluginInterface, IDalamudPlugin instance, params Module[] modules)
|
||||
{
|
||||
Instance = instance;
|
||||
GenericHelpers.Safe(() => Svc.Init(pluginInterface));
|
||||
#if DEBUG
|
||||
var type = "debug build";
|
||||
#elif RELEASE
|
||||
var type = "release build";
|
||||
#else
|
||||
var type = "unknown build";
|
||||
#endif
|
||||
PluginLog.Information($"This is ECommonsLite v{typeof(ECommonsLiteMain).Assembly.GetName().Version} ({type}) and {Svc.PluginInterface.InternalName} v{instance.GetType().Assembly.GetName().Version}. Hello!");
|
||||
Svc.Log.MinimumLogLevel = LogEventLevel.Verbose;
|
||||
}
|
||||
|
||||
public static void Dispose()
|
||||
{
|
||||
Disposed = true;
|
||||
GenericHelpers.Safe(EzIPC.Dispose);
|
||||
Instance = null;
|
||||
}
|
||||
}
|
||||
303
submodules/ECommonsLite/ECommonsLite/EzIpcManager/EzIPC.cs
Normal file
303
submodules/ECommonsLite/ECommonsLite/EzIpcManager/EzIPC.cs
Normal file
@@ -0,0 +1,303 @@
|
||||
using ECommonsLite.DalamudServices;
|
||||
using ECommonsLite.Logging;
|
||||
using ECommonsLite.Reflection;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace ECommonsLite.EzIpcManager;
|
||||
|
||||
/// <summary>
|
||||
/// Provides easier way to interact with Dalamud IPC.<br></br>
|
||||
/// See EzIPC.md for example use.
|
||||
/// </summary>
|
||||
public static class EzIPC
|
||||
{
|
||||
/// <summary>
|
||||
/// Event that fires whenever an exception occurs in any of safe invocation wrapper methods.
|
||||
/// </summary>
|
||||
public static event Action<Exception>? OnSafeInvocationException;
|
||||
|
||||
internal static void InvokeOnSafeInvocationException(Exception e) => OnSafeInvocationException?.Invoke(e);
|
||||
|
||||
private static List<EzIPCDisposalToken> Unregister = [];
|
||||
private static Type[] FuncTypes = [typeof(Func<>), typeof(Func<,>), typeof(Func<,,>), typeof(Func<,,,>), typeof(Func<,,,,>), typeof(Func<,,,,,>), typeof(Func<,,,,,,>), typeof(Func<,,,,,,,>), typeof(Func<,,,,,,,,>), typeof(Func<,,,,,,,,,>)];
|
||||
private static Type[] ActionTypes = [typeof(Action<>), typeof(Action<,>), typeof(Action<,,>), typeof(Action<,,,>), typeof(Action<,,,,>), typeof(Action<,,,,,>), typeof(Action<,,,,,,>), typeof(Action<,,,,,,,>), typeof(Action<,,,,,,,,>), typeof(Action<,,,,,,,,,>)];
|
||||
|
||||
/// <summary>
|
||||
/// Initializes IPC provider and subscriber for an instance type. Static methods or field/properties/properties will be ignored, register them separately via static Init if you must.<br></br>
|
||||
/// Each method that have <see cref="EzIPCAttribute"/> or <see cref="EzIPCEventAttribute"/> will be registered for IPC under "Prefix.IPCName" tag. If prefix is not specified, it is your plugin's internal name. If IPCName is not specified, it is method name.<br></br>
|
||||
/// Each Action and Function field/property that have <see cref="EzIPCAttribute"/> will be assigned delegate that represents respective GetIPCSubscriber. Each Action field/property that have <see cref="EzIPCEventAttribute"/> will be assigned to become respective tag's event trigger. Make sure to explicitly specify prefix if you're interacting with other plugin's IPC.<br></br>
|
||||
/// You do not need to dispose IPC methods in any way. Everything is disposed upon calling <see cref="ECommonsLiteMain.Dispose"/>.
|
||||
/// </summary>
|
||||
/// <param name="instance">Instance of a class that has EzIPC methods and field/properties/properties.</param>
|
||||
/// <param name="prefix">Name prefix</param>
|
||||
/// <param name="safeWrapper">Type of a safe invocation wrapper to be used for IPC calls. Wrappers, when used, will silently drop exceptions and return default object if invocation has failed. You can subscribe to <see cref="EzIPC.OnSafeInvocationException"/> event to observe these exceptions.</param>
|
||||
/// <exception cref="ArgumentNullException"></exception>
|
||||
/// <returns>Array of disposal tokens that can be used to dispose registered providers and event subscription. <b>Typical use of EzIPC never has any need to store and deal with these tokens</b>; you only ever need them when you want to unregister IPC before your plugin's Dispose method is called.</returns>
|
||||
public static EzIPCDisposalToken[] Init(object instance, string? prefix = null, SafeWrapper safeWrapper = SafeWrapper.None) => Init(instance, instance.GetType(), prefix, safeWrapper);
|
||||
|
||||
/// <summary>
|
||||
/// Initializes IPC provider and subscriber for a static type.<br></br>
|
||||
/// Each method that have <see cref="EzIPCAttribute"/> or <see cref="EzIPCEventAttribute"/> will be registered for IPC under "Prefix.IPCName" tag. If prefix is not specified, it is your plugin's internal name. If IPCName is not specified, it is method name.<br></br>
|
||||
/// Each Action and Function field/property that have <see cref="EzIPCAttribute"/> will be assigned delegate that represents respective GetIPCSubscriber. Each Action field/property that have <see cref="EzIPCEventAttribute"/> will be assigned to become respective tag's event trigger. Make sure to explicitly specify prefix if you're interacting with other plugin's IPC.<br></br>
|
||||
/// You do not need to dispose IPC methods in any way. Everything is disposed upon calling <see cref="ECommonsLiteMain.Dispose"/>.
|
||||
/// </summary>
|
||||
/// <param name="staticType">Type of a static class that has EzIPC methods and field/properties/properties.</param>
|
||||
/// <param name="prefix">Name prefix</param>
|
||||
/// <param name="safeWrapper">Type of a safe invocation wrapper to be used for IPC calls. Wrappers, when used, will silently drop exceptions and return default object if invocation has failed. You can subscribe to <see cref="EzIPC.OnSafeInvocationException"/> event to observe these exceptions.</param>
|
||||
/// <exception cref="ArgumentNullException"></exception>
|
||||
/// <returns>Array of disposal tokens that can be used to dispose registered providers and event subscription. <b>Typical use of EzIPC never has any need to store and deal with these tokens</b>; you only ever need them when you want to unregister IPC before your plugin's Dispose method is called.</returns>
|
||||
public static EzIPCDisposalToken[] Init(Type staticType, string? prefix = null, SafeWrapper safeWrapper = SafeWrapper.None) => Init(null, staticType, prefix, safeWrapper);
|
||||
|
||||
private static EzIPCDisposalToken[] Init(object? instance, Type instanceType, string? prefix, SafeWrapper safeWrapper)
|
||||
{
|
||||
if(safeWrapper == SafeWrapper.Inherit) throw new InvalidOperationException($"{nameof(SafeWrapper.Inherit)} is only valid option when used in EzIPC attribute. Please choose your desired SafeWrapper.");
|
||||
var ret = new List<EzIPCDisposalToken>();
|
||||
var bFlags = BindingFlags.Public | BindingFlags.NonPublic | (instance != null ? BindingFlags.Instance : BindingFlags.Static);
|
||||
//init provider
|
||||
prefix ??= Svc.PluginInterface.InternalName;
|
||||
foreach(var method in instanceType.GetMethods(bFlags))
|
||||
{
|
||||
try
|
||||
{
|
||||
var attr = method.GetCustomAttributes(true).OfType<EzIPCAttribute>().FirstOrDefault();
|
||||
if(attr != null)
|
||||
{
|
||||
PluginLog.Information($"[EzIPC Provider] Attempting to register {instanceType.Name}.{method.Name} as IPC method ({method.GetParameters().Length})");
|
||||
var ipcName = attr.IPCName ?? method.Name;
|
||||
ipcName = ipcName.Replace("%m", method.Name);
|
||||
ipcName = ipcName.Replace("%p", Svc.PluginInterface.InternalName);
|
||||
var reg = FindIpcProvider(method.GetParameters().Length + 1) ?? throw new NullReferenceException("[EzIPC Provider] Could not retrieve GetIpcProvider. Did you called EzIPC.Init before ECommonsMain.Init or specified more than 9 arguments?");
|
||||
var isAction = method.ReturnType == typeof(void);
|
||||
var genericArray = (Type[])[.. method.GetParameters().Select(x => x.ParameterType), isAction ? attr.ActionLastGenericType : method.ReturnType];
|
||||
var genericMethod = reg.MakeGenericMethod([.. genericArray]);
|
||||
var name = attr.ApplyPrefix ? $"{prefix}.{ipcName}" : ipcName;
|
||||
PluginLog.Information($"[EzIPC Provider] Registering IPC method {name} with method {instanceType.FullName}.{method.Name}");
|
||||
genericMethod.Invoke(Svc.PluginInterface, [name]).Call(isAction ? "RegisterAction" : "RegisterFunc", [ReflectionHelper.CreateDelegate(method, instance)], true);
|
||||
var token = new EzIPCDisposalToken(name, false, () =>
|
||||
{
|
||||
PluginLog.Information($"[EzIPC Provider] Unregistering IPC method {name}");
|
||||
genericMethod.Invoke(Svc.PluginInterface, [name]).Call(isAction ? "UnregisterAction" : "UnregisterFunc", [], true);
|
||||
});
|
||||
ret.Add(token);
|
||||
Unregister.Add(token);
|
||||
}
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
PluginLog.Error($"[EzIPC Provider] Failed to initialize provider for {instanceType.Name}.{method.Name}");
|
||||
e.Log();
|
||||
}
|
||||
}
|
||||
|
||||
//init subscriber
|
||||
foreach(var reference in instanceType.GetFieldPropertyUnions(bFlags))
|
||||
{
|
||||
try
|
||||
{
|
||||
var attr = reference.GetCustomAttributes(true).OfType<EzIPCAttribute>().FirstOrDefault();
|
||||
if(attr != null)
|
||||
{
|
||||
var ipcName = attr.IPCName ?? reference.Name;
|
||||
ipcName = ipcName.Replace("%m", reference.Name);
|
||||
ipcName = ipcName.Replace("%p", Svc.PluginInterface.InternalName);
|
||||
var isNonGenericAction = reference.UnionType == typeof(Action);
|
||||
if(isNonGenericAction || reference.UnionType.GetGenericTypeDefinition().EqualsAny([.. FuncTypes, .. ActionTypes]))
|
||||
{
|
||||
var wrapper = attr.Wrapper == SafeWrapper.Inherit ? safeWrapper : attr.Wrapper;
|
||||
PluginLog.Information($"[EzIPC Subscriber] Attempting to assign IPC method to {instanceType.Name}.{reference.Name} with wrapper {wrapper}");
|
||||
var isAction = isNonGenericAction || reference.UnionType.GetGenericTypeDefinition().EqualsAny(ActionTypes);
|
||||
var genericArgsLen = reference.UnionType.GetGenericArguments().Length;
|
||||
var reg = FindIpcSubscriber(genericArgsLen + (isAction ? 1 : 0)) ?? throw new NullReferenceException("Could not retrieve GetIpcSubscriber. Did you called EzIPC.Init before ECommonsMain.Init or specified more than 9 arguments?");
|
||||
var genericArgs = reference.UnionType.IsGenericType ? reference.UnionType.GetGenericArguments() : [];
|
||||
var adjustedGenericArgs = isAction ? [.. genericArgs, attr.ActionLastGenericType] : genericArgs;
|
||||
var genericMethod = reg.MakeGenericMethod(adjustedGenericArgs);
|
||||
var name = attr.ApplyPrefix ? $"{prefix}.{ipcName}" : ipcName;
|
||||
var callerInfo = genericMethod.Invoke(Svc.PluginInterface, [name])!;
|
||||
var invocationDelegate = ReflectionHelper.CreateDelegate(callerInfo.GetType().GetMethod(isAction ? "InvokeAction" : "InvokeFunc"), callerInfo);
|
||||
if(wrapper != SafeWrapper.None)
|
||||
{
|
||||
var safeWrapperObj = CreateSafeWrapper(wrapper, adjustedGenericArgs) ?? throw new NullReferenceException("Safe wrapper creation failed. Please report this exception to developer.");
|
||||
var safeWrapperMethod = safeWrapperObj.GetType().GetMethod(isAction ? "InvokeAction" : "InvokeFunction", ReflectionHelper.AllFlags);
|
||||
safeWrapperObj.SetFoP(isAction ? "Action" : "Function", invocationDelegate);
|
||||
reference.SetValue(instance, ReflectionHelper.CreateDelegate(safeWrapperMethod, safeWrapperObj));
|
||||
}
|
||||
else
|
||||
{
|
||||
reference.SetValue(instance, invocationDelegate);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
PluginLog.Error($"[EzIPC Subscriber] Failed to initialize subscriber for {instanceType.Name}.{reference.Name}");
|
||||
e.Log();
|
||||
}
|
||||
}
|
||||
|
||||
//init subscriber event
|
||||
prefix ??= Svc.PluginInterface.InternalName;
|
||||
foreach(var method in instanceType.GetMethods(bFlags))
|
||||
{
|
||||
try
|
||||
{
|
||||
var attr = method.GetCustomAttributes(true).OfType<EzIPCEventAttribute>().FirstOrDefault();
|
||||
if(attr != null)
|
||||
{
|
||||
PluginLog.Information($"[EzIPC Subscriber] Attempting to register {instanceType.Name}.{method.Name} as IPC event ({method.GetParameters().Length})");
|
||||
var ipcName = attr.IPCName ?? method.Name;
|
||||
ipcName = ipcName.Replace("%m", method.Name);
|
||||
ipcName = ipcName.Replace("%p", Svc.PluginInterface.InternalName);
|
||||
var reg = FindIpcSubscriber(method.GetParameters().Length + 1) ?? throw new NullReferenceException("[EzIPC Provider] Could not retrieve FindIpcSubscriber. Did you called EzIPC.Init before ECommonsMain.Init or specified more than 9 arguments?");
|
||||
if(method.ReturnType != typeof(void)) throw new InvalidOperationException($"Event method must have void return value");
|
||||
var genericArray = (Type[])[.. method.GetParameters().Select(x => x.ParameterType), attr.ActionLastGenericType];
|
||||
var genericMethod = reg.MakeGenericMethod([.. genericArray]);
|
||||
var name = attr.ApplyPrefix ? $"{prefix}.{ipcName}" : ipcName;
|
||||
PluginLog.Information($"[EzIPC Subscriber] Registering IPC event {name} with method {instanceType.FullName}.{method.Name}");
|
||||
var d = ReflectionHelper.CreateDelegate(method, instance);
|
||||
genericMethod.Invoke(Svc.PluginInterface, [name]).Call("Subscribe", [d], true);
|
||||
var token = new EzIPCDisposalToken(name, true, () =>
|
||||
{
|
||||
PluginLog.Information($"[EzIPC Subscriber] Unregistering IPC event {name}");
|
||||
genericMethod.Invoke(Svc.PluginInterface, [name]).Call("Unsubscribe", [d], true);
|
||||
});
|
||||
Unregister.Add(token);
|
||||
ret.Add(token);
|
||||
}
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
PluginLog.Error($"[EzIPC Subscriber] Failed to subscribe for event for {instanceType.Name}.{method.Name}");
|
||||
e.Log();
|
||||
}
|
||||
}
|
||||
|
||||
//init provider event
|
||||
foreach(var reference in instanceType.GetFieldPropertyUnions(bFlags))
|
||||
{
|
||||
try
|
||||
{
|
||||
var attr = reference.GetCustomAttributes(true).OfType<EzIPCEventAttribute>().FirstOrDefault();
|
||||
if(attr != null)
|
||||
{
|
||||
var ipcName = attr.IPCName ?? reference.Name;
|
||||
ipcName = ipcName.Replace("%m", reference.Name);
|
||||
ipcName = ipcName.Replace("%p", Svc.PluginInterface.InternalName);
|
||||
var isNonGenericAction = reference.UnionType == typeof(Action);
|
||||
if(isNonGenericAction || reference.UnionType.GetGenericTypeDefinition().EqualsAny(ActionTypes))
|
||||
{
|
||||
PluginLog.Information($"[EzIPC Provider] Attempting to assign IPC event to {instanceType.Name}.{reference.Name}");
|
||||
var reg = FindIpcProvider(reference.UnionType.GetGenericArguments().Length + 1) ?? throw new NullReferenceException("Could not retrieve GetIpcProvider. Did you called EzIPC.Init before ECommonsMain.Init or specified more than 9 arguments?");
|
||||
var genericArgs = reference.UnionType.IsGenericType ? reference.UnionType.GetGenericArguments() : [];
|
||||
var genericMethod = reg.MakeGenericMethod([.. genericArgs, attr.ActionLastGenericType]);
|
||||
var name = attr.ApplyPrefix ? $"{prefix}.{ipcName}" : ipcName;
|
||||
var callerInfo = genericMethod.Invoke(Svc.PluginInterface, [name])!;
|
||||
reference.SetValue(instance, ReflectionHelper.CreateDelegate(callerInfo.GetType().GetMethod("SendMessage"), callerInfo));
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
PluginLog.Error($"[EzIPC Provider] Failed to initialize event provider for {instanceType.Name}.{reference.Name}");
|
||||
e.Log();
|
||||
}
|
||||
}
|
||||
return [.. ret];
|
||||
}
|
||||
|
||||
internal static void Dispose()
|
||||
{
|
||||
foreach(var token in Unregister)
|
||||
{
|
||||
try
|
||||
{
|
||||
token.Dispose();
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
PluginLog.Error($"Error while unregistering IPC");
|
||||
e.Log();
|
||||
}
|
||||
}
|
||||
Unregister.Clear();
|
||||
OnSafeInvocationException = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Searches for IPC provider function with specified number of generic arguments
|
||||
/// </summary>
|
||||
/// <param name="numGenericArgs"></param>
|
||||
/// <returns></returns>
|
||||
public static MethodInfo? FindIpcProvider(int numGenericArgs)
|
||||
{
|
||||
foreach(var m in Svc.PluginInterface.GetType().GetMethods(ReflectionHelper.AllFlags))
|
||||
{
|
||||
if(m.Name == "GetIpcProvider" && m.IsGenericMethod && m.GetGenericArguments().Length == numGenericArgs)
|
||||
{
|
||||
return m;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Searches for IPC subscriber function with specified number of generic arguments
|
||||
/// </summary>
|
||||
/// <param name="numGenericArgs"></param>
|
||||
/// <returns></returns>
|
||||
public static MethodInfo? FindIpcSubscriber(int numGenericArgs)
|
||||
{
|
||||
foreach(var m in Svc.PluginInterface.GetType().GetMethods(ReflectionHelper.AllFlags))
|
||||
{
|
||||
if(m.Name == "GetIpcSubscriber" && m.IsGenericMethod && m.GetGenericArguments().Length == numGenericArgs)
|
||||
{
|
||||
return m;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static object? CreateSafeWrapper(SafeWrapper wrapperKind, Type[] adjustedGenericArgs)
|
||||
{
|
||||
Type? type = null;
|
||||
if(wrapperKind == SafeWrapper.IPCException)
|
||||
{
|
||||
type = adjustedGenericArgs.Length switch
|
||||
{
|
||||
1 => typeof(SafeWrapperIPC.Wrapper<>),
|
||||
2 => typeof(SafeWrapperIPC.Wrapper<,>),
|
||||
3 => typeof(SafeWrapperIPC.Wrapper<,,>),
|
||||
4 => typeof(SafeWrapperIPC.Wrapper<,,,>),
|
||||
5 => typeof(SafeWrapperIPC.Wrapper<,,,,>),
|
||||
6 => typeof(SafeWrapperIPC.Wrapper<,,,,,>),
|
||||
7 => typeof(SafeWrapperIPC.Wrapper<,,,,,,>),
|
||||
8 => typeof(SafeWrapperIPC.Wrapper<,,,,,,,>),
|
||||
9 => typeof(SafeWrapperIPC.Wrapper<,,,,,,,,>),
|
||||
_ => throw new ArgumentOutOfRangeException(GetThrowString()),
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
type = adjustedGenericArgs.Length switch
|
||||
{
|
||||
1 => typeof(SafeWrapperAny.Wrapper<>),
|
||||
2 => typeof(SafeWrapperAny.Wrapper<,>),
|
||||
3 => typeof(SafeWrapperAny.Wrapper<,,>),
|
||||
4 => typeof(SafeWrapperAny.Wrapper<,,,>),
|
||||
5 => typeof(SafeWrapperAny.Wrapper<,,,,>),
|
||||
6 => typeof(SafeWrapperAny.Wrapper<,,,,,>),
|
||||
7 => typeof(SafeWrapperAny.Wrapper<,,,,,,>),
|
||||
8 => typeof(SafeWrapperAny.Wrapper<,,,,,,,>),
|
||||
9 => typeof(SafeWrapperAny.Wrapper<,,,,,,,,>),
|
||||
_ => throw new ArgumentOutOfRangeException(GetThrowString()),
|
||||
};
|
||||
}
|
||||
type = type.MakeGenericType(adjustedGenericArgs);
|
||||
return Activator.CreateInstance(type);
|
||||
|
||||
string GetThrowString() => $"Could not find safe wrapper of {wrapperKind} kind with {adjustedGenericArgs.Length} arguments";
|
||||
}
|
||||
}
|
||||
57
submodules/ECommonsLite/ECommonsLite/EzIpcManager/EzIPC.md
Normal file
57
submodules/ECommonsLite/ECommonsLite/EzIpcManager/EzIPC.md
Normal file
@@ -0,0 +1,57 @@
|
||||
IPC provider side example:
|
||||
```C#
|
||||
public class IPCProvider()
|
||||
{
|
||||
//Internal plugin name is MyPlugin
|
||||
public IPCProvider()
|
||||
{
|
||||
EzIPC.Init(this);
|
||||
}
|
||||
|
||||
[EzIPC]
|
||||
public void MyIPCAction() //will register as MyPlugin.MyIPCAction
|
||||
{
|
||||
DoThings();
|
||||
}
|
||||
|
||||
[EzIPC("RenamedFunction")]
|
||||
public int MyIPCFunction() //will register as MyPlugin.RenamedFunction
|
||||
{
|
||||
return DoOtherThings();
|
||||
}
|
||||
|
||||
[EzIPCEvent] public Action Event; //Provides delegate for firing events
|
||||
[EzIPCEvent] public Action<int> AwesomeEvent;
|
||||
}
|
||||
```
|
||||
|
||||
IPC subscriber (consumer) side example:
|
||||
```C#
|
||||
public class IPCSubscriber()
|
||||
{
|
||||
public IPCSubscriber()
|
||||
{
|
||||
EzIPC.Init(this, "MyPlugin");
|
||||
}
|
||||
|
||||
[EzIPC] public readonly Action MyIPCAction; //retrieves delegate for MyPlugin.MyIPCAction
|
||||
[EzIPC("RenamedFunction")] public readonly Func<int> SinceItsRenamedFieldCanHaveAnyName;
|
||||
|
||||
[EzIPC("OtherPlugin_OtherAction", applyPrefix:false)] public Action OtherPluginAction;
|
||||
//you can define full tag without prefix for plugins
|
||||
//that don't follow this standard naming convention or
|
||||
//if you want to get IPC from multiple plugins in one class
|
||||
|
||||
[EzIPCEvent] //event subscription
|
||||
void Event()
|
||||
{
|
||||
DoSomething();
|
||||
}
|
||||
|
||||
[EzIPCEvent]
|
||||
void AwesomeEvent(int a1)
|
||||
{
|
||||
DoSomethingElse(a1);
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,26 @@
|
||||
using System;
|
||||
|
||||
namespace ECommonsLite.EzIpcManager;
|
||||
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false)]
|
||||
public class EzIPCAttribute : Attribute
|
||||
{
|
||||
public string? IPCName;
|
||||
public bool ApplyPrefix;
|
||||
public Type ActionLastGenericType;
|
||||
public SafeWrapper Wrapper = SafeWrapper.Inherit;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes <see cref="EzIPCAttribute"/>.
|
||||
/// </summary>
|
||||
/// <param name="iPCName">IPC method name.</param>
|
||||
/// <param name="applyPrefix">Whether to apply prefix before name or not.</param>
|
||||
/// <param name="actionLastGenericType">Dummy return type used as a last generic argument for actions. When omitted, typeof(object) is used.</param>
|
||||
/// <param name="wrapper">Wrapper type</param>
|
||||
public EzIPCAttribute(string? iPCName = null, bool applyPrefix = true, Type? actionLastGenericType = null, SafeWrapper wrapper = SafeWrapper.Inherit)
|
||||
{
|
||||
IPCName = iPCName;
|
||||
ApplyPrefix = applyPrefix;
|
||||
ActionLastGenericType = actionLastGenericType ?? typeof(object);
|
||||
Wrapper = wrapper;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
using ECommonsLite.Logging;
|
||||
using System;
|
||||
|
||||
namespace ECommonsLite.EzIpcManager;
|
||||
/// <summary>
|
||||
/// Represents EzIPC token, which can be used to manually dispose IPC when you want fine-grained control over disposing IPC. Any undisposed tokens are disposed during ECommonsMain's dispose so <b>you do not need to manually dispose tokens</b>.
|
||||
/// </summary>
|
||||
public sealed class EzIPCDisposalToken
|
||||
{
|
||||
/// <summary>
|
||||
/// Full IPC tag
|
||||
/// </summary>
|
||||
public readonly string IpcTag;
|
||||
/// <summary>
|
||||
/// Whether the token is event subscription
|
||||
/// </summary>
|
||||
public readonly bool IsEvent;
|
||||
/// <summary>
|
||||
/// Whether the token was already disposed
|
||||
/// </summary>
|
||||
public bool IsDisposed { get; private set; } = false;
|
||||
|
||||
private readonly Action DisposeAction;
|
||||
|
||||
internal EzIPCDisposalToken(string name, bool isEvent, Action disposeAction)
|
||||
{
|
||||
IpcTag = name ?? throw new ArgumentNullException(nameof(name));
|
||||
IsEvent = isEvent;
|
||||
DisposeAction = disposeAction ?? throw new ArgumentNullException(nameof(disposeAction));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disposes token, unregistering IPC provider or event subscription, if not already disposed.<br></br>
|
||||
/// <b>You do not need to call this method unless you specifically want to unregister your IPC before plugin unloads.</b>
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
if(!IsDisposed)
|
||||
{
|
||||
IsDisposed = true;
|
||||
try
|
||||
{
|
||||
DisposeAction();
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
PluginLog.Error($"[EzIPC Disposer] Error while disposing EzIPC");
|
||||
e.Log();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using System;
|
||||
|
||||
namespace ECommonsLite.EzIpcManager;
|
||||
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Field, AllowMultiple = false)]
|
||||
public class EzIPCEventAttribute : Attribute
|
||||
{
|
||||
public string? IPCName;
|
||||
public bool ApplyPrefix;
|
||||
public Type ActionLastGenericType;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes <see cref="EzIPCAttribute"/>.
|
||||
/// </summary>
|
||||
/// <param name="iPCName">IPC method name.</param>
|
||||
/// <param name="applyPrefix">Whether to apply prefix before name or not.</param>
|
||||
/// /// <param name="actionLastGenericType">Dummy return type used as a last generic argument for actions. When omitted, typeof(object) is used.</param>
|
||||
public EzIPCEventAttribute(string? iPCName = null, bool applyPrefix = true, Type? actionLastGenericType = null)
|
||||
{
|
||||
IPCName = iPCName;
|
||||
ApplyPrefix = applyPrefix;
|
||||
ActionLastGenericType = actionLastGenericType ?? typeof(object);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,315 @@
|
||||
using Dalamud.Plugin.Ipc.Exceptions;
|
||||
using System;
|
||||
|
||||
namespace ECommonsLite.EzIpcManager;
|
||||
#pragma warning disable CS1573 // Parameter has no matching param tag in the XML comment (but other parameters do)
|
||||
public static class EzIPCExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Tries to invoke previously obtained action delegate via <see cref="EzIPC"/> safely. Does not throws <see cref="IpcNotReadyError"/>.
|
||||
/// </summary>
|
||||
/// <returns>Whether invocation did not throw <see cref="IpcNotReadyError"/></returns>
|
||||
public static bool TryInvoke<T1, T2, T3, T4, T5, T6, T7, T8>(this Action<T1, T2, T3, T4, T5, T6, T7, T8> action, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8)
|
||||
{
|
||||
try
|
||||
{
|
||||
action(a1, a2, a3, a4, a5, a6, a7, a8);
|
||||
return true;
|
||||
}
|
||||
catch(IpcNotReadyError)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Tries to invoke previously obtained action delegate via <see cref="EzIPC"/> safely. Does not throws <see cref="IpcNotReadyError"/>.
|
||||
/// </summary>
|
||||
/// <returns>Whether invocation did not throw <see cref="IpcNotReadyError"/></returns>
|
||||
public static bool TryInvoke<T1, T2, T3, T4, T5, T6, T7>(this Action<T1, T2, T3, T4, T5, T6, T7> action, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7)
|
||||
{
|
||||
try
|
||||
{
|
||||
action(a1, a2, a3, a4, a5, a6, a7);
|
||||
return true;
|
||||
}
|
||||
catch(IpcNotReadyError)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Tries to invoke previously obtained action delegate via <see cref="EzIPC"/> safely. Does not throws <see cref="IpcNotReadyError"/>.
|
||||
/// </summary>
|
||||
/// <returns>Whether invocation did not throw <see cref="IpcNotReadyError"/></returns>
|
||||
public static bool TryInvoke<T1, T2, T3, T4, T5, T6>(this Action<T1, T2, T3, T4, T5, T6> action, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6)
|
||||
{
|
||||
try
|
||||
{
|
||||
action(a1, a2, a3, a4, a5, a6);
|
||||
return true;
|
||||
}
|
||||
catch(IpcNotReadyError)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Tries to invoke previously obtained action delegate via <see cref="EzIPC"/> safely. Does not throws <see cref="IpcNotReadyError"/>.
|
||||
/// </summary>
|
||||
/// <returns>Whether invocation did not throw <see cref="IpcNotReadyError"/></returns>
|
||||
public static bool TryInvoke<T1, T2, T3, T4, T5>(this Action<T1, T2, T3, T4, T5> action, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5)
|
||||
{
|
||||
try
|
||||
{
|
||||
action(a1, a2, a3, a4, a5);
|
||||
return true;
|
||||
}
|
||||
catch(IpcNotReadyError)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Tries to invoke previously obtained action delegate via <see cref="EzIPC"/> safely. Does not throws <see cref="IpcNotReadyError"/>.
|
||||
/// </summary>
|
||||
/// <returns>Whether invocation did not throw <see cref="IpcNotReadyError"/></returns>
|
||||
public static bool TryInvoke<T1, T2, T3, T4>(this Action<T1, T2, T3, T4> action, T1 a1, T2 a2, T3 a3, T4 a4)
|
||||
{
|
||||
try
|
||||
{
|
||||
action(a1, a2, a3, a4);
|
||||
return true;
|
||||
}
|
||||
catch(IpcNotReadyError)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Tries to invoke previously obtained action delegate via <see cref="EzIPC"/> safely. Does not throws <see cref="IpcNotReadyError"/>.
|
||||
/// </summary>
|
||||
/// <returns>Whether invocation did not throw <see cref="IpcNotReadyError"/></returns>
|
||||
public static bool TryInvoke<T1, T2, T3>(this Action<T1, T2, T3> action, T1 a1, T2 a2, T3 a3)
|
||||
{
|
||||
try
|
||||
{
|
||||
action(a1, a2, a3);
|
||||
return true;
|
||||
}
|
||||
catch(IpcNotReadyError)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Tries to invoke previously obtained action delegate via <see cref="EzIPC"/> safely. Does not throws <see cref="IpcNotReadyError"/>.
|
||||
/// </summary>
|
||||
/// <returns>Whether invocation did not throw <see cref="IpcNotReadyError"/></returns>
|
||||
public static bool TryInvoke<T1, T2>(this Action<T1, T2> action, T1 a1, T2 a2)
|
||||
{
|
||||
try
|
||||
{
|
||||
action(a1, a2);
|
||||
return true;
|
||||
}
|
||||
catch(IpcNotReadyError)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Tries to invoke previously obtained action delegate via <see cref="EzIPC"/> safely. Does not throws <see cref="IpcNotReadyError"/>.
|
||||
/// </summary>
|
||||
/// <returns>Whether invocation did not throw <see cref="IpcNotReadyError"/></returns>
|
||||
public static bool TryInvoke<T1>(this Action<T1> action, T1 a1)
|
||||
{
|
||||
try
|
||||
{
|
||||
action(a1);
|
||||
return true;
|
||||
}
|
||||
catch(IpcNotReadyError)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Tries to invoke previously obtained action delegate via <see cref="EzIPC"/> safely. Does not throws <see cref="IpcNotReadyError"/>.
|
||||
/// </summary>
|
||||
/// <returns>Whether invocation did not throw <see cref="IpcNotReadyError"/></returns>
|
||||
public static bool TryInvoke(this Action action)
|
||||
{
|
||||
try
|
||||
{
|
||||
action();
|
||||
return true;
|
||||
}
|
||||
catch(IpcNotReadyError)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to invoke previously obtained function delegate via <see cref="EzIPC"/> safely. Does not throws <see cref="IpcNotReadyError"/>.
|
||||
/// </summary>
|
||||
/// <param name="ret">Result returned by a function if invocation succeeded</param>
|
||||
/// <returns>Whether invocation did not throw <see cref="IpcNotReadyError"/></returns>
|
||||
public static bool TryInvoke<T1, T2, T3, T4, T5, T6, T7, T8, TRet>(this Func<T1, T2, T3, T4, T5, T6, T7, T8, TRet> function, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, out TRet? ret)
|
||||
{
|
||||
try
|
||||
{
|
||||
ret = function(a1, a2, a3, a4, a5, a6, a7, a8);
|
||||
return true;
|
||||
}
|
||||
catch(IpcNotReadyError)
|
||||
{
|
||||
ret = default;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Tries to invoke previously obtained function delegate via <see cref="EzIPC"/> safely. Does not throws <see cref="IpcNotReadyError"/>.
|
||||
/// </summary>
|
||||
/// <param name="ret">Result returned by a function if invocation succeeded</param>
|
||||
/// <returns>Whether invocation did not throw <see cref="IpcNotReadyError"/></returns>
|
||||
public static bool TryInvoke<T1, T2, T3, T4, T5, T6, T7, TRet>(this Func<T1, T2, T3, T4, T5, T6, T7, TRet> function, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, out TRet? ret)
|
||||
{
|
||||
try
|
||||
{
|
||||
ret = function(a1, a2, a3, a4, a5, a6, a7);
|
||||
return true;
|
||||
}
|
||||
catch(IpcNotReadyError)
|
||||
{
|
||||
ret = default;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Tries to invoke previously obtained function delegate via <see cref="EzIPC"/> safely. Does not throws <see cref="IpcNotReadyError"/>.
|
||||
/// </summary>
|
||||
/// <param name="ret">Result returned by a function if invocation succeeded</param>
|
||||
/// <returns>Whether invocation did not throw <see cref="IpcNotReadyError"/></returns>
|
||||
public static bool TryInvoke<T1, T2, T3, T4, T5, T6, TRet>(this Func<T1, T2, T3, T4, T5, T6, TRet> function, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, out TRet? ret)
|
||||
{
|
||||
try
|
||||
{
|
||||
ret = function(a1, a2, a3, a4, a5, a6);
|
||||
return true;
|
||||
}
|
||||
catch(IpcNotReadyError)
|
||||
{
|
||||
ret = default;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Tries to invoke previously obtained function delegate via <see cref="EzIPC"/> safely. Does not throws <see cref="IpcNotReadyError"/>.
|
||||
/// </summary>
|
||||
/// <param name="ret">Result returned by a function if invocation succeeded</param>
|
||||
/// <returns>Whether invocation did not throw <see cref="IpcNotReadyError"/></returns>
|
||||
public static bool TryInvoke<T1, T2, T3, T4, T5, TRet>(this Func<T1, T2, T3, T4, T5, TRet> function, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, out TRet? ret)
|
||||
{
|
||||
try
|
||||
{
|
||||
ret = function(a1, a2, a3, a4, a5);
|
||||
return true;
|
||||
}
|
||||
catch(IpcNotReadyError)
|
||||
{
|
||||
ret = default;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Tries to invoke previously obtained function delegate via <see cref="EzIPC"/> safely. Does not throws <see cref="IpcNotReadyError"/>.
|
||||
/// </summary>
|
||||
/// <param name="ret">Result returned by a function if invocation succeeded</param>
|
||||
/// <returns>Whether invocation did not throw <see cref="IpcNotReadyError"/></returns>
|
||||
public static bool TryInvoke<T1, T2, T3, T4, TRet>(this Func<T1, T2, T3, T4, TRet> function, T1 a1, T2 a2, T3 a3, T4 a4, out TRet? ret)
|
||||
{
|
||||
try
|
||||
{
|
||||
ret = function(a1, a2, a3, a4);
|
||||
return true;
|
||||
}
|
||||
catch(IpcNotReadyError)
|
||||
{
|
||||
ret = default;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Tries to invoke previously obtained function delegate via <see cref="EzIPC"/> safely. Does not throws <see cref="IpcNotReadyError"/>.
|
||||
/// </summary>
|
||||
/// <param name="ret">Result returned by a function if invocation succeeded</param>
|
||||
/// <returns>Whether invocation did not throw <see cref="IpcNotReadyError"/></returns>
|
||||
public static bool TryInvoke<T1, T2, T3, TRet>(this Func<T1, T2, T3, TRet> function, T1 a1, T2 a2, T3 a3, out TRet? ret)
|
||||
{
|
||||
try
|
||||
{
|
||||
ret = function(a1, a2, a3);
|
||||
return true;
|
||||
}
|
||||
catch(IpcNotReadyError)
|
||||
{
|
||||
ret = default;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Tries to invoke previously obtained function delegate via <see cref="EzIPC"/> safely. Does not throws <see cref="IpcNotReadyError"/>.
|
||||
/// </summary>
|
||||
/// <param name="ret">Result returned by a function if invocation succeeded</param>
|
||||
/// <returns>Whether invocation did not throw <see cref="IpcNotReadyError"/></returns>
|
||||
public static bool TryInvoke<T1, T2, TRet>(this Func<T1, T2, TRet> function, T1 a1, T2 a2, out TRet? ret)
|
||||
{
|
||||
try
|
||||
{
|
||||
ret = function(a1, a2);
|
||||
return true;
|
||||
}
|
||||
catch(IpcNotReadyError)
|
||||
{
|
||||
ret = default;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Tries to invoke previously obtained function delegate via <see cref="EzIPC"/> safely. Does not throws <see cref="IpcNotReadyError"/>.
|
||||
/// </summary>
|
||||
/// <param name="ret">Result returned by a function if invocation succeeded</param>
|
||||
/// <returns>Whether invocation did not throw <see cref="IpcNotReadyError"/></returns>
|
||||
public static bool TryInvoke<T1, TRet>(this Func<T1, TRet> function, T1 a1, out TRet? ret)
|
||||
{
|
||||
try
|
||||
{
|
||||
ret = function(a1);
|
||||
return true;
|
||||
}
|
||||
catch(IpcNotReadyError)
|
||||
{
|
||||
ret = default;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Tries to invoke previously obtained function delegate via <see cref="EzIPC"/> safely. Does not throws <see cref="IpcNotReadyError"/>.
|
||||
/// </summary>
|
||||
/// <param name="ret">Result returned by a function if invocation succeeded</param>
|
||||
/// <returns>Whether invocation did not throw <see cref="IpcNotReadyError"/></returns>
|
||||
public static bool TryInvoke<TRet>(this Func<TRet> function, out TRet? ret)
|
||||
{
|
||||
try
|
||||
{
|
||||
ret = function();
|
||||
return true;
|
||||
}
|
||||
catch(IpcNotReadyError)
|
||||
{
|
||||
ret = default;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
using System.Reflection;
|
||||
|
||||
namespace ECommonsLite.EzIpcManager;
|
||||
[Obfuscation(Exclude = true)]
|
||||
public enum SafeWrapper
|
||||
{
|
||||
/// <summary>
|
||||
/// Directly call IPC, don't use any wrapper
|
||||
/// </summary>
|
||||
None,
|
||||
/// <summary>
|
||||
/// Only catch and discard IPCException
|
||||
/// </summary>
|
||||
IPCException,
|
||||
/// <summary>
|
||||
/// Catch and discard all exceptions
|
||||
/// </summary>
|
||||
AnyException,
|
||||
#pragma warning disable
|
||||
/// <summary>
|
||||
/// Inherit default setting from <see cref="EzIPC.Init"/> call
|
||||
/// </summary>
|
||||
#pragma warning restore
|
||||
Inherit = 255
|
||||
}
|
||||
@@ -0,0 +1,286 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
namespace ECommonsLite.EzIpcManager;
|
||||
#nullable disable
|
||||
[Obfuscation(Exclude = true)]
|
||||
internal static class SafeWrapperAny
|
||||
{
|
||||
internal class Wrapper<T1, T2, T3, T4, T5, T6, T7, T8, TRet>()
|
||||
{
|
||||
internal Action<T1, T2, T3, T4, T5, T6, T7, T8> Action;
|
||||
internal Func<T1, T2, T3, T4, T5, T6, T7, T8, TRet> Function;
|
||||
|
||||
internal void InvokeAction(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8)
|
||||
{
|
||||
try
|
||||
{
|
||||
Action(a1, a2, a3, a4, a5, a6, a7, a8);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
EzIPC.InvokeOnSafeInvocationException(e);
|
||||
}
|
||||
}
|
||||
internal TRet InvokeFunction(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Function(a1, a2, a3, a4, a5, a6, a7, a8);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
EzIPC.InvokeOnSafeInvocationException(e);
|
||||
}
|
||||
return default;
|
||||
}
|
||||
}
|
||||
|
||||
internal class Wrapper<T1, T2, T3, T4, T5, T6, T7, TRet>()
|
||||
{
|
||||
internal Action<T1, T2, T3, T4, T5, T6, T7> Action;
|
||||
internal Func<T1, T2, T3, T4, T5, T6, T7, TRet> Function;
|
||||
|
||||
internal void InvokeAction(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7)
|
||||
{
|
||||
try
|
||||
{
|
||||
Action(a1, a2, a3, a4, a5, a6, a7);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
EzIPC.InvokeOnSafeInvocationException(e);
|
||||
}
|
||||
}
|
||||
|
||||
internal TRet InvokeFunction(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Function(a1, a2, a3, a4, a5, a6, a7);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
EzIPC.InvokeOnSafeInvocationException(e);
|
||||
}
|
||||
return default;
|
||||
}
|
||||
}
|
||||
|
||||
internal class Wrapper<T1, T2, T3, T4, T5, T6, TRet>()
|
||||
{
|
||||
internal Action<T1, T2, T3, T4, T5, T6> Action;
|
||||
internal Func<T1, T2, T3, T4, T5, T6, TRet> Function;
|
||||
|
||||
internal void InvokeAction(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6)
|
||||
{
|
||||
try
|
||||
{
|
||||
Action(a1, a2, a3, a4, a5, a6);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
EzIPC.InvokeOnSafeInvocationException(e);
|
||||
}
|
||||
}
|
||||
|
||||
internal TRet InvokeFunction(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Function(a1, a2, a3, a4, a5, a6);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
EzIPC.InvokeOnSafeInvocationException(e);
|
||||
}
|
||||
return default;
|
||||
}
|
||||
}
|
||||
|
||||
internal class Wrapper<T1, T2, T3, T4, T5, TRet>()
|
||||
{
|
||||
internal Action<T1, T2, T3, T4, T5> Action;
|
||||
internal Func<T1, T2, T3, T4, T5, TRet> Function;
|
||||
|
||||
internal void InvokeAction(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5)
|
||||
{
|
||||
try
|
||||
{
|
||||
Action(a1, a2, a3, a4, a5);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
EzIPC.InvokeOnSafeInvocationException(e);
|
||||
}
|
||||
}
|
||||
|
||||
internal TRet InvokeFunction(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Function(a1, a2, a3, a4, a5);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
EzIPC.InvokeOnSafeInvocationException(e);
|
||||
}
|
||||
return default;
|
||||
}
|
||||
}
|
||||
|
||||
internal class Wrapper<T1, T2, T3, T4, TRet>()
|
||||
{
|
||||
internal Action<T1, T2, T3, T4> Action;
|
||||
internal Func<T1, T2, T3, T4, TRet> Function;
|
||||
|
||||
internal void InvokeAction(T1 a1, T2 a2, T3 a3, T4 a4)
|
||||
{
|
||||
try
|
||||
{
|
||||
Action(a1, a2, a3, a4);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
EzIPC.InvokeOnSafeInvocationException(e);
|
||||
}
|
||||
}
|
||||
|
||||
internal TRet InvokeFunction(T1 a1, T2 a2, T3 a3, T4 a4)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Function(a1, a2, a3, a4);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
EzIPC.InvokeOnSafeInvocationException(e);
|
||||
}
|
||||
return default;
|
||||
}
|
||||
}
|
||||
|
||||
internal class Wrapper<T1, T2, T3, TRet>()
|
||||
{
|
||||
internal Action<T1, T2, T3> Action;
|
||||
internal Func<T1, T2, T3, TRet> Function;
|
||||
|
||||
internal void InvokeAction(T1 a1, T2 a2, T3 a3)
|
||||
{
|
||||
try
|
||||
{
|
||||
Action(a1, a2, a3);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
EzIPC.InvokeOnSafeInvocationException(e);
|
||||
}
|
||||
}
|
||||
|
||||
internal TRet InvokeFunction(T1 a1, T2 a2, T3 a3)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Function(a1, a2, a3);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
EzIPC.InvokeOnSafeInvocationException(e);
|
||||
}
|
||||
return default;
|
||||
}
|
||||
}
|
||||
|
||||
internal class Wrapper<T1, T2, TRet>()
|
||||
{
|
||||
internal Action<T1, T2> Action;
|
||||
internal Func<T1, T2, TRet> Function;
|
||||
|
||||
internal void InvokeAction(T1 a1, T2 a2)
|
||||
{
|
||||
try
|
||||
{
|
||||
Action(a1, a2);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
EzIPC.InvokeOnSafeInvocationException(e);
|
||||
}
|
||||
}
|
||||
|
||||
internal TRet InvokeFunction(T1 a1, T2 a2)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Function(a1, a2);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
EzIPC.InvokeOnSafeInvocationException(e);
|
||||
}
|
||||
return default;
|
||||
}
|
||||
}
|
||||
|
||||
internal class Wrapper<T1, TRet>()
|
||||
{
|
||||
internal Action<T1> Action;
|
||||
internal Func<T1, TRet> Function;
|
||||
|
||||
internal void InvokeAction(T1 a1)
|
||||
{
|
||||
try
|
||||
{
|
||||
Action(a1);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
EzIPC.InvokeOnSafeInvocationException(e);
|
||||
}
|
||||
}
|
||||
|
||||
internal TRet InvokeFunction(T1 a1)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Function(a1);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
EzIPC.InvokeOnSafeInvocationException(e);
|
||||
}
|
||||
return default;
|
||||
}
|
||||
}
|
||||
|
||||
internal class Wrapper<TRet>()
|
||||
{
|
||||
internal Action Action;
|
||||
internal Func<TRet> Function;
|
||||
|
||||
internal void InvokeAction()
|
||||
{
|
||||
try
|
||||
{
|
||||
Action();
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
EzIPC.InvokeOnSafeInvocationException(e);
|
||||
}
|
||||
}
|
||||
|
||||
internal TRet InvokeFunction()
|
||||
{
|
||||
try
|
||||
{
|
||||
return Function();
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
EzIPC.InvokeOnSafeInvocationException(e);
|
||||
}
|
||||
return default;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,287 @@
|
||||
using Dalamud.Plugin.Ipc.Exceptions;
|
||||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
namespace ECommonsLite.EzIpcManager;
|
||||
#nullable disable
|
||||
[Obfuscation(Exclude = true)]
|
||||
internal static class SafeWrapperIPC
|
||||
{
|
||||
internal class Wrapper<T1, T2, T3, T4, T5, T6, T7, T8, TRet>()
|
||||
{
|
||||
internal Action<T1, T2, T3, T4, T5, T6, T7, T8> Action;
|
||||
internal Func<T1, T2, T3, T4, T5, T6, T7, T8, TRet> Function;
|
||||
|
||||
internal void InvokeAction(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8)
|
||||
{
|
||||
try
|
||||
{
|
||||
Action(a1, a2, a3, a4, a5, a6, a7, a8);
|
||||
}
|
||||
catch(IpcNotReadyError e)
|
||||
{
|
||||
EzIPC.InvokeOnSafeInvocationException(e);
|
||||
}
|
||||
}
|
||||
internal TRet InvokeFunction(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Function(a1, a2, a3, a4, a5, a6, a7, a8);
|
||||
}
|
||||
catch(IpcNotReadyError e)
|
||||
{
|
||||
EzIPC.InvokeOnSafeInvocationException(e);
|
||||
}
|
||||
return default;
|
||||
}
|
||||
}
|
||||
|
||||
internal class Wrapper<T1, T2, T3, T4, T5, T6, T7, TRet>()
|
||||
{
|
||||
internal Action<T1, T2, T3, T4, T5, T6, T7> Action;
|
||||
internal Func<T1, T2, T3, T4, T5, T6, T7, TRet> Function;
|
||||
|
||||
internal void InvokeAction(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7)
|
||||
{
|
||||
try
|
||||
{
|
||||
Action(a1, a2, a3, a4, a5, a6, a7);
|
||||
}
|
||||
catch(IpcNotReadyError e)
|
||||
{
|
||||
EzIPC.InvokeOnSafeInvocationException(e);
|
||||
}
|
||||
}
|
||||
|
||||
internal TRet InvokeFunction(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Function(a1, a2, a3, a4, a5, a6, a7);
|
||||
}
|
||||
catch(IpcNotReadyError e)
|
||||
{
|
||||
EzIPC.InvokeOnSafeInvocationException(e);
|
||||
}
|
||||
return default;
|
||||
}
|
||||
}
|
||||
|
||||
internal class Wrapper<T1, T2, T3, T4, T5, T6, TRet>()
|
||||
{
|
||||
internal Action<T1, T2, T3, T4, T5, T6> Action;
|
||||
internal Func<T1, T2, T3, T4, T5, T6, TRet> Function;
|
||||
|
||||
internal void InvokeAction(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6)
|
||||
{
|
||||
try
|
||||
{
|
||||
Action(a1, a2, a3, a4, a5, a6);
|
||||
}
|
||||
catch(IpcNotReadyError e)
|
||||
{
|
||||
EzIPC.InvokeOnSafeInvocationException(e);
|
||||
}
|
||||
}
|
||||
|
||||
internal TRet InvokeFunction(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Function(a1, a2, a3, a4, a5, a6);
|
||||
}
|
||||
catch(IpcNotReadyError e)
|
||||
{
|
||||
EzIPC.InvokeOnSafeInvocationException(e);
|
||||
}
|
||||
return default;
|
||||
}
|
||||
}
|
||||
|
||||
internal class Wrapper<T1, T2, T3, T4, T5, TRet>()
|
||||
{
|
||||
internal Action<T1, T2, T3, T4, T5> Action;
|
||||
internal Func<T1, T2, T3, T4, T5, TRet> Function;
|
||||
|
||||
internal void InvokeAction(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5)
|
||||
{
|
||||
try
|
||||
{
|
||||
Action(a1, a2, a3, a4, a5);
|
||||
}
|
||||
catch(IpcNotReadyError e)
|
||||
{
|
||||
EzIPC.InvokeOnSafeInvocationException(e);
|
||||
}
|
||||
}
|
||||
|
||||
internal TRet InvokeFunction(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Function(a1, a2, a3, a4, a5);
|
||||
}
|
||||
catch(IpcNotReadyError e)
|
||||
{
|
||||
EzIPC.InvokeOnSafeInvocationException(e);
|
||||
}
|
||||
return default;
|
||||
}
|
||||
}
|
||||
|
||||
internal class Wrapper<T1, T2, T3, T4, TRet>()
|
||||
{
|
||||
internal Action<T1, T2, T3, T4> Action;
|
||||
internal Func<T1, T2, T3, T4, TRet> Function;
|
||||
|
||||
internal void InvokeAction(T1 a1, T2 a2, T3 a3, T4 a4)
|
||||
{
|
||||
try
|
||||
{
|
||||
Action(a1, a2, a3, a4);
|
||||
}
|
||||
catch(IpcNotReadyError e)
|
||||
{
|
||||
EzIPC.InvokeOnSafeInvocationException(e);
|
||||
}
|
||||
}
|
||||
|
||||
internal TRet InvokeFunction(T1 a1, T2 a2, T3 a3, T4 a4)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Function(a1, a2, a3, a4);
|
||||
}
|
||||
catch(IpcNotReadyError e)
|
||||
{
|
||||
EzIPC.InvokeOnSafeInvocationException(e);
|
||||
}
|
||||
return default;
|
||||
}
|
||||
}
|
||||
|
||||
internal class Wrapper<T1, T2, T3, TRet>()
|
||||
{
|
||||
internal Action<T1, T2, T3> Action;
|
||||
internal Func<T1, T2, T3, TRet> Function;
|
||||
|
||||
internal void InvokeAction(T1 a1, T2 a2, T3 a3)
|
||||
{
|
||||
try
|
||||
{
|
||||
Action(a1, a2, a3);
|
||||
}
|
||||
catch(IpcNotReadyError e)
|
||||
{
|
||||
EzIPC.InvokeOnSafeInvocationException(e);
|
||||
}
|
||||
}
|
||||
|
||||
internal TRet InvokeFunction(T1 a1, T2 a2, T3 a3)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Function(a1, a2, a3);
|
||||
}
|
||||
catch(IpcNotReadyError e)
|
||||
{
|
||||
EzIPC.InvokeOnSafeInvocationException(e);
|
||||
}
|
||||
return default;
|
||||
}
|
||||
}
|
||||
|
||||
internal class Wrapper<T1, T2, TRet>()
|
||||
{
|
||||
internal Action<T1, T2> Action;
|
||||
internal Func<T1, T2, TRet> Function;
|
||||
|
||||
internal void InvokeAction(T1 a1, T2 a2)
|
||||
{
|
||||
try
|
||||
{
|
||||
Action(a1, a2);
|
||||
}
|
||||
catch(IpcNotReadyError e)
|
||||
{
|
||||
EzIPC.InvokeOnSafeInvocationException(e);
|
||||
}
|
||||
}
|
||||
|
||||
internal TRet InvokeFunction(T1 a1, T2 a2)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Function(a1, a2);
|
||||
}
|
||||
catch(IpcNotReadyError e)
|
||||
{
|
||||
EzIPC.InvokeOnSafeInvocationException(e);
|
||||
}
|
||||
return default;
|
||||
}
|
||||
}
|
||||
|
||||
internal class Wrapper<T1, TRet>()
|
||||
{
|
||||
internal Action<T1> Action;
|
||||
internal Func<T1, TRet> Function;
|
||||
|
||||
internal void InvokeAction(T1 a1)
|
||||
{
|
||||
try
|
||||
{
|
||||
Action(a1);
|
||||
}
|
||||
catch(IpcNotReadyError e)
|
||||
{
|
||||
EzIPC.InvokeOnSafeInvocationException(e);
|
||||
}
|
||||
}
|
||||
|
||||
internal TRet InvokeFunction(T1 a1)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Function(a1);
|
||||
}
|
||||
catch(IpcNotReadyError e)
|
||||
{
|
||||
EzIPC.InvokeOnSafeInvocationException(e);
|
||||
}
|
||||
return default;
|
||||
}
|
||||
}
|
||||
|
||||
internal class Wrapper<TRet>()
|
||||
{
|
||||
internal Action Action;
|
||||
internal Func<TRet> Function;
|
||||
|
||||
internal void InvokeAction()
|
||||
{
|
||||
try
|
||||
{
|
||||
Action();
|
||||
}
|
||||
catch(IpcNotReadyError e)
|
||||
{
|
||||
EzIPC.InvokeOnSafeInvocationException(e);
|
||||
}
|
||||
}
|
||||
|
||||
internal TRet InvokeFunction()
|
||||
{
|
||||
try
|
||||
{
|
||||
return Function();
|
||||
}
|
||||
catch(IpcNotReadyError e)
|
||||
{
|
||||
EzIPC.InvokeOnSafeInvocationException(e);
|
||||
}
|
||||
return default;
|
||||
}
|
||||
}
|
||||
}
|
||||
36
submodules/ECommonsLite/ECommonsLite/GenericHelpers.cs
Normal file
36
submodules/ECommonsLite/ECommonsLite/GenericHelpers.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using Dalamud.Game.Text.SeStringHandling;
|
||||
using ECommonsLite.Logging;
|
||||
using FFXIVClientStructs.FFXIV.Client.System.String;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
#nullable disable
|
||||
|
||||
namespace ECommonsLite;
|
||||
|
||||
public static unsafe partial class GenericHelpers
|
||||
{
|
||||
public static void Log(this Exception e)
|
||||
{
|
||||
PluginLog.Error($"{e.Message}\n{e.StackTrace ?? ""}");
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static bool EqualsAny<T>(this T obj, params T[] values)
|
||||
{
|
||||
return values.Any(x => x.Equals(obj));
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void Safe(System.Action a, bool suppressErrors = false)
|
||||
{
|
||||
try
|
||||
{
|
||||
a();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (!suppressErrors) PluginLog.Error($"{e.Message}\n{e.StackTrace ?? ""}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using System;
|
||||
using System.Numerics;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using Action = System.Action;
|
||||
|
||||
namespace ECommonsLite.ImGuiMethods;
|
||||
#nullable disable
|
||||
|
||||
public static unsafe partial class ImGuiEx
|
||||
{
|
||||
public static void EzTabBar(string id, params (string name, Action function, Vector4? color, bool child)[] tabs) => EzTabBar(id, null, tabs);
|
||||
public static void EzTabBar(string id, string KoFiTransparent, params (string name, Action function, Vector4? color, bool child)[] tabs) => EzTabBar(id, KoFiTransparent, null, tabs);
|
||||
public static void EzTabBar(string id, string KoFiTransparent, string openTabName, params (string name, Action function, Vector4? color, bool child)[] tabs) => EzTabBar(id, KoFiTransparent, openTabName, ImGuiTabBarFlags.None, tabs);
|
||||
public static void EzTabBar(string id, string KoFiTransparent, string openTabName, ImGuiTabBarFlags flags, params (string name, Action function, Vector4? color, bool child)[] tabs)
|
||||
{
|
||||
ImGui.BeginTabBar(id, flags);
|
||||
foreach (var x in tabs)
|
||||
{
|
||||
if (x.name == null) continue;
|
||||
if (x.color != null)
|
||||
{
|
||||
ImGui.PushStyleColor(ImGuiCol.Text, x.color.Value);
|
||||
}
|
||||
if (ImGui.BeginTabItem(x.name, openTabName == x.name ? ImGuiTabItemFlags.SetSelected : ImGuiTabItemFlags.None))
|
||||
{
|
||||
if (x.color != null)
|
||||
{
|
||||
ImGui.PopStyleColor();
|
||||
}
|
||||
if (x.child) ImGui.BeginChild(x.name + "child");
|
||||
x.function();
|
||||
if (x.child) ImGui.EndChild();
|
||||
ImGui.EndTabItem();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (x.color != null)
|
||||
{
|
||||
ImGui.PopStyleColor();
|
||||
}
|
||||
}
|
||||
}
|
||||
//if (KoFiTransparent != null) PatreonBanner.RightTransparentTab();
|
||||
ImGui.EndTabBar();
|
||||
}
|
||||
|
||||
public static unsafe bool BeginTabItem(string label, ImGuiTabItemFlags flags)
|
||||
{
|
||||
throw new NotImplementedException("Switch to using ImGui.BeginTabItem. It now has version without \"close\".");
|
||||
}
|
||||
internal static unsafe byte* Allocate(int byteCount)
|
||||
{
|
||||
return (byte*)(void*)Marshal.AllocHGlobal(byteCount);
|
||||
}
|
||||
|
||||
internal static unsafe void Free(byte* ptr)
|
||||
{
|
||||
Marshal.FreeHGlobal((IntPtr)ptr);
|
||||
}
|
||||
|
||||
internal static unsafe int GetUtf8(string s, byte* utf8Bytes, int utf8ByteCount)
|
||||
{
|
||||
fixed (char* chars = s)
|
||||
{
|
||||
return Encoding.UTF8.GetBytes(chars, s.Length, utf8Bytes, utf8ByteCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
61
submodules/ECommonsLite/ECommonsLite/Logging/PluginLog.cs
Normal file
61
submodules/ECommonsLite/ECommonsLite/Logging/PluginLog.cs
Normal file
@@ -0,0 +1,61 @@
|
||||
using ECommonsLite.DalamudServices;
|
||||
using Serilog.Events;
|
||||
|
||||
namespace ECommonsLite.Logging;
|
||||
|
||||
public static class PluginLog
|
||||
{
|
||||
|
||||
public static void Information(string s)
|
||||
{
|
||||
Svc.Log.Information($"{s}");
|
||||
}
|
||||
public static void Error(string s)
|
||||
{
|
||||
Svc.Log.Error($"{s}");
|
||||
}
|
||||
public static void Fatal(string s)
|
||||
{
|
||||
Svc.Log.Fatal($"{s}");
|
||||
}
|
||||
public static void Debug(string s)
|
||||
{
|
||||
Svc.Log.Debug($"{s}");
|
||||
}
|
||||
public static void Verbose(string s)
|
||||
{
|
||||
Svc.Log.Verbose($"{s}");
|
||||
}
|
||||
public static void Warning(string s)
|
||||
{
|
||||
Svc.Log.Warning($"{s}");
|
||||
}
|
||||
public static void LogInformation(string s)
|
||||
{
|
||||
Information(s);
|
||||
}
|
||||
public static void LogError(string s)
|
||||
{
|
||||
Error(s);
|
||||
}
|
||||
public static void LogFatal(string s)
|
||||
{
|
||||
Fatal(s);
|
||||
}
|
||||
public static void LogDebug(string s)
|
||||
{
|
||||
Debug(s);
|
||||
}
|
||||
public static void LogVerbose(string s)
|
||||
{
|
||||
Verbose(s);
|
||||
}
|
||||
public static void LogWarning(string s)
|
||||
{
|
||||
Warning(s);
|
||||
}
|
||||
public static void Log(string s)
|
||||
{
|
||||
Information(s);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Reflection;
|
||||
|
||||
namespace ECommonsLite.Reflection.FieldPropertyUnion;
|
||||
/// <summary>
|
||||
/// Interface that represents union of FieldInfo and PropertyInfo. Allows access to common methods and properties.
|
||||
/// </summary>
|
||||
public interface IFieldPropertyUnion
|
||||
{
|
||||
public Type UnionType { get; }
|
||||
public bool IsSpecialName { get; }
|
||||
public object? GetRawConstantValue();
|
||||
public object? GetValue(object? obj);
|
||||
public void SetValue(object? obj, object? value);
|
||||
public void SetValue(object? obj, object? value, BindingFlags invokeAttr, Binder? binder, CultureInfo? culture);
|
||||
|
||||
//MemberInfo
|
||||
public string Name { get; }
|
||||
public MemberTypes MemberType { get; }
|
||||
public Type? DeclaringType { get; }
|
||||
public Type? ReflectedType { get; }
|
||||
public System.Reflection.Module Module { get; }
|
||||
public bool IsDefined(Type attributeType, bool inherit);
|
||||
public object[] GetCustomAttributes(bool inherit);
|
||||
public object[] GetCustomAttributes(Type attributeType, bool inherit);
|
||||
public T? GetCustomAttribute<T>() where T : Attribute;
|
||||
public IEnumerable<T> GetCustomAttributes<T>() where T : Attribute;
|
||||
|
||||
public IEnumerable<CustomAttributeData> CustomAttributes { get; }
|
||||
public bool IsCollectible { get; }
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Reflection;
|
||||
|
||||
namespace ECommonsLite.Reflection.FieldPropertyUnion;
|
||||
public class UnionField : IFieldPropertyUnion
|
||||
{
|
||||
public readonly FieldInfo FieldInfo;
|
||||
public UnionField(FieldInfo fieldInfo)
|
||||
{
|
||||
FieldInfo = fieldInfo;
|
||||
}
|
||||
|
||||
public string Name => FieldInfo.Name;
|
||||
|
||||
public Type UnionType => FieldInfo.FieldType;
|
||||
|
||||
public Type? DeclaringType => FieldInfo.DeclaringType;
|
||||
|
||||
public MemberTypes MemberType => FieldInfo.MemberType;
|
||||
|
||||
public Type? ReflectedType => FieldInfo.ReflectedType;
|
||||
|
||||
public bool IsSpecialName => FieldInfo.IsSpecialName;
|
||||
|
||||
public System.Reflection.Module Module => FieldInfo.Module;
|
||||
|
||||
public IEnumerable<CustomAttributeData> CustomAttributes => FieldInfo.CustomAttributes;
|
||||
|
||||
public bool IsCollectible => FieldInfo.IsCollectible;
|
||||
|
||||
public object[] GetCustomAttributes(bool inherit) => FieldInfo.GetCustomAttributes(inherit);
|
||||
|
||||
public object[] GetCustomAttributes(Type attributeType, bool inherit) => FieldInfo.GetCustomAttributes(attributeType, inherit);
|
||||
|
||||
public T? GetCustomAttribute<T>() where T : Attribute => FieldInfo.GetCustomAttribute<T>();
|
||||
public IEnumerable<T> GetCustomAttributes<T>() where T : Attribute => FieldInfo.GetCustomAttributes<T>();
|
||||
|
||||
public object? GetRawConstantValue() => FieldInfo.GetRawConstantValue();
|
||||
|
||||
public object? GetValue(object? obj) => FieldInfo.GetValue(obj);
|
||||
|
||||
public bool IsDefined(Type attributeType, bool inherit) => FieldInfo.IsDefined(attributeType, inherit);
|
||||
|
||||
public void SetValue(object? obj, object? value) => FieldInfo.SetValue(obj, value);
|
||||
|
||||
public void SetValue(object? obj, object? value, BindingFlags invokeAttr, Binder? binder, CultureInfo? culture) => FieldInfo.SetValue(obj, value, invokeAttr, binder, culture);
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Reflection;
|
||||
|
||||
namespace ECommonsLite.Reflection.FieldPropertyUnion;
|
||||
public class UnionProperty : IFieldPropertyUnion
|
||||
{
|
||||
public readonly PropertyInfo PropertyInfo;
|
||||
public UnionProperty(PropertyInfo propertyInfo)
|
||||
{
|
||||
PropertyInfo = propertyInfo;
|
||||
}
|
||||
|
||||
public string Name => PropertyInfo.Name;
|
||||
|
||||
public Type UnionType => PropertyInfo.PropertyType;
|
||||
|
||||
public Type? DeclaringType => PropertyInfo.DeclaringType;
|
||||
|
||||
public MemberTypes MemberType => PropertyInfo.MemberType;
|
||||
|
||||
public Type? ReflectedType => PropertyInfo.ReflectedType;
|
||||
|
||||
public bool IsSpecialName => PropertyInfo.IsSpecialName;
|
||||
|
||||
public System.Reflection.Module Module => PropertyInfo.Module;
|
||||
|
||||
public IEnumerable<CustomAttributeData> CustomAttributes => PropertyInfo.CustomAttributes;
|
||||
|
||||
public bool IsCollectible => PropertyInfo.IsCollectible;
|
||||
|
||||
public object[] GetCustomAttributes(bool inherit) => PropertyInfo.GetCustomAttributes(inherit);
|
||||
|
||||
public object[] GetCustomAttributes(Type attributeType, bool inherit) => PropertyInfo.GetCustomAttributes(attributeType, inherit);
|
||||
public T? GetCustomAttribute<T>() where T : Attribute => PropertyInfo.GetCustomAttribute<T>();
|
||||
public IEnumerable<T> GetCustomAttributes<T>() where T : Attribute => PropertyInfo.GetCustomAttributes<T>();
|
||||
|
||||
public object? GetRawConstantValue() => PropertyInfo.GetRawConstantValue();
|
||||
|
||||
public object? GetValue(object? obj) => PropertyInfo.GetValue(obj);
|
||||
|
||||
public bool IsDefined(Type attributeType, bool inherit) => PropertyInfo.IsDefined(attributeType, inherit);
|
||||
|
||||
public void SetValue(object? obj, object? value) => PropertyInfo.SetValue(obj, value);
|
||||
|
||||
public void SetValue(object? obj, object? value, BindingFlags invokeAttr, Binder? binder, CultureInfo? culture) => PropertyInfo.SetValue(obj, value, invokeAttr, binder, null, culture);
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace ECommonsLite.Reflection;
|
||||
#nullable disable
|
||||
|
||||
public static partial class ReflectionHelper
|
||||
{
|
||||
public const BindingFlags AllFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static;
|
||||
public const BindingFlags StaticFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static;
|
||||
public const BindingFlags InstanceFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
|
||||
|
||||
/// <summary>
|
||||
/// Gets field or property of an instance object.
|
||||
/// </summary>
|
||||
/// <param name="obj">Instance containing field/property.</param>
|
||||
/// <param name="name">Name of the field/property</param>
|
||||
/// <returns>Value of a field/property</returns>
|
||||
public static object GetFoP(this object obj, string name)
|
||||
{
|
||||
return obj.GetType().GetField(name, AllFlags)?.GetValue(obj)
|
||||
?? obj.GetType().GetProperty(name, AllFlags)?.GetValue(obj);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets field or property of an instance object.
|
||||
/// </summary>
|
||||
/// <param name="obj">Instance containing field/property.</param>
|
||||
/// <param name="name">Name of the field/property</param>
|
||||
/// <returns>Value of a field/property</returns>
|
||||
public static T GetFoP<T>(this object obj, string name)
|
||||
{
|
||||
return (T)GetFoP(obj, name);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets a field or property of an instance object.
|
||||
/// </summary>
|
||||
/// <param name="obj">Instance containing field/property.</param>
|
||||
/// <param name="name">Name of the field/property</param>
|
||||
/// <param name="value">Value to set</param>
|
||||
public static void SetFoP(this object obj, string name, object value)
|
||||
{
|
||||
var field = obj.GetType().GetField(name, AllFlags);
|
||||
if(field != null)
|
||||
{
|
||||
field.SetValue(obj, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
obj.GetType().GetProperty(name, AllFlags).SetValue(obj, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Subject for future refactoring and changes!
|
||||
/// </summary>
|
||||
public static object GetStaticFoP(this object obj, string type, string name)
|
||||
{
|
||||
return obj.GetType().Assembly.GetType(type).GetField(name, StaticFlags)?.GetValue(null)
|
||||
?? obj.GetType().Assembly.GetType(type).GetProperty(name, StaticFlags)?.GetValue(null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Subject for future refactoring and changes!
|
||||
/// </summary>
|
||||
public static T GetStaticFoP<T>(this object obj, string type, string name)
|
||||
{
|
||||
return (T)GetStaticFoP(obj, type, name);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Subject for future refactoring and changes!
|
||||
/// </summary>
|
||||
public static void SetStaticFoP(this object obj, string type, string name, object value)
|
||||
{
|
||||
var field = obj.GetType().Assembly.GetType(type).GetField(name, StaticFlags);
|
||||
if(field != null)
|
||||
{
|
||||
field.SetValue(null, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
obj.GetType().Assembly.GetType(type).GetProperty(name, StaticFlags).SetValue(null, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to call a non-generic instance method.
|
||||
/// </summary>
|
||||
/// <param name="obj">Instance containing method</param>
|
||||
/// <param name="name">Method's name</param>
|
||||
/// <param name="params">Method's parameters</param>
|
||||
/// <param name="matchExactArgumentTypes">Whether to search for exact method types. Set this to true if you're dealing with ambiguous overloads.</param>
|
||||
/// <returns>Object returned by the target method</returns>
|
||||
public static object Call(this object obj, string name, object[] @params, bool matchExactArgumentTypes = false)
|
||||
{
|
||||
MethodInfo info;
|
||||
if(!matchExactArgumentTypes)
|
||||
{
|
||||
info = obj.GetType().GetMethod(name, AllFlags);
|
||||
}
|
||||
else
|
||||
{
|
||||
info = obj.GetType().GetMethod(name, AllFlags, @params.Select(x => x.GetType()).ToArray());
|
||||
}
|
||||
return info.Invoke(obj, @params);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to call a non-generic instance method.
|
||||
/// </summary>
|
||||
/// <param name="obj">Instance containing method</param>
|
||||
/// <param name="name">Method's name</param>
|
||||
/// <param name="params">Method's parameters</param>
|
||||
/// <param name="matchExactArgumentTypes">Whether to search for exact method types. Set this to true if you're dealing with ambiguous overloads.</param>
|
||||
/// <returns>Object returned by the target method</returns>
|
||||
public static T Call<T>(this object obj, string name, object[] @params, bool matchExactArgumentTypes = false)
|
||||
{
|
||||
return (T)Call(obj, name, @params, matchExactArgumentTypes);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,187 @@
|
||||
using ECommonsLite.Reflection.FieldPropertyUnion;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace ECommonsLite.Reflection;
|
||||
#nullable disable
|
||||
public static partial class ReflectionHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// Searches for a static method in the array of assemblies.
|
||||
/// </summary>
|
||||
/// <param name="assemblies">Assemblies to search in</param>
|
||||
/// <param name="typeName">Fully qualified class name</param>
|
||||
/// <param name="typeArguments">Type arguments, if necessary. Leave as null if type is non-generic.</param>
|
||||
/// <param name="methodName">Static method name</param>
|
||||
/// <param name="methodTypeArguments">Method type arguments, if necessary. Leave as null if method is non-generic.</param>
|
||||
/// <param name="parameterTypes">Method parameters types.</param>
|
||||
/// <returns>MethodInfo of a method that was found or null.</returns>
|
||||
public static MethodInfo FindStaticMethodInAssemblies(IEnumerable<Assembly> assemblies, string typeName, Type[] typeArguments, string methodName, Type[] methodTypeArguments, Type[] parameterTypes)
|
||||
{
|
||||
MethodInfo methodInfo = null;
|
||||
foreach(var t in FindTypesInAssemblies(assemblies, [(typeName, typeArguments)]))
|
||||
{
|
||||
if(t != null)
|
||||
{
|
||||
methodInfo = t.GetMethod(methodName, AllFlags, parameterTypes);
|
||||
if(methodInfo != null)
|
||||
{
|
||||
if(methodTypeArguments != null && methodTypeArguments.Length > 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
methodInfo = methodInfo.MakeGenericMethod(methodTypeArguments);
|
||||
}
|
||||
catch(Exception)
|
||||
{
|
||||
methodInfo = null;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return methodInfo;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Searches for specified non-generic types in specified assembly list.
|
||||
/// </summary>
|
||||
/// <param name="assemblies">Assemblies to search in</param>
|
||||
/// <param name="typeNames">A list of requested types names</param>
|
||||
/// <returns>A list of requested types. Please check resulting list length to ensure all types were found.</returns>
|
||||
public static List<Type> FindTypesInAssemblies(IEnumerable<Assembly> assemblies, IEnumerable<string> typeNames)
|
||||
{
|
||||
var genericArgs = new List<Type>();
|
||||
foreach(var x in typeNames)
|
||||
{
|
||||
foreach(var a in assemblies)
|
||||
{
|
||||
var type = a.GetType(x, false);
|
||||
if(type != null)
|
||||
{
|
||||
genericArgs.Add(type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return genericArgs;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Searches for specified generic and non-generic types in specified assembly list.
|
||||
/// </summary>
|
||||
/// <param name="assemblies">Assemblies to search in</param>
|
||||
/// <param name="typeNames">A list of tuples of requested types names and generic argument types. Array of types can be left empty or null to specify that this type is non-generic.</param>
|
||||
/// <returns>A list of requested types. Please check resulting list length to ensure all types were found.</returns>
|
||||
public static List<Type> FindTypesInAssemblies(IEnumerable<Assembly> assemblies, IEnumerable<(string TypeName, Type[] TypeArguments)> typeNames)
|
||||
{
|
||||
var genericArgs = new List<Type>();
|
||||
foreach(var x in typeNames)
|
||||
{
|
||||
foreach(var a in assemblies)
|
||||
{
|
||||
var type = a.GetType(x.TypeName, false);
|
||||
if(type != null)
|
||||
{
|
||||
if(x.TypeArguments != null && x.TypeArguments.Length > 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
type = type.MakeGenericType(x.TypeArguments);
|
||||
genericArgs.Add(type);
|
||||
}
|
||||
catch(Exception)
|
||||
{
|
||||
type = null;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
genericArgs.Add(type);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return genericArgs;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts array of objects into array of these objects' types.
|
||||
/// </summary>
|
||||
/// <param name="objects"></param>
|
||||
/// <returns></returns>
|
||||
public static Type[] GetTypes(this IEnumerable<object> objects)
|
||||
{
|
||||
return objects.Select(x => x.GetType()).ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates delegate to a method by MethodInfo
|
||||
/// </summary>
|
||||
/// <param name="methodInfo">MethodInfo of a method for which a delegate will be created.</param>
|
||||
/// <param name="target">Instance object that is hosting the method. Pass null if a method is static.</param>
|
||||
/// <returns></returns>
|
||||
public static Delegate CreateDelegate(MethodInfo methodInfo, object target)
|
||||
{
|
||||
Func<Type[], Type> getType;
|
||||
var isAction = methodInfo.ReturnType.Equals((typeof(void)));
|
||||
var types = methodInfo.GetParameters().Select(p => p.ParameterType);
|
||||
|
||||
if(isAction)
|
||||
{
|
||||
getType = Expression.GetActionType;
|
||||
}
|
||||
else
|
||||
{
|
||||
getType = Expression.GetFuncType;
|
||||
types = types.Concat(new[] { methodInfo.ReturnType });
|
||||
}
|
||||
|
||||
if(methodInfo.IsStatic)
|
||||
{
|
||||
return Delegate.CreateDelegate(getType(types.ToArray()), methodInfo);
|
||||
}
|
||||
|
||||
return Delegate.CreateDelegate(getType(types.ToArray()), target, methodInfo.Name);
|
||||
}
|
||||
|
||||
public static IFieldPropertyUnion[] GetFieldPropertyUnions(this Type type, BindingFlags bindingFlags = BindingFlags.Default)
|
||||
{
|
||||
var ret = new List<IFieldPropertyUnion>();
|
||||
foreach(var item in type.GetFields(bindingFlags))
|
||||
{
|
||||
//if (item.GetCustomAttribute<CompilerGeneratedAttribute>() != null) continue;
|
||||
ret.Add(new UnionField(item));
|
||||
}
|
||||
foreach(var item in type.GetProperties(bindingFlags))
|
||||
{
|
||||
//if (item.GetCustomAttribute<CompilerGeneratedAttribute>() != null) continue;
|
||||
ret.Add(new UnionProperty(item));
|
||||
}
|
||||
return [.. ret];
|
||||
}
|
||||
|
||||
public static IFieldPropertyUnion? GetFieldPropertyUnion(this Type type, string name, BindingFlags bindingFlags = BindingFlags.Default)
|
||||
{
|
||||
var f = type.GetField(name, bindingFlags);
|
||||
if(f != null)
|
||||
{
|
||||
return new UnionField(f);
|
||||
}
|
||||
var p = type.GetProperty(name, bindingFlags);
|
||||
if(p != null)
|
||||
{
|
||||
return new UnionProperty(p);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
using System;
|
||||
|
||||
namespace ECommonsLite .Schedulers;
|
||||
|
||||
public interface IScheduler : IDisposable
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
using ECommonsLite.DalamudServices;
|
||||
using ECommonsLite.Logging;
|
||||
using System;
|
||||
|
||||
namespace ECommonsLite.Schedulers;
|
||||
|
||||
public class TickScheduler : IScheduler
|
||||
{
|
||||
private long ExecuteAt;
|
||||
private Action Action;
|
||||
public bool Disposed { get; private set; } = false;
|
||||
|
||||
public TickScheduler(Action function, long delayMS = 0)
|
||||
{
|
||||
ExecuteAt = Environment.TickCount64 + delayMS;
|
||||
this.Action = function;
|
||||
Svc.Framework.Update += Execute;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if(!Disposed)
|
||||
{
|
||||
Svc.Framework.Update -= Execute;
|
||||
}
|
||||
Disposed = true;
|
||||
}
|
||||
|
||||
private void Execute(object _)
|
||||
{
|
||||
if(Environment.TickCount64 < ExecuteAt) return;
|
||||
try
|
||||
{
|
||||
Action();
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
PluginLog.Error(e.Message + "\n" + e.StackTrace ?? "");
|
||||
}
|
||||
Dispose();
|
||||
}
|
||||
}
|
||||
13
submodules/ECommonsLite/ECommonsLite/packages.lock.json
Normal file
13
submodules/ECommonsLite/ECommonsLite/packages.lock.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"version": 1,
|
||||
"dependencies": {
|
||||
"net9.0-windows7.0": {
|
||||
"DotNet.ReproducibleBuilds": {
|
||||
"type": "Direct",
|
||||
"requested": "[1.2.25, )",
|
||||
"resolved": "1.2.25",
|
||||
"contentHash": "xCXiw7BCxHJ8pF6wPepRUddlh2dlQlbr81gXA72hdk4FLHkKXas7EH/n+fk5UCA/YfMqG1Z6XaPiUjDbUNBUzg=="
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
21
submodules/ECommonsLite/LICENSE
Normal file
21
submodules/ECommonsLite/LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2024 Aether Tools
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
9
submodules/ECommonsLite/README.md
Normal file
9
submodules/ECommonsLite/README.md
Normal file
@@ -0,0 +1,9 @@
|
||||
# ECommonsLite
|
||||
This repository contains lightweight version of [ECommons](https://github.com/NightmareXIV/ECommons) library containing only essential features used by Customize+.
|
||||
|
||||
## Acknowledgements
|
||||
* Limiana and ECommons Contributors for [ECommons](https://github.com/NightmareXIV/ECommons).
|
||||
* Everyone who contributed code and features through pull requests.
|
||||
|
||||
## License
|
||||
All files in this repository are licensed under the license listed in LICENSE.md file unless stated otherwise. By contributing the code into this repository you agreeing with licensing submitted code under this license.
|
||||
Reference in New Issue
Block a user