Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import net.fabricmc.fabric.api.client.screen.v1.ScreenEvents;
import net.minecraft.client.gui.screen.ingame.GenericContainerScreen;
import net.minecraft.component.DataComponentTypes;
import net.minecraft.component.type.LoreComponent;
import net.minecraft.inventory.Inventory;
import net.minecraft.item.ItemStack;
import net.minecraft.screen.GenericContainerScreenHandler;
Expand Down Expand Up @@ -143,11 +144,24 @@ private static boolean isItemLoading(Inventory inventory) {
if (item.isEmpty()) continue;

Text customName = item.get(DataComponentTypes.CUSTOM_NAME);
if (customName != null) {
String displayName = Util.removeFormatting(customName.getString());
if (displayName.contains("Loading")) {
PlayerActionUtil.notifyAll("Loading item...", NotificationType.GUI);
return true;
if (customName == null) continue;

String name = Util.removeFormatting(customName.getString());

if (name.contains("Loading")) {
return true;
}

// Only bottleneck on lore data of items known to have partialized lore
if (name.contains("Sell")) {
LoreComponent lore = item.get(DataComponentTypes.LORE);

if (lore != null && !lore.lines().isEmpty()) {
for (Text line : lore.lines()) {
if (Util.removeFormatting(line.getString()).contains("Loading")) {
return true;
}
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,113 +1,122 @@
package com.github.mkram17.bazaarutils.features.gui.inventory;

import com.github.mkram17.bazaarutils.BazaarUtils;
import com.github.mkram17.bazaarutils.config.features.gui.InventoryConfig;
import com.github.mkram17.bazaarutils.events.ChestLoadedEvent;
import com.github.mkram17.bazaarutils.events.listener.BUListener;
import com.github.mkram17.bazaarutils.generated.BazaarUtilsModules;
import com.github.mkram17.bazaarutils.misc.SlotHighlightCache;
import com.github.mkram17.bazaarutils.utils.Util;
import com.github.mkram17.bazaarutils.utils.bazaar.gui.BazaarScreenHandler;
import com.github.mkram17.bazaarutils.utils.bazaar.gui.BazaarScreens;
import com.github.mkram17.bazaarutils.utils.annotations.modules.Module;
import com.github.mkram17.bazaarutils.utils.bazaar.components.InstantSellParser;
import com.github.mkram17.bazaarutils.utils.bazaar.market.order.OrderInfo;
import com.github.mkram17.bazaarutils.utils.config.BUToggleableFeature;
import com.github.mkram17.bazaarutils.utils.minecraft.ItemInfo;
import com.github.mkram17.bazaarutils.utils.minecraft.SlotHighlight;
import com.github.mkram17.bazaarutils.utils.minecraft.gui.ScreenContext;
import com.github.mkram17.bazaarutils.utils.minecraft.gui.ScreenManager;
import com.github.mkram17.bazaarutils.utils.Util;
import com.github.mkram17.bazaarutils.utils.InstaSellUtil;
import meteordevelopment.orbit.EventHandler;
import net.fabricmc.fabric.api.client.screen.v1.ScreenEvents;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.network.ClientPlayerEntity;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.screen.ingame.HandledScreen;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.screen.slot.Slot;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

@Module
public class InstantSellHighlight extends BUListener implements BUToggleableFeature {
private static final List<Integer> highlightedSlotIndexes = new ArrayList<>();
public class InstantSellHighlight extends BUListener implements BUToggleableFeature, SlotHighlight {
public static final Identifier IDENTIFIER = Identifier.tryParse(BazaarUtils.MOD_ID, "highlights/standard_background");

@Override
public boolean isEnabled() {
return InventoryConfig.INSTANT_SELL_HIGHLIGHT_TOGGLE;
public Identifier getIdentifier() {
return IDENTIFIER;
}

public InstantSellHighlight() {}
private static final Map<Integer, Integer> colorCache = new ConcurrentHashMap<>();

@EventHandler
private void onScreenLoad(ChestLoadedEvent e) {
highlightedSlotIndexes.clear();
private void populateCache(Set<String> names, HandledScreen<?> screen, PlayerInventory playerInventory) {
colorCache.clear();

if (!isEnabled() || !ScreenManager.getInstance().isCurrent(BazaarScreens.MAIN_PAGE)) {
return;
}
for (Slot slot : screen.getScreenHandler().slots) {
if (!slot.hasStack() || slot.inventory != playerInventory) continue;

Text customName = slot.getStack().getCustomName();

if (customName == null) continue;

Optional<PlayerInventory> optionalInventory = getInventory();
if (optionalInventory.isEmpty()) {
Util.notifyError("Failed to get player inventory.", new Throwable());
return;
String itemName = customName.getString();

if (names.stream().anyMatch(itemName::equalsIgnoreCase)) {
colorCache.put(slot.getIndex(), InventoryConfig.INSTANT_SELL_HIGHLIGHT_COLOR);
}
}
PlayerInventory inventory = optionalInventory.get();

List<OrderInfo> instaSellOrders = InstaSellUtil.getInstaSellOrders(e.getItemStacks());
List<String> names = instaSellOrders.stream()
.map(OrderInfo::getName)
.distinct()
.toList();

List<ItemStack> inventoryStacks = getInventoryStacks(names);

highlightedSlotIndexes.addAll(
inventoryStacks.stream()
.filter(itemStack -> !itemStack.isEmpty())
.map(ScreenManager::getInventorySlotFromItemStack)
.flatMap(Optional::stream)
.toList()
);
}

private Optional<PlayerInventory> getInventory(){
ClientPlayerEntity player = MinecraftClient.getInstance().player;
if (player == null) {
Util.notifyError("Player is null, cannot get inventory stacks.", new Throwable());
return Optional.empty();
}
@Override
public Integer getHighlightColor(int slotIndex) {
return colorCache.get(slotIndex);
}

return Optional.of(player.getInventory());
@Override
public boolean isEnabled() {
return InventoryConfig.INSTANT_SELL_HIGHLIGHT_TOGGLE;
}

public InstantSellHighlight() {
super();
}

private List<ItemStack> getInventoryStacks(List<String> names){
List<ItemStack> inventoryStacks = new ArrayList<>();
@Override
protected void registerFabricEvents() {
ScreenEvents.AFTER_INIT.register(this::onScreenInitialized);
}

var inventoryOpt = getInventory();
if (inventoryOpt.isEmpty()) return Collections.emptyList();
var inventory = inventoryOpt.get();
@EventHandler
private void onChestLoaded(ChestLoadedEvent event) {
colorCache.clear();

var stacks = inventory.getMainStacks();
if (!isEnabled()) return;

stacks.forEach(itemStack -> {
if(itemStack.isEmpty()) return;
String itemName = itemStack.getName().getString();
if (names.stream().anyMatch(name -> itemName.toLowerCase().contains(name.toLowerCase()))) {
inventoryStacks.add(itemStack);
}
});
return inventoryStacks;
}
ScreenManager.getInstance().current().ifPresent(context -> {
HandledScreen<?> screen = ScreenManager.getCurrentlyHandledScreen(HandledScreen.class).orElse(null);
MinecraftClient client = MinecraftClient.getInstance();

public static void updateHighlightCache() {
if (!BazaarUtilsModules.InstantSellHighlight.isEnabled()) {
return;
}
if (screen == null || client.player == null) return;

for (Integer index : highlightedSlotIndexes) {
getColorFromIndex(index).ifPresent(instaSellHighlightColor -> SlotHighlightCache.instaSellHighlightCache.computeIfAbsent(index, (k) -> instaSellHighlightColor));
}
List<OrderInfo> orders = resolveOrders(context);

if (orders.isEmpty()) return;

Set<String> names = orders.stream()
.map(OrderInfo::getName)
.collect(Collectors.toSet());

populateCache(names, screen, client.player.getInventory());
});
}

public static OptionalInt getColorFromIndex(int slotIndex) {
if (highlightedSlotIndexes.stream().noneMatch(i -> i.equals(slotIndex))) {
return OptionalInt.empty();
}
private void onScreenInitialized(MinecraftClient client, Screen screen, int width, int height) {
colorCache.clear();
}

return OptionalInt.of(InventoryConfig.INSTANT_SELL_HIGHLIGHT_COLOR);
private static List<OrderInfo> resolveOrders(ScreenContext context) {
if (context.isAnyOf(BazaarScreens.ITEM_PAGE))
return BazaarScreenHandler.getInstantSellItem(context)
.map(ItemInfo::itemStack)
.flatMap(InstantSellParser::parseItemPageOrder)
.map(InstantSellParser.InstantSellResult::items)
.orElse(List.of());

return BazaarScreenHandler.getInstantSellItem(context)
.map(ItemInfo::itemStack)
.map(InstantSellParser::parseOrders)
.map(InstantSellParser.InstantSellResult::items)
.orElse(List.of());
}
}
}
Loading
Loading