Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Brewing recipes #161

Open
wants to merge 28 commits into
base: 1.19.4
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
0d973e0
brewing fuel registry
Platymemo Aug 5, 2022
b834560
quilt brewing recipes
Platymemo Aug 5, 2022
8cf04c8
Merge remote-tracking branch 'QuiltMC/1.19' into 1.19+brewing_recipes
Platymemo Aug 5, 2022
a00e0fa
fix incompatibility with vanilla clients
Platymemo Aug 5, 2022
d5789d4
test brewing recipe
Platymemo Aug 6, 2022
8b845fc
brewing recipes ready for review
Platymemo Aug 6, 2022
e55b31d
Merge remote-tracking branch 'QuiltMC/1.19' into 1.19+brewing_recipes
Platymemo Aug 6, 2022
e205201
quick fix
Platymemo Aug 6, 2022
40b60f5
apply licenses
Platymemo Aug 6, 2022
c42ad20
apply suggestions
Platymemo Aug 6, 2022
3581671
Apply javadoc suggestions
Platymemo Aug 9, 2022
312b54e
Extend max values for brewing fuel and brew time
Platymemo Aug 9, 2022
1b642b5
missed a suggestion
Platymemo Aug 9, 2022
e4bd994
Apply suggestions
Platymemo Aug 9, 2022
d2cd203
Merge remote-tracking branch 'QuiltMC/1.19' into brewing-recipes
Platymemo Aug 29, 2022
36424a4
Clear brewing ingredients on reload
Platymemo Aug 29, 2022
de4faf0
dont crash with vanilla recipes
Platymemo Sep 7, 2022
fb046cb
fix potion villager trades
Platymemo Sep 7, 2022
f072fd3
brewing docs
Platymemo Sep 7, 2022
0ac3b3a
more compatible mixin
Platymemo Sep 12, 2022
bf63a47
deduplicate recipe match checks
Platymemo Sep 20, 2022
494ce5b
Merge remote-tracking branch 'QuiltMC/1.19.4' into brewing-recipes
Platymemo Mar 31, 2023
984d0a5
update brewing recipes
Platymemo Apr 1, 2023
9d77336
Merge branch '1.19.4' into brewing-recipes
EnnuiL Apr 12, 2023
f19b914
Apply suggestions from code review
Platymemo Apr 13, 2023
56260fb
move recipe serializer registration to onInitialize
Platymemo Apr 13, 2023
80d2d31
move brewing recipes to the quilt namespace
Platymemo Apr 13, 2023
ce54b86
Merge branch '1.19.4' into brewing-recipes
EnnuiL Apr 22, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions library/data/recipe/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,10 @@ qslModule {
testmodOnly("resource_loader")
}
}
entrypoints {
init {
values = ["org.quiltmc.qsl.recipe.impl.RecipeImpl"]
}
}
accessWidener()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,266 @@
/*
* Copyright 2022 QuiltMC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.quiltmc.qsl.recipe.api;
Platymemo marked this conversation as resolved.
Show resolved Hide resolved

import java.util.ArrayList;
import java.util.List;

import com.google.gson.JsonObject;

import net.minecraft.block.Blocks;
import net.minecraft.block.entity.BrewingStandBlockEntity;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.network.PacketByteBuf;
import net.minecraft.potion.Potion;
import net.minecraft.recipe.Ingredient;
import net.minecraft.recipe.Recipe;
import net.minecraft.recipe.RecipeSerializer;
import net.minecraft.recipe.RecipeType;
import net.minecraft.util.Identifier;
import net.minecraft.util.JsonHelper;
import net.minecraft.util.collection.DefaultedList;
import net.minecraft.util.registry.Registry;
import net.minecraft.world.World;

import org.quiltmc.qsl.recipe.api.serializer.QuiltRecipeSerializer;

/**
* The base for all Quilt brewing recipes.
*
* @param <T> what type the input and output represents.
* Vanilla would be {@link Potion} and {@link Item}
* @see PotionBrewingRecipe
* @see CustomPotionBrewingRecipe
* @see PotionItemBrewingRecipe
*/
public abstract class AbstractBrewingRecipe<T> implements Recipe<BrewingStandBlockEntity> {
public static final List<Ingredient> VALID_INGREDIENTS = new ArrayList<>();
protected final T input;
protected final Ingredient ingredient;
protected final T output;
protected final int fuel;
protected final int brewTime;
protected ItemStack ghostOutput;
protected final String group;
private final Identifier id;

public AbstractBrewingRecipe(Identifier id, String group, T input, Ingredient ingredient, T output, int fuel, int brewTime) {
this.id = id;
this.group = group;
this.input = input;
this.ingredient = ingredient;
VALID_INGREDIENTS.add(ingredient);
this.output = output;
this.ghostOutput = new ItemStack(Items.POTION);
this.fuel = fuel;
this.brewTime = brewTime;
}

@Override
public RecipeType<AbstractBrewingRecipe<?>> getType() {
return Recipes.BREWING;
}

@Override
public ItemStack craft(BrewingStandBlockEntity inventory) {
for (int i = 0; i < 3; i++) {
if (this.matches(i, inventory.getStack(i))) {
inventory.setStack(i, craft(i, inventory.getStack(i)));
}
}

return ItemStack.EMPTY;
}

/**
* Transforms the input {@link ItemStack} to the output {@link ItemStack}.
* <p>
* The input is guaranteed to match the required input, as defined by {@link #matches(int, ItemStack)}.</p>
*
* @param slot the index of the slot
* @param input the {@link ItemStack} in the provided slot
* @return the output {@link ItemStack}
*/
protected abstract ItemStack craft(int slot, ItemStack input);

@Override
public boolean matches(BrewingStandBlockEntity inventory, World world) {
ItemStack ingredient = inventory.getStack(3);
if (this.ingredient.test(ingredient)) {
for (int i = 0; i < 3; ++i) {
if (matches(i, inventory.getStack(i))) {
return true;
}
}
}
return false;
}

/**
* Matches based on stacks in the potion slots.
*
* @param slot the index of the slot
* @param input the {@link ItemStack} in the provided slot
* @return {@code true} if the {@link ItemStack} is a valid {@link AbstractBrewingRecipe#input} for this recipe, or {@code false}
*/
public abstract boolean matches(int slot, ItemStack input);

/**
* @return how much fuel this recipe takes to craft
*/
public int getFuelUse() {
return this.fuel;
}

/**
* @return how long this recipe takes to craft
*/
public int getBrewTime() {
return this.brewTime;
}

@Override
public boolean fits(int width, int height) {
return true;
}

@Override
public DefaultedList<ItemStack> getRemainder(BrewingStandBlockEntity inventory) {
// TODO integrate with custom recipe remainders
return Recipe.super.getRemainder(inventory);
}

@Override
public boolean isIgnoredInRecipeBook() {
return true;
}

@Override
public ItemStack createIcon() {
return new ItemStack(Blocks.BREWING_STAND);
}

@Override
public ItemStack getOutput() {
return this.ghostOutput;
}

@Override
public Identifier getId() {
return this.id;
}

/**
* The base serializer for all Quilt brewing recipe serializers to extend.
*
* @param <T> the type of the recipe's input and output
* @param <R> the recipe
*/
public static abstract class AbstractBrewingSerializer<T, R extends AbstractBrewingRecipe<T>> implements RecipeSerializer<R>, QuiltRecipeSerializer<R> {
private final RecipeFactory<T, ? extends R> recipeFactory;

protected AbstractBrewingSerializer(RecipeFactory<T, ? extends R> recipeFactory) {
this.recipeFactory = recipeFactory;
}

@Override
public R read(Identifier id, JsonObject json) {
String group = JsonHelper.getString(json, "group", "");
Ingredient ingredient = Ingredient.fromJson(JsonHelper.getObject(json, "ingredient"));
T input = this.deserialize("input", json);
T output = this.deserialize("output", json);
int fuel = JsonHelper.getInt(json, "fuel", 1);
int brewTime = JsonHelper.getInt(json, "time", 400);
return this.recipeFactory.create(id, group, input, ingredient, output, fuel, brewTime);
}

@Override
public R read(Identifier id, PacketByteBuf buf) {
String group = buf.readString();
Ingredient ingredient = Ingredient.fromPacket(buf);
T input = this.deserialize(buf);
T output = this.deserialize(buf);
int fuel = buf.readInt();
int brewTime = buf.readInt();
return this.recipeFactory.create(id, group, input, ingredient, output, fuel, brewTime);
}

@Override
public void write(PacketByteBuf buf, R recipe) {
buf.writeString(recipe.group);
recipe.ingredient.write(buf);
this.serialize(recipe.input, buf);
this.serialize(recipe.output, buf);
buf.writeInt(recipe.fuel);
buf.writeInt(recipe.brewTime);
}

@Override
public JsonObject toJson(R recipe) {
JsonObject json = new JsonObject();
json.addProperty("group", recipe.group);
json.add("ingredient", recipe.ingredient.toJson());
json.addProperty("type", Registry.RECIPE_SERIALIZER.getId(recipe.getSerializer()).toString());
this.serialize(recipe.input, "input", json);
this.serialize(recipe.output, "output", json);
json.addProperty("fuel", recipe.fuel);
json.addProperty("time", recipe.brewTime);
return json;
}

/**
* Deserializes the object from json.
*
* @param element the json element to read
* @param json the json object
* @return the deserialized object
*/
public abstract T deserialize(String element, JsonObject json);

/**
* Deserializes the object from the buffer.
*
* @param buf the buffer
* @return the deserialized object
*/
public abstract T deserialize(PacketByteBuf buf);

/**
* Serializes the value to the json under the provided element key.
*
* @param value the value to serialize
* @param element the key to serialize it under
* @param json the json object
*/
public abstract void serialize(T value, String element, JsonObject json);

/**
* Serializes the value to the buffer.
*
* @param value the value to serialize
* @param buf the buffer
*/
public abstract void serialize(T value, PacketByteBuf buf);

@FunctionalInterface
public interface RecipeFactory<T, R extends AbstractBrewingRecipe<T>> {
R create(Identifier id, String group, T input, Ingredient ingredient, T output, int fuel, int brewTime);
}
}
}
Loading