SMAPI - Stardew Modding API

SMAPI - Stardew Modding API

971k Downloads

SMAPI on other platforms

Pathoschild opened this issue · 18 comments

commented

SMAPI officially runs on Linux, macOS, Windows, and Steam Deck (see player guide).

I don't plan to port it to mobile/consoles myself, but I'm happy to provide any help needed if someone familiar with those wants to figure it out.

Current status:

group platform status
PC Linux fully supported.
macOS fully supported.
Windows fully supported.
Mobile Android unofficial support, many mods compatible.
iOS ☐ no current support.
Console PS4 ☐ no current support.
PS Vita ☐ no current support.
Steam Deck supported, equivalent to Linux. May increase power usage.
Switch ☐ no current support.
Xbox One ☐ no current support.
commented

Brief introduction

I'm new to Stardew Valley modding, but in no way new to modding C# games in general (having worked on tConfig, a modding API for Terraria 1.1.x and being one of the main developers of tAPI, a modding API for Terraria 1.2.x; also dabbling in some tModLoader modding for Terraria 1.3+).

I've been an iOS developer for several years now, both commercially and as a hobby.

I also do a lot of Kotlin/Java work, which would normally be unrelated, but I'll get to it later below.

iOS/iPadOS support

TL;DR: It's possible, but we will most likely lose all mods we already have.

I'll just call it "iOS" from now on, it's literally the same thing, I don't get why Apple had to split those names...

The iOS port of Stardew Valley is built using Xamarin. So is the Android port, I believe. Disclaimer: I've never worked with Xamarin myself, all I'm saying is reading research and conjecture.

Xamarin has two ways of compiling your CIL into something applicable for its platforms:

  1. JIT, or "just in time",
  2. AOT, or "ahead of time".

By default, the Android builds use JIT, but they can also use AOT if preferred. Unfortunately, Apple does not allow code compilation to be done on their iOS devices, nor dynamically loading from an external resource -- all code has to be precompiled and included in the app before submitting to the App Store. Interpreting code may sometimes be allowed, but is usually frowned upon. So, the iOS port uses the AOT method.

Harmony

SMAPI uses Harmony (or MonoMod RuntimeDetour for the unofficial Android port) for hooking into the methods in the game, via IL editing. Unfortunately, IL is not a thing in AOT builds -- at this point we're way past that.

To achieve similar results, one could engineer a process in which the IL gets modified before it gets AOT compiled... but that requires actual source code for the iOS port. More details in a section below.

Editing assemblies before compilation

Harmony is a runtime hooking framework. It doesn't have the capability to edit an assembly and save it back to a file for later use. This is a problem, because this is something we need to make an iOS port possible.

Switching to using MonoMod could be a way out, as if I'm not mistaken it has the capability to hook both at runtime AND to edit assemblies and write modified ones to disk, but that comes at a cost...

All mods nowadays use Harmony. I don't know how compatible the APIs for Harmony and MonoMod are (@0x0ade would probably be able to answer that) and whether it would be possible to do some automatic code rewriting, but if they aren't... All of the current mods would have to be deprecated and rewritten to use a new hooking framework, which I believe is too big of a cost -- there are hundreds (thousands?) of SMAPI mods out there. Sure, some would port over... but a lot of them would be abandoned for good. It's also likely the community would also split into two -- one using the Harmony SMAPI, the other using MonoMod SMAPI.

Obtaining the source code

There are two ways iOS source code could be obtained.

1. Just... ask the developers

I don't see this happening, but you never know. The community could just... ask the developers.

The source code itself is not enough to play the game. You still need to obtain all of its content. This means piracy shouldn't be much of a concern.

There may be some legal problems. I'm in no way a lawyer, but sharing the source code may make it so ConcernedApe & co. could no longer do anything if someone were to steal the code and publish their own game (I may be completely in the wrong here, please tell me so if I am).

2. Decompiling the Android port

Because the Android build doesn't AOT compile the code, we can just extract it. This would give us a mobile Stardew Valley to work with, but there's still a lot to do. Android and iOS are two different beasts. OS-specific things would need to be reimplemented for iOS. I didn't think too much about it, but keyboard input and safe area (notch, home screen indicator) handling come to mind, not to mention just getting the thing to compile and work without problems game-engine-wise.

As we cannot just share this extracted/decompiled code, the user would have to acquire an APK file for the Android version by himself, but I don't think you can get APKs directly from the Google Play Store in a legal way, so unfortunately that would basically be piracy on the user's part.

At this point, a tool could be written which would take an Android APK, extract it, patch the assembly IL with iOS-specific changes (or decompile the assemblies, patch the C# code with iOS-specific changes and recompile it back to assemblies), patch those assemblies with the mods of the user's choosing and finally compile the whole thing back into an iOS app. Changing the mod list would require running this process again. Some of those steps could be cached between re-runs, so further changing of mods would be much faster.

Also... you know... this is just hilarious that you would need an Android version of the game to install mods on your iPhone.

Reflection

There were some concerns, that due to the AOT nature of iOS builds reflection would no longer be something that could be used in mods. Here comes the part where my Java world knowledge gets useful!

Back in the day I used to do some cross-platform Java game development, with the libGDX library. The desktop and Android platforms aren't anything special, but... The iOS build used a tool called RoboVM, which is very similar to what Xamarin AOT compiling does. It finds all of the types used by your project and compiles all of them as native code. It also supports reflection. Any code that is directly referenced will work right away, but if any type is only used at runtime (for example via Class.forName("com.example.MyClass")), you would need to specify it in RoboVM's configuration file.

Xamarin AOT does support System.Reflection. I may be completely in the wrong here, but I don't see why Xamarin would be any different from RoboVM, it's a no-brainer to allow specifying types to compile manually, but I can't find any information regarding that. The only unsupported part in Xamarin AOT is System.Reflection.Emit -- no code can be generated at runtime, but we wouldn't need that.

Source: https://docs.microsoft.com/en-us/xamarin/ios/internals/limitations

Building the game

To build any iOS app, you need to use a Mac(Book) (well, technically, macOS -- hackintoshing is a thing). So, anyone who would like to install modded Stardew on their iOS devices would also need to have access to a macOS device.

...or they could get a pre-modded built IPA from the internet. Hopefully this does not turn into people installing malicious apps on their iPhones...

Signing the build

To actually run the game on your own iOS device, you need to either download it from the App Store (which is a no-go here) or sign it for your own device.

Signing for yourself

Recently (2-3 years ago? I can't remember) Apple made it so you can develop iOS apps for free. Apps signed with free developer accounts are valid for 7 days, after which you have to sign them and install them again. An app built with a paid developer account ($99/year) are valid for 1 year.

Alternatively, if the iOS device is jailbroken, the AppSync tweak can be installed which allows installing any IPA, without the need of signing it.

A tool like Cydia Impactor can be used to sign an IPA for your own device. Impactor works on Windows, Linux and macOS, so if you already have a pre-modded IPA, you no longer need a Mac to install it on your iPhone/iPad.

Enterprise signing

Apple also offers enterprise certificates and provisioning profiles, which don't require the actual device to be specified. There are (were?) (paid) web services out there, which allowed you to upload any IPA and they would sign it for you with their enterprise profile. With such a signed IPA, you could install it on any device.

Benefits for other platforms

Switching to generating patched assemblies could also have the benefit of speeding up the game startup process, as patching would only need to be done whenever any mods are changed. Just today I've seen someone say they're using 800+ mods at once (JESUS, BUT WHY) and they've already been waiting for 11 minutes and it still didn't launch. I don't know about you, but 11 minutes to launch a game, only to play it for an hour (no, actually 49 minutes, you lost the 11 minutes there) would certainly not make me want to play the game anymore.

commented

hi. so a few months ago i wanted try this so i made an smapi-looking app that imports mod to your real game not to make another game. but i had no idea that how much the base code is different. and the app was running on my pc not on my other i phone. so i just wanted to say. you are a genius pathoschild.

commented

Looks like there's another person working on SMAPI for Android.
Guess wiki need to be updated(?)

SMAPI Loader by NRTnarathip

commented

I'm working on supporting Xbox One since a few days. It's currently all experimental and reading/debugging a lots of stufft, but I'm willing to implement that until the end of 2019.

commented

Android support is currently in the early stages of development. Further work won't be ready until I have time available.

commented

@ZaneYork is also working on experimental Android support in #635.

commented

Also taking a swing at Android. Still very early.

commented

Update on Progress: Found a way to run SMAPI on Android devices without touching the main StardewValley.dll. Currently sifting through SMAPI exceptions.

commented

YAU(Yet Another Update): Commited source code for the project. Working on an installer. Now I have to look into making Harmony work (thanks @0x0ade)

commented

Basic Harmony functionality can now be restored on Android without a fork of Harmony, by making use of MonoMod.RuntimeDetour as a replacement detouring backend.

Running HarmonyDetourBridge.Init(); before using Harmony patches it in memory to use RuntimeDetour instead of its own ASM jumps, while also applying a few other changes for compatibility. RD itself supports x86, x64 and ARM.

This is still experimental, currently part of a separate MonoMod branch (rd-harmonybridge) and has yet to be tested in the real world (user mods).

commented

The HarmonyDetourBridge is now stable enough that some mods using Harmony are now working on Android. This has yet to be tested further though - who knows what weird edge cases are going to pop up.

Thanks to @MartyrPher for testing anything I threw at him and quickly reporting back afterwards, and for testing the mods themselves!

commented

@ZaneYork Thanks! I'll update the documentation. Is this still a separate fork, or a continuation of MartyrPher's fork now?

commented

@ZaneYork Thanks! I'll update the documentation. Is this still a separate fork, or a continuation of MartyrPher's fork now?

Installer project is a separately fork, using same patch logic(a little improvement), but all code was rewrote.
SMAPI project is a continuation of MartyrPher's fork, forked from his 3.2 update.

commented

@ZaneYork I updated the install guide on the wiki, and updated the summary here to link to that. Let me know if anything is incorrect, or feel free to edit the page!

commented

I made a new SMAPI Installer for Android at here.Provides environment check feature and config editor(with JSON format check), launch button in Installer can check whether the mod's dependencies is satisfied or not.Also released to Play Store

commented

Latest Update: I have released an experimental prototype found on my "SMAPI-Android-Installer" GitHub. Which can be found here. There is more info on that release page. Also, there is a little more to do regarding debris and other things before it hits 1.0. Cheers!

commented

hey so If anyone is interested in looking into Ps4 Smapi development I have a jailbroken ps4, access to the decrypted rom and a file redirector tool to test modded files on my ps4. Let me know if anyone’s looking to try to develop on ps4!

commented

It looks like @ZaneYork stopped updating their fork and responding to support requests in June, so currently @MartyrPher's fork seems to be the de facto version for Android.