Add crafting overlay
This commit is contained in:
10
TODO.txt
10
TODO.txt
@@ -15,8 +15,6 @@
|
||||
- Dwarven Mines
|
||||
- Experimentation Solver
|
||||
- Capes
|
||||
- Dungeon Profit
|
||||
- Dungeon Map
|
||||
|
||||
Priority 2:
|
||||
- missing talismans / pets in pv
|
||||
@@ -33,7 +31,6 @@ Priority 2:
|
||||
Priority 3:
|
||||
- Item rarity halo
|
||||
- Zealot Counter using Combat XP popups
|
||||
- Use REIs "Move Item" functionality to higlight slots
|
||||
- client sided stat tracker that does not need the api
|
||||
- skills
|
||||
- coins
|
||||
@@ -43,3 +40,10 @@ Priority 3:
|
||||
|
||||
|
||||
- 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.features.debug.DeveloperFeatures
|
||||
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.world.FairySouls
|
||||
import moe.nea.firmament.util.data.DataHolder
|
||||
@@ -49,6 +50,7 @@ object FeatureManager : DataHolder<FeatureManager.Config>(serializer(), "feature
|
||||
loadFeature(FairySouls)
|
||||
loadFeature(FishingWarning)
|
||||
loadFeature(SlotLocking)
|
||||
loadFeature(CraftingOverlay)
|
||||
if (Firmament.DEBUG)
|
||||
loadFeature(DeveloperFeatures)
|
||||
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.EntryRegistry
|
||||
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.ingame.GenericContainerScreen
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.text.Text
|
||||
import net.minecraft.util.Identifier
|
||||
import moe.nea.firmament.features.inventory.CraftingOverlay
|
||||
import moe.nea.firmament.recipes.SBCraftingRecipe
|
||||
import moe.nea.firmament.recipes.SBForgeRecipe
|
||||
import moe.nea.firmament.repo.ItemCache.asItemStack
|
||||
import moe.nea.firmament.repo.RepoManager
|
||||
import moe.nea.firmament.util.SkyblockId
|
||||
import moe.nea.firmament.util.skyblockId
|
||||
import moe.nea.firmament.util.unformattedString
|
||||
|
||||
|
||||
class FirmamentReiPlugin : REIClientPlugin {
|
||||
@@ -48,6 +52,19 @@ class FirmamentReiPlugin : REIClientPlugin {
|
||||
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) {
|
||||
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.RepoManager
|
||||
import moe.nea.firmament.util.FirmFormatters
|
||||
import moe.nea.firmament.util.HypixelPetInfo
|
||||
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
|
||||
data class PetData(
|
||||
@@ -47,6 +50,12 @@ data class PetData(
|
||||
val petId: String,
|
||||
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) }
|
||||
}
|
||||
|
||||
@@ -155,5 +164,13 @@ object SBItemEntryDefinition : EntryDefinition<SBItemStack> {
|
||||
fun getEntry(ingredient: NEUIngredient): EntryStack<SBItemStack> =
|
||||
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
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
@file:UseSerializers(DashlessUUIDSerializer::class)
|
||||
package moe.nea.firmament.util
|
||||
|
||||
import io.github.moulberry.repo.data.NEUItem
|
||||
import io.github.moulberry.repo.data.Rarity
|
||||
import java.util.UUID
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.UseSerializers
|
||||
import kotlinx.serialization.decodeFromString
|
||||
import kotlinx.serialization.json.Json
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.nbt.NbtCompound
|
||||
import net.minecraft.util.Identifier
|
||||
import moe.nea.firmament.util.json.DashlessUUIDSerializer
|
||||
|
||||
/**
|
||||
* 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")
|
||||
private val bazaarEnchantmentRegex = "ENCHANTMENT_(\\D*)_(\\d+)".toRegex()
|
||||
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(
|
||||
val type: String,
|
||||
val tier: Rarity,
|
||||
val exp: Double = 0.0,
|
||||
val candyUsed: Int = 0,
|
||||
val uuid: UUID? = null,
|
||||
) {
|
||||
val skyblockId get() = SkyblockId("${type.uppercase()};${tier.ordinal}")
|
||||
}
|
||||
@@ -77,20 +84,23 @@ private val jsonparser = Json { ignoreUnknownKeys = true }
|
||||
val ItemStack.extraAttributes: NbtCompound
|
||||
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?
|
||||
get() {
|
||||
when (val id = extraAttributes.getString("id")) {
|
||||
return when (val id = extraAttributes.getString("id")) {
|
||||
"PET" -> {
|
||||
val jsonString = extraAttributes.getString("petInfo")
|
||||
if (jsonString.isNullOrBlank()) return null
|
||||
val petInfo =
|
||||
runCatching { jsonparser.decodeFromString<HypixelPetInfo>(jsonString) }
|
||||
.getOrElse { return null }
|
||||
return petInfo.skyblockId
|
||||
petData?.skyblockId ?: SkyblockId.PET_NULL
|
||||
}
|
||||
// TODO: RUNE, ENCHANTED_BOOK, PARTY_HAT_CRAB{,_ANIMATED}, ABICASE
|
||||
else -> {
|
||||
return SkyblockId(id)
|
||||
SkyblockId(id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user