diff --git a/src/main/java/com/zorbatron/zbgt/api/render/ZBGTTextures.java b/src/main/java/com/zorbatron/zbgt/api/render/ZBGTTextures.java index 9b87fec2..c8be4170 100644 --- a/src/main/java/com/zorbatron/zbgt/api/render/ZBGTTextures.java +++ b/src/main/java/com/zorbatron/zbgt/api/render/ZBGTTextures.java @@ -14,6 +14,9 @@ public class ZBGTTextures { public static SimpleOverlayRenderer SWIRLY_INFINITY; public static SimpleOverlayRenderer YOTTANK_ME_HATCH; public static SimpleOverlayRenderer MAINTENANCE_OVERLAY_STERILE; + public static SimpleOverlayRenderer CRIB_ACTIVE; + public static SimpleOverlayRenderer CRIB_INACTIVE; + public static SimpleOverlayRenderer CRIB_PROXY; // GUI overlays public static TextureArea ITEM_FLUID_OVERLAY; @@ -21,6 +24,8 @@ public class ZBGTTextures { public static TextureArea PME; public static TextureArea AE2_RW_STATES; public static TextureArea SLIME_BALL; + public static TextureArea ME_PATTERN_OVERLAY; + public static TextureArea EXPORT; public static TextureArea PROGRESS_BAR_CoAL; @@ -44,12 +49,17 @@ public static void preInit() { SWIRLY_INFINITY = new SimpleOverlayRenderer("overlay/machine/swirly_infinity"); YOTTANK_ME_HATCH = new SimpleOverlayRenderer("overlay/machine/yottank_me_hatch"); MAINTENANCE_OVERLAY_STERILE = new SimpleOverlayRenderer("overlay/machine/overlay_maintenance_sterile"); + CRIB_ACTIVE = new SimpleOverlayRenderer("overlay/machine/OVERLAY_ME_CRAFTING_INPUT_BUFFER"); + CRIB_INACTIVE = new SimpleOverlayRenderer("overlay/machine/OVERLAY_ME_CRAFTING_INPUT_BUS"); + CRIB_PROXY = new SimpleOverlayRenderer("overlay/machine/OVERLAY_ME_CRAFTING_INPUT_SLAVE"); ITEM_FLUID_OVERLAY = TextureArea.fullImage("textures/gui/widget/item_fluid.png"); AUTO_PULL = TextureArea.fullImage("textures/gui/widget/auto_pull.png"); PME = TextureArea.fullImage("textures/gui/widget/pme.png"); AE2_RW_STATES = TextureArea.fullImage("textures/gui/widget/ae2_rw_states.png"); SLIME_BALL = TextureArea.fullImage("textures/gui/widget/slimeball.png"); + ME_PATTERN_OVERLAY = TextureArea.fullImage("textures/gui/widget/pattern_me.png"); + EXPORT = TextureArea.fullImage("textures/gui/widget/export.png"); PROGRESS_BAR_CoAL = TextureArea.fullImage("textures/gui/progress_bar/progress_bar_component_al.png"); diff --git a/src/main/java/com/zorbatron/zbgt/client/widgets/PhantomSlotNoTextWidget.java b/src/main/java/com/zorbatron/zbgt/client/widgets/PhantomSlotNoAmountTextWidget.java similarity index 50% rename from src/main/java/com/zorbatron/zbgt/client/widgets/PhantomSlotNoTextWidget.java rename to src/main/java/com/zorbatron/zbgt/client/widgets/PhantomSlotNoAmountTextWidget.java index c0c2e79d..3fd18059 100644 --- a/src/main/java/com/zorbatron/zbgt/client/widgets/PhantomSlotNoTextWidget.java +++ b/src/main/java/com/zorbatron/zbgt/client/widgets/PhantomSlotNoAmountTextWidget.java @@ -1,9 +1,5 @@ package com.zorbatron.zbgt.client.widgets; -import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.GlStateManager; -import net.minecraft.client.renderer.RenderHelper; -import net.minecraft.client.renderer.RenderItem; import net.minecraft.inventory.Container; import net.minecraft.item.ItemStack; import net.minecraftforge.fml.relauncher.Side; @@ -17,9 +13,10 @@ import gregtech.api.util.Position; import gregtech.api.util.Size; -public class PhantomSlotNoTextWidget extends PhantomSlotWidget { +public class PhantomSlotNoAmountTextWidget extends PhantomSlotWidget { - public PhantomSlotNoTextWidget(IItemHandlerModifiable itemHandler, int slotIndex, int xPosition, int yPosition) { + public PhantomSlotNoAmountTextWidget(IItemHandlerModifiable itemHandler, int slotIndex, int xPosition, + int yPosition) { super(itemHandler, slotIndex, xPosition, yPosition); } @@ -50,42 +47,13 @@ public void drawInBackground(int mouseX, int mouseY, float partialTicks, IRender } } if (!itemStack.isEmpty()) { - GlStateManager.enableBlend(); - GlStateManager.enableDepth(); - GlStateManager.disableRescaleNormal(); - GlStateManager.disableLighting(); - RenderHelper.disableStandardItemLighting(); - RenderHelper.enableStandardItemLighting(); - RenderHelper.enableGUIStandardItemLighting(); - GlStateManager.pushMatrix(); - RenderItem itemRender = Minecraft.getMinecraft().getRenderItem(); - // itemStack.setCount(1); - itemRender.renderItemAndEffectIntoGUI(itemStack, pos.x + 1, pos.y + 1); - // itemRender.renderItemOverlayIntoGUI(Minecraft.getMinecraft().fontRenderer, itemStack, pos.x + 1, pos.y + - // 1, - // null); - GlStateManager.enableAlpha(); - GlStateManager.popMatrix(); - RenderHelper.disableStandardItemLighting(); + // Set the stack count to 1 which doesn't show the amount text + itemStack.setCount(1); + drawItemStack(itemStack, pos.x + 1, pos.y + 1, null); } - if (isActive()) { - if (slotReference instanceof ISlotWidget) { - if (isMouseOverElement(mouseX, mouseY)) { - GlStateManager.disableDepth(); - GlStateManager.colorMask(true, true, true, false); - drawSolidRect(getPosition().x + 1, getPosition().y + 1, 16, 16, -2130706433); - GlStateManager.colorMask(true, true, true, true); - GlStateManager.enableDepth(); - GlStateManager.enableBlend(); - } - } - } else { - GlStateManager.disableDepth(); - GlStateManager.colorMask(true, true, true, false); - drawSolidRect(getPosition().x + 1, getPosition().y + 1, 16, 16, 0xbf000000); - GlStateManager.colorMask(true, true, true, true); - GlStateManager.enableDepth(); - GlStateManager.enableBlend(); + + if (isMouseOverElement(mouseX, mouseY)) { + drawSelectionOverlay(pos.x + 1, pos.y + 1, 16, 16); } } } diff --git a/src/main/java/com/zorbatron/zbgt/common/metatileentities/ZBGTMetaTileEntities.java b/src/main/java/com/zorbatron/zbgt/common/metatileentities/ZBGTMetaTileEntities.java index 5e66aa0b..648ee9a9 100644 --- a/src/main/java/com/zorbatron/zbgt/common/metatileentities/ZBGTMetaTileEntities.java +++ b/src/main/java/com/zorbatron/zbgt/common/metatileentities/ZBGTMetaTileEntities.java @@ -30,6 +30,8 @@ public class ZBGTMetaTileEntities { public static MetaTileEntityLargeParallelHatch[] ZBGT_PARALLEL_HATCHES = new MetaTileEntityLargeParallelHatch[7]; public static MetaTileEntityYOTTankMEHatch YOTTANK_ME_HATCH; public static MetaTileEntitySterileCleaningHatch STERILE_CLEANING_HATCH; + public static MetaTileEntityBudgetCRIB BUDGET_CRIB; + public static MetaTileEntityBudgetCRIBProxy BUDGET_CRIB_PROXY; public static MetaTileEntityMegaEBF MEGA_EBF; public static MetaTileEntityMegaLCR MEGA_LCR; @@ -104,6 +106,11 @@ public static void init() { STERILE_CLEANING_HATCH = registerMetaTileEntity(18018, new MetaTileEntitySterileCleaningHatch(zbgtId("sterile_cleaning_hatch"))); + BUDGET_CRIB = registerMetaTileEntity(18019, + new MetaTileEntityBudgetCRIB(zbgtId("budget_crib"))); + BUDGET_CRIB_PROXY = registerMetaTileEntity(18020, + new MetaTileEntityBudgetCRIBProxy(zbgtId("budget_crib_proxy"))); + // 18050-18099 (50) reserved for multiblocks MEGA_EBF = registerMetaTileEntity(18050, new MetaTileEntityMegaEBF(zbgtId("mega_ebf"))); diff --git a/src/main/java/com/zorbatron/zbgt/common/metatileentities/multi/multiblockpart/MetaTileEntityBudgetCRIB.java b/src/main/java/com/zorbatron/zbgt/common/metatileentities/multi/multiblockpart/MetaTileEntityBudgetCRIB.java new file mode 100644 index 00000000..a69b7d12 --- /dev/null +++ b/src/main/java/com/zorbatron/zbgt/common/metatileentities/multi/multiblockpart/MetaTileEntityBudgetCRIB.java @@ -0,0 +1,653 @@ +package com.zorbatron.zbgt.common.metatileentities.multi.multiblockpart; + +import static gregtech.api.capability.GregtechDataCodes.*; + +import java.io.IOException; +import java.util.Arrays; +import java.util.EnumSet; +import java.util.List; + +import net.minecraft.client.resources.I18n; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.InventoryCrafting; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.network.PacketBuffer; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.NonNullList; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.text.TextComponentTranslation; +import net.minecraft.util.text.TextFormatting; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.items.IItemHandler; +import net.minecraftforge.items.IItemHandlerModifiable; +import net.minecraftforge.items.ItemHandlerHelper; +import net.minecraftforge.items.ItemStackHandler; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import com.zorbatron.zbgt.api.render.ZBGTTextures; +import com.zorbatron.zbgt.api.util.ZBGTUtility; +import com.zorbatron.zbgt.client.widgets.ItemSlotTinyAmountTextWidget; + +import appeng.api.AEApi; +import appeng.api.config.Actionable; +import appeng.api.implementations.ICraftingPatternItem; +import appeng.api.implementations.IPowerChannelState; +import appeng.api.networking.GridFlags; +import appeng.api.networking.IGridNode; +import appeng.api.networking.crafting.ICraftingPatternDetails; +import appeng.api.networking.crafting.ICraftingProvider; +import appeng.api.networking.crafting.ICraftingProviderHelper; +import appeng.api.networking.events.MENetworkCraftingPatternChange; +import appeng.api.networking.security.IActionHost; +import appeng.api.networking.security.IActionSource; +import appeng.api.storage.IMEMonitor; +import appeng.api.storage.IStorageChannel; +import appeng.api.storage.channels.IItemStorageChannel; +import appeng.api.storage.data.IAEItemStack; +import appeng.api.util.AECableType; +import appeng.api.util.AEPartLocation; +import appeng.api.util.DimensionalCoord; +import appeng.me.GridAccessException; +import appeng.me.helpers.AENetworkProxy; +import appeng.me.helpers.BaseActionSource; +import appeng.me.helpers.IGridProxyable; +import appeng.me.helpers.MachineSource; +import appeng.util.item.AEItemStack; +import codechicken.lib.render.CCRenderState; +import codechicken.lib.render.pipeline.IVertexOperation; +import codechicken.lib.vec.Matrix4; +import gregtech.api.GTValues; +import gregtech.api.capability.*; +import gregtech.api.capability.impl.GhostCircuitItemStackHandler; +import gregtech.api.capability.impl.ItemHandlerList; +import gregtech.api.capability.impl.NotifiableItemStackHandler; +import gregtech.api.gui.GuiTextures; +import gregtech.api.gui.ModularUI; +import gregtech.api.gui.widgets.*; +import gregtech.api.metatileentity.MetaTileEntity; +import gregtech.api.metatileentity.interfaces.IGregTechTileEntity; +import gregtech.api.metatileentity.multiblock.IMultiblockAbilityPart; +import gregtech.api.metatileentity.multiblock.MultiblockAbility; +import gregtech.api.metatileentity.multiblock.MultiblockControllerBase; +import gregtech.api.util.GTUtility; +import gregtech.api.util.Position; +import gregtech.api.util.TextFormattingUtil; +import gregtech.common.ConfigHolder; +import gregtech.common.metatileentities.multi.multiblockpart.MetaTileEntityMultiblockNotifiablePart; + +public class MetaTileEntityBudgetCRIB extends MetaTileEntityMultiblockNotifiablePart + implements IMultiblockAbilityPart, ICraftingProvider, + IGridProxyable, IPowerChannelState, IGhostSlotConfigurable, IControllable, + IDataStickIntractable { + + @Nullable + protected GhostCircuitItemStackHandler circuitInventory; + private ItemStackHandler patternSlot; + private ICraftingPatternDetails patternDetails; + private NotifiableItemStackHandler patternItems; + private IItemHandlerModifiable actualImportItems; + private IItemHandlerModifiable extraItem; + private boolean needPatternSync = true; + // Controls blocking + private boolean isWorkingEnabled = true; + + private @Nullable AENetworkProxy aeProxy; + private boolean isOnline; + + public MetaTileEntityBudgetCRIB(ResourceLocation metaTileEntityId) { + super(metaTileEntityId, GTValues.EV, false); + } + + @Override + protected void initializeInventory() { + super.initializeInventory(); + + this.patternSlot = new ItemStackHandler(1) { + + @Override + public int getSlotLimit(int slot) { + return 1; + } + + @Override + public boolean isItemValid(int slot, @NotNull ItemStack stack) { + return stack.getItem() instanceof ICraftingPatternItem; + } + + @Override + protected void onContentsChanged(int slot) { + needPatternSync = true; + setPatternDetails(); + } + }; + + this.circuitInventory = new GhostCircuitItemStackHandler(this); + this.circuitInventory.addNotifiableMetaTileEntity(this); + + this.extraItem = new NotifiableItemStackHandler(this, 1, null, false) { + + @Override + public boolean isItemValid(int slot, @NotNull ItemStack stack) { + return !(stack.getItem() instanceof ICraftingPatternItem); + } + }; + + this.patternItems = new NotifiableItemStackHandler(this, 16, null, false) { + + @Override + public int getSlotLimit(int slot) { + return Integer.MAX_VALUE; + } + + @Override + protected int getStackLimit(int slot, @NotNull ItemStack stack) { + return getSlotLimit(slot); + } + + @NotNull + @Override + public ItemStack extractItem(int slot, int amount, boolean simulate) { + if (amount == 0) return ItemStack.EMPTY; + + validateSlotIndex(slot); + + ItemStack existing = this.stacks.get(slot); + + if (existing.isEmpty()) return ItemStack.EMPTY; + + if (existing.getCount() <= amount) { + if (!simulate) { + this.stacks.set(slot, ItemStack.EMPTY); + onContentsChanged(slot); + } + + return existing; + } else { + if (!simulate) { + this.stacks.set(slot, ItemHandlerHelper.copyStackWithSize( + existing, existing.getCount() - amount)); + onContentsChanged(slot); + } + + return ItemHandlerHelper.copyStackWithSize(existing, amount); + } + } + }; + + this.actualImportItems = new ItemHandlerList( + Arrays.asList(this.patternItems, this.circuitInventory, this.extraItem)); + } + + @Override + public IItemHandlerModifiable getImportItems() { + return this.actualImportItems; + } + + @Override + public MetaTileEntity createMetaTileEntity(IGregTechTileEntity tileEntity) { + return new MetaTileEntityBudgetCRIB(metaTileEntityId); + } + + @Override + protected ModularUI createUI(EntityPlayer entityPlayer) { + ModularUI.Builder builder = ModularUI.builder(GuiTextures.BACKGROUND, 176, 166 + 18 * 2) + .label(7, 7, getMetaFullName()); + + // Item slots + WidgetGroup slots = new WidgetGroup(new Position((int) (7 + 18 * 2.5), 20)); + for (int y = 0; y <= 3; y++) { + for (int x = 0; x <= 3; x++) { + int index = y * 4 + x; + slots.addWidget(new ItemSlotTinyAmountTextWidget(patternItems, index, 18 * x, 18 * y, + false, false) { + + @Override + public void drawInForeground(int mouseX, int mouseY) { + ItemStack item = patternItems.getStackInSlot(index); + + if (isMouseOverElement(mouseX, mouseY) && !item.isEmpty()) { + List tooltip = getItemToolTip(item); + + tooltip.add(TextFormatting.GRAY + I18n.format("zbgt.machine.budget_crib.amount_tooltip", + TextFormattingUtil.formatNumbers(item.getCount()))); + + drawHoveringText(item, tooltip, -1, mouseX, mouseY); + } + } + }.setBackgroundTexture(GuiTextures.SLOT)); + } + } + + WidgetGroup buttons = new WidgetGroup(new Position(7 + 18 * 2, (int) (18 * 5.25) + 3)); + + // Extra item slot + buttons.addWidget(new SlotWidget(extraItem, 0, 0, 0) + .setBackgroundTexture(GuiTextures.SLOT).setTooltipText("zbgt.machine.budget_crib.extra_item")); + + // Circuit slot + buttons.addWidget(new GhostCircuitSlotWidget(circuitInventory, 0, 18, 0) + .setBackgroundTexture(GuiTextures.SLOT, GuiTextures.INT_CIRCUIT_OVERLAY) + .setConsumer(this::getCircuitSlotTooltip)); + + // Pattern slot + buttons.addWidget(new SlotWidget(patternSlot, 0, 18 * 2, 0) + .setBackgroundTexture(GuiTextures.SLOT, ZBGTTextures.ME_PATTERN_OVERLAY)); + + // Blocking toggle + buttons.addWidget(new ImageCycleButtonWidget(18 * 3, 0, 18, 18, GuiTextures.BUTTON_POWER, + this::isWorkingEnabled, this::setWorkingEnabled) + .setTooltipHoverString("zbgt.machine.budget_crib.blocking_button")); + + // Return items + buttons.addWidget(new ClickButtonWidget(18 * 4, 0, 18, 18, "", (clickData) -> returnItems()) + .setButtonTexture(ZBGTTextures.EXPORT).setTooltipText("zbgt.machine.budget_crib.return_button")); + + builder.bindPlayerInventory(entityPlayer.inventory, GuiTextures.SLOT, 7, 18 + 18 * 5 + 12); + return builder.widget(slots).widget(buttons).build(getHolder(), entityPlayer); + } + + protected void getCircuitSlotTooltip(@NotNull SlotWidget widget) { + String configString; + if (circuitInventory == null || circuitInventory.getCircuitValue() == GhostCircuitItemStackHandler.NO_CONFIG) { + configString = new TextComponentTranslation("gregtech.gui.configurator_slot.no_value").getFormattedText(); + } else { + configString = String.valueOf(circuitInventory.getCircuitValue()); + } + + widget.setTooltipText("gregtech.gui.configurator_slot.tooltip", configString); + } + + @Override + public boolean hasGhostCircuitInventory() { + return this.circuitInventory != null; + } + + @Override + public void setGhostCircuitConfig(int config) { + if (this.circuitInventory == null || this.circuitInventory.getCircuitValue() == config) { + return; + } + this.circuitInventory.setCircuitValue(config); + if (!getWorld().isRemote) { + markDirty(); + } + } + + @Override + public void renderMetaTileEntity(CCRenderState renderState, Matrix4 translation, IVertexOperation[] pipeline) { + super.renderMetaTileEntity(renderState, translation, pipeline); + if (isOnline) { + ZBGTTextures.CRIB_ACTIVE.renderSided(getFrontFacing(), renderState, translation, pipeline); + } else { + ZBGTTextures.CRIB_INACTIVE.renderSided(getFrontFacing(), renderState, translation, pipeline); + } + } + + @Override + public void update() { + super.update(); + + if (!getWorld().isRemote) { + updateMEStatus(); + + if (needPatternSync && getOffsetTimer() % 10 == 0) { + needPatternSync = MEPatternChange(); + } + } + } + + private IActionSource getActionSource() { + if (this.getHolder() instanceof IActionHost holder) { + return new MachineSource(holder); + } + return new BaseActionSource(); + } + + @Nullable + private IMEMonitor getMonitor() { + AENetworkProxy proxy = getProxy(); + if (proxy == null) return null; + + IStorageChannel channel = AEApi.instance().storage().getStorageChannel(IItemStorageChannel.class); + + try { + return proxy.getStorage().getInventory(channel); + } catch (GridAccessException ignored) { + return null; + } + } + + private void returnItems() { + if (checkIfEmpty()) return; + + IMEMonitor monitor = getMonitor(); + if (monitor == null) return; + + for (int x = 0; x < this.patternItems.getSlots(); x++) { + ItemStack itemStack = this.patternItems.getStackInSlot(x); + if (itemStack.isEmpty()) continue; + + IAEItemStack iaeItemStack = AEItemStack.fromItemStack(itemStack); + + IAEItemStack notInserted = monitor.injectItems(iaeItemStack, Actionable.MODULATE, getActionSource()); + if (notInserted != null && notInserted.getStackSize() > 0) { + itemStack.setCount((int) notInserted.getStackSize()); + } else { + this.patternItems.setStackInSlot(x, ItemStack.EMPTY); + } + } + } + + private boolean MEPatternChange() { + // don't post until it's active + if (getProxy() == null || !getProxy().isActive()) return true; + + try { + getProxy().getGrid().postEvent(new MENetworkCraftingPatternChange(this, getProxy().getNode())); + } catch (Exception ignored) { + return true; + } + + return false; + } + + public boolean updateMEStatus() { + boolean isOnline = this.aeProxy != null && this.aeProxy.isActive() && this.aeProxy.isPowered(); + if (this.isOnline != isOnline) { + writeCustomData(UPDATE_ONLINE_STATUS, buf -> buf.writeBoolean(isOnline)); + this.isOnline = isOnline; + } + return this.isOnline; + } + + @Override + public void receiveCustomData(int dataId, PacketBuffer buf) { + super.receiveCustomData(dataId, buf); + if (dataId == UPDATE_ONLINE_STATUS) { + boolean isOnline = buf.readBoolean(); + if (this.isOnline != isOnline) { + this.isOnline = isOnline; + scheduleRenderUpdate(); + } else if (dataId == UPDATE_ACTIVE) { + this.isWorkingEnabled = buf.readBoolean(); + } + } + } + + @Override + public void writeInitialSyncData(PacketBuffer buf) { + super.writeInitialSyncData(buf); + if (this.aeProxy != null) { + buf.writeBoolean(true); + NBTTagCompound proxy = new NBTTagCompound(); + this.aeProxy.writeToNBT(proxy); + buf.writeCompoundTag(proxy); + } else { + buf.writeBoolean(false); + } + buf.writeBoolean(this.isOnline); + buf.writeBoolean(this.isWorkingEnabled); + } + + @Override + public void receiveInitialSyncData(PacketBuffer buf) { + super.receiveInitialSyncData(buf); + if (buf.readBoolean()) { + NBTTagCompound nbtTagCompound; + try { + nbtTagCompound = buf.readCompoundTag(); + } catch (IOException ignored) { + nbtTagCompound = null; + } + + if (this.aeProxy != null && nbtTagCompound != null) { + this.aeProxy.readFromNBT(nbtTagCompound); + } + } + this.isOnline = buf.readBoolean(); + this.isWorkingEnabled = buf.readBoolean(); + } + + @Nullable + @Override + public IGridNode getGridNode(@NotNull AEPartLocation aePartLocation) { + return getProxy().getNode(); + } + + @NotNull + @Override + public AECableType getCableConnectionType(@NotNull AEPartLocation part) { + if (part.getFacing() != this.frontFacing) { + return AECableType.NONE; + } + return AECableType.SMART; + } + + @Nullable + @Override + public AENetworkProxy getProxy() { + if (this.aeProxy == null) { + return this.aeProxy = this.createProxy(); + } + if (!this.aeProxy.isReady() && this.getWorld() != null) { + this.aeProxy.onReady(); + } + return this.aeProxy; + } + + @Nullable + private AENetworkProxy createProxy() { + AENetworkProxy proxy = new AENetworkProxy(this, "mte_proxy", this.getStackForm(), true); + proxy.setFlags(GridFlags.REQUIRE_CHANNEL); + proxy.setIdlePowerUsage(ConfigHolder.compat.ae2.meHatchEnergyUsage); + proxy.setValidSides(EnumSet.of(this.getFrontFacing())); + return proxy; + } + + @Override + public void setFrontFacing(EnumFacing frontFacing) { + super.setFrontFacing(frontFacing); + if (this.aeProxy != null) { + this.aeProxy.setValidSides(EnumSet.of(this.getFrontFacing())); + } + } + + @Override + public void securityBreak() {} + + @Override + public void provideCrafting(ICraftingProviderHelper iCraftingProviderHelper) { + if (!isActive() || patternDetails == null) return; + iCraftingProviderHelper.addCraftingOption(this, patternDetails); + } + + private void setPatternDetails() { + ItemStack pattern = patternSlot.getStackInSlot(0); + if (pattern.isEmpty()) { + patternDetails = null; + return; + } + + if (pattern.getItem() instanceof ICraftingPatternItem patternItem) { + this.patternDetails = patternItem.getPatternForItem(pattern, getWorld()); + } + } + + @Override + public boolean pushPattern(ICraftingPatternDetails iCraftingPatternDetails, InventoryCrafting inventoryCrafting) { + if (!isActive()) return false; + + for (int i = 0; i < inventoryCrafting.getSizeInventory(); ++i) { + ItemStack itemStack = inventoryCrafting.getStackInSlot(i); + if (itemStack.isEmpty()) continue; + if (patternItems.insertItem(i, itemStack, true) != ItemStack.EMPTY) return false; + } + + for (int i = 0; i < inventoryCrafting.getSizeInventory(); ++i) { + ItemStack itemStack = inventoryCrafting.getStackInSlot(i); + if (itemStack.isEmpty()) continue; + patternItems.insertItem(i, itemStack, false); + } + + return true; + } + + @Override + public boolean isBusy() { + return isWorkingEnabled && !checkIfEmpty(); + } + + /** + * @return false if items are in any slot, true if empty + */ + private boolean checkIfEmpty() { + return ZBGTUtility.isInventoryEmpty(patternItems); + } + + @Override + public void gridChanged() { + needPatternSync = true; + } + + @Override + public DimensionalCoord getLocation() { + return new DimensionalCoord(getWorld(), getPos()); + } + + @Override + public MultiblockAbility getAbility() { + return MultiblockAbility.IMPORT_ITEMS; + } + + @Override + public void registerAbilities(List abilityList) { + abilityList.add(this.actualImportItems); + } + + @Override + public boolean isPowered() { + return getProxy() != null && getProxy().isPowered(); + } + + @Override + public boolean isActive() { + return getProxy() != null && getProxy().isActive(); + } + + @Override + public NBTTagCompound writeToNBT(NBTTagCompound data) { + super.writeToNBT(data); + + data.setTag("Pattern", this.patternSlot.serializeNBT()); + GTUtility.writeItems(this.patternItems, "PatternItems", data); + + if (this.circuitInventory != null) { + this.circuitInventory.write(data); + } + + GTUtility.writeItems(this.extraItem, "ExtraItem", data); + + data.setBoolean("BlockingEnabled", this.isWorkingEnabled); + + return data; + } + + @Override + public void readFromNBT(NBTTagCompound data) { + super.readFromNBT(data); + + this.patternSlot.deserializeNBT(data.getCompoundTag("Pattern")); + setPatternDetails(); + GTUtility.readItems(this.patternItems, "PatternItems", data); + + circuitInventory.read(data); + + GTUtility.readItems(this.extraItem, "ExtraItem", data); + + this.isWorkingEnabled = data.getBoolean("BlockingEnabled"); + } + + @Override + public void addToMultiBlock(MultiblockControllerBase controllerBase) { + super.addToMultiBlock(controllerBase); + + for (IItemHandler handler : ((ItemHandlerList) this.actualImportItems).getBackingHandlers()) { + if (handler instanceof INotifiableHandler notifiable) { + notifiable.addNotifiableMetaTileEntity(controllerBase); + notifiable.addToNotifiedList(this, handler, false); + } + } + } + + @Override + public void removeFromMultiBlock(MultiblockControllerBase controllerBase) { + super.removeFromMultiBlock(controllerBase); + + for (IItemHandler handler : ((ItemHandlerList) this.actualImportItems).getBackingHandlers()) { + if (handler instanceof INotifiableHandler notifiable) { + notifiable.removeNotifiableMetaTileEntity(controllerBase); + } + } + } + + @Override + public boolean isWorkingEnabled() { + return this.isWorkingEnabled; + } + + @Override + public void setWorkingEnabled(boolean isWorkingAllowed) { + this.isWorkingEnabled = isWorkingAllowed; + if (!getWorld().isRemote) { + writeCustomData(GregtechDataCodes.UPDATE_ACTIVE, buf -> buf.writeBoolean(isWorkingAllowed)); + } + } + + @Override + public T getCapability(Capability capability, EnumFacing side) { + if (capability == GregtechTileCapabilities.CAPABILITY_CONTROLLABLE) { + return GregtechTileCapabilities.CAPABILITY_CONTROLLABLE.cast(this); + } + return super.getCapability(capability, side); + } + + @Override + public void clearMachineInventory(NonNullList itemBuffer) { + super.clearMachineInventory(itemBuffer); + clearInventory(itemBuffer, this.patternSlot); + clearInventory(itemBuffer, this.extraItem); + this.returnItems(); + } + + @Override + public void onDataStickLeftClick(EntityPlayer player, ItemStack dataStick) { + NBTTagCompound tag = new NBTTagCompound(); + + tag.setTag("BudgetCRIB", writeLocationToTag()); + dataStick.setTagCompound(tag); + dataStick.setTranslatableName("zbgt.machine.budget_crib.data_stick_name"); + player.sendStatusMessage(new TextComponentTranslation("zbgt.machine.budget_crib.data_stick_use"), true); + } + + private NBTTagCompound writeLocationToTag() { + NBTTagCompound tag = new NBTTagCompound(); + + tag.setInteger("MainX", getPos().getX()); + tag.setInteger("MainY", getPos().getY()); + tag.setInteger("MainZ", getPos().getZ()); + + return tag; + } + + @Override + public boolean onDataStickRightClick(EntityPlayer player, ItemStack dataStick) { + return false; + } + + public NotifiableItemStackHandler getPatternItems() { + return this.patternItems; + } +} diff --git a/src/main/java/com/zorbatron/zbgt/common/metatileentities/multi/multiblockpart/MetaTileEntityBudgetCRIBProxy.java b/src/main/java/com/zorbatron/zbgt/common/metatileentities/multi/multiblockpart/MetaTileEntityBudgetCRIBProxy.java new file mode 100644 index 00000000..9f33cf6b --- /dev/null +++ b/src/main/java/com/zorbatron/zbgt/common/metatileentities/multi/multiblockpart/MetaTileEntityBudgetCRIBProxy.java @@ -0,0 +1,249 @@ +package com.zorbatron.zbgt.common.metatileentities.multi.multiblockpart; + +import java.util.List; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.network.PacketBuffer; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.text.TextComponentTranslation; +import net.minecraftforge.items.IItemHandlerModifiable; + +import org.jetbrains.annotations.NotNull; + +import com.zorbatron.zbgt.api.render.ZBGTTextures; +import com.zorbatron.zbgt.api.util.ZBGTUtility; + +import codechicken.lib.render.CCRenderState; +import codechicken.lib.render.pipeline.IVertexOperation; +import codechicken.lib.vec.Matrix4; +import gregtech.api.GTValues; +import gregtech.api.capability.IDataStickIntractable; +import gregtech.api.capability.impl.NotifiableItemStackHandler; +import gregtech.api.gui.ModularUI; +import gregtech.api.gui.widgets.*; +import gregtech.api.metatileentity.MetaTileEntity; +import gregtech.api.metatileentity.interfaces.IGregTechTileEntity; +import gregtech.api.metatileentity.multiblock.IMultiblockAbilityPart; +import gregtech.api.metatileentity.multiblock.MultiblockAbility; +import gregtech.api.metatileentity.multiblock.MultiblockControllerBase; +import gregtech.api.util.TextFormattingUtil; +import gregtech.common.metatileentities.multi.multiblockpart.MetaTileEntityMultiblockNotifiablePart; + +public class MetaTileEntityBudgetCRIBProxy extends MetaTileEntityMultiblockNotifiablePart + implements IMultiblockAbilityPart, + IDataStickIntractable { + + private MetaTileEntityBudgetCRIB main; + private BlockPos mainPos; + private boolean checkForMain = true; + private final ProxyItemHandler proxyItemHandler = new ProxyItemHandler(); + + public MetaTileEntityBudgetCRIBProxy(ResourceLocation metaTileEntityId) { + super(metaTileEntityId, GTValues.LuV, false); + } + + @Override + public MetaTileEntity createMetaTileEntity(IGregTechTileEntity tileEntity) { + return new MetaTileEntityBudgetCRIBProxy(metaTileEntityId); + } + + @Override + public void update() { + super.update(); + + if (!getWorld().isRemote && getOffsetTimer() % 100 == 0 && checkForMain && !hasMain()) { + tryToSetMain(); + } + } + + @Override + public MultiblockAbility getAbility() { + return MultiblockAbility.IMPORT_ITEMS; + } + + @Override + public void registerAbilities(List abilityList) { + abilityList.add(new ProxyItemHandler()); + } + + @Override + public void addToMultiBlock(MultiblockControllerBase controllerBase) { + super.addToMultiBlock(controllerBase); + + if (hasMain()) { + ZBGTUtility.addNotifiableToMTE(getMain().getPatternItems(), controllerBase, this, false); + } + } + + @Override + public void removeFromMultiBlock(MultiblockControllerBase controllerBase) { + super.removeFromMultiBlock(controllerBase); + + if (hasMain()) { + ZBGTUtility.removeNotifiableFromMTE(getMain().getPatternItems(), controllerBase); + } + } + + @Override + protected boolean openGUIOnRightClick() { + return getMain() != null; + } + + @Override + protected ModularUI createUI(EntityPlayer entityPlayer) { + return getMain().createUI(entityPlayer); + } + + @Override + public void renderMetaTileEntity(CCRenderState renderState, Matrix4 translation, IVertexOperation[] pipeline) { + super.renderMetaTileEntity(renderState, translation, pipeline); + + ZBGTTextures.CRIB_PROXY.renderSided(getFrontFacing(), renderState, translation, pipeline); + } + + private void tryToSetMain() { + if (getWorld() == null || mainPos == null) return; + + TileEntity tileEntity = getWorld().getTileEntity(mainPos); + if (!(tileEntity instanceof IGregTechTileEntity iGregTechTileEntity)) { + this.checkForMain = true; + return; + } + + MetaTileEntity metaTileEntity = iGregTechTileEntity.getMetaTileEntity(); + if (!(metaTileEntity instanceof MetaTileEntityBudgetCRIB budgetCRIB)) { + this.checkForMain = true; + return; + } + + this.main = budgetCRIB; + this.checkForMain = false; + + MultiblockControllerBase controllerBase = getController(); + if (controllerBase != null) { + NotifiableItemStackHandler mainCRIBPatternItems = getMain().getPatternItems(); + ZBGTUtility.addNotifiableToMTE(mainCRIBPatternItems, controllerBase, this, false); + controllerBase.addNotifiedInput(mainCRIBPatternItems); + } + } + + private MetaTileEntityBudgetCRIB getMain() { + return main; + } + + public boolean hasMain() { + return main != null && main.isValid(); + } + + @Override + public void onDataStickLeftClick(EntityPlayer player, ItemStack dataStick) {} + + @Override + public boolean onDataStickRightClick(EntityPlayer player, ItemStack dataStick) { + NBTTagCompound tag = dataStick.getTagCompound(); + if (tag == null || !tag.hasKey("BudgetCRIB")) return false; + + readLocationFromTag(tag.getCompoundTag("BudgetCRIB")); + player.sendStatusMessage(new TextComponentTranslation("zbgt.machine.budget_crib_proxy.data_stick_use", + TextFormattingUtil.formatNumbers(mainPos.getX()), + TextFormattingUtil.formatNumbers(mainPos.getY()), + TextFormattingUtil.formatNumbers(mainPos.getZ())), true); + + tryToSetMain(); + + return true; + } + + private void readLocationFromTag(NBTTagCompound tag) { + this.mainPos = new BlockPos(tag.getInteger("MainX"), tag.getInteger("MainY"), tag.getInteger("MainZ")); + } + + @Override + public void readFromNBT(NBTTagCompound data) { + super.readFromNBT(data); + + if (data.getBoolean("HasMain")) { + readLocationFromTag(data); + } + + tryToSetMain(); + } + + @Override + public NBTTagCompound writeToNBT(NBTTagCompound data) { + if (hasMain()) { + data.setBoolean("HasMain", true); + data.setInteger("MainX", mainPos.getX()); + data.setInteger("MainY", mainPos.getY()); + data.setInteger("MainZ", mainPos.getZ()); + } else { + data.setBoolean("HasMain", false); + } + + return super.writeToNBT(data); + } + + @Override + public void writeInitialSyncData(PacketBuffer buf) { + super.writeInitialSyncData(buf); + + if (main != null) { + buf.writeBoolean(true); + buf.writeBlockPos(mainPos); + } else { + buf.writeBoolean(false); + } + } + + @Override + public void receiveInitialSyncData(PacketBuffer buf) { + super.receiveInitialSyncData(buf); + + if (buf.readBoolean()) { + mainPos = buf.readBlockPos(); + + tryToSetMain(); + } + } + + // To act as a middleman when not linked to a main crib + @SuppressWarnings("InnerClassMayBeStatic") + private class ProxyItemHandler implements IItemHandlerModifiable { + + public ProxyItemHandler() {/**/} + + @Override + public void setStackInSlot(int slot, @NotNull ItemStack stack) { + // I only have to worry about extracting :p + } + + @Override + public int getSlots() { + return 18; // 16 pattern slots + catalyst slot + circuit + } + + @Override + public @NotNull ItemStack getStackInSlot(int slot) { + return hasMain() ? getMain().getImportItems().getStackInSlot(slot) : ItemStack.EMPTY; + } + + @Override + public @NotNull ItemStack insertItem(int slot, @NotNull ItemStack stack, boolean simulate) { + return stack; + } + + @Override + public @NotNull ItemStack extractItem(int slot, int amount, boolean simulate) { + return hasMain() ? getMain().getImportItems().extractItem(slot, amount, simulate) : ItemStack.EMPTY; + } + + @Override + public int getSlotLimit(int slot) { + return Integer.MAX_VALUE; + } + } +} diff --git a/src/main/java/com/zorbatron/zbgt/common/metatileentities/multi/multiblockpart/MetaTileEntityCreativeItemBus.java b/src/main/java/com/zorbatron/zbgt/common/metatileentities/multi/multiblockpart/MetaTileEntityCreativeItemBus.java index 098cf994..dfc7ed16 100644 --- a/src/main/java/com/zorbatron/zbgt/common/metatileentities/multi/multiblockpart/MetaTileEntityCreativeItemBus.java +++ b/src/main/java/com/zorbatron/zbgt/common/metatileentities/multi/multiblockpart/MetaTileEntityCreativeItemBus.java @@ -21,7 +21,7 @@ import com.zorbatron.zbgt.api.capability.impl.InfiniteItemStackHandler; import com.zorbatron.zbgt.api.render.ZBGTTextures; import com.zorbatron.zbgt.api.util.ZBGTUtility; -import com.zorbatron.zbgt.client.widgets.PhantomSlotNoTextWidget; +import com.zorbatron.zbgt.client.widgets.PhantomSlotNoAmountTextWidget; import codechicken.lib.render.CCRenderState; import codechicken.lib.render.pipeline.IVertexOperation; @@ -85,7 +85,7 @@ protected ModularUI createUI(EntityPlayer entityPlayer) { for (int x = 0; x < 4; x++) { int index = y * 4 + x; - slots.addWidget(new PhantomSlotNoTextWidget(infiniteItemStackHandler, index, x * 18, y * 18) + slots.addWidget(new PhantomSlotNoAmountTextWidget(infiniteItemStackHandler, index, x * 18, y * 18) .setClearSlotOnRightClick(true).setBackgroundTexture(GuiTextures.SLOT)); } } diff --git a/src/main/resources/assets/gregtech/textures/blocks/overlay/machine/overlay_me_crafting_input_buffer.png b/src/main/resources/assets/gregtech/textures/blocks/overlay/machine/overlay_me_crafting_input_buffer.png new file mode 100644 index 00000000..ad6e2159 Binary files /dev/null and b/src/main/resources/assets/gregtech/textures/blocks/overlay/machine/overlay_me_crafting_input_buffer.png differ diff --git a/src/main/resources/assets/gregtech/textures/blocks/overlay/machine/overlay_me_crafting_input_bus.png b/src/main/resources/assets/gregtech/textures/blocks/overlay/machine/overlay_me_crafting_input_bus.png new file mode 100644 index 00000000..92325f21 Binary files /dev/null and b/src/main/resources/assets/gregtech/textures/blocks/overlay/machine/overlay_me_crafting_input_bus.png differ diff --git a/src/main/resources/assets/gregtech/textures/blocks/overlay/machine/overlay_me_crafting_input_slave.png b/src/main/resources/assets/gregtech/textures/blocks/overlay/machine/overlay_me_crafting_input_slave.png new file mode 100644 index 00000000..b1188aaf Binary files /dev/null and b/src/main/resources/assets/gregtech/textures/blocks/overlay/machine/overlay_me_crafting_input_slave.png differ diff --git a/src/main/resources/assets/gregtech/textures/gui/widget/export.png b/src/main/resources/assets/gregtech/textures/gui/widget/export.png new file mode 100644 index 00000000..aa586cce Binary files /dev/null and b/src/main/resources/assets/gregtech/textures/gui/widget/export.png differ diff --git a/src/main/resources/assets/gregtech/textures/gui/widget/pattern_me.png b/src/main/resources/assets/gregtech/textures/gui/widget/pattern_me.png new file mode 100644 index 00000000..86f9f491 Binary files /dev/null and b/src/main/resources/assets/gregtech/textures/gui/widget/pattern_me.png differ diff --git a/src/main/resources/assets/zbgt/lang/en_us.lang b/src/main/resources/assets/zbgt/lang/en_us.lang index 34c40429..674681fc 100644 --- a/src/main/resources/assets/zbgt/lang/en_us.lang +++ b/src/main/resources/assets/zbgt/lang/en_us.lang @@ -73,6 +73,19 @@ zbgt.machine.yottank_me_hatch.sticky.disabled=Enable sticky mode zbgt.machine.sterile_cleaning_hatch.name=Automatic Sterilization Maintenance Hatch zbgt.machine.sterile_cleaning_hatch.tooltip=For automatically maintaining Multiblocks with Cleaning, but sterile! +zbgt.machine.budget_crib.name=Budget CRIB +zbgt.machine.budget_crib.tooltip=A Crafting Input Bus on a budget +zbgt.machine.budget_crib.blocking_button=Click to toggle blocking mode +zbgt.machine.budget_crib.amount_tooltip=Amount: %s +zbgt.machine.budget_crib.return_button=Click to return items back to the network +zbgt.machine.budget_crib.extra_item=Slot for an extra item, such as a catalyst +zbgt.machine.budget_crib.data_stick_use=Wrote location to data stick +zbgt.machine.budget_crib.data_stick_name=Budget CRIB Location Data + +zbgt.machine.budget_crib_proxy.name=Budget CRIB Proxy +zbgt.machine.budget_crib_proxy.tooltip=Shares the inventory of the linked Budget CRIB +zbgt.machine.budget_crib_proxy.data_stick_use=Linked to Budget CRIB at X: %s, Y: %s, Z: %s + # Covers metaitem.cover.dual_cover.lv.name=LV Dual Cover