LogoReliable Recipe Viewer

Adding a Client Recipe

Now you need to add your recipe's class to tell RRV about things like rendering & items. Just create a class implementing ReliableClientRecipe and override the required methods.

Note that SlotContent is used rather than displaying the ItemStacks themselves. This abstraction allows for different types of content to be displayed easily.

Example

public class UpgradingClientRecipe implements ReliableClientRecipe {
private final Identifier id;
private final SlotContent baseItem, upgradeItem, resultItem;
//You can design your constructor to suit your needs
public UpgradingClientRecipe(Identifier id, Ingredient baseItem, Ingredient upgradeItem, ItemStackTemplate resultItem) {
//Define your inputs and outputs here
this.baseItem = SlotContent.of(baseItem);
this.upgradeItem = SlotContent.of(upgradeItem);
this.resultItem = SlotContent.of(resultItem);
this.id = id;
}
// Prior to RRV 8.0.0, this was `getViewType`.
@Override
public ReliableClientRecipeType getType() {
return ExampleModClientRecipeType.INSTANCE; // Here you need your client recipe type's instance you created before
}
// The identifier of this recipe, used for clientside operations like recipe hiding. Only available/required since v8.0.0.
// If this recipe does not have a file associated with it, prefix the path with ' e.g. `minecraft:/code_driven_recipe` so that users do not look for a nonexistent file.
public Identifier getId() {
return id;
}
@Override
public void bindSlots(RecipeViewMenu.SlotFillContext slotFillContext) {
//Tell RRV which SlotContent belongs to which of your previously defined slots
slotFillContext.bindSlot(0, this.baseItem);
slotFillContext.bindSlot(1, this.upgradeItem);
slotFillContext.bindSlot(2, this.resultItem);
// When you want to add custom information to some of your items simply add a stack modifier to the corresponding slots
slotFillContext.addAdditionalStackModifier(1, (stack, tooltip) -> {
tooltip.add(Component.literal("Used to upgrade an item!"));
});
// You can also bind a slot as "optional" and provide it with a valid SlotRenderer to ensure a slot
// is only rendered if there's an item in it
// The default SlotRenderer is used for rendering Minecraft's default slot texture
slotFillContext.bindOptionalSlot(0, this.resultItem, RecipeViewMenu.OptionalSlotRenderer.DEFAULT);
}
@Override
public List<SlotContent> getIngredients() {
return List.of(this.baseItem, this.upgradeItem); // Return all of your inputs here
}
@Override
public List<SlotContent> getResults() {
return List.of(this.resultItem); // Return all of your outputs here
}
// Recipes with more complicated displays can override `renderRecipe`.
public void renderRecipe(RecipeViewScreen screen, RecipePosition recipePosition, GuiGraphicsExtractor guiGraphics, int mouseX, int mouseY, float partialTicks) {
guiGraphics.text(Minecraft.getInstance().font, "Rendered text on the center of the screen!", 5, 20, -16777216, false);
if ((mouseX > 65 && mouseX < 90) && mouseY < 37 && mouseY > 5) {
guiGraphics.setTooltipForNextFrame(Component.literal("Text in a tooltip when hovering over an area!"), mouseX, mouseY);
}
}
}

Slot dependencies

Slots that should not tick independently can be bound as dependent slots in your client recipe. This can be used to keep recipe outputs that are dependent on the recipe inputs synchronized (e.g. smithing recipes, dye recipes, decorated pot recipes).

@Override
public void bindSlots(RecipeViewMenu.SlotFillContext slotFillContext) {
//...
slotFillContext.bindDependentSlot(0, this.input::index, this.input2);
}

The method requires an integer supplier which tells the SlotContent at which position it is currently ticking.

In this case, we are using the current index of this.input as the index for this.input2, which ensures they are always synchronized.

Recipe-transfer functionality

To be able to shift items from the players inventory into the workstation's GUI, you have to override a few more methods of your class that implements ReliableClientRecipe:

@Override
public boolean supportsItemTransfer() {
return true; // Enable item transfer
}
@Override
public List<Class<? extends AbstractContainerScreen<?>>> getTransferClasses() {
return List.of(UpgradingScreen.class); // Tell which screen is the corresponding crafting gui
}
@Override
public void mapRecipeItems(RecipeTransferMap map) {
// Link your recipe slots to the corresponding slots in the destination inventory (the crafting inventory)
map.linkSlots(0, 1);
map.linkSlots(1, 2);
}

With your client recipes created, you can move on to creating the plugins that will be used to convert normal recipes into client recipes. On versions of RRV prior to 8.0.0, you'll also need Server Recipes that will supply them with data.