Skip to content

Commit

Permalink
Merge branch 'dedicated-servers'
Browse files Browse the repository at this point in the history
  • Loading branch information
mircearoata committed Jan 6, 2024
2 parents 1273777 + bb850e9 commit 6c19323
Show file tree
Hide file tree
Showing 50 changed files with 915 additions and 400 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,11 @@ jobs:
run: MSBuild.exe .\\SML\\FactoryGame.sln /p:Configuration="Development Editor" /p:Platform="Win64" /t:"Games\FactoryGame"

- name: Package SML Mod
run: .\\ue\\Engine\\Build\\BatchFiles\\RunUAT.bat -ScriptsForProject="$Env:GITHUB_WORKSPACE\\SML\\FactoryGame.uproject" PackagePlugin -Project="$Env:GITHUB_WORKSPACE\\SML\\FactoryGame.uproject" -dlcname=SML -build -clientconfig=Shipping -serverconfig=Shipping -platform=Win64 -nocompileeditor -installed
run: .\\ue\\Engine\\Build\\BatchFiles\\RunUAT.bat -ScriptsForProject="$Env:GITHUB_WORKSPACE\\SML\\FactoryGame.uproject" PackagePlugin -Project="$Env:GITHUB_WORKSPACE\\SML\\FactoryGame.uproject" -dlcname=SML -build -server -clientconfig=Shipping -serverconfig=Shipping -platform=Win64 -serverplatform=Win64+Linux -nocompileeditor -installed

- name: Archive SML artifact
uses: actions/upload-artifact@v2
if: ${{ github.event_name == 'push' }}
with:
name: sml
path: SML\\Saved\\ArchivedPlugins\\SML\\SML-Windows.zip
path: SML\\Saved\\ArchivedPlugins\\SML\\*.zip
10 changes: 9 additions & 1 deletion FactoryGame.uproject
Original file line number Diff line number Diff line change
Expand Up @@ -274,5 +274,13 @@
"Win64",
"Linux",
"Windows"
]
],
"PreBuildSteps": {
"Win64": [
"powershell -Command \"$file = '$(ProjectDir)\\Plugins\\Wwise\\Source\\AkAudio\\Classes\\OcclusionObstructionService\\AkOcclusionObstructionService.h'; if (Test-Path $file) { if (!(Select-String -Path $file -Pattern 'class AKAUDIO_API AkOcclusionObstructionService' -SimpleMatch -Quiet)) { (Get-Content $file) -replace 'class AkOcclusionObstructionService', 'class AKAUDIO_API AkOcclusionObstructionService' | Out-File -encoding UTF8 $file } }\""
],
"Linux": [
"if ! grep -q 'class AKAUDIO_API AkOcclusionObstructionService' $(ProjectDir)/Plugins/Wwise/Source/AkAudio/Classes/OcclusionObstructionService/AkOcclusionObstructionService.h; then sed -i 's/class AkOcclusionObstructionService/class AKAUDIO_API AkOcclusionObstructionService/' $(ProjectDir)/Plugins/Wwise/Source/AkAudio/Classes/OcclusionObstructionService/AkOcclusionObstructionService.h; fi"
]
}
}
71 changes: 60 additions & 11 deletions Mods/Alpakit/Source/Alpakit.Automation/PackagePlugin.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,18 @@
using EpicGames.Core;
using UnrealBuildTool;
using AutomationScripts;
using Microsoft.Extensions.Logging;
using UnrealBuildBase;

namespace Alpakit.Automation;

public class PackagePlugin : BuildCookRun
{
public override void ExecuteBuild()
{
var mergeArchive = ParseParam("merge");
Logger.LogWarning($"Merge archive: {mergeArchive}");

var projectParams = SetupParams();
projectParams.PreModifyDeploymentContextCallback = (ProjectParams, SC) =>
{
Expand All @@ -36,6 +41,11 @@ public override void ExecuteBuild()
ArchiveStagedPlugin(projectParams, SC);
}

if (mergeArchive)
{
ArchiveMergedStagedPlugin(projectParams, deploymentContexts);
}

foreach (var SC in deploymentContexts)
{
var copyToGameDirectory = ParseOptionalDirectoryReferenceParam($"CopyToGameDirectory_{SC.FinalCookPlatform}");
Expand Down Expand Up @@ -107,26 +117,65 @@ private static void DeployStagedPlugin(ProjectParams ProjectParams, DeploymentCo

private static void ArchiveStagedPlugin(ProjectParams ProjectParams, DeploymentContext SC)
{
// Plugins will be archived under <Project>/Saved/ArchivedPlugins/<DLCName>
var baseArchiveDirectory = CombinePaths(SC.ProjectRoot.FullName, "Saved", "ArchivedPlugins");
var archiveDirectory = CombinePaths(baseArchiveDirectory, ProjectParams.DLCFile.GetFileNameWithoutAnyExtensions());

CreateDirectory(archiveDirectory);
var archiveDirectory = GetArchivedPluginDirectory(ProjectParams);

var dlcName = ProjectParams.DLCFile.GetFileNameWithoutAnyExtensions();

var zipFileName = $"{dlcName}-{SC.FinalCookPlatform}.zip";

var zipFilePath = CombinePaths(archiveDirectory, zipFileName);

if (FileExists(zipFilePath))
DeleteFile(zipFilePath);

// We only want to archive the staged files of the plugin, not the entire stage directory
var stagedPluginDirectory = Project.ApplyDirectoryRemap(SC, SC.GetStagedFileLocation(ProjectParams.DLCFile));
var fullStagedPluginDirectory = DirectoryReference.Combine(SC.StageDirectory, stagedPluginDirectory.Directory.Name);

CreateZipFromDirectory(fullStagedPluginDirectory, FileReference.Combine(archiveDirectory, zipFileName));
}

private static void ArchiveMergedStagedPlugin(ProjectParams ProjectParams, List<DeploymentContext> DeploymentContexts)
{
var archiveDirectory = GetArchivedPluginDirectory(ProjectParams);

var dlcName = ProjectParams.DLCFile.GetFileNameWithoutAnyExtensions();

ZipFile.CreateFromDirectory(fullStagedPluginDirectory.FullName, zipFilePath);
var zipFileName = $"{dlcName}.zip";

// We only want to archive the staged files of the plugin, not the entire stage directory
var mergedTempDir = DirectoryReference.Combine(ProjectParams.DLCFile.Directory, "Saved", "ArchiveMerging");
try
{
if (DirectoryReference.Exists(mergedTempDir))
DirectoryReference.Delete(mergedTempDir, true);
DirectoryReference.CreateDirectory(mergedTempDir);
foreach (var SC in DeploymentContexts)
{
var stagedPluginDirectory =
Project.ApplyDirectoryRemap(SC, SC.GetStagedFileLocation(ProjectParams.DLCFile));
var fullStagedPluginDirectory =
DirectoryReference.Combine(SC.StageDirectory, stagedPluginDirectory.Directory.Name);
CopyDirectory_NoExceptions(fullStagedPluginDirectory, DirectoryReference.Combine(mergedTempDir, SC.FinalCookPlatform));
}

CreateZipFromDirectory(mergedTempDir, FileReference.Combine(archiveDirectory, zipFileName));
}
finally
{
DirectoryReference.Delete(mergedTempDir, true);
}
}

private static DirectoryReference GetArchivedPluginDirectory(ProjectParams ProjectParams)
{
// Plugins will be archived under <Project>/Saved/ArchivedPlugins/<DLCName>
return DirectoryReference.Combine(ProjectParams.RawProjectPath.Directory, "Saved", "ArchivedPlugins", ProjectParams.DLCFile.GetFileNameWithoutAnyExtensions());
}

private static void CreateZipFromDirectory(DirectoryReference SourceDirectory, FileReference DestinationFile)
{
CreateDirectory(DestinationFile.Directory);

if (FileReference.Exists(DestinationFile))
FileReference.Delete(DestinationFile);

ZipFile.CreateFromDirectory(SourceDirectory.FullName, DestinationFile.FullName);
}

private static string GetPluginPathRelativeToStageRoot(ProjectParams ProjectParams)
Expand Down
78 changes: 61 additions & 17 deletions Mods/Alpakit/Source/Alpakit/Private/Alpakit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
#include "ISettingsSection.h"
#include "LevelEditor.h"
#include "IPluginBrowser.h"
#include "UATHelper/Public/IUATHelperModule.h"
#include "ModWizardDefinition.h"
#include "ModTargetsConfig.h"
#include "SAlpakitLogTabContent.h"

static const FName AlpakitTabName("Alpakit");
Expand Down Expand Up @@ -124,7 +126,30 @@ void FAlpakitModule::ShutdownModule() {
FGlobalTabmanager::Get()->UnregisterNomadTabSpawner(AlpakitLogTabName);
}

void FAlpakitModule::PackageMods(TArray<TSharedRef<IPlugin>> Mods) {
TSharedRef<FAlpakitProfile> MakeDevelopmentProfileForMod(TSharedRef<IPlugin> Mod) {
TSharedRef<FAlpakitProfile> Profile = MakeShared<FAlpakitProfile>(Mod->GetName());

Profile->bBuild = Mod->GetDescriptor().Modules.Num() > 0;

UAlpakitSettings* Settings = UAlpakitSettings::Get();

Profile->BuildConfiguration = Settings->GetBuildConfiguration();

for (auto [CookedPlatform, TargetSetting] : Settings->GetPlatformTargetSettings()) {
if (TargetSetting.bEnabled) {
Profile->CookedPlatforms.Add(CookedPlatform);
if (TargetSetting.bCopyModsToGame) {
FAlpakitProfileGameInfo& GameInfo = Profile->PlatformGameInfo.FindOrAdd(CookedPlatform);
GameInfo.bCopyToGame = true;
GameInfo.GamePath = TargetSetting.SatisfactoryGamePath;
}
}
}

return Profile;
}

void FAlpakitModule::PackageModsDevelopment(TArray<TSharedRef<IPlugin>> Mods) {
if (Mods.Num() == 0) {
return;
}
Expand All @@ -134,28 +159,47 @@ void FAlpakitModule::PackageMods(TArray<TSharedRef<IPlugin>> Mods) {
UAlpakitSettings* Settings = UAlpakitSettings::Get();

for (TSharedRef<IPlugin> Mod : Mods) {
TSharedRef<FAlpakitProfile> Profile = MakeShared<FAlpakitProfile>(Mod->GetName());

Profile->bBuild = Mod->GetDescriptor().Modules.Num() > 0;
ProfilesToPackage.Add(MakeDevelopmentProfileForMod(Mod));
}

Profile->BuildConfiguration = Settings->GetBuildConfiguration();
// Profile->CookedPlatforms = Settings->CookPlatforms;
Profile->CookedPlatforms = {TEXT("Windows")}; // Only Windows is allowed for now
TSharedRef<FAlpakitProfile> LastProfile = ProfilesToPackage.Last();

if (Settings->bCopyModsToGame) {
FAlpakitProfileGameInfo& GameInfo = Profile->PlatformGameInfo.FindOrAdd(TEXT("Windows"));
GameInfo.bCopyToGame = true;
GameInfo.GamePath = Settings->SatisfactoryGamePath.Path;
for (auto [CookedPlatform, TargetSetting] : Settings->GetPlatformTargetSettings()) {
if (TargetSetting.bEnabled) {
if (TargetSetting.bLaunchGame) {
FAlpakitProfileGameInfo& GameInfo = LastProfile->PlatformGameInfo.FindOrAdd(CookedPlatform);
GameInfo.bStartGame = true;
GameInfo.StartGameType = TargetSetting.LaunchGameType;
}
}

ProfilesToPackage.Add(Profile);
}

TSharedRef<FAlpakitProfile> LastProfile = ProfilesToPackage.Last();
PackageMods(ProfilesToPackage);
}

TSharedRef<FAlpakitProfile> MakeReleaseProfileForMod(TSharedRef<IPlugin> Mod) {
TSharedRef<FAlpakitProfile> Profile = MakeShared<FAlpakitProfile>(Mod->GetName());

Profile->bBuild = Mod->GetDescriptor().Modules.Num() > 0;
Profile->BuildConfiguration = EBuildConfiguration::Shipping;

Profile->bMergeArchive = true;

FModTargetsConfig TargetsConfig(Mod);
Profile->CookedPlatforms.Append(TargetsConfig.GetCookedPlatforms());

return Profile;
}

if (Settings->LaunchGameAfterPacking != EAlpakitStartGameType::NONE) {
FAlpakitProfileGameInfo& GameInfo = LastProfile->PlatformGameInfo.FindOrAdd(TEXT("Windows"));
GameInfo.StartGameType = Settings->LaunchGameAfterPacking;
void FAlpakitModule::PackageModsRelease(TArray<TSharedRef<IPlugin>> Mods) {
if (Mods.Num() == 0) {
return;
}

TArray<TSharedRef<FAlpakitProfile>> ProfilesToPackage;

for (TSharedRef<IPlugin> Mod : Mods) {
ProfilesToPackage.Add(MakeReleaseProfileForMod(Mod));
}

PackageMods(ProfilesToPackage);
Expand Down
100 changes: 100 additions & 0 deletions Mods/Alpakit/Source/Alpakit/Private/AlpakitEditModDialog.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
#include "AlpakitEditModDialog.h"

#include "ISourceControlModule.h"
#include "ISourceControlProvider.h"
#include "ISourceControlOperation.h"
#include "ISourceControlState.h"
#include "ModMetadataObject.h"
#include "SourceControlOperations.h"

#define LOCTEXT_NAMESPACE "AlpakitEditMod"

void SAlpakitEditModDialog::Construct(const FArguments& InArgs, TSharedRef<IPlugin> InMod) {
Mod = InMod;

// Construct the plugin metadata object using the descriptor for this plugin
MetadataObject = NewObject<UModMetadataObject>();
MetadataObject->TargetIconPath = Mod->GetBaseDir() / TEXT("Resources/Icon128.png");
MetadataObject->PopulateFromDescriptor(Mod->GetDescriptor());
MetadataObject->AddToRoot();

// Create a property view
FPropertyEditorModule& EditModule = FModuleManager::Get().GetModuleChecked<FPropertyEditorModule>("PropertyEditor");
EditModule.RegisterCustomClassLayout(UModMetadataObject::StaticClass()->GetFName(), FOnGetDetailCustomizationInstance::CreateStatic(&FModMetadataCustomization::MakeInstance));
TSharedRef<IDetailsView> PropertyView = EditModule.CreateDetailView(FDetailsViewArgs(false, false, false, FDetailsViewArgs::ActorsUseNameArea, true));
PropertyView->SetObject(MetadataObject, true);

SWindow::Construct(SWindow::FArguments()
.ClientSize(FVector2D(800.0f, 700.0f))
.Title(FText::Format(LOCTEXT("ModMetadata", "{0} ({1}) Properties"), FText::FromString(Mod->GetFriendlyName()), FText::FromString(Mod->GetName())))
.Content()
[
SNew(SBorder)
.Padding(FMargin(8.0f, 8.0f))
[
SNew(SVerticalBox)

+ SVerticalBox::Slot()
.Padding(5)
[
PropertyView
]

+ SVerticalBox::Slot()
.AutoHeight()
.Padding(5)
.HAlign(HAlign_Right)
[
SNew(SButton)
.ContentPadding(FMargin(20.0f, 2.0f))
.Text(LOCTEXT("OkButtonLabel", "Ok"))
.OnClicked(this, &SAlpakitEditModDialog::OnOkClicked)
]
]
]
);
}

FReply SAlpakitEditModDialog::OnOkClicked() {
FPluginDescriptor OldDescriptor = Mod->GetDescriptor();

// Update the descriptor with the new metadata
FPluginDescriptor NewDescriptor = OldDescriptor;
MetadataObject->CopyIntoDescriptor(NewDescriptor);
MetadataObject->RemoveFromRoot();

// Close the properties window
RequestDestroyWindow();

// Write both to strings
FString OldText;
OldDescriptor.Write(OldText);
FString NewText;
NewDescriptor.Write(NewText);
if(OldText.Compare(NewText, ESearchCase::CaseSensitive) != 0)
{
FString DescriptorFileName = Mod->GetDescriptorFileName();

// First attempt to check out the file if SCC is enabled
ISourceControlModule& SourceControlModule = ISourceControlModule::Get();
if(SourceControlModule.IsEnabled())
{
ISourceControlProvider& SourceControlProvider = SourceControlModule.GetProvider();
TSharedPtr<ISourceControlState, ESPMode::ThreadSafe> SourceControlState = SourceControlProvider.GetState(DescriptorFileName, EStateCacheUsage::ForceUpdate);
if(SourceControlState.IsValid() && SourceControlState->CanCheckout())
{
SourceControlProvider.Execute(ISourceControlOperation::Create<FCheckOut>(), DescriptorFileName);
}
}

// Write to the file and update the in-memory metadata
FText FailReason;
if(!Mod->UpdateDescriptor(NewDescriptor, FailReason))
{
FMessageDialog::Open(EAppMsgType::Ok, FailReason);
}
}
return FReply::Handled();
}

#undef LOCTEXT_NAMESPACE
Loading

0 comments on commit 6c19323

Please sign in to comment.