├── .gitattributes ├── .github └── workflows │ ├── daily.yml │ └── dotnet.yml ├── .gitignore ├── Authentication ├── Authentication.cs ├── CaptchaRiotAuth │ ├── 2Captcha.cs │ └── SuperMemory.cs ├── DriverRiotAuth │ ├── Events.cs │ ├── Handlers │ │ ├── AuthHandler.cs │ │ ├── DriverHandler.cs │ │ └── SocketHandler.cs │ └── Records │ │ ├── AuthRecords.cs │ │ ├── AuthenticationRecords.cs │ │ └── DriverRecords.cs ├── QRSignIn │ ├── Handlers │ │ ├── LoginQrManager.cs │ │ ├── SignInManager.cs │ │ └── TokenManager.cs │ └── Modules │ │ └── Records.cs └── SSIDReAuth │ └── SSIDAuthManager.cs ├── EventHandler ├── Events │ ├── InGameEvents.cs │ ├── MatchEvents.cs │ ├── MenuEvents.cs │ ├── MiscEvents.cs │ ├── PartyEvents.cs │ ├── PreGameEvents.cs │ ├── QueueEvents.cs │ ├── RoundEvents.cs │ └── VoteEvents.cs └── GameEvents.cs ├── HenrikApi ├── Accounts.cs ├── Content.cs ├── Crosshair.cs ├── Esports.cs ├── Leaderboard.cs ├── MMR.cs ├── MMRHistory.cs ├── Match.cs ├── Matchlist.cs ├── Premier.cs ├── QueueStatus.cs ├── Raw.cs ├── Status.cs ├── Store.cs ├── StoredData.cs └── Website.cs ├── ImageRecognition ├── Handlers │ ├── ColorHandler.cs │ ├── ImageCaptureHandler.cs │ ├── KillFeed │ │ ├── ActionDetection.cs │ │ └── KillFeedHandler.cs │ └── Spike │ │ ├── ActionDetection.cs │ │ └── SpikeHandler.cs ├── ImageRecognition.cs └── Internals │ ├── IntMethods.cs │ └── RecognitionRecords.cs ├── Initiator.cs ├── LICENSE ├── Network ├── ChatEndpoints │ ├── ChatEndpoints.cs │ └── DataTypes │ │ ├── ChatInfo.cs │ │ ├── ChatParticipant.cs │ │ ├── Message.cs │ │ └── NewMessage.cs ├── ContractEndpoints │ ├── ContractEndpoints.cs │ └── DataTypes │ │ ├── Contract.cs │ │ └── ItemUpgrade.cs ├── CurrentGameEndpoints │ ├── CurrentGameEndpoints.cs │ └── DataTypes │ │ ├── CurrentGameMatch.cs │ │ └── CurrentGamePlayer.cs ├── LocalEndpoints │ ├── DataTypes │ │ ├── AliasInfo.cs │ │ ├── EntitlementTokens.cs │ │ ├── FriendPresences.cs │ │ ├── FriendRequests.cs │ │ ├── Friends.cs │ │ ├── LocalChatSession.cs │ │ └── Locale.cs │ └── LocalEndpoints.cs ├── PVPEndpoints │ ├── DataTypes │ │ ├── AccountXP.cs │ │ ├── ClientConfig.cs │ │ ├── CompetitiveUpdate.cs │ │ ├── Content.cs │ │ ├── Leaderboard.cs │ │ ├── MatchHistory.cs │ │ ├── MatchInfo.cs │ │ ├── NameService.cs │ │ ├── Penalty.cs │ │ ├── PlayerLoadout.cs │ │ ├── PlayerMMR.cs │ │ └── SetPlayerLoadout.cs │ └── PVPEndpoints.cs ├── PartyEndpoints │ ├── DataTypes │ │ ├── CustomGameConfig.cs │ │ ├── CustomGameSettings.cs │ │ ├── Party.cs │ │ ├── PartyChatToken.cs │ │ ├── PartyPlayer.cs │ │ ├── PartySetReady.cs │ │ └── PartyVoiceToken.cs │ └── PartyEndpoints.cs ├── PreGameEndpoints │ ├── DataTypes │ │ ├── GameLoadout.cs │ │ ├── PreGameMatch.cs │ │ └── PreGamePlayer.cs │ └── PreGameEndpoints.cs ├── StoreEndpoints │ ├── DataTypes │ │ ├── Balances.cs │ │ ├── OwnedItem.cs │ │ └── Storefront.cs │ └── StoreEndpoints.cs └── ValorantNet.cs ├── RConnect ├── DataTypes │ └── MatchStats.cs ├── RConnectMethods.cs └── ValorantTables.cs ├── README.md ├── RadiantConnect.Tests ├── AuthenticationTest.cs ├── Client.cs ├── EndpointsTest.cs ├── RadiantConnect.Tests.csproj ├── TablesUnitTest.cs └── ValorantApi │ ├── Agents.cs │ ├── Currencies.cs │ ├── Maps.cs │ └── Weapons.cs ├── RadiantConnect.csproj ├── RadiantConnect.csproj.DotSettings ├── RadiantConnect.sln ├── RadiantConnect.sln.DotSettings ├── Services ├── ExceptionService.cs ├── GameVersionService.cs ├── LogService.cs ├── RiotPathService.cs └── ValorantService.cs ├── ShadowClient └── ShadowClient.cs ├── SocketServices ├── InternalTcp │ └── ValSocket.cs ├── RMS │ └── RMSClient.cs └── XMPP │ ├── DataTypes │ ├── PlayerPresence.cs │ └── ValorantPresence.cs │ ├── RemoteXMPP.cs │ ├── ValXMPP.cs │ ├── XMPPController.cs │ └── XMPPManagement │ ├── InternalProxy.cs │ └── XMPPSocketHandle.cs ├── Utilities ├── AuthUtil.cs ├── InternalHttp.cs ├── InternalValorantMethods.cs ├── SocketUtil.cs ├── StringExtensions.cs └── Win32.cs ├── ValorantApi ├── Agents.cs ├── Buddies.cs ├── Bundles.cs ├── Ceremonies.cs ├── Client.cs ├── CompetitiveTiers.cs ├── ContentTiers.cs ├── Contracts.cs ├── Currencies.cs ├── Events.cs ├── Flex.cs ├── Gamemodes.cs ├── Gear.cs ├── LevelBorders.cs ├── Maps.cs ├── PlayerCards.cs ├── PlayerTitles.cs ├── Seasons.cs ├── Sprays.cs ├── Themes.cs ├── Version.cs └── Weapons.cs ├── docs ├── docs │ ├── .gitignore │ ├── Client Events │ │ ├── In Game Events.md │ │ ├── Match Events.md │ │ ├── Menu Events.md │ │ ├── Pre Game Events.md │ │ ├── Queue Events.md │ │ ├── Round Events.md │ │ └── Vote Events.md │ ├── DataTypes │ │ ├── Authentication │ │ │ ├── DriverSettings.md │ │ │ └── RIot Sign On.md │ │ ├── Chat │ │ │ ├── Chat Participant.md │ │ │ ├── ChatInfo.md │ │ │ ├── Message.md │ │ │ └── New Message.md │ │ ├── Contract │ │ │ ├── Contract.md │ │ │ └── Item Upgrade.md │ │ ├── Current Game │ │ │ ├── Current Game Match.md │ │ │ └── Current Game Player.md │ │ ├── Local │ │ │ ├── Alias Info.md │ │ │ ├── Entitlement Tokens.md │ │ │ ├── Friend Presences.md │ │ │ ├── Friend Requests.md │ │ │ ├── Friends.md │ │ │ ├── Local Chat Session.md │ │ │ └── Locale.md │ │ ├── PVP │ │ │ ├── Account XP.md │ │ │ ├── Client Config.md │ │ │ ├── Competitive Update.md │ │ │ ├── Content.md │ │ │ ├── Leaderboard.md │ │ │ ├── Match History.md │ │ │ ├── Match Info.md │ │ │ ├── Name Service.md │ │ │ ├── Penalty.md │ │ │ ├── Player Loadout.md │ │ │ ├── Player MMR.md │ │ │ └── Set Player Loadout.md │ │ ├── Party │ │ │ ├── Custom Game Config.md │ │ │ ├── Custom Game Settings.md │ │ │ ├── Party Chat Token.md │ │ │ ├── Party Player.md │ │ │ ├── Party Set Ready.md │ │ │ ├── Party Voice Token.md │ │ │ └── Party.md │ │ ├── PreGame │ │ │ ├── Game Loadout.md │ │ │ ├── Pre Game Match.md │ │ │ └── Pre Game Player.md │ │ ├── RConnect │ │ │ └── MatchStats.md │ │ ├── Store │ │ │ ├── Balances.md │ │ │ ├── Owned Item.md │ │ │ └── Store Front.md │ │ └── XMPP │ │ │ └── ValorantPresence.md │ ├── Extra Data & How To │ │ ├── How To.md │ │ ├── Internal Dictionaries.md │ │ └── Samples.md │ ├── Image Recognition │ │ └── Setup.md │ ├── Method Usage │ │ ├── .gitignore │ │ ├── Authentication Methods.md │ │ ├── Chat Methods.md │ │ ├── Contract Methods.md │ │ ├── Current Game Methods.md │ │ ├── Local Requests Methods.md │ │ ├── PVP Methods.md │ │ ├── Party Methods.md │ │ ├── PreGame Methods.md │ │ ├── RConnect Methods.md │ │ └── Store Methods.md │ ├── Setup │ │ └── QuickStart.md │ ├── TCP & XMPP │ │ ├── TCP Guide.md │ │ ├── XMPP MITM Guide.md │ │ ├── XMPP Remote Guide copy.md │ │ └── XMPP Usage.md │ ├── ValorantNet │ │ └── ValorantNet Usage.md │ └── index.md └── mkdocs.yml └── icon.png /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.github/workflows/daily.yml: -------------------------------------------------------------------------------- 1 | name: Daily Test 2 | 3 | on: 4 | schedule: 5 | - cron: "0 0 * * *" 6 | 7 | jobs: 8 | build: 9 | 10 | runs-on: windows-latest 11 | 12 | strategy: 13 | matrix: 14 | dotnet-version: [ '9.*' ] 15 | 16 | steps: 17 | - name: Checkout 18 | uses: actions/checkout@v4 19 | with: 20 | fetch-depth: 0 # Ensure full history is fetched for tags 21 | 22 | - name: Set up .NET SDK 23 | uses: actions/setup-dotnet@v3 24 | with: 25 | dotnet-version: '9.*' 26 | 27 | - name: Restore dependencies 28 | run: dotnet restore RadiantConnect.sln 29 | 30 | - name: Build the project 31 | run: dotnet build RadiantConnect.sln --configuration Release --framework net9.0 32 | 33 | - name: Test RadiantConnect.Tests 34 | run: dotnet test RadiantConnect.Tests/RadiantConnect.Tests.csproj --no-restore --verbosity normal 35 | -------------------------------------------------------------------------------- /.github/workflows/dotnet.yml: -------------------------------------------------------------------------------- 1 | name: Build & Test 2 | 3 | on: 4 | push: 5 | branches: [ "main" ] 6 | 7 | jobs: 8 | build: 9 | 10 | runs-on: windows-latest 11 | 12 | strategy: 13 | matrix: 14 | dotnet-version: [ '8.*' ] 15 | 16 | steps: 17 | - name: Checkout 18 | uses: actions/checkout@v4 19 | with: 20 | fetch-depth: 0 # Ensure full history is fetched for tags 21 | 22 | - name: Set up .NET SDK 23 | uses: actions/setup-dotnet@v3 24 | with: 25 | dotnet-version: '8.*' 26 | 27 | - name: Restore dependencies 28 | run: dotnet restore RadiantConnect.csproj 29 | 30 | - name: Build the project 31 | run: dotnet build RadiantConnect.csproj --configuration Release --framework net8.0 32 | 33 | - name: Test RadiantConnect.Tests 34 | run: dotnet test RadiantConnect.Tests/RadiantConnect.Tests.csproj --no-restore --verbosity normal 35 | 36 | - name: Publish the project 37 | run: dotnet publish RadiantConnect.csproj --configuration Release --framework net8.0 --output ./bin/Release/net8.0/publish 38 | 39 | - name: Create Artifact 40 | uses: actions/upload-artifact@v4 41 | with: 42 | name: published-files 43 | path: ./bin/Release/net8.0/publish/ 44 | 45 | - name: Zip Artifact For Pre-Release 46 | run: Compress-Archive -Path ./bin/Release/net8.0/publish* -DestinationPath ./RadiantConnect.zip 47 | 48 | - name: Create GitHub Pre-Release 49 | id: create_release 50 | uses: softprops/action-gh-release@v2 51 | with: 52 | tag_name: pre-release-${{ github.run_number }} 53 | release_name: "Beta Pre-Build ${{ github.run_number }}" 54 | draft: false 55 | prerelease: true 56 | files: ./RadiantConnect.zip 57 | env: 58 | GITHUB_TOKEN: ${{ secrets.PAT_TOKEN }} 59 | -------------------------------------------------------------------------------- /Authentication/CaptchaRiotAuth/2Captcha.cs: -------------------------------------------------------------------------------- 1 | namespace RadiantConnect.Authentication.CaptchaRiotAuth 2 | { 3 | internal class _2Captcha; 4 | } 5 | -------------------------------------------------------------------------------- /Authentication/DriverRiotAuth/Events.cs: -------------------------------------------------------------------------------- 1 | using static RadiantConnect.Authentication.Authentication; 2 | 3 | namespace RadiantConnect.Authentication.DriverRiotAuth 4 | { 5 | public static class Events 6 | { 7 | 8 | internal delegate void RadiantConsoleDetected(string? data = null); 9 | internal delegate void RuntimeChanged(); 10 | internal delegate void FrameChangedEvent(string? url, string frameId); 11 | 12 | public delegate void MultiFactorEvent(); 13 | 14 | public delegate void DriverEvent(DriverStatus status); 15 | 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Authentication/DriverRiotAuth/Records/AuthRecords.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace RadiantConnect.Authentication.DriverRiotAuth.Records; 4 | 5 | internal record EntitleReturn( 6 | [property: JsonPropertyName("entitlements_token")] string EntitlementsToken 7 | ); 8 | 9 | internal record Alias( 10 | [property: JsonPropertyName("game_name")] string GameName, 11 | [property: JsonPropertyName("tag_line")] string TagLine 12 | ); 13 | 14 | internal record Mfa( 15 | [property: JsonPropertyName("verified")] bool? Verified 16 | ); 17 | 18 | internal record UserInfo( 19 | [property: JsonPropertyName("sub")] string Sub, 20 | [property: JsonPropertyName("email")] string Email, 21 | [property: JsonPropertyName("locale")] string Locale, 22 | [property: JsonPropertyName("username")] string Username, 23 | [property: JsonPropertyName("mfa")] Mfa Mfa, 24 | [property: JsonPropertyName("country")] string Country, 25 | [property: JsonPropertyName("email_status")] string EmailStatus, 26 | [property: JsonPropertyName("alias")] Alias Alias, 27 | [property: JsonPropertyName("amr")] IReadOnlyList Amr, 28 | [property: JsonPropertyName("birth_date")] string BirthDate 29 | ); -------------------------------------------------------------------------------- /Authentication/DriverRiotAuth/Records/AuthenticationRecords.cs: -------------------------------------------------------------------------------- 1 |  2 | // ReSharper disable IdentifierTypo 3 | // ReSharper disable InconsistentNaming 4 | // ReSharper disable StringLiteralTypo 5 | 6 | namespace RadiantConnect.Authentication.DriverRiotAuth.Records; 7 | 8 | public record DriverSettings( 9 | string ProcessName = "msedge", 10 | string BrowserExecutable = @"C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe", 11 | bool KillBrowser = false, 12 | bool CacheCookies = true, 13 | bool UseHeadless = true 14 | ); 15 | 16 | [Obsolete("Record is no longer used, and will throw an error.", true)] 17 | public record RadiantConnectRSO(string SSID); // Supposedly all you need for authorization? 18 | 19 | public record RSOAuth( 20 | string? Subject, 21 | string? SSID, 22 | string? TDID, 23 | string? CSID, 24 | string? CLID, 25 | string? AccessToken, 26 | string? PasToken, 27 | string? Entitlement, 28 | string? Affinity, 29 | string? ChatAffinity, 30 | object? ClientConfig, 31 | IEnumerable? RiotCookies, 32 | string? IdToken 33 | ) 34 | { 35 | public string? RmsToken { get; set; } 36 | }; -------------------------------------------------------------------------------- /Authentication/DriverRiotAuth/Records/DriverRecords.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace RadiantConnect.Authentication.DriverRiotAuth.Records; 4 | 5 | 6 | public record Cookie( 7 | [property: JsonPropertyName("name")] string Name, 8 | [property: JsonPropertyName("value")] string Value, 9 | [property: JsonPropertyName("domain")] string Domain, 10 | [property: JsonPropertyName("path")] string Path, 11 | [property: JsonPropertyName("expires")] double? Expires, 12 | [property: JsonPropertyName("size")] int? Size, 13 | [property: JsonPropertyName("httpOnly")] bool? HttpOnly, 14 | [property: JsonPropertyName("secure")] bool? Secure, 15 | [property: JsonPropertyName("session")] bool? Session, 16 | [property: JsonPropertyName("priority")] string Priority, 17 | [property: JsonPropertyName("sameParty")] bool? SameParty, 18 | [property: JsonPropertyName("sourceScheme")] string SourceScheme, 19 | [property: JsonPropertyName("sourcePort")] int? SourcePort, 20 | [property: JsonPropertyName("sameSite")] string SameSite, 21 | [property: JsonPropertyName("partitionKey")] PartitionKey PartitionKey 22 | ); 23 | 24 | public record PartitionKey( 25 | [property: JsonPropertyName("topLevelSite")] string TopLevelSite, 26 | [property: JsonPropertyName("hasCrossSiteAncestor")] bool? HasCrossSiteAncestor 27 | ); 28 | 29 | internal record Result( 30 | [property: JsonPropertyName("cookies")] IReadOnlyList Cookies 31 | ); 32 | 33 | internal record CookieRoot( 34 | [property: JsonPropertyName("id")] int? Id, 35 | [property: JsonPropertyName("result")] Result Result 36 | ); 37 | 38 | 39 | internal record EdgeDev( 40 | [property: JsonPropertyName("description")] string Description, 41 | [property: JsonPropertyName("devtoolsFrontendUrl")] string DevtoolsFrontendUrl, 42 | [property: JsonPropertyName("id")] string Id, 43 | [property: JsonPropertyName("title")] string Title, 44 | [property: JsonPropertyName("type")] string Type, 45 | [property: JsonPropertyName("url")] string Url, 46 | [property: JsonPropertyName("webSocketDebuggerUrl")] string WebSocketDebuggerUrl, 47 | [property: JsonPropertyName("parentId")] string ParentId 48 | ); 49 | -------------------------------------------------------------------------------- /Authentication/QRSignIn/Handlers/SignInManager.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | using System.Net; 3 | using System.Runtime.InteropServices; 4 | using System.Web; 5 | using RadiantConnect.Authentication.DriverRiotAuth.Records; 6 | using RadiantConnect.Authentication.QRSignIn.Modules; 7 | using RadiantConnect.Utilities; 8 | 9 | /* 10 | * 11 | * Huge credit to https://github.com/judongdev/riot-qr-auth/blob/main/api/index.py for implementation <3 12 | * 13 | */ 14 | 15 | namespace RadiantConnect.Authentication.QRSignIn.Handlers 16 | { 17 | public delegate void UrlBuilder(string url); 18 | 19 | internal class SignInManager(Authentication.CountryCode code, bool returnUrl = false) 20 | { 21 | internal event UrlBuilder? OnUrlBuilt; 22 | 23 | internal Process DisplayImage(string path) 24 | { 25 | if (!File.Exists(path)) throw new FileNotFoundException("QR code image not found", path); 26 | 27 | if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) 28 | { 29 | ProcessStartInfo startInfo = new() 30 | { 31 | FileName = path, 32 | UseShellExecute = true 33 | }; 34 | return Process.Start(startInfo)!; 35 | } 36 | 37 | if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) 38 | { 39 | if (string.IsNullOrEmpty(Environment.GetEnvironmentVariable("XDG_CURRENT_DESKTOP") ?? Environment.GetEnvironmentVariable("DESKTOP_SESSION"))) 40 | throw new InvalidOperationException("No desktop environment detected, please use ReturnUrl."); 41 | return Process.Start("xdg-open", path); 42 | } 43 | 44 | throw new PlatformNotSupportedException("Unsupported OS"); 45 | } 46 | 47 | internal async Task Authenticate() 48 | { 49 | (HttpClient httpClient, CookieContainer container) = AuthUtil.BuildClient(); 50 | 51 | LoginQrManager builder = new(httpClient); 52 | BuiltData qrData = await builder.Build(code); 53 | 54 | string tempName = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid():N}.jpg"); 55 | Process? form = null; 56 | 57 | try 58 | { 59 | if (returnUrl) 60 | { 61 | OnUrlBuilt?.Invoke(qrData.LoginUrl); 62 | } 63 | else 64 | { 65 | string urlProper = HttpUtility.UrlEncode(qrData.LoginUrl); 66 | byte[] imageData = await httpClient.GetByteArrayAsync($"https://api.qrserver.com/v1/create-qr-code/?size=250x250&data={urlProper}"); 67 | await File.WriteAllBytesAsync(tempName, imageData); 68 | form = DisplayImage(tempName); 69 | } 70 | 71 | TokenManager manager = new(form, qrData, httpClient, returnUrl, container); 72 | TaskCompletionSource tcs = new(); 73 | 74 | manager.OnTokensFinished += authData => tcs.SetResult(authData); 75 | manager.InitiateTimer(tempName); 76 | 77 | return await tcs.Task; 78 | } 79 | finally 80 | { 81 | httpClient.Dispose(); 82 | try { form?.Kill(true); }catch{/**/} 83 | try { Process.GetProcessesByName(tempName).ToList().ForEach(x => x.Kill(true)); } catch {/**/} 84 | 85 | form?.Dispose(); 86 | 87 | if (File.Exists(tempName)) File.Delete(tempName); 88 | } 89 | } 90 | } 91 | } 92 | 93 | -------------------------------------------------------------------------------- /Authentication/QRSignIn/Modules/Records.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace RadiantConnect.Authentication.QRSignIn.Modules; 4 | 5 | public record Auth( 6 | [property: JsonPropertyName("auth_method")] string AuthMethod 7 | ); 8 | 9 | public record Captcha( 10 | [property: JsonPropertyName("type")] string Type, 11 | [property: JsonPropertyName("hcaptcha")] Hcaptcha Hcaptcha 12 | ); 13 | 14 | public record Hcaptcha( 15 | [property: JsonPropertyName("key")] string Key, 16 | [property: JsonPropertyName("data")] string Data 17 | ); 18 | 19 | public record Stage3Return( 20 | [property: JsonPropertyName("type")] string Type, 21 | [property: JsonPropertyName("auth")] Auth Auth, 22 | [property: JsonPropertyName("captcha")] Captcha Captcha, 23 | [property: JsonPropertyName("suuid")] string Suuid, 24 | [property: JsonPropertyName("cluster")] string Cluster, 25 | [property: JsonPropertyName("country")] string Country, 26 | [property: JsonPropertyName("timestamp")] string Timestamp, 27 | [property: JsonPropertyName("platform")] string Platform 28 | ); 29 | 30 | public record BuiltData(string LoginUrl, string Session, string SdkSid, string Cluster, string Suuid, string Timestamp, string Language, Authentication.CountryCode CountryCode); 31 | 32 | public record QrDataSuccess( 33 | [property: JsonPropertyName("type")] string? Type, 34 | [property: JsonPropertyName("success")] Success? Success, 35 | [property: JsonPropertyName("country")] string? Country, 36 | [property: JsonPropertyName("timestamp")] string? Timestamp, 37 | [property: JsonPropertyName("platform")] string? Platform 38 | ); 39 | 40 | public record Success( 41 | [property: JsonPropertyName("login_token")] string? LoginToken, 42 | [property: JsonPropertyName("redirect_url")] string? RedirectUrl, 43 | [property: JsonPropertyName("is_console_link_session")] bool? IsConsoleLinkSession, 44 | [property: JsonPropertyName("auth_method")] string? AuthMethod, 45 | [property: JsonPropertyName("puuid")] string? Puuid 46 | ); 47 | 48 | public record Parameters( 49 | [property: JsonPropertyName("uri")] string Uri 50 | ); 51 | 52 | public record Response( 53 | [property: JsonPropertyName("mode")] string Mode, 54 | [property: JsonPropertyName("parameters")] Parameters Parameters 55 | ); 56 | 57 | public record AccessTokenReturn( 58 | [property: JsonPropertyName("type")] string Type, 59 | [property: JsonPropertyName("response")] Response Response, 60 | [property: JsonPropertyName("country")] string Country 61 | ); -------------------------------------------------------------------------------- /Authentication/SSIDReAuth/SSIDAuthManager.cs: -------------------------------------------------------------------------------- 1 | using System.Net; 2 | using Microsoft.IdentityModel.JsonWebTokens; 3 | using RadiantConnect.Authentication.DriverRiotAuth.Records; 4 | using RadiantConnect.Utilities; 5 | using Cookie = System.Net.Cookie; 6 | 7 | namespace RadiantConnect.Authentication.SSIDReAuth 8 | { 9 | internal class SsidAuthManager 10 | { 11 | internal static async Task Authenticate(string ssid, string? clid = "", string? csid = "", string? tdid = "") 12 | { 13 | (HttpClient client, CookieContainer container) = AuthUtil.BuildClient(); 14 | 15 | container.Add(new Cookie("ssid", ssid, "/", "auth.riotgames.com")); 16 | container.Add(new Cookie("clid", clid, "/", "auth.riotgames.com")); 17 | container.Add(new Cookie("csid", csid, "/", "auth.riotgames.com")); 18 | container.Add(new Cookie("tdid", tdid, "/", "auth.riotgames.com")); 19 | 20 | HttpResponseMessage response = await client.SendAsync(new HttpRequestMessage(HttpMethod.Get, "https://auth.riotgames.com/authorize?redirect_uri=https%3A%2F%2Fplayvalorant.com%2Fopt_in&client_id=play-valorant-web-prod&response_type=token%20id_token&nonce=1&scope=account%20openid")); 21 | 22 | string? validAuthUrl = response.RequestMessage?.RequestUri?.ToString(); 23 | 24 | if (string.IsNullOrEmpty(validAuthUrl)) 25 | throw new RadiantConnectAuthException("Failed to get Auth Url"); 26 | 27 | if (!validAuthUrl.Contains("access_token")) 28 | throw new RadiantConnectAuthException("Failed to find access tokens in auth, note in certain regions you must specify CLID"); 29 | 30 | if (!validAuthUrl.Contains("id_token")) 31 | throw new RadiantConnectAuthException("Failed to find id tokens in auth, note in certain regions you must specify CLID"); 32 | 33 | string accessToken = AuthUtil.ParseAccessToken(validAuthUrl); 34 | string idToken = AuthUtil.ParseIdToken(validAuthUrl); 35 | (string pasToken, string entitlementToken, object clientConfig, string _, string rmsToken) = await AuthUtil.GetTokens(accessToken); 36 | 37 | JsonWebToken token = new (accessToken); 38 | string suuid = token.Subject; 39 | 40 | JsonWebToken affinityJwt = new(pasToken); 41 | string? affinity = affinityJwt.GetPayloadValue("affinity"); 42 | string? chatAffinity = affinityJwt.GetPayloadValue("desired.affinity"); 43 | 44 | CookieCollection cookies = container.GetAllCookies(); 45 | 46 | client.Dispose(); 47 | 48 | return new RSOAuth( 49 | suuid, 50 | ssid, 51 | cookies.First(x => x.Name == "tdid").Value, 52 | cookies.First(x => x.Name == "csid").Value, 53 | cookies.First(x => x.Name == "clid").Value, 54 | accessToken, 55 | pasToken, 56 | entitlementToken, 57 | affinity, 58 | chatAffinity, 59 | clientConfig, 60 | null, 61 | idToken 62 | ) 63 | { 64 | RmsToken = rmsToken 65 | }; 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /EventHandler/Events/InGameEvents.cs: -------------------------------------------------------------------------------- 1 | using RadiantConnect.Utilities; 2 | 3 | namespace RadiantConnect.EventHandler.Events 4 | { 5 | public class InGameEvents 6 | { 7 | public delegate void InGameEvent(T value); 8 | 9 | public event InGameEvent? OnBuyMenuOpened; 10 | public event InGameEvent? OnBuyMenuClosed; 11 | 12 | public event InGameEvent? OnUtilPlaced; 13 | 14 | 15 | public void HandleInGameEvent(string invoker, string logData) 16 | { 17 | switch (invoker) 18 | { 19 | case "Buy_Menu_Opened": 20 | OnBuyMenuOpened?.Invoke(1); 21 | break; 22 | case "Buy_Menu_Closed": 23 | OnBuyMenuClosed?.Invoke(0); 24 | break; 25 | case "Util_Placed": 26 | string util = logData.ExtractValue(@"actor\s(\S+)(?=\.)", 1); 27 | OnUtilPlaced?.Invoke(util); 28 | break; 29 | } 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /EventHandler/Events/MatchEvents.cs: -------------------------------------------------------------------------------- 1 | using RadiantConnect.Utilities; 2 | 3 | namespace RadiantConnect.EventHandler.Events 4 | { 5 | public class MatchEvents 6 | { 7 | private string? _mapName; 8 | private static string GetWinningTeam(string log) => log.TryExtractSubstring("Team: ", '(', startIndex => startIndex >= 0).Trim().Replace("Team:'", "")[..^1]; 9 | private static string GetMapName(string log) => log.TryExtractSubstring("Map Name:", '|', startIndex => startIndex >= 0, "Map Name: ").Trim(); 10 | 11 | public delegate void MatchEvent(T value); 12 | 13 | public event MatchEvent? OnMapLoaded; 14 | public event MatchEvent? OnMatchEnded; 15 | public event MatchEvent? OnMatchStarted; 16 | 17 | public void HandleMatchEvent(string invoker, string logData) 18 | { 19 | switch (invoker) 20 | { 21 | case "Map_Loaded": 22 | _mapName = GetMapName(logData); 23 | OnMapLoaded?.Invoke(_mapName); 24 | break; 25 | case "Match_Ended": 26 | OnMatchEnded?.Invoke(GetWinningTeam(logData)); 27 | _mapName = null; 28 | break; 29 | case "Match_Started": 30 | OnMatchStarted?.Invoke(null); 31 | break; 32 | } 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /EventHandler/Events/MenuEvents.cs: -------------------------------------------------------------------------------- 1 | namespace RadiantConnect.EventHandler.Events 2 | { 3 | public class MenuEvents 4 | { 5 | public delegate void MenuEvent(T value); 6 | 7 | public event MenuEvent? OnBattlePassView; 8 | public event MenuEvent? OnAgentsView; 9 | public event MenuEvent? OnCareerView; 10 | public event MenuEvent? OnPlayScreen; 11 | public event MenuEvent? OnEsportView; 12 | public event MenuEvent? OnCollectionView; 13 | public event MenuEvent? OnStoreView; 14 | public event MenuEvent? OnPremierView; 15 | 16 | public void HandleMenuEvent(string invoker, string logData) 17 | { 18 | if (!logData.Contains("LogMenuStackManager")) return; 19 | 20 | switch (invoker) 21 | { 22 | case "BattlePassScreenV2_Opened": 23 | OnBattlePassView?.Invoke(null); 24 | break; 25 | case "CharactersScreenV2_Opened": 26 | OnAgentsView?.Invoke(null); 27 | break; 28 | case "MatchHistoryScreenWidgetV3_Opened": 29 | OnCareerView?.Invoke(null); 30 | break; 31 | case "PlayScreenV5_Opened": 32 | OnPlayScreen?.Invoke(null); 33 | break; 34 | case "Esports_MainScreen_Opened": 35 | OnEsportView?.Invoke(null); 36 | break; 37 | case "CollectionsScreen_Opened": 38 | OnCollectionView?.Invoke(null); 39 | break; 40 | case "TabbedStoreScreen_Opened": 41 | OnStoreView?.Invoke(null); 42 | break; 43 | case "TournamentsScreen_Opened": 44 | OnPremierView?.Invoke(null); 45 | break; 46 | } 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /EventHandler/Events/MiscEvents.cs: -------------------------------------------------------------------------------- 1 | namespace RadiantConnect.EventHandler.Events; 2 | 3 | public class MiscEvents 4 | { 5 | public delegate void MiscEvent(); 6 | 7 | public event MiscEvent? OnHeartbeat; 8 | 9 | public void HandleInGameEvent(string invoker, string logData) 10 | { 11 | switch (invoker) 12 | { 13 | case "Session_Heartbeat": 14 | OnHeartbeat?.Invoke(); 15 | break; 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /EventHandler/Events/PartyEvents.cs: -------------------------------------------------------------------------------- 1 | using RadiantConnect.Utilities; 2 | 3 | namespace RadiantConnect.EventHandler.Events 4 | { 5 | public class PartyEvents 6 | { 7 | public delegate void PartyEvent(string value); 8 | 9 | public event PartyEvent? OnChanged; 10 | public event PartyEvent? OnInviteSent; 11 | public event PartyEvent? OnInviteDeclined; 12 | public event PartyEvent? OnGamePodChanged; 13 | 14 | public void HandleMatchEvent(string invoker, string logData) 15 | { 16 | string partyId; 17 | switch (invoker) 18 | { 19 | case "Party_Updated": 20 | string partyNegateData = logData[..(logData.LastIndexOf('/')+1)]; 21 | partyId = logData.Replace(partyNegateData, ""); 22 | OnChanged?.Invoke(partyId); 23 | break; 24 | case "Party_InviteToParty": 25 | partyId = logData.ExtractValue(@"\/parties\/([a-fA-F\d-]+)\/", 1); 26 | OnInviteSent?.Invoke(partyId); 27 | break; 28 | case "Party_DeclineRequest": 29 | partyId = logData.ExtractValue(@"\/parties\/([a-fA-F\d-]+)\/", 1); 30 | OnInviteDeclined?.Invoke(partyId); 31 | break; 32 | case "Party_SetPreferredGamePods": 33 | partyId = logData.ExtractValue(@"\/parties\/([a-fA-F\d-]+)\/", 1); 34 | OnGamePodChanged?.Invoke(partyId); 35 | break; 36 | } 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /EventHandler/Events/PreGameEvents.cs: -------------------------------------------------------------------------------- 1 | using RadiantConnect.Methods; 2 | using RadiantConnect.Utilities; 3 | 4 | namespace RadiantConnect.EventHandler.Events 5 | { 6 | public class PreGameEvents(Initiator initiator) 7 | { 8 | private string _matchId = null!; 9 | public delegate void QueueEvent(string id); 10 | 11 | public event QueueEvent? OnPreGamePlayerLoaded; 12 | public event QueueEvent? OnPreGameMatchLoaded; 13 | public event QueueEvent? OnAgentSelected; 14 | public event QueueEvent? OnAgentLockedIn; 15 | 16 | public void HandlePreGameEvents(string invoker, string logData) 17 | { 18 | string agentId; 19 | switch (invoker) 20 | { 21 | case "Pregame_GetPlayer": 22 | OnPreGamePlayerLoaded?.Invoke(initiator.ExternalSystem.ClientData.UserId); 23 | break; 24 | case "Pregame_GetMatch": 25 | string matchId = logData.ExtractValue(@"matches/([a-fA-F\d-]+)", 1); 26 | if (string.IsNullOrEmpty(matchId)) return; 27 | if (matchId == _matchId) return; 28 | _matchId = matchId; 29 | OnPreGameMatchLoaded?.Invoke(matchId); 30 | break; 31 | case "Pregame_LockCharacter": 32 | agentId = logData.ExtractValue(@"lock/([a-fA-F\d-]+)", 1); 33 | OnAgentLockedIn?.Invoke(ValorantTables.AgentIdToAgent[agentId]); 34 | break; 35 | case "Pregame_SelectCharacter": 36 | agentId = logData.ExtractValue(@"select/([a-fA-F\d-]+)", 1); 37 | OnAgentSelected?.Invoke(ValorantTables.AgentIdToAgent[agentId]); 38 | break; 39 | } 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /EventHandler/Events/RoundEvents.cs: -------------------------------------------------------------------------------- 1 | using RadiantConnect.Utilities; 2 | 3 | // ReSharper disable RedundantDefaultMemberInitializer 4 | 5 | namespace RadiantConnect.EventHandler.Events 6 | { 7 | public class RoundEvents 8 | { 9 | private bool _roundEnded = false; 10 | private int _roundNumber = 0; 11 | public delegate void RoundEvent(int roundNumber); 12 | 13 | public event RoundEvent? OnRoundStarted; 14 | public event RoundEvent? OnRoundEnded; 15 | 16 | public void ResetRound() { _roundNumber = 0; } 17 | 18 | public void HandleRoundEvent(string invoker, string logData) 19 | { 20 | switch (invoker) 21 | { 22 | case "Round_Started": 23 | if (!_roundEnded) return; 24 | _roundNumber++; 25 | OnRoundStarted?.Invoke(_roundNumber); 26 | _roundEnded = false; 27 | break; 28 | case "Round_Ended": 29 | int roundNumber = int.Parse(logData.ExtractValue(@"round '([a-fA-F\d-]+)'", 1)) + 1; 30 | if (_roundNumber < roundNumber) _roundNumber = roundNumber; 31 | OnRoundEnded?.Invoke(roundNumber); 32 | _roundEnded = true; 33 | break; 34 | } 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /EventHandler/Events/VoteEvents.cs: -------------------------------------------------------------------------------- 1 | namespace RadiantConnect.EventHandler.Events 2 | { 3 | public class VoteEvents 4 | { 5 | public delegate void VoteEvent(bool yesNo); 6 | 7 | public event VoteEvent? OnVoteDeclared; 8 | public event VoteEvent? OnVoteInvoked; 9 | 10 | public event VoteEvent? OnSurrenderCalled; 11 | public event VoteEvent? OnRemakeCalled; 12 | public event VoteEvent? OnTimeoutCalled; 13 | 14 | public void HandleVoteEvent(string invoker, string logData) 15 | { 16 | switch (invoker) 17 | { 18 | case "Vote_Called": 19 | OnVoteDeclared?.Invoke(true); 20 | break; 21 | case "Vote_Invoked": 22 | OnVoteInvoked?.Invoke(logData[^1] == 's'); 23 | break; 24 | case "Surrender_Called": 25 | OnSurrenderCalled?.Invoke(true); 26 | break; 27 | case "Timeout_Called": 28 | OnTimeoutCalled?.Invoke(true); 29 | break; 30 | case "Remake_Called": 31 | OnRemakeCalled?.Invoke(true); 32 | break; 33 | } 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /HenrikApi/Accounts.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace RadiantConnect.HenrikApi 8 | { 9 | internal class Accounts 10 | { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /HenrikApi/Content.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace RadiantConnect.HenrikApi 8 | { 9 | internal class Content 10 | { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /HenrikApi/Crosshair.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace RadiantConnect.HenrikApi 8 | { 9 | internal class Crosshair 10 | { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /HenrikApi/Esports.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace RadiantConnect.HenrikApi 8 | { 9 | internal class Esports 10 | { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /HenrikApi/Leaderboard.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace RadiantConnect.HenrikApi 8 | { 9 | internal class Leaderboard 10 | { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /HenrikApi/MMR.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace RadiantConnect.HenrikApi 8 | { 9 | internal class MMR 10 | { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /HenrikApi/MMRHistory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace RadiantConnect.HenrikApi 8 | { 9 | internal class MMRHistory 10 | { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /HenrikApi/Match.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace RadiantConnect.HenrikApi 8 | { 9 | internal class Match 10 | { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /HenrikApi/Matchlist.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace RadiantConnect.HenrikApi 8 | { 9 | internal class Matchlist 10 | { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /HenrikApi/Premier.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace RadiantConnect.HenrikApi 8 | { 9 | internal class Premier 10 | { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /HenrikApi/QueueStatus.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace RadiantConnect.HenrikApi 8 | { 9 | internal class QueueStatus 10 | { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /HenrikApi/Raw.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace RadiantConnect.HenrikApi 8 | { 9 | internal class Raw 10 | { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /HenrikApi/Status.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace RadiantConnect.HenrikApi 8 | { 9 | internal class Status 10 | { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /HenrikApi/Store.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace RadiantConnect.HenrikApi 8 | { 9 | internal class Store 10 | { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /HenrikApi/StoredData.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace RadiantConnect.HenrikApi 8 | { 9 | internal class StoredData 10 | { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /HenrikApi/Website.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace RadiantConnect.HenrikApi 8 | { 9 | internal class Website 10 | { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /ImageRecognition/Handlers/ImageCaptureHandler.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | using System.Runtime.InteropServices; 3 | using RadiantConnect.Utilities; 4 | using System.Drawing; 5 | using System.Drawing.Drawing2D; 6 | 7 | #pragma warning disable CA1416 8 | 9 | namespace RadiantConnect.ImageRecognition.Handlers 10 | { 11 | internal static class ImageCaptureHandler 12 | { 13 | [DllImport("user32.dll")] 14 | public static extern bool GetWindowRect(nint hwnd, ref Rectangle rectangle); 15 | // Kill feed offsets 16 | internal const int KillFeedHeight = 700; 17 | internal const int KillFeedWidth = 900; 18 | internal const int KillFeedWidthOffset = 110; 19 | 20 | // Spike offsets 21 | internal const int SpikeBoxWidth = 200; 22 | internal const int SpikeBoxHeight = 80; 23 | internal const int HeightOffset = 10; 24 | 25 | internal static Rectangle GetValorantRectangle() 26 | { 27 | if (!InternalValorantMethods.IsValorantProcessRunning()) throw new RadiantConnectException("Valorant is not running"); 28 | 29 | nint processHandle = Process.GetProcessesByName("VALORANT-Win64-Shipping")[0].MainWindowHandle; 30 | Rectangle captureRectangle = new(); 31 | GetWindowRect(processHandle, ref captureRectangle); 32 | 33 | return captureRectangle; 34 | } 35 | internal static Bitmap GetSpikeBox() 36 | { 37 | Rectangle valorantRectangle = GetValorantRectangle(); 38 | 39 | int valorantMiddle = (valorantRectangle.Width - SpikeBoxWidth) / 2; 40 | 41 | Bitmap croppedScreenshot = new(SpikeBoxWidth, SpikeBoxHeight); 42 | 43 | using Graphics graphics = Graphics.FromImage(croppedScreenshot); 44 | graphics.CopyFromScreen(valorantMiddle, HeightOffset, 0, -HeightOffset, croppedScreenshot.Size); 45 | 46 | return croppedScreenshot; 47 | } 48 | 49 | internal static Bitmap GetKillFeedBox(Point captureLocation = default, Size captureSize = default) 50 | { 51 | Rectangle valorantRectangle = GetValorantRectangle(); 52 | 53 | captureLocation = captureLocation with { X = valorantRectangle.Width - KillFeedWidth + captureLocation.X + KillFeedWidthOffset }; 54 | captureSize = new Size(KillFeedWidth - KillFeedWidthOffset, captureSize.Height > 0 ? captureSize.Height : KillFeedHeight); 55 | 56 | Bitmap bitmap = new(captureSize.Width, captureSize.Height); 57 | using Graphics graphics = Graphics.FromImage(bitmap); 58 | graphics.CompositingQuality = CompositingQuality.HighQuality; 59 | graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; 60 | graphics.CopyFromScreen(captureLocation, Point.Empty, captureSize); 61 | 62 | return bitmap; 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /ImageRecognition/Handlers/Spike/ActionDetection.cs: -------------------------------------------------------------------------------- 1 |  2 | using System.Drawing; 3 | using RadiantConnect.ImageRecognition.Internals; 4 | 5 | #pragma warning disable CA1416 6 | 7 | namespace RadiantConnect.ImageRecognition.Handlers.Spike 8 | { 9 | internal class ActionDetection 10 | { 11 | internal static bool SpikePlantedResult(Bitmap spikeItem, ColorConfig? colorConfig = null) 12 | { 13 | int middle = spikeItem.Width / 2; 14 | bool wasFound = false; 15 | 16 | for (int yIndex = 0; yIndex < spikeItem.Height; yIndex++) 17 | { 18 | Color pixelColor = spikeItem.GetPixel(middle, yIndex); 19 | if (!ColorHandler.IsSpikeRed(pixelColor, colorConfig?.SpikeColorConfig)) continue; 20 | wasFound = true; 21 | break; 22 | } 23 | 24 | return wasFound; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /ImageRecognition/Handlers/Spike/SpikeHandler.cs: -------------------------------------------------------------------------------- 1 | using System.Drawing; 2 | using RadiantConnect.ImageRecognition.Internals; 3 | 4 | // ReSharper disable MethodSupportsCancellation 5 | #pragma warning disable CA1416 6 | 7 | // ReSharper disable 8 | namespace RadiantConnect.ImageRecognition.Handlers.Spike 9 | { 10 | public class SpikeHandler 11 | { 12 | internal CancellationTokenSource SpikeCancellationSource = new(); 13 | internal CancellationToken SpikeCancellationToken; 14 | 15 | public delegate void SpikeEvent(); 16 | public event SpikeEvent? OnSpikeActive; 17 | public event SpikeEvent? OnSpikeDeActive; 18 | 19 | internal int FalseCounter; 20 | internal bool SpikeActive; 21 | 22 | public SpikeHandler() 23 | { 24 | SpikeCancellationToken = SpikeCancellationSource.Token; 25 | } 26 | 27 | public async Task StartSpikeDetection(ColorConfig? colorConfig = null) 28 | { 29 | SpikeCancellationSource.TryReset(); 30 | 31 | while (!SpikeCancellationToken.IsCancellationRequested) 32 | { 33 | Bitmap spikeBox = ImageCaptureHandler.GetSpikeBox(); 34 | bool spikePlanted = ActionDetection.SpikePlantedResult(spikeBox, colorConfig); 35 | 36 | switch (spikePlanted) 37 | { 38 | case true when !SpikeActive: 39 | FalseCounter = 0; 40 | SpikeActive = true; 41 | OnSpikeActive?.Invoke(); 42 | break; 43 | case false when SpikeActive: 44 | { 45 | if (FalseCounter > 20) 46 | { 47 | SpikeActive = false; 48 | OnSpikeDeActive?.Invoke(); 49 | } 50 | else FalseCounter++; 51 | 52 | break; 53 | } 54 | } 55 | 56 | spikeBox.Dispose(); 57 | 58 | await Task.Delay(10); 59 | } 60 | } 61 | 62 | public void StopSpikeDetection() { SpikeCancellationSource.Cancel(); } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /ImageRecognition/ImageRecognition.cs: -------------------------------------------------------------------------------- 1 | using System.Drawing; 2 | using RadiantConnect.ImageRecognition.Handlers.KillFeed; 3 | using RadiantConnect.ImageRecognition.Handlers.Spike; 4 | using RadiantConnect.ImageRecognition.Internals; 5 | 6 | #pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed 7 | 8 | namespace RadiantConnect.ImageRecognition 9 | { 10 | public class ImageRecognition 11 | { 12 | public delegate void HandlerCreated(T value); 13 | 14 | public event HandlerCreated? OnKillFeedHandlerCreated; 15 | public event HandlerCreated? OnSpikeHandlerCreated; 16 | 17 | public KillFeedHandler? KillFeedHandler { get; internal set; } 18 | public SpikeHandler? SpikeHandler { get; internal set; } 19 | 20 | internal static void DrawDebugLine(Bitmap bitmap, int x, int y, int width, Color color) 21 | { 22 | using Graphics g = Graphics.FromImage(bitmap); 23 | using Pen pen = new(color, width); 24 | g.DrawLine(pen, x, y, x + width, y); 25 | } 26 | 27 | [Obsolete("No longer maintained, may not work correctly.")] 28 | public void Initiator(Config config) 29 | { 30 | KillFeedConfig feedConfig = config.KillFeedConfig; 31 | 32 | if (feedConfig.CheckAssists || feedConfig.CheckKilled || feedConfig.CheckWasKilled) Task.Run(() => 33 | { 34 | KillFeedHandler = new KillFeedHandler(); 35 | OnKillFeedHandlerCreated?.Invoke(KillFeedHandler); 36 | KillFeedHandler.StartKillDetection(feedConfig, config.ColorConfig); 37 | }); 38 | 39 | if (config.SpikePlanted) 40 | { 41 | SpikeHandler = new SpikeHandler(); 42 | OnSpikeHandlerCreated?.Invoke(SpikeHandler); 43 | SpikeHandler.StartSpikeDetection(config.ColorConfig); 44 | } 45 | } 46 | } 47 | } -------------------------------------------------------------------------------- /ImageRecognition/Internals/IntMethods.cs: -------------------------------------------------------------------------------- 1 | namespace RadiantConnect.ImageRecognition.Internals 2 | { 3 | internal static class IntMethods 4 | { 5 | internal static bool IsClose(this int caller, int toCheck, int range) 6 | { 7 | long minimum = (long)caller - range; 8 | long maximum = (long)caller + range; 9 | 10 | return toCheck >= minimum && toCheck <= maximum; 11 | } 12 | 13 | public static bool IsWithinFourSeconds(this TimeOnly time1, TimeOnly time2) 14 | { 15 | if (time1.Hour != time2.Hour) return false; 16 | if (time1.Minute != time2.Minute) return false; 17 | if (time1.Second.IsClose(time2.Second, 3)) return true; 18 | if (time1.Millisecond.IsClose(time2.Millisecond, 300)) return true; 19 | return false; 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /ImageRecognition/Internals/RecognitionRecords.cs: -------------------------------------------------------------------------------- 1 | using System.Drawing; 2 | 3 | namespace RadiantConnect.ImageRecognition.Internals; 4 | 5 | public record SpikeColorConfig(Color LowestColor, Color HighestColor); 6 | 7 | public record ActionColorConfig(Color LowestColor, Color HighestColor); 8 | 9 | public record RedConfig(Color LowestColor, Color HighestColor); 10 | 11 | public record GreenConfig(Color LowestColor, Color HighestColor); 12 | 13 | public record ColorConfig(SpikeColorConfig SpikeColorConfig, ActionColorConfig ActionColorConfig, RedConfig RedConfig, GreenConfig GreenConfig); 14 | 15 | internal record KillFeedPositions(int RedPixel, int GreenPixel, int Middle, bool ValidPosition, TimeOnly KillTime); 16 | 17 | internal record KillFeedAction(bool PerformedKill, bool WasKilled, bool WasAssist, bool WasInFeed, KillFeedPositions Positions); 18 | 19 | public record KillFeedConfig(bool CheckKilled, bool CheckAssists, bool CheckWasKilled); 20 | 21 | public record Config(KillFeedConfig KillFeedConfig, bool SpikePlanted, ColorConfig? ColorConfig = null); -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 Iris 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Network/ChatEndpoints/ChatEndpoints.cs: -------------------------------------------------------------------------------- 1 | using System.Net.Http.Json; 2 | using RadiantConnect.Network.ChatEndpoints.DataTypes; 3 | 4 | namespace RadiantConnect.Network.ChatEndpoints; 5 | 6 | public class ChatEndpoints(Initiator initiator) 7 | { 8 | public async Task GetChatInfo() 9 | { 10 | return await initiator.ExternalSystem.Net.GetAsync($"https://127.0.0.1:{ValorantNet.GetAuthPort()}", "/chat/v6/conversations"); 11 | } 12 | 13 | internal async Task GetChatParticipants() 14 | { 15 | return await initiator.ExternalSystem.Net.GetAsync($"https://127.0.0.1:{ValorantNet.GetAuthPort()}", "/chat/v5/participants"); 16 | } 17 | 18 | internal async Task GetMessageHistory() 19 | { 20 | return await initiator.ExternalSystem.Net.GetAsync($"https://127.0.0.1:{ValorantNet.GetAuthPort()}", "/chat/v6/messages"); 21 | } 22 | 23 | internal async Task SendChatMessage(NewMessage newMessage) 24 | { 25 | return await initiator.ExternalSystem.Net.PostAsync($"https://127.0.0.1:{ValorantNet.GetAuthPort()}", "/chat/v6/messages", JsonContent.Create(newMessage)); 26 | } 27 | } -------------------------------------------------------------------------------- /Network/ChatEndpoints/DataTypes/ChatInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace RadiantConnect.Network.ChatEndpoints.DataTypes; 4 | 5 | public record Conversation( 6 | [property: JsonPropertyName("cid")] string Cid, 7 | [property: JsonPropertyName("direct_messages")] bool DirectMessages, 8 | [property: JsonPropertyName("global_readership")] bool GlobalReadership, 9 | [property: JsonPropertyName("message_history")] bool MessageHistory, 10 | [property: JsonPropertyName("mid")] string Mid, 11 | [property: JsonPropertyName("muted")] bool Muted, 12 | [property: JsonPropertyName("mutedRestriction")] bool MutedRestriction, 13 | [property: JsonPropertyName("type")] string Type, 14 | [property: JsonPropertyName("uiState")] UiState UiState, 15 | [property: JsonPropertyName("unread_count")] int UnreadCount 16 | ); 17 | 18 | public record ChatInfo( 19 | [property: JsonPropertyName("conversations")] IReadOnlyList Conversations 20 | ); 21 | 22 | public record UiState( 23 | [property: JsonPropertyName("changedSinceHidden")] bool ChangedSinceHidden, 24 | [property: JsonPropertyName("hidden")] bool Hidden 25 | ); 26 | 27 | -------------------------------------------------------------------------------- /Network/ChatEndpoints/DataTypes/ChatParticipant.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | namespace RadiantConnect.Network.ChatEndpoints.DataTypes; 3 | // ReSharper disable All 4 | 5 | public record Participant( 6 | [property: JsonPropertyName("activePlatform")] object ActivePlatform, 7 | [property: JsonPropertyName("cid")] string Cid, 8 | [property: JsonPropertyName("game_name")] string GameName, 9 | [property: JsonPropertyName("game_tag")] string GameTag, 10 | [property: JsonPropertyName("muted")] bool Muted, 11 | [property: JsonPropertyName("name")] string Name, 12 | [property: JsonPropertyName("pid")] string Pid, 13 | [property: JsonPropertyName("puuid")] string Puuid, 14 | [property: JsonPropertyName("region")] string Region 15 | ); 16 | 17 | public record ChatParticipant( 18 | [property: JsonPropertyName("participants")] IReadOnlyList Participants 19 | ); 20 | 21 | -------------------------------------------------------------------------------- /Network/ChatEndpoints/DataTypes/Message.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | namespace RadiantConnect.Network.ChatEndpoints.DataTypes; 3 | // ReSharper disable All 4 | 5 | public record Message( 6 | [property: JsonPropertyName("body")] string Body, 7 | [property: JsonPropertyName("cid")] string Cid, 8 | [property: JsonPropertyName("droppedDueToThrottle")] bool DroppedDueToThrottle, 9 | [property: JsonPropertyName("game_name")] string GameName, 10 | [property: JsonPropertyName("game_tag")] string GameTag, 11 | [property: JsonPropertyName("id")] string Id, 12 | [property: JsonPropertyName("mid")] string Mid, 13 | [property: JsonPropertyName("name")] string Name, 14 | [property: JsonPropertyName("pid")] string Pid, 15 | [property: JsonPropertyName("puuid")] string Puuid, 16 | [property: JsonPropertyName("read")] bool Read, 17 | [property: JsonPropertyName("region")] string Region, 18 | [property: JsonPropertyName("time")] string Time, 19 | [property: JsonPropertyName("type")] string Type, 20 | [property: JsonPropertyName("uicEvent")] bool UicEvent 21 | ); 22 | 23 | public record InternalMessages( 24 | [property: JsonPropertyName("messages")] IReadOnlyList Messages 25 | ); -------------------------------------------------------------------------------- /Network/ChatEndpoints/DataTypes/NewMessage.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | namespace RadiantConnect.Network.ChatEndpoints.DataTypes; 3 | 4 | // ReSharper disable All 5 | 6 | public enum ChatType 7 | { 8 | groupchat, 9 | chat, 10 | system 11 | } 12 | 13 | public record NewMessage( 14 | [property: JsonPropertyName("cid")] string ConversationId, 15 | [property: JsonPropertyName("message")] string Message, 16 | [property: JsonPropertyName("type")] string ChatType 17 | ); -------------------------------------------------------------------------------- /Network/ContractEndpoints/ContractEndpoints.cs: -------------------------------------------------------------------------------- 1 |  2 | using RadiantConnect.Network.ContractEndpoints.DataTypes; 3 | 4 | namespace RadiantConnect.Network.ContractEndpoints; 5 | 6 | public class ContractEndpoints(Initiator initiator) 7 | { 8 | internal string Url = initiator.ExternalSystem.ClientData.PdUrl; 9 | 10 | public async Task GetItemUpgradesAsync() 11 | { 12 | return await initiator.ExternalSystem.Net.GetAsync(Url, "/contract-definitions/v3/item-upgrades"); 13 | } 14 | 15 | public async Task GetContractsAsync(string userId) 16 | { 17 | return await initiator.ExternalSystem.Net.GetAsync(Url, $"/contracts/v1/contracts/{userId}"); 18 | } 19 | } -------------------------------------------------------------------------------- /Network/ContractEndpoints/DataTypes/ItemUpgrade.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace RadiantConnect.Network.ContractEndpoints.DataTypes; 4 | 5 | // ReSharper disable All 6 | public record Cost( 7 | [property: JsonPropertyName("WalletCosts")] IReadOnlyList WalletCosts 8 | ); 9 | 10 | public record Definition( 11 | [property: JsonPropertyName("ID")] string ID, 12 | [property: JsonPropertyName("Item")] Item Item, 13 | [property: JsonPropertyName("RequiredEntitlement")] RequiredEntitlement RequiredEntitlement, 14 | [property: JsonPropertyName("ProgressionSchedule")] ProgressionSchedule ProgressionSchedule, 15 | [property: JsonPropertyName("RewardSchedule")] RewardSchedule RewardSchedule, 16 | [property: JsonPropertyName("Sidegrades")] IReadOnlyList Sidegrades 17 | ); 18 | 19 | public record EntitlementReward( 20 | [property: JsonPropertyName("ItemTypeID")] string ItemTypeID, 21 | [property: JsonPropertyName("ItemID")] string ItemID, 22 | [property: JsonPropertyName("Amount")] int Amount 23 | ); 24 | 25 | public record Item( 26 | [property: JsonPropertyName("ItemTypeID")] string ItemTypeID, 27 | [property: JsonPropertyName("ItemID")] string ItemID 28 | ); 29 | 30 | public record Option( 31 | [property: JsonPropertyName("OptionID")] string OptionID, 32 | [property: JsonPropertyName("Cost")] Cost Cost, 33 | [property: JsonPropertyName("Rewards")] IReadOnlyList Rewards 34 | ); 35 | 36 | public record Prerequisites( 37 | [property: JsonPropertyName("RequiredEntitlements")] IReadOnlyList RequiredEntitlements 38 | ); 39 | 40 | public record ProgressionSchedule( 41 | [property: JsonPropertyName("Name")] string Name, 42 | [property: JsonPropertyName("ProgressionCurrencyID")] string ProgressionCurrencyID, 43 | [property: JsonPropertyName("ProgressionDeltaPerLevel")] IReadOnlyList ProgressionDeltaPerLevel 44 | ); 45 | 46 | public record RequiredEntitlement( 47 | [property: JsonPropertyName("ItemTypeID")] string ItemTypeID, 48 | [property: JsonPropertyName("ItemID")] string ItemID 49 | ); 50 | 51 | public record RequiredEntitlement2( 52 | [property: JsonPropertyName("ItemTypeID")] string ItemTypeID, 53 | [property: JsonPropertyName("ItemID")] string ItemID 54 | ); 55 | 56 | public record Reward( 57 | [property: JsonPropertyName("ItemTypeID")] string ItemTypeID, 58 | [property: JsonPropertyName("ItemID")] string ItemID, 59 | [property: JsonPropertyName("Amount")] long Amount 60 | ); 61 | 62 | public record RewardSchedule( 63 | [property: JsonPropertyName("ID")] string ID, 64 | [property: JsonPropertyName("Name")] string Name, 65 | [property: JsonPropertyName("Prerequisites")] object Prerequisites, 66 | [property: JsonPropertyName("RewardsPerLevel")] IReadOnlyList RewardsPerLevel 67 | ); 68 | 69 | public record RewardsPerLevel( 70 | [property: JsonPropertyName("EntitlementRewards")] IReadOnlyList EntitlementRewards, 71 | [property: JsonPropertyName("WalletRewards")] object WalletRewards, 72 | [property: JsonPropertyName("CounterRewards")] object CounterRewards 73 | ); 74 | 75 | public record ItemUpgrade( 76 | [property: JsonPropertyName("Definitions")] IReadOnlyList Definitions 77 | ); 78 | 79 | public record Sidegrade( 80 | [property: JsonPropertyName("SidegradeID")] string SidegradeID, 81 | [property: JsonPropertyName("Options")] IReadOnlyList