Skip to content

Commit

Permalink
Fixed crash on the client, disable mod list checking in the editor by…
Browse files Browse the repository at this point in the history
… default
  • Loading branch information
Archengius committed Oct 20, 2023
1 parent 7998b28 commit 75bbccb
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 37 deletions.
17 changes: 17 additions & 0 deletions Mods/SML/Source/SML/Private/Network/NetworkHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,23 @@ void UModNetworkHandler::SendMessage(UNetConnection* Connection, FMessageType Me
Connection->FlushNet(true);
}

UGameInstance* UModNetworkHandler::GetGameInstanceFromNetDriver( const UNetDriver* NetDriver )
{
if ( NetDriver )
{
if ( NetDriver->World != nullptr && NetDriver->World->GetGameInstance() != nullptr )
{
return NetDriver->World->GetGameInstance();
}
const FWorldContext* Context = GEngine->GetWorldContextFromPendingNetGameNetDriver( NetDriver );
if ( Context != nullptr && Context->OwningGameInstance != nullptr )
{
return Context->OwningGameInstance;
}
}
return nullptr;
}

void UModNetworkHandler::ReceiveMessage(UNetConnection* Connection, const FString& ModId, int32 MessageId, const FString& Content) const {
const TMap<int32, FMessageEntry>* Result = MessageHandlers.Find(ModId);
if (Result != nullptr) {
Expand Down
100 changes: 63 additions & 37 deletions Mods/SML/Source/SML/Private/Network/SMLNetworkManager.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "Network/SMLConnection/SMLNetworkManager.h"
#include "FGPlayerController.h"
#include "Dom/JsonObject.h"
#include "Engine/GameInstance.h"
#include "Network/NetworkHandler.h"
#include "Player/SMLRemoteCallObject.h"
#include "GameFramework/GameModeBase.h"
Expand All @@ -9,6 +10,13 @@
#include "Serialization/JsonSerializer.h"
#include "Serialization/JsonWriter.h"

static TAutoConsoleVariable CVarSkipRemoteModListCheck(
TEXT("SML.SkipRemoteModListCheck"),
GIsEditor,
TEXT("1 to skip remote mod list check, 0 to enable it. Remote mod list checks are disabled by default in the editor."),
ECVF_Default
);

static FUObjectAnnotationSparse<FConnectionMetadata, true> GModConnectionMetadata;

TSharedPtr<FMessageType> FSMLNetworkManager::MessageTypeModInit = NULL;
Expand Down Expand Up @@ -70,17 +78,23 @@ void FSMLNetworkManager::HandleGameModePostLogin(AGameModeBase* GameMode, APlaye
}
}

FString FSMLNetworkManager::SerializeLocalModList(UNetConnection* Connection) {
TSharedRef<FJsonObject> ModListObject = MakeShareable(new FJsonObject());

UModLoadingLibrary* ModLoadingLibrary = Connection->GetWorld()->GetGameInstance()->GetSubsystem<UModLoadingLibrary>();
const TArray<FModInfo> Mods = ModLoadingLibrary->GetLoadedMods();
FString FSMLNetworkManager::SerializeLocalModList(UNetConnection* Connection)
{
const TSharedRef<FJsonObject> ModListObject = MakeShareable(new FJsonObject());

if (const UGameInstance* GameInstance = UModNetworkHandler::GetGameInstanceFromNetDriver( Connection->GetDriver() ) )
{
if ( UModLoadingLibrary* ModLoadingLibrary = GameInstance->GetSubsystem<UModLoadingLibrary>() )
{
const TArray<FModInfo> Mods = ModLoadingLibrary->GetLoadedMods();

for (const FModInfo& ModInfo : Mods) {
ModListObject->SetStringField(ModInfo.Name, ModInfo.Version.ToString());
}

const TSharedRef<FJsonObject> MetadataObject = MakeShareable(new FJsonObject());
for (const FModInfo& ModInfo : Mods) {
ModListObject->SetStringField(ModInfo.Name, ModInfo.Version.ToString());
}
}
}

const TSharedRef<FJsonObject> MetadataObject = MakeShareable(new FJsonObject());
MetadataObject->SetObjectField(TEXT("ModList"), ModListObject);

FString ResultString;
Expand Down Expand Up @@ -117,41 +131,53 @@ bool FSMLNetworkManager::HandleModListObject( FConnectionMetadata& Metadata, con
return true;
}

void FSMLNetworkManager::ValidateSMLConnectionData(UNetConnection* Connection) {
UModNetworkHandler* NetworkHandler = GEngine->GetEngineSubsystem<UModNetworkHandler>();
void FSMLNetworkManager::ValidateSMLConnectionData(UNetConnection* Connection)
{
const bool bAllowMissingMods = CVarSkipRemoteModListCheck.GetValueOnGameThread();
const FConnectionMetadata SMLMetadata = GModConnectionMetadata.GetAnnotation( Connection );

TArray<FString> ClientMissingMods;

if (!SMLMetadata.bIsInitialized) {
if (!SMLMetadata.bIsInitialized && !bAllowMissingMods ) {
UModNetworkHandler::CloseWithFailureMessage(Connection, TEXT("This server is running Satisfactory Mod Loader, and your client doesn't have it installed."));
return;
}

UModLoadingLibrary* ModLoadingLibrary = Connection->GetWorld()->GetGameInstance()->GetSubsystem<UModLoadingLibrary>();
const TArray<FModInfo> Mods = ModLoadingLibrary->GetLoadedMods();
if (const UGameInstance* GameInstance = UModNetworkHandler::GetGameInstanceFromNetDriver( Connection->GetDriver() ) )
{
if ( UModLoadingLibrary* ModLoadingLibrary = GameInstance->GetSubsystem<UModLoadingLibrary>() )
{
const TArray<FModInfo> Mods = ModLoadingLibrary->GetLoadedMods();

for (const FModInfo& ModInfo : Mods)
{
if ( ModInfo.bAcceptsAnyRemoteVersion )
{
continue; //Server-side only mod
}

const FVersion* ClientVersion = SMLMetadata.InstalledClientMods.Find( ModInfo.Name );
const FString ModName = FString::Printf( TEXT("%s (%s)"), *ModInfo.FriendlyName, *ModInfo.Name );
if ( ClientVersion == nullptr )
{
ClientMissingMods.Add( ModName );
continue;
}
const FVersionRange& RemoteVersion = ModInfo.RemoteVersionRange;

if ( !RemoteVersion.Matches(*ClientVersion) )
{
const FString VersionText = FString::Printf( TEXT("required: %s, client: %s"), *RemoteVersion.ToString(), *ClientVersion->ToString() );
ClientMissingMods.Add( FString::Printf( TEXT("%s: %s"), *ModName, *VersionText ) );
}
}
}
}

for (const FModInfo& ModInfo : Mods) {
if (ModInfo.bAcceptsAnyRemoteVersion) {
continue; //Server-side only mod
}
const FVersion* ClientVersion = SMLMetadata.InstalledClientMods.Find(ModInfo.Name);
const FString ModName = FString::Printf(TEXT("%s (%s)"), *ModInfo.FriendlyName, *ModInfo.Name);
if (ClientVersion == nullptr) {
ClientMissingMods.Add(ModName);
continue;
}
const FVersionRange& RemoteVersion = ModInfo.RemoteVersionRange;
if (!RemoteVersion.Matches(*ClientVersion)) {
const FString VersionText = FString::Printf(TEXT("required: %s, client: %s"), *RemoteVersion.ToString(), *ClientVersion->ToString());
ClientMissingMods.Add(FString::Printf(TEXT("%s: %s"), *ModName, *VersionText));
}
}

if (ClientMissingMods.Num() > 0) {
const FString JoinedModList = FString::Join(ClientMissingMods, TEXT("\n"));
const FString Reason = FString::Printf(TEXT("Client missing mods: %s"), *JoinedModList);
UModNetworkHandler::CloseWithFailureMessage(Connection, Reason);
if ( ClientMissingMods.Num() > 0 && !bAllowMissingMods )
{
const FString JoinedModList = FString::Join( ClientMissingMods, TEXT("\n") );
const FString Reason = FString::Printf( TEXT("Client missing mods: %s"), *JoinedModList );
UModNetworkHandler::CloseWithFailureMessage( Connection, Reason );
}
}

Expand Down
9 changes: 9 additions & 0 deletions Mods/SML/Source/SML/Public/Network/NetworkHandler.h
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
#pragma once

#include "CoreMinimal.h"
#include "Subsystems/EngineSubsystem.h"
#include "UObject/Object.h"
#include "Kismet/BlueprintFunctionLibrary.h"
#include "NetworkHandler.generated.h"

class UGameInstance;
class UNetDriver;

DECLARE_LOG_CATEGORY_EXTERN(LogModNetworkHandler, Log, All);
DECLARE_DELEGATE_TwoParams(FMessageReceived, class UNetConnection* /*Connection*/, FString /*Data*/);
DECLARE_MULTICAST_DELEGATE_TwoParams(FWelcomePlayer, UWorld* /*ServerWorld*/, class UNetConnection* /*Connection*/);
Expand Down Expand Up @@ -67,6 +71,11 @@ class SML_API UModNetworkHandler : public UEngineSubsystem {
* Send registered mod message to this connection to be processed on the remote side
*/
static void SendMessage(class UNetConnection* Connection, FMessageType MessageType, FString Data);

/**
* Retrieves the game instance owning the specified net driver
*/
static UGameInstance* GetGameInstanceFromNetDriver( const UNetDriver* NetDriver );
private:
friend class FSatisfactoryModLoader;

Expand Down

0 comments on commit 75bbccb

Please sign in to comment.