Files
NotEnoughItems/src/main/java/codechicken/nei/SubsetWidget.java
T

960 lines
32 KiB
Java

package codechicken.nei;
import java.awt.Point;
import java.io.File;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import net.minecraft.client.Minecraft;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTBase;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.nbt.NBTTagString;
import net.minecraft.util.EnumChatFormatting;
import org.lwjgl.opengl.GL11;
import com.google.gson.JsonParser;
import codechicken.core.gui.GuiScrollSlot;
import codechicken.lib.gui.GuiDraw;
import codechicken.lib.vec.Rectangle4i;
import codechicken.nei.ItemList.AnyMultiItemFilter;
import codechicken.nei.ItemList.NothingItemFilter;
import codechicken.nei.SearchTokenParser.ISearchParserProvider;
import codechicken.nei.SearchTokenParser.SearchMode;
import codechicken.nei.api.API;
import codechicken.nei.api.ItemFilter;
import codechicken.nei.api.ItemFilter.ItemFilterProvider;
import codechicken.nei.guihook.GuiContainerManager;
import codechicken.nei.recipe.GuiCraftingRecipe;
import codechicken.nei.recipe.GuiRecipeTab;
import codechicken.nei.recipe.ICraftingHandler;
import codechicken.nei.recipe.IRecipeHandler;
import codechicken.nei.recipe.StackInfo;
import codechicken.nei.util.NBTJson;
import codechicken.nei.util.NEIMouseUtils;
public class SubsetWidget extends Button implements ItemFilterProvider {
protected static final int SLOT_HEIGHT = 18;
protected static final int MARGIN = 2;
protected static final char PREFIX = '%';
private static final Object hiddenLock = new Object();
public static class SubsetTag {
protected class SubsetSlot extends GuiScrollSlot {
public SubsetSlot() {
super(0, 0, 0, 0);
setSmoothScroll(false);
}
@Override
public int getSlotHeight(int slot) {
return SubsetWidget.SLOT_HEIGHT;
}
@Override
protected int getNumSlots() {
return children.size() + items.size();
}
@Override
protected void slotClicked(int slot, int button, int mx, int my, int count) {
if (slot < children.size()) {
SubsetTag tag = children.get(slot);
if (SubsetWidget.enableSearchBySubsets && NEIClientUtils.shiftKey()) {
LayoutManager.searchField
.setText(SearchField.searchParser.getRedefinedPrefix(SubsetWidget.PREFIX) + tag.path);
} else if (button == 0 && count >= 2) {
SubsetWidget.showOnly(tag);
} else if (button == 0 || button == 1) {
SubsetWidget.setHidden(tag, button == 1);
}
} else {
ItemStack item = items.get(slot - children.size());
if (NEIClientUtils.controlKey() && NEIClientConfig.canCheatItem(item)) {
NEIClientUtils.cheatItem(item, button, -1);
} else if (SubsetWidget.enableSearchBySubsets && NEIClientUtils.shiftKey()) {
LayoutManager.searchField.setText(SearchField.getEscapedSearchText(item));
} else if (button == 0 || button == 1) {
SubsetWidget.setHidden(item, button == 1);
}
}
}
@Override
protected void drawSlot(int slot, int x, int y, int mx, int my, float frame) {
int w = windowBounds().width;
Rectangle4i r = new Rectangle4i(0, 0, w, getSlotHeight(slot));
if (slot < children.size()) {
SubsetTag tag = children.get(slot);
LayoutManager.getLayoutStyle()
.drawSubsetTag(tag.displayName(), x, y, r.w, r.h, tag.state, r.contains(mx, my));
if (r.contains(mx, my)) {
SubsetWidget.hoverTag = tag;
}
} else {
ItemStack stack = items.get(slot - children.size());
boolean hidden = SubsetWidget.isHidden(stack);
LayoutManager.getLayoutStyle()
.drawSubsetTag(null, x, y, r.w, r.h, hidden ? 0 : 2, r.contains(mx, my));
GuiContainerManager.drawItem(x + (w / 2 - 8), y + 1, stack);
if (r.contains(mx, my)) {
SubsetWidget.hoverStack = stack;
}
}
}
@Override
public void drawOverlay(float frame) { /** disabled draw overlay */
}
@Override
public void drawBackground(float frame) {
drawRect(x, y, x + width, y + height, 0xFF202020);
}
@Override
public int scrollbarAlignment() {
return marginleft == 0 ? 1 : -1;
}
@Override
public void drawScrollbar(float frame) {
if (hasScrollbar()) super.drawScrollbar(frame);
}
@Override
public int scrollbarGuideAlignment() {
return 0;
}
}
public final String fullname;
public final String path;
public final String parentPath;
public final ItemFilter filter;
// 0 - full hidden
// 1 - partitial hidden
// 2 - enabled
public int state = 2;
public volatile int calculatedWidth = -1;
public final List<ItemStack> items;
public final List<SubsetTag> children = new ArrayList<>();
protected final SubsetSlot slot = new SubsetSlot();
private SubsetTag selectedChild;
private int visible;
public SubsetTag(String fullname) {
this(fullname, null);
}
public SubsetTag(String fullname, ItemFilter filter) {
this.fullname = EnumChatFormatting.getTextWithoutFormattingCodes(fullname);
this.filter = filter == null ? new NothingItemFilter() : filter;
this.items = new ArrayList<>();
if (this.fullname != null) {
this.path = this.fullname.replaceAll("\\s+", "").toLowerCase();
int idx = this.path.lastIndexOf('.');
this.parentPath = idx < 0 ? null : this.path.substring(0, idx);
} else {
this.parentPath = this.path = null;
}
}
public String displayName() {
final String translated = NEIClientUtils.translate("subsets." + this.fullname);
return translated.startsWith("nei.") ? name() : translated;
}
public String name() {
int idx = this.fullname.lastIndexOf('.');
return idx < 0 ? this.fullname : this.fullname.substring(idx + 1);
}
public String parent() {
int idx = this.fullname.lastIndexOf('.');
return idx < 0 ? null : this.fullname.substring(0, idx);
}
public void clearCache() {
this.state = 2;
this.items.clear();
this.children.clear();
this.calculatedWidth = -1;
}
public void updateVisiblity(int mx, int my) {
if (selectedChild != null) {
selectedChild.updateVisiblity(mx, my);
if (!selectedChild.isVisible()) {
selectedChild = null;
}
}
if (slot.contains(mx, my) && (selectedChild == null || !selectedChild.contains(mx, my))) {
int mslot = slot.getClickedSlot(my);
if (mslot >= 0 && mslot < children.size()) {
SubsetTag mtag = children.get(mslot);
if (mtag != null) {
if (mtag != selectedChild && selectedChild != null) {
selectedChild.setHidden();
}
selectedChild = mtag;
selectedChild.setVisible();
}
}
setVisible();
}
if (this.selectedChild == null) {
countdownVisible();
}
}
public void setHidden() {
this.visible = 0;
slot.mouseMovedOrUp(0, 0, 0); // cancel any scrolling
if (this.selectedChild != null) {
this.selectedChild.setHidden();
this.selectedChild = null;
}
}
public void setVisible() {
this.visible = 10;
}
private void countdownVisible() {
if (this.visible > 0 && --this.visible == 0) {
setHidden();
}
}
public void resize(Rectangle4i screen, Rectangle4i parent, boolean dropRight) {
if (calculatedWidth < 0) {
calculatedWidth = this.children.stream().mapToInt(SubsetTag::nameWidth).max().orElse(0);
}
int height = Math.min(slot.contentHeight(), screen.h);
int width = Math.max(calculatedWidth + 2, this.items.isEmpty() ? 0 : 16 + MARGIN * 2);
int scrollbarWidth = slot.scrollbarDim().width;
if (slot.contentHeight() > height) {
width += scrollbarWidth;
}
int slotY = parent.y1() + Math.min(0, alignValueToStep(screen.y2() - parent.y1() - height));
int slotX = dropRight ? parent.x2() : parent.x1() - width;
if (slotX + width >= screen.x2()) {
slotX = parent.x1() - width;
dropRight = false;
} else if (slotX <= screen.x1()) {
slotX = parent.x2();
dropRight = true;
}
slot.setSize(slotX, slotY, width, height);
if (dropRight) {
slot.setMargins(0, 0, slot.hasScrollbar() ? scrollbarWidth : 0, 0);
} else {
slot.setMargins(slot.hasScrollbar() ? scrollbarWidth : 0, 0, 0, 0);
}
if (selectedChild != null) {
selectedChild.resize(
screen,
new Rectangle4i(
slot.x,
slot.y + slot.getSlotY(this.children.indexOf(selectedChild)) - slot.scrolledPixels(),
width,
SLOT_HEIGHT),
dropRight);
}
}
protected int nameWidth() {
return Minecraft.getMinecraft().fontRenderer.getStringWidth(displayName()) + 4;
}
public boolean isVisible() {
return this.visible > 0;
}
public void draw(int mx, int my) {
slot.draw(mx, my, 0);
if (selectedChild != null) selectedChild.draw(mx, my);
}
public boolean contains(int px, int py) {
return slot.contains(px, py) || selectedChild != null && selectedChild.contains(px, py);
}
public void mouseClicked(int mx, int my, int button) {
if (selectedChild != null && selectedChild.contains(mx, my)) {
selectedChild.mouseClicked(mx, my, button);
} else if (slot.contains(mx, my)) {
slot.mouseClicked(mx, my, button);
}
}
public void mouseDragged(int mx, int my, int button, long heldTime) {
slot.mouseDragged(mx, my, button, heldTime);
if (selectedChild != null) {
selectedChild.mouseDragged(mx, my, button, heldTime);
}
}
public void mouseUp(int mx, int my, int button) {
slot.mouseMovedOrUp(mx, my, button);
if (selectedChild != null) {
selectedChild.mouseUp(mx, my, button);
}
}
public boolean mouseScrolled(int mx, int my, int scroll) {
if (slot.hasScrollbar() && slot.contains(mx, my)) {
slot.scroll(scroll);
return true;
}
if (selectedChild != null && selectedChild.mouseScrolled(mx, my, scroll)) return true;
if (slot.hasScrollbar() && !contains(mx, my)) {
slot.scroll(scroll);
return true;
}
return false;
}
public boolean isScrolling() {
return slot.isScrolling() || selectedChild != null && selectedChild.isScrolling();
}
}
private static class DefaultParserProvider implements ISearchParserProvider {
public ItemFilter getFilter(String searchText) {
final int patternMode = NEIClientConfig.getIntSetting("inventory.search.patternMode");
Pattern pattern = null;
if (patternMode != 3) {
searchText = searchText.replaceAll("\\s+", "").toLowerCase();
} else {
pattern = SearchField.getPattern(searchText, patternMode);
}
final AnyMultiItemFilter filter = new AnyMultiItemFilter();
final Set<ItemStack> filteredItems = new HashSet<>();
final List<SubsetTag> snapshot;
synchronized (tags) {
snapshot = new ArrayList<>(tags.values());
}
for (SubsetTag tag : snapshot) {
if (tag.filter != null && matches(tag.path, searchText, pattern)) {
synchronized (tag.items) {
filteredItems.addAll(tag.items);
filter.filters.add(tag.filter);
}
}
}
return stack -> filteredItems.contains(stack) || !ItemList.items.contains(stack) && filter.matches(stack);
}
public char getPrefix() {
return SubsetWidget.PREFIX;
}
public EnumChatFormatting getHighlightedColor() {
return EnumChatFormatting.DARK_PURPLE;
}
@Override
public String getName() {
return "subsets";
}
private boolean matches(String name, String searchText, Pattern pattern) {
if (pattern != null) {
return pattern.matcher(name).find();
} else {
return name.contains(searchText);
}
}
}
/**
* Canonical {@link StackInfo#getItemStackGUID(ItemStack)} of every hidden item, stored by GUID so the state
* survives world reloads. All operations should be synchronised.
*/
private static final Set<String> hiddenItems = new HashSet<>();
private static final Map<String, SubsetTag> tags = new HashMap<>();
private static final SubsetTag root = new SubsetTag("");
protected static boolean enableSearchBySubsets = false;
protected static ItemStack hoverStack;
protected static SubsetTag hoverTag;
private long lastclicktime;
public static void addTag(SubsetTag tag) {
updateState.stop();
synchronized (tags) {
tags.put(tag.path, tag);
String parentname = tag.parent();
while (parentname != null && !tags.containsKey(parentname.replaceAll("\\s+", "").toLowerCase())) {
SubsetTag parent = new SubsetTag(parentname);
tags.put(parent.path, parent);
parentname = parent.parent();
}
updateHiddenItems();
SearchField.searchParser.clearCache();
}
}
public static void removeTag(String path) {
updateState.stop();
synchronized (tags) {
tags.keySet().removeIf(
parentpath -> parentpath.equals(path.toLowerCase())
|| parentpath.startsWith(path.toLowerCase() + "."));
updateHiddenItems();
SearchField.searchParser.clearCache();
}
}
public static boolean isHidden(ItemStack item) {
final String guid = StackInfo.getItemStackGUID(item);
synchronized (hiddenLock) {
return hiddenItems.contains(guid);
}
}
private static List<String> toGUIDs(List<ItemStack> items) {
return items.stream().map(StackInfo::getItemStackGUID).collect(Collectors.toList());
}
private static List<ItemStack> getItems(SubsetTag tag, List<ItemStack> items) {
items.addAll(tag.items);
for (SubsetTag child : tag.children) {
getItems(child, items);
}
return items;
}
public static void showOnly(SubsetTag tag) {
final List<String> allItems = toGUIDs(getItems(root, new ArrayList<>()));
final List<String> tagItems = toGUIDs(getItems(tag, new ArrayList<>()));
synchronized (hiddenLock) {
hiddenItems.clear();
hiddenItems.addAll(allItems);
hiddenItems.removeAll(tagItems);
}
calculateVisibility();
}
public static void setHidden(SubsetTag tag, boolean hidden) {
final List<String> tagItems = toGUIDs(getItems(tag, new ArrayList<>()));
synchronized (hiddenLock) {
if (hidden) {
hiddenItems.addAll(tagItems);
} else {
hiddenItems.removeAll(tagItems);
}
}
calculateVisibility();
}
public static void setHidden(ItemStack item, boolean hidden) {
final String guid = StackInfo.getItemStackGUID(item);
synchronized (hiddenLock) {
if (hidden) {
hiddenItems.add(guid);
} else {
hiddenItems.remove(guid);
}
}
calculateVisibility();
}
public static void unhideAll() {
synchronized (hiddenLock) {
hiddenItems.clear();
}
calculateVisibility();
}
public static void updateHiddenItems() {
if (ItemList.loadFinished) {
updateState.restart();
}
}
public static void loadCustomSubsets() {
File dir = new File(NEIClientConfig.configDir, "subsets");
if (!dir.exists() || !dir.isDirectory()) {
return;
}
Stream.of(dir.listFiles()).filter(file -> !file.isDirectory()).forEach(file -> {
ClientHandler.loadSettingsFile(
"subsets/" + file.getName(),
lines -> parseFile(file.getName(), lines.collect(Collectors.toList())));
});
}
private static void parseFile(String resource, List<String> itemStrings) {
final JsonParser parser = new JsonParser();
final int dotIndex = resource.lastIndexOf('.');
final String subsetNamespace = dotIndex > 0 ? resource.substring(0, dotIndex) : resource;
SubsetTag processedTag = new SubsetTag(subsetNamespace, new ItemStackSet());
for (String itemStr : itemStrings) {
try {
if (itemStr.startsWith("; ")) {
addTag(processedTag);
final String handlerName = itemStr.substring(2);
final IRecipeHandler recipeHandler = Stream
.concat(
GuiCraftingRecipe.craftinghandlers.stream(),
GuiCraftingRecipe.serialCraftingHandlers.stream())
.filter(handler -> handlerName.equals(getHandlerName(handler))).findFirst().orElse(null);
String recipeName = handlerName;
if (recipeHandler != null) {
recipeName = recipeHandler.getRecipeName().trim();
}
processedTag = new SubsetTag(
subsetNamespace + "." + recipeName.replace(".", ""),
new ItemStackSet());
} else {
final NBTBase nbt = NBTJson.toNbt(parser.parse(itemStr));
if (nbt instanceof NBTTagCompound tag) {
((ItemStackSet) processedTag.filter).add(StackInfo.loadFromNBT(tag));
} else {
throw new IllegalArgumentException(
"Expected NBTTagCompound but got " + nbt.getClass().getSimpleName());
}
}
} catch (Exception e) {
NEIClientConfig.logger.error("Failed to load custom subset items from json string:\n{}", itemStr);
}
}
addTag(processedTag);
}
private static String getHandlerName(ICraftingHandler handler) {
return GuiRecipeTab.getHandlerInfo(handler).getHandlerName();
}
public static void loadHidden() {
final Set<String> guids = new HashSet<>();
try {
final NBTTagList guidList = NEIClientConfig.world.nbt.getTagList("hiddenItems", 8);
for (int i = 0; i < guidList.tagCount(); i++) {
guids.add(guidList.getStringTagAt(i));
}
final NBTTagList list = NEIClientConfig.world.nbt.getTagList("hiddenItems", 10);
for (int i = 0; i < list.tagCount(); i++) {
final ItemStack stack = ItemStack.loadItemStackFromNBT(list.getCompoundTagAt(i));
if (stack != null) {
guids.add(StackInfo.getItemStackGUID(stack));
}
}
} catch (Exception e) {
NEIClientConfig.logger.error("Error loading hiddenItems", e);
return;
}
synchronized (hiddenLock) {
hiddenItems.clear();
hiddenItems.addAll(guids);
}
}
public static void saveHidden() {
if (NEIClientConfig.world == null) return;
final NBTTagList list = new NBTTagList();
synchronized (hiddenLock) {
for (String guid : hiddenItems) {
list.appendTag(new NBTTagString(guid));
}
}
NEIClientConfig.world.nbt.setTag("hiddenItems", list);
}
private static final UpdateStateTask updateState = new UpdateStateTask();
private static class UpdateStateTask extends RestartableTask {
public UpdateStateTask() {
super("NEI Subset Item Allocation");
}
@Override
public void execute() {
try {
final List<SubsetTag> list;
synchronized (tags) {
list = new ArrayList<>(tags.values());
}
root.clearCache();
list.parallelStream().forEach(tag -> {
tag.clearCache();
if (!(tag.filter instanceof NothingItemFilter)) {
ItemList.items.stream().filter(tag.filter::matches)
.collect(Collectors.toCollection(() -> tag.items));
}
});
for (SubsetTag tag : list) {
if (tag.parentPath == null) {
root.children.add(tag);
} else {
tags.get(tag.parentPath).children.add(tag);
}
}
boolean changed = false;
do {
changed = false;
for (SubsetTag tag : list) {
changed = tag.children.removeIf(child -> child.children.isEmpty() && child.items.isEmpty())
|| changed;
}
} while (changed);
for (SubsetTag tag : list) {
tag.children.sort(Comparator.comparing(SubsetTag::displayName));
tag.calculatedWidth = -1;
}
root.children.removeIf(child -> child.children.isEmpty() && child.items.isEmpty());
root.children.sort(Comparator.comparing(SubsetTag::displayName));
root.calculatedWidth = -1;
calculateVisibility(root);
} catch (Throwable e) {
e.printStackTrace();
}
SearchField.searchParser.clearCache();
}
}
public SubsetWidget() {
super("NEI Subsets");
API.addItemFilter(this);
API.addSearchProvider(new DefaultParserProvider());
this.z = 1;
}
@Override
public int getRenderLabelColor() {
return NEIClientConfig.subsetWidgetOnTop() ? 0 : ColorUtils.subsetWidget.getColor();
}
@Override
public String getRenderLabel() {
if (NEIClientConfig.subsetWidgetOnTop()) {
return NEIClientUtils.translate("inventory.item_subsets");
} else {
return String.valueOf(SearchField.searchParser.getRedefinedPrefix(PREFIX));
}
}
@Override
public void draw(int mx, int my) {
super.draw(mx, my);
SubsetWidget.hoverTag = null;
SubsetWidget.hoverStack = null;
if (root.isVisible()) {
final Minecraft mc = NEIClientUtils.mc();
final Rectangle4i screen = new Rectangle4i(
MARGIN,
MARGIN,
mc.currentScreen.width - MARGIN * 2,
mc.currentScreen.height - MARGIN * 2);
final Rectangle4i parent = new Rectangle4i();
final boolean dropRight = this.x < (screen.x + screen.w / 2);
final boolean dropDown = this.y < (screen.y + screen.h / 2);
if (dropRight) {
parent.x = this.x;
} else {
parent.x = this.x + this.w;
}
if (dropDown) {
screen.y = parent.y = this.y + this.h;
screen.h = alignValueToStep(mc.currentScreen.height - MARGIN - screen.y);
} else {
screen.h = alignValueToStep(this.y - screen.y);
screen.y = this.y - screen.h;
parent.y = this.y;
}
root.resize(screen, parent, dropRight);
GL11.glPushAttrib(GL11.GL_ENABLE_BIT | GL11.GL_COLOR_BUFFER_BIT | GL11.GL_LIGHTING_BIT);
GuiContainerManager.enable2DRender();
GuiContainerManager.drawItems.zLevel += 100;
root.draw(mx, my);
GuiContainerManager.drawItems.zLevel -= 100;
GL11.glPopAttrib();
}
}
private static int alignValueToStep(int height) {
return (height / SLOT_HEIGHT) * SLOT_HEIGHT;
}
protected static void calculateVisibility() {
calculateVisibility(root);
ItemList.updateFilter.restart();
}
protected static void calculateVisibility(SubsetTag tag) {
// 0 - full hidden
// 1 - partitial hidden
// 2 - enabled
int hidden = 0;
tag.state = 2;
for (SubsetTag child : tag.children) {
calculateVisibility(child);
if (child.state == 1) {
tag.state = 1;
} else if (child.state == 0) {
hidden++;
}
}
if (tag.state == 1) return;
for (ItemStack item : tag.items) {
if (isHidden(item)) {
hidden++;
} else if (hidden > 0) {
break;
}
}
if (hidden == tag.children.size() + tag.items.size()) {
tag.state = 0;
} else if (hidden > 0) {
tag.state = 1;
}
}
@Override
public void update() {
SubsetWidget.enableSearchBySubsets = SearchMode
.fromInt(NEIClientConfig.getIntSetting("inventory.search.subsetsSearchMode")) == SearchMode.PREFIX;
Point mouse = GuiDraw.getMousePosition();
updateVisiblity(mouse.x, mouse.y);
}
private void updateVisiblity(int mx, int my) {
if (!root.isVisible() || root.isScrolling()) return;
root.updateVisiblity(mx, my);
if (!root.isVisible() && bounds().contains(mx, my)) {
root.setVisible();
}
}
@Override
public boolean contains(int px, int py) {
return super.contains(px, py) || root.isVisible() && root.contains(px, py);
}
@Override
public boolean handleClick(int mx, int my, int button) {
if (root.isVisible() && root.contains(mx, my)) {
root.mouseClicked(mx, my, button);
return true;
}
if (button == 0) {
if (System.currentTimeMillis() - lastclicktime < 500) {
unhideAll();
} else {
root.setVisible();
}
NEIClientUtils.playClickSound();
lastclicktime = System.currentTimeMillis();
}
return true;
}
/**
* Not called
*/
@Override
public boolean onButtonPress(boolean rightclick) {
return false;
}
@Override
public void mouseDragged(int mx, int my, int button, long heldTime) {
if (root.isVisible()) {
root.mouseDragged(mx, my, button, heldTime);
}
}
@Override
public void mouseUp(int mx, int my, int button) {
if (root.isVisible()) root.mouseUp(mx, my, button);
}
@Override
public boolean onMouseWheel(int i, int mx, int my) {
return root.isVisible() && root.mouseScrolled(mx, my, -i) || contains(mx, my);
}
@Override
public void onGuiClick(int mx, int my) {
if (!contains(mx, my)) {
root.setHidden();
}
}
@Override
public ItemStack getStackMouseOver(int mx, int my) {
return SubsetWidget.hoverStack;
}
@Override
public ItemFilter getFilter() {
return item -> !isHidden(item);
}
@Override
public void addTooltips(List<String> tooltip) {
if (SubsetWidget.hoverStack == null && SubsetWidget.hoverTag != null) {
tooltip.add(SubsetWidget.hoverTag.displayName() + GuiDraw.TOOLTIP_LINESPACE);
}
}
@Override
public Map<String, String> handleHotkeys(int mousex, int mousey, Map<String, String> hotkeys) {
if (SubsetWidget.hoverStack != null) {
if (NEIClientConfig.canCheatItem(SubsetWidget.hoverStack)) {
hotkeys.put(
NEIClientUtils.getKeyName(NEIClientUtils.CTRL_HASH, NEIMouseUtils.MOUSE_BTN_LMB),
NEIClientUtils.translate("subsets.item.cheat"));
}
if (SubsetWidget.enableSearchBySubsets) {
hotkeys.put(
NEIClientUtils.getKeyName(NEIClientUtils.SHIFT_HASH, NEIMouseUtils.MOUSE_BTN_LMB),
NEIClientUtils.translate("subsets.item.search"));
}
hotkeys.put(
NEIMouseUtils.getKeyName(NEIMouseUtils.MOUSE_BTN_LMB),
NEIClientUtils.translate("subsets.item.show"));
hotkeys.put(
NEIMouseUtils.getKeyName(NEIMouseUtils.MOUSE_BTN_RMB),
NEIClientUtils.translate("subsets.item.hide"));
} else if (SubsetWidget.hoverTag != null) {
hotkeys.put(
NEIClientUtils.translate("subsets.tag.onlythis.key"),
NEIClientUtils.translate("subsets.tag.onlythis"));
if (SubsetWidget.enableSearchBySubsets) {
hotkeys.put(
NEIClientUtils.getKeyName(NEIClientUtils.SHIFT_HASH, NEIMouseUtils.MOUSE_BTN_LMB),
NEIClientUtils.translate("subsets.tag.search"));
}
hotkeys.put(
NEIMouseUtils.getKeyName(NEIMouseUtils.MOUSE_BTN_LMB),
NEIClientUtils.translate("subsets.tag.show"));
hotkeys.put(
NEIMouseUtils.getKeyName(NEIMouseUtils.MOUSE_BTN_RMB),
NEIClientUtils.translate("subsets.tag.hide"));
}
return hotkeys;
}
}