[Solved] Help Getting Achievements to Work in Mac Builds

Started by TheVolumeRemote, Fri 14/06/2024 22:47:01

Previous topic - Next topic

TheVolumeRemote

Hi all! I'm struggling to get achievements to trigger during game play, only on my Mac build.

Can someone break down exactly what dylib files I need and where to put them and at what point in the build process do I put them there?

I'm using AGS2Client so it's jointed. I use cmake to build my Mac ports from the ags-master folder by putting my Data files in OSX > Resources. I rename the .ags file game.ags as standard practice and then terminal-at-folder:

Code: ags
export BUILD_TYPE=Release
mkdir build_$BUILD_TYPE
cd build_$BUILD_TYPE
cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE ..
make

Previously I'd next sign and staple it. But for achievements, after compiling w cmake, I now add to Contents/Resources:

steam_appid.txt (with my games App ID)
libsteam_api.dylib
libagsteam.dylib
libagsteam-unified.dylib

- I got libsteam_api.dylib from Steam's latest SDK and I got the other dylib's from monkies repo or git
- I'm signing the dylibs I've placed in Resources separately and before signing the entire app.
- Before cmake, when I have AGS compile the game, I have also placed the dylibs in my project folder's root and in _Debug folder.

From my own Steam library I see some games use agsteam.dylib instead of libagsteam.dylib. No idea why. Newer games such as Hob's Barrow and Old Skies Demo use libagsteam.dylib so that's what I'm using (I did try agsteam.dylib at some point)

Additionally, no other game on Steam uses "game.ags" as the exe, they use "ac2game.dat" so I began trying with my executable named as "ac2game.dat" which made no difference- it still compiles, runs and does not trigger achievements.

Lastly, I'll be building for GOG next so if anyone responding has done both, I'd also greatly appreciate the same info for Galaxy, what dylibs, where and at what point in the process do I put them there.

Thank you for any help :)

PS - @Dualnames if you're around I'd be super grateful for any pointers or tips, I think you recently ported Hob's?

TheVolumeRemote

#1
Edit: Removed unnecessary libagsshell.dylib from steps and helper script. cmake will now build a universal binary for Mac Intel & Silicon (thanks again to @edenwaith ). Download also updated with new helper script.

Edit 2: If you want to download this tutorial including how to compile your own Mac App Bundle and all needed files (except GOG API library for legal reasons) you can find step by step instructions for porting your AGS game to Mac and for preparing it for GOG Galaxy and Steam, with working Achievements, HERE

Got it working :-D Huge thanks to @edenwaith I wouldn't have gotten this without him. In hopes this helps somebody someday, here are the exact steps to follow and a download of the dylibs that worked for me because compiling my own and others I had tried didn't work. Note there are definitely superfluous steps in here but I'm not sure what isn't needed and I know it works as instructed.

Compile AGS Game for MacOS with Steam Achievements
--------------------------------------------------

In Windows:

- On the AGS side, before having AGS compile your game, place the .dylib files in you game's project folder, wherever you put the dll's. I put them in all the folders, my game's main project folder, the game's _Debug folder, the game's Compiled folder and in the main AGS folder.
- Compile the game within AGS
- In your game's project folder go to Compiled. You want the Data folder.

Switch to macOS:

Open Terminal, install Homebrew:

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

Install cmake:

Brew install cmake

Download AGS-Master from git hub, run:

git clone https://github.com/adventuregamestudio/ags.git

Open your game's Data folder and copy contents.

Open AGS-master, Go to OSX > Resources

Paste your game files there. Rename your GameTitle.ags to game.ags

Right/Control click on AGS-master folder

Select Services > New Terminal at Folder

Build .app, Run this:

Code: ags
export BUILD_TYPE=Release
mkdir build_$BUILD_TYPE
cd build_$BUILD_TYPE
cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_OSX_ARCHITECTURES="x86_64;arm64" ..
make

- This will build the executable `AGS.app` in `the build_Release/` directory within ags-master.
- Go there, Rename AGS.app to your game's name and move the .app to you computer's home directory (Finder bar > Go > Go to Folder, type: ~/

-To access contents of the app bundle, right click on it > show package contents.

1. Edit steam_appid.txt put your games App ID in and save it.

1b. Edit info.plist, change bundle ID to com.YourWebsite.YourGame

2. In your computers ~/ home directory place:

    - Your Game.app
    - prepare_app_bundle.sh
    - entitlements.plist

3. Right click Your Game.app > show package contents > Contents > MacOS.

In MacOS, place:

libsteam_api.dylib

3b. Right click Your Game.app > show package contents > Contents > Resources.

In Resources, place:
 
steam_appid.txt
libagsteam.dylib
libagsteam-unified.dylib
libsteam_api.dylib (yes, here as well)

Next, Rename game.ags to ac2game.dat

4. Open Terminal. Make .sh executable:

chmod +x prepare_app_bundle.sh

4b. Then run the signing script for dylibs and entitlment.plist:

./prepare_app_bundle.sh

5. Zip App for Notarization:

zip -r "Your Game.zip" "Your Game.app"

6. Head to https://appleid.apple.com and generate an "app specific password". Use it in the step below in place of xxxx-xxxx-xxxx-xxxx

6b. Submit for Notarization:

xcrun notarytool submit "Your Game.zip" --apple-id YourAppleIDicloud.com --password xxxx-xxxx-xxxx-xxxx --team-id XXXXXXXXXX --wait

7. Staple the Notarization Ticket:

xcrun stapler staple -v "Your Game.app"

7b. Verify Staple:

xcrun stapler validate "Your Game.app"

7c. You can now delete the .zip was made to notarize it.

8. Create a folder and place Your Game.app in it. Right click the folder, select new terminal at folder.

Run this to zip the .app and to remove Mac forks (like DS_Store)

zip -r Your\ Game.zip  . -x ".*" -x "__MACOSX"

----------------------------------------------------------------------

Make your own entitlements.plist:

Open TextEdit

Paste this:

Code: ags
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>com.apple.security.cs.disable-library-validation</key>
    <true/>
    <key>com.apple.security.cs.allow-dyld-environment-variables</key>
    <true/>
    <key>com.apple.security.network.client</key>
    <true/>
    <key>com.apple.security.cs.allow-jit</key>
    <true/>
    <key>com.apple.security.cs.allow-unsigned-executable-memory</key>
    <true/>
    <key>com.apple.security.cs.allow-executable-memory</key>
    <true/>
</dict>
</plist>
Rename file to entitlements.plist

Save, place in your home directory ~/

---------------------------------------------------------------------------------
Make your own prepare_app_bundle.sh:

Open TextEdit

Paste this, replacing 'Your Game' and 'Your Name' and (XXXXXXXXXX) with your game's name and your Apple Dev Team ID:

Code: ags
#!/bin/bash

# Define paths
APP_NAME="Your Game"
APP_DIR=~/Your\ Game.app
RESOURCES_DIR="${APP_DIR}/Contents/Resources"
MACOS_DIR="${APP_DIR}/Contents/MacOS"
ENTITLEMENTS_PLIST=~/entitlements.plist
CERTIFICATE="Developer ID Application: Your Name (XXXXXXXXXX)"
EXECUTABLE_NAME="ags"

# Update install_name for each .dylib in Resources
install_name_tool -id "@executable_path/../Resources/libagsteam.dylib" "${RESOURCES_DIR}/libagsteam.dylib"
install_name_tool -id "@executable_path/../Resources/libsteam_api.dylib" "${RESOURCES_DIR}/libsteam_api.dylib"
install_name_tool -id "@executable_path/../Resources/libagsteam-unified.dylib" "${RESOURCES_DIR}/libagsteam-unified.dylib"

install_name_tool -change "@loader_path/libagsteam.dylib" "@executable_path/../Resources/libagsteam.dylib" "${MACOS_DIR}/${EXECUTABLE_NAME}"
install_name_tool -change "@loader_path/libsteam_api.dylib" "@executable_path/../Resources/libsteam_api.dylib" "${MACOS_DIR}/${EXECUTABLE_NAME}"
install_name_tool -change "@loader_path/libagsteam-unified.dylib" "@executable_path/../Resources/libagsteam-unified.dylib" "${MACOS_DIR}/${EXECUTABLE_NAME}"

# Update install_name for libsteam_api.dylib in MacOS
install_name_tool -id "@executable_path/libsteam_api.dylib" "${MACOS_DIR}/libsteam_api.dylib"

# Code sign the .dylib files in Resources
codesign --force --options runtime --entitlements "$ENTITLEMENTS_PLIST" --sign "$CERTIFICATE" "${RESOURCES_DIR}/libagsteam.dylib"
codesign --force --options runtime --entitlements "$ENTITLEMENTS_PLIST" --sign "$CERTIFICATE" "${RESOURCES_DIR}/libsteam_api.dylib"
codesign --force --options runtime --entitlements "$ENTITLEMENTS_PLIST" --sign "$CERTIFICATE" "${RESOURCES_DIR}/libagsteam-unified.dylib"

# Code sign the additional libsteam_api.dylib in MacOS
codesign --force --options runtime --entitlements "$ENTITLEMENTS_PLIST" --sign "$CERTIFICATE" "${MACOS_DIR}/libsteam_api.dylib"

# Code sign the main executable
codesign --force --options runtime --entitlements "$ENTITLEMENTS_PLIST" --sign "$CERTIFICATE" "$MACOS_DIR/$EXECUTABLE_NAME"

# Code sign the entire app bundle
codesign --force --options runtime --deep --entitlements "$ENTITLEMENTS_PLIST" --sign "$CERTIFICATE" "$APP_DIR"

echo "App bundle signed successfully."


Rename file to prepare_app_bundle.sh

Save, place in your home directory ~/

------------------------------------------------------------------------------------

download dylibs, prepare_app_bundle.sh and entitlements.plist HERE


eri0o

Heads up to people using agsshell, you really should not be using it if possible as it has way too much surface for trouble. If you use it to open a browser please switch to agsappopenurl instead. If you use for other reasons, please write what you are using so a proper alternative can be written.

TheVolumeRemote

#3
Quote from: eri0o on Thu 20/06/2024 09:19:44Heads up to people using agsshell...

Edit: I updated my instructions with a new script and steps which excludes libagsshell.dylib and confirmed works :)

Thanks Eri0o, I probably don't need it but I couldnt find a single AGS game on Steam that wasn't using it and I got it in my head that it could help. And after 24 builds and dozens of hours on this the past 2 weeks, I didn't have it in me to start deducing what I didn't need and posted this guide so at least there's finally some documentation and instructions that will work for people.

After some time away from this I'll possibly try it without agsshell and assuming it still works I'll revise the tutorial :)

edenwaith

I think that @TheVolumeRemote's approach here includes the kitchen sink, now we need to scale down to figure out what is truly necessary while being able to preserve the Steam achievement functionality.

I still suspect that the only keys we need to enable in the entitlements.plist file are com.apple.security.cs.allow-dyld-environment-variables and com.apple.security.cs.disable-library-validation.  Those are the two keys I have often seen mentioned.  When I looked at Valve's Steam example (steamworksexample), those were also the two Hardened Runtime options selected (Allow DYLD Environment Variables and Disable Library Validation).

I'm doing some additional dividing into how the skeleton AGS app and executable are build and ensuring that they are properly built and linked against the Steam dylib.

edenwaith

For historical documentation purposes, I'm linking this thread to the newer Implementing Steam Achievements for Mac AGS Games post.  Both of these posts provide a lot of the insight, efforts, and pitfalls of getting Steam achievements to work on Mac AGS games in 2024.

Radiant

Thank you, that was insightful.

I'd like to add that you need to install a certificate per instructions here: https://developer.apple.com/help/account/create-certificates/create-developer-id-certificates
And also, that the steam_appid.txt file is not needed, and the Steam builder will tell you not to include it. I'd also think that using both libagsteam.dylib and libagsteam-unified.dylib is redundant. Including that is pretty harmless though. Turns out that the additional libsteam_api.dylib in MacOS is also not necessary.

My terminal is currently taking a looong time to process "xcrun notarytool". Got it to work.

Radiant

Well actually, notarytool ran over an hour so I decided to break it off and log out. I'll try again tomorrow, not sure what's up with that.

SMF spam blocked by CleanTalk