From 5d140c8ce0b9895b48da351d8b9f5427085ed462 Mon Sep 17 00:00:00 2001 From: Jottyfan Date: Sat, 3 Dec 2022 22:12:08 +0100 Subject: [PATCH] whitelist and blacklist filtering for blockstacker --- gradle.properties | 2 +- .../blockentity/BlockStackerEntity.java | 121 +++++++++++++----- .../container/BlockStackerScreen.java | 3 +- .../container/BlockStackerScreenHandler.java | 15 ++- .../textures/gui/blockstacker.png | Bin 0 -> 11057 bytes 5 files changed, 104 insertions(+), 37 deletions(-) create mode 100644 src/main/resources/assets/quickiefabric/textures/gui/blockstacker.png diff --git a/gradle.properties b/gradle.properties index aa00a65..3f699c2 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,7 +9,7 @@ loader_version=0.14.9 # Mod Properties - mod_version = 1.19.2.3 + mod_version = 1.19.2.4 maven_group = de.jottyfan.minecraft archives_base_name = quickiefabric diff --git a/src/main/java/de/jottyfan/minecraft/quickiefabric/blockentity/BlockStackerEntity.java b/src/main/java/de/jottyfan/minecraft/quickiefabric/blockentity/BlockStackerEntity.java index 1a865c2..476a199 100644 --- a/src/main/java/de/jottyfan/minecraft/quickiefabric/blockentity/BlockStackerEntity.java +++ b/src/main/java/de/jottyfan/minecraft/quickiefabric/blockentity/BlockStackerEntity.java @@ -1,7 +1,6 @@ package de.jottyfan.minecraft.quickiefabric.blockentity; import java.util.ArrayList; -import java.util.Iterator; import java.util.List; import org.apache.logging.log4j.LogManager; @@ -35,7 +34,7 @@ import net.minecraft.world.World; public class BlockStackerEntity extends BlockEntity implements NamedScreenHandlerFactory, ImplementedInventory { private static final Logger LOGGER = LogManager.getLogger(BlockStackerEntity.class); - private final DefaultedList inventory = DefaultedList.ofSize(9, ItemStack.EMPTY); + private final DefaultedList inventory = DefaultedList.ofSize(BlockStackerScreenHandler.SLOTSIZE, ItemStack.EMPTY); public BlockStackerEntity(BlockPos blockPos, BlockState blockState) { super(QuickieFabricBlockEntity.BLOCKSTACKER_ENTITY, blockPos, blockState); @@ -46,6 +45,30 @@ public class BlockStackerEntity extends BlockEntity implements NamedScreenHandle return inventory; } + public List getWhiteList() { + int counter = 0; + List list = new ArrayList<>(); + for (ItemStack stack : inventory) { + counter++; + if (counter < 10) { // first 9 items are whitelist items + list.add(stack); + } + } + return list; + } + + public List getBlackList() { + int counter = 0; + List list = new ArrayList<>(); + for (ItemStack stack : inventory) { + counter++; + if (counter > 9) { // second 9 items are blacklist items + list.add(stack); + } + } + return list; + } + @Override public ScreenHandler createMenu(int syncId, PlayerInventory playerInventory, PlayerEntity player) { return new BlockStackerScreenHandler(syncId, playerInventory, this); @@ -92,38 +115,57 @@ public class BlockStackerEntity extends BlockEntity implements NamedScreenHandle if (sourceIsLootable && destIsLootable) { LootableContainerBlockEntity lootableSource = (LootableContainerBlockEntity) source; LootableContainerBlockEntity lootableDest = (LootableContainerBlockEntity) dest; - List checked = new ArrayList<>(); - Boolean found = false; - Boolean whitelist = hasAnyItem(entity.getItems()); - if (whitelist) { - Item item = findNextItem(entity.getItems(), checked); - while(!found && item != null) { - checked.add(item); - found = transferOneStack(lootableSource, lootableDest, item, whitelist); - item = findNextItem(entity.getItems(), checked); - } - } else { - transferOneStack(lootableSource, lootableDest, null, whitelist); - } + transferOneStack(lootableSource, lootableDest, entity.getWhiteList(), entity.getBlackList()); } } } - private static final Boolean hasAnyItem(DefaultedList list) { - Iterator i = list.iterator(); - while (i.hasNext()) { - ItemStack s = i.next(); - if (s != null && s.getCount() > 0) { - return true; + private static final Boolean transferOneStack(LootableContainerBlockEntity source, LootableContainerBlockEntity dest, List whiteList, List blackList) { + + // whitelist behaviour + List checked = new ArrayList<>(); + + // this way, we block whitelist items that are in the blacklist + for (ItemStack stack : blackList) { + if (stack != null && !stack.isEmpty()) { + checked.add(stack.getItem()); } } - return false; + Boolean found = false; + + Item matchItem = findNextItem(whiteList, checked); + while(!found && matchItem != null) { + checked.add(matchItem); + List matchItems = new ArrayList<>(); + matchItems.add(matchItem); + found = transferOneStack(source, dest, matchItems, true, !hasItems(whiteList)); + matchItem = findNextItem(whiteList, checked); + } + + // blacklist behaviour + // for all the items that are not in the (already handled) whitelist and not in the blacklist, handle the transport + List ignoreItems = new ArrayList<>(); + for (ItemStack stack : blackList) { + if (stack != null && !stack.isEmpty()) { + ignoreItems.add(stack.getItem()); + } + } + for (ItemStack stack : whiteList) { + if (stack != null && !stack.isEmpty()) { + ignoreItems.add(stack.getItem()); + } + } + if (!found) { + found = transferOneStack(source, dest, ignoreItems, false, !hasItems(whiteList)); + } + + return found; } private static final Boolean transferOneStack(LootableContainerBlockEntity source, LootableContainerBlockEntity dest, - Item filterItem, Boolean whitelist) { + List ignoreItems, Boolean whitelist, Boolean emptyWhitelist) { Boolean result = false; - Integer sourceSlot = findItemStackPos(source, filterItem, whitelist); + Integer sourceSlot = findItemStackPos(source, ignoreItems, whitelist, emptyWhitelist); if (sourceSlot != null && !Items.AIR.equals(source.getStack(sourceSlot).getItem())) { ItemStack sourceStack = source.getStack(sourceSlot); Integer destSlot = findItemStackPos(dest, sourceStack); @@ -155,6 +197,14 @@ public class BlockStackerEntity extends BlockEntity implements NamedScreenHandle return result; } + private static final Boolean hasItems(List list) { + Boolean result = false; + for (ItemStack stack : list) { + result = result || (stack != null && !stack.isEmpty() && stack.getCount() > 0); + } + return result; + } + private static final Item findNextItem(List inventory, List exclude) { for (ItemStack stack : inventory) { if (!stack.isEmpty()) { @@ -193,19 +243,26 @@ public class BlockStackerEntity extends BlockEntity implements NamedScreenHandle return null; } - private static final Integer findItemStackPos(LootableContainerBlockEntity lcbe, Item item, Boolean whitelist) { - if (item == null) { - return findItemStackPos(lcbe, false); - } else { - if (whitelist == null) { - whitelist = true; - LOGGER.error("whitelist is null"); + private static final Integer findItemStackPos(LootableContainerBlockEntity lcbe, List filterItems, Boolean whitelist, Boolean emptyWhitelist) { + if (whitelist == null) { + whitelist = true; + LOGGER.error("whitelist is null"); + } + if (filterItems == null || filterItems.size() < 1) { + if (whitelist) { + return null; + } else if (emptyWhitelist) { + return findItemStackPos(lcbe, false); + } else { + LOGGER.error("no filter items, but whitelist is not empty"); + return null; } + } else { Integer counter = lcbe.size(); while (counter > 0) { counter--; ItemStack stack = lcbe.getStack(counter); - Boolean found = whitelist ? item.equals(stack.getItem()) : true; + Boolean found = whitelist ? filterItems.contains(stack.getItem()) : (!emptyWhitelist && !filterItems.contains(stack.getItem())); if (found) { return counter; } diff --git a/src/main/java/de/jottyfan/minecraft/quickiefabric/container/BlockStackerScreen.java b/src/main/java/de/jottyfan/minecraft/quickiefabric/container/BlockStackerScreen.java index 4a406ea..9051544 100644 --- a/src/main/java/de/jottyfan/minecraft/quickiefabric/container/BlockStackerScreen.java +++ b/src/main/java/de/jottyfan/minecraft/quickiefabric/container/BlockStackerScreen.java @@ -2,6 +2,7 @@ package de.jottyfan.minecraft.quickiefabric.container; import com.mojang.blaze3d.systems.RenderSystem; +import de.jottyfan.minecraft.quickiefabric.init.RegistryManager; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.minecraft.client.gui.screen.ingame.HandledScreen; @@ -20,7 +21,7 @@ import net.minecraft.util.Identifier; @Environment(EnvType.CLIENT) public class BlockStackerScreen extends HandledScreen implements ScreenHandlerProvider { - private final static Identifier TEXTURE = new Identifier("minecraft", "textures/gui/container/dispenser.png"); + private final static Identifier TEXTURE = new Identifier(RegistryManager.QUICKIEFABRIC, "textures/gui/blockstacker.png"); public BlockStackerScreen(BlockStackerScreenHandler handler, PlayerInventory inventory, Text text) { super(handler, inventory, text); diff --git a/src/main/java/de/jottyfan/minecraft/quickiefabric/container/BlockStackerScreenHandler.java b/src/main/java/de/jottyfan/minecraft/quickiefabric/container/BlockStackerScreenHandler.java index 71c0054..68d9431 100644 --- a/src/main/java/de/jottyfan/minecraft/quickiefabric/container/BlockStackerScreenHandler.java +++ b/src/main/java/de/jottyfan/minecraft/quickiefabric/container/BlockStackerScreenHandler.java @@ -16,7 +16,7 @@ import net.minecraft.screen.slot.Slot; */ public class BlockStackerScreenHandler extends ScreenHandler { - public static final Integer SLOTSIZE = 9; + public static final Integer SLOTSIZE = 18; private final Inventory inventory; @@ -31,14 +31,23 @@ public class BlockStackerScreenHandler extends ScreenHandler { inventory.onOpen(playerInventory.player); int m; int l; + // whitelist for (m = 0; m < 3; ++m) { for (l = 0; l < 3; ++l) { - this.addSlot(new Slot(inventory, l + m * 3, 62 + l * 18, 17 + m * 18)); + this.addSlot(new Slot(inventory, l + m * 3, 8 + l * 18, 17 + m * 18)); } } + + // blacklist + for (m = 0; m < 3; ++m) { + for (l = 0; l < 3; ++l) { + this.addSlot(new Slot(inventory, l + m * 3 + 9, 116 + l * 18, 17 + m * 18)); + } + } + for (m = 0; m < 3; ++m) { for (l = 0; l < 9; ++l) { - this.addSlot(new Slot(playerInventory, l + m * 9 + 9, 8 + l * 18, 84 + m * 18)); + this.addSlot(new Slot(playerInventory, l + m * 9 + 18, 8 + l * 18, 84 + m * 18)); } } for (m = 0; m < 9; ++m) { diff --git a/src/main/resources/assets/quickiefabric/textures/gui/blockstacker.png b/src/main/resources/assets/quickiefabric/textures/gui/blockstacker.png new file mode 100644 index 0000000000000000000000000000000000000000..dba71b604729f7671ed3179dfd3f955caa0e0026 GIT binary patch literal 11057 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 literal 0 HcmV?d00001