Recipe filter
Status: experimental.
What it is
The game shows the recipes of a crafting panel as a list of buttons. This API lets your mod decide which recipes appear in that list. You give the framework a function that is called for each recipe, with the recipe’s details, and it returns true to keep the recipe or false to hide it. A recipe is shown only when every mod’s function keeps it.
When to use it
- Show only the recipes the player has, hiding the recipes that need no learning and that the player has not collected.
- Let the player search the recipe list by name.
Quick example
This mod hides the recipes that need no learning and that the player has not collected, so the list shows only the recipes the player has or has learned. It is a plain rule, so it runs the same way at every crafting panel.
using ObenseuerCore;
[ModInfo("example.knownonly", "Known Only", "0.1.0")]
[ModDependency("obenseuer.moddingframework", "0.11.0")]
public sealed class KnownOnly : FrameworkMod
{
protected override void OnLoad()
{
if (!RecipeFilter.Add(Mod.Id, recipe => recipe.Known)) Log.Info("The recipe filter was not added.");
}
}
Mod.Id is your mod’s id (see the glossary). RecipeInfo is the recipe the framework gives you, see Recipes and crafting. RecipeInfo.Known is true when the player has or has learned the recipe. For the recipes the list shows it is false only for the recipes that need no learning, because the game does not list a recipe that needs learning until the player has it.
Common tasks
Search the list by name. Your mod keeps the text in its own field, and the function keeps the recipes whose name contains it. Matches ignores upper and lower case, and an empty text keeps every recipe.
private string searchText = string.Empty;
private bool Search(RecipeInfo recipe)
{
return RecipeFilter.Matches(recipe, searchText);
}
RecipeFilter.Add(Mod.Id, Search);
Remove your filter, for example when the player turns your option off. Remove returns false when your mod had no filter.
bool removed = RecipeFilter.Remove(Mod.Id);
Reference
Text in brackets at the end of a note is extra detail you can skip on a first read.
RecipeFilter deciding which recipes the list shows
Call Add with your mod id and a function, and Remove to take your function away. Matches is a helper for name searches.
public static class RecipeFilter
{
public static bool IsAvailable { get; }
public static bool Add(string modId, Func<RecipeInfo, bool> keep);
public static bool Remove(string modId);
public static bool Matches(RecipeInfo recipe, string text);
}
| Method | Returns | What it does |
|---|---|---|
Add(modId, keep) | bool | Adds your function. true when it was added. Calling it again with the same mod id replaces the function. |
Remove(modId) | bool | Removes your function. false when your mod had none. |
Matches(recipe, text) | bool | true when the recipe’s name contains the text, ignoring upper and lower case. An empty text matches every recipe. A null recipe does not match. |
IsAvailable | bool | false when the framework could not change the recipe list, so no filter is used. |
RecipeInfo the recipe your function is asked about
The details of one recipe, as the framework reads them from the game.
public sealed class RecipeInfo
{
public int Id { get; }
public string Name { get; }
public string Station { get; }
public bool Known { get; }
public List<RecipeIngredient> Ingredients { get; }
public List<ItemCount> Results { get; }
}
| Property | Type | What it is |
|---|---|---|
Id | int | The recipe’s id. |
Name | string | The name the list shows. |
Station | string | The name of the recipe’s type. |
Known | bool | true when the player has the recipe. |
Ingredients | List<RecipeIngredient> | The items the recipe uses. |
Results | List<ItemCount> | The items the recipe makes. |
Things to know
- Your function is called for each recipe when the game builds a recipe list. A recipe is shown only when every mod’s function keeps it. A recipe that no function refuses is shown as the game would show it.
- The framework does not rebuild the list when your text changes. The list changes the next time the game builds it, for example when the player opens the panel again. This API cannot force a rebuild.
- The filter covers the recipe lists of the manufacturing, manufacturing process and growing panels, which the framework checks in build 25969064 of the game. (The game fills these lists through
RecipeListUI.UpdateRecipes, and the filter is onRecipeListUI.CreateButton. The basic crafting station panel is not checked.) - Your function should be cheap. It runs once for each recipe in the list.
- A filter that throws does not hide the recipe. The framework keeps the recipe and logs the error once.
- Filters are not saved. Add yours again when the game starts, for example from
Events.WhenReady.
Limits
Addreturnsfalseand logs once when the mod id is not valid (1 to 64 letters, digits,.,_or-), the function isnull, or the framework could not change the recipe list.RemoveandMatchesdo not throw.- A filter that calls
AddorRemovewhile it runs is safe. The framework runs the filters on a copy it takes before the call, so a change made from inside a filter applies to the next recipe list. - Hiding a recipe in the list does not stop the game from knowing it. The player can still learn or use it by other means.
- Selecting a recipe with the controller or the keyboard is mapped onto the list you can see, so the same recipe as a mouse click is picked. When the framework cannot map it (a station without a recipe list of its own, or a list that does not match the open panel) the game’s own behaviour is used instead.