diff --git a/src/main/java/github/kasuminova/mmce/client/gui/GuiMEItemInputBus.java b/src/main/java/github/kasuminova/mmce/client/gui/GuiMEItemInputBus.java index ede0b401..24ae90d3 100644 --- a/src/main/java/github/kasuminova/mmce/client/gui/GuiMEItemInputBus.java +++ b/src/main/java/github/kasuminova/mmce/client/gui/GuiMEItemInputBus.java @@ -28,7 +28,6 @@ import net.minecraft.util.ResourceLocation; import net.minecraft.util.text.TextFormatting; import net.minecraftforge.fml.client.config.GuiUtils; -import org.lwjgl.input.Keyboard; import org.lwjgl.input.Mouse; import javax.annotation.Nonnull; @@ -55,30 +54,33 @@ private static List getAddActionInfo() { tooltip.add(TextFormatting.GRAY + I18n.format("gui.meiteminputbus.inv_action")); // Quite a sight, isn't it? // It was truly a beautiful sight... + final boolean shift = isShiftKeyDown(); + final boolean ctrl = isCtrlKeyDown(); - if (isShiftDown() && isControlDown()) { + if (shift && ctrl) { String keyCombination = "SHIFT + CTRL"; tooltip.add(TextFormatting.GRAY + I18n.format("gui.meiteminputbus.inv_action.multiply", - keyCombination)); + keyCombination)); tooltip.add(TextFormatting.GRAY + I18n.format("gui.meiteminputbus.inv_action.divide", - keyCombination)); + keyCombination)); } else { - tooltip.add(TextFormatting.GRAY + I18n.format("gui.meiteminputbus.inv_action.increase.normal")); - tooltip.add(TextFormatting.GRAY + I18n.format("gui.meiteminputbus.inv_action.decrease.normal")); + final int i = ctrl ? 100 : shift ? 10 : 1; + final String keyCombination = ctrl ? "CTRL" : shift ? "SHIFT" : null; + if (keyCombination != null) { + tooltip.add(TextFormatting.GRAY + I18n.format("gui.meiteminputbus.inv_action.increase", + keyCombination, i)); + tooltip.add(TextFormatting.GRAY + I18n.format("gui.meiteminputbus.inv_action.decrease", + keyCombination, i)); + } else { + tooltip.add(TextFormatting.GRAY + I18n.format("gui.meiteminputbus.inv_action.increase.normal")); + tooltip.add(TextFormatting.GRAY + I18n.format("gui.meiteminputbus.inv_action.decrease.normal")); + } } return tooltip; } - private static boolean isControlDown() { - return Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) || Keyboard.isKeyDown(Keyboard.KEY_RCONTROL); - } - - private static boolean isShiftDown() { - return Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) || Keyboard.isKeyDown(Keyboard.KEY_RSHIFT); - } - @Override public void handleMouseInput() throws IOException { super.handleMouseInput(); @@ -124,7 +126,10 @@ private boolean isScrollingUp(int wheel) { } private int getUpdatedCount(boolean isScrollingUp, int currentAmount) { - if (isShiftDown() && isControlDown()) { + final boolean shift = isShiftKeyDown(); + final boolean ctrl = isCtrlKeyDown(); + + if (shift && ctrl) { if (isScrollingUp) { // Overflow protection if (currentAmount <= Integer.MAX_VALUE / 2) { @@ -135,14 +140,15 @@ private int getUpdatedCount(boolean isScrollingUp, int currentAmount) { return Math.max(1, currentAmount / 2); } } else { + int i = ctrl ? 100 : shift ? 10 : 1; if (isScrollingUp) { // Overflow protection if (currentAmount < Integer.MAX_VALUE) { - return 1 + currentAmount; + return i + currentAmount; } return Integer.MAX_VALUE; } else { - return Math.max(1, currentAmount - 1); + return Math.max(1, currentAmount - i); } } } diff --git a/src/main/java/github/kasuminova/mmce/client/gui/GuiMEPatternProvider.java b/src/main/java/github/kasuminova/mmce/client/gui/GuiMEPatternProvider.java index 7bc13ffe..9271e10a 100644 --- a/src/main/java/github/kasuminova/mmce/client/gui/GuiMEPatternProvider.java +++ b/src/main/java/github/kasuminova/mmce/client/gui/GuiMEPatternProvider.java @@ -18,10 +18,12 @@ import github.kasuminova.mmce.common.util.InfItemFluidHandler; import hellfirepvp.modularmachinery.ModularMachinery; import hellfirepvp.modularmachinery.common.base.Mods; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.resources.I18n; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.ResourceLocation; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fml.common.ObfuscationReflectionHelper; @@ -38,7 +40,7 @@ public class GuiMEPatternProvider extends AEBaseGuiContainerDynamic { protected final MEPatternProvider owner; - protected final PatternProviderIngredientList stackList = new PatternProviderIngredientList(); + protected final PatternProviderIngredientList stackList = new PatternProviderIngredientList(); protected final ButtonElements workModeSetting = new ButtonElements<>(); public GuiMEPatternProvider(final MEPatternProvider owner, final EntityPlayer player) { @@ -108,6 +110,7 @@ public GuiMEPatternProvider(final MEPatternProvider owner, final EntityPlayer pl .addElement(MEPatternProvider.WorkModeSetting.CRAFTING_LOCK_MODE, TextureProperties.of(140 + 18 + 18, 196, 16, 16)) // ButtonTexture 0 .addElement(MEPatternProvider.WorkModeSetting.ENHANCED_BLOCKING_MODE, TextureProperties.of(140 - 18, 196, 16, 16)) + .addElement(MEPatternProvider.WorkModeSetting.ISOLATION_INPUT, TextureProperties.of(140 - 18 - 18, 196, 16, 16)) // ButtonTexture 5 .setMouseDownTexture(140 + 18 + 18 + 18 + 18 + 18, 196) // ButtonTexture 5 @@ -127,6 +130,8 @@ public GuiMEPatternProvider(final MEPatternProvider owner, final EntityPlayer pl + I18n.format("gui.mepatternprovider.crafting_lock_mode.desc")); tooltips.add((current == MEPatternProvider.WorkModeSetting.ENHANCED_BLOCKING_MODE ? I18n.format("gui.mepatternprovider.current") : "") + I18n.format("gui.mepatternprovider.enhanced_blocking_mode.desc")); + tooltips.add((current == MEPatternProvider.WorkModeSetting.ISOLATION_INPUT ? I18n.format("gui.mepatternprovider.current") : "") + + I18n.format("gui.mepatternprovider.isolation_input.desc")); return tooltips; }) .setOnClickedListener((btn) -> { @@ -143,6 +148,8 @@ public GuiMEPatternProvider(final MEPatternProvider owner, final EntityPlayer pl ModularMachinery.NET_CHANNEL.sendToServer(new PktMEPatternProviderAction(PktMEPatternProviderAction.Action.ENABLE_CRAFTING_LOCK_MODE)); case ENHANCED_BLOCKING_MODE -> ModularMachinery.NET_CHANNEL.sendToServer(new PktMEPatternProviderAction(PktMEPatternProviderAction.Action.ENABLE_ENHANCED_BLOCKING_MODE)); + case ISOLATION_INPUT -> + ModularMachinery.NET_CHANNEL.sendToServer(new PktMEPatternProviderAction(PktMEPatternProviderAction.Action.ENABLE_ENHANCED_ISOLATION_INPUT)); } }) .setWidthHeight(16, 16); @@ -222,12 +229,25 @@ public MEPatternProvider getOwner() { public void updateGUIState() { InfItemFluidHandler infHandler = owner.getInfHandler(); - stackList.setStackList(infHandler.getItemStackList(), infHandler.getFluidStackList(), infHandler.getGasStackList()); + + List itemStacks = new ObjectArrayList<>(infHandler.getItemStackList()); + List fluids = new ObjectArrayList<>(infHandler.getFluidStackList()); + List gass = new ObjectArrayList<>(infHandler.getGasStackList()); + + for (var component : owner.getCombinationComponents()) { + var h = (InfItemFluidHandler) component.getContainerProvider(); + itemStacks.addAll(h.getItemStackList()); + fluids.addAll(h.getFluidStackList()); + gass.addAll(h.getGasStackList()); + } + + stackList.setStackList(itemStacks, fluids, gass); workModeSetting.setCurrentSelection(owner.getWorkMode()); } - public void setStackList(final List itemStackList, final List fluidStackList, final List gasStackList) { - stackList.setStackList(itemStackList, fluidStackList, gasStackList); + public void setStackList(final NBTTagCompound tagCompound) { + owner.readProviderHandlerNBT(tagCompound, true); + updateGUIState(); } -} +} \ No newline at end of file diff --git a/src/main/java/github/kasuminova/mmce/common/block/appeng/BlockMEFluidInputBus.java b/src/main/java/github/kasuminova/mmce/common/block/appeng/BlockMEFluidInputBus.java index ef0c5337..38c456e6 100644 --- a/src/main/java/github/kasuminova/mmce/common/block/appeng/BlockMEFluidInputBus.java +++ b/src/main/java/github/kasuminova/mmce/common/block/appeng/BlockMEFluidInputBus.java @@ -5,6 +5,8 @@ import hellfirepvp.modularmachinery.ModularMachinery; import hellfirepvp.modularmachinery.common.CommonProxy; import net.minecraft.block.state.IBlockState; +import net.minecraft.client.resources.I18n; +import net.minecraft.client.util.ITooltipFlag; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntity; @@ -12,9 +14,13 @@ import net.minecraft.util.EnumHand; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; +import org.jetbrains.annotations.NotNull; import javax.annotation.Nonnull; import javax.annotation.Nullable; +import java.util.List; public class BlockMEFluidInputBus extends BlockMEFluidBus { @@ -42,4 +48,12 @@ public boolean onBlockActivated(@Nonnull final World worldIn, @Nonnull final Blo public TileEntity createTileEntity(final World world, final IBlockState state) { return new MEFluidInputBus(); } + + @Override + @SideOnly(Side.CLIENT) + public void addInformation(@NotNull ItemStack stack, @Nullable World worldIn, @NotNull List tooltip, @NotNull ITooltipFlag flagIn) { + super.addInformation(stack, worldIn, tooltip, flagIn); + tooltip.add(I18n.format("tooltip.groupinput.block")); + } + } diff --git a/src/main/java/github/kasuminova/mmce/common/block/appeng/BlockMEGasInputBus.java b/src/main/java/github/kasuminova/mmce/common/block/appeng/BlockMEGasInputBus.java index 31cd7cba..01e6dd72 100644 --- a/src/main/java/github/kasuminova/mmce/common/block/appeng/BlockMEGasInputBus.java +++ b/src/main/java/github/kasuminova/mmce/common/block/appeng/BlockMEGasInputBus.java @@ -5,6 +5,8 @@ import hellfirepvp.modularmachinery.ModularMachinery; import hellfirepvp.modularmachinery.common.CommonProxy; import net.minecraft.block.state.IBlockState; +import net.minecraft.client.resources.I18n; +import net.minecraft.client.util.ITooltipFlag; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntity; @@ -12,9 +14,13 @@ import net.minecraft.util.EnumHand; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; +import org.jetbrains.annotations.NotNull; import javax.annotation.Nonnull; import javax.annotation.Nullable; +import java.util.List; public class BlockMEGasInputBus extends BlockMEGasBus { @@ -43,4 +49,11 @@ public TileEntity createTileEntity(final World world, final IBlockState state) { return new MEGasInputBus(); } + @Override + @SideOnly(Side.CLIENT) + public void addInformation(@NotNull ItemStack stack, @Nullable World worldIn, @NotNull List tooltip, @NotNull ITooltipFlag flagIn) { + super.addInformation(stack, worldIn, tooltip, flagIn); + tooltip.add(I18n.format("tooltip.groupinput.block")); + } + } diff --git a/src/main/java/github/kasuminova/mmce/common/block/appeng/BlockMEItemInputBus.java b/src/main/java/github/kasuminova/mmce/common/block/appeng/BlockMEItemInputBus.java index b936db80..a0059bb3 100644 --- a/src/main/java/github/kasuminova/mmce/common/block/appeng/BlockMEItemInputBus.java +++ b/src/main/java/github/kasuminova/mmce/common/block/appeng/BlockMEItemInputBus.java @@ -7,6 +7,8 @@ import hellfirepvp.modularmachinery.common.lib.ItemsMM; import hellfirepvp.modularmachinery.common.util.IOInventory; import net.minecraft.block.state.IBlockState; +import net.minecraft.client.resources.I18n; +import net.minecraft.client.util.ITooltipFlag; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; @@ -18,9 +20,13 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; +import org.jetbrains.annotations.NotNull; import javax.annotation.Nonnull; import javax.annotation.Nullable; +import java.util.List; public class BlockMEItemInputBus extends BlockMEItemBus { @Override @@ -118,4 +124,12 @@ public void onBlockPlacedBy(@Nonnull final World worldIn, bus.readConfigInventoryNBT(tag.getCompoundTag("configInventory")); } } + + @Override + @SideOnly(Side.CLIENT) + public void addInformation(@NotNull ItemStack stack, @Nullable World worldIn, @NotNull List tooltip, @NotNull ITooltipFlag flagIn) { + super.addInformation(stack, worldIn, tooltip, flagIn); + tooltip.add(I18n.format("tooltip.groupinput.block")); + } + } diff --git a/src/main/java/github/kasuminova/mmce/common/block/appeng/BlockMEPatternMirrorImage.java b/src/main/java/github/kasuminova/mmce/common/block/appeng/BlockMEPatternMirrorImage.java index a61085c4..910a0931 100644 --- a/src/main/java/github/kasuminova/mmce/common/block/appeng/BlockMEPatternMirrorImage.java +++ b/src/main/java/github/kasuminova/mmce/common/block/appeng/BlockMEPatternMirrorImage.java @@ -8,7 +8,10 @@ import net.minecraft.block.SoundType; import net.minecraft.block.material.Material; import net.minecraft.block.state.IBlockState; +import net.minecraft.client.resources.I18n; +import net.minecraft.client.util.ITooltipFlag; import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.BlockRenderLayer; @@ -20,9 +23,11 @@ import net.minecraft.world.World; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; +import org.jetbrains.annotations.NotNull; import javax.annotation.Nonnull; import javax.annotation.Nullable; +import java.util.List; public class BlockMEPatternMirrorImage extends BlockMachineComponent { @@ -98,4 +103,11 @@ public BlockRenderLayer getRenderLayer() { public EnumBlockRenderType getRenderType(@Nonnull IBlockState state) { return EnumBlockRenderType.MODEL; } + + @Override + @SideOnly(Side.CLIENT) + public void addInformation(@NotNull ItemStack stack, @Nullable World worldIn, @NotNull List tooltip, @NotNull ITooltipFlag flagIn) { + super.addInformation(stack, worldIn, tooltip, flagIn); + tooltip.add(I18n.format("tooltip.mepatternmirrorimage")); + } } diff --git a/src/main/java/github/kasuminova/mmce/common/block/appeng/BlockMEPatternProvider.java b/src/main/java/github/kasuminova/mmce/common/block/appeng/BlockMEPatternProvider.java index 566078ec..7f5175cb 100644 --- a/src/main/java/github/kasuminova/mmce/common/block/appeng/BlockMEPatternProvider.java +++ b/src/main/java/github/kasuminova/mmce/common/block/appeng/BlockMEPatternProvider.java @@ -10,6 +10,8 @@ import hellfirepvp.modularmachinery.common.CommonProxy; import hellfirepvp.modularmachinery.common.lib.ItemsMM; import net.minecraft.block.state.IBlockState; +import net.minecraft.client.resources.I18n; +import net.minecraft.client.util.ITooltipFlag; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; @@ -21,9 +23,13 @@ import net.minecraft.util.text.TextComponentTranslation; import net.minecraft.world.World; import net.minecraftforge.event.ForgeEventFactory; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; +import org.jetbrains.annotations.NotNull; import javax.annotation.Nonnull; import javax.annotation.Nullable; +import java.util.List; public class BlockMEPatternProvider extends BlockMEMachineComponent { @@ -120,4 +126,12 @@ public void onBlockPlacedBy(@Nonnull final World worldIn, provider.readProviderNBT(tag.getCompoundTag("patternProvider")); } } -} + + @Override + @SideOnly(Side.CLIENT) + public void addInformation(@NotNull ItemStack stack, @Nullable World worldIn, @NotNull List tooltip, @NotNull ITooltipFlag flagIn) { + super.addInformation(stack, worldIn, tooltip, flagIn); + tooltip.add(I18n.format("tooltip.groupinput.block")); + } + +} \ No newline at end of file diff --git a/src/main/java/github/kasuminova/mmce/common/container/ContainerMEPatternProvider.java b/src/main/java/github/kasuminova/mmce/common/container/ContainerMEPatternProvider.java index 0252ee02..ce3eccaa 100644 --- a/src/main/java/github/kasuminova/mmce/common/container/ContainerMEPatternProvider.java +++ b/src/main/java/github/kasuminova/mmce/common/container/ContainerMEPatternProvider.java @@ -10,8 +10,10 @@ import appeng.helpers.InventoryAction; import appeng.tile.inventory.AppEngInternalInventory; import appeng.util.Platform; +import github.kasuminova.mmce.common.network.PktMEPatternProviderHandlerItems; import github.kasuminova.mmce.common.tile.MEPatternProvider; import github.kasuminova.mmce.common.util.AEFluidInventoryUpgradeable; +import hellfirepvp.modularmachinery.ModularMachinery; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.inventory.IContainerListener; @@ -32,6 +34,11 @@ public class ContainerMEPatternProvider extends AEBaseContainer implements IFlui public ContainerMEPatternProvider(final MEPatternProvider owner, final EntityPlayer player) { super(player.inventory, owner); this.owner = owner; + + if (player instanceof EntityPlayerMP p) { + ModularMachinery.NET_CHANNEL.sendTo(new PktMEPatternProviderHandlerItems(owner), p); + } + this.tankSync = new FluidSyncHelper(owner.getSubFluidHandler(), 0); this.bindPlayerInventory(getInventoryPlayer(), 0, 114); diff --git a/src/main/java/github/kasuminova/mmce/common/event/machine/MachineEvent.java b/src/main/java/github/kasuminova/mmce/common/event/machine/MachineEvent.java index 35da05f2..44207a74 100644 --- a/src/main/java/github/kasuminova/mmce/common/event/machine/MachineEvent.java +++ b/src/main/java/github/kasuminova/mmce/common/event/machine/MachineEvent.java @@ -5,6 +5,7 @@ import github.kasuminova.mmce.common.handler.UpgradeMachineEventHandler; import github.kasuminova.mmce.common.helper.IMachineController; import hellfirepvp.modularmachinery.ModularMachinery; +import hellfirepvp.modularmachinery.common.crafting.helper.ProcessingComponent; import hellfirepvp.modularmachinery.common.machine.DynamicMachine; import hellfirepvp.modularmachinery.common.tiles.base.MachineComponentTileNotifiable; import hellfirepvp.modularmachinery.common.tiles.base.TileMultiblockMachineController; @@ -15,6 +16,7 @@ import stanhebben.zenscript.annotations.ZenSetter; import java.util.List; +import java.util.Map; @ZenRegister @ZenClass("mods.modularmachinery.MachineEvent") @@ -48,11 +50,13 @@ public void postEvent() { } public void postEventToComponents() { - for (TileEntity tileEntity : controller.getFoundComponents().keySet()) { - if (tileEntity instanceof final MachineComponentTileNotifiable componentTile) { - componentTile.onMachineEvent(this); - if (isCanceled()) { - break; + for (Map> value : controller.getFoundComponents().values()) { + for (TileEntity tileEntity : value.keySet()) { + if (tileEntity instanceof final MachineComponentTileNotifiable componentTile) { + componentTile.onMachineEvent(this); + if (isCanceled()) { + break; + } } } } diff --git a/src/main/java/github/kasuminova/mmce/common/handler/EventHandler.java b/src/main/java/github/kasuminova/mmce/common/handler/EventHandler.java index 9fd3eadb..1088f7de 100644 --- a/src/main/java/github/kasuminova/mmce/common/handler/EventHandler.java +++ b/src/main/java/github/kasuminova/mmce/common/handler/EventHandler.java @@ -3,10 +3,12 @@ import appeng.container.AEBaseContainer; import github.kasuminova.mmce.common.network.PktPerformanceReport; import hellfirepvp.modularmachinery.ModularMachinery; +import hellfirepvp.modularmachinery.common.CommonProxy; import hellfirepvp.modularmachinery.common.base.Mods; import hellfirepvp.modularmachinery.common.block.BlockController; import hellfirepvp.modularmachinery.common.container.ContainerBase; import hellfirepvp.modularmachinery.common.item.ItemBlockController; +import hellfirepvp.modularmachinery.common.tiles.base.MachineGroupInput; import hellfirepvp.modularmachinery.common.tiles.base.SelectiveUpdateTileEntity; import hellfirepvp.modularmachinery.common.tiles.base.TileEntitySynchronized; import hellfirepvp.modularmachinery.common.tiles.base.TileMultiblockMachineController; @@ -16,6 +18,8 @@ import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.EnumActionResult; +import net.minecraft.util.EnumHand; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import net.minecraftforge.event.entity.player.PlayerInteractEvent; @@ -150,7 +154,29 @@ public void onBlockPlaced(BlockEvent.PlaceEvent event) { event.setCanceled(true); } } catch (Exception e) { - ModularMachinery.log.warn("Invalid owner uuid " + ownerUUIDStr, e); + ModularMachinery.log.warn("Invalid owner uuid {}", ownerUUIDStr, e); } } -} + + /** + * 打开用于配置MachineGroupInput的配置Gui + * + */ + @SubscribeEvent + public void onBlockPlaced(PlayerInteractEvent.RightClickBlock event) { + var player = event.getEntityPlayer(); + var pos = event.getPos(); + var tile = event.getWorld().getTileEntity(pos); + if (player.isSneaking() && tile instanceof MachineGroupInput m && m.canGroupInput()) { + if (!player.getHeldItem(EnumHand.MAIN_HAND).isEmpty() + || !player.getHeldItem(EnumHand.OFF_HAND).isEmpty()) return; + + if (!player.world.isRemote) { + player.openGui(ModularMachinery.instance, CommonProxy.GuiType.GUI_GROUP_INPUT_CONFIG.ordinal(), player.world, pos.getX(), pos.getY(), pos.getZ()); + } + + event.setCanceled(true); + event.setCancellationResult(EnumActionResult.SUCCESS); + } + } +} \ No newline at end of file diff --git a/src/main/java/github/kasuminova/mmce/common/network/PktMEPatternProviderAction.java b/src/main/java/github/kasuminova/mmce/common/network/PktMEPatternProviderAction.java index f29612d8..eb9ca5d3 100644 --- a/src/main/java/github/kasuminova/mmce/common/network/PktMEPatternProviderAction.java +++ b/src/main/java/github/kasuminova/mmce/common/network/PktMEPatternProviderAction.java @@ -43,6 +43,7 @@ public IMessage onMessage(final PktMEPatternProviderAction message, final Messag case ENABLE_DEFAULT_MODE -> provider.setWorkMode(MEPatternProvider.WorkModeSetting.DEFAULT); case ENABLE_CRAFTING_LOCK_MODE -> provider.setWorkMode(MEPatternProvider.WorkModeSetting.CRAFTING_LOCK_MODE); case ENABLE_ENHANCED_BLOCKING_MODE -> provider.setWorkMode(MEPatternProvider.WorkModeSetting.ENHANCED_BLOCKING_MODE); + case ENABLE_ENHANCED_ISOLATION_INPUT -> provider.setWorkMode(MEPatternProvider.WorkModeSetting.ISOLATION_INPUT); case RETURN_ITEMS -> provider.returnItemsScheduled(); } }); @@ -54,6 +55,7 @@ public enum Action { ENABLE_DEFAULT_MODE, ENABLE_CRAFTING_LOCK_MODE, ENABLE_ENHANCED_BLOCKING_MODE, + ENABLE_ENHANCED_ISOLATION_INPUT, RETURN_ITEMS, } diff --git a/src/main/java/github/kasuminova/mmce/common/network/PktMEPatternProviderHandlerItems.java b/src/main/java/github/kasuminova/mmce/common/network/PktMEPatternProviderHandlerItems.java index 65d12d83..064e481c 100644 --- a/src/main/java/github/kasuminova/mmce/common/network/PktMEPatternProviderHandlerItems.java +++ b/src/main/java/github/kasuminova/mmce/common/network/PktMEPatternProviderHandlerItems.java @@ -2,17 +2,10 @@ import github.kasuminova.mmce.client.gui.GuiMEPatternProvider; import github.kasuminova.mmce.common.tile.MEPatternProvider; -import github.kasuminova.mmce.common.util.InfItemFluidHandler; -import hellfirepvp.modularmachinery.common.base.Mods; import io.netty.buffer.ByteBuf; -import mekanism.api.gas.GasStack; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiScreen; -import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; -import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.fml.common.FMLCommonHandler; -import net.minecraftforge.fml.common.Optional; import net.minecraftforge.fml.common.network.ByteBufUtils; import net.minecraftforge.fml.common.network.simpleimpl.IMessage; import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler; @@ -20,111 +13,39 @@ import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; -import java.util.stream.IntStream; - public class PktMEPatternProviderHandlerItems implements IMessage, IMessageHandler { - private final List itemStackList = new ArrayList<>(); - private final List fluidStackList = new ArrayList<>(); - private final List gasStackList = new ArrayList<>(); + private NBTTagCompound nbt; public PktMEPatternProviderHandlerItems() { } public PktMEPatternProviderHandlerItems(final MEPatternProvider patternProvider) { - InfItemFluidHandler infHandler = patternProvider.getInfHandler(); - infHandler.getItemStackList().stream() - .filter(stack -> !stack.isEmpty()) - .forEach(itemStackList::add); - infHandler.getFluidStackList().stream() - .filter(Objects::nonNull) - .forEach(fluidStackList::add); - if (Mods.MEKANISM.isPresent() && Mods.MEKENG.isPresent()) { - addGasToList(infHandler); - } + nbt = patternProvider.writeProviderHandlerNBT(new NBTTagCompound()); } @SideOnly(Side.CLIENT) protected static void processPacket(final PktMEPatternProviderHandlerItems message) { - List itemStackList = message.itemStackList; - List fluidStackList = message.fluidStackList; - List gasStackList = message.gasStackList; GuiScreen cur = Minecraft.getMinecraft().currentScreen; if (!(cur instanceof GuiMEPatternProvider patternProvider)) { return; } - Minecraft.getMinecraft().addScheduledTask(() -> patternProvider.setStackList(itemStackList, fluidStackList, gasStackList)); - } - - @SuppressWarnings("unchecked") - @Optional.Method(modid = "mekanism") - private void addGasToList(final InfItemFluidHandler infHandler) { - List gasStackList = (List) this.gasStackList; - infHandler.getGasStackList().stream() - .filter(Objects::nonNull) - .map(GasStack.class::cast) - .forEach(gasStackList::add); + Minecraft.getMinecraft().addScheduledTask(() -> patternProvider.setStackList(message.nbt)); } @Override public void fromBytes(final ByteBuf buf) { - int itemStackListSize = buf.readInt(); - IntStream.range(0, itemStackListSize) - .mapToObj(i -> ByteBufUtils.readItemStack(buf)) - .filter(read -> !read.isEmpty()) - .forEach(itemStackList::add); - - int fluidStackListSize = buf.readInt(); - IntStream.range(0, fluidStackListSize) - .mapToObj(i -> FluidStack.loadFluidStackFromNBT(ByteBufUtils.readTag(buf))) - .filter(Objects::nonNull) - .forEach(fluidStackList::add); - - if (Mods.MEKANISM.isPresent() && Mods.MEKENG.isPresent()) { - fromBytesMekGas(buf); - } - } - - @SuppressWarnings("unchecked") - @Optional.Method(modid = "mekanism") - private void fromBytesMekGas(final ByteBuf buf) { - List gasStackList = (List) this.gasStackList; - - int gasStackListSize = buf.readInt(); - IntStream.range(0, gasStackListSize) - .mapToObj(i -> GasStack.readFromNBT(ByteBufUtils.readTag(buf))) - .filter(Objects::nonNull) - .forEach(gasStackList::add); + nbt = ByteBufUtils.readTag(buf); } @Override public void toBytes(final ByteBuf buf) { - buf.writeInt(itemStackList.size()); - itemStackList.forEach(stack -> ByteBufUtils.writeItemStack(buf, stack)); - - buf.writeInt(fluidStackList.size()); - fluidStackList.forEach(stack -> ByteBufUtils.writeTag(buf, stack.writeToNBT(new NBTTagCompound()))); - - if (Mods.MEKANISM.isPresent() && Mods.MEKENG.isPresent()) { - toBytesMekGas(buf); - } - } - - @SuppressWarnings("unchecked") - @Optional.Method(modid = "mekanism") - private void toBytesMekGas(final ByteBuf buf) { - List gasStackList = (List) this.gasStackList; - - buf.writeInt(gasStackList.size()); - gasStackList.forEach(stack -> ByteBufUtils.writeTag(buf, stack.write(new NBTTagCompound()))); + ByteBufUtils.writeTag(buf, nbt); } @Override public IMessage onMessage(final PktMEPatternProviderHandlerItems message, final MessageContext ctx) { - if (FMLCommonHandler.instance().getSide().isClient()) { + if (ctx.side.isClient()) { processPacket(message); } return null; diff --git a/src/main/java/github/kasuminova/mmce/common/tile/MEFluidInputBus.java b/src/main/java/github/kasuminova/mmce/common/tile/MEFluidInputBus.java index 477e33ab..cc9bf3ff 100644 --- a/src/main/java/github/kasuminova/mmce/common/tile/MEFluidInputBus.java +++ b/src/main/java/github/kasuminova/mmce/common/tile/MEFluidInputBus.java @@ -187,9 +187,19 @@ public MachineComponent provideComponent() { public IFluidHandler getContainerProvider() { return tanks; } + + @Override + public long getGroupID() { + return getGroupId(); + } }; } + @Override + public boolean canGroupInput() { + return true; + } + @Override public void markNoUpdate() { if (needsUpdate()) { diff --git a/src/main/java/github/kasuminova/mmce/common/tile/MEGasInputBus.java b/src/main/java/github/kasuminova/mmce/common/tile/MEGasInputBus.java index 29581c16..f43a5a5c 100644 --- a/src/main/java/github/kasuminova/mmce/common/tile/MEGasInputBus.java +++ b/src/main/java/github/kasuminova/mmce/common/tile/MEGasInputBus.java @@ -182,6 +182,11 @@ private IAEGasStack insertStackToAE(final IMEMonitor inv, final Gas return Platform.poweredInsert(proxy.getEnergy(), inv, Objects.requireNonNull(AEGasStack.of(stack)), source); } + @Override + public boolean canGroupInput() { + return true; + } + @Nullable @Override public MachineComponent provideComponent() { @@ -195,6 +200,11 @@ public ComponentType getComponentType() { public IExtendedGasHandler getContainerProvider() { return handler; } + + @Override + public long getGroupID() { + return getGroupId(); + } }; } diff --git a/src/main/java/github/kasuminova/mmce/common/tile/MEItemInputBus.java b/src/main/java/github/kasuminova/mmce/common/tile/MEItemInputBus.java index e11cc829..33b3a2da 100644 --- a/src/main/java/github/kasuminova/mmce/common/tile/MEItemInputBus.java +++ b/src/main/java/github/kasuminova/mmce/common/tile/MEItemInputBus.java @@ -99,9 +99,19 @@ public MachineComponent.ItemBus provideComponent() { public IOInventory getContainerProvider() { return inventory; } + + @Override + public long getGroupID() { + return getGroupId(); + } }; } + @Override + public boolean canGroupInput() { + return true; + } + @Nonnull @Override public TickingRequest getTickingRequest(@Nonnull final IGridNode node) { diff --git a/src/main/java/github/kasuminova/mmce/common/tile/MEPatternMirrorImage.java b/src/main/java/github/kasuminova/mmce/common/tile/MEPatternMirrorImage.java index 312f3203..45df34da 100644 --- a/src/main/java/github/kasuminova/mmce/common/tile/MEPatternMirrorImage.java +++ b/src/main/java/github/kasuminova/mmce/common/tile/MEPatternMirrorImage.java @@ -1,9 +1,7 @@ package github.kasuminova.mmce.common.tile; +import github.kasuminova.mmce.common.tile.base.MachineCombinationComponent; import github.kasuminova.mmce.common.util.InfItemFluidHandler; -import hellfirepvp.modularmachinery.common.crafting.ComponentType; -import hellfirepvp.modularmachinery.common.lib.ComponentTypesMM; -import hellfirepvp.modularmachinery.common.machine.IOType; import hellfirepvp.modularmachinery.common.machine.MachineComponent; import hellfirepvp.modularmachinery.common.tiles.base.MachineComponentTile; import hellfirepvp.modularmachinery.common.tiles.base.SelectiveUpdateTileEntity; @@ -12,12 +10,15 @@ import net.minecraft.tileentity.TileEntity; import net.minecraft.util.math.BlockPos; import net.minecraft.world.WorldServer; +import org.jetbrains.annotations.NotNull; import javax.annotation.Nullable; +import java.util.Collection; +import java.util.Collections; -public class MEPatternMirrorImage extends TileColorableMachineComponent implements SelectiveUpdateTileEntity, MachineComponentTile { +public class MEPatternMirrorImage extends TileColorableMachineComponent implements SelectiveUpdateTileEntity, MachineComponentTile, MachineCombinationComponent { - public BlockPos providerPos; + public BlockPos providerPos; public InfItemFluidHandler handler; public MEPatternMirrorImage() { @@ -29,27 +30,23 @@ public MEPatternMirrorImage() { public MachineComponent provideComponent() { if (!this.world.isRemote && providerPos != null && ((WorldServer) this.world).getChunkProvider().chunkExists(providerPos.getX() >> 4, providerPos.getZ() >> 4)) { TileEntity tileEntity = this.world.getTileEntity(providerPos); - if (tileEntity instanceof MEPatternProvider) { - return new MachineComponent<>(IOType.INPUT) { - public ComponentType getComponentType() { - return ComponentTypesMM.COMPONENT_ITEM_FLUID_GAS; - } - - public InfItemFluidHandler getContainerProvider() { - return ((MEPatternProvider) tileEntity).getInfHandler(); - } - }; + if (tileEntity instanceof MEPatternProvider mep) { + return mep.provideComponent(); } } - return new MachineComponent<>(IOType.INPUT) { - public ComponentType getComponentType() { - return ComponentTypesMM.COMPONENT_ITEM_FLUID_GAS; - } + return null; + } - public InfItemFluidHandler getContainerProvider() { - return handler; + @NotNull + @Override + public Collection> provideComponents() { + if (!this.world.isRemote && providerPos != null && ((WorldServer) this.world).getChunkProvider().chunkExists(providerPos.getX() >> 4, providerPos.getZ() >> 4)) { + TileEntity tileEntity = this.world.getTileEntity(providerPos); + if (tileEntity instanceof MEPatternProvider mep) { + return mep.provideComponents(); } - }; + } + return Collections.emptyList(); } @Override diff --git a/src/main/java/github/kasuminova/mmce/common/tile/MEPatternProvider.java b/src/main/java/github/kasuminova/mmce/common/tile/MEPatternProvider.java index 3f942a47..b4b603d4 100644 --- a/src/main/java/github/kasuminova/mmce/common/tile/MEPatternProvider.java +++ b/src/main/java/github/kasuminova/mmce/common/tile/MEPatternProvider.java @@ -42,6 +42,7 @@ import github.kasuminova.mmce.common.event.recipe.RecipeFinishEvent; import github.kasuminova.mmce.common.network.PktMEPatternProviderHandlerItems; import github.kasuminova.mmce.common.tile.base.MEMachineComponent; +import github.kasuminova.mmce.common.tile.base.MachineCombinationComponent; import github.kasuminova.mmce.common.util.AEFluidInventoryUpgradeable; import github.kasuminova.mmce.common.util.InfItemFluidHandler; import github.kasuminova.mmce.common.util.PatternItemFilter; @@ -76,34 +77,38 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; import java.util.EnumSet; import java.util.List; import java.util.Objects; import java.util.stream.IntStream; -public class MEPatternProvider extends MEMachineComponent implements ICraftingProvider, IAEAppEngInventory, IAEFluidInventory, MachineComponentTileNotifiable, IInterfaceHost, ICustomNameObject { +public class MEPatternProvider extends MEMachineComponent implements ICraftingProvider, IAEAppEngInventory, IAEFluidInventory, MachineComponentTileNotifiable, IInterfaceHost, ICustomNameObject , MachineCombinationComponent { public static final int PATTERNS = 36; public static final int SUB_ITEM_HANDLER_SLOTS = 2; private static final ItemStack item = new ItemStack(ItemsMM.mePatternProvider); protected final AppEngInternalInventory subItemHandler = new AppEngInternalInventory(this, SUB_ITEM_HANDLER_SLOTS); protected final AEFluidInventoryUpgradeable subFluidHandler = new AEFluidInventoryUpgradeable(this, 1, Integer.MAX_VALUE); - protected final InfItemFluidHandler handler = new InfItemFluidHandler(subItemHandler, subFluidHandler); protected final AppEngInternalInventory patterns = new AppEngInternalInventory(this, PATTERNS, 1, PatternItemFilter.INSTANCE); - protected final List details = new ObjectArrayList<>(PATTERNS); + protected final ICraftingPatternDetails[] details = new ICraftingPatternDetails[PATTERNS]; private final DualityInterface duality = new DualityInterface(this.proxy, this); protected WorkModeSetting workMode = WorkModeSetting.DEFAULT; protected volatile boolean machineCompleted = true; protected boolean shouldReturnItems = false; - protected boolean handlerDirty = false; + public boolean handlerDirty = false; protected int currentPatternIdx = -1; protected ICraftingPatternDetails currentPattern = null; private String customName; private String machineName; + protected final InfItemFluidHandler handler = new InfItemFluidHandler(subItemHandler, subFluidHandler); + protected final List> combinationComponents = new ObjectArrayList<>(); + public MEPatternProvider() { // Initialize details... - IntStream.range(0, 36).mapToObj(i -> null).forEach(details::add); // Set handler onChanged consumer... handler.setOnItemChanged(slot -> { handlerDirty = true; @@ -119,11 +124,61 @@ public MEPatternProvider() { markChunkDirty(); }); } + + for (int i = 0; i < PATTERNS; i++) { + combinationComponents.add(new MachineComponent<>(IOType.INPUT) { + private final InfItemFluidHandler handler = new InfItemFluidHandler(subItemHandler, subFluidHandler); + private final long groupId = getUniqueGroupID(); + + { + handler.setOnItemChanged(slot -> { + handlerDirty = true; + markChunkDirty(); + }); + handler.setOnFluidChanged(slot -> { + handlerDirty = true; + markChunkDirty(); + }); + if (Mods.MEKANISM.isPresent() && Mods.MEKENG.isPresent()) { + handler.setOnGasChanged(slot -> { + handlerDirty = true; + markChunkDirty(); + }); + } + } + + @Override + public ComponentType getComponentType() { + return ComponentTypesMM.COMPONENT_ITEM_FLUID_GAS; + } + + @Override + public InfItemFluidHandler getContainerProvider() { + return handler; + } + + @Override + public long getGroupID() { + return groupId; + } + }); + } + } + + public List> getCombinationComponents() { + return combinationComponents; + } + + @Override + public boolean canGroupInput() { + return true; } @Nullable @Override public MachineComponent provideComponent() { + if (workMode == WorkModeSetting.ISOLATION_INPUT) return null; + return new MachineComponent<>(IOType.INPUT) { @Override public ComponentType getComponentType() { @@ -134,9 +189,22 @@ public ComponentType getComponentType() { public InfItemFluidHandler getContainerProvider() { return handler; } + + @Override + public long getGroupID() { + return getGroupId(); + } }; } + @Nonnull + @Override + public Collection> provideComponents() { + if (workMode == WorkModeSetting.ISOLATION_INPUT) + return combinationComponents; + return Collections.emptyList(); + } + @MENetworkEventSubscribe public void stateChange(final MENetworkChannelsChanged change) { this.notifyNeighbors(); @@ -152,7 +220,7 @@ public void provideCrafting(final ICraftingProviderHelper craftingTracker) { if (!proxy.isActive() || !proxy.isPowered()) { return; } - details.stream() + Arrays.stream(details) .filter(Objects::nonNull) .forEach(detail -> craftingTracker.addCraftingOption(this, detail)); } @@ -163,6 +231,17 @@ public boolean pushPattern(final ICraftingPatternDetails patternDetails, final I return false; } + InfItemFluidHandler handler = null; + if (workMode == WorkModeSetting.ISOLATION_INPUT) { + for (var i = 0; i < details.length; i++) { + if (patternDetails.equals(details[i])) { + handler = (InfItemFluidHandler) combinationComponents.get(i).getContainerProvider(); + break; + } + } + } else handler = this.handler; + if (handler == null) return false; + int slots = table.getSizeInventory(); for (int slot = 0; slot < slots; slot++) { ItemStack stackInSlot = table.getStackInSlot(slot); @@ -233,8 +312,8 @@ protected void refreshPatterns() { for (int i = 0; i < PATTERNS; i++) { refreshPattern(i); } - if (currentPatternIdx != -1 && currentPatternIdx < details.size()) { - setCurrentPattern(details.get(currentPatternIdx)); + if (currentPatternIdx != -1 && currentPatternIdx < details.length) { + setCurrentPattern(details[currentPatternIdx]); } try { this.getProxy().getGrid().postEvent(new MENetworkCraftingPatternChange(this, this.getProxy().getNode())); @@ -243,7 +322,7 @@ protected void refreshPatterns() { } protected void refreshPattern(final int slot) { - details.set(slot, null); + details[slot] = null; ItemStack pattern = patterns.getStackInSlot(slot); Item item = pattern.getItem(); @@ -253,7 +332,7 @@ protected void refreshPattern(final int slot) { ICraftingPatternDetails detail = patternItem.getPatternForItem(pattern, getWorld()); if (detail != null && !detail.isCraftable()) { - details.set(slot, detail); + details[slot] = detail; } if (workMode == WorkModeSetting.ENHANCED_BLOCKING_MODE && slot == currentPatternIdx) { @@ -273,58 +352,68 @@ public void returnItemsScheduled() { } } - public void returnItems() { + private void returnItems() { if (!shouldReturnItems || !proxy.isActive() || !proxy.isPowered()) { return; } shouldReturnItems = false; machineCompleted = true; + synchronized (handler) { + returnItem(handler); + } + + for (var component : combinationComponents) { + synchronized (component.getContainerProvider()) { + returnItem((InfItemFluidHandler) component.getContainerProvider()); + } + } + + handlerDirty = true; + markChunkDirty(); + } + + private void returnItem(InfItemFluidHandler handler) { try { - synchronized (handler) { - List itemStackList = handler.getItemStackList(); - List fluidStackList = handler.getFluidStackList(); + List itemStackList = handler.getItemStackList(); + List fluidStackList = handler.getFluidStackList(); - IItemStorageChannel itemChannel = AEApi.instance().storage().getStorageChannel(IItemStorageChannel.class); - IMEMonitor itemInv = proxy.getStorage().getInventory(itemChannel); + IItemStorageChannel itemChannel = AEApi.instance().storage().getStorageChannel(IItemStorageChannel.class); + IMEMonitor itemInv = proxy.getStorage().getInventory(itemChannel); - for (int i = 0; i < itemStackList.size(); i++) { - final ItemStack stack = itemStackList.get(i); - if (stack.isEmpty()) { - continue; - } - IAEItemStack notInserted = insertStackToAE(itemInv, itemChannel.createStack(stack)); - if (notInserted != null) { - itemStackList.set(i, notInserted.createItemStack()); - } else { - itemStackList.set(i, ItemStack.EMPTY); - } + for (int i = 0; i < itemStackList.size(); i++) { + final ItemStack stack = itemStackList.get(i); + if (stack.isEmpty()) { + continue; } - - IFluidStorageChannel fluidChannel = AEApi.instance().storage().getStorageChannel(IFluidStorageChannel.class); - IMEMonitor fluidInv = proxy.getStorage().getInventory(fluidChannel); - for (int i = 0; i < fluidStackList.size(); i++) { - final FluidStack stack = fluidStackList.get(i); - if (stack == null) { - continue; - } - IAEFluidStack notInserted = insertStackToAE(fluidInv, fluidChannel.createStack(stack)); - if (notInserted != null) { - fluidStackList.set(i, notInserted.getFluidStack()); - } else { - fluidStackList.set(i, null); - } + IAEItemStack notInserted = insertStackToAE(itemInv, itemChannel.createStack(stack)); + if (notInserted != null) { + itemStackList.set(i, notInserted.createItemStack()); + } else { + itemStackList.set(i, ItemStack.EMPTY); } + } - if (Mods.MEKANISM.isPresent() && Mods.MEKENG.isPresent()) { - returnGases(); + IFluidStorageChannel fluidChannel = AEApi.instance().storage().getStorageChannel(IFluidStorageChannel.class); + IMEMonitor fluidInv = proxy.getStorage().getInventory(fluidChannel); + for (int i = 0; i < fluidStackList.size(); i++) { + final FluidStack stack = fluidStackList.get(i); + if (stack == null) { + continue; } + IAEFluidStack notInserted = insertStackToAE(fluidInv, fluidChannel.createStack(stack)); + if (notInserted != null) { + fluidStackList.set(i, notInserted.getFluidStack()); + } else { + fluidStackList.set(i, null); + } + } + + if (Mods.MEKANISM.isPresent() && Mods.MEKENG.isPresent()) { + returnGases(); } } catch (GridAccessException ignored) { } - - handlerDirty = true; - markChunkDirty(); } @Optional.Method(modid = "mekeng") @@ -363,7 +452,11 @@ private void setCurrentPattern(final ICraftingPatternDetails pattern) { resetCurrentPattern(); return; } - currentPatternIdx = details.indexOf(pattern); + for (var i = 0; i < details.length; i++) { + if (pattern.equals(details[i])) { + currentPatternIdx = i; + } + } currentPattern = pattern; } @@ -388,6 +481,10 @@ public WorkModeSetting getWorkMode() { } public void setWorkMode(final WorkModeSetting workMode) { + if (this.workMode == WorkModeSetting.ISOLATION_INPUT + || workMode == WorkModeSetting.ISOLATION_INPUT) { + returnItemsScheduled(); + } this.workMode = workMode; if (workMode != WorkModeSetting.CRAFTING_LOCK_MODE) { this.machineCompleted = true; @@ -432,9 +529,9 @@ public void readCustomNBT(final NBTTagCompound compound) { public void readProviderNBT(final NBTTagCompound compound) { subItemHandler.readFromNBT(compound, "subItemHandler"); subFluidHandler.readFromNBT(compound, "subFluidHandler"); - handler.readFromNBT(compound, "handler"); patterns.readFromNBT(compound, "patterns"); - workMode = WorkModeSetting.values()[compound.getByte("workMode")]; + + readProviderHandlerNBT(compound, false); if (compound.hasKey("currentPatternIdx") && workMode == WorkModeSetting.ENHANCED_BLOCKING_MODE) { currentPatternIdx = compound.getByte("currentPatternIdx"); @@ -443,6 +540,28 @@ public void readProviderNBT(final NBTTagCompound compound) { } } + public void readProviderHandlerNBT(final NBTTagCompound compound, boolean allUp) { + workMode = WorkModeSetting.values()[compound.getByte("workMode")]; + if (allUp) { + handler.readFromNBT(compound, "handler"); + var nbt = compound.getCompoundTag("components"); + for (var i = 0; i < combinationComponents.size(); i++) { + var handler = (InfItemFluidHandler) combinationComponents.get(i).getContainerProvider(); + handler.readFromNBT(nbt, "handler#" + i); + } + } else { + if (workMode == WorkModeSetting.ISOLATION_INPUT && compound.hasKey("components")) { + var nbt = compound.getCompoundTag("components"); + for (var i = 0; i < combinationComponents.size(); i++) { + var subTagName = "handler#" + i; + if (!nbt.hasKey(subTagName)) continue; + var handler = (InfItemFluidHandler) combinationComponents.get(i).getContainerProvider(); + handler.readFromNBT(nbt, subTagName); + } + } else handler.readFromNBT(compound, "handler"); + } + } + @Override public void writeCustomNBT(final NBTTagCompound compound) { super.writeCustomNBT(compound); @@ -454,16 +573,28 @@ public void writeCustomNBT(final NBTTagCompound compound) { } public NBTTagCompound writeProviderNBT(final NBTTagCompound compound) { - handler.writeToNBT(compound, "handler"); patterns.writeToNBT(compound, "patterns"); subItemHandler.writeToNBT(compound, "subItemHandler"); subFluidHandler.writeToNBT(compound, "subFluidHandler"); - if (workMode != WorkModeSetting.DEFAULT) { - compound.setByte("workMode", (byte) workMode.ordinal()); - } if (!handler.isEmpty() && currentPatternIdx != -1) { compound.setByte("currentPatternIdx", (byte) currentPatternIdx); } + return writeProviderHandlerNBT(compound); + } + + public NBTTagCompound writeProviderHandlerNBT(final NBTTagCompound compound) { + if (workMode != WorkModeSetting.DEFAULT) { + compound.setByte("workMode", (byte) workMode.ordinal()); + } + if (workMode == WorkModeSetting.ISOLATION_INPUT) { + var nbt = new NBTTagCompound(); + for (var i = 0; i < combinationComponents.size(); i++) { + var handler = (InfItemFluidHandler) combinationComponents.get(i).getContainerProvider(); + if (!handler.isEmpty()) handler.writeToNBT(nbt, "handler#" + i); + } + if (!nbt.isEmpty()) compound.setTag("components", nbt); + } else handler.writeToNBT(compound, "handler"); + return compound; } @@ -644,11 +775,18 @@ public IConfigManager getConfigManager() { return this.duality.getConfigManager(); } + @Override + public void invalidate() { + super.invalidate(); + GROUP_ACQUIRER.addAndGet(-PATTERNS); + } + public enum WorkModeSetting { DEFAULT, BLOCKING_MODE, CRAFTING_LOCK_MODE, ENHANCED_BLOCKING_MODE, + ISOLATION_INPUT } } diff --git a/src/main/java/github/kasuminova/mmce/common/tile/base/MachineCombinationComponent.java b/src/main/java/github/kasuminova/mmce/common/tile/base/MachineCombinationComponent.java new file mode 100644 index 00000000..f65323ef --- /dev/null +++ b/src/main/java/github/kasuminova/mmce/common/tile/base/MachineCombinationComponent.java @@ -0,0 +1,28 @@ +package github.kasuminova.mmce.common.tile.base; + +import hellfirepvp.modularmachinery.common.machine.MachineComponent; + +import javax.annotation.Nonnull; +import java.util.Collection; +import java.util.concurrent.atomic.AtomicLong; + +public interface MachineCombinationComponent { + + AtomicLong GROUP_ACQUIRER = new AtomicLong(Integer.MAX_VALUE); + + /** + * 每个MachineComponent的getGroupID方法应该返回不同的值,否则不应该实现此接口 + * + */ + @Nonnull + Collection> provideComponents(); + + /** + * 应该缓存结果而不是反复调用 + * Should cache the results instead of repeatedly calling + */ + default long getUniqueGroupID() { + return GROUP_ACQUIRER.incrementAndGet(); + } + +} diff --git a/src/main/java/github/kasuminova/mmce/common/util/InfItemFluidHandler.java b/src/main/java/github/kasuminova/mmce/common/util/InfItemFluidHandler.java index 1ca3c390..f78de908 100644 --- a/src/main/java/github/kasuminova/mmce/common/util/InfItemFluidHandler.java +++ b/src/main/java/github/kasuminova/mmce/common/util/InfItemFluidHandler.java @@ -400,44 +400,50 @@ public void setSubFluidHandler(final IFluidHandler subFluidHandler) { public void writeToNBT(final NBTTagCompound tag, final String subTagName) { NBTTagCompound subTag = new NBTTagCompound(); - final NBTTagList fluidList = new NBTTagList(); - fluidStackList.stream() - .filter(Objects::nonNull) - .map(fluidStack -> fluidStack.writeToNBT(new NBTTagCompound())) - .forEach(fluidList::appendTag); - subTag.setTag("Fluids", fluidList); - - final NBTTagList itemList = new NBTTagList(); - itemStackList.stream() - .filter(itemStack -> !itemStack.isEmpty()) - .map(ItemStackUtils::writeNBTOversize) - .forEach(itemList::appendTag); - subTag.setTag("Items", itemList); + if (!fluidStackList.isEmpty()) { + final NBTTagList fluidList = new NBTTagList(); + fluidStackList.stream() + .filter(Objects::nonNull) + .map(fluidStack -> fluidStack.writeToNBT(new NBTTagCompound())) + .forEach(fluidList::appendTag); + subTag.setTag("Fluids", fluidList); + } + + if (!itemStackList.isEmpty()) { + final NBTTagList itemList = new NBTTagList(); + itemStackList.stream() + .filter(itemStack -> !itemStack.isEmpty()) + .map(ItemStackUtils::writeNBTOversize) + .forEach(itemList::appendTag); + subTag.setTag("Items", itemList); + } if (Mods.MEKANISM.isPresent() && Mods.MEKENG.isPresent()) { writeNBTMekGas(subTag); } - tag.setTag(subTagName, subTag); + if (!subTag.isEmpty()) tag.setTag(subTagName, subTag); } public void readFromNBT(final NBTTagCompound tag, final String subTagName) { NBTTagCompound subTag = tag.getCompoundTag(subTagName); fluidStackList.clear(); final NBTTagList fluidList = subTag.getTagList("Fluids", Constants.NBT.TAG_COMPOUND); - IntStream.range(0, fluidList.tagCount()) - .mapToObj(fluidList::getCompoundTagAt) - .map(FluidStack::loadFluidStackFromNBT) - .filter(Objects::nonNull) - .forEach(fluidStackList::add); + if (!fluidList.isEmpty()) + IntStream.range(0, fluidList.tagCount()) + .mapToObj(fluidList::getCompoundTagAt) + .map(FluidStack::loadFluidStackFromNBT) + .filter(Objects::nonNull) + .forEach(fluidStackList::add); itemStackList.clear(); final NBTTagList itemList = subTag.getTagList("Items", Constants.NBT.TAG_COMPOUND); - IntStream.range(0, itemList.tagCount()) - .mapToObj(itemList::getCompoundTagAt) - .map(ItemStackUtils::readNBTOversize) - .filter(itemStack -> !itemStack.isEmpty()) - .forEach(itemStackList::add); + if (!itemList.isEmpty()) + IntStream.range(0, itemList.tagCount()) + .mapToObj(itemList::getCompoundTagAt) + .map(ItemStackUtils::readNBTOversize) + .filter(itemStack -> !itemStack.isEmpty()) + .forEach(itemStackList::add); if (Mods.MEKANISM.isPresent() && Mods.MEKENG.isPresent()) { readFromNBTMekGas(subTag); @@ -448,6 +454,7 @@ public void readFromNBT(final NBTTagCompound tag, final String subTagName) { @Optional.Method(modid = "mekanism") public void writeNBTMekGas(final NBTTagCompound subTag) { + if (gasStackList.isEmpty()) return; List gasStackList = (List) this.gasStackList; final NBTTagList gasList = new NBTTagList(); gasStackList.stream() @@ -462,6 +469,7 @@ public void readFromNBTMekGas(final NBTTagCompound subTag) { List gasStackList = (List) this.gasStackList; gasStackList.clear(); final NBTTagList gasList = subTag.getTagList("Gases", Constants.NBT.TAG_COMPOUND); + if (gasList.isEmpty()) return; IntStream.range(0, gasList.tagCount()) .mapToObj(gasList::getCompoundTagAt) .map(GasStack::readFromNBT) diff --git a/src/main/java/hellfirepvp/modularmachinery/ModularMachinery.java b/src/main/java/hellfirepvp/modularmachinery/ModularMachinery.java index 8a405622..a045ed71 100644 --- a/src/main/java/hellfirepvp/modularmachinery/ModularMachinery.java +++ b/src/main/java/hellfirepvp/modularmachinery/ModularMachinery.java @@ -26,6 +26,7 @@ import hellfirepvp.modularmachinery.common.integration.crafttweaker.command.CommandCTReload; import hellfirepvp.modularmachinery.common.network.PktAssemblyReport; import hellfirepvp.modularmachinery.common.network.PktCopyToClipboard; +import hellfirepvp.modularmachinery.common.network.PktGroupInputConfig; import hellfirepvp.modularmachinery.common.network.PktInteractFluidTankGui; import hellfirepvp.modularmachinery.common.network.PktParallelControllerUpdate; import hellfirepvp.modularmachinery.common.network.PktSmartInterfaceUpdate; @@ -115,6 +116,7 @@ public void preInit(FMLPreInitializationEvent event) { NET_CHANNEL.registerMessage(StarlightMessage.StarlightMessageHandler.class, StarlightMessage.class, 5, Side.CLIENT); } + NET_CHANNEL.registerMessage(PktGroupInputConfig.class, PktGroupInputConfig.class, 99, Side.SERVER); NET_CHANNEL.registerMessage(PktInteractFluidTankGui.class, PktInteractFluidTankGui.class, 100, Side.SERVER); NET_CHANNEL.registerMessage(PktSmartInterfaceUpdate.class, PktSmartInterfaceUpdate.class, 101, Side.SERVER); NET_CHANNEL.registerMessage(PktParallelControllerUpdate.class, PktParallelControllerUpdate.class, 102, Side.SERVER); diff --git a/src/main/java/hellfirepvp/modularmachinery/client/ClientProxy.java b/src/main/java/hellfirepvp/modularmachinery/client/ClientProxy.java index 59b1e0e3..e62da3d9 100644 --- a/src/main/java/hellfirepvp/modularmachinery/client/ClientProxy.java +++ b/src/main/java/hellfirepvp/modularmachinery/client/ClientProxy.java @@ -22,6 +22,7 @@ import hellfirepvp.modularmachinery.ModularMachinery; import hellfirepvp.modularmachinery.client.gui.GuiContainerEnergyHatch; import hellfirepvp.modularmachinery.client.gui.GuiContainerFluidHatch; +import hellfirepvp.modularmachinery.client.gui.GuiContainerGroupInputConfig; import hellfirepvp.modularmachinery.client.gui.GuiContainerItemBus; import hellfirepvp.modularmachinery.client.gui.GuiContainerParallelController; import hellfirepvp.modularmachinery.client.gui.GuiContainerSmartInterface; @@ -49,6 +50,7 @@ import hellfirepvp.modularmachinery.common.tiles.TileParallelController; import hellfirepvp.modularmachinery.common.tiles.TileSmartInterface; import hellfirepvp.modularmachinery.common.tiles.TileUpgradeBus; +import hellfirepvp.modularmachinery.common.tiles.base.MachineGroupInput; import hellfirepvp.modularmachinery.common.tiles.base.TileEnergyHatch; import hellfirepvp.modularmachinery.common.tiles.base.TileFluidTank; import hellfirepvp.modularmachinery.common.tiles.base.TileItemBus; @@ -357,6 +359,11 @@ public Object getClientGuiElement(int ID, EntityPlayer player, World world, int } return new GuiContainerLifeEssence((TileLifeEssenceProvider) present, player); } + case GUI_GROUP_INPUT_CONFIG -> { + if (present instanceof MachineGroupInput m && m.canGroupInput()) { + return new GuiContainerGroupInputConfig(present, player); + } + } } return null; } diff --git a/src/main/java/hellfirepvp/modularmachinery/client/gui/GuiContainerGroupInputConfig.java b/src/main/java/hellfirepvp/modularmachinery/client/gui/GuiContainerGroupInputConfig.java new file mode 100644 index 00000000..2fe592f7 --- /dev/null +++ b/src/main/java/hellfirepvp/modularmachinery/client/gui/GuiContainerGroupInputConfig.java @@ -0,0 +1,146 @@ +package hellfirepvp.modularmachinery.client.gui; + +import hellfirepvp.modularmachinery.ModularMachinery; +import hellfirepvp.modularmachinery.common.container.ContainerGroupInputConfig; +import hellfirepvp.modularmachinery.common.network.PktGroupInputConfig; +import hellfirepvp.modularmachinery.common.util.MiscUtils; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.GuiButton; +import net.minecraft.client.gui.GuiTextField; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.resources.I18n; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.tileentity.TileEntity; +import net.minecraftforge.client.model.animation.Animation; + +import java.io.IOException; + +public class GuiContainerGroupInputConfig extends GuiContainerBase { + + private GuiTextField textField; + private GuiButton enableIsolation; + private GuiButton closeIsolation; + + public GuiContainerGroupInputConfig(TileEntity owner, EntityPlayer opening) { + super(new ContainerGroupInputConfig(owner, opening)); + } + + @Override + protected void setWidthHeight() { + + } + + @Override + protected void drawGuiContainerForegroundLayer(int mouseX, int mouseY) { + super.drawGuiContainerForegroundLayer(mouseX, mouseY); + GlStateManager.pushMatrix(); + GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); + + int offsetX = 4; + int offsetY = 4; + FontRenderer fr = this.fontRenderer; + fr.drawStringWithShadow(I18n.format("gui.groupinputconfig.title"), offsetX, offsetY, 0xFFFFFF); + offsetX += 2; + offsetY += 20; + + fr.drawStringWithShadow(I18n.format("gui.groupinputconfig.tooltip"), offsetX, offsetY, 0xFFFFFF); + offsetY += 25; + + fr.drawStringWithShadow(I18n.format("gui.groupinputconfig.value"), offsetX, offsetY, 0xFFFFFF); + + GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); + GlStateManager.popMatrix(); + } + + @Override + protected void drawGuiContainerBackgroundLayer(float partialTicks, int mouseX, int mouseY) { + GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); + this.mc.getTextureManager().bindTexture(TEXTURES_EMPTY_GUI); + int i = (this.width - this.xSize) / 2; + int j = (this.height - this.ySize) / 2; + this.drawTexturedModalRect(i, j, 0, 0, this.xSize, this.ySize); + + textField.drawTextBox(); + enableIsolation.drawButton(Minecraft.getMinecraft(), mouseX, mouseY, Animation.getPartialTickTime()); + enableIsolation.drawButtonForegroundLayer(mouseX, mouseY); + closeIsolation.drawButton(Minecraft.getMinecraft(), mouseX, mouseY, Animation.getPartialTickTime()); + closeIsolation.drawButtonForegroundLayer(mouseX, mouseY); + } + + @Override + protected void mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException { + if (mouseButton == 0 && closeIsolation.visible) { + boolean clicked = textField.mouseClicked(mouseX, mouseY, mouseButton); + if (clicked) { + return; + } else { + try { + long newId = Long.parseLong(textField.getText()); + if (newId > Integer.MAX_VALUE) { + newId = Integer.MAX_VALUE; + } + if (newId != this.container.getMachine().getGroupId()) { + this.container.getMachine().setGroupId((int) newId); + ModularMachinery.NET_CHANNEL.sendToServer(new PktGroupInputConfig((int) newId)); + } + } catch (NumberFormatException ignored) { + } + } + } else if (enableIsolation.visible) { + if (textField.isFocused()) { + textField.setFocused(false); + } + } + + super.mouseClicked(mouseX, mouseY, mouseButton); + + if (mouseButton != 0) { + return; + } + + if (enableIsolation.visible && enableIsolation.mousePressed(mc, mouseX, mouseY)) { + enableIsolation.visible = false; + closeIsolation.visible = true; + container.getMachine().setGroupInput(true); + textField.setText(Integer.toString(container.getMachine().getGroupId())); + ModularMachinery.NET_CHANNEL.sendToServer(new PktGroupInputConfig(true)); + return; + } + if (closeIsolation.visible && closeIsolation.mousePressed(mc, mouseX, mouseY)) { + enableIsolation.visible = true; + closeIsolation.visible = false; + container.getMachine().setGroupInput(false); + textField.setText(Integer.toString(container.getMachine().getGroupId())); + ModularMachinery.NET_CHANNEL.sendToServer(new PktGroupInputConfig(false)); + } + + } + + @Override + public void keyTyped(char c, int i) throws IOException { + if (!textField.isFocused()) { + super.keyTyped(c, i); + } + + if (Character.isDigit(c) || MiscUtils.isTextBoxKey(i)) { + textField.textboxKeyTyped(c, i); + } + } + + @Override + public void initGui() { + super.initGui(); + textField = new GuiTextField(0, fontRenderer, this.width / 2 - 15, this.height / 2 - 35, 95, 10); + textField.setMaxStringLength(10); + + enableIsolation = new GuiButton(1, this.width / 2 + 31, this.height / 2 - 23, 50, 20, + I18n.format("gui.groupinputconfig.enable")); + closeIsolation = new GuiButton(2, this.width / 2 + 31, this.height / 2 - 23, 50, 20, + I18n.format("gui.groupinputconfig.close")); + + enableIsolation.visible = !container.getMachine().isGroupInput(); + closeIsolation.visible = container.getMachine().isGroupInput(); + textField.setText(Integer.toString(container.getMachine().getGroupId())); + } +} diff --git a/src/main/java/hellfirepvp/modularmachinery/common/CommonProxy.java b/src/main/java/hellfirepvp/modularmachinery/common/CommonProxy.java index 3a470128..c9bb9cd2 100644 --- a/src/main/java/hellfirepvp/modularmachinery/common/CommonProxy.java +++ b/src/main/java/hellfirepvp/modularmachinery/common/CommonProxy.java @@ -38,6 +38,7 @@ import hellfirepvp.modularmachinery.common.container.ContainerEnergyHatch; import hellfirepvp.modularmachinery.common.container.ContainerFactoryController; import hellfirepvp.modularmachinery.common.container.ContainerFluidHatch; +import hellfirepvp.modularmachinery.common.container.ContainerGroupInputConfig; import hellfirepvp.modularmachinery.common.container.ContainerItemBus; import hellfirepvp.modularmachinery.common.container.ContainerParallelController; import hellfirepvp.modularmachinery.common.container.ContainerSmartInterface; @@ -63,6 +64,7 @@ import hellfirepvp.modularmachinery.common.tiles.TileParallelController; import hellfirepvp.modularmachinery.common.tiles.TileSmartInterface; import hellfirepvp.modularmachinery.common.tiles.TileUpgradeBus; +import hellfirepvp.modularmachinery.common.tiles.base.MachineGroupInput; import hellfirepvp.modularmachinery.common.tiles.base.TileEnergyHatch; import hellfirepvp.modularmachinery.common.tiles.base.TileFluidTank; import hellfirepvp.modularmachinery.common.tiles.base.TileItemBus; @@ -87,6 +89,7 @@ import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.fml.common.network.IGuiHandler; import net.minecraftforge.fml.common.network.NetworkRegistry; +import org.jetbrains.annotations.NotNull; import javax.annotation.Nullable; import java.io.File; @@ -127,6 +130,7 @@ private static boolean aeSecurityCheck(EntityPlayer player, TileEntity te) { public void preInit() { creativeTabModularMachinery = new CreativeTabs(ModularMachinery.MODID) { + @NotNull @Override public ItemStack createIcon() { return new ItemStack(BlocksMM.blockController); @@ -309,6 +313,11 @@ public Object getServerGuiElement(int ID, EntityPlayer player, World world, int } return new ContainerMEItemOutputBusStackSize(player.inventory, (MEItemOutputBus) present); } + case GUI_GROUP_INPUT_CONFIG -> { + if (present instanceof MachineGroupInput m && m.canGroupInput()) { + return new ContainerGroupInputConfig(present, player); + } + } } return null; @@ -340,6 +349,7 @@ public enum GuiType { ME_GAS_INPUT_BUS(Mods.AE2EL.isPresent() && Mods.MEKENG.isPresent() ? MEGasInputBus.class : null), ME_PATTERN_PROVIDER(Mods.AE2.isPresent() ? MEPatternProvider.class : null), GUI_ESSENCE_PROVIDER(Mods.BM2.isPresent() ? TileLifeEssenceProvider.class : null), + GUI_GROUP_INPUT_CONFIG(TileEntity.class) ; public final Class requiredTileEntity; diff --git a/src/main/java/hellfirepvp/modularmachinery/common/block/BlockFluidInputHatch.java b/src/main/java/hellfirepvp/modularmachinery/common/block/BlockFluidInputHatch.java index c673cd54..ffd19a07 100644 --- a/src/main/java/hellfirepvp/modularmachinery/common/block/BlockFluidInputHatch.java +++ b/src/main/java/hellfirepvp/modularmachinery/common/block/BlockFluidInputHatch.java @@ -10,10 +10,17 @@ import hellfirepvp.modularmachinery.common.tiles.TileFluidInputHatch; import net.minecraft.block.state.IBlockState; +import net.minecraft.client.resources.I18n; +import net.minecraft.client.util.ITooltipFlag; +import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntity; import net.minecraft.world.World; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; +import org.jetbrains.annotations.NotNull; import javax.annotation.Nullable; +import java.util.List; /** * This class is part of the Modular Machinery Mod @@ -28,4 +35,11 @@ public class BlockFluidInputHatch extends BlockFluidHatch { public TileEntity createTileEntity(World world, IBlockState state) { return new TileFluidInputHatch(state.getValue(BUS_TYPE)); } + + @Override + @SideOnly(Side.CLIENT) + public void addInformation(@NotNull ItemStack stack, @Nullable World worldIn, @NotNull List tooltip, @NotNull ITooltipFlag flagIn) { + super.addInformation(stack, worldIn, tooltip, flagIn); + tooltip.add(I18n.format("tooltip.groupinput.block")); + } } diff --git a/src/main/java/hellfirepvp/modularmachinery/common/block/BlockInputBus.java b/src/main/java/hellfirepvp/modularmachinery/common/block/BlockInputBus.java index 923037ee..17f22347 100644 --- a/src/main/java/hellfirepvp/modularmachinery/common/block/BlockInputBus.java +++ b/src/main/java/hellfirepvp/modularmachinery/common/block/BlockInputBus.java @@ -10,10 +10,17 @@ import hellfirepvp.modularmachinery.common.tiles.TileItemInputBus; import net.minecraft.block.state.IBlockState; +import net.minecraft.client.resources.I18n; +import net.minecraft.client.util.ITooltipFlag; +import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntity; import net.minecraft.world.World; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; +import org.jetbrains.annotations.NotNull; import javax.annotation.Nullable; +import java.util.List; /** * This class is part of the Modular Machinery Mod @@ -29,4 +36,11 @@ public TileEntity createTileEntity(World world, IBlockState state) { return new TileItemInputBus(state.getValue(BUS_TYPE)); } + @Override + @SideOnly(Side.CLIENT) + public void addInformation(@NotNull ItemStack stack, @Nullable World worldIn, @NotNull List tooltip, @NotNull ITooltipFlag flagIn) { + super.addInformation(stack, worldIn, tooltip, flagIn); + tooltip.add(I18n.format("tooltip.groupinput.block")); + } + } diff --git a/src/main/java/hellfirepvp/modularmachinery/common/block/BlockParallelController.java b/src/main/java/hellfirepvp/modularmachinery/common/block/BlockParallelController.java index 488dfb91..6bdca482 100644 --- a/src/main/java/hellfirepvp/modularmachinery/common/block/BlockParallelController.java +++ b/src/main/java/hellfirepvp/modularmachinery/common/block/BlockParallelController.java @@ -25,6 +25,7 @@ import net.minecraft.world.World; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; +import org.jetbrains.annotations.NotNull; import javax.annotation.Nullable; import java.util.LinkedList; @@ -43,24 +44,26 @@ public BlockParallelController() { } @Override - public void addInformation(ItemStack stack, @Nullable World worldIn, List tooltip, ITooltipFlag flagIn) { + public void addInformation(@NotNull ItemStack stack, @Nullable World worldIn, @NotNull List tooltip, @NotNull ITooltipFlag flagIn) { super.addInformation(stack, worldIn, tooltip, flagIn); ParallelControllerData data = ParallelControllerData.values()[MathHelper.clamp(stack.getMetadata(), 0, ParallelControllerData.values().length - 1)]; tooltip.add(I18n.format("tile.modularmachinery.blockparallelcontroller.tip", data.getMaxParallelism())); } @Override - public void getSubBlocks(CreativeTabs itemIn, NonNullList items) { + public void getSubBlocks(@NotNull CreativeTabs itemIn, @NotNull NonNullList items) { for (ParallelControllerData size : ParallelControllerData.values()) { items.add(new ItemStack(this, 1, size.ordinal())); } } + @NotNull @Override - public EnumBlockRenderType getRenderType(IBlockState state) { + public EnumBlockRenderType getRenderType(@NotNull IBlockState state) { return EnumBlockRenderType.MODEL; } + @NotNull @Override @SideOnly(Side.CLIENT) public BlockRenderLayer getRenderLayer() { @@ -68,7 +71,7 @@ public BlockRenderLayer getRenderLayer() { } @Override - public int damageDropped(IBlockState state) { + public int damageDropped(@NotNull IBlockState state) { return getMetaFromState(state); } @@ -77,11 +80,13 @@ public int getMetaFromState(IBlockState state) { return state.getValue(CONTROLLER_TYPE).ordinal(); } + @NotNull @Override protected BlockStateContainer createBlockState() { return new BlockStateContainer(this, CONTROLLER_TYPE); } + @NotNull @Override public IBlockState getStateFromMeta(int meta) { return getDefaultState().withProperty(CONTROLLER_TYPE, ParallelControllerData.values()[meta]); @@ -129,7 +134,7 @@ public TileEntity createNewTileEntity(World worldIn, int meta) { } @Override - public boolean onBlockActivated(World worldIn, BlockPos pos, IBlockState state, EntityPlayer playerIn, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ) { + public boolean onBlockActivated(World worldIn, @NotNull BlockPos pos, @NotNull IBlockState state, @NotNull EntityPlayer playerIn, @NotNull EnumHand hand, @NotNull EnumFacing facing, float hitX, float hitY, float hitZ) { if (!worldIn.isRemote) { TileEntity te = worldIn.getTileEntity(pos); if (te instanceof TileParallelController) { diff --git a/src/main/java/hellfirepvp/modularmachinery/common/container/ContainerGroupInputConfig.java b/src/main/java/hellfirepvp/modularmachinery/common/container/ContainerGroupInputConfig.java new file mode 100644 index 00000000..5f97883f --- /dev/null +++ b/src/main/java/hellfirepvp/modularmachinery/common/container/ContainerGroupInputConfig.java @@ -0,0 +1,19 @@ +package hellfirepvp.modularmachinery.common.container; + +import hellfirepvp.modularmachinery.common.tiles.base.MachineGroupInput; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.tileentity.TileEntity; + +public class ContainerGroupInputConfig extends ContainerBase { + + private final MachineGroupInput machine; + + public ContainerGroupInputConfig(TileEntity owner, EntityPlayer opening) { + super(owner, opening); + machine = (MachineGroupInput) owner; + } + + public MachineGroupInput getMachine() { + return machine; + } +} diff --git a/src/main/java/hellfirepvp/modularmachinery/common/crafting/helper/RecipeCraftingContext.java b/src/main/java/hellfirepvp/modularmachinery/common/crafting/helper/RecipeCraftingContext.java index fb0b6745..7f44c32c 100644 --- a/src/main/java/hellfirepvp/modularmachinery/common/crafting/helper/RecipeCraftingContext.java +++ b/src/main/java/hellfirepvp/modularmachinery/common/crafting/helper/RecipeCraftingContext.java @@ -23,12 +23,18 @@ import hellfirepvp.modularmachinery.common.tiles.base.TileMultiblockMachineController; import hellfirepvp.modularmachinery.common.util.Asyncable; import hellfirepvp.modularmachinery.common.util.ResultChance; +import it.unimi.dsi.fastutil.objects.Object2IntMap; +import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import it.unimi.dsi.fastutil.objects.ObjectLists; +import net.minecraft.tileentity.TileEntity; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.EnumMap; @@ -42,7 +48,6 @@ import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; -import java.util.function.Predicate; import java.util.stream.Collectors; /** @@ -57,22 +62,25 @@ public class RecipeCraftingContext { private final int reloadCounter; - private final Map, List> modifiers = new ConcurrentHashMap<>(); - private final Map, RecipeModifier.ModifierApplier> modifierAppliers = new ConcurrentHashMap<>(); + private final Map, List> modifiers = new ConcurrentHashMap<>(); + private final Map, RecipeModifier.ModifierApplier> modifierAppliers = new ConcurrentHashMap<>(); private final Map, RecipeModifier.ModifierApplier> chanceModifierAppliers = new ConcurrentHashMap<>(); private final List permanentModifierList = new ArrayList<>(); private final List currentRestrictions = new ArrayList<>(); - private final List> requirements = new ArrayList<>(); - private final List requirementComponents = new ArrayList<>(); + private final List> requirements = new ArrayList<>(); + private final Map> requirementComponents = new ConcurrentHashMap<>(); + private boolean isCrafting = false; + private long groupId = 0; + private final long[][] groupKeys = new long[2][]; - private ActiveMachineRecipe activeRecipe; - private TileMultiblockMachineController controller = null; - private ControllerCommandSender commandSender = null; + private ActiveMachineRecipe activeRecipe; + private TileMultiblockMachineController controller = null; + private ControllerCommandSender commandSender = null; - private Collection> typeComponents = new ArrayList<>(); + private final Map>> typeComponents = new ConcurrentHashMap<>(); private int currentIOTickIndex = 0; @@ -88,6 +96,10 @@ public RecipeCraftingContext(final int reloadCounter, init(activeRecipe, controller); } + public void setCrafting(boolean crafting) { + isCrafting = crafting; + } + private static List> getCopiedRequirementComponents( final ReqCompMap reqCompMap, final TaggedReqCompMap taggedReqCompMap, @@ -112,6 +124,7 @@ public RecipeCraftingContext reset() { this.chanceModifierAppliers.clear(); this.permanentModifierList.clear(); this.currentRestrictions.clear(); + this.isCrafting = false; this.currentIOTickIndex = 0; return this; @@ -122,7 +135,7 @@ public RecipeCraftingContext resetAll() { this.activeRecipe = null; this.controller = null; this.commandSender = null; - this.typeComponents = null; + this.typeComponents.clear(); this.requirementComponents.clear(); return reset(); @@ -148,7 +161,7 @@ public RecipeCraftingContext init(final ActiveMachineRecipe activeRecipe, this.commandSender = new ControllerCommandSender(this.controller); reset(); - updateComponents(ctrl.getFoundComponents().values()); + updateComponents(ctrl.getFoundComponents()); return this; } @@ -193,23 +206,33 @@ public void addRestriction(ComponentOutputRestrictor restrictor) { this.currentRestrictions.add(restrictor); } - public List> getComponentsFor(ComponentRequirement requirement, @Nullable ComponentSelectorTag tag) { - List> validComponents = new ArrayList<>(); - for (ProcessingComponent typeComponent : this.typeComponents) { - if (!requirement.isValidComponent(typeComponent, this)) { - continue; - } + private static final Map>> emptyComponents + = Collections.singletonMap(0L, Collections.emptyList()); - if (tag != null) { - if (tag.equals(typeComponent.getTag())) { - validComponents.add(typeComponent); + private Map>> getComponentsFor(ComponentRequirement requirement, @Nullable ComponentSelectorTag tag) { + Map>> validComponents = new HashMap<>(); + for (Map.Entry>> set : this.typeComponents.entrySet()) { + final Long groupId = set.getKey(); + for (var typeComponent : set.getValue()) { + if (!requirement.isValidComponent(typeComponent, this)) { + continue; + } + + if (tag != null) { + if (tag.equals(typeComponent.getTag())) { + validComponents + .computeIfAbsent(groupId, i -> new ObjectArrayList<>()) + .add(typeComponent); + } + } else { + validComponents + .computeIfAbsent(groupId, i -> new ObjectArrayList<>()) + .add(typeComponent); } - } else { - validComponents.add(typeComponent); } } - return validComponents; + return validComponents.isEmpty() ? emptyComponents : validComponents; } public CraftingCheckResult ioTick(int currentTick) { @@ -217,19 +240,20 @@ public CraftingCheckResult ioTick(int currentTick) { CraftingCheckResult checkResult = new CraftingCheckResult(); float durMultiplier = this.getDurationMultiplier(); + final List components = getCurrentComponents(); + //Input / Output tick - for (int i = currentIOTickIndex; i < requirementComponents.size(); i++) { - final RequirementComponents reqComponent = requirementComponents.get(i); + for (int i = currentIOTickIndex; i < components.size(); i++) { + final RequirementComponents reqComponent = components.get(i); ComponentRequirement requirement = reqComponent.requirement(); if (!(requirement instanceof ComponentRequirement.PerTick perTickReq)) { - if (requirement.getTriggerTime() >= 1) { + if (requirement.getTriggerTime() <= 0) { checkAndTriggerRequirement(checkResult, currentTick, chance, reqComponent); if (checkResult.isFailure()) { currentIOTickIndex = i; return checkResult; } - continue; } continue; } @@ -302,6 +326,23 @@ private void checkAndTriggerRequirement(final CraftingCheckResult res, } } + public List getCurrentComponents() { + List components; + var g = requirementComponents.get(groupId); + if (g == null) { + for (Long l : this.requirementComponents.keySet()) { + if (l >= 0) { + setGroupId(l); + break; + } + } + components = requirementComponents.get(groupId); + } else { + components = g; + } + return components; + } + public void startCrafting() { startCrafting(RAND.nextLong()); } @@ -309,7 +350,7 @@ public void startCrafting() { public void startCrafting(long seed) { ResultChance chance = new ResultChance(seed); - for (RequirementComponents reqComponents : requirementComponents) { + for (RequirementComponents reqComponents : getCurrentComponents()) { if (reqComponents.requirement().getTriggerTime() <= 0) { startCrafting(chance, reqComponents); } @@ -352,7 +393,7 @@ public void finishCrafting(long seed) { event.postEvent(); ResultChance chance = event.getResultChance(); - for (RequirementComponents reqComponents : requirementComponents) { + for (RequirementComponents reqComponents : getCurrentComponents()) { ComponentRequirement requirement = reqComponents.requirement(); List> components = reqComponents.components(); @@ -379,9 +420,9 @@ public void finishCrafting(long seed) { this.getParentRecipe().getCommandContainer().runFinishCommands(this.commandSender); } - public List getAllParallelizableComponents() { - List list = new ArrayList<>(); - for (RequirementComponents reqComponent : requirementComponents) { + public Collection getAllParallelizableComponents() { + Collection list = new ObjectArrayList<>(); + for (RequirementComponents reqComponent : getCurrentComponents()) { if (reqComponent.requirement() instanceof ComponentRequirement.Parallelizable parallelizable && !parallelizable.isParallelizeUnaffected()) { list.add(reqComponent); @@ -390,7 +431,7 @@ public List getAllParallelizableComponents() { return list; } - public int getMaxParallelism(List parallelizable) { + public int getMaxParallelism(Collection parallelizable) { int maxParallelism = this.activeRecipe.getMaxParallelism(); ReqCompMap typeCopiedComp = new ReqCompMap(); @@ -414,9 +455,9 @@ public int getMaxParallelism(List parallelizable) { } public void setParallelism(int parallelism) { - for (RequirementComponents obj : requirementComponents) { - if (obj.requirement() instanceof ComponentRequirement.Parallelizable) { - ((ComponentRequirement.Parallelizable) obj.requirement()).setParallelism(parallelism); + for (RequirementComponents obj : getCurrentComponents()) { + if (obj.requirement() instanceof ComponentRequirement.Parallelizable p) { + p.setParallelism(parallelism); } } activeRecipe.setParallelism(parallelism); @@ -425,15 +466,15 @@ public void setParallelism(int parallelism) { public CraftingCheckResult canStartCrafting() { permanentModifierList.clear(); if (getParentRecipe().isParallelized() && activeRecipe.getMaxParallelism() > 1) { - List parallelizable = getAllParallelizableComponents(); + Collection parallelizable = getAllParallelizableComponents(); int maxParallelism = getMaxParallelism(parallelizable); setParallelism(Math.max(1, maxParallelism)); - if (maxParallelism > 0 && parallelizable.size() >= requirementComponents.size()) { + if (maxParallelism > 0 && parallelizable.size() >= getCurrentComponents().size()) { return CraftingCheckResult.SUCCESS; } } - return canStartCrafting(req -> true); + return canStartCrafting(true); } public CraftingCheckResult canRestartCrafting() { @@ -443,7 +484,7 @@ public CraftingCheckResult canRestartCrafting() { if (currentParallelism > maxParallelism) { setParallelism(maxParallelism); - CraftingCheckResult result = canStartCrafting(req -> true); + CraftingCheckResult result = canStartCrafting(true); if (!result.isSuccess()) { setParallelism(1); } else { @@ -455,33 +496,72 @@ public CraftingCheckResult canRestartCrafting() { } public CraftingCheckResult canFinishCrafting() { - return this.canStartCrafting(req -> req.requirement().actionType == IOType.OUTPUT); + return this.canStartCrafting(false); } - public CraftingCheckResult canStartCrafting(Predicate filter) { + private CraftingCheckResult canStartCrafting(boolean input) { currentRestrictions.clear(); - List requirements = new ArrayList<>(); - for (RequirementComponents requirementComponent : this.requirementComponents) { - if (filter.test(requirementComponent)) { - requirements.add(requirementComponent); - } - } - CraftingCheckResult result = new CraftingCheckResult(); + + CraftingCheckResult result = CraftingCheckResult.FAILURE; float successfulRequirements = 0; + boolean success = false; + long fkey = 0; + + for (var key : groupKeys[!isCrafting ? 0 : 1]) { + if (key < 0) continue; + List components = this.requirementComponents.get(key); + List requirements = input ? components + : components.stream() + .filter(r -> r.requirement().actionType == IOType.OUTPUT) + .collect(Collectors.toCollection(ObjectArrayList::new)); + + result = new CraftingCheckResult(); + ReqCompMap typeCopiedComp = new ReqCompMap(); + TaggedReqCompMap taggedTypeCopiedComp = new TaggedReqCompMap(); + for (RequirementComponents reqEntry : requirements) { + if (canStartCrafting(result, reqEntry, typeCopiedComp, taggedTypeCopiedComp)) { + ++successfulRequirements; + } + } + final float validity = successfulRequirements / requirements.size(); + result.setValidity(validity); - ReqCompMap typeCopiedComp = new ReqCompMap(); - TaggedReqCompMap taggedTypeCopiedComp = new TaggedReqCompMap(); - for (RequirementComponents reqEntry : requirements) { - if (canStartCrafting(result, reqEntry, typeCopiedComp, taggedTypeCopiedComp)) { - successfulRequirements++; + if (!input) { + success = true; + break; + } + + if (result.isSuccess()) { + success = true; + setGroupId(key); + this.isCrafting = true; + break; + } else { + fkey = key; + successfulRequirements = 0; } } - result.setValidity(successfulRequirements / requirements.size()); + + if (!success) setGroupId(fkey); currentRestrictions.clear(); return result; } + public final RecipeCraftingContext setGroupId(long i) { + if (!isCrafting) { + groupId = i; + if (groupKeys[1] == null) + groupKeys[1] = new long[]{groupId}; + else if (groupKeys[1][0] != groupId) groupKeys[1][0] = groupId; + } + return this; + } + + public long getGroupId() { + return groupId; + } + private boolean canStartCrafting(final CraftingCheckResult result, final RequirementComponents reqComponent, final ReqCompMap reqCompMap, @@ -524,15 +604,38 @@ private boolean canStartCrafting(final CraftingCheckResult result, return false; } - public void updateComponents(Collection> components) { - this.typeComponents = components; + public void updateComponents(Map>> components) { + this.typeComponents.clear(); + components.forEach((groupId, map) + -> this.typeComponents.put(groupId, map.values())); updateRequirementComponents(); } public void updateRequirementComponents() { requirementComponents.clear(); requirements.forEach(req -> - requirementComponents.add(new RequirementComponents(req, getComponentsFor(req, req.tag)))); + getComponentsFor(req, req.tag) + .forEach((groupId, list) + -> requirementComponents + .computeIfAbsent(groupId, i -> new ObjectArrayList<>()) + .add(new RequirementComponents(req, list)))); + + if (this.requirementComponents.isEmpty()) { + this.requirementComponents.put(0L, ObjectLists.emptyList()); + setGroupId(0); + } else { + for (Long l : this.requirementComponents.keySet()) { + if (l >= 0) { + setGroupId(l); + break; + } + } + } + + groupKeys[0] = this.requirementComponents.keySet().stream().mapToLong(Long::longValue).toArray(); + Arrays.sort(groupKeys[0]); + if (groupKeys[1] == null) groupKeys[1] = new long[]{groupId}; + else if (groupKeys[1][0] != groupId) groupKeys[1][0] = groupId; } public void addModifier(SingleBlockModifierReplacement replacement) { @@ -623,22 +726,36 @@ public void overrideError(final String ignored) { } @Override - public List getUnlocalizedErrorMessages() { - return Collections.emptyList(); + public boolean isFailure() { + return false; } @Override - public String getFirstErrorMessage(final String defaultMessage) { - return defaultMessage; + public boolean isSuccess() { + return true; } }; - private final Map unlocErrorMessagesMap = new HashMap<>(); - public float validity = 0F; + private static final CraftingCheckResult FAILURE = new CraftingCheckResult() { + + @Override + public boolean isFailure() { + return true; + } + + @Override + public boolean isSuccess() { + return false; + } + + }; + + private final Object2IntMap unlocErrorMessagesMap = new Object2IntOpenHashMap<>(); + public float validity = 0F; public void addError(String unlocError) { if (!unlocError.isEmpty()) { - int count = this.unlocErrorMessagesMap.getOrDefault(unlocError, 0); + int count = this.unlocErrorMessagesMap.getInt(unlocError); count++; this.unlocErrorMessagesMap.put(unlocError, count); } diff --git a/src/main/java/hellfirepvp/modularmachinery/common/machine/MachineComponent.java b/src/main/java/hellfirepvp/modularmachinery/common/machine/MachineComponent.java index ec6548e4..31665e9e 100644 --- a/src/main/java/hellfirepvp/modularmachinery/common/machine/MachineComponent.java +++ b/src/main/java/hellfirepvp/modularmachinery/common/machine/MachineComponent.java @@ -41,6 +41,10 @@ public boolean isAsyncSupported() { public abstract T getContainerProvider(); + public long getGroupID() { + return -1; + } + public abstract static class ItemBus extends MachineComponent { public ItemBus(IOType ioType) { diff --git a/src/main/java/hellfirepvp/modularmachinery/common/machine/RecipeThread.java b/src/main/java/hellfirepvp/modularmachinery/common/machine/RecipeThread.java index 04f50752..241579a1 100644 --- a/src/main/java/hellfirepvp/modularmachinery/common/machine/RecipeThread.java +++ b/src/main/java/hellfirepvp/modularmachinery/common/machine/RecipeThread.java @@ -46,7 +46,7 @@ protected static ActiveMachineRecipe deserializeActiveRecipe(NBTTagCompound tag, } if (activeRecipe != null && activeRecipe.getRecipe() == null) { activeRecipe = null; - ModularMachinery.log.info("Couldn't find recipe named " + recipeTag.getString("recipeName") + " for controller at " + factory.getPos()); + ModularMachinery.log.info("Couldn't find recipe named {} for controller at {}", recipeTag.getString("recipeName"), factory.getPos()); } return activeRecipe; } @@ -142,6 +142,7 @@ protected boolean shouldSearchRecipe() { } public void invalidate() { + if (context != null) context.setCrafting(false); setActiveRecipe(null).setContext(null); permanentModifiers.clear(); semiPermanentModifiers.clear(); @@ -167,9 +168,8 @@ public void invalidate() { protected abstract void createRecipeSearchTask(); public void flushContextModifier() { - if (context == null) { - return; - } + if (context == null) return; + context.overrideModifier(MiscUtils.flatten(ctrl.getFoundModifiers().values())); context.addModifier(ctrl.getCustomModifiers().values()); context.addModifier(semiPermanentModifiers.values()); diff --git a/src/main/java/hellfirepvp/modularmachinery/common/network/PktGroupInputConfig.java b/src/main/java/hellfirepvp/modularmachinery/common/network/PktGroupInputConfig.java new file mode 100644 index 00000000..56df23a2 --- /dev/null +++ b/src/main/java/hellfirepvp/modularmachinery/common/network/PktGroupInputConfig.java @@ -0,0 +1,59 @@ +package hellfirepvp.modularmachinery.common.network; + +import hellfirepvp.modularmachinery.common.container.ContainerGroupInputConfig; +import io.netty.buffer.ByteBuf; +import net.minecraftforge.fml.common.network.simpleimpl.IMessage; +import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler; +import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; + +public class PktGroupInputConfig implements IMessage, IMessageHandler { + + private byte i; + private int id; + private boolean isGroupInput; + + public PktGroupInputConfig() { + + } + + public PktGroupInputConfig(int id) { + this.id = id; + i = 0; + } + + public PktGroupInputConfig(boolean isGroupInput) { + this.isGroupInput = isGroupInput; + i = 1; + } + + @Override + public void fromBytes(ByteBuf buf) { + i = buf.readByte(); + if (i == 0) { + id = buf.readInt(); + } else if (i == 1) { + isGroupInput = buf.readBoolean(); + } + } + + @Override + public void toBytes(ByteBuf buf) { + buf.writeByte(i); + if (i == 0) { + buf.writeInt(id); + } else if (i == 1) { + buf.writeBoolean(isGroupInput); + } + } + + @Override + public IMessage onMessage(PktGroupInputConfig message, MessageContext ctx) { + if (ctx.getServerHandler().player.openContainer instanceof ContainerGroupInputConfig c) { + switch (message.i) { + case 0 -> c.getMachine().setGroupId(message.id); + case 1 -> c.getMachine().setGroupInput(message.isGroupInput); + } + } + return null; + } +} \ No newline at end of file diff --git a/src/main/java/hellfirepvp/modularmachinery/common/tiles/TileFactoryController.java b/src/main/java/hellfirepvp/modularmachinery/common/tiles/TileFactoryController.java index d743b83f..0d82a42f 100644 --- a/src/main/java/hellfirepvp/modularmachinery/common/tiles/TileFactoryController.java +++ b/src/main/java/hellfirepvp/modularmachinery/common/tiles/TileFactoryController.java @@ -540,7 +540,7 @@ protected void updateComponents() { if (ctx == null) { continue; } - ctx.updateComponents(foundComponents.values()); + ctx.updateComponents(foundComponents); } for (final FactoryRecipeThread thread : coreRecipeThreads.values()) { @@ -548,7 +548,7 @@ protected void updateComponents() { if (ctx == null) { continue; } - ctx.updateComponents(foundComponents.values()); + ctx.updateComponents(foundComponents); } } diff --git a/src/main/java/hellfirepvp/modularmachinery/common/tiles/TileItemInputBus.java b/src/main/java/hellfirepvp/modularmachinery/common/tiles/TileItemInputBus.java index a464dab4..10baa3a8 100644 --- a/src/main/java/hellfirepvp/modularmachinery/common/tiles/TileItemInputBus.java +++ b/src/main/java/hellfirepvp/modularmachinery/common/tiles/TileItemInputBus.java @@ -138,6 +138,11 @@ public IOInventory buildInventory(TileInventory tile, int size) { return new IOInventory(tile, slots, new int[]{}); } + @Override + public boolean canGroupInput() { + return true; + } + @Nullable @Override public MachineComponent.ItemBus provideComponent() { @@ -146,6 +151,11 @@ public MachineComponent.ItemBus provideComponent() { public IOInventory getContainerProvider() { return TileItemInputBus.this.inventory; } + + @Override + public long getGroupID() { + return getGroupId(); + } }; } diff --git a/src/main/java/hellfirepvp/modularmachinery/common/tiles/TileMachineController.java b/src/main/java/hellfirepvp/modularmachinery/common/tiles/TileMachineController.java index 2839e516..93dec3b7 100644 --- a/src/main/java/hellfirepvp/modularmachinery/common/tiles/TileMachineController.java +++ b/src/main/java/hellfirepvp/modularmachinery/common/tiles/TileMachineController.java @@ -223,7 +223,7 @@ protected void updateComponents() { if (ctx == null) { return; } - ctx.updateComponents(foundComponents.values()); + ctx.updateComponents(foundComponents); } @Override diff --git a/src/main/java/hellfirepvp/modularmachinery/common/tiles/TileUpgradeBus.java b/src/main/java/hellfirepvp/modularmachinery/common/tiles/TileUpgradeBus.java index 3f145f5e..b1dc958d 100644 --- a/src/main/java/hellfirepvp/modularmachinery/common/tiles/TileUpgradeBus.java +++ b/src/main/java/hellfirepvp/modularmachinery/common/tiles/TileUpgradeBus.java @@ -174,7 +174,6 @@ public boolean hasCapability(@Nonnull Capability capability, @Nullable EnumFa @Nullable @Override - @SuppressWarnings("unchecked") public T getCapability(@Nonnull Capability capability, @Nullable EnumFacing facing) { if (capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) { return (T) inventory; diff --git a/src/main/java/hellfirepvp/modularmachinery/common/tiles/base/MachineGroupInput.java b/src/main/java/hellfirepvp/modularmachinery/common/tiles/base/MachineGroupInput.java new file mode 100644 index 00000000..0aa8f359 --- /dev/null +++ b/src/main/java/hellfirepvp/modularmachinery/common/tiles/base/MachineGroupInput.java @@ -0,0 +1,23 @@ +package hellfirepvp.modularmachinery.common.tiles.base; + +import hellfirepvp.modularmachinery.common.machine.MachineComponent; + +/** + * 实现此接口允许将输入仓室划分为“组”,不实现的情况下默认为-1组,被所有输入通用,组ID必须>0,对于不同的组,输入是互相隔离的 + * TileColorableMachineComponent实现了此接口,{@link #canGroupInput}返回false,重写返回true认为是可分配组的输入供GUI修改 + * 同时,应该重写{@link MachineComponent#getGroupID()}使其返回getGroupId的对应值 + * {@link #isGroupInput}返回false时,{@link #getGroupId()}应当返回-1 + */ +public interface MachineGroupInput { + + void setGroupId(int groupId); + + boolean canGroupInput(); + + boolean isGroupInput(); + + void setGroupInput(boolean b); + + int getGroupId(); + +} \ No newline at end of file diff --git a/src/main/java/hellfirepvp/modularmachinery/common/tiles/base/TileColorableMachineComponent.java b/src/main/java/hellfirepvp/modularmachinery/common/tiles/base/TileColorableMachineComponent.java index bef51d2c..22705091 100644 --- a/src/main/java/hellfirepvp/modularmachinery/common/tiles/base/TileColorableMachineComponent.java +++ b/src/main/java/hellfirepvp/modularmachinery/common/tiles/base/TileColorableMachineComponent.java @@ -21,9 +21,16 @@ * Created by HellFirePvP * Date: 15.08.2017 / 16:20 */ -public class TileColorableMachineComponent extends TileEntitySynchronized implements ColorableMachineTile { +public class TileColorableMachineComponent extends TileEntitySynchronized implements ColorableMachineTile, MachineGroupInput { private int definedColor = Config.machineColor; + private int groupId; + private boolean isGroupInput; + + public void setGroupId(int groupId) { + this.groupId = groupId; + markChunkDirty(); + } @Override public int getMachineColor() { @@ -60,6 +67,11 @@ public void readCustomNBT(NBTTagCompound compound) { } }, 0)); } + + if (canGroupInput()) { + groupId = compound.getInteger("groupId"); + isGroupInput = compound.getBoolean("isGroupInput"); + } } @Override @@ -67,5 +79,32 @@ public void writeCustomNBT(NBTTagCompound compound) { super.writeCustomNBT(compound); compound.setInteger("casingColor", this.definedColor); + if (canGroupInput()) { + compound.setInteger("groupId", this.groupId); + compound.setBoolean("isGroupInput", this.isGroupInput); + } + } + + @Override + public boolean canGroupInput() { + return false; + } + + @Override + public boolean isGroupInput() { + return isGroupInput; + } + + @Override + public void setGroupInput(boolean b) { + isGroupInput = b; + markChunkDirty(); } -} + + @Override + public int getGroupId() { + if (isGroupInput()) return groupId; + return -1; + } + +} \ No newline at end of file diff --git a/src/main/java/hellfirepvp/modularmachinery/common/tiles/base/TileFluidTank.java b/src/main/java/hellfirepvp/modularmachinery/common/tiles/base/TileFluidTank.java index 6ce004e9..da7cbdb2 100644 --- a/src/main/java/hellfirepvp/modularmachinery/common/tiles/base/TileFluidTank.java +++ b/src/main/java/hellfirepvp/modularmachinery/common/tiles/base/TileFluidTank.java @@ -89,7 +89,6 @@ public boolean hasCapability(@Nonnull Capability capability, @Nullable EnumFa @Nullable @Override - @SuppressWarnings("unchecked") public T getCapability(@Nonnull Capability capability, @Nullable EnumFacing facing) { if (capability == CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY) { return (T) tank; @@ -142,6 +141,11 @@ public void markNoUpdate() { this.requireUpdateComparatorLevel = false; } + @Override + public boolean canGroupInput() { + return ioType == IOType.INPUT; + } + @Nullable @Override public MachineComponent provideComponent() { diff --git a/src/main/java/hellfirepvp/modularmachinery/common/tiles/base/TileMultiblockMachineController.java b/src/main/java/hellfirepvp/modularmachinery/common/tiles/base/TileMultiblockMachineController.java index f198ae26..bc4e7019 100644 --- a/src/main/java/hellfirepvp/modularmachinery/common/tiles/base/TileMultiblockMachineController.java +++ b/src/main/java/hellfirepvp/modularmachinery/common/tiles/base/TileMultiblockMachineController.java @@ -25,6 +25,7 @@ import github.kasuminova.mmce.common.helper.IMachineController; import github.kasuminova.mmce.common.machine.component.MachineComponentProxyRegistry; import github.kasuminova.mmce.common.tile.MEPatternProvider; +import github.kasuminova.mmce.common.tile.base.MachineCombinationComponent; import github.kasuminova.mmce.common.upgrade.MachineUpgrade; import github.kasuminova.mmce.common.upgrade.UpgradeType; import github.kasuminova.mmce.common.util.DynamicPattern; @@ -61,7 +62,10 @@ import hellfirepvp.modularmachinery.common.util.MiscUtils; import hellfirepvp.modularmachinery.common.util.SmartInterfaceData; import hellfirepvp.modularmachinery.common.util.SmartInterfaceType; +import it.unimi.dsi.fastutil.longs.Long2ObjectMap; +import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import net.minecraft.block.Block; import net.minecraft.block.state.IBlockState; import net.minecraft.entity.player.EntityPlayerMP; @@ -99,7 +103,6 @@ import javax.annotation.Nullable; import java.util.ArrayList; import java.util.HashMap; -import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Objects; @@ -133,30 +136,32 @@ public abstract class TileMultiblockMachineController extends TileEntityRestrict protected final Map> foundUpgrades = new ConcurrentHashMap<>(); protected final List foundUpgradeBuses = new ArrayList<>(); protected final List foundParallelControllers = new ArrayList<>(); - protected final Map> foundComponents = new ConcurrentHashMap<>(); - - protected final TimeRecorder timeRecorder = new TimeRecorder(); - protected final Set componentSet = new HashSet<>(); - protected boolean searchRecipeImmediately = false; - protected EnumFacing controllerRotation = null; - protected DynamicMachine.ModifierReplacementMap foundReplacements = null; - protected IOInventory inventory; - protected NBTTagCompound customData = new NBTTagCompound(); - protected DynamicMachine prevMachine = null; - protected DynamicMachine foundMachine = null; - protected DynamicMachine parentMachine = null; - protected TaggedPositionBlockArray foundPattern = null; - protected Map foundDynamicPatterns = new HashMap<>(); - protected ActionExecutor tickExecutor = null; - protected WorkMode workMode = WorkMode.ASYNC; - protected UUID owner = null; - protected int structureCheckCounter = 0; - protected int recipeResearchRetryCounter = 0; - protected int lastStrongPower = -1; - protected int lastStructureCheckTick = -1; - protected long executeGroupId = -1; - protected Object animationFactory = null; - protected boolean loaded = false; + protected final Map> generalComponents = new ConcurrentHashMap<>(); + protected final Map>> foundComponents = new ConcurrentHashMap<>(); + + protected final TimeRecorder timeRecorder = new TimeRecorder(); + protected final Set generalComponentSet = new ObjectOpenHashSet<>(); + protected final Long2ObjectMap> componentSet = new Long2ObjectOpenHashMap<>(); + protected boolean searchRecipeImmediately = false; + protected EnumFacing controllerRotation = null; + protected DynamicMachine.ModifierReplacementMap foundReplacements = null; + protected IOInventory inventory; + protected NBTTagCompound customData = new NBTTagCompound(); + protected DynamicMachine prevMachine = null; + protected DynamicMachine foundMachine = null; + protected DynamicMachine parentMachine = null; + protected TaggedPositionBlockArray foundPattern = null; + protected Map foundDynamicPatterns = new HashMap<>(); + protected ActionExecutor tickExecutor = null; + protected WorkMode workMode = WorkMode.ASYNC; + protected UUID owner = null; + protected int structureCheckCounter = 0; + protected int recipeResearchRetryCounter = 0; + protected int lastStrongPower = -1; + protected int lastStructureCheckTick = -1; + protected long executeGroupId = -1; + protected Object animationFactory = null; + protected boolean loaded = false; public TileMultiblockMachineController() { this.inventory = buildInventory(); @@ -193,16 +198,32 @@ public static void loadFromConfig(Configuration config) { "When enabled, the controller sends the full NBT to the client at the start and completion of the recipe, which can be helpful for machinery where the client needs to perform special operations."); } - public void addComponent(MachineComponent component, @Nullable ComponentSelectorTag tag, TileEntity te, Map> components) { + public void addComponent(MachineComponent component, @Nullable ComponentSelectorTag tag, TileEntity te, Map>> components) { T handler = component.getContainerProvider(); + Long groupId = component.getGroupID(); if (handler instanceof InfItemFluidHandler ifh) { - if (componentSet.contains(ifh)) { + Set s; + if (groupId < 0) { + if (generalComponentSet.contains(ifh)) { + return; + } + generalComponentSet.add(ifh); + } else if ((s = componentSet.get(groupId)) != null && s.contains(ifh)) { return; + } else if (s != null) + s.add(ifh); + else { + Set set = new ObjectOpenHashSet<>(); + set.add(ifh); + componentSet.put(groupId, set); } - componentSet.add(ifh); } MachineComponentManager.INSTANCE.checkComponentShared(te, this); - components.put(te, new ProcessingComponent<>(component, handler, tag)); + if (groupId < 0) generalComponents.put(te, new ProcessingComponent<>(component, handler, tag)); + else components.computeIfAbsent( + groupId, + i -> new ConcurrentHashMap<>() + ).put(te, new ProcessingComponent<>(component, handler, tag)); } @Override @@ -735,8 +756,9 @@ protected void checkAllPatterns() { protected void updateComponents() { if (this.foundMachine == null || this.foundPattern == null || this.controllerRotation == null || this.foundReplacements == null) { - this.foundComponents.forEach((te, component) -> MachineComponentManager.INSTANCE.removeOwner(te, this)); + this.foundComponents.forEach((i, map) -> map.forEach((te, c) -> MachineComponentManager.INSTANCE.removeOwner(te, this))); this.foundComponents.clear(); + this.generalComponents.clear(); this.foundModifiers.clear(); this.foundSmartInterfaces.clear(); @@ -749,15 +771,21 @@ protected void updateComponents() { this.foundUpgrades.clear(); this.foundUpgradeBuses.clear(); - this.foundComponents.forEach((te, component) -> MachineComponentManager.INSTANCE.removeOwner(te, this)); + this.foundComponents.forEach((i, map) -> map.forEach((te, c) -> MachineComponentManager.INSTANCE.removeOwner(te, this))); this.foundComponents.clear(); + this.generalComponents.clear(); this.foundSmartInterfaces.clear(); this.foundParallelControllers.clear(); - Map> found = new HashMap<>(); + Map>> found = new Long2ObjectOpenHashMap<>(); - componentSet.clear(); this.foundPattern.getTileBlocksArray().forEach((pos, info) -> checkAndAddComponents(pos, getPos(), found)); - this.foundComponents.putAll(found); + if (found.isEmpty()) this.foundComponents.put(0L, generalComponents); + else { + this.foundComponents.putAll(found); + this.foundComponents.values().forEach(c -> c.putAll(generalComponents)); + } + this.componentSet.clear(); + this.generalComponentSet.clear(); this.foundModifiers.clear(); updateModifiers(); updateMultiBlockModifiers(); @@ -768,15 +796,19 @@ protected void updateComponents() { } } - private void checkAndAddComponents(final BlockPos pos, final BlockPos ctrlPos, final Map> found) { + private void checkAndAddComponents(final BlockPos pos, final BlockPos ctrlPos, final Map>> found) { BlockPos realPos = ctrlPos.add(pos); if (!getWorld().isBlockLoaded(realPos)) { return; } TileEntity te = getWorld().getTileEntity(realPos); - MachineComponent component; - if (!(te instanceof MachineComponentTile mte)) { + List> components = new ObjectArrayList<>(); + if (te instanceof MachineComponentTile mte) { + MachineComponent pc; + if ((pc = mte.provideComponent()) != null) + components.add(pc); + } else { if (te == null) { return; } @@ -784,26 +816,32 @@ private void checkAndAddComponents(final BlockPos pos, final BlockPos ctrlPos, f if (proxiedComponent == null) { return; } - component = proxiedComponent; - } else { - component = mte.provideComponent(); + components.add(proxiedComponent); } - ComponentSelectorTag tag = this.foundPattern.getTag(pos); - if (component == null) { - return; - } - if (!component.isAsyncSupported()) { - workMode = WorkMode.SEMI_SYNC; + if (te instanceof MachineCombinationComponent mcc) { + components.addAll(mcc.provideComponents()); } - addComponent(component, tag, te, found); - if (component instanceof TileParallelController.ParallelControllerProvider) { - this.foundParallelControllers.add((TileParallelController.ParallelControllerProvider) component); + if (components.isEmpty()) { return; } - checkAndAddUpgradeBus(component); - checkAndAddSmartInterface(component, realPos); + + ComponentSelectorTag tag = this.foundPattern.getTag(pos); + + for (var component : components) { + if (!component.isAsyncSupported()) { + workMode = WorkMode.SEMI_SYNC; + } + + addComponent(component, tag, te, found); + if (component instanceof TileParallelController.ParallelControllerProvider p) { + this.foundParallelControllers.add(p); + return; + } + checkAndAddUpgradeBus(component); + checkAndAddSmartInterface(component, realPos); + } } public void checkAndAddUpgradeBus(final MachineComponent component) { @@ -1051,10 +1089,14 @@ public List getFoundParallelC return foundParallelControllers; } - public Map> getFoundComponents() { + public Map>> getFoundComponents() { return foundComponents; } + public Map> getGeneralComponents() { + return generalComponents; + } + public DynamicMachine.ModifierReplacementMap getFoundReplacements() { return foundReplacements; } @@ -1319,7 +1361,7 @@ public void validate() { public void invalidate() { super.invalidate(); loaded = false; - foundComponents.forEach((te, component) -> MachineComponentManager.INSTANCE.removeOwner(te, this)); + this.foundComponents.forEach((i, map) -> map.forEach((te,c) -> MachineComponentManager.INSTANCE.removeOwner(te, this))); if (getWorld().isRemote) { BlockModelHider.hideOrShowBlocks(this); diff --git a/src/main/java/kport/modularmagic/common/block/BlockAspectProviderInput.java b/src/main/java/kport/modularmagic/common/block/BlockAspectProviderInput.java index aa2e49a9..ac59dec6 100644 --- a/src/main/java/kport/modularmagic/common/block/BlockAspectProviderInput.java +++ b/src/main/java/kport/modularmagic/common/block/BlockAspectProviderInput.java @@ -5,11 +5,18 @@ import net.minecraft.block.SoundType; import net.minecraft.block.material.Material; import net.minecraft.block.state.IBlockState; +import net.minecraft.client.resources.I18n; +import net.minecraft.client.util.ITooltipFlag; +import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntity; import net.minecraft.world.World; import net.minecraftforge.fml.common.Optional; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; +import org.jetbrains.annotations.NotNull; import javax.annotation.Nullable; +import java.util.List; public class BlockAspectProviderInput extends BlockAspectProvider { @@ -29,4 +36,11 @@ public TileEntity createTileEntity(World world, IBlockState state) { return new TileAspectProvider.Input(); } + @Override + @SideOnly(Side.CLIENT) + public void addInformation(@NotNull ItemStack stack, @Nullable World worldIn, @NotNull List tooltip, @NotNull ITooltipFlag flagIn) { + super.addInformation(stack, worldIn, tooltip, flagIn); + tooltip.add(I18n.format("tooltip.groupinput.block")); + } + } diff --git a/src/main/java/kport/modularmagic/common/block/BlockLifeEssenceProviderOutput.java b/src/main/java/kport/modularmagic/common/block/BlockLifeEssenceProviderOutput.java index 05492a23..89b519ae 100644 --- a/src/main/java/kport/modularmagic/common/block/BlockLifeEssenceProviderOutput.java +++ b/src/main/java/kport/modularmagic/common/block/BlockLifeEssenceProviderOutput.java @@ -18,6 +18,7 @@ import net.minecraft.util.EnumHand; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; +import org.jetbrains.annotations.NotNull; import javax.annotation.Nullable; @@ -34,9 +35,9 @@ public BlockLifeEssenceProviderOutput() { } @Override - public void breakBlock(World worldIn, BlockPos pos, IBlockState state) { + public void breakBlock(World worldIn, @NotNull BlockPos pos, @NotNull IBlockState state) { TileEntity te = worldIn.getTileEntity(pos); - if (te != null && te instanceof TileInventory) { + if (te instanceof TileInventory) { IOInventory inv = ((TileInventory) te).getInventory(); for (int i = 0; i < inv.getSlots(); i++) { ItemStack stack = inv.getStackInSlot(i); @@ -50,21 +51,23 @@ public void breakBlock(World worldIn, BlockPos pos, IBlockState state) { } @Override - public boolean onBlockActivated(World worldIn, BlockPos pos, IBlockState state, EntityPlayer playerIn, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ) { + public boolean onBlockActivated(World worldIn, @NotNull BlockPos pos, @NotNull IBlockState state, @NotNull EntityPlayer playerIn, @NotNull EnumHand hand, @NotNull EnumFacing facing, float hitX, float hitY, float hitZ) { if (!worldIn.isRemote) { TileEntity te = worldIn.getTileEntity(pos); - if (te != null && te instanceof TileLifeEssenceProvider) { + if (te instanceof TileLifeEssenceProvider) { playerIn.openGui(ModularMachinery.instance, CommonProxy.GuiType.GUI_ESSENCE_PROVIDER.ordinal(), worldIn, pos.getX(), pos.getY(), pos.getZ()); } } return true; } + @NotNull @Override - public EnumBlockRenderType getRenderType(IBlockState state) { + public EnumBlockRenderType getRenderType(@NotNull IBlockState state) { return EnumBlockRenderType.MODEL; } + @NotNull @Override public BlockRenderLayer getRenderLayer() { return BlockRenderLayer.CUTOUT; @@ -72,17 +75,17 @@ public BlockRenderLayer getRenderLayer() { @Override public boolean hasTileEntity(IBlockState state) { - return true; + return super.hasTileEntity(state); } @Override - public boolean isOpaqueCube(IBlockState state) { + public boolean isOpaqueCube(@NotNull IBlockState state) { return false; } @Override - public boolean isFullCube(IBlockState state) { + public boolean isFullCube(@NotNull IBlockState state) { return false; } diff --git a/src/main/java/kport/modularmagic/common/tile/TileAspectProvider.java b/src/main/java/kport/modularmagic/common/tile/TileAspectProvider.java index c8494041..e54ce4de 100644 --- a/src/main/java/kport/modularmagic/common/tile/TileAspectProvider.java +++ b/src/main/java/kport/modularmagic/common/tile/TileAspectProvider.java @@ -5,6 +5,7 @@ import hellfirepvp.modularmachinery.common.machine.IOType; import hellfirepvp.modularmachinery.common.tiles.base.ColorableMachineTile; import hellfirepvp.modularmachinery.common.tiles.base.MachineComponentTile; +import hellfirepvp.modularmachinery.common.tiles.base.MachineGroupInput; import kport.modularmagic.common.crafting.helper.AspectProviderCopy; import kport.modularmagic.common.tile.machinecomponent.MachineComponentAspectProvider; import net.minecraft.block.state.IBlockState; @@ -12,6 +13,7 @@ import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumFacing; import net.minecraftforge.fml.common.Optional; +import org.jetbrains.annotations.NotNull; import thaumcraft.api.ThaumcraftApiHelper; import thaumcraft.api.aspects.Aspect; import thaumcraft.api.aspects.AspectList; @@ -124,6 +126,7 @@ private void fillJar(EnumFacing face) { } } + @NotNull @Override public NBTTagCompound writeToNBT(NBTTagCompound nbt) { super.writeToNBT(nbt); @@ -150,11 +153,72 @@ public void readSyncNBT(NBTTagCompound nbt) { this.color = nbt.hasKey("casingColor") ? nbt.getInteger("casingColor") : Config.machineColor; } - public static class Input extends TileAspectProvider { + public static class Input extends TileAspectProvider implements MachineGroupInput { + + private int groupId; + private boolean isGroupInput; + @Override public MachineComponentAspectProvider provideComponent() { return new MachineComponentAspectProvider(new AspectProviderCopy(this), IOType.INPUT); } + + @Override + public void setGroupId(int groupId) { + this.groupId = groupId; + } + + @Override + public boolean canGroupInput() { + return true; + } + + @Override + public boolean isGroupInput() { + return isGroupInput; + } + + @Override + public void setGroupInput(boolean b) { + isGroupInput = b; + } + + @Override + public int getGroupId() { + if (isGroupInput()) return groupId; + return -1; + } + + @NotNull + @Override + public NBTTagCompound writeToNBT(NBTTagCompound nbt) { + super.writeToNBT(nbt); + nbt.setInteger("groupId", this.groupId); + nbt.setBoolean("isGroupInput", this.isGroupInput); + return nbt; + } + + @Override + public void readFromNBT(NBTTagCompound nbt) { + super.readFromNBT(nbt); + groupId = nbt.getInteger("groupId"); + isGroupInput = nbt.getBoolean("isGroupInput"); + } + + @Override + public NBTTagCompound writeSyncNBT(NBTTagCompound nbt) { + super.writeSyncNBT(nbt); + nbt.setInteger("groupId", this.groupId); + nbt.setBoolean("isGroupInput", this.isGroupInput); + return nbt; + } + + @Override + public void readSyncNBT(NBTTagCompound nbt) { + super.readSyncNBT(nbt); + groupId = nbt.getInteger("groupId"); + isGroupInput = nbt.getBoolean("isGroupInput"); + } } public static class Output extends TileAspectProvider { diff --git a/src/main/resources/assets/modularmachinery/lang/en_US.lang b/src/main/resources/assets/modularmachinery/lang/en_US.lang index 2b9cc0af..bdaaee5c 100644 --- a/src/main/resources/assets/modularmachinery/lang/en_US.lang +++ b/src/main/resources/assets/modularmachinery/lang/en_US.lang @@ -56,16 +56,22 @@ gui.upgradebus.bounded.empty=No binding machinery. gui.upgradebus.bounded=Bound %s machinery gui.upgradebus.incompatible=§eWarning: %s is not compatible with this machinery. +gui.groupinputconfig.title=Group ID Settings +gui.groupinputconfig.tooltip=In different groups, recipe checks are performed independently +gui.groupinputconfig.value=Current ID: +gui.groupinputconfig.enable=Enable Group +gui.groupinputconfig.close=Disable Group + gui.meitemoutputbus.title=ME Machinery Item Output Bus gui.meiteminputbus.title=ME Machinery Item Input Bus gui.meiteminputbus.inv_action=Use the scroll wheel and the SHIFT and CONTROL key combination to modify the number of marked items. gui.meiteminputbus.inv_action.increase.normal=Scroll the wheel up to increase the number of items by 1. gui.meiteminputbus.inv_action.decrease.normal=Scroll the wheel down or right-click on an item to decrease the number of items by 1. -gui.meiteminputbus.inv_action.increase=Press the %s key combination to increase the number of %s items while the wheel is scrolling up. -gui.meiteminputbus.inv_action.decrease=Press the %s key combination to decrease the number of %s items while the wheel is scrolling up. -gui.meiteminputbus.inv_action.multiply=Press the %s key combination to double the number of items while the wheel is scrolling up. -gui.meiteminputbus.inv_action.divide=Press the %s key combination to halve the number of items while the wheel is scrolling down. +gui.meiteminputbus.inv_action.increase=The wheel is scrolling up to increase the number of %s items while press the %s key combination. +gui.meiteminputbus.inv_action.decrease=The wheel is scrolling down to decrease the number of %s items while press the %s key combination. +gui.meiteminputbus.inv_action.multiply=The wheel is scrolling up to double the number of items while press the %s key combination. +gui.meiteminputbus.inv_action.divide=The wheel is scrolling down to halve the number of items while press the %s key combination. gui.meiteminputbus.items_marked=Items marked: %s gui.meitembus.item_cached=Items Cached: %s gui.meitembus.nbt_stored=Items have been stored internally. @@ -84,7 +90,8 @@ gui.mepatternprovider.default.desc=Default: The provider works normally. gui.mepatternprovider.crafting_lock_mode.desc=Crafting Lock Mode: Items will only continue to be stored when the machine completes the recipe. gui.mepatternprovider.blocking_mode.desc=Blocking Mode: Items will not continue to be stored when there are items in the provider. gui.mepatternprovider.enhanced_blocking_mode.desc=Enhanced Blocking Mode: builds on the blocking mode so that the current recipe can still continue to store items. -gui.mepatternprovider.work_mode.desc=Provider work mode (Click to switch between the 4 modes): +gui.mepatternprovider.isolation_input.desc=Input Isolation Mode: Set up independent containers for each pattern slot, and recipe checks are isolated from each other, group settings will be ignored. +gui.mepatternprovider.work_mode.desc=Provider work mode (Click to switch between the 5 modes): gui.mepatternprovider.return_items=Return Items gui.mepatternprovider.return_items.desc=Return all items and fluids in the provider to the ME network. This will reset the state of the Crafting Lock Mode. gui.mepatternprovider.nbt_stored=Provider Configured. @@ -250,6 +257,10 @@ tooltip.constructtool.creative=Creative Structure-To-JSON Tool tooltip.itembus.slot=1 Slot tooltip.itembus.slots=%s Slots +tooltip.mepatternmirrorimage=Use Memory Card to bind the corresponding ME Machinery Pattern Provider. + +tooltip.groupinput.block=Modify group settings by shift+right-clicking the block when empty-handed + tooltip.fluidhatch.empty=Empty tooltip.fluidhatch.fluid=[Fluid] tooltip.fluidhatch.gas=[Gas] diff --git a/src/main/resources/assets/modularmachinery/lang/zh_CN.lang b/src/main/resources/assets/modularmachinery/lang/zh_CN.lang index f474e1d0..48e5672f 100644 --- a/src/main/resources/assets/modularmachinery/lang/zh_CN.lang +++ b/src/main/resources/assets/modularmachinery/lang/zh_CN.lang @@ -56,14 +56,22 @@ gui.upgradebus.bounded.empty=无绑定机械。 gui.upgradebus.bounded=已绑定 %s 个机械 gui.upgradebus.incompatible=§e警告:%s 与此机械不兼容。 +gui.groupinputconfig.title=组ID配置 +gui.groupinputconfig.tooltip=不同的组中,配方检查独立进行 +gui.groupinputconfig.value=当前ID: +gui.groupinputconfig.enable=启用组 +gui.groupinputconfig.close=禁用组 + gui.meitemoutputbus.title=ME 机械物品输出总线 gui.meiteminputbus.title=ME 机械物品输入总线 -gui.meiteminputbus.inv_action=使用滚轮和 SHIFT, CONTROL, ALT 组合键来修改标记物品的数量。 +gui.meiteminputbus.inv_action=使用滚轮,SHIFT和CONTROL组合键修改标记物品的数量。 gui.meiteminputbus.inv_action.increase.normal=滚轮向上滚动增加 1 个物品数量。 gui.meiteminputbus.inv_action.decrease.normal=滚轮向下滚动或右击物品减少 1 个物品数量。 -gui.meiteminputbus.inv_action.increase=滚轮向上滚动时,按 %s 组合键增加 %s 个物品数量。 -gui.meiteminputbus.inv_action.decrease=滚轮向下滚动时,按 %s 组合键减少 %s 个物品数量。 +gui.meiteminputbus.inv_action.increase=按下 %s 组合键时,滚轮向上滚动增加 %s 个物品数量。 +gui.meiteminputbus.inv_action.decrease=按下 %s 组合键时,滚轮向下滚动减少 %s 个物品数量。 +gui.meiteminputbus.inv_action.multiply=按下 %s 组合键时,滚轮向上滚动将物品数量翻倍。 +gui.meiteminputbus.inv_action.divide=按下 %s 组合键时,滚轮向下滚动将物品数量减半。 gui.meiteminputbus.items_marked=已标记物品:%s gui.meitembus.item_cached=已缓存物品: %s gui.meitembus.nbt_stored=内部已存储物品。 @@ -82,7 +90,8 @@ gui.mepatternprovider.default.desc=默认:供应器正常工作。 gui.mepatternprovider.crafting_lock_mode.desc=合成锁定模式:只有当机器完成配方时才会继续存储物品。 gui.mepatternprovider.blocking_mode.desc=阻挡模式:供应器内含有物品时不继续存储物品。 gui.mepatternprovider.enhanced_blocking_mode.desc=强化阻挡模式:在阻挡模式的基础上,使当前配方仍然可以继续存储物品。 -gui.mepatternprovider.work_mode.desc=供应器工作模式(点击在四个模式中切换): +gui.mepatternprovider.isolation_input.desc=输入隔离模式:为每个样板槽位设置独立容器,配方检查时互相隔离,此时组设置将被忽略 +gui.mepatternprovider.work_mode.desc=供应器工作模式(点击在五个模式中切换): gui.mepatternprovider.return_items=清空物品 gui.mepatternprovider.return_items.desc=将供应器中的所有物品和流体返还给 ME 网络,这会重置合成锁定模式的状态。 gui.mepatternprovider.nbt_stored=供应器已配置。 @@ -248,6 +257,10 @@ tooltip.constructtool.creative=创造模式用机械结构到 JSON 转换工具 tooltip.itembus.slot=1 格 tooltip.itembus.slots=%s 格 +tooltip.mepatternmirrorimage=使用内存卡绑定对应的ME机械样板供应器 + +tooltip.groupinput.block=在空手时通过潜行 + 右键放置的方块修改组设置 + tooltip.fluidhatch.empty=空 tooltip.fluidhatch.fluid=[流体] tooltip.fluidhatch.gas=[气体] @@ -445,6 +458,4 @@ tile.modularmachinery.blockmanaprovideroutput.name=魔力输出仓 tile.modularmachinery.blockimpetusproviderinput.name=元动输入接口 tile.modularmachinery.blockimpetusprovideroutput.name=元动输出接口 -tooltip.modularcontroller.machine_projector=蹲下时右击控制器以投影其机器的蓝图至世界。 - - +tooltip.modularcontroller.machine_projector=蹲下时右击控制器以投影其机器的蓝图至世界。 \ No newline at end of file diff --git a/src/main/resources/assets/modularmachinery/textures/gui/mepatternprovider.png b/src/main/resources/assets/modularmachinery/textures/gui/mepatternprovider.png index 3b8c11df..a339ddf2 100644 Binary files a/src/main/resources/assets/modularmachinery/textures/gui/mepatternprovider.png and b/src/main/resources/assets/modularmachinery/textures/gui/mepatternprovider.png differ