forked from mirrors/cobblemon
Compare commits
21
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4bac41d6d8 | ||
|
|
bf4c211313 | ||
|
|
91e4bbf54d | ||
|
|
a32769e8ed | ||
|
|
f8a28d7d9f | ||
|
|
ea02c69ef4 | ||
|
|
40563d4165 | ||
|
|
0864be3a54 | ||
|
|
081ad66d22 | ||
|
|
9251c6ebf7 | ||
|
|
f0247c764c | ||
|
|
6116f3d3c3 | ||
|
|
d3e75af5e4 | ||
|
|
ac6846a82f | ||
|
|
ad16dab0d4 | ||
|
|
14ad76b672 | ||
|
|
ab02895eed | ||
|
|
64e34df1ed | ||
|
|
9cf65810ee | ||
|
|
99f8711063 | ||
|
|
433b351bcd |
@@ -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> {
|
||||
|
||||
@@ -76,7 +76,7 @@ class TMMachineMenu(menuType: MenuType<*>, syncId: Int) : AbstractContainerMenu(
|
||||
}
|
||||
|
||||
private fun initiateSlots() {
|
||||
val startX = 15
|
||||
val startX = 75
|
||||
val startY = 144
|
||||
val slotWidth = 18
|
||||
val slotHeight = 18
|
||||
@@ -160,7 +160,7 @@ class TMMachineMenu(menuType: MenuType<*>, syncId: Int) : AbstractContainerMenu(
|
||||
}
|
||||
|
||||
class BlankTMSlot(container: Container, slot: Int, x: Int, y: Int) : Slot(container, slot, x, y) {
|
||||
override fun mayPlace(stack: ItemStack): Boolean = super.mayPlace(stack) && (stack.item == CobblemonItems.BLANK_TM)
|
||||
override fun mayPlace(stack: ItemStack): Boolean = super.mayPlace(stack) && ((stack.item == CobblemonItems.BLANK_TM) || stack.isEmpty)
|
||||
}
|
||||
|
||||
override fun slotChanged(containerToSend: AbstractContainerMenu, dataSlotIndex: Int, stack: ItemStack) {
|
||||
|
||||
-37
@@ -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(
|
||||
|
||||
+48
-47
@@ -68,7 +68,7 @@ import kotlin.math.ceil
|
||||
class TMMachineScreen(containerMenu: TMMachineMenu, val inventory: Inventory, title: Component) : AbstractContainerScreen<TMMachineMenu>(containerMenu, inventory, title) {
|
||||
companion object {
|
||||
const val HEIGHT = 226
|
||||
const val WIDTH = 191
|
||||
const val WIDTH = 251
|
||||
const val HALF_SCALE = 0.5F
|
||||
|
||||
const val DISC_DIAMETER = 56
|
||||
@@ -167,6 +167,8 @@ class TMMachineScreen(containerMenu: TMMachineMenu, val inventory: Inventory, ti
|
||||
|
||||
super.init()
|
||||
|
||||
leftPos -= 60 / 2 // Adjust for the left slots
|
||||
|
||||
logoResource = getLogoResource(minecraft?.languageManager?.selected)
|
||||
|
||||
logoPosX = leftPos + 1
|
||||
@@ -178,7 +180,7 @@ class TMMachineScreen(containerMenu: TMMachineMenu, val inventory: Inventory, ti
|
||||
partySlotList.clear()
|
||||
CobblemonClient.storage.party.forEachIndexed { index, pokemon ->
|
||||
partySlotList.add(TMPartySlotWidget(
|
||||
pX = leftPos - 60,
|
||||
pX = leftPos,
|
||||
pY = topPos + 9 + ((TMPartySlotWidget.HEIGHT + 3) * index),
|
||||
pokemon = pokemon,
|
||||
onPress = {
|
||||
@@ -208,7 +210,7 @@ class TMMachineScreen(containerMenu: TMMachineMenu, val inventory: Inventory, ti
|
||||
}
|
||||
|
||||
moveDescriptionWidget = MoveDescriptionWidget(
|
||||
leftPos + 125,
|
||||
leftPos + 185,
|
||||
topPos + 42,
|
||||
60,
|
||||
34
|
||||
@@ -216,7 +218,7 @@ class TMMachineScreen(containerMenu: TMMachineMenu, val inventory: Inventory, ti
|
||||
if (!children().contains(moveDescriptionWidget)) addRenderableWidget(moveDescriptionWidget)
|
||||
|
||||
typesScrollList = TypesScrollingWidget(
|
||||
pX = leftPos + 6,
|
||||
pX = leftPos + 66,
|
||||
pY = topPos + 11,
|
||||
setType = { type ->
|
||||
sortType = type
|
||||
@@ -227,7 +229,7 @@ class TMMachineScreen(containerMenu: TMMachineMenu, val inventory: Inventory, ti
|
||||
if (!children().contains(typesScrollList)) addRenderableWidget(typesScrollList)
|
||||
|
||||
movesScrollingList = MovesScrollingWidget(
|
||||
pX = leftPos + 4,
|
||||
pX = leftPos + 64,
|
||||
pY = topPos + 29,
|
||||
tmList,
|
||||
setTM = { tm, clicked ->
|
||||
@@ -241,7 +243,7 @@ class TMMachineScreen(containerMenu: TMMachineMenu, val inventory: Inventory, ti
|
||||
)
|
||||
if (!children().contains(movesScrollingList)) addRenderableWidget(movesScrollingList)
|
||||
|
||||
moveSearchWidget = MoveSearchWidget(pX = leftPos + 16, pY = topPos + 13) {
|
||||
moveSearchWidget = MoveSearchWidget(pX = leftPos + 76, pY = topPos + 13) {
|
||||
if (::movesScrollingList.isInitialized && moveSearchWidget.isFocused) {
|
||||
val input = moveSearchWidget.value
|
||||
setMoveList(filter = if (input.isBlank()) null else input)
|
||||
@@ -250,7 +252,7 @@ class TMMachineScreen(containerMenu: TMMachineMenu, val inventory: Inventory, ti
|
||||
if (!children().contains(moveSearchWidget)) addRenderableWidget(moveSearchWidget)
|
||||
|
||||
backButton = IconButton(
|
||||
leftPos + 106F,
|
||||
leftPos + 166F,
|
||||
topPos + 1F,
|
||||
20,
|
||||
18,
|
||||
@@ -261,7 +263,7 @@ class TMMachineScreen(containerMenu: TMMachineMenu, val inventory: Inventory, ti
|
||||
if (!children().contains(backButton)) addRenderableWidget(backButton)
|
||||
|
||||
selectedMoveButton = MoveSlotButton(
|
||||
leftPos + 6,
|
||||
leftPos + 66,
|
||||
topPos + 6,
|
||||
move = menu.currentlySelectedTM?.moveName,
|
||||
pp = menu.currentlySelectedTM?.moveName?.pp ?: 0,
|
||||
@@ -275,7 +277,7 @@ class TMMachineScreen(containerMenu: TMMachineMenu, val inventory: Inventory, ti
|
||||
}
|
||||
if (!children().contains(selectedMoveButton)) addRenderableWidget(selectedMoveButton)
|
||||
|
||||
startButton = StartButton(leftPos + 5F, topPos + 35F) {
|
||||
startButton = StartButton(leftPos + 65F, topPos + 35F) {
|
||||
if (!(it as StartButton).disabled) {
|
||||
menu.currentlySelectedTM?.let {
|
||||
val burnActive = menu.containerData?.get(TMMachineBlockEntity.BURN_ACTIVE_INDEX) ?: 0
|
||||
@@ -368,11 +370,11 @@ class TMMachineScreen(containerMenu: TMMachineMenu, val inventory: Inventory, ti
|
||||
logoPosY = logoPosY + (if (logoSlideDown) 1 else -1)
|
||||
var borderHit = false
|
||||
|
||||
if (logoSlideRight && (logoPosX + (LOGO_WIDTH * HALF_SCALE).toInt()) >= (leftPos + SCREEN_SAVER_WIDTH + 1)) {
|
||||
if (logoSlideRight && (logoPosX + (LOGO_WIDTH * HALF_SCALE).toInt()) >= (leftPos + SCREEN_SAVER_WIDTH + 61)) {
|
||||
logoSlideRight = false
|
||||
borderHit = true
|
||||
}
|
||||
if ((!logoSlideRight) && logoPosX <= (leftPos + 1)) {
|
||||
if ((!logoSlideRight) && logoPosX <= (leftPos + 61)) {
|
||||
logoSlideRight = true
|
||||
borderHit = true
|
||||
}
|
||||
@@ -404,7 +406,7 @@ class TMMachineScreen(containerMenu: TMMachineMenu, val inventory: Inventory, ti
|
||||
|
||||
private fun isBurnActive(): Boolean = (menu.containerData?.get(TMMachineBlockEntity.BURN_ACTIVE_INDEX) ?: 0) == 1
|
||||
|
||||
private fun setScreenFromMode(screen: Int) {
|
||||
fun setScreenFromMode(screen: Int) {
|
||||
mode = screen
|
||||
when (mode) {
|
||||
TYPE_SELECT_MODE -> {
|
||||
@@ -426,7 +428,7 @@ class TMMachineScreen(containerMenu: TMMachineMenu, val inventory: Inventory, ti
|
||||
updateHeldStackMove()
|
||||
}
|
||||
|
||||
private fun setMoveList(filter: String? = null, pokemon: Pokemon? = null) {
|
||||
fun setMoveList(filter: String? = null, pokemon: Pokemon? = null) {
|
||||
val filteredList = TechnicalMachine.filterTms(
|
||||
search = filter,
|
||||
type = sortType,
|
||||
@@ -542,7 +544,7 @@ class TMMachineScreen(containerMenu: TMMachineMenu, val inventory: Inventory, ti
|
||||
blitk(
|
||||
matrixStack = poseStack,
|
||||
texture = discBase,
|
||||
x = leftPos + 32,
|
||||
x = leftPos + 92,
|
||||
y = topPos + 50,
|
||||
width = DISC_DIAMETER,
|
||||
height = DISC_DIAMETER,
|
||||
@@ -557,7 +559,7 @@ class TMMachineScreen(containerMenu: TMMachineMenu, val inventory: Inventory, ti
|
||||
blitk(
|
||||
matrixStack = poseStack,
|
||||
texture = discReflectiveRotating,
|
||||
x = leftPos + 32,
|
||||
x = leftPos + 92,
|
||||
y = topPos + 50,
|
||||
width = DISC_DIAMETER,
|
||||
height = DISC_DIAMETER,
|
||||
@@ -573,7 +575,7 @@ class TMMachineScreen(containerMenu: TMMachineMenu, val inventory: Inventory, ti
|
||||
blitk(
|
||||
matrixStack = poseStack,
|
||||
texture = discRotating,
|
||||
x = leftPos + 32,
|
||||
x = leftPos + 92,
|
||||
y = topPos + 50,
|
||||
width = DISC_DIAMETER,
|
||||
height = DISC_DIAMETER,
|
||||
@@ -588,7 +590,7 @@ class TMMachineScreen(containerMenu: TMMachineMenu, val inventory: Inventory, ti
|
||||
blitk(
|
||||
matrixStack = poseStack,
|
||||
texture = discReflective,
|
||||
x = leftPos + 32,
|
||||
x = leftPos + 92,
|
||||
y = topPos + 50,
|
||||
width = DISC_DIAMETER,
|
||||
height = DISC_DIAMETER,
|
||||
@@ -610,7 +612,7 @@ class TMMachineScreen(containerMenu: TMMachineMenu, val inventory: Inventory, ti
|
||||
blitk(
|
||||
matrixStack = poseStack,
|
||||
texture = discOverlay,
|
||||
x = leftPos + 32,
|
||||
x = leftPos + 92,
|
||||
y = topPos + 50,
|
||||
width = DISC_DIAMETER,
|
||||
height = DISC_DIAMETER,
|
||||
@@ -624,7 +626,7 @@ class TMMachineScreen(containerMenu: TMMachineMenu, val inventory: Inventory, ti
|
||||
blitk(
|
||||
matrixStack = poseStack,
|
||||
texture = discBase,
|
||||
x = leftPos + 32,
|
||||
x = leftPos + 92,
|
||||
y = topPos + 50,
|
||||
width = DISC_DIAMETER,
|
||||
height = DISC_DIAMETER,
|
||||
@@ -636,7 +638,7 @@ class TMMachineScreen(containerMenu: TMMachineMenu, val inventory: Inventory, ti
|
||||
blitk(
|
||||
matrixStack = poseStack,
|
||||
texture = discReflectiveRotating,
|
||||
x = leftPos + 32,
|
||||
x = leftPos + 92,
|
||||
y = topPos + 50,
|
||||
width = DISC_DIAMETER,
|
||||
height = DISC_DIAMETER,
|
||||
@@ -649,7 +651,7 @@ class TMMachineScreen(containerMenu: TMMachineMenu, val inventory: Inventory, ti
|
||||
blitk(
|
||||
matrixStack = poseStack,
|
||||
texture = discRotating,
|
||||
x = leftPos + 32,
|
||||
x = leftPos + 92,
|
||||
y = topPos + 50,
|
||||
width = DISC_DIAMETER,
|
||||
height = DISC_DIAMETER,
|
||||
@@ -661,7 +663,7 @@ class TMMachineScreen(containerMenu: TMMachineMenu, val inventory: Inventory, ti
|
||||
blitk(
|
||||
matrixStack = poseStack,
|
||||
texture = discReflective,
|
||||
x = leftPos + 32,
|
||||
x = leftPos + 92,
|
||||
y = topPos + 50,
|
||||
width = DISC_DIAMETER,
|
||||
height = DISC_DIAMETER,
|
||||
@@ -676,7 +678,7 @@ class TMMachineScreen(containerMenu: TMMachineMenu, val inventory: Inventory, ti
|
||||
blitk(
|
||||
matrixStack = poseStack,
|
||||
texture = discBorder,
|
||||
x = leftPos + 32,
|
||||
x = leftPos + 92,
|
||||
y = topPos + 50,
|
||||
width = DISC_DIAMETER,
|
||||
height = DISC_DIAMETER,
|
||||
@@ -690,7 +692,7 @@ class TMMachineScreen(containerMenu: TMMachineMenu, val inventory: Inventory, ti
|
||||
blitk(
|
||||
matrixStack = context.pose(),
|
||||
texture = MovesWidget.movesPowerIconResource,
|
||||
x = leftPos + 127.5,
|
||||
x = leftPos + 187.5,
|
||||
y = topPos + 7.5,
|
||||
width = 5,
|
||||
height = 5
|
||||
@@ -699,7 +701,7 @@ class TMMachineScreen(containerMenu: TMMachineMenu, val inventory: Inventory, ti
|
||||
blitk(
|
||||
matrixStack = context.pose(),
|
||||
texture = MovesWidget.movesAccuracyIconResource,
|
||||
x = leftPos + 127.5,
|
||||
x = leftPos + 187.5,
|
||||
y = topPos + 19.5,
|
||||
width = 5,
|
||||
height = 5
|
||||
@@ -708,7 +710,7 @@ class TMMachineScreen(containerMenu: TMMachineMenu, val inventory: Inventory, ti
|
||||
blitk(
|
||||
matrixStack = context.pose(),
|
||||
texture = MovesWidget.movesEffectIconResource,
|
||||
x = leftPos + 127.5,
|
||||
x = leftPos + 187.5,
|
||||
y = topPos + 31.5,
|
||||
width = 5,
|
||||
height = 5
|
||||
@@ -717,7 +719,7 @@ class TMMachineScreen(containerMenu: TMMachineMenu, val inventory: Inventory, ti
|
||||
drawScaledText(
|
||||
context = context,
|
||||
text = lang("ui.power"),
|
||||
x = leftPos + 134.5,
|
||||
x = leftPos + 194.5,
|
||||
y = topPos + 8,
|
||||
shadow = true,
|
||||
scale = HALF_SCALE
|
||||
@@ -726,7 +728,7 @@ class TMMachineScreen(containerMenu: TMMachineMenu, val inventory: Inventory, ti
|
||||
drawScaledText(
|
||||
context = context,
|
||||
text = lang("ui.accuracy"),
|
||||
x = leftPos + 134.5,
|
||||
x = leftPos + 194.5,
|
||||
y = topPos + 20,
|
||||
shadow = true,
|
||||
scale = HALF_SCALE
|
||||
@@ -735,7 +737,7 @@ class TMMachineScreen(containerMenu: TMMachineMenu, val inventory: Inventory, ti
|
||||
drawScaledText(
|
||||
context = context,
|
||||
text = lang("ui.effect"),
|
||||
x = leftPos + 134.5,
|
||||
x = leftPos + 194.5,
|
||||
y = topPos + 32,
|
||||
shadow = true,
|
||||
scale = HALF_SCALE
|
||||
@@ -745,7 +747,7 @@ class TMMachineScreen(containerMenu: TMMachineMenu, val inventory: Inventory, ti
|
||||
drawScaledTextJustifiedRight(
|
||||
context = context,
|
||||
text = movePower,
|
||||
x = leftPos + 183,
|
||||
x = leftPos + 243,
|
||||
y = topPos + 8,
|
||||
shadow = true,
|
||||
scale = HALF_SCALE
|
||||
@@ -755,7 +757,7 @@ class TMMachineScreen(containerMenu: TMMachineMenu, val inventory: Inventory, ti
|
||||
drawScaledTextJustifiedRight(
|
||||
context = context,
|
||||
text = moveAccuracy,
|
||||
x = leftPos + 183,
|
||||
x = leftPos + 243,
|
||||
y = topPos + 20,
|
||||
shadow = true,
|
||||
scale = HALF_SCALE
|
||||
@@ -765,7 +767,7 @@ class TMMachineScreen(containerMenu: TMMachineMenu, val inventory: Inventory, ti
|
||||
drawScaledTextJustifiedRight(
|
||||
context = context,
|
||||
text = moveEffect,
|
||||
x = leftPos + 183,
|
||||
x = leftPos + 243,
|
||||
y = topPos + 32,
|
||||
shadow = true,
|
||||
scale = HALF_SCALE
|
||||
@@ -775,7 +777,7 @@ class TMMachineScreen(containerMenu: TMMachineMenu, val inventory: Inventory, ti
|
||||
val recipe = TechnicalMachines.moveToTM[moveTemplate]?.getClampedRecipe() ?: listOf()
|
||||
// Render material cost
|
||||
recipe.forEachIndexed { index, recipe ->
|
||||
val itemX = (leftPos + 129 + (index * 18))
|
||||
val itemX = (leftPos + 189 + (index * 18))
|
||||
val itemY = (topPos + 90)
|
||||
|
||||
val stacks = recipe.ingredient.items
|
||||
@@ -953,7 +955,7 @@ class TMMachineScreen(containerMenu: TMMachineMenu, val inventory: Inventory, ti
|
||||
blitk(
|
||||
matrixStack = poseStack,
|
||||
texture = screenSaver,
|
||||
x = leftPos + 1,
|
||||
x = leftPos + 61,
|
||||
y = topPos + 1,
|
||||
width = SCREEN_SAVER_WIDTH,
|
||||
height = SCREEN_SAVER_HEIGHT,
|
||||
@@ -977,7 +979,7 @@ class TMMachineScreen(containerMenu: TMMachineMenu, val inventory: Inventory, ti
|
||||
blitk(
|
||||
matrixStack = poseStack,
|
||||
texture = cobblemonResource("textures/white.png"),
|
||||
x = leftPos + 1,
|
||||
x = leftPos + 61,
|
||||
y = scanPosY * 0.5,
|
||||
width = SCREEN_SAVER_WIDTH,
|
||||
height = 1,
|
||||
@@ -988,15 +990,15 @@ class TMMachineScreen(containerMenu: TMMachineMenu, val inventory: Inventory, ti
|
||||
)
|
||||
|
||||
context.enableScissor(
|
||||
leftPos + 1,
|
||||
leftPos + 61,
|
||||
topPos + 1,
|
||||
leftPos + 1 + SCREEN_SAVER_WIDTH,
|
||||
leftPos + 61 + SCREEN_SAVER_WIDTH,
|
||||
topPos + 1 + SCREEN_SAVER_HEIGHT
|
||||
)
|
||||
blitk(
|
||||
matrixStack = poseStack,
|
||||
texture = scanLines,
|
||||
x = leftPos + 1,
|
||||
x = leftPos + 61,
|
||||
y = topPos + 1 - scanLineOffsetY,
|
||||
width = 118,
|
||||
height = 114,
|
||||
@@ -1007,7 +1009,7 @@ class TMMachineScreen(containerMenu: TMMachineMenu, val inventory: Inventory, ti
|
||||
blitk(
|
||||
matrixStack = poseStack,
|
||||
texture = screenOverlay,
|
||||
x = leftPos + 1,
|
||||
x = leftPos + 61,
|
||||
y = topPos + 1,
|
||||
width = SCREEN_SAVER_WIDTH,
|
||||
height = SCREEN_SAVER_HEIGHT,
|
||||
@@ -1153,9 +1155,8 @@ class TMMachineScreen(containerMenu: TMMachineMenu, val inventory: Inventory, ti
|
||||
return super.keyPressed(keyCode, scanCode, modifiers)
|
||||
}
|
||||
|
||||
override fun renderBackground(guiGraphics: GuiGraphics, mouseX: Int, mouseY: Int, partialTick: Float) {}
|
||||
|
||||
override fun renderBg(guiGraphics: GuiGraphics, partialTick: Float, mouseX: Int, mouseY: Int) {}
|
||||
override fun renderTransparentBackground(guiGraphics: GuiGraphics) {}
|
||||
|
||||
override fun render(graphics: GuiGraphics, mouseX: Int, mouseY: Int, delta: Float) {
|
||||
super.renderTransparentBackground(graphics)
|
||||
@@ -1164,16 +1165,16 @@ class TMMachineScreen(containerMenu: TMMachineMenu, val inventory: Inventory, ti
|
||||
blitk(
|
||||
matrixStack = matrices,
|
||||
texture = baseResource,
|
||||
x = leftPos,
|
||||
x = leftPos + 60,
|
||||
y = topPos,
|
||||
width = WIDTH,
|
||||
width = WIDTH - 60,
|
||||
height = HEIGHT
|
||||
)
|
||||
|
||||
blitk(
|
||||
matrixStack = matrices,
|
||||
texture = emptyDiscSlot,
|
||||
x = leftPos + 105,
|
||||
x = leftPos + 165,
|
||||
y = topPos + 116,
|
||||
width = 16,
|
||||
height = 16
|
||||
@@ -1185,7 +1186,7 @@ class TMMachineScreen(containerMenu: TMMachineMenu, val inventory: Inventory, ti
|
||||
context = graphics,
|
||||
font = CobblemonResources.DEFAULT_LARGE,
|
||||
text = label.bold(),
|
||||
x = leftPos + 5,
|
||||
x = leftPos + 65,
|
||||
y = topPos + 1
|
||||
)
|
||||
|
||||
@@ -1193,7 +1194,7 @@ class TMMachineScreen(containerMenu: TMMachineMenu, val inventory: Inventory, ti
|
||||
blitk(
|
||||
matrixStack = matrices,
|
||||
texture = tmTray,
|
||||
x = leftPos,
|
||||
x = leftPos + 60,
|
||||
y = topPos,
|
||||
width = 120,
|
||||
height = 112
|
||||
@@ -1203,7 +1204,7 @@ class TMMachineScreen(containerMenu: TMMachineMenu, val inventory: Inventory, ti
|
||||
blitk(
|
||||
matrixStack = matrices,
|
||||
texture = CobblemonResources.WHITE,
|
||||
x = leftPos + 33,
|
||||
x = leftPos + 93,
|
||||
y = topPos + 36,
|
||||
width = burnProgressWidth,
|
||||
height = 2
|
||||
|
||||
+27
@@ -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,44 @@
|
||||
/*
|
||||
* 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.CobblemonItems
|
||||
import com.cobblemon.mod.common.integration.emi.brewing.EmiCobblemonBrewingRecipe
|
||||
import com.cobblemon.mod.common.integration.recipeviewer.RecipeViewerCategoryProvider
|
||||
import com.cobblemon.mod.common.integration.recipeviewer.RecipeViewerComponentRegistry
|
||||
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
|
||||
import dev.emi.emi.api.stack.Comparison
|
||||
import dev.emi.emi.api.stack.EmiStack
|
||||
|
||||
@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))
|
||||
}
|
||||
|
||||
RecipeViewerComponentRegistry.register { item, component ->
|
||||
registry.setDefaultComparison(EmiStack.of(item), Comparison.compareData { it.itemStack.get(component) })
|
||||
}
|
||||
}
|
||||
}
|
||||
+36
@@ -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.recipeviewer.RecipeViewerCategoryProvider
|
||||
import com.cobblemon.mod.common.integration.recipeviewer.RecipeViewerRecipe
|
||||
import com.cobblemon.mod.common.integration.recipeviewer.RecipeViewerRecipeHandler
|
||||
import dev.emi.emi.api.EmiRegistry
|
||||
import dev.emi.emi.api.stack.EmiStack
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu
|
||||
|
||||
class CobblemonEmiProvider<T: RecipeViewerRecipe>(val originalProvider: RecipeViewerCategoryProvider<T>) {
|
||||
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().forEach {
|
||||
registry.addRecipeHandler(it.getMenuType(), CobblemonEmiRecipeHandler(this, it))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* 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 com.cobblemon.mod.common.integration.recipeviewer.SlotType
|
||||
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.ingredient) { EmiIngredient.of(it.ingredient, it.count.toLong()) } }
|
||||
}
|
||||
|
||||
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.ingredient) { EmiIngredient.of(it.ingredient.ingredient, it.ingredient.count.toLong()) }
|
||||
val emiSlot = SlotWidget(ingredient, it.x - 1, it.y - 1) //X, Y coordinate system slightly offset
|
||||
emiSlot.drawBack(false)
|
||||
if (it.type == 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.ingredient) }
|
||||
}
|
||||
}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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 com.cobblemon.mod.common.integration.recipeviewer.RecipeViewerRecipeHandler
|
||||
import dev.emi.emi.api.recipe.EmiRecipe
|
||||
import dev.emi.emi.api.recipe.handler.EmiCraftContext
|
||||
import dev.emi.emi.api.recipe.handler.StandardRecipeHandler
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu
|
||||
import net.minecraft.world.inventory.Slot
|
||||
|
||||
class CobblemonEmiRecipeHandler<E: AbstractContainerMenu, R: RecipeViewerRecipe>(val provider: CobblemonEmiProvider<*>, val originalHandler: RecipeViewerRecipeHandler<R, 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.category == provider.category
|
||||
}
|
||||
|
||||
override fun canCraft(recipe: EmiRecipe?, context: EmiCraftContext<E?>?): Boolean {
|
||||
return super.canCraft(recipe, context) && (recipe as? CobblemonEmiRecipe<R>)?.let { originalHandler.isApplicable(it.recipe) } ?: false
|
||||
}
|
||||
|
||||
override fun craft(recipe: EmiRecipe, context: EmiCraftContext<E>): Boolean {
|
||||
(recipe as? CobblemonEmiRecipe<R>)?.let {
|
||||
originalHandler.additionalHandle(recipe.recipe, context.screen.menu, context.screen)
|
||||
}
|
||||
return super.craft(recipe, context)
|
||||
}
|
||||
}
|
||||
+27
@@ -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)
|
||||
}
|
||||
}
|
||||
+64
@@ -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")
|
||||
}
|
||||
}
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* 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 com.cobblemon.mod.common.integration.recipeviewer.SlotType
|
||||
import mezz.jei.api.constants.VanillaTypes
|
||||
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
|
||||
import net.minecraft.world.item.ItemStack
|
||||
|
||||
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) {
|
||||
SlotType.INPUT -> RecipeIngredientRole.INPUT
|
||||
SlotType.OUTPUT -> RecipeIngredientRole.OUTPUT
|
||||
SlotType.CATALYST -> RecipeIngredientRole.CATALYST
|
||||
}, slot.x, slot.y)
|
||||
val items = slot.ingredient.ingredient.items.map { it.copyWithCount(slot.ingredient.count) }
|
||||
jeiSlot.addIngredients(VanillaTypes.ITEM_STACK, items)
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* 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 mezz.jei.api.ingredients.subtypes.ISubtypeInterpreter
|
||||
import mezz.jei.api.ingredients.subtypes.UidContext
|
||||
import net.minecraft.core.component.DataComponentType
|
||||
import net.minecraft.world.item.ItemStack
|
||||
|
||||
class CobblemonJeiComponentComparator(val component: DataComponentType<*>): ISubtypeInterpreter<ItemStack> {
|
||||
override fun getSubtypeData(ingredient: ItemStack, context: UidContext): Any? {
|
||||
return ingredient.get(component)
|
||||
}
|
||||
|
||||
override fun getLegacyStringSubtypeInfo(ingredient: ItemStack, context: UidContext): String = ""
|
||||
}
|
||||
+36
-19
@@ -8,54 +8,71 @@
|
||||
|
||||
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.CobblemonItemComponents
|
||||
import com.cobblemon.mod.common.CobblemonItems
|
||||
import com.cobblemon.mod.common.integration.jei.brewing.JeiBrewingStandRecipe
|
||||
import com.cobblemon.mod.common.integration.recipeviewer.RecipeViewerCategoryProvider
|
||||
import com.cobblemon.mod.common.integration.recipeviewer.RecipeViewerComponentRegistry
|
||||
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.runtime.IJeiRuntime
|
||||
import mezz.jei.api.registration.IRecipeTransferRegistration
|
||||
import mezz.jei.api.registration.ISubtypeRegistration
|
||||
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 onRuntimeAvailable(jeiRuntime: IJeiRuntime) {
|
||||
CobblemonJeiPlugin.jeiRuntime = jeiRuntime
|
||||
override fun registerRecipeTransferHandlers(registration: IRecipeTransferRegistration) {
|
||||
jeiProviders.forEach {
|
||||
it.registerRecipeTransferHandlers(registration)
|
||||
}
|
||||
}
|
||||
|
||||
override fun registerItemSubtypes(registration: ISubtypeRegistration) {
|
||||
RecipeViewerComponentRegistry.register { item, component ->
|
||||
registration.registerSubtypeInterpreter(item, CobblemonJeiComponentComparator(component))
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
var jeiRuntime: IJeiRuntime? = null
|
||||
private val jeiProviders = RecipeViewerCategoryProvider.categoriesProviders.map {
|
||||
CobblemonJeiProvider(it)
|
||||
}
|
||||
|
||||
val ID = cobblemonResource("jei_plugin")
|
||||
}
|
||||
}
|
||||
|
||||
+33
-8
@@ -8,15 +8,40 @@
|
||||
|
||||
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().forEach {
|
||||
registration.addRecipeTransferHandler(CobblemonJeiRecipeHandler(this, it, registration), recipeType)
|
||||
}
|
||||
}
|
||||
}
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* 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.gui.ingredient.IRecipeSlotsView
|
||||
import mezz.jei.api.recipe.RecipeType
|
||||
import mezz.jei.api.recipe.transfer.IRecipeTransferError
|
||||
import mezz.jei.api.recipe.transfer.IRecipeTransferHandler
|
||||
import mezz.jei.api.registration.IRecipeTransferRegistration
|
||||
import mezz.jei.api.runtime.IRecipesGui
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu
|
||||
import net.minecraft.world.inventory.MenuType
|
||||
import java.util.Optional
|
||||
|
||||
class CobblemonJeiRecipeHandler<E: AbstractContainerMenu, R: RecipeViewerRecipe>(val provider: CobblemonJeiProvider<R>, val originalHandler: RecipeViewerRecipeHandler<R, E>, registry: IRecipeTransferRegistration): IRecipeTransferHandler<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
|
||||
|
||||
val recipeInfoHandler = registry.transferHelper.createUnregisteredRecipeTransferHandler(CobblemonJeiRecipeInfo(provider, originalHandler))
|
||||
|
||||
override fun transferRecipe(
|
||||
container: E,
|
||||
recipe: R,
|
||||
recipeSlots: IRecipeSlotsView,
|
||||
player: Player,
|
||||
maxTransfer: Boolean,
|
||||
doTransfer: Boolean
|
||||
): IRecipeTransferError? {
|
||||
if (doTransfer) {
|
||||
val screen = Minecraft.getInstance().screen
|
||||
val containerScreen = when (screen) {
|
||||
is IRecipesGui -> if (screen.parentScreen.isPresent) screen.parentScreen.get() as? AbstractContainerScreen<E> else null
|
||||
is AbstractContainerScreen<*> -> screen as? AbstractContainerScreen<E>
|
||||
else -> null
|
||||
}
|
||||
originalHandler.additionalHandle(recipe, container, containerScreen)
|
||||
}
|
||||
return recipeInfoHandler.transferRecipe(container, recipe, recipeSlots, player, maxTransfer, doTransfer)
|
||||
}
|
||||
}
|
||||
+36
@@ -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 CobblemonJeiRecipeInfo<E: AbstractContainerMenu, R: RecipeViewerRecipe>(val provider: CobblemonJeiProvider<R>, val originalHandler: RecipeViewerRecipeHandler<R, 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 originalHandler.isApplicable(recipe)
|
||||
}
|
||||
}
|
||||
-42
@@ -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) { }
|
||||
}
|
||||
-20
@@ -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
|
||||
) {
|
||||
|
||||
}
|
||||
-61
@@ -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
|
||||
}
|
||||
}
|
||||
-37
@@ -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) { }
|
||||
}
|
||||
-39
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
-122
@@ -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)
|
||||
}
|
||||
}
|
||||
+20
@@ -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
|
||||
)
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* 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.item.crafting.Ingredient
|
||||
|
||||
// Whole existence due to the fact we can have recipes with multiple count requirement
|
||||
data class RecipeIngredient(
|
||||
val ingredient: Ingredient,
|
||||
val count: Int = 1
|
||||
)
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
data class RecipeSlot(
|
||||
val x: Int,
|
||||
val y: Int,
|
||||
val type: SlotType,
|
||||
val ingredient: RecipeIngredient
|
||||
)
|
||||
|
||||
enum class SlotType {
|
||||
INPUT,
|
||||
OUTPUT,
|
||||
CATALYST
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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 com.cobblemon.mod.common.integration.recipeviewer.tm.TMViewerProvider
|
||||
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> {
|
||||
companion object {
|
||||
val categoriesProviders: Set<RecipeViewerCategoryProvider<*>> = setOf(
|
||||
BerryMutationProvider(),
|
||||
CampfirePotViewerProvider(),
|
||||
TMViewerProvider()
|
||||
)
|
||||
}
|
||||
|
||||
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(): List<RecipeViewerRecipeHandler<T, AbstractContainerMenu>> = listOf()
|
||||
}
|
||||
+20
@@ -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 com.cobblemon.mod.common.CobblemonItemComponents
|
||||
import com.cobblemon.mod.common.CobblemonItems
|
||||
import net.minecraft.core.component.DataComponentType
|
||||
import net.minecraft.world.item.Item
|
||||
|
||||
object RecipeViewerComponentRegistry {
|
||||
fun register(method: (item: Item, component: DataComponentType<*>) -> Unit) {
|
||||
method(CobblemonItems.TECHNICAL_MACHINE, CobblemonItemComponents.TM_MOVE)
|
||||
}
|
||||
}
|
||||
+29
@@ -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
|
||||
|
||||
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<RecipeIngredient>
|
||||
fun getOutputs(): List<ItemStack>
|
||||
|
||||
fun getOptionalInputs(): List<RecipeIngredient> = emptyList()
|
||||
|
||||
fun supportsRecipeTree(): Boolean = true
|
||||
|
||||
fun renderRecipe(context: GuiGraphics, mouseX: Int, mouseY: Int, delta: Float) {}
|
||||
|
||||
fun getSlots(): List<RecipeSlot>
|
||||
}
|
||||
+25
@@ -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.recipeviewer
|
||||
|
||||
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu
|
||||
import net.minecraft.world.inventory.MenuType
|
||||
import net.minecraft.world.inventory.Slot
|
||||
|
||||
interface RecipeViewerRecipeHandler<T: RecipeViewerRecipe, 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>
|
||||
|
||||
fun isApplicable(recipe: T): Boolean = true
|
||||
fun additionalHandle(recipe: T, menu: E, screen: AbstractContainerScreen<E>?) {}
|
||||
}
|
||||
+58
@@ -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> {
|
||||
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")
|
||||
}
|
||||
}
|
||||
+73
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* 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.RecipeIngredient
|
||||
import com.cobblemon.mod.common.integration.recipeviewer.RecipeSlot
|
||||
import com.cobblemon.mod.common.integration.recipeviewer.RecipeViewerCategoryProvider
|
||||
import com.cobblemon.mod.common.integration.recipeviewer.RecipeViewerRecipe
|
||||
import com.cobblemon.mod.common.integration.recipeviewer.SlotType
|
||||
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<RecipeIngredient> {
|
||||
return listOf(RecipeIngredient(Ingredient.of(berryOne)), RecipeIngredient(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<RecipeSlot> {
|
||||
val list = mutableListOf<RecipeSlot>()
|
||||
list.add(RecipeSlot(1, 1, SlotType.INPUT, RecipeIngredient(Ingredient.of(berryOne))))
|
||||
list.add(RecipeSlot(50, 1, SlotType.INPUT, RecipeIngredient(Ingredient.of(berryTwo))))
|
||||
list.add(RecipeSlot(108, 1, SlotType.OUTPUT, RecipeIngredient(Ingredient.of(berryResult))))
|
||||
return list
|
||||
}
|
||||
|
||||
private fun berryIdentifier(berry: BerryItem): String {
|
||||
return berry.berry()?.identifier?.path ?: ""
|
||||
}
|
||||
}
|
||||
+23
@@ -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)
|
||||
}
|
||||
}
|
||||
+65
@@ -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> {
|
||||
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(): List<RecipeViewerRecipeHandler<CampfirePotViewerRecipe, AbstractContainerMenu>> = listOf(CampfirePotViewerRecipeHandler() as RecipeViewerRecipeHandler<CampfirePotViewerRecipe, AbstractContainerMenu>)
|
||||
|
||||
companion object {
|
||||
private const val WIDTH = 146
|
||||
private const val HEIGHT = 59
|
||||
|
||||
val ID = cobblemonResource("cooking_pot_recipe")
|
||||
}
|
||||
}
|
||||
+106
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* 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.integration.recipeviewer.RecipeIngredient
|
||||
import com.cobblemon.mod.common.integration.recipeviewer.RecipeSlot
|
||||
import com.cobblemon.mod.common.integration.recipeviewer.SlotType
|
||||
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<RecipeIngredient> {
|
||||
return originalRecipe.ingredients.map { RecipeIngredient(it) }
|
||||
}
|
||||
|
||||
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<RecipeIngredient> {
|
||||
return listOf(RecipeIngredient(Ingredient.of(*generateProperSeasoningList().toTypedArray())))
|
||||
}
|
||||
|
||||
override fun getSlots(): List<RecipeSlot> {
|
||||
val registryAccess = Minecraft.getInstance().level?.registryAccess() ?: throw IllegalStateException("Registry access not found")
|
||||
val slots = mutableListOf<RecipeSlot>()
|
||||
|
||||
originalRecipe.ingredients.forEachIndexed { index, ingredient ->
|
||||
val row = index / CRAFTING_GRID_WIDTH
|
||||
val column = index % CRAFTING_GRID_WIDTH
|
||||
slots.add(RecipeSlot(16 + column * 18, 1 + row * 18,
|
||||
SlotType.INPUT, RecipeIngredient(ingredient)))
|
||||
}
|
||||
|
||||
if (originalRecipe.seasoningProcessors.isNotEmpty()) {
|
||||
val processedSeasonings = generateProperSeasoningList()
|
||||
|
||||
for ((index, _) in SEASONING_SLOTS.withIndex()) {
|
||||
val x = 93 + index * 18
|
||||
val y = 1
|
||||
|
||||
slots.add(RecipeSlot(x, y,
|
||||
SlotType.CATALYST, RecipeIngredient(Ingredient.of(*processedSeasonings.shuffled().toTypedArray()))))
|
||||
}
|
||||
}
|
||||
|
||||
slots.add(RecipeSlot(111, 38,
|
||||
SlotType.OUTPUT, RecipeIngredient(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
|
||||
}
|
||||
}
|
||||
+29
@@ -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<CampfirePotViewerRecipe, 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
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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.tm
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonItems
|
||||
import com.cobblemon.mod.common.api.tms.TechnicalMachines
|
||||
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.resources.ResourceLocation
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import org.joml.Vector2i
|
||||
|
||||
class TMViewerProvider: RecipeViewerCategoryProvider<TMViewerRecipe> {
|
||||
override val id = ID
|
||||
override val recipeClass = TMViewerRecipe::class.java
|
||||
|
||||
override fun getIconResource(): ResourceLocation = cobblemonResource("textures/item/tms/blank_disc.png")
|
||||
override fun getIconDimensions(): Vector2i = Vector2i(16, 16)
|
||||
|
||||
override fun getWidth(): Int = WIDTH
|
||||
override fun getHeight(): Int = HEIGHT
|
||||
|
||||
override fun getRecipes(): List<TMViewerRecipe> {
|
||||
return TechnicalMachines.tmMap.values.map { TMViewerRecipe(it) }.sortedBy { it.originalTM.type }
|
||||
}
|
||||
|
||||
override fun getWorkstations(): List<ItemStack> {
|
||||
return listOf(CobblemonItems.TM_MACHINE.defaultInstance)
|
||||
}
|
||||
|
||||
override fun recipeHandler(): List<RecipeViewerRecipeHandler<TMViewerRecipe, AbstractContainerMenu>> = listOf(TMViewerRecipeHandler() as RecipeViewerRecipeHandler<TMViewerRecipe, AbstractContainerMenu>)
|
||||
|
||||
companion object {
|
||||
private const val WIDTH = 125
|
||||
private const val HEIGHT = 30
|
||||
|
||||
val ID = cobblemonResource("tm_recipe")
|
||||
}
|
||||
}
|
||||
+86
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* 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.tm
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonItems
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.api.text.red
|
||||
import com.cobblemon.mod.common.api.tms.TechnicalMachine
|
||||
import com.cobblemon.mod.common.api.tms.TechnicalMachines
|
||||
import com.cobblemon.mod.common.client.CobblemonClient
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import com.cobblemon.mod.common.integration.recipeviewer.RecipeIngredient
|
||||
import com.cobblemon.mod.common.integration.recipeviewer.RecipeSlot
|
||||
import com.cobblemon.mod.common.integration.recipeviewer.RecipeViewerCategoryProvider
|
||||
import com.cobblemon.mod.common.integration.recipeviewer.RecipeViewerRecipe
|
||||
import com.cobblemon.mod.common.integration.recipeviewer.SlotType
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.item.crafting.Ingredient
|
||||
|
||||
class TMViewerRecipe(val originalTM: TechnicalMachine): RecipeViewerRecipe {
|
||||
companion object {
|
||||
val BACKGROUND = cobblemonResource("textures/gui/recipeviewer/tm_recipe.png")
|
||||
}
|
||||
|
||||
override fun getId(): ResourceLocation = cobblemonResource("/tm_recipe_" + originalTM.id.path)
|
||||
|
||||
override fun getInputs(): List<RecipeIngredient> {
|
||||
val items = mutableListOf(RecipeIngredient(Ingredient.of(CobblemonItems.BLANK_TM)))
|
||||
items.addAll(originalTM.recipe?.map { RecipeIngredient(it.ingredient, it.count) } ?: listOf())
|
||||
return items
|
||||
}
|
||||
|
||||
override fun getOutputs(): List<ItemStack> {
|
||||
return listOf(originalTM.createItemStack())
|
||||
}
|
||||
|
||||
override fun getSlots(): List<RecipeSlot> {
|
||||
val slots = mutableListOf<RecipeSlot>()
|
||||
val recipe = originalTM.recipe ?: listOf()
|
||||
|
||||
slots.add(RecipeSlot(1, 1, SlotType.INPUT, RecipeIngredient(Ingredient.of(CobblemonItems.BLANK_TM))))
|
||||
|
||||
for (i in 0..2) {
|
||||
val ingredient = recipe.getOrNull(i)?.let { RecipeIngredient(it.ingredient, it.count) } ?: RecipeIngredient(Ingredient.of())
|
||||
slots.add(RecipeSlot(24 + i * 18, 1, SlotType.INPUT, ingredient))
|
||||
}
|
||||
|
||||
slots.add(RecipeSlot(108, 1, SlotType.OUTPUT, RecipeIngredient(Ingredient.of(originalTM.createItemStack()))))
|
||||
|
||||
return slots
|
||||
}
|
||||
|
||||
override fun renderRecipe(context: GuiGraphics, mouseX: Int, mouseY: Int, delta: Float) {
|
||||
blitk(
|
||||
matrixStack = context.pose(),
|
||||
texture = BACKGROUND,
|
||||
x = 0,
|
||||
y = 0,
|
||||
width = 125,
|
||||
height = 30
|
||||
)
|
||||
|
||||
drawScaledText(
|
||||
context = context,
|
||||
text = if (recipeKnown()) lang("recipeviewer.tm_learned") else lang("recipeviewer.tm_not_learned").red(),
|
||||
x = 0,
|
||||
y = 21,
|
||||
shadow = true
|
||||
)
|
||||
}
|
||||
|
||||
fun recipeKnown(): Boolean {
|
||||
val learnedTMs = CobblemonClient.clientTMMoveData.learnedTMs
|
||||
return originalTM.isPassivelyObtained() || originalTM.id in learnedTMs
|
||||
}
|
||||
}
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* 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.tm
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonMenuType
|
||||
import com.cobblemon.mod.common.CobblemonNetwork
|
||||
import com.cobblemon.mod.common.api.types.ElementalTypes
|
||||
import com.cobblemon.mod.common.block.entity.TMMachineBlockEntity
|
||||
import com.cobblemon.mod.common.block.tmmachine.TMMachineMenu
|
||||
import com.cobblemon.mod.common.client.gui.tmmachine.TMMachineScreen
|
||||
import com.cobblemon.mod.common.integration.recipeviewer.RecipeViewerRecipeHandler
|
||||
import com.cobblemon.mod.common.net.messages.client.ui.SetActiveTMPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.ui.SetTMMachineContainerDataPacket
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen
|
||||
import net.minecraft.world.inventory.MenuType
|
||||
import net.minecraft.world.inventory.Slot
|
||||
|
||||
class TMViewerRecipeHandler: RecipeViewerRecipeHandler<TMViewerRecipe, TMMachineMenu> {
|
||||
override fun getInputSlots(menu: TMMachineMenu): List<Slot> {
|
||||
return menu.slots.filter { it.index in 37..40 }
|
||||
}
|
||||
|
||||
override fun getInventorySlots(menu: TMMachineMenu): List<Slot> {
|
||||
return menu.slots.filter { it.index in 0..35}
|
||||
}
|
||||
|
||||
override fun getMenuClass(): Class<TMMachineMenu> = TMMachineMenu::class.java
|
||||
override fun getMenuType(): MenuType<TMMachineMenu> = CobblemonMenuType.TM_MACHINE
|
||||
|
||||
override fun isApplicable(recipe: TMViewerRecipe): Boolean {
|
||||
return recipe.recipeKnown()
|
||||
}
|
||||
|
||||
override fun additionalHandle(recipe: TMViewerRecipe, menu: TMMachineMenu, screen: AbstractContainerScreen<TMMachineMenu>?) {
|
||||
(screen as? TMMachineScreen)?.let {
|
||||
it.setScreenFromMode(TMMachineScreen.TM_BURN_MODE)
|
||||
it.sortType = ElementalTypes.get(recipe.originalTM.type)
|
||||
it.setMoveList()
|
||||
}
|
||||
|
||||
if (menu.currentlySelectedTM != recipe.originalTM) {
|
||||
CobblemonNetwork.sendToServer(SetActiveTMPacket(recipe.originalTM))
|
||||
}
|
||||
}
|
||||
}
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* 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 com.cobblemon.mod.common.integration.recipeviewer.SlotType
|
||||
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.ofItemStacks(slot.ingredient.ingredient.items.map { it.copyWithCount(slot.ingredient.count) }))
|
||||
reiSlot.disableBackground()
|
||||
when (slot.type) {
|
||||
SlotType.INPUT -> reiSlot.markInput()
|
||||
SlotType.CATALYST -> reiSlot.markInput()
|
||||
SlotType.OUTPUT -> reiSlot.markOutput()
|
||||
}
|
||||
widgets.add(reiSlot)
|
||||
}
|
||||
|
||||
return widgets
|
||||
}
|
||||
}
|
||||
+67
@@ -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.rei
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonItems
|
||||
import com.cobblemon.mod.common.api.tms.TechnicalMachines
|
||||
import com.cobblemon.mod.common.integration.recipeviewer.RecipeViewerCategoryProvider
|
||||
import com.cobblemon.mod.common.integration.recipeviewer.RecipeViewerComponentRegistry
|
||||
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.entry.EntryRegistry
|
||||
import me.shedaniel.rei.api.client.registry.screen.ScreenRegistry
|
||||
import me.shedaniel.rei.api.client.registry.transfer.TransferHandlerRegistry
|
||||
import me.shedaniel.rei.api.common.entry.comparison.ItemComparatorRegistry
|
||||
import me.shedaniel.rei.api.common.util.EntryStacks
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
override fun registerItemComparators(registry: ItemComparatorRegistry) {
|
||||
RecipeViewerComponentRegistry.register { item, component ->
|
||||
registry.register(CobblemonReiComponentComparator(component), item)
|
||||
}
|
||||
}
|
||||
}
|
||||
+20
@@ -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.rei
|
||||
|
||||
import me.shedaniel.rei.api.common.entry.comparison.ComparisonContext
|
||||
import me.shedaniel.rei.api.common.entry.comparison.EntryComparator
|
||||
import net.minecraft.core.component.DataComponentType
|
||||
import net.minecraft.world.item.ItemStack
|
||||
|
||||
class CobblemonReiComponentComparator(val component: DataComponentType<*>): EntryComparator<ItemStack> {
|
||||
override fun hash(context: ComparisonContext, stack: ItemStack): Long {
|
||||
return stack.get(component).hashCode().toLong()
|
||||
}
|
||||
}
|
||||
+48
@@ -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.ofItems(it.ingredient.items.map { it.item }, it.count) }.toMutableList()
|
||||
entries.addAll(recipe.getOptionalInputs().map { EntryIngredients.ofItemStacks(it.ingredient.items.map { it.copyWithCount(it.count) }) })
|
||||
return entries
|
||||
}
|
||||
|
||||
override fun getOutputEntries(): List<EntryIngredient> {
|
||||
return recipe.getOutputs().map { EntryIngredients.of(it) }
|
||||
}
|
||||
|
||||
override fun getRequiredEntries(): List<EntryIngredient> {
|
||||
return recipe.getInputs().map { EntryIngredients.ofItemStacks(it.ingredient.items.map { it.copyWithCount(it.count) }) }
|
||||
}
|
||||
|
||||
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.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
|
||||
)
|
||||
}
|
||||
}
|
||||
+43
@@ -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>(val originalProvider: RecipeViewerCategoryProvider<T>) {
|
||||
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().forEach { registry.register(CobblemonReiRecipeHandler(this,it)) }
|
||||
}
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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 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.entry.InputIngredient
|
||||
import me.shedaniel.rei.api.common.transfer.info.stack.SlotAccessor
|
||||
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu
|
||||
import net.minecraft.world.item.ItemStack
|
||||
|
||||
class CobblemonReiRecipeHandler<E: AbstractContainerMenu, R: RecipeViewerRecipe>(val provider: CobblemonReiProvider<*>, val originalHandler: RecipeViewerRecipeHandler<R, E>): SimpleTransferHandler {
|
||||
override fun checkApplicable(context: TransferHandler.Context): TransferHandler.ApplicabilityResult {
|
||||
val display = context.display as? CobblemonReiDisplay<R>
|
||||
if (display == null || display.categoryId != provider.categoryIdentifier || context.menu == null
|
||||
|| !originalHandler.getMenuClass().isInstance(context.menu) || !originalHandler.isApplicable(display.recipe))
|
||||
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) }
|
||||
}
|
||||
|
||||
override fun handle(context: TransferHandler.Context): TransferHandler.Result {
|
||||
if (context.isActuallyCrafting) {
|
||||
val display = context.display as? CobblemonReiDisplay<R>
|
||||
display?.let {
|
||||
originalHandler.additionalHandle(display.recipe, context.menu as E, context.containerScreen as AbstractContainerScreen<E>)
|
||||
}
|
||||
}
|
||||
return super.handle(context)
|
||||
}
|
||||
}
|
||||
+30
@@ -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()
|
||||
}
|
||||
}
|
||||
+25
@@ -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.
|
||||
|
||||
@@ -9472,5 +9472,11 @@
|
||||
"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",
|
||||
"cobblemon.recipeviewer.category.tm_recipe": "TM Burning",
|
||||
"cobblemon.recipeviewer.tm_learned": "TM Discovered",
|
||||
"cobblemon.recipeviewer.tm_not_learned": "TM Undiscovered"
|
||||
}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 1.7 KiB |
BIN
Binary file not shown.
|
After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 616 B After Width: | Height: | Size: 616 B |
Binary file not shown.
|
After Width: | Height: | Size: 876 B |
@@ -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": [
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
+15
@@ -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()
|
||||
Reference in New Issue
Block a user