From d28bff3fcff00306b0385ec82975087160c92cf1 Mon Sep 17 00:00:00 2001 From: Ellpeck Date: Sat, 18 Apr 2020 22:30:14 +0200 Subject: [PATCH] added stack size module --- .../java/de/ellpeck/prettypipes/Registry.java | 23 ++++-- .../de/ellpeck/prettypipes/items/IModule.java | 2 + .../ellpeck/prettypipes/items/ModuleItem.java | 6 ++ .../ellpeck/prettypipes/misc/ItemFilter.java | 8 +- .../prettypipes/packets/PacketButton.java | 16 ++++ .../prettypipes/pipe/PipeTileEntity.java | 10 ++- .../stacksize/StackSizeModuleContainer.java | 19 +++++ .../modules/stacksize/StackSizeModuleGui.java | 56 +++++++++++++ .../stacksize/StackSizeModuleItem.java | 77 ++++++++++++++++++ .../assets/prettypipes/lang/en_us.json | 7 +- .../models/item/stack_size_module.json | 6 ++ .../textures/item/stack_size_module.png | Bin 0 -> 380 bytes .../recipes/stack_size_module.json | 22 +++++ 13 files changed, 234 insertions(+), 18 deletions(-) create mode 100644 src/main/java/de/ellpeck/prettypipes/pipe/modules/stacksize/StackSizeModuleContainer.java create mode 100644 src/main/java/de/ellpeck/prettypipes/pipe/modules/stacksize/StackSizeModuleGui.java create mode 100644 src/main/java/de/ellpeck/prettypipes/pipe/modules/stacksize/StackSizeModuleItem.java create mode 100644 src/main/resources/assets/prettypipes/models/item/stack_size_module.json create mode 100644 src/main/resources/assets/prettypipes/textures/item/stack_size_module.png create mode 100644 src/main/resources/data/prettypipes/recipes/stack_size_module.json diff --git a/src/main/java/de/ellpeck/prettypipes/Registry.java b/src/main/java/de/ellpeck/prettypipes/Registry.java index 3893f64..0742d4c 100644 --- a/src/main/java/de/ellpeck/prettypipes/Registry.java +++ b/src/main/java/de/ellpeck/prettypipes/Registry.java @@ -19,6 +19,9 @@ import de.ellpeck.prettypipes.pipe.modules.insertion.FilterModuleItem; import de.ellpeck.prettypipes.pipe.modules.retrieval.RetrievalModuleContainer; import de.ellpeck.prettypipes.pipe.modules.retrieval.RetrievalModuleGui; import de.ellpeck.prettypipes.pipe.modules.retrieval.RetrievalModuleItem; +import de.ellpeck.prettypipes.pipe.modules.stacksize.StackSizeModuleContainer; +import de.ellpeck.prettypipes.pipe.modules.stacksize.StackSizeModuleGui; +import de.ellpeck.prettypipes.pipe.modules.stacksize.StackSizeModuleItem; import net.minecraft.block.Block; import net.minecraft.client.gui.ScreenManager; import net.minecraft.client.renderer.RenderType; @@ -73,6 +76,7 @@ public final class Registry { public static ContainerType extractionModuleContainer; public static ContainerType filterModuleContainer; public static ContainerType retrievalModuleContainer; + public static ContainerType stackSizeModuleContainer; @SubscribeEvent public static void registerBlocks(RegistryEvent.Register event) { @@ -93,6 +97,7 @@ public final class Registry { registry.registerAll(createTieredModule("speed_module", SpeedModuleItem::new)); registry.registerAll(createTieredModule("low_priority_module", LowPriorityModuleItem::new)); registry.registerAll(createTieredModule("retrieval_module", RetrievalModuleItem::new)); + registry.register(new StackSizeModuleItem("stack_size_module")); ForgeRegistries.BLOCKS.getValues().stream() .filter(b -> b.getRegistryName().getNamespace().equals(PrettyPipes.ID)) @@ -113,7 +118,8 @@ public final class Registry { pipeContainer = (ContainerType) IForgeContainerType.create((windowId, inv, data) -> new MainPipeContainer(pipeContainer, windowId, inv.player, data.readBlockPos())).setRegistryName("pipe"), extractionModuleContainer = createPipeContainer("extraction_module"), filterModuleContainer = createPipeContainer("filter_module"), - retrievalModuleContainer = createPipeContainer("retrieval_module") + retrievalModuleContainer = createPipeContainer("retrieval_module"), + stackSizeModuleContainer = createPipeContainer("stack_size_module") ); } @@ -126,6 +132,13 @@ public final class Registry { }).setRegistryName(name); } + private static Item[] createTieredModule(String name, BiFunction item) { + List items = new ArrayList<>(); + for (ModuleTier tier : ModuleTier.values()) + items.add(item.apply(name, tier).setRegistryName(tier.name().toLowerCase(Locale.ROOT) + "_" + name)); + return items.toArray(new Item[0]); + } + public static void setup(FMLCommonSetupEvent event) { CapabilityManager.INSTANCE.register(PipeNetwork.class, new Capability.IStorage() { @Nullable @@ -142,13 +155,6 @@ public final class Registry { PacketHandler.setup(); } - private static Item[] createTieredModule(String name, BiFunction item) { - List items = new ArrayList<>(); - for (ModuleTier tier : ModuleTier.values()) - items.add(item.apply(name, tier).setRegistryName(tier.name().toLowerCase(Locale.ROOT) + "_" + name)); - return items.toArray(new Item[0]); - } - public static final class Client { public static void setup(FMLClientSetupEvent event) { RenderTypeLookup.setRenderLayer(pipeBlock, RenderType.cutout()); @@ -158,6 +164,7 @@ public final class Registry { ScreenManager.registerFactory(extractionModuleContainer, ExtractionModuleGui::new); ScreenManager.registerFactory(filterModuleContainer, FilterModuleGui::new); ScreenManager.registerFactory(retrievalModuleContainer, RetrievalModuleGui::new); + ScreenManager.registerFactory(stackSizeModuleContainer, StackSizeModuleGui::new); } } } diff --git a/src/main/java/de/ellpeck/prettypipes/items/IModule.java b/src/main/java/de/ellpeck/prettypipes/items/IModule.java index fddb3b7..b9542e9 100644 --- a/src/main/java/de/ellpeck/prettypipes/items/IModule.java +++ b/src/main/java/de/ellpeck/prettypipes/items/IModule.java @@ -15,6 +15,8 @@ public interface IModule { boolean canAcceptItem(ItemStack module, PipeTileEntity tile, ItemStack stack); + int getMaxInsertionAmount(ItemStack module, PipeTileEntity tile, ItemStack stack, IItemHandler destination); + int getPriority(ItemStack module, PipeTileEntity tile); boolean isCompatible(ItemStack module, PipeTileEntity tile, IModule other); diff --git a/src/main/java/de/ellpeck/prettypipes/items/ModuleItem.java b/src/main/java/de/ellpeck/prettypipes/items/ModuleItem.java index 6f099b5..72e96e3 100644 --- a/src/main/java/de/ellpeck/prettypipes/items/ModuleItem.java +++ b/src/main/java/de/ellpeck/prettypipes/items/ModuleItem.java @@ -15,6 +15,7 @@ import net.minecraft.util.text.*; import net.minecraft.world.World; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.items.IItemHandler; import javax.annotation.Nullable; import java.util.List; @@ -56,6 +57,11 @@ public abstract class ModuleItem extends Item implements IModule { return true; } + @Override + public int getMaxInsertionAmount(ItemStack module, PipeTileEntity tile, ItemStack stack, IItemHandler destination) { + return Integer.MAX_VALUE; + } + @Override public int getPriority(ItemStack module, PipeTileEntity tile) { return 0; diff --git a/src/main/java/de/ellpeck/prettypipes/misc/ItemFilter.java b/src/main/java/de/ellpeck/prettypipes/misc/ItemFilter.java index 4882418..4530974 100644 --- a/src/main/java/de/ellpeck/prettypipes/misc/ItemFilter.java +++ b/src/main/java/de/ellpeck/prettypipes/misc/ItemFilter.java @@ -53,16 +53,12 @@ public class ItemFilter extends ItemStackHandler { if (this.canModifyWhitelist) { Supplier whitelistText = () -> I18n.format("info." + PrettyPipes.ID + "." + (this.isWhitelist ? "whitelist" : "blacklist")); buttons.add(new Button(x, y, 70, 20, whitelistText.get(), button -> { - PacketHandler.sendToServer(new PacketButton(this.pipe.getPos(), PacketButton.ButtonResult.FILTER_CHANGE, 0)); - this.onButtonPacket(0); + PacketButton.sendAndExecute(this.pipe.getPos(), PacketButton.ButtonResult.FILTER_CHANGE, 0); button.setMessage(whitelistText.get()); })); } if (this.canPopulateFromInventories) { - buttons.add(new Button(x + 72, y, 70, 20, I18n.format("info." + PrettyPipes.ID + ".populate"), button -> { - PacketHandler.sendToServer(new PacketButton(this.pipe.getPos(), PacketButton.ButtonResult.FILTER_CHANGE, 1)); - this.onButtonPacket(1); - }) { + buttons.add(new Button(x + 72, y, 70, 20, I18n.format("info." + PrettyPipes.ID + ".populate"), button -> PacketButton.sendAndExecute(this.pipe.getPos(), PacketButton.ButtonResult.FILTER_CHANGE, 1)) { @Override public void renderToolTip(int x, int y) { gui.renderTooltip(TextFormatting.GRAY + I18n.format("info." + PrettyPipes.ID + ".populate.description"), x, y); diff --git a/src/main/java/de/ellpeck/prettypipes/packets/PacketButton.java b/src/main/java/de/ellpeck/prettypipes/packets/PacketButton.java index 037e5bc..78b5d07 100644 --- a/src/main/java/de/ellpeck/prettypipes/packets/PacketButton.java +++ b/src/main/java/de/ellpeck/prettypipes/packets/PacketButton.java @@ -5,6 +5,9 @@ import de.ellpeck.prettypipes.items.IModule; import de.ellpeck.prettypipes.misc.ItemFilter; import de.ellpeck.prettypipes.misc.ItemFilter.IFilteredContainer; import de.ellpeck.prettypipes.pipe.PipeTileEntity; +import de.ellpeck.prettypipes.pipe.modules.containers.AbstractPipeContainer; +import de.ellpeck.prettypipes.pipe.modules.stacksize.StackSizeModuleItem; +import net.minecraft.client.Minecraft; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerInventory; import net.minecraft.entity.player.ServerPlayerEntity; @@ -63,6 +66,11 @@ public class PacketButton { ctx.get().setPacketHandled(true); } + public static void sendAndExecute(BlockPos pos, ButtonResult result, int... data) { + PacketHandler.sendToServer(new PacketButton(pos, result, data)); + result.action.accept(pos, data, Minecraft.getInstance().player); + } + public enum ButtonResult { PIPE_TAB((pos, data, player) -> { PipeTileEntity tile = Utility.getTileEntity(PipeTileEntity.class, player.world, pos); @@ -91,6 +99,14 @@ public class PacketButton { IFilteredContainer container = (IFilteredContainer) player.openContainer; ItemFilter filter = container.getFilter(); filter.onButtonPacket(data[0]); + }), + STACK_SIZE_MODULE_BUTTON((pos, data, player) -> { + AbstractPipeContainer container = (AbstractPipeContainer) player.openContainer; + StackSizeModuleItem.setLimitToMaxStackSize(container.moduleStack, !StackSizeModuleItem.getLimitToMaxStackSize(container.moduleStack)); + }), + STACK_SIZE_AMOUNT((pos, data, player) -> { + AbstractPipeContainer container = (AbstractPipeContainer) player.openContainer; + StackSizeModuleItem.setMaxStackSize(container.moduleStack, data[0]); }); public final TriConsumer action; diff --git a/src/main/java/de/ellpeck/prettypipes/pipe/PipeTileEntity.java b/src/main/java/de/ellpeck/prettypipes/pipe/PipeTileEntity.java index ac78093..93b5aac 100644 --- a/src/main/java/de/ellpeck/prettypipes/pipe/PipeTileEntity.java +++ b/src/main/java/de/ellpeck/prettypipes/pipe/PipeTileEntity.java @@ -13,8 +13,6 @@ import net.minecraft.inventory.container.INamedContainerProvider; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.nbt.CompoundNBT; -import net.minecraft.nbt.ListNBT; -import net.minecraft.nbt.NBTUtil; import net.minecraft.profiler.IProfiler; import net.minecraft.tileentity.ITickableTileEntity; import net.minecraft.tileentity.TileEntity; @@ -133,10 +131,16 @@ public class PipeTileEntity extends TileEntity implements INamedContainerProvide continue; if (!ItemHandlerHelper.insertItem(handler, stack, true).isEmpty()) continue; - if (preventOversending) { + int maxAmount = this.streamModules().mapToInt(m -> m.getRight().getMaxInsertionAmount(m.getLeft(), this, stack, handler)).min().orElse(Integer.MAX_VALUE); + if (maxAmount < stack.getCount()) + continue; + if (preventOversending || maxAmount < Integer.MAX_VALUE) { // these are the items that are currently in the pipes, going to this pipe int onTheWay = PipeNetwork.get(this.world).getItemsOnTheWay(this.pos, stack); if (onTheWay > 0) { + // check if any modules are limiting us + if (onTheWay + stack.getCount() > maxAmount) + continue; ItemStack copy = stack.copy(); copy.setCount(copy.getMaxStackSize()); // totalSpace will be the amount of items that fit into the attached container diff --git a/src/main/java/de/ellpeck/prettypipes/pipe/modules/stacksize/StackSizeModuleContainer.java b/src/main/java/de/ellpeck/prettypipes/pipe/modules/stacksize/StackSizeModuleContainer.java new file mode 100644 index 0000000..5fdedec --- /dev/null +++ b/src/main/java/de/ellpeck/prettypipes/pipe/modules/stacksize/StackSizeModuleContainer.java @@ -0,0 +1,19 @@ +package de.ellpeck.prettypipes.pipe.modules.stacksize; + +import de.ellpeck.prettypipes.pipe.modules.containers.AbstractPipeContainer; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.inventory.container.ContainerType; +import net.minecraft.util.math.BlockPos; + +import javax.annotation.Nullable; + +public class StackSizeModuleContainer extends AbstractPipeContainer { + public StackSizeModuleContainer(@Nullable ContainerType type, int id, PlayerEntity player, BlockPos pos, int moduleIndex) { + super(type, id, player, pos, moduleIndex); + } + + @Override + protected void addSlots() { + + } +} diff --git a/src/main/java/de/ellpeck/prettypipes/pipe/modules/stacksize/StackSizeModuleGui.java b/src/main/java/de/ellpeck/prettypipes/pipe/modules/stacksize/StackSizeModuleGui.java new file mode 100644 index 0000000..bb04597 --- /dev/null +++ b/src/main/java/de/ellpeck/prettypipes/pipe/modules/stacksize/StackSizeModuleGui.java @@ -0,0 +1,56 @@ +package de.ellpeck.prettypipes.pipe.modules.stacksize; + +import de.ellpeck.prettypipes.PrettyPipes; +import de.ellpeck.prettypipes.packets.PacketButton; +import de.ellpeck.prettypipes.packets.PacketButton.ButtonResult; +import de.ellpeck.prettypipes.packets.PacketHandler; +import de.ellpeck.prettypipes.pipe.modules.containers.AbstractPipeGui; +import net.minecraft.client.gui.widget.TextFieldWidget; +import net.minecraft.client.gui.widget.button.Button; +import net.minecraft.client.resources.I18n; +import net.minecraft.entity.player.PlayerInventory; +import net.minecraft.util.text.ITextComponent; + +import java.util.function.Supplier; + +public class StackSizeModuleGui extends AbstractPipeGui { + public StackSizeModuleGui(StackSizeModuleContainer screenContainer, PlayerInventory inv, ITextComponent titleIn) { + super(screenContainer, inv, titleIn); + } + + @Override + protected void init() { + super.init(); + TextFieldWidget textField = this.addButton(new TextFieldWidget(this.font, this.guiLeft + 7, this.guiTop + 17 + 32 + 10, 40, 20, "info." + PrettyPipes.ID + ".max_stack_size") { + @Override + public void writeText(String textToWrite) { + StringBuilder ret = new StringBuilder(); + for (char c : textToWrite.toCharArray()) { + if (Character.isDigit(c)) + ret.append(c); + } + super.writeText(ret.toString()); + } + }); + textField.setText(String.valueOf(StackSizeModuleItem.getMaxStackSize(this.container.moduleStack))); + textField.setMaxStringLength(4); + textField.setResponder(s -> { + if (s.isEmpty()) + return; + int amount = Integer.parseInt(s); + PacketButton.sendAndExecute(this.container.tile.getPos(), ButtonResult.STACK_SIZE_AMOUNT, amount); + }); + Supplier buttonText = () -> I18n.format("info." + PrettyPipes.ID + ".limit_to_max_" + (StackSizeModuleItem.getLimitToMaxStackSize(this.container.moduleStack) ? "on" : "off")); + this.addButton(new Button(this.guiLeft + 7, this.guiTop + 17 + 32 + 10 + 22, 120, 20, buttonText.get(), b -> { + PacketButton.sendAndExecute(this.container.tile.getPos(), ButtonResult.STACK_SIZE_MODULE_BUTTON); + b.setMessage(buttonText.get()); + })); + } + + @Override + protected void drawGuiContainerForegroundLayer(int mouseX, int mouseY) { + super.drawGuiContainerForegroundLayer(mouseX, mouseY); + this.font.drawString(I18n.format("info." + PrettyPipes.ID + ".max_stack_size") + ":", 7, 17 + 32, 4210752); + + } +} diff --git a/src/main/java/de/ellpeck/prettypipes/pipe/modules/stacksize/StackSizeModuleItem.java b/src/main/java/de/ellpeck/prettypipes/pipe/modules/stacksize/StackSizeModuleItem.java new file mode 100644 index 0000000..2a6e3f6 --- /dev/null +++ b/src/main/java/de/ellpeck/prettypipes/pipe/modules/stacksize/StackSizeModuleItem.java @@ -0,0 +1,77 @@ +package de.ellpeck.prettypipes.pipe.modules.stacksize; + +import de.ellpeck.prettypipes.Registry; +import de.ellpeck.prettypipes.items.IModule; +import de.ellpeck.prettypipes.items.ModuleItem; +import de.ellpeck.prettypipes.pipe.PipeTileEntity; +import de.ellpeck.prettypipes.pipe.modules.containers.AbstractPipeContainer; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.entity.player.PlayerInventory; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.CompoundNBT; +import net.minecraftforge.items.IItemHandler; + +public class StackSizeModuleItem extends ModuleItem { + + public StackSizeModuleItem(String name) { + super(name); + this.setRegistryName(name); + } + + public static int getMaxStackSize(ItemStack module) { + if (module.hasTag()) { + int amount = module.getTag().getInt("max_stack_size"); + if (amount > 0) + return amount; + } + return 64; + } + + public static void setMaxStackSize(ItemStack module, int amount) { + module.getOrCreateTag().putInt("max_stack_size", amount); + } + + public static boolean getLimitToMaxStackSize(ItemStack module) { + if (module.hasTag()) + return module.getTag().getBoolean("limit_to_max_stack_size"); + return false; + } + + public static void setLimitToMaxStackSize(ItemStack module, boolean yes) { + module.getOrCreateTag().putBoolean("limit_to_max_stack_size", yes); + } + + @Override + public int getMaxInsertionAmount(ItemStack module, PipeTileEntity tile, ItemStack stack, IItemHandler destination) { + int max = getMaxStackSize(module); + if (getLimitToMaxStackSize(module)) + max = Math.min(max, stack.getMaxStackSize()); + int amount = 0; + for (int i = 0; i < destination.getSlots(); i++) { + ItemStack stored = destination.getStackInSlot(i); + if (stored.isEmpty()) + continue; + if (!stored.isItemEqual(stack)) + continue; + amount += stored.getCount(); + if (amount >= max) + return 0; + } + return max - amount; + } + + @Override + public boolean isCompatible(ItemStack module, PipeTileEntity tile, IModule other) { + return !(other instanceof StackSizeModuleItem); + } + + @Override + public boolean hasContainer(ItemStack module, PipeTileEntity tile) { + return true; + } + + @Override + public AbstractPipeContainer getContainer(ItemStack module, PipeTileEntity tile, int windowId, PlayerInventory inv, PlayerEntity player, int moduleIndex) { + return new StackSizeModuleContainer(Registry.stackSizeModuleContainer, windowId, player, tile.getPos(), moduleIndex); + } +} diff --git a/src/main/resources/assets/prettypipes/lang/en_us.json b/src/main/resources/assets/prettypipes/lang/en_us.json index 1f8af69..30c7497 100644 --- a/src/main/resources/assets/prettypipes/lang/en_us.json +++ b/src/main/resources/assets/prettypipes/lang/en_us.json @@ -16,11 +16,13 @@ "item.prettypipes.low_retrieval_module": "Low Retrieval Module", "item.prettypipes.medium_retrieval_module": "Medium Retrieval Module", "item.prettypipes.high_retrieval_module": "High Retrieval Module", + "item.prettypipes.stack_size_module": "Stack Limiter Module", "info.prettypipes.extraction_module": "Pulls items from adjacent inventories\nFilters and pull rates vary by tier\nHigh tiers prevent over-sending", "info.prettypipes.filter_module": "Restricts flow from pipes into adjacent inventories\nFilter amount varies by tier", "info.prettypipes.speed_module": "Increases speed of items exiting adjacent inventories\nSpeed varies by tier", "info.prettypipes.low_priority_module": "Decreases the reception priority of adjacent inventories\nLower priority means items will prefer other inventories", "info.prettypipes.retrieval_module": "Pulls items from other inventories in the network\nFilters and pull rates vary by tier\nHigh tiers prevent over-sending", + "info.prettypipes.stack_size_module": "Limits the amount of items that can enter adjacent inventories\nAutomatically prevents over-sending", "block.prettypipes.pipe": "Pipe", "itemGroup.prettypipes": "Pretty Pipes", "container.prettypipes.pipe": "Pipe", @@ -28,5 +30,8 @@ "info.prettypipes.blacklist": "Disallowed", "info.prettypipes.shift": "Hold Shift for info", "info.prettypipes.populate": "Populate", - "info.prettypipes.populate.description": "Filters items from adjacent inventories" + "info.prettypipes.populate.description": "Filters items from adjacent inventories", + "info.prettypipes.max_stack_size": "Maximum item amount", + "info.prettypipes.limit_to_max_on": "Limit to one stack", + "info.prettypipes.limit_to_max_off": "Don't limit to one stack" } \ No newline at end of file diff --git a/src/main/resources/assets/prettypipes/models/item/stack_size_module.json b/src/main/resources/assets/prettypipes/models/item/stack_size_module.json new file mode 100644 index 0000000..66d78b4 --- /dev/null +++ b/src/main/resources/assets/prettypipes/models/item/stack_size_module.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "prettypipes:item/stack_size_module" + } +} diff --git a/src/main/resources/assets/prettypipes/textures/item/stack_size_module.png b/src/main/resources/assets/prettypipes/textures/item/stack_size_module.png new file mode 100644 index 0000000000000000000000000000000000000000..6d0f62374e658556682ad86331088533a67a787a GIT binary patch literal 380 zcmV-?0fYXDP)Px$Hc3Q5R5*>LlQB!fP!Pv|fjk-;tEt){)Isob2(E%d7Y7j+$9@KpQu-N!i-L+c z+M!TKzk;}0yC_xDhMR^_}t?hy$0rgsS z@Ye3kG`acMq*SgbYBV8Kk=W?>{ZJeN2vxB9eJkTe%Vyoo$@nR?iBLrdGNz!>vN3cG z*ZZR9c4+{HuKgx+(dr3+pxDqgdTtlfSdzKI-aY_VmlyGX)^nQ|=aW~*1K{q#=J@&^ z0L!ufm=6?90+{&~%sebFWY{=32{mRHGXTjum=kFLI`1E{u~;mQNsoVm>qtNC-C*b% zLyiQUpPj}7QfoV*xCdm1{?r}#eLwV(c86P!TB3r{1qBnMHmX1#Q|ah%rei9VE6Vh$ aKiCh09b(77$AmWk0000