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 all 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
6 changes: 6 additions & 0 deletions library/data/recipe/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,14 @@ qslModule {
api("resource_loader")
testmodOnly("lifecycle_events")
}
item {
api("item_setting")
}
}
entrypoints {
init {
values = ["org.quiltmc.qsl.recipe.impl.RecipeImpl"]
}
events {
values = ["org.quiltmc.qsl.recipe.impl.RecipeManagerImpl"]
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* Copyright 2022-2023 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;

import net.minecraft.recipe.RecipeType;

import org.quiltmc.qsl.recipe.api.brewing.AbstractBrewingRecipe;
import org.quiltmc.qsl.recipe.impl.RecipeImpl;

public class QuiltRecipeTypes {
public static final RecipeType<AbstractBrewingRecipe<?>> BREWING = RecipeImpl.BREWING;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,273 @@
/*
* Copyright 2023 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.brewing;

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.registry.DynamicRegistryManager;
import net.minecraft.registry.Registries;
import net.minecraft.util.Identifier;
import net.minecraft.util.JsonHelper;
import net.minecraft.util.collection.DefaultedList;
import net.minecraft.world.World;

import org.quiltmc.qsl.item.setting.api.RecipeRemainderLogicHandler;
import org.quiltmc.qsl.recipe.api.QuiltRecipeTypes;
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 SimplePotionBrewingRecipe
* @see CustomPotionBrewingRecipe
* @see PotionItemBrewingRecipe
*/
public abstract class AbstractBrewingRecipe<T> implements Recipe<BrewingStandBlockEntity> {
public static final List<Ingredient> VALID_INGREDIENTS = new ArrayList<>();
Platymemo marked this conversation as resolved.
Show resolved Hide resolved
protected final T input;
protected final Ingredient ingredient;
protected final T output;
protected final int fuel;
protected final int brewTime;
protected ItemStack result;
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.result = new ItemStack(Items.POTION);
this.fuel = fuel;
this.brewTime = brewTime;
}

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

@Override
public ItemStack craft(BrewingStandBlockEntity inventory, DynamicRegistryManager manager) {
for (int i = 0; i < 3; i++) {
if (this.matches(i, inventory.getStack(i))) {
inventory.setStack(i, this.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)}.
*
* @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 (this.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) {
DefaultedList<ItemStack> remainders = DefaultedList.ofSize(inventory.size());

remainders.set(0, RecipeRemainderLogicHandler.getRemainder(inventory.getStack(0), this));

return remainders;
}

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

@Override
public ItemStack createIcon() {
return new ItemStack(Blocks.BREWING_STAND);
Platymemo marked this conversation as resolved.
Show resolved Hide resolved
}

@Override
public ItemStack getResult(DynamicRegistryManager manager) {
return this.result;
}

@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 abstract static 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", Registries.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 value from JSON.
*
* @param element the key of the element to read
* @param json the JSON object
* @return the deserialized value
*/
public abstract T deserialize(String element, JsonObject json);

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

/**
* Serializes the value to JSON, under the specified 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 a 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