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

Add a recipe datagen API #7

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/*
* Copyright (C) 2022 GroovyMC and contributors
* SPDX-License-Identifier: LGPL-3.0-or-later
*/

package io.github.groovymc.cgl.api.extension

import groovy.transform.CompileStatic
import net.minecraft.core.BlockPos
import net.minecraft.core.Holder
import net.minecraft.core.Position
import net.minecraft.nbt.CompoundTag
import net.minecraft.tags.TagKey
import net.minecraft.world.item.Item
import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.crafting.Ingredient
import net.minecraft.world.level.ItemLike
import net.minecraft.world.phys.Vec3
import org.codehaus.groovy.runtime.DefaultGroovyMethods

@CompileStatic
class ItemExtensions {
static ItemStack count(ItemLike self, int count) {
new ItemStack(self, count)
}

static ItemStack multiply(ItemLike self, int count) {
new ItemStack(self, count)
}

static ItemStack multiply(Integer count, ItemLike item) {
new ItemStack(item, count)
}

static ItemStack count(ItemStack self, int count) {
Matyrobbrt marked this conversation as resolved.
Show resolved Hide resolved
self.setCount(count)
return self
}

static ItemStack tag(ItemStack self, CompoundTag tag) {
Matyrobbrt marked this conversation as resolved.
Show resolved Hide resolved
self.setTag(tag)
return self
}

static ItemStack tag(ItemStack self, Object tag) {
self.setTag(StaticNBTExtensions.from(null, tag) as CompoundTag)
return self
}

static Ingredient ingredient(ItemLike item) {
return Ingredient.of(item)
}

static Ingredient ingredient(TagKey<Item> tag) {
return Ingredient.of(tag)
}

static <T> T asType(ItemStack self, Class<T> type) {
return switch (type) {
case Ingredient -> (T) ingredient(self.item)
case ItemLike, Item -> (T) self.item
case Holder<Item> -> (T) self.itemHolder
default -> (T) DefaultGroovyMethods.asType(self, type)
}
}

static <T> T asType(ItemLike self, Class<T> type) {
return switch (type) {
case Ingredient -> (T) ingredient(self.asItem())
case ItemStack -> (T) self.asItem().defaultInstance
default -> (T) DefaultGroovyMethods.asType(self, type)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ final class StaticNBTExtensions {
case Collection -> new ListTag().tap { list ->
toConvert.each { list.add(from(null, it)) }
}
case Map -> of(null, toConvert as Map)
default -> (Tag) null
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
moduleName=CGL Extensions
moduleVersion=0.2.0
extensionClasses=io.github.groovymc.cgl.api.extension.registry.RegistryExtension,io.github.groovymc.cgl.api.extension.math.ArithmeticExtension,io.github.groovymc.cgl.api.extension.chat.ComponentExtension,io.github.groovymc.cgl.api.extension.TagExtensions,io.github.groovymc.cgl.api.extension.client.MinecraftExtensions,io.github.groovymc.cgl.api.extension.NBTExtensions,io.github.groovymc.cgl.api.extension.CodecExtensions,io.github.groovymc.cgl.api.extension.brigadier.CommandExtensions,io.github.groovymc.cgl.api.extension.brigadier.CommandContextExtensions,io.github.groovymc.cgl.api.extension.brigadier.ArgumentExtensions,io.github.groovymc.cgl.api.extension.GeneralExtensions
extensionClasses=io.github.groovymc.cgl.api.extension.registry.RegistryExtension,io.github.groovymc.cgl.api.extension.math.ArithmeticExtension,io.github.groovymc.cgl.api.extension.chat.ComponentExtension,io.github.groovymc.cgl.api.extension.TagExtensions,io.github.groovymc.cgl.api.extension.client.MinecraftExtensions,io.github.groovymc.cgl.api.extension.NBTExtensions,io.github.groovymc.cgl.api.extension.CodecExtensions,io.github.groovymc.cgl.api.extension.brigadier.CommandExtensions,io.github.groovymc.cgl.api.extension.brigadier.CommandContextExtensions,io.github.groovymc.cgl.api.extension.brigadier.ArgumentExtensions,io.github.groovymc.cgl.api.extension.GeneralExtensions,io.github.groovymc.cgl.api.extension.ItemExtensions
staticExtensionClasses=io.github.groovymc.cgl.api.extension.StaticGeneralExtensions,io.github.groovymc.cgl.api.extension.chat.StyleExtension,io.github.groovymc.cgl.api.extension.StaticNBTExtensions
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* Copyright (C) 2022 GroovyMC and contributors
* SPDX-License-Identifier: LGPL-3.0-or-later
*/

package io.github.groovymc.cgl.api.datagen.recipe

import groovy.transform.CompileStatic
import net.minecraft.core.registries.BuiltInRegistries
import net.minecraft.data.recipes.RecipeBuilder
import net.minecraft.resources.ResourceLocation
import net.minecraft.world.item.Item
import net.minecraft.world.item.ItemStack
import net.minecraft.world.level.ItemLike

@CompileStatic
trait BaseRecipeBuilder extends SaveableRecipe implements RecipeBuilder {
ItemStack result

ItemStack result(ItemLike result) {
this.result = result.asItem().getDefaultInstance()
return this.result
}

void setResult(ItemLike result) {
this.result(result)
}

ItemStack result(ItemStack result) {
this.result = result
return this.result
}

void setResult(ItemStack result) {
this.result(result)
}

Item getResult() {
return this.@result.item
}

ItemStack getResultStack() {
return this.@result
}

/**
* Saves this recipe to a location representing the {@link #getResult() result's} registry name.
*/
void save() {
this.save(BuiltInRegistries.ITEM.getKey(getResult()))
}

/**
* {@inheritDoc}
*/
void save(ResourceLocation location) {
provider.forgottenRecipes.remove(this)
this.save(this.getProvider().writer, location)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
/*
* Copyright (C) 2022 GroovyMC and contributors
* SPDX-License-Identifier: LGPL-3.0-or-later
*/

package io.github.groovymc.cgl.api.datagen.recipe

import com.google.gson.JsonObject
import groovy.contracts.Requires
import groovy.time.TimeDuration
import groovy.transform.CompileStatic
import net.minecraft.advancements.Advancement
import net.minecraft.advancements.AdvancementRewards
import net.minecraft.advancements.RequirementsStrategy
import net.minecraft.advancements.critereon.RecipeUnlockedTrigger
import net.minecraft.core.registries.BuiltInRegistries
import net.minecraft.data.recipes.FinishedRecipe
import net.minecraft.resources.ResourceLocation
import net.minecraft.world.item.BlockItem
import net.minecraft.world.item.Item
import net.minecraft.world.item.crafting.AbstractCookingRecipe
import net.minecraft.world.item.crafting.CookingBookCategory
import net.minecraft.world.item.crafting.Ingredient
import net.minecraft.world.item.crafting.RecipeSerializer
import net.minecraft.world.level.ItemLike
import org.jetbrains.annotations.Nullable

import java.util.function.Consumer

@CompileStatic
class GCookingRecipeBuilder implements SimpleRecipeBuilder<GCookingRecipeBuilder> {
private CookingBookCategory bookCategory
private Ingredient ingredient
private float experience = 20
private int cookingTime = 200
private RecipeSerializer<? extends AbstractCookingRecipe> serializer

GCookingRecipeBuilder() {
this(RecipeSerializer.SMELTING_RECIPE)
}

GCookingRecipeBuilder(RecipeSerializer<? extends AbstractCookingRecipe> serializer) {
this.serializer = serializer
}

GCookingRecipeBuilder serializer(RecipeSerializer<? extends AbstractCookingRecipe> serializer) {
return setSerializer(serializer)
}

GCookingRecipeBuilder setSerializer(RecipeSerializer<? extends AbstractCookingRecipe> serializer) {
this.serializer = serializer
return this
}

GCookingRecipeBuilder ingredient(Ingredient ingredient) {
setIngredient(ingredient)
return this
}

void setIngredient(Ingredient ingredient) {
this.ingredient = ingredient
}

void setExperience(float exp) {
this.experience = exp
}

GCookingRecipeBuilder experience(float exp) {
setExperience(exp)
return this
}

void setCookingTime(int cookingTime) {
this.cookingTime = cookingTime
}

GCookingRecipeBuilder cookingTime(int cookingTime) {
setCookingTime(cookingTime)
return this
}

void setCookingTime(TimeDuration cookingTime) {
this.cookingTime = cookingTime.seconds * 20
}

GCookingRecipeBuilder cookingTime(TimeDuration cookingTime) {
setCookingTime(cookingTime)
return this
}

@Requires({ ingredient && serializer && cookingTime > 0 })
void save(Consumer<FinishedRecipe> finishedRecipeConsumer, ResourceLocation recipeId) {
this.advancement.parent(ROOT_RECIPE_ADVANCEMENT).addCriterion('has_the_recipe', RecipeUnlockedTrigger.unlocked(recipeId)).rewards(AdvancementRewards.Builder.recipe(recipeId)).requirements(RequirementsStrategy.OR);
finishedRecipeConsumer.accept(new Result(recipeId, this.group ?: '', this.bookCategory ?: determineRecipeCategory(this.serializer, this.result), this.ingredient, this.result, this.experience, this.cookingTime, this.advancement, recipeId.withPrefix("recipes/" + this.category.getFolderName() + "/"), this.serializer));
}

private static CookingBookCategory determineRecipeCategory(RecipeSerializer<? extends AbstractCookingRecipe> serializer, ItemLike result) {
if (serializer == RecipeSerializer.SMELTING_RECIPE) {
if (result.asItem().isEdible()) {
return CookingBookCategory.FOOD
} else {
return result.asItem() instanceof BlockItem ? CookingBookCategory.BLOCKS : CookingBookCategory.MISC
}
} else if (serializer == RecipeSerializer.BLASTING_RECIPE) {
return result.asItem() instanceof BlockItem ? CookingBookCategory.BLOCKS : CookingBookCategory.MISC
} else {
return CookingBookCategory.MISC
}
}

static class Result implements FinishedRecipe {
private final ResourceLocation id
private final String group
private final CookingBookCategory category
private final Ingredient ingredient
private final Item result
private final float experience
private final int cookingTime
private final Advancement.Builder advancement
private final ResourceLocation advancementId
private final RecipeSerializer<? extends AbstractCookingRecipe> serializer

Result(ResourceLocation resourceLocation, String string, CookingBookCategory cookingBookCategory, Ingredient ingredient, Item item, float exp, int time, Advancement.Builder builder, ResourceLocation resourceLocation2, RecipeSerializer<? extends AbstractCookingRecipe> recipeSerializer) {
this.id = resourceLocation
this.group = string
this.category = cookingBookCategory
this.ingredient = ingredient
this.result = item
this.experience = exp
this.cookingTime = time
this.advancement = builder
this.advancementId = resourceLocation2
this.serializer = recipeSerializer
}

void serializeRecipeData(JsonObject json) {
if (!this.group.isEmpty()) {
json.addProperty('group', this.group);
}

json.addProperty('category', this.category.getSerializedName())
json.add('ingredient', this.ingredient.toJson())
json.addProperty('result', BuiltInRegistries.ITEM.getKey(this.result).toString())
json.addProperty('experience', this.experience)
json.addProperty('cookingtime', this.cookingTime)
}

RecipeSerializer getType() {
this.serializer
}

ResourceLocation getId() {
this.id
}

@Nullable
JsonObject serializeAdvancement() {
this.advancement.criteria.size() == 1 ? null : this.advancement.serializeToJson()
}

@Nullable
ResourceLocation getAdvancementId() {
this.advancementId
}
}
}
Loading