Improve crafting screen
This commit is contained in:
		| @@ -11,7 +11,7 @@ loader_version=0.16.0 | ||||
| fabric_version=0.102.1+1.21.1 | ||||
|  | ||||
| # Mod Properties | ||||
| mod_version=3.2.6 | ||||
| mod_version=3.2.9 | ||||
| maven_group=systems.brn | ||||
| archives_base_name=Serverstorage | ||||
|  | ||||
|   | ||||
| @@ -15,14 +15,20 @@ public class CraftingEntry { | ||||
|     public final ArrayList<ItemStack> outputStacks; | ||||
|     public final RecipeEntry<CraftingRecipe> recipeEntry; | ||||
|     public final ArrayList<RecipeEntry<CraftingRecipe>> myCraftingRecipeEntries; | ||||
|     public final int totalMax; | ||||
|     public final int eachCraft; | ||||
|     public final int maxCrafts; | ||||
|  | ||||
|     public CraftingEntry(ItemStack itemStack, RecipeEntry<CraftingRecipe> recipeEntry, HashMap<ItemStack, Integer> inputs, Integer maxCount) { | ||||
|         maxCrafts = maxCount; | ||||
|         eachCraft = itemStack.getCount(); | ||||
|         totalMax = eachCraft * maxCrafts; | ||||
|         ArrayList<ItemStack> tempOutputStacks = new ArrayList<>(); | ||||
|         ItemStack outputStack = itemStack.copy(); | ||||
|         outputStack.setCount(maxCount); | ||||
|         outputStack = addCountToLore(itemStack.getCount() * maxCount, outputStack, "Total max: "); | ||||
|         outputStack = addCountToLore(itemStack.getCount(), outputStack, "Each craft: "); | ||||
|         outputStack = addCountToLore(maxCount, outputStack, "Max crafts: "); | ||||
|         outputStack = addCountToLore(totalMax, outputStack, "Total max: "); | ||||
|         outputStack = addCountToLore(eachCraft, outputStack, "Each craft: "); | ||||
|         outputStack = addCountToLore(maxCrafts, outputStack, "Max crafts: "); | ||||
|         tempOutputStacks.add(outputStack); | ||||
|         for (Map.Entry<ItemStack, Integer> entry : inputs.entrySet()) { | ||||
|             ItemStack stackIn = entry.getKey(); | ||||
|   | ||||
| @@ -0,0 +1,5 @@ | ||||
| package systems.brn.serverstorage.lib; | ||||
|  | ||||
| public interface Searchable { | ||||
|     public void doSearch(String searchText); | ||||
| } | ||||
| @@ -6,9 +6,7 @@ import net.minecraft.item.Item; | ||||
| import net.minecraft.item.ItemStack; | ||||
| import org.jetbrains.annotations.NotNull; | ||||
|  | ||||
| import java.util.HashMap; | ||||
| import java.util.Map; | ||||
| import java.util.TreeMap; | ||||
| import java.util.*; | ||||
|  | ||||
| public class StorageOperations { | ||||
|     // Modify getSimpleInventory to include item metadata and sort conditionally | ||||
| @@ -20,7 +18,7 @@ public class StorageOperations { | ||||
|         } else { | ||||
|             Map<ItemStack, Integer> filteredMap = new HashMap<>(); | ||||
|             for (Map.Entry<ItemStack, Integer> entry : itemStackMap.entrySet()) { | ||||
|                 if (filterItem(entry.getKey().getItem(), query)){ | ||||
|                 if (filterItem(entry.getKey().getItem(), query)) { | ||||
|                     ItemStack stack = entry.getKey(); | ||||
|                     stack.setCount(Math.min(entry.getValue(), stack.getMaxCount())); | ||||
|                     filteredMap.put(stack, entry.getValue()); | ||||
| @@ -31,7 +29,24 @@ public class StorageOperations { | ||||
|         return sortedMap; | ||||
|     } | ||||
|  | ||||
|     public static boolean filterItem(Item item, String query){ | ||||
|     public static TreeSet<CraftingEntry> sortAndFilterEntries(ArrayList<CraftingEntry> craftingEntries, boolean sortAlphabetically, String query) { | ||||
|         TreeSet<CraftingEntry> sortedSet = getTreeSetCraftingEntries(sortAlphabetically); | ||||
|  | ||||
|         if (query == null || query.isEmpty() || query.equals("*")) { | ||||
|             sortedSet.addAll(craftingEntries); | ||||
|         } else { | ||||
|             ArrayList<CraftingEntry> filteredSet = new ArrayList<>(); | ||||
|             for (CraftingEntry entry : craftingEntries) { | ||||
|                 if (!entry.outputStacks.isEmpty() && filterItem(entry.outputStacks.getFirst().getItem(), query)) { | ||||
|                     filteredSet.add(entry); | ||||
|                 } | ||||
|             } | ||||
|             sortedSet.addAll(filteredSet); | ||||
|         } | ||||
|         return sortedSet; | ||||
|     } | ||||
|  | ||||
|     public static boolean filterItem(Item item, String query) { | ||||
|         if (item != null) { | ||||
|             String itemName = String.valueOf(item); | ||||
|             return itemName == null || itemName.contains(query); | ||||
| @@ -62,6 +77,44 @@ public class StorageOperations { | ||||
|         return sortedMap; | ||||
|     } | ||||
|  | ||||
|     private static @NotNull TreeSet<CraftingEntry> getTreeSetCraftingEntries(boolean sortAlphabetically) { | ||||
|         TreeSet<CraftingEntry> sortedSet; | ||||
|  | ||||
|         if (sortAlphabetically) { | ||||
|             // Sort alphabetically by item name | ||||
|             sortedSet = new TreeSet<>((o1, o2) -> { | ||||
|                 if (o1.outputStacks.isEmpty()) { | ||||
|                     return 1; | ||||
|                 } else if (o2.outputStacks.isEmpty()) { | ||||
|                     return -1; | ||||
|                 } | ||||
|                 String name1 = String.valueOf(o1.outputStacks.getFirst().getItem()); | ||||
|                 String name2 = String.valueOf(o2.outputStacks.getFirst().getItem()); | ||||
|                 return name1.compareToIgnoreCase(name2); | ||||
|             }); | ||||
|         } else { | ||||
|             // Sort by count in descending order | ||||
|             sortedSet = new TreeSet<>((o1, o2) -> { | ||||
|                 if (o1.outputStacks.isEmpty()) { | ||||
|                     return 1; | ||||
|                 } else if (o2.outputStacks.isEmpty()) { | ||||
|                     return -1; | ||||
|                 } | ||||
|                 int count1 = o1.totalMax; | ||||
|                 int count2 = o2.totalMax; | ||||
|                 int countCompare = Integer.compare(count2, count1); | ||||
|                 // If counts are equal, compare items alphabetically by name | ||||
|                 if (countCompare == 0) { | ||||
|                     String name1 = String.valueOf(o1.outputStacks.getFirst().getItem()); | ||||
|                     String name2 = String.valueOf(o2.outputStacks.getFirst().getItem()); | ||||
|                     return name1.compareToIgnoreCase(name2); | ||||
|                 } | ||||
|                 return countCompare; | ||||
|             }); | ||||
|         } | ||||
|         return sortedSet; | ||||
|     } | ||||
|  | ||||
|     public static int canInsertToStack(ItemStack stack1, ItemStack stack2, int maxInsert) { | ||||
|         if (stack1.isEmpty() || ItemStack.areItemsEqual(stack1, stack2)) { | ||||
|             int remainingSpace = stack1.isEmpty() ? stack2.getMaxCount() : stack1.getMaxCount() - stack1.getCount(); | ||||
| @@ -145,7 +198,7 @@ public class StorageOperations { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public static int howMuchFits(ItemStack stack, Inventory inventory){ | ||||
|     public static int howMuchFits(ItemStack stack, Inventory inventory) { | ||||
|         int out = 0; | ||||
|         for (int i = 0; i < inventory.size(); i++) { | ||||
|             ItemStack slotStack = inventory.getStack(i); | ||||
|   | ||||
| @@ -5,27 +5,30 @@ import net.minecraft.entity.player.PlayerEntity; | ||||
| import net.minecraft.entity.player.PlayerInventory; | ||||
| import net.minecraft.inventory.Inventory; | ||||
| import net.minecraft.item.ItemStack; | ||||
| import net.minecraft.item.Items; | ||||
| import net.minecraft.recipe.CraftingRecipe; | ||||
| import net.minecraft.recipe.Ingredient; | ||||
| import net.minecraft.recipe.RecipeEntry; | ||||
| import net.minecraft.text.Text; | ||||
| import net.minecraft.util.Formatting; | ||||
| import systems.brn.serverstorage.blockentities.StorageInterfaceBlockEntity; | ||||
| import systems.brn.serverstorage.lib.CraftingEntry; | ||||
| import systems.brn.serverstorage.lib.PagedGui; | ||||
| import systems.brn.serverstorage.lib.Searchable; | ||||
| import systems.brn.serverstorage.lib.WirelessTerminalComponents; | ||||
|  | ||||
| import java.util.ArrayList; | ||||
| import java.util.HashMap; | ||||
| import java.util.Map; | ||||
| import java.util.Objects; | ||||
| import java.util.*; | ||||
|  | ||||
| import static systems.brn.serverstorage.lib.StorageOperations.*; | ||||
| import static systems.brn.serverstorage.lib.Util.getCraftableRecipes; | ||||
|  | ||||
| public class CraftingScreen extends PagedGui { | ||||
| public class CraftingScreen extends PagedGui implements Searchable { | ||||
|     private final StorageScreen storageScreen; | ||||
|     private ArrayList<CraftingEntry> craftingEntries; | ||||
|     private final StorageInterfaceBlockEntity blockEntity; | ||||
|     private ArrayList<DisplayElement> recipesList; | ||||
|     public String searchQuery; | ||||
|     public boolean sortAlphabetically = false; | ||||
|  | ||||
|     public CraftingScreen(StorageScreen storageScreen) { | ||||
|         super(storageScreen.getPlayer(), null); | ||||
| @@ -57,36 +60,40 @@ public class CraftingScreen extends PagedGui { | ||||
|  | ||||
|     private ArrayList<DisplayElement> getAvailableRecipes() { | ||||
|         ArrayList<DisplayElement> recipes = new ArrayList<>(); | ||||
|  | ||||
|         for (CraftingEntry craftingEntry : craftingEntries) { | ||||
|         TreeSet<CraftingEntry> filteredCraftingEntries = sortAndFilterEntries(craftingEntries, getAlphabeticalSorting(), getQueryString()); | ||||
|         for (CraftingEntry craftingEntry : filteredCraftingEntries) { | ||||
|             ItemStack stackWithCount = craftingEntry.outputStacks.getFirst().copy(); | ||||
|             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; | ||||
|             if (stackWithCount.getItem() != null && filterItem(stackWithCount.getItem(), getQueryString())) { | ||||
|                 recipes.add( | ||||
|                         DisplayElement.of(new GuiElementBuilder(stackWithCount) | ||||
|                                 .setCallback((i, clickType, slotActionType) -> { | ||||
|                                     if (storageScreen.checkDistance()) { | ||||
|                                         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 | ||||
|                                         craftOne(player, recipeEntry, true); | ||||
|                                         // 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 | ||||
|                                                 craftOne(player, recipeEntry, true); | ||||
|                                             } | ||||
|                                         } else if (clickType.isRight) { // put back into storage | ||||
|                                             if (clickType.shift) { // craft all | ||||
|                                                 craftAll(player, recipeEntry, false); | ||||
|                                             } else { // craft one | ||||
|                                                 craftOne(player, recipeEntry, false); | ||||
|                                             } | ||||
|                                         } | ||||
|                                         updateDisplay(); | ||||
|                                     } | ||||
|                                 } else if (clickType.isRight) { // put back into storage | ||||
|                                     if (clickType.shift) { // craft all | ||||
|                                         craftAll(player, recipeEntry, false); | ||||
|                                     } else { // craft one | ||||
|                                         craftOne(player, recipeEntry, false); | ||||
|                                     } | ||||
|                                 } | ||||
|                                 updateDisplay(); | ||||
|                             }) | ||||
|                     ) | ||||
|             ); | ||||
|                                 }) | ||||
|                         ) | ||||
|                 ); | ||||
|             } | ||||
|         } | ||||
|         return recipes; | ||||
|     } | ||||
| @@ -110,6 +117,7 @@ public class CraftingScreen extends PagedGui { | ||||
|     } | ||||
|  | ||||
|     private boolean craftOne(PlayerEntity player, RecipeEntry<CraftingRecipe> recipeEntry, boolean toPlayerInventory) { | ||||
|         this.storageScreen.refreshTerminals(); | ||||
|         ArrayList<ItemStack> stacksToRemove = new ArrayList<>(); | ||||
|  | ||||
|         // Check and remove ingredients for one crafting operation | ||||
| @@ -190,6 +198,55 @@ public class CraftingScreen extends PagedGui { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public String getQueryString() { | ||||
|         if (blockEntity == null) { | ||||
|             return storageScreen.itemStack.getOrDefault(WirelessTerminalComponents.QUERY_STRING, ""); | ||||
|         } else { | ||||
|             return blockEntity.searchString == null ? "*" : blockEntity.searchString; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public void setQueryString(String queryString) { | ||||
|         if (blockEntity == null) { | ||||
|             storageScreen.itemStack.set(WirelessTerminalComponents.QUERY_STRING, queryString); | ||||
|         } else { | ||||
|             blockEntity.searchString = queryString; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public boolean getAlphabeticalSorting() { | ||||
|         if (blockEntity == null) { | ||||
|             return storageScreen.itemStack.getOrDefault(WirelessTerminalComponents.SORT_ALPHABETICALLY, false); | ||||
|         } else { | ||||
|             return blockEntity.sortAlphabetically; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public void setAlphabeticalSorting(boolean sorting) { | ||||
|         if (blockEntity == null) { | ||||
|             storageScreen.itemStack.set(WirelessTerminalComponents.SORT_ALPHABETICALLY, sorting); | ||||
|         } else { | ||||
|             blockEntity.sortAlphabetically = sorting; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     protected DisplayElement sorting() { | ||||
|         return DisplayElement.of( | ||||
|                 new GuiElementBuilder(Items.PLAYER_HEAD) | ||||
|                         .setName(Text.translatable(getAlphabeticalSorting() ? "A->Z" : "9->1").formatted(Formatting.WHITE)) | ||||
|                         .hideDefaultTooltip().noDefaults() | ||||
|                         .setSkullOwner(getAlphabeticalSorting() ? GUI_A : GUI_1) | ||||
|                         .setCallback((x, y, z) -> { | ||||
|                             playClickSound(getPlayer()); | ||||
|                             if (storageScreen.checkDistance()) { | ||||
|                                 setAlphabeticalSorting(!getAlphabeticalSorting()); | ||||
|                                 updateDisplay(); | ||||
|                             } | ||||
|                         }) | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public boolean open() { | ||||
|         if (this.blockEntity != null) { | ||||
| @@ -225,4 +282,35 @@ public class CraftingScreen extends PagedGui { | ||||
|             return DisplayElement.empty(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void doSearch(String searchText) { | ||||
|         setQueryString(searchText); | ||||
|         this.updateDisplay(); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     protected DisplayElement search() { | ||||
|         String searchString = getQueryString(); | ||||
|         if (searchString == null || searchString.isEmpty() || searchString.equals("*")) { | ||||
|             searchString = "Filter not set"; | ||||
|         } | ||||
|         return DisplayElement.of( | ||||
|                 new GuiElementBuilder(Items.PLAYER_HEAD) | ||||
|                         .setName(Text.literal(searchString).formatted(Formatting.WHITE)) | ||||
|                         .hideDefaultTooltip().noDefaults() | ||||
|                         .setSkullOwner(GUI_QUESTION_MARK) | ||||
|                         .setCallback((x, y, z) -> { | ||||
|                             playClickSound(getPlayer()); | ||||
|                             if (storageScreen.checkDistance()) { | ||||
|                                 if (y.isRight) { | ||||
|                                     doSearch(""); | ||||
|                                 } else if (y.isLeft) { | ||||
|                                     SearchScreen searchScreen = new SearchScreen(this, ""); | ||||
|                                     searchScreen.open(); | ||||
|                                 } | ||||
|                             } | ||||
|                         }) | ||||
|         ); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -3,6 +3,7 @@ package systems.brn.serverstorage.screens; | ||||
| import eu.pb4.sgui.api.gui.AnvilInputGui; | ||||
| import eu.pb4.sgui.api.gui.SimpleGui; | ||||
| import systems.brn.serverstorage.blockentities.InventoryInterfaceBlockEntity; | ||||
| import systems.brn.serverstorage.lib.Searchable; | ||||
|  | ||||
| public class SearchScreen extends AnvilInputGui { | ||||
|  | ||||
| @@ -20,10 +21,11 @@ public class SearchScreen extends AnvilInputGui { | ||||
|         super.onClose(); | ||||
|         parentScreen.open(); | ||||
|         String query = this.getInput(); | ||||
|         if (parentScreen instanceof StorageScreen storageScreen) { | ||||
|             storageScreen.doSearch(query); | ||||
|         } else if (parentScreen instanceof SettingsScreen settingsScreen && settingsScreen.blockEntity instanceof InventoryInterfaceBlockEntity inventoryInterfaceBlockEntity) { | ||||
|             inventoryInterfaceBlockEntity.doSearch(query); | ||||
|         if (parentScreen instanceof Searchable searchable) { | ||||
|             searchable.doSearch(query); | ||||
|             if (parentScreen instanceof SettingsScreen settingsScreen && settingsScreen.blockEntity instanceof InventoryInterfaceBlockEntity inventoryInterfaceBlockEntity) { | ||||
|                 inventoryInterfaceBlockEntity.doSearch(query); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -10,10 +10,11 @@ import net.minecraft.util.Formatting; | ||||
| import org.jetbrains.annotations.Nullable; | ||||
| import systems.brn.serverstorage.blockentities.InventoryInterfaceBlockEntity; | ||||
| import systems.brn.serverstorage.lib.PagedGui; | ||||
| import systems.brn.serverstorage.lib.Searchable; | ||||
|  | ||||
| import java.util.ArrayList; | ||||
|  | ||||
| public class SettingsScreen extends PagedGui { | ||||
| public class SettingsScreen extends PagedGui implements Searchable { | ||||
|  | ||||
|     private final SimpleGui parentScreen; | ||||
|  | ||||
| @@ -33,6 +34,10 @@ public class SettingsScreen extends PagedGui { | ||||
|         this.updateDisplay(); | ||||
|     } | ||||
|  | ||||
|     public void doSearch(String query) { | ||||
|  | ||||
|     } | ||||
|  | ||||
|     public SettingsScreen(StorageScreen parentScreen) { | ||||
|         this(parentScreen, parentScreen.getPlayer(), parentScreen.blockEntity); | ||||
|     } | ||||
|   | ||||
| @@ -17,10 +17,7 @@ import net.minecraft.util.math.BlockPos; | ||||
| import org.jetbrains.annotations.Nullable; | ||||
| import systems.brn.serverstorage.blockentities.RadioInterfaceBlockEntity; | ||||
| import systems.brn.serverstorage.blockentities.StorageInterfaceBlockEntity; | ||||
| import systems.brn.serverstorage.lib.PagedGui; | ||||
| import systems.brn.serverstorage.lib.RadioDistance; | ||||
| import systems.brn.serverstorage.lib.StorageNetwork; | ||||
| import systems.brn.serverstorage.lib.WirelessTerminalComponents; | ||||
| import systems.brn.serverstorage.lib.*; | ||||
|  | ||||
| import java.util.Map; | ||||
|  | ||||
| @@ -30,7 +27,7 @@ import static systems.brn.serverstorage.lib.StorageOperations.*; | ||||
| import static systems.brn.serverstorage.lib.Util.addCountToLore; | ||||
| import static systems.brn.serverstorage.lib.Util.removeCountFromLore; | ||||
|  | ||||
| public class StorageScreen extends PagedGui { | ||||
| public class StorageScreen extends PagedGui implements Searchable { | ||||
|     private final ServerPlayerEntity player; | ||||
|     public final StorageInterfaceBlockEntity blockEntity; | ||||
|     public final StorageNetwork network; | ||||
| @@ -249,7 +246,7 @@ public class StorageScreen extends PagedGui { | ||||
|     } | ||||
|  | ||||
|     public void insertItem(ItemStack stack, boolean isCursor) { | ||||
|         if (!checkDistance()) { | ||||
|         if (!checkDistance() || stack.getItem() == itemStack.getItem()) { | ||||
|             return; | ||||
|         } | ||||
|         int canPutIn = stack.getCount() - getNetwork().putItemStackRemainder(stack); | ||||
|   | ||||
| @@ -11,10 +11,7 @@ import net.minecraft.util.Formatting; | ||||
| import net.minecraft.util.math.BlockPos; | ||||
| import org.jetbrains.annotations.Nullable; | ||||
| import systems.brn.serverstorage.items.WirelessTerminalItem; | ||||
| import systems.brn.serverstorage.lib.PagedGui; | ||||
| import systems.brn.serverstorage.lib.SessionStorageClass; | ||||
| import systems.brn.serverstorage.lib.Util; | ||||
| import systems.brn.serverstorage.lib.WirelessTerminalComponents; | ||||
| import systems.brn.serverstorage.lib.*; | ||||
|  | ||||
| import java.util.ArrayList; | ||||
| import java.util.List; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user