Single-file mods#

While pyMHF is designed to be used to create libraries upon which mods can be made, for smaller scale projects or small tests, this is not convenient. To accomodate this, pyMHF can run a single file containing a mod.

This file MAY have the following attributes defined in it to simplify the defintions:

__pymhf_func_binary__ (str)

The name of the binary all the function offsets/patterns are to be found relative to/in. If provided this will be the default for all functions, however any manual_hook with a different value provided will supersede this value.

__pymhf_func_offsets__ (dict[str, Union[int, dict[str, int]]])

A lookup containing the function names and offsets. Generally the keys will be the function names that you want to call the function by, and the values will simply be the offset relative to the start of the binary. For overloads the value can be another dictionary with keys being some identifier for the overload (eg. the argument types), and the values being the offsets.

__pymhf_func_call_sigs__ (dict[str, Union[FUNCDEF, dict[str, FUNCDEF]]])

A lookup containing the function names and function call signatures. The keys will be the function names that you want to call the function by, and the values will either be the FUNCDEF itself, or a dictionary similar to the __pymhf_func_offsets__ mapping.

__pymhf_func_patterns__ (dict[str, Union[str, dict[str, str]]])

A lookup containing the function names and byte patterns to find the functions at. The keys will be the function names that you want to call the function by, and the values will be either a string containing the pattern, or a dictionary similar to the __pymhf_func_offsets__ mapping.

Note that none of these are mandatory, however they do simplify the code in the file a decent amount and keep the file more easy to maintain.

Below is an example single-file mod for the game No Man’s Sky:

example_mod.py#
# /// script
# dependencies = ["pymhf"]
#
# [tool.pymhf]
# exe = "NMS.exe"
# steam_gameid = 275850
# start_paused = false
#
# [tool.pymhf.logging]
# log_dir = "."
# log_level = "info"
# window_name_override = "NMS test mod"
# ///

from logging import getLogger

from pymhf import Mod, load_mod_file
from pymhf.core.hooking import on_key_pressed

logger = getLogger("testmod")


class MyMod(Mod):
    @on_key_pressed("p")
    def press_p(self):
        logger.info("Pressed P now!")


if __name__ == "__main__":
    load_mod_file(__file__)

This mod clearly has very little functionality, but the above highlights the minimum requirements to make a single-file mod using pyMHF.

To run this mod it is strongly recommended to use uv as it has full support for inline script metadata.

The steps to run the above script from scratch (ie. with no uv installed) are as follows:

python -m pip install uv
uv run script.py

In the above ensure that the python command runs a python version between 3.9 and 3.11 INCLUSIVE. Replace script.py with the name of the script as it was saved.

To modify the above script, the only values that really need to be changed are the steam_guid and exe values.

If the game is being ran via steam, replace steam_gameid with the value found in steam, and set exe to be the name of the game binary. If the game or program is not run through steam, remove the steam_gameid value and instead set exe and the absolute path to the binary.

Note that by default the GUI will not be installed by uv and is only available on 64-bit installations of Python due to DearPyGui lacking support for 32-bit. If you want the GUI to be included, add the [gui] extra to your script dependecies metadata, like so:

# /// script
# dependencies = ["pymhf[gui]"]
#
... (truncated)