refactor: Use custom ray trace provider

This commit is contained in:
Linnea Gräf
2025-03-06 21:43:11 +01:00
parent 9099abe955
commit 8a4bfe24b3
6 changed files with 119 additions and 38 deletions

View File

@@ -0,0 +1,38 @@
package moe.nea.firmament.compat.jade
import moe.nea.firmament.annotations.Subscribe
import moe.nea.firmament.events.SkyblockServerUpdateEvent
import moe.nea.firmament.repo.MiningRepoData
import moe.nea.firmament.repo.RepoManager
import moe.nea.firmament.util.ErrorUtil
import net.minecraft.block.Block
object CurrentCustomBlockHolder {
var customBlocks: Map<Block, MiningRepoData.CustomMiningBlock> = mapOf()
fun refreshBlockInfo() {
if (!isOnMiningIsland()) {
customBlocks = mapOf()
return
}
val blocks = RepoManager.miningData.customMiningBlocks
.flatMap { customBlock ->
// TODO: add a lifted helper method for this
customBlock.blocks189.filter { it.isCurrentlyActive }
.mapNotNull { it.block }
.map { customBlock to it }
}
.groupBy { it.second }
customBlocks = blocks.mapNotNull { (block, customBlocks) ->
val singleMatch =
ErrorUtil.notNullOr(customBlocks.singleOrNull()?.first,
"Two custom blocks both want to supply custom mining behaviour for $block.") { return@mapNotNull null }
block to singleMatch
}.toMap()
}
@Subscribe
fun onWorldSwap(event: SkyblockServerUpdateEvent) {
refreshBlockInfo()
}
}

View File

@@ -0,0 +1,34 @@
package moe.nea.firmament.compat.jade
import snownee.jade.api.Accessor
import snownee.jade.api.BlockAccessor
import snownee.jade.api.IWailaClientRegistration
import snownee.jade.api.callback.JadeRayTraceCallback
import net.minecraft.util.hit.HitResult
import moe.nea.firmament.repo.MiningRepoData
import moe.nea.firmament.util.mc.FirmamentDataComponentTypes
class CustomFakeBlockProvider(val registration: IWailaClientRegistration) : JadeRayTraceCallback {
override fun onRayTrace(
hitResult: HitResult,
accessor: Accessor<*>?,
originalAccessor: Accessor<*>?
): Accessor<*>? {
if (accessor !is BlockAccessor) return accessor
val customBlock = CurrentCustomBlockHolder.customBlocks[accessor.block]
if (customBlock == null) return accessor
return registration.blockAccessor()
.from(accessor)
.fakeBlock(customBlock.getDisplayItem(accessor.block))
.build()
}
companion object {
fun getCustomBlock(accessor: BlockAccessor): MiningRepoData.CustomMiningBlock? {
if (!accessor.isFakeBlock) return null
val item = accessor.fakeBlock
return item.get(FirmamentDataComponentTypes.CUSTOM_MINING_BLOCK_DATA)
}
}
}

View File

@@ -4,54 +4,18 @@ import snownee.jade.api.BlockAccessor
import snownee.jade.api.IBlockComponentProvider import snownee.jade.api.IBlockComponentProvider
import snownee.jade.api.ITooltip import snownee.jade.api.ITooltip
import snownee.jade.api.config.IPluginConfig import snownee.jade.api.config.IPluginConfig
import net.minecraft.block.Block
import net.minecraft.util.Identifier import net.minecraft.util.Identifier
import moe.nea.firmament.Firmament import moe.nea.firmament.Firmament
import moe.nea.firmament.annotations.Subscribe
import moe.nea.firmament.events.SkyblockServerUpdateEvent
import moe.nea.firmament.repo.MiningRepoData
import moe.nea.firmament.repo.RepoManager
import moe.nea.firmament.util.ErrorUtil
import moe.nea.firmament.util.tr import moe.nea.firmament.util.tr
object CustomMiningHardnessProvider : IBlockComponentProvider { object CustomMiningHardnessProvider : IBlockComponentProvider {
var customBlocks: Map<Block, MiningRepoData.CustomMiningBlock> = mapOf()
fun refreshBlockInfo() {
if (!isOnMiningIsland()) {
customBlocks = mapOf()
return
}
val blocks = RepoManager.miningData.customMiningBlocks
.flatMap { customBlock ->
// TODO: add a lifted helper method for this
customBlock.blocks189.filter { it.isCurrentlyActive }
.mapNotNull { it.block }
.map { customBlock to it }
}
.groupBy { it.second }
customBlocks = blocks.mapNotNull { (block, customBlocks) ->
val singleMatch =
ErrorUtil.notNullOr(customBlocks.singleOrNull()?.first,
"Two custom blocks both want to supply custom mining behaviour for $block.") { return@mapNotNull null }
block to singleMatch
}.toMap()
}
@Subscribe
fun onWorldSwap(event: SkyblockServerUpdateEvent) {
refreshBlockInfo()
}
override fun appendTooltip( override fun appendTooltip(
tooltip: ITooltip, tooltip: ITooltip,
block: BlockAccessor, block: BlockAccessor,
config: IPluginConfig? config: IPluginConfig?
) { ) {
val customBlock = customBlocks[block.block] val customBlock = CustomFakeBlockProvider.getCustomBlock(block) ?: return
?: return
if (customBlock.breakingPower > 0) if (customBlock.breakingPower > 0)
tooltip.add(tr("firmament.jade.breaking_power", "Required Breaking Power: ${customBlock.breakingPower}")) tooltip.add(tr("firmament.jade.breaking_power", "Required Breaking Power: ${customBlock.breakingPower}"))
} }

View File

@@ -18,5 +18,6 @@ class FirmamentJadePlugin : IWailaPlugin {
override fun registerClient(registration: IWailaClientRegistration) { override fun registerClient(registration: IWailaClientRegistration) {
registration.registerBlockComponent(CustomMiningHardnessProvider, Block::class.java) registration.registerBlockComponent(CustomMiningHardnessProvider, Block::class.java)
registration.registerProgressClient(SkyblockProgressProvider()) registration.registerProgressClient(SkyblockProgressProvider())
registration.addRayTraceCallback(CustomFakeBlockProvider(registration))
} }
} }

View File

@@ -11,11 +11,14 @@ import net.minecraft.block.Block
import net.minecraft.item.BlockItem import net.minecraft.item.BlockItem
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
import net.minecraft.nbt.NbtCompound import net.minecraft.nbt.NbtCompound
import net.minecraft.text.Text
import moe.nea.firmament.repo.ReforgeStore.kJson import moe.nea.firmament.repo.ReforgeStore.kJson
import moe.nea.firmament.util.MC import moe.nea.firmament.util.MC
import moe.nea.firmament.util.SBData import moe.nea.firmament.util.SBData
import moe.nea.firmament.util.SkyBlockIsland import moe.nea.firmament.util.SkyBlockIsland
import moe.nea.firmament.util.SkyblockId import moe.nea.firmament.util.SkyblockId
import moe.nea.firmament.util.mc.FirmamentDataComponentTypes
import moe.nea.firmament.util.mc.displayNameAccordingToNbt
class MiningRepoData : IReloadable { class MiningRepoData : IReloadable {
var customMiningAreas: Map<SkyBlockIsland, CustomMiningArea> = mapOf() var customMiningAreas: Map<SkyBlockIsland, CustomMiningArea> = mapOf()
@@ -41,7 +44,23 @@ class MiningRepoData : IReloadable {
val name: String? = null, val name: String? = null,
val baseDrop: SkyblockId? = null, val baseDrop: SkyblockId? = null,
val blocks189: List<Block189> = emptyList() val blocks189: List<Block189> = emptyList()
) ) {
@Transient
val dropItem = baseDrop?.let(::SBItemStack)
private val labeledStack by lazy {
dropItem?.asCopiedItemStack()?.also(::markItemStack)
}
private fun markItemStack(itemStack: ItemStack) {
itemStack.set(FirmamentDataComponentTypes.CUSTOM_MINING_BLOCK_DATA, this)
if (name != null)
itemStack.displayNameAccordingToNbt = Text.literal(name)
}
fun getDisplayItem(block: Block): ItemStack {
return labeledStack ?: ItemStack(block).also(::markItemStack)
}
}
@Serializable @Serializable
data class Block189( data class Block189(
@@ -54,6 +73,7 @@ class MiningRepoData : IReloadable {
val isCurrentlyActive: Boolean val isCurrentlyActive: Boolean
get() = isActiveIn(SBData.skyblockLocation ?: SkyBlockIsland.NIL) get() = isActiveIn(SBData.skyblockLocation ?: SkyBlockIsland.NIL)
fun isActiveIn(location: SkyBlockIsland) = onlyIn == null || location in onlyIn fun isActiveIn(location: SkyBlockIsland) = onlyIn == null || location in onlyIn
private fun convertToModernBlock(): Block? { private fun convertToModernBlock(): Block? {

View File

@@ -1,12 +1,15 @@
package moe.nea.firmament.util.mc package moe.nea.firmament.util.mc
import com.mojang.serialization.Codec import com.mojang.serialization.Codec
import io.netty.buffer.ByteBuf
import net.minecraft.component.ComponentType import net.minecraft.component.ComponentType
import net.minecraft.network.codec.PacketCodec
import net.minecraft.registry.Registries import net.minecraft.registry.Registries
import net.minecraft.registry.Registry import net.minecraft.registry.Registry
import moe.nea.firmament.Firmament import moe.nea.firmament.Firmament
import moe.nea.firmament.annotations.Subscribe import moe.nea.firmament.annotations.Subscribe
import moe.nea.firmament.events.ClientInitEvent import moe.nea.firmament.events.ClientInitEvent
import moe.nea.firmament.repo.MiningRepoData
object FirmamentDataComponentTypes { object FirmamentDataComponentTypes {
@@ -26,11 +29,32 @@ object FirmamentDataComponentTypes {
) )
} }
fun <T> errorCodec(message: String): PacketCodec<in ByteBuf, T> =
object : PacketCodec<ByteBuf, T> {
override fun decode(buf: ByteBuf?): T? {
error(message)
}
override fun encode(buf: ByteBuf?, value: T?) {
error(message)
}
}
fun <T, B : ComponentType.Builder<T>> B.neverEncode(message: String = "This element should never be encoded or decoded"): B {
packetCodec(errorCodec(message))
codec(null)
return this
}
val IS_BROKEN = register<Boolean>( val IS_BROKEN = register<Boolean>(
"is_broken" "is_broken"
) { ) {
it.codec(Codec.BOOL.fieldOf("is_broken").codec()) it.codec(Codec.BOOL.fieldOf("is_broken").codec())
} }
val CUSTOM_MINING_BLOCK_DATA = register<MiningRepoData.CustomMiningBlock>("custom_mining_block") {
it.neverEncode()
}
} }