feat: Add pickobulus blocker on private island
This commit is contained in:
@@ -20,6 +20,7 @@ import io.github.notenoughupdates.moulconfig.gui.editors.ComponentEditor
|
||||
import io.github.notenoughupdates.moulconfig.gui.editors.GuiOptionEditorAccordion
|
||||
import io.github.notenoughupdates.moulconfig.gui.editors.GuiOptionEditorBoolean
|
||||
import io.github.notenoughupdates.moulconfig.gui.editors.GuiOptionEditorButton
|
||||
import io.github.notenoughupdates.moulconfig.gui.editors.GuiOptionEditorDropdown
|
||||
import io.github.notenoughupdates.moulconfig.gui.editors.GuiOptionEditorText
|
||||
import io.github.notenoughupdates.moulconfig.observer.GetSetter
|
||||
import io.github.notenoughupdates.moulconfig.processor.ProcessedCategory
|
||||
@@ -31,9 +32,11 @@ import kotlin.time.Duration.Companion.seconds
|
||||
import kotlin.time.DurationUnit
|
||||
import net.minecraft.client.gui.screen.Screen
|
||||
import net.minecraft.util.Identifier
|
||||
import net.minecraft.util.StringIdentifiable
|
||||
import net.minecraft.util.Util
|
||||
import moe.nea.firmament.Firmament
|
||||
import moe.nea.firmament.gui.config.BooleanHandler
|
||||
import moe.nea.firmament.gui.config.ChoiceHandler
|
||||
import moe.nea.firmament.gui.config.ClickHandler
|
||||
import moe.nea.firmament.gui.config.DurationHandler
|
||||
import moe.nea.firmament.gui.config.FirmamentConfigScreenProvider
|
||||
@@ -115,7 +118,33 @@ class MCConfigEditorIntegration : FirmamentConfigScreenProvider {
|
||||
}
|
||||
}
|
||||
|
||||
fun <T> helpRegisterChoice() where T : Enum<T>, T : StringIdentifiable {
|
||||
register(ChoiceHandler::class.java as Class<ChoiceHandler<T>>) { handler, option, categoryAccordionId, configObject ->
|
||||
object : ProcessedEditableOptionFirm<T>(option, categoryAccordionId, configObject) {
|
||||
override fun createEditor(): GuiOptionEditor {
|
||||
return GuiOptionEditorDropdown(
|
||||
this,
|
||||
handler.universe.map { handler.renderer.getName(option, it).string }.toTypedArray()
|
||||
)
|
||||
}
|
||||
|
||||
override fun toT(any: Any?): T? {
|
||||
return handler.universe[any as Int]
|
||||
}
|
||||
|
||||
override fun getType(): Type {
|
||||
return Int::class.java
|
||||
}
|
||||
|
||||
override fun fromT(t: T): Any {
|
||||
return t.ordinal
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
helpRegisterChoice<Nothing>()
|
||||
register(BooleanHandler::class.java) { handler, option, categoryAccordionId, configObject ->
|
||||
object : ProcessedEditableOptionFirm<Boolean>(option, categoryAccordionId, configObject) {
|
||||
override fun createEditor(): GuiOptionEditor {
|
||||
|
||||
@@ -16,6 +16,14 @@ import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
public class AutoDiscoveryPlugin {
|
||||
public static List<String> getDefaultAllMixinClassesFQNs() {
|
||||
var defaultName = "moe.nea.firmament.mixins";
|
||||
var plugin = new AutoDiscoveryPlugin();
|
||||
plugin.setMixinPackage(defaultName);
|
||||
var mixins = plugin.getMixins();
|
||||
return mixins.stream().map(it -> defaultName + "." + it).toList();
|
||||
}
|
||||
|
||||
private static final List<AutoDiscoveryPlugin> mixinPlugins = new ArrayList<>();
|
||||
|
||||
public static List<AutoDiscoveryPlugin> getMixinPlugins() {
|
||||
|
||||
11
src/main/kotlin/events/UseItemEvent.kt
Normal file
11
src/main/kotlin/events/UseItemEvent.kt
Normal file
@@ -0,0 +1,11 @@
|
||||
package moe.nea.firmament.events
|
||||
|
||||
import net.minecraft.entity.player.PlayerEntity
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.util.Hand
|
||||
import net.minecraft.world.World
|
||||
|
||||
data class UseItemEvent(val playerEntity: PlayerEntity, val world: World, val hand: Hand) : FirmamentEvent.Cancellable() {
|
||||
companion object : FirmamentEventBus<UseItemEvent>()
|
||||
val item: ItemStack = playerEntity.getStackInHand(hand)
|
||||
}
|
||||
@@ -1,10 +1,9 @@
|
||||
|
||||
|
||||
package moe.nea.firmament.events.registration
|
||||
|
||||
import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents
|
||||
import net.fabricmc.fabric.api.event.player.AttackBlockCallback
|
||||
import net.fabricmc.fabric.api.event.player.UseBlockCallback
|
||||
import net.fabricmc.fabric.api.event.player.UseItemCallback
|
||||
import net.minecraft.text.Text
|
||||
import net.minecraft.util.ActionResult
|
||||
import moe.nea.firmament.events.AllowChatEvent
|
||||
@@ -12,6 +11,7 @@ import moe.nea.firmament.events.AttackBlockEvent
|
||||
import moe.nea.firmament.events.ModifyChatEvent
|
||||
import moe.nea.firmament.events.ProcessChatEvent
|
||||
import moe.nea.firmament.events.UseBlockEvent
|
||||
import moe.nea.firmament.events.UseItemEvent
|
||||
|
||||
private var lastReceivedMessage: Text? = null
|
||||
|
||||
@@ -51,4 +51,13 @@ fun registerFirmamentEvents() {
|
||||
ActionResult.CONSUME
|
||||
else ActionResult.PASS
|
||||
})
|
||||
UseBlockCallback.EVENT.register(UseBlockCallback { player, world, hand, hitResult ->
|
||||
if (UseItemEvent.publish(UseItemEvent(player, world, hand)).cancelled)
|
||||
ActionResult.CONSUME
|
||||
else ActionResult.PASS
|
||||
})
|
||||
UseItemCallback.EVENT.register(UseItemCallback { playerEntity, world, hand ->
|
||||
if (UseItemEvent.publish(UseItemEvent(playerEntity, world, hand)).cancelled) ActionResult.CONSUME
|
||||
else ActionResult.PASS
|
||||
})
|
||||
}
|
||||
|
||||
@@ -7,11 +7,13 @@ import net.minecraft.item.ItemStack
|
||||
import net.minecraft.util.DyeColor
|
||||
import net.minecraft.util.Hand
|
||||
import net.minecraft.util.Identifier
|
||||
import net.minecraft.util.StringIdentifiable
|
||||
import moe.nea.firmament.annotations.Subscribe
|
||||
import moe.nea.firmament.events.HudRenderEvent
|
||||
import moe.nea.firmament.events.ProcessChatEvent
|
||||
import moe.nea.firmament.events.ProfileSwitchEvent
|
||||
import moe.nea.firmament.events.SlotClickEvent
|
||||
import moe.nea.firmament.events.UseItemEvent
|
||||
import moe.nea.firmament.events.WorldReadyEvent
|
||||
import moe.nea.firmament.features.FirmamentFeature
|
||||
import moe.nea.firmament.gui.config.ManagedConfig
|
||||
@@ -27,10 +29,13 @@ import moe.nea.firmament.util.mc.displayNameAccordingToNbt
|
||||
import moe.nea.firmament.util.mc.loreAccordingToNbt
|
||||
import moe.nea.firmament.util.parseShortNumber
|
||||
import moe.nea.firmament.util.parseTimePattern
|
||||
import moe.nea.firmament.util.red
|
||||
import moe.nea.firmament.util.render.RenderCircleProgress
|
||||
import moe.nea.firmament.util.render.lerp
|
||||
import moe.nea.firmament.util.skyblock.AbilityUtils
|
||||
import moe.nea.firmament.util.skyblock.ItemType
|
||||
import moe.nea.firmament.util.toShedaniel
|
||||
import moe.nea.firmament.util.tr
|
||||
import moe.nea.firmament.util.unformattedString
|
||||
import moe.nea.firmament.util.useMatch
|
||||
|
||||
@@ -43,6 +48,22 @@ object PickaxeAbility : FirmamentFeature {
|
||||
val cooldownEnabled by toggle("ability-cooldown") { false }
|
||||
val cooldownScale by integer("ability-scale", 16, 64) { 16 }
|
||||
val drillFuelBar by toggle("fuel-bar") { true }
|
||||
val blockOnPrivateIsland by choice(
|
||||
"block-on-dynamic",
|
||||
BlockPickaxeAbility.entries,
|
||||
) {
|
||||
BlockPickaxeAbility.ONLY_DESTRUCTIVE
|
||||
}
|
||||
}
|
||||
|
||||
enum class BlockPickaxeAbility : StringIdentifiable {
|
||||
NEVER,
|
||||
ALWAYS,
|
||||
ONLY_DESTRUCTIVE;
|
||||
|
||||
override fun asString(): String {
|
||||
return name
|
||||
}
|
||||
}
|
||||
|
||||
var lobbyJoinTime = TimeMark.farPast()
|
||||
@@ -56,6 +77,8 @@ object PickaxeAbility : FirmamentFeature {
|
||||
"Maniac Miner" to 59.seconds,
|
||||
"Vein Seeker" to 60.seconds
|
||||
)
|
||||
val destructiveAbilities = setOf("Pickobulus")
|
||||
val pickaxeTypes = setOf(ItemType.PICKAXE, ItemType.DRILL, ItemType.GAUNTLET)
|
||||
|
||||
override val config: ManagedConfig
|
||||
get() = TConfig
|
||||
@@ -73,6 +96,26 @@ object PickaxeAbility : FirmamentFeature {
|
||||
return 1.0
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
fun onPickaxeRightClick(event: UseItemEvent) {
|
||||
if (TConfig.blockOnPrivateIsland == BlockPickaxeAbility.NEVER) return
|
||||
val itemType = ItemType.fromItemStack(event.item)
|
||||
if (itemType !in pickaxeTypes) return
|
||||
val ability = AbilityUtils.getAbilities(event.item)
|
||||
val shouldBlock = when (TConfig.blockOnPrivateIsland) {
|
||||
BlockPickaxeAbility.NEVER -> false
|
||||
BlockPickaxeAbility.ALWAYS -> ability.any()
|
||||
BlockPickaxeAbility.ONLY_DESTRUCTIVE -> ability.any { it.name in destructiveAbilities }
|
||||
}
|
||||
if (shouldBlock) {
|
||||
MC.sendChat(tr("firmament.pickaxe.blocked",
|
||||
"Firmament blocked a pickaxe ability from being used on a private island.")
|
||||
.red() // TODO: .clickCommand("firm confignavigate ${TConfig.identifier} block-on-dynamic")
|
||||
)
|
||||
event.cancel()
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
fun onSlotClick(it: SlotClickEvent) {
|
||||
if (MC.screen?.title?.unformattedString == "Heart of the Mountain") {
|
||||
|
||||
56
src/main/kotlin/gui/CheckboxComponent.kt
Normal file
56
src/main/kotlin/gui/CheckboxComponent.kt
Normal file
@@ -0,0 +1,56 @@
|
||||
package moe.nea.firmament.gui
|
||||
|
||||
import io.github.notenoughupdates.moulconfig.gui.GuiComponent
|
||||
import io.github.notenoughupdates.moulconfig.gui.GuiImmediateContext
|
||||
import io.github.notenoughupdates.moulconfig.gui.MouseEvent
|
||||
import io.github.notenoughupdates.moulconfig.observer.GetSetter
|
||||
import io.github.notenoughupdates.moulconfig.platform.ModernRenderContext
|
||||
import net.minecraft.client.render.RenderLayer
|
||||
import moe.nea.firmament.Firmament
|
||||
|
||||
class CheckboxComponent<T>(
|
||||
val state: GetSetter<T>,
|
||||
val value: T,
|
||||
) : GuiComponent() {
|
||||
override fun getWidth(): Int {
|
||||
return 16
|
||||
}
|
||||
|
||||
override fun getHeight(): Int {
|
||||
return 16
|
||||
}
|
||||
|
||||
fun isEnabled(): Boolean {
|
||||
return state.get() == value
|
||||
}
|
||||
|
||||
override fun render(context: GuiImmediateContext) {
|
||||
val ctx = (context.renderContext as ModernRenderContext).drawContext
|
||||
ctx.drawGuiTexture(
|
||||
RenderLayer::getGuiTextured,
|
||||
if (isEnabled()) Firmament.identifier("firmament:widget/checkbox_checked")
|
||||
else Firmament.identifier("firmament:widget/checkbox_unchecked"),
|
||||
0, 0,
|
||||
16, 16
|
||||
)
|
||||
}
|
||||
|
||||
var isClicking = false
|
||||
|
||||
override fun mouseEvent(mouseEvent: MouseEvent, context: GuiImmediateContext): Boolean {
|
||||
if (mouseEvent is MouseEvent.Click) {
|
||||
if (isClicking && !mouseEvent.mouseState && mouseEvent.mouseButton == 0) {
|
||||
isClicking = false
|
||||
if (context.isHovered)
|
||||
state.set(value)
|
||||
return true
|
||||
}
|
||||
if (mouseEvent.mouseState && mouseEvent.mouseButton == 0 && context.isHovered) {
|
||||
requestFocus()
|
||||
isClicking = true
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
47
src/main/kotlin/gui/config/ChoiceHandler.kt
Normal file
47
src/main/kotlin/gui/config/ChoiceHandler.kt
Normal file
@@ -0,0 +1,47 @@
|
||||
package moe.nea.firmament.gui.config
|
||||
|
||||
import io.github.notenoughupdates.moulconfig.gui.HorizontalAlign
|
||||
import io.github.notenoughupdates.moulconfig.gui.VerticalAlign
|
||||
import io.github.notenoughupdates.moulconfig.gui.component.AlignComponent
|
||||
import io.github.notenoughupdates.moulconfig.gui.component.RowComponent
|
||||
import io.github.notenoughupdates.moulconfig.gui.component.TextComponent
|
||||
import kotlinx.serialization.json.JsonElement
|
||||
import kotlin.jvm.optionals.getOrNull
|
||||
import net.minecraft.util.StringIdentifiable
|
||||
import moe.nea.firmament.gui.CheckboxComponent
|
||||
import moe.nea.firmament.util.ErrorUtil
|
||||
import moe.nea.firmament.util.json.KJsonOps
|
||||
|
||||
class ChoiceHandler<E>(
|
||||
val universe: List<E>,
|
||||
) : ManagedConfig.OptionHandler<E> where E : Enum<E>, E : StringIdentifiable {
|
||||
val codec = StringIdentifiable.createCodec {
|
||||
@Suppress("UNCHECKED_CAST", "PLATFORM_CLASS_MAPPED_TO_KOTLIN")
|
||||
(universe as java.util.List<*>).toArray(arrayOfNulls<Enum<E>>(0)) as Array<E>
|
||||
}
|
||||
val renderer = EnumRenderer.default<E>()
|
||||
|
||||
override fun toJson(element: E): JsonElement? {
|
||||
return codec.encodeStart(KJsonOps.INSTANCE, element)
|
||||
.promotePartial { ErrorUtil.softError("Failed to encode json element '$element': $it") }.result()
|
||||
.getOrNull()
|
||||
}
|
||||
|
||||
override fun fromJson(element: JsonElement): E {
|
||||
return codec.decode(KJsonOps.INSTANCE, element)
|
||||
.promotePartial { ErrorUtil.softError("Failed to decode json element '$element': $it") }
|
||||
.result()
|
||||
.get()
|
||||
.first
|
||||
}
|
||||
|
||||
override fun emitGuiElements(opt: ManagedOption<E>, guiAppender: GuiAppender) {
|
||||
guiAppender.appendFullRow(TextComponent(opt.labelText.string))
|
||||
for (e in universe) {
|
||||
guiAppender.appendFullRow(RowComponent(
|
||||
AlignComponent(CheckboxComponent(opt, e), { HorizontalAlign.LEFT }, { VerticalAlign.CENTER }),
|
||||
TextComponent(renderer.getName(opt, e).string)
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
15
src/main/kotlin/gui/config/EnumRenderer.kt
Normal file
15
src/main/kotlin/gui/config/EnumRenderer.kt
Normal file
@@ -0,0 +1,15 @@
|
||||
package moe.nea.firmament.gui.config
|
||||
|
||||
import net.minecraft.text.Text
|
||||
|
||||
interface EnumRenderer<E : Any> {
|
||||
fun getName(option: ManagedOption<E>, value: E): Text
|
||||
|
||||
companion object {
|
||||
fun <E : Enum<E>> default() = object : EnumRenderer<E> {
|
||||
override fun getName(option: ManagedOption<E>, value: E): Text {
|
||||
return Text.translatable(option.rawLabelText + ".choice." + value.name.lowercase())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package moe.nea.firmament.gui.config
|
||||
|
||||
import com.mojang.serialization.Codec
|
||||
import io.github.notenoughupdates.moulconfig.gui.CloseEventListener
|
||||
import io.github.notenoughupdates.moulconfig.gui.GuiComponentWrapper
|
||||
import io.github.notenoughupdates.moulconfig.gui.GuiContext
|
||||
@@ -20,6 +21,7 @@ import kotlin.io.path.writeText
|
||||
import kotlin.time.Duration
|
||||
import net.minecraft.client.gui.screen.Screen
|
||||
import net.minecraft.text.Text
|
||||
import net.minecraft.util.StringIdentifiable
|
||||
import moe.nea.firmament.Firmament
|
||||
import moe.nea.firmament.gui.FirmButtonComponent
|
||||
import moe.nea.firmament.keybindings.SavedKeyBinding
|
||||
@@ -113,6 +115,28 @@ abstract class ManagedConfig(
|
||||
return option(propertyName, default, BooleanHandler(this))
|
||||
}
|
||||
|
||||
protected fun <E> choice(
|
||||
propertyName: String,
|
||||
universe: List<E>,
|
||||
default: () -> E
|
||||
): ManagedOption<E> where E : Enum<E>, E : StringIdentifiable {
|
||||
return option(propertyName, default, ChoiceHandler(universe))
|
||||
}
|
||||
|
||||
// TODO: wait on https://youtrack.jetbrains.com/issue/KT-73434
|
||||
// protected inline fun <reified E> choice(
|
||||
// propertyName: String,
|
||||
// noinline default: () -> E
|
||||
// ): ManagedOption<E> where E : Enum<E>, E : StringIdentifiable {
|
||||
// return choice(
|
||||
// propertyName,
|
||||
// enumEntries<E>().toList(),
|
||||
// StringIdentifiable.createCodec { enumValues<E>() },
|
||||
// EnumRenderer.default(),
|
||||
// default
|
||||
// )
|
||||
// }
|
||||
|
||||
protected fun duration(
|
||||
propertyName: String,
|
||||
min: Duration,
|
||||
|
||||
@@ -1,23 +1,22 @@
|
||||
|
||||
|
||||
package moe.nea.firmament.keybindings
|
||||
|
||||
import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper
|
||||
import net.minecraft.client.option.KeyBinding
|
||||
import net.minecraft.client.util.InputUtil
|
||||
import moe.nea.firmament.gui.config.KeyBindingHandler
|
||||
import moe.nea.firmament.gui.config.ManagedOption
|
||||
import moe.nea.firmament.util.TestUtil
|
||||
|
||||
object FirmamentKeyBindings {
|
||||
fun registerKeyBinding(name: String, config: ManagedOption<SavedKeyBinding>) {
|
||||
val vanillaKeyBinding = KeyBindingHelper.registerKeyBinding(
|
||||
KeyBinding(
|
||||
val vanillaKeyBinding = KeyBinding(
|
||||
name,
|
||||
InputUtil.Type.KEYSYM,
|
||||
-1,
|
||||
"firmament.key.category"
|
||||
)
|
||||
)
|
||||
if (!TestUtil.isInTest) {
|
||||
KeyBindingHelper.registerKeyBinding(vanillaKeyBinding)
|
||||
}
|
||||
keyBindings[vanillaKeyBinding] = config
|
||||
}
|
||||
|
||||
|
||||
@@ -92,12 +92,12 @@ object MC {
|
||||
inline val inGameHud: InGameHud get() = instance.inGameHud
|
||||
inline val font get() = instance.textRenderer
|
||||
inline val soundManager get() = instance.soundManager
|
||||
inline val player: ClientPlayerEntity? get() = instance.player
|
||||
inline val player: ClientPlayerEntity? get() = TestUtil.unlessTesting { instance.player }
|
||||
inline val camera: Entity? get() = instance.cameraEntity
|
||||
inline val guiAtlasManager get() = instance.guiAtlasManager
|
||||
inline val world: ClientWorld? get() = instance.world
|
||||
inline val world: ClientWorld? get() = TestUtil.unlessTesting { instance.world }
|
||||
inline var screen: Screen?
|
||||
get() = instance.currentScreen
|
||||
get() = TestUtil.unlessTesting{ instance.currentScreen }
|
||||
set(value) = instance.setScreen(value)
|
||||
val screenName get() = screen?.title?.unformattedString?.trim()
|
||||
inline val handledScreen: HandledScreen<*>? get() = instance.currentScreen as? HandledScreen<*>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package moe.nea.firmament.util
|
||||
|
||||
object TestUtil {
|
||||
inline fun <T> unlessTesting(block: () -> T): T? = if (isInTest) null else block()
|
||||
val isInTest =
|
||||
Thread.currentThread().stackTrace.any {
|
||||
it.className.startsWith("org.junit.") || it.className.startsWith("io.kotest.")
|
||||
|
||||
131
src/main/kotlin/util/json/KJsonOps.kt
Normal file
131
src/main/kotlin/util/json/KJsonOps.kt
Normal file
@@ -0,0 +1,131 @@
|
||||
package moe.nea.firmament.util.json
|
||||
|
||||
import com.google.gson.internal.LazilyParsedNumber
|
||||
import com.mojang.datafixers.util.Pair
|
||||
import com.mojang.serialization.DataResult
|
||||
import com.mojang.serialization.DynamicOps
|
||||
import java.util.stream.Stream
|
||||
import kotlinx.serialization.json.JsonArray
|
||||
import kotlinx.serialization.json.JsonElement
|
||||
import kotlinx.serialization.json.JsonNull
|
||||
import kotlinx.serialization.json.JsonObject
|
||||
import kotlinx.serialization.json.JsonPrimitive
|
||||
import kotlinx.serialization.json.boolean
|
||||
import kotlinx.serialization.json.booleanOrNull
|
||||
import kotlin.streams.asSequence
|
||||
|
||||
class KJsonOps : DynamicOps<JsonElement> {
|
||||
companion object {
|
||||
val INSTANCE = KJsonOps()
|
||||
}
|
||||
|
||||
override fun empty(): JsonElement {
|
||||
return JsonNull
|
||||
}
|
||||
|
||||
override fun createNumeric(num: Number): JsonElement {
|
||||
return JsonPrimitive(num)
|
||||
}
|
||||
|
||||
override fun createString(str: String): JsonElement {
|
||||
return JsonPrimitive(str)
|
||||
}
|
||||
|
||||
override fun remove(input: JsonElement, key: String): JsonElement {
|
||||
if (input is JsonObject) {
|
||||
return JsonObject(input.filter { it.key != key })
|
||||
} else {
|
||||
return input
|
||||
}
|
||||
}
|
||||
|
||||
override fun createList(stream: Stream<JsonElement>): JsonElement {
|
||||
return JsonArray(stream.toList())
|
||||
}
|
||||
|
||||
override fun getStream(input: JsonElement): DataResult<Stream<JsonElement>> {
|
||||
if (input is JsonArray)
|
||||
return DataResult.success(input.stream())
|
||||
return DataResult.error { "Not a json array: $input" }
|
||||
}
|
||||
|
||||
override fun createMap(map: Stream<Pair<JsonElement, JsonElement>>): JsonElement {
|
||||
return JsonObject(map.asSequence()
|
||||
.map { ((it.first as JsonPrimitive).content) to it.second }
|
||||
.toMap())
|
||||
}
|
||||
|
||||
override fun getMapValues(input: JsonElement): DataResult<Stream<Pair<JsonElement, JsonElement>>> {
|
||||
if (input is JsonObject) {
|
||||
return DataResult.success(input.entries.stream().map { Pair.of(createString(it.key), it.value) })
|
||||
}
|
||||
return DataResult.error { "Not a JSON object: $input" }
|
||||
}
|
||||
|
||||
override fun mergeToMap(map: JsonElement, key: JsonElement, value: JsonElement): DataResult<JsonElement> {
|
||||
if (key !is JsonPrimitive || key.isString) {
|
||||
return DataResult.error { "key is not a string: $key" }
|
||||
}
|
||||
val jKey = key.content
|
||||
val extra = mapOf(jKey to value)
|
||||
if (map == empty()) {
|
||||
return DataResult.success(JsonObject(extra))
|
||||
}
|
||||
if (map is JsonObject) {
|
||||
return DataResult.success(JsonObject(map + extra))
|
||||
}
|
||||
return DataResult.error { "mergeToMap called with not a map: $map" }
|
||||
}
|
||||
|
||||
override fun mergeToList(list: JsonElement, value: JsonElement): DataResult<JsonElement> {
|
||||
if (list == empty())
|
||||
return DataResult.success(JsonArray(listOf(value)))
|
||||
if (list is JsonArray) {
|
||||
return DataResult.success(JsonArray(list + value))
|
||||
}
|
||||
return DataResult.error { "mergeToList called with not a list: $list" }
|
||||
}
|
||||
|
||||
override fun getStringValue(input: JsonElement): DataResult<String> {
|
||||
if (input is JsonPrimitive && input.isString) {
|
||||
return DataResult.success(input.content)
|
||||
}
|
||||
return DataResult.error { "Not a string: $input" }
|
||||
}
|
||||
|
||||
override fun getNumberValue(input: JsonElement): DataResult<Number> {
|
||||
if (input is JsonPrimitive && !input.isString && input.booleanOrNull == null)
|
||||
return DataResult.success(LazilyParsedNumber(input.content))
|
||||
return DataResult.error { "not a number: $input" }
|
||||
}
|
||||
|
||||
override fun createBoolean(value: Boolean): JsonElement {
|
||||
return JsonPrimitive(value)
|
||||
}
|
||||
|
||||
override fun getBooleanValue(input: JsonElement): DataResult<Boolean> {
|
||||
if (input is JsonPrimitive) {
|
||||
if (input.booleanOrNull != null)
|
||||
return DataResult.success(input.boolean)
|
||||
return super.getBooleanValue(input)
|
||||
}
|
||||
return DataResult.error { "Not a boolean: $input" }
|
||||
}
|
||||
|
||||
override fun <U : Any?> convertTo(output: DynamicOps<U>, input: JsonElement): U {
|
||||
if (input is JsonObject)
|
||||
return output.createMap(
|
||||
input.entries.stream().map { Pair.of(output.createString(it.key), convertTo(output, it.value)) })
|
||||
if (input is JsonArray)
|
||||
return output.createList(input.stream().map { convertTo(output, it) })
|
||||
if (input is JsonNull)
|
||||
return output.empty()
|
||||
if (input is JsonPrimitive) {
|
||||
if (input.isString)
|
||||
return output.createString(input.content)
|
||||
if (input.booleanOrNull != null)
|
||||
return output.createBoolean(input.boolean)
|
||||
}
|
||||
error("Unknown json value: $input")
|
||||
}
|
||||
}
|
||||
@@ -32,10 +32,15 @@ value class ItemType private constructor(val name: String) {
|
||||
val SWORD = ofName("SWORD")
|
||||
val DRILL = ofName("DRILL")
|
||||
val PICKAXE = ofName("PICKAXE")
|
||||
val GAUNTLET = ofName("GAUNTLET")
|
||||
|
||||
/**
|
||||
* This one is not really official (it never shows up in game).
|
||||
*/
|
||||
val PET = ofName("PET")
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return name
|
||||
}
|
||||
}
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 683 B |
Binary file not shown.
|
After Width: | Height: | Size: 614 B |
@@ -34,3 +34,5 @@ accessible method net/minecraft/entity/passive/TameableEntity isInSameTeam (Lnet
|
||||
accessible method net/minecraft/entity/Entity isInSameTeam (Lnet/minecraft/entity/Entity;)Z
|
||||
accessible method net/minecraft/registry/entry/RegistryEntry$Reference setTags (Ljava/util/Collection;)V
|
||||
accessible method net/minecraft/registry/entry/RegistryEntryList$Named setEntries (Ljava/util/List;)V
|
||||
accessible method net/minecraft/world/biome/source/util/VanillaBiomeParameters writeOverworldBiomeParameters (Ljava/util/function/Consumer;)V
|
||||
accessible method net/minecraft/world/gen/densityfunction/DensityFunctions createSurfaceNoiseRouter (Lnet/minecraft/registry/RegistryEntryLookup;Lnet/minecraft/registry/RegistryEntryLookup;ZZ)Lnet/minecraft/world/gen/noise/NoiseRouter;
|
||||
|
||||
@@ -2,11 +2,14 @@ package moe.nea.firmament.test.testutil
|
||||
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.nbt.NbtCompound
|
||||
import net.minecraft.nbt.NbtElement
|
||||
import net.minecraft.nbt.NbtOps
|
||||
import net.minecraft.nbt.StringNbtReader
|
||||
import net.minecraft.registry.RegistryOps
|
||||
import net.minecraft.text.Text
|
||||
import net.minecraft.text.TextCodecs
|
||||
import moe.nea.firmament.test.FirmTestBootstrap
|
||||
import moe.nea.firmament.util.MC
|
||||
|
||||
object ItemResources {
|
||||
init {
|
||||
@@ -23,15 +26,16 @@ object ItemResources {
|
||||
fun loadSNbt(path: String): NbtCompound {
|
||||
return StringNbtReader.parse(loadString(path))
|
||||
}
|
||||
fun getNbtOps(): RegistryOps<NbtElement> = MC.currentOrDefaultRegistries.getOps(NbtOps.INSTANCE)
|
||||
|
||||
fun loadText(name: String): Text {
|
||||
return TextCodecs.CODEC.parse(NbtOps.INSTANCE, loadSNbt("testdata/chat/$name.snbt"))
|
||||
return TextCodecs.CODEC.parse(getNbtOps(), loadSNbt("testdata/chat/$name.snbt"))
|
||||
.getOrThrow { IllegalStateException("Could not load test chat '$name': $it") }
|
||||
}
|
||||
|
||||
fun loadItem(name: String): ItemStack {
|
||||
// TODO: make the load work with enchantments
|
||||
return ItemStack.CODEC.parse(NbtOps.INSTANCE, loadSNbt("testdata/items/$name.snbt"))
|
||||
return ItemStack.CODEC.parse(getNbtOps(), loadSNbt("testdata/items/$name.snbt"))
|
||||
.getOrThrow { IllegalStateException("Could not load test item '$name': $it") }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ package moe.nea.firmament.test.util
|
||||
|
||||
import io.kotest.core.spec.style.AnnotationSpec
|
||||
import org.junit.jupiter.api.Assertions
|
||||
import org.junit.jupiter.api.Test
|
||||
import moe.nea.firmament.test.testutil.ItemResources
|
||||
import moe.nea.firmament.util.getLegacyFormatString
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@ package moe.nea.firmament.test.util.skyblock
|
||||
|
||||
import io.kotest.core.spec.style.AnnotationSpec
|
||||
import org.junit.jupiter.api.Assertions
|
||||
import org.junit.jupiter.api.Test
|
||||
import kotlin.time.Duration.Companion.minutes
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
import net.minecraft.text.Text
|
||||
|
||||
@@ -1,53 +1,26 @@
|
||||
package moe.nea.firmament.test.util.skyblock
|
||||
|
||||
import io.kotest.core.spec.style.AnnotationSpec
|
||||
import org.junit.jupiter.api.Assertions
|
||||
import org.junit.jupiter.api.Test
|
||||
import io.kotest.core.spec.style.ShouldSpec
|
||||
import io.kotest.matchers.shouldBe
|
||||
import moe.nea.firmament.test.testutil.ItemResources
|
||||
import moe.nea.firmament.util.skyblock.ItemType
|
||||
|
||||
class ItemTypeTest : AnnotationSpec() {
|
||||
@Test
|
||||
fun testPetItem() {
|
||||
Assertions.assertEquals(
|
||||
ItemType.PET,
|
||||
ItemType.fromItemStack(ItemResources.loadItem("pets/lion-item"))
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testPetInUI() {
|
||||
Assertions.assertEquals(
|
||||
ItemType.PET,
|
||||
ItemType.fromItemStack(ItemResources.loadItem("pets/rabbit-selected"))
|
||||
)
|
||||
Assertions.assertEquals(
|
||||
ItemType.PET,
|
||||
ItemType.fromItemStack(ItemResources.loadItem("pets/mithril-golem-not-selected"))
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testAOTV() {
|
||||
Assertions.assertEquals(
|
||||
ItemType.SWORD,
|
||||
ItemType.fromItemStack(ItemResources.loadItem("aspect-of-the-void"))
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testDrill() {
|
||||
Assertions.assertEquals(
|
||||
ItemType.DRILL,
|
||||
ItemType.fromItemStack(ItemResources.loadItem("titanium-drill"))
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testPickaxe() {
|
||||
Assertions.assertEquals(
|
||||
ItemType.PICKAXE,
|
||||
ItemType.fromItemStack(ItemResources.loadItem("diamond-pickaxe"))
|
||||
)
|
||||
class ItemTypeTest
|
||||
: ShouldSpec(
|
||||
{
|
||||
context("ItemType.fromItemstack") {
|
||||
listOf(
|
||||
"pets/lion-item" to ItemType.PET,
|
||||
"pets/rabbit-selected" to ItemType.PET,
|
||||
"pets/mithril-golem-not-selected" to ItemType.PET,
|
||||
"aspect-of-the-void" to ItemType.SWORD,
|
||||
"titanium-drill" to ItemType.DRILL,
|
||||
"diamond-pickaxe" to ItemType.PICKAXE,
|
||||
"gemstone-gauntlet" to ItemType.GAUNTLET,
|
||||
).forEach { (name, typ) ->
|
||||
should("return $typ for $name") {
|
||||
ItemType.fromItemStack(ItemResources.loadItem(name)) shouldBe typ
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -2,7 +2,6 @@ package moe.nea.firmament.test.util.skyblock
|
||||
|
||||
import io.kotest.core.spec.style.AnnotationSpec
|
||||
import org.junit.jupiter.api.Assertions
|
||||
import org.junit.jupiter.api.Test
|
||||
import moe.nea.firmament.test.testutil.ItemResources
|
||||
import moe.nea.firmament.util.skyblock.SackUtil
|
||||
import moe.nea.firmament.util.skyblock.SkyBlockItems
|
||||
|
||||
@@ -130,11 +130,16 @@
|
||||
"firmament.config.pets": "Pets",
|
||||
"firmament.config.pets.highlight-pet": "Highlight active pet",
|
||||
"firmament.config.pets.highlight-pet.description": "Highlight your currently selected pet in the /pets menu.",
|
||||
"firmament.config.pickaxe-info": "Pickaxes",
|
||||
"firmament.config.pickaxe-info": "Pickaxes & Drills",
|
||||
"firmament.config.pickaxe-info.ability-cooldown": "Pickaxe Ability Cooldown",
|
||||
"firmament.config.pickaxe-info.ability-cooldown.description": "Show a cooldown on your cross-hair for your pickaxe ability.",
|
||||
"firmament.config.pickaxe-info.ability-scale": "Ability Cooldown Scale",
|
||||
"firmament.config.pickaxe-info.ability-scale.description": "Resize the cooldown around your cross-hair for your pickaxe ability.",
|
||||
"firmament.config.pickaxe-info.block-on-dynamic": "Block on Private Island",
|
||||
"firmament.config.pickaxe-info.block-on-dynamic.choice.always": "Always Block",
|
||||
"firmament.config.pickaxe-info.block-on-dynamic.choice.never": "Never Block",
|
||||
"firmament.config.pickaxe-info.block-on-dynamic.choice.only_destructive": "Only with dangerous",
|
||||
"firmament.config.pickaxe-info.block-on-dynamic.description": "Block pickaxe abilities on private islands by preventing you from right clicking.",
|
||||
"firmament.config.pickaxe-info.fuel-bar": "Drill Fuel Durability Bar",
|
||||
"firmament.config.pickaxe-info.fuel-bar.description": "Replace the item durability bar of your drills with one that shows the remaining fuel.",
|
||||
"firmament.config.power-user": "Power Users",
|
||||
|
||||
Reference in New Issue
Block a user