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

Game Extension Creation with Harmony #12

Open
IDCs opened this issue Nov 3, 2020 · 0 comments
Open

Game Extension Creation with Harmony #12

IDCs opened this issue Nov 3, 2020 · 0 comments
Labels
Article Harmony Patcher Anything tied to Vortex's Harmony Patcher API Tutorial

Comments

@IDCs
Copy link
Contributor

IDCs commented Nov 3, 2020

Vortex extensions can import/require the “harmony-patcher” module as you do with any other JS module. The module currently exports several functions:

  • “runPatcher” which is used to start up the patcher executable and patch the targeted game assembly

  • “addLoadOrderPage” Which as the name suggests, will add a "Load Order" for the user to organize his mods

  • “raiseConsentDialog” a pre-defined, dialog which can be used to inform users that their game needs to be patched, and give them a chance to cancel the patching mechanism. (Should not be used with the "harmonypatchmod" modtype, more on that below)

The image below shows how to add the runPatcher function to your game extension. Please note we’re also defining a set of constants which we expect to use with the patcher, in this case we’re modding the “Untitled Goose Game”.

runPatcher(...)

The runPatcher function expects up to 8 arguments:

  • The extension’s folder (extensionPath: string)
  • Path to the game assembly’s file (dataPath: string)
  • The entry point; the patcher function call will be injected right at the start of the provided method. (Must respect the ‘Namespace.Classname::Method’ format) (entryPoint: string)
  • Boolean which tells the patcher executable whether we want to remove or inject the patch functions (remove: boolean)

All below arguments are optional and only available when using Vortex 1.2.0 and above

  • (Optional) The mods path; when omitted the mods folder will be generated alongside the game's assembly "VortexMods" by default. Alternatively game extensions can define a custom mods path as long as it is within the game's root folder e.g. "../UntitledGoose/Mods". (modsPath: string)
  • (Optional) Vortex's extension context object - used to raise error notifications within Vortex's UI. These will be logged inside vortex.log when the API object is omitted. (context: IExtensionContext)
  • (Optional) Vortex's In-Game Overlay component (VIGO) will deploy by default unless the game extension opts out (injectVIGO: boolean)
  • (Optional) (VIGO/Unity3D specific) - Some game assemblies we wish to patch might be located in a different directory from the UnityEngine libraries. In this case if we wish to build VIGO, the final argument allows us to tell the patcher where the UnityEngine libraries are located (This is primarily used by the harmonypatchermod mod type) (unityEngineDir: string)

In the case of “Untitled Goose Game” (UGG) we call the runPatcher function during our extension’s setup step which will attempt to patch the game assembly every time UGG game mode is activated inside Vortex; this is fine as the patcher will identify whether the game has already been patched and will not re-inject if the patch is present.

Choosing an entry-point for your game extension may be tricky and will differ between games but here are a few guidelines:

Most game developers usually follow the singleton design pattern for things like Game Managers, Audio Managers, Animation Managers or even UI Managers; the primary aim is to find a class/object which is instantiated once at the beginning of the game, and hopefully persists throughout the game’s life cycle; that being said, avoid choosing methods which are invoked more than once - the patch call should only execute once.

If the game is created using the Unity3D game engine, there’s a very good chance that the singletons are MonoBehaviour derived which means that the “Awake” and “Start” functions are perfect to inject the patch into.

addLoadOrderPage(...)

If mod load ordering is required, the patcher module can register and create a load order page where game extension users can organize their mods. To use this simply import the function from the harmony-patcher module and call it immediately after registering the game extension.

The function expects up to 7 arguments:

  • The extension context object which is passed to the game extension upon initialization (context: IExtensionContext)
  • The Nexus Mods game id. (gameId: string)
  • Information that the user may consider important, this will be displayed in a different panel next to the mods. (loadOrderInfo: string)
  • The path to the game's default gameart/logo.
  • (optional) The preSort functor allows game extensions to intervene right before the load order table applies its sort functionality and displays the mods to the user. It can be used to add/modify/remove mod display entries from the table, this is helpful if for example a certain mod entry must always be locked to a certain table position due to a game specific reason.
  • (optional) The filter functor allows the game extension to filter out unwanted mod entries entirely - for example we do not want to include mod entries of a certain mod type (harmonypatchermod mod type is ignored by default)
  • (optional) The callback functor is called whenever a change has been made to the load order itself - it allows game extensions to react to the change immediately. This is useful when the game extension needs to run game specific logic such as writing the new load order to a file. Please note: Currently the load_order.txt file (used by the Vortex mod loader) will be written to automatically upon any load order change - there is no need to do this yourself.

The "Load order" tab will appear in the navigation panel alongside "Mods" as seen in the screenshot above. Clicking the tab will open the page.

raiseConsentDialog(...)

This function can be used to inform the user that his game assemblies require patching and ask him to give consent prior to allowing the patcher to execute. It expects two arguments:

  • The extension context object which should be passed from the game extension.
  • The Nexus Mods game id/domain name.
  • (Optional) default text for the dialog is provided by default - but if needed, the extension writer is able to provide custom text instead.

The usage example below will ensure that the consent dialog appears before we even create the modding directory. Responding negatively to the consent dialog will not allow the user to proceed, and will deactivate the game extension.

The reversal text depends on patch method.

Automated patch application and removal (Vortex 1.2.0 and above)

A new patching mechanism has been added for Vortex 1.2.0 and above which will provide a simpler patching methodology. To use this method, a "harmonyPatchDetails" object needs to be defined when registering the game extension, providing the dataPath (path to game assembly), entry point, mods path and finally specifying whether VIGO is required.

When using this method, the patch functions will be added/removed upon every deploy/purge event. Additionally, This will create a new "Vortex Harmony Mod" which will contain a patched copy of the original game assembly, alongside any other assemblies which are required by the patch inside Vortex's staging folder. This ensures that the user has full control of the patch's status as he is able to enable/disable this as he does with any mod.

@IDCs IDCs added Article Tutorial Harmony Patcher Anything tied to Vortex's Harmony Patcher API labels Nov 3, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Article Harmony Patcher Anything tied to Vortex's Harmony Patcher API Tutorial
Projects
None yet
Development

No branches or pull requests

1 participant