Testing Your Mods

Testing your mods to ensure that content is accessible and there are no bugs present is an important step in development. Careful testing before release can save you from having to release multiple versions in quick succession in order to fix a bug.

This page lists some helpful resources and information regarding testing your mods.

SML Logging

SML Logging is a valuable troubleshooting and testing tool, especially for blueprint mods.

You can find more information on how to use and configure it on the Logging page.

If you select text in the log terminal window, it will freeze the game until you press 'enter' to deselect it. This can help with reading things before they would normally scroll by.

Since the log terminal is a regular Windows Command Prompt window, you can right click on its top bar and set some default customization values, such as where the window spawns and how wide it is, which will be applied every time the terminal opens. You can use this to have it always open on a second monitor, for example. Be aware that the values you set here will affect every instance of Command Prompt on your system. See the Launch Script Enhancements section below for another method of controlling where the window will appear.

Quick Launch Script

Testing mods often involves frequent restarts of the game. You can shave some time off of this process by launching via a script that loads you directly into the game world. In order to use this script, create a file with the .ps1 extension somewhere convenient to you.

Next, copy the contents of the below codeblock into the file. Note that you will have to modify the section near the top to match the location of files on your system.

If you have never ran a powershell script before on your Windows install, you may need to modify the system execution policy to allow them to run.

param (
	[string]$branch = "EA",
	[switch]$multiplayer = $false,
	[switch]$loadLatestSave = $false
)

# Configure these to match your system and preferences
$GameDir_EA = "C:\EpicGamesGames\SatisfactoryEarlyAccess"
$GameDir_EXP = "C:\EpicGamesGames\SatisfactoryExperimental"
$SaveFolder = "C:\Users\YourUserName\AppData\Local\FactoryGame\Saved\SaveGames\YourID"
$Username1 = "Host" # Note - Unreal Engine 5 has broken the Username functionality, so this is currently ignored
$Username2 = "Client"
$CommonArgs = "-EpicPortal", "-NoSteamClient", "-NoMultiplayer", "-log"
# End configuration section

$AutolaunchTempFileName = "AutolaunchScript_Temp.ini"

if ($branch -eq "EA") {
	$GameDir = $GameDir_EA
} elseif ($branch -eq "EXP") {
	$GameDir = $GameDir_EXP
} else {
	Write-Error "Unknown branch type: '$branch'"
	return
}

# You can optionally configure the window size and position on the screen per instance
$Args1 = "$CommonArgs", "-Username=`"$Username1`""#, "-WinX=0", "-WinY=32", "ResX=960", "ResY=1040"

# TODO multiplayer and loadLatestSave arguments incompatible. direct loading into a save does not allow joining via `open 127.0.0.1` in the client, the host must manually load another save file for that to be set up

if ($loadLatestSave) {
	# https://stackoverflow.com/questions/9675658/powershell-get-childitem-most-recent-file-in-directory
	# Steam keeps a steam_autocloud.vdf file in here that isn't a savegame
	$latestSaveFile = (Get-ChildItem $SaveFolder -Attributes !Directory -Filter *.sav | sort LastWriteTime | select -last 1)
	$latestSaveFileName = $latestSaveFile.Basename

	$AutolaunchFilePath = "$($env:LOCALAPPDATA)\FactoryGame\$AutolaunchTempFileName"
	New-Item $AutolaunchFilePath -ItemType File -Force
	Add-Content $AutolaunchFilePath "[/Script/EngineSettings.GameMapsSettings]"
	Add-Content $AutolaunchFilePath "LocalMapOptions=??skipOnboarding?loadgame=$latestSaveFileName"
	Add-Content $AutolaunchFilePath "GameDefaultMap=/Game/FactoryGame/Map/GameLevel01/Persistent_Level.Persistent_Level`nGameInstanceClass=/Script/FactoryGame.FGGameInstance"

	$Args1 = "$Args1", "EngineINI=`"$AutolaunchFilePath`""
}

$Args2 = "$CommonArgs", "-Username=`"$Username2`""#, "-WinX=960", "-WinY=32", "ResX=960", "ResY=1040"

function BGProcess(){
    Start-Process -NoNewWindow @args
}

BGProcess "$($GameDir)\FactoryGame.exe" $Args1

if ($multiplayer) {
	sleep -m 5000
} else {
	return
}

BGProcess "$($GameDir)\FactoryGame.exe" $Args2

Usage

After the launch script has been set up, use flags when running it to controls its behavior. Note that in order to use the branch feature you must have separate copies of the game installed in the locations you specified in the config section.

Assuming your powershell file is named SFLaunch_Advanced:

  • .\SFLaunch_Advanced.ps1 will launch the Early Access version of the game

  • .\SFLaunch_Advanced.ps1 -loadLatestSave will automatically load you into the last save file you made.

  • .\SFLaunch_Advanced.ps1 -branch EXP will launch the Experimental copy of the game

  • .\SFLaunch_Advanced.ps1 -multiplayer will launch two copies of the game

  • .\SFLaunch_Advanced.ps1 -branch EXP -multiplayer will launch two copies of the Experimental game

Note that the -multiplayer flag is currently incompatible with the -loadLatestSave flag and that the -loadLatestSave flag requires extra configuration to work with saves made in custom levels and doesn’t guarantee that you’ll be put into the same player pawn.

When using the -loadLatestSave flag, if the game can’t load the save for some reason (for example, trying to load a newer save in an older version of the game) the game will create and load into a new save file instead.

Launch Script Enhancements

Unreal supports many other command-line arguments, some of which may prove to be useful with MP testing. For example, -WinX=0 -WinY=0 will open the game in the top left corner of the screen. Similar arguments also exist for the console window (ConsoleX and ConsoleY). You can also specify what resolution you want the game to run at: -WinX=1280 -WinY=720.

If you want windows to open on other monitors, you will need to use either negative or larger numbers for the arguments. The top left corner of your primary monitor is X=0, Y=0.

Combining these options, you could end up with launch args like those shown below, which will give each instance as much screen space as possible (while accounting for Title Bar and Start Menu height) on a 1920x1080 resolution screen, at the cost of an unusual aspect ratio.

$Args1 = "-EpicPortal", "-NoSteamClient", '-Username="'+$Username1+'"', "-WinX=0", "-WinY=32", "ResX=960", "ResY=1040"
$Args2 = "-EpicPortal", "-NoSteamClient", '-Username="'+$Username2+'"', "-WinX=960", "-WinY=32", "ResX=960", "ResY=1040"

Multiplayer Testing

Update 8 has recently changed how local multiplayer testing works. This page has not yet been updated to reflect these changes. You must load with the -offline flag and use a Map Travel URL with the ?listen argument to be able to connect. For example, open Persistent_Level?loadgame=NameOfYourSaveGame?listen. Remember that Session Settings are stored in the Map Travel URL as well so the defaults will be used if you don’t specify them directly in the travel URL here.

Consider locally hosting your own dedicated server for multiplayer testing instead.

Locally testing multiplayer functionality requires running two copies of the game at once. Normally the Steam and Epic Games client don’t allow you to do this, but the launch script in the previous section will allow you to do so.

Instructions

  1. First, run the launch script with the -multiplayer flag to open two copies of the game.

  2. Open up your save file in either copy of the game - this one will be the host, the other copy is the client.

  3. Once you’ve loaded in, go to the client game instance and open the in-game console. Learn how to do this here. Then type in open 127.0.0.1 and hit enter. The second instance will now connect to the game hosted by the first instance.

Load a Custom Level on Launch

The launch script demonstrates how to make the game to automatically load to the game world on launch, as opposed to the main menu, cutting down on load time and clicks when testing your mod. However, you will need to tweak it slightly if the level you want to load is a custom level.

Notice that the powershell script’s loadLatestSave option creates an ini file on the fly containing instructions to load into a specific save file and GameDefaultMap. You’ll either need to modify the powershell script to point to your custom level or create your own ini file for it to use instead.

First, you’ll need to find the path to use for your custom level. It’s based on the level’s asset path. For example, Nog’s Level’s level asset is at the content root, so its path is /NogsLevel/NogsLevel.NogsLevel. Example Level’s is a few layers of folder deep, it’s path is /ExampleMod/Maps/ExampleLevel/ExampleLevel.ExampleLevel.

While you’re at it, there are a few other flags you can use to customize the loading process:

FG Map Options Switches from Archengius:

Switches found in AFGGameMode::InitGame:

?skipOnboarding (skip landing animation)
?allowPossessAny (allow possessing any pawn on the map, even if player IDs don't match)
?loadgame=<SaveGame Name Here Without Path and extension>
?startloc<Start Location Tag Name> (see AFGGameMode::ChoosePlayerStart_Implementation)
?sessionName=<Session Name> (sets mSaveSessionName, so apparently it determines autosave file name and probably name visible to other players?)
?DayLength=<Day Length In Minutes>
?NightLength=<Night Length In Minutes>

General notes:
  Regarding Start Location Tag Name:
      - TRADING_POST is the hub APlayerStart actor tag
      - Any APlayerStart actor with matching PlayerStartTag is selected
  Regarding Session Name:
      - Apparently there is a system of "bundled saves" that I know nothing about. Further investigation is required.

Switches found in AFGGameSession:

?Visibility=SV_Private/SV_Public (Session visibility)
?adminpassword=<Admin Password used in console command AdminLogin to gain host privileges>

There is also ?bUseIpSockets linked with offline sessions
Apparently it disables EOS sockets and makes the game fall back to normal IPv4 sockets

Option 1: Modify Powershell Script’s Automatic ini Generation

Alter the Add-Content instruction that adds a GameDefaultMap to point to the asset path of your custom level. Note that this requires you to use the loadLatestSave flag (since that’s what causes the script to generate the ini file) or modify the script to use the ini file under other conditions.

Option 2: Use Your Own ini File

Note how the powershell script uses the EngineINI option to point to an Engine.ini file to use when launching the game.

You can manually write an ini file and modify the powershell script to always launch the game with it, or, launch separate from the powershell script by writing your own command.

For example, if your file was called LoadMapEngineConfiguration.ini, your launch command could look like this:

"D:\SatisfactoryExperimental\FactoryGame\Binaries\Win64\FactoryGame-Win64-Shipping.exe" -EpicPortal -NoMultiplayer -Username=Player1 EngineINI="D:\SatisfactoryExperimental\LoadMapEngineConfiguration.ini"

Note that you will have to modify this example command so that it points to where you have the game installed.

You might want to save it in a batch file or powershell script for easy execution later.

Option 3 - Add to Default Game Configuration

Instead of creating a new file for your configuration, you can edit your default game configuration, found at %APPDATA%/Local/FactoryGame/Saved/Windows/Engine.ini.

If you choose this option, the game will always launch using this config no matter where you launch it from, even when mods are not installed.

Dedicated Servers

In order to start testing on dedicated servers, you will first need to set up your own dedicated server.

Setup

You have a few options for setting up the server. Consider which of these would work best for you before moving on to the next section.

Note that in order to perform the first time server claiming process you will need to use a client of the game that was launched normally (ex. through Steam or Epic). After the server claiming process is complete you can return to using a copy launched with the launch scripts described elsewhere on this page.

Option 1: Locally Installed Dedicated Server

You can install the dedicated server on your own computer and run it locally. This places extra strain on your computer and may not be feasible if you have a lower-end system. However, it is usually the easiest option to set up.

In this option, since the dedicated server will be sharing your own personal copy of the game’s save folder, attempting to upload saves to it will fail, since the save is already present in that folder. Selecting a save to use will require editing the server’s session name; follow the directions on the Satisfactory wiki to do this.

Since the server you will be testing with does not need to connect to the internet, following the wiki’s directions for correctly authenticating with Steam or Epic servers are not required. The minimum suggested launch arguments for a dedicated server is .\FactoryServer.exe -log -EpicPortal -NoSteamClient.

You can connect to a locally hosted server either through the normal server browser or with the open console command, for example, open 127.0.0.1.

Option 2: Remote Dedicated Server

You can also set up the dedicated server on another computer on your network. This avoids resource strain on your own computer.

It is possible to provide a network location in the Copy Game to Path Dev Packaging setting option, for example //192.168.1.42/appdata/satisfactory, meaning that Alpakit will handle copying and replacing the files on the remote server for you.

You’ll still need to restart it after every package for the server to reload file changes.

Option 3: Ask Nicely on Discord

A community member may have a dedicated server they can give you access to in order to test mods on. Ask in the modding help channels and see if anyone speaks up, but you may not get a response.

You will likely have to manually transfer each testing build of the mod to the server.

Option 4: Cross your Fingers

The option of last resort: you can compile your mods for dedicated servers and release them without testing them. Do not assume that silence means the mod is bug free - some users will not bother to report errors they encounter. If you choose this route, you should mention on your mod page that your mods haven’t been tested extensively on dedicated servers.

Installing and Claiming the Server

Now that you’ve decided how you want to set up your server, follow the directions on the Satisfactory Wiki to set up a working dedicated server and verify that you can connect to it with an unmodified client.

Once you’ve verified that you can connect to the vanilla server you can start adding mods to it. Either install them the same way an end user would or follow the process outlined in the Option section you selected above.

Modify Online Subsystem Behavior

Additional information about the Online Subsystem.

True offline mode information from Archengius:
Example configuration file to run game offline with just IP sockets and no online subsystems and strings attached whatsoever

[/Script/EngineSettings.GameMapsSettings]
GameDefaultMap=/Game/FactoryGame/Map/MenuScenes/Map_MenuScene_Update_06.Map_MenuScene_Update_06
ServerDefaultMap=/Game/FactoryGame/Map/DedicatedserverEntry.DedicatedserverEntry
LocalMapOptions=

[URL]
Name=Player
Port=7777

[/Script/Engine.Engine]
NetDriverDefinitions=(DefName="GameNetDriver",DriverClassName="/Script/OnlineSubsystemUtils.IpNetDriver",DriverClassNameFallback="/Script/OnlineSubsystemUtils.IpNetDriver")
NetDriverDefinitions=(DefName="BeaconNetDriver",DriverClassName="/Script/OnlineSubsystemUtils.IpNetDriver",DriverClassNameFallback="/Script/OnlineSubsystemUtils.IpNetDriver")
NetDriverDefinitions=(DefName="DemoNetDriver",DriverClassName="/Script/Engine.DemoNetDriver",DriverClassNameFallback="/Script/Engine.DemoNetDriver")

[OnlineSubsystem]
DefaultPlatformService=NULL
NativePlatformService=NULL

[OnlineSubsystemSteam]
bEnabled=false
bRelaunchInSteam=false

[OnlineSubsystemEOS]
bEnabled=false

[OnlineSubsystemNull]
bEnabled=true

Example command line:

FactoryGame-Win64-Shipping.exe -NoEpicPortal -EngineIni="C:\EpicLibrary\SatisfactoryExperimental\OfflineEngineIni2.ini" -Multiprocess -Log

-Multiprocess prevents game writing to any files (which is really what you want if you plan running multiple instances simultaneously) and -Log opens the console log window