Add UUID Locking (per unique item locking that allows movement)
This commit is contained in:
@@ -10,6 +10,7 @@ import moe.nea.firmament.events.IsSlotProtectedEvent;
|
|||||||
import net.minecraft.client.network.ClientPlayerEntity;
|
import net.minecraft.client.network.ClientPlayerEntity;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
import net.minecraft.screen.slot.Slot;
|
import net.minecraft.screen.slot.Slot;
|
||||||
|
import net.minecraft.screen.slot.SlotActionType;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
@@ -24,7 +25,7 @@ public abstract class MixinClientPlayerEntity extends PlayerEntity {
|
|||||||
@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)) {
|
if (IsSlotProtectedEvent.shouldBlockInteraction(fakeSlot, SlotActionType.THROW)) {
|
||||||
cir.setReturnValue(false);
|
cir.setReturnValue(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import moe.nea.firmament.events.*;
|
|||||||
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;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.screen.ScreenHandler;
|
import net.minecraft.screen.ScreenHandler;
|
||||||
import net.minecraft.screen.slot.Slot;
|
import net.minecraft.screen.slot.Slot;
|
||||||
import net.minecraft.screen.slot.SlotActionType;
|
import net.minecraft.screen.slot.SlotActionType;
|
||||||
@@ -63,11 +64,19 @@ public abstract class MixinHandledScreen<T extends ScreenHandler> {
|
|||||||
|
|
||||||
@Inject(method = "onMouseClick(Lnet/minecraft/screen/slot/Slot;IILnet/minecraft/screen/slot/SlotActionType;)V", at = @At("HEAD"), cancellable = true)
|
@Inject(method = "onMouseClick(Lnet/minecraft/screen/slot/Slot;IILnet/minecraft/screen/slot/SlotActionType;)V", at = @At("HEAD"), cancellable = true)
|
||||||
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 (IsSlotProtectedEvent.shouldBlockInteraction(slot)) {
|
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)) {
|
||||||
|
ci.cancel();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (IsSlotProtectedEvent.shouldBlockInteraction(slot, actionType)) {
|
||||||
ci.cancel();
|
ci.cancel();
|
||||||
|
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))) {
|
if (IsSlotProtectedEvent.shouldBlockInteraction(new Slot(playerInventory, button, 0, 0), actionType)) {
|
||||||
ci.cancel();
|
ci.cancel();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,28 +6,37 @@
|
|||||||
|
|
||||||
package moe.nea.firmament.events
|
package moe.nea.firmament.events
|
||||||
|
|
||||||
|
import net.minecraft.item.ItemStack
|
||||||
import net.minecraft.screen.slot.Slot
|
import net.minecraft.screen.slot.Slot
|
||||||
|
import net.minecraft.screen.slot.SlotActionType
|
||||||
import net.minecraft.text.Text
|
import net.minecraft.text.Text
|
||||||
import moe.nea.firmament.util.CommonSoundEffects
|
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, var isProtected: Boolean = false
|
val slot: Slot?,
|
||||||
|
val actionType: SlotActionType,
|
||||||
|
var isProtected: Boolean,
|
||||||
|
val itemStackOverride: ItemStack?,
|
||||||
) : FirmamentEvent() {
|
) : FirmamentEvent() {
|
||||||
|
val itemStack get() = itemStackOverride ?: slot!!.stack
|
||||||
|
|
||||||
|
fun protect() {
|
||||||
|
isProtected = true
|
||||||
|
}
|
||||||
|
|
||||||
companion object : FirmamentEventBus<IsSlotProtectedEvent>() {
|
companion object : FirmamentEventBus<IsSlotProtectedEvent>() {
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun shouldBlockInteraction(slot: Slot?): Boolean {
|
@JvmOverloads
|
||||||
if (slot == null) return false
|
fun shouldBlockInteraction(slot: Slot?, action: SlotActionType, itemStackOverride: ItemStack? = null): Boolean {
|
||||||
return publish(IsSlotProtectedEvent(slot)).isProtected.also {
|
if (slot == null && itemStackOverride == null) return false
|
||||||
|
val event = IsSlotProtectedEvent(slot, action, false, itemStackOverride)
|
||||||
|
return publish(event).isProtected.also {
|
||||||
if (it) {
|
if (it) {
|
||||||
MC.player?.sendMessage(Text.translatable("firmament.protectitem").append(slot.stack.name))
|
MC.player?.sendMessage(Text.translatable("firmament.protectitem").append(event.itemStack.name))
|
||||||
CommonSoundEffects.playFailure()
|
CommonSoundEffects.playFailure()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun protect() {
|
|
||||||
isProtected = true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,23 +3,30 @@
|
|||||||
*
|
*
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
*/
|
*/
|
||||||
|
@file:UseSerializers(DashlessUUIDSerializer::class)
|
||||||
|
|
||||||
package moe.nea.firmament.features.inventory
|
package moe.nea.firmament.features.inventory
|
||||||
|
|
||||||
|
import java.util.*
|
||||||
import org.lwjgl.glfw.GLFW
|
import org.lwjgl.glfw.GLFW
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.UseSerializers
|
||||||
import kotlinx.serialization.serializer
|
import kotlinx.serialization.serializer
|
||||||
import net.minecraft.entity.player.PlayerInventory
|
import net.minecraft.entity.player.PlayerInventory
|
||||||
|
import net.minecraft.screen.slot.SlotActionType
|
||||||
import moe.nea.firmament.events.HandledScreenKeyPressedEvent
|
import moe.nea.firmament.events.HandledScreenKeyPressedEvent
|
||||||
import moe.nea.firmament.events.IsSlotProtectedEvent
|
import moe.nea.firmament.events.IsSlotProtectedEvent
|
||||||
import moe.nea.firmament.events.SlotRenderEvents
|
import moe.nea.firmament.events.SlotRenderEvents
|
||||||
import moe.nea.firmament.features.FirmamentFeature
|
import moe.nea.firmament.features.FirmamentFeature
|
||||||
import moe.nea.firmament.gui.config.ManagedConfig
|
import moe.nea.firmament.gui.config.ManagedConfig
|
||||||
|
import moe.nea.firmament.keybindings.SavedKeyBinding
|
||||||
import moe.nea.firmament.mixins.accessor.AccessorHandledScreen
|
import moe.nea.firmament.mixins.accessor.AccessorHandledScreen
|
||||||
import moe.nea.firmament.util.CommonSoundEffects
|
import moe.nea.firmament.util.CommonSoundEffects
|
||||||
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.data.ProfileSpecificDataHolder
|
import moe.nea.firmament.util.data.ProfileSpecificDataHolder
|
||||||
|
import moe.nea.firmament.util.json.DashlessUUIDSerializer
|
||||||
|
import moe.nea.firmament.util.skyblockUUID
|
||||||
|
|
||||||
object SlotLocking : FirmamentFeature {
|
object SlotLocking : FirmamentFeature {
|
||||||
override val identifier: String
|
override val identifier: String
|
||||||
@@ -29,10 +36,15 @@ object SlotLocking : FirmamentFeature {
|
|||||||
data class Data(
|
data class Data(
|
||||||
val lockedSlots: MutableSet<Int> = mutableSetOf(),
|
val lockedSlots: MutableSet<Int> = mutableSetOf(),
|
||||||
val lockedSlotsRift: MutableSet<Int> = mutableSetOf(),
|
val lockedSlotsRift: MutableSet<Int> = mutableSetOf(),
|
||||||
|
|
||||||
|
val lockedUUIDs: MutableSet<UUID> = mutableSetOf(),
|
||||||
)
|
)
|
||||||
|
|
||||||
object TConfig : ManagedConfig(identifier) {
|
object TConfig : ManagedConfig(identifier) {
|
||||||
val lock by keyBinding("lock") { GLFW.GLFW_KEY_L }
|
val lockSlot by keyBinding("lock") { GLFW.GLFW_KEY_L }
|
||||||
|
val lockUUID by keyBindingWithOutDefaultModifiers("lock-uuid") {
|
||||||
|
SavedKeyBinding(GLFW.GLFW_KEY_L, shift = true)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override val config: TConfig
|
override val config: TConfig
|
||||||
@@ -40,6 +52,8 @@ object SlotLocking : FirmamentFeature {
|
|||||||
|
|
||||||
object DConfig : ProfileSpecificDataHolder<Data>(serializer(), "locked-slots", ::Data)
|
object DConfig : ProfileSpecificDataHolder<Data>(serializer(), "locked-slots", ::Data)
|
||||||
|
|
||||||
|
val lockedUUIDs get() = DConfig.data?.lockedUUIDs
|
||||||
|
|
||||||
val lockedSlots
|
val lockedSlots
|
||||||
get() = when (SBData.skyblockLocation) {
|
get() = when (SBData.skyblockLocation) {
|
||||||
"rift" -> DConfig.data?.lockedSlotsRift
|
"rift" -> DConfig.data?.lockedSlotsRift
|
||||||
@@ -49,7 +63,7 @@ object SlotLocking : FirmamentFeature {
|
|||||||
|
|
||||||
override fun onLoad() {
|
override fun onLoad() {
|
||||||
HandledScreenKeyPressedEvent.subscribe {
|
HandledScreenKeyPressedEvent.subscribe {
|
||||||
if (!it.matches(TConfig.lock)) return@subscribe
|
if (!it.matches(TConfig.lockSlot)) return@subscribe
|
||||||
val inventory = MC.handledScreen ?: return@subscribe
|
val inventory = MC.handledScreen ?: return@subscribe
|
||||||
inventory as AccessorHandledScreen
|
inventory as AccessorHandledScreen
|
||||||
|
|
||||||
@@ -65,19 +79,56 @@ object SlotLocking : FirmamentFeature {
|
|||||||
CommonSoundEffects.playSuccess()
|
CommonSoundEffects.playSuccess()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
HandledScreenKeyPressedEvent.subscribe {
|
||||||
|
if (!it.matches(TConfig.lockUUID)) return@subscribe
|
||||||
|
val inventory = MC.handledScreen ?: return@subscribe
|
||||||
|
inventory as AccessorHandledScreen
|
||||||
|
|
||||||
|
val slot = inventory.focusedSlot_Firmament ?: return@subscribe
|
||||||
|
val stack = slot.stack ?: return@subscribe
|
||||||
|
val uuid = stack.skyblockUUID ?: return@subscribe
|
||||||
|
val lockedUUIDs = lockedUUIDs ?: return@subscribe
|
||||||
|
if (uuid in lockedUUIDs) {
|
||||||
|
lockedUUIDs.remove(uuid)
|
||||||
|
} else {
|
||||||
|
lockedUUIDs.add(uuid)
|
||||||
|
}
|
||||||
|
DConfig.markDirty()
|
||||||
|
CommonSoundEffects.playSuccess()
|
||||||
|
}
|
||||||
IsSlotProtectedEvent.subscribe {
|
IsSlotProtectedEvent.subscribe {
|
||||||
if (it.slot.inventory is PlayerInventory && it.slot.index in (lockedSlots ?: setOf())) {
|
if (it.slot != null && it.slot.inventory is PlayerInventory && it.slot.index in (lockedSlots ?: setOf())) {
|
||||||
|
it.protect()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
IsSlotProtectedEvent.subscribe {
|
||||||
|
if (it.actionType == SlotActionType.SWAP
|
||||||
|
|| it.actionType == SlotActionType.PICKUP
|
||||||
|
|| it.actionType == SlotActionType.QUICK_MOVE
|
||||||
|
|| it.actionType == SlotActionType.QUICK_CRAFT
|
||||||
|
|| it.actionType == SlotActionType.CLONE
|
||||||
|
|| it.actionType == SlotActionType.PICKUP_ALL
|
||||||
|
) return@subscribe
|
||||||
|
val stack = it.itemStack ?: return@subscribe
|
||||||
|
val uuid = stack.skyblockUUID ?: return@subscribe
|
||||||
|
if (uuid in (lockedUUIDs ?: return@subscribe)) {
|
||||||
it.protect()
|
it.protect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SlotRenderEvents.Before.subscribe {
|
SlotRenderEvents.Before.subscribe {
|
||||||
if (it.slot.inventory is PlayerInventory && it.slot.index in (lockedSlots ?: setOf())) {
|
val isSlotLocked = it.slot.inventory is PlayerInventory && it.slot.index in (lockedSlots ?: setOf())
|
||||||
|
val isUUIDLocked = (it.slot.stack?.skyblockUUID ?: return@subscribe) in (lockedUUIDs ?: setOf())
|
||||||
|
if (isSlotLocked || isUUIDLocked) {
|
||||||
it.context.fill(
|
it.context.fill(
|
||||||
it.slot.x,
|
it.slot.x,
|
||||||
it.slot.y,
|
it.slot.y,
|
||||||
it.slot.x + 16,
|
it.slot.x + 16,
|
||||||
it.slot.y + 16,
|
it.slot.y + 16,
|
||||||
0xFFFF0000.toInt()
|
when {
|
||||||
|
isSlotLocked -> 0xFFFF0000.toInt()
|
||||||
|
isUUIDLocked -> 0xFF00FF00.toInt()
|
||||||
|
else -> error("Slot is locked, but not by slot or uuid")
|
||||||
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import net.minecraft.client.gui.screen.ingame.HandledScreen
|
|||||||
import net.minecraft.text.Text
|
import net.minecraft.text.Text
|
||||||
import net.minecraft.util.math.BlockPos
|
import net.minecraft.util.math.BlockPos
|
||||||
import moe.nea.firmament.events.TickEvent
|
import moe.nea.firmament.events.TickEvent
|
||||||
|
import moe.nea.firmament.mixins.accessor.AccessorHandledScreen
|
||||||
|
|
||||||
object MC {
|
object MC {
|
||||||
|
|
||||||
|
|||||||
@@ -5,11 +5,12 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
@file:UseSerializers(DashlessUUIDSerializer::class)
|
@file:UseSerializers(DashlessUUIDSerializer::class)
|
||||||
|
|
||||||
package moe.nea.firmament.util
|
package moe.nea.firmament.util
|
||||||
|
|
||||||
import io.github.moulberry.repo.data.NEUItem
|
import io.github.moulberry.repo.data.NEUItem
|
||||||
import io.github.moulberry.repo.data.Rarity
|
import io.github.moulberry.repo.data.Rarity
|
||||||
import java.util.UUID
|
import java.util.*
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import kotlinx.serialization.UseSerializers
|
import kotlinx.serialization.UseSerializers
|
||||||
import kotlinx.serialization.decodeFromString
|
import kotlinx.serialization.decodeFromString
|
||||||
@@ -73,6 +74,12 @@ private val jsonparser = Json { ignoreUnknownKeys = true }
|
|||||||
val ItemStack.extraAttributes: NbtCompound
|
val ItemStack.extraAttributes: NbtCompound
|
||||||
get() = getOrCreateSubNbt("ExtraAttributes")
|
get() = getOrCreateSubNbt("ExtraAttributes")
|
||||||
|
|
||||||
|
val ItemStack.skyblockUUIDString: String?
|
||||||
|
get() = extraAttributes.getString("uuid")?.takeIf { it.isNotBlank() }
|
||||||
|
|
||||||
|
val ItemStack.skyblockUUID: UUID?
|
||||||
|
get() = skyblockUUIDString?.let { UUID.fromString(it) }
|
||||||
|
|
||||||
val ItemStack.petData: HypixelPetInfo?
|
val ItemStack.petData: HypixelPetInfo?
|
||||||
get() {
|
get() {
|
||||||
val jsonString = extraAttributes.getString("petInfo")
|
val jsonString = extraAttributes.getString("petInfo")
|
||||||
|
|||||||
@@ -57,8 +57,6 @@
|
|||||||
"firmament.config.fishing-warning": "Fishing Warning",
|
"firmament.config.fishing-warning": "Fishing Warning",
|
||||||
"firmament.config.fishing-warning.display-warning": "Display a warning when you are about to hook a fish",
|
"firmament.config.fishing-warning.display-warning": "Display a warning when you are about to hook a fish",
|
||||||
"firmament.config.fishing-warning.highlight-wake-chain": "Highlight fishing particles",
|
"firmament.config.fishing-warning.highlight-wake-chain": "Highlight fishing particles",
|
||||||
"firmament.key.slotlocking": "Lock Slot / Slot Binding",
|
|
||||||
"firmament.key.category": "Firmament",
|
|
||||||
"firmament.protectitem": "Firmament protected your item: ",
|
"firmament.protectitem": "Firmament protected your item: ",
|
||||||
"firmament.recipe.forge.time": "Forging Time: %s",
|
"firmament.recipe.forge.time": "Forging Time: %s",
|
||||||
"firmament.pv.skills": "Skills",
|
"firmament.pv.skills": "Skills",
|
||||||
@@ -97,6 +95,7 @@
|
|||||||
"firmament.keybinding.external": "External",
|
"firmament.keybinding.external": "External",
|
||||||
"firmament.config.slot-locking": "Slot Locking",
|
"firmament.config.slot-locking": "Slot Locking",
|
||||||
"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.fixes.auto-sprint": "Auto Sprint",
|
"firmament.config.fixes.auto-sprint": "Auto Sprint",
|
||||||
"firmament.config.fixes.auto-sprint-keybinding": "Auto Sprint KeyBinding",
|
"firmament.config.fixes.auto-sprint-keybinding": "Auto Sprint KeyBinding",
|
||||||
"firmament.config.fixes.auto-sprint-hud": "Sprint State Hud",
|
"firmament.config.fixes.auto-sprint-hud": "Sprint State Hud",
|
||||||
|
|||||||
Reference in New Issue
Block a user