Forge recipes and coin items
This commit is contained in:
@@ -27,10 +27,14 @@ import me.shedaniel.rei.api.client.gui.widgets.Widgets
|
|||||||
import me.shedaniel.rei.api.client.registry.display.DisplayCategory
|
import me.shedaniel.rei.api.client.registry.display.DisplayCategory
|
||||||
import me.shedaniel.rei.api.common.category.CategoryIdentifier
|
import me.shedaniel.rei.api.common.category.CategoryIdentifier
|
||||||
import me.shedaniel.rei.api.common.util.EntryStacks
|
import me.shedaniel.rei.api.common.util.EntryStacks
|
||||||
|
import kotlin.math.cos
|
||||||
|
import kotlin.math.sin
|
||||||
|
import kotlin.time.Duration.Companion.seconds
|
||||||
import net.minecraft.block.Blocks
|
import net.minecraft.block.Blocks
|
||||||
import net.minecraft.text.Text
|
import net.minecraft.text.Text
|
||||||
import moe.nea.firmament.Firmament
|
import moe.nea.firmament.Firmament
|
||||||
import moe.nea.firmament.rei.SBItemEntryDefinition
|
import moe.nea.firmament.rei.SBItemEntryDefinition
|
||||||
|
import moe.nea.firmament.rei.plus
|
||||||
|
|
||||||
class SBForgeRecipe(override val neuRecipe: NEUForgeRecipe) : SBRecipe() {
|
class SBForgeRecipe(override val neuRecipe: NEUForgeRecipe) : SBRecipe() {
|
||||||
override fun getCategoryIdentifier(): CategoryIdentifier<*> = Category.categoryIdentifier
|
override fun getCategoryIdentifier(): CategoryIdentifier<*> = Category.categoryIdentifier
|
||||||
@@ -41,27 +45,39 @@ class SBForgeRecipe(override val neuRecipe: NEUForgeRecipe) : SBRecipe() {
|
|||||||
|
|
||||||
override fun getTitle(): Text = Text.literal("Forge Recipes")
|
override fun getTitle(): Text = Text.literal("Forge Recipes")
|
||||||
override fun getDisplayHeight(): Int {
|
override fun getDisplayHeight(): Int {
|
||||||
return super.getDisplayHeight()
|
return 104
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getIcon(): Renderer = EntryStacks.of(Blocks.ANVIL)
|
override fun getIcon(): Renderer = EntryStacks.of(Blocks.ANVIL)
|
||||||
override fun setupDisplay(display: SBForgeRecipe, bounds: Rectangle): List<Widget> {
|
override fun setupDisplay(display: SBForgeRecipe, bounds: Rectangle): List<Widget> {
|
||||||
return buildList {
|
return buildList {
|
||||||
// TODO: proper gui for this (possibly inspired by the old circular gui)
|
|
||||||
add(Widgets.createRecipeBase(bounds))
|
add(Widgets.createRecipeBase(bounds))
|
||||||
val resultSlot = Point(bounds.centerX, bounds.centerY + 5)
|
add(Widgets.createResultSlotBackground(Point(bounds.minX + 124, bounds.minY + 46)))
|
||||||
add(Widgets.createResultSlotBackground(resultSlot))
|
val arrow = Widgets.createArrow(Point(bounds.minX + 90, bounds.minY + 54 - 18 / 2))
|
||||||
val ingredientsCenter = Point(bounds.centerX, bounds.centerY - 20)
|
add(arrow)
|
||||||
|
add(Widgets.createTooltip(arrow.bounds, Text.translatable("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
|
val count = display.neuRecipe.inputs.size
|
||||||
display.neuRecipe.inputs.forEachIndexed { idx, ingredient ->
|
if (count == 1) {
|
||||||
add(
|
add(
|
||||||
Widgets.createSlot(
|
Widgets.createSlot(Point(ingredientsCenter.x, ingredientsCenter.y)).markInput()
|
||||||
Point(ingredientsCenter.x + 12 - count * 24 / 2 + idx * 24, ingredientsCenter.y)
|
.entry(SBItemEntryDefinition.getEntry(display.neuRecipe.inputs.single()))
|
||||||
).markInput().entry(SBItemEntryDefinition.getEntry(ingredient))
|
|
||||||
)
|
)
|
||||||
|
} 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(
|
add(
|
||||||
Widgets.createSlot(resultSlot).markOutput().disableBackground()
|
Widgets.createSlot(Point(bounds.minX + 124, bounds.minY + 46)).markOutput().disableBackground()
|
||||||
.entry(SBItemEntryDefinition.getEntry(display.neuRecipe.outputStack))
|
.entry(SBItemEntryDefinition.getEntry(display.neuRecipe.outputStack))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ import net.minecraft.registry.tag.TagKey
|
|||||||
import net.minecraft.text.Text
|
import net.minecraft.text.Text
|
||||||
import net.minecraft.util.Identifier
|
import net.minecraft.util.Identifier
|
||||||
import moe.nea.firmament.rei.FirmamentReiPlugin.Companion.asItemEntry
|
import moe.nea.firmament.rei.FirmamentReiPlugin.Companion.asItemEntry
|
||||||
|
import moe.nea.firmament.repo.ItemCache
|
||||||
import moe.nea.firmament.repo.ItemCache.asItemStack
|
import moe.nea.firmament.repo.ItemCache.asItemStack
|
||||||
import moe.nea.firmament.repo.RepoManager
|
import moe.nea.firmament.repo.RepoManager
|
||||||
import moe.nea.firmament.util.SkyblockId
|
import moe.nea.firmament.util.SkyblockId
|
||||||
@@ -43,15 +44,17 @@ data class SBItemStack(
|
|||||||
val skyblockId: SkyblockId,
|
val skyblockId: SkyblockId,
|
||||||
val neuItem: NEUItem?,
|
val neuItem: NEUItem?,
|
||||||
val stackSize: Int,
|
val stackSize: Int,
|
||||||
)
|
) {
|
||||||
|
fun asItemStack(): ItemStack? {
|
||||||
|
if (skyblockId == SkyblockId.COINS)
|
||||||
|
return ItemCache.coinItem(stackSize)
|
||||||
|
return neuItem.asItemStack(idHint = skyblockId).copyWithCount(stackSize)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
object SBItemEntryDefinition : EntryDefinition<SBItemStack> {
|
object SBItemEntryDefinition : EntryDefinition<SBItemStack> {
|
||||||
override fun equals(o1: SBItemStack, o2: SBItemStack, context: ComparisonContext): Boolean {
|
override fun equals(o1: SBItemStack, o2: SBItemStack, context: ComparisonContext): Boolean {
|
||||||
if (!context.isFuzzy) {
|
return o1.skyblockId == o2.skyblockId && o1.stackSize == o2.stackSize
|
||||||
if (o1.stackSize != o2.stackSize)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return o1.skyblockId == o2.skyblockId
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun cheatsAs(entry: EntryStack<SBItemStack>?, value: SBItemStack): ItemStack {
|
override fun cheatsAs(entry: EntryStack<SBItemStack>?, value: SBItemStack): ItemStack {
|
||||||
|
|||||||
8
src/main/kotlin/moe/nea/firmament/rei/math.kt
Normal file
8
src/main/kotlin/moe/nea/firmament/rei/math.kt
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
package moe.nea.firmament.rei
|
||||||
|
|
||||||
|
import me.shedaniel.math.Point
|
||||||
|
|
||||||
|
operator fun Point.plus(other: Point): Point = Point(
|
||||||
|
this.x + other.x,
|
||||||
|
this.y + other.y,
|
||||||
|
)
|
||||||
@@ -18,29 +18,38 @@
|
|||||||
|
|
||||||
package moe.nea.firmament.repo
|
package moe.nea.firmament.repo
|
||||||
|
|
||||||
|
import com.mojang.authlib.GameProfile
|
||||||
|
import com.mojang.authlib.minecraft.MinecraftProfileTexture
|
||||||
import com.mojang.serialization.Dynamic
|
import com.mojang.serialization.Dynamic
|
||||||
import io.github.cottonmc.cotton.gui.client.CottonHud
|
import io.github.cottonmc.cotton.gui.client.CottonHud
|
||||||
import io.github.moulberry.repo.IReloadable
|
import io.github.moulberry.repo.IReloadable
|
||||||
import io.github.moulberry.repo.NEURepository
|
import io.github.moulberry.repo.NEURepository
|
||||||
import io.github.moulberry.repo.data.NEUItem
|
import io.github.moulberry.repo.data.NEUItem
|
||||||
|
import java.text.NumberFormat
|
||||||
|
import java.util.UUID
|
||||||
import java.util.concurrent.ConcurrentHashMap
|
import java.util.concurrent.ConcurrentHashMap
|
||||||
import org.apache.logging.log4j.LogManager
|
import org.apache.logging.log4j.LogManager
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import net.minecraft.SharedConstants
|
import net.minecraft.SharedConstants
|
||||||
|
import net.minecraft.block.entity.SkullBlockEntity
|
||||||
import net.minecraft.client.resource.language.I18n
|
import net.minecraft.client.resource.language.I18n
|
||||||
import net.minecraft.datafixer.Schemas
|
import net.minecraft.datafixer.Schemas
|
||||||
import net.minecraft.datafixer.TypeReferences
|
import net.minecraft.datafixer.TypeReferences
|
||||||
import net.minecraft.item.ItemStack
|
import net.minecraft.item.ItemStack
|
||||||
import net.minecraft.item.Items
|
import net.minecraft.item.Items
|
||||||
import net.minecraft.nbt.NbtCompound
|
import net.minecraft.nbt.NbtCompound
|
||||||
|
import net.minecraft.nbt.NbtElement
|
||||||
|
import net.minecraft.nbt.NbtHelper
|
||||||
import net.minecraft.nbt.NbtOps
|
import net.minecraft.nbt.NbtOps
|
||||||
import net.minecraft.text.Text
|
import net.minecraft.text.Text
|
||||||
import moe.nea.firmament.Firmament
|
import moe.nea.firmament.Firmament
|
||||||
import moe.nea.firmament.rei.SBItemStack
|
|
||||||
import moe.nea.firmament.util.LegacyTagParser
|
import moe.nea.firmament.util.LegacyTagParser
|
||||||
import moe.nea.firmament.util.SkyblockId
|
import moe.nea.firmament.util.SkyblockId
|
||||||
import moe.nea.firmament.util.appendLore
|
import moe.nea.firmament.util.appendLore
|
||||||
|
import moe.nea.firmament.util.item.MinecraftProfileTextureKt
|
||||||
|
import moe.nea.firmament.util.item.MinecraftTexturesPayloadKt
|
||||||
|
import moe.nea.firmament.util.item.setTextures
|
||||||
import moe.nea.firmament.util.skyblockId
|
import moe.nea.firmament.util.skyblockId
|
||||||
|
|
||||||
object ItemCache : IReloadable {
|
object ItemCache : IReloadable {
|
||||||
@@ -73,7 +82,7 @@ object ItemCache : IReloadable {
|
|||||||
|
|
||||||
fun brokenItemStack(neuItem: NEUItem?, idHint: SkyblockId? = null): ItemStack {
|
fun brokenItemStack(neuItem: NEUItem?, idHint: SkyblockId? = null): ItemStack {
|
||||||
return ItemStack(Items.PAINTING).apply {
|
return ItemStack(Items.PAINTING).apply {
|
||||||
setCustomName(Text.literal(neuItem?.displayName ?: idHint?.toString() ?: "null"))
|
setCustomName(Text.literal(neuItem?.displayName ?: idHint?.neuItem ?: "null"))
|
||||||
appendLore(listOf(Text.translatable("firmament.repo.brokenitem", neuItem?.skyblockItemId ?: idHint)))
|
appendLore(listOf(Text.translatable("firmament.repo.brokenitem", neuItem?.skyblockItemId ?: idHint)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -94,11 +103,6 @@ object ItemCache : IReloadable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun SBItemStack.asItemStack(): ItemStack {
|
|
||||||
return this.neuItem.asItemStack(idHint = this.skyblockId)
|
|
||||||
.let { if (this.stackSize != 1) it.copyWithCount(this.stackSize) else it }
|
|
||||||
}
|
|
||||||
|
|
||||||
fun NEUItem?.asItemStack(idHint: SkyblockId? = null): ItemStack {
|
fun NEUItem?.asItemStack(idHint: SkyblockId? = null): ItemStack {
|
||||||
if (this == null) return brokenItemStack(null, idHint)
|
if (this == null) return brokenItemStack(null, idHint)
|
||||||
var s = cache[this.skyblockItemId]
|
var s = cache[this.skyblockItemId]
|
||||||
@@ -139,4 +143,47 @@ object ItemCache : IReloadable {
|
|||||||
CottonHud.remove(RepoManager.progressBar)
|
CottonHud.remove(RepoManager.progressBar)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun coinItem(coinAmount: Int): ItemStack {
|
||||||
|
var uuid = UUID.fromString("2070f6cb-f5db-367a-acd0-64d39a7e5d1b")
|
||||||
|
var texture =
|
||||||
|
"http://textures.minecraft.net/texture/538071721cc5b4cd406ce431a13f86083a8973e1064d2f8897869930ee6e5237"
|
||||||
|
if (coinAmount >= 100000) {
|
||||||
|
uuid = UUID.fromString("94fa2455-2881-31fe-bb4e-e3e24d58dbe3")
|
||||||
|
texture =
|
||||||
|
"http://textures.minecraft.net/texture/c9b77999fed3a2758bfeaf0793e52283817bea64044bf43ef29433f954bb52f6"
|
||||||
|
}
|
||||||
|
if (coinAmount >= 10000000) {
|
||||||
|
uuid = UUID.fromString("0af8df1f-098c-3b72-ac6b-65d65fd0b668")
|
||||||
|
texture =
|
||||||
|
"http://textures.minecraft.net/texture/7b951fed6a7b2cbc2036916dec7a46c4a56481564d14f945b6ebc03382766d3b"
|
||||||
|
}
|
||||||
|
val itemStack = ItemStack(Items.PLAYER_HEAD)
|
||||||
|
itemStack.setCustomName(Text.literal("§r§6" + NumberFormat.getInstance().format(coinAmount) + " Coins"))
|
||||||
|
val nbt: NbtCompound = itemStack.orCreateNbt
|
||||||
|
nbt[SkullBlockEntity.SKULL_OWNER_KEY] = NbtHelper.writeGameProfile(
|
||||||
|
NbtCompound(),
|
||||||
|
GameProfile(uuid, "CoolGuy123").also {
|
||||||
|
it.setTextures(
|
||||||
|
MinecraftTexturesPayloadKt(
|
||||||
|
mapOf(
|
||||||
|
MinecraftProfileTexture.Type.SKIN to MinecraftProfileTextureKt(texture),
|
||||||
|
),
|
||||||
|
uuid,
|
||||||
|
"CoolGuy123"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
return itemStack
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
operator fun NbtCompound.set(key: String, value: String) {
|
||||||
|
putString(key, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
operator fun NbtCompound.set(key: String, value: NbtElement) {
|
||||||
|
put(key, value)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ value class SkyblockId(val neuItem: String) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
val COINS: SkyblockId = SkyblockId("SKYBLOCK_COIN")
|
||||||
private val bazaarEnchantmentRegex = "ENCHANTMENT_(\\D*)_(\\d+)".toRegex()
|
private val bazaarEnchantmentRegex = "ENCHANTMENT_(\\D*)_(\\d+)".toRegex()
|
||||||
val NULL: SkyblockId = SkyblockId("null")
|
val NULL: SkyblockId = SkyblockId("null")
|
||||||
}
|
}
|
||||||
|
|||||||
39
src/main/kotlin/moe/nea/firmament/util/item/SkullItemData.kt
Normal file
39
src/main/kotlin/moe/nea/firmament/util/item/SkullItemData.kt
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
@file:UseSerializers(DashlessUUIDSerializer::class, InstantAsLongSerializer::class)
|
||||||
|
|
||||||
|
package moe.nea.firmament.util.item
|
||||||
|
|
||||||
|
import com.mojang.authlib.GameProfile
|
||||||
|
import com.mojang.authlib.minecraft.MinecraftProfileTexture
|
||||||
|
import com.mojang.authlib.properties.Property
|
||||||
|
import java.util.UUID
|
||||||
|
import kotlinx.datetime.Clock
|
||||||
|
import kotlinx.datetime.Instant
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.UseSerializers
|
||||||
|
import kotlinx.serialization.encodeToString
|
||||||
|
import net.minecraft.client.texture.PlayerSkinProvider
|
||||||
|
import moe.nea.firmament.Firmament
|
||||||
|
import moe.nea.firmament.util.json.DashlessUUIDSerializer
|
||||||
|
import moe.nea.firmament.util.json.InstantAsLongSerializer
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class MinecraftProfileTextureKt(
|
||||||
|
val url: String,
|
||||||
|
val metadata: Map<String, String> = mapOf(),
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class MinecraftTexturesPayloadKt(
|
||||||
|
val textures: Map<MinecraftProfileTexture.Type, MinecraftProfileTextureKt>,
|
||||||
|
val profileId: UUID,
|
||||||
|
val profileName: String,
|
||||||
|
val isPublic: Boolean = true,
|
||||||
|
val timestamp: Instant = Clock.System.now(),
|
||||||
|
)
|
||||||
|
|
||||||
|
fun GameProfile.setTextures(textures: MinecraftTexturesPayloadKt) {
|
||||||
|
val json = Firmament.json.encodeToString(textures)
|
||||||
|
val encoded = java.util.Base64.getEncoder().encodeToString(json.encodeToByteArray())
|
||||||
|
properties.put(PlayerSkinProvider.TEXTURES, Property(PlayerSkinProvider.TEXTURES, encoded))
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package moe.nea.firmament.util.json
|
||||||
|
|
||||||
|
import java.util.UUID
|
||||||
|
import kotlinx.serialization.KSerializer
|
||||||
|
import kotlinx.serialization.Serializer
|
||||||
|
import kotlinx.serialization.descriptors.PrimitiveKind
|
||||||
|
import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
|
||||||
|
import kotlinx.serialization.descriptors.SerialDescriptor
|
||||||
|
import kotlinx.serialization.encoding.Decoder
|
||||||
|
import kotlinx.serialization.encoding.Encoder
|
||||||
|
import moe.nea.firmament.util.parseDashlessUUID
|
||||||
|
|
||||||
|
object DashlessUUIDSerializer : KSerializer<UUID> {
|
||||||
|
override val descriptor: SerialDescriptor =
|
||||||
|
PrimitiveSerialDescriptor("DashlessUUIDSerializer", PrimitiveKind.STRING)
|
||||||
|
|
||||||
|
override fun deserialize(decoder: Decoder): UUID {
|
||||||
|
return parseDashlessUUID(decoder.decodeString())
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun serialize(encoder: Encoder, value: UUID) {
|
||||||
|
encoder.encodeString(value.toString().replace("-", ""))
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package moe.nea.firmament.util.json
|
||||||
|
|
||||||
|
import kotlinx.datetime.Instant
|
||||||
|
import kotlinx.serialization.KSerializer
|
||||||
|
import kotlinx.serialization.descriptors.PrimitiveKind
|
||||||
|
import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
|
||||||
|
import kotlinx.serialization.descriptors.SerialDescriptor
|
||||||
|
import kotlinx.serialization.encoding.Decoder
|
||||||
|
import kotlinx.serialization.encoding.Encoder
|
||||||
|
|
||||||
|
object InstantAsLongSerializer : KSerializer<Instant> {
|
||||||
|
override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("InstantAsLongSerializer", PrimitiveKind.LONG)
|
||||||
|
override fun deserialize(decoder: Decoder): Instant {
|
||||||
|
return Instant.fromEpochMilliseconds(decoder.decodeLong())
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun serialize(encoder: Encoder, value: Instant) {
|
||||||
|
encoder.encodeLong(value.toEpochMilliseconds())
|
||||||
|
}
|
||||||
|
}
|
||||||
10
src/main/kotlin/moe/nea/firmament/util/uuid.kt
Normal file
10
src/main/kotlin/moe/nea/firmament/util/uuid.kt
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
package moe.nea.firmament.util
|
||||||
|
|
||||||
|
import java.math.BigInteger
|
||||||
|
import java.util.UUID
|
||||||
|
|
||||||
|
fun parseDashlessUUID(dashlessUuid: String): UUID {
|
||||||
|
val most = BigInteger(dashlessUuid.substring(0, 16), 16)
|
||||||
|
val least = BigInteger(dashlessUuid.substring(16, 32), 16)
|
||||||
|
return UUID(most.toLong(), least.toLong())
|
||||||
|
}
|
||||||
@@ -35,5 +35,6 @@
|
|||||||
"firmament.config.fishing-warning.highlight-wake-chain": "Highlight fishing particles",
|
"firmament.config.fishing-warning.highlight-wake-chain": "Highlight fishing particles",
|
||||||
"firmament.key.slotlocking": "Lock Slot / Slot Binding",
|
"firmament.key.slotlocking": "Lock Slot / Slot Binding",
|
||||||
"firmament.key.category": "Firmament",
|
"firmament.key.category": "Firmament",
|
||||||
"firmament.protectitem": "Firmament protected your item: "
|
"firmament.protectitem": "Firmament protected your item: ",
|
||||||
|
"firmament.recipe.forge.time": "Forging Time: %s"
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user