# Fabric Loader
The loader for mods under Fabric. Fabric Loader provides mod loading facilities and useful abstractions for other mods to use.
## License
Fabric Loader is Licensed under the Apache License 2.0
## Using Fabric Loader with vanilla launcher, MultiMC and other launchers
TODO: Write section
## Creating mods
This section details the creation of a mod. Registration of events, registry objects and other logic is version dependent any may vary by game version and physical environment. Details on version dependent logic and registration of said logic can be found on the Fabric wiki **(TODO: Link)**
This section explains how to make a simple mod which prints a message to the console when initialized.
For this tutorial, all the code is in Java. Much of this article is applicable to other JVM languages such as Kotlin, Scala, Groovy, etc. Specifics on using entrypoints with other JVM languages is detailed in the language provider mod for each language.
**Note:** All code examples that contain `[...]` mean insert "other code here". These markers should be excluded from resulting files.
### What actually is a mod to Fabric Loader?
A mod in fabric loader is loaded and detected via the precense of a `fabric.mod.json`. In a development environment, this should be placed in `/src/SOURCESET/resources`. Where `SOURCESET` refers to the current source set, typically `main`.
The file must be named `fabric.mod.json`
The JSON file specifies the id of a mod, the version and additional metadata.
The current schema version is 1. This is specified via the `schemaVersion` field.
| Field | Type | Description |
| ----- | ---- | ----------- |
| `schemaVersion` | Integer | Specifies the current version of the `fabric.mod.json` schema. If absent, it is assumed the specification version is 0. |
In schema version 1 there are two **required** fields
| Field | Type | Description |
| -------- | ---- | ----------- |
| `id` | String | Specifies the mod id. Must be 3-64 characters long and can only contain lowercase letters, numbers, dashes `-` and underscores `_`. |
| `version` | String | Specifies the version of the mod. Encouraged to match the [Semantic Versioning 2.0.0](https://semver.org/) specification for versions. |
Below is an example of the minimum required fields.
```json
{
"schemaVersion": 1,
"id": "modid",
"version": "0.1",
[...]
}
```
The `id` is the mod id of the mod. The mod id must be 3-64 characters long and can only contain lowercase letters, numbers, dashes `-` and underscores `_`.
The specification of a `fabric.mod.json` file can be found here **(TODO: Link to spec/create one)**
### Entrypoints
Fabric Loader uses an "entrypoint prototype" system for initializing mods. An entrypoint is typically an interface that specifies methods for mods to implement. These methods may be called during mod initialization or for other reasons. Entrypoints can be considered a more powerful implementation of Java's [Service Provider Interfaces](https://www.baeldung.com/java-spi).
Entrypoints are declared in a mod's `fabric.mod.json`. Entrypoints are resolved via a "name" and must be a certain type.
An example entrypoints block in a `fabric.mod.json`:
```json
{
[...]
"entrypoints": {
"main": [
"net.fabricmc.ExampleMod",
"net.fabricmc.ExampleMod2"
],
"client": [
"net.fabricmc.ExampleClientMod"
]
}
[...]
}
```
The JSON file defines two entrypoint types, one called `main` and the other `client`. The `main` entrypoint refers to two classes.
It is advised that side-specific entrypoints (`client` and `server`) be placed in seperate classes from each other and from the `main` entrypoint to prevent classloading issues.
Mods may define their own entrypoints with custom names and types, however this is out of scope for this document. Further details on entrypoints such as defining entrypoints in alternative ways may be found here: **(TODO: Link)**
### Built-in entrypoints
Fabric Loader defines 4 built-in entrypoints.
- `main`
- The first normal initialization entrypoint to run.
- Uses the type `ModInitializer` and will call `onInitialize`.
- `client`
- Will run after main only in a physical client (`EnvType.CLIENT`).
- Uses the type `ClientModInitializer` and will call `onInitializeClient`.
- `server`
- Will run after main only in a physical (dedicated) server (`EnvType.SERVER`).
- Uses the type `DedicatedServerModInitializer` and will call `onInitializeServer`.
- `preLaunch`
- **Not recomended for general use**
- The earliest possible entrypoint, which is called just before the game launches. Use with caution to not interfere with the game's initialization.
- Uses the type `PreLaunchEntryPoint` and will call `onPreLaunch`.
### Creating a simple mod
It is recomended to use the [fabric example mod](https://github.com/FabricMC/fabric-example-mod) to start with. The example mod includes a default development environment and an example of the example below.
Further information on setting up the development environment may be found on the loom repository **(TODO: Link to loom and write a readme for using it)**.
A mod is recoginized by the precense of a `fabric.mod.json`, and if present, the built artifact will considered a mod. However this is not very useful and does very little.
In order to do things like register blocks, events and setup your mod, you need an entrypoint to invoke for initialization. Depending on the type of mod, the `client` or `server` entrypoints may be used, but for the simplicity, this example will use the `main` entrypoint but is applicable to both the `client` and `server` entrypoint.
Firstly, define a class that the entrypoint will be ran in:
```java=
public class ExampleMod {
[...]
}
```
Since the `main` entrypoint is being used, `ModInitializer` must be implemented by this class.
The class must be:
- public
- not abstract (`abstract class` or `interface`)
- contain a 0 argument constructor that is public
```java=
package net.fabricmc.example;
import net.fabricmc.api.ModInitializer;
public class ExampleMod implements ModInitializer {
[...]
}
```
And then implement the `onInitialize` method in `ModInitializer`. Inside this method,
```java=
package net.fabricmc.example;
import net.fabricmc.api.ModInitializer;
public class ExampleMod implements ModInitializer {
[...]
@Override
public void onInitialize() {
System.out.println("Hello Fabric Mod!");
// Run initialization code, register objects in registries, register events
[...]
}
[...]
}
```
Just because you created a class does not mean the entrypoint will be run when the game starts. In order to have an entrypoint load, you need to register it in your `fabric.mod.json`
Since the entrypoint name is `main`, you will create a json entry where the key is `main` and the type is an array:
```json
{
"schemaVersion": 1
"id": "example-mod",
"version": "0.1",
[...]
"entrypoints": {
"main": [
"net.fabricmc.example.ExampleMod"
]
}
}
```
If done correctly, then the message should be printed to the log when the game is run.
## Fabric Loader's API
Fabric loader contains an api to allow access to the current context in which a mod is loaded or running in. This is accessible via the `FabricLoader` interface (in the `api` package).
To get the current instance of fabric loader, call `FabricLoader.getInstance();`
The `FabricLoader` instance allows access to many things, such as getting the current game directory, the config directory, entrypoint instances, the mod list, the physical environment type and the mappings resolver.
### Mods in API
Mods are represented in Fabric Loader's API as a `ModContainer`. A mod container contains mod metadata and methods to resolve files present inside of a mod's jar file.
To get a list of all mods that are loaded, you may use `getAllMods`. This returns a Collection of `ModContainer`. Alternatively, checking for the precense of a mod may use `isModLoaded(String)`, where the string parameter is the mod id.
To get the mod container of a specific mod, `getModContainer(String)`, where the string parameter is the mod id. This returns an Optional which may contain a `ModContainer`. The optional is empty if the mod is not loaded.
### Physical environment
Fabric Loader's API spcifies the current "physical" environment Fabric Loader is running in. This is represented by an Enum called `EnvType`. The enum contains two values, `CLIENT` which refers to a physical client and `SERVER` which refers to a physical (dedicated) server. The can be checked by using `getEnvironmentType` using an instance of `FabricLoader`.
### Mapping resolver
The mapping resolver is used to convert class names. Typically this is used by Fabric Loader in development to load classes using yarn mappings. This is a more complex topic and more information may be found here: **(TODO: Link)**
### Getting Entrypoints
Entrypoints can be obtained via Fabric Loader. There are two methods, `getEntrypoints(T)` and `getEntrypointContainers(T)`. Usage of these methods is further documented here: **(TODO: Link)**
## Support
TODO: Write section, explain support channels (Discord primarily, IRC is an option, Issues, etc.)
## Contributing
See something Fabric Loader doesn't supply, a bug or something that may be useful? We welcome contributions to improve Fabric Loader.
Check out [the Contributing guidelines](../CONTRIBUTING.md).