# File layout and discovery

A patch only runs if the game can find it. This page covers where patch files go and the two globals that tell your script who it belongs to.

## What a mod is

If you have not packaged a mod before, here is the short version. A **mod** is a folder the game loads at startup. Inside it is a `swinfo.json` **manifest** that gives the mod an id, a name, and a version. (It is a file from SpaceWarp, the modding platform Redux is built on.) Your patches are just `.lua` files sitting inside that folder.

Mods live in the game's `mods` folder, the same place every Redux and SpaceWarp mod is installed. The in-game mod list has an "Open Mods Folder" button that opens it, which is the easiest way to find it. At startup PatchManager looks through the mods there and discovers the `.lua` files inside each one.

[Shipping patches](/doc/shipping-patches-8EnGXsVNKP) covers the manifest in detail. For now you only need the picture: a mod is a folder with a manifest and your `.lua` files.

## Where patch files live

There are two ways a `.lua` patch gets discovered.

### Inside a mod

The normal case. Your mod is a folder with a `swinfo.json` manifest. Every `.lua` file anywhere under that folder is discovered and run as a patch, at any depth. You can organize patches into subfolders however you like:

```
MyMod/
  swinfo.json
  patches/
    parts.lua
    planets/
      reentry.lua
      dust-colors.lua
```

All three `.lua` files will be discovered and run.

There is one rule: a file whose name starts with an underscore is skipped. A file like `_shared.lua` is not run as a patch. This is how you keep helper libraries that other patch files pull in with `require` from being executed on their own. See [Sharing Lua with require](/doc/sharing-lua-with-require-hXbW2HK8Ep).

### As a standalone drop-in

A single `.lua` file dropped directly into the game's `mods` folder, with no `swinfo.json` around it, is treated as a tiny mod of its own. Its mod id becomes the file name without the extension. This is convenient for a one-file tweak you do not want to package, but for anything you share, it is recommended to ship it as a packaged mod.

## ModId

`ModId` is a global string holding the id of the mod your script belongs to. For a packaged mod it is the `ModID` from `swinfo.json`. For a standalone drop-in it is the file name sans extension.

You will use it when you want a name that is unique across all mods. Patch names, for instance, are automatically prefixed with your `ModId` behind the scenes, which is why two mods can both have a patch called `Fixes` without clashing. As such you will rarely need to read `ModId` directly.

## Location

`Location` is a global string holding the full path to the folder your script was found in. It is useful when a patch needs to load a file you shipped alongside it: instead of hard-coding a path, you build one relative to `Location`. This matters because the modloader lets a mod sit at any depth in the file tree, so there is no fixed path you could assume. `Location` always points at your own mod's folder, wherever it ended up.

`Location` is `nil` only in unusual setups where a script was not loaded from a folder on disk. That does not happen by accident, so unless you have deliberately arranged it, you do not need to guard against the `nil` case.

## When patches run

Discovery happens once, at game startup, before assets load. All discovered scripts run to **register** their patches first. This includes the scripts of mods that are not yet on in a campaign. Then PatchManager loads the assets and runs the registered patches on them:

* One time for the [feature set](/doc/campaign-features-9YIewcIArR) of the main menu, at startup.
* One more time for the set of each campaign, when that campaign loads.

Each run uses only the patches that the set allows. This split is important. The body of a `Do` callback runs later than the `PM.Parts:Patch(...)` call that registered it. The callback can run more than one time, one time for each set. You cannot register a new patch from inside a `Do` callback, because registration is already over by then.

## Next

Once your patches work locally, [shipping patches](/doc/shipping-patches-8EnGXsVNKP) covers packaging them for other people.