diff options
author | Linnea Gräf <nea@nea.moe> | 2025-01-17 18:00:43 +0100 |
---|---|---|
committer | Linnea Gräf <nea@nea.moe> | 2025-01-17 18:00:43 +0100 |
commit | 74a043e53540c120ebe58b0199f57bfa36d30e47 (patch) | |
tree | 62b3505d5cc707eb854ad611a4bec38285ec29f8 | |
parent | 19bc576b67c856b33922ee99c3e22a14f39ab55f (diff) | |
download | Firmament-74a043e53540c120ebe58b0199f57bfa36d30e47.tar.gz Firmament-74a043e53540c120ebe58b0199f57bfa36d30e47.tar.bz2 Firmament-74a043e53540c120ebe58b0199f57bfa36d30e47.zip |
feat: Allow dropping protected items in dungeons
-rw-r--r-- | src/main/java/moe/nea/firmament/mixins/MixinHandledScreen.java | 16 | ||||
-rw-r--r-- | src/main/java/moe/nea/firmament/mixins/PlayerDropEventPatch.java | 20 | ||||
-rw-r--r-- | src/main/kotlin/events/IsSlotProtectedEvent.kt | 72 | ||||
-rw-r--r-- | src/main/kotlin/features/FeatureManager.kt | 4 | ||||
-rw-r--r-- | src/main/kotlin/features/inventory/SlotLocking.kt | 24 | ||||
-rw-r--r-- | src/main/kotlin/util/ScoreboardUtil.kt | 72 | ||||
-rw-r--r-- | src/main/kotlin/util/SkyBlockIsland.kt | 1 | ||||
-rw-r--r-- | src/main/kotlin/util/skyblock/DungeonUtil.kt | 33 | ||||
-rw-r--r-- | translations/en_us.json | 2 |
9 files changed, 158 insertions, 86 deletions
diff --git a/src/main/java/moe/nea/firmament/mixins/MixinHandledScreen.java b/src/main/java/moe/nea/firmament/mixins/MixinHandledScreen.java index e607ba3..43aec40 100644 --- a/src/main/java/moe/nea/firmament/mixins/MixinHandledScreen.java +++ b/src/main/java/moe/nea/firmament/mixins/MixinHandledScreen.java @@ -4,8 +4,11 @@ package moe.nea.firmament.mixins; import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; -import com.llamalad7.mixinextras.sugar.Local; -import moe.nea.firmament.events.*; +import moe.nea.firmament.events.HandledScreenClickEvent; +import moe.nea.firmament.events.HandledScreenForegroundEvent; +import moe.nea.firmament.events.HandledScreenKeyPressedEvent; +import moe.nea.firmament.events.IsSlotProtectedEvent; +import moe.nea.firmament.events.SlotRenderEvents; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.ingame.HandledScreen; import net.minecraft.entity.player.PlayerInventory; @@ -22,9 +25,6 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; - -import java.util.Iterator; @Mixin(value = HandledScreen.class, priority = 990) public abstract class MixinHandledScreen<T extends ScreenHandler> { @@ -74,17 +74,17 @@ public abstract class MixinHandledScreen<T extends ScreenHandler> { public void onMouseClickedSlot(Slot slot, int slotId, int button, SlotActionType actionType, CallbackInfo ci) { if (slotId == -999 && getScreenHandler() != null && actionType == SlotActionType.PICKUP) { // -999 is code for "clicked outside the main window" ItemStack cursorStack = getScreenHandler().getCursorStack(); - if (cursorStack != null && IsSlotProtectedEvent.shouldBlockInteraction(slot, SlotActionType.THROW, cursorStack)) { + if (cursorStack != null && IsSlotProtectedEvent.shouldBlockInteraction(slot, SlotActionType.THROW, IsSlotProtectedEvent.MoveOrigin.INVENTORY_MOVE, cursorStack)) { ci.cancel(); return; } } - if (IsSlotProtectedEvent.shouldBlockInteraction(slot, actionType)) { + if (IsSlotProtectedEvent.shouldBlockInteraction(slot, actionType, IsSlotProtectedEvent.MoveOrigin.INVENTORY_MOVE)) { ci.cancel(); return; } if (actionType == SlotActionType.SWAP && 0 <= button && button < 9) { - if (IsSlotProtectedEvent.shouldBlockInteraction(new Slot(playerInventory, button, 0, 0), actionType)) { + if (IsSlotProtectedEvent.shouldBlockInteraction(new Slot(playerInventory, button, 0, 0), actionType, IsSlotProtectedEvent.MoveOrigin.INVENTORY_MOVE)) { ci.cancel(); } } diff --git a/src/main/java/moe/nea/firmament/mixins/PlayerDropEventPatch.java b/src/main/java/moe/nea/firmament/mixins/PlayerDropEventPatch.java index 9a4626f..b20c223 100644 --- a/src/main/java/moe/nea/firmament/mixins/PlayerDropEventPatch.java +++ b/src/main/java/moe/nea/firmament/mixins/PlayerDropEventPatch.java @@ -14,15 +14,15 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @Mixin(ClientPlayerEntity.class) public abstract class PlayerDropEventPatch extends PlayerEntity { - public PlayerDropEventPatch() { - super(null, null, 0, null); - } + public PlayerDropEventPatch() { + super(null, null, 0, null); + } - @Inject(method = "dropSelectedItem", at = @At("HEAD"), cancellable = true) - public void onDropSelectedItem(boolean entireStack, CallbackInfoReturnable<Boolean> cir) { - Slot fakeSlot = new Slot(getInventory(), getInventory().selectedSlot, 0, 0); - if (IsSlotProtectedEvent.shouldBlockInteraction(fakeSlot, SlotActionType.THROW)) { - cir.setReturnValue(false); - } - } + @Inject(method = "dropSelectedItem", at = @At("HEAD"), cancellable = true) + public void onDropSelectedItem(boolean entireStack, CallbackInfoReturnable<Boolean> cir) { + Slot fakeSlot = new Slot(getInventory(), getInventory().selectedSlot, 0, 0); + if (IsSlotProtectedEvent.shouldBlockInteraction(fakeSlot, SlotActionType.THROW, IsSlotProtectedEvent.MoveOrigin.DROP_FROM_HOTBAR)) { + cir.setReturnValue(false); + } + } } diff --git a/src/main/kotlin/events/IsSlotProtectedEvent.kt b/src/main/kotlin/events/IsSlotProtectedEvent.kt index cd2b676..eac2d9b 100644 --- a/src/main/kotlin/events/IsSlotProtectedEvent.kt +++ b/src/main/kotlin/events/IsSlotProtectedEvent.kt @@ -1,5 +1,3 @@ - - package moe.nea.firmament.events import net.minecraft.item.ItemStack @@ -10,37 +8,49 @@ import moe.nea.firmament.util.CommonSoundEffects import moe.nea.firmament.util.MC data class IsSlotProtectedEvent( - val slot: Slot?, - val actionType: SlotActionType, - var isProtected: Boolean, - val itemStackOverride: ItemStack?, - var silent: Boolean = false, + val slot: Slot?, + val actionType: SlotActionType, + var isProtected: Boolean, + val itemStackOverride: ItemStack?, + val origin: MoveOrigin, + var silent: Boolean = false, ) : FirmamentEvent() { - val itemStack get() = itemStackOverride ?: slot!!.stack + val itemStack get() = itemStackOverride ?: slot!!.stack - fun protect() { - isProtected = true - } + fun protect() { + isProtected = true + silent = false + } - fun protectSilent() { - if (!isProtected) { - silent = true - } - isProtected = true - } + fun protectSilent() { + if (!isProtected) { + silent = true + } + isProtected = true + } - companion object : FirmamentEventBus<IsSlotProtectedEvent>() { - @JvmStatic - @JvmOverloads - fun shouldBlockInteraction(slot: Slot?, action: SlotActionType, itemStackOverride: ItemStack? = null): Boolean { - if (slot == null && itemStackOverride == null) return false - val event = IsSlotProtectedEvent(slot, action, false, itemStackOverride) - publish(event) - if (event.isProtected && !event.silent) { - MC.sendChat(Text.translatable("firmament.protectitem").append(event.itemStack.name)) - CommonSoundEffects.playFailure() - } - return event.isProtected - } - } + enum class MoveOrigin { + DROP_FROM_HOTBAR, + SALVAGE, + INVENTORY_MOVE + ; + } + companion object : FirmamentEventBus<IsSlotProtectedEvent>() { + @JvmStatic + @JvmOverloads + fun shouldBlockInteraction( + slot: Slot?, action: SlotActionType, + origin: MoveOrigin, + itemStackOverride: ItemStack? = null, + ): Boolean { + if (slot == null && itemStackOverride == null) return false + val event = IsSlotProtectedEvent(slot, action, false, itemStackOverride, origin) + publish(event) + if (event.isProtected && !event.silent) { + MC.sendChat(Text.translatable("firmament.protectitem").append(event.itemStack.name)) + CommonSoundEffects.playFailure() + } + return event.isProtected + } + } } diff --git a/src/main/kotlin/features/FeatureManager.kt b/src/main/kotlin/features/FeatureManager.kt index 0f5ebf8..9a3cbf8 100644 --- a/src/main/kotlin/features/FeatureManager.kt +++ b/src/main/kotlin/features/FeatureManager.kt @@ -45,10 +45,6 @@ object FeatureManager : DataHolder<FeatureManager.Config>(serializer(), "feature private var hasAutoloaded = false - init { - autoload() - } - fun autoload() { synchronized(this) { if (hasAutoloaded) return diff --git a/src/main/kotlin/features/inventory/SlotLocking.kt b/src/main/kotlin/features/inventory/SlotLocking.kt index 99130d5..7a3a152 100644 --- a/src/main/kotlin/features/inventory/SlotLocking.kt +++ b/src/main/kotlin/features/inventory/SlotLocking.kt @@ -15,6 +15,7 @@ import net.minecraft.screen.slot.SlotActionType import net.minecraft.util.Identifier import net.minecraft.util.StringIdentifiable import moe.nea.firmament.annotations.Subscribe +import moe.nea.firmament.events.FeaturesInitializedEvent import moe.nea.firmament.events.HandledScreenForegroundEvent import moe.nea.firmament.events.HandledScreenKeyPressedEvent import moe.nea.firmament.events.HandledScreenKeyReleasedEvent @@ -37,6 +38,7 @@ import moe.nea.firmament.util.mc.displayNameAccordingToNbt import moe.nea.firmament.util.mc.loreAccordingToNbt import moe.nea.firmament.util.render.GuiRenderLayers import moe.nea.firmament.util.render.drawLine +import moe.nea.firmament.util.skyblock.DungeonUtil import moe.nea.firmament.util.skyblockUUID import moe.nea.firmament.util.unformattedString @@ -60,6 +62,7 @@ object SlotLocking : FirmamentFeature { val slotBind by keyBinding("bind") { GLFW.GLFW_KEY_L } val slotBindRequireShift by toggle("require-quick-move") { true } val slotRenderLines by choice("bind-render") { SlotRenderLinesMode.ONLY_BOXES } + val allowDroppingInDungeons by toggle("drop-in-dungeons") { true } } enum class SlotRenderLinesMode : StringIdentifiable { @@ -120,7 +123,11 @@ object SlotLocking : FirmamentFeature { var anyBlocked = false for (i in 0 until event.slot.index) { val stack = inv.getStack(i) - if (IsSlotProtectedEvent.shouldBlockInteraction(null, SlotActionType.THROW, stack)) + if (IsSlotProtectedEvent.shouldBlockInteraction(null, + SlotActionType.THROW, + IsSlotProtectedEvent.MoveOrigin.SALVAGE, + stack) + ) anyBlocked = true } if (anyBlocked) { @@ -156,6 +163,19 @@ object SlotLocking : FirmamentFeature { } @Subscribe + fun onEvent(event: FeaturesInitializedEvent) { + IsSlotProtectedEvent.subscribe(receivesCancelled = true, "SlotLocking:unlockInDungeons") { + if (it.isProtected + && it.origin == IsSlotProtectedEvent.MoveOrigin.DROP_FROM_HOTBAR + && DungeonUtil.isInActiveDungeon + && TConfig.allowDroppingInDungeons + ) { + it.isProtected = false + } + } + } + + @Subscribe fun onQuickMoveBoundSlot(it: IsSlotProtectedEvent) { val boundSlots = DConfig.data?.boundSlots ?: mapOf() val isValidAction = @@ -245,7 +265,7 @@ object SlotLocking : FirmamentFeature { val (hotX, hotY) = hotbarSlot.lineCenter() val (invX, invY) = inventorySlot.lineCenter() val anyHovered = accScreen.focusedSlot_Firmament === hotbarSlot - || accScreen.focusedSlot_Firmament === inventorySlot + || accScreen.focusedSlot_Firmament === inventorySlot if (!anyHovered && TConfig.slotRenderLines == SlotRenderLinesMode.NOTHING) continue val color = if (anyHovered) diff --git a/src/main/kotlin/util/ScoreboardUtil.kt b/src/main/kotlin/util/ScoreboardUtil.kt index 4311971..0970892 100644 --- a/src/main/kotlin/util/ScoreboardUtil.kt +++ b/src/main/kotlin/util/ScoreboardUtil.kt @@ -1,8 +1,6 @@ - - package moe.nea.firmament.util -import java.util.* +import java.util.Optional import net.minecraft.client.gui.hud.InGameHud import net.minecraft.scoreboard.ScoreboardDisplaySlot import net.minecraft.scoreboard.Team @@ -10,36 +8,48 @@ import net.minecraft.text.StringVisitable import net.minecraft.text.Style import net.minecraft.text.Text import net.minecraft.util.Formatting +import moe.nea.firmament.annotations.Subscribe +import moe.nea.firmament.events.TickEvent -fun getScoreboardLines(): List<Text> { - val scoreboard = MC.player?.scoreboard ?: return listOf() - val activeObjective = scoreboard.getObjectiveForSlot(ScoreboardDisplaySlot.SIDEBAR) ?: return listOf() - return scoreboard.getScoreboardEntries(activeObjective) - .filter { !it.hidden() } - .sortedWith(InGameHud.SCOREBOARD_ENTRY_COMPARATOR) - .take(15).map { - val team = scoreboard.getScoreHolderTeam(it.owner) - val text = it.name() - Team.decorateName(team, text) - } -} +object ScoreboardUtil { + var scoreboardLines: List<Text> = listOf() + var simplifiedScoreboardLines: List<String> = listOf() + @Subscribe + fun onTick(event: TickEvent) { + scoreboardLines = getScoreboardLinesUncached() + simplifiedScoreboardLines = scoreboardLines.map { it.unformattedString } + } + + private fun getScoreboardLinesUncached(): List<Text> { + val scoreboard = MC.player?.scoreboard ?: return listOf() + val activeObjective = scoreboard.getObjectiveForSlot(ScoreboardDisplaySlot.SIDEBAR) ?: return listOf() + return scoreboard.getScoreboardEntries(activeObjective) + .filter { !it.hidden() } + .sortedWith(InGameHud.SCOREBOARD_ENTRY_COMPARATOR) + .take(15).map { + val team = scoreboard.getScoreHolderTeam(it.owner) + val text = it.name() + Team.decorateName(team, text) + } + } +} fun Text.formattedString(): String { - val sb = StringBuilder() - visit(StringVisitable.StyledVisitor<Unit> { style, string -> - val c = Formatting.byName(style.color?.name) - if (c != null) { - sb.append("§${c.code}") - } - if (style.isUnderlined) { - sb.append("§n") - } - if (style.isBold) { - sb.append("§l") - } - sb.append(string) - Optional.empty() - }, Style.EMPTY) - return sb.toString().replace("§[^a-f0-9]".toRegex(), "") + val sb = StringBuilder() + visit(StringVisitable.StyledVisitor<Unit> { style, string -> + val c = Formatting.byName(style.color?.name) + if (c != null) { + sb.append("§${c.code}") + } + if (style.isUnderlined) { + sb.append("§n") + } + if (style.isBold) { + sb.append("§l") + } + sb.append(string) + Optional.empty() + }, Style.EMPTY) + return sb.toString().replace("§[^a-f0-9]".toRegex(), "") } diff --git a/src/main/kotlin/util/SkyBlockIsland.kt b/src/main/kotlin/util/SkyBlockIsland.kt index f15cadb..a86543c 100644 --- a/src/main/kotlin/util/SkyBlockIsland.kt +++ b/src/main/kotlin/util/SkyBlockIsland.kt @@ -36,6 +36,7 @@ private constructor( val RIFT = forMode("rift") val MINESHAFT = forMode("mineshaft") val GARDEN = forMode("garden") + val DUNGEON = forMode("dungeon") } val userFriendlyName diff --git a/src/main/kotlin/util/skyblock/DungeonUtil.kt b/src/main/kotlin/util/skyblock/DungeonUtil.kt new file mode 100644 index 0000000..488b158 --- /dev/null +++ b/src/main/kotlin/util/skyblock/DungeonUtil.kt @@ -0,0 +1,33 @@ +package moe.nea.firmament.util.skyblock + +import moe.nea.firmament.util.SBData +import moe.nea.firmament.util.ScoreboardUtil +import moe.nea.firmament.util.SkyBlockIsland +import moe.nea.firmament.util.TIME_PATTERN + +object DungeonUtil { + val isInDungeonIsland get() = SBData.skyblockLocation == SkyBlockIsland.DUNGEON + private val timeElapsedRegex = "Time Elapsed: $TIME_PATTERN".toRegex() + val isInActiveDungeon get() = isInDungeonIsland && ScoreboardUtil.simplifiedScoreboardLines.any { it.matches( + timeElapsedRegex) } + +/*Title: + +§f§lSKYBLOCK§B§L CO-OP + +' Late Spring 7th' +' §75:20am' +' §7⏣ §cThe Catacombs §7(M3)' +' §7♲ §7Ironman' +' ' +'Keys: §c■ §c✗ §8■ §a1x' +'Time Elapsed: §a46s' +'Cleared: §660% §8(105)' +' ' +'§e[B] §b151_Dragon §e2,062§c❤' +'§e[A] §6Lennart0312 §a17,165§c' +'§e[T] §b187i §a14,581§c❤' +'§e[H] §bFlameeke §a8,998§c❤' +' ' +'§ewww.hypixel.net'*/ +} diff --git a/translations/en_us.json b/translations/en_us.json index 82dcd45..520d453 100644 --- a/translations/en_us.json +++ b/translations/en_us.json @@ -231,6 +231,8 @@ "firmament.config.slot-locking.bind-render.choice.only_boxes": "Only boxes", "firmament.config.slot-locking.bind-render.description": "Disable rendering of the slot binding lines (or all of the slot binding rendering), unless the relevant slot is being hovered.", "firmament.config.slot-locking.bind.description": "Bind a hotbar slot to another slot. This allows quick switching between the slots by shift clicking on either slot.", + "firmament.config.slot-locking.drop-in-dungeons": "Allow Dungeon Abilities", + "firmament.config.slot-locking.drop-in-dungeons.description": "Allow dropping items in dungeons, to use your dungeon ultimate abilities.", "firmament.config.slot-locking.lock": "Lock Slot", "firmament.config.slot-locking.lock-uuid": "Lock UUID (Lock Item)", "firmament.config.slot-locking.lock-uuid.description": "Lock a SkyBlock item by it's UUID. This blocks a specific item from being dropped/sold, but still allows moving it around.", |