forked from BRNSystems/Server_storage
		
	UNFINISHED
Add Crafting, improve autosuck //TODO: - add into SettingsScreen all containers with taking out, autosuck and putting in - add block to store hard drives, because chests are too expensive to index - fix crafting
This commit is contained in:
		@@ -8,7 +8,7 @@ yarn_mappings=1.20.6+build.3
 | 
			
		||||
loader_version=0.15.11
 | 
			
		||||
 | 
			
		||||
# Mod Properties
 | 
			
		||||
mod_version=2.3
 | 
			
		||||
mod_version=2.4
 | 
			
		||||
maven_group=systems.brn
 | 
			
		||||
archives_base_name=Server_storage
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -25,6 +25,7 @@ public class StorageBlockEntity extends BlockEntity implements Inventory, SidedI
 | 
			
		||||
 | 
			
		||||
    public Boolean sortAlphabetically = false;
 | 
			
		||||
    public Boolean allInventories = false;
 | 
			
		||||
    public Boolean autoSuck = false;
 | 
			
		||||
    public String searchString = "";
 | 
			
		||||
    public int page = 0;
 | 
			
		||||
    public ConnectedChests chests;
 | 
			
		||||
@@ -37,6 +38,9 @@ public class StorageBlockEntity extends BlockEntity implements Inventory, SidedI
 | 
			
		||||
 | 
			
		||||
    public void rescanChests() {
 | 
			
		||||
        this.chests = new ConnectedChests(world, this.pos, sortAlphabetically, searchString, allInventories);
 | 
			
		||||
        if(autoSuck){
 | 
			
		||||
            this.chests.autoSuck();
 | 
			
		||||
        }
 | 
			
		||||
        this.updateDisplays();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -158,6 +162,7 @@ public class StorageBlockEntity extends BlockEntity implements Inventory, SidedI
 | 
			
		||||
        nbt.putBoolean("sortAlphabetically", sortAlphabetically);
 | 
			
		||||
        nbt.putString("searchString", searchString);
 | 
			
		||||
        nbt.putBoolean("allInventories", allInventories);
 | 
			
		||||
        nbt.putBoolean("autoSuck", autoSuck);
 | 
			
		||||
 | 
			
		||||
        super.writeNbt(nbt, wrapperLookup);
 | 
			
		||||
    }
 | 
			
		||||
@@ -171,5 +176,6 @@ public class StorageBlockEntity extends BlockEntity implements Inventory, SidedI
 | 
			
		||||
        sortAlphabetically = nbt.getBoolean("sortAlphabetically");
 | 
			
		||||
        searchString = nbt.getString("searchString");
 | 
			
		||||
        allInventories = nbt.getBoolean("allInventories");
 | 
			
		||||
        autoSuck = nbt.getBoolean("autoSuck");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -15,6 +15,7 @@ import static systems.brn.server_storage.lib.StorageOperations.*;
 | 
			
		||||
 | 
			
		||||
public class ConnectedChests {
 | 
			
		||||
    public final List<Inventory> inventories;
 | 
			
		||||
    public final List<Inventory> hoppers;
 | 
			
		||||
    public final Inventory inventory;
 | 
			
		||||
 | 
			
		||||
    public final int containerCount;
 | 
			
		||||
@@ -24,11 +25,13 @@ public class ConnectedChests {
 | 
			
		||||
 | 
			
		||||
    public ConnectedChests(World world, BlockPos startPos, boolean sortAlphabetically, String searchString, boolean allInventories) {
 | 
			
		||||
        List<Inventory> inventories = new ArrayList<>();
 | 
			
		||||
        List<Inventory> hoppers = new ArrayList<>();
 | 
			
		||||
        Set<BlockPos> visited = new HashSet<>();
 | 
			
		||||
 | 
			
		||||
        getConnectedChestsHelper(world, startPos, inventories, visited, allInventories);
 | 
			
		||||
        getConnectedChestsHelper(world, startPos, inventories, hoppers, visited, allInventories);
 | 
			
		||||
 | 
			
		||||
        this.inventories = inventories;
 | 
			
		||||
        this.hoppers = hoppers;
 | 
			
		||||
        this.containerCount = inventories.size();
 | 
			
		||||
        this.inventory = getCombinedInventory(sortAlphabetically, searchString);
 | 
			
		||||
 | 
			
		||||
@@ -58,13 +61,18 @@ public class ConnectedChests {
 | 
			
		||||
                blockEntity instanceof ShulkerBoxBlockEntity;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static void getConnectedChestsHelper(World world, BlockPos pos, List<Inventory> inventories, Set<BlockPos> visited, Boolean allContainers) {
 | 
			
		||||
    private static void getConnectedChestsHelper(World world, BlockPos pos, List<Inventory> inventories, List<Inventory> hoppers, Set<BlockPos> visited, Boolean allContainers) {
 | 
			
		||||
        if (visited.contains(pos)) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        visited.add(pos);
 | 
			
		||||
 | 
			
		||||
        BlockEntity blockEntity = world.getBlockEntity(pos);
 | 
			
		||||
 | 
			
		||||
        if (isEnabledHopper(blockEntity)) {
 | 
			
		||||
            hoppers.add((Inventory) blockEntity);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (isEnabledContainer(blockEntity, allContainers) || blockEntity instanceof StorageBlockEntity) {
 | 
			
		||||
            if (isEnabledContainer(blockEntity, allContainers) && !(blockEntity instanceof StorageBlockEntity)) {
 | 
			
		||||
                inventories.add((Inventory) blockEntity);
 | 
			
		||||
@@ -72,7 +80,7 @@ public class ConnectedChests {
 | 
			
		||||
 | 
			
		||||
            for (Direction direction : Direction.values()) {
 | 
			
		||||
                BlockPos nextPos = pos.offset(direction);
 | 
			
		||||
                getConnectedChestsHelper(world, nextPos, inventories, visited, allContainers);
 | 
			
		||||
                getConnectedChestsHelper(world, nextPos, inventories, hoppers, visited, allContainers);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@@ -81,27 +89,7 @@ public class ConnectedChests {
 | 
			
		||||
    private SimpleInventory getCombinedInventory(boolean sortAlphabetically, String query) {
 | 
			
		||||
        Map<ItemStack, Integer> itemStackMap = new HashMap<>();
 | 
			
		||||
        for (Inventory inventory : inventories) {
 | 
			
		||||
            for (int i = 0; i < inventory.size(); i++) {
 | 
			
		||||
                ItemStack stack = inventory.getStack(i);
 | 
			
		||||
                if (!stack.isEmpty()) {
 | 
			
		||||
                    // Check if there's an existing ItemStack with the same item and metadata
 | 
			
		||||
                    boolean found = false;
 | 
			
		||||
                    for (Map.Entry<ItemStack, Integer> entry : itemStackMap.entrySet()) {
 | 
			
		||||
                        ItemStack existingStack = entry.getKey();
 | 
			
		||||
                        if (ItemStack.areItemsAndComponentsEqual(stack, existingStack)) {
 | 
			
		||||
                            int count = entry.getValue() + stack.getCount();
 | 
			
		||||
                            itemStackMap.put(existingStack.copy(), count);
 | 
			
		||||
                            found = true;
 | 
			
		||||
                            break;
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    // If no existing stack with the same item and metadata, add a new entry
 | 
			
		||||
                    if (!found) {
 | 
			
		||||
                        ItemStack copiedStack = stack.copy();
 | 
			
		||||
                        itemStackMap.put(copiedStack, stack.getCount());
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            addInventoryToMap(inventory, itemStackMap);
 | 
			
		||||
        }
 | 
			
		||||
        return filterInventory(getSimpleInventory(itemStackMap.size(), itemStackMap, sortAlphabetically), query, sortAlphabetically);
 | 
			
		||||
    }
 | 
			
		||||
@@ -119,7 +107,7 @@ public class ConnectedChests {
 | 
			
		||||
            if (!filteredStack.isEmpty()) {
 | 
			
		||||
                itemCount++;
 | 
			
		||||
                int count = itemStackMap.getOrDefault(filteredStack, 0) + filteredStack.getCount();
 | 
			
		||||
                itemStackMap.put(filteredStack.copy(), count);
 | 
			
		||||
                itemStackMap.put(filteredStack, count);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return getSimpleInventory(itemCount, itemStackMap, sortAlphabetically);
 | 
			
		||||
@@ -141,6 +129,15 @@ public class ConnectedChests {
 | 
			
		||||
        return stack.isEmpty();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static boolean isEnabledHopper(BlockEntity blockEntity) {
 | 
			
		||||
        return blockEntity instanceof HopperBlockEntity ||
 | 
			
		||||
                blockEntity instanceof TrappedChestBlockEntity ||
 | 
			
		||||
                blockEntity instanceof FurnaceBlockEntity ||
 | 
			
		||||
                blockEntity instanceof BlastFurnaceBlockEntity ||
 | 
			
		||||
                blockEntity instanceof SmokerBlockEntity ||
 | 
			
		||||
                blockEntity instanceof BrewingStandBlockEntity;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public boolean canAddItemStack(ItemStack stack) {
 | 
			
		||||
        // Iterate over each chest to check if it's possible to insert the ItemStack
 | 
			
		||||
        for (Inventory chest : inventories) {
 | 
			
		||||
@@ -155,29 +152,30 @@ public class ConnectedChests {
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // If it's not possible to insert into any chest, return false
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public boolean canRemove(ItemStack stackToRemove) {
 | 
			
		||||
        int remainingToRemove = stackToRemove.getCount();
 | 
			
		||||
 | 
			
		||||
        for (int i = 0; i < inventory.size(); i++) {
 | 
			
		||||
            ItemStack slotStack = inventory.getStack(i);
 | 
			
		||||
            if (canCombine(slotStack, stackToRemove)) {
 | 
			
		||||
                // If the slot contains the same item type
 | 
			
		||||
                if (slotStack.getCount() >= remainingToRemove) {
 | 
			
		||||
                    // If the count in the slot is sufficient to remove the requested amount
 | 
			
		||||
                    return true;
 | 
			
		||||
                } else {
 | 
			
		||||
                    // If the count in the slot is not sufficient, update remainingToRemove
 | 
			
		||||
                    remainingToRemove -= slotStack.getCount();
 | 
			
		||||
    public void autoSuck() {
 | 
			
		||||
        for (Inventory chest : hoppers) {
 | 
			
		||||
            for (int i = 0; i < chest.size(); i++) {
 | 
			
		||||
                ItemStack slotStack = chest.getStack(i);
 | 
			
		||||
                if (!slotStack.isEmpty()) {
 | 
			
		||||
                    if (this.canAddItemStack(slotStack)) {
 | 
			
		||||
                        if (this.tryPutItemStack(slotStack)) {
 | 
			
		||||
                            removeFromInventory(chest, slotStack, slotStack.getCount());
 | 
			
		||||
                        }
 | 
			
		||||
                        ;
 | 
			
		||||
                    } else {
 | 
			
		||||
                        return;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        // If no matching stack with sufficient count is found, return false
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public boolean canRemove(ItemStack stackToRemove) {
 | 
			
		||||
        return canRemoveCount(stackToRemove, inventory) == 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public ItemStack removeItemStack(ItemStack stackToRemove) {
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,14 @@
 | 
			
		||||
package systems.brn.server_storage.lib;
 | 
			
		||||
 | 
			
		||||
import net.minecraft.item.ItemStack;
 | 
			
		||||
import net.minecraft.recipe.CraftingRecipe;
 | 
			
		||||
import net.minecraft.recipe.RecipeEntry;
 | 
			
		||||
 | 
			
		||||
public class CraftingEntry {
 | 
			
		||||
    public final ItemStack itemStack;
 | 
			
		||||
    public final RecipeEntry<CraftingRecipe> recipeEntry;
 | 
			
		||||
    public CraftingEntry(ItemStack itemStack, RecipeEntry<CraftingRecipe> recipeEntry) {
 | 
			
		||||
        this.itemStack = itemStack;
 | 
			
		||||
        this.recipeEntry = recipeEntry;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -31,7 +31,11 @@ public abstract class PagedGui extends SimpleGui {
 | 
			
		||||
    public static final String GUI_A = "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNGU0MTc0ODEyMTYyNmYyMmFlMTZhNGM2NjRjNzMwMWE5ZjhlYTU5MWJmNGQyOTg4ODk1NzY4MmE5ZmRhZiJ9fX0=";
 | 
			
		||||
    public static final String GUI_1 = "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvY2E1MTZmYmFlMTYwNThmMjUxYWVmOWE2OGQzMDc4NTQ5ZjQ4ZjZkNWI2ODNmMTljZjVhMTc0NTIxN2Q3MmNjIn19fQ==";
 | 
			
		||||
    public static final String GUI_STORE_ALL = "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMWFkNmM4MWY4OTlhNzg1ZWNmMjZiZTFkYzQ4ZWFlMmJjZmU3NzdhODYyMzkwZjU3ODVlOTViZDgzYmQxNGQifX19";
 | 
			
		||||
    public static final String GUI_SETTINGS = "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvN2EzYzhjNmQzYWFhOTYzNjNkNGJlZjI1NzhmMTAyNDc4MWVhMTRlOWQ4NWE5ZGNmYzA5MzU4NDdhNmZiNWM4ZCJ9fX0=";
 | 
			
		||||
    public static final String GUI_CONTAINERS = "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvN2EzYzhjNmQzYWFhOTYzNjNkNGJlZjI1NzhmMTAyNDc4MWVhMTRlOWQ4NWE5ZGNmYzA5MzU4NDdhNmZiNWM4ZCJ9fX0=";
 | 
			
		||||
    public static final String GUI_SETTINGS = "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZTRkNDliYWU5NWM3OTBjM2IxZmY1YjJmMDEwNTJhNzE0ZDYxODU0ODFkNWIxYzg1OTMwYjNmOTlkMjMyMTY3NCJ9fX0=";
 | 
			
		||||
    public static final String GUI_CRAFTING = "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYWQyYzBjZWRmYzMyZTNiZWVlOTU1Y2FiZDY2ZmQ0ZDc2NWVlZGEzYWRjYzg0YmM0NTFjOWZkYmVjZjNjYjdjMiJ9fX0=";
 | 
			
		||||
    public static final String GUI_AUTOSUCK_OFF = "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvOGViODFlZjg5MDIzNzk2NTBiYTc5ZjQ1NzIzZDZiOWM4ODgzODhhMDBmYzRlMTkyZjM0NTRmZTE5Mzg4MmVlMSJ9fX0=";
 | 
			
		||||
    public static final String GUI_AUTOSUCK_ON = "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMThjNDQzYWRhNmUzOWZjYTgzN2EwMzgzYjBhNWUzZTU1NDc3M2I5NjYwYzQ4NzNmNTkxMDMyZGJlOWFkY2RmOCJ9fX0=";
 | 
			
		||||
 | 
			
		||||
    public static final int PAGE_SIZE = 9 * 5;
 | 
			
		||||
    protected final Runnable closeCallback;
 | 
			
		||||
@@ -112,17 +116,18 @@ public abstract class PagedGui extends SimpleGui {
 | 
			
		||||
    protected DisplayElement getNavElement(int id) {
 | 
			
		||||
        return switch (id) {
 | 
			
		||||
            case 0 -> DisplayElement.previousPage(this);
 | 
			
		||||
            case 2 -> this.search();
 | 
			
		||||
            case 3 -> this.sorting();
 | 
			
		||||
            case 4 -> this.refresh();
 | 
			
		||||
            case 5 -> this.storeAll();
 | 
			
		||||
            case 6 -> this.settings();
 | 
			
		||||
            case 1 -> this.search();
 | 
			
		||||
            case 2 -> this.sorting();
 | 
			
		||||
            case 3 -> this.refresh();
 | 
			
		||||
            case 4 -> this.storeAll();
 | 
			
		||||
            case 5 -> this.settings();
 | 
			
		||||
            case 6 -> this.crafting();
 | 
			
		||||
            case 7 -> DisplayElement.nextPage(this);
 | 
			
		||||
            case 8 -> DisplayElement.of(
 | 
			
		||||
                    new GuiElementBuilder(Items.STRUCTURE_VOID)
 | 
			
		||||
                            .setName(Text.translatable(this.closeCallback != null ? "gui.back" : "mco.selectServer.close").formatted(Formatting.RED))
 | 
			
		||||
                            .hideDefaultTooltip().noDefaults()
 | 
			
		||||
                            .setCallback((x, y, z) -> {
 | 
			
		||||
                            .setCallback((i, clickType, slotActionType) -> {
 | 
			
		||||
                                playClickSound(this.player);
 | 
			
		||||
                                this.close();
 | 
			
		||||
                            })
 | 
			
		||||
@@ -135,9 +140,14 @@ public abstract class PagedGui extends SimpleGui {
 | 
			
		||||
        return DisplayElement.filler();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected DisplayElement crafting() {
 | 
			
		||||
        return DisplayElement.filler();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected DisplayElement search(){
 | 
			
		||||
        return DisplayElement.filler();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected DisplayElement sorting(){
 | 
			
		||||
        return DisplayElement.filler();
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -134,7 +134,48 @@ public class StorageOperations {
 | 
			
		||||
        return remainingToRemove;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static int canRemoveCount(ItemStack stackToRemove, Inventory inventory) {
 | 
			
		||||
        int remainingToRemove = stackToRemove.getCount();
 | 
			
		||||
 | 
			
		||||
        for (int i = 0; i < inventory.size(); i++) {
 | 
			
		||||
            ItemStack slotStack = inventory.getStack(i);
 | 
			
		||||
            if (canCombine(slotStack, stackToRemove)) {
 | 
			
		||||
                // If the slot contains the same item type
 | 
			
		||||
                if (slotStack.getCount() >= remainingToRemove) {
 | 
			
		||||
                    // If the count in the slot is sufficient to remove the requested amount
 | 
			
		||||
                    return 0;
 | 
			
		||||
                } else {
 | 
			
		||||
                    // If the count in the slot is not sufficient, update remainingToRemove
 | 
			
		||||
                    remainingToRemove -= slotStack.getCount();
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        // If no matching stack with sufficient count is found, return false
 | 
			
		||||
        return remainingToRemove;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static boolean canCombine(ItemStack stack1, ItemStack stack2) {
 | 
			
		||||
        return !stack1.isEmpty() && stack1.getItem() == stack2.getItem() && ItemStack.areItemsAndComponentsEqual(stack1, stack2);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static void addInventoryToMap(Inventory inventory, Map<ItemStack, Integer> itemStackMap) {
 | 
			
		||||
        for (int i = 0; i < inventory.size(); i++) {
 | 
			
		||||
            ItemStack stack = inventory.getStack(i);
 | 
			
		||||
            if (!stack.isEmpty()) {
 | 
			
		||||
                addToMap(itemStackMap, stack);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static void addToMap(Map<ItemStack, Integer> itemStackMap, ItemStack stack) {
 | 
			
		||||
        for (Map.Entry<ItemStack, Integer> entry : itemStackMap.entrySet()) {
 | 
			
		||||
            ItemStack existingStack = entry.getKey();
 | 
			
		||||
            if (ItemStack.areItemsAndComponentsEqual(stack, existingStack)) {
 | 
			
		||||
                int newCount = entry.getValue() + stack.getCount();
 | 
			
		||||
                itemStackMap.put(existingStack, newCount);
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        itemStackMap.put(stack.copy(), stack.getCount());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,8 @@ import net.minecraft.component.type.LoreComponent;
 | 
			
		||||
import net.minecraft.inventory.Inventory;
 | 
			
		||||
import net.minecraft.item.Item;
 | 
			
		||||
import net.minecraft.item.ItemStack;
 | 
			
		||||
import net.minecraft.recipe.*;
 | 
			
		||||
import net.minecraft.server.MinecraftServer;
 | 
			
		||||
import net.minecraft.text.RawFilteredPair;
 | 
			
		||||
import net.minecraft.text.Style;
 | 
			
		||||
import net.minecraft.text.Text;
 | 
			
		||||
@@ -99,4 +101,60 @@ public class Util {
 | 
			
		||||
            return stack;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static ArrayList<CraftingEntry> getCraftableRecipes(Inventory inventory, MinecraftServer server) {
 | 
			
		||||
        RecipeManager recipeManager = server.getRecipeManager();
 | 
			
		||||
        List<RecipeEntry<CraftingRecipe>> allRecipes = recipeManager.listAllOfType(RecipeType.CRAFTING);
 | 
			
		||||
 | 
			
		||||
        ArrayList<CraftingEntry> craftingEntries = new ArrayList<>();
 | 
			
		||||
 | 
			
		||||
        for (RecipeEntry<CraftingRecipe> recipe : allRecipes) {
 | 
			
		||||
            int maxAmount = -1;
 | 
			
		||||
            boolean canMake = true;
 | 
			
		||||
            for (Ingredient ingredient : recipe.value().getIngredients()) {
 | 
			
		||||
                for (ItemStack stack : ingredient.getMatchingStacks()) {
 | 
			
		||||
                    if (stack.isEmpty()) {
 | 
			
		||||
                        break;
 | 
			
		||||
                    } else {
 | 
			
		||||
                        //if inventory contains stack
 | 
			
		||||
                        boolean foundUsableStack = false;
 | 
			
		||||
                        for (int i = 0; i < inventory.size(); i++) {
 | 
			
		||||
                            if (inventory.getStack(i).getItem().equals(stack.getItem())) {
 | 
			
		||||
                                if (maxAmount == -1) {
 | 
			
		||||
                                    maxAmount = inventory.getStack(i).getCount();
 | 
			
		||||
                                } else {
 | 
			
		||||
                                    maxAmount = Math.min(maxAmount, inventory.getStack(i).getCount());
 | 
			
		||||
                                }
 | 
			
		||||
                                foundUsableStack = true;
 | 
			
		||||
                                break;
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                        if (!foundUsableStack) {
 | 
			
		||||
                            canMake = false;
 | 
			
		||||
                            break;
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            if (maxAmount > 1 && canMake) {
 | 
			
		||||
                Item outputItem = recipe.value().getResult(server.getRegistryManager()).getItem();
 | 
			
		||||
                CraftingEntry entry = new CraftingEntry(new ItemStack(outputItem, maxAmount), recipe);
 | 
			
		||||
                boolean needToAdd = true;
 | 
			
		||||
                for (int i = 0; i < craftingEntries.size(); i++) {
 | 
			
		||||
                    CraftingEntry entryLoop = craftingEntries.get(i);
 | 
			
		||||
                    if (entryLoop.itemStack.getItem().equals(outputItem)) {
 | 
			
		||||
                        needToAdd = false;
 | 
			
		||||
                        if (maxAmount > entryLoop.itemStack.getCount()) {
 | 
			
		||||
                            craftingEntries.set(i, entry);
 | 
			
		||||
                            break;
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                if (needToAdd) {
 | 
			
		||||
                    craftingEntries.add(entry);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return craftingEntries;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,199 @@
 | 
			
		||||
package systems.brn.server_storage.screens;
 | 
			
		||||
 | 
			
		||||
import eu.pb4.sgui.api.elements.GuiElementBuilder;
 | 
			
		||||
import net.minecraft.entity.player.PlayerEntity;
 | 
			
		||||
import net.minecraft.inventory.Inventory;
 | 
			
		||||
import net.minecraft.item.ItemStack;
 | 
			
		||||
import net.minecraft.recipe.CraftingRecipe;
 | 
			
		||||
import net.minecraft.recipe.Ingredient;
 | 
			
		||||
import net.minecraft.recipe.RecipeEntry;
 | 
			
		||||
import net.minecraft.text.Text;
 | 
			
		||||
import systems.brn.server_storage.lib.CraftingEntry;
 | 
			
		||||
import systems.brn.server_storage.lib.PagedGui;
 | 
			
		||||
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.HashMap;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
import java.util.Objects;
 | 
			
		||||
 | 
			
		||||
import static systems.brn.server_storage.lib.StorageOperations.*;
 | 
			
		||||
import static systems.brn.server_storage.lib.Util.addCountToLore;
 | 
			
		||||
import static systems.brn.server_storage.lib.Util.getCraftableRecipes;
 | 
			
		||||
 | 
			
		||||
public class CraftingScreen extends PagedGui {
 | 
			
		||||
    private final StorageScreen storageScreen;
 | 
			
		||||
 | 
			
		||||
    private ArrayList<CraftingEntry> craftingEntries;
 | 
			
		||||
 | 
			
		||||
    private ArrayList<DisplayElement> recipesList;
 | 
			
		||||
 | 
			
		||||
    public CraftingScreen(StorageScreen storageScreen) {
 | 
			
		||||
        super(storageScreen.getPlayer(), null);
 | 
			
		||||
        this.storageScreen = storageScreen;
 | 
			
		||||
        this.setTitle(Text.translatable("container.crafting"));
 | 
			
		||||
        this.updateDisplay();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void updateDisplay(){
 | 
			
		||||
        storageScreen.blockEntity.rescanChests();
 | 
			
		||||
        Map<ItemStack, Integer> itemStackMap = new HashMap<>();
 | 
			
		||||
        addInventoryToMap(storageScreen.getPlayer().getInventory(), itemStackMap);
 | 
			
		||||
        addInventoryToMap(storageScreen.blockEntity.chests.inventory, itemStackMap);
 | 
			
		||||
        Inventory inventory = getSimpleInventory(itemStackMap.size(), itemStackMap, false);
 | 
			
		||||
        this.craftingEntries = getCraftableRecipes(inventory, Objects.requireNonNull(player.getServer()));
 | 
			
		||||
        this.recipesList = getAvailableRecipes();
 | 
			
		||||
        super.updateDisplay();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private ArrayList<DisplayElement> getAvailableRecipes() {
 | 
			
		||||
        ArrayList<DisplayElement> recipes = new ArrayList<>();
 | 
			
		||||
 | 
			
		||||
        for (CraftingEntry craftingEntry : craftingEntries) {
 | 
			
		||||
            ItemStack stackWithCount = addCountToLore(craftingEntry.itemStack.getCount(), craftingEntry.itemStack);
 | 
			
		||||
            if (stackWithCount.getCount() > stackWithCount.getMaxCount()) {
 | 
			
		||||
                stackWithCount.setCount(stackWithCount.getMaxCount());
 | 
			
		||||
            }
 | 
			
		||||
            recipes.add(
 | 
			
		||||
                    DisplayElement.of(new GuiElementBuilder(stackWithCount)
 | 
			
		||||
                            .setCallback((i, clickType, slotActionType) -> {
 | 
			
		||||
                                playClickSound(player);
 | 
			
		||||
                                RecipeEntry<CraftingRecipe> recipeEntry = craftingEntry.recipeEntry;
 | 
			
		||||
 | 
			
		||||
                                // Crafting logic based on click type
 | 
			
		||||
                                if (clickType.isLeft) { // put into player inventory
 | 
			
		||||
                                    if (clickType.shift) { // craft all
 | 
			
		||||
                                        craftAll(player, recipeEntry, true);
 | 
			
		||||
                                    } else { // craft one stack
 | 
			
		||||
                                        craftOneStack(player, recipeEntry, true);
 | 
			
		||||
                                    }
 | 
			
		||||
                                } else if (clickType.isRight) { // put back into storage
 | 
			
		||||
                                    if (clickType.shift) { // craft all
 | 
			
		||||
                                        craftAll(player, recipeEntry, false);
 | 
			
		||||
                                    } else { // craft one stack
 | 
			
		||||
                                        craftOneStack(player, recipeEntry, false);
 | 
			
		||||
                                    }
 | 
			
		||||
                                }
 | 
			
		||||
                                updateDisplay();
 | 
			
		||||
                            })
 | 
			
		||||
                    )
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
        return recipes;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void craftAll(PlayerEntity player, RecipeEntry<CraftingRecipe> recipeEntry, boolean toPlayerInventory) {
 | 
			
		||||
        while (canCraft(recipeEntry)) {
 | 
			
		||||
            if (craftOneStack(player, recipeEntry, toPlayerInventory)) {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private boolean craftOneStack(PlayerEntity player, RecipeEntry<CraftingRecipe> recipeEntry, boolean toPlayerInventory) {
 | 
			
		||||
        if (!canCraft(recipeEntry)) {
 | 
			
		||||
            return true; //stop
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Check and remove ingredients
 | 
			
		||||
        for (Ingredient ingredient : recipeEntry.value().getIngredients()) {
 | 
			
		||||
            ItemStack stackToRemove = findMatchingStack(ingredient);
 | 
			
		||||
            if (stackToRemove == null){
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
            int requiredCount = canRemoveCount(stackToRemove, this.storageScreen.blockEntity.chests.inventory);
 | 
			
		||||
 | 
			
		||||
            if (requiredCount > 0 && canRemoveCount(stackToRemove, this.storageScreen.getPlayer().getInventory()) < requiredCount) {
 | 
			
		||||
                return true;
 | 
			
		||||
            } else {
 | 
			
		||||
                removeItems(stackToRemove, requiredCount);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Add the result to the appropriate inventory
 | 
			
		||||
        ItemStack outputStack = recipeEntry.value().getResult(storageScreen.getPlayer().getRegistryManager());
 | 
			
		||||
        if (toPlayerInventory) {
 | 
			
		||||
            if (canInsertItemIntoPlayerInventory(player, outputStack) == outputStack.getCount()) {
 | 
			
		||||
                player.getInventory().insertStack(outputStack);
 | 
			
		||||
            } else {
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            if (this.storageScreen.blockEntity.chests.canAddItemStack(outputStack)) {
 | 
			
		||||
                this.storageScreen.blockEntity.chests.tryPutItemStack(outputStack);
 | 
			
		||||
            } else {
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Remove ingredients
 | 
			
		||||
        for (Ingredient ingredient : recipeEntry.value().getIngredients()) {
 | 
			
		||||
            ItemStack stackToRemove = findMatchingStack(ingredient);
 | 
			
		||||
            if (stackToRemove == null){
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
            removeItems(stackToRemove, stackToRemove.getCount());
 | 
			
		||||
        }
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private boolean canCraft(RecipeEntry<CraftingRecipe> recipeEntry) {
 | 
			
		||||
        for (Ingredient ingredient : recipeEntry.value().getIngredients()) {
 | 
			
		||||
            ItemStack stackToRemove = findMatchingStack(ingredient);
 | 
			
		||||
            if (stackToRemove == null){
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
            int requiredCount = canRemoveCount(stackToRemove, this.storageScreen.blockEntity.chests.inventory);
 | 
			
		||||
 | 
			
		||||
            if (requiredCount > 0 && canRemoveCount(stackToRemove, this.storageScreen.getPlayer().getInventory()) < requiredCount) {
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private ItemStack findMatchingStack(Ingredient ingredient) {
 | 
			
		||||
        for (ItemStack stack : ingredient.getMatchingStacks()) {
 | 
			
		||||
            if (this.storageScreen.blockEntity.chests.canRemove(stack)) {
 | 
			
		||||
                return stack;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void removeItems(ItemStack stack, int count) {
 | 
			
		||||
        // Logic to remove items from the storage
 | 
			
		||||
        ItemStack stackRemove = stack.copy();
 | 
			
		||||
        stackRemove.setCount(count);
 | 
			
		||||
        ItemStack fromPlayer = this.storageScreen.blockEntity.chests.removeItemStack(stackRemove);
 | 
			
		||||
        if (fromPlayer != null && fromPlayer.getCount() > 0) {
 | 
			
		||||
            Inventory playerInventory = player.getInventory();
 | 
			
		||||
            for (int i = 0; i < playerInventory.size(); i++) {
 | 
			
		||||
                if (playerInventory.getStack(i).equals(fromPlayer)) {
 | 
			
		||||
                    playerInventory.removeStack(i);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onClose() {
 | 
			
		||||
        super.onClose();
 | 
			
		||||
        storageScreen.open();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected int getPageAmount() {
 | 
			
		||||
        return Math.ceilDivExact(recipesList.size(), 9 * 6);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected DisplayElement getElement(int id) {
 | 
			
		||||
        if (id >=0 && id < recipesList.size()) {
 | 
			
		||||
            return recipesList.get(id);
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            return DisplayElement.empty();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,83 @@
 | 
			
		||||
package systems.brn.server_storage.screens;
 | 
			
		||||
 | 
			
		||||
import eu.pb4.sgui.api.elements.GuiElementBuilder;
 | 
			
		||||
import net.minecraft.item.Items;
 | 
			
		||||
import net.minecraft.text.Text;
 | 
			
		||||
import net.minecraft.util.Formatting;
 | 
			
		||||
import systems.brn.server_storage.lib.PagedGui;
 | 
			
		||||
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
 | 
			
		||||
public class SettingsScreen extends PagedGui {
 | 
			
		||||
 | 
			
		||||
    private final StorageScreen storageScreen;
 | 
			
		||||
 | 
			
		||||
    private ArrayList<DisplayElement> settingsList;
 | 
			
		||||
 | 
			
		||||
    public SettingsScreen(StorageScreen storageScreen) {
 | 
			
		||||
        super(storageScreen.getPlayer(), null);
 | 
			
		||||
        this.storageScreen = storageScreen;
 | 
			
		||||
        this.setTitle(Text.translatable("mco.configure.world.buttons.settings"));
 | 
			
		||||
        this.updateDisplay();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onClose() {
 | 
			
		||||
        super.onClose();
 | 
			
		||||
        storageScreen.open();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void updateDisplay() {
 | 
			
		||||
        this.settingsList = new ArrayList<>();
 | 
			
		||||
        this.settingsList.add(containers());
 | 
			
		||||
        this.settingsList.add(autoSuck());
 | 
			
		||||
        super.updateDisplay();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected PagedGui.DisplayElement containers() {
 | 
			
		||||
        return PagedGui.DisplayElement.of(
 | 
			
		||||
                new GuiElementBuilder(Items.PLAYER_HEAD)
 | 
			
		||||
                        .setName(Text.translatable(storageScreen.blockEntity.allInventories ? "gui.all" : "options.fov.min").formatted(Formatting.WHITE))
 | 
			
		||||
                        .hideDefaultTooltip().noDefaults()
 | 
			
		||||
                        .setSkullOwner(GUI_CONTAINERS)
 | 
			
		||||
                        .setCallback((x, y, z) -> {
 | 
			
		||||
                            storageScreen.blockEntity.allInventories ^= true;
 | 
			
		||||
                            storageScreen.blockEntity.markDirty();
 | 
			
		||||
                            storageScreen.blockEntity.rescanChests();
 | 
			
		||||
                            playClickSound(getPlayer());
 | 
			
		||||
                            updateDisplay();
 | 
			
		||||
                        })
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected int getPageAmount() {
 | 
			
		||||
        return Math.ceilDivExact(settingsList.size(), 9*6);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected DisplayElement getElement(int id) {
 | 
			
		||||
        if (id >= 0 && id < settingsList.size()) {
 | 
			
		||||
            return settingsList.get(id);
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            return DisplayElement.empty();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected PagedGui.DisplayElement autoSuck() {
 | 
			
		||||
        return PagedGui.DisplayElement.of(
 | 
			
		||||
                new GuiElementBuilder(Items.PLAYER_HEAD)
 | 
			
		||||
                        .setName(Text.translatable(storageScreen.blockEntity.autoSuck ? "gui.yes" : "gui.no").formatted(Formatting.WHITE))
 | 
			
		||||
                        .hideDefaultTooltip().noDefaults()
 | 
			
		||||
                        .setSkullOwner(storageScreen.blockEntity.autoSuck ? GUI_AUTOSUCK_ON : GUI_AUTOSUCK_OFF)
 | 
			
		||||
                        .setCallback((x, y, z) -> {
 | 
			
		||||
                            storageScreen.blockEntity.autoSuck ^= true;
 | 
			
		||||
                            storageScreen.blockEntity.rescanChests();
 | 
			
		||||
                            playClickSound(getPlayer());
 | 
			
		||||
                            updateDisplay();
 | 
			
		||||
                        })
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -20,7 +20,7 @@ import static systems.brn.server_storage.lib.Util.removeCountFromLore;
 | 
			
		||||
 | 
			
		||||
public class StorageScreen extends PagedGui {
 | 
			
		||||
    private final ServerPlayerEntity player;
 | 
			
		||||
    private final StorageBlockEntity blockEntity;
 | 
			
		||||
    public final StorageBlockEntity blockEntity;
 | 
			
		||||
 | 
			
		||||
    public StorageScreen(ServerPlayerEntity player, BlockPos pos, @Nullable Runnable closeCallback) {
 | 
			
		||||
        super(player, closeCallback);
 | 
			
		||||
@@ -118,22 +118,6 @@ public class StorageScreen extends PagedGui {
 | 
			
		||||
        return super.insertItem(stack, startIndex, endIndex, fromLast);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected DisplayElement settings() {
 | 
			
		||||
        return DisplayElement.of(
 | 
			
		||||
                new GuiElementBuilder(Items.PLAYER_HEAD)
 | 
			
		||||
                        .setName(Text.translatable(this.blockEntity.allInventories ? "gui.all" : "options.fov.min").formatted(Formatting.WHITE))
 | 
			
		||||
                        .hideDefaultTooltip().noDefaults()
 | 
			
		||||
                        .setSkullOwner(GUI_SETTINGS)
 | 
			
		||||
                        .setCallback((x, y, z) -> {
 | 
			
		||||
                            this.blockEntity.allInventories ^= true;
 | 
			
		||||
                            this.blockEntity.markDirty();
 | 
			
		||||
                            this.blockEntity.rescanChests();
 | 
			
		||||
                            playClickSound(getPlayer());
 | 
			
		||||
                        })
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected DisplayElement search() {
 | 
			
		||||
        return DisplayElement.of(
 | 
			
		||||
@@ -149,6 +133,21 @@ public class StorageScreen extends PagedGui {
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected DisplayElement settings() {
 | 
			
		||||
        return DisplayElement.of(
 | 
			
		||||
                new GuiElementBuilder(Items.PLAYER_HEAD)
 | 
			
		||||
                        .setName(Text.translatable("mco.configure.world.settings.title").formatted(Formatting.WHITE))
 | 
			
		||||
                        .hideDefaultTooltip().noDefaults()
 | 
			
		||||
                        .setSkullOwner(GUI_SETTINGS)
 | 
			
		||||
                        .setCallback((x, y, z) -> {
 | 
			
		||||
                            SettingsScreen settingsScreen = new SettingsScreen(this);
 | 
			
		||||
                            playClickSound(getPlayer());
 | 
			
		||||
                            settingsScreen.open();
 | 
			
		||||
                        })
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected DisplayElement sorting() {
 | 
			
		||||
        return DisplayElement.of(
 | 
			
		||||
@@ -164,6 +163,7 @@ public class StorageScreen extends PagedGui {
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected DisplayElement storeAll() {
 | 
			
		||||
        return DisplayElement.of(
 | 
			
		||||
@@ -181,6 +181,22 @@ public class StorageScreen extends PagedGui {
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected DisplayElement crafting() {
 | 
			
		||||
        return DisplayElement.of(
 | 
			
		||||
                new GuiElementBuilder(Items.PLAYER_HEAD)
 | 
			
		||||
                        .setName(Text.translatable("container.crafting").formatted(Formatting.WHITE))
 | 
			
		||||
                        .hideDefaultTooltip().noDefaults()
 | 
			
		||||
                        .setSkullOwner(GUI_CRAFTING)
 | 
			
		||||
                        .setCallback((x, y, z) -> {
 | 
			
		||||
                            playClickSound(player);
 | 
			
		||||
                            CraftingScreen craftingScreen = new CraftingScreen(this);
 | 
			
		||||
                            playClickSound(getPlayer());
 | 
			
		||||
                            craftingScreen.open();
 | 
			
		||||
                        })
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void doSearch(String query) {
 | 
			
		||||
        this.blockEntity.searchString = query;
 | 
			
		||||
        this.blockEntity.rescanChests();
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user