1.21.3 WIP

This commit is contained in:
Linnea Gräf
2024-11-03 01:24:24 +01:00
parent 646843ba3b
commit 22f0cc59a2
105 changed files with 2854 additions and 2646 deletions

View File

@@ -4,32 +4,32 @@ import me.shedaniel.math.Dimension
import me.shedaniel.math.Point
import me.shedaniel.math.Rectangle
import me.shedaniel.rei.api.client.gui.widgets.WidgetWithBounds
import moe.nea.firmament.gui.entity.EntityRenderer
import net.minecraft.client.gui.DrawContext
import net.minecraft.client.gui.Element
import net.minecraft.entity.LivingEntity
import moe.nea.firmament.gui.entity.EntityRenderer
class EntityWidget(val entity: LivingEntity, val point: Point) : WidgetWithBounds() {
override fun children(): List<Element> {
return emptyList()
}
override fun children(): List<Element> {
return emptyList()
}
var hasErrored = false
var hasErrored = false
override fun render(context: DrawContext, mouseX: Int, mouseY: Int, delta: Float) {
try {
if (!hasErrored)
EntityRenderer.renderEntity(entity, context, point.x, point.y, mouseX.toFloat(), mouseY.toFloat())
} catch (ex: Exception) {
EntityRenderer.logger.error("Failed to render constructed entity: $entity", ex)
hasErrored = true
}
if (hasErrored) {
context.fill(point.x, point.y, point.x + 50, point.y + 80, 0xFFAA2222.toInt())
}
}
override fun render(context: DrawContext, mouseX: Int, mouseY: Int, delta: Float) {
try {
if (!hasErrored)
EntityRenderer.renderEntity(entity, context, point.x, point.y, mouseX.toFloat(), mouseY.toFloat())
} catch (ex: Exception) {
EntityRenderer.logger.error("Failed to render constructed entity: $entity", ex)
hasErrored = true
}
if (hasErrored) {
context.fill(point.x, point.y, point.x + 50, point.y + 80, 0xFFAA2222.toInt())
}
}
override fun getBounds(): Rectangle {
return Rectangle(point, Dimension(50, 80))
}
override fun getBounds(): Rectangle {
return Rectangle(point, Dimension(50, 80))
}
}

View File

@@ -0,0 +1,10 @@
package moe.nea.firmament.compat.rei
import me.shedaniel.rei.api.common.entry.type.EntryTypeRegistry
import me.shedaniel.rei.api.common.plugins.REICommonPlugin
class FirmamentReiCommonPlugin : REICommonPlugin {
override fun registerEntryTypes(registry: EntryTypeRegistry) {
registry.register(FirmamentReiPlugin.SKYBLOCK_ITEM_TYPE_ID, SBItemEntryDefinition)
}
}

View File

@@ -11,7 +11,6 @@ import me.shedaniel.rei.api.client.registry.screen.ScreenRegistry
import me.shedaniel.rei.api.client.registry.transfer.TransferHandler
import me.shedaniel.rei.api.client.registry.transfer.TransferHandlerRegistry
import me.shedaniel.rei.api.common.entry.EntryStack
import me.shedaniel.rei.api.common.entry.type.EntryTypeRegistry
import me.shedaniel.rei.api.common.entry.type.VanillaEntryTypes
import net.minecraft.client.gui.screen.Screen
import net.minecraft.client.gui.screen.ingame.GenericContainerScreen
@@ -20,18 +19,17 @@ import net.minecraft.item.ItemStack
import net.minecraft.text.Text
import net.minecraft.util.ActionResult
import net.minecraft.util.Identifier
import moe.nea.firmament.events.HandledScreenPushREIEvent
import moe.nea.firmament.features.inventory.CraftingOverlay
import moe.nea.firmament.features.inventory.storageoverlay.StorageOverlayScreen
import moe.nea.firmament.compat.rei.recipes.SBCraftingRecipe
import moe.nea.firmament.compat.rei.recipes.SBEssenceUpgradeRecipe
import moe.nea.firmament.compat.rei.recipes.SBForgeRecipe
import moe.nea.firmament.compat.rei.recipes.SBKatRecipe
import moe.nea.firmament.compat.rei.recipes.SBMobDropRecipe
import moe.nea.firmament.events.HandledScreenPushREIEvent
import moe.nea.firmament.features.inventory.CraftingOverlay
import moe.nea.firmament.features.inventory.storageoverlay.StorageOverlayScreen
import moe.nea.firmament.repo.RepoManager
import moe.nea.firmament.repo.SBItemStack
import moe.nea.firmament.util.MC
import moe.nea.firmament.util.ScreenUtil
import moe.nea.firmament.util.SkyblockId
import moe.nea.firmament.util.guessRecipeId
import moe.nea.firmament.util.skyblockId
@@ -74,9 +72,6 @@ class FirmamentReiPlugin : REIClientPlugin {
})
}
override fun registerEntryTypes(registry: EntryTypeRegistry) {
registry.register(SKYBLOCK_ITEM_TYPE_ID, SBItemEntryDefinition)
}
override fun registerCategories(registry: CategoryRegistry) {
registry.add(SBCraftingRecipe.Category)

View File

@@ -21,6 +21,7 @@ class ScreenRegistryHoveredItemStackProvider : HoveredItemStackProvider {
return entryStack.value as? ItemStack ?: entryStack.cheatsAs().value
}
}
@AutoService(HoveredItemStackProvider::class)
@CompatLoader.RequireMod("roughlyenoughitems")
class OverlayHoveredItemStackProvider : HoveredItemStackProvider {

View File

@@ -25,163 +25,128 @@ import net.minecraft.client.render.LightmapTextureManager
import net.minecraft.client.render.OverlayTexture
import net.minecraft.client.render.VertexConsumerProvider
import net.minecraft.client.render.model.BakedModel
import net.minecraft.client.render.model.json.ModelTransformationMode
import net.minecraft.client.texture.SpriteAtlasTexture
import net.minecraft.item.Item
import net.minecraft.item.ItemStack
import net.minecraft.item.tooltip.TooltipType
import net.minecraft.item.ModelTransformationMode
import moe.nea.firmament.compat.rei.FirmamentReiPlugin.Companion.asItemEntry
import moe.nea.firmament.repo.SBItemStack
import moe.nea.firmament.util.MC
import moe.nea.firmament.util.mc.displayNameAccordingToNbt
import moe.nea.firmament.util.mc.loreAccordingToNbt
object NEUItemEntryRenderer : EntryRenderer<SBItemStack>, BatchedEntryRenderer<SBItemStack, BakedModel> {
override fun render(
entry: EntryStack<SBItemStack>,
context: DrawContext,
bounds: Rectangle,
mouseX: Int,
mouseY: Int,
delta: Float
) {
entry.asItemEntry().render(context, bounds, mouseX, mouseY, delta)
}
override fun render(
entry: EntryStack<SBItemStack>,
context: DrawContext,
bounds: Rectangle,
mouseX: Int,
mouseY: Int,
delta: Float
) {
entry.asItemEntry().render(context, bounds, mouseX, mouseY, delta)
}
val minecraft = MinecraftClient.getInstance()
val minecraft = MinecraftClient.getInstance()
override fun getTooltip(entry: EntryStack<SBItemStack>, tooltipContext: TooltipContext): Tooltip? {
val stack = entry.value.asImmutableItemStack()
val lore = stack.getTooltip(
Item.TooltipContext.DEFAULT,
null,
TooltipType.BASIC
)
return Tooltip.create(lore)
}
override fun getTooltip(entry: EntryStack<SBItemStack>, tooltipContext: TooltipContext): Tooltip? {
val stack = entry.value.asImmutableItemStack()
override fun getExtraData(entry: EntryStack<SBItemStack>): BakedModel {
return minecraft.itemRenderer.getModel(entry.asItemEntry().value, minecraft.world, minecraft.player, 0)
}
val lore = mutableListOf(stack.displayNameAccordingToNbt)
lore.addAll(stack.loreAccordingToNbt)
override fun getBatchIdentifier(entry: EntryStack<SBItemStack>?, bounds: Rectangle?, extraData: BakedModel): Int {
return 1738923 + if (extraData.isSideLit) 1 else 0
}
// TODO: tags aren't sent as early now so some tooltip components that use tags will crash the game
// stack.getTooltip(
// Item.TooltipContext.create(
// tooltipContext.vanillaContext().registryLookup
// ?: MC.defaultRegistries
// ),
// MC.player,
// TooltipType.BASIC
// )
return Tooltip.create(lore)
}
override fun startBatch(
entry: EntryStack<SBItemStack>,
model: BakedModel,
graphics: DrawContext,
delta: Float
) {
val modelViewStack = RenderSystem.getModelViewStack()
modelViewStack.pushMatrix()
modelViewStack.scale(20.0f, 20.0f, 1.0f)
RenderSystem.applyModelViewMatrix()
setupGL(model)
}
override fun getExtraData(entry: EntryStack<SBItemStack>): BakedModel {
return MC.itemRenderer.getModel(entry.asItemEntry().value,
MC.world,
MC.player, 0)
fun setupGL(model: BakedModel) {
minecraft.textureManager.getTexture(SpriteAtlasTexture.BLOCK_ATLAS_TEXTURE)
.setFilter(false, false)
RenderSystem.setShaderTexture(0, SpriteAtlasTexture.BLOCK_ATLAS_TEXTURE)
RenderSystem.enableBlend()
RenderSystem.blendFunc(SrcFactor.SRC_ALPHA, DstFactor.ONE_MINUS_SRC_ALPHA)
RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, 1.0f)
val sideLit = model.isSideLit
if (!sideLit) {
DiffuseLighting.disableGuiDepthLighting()
}
}
}
override fun renderBase(
entry: EntryStack<SBItemStack>,
model: BakedModel,
graphics: DrawContext,
immediate: VertexConsumerProvider.Immediate,
bounds: Rectangle,
mouseX: Int,
mouseY: Int,
delta: Float
) {
if (entry.isEmpty) return
val value = entry.asItemEntry().value
graphics.matrices.push()
graphics.matrices.translate(bounds.centerX.toFloat() / 20.0f, bounds.centerY.toFloat() / 20.0f, 0.0f)
graphics.matrices.scale(
bounds.getWidth().toFloat() / 20.0f,
-(bounds.getWidth() + bounds.getHeight()).toFloat() / 2.0f / 20.0f,
1.0f
)
minecraft
.itemRenderer
.renderItem(
value,
ModelTransformationMode.GUI,
false,
graphics.matrices,
immediate,
LightmapTextureManager.MAX_LIGHT_COORDINATE,
OverlayTexture.DEFAULT_UV,
model
)
graphics.matrices.pop()
override fun getBatchIdentifier(entry: EntryStack<SBItemStack>, bounds: Rectangle?, extraData: BakedModel): Int {
return 1738923 + if (extraData.isSideLit) 1 else 0
}
}
override fun afterBase(
entry: EntryStack<SBItemStack>,
model: BakedModel,
graphics: DrawContext,
delta: Float
) {
RenderSystem.getModelViewStack().popMatrix()
RenderSystem.applyModelViewMatrix()
this.endGL(model)
}
override fun startBatch(entryStack: EntryStack<SBItemStack>, e: BakedModel, drawContext: DrawContext, v: Float) {
MC.textureManager.getTexture(SpriteAtlasTexture.BLOCK_ATLAS_TEXTURE)
.setFilter(false, false)
RenderSystem.setShaderTexture(0, SpriteAtlasTexture.BLOCK_ATLAS_TEXTURE)
RenderSystem.enableBlend()
RenderSystem.blendFunc(SrcFactor.SRC_ALPHA, DstFactor.ONE_MINUS_SRC_ALPHA)
RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, 1.0f)
if (!e.isSideLit) {
DiffuseLighting.disableGuiDepthLighting()
}
}
fun endGL(model: BakedModel) {
RenderSystem.enableDepthTest()
val sideLit = model.isSideLit
if (!sideLit) {
DiffuseLighting.enableGuiDepthLighting()
}
}
override fun renderBase(
entryStack: EntryStack<SBItemStack>,
model: BakedModel,
drawContext: DrawContext,
immediate: VertexConsumerProvider.Immediate,
bounds: Rectangle,
i: Int,
i1: Int,
v: Float
) {
if (entryStack.isEmpty) return
drawContext.matrices.push()
drawContext.matrices.translate(bounds.centerX.toDouble(), bounds.centerY.toDouble(), 0.0)
// TODO: check the scaling here again
drawContext.matrices.scale(
bounds.width.toFloat(),
(bounds.height + bounds.height) / -2F,
(bounds.width + bounds.height) / 2f)
MC.itemRenderer.renderItem(
entryStack.value.asImmutableItemStack(),
ModelTransformationMode.GUI,
false, drawContext.matrices,
immediate, LightmapTextureManager.MAX_LIGHT_COORDINATE,
OverlayTexture.DEFAULT_UV,
model
)
drawContext.matrices.pop()
}
override fun renderOverlay(
entry: EntryStack<SBItemStack>,
extraData: BakedModel,
graphics: DrawContext,
immediate: VertexConsumerProvider.Immediate,
bounds: Rectangle,
mouseX: Int,
mouseY: Int,
delta: Float
) {
val modelViewStack = RenderSystem.getModelViewStack()
modelViewStack.pushMatrix()
modelViewStack.mul(graphics.matrices.peek().positionMatrix)
modelViewStack.translate(bounds.x.toFloat(), bounds.y.toFloat(), 0.0f)
modelViewStack.scale(
bounds.width.toFloat() / 16.0f,
-(bounds.getWidth() + bounds.getHeight()).toFloat() / 2.0f / 16.0f,
1.0f
)
RenderSystem.applyModelViewMatrix()
renderOverlay(DrawContext(minecraft, graphics.vertexConsumers), entry.asItemEntry())
modelViewStack.popMatrix()
RenderSystem.applyModelViewMatrix()
}
override fun afterBase(entryStack: EntryStack<SBItemStack>?, e: BakedModel, drawContext: DrawContext?, v: Float) {
RenderSystem.enableDepthTest()
if (!e.isSideLit)
DiffuseLighting.enableGuiDepthLighting()
}
fun renderOverlay(graphics: DrawContext, entry: EntryStack<ItemStack>) {
if (!entry.isEmpty) {
graphics.drawItemInSlot(MinecraftClient.getInstance().textRenderer, entry.value, 0, 0, null)
}
}
override fun renderOverlay(
entryStack: EntryStack<SBItemStack>,
e: BakedModel,
drawContext: DrawContext,
immediate: VertexConsumerProvider.Immediate,
bounds: Rectangle,
i: Int,
i1: Int,
v: Float
) {
if (entryStack.isEmpty) return
val modelViewStack = RenderSystem.getModelViewStack()
modelViewStack.pushMatrix()
modelViewStack.mul(drawContext.matrices.peek().positionMatrix)
modelViewStack.translate(bounds.x.toFloat(), bounds.y.toFloat(), 0F)
modelViewStack.scale(bounds.width / 16.0f,
(bounds.width + bounds.height) / 2.0f / 16.0f,
1.0f) // TODO: weird scale again
drawContext.drawStackOverlay(MC.font, entryStack.value.asImmutableItemStack(), 0, 0, null)
modelViewStack.popMatrix()
}
override fun endBatch(
entry: EntryStack<SBItemStack>?,
extraData: BakedModel?,
graphics: DrawContext?,
delta: Float
) {
}
override fun endBatch(entryStack: EntryStack<SBItemStack>?, e: BakedModel?, drawContext: DrawContext?, v: Float) {
}
}

View File

@@ -1,30 +1,17 @@
package moe.nea.firmament.compat.rei
import com.mojang.serialization.Codec
import me.shedaniel.rei.api.common.entry.EntrySerializer
import me.shedaniel.rei.api.common.entry.EntryStack
import net.minecraft.nbt.NbtCompound
import net.minecraft.network.RegistryByteBuf
import net.minecraft.network.codec.PacketCodec
import moe.nea.firmament.repo.SBItemStack
import moe.nea.firmament.util.SkyblockId
object NEUItemEntrySerializer : EntrySerializer<SBItemStack> {
const val SKYBLOCK_ID_ENTRY = "SKYBLOCK_ID"
const val SKYBLOCK_ITEM_COUNT = "SKYBLOCK_ITEM_COUNT"
override fun codec(): Codec<SBItemStack> {
return SBItemStack.CODEC
}
override fun supportSaving(): Boolean = true
override fun supportReading(): Boolean = true
override fun read(tag: NbtCompound): SBItemStack {
val id = SkyblockId(tag.getString(SKYBLOCK_ID_ENTRY))
val count = if (tag.contains(SKYBLOCK_ITEM_COUNT)) tag.getInt(SKYBLOCK_ITEM_COUNT) else 1
return SBItemStack(id, count)
}
override fun save(entry: EntryStack<SBItemStack>, value: SBItemStack): NbtCompound {
return NbtCompound().apply {
putString(SKYBLOCK_ID_ENTRY, value.skyblockId.neuItem)
putInt(SKYBLOCK_ITEM_COUNT, value.getStackSize())
}
}
override fun streamCodec(): PacketCodec<RegistryByteBuf, SBItemStack> {
return SBItemStack.PACKET_CODEC.cast()
}
}

View File

@@ -1,10 +1,8 @@
package moe.nea.firmament.compat.rei
import me.shedaniel.math.Point
operator fun Point.plus(other: Point): Point = Point(
this.x + other.x,
this.y + other.y,
this.x + other.x,
this.y + other.y,
)

View File

@@ -1,5 +1,3 @@
package moe.nea.firmament.compat.rei.recipes
import io.github.moulberry.repo.data.NEUCraftingRecipe
@@ -11,6 +9,8 @@ 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.display.Display
import me.shedaniel.rei.api.common.display.DisplaySerializer
import me.shedaniel.rei.api.common.util.EntryStacks
import net.minecraft.block.Blocks
import net.minecraft.text.Text
@@ -18,38 +18,38 @@ import moe.nea.firmament.Firmament
import moe.nea.firmament.compat.rei.SBItemEntryDefinition
class SBCraftingRecipe(override val neuRecipe: NEUCraftingRecipe) : SBRecipe() {
override fun getCategoryIdentifier(): CategoryIdentifier<*> = Category.catIdentifier
override fun getCategoryIdentifier(): CategoryIdentifier<*> = Category.catIdentifier
object Category : DisplayCategory<SBCraftingRecipe> {
val catIdentifier = CategoryIdentifier.of<SBCraftingRecipe>(Firmament.MOD_ID, "crafing_recipe")
override fun getCategoryIdentifier(): CategoryIdentifier<out SBCraftingRecipe> = catIdentifier
object Category : DisplayCategory<SBCraftingRecipe> {
val catIdentifier = CategoryIdentifier.of<SBCraftingRecipe>(Firmament.MOD_ID, "crafing_recipe")
override fun getCategoryIdentifier(): CategoryIdentifier<out SBCraftingRecipe> = catIdentifier
override fun getTitle(): Text = Text.literal("SkyBlock Crafting")
override fun getTitle(): Text = Text.literal("SkyBlock Crafting")
override fun getIcon(): Renderer = EntryStacks.of(Blocks.CRAFTING_TABLE)
override fun setupDisplay(display: SBCraftingRecipe, bounds: Rectangle): List<Widget> {
val point = Point(bounds.centerX - 58, bounds.centerY - 27)
return buildList {
add(Widgets.createRecipeBase(bounds))
add(Widgets.createArrow(Point(point.x + 60, point.y + 18)))
add(Widgets.createResultSlotBackground(Point(point.x + 95, point.y + 19)))
for (i in 0 until 3) {
for (j in 0 until 3) {
val slot = Widgets.createSlot(Point(point.x + 1 + i * 18, point.y + 1 + j * 18)).markInput()
add(slot)
val item = display.neuRecipe.inputs[i + j * 3]
if (item == NEUIngredient.SENTINEL_EMPTY) continue
slot.entry(SBItemEntryDefinition.getEntry(item)) // TODO: make use of stackable item entries
}
}
add(
Widgets.createSlot(Point(point.x + 95, point.y + 19))
.entry(SBItemEntryDefinition.getEntry(display.neuRecipe.output))
.disableBackground().markOutput()
)
}
}
override fun getIcon(): Renderer = EntryStacks.of(Blocks.CRAFTING_TABLE)
override fun setupDisplay(display: SBCraftingRecipe, bounds: Rectangle): List<Widget> {
val point = Point(bounds.centerX - 58, bounds.centerY - 27)
return buildList {
add(Widgets.createRecipeBase(bounds))
add(Widgets.createArrow(Point(point.x + 60, point.y + 18)))
add(Widgets.createResultSlotBackground(Point(point.x + 95, point.y + 19)))
for (i in 0 until 3) {
for (j in 0 until 3) {
val slot = Widgets.createSlot(Point(point.x + 1 + i * 18, point.y + 1 + j * 18)).markInput()
add(slot)
val item = display.neuRecipe.inputs[i + j * 3]
if (item == NEUIngredient.SENTINEL_EMPTY) continue
slot.entry(SBItemEntryDefinition.getEntry(item)) // TODO: make use of stackable item entries
}
}
add(
Widgets.createSlot(Point(point.x + 95, point.y + 19))
.entry(SBItemEntryDefinition.getEntry(display.neuRecipe.output))
.disableBackground().markOutput()
)
}
}
}
}
}

View File

@@ -1,4 +1,3 @@
package moe.nea.firmament.compat.rei.recipes
import me.shedaniel.math.Point
@@ -16,47 +15,47 @@ import moe.nea.firmament.repo.SBItemStack
import moe.nea.firmament.util.SkyblockId
class SBEssenceUpgradeRecipe(override val neuRecipe: EssenceRecipeProvider.EssenceUpgradeRecipe) : SBRecipe() {
object Category : DisplayCategory<SBEssenceUpgradeRecipe> {
override fun getCategoryIdentifier(): CategoryIdentifier<SBEssenceUpgradeRecipe> =
CategoryIdentifier.of(Firmament.MOD_ID, "essence_upgrade")
object Category : DisplayCategory<SBEssenceUpgradeRecipe> {
override fun getCategoryIdentifier(): CategoryIdentifier<SBEssenceUpgradeRecipe> =
CategoryIdentifier.of(Firmament.MOD_ID, "essence_upgrade")
override fun getTitle(): Text {
return Text.literal("Essence Upgrades")
}
override fun getTitle(): Text {
return Text.literal("Essence Upgrades")
}
override fun getIcon(): Renderer {
return SBItemEntryDefinition.getEntry(SkyblockId("ESSENCE_WITHER"))
}
override fun getIcon(): Renderer {
return SBItemEntryDefinition.getEntry(SkyblockId("ESSENCE_WITHER"))
}
override fun setupDisplay(display: SBEssenceUpgradeRecipe, bounds: Rectangle): List<Widget> {
val recipe = display.neuRecipe
val list = mutableListOf<Widget>()
list.add(Widgets.createRecipeBase(bounds))
list.add(Widgets.createSlot(Point(bounds.minX + 12, bounds.centerY - 8 - 18 / 2))
.markInput()
.entry(SBItemEntryDefinition.getEntry(SBItemStack(recipe.itemId).copy(stars = recipe.starCountAfter - 1))))
list.add(Widgets.createSlot(Point(bounds.minX + 12, bounds.centerY - 8 + 18 / 2))
.markInput()
.entry(SBItemEntryDefinition.getEntry(recipe.essenceIngredient)))
list.add(Widgets.createSlot(Point(bounds.maxX - 12 - 16, bounds.centerY - 8))
.markOutput()
.entry(SBItemEntryDefinition.getEntry(SBItemStack(recipe.itemId).copy(stars = recipe.starCountAfter))))
val extraItems = recipe.extraItems
list.add(Widgets.createArrow(Point(bounds.centerX - 24 / 2,
if (extraItems.isEmpty()) bounds.centerY - 17 / 2
else bounds.centerY + 18 / 2)))
for ((index, item) in extraItems.withIndex()) {
list.add(Widgets.createSlot(
Point(bounds.centerX - extraItems.size * 16 / 2 - 2 / 2 + index * 18,
bounds.centerY - 18 / 2))
.markInput()
.entry(SBItemEntryDefinition.getEntry(item)))
}
return list
}
}
override fun setupDisplay(display: SBEssenceUpgradeRecipe, bounds: Rectangle): List<Widget> {
val recipe = display.neuRecipe
val list = mutableListOf<Widget>()
list.add(Widgets.createRecipeBase(bounds))
list.add(Widgets.createSlot(Point(bounds.minX + 12, bounds.centerY - 8 - 18 / 2))
.markInput()
.entry(SBItemEntryDefinition.getEntry(SBItemStack(recipe.itemId).copy(stars = recipe.starCountAfter - 1))))
list.add(Widgets.createSlot(Point(bounds.minX + 12, bounds.centerY - 8 + 18 / 2))
.markInput()
.entry(SBItemEntryDefinition.getEntry(recipe.essenceIngredient)))
list.add(Widgets.createSlot(Point(bounds.maxX - 12 - 16, bounds.centerY - 8))
.markOutput()
.entry(SBItemEntryDefinition.getEntry(SBItemStack(recipe.itemId).copy(stars = recipe.starCountAfter))))
val extraItems = recipe.extraItems
list.add(Widgets.createArrow(Point(bounds.centerX - 24 / 2,
if (extraItems.isEmpty()) bounds.centerY - 17 / 2
else bounds.centerY + 18 / 2)))
for ((index, item) in extraItems.withIndex()) {
list.add(Widgets.createSlot(
Point(bounds.centerX - extraItems.size * 16 / 2 - 2 / 2 + index * 18,
bounds.centerY - 18 / 2))
.markInput()
.entry(SBItemEntryDefinition.getEntry(item)))
}
return list
}
}
override fun getCategoryIdentifier(): CategoryIdentifier<*> {
return Category.categoryIdentifier
}
override fun getCategoryIdentifier(): CategoryIdentifier<*> {
return Category.categoryIdentifier
}
}

View File

@@ -1,5 +1,3 @@
package moe.nea.firmament.compat.rei.recipes
import io.github.moulberry.repo.data.NEUForgeRecipe
@@ -21,51 +19,53 @@ import moe.nea.firmament.compat.rei.SBItemEntryDefinition
import moe.nea.firmament.compat.rei.plus
class SBForgeRecipe(override val neuRecipe: NEUForgeRecipe) : SBRecipe() {
override fun getCategoryIdentifier(): CategoryIdentifier<*> = Category.categoryIdentifier
override fun getCategoryIdentifier(): CategoryIdentifier<*> = Category.categoryIdentifier
object Category : DisplayCategory<SBForgeRecipe> {
override fun getCategoryIdentifier(): CategoryIdentifier<SBForgeRecipe> =
CategoryIdentifier.of(Firmament.MOD_ID, "forge_recipe")
object Category : DisplayCategory<SBForgeRecipe> {
override fun getCategoryIdentifier(): CategoryIdentifier<SBForgeRecipe> =
CategoryIdentifier.of(Firmament.MOD_ID, "forge_recipe")
override fun getTitle(): Text = Text.literal("Forge Recipes")
override fun getDisplayHeight(): Int {
return 104
}
override fun getTitle(): Text = Text.literal("Forge Recipes")
override fun getDisplayHeight(): Int {
return 104
}
override fun getIcon(): Renderer = EntryStacks.of(Blocks.ANVIL)
override fun setupDisplay(display: SBForgeRecipe, bounds: Rectangle): List<Widget> {
return buildList {
add(Widgets.createRecipeBase(bounds))
add(Widgets.createResultSlotBackground(Point(bounds.minX + 124, bounds.minY + 46)))
val arrow = Widgets.createArrow(Point(bounds.minX + 90, bounds.minY + 54 - 18 / 2))
add(arrow)
add(Widgets.createTooltip(arrow.bounds, Text.stringifiedTranslatable("firmament.recipe.forge.time", display.neuRecipe.duration.seconds)))
val ingredientsCenter = Point(bounds.minX + 49 - 8, bounds.minY + 54 - 8)
val count = display.neuRecipe.inputs.size
if (count == 1) {
add(
Widgets.createSlot(Point(ingredientsCenter.x, ingredientsCenter.y)).markInput()
.entry(SBItemEntryDefinition.getEntry(display.neuRecipe.inputs.single()))
)
} else {
display.neuRecipe.inputs.forEachIndexed { idx, ingredient ->
val rad = Math.PI * 2 * idx / count
add(
Widgets.createSlot(
Point(
cos(rad) * 30,
sin(rad) * 30,
) + ingredientsCenter
).markInput().entry(SBItemEntryDefinition.getEntry(ingredient))
)
}
}
add(
Widgets.createSlot(Point(bounds.minX + 124, bounds.minY + 46)).markOutput().disableBackground()
.entry(SBItemEntryDefinition.getEntry(display.neuRecipe.outputStack))
)
}
}
}
override fun getIcon(): Renderer = EntryStacks.of(Blocks.ANVIL)
override fun setupDisplay(display: SBForgeRecipe, bounds: Rectangle): List<Widget> {
return buildList {
add(Widgets.createRecipeBase(bounds))
add(Widgets.createResultSlotBackground(Point(bounds.minX + 124, bounds.minY + 46)))
val arrow = Widgets.createArrow(Point(bounds.minX + 90, bounds.minY + 54 - 18 / 2))
add(arrow)
add(Widgets.createTooltip(arrow.bounds,
Text.stringifiedTranslatable("firmament.recipe.forge.time",
display.neuRecipe.duration.seconds)))
val ingredientsCenter = Point(bounds.minX + 49 - 8, bounds.minY + 54 - 8)
val count = display.neuRecipe.inputs.size
if (count == 1) {
add(
Widgets.createSlot(Point(ingredientsCenter.x, ingredientsCenter.y)).markInput()
.entry(SBItemEntryDefinition.getEntry(display.neuRecipe.inputs.single()))
)
} else {
display.neuRecipe.inputs.forEachIndexed { idx, ingredient ->
val rad = Math.PI * 2 * idx / count
add(
Widgets.createSlot(
Point(
cos(rad) * 30,
sin(rad) * 30,
) + ingredientsCenter
).markInput().entry(SBItemEntryDefinition.getEntry(ingredient))
)
}
}
add(
Widgets.createSlot(Point(bounds.minX + 124, bounds.minY + 46)).markOutput().disableBackground()
.entry(SBItemEntryDefinition.getEntry(display.neuRecipe.outputStack))
)
}
}
}
}

View File

@@ -1,4 +1,3 @@
package moe.nea.firmament.compat.rei.recipes
import io.github.moulberry.repo.data.NEUKatUpgradeRecipe
@@ -20,7 +19,6 @@ import me.shedaniel.rei.api.client.registry.display.DisplayCategory
import me.shedaniel.rei.api.common.category.CategoryIdentifier
import me.shedaniel.rei.api.common.util.EntryStacks
import kotlin.time.Duration.Companion.seconds
import net.minecraft.block.Blocks
import net.minecraft.client.gui.DrawContext
import net.minecraft.client.gui.Element
import net.minecraft.item.Items
@@ -34,191 +32,191 @@ import moe.nea.firmament.util.MC
import moe.nea.firmament.util.SkyblockId
class SBKatRecipe(override val neuRecipe: NEUKatUpgradeRecipe) : SBRecipe() {
override fun getCategoryIdentifier(): CategoryIdentifier<*> = Category.categoryIdentifier
override fun getCategoryIdentifier(): CategoryIdentifier<*> = Category.categoryIdentifier
object Category : DisplayCategory<SBKatRecipe> {
override fun getCategoryIdentifier(): CategoryIdentifier<SBKatRecipe> =
CategoryIdentifier.of(Firmament.MOD_ID, "kat_recipe")
object Category : DisplayCategory<SBKatRecipe> {
override fun getCategoryIdentifier(): CategoryIdentifier<SBKatRecipe> =
CategoryIdentifier.of(Firmament.MOD_ID, "kat_recipe")
override fun getTitle(): Text = Text.literal("Kat Pet Upgrade")
override fun getDisplayHeight(): Int {
return 100
}
override fun getTitle(): Text = Text.literal("Kat Pet Upgrade")
override fun getDisplayHeight(): Int {
return 100
}
override fun getIcon(): Renderer = EntryStacks.of(Items.BONE)
override fun setupDisplay(display: SBKatRecipe, bounds: Rectangle): List<Widget> {
return buildList {
val arrowWidth = 24
val recipe = display.neuRecipe
val levelValue = Property.upgrade(GetSetter.floating(0F))
val slider = SliderComponent(levelValue, 1F, 100F, 1f, 100)
val outputStack = SBItemStack(SkyblockId(recipe.output.itemId))
val inputStack = SBItemStack(SkyblockId(recipe.input.itemId))
val inputLevelLabelCenter = Point(bounds.minX + 30 - 18 + 5 + 8, bounds.minY + 25)
val inputLevelLabel = Widgets.createLabel(
inputLevelLabelCenter,
Text.literal("")).centered()
val outputLevelLabelCenter = Point(bounds.maxX - 30 + 8, bounds.minY + 25)
val outputLevelLabel = Widgets.createLabel(
outputLevelLabelCenter,
Text.literal("")).centered()
val coinStack = SBItemStack(SkyblockId.COINS, recipe.coins.toInt())
levelValue.whenChanged { oldValue, newValue ->
if (oldValue.toInt() == newValue.toInt()) return@whenChanged
val oldInput = inputStack.getPetData() ?: return@whenChanged
val newInput = PetData.forLevel(oldInput.petId, oldInput.rarity, newValue.toInt())
inputStack.setPetData(newInput)
val oldOutput = outputStack.getPetData() ?: return@whenChanged
val newOutput = PetData(oldOutput.rarity, oldOutput.petId, newInput.exp)
outputStack.setPetData(newOutput)
inputLevelLabel.message = Text.literal(newInput.levelData.currentLevel.toString())
inputLevelLabel.bounds.location = Point(
inputLevelLabelCenter.x - MC.font.getWidth(inputLevelLabel.message) / 2,
inputLevelLabelCenter.y)
outputLevelLabel.message = Text.literal(newOutput.levelData.currentLevel.toString())
outputLevelLabel.bounds.location = Point(
outputLevelLabelCenter.x - MC.font.getWidth(outputLevelLabel.message) / 2,
outputLevelLabelCenter.y)
coinStack.setStackSize((recipe.coins * (1 - 0.3 * newValue / 100)).toInt())
}
levelValue.set(1F)
add(Widgets.createRecipeBase(bounds))
add(wrapWidget(Rectangle(bounds.centerX - slider.width / 2,
bounds.maxY - 30,
slider.width,
slider.height),
slider))
add(Widgets.withTooltip(
Widgets.createArrow(Point(bounds.centerX - arrowWidth / 2, bounds.minY + 40)),
Text.literal("Upgrade time: " + FirmFormatters.formatTimespan(recipe.seconds.seconds))))
override fun getIcon(): Renderer = EntryStacks.of(Items.BONE)
override fun setupDisplay(display: SBKatRecipe, bounds: Rectangle): List<Widget> {
return buildList {
val arrowWidth = 24
val recipe = display.neuRecipe
val levelValue = Property.upgrade(GetSetter.floating(0F))
val slider = SliderComponent(levelValue, 1F, 100F, 1f, 100)
val outputStack = SBItemStack(SkyblockId(recipe.output.itemId))
val inputStack = SBItemStack(SkyblockId(recipe.input.itemId))
val inputLevelLabelCenter = Point(bounds.minX + 30 - 18 + 5 + 8, bounds.minY + 25)
val inputLevelLabel = Widgets.createLabel(
inputLevelLabelCenter,
Text.literal("")).centered()
val outputLevelLabelCenter = Point(bounds.maxX - 30 + 8, bounds.minY + 25)
val outputLevelLabel = Widgets.createLabel(
outputLevelLabelCenter,
Text.literal("")).centered()
val coinStack = SBItemStack(SkyblockId.COINS, recipe.coins.toInt())
levelValue.whenChanged { oldValue, newValue ->
if (oldValue.toInt() == newValue.toInt()) return@whenChanged
val oldInput = inputStack.getPetData() ?: return@whenChanged
val newInput = PetData.forLevel(oldInput.petId, oldInput.rarity, newValue.toInt())
inputStack.setPetData(newInput)
val oldOutput = outputStack.getPetData() ?: return@whenChanged
val newOutput = PetData(oldOutput.rarity, oldOutput.petId, newInput.exp)
outputStack.setPetData(newOutput)
inputLevelLabel.message = Text.literal(newInput.levelData.currentLevel.toString())
inputLevelLabel.bounds.location = Point(
inputLevelLabelCenter.x - MC.font.getWidth(inputLevelLabel.message) / 2,
inputLevelLabelCenter.y)
outputLevelLabel.message = Text.literal(newOutput.levelData.currentLevel.toString())
outputLevelLabel.bounds.location = Point(
outputLevelLabelCenter.x - MC.font.getWidth(outputLevelLabel.message) / 2,
outputLevelLabelCenter.y)
coinStack.setStackSize((recipe.coins * (1 - 0.3 * newValue / 100)).toInt())
}
levelValue.set(1F)
add(Widgets.createRecipeBase(bounds))
add(wrapWidget(Rectangle(bounds.centerX - slider.width / 2,
bounds.maxY - 30,
slider.width,
slider.height),
slider))
add(Widgets.withTooltip(
Widgets.createArrow(Point(bounds.centerX - arrowWidth / 2, bounds.minY + 40)),
Text.literal("Upgrade time: " + FirmFormatters.formatTimespan(recipe.seconds.seconds))))
add(Widgets.createResultSlotBackground(Point(bounds.maxX - 30, bounds.minY + 40)))
add(inputLevelLabel)
add(outputLevelLabel)
add(Widgets.createSlot(Point(bounds.maxX - 30, bounds.minY + 40)).markOutput().disableBackground()
.entry(SBItemEntryDefinition.getEntry(outputStack)))
add(Widgets.createSlot(Point(bounds.minX + 30 - 18 + 5, bounds.minY + 40)).markInput()
.entry(SBItemEntryDefinition.getEntry(inputStack)))
add(Widgets.createResultSlotBackground(Point(bounds.maxX - 30, bounds.minY + 40)))
add(inputLevelLabel)
add(outputLevelLabel)
add(Widgets.createSlot(Point(bounds.maxX - 30, bounds.minY + 40)).markOutput().disableBackground()
.entry(SBItemEntryDefinition.getEntry(outputStack)))
add(Widgets.createSlot(Point(bounds.minX + 30 - 18 + 5, bounds.minY + 40)).markInput()
.entry(SBItemEntryDefinition.getEntry(inputStack)))
val allInputs = recipe.items.map { SBItemEntryDefinition.getEntry(it) } +
listOf(SBItemEntryDefinition.getEntry(coinStack))
for ((index, item) in allInputs.withIndex()) {
add(Widgets.createSlot(
Point(bounds.centerX + index * 20 - allInputs.size * 18 / 2 - (allInputs.size - 1) * 2 / 2,
bounds.minY + 20))
.markInput()
.entry(item))
}
}
}
}
val allInputs = recipe.items.map { SBItemEntryDefinition.getEntry(it) } +
listOf(SBItemEntryDefinition.getEntry(coinStack))
for ((index, item) in allInputs.withIndex()) {
add(Widgets.createSlot(
Point(bounds.centerX + index * 20 - allInputs.size * 18 / 2 - (allInputs.size - 1) * 2 / 2,
bounds.minY + 20))
.markInput()
.entry(item))
}
}
}
}
}
fun wrapWidget(bounds: Rectangle, component: GuiComponent): Widget {
return object : WidgetWithBounds() {
override fun getBounds(): Rectangle {
return bounds
}
return object : WidgetWithBounds() {
override fun getBounds(): Rectangle {
return bounds
}
override fun children(): List<Element> {
return listOf()
}
override fun children(): List<Element> {
return listOf()
}
override fun render(context: DrawContext, mouseX: Int, mouseY: Int, delta: Float) {
context.matrices.push()
context.matrices.translate(bounds.minX.toFloat(), bounds.minY.toFloat(), 0F)
component.render(
GuiImmediateContext(
ModernRenderContext(context),
bounds.minX, bounds.minY,
bounds.width, bounds.height,
mouseX - bounds.minX, mouseY - bounds.minY,
mouseX, mouseY,
mouseX.toFloat(), mouseY.toFloat()
))
context.matrices.pop()
}
override fun render(context: DrawContext, mouseX: Int, mouseY: Int, delta: Float) {
context.matrices.push()
context.matrices.translate(bounds.minX.toFloat(), bounds.minY.toFloat(), 0F)
component.render(
GuiImmediateContext(
ModernRenderContext(context),
bounds.minX, bounds.minY,
bounds.width, bounds.height,
mouseX - bounds.minX, mouseY - bounds.minY,
mouseX, mouseY,
mouseX.toFloat(), mouseY.toFloat()
))
context.matrices.pop()
}
override fun mouseMoved(mouseX: Double, mouseY: Double) {
val mouseXInt = mouseX.toInt()
val mouseYInt = mouseY.toInt()
component.mouseEvent(MouseEvent.Move(0F, 0F),
GuiImmediateContext(
IMinecraft.instance.provideTopLevelRenderContext(),
bounds.minX, bounds.minY,
bounds.width, bounds.height,
mouseXInt - bounds.minX, mouseYInt - bounds.minY,
mouseXInt, mouseYInt,
mouseX.toFloat(), mouseY.toFloat()
))
}
override fun mouseMoved(mouseX: Double, mouseY: Double) {
val mouseXInt = mouseX.toInt()
val mouseYInt = mouseY.toInt()
component.mouseEvent(MouseEvent.Move(0F, 0F),
GuiImmediateContext(
IMinecraft.instance.provideTopLevelRenderContext(),
bounds.minX, bounds.minY,
bounds.width, bounds.height,
mouseXInt - bounds.minX, mouseYInt - bounds.minY,
mouseXInt, mouseYInt,
mouseX.toFloat(), mouseY.toFloat()
))
}
override fun mouseClicked(mouseX: Double, mouseY: Double, button: Int): Boolean {
val mouseXInt = mouseX.toInt()
val mouseYInt = mouseY.toInt()
return component.mouseEvent(MouseEvent.Click(button, true),
GuiImmediateContext(
IMinecraft.instance.provideTopLevelRenderContext(),
bounds.minX, bounds.minY,
bounds.width, bounds.height,
mouseXInt - bounds.minX, mouseYInt - bounds.minY,
mouseXInt, mouseYInt,
mouseX.toFloat(), mouseY.toFloat()
))
}
override fun mouseClicked(mouseX: Double, mouseY: Double, button: Int): Boolean {
val mouseXInt = mouseX.toInt()
val mouseYInt = mouseY.toInt()
return component.mouseEvent(MouseEvent.Click(button, true),
GuiImmediateContext(
IMinecraft.instance.provideTopLevelRenderContext(),
bounds.minX, bounds.minY,
bounds.width, bounds.height,
mouseXInt - bounds.minX, mouseYInt - bounds.minY,
mouseXInt, mouseYInt,
mouseX.toFloat(), mouseY.toFloat()
))
}
override fun mouseReleased(mouseX: Double, mouseY: Double, button: Int): Boolean {
val mouseXInt = mouseX.toInt()
val mouseYInt = mouseY.toInt()
return component.mouseEvent(MouseEvent.Click(button, false),
GuiImmediateContext(
IMinecraft.instance.provideTopLevelRenderContext(),
bounds.minX, bounds.minY,
bounds.width, bounds.height,
mouseXInt - bounds.minX, mouseYInt - bounds.minY,
mouseXInt, mouseYInt,
mouseX.toFloat(), mouseY.toFloat()
))
}
override fun mouseReleased(mouseX: Double, mouseY: Double, button: Int): Boolean {
val mouseXInt = mouseX.toInt()
val mouseYInt = mouseY.toInt()
return component.mouseEvent(MouseEvent.Click(button, false),
GuiImmediateContext(
IMinecraft.instance.provideTopLevelRenderContext(),
bounds.minX, bounds.minY,
bounds.width, bounds.height,
mouseXInt - bounds.minX, mouseYInt - bounds.minY,
mouseXInt, mouseYInt,
mouseX.toFloat(), mouseY.toFloat()
))
}
override fun mouseDragged(
mouseX: Double,
mouseY: Double,
button: Int,
deltaX: Double,
deltaY: Double
): Boolean {
val mouseXInt = mouseX.toInt()
val mouseYInt = mouseY.toInt()
return component.mouseEvent(MouseEvent.Move(deltaX.toFloat(), deltaY.toFloat()),
GuiImmediateContext(
IMinecraft.instance.provideTopLevelRenderContext(),
bounds.minX, bounds.minY,
bounds.width, bounds.height,
mouseXInt - bounds.minX, mouseYInt - bounds.minY,
mouseXInt, mouseYInt,
mouseX.toFloat(), mouseY.toFloat()
))
override fun mouseDragged(
mouseX: Double,
mouseY: Double,
button: Int,
deltaX: Double,
deltaY: Double
): Boolean {
val mouseXInt = mouseX.toInt()
val mouseYInt = mouseY.toInt()
return component.mouseEvent(MouseEvent.Move(deltaX.toFloat(), deltaY.toFloat()),
GuiImmediateContext(
IMinecraft.instance.provideTopLevelRenderContext(),
bounds.minX, bounds.minY,
bounds.width, bounds.height,
mouseXInt - bounds.minX, mouseYInt - bounds.minY,
mouseXInt, mouseYInt,
mouseX.toFloat(), mouseY.toFloat()
))
}
}
override fun mouseScrolled(
mouseX: Double,
mouseY: Double,
horizontalAmount: Double,
verticalAmount: Double
): Boolean {
val mouseXInt = mouseX.toInt()
val mouseYInt = mouseY.toInt()
return component.mouseEvent(MouseEvent.Scroll(verticalAmount.toFloat()),
GuiImmediateContext(
IMinecraft.instance.provideTopLevelRenderContext(),
bounds.minX, bounds.minY,
bounds.width, bounds.height,
mouseXInt - bounds.minX, mouseYInt - bounds.minY,
mouseXInt, mouseYInt,
mouseX.toFloat(), mouseY.toFloat()
))
}
}
override fun mouseScrolled(
mouseX: Double,
mouseY: Double,
horizontalAmount: Double,
verticalAmount: Double
): Boolean {
val mouseXInt = mouseX.toInt()
val mouseYInt = mouseY.toInt()
return component.mouseEvent(MouseEvent.Scroll(verticalAmount.toFloat()),
GuiImmediateContext(
IMinecraft.instance.provideTopLevelRenderContext(),
bounds.minX, bounds.minY,
bounds.width, bounds.height,
mouseXInt - bounds.minX, mouseYInt - bounds.minY,
mouseXInt, mouseYInt,
mouseX.toFloat(), mouseY.toFloat()
))
}
}
}

View File

@@ -1,4 +1,3 @@
package moe.nea.firmament.compat.rei.recipes
import io.github.moulberry.repo.data.NEUMobDropRecipe
@@ -14,95 +13,95 @@ import net.minecraft.item.Items
import net.minecraft.text.Text
import net.minecraft.util.Identifier
import moe.nea.firmament.Firmament
import moe.nea.firmament.gui.entity.EntityRenderer
import moe.nea.firmament.compat.rei.EntityWidget
import moe.nea.firmament.compat.rei.SBItemEntryDefinition
import moe.nea.firmament.gui.entity.EntityRenderer
class SBMobDropRecipe(override val neuRecipe: NEUMobDropRecipe) : SBRecipe() {
override fun getCategoryIdentifier(): CategoryIdentifier<*> = Category.categoryIdentifier
override fun getCategoryIdentifier(): CategoryIdentifier<*> = Category.categoryIdentifier
object Category : DisplayCategory<SBMobDropRecipe> {
override fun getCategoryIdentifier(): CategoryIdentifier<SBMobDropRecipe> =
CategoryIdentifier.of(Firmament.MOD_ID, "mob_drop_recipe")
object Category : DisplayCategory<SBMobDropRecipe> {
override fun getCategoryIdentifier(): CategoryIdentifier<SBMobDropRecipe> =
CategoryIdentifier.of(Firmament.MOD_ID, "mob_drop_recipe")
override fun getTitle(): Text = Text.literal("Mob Drops")
override fun getDisplayHeight(): Int {
return 100
}
override fun getTitle(): Text = Text.literal("Mob Drops")
override fun getDisplayHeight(): Int {
return 100
}
override fun getIcon(): Renderer = EntryStacks.of(Items.DIAMOND_SWORD)
override fun setupDisplay(display: SBMobDropRecipe, bounds: Rectangle): List<Widget> {
return buildList {
add(Widgets.createRecipeBase(bounds))
val source = display.neuRecipe.render
val entity = if (source.startsWith("@")) {
EntityRenderer.constructEntity(Identifier.of(source.substring(1)))
} else {
EntityRenderer.applyModifiers(source, listOf())
}
if (entity != null) {
val level = display.neuRecipe.level
val fullMobName =
if (level > 0) Text.translatable("firmament.recipe.mobs.name", level, display.neuRecipe.name)
else Text.translatable("firmament.recipe.mobs.name.nolevel", display.neuRecipe.name)
val tt = mutableListOf<Text>()
tt.add((fullMobName))
tt.add(Text.literal(""))
if (display.neuRecipe.coins > 0) {
tt.add(Text.stringifiedTranslatable("firmament.recipe.mobs.coins", display.neuRecipe.coins))
}
if (display.neuRecipe.combatExperience > 0) {
tt.add(
Text.stringifiedTranslatable(
"firmament.recipe.mobs.combat",
display.neuRecipe.combatExperience
)
)
}
if (display.neuRecipe.enchantingExperience > 0) {
tt.add(
Text.stringifiedTranslatable(
"firmament.recipe.mobs.exp",
display.neuRecipe.enchantingExperience
)
)
}
if (display.neuRecipe.extra != null)
display.neuRecipe.extra.mapTo(tt) { Text.literal(it) }
if (tt.size == 2)
tt.removeAt(1)
add(
Widgets.withTooltip(
EntityWidget(entity, Point(bounds.minX + 5, bounds.minY + 15)),
tt
)
)
}
add(
Widgets.createLabel(Point(bounds.minX + 15, bounds.minY + 5), Text.literal(display.neuRecipe.name))
.leftAligned()
)
var x = bounds.minX + 60
var y = bounds.minY + 20
for (drop in display.neuRecipe.drops) {
val lore = drop.extra.mapTo(mutableListOf()) { Text.literal(it) }
if (drop.chance != null) {
lore += listOf(Text.translatable("firmament.recipe.mobs.drops", drop.chance))
}
val item = SBItemEntryDefinition.getEntry(drop.dropItem)
.value.copy(extraLore = lore)
add(
Widgets.createSlot(Point(x, y)).markOutput()
.entries(listOf(SBItemEntryDefinition.getEntry(item)))
)
x += 18
if (x > bounds.maxX - 30) {
x = bounds.minX + 60
y += 18
}
}
}
}
}
override fun getIcon(): Renderer = EntryStacks.of(Items.DIAMOND_SWORD)
override fun setupDisplay(display: SBMobDropRecipe, bounds: Rectangle): List<Widget> {
return buildList {
add(Widgets.createRecipeBase(bounds))
val source = display.neuRecipe.render
val entity = if (source.startsWith("@")) {
EntityRenderer.constructEntity(Identifier.of(source.substring(1)))
} else {
EntityRenderer.applyModifiers(source, listOf())
}
if (entity != null) {
val level = display.neuRecipe.level
val fullMobName =
if (level > 0) Text.translatable("firmament.recipe.mobs.name", level, display.neuRecipe.name)
else Text.translatable("firmament.recipe.mobs.name.nolevel", display.neuRecipe.name)
val tt = mutableListOf<Text>()
tt.add((fullMobName))
tt.add(Text.literal(""))
if (display.neuRecipe.coins > 0) {
tt.add(Text.stringifiedTranslatable("firmament.recipe.mobs.coins", display.neuRecipe.coins))
}
if (display.neuRecipe.combatExperience > 0) {
tt.add(
Text.stringifiedTranslatable(
"firmament.recipe.mobs.combat",
display.neuRecipe.combatExperience
)
)
}
if (display.neuRecipe.enchantingExperience > 0) {
tt.add(
Text.stringifiedTranslatable(
"firmament.recipe.mobs.exp",
display.neuRecipe.enchantingExperience
)
)
}
if (display.neuRecipe.extra != null)
display.neuRecipe.extra.mapTo(tt) { Text.literal(it) }
if (tt.size == 2)
tt.removeAt(1)
add(
Widgets.withTooltip(
EntityWidget(entity, Point(bounds.minX + 5, bounds.minY + 15)),
tt
)
)
}
add(
Widgets.createLabel(Point(bounds.minX + 15, bounds.minY + 5), Text.literal(display.neuRecipe.name))
.leftAligned()
)
var x = bounds.minX + 60
var y = bounds.minY + 20
for (drop in display.neuRecipe.drops) {
val lore = drop.extra.mapTo(mutableListOf()) { Text.literal(it) }
if (drop.chance != null) {
lore += listOf(Text.translatable("firmament.recipe.mobs.drops", drop.chance))
}
val item = SBItemEntryDefinition.getEntry(drop.dropItem)
.value.copy(extraLore = lore)
add(
Widgets.createSlot(Point(x, y)).markOutput()
.entries(listOf(SBItemEntryDefinition.getEntry(item)))
)
x += 18
if (x > bounds.maxX - 30) {
x = bounds.minX + 60
y += 18
}
}
}
}
}
}

View File

@@ -2,28 +2,41 @@ package moe.nea.firmament.compat.rei.recipes
import io.github.moulberry.repo.data.NEUIngredient
import io.github.moulberry.repo.data.NEURecipe
import java.util.Optional
import me.shedaniel.rei.api.common.display.Display
import me.shedaniel.rei.api.common.display.DisplaySerializer
import me.shedaniel.rei.api.common.entry.EntryIngredient
import net.minecraft.util.Identifier
import moe.nea.firmament.compat.rei.SBItemEntryDefinition
import moe.nea.firmament.util.SkyblockId
abstract class SBRecipe : Display {
abstract val neuRecipe: NEURecipe
override fun getInputEntries(): List<EntryIngredient> {
return neuRecipe.allInputs
.filter { it.itemId != NEUIngredient.NEU_SENTINEL_EMPTY }
.map {
val entryStack = SBItemEntryDefinition.getEntry(SkyblockId(it.itemId))
EntryIngredient.of(entryStack)
}
}
override fun getDisplayLocation(): Optional<Identifier> {
// In theory, we could return a location for the neuRecipe here. (Something along the lines of neurepo:items/item_id.json/0 for the 0th recipe in the items/item_id.json recipes array).
return Optional.empty()
}
override fun getOutputEntries(): List<EntryIngredient> {
return neuRecipe.allOutputs
.filter { it.itemId != NEUIngredient.NEU_SENTINEL_EMPTY }
.map {
val entryStack = SBItemEntryDefinition.getEntry(SkyblockId(it.itemId))
EntryIngredient.of(entryStack)
}
}
override fun getSerializer(): DisplaySerializer<out Display>? {
// While returning null here is discouraged, we are fine to do so, since this recipe will never travel through the network
return null
}
abstract val neuRecipe: NEURecipe
override fun getInputEntries(): List<EntryIngredient> {
return neuRecipe.allInputs
.filter { it.itemId != NEUIngredient.NEU_SENTINEL_EMPTY }
.map {
val entryStack = SBItemEntryDefinition.getEntry(SkyblockId(it.itemId))
EntryIngredient.of(entryStack)
}
}
override fun getOutputEntries(): List<EntryIngredient> {
return neuRecipe.allOutputs
.filter { it.itemId != NEUIngredient.NEU_SENTINEL_EMPTY }
.map {
val entryStack = SBItemEntryDefinition.getEntry(SkyblockId(it.itemId))
EntryIngredient.of(entryStack)
}
}
}

View File

@@ -1,6 +1,6 @@
package moe.nea.firmament.compat.sodium
import me.jellysquid.mods.sodium.client.render.SodiumWorldRenderer
import net.caffeinemc.mods.sodium.client.render.SodiumWorldRenderer
import moe.nea.firmament.mixins.accessor.sodium.AccessorSodiumWorldRenderer
class SodiumChunkReloader : Runnable {

View File

@@ -1,7 +1,7 @@
package moe.nea.firmament.mixins.accessor.sodium;
import me.jellysquid.mods.sodium.client.render.SodiumWorldRenderer;
import me.jellysquid.mods.sodium.client.render.chunk.RenderSectionManager;
import net.caffeinemc.mods.sodium.client.render.SodiumWorldRenderer;
import net.caffeinemc.mods.sodium.client.render.chunk.RenderSectionManager;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Pseudo;
import org.spongepowered.asm.mixin.gen.Accessor;
@@ -9,6 +9,6 @@ import org.spongepowered.asm.mixin.gen.Accessor;
@Mixin(SodiumWorldRenderer.class)
@Pseudo
public interface AccessorSodiumWorldRenderer {
@Accessor(value = "renderSectionManager", remap = false)
RenderSectionManager getRenderSectionManager_firmament();
@Accessor(value = "renderSectionManager", remap = false)
RenderSectionManager getRenderSectionManager_firmament();
}

View File

@@ -3,8 +3,8 @@ package moe.nea.firmament.mixins.custommodels;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import com.llamalad7.mixinextras.sugar.Local;
import me.jellysquid.mods.sodium.client.render.chunk.compile.tasks.ChunkBuilderMeshingTask;
import moe.nea.firmament.features.texturepack.CustomBlockTextures;
import net.caffeinemc.mods.sodium.client.render.chunk.compile.tasks.ChunkBuilderMeshingTask;
import net.minecraft.block.BlockState;
import net.minecraft.client.render.block.BlockModels;
import net.minecraft.client.render.model.BakedModel;
@@ -15,7 +15,7 @@ import org.spongepowered.asm.mixin.injection.At;
@Mixin(ChunkBuilderMeshingTask.class)
public class PatchBlockModelInSodiumChunkGenerator {
@WrapOperation(
method = "execute(Lme/jellysquid/mods/sodium/client/render/chunk/compile/ChunkBuildContext;Lme/jellysquid/mods/sodium/client/util/task/CancellationToken;)Lme/jellysquid/mods/sodium/client/render/chunk/compile/ChunkBuildOutput;",
method = "execute(Lnet/caffeinemc/mods/sodium/client/render/chunk/compile/ChunkBuildContext;Lnet/caffeinemc/mods/sodium/client/util/task/CancellationToken;)Lnet/caffeinemc/mods/sodium/client/render/chunk/compile/ChunkBuildOutput;",
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/block/BlockModels;getModel(Lnet/minecraft/block/BlockState;)Lnet/minecraft/client/render/model/BakedModel;"))
private BakedModel replaceBlockModel(BlockModels instance, BlockState state, Operation<BakedModel> original,
@Local(name = "blockPos") BlockPos.Mutable pos) {