Initial commit

This commit is contained in:
Taskeren 2024-04-06 00:12:07 +08:00
commit b488b73422
No known key found for this signature in database
GPG Key ID: BC3749B9DFBE1F00
24 changed files with 1071 additions and 0 deletions

3
.editorconfig Normal file
View File

@ -0,0 +1,3 @@
[*.cs]
indent_size = 4
indent_style = tab

5
.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
bin/
obj/
/packages/
riderModule.iml
/_ReSharper.Caches/

13
.idea/.idea.3074/.idea/.gitignore vendored Normal file
View File

@ -0,0 +1,13 @@
# Default ignored files
/shelf/
/workspace.xml
# Rider ignored files
/contentModel.xml
/.idea.3074.iml
/modules.xml
/projectSettingsUpdater.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding" addBOMForNewFiles="with BOM under Windows, with no BOM otherwise" />
</project>

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="UserContentModel">
<attachedFolders />
<explicitIncludes />
<explicitExcludes />
</component>
</project>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

110
3074.csproj Normal file
View File

@ -0,0 +1,110 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props"
Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')"/>
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{55FD1115-6694-4C85-B2BD-09D4ACB38E76}</ProjectGuid>
<OutputType>WinExe</OutputType>
<RootNamespace>tsf_3074</RootNamespace>
<AssemblyName>tsf_3074</AssemblyName>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<WarningLevel>4</WarningLevel>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<LangVersion>7.3</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="CoreLibNet, Version=5.0.8614.32711, Culture=neutral, processorArchitecture=MSIL">
<HintPath>packages\NetLimiter.5.2.10\lib\net462\CoreLibNet.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Extensions.Logging.Abstractions, Version=5.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<HintPath>packages\Microsoft.Extensions.Logging.Abstractions.5.0.0\lib\net461\Microsoft.Extensions.Logging.Abstractions.dll</HintPath>
</Reference>
<Reference Include="mscorlib" />
<Reference Include="NetLimiter, Version=5.2.8.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>packages\NetLimiter.5.2.10\lib\net462\NetLimiter.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="System"/>
<Reference Include="System.Core"/>
<Reference Include="System.Data"/>
<Reference Include="System.Xml"/>
<Reference Include="System.Xaml">
<RequiredTargetFramework>4.0</RequiredTargetFramework>
</Reference>
<Reference Include="VirusTotalNet, Version=2.0.1.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>packages\NetLimiter.5.2.10\lib\net462\VirusTotalNet.dll</HintPath>
</Reference>
<Reference Include="WindowsBase"/>
<Reference Include="PresentationCore"/>
<Reference Include="PresentationFramework"/>
</ItemGroup>
<ItemGroup>
<ApplicationDefinition Include="App.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</ApplicationDefinition>
<Compile Include="App.xaml.cs">
<DependentUpon>App.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Include="Config.cs" />
<Compile Include="HotkeyManager.cs" />
<Compile Include="OnEvent.cs" />
<Compile Include="VirtualKey.cs" />
</ItemGroup>
<ItemGroup>
<Compile Include="OverlayWindow.xaml.cs">
<DependentUpon>OverlayWindow.xaml</DependentUpon>
</Compile>
<Compile Include="Tsf.cs" />
<Compile Include="Properties\AssemblyInfo.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<None Include="App.config"/>
<None Include="icon.png" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<Content Include=".editorconfig" />
</ItemGroup>
<ItemGroup>
<Page Include="OverlayWindow.xaml" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets"/>
</Project>

View File

@ -0,0 +1,2 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeEditing/Localization/MoveToResource/LastResourceFile/@EntryValue">55FD1115-6694-4C85-B2BD-09D4ACB38E76/d:Properties/f:Resources.resx</s:String></wpf:ResourceDictionary>

16
3074.sln Normal file
View File

@ -0,0 +1,16 @@

Microsoft Visual Studio Solution File, Format Version 12.00
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "3074", "3074.csproj", "{55FD1115-6694-4C85-B2BD-09D4ACB38E76}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{55FD1115-6694-4C85-B2BD-09D4ACB38E76}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{55FD1115-6694-4C85-B2BD-09D4ACB38E76}.Debug|Any CPU.Build.0 = Debug|Any CPU
{55FD1115-6694-4C85-B2BD-09D4ACB38E76}.Release|Any CPU.ActiveCfg = Release|Any CPU
{55FD1115-6694-4C85-B2BD-09D4ACB38E76}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,3 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/ResxEditorPersonal/CheckedGroups/=3074_002FProperties_002FResources/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/ResxEditorPersonal/Initialized/@EntryValue">True</s:Boolean></wpf:ResourceDictionary>

14
App.config Normal file
View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
</startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

10
App.xaml Normal file
View File

@ -0,0 +1,10 @@
<Application x:Class="_3074.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:_3074"
Startup="App_OnStartup"
DispatcherUnhandledException="App_OnDispatcherUnhandledException">
<Application.Resources>
</Application.Resources>
</Application>

45
App.xaml.cs Normal file
View File

@ -0,0 +1,45 @@
using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Threading;
namespace _3074
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App
{
private void App_OnStartup(object sender, StartupEventArgs e)
{
SetCurrentProcessExplicitAppUserModelID("com.squirrel.Tsf");
Tsf.FFullGame.ToString();
var window = new OverlayWindow();
window.Show();
}
private void App_OnDispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
{
// export the exception info
var date = DateTime.Now;
var fileName = $"tsf-crash_{date.Day}_{date.Month}_{date.Year}-{date.Hour}_{date.Minute}_{date.Second}.txt";
using (var writer = new StreamWriter(fileName, true))
{
writer.WriteLine("##########" + DateTime.Now + "##########");
writer.WriteLine("An exception occurred when loading tsf.");
writer.WriteLine(e.Exception);
}
Console.WriteLine(_3074.Properties.Resources.CrashTextOutputAt);
Console.WriteLine(fileName);
Shutdown();
e.Handled = true;
}
[DllImport("shell32.dll", SetLastError = true)]
public static extern void SetCurrentProcessExplicitAppUserModelID(
[MarshalAs(UnmanagedType.LPWStr)] string appUserModelId);
}
}

36
Config.cs Normal file
View File

@ -0,0 +1,36 @@
using System;
using System.Collections.Generic;
using System.IO;
using Newtonsoft.Json;
namespace _3074
{
public static class Config
{
public static ConfigData Instance => _instance ?? ReadConfig();
private static ConfigData _instance;
private static ConfigData ReadConfig(string path = "config.json")
{
if (File.Exists(path))
{
return _instance = JsonConvert.DeserializeObject<ConfigData>(File.ReadAllText(path));
}
var defaults = new ConfigData
{
Destiny2Path = "Your Destiny 2 application path"
};
File.WriteAllText(path, JsonConvert.SerializeObject(defaults));
throw new Exception("Config is not set");
}
}
public class ConfigData
{
public string Destiny2Path;
}
}

87
HotkeyManager.cs Normal file
View File

@ -0,0 +1,87 @@
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Interop;
namespace _3074
{
public partial class HotkeyManager
{
private readonly Window _window;
public HotkeyManager(Window window)
{
_window = window;
}
private HwndSource _source;
private readonly Dictionary<int, OnEvent> _listener = new Dictionary<int, OnEvent>();
private const int HotkeyIdStart = 9000;
private int _hotkeyId = HotkeyIdStart;
public void RegisterHotkey(uint fsModifiers, uint vk, OnEvent onEvent)
{
var thisId = _hotkeyId++;
RegisterHotKey(new WindowInteropHelper(_window).Handle, thisId, fsModifiers, vk);
_listener[thisId] = onEvent;
}
private void UnregisterAllHotkeys()
{
var helper = new WindowInteropHelper(_window);
while (_hotkeyId >= HotkeyIdStart)
{
UnregisterHotKey(helper.Handle, _hotkeyId--);
}
}
public void OnSourceInitialized()
{
_source = HwndSource.FromHwnd(new WindowInteropHelper(_window).Handle) ?? throw new Exception();
_source.AddHook(HwndHook);
}
public void OnClosed()
{
_source.RemoveHook(HwndHook);
_source = null;
UnregisterAllHotkeys();
}
private IntPtr HwndHook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
if (msg != 0x0312) return IntPtr.Zero;
var hotkeyId = wParam.ToInt32();
if (OnHotKeyPressed(hotkeyId))
{
handled = true;
}
return IntPtr.Zero;
}
private bool OnHotKeyPressed(int hotkeyId)
{
var listener = _listener[hotkeyId];
if (listener == null) return false;
listener.Invoke();
return true;
}
[DllImport("User32.dll")]
private static extern bool RegisterHotKey(
[In] IntPtr hWnd,
[In] int id,
[In] uint fsModifiers,
[In] uint vk);
[DllImport("User32.dll")]
private static extern bool UnregisterHotKey(
[In] IntPtr hWnd,
[In] int id);
}
}

4
OnEvent.cs Normal file
View File

@ -0,0 +1,4 @@
namespace _3074
{
public delegate void OnEvent();
}

41
OverlayWindow.xaml Normal file
View File

@ -0,0 +1,41 @@
<Window x:Class="_3074.OverlayWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:_3074"
mc:Ignorable="d"
Title="Thirty-Seventy-Four Overlay" Height="100" Width="120"
Background="{x:Null}" ResizeMode="NoResize"
AllowsTransparency="True"
WindowStyle="None" Topmost="True"
WindowStartupLocation="Manual" Top="0" Left="0"
FontFamily="Consolas" d:DataContext="{d:DesignInstance local:OverlayViewModel}">
<Grid Margin="15">
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" Text="3074" Foreground="Orange"></TextBlock>
<TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding F3074}" Foreground="Red"></TextBlock>
<TextBlock Grid.Row="1" Grid.Column="0" Text="3074UL" Foreground="Orange"></TextBlock>
<TextBlock Grid.Row="1" Grid.Column="1" Text="{Binding F3074UL}" Foreground="Red"></TextBlock>
<TextBlock Grid.Row="2" Grid.Column="0" Text="7500" Foreground="Orange"></TextBlock>
<TextBlock Grid.Row="2" Grid.Column="1" Text="{Binding F7500}" Foreground="Red"></TextBlock>
<TextBlock Grid.Row="3" Grid.Column="0" Text="27k" Foreground="Orange"></TextBlock>
<TextBlock Grid.Row="3" Grid.Column="1" Text="{Binding F27K}" Foreground="Red"></TextBlock>
<TextBlock Grid.Row="4" Grid.Column="0" Text="30k" Foreground="Orange"></TextBlock>
<TextBlock Grid.Row="4" Grid.Column="1" Text="{Binding F30K}" Foreground="Red"></TextBlock>
<TextBlock Grid.Row="5" Grid.Column="0" Text="FG" Foreground="Orange"></TextBlock>
<TextBlock Grid.Row="5" Grid.Column="1" Text="{Binding FFullGame}" Foreground="Red"></TextBlock>
</Grid>
</Window>

53
OverlayWindow.xaml.cs Normal file
View File

@ -0,0 +1,53 @@
using System;
using System.ComponentModel;
using System.Windows;
namespace _3074
{
public partial class OverlayWindow : Window
{
internal readonly HotkeyManager _hotkey;
public OverlayWindow()
{
InitializeComponent();
DataContext = new OverlayViewModel();
_hotkey = new HotkeyManager(this);
}
protected override void OnSourceInitialized(EventArgs e)
{
base.OnSourceInitialized(e);
TsfFilter.AllFilters.ForEach(f => f.RegisterHotkey(_hotkey));
_hotkey.OnSourceInitialized();
}
protected override void OnClosed(EventArgs e)
{
_hotkey.OnClosed();
base.OnClosed(e);
}
}
public class OverlayViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public string F3074 => Tsf.F3074.GetState();
public string F3074UL => Tsf.F3074UL.GetState();
public string F7500 => Tsf.F7500.GetState();
public string F27K => Tsf.F27K.GetState();
public string F30K => Tsf.F30K.GetState();
public string FFullGame => Tsf.FFullGame.GetState();
public OverlayViewModel()
{
Tsf.F3074.OnStateChanged += () => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(F3074)));
Tsf.F3074UL.OnStateChanged += () => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(F3074UL)));
Tsf.F7500.OnStateChanged += () => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(F7500)));
Tsf.F27K.OnStateChanged += () => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(F27K)));
Tsf.F30K.OnStateChanged += () => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(F30K)));
Tsf.FFullGame.OnStateChanged += () => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(FFullGame)));
}
}
}

View File

@ -0,0 +1,55 @@
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Windows;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("_3074")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("_3074")]
[assembly: AssemblyCopyright("Copyright © 2024")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
//In order to begin building localizable applications, set
//<UICulture>CultureYouAreCodingWith</UICulture> in your .csproj file
//inside a <PropertyGroup>. For example, if you are using US english
//in your source files, set the <UICulture> to en-US. Then uncomment
//the NeutralResourceLanguage attribute below. Update the "en-US" in
//the line below to match the UICulture setting in the project file.
//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
[assembly: ThemeInfo(
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
//(used if a resource is not found in the page,
// or application resource dictionaries)
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
//(used if a resource is not found in the page,
// app, or any theme specific resource dictionaries)
)]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

71
Properties/Resources.Designer.cs generated Normal file
View File

@ -0,0 +1,71 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace _3074.Properties {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("_3074.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// Looks up a localized string similar to Tsf has crashed because of unhandled exceptions. Thrown exception log is output at:.
/// </summary>
internal static string CrashTextOutputAt {
get {
return ResourceManager.GetString("CrashTextOutputAt", resourceCulture);
}
}
}
}

120
Properties/Resources.resx Normal file
View File

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="CrashTextOutputAt" xml:space="preserve">
<value>Tsf has crashed because of unhandled exceptions. Thrown exception log is output at:</value>
</data>
</root>

149
Tsf.cs Normal file
View File

@ -0,0 +1,149 @@
using System;
using System.Collections.Generic;
using System.Linq;
using NetLimiter.Service;
namespace _3074
{
public static class Tsf
{
private const string Prefix = "tsf"; // thirty-seventy-four
private static NLClient _client;
private static NLClient GetClient()
{
if (_client != null) return _client;
_client = new NLClient();
_client.Connect();
return _client;
}
private static string GetFilterNameFor(string portName, bool upload = false)
{
return upload ? $"{Prefix}_{portName}_ul" : $"{Prefix}_{portName}";
}
private static TsfFilter CreateFilter(string portName, ushort portStart, ushort portEnd, bool upload = false,
uint fs = 0, uint vk = 0)
{
var cli = GetClient();
var name = GetFilterNameFor(portName);
var filter = cli.Filters.FirstOrDefault(f => f.Name == name) ??
cli.AddFilter(new Filter(name)
{
Functions = { new FFRemotePortInRange(new PortRangeFilterValue(portStart, portEnd)) }
});
return new TsfFilter(name, filter, cli, upload, 1, fs, vk);
}
private static TsfFilter CreateFilterFullGame(uint fs, uint vk)
{
var cli = GetClient();
var name = GetFilterNameFor("fg");
var filter = cli.Filters.FirstOrDefault(f => f.Name == name) ??
cli.AddFilter(new Filter(name)
{
Functions = { new FFPathEqual(Config.Instance.Destiny2Path) }
});
return new TsfFilter(name, filter, cli, false, 811, fs, vk);
}
public static readonly TsfFilter F3074;
public static readonly TsfFilter F3074UL;
public static readonly TsfFilter F7500;
public static readonly TsfFilter F27K;
public static readonly TsfFilter F30K;
public static readonly TsfFilter FFullGame;
static Tsf()
{
F3074 = CreateFilter("3074", 3074, 3074, false, VirtualKey.ModCtrl, VirtualKey.VkG);
F3074UL = CreateFilter("3074", 3074, 3074, true, VirtualKey.ModCtrl, VirtualKey.VkH);
F7500 = CreateFilter("7500", 7500, 7509, false, VirtualKey.ModCtrl, VirtualKey.VkT);
F27K = CreateFilter("27k", 27015, 27200, false, VirtualKey.ModAlt, VirtualKey.VkN);
F30K = CreateFilter("30k", 30000, 30009, false, VirtualKey.ModAlt, VirtualKey.VkB);
FFullGame = CreateFilterFullGame(VirtualKey.ModCtrl, VirtualKey.VkJ);
}
}
public class TsfFilter
{
private readonly string _name;
private readonly Filter _filter;
private readonly NLClient _client;
private readonly bool _upload;
private readonly uint _limitSize; // the limit rate, normally is 1, only FG is 800 or 811
private readonly uint _fs;
private readonly uint _vk;
private Rule _rule;
public event OnEvent OnStateChanged = delegate { };
public static readonly List<TsfFilter> AllFilters = new List<TsfFilter>();
public TsfFilter(string name, Filter filter, NLClient client, bool upload, uint limitSize = 1, uint fs = 0,
uint vk = 0)
{
_name = name;
_filter = filter;
_client = client;
_upload = upload;
_limitSize = limitSize;
_fs = fs;
_vk = vk;
GetLimitRule();
AllFilters.Add(this);
}
public void RegisterHotkey(HotkeyManager manager)
{
if (_vk != 0)
{
Console.WriteLine($"Registering Hotkey for {_name}");
manager.RegisterHotkey(_fs, _vk, () =>
{
Toggle();
var currState = GetLimitRule().IsEnabled ? "On" : "Off";
Console.WriteLine($"Updated [{_name}] {currState}");
});
}
}
private Rule GetLimitRule()
{
if (_rule != null) return _rule;
var dir = _upload ? RuleDir.Out : RuleDir.In;
_rule = _client.Rules.FirstOrDefault(r => r.FilterId == _filter.Id && r.Dir == dir) ??
_client.AddRule(_filter.Id, new LimitRule(dir, _limitSize) { IsEnabled = false });
return _rule;
}
public void Toggle()
{
_rule.IsEnabled = !_rule.IsEnabled;
_rule = _client.UpdateRule(_rule).Rule;
OnStateChanged.Invoke();
}
public void Set(bool value)
{
_rule.IsEnabled = value;
_rule = _client.UpdateRule(_rule).Rule;
OnStateChanged.Invoke();
}
public bool IsEnabled()
{
return _rule?.IsEnabled ?? false;
}
public string GetState()
{
return IsEnabled() ? "On" : "Off";
}
}
}

210
VirtualKey.cs Normal file
View File

@ -0,0 +1,210 @@
namespace _3074
{
public static class VirtualKey
{
public const uint ModNone = 0x0000;
public const uint ModAlt = 0x0001;
public const uint ModCtrl = 0x0002;
public const uint ModShift = 0x0004;
public const uint ModWin = 0x0008;
// https://learn.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes
public const uint VkLButton = 0x01; // Left mouse button
public const uint VkRButton = 0x02; // Right mouse button
public const uint VkCancel = 0x03; // Control-break processing
public const uint VkMButton = 0x04; // Middle mouse button
public const uint VkXButton1 = 0x05; // X1 mouse button
public const uint VkXButton2 = 0x06; // X2 mouse button
public const uint VkBack = 0x08; // BACKSPACE key
public const uint VkTab = 0x09; // TAB key
public const uint VkClear = 0x0C; // CLEAR key
public const uint VkReturn = 0x0D; // ENTER key
public const uint VkShift = 0x10; // SHIFT key
public const uint VkControl = 0x11; // CTRL key
public const uint VkMenu = 0x12; // ALT key
public const uint VkPause = 0x13; // PAUSE key
public const uint VkCapital = 0x14; // CAPS LOCK key
public const uint VkKana = 0x15; // IME Kana mode
public const uint VkHangul = 0x15; // IME Hangul mode
public const uint VkImeOn = 0x16; // IME On
public const uint VkJunja = 0x17; // IME Junja mode
public const uint VkFinal = 0x18; // IME final mode
public const uint VkHanja = 0x19; // IME Hanja mode
public const uint VkKanji = 0x19; // IME Kanji mode
public const uint VkImeOff = 0x1A; // IME Off
public const uint VkEscape = 0x1B; // ESC key
public const uint VkConvert = 0x1C; // IME convert
public const uint VkNonConvert = 0x1D; // IME nonconvert
public const uint VkAccept = 0x1E; // IME accept
public const uint VkModeChange = 0x1F; // IME mode change request
public const uint VkSpace = 0x20; // SPACEBAR
public const uint VkPrior = 0x21; // PAGE UP key
public const uint VkNext = 0x22; // PAGE DOWN key
public const uint VkEnd = 0x23; // END key
public const uint VkHome = 0x24; // HOME key
public const uint VkLeft = 0x25; // LEFT ARROW key
public const uint VkUp = 0x26; // UP ARROW key
public const uint VkRight = 0x27; // RIGHT ARROW key
public const uint VkDown = 0x28; // DOWN ARROW key
public const uint VkSelect = 0x29; // SELECT key
public const uint VkPrint = 0x2A; // PRINT key
public const uint VkExecute = 0x2B; // EXECUTE key
public const uint VkSnapshot = 0x2C; // PRINT SCREEN key
public const uint VkInsert = 0x2D; // INS key
public const uint VkDelete = 0x2E; // DEL key
public const uint VkHelp = 0x2F; // HELP key
public const uint Vk0 = 0x30;
public const uint Vk1 = 0x31;
public const uint Vk2 = 0x32;
public const uint Vk3 = 0x33;
public const uint Vk4 = 0x34;
public const uint Vk5 = 0x35;
public const uint Vk6 = 0x36;
public const uint Vk7 = 0x37;
public const uint Vk8 = 0x38;
public const uint Vk9 = 0x39;
public const uint VkA = 0x41;
public const uint VkB = 0x42;
public const uint VkC = 0x43;
public const uint VkD = 0x44;
public const uint VkE = 0x45;
public const uint VkF = 0x46;
public const uint VkG = 0x47;
public const uint VkH = 0x48;
public const uint VkI = 0x49;
public const uint VkJ = 0x4A;
public const uint VkK = 0x4B;
public const uint VkL = 0x4C;
public const uint VkM = 0x4D;
public const uint VkN = 0x4E;
public const uint VkO = 0x4F;
public const uint VkP = 0x50;
public const uint VkQ = 0x51;
public const uint VkR = 0x52;
public const uint VkS = 0x53;
public const uint VkT = 0x54;
public const uint VkU = 0x55;
public const uint VkV = 0x56;
public const uint VkW = 0x57;
public const uint VkX = 0x58;
public const uint VkY = 0x59;
public const uint VkZ = 0x5A;
public const uint VkLWin = 0x5B; // Left Windows key
public const uint VkRWin = 0x5C; // Right Windows key
public const uint VkApps = 0x5D; // Applications key
public const uint VkSleep = 0x5F; // Computer Sleep key
public const uint VkNumpad0 = 0x60; // Numeric keypad 0 key
public const uint VkNumpad1 = 0x61; // Numeric keypad 1 key
public const uint VkNumpad2 = 0x62; // Numeric keypad 2 key
public const uint VkNumpad3 = 0x63; // Numeric keypad 3 key
public const uint VkNumpad4 = 0x64; // Numeric keypad 4 key
public const uint VkNumpad5 = 0x65; // Numeric keypad 5 key
public const uint VkNumpad6 = 0x66; // Numeric keypad 6 key
public const uint VkNumpad7 = 0x67; // Numeric keypad 7 key
public const uint VkNumpad8 = 0x68; // Numeric keypad 8 key
public const uint VkNumpad9 = 0x69; // Numeric keypad 9 key
public const uint VkMultiply = 0x6A; // Multiply key
public const uint VkAdd = 0x6B; // Add key
public const uint VkSeparator = 0x6C; // Separator key
public const uint VkSubtract = 0x6D; // Subtract key
public const uint VkDecimal = 0x6E; // Decimal key
public const uint VkDivide = 0x6F; // Divide key
public const uint VkF1 = 0x70; // F1 key
public const uint VkF2 = 0x71; // F2 key
public const uint VkF3 = 0x72; // F3 key
public const uint VkF4 = 0x73; // F4 key
public const uint VkF5 = 0x74; // F5 key
public const uint VkF6 = 0x75; // F6 key
public const uint VkF7 = 0x76; // F7 key
public const uint VkF8 = 0x77; // F8 key
public const uint VkF9 = 0x78; // F9 key
public const uint VkF10 = 0x79; // F10 key
public const uint VkF11 = 0x7A; // F11 key
public const uint VkF12 = 0x7B; // F12 key
public const uint VkF13 = 0x7C; // F13 key
public const uint VkF14 = 0x7D; // F14 key
public const uint VkF15 = 0x7E; // F15 key
public const uint VkF16 = 0x7F; // F16 key
public const uint VkF17 = 0x80; // F17 key
public const uint VkF18 = 0x81; // F18 key
public const uint VkF19 = 0x82; // F19 key
public const uint VkF20 = 0x83; // F20 key
public const uint VkF21 = 0x84; // F21 key
public const uint VkF22 = 0x85; // F22 key
public const uint VkF23 = 0x86; // F23 key
public const uint VkF24 = 0x87; // F24 key
public const uint VkNumlock = 0x90; // NUM LOCK key
public const uint VkScroll = 0x91; // SCROLL LOCK key
public const uint VkLShift = 0xA0; // Left SHIFT key
public const uint VkRShift = 0xA1; // Right SHIFT key
public const uint VkLControl = 0xA2; // Left CONTROL key
public const uint VkRControl = 0xA3; // Right CONTROL key
public const uint VkLMenu = 0xA4; // Left ALT key
public const uint VkRMenu = 0xA5; // Right ALT key
public const uint VkBrowserBack = 0xA6; // Browser Back key
public const uint VkBrowserForward = 0xA7; // Browser Forward key
public const uint VkBrowserRefresh = 0xA8; // Browser Refresh key
public const uint VkBrowserStop = 0xA9; // Browser Stop key
public const uint VkBrowserSearch = 0xAA; // Browser Search key
public const uint VkBrowserFavorites = 0xAB; // Browser Favorites key
public const uint VkBrowserHome = 0xAC; // Browser Start and Home key
public const uint VkVolumeMute = 0xAD; // Volume Mute key
public const uint VkVolumeDown = 0xAE; // Volume Down key
public const uint VkVolumeUp = 0xAF; // Volume Up key
public const uint VkMediaNextTrack = 0xB0; // Next Track key
public const uint VkMediaPrevTrack = 0xB1; // Previous Track key
public const uint VkMediaStop = 0xB2; // Stop Media key
public const uint VkMediaPlayPause = 0xB3; // Play/Pause Media key
public const uint VkLaunchMail = 0xB4; // Start Mail key
public const uint VkLaunchMediaSelect = 0xB5; // Select Media key
public const uint VkLaunchApp1 = 0xB6; // Start Application 1 key
public const uint VkLaunchApp2 = 0xB7; // Start Application 2 key
public const uint
VkOem1 = 0xBA; // Used for miscellaneous characters; it can vary by keyboard. For the US standard keyboard, the ;: key
public const uint VkOemPlus = 0xBB; // For any country/region, the + key
public const uint VkOemComma = 0xBC; // For any country/region, the , key
public const uint VkOemMinus = 0xBD; // For any country/region, the - key
public const uint VkOemPeriod = 0xBE; // For any country/region, the . key
public const uint
VkOem2 = 0xBF; // Used for miscellaneous characters; it can vary by keyboard. For the US standard keyboard, the /? key
public const uint
VkOem3 = 0xC0; // Used for miscellaneous characters; it can vary by keyboard. For the US standard keyboard, the `~ key
public const uint
VkOem4 = 0xDB; // Used for miscellaneous characters; it can vary by keyboard. For the US standard keyboard, the [{ key
public const uint
VkOem5 = 0xDC; // Used for miscellaneous characters; it can vary by keyboard. For the US standard keyboard, the \\| key
public const uint
VkOem6 = 0xDD; // Used for miscellaneous characters; it can vary by keyboard. For the US standard keyboard, the ]} key
public const uint
VkOem7 = 0xDE; // Used for miscellaneous characters; it can vary by keyboard. For the US standard keyboard, the '" key
public const uint VkOem8 = 0xDF; // Used for miscellaneous characters; it can vary by keyboard.
public const uint
VkOem102 = 0xE2; // The <> keys on the US standard keyboard, or the \\| key on the non-US 102-key keyboard
public const uint VkProcessKey = 0xE5; // IME PROCESS key
public const uint
VkPacket = 0xE7; // Used to pass Unicode characters as if they were keystrokes. The VK_PACKET key is the low word of a 32-bit Virtual Key value used for non-keyboard input methods. For more information, see Remark in KEYBDINPUT, SendInput, WM_KEYDOWN, and WM_KEYUP
public const uint VkAttn = 0xF6; // Attn key
public const uint VkCrSel = 0xF7; // CrSel key
public const uint VkExSel = 0xF8; // ExSel key
public const uint VkErEof = 0xF9; // Erase EOF key
public const uint VkPlay = 0xFA; // Play key
public const uint VkZoom = 0xFB; // Zoom key
public const uint VkNoname = 0xFC; // Reserved
public const uint VkPa1 = 0xFD; // PA1 key
public const uint VkOemClear = 0xFE; // Clear key
}
}

6
packages.config Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Extensions.Logging.Abstractions" version="5.0.0" targetFramework="net472" />
<package id="NetLimiter" version="5.2.10" targetFramework="net472" />
<package id="Newtonsoft.Json" version="13.0.3" targetFramework="net472" />
</packages>