├── .gitignore ├── LICENSE ├── Plugins └── Rivet │ ├── Resources │ └── Icon128.png │ ├── Rivet.uplugin │ └── Source │ └── Rivet │ ├── Private │ ├── MatchmakerLobbiesFind.cpp │ ├── MatchmakerLobbiesJoin.cpp │ ├── MatchmakerLobbiesReady.cpp │ ├── MatchmakerPlayersConnected.cpp │ ├── MatchmakerPlayersDisconnected.cpp │ ├── RivetClient.cpp │ ├── RivetHttpEndpoint.cpp │ ├── RivetModule.cpp │ └── RivetPlayer.cpp │ ├── Public │ ├── MatchmakerCommon.h │ ├── MatchmakerLobbiesFind.h │ ├── MatchmakerLobbiesJoin.h │ ├── MatchmakerLobbiesReady.h │ ├── MatchmakerPlayersConnected.h │ ├── MatchmakerPlayersDisconnected.h │ ├── Rivet.h │ ├── RivetClient.h │ ├── RivetHttpEndpoint.h │ └── RivetPlayer.h │ └── Rivet.Build.cs └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by https://www.toptal.com/developers/gitignore/api/unrealengine 2 | # Edit at https://www.toptal.com/developers/gitignore?templates=unrealengine 3 | 4 | ### UnrealEngine ### 5 | # Visual Studio 2015 user specific files 6 | .vs/ 7 | 8 | # Compiled Object files 9 | *.slo 10 | *.lo 11 | *.o 12 | *.obj 13 | 14 | # Precompiled Headers 15 | *.gch 16 | *.pch 17 | 18 | # Compiled Dynamic libraries 19 | *.so 20 | *.dylib 21 | *.dll 22 | 23 | # Fortran module files 24 | *.mod 25 | 26 | # Compiled Static libraries 27 | *.lai 28 | *.la 29 | *.a 30 | *.lib 31 | 32 | # Executables 33 | *.exe 34 | *.out 35 | *.app 36 | *.ipa 37 | 38 | # These project files can be generated by the engine 39 | *.xcodeproj 40 | *.xcworkspace 41 | *.sln 42 | *.suo 43 | *.opensdf 44 | *.sdf 45 | *.VC.db 46 | *.VC.opendb 47 | 48 | # Precompiled Assets 49 | SourceArt/**/*.png 50 | SourceArt/**/*.tga 51 | 52 | # Binary Files 53 | Binaries/* 54 | Plugins/*/Binaries/* 55 | 56 | # Builds 57 | Build/* 58 | 59 | # Whitelist PakBlacklist-.txt files 60 | !Build/*/ 61 | Build/*/** 62 | !Build/*/PakBlacklist*.txt 63 | 64 | # Don't ignore icon files in Build 65 | !Build/**/*.ico 66 | 67 | # Built data for maps 68 | *_BuiltData.uasset 69 | 70 | # Configuration files generated by the Editor 71 | Saved/* 72 | 73 | # Compiled source files for the engine to use 74 | Intermediate/* 75 | Plugins/*/Intermediate/* 76 | 77 | # Cache files for the editor to use 78 | DerivedDataCache/* 79 | 80 | ### UnrealEngine Patch ### 81 | # Don't ignore icon and splash images for mobile app 82 | !Build/IOS/Resources/ 83 | Build/IOS/Resources/* 84 | !Build/IOS/Resources/Graphics/ 85 | Build/IOS/Resources/Graphics/* 86 | !Build/IOS/Resources/Graphics/*.png 87 | !Build/Android/res/ 88 | Build/Android/res/* 89 | !Build/Android/res/*/ 90 | Build/Android/res/*/* 91 | !Build/Android/res/*/*.png 92 | # Ignore plugins binaries on deep subfolders 93 | Plugins/**/Binaries/* 94 | Plugins/**/Intermediate/* 95 | 96 | # End of https://www.toptal.com/developers/gitignore/api/unrealengine 97 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright 2023 Rivet Gaming, Inc. 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /Plugins/Rivet/Resources/Icon128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenGameBackend/plugin-unreal/89ac29e709f0d94556f117256fe8dd4326308b91/Plugins/Rivet/Resources/Icon128.png -------------------------------------------------------------------------------- /Plugins/Rivet/Rivet.uplugin: -------------------------------------------------------------------------------- 1 | { 2 | "FileVersion" : 3, 3 | "Version" : 1, 4 | "VersionName" : "0.0.1", 5 | "FriendlyName" : "Rivet Plugin", 6 | "Description" : "Open-source solution to deploy, scale, and operate your multiplayer game", 7 | "Category" : "Multiplayer", 8 | "CreatedBy" : "Rivet Gaming, Inc.", 9 | "CreatedByURL" : "https://rivet.gg/", 10 | "DocsURL" : "https://rivet.gg/learn/unreal", 11 | "MarketplaceURL" : "", 12 | "SupportURL" : "https://rivet.gg/support", 13 | "EnabledByDefault" : true, 14 | "CanContainContent" : false, 15 | "IsBetaVersion" : false, 16 | "Installed" : false, 17 | "Modules" : 18 | [ 19 | { 20 | "Name" : "Rivet", 21 | "Type" : "Runtime", 22 | "LoadingPhase" : "Default", 23 | "WhitelistPlatforms": [ 24 | "Win64", 25 | "Linux", 26 | "IOS", 27 | "Mac" 28 | ] 29 | } 30 | ] 31 | } 32 | -------------------------------------------------------------------------------- /Plugins/Rivet/Source/Rivet/Private/MatchmakerLobbiesFind.cpp: -------------------------------------------------------------------------------- 1 | #include "MatchmakerLobbiesFind.h" 2 | #include "JsonObjectConverter.h" 3 | 4 | TSharedPtr FMatchmakerLobbiesFindRequest::ToJson() const 5 | { 6 | TSharedPtr Req = MakeShareable(new FJsonObject); 7 | 8 | TArray> GameModesJsonArray; 9 | for (const FString& GameMode : GameModes) 10 | { 11 | GameModesJsonArray.Add(MakeShared(GameMode)); 12 | } 13 | Req->SetArrayField(TEXT("game_modes"), GameModesJsonArray); 14 | 15 | TArray> RegionsJsonArray; 16 | for (const FString& Region : Regions) 17 | { 18 | RegionsJsonArray.Add(MakeShared(Region)); 19 | } 20 | if (!RegionsJsonArray.IsEmpty()) 21 | { 22 | Req->SetArrayField(TEXT("regions"), RegionsJsonArray); 23 | } 24 | 25 | Req->SetBoolField(TEXT("prevent_auto_create_lobby"), PreventAutoCreateLobby); 26 | 27 | return Req; 28 | } 29 | 30 | void UMatchmakerLobbiesFindEndpoint::HandleResponse(TSharedPtr ResponseJson) const 31 | { 32 | FMatchmakerLobbiesFindResponse Res; 33 | 34 | auto LobbyJson = ResponseJson->GetObjectField("lobby"); 35 | Res.Lobby.LobbyId = LobbyJson->GetStringField("lobby_id"); 36 | 37 | auto Ports = ResponseJson->GetObjectField("ports"); 38 | for (const auto& Pair : Ports->Values) 39 | { 40 | auto PortJson = Pair.Value->AsObject(); 41 | 42 | FMatchmakerJoinPort Port; 43 | Port.Host = PortJson->GetStringField("host"); 44 | Port.Hostname = PortJson->GetStringField("hostname"); 45 | PortJson->TryGetNumberField("port", Port.Port); 46 | 47 | const TSharedPtr* PortRangeJson; 48 | if (PortJson->TryGetObjectField("port_range", PortRangeJson)) 49 | { 50 | FMatchmakerJoinPortRange PortRange; 51 | (*PortRangeJson)->TryGetNumberField("min", PortRange.Min); 52 | (*PortRangeJson)->TryGetNumberField("max", PortRange.Max); 53 | } 54 | 55 | Port.IsTls = PortJson->GetBoolField("is_tls"); 56 | 57 | Res.Ports.Add(Pair.Key, Port); 58 | } 59 | 60 | auto PlayerJson = ResponseJson->GetObjectField("player"); 61 | Res.Player.Token = PlayerJson->GetStringField("token"); 62 | 63 | OnSuccess.ExecuteIfBound(Res); 64 | } 65 | -------------------------------------------------------------------------------- /Plugins/Rivet/Source/Rivet/Private/MatchmakerLobbiesJoin.cpp: -------------------------------------------------------------------------------- 1 | #include "MatchmakerLobbiesJoin.h" 2 | 3 | TSharedPtr FMatchmakerLobbiesJoinRequest::ToJson() const 4 | { 5 | TSharedPtr Req = MakeShareable(new FJsonObject); 6 | Req->SetStringField(TEXT("lobby_id"), LobbyId); 7 | return Req; 8 | } 9 | 10 | void UMatchmakerLobbiesJoinEndpoint::HandleResponse(TSharedPtr ResponseJson) const 11 | { 12 | FMatchmakerLobbiesJoinResponse Res; 13 | 14 | auto LobbyJson = ResponseJson->GetObjectField("lobby"); 15 | Res.Lobby.LobbyId = LobbyJson->GetStringField("lobby_id"); 16 | 17 | auto Ports = ResponseJson->GetObjectField("ports"); 18 | for (const auto& Pair : Ports->Values) 19 | { 20 | auto PortJson = Pair.Value->AsObject(); 21 | 22 | FMatchmakerJoinPort Port; 23 | Port.Host = PortJson->GetStringField("host"); 24 | Port.Hostname = PortJson->GetStringField("hostname"); 25 | PortJson->TryGetNumberField("port", Port.Port); 26 | 27 | const TSharedPtr* PortRangeJson; 28 | if (PortJson->TryGetObjectField("port_range", PortRangeJson)) 29 | { 30 | FMatchmakerJoinPortRange PortRange; 31 | (*PortRangeJson)->TryGetNumberField("min", PortRange.Min); 32 | (*PortRangeJson)->TryGetNumberField("max", PortRange.Max); 33 | } 34 | 35 | Port.IsTls = PortJson->GetBoolField("is_tls"); 36 | 37 | Res.Ports.Add(Pair.Key, Port); 38 | } 39 | 40 | auto PlayerJson = ResponseJson->GetObjectField("player"); 41 | Res.Player.Token = PlayerJson->GetStringField("token"); 42 | 43 | OnSuccess.ExecuteIfBound(Res); 44 | } -------------------------------------------------------------------------------- /Plugins/Rivet/Source/Rivet/Private/MatchmakerLobbiesReady.cpp: -------------------------------------------------------------------------------- 1 | #include "MatchmakerLobbiesReady.h" 2 | #include "JsonObjectConverter.h" 3 | 4 | TSharedPtr FMatchmakerLobbiesReadyRequest::ToJson() const 5 | { 6 | TSharedPtr Req = MakeShareable(new FJsonObject); 7 | return Req; 8 | } 9 | 10 | void UMatchmakerLobbiesReadyEndpoint::HandleResponse(TSharedPtr ResponseJson) const 11 | { 12 | FMatchmakerLobbiesReadyResponse Res; 13 | OnSuccess.ExecuteIfBound(Res); 14 | } 15 | -------------------------------------------------------------------------------- /Plugins/Rivet/Source/Rivet/Private/MatchmakerPlayersConnected.cpp: -------------------------------------------------------------------------------- 1 | #include "MatchmakerPlayersConnected.h" 2 | #include "JsonObjectConverter.h" 3 | 4 | TSharedPtr FMatchmakerPlayersConnectedRequest::ToJson() const 5 | { 6 | TSharedPtr Req = MakeShareable(new FJsonObject); 7 | Req->SetStringField(TEXT("player_token"), PlayerToken); 8 | return Req; 9 | } 10 | 11 | void UMatchmakerPlayersConnectedEndpoint::HandleResponse(TSharedPtr ResponseJson) const 12 | { 13 | FMatchmakerPlayersConnectedResponse Res; 14 | OnSuccess.ExecuteIfBound(Res); 15 | } 16 | -------------------------------------------------------------------------------- /Plugins/Rivet/Source/Rivet/Private/MatchmakerPlayersDisconnected.cpp: -------------------------------------------------------------------------------- 1 | #include "MatchmakerPlayersDisconnected.h" 2 | #include "JsonObjectConverter.h" 3 | 4 | TSharedPtr FMatchmakerPlayersDisconnectedRequest::ToJson() const 5 | { 6 | TSharedPtr Req = MakeShareable(new FJsonObject); 7 | Req->SetStringField(TEXT("player_token"), PlayerToken); 8 | return Req; 9 | } 10 | 11 | void UMatchmakerPlayersDisconnectedEndpoint::HandleResponse(TSharedPtr ResponseJson) const 12 | { 13 | FMatchmakerPlayersDisconnectedResponse Res; 14 | OnSuccess.ExecuteIfBound(Res); 15 | } -------------------------------------------------------------------------------- /Plugins/Rivet/Source/Rivet/Private/RivetClient.cpp: -------------------------------------------------------------------------------- 1 | #include "RivetClient.h" 2 | 3 | URivetClient::URivetClient() 4 | { 5 | EnvToken = FPlatformMisc::GetEnvironmentVariable(TEXT("RIVET_TOKEN")); 6 | EnvMatchmakerUrl = FPlatformMisc::GetEnvironmentVariable(TEXT("RIVET_MATCHMAKER_API_URL")); 7 | } 8 | 9 | FString URivetClient::BuildUrl(FString Url, FString Path) const 10 | { 11 | return Url + Path; 12 | } 13 | 14 | void URivetClient::SendRequest(FString Method, FString Url, FString Path, const URivetHttpEndpoint* Endpoint, TSharedPtr RequestJson) const 15 | { 16 | auto EndpointUrl = BuildUrl(Url, Path); 17 | 18 | FString RequestBodyRaw; 19 | TSharedRef> Writer = TJsonWriterFactory<>::Create(&RequestBodyRaw); 20 | FJsonSerializer::Serialize(RequestJson.ToSharedRef(), Writer); 21 | 22 | UE_LOG(LogTemp, Display, TEXT("Rivet request: %s %s (%s)\n%s"), *Method, *EndpointUrl, *GetToken(), *RequestBodyRaw); 23 | 24 | TSharedRef HttpRequest = FHttpModule::Get().CreateRequest(); 25 | HttpRequest->SetVerb(Method); 26 | HttpRequest->SetURL(EndpointUrl); 27 | HttpRequest->SetHeader(TEXT("Authorization"), TEXT("Bearer ") + GetToken()); 28 | HttpRequest->SetHeader(TEXT("Content-Type"), TEXT("application/json")); 29 | HttpRequest->SetHeader(TEXT("Accepts"), TEXT("application/json")); 30 | HttpRequest->SetContentAsString(RequestBodyRaw); 31 | HttpRequest->OnProcessRequestComplete().BindUObject(Endpoint, &URivetHttpEndpoint::ProcessRequestComplete); 32 | HttpRequest->ProcessRequest(); 33 | } 34 | 35 | URivetClient* URivetClient::CreateRivetClient(FString RivetToken) 36 | { 37 | auto Client = NewObject(); 38 | if (!RivetToken.IsEmpty()) Client->Token = RivetToken; 39 | return Client; 40 | } 41 | 42 | // === Endpoints === 43 | void URivetClient::MatchmakerLobbiesFind(FMatchmakerLobbiesFindRequest Request, FMatchmakerLobbiesFindDelegate OnSuccess, FRivetHttpRequestFailDelegate OnFailure) const 44 | { 45 | UMatchmakerLobbiesFindEndpoint* Endpoint = NewObject(); 46 | Endpoint->OnSuccess = OnSuccess; 47 | Endpoint->OnFailure = OnFailure; 48 | SendRequest("POST", GetMatchmakerUrl(), "/lobbies/find", Endpoint, Request.ToJson()); 49 | }; 50 | 51 | void URivetClient::MatchmakerLobbiesJoin(FMatchmakerLobbiesJoinRequest Request, FMatchmakerLobbiesJoinDelegate OnSuccess, FRivetHttpRequestFailDelegate OnFailure) const 52 | { 53 | UMatchmakerLobbiesJoinEndpoint* Endpoint = NewObject(); 54 | Endpoint->OnSuccess = OnSuccess; 55 | Endpoint->OnFailure = OnFailure; 56 | SendRequest("POST", GetMatchmakerUrl(), "/lobbies/join", Endpoint, Request.ToJson()); 57 | }; 58 | 59 | void URivetClient::MatchmakerLobbiesReady(FMatchmakerLobbiesReadyRequest Request, FMatchmakerLobbiesReadyDelegate OnSuccess, FRivetHttpRequestFailDelegate OnFailure) const 60 | { 61 | UMatchmakerLobbiesReadyEndpoint* Endpoint = NewObject(); 62 | Endpoint->OnSuccess = OnSuccess; 63 | Endpoint->OnFailure = OnFailure; 64 | SendRequest("POST", GetMatchmakerUrl(), "/lobbies/ready", Endpoint, Request.ToJson()); 65 | }; 66 | 67 | void URivetClient::MatchmakerPlayersConnected(FMatchmakerPlayersConnectedRequest Request, FMatchmakerPlayersConnectedDelegate OnSuccess, FRivetHttpRequestFailDelegate OnFailure) const 68 | { 69 | UMatchmakerPlayersConnectedEndpoint* Endpoint = NewObject(); 70 | Endpoint->OnSuccess = OnSuccess; 71 | Endpoint->OnFailure = OnFailure; 72 | SendRequest("POST", GetMatchmakerUrl(), "/players/connected", Endpoint, Request.ToJson()); 73 | }; 74 | 75 | void URivetClient::MatchmakerPlayersDisconnected(FMatchmakerPlayersDisconnectedRequest Request, FMatchmakerPlayersDisconnectedDelegate OnSuccess, FRivetHttpRequestFailDelegate OnFailure) const 76 | { 77 | UMatchmakerPlayersDisconnectedEndpoint* Endpoint = NewObject(); 78 | Endpoint->OnSuccess = OnSuccess; 79 | Endpoint->OnFailure = OnFailure; 80 | SendRequest("POST", GetMatchmakerUrl(), "/players/disconnected", Endpoint, Request.ToJson()); 81 | }; 82 | -------------------------------------------------------------------------------- /Plugins/Rivet/Source/Rivet/Private/RivetHttpEndpoint.cpp: -------------------------------------------------------------------------------- 1 | #include "RivetHttpEndpoint.h" 2 | #include "HttpModule.h" 3 | #include "Interfaces/IHttpResponse.h" 4 | #include "JsonObjectConverter.h" 5 | 6 | 7 | void URivetHttpEndpoint::ProcessRequestComplete(FHttpRequestPtr HttpRequest, FHttpResponsePtr HttpResponse, bool bSuccess) const 8 | { 9 | // Validate request went through 10 | if (!bSuccess || !HttpResponse.IsValid()) 11 | { 12 | if (!bSuccess) UE_LOG(LogTemp, Error, TEXT("Request failed.")); 13 | if (!HttpResponse.IsValid()) UE_LOG(LogTemp, Error, TEXT("Response invalid.")); 14 | 15 | FRivetErrorResponse Response; 16 | OnFailure.ExecuteIfBound(Response); 17 | 18 | return; 19 | } 20 | 21 | // Validate status 22 | FString ResponseBody = HttpResponse->GetContentAsString(); 23 | if (!EHttpResponseCodes::IsOk(HttpResponse->GetResponseCode())) 24 | { 25 | UE_LOG(LogTemp, Error, TEXT("Request status not ok: %d\n%s"), HttpResponse->GetResponseCode(), *ResponseBody); 26 | 27 | FRivetErrorResponse Response; 28 | Response.StatusCode = HttpResponse->GetResponseCode(); 29 | Response.ResponseBody = ResponseBody; 30 | OnFailure.ExecuteIfBound(Response); 31 | 32 | return; 33 | } 34 | 35 | // Parse response 36 | TSharedRef> Reader = TJsonReaderFactory<>::Create(ResponseBody); 37 | TSharedPtr JsonObject; 38 | if (!FJsonSerializer::Deserialize(Reader, JsonObject)) 39 | { 40 | UE_LOG(LogTemp, Error, TEXT("Request returned inalid JSON\n%s"), *ResponseBody); 41 | 42 | FRivetErrorResponse Response; 43 | Response.StatusCode = HttpResponse->GetResponseCode(); 44 | Response.ResponseBody = ResponseBody; 45 | OnFailure.ExecuteIfBound(Response); 46 | 47 | return; 48 | } 49 | 50 | // Response succeeded 51 | UE_LOG(LogTemp, Warning, TEXT("Received succeeded:\n%s"), *ResponseBody); 52 | HandleResponse(JsonObject); 53 | } 54 | -------------------------------------------------------------------------------- /Plugins/Rivet/Source/Rivet/Private/RivetModule.cpp: -------------------------------------------------------------------------------- 1 | #include "Modules/ModuleManager.h" 2 | 3 | IMPLEMENT_MODULE(FDefaultModuleImpl, Rivet); 4 | -------------------------------------------------------------------------------- /Plugins/Rivet/Source/Rivet/Private/RivetPlayer.cpp: -------------------------------------------------------------------------------- 1 | #include "RivetPlayer.h" 2 | #include "GameFramework/GameModeBase.h" 3 | #include "GameFramework/GameSession.h" 4 | 5 | void URivetPlayer::OnPlayerConnectedSuccess(FMatchmakerPlayersConnectedResponse Response) 6 | { 7 | UE_LOG(LogTemp, Warning, TEXT("Player connected success")); 8 | } 9 | 10 | void URivetPlayer::OnPlayerConnectedFailure(FRivetErrorResponse Error) 11 | { 12 | UE_LOG(LogTemp, Error, TEXT("Player connected fail")); 13 | 14 | // Validate player still exists 15 | if (PlayerController == nullptr) 16 | { 17 | UE_LOG(LogTemp, Warning, TEXT("Player controller garbage collected: %d %s"), PlayerId, *PlayerToken); 18 | return; 19 | } 20 | 21 | // Kick player 22 | auto GameMode = PlayerController->GetWorld()->GetAuthGameMode(); 23 | const FText KickReason = FText::FromString("You were kicked from the game."); 24 | if (GameMode->GameSession->KickPlayer(&*PlayerController, KickReason)) 25 | { 26 | UE_LOG(LogTemp, Warning, TEXT("Player kicked: %d %s"), PlayerId, *PlayerToken); 27 | } 28 | else 29 | { 30 | UE_LOG(LogTemp, Error, TEXT("Failed to kick player: %d %s"), PlayerId, *PlayerToken); 31 | } 32 | } 33 | 34 | void URivetPlayer::OnPlayerDisconnectedSuccess(FMatchmakerPlayersDisconnectedResponse Response) 35 | { 36 | UE_LOG(LogTemp, Warning, TEXT("Player disconnected success")); 37 | } 38 | 39 | void URivetPlayer::OnPlayerDisconnectedFailure(FRivetErrorResponse Error) 40 | { 41 | UE_LOG(LogTemp, Warning, TEXT("Player disconnected fail")); 42 | } 43 | -------------------------------------------------------------------------------- /Plugins/Rivet/Source/Rivet/Public/MatchmakerCommon.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "CoreMinimal.h" 4 | #include "HttpModule.h" 5 | #include "MatchmakerCommon.generated.h" 6 | 7 | // === Matchmaker.Lobbies === 8 | USTRUCT(BlueprintType) 9 | struct FMatchmakerJoinLobby 10 | { 11 | GENERATED_BODY() 12 | 13 | UPROPERTY(BlueprintReadOnly) 14 | FString LobbyId = TEXT(""); 15 | }; 16 | 17 | USTRUCT(BlueprintType) 18 | struct FMatchmakerJoinPortRange 19 | { 20 | GENERATED_BODY() 21 | 22 | UPROPERTY(BlueprintReadOnly) 23 | int32 Min = 0; 24 | 25 | UPROPERTY(BlueprintReadOnly) 26 | int32 Max = 0; 27 | }; 28 | 29 | USTRUCT(BlueprintType) 30 | struct FMatchmakerJoinPort 31 | { 32 | GENERATED_BODY() 33 | 34 | UPROPERTY(BlueprintReadOnly) 35 | FString Host = TEXT(""); 36 | 37 | UPROPERTY(BlueprintReadOnly) 38 | FString Hostname = TEXT(""); 39 | 40 | UPROPERTY(BlueprintReadOnly) 41 | int32 Port = 0; 42 | 43 | UPROPERTY(BlueprintReadOnly) 44 | FMatchmakerJoinPortRange PortRange; 45 | 46 | UPROPERTY(BlueprintReadOnly) 47 | bool IsTls = false; 48 | }; 49 | 50 | USTRUCT(BlueprintType) 51 | struct FMatchmakerJoinPlayer 52 | { 53 | GENERATED_BODY() 54 | 55 | UPROPERTY(BlueprintReadOnly) 56 | FString Token = TEXT(""); 57 | }; -------------------------------------------------------------------------------- /Plugins/Rivet/Source/Rivet/Public/MatchmakerLobbiesFind.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "CoreMinimal.h" 4 | #include "HttpModule.h" 5 | #include "RivetHttpEndpoint.h" 6 | #include "MatchmakerCommon.h" 7 | #include "MatchmakerLobbiesFind.generated.h" 8 | 9 | USTRUCT(BlueprintType) 10 | struct FMatchmakerLobbiesFindRequest 11 | { 12 | GENERATED_BODY() 13 | 14 | TSharedPtr ToJson() const; 15 | 16 | UPROPERTY(EditAnywhere, BlueprintReadWrite) 17 | TArray GameModes = {}; 18 | 19 | UPROPERTY(EditAnywhere, BlueprintReadWrite) 20 | TArray Regions; 21 | 22 | UPROPERTY(EditAnywhere, BlueprintReadWrite) 23 | bool PreventAutoCreateLobby = false; 24 | }; 25 | 26 | USTRUCT(BlueprintType) 27 | struct FMatchmakerLobbiesFindResponse 28 | { 29 | GENERATED_BODY() 30 | 31 | UPROPERTY(BlueprintReadOnly) 32 | FMatchmakerJoinLobby Lobby; 33 | 34 | UPROPERTY(BlueprintReadOnly) 35 | TMap Ports; 36 | 37 | UPROPERTY(BlueprintReadOnly) 38 | FMatchmakerJoinPlayer Player; 39 | }; 40 | 41 | DECLARE_DYNAMIC_DELEGATE_OneParam(FMatchmakerLobbiesFindDelegate, FMatchmakerLobbiesFindResponse, Response); 42 | 43 | UCLASS(Blueprintable) 44 | class RIVET_API UMatchmakerLobbiesFindEndpoint : public URivetHttpEndpoint 45 | { 46 | GENERATED_BODY() 47 | 48 | public: 49 | void HandleResponse(TSharedPtr ResponseJson) const override; 50 | 51 | UPROPERTY(BlueprintReadWrite) 52 | FMatchmakerLobbiesFindDelegate OnSuccess; 53 | }; 54 | -------------------------------------------------------------------------------- /Plugins/Rivet/Source/Rivet/Public/MatchmakerLobbiesJoin.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "CoreMinimal.h" 4 | #include "HttpModule.h" 5 | #include "RivetHttpEndpoint.h" 6 | #include "MatchmakerCommon.h" 7 | #include "MatchmakerLobbiesJoin.generated.h" 8 | 9 | USTRUCT(BlueprintType) 10 | struct FMatchmakerLobbiesJoinRequest 11 | { 12 | GENERATED_BODY() 13 | 14 | TSharedPtr ToJson() const; 15 | 16 | UPROPERTY(EditAnywhere, BlueprintReadWrite) 17 | FString LobbyId = TEXT(""); 18 | }; 19 | 20 | USTRUCT(BlueprintType) 21 | struct FMatchmakerLobbiesJoinResponse 22 | { 23 | GENERATED_BODY() 24 | 25 | UPROPERTY(BlueprintReadOnly) 26 | FMatchmakerJoinLobby Lobby; 27 | 28 | UPROPERTY(BlueprintReadOnly) 29 | TMap Ports; 30 | 31 | UPROPERTY(BlueprintReadOnly) 32 | FMatchmakerJoinPlayer Player; 33 | }; 34 | 35 | DECLARE_DYNAMIC_DELEGATE_OneParam(FMatchmakerLobbiesJoinDelegate, FMatchmakerLobbiesJoinResponse, Response); 36 | 37 | UCLASS(Blueprintable) 38 | class RIVET_API UMatchmakerLobbiesJoinEndpoint : public URivetHttpEndpoint 39 | { 40 | GENERATED_BODY() 41 | 42 | public: 43 | void HandleResponse(TSharedPtr ResponseJson) const override; 44 | 45 | UPROPERTY(BlueprintReadWrite) 46 | FMatchmakerLobbiesJoinDelegate OnSuccess; 47 | }; 48 | -------------------------------------------------------------------------------- /Plugins/Rivet/Source/Rivet/Public/MatchmakerLobbiesReady.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "CoreMinimal.h" 4 | #include "HttpModule.h" 5 | #include "RivetHttpEndpoint.h" 6 | #include "MatchmakerLobbiesReady.generated.h" 7 | 8 | USTRUCT(BlueprintType) 9 | struct FMatchmakerLobbiesReadyRequest 10 | { 11 | GENERATED_BODY() 12 | 13 | TSharedPtr ToJson() const; 14 | }; 15 | 16 | USTRUCT(BlueprintType) 17 | struct FMatchmakerLobbiesReadyResponse 18 | { 19 | GENERATED_BODY() 20 | }; 21 | 22 | DECLARE_DYNAMIC_DELEGATE_OneParam(FMatchmakerLobbiesReadyDelegate, FMatchmakerLobbiesReadyResponse, Response); 23 | 24 | UCLASS(Blueprintable) 25 | class RIVET_API UMatchmakerLobbiesReadyEndpoint : public URivetHttpEndpoint 26 | { 27 | GENERATED_BODY() 28 | 29 | public: 30 | void HandleResponse(TSharedPtr ResponseJson) const override; 31 | 32 | UPROPERTY(BlueprintReadWrite) 33 | FMatchmakerLobbiesReadyDelegate OnSuccess; 34 | }; -------------------------------------------------------------------------------- /Plugins/Rivet/Source/Rivet/Public/MatchmakerPlayersConnected.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "CoreMinimal.h" 4 | #include "HttpModule.h" 5 | #include "RivetHttpEndpoint.h" 6 | #include "MatchmakerPlayersConnected.generated.h" 7 | 8 | USTRUCT(BlueprintType) 9 | struct FMatchmakerPlayersConnectedRequest 10 | { 11 | GENERATED_BODY() 12 | 13 | TSharedPtr ToJson() const; 14 | 15 | UPROPERTY(EditAnywhere, BlueprintReadWrite) 16 | FString PlayerToken = TEXT(""); 17 | }; 18 | 19 | USTRUCT(BlueprintType) 20 | struct FMatchmakerPlayersConnectedResponse 21 | { 22 | GENERATED_BODY() 23 | }; 24 | 25 | DECLARE_DYNAMIC_DELEGATE_OneParam(FMatchmakerPlayersConnectedDelegate, FMatchmakerPlayersConnectedResponse, Response); 26 | 27 | UCLASS(Blueprintable) 28 | class RIVET_API UMatchmakerPlayersConnectedEndpoint : public URivetHttpEndpoint 29 | { 30 | GENERATED_BODY() 31 | 32 | public: 33 | void HandleResponse(TSharedPtr ResponseJson) const override; 34 | 35 | UPROPERTY(BlueprintReadWrite) 36 | FMatchmakerPlayersConnectedDelegate OnSuccess; 37 | }; -------------------------------------------------------------------------------- /Plugins/Rivet/Source/Rivet/Public/MatchmakerPlayersDisconnected.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "CoreMinimal.h" 4 | #include "HttpModule.h" 5 | #include "RivetHttpEndpoint.h" 6 | #include "MatchmakerPlayersDisconnected.generated.h" 7 | 8 | USTRUCT(BlueprintType) 9 | struct FMatchmakerPlayersDisconnectedRequest 10 | { 11 | GENERATED_BODY() 12 | 13 | TSharedPtr ToJson() const; 14 | 15 | UPROPERTY(EditAnywhere, BlueprintReadWrite) 16 | FString PlayerToken = TEXT(""); 17 | }; 18 | 19 | USTRUCT(BlueprintType) 20 | struct FMatchmakerPlayersDisconnectedResponse 21 | { 22 | GENERATED_BODY() 23 | }; 24 | 25 | DECLARE_DYNAMIC_DELEGATE_OneParam(FMatchmakerPlayersDisconnectedDelegate, FMatchmakerPlayersDisconnectedResponse, Response); 26 | 27 | UCLASS(Blueprintable) 28 | class RIVET_API UMatchmakerPlayersDisconnectedEndpoint : public URivetHttpEndpoint 29 | { 30 | GENERATED_BODY() 31 | 32 | public: 33 | void HandleResponse(TSharedPtr ResponseJson) const override; 34 | 35 | UPROPERTY(BlueprintReadWrite) 36 | FMatchmakerPlayersDisconnectedDelegate OnSuccess; 37 | }; -------------------------------------------------------------------------------- /Plugins/Rivet/Source/Rivet/Public/Rivet.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "CoreMinimal.h" 4 | #include "RivetClient.h" 5 | -------------------------------------------------------------------------------- /Plugins/Rivet/Source/Rivet/Public/RivetClient.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "CoreMinimal.h" 4 | #include "HttpModule.h" 5 | #include "RivetHttpEndpoint.h" 6 | #include "MatchmakerLobbiesFind.h" 7 | #include "MatchmakerLobbiesJoin.h" 8 | #include "MatchmakerLobbiesReady.h" 9 | #include "MatchmakerPlayersConnected.h" 10 | #include "MatchmakerPlayersDisconnected.h" 11 | #include "RivetClient.generated.h" 12 | 13 | UCLASS(Blueprintable, Config=Game) 14 | class RIVET_API URivetClient : public UObject 15 | { 16 | GENERATED_BODY() 17 | 18 | public: 19 | URivetClient(); 20 | 21 | UPROPERTY(Config) 22 | FString DefaultToken; 23 | 24 | UPROPERTY(Config) 25 | FString EnvToken; 26 | 27 | UPROPERTY(BlueprintReadWrite) 28 | FString Token; 29 | 30 | FString GetToken() const 31 | { 32 | if (!EnvToken.IsEmpty()) return EnvToken; 33 | else if (!Token.IsEmpty()) return Token; 34 | else return DefaultToken; 35 | } 36 | 37 | UPROPERTY(Config) 38 | FString DefaultMatchmakerUrl; 39 | 40 | UPROPERTY(Config) 41 | FString EnvMatchmakerUrl; 42 | 43 | UPROPERTY() 44 | FString MatchmakerUrl; 45 | 46 | FString GetMatchmakerUrl() const 47 | { 48 | if (!MatchmakerUrl.IsEmpty()) return MatchmakerUrl; 49 | else if (!EnvMatchmakerUrl.IsEmpty()) return EnvMatchmakerUrl; 50 | else if (!DefaultMatchmakerUrl.IsEmpty()) return DefaultMatchmakerUrl; 51 | else return TEXT("https://api.rivet.gg/matchmaker"); 52 | } 53 | 54 | FString BuildUrl(FString Url, FString Path) const; 55 | void SendRequest(FString Method, FString Service, FString Path, const URivetHttpEndpoint* Endpoint, TSharedPtr RequestJson) const; 56 | 57 | public: 58 | UFUNCTION(BlueprintCallable, Category="Rivet|Matchmaker|Lobbies") 59 | static URivetClient* CreateRivetClient(FString RivetToken); 60 | 61 | UFUNCTION(BlueprintCallable, Category="Rivet|Matchmaker|Lobbies") 62 | void MatchmakerLobbiesFind(FMatchmakerLobbiesFindRequest Request, FMatchmakerLobbiesFindDelegate OnSuccess, FRivetHttpRequestFailDelegate OnFailure) const; 63 | 64 | UFUNCTION(BlueprintCallable, Category="Rivet|Matchmaker|Lobbies") 65 | void MatchmakerLobbiesJoin(FMatchmakerLobbiesJoinRequest Request, FMatchmakerLobbiesJoinDelegate OnSuccess, FRivetHttpRequestFailDelegate OnFailure) const; 66 | 67 | UFUNCTION(BlueprintCallable, Category="Rivet|Matchmaker|Lobbies") 68 | void MatchmakerLobbiesReady(FMatchmakerLobbiesReadyRequest Request, FMatchmakerLobbiesReadyDelegate OnSuccess, FRivetHttpRequestFailDelegate OnFailure) const; 69 | 70 | UFUNCTION(BlueprintCallable, Category="Rivet|Matchmaker|Players") 71 | void MatchmakerPlayersConnected(FMatchmakerPlayersConnectedRequest Request, FMatchmakerPlayersConnectedDelegate OnSuccess, FRivetHttpRequestFailDelegate OnFailure) const; 72 | 73 | UFUNCTION(BlueprintCallable, Category="Rivet|Matchmaker|Players") 74 | void MatchmakerPlayersDisconnected(FMatchmakerPlayersDisconnectedRequest Request, FMatchmakerPlayersDisconnectedDelegate OnSuccess, FRivetHttpRequestFailDelegate OnFailure) const; 75 | }; -------------------------------------------------------------------------------- /Plugins/Rivet/Source/Rivet/Public/RivetHttpEndpoint.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "CoreMinimal.h" 4 | #include "HttpModule.h" 5 | #include "RivetHttpEndpoint.generated.h" 6 | 7 | USTRUCT(BlueprintType) 8 | struct FRivetErrorResponse 9 | { 10 | GENERATED_BODY() 11 | 12 | UPROPERTY(BlueprintReadOnly) 13 | int32 StatusCode = 0; 14 | 15 | UPROPERTY(BlueprintReadOnly) 16 | FString ResponseBody = TEXT(""); 17 | }; 18 | 19 | DECLARE_DYNAMIC_DELEGATE_OneParam(FRivetHttpRequestFailDelegate, FRivetErrorResponse, Error); 20 | UCLASS(Abstract) 21 | class RIVET_API URivetHttpEndpoint : public UObject 22 | { 23 | GENERATED_BODY() 24 | 25 | public: 26 | UPROPERTY(BlueprintReadWrite) 27 | FRivetHttpRequestFailDelegate OnFailure; 28 | 29 | // === Override === 30 | public: 31 | virtual void HandleResponse(TSharedPtr ResponseJson) const { checkf(false, TEXT("HandleResponse() is not implemented!")); }; 32 | 33 | // === Helpers === 34 | public: 35 | void ProcessRequestComplete(FHttpRequestPtr HttpRequest, FHttpResponsePtr HttpResponse, bool bSuccess) const; 36 | }; -------------------------------------------------------------------------------- /Plugins/Rivet/Source/Rivet/Public/RivetPlayer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "CoreMinimal.h" 4 | #include "MatchmakerPlayersConnected.h" 5 | #include "MatchmakerPlayersDisconnected.h" 6 | #include "RivetHttpEndpoint.h" 7 | #include "RivetPlayer.generated.h" 8 | 9 | UCLASS() 10 | class RIVET_API URivetPlayer : public UObject 11 | { 12 | GENERATED_BODY() 13 | 14 | public: 15 | int32 PlayerId; 16 | TWeakObjectPtr PlayerController; 17 | 18 | FString PlayerToken; 19 | 20 | UFUNCTION() 21 | void OnPlayerConnectedSuccess(FMatchmakerPlayersConnectedResponse Response); 22 | UFUNCTION() 23 | void OnPlayerConnectedFailure(FRivetErrorResponse Error); 24 | 25 | UFUNCTION() 26 | void OnPlayerDisconnectedSuccess(FMatchmakerPlayersDisconnectedResponse Response); 27 | UFUNCTION() 28 | void OnPlayerDisconnectedFailure(FRivetErrorResponse Error); 29 | }; 30 | -------------------------------------------------------------------------------- /Plugins/Rivet/Source/Rivet/Rivet.Build.cs: -------------------------------------------------------------------------------- 1 | using UnrealBuildTool; 2 | 3 | public class Rivet: ModuleRules 4 | { 5 | public Rivet(ReadOnlyTargetRules Target) : base(Target) 6 | { 7 | PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "HTTP", "Json", "JsonUtilities" }); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Unreal Engine 5 Plugin 2 | 3 | _Tested with Unreal Engine 5.2.1._ 4 | 5 | _Has not been tested with Unreal Engine 4._ 6 | 7 | ## Installation 8 | 9 | ### Method 1: Initialize project with the Rivet CLI (recommended) 10 | 11 | This method will also configure your Rivet project. 12 | 13 | 1. Install the [Rivet CLI](https://github.com/rivet-gg/cli) 14 | 2. Run `rivet init --unreal` in the root of your project 15 | 3. The CLI will prompt you to configure your project & install the plugin 16 | 4. Restart the Unreal editor 17 | 18 | ### Method 2: Install with Rivet CLI 19 | 20 | This method can be used to upgrade an existing plugin installation. 21 | 22 | 1. Install the [Rivet CLI](https://github.com/rivet-gg/cli) 23 | 2. Run `rivet unreal install-plugin` in the root of your project 24 | 3. Restart the Unreal editor 25 | 26 | ### Method 3: Copy manually 27 | 28 | 1. Create a `Plugins` folder in the root of your project (it may already exist) 29 | 2. Copy the `Plugins/Rivet/` folder from this repository to the `Plugins/Rivet/` folder in your project 30 | 3. Restart the Unreal editor 31 | 32 | ## Getting started 33 | 34 | [Getting started guide](https://rivet.gg/learn/unreal) 35 | --------------------------------------------------------------------------------