feat: Add tool/harvestability indicator
This commit is contained in:
@@ -57,7 +57,7 @@ devauth = "1.2.1"
|
|||||||
ktor = "3.0.3"
|
ktor = "3.0.3"
|
||||||
|
|
||||||
# Update from https://repo.nea.moe/#/releases/moe/nea/neurepoparser
|
# Update from https://repo.nea.moe/#/releases/moe/nea/neurepoparser
|
||||||
neurepoparser = "1.6.0"
|
neurepoparser = "1.7.0"
|
||||||
|
|
||||||
# Update from https://github.com/HotswapProjects/HotswapAgent/releases
|
# Update from https://github.com/HotswapProjects/HotswapAgent/releases
|
||||||
# TODO: bump to 2.0.1
|
# TODO: bump to 2.0.1
|
||||||
|
|||||||
@@ -1,36 +0,0 @@
|
|||||||
package moe.nea.firmament.compat.jade
|
|
||||||
|
|
||||||
import com.google.common.collect.Lists
|
|
||||||
import snownee.jade.addon.harvest.SimpleToolHandler
|
|
||||||
import snownee.jade.addon.harvest.ToolHandler
|
|
||||||
import net.minecraft.block.BlockState
|
|
||||||
import net.minecraft.client.MinecraftClient
|
|
||||||
import net.minecraft.item.Item
|
|
||||||
import net.minecraft.item.ItemStack
|
|
||||||
import net.minecraft.util.Identifier
|
|
||||||
import net.minecraft.util.math.BlockPos
|
|
||||||
import net.minecraft.world.World
|
|
||||||
import moe.nea.firmament.util.SBData
|
|
||||||
|
|
||||||
class DrillToolHandler(
|
|
||||||
private val uid: Identifier,
|
|
||||||
private val tools: MutableList<ItemStack>
|
|
||||||
) : ToolHandler {
|
|
||||||
override fun test(state: BlockState, world: World, pos: BlockPos): ItemStack {
|
|
||||||
if (isOnMiningIsland()) {
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: figure out how this work
|
|
||||||
return SimpleToolHandler.create(uid, tools.map {
|
|
||||||
return@map it.item
|
|
||||||
}).test(state, world, pos)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getTools(): List<ItemStack> {
|
|
||||||
return this.tools
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getUid(): Identifier {
|
|
||||||
return this.uid
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,47 +1,79 @@
|
|||||||
package moe.nea.firmament.compat.jade
|
package moe.nea.firmament.compat.jade
|
||||||
|
|
||||||
import com.google.common.cache.Cache
|
import java.util.Optional
|
||||||
import com.google.common.cache.CacheBuilder
|
import java.util.function.UnaryOperator
|
||||||
import com.google.common.collect.ImmutableList
|
|
||||||
import com.google.common.collect.Maps
|
|
||||||
import java.util.concurrent.TimeUnit
|
|
||||||
import snownee.jade.addon.harvest.ToolHandler
|
|
||||||
import snownee.jade.api.BlockAccessor
|
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.JadeIds
|
||||||
import snownee.jade.api.config.IPluginConfig
|
import snownee.jade.api.config.IPluginConfig
|
||||||
import net.minecraft.block.Block
|
import snownee.jade.api.theme.IThemeHelper
|
||||||
import net.minecraft.block.BlockState
|
import snownee.jade.api.ui.IElement
|
||||||
|
import snownee.jade.api.ui.IElementHelper
|
||||||
|
import snownee.jade.impl.ui.ItemStackElement
|
||||||
|
import snownee.jade.impl.ui.TextElement
|
||||||
|
import kotlin.jvm.optionals.getOrDefault
|
||||||
import net.minecraft.item.ItemStack
|
import net.minecraft.item.ItemStack
|
||||||
import net.minecraft.resource.ResourceManager
|
import net.minecraft.item.Items
|
||||||
import net.minecraft.resource.SynchronousResourceReloader
|
|
||||||
import net.minecraft.text.Text
|
import net.minecraft.text.Text
|
||||||
import net.minecraft.util.Identifier
|
import net.minecraft.util.Identifier
|
||||||
import net.minecraft.util.math.Vec2f
|
import net.minecraft.util.math.Vec2f
|
||||||
|
import moe.nea.firmament.Firmament
|
||||||
|
import moe.nea.firmament.repo.ItemCache.asItemStack
|
||||||
|
import moe.nea.firmament.repo.RepoManager
|
||||||
|
import moe.nea.firmament.repo.SBItemStack
|
||||||
|
import moe.nea.firmament.util.MC
|
||||||
|
|
||||||
|
class DrillToolProvider : IBlockComponentProvider {
|
||||||
class DrillToolProvider : IBlockComponentProvider, SynchronousResourceReloader {
|
override fun appendTooltip(
|
||||||
val resultCache: Cache<BlockState, ImmutableList<ItemStack>> = CacheBuilder.newBuilder().expireAfterAccess(5, TimeUnit.MINUTES).build()
|
tooltip: ITooltip,
|
||||||
val toolHandlers: MutableMap<Identifier, ToolHandler> = Maps.newLinkedHashMap()
|
accessor: BlockAccessor,
|
||||||
private val shearableBlocks: MutableList<Block> = mutableListOf()
|
p2: IPluginConfig?
|
||||||
private val checkIcon: Text = Text.literal("✔")
|
) {
|
||||||
private val xIcon: Text = Text.literal("✕")
|
val customBlock = CustomFakeBlockProvider.getCustomBlock(accessor) ?: return
|
||||||
private val itemSize = Vec2f(10f, 0f)
|
if (customBlock.breakingPower <= 0) return
|
||||||
|
val tool = RepoManager.miningData.getToolsThatCanBreak(customBlock.breakingPower).firstOrNull()
|
||||||
@Synchronized
|
?.asItemStack() ?: return
|
||||||
fun registerHandler(handler: ToolHandler) {
|
tooltip.replace(JadeIds.MC_HARVEST_TOOL, UnaryOperator { elements ->
|
||||||
toolHandlers.put(handler.uid, handler)
|
elements.map { inner ->
|
||||||
|
val lastItemIndex = inner.indexOfLast { it is ItemStackElement }
|
||||||
|
if (lastItemIndex < 0) return@map inner
|
||||||
|
val innerMut = inner.toMutableList()
|
||||||
|
val harvestIndicator = innerMut.indexOfLast {
|
||||||
|
it is TextElement && it.cachedSize == Vec2f.ZERO && it.text.visit {
|
||||||
|
if (it.isEmpty()) Optional.empty() else Optional.of(true)
|
||||||
|
}.getOrDefault(false)
|
||||||
|
}
|
||||||
|
val canHarvest = (SBItemStack(MC.stackInHand).neuItem?.breakingPower ?: 0) >= customBlock.breakingPower
|
||||||
|
val lastItem = innerMut[lastItemIndex] as ItemStackElement
|
||||||
|
if (harvestIndicator < 0) {
|
||||||
|
innerMut.add(lastItemIndex + 1, canHarvestIndicator(canHarvest, lastItem.alignment))
|
||||||
|
} else {
|
||||||
|
innerMut.set(harvestIndicator, canHarvestIndicator(canHarvest, lastItem.alignment))
|
||||||
|
}
|
||||||
|
innerMut.set(lastItemIndex, IElementHelper.get()
|
||||||
|
.item(tool, 0.75f)
|
||||||
|
.translate(lastItem.translation)
|
||||||
|
.size(lastItem.size)
|
||||||
|
.message(null)
|
||||||
|
.align(lastItem.alignment))
|
||||||
|
innerMut.subList(0, lastItemIndex - 1).removeIf { it is ItemStackElement }
|
||||||
|
innerMut
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun appendTooltip(tooltip: ITooltip, accessor: BlockAccessor, config: IPluginConfig) {
|
fun canHarvestIndicator(canHarvest: Boolean, align: IElement.Align): IElement {
|
||||||
TODO("Not yet implemented")
|
val t = IThemeHelper.get()
|
||||||
|
val text = if (canHarvest) t.success(CHECK) else t.danger(X)
|
||||||
|
return IElementHelper.get().text(text)
|
||||||
|
.scale(0.75F).zOffset(800).size(Vec2f.ZERO).translate(Vec2f(-3F, 3.25F)).align(align)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val CHECK: Text = Text.literal("✔")
|
||||||
|
private val X: Text = Text.literal("✕")
|
||||||
|
|
||||||
override fun getUid(): Identifier {
|
override fun getUid(): Identifier {
|
||||||
TODO("Not yet implemented")
|
return Firmament.identifier("toolprovider")
|
||||||
}
|
|
||||||
|
|
||||||
override fun reload(manager: ResourceManager) {
|
|
||||||
TODO("Not yet implemented")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package moe.nea.firmament.compat.jade
|
package moe.nea.firmament.compat.jade
|
||||||
|
|
||||||
|
import snownee.jade.addon.harvest.HarvestToolProvider
|
||||||
import snownee.jade.api.IWailaClientRegistration
|
import snownee.jade.api.IWailaClientRegistration
|
||||||
import snownee.jade.api.IWailaCommonRegistration
|
import snownee.jade.api.IWailaCommonRegistration
|
||||||
import snownee.jade.api.IWailaPlugin
|
import snownee.jade.api.IWailaPlugin
|
||||||
@@ -18,6 +19,7 @@ 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.registerBlockComponent(DrillToolProvider(), Block::class.java)
|
||||||
registration.addRayTraceCallback(CustomFakeBlockProvider(registration))
|
registration.addRayTraceCallback(CustomFakeBlockProvider(registration))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,24 +0,0 @@
|
|||||||
package moe.nea.firmament.compat.jade
|
|
||||||
|
|
||||||
import snownee.jade.api.BlockAccessor
|
|
||||||
import snownee.jade.api.IBlockComponentProvider
|
|
||||||
import snownee.jade.api.ITooltip
|
|
||||||
import snownee.jade.api.config.IPluginConfig
|
|
||||||
import net.minecraft.text.Text
|
|
||||||
import net.minecraft.util.Identifier
|
|
||||||
import moe.nea.firmament.util.SBData
|
|
||||||
|
|
||||||
class GemstoneProvider(val type: String, val replacement: String) : IBlockComponentProvider {
|
|
||||||
override fun appendTooltip(tooltip: ITooltip, accessor: BlockAccessor, config: IPluginConfig) {
|
|
||||||
if (SBData.isOnSkyblock) {
|
|
||||||
tooltip.add(drillIcon)
|
|
||||||
// TODO: override jade breakability test to include breaking power of drills on mining islands
|
|
||||||
tooltip.append(Text.of("Breaking Power 6/7/8/9/10")) // TODO: Use NEU API/add new data for breaking power
|
|
||||||
tooltip.replace(Identifier.of("minecraft", type), Text.literal("Gemstone $type of $replacement y")) // this doesnt work
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getUid(): Identifier {
|
|
||||||
return "gemstone_${type}_${replacement}".jadeId()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
package moe.nea.firmament.compat.jade
|
|
||||||
|
|
||||||
import snownee.jade.api.BlockAccessor
|
|
||||||
import snownee.jade.api.IBlockComponentProvider
|
|
||||||
import snownee.jade.api.ITooltip
|
|
||||||
import snownee.jade.api.config.IPluginConfig
|
|
||||||
import net.minecraft.text.Text
|
|
||||||
import net.minecraft.util.Identifier
|
|
||||||
import moe.nea.firmament.util.SBData
|
|
||||||
|
|
||||||
class HardstoneProvider : IBlockComponentProvider {
|
|
||||||
override fun appendTooltip(tooltip: ITooltip, accessor: BlockAccessor, config: IPluginConfig) {
|
|
||||||
if (SBData.isOnSkyblock) {
|
|
||||||
tooltip.add(drillIcon)
|
|
||||||
// TODO: override jade breakability test to include breaking power of drills on mining islands
|
|
||||||
tooltip.append(Text.of("Breaking Power 5"))
|
|
||||||
tooltip.replace(Identifier.of("minecraft", "stone"), Text.literal("Hard Stone")) // this doesnt work
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getUid(): Identifier {
|
|
||||||
return "hardstone".jadeId()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
package moe.nea.firmament.compat.jade
|
|
||||||
|
|
||||||
import snownee.jade.api.BlockAccessor
|
|
||||||
import snownee.jade.api.IBlockComponentProvider
|
|
||||||
import snownee.jade.api.ITooltip
|
|
||||||
import snownee.jade.api.config.IPluginConfig
|
|
||||||
import net.minecraft.text.Text
|
|
||||||
import net.minecraft.util.Identifier
|
|
||||||
import moe.nea.firmament.util.SBData
|
|
||||||
|
|
||||||
class MithrilProvider(val type: String) : IBlockComponentProvider {
|
|
||||||
override fun appendTooltip(tooltip: ITooltip, accessor: BlockAccessor, config: IPluginConfig) {
|
|
||||||
if (SBData.isOnSkyblock) { // why is there no utility to check if we are on an island with mithril am i dumb
|
|
||||||
tooltip.add(drillIcon)
|
|
||||||
tooltip.append(Text.of("Breaking Power 5"))
|
|
||||||
tooltip.replace(Identifier.of("minecraft", type), Text.literal("Mithril $type")) // this doesnt work
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getUid(): Identifier {
|
|
||||||
return "mithril_$type".jadeId()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package moe.nea.firmament.mixins.compat.jade;
|
||||||
|
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||||
|
import snownee.jade.api.ui.Element;
|
||||||
|
import snownee.jade.api.ui.IElement;
|
||||||
|
|
||||||
|
@Mixin(Element.class)
|
||||||
|
public interface ElementAccessor {
|
||||||
|
@Accessor("align")
|
||||||
|
IElement.Align getAlign_firmament();
|
||||||
|
}
|
||||||
@@ -2,6 +2,10 @@ package moe.nea.firmament.repo
|
|||||||
|
|
||||||
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 java.util.Collections
|
||||||
|
import java.util.NavigableMap
|
||||||
|
import java.util.TreeMap
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import kotlinx.serialization.Transient
|
import kotlinx.serialization.Transient
|
||||||
import kotlinx.serialization.serializer
|
import kotlinx.serialization.serializer
|
||||||
@@ -19,14 +23,31 @@ 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.FirmamentDataComponentTypes
|
||||||
import moe.nea.firmament.util.mc.displayNameAccordingToNbt
|
import moe.nea.firmament.util.mc.displayNameAccordingToNbt
|
||||||
|
import moe.nea.firmament.util.skyblockId
|
||||||
|
|
||||||
class MiningRepoData : IReloadable {
|
class MiningRepoData : IReloadable {
|
||||||
var customMiningAreas: Map<SkyBlockIsland, CustomMiningArea> = mapOf()
|
var customMiningAreas: Map<SkyBlockIsland, CustomMiningArea> = mapOf()
|
||||||
private set
|
private set
|
||||||
var customMiningBlocks: List<CustomMiningBlock> = listOf()
|
var customMiningBlocks: List<CustomMiningBlock> = listOf()
|
||||||
private set
|
private set
|
||||||
|
var toolsByBreakingPower: NavigableMap<BreakingPowerKey, NEUItem> = Collections.emptyNavigableMap()
|
||||||
|
private set
|
||||||
|
|
||||||
|
|
||||||
|
data class BreakingPowerKey(
|
||||||
|
val breakingPower: Int,
|
||||||
|
val itemId: SkyblockId? = null
|
||||||
|
) {
|
||||||
|
companion object {
|
||||||
|
val COMPARATOR: Comparator<BreakingPowerKey> =
|
||||||
|
Comparator
|
||||||
|
.comparingInt<BreakingPowerKey> { it.breakingPower }
|
||||||
|
.thenComparing(Comparator.comparing(
|
||||||
|
{ it.itemId },
|
||||||
|
nullsFirst(Comparator.naturalOrder<SkyblockId>())))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun reload(repo: NEURepository) {
|
override fun reload(repo: NEURepository) {
|
||||||
customMiningAreas = repo.file("mining/custom_mining_areas.json")
|
customMiningAreas = repo.file("mining/custom_mining_areas.json")
|
||||||
?.kJson(serializer()) ?: mapOf()
|
?.kJson(serializer()) ?: mapOf()
|
||||||
@@ -35,6 +56,18 @@ class MiningRepoData : IReloadable {
|
|||||||
.filter { it.path.endsWith(".json") }
|
.filter { it.path.endsWith(".json") }
|
||||||
.map { it.kJson(serializer<CustomMiningBlock>()) }
|
.map { it.kJson(serializer<CustomMiningBlock>()) }
|
||||||
.toList()
|
.toList()
|
||||||
|
toolsByBreakingPower = Collections.unmodifiableNavigableMap(
|
||||||
|
repo.items.items
|
||||||
|
.values
|
||||||
|
.asSequence()
|
||||||
|
.filter { it.breakingPower > 0 }
|
||||||
|
.associateTo(TreeMap<BreakingPowerKey, NEUItem>(BreakingPowerKey.COMPARATOR)) {
|
||||||
|
BreakingPowerKey(it.breakingPower, it.skyblockId) to it
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getToolsThatCanBreak(breakingPower: Int): Collection<NEUItem> {
|
||||||
|
return toolsByBreakingPower.tailMap(BreakingPowerKey(breakingPower, null), true).values
|
||||||
}
|
}
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ object MC {
|
|||||||
inline val soundManager get() = instance.soundManager
|
inline val soundManager get() = instance.soundManager
|
||||||
inline val player: ClientPlayerEntity? get() = TestUtil.unlessTesting { instance.player }
|
inline val player: ClientPlayerEntity? get() = TestUtil.unlessTesting { instance.player }
|
||||||
inline val camera: Entity? get() = instance.cameraEntity
|
inline val camera: Entity? get() = instance.cameraEntity
|
||||||
inline val stackInHand: ItemStack? get() = player?.inventory?.mainHandStack
|
inline val stackInHand: ItemStack get() = player?.inventory?.mainHandStack ?: ItemStack.EMPTY
|
||||||
inline val guiAtlasManager get() = instance.guiAtlasManager
|
inline val guiAtlasManager get() = instance.guiAtlasManager
|
||||||
inline val world: ClientWorld? get() = TestUtil.unlessTesting { instance.world }
|
inline val world: ClientWorld? get() = TestUtil.unlessTesting { instance.world }
|
||||||
inline val playerName: String? get() = player?.name?.unformattedString
|
inline val playerName: String? get() = player?.name?.unformattedString
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ import moe.nea.firmament.util.json.DashlessUUIDSerializer
|
|||||||
*/
|
*/
|
||||||
@JvmInline
|
@JvmInline
|
||||||
@Serializable
|
@Serializable
|
||||||
value class SkyblockId(val neuItem: String) {
|
value class SkyblockId(val neuItem: String) : Comparable<SkyblockId> {
|
||||||
val identifier
|
val identifier
|
||||||
get() = Identifier.of("skyblockitem",
|
get() = Identifier.of("skyblockitem",
|
||||||
neuItem.lowercase().replace(";", "__")
|
neuItem.lowercase().replace(";", "__")
|
||||||
@@ -48,6 +48,10 @@ value class SkyblockId(val neuItem: String) {
|
|||||||
return neuItem
|
return neuItem
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun compareTo(other: SkyblockId): Int {
|
||||||
|
return neuItem.compareTo(other.neuItem)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A bazaar stock item id, as returned by the HyPixel bazaar api endpoint.
|
* A bazaar stock item id, as returned by the HyPixel bazaar api endpoint.
|
||||||
* These are not equivalent to the in-game ids, or the NEU repo ids, and in fact, do not refer to items, but instead
|
* These are not equivalent to the in-game ids, or the NEU repo ids, and in fact, do not refer to items, but instead
|
||||||
|
|||||||
Reference in New Issue
Block a user