Compare commits

...
47 changed files with 1286 additions and 385 deletions
+6
View File
@@ -32,6 +32,8 @@ repositories {
maven(url = "https://api.modrinth.com/maven")
maven(url = "https://maven.neoforged.net/releases")
maven(url = "https://maven.gegy.dev")
maven(url = "https://maven.terraformersmc.com/")
maven(url = "https://maven.shedaniel.me")
mavenLocal()
}
@@ -62,6 +64,10 @@ dependencies {
// Unit Testing
testImplementation(libs.bundles.unitTesting)
modCompileOnlyApi(libs.emi)
modCompileOnlyApi(libs.rei.api)
modCompileOnlyApi(libs.rei.defaultplugin)
}
tasks.withType<Test> {
@@ -8,7 +8,6 @@
package com.cobblemon.mod.common.client.gui.cookingpot
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.CobblemonNetwork.sendToServer
import com.cobblemon.mod.common.api.gui.blitk
import com.cobblemon.mod.common.block.campfirepot.CampfirePotColor
@@ -16,8 +15,6 @@ import com.cobblemon.mod.common.block.campfirepot.CookingPotMenu
import com.cobblemon.mod.common.block.campfirepot.SeasoningSlot
import com.cobblemon.mod.common.block.entity.CampfireBlockEntity.Companion.COOKING_POT_COLOR_INDEX
import com.cobblemon.mod.common.block.entity.CampfireBlockEntity.Companion.IS_LID_OPEN_INDEX
import com.cobblemon.mod.common.integration.jei.CobblemonJeiPlugin
import com.cobblemon.mod.common.integration.jei.cooking.CampfirePotRecipeCategory
import com.cobblemon.mod.common.item.crafting.CookingPotRecipe
import com.cobblemon.mod.common.mixin.accessor.RecipeBookComponentAccessor
import com.cobblemon.mod.common.net.messages.client.cooking.ToggleCookingPotLidPacket
@@ -216,18 +213,6 @@ class CookingPotScreen(
override fun getRecipeBookComponent(): RecipeBookComponent = this.recipeBookComponent
override fun mouseClicked(mouseX: Double, mouseY: Double, button: Int): Boolean {
val progressX = leftPos + 96
val progressY = topPos + 39
if (Cobblemon.implementation.isModInstalled("jei") &&
mouseX >= progressX && mouseX < progressX + COOK_PROGRESS_WIDTH &&
mouseY >= progressY && mouseY < progressY + COOK_PROGRESS_HEIGHT
) {
CobblemonJeiPlugin.jeiRuntime?.recipesGui?.showTypes(
listOf(CampfirePotRecipeCategory.RECIPE_TYPE)
)
return true
}
if (this.recipeBookComponent.mouseClicked(mouseX, mouseY, button)) {
this.focused = this.recipeBookComponent
@@ -248,28 +233,6 @@ class CookingPotScreen(
}
}
override fun renderTooltip(
guiGraphics: GuiGraphics,
mouseX: Int,
mouseY: Int
) {
val progressX = leftPos + 96
val progressY = topPos + 39
if (Cobblemon.implementation.isModInstalled("jei") &&
mouseX >= progressX && mouseX < progressX + COOK_PROGRESS_WIDTH &&
mouseY >= progressY && mouseY < progressY + COOK_PROGRESS_HEIGHT
) {
guiGraphics.renderTooltip(
this.font,
Component.translatable("jei.tooltip.show.recipes"),
mouseX,
mouseY
)
return
}
super.renderTooltip(guiGraphics, mouseX, mouseY)
}
private fun overrideRecipeBookFilterButton(filterButton: StateSwitchingButton) {
filterButton.initTextureValues(FILTER_BUTTON_SPRITES)
filterButton.setTooltip(
@@ -0,0 +1,27 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.integration.emi
import com.cobblemon.mod.common.integration.recipeviewer.RecipeViewerRecipe
import dev.emi.emi.api.recipe.EmiRecipeCategory
import dev.emi.emi.api.render.EmiTexture
import net.minecraft.network.chat.Component
class CobblemonEmiCategory<T: RecipeViewerRecipe>(val provider: CobblemonEmiProvider<T, *>): EmiRecipeCategory(provider.originalProvider.id,
EmiTexture(provider.originalProvider.getIconResource(), 0, 0,
provider.originalProvider.getIconDimensions().x,
provider.originalProvider.getIconDimensions().y,
provider.originalProvider.getIconDimensions().x,
provider.originalProvider.getIconDimensions().y,
provider.originalProvider.getIconDimensions().x,
provider.originalProvider.getIconDimensions().y
)
) {
override fun getName(): Component = provider.originalProvider.getName()
}
@@ -0,0 +1,36 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.integration.emi
import com.cobblemon.mod.common.integration.emi.brewing.EmiCobblemonBrewingRecipe
import com.cobblemon.mod.common.integration.recipeviewer.RecipeViewerCategoryProvider
import com.cobblemon.mod.common.integration.recipeviewer.brewing.CobblemonBrewingRecipeProvider
import dev.emi.emi.api.EmiEntrypoint
import dev.emi.emi.api.EmiPlugin
import dev.emi.emi.api.EmiRegistry
@EmiEntrypoint
class CobblemonEmiPlugin: EmiPlugin {
companion object {
val emiProviders = RecipeViewerCategoryProvider.categoriesProviders.map {
CobblemonEmiProvider(it)
}
}
override fun register(registry: EmiRegistry) {
emiProviders.forEach {
it.register(registry)
}
// Cobblemon Brewing Recipes
CobblemonBrewingRecipeProvider.getRecipes().forEach { entry ->
registry.addRecipe(EmiCobblemonBrewingRecipe(entry.value, entry.id))
}
}
}
@@ -0,0 +1,35 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.integration.emi
import com.cobblemon.mod.common.integration.recipeviewer.RecipeViewerCategoryProvider
import com.cobblemon.mod.common.integration.recipeviewer.RecipeViewerRecipe
import dev.emi.emi.api.EmiRegistry
import dev.emi.emi.api.stack.EmiStack
import net.minecraft.world.inventory.AbstractContainerMenu
class CobblemonEmiProvider<T: RecipeViewerRecipe, E: AbstractContainerMenu>(val originalProvider: RecipeViewerCategoryProvider<T, E>) {
val category = CobblemonEmiCategory(this)
fun register(registry: EmiRegistry) {
registry.addCategory(category)
originalProvider.getWorkstations().forEach {
registry.addWorkstation(category, EmiStack.of(it))
}
originalProvider.getRecipes().forEach {
registry.addRecipe(CobblemonEmiRecipe(this, it))
}
originalProvider.recipeHandler()?.let {
registry.addRecipeHandler(it.getMenuType(), CobblemonEmiRecipeHandler(this, it))
}
}
}
@@ -0,0 +1,55 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.integration.emi
import com.cobblemon.mod.common.integration.recipeviewer.RecipeViewerCategoryProvider
import com.cobblemon.mod.common.integration.recipeviewer.RecipeViewerRecipe
import dev.emi.emi.api.recipe.EmiRecipe
import dev.emi.emi.api.recipe.EmiRecipeCategory
import dev.emi.emi.api.stack.EmiIngredient
import dev.emi.emi.api.stack.EmiStack
import dev.emi.emi.api.widget.SlotWidget
import dev.emi.emi.api.widget.WidgetHolder
import net.minecraft.resources.ResourceLocation
import net.minecraft.world.item.crafting.Ingredient
class CobblemonEmiRecipe<T: RecipeViewerRecipe>(val provider: CobblemonEmiProvider<T, *>, val recipe: T): EmiRecipe {
override fun getCategory(): EmiRecipeCategory = provider.category
override fun getId(): ResourceLocation = recipe.getId()
override fun getDisplayWidth(): Int = provider.originalProvider.getWidth()
override fun getDisplayHeight(): Int = provider.originalProvider.getHeight()
private val ingredientHash = hashMapOf<Ingredient, EmiIngredient>() // This fixes the issue with some stuff
override fun getInputs(): List<EmiIngredient> {
return recipe.getInputs().map { ingredientHash.getOrPut(it) { EmiIngredient.of(it) } }
}
override fun getOutputs(): List<EmiStack?> {
return recipe.getOutputs().map { EmiStack.of(it) }
}
override fun addWidgets(widgets: WidgetHolder) {
widgets.add(CobblemonEmiSimpleWidget(provider, recipe))
recipe.getSlots().forEach {
val ingredient = ingredientHash.getOrPut(it.ingredient) { EmiIngredient.of(it.ingredient) }
val emiSlot = SlotWidget(ingredient, it.x - 1, it.y - 1) //X, Y coordinate system slightly offset
emiSlot.drawBack(false)
if (it.type == RecipeViewerCategoryProvider.SlotType.OUTPUT) emiSlot.recipeContext(this)
widgets.add(emiSlot)
}
}
override fun supportsRecipeTree(): Boolean = recipe.supportsRecipeTree()
override fun getCatalysts(): List<EmiIngredient> {
return recipe.getOptionalInputs().map { EmiIngredient.of(it) }
}
}
@@ -0,0 +1,31 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.integration.emi
import com.cobblemon.mod.common.integration.recipeviewer.RecipeViewerRecipeHandler
import dev.emi.emi.api.recipe.EmiRecipe
import dev.emi.emi.api.recipe.handler.StandardRecipeHandler
import net.minecraft.world.inventory.AbstractContainerMenu
import net.minecraft.world.inventory.Slot
class CobblemonEmiRecipeHandler<E: AbstractContainerMenu>(val provider: CobblemonEmiProvider<*, *>, val originalHandler: RecipeViewerRecipeHandler<E>): StandardRecipeHandler<E> {
override fun getCraftingSlots(menu: E): List<Slot> {
return originalHandler.getInputSlots(menu)
}
override fun getInputSources(menu: E): List<Slot> {
val theList = originalHandler.getInventorySlots(menu).toMutableList()
theList.addAll(originalHandler.getInputSlots(menu))
return theList
}
override fun supportsRecipe(recipe: EmiRecipe): Boolean {
return (recipe as? CobblemonEmiRecipe<*>)?.category == provider.category
}
}
@@ -0,0 +1,27 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.integration.emi
import com.cobblemon.mod.common.integration.recipeviewer.RecipeViewerRecipe
import dev.emi.emi.api.widget.Bounds
import dev.emi.emi.api.widget.Widget
import net.minecraft.client.Minecraft
import net.minecraft.client.gui.GuiGraphics
class CobblemonEmiSimpleWidget<T: RecipeViewerRecipe>(val provider: CobblemonEmiProvider<T, *>, val recipe: T): Widget() {
override fun getBounds(): Bounds {
val original = provider.originalProvider
return Bounds(0, 0, original.getWidth(), original.getHeight())
}
override fun render(draw: GuiGraphics, mouseX: Int, mouseY: Int, delta: Float) {
val realDelta = Minecraft.getInstance().timer.realtimeDeltaTicks
recipe.renderRecipe( draw, mouseX, mouseY, realDelta)
}
}
@@ -0,0 +1,64 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.integration.emi.brewing
import com.cobblemon.mod.common.item.crafting.brewingstand.BrewingStandRecipe
import dev.emi.emi.EmiPort
import dev.emi.emi.api.recipe.EmiRecipe
import dev.emi.emi.api.recipe.EmiRecipeCategory
import dev.emi.emi.api.recipe.VanillaEmiRecipeCategories
import dev.emi.emi.api.stack.EmiIngredient
import dev.emi.emi.api.stack.EmiStack
import dev.emi.emi.api.widget.WidgetHolder
import net.minecraft.client.gui.screens.inventory.tooltip.ClientTooltipComponent
import net.minecraft.resources.ResourceLocation
import net.minecraft.world.item.Items
class EmiCobblemonBrewingRecipe(val recipe: BrewingStandRecipe, val theId: ResourceLocation): EmiRecipe {
//I would have loved to use the base recipe one, but it just has 1 little caveat, input is an EmiStack, this is basically 99% recreation without that issue
private val input = EmiIngredient.of(recipe.input)
private val bottle = EmiIngredient.of(recipe.bottle)
private val output = EmiStack.of(recipe.result)
override fun getCategory(): EmiRecipeCategory = VanillaEmiRecipeCategories.BREWING
override fun getId(): ResourceLocation = theId
override fun getDisplayWidth(): Int = 120
override fun getDisplayHeight(): Int = 61
override fun getInputs(): List<EmiIngredient> {
return listOf(
bottle.copy().setAmount(3),
input
)
}
override fun getOutputs(): List<EmiStack> {
return listOf(
output.copy().setAmount(3)
)
}
override fun addWidgets(widgets: WidgetHolder) {
widgets.addTexture(BACKGROUND, 0, 0, 103, 61, 16, 14)
widgets.addAnimatedTexture(BACKGROUND, 81, 2, 9, 28, 176, 0, 1000 * 20, false, false, false).tooltip { mx, my ->
listOf(ClientTooltipComponent.create(EmiPort.ordered(EmiPort.translatable("emi.cooking.time", 20))))
}
widgets.addAnimatedTexture(BACKGROUND, 47, 0, 12, 29, 185, 0, 700, false, true, false)
widgets.addSlot(BLAZE_POWDER, 0, 2).drawBack(false)
widgets.addSlot(bottle, 39, 36).drawBack(false)
widgets.addSlot(input, 62, 2).drawBack(false)
widgets.addSlot(output, 85, 36).drawBack(false).recipeContext(this)
}
companion object {
private val BLAZE_POWDER = EmiStack.of(Items.BLAZE_POWDER)
private val BACKGROUND = EmiPort.id("minecraft", "textures/gui/container/brewing_stand.png")
}
}
@@ -0,0 +1,67 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.integration.jei
import com.cobblemon.mod.common.integration.recipeviewer.RecipeViewerCategoryProvider
import com.cobblemon.mod.common.integration.recipeviewer.RecipeViewerRecipe
import mezz.jei.api.gui.builder.IRecipeLayoutBuilder
import mezz.jei.api.gui.builder.IRecipeSlotBuilder
import mezz.jei.api.gui.drawable.IDrawable
import mezz.jei.api.gui.ingredient.IRecipeSlotsView
import mezz.jei.api.recipe.IFocusGroup
import mezz.jei.api.recipe.RecipeIngredientRole
import mezz.jei.api.recipe.RecipeType
import mezz.jei.api.recipe.category.IRecipeCategory
import mezz.jei.api.registration.IRecipeCategoryRegistration
import net.minecraft.client.Minecraft
import net.minecraft.client.gui.GuiGraphics
import net.minecraft.network.chat.Component
class CobblemonJeiCategory<T: RecipeViewerRecipe>(private val registration: IRecipeCategoryRegistration, val categoryProvider: CobblemonJeiProvider<T>):
IRecipeCategory<T> {
private val icon: IDrawable
init {
val guiHelper = registration.jeiHelpers.guiHelper
val dimensions = categoryProvider.originalProvider.getIconDimensions()
icon = guiHelper.drawableBuilder(categoryProvider.originalProvider.getIconResource(), 0, 0,
dimensions.x, dimensions.y)
.setTextureSize(dimensions.x, dimensions.y)
.build()
}
override fun getIcon(): IDrawable = icon
override fun getRecipeType(): RecipeType<T> = categoryProvider.recipeType
override fun getTitle(): Component = categoryProvider.originalProvider.getName()
override fun getWidth(): Int = categoryProvider.originalProvider.getWidth()
override fun getHeight(): Int = categoryProvider.originalProvider.getHeight()
override fun setRecipe(builder: IRecipeLayoutBuilder, recipe: T, focuses: IFocusGroup) {
recipe.getSlots().forEach { slot ->
val jeiSlot: IRecipeSlotBuilder = builder.addSlot(when (slot.type) {
RecipeViewerCategoryProvider.SlotType.INPUT -> RecipeIngredientRole.INPUT
RecipeViewerCategoryProvider.SlotType.OUTPUT -> RecipeIngredientRole.OUTPUT
RecipeViewerCategoryProvider.SlotType.CATALYST -> RecipeIngredientRole.CATALYST
}, slot.x, slot.y)
jeiSlot.addIngredients(slot.ingredient)
}
}
override fun draw(
recipe: T,
recipeSlotsView: IRecipeSlotsView,
guiGraphics: GuiGraphics,
mouseX: Double,
mouseY: Double
) {
val delta = Minecraft.getInstance().timer.realtimeDeltaTicks
recipe.renderRecipe( guiGraphics, mouseX.toInt(), mouseY.toInt(), delta)
}
}
@@ -8,45 +8,54 @@
package com.cobblemon.mod.common.integration.jei
import com.cobblemon.mod.common.integration.jei.berry.BerryMutationProvider
import com.cobblemon.mod.common.integration.jei.brewing.BrewingStandJeiProvider
import com.cobblemon.mod.common.integration.jei.cooking.CampfirePotJeiProvider
import com.cobblemon.mod.common.integration.jei.brewing.JeiBrewingStandRecipe
import com.cobblemon.mod.common.integration.recipeviewer.RecipeViewerCategoryProvider
import com.cobblemon.mod.common.integration.recipeviewer.brewing.CobblemonBrewingRecipeProvider
import com.cobblemon.mod.common.util.cobblemonResource
import mezz.jei.api.IModPlugin
import mezz.jei.api.JeiPlugin
import mezz.jei.api.constants.RecipeTypes
import mezz.jei.api.registration.IGuiHandlerRegistration
import mezz.jei.api.registration.IRecipeCatalystRegistration
import mezz.jei.api.registration.IRecipeCategoryRegistration
import mezz.jei.api.registration.IRecipeRegistration
import mezz.jei.api.registration.IRecipeTransferRegistration
import mezz.jei.api.runtime.IJeiRuntime
import net.minecraft.resources.ResourceLocation
@JeiPlugin
class CobblemonJeiPlugin : IModPlugin {
private val jeiProviders: Set<CobblemonJeiProvider> = setOf(
BerryMutationProvider(),
CampfirePotJeiProvider(),
BrewingStandJeiProvider()
)
override fun getPluginUid(): ResourceLocation {
return ID
}
override fun registerCategories(registration: IRecipeCategoryRegistration) {
jeiProviders.forEach {
it.registerCategory(registration)
}
jeiProviders.forEach { it.registerCategory(registration) }
}
override fun registerRecipes(registration: IRecipeRegistration) {
jeiProviders.forEach {
it.registerRecipes(registration)
jeiProviders.forEach { it.registerRecipes(registration) }
// Cobblemon Brewing Recipes
val jeiRecipes = CobblemonBrewingRecipeProvider.getRecipes().map { entry ->
JeiBrewingStandRecipe(entry.value, entry.id)
}
registration.addRecipes(RecipeTypes.BREWING, jeiRecipes)
}
override fun registerRecipeCatalysts(registration: IRecipeCatalystRegistration) {
jeiProviders.forEach { it.registerRecipeCatalsysts(registration) }
}
override fun registerGuiHandlers(registration: IGuiHandlerRegistration) {
jeiProviders.forEach {
it.registerRecipeCatalsysts(registration)
it.registerGuiHandlers(registration)
}
}
override fun registerRecipeTransferHandlers(registration: IRecipeTransferRegistration) {
jeiProviders.forEach {
it.registerRecipeTransferHandlers(registration)
}
}
@@ -55,7 +64,19 @@ class CobblemonJeiPlugin : IModPlugin {
}
companion object {
private val jeiProviders = RecipeViewerCategoryProvider.categoriesProviders.map {
CobblemonJeiProvider(it)
}
var jeiRuntime: IJeiRuntime? = null
val ID = cobblemonResource("jei_plugin")
fun showTypes(id: ResourceLocation) {
val jeiProvider = jeiProviders.firstOrNull { it.originalProvider.id == id } ?: return
jeiRuntime?.recipesGui?.showTypes(
listOf(jeiProvider.recipeType)
)
}
}
}
@@ -8,15 +8,38 @@
package com.cobblemon.mod.common.integration.jei
import com.cobblemon.mod.common.integration.recipeviewer.RecipeViewerCategoryProvider
import com.cobblemon.mod.common.integration.recipeviewer.RecipeViewerRecipe
import mezz.jei.api.recipe.RecipeType
import mezz.jei.api.registration.IGuiHandlerRegistration
import mezz.jei.api.registration.IRecipeCatalystRegistration
import mezz.jei.api.registration.IRecipeCategoryRegistration
import mezz.jei.api.registration.IRecipeRegistration
import mezz.jei.api.registration.IRecipeTransferRegistration
/**
*
*/
interface CobblemonJeiProvider {
fun registerCategory(registration: IRecipeCategoryRegistration)
fun registerRecipes(registration: IRecipeRegistration)
fun registerRecipeCatalsysts(registration: IRecipeCatalystRegistration)
}
class CobblemonJeiProvider<T: RecipeViewerRecipe>(val originalProvider: RecipeViewerCategoryProvider<T, *>) {
val recipeType: RecipeType<T> =
RecipeType<T>.create(originalProvider.id.namespace, originalProvider.id.path, originalProvider.recipeClass)
fun registerCategory(registration: IRecipeCategoryRegistration) {
registration.addRecipeCategories(CobblemonJeiCategory(registration, this))
}
fun registerRecipes(registration: IRecipeRegistration) {
registration.addRecipes(recipeType, originalProvider.getRecipes())
}
fun registerRecipeCatalsysts(registration: IRecipeCatalystRegistration) {
originalProvider.getWorkstations().forEach {
registration.addRecipeCatalyst(it, recipeType)
}
}
fun registerGuiHandlers(registration: IGuiHandlerRegistration) {
originalProvider.getClickArea()?.let { registration.addRecipeClickArea(it.containerScreen, it.x, it.y, it.width, it.height, recipeType) }
}
fun registerRecipeTransferHandlers(registration: IRecipeTransferRegistration) {
originalProvider.recipeHandler()?.let { registration.addRecipeTransferHandler(CobblemonJeiRecipeHandler(this, it)) }
}
}
@@ -0,0 +1,36 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.integration.jei
import com.cobblemon.mod.common.integration.recipeviewer.RecipeViewerRecipe
import com.cobblemon.mod.common.integration.recipeviewer.RecipeViewerRecipeHandler
import mezz.jei.api.recipe.RecipeType
import mezz.jei.api.recipe.transfer.IRecipeTransferInfo
import net.minecraft.world.inventory.AbstractContainerMenu
import net.minecraft.world.inventory.MenuType
import net.minecraft.world.inventory.Slot
import java.util.Optional
class CobblemonJeiRecipeHandler<E: AbstractContainerMenu, R: RecipeViewerRecipe>(val provider: CobblemonJeiProvider<R>, val originalHandler: RecipeViewerRecipeHandler<E>): IRecipeTransferInfo<E, R> {
override fun getContainerClass(): Class<out E> = originalHandler.getMenuClass()
override fun getMenuType(): Optional<MenuType<E>> = Optional.of(originalHandler.getMenuType())
override fun getRecipeType(): RecipeType<R> = provider.recipeType
override fun getRecipeSlots(container: E, recipe: R): List<Slot> {
return originalHandler.getInputSlots(container)
}
override fun getInventorySlots(container: E, recipe: R): List<Slot> {
return originalHandler.getInventorySlots(container)
}
override fun canHandle(container: E, recipe: R): Boolean {
return true
}
}
@@ -1,42 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.integration.jei.berry
import com.cobblemon.mod.common.CobblemonItems
import com.cobblemon.mod.common.integration.jei.CobblemonJeiProvider
import com.cobblemon.mod.common.item.berry.BerryItem
import mezz.jei.api.registration.IRecipeCatalystRegistration
import mezz.jei.api.registration.IRecipeCategoryRegistration
import mezz.jei.api.registration.IRecipeRegistration
class BerryMutationProvider : CobblemonJeiProvider {
override fun registerCategory(registration: IRecipeCategoryRegistration) {
registration.addRecipeCategories(BerryRecipeCategory(registration))
}
override fun registerRecipes(registration: IRecipeRegistration) {
val berryList = CobblemonItems.berries().map { it.value }
val berryMutations = mutableSetOf<Triple<BerryItem, BerryItem, BerryItem>>()
berryList.forEach {berry ->
for (mut in berry.berry()?.mutations?.entries ?: emptySet()) {
val berryTwo = CobblemonItems.berries()[mut.key] ?: continue
val berryThree = CobblemonItems.berries()[mut.value] ?: continue
val mutation = Triple(berry, berryTwo, berryThree)
val altMutation = Triple(berryTwo, berry, berryThree)
if (!(berryMutations.contains(mutation) || berryMutations.contains(altMutation))) {
berryMutations.add(mutation)
}
}
}
val berryMutationRecipes = berryMutations.map { BerryMutationRecipe(it.first, it.second, it.third) }
registration.addRecipes(BerryRecipeCategory.RECIPE_TYPE, berryMutationRecipes)
}
override fun registerRecipeCatalsysts(registration: IRecipeCatalystRegistration) { }
}
@@ -1,20 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.integration.jei.berry
import com.cobblemon.mod.common.item.berry.BerryItem
//Dont make these ItemStacks, they do not have consistent hash codes, breaks stuff
data class BerryMutationRecipe(
val berryOne: BerryItem,
val berryTwo: BerryItem,
val berryResult: BerryItem
) {
}
@@ -1,61 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.integration.jei.berry
import com.cobblemon.mod.common.CobblemonItems
import com.cobblemon.mod.common.util.cobblemonResource
import mezz.jei.api.constants.ModIds
import mezz.jei.api.gui.builder.IRecipeLayoutBuilder
import mezz.jei.api.gui.drawable.IDrawable
import mezz.jei.api.recipe.IFocusGroup
import mezz.jei.api.recipe.RecipeIngredientRole
import mezz.jei.api.recipe.RecipeType
import mezz.jei.api.recipe.category.IRecipeCategory
import mezz.jei.api.registration.IRecipeCategoryRegistration
import net.minecraft.network.chat.Component
import net.minecraft.world.item.crafting.Ingredient
class BerryRecipeCategory(private val registration: IRecipeCategoryRegistration) : IRecipeCategory<BerryMutationRecipe> {
private var background: IDrawable
private var icon: IDrawable
init {
val guiHelper = registration.jeiHelpers.guiHelper
background = guiHelper.createDrawable(GUI_TEXTURE_ID, 0, 0, WIDTH, HEIGHT)
icon = guiHelper.createDrawableItemStack(CobblemonItems.SURPRISE_MULCH.defaultInstance)
}
override fun getRecipeType(): RecipeType<BerryMutationRecipe> {
return RECIPE_TYPE
}
override fun getTitle(): Component {
return Component.literal("Berry Mutation")
}
override fun getBackground(): IDrawable {
return background
}
override fun getIcon(): IDrawable {
return icon
}
override fun setRecipe(p0: IRecipeLayoutBuilder, p1: BerryMutationRecipe, p2: IFocusGroup) {
//These magic numbers are where the items should be positioned on the gui texture
p0.addSlot(RecipeIngredientRole.INPUT, 1, 1).addIngredients(Ingredient.of(p1.berryOne.defaultInstance))
p0.addSlot(RecipeIngredientRole.INPUT, 50, 1).addIngredients(Ingredient.of(p1.berryTwo.defaultInstance))
p0.addSlot(RecipeIngredientRole.OUTPUT, 108, 1).addIngredients(Ingredient.of(p1.berryResult.defaultInstance))
}
companion object {
val RECIPE_TYPE = RecipeType.create("cobblemon", "berry_recipe", BerryMutationRecipe::class.java)!!
val GUI_TEXTURE_ID = cobblemonResource("textures/gui/jei/berry_mutation.png")
const val WIDTH = 124
const val HEIGHT = 17
}
}
@@ -1,37 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.integration.jei.brewing
import com.cobblemon.mod.common.CobblemonRecipeTypes
import com.cobblemon.mod.common.integration.jei.CobblemonJeiProvider
import mezz.jei.api.constants.RecipeTypes
import mezz.jei.api.registration.IRecipeCatalystRegistration
import mezz.jei.api.registration.IRecipeCategoryRegistration
import mezz.jei.api.registration.IRecipeRegistration
import net.minecraft.client.Minecraft
class BrewingStandJeiProvider : CobblemonJeiProvider {
override fun registerCategory(registration: IRecipeCategoryRegistration) {
}
override fun registerRecipes(registration: IRecipeRegistration) {
val recipeManger =
Minecraft.getInstance().level?.recipeManager ?: throw IllegalStateException("Recipe manager not found")
val allBrewingRecipes = recipeManger.getAllRecipesFor(CobblemonRecipeTypes.BREWING_STAND)
val jeiRecipes = allBrewingRecipes.map { entry ->
JeiBrewingStandRecipe(entry.value, entry.id)
}
registration.addRecipes(RecipeTypes.BREWING, jeiRecipes)
}
override fun registerRecipeCatalsysts(registration: IRecipeCatalystRegistration) { }
}
@@ -1,39 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.integration.jei.cooking
import com.cobblemon.mod.common.CobblemonItems
import com.cobblemon.mod.common.CobblemonRecipeTypes
import com.cobblemon.mod.common.integration.jei.CobblemonJeiProvider
import mezz.jei.api.registration.IRecipeCatalystRegistration
import mezz.jei.api.registration.IRecipeCategoryRegistration
import mezz.jei.api.registration.IRecipeRegistration
import net.minecraft.client.Minecraft
class CampfirePotJeiProvider : CobblemonJeiProvider {
override fun registerCategory(registration: IRecipeCategoryRegistration) {
registration.addRecipeCategories(CampfirePotRecipeCategory(registration))
}
override fun registerRecipes(registration: IRecipeRegistration) {
val recipeManger = Minecraft.getInstance().level?.recipeManager ?: throw IllegalStateException("Recipe manager not found")
val shapelessRecipes = recipeManger.getAllRecipesFor(CobblemonRecipeTypes.COOKING_POT_SHAPELESS).map { it.value }
val cookingRecipes = recipeManger.getAllRecipesFor(CobblemonRecipeTypes.COOKING_POT_COOKING).map { it.value }
registration.addRecipes(CampfirePotRecipeCategory.RECIPE_TYPE, shapelessRecipes)
registration.addRecipes(CampfirePotRecipeCategory.RECIPE_TYPE, cookingRecipes)
}
override fun registerRecipeCatalsysts(registration: IRecipeCatalystRegistration) {
CobblemonItems.campfire_pots.forEach {
registration.addRecipeCatalyst(it, CampfirePotRecipeCategory.RECIPE_TYPE)
}
}
}
@@ -1,122 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.integration.jei.cooking
import com.cobblemon.mod.common.CobblemonItems
import com.cobblemon.mod.common.api.berry.Berries
import com.cobblemon.mod.common.api.cooking.Seasonings
import com.cobblemon.mod.common.block.entity.CampfireBlockEntity
import com.cobblemon.mod.common.block.entity.CampfireBlockEntity.Companion.CRAFTING_GRID_WIDTH
import com.cobblemon.mod.common.block.entity.CampfireBlockEntity.Companion.SEASONING_SLOTS
import com.cobblemon.mod.common.client.gui.cookingpot.CookingPotScreen.Companion.COOK_PROGRESS_HEIGHT
import com.cobblemon.mod.common.client.gui.cookingpot.CookingPotScreen.Companion.COOK_PROGRESS_SPRITE
import com.cobblemon.mod.common.client.gui.cookingpot.CookingPotScreen.Companion.COOK_PROGRESS_WIDTH
import com.cobblemon.mod.common.item.crafting.CookingPotRecipeBase
import com.cobblemon.mod.common.util.cobblemonResource
import com.cobblemon.mod.common.util.lang
import mezz.jei.api.constants.VanillaTypes
import mezz.jei.api.gui.builder.IRecipeLayoutBuilder
import mezz.jei.api.gui.drawable.IDrawable
import mezz.jei.api.gui.drawable.IDrawableAnimated
import mezz.jei.api.gui.ingredient.IRecipeSlotsView
import mezz.jei.api.helpers.IGuiHelper
import mezz.jei.api.recipe.IFocusGroup
import mezz.jei.api.recipe.RecipeIngredientRole
import mezz.jei.api.recipe.RecipeType
import mezz.jei.api.recipe.category.IRecipeCategory
import mezz.jei.api.registration.IRecipeCategoryRegistration
import net.minecraft.client.Minecraft
import net.minecraft.client.gui.GuiGraphics
import net.minecraft.core.registries.BuiltInRegistries
import net.minecraft.network.chat.Component
import net.minecraft.resources.ResourceLocation
import net.minecraft.world.item.crafting.Ingredient
class CampfirePotRecipeCategory(registration: IRecipeCategoryRegistration) : IRecipeCategory<CookingPotRecipeBase> {
companion object {
val RECIPE_TYPE = RecipeType.create("cobblemon", "campfire_pot_recipe", CookingPotRecipeBase::class.java)!!
val CAMPFIRE_POT_TEXTURE: ResourceLocation = cobblemonResource("textures/gui/jei/campfire_pot.png")
const val TEXTURE_WIDTH = 146
const val TEXTURE_HEIGHT = 59
const val WIDTH = 146
const val HEIGHT = 59
val EXAMPLE_SEASONINGS = BuiltInRegistries.ITEM.map { it.defaultInstance }.filter { Seasonings.isSeasoning(it) }
}
val guiHelper: IGuiHelper = registration.jeiHelpers.guiHelper
val campfirePotBackground: IDrawable = guiHelper.drawableBuilder(CAMPFIRE_POT_TEXTURE, 0, 0, WIDTH, HEIGHT)
.setTextureSize(TEXTURE_WIDTH, TEXTURE_HEIGHT)
.build()
val cookProgressSprite: IDrawableAnimated =
guiHelper.drawableBuilder(COOK_PROGRESS_SPRITE, 0, 0, COOK_PROGRESS_WIDTH, COOK_PROGRESS_HEIGHT)
.setTextureSize(22, COOK_PROGRESS_HEIGHT)
.buildAnimated(CampfireBlockEntity.COOKING_TOTAL_TIME, IDrawableAnimated.StartDirection.LEFT, false)
val campfirePotIcon: IDrawable = guiHelper.createDrawableItemStack(CobblemonItems.CAMPFIRE_POT_BLACK.defaultInstance)
override fun getRecipeType(): RecipeType<CookingPotRecipeBase?>? = RECIPE_TYPE
override fun getTitle(): Component? = lang("container.campfire_pot")
override fun getBackground(): IDrawable? = campfirePotBackground
override fun getIcon(): IDrawable? = campfirePotIcon
override fun setRecipe(
builder: IRecipeLayoutBuilder,
recipe: CookingPotRecipeBase,
focuses: IFocusGroup
) {
recipe.ingredients.forEachIndexed { index, ingredient ->
val column = index / CRAFTING_GRID_WIDTH
val row = index % CRAFTING_GRID_WIDTH
val x = 16 + row * 18
val y = 1 + column * 18
builder.addSlot(RecipeIngredientRole.INPUT, x, y).addIngredients(ingredient)
}
if (recipe.seasoningProcessors.isNotEmpty()) {
val processedSeasonings = EXAMPLE_SEASONINGS.filter { item ->
var valid = true
if (!item.`is`(recipe.seasoningTag)) return@filter false
recipe.seasoningProcessors.forEach {
if (!it.consumesItem(item)) {
valid = false
return@forEach
}
}
valid
}
for ((index, _) in SEASONING_SLOTS.withIndex()) {
val x = 93 + index * 18
val y = 1
builder.addSlot(RecipeIngredientRole.INPUT, x, y)
.addIngredients(VanillaTypes.ITEM_STACK, processedSeasonings.shuffled())
}
}
val registryAccess = Minecraft.getInstance().level?.registryAccess() ?: throw IllegalStateException("Registry access not found")
builder.addSlot(RecipeIngredientRole.OUTPUT, 111, 38).addIngredients(Ingredient.of(recipe.getResultItem(registryAccess)))
}
override fun draw(
recipe: CookingPotRecipeBase,
recipeSlotsView: IRecipeSlotsView,
guiGraphics: GuiGraphics,
mouseX: Double,
mouseY: Double
) {
super.draw(recipe, recipeSlotsView, guiGraphics, mouseX, mouseY)
cookProgressSprite.draw(guiGraphics, 79, 22)
}
}
@@ -0,0 +1,20 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.integration.recipeviewer
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen
import net.minecraft.world.inventory.AbstractContainerMenu
data class RecipeClickArea(
val containerScreen: Class<AbstractContainerScreen<AbstractContainerMenu>>,
val x: Int,
val y: Int,
val width: Int,
val height: Int
)
@@ -0,0 +1,58 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.integration.recipeviewer
import com.cobblemon.mod.common.integration.recipeviewer.berry.BerryMutationProvider
import com.cobblemon.mod.common.integration.recipeviewer.cooking.CampfirePotViewerProvider
import net.minecraft.network.chat.Component
import net.minecraft.resources.ResourceLocation
import net.minecraft.world.inventory.AbstractContainerMenu
import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.crafting.Ingredient
import org.joml.Vector2i
interface RecipeViewerCategoryProvider<T: RecipeViewerRecipe, E: AbstractContainerMenu> {
companion object {
val categoriesProviders: Set<RecipeViewerCategoryProvider<*,*>> = setOf(
BerryMutationProvider(),
CampfirePotViewerProvider()
)
}
val recipeClass: Class<T>
val id: ResourceLocation
fun getName(): Component = Component.translatable("${id.namespace}.recipeviewer.category.${id.path}")
fun getIconResource(): ResourceLocation
fun getIconDimensions(): Vector2i
fun getRecipes(): List<T>
fun getWorkstations(): List<ItemStack>
fun getHeight(): Int
fun getWidth(): Int
fun getClickArea(): RecipeClickArea? = null
fun recipeHandler(): RecipeViewerRecipeHandler<E>? = null
data class Slot(
val x: Int,
val y: Int,
val type: SlotType,
val ingredient: Ingredient
)
enum class SlotType {
INPUT,
OUTPUT,
CATALYST
}
}
@@ -0,0 +1,30 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.integration.recipeviewer
import com.cobblemon.mod.common.integration.recipeviewer.RecipeViewerCategoryProvider.Slot
import net.minecraft.client.gui.GuiGraphics
import net.minecraft.resources.ResourceLocation
import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.crafting.Ingredient
interface RecipeViewerRecipe {
fun getId(): ResourceLocation
fun getInputs(): List<Ingredient>
fun getOutputs(): List<ItemStack>
fun getOptionalInputs(): List<Ingredient> = emptyList()
fun supportsRecipeTree(): Boolean = true
fun renderRecipe(context: GuiGraphics, mouseX: Int, mouseY: Int, delta: Float) {}
fun getSlots(): List<Slot>
}
@@ -0,0 +1,21 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.integration.recipeviewer
import net.minecraft.world.inventory.AbstractContainerMenu
import net.minecraft.world.inventory.MenuType
import net.minecraft.world.inventory.Slot
interface RecipeViewerRecipeHandler<E: AbstractContainerMenu> {
fun getInputSlots(menu: E): List<Slot> //Returns crafting slots
fun getInventorySlots(menu: E): List<Slot>
fun getMenuClass(): Class<E>
fun getMenuType(): MenuType<E>
}
@@ -0,0 +1,58 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.integration.recipeviewer.berry
import com.cobblemon.mod.common.CobblemonItems
import com.cobblemon.mod.common.block.campfirepot.CookingPotMenu
import com.cobblemon.mod.common.integration.recipeviewer.RecipeViewerCategoryProvider
import com.cobblemon.mod.common.item.berry.BerryItem
import com.cobblemon.mod.common.util.cobblemonResource
import net.minecraft.resources.ResourceLocation
import net.minecraft.world.item.ItemStack
import org.joml.Vector2i
class BerryMutationProvider: RecipeViewerCategoryProvider<BerryMutationRecipe, CookingPotMenu> {
override val id = ID
override val recipeClass = BerryMutationRecipe::class.java
override fun getIconResource(): ResourceLocation = cobblemonResource("textures/item/mulches/surprise_mulch.png")
override fun getIconDimensions(): Vector2i = Vector2i(16, 16)
override fun getWidth(): Int = WIDTH
override fun getHeight(): Int = HEIGHT
override fun getRecipes(): List<BerryMutationRecipe> {
val berryList = CobblemonItems.berries().map { it.value }
val berryMutations = mutableSetOf<Triple<BerryItem, BerryItem, BerryItem>>()
berryList.forEach {berry ->
for (mut in berry.berry()?.mutations?.entries ?: emptySet()) {
val berryTwo = CobblemonItems.berries()[mut.key] ?: continue
val berryThree = CobblemonItems.berries()[mut.value] ?: continue
val mutation = Triple(berry, berryTwo, berryThree)
val altMutation = Triple(berryTwo, berry, berryThree)
if (!(berryMutations.contains(mutation) || berryMutations.contains(altMutation))) {
berryMutations.add(mutation)
}
}
}
return berryMutations.map { values ->
BerryMutationRecipe(values.first, values.second, values.third) }
}
override fun getWorkstations(): List<ItemStack> {
return emptyList()
}
companion object {
private const val WIDTH = 125
private const val HEIGHT = 18
val ID = cobblemonResource("berry_recipe")
}
}
@@ -0,0 +1,70 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.integration.recipeviewer.berry
import com.cobblemon.mod.common.api.gui.blitk
import com.cobblemon.mod.common.integration.recipeviewer.RecipeViewerCategoryProvider
import com.cobblemon.mod.common.integration.recipeviewer.RecipeViewerRecipe
import com.cobblemon.mod.common.item.berry.BerryItem
import com.cobblemon.mod.common.util.cobblemonResource
import net.minecraft.client.gui.GuiGraphics
import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.crafting.Ingredient
//Dont make these ItemStacks, they do not have consistent hash codes, breaks stuff
data class BerryMutationRecipe(
val berryOne: BerryItem,
val berryTwo: BerryItem,
val berryResult: BerryItem
): RecipeViewerRecipe {
companion object {
val BACKGROUND = cobblemonResource("textures/gui/recipeviewer/berry_mutation.png")
}
override fun getId() = cobblemonResource("/berry_mutation_" +
"${berryIdentifier(berryResult)}_${berryIdentifier(berryOne)}_${berryIdentifier(berryTwo)}")
override fun getInputs(): List<Ingredient> {
return listOf(Ingredient.of(berryOne), Ingredient.of(berryTwo))
}
override fun getOutputs(): List<ItemStack> {
return listOf(berryResult.defaultInstance)
}
override fun supportsRecipeTree(): Boolean = false
override fun renderRecipe(
context: GuiGraphics,
mouseX: Int,
mouseY: Int,
delta: Float
) {
blitk(
matrixStack = context.pose(),
texture = BACKGROUND,
x = 0,
y = 0,
width = 125,
height = 18
)
}
override fun getSlots(): List<RecipeViewerCategoryProvider.Slot> {
val list = mutableListOf<RecipeViewerCategoryProvider.Slot>()
list.add(RecipeViewerCategoryProvider.Slot(1, 1, RecipeViewerCategoryProvider.SlotType.INPUT, Ingredient.of(berryOne)))
list.add(RecipeViewerCategoryProvider.Slot(50, 1, RecipeViewerCategoryProvider.SlotType.INPUT, Ingredient.of(berryTwo)))
list.add(RecipeViewerCategoryProvider.Slot(108, 1, RecipeViewerCategoryProvider.SlotType.OUTPUT, Ingredient.of(berryResult)))
return list
}
private fun berryIdentifier(berry: BerryItem): String {
return berry.berry()?.identifier?.path ?: ""
}
}
@@ -0,0 +1,23 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.integration.recipeviewer.brewing
import com.cobblemon.mod.common.CobblemonRecipeTypes
import com.cobblemon.mod.common.item.crafting.brewingstand.BrewingStandRecipe
import net.minecraft.client.Minecraft
import net.minecraft.world.item.crafting.RecipeHolder
object CobblemonBrewingRecipeProvider { // This has custom implementation
fun getRecipes(): List<RecipeHolder<BrewingStandRecipe>> {
val recipeManger =
Minecraft.getInstance().level?.recipeManager ?: throw IllegalStateException("Recipe manager not found")
return recipeManger.getAllRecipesFor(CobblemonRecipeTypes.BREWING_STAND)
}
}
@@ -0,0 +1,65 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.integration.recipeviewer.cooking
import com.cobblemon.mod.common.CobblemonItems
import com.cobblemon.mod.common.CobblemonRecipeTypes
import com.cobblemon.mod.common.block.campfirepot.CookingPotMenu
import com.cobblemon.mod.common.client.gui.cookingpot.CookingPotScreen
import com.cobblemon.mod.common.integration.recipeviewer.RecipeClickArea
import com.cobblemon.mod.common.integration.recipeviewer.RecipeViewerCategoryProvider
import com.cobblemon.mod.common.integration.recipeviewer.RecipeViewerRecipeHandler
import com.cobblemon.mod.common.util.cobblemonResource
import net.minecraft.client.Minecraft
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen
import net.minecraft.resources.ResourceLocation
import net.minecraft.world.inventory.AbstractContainerMenu
import net.minecraft.world.item.ItemStack
import org.joml.Vector2i
class CampfirePotViewerProvider: RecipeViewerCategoryProvider<CampfirePotViewerRecipe, CookingPotMenu> {
override val id = ID
override val recipeClass = CampfirePotViewerRecipe::class.java
override fun getIconResource(): ResourceLocation = cobblemonResource("textures/item/campfire_pots/campfire_pot_red.png")
override fun getIconDimensions(): Vector2i = Vector2i(16, 16)
override fun getWidth(): Int = WIDTH
override fun getHeight(): Int = HEIGHT
override fun getRecipes(): List<CampfirePotViewerRecipe> {
val recipeManger = Minecraft.getInstance().level?.recipeManager ?: throw IllegalStateException("Recipe manager not found")
val recipeList = mutableListOf<CampfirePotViewerRecipe>()
recipeManger.getAllRecipesFor(CobblemonRecipeTypes.COOKING_POT_SHAPELESS).forEach {
recipeList.add(CampfirePotViewerRecipe(it.id, it.value))
}
recipeManger.getAllRecipesFor(CobblemonRecipeTypes.COOKING_POT_COOKING).forEach {
recipeList.add(CampfirePotViewerRecipe(it.id, it.value))
}
return recipeList
}
override fun getWorkstations(): List<ItemStack> {
return CobblemonItems.campfire_pots.map { it.defaultInstance }
}
override fun getClickArea(): RecipeClickArea = RecipeClickArea(CookingPotScreen::class.java as Class<AbstractContainerScreen<AbstractContainerMenu>>, 96, 39 ,
CookingPotScreen.COOK_PROGRESS_WIDTH, CookingPotScreen.COOK_PROGRESS_HEIGHT)
override fun recipeHandler(): RecipeViewerRecipeHandler<CookingPotMenu> = CampfirePotViewerRecipeHandler()
companion object {
private const val WIDTH = 146
private const val HEIGHT = 59
val ID = cobblemonResource("cooking_pot_recipe")
}
}
@@ -0,0 +1,103 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.integration.recipeviewer.cooking
import com.cobblemon.mod.common.api.cooking.Seasonings
import com.cobblemon.mod.common.api.gui.blitk
import com.cobblemon.mod.common.integration.recipeviewer.RecipeViewerCategoryProvider
import com.cobblemon.mod.common.integration.recipeviewer.RecipeViewerRecipe
import com.cobblemon.mod.common.item.crafting.CookingPotRecipeBase
import net.minecraft.client.Minecraft
import net.minecraft.core.registries.BuiltInRegistries
import net.minecraft.resources.ResourceLocation
import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.crafting.Ingredient
import com.cobblemon.mod.common.block.entity.CampfireBlockEntity.Companion.CRAFTING_GRID_WIDTH
import com.cobblemon.mod.common.block.entity.CampfireBlockEntity.Companion.SEASONING_SLOTS
import com.cobblemon.mod.common.util.cobblemonResource
import net.minecraft.client.gui.GuiGraphics
class CampfirePotViewerRecipe(val theId: ResourceLocation, val originalRecipe: CookingPotRecipeBase): RecipeViewerRecipe {
companion object {
val EXAMPLE_SEASONINGS = BuiltInRegistries.ITEM.map { it.defaultInstance }.filter { Seasonings.isSeasoning(it) }
val BACKGROUND = cobblemonResource("textures/gui/recipeviewer/campfire_pot.png")
}
override fun getId(): ResourceLocation = theId
override fun getInputs(): List<Ingredient> {
return originalRecipe.ingredients
}
override fun getOutputs(): List<ItemStack> {
val registryAccess = Minecraft.getInstance().level?.registryAccess() ?: throw IllegalStateException("Registry access not found")
return listOf(originalRecipe.getResultItem(registryAccess))
}
override fun getOptionalInputs(): List<Ingredient> {
return listOf(Ingredient.of(*generateProperSeasoningList().toTypedArray()))
}
override fun getSlots(): List<RecipeViewerCategoryProvider.Slot> {
val registryAccess = Minecraft.getInstance().level?.registryAccess() ?: throw IllegalStateException("Registry access not found")
val slots = mutableListOf<RecipeViewerCategoryProvider.Slot>()
originalRecipe.ingredients.forEachIndexed { index, ingredient ->
val row = index / CRAFTING_GRID_WIDTH
val column = index % CRAFTING_GRID_WIDTH
slots.add(RecipeViewerCategoryProvider.Slot(16 + column * 18, 1 + row * 18,
RecipeViewerCategoryProvider.SlotType.INPUT, ingredient))
}
if (originalRecipe.seasoningProcessors.isNotEmpty()) {
val processedSeasonings = generateProperSeasoningList()
for ((index, _) in SEASONING_SLOTS.withIndex()) {
val x = 93 + index * 18
val y = 1
slots.add(RecipeViewerCategoryProvider.Slot(x, y,
RecipeViewerCategoryProvider.SlotType.CATALYST, Ingredient.of(*processedSeasonings.shuffled().toTypedArray())))
}
}
slots.add(RecipeViewerCategoryProvider.Slot(111, 38,
RecipeViewerCategoryProvider.SlotType.OUTPUT, Ingredient.of(originalRecipe.getResultItem(registryAccess))))
return slots
}
override fun renderRecipe(context: GuiGraphics, mouseX: Int, mouseY: Int, delta: Float) {
blitk(
matrixStack = context.pose(),
texture = BACKGROUND,
x = 0,
y = 0,
width = 146,
height = 59
)
}
private fun generateProperSeasoningList(): List<ItemStack> {
if (originalRecipe.seasoningProcessors.isEmpty()) return emptyList()
val processedSeasonings = EXAMPLE_SEASONINGS.filter { item ->
var valid = true
if (!item.`is`(originalRecipe.seasoningTag)) return@filter false
originalRecipe.seasoningProcessors.forEach {
if (!it.consumesItem(item)) {
valid = false
return@forEach
}
}
valid
}
return processedSeasonings
}
}
@@ -0,0 +1,29 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.integration.recipeviewer.cooking
import com.cobblemon.mod.common.CobblemonMenuType
import com.cobblemon.mod.common.block.campfirepot.CookingPotMenu
import com.cobblemon.mod.common.block.entity.CampfireBlockEntity
import com.cobblemon.mod.common.integration.recipeviewer.RecipeViewerRecipeHandler
import net.minecraft.world.inventory.MenuType
import net.minecraft.world.inventory.Slot
class CampfirePotViewerRecipeHandler: RecipeViewerRecipeHandler<CookingPotMenu> {
override fun getInputSlots(menu: CookingPotMenu): List<Slot> {
return menu.slots.filter { it.index in CampfireBlockEntity.CRAFTING_GRID_SLOTS }
}
override fun getInventorySlots(menu: CookingPotMenu): List<Slot> {
return menu.slots.filter { it.index in CampfireBlockEntity.PLAYER_INVENTORY_SLOTS || it.index in CampfireBlockEntity.PLAYER_HOTBAR_SLOTS }
}
override fun getMenuClass(): Class<CookingPotMenu> = CookingPotMenu::class.java
override fun getMenuType(): MenuType<CookingPotMenu> = CobblemonMenuType.COOKING_POT
}
@@ -0,0 +1,61 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.integration.rei
import com.cobblemon.mod.common.integration.recipeviewer.RecipeViewerCategoryProvider
import com.cobblemon.mod.common.integration.recipeviewer.RecipeViewerRecipe
import me.shedaniel.math.Point
import me.shedaniel.math.Rectangle
import me.shedaniel.rei.api.client.gui.Renderer
import me.shedaniel.rei.api.client.gui.widgets.Widget
import me.shedaniel.rei.api.client.gui.widgets.Widgets
import me.shedaniel.rei.api.client.registry.display.DisplayCategory
import me.shedaniel.rei.api.common.category.CategoryIdentifier
import me.shedaniel.rei.api.common.util.EntryIngredients
import net.minecraft.network.chat.Component
class CobblemonReiCategory<T: RecipeViewerRecipe>(val provider: CobblemonReiProvider<T, *>): DisplayCategory<CobblemonReiDisplay<T>> {
companion object {
private const val PADDING = 4
}
val theIcon = CobblemonReiIcon(provider.originalProvider.getIconResource(), provider.originalProvider.getIconDimensions().x, provider.originalProvider.getIconDimensions().y)
override fun getCategoryIdentifier(): CategoryIdentifier<CobblemonReiDisplay<T>> = provider.categoryIdentifier
override fun getIcon(): Renderer = theIcon
override fun getTitle(): Component = provider.originalProvider.getName()
// Add Padding so insides fit perfectly
override fun getDisplayWidth(display: CobblemonReiDisplay<T>): Int = provider.originalProvider.getWidth() + PADDING * 2
override fun getDisplayHeight(): Int = provider.originalProvider.getHeight() + PADDING * 2
override fun setupDisplay(display: CobblemonReiDisplay<T>, bounds: Rectangle): List<Widget> {
val widgets = mutableListOf<Widget>()
val startX = bounds.minX + PADDING
val startY = bounds.minY + PADDING
widgets.add(Widgets.createCategoryBase(bounds))
widgets.add(CobblemonReiSimpleWidget(startX, startY, display.recipe))
display.recipe.getSlots().forEach { slot ->
val reiSlot = Widgets.createSlot(Point(startX + slot.x, startY + slot.y))
reiSlot.entries(EntryIngredients.ofIngredient(slot.ingredient))
reiSlot.disableBackground()
when (slot.type) {
RecipeViewerCategoryProvider.SlotType.INPUT -> reiSlot.markInput()
RecipeViewerCategoryProvider.SlotType.OUTPUT -> reiSlot.markOutput()
else -> {}
}
widgets.add(reiSlot)
}
return widgets
}
}
@@ -0,0 +1,55 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.integration.rei
import com.cobblemon.mod.common.integration.recipeviewer.RecipeViewerCategoryProvider
import com.cobblemon.mod.common.integration.recipeviewer.brewing.CobblemonBrewingRecipeProvider
import com.cobblemon.mod.common.integration.rei.brewing.ReiCobblemonBrewingDisplay
import me.shedaniel.rei.api.client.plugins.REIClientPlugin
import me.shedaniel.rei.api.client.registry.category.CategoryRegistry
import me.shedaniel.rei.api.client.registry.display.DisplayRegistry
import me.shedaniel.rei.api.client.registry.screen.ScreenRegistry
import me.shedaniel.rei.api.client.registry.transfer.TransferHandlerRegistry
open class CobblemonReiClientPlugin: REIClientPlugin {
companion object {
private val reiProviders = RecipeViewerCategoryProvider.categoriesProviders.map {
CobblemonReiProvider(it)
}
}
override fun registerDisplays(registry: DisplayRegistry) {
reiProviders.forEach {
it.registerDisplay(registry)
}
// Cobblemon Brewing Recipes
CobblemonBrewingRecipeProvider.getRecipes().forEach {
registry.add(ReiCobblemonBrewingDisplay(it.value, it.id))
}
}
override fun registerCategories(registry: CategoryRegistry) {
reiProviders.forEach {
it.registerCategory(registry)
}
}
override fun registerScreens(registry: ScreenRegistry) {
reiProviders.forEach {
it.registerScreens(registry)
}
}
override fun registerTransferHandlers(registry: TransferHandlerRegistry) {
reiProviders.forEach {
it.registerTransferHandlers(registry)
}
}
}
@@ -0,0 +1,48 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.integration.rei
import com.cobblemon.mod.common.integration.recipeviewer.RecipeViewerRecipe
import me.shedaniel.rei.api.common.category.CategoryIdentifier
import me.shedaniel.rei.api.common.display.Display
import me.shedaniel.rei.api.common.entry.EntryIngredient
import me.shedaniel.rei.api.common.entry.EntryStack
import me.shedaniel.rei.api.common.entry.InputIngredient
import me.shedaniel.rei.api.common.util.EntryIngredients
import net.minecraft.resources.ResourceLocation
import net.minecraft.world.entity.player.Player
import net.minecraft.world.inventory.AbstractContainerMenu
import java.util.Optional
class CobblemonReiDisplay<T: RecipeViewerRecipe>(val recipe: T, val categoryId: CategoryIdentifier<*>): Display {
override fun getCategoryIdentifier(): CategoryIdentifier<*> = categoryId
override fun getInputEntries(): List<EntryIngredient> {
val entries = recipe.getInputs().map { EntryIngredients.ofIngredient(it) }.toMutableList()
entries.addAll(recipe.getOptionalInputs().map { EntryIngredients.ofIngredient(it) })
return entries
}
override fun getOutputEntries(): List<EntryIngredient> {
return recipe.getOutputs().map { EntryIngredients.of(it) }
}
override fun getRequiredEntries(): List<EntryIngredient> {
return recipe.getInputs().map { EntryIngredients.ofIngredient(it) }
}
override fun getDisplayLocation(): Optional<ResourceLocation> = Optional.of(recipe.getId())
override fun getInputIngredients(
menu: AbstractContainerMenu?,
player: Player?
): List<InputIngredient<EntryStack<*>>> {
return recipe.getInputs().mapIndexed { index, ingredient -> InputIngredient.of(index, EntryIngredients.ofIngredient(ingredient)) }
}
}
@@ -0,0 +1,28 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.integration.rei
import com.cobblemon.mod.common.api.gui.blitk
import me.shedaniel.math.Rectangle
import me.shedaniel.rei.api.client.gui.Renderer
import net.minecraft.client.gui.GuiGraphics
import net.minecraft.resources.ResourceLocation
class CobblemonReiIcon(val iconResource: ResourceLocation, val width: Int, val height: Int): Renderer {
override fun render(graphics: GuiGraphics, bounds: Rectangle, mouseX: Int, mouseY: Int, delta: Float) {
blitk(
matrixStack = graphics.pose(),
texture = iconResource,
x = bounds.minX,
y = bounds.minY,
width = width,
height = height
)
}
}
@@ -0,0 +1,43 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.integration.rei
import com.cobblemon.mod.common.integration.recipeviewer.RecipeViewerCategoryProvider
import com.cobblemon.mod.common.integration.recipeviewer.RecipeViewerRecipe
import me.shedaniel.math.Rectangle
import me.shedaniel.rei.api.client.registry.category.CategoryRegistry
import me.shedaniel.rei.api.client.registry.display.DisplayRegistry
import me.shedaniel.rei.api.client.registry.screen.ScreenRegistry
import me.shedaniel.rei.api.client.registry.transfer.TransferHandlerRegistry
import me.shedaniel.rei.api.common.category.CategoryIdentifier
import me.shedaniel.rei.api.common.util.EntryStacks
import net.minecraft.world.inventory.AbstractContainerMenu
class CobblemonReiProvider<T: RecipeViewerRecipe, E: AbstractContainerMenu>(val originalProvider: RecipeViewerCategoryProvider<T, E>) {
val categoryIdentifier: CategoryIdentifier<CobblemonReiDisplay<T>> = CategoryIdentifier.of<CobblemonReiDisplay<T>>(originalProvider.id)
fun registerDisplay(registry: DisplayRegistry) {
originalProvider.getRecipes().forEach {
registry.add(CobblemonReiDisplay(it, categoryIdentifier))
}
}
fun registerCategory(registry: CategoryRegistry) {
registry.add(CobblemonReiCategory(this))
registry.addWorkstations(categoryIdentifier, *originalProvider.getWorkstations().map { EntryStacks.of(it) }.toTypedArray())
}
fun registerScreens(registry: ScreenRegistry) {
originalProvider.getClickArea()?.let { registry.registerContainerClickArea(Rectangle(it.x, it.y, it.width, it.height), it.containerScreen, categoryIdentifier) }
}
fun registerTransferHandlers(registry: TransferHandlerRegistry) {
originalProvider.recipeHandler()?.let { registry.register(CobblemonReiRecipeHandler(this,it)) }
}
}
@@ -0,0 +1,32 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.integration.rei
import com.cobblemon.mod.common.integration.recipeviewer.RecipeViewerRecipeHandler
import me.shedaniel.rei.api.client.registry.transfer.TransferHandler
import me.shedaniel.rei.api.client.registry.transfer.simple.SimpleTransferHandler
import me.shedaniel.rei.api.common.transfer.info.stack.SlotAccessor
import net.minecraft.world.inventory.AbstractContainerMenu
class CobblemonReiRecipeHandler<E: AbstractContainerMenu>(val provider: CobblemonReiProvider<*, E>, val originalHandler: RecipeViewerRecipeHandler<E>): SimpleTransferHandler {
override fun checkApplicable(context: TransferHandler.Context): TransferHandler.ApplicabilityResult {
val category = (context.display as? CobblemonReiDisplay<*>)?.categoryId
if (category == null || category != provider.categoryIdentifier || context.menu == null || !originalHandler.getMenuClass().isInstance(context.menu))
return TransferHandler.ApplicabilityResult.createNotApplicable()
return TransferHandler.ApplicabilityResult.createApplicable()
}
override fun getInputSlots(context: TransferHandler.Context): Iterable<SlotAccessor> {
return originalHandler.getInputSlots(context.menu!! as E).map { SlotAccessor.fromSlot(it) }
}
override fun getInventorySlots(context: TransferHandler.Context): Iterable<SlotAccessor> {
return originalHandler.getInventorySlots(context.menu!! as E).map { SlotAccessor.fromSlot(it) }
}
}
@@ -0,0 +1,30 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.integration.rei
import com.cobblemon.mod.common.integration.recipeviewer.RecipeViewerRecipe
import me.shedaniel.rei.api.client.gui.widgets.Widget
import net.minecraft.client.Minecraft
import net.minecraft.client.gui.GuiGraphics
import net.minecraft.client.gui.components.events.GuiEventListener
class CobblemonReiSimpleWidget<T: RecipeViewerRecipe>(val x: Int, val y: Int, val recipe: T): Widget() {
override fun children(): List<GuiEventListener> {
return emptyList()
}
override fun render(guiGraphics: GuiGraphics, mouseX: Int, mouseY: Int, partialTick: Float) {
val realDelta = Minecraft.getInstance().timer.realtimeDeltaTicks
val matrices = guiGraphics.pose()
matrices.pushPose()
matrices.translate(x.toDouble(), y.toDouble(), 0.0)
recipe.renderRecipe(guiGraphics, mouseX, mouseY, realDelta)
matrices.popPose()
}
}
@@ -0,0 +1,25 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.integration.rei.brewing
import com.cobblemon.mod.common.item.crafting.brewingstand.BrewingStandRecipe
import me.shedaniel.rei.plugin.common.displays.brewing.DefaultBrewingDisplay
import net.minecraft.resources.ResourceLocation
import java.util.Optional
class ReiCobblemonBrewingDisplay(
val recipe: BrewingStandRecipe,
val id: ResourceLocation
): DefaultBrewingDisplay(
recipe.bottle,
recipe.input,
recipe.result
) {
override fun getDisplayLocation(): Optional<ResourceLocation> = Optional.of(id)
}
@@ -38,7 +38,7 @@ abstract class PlatformRegistry<R : Registry<T>, K : ResourceKey<R>, T> {
*/
abstract val resourceKey: K
protected val queue = hashMapOf<ResourceLocation, T>()
protected val queue = mutableMapOf<ResourceLocation, T>()
/**
* Creates a new entry in this registry.
@@ -9473,5 +9473,8 @@
"stat.cobblemon.reel_ins": "PokéRod Catches",
"stat.cobblemon.riding_land": "Distance by Pokémon on Land",
"stat.cobblemon.riding_air": "Distance by Pokémon in Air",
"stat.cobblemon.riding_liquid": "Distance by Pokémon in Liquid"
}
"stat.cobblemon.riding_liquid": "Distance by Pokémon in Liquid",
"cobblemon.recipeviewer.category.berry_recipe": "Berry Mutations",
"cobblemon.recipeviewer.category.cooking_pot_recipe": "Pot Cooking"
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

-1
View File
@@ -84,7 +84,6 @@ dependencies {
}
minecraftServerLibraries(libs.icu4j)
}
publishing {
@@ -33,6 +33,12 @@
],
"modmenu": [
"com.cobblemon.mod.fabric.client.integration.modmenu.CobblemonModMenu"
],
"emi": [
"com.cobblemon.mod.common.integration.emi.CobblemonEmiPlugin"
],
"rei_client": [
"com.cobblemon.mod.common.integration.rei.CobblemonReiClientPlugin"
]
},
"mixins": [
+6
View File
@@ -17,6 +17,8 @@ moddev = "1.0.11"
# Common
molang = "1.1.20"
jei-api = "19.22.1.316"
emi-api = "1.1.22+1.21.1"
rei-api = "16.0.799"
# Graal
graal = "22.3.0"
@@ -68,6 +70,9 @@ kotlin-reflect = { group = "org.jetbrains.kotlin", name = "kotlin-reflect", vers
# Common
jei-api = { group = "mezz.jei", name = "jei-1.21.1-common-api", version.ref = "jei-api"}
molang = { group = "local.com.bedrockk", name = "molang", version.ref = "molang" }
emi = { group = "dev.emi", name = "emi-xplat-intermediary", version.ref = "emi-api"}
rei-api = { group = "me.shedaniel", name = "RoughlyEnoughItems-api", version.ref = "rei-api"}
rei-defaultplugin = { group = "me.shedaniel", name = "RoughlyEnoughItems-default-plugin", version.ref = "rei-api"}
# Graal
graal-core = { group = "org.graalvm.js", name = "js", version.ref = "graal" }
@@ -93,6 +98,7 @@ neoforge-api = { group = "net.neoforged", name = "neoforge", version.ref = "neof
neo-kotlin-forge = { group = "thedarkcolour", name = "kotlinforforge-neoforge", version.ref = "neo-kotlin-for-forge" }
neoforge-debugutils = { group = "maven.modrinth", name = "debugutils", version.ref = "debugutils-forge"}
jei-neoforge = { group = "mezz.jei", name = "jei-1.21.1-neoforge", version.ref = "jei-api"}
rei-neoforge-api = { group = "me.shedaniel", name = "RoughlyEnoughItems-api-neoforge", version.ref = "rei-api"}
c2me-neoforge = { group = "maven.modrinth", name = "c2me-neoforge", version.ref = "c2me-neoforge" }
# Data Storage
+3
View File
@@ -29,6 +29,8 @@ repositories {
maven(url = "https://thedarkcolour.github.io/KotlinForForge/")
maven(url = "https://api.modrinth.com/maven")
maven(url = "https://maven.neoforged.net/releases")
maven(url = "https://maven.terraformersmc.com/")
maven(url = "https://maven.shedaniel.me")
mavenLocal()
}
@@ -68,6 +70,7 @@ dependencies {
bundle(it)
}
modCompileOnlyApi(libs.rei.neoforge.api)
}
tasks {
@@ -0,0 +1,15 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.neoforge.integration.rei
import com.cobblemon.mod.common.integration.rei.CobblemonReiClientPlugin
import me.shedaniel.rei.forge.REIPluginClient
@REIPluginClient
class CobblemonReiPluginNeoforge: CobblemonReiClientPlugin()