feat: Allow dropping protected items in dungeons
This commit is contained in:
@@ -4,8 +4,11 @@ package moe.nea.firmament.mixins;
|
|||||||
|
|
||||||
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
|
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
|
||||||
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
|
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
|
||||||
import com.llamalad7.mixinextras.sugar.Local;
|
import moe.nea.firmament.events.HandledScreenClickEvent;
|
||||||
import moe.nea.firmament.events.*;
|
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.DrawContext;
|
||||||
import net.minecraft.client.gui.screen.ingame.HandledScreen;
|
import net.minecraft.client.gui.screen.ingame.HandledScreen;
|
||||||
import net.minecraft.entity.player.PlayerInventory;
|
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.Inject;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
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)
|
@Mixin(value = HandledScreen.class, priority = 990)
|
||||||
public abstract class MixinHandledScreen<T extends ScreenHandler> {
|
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) {
|
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"
|
if (slotId == -999 && getScreenHandler() != null && actionType == SlotActionType.PICKUP) { // -999 is code for "clicked outside the main window"
|
||||||
ItemStack cursorStack = getScreenHandler().getCursorStack();
|
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();
|
ci.cancel();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (IsSlotProtectedEvent.shouldBlockInteraction(slot, actionType)) {
|
if (IsSlotProtectedEvent.shouldBlockInteraction(slot, actionType, IsSlotProtectedEvent.MoveOrigin.INVENTORY_MOVE)) {
|
||||||
ci.cancel();
|
ci.cancel();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (actionType == SlotActionType.SWAP && 0 <= button && button < 9) {
|
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();
|
ci.cancel();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,15 +14,15 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
|||||||
|
|
||||||
@Mixin(ClientPlayerEntity.class)
|
@Mixin(ClientPlayerEntity.class)
|
||||||
public abstract class PlayerDropEventPatch extends PlayerEntity {
|
public abstract class PlayerDropEventPatch extends PlayerEntity {
|
||||||
public PlayerDropEventPatch() {
|
public PlayerDropEventPatch() {
|
||||||
super(null, null, 0, null);
|
super(null, null, 0, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Inject(method = "dropSelectedItem", at = @At("HEAD"), cancellable = true)
|
@Inject(method = "dropSelectedItem", at = @At("HEAD"), cancellable = true)
|
||||||
public void onDropSelectedItem(boolean entireStack, CallbackInfoReturnable<Boolean> cir) {
|
public void onDropSelectedItem(boolean entireStack, CallbackInfoReturnable<Boolean> cir) {
|
||||||
Slot fakeSlot = new Slot(getInventory(), getInventory().selectedSlot, 0, 0);
|
Slot fakeSlot = new Slot(getInventory(), getInventory().selectedSlot, 0, 0);
|
||||||
if (IsSlotProtectedEvent.shouldBlockInteraction(fakeSlot, SlotActionType.THROW)) {
|
if (IsSlotProtectedEvent.shouldBlockInteraction(fakeSlot, SlotActionType.THROW, IsSlotProtectedEvent.MoveOrigin.DROP_FROM_HOTBAR)) {
|
||||||
cir.setReturnValue(false);
|
cir.setReturnValue(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
|
|
||||||
|
|
||||||
package moe.nea.firmament.events
|
package moe.nea.firmament.events
|
||||||
|
|
||||||
import net.minecraft.item.ItemStack
|
import net.minecraft.item.ItemStack
|
||||||
@@ -10,37 +8,49 @@ import moe.nea.firmament.util.CommonSoundEffects
|
|||||||
import moe.nea.firmament.util.MC
|
import moe.nea.firmament.util.MC
|
||||||
|
|
||||||
data class IsSlotProtectedEvent(
|
data class IsSlotProtectedEvent(
|
||||||
val slot: Slot?,
|
val slot: Slot?,
|
||||||
val actionType: SlotActionType,
|
val actionType: SlotActionType,
|
||||||
var isProtected: Boolean,
|
var isProtected: Boolean,
|
||||||
val itemStackOverride: ItemStack?,
|
val itemStackOverride: ItemStack?,
|
||||||
var silent: Boolean = false,
|
val origin: MoveOrigin,
|
||||||
|
var silent: Boolean = false,
|
||||||
) : FirmamentEvent() {
|
) : FirmamentEvent() {
|
||||||
val itemStack get() = itemStackOverride ?: slot!!.stack
|
val itemStack get() = itemStackOverride ?: slot!!.stack
|
||||||
|
|
||||||
fun protect() {
|
fun protect() {
|
||||||
isProtected = true
|
isProtected = true
|
||||||
}
|
silent = false
|
||||||
|
}
|
||||||
|
|
||||||
fun protectSilent() {
|
fun protectSilent() {
|
||||||
if (!isProtected) {
|
if (!isProtected) {
|
||||||
silent = true
|
silent = true
|
||||||
}
|
}
|
||||||
isProtected = true
|
isProtected = true
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object : FirmamentEventBus<IsSlotProtectedEvent>() {
|
enum class MoveOrigin {
|
||||||
@JvmStatic
|
DROP_FROM_HOTBAR,
|
||||||
@JvmOverloads
|
SALVAGE,
|
||||||
fun shouldBlockInteraction(slot: Slot?, action: SlotActionType, itemStackOverride: ItemStack? = null): Boolean {
|
INVENTORY_MOVE
|
||||||
if (slot == null && itemStackOverride == null) return false
|
;
|
||||||
val event = IsSlotProtectedEvent(slot, action, false, itemStackOverride)
|
}
|
||||||
publish(event)
|
companion object : FirmamentEventBus<IsSlotProtectedEvent>() {
|
||||||
if (event.isProtected && !event.silent) {
|
@JvmStatic
|
||||||
MC.sendChat(Text.translatable("firmament.protectitem").append(event.itemStack.name))
|
@JvmOverloads
|
||||||
CommonSoundEffects.playFailure()
|
fun shouldBlockInteraction(
|
||||||
}
|
slot: Slot?, action: SlotActionType,
|
||||||
return event.isProtected
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,10 +45,6 @@ object FeatureManager : DataHolder<FeatureManager.Config>(serializer(), "feature
|
|||||||
|
|
||||||
private var hasAutoloaded = false
|
private var hasAutoloaded = false
|
||||||
|
|
||||||
init {
|
|
||||||
autoload()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun autoload() {
|
fun autoload() {
|
||||||
synchronized(this) {
|
synchronized(this) {
|
||||||
if (hasAutoloaded) return
|
if (hasAutoloaded) return
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import net.minecraft.screen.slot.SlotActionType
|
|||||||
import net.minecraft.util.Identifier
|
import net.minecraft.util.Identifier
|
||||||
import net.minecraft.util.StringIdentifiable
|
import net.minecraft.util.StringIdentifiable
|
||||||
import moe.nea.firmament.annotations.Subscribe
|
import moe.nea.firmament.annotations.Subscribe
|
||||||
|
import moe.nea.firmament.events.FeaturesInitializedEvent
|
||||||
import moe.nea.firmament.events.HandledScreenForegroundEvent
|
import moe.nea.firmament.events.HandledScreenForegroundEvent
|
||||||
import moe.nea.firmament.events.HandledScreenKeyPressedEvent
|
import moe.nea.firmament.events.HandledScreenKeyPressedEvent
|
||||||
import moe.nea.firmament.events.HandledScreenKeyReleasedEvent
|
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.mc.loreAccordingToNbt
|
||||||
import moe.nea.firmament.util.render.GuiRenderLayers
|
import moe.nea.firmament.util.render.GuiRenderLayers
|
||||||
import moe.nea.firmament.util.render.drawLine
|
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.skyblockUUID
|
||||||
import moe.nea.firmament.util.unformattedString
|
import moe.nea.firmament.util.unformattedString
|
||||||
|
|
||||||
@@ -60,6 +62,7 @@ object SlotLocking : FirmamentFeature {
|
|||||||
val slotBind by keyBinding("bind") { GLFW.GLFW_KEY_L }
|
val slotBind by keyBinding("bind") { GLFW.GLFW_KEY_L }
|
||||||
val slotBindRequireShift by toggle("require-quick-move") { true }
|
val slotBindRequireShift by toggle("require-quick-move") { true }
|
||||||
val slotRenderLines by choice("bind-render") { SlotRenderLinesMode.ONLY_BOXES }
|
val slotRenderLines by choice("bind-render") { SlotRenderLinesMode.ONLY_BOXES }
|
||||||
|
val allowDroppingInDungeons by toggle("drop-in-dungeons") { true }
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class SlotRenderLinesMode : StringIdentifiable {
|
enum class SlotRenderLinesMode : StringIdentifiable {
|
||||||
@@ -120,7 +123,11 @@ object SlotLocking : FirmamentFeature {
|
|||||||
var anyBlocked = false
|
var anyBlocked = false
|
||||||
for (i in 0 until event.slot.index) {
|
for (i in 0 until event.slot.index) {
|
||||||
val stack = inv.getStack(i)
|
val stack = inv.getStack(i)
|
||||||
if (IsSlotProtectedEvent.shouldBlockInteraction(null, SlotActionType.THROW, stack))
|
if (IsSlotProtectedEvent.shouldBlockInteraction(null,
|
||||||
|
SlotActionType.THROW,
|
||||||
|
IsSlotProtectedEvent.MoveOrigin.SALVAGE,
|
||||||
|
stack)
|
||||||
|
)
|
||||||
anyBlocked = true
|
anyBlocked = true
|
||||||
}
|
}
|
||||||
if (anyBlocked) {
|
if (anyBlocked) {
|
||||||
@@ -155,6 +162,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
|
@Subscribe
|
||||||
fun onQuickMoveBoundSlot(it: IsSlotProtectedEvent) {
|
fun onQuickMoveBoundSlot(it: IsSlotProtectedEvent) {
|
||||||
val boundSlots = DConfig.data?.boundSlots ?: mapOf()
|
val boundSlots = DConfig.data?.boundSlots ?: mapOf()
|
||||||
@@ -245,7 +265,7 @@ object SlotLocking : FirmamentFeature {
|
|||||||
val (hotX, hotY) = hotbarSlot.lineCenter()
|
val (hotX, hotY) = hotbarSlot.lineCenter()
|
||||||
val (invX, invY) = inventorySlot.lineCenter()
|
val (invX, invY) = inventorySlot.lineCenter()
|
||||||
val anyHovered = accScreen.focusedSlot_Firmament === hotbarSlot
|
val anyHovered = accScreen.focusedSlot_Firmament === hotbarSlot
|
||||||
|| accScreen.focusedSlot_Firmament === inventorySlot
|
|| accScreen.focusedSlot_Firmament === inventorySlot
|
||||||
if (!anyHovered && TConfig.slotRenderLines == SlotRenderLinesMode.NOTHING)
|
if (!anyHovered && TConfig.slotRenderLines == SlotRenderLinesMode.NOTHING)
|
||||||
continue
|
continue
|
||||||
val color = if (anyHovered)
|
val color = if (anyHovered)
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
|
|
||||||
|
|
||||||
package moe.nea.firmament.util
|
package moe.nea.firmament.util
|
||||||
|
|
||||||
import java.util.*
|
import java.util.Optional
|
||||||
import net.minecraft.client.gui.hud.InGameHud
|
import net.minecraft.client.gui.hud.InGameHud
|
||||||
import net.minecraft.scoreboard.ScoreboardDisplaySlot
|
import net.minecraft.scoreboard.ScoreboardDisplaySlot
|
||||||
import net.minecraft.scoreboard.Team
|
import net.minecraft.scoreboard.Team
|
||||||
@@ -10,36 +8,48 @@ import net.minecraft.text.StringVisitable
|
|||||||
import net.minecraft.text.Style
|
import net.minecraft.text.Style
|
||||||
import net.minecraft.text.Text
|
import net.minecraft.text.Text
|
||||||
import net.minecraft.util.Formatting
|
import net.minecraft.util.Formatting
|
||||||
|
import moe.nea.firmament.annotations.Subscribe
|
||||||
|
import moe.nea.firmament.events.TickEvent
|
||||||
|
|
||||||
fun getScoreboardLines(): List<Text> {
|
object ScoreboardUtil {
|
||||||
val scoreboard = MC.player?.scoreboard ?: return listOf()
|
var scoreboardLines: List<Text> = listOf()
|
||||||
val activeObjective = scoreboard.getObjectiveForSlot(ScoreboardDisplaySlot.SIDEBAR) ?: return listOf()
|
var simplifiedScoreboardLines: List<String> = listOf()
|
||||||
return scoreboard.getScoreboardEntries(activeObjective)
|
|
||||||
.filter { !it.hidden() }
|
@Subscribe
|
||||||
.sortedWith(InGameHud.SCOREBOARD_ENTRY_COMPARATOR)
|
fun onTick(event: TickEvent) {
|
||||||
.take(15).map {
|
scoreboardLines = getScoreboardLinesUncached()
|
||||||
val team = scoreboard.getScoreHolderTeam(it.owner)
|
simplifiedScoreboardLines = scoreboardLines.map { it.unformattedString }
|
||||||
val text = it.name()
|
}
|
||||||
Team.decorateName(team, text)
|
|
||||||
}
|
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 {
|
fun Text.formattedString(): String {
|
||||||
val sb = StringBuilder()
|
val sb = StringBuilder()
|
||||||
visit(StringVisitable.StyledVisitor<Unit> { style, string ->
|
visit(StringVisitable.StyledVisitor<Unit> { style, string ->
|
||||||
val c = Formatting.byName(style.color?.name)
|
val c = Formatting.byName(style.color?.name)
|
||||||
if (c != null) {
|
if (c != null) {
|
||||||
sb.append("§${c.code}")
|
sb.append("§${c.code}")
|
||||||
}
|
}
|
||||||
if (style.isUnderlined) {
|
if (style.isUnderlined) {
|
||||||
sb.append("§n")
|
sb.append("§n")
|
||||||
}
|
}
|
||||||
if (style.isBold) {
|
if (style.isBold) {
|
||||||
sb.append("§l")
|
sb.append("§l")
|
||||||
}
|
}
|
||||||
sb.append(string)
|
sb.append(string)
|
||||||
Optional.empty()
|
Optional.empty()
|
||||||
}, Style.EMPTY)
|
}, Style.EMPTY)
|
||||||
return sb.toString().replace("§[^a-f0-9]".toRegex(), "")
|
return sb.toString().replace("§[^a-f0-9]".toRegex(), "")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ private constructor(
|
|||||||
val RIFT = forMode("rift")
|
val RIFT = forMode("rift")
|
||||||
val MINESHAFT = forMode("mineshaft")
|
val MINESHAFT = forMode("mineshaft")
|
||||||
val GARDEN = forMode("garden")
|
val GARDEN = forMode("garden")
|
||||||
|
val DUNGEON = forMode("dungeon")
|
||||||
}
|
}
|
||||||
|
|
||||||
val userFriendlyName
|
val userFriendlyName
|
||||||
|
|||||||
33
src/main/kotlin/util/skyblock/DungeonUtil.kt
Normal file
33
src/main/kotlin/util/skyblock/DungeonUtil.kt
Normal file
@@ -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'*/
|
||||||
|
}
|
||||||
@@ -231,6 +231,8 @@
|
|||||||
"firmament.config.slot-locking.bind-render.choice.only_boxes": "Only boxes",
|
"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-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.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": "Lock Slot",
|
||||||
"firmament.config.slot-locking.lock-uuid": "Lock UUID (Lock Item)",
|
"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.",
|
"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.",
|
||||||
|
|||||||
Reference in New Issue
Block a user