Skip to content

Commit

Permalink
Merge pull request #277 from satisfactorymodding/Dev
Browse files Browse the repository at this point in the history
Update with changes from Dev
  • Loading branch information
budak7273 authored Jan 29, 2024
2 parents 67683bc + 3d20d1e commit c0399e6
Show file tree
Hide file tree
Showing 6 changed files with 174 additions and 43 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -264,8 +264,11 @@ Click `Install`.
[WARNING]
====
Watch out - most older versions of Wwise don't have support for Unreal Engine 5, which this project needs.
Newer versions of Wwise __might__ work,
but they are likely to have other incompatible changes that will break the setup process.
If you don't see this exact Wwise version,
**Try to download the exact Wwise version mentioned above**.
If you don't see it,
try any other version starting with `2022.1.5`, preferring newer versions,
or asking for help on the Discord.
====
Expand Down Expand Up @@ -339,14 +342,15 @@ or the **`master` branch** .
Of those two, you probably want whichever branch was pushed to most recently, which you can see
https://github.com/satisfactorymodding/SatisfactoryModLoader/branches[on the GitHub repository].
If you're still uncertain which to download, **ask us on the Discord**.
If you choose to download the `dev` branch, click
https://github.com/satisfactorymodding/SatisfactoryModLoader/archive/refs/heads/dev.zip[here].
If you choose to download the `master` branch, click
https://github.com/satisfactorymodding/SatisfactoryModLoader/archive/refs/heads/master.zip[here].
====

If you're still uncertain which to download, ask us on the Discord.

Don't do anything with the downloaded files yet - this will be covered on the next page, Project Setup.

Expand Down
97 changes: 78 additions & 19 deletions modules/ROOT/pages/Development/ModLoader/SessionSettings.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -16,59 +16,116 @@ making them available exceedingly early in the loading process.
This may change in the future.

It's possible to make a session setting specific to only a certain level,
making them particularly useful for configuring options for custom levels.
making them particularly useful for providing config options for custom levels
since they can be edited before the save is created.

== Creation
== Defining New Session Settings

Session Settings are defined by Data Assets.
To create a Session Setting in Blueprint, in a content browser right click and select
`Create Advanced Asset` > `Miscellaneous` > `Data Asset` and search for `SMLSessionSetting`.

== Registration
=== Selecting a Str Id

To register a Session Setting, list it the relevant array in your mod's
xref:Development/ModLoader/ModModules.adoc#_game_instance_bound_module_ugameinstancemodule[Game Instance Module].
Session Settings inherit from `UFGUserSetting`, the class the game uses to define the configuration options in the settings menu.

As soon as the Session Setting is registered it will be available to be set in the SML Session Settings menu,
which is available at both world creation and in the pause menu.
The "Str Id" field is a unique identifier for the session setting
and is used for retriving the value of the session setting later.
See the table below for some examples of Str Ids and things to keep in mind when selecting one.

== Configuration
.Example Session Setting Str Ids
|===
|✔️ Good Example |❌ Bad Practice

Session Settings inherit from `UFGUserSetting`, the class the game uses to define the configuration options in the settings menu.
|✔️ `YourModReference.EnableFizzBuzz`

Prefix the id with your Mod Reference to ensure it is unique across mods.

| ❌ `EnableFizzBuzz`

Another mod could implement a session setting by this name,
leading to a conflict.

|✔️ `YourModReference.WhizzbangStrengthMult`

Since session settings are referenced by their string id,
giving them a verbose, unique name makes it easy to find all usages of the setting in code
via a find operation.

| ❌ `YourModReference.Multiplier`

Multiplier for what? It's easy to forget what this setting controls,
and if you ever decide to add other "multipliers" in the future,
they could easily be mentally confused with this one.

|✔️ `YourModReference.PowerCostMultFloat`

Since you must use a type-specific method to read/write a Session Setting,
consider including the setting's type as part of its id as a reminder of what type it is.
Unfortunately using the wrong getter method is currently a silent error due to how the FG Options system is implemented,
making this problem particularly annoying to track down.

|
// intentionally blank

|✔️ `YourModRef.MinerMk1.PowerCostMultFloat`

Consider indicating which building/feature a setting applies to
if you offer multiple settings with similar names or functionality.

|
// intentionally blank


|===

=== Selecting Session Setting Behaviors

Not all of the properties of `UFGUserSetting` are relevant to Session Settings.
You will have to experiment to see which ones have an effect.
Please update this documentation page via "Edit This Page" in the top right with your findings.

The "Str Id" field is a unique identifier for the session setting.
It should include your Mod Reference and is used for retriving the value of the session setting later.

Checking the "Use CVar" field is only required
if you wish to allow modifying the value of the session setting via the game console.

SML automatically forces the following property values on Session Settings.
If you change any of these properties they will be automatically reset to these values
next time the asset is loaded.

- ShowInBuilds: `Public Builds` to ensure that session settings are visible to the user
- ManagerAvailability: `USM MAX`, which is an invalid value, ensuring that the setting never displays in base-game options menus.
- IsSettingSessionWide: `true` to ensure that multiplayer clients are able to modify session settings and have their changes stored with the save file.
* ShowInBuilds: `Public Builds` to ensure that session settings are visible to the user
* ManagerAvailability: `USM MAX`, which is an invalid value, ensuring that the setting never displays in base-game options menus.
* IsSettingSessionWide: `true` to ensure that multiplayer clients are able to modify session settings and have their changes stored with the save file.

In order to have a session setting only editable at save creation, use the "Don't show in game" Visibility Disqualifier.

=== Registration

A Session Setting must be registered to be usable by the player.

To register a Session Setting, list it in the relevant array of your mod's
xref:Development/ModLoader/ModModules.adoc#_game_instance_bound_module_ugameinstancemodule[Game Instance Module].

Registering a Session Setting makes it available to be configured in the SML Session Settings menu
which is available at both world creation and in the pause menu.

== Reading and Writing Session Settings

You can read the value of a session setting via the "Get <something> Option Value" method of the Session Settings Manager.
You can also subscribe to changes via "Subscribe to Dynamic Option Update".

Check ExampleMod for some example session settings and how to read their values.
There is an example in the ExampleMod Level Blueprint and in the Game World Module.

If you want to programatically modify the value of a session setting,
use the "Set <something> Option Value" method of the Session Settings Manager.

Check ExampleMod for some example session settings and how to read their values.
There is an example in the ExampleMod Level Blueprint and in the Game World Module.

// TODO are they currently synced from clients to host? SML forces them all to be "for all players" so it can be saved with the savegame.
An example of reading a integer Session Setting value from {cpp}:

```cpp
// self->GetWorld() can be substituted with any other method of obtaining world context
USessionSettingsManager* SessionSettings = self->GetWorld()->GetSubsystem<USessionSettingsManager>();
auto optionValue = SessionSettings->GetIntOptionValue("YourModReference.IntSessionSetting");
```

// TODO verify
// Session settings are stored in the session settings subsystem https://discord.com/channels/555424930502541343/562722670974599227/1126996669481889903
Expand All @@ -83,6 +140,8 @@ Mod Config is better for user interface or visual stuff since it is saved with t

Session Settings are good for things you want to be a choice per save file, such as options for a custom level.

Session Setting values are xref:Development/Satisfactory/Multiplayer.adoc[replicated in multiplayer].

== Advanced Game Settings

In order to create an Advanced Game Setting instead of a Session Setting,
Expand Down
71 changes: 58 additions & 13 deletions modules/ROOT/pages/Development/Satisfactory/Multiplayer.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -51,22 +51,62 @@ contains some examples of correctly adding multiplayer functionality to mods.

The examples are not exhaustive, but they should help you get started.

== Remote Call Objects
[id="RPCs"]
== Remote Procedure Calls (RPCs)

Remote Call Objects are an Unreal concept described in the video.
Note that dedicated servers have no player controller they can't make use of Remote Call Objects.
In that case, consider using a link:#ReplicatedSubsystems[Replicated Subsystem] instead.
The video explains what a Remote Procedure Call (RPC) is.
You can find more detailed information in the
https://docs.unrealengine.com/5.2/en-US/rpcs-in-unreal-engine/[Unreal Engine documentation].

Coffee Stain Studios has written custom code to make it easier for mods to register their own Remote Call Objects.
The inner details of this system are described in the link:#HowRCOsImplemented[appendix].
Satisfactory mods generally have their RPCs defined in one of two places depending on the use case.
The table below contains information about when to use each.
Be sure to read the sections below that explain each system in more detail.

Remote call objects can be registered via listing their classes in your Game Instance Module's `Remote Call Objects` array.
.Remote Call Object or Replicated Mod Subsystem
|===
| Use a link:#RCOs[Remote Call Object (RCO)] when... | Use a link:#ReplicatedSubsystems[Replicated Mod Subsystem] when...

Remote call objects can be retrieved from a player controller instance via
| Your RPC is sending info from one client to the server.

| Your RPC is sending info from the server to one or more clients.

| When the RPC is being called because of some action the client took.

| When the RPC is being called automatically or without client action.

|
// Intentionally blank

| When your RPC is Multicast

|===

=== RPC Execution

The outcome of calling an RPC depends on the RPC's type and the network ownership of the calling actor.
The https://docs.unrealengine.com/5.2/en-US/rpcs-in-unreal-engine/#requirementsandcaveats[Unreal Documentation]
has an excellent table summarizing the different possible execution results.

[id="RCOs"]
== Remote Call Objects (RCOs)

A Remote Call Object (RCO) is a convenient place for modded RPCs to be defined.
Coffee Stain Studios has written custom code to make it easier for mods to register their own RCOs.
The inner details of this system are described in the link:#HowRCOsImplemented[appendix] if you want to learn more.

RCOs are spawned by the server for each player controller,
but importantly, that player controller is given network ownership of the RCO.
This gives RCOs the ability to call RPCs -
RPCs only work on objects that are (transitively) owned by the connection
(i.e. the player controller, which is owned by the connection).
Without this network ownership, RPCs would fail to execute.

RCOs can be registered via listing their classes in your Game Instance Module's `Remote Call Objects` array.
Registered RCOs can be retrieved at runtime from a player controller instance via
`FGPlayerController::GetRemoteCallObjectOfClass`
which is accessible in both blueprints and {cpp}.

If for some reason you need to manually register a remote call object it can be done via
If for some reason you need to manually register an RCO it can be done via
`FGPlayerController::RegisterRemoteCallObjectOfClass` or
`FGGameMode::RegisterRemoteCallObjectClass`.

Expand All @@ -78,14 +118,16 @@ they do not exist on every connection.
As such, you should not use them for any multicast RPCs - triggering one will softlock and crash client players!
If you want to use Multicast, do it from an link:#ReplicatedSubsystems[Replicated Subsystem] instead.

An example why you should not do this is demonstrated in the ExampleMod.
An example why you should not do this is demonstrated in the ExampleMod's `CC_ExampleReplication` chat command.

[id="RCO_Blueprint"]
=== Blueprint Example

Your remote call objects should inherit from `BP Remote Call Object`.

The ExampleMod demonstrates blueprint remote call object registration and usage from a building.
The ExampleMod demonstrates blueprint remote call object usage in `Widget_MultiplayerDemoBuilding`.

[id="RCO_Cpp"]
=== {cpp} Example

Your remote call objects should inherit from `FGRemoteCallObject`.
Expand Down Expand Up @@ -157,10 +199,13 @@ Configure if a subsystem is replicated via its `Replication Policy` field.

Replicated subsystems are a good place to implement multicast RPCs since they will be present on all connections.

[id="ReplicatedSubsystem_Blueprint"]
=== Blueprint Example

The ExampleMod uses a replicated property on the Multiplayer Demo Building.
The ExampleMod uses a Multicast RPC
on the `ReplicationExampleSubsystem` to implement the `CC_ExampleReplication` chat command.

[id="ReplicatedSubsystem_Cpp"]
=== {cpp} Example

No example is currently provided.
Expand All @@ -174,7 +219,7 @@ See the video or Unreal documentation for more info on their purpose.

Variables can be configured to replicate by specifying their `Replication` option in the details panel.

The ExampleMod uses a replicated property on the Multiplayer Demo Building.
The ExampleMod uses a replicated property with RepNotify in `Build_MultiplayerDemoBuilding`.

=== {cpp} Example

Expand Down
22 changes: 19 additions & 3 deletions modules/ROOT/pages/Development/TestingResources.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -78,11 +78,13 @@ $Args1 = "$CommonArgs", "-Username=`"$Username1`""#, "-WinX=0", "-WinY=32", "Res
if ($loadLatestSave) {
# https://stackoverflow.com/questions/9675658/powershell-get-childitem-most-recent-file-in-directory
$latestSaveFile = (Get-ChildItem $SaveFolder | sort LastWriteTime | select -last 1)
# 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 = "$GameDir\$AutolaunchTempFileName"
New-Item $AutolaunchFilePath -ItemType File -Force -Value "[/Script/EngineSettings.GameMapsSettings]`n"
$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"
Expand Down Expand Up @@ -125,6 +127,13 @@ and that the `-loadLatestSave` flag requires
link:#LoadCustomLevel[extra configuration] to work with saves made in custom levels
and doesn't guarantee that you'll be put into the same player pawn.

[NOTE]
====
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 https://docs.unrealengine.com/4.26/en-US/ProductionPipelines/CommandLineArguments/[many]
Expand Down Expand Up @@ -288,6 +297,8 @@ 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 https://satisfactory.wiki.gg/wiki/Dedicated_servers#Loading_a_save_file[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.
Expand Down Expand Up @@ -329,6 +340,11 @@ Now that you've decided how you want to set up your server,
follow the directions on the https://satisfactory.wiki.gg/wiki/Dedicated_servers[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 xref:ForUsers/DedicatedServerSetup.adoc[the same way an end user would]
or follow the process outlined in the Option section you selected above.

== Modify Online Subsystem Behavior

// From https://discord.com/channels/555424930502541343/562722670974599227/1044575456659259472
Expand Down
15 changes: 10 additions & 5 deletions modules/ROOT/pages/ForUsers/DedicatedServerSetup.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@ You could also install ficsit-cli on the server and interact with its file syste
// cspell:ignore CIFS
[NOTE]
====
SMM cannot currently connect to servers by filesystem path, including SMB/CIFS or network mounts.
SMM cannot currently connect to servers by filesystem path.
This includes **local servers** (on your computer) and SMB/CIFS or network mounts.
Use ficsit-cli for this in the mean time.
====

Expand All @@ -76,7 +77,8 @@ If using the Mod Manager to manage your server:
* If you don't see this option, ensure that you have installed the latest version of the Mod Manager,
as only versions 3.0.0 and up support this feature.
. Enter server connection details in the popup window.
* Decide what method to select and what to enter by reading the link:#FileTransferMethods[File Transfer Methods] section,
* Decide what method to select and what to enter
by reading the link:#FileTransferMethods[File Transfer Methods] section,
then return here.
. The server will now appear in your Game Version dropdown and can be managed like a local install.
. Skim the below ficsit-cli section to stay informed, then continue reading the link:#ServerClientConsistency[next setup step].
Expand All @@ -101,6 +103,8 @@ If using ficsit-cli to manage your server:
. The server will now appear as an install you can select and manage as usual.
. Read the below, then continue reading the link:#ServerClientConsistency[next setup step].

ficsit-cli will probably see your local Satisfactory Mod Manager profiles and may have one selected by default.
Consider creating a new profile to use for your server.
Make sure to apply changes after installing mods or loading a profile,
otherwise all changes will be discarded on exit.

Expand Down Expand Up @@ -155,18 +159,19 @@ image::DedicatedServers/SMM_FTP.png[Satisfactory Mod Manager Example]
image::DedicatedServers/CLI_FTP.png[Ficsit-CLI Example]

[id="FileTransferMethods_SMB"]
=== SMB/CIFS
=== Filepath or SMB/CIFS

Server Message Block (SMB), also known as CIFS (Common Internet File System) or Windows File Shares,
is a network file transfer method commonly used on Windows Systems and occasionally Linux/Unix systems.
Think of it like Windows file paths but expanded to supports network locations.
SMB typically uses TCP port 445, but your server may differ.
The examples below are for a self-hosted dedicated server.

* The authenticating user requires Read/Write/Delete or Read/Modify permissions.
* The path should follow this format:
** If using a Windows ficsit-cli install:
+
`\\ServerNameOrIP\ShareName\Path` or `//ServerNameOrIP/ShareName/Path`
*** If the server is installed on your local computer, use the file path, for example `C:\EpicGamesGames\SatisfactoryDSExperiment`
*** If the server is on a network location: `\\ServerNameOrIP\ShareName\Path` or `//ServerNameOrIP/ShareName/Path`
** If using a Linux ficsit-cli install:
+
link:https://github.com/satisfactorymodding/ficsit-cli/issues/57[(A bug is currently preventing this from working)]
Expand Down
Loading

0 comments on commit c0399e6

Please sign in to comment.