Add crafting overlay
This commit is contained in:
10
TODO.txt
10
TODO.txt
@@ -15,8 +15,6 @@
|
|||||||
- Dwarven Mines
|
- Dwarven Mines
|
||||||
- Experimentation Solver
|
- Experimentation Solver
|
||||||
- Capes
|
- Capes
|
||||||
- Dungeon Profit
|
|
||||||
- Dungeon Map
|
|
||||||
|
|
||||||
Priority 2:
|
Priority 2:
|
||||||
- missing talismans / pets in pv
|
- missing talismans / pets in pv
|
||||||
@@ -33,7 +31,6 @@ Priority 2:
|
|||||||
Priority 3:
|
Priority 3:
|
||||||
- Item rarity halo
|
- Item rarity halo
|
||||||
- Zealot Counter using Combat XP popups
|
- Zealot Counter using Combat XP popups
|
||||||
- Use REIs "Move Item" functionality to higlight slots
|
|
||||||
- client sided stat tracker that does not need the api
|
- client sided stat tracker that does not need the api
|
||||||
- skills
|
- skills
|
||||||
- coins
|
- coins
|
||||||
@@ -43,3 +40,10 @@ Priority 3:
|
|||||||
|
|
||||||
|
|
||||||
- and much more that i will add as i go along
|
- and much more that i will add as i go along
|
||||||
|
|
||||||
|
Dungeons (planned in another mod):
|
||||||
|
- Dungeon Profit
|
||||||
|
- Dungeon Map
|
||||||
|
- Dungeon waypoints
|
||||||
|
- Dungeon puzzle solvers
|
||||||
|
- Talk with the big D
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import kotlinx.serialization.serializer
|
|||||||
import moe.nea.firmament.Firmament
|
import moe.nea.firmament.Firmament
|
||||||
import moe.nea.firmament.features.debug.DeveloperFeatures
|
import moe.nea.firmament.features.debug.DeveloperFeatures
|
||||||
import moe.nea.firmament.features.fishing.FishingWarning
|
import moe.nea.firmament.features.fishing.FishingWarning
|
||||||
|
import moe.nea.firmament.features.inventory.CraftingOverlay
|
||||||
import moe.nea.firmament.features.inventory.SlotLocking
|
import moe.nea.firmament.features.inventory.SlotLocking
|
||||||
import moe.nea.firmament.features.world.FairySouls
|
import moe.nea.firmament.features.world.FairySouls
|
||||||
import moe.nea.firmament.util.data.DataHolder
|
import moe.nea.firmament.util.data.DataHolder
|
||||||
@@ -49,6 +50,7 @@ object FeatureManager : DataHolder<FeatureManager.Config>(serializer(), "feature
|
|||||||
loadFeature(FairySouls)
|
loadFeature(FairySouls)
|
||||||
loadFeature(FishingWarning)
|
loadFeature(FishingWarning)
|
||||||
loadFeature(SlotLocking)
|
loadFeature(SlotLocking)
|
||||||
|
loadFeature(CraftingOverlay)
|
||||||
if (Firmament.DEBUG)
|
if (Firmament.DEBUG)
|
||||||
loadFeature(DeveloperFeatures)
|
loadFeature(DeveloperFeatures)
|
||||||
hasAutoloaded = true
|
hasAutoloaded = true
|
||||||
|
|||||||
@@ -0,0 +1,66 @@
|
|||||||
|
package moe.nea.firmament.features.inventory
|
||||||
|
|
||||||
|
import net.minecraft.client.gui.screen.ingame.GenericContainerScreen
|
||||||
|
import net.minecraft.item.ItemStack
|
||||||
|
import net.minecraft.util.Formatting
|
||||||
|
import moe.nea.firmament.events.SlotRenderEvents
|
||||||
|
import moe.nea.firmament.features.FirmamentFeature
|
||||||
|
import moe.nea.firmament.recipes.SBCraftingRecipe
|
||||||
|
import moe.nea.firmament.rei.FirmamentReiPlugin.Companion.asItemEntry
|
||||||
|
import moe.nea.firmament.rei.SBItemEntryDefinition
|
||||||
|
import moe.nea.firmament.util.MC
|
||||||
|
|
||||||
|
object CraftingOverlay : FirmamentFeature {
|
||||||
|
|
||||||
|
private var screen: GenericContainerScreen? = null
|
||||||
|
private var recipe: SBCraftingRecipe? = null
|
||||||
|
private val craftingOverlayIndices = listOf(
|
||||||
|
10, 11, 12,
|
||||||
|
19, 20, 21,
|
||||||
|
28, 29, 30,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
fun setOverlay(screen: GenericContainerScreen, recipe: SBCraftingRecipe) {
|
||||||
|
this.screen = screen
|
||||||
|
this.recipe = recipe
|
||||||
|
}
|
||||||
|
|
||||||
|
override val name: String
|
||||||
|
get() = "Crafting Overlay"
|
||||||
|
override val identifier: String
|
||||||
|
get() = "crafting-overlay"
|
||||||
|
|
||||||
|
override fun onLoad() {
|
||||||
|
SlotRenderEvents.After.subscribe { event ->
|
||||||
|
val slot = event.slot
|
||||||
|
val recipe = this.recipe ?: return@subscribe
|
||||||
|
if (slot.inventory != screen?.screenHandler?.inventory) return@subscribe
|
||||||
|
val recipeIndex = craftingOverlayIndices.indexOf(slot.index)
|
||||||
|
if (recipeIndex < 0) return@subscribe
|
||||||
|
val expectedItem = recipe.neuRecipe.inputs[recipeIndex]
|
||||||
|
val actualStack = slot.stack ?: ItemStack.EMPTY!!
|
||||||
|
val actualEntry = SBItemEntryDefinition.getEntry(actualStack).value
|
||||||
|
if ((actualEntry.skyblockId.neuItem != expectedItem.itemId || actualEntry.stackSize < expectedItem.amount) && expectedItem.amount.toInt() != 0) {
|
||||||
|
event.context.fill(
|
||||||
|
event.slot.x,
|
||||||
|
event.slot.y,
|
||||||
|
event.slot.x + 16,
|
||||||
|
event.slot.y + 16,
|
||||||
|
0x80FF0000.toInt()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if (!slot.hasStack()) {
|
||||||
|
val itemStack = SBItemEntryDefinition.getEntry(expectedItem).asItemEntry().value
|
||||||
|
event.context.drawItem(itemStack, event.slot.x, event.slot.y)
|
||||||
|
event.context.drawItemInSlot(
|
||||||
|
MC.font,
|
||||||
|
itemStack,
|
||||||
|
event.slot.x,
|
||||||
|
event.slot.y,
|
||||||
|
"${Formatting.RED}${expectedItem.amount.toInt()}"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -24,18 +24,22 @@ import me.shedaniel.rei.api.client.registry.display.DisplayRegistry
|
|||||||
import me.shedaniel.rei.api.client.registry.entry.CollapsibleEntryRegistry
|
import me.shedaniel.rei.api.client.registry.entry.CollapsibleEntryRegistry
|
||||||
import me.shedaniel.rei.api.client.registry.entry.EntryRegistry
|
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.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.EntryStack
|
||||||
import me.shedaniel.rei.api.common.entry.type.EntryTypeRegistry
|
import me.shedaniel.rei.api.common.entry.type.EntryTypeRegistry
|
||||||
import me.shedaniel.rei.api.common.entry.type.VanillaEntryTypes
|
import me.shedaniel.rei.api.common.entry.type.VanillaEntryTypes
|
||||||
|
import net.minecraft.client.gui.screen.ingame.GenericContainerScreen
|
||||||
import net.minecraft.item.ItemStack
|
import net.minecraft.item.ItemStack
|
||||||
import net.minecraft.text.Text
|
import net.minecraft.text.Text
|
||||||
import net.minecraft.util.Identifier
|
import net.minecraft.util.Identifier
|
||||||
|
import moe.nea.firmament.features.inventory.CraftingOverlay
|
||||||
import moe.nea.firmament.recipes.SBCraftingRecipe
|
import moe.nea.firmament.recipes.SBCraftingRecipe
|
||||||
import moe.nea.firmament.recipes.SBForgeRecipe
|
import moe.nea.firmament.recipes.SBForgeRecipe
|
||||||
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
|
||||||
import moe.nea.firmament.util.skyblockId
|
import moe.nea.firmament.util.skyblockId
|
||||||
|
import moe.nea.firmament.util.unformattedString
|
||||||
|
|
||||||
|
|
||||||
class FirmamentReiPlugin : REIClientPlugin {
|
class FirmamentReiPlugin : REIClientPlugin {
|
||||||
@@ -48,6 +52,19 @@ class FirmamentReiPlugin : REIClientPlugin {
|
|||||||
val SKYBLOCK_ITEM_TYPE_ID = Identifier("firmament", "skyblockitems")
|
val SKYBLOCK_ITEM_TYPE_ID = Identifier("firmament", "skyblockitems")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun registerTransferHandlers(registry: TransferHandlerRegistry) {
|
||||||
|
registry.register(TransferHandler { context ->
|
||||||
|
val screen = context.containerScreen
|
||||||
|
val display = context.display
|
||||||
|
if (display !is SBCraftingRecipe || screen !is GenericContainerScreen || screen.title?.unformattedString != "Craft Item") {
|
||||||
|
return@TransferHandler TransferHandler.Result.createNotApplicable()
|
||||||
|
}
|
||||||
|
if (context.isActuallyCrafting)
|
||||||
|
CraftingOverlay.setOverlay(screen, display)
|
||||||
|
return@TransferHandler TransferHandler.Result.createSuccessful()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
override fun registerEntryTypes(registry: EntryTypeRegistry) {
|
override fun registerEntryTypes(registry: EntryTypeRegistry) {
|
||||||
registry.register(SKYBLOCK_ITEM_TYPE_ID, SBItemEntryDefinition)
|
registry.register(SKYBLOCK_ITEM_TYPE_ID, SBItemEntryDefinition)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,7 +39,10 @@ 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.FirmFormatters
|
import moe.nea.firmament.util.FirmFormatters
|
||||||
|
import moe.nea.firmament.util.HypixelPetInfo
|
||||||
import moe.nea.firmament.util.SkyblockId
|
import moe.nea.firmament.util.SkyblockId
|
||||||
|
import moe.nea.firmament.util.petData
|
||||||
|
import moe.nea.firmament.util.skyBlockId
|
||||||
|
|
||||||
// TODO: add in extra data like pet info, into this structure
|
// TODO: add in extra data like pet info, into this structure
|
||||||
data class PetData(
|
data class PetData(
|
||||||
@@ -47,6 +50,12 @@ data class PetData(
|
|||||||
val petId: String,
|
val petId: String,
|
||||||
val exp: Double,
|
val exp: Double,
|
||||||
) {
|
) {
|
||||||
|
companion object {
|
||||||
|
fun fromHypixel(petInfo: HypixelPetInfo) = PetData(
|
||||||
|
petInfo.tier, petInfo.type, petInfo.exp,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
val levelData by lazy { ExpLadders.getExpLadder(petId, rarity).getPetLevel(exp) }
|
val levelData by lazy { ExpLadders.getExpLadder(petId, rarity).getPetLevel(exp) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -155,5 +164,13 @@ object SBItemEntryDefinition : EntryDefinition<SBItemStack> {
|
|||||||
fun getEntry(ingredient: NEUIngredient): EntryStack<SBItemStack> =
|
fun getEntry(ingredient: NEUIngredient): EntryStack<SBItemStack> =
|
||||||
getEntry(SkyblockId(ingredient.itemId), count = ingredient.amount.toInt())
|
getEntry(SkyblockId(ingredient.itemId), count = ingredient.amount.toInt())
|
||||||
|
|
||||||
|
fun getEntry(stack: ItemStack): EntryStack<SBItemStack> =
|
||||||
|
getEntry(
|
||||||
|
SBItemStack(
|
||||||
|
stack.skyBlockId ?: SkyblockId.NULL,
|
||||||
|
RepoManager.getNEUItem(stack.skyBlockId ?: SkyblockId.NULL),
|
||||||
|
stack.count,
|
||||||
|
petData = stack.petData?.let { PetData.fromHypixel(it) }
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,17 +15,20 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
@file:UseSerializers(DashlessUUIDSerializer::class)
|
||||||
package moe.nea.firmament.util
|
package moe.nea.firmament.util
|
||||||
|
|
||||||
import io.github.moulberry.repo.data.NEUItem
|
import io.github.moulberry.repo.data.NEUItem
|
||||||
import io.github.moulberry.repo.data.Rarity
|
import io.github.moulberry.repo.data.Rarity
|
||||||
|
import java.util.UUID
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.UseSerializers
|
||||||
import kotlinx.serialization.decodeFromString
|
import kotlinx.serialization.decodeFromString
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import net.minecraft.item.ItemStack
|
import net.minecraft.item.ItemStack
|
||||||
import net.minecraft.nbt.NbtCompound
|
import net.minecraft.nbt.NbtCompound
|
||||||
import net.minecraft.util.Identifier
|
import net.minecraft.util.Identifier
|
||||||
|
import moe.nea.firmament.util.json.DashlessUUIDSerializer
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A skyblock item id, as used by the NEU repo.
|
* A skyblock item id, as used by the NEU repo.
|
||||||
@@ -59,6 +62,7 @@ value class SkyblockId(val neuItem: String) {
|
|||||||
val COINS: SkyblockId = SkyblockId("SKYBLOCK_COIN")
|
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")
|
||||||
|
val PET_NULL: SkyblockId = SkyblockId("null_pet")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,6 +72,9 @@ val NEUItem.skyblockId get() = SkyblockId(skyblockItemId)
|
|||||||
data class HypixelPetInfo(
|
data class HypixelPetInfo(
|
||||||
val type: String,
|
val type: String,
|
||||||
val tier: Rarity,
|
val tier: Rarity,
|
||||||
|
val exp: Double = 0.0,
|
||||||
|
val candyUsed: Int = 0,
|
||||||
|
val uuid: UUID? = null,
|
||||||
) {
|
) {
|
||||||
val skyblockId get() = SkyblockId("${type.uppercase()};${tier.ordinal}")
|
val skyblockId get() = SkyblockId("${type.uppercase()};${tier.ordinal}")
|
||||||
}
|
}
|
||||||
@@ -77,20 +84,23 @@ private val jsonparser = Json { ignoreUnknownKeys = true }
|
|||||||
val ItemStack.extraAttributes: NbtCompound
|
val ItemStack.extraAttributes: NbtCompound
|
||||||
get() = getOrCreateSubNbt("ExtraAttributes")
|
get() = getOrCreateSubNbt("ExtraAttributes")
|
||||||
|
|
||||||
|
val ItemStack.petData: HypixelPetInfo?
|
||||||
|
get() {
|
||||||
|
val jsonString = extraAttributes.getString("petInfo")
|
||||||
|
if (jsonString.isNullOrBlank()) return null
|
||||||
|
return runCatching { jsonparser.decodeFromString<HypixelPetInfo>(jsonString) }
|
||||||
|
.getOrElse { return null }
|
||||||
|
}
|
||||||
|
|
||||||
val ItemStack.skyBlockId: SkyblockId?
|
val ItemStack.skyBlockId: SkyblockId?
|
||||||
get() {
|
get() {
|
||||||
when (val id = extraAttributes.getString("id")) {
|
return when (val id = extraAttributes.getString("id")) {
|
||||||
"PET" -> {
|
"PET" -> {
|
||||||
val jsonString = extraAttributes.getString("petInfo")
|
petData?.skyblockId ?: SkyblockId.PET_NULL
|
||||||
if (jsonString.isNullOrBlank()) return null
|
|
||||||
val petInfo =
|
|
||||||
runCatching { jsonparser.decodeFromString<HypixelPetInfo>(jsonString) }
|
|
||||||
.getOrElse { return null }
|
|
||||||
return petInfo.skyblockId
|
|
||||||
}
|
}
|
||||||
// TODO: RUNE, ENCHANTED_BOOK, PARTY_HAT_CRAB{,_ANIMATED}, ABICASE
|
// TODO: RUNE, ENCHANTED_BOOK, PARTY_HAT_CRAB{,_ANIMATED}, ABICASE
|
||||||
else -> {
|
else -> {
|
||||||
return SkyblockId(id)
|
SkyblockId(id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user