Skip to content

Latest commit

 

History

History
141 lines (105 loc) · 8.84 KB

CONTRIBUTING.md

File metadata and controls

141 lines (105 loc) · 8.84 KB

Contributing

Contributions are very welcome and greatly appreciated! Make sure to join the Celeste Community Discord for any help you need.

Table of Contents

Getting started

⚠️ Make sure to search the existing Issues and Pull Requests to see if one already exists for your contribution.

If you are planning on contributing code to Everest, it is recommended to create a fork of the main repo to develop on. Once you have a fork, clone it to your machine and follow the instructions here to build and install it.

Types of Contributions

These are guidelines for some of the different types of contributions you can make to Everest.

Bug Reports

Make sure bug reports have enough information to be reproduced easily!
That means:

  • Steps to reproduce.
  • Description of the bug (expected behaviour vs actual behaviour).
  • log.txt file from the session where the bug was encountered (located in your Celeste install folder, with previous sessions stored in the LogHistory subfolder).

Ideas or Feature Requests

When submitting ideas or feature requests, consider carefully whether the feature would be more suited for a code mod.
Features for Everest should match at least one of the following criteria:

  • Adds features for code mods.
  • Specific to the Everest project.
  • Not possible to achieve through a code mod.

Pull Requests

When making a pull request, please note the following guidelines:

  • Branch name: use a descriptive name for your branch, following the format of action-target-details where possible.
  • Description: explain what your pull request changes and why.
  • Credits: if your modifications are in response to a request or issue, link to it or otherwise provide a "paper trail".
  • Testing: if you are submitting a bugfix, describe the issue thouroughly and provide recreation steps, especially if it is not an existing issue.
  • Response: when you submit a pull request, you are responsible for making sure any questions and change requests on it are answered in a timely manner.

Making Changes

These are explanations and guidelines for how to make changes to the Everest source code.

Adding Content

Content added must not change the functionality of the base game, or change any public facing API.
While many mods also make use of non-public code it is not as important to maintain backwards compatibility for it.

New features should only be added to improve or un-hardcode vanilla features, especially for general use in code mods (f.e. StrawberryRegistry, CustomNPC, Custom Events).
Gameplay mechanics, entities, and other features not present in the base game are usually better suited for a mod, although some exceptions will be made on a case by case basis.

Patching

As with in adding content, patches must not change the functionality of the base game, or change any public API.

Everest uses MonoMod to patch Celeste, which allows for classes and members to be modified. For an explanation of how the MonoMod patcher works, see the MonoMod GitHub

There are two ways to modify Vanilla code, depending on the scope of what is being modified:

patch_ classes

Adding a class with the same name as an existing one, and prefixing it with patch_ will direct MonoMod to apply it as a patch onto the original class.

By default, any methods that are patched are preserved by MonoMod with an orig_ prefix, and can be referenced in the patched method:

public extern void orig_DoThing(int val);
public void DoThing(int val) {
    int newVal = Transform(val);
    orig_DoThing(newVal);
}

There are a few attributes that can be applied to members of the class with different effects:

  • [MonoModIgnore] ignore this member, do not patch it except for MonoMod custom attributes.
  • [MonoModConstructor] treat this method as a constructor - why this is needed.
  • [MonoModReplace] replace this method entirely, do not generate an orig_ method.

Ext classes

Code mods were previously created with Everest as a git submodule, which meant that any additions from Everest in patch_ classes were not available to those mods at build time.

The recommended practice has since been updated to build against a patched version of Celeste, making Ext classes relatively obsolete.

In most cases, new patch_ members should not be added to their associated Ext class, and new Ext classes should not be created.

Exceptions are made when the Ext class contains significant additions that are not within the scope of the original class (ex: TextMenuExt).

Existing Ext classes will also be kept in the following cases:

  • An associated patch_ class member was not made public (ex: patch_Audio.CheckFmod)
  • Useful extension methods are defined (ex: AreaDataExt.ToKey)

MonoModRules

ℹ️ The recommended practices for MonoModRules have recently been changed as described in this PR.

Everest uses MonoModRules to directly modify the IL code of vanilla methods.
Some guidelines for using them are as follows:

  • Patches and Attribute definitions should be located in the Celeste.Mod.mm/Patches/ folder alongside their associated patch_ class.

    • If a patch is used across multiple files, it can be moved into the main MonoModRules file.
  • When using types or methods in an IL patch, they must be imported as a reference through MonoModRule.Modder or by association with an already imported type.

  • While in code mods it is often preferred to fail safe when patching, if an Everest patch does not work it should fail hard to prevent broken builds from reaching end-users.
    This means using ILCursor.GotoNext instead of TryGotoNext where possible, and implementing additional checks when TryGotoNext is necessary.

  • Primitive arrays and switch statements with more than 6 cases are not usable due to compiler optimizations.

Miscellaneous

Warnings

Due to the nature of modding, there are situations where the C# compiler will generate a warning that isn't possible to fix. In this situation you can add the following preprocessor directive to the top of the file:

#pragma warning disable [Warning Number] // Add a comment with the warning description

Warnings can be disabled for a specific block of code by surrounding it with pragma warning disable and pragma warning enable.

Documentation

Documentation takes the form of comments, xmldoc, guides, and references.

  • Comments should be added as needed to code, to help other developers and maintainers understand what it does and why it is necessary.
  • XMLDoc (in-line code docs that show up in IDEs) are recommended to help modders out. Vanilla types and members should be documented in lib-stripped/Celeste.xml. When adding xmldoc to modded or patched members, the inheritdoc tag should be used for members that would otherwise override vanilla docs, and the origdoc tag can be added to orig_ members to warn users against using them.
  • Guides and References are kept in a number of locations, the most prominent being the Everest Wiki. Anything new for use in mods should be included there, with bonus points for adding an example in the Reference Mod, if appropriate.