Skip to content

Commit

Permalink
Merge pull request #335 from AzureAaron/item-protection
Browse files Browse the repository at this point in the history
Item Protection
  • Loading branch information
Aaron committed Oct 4, 2023
2 parents 88e2088 + 8e19196 commit da657c4
Show file tree
Hide file tree
Showing 6 changed files with 155 additions and 2 deletions.
1 change: 1 addition & 0 deletions src/main/java/me/xmrvizzy/skyblocker/SkyblockerMod.java
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ public void onInitializeClient() {
TicTacToe.init();
QuiverWarning.init();
SpecialEffects.init();
ItemProtection.init();
containerSolverManager.init();
statusBarTracker.init();
Scheduler.INSTANCE.scheduleCyclic(Utils::update, 20);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import dev.isxander.yacl3.config.v2.api.SerialEntry;
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
import me.xmrvizzy.skyblocker.skyblock.item.CustomArmorTrims;
import me.xmrvizzy.skyblocker.utils.chat.ChatFilterResult;
import net.minecraft.client.resource.language.I18n;
Expand Down Expand Up @@ -206,6 +207,9 @@ public static class General {

@SerialEntry
public List<Integer> lockedSlots = new ArrayList<>();

@SerialEntry
public ObjectOpenHashSet<String> protectedItems = new ObjectOpenHashSet<>();

@SerialEntry
public Object2ObjectOpenHashMap<String, Text> customItemNames = new Object2ObjectOpenHashMap<>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import dev.cbyrne.betterinject.annotations.Inject;
import me.xmrvizzy.skyblocker.skyblock.HotbarSlotLock;
import me.xmrvizzy.skyblocker.skyblock.item.ItemProtection;
import me.xmrvizzy.skyblocker.skyblock.rift.HealingMelonIndicator;
import me.xmrvizzy.skyblocker.utils.Utils;
import net.minecraft.client.network.AbstractClientPlayerEntity;
Expand All @@ -21,7 +22,10 @@ public ClientPlayerEntityMixin(ClientWorld world, GameProfile profile) {

@Inject(method = "dropSelectedItem", at = @At("HEAD"), cancellable = true)
public void skyblocker$dropSelectedItem(CallbackInfoReturnable<Boolean> cir) {
if (Utils.isOnSkyblock()) HotbarSlotLock.handleDropSelectedItem(this.getInventory().selectedSlot, cir);
if (Utils.isOnSkyblock()) {
if (ItemProtection.isItemProtected(this.getInventory().getMainHandStack())) cir.setReturnValue(false);
HotbarSlotLock.handleDropSelectedItem(this.getInventory().selectedSlot, cir);
}
}

@Inject(method = "updateHealth", at = @At("RETURN"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,26 @@
import me.xmrvizzy.skyblocker.skyblock.experiment.UltrasequencerSolver;
import me.xmrvizzy.skyblocker.skyblock.item.BackpackPreview;
import me.xmrvizzy.skyblocker.skyblock.item.CompactorDeletorPreview;
import me.xmrvizzy.skyblocker.skyblock.item.ItemProtection;
import me.xmrvizzy.skyblocker.skyblock.item.WikiLookup;
import me.xmrvizzy.skyblocker.skyblock.itemlist.ItemRegistry;
import me.xmrvizzy.skyblocker.utils.Utils;
import me.xmrvizzy.skyblocker.utils.render.gui.ContainerSolver;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.screen.ingame.HandledScreen;
import net.minecraft.client.item.TooltipContext;
import net.minecraft.inventory.SimpleInventory;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.screen.GenericContainerScreenHandler;
import net.minecraft.screen.ScreenHandler;
import net.minecraft.screen.slot.Slot;
import net.minecraft.screen.slot.SlotActionType;
import net.minecraft.text.Text;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
Expand All @@ -36,10 +42,20 @@
import java.util.regex.Matcher;

@Mixin(HandledScreen.class)
public abstract class HandledScreenMixin extends Screen {
public abstract class HandledScreenMixin<T extends ScreenHandler> extends Screen {
/**
* This is the slot id returned for when a click is outside of the screen's bounds
*/
@Unique
private static final int OUT_OF_BOUNDS_SLOT = -999;

@Shadow
@Nullable
protected Slot focusedSlot;

@Shadow
@Final
protected T handler;

protected HandledScreenMixin(Text title) {
super(title);
Expand Down Expand Up @@ -120,4 +136,52 @@ protected HandledScreenMixin(Text title) {
}
}
}

/**
* The naming of this method in yarn is half true, its mostly to handle slot/item interactions (which are mouse or keyboard clicks)
* For example, using the drop key bind while hovering over an item will invoke this method to drop the players item
*/
@Inject(method = "onMouseClick(Lnet/minecraft/screen/slot/Slot;IILnet/minecraft/screen/slot/SlotActionType;)V", at = @At("HEAD"), cancellable = true)
private void skyblocker$onSlotInteract(Slot slot, int slotId, int button, SlotActionType actionType, CallbackInfo ci) {
if (Utils.isOnSkyblock()) {
// When you try and drop the item by picking it up then clicking outside of the screen
if (slotId == OUT_OF_BOUNDS_SLOT) {
ItemStack cursorStack = this.handler.getCursorStack();

if (ItemProtection.isItemProtected(cursorStack)) ci.cancel();
}

if (slot != null) {
// When you click your drop key while hovering over an item
if (actionType == SlotActionType.THROW) {
ItemStack stack = slot.getStack();

if (ItemProtection.isItemProtected(stack)) ci.cancel();
}

//Prevent salvaging
if (this.getTitle().getString().equals("Salvage Items")) {
ItemStack stack = slot.getStack();

if (ItemProtection.isItemProtected(stack)) ci.cancel();
}

//Prevent selling to NPC shops
if (this.client != null && this.handler instanceof GenericContainerScreenHandler genericContainerScreenHandler && genericContainerScreenHandler.getRows() == 6) {
ItemStack sellItem = this.handler.slots.get(49).getStack();

if (sellItem.getName().getString().equals("Sell Item") || skyblocker$doesLoreContain(sellItem, this.client, "buyback")) {
ItemStack stack = slot.getStack();

if (ItemProtection.isItemProtected(stack)) ci.cancel();
}
}
}
}
}

//TODO make this a util method somewhere else, eventually
private static boolean skyblocker$doesLoreContain(ItemStack stack, MinecraftClient client, String searchString) {
return stack.getTooltip(client.player, TooltipContext.BASIC).stream().map(Text::getString).anyMatch(line -> line.contains(searchString));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package me.xmrvizzy.skyblocker.skyblock.item;

import com.mojang.brigadier.Command;
import com.mojang.brigadier.CommandDispatcher;

import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
import me.xmrvizzy.skyblocker.config.SkyblockerConfigManager;
import me.xmrvizzy.skyblocker.utils.Utils;
import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager;
import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback;
import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
import net.minecraft.command.CommandRegistryAccess;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.text.Text;

public class ItemProtection {

public static void init() {
ClientCommandRegistrationCallback.EVENT.register(ItemProtection::registerCommand);
}

public static boolean isItemProtected(ItemStack stack) {
if (stack == null || stack.isEmpty()) return false;

NbtCompound nbt = stack.getNbt();

if (nbt != null && nbt.contains("ExtraAttributes")) {
NbtCompound extraAttributes = nbt.getCompound("ExtraAttributes");
String itemUuid = extraAttributes.contains("uuid") ? extraAttributes.getString("uuid") : "";

return SkyblockerConfigManager.get().general.protectedItems.contains(itemUuid);
}

return false;
}

private static void registerCommand(CommandDispatcher<FabricClientCommandSource> dispatcher, CommandRegistryAccess registryAccess) {
dispatcher.register(ClientCommandManager.literal("skyblocker")
.then(ClientCommandManager.literal("protectItem")
.executes(context -> protectMyItem(context.getSource()))));
}

private static int protectMyItem(FabricClientCommandSource source) {
ItemStack heldItem = source.getPlayer().getMainHandStack();
NbtCompound nbt = (heldItem != null) ? heldItem.getNbt() : null;

if (Utils.isOnSkyblock() && nbt != null && nbt.contains("ExtraAttributes")) {
NbtCompound extraAttributes = nbt.getCompound("ExtraAttributes");
String itemUuid = extraAttributes.contains("uuid") ? extraAttributes.getString("uuid") : null;

if (itemUuid != null) {
ObjectOpenHashSet<String> protectedItems = SkyblockerConfigManager.get().general.protectedItems;

if (!protectedItems.contains(itemUuid)) {
protectedItems.add(itemUuid);
SkyblockerConfigManager.save();

source.sendFeedback(Text.translatable("skyblocker.itemProtection.added", heldItem.getName()));
} else {
protectedItems.remove(itemUuid);
SkyblockerConfigManager.save();

source.sendFeedback(Text.translatable("skyblocker.itemProtection.removed", heldItem.getName()));
}
} else {
source.sendFeedback(Text.translatable("skyblocker.itemProtection.noItemUuid"));
}
} else {
source.sendFeedback(Text.translatable("skyblocker.itemProtection.unableToProtect"));
}

return Command.SINGLE_SUCCESS;
}
}
5 changes: 5 additions & 0 deletions src/main/resources/assets/skyblocker/lang/en_us.json
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,11 @@
"skyblocker.quiverWarning.50Left": "You only have 50 Arrows left in your Quiver!",
"skyblocker.quiverWarning.10Left": "You only have 10 Arrows left in your Quiver!",
"skyblocker.quiverWarning.empty": "You don't have any more Arrows left in your Quiver!",

"skyblocker.itemProtection.added": "§b[§6Skyblocker§b] §fYour %s will now be protected! §o*your item now feels a little safer :')*",
"skyblocker.itemProtection.removed": "§b[§6Skyblocker§b] §fYour %s will §nno longer be protected§f :( - §lBeware of the dangers in doing this!",
"skyblocker.itemProtection.noItemUuid": "§b[§6Skyblocker§b] §cYou must be holding an item that has a uuid in order to protect it!",
"skyblocker.itemProtection.unableToProtect": "§b[§6Skyblocker§b] §cUnable to protect this item :( (Are you in skyblock?, are you holding an item?)",

"emi.category.skyblocker.skyblock": "Skyblock"
}

0 comments on commit da657c4

Please sign in to comment.