diff --git a/gradle.properties b/gradle.properties index 997eb81..4cefad5 100644 --- a/gradle.properties +++ b/gradle.properties @@ -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 diff --git a/src/main/java/systems/brn/server_storage/blockentities/StorageBlockEntity.java b/src/main/java/systems/brn/server_storage/blockentities/StorageBlockEntity.java index 04dfa7f..24be7d1 100644 --- a/src/main/java/systems/brn/server_storage/blockentities/StorageBlockEntity.java +++ b/src/main/java/systems/brn/server_storage/blockentities/StorageBlockEntity.java @@ -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"); } } diff --git a/src/main/java/systems/brn/server_storage/lib/ConnectedChests.java b/src/main/java/systems/brn/server_storage/lib/ConnectedChests.java index c4637b6..7430c41 100644 --- a/src/main/java/systems/brn/server_storage/lib/ConnectedChests.java +++ b/src/main/java/systems/brn/server_storage/lib/ConnectedChests.java @@ -15,6 +15,7 @@ import static systems.brn.server_storage.lib.StorageOperations.*; public class ConnectedChests { public final List inventories; + public final List 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 inventories = new ArrayList<>(); + List hoppers = new ArrayList<>(); Set 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 inventories, Set visited, Boolean allContainers) { + private static void getConnectedChestsHelper(World world, BlockPos pos, List inventories, List hoppers, Set 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 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 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) { diff --git a/src/main/java/systems/brn/server_storage/lib/CraftingEntry.java b/src/main/java/systems/brn/server_storage/lib/CraftingEntry.java new file mode 100644 index 0000000..b36389e --- /dev/null +++ b/src/main/java/systems/brn/server_storage/lib/CraftingEntry.java @@ -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 recipeEntry; + public CraftingEntry(ItemStack itemStack, RecipeEntry recipeEntry) { + this.itemStack = itemStack; + this.recipeEntry = recipeEntry; + } +} diff --git a/src/main/java/systems/brn/server_storage/lib/PagedGui.java b/src/main/java/systems/brn/server_storage/lib/PagedGui.java index 96502a6..1a35054 100644 --- a/src/main/java/systems/brn/server_storage/lib/PagedGui.java +++ b/src/main/java/systems/brn/server_storage/lib/PagedGui.java @@ -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(); } diff --git a/src/main/java/systems/brn/server_storage/lib/StorageOperations.java b/src/main/java/systems/brn/server_storage/lib/StorageOperations.java index 39d7e7d..8926a5f 100644 --- a/src/main/java/systems/brn/server_storage/lib/StorageOperations.java +++ b/src/main/java/systems/brn/server_storage/lib/StorageOperations.java @@ -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 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 itemStackMap, ItemStack stack) { + for (Map.Entry 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()); + } } diff --git a/src/main/java/systems/brn/server_storage/lib/Util.java b/src/main/java/systems/brn/server_storage/lib/Util.java index 789c2a2..f869182 100644 --- a/src/main/java/systems/brn/server_storage/lib/Util.java +++ b/src/main/java/systems/brn/server_storage/lib/Util.java @@ -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 getCraftableRecipes(Inventory inventory, MinecraftServer server) { + RecipeManager recipeManager = server.getRecipeManager(); + List> allRecipes = recipeManager.listAllOfType(RecipeType.CRAFTING); + + ArrayList craftingEntries = new ArrayList<>(); + + for (RecipeEntry 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; + } } diff --git a/src/main/java/systems/brn/server_storage/screens/CraftingScreen.java b/src/main/java/systems/brn/server_storage/screens/CraftingScreen.java new file mode 100644 index 0000000..7a27713 --- /dev/null +++ b/src/main/java/systems/brn/server_storage/screens/CraftingScreen.java @@ -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 craftingEntries; + + private ArrayList 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 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 getAvailableRecipes() { + ArrayList 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 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 recipeEntry, boolean toPlayerInventory) { + while (canCraft(recipeEntry)) { + if (craftOneStack(player, recipeEntry, toPlayerInventory)) { + return; + } + } + } + + private boolean craftOneStack(PlayerEntity player, RecipeEntry 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 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(); + } + } +} diff --git a/src/main/java/systems/brn/server_storage/screens/SettingsScreen.java b/src/main/java/systems/brn/server_storage/screens/SettingsScreen.java new file mode 100644 index 0000000..1c5a3cc --- /dev/null +++ b/src/main/java/systems/brn/server_storage/screens/SettingsScreen.java @@ -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 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(); + }) + ); + } +} diff --git a/src/main/java/systems/brn/server_storage/screens/StorageScreen.java b/src/main/java/systems/brn/server_storage/screens/StorageScreen.java index dfe622f..875e01c 100644 --- a/src/main/java/systems/brn/server_storage/screens/StorageScreen.java +++ b/src/main/java/systems/brn/server_storage/screens/StorageScreen.java @@ -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();