aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornea <nea@nea.moe>2023-05-30 22:47:56 +0200
committernea <nea@nea.moe>2023-05-30 22:47:56 +0200
commit88cb9468b4432f68d1197f512f68c951fdbdf3dd (patch)
treefb9da150d4173cbe33d68b80c6d86240fe03c4e2
parent3139306088f8d3cad1b4906c3bbd1b412b9bda6f (diff)
downloadFirmament-88cb9468b4432f68d1197f512f68c951fdbdf3dd.tar.gz
Firmament-88cb9468b4432f68d1197f512f68c951fdbdf3dd.tar.bz2
Firmament-88cb9468b4432f68d1197f512f68c951fdbdf3dd.zip
Forge recipes and coin items
-rw-r--r--src/main/kotlin/moe/nea/firmament/recipes/SBForgeRecipe.kt36
-rw-r--r--src/main/kotlin/moe/nea/firmament/rei/SBItemEntryDefinition.kt15
-rw-r--r--src/main/kotlin/moe/nea/firmament/rei/math.kt8
-rw-r--r--src/main/kotlin/moe/nea/firmament/repo/ItemCache.kt61
-rw-r--r--src/main/kotlin/moe/nea/firmament/util/SkyblockId.kt1
-rw-r--r--src/main/kotlin/moe/nea/firmament/util/item/SkullItemData.kt39
-rw-r--r--src/main/kotlin/moe/nea/firmament/util/json/DashlessUUIDSerializer.kt24
-rw-r--r--src/main/kotlin/moe/nea/firmament/util/json/InstantAsLongSerializer.kt20
-rw-r--r--src/main/kotlin/moe/nea/firmament/util/uuid.kt10
-rw-r--r--src/main/resources/assets/firmament/lang/en_us.json3
10 files changed, 193 insertions, 24 deletions
diff --git a/src/main/kotlin/moe/nea/firmament/recipes/SBForgeRecipe.kt b/src/main/kotlin/moe/nea/firmament/recipes/SBForgeRecipe.kt
index 9f13cca..d70ebcd 100644
--- a/src/main/kotlin/moe/nea/firmament/recipes/SBForgeRecipe.kt
+++ b/src/main/kotlin/moe/nea/firmament/recipes/SBForgeRecipe.kt
@@ -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.common.category.CategoryIdentifier
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.text.Text
import moe.nea.firmament.Firmament
import moe.nea.firmament.rei.SBItemEntryDefinition
+import moe.nea.firmament.rei.plus
class SBForgeRecipe(override val neuRecipe: NEUForgeRecipe) : SBRecipe() {
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 getDisplayHeight(): Int {
- return super.getDisplayHeight()
+ return 104
}
override fun getIcon(): Renderer = EntryStacks.of(Blocks.ANVIL)
override fun setupDisplay(display: SBForgeRecipe, bounds: Rectangle): List<Widget> {
return buildList {
- // TODO: proper gui for this (possibly inspired by the old circular gui)
add(Widgets.createRecipeBase(bounds))
- val resultSlot = Point(bounds.centerX, bounds.centerY + 5)
- add(Widgets.createResultSlotBackground(resultSlot))
- val ingredientsCenter = Point(bounds.centerX, bounds.centerY - 20)
+ 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.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
- display.neuRecipe.inputs.forEachIndexed { idx, ingredient ->
+ if (count == 1) {
add(
- Widgets.createSlot(
- Point(ingredientsCenter.x + 12 - count * 24 / 2 + idx * 24, ingredientsCenter.y)
- ).markInput().entry(SBItemEntryDefinition.getEntry(ingredient))
+ 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(resultSlot).markOutput().disableBackground()
+ Widgets.createSlot(Point(bounds.minX + 124, bounds.minY + 46)).markOutput().disableBackground()
.entry(SBItemEntryDefinition.getEntry(display.neuRecipe.outputStack))
)
}
diff --git a/src/main/kotlin/moe/nea/firmament/rei/SBItemEntryDefinition.kt b/src/main/kotlin/moe/nea/firmament/rei/SBItemEntryDefinition.kt
index 1e5ae4c..ee6b673 100644
--- a/src/main/kotlin/moe/nea/firmament/rei/SBItemEntryDefinition.kt
+++ b/src/main/kotlin/moe/nea/firmament/rei/SBItemEntryDefinition.kt
@@ -33,6 +33,7 @@ import net.minecraft.registry.tag.TagKey
import net.minecraft.text.Text
import net.minecraft.util.Identifier
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.RepoManager
import moe.nea.firmament.util.SkyblockId
@@ -43,15 +44,17 @@ data class SBItemStack(
val skyblockId: SkyblockId,
val neuItem: NEUItem?,
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> {
override fun equals(o1: SBItemStack, o2: SBItemStack, context: ComparisonContext): Boolean {
- if (!context.isFuzzy) {
- if (o1.stackSize != o2.stackSize)
- return false
- }
- return o1.skyblockId == o2.skyblockId
+ return o1.skyblockId == o2.skyblockId && o1.stackSize == o2.stackSize
}
override fun cheatsAs(entry: EntryStack<SBItemStack>?, value: SBItemStack): ItemStack {
diff --git a/src/main/kotlin/moe/nea/firmament/rei/math.kt b/src/main/kotlin/moe/nea/firmament/rei/math.kt
new file mode 100644
index 0000000..e3504a1
--- /dev/null
+++ b/src/main/kotlin/moe/nea/firmament/rei/math.kt
@@ -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,
+)
diff --git a/src/main/kotlin/moe/nea/firmament/repo/ItemCache.kt b/src/main/kotlin/moe/nea/firmament/repo/ItemCache.kt
index ab6034f..5452d33 100644
--- a/src/main/kotlin/moe/nea/firmament/repo/ItemCache.kt
+++ b/src/main/kotlin/moe/nea/firmament/repo/ItemCache.kt
@@ -18,29 +18,38 @@
package moe.nea.firmament.repo
+import com.mojang.authlib.GameProfile
+import com.mojang.authlib.minecraft.MinecraftProfileTexture
import com.mojang.serialization.Dynamic
import io.github.cottonmc.cotton.gui.client.CottonHud
import io.github.moulberry.repo.IReloadable
import io.github.moulberry.repo.NEURepository
import io.github.moulberry.repo.data.NEUItem
+import java.text.NumberFormat
+import java.util.UUID
import java.util.concurrent.ConcurrentHashMap
import org.apache.logging.log4j.LogManager
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import net.minecraft.SharedConstants
+import net.minecraft.block.entity.SkullBlockEntity
import net.minecraft.client.resource.language.I18n
import net.minecraft.datafixer.Schemas
import net.minecraft.datafixer.TypeReferences
import net.minecraft.item.ItemStack
import net.minecraft.item.Items
import net.minecraft.nbt.NbtCompound
+import net.minecraft.nbt.NbtElement
+import net.minecraft.nbt.NbtHelper
import net.minecraft.nbt.NbtOps
import net.minecraft.text.Text
import moe.nea.firmament.Firmament
-import moe.nea.firmament.rei.SBItemStack
import moe.nea.firmament.util.LegacyTagParser
import moe.nea.firmament.util.SkyblockId
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
object ItemCache : IReloadable {
@@ -73,7 +82,7 @@ object ItemCache : IReloadable {
fun brokenItemStack(neuItem: NEUItem?, idHint: SkyblockId? = null): ItemStack {
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)))
}
}
@@ -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 {
if (this == null) return brokenItemStack(null, idHint)
var s = cache[this.skyblockItemId]
@@ -139,4 +143,47 @@ object ItemCache : IReloadable {
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)
}
diff --git a/src/main/kotlin/moe/nea/firmament/util/SkyblockId.kt b/src/main/kotlin/moe/nea/firmament/util/SkyblockId.kt
index f0998a7..b3c0e9d 100644
--- a/src/main/kotlin/moe/nea/firmament/util/SkyblockId.kt
+++ b/src/main/kotlin/moe/nea/firmament/util/SkyblockId.kt
@@ -56,6 +56,7 @@ value class SkyblockId(val neuItem: String) {
}
companion object {
+ val COINS: SkyblockId = SkyblockId("SKYBLOCK_COIN")
private val bazaarEnchantmentRegex = "ENCHANTMENT_(\\D*)_(\\d+)".toRegex()
val NULL: SkyblockId = SkyblockId("null")
}
diff --git a/src/main/kotlin/moe/nea/firmament/util/item/SkullItemData.kt b/src/main/kotlin/moe/nea/firmament/util/item/SkullItemData.kt
new file mode 100644
index 0000000..ad9d388
--- /dev/null
+++ b/src/main/kotlin/moe/nea/firmament/util/item/SkullItemData.kt
@@ -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))
+}
+
diff --git a/src/main/kotlin/moe/nea/firmament/util/json/DashlessUUIDSerializer.kt b/src/main/kotlin/moe/nea/firmament/util/json/DashlessUUIDSerializer.kt
new file mode 100644
index 0000000..c95b343
--- /dev/null
+++ b/src/main/kotlin/moe/nea/firmament/util/json/DashlessUUIDSerializer.kt
@@ -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("-", ""))
+ }
+}
diff --git a/src/main/kotlin/moe/nea/firmament/util/json/InstantAsLongSerializer.kt b/src/main/kotlin/moe/nea/firmament/util/json/InstantAsLongSerializer.kt
new file mode 100644
index 0000000..988c7dd
--- /dev/null
+++ b/src/main/kotlin/moe/nea/firmament/util/json/InstantAsLongSerializer.kt
@@ -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())
+ }
+}
diff --git a/src/main/kotlin/moe/nea/firmament/util/uuid.kt b/src/main/kotlin/moe/nea/firmament/util/uuid.kt
new file mode 100644
index 0000000..d5409fa
--- /dev/null
+++ b/src/main/kotlin/moe/nea/firmament/util/uuid.kt
@@ -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())
+}
diff --git a/src/main/resources/assets/firmament/lang/en_us.json b/src/main/resources/assets/firmament/lang/en_us.json
index 440d923..541724f 100644
--- a/src/main/resources/assets/firmament/lang/en_us.json
+++ b/src/main/resources/assets/firmament/lang/en_us.json
@@ -35,5 +35,6 @@
"firmament.config.fishing-warning.highlight-wake-chain": "Highlight fishing particles",
"firmament.key.slotlocking": "Lock Slot / Slot Binding",
"firmament.key.category": "Firmament",
- "firmament.protectitem": "Firmament protected your item: "
+ "firmament.protectitem": "Firmament protected your item: ",
+ "firmament.recipe.forge.time": "Forging Time: %s"
}