Skip to content

Commit

Permalink
Merge pull request #301 from satisfactorymodding/Dev
Browse files Browse the repository at this point in the history
Update with changes from Dev
  • Loading branch information
budak7273 authored Jun 14, 2024
2 parents f9eaa28 + f29dadf commit ce83cdc
Show file tree
Hide file tree
Showing 8 changed files with 132 additions and 59 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/push.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ jobs:
- id: lychee
uses: lycheeverse/lychee-action@v1
with:
args: --verbose --exclude-all-private --accept '200,429' --github-token '${{ secrets.LYCHEE_TOKEN }}' './build/**/*.html'
args: --verbose --exclude-all-private --no-progress --accept '200,429' --github-token '${{ secrets.LYCHEE_TOKEN }}' './build/**/*.html'
fail: true

image:
Expand Down
1 change: 1 addition & 0 deletions cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@
"UKBFL",
"umenuworldmodule",
"undetailed",
"UE_LOGFMT",
"UOBJECT",
"UPARAM",
"uplugin",
Expand Down
12 changes: 6 additions & 6 deletions lychee.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,9 @@
# Exclude URLs and mail addresses from checking (supports regex).
# Please explain the inclusion of each one.
exclude = [
# This will always be a 404 unless you're authed
# These will always be 404s unless you're authed
"https://github.com/satisfactorymodding/UnrealEngine/",
# This will always be a 404 unless you're authed
"https://github.com/EpicGames/UnrealEngine/",
# This will always be a 404 unless you're authed
"https://github.com/SatisfactoryModdingUE/UnrealEngine/",
# Site seems to disallow robots
"https://cable.ayra.ch/satisfactory/editor.php",
Expand All @@ -24,10 +22,12 @@ exclude = [
"https://www.audiokinetic.com/en/download/",
# unable to get local issuer certificate
"https://questions.satisfactorygame.com/",
# 403s despite being valid page
# 403s despite being valid pages
"https://stackoverflow.com/questions/",
# 403s despite being valid page
"https://www.unrealengine.com/en-US/ue-on-github"
"https://www.unrealengine.com/en-US/ue-on-github",
# 403s despite being valid page, we should try to get this working somehow, since these links can change without warning
"https://docs.unrealengine.com/",
"https://dev.epicgames.com/"
]

# Exclude these filesystem paths from getting checked.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,11 @@ try turning off any ad-blockers or content filters you may have enabled and refr
You will probably have to check your email and confirm from there,
as well as making sure you're logged into your linked GitHub account when you follow the upcoming link.

Verify this step has worked by visiting this repository link:
https://github.com/EpicGames/UnrealEngine/
If it worked, you will see a private GitHub repository
Close that browser tab - we don't need any files this repository.

[id="UnrealLinker"]
=== Link Your GitHub Account to Our Repository

Expand Down
75 changes: 45 additions & 30 deletions modules/ROOT/pages/Development/Cpp/hooking.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -33,28 +33,28 @@ The call scope object allows you to:
+
[source,cpp]
----
void hook(TCallScope<...>& Scope, class* exampleClass, int exampleArg)
scope.Cancel();
void hook(TCallScope<...>& Scope, class* exampleClass, int exampleArg) {
Scope.Cancel();
}
----
- Call the next hooks and the final function within your body.
Calling the scope need to have all the same parameters as the func hook signature.
+
[source,cpp]
----
void hook(TCallScope<int(int)>& Scope, class* exampleClass, int exampleArg)
void hook(TCallScope<int(int)>& Scope, class* exampleClass, int exampleArg) {
// stuff before final function call
int result = scope(exampleClass, exampleArg); // call following hooks (final function might get called as long as following hooks don't cancel/overwrite it)
int result = Scope(exampleClass, exampleArg); // call following hooks (final function might get called as long as following hooks don't cancel/overwrite it)
// stuff after final function call
}
----
- You can also override the return value before the final call (causes the final call to not occur)
+
[source,cpp]
----
void hook(TCallScope<int(int)>& Scope, class* exampleClass, int exampleArg)
void hook(TCallScope<int(int)>& Scope, class* exampleClass, int exampleArg) {
// final function might get called
scope.Override(customReturnValue);
Scope.Override(customReturnValue);
// final function wont get called anymore
}
----
Expand Down Expand Up @@ -82,28 +82,43 @@ Each attachment method works differently under the hood, and it's important to p
Be aware that type of return values and parameters etc has nothing to do with each other or if it is a member function, you can use them in any way.
Note that the Hook function is a std::function, which means that it can be any type a std::function can accept, such as function pointers, function pointers with bound placeholders, or even lambdas.

[WARNING]
[IMPORTANT]
====
If your mod is not {cpp} only, meaning it is Blueprint **and** {cpp}, you should surround your hook functions with `#if !WITH_EDITOR`, remembering to place `#endif` after the end of your hook function. Failure to do so may prevent the Unreal Editor from opening.
The behavior of hooks at editor time is highly unpredictable and can cause crashes.
As such, you should ensure that your hooks are not applied at editor time,
else you could potentially be unable to open the Unreal Editor until you edit the hook code externally.
The most convenient way is to put the `SUBSCRIBE_` macros in your code inside an `if (!WITH_EDITOR) { ... }` block:
[source,cpp]
----
if (!WITH_EDITOR) {
SUBSCRIBE_METHOD(SomeClass::SomeMethod, &Hook_SomeMethod);
}
----
Using `#if !WITH_EDITOR` and `#endif` directives is also an option, but it is not recommended: it hides errors until building shipping and confuses IDEs, making development and debugging slightly more annoying with no benefit.
====

=== Type: SUBSCRIBE_METHOD

The `SUBSCRIBE_METHOD`-Macro attaches a hook to the given function passed by pointer.
SML will take that function pointer and find the symbol name so bootstrapper can then redirect
the function calls for that symbol to SML's hook framework.
The `SUBSCRIBE_METHOD`-Macro attaches a hook
such that the code you pass will be called before the function executes.

If multiple mods have subscribed to the same function,
the hooks will be called in the order they were registered.

Usage goes as following:

[source,cpp]
----
#include "Patching/NativeHookManager.h"
class SomeClass {
// in target class SomeClass
public:
int MemberFunction(int arg1);
static void StaticFunction();
}
// in your code
#include "Patching/NativeHookManager.h"
void registerHooks() {
SUBSCRIBE_METHOD(SomeClass::MemberFunction, [](auto& scope, SomeClass* self, int arg1) {
Expand All @@ -125,30 +140,29 @@ to explicitly set the symbol you want to hook.

=== Type: SUBSCRIBE_METHOD_VIRTUAL

The `SUBSCRIBE_METHOD_VIRTUAL`-Macro attaches the given hook to the given function passed
by pointer in the virtual table of the given class.
This happens by SML reading the function symbol and class name so bootstrapper can then
change the the virtual table entry to the proper function of the SML hooking framework.
The `SUBSCRIBE_METHOD_VIRTUAL` macro attaches the given hook to the function passed by pointer for the given class.

That also means, you change the virtual table of only the given table,
if you allow want to change the virtual table entry of other classes you need to hook them
separately.
This hook only modifies the function that the virtual table for the given class points to.
Functions in subclasses overriding the virtual function of the given class won't be modified,
but the hook will still run if the hooked function is called by the overriding implementation (i.e. "calls super").
If the overriding implementation of a subclass does not "call super", you have to hook said subclass separately.
Because pure virtual functions do not have a proper function body, they cannot possibly be hooked.

Usage goes as following:

[source,cpp]
----
#include "Patching/NativeHookManager.h"
class SomeClass {
// in target parent class SomeClass
public:
virtual int MemberFunction(int arg1);
}
class SomeChild : public SomeClass {
// in child class SomeChild that we don't want to hook
// class SomeChild : public SomeClass
public:
virtual int MemberFunction(int arg1) override;
}
// in your code
#include "Patching/NativeHookManager.h"
void registerHooks() {
SUBSCRIBE_METHOD_VIRTUAL(SomeClass::MemberFunction, SomeClass, [](auto& scope, SomeClass* self, int arg1) {
Expand Down Expand Up @@ -180,8 +194,8 @@ For "after" hooks, add the `_AFTER` postfix to the macro names.

Be aware that the hook function signature changes accordingly and will no longer need the "scope":
[horizontal]
*Non-Virtual*:: `SUBSCRIBE_METHOD_AFTER(SomeClass::MemberFunction, [](SomeClass* self)`
*Virtual*:: `SUBSCRIBE_METHOD_VIRTUAL_AFTER(SomeClass::MemberFunction, [](SomeClass* self)`
*Non-Virtual*:: `SUBSCRIBE_METHOD_AFTER(SomeClass::MemberFunction, [](SomeClass* self))`
*Virtual*:: `SUBSCRIBE_METHOD_VIRTUAL_AFTER(SomeClass::MemberFunction, [](SomeClass* self))`

==== FORCEINLINE Functions

Expand Down Expand Up @@ -279,4 +293,5 @@ public:
friend MyMod::MyWatcher;
...
}
----
5 changes: 3 additions & 2 deletions modules/ROOT/pages/Development/ModLoader/Logging.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,11 @@ which will be automatically created if it doesn't exist yet.

== Logging from {cpp}

Logging from {cpp} is usually accomplished via the `UE_LOG` macro.
Logging from {cpp} is usually accomplished via the `UE_LOG` macro,
or the new `UE_LOGFMT` macro introduced in Unreal Engine 5.2.

https://unrealcommunity.wiki/logging-lgpidy6i[This Unreal Engine community wiki page]
does a good job of explaining how to use the macro,
does a good job of explaining how to use the macros,
set up your own custom logging categories,
and the macro's formatting capabilities.

Expand Down
8 changes: 6 additions & 2 deletions modules/ROOT/pages/ForUsers/SatisfactoryModManager.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,12 @@ for the rest of the steps.
[id="Install_Linux"]
=== Linux

The latest Linux build of the mod manager can be downloaded from the
https://github.com/satisfactorymodding/SatisfactoryModManager/releases/latest/download/Satisfactory-Mod-Manager.AppImage[github releases page].
Linux builds of the mod manager can be found on the
https://github.com/satisfactorymodding/SatisfactoryModManager/releases[GitHub releases page].
You can directly download the latest release by clicking
https://github.com/satisfactorymodding/SatisfactoryModManager/releases/latest/download/Satisfactory-Mod-Manager.AppImage[this link].

`+webkit2gtk-4.0+` is required - if you don't have it yet, obtain it through your package manager of choice.

[id="Install_Winget"]
=== With Winget
Expand Down
83 changes: 65 additions & 18 deletions modules/ROOT/pages/faq.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,74 @@ Moving or reinstalling will not affect your save files.
It varies depending on the mod, but in general, yes, this is totally fine.
The mod should say on its mod page on ficsit.app if it can't be added to an in-progress game.

[id="MultiplayerSupport"]
== Do mods work with multiplayer?

It is up to the mod developer to support multiplayer.
Check the mod's page on ficsit.app for information about multiplayer support.
[id="MultiplayerSupport_ShortAnswer"]
=== Short Answer

Not all mods work with multiplayer, but most of them do.
It is up to the mod developer to communicate to you if their mod works in multiplayer.
Usually there will be text or an image on the mod's page on ficsit.app with information about multiplayer support.
If the mod page doesn't say yet, try it out yourself and see!

All players in multiplayer generally require the exact same mods installed to play together.
To share your mods with other players,
see link:#_how_do_i_share_my_mods_with_my_friends_for_multiplayer[this section].

As a general rule of thumb,
if the mod only adds recipes, items, or buildings that have no custom logic
(behave exactly like base-game ones with a new model, or for recipes that the mod adds)
then it usually works.

Sometimes a mod that is not coded correctly for multiplayer will still work just for the host player.
It's up to you to decide if that's good enough for your group.

[id="MultiplayerSupport_LongAnswer"]
=== Long Answer

There are two kinds of multiplayer in Satisfactory.
A mod may be compatible with both, one, or neither of them.

* **Host-and-Play**
** One game client runs the game for the host player and allows other players to connect
** Requires the mod to be coded with multiplayer functionality in mind, else _it will only work for the host player_
** The mod developer should have written something on the mod page telling you if the mod is multiplayer compatible or not
* **Dedicated Server**
** One server executable hosts allows others to connect
** Requires the mod to be coded with multiplayer functionality in mind, else _it will work for no one_ (since there is no longer a host player)
** The Mod Repository can tell you if a mod works for dedicated servers, see link:#DoModsWorkOnDedicatedServers[this section] for more info.
** If a mod works for dedicated servers, it usually also works for host-and-play

There are also three kinds of mods with respect to multiplayer:

* Both-sided mods
** The most common varaint
** This mod must be present on both the host and the clients to work
* Server-side mods
** This mod only needs to be present on the host side to work - clients do not need to have it installed
** Sometimes these mods only support dedicated servers - they will not function in host-and-play
* Client-side mods
** This mod only needs to be present on the client side to work - the host does not need to have it installed. However, the host having it installed may enable additional functionality for clients.

Assume that mods are both-sided unless explicitly stated otherwise by the mod page or dedicated server compatibility grid.

== How do I share my mods with my friends for multiplayer?

You can use the Mod Manager's profile import/export functionality.

image:FAQ/SmmImportExport.png[SMM Import/Export screenshot]

[id="DoModsWorkOnDedicatedServers"]
== Do mods work with dedicated servers?

_Or: How do I tell if a mod works on Dedicated Servers?_

In general, mods do work on dedicated servers, but exact support will vary depending on the mod.
See xref:ForUsers/DedicatedServerSetup.adoc[Installing Mods on Dedicated Servers] for more details.
The xref:ForUsers/DedicatedServerSetup.adoc#CheckModDedicatedServerSupport[Installing Mods section]
describes how to tell if an individual mod supports Dedicated Servers.

If the mod page doesn't say, try it out yourself and see!

== Are Satisfactory mods safe?

Expand Down Expand Up @@ -143,15 +205,6 @@ If you find a mod that is missing its stickers or ones that seem to be incorrect
please let us know in the Discord (including a SMM debug zip if it does not work is useful as well!)
and we will investigate and update the info if necessary.

== Do mods work with dedicated servers?

_Or: How do I tell if a mod works on Dedicated Servers?_

In general, mods do work on dedicated servers, but exact support will vary depending on the mod.
See xref:ForUsers/DedicatedServerSetup.adoc[Installing Mods on Dedicated Servers] for more details.
The xref:ForUsers/DedicatedServerSetup.adoc#CheckModDedicatedServerSupport[Installing Mods section]
describes how to tell if an individual mod supports Dedicated Servers.

== Satisfactory Mod Manager is open, but I can't see it's window!

The program's window somehow got offscreen.
Expand Down Expand Up @@ -187,12 +240,6 @@ Check out
xref:index.adoc#_for_developers[this section of the home page]
for more information.

== How do I share my mods with my friends for multiplayer?

You can use the Mod Manager's profile import/export functionality.

image:FAQ/SmmImportExport.png[SMM Import/Export screenshot]

== Where are my game files located?

[id="Files_GameInstall"]
Expand Down

0 comments on commit ce83cdc

Please sign in to comment.