Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mod support #9

Closed
Fusion86 opened this issue Mar 30, 2023 · 18 comments
Closed

Mod support #9

Fusion86 opened this issue Mar 30, 2023 · 18 comments
Labels
help wanted Extra attention is needed question Further information is requested

Comments

@Fusion86
Copy link

I do feel a bit selfish for immediately asking for this, but I've been wondering whether it is possible to get mods working with this setup?
The official BepInEx site mentions that it is compatible with macOS, but I couldn't get it to work on the first try.

@timkurvers
Copy link
Owner

No worries! 🙌

The current Valheim + Steam integration works due to injection of SteamAppId into the environment when the app launches in Info.plist.

From a quick inspection it seems that the BepInEx script launches the MacOS/Valheim binary directly, which might mean that particular Steam setting is not taken into account.

Could you try running it as follows:

SteamAppId=892970 ./run_bepinex.sh

@timkurvers timkurvers added help wanted Extra attention is needed question Further information is requested labels Apr 5, 2023
@phonique
Copy link

phonique commented Apr 29, 2023

Hey, @Fusion86. Spent the evening yesterday myself getting BepInEx to work.
Here's the rundown.

  • Moved Valheim.app from build/ to it's own directory in /Applications/Games/Valheim/GAME
  • Downloaded BepInEx (BepInEx_unix_5.4.21.0.zip)
  • Unpacked it into GAME dir (i.e. the dir-structure is now: Valheim.app, BepInEx, doorstop_libs, run_bepinex.sh and changelog.txt)
  • Open a terminal in the GAME dir and make the .sh user-executable by typing chmod u+x run_bepinex.sh
  • [hours of trying to get it to work skipped for you]
  • Download the denikson BepInEx distribution for Valheim at thunderstore.io
  • unpack somewhere else and copy winhttp.dll, doostop_config.ini and (probably, most importantly) unstripped_corlib to the GAME dir. Also copy BepInEx/config (and why not BepInEx/plugins/Valheim.DisplayBepInExInfo.dll, while you're at it) to GAME/BepInEx/
    First part is done.

Now edit run_bepinex.sh in the GAME dir as follows:

  • after the # ---- EDIT AS NEEDED ------ line - add export SteamAppId=892970 as per @timkurvers comment above (thanks!)
  • change executable_name to executable_name="Valheim.app"
  • find the DOORSTOP_CORLIB_OVERRIDE_PATH and change it to "$BASEDIR/unstripped_corlib"
    (or copy the relevant part for it from here:)
# -------- SETTINGS --------
# ---- EDIT AS NEEDED ------

export SteamAppId=892970

# EDIT THIS: The name of the executable to run
# LINUX: This is the name of the Unity game executable 
# MACOS: This is the name of the game app folder, including the .app suffix
executable_name="Valheim.app"

# The rest is automatically handled by BepInEx

# Whether or not to enable Doorstop. Valid values: TRUE or FALSE
export DOORSTOP_ENABLE=TRUE

# What .NET assembly to execute. Valid value is a path to a .NET DLL that mono can execute.
export DOORSTOP_INVOKE_DLL_PATH="$BASEDIR/BepInEx/core/BepInEx.Preloader.dll"

# If specified, Doorstop will load core libraries from this folder instead of the normal Managed folder
# Mainly usable to unstrip assemblies in some games
export DOORSTOP_CORLIB_OVERRIDE_PATH="$BASEDIR/unstripped_corlib"

# ----- DO NOT EDIT FROM THIS LINE FORWARD  ------

To launch directly from steam:

  • Open steam and add a non-steam game.
  • Now, find Valheim.app (in my case it's inside: /Applications/Games/Valheim/GAME)
  • After you add the game, select the newly added Valheim in your steam library (it shouldn't have an icon), click the little cogwheel-settings button and select Properties....
  • There, edit Launch Options as follows:
    "/Applications/Games/Valheim/GAME/run_bepinex.sh" %command% --args -console"
    (You can skip the --args -console if you don't need the in-game console for some reason).

That's it.

You should now be able to start from steam and it should work.
In case it doesn't - try to launch from the terminal and post the output here: (i.e. open the terminal, go to the GAME dir and type in ./run_bepinex.sh).

PS: Oh, and @timkurvers: Thanks so much for making this happen! We'll enjoy the ride, while it lasts : )

@timkurvers
Copy link
Owner

Incredible write-up @phonique! Thanks for sharing 🥳

@fellnerse
Copy link

fellnerse commented Jul 21, 2023

Thanks @phonique for that detailed description! with that held I was able to make it even easier to work (in my case I wanted to use ValheimPlus, which already includes BepEx):

Just head to their release page and get the latest UnixClient.zip (for me it was 0.9.9.16) and put the content next to the Valheim.app folder.
The only thing you have to adapt now is the same as @phonique described:

edit the start_game_bepinex.sh:

...

# -------- SETTINGS --------
# ---- EDIT AS NEEDED ------
export SteamAppId=892970
# EDIT THIS: The name of the executable to run
# LINUX: This is the name of the Unity game executable 
# MACOS: This is the name of the game app folder, including the .app suffix
executable_name="Valheim.app"

...

export DOORSTOP_CORLIB_OVERRIDE_PATH="$BASEDIR/unstripped_corlib"

...

If you do not want ValheimPlus you can just delete the dll in the `BepInEx/plugins` folder

@lyk4ndna
Copy link

lyk4ndna commented Aug 7, 2023

This worked fantastic! Thank you! Was able to get Valheim+ (Grantapher Temp) and Advize PlantEverything installed and haven't had any issues so far.

@HankHill121
Copy link

HankHill121 commented Sep 10, 2023

I've followed the steps in this thread and have mods loading but some mods have a problem where their textures aren't loading and all the items or enemies they add are purple. For example monstrum mobs are purple but the odinshorse loads in just fine. Epicloot weapons are purple pillars when thrown. but odins campsites loads and works fine. There are no errors in the logs.

I've tested it on windows and all the mods are compatible with no issues.

Any help would be appreciated.

@timkurvers
Copy link
Owner

I've followed the steps in this thread and have mods loading but some mods have a problem where their textures aren't loading and all the items or enemies they add are purple. For example monstrum mobs are purple but the odinshorse loads in just fine. Epicloot weapons are purple pillars when thrown. but odins campsites loads and works fine. There are no errors in the logs.

I've tested it on windows and all the mods are compatible with no issues.

Any help would be appreciated.

It's possible the mods are using texture formats that are not supported by OpenGL for macOS (Apple deprecated it years ago, after all).

Anything in the Player.log about textures that could not be loaded?

@hvab hvab mentioned this issue Oct 7, 2023
6 tasks
@seathasky
Copy link

seathasky commented Nov 8, 2023

Great write up @phonique
Just chiming in about some recent changes:

image

Basically unstripped_corlibs is no longer needed. Tested this last night, and bepinex works.

For reference, this is what my shell file now looks like:

Screenshot_2023-11-08_at_1 37 48_PM

Have fun!

@seathasky
Copy link

seathasky commented Nov 9, 2023

LogOutput.log
Anyone able to get epicloot working? Bepin loads just fine, but plugins seem to not load in game. Doing same manual setup on pc works just fine.

Here's the error in the log:

[Error  : Unity Log] IOException: Operation not supported
Stack trace:
System.IO.CoreFX.FileSystemWatcher.StartRaisingEvents () (at <5fe808a9ce234d7cb9b1a4e14f988a80>:0)
System.IO.CoreFX.FileSystemWatcher.StartRaisingEventsIfNotDisposed () (at <5fe808a9ce234d7cb9b1a4e14f988a80>:0)
System.IO.CoreFX.FileSystemWatcher.set_EnableRaisingEvents (System.Boolean value) (at <5fe808a9ce234d7cb9b1a4e14f988a80>:0)
(wrapper remoting-invoke-with-check) System.IO.CoreFX.FileSystemWatcher.set_EnableRaisingEvents(bool)
System.IO.CoreFXFileSystemWatcherProxy+<>c.<StartDispatching>b__9_0 (System.IO.CoreFX.FileSystemWatcher internal_fsw, System.IO.FileSystemWatcher fsw) (at <5fe808a9ce234d7cb9b1a4e14f988a80>:0)
System.IO.CoreFXFileSystemWatcherProxy.Operation (System.Action`4[T1,T2,T3,T4] map_op, System.Action`2[T1,T2] object_op, System.Object handle, System.Action`2[T1,T2] cancel_op) (at <5fe808a9ce234d7cb9b1a4e14f988a80>:0)
Rethrow as InvalidOperationException: object_op
System.IO.CoreFXFileSystemWatcherProxy.Operation (System.Action`4[T1,T2,T3,T4] map_op, System.Action`2[T1,T2] object_op, System.Object handle, System.Action`2[T1,T2] cancel_op) (at <5fe808a9ce234d7cb9b1a4e14f988a80>:0)
System.IO.CoreFXFileSystemWatcherProxy.StartDispatching (System.Object handle) (at <5fe808a9ce234d7cb9b1a4e14f988a80>:0)
System.IO.FileSystemWatcher.Start () (at <5fe808a9ce234d7cb9b1a4e14f988a80>:0)
System.IO.FileSystemWatcher.set_EnableRaisingEvents (System.Boolean value) (at <5fe808a9ce234d7cb9b1a4e14f988a80>:0)
(wrapper remoting-invoke-with-check) System.IO.FileSystemWatcher.set_EnableRaisingEvents(bool)
EpicLoot.EpicLoot.LoadJsonFile[T] (System.String filename, System.Action`1[T] onFileLoad, EpicLoot.Data.ConfigType configType, System.Boolean update) (at <c085ade0925d42a7910d0d32c1396d5c>:0)
EpicLoot.EpicLoot.InitializeConfig () (at <c085ade0925d42a7910d0d32c1396d5c>:0)
EpicLoot.EpicLoot.Awake () (at <c085ade0925d42a7910d0d32c1396d5c>:0)
UnityEngine.GameObject:AddComponent(Type)
BepInEx.Bootstrap.Chainloader:Start()
UnityEngine.UI.Graphic:get_canvas()
TMPro.TextMeshProUGUI:OnCanvasHierarchyChanged()

@timkurvers
Copy link
Owner

timkurvers commented Nov 10, 2023

@seathasky Judging from Mono's FileSystemWatcher code, it should be possible to swap to a different watcher (seems to default to CoreFX on macOS?) by setting environment variable MONO_MANAGED_WATCHER to something (e.g. false) or disabled.

@seathasky
Copy link

seathasky commented Nov 10, 2023

@seathasky Judging from Mono's FileSystemWatcher code, it should be possible to swap to a different watcher (seems to default to CoreFX on macOS?) by setting environment variable MONO_MANAGED_WATCHER to something (e.g. false) or disabled.

This did it! Thank you!!

For those having similar issues to mods, add export MONO_MANAGED_WATCHER=FALSE to you run shell.

Screenshot 2023-11-09 at 11 56 37 PM

epic loot working:

Screenshot 2023-11-09 at 11 59 16 PM

@timkurvers thanks again

@Alanko5 Alanko5 mentioned this issue Mar 8, 2024
@karim090
Copy link

karim090 commented Apr 6, 2024

Hey, @Fusion86. Spent the evening yesterday myself getting BepInEx to work. Here's the rundown.

* Moved Valheim.app from build/ to it's own directory in `/Applications/Games/Valheim/GAME`

* Downloaded [BepInEx](https://github.com/BepInEx/BepInEx/releases/tag/v5.4.21) (BepInEx_unix_5.4.21.0.zip)

* Unpacked it into `GAME` dir (i.e. the dir-structure is now: `Valheim.app`, `BepInEx`, `doorstop_libs`, `run_bepinex.sh` and `changelog.txt`)

* Open a terminal in the `GAME` dir and make the .sh user-executable by typing `chmod u+x run_bepinex.sh`

* [hours of trying to get it to work skipped for you]

* Download the denikson BepInEx distribution for Valheim at [thunderstore.io](https://valheim.thunderstore.io/package/denikson/BepInExPack_Valheim/)

* unpack somewhere else and copy `winhttp.dll`, `doostop_config.ini` and (probably, most importantly) `unstripped_corlib` to the `GAME` dir. Also copy `BepInEx/config` (and why not `BepInEx/plugins/Valheim.DisplayBepInExInfo.dll`, while you're at it) to `GAME/BepInEx/`
  First part is done.

Now edit run_bepinex.sh in the GAME dir as follows:

* after the `# ---- EDIT AS NEEDED ------` line - add `export SteamAppId=892970` as per @timkurvers comment above (thanks!)

* change `executable_name` to `executable_name="Valheim.app"`

* find the `DOORSTOP_CORLIB_OVERRIDE_PATH` and change it to `"$BASEDIR/unstripped_corlib"`
  (or copy the relevant part for it from here:)
# -------- SETTINGS --------
# ---- EDIT AS NEEDED ------

export SteamAppId=892970

# EDIT THIS: The name of the executable to run
# LINUX: This is the name of the Unity game executable 
# MACOS: This is the name of the game app folder, including the .app suffix
executable_name="Valheim.app"

# The rest is automatically handled by BepInEx

# Whether or not to enable Doorstop. Valid values: TRUE or FALSE
export DOORSTOP_ENABLE=TRUE

# What .NET assembly to execute. Valid value is a path to a .NET DLL that mono can execute.
export DOORSTOP_INVOKE_DLL_PATH="$BASEDIR/BepInEx/core/BepInEx.Preloader.dll"

# If specified, Doorstop will load core libraries from this folder instead of the normal Managed folder
# Mainly usable to unstrip assemblies in some games
export DOORSTOP_CORLIB_OVERRIDE_PATH="$BASEDIR/unstripped_corlib"

# ----- DO NOT EDIT FROM THIS LINE FORWARD  ------

To launch directly from steam:

* Open steam and add a non-steam game.

* Now, find `Valheim.app` (in my case it's inside: `/Applications/Games/Valheim/GAME`)

* After you add the game, select the newly added Valheim in your steam library (it shouldn't have an icon), click the little cogwheel-settings button and select `Properties...`.

* There, edit `Launch Options` as follows:
  `"/Applications/Games/Valheim/GAME/run_bepinex.sh" %command% --args -console"`
  (You can skip the --args -console if you don't need the in-game console for some reason).

That's it.

You should now be able to start from steam and it should work. In case it doesn't - try to launch from the terminal and post the output here: (i.e. open the terminal, go to the GAME dir and type in ./run_bepinex.sh).

PS: Oh, and @timkurvers: Thanks so much for making this happen! We'll enjoy the ride, while it lasts : )

got it working, thanks a lot.

but now must comment DOORSTOP_CORLIB_OVERRIDE_PATH asignation, now that lib is into Valheim i think

@drummercraig
Copy link

Thank you @timkurvers for all you've done. I'm new to Mac but got this going thanks to you. Additionally I want to thank @phonique and @seathasky for the details with getting mods to work...which I have. The only thing that doesn't work for me is launching the external app in Steam. I put in the console options "/Applications/Games/Valheim/GAME/run_bepinex.sh" %command% --args -console" but it throws an unknown error. If I remove %command% it launches but no bepinex or mods are enabled. Currently I can only run mods by using @phonique 's terminal instructions: ./run_bepinex.sh

If anyone has any suggestions to get it working from the external Steam app method I would be most grateful.

@p2im0
Copy link

p2im0 commented Jun 4, 2024

@drummercraig - can you share any details on what mod you were using and how you got it runnning? It looks like BepInEx had it's config files rearchitected at some point as the config files look completely different than this thread.

I'm trying to play ValheimPlus and when I update the game path and try to launch using the start_game_bepinex.sh script I get an error:
./start_game_bepinex.sh: line 86: /gamepath/GAME/Valheim.app: is a directory

I've tried to update the config to point to the exectuable at Valheim.app/Contents/MacOS/Valheim and the game launches but BepInEx is not injected and its not running ValheimPlus.

Example of the current config file:

# Resolve base directory relative to this script
# Hopefully this resolves relative paths and links
a="/$0"; a=${a%/*}; a=${a#/}; a=${a:-.}; BASEDIR=$(cd "$a"; pwd -P)

# Special case: program is launched via Steam
# In that case rerun the script via their bootstrapper to ensure Steam overlay works
if [ "$2" = "SteamLaunch" ]; then
    cmd="$1 $2 $3 $4 $0"
    shift 4
    exec $cmd $@
    exit
fi

exec="$BASEDIR/Valheim.app"

export DOORSTOP_ENABLE=TRUE
export DOORSTOP_INVOKE_DLL_PATH="$BASEDIR/BepInEx/core/BepInEx.Preloader.dll"
export DOORSTOP_CORLIB_OVERRIDE_PATH="$BASEDIR/unstripped_corlib"
export SteamAppId=892970

# Allow to specify --doorstop-enable true|false
# Everything else is passed as-is to `exec`
while :; do
    case $1 in

To answer your question - I was able to get (the base game) running via steam by following some of the steps here.

EDIT: while I was working on getting this running Valhiem announced an official MacOS Port earlier today on Twitter!!

@drummercraig
Copy link

Totally appreciate you asking. I have learned to just use the command line to launch and don't need to launch with Steam and am happy with that. A friend told me today about the official MacOS coming on the 10th I think? Awesome.

@drummercraig
Copy link

drummercraig commented Jun 6, 2024

Sorry, I think my earlier response didn't answer a question you asked. I run it on an M1 Mac Studio and have never got the Steam launch to work. I do currently run 13 mods with my install. I also never got the start_game_bepinex.sh to work. So to try and clarify, I built the Valheim app using Tim's instructions. I then created a new separate folder (name it what you want) to be my Valheim game folder and copied the single Valheim.app file previously built. Then I manually downloaded from thunderstore the specific Valheim Bepinex and copied the Bepinex folder into my new folder and added the mods into the plugin folder within. I have a separate run_bepinex.sh file that I got from somewhere in here that I use to launch the game via command line. I have copied the contents below. I hope that helps and if you need any other details just ask. Sorry about the comment formatting below...this page just does it, changing font, removing the # etc and I don't know how to not have it change anything.

#!/bin/sh

BepInEx running script

This script is used to run a Unity game with BepInEx enabled.

Usage: Configure the script below and simply run this script when you want to run your game modded.

a="/$0"; a=${a%/*}; a=${a#/}; a=${a:-.}; BASEDIR=$(cd "$a"; pwd -P)

-------- SETTINGS --------

---- EDIT AS NEEDED ------

export SteamAppId=892970

EDIT THIS: The name of the executable to run

LINUX: This is the name of the Unity game executable

MACOS: This is the name of the game app folder, including the .app suffix

executable_name="Valheim.app"

The rest is automatically handled by BepInEx

Whether or not to enable Doorstop. Valid values: TRUE or FALSE

export DOORSTOP_ENABLE=TRUE

What .NET assembly to execute. Valid value is a path to a .NET DLL that mono can execute.

export DOORSTOP_INVOKE_DLL_PATH="$BASEDIR/BepInEx/core/BepInEx.Preloader.dll"

If specified, Doorstop will load core libraries from this folder instead of the normal Managed folder

Mainly usable to unstrip assemblies in some games

export DOORSTOP_CORLIB_OVERRIDE_PATH=""

----- DO NOT EDIT FROM THIS LINE FORWARD ------

----- (unless you know what you're doing) ------

Special case: program is launched via Steam

In that case rerun the script via their bootstrapper to ensure Steam overlay works

if [ "$2" = "SteamLaunch" ]; then
"$1" "$2" "$3" "$4" "$0" "$5"
exit
fi

if [ ! -x "$1" -a ! -x "$executable_name" ]; then
echo "Please open run.sh in a text editor and configure executable name."
exit 1
fi

doorstop_libs="$BASEDIR/doorstop_libs"
arch=""
executable_path=""
lib_postfix=""

os_type=$(uname -s)
case $os_type in
Linux*)
executable_path="$BASEDIR/${executable_name}"
lib_postfix="so"
;;
Darwin*)
executable_name=$(basename "${executable_name}" .app)
real_executable_name=$(defaults read "$BASEDIR/${executable_name}.app/Contents/Info" CFBundleExecutable)
executable_path="$BASEDIR/${executable_name}.app/Contents/MacOS/${real_executable_name}"
lib_postfix="dylib"
;;
*)
echo "Cannot identify OS (got $(uname -s))!"
echo "Please create an issue at https://github.com/BepInEx/BepInEx/issues."
exit 1
;;
esac

Special case: if there is an arg, use that as executable path

Linux: arg is path to the executable

MacOS: arg is path to the .app folder which we need to resolve to the exectuable

if [ -n "$1" ]; then
case $os_type in
Linux*)
executable_path="$1"
;;
Darwin*)
# Special case: allow to specify path to the executable within .app
full_path_part=$(echo "$1" | grep ".app/Contents/MacOS")
if [ -z "$full_path_part" ]; then
executable_name=$(basename "$1" .app)
real_executable_name=$(defaults read "$1/Contents/Info" CFBundleExecutable)
executable_path="$1/Contents/MacOS/${real_executable_name}"
else
executable_path="$1"
fi
;;
esac
fi

abs_path() {
echo "$(cd "$(dirname "$1")" && pwd)/$(basename "$1")"
}

_readlink() {
# relative links with readlink (without -f) do not preserve the path info
ab_path="$(abs_path "$1")"
link="$(readlink "${ab_path}")"
case $link in
/*);;
*) link="$(dirname "$ab_path")/$link";;
esac
echo "$link"
}

resolve_executable_path () {
e_path="$(abs_path "$1")"

while [ -L "${e_path}" ]; do 
    e_path=$(_readlink "${e_path}");
done
echo "${e_path}"

}

executable_path=$(resolve_executable_path "${executable_path}")
echo "${executable_path}"
executable_type=$(LD_PRELOAD="" file -b "${executable_path}");

case $executable_type in
PE32)
echo "The executable is a Windows executable file. You must use Wine/Proton and BepInEx for Windows with this executable."
echo "Uninstall BepInEx for *nix and install BepInEx for Windows instead."
echo "More info: https://docs.bepinex.dev/articles/advanced/steam_interop.html#protonwine"
exit 1
;;
64-bit)
arch="x64"
;;
32-bit|i386)
arch="x86"
;;
*)
echo "Cannot identify executable type (got ${executable_type})!"
echo "Please create an issue at https://github.com/BepInEx/BepInEx/issues."
exit 1
;;
esac

doorstop_libname=libdoorstop_${arch}.${lib_postfix}
export LD_LIBRARY_PATH="${doorstop_libs}":${LD_LIBRARY_PATH}
export LD_PRELOAD=$doorstop_libname:$LD_PRELOAD
export DYLD_LIBRARY_PATH="${doorstop_libs}"
export DYLD_INSERT_LIBRARIES="${doorstop_libs}/$doorstop_libname"

"${executable_path}"

@p2im0
Copy link

p2im0 commented Jun 8, 2024

@drummercraig - thank you! Could you try pasting the old run_bepinx.sh script here again - try using triple tilde's before and after the script and it should format the whole thing correctly as a code block. I'm tying to make it work but some of the code was reformatted from not being in a code-block.

I think that's the issue - the newer .sh included with the later versions of Bepinx refuse to launch the .app file and are detecting it as a folder.

EDIT: nevermind - the older releases are still available - I pulled down the start script from there. Thank you!

@timkurvers
Copy link
Owner

Closing this issue as the official macOS client is now available! 🥳 (see #104)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Extra attention is needed question Further information is requested
Projects
None yet
Development

No branches or pull requests

10 participants