aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/gregtech/common/tileentities/automation
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/gregtech/common/tileentities/automation')
-rw-r--r--src/main/java/gregtech/common/tileentities/automation/GT_MetaTileEntity_ChestBuffer.java137
-rw-r--r--src/main/java/gregtech/common/tileentities/automation/GT_MetaTileEntity_Filter.java144
-rw-r--r--src/main/java/gregtech/common/tileentities/automation/GT_MetaTileEntity_ItemDistributor.java204
-rw-r--r--src/main/java/gregtech/common/tileentities/automation/GT_MetaTileEntity_RecipeFilter.java326
-rw-r--r--src/main/java/gregtech/common/tileentities/automation/GT_MetaTileEntity_Regulator.java228
-rw-r--r--src/main/java/gregtech/common/tileentities/automation/GT_MetaTileEntity_SuperBuffer.java105
-rw-r--r--src/main/java/gregtech/common/tileentities/automation/GT_MetaTileEntity_TypeFilter.java213
7 files changed, 1357 insertions, 0 deletions
diff --git a/src/main/java/gregtech/common/tileentities/automation/GT_MetaTileEntity_ChestBuffer.java b/src/main/java/gregtech/common/tileentities/automation/GT_MetaTileEntity_ChestBuffer.java
new file mode 100644
index 0000000000..67c38fad9e
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/automation/GT_MetaTileEntity_ChestBuffer.java
@@ -0,0 +1,137 @@
+package gregtech.common.tileentities.automation;
+
+import static gregtech.api.enums.Textures.BlockIcons.AUTOMATION_CHESTBUFFER;
+import static gregtech.api.enums.Textures.BlockIcons.AUTOMATION_CHESTBUFFER_GLOW;
+
+import com.gtnewhorizons.modularui.api.screen.ModularWindow;
+import com.gtnewhorizons.modularui.api.screen.UIBuildContext;
+import com.gtnewhorizons.modularui.common.widget.DrawableWidget;
+
+import gregtech.api.gui.modularui.GT_UITextures;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Buffer;
+import gregtech.api.render.TextureFactory;
+
+public class GT_MetaTileEntity_ChestBuffer extends GT_MetaTileEntity_Buffer {
+
+ private static final int[] tickRate = { 400, 200, 100, 20, 4, 1, 1, 1, 1, 1, 1, 1, 1 };
+ private static final int[] maxStacks = { 1, 1, 1, 1, 1, 1, 2, 4, 8, 16, 32, 64, 128 };
+
+ public GT_MetaTileEntity_ChestBuffer(int aID, String aName, String aNameRegional, int aTier) {
+ super(
+ aID,
+ aName,
+ aNameRegional,
+ aTier,
+ 28,
+ new String[] { "Buffers up to 27 Item Stacks", "Use Screwdriver to regulate output stack size",
+ getTickRateDesc(aTier) });
+ }
+
+ public GT_MetaTileEntity_ChestBuffer(int aID, String aName, String aNameRegional, int aTier, int aInvSlotCount,
+ String aDescription) {
+ super(aID, aName, aNameRegional, aTier, aInvSlotCount, aDescription);
+ }
+
+ public GT_MetaTileEntity_ChestBuffer(int aID, String aName, String aNameRegional, int aTier, int aInvSlotCount,
+ String[] aDescription) {
+ super(aID, aName, aNameRegional, aTier, aInvSlotCount, aDescription);
+ }
+
+ public GT_MetaTileEntity_ChestBuffer(String aName, int aTier, int aInvSlotCount, String aDescription,
+ ITexture[][][] aTextures) {
+ super(aName, aTier, aInvSlotCount, aDescription, aTextures);
+ }
+
+ public GT_MetaTileEntity_ChestBuffer(String aName, int aTier, int aInvSlotCount, String[] aDescription,
+ ITexture[][][] aTextures) {
+ super(aName, aTier, aInvSlotCount, aDescription, aTextures);
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_ChestBuffer(
+ this.mName,
+ this.mTier,
+ this.mInventory.length,
+ this.mDescriptionArray,
+ this.mTextures);
+ }
+
+ @Override
+ public ITexture getOverlayIcon() {
+ return TextureFactory.of(
+ TextureFactory.of(AUTOMATION_CHESTBUFFER),
+ TextureFactory.builder()
+ .addIcon(AUTOMATION_CHESTBUFFER_GLOW)
+ .glow()
+ .build());
+ }
+
+ @Override
+ public boolean isValidSlot(int aIndex) {
+ return aIndex < this.mInventory.length - 1;
+ }
+
+ @Override
+ protected void moveItems(IGregTechTileEntity aBaseMetaTileEntity, long aTimer) {
+ if (aTimer % tickRate[mTier] > 0) return;
+
+ // mSuccess will be negative if the call is caused by the %200 aTimer, always try to push. Otherwise it will be
+ // positive.
+ // For the first 6 ticks after a successful move (49->44), push every tick. Then go to every 5 ticks.
+ if ((mSuccess <= 0) || (mSuccess > 43) || ((mSuccess % 5) == 0)) {
+ super.moveItems(aBaseMetaTileEntity, aTimer, Math.min(MAX, maxStacks[mTier]));
+ }
+
+ if (mSuccess < 0) {
+ mSuccess = 0;
+ }
+ }
+
+ protected static String getTickRateDesc(int tier) {
+ int tickRate = getTickRate(tier);
+ String timeStr = "";
+ String numStr = "";
+ if (maxStacks[tier] > 1) {
+ numStr = maxStacks[tier] + " items";
+ } else {
+ numStr = "1 item";
+ }
+ if (tickRate < 20) timeStr = "1/" + 20 / tickRate + " ";
+ else if (tickRate > 20) {
+ timeStr = (tickRate / 20) + "th ";
+ }
+ return "Moves " + numStr + " every " + timeStr + "second";
+ }
+
+ protected static int getTickRate(int tier) {
+ if (tier > 9) return 1;
+ return tickRate[tier];
+ }
+
+ protected static int getMaxStacks(int tier) {
+ // Included higher tiers on the off chance they actually work without blowing things up lmao
+ return tier > 9 ? MAX : Math.min(maxStacks[tier], MAX);
+ }
+
+ @Override
+ public void addUIWidgets(ModularWindow.Builder builder, UIBuildContext buildContext) {
+ super.addUIWidgets(builder, buildContext);
+ addSortStacksButton(builder);
+ addEmitRedstoneIfFullButton(builder);
+ addInvertRedstoneButton(builder);
+ addStockingModeButton(builder);
+ builder.widget(
+ new DrawableWidget().setDrawable(GT_UITextures.PICTURE_ARROW_22_RED.apply(69, true))
+ .setPos(98, 60)
+ .setSize(51, 22));
+ addMainUI(builder);
+ }
+
+ protected void addMainUI(ModularWindow.Builder builder) {
+ addInventorySlots(builder);
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/automation/GT_MetaTileEntity_Filter.java b/src/main/java/gregtech/common/tileentities/automation/GT_MetaTileEntity_Filter.java
new file mode 100644
index 0000000000..b6f1d53604
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/automation/GT_MetaTileEntity_Filter.java
@@ -0,0 +1,144 @@
+package gregtech.common.tileentities.automation;
+
+import static gregtech.api.enums.Textures.BlockIcons.AUTOMATION_FILTER;
+import static gregtech.api.enums.Textures.BlockIcons.AUTOMATION_FILTER_GLOW;
+
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import com.gtnewhorizons.modularui.api.screen.ModularWindow;
+import com.gtnewhorizons.modularui.api.screen.UIBuildContext;
+import com.gtnewhorizons.modularui.common.widget.DrawableWidget;
+import com.gtnewhorizons.modularui.common.widget.SlotGroup;
+
+import gregtech.api.gui.modularui.GT_UITextures;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_FilterBase;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Utility;
+
+public class GT_MetaTileEntity_Filter extends GT_MetaTileEntity_FilterBase {
+
+ private static final int NUM_FILTER_SLOTS = 9;
+ private static final String IGNORE_NBT_TOOLTIP = "GT5U.machines.ignore_nbt.tooltip";
+ private boolean ignoreNbt = false;
+
+ public GT_MetaTileEntity_Filter(int aID, String aName, String aNameRegional, int aTier) {
+ super(
+ aID,
+ aName,
+ aNameRegional,
+ aTier,
+ 19,
+ new String[] { "Filters up to 9 different Items", "Use Screwdriver to regulate output stack size" });
+ }
+
+ public GT_MetaTileEntity_Filter(String aName, int aTier, int aInvSlotCount, String aDescription,
+ ITexture[][][] aTextures) {
+ super(aName, aTier, aInvSlotCount, aDescription, aTextures);
+ }
+
+ public GT_MetaTileEntity_Filter(String aName, int aTier, int aInvSlotCount, String[] aDescription,
+ ITexture[][][] aTextures) {
+ super(aName, aTier, aInvSlotCount, aDescription, aTextures);
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_Filter(
+ this.mName,
+ this.mTier,
+ this.mInventory.length,
+ this.mDescriptionArray,
+ this.mTextures);
+ }
+
+ @Override
+ public ITexture getOverlayIcon() {
+ return TextureFactory.of(
+ TextureFactory.of(AUTOMATION_FILTER),
+ TextureFactory.builder()
+ .addIcon(AUTOMATION_FILTER_GLOW)
+ .glow()
+ .build());
+ }
+
+ @Override
+ public void saveNBTData(NBTTagCompound aNBT) {
+ super.saveNBTData(aNBT);
+ aNBT.setBoolean("bIgnoreNBT", this.ignoreNbt);
+ }
+
+ @Override
+ public void loadNBTData(NBTTagCompound aNBT) {
+ super.loadNBTData(aNBT);
+ this.ignoreNbt = aNBT.getBoolean("bIgnoreNBT");
+ }
+
+ @Override
+ public boolean allowPutStack(IGregTechTileEntity aBaseMetaTileEntity, int aIndex, ForgeDirection side,
+ ItemStack aStack) {
+ if (!super.allowPutStack(aBaseMetaTileEntity, aIndex, side, aStack)) {
+ return false;
+ }
+ if (this.invertFilter) {
+ for (int i = 0; i < NUM_FILTER_SLOTS; i++) {
+ if (GT_Utility.areStacksEqual(this.mInventory[FILTER_SLOT_INDEX + i], aStack, this.ignoreNbt)) {
+ return false;
+ }
+ }
+ return true;
+ }
+ return GT_Utility.areStacksEqual(this.mInventory[(FILTER_SLOT_INDEX + aIndex)], aStack, this.ignoreNbt);
+ }
+
+ @Override
+ public void addUIWidgets(ModularWindow.Builder builder, UIBuildContext buildContext) {
+ super.addUIWidgets(builder, buildContext);
+ addAllowNbtButton(builder);
+ builder.widget(
+ new DrawableWidget().setDrawable(GT_UITextures.PICTURE_ARROW_24_WHITE.apply(9, false))
+ .setPos(6, 19)
+ .setSize(9, 24))
+ .widget(
+ new DrawableWidget().setDrawable(GT_UITextures.PICTURE_ARROW_24_BLUE.apply(24, true))
+ .setPos(71, 19)
+ .setSize(24, 24))
+ .widget(
+ new DrawableWidget().setDrawable(GT_UITextures.PICTURE_ARROW_24_RED.apply(19, true))
+ .setPos(152, 19)
+ .setSize(19, 24))
+ .widget(
+ new DrawableWidget().setDrawable(GT_UITextures.PICTURE_SLOTS_HOLO_3BY3)
+ .setPos(16, 4)
+ .setSize(54, 54))
+ .widget(
+ SlotGroup.ofItemHandler(inventoryHandler, 3)
+ .startFromSlot(FILTER_SLOT_INDEX)
+ .endAtSlot(FILTER_SLOT_INDEX + NUM_FILTER_SLOTS - 1)
+ .phantom(true)
+ .applyForWidget(
+ widget -> widget.disableShiftInsert()
+ .setBackground(GT_UITextures.TRANSPARENT))
+ .build()
+ .setPos(16, 4))
+ .widget(
+ SlotGroup.ofItemHandler(inventoryHandler, 3)
+ .startFromSlot(0)
+ .endAtSlot(NUM_INVENTORY_SLOTS - 1)
+ .build()
+ .setPos(97, 4));
+ }
+
+ private void addAllowNbtButton(ModularWindow.Builder builder) {
+ builder.widget(
+ createToggleButton(
+ () -> ignoreNbt,
+ val -> ignoreNbt = val,
+ GT_UITextures.OVERLAY_BUTTON_NBT,
+ () -> mTooltipCache.getData(IGNORE_NBT_TOOLTIP)));
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/automation/GT_MetaTileEntity_ItemDistributor.java b/src/main/java/gregtech/common/tileentities/automation/GT_MetaTileEntity_ItemDistributor.java
new file mode 100644
index 0000000000..58b7fa57df
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/automation/GT_MetaTileEntity_ItemDistributor.java
@@ -0,0 +1,204 @@
+package gregtech.common.tileentities.automation;
+
+import static gregtech.api.enums.Textures.BlockIcons.AUTOMATION_ITEMDISTRIBUTOR;
+import static gregtech.api.enums.Textures.BlockIcons.AUTOMATION_ITEMDISTRIBUTOR_GLOW;
+
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.tileentity.TileEntity;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import com.gtnewhorizons.modularui.api.screen.ModularWindow;
+import com.gtnewhorizons.modularui.api.screen.UIBuildContext;
+import com.gtnewhorizons.modularui.common.widget.DrawableWidget;
+
+import gregtech.api.enums.Textures;
+import gregtech.api.gui.modularui.GT_UITextures;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Buffer;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Utility;
+
+public class GT_MetaTileEntity_ItemDistributor extends GT_MetaTileEntity_Buffer {
+
+ private byte[] itemsPerSide = new byte[6];
+ private ForgeDirection currentSide = ForgeDirection.DOWN;
+ private byte currentSideItemCount = 0;
+
+ public GT_MetaTileEntity_ItemDistributor(int aID, String aName, String aNameRegional, int aTier) {
+ super(
+ aID,
+ aName,
+ aNameRegional,
+ aTier,
+ 28,
+ new String[] { "Distributes Items between different Machine Sides", "Default Items per Machine Side: 0",
+ "Use Screwdriver to increase/decrease Items per Side" });
+ }
+
+ public GT_MetaTileEntity_ItemDistributor(int aID, String aName, String aNameRegional, int aTier, int aInvSlotCount,
+ String aDescription) {
+ super(aID, aName, aNameRegional, aTier, aInvSlotCount, aDescription);
+ }
+
+ public GT_MetaTileEntity_ItemDistributor(String aName, int aTier, int aInvSlotCount, String aDescription,
+ ITexture[][][] aTextures) {
+ super(aName, aTier, aInvSlotCount, aDescription, aTextures);
+ }
+
+ public GT_MetaTileEntity_ItemDistributor(String aName, int aTier, int aInvSlotCount, String[] aDescription,
+ ITexture[][][] aTextures) {
+ super(aName, aTier, aInvSlotCount, aDescription, aTextures);
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_ItemDistributor(
+ this.mName,
+ this.mTier,
+ this.mInventory.length,
+ this.mDescriptionArray,
+ this.mTextures);
+ }
+
+ @Override
+ public ITexture getOverlayIcon() {
+ return TextureFactory.of(
+ TextureFactory.of(AUTOMATION_ITEMDISTRIBUTOR),
+ TextureFactory.builder()
+ .addIcon(AUTOMATION_ITEMDISTRIBUTOR_GLOW)
+ .glow()
+ .build());
+ }
+
+ @Override
+ public boolean allowPutStack(IGregTechTileEntity aBaseMetaTileEntity, int aIndex, ForgeDirection side,
+ ItemStack aStack) {
+ return side == aBaseMetaTileEntity.getFrontFacing();
+ }
+
+ @Override
+ public ITexture[] getTexture(IGregTechTileEntity aBaseMetaTileEntity, ForgeDirection side, ForgeDirection aFacing,
+ int colorIndex, boolean aActive, boolean redstoneLevel) {
+ if (side == aFacing) {
+ return mTextures[0][colorIndex + 1];
+ } else {
+ return mTextures[1][colorIndex + 1];
+ }
+ }
+
+ @Override
+ public ITexture[][][] getTextureSet(ITexture[] aTextures) {
+ ITexture[][][] returnTextures = new ITexture[2][17][];
+ ITexture baseIcon = getOverlayIcon(), pipeIcon = TextureFactory.of(Textures.BlockIcons.OVERLAY_PIPE_OUT);
+ for (int i = 0; i < 17; i++) {
+ returnTextures[0][i] = new ITexture[] { Textures.BlockIcons.MACHINE_CASINGS[mTier][i], baseIcon };
+ returnTextures[1][i] = new ITexture[] { Textures.BlockIcons.MACHINE_CASINGS[mTier][i], pipeIcon, baseIcon };
+ }
+ return returnTextures;
+ }
+
+ @Override
+ public boolean isInputFacing(ForgeDirection side) {
+ return getBaseMetaTileEntity().getFrontFacing() == side || itemsPerSide[side.ordinal()] == 0;
+ }
+
+ @Override
+ public boolean isOutputFacing(ForgeDirection side) {
+ return getBaseMetaTileEntity().getFrontFacing() != side && itemsPerSide[side.ordinal()] > 0;
+ }
+
+ @Override
+ public boolean isValidSlot(int aIndex) {
+ return aIndex < this.mInventory.length - 1;
+ }
+
+ @Override
+ public void loadNBTData(NBTTagCompound aNBT) {
+ super.loadNBTData(aNBT);
+ itemsPerSide = aNBT.getByteArray("mItemsPerSide");
+ if (itemsPerSide.length != 6) {
+ itemsPerSide = new byte[6];
+ }
+ currentSide = ForgeDirection.getOrientation(aNBT.getByte("mCurrentSide"));
+ currentSideItemCount = aNBT.getByte("mCurrentSideItemCount");
+ }
+
+ @Override
+ protected void moveItems(IGregTechTileEntity aBaseMetaTileEntity, long aTimer) {
+ int currentSideOrdinal = currentSide.ordinal();
+ fillStacksIntoFirstSlots();
+ int movedItems;
+ TileEntity adjacentTileEntity = aBaseMetaTileEntity.getTileEntityAtSide(currentSide);
+ int inspectedSides = 0;
+ while (itemsPerSide[currentSideOrdinal] == 0) {
+ currentSideOrdinal = ((currentSideOrdinal + 1) % 6);
+ currentSide = ForgeDirection.getOrientation(currentSideOrdinal);
+ currentSideItemCount = 0;
+ adjacentTileEntity = aBaseMetaTileEntity.getTileEntityAtSide(currentSide);
+ inspectedSides += 1;
+ if (inspectedSides == 6) {
+ return;
+ }
+ }
+ movedItems = GT_Utility.moveOneItemStack(
+ aBaseMetaTileEntity,
+ adjacentTileEntity,
+ currentSide,
+ currentSide.getOpposite(),
+ null,
+ false,
+ (byte) 64,
+ (byte) 1,
+ (byte) (itemsPerSide[currentSideOrdinal] - currentSideItemCount),
+ (byte) 1);
+ currentSideItemCount += movedItems;
+ if (currentSideItemCount >= itemsPerSide[currentSideOrdinal]) {
+ currentSideOrdinal = ((currentSideOrdinal + 1) % 6);
+ currentSide = ForgeDirection.getOrientation(currentSideOrdinal);
+ currentSideItemCount = 0;
+ }
+ if (movedItems > 0 || aBaseMetaTileEntity.hasInventoryBeenModified()) {
+ mSuccess = 50;
+ }
+ fillStacksIntoFirstSlots();
+ }
+
+ @Override
+ public void onScrewdriverRightClick(ForgeDirection side, EntityPlayer aPlayer, float aX, float aY, float aZ) {
+ final int ordinalSide = side.ordinal();
+ // Adjust items per side by 1 or -1, constrained to the cyclic interval [0, 127]
+ itemsPerSide[ordinalSide] += aPlayer.isSneaking() ? -1 : 1;
+ itemsPerSide[ordinalSide] = (byte) ((itemsPerSide[ordinalSide] + 128) % 128);
+ GT_Utility.sendChatToPlayer(aPlayer, GT_Utility.trans("211", "Items per side: ") + itemsPerSide[ordinalSide]);
+ }
+
+ @Override
+ public void saveNBTData(NBTTagCompound aNBT) {
+ super.saveNBTData(aNBT);
+ aNBT.setByteArray("mItemsPerSide", itemsPerSide);
+ aNBT.setByte("mCurrentSide", (byte) currentSide.ordinal());
+ aNBT.setByte("mCurrentSideItemCount", currentSideItemCount);
+ }
+
+ @Override
+ public void setItemNBT(NBTTagCompound aNBT) {
+ super.setItemNBT(aNBT);
+ aNBT.setByteArray("mItemsPerSide", itemsPerSide);
+ }
+
+ @Override
+ public void addUIWidgets(ModularWindow.Builder builder, UIBuildContext buildContext) {
+ super.addUIWidgets(builder, buildContext);
+ addEmitRedstoneIfFullButton(builder);
+ addInvertRedstoneButton(builder);
+ builder.widget(
+ new DrawableWidget().setDrawable(GT_UITextures.PICTURE_ARROW_22_RED.apply(87, true))
+ .setPos(62, 60)
+ .setSize(87, 22));
+ addInventorySlots(builder);
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/automation/GT_MetaTileEntity_RecipeFilter.java b/src/main/java/gregtech/common/tileentities/automation/GT_MetaTileEntity_RecipeFilter.java
new file mode 100644
index 0000000000..d446009ac7
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/automation/GT_MetaTileEntity_RecipeFilter.java
@@ -0,0 +1,326 @@
+package gregtech.common.tileentities.automation;
+
+import static gregtech.api.enums.Textures.BlockIcons.AUTOMATION_RECIPEFILTER;
+import static gregtech.api.enums.Textures.BlockIcons.AUTOMATION_RECIPEFILTER_GLOW;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.nbt.NBTTagList;
+import net.minecraft.network.PacketBuffer;
+import net.minecraft.tileentity.TileEntity;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.StatCollector;
+import net.minecraftforge.common.util.Constants;
+
+import org.jetbrains.annotations.NotNull;
+
+import com.gtnewhorizons.modularui.api.drawable.Text;
+import com.gtnewhorizons.modularui.api.screen.ModularWindow;
+import com.gtnewhorizons.modularui.api.screen.UIBuildContext;
+import com.gtnewhorizons.modularui.common.internal.network.NetworkUtils;
+import com.gtnewhorizons.modularui.common.internal.wrapper.BaseSlot;
+import com.gtnewhorizons.modularui.common.widget.FakeSyncWidget;
+import com.gtnewhorizons.modularui.common.widget.SlotWidget;
+
+import codechicken.nei.recipe.RecipeCatalysts;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.interfaces.tileentity.RecipeMapWorkable;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_SpecialFilter;
+import gregtech.api.multitileentity.MultiTileEntityItem;
+import gregtech.api.recipe.RecipeMap;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Utility;
+import gregtech.common.blocks.GT_Item_Machines;
+import gregtech.loaders.preload.GT_Loader_MultiTileEntities;
+
+public class GT_MetaTileEntity_RecipeFilter extends GT_MetaTileEntity_SpecialFilter {
+
+ private static final String TT_machineType = "GT5U.MBTT.MachineType";
+ private static final String REPRESENTATION_SLOT_TOOLTIP = "GT5U.recipe_filter.representation_slot.tooltip";
+ private static final String EMPTY_REPRESENTATION_SLOT_TOOLTIP = "GT5U.recipe_filter.empty_representation_slot.tooltip";
+ public RecipeMap<?> mRecipeMap;
+ private List<ItemStack> filteredMachines = new ArrayList<>();
+ public int mRotationIndex = 0;
+
+ public GT_MetaTileEntity_RecipeFilter(int aID, String aName, String aNameRegional, int aTier) {
+ super(
+ aID,
+ aName,
+ aNameRegional,
+ aTier,
+ new String[] { "Filters 1 Recipe Type", "Use Screwdriver to regulate output stack size" });
+ }
+
+ public GT_MetaTileEntity_RecipeFilter(String aName, int aTier, int aInvSlotCount, String aDescription,
+ ITexture[][][] aTextures) {
+ super(aName, aTier, aInvSlotCount, aDescription, aTextures);
+ }
+
+ public GT_MetaTileEntity_RecipeFilter(String aName, int aTier, int aInvSlotCount, String[] aDescription,
+ ITexture[][][] aTextures) {
+ super(aName, aTier, aInvSlotCount, aDescription, aTextures);
+ }
+
+ private static RecipeMap<?> getItemStackMachineRecipeMap(ItemStack stack) {
+ if (stack != null) {
+ IMetaTileEntity metaTileEntity = GT_Item_Machines.getMetaTileEntity(stack);
+ if (metaTileEntity != null) {
+ return getMetaTileEntityRecipeMap(metaTileEntity);
+ } else if (stack.getItem() instanceof MultiTileEntityItem) {
+ return getMuTeRecipeMap(stack);
+ }
+ }
+ return null;
+ }
+
+ private static RecipeMap<?> getMetaTileEntityRecipeMap(IMetaTileEntity metaTileEntity) {
+ if (metaTileEntity instanceof RecipeMapWorkable recipeMapWorkable) {
+ return recipeMapWorkable.getRecipeMap();
+ }
+ return null;
+ }
+
+ private static RecipeMap<?> getMuTeRecipeMap(@NotNull ItemStack stack) {
+ final TileEntity tileEntity = GT_Loader_MultiTileEntities.MACHINE_REGISTRY.getReferenceTileEntity(stack);
+ if (tileEntity instanceof RecipeMapWorkable recipeMapWorkable) {
+ return recipeMapWorkable.getRecipeMap();
+ }
+ return null;
+ }
+
+ private static List<ItemStack> getFilteredMachines(RecipeMap<?> recipeMap) {
+ return RecipeCatalysts.getRecipeCatalysts(
+ recipeMap.getFrontend()
+ .getUIProperties().neiTransferRectId)
+ .stream()
+ .map(positionedStack -> positionedStack.item)
+ .collect(Collectors.toList());
+ }
+
+ @Override
+ public void onPreTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) {
+ super.onPreTick(aBaseMetaTileEntity, aTick);
+ if ((!getBaseMetaTileEntity().isServerSide()) || ((aTick % 8L != 0L) && mRotationIndex != -1)) return;
+ if (this.filteredMachines.isEmpty()) {
+ return;
+ }
+ this.mInventory[FILTER_SLOT_INDEX] = GT_Utility.copyAmount(
+ 1,
+ this.filteredMachines.get(this.mRotationIndex = (this.mRotationIndex + 1) % this.filteredMachines.size()));
+ if (this.mInventory[FILTER_SLOT_INDEX] == null) return;
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_RecipeFilter(
+ this.mName,
+ this.mTier,
+ this.mInventory.length,
+ this.mDescriptionArray,
+ this.mTextures);
+ }
+
+ @Override
+ public ITexture getOverlayIcon() {
+ return TextureFactory.of(
+ TextureFactory.of(AUTOMATION_RECIPEFILTER),
+ TextureFactory.builder()
+ .addIcon(AUTOMATION_RECIPEFILTER_GLOW)
+ .glow()
+ .build());
+ }
+
+ @Override
+ public void saveNBTData(NBTTagCompound aNBT) {
+ super.saveNBTData(aNBT);
+ if (mRecipeMap != null) {
+ aNBT.setString("mRecipeMap", this.mRecipeMap.unlocalizedName);
+ }
+ NBTTagList tagList = new NBTTagList();
+ for (ItemStack filteredMachine : filteredMachines) {
+ tagList.appendTag(filteredMachine.writeToNBT(new NBTTagCompound()));
+ }
+ aNBT.setTag("filteredMachines", tagList);
+ }
+
+ @Override
+ public void loadNBTData(NBTTagCompound aNBT) {
+ super.loadNBTData(aNBT);
+ this.mRecipeMap = RecipeMap.getFromOldIdentifier(aNBT.getString("mRecipeMap"));
+ filteredMachines.clear();
+ NBTTagList tagList = aNBT.getTagList("filteredMachines", Constants.NBT.TAG_COMPOUND);
+ for (int i = 0; i < tagList.tagCount(); i++) {
+ ItemStack readStack = ItemStack.loadItemStackFromNBT(tagList.getCompoundTagAt(i));
+ if (readStack != null) {
+ filteredMachines.add(readStack);
+ }
+ }
+ }
+
+ @Override
+ protected boolean isStackAllowed(ItemStack aStack) {
+ return mRecipeMap != null && mRecipeMap.containsInput(aStack);
+ }
+
+ @Override
+ public void addUIWidgets(ModularWindow.Builder builder, UIBuildContext buildContext) {
+ super.addUIWidgets(builder, buildContext);
+ builder.widget(
+ new FakeSyncWidget.StringSyncer(
+ () -> this.mRecipeMap == null ? "" : this.mRecipeMap.unlocalizedName,
+ id -> this.mRecipeMap = RecipeMap.ALL_RECIPE_MAPS.get(id)));
+ }
+
+ @Override
+ protected List<Text> getEmptySlotTooltip() {
+ return Collections.singletonList(Text.localised(EMPTY_REPRESENTATION_SLOT_TOOLTIP));
+ }
+
+ @Override
+ public Function<List<String>, List<String>> getItemStackReplacementTooltip() {
+ if (mRecipeMap != null) {
+ List<String> tooltip = assembleItemStackReplacementTooltip(mRecipeMap);
+ return list -> tooltip;
+ }
+ return super.getItemStackReplacementTooltip();
+ }
+
+ @NotNull
+ private List<String> assembleItemStackReplacementTooltip(RecipeMap<?> recipeMap) {
+ List<String> tooltip = new ArrayList<>();
+ tooltip.add(
+ StatCollector.translateToLocal(TT_machineType) + ": "
+ + EnumChatFormatting.YELLOW
+ + StatCollector.translateToLocal(recipeMap.unlocalizedName)
+ + EnumChatFormatting.RESET);
+ int recipeSize = recipeMap.getAllRecipes()
+ .size();
+ if (recipeSize > 0) {
+ tooltip.add("Filter size: §e" + recipeSize + "§r");
+ }
+ tooltip.addAll(mTooltipCache.getData(REPRESENTATION_SLOT_TOOLTIP).text);
+ return tooltip;
+ }
+
+ @Override
+ protected SlotWidget createFilterIconSlot(BaseSlot slot) {
+ return new RecipeFilterIconSlotWidget(slot);
+ }
+
+ private class RecipeFilterIconSlotWidget extends FilterIconSlotWidget {
+
+ private static final int SYNC_RECIPEMAP_C2S = 98;
+ private static final int REQUEST_FILTERED_MACHINES_S2C = 99;
+
+ public RecipeFilterIconSlotWidget(BaseSlot slot) {
+ super(slot);
+ }
+
+ @Override
+ protected void phantomClick(ClickData clickData, ItemStack cursorStack) {}
+
+ // region client
+
+ @Override
+ public ClickResult onClick(int buttonId, boolean doubleClick) {
+ updateAndSendRecipeMapToServer(
+ getContext().getCursor()
+ .getItemStack());
+ return ClickResult.SUCCESS;
+ }
+
+ @Override
+ public boolean handleDragAndDrop(ItemStack draggedStack, int button) {
+ updateAndSendRecipeMapToServer(draggedStack);
+ draggedStack.stackSize = 0;
+ return true;
+ }
+
+ private void updateAndSendRecipeMapToServer(ItemStack stack) {
+ mRecipeMap = getItemStackMachineRecipeMap(stack);
+ updateAndSendRecipeMapToServer(mRecipeMap);
+ }
+
+ private void updateAndSendRecipeMapToServer(RecipeMap<?> recipeMap) {
+ if (recipeMap != null) {
+ filteredMachines = getFilteredMachines(recipeMap);
+ } else {
+ filteredMachines = new ArrayList<>();
+ mInventory[FILTER_SLOT_INDEX] = null;
+ }
+ mRotationIndex = -1;
+ syncToServer(SYNC_RECIPEMAP_C2S, buffer -> {
+ NetworkUtils.writeStringSafe(buffer, recipeMap != null ? recipeMap.unlocalizedName : null);
+ buffer.writeVarIntToBuffer(filteredMachines.size());
+ for (ItemStack filteredMachine : filteredMachines) {
+ NetworkUtils.writeItemStack(buffer, filteredMachine);
+ }
+ });
+ }
+
+ @Override
+ public void readOnClient(int id, PacketBuffer buf) {
+ if (id != REQUEST_FILTERED_MACHINES_S2C) {
+ super.readOnClient(id, buf);
+ return;
+ }
+
+ String recipeMapName = NetworkUtils.readStringSafe(buf);
+ mRecipeMap = recipeMapName != null ? RecipeMap.ALL_RECIPE_MAPS.get(recipeMapName) : null;
+ if (mRecipeMap != null) {
+ updateAndSendRecipeMapToServer(mRecipeMap);
+ }
+ }
+
+ // endregion
+
+ // region server
+
+ @Override
+ public void readOnServer(int id, PacketBuffer buf) throws IOException {
+ if (id != SYNC_RECIPEMAP_C2S) {
+ super.readOnServer(id, buf);
+ return;
+ }
+
+ String recipeMapName = NetworkUtils.readStringSafe(buf);
+ mRecipeMap = recipeMapName != null ? RecipeMap.getFromOldIdentifier(recipeMapName) : null;
+ mRotationIndex = -1;
+ mInventory[FILTER_SLOT_INDEX] = null;
+ filteredMachines.clear();
+
+ if (mRecipeMap != null) {
+ int filteredMachineSize = buf.readVarIntFromBuffer();
+ filteredMachineSize = Math.min(filteredMachineSize, 256); // Prevent storing too many items
+ for (int i = 0; i < filteredMachineSize; i++) {
+ ItemStack stack = NetworkUtils.readItemStack(buf);
+ if (stack != null) {
+ filteredMachines.add(stack);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void detectAndSendChanges(boolean init) {
+ super.detectAndSendChanges(init);
+ if (init && mRecipeMap != null && filteredMachines.isEmpty()) {
+ // backward compatibility: This machine used to store only mRecipeMap, not filteredMachines
+ syncToClient(
+ REQUEST_FILTERED_MACHINES_S2C,
+ buffer -> NetworkUtils.writeStringSafe(buffer, mRecipeMap.unlocalizedName));
+ }
+ }
+
+ // endregion
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/automation/GT_MetaTileEntity_Regulator.java b/src/main/java/gregtech/common/tileentities/automation/GT_MetaTileEntity_Regulator.java
new file mode 100644
index 0000000000..08d3d32512
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/automation/GT_MetaTileEntity_Regulator.java
@@ -0,0 +1,228 @@
+package gregtech.common.tileentities.automation;
+
+import static gregtech.api.enums.Textures.BlockIcons.AUTOMATION_REGULATOR;
+import static gregtech.api.enums.Textures.BlockIcons.AUTOMATION_REGULATOR_GLOW;
+
+import java.util.Collections;
+
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import com.gtnewhorizons.modularui.api.screen.ModularWindow;
+import com.gtnewhorizons.modularui.api.screen.UIBuildContext;
+import com.gtnewhorizons.modularui.common.internal.wrapper.BaseSlot;
+import com.gtnewhorizons.modularui.common.widget.DrawableWidget;
+import com.gtnewhorizons.modularui.common.widget.SlotGroup;
+import com.gtnewhorizons.modularui.common.widget.SlotWidget;
+import com.gtnewhorizons.modularui.common.widget.TextWidget;
+
+import gregtech.api.gui.modularui.GT_UITextures;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Buffer;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Utility;
+
+public class GT_MetaTileEntity_Regulator extends GT_MetaTileEntity_Buffer {
+
+ public int[] mTargetSlots = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+ private boolean charge = false, decharge = false;
+
+ public GT_MetaTileEntity_Regulator(int aID, String aName, String aNameRegional, int aTier) {
+ super(
+ aID,
+ aName,
+ aNameRegional,
+ aTier,
+ 20,
+ new String[] { "Filters up to 9 different Items", "Allows Item-specific output stack size",
+ "Allows Item-specific output slot" });
+ }
+
+ public GT_MetaTileEntity_Regulator(String aName, int aTier, int aInvSlotCount, String aDescription,
+ ITexture[][][] aTextures) {
+ super(aName, aTier, aInvSlotCount, aDescription, aTextures);
+ }
+
+ public GT_MetaTileEntity_Regulator(String aName, int aTier, int aInvSlotCount, String[] aDescription,
+ ITexture[][][] aTextures) {
+ super(aName, aTier, aInvSlotCount, aDescription, aTextures);
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_Regulator(
+ this.mName,
+ this.mTier,
+ this.mInventory.length,
+ this.mDescriptionArray,
+ this.mTextures);
+ }
+
+ @Override
+ public ITexture getOverlayIcon() {
+ return TextureFactory.of(
+ TextureFactory.of(AUTOMATION_REGULATOR),
+ TextureFactory.builder()
+ .addIcon(AUTOMATION_REGULATOR_GLOW)
+ .glow()
+ .build());
+ }
+
+ @Override
+ public boolean isValidSlot(int aIndex) {
+ return aIndex < 9 || aIndex == rechargerSlotStartIndex();
+ }
+
+ @Override
+ public void saveNBTData(NBTTagCompound aNBT) {
+ super.saveNBTData(aNBT);
+ aNBT.setInteger("mTargetSlot1", this.mTargetSlots[0]);
+ aNBT.setInteger("mTargetSlot2", this.mTargetSlots[1]);
+ aNBT.setInteger("mTargetSlot3", this.mTargetSlots[2]);
+ aNBT.setInteger("mTargetSlot4", this.mTargetSlots[3]);
+ aNBT.setInteger("mTargetSlot5", this.mTargetSlots[4]);
+ aNBT.setInteger("mTargetSlot6", this.mTargetSlots[5]);
+ aNBT.setInteger("mTargetSlot7", this.mTargetSlots[6]);
+ aNBT.setInteger("mTargetSlot8", this.mTargetSlots[7]);
+ aNBT.setInteger("mTargetSlot9", this.mTargetSlots[8]);
+ }
+
+ @Override
+ public void loadNBTData(NBTTagCompound aNBT) {
+ super.loadNBTData(aNBT);
+ this.mTargetSlots[0] = aNBT.getInteger("mTargetSlot1");
+ this.mTargetSlots[1] = aNBT.getInteger("mTargetSlot2");
+ this.mTargetSlots[2] = aNBT.getInteger("mTargetSlot3");
+ this.mTargetSlots[3] = aNBT.getInteger("mTargetSlot4");
+ this.mTargetSlots[4] = aNBT.getInteger("mTargetSlot5");
+ this.mTargetSlots[5] = aNBT.getInteger("mTargetSlot6");
+ this.mTargetSlots[6] = aNBT.getInteger("mTargetSlot7");
+ this.mTargetSlots[7] = aNBT.getInteger("mTargetSlot8");
+ this.mTargetSlots[8] = aNBT.getInteger("mTargetSlot9");
+ }
+
+ @Override
+ public void onScrewdriverRightClick(ForgeDirection side, EntityPlayer aPlayer, float aX, float aY, float aZ) {
+ // Regulation per Screwdriver is overridden by GUI regulation.
+ }
+
+ @Override
+ public void moveItems(IGregTechTileEntity aBaseMetaTileEntity, long aTimer) {
+ for (int i = 0, tCosts; i < 9; i++) {
+ if (this.mInventory[(i + 9)] != null) {
+ tCosts = GT_Utility.moveOneItemStackIntoSlot(
+ getBaseMetaTileEntity(),
+ getBaseMetaTileEntity().getTileEntityAtSide(getBaseMetaTileEntity().getBackFacing()),
+ getBaseMetaTileEntity().getBackFacing(),
+ this.mTargetSlots[i],
+ Collections.singletonList(this.mInventory[(i + 9)]),
+ false,
+ (byte) this.mInventory[(i + 9)].stackSize,
+ (byte) this.mInventory[(i + 9)].stackSize,
+ (byte) 64,
+ (byte) 1) * 3;
+ if (tCosts > 0) {
+ this.mSuccess = 50;
+ break;
+ }
+ }
+ }
+ }
+
+ @Override
+ public boolean allowPutStack(IGregTechTileEntity aBaseMetaTileEntity, int aIndex, ForgeDirection side,
+ ItemStack aStack) {
+ return super.allowPutStack(aBaseMetaTileEntity, aIndex, side, aStack) && aIndex >= 0
+ && aIndex <= 8
+ && GT_Utility.areStacksEqual(aStack, this.mInventory[(aIndex + 9)]);
+ }
+
+ @Override
+ public int rechargerSlotStartIndex() {
+ return 19;
+ }
+
+ @Override
+ public int dechargerSlotStartIndex() {
+ return 19;
+ }
+
+ @Override
+ public int rechargerSlotCount() {
+ return charge ? 1 : 0;
+ }
+
+ @Override
+ public int dechargerSlotCount() {
+ return decharge ? 1 : 0;
+ }
+
+ @Override
+ public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) {
+ super.onPostTick(aBaseMetaTileEntity, aTick);
+ if (aBaseMetaTileEntity.isServerSide()) {
+ charge = aBaseMetaTileEntity.getStoredEU() / 2 > aBaseMetaTileEntity.getEUCapacity() / 3;
+ decharge = aBaseMetaTileEntity.getStoredEU() < aBaseMetaTileEntity.getEUCapacity() / 3;
+ }
+ }
+
+ @Override
+ public void addUIWidgets(ModularWindow.Builder builder, UIBuildContext buildContext) {
+ super.addUIWidgets(builder, buildContext);
+ builder.widget(createChargerSlot(43, 62));
+ builder.widget(
+ new DrawableWidget().setDrawable(GT_UITextures.PICTURE_ARROW_22_RED.apply(84, true))
+ .setPos(65, 60)
+ .setSize(84, 22))
+ .widget(
+ SlotGroup.ofItemHandler(inventoryHandler, 3)
+ .startFromSlot(0)
+ .endAtSlot(8)
+ .build()
+ .setPos(7, 5))
+ .widget(
+ new DrawableWidget().setDrawable(GT_UITextures.PICTURE_SLOTS_HOLO_3BY3)
+ .setPos(62, 5)
+ .setSize(54, 54))
+ .widget(
+ SlotGroup.ofItemHandler(inventoryHandler, 3)
+ .phantom(true)
+ .startFromSlot(9)
+ .endAtSlot(17)
+ .applyForWidget(
+ widget -> widget.setControlsAmount(true)
+ .setBackground(GT_UITextures.TRANSPARENT))
+ .build()
+ .setPos(62, 5))
+ .widget(
+ new DrawableWidget().setDrawable(GT_UITextures.PICTURE_SLOTS_HOLO_3BY3)
+ .setPos(117, 5)
+ .setSize(54, 54));
+
+ int xBase = 117, yBase = 5;
+ for (int i = 0; i < mTargetSlots.length; i++) {
+ final int index = i;
+ int xPos = xBase + (i % 3) * 18, yPos = yBase + (i / 3) * 18;
+ builder.widget(new SlotWidget(BaseSlot.empty()) {
+
+ @Override
+ protected void phantomClick(ClickData clickData, ItemStack cursorStack) {
+ mTargetSlots[index] = Math.min(
+ 99,
+ Math.max(
+ 0,
+ mTargetSlots[index] + (clickData.mouseButton == 0 ? -1 : 1) * (clickData.shift ? 16 : 1)));
+ }
+ }.setBackground(GT_UITextures.TRANSPARENT)
+ .setPos(xPos, yPos))
+ .widget(
+ TextWidget.dynamicString(() -> String.valueOf(mTargetSlots[index]))
+ .setDefaultColor(COLOR_TEXT_WHITE.get())
+ .setPos(xPos + 2 + (i % 3 == 0 ? 1 : 0), yPos + 3 + (i / 3 == 0 ? 1 : 0)));
+ }
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/automation/GT_MetaTileEntity_SuperBuffer.java b/src/main/java/gregtech/common/tileentities/automation/GT_MetaTileEntity_SuperBuffer.java
new file mode 100644
index 0000000000..9a1d2d7dcf
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/automation/GT_MetaTileEntity_SuperBuffer.java
@@ -0,0 +1,105 @@
+package gregtech.common.tileentities.automation;
+
+import static gregtech.api.enums.Textures.BlockIcons.AUTOMATION_SUPERBUFFER;
+import static gregtech.api.enums.Textures.BlockIcons.AUTOMATION_SUPERBUFFER_GLOW;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import net.minecraft.item.ItemStack;
+
+import com.gtnewhorizons.modularui.api.screen.ModularWindow;
+import com.gtnewhorizons.modularui.common.widget.DrawableWidget;
+
+import gregtech.api.gui.modularui.GT_UITextures;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Utility;
+
+public class GT_MetaTileEntity_SuperBuffer extends GT_MetaTileEntity_ChestBuffer {
+
+ public GT_MetaTileEntity_SuperBuffer(int aID, String aName, String aNameRegional, int aTier) {
+ super(
+ aID,
+ aName,
+ aNameRegional,
+ aTier,
+ 257,
+ new String[] { "Buffers up to 256 Item Stacks", "Use Screwdriver to regulate output stack size",
+ getTickRateDesc(aTier) });
+ }
+
+ public GT_MetaTileEntity_SuperBuffer(String aName, int aTier, int aInvSlotCount, String aDescription,
+ ITexture[][][] aTextures) {
+ super(aName, aTier, aInvSlotCount, aDescription, aTextures);
+ }
+
+ public GT_MetaTileEntity_SuperBuffer(String aName, int aTier, int aInvSlotCount, String[] aDescription,
+ ITexture[][][] aTextures) {
+ super(aName, aTier, aInvSlotCount, aDescription, aTextures);
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_SuperBuffer(
+ this.mName,
+ this.mTier,
+ this.mInventory.length,
+ this.mDescriptionArray,
+ this.mTextures);
+ }
+
+ @Override
+ public ITexture getOverlayIcon() {
+ return TextureFactory.of(
+ TextureFactory.of(AUTOMATION_SUPERBUFFER),
+ TextureFactory.builder()
+ .addIcon(AUTOMATION_SUPERBUFFER_GLOW)
+ .glow()
+ .build());
+ }
+
+ @Override
+ protected void fillStacksIntoFirstSlots() {
+ // no order, this is super buffer
+ HashMap<GT_Utility.ItemId, Integer> slots = new HashMap<>(mInventory.length);
+ HashMap<GT_Utility.ItemId, ItemStack> stacks = new HashMap<>(mInventory.length);
+ List<Integer> validSlots = new ArrayList<>(mInventory.length);
+ // List<String> order = new ArrayList<>(mInventory.length);
+ for (int i = 0; i < mInventory.length - 1; i++) {
+ if (!isValidSlot(i)) continue;
+ validSlots.add(i);
+ ItemStack s = mInventory[i];
+ if (s == null) continue;
+ GT_Utility.ItemId sID = GT_Utility.ItemId.createNoCopy(s);
+ slots.merge(sID, s.stackSize, Integer::sum);
+ if (!stacks.containsKey(sID)) stacks.put(sID, s);
+ // order.add(sID);
+ mInventory[i] = null;
+ }
+ int i = 0;
+ for (Map.Entry<GT_Utility.ItemId, Integer> entry : slots.entrySet()) {
+ do {
+ int slot = validSlots.get(i);
+ mInventory[slot] = stacks.get(entry.getKey())
+ .copy();
+ int toSet = Math.min(entry.getValue(), mInventory[slot].getMaxStackSize());
+ mInventory[slot].stackSize = toSet;
+ entry.setValue(entry.getValue() - toSet);
+ i++;
+ } while (entry.getValue() > 0);
+ }
+ }
+
+ @Override
+ protected void addMainUI(ModularWindow.Builder builder) {
+ builder.widget(
+ new DrawableWidget().setDrawable(GT_UITextures.PICTURE_SUPER_BUFFER)
+ .setPos(61, 4)
+ .setSize(54, 54));
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/automation/GT_MetaTileEntity_TypeFilter.java b/src/main/java/gregtech/common/tileentities/automation/GT_MetaTileEntity_TypeFilter.java
new file mode 100644
index 0000000000..be4a2226a1
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/automation/GT_MetaTileEntity_TypeFilter.java
@@ -0,0 +1,213 @@
+package gregtech.common.tileentities.automation;
+
+import static gregtech.api.enums.GT_Values.W;
+import static gregtech.api.enums.Textures.BlockIcons.AUTOMATION_TYPEFILTER;
+import static gregtech.api.enums.Textures.BlockIcons.AUTOMATION_TYPEFILTER_GLOW;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.Function;
+
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+
+import com.google.common.collect.ImmutableList;
+import com.gtnewhorizons.modularui.api.screen.ModularWindow;
+import com.gtnewhorizons.modularui.api.screen.UIBuildContext;
+import com.gtnewhorizons.modularui.common.internal.wrapper.BaseSlot;
+import com.gtnewhorizons.modularui.common.widget.FakeSyncWidget;
+import com.gtnewhorizons.modularui.common.widget.SlotWidget;
+
+import gregtech.api.enums.OrePrefixes;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_SpecialFilter;
+import gregtech.api.objects.ItemData;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_OreDictUnificator;
+import gregtech.api.util.GT_Utility;
+
+public class GT_MetaTileEntity_TypeFilter extends GT_MetaTileEntity_SpecialFilter {
+
+ private static final String REPRESENTATION_SLOT_TOOLTIP = "GT5U.type_filter.representation_slot.tooltip";
+ public int mRotationIndex = 0;
+ public OrePrefixes mPrefix = OrePrefixes.ore;
+
+ public static ImmutableList<OrePrefixes> OREBLOCK_PREFIXES = ImmutableList.of(
+ OrePrefixes.oreBlackgranite,
+ OrePrefixes.oreDense,
+ OrePrefixes.oreEnd,
+ OrePrefixes.oreEndstone,
+ OrePrefixes.oreNether,
+ OrePrefixes.oreNetherrack,
+ OrePrefixes.oreNormal,
+ OrePrefixes.orePoor,
+ OrePrefixes.oreRedgranite,
+ OrePrefixes.oreRich,
+ OrePrefixes.oreSmall,
+ OrePrefixes.oreBasalt,
+ OrePrefixes.oreMarble);
+
+ public GT_MetaTileEntity_TypeFilter(int aID, String aName, String aNameRegional, int aTier) {
+ super(
+ aID,
+ aName,
+ aNameRegional,
+ aTier,
+ new String[] { "Filters 1 Item Type", "Use Screwdriver to regulate output stack size" });
+ }
+
+ public GT_MetaTileEntity_TypeFilter(String aName, int aTier, int aInvSlotCount, String aDescription,
+ ITexture[][][] aTextures) {
+ super(aName, aTier, aInvSlotCount, aDescription, aTextures);
+ }
+
+ public GT_MetaTileEntity_TypeFilter(String aName, int aTier, int aInvSlotCount, String[] aDescription,
+ ITexture[][][] aTextures) {
+ super(aName, aTier, aInvSlotCount, aDescription, aTextures);
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_TypeFilter(
+ this.mName,
+ this.mTier,
+ this.mInventory.length,
+ this.mDescriptionArray,
+ this.mTextures);
+ }
+
+ @Override
+ public ITexture getOverlayIcon() {
+ return TextureFactory.of(
+ TextureFactory.of(AUTOMATION_TYPEFILTER),
+ TextureFactory.builder()
+ .addIcon(AUTOMATION_TYPEFILTER_GLOW)
+ .glow()
+ .build());
+ }
+
+ public void clickTypeIcon(boolean aRightClick, ItemStack aHandStack) {
+ if (getBaseMetaTileEntity().isServerSide()) {
+ if (aHandStack != null) {
+ copyHeldItemPrefix(aHandStack);
+ } else {
+ cyclePrefix(aRightClick);
+ }
+ }
+ }
+
+ private void copyHeldItemPrefix(ItemStack handStack) {
+ ItemData data = GT_OreDictUnificator.getAssociation(handStack);
+ if (data != null && data.hasValidPrefixData()) {
+ this.mPrefix = data.mPrefix;
+ this.mRotationIndex = -1;
+ }
+ }
+
+ private void cyclePrefix(boolean aRightClick) {
+ for (int i = 0; i < OrePrefixes.values().length; i++) {
+ if (this.mPrefix == OrePrefixes.values()[i]) {
+ for (this.mPrefix = null; this.mPrefix == null; this.mPrefix = OrePrefixes.values()[i]) {
+ if (aRightClick) {
+ do {
+ i--;
+ if (i < 0) {
+ i = OrePrefixes.values().length - 1;
+ }
+ } while (OrePrefixes.values()[i].mPrefixedItems.isEmpty());
+ } else {
+ do {
+ i++;
+ if (i >= OrePrefixes.values().length) {
+ i = 0;
+ }
+ } while (OrePrefixes.values()[i].mPrefixedItems.isEmpty());
+ }
+ if (!OrePrefixes.values()[i].mPrefixedItems.isEmpty()
+ && OrePrefixes.values()[i].mPrefixInto == OrePrefixes.values()[i])
+ mPrefix = OrePrefixes.values()[i];
+ }
+ }
+ this.mRotationIndex = -1;
+ }
+ }
+
+ @Override
+ public void onPreTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) {
+ super.onPreTick(aBaseMetaTileEntity, aTick);
+ if ((!getBaseMetaTileEntity().isServerSide()) || ((aTick % 8L != 0L) && mRotationIndex != -1)) return;
+ if (this.mPrefix.mPrefixedItems.isEmpty()) {
+ this.mInventory[FILTER_SLOT_INDEX] = null;
+ return;
+ }
+ this.mInventory[FILTER_SLOT_INDEX] = GT_Utility.copyAmount(
+ 1,
+ this.mPrefix.mPrefixedItems
+ .get(this.mRotationIndex = (this.mRotationIndex + 1) % this.mPrefix.mPrefixedItems.size()));
+ if (this.mInventory[FILTER_SLOT_INDEX] == null) return;
+ if (this.mInventory[FILTER_SLOT_INDEX].getItemDamage() == W) this.mInventory[9].setItemDamage(0);
+ }
+
+ @Override
+ public void saveNBTData(NBTTagCompound aNBT) {
+ super.saveNBTData(aNBT);
+ aNBT.setString("mPrefix", this.mPrefix.toString());
+ }
+
+ @Override
+ public void loadNBTData(NBTTagCompound aNBT) {
+ super.loadNBTData(aNBT);
+ this.mPrefix = OrePrefixes.getPrefix(aNBT.getString("mPrefix"), this.mPrefix);
+ }
+
+ @Override
+ protected boolean isStackAllowed(ItemStack aStack) {
+ if (this.mPrefix == OrePrefixes.ore) {
+ ItemData data = GT_OreDictUnificator.getItemData(aStack);
+ if (data != null && data.mPrefix != null && OREBLOCK_PREFIXES.contains(data.mPrefix)) {
+ return true;
+ }
+ }
+ return this.mPrefix.contains(aStack);
+ }
+
+ @Override
+ public void addUIWidgets(ModularWindow.Builder builder, UIBuildContext buildContext) {
+ super.addUIWidgets(builder, buildContext);
+ builder.widget(
+ new FakeSyncWidget.StringSyncer(
+ () -> this.mPrefix.toString(),
+ (prefix) -> this.mPrefix = OrePrefixes.getPrefix(prefix, this.mPrefix)));
+ }
+
+ @Override
+ protected Function<List<String>, List<String>> getItemStackReplacementTooltip() {
+ return (itemTooltip) -> {
+ List<String> replacementTooltip = new ArrayList<>();
+ replacementTooltip.add("Filter set to " + mPrefix.mRegularLocalName);
+ replacementTooltip.add("Ore prefix: §e" + mPrefix + "§r");
+ replacementTooltip.add("Filter size: §e" + mPrefix.mPrefixedItems.size() + "§r");
+ replacementTooltip.addAll(mTooltipCache.getData(REPRESENTATION_SLOT_TOOLTIP).text);
+ return replacementTooltip;
+ };
+ }
+
+ @Override
+ protected SlotWidget createFilterIconSlot(BaseSlot slot) {
+ return new TypeFilterIconSlotWidget(slot);
+ }
+
+ private class TypeFilterIconSlotWidget extends FilterIconSlotWidget {
+
+ public TypeFilterIconSlotWidget(BaseSlot slot) {
+ super(slot);
+ }
+
+ @Override
+ protected void phantomClick(ClickData clickData, ItemStack cursorStack) {
+ clickTypeIcon(clickData.mouseButton != 0, cursorStack);
+ }
+ }
+}