From 23bb18a40e9a06f00e195f3b7ceef97ae6759c1b Mon Sep 17 00:00:00 2001 From: bruberu <80226372+bruberu@users.noreply.github.com> Date: Mon, 12 Jul 2021 20:41:51 -0500 Subject: [PATCH 01/42] Start on clipboard GUI --- .../java/gregtech/api/gui/GuiTextures.java | 1 + .../gui/widgets/ImageCycleButtonWidget.java | 150 ++++++ .../api/gui/widgets/TextFieldWidget.java | 20 + .../blocks/clipboard/BlockClipboard.java | 196 +++++++ .../clipboard/MetaTileEntityClipboard.java | 289 ++++++++++ .../common/blocks/models/ModelCache.java | 52 ++ .../common/blocks/models/ModelClipboard.java | 210 ++++++++ .../java/gregtech/common/items/MetaItem2.java | 6 +- .../java/gregtech/common/items/MetaItems.java | 2 + .../items/behaviors/ClipboardBehaviour.java | 127 +++++ .../render/GTNativeTileEntityRenderer.java | 316 +++++++++++ .../TileEntityClipboardRenderer.java | 90 ++++ .../tileentities/EnumShiftPosition.java | 30 ++ .../common/tileentities/EnumVertPosition.java | 30 ++ .../tileentities/GTNativeTileEntity.java | 493 ++++++++++++++++++ 15 files changed, 2008 insertions(+), 4 deletions(-) create mode 100644 src/main/java/gregtech/api/gui/widgets/ImageCycleButtonWidget.java create mode 100644 src/main/java/gregtech/common/blocks/clipboard/BlockClipboard.java create mode 100644 src/main/java/gregtech/common/blocks/clipboard/MetaTileEntityClipboard.java create mode 100644 src/main/java/gregtech/common/blocks/models/ModelCache.java create mode 100644 src/main/java/gregtech/common/blocks/models/ModelClipboard.java create mode 100644 src/main/java/gregtech/common/items/behaviors/ClipboardBehaviour.java create mode 100644 src/main/java/gregtech/common/render/GTNativeTileEntityRenderer.java create mode 100644 src/main/java/gregtech/common/render/clipboard/TileEntityClipboardRenderer.java create mode 100644 src/main/java/gregtech/common/tileentities/EnumShiftPosition.java create mode 100644 src/main/java/gregtech/common/tileentities/EnumVertPosition.java create mode 100644 src/main/java/gregtech/common/tileentities/GTNativeTileEntity.java diff --git a/src/main/java/gregtech/api/gui/GuiTextures.java b/src/main/java/gregtech/api/gui/GuiTextures.java index 22319d1ee0b..1ed57383264 100644 --- a/src/main/java/gregtech/api/gui/GuiTextures.java +++ b/src/main/java/gregtech/api/gui/GuiTextures.java @@ -21,6 +21,7 @@ public class GuiTextures { //FLUID & ITEM OUTPUT BUTTONS public static final TextureArea BUTTON_FLUID_OUTPUT = TextureArea.fullImage("textures/gui/widget/button_fluid_output.png"); public static final TextureArea BUTTON_ITEM_OUTPUT = TextureArea.fullImage("textures/gui/widget/button_item_output.png"); + public static final TextureArea CLIPBOARD_CHECKBOX = TextureArea.fullImage("textures/gui/widget/clipboard_checkbox.png"); public static final SizedTextureArea VANILLA_BUTTON = SizedTextureArea.fullImage("textures/gui/widget/vanilla_button.png", 200, 40); public static final TextureArea BUTTON = TextureArea.fullImage("textures/gui/widget/button.png"); public static final TextureArea SWITCH = TextureArea.fullImage("textures/gui/widget/switch.png"); diff --git a/src/main/java/gregtech/api/gui/widgets/ImageCycleButtonWidget.java b/src/main/java/gregtech/api/gui/widgets/ImageCycleButtonWidget.java new file mode 100644 index 00000000000..05e24f7b85f --- /dev/null +++ b/src/main/java/gregtech/api/gui/widgets/ImageCycleButtonWidget.java @@ -0,0 +1,150 @@ +package gregtech.api.gui.widgets; + +import gregtech.api.gui.GuiTextures; +import gregtech.api.gui.IRenderContext; +import gregtech.api.gui.Widget; +import gregtech.api.gui.resources.SizedTextureArea; +import gregtech.api.gui.resources.TextureArea; +import gregtech.api.util.GTUtility; +import gregtech.api.util.Position; +import gregtech.api.util.Size; +import gregtech.api.util.function.BooleanConsumer; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.resources.I18n; +import net.minecraft.item.ItemStack; +import net.minecraft.network.PacketBuffer; +import net.minecraft.util.IStringSerializable; +import net.minecraft.util.math.MathHelper; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +import java.util.Arrays; +import java.util.List; +import java.util.function.*; + +public class ImageCycleButtonWidget extends Widget { + + protected TextureArea buttonTexture; + private int textColor = 0xFFFFFF; + private IntSupplier currentOptionSupplier; + private IntConsumer setOptionExecutor; + private int optionCount; + private final int RIGHT_MOUSE = 1; + protected int currentOption; + protected String tooltipHoverString; + protected long hoverStartTime = -1L; + protected boolean isMouseHovered; + + public ImageCycleButtonWidget(int xPosition, int yPosition, int width, int height, TextureArea buttonTexture, int optionCount, IntSupplier currentOptionSupplier, IntConsumer setOptionExecutor) { + super(new Position(xPosition, yPosition), new Size(width, height)); + this.buttonTexture = buttonTexture; + this.currentOptionSupplier = currentOptionSupplier; + this.setOptionExecutor = setOptionExecutor; + this.optionCount = optionCount; + } + + + public ImageCycleButtonWidget(int xPosition, int yPosition, int width, int height, TextureArea buttonTexture, int optionCount, BooleanSupplier supplier, BooleanConsumer updater) { + super(new Position(xPosition, yPosition), new Size(width, height)); + this.buttonTexture = buttonTexture; + this.currentOptionSupplier = () -> supplier.getAsBoolean() ? 1 : 0; + this.setOptionExecutor = (value) -> updater.apply(value >= 1); + this.optionCount = optionCount; + } + + public ImageCycleButtonWidget setTooltipHoverString(String hoverString) { + this.tooltipHoverString = hoverString; + return this; + } + + public ImageCycleButtonWidget setButtonTexture(TextureArea texture) { + this.buttonTexture = texture; + return this; + } + + public ImageCycleButtonWidget setTextColor(int textColor) { + this.textColor = textColor; + return this; + } + + @Override + @SideOnly(Side.CLIENT) + public void drawInBackground(int mouseX, int mouseY, IRenderContext context) { + Position pos = getPosition(); + Size size = getSize(); + if (buttonTexture instanceof SizedTextureArea) { + ((SizedTextureArea) buttonTexture).drawHorizontalCutSubArea(pos.x, pos.y, size.width, size.height, (float)currentOption / optionCount, (float)1 / optionCount); + } else { + buttonTexture.drawSubArea(pos.x, pos.y, size.width, size.height, 0.0, (float)currentOption / optionCount, 1.0, (float)1 / optionCount); + } + } + + @Override + public void drawInForeground(int mouseX, int mouseY) { + boolean isHovered = isMouseOverElement(mouseX, mouseY); + boolean wasHovered = isMouseHovered; + if (isHovered && !wasHovered) { + this.isMouseHovered = true; + this.hoverStartTime = System.currentTimeMillis(); + } else if (!isHovered && wasHovered) { + this.isMouseHovered = false; + this.hoverStartTime = 0L; + } else if (isHovered) { + long timeSinceHover = System.currentTimeMillis() - hoverStartTime; + if (timeSinceHover > 1000L && tooltipHoverString != null) { + List hoverList = Arrays.asList(I18n.format(tooltipHoverString).split("/n")); + drawHoveringText(ItemStack.EMPTY, hoverList, 300, mouseX, mouseY); + } + } + } + + @Override + public void detectAndSendChanges() { + super.detectAndSendChanges(); + if (currentOptionSupplier.getAsInt() != currentOption) { + this.currentOption = currentOptionSupplier.getAsInt(); + writeUpdateInfo(1, buf -> buf.writeVarInt(currentOption)); + } + } + + @Override + public void readUpdateInfo(int id, PacketBuffer buffer) { + super.readUpdateInfo(id, buffer); + if (id == 1) { + this.currentOption = buffer.readVarInt(); + } + } + + @Override + @SideOnly(Side.CLIENT) + public boolean mouseClicked(int mouseX, int mouseY, int button) { + super.mouseClicked(mouseX, mouseY, button); + if (isMouseOverElement(mouseX, mouseY)) { + //Allow only the RMB to reverse cycle + if(button == RIGHT_MOUSE) { + //Wrap from the first option to the last if needed + this.currentOption = currentOption == 0 ? optionCount - 1 : currentOption - 1; + } + else { + this.currentOption = (currentOption + 1) % optionCount; + } + writeClientAction(1, buf -> buf.writeVarInt(currentOption)); + playButtonClickSound(); + return true; + } + return false; + } + + + @Override + public void handleClientAction(int id, PacketBuffer buffer) { + super.handleClientAction(id, buffer); + if (id == 1) { + this.currentOption = MathHelper.clamp(buffer.readVarInt(), 0, optionCount); + setOptionExecutor.accept(currentOption); + } + } + +} diff --git a/src/main/java/gregtech/api/gui/widgets/TextFieldWidget.java b/src/main/java/gregtech/api/gui/widgets/TextFieldWidget.java index 2ee4448526e..666e5e62ca4 100644 --- a/src/main/java/gregtech/api/gui/widgets/TextFieldWidget.java +++ b/src/main/java/gregtech/api/gui/widgets/TextFieldWidget.java @@ -22,12 +22,27 @@ public class TextFieldWidget extends Widget { protected GuiTextField textField; protected int maxStringLength = 32; + protected int fontSize = 9; protected Predicate textValidator; protected final Supplier textSupplier; protected final Consumer textResponder; protected String currentString; public TextFieldWidget(int xPosition, int yPosition, int width, int height, boolean enableBackground, Supplier textSupplier, Consumer textResponder) { + super(new Position(xPosition, yPosition), new Size(width, height)); + if (isClientSide()) { + FontRenderer fontRenderer = Minecraft.getMinecraft().fontRenderer; + this.textField = new GuiTextField(0, fontRenderer, xPosition, yPosition, width, height); + this.textField.setCanLoseFocus(true); + this.textField.setEnableBackgroundDrawing(enableBackground); + this.textField.setMaxStringLength(this.maxStringLength); + this.textField.setGuiResponder(MCGuiUtil.createTextFieldResponder(this::onTextChanged)); + } + this.textSupplier = textSupplier; + this.textResponder = textResponder; + } + + public TextFieldWidget(int xPosition, int yPosition, int width, int height, boolean enableBackground, Supplier textSupplier, Consumer textResponder, int maxStringLength, int fontSize) { super(new Position(xPosition, yPosition), new Size(width, height)); if (isClientSide()) { FontRenderer fontRenderer = Minecraft.getMinecraft().fontRenderer; @@ -35,6 +50,8 @@ public TextFieldWidget(int xPosition, int yPosition, int width, int height, bool this.textField.setCanLoseFocus(true); this.textField.setEnableBackgroundDrawing(enableBackground); this.textField.setMaxStringLength(maxStringLength); + this.maxStringLength = maxStringLength; + this.fontSize = fontSize; this.textField.setGuiResponder(MCGuiUtil.createTextFieldResponder(this::onTextChanged)); } this.textSupplier = textSupplier; @@ -64,7 +81,10 @@ protected void onSizeUpdate() { @Override public void drawInBackground(int mouseX, int mouseY, IRenderContext context) { super.drawInBackground(mouseX, mouseY, context); + FontRenderer fontRenderer = Minecraft.getMinecraft().fontRenderer; + fontRenderer.FONT_HEIGHT = fontSize; this.textField.drawTextBox(); + fontRenderer.FONT_HEIGHT = 9; } @Override diff --git a/src/main/java/gregtech/common/blocks/clipboard/BlockClipboard.java b/src/main/java/gregtech/common/blocks/clipboard/BlockClipboard.java new file mode 100644 index 00000000000..a6f75b7b65a --- /dev/null +++ b/src/main/java/gregtech/common/blocks/clipboard/BlockClipboard.java @@ -0,0 +1,196 @@ +package gregtech.common.blocks.clipboard; +/* + +import net.minecraft.util.math.AxisAlignedBB; + +public class BlockClipboard extends BiblioBlock { + public static final String name = "Clipboard"; + + public static final BlockClipboard instance = new BlockClipboard(); + + public BlockClipboard() { + super(Material.WOOD, SoundType.WOOD, null, "Clipboard"); + } + + public List getDrops(IBlockAccess world, BlockPos pos, IBlockState state, int fortune) { + return new ArrayList<>(); + } + + public boolean onBlockActivatedCustomCommands(World world, BlockPos pos, IBlockState state, EntityPlayer player, EnumFacing face, float hitX, float hitY, float hitZ) { + if (player.isSneaking() && !world.isRemote) { + dropStackInSlot(world, pos, 0, pos); + world.setBlockToAir(pos); + return true; + } + if (!player.isSneaking() && world.isRemote) { + TileEntity tile = world.getTileEntity(pos); + if (tile != null && tile instanceof MetaTileEntityClipboard) { + MetaTileEntityClipboard clipboard = (MetaTileEntityClipboard)tile; + int updatePos = getSelectionPointFromFace(face, hitX, hitY, hitZ); + ByteBuf buffer = Unpooled.buffer(); + buffer.writeInt(pos.getX()); + buffer.writeInt(pos.getY()); + buffer.writeInt(pos.getZ()); + buffer.writeInt(updatePos); + BiblioCraft.ch_BiblioClipboard.sendToServer(new FMLProxyPacket(new PacketBuffer(buffer), "BiblioClipboard")); + return true; + } + } + return false; + } + + private int getSelectionPointFromFace(EnumFacing face, float hitx, float hity, float hitz) { + switch (face) { + case NORTH: + return getSelectionPoint(1.0F - hitx, 1.0F - hity); + case SOUTH: + return getSelectionPoint(hitx, 1.0F - hity); + case WEST: + return getSelectionPoint(hitz, 1.0F - hity); + case EAST: + return getSelectionPoint(1.0F - hitz, 1.0F - hity); + } + return -1; + } + + private int getSelectionPoint(float x, float y) { + if (x > 0.21F && x < 0.272F) { + float spacing = 0.0655F; + for (int i = 0; i < 9; i++) { + if (y > 0.23D + (i * spacing) && y < 0.285F + i * spacing) + return i; + } + } + if (y > 0.83D && y < 0.868F) { + if (x > 0.296F && x < 0.387F) + return 10; + if (x > 0.599F && x < 0.843F) + return 11; + } + return -1; + } + + public TileEntity createNewTileEntity(World worldIn, int meta) { + return (TileEntity)new MetaTileEntityClipboard(); + } + + public List getModelParts(BiblioTileEntity tile) { + List modelParts = new ArrayList<>(); + modelParts.add("Clipboard"); + if (tile instanceof MetaTileEntityClipboard) { + MetaTileEntityClipboard clipboard = (MetaTileEntityClipboard)tile; + clipboard.getNBTData(); + switch (clipboard.button0state) { + case 1: + modelParts.add("box1c"); + break; + case 2: + modelParts.add("box1x"); + break; + } + switch (clipboard.button1state) { + case 1: + modelParts.add("box2c"); + break; + case 2: + modelParts.add("box2x"); + break; + } + switch (clipboard.button2state) { + case 1: + modelParts.add("box3c"); + break; + case 2: + modelParts.add("box3x"); + break; + } + switch (clipboard.button3state) { + case 1: + modelParts.add("box4c"); + break; + case 2: + modelParts.add("box4x"); + break; + } + switch (clipboard.button4state) { + case 1: + modelParts.add("box5c"); + break; + case 2: + modelParts.add("box5x"); + break; + } + switch (clipboard.button5state) { + case 1: + modelParts.add("box6c"); + break; + case 2: + modelParts.add("box6x"); + break; + } + switch (clipboard.button6state) { + case 1: + modelParts.add("box7c"); + break; + case 2: + modelParts.add("box7x"); + break; + } + switch (clipboard.button7state) { + case 1: + modelParts.add("box8c"); + break; + case 2: + modelParts.add("box8x"); + break; + } + } + return modelParts; + } + + public void additionalPlacementCommands(BiblioTileEntity biblioTile, EntityLivingBase player) {} + + public ItemStack getPickBlockExtras(ItemStack stack, World world, BlockPos pos) { + return stack; + } + + public ExtendedBlockState getExtendedBlockStateAlternate(ExtendedBlockState state) { + return state; + } + + public IExtendedBlockState getIExtendedBlockStateAlternate(BiblioTileEntity biblioTile, IExtendedBlockState state) { + return state; + } + + public TRSRTransformation getAdditionalTransforms(TRSRTransformation transform, BiblioTileEntity tile) { + return transform; + } + + public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess blockAccess, BlockPos pos) { + AxisAlignedBB output = getBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F); + TileEntity tile = blockAccess.getTileEntity(pos); + if (tile != null && tile instanceof MetaTileEntityClipboard) { + MetaTileEntityClipboard clipboard = (MetaTileEntityClipboard)tile; + switch (clipboard.getAngle()) { + case SOUTH: + output = getBlockBounds(0.97F, 0.08F, 0.15F, 1.0F, 0.92F, 0.85F); + break; + case WEST: + output = getBlockBounds(0.15F, 0.08F, 0.97F, 0.85F, 0.92F, 1.0F); + break; + case NORTH: + output = getBlockBounds(0.0F, 0.08F, 0.15F, 0.03F, 0.92F, 0.85F); + break; + case EAST: + output = getBlockBounds(0.15F, 0.08F, 0.0F, 0.85F, 0.92F, 0.03F); + break; + } + } + return output; + } + + public IBlockState getFinalBlockstate(IBlockState state, IBlockState newState) { + return newState; + } +} +*/ diff --git a/src/main/java/gregtech/common/blocks/clipboard/MetaTileEntityClipboard.java b/src/main/java/gregtech/common/blocks/clipboard/MetaTileEntityClipboard.java new file mode 100644 index 00000000000..a700f1bc389 --- /dev/null +++ b/src/main/java/gregtech/common/blocks/clipboard/MetaTileEntityClipboard.java @@ -0,0 +1,289 @@ +package gregtech.common.blocks.clipboard; + +import gregtech.api.gui.ModularUI; +import gregtech.api.metatileentity.MetaTileEntity; +import gregtech.api.metatileentity.MetaTileEntityHolder; +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.ResourceLocation; +import net.minecraft.util.text.ITextComponent; +import net.minecraft.util.text.TextComponentString; +import net.minecraftforge.items.IItemHandler; + +public class MetaTileEntityClipboard extends MetaTileEntity { + public int button0state = 0; + + public int button1state = 0; + + public int button2state = 0; + + public int button3state = 0; + + public int button4state = 0; + + public int button5state = 0; + + public int button6state = 0; + + public int button7state = 0; + + public String button0text = " "; + + public String button1text = " "; + + public String button2text = " "; + + public String button3text = " "; + + public String button4text = " "; + + public String button5text = " "; + + public String button6text = " "; + + public String button7text = " "; + + public String titletext = " "; + + public int currentPage = 1; + + public int totalPages = 1; + + public MetaTileEntityClipboard(ResourceLocation metaTileEntityId) { + super(metaTileEntityId); + } + + public void updateClipboardFromPlayerSelection(int selection) { + if (selection >= 0 && selection <= 8) { + checkCheckBox(selection); + } else if (selection == 10) { + changePage(false); + } else if (selection == 11) { + changePage(true); + } + getWorld().notifyBlockUpdate(getPos(), getWorld().getBlockState(getPos()), getWorld().getBlockState(getPos()), 3); + } + + public void checkCheckBox(int box) { + switch (box) { + case 0: + if (this.button0state >= 2) { + this.button0state = 0; + break; + } + this.button0state++; + break; + case 1: + if (this.button1state >= 2) { + this.button1state = 0; + break; + } + this.button1state++; + break; + case 2: + if (this.button2state >= 2) { + this.button2state = 0; + break; + } + this.button2state++; + break; + case 3: + if (this.button3state >= 2) { + this.button3state = 0; + break; + } + this.button3state++; + break; + case 4: + if (this.button4state >= 2) { + this.button4state = 0; + break; + } + this.button4state++; + break; + case 5: + if (this.button5state >= 2) { + this.button5state = 0; + break; + } + this.button5state++; + break; + case 6: + if (this.button6state >= 2) { + this.button6state = 0; + break; + } + this.button6state++; + break; + case 7: + if (this.button7state >= 2) { + this.button7state = 0; + break; + } + this.button7state++; + break; + } + ItemStack clipStack = itemInventory.getStackInSlot(0); + if (clipStack != ItemStack.EMPTY) { + NBTTagCompound cliptags = clipStack.getTagCompound(); + if (cliptags != null) { + String pagenum = "page" + cliptags.getInteger("currentPage"); + NBTTagCompound pagetag = cliptags.getCompoundTag(pagenum); + if (pagetag != null) { + int[] taskstat = pagetag.getIntArray("taskStates"); + taskstat[0] = this.button0state; + taskstat[1] = this.button1state; + taskstat[2] = this.button2state; + taskstat[3] = this.button3state; + taskstat[4] = this.button4state; + taskstat[5] = this.button5state; + taskstat[6] = this.button6state; + taskstat[7] = this.button7state; + pagetag.setIntArray("taskStates", taskstat); + clipStack.setTagCompound(cliptags); + itemInventory.extractItem(0, 1, false); + itemInventory.insertItem(0, clipStack, false); + getNBTData(); + getWorld().notifyBlockUpdate(getPos(), getWorld().getBlockState(getPos()), getWorld().getBlockState(getPos()), 3); + } + } + } + } + + + public void changePage(boolean nextPage) { + if (nextPage) { + if (this.currentPage < this.totalPages) + this.currentPage++; + } else if (this.currentPage > 1) { + this.currentPage--; + } + ItemStack clipStack = itemInventory.getStackInSlot(0); + if (clipStack != ItemStack.EMPTY) { + NBTTagCompound cliptags = clipStack.getTagCompound(); + if (cliptags != null) { + String pagenum = "page" + this.currentPage; + NBTTagCompound pagetag = cliptags.getCompoundTag(pagenum); + if (pagetag != null) { + cliptags.setInteger("currentPage", this.currentPage); + clipStack.setTagCompound(cliptags); + itemInventory.extractItem(0, 1, false); + itemInventory.insertItem(0, clipStack, false); + getNBTData(); + getWorld().notifyBlockUpdate(getPos(), getWorld().getBlockState(getPos()), getWorld().getBlockState(getPos()), 3); + } + } + } + } + + public void getNBTData() { + ItemStack clipStack = itemInventory.getStackInSlot(0); + if (clipStack != ItemStack.EMPTY) { + NBTTagCompound cliptags = clipStack.getTagCompound(); + if (cliptags != null) { + this.currentPage = cliptags.getInteger("currentPage"); + this.totalPages = cliptags.getInteger("totalPages"); + String pagenum = "page" + this.currentPage; + NBTTagCompound pagetag = cliptags.getCompoundTag(pagenum); + if (pagetag != null) { + int[] taskstat = pagetag.getIntArray("taskStates"); + if (taskstat.length > 0) { + this.button0state = taskstat[0]; + this.button1state = taskstat[1]; + this.button2state = taskstat[2]; + this.button3state = taskstat[3]; + this.button4state = taskstat[4]; + this.button5state = taskstat[5]; + this.button6state = taskstat[6]; + this.button7state = taskstat[7]; + } + NBTTagCompound tasks = pagetag.getCompoundTag("tasks"); + this.button0text = tasks.getString("task1"); + this.button1text = tasks.getString("task2"); + this.button2text = tasks.getString("task3"); + this.button3text = tasks.getString("task4"); + this.button4text = tasks.getString("task5"); + this.button5text = tasks.getString("task6"); + this.button6text = tasks.getString("task7"); + this.button7text = tasks.getString("task8"); + this.titletext = pagetag.getString("title"); + } + } + } + } + + public int getInventoryStackLimit() { + return 1; + } + + public boolean isItemValidForSlot(int slot, ItemStack itemstack) { + return false; + } + + public String getName() { + return "Clipboard"; + } + + public void setInventorySlotContentsAdditionalCommands(int slot, ItemStack stack) {} + + public void loadCustomNBTData(NBTTagCompound nbt) { + this.button0state = nbt.getInteger("button0state"); + this.button1state = nbt.getInteger("button1state"); + this.button2state = nbt.getInteger("button2state"); + this.button3state = nbt.getInteger("button3state"); + this.button4state = nbt.getInteger("button4state"); + this.button5state = nbt.getInteger("button5state"); + this.button6state = nbt.getInteger("button6state"); + this.button7state = nbt.getInteger("button7state"); + this.button0text = nbt.getString("button0text"); + this.button1text = nbt.getString("button1text"); + this.button2text = nbt.getString("button2text"); + this.button3text = nbt.getString("button3text"); + this.button4text = nbt.getString("button4text"); + this.button5text = nbt.getString("button5text"); + this.button6text = nbt.getString("button6text"); + this.button7text = nbt.getString("button7text"); + this.currentPage = nbt.getInteger("currentPage"); + this.totalPages = nbt.getInteger("totalPages"); + this.titletext = nbt.getString("titletext"); + } + + public NBTTagCompound writeCustomNBTData(NBTTagCompound nbt) { + nbt.setInteger("button0state", this.button0state); + nbt.setInteger("button1state", this.button1state); + nbt.setInteger("button2state", this.button2state); + nbt.setInteger("button3state", this.button3state); + nbt.setInteger("button4state", this.button4state); + nbt.setInteger("button5state", this.button5state); + nbt.setInteger("button6state", this.button6state); + nbt.setInteger("button7state", this.button7state); + nbt.setString("button0text", this.button0text); + nbt.setString("button1text", this.button1text); + nbt.setString("button2text", this.button2text); + nbt.setString("button3text", this.button3text); + nbt.setString("button4text", this.button4text); + nbt.setString("button5text", this.button5text); + nbt.setString("button6text", this.button6text); + nbt.setString("button7text", this.button7text); + nbt.setInteger("currentPage", this.currentPage); + nbt.setInteger("totalPages", this.totalPages); + nbt.setString("titletext", this.titletext); + return nbt; + } + + public ITextComponent getDisplayName() { + return (ITextComponent)new TextComponentString(getName()); + } + + @Override + public MetaTileEntity createMetaTileEntity(MetaTileEntityHolder holder) { + return null; + } + + @Override + protected ModularUI createUI(EntityPlayer entityPlayer) { + return null; + } +} diff --git a/src/main/java/gregtech/common/blocks/models/ModelCache.java b/src/main/java/gregtech/common/blocks/models/ModelCache.java new file mode 100644 index 00000000000..f74b7d84681 --- /dev/null +++ b/src/main/java/gregtech/common/blocks/models/ModelCache.java @@ -0,0 +1,52 @@ +package gregtech.common.blocks.models; + +import java.util.ArrayList; +import net.minecraft.client.renderer.block.model.IBakedModel; + +public class ModelCache { + private ArrayList models = new ArrayList<>(); + + private IBakedModel currentMatch = null; + + public void addToCache(IBakedModel model, String name) { + ModelCachePackage pack = new ModelCachePackage(model, name); + this.models.add(pack); + } + + public boolean hasModel(String name) { + boolean output = false; + for (int i = 0; i < this.models.size(); i++) { + ModelCachePackage pack = this.models.get(i); + if (pack.getTextureName().contentEquals(name)) { + output = true; + this.currentMatch = pack.getModel(); + break; + } + } + return output; + } + + public IBakedModel getCurrentMatch() { + return this.currentMatch; + } + + public static class ModelCachePackage { + private IBakedModel model; + + private String name; + + public ModelCachePackage(IBakedModel modelIn, String nameIn) { + this.model = modelIn; + this.name = nameIn; + } + + public IBakedModel getModel() { + return this.model; + } + + public String getTextureName() { + return this.name; + } + } + +} diff --git a/src/main/java/gregtech/common/blocks/models/ModelClipboard.java b/src/main/java/gregtech/common/blocks/models/ModelClipboard.java new file mode 100644 index 00000000000..d5adc23da94 --- /dev/null +++ b/src/main/java/gregtech/common/blocks/models/ModelClipboard.java @@ -0,0 +1,210 @@ +package gregtech.common.blocks.models; + + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Lists; +import net.minecraft.block.state.IBlockState; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.renderer.block.model.*; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.ResourceLocation; +import net.minecraft.world.World; +import net.minecraftforge.client.model.IModel; +import net.minecraftforge.client.model.ModelLoaderRegistry; +import net.minecraftforge.client.model.obj.OBJModel; +import net.minecraftforge.common.model.IModelState; +import net.minecraftforge.common.model.TRSRTransformation; +import net.minecraftforge.common.property.IExtendedBlockState; +import net.minecraftforge.common.property.IUnlistedProperty; +import org.apache.commons.lang3.tuple.Pair; + +import javax.annotation.Nonnull; +import javax.vecmath.Matrix4f; +import javax.vecmath.Quat4f; +import javax.vecmath.Vector3f; +import java.util.ArrayList; +import java.util.List; +import java.util.function.Function; + +public class ModelClipboard implements IBakedModel { + private IModel model = null; + + private IBakedModel baseModel; + + public static final ModelResourceLocation modelResourceLocation = new ModelResourceLocation("bibliocraft:Clipboard"); + + public static final ModelResourceLocation clipboardBasicModel = new ModelResourceLocation("bibliocraft:clipboardsimple"); + + private CustomItemOverrideList overrides = new CustomItemOverrideList(); + + public IBakedModel wrapper; + + private FontRenderer textRender; + + private ModelCache cache; + + private boolean gotOBJ = false; + + protected Function textureGetter; + + private void getModel(IBlockState state, ItemStack stack) { + if (this.model == null || (this.model != null && !this.model.toString().contains("obj.OBJModel"))) + try { + this.model = ModelLoaderRegistry.getModel(new ResourceLocation("bibliocraft:block/clipboard.obj")); + this.model = this.model.process(ImmutableMap.of("flip-v", "true")); + this.gotOBJ = true; + } catch (Exception e) { + this.model = ModelLoaderRegistry.getMissingModel(); + this.gotOBJ = false; + } + OBJModel.OBJState modelState = new OBJModel.OBJState(Lists.newArrayList("OBJModel.Group.All.Key"), true); + if (state != null && state instanceof IExtendedBlockState) { + IExtendedBlockState exState = (IExtendedBlockState) state; + if (exState.getUnlistedNames().contains(OBJModel.OBJProperty.INSTANCE)) { + modelState = exState.getValue(OBJModel.OBJProperty.INSTANCE); + IBakedModel bakedModel = this.model.bake(modelState, DefaultVertexFormats.ITEM, this.textureGetter); + this.baseModel = bakedModel; + } + if (modelState == null) + return; + } + if (state == null /*&& stack.getItem() == ItemClipboard.instance*/) { + String cacheName = "clipboard" + getModelPartsNumberString(stack); + if (this.cache.hasModel(cacheName)) { + this.baseModel = this.cache.getCurrentMatch(); + } else { + modelState = new OBJModel.OBJState(getModelParts(stack), true); + IBakedModel bakedModel = this.model.bake(new OBJModel.OBJState(getModelParts(stack), true), DefaultVertexFormats.ITEM, (Function) this.textureGetter); + if (this.gotOBJ) + this.cache.addToCache(bakedModel, cacheName); + this.baseModel = bakedModel; + } + } + } + + private String getModelPartsNumberString(ItemStack stack) { + NBTTagCompound tags = stack.getTagCompound(); + String value = ""; + if (tags != null) { + int currentPage = tags.getInteger("currentPage"); + int totalPages = tags.getInteger("totalPages"); + String pagenum = "page" + currentPage; + NBTTagCompound pagetag = tags.getCompoundTag(pagenum); + if (pagetag != null) { + int[] states = pagetag.getIntArray("taskStates"); + if (states != null && states.length == 9) + for (int i = 0; i < states.length; i++) + value = value + states[i]; + } + } + return value; + } + + public List getModelParts(ItemStack stack) { + List modelParts = new ArrayList<>(); + NBTTagCompound tags = stack.getTagCompound(); + if (tags != null) { + int currentPage = tags.getInteger("currentPage"); + int totalPages = tags.getInteger("totalPages"); + String pagenum = "page" + currentPage; + NBTTagCompound pagetag = tags.getCompoundTag(pagenum); + if (pagetag != null) { + int[] states = pagetag.getIntArray("taskStates"); + if (states != null && states.length == 9) { + for (int i = 0; i < 9; i++) { + modelParts.add(states[i] == 1 ? String.format("box%sc", i) : String.format("box%sx", i)); + } // Look at that, Nuchaz. 70 lines reduced into one ternary. What were you thinking?????? + } + } + } + modelParts.add("Clipboard"); + return modelParts; + } + + public ModelClipboard() { + this.textureGetter = location -> Minecraft.getMinecraft().getTextureMapBlocks().getAtlasSprite("bibliocraft:models/clipboard"); + this.textRender = (Minecraft.getMinecraft()).fontRenderer; + this.wrapper = this; + this.cache = new ModelCache(); + } + + public boolean isAmbientOcclusion() { + return false; + } + + public boolean isGui3d() { + return false; + } + + public boolean isBuiltInRenderer() { + return false; + } + + public TextureAtlasSprite getParticleTexture() { + if (this.baseModel.getParticleTexture() == null) + return Minecraft.getMinecraft().getTextureMapBlocks().getAtlasSprite("minecraft:blocks/planks_oak"); + return this.baseModel.getParticleTexture(); + } + + public ItemCameraTransforms getItemCameraTransforms() { + return ItemCameraTransforms.DEFAULT; + } + + public Pair handlePerspective(ItemCameraTransforms.TransformType cameraTransformType) { + TRSRTransformation transform = new TRSRTransformation(new Vector3f(0.0F, 0.0F, 0.0F), new Quat4f(0.0F, 0.0F, 0.0F, 1.0F), new Vector3f(1.0F, 1.0F, 1.0F), new Quat4f(0.0F, 0.0F, 0.0F, 1.0F)); + switch (cameraTransformType) { + case FIRST_PERSON_RIGHT_HAND: + transform = new TRSRTransformation(new Vector3f(-0.05F, 0.25F, 0.3F), new Quat4f(0.0F, -1.0F, 0.0F, 1.0F), new Vector3f(0.5F, 0.5F, 0.5F), new Quat4f(0.0F, 0.0F, 0.0F, 1.0F)); + break; + case FIRST_PERSON_LEFT_HAND: + transform = new TRSRTransformation(new Vector3f(0.0F, 0.25F, 0.3F), new Quat4f(0.0F, 1.0F, 0.0F, 1.0F), new Vector3f(0.5F, 0.5F, 0.5F), new Quat4f(0.0F, 0.0F, 0.0F, 1.0F)); + break; + case THIRD_PERSON_RIGHT_HAND: + transform = new TRSRTransformation(new Vector3f(0.0F, 0.2F, 0.4F), new Quat4f(0.0F, -1.0F, 0.0F, 1.0F), new Vector3f(0.75F, 0.75F, 0.75F), new Quat4f(0.0F, 0.0F, 0.0F, 1.0F)); + break; + case THIRD_PERSON_LEFT_HAND: + transform = new TRSRTransformation(new Vector3f(0.0F, 0.2F, 0.4F), new Quat4f(0.0F, 1.0F, 0.0F, 1.0F), new Vector3f(0.75F, 0.75F, 0.75F), new Quat4f(0.0F, 0.0F, 0.0F, 1.0F)); + break; + case GUI: + transform = new TRSRTransformation(new Vector3f(0.0F, 0.0F, 0.0F), new Quat4f(0.0F, -1.0F, 0.0F, 1.0F), new Vector3f(1.0F, 1.0F, 1.0F), new Quat4f(0.0F, 0.0F, 0.0F, 1.0F)); + break; + case GROUND: + transform = new TRSRTransformation(new Vector3f(0.35F, 0.15F, 0.0F), new Quat4f(0.0F, 0.0F, 0.0F, 1.0F), new Vector3f(0.75F, 0.75F, 0.75F), new Quat4f(0.0F, 0.0F, 0.0F, 1.0F)); + break; + } + return Pair.of(this, transform.getMatrix()); + } + + public List getQuads(IBlockState state, EnumFacing side, long rand) { + getModel(state, ItemStack.EMPTY); + try { + List q = this.baseModel.getQuads(state, side, rand); + return q; + } catch (NullPointerException e) { + return new ArrayList<>(); + } + } + + public ItemOverrideList getOverrides() { + return this.overrides; + } + + private class CustomItemOverrideList extends ItemOverrideList { + private CustomItemOverrideList() { + super(ImmutableList.of()); + } + + @Nonnull + public IBakedModel handleItemState(@Nonnull IBakedModel originalModel, ItemStack stack, @Nonnull World world, @Nonnull EntityLivingBase entity) { + ModelClipboard.this.getModel(null, stack); + return ModelClipboard.this.wrapper; + } + } +} diff --git a/src/main/java/gregtech/common/items/MetaItem2.java b/src/main/java/gregtech/common/items/MetaItem2.java index d2b588ed6f5..da5e29129cc 100644 --- a/src/main/java/gregtech/common/items/MetaItem2.java +++ b/src/main/java/gregtech/common/items/MetaItem2.java @@ -15,10 +15,7 @@ import gregtech.api.unification.ore.OrePrefix; import gregtech.api.util.RandomPotionEffect; import gregtech.common.ConfigHolder; -import gregtech.common.items.behaviors.FacadeItem; -import gregtech.common.items.behaviors.ScannerBehavior; -import gregtech.common.items.behaviors.NanoSaberBehavior; -import gregtech.common.items.behaviors.TurbineRotorBehavior; +import gregtech.common.items.behaviors.*; import net.minecraft.init.Blocks; import net.minecraft.init.Items; import net.minecraft.init.MobEffects; @@ -104,6 +101,7 @@ public void registerSubItems() { ENERGY_FIELD_PROJECTOR = addItem(579, "energy_field_projector").addComponents(ElectricStats.createElectricItem(16000000L, GTValues.EV)).setMaxStackSize(1); SCANNER = addItem(580, "scanner").addComponents(ElectricStats.createElectricItem(200_000L, GTValues.LV), new ScannerBehavior(50)); + CLIPBOARD = addItem(540, "clipboard").addComponents(new ClipboardBehaviour()); INGOT_MIXED_METAL = addItem(432, "ingot.mixed_metal"); ADVANCED_ALLOY_PLATE = addItem(433, "plate.advanced_alloy"); diff --git a/src/main/java/gregtech/common/items/MetaItems.java b/src/main/java/gregtech/common/items/MetaItems.java index e65b53d8a66..324a46a9f5f 100644 --- a/src/main/java/gregtech/common/items/MetaItems.java +++ b/src/main/java/gregtech/common/items/MetaItems.java @@ -469,6 +469,8 @@ private MetaItems() { public static MetaItem.MetaValueItem BIO_CHAFF; + public static MetaItem.MetaValueItem CLIPBOARD; + public static void init() { MetaItem1 first = new MetaItem1(); first.setRegistryName("meta_item_1"); diff --git a/src/main/java/gregtech/common/items/behaviors/ClipboardBehaviour.java b/src/main/java/gregtech/common/items/behaviors/ClipboardBehaviour.java new file mode 100644 index 00000000000..69ab3823044 --- /dev/null +++ b/src/main/java/gregtech/common/items/behaviors/ClipboardBehaviour.java @@ -0,0 +1,127 @@ +package gregtech.common.items.behaviors; + +import gregtech.api.gui.GuiTextures; +import gregtech.api.gui.ModularUI; +import gregtech.api.gui.widgets.ImageCycleButtonWidget; +import gregtech.api.gui.widgets.TextFieldWidget; +import gregtech.api.gui.widgets.ToggleButtonWidget; +import gregtech.api.items.gui.ItemUIFactory; +import gregtech.api.items.gui.PlayerInventoryHolder; +import gregtech.api.items.metaitem.stats.IItemBehaviour; +import gregtech.common.items.MetaItems; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.ActionResult; +import net.minecraft.util.EnumActionResult; +import net.minecraft.util.EnumHand; +import net.minecraft.world.World; + +public class ClipboardBehaviour implements IItemBehaviour, ItemUIFactory { + public static final int MAX_PAGES = 25; + + @Override + public ModularUI createUI(PlayerInventoryHolder holder, EntityPlayer entityPlayer) { + initNBT(holder.getCurrentItem()); + ModularUI.Builder builder = ModularUI.builder(GuiTextures.BACKGROUND, 170, 238); + for (int i = 0; i < 8; i++) { + int finalI = i; + builder.widget(new ImageCycleButtonWidget(5, 27 + 15 * i, 15, 15, GuiTextures.CLIPBOARD_CHECKBOX, 2, + () -> getButtonState(holder, finalI), (x) -> toggleButton(holder, finalI))); + builder.widget(new TextFieldWidget(21, 30 + 15 * i, 140, 10, true, + () -> getString(holder, finalI), (x) -> setString(holder, finalI, x), 23, 8) + .setValidator((x) -> true)); + } + + return builder.build(holder, entityPlayer); + } + + private static NBTTagCompound getPageCompound(ItemStack stack) { + if (!MetaItems.CLIPBOARD.isItemEqual(stack)) + throw new IllegalArgumentException("Given item stack is not a clipboard!"); + assert stack.getTagCompound() != null; + short pageNum = stack.getTagCompound().getShort("PageIndex"); + return stack.getTagCompound().getCompoundTag("Page" + pageNum); + } + + private static void setPageCompound(ItemStack stack, NBTTagCompound pageCompound) { + if (!MetaItems.CLIPBOARD.isItemEqual(stack)) + throw new IllegalArgumentException("Given item stack is not a clipboard!"); + assert stack.getTagCompound() != null; + short pageNum = stack.getTagCompound().getShort("PageIndex"); + stack.getTagCompound().setTag("Page" + pageNum, pageCompound); + } + + private static void initNBT(ItemStack stack) { + if (!MetaItems.CLIPBOARD.isItemEqual(stack)) + throw new IllegalArgumentException("Given item stack is not a clipboard!"); + NBTTagCompound tagCompound = stack.getTagCompound(); + if (tagCompound == null) { + tagCompound = new NBTTagCompound(); + tagCompound.setShort("PageIndex", (short) 0); + tagCompound.setShort("TotalPages", (short) 0); + + NBTTagCompound pageCompound = new NBTTagCompound(); + pageCompound.setShort("ButStat", (short) 0); + for(int i = 0; i < 8; i++) { + pageCompound.setString("Task" + i, ""); + } + + for(int i = 0; i < MAX_PAGES; i++) { + tagCompound.setTag("Page" + i, pageCompound.copy()); + } + + stack.setTagCompound(tagCompound); + } + } + + private static void toggleButton(PlayerInventoryHolder holder, int pos) { + ItemStack stack = holder.getCurrentItem(); + if (!MetaItems.CLIPBOARD.isItemEqual(stack)) + throw new IllegalArgumentException("Given item stack is not a clipboard!"); + NBTTagCompound tagCompound = getPageCompound(stack); + short buttonState; + buttonState = tagCompound.getByte("ButStat"); + buttonState ^= 1 << pos; + tagCompound.setShort("ButStat", buttonState); + setPageCompound(stack, tagCompound); + } + + private static boolean getButtonState(PlayerInventoryHolder holder, int pos) { + ItemStack stack = holder.getCurrentItem(); + if (!MetaItems.CLIPBOARD.isItemEqual(stack)) + throw new IllegalArgumentException("Given item stack is not a clipboard!"); + NBTTagCompound tagCompound = getPageCompound(stack); + short buttonState = 0; + buttonState = tagCompound.getShort("ButStat"); + return ((buttonState >> pos) & 1) != 0; + } + + private static void setString(PlayerInventoryHolder holder, int pos, String newString) { + ItemStack stack = holder.getCurrentItem(); + if (!MetaItems.CLIPBOARD.isItemEqual(stack)) + throw new IllegalArgumentException("Given item stack is not a clipboard!"); + NBTTagCompound tagCompound = getPageCompound(stack); + tagCompound.setString("Task" + pos, newString); + setPageCompound(stack, tagCompound); + } + + private static String getString(PlayerInventoryHolder holder, int pos) { + ItemStack stack = holder.getCurrentItem(); + if (!MetaItems.CLIPBOARD.isItemEqual(stack)) + throw new IllegalArgumentException("Given item stack is not a clipboard!"); + NBTTagCompound tagCompound = getPageCompound(stack); + return tagCompound.getString("Task" + pos); + } + + + @Override + public ActionResult onItemRightClick(World world, EntityPlayer player, EnumHand hand) { + ItemStack heldItem = player.getHeldItem(hand); + if (!world.isRemote) { + PlayerInventoryHolder holder = new PlayerInventoryHolder(player, hand); + holder.openUI(); + } + return ActionResult.newResult(EnumActionResult.SUCCESS, heldItem); + } +} diff --git a/src/main/java/gregtech/common/render/GTNativeTileEntityRenderer.java b/src/main/java/gregtech/common/render/GTNativeTileEntityRenderer.java new file mode 100644 index 00000000000..61fce13d597 --- /dev/null +++ b/src/main/java/gregtech/common/render/GTNativeTileEntityRenderer.java @@ -0,0 +1,316 @@ +package gregtech.common.render; + + +import com.google.common.collect.ImmutableMap; +import gregtech.api.items.metaitem.MetaItem; +import gregtech.api.items.metaitem.stats.IItemBehaviour; +import gregtech.common.items.behaviors.ClipboardBehaviour; +import gregtech.common.tileentities.EnumShiftPosition; +import gregtech.common.tileentities.EnumVertPosition; +import gregtech.common.tileentities.GTNativeTileEntity; +import net.minecraft.block.Block; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.renderer.BufferBuilder; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.RenderItem; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.block.model.IBakedModel; +import net.minecraft.client.renderer.block.model.ItemCameraTransforms; +import net.minecraft.client.renderer.entity.RenderManager; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.init.Items; +import net.minecraft.item.ItemStack; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.ResourceLocation; +import net.minecraft.world.storage.MapData; +import net.minecraftforge.client.model.Attributes; +import net.minecraftforge.client.model.IModel; +import net.minecraftforge.client.model.ModelLoaderRegistry; +import net.minecraftforge.client.model.obj.OBJModel; +import net.minecraftforge.common.model.IModelState; +import org.lwjgl.opengl.GL11; + +import java.util.List; +import java.util.function.Function; + +import static gregtech.common.tileentities.EnumShiftPosition.FULL_SHIFT; +import static gregtech.common.tileentities.EnumShiftPosition.HALF_SHIFT; + +public abstract class GTNativeTileEntityRenderer extends TileEntitySpecialRenderer { + private static final ResourceLocation RES_MAP_BACKGROUND = new ResourceLocation("textures/map/map_background.png"); + + Minecraft mc = Minecraft.getMinecraft(); + + private EnumFacing angle = EnumFacing.NORTH; + + private EnumVertPosition vert = EnumVertPosition.FLOOR; + + private EnumShiftPosition shift = EnumShiftPosition.NO_SHIFT; + + public float xshift; + + public float zshift; + + public int degreeAngle; + + public double globalX; + + public double globalY; + + public double globalZ; + + public Tessellator tessellator; + + public BufferBuilder worldRenderer; + + private RenderItem itemRenderer; + + private RenderManager renderManager = Minecraft.getMinecraft().getRenderManager(); + + public void render(TileEntity tileEntity, double x, double y, double z, float tick, int destroyStage, float what) { + this.globalX = x; + this.globalY = y; + this.globalZ = z; + GTNativeTileEntity tile = (GTNativeTileEntity)tileEntity; + if (tile != null) { + this.angle = tile.getAngle(); + this.vert = tile.getVertPosition(); + this.shift = tile.getShiftPosition(); + } + + this.xshift = 0.0F; + this.zshift = 0.0F; + if (this.itemRenderer == null || this.tessellator == null || this.worldRenderer == null) { + this.itemRenderer = Minecraft.getMinecraft().getRenderItem(); + this.tessellator = Tessellator.getInstance(); + this.worldRenderer = this.tessellator.getBuffer(); + } + + float halfShift = 0.25F; + float fullShift = 0.5F; + switch(this.angle) { + case SOUTH: + this.degreeAngle = 270; + this.xshift = 1.0F; + this.zshift = 0.0F; + if (this.shift == EnumShiftPosition.FULL_SHIFT) { + this.xshift += -fullShift; + this.zshift += 0.0F; + } + + if (this.shift == EnumShiftPosition.HALF_SHIFT) { + this.xshift += -halfShift; + this.zshift += 0.0F; + } + break; + case WEST: + this.degreeAngle = 180; + this.xshift = 1.0F; + this.zshift = 1.0F; + if (this.shift == EnumShiftPosition.FULL_SHIFT) { + this.xshift += 0.0F; + this.zshift += -fullShift; + } + + if (this.shift == EnumShiftPosition.HALF_SHIFT) { + this.xshift += 0.0F; + this.zshift += -halfShift; + } + break; + case NORTH: + this.degreeAngle = 90; + this.xshift = 0.0F; + this.zshift = 1.0F; + if (this.shift == EnumShiftPosition.FULL_SHIFT) { + this.xshift += fullShift; + this.zshift += 0.0F; + } + + if (this.shift == EnumShiftPosition.HALF_SHIFT) { + this.xshift += halfShift; + this.zshift += 0.0F; + } + break; + case EAST: + this.degreeAngle = 0; + this.xshift = 0.0F; + this.zshift = 0.0F; + if (this.shift == EnumShiftPosition.FULL_SHIFT) { + this.xshift += 0.0F; + this.zshift += fullShift; + } + + if (this.shift == EnumShiftPosition.HALF_SHIFT) { + this.xshift += 0.0F; + this.zshift += halfShift; + } + } + + render(tile, x, y, z, tick); + } + + public abstract void render(GTNativeTileEntity paramBiblioTileEntity, double paramDouble1, double paramDouble2, double paramDouble3, float paramFloat); + + public EnumFacing getAngle() { + return this.angle; + } + + public EnumVertPosition getVertPosition() { + return this.vert; + } + + public EnumShiftPosition getShiftPosition() { + return this.shift; + } + + public void renderSlotItem(ItemStack stack, double x, double y, double z, float scale) { + if (stack != null && stack != ItemStack.EMPTY) { + double tx; + switch(this.angle) { + case SOUTH: + tx = x; + x = -z; + z = tx; + break; + case WEST: + x *= -1.0D; + z *= -1.0D; + break; + case NORTH: + tx = x; + x = z; + z = -tx; + case EAST: + } + + GlStateManager.pushMatrix(); + GlStateManager.color(1.0F, 1.0F, 1.0F); + GlStateManager.translate(this.globalX + x + (double)this.xshift, this.globalY + y + 0.05D, this.globalZ + z + (double)this.zshift); + GlStateManager.rotate((float)this.degreeAngle + 180.0F, 0.0F, 1.0F, 0.0F); + this.additionalGLStuffForItemStack(); + Block testBlock = Block.getBlockFromItem(stack.getItem()); + + if (stack.getItem() instanceof MetaItem && + ((MetaItem)stack.getItem()).getItem((short) stack.getItemDamage()).getBehaviours() + .stream() + .filter(behaviour -> behaviour instanceof ClipboardBehaviour) + .count() == 1 ) { + GlStateManager.rotate(90.0F, 0.0F, 1.0F, 0.0F); + GlStateManager.translate(0.4D, 0.05D, 0.0D); + } + + if (testBlock == null) { + scale *= 0.7F; + GlStateManager.rotate(180.0F, 0.0F, 1.0F, 0.0F); + } + + GlStateManager.scale(scale, scale, scale); + this.itemRenderer.renderItem(stack, ItemCameraTransforms.TransformType.FIXED); + GlStateManager.popMatrix(); + } + } + + public void additionalGLStuffForItemStack() {} + + public void renderItemMap(ItemStack stack, float x, float y, float z, float scale) { + GlStateManager.pushMatrix(); + GlStateManager.translate(this.globalX + x, this.globalY + y + 1.0199999809265137D, this.globalZ + z); + GlStateManager.rotate(90.0F, 1.0F, 0.0F, 0.0F); + scale = (float)(scale * 0.0063D); + GlStateManager.scale(scale, scale, scale); + this.mc.getTextureManager().bindTexture(RES_MAP_BACKGROUND); + Tessellator tessellator = Tessellator.getInstance(); + BufferBuilder worldrenderer = tessellator.getBuffer(); + GL11.glNormal3f(0.0F, 0.0F, -1.0F); + worldrenderer.begin(7, DefaultVertexFormats.POSITION_TEX); + worldrenderer.pos(-7.0D, 135.0D, 0.0D).tex(0.0D, 1.0D).endVertex(); + worldrenderer.pos(135.0D, 135.0D, 0.0D).tex(1.0D, 1.0D).endVertex(); + worldrenderer.pos(135.0D, -7.0D, 0.0D).tex(1.0D, 0.0D).endVertex(); + worldrenderer.pos(-7.0D, -7.0D, 0.0D).tex(0.0D, 0.0D).endVertex(); + tessellator.draw(); + MapData mapdata = Items.FILLED_MAP.getMapData(stack, getWorld()); + if (mapdata != null) + this.mc.entityRenderer.getMapItemRenderer().renderMap(mapdata, false); + GlStateManager.popMatrix(); + } + + public IBakedModel initModel(List parts, ResourceLocation modelResource) { + IModel model = null; + try { + model = ModelLoaderRegistry.getModel(modelResource); + model = model.process(ImmutableMap.of("flip-v", "true")); + } catch (Exception e) { + model = ModelLoaderRegistry.getMissingModel(); + } + OBJModel.OBJState state = new OBJModel.OBJState(parts, true); + return model.bake(state, Attributes.DEFAULT_BAKED_FORMAT, this.getModelTexture); + } + + protected Function getModelTexture = new Function() { + public TextureAtlasSprite apply(ResourceLocation location) { + return Minecraft.getMinecraft().getTextureMapBlocks().getAtlasSprite(GTNativeTileEntityRenderer.this.getTextureString(location)); + } + }; + + public String getTextureString(ResourceLocation location) { + return location.toString(); + } + + public void renderText(String text, double xAdjust, double yAdjust, double zAdjust) { + FontRenderer fontRender = this.getFontRenderer(); + float offsetx = 0.0F; + float offsetz = 0.0F; + switch(this.getAngle()) { + case SOUTH: + offsetx = -0.0116F; + break; + case WEST: + offsetz = -0.0116F; + break; + case NORTH: + offsetx = 0.0116F; + break; + case EAST: + offsetz = 0.0116F; + } + GlStateManager.pushMatrix(); + GlStateManager.translate(this.globalX + 0.5D + offsetx, this.globalY, this.globalZ + 0.5D + offsetz); + switch (getAngle()) { + case SOUTH: + GlStateManager.rotate(180.0F, 0.0F, 1.0F, 0.0F); + break; + case WEST: + GlStateManager.rotate(90.0F, 0.0F, 1.0F, 0.0F); + case NORTH: + default: + break; + case EAST: + GlStateManager.rotate(-90.0F, 0.0F, 1.0F, 0.0F); + } + GlStateManager.translate(-0.5D + xAdjust, yAdjust, zAdjust); + GlStateManager.depthMask(false); + GlStateManager.scale(0.0045F, 0.0045F, 0.0045F); + GlStateManager.rotate(270.0F, 0.0F, 1.0F, 0.0F); + GlStateManager.rotate(180.0F, 0.0F, 0.0F, 1.0F); + switch (this.shift) { + case HALF_SHIFT: + GlStateManager.translate(0.0D, 0.0D, -95.0D); + break; + case FULL_SHIFT: + GlStateManager.translate(0.0D, 0.0D, -205.0D); + break; + } + additionalGLStuffForText(); + GlStateManager.glNormal3f(0.0F, 0.0F, -0.010416667F); + fontRender.drawString(text, 0, 0, 0); + GlStateManager.depthMask(true); + GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); + GlStateManager.popMatrix(); + } + + public void additionalGLStuffForText() {} +} diff --git a/src/main/java/gregtech/common/render/clipboard/TileEntityClipboardRenderer.java b/src/main/java/gregtech/common/render/clipboard/TileEntityClipboardRenderer.java new file mode 100644 index 00000000000..2c14edaf25a --- /dev/null +++ b/src/main/java/gregtech/common/render/clipboard/TileEntityClipboardRenderer.java @@ -0,0 +1,90 @@ +package gregtech.common.render.clipboard; +/* +import gregtech.api.items.metaitem.MetaItem; +import gregtech.api.metatileentity.MetaTileEntity; +import gregtech.api.render.MetaTileEntityRenderer; +import gregtech.common.blocks.clipboard.MetaTileEntityClipboard; +import gregtech.common.tileentities.GTNativeTileEntity; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.tileentity.TileEntity; + +public class TileEntityClipboardRenderer extends MetaTileEntityRenderer { + private double textSpacing = -0.0658D; + + @Override + public void render(MetaTileEntity tileEntity, double paramDouble1, double paramDouble2, double paramDouble3, float paramFloat) { + MetaTileEntityClipboard tile = (MetaTileEntityClipboard) tileEntity; + if (tile != null) { + renderText(tile.titletext, 0.037D, 0.825D, 0.27D); + renderText(tile.button0text, 0.037D, 0.76D, 0.222D); + renderText(tile.button1text, 0.037D, 0.76D + 1.0D * this.textSpacing, 0.222D); + renderText(tile.button2text, 0.037D, 0.76D + 2.0D * this.textSpacing, 0.222D); + renderText(tile.button3text, 0.037D, 0.76D + 3.0D * this.textSpacing, 0.222D); + renderText(tile.button4text, 0.037D, 0.76D + 4.0D * this.textSpacing, 0.222D); + renderText(tile.button5text, 0.037D, 0.76D + 5.0D * this.textSpacing, 0.222D); + renderText(tile.button6text, 0.037D, 0.76D + 6.0D * this.textSpacing, 0.222D); + renderText(tile.button7text, 0.037D, 0.76D + 7.0D * this.textSpacing, 0.222D); + String pageNum = "" + tile.currentPage; + if (tile.currentPage > 9) { + renderText(pageNum, 0.037D, 0.17D, 0.03D); + } else { + renderText(pageNum, 0.037D, 0.17D, 0.02D); + } + } + } + + public void renderText(String text, double xAdjust, double yAdjust, double zAdjust) { + FontRenderer fontRender = this.getFontRenderer(); + float offsetx = 0.0F; + float offsetz = 0.0F; + switch(this.getAngle()) { + case SOUTH: + offsetx = -0.0116F; + break; + case WEST: + offsetz = -0.0116F; + break; + case NORTH: + offsetx = 0.0116F; + break; + case EAST: + offsetz = 0.0116F; + } + GlStateManager.pushMatrix(); + GlStateManager.translate(this.globalX + 0.5D + offsetx, this.globalY, this.globalZ + 0.5D + offsetz); + switch (getAngle()) { + case SOUTH: + GlStateManager.rotate(180.0F, 0.0F, 1.0F, 0.0F); + break; + case WEST: + GlStateManager.rotate(90.0F, 0.0F, 1.0F, 0.0F); + case NORTH: + default: + break; + case EAST: + GlStateManager.rotate(-90.0F, 0.0F, 1.0F, 0.0F); + } + GlStateManager.translate(-0.5D + xAdjust, yAdjust, zAdjust); + GlStateManager.depthMask(false); + GlStateManager.scale(0.0045F, 0.0045F, 0.0045F); + GlStateManager.rotate(270.0F, 0.0F, 1.0F, 0.0F); + GlStateManager.rotate(180.0F, 0.0F, 0.0F, 1.0F); + switch (this.shift) { + case HALF_SHIFT: + GlStateManager.translate(0.0D, 0.0D, -95.0D); + break; + case FULL_SHIFT: + GlStateManager.translate(0.0D, 0.0D, -205.0D); + break; + } + additionalGLStuffForText(); + GlStateManager.glNormal3f(0.0F, 0.0F, -0.010416667F); + fontRender.drawString(text, 0, 0, 0); + GlStateManager.depthMask(true); + GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); + GlStateManager.popMatrix(); + } + +} +*/ diff --git a/src/main/java/gregtech/common/tileentities/EnumShiftPosition.java b/src/main/java/gregtech/common/tileentities/EnumShiftPosition.java new file mode 100644 index 00000000000..4d0662f076b --- /dev/null +++ b/src/main/java/gregtech/common/tileentities/EnumShiftPosition.java @@ -0,0 +1,30 @@ +package gregtech.common.tileentities; + +public enum EnumShiftPosition { + NO_SHIFT(0), + HALF_SHIFT(1), + FULL_SHIFT(2); + + private int ID; + + EnumShiftPosition(int ID) { + this.ID = ID; + } + + public int getID() { + return this.ID; + } + + public static EnumShiftPosition getEnumFromID(int id) { + EnumShiftPosition position = NO_SHIFT; + switch (id) { + case 1: + position = HALF_SHIFT; + break; + case 2: + position = FULL_SHIFT; + break; + } + return position; + } +} diff --git a/src/main/java/gregtech/common/tileentities/EnumVertPosition.java b/src/main/java/gregtech/common/tileentities/EnumVertPosition.java new file mode 100644 index 00000000000..abe605dfba9 --- /dev/null +++ b/src/main/java/gregtech/common/tileentities/EnumVertPosition.java @@ -0,0 +1,30 @@ +package gregtech.common.tileentities; + +public enum EnumVertPosition { + FLOOR(0), + WALL(1), + CEILING(2); + + private int ID; + + EnumVertPosition(int ID) { + this.ID = ID; + } + + public int getID() { + return this.ID; + } + + public static EnumVertPosition getEnumFromID(int id) { + EnumVertPosition position = FLOOR; + switch (id) { + case 1: + position = WALL; + break; + case 2: + position = CEILING; + break; + } + return position; + } +} diff --git a/src/main/java/gregtech/common/tileentities/GTNativeTileEntity.java b/src/main/java/gregtech/common/tileentities/GTNativeTileEntity.java new file mode 100644 index 00000000000..f5a15df1060 --- /dev/null +++ b/src/main/java/gregtech/common/tileentities/GTNativeTileEntity.java @@ -0,0 +1,493 @@ +package gregtech.common.tileentities; + +import net.minecraft.block.Block; +import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.Entity; +import net.minecraft.entity.item.EntityItem; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.IInventory; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTBase; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraft.network.NetworkManager; +import net.minecraft.network.play.server.SPacketUpdateTileEntity; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.NonNullList; +import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; +import net.minecraftforge.items.IItemHandler; + +import javax.annotation.Nonnull; + +public abstract class GTNativeTileEntity extends TileEntity implements IInventory, IItemHandler { + private EnumFacing angle = EnumFacing.NORTH; + + private EnumShiftPosition shift = EnumShiftPosition.NO_SHIFT; + + private EnumVertPosition vertPosition = EnumVertPosition.WALL; + + public NonNullList inventory; + + private String customTexture = "none"; + + private boolean isRetexturable; + + private boolean isLocked = false; + + private String lockee = ""; + + private int renderBoxAdditionalSize = 1; + + public GTNativeTileEntity(int inventorySize, boolean canRetexture) { + this.inventory = NonNullList.withSize(inventorySize, ItemStack.EMPTY); + this.isRetexturable = canRetexture; + } + + public boolean addStackToInventoryFromWorld(ItemStack stack, int slot, EntityPlayer player) { + if (slot == -1) + return false; + boolean returnValue = false; + ItemStack currentStack = getStackInSlot(slot); + if (stack != ItemStack.EMPTY && currentStack == ItemStack.EMPTY) { + setInventorySlotContents(slot, stack); + player.inventory.setInventorySlotContents(player.inventory.currentItem, ItemStack.EMPTY); + returnValue = true; + } else if (stack != ItemStack.EMPTY && currentStack != ItemStack.EMPTY) { + ItemStack leftStack = stack.copy(); + ItemStack rightStack = currentStack.copy(); + leftStack.setCount(1); + rightStack.setCount(1); + if (getIsItemStacksEqual(leftStack, rightStack)) { + int total = stack.getCount() + currentStack.getCount(); + if (total > stack.getMaxStackSize() && currentStack.getCount() != currentStack.getMaxStackSize()) { + currentStack.setCount(stack.getMaxStackSize()); + stack.setCount(total - stack.getMaxStackSize()); + setInventorySlotContents(slot, currentStack); + player.inventory.setInventorySlotContents(player.inventory.currentItem, stack); + returnValue = true; + } else if (total <= stack.getMaxStackSize()) { + currentStack.setCount(total); + setInventorySlotContents(slot, currentStack); + player.inventory.setInventorySlotContents(player.inventory.currentItem, ItemStack.EMPTY); + returnValue = true; + } + } + if (returnValue) + getWorld().notifyBlockUpdate(getPos(), getWorld().getBlockState(getPos()), getWorld().getBlockState(getPos()), 3); + } + return returnValue; + } + + public boolean getIsItemStacksEqual(ItemStack stack1, ItemStack stack2) { + boolean output = false; + if (stack1 != ItemStack.EMPTY && stack2 != ItemStack.EMPTY) + if (stack1.getItem() == stack2.getItem() && stack1.getItemDamage() == stack2.getItemDamage()) { + NBTTagCompound tag1 = stack1.getTagCompound(); + NBTTagCompound tag2 = stack2.getTagCompound(); + if (tag1 == null && tag2 == null) { + output = true; + } else { + output = tag1.equals(tag2); + } + } + return output; + } + + public boolean addStackToInventoryFromWorldSingleStackSize(ItemStack stack, int slot, EntityPlayer player) { + boolean returnValue = false; + ItemStack currentStack = getStackInSlot(slot); + if (stack != ItemStack.EMPTY && currentStack == ItemStack.EMPTY) { + if (stack.getCount() > 1) { + ItemStack newStack = stack.copy(); + newStack.setCount(1); + stack.setCount(stack.getCount() - 1); + setInventorySlotContents(slot, newStack); + player.inventory.setInventorySlotContents(player.inventory.currentItem, stack); + } else { + setInventorySlotContents(slot, stack); + player.inventory.setInventorySlotContents(player.inventory.currentItem, ItemStack.EMPTY); + } + returnValue = true; + } + if (returnValue) + getWorld().notifyBlockUpdate(getPos(), getWorld().getBlockState(getPos()), getWorld().getBlockState(getPos()), 3); + return returnValue; + } + + public boolean removeStackFromInventoryFromWorld(int slot, EntityPlayer player, Block block) { + boolean returnValue = false; + ItemStack stack = getStackInSlot(slot); + if (stack != ItemStack.EMPTY) { + this.dropStackInSlot(this.world, slot, getPos()); + setInventorySlotContents(slot, ItemStack.EMPTY); + getWorld().notifyBlockUpdate(getPos(), getWorld().getBlockState(getPos()), getWorld().getBlockState(getPos()), 3); + returnValue = true; + } + return returnValue; + } + + public void dropStackInSlot(World world, int slot, BlockPos extractPos) { + ItemStack stack = this.getStackInSlot(slot); + if (stack != ItemStack.EMPTY && stack.getCount() > 0) { + EntityItem entityItem = new EntityItem(world, (extractPos.getX() + 0.5F), (extractPos.getY() + 0.5F), (extractPos.getZ() + 0.5F), new ItemStack(stack.getItem(), stack.getCount(), stack.getItemDamage())); + if (stack.hasTagCompound()) + entityItem.getItem().setTagCompound(stack.getTagCompound().copy()); + entityItem.motionX = 0.0D; + entityItem.motionY = 0.0D; + entityItem.motionZ = 0.0D; + world.spawnEntity(entityItem); + stack.setCount(0); + } + } + + public abstract void setInventorySlotContentsAdditionalCommands(int paramInt, ItemStack paramItemStack); + + public abstract void loadCustomNBTData(NBTTagCompound paramNBTTagCompound); + + public abstract NBTTagCompound writeCustomNBTData(NBTTagCompound paramNBTTagCompound); + + public void setAngle(EnumFacing facing) { + this.angle = facing; + getWorld().notifyBlockUpdate(getPos(), getWorld().getBlockState(getPos()), getWorld().getBlockState(getPos()), 3); + } + + public void setShiftPosition(EnumShiftPosition position) { + this.shift = position; + getWorld().notifyBlockUpdate(getPos(), getWorld().getBlockState(getPos()), getWorld().getBlockState(getPos()), 3); + } + + public void setVertPosition(EnumVertPosition position) { + this.vertPosition = position; + getWorld().notifyBlockUpdate(getPos(), getWorld().getBlockState(getPos()), getWorld().getBlockState(getPos()), 3); + } + + public EnumFacing getAngle() { + return this.angle; + } + + public EnumShiftPosition getShiftPosition() { + return this.shift; + } + + public EnumVertPosition getVertPosition() { + return this.vertPosition; + } + + public boolean canRetextureBlock() { + return this.isRetexturable; + } + + public String getCustomTextureString() { + return this.customTexture; + } + + public void setCustomTexureString(String tex) { + this.customTexture = tex; + getWorld().notifyBlockUpdate(getPos(), getWorld().getBlockState(getPos()), getWorld().getBlockState(getPos()), 3); + this.world.markBlockRangeForRenderUpdate(this.pos, this.pos); + } + + public boolean isLocked() { + return this.isLocked; + } + + public void setLocked(boolean locked) { + this.isLocked = locked; + getWorld().notifyBlockUpdate(getPos(), getWorld().getBlockState(getPos()), getWorld().getBlockState(getPos()), 3); + } + + public String getLockee() { + return this.lockee; + } + + public void setLockee(String lockeeperson) { + this.lockee = lockeeperson; + } + + public int getSizeInventory() { + return this.inventory.size(); + } + + public ItemStack getStackInSlot(int slot) { + ItemStack output = ItemStack.EMPTY; + if (slot >= 0 && slot < this.inventory.size()) + output = (ItemStack)this.inventory.get(slot); + return output; + } + + public void setInventorySlotContents(int slot, ItemStack stack) { + if (slot >= 0 && slot < this.inventory.size()) { + this.inventory.set(slot, stack); + if (stack != ItemStack.EMPTY && stack.getCount() > getInventoryStackLimit()) + stack.setCount(getInventoryStackLimit()); + setInventorySlotContentsAdditionalCommands(slot, stack); + getWorld().notifyBlockUpdate(getPos(), getWorld().getBlockState(getPos()), getWorld().getBlockState(getPos()), 3); + } + } + + public ItemStack decrStackSize(int slot, int amount) { + ItemStack stack = getStackInSlot(slot); + if (stack != ItemStack.EMPTY) + if (stack.getCount() <= amount) { + setInventorySlotContents(slot, ItemStack.EMPTY); + } else { + stack = stack.splitStack(amount); + if (stack.getCount() == 0) + setInventorySlotContents(slot, ItemStack.EMPTY); + } + return stack; + } + + public ItemStack removeStackFromSlot(int slot) { + ItemStack stack = getStackInSlot(slot); + if (stack != ItemStack.EMPTY) + setInventorySlotContents(slot, ItemStack.EMPTY); + return stack; + } + + public abstract int getInventoryStackLimit(); + + public boolean isItemValidForSlot(int slot, ItemStack itemstack) { + return true; + } + + @SideOnly(Side.CLIENT) + public AxisAlignedBB getRenderBoundingBox() { + AxisAlignedBB bb = INFINITE_EXTENT_AABB; + bb = new AxisAlignedBB(this.pos.getX(), this.pos.getY(), this.pos.getZ(), (this.pos.getX() + this.renderBoxAdditionalSize), (this.pos.getY() + this.renderBoxAdditionalSize), (this.pos.getZ() + this.renderBoxAdditionalSize)); + return bb; + } + + public void setRenderBoxAdditionalSize(int size) { + this.renderBoxAdditionalSize = size; + } + + public boolean hasCustomName() { + return false; + } + + public void openInventory(EntityPlayer player) {} + + public void closeInventory(EntityPlayer player) {} + + public int getField(int id) { + return 0; + } + + public void setField(int id, int value) {} + + public int getFieldCount() { + return 0; + } + + public void clear() {} + + public void readFromNBT(NBTTagCompound nbt) { + super.readFromNBT(nbt); + loadNBTData(nbt); + } + + public void onDataPacket(NetworkManager manager, SPacketUpdateTileEntity packet) { + NBTTagCompound nbtData = packet.getNbtCompound(); + loadNBTData(nbtData); + this.world.markBlockRangeForRenderUpdate(getPos(), getPos()); + } + + private void loadNBTData(NBTTagCompound nbt) { + NBTTagList tagList = nbt.getTagList("Inventory", 10); + this.inventory = NonNullList.withSize(getSizeInventory(), ItemStack.EMPTY); + for (int i = 0; i < tagList.tagCount(); i++) { + NBTTagCompound tag = tagList.getCompoundTagAt(i); + byte slot = tag.getByte("Slot"); + if (slot >= 0 && slot < this.inventory.size()) + this.inventory.set(slot, new ItemStack(tag)); + } + this.isLocked = nbt.getBoolean("locked"); + this.lockee = nbt.getString("lockee"); + this.angle = getFacingFromAngleID(nbt.getInteger("angle")); + this.shift = EnumShiftPosition.getEnumFromID(nbt.getInteger("shift")); + this.vertPosition = EnumVertPosition.getEnumFromID(nbt.getInteger("position")); + loadCustomNBTData(nbt); + if (this.isRetexturable) + this.customTexture = nbt.getString("customTexture"); + } + + public NBTTagCompound writeToNBT(NBTTagCompound nbt) { + super.writeToNBT(nbt); + nbt = writeNBTData(nbt); + return nbt; + } + + public SPacketUpdateTileEntity getUpdatePacket() { + NBTTagCompound dataTag = new NBTTagCompound(); + dataTag = writeNBTData(dataTag); + return new SPacketUpdateTileEntity(this.pos, 1, dataTag); + } + + public NBTTagCompound getUpdateTag() { + NBTTagCompound tags = super.getUpdateTag(); + return writeNBTData(tags); + } + + private NBTTagCompound writeNBTData(NBTTagCompound nbt) { + NBTTagList itemList = new NBTTagList(); + for (int i = 0; i < this.inventory.size(); i++) { + ItemStack stack = (ItemStack)this.inventory.get(i); + if (stack != ItemStack.EMPTY) { + NBTTagCompound tag = new NBTTagCompound(); + tag.setByte("Slot", (byte)i); + stack.writeToNBT(tag); + itemList.appendTag(tag); + } + } + nbt.setTag("Inventory", itemList); + nbt.setBoolean("locked", this.isLocked); + nbt.setString("lockee", this.lockee); + nbt.setInteger("angle", getAngleIDFromFacing(this.angle)); + nbt.setInteger("shift", this.shift.getID()); + nbt.setInteger("position", this.vertPosition.getID()); + nbt = writeCustomNBTData(nbt); + if (this.isRetexturable) + nbt.setString("customTexture", this.customTexture); + return nbt; + } + + private int getAngleIDFromFacing(EnumFacing facing) { + switch (facing) { + case WEST: + return 1; + case NORTH: + return 2; + case EAST: + return 3; + case DOWN: + return 4; + case UP: + return 5; + } + return 0; + } + + public int getAngleID() { + return getAngleIDFromFacing(getAngle()); + } + + private EnumFacing getFacingFromAngleID(int angle) { + EnumFacing face = EnumFacing.SOUTH; + switch (angle) { + case 1: + face = EnumFacing.WEST; + break; + case 2: + face = EnumFacing.NORTH; + break; + case 3: + face = EnumFacing.EAST; + break; + case 4: + face = EnumFacing.DOWN; + break; + case 5: + face = EnumFacing.UP; + break; + } + return face; + } + + public void updateSurroundingBlocks(Block blocktype) { + this.world.notifyNeighborsOfStateChange(new BlockPos(this.pos.getX(), this.pos.getY(), this.pos.getZ()), blocktype, true); + this.world.notifyNeighborsOfStateChange(new BlockPos(this.pos.getX() + 1, this.pos.getY(), this.pos.getZ()), blocktype, true); + this.world.notifyNeighborsOfStateChange(new BlockPos(this.pos.getX() - 1, this.pos.getY(), this.pos.getZ() + 1), blocktype, true); + this.world.notifyNeighborsOfStateChange(new BlockPos(this.pos.getX(), this.pos.getY(), this.pos.getZ() - 1), blocktype, true); + this.world.notifyNeighborsOfStateChange(new BlockPos(this.pos.getX(), this.pos.getY() + 1, this.pos.getZ()), blocktype, true); + this.world.notifyNeighborsOfStateChange(new BlockPos(this.pos.getX(), this.pos.getY() - 1, this.pos.getZ()), blocktype, true); + this.world.notifyNeighborsOfStateChange(new BlockPos(this.pos.getX(), this.pos.getY(), this.pos.getZ()), blocktype, true); + this.world.notifyNeighborsOfStateChange(new BlockPos(this.pos.getX() + 2, this.pos.getY(), this.pos.getZ()), blocktype, true); + this.world.notifyNeighborsOfStateChange(new BlockPos(this.pos.getX() - 2, this.pos.getY(), this.pos.getZ()), blocktype, true); + this.world.notifyNeighborsOfStateChange(new BlockPos(this.pos.getX(), this.pos.getY(), this.pos.getZ() + 2), blocktype, true); + this.world.notifyNeighborsOfStateChange(new BlockPos(this.pos.getX(), this.pos.getY(), this.pos.getZ() - 2), blocktype, true); + this.world.notifyNeighborsOfStateChange(new BlockPos(this.pos.getX(), this.pos.getY() + 2, this.pos.getZ()), blocktype, true); + this.world.notifyNeighborsOfStateChange(new BlockPos(this.pos.getX(), this.pos.getY() - 2, this.pos.getZ()), blocktype, true); + getWorld().notifyBlockUpdate(getPos(), getWorld().getBlockState(getPos()), getWorld().getBlockState(getPos()), 3); + } + + public boolean shouldRefresh(@Nonnull World world, @Nonnull BlockPos pos, @Nonnull IBlockState oldState, @Nonnull IBlockState newState) { + return true; + } + + public boolean isEmpty() { + boolean output = true; + for (ItemStack itemStack : this.inventory) { + if (itemStack != ItemStack.EMPTY) { + output = false; + break; + } + } + return output; + } + + public boolean isUsableByPlayer(@Nonnull EntityPlayer player) { + return (this.world.getTileEntity(this.pos) == this && player.getDistanceSq(this.pos.getX() + 0.5D, this.pos.getY() + 0.5D, this.pos.getZ() + 0.5D) < 64.0D); + } + + public int getSlots() { + return this.inventory.size(); + } + + @Nonnull + public ItemStack insertItem(int slot, @Nonnull ItemStack stack, boolean simulate) { + ItemStack returnStack = stack; + if (slot < this.inventory.size()) { + ItemStack currentSlot = getStackInSlot(slot); + if (currentSlot != ItemStack.EMPTY) { + if (stack.getItem() == currentSlot.getItem() && currentSlot.getCount() < currentSlot.getMaxStackSize()) + if (!simulate) { + int count = currentSlot.getCount() + stack.getCount(); + if (count > stack.getMaxStackSize()) { + currentSlot.setCount(currentSlot.getMaxStackSize()); + setInventorySlotContents(slot, currentSlot); + returnStack = stack.copy(); + returnStack.setCount(count - currentSlot.getMaxStackSize()); + } else { + stack.setCount(count); + setInventorySlotContents(slot, stack); + returnStack = ItemStack.EMPTY; + } + } + } else if (!simulate) { + setInventorySlotContents(slot, stack); + returnStack = ItemStack.EMPTY; + } + } + return returnStack; + } + + @Nonnull + public ItemStack extractItem(int slot, int amount, boolean simulate) { + ItemStack result = ItemStack.EMPTY; + if (slot < this.inventory.size()) { + ItemStack slottedStack = getStackInSlot(slot); + if (slottedStack != ItemStack.EMPTY && !simulate) { + result = slottedStack.copy(); + if (amount >= slottedStack.getCount()) { + setInventorySlotContents(slot, ItemStack.EMPTY); + } else { + result.setCount(amount); + slottedStack.setCount(slottedStack.getCount() - amount); + setInventorySlotContents(slot, slottedStack); + } + } + } + return result; + } + + public int getSlotLimit(int slot) { + return 64; + } +} From ddc506d6e1db027415416f4ae9af24cb19633320 Mon Sep 17 00:00:00 2001 From: bruberu <80226372+bruberu@users.noreply.github.com> Date: Wed, 14 Jul 2021 16:42:04 -0500 Subject: [PATCH 02/42] Complete everything up to the actual rendering --- .../api/items/gui/PlayerInventoryHolder.java | 6 +- .../InaccessibleItemStackHandler.java | 19 ++++ .../items/behaviors/ClipboardBehaviour.java | 59 +++++++++-- .../metatileentities/MetaTileEntities.java | 4 + .../MetaTileEntityClipboard.java | 68 +++++++++++++ .../gregtech/models/block/clipboard.json | 94 ++++++++++++++++++ .../models/item/metaitems/clipboard.json | 94 ++++++++++++++++++ .../gui/widget/clipboard_checkbox.png | Bin 0 -> 721 bytes .../gregtech/textures/gui/widget/left.png | Bin 0 -> 288 bytes .../gregtech/textures/gui/widget/right.png | Bin 0 -> 297 bytes .../items/metaitems/clipboard/clipboard.png | Bin 0 -> 495 bytes .../items/metaitems/clipboard/page.png | Bin 0 -> 336 bytes 12 files changed, 336 insertions(+), 8 deletions(-) create mode 100644 src/main/java/gregtech/api/items/itemhandlers/InaccessibleItemStackHandler.java create mode 100644 src/main/java/gregtech/common/metatileentities/MetaTileEntityClipboard.java create mode 100644 src/main/resources/assets/gregtech/models/block/clipboard.json create mode 100644 src/main/resources/assets/gregtech/models/item/metaitems/clipboard.json create mode 100644 src/main/resources/assets/gregtech/textures/gui/widget/clipboard_checkbox.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/widget/left.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/widget/right.png create mode 100644 src/main/resources/assets/gregtech/textures/items/metaitems/clipboard/clipboard.png create mode 100644 src/main/resources/assets/gregtech/textures/items/metaitems/clipboard/page.png diff --git a/src/main/java/gregtech/api/items/gui/PlayerInventoryHolder.java b/src/main/java/gregtech/api/items/gui/PlayerInventoryHolder.java index 51670ee9d59..f974dff68d0 100644 --- a/src/main/java/gregtech/api/items/gui/PlayerInventoryHolder.java +++ b/src/main/java/gregtech/api/items/gui/PlayerInventoryHolder.java @@ -17,7 +17,7 @@ public class PlayerInventoryHolder implements IUIHolder { /*package-local*/ ItemStack sampleItem; @SideOnly(Side.CLIENT) - /*package-local*/ PlayerInventoryHolder(EntityPlayer player, EnumHand hand, ItemStack sampleItem) { + public PlayerInventoryHolder(EntityPlayer player, EnumHand hand, ItemStack sampleItem) { this.player = player; this.hand = hand; this.sampleItem = sampleItem; @@ -56,6 +56,10 @@ public boolean isRemote() { return player.getEntityWorld().isRemote; } + public ItemStack getSampleItem() { + return sampleItem; + } + public ItemStack getCurrentItem() { ItemStack itemStack = player.getHeldItem(hand); if (!ItemStack.areItemsEqual(sampleItem, itemStack)) diff --git a/src/main/java/gregtech/api/items/itemhandlers/InaccessibleItemStackHandler.java b/src/main/java/gregtech/api/items/itemhandlers/InaccessibleItemStackHandler.java new file mode 100644 index 00000000000..a7c30277482 --- /dev/null +++ b/src/main/java/gregtech/api/items/itemhandlers/InaccessibleItemStackHandler.java @@ -0,0 +1,19 @@ +package gregtech.api.items.itemhandlers; + +import net.minecraft.item.ItemStack; +import net.minecraftforge.items.ItemStackHandler; + +import javax.annotation.Nonnull; + +public class InaccessibleItemStackHandler extends ItemStackHandler { + @Nonnull + public ItemStack insertItem(int slot, @Nonnull ItemStack stack, boolean simulate) { + return stack; + } + + @Nonnull + public ItemStack extractItem(int slot, int amount, boolean simulate) { + return ItemStack.EMPTY; + } + +} diff --git a/src/main/java/gregtech/common/items/behaviors/ClipboardBehaviour.java b/src/main/java/gregtech/common/items/behaviors/ClipboardBehaviour.java index 69ab3823044..d2e770147f3 100644 --- a/src/main/java/gregtech/common/items/behaviors/ClipboardBehaviour.java +++ b/src/main/java/gregtech/common/items/behaviors/ClipboardBehaviour.java @@ -22,13 +22,18 @@ public class ClipboardBehaviour implements IItemBehaviour, ItemUIFactory { @Override public ModularUI createUI(PlayerInventoryHolder holder, EntityPlayer entityPlayer) { - initNBT(holder.getCurrentItem()); + initNBT(holder.getSampleItem()); ModularUI.Builder builder = ModularUI.builder(GuiTextures.BACKGROUND, 170, 238); + + builder.widget(new TextFieldWidget(20, 10, 130, 13, true, + () -> getTitle(holder), (x) -> setTitle(holder, x), 23, 12) + .setValidator((x) -> true)); + for (int i = 0; i < 8; i++) { int finalI = i; - builder.widget(new ImageCycleButtonWidget(5, 27 + 15 * i, 15, 15, GuiTextures.CLIPBOARD_CHECKBOX, 2, + builder.widget(new ImageCycleButtonWidget(5, 37 + 20 * i, 15, 15, GuiTextures.CLIPBOARD_CHECKBOX, 2, () -> getButtonState(holder, finalI), (x) -> toggleButton(holder, finalI))); - builder.widget(new TextFieldWidget(21, 30 + 15 * i, 140, 10, true, + builder.widget(new TextFieldWidget(21, 40 + 20 * i, 140, 10, true, () -> getString(holder, finalI), (x) -> setString(holder, finalI, x), 23, 8) .setValidator((x) -> true)); } @@ -60,6 +65,7 @@ private static void initNBT(ItemStack stack) { tagCompound = new NBTTagCompound(); tagCompound.setShort("PageIndex", (short) 0); tagCompound.setShort("TotalPages", (short) 0); + tagCompound.setString("PageTitle", ""); NBTTagCompound pageCompound = new NBTTagCompound(); pageCompound.setShort("ButStat", (short) 0); @@ -76,7 +82,7 @@ private static void initNBT(ItemStack stack) { } private static void toggleButton(PlayerInventoryHolder holder, int pos) { - ItemStack stack = holder.getCurrentItem(); + ItemStack stack = holder.getSampleItem(); if (!MetaItems.CLIPBOARD.isItemEqual(stack)) throw new IllegalArgumentException("Given item stack is not a clipboard!"); NBTTagCompound tagCompound = getPageCompound(stack); @@ -88,7 +94,7 @@ private static void toggleButton(PlayerInventoryHolder holder, int pos) { } private static boolean getButtonState(PlayerInventoryHolder holder, int pos) { - ItemStack stack = holder.getCurrentItem(); + ItemStack stack = holder.getSampleItem(); if (!MetaItems.CLIPBOARD.isItemEqual(stack)) throw new IllegalArgumentException("Given item stack is not a clipboard!"); NBTTagCompound tagCompound = getPageCompound(stack); @@ -98,7 +104,7 @@ private static boolean getButtonState(PlayerInventoryHolder holder, int pos) { } private static void setString(PlayerInventoryHolder holder, int pos, String newString) { - ItemStack stack = holder.getCurrentItem(); + ItemStack stack = holder.getSampleItem(); if (!MetaItems.CLIPBOARD.isItemEqual(stack)) throw new IllegalArgumentException("Given item stack is not a clipboard!"); NBTTagCompound tagCompound = getPageCompound(stack); @@ -107,13 +113,52 @@ private static void setString(PlayerInventoryHolder holder, int pos, String newS } private static String getString(PlayerInventoryHolder holder, int pos) { - ItemStack stack = holder.getCurrentItem(); + ItemStack stack = holder.getSampleItem(); if (!MetaItems.CLIPBOARD.isItemEqual(stack)) throw new IllegalArgumentException("Given item stack is not a clipboard!"); NBTTagCompound tagCompound = getPageCompound(stack); return tagCompound.getString("Task" + pos); } + private static void setTitle(PlayerInventoryHolder holder, String newString) { + ItemStack stack = holder.getSampleItem(); + if (!MetaItems.CLIPBOARD.isItemEqual(stack)) + throw new IllegalArgumentException("Given item stack is not a clipboard!"); + NBTTagCompound tagCompound = stack.getTagCompound(); + assert tagCompound != null; + tagCompound.setString("Title", newString); + stack.setTagCompound(tagCompound); + } + + private static String getTitle(PlayerInventoryHolder holder) { + ItemStack stack = holder.getSampleItem(); + if (!MetaItems.CLIPBOARD.isItemEqual(stack)) + throw new IllegalArgumentException("Given item stack is not a clipboard!"); + NBTTagCompound tagCompound = stack.getTagCompound(); + return tagCompound.getString("Title"); + } + + private static int getPageNum(PlayerInventoryHolder holder) { + ItemStack stack = holder.getSampleItem(); + if (!MetaItems.CLIPBOARD.isItemEqual(stack)) + throw new IllegalArgumentException("Given item stack is not a clipboard!"); + NBTTagCompound tagCompound = stack.getTagCompound(); + return tagCompound.getInteger("PageIndex"); + } + + private static void incrPageNum(PlayerInventoryHolder holder, int increment) { + ItemStack stack = holder.getSampleItem(); + if (!MetaItems.CLIPBOARD.isItemEqual(stack)) + throw new IllegalArgumentException("Given item stack is not a clipboard!"); + NBTTagCompound tagCompound = stack.getTagCompound(); + assert tagCompound != null; + + int currentIndex = tagCompound.getInteger("PageIndex"); + // Clamps currentIndex between 0 and MAX_PAGES. + tagCompound.setInteger("PageIndex", Math.max(Math.min(currentIndex + increment, MAX_PAGES), 0)); + stack.setTagCompound(tagCompound); + } + @Override public ActionResult onItemRightClick(World world, EntityPlayer player, EnumHand hand) { diff --git a/src/main/java/gregtech/common/metatileentities/MetaTileEntities.java b/src/main/java/gregtech/common/metatileentities/MetaTileEntities.java index 6d83f248be7..3b957205b09 100644 --- a/src/main/java/gregtech/common/metatileentities/MetaTileEntities.java +++ b/src/main/java/gregtech/common/metatileentities/MetaTileEntities.java @@ -196,6 +196,8 @@ public class MetaTileEntities { public static MetaTileEntityInfiniteEmitter INFINITE_EMITTER; + public static MetaTileEntityClipboard CLIPBOARD_TILE; + public static void init() { GTLog.logger.info("Registering MetaTileEntities"); @@ -685,6 +687,8 @@ public static void init() { INFINITE_EMITTER = GregTechAPI.registerMetaTileEntity(1630, new MetaTileEntityInfiniteEmitter(gregtechId("infinite_emitter"))); + CLIPBOARD_TILE = GregTechAPI.registerMetaTileEntity(1631, new MetaTileEntityClipboard(gregtechId("clipboard"))); + /* * FOR ADDON DEVELOPERS: * diff --git a/src/main/java/gregtech/common/metatileentities/MetaTileEntityClipboard.java b/src/main/java/gregtech/common/metatileentities/MetaTileEntityClipboard.java new file mode 100644 index 00000000000..5e413c5b715 --- /dev/null +++ b/src/main/java/gregtech/common/metatileentities/MetaTileEntityClipboard.java @@ -0,0 +1,68 @@ +package gregtech.common.metatileentities; + +import codechicken.lib.render.CCRenderState; +import codechicken.lib.render.pipeline.IVertexOperation; +import codechicken.lib.vec.Matrix4; +import gregtech.api.capability.impl.FluidHandlerProxy; +import gregtech.api.gui.ModularUI; +import gregtech.api.items.gui.PlayerInventoryHolder; +import gregtech.api.items.itemhandlers.InaccessibleItemStackHandler; +import gregtech.api.items.metaitem.MetaItem; +import gregtech.api.items.metaitem.stats.IItemBehaviour; +import gregtech.api.metatileentity.MetaTileEntity; +import gregtech.api.metatileentity.MetaTileEntityHolder; +import gregtech.common.items.MetaItems; +import gregtech.common.items.behaviors.ClipboardBehaviour; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.items.IItemHandler; + +import javax.annotation.Nonnull; + +import java.util.List; +import java.util.Optional; + +import static gregtech.common.items.MetaItems.CLIPBOARD; + +public class MetaTileEntityClipboard extends MetaTileEntity { + + public MetaTileEntityClipboard(ResourceLocation metaTileEntityId) { + super(metaTileEntityId); + } + + @Override + public MetaTileEntity createMetaTileEntity(MetaTileEntityHolder holder) { + return new MetaTileEntityClipboard(metaTileEntityId); + } + + @Override + protected ModularUI createUI(EntityPlayer entityPlayer) { + if(itemInventory.getStackInSlot(0) == ItemStack.EMPTY) { + ((InaccessibleItemStackHandler) itemInventory).setStackInSlot(0, CLIPBOARD.getStackForm()); + } + if(itemInventory.getStackInSlot(0).isItemEqual(CLIPBOARD.getStackForm())) { + List behaviours = ((MetaItem) itemInventory.getStackInSlot(0).getItem()).getBehaviours(itemInventory.getStackInSlot(0)); + Optional clipboardBehaviour = behaviours.stream().filter((x) -> x instanceof ClipboardBehaviour).findFirst(); + if(!clipboardBehaviour.isPresent()) + return null; + if(clipboardBehaviour.get() instanceof ClipboardBehaviour) { + return ((ClipboardBehaviour) clipboardBehaviour.get()).createUI(new PlayerInventoryHolder(entityPlayer, entityPlayer.getActiveHand(), itemInventory.getStackInSlot(0)), entityPlayer); + } + } + return null; + } + + @Override + protected void initializeInventory() { + this.itemInventory = new InaccessibleItemStackHandler(); + + this.importItems = createImportItemHandler(); + this.exportItems = createExportItemHandler(); + this.importFluids = createImportFluidHandler(); + this.exportFluids = createExportFluidHandler(); + this.fluidInventory = new FluidHandlerProxy(importFluids, exportFluids); + } +} diff --git a/src/main/resources/assets/gregtech/models/block/clipboard.json b/src/main/resources/assets/gregtech/models/block/clipboard.json new file mode 100644 index 00000000000..7be55aa10b1 --- /dev/null +++ b/src/main/resources/assets/gregtech/models/block/clipboard.json @@ -0,0 +1,94 @@ +{ + "credit": "Made with Blockbench", + "textures": { + "0": "gregtech:items/metaitems/clipboard/clipboard", + "1": "gregtech:items/metaitems/clipboard/page", + "particle": "gregtech:items/metaitems/clipboard/clipboard" + }, + "elements": [ + { + "from": [6, 1, 9.025], + "to": [11, 8, 9.075], + "rotation": {"angle": 0, "axis": "y", "origin": [8.5, 6.59375, 9.0125]}, + "faces": { + "north": {"uv": [8.5, 8.5, 13.5, 15.5], "texture": "#0"}, + "east": {"uv": [8.5, 8.5, 8.55, 15.5], "texture": "#0"}, + "south": {"uv": [0, 0, 11.42857, 16], "texture": "#1"}, + "west": {"uv": [8.5, 8.5, 8.55, 15.5], "texture": "#0"}, + "up": {"uv": [8.5, 8.5, 13.5, 8.55], "rotation": 180, "texture": "#0"}, + "down": {"uv": [8.5, 8.5, 13.5, 8.55], "rotation": 180, "texture": "#0"} + } + }, + { + "from": [5.75, 0.75, 8.775], + "to": [11.25, 8.5, 9.025], + "rotation": {"angle": 0, "axis": "y", "origin": [8.5, 6.59375, 9.0125]}, + "faces": { + "north": {"uv": [8.5, 0, 14, 7.75], "texture": "#0"}, + "east": {"uv": [8.5, 0, 8.75, 7.75], "texture": "#0"}, + "south": {"uv": [8.5, 0, 14, 7.75], "texture": "#0"}, + "west": {"uv": [8.5, 0, 8.75, 7.75], "texture": "#0"}, + "up": {"uv": [8.5, 0.5, 14, 0.75], "rotation": 180, "texture": "#0"}, + "down": {"uv": [8.5, 0.5, 14, 0.75], "rotation": 180, "texture": "#0"} + } + }, + { + "from": [6.75, 8, 9.025], + "to": [10.25, 8.75, 9.175], + "rotation": {"angle": 0, "axis": "y", "origin": [8.5, 6.59375, 9.0125]}, + "faces": { + "north": {"uv": [0.5, 0.5, 4, 1.25], "texture": "#0"}, + "east": {"uv": [0.5, 0.5, 0.65, 1.25], "texture": "#0"}, + "south": {"uv": [0.5, 0.5, 4, 1.25], "texture": "#0"}, + "west": {"uv": [0.5, 0.5, 0.65, 1.25], "texture": "#0"}, + "up": {"uv": [0.5, 0.5, 4, 0.65], "rotation": 180, "texture": "#0"}, + "down": {"uv": [0.5, 0.5, 4, 0.65], "rotation": 180, "texture": "#0"} + } + }, + { + "from": [8, 8.5, 8.875], + "to": [9, 9.25, 9.125], + "rotation": {"angle": 0, "axis": "y", "origin": [8.5, 6.59375, 9.0125]}, + "faces": { + "north": {"uv": [0.5, 0.5, 1.5, 1.25], "texture": "#0"}, + "east": {"uv": [0.5, 0.5, 0.75, 1.25], "texture": "#0"}, + "south": {"uv": [0.5, 0.5, 1.5, 1.25], "texture": "#0"}, + "west": {"uv": [0.5, 0.5, 0.75, 1.25], "texture": "#0"}, + "up": {"uv": [0.5, 0.5, 1.5, 0.75], "rotation": 180, "texture": "#0"}, + "down": {"uv": [0.5, 0.5, 1.5, 0.75], "rotation": 180, "texture": "#0"} + } + } + ], + "display": { + "thirdperson_righthand": { + "translation": [-0.5, 7, -0.5] + }, + "thirdperson_lefthand": { + "translation": [0.5, 7, -0.5] + }, + "firstperson_righthand": { + "rotation": [-10, 0, 0], + "translation": [-3, 10, 2.5] + }, + "firstperson_lefthand": { + "rotation": [-10, 0, 0], + "translation": [-2, 10, 2.5] + }, + "ground": { + "translation": [0, 3.75, 0] + }, + "gui": { + "translation": [-1, 5.5, 0], + "scale": [1.75, 1.75, 1.75] + }, + "head": { + "translation": [-1, 5.75, 5], + "scale": [2, 2, 2] + }, + "fixed": { + "rotation": [0, -180, 0], + "translation": [1.25, 8.25, 1.5], + "scale": [2.5, 2.5, 2.5] + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/gregtech/models/item/metaitems/clipboard.json b/src/main/resources/assets/gregtech/models/item/metaitems/clipboard.json new file mode 100644 index 00000000000..7be55aa10b1 --- /dev/null +++ b/src/main/resources/assets/gregtech/models/item/metaitems/clipboard.json @@ -0,0 +1,94 @@ +{ + "credit": "Made with Blockbench", + "textures": { + "0": "gregtech:items/metaitems/clipboard/clipboard", + "1": "gregtech:items/metaitems/clipboard/page", + "particle": "gregtech:items/metaitems/clipboard/clipboard" + }, + "elements": [ + { + "from": [6, 1, 9.025], + "to": [11, 8, 9.075], + "rotation": {"angle": 0, "axis": "y", "origin": [8.5, 6.59375, 9.0125]}, + "faces": { + "north": {"uv": [8.5, 8.5, 13.5, 15.5], "texture": "#0"}, + "east": {"uv": [8.5, 8.5, 8.55, 15.5], "texture": "#0"}, + "south": {"uv": [0, 0, 11.42857, 16], "texture": "#1"}, + "west": {"uv": [8.5, 8.5, 8.55, 15.5], "texture": "#0"}, + "up": {"uv": [8.5, 8.5, 13.5, 8.55], "rotation": 180, "texture": "#0"}, + "down": {"uv": [8.5, 8.5, 13.5, 8.55], "rotation": 180, "texture": "#0"} + } + }, + { + "from": [5.75, 0.75, 8.775], + "to": [11.25, 8.5, 9.025], + "rotation": {"angle": 0, "axis": "y", "origin": [8.5, 6.59375, 9.0125]}, + "faces": { + "north": {"uv": [8.5, 0, 14, 7.75], "texture": "#0"}, + "east": {"uv": [8.5, 0, 8.75, 7.75], "texture": "#0"}, + "south": {"uv": [8.5, 0, 14, 7.75], "texture": "#0"}, + "west": {"uv": [8.5, 0, 8.75, 7.75], "texture": "#0"}, + "up": {"uv": [8.5, 0.5, 14, 0.75], "rotation": 180, "texture": "#0"}, + "down": {"uv": [8.5, 0.5, 14, 0.75], "rotation": 180, "texture": "#0"} + } + }, + { + "from": [6.75, 8, 9.025], + "to": [10.25, 8.75, 9.175], + "rotation": {"angle": 0, "axis": "y", "origin": [8.5, 6.59375, 9.0125]}, + "faces": { + "north": {"uv": [0.5, 0.5, 4, 1.25], "texture": "#0"}, + "east": {"uv": [0.5, 0.5, 0.65, 1.25], "texture": "#0"}, + "south": {"uv": [0.5, 0.5, 4, 1.25], "texture": "#0"}, + "west": {"uv": [0.5, 0.5, 0.65, 1.25], "texture": "#0"}, + "up": {"uv": [0.5, 0.5, 4, 0.65], "rotation": 180, "texture": "#0"}, + "down": {"uv": [0.5, 0.5, 4, 0.65], "rotation": 180, "texture": "#0"} + } + }, + { + "from": [8, 8.5, 8.875], + "to": [9, 9.25, 9.125], + "rotation": {"angle": 0, "axis": "y", "origin": [8.5, 6.59375, 9.0125]}, + "faces": { + "north": {"uv": [0.5, 0.5, 1.5, 1.25], "texture": "#0"}, + "east": {"uv": [0.5, 0.5, 0.75, 1.25], "texture": "#0"}, + "south": {"uv": [0.5, 0.5, 1.5, 1.25], "texture": "#0"}, + "west": {"uv": [0.5, 0.5, 0.75, 1.25], "texture": "#0"}, + "up": {"uv": [0.5, 0.5, 1.5, 0.75], "rotation": 180, "texture": "#0"}, + "down": {"uv": [0.5, 0.5, 1.5, 0.75], "rotation": 180, "texture": "#0"} + } + } + ], + "display": { + "thirdperson_righthand": { + "translation": [-0.5, 7, -0.5] + }, + "thirdperson_lefthand": { + "translation": [0.5, 7, -0.5] + }, + "firstperson_righthand": { + "rotation": [-10, 0, 0], + "translation": [-3, 10, 2.5] + }, + "firstperson_lefthand": { + "rotation": [-10, 0, 0], + "translation": [-2, 10, 2.5] + }, + "ground": { + "translation": [0, 3.75, 0] + }, + "gui": { + "translation": [-1, 5.5, 0], + "scale": [1.75, 1.75, 1.75] + }, + "head": { + "translation": [-1, 5.75, 5], + "scale": [2, 2, 2] + }, + "fixed": { + "rotation": [0, -180, 0], + "translation": [1.25, 8.25, 1.5], + "scale": [2.5, 2.5, 2.5] + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/gregtech/textures/gui/widget/clipboard_checkbox.png b/src/main/resources/assets/gregtech/textures/gui/widget/clipboard_checkbox.png new file mode 100644 index 0000000000000000000000000000000000000000..04b8efe7722a669bf636bfc48e883bd40502be4a GIT binary patch literal 721 zcmV;?0xtcDP)EX>4Tx04R}tkvm8OK@>$#q7spag(*ZVwonUE5EZeMD2kvUNrXf#+}-?y>>73> zHkN{|VBx3nSJ+rg7?1B@S z3~TYkycT#NKoAJgqnmDiCOQ$L=K8$Dr_S3xl~w!QpQ|~Ua!v4Q!lP#1DF`nK53d#S zig#5NW>!xMp9%LmQlRjI(v1?oD$W$yuQEeUEHWk>64o+RY*ewCbu8f_;m)LGOTIr| z;-unr#a3?BEZ3wvT&NC=4mLEH$V|OEA;3-y1(-%Z` zB1>%T6*eL##;8|+L47$&!Zle*3nxVF6=1+c&Dp~bkn2-Km5MeY00000NkvXXu0mjf DeuymD literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/widget/left.png b/src/main/resources/assets/gregtech/textures/gui/widget/left.png new file mode 100644 index 0000000000000000000000000000000000000000..3d32885b8b71cc3952f78590c3620154eba5ac56 GIT binary patch literal 288 zcmV+*0pI?KP)Tu|i^jgSirAO95duorqUo;~x>byh3O6 z&_dseKrp;R2M7GY4LUf`?qBhXRa}95&TydByWktMFb9zV+N*OMXm-y~W$g(_&RZbo zEg7Aua~x=dCrGLM5QaO0;m%=__g|QW1?W!B(aM2(c!HEL`p7y{W;hgkp*uN8D+g-9 z5vq7P1j*PFK|INsiZgYN16BWkZ=y*bByEk6vBqMr&T*j9-s2Y;`kdiFxwV514wRZ( m=-@!Hv4IW|p!da6fwm{dnYJILaol780000Px#<4Ht8R5*>Ll1)y-Fc3zcom`+Ye+f|T%94w4FBYv*YN9SsThWe~l~b!P!pJ!iRi`O41; v2Y|kl>ooAzzA*v$9@cZ8L+-d`BQ00000NkvXXu0mjfWuA9< literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/items/metaitems/clipboard/clipboard.png b/src/main/resources/assets/gregtech/textures/items/metaitems/clipboard/clipboard.png new file mode 100644 index 0000000000000000000000000000000000000000..af69676cc7f8bf0e13deb94a7179a537dfc6b821 GIT binary patch literal 495 zcmVPx#1ZP1_K>z@;j|==^1poj5MNmvsMUaq?k&%&-l9H2?lc8}uqH;Z@bwHzYKB#y@ zpl~~+bU%)cj*pLzrglN9dPS#qLaBK~pKm&zZaI{cl&gD2oozV(|NoxUo$LSr010qN zS#tmY4!{5a4!{9w)`eL_t(IPwkOgcEd0TL_y*q5fRx=oBc1fgR_7xphf5S zLyU&YnC{}%xO073)ZB)fis}q?dQf8ssP)wsFG_ue=?LF`%y}BM27`J{%(NCw$w-r7 zLv-fl1cN%!lvI6;>1s;*b3=DjSK$uZf!>a)(_|((IF{C2y?X`nkO%4pMfp7o+-boFyt=akR{0AlKa A&j0`b literal 0 HcmV?d00001 From 4db918c23997bb359dfa9eb6c51c9ba51bc4ca36 Mon Sep 17 00:00:00 2001 From: bruberu <80226372+bruberu@users.noreply.github.com> Date: Wed, 14 Jul 2021 18:05:50 -0500 Subject: [PATCH 03/42] Don't forget the buttons --- .../java/gregtech/api/gui/GuiTextures.java | 2 ++ .../items/behaviors/ClipboardBehaviour.java | 30 ++++++++++++------- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/src/main/java/gregtech/api/gui/GuiTextures.java b/src/main/java/gregtech/api/gui/GuiTextures.java index 1ed57383264..e2c775feb27 100644 --- a/src/main/java/gregtech/api/gui/GuiTextures.java +++ b/src/main/java/gregtech/api/gui/GuiTextures.java @@ -33,6 +33,8 @@ public class GuiTextures { public static final TextureArea BUTTON_SWITCH_VIEW = TextureArea.fullImage("textures/gui/widget/button_switch_view.png"); public static final TextureArea BUTTON_ALLOW_IMPORT_EXPORT = TextureArea.fullImage("textures/gui/widget/button_allow_import_export.png"); public static final TextureArea BUTTON_CLEAR_GRID = TextureArea.fullImage("textures/gui/widget/button_clear_grid.png"); + public static final TextureArea BUTTON_LEFT = TextureArea.fullImage("textures/gui/widget/left.png"); + public static final TextureArea BUTTON_RIGHT = TextureArea.fullImage("textures/gui/widget/right.png"); public static final TextureArea LOCK = TextureArea.fullImage("textures/gui/widget/lock.png"); //INDICATORS & ICONS diff --git a/src/main/java/gregtech/common/items/behaviors/ClipboardBehaviour.java b/src/main/java/gregtech/common/items/behaviors/ClipboardBehaviour.java index d2e770147f3..ce371abaf4d 100644 --- a/src/main/java/gregtech/common/items/behaviors/ClipboardBehaviour.java +++ b/src/main/java/gregtech/common/items/behaviors/ClipboardBehaviour.java @@ -2,9 +2,10 @@ import gregtech.api.gui.GuiTextures; import gregtech.api.gui.ModularUI; +import gregtech.api.gui.widgets.ClickButtonWidget; import gregtech.api.gui.widgets.ImageCycleButtonWidget; +import gregtech.api.gui.widgets.SimpleTextWidget; import gregtech.api.gui.widgets.TextFieldWidget; -import gregtech.api.gui.widgets.ToggleButtonWidget; import gregtech.api.items.gui.ItemUIFactory; import gregtech.api.items.gui.PlayerInventoryHolder; import gregtech.api.items.metaitem.stats.IItemBehaviour; @@ -33,11 +34,18 @@ public ModularUI createUI(PlayerInventoryHolder holder, EntityPlayer entityPlaye int finalI = i; builder.widget(new ImageCycleButtonWidget(5, 37 + 20 * i, 15, 15, GuiTextures.CLIPBOARD_CHECKBOX, 2, () -> getButtonState(holder, finalI), (x) -> toggleButton(holder, finalI))); - builder.widget(new TextFieldWidget(21, 40 + 20 * i, 140, 10, true, - () -> getString(holder, finalI), (x) -> setString(holder, finalI, x), 23, 8) - .setValidator((x) -> true)); + builder.widget(new TextFieldWidget(21, 40 + 20 * i, 140, 6, true, + () -> getString(holder, finalI), (x) -> setString(holder, finalI, x), 40, 5) + .setValidator((x) -> true)); } + builder.widget(new ClickButtonWidget(30, 200, 16, 16, "", (x) -> incrPageNum(holder, -1)) + .setButtonTexture(GuiTextures.BUTTON_LEFT)); + builder.widget(new ClickButtonWidget(124, 200, 16, 16, "", (x) -> incrPageNum(holder, 1)) + .setButtonTexture(GuiTextures.BUTTON_RIGHT)); + builder.widget(new SimpleTextWidget(85, 208, "", 0x000000, + () -> (getPageNum(holder) + 1) + " / " + MAX_PAGES)); + return builder.build(holder, entityPlayer); } @@ -65,15 +73,15 @@ private static void initNBT(ItemStack stack) { tagCompound = new NBTTagCompound(); tagCompound.setShort("PageIndex", (short) 0); tagCompound.setShort("TotalPages", (short) 0); - tagCompound.setString("PageTitle", ""); NBTTagCompound pageCompound = new NBTTagCompound(); pageCompound.setShort("ButStat", (short) 0); - for(int i = 0; i < 8; i++) { + pageCompound.setString("PageTitle", ""); + for (int i = 0; i < 8; i++) { pageCompound.setString("Task" + i, ""); } - for(int i = 0; i < MAX_PAGES; i++) { + for (int i = 0; i < MAX_PAGES; i++) { tagCompound.setTag("Page" + i, pageCompound.copy()); } @@ -124,17 +132,17 @@ private static void setTitle(PlayerInventoryHolder holder, String newString) { ItemStack stack = holder.getSampleItem(); if (!MetaItems.CLIPBOARD.isItemEqual(stack)) throw new IllegalArgumentException("Given item stack is not a clipboard!"); - NBTTagCompound tagCompound = stack.getTagCompound(); + NBTTagCompound tagCompound = getPageCompound(stack); assert tagCompound != null; tagCompound.setString("Title", newString); - stack.setTagCompound(tagCompound); + setPageCompound(stack, tagCompound); } private static String getTitle(PlayerInventoryHolder holder) { ItemStack stack = holder.getSampleItem(); if (!MetaItems.CLIPBOARD.isItemEqual(stack)) throw new IllegalArgumentException("Given item stack is not a clipboard!"); - NBTTagCompound tagCompound = stack.getTagCompound(); + NBTTagCompound tagCompound = getPageCompound(stack); return tagCompound.getString("Title"); } @@ -155,7 +163,7 @@ private static void incrPageNum(PlayerInventoryHolder holder, int increment) { int currentIndex = tagCompound.getInteger("PageIndex"); // Clamps currentIndex between 0 and MAX_PAGES. - tagCompound.setInteger("PageIndex", Math.max(Math.min(currentIndex + increment, MAX_PAGES), 0)); + tagCompound.setInteger("PageIndex", Math.max(Math.min(currentIndex + increment, MAX_PAGES - 1), 0)); stack.setTagCompound(tagCompound); } From c938a8db6933bdd2928f0c388664dab03e417ba8 Mon Sep 17 00:00:00 2001 From: bruberu <80226372+bruberu@users.noreply.github.com> Date: Thu, 15 Jul 2021 13:05:40 -0500 Subject: [PATCH 04/42] Remove TileEntity systems, since they're not really needed --- .../render/GTNativeTileEntityRenderer.java | 316 ----------- .../TileEntityClipboardRenderer.java | 78 --- .../tileentities/EnumShiftPosition.java | 30 -- .../common/tileentities/EnumVertPosition.java | 30 -- .../tileentities/GTNativeTileEntity.java | 493 ------------------ 5 files changed, 947 deletions(-) delete mode 100644 src/main/java/gregtech/common/render/GTNativeTileEntityRenderer.java delete mode 100644 src/main/java/gregtech/common/tileentities/EnumShiftPosition.java delete mode 100644 src/main/java/gregtech/common/tileentities/EnumVertPosition.java delete mode 100644 src/main/java/gregtech/common/tileentities/GTNativeTileEntity.java diff --git a/src/main/java/gregtech/common/render/GTNativeTileEntityRenderer.java b/src/main/java/gregtech/common/render/GTNativeTileEntityRenderer.java deleted file mode 100644 index 61fce13d597..00000000000 --- a/src/main/java/gregtech/common/render/GTNativeTileEntityRenderer.java +++ /dev/null @@ -1,316 +0,0 @@ -package gregtech.common.render; - - -import com.google.common.collect.ImmutableMap; -import gregtech.api.items.metaitem.MetaItem; -import gregtech.api.items.metaitem.stats.IItemBehaviour; -import gregtech.common.items.behaviors.ClipboardBehaviour; -import gregtech.common.tileentities.EnumShiftPosition; -import gregtech.common.tileentities.EnumVertPosition; -import gregtech.common.tileentities.GTNativeTileEntity; -import net.minecraft.block.Block; -import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.FontRenderer; -import net.minecraft.client.renderer.BufferBuilder; -import net.minecraft.client.renderer.GlStateManager; -import net.minecraft.client.renderer.RenderItem; -import net.minecraft.client.renderer.Tessellator; -import net.minecraft.client.renderer.block.model.IBakedModel; -import net.minecraft.client.renderer.block.model.ItemCameraTransforms; -import net.minecraft.client.renderer.entity.RenderManager; -import net.minecraft.client.renderer.texture.TextureAtlasSprite; -import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer; -import net.minecraft.client.renderer.vertex.DefaultVertexFormats; -import net.minecraft.init.Items; -import net.minecraft.item.ItemStack; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.EnumFacing; -import net.minecraft.util.ResourceLocation; -import net.minecraft.world.storage.MapData; -import net.minecraftforge.client.model.Attributes; -import net.minecraftforge.client.model.IModel; -import net.minecraftforge.client.model.ModelLoaderRegistry; -import net.minecraftforge.client.model.obj.OBJModel; -import net.minecraftforge.common.model.IModelState; -import org.lwjgl.opengl.GL11; - -import java.util.List; -import java.util.function.Function; - -import static gregtech.common.tileentities.EnumShiftPosition.FULL_SHIFT; -import static gregtech.common.tileentities.EnumShiftPosition.HALF_SHIFT; - -public abstract class GTNativeTileEntityRenderer extends TileEntitySpecialRenderer { - private static final ResourceLocation RES_MAP_BACKGROUND = new ResourceLocation("textures/map/map_background.png"); - - Minecraft mc = Minecraft.getMinecraft(); - - private EnumFacing angle = EnumFacing.NORTH; - - private EnumVertPosition vert = EnumVertPosition.FLOOR; - - private EnumShiftPosition shift = EnumShiftPosition.NO_SHIFT; - - public float xshift; - - public float zshift; - - public int degreeAngle; - - public double globalX; - - public double globalY; - - public double globalZ; - - public Tessellator tessellator; - - public BufferBuilder worldRenderer; - - private RenderItem itemRenderer; - - private RenderManager renderManager = Minecraft.getMinecraft().getRenderManager(); - - public void render(TileEntity tileEntity, double x, double y, double z, float tick, int destroyStage, float what) { - this.globalX = x; - this.globalY = y; - this.globalZ = z; - GTNativeTileEntity tile = (GTNativeTileEntity)tileEntity; - if (tile != null) { - this.angle = tile.getAngle(); - this.vert = tile.getVertPosition(); - this.shift = tile.getShiftPosition(); - } - - this.xshift = 0.0F; - this.zshift = 0.0F; - if (this.itemRenderer == null || this.tessellator == null || this.worldRenderer == null) { - this.itemRenderer = Minecraft.getMinecraft().getRenderItem(); - this.tessellator = Tessellator.getInstance(); - this.worldRenderer = this.tessellator.getBuffer(); - } - - float halfShift = 0.25F; - float fullShift = 0.5F; - switch(this.angle) { - case SOUTH: - this.degreeAngle = 270; - this.xshift = 1.0F; - this.zshift = 0.0F; - if (this.shift == EnumShiftPosition.FULL_SHIFT) { - this.xshift += -fullShift; - this.zshift += 0.0F; - } - - if (this.shift == EnumShiftPosition.HALF_SHIFT) { - this.xshift += -halfShift; - this.zshift += 0.0F; - } - break; - case WEST: - this.degreeAngle = 180; - this.xshift = 1.0F; - this.zshift = 1.0F; - if (this.shift == EnumShiftPosition.FULL_SHIFT) { - this.xshift += 0.0F; - this.zshift += -fullShift; - } - - if (this.shift == EnumShiftPosition.HALF_SHIFT) { - this.xshift += 0.0F; - this.zshift += -halfShift; - } - break; - case NORTH: - this.degreeAngle = 90; - this.xshift = 0.0F; - this.zshift = 1.0F; - if (this.shift == EnumShiftPosition.FULL_SHIFT) { - this.xshift += fullShift; - this.zshift += 0.0F; - } - - if (this.shift == EnumShiftPosition.HALF_SHIFT) { - this.xshift += halfShift; - this.zshift += 0.0F; - } - break; - case EAST: - this.degreeAngle = 0; - this.xshift = 0.0F; - this.zshift = 0.0F; - if (this.shift == EnumShiftPosition.FULL_SHIFT) { - this.xshift += 0.0F; - this.zshift += fullShift; - } - - if (this.shift == EnumShiftPosition.HALF_SHIFT) { - this.xshift += 0.0F; - this.zshift += halfShift; - } - } - - render(tile, x, y, z, tick); - } - - public abstract void render(GTNativeTileEntity paramBiblioTileEntity, double paramDouble1, double paramDouble2, double paramDouble3, float paramFloat); - - public EnumFacing getAngle() { - return this.angle; - } - - public EnumVertPosition getVertPosition() { - return this.vert; - } - - public EnumShiftPosition getShiftPosition() { - return this.shift; - } - - public void renderSlotItem(ItemStack stack, double x, double y, double z, float scale) { - if (stack != null && stack != ItemStack.EMPTY) { - double tx; - switch(this.angle) { - case SOUTH: - tx = x; - x = -z; - z = tx; - break; - case WEST: - x *= -1.0D; - z *= -1.0D; - break; - case NORTH: - tx = x; - x = z; - z = -tx; - case EAST: - } - - GlStateManager.pushMatrix(); - GlStateManager.color(1.0F, 1.0F, 1.0F); - GlStateManager.translate(this.globalX + x + (double)this.xshift, this.globalY + y + 0.05D, this.globalZ + z + (double)this.zshift); - GlStateManager.rotate((float)this.degreeAngle + 180.0F, 0.0F, 1.0F, 0.0F); - this.additionalGLStuffForItemStack(); - Block testBlock = Block.getBlockFromItem(stack.getItem()); - - if (stack.getItem() instanceof MetaItem && - ((MetaItem)stack.getItem()).getItem((short) stack.getItemDamage()).getBehaviours() - .stream() - .filter(behaviour -> behaviour instanceof ClipboardBehaviour) - .count() == 1 ) { - GlStateManager.rotate(90.0F, 0.0F, 1.0F, 0.0F); - GlStateManager.translate(0.4D, 0.05D, 0.0D); - } - - if (testBlock == null) { - scale *= 0.7F; - GlStateManager.rotate(180.0F, 0.0F, 1.0F, 0.0F); - } - - GlStateManager.scale(scale, scale, scale); - this.itemRenderer.renderItem(stack, ItemCameraTransforms.TransformType.FIXED); - GlStateManager.popMatrix(); - } - } - - public void additionalGLStuffForItemStack() {} - - public void renderItemMap(ItemStack stack, float x, float y, float z, float scale) { - GlStateManager.pushMatrix(); - GlStateManager.translate(this.globalX + x, this.globalY + y + 1.0199999809265137D, this.globalZ + z); - GlStateManager.rotate(90.0F, 1.0F, 0.0F, 0.0F); - scale = (float)(scale * 0.0063D); - GlStateManager.scale(scale, scale, scale); - this.mc.getTextureManager().bindTexture(RES_MAP_BACKGROUND); - Tessellator tessellator = Tessellator.getInstance(); - BufferBuilder worldrenderer = tessellator.getBuffer(); - GL11.glNormal3f(0.0F, 0.0F, -1.0F); - worldrenderer.begin(7, DefaultVertexFormats.POSITION_TEX); - worldrenderer.pos(-7.0D, 135.0D, 0.0D).tex(0.0D, 1.0D).endVertex(); - worldrenderer.pos(135.0D, 135.0D, 0.0D).tex(1.0D, 1.0D).endVertex(); - worldrenderer.pos(135.0D, -7.0D, 0.0D).tex(1.0D, 0.0D).endVertex(); - worldrenderer.pos(-7.0D, -7.0D, 0.0D).tex(0.0D, 0.0D).endVertex(); - tessellator.draw(); - MapData mapdata = Items.FILLED_MAP.getMapData(stack, getWorld()); - if (mapdata != null) - this.mc.entityRenderer.getMapItemRenderer().renderMap(mapdata, false); - GlStateManager.popMatrix(); - } - - public IBakedModel initModel(List parts, ResourceLocation modelResource) { - IModel model = null; - try { - model = ModelLoaderRegistry.getModel(modelResource); - model = model.process(ImmutableMap.of("flip-v", "true")); - } catch (Exception e) { - model = ModelLoaderRegistry.getMissingModel(); - } - OBJModel.OBJState state = new OBJModel.OBJState(parts, true); - return model.bake(state, Attributes.DEFAULT_BAKED_FORMAT, this.getModelTexture); - } - - protected Function getModelTexture = new Function() { - public TextureAtlasSprite apply(ResourceLocation location) { - return Minecraft.getMinecraft().getTextureMapBlocks().getAtlasSprite(GTNativeTileEntityRenderer.this.getTextureString(location)); - } - }; - - public String getTextureString(ResourceLocation location) { - return location.toString(); - } - - public void renderText(String text, double xAdjust, double yAdjust, double zAdjust) { - FontRenderer fontRender = this.getFontRenderer(); - float offsetx = 0.0F; - float offsetz = 0.0F; - switch(this.getAngle()) { - case SOUTH: - offsetx = -0.0116F; - break; - case WEST: - offsetz = -0.0116F; - break; - case NORTH: - offsetx = 0.0116F; - break; - case EAST: - offsetz = 0.0116F; - } - GlStateManager.pushMatrix(); - GlStateManager.translate(this.globalX + 0.5D + offsetx, this.globalY, this.globalZ + 0.5D + offsetz); - switch (getAngle()) { - case SOUTH: - GlStateManager.rotate(180.0F, 0.0F, 1.0F, 0.0F); - break; - case WEST: - GlStateManager.rotate(90.0F, 0.0F, 1.0F, 0.0F); - case NORTH: - default: - break; - case EAST: - GlStateManager.rotate(-90.0F, 0.0F, 1.0F, 0.0F); - } - GlStateManager.translate(-0.5D + xAdjust, yAdjust, zAdjust); - GlStateManager.depthMask(false); - GlStateManager.scale(0.0045F, 0.0045F, 0.0045F); - GlStateManager.rotate(270.0F, 0.0F, 1.0F, 0.0F); - GlStateManager.rotate(180.0F, 0.0F, 0.0F, 1.0F); - switch (this.shift) { - case HALF_SHIFT: - GlStateManager.translate(0.0D, 0.0D, -95.0D); - break; - case FULL_SHIFT: - GlStateManager.translate(0.0D, 0.0D, -205.0D); - break; - } - additionalGLStuffForText(); - GlStateManager.glNormal3f(0.0F, 0.0F, -0.010416667F); - fontRender.drawString(text, 0, 0, 0); - GlStateManager.depthMask(true); - GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); - GlStateManager.popMatrix(); - } - - public void additionalGLStuffForText() {} -} diff --git a/src/main/java/gregtech/common/render/clipboard/TileEntityClipboardRenderer.java b/src/main/java/gregtech/common/render/clipboard/TileEntityClipboardRenderer.java index 2c14edaf25a..5e4a2120cf4 100644 --- a/src/main/java/gregtech/common/render/clipboard/TileEntityClipboardRenderer.java +++ b/src/main/java/gregtech/common/render/clipboard/TileEntityClipboardRenderer.java @@ -1,90 +1,12 @@ package gregtech.common.render.clipboard; -/* import gregtech.api.items.metaitem.MetaItem; import gregtech.api.metatileentity.MetaTileEntity; import gregtech.api.render.MetaTileEntityRenderer; import gregtech.common.blocks.clipboard.MetaTileEntityClipboard; -import gregtech.common.tileentities.GTNativeTileEntity; import net.minecraft.client.gui.FontRenderer; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.tileentity.TileEntity; public class TileEntityClipboardRenderer extends MetaTileEntityRenderer { - private double textSpacing = -0.0658D; - - @Override - public void render(MetaTileEntity tileEntity, double paramDouble1, double paramDouble2, double paramDouble3, float paramFloat) { - MetaTileEntityClipboard tile = (MetaTileEntityClipboard) tileEntity; - if (tile != null) { - renderText(tile.titletext, 0.037D, 0.825D, 0.27D); - renderText(tile.button0text, 0.037D, 0.76D, 0.222D); - renderText(tile.button1text, 0.037D, 0.76D + 1.0D * this.textSpacing, 0.222D); - renderText(tile.button2text, 0.037D, 0.76D + 2.0D * this.textSpacing, 0.222D); - renderText(tile.button3text, 0.037D, 0.76D + 3.0D * this.textSpacing, 0.222D); - renderText(tile.button4text, 0.037D, 0.76D + 4.0D * this.textSpacing, 0.222D); - renderText(tile.button5text, 0.037D, 0.76D + 5.0D * this.textSpacing, 0.222D); - renderText(tile.button6text, 0.037D, 0.76D + 6.0D * this.textSpacing, 0.222D); - renderText(tile.button7text, 0.037D, 0.76D + 7.0D * this.textSpacing, 0.222D); - String pageNum = "" + tile.currentPage; - if (tile.currentPage > 9) { - renderText(pageNum, 0.037D, 0.17D, 0.03D); - } else { - renderText(pageNum, 0.037D, 0.17D, 0.02D); - } - } - } - - public void renderText(String text, double xAdjust, double yAdjust, double zAdjust) { - FontRenderer fontRender = this.getFontRenderer(); - float offsetx = 0.0F; - float offsetz = 0.0F; - switch(this.getAngle()) { - case SOUTH: - offsetx = -0.0116F; - break; - case WEST: - offsetz = -0.0116F; - break; - case NORTH: - offsetx = 0.0116F; - break; - case EAST: - offsetz = 0.0116F; - } - GlStateManager.pushMatrix(); - GlStateManager.translate(this.globalX + 0.5D + offsetx, this.globalY, this.globalZ + 0.5D + offsetz); - switch (getAngle()) { - case SOUTH: - GlStateManager.rotate(180.0F, 0.0F, 1.0F, 0.0F); - break; - case WEST: - GlStateManager.rotate(90.0F, 0.0F, 1.0F, 0.0F); - case NORTH: - default: - break; - case EAST: - GlStateManager.rotate(-90.0F, 0.0F, 1.0F, 0.0F); - } - GlStateManager.translate(-0.5D + xAdjust, yAdjust, zAdjust); - GlStateManager.depthMask(false); - GlStateManager.scale(0.0045F, 0.0045F, 0.0045F); - GlStateManager.rotate(270.0F, 0.0F, 1.0F, 0.0F); - GlStateManager.rotate(180.0F, 0.0F, 0.0F, 1.0F); - switch (this.shift) { - case HALF_SHIFT: - GlStateManager.translate(0.0D, 0.0D, -95.0D); - break; - case FULL_SHIFT: - GlStateManager.translate(0.0D, 0.0D, -205.0D); - break; - } - additionalGLStuffForText(); - GlStateManager.glNormal3f(0.0F, 0.0F, -0.010416667F); - fontRender.drawString(text, 0, 0, 0); - GlStateManager.depthMask(true); - GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); - GlStateManager.popMatrix(); - } } -*/ diff --git a/src/main/java/gregtech/common/tileentities/EnumShiftPosition.java b/src/main/java/gregtech/common/tileentities/EnumShiftPosition.java deleted file mode 100644 index 4d0662f076b..00000000000 --- a/src/main/java/gregtech/common/tileentities/EnumShiftPosition.java +++ /dev/null @@ -1,30 +0,0 @@ -package gregtech.common.tileentities; - -public enum EnumShiftPosition { - NO_SHIFT(0), - HALF_SHIFT(1), - FULL_SHIFT(2); - - private int ID; - - EnumShiftPosition(int ID) { - this.ID = ID; - } - - public int getID() { - return this.ID; - } - - public static EnumShiftPosition getEnumFromID(int id) { - EnumShiftPosition position = NO_SHIFT; - switch (id) { - case 1: - position = HALF_SHIFT; - break; - case 2: - position = FULL_SHIFT; - break; - } - return position; - } -} diff --git a/src/main/java/gregtech/common/tileentities/EnumVertPosition.java b/src/main/java/gregtech/common/tileentities/EnumVertPosition.java deleted file mode 100644 index abe605dfba9..00000000000 --- a/src/main/java/gregtech/common/tileentities/EnumVertPosition.java +++ /dev/null @@ -1,30 +0,0 @@ -package gregtech.common.tileentities; - -public enum EnumVertPosition { - FLOOR(0), - WALL(1), - CEILING(2); - - private int ID; - - EnumVertPosition(int ID) { - this.ID = ID; - } - - public int getID() { - return this.ID; - } - - public static EnumVertPosition getEnumFromID(int id) { - EnumVertPosition position = FLOOR; - switch (id) { - case 1: - position = WALL; - break; - case 2: - position = CEILING; - break; - } - return position; - } -} diff --git a/src/main/java/gregtech/common/tileentities/GTNativeTileEntity.java b/src/main/java/gregtech/common/tileentities/GTNativeTileEntity.java deleted file mode 100644 index f5a15df1060..00000000000 --- a/src/main/java/gregtech/common/tileentities/GTNativeTileEntity.java +++ /dev/null @@ -1,493 +0,0 @@ -package gregtech.common.tileentities; - -import net.minecraft.block.Block; -import net.minecraft.block.state.IBlockState; -import net.minecraft.entity.Entity; -import net.minecraft.entity.item.EntityItem; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.inventory.IInventory; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NBTBase; -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.nbt.NBTTagList; -import net.minecraft.network.NetworkManager; -import net.minecraft.network.play.server.SPacketUpdateTileEntity; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.EnumFacing; -import net.minecraft.util.NonNullList; -import net.minecraft.util.math.AxisAlignedBB; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; -import net.minecraftforge.items.IItemHandler; - -import javax.annotation.Nonnull; - -public abstract class GTNativeTileEntity extends TileEntity implements IInventory, IItemHandler { - private EnumFacing angle = EnumFacing.NORTH; - - private EnumShiftPosition shift = EnumShiftPosition.NO_SHIFT; - - private EnumVertPosition vertPosition = EnumVertPosition.WALL; - - public NonNullList inventory; - - private String customTexture = "none"; - - private boolean isRetexturable; - - private boolean isLocked = false; - - private String lockee = ""; - - private int renderBoxAdditionalSize = 1; - - public GTNativeTileEntity(int inventorySize, boolean canRetexture) { - this.inventory = NonNullList.withSize(inventorySize, ItemStack.EMPTY); - this.isRetexturable = canRetexture; - } - - public boolean addStackToInventoryFromWorld(ItemStack stack, int slot, EntityPlayer player) { - if (slot == -1) - return false; - boolean returnValue = false; - ItemStack currentStack = getStackInSlot(slot); - if (stack != ItemStack.EMPTY && currentStack == ItemStack.EMPTY) { - setInventorySlotContents(slot, stack); - player.inventory.setInventorySlotContents(player.inventory.currentItem, ItemStack.EMPTY); - returnValue = true; - } else if (stack != ItemStack.EMPTY && currentStack != ItemStack.EMPTY) { - ItemStack leftStack = stack.copy(); - ItemStack rightStack = currentStack.copy(); - leftStack.setCount(1); - rightStack.setCount(1); - if (getIsItemStacksEqual(leftStack, rightStack)) { - int total = stack.getCount() + currentStack.getCount(); - if (total > stack.getMaxStackSize() && currentStack.getCount() != currentStack.getMaxStackSize()) { - currentStack.setCount(stack.getMaxStackSize()); - stack.setCount(total - stack.getMaxStackSize()); - setInventorySlotContents(slot, currentStack); - player.inventory.setInventorySlotContents(player.inventory.currentItem, stack); - returnValue = true; - } else if (total <= stack.getMaxStackSize()) { - currentStack.setCount(total); - setInventorySlotContents(slot, currentStack); - player.inventory.setInventorySlotContents(player.inventory.currentItem, ItemStack.EMPTY); - returnValue = true; - } - } - if (returnValue) - getWorld().notifyBlockUpdate(getPos(), getWorld().getBlockState(getPos()), getWorld().getBlockState(getPos()), 3); - } - return returnValue; - } - - public boolean getIsItemStacksEqual(ItemStack stack1, ItemStack stack2) { - boolean output = false; - if (stack1 != ItemStack.EMPTY && stack2 != ItemStack.EMPTY) - if (stack1.getItem() == stack2.getItem() && stack1.getItemDamage() == stack2.getItemDamage()) { - NBTTagCompound tag1 = stack1.getTagCompound(); - NBTTagCompound tag2 = stack2.getTagCompound(); - if (tag1 == null && tag2 == null) { - output = true; - } else { - output = tag1.equals(tag2); - } - } - return output; - } - - public boolean addStackToInventoryFromWorldSingleStackSize(ItemStack stack, int slot, EntityPlayer player) { - boolean returnValue = false; - ItemStack currentStack = getStackInSlot(slot); - if (stack != ItemStack.EMPTY && currentStack == ItemStack.EMPTY) { - if (stack.getCount() > 1) { - ItemStack newStack = stack.copy(); - newStack.setCount(1); - stack.setCount(stack.getCount() - 1); - setInventorySlotContents(slot, newStack); - player.inventory.setInventorySlotContents(player.inventory.currentItem, stack); - } else { - setInventorySlotContents(slot, stack); - player.inventory.setInventorySlotContents(player.inventory.currentItem, ItemStack.EMPTY); - } - returnValue = true; - } - if (returnValue) - getWorld().notifyBlockUpdate(getPos(), getWorld().getBlockState(getPos()), getWorld().getBlockState(getPos()), 3); - return returnValue; - } - - public boolean removeStackFromInventoryFromWorld(int slot, EntityPlayer player, Block block) { - boolean returnValue = false; - ItemStack stack = getStackInSlot(slot); - if (stack != ItemStack.EMPTY) { - this.dropStackInSlot(this.world, slot, getPos()); - setInventorySlotContents(slot, ItemStack.EMPTY); - getWorld().notifyBlockUpdate(getPos(), getWorld().getBlockState(getPos()), getWorld().getBlockState(getPos()), 3); - returnValue = true; - } - return returnValue; - } - - public void dropStackInSlot(World world, int slot, BlockPos extractPos) { - ItemStack stack = this.getStackInSlot(slot); - if (stack != ItemStack.EMPTY && stack.getCount() > 0) { - EntityItem entityItem = new EntityItem(world, (extractPos.getX() + 0.5F), (extractPos.getY() + 0.5F), (extractPos.getZ() + 0.5F), new ItemStack(stack.getItem(), stack.getCount(), stack.getItemDamage())); - if (stack.hasTagCompound()) - entityItem.getItem().setTagCompound(stack.getTagCompound().copy()); - entityItem.motionX = 0.0D; - entityItem.motionY = 0.0D; - entityItem.motionZ = 0.0D; - world.spawnEntity(entityItem); - stack.setCount(0); - } - } - - public abstract void setInventorySlotContentsAdditionalCommands(int paramInt, ItemStack paramItemStack); - - public abstract void loadCustomNBTData(NBTTagCompound paramNBTTagCompound); - - public abstract NBTTagCompound writeCustomNBTData(NBTTagCompound paramNBTTagCompound); - - public void setAngle(EnumFacing facing) { - this.angle = facing; - getWorld().notifyBlockUpdate(getPos(), getWorld().getBlockState(getPos()), getWorld().getBlockState(getPos()), 3); - } - - public void setShiftPosition(EnumShiftPosition position) { - this.shift = position; - getWorld().notifyBlockUpdate(getPos(), getWorld().getBlockState(getPos()), getWorld().getBlockState(getPos()), 3); - } - - public void setVertPosition(EnumVertPosition position) { - this.vertPosition = position; - getWorld().notifyBlockUpdate(getPos(), getWorld().getBlockState(getPos()), getWorld().getBlockState(getPos()), 3); - } - - public EnumFacing getAngle() { - return this.angle; - } - - public EnumShiftPosition getShiftPosition() { - return this.shift; - } - - public EnumVertPosition getVertPosition() { - return this.vertPosition; - } - - public boolean canRetextureBlock() { - return this.isRetexturable; - } - - public String getCustomTextureString() { - return this.customTexture; - } - - public void setCustomTexureString(String tex) { - this.customTexture = tex; - getWorld().notifyBlockUpdate(getPos(), getWorld().getBlockState(getPos()), getWorld().getBlockState(getPos()), 3); - this.world.markBlockRangeForRenderUpdate(this.pos, this.pos); - } - - public boolean isLocked() { - return this.isLocked; - } - - public void setLocked(boolean locked) { - this.isLocked = locked; - getWorld().notifyBlockUpdate(getPos(), getWorld().getBlockState(getPos()), getWorld().getBlockState(getPos()), 3); - } - - public String getLockee() { - return this.lockee; - } - - public void setLockee(String lockeeperson) { - this.lockee = lockeeperson; - } - - public int getSizeInventory() { - return this.inventory.size(); - } - - public ItemStack getStackInSlot(int slot) { - ItemStack output = ItemStack.EMPTY; - if (slot >= 0 && slot < this.inventory.size()) - output = (ItemStack)this.inventory.get(slot); - return output; - } - - public void setInventorySlotContents(int slot, ItemStack stack) { - if (slot >= 0 && slot < this.inventory.size()) { - this.inventory.set(slot, stack); - if (stack != ItemStack.EMPTY && stack.getCount() > getInventoryStackLimit()) - stack.setCount(getInventoryStackLimit()); - setInventorySlotContentsAdditionalCommands(slot, stack); - getWorld().notifyBlockUpdate(getPos(), getWorld().getBlockState(getPos()), getWorld().getBlockState(getPos()), 3); - } - } - - public ItemStack decrStackSize(int slot, int amount) { - ItemStack stack = getStackInSlot(slot); - if (stack != ItemStack.EMPTY) - if (stack.getCount() <= amount) { - setInventorySlotContents(slot, ItemStack.EMPTY); - } else { - stack = stack.splitStack(amount); - if (stack.getCount() == 0) - setInventorySlotContents(slot, ItemStack.EMPTY); - } - return stack; - } - - public ItemStack removeStackFromSlot(int slot) { - ItemStack stack = getStackInSlot(slot); - if (stack != ItemStack.EMPTY) - setInventorySlotContents(slot, ItemStack.EMPTY); - return stack; - } - - public abstract int getInventoryStackLimit(); - - public boolean isItemValidForSlot(int slot, ItemStack itemstack) { - return true; - } - - @SideOnly(Side.CLIENT) - public AxisAlignedBB getRenderBoundingBox() { - AxisAlignedBB bb = INFINITE_EXTENT_AABB; - bb = new AxisAlignedBB(this.pos.getX(), this.pos.getY(), this.pos.getZ(), (this.pos.getX() + this.renderBoxAdditionalSize), (this.pos.getY() + this.renderBoxAdditionalSize), (this.pos.getZ() + this.renderBoxAdditionalSize)); - return bb; - } - - public void setRenderBoxAdditionalSize(int size) { - this.renderBoxAdditionalSize = size; - } - - public boolean hasCustomName() { - return false; - } - - public void openInventory(EntityPlayer player) {} - - public void closeInventory(EntityPlayer player) {} - - public int getField(int id) { - return 0; - } - - public void setField(int id, int value) {} - - public int getFieldCount() { - return 0; - } - - public void clear() {} - - public void readFromNBT(NBTTagCompound nbt) { - super.readFromNBT(nbt); - loadNBTData(nbt); - } - - public void onDataPacket(NetworkManager manager, SPacketUpdateTileEntity packet) { - NBTTagCompound nbtData = packet.getNbtCompound(); - loadNBTData(nbtData); - this.world.markBlockRangeForRenderUpdate(getPos(), getPos()); - } - - private void loadNBTData(NBTTagCompound nbt) { - NBTTagList tagList = nbt.getTagList("Inventory", 10); - this.inventory = NonNullList.withSize(getSizeInventory(), ItemStack.EMPTY); - for (int i = 0; i < tagList.tagCount(); i++) { - NBTTagCompound tag = tagList.getCompoundTagAt(i); - byte slot = tag.getByte("Slot"); - if (slot >= 0 && slot < this.inventory.size()) - this.inventory.set(slot, new ItemStack(tag)); - } - this.isLocked = nbt.getBoolean("locked"); - this.lockee = nbt.getString("lockee"); - this.angle = getFacingFromAngleID(nbt.getInteger("angle")); - this.shift = EnumShiftPosition.getEnumFromID(nbt.getInteger("shift")); - this.vertPosition = EnumVertPosition.getEnumFromID(nbt.getInteger("position")); - loadCustomNBTData(nbt); - if (this.isRetexturable) - this.customTexture = nbt.getString("customTexture"); - } - - public NBTTagCompound writeToNBT(NBTTagCompound nbt) { - super.writeToNBT(nbt); - nbt = writeNBTData(nbt); - return nbt; - } - - public SPacketUpdateTileEntity getUpdatePacket() { - NBTTagCompound dataTag = new NBTTagCompound(); - dataTag = writeNBTData(dataTag); - return new SPacketUpdateTileEntity(this.pos, 1, dataTag); - } - - public NBTTagCompound getUpdateTag() { - NBTTagCompound tags = super.getUpdateTag(); - return writeNBTData(tags); - } - - private NBTTagCompound writeNBTData(NBTTagCompound nbt) { - NBTTagList itemList = new NBTTagList(); - for (int i = 0; i < this.inventory.size(); i++) { - ItemStack stack = (ItemStack)this.inventory.get(i); - if (stack != ItemStack.EMPTY) { - NBTTagCompound tag = new NBTTagCompound(); - tag.setByte("Slot", (byte)i); - stack.writeToNBT(tag); - itemList.appendTag(tag); - } - } - nbt.setTag("Inventory", itemList); - nbt.setBoolean("locked", this.isLocked); - nbt.setString("lockee", this.lockee); - nbt.setInteger("angle", getAngleIDFromFacing(this.angle)); - nbt.setInteger("shift", this.shift.getID()); - nbt.setInteger("position", this.vertPosition.getID()); - nbt = writeCustomNBTData(nbt); - if (this.isRetexturable) - nbt.setString("customTexture", this.customTexture); - return nbt; - } - - private int getAngleIDFromFacing(EnumFacing facing) { - switch (facing) { - case WEST: - return 1; - case NORTH: - return 2; - case EAST: - return 3; - case DOWN: - return 4; - case UP: - return 5; - } - return 0; - } - - public int getAngleID() { - return getAngleIDFromFacing(getAngle()); - } - - private EnumFacing getFacingFromAngleID(int angle) { - EnumFacing face = EnumFacing.SOUTH; - switch (angle) { - case 1: - face = EnumFacing.WEST; - break; - case 2: - face = EnumFacing.NORTH; - break; - case 3: - face = EnumFacing.EAST; - break; - case 4: - face = EnumFacing.DOWN; - break; - case 5: - face = EnumFacing.UP; - break; - } - return face; - } - - public void updateSurroundingBlocks(Block blocktype) { - this.world.notifyNeighborsOfStateChange(new BlockPos(this.pos.getX(), this.pos.getY(), this.pos.getZ()), blocktype, true); - this.world.notifyNeighborsOfStateChange(new BlockPos(this.pos.getX() + 1, this.pos.getY(), this.pos.getZ()), blocktype, true); - this.world.notifyNeighborsOfStateChange(new BlockPos(this.pos.getX() - 1, this.pos.getY(), this.pos.getZ() + 1), blocktype, true); - this.world.notifyNeighborsOfStateChange(new BlockPos(this.pos.getX(), this.pos.getY(), this.pos.getZ() - 1), blocktype, true); - this.world.notifyNeighborsOfStateChange(new BlockPos(this.pos.getX(), this.pos.getY() + 1, this.pos.getZ()), blocktype, true); - this.world.notifyNeighborsOfStateChange(new BlockPos(this.pos.getX(), this.pos.getY() - 1, this.pos.getZ()), blocktype, true); - this.world.notifyNeighborsOfStateChange(new BlockPos(this.pos.getX(), this.pos.getY(), this.pos.getZ()), blocktype, true); - this.world.notifyNeighborsOfStateChange(new BlockPos(this.pos.getX() + 2, this.pos.getY(), this.pos.getZ()), blocktype, true); - this.world.notifyNeighborsOfStateChange(new BlockPos(this.pos.getX() - 2, this.pos.getY(), this.pos.getZ()), blocktype, true); - this.world.notifyNeighborsOfStateChange(new BlockPos(this.pos.getX(), this.pos.getY(), this.pos.getZ() + 2), blocktype, true); - this.world.notifyNeighborsOfStateChange(new BlockPos(this.pos.getX(), this.pos.getY(), this.pos.getZ() - 2), blocktype, true); - this.world.notifyNeighborsOfStateChange(new BlockPos(this.pos.getX(), this.pos.getY() + 2, this.pos.getZ()), blocktype, true); - this.world.notifyNeighborsOfStateChange(new BlockPos(this.pos.getX(), this.pos.getY() - 2, this.pos.getZ()), blocktype, true); - getWorld().notifyBlockUpdate(getPos(), getWorld().getBlockState(getPos()), getWorld().getBlockState(getPos()), 3); - } - - public boolean shouldRefresh(@Nonnull World world, @Nonnull BlockPos pos, @Nonnull IBlockState oldState, @Nonnull IBlockState newState) { - return true; - } - - public boolean isEmpty() { - boolean output = true; - for (ItemStack itemStack : this.inventory) { - if (itemStack != ItemStack.EMPTY) { - output = false; - break; - } - } - return output; - } - - public boolean isUsableByPlayer(@Nonnull EntityPlayer player) { - return (this.world.getTileEntity(this.pos) == this && player.getDistanceSq(this.pos.getX() + 0.5D, this.pos.getY() + 0.5D, this.pos.getZ() + 0.5D) < 64.0D); - } - - public int getSlots() { - return this.inventory.size(); - } - - @Nonnull - public ItemStack insertItem(int slot, @Nonnull ItemStack stack, boolean simulate) { - ItemStack returnStack = stack; - if (slot < this.inventory.size()) { - ItemStack currentSlot = getStackInSlot(slot); - if (currentSlot != ItemStack.EMPTY) { - if (stack.getItem() == currentSlot.getItem() && currentSlot.getCount() < currentSlot.getMaxStackSize()) - if (!simulate) { - int count = currentSlot.getCount() + stack.getCount(); - if (count > stack.getMaxStackSize()) { - currentSlot.setCount(currentSlot.getMaxStackSize()); - setInventorySlotContents(slot, currentSlot); - returnStack = stack.copy(); - returnStack.setCount(count - currentSlot.getMaxStackSize()); - } else { - stack.setCount(count); - setInventorySlotContents(slot, stack); - returnStack = ItemStack.EMPTY; - } - } - } else if (!simulate) { - setInventorySlotContents(slot, stack); - returnStack = ItemStack.EMPTY; - } - } - return returnStack; - } - - @Nonnull - public ItemStack extractItem(int slot, int amount, boolean simulate) { - ItemStack result = ItemStack.EMPTY; - if (slot < this.inventory.size()) { - ItemStack slottedStack = getStackInSlot(slot); - if (slottedStack != ItemStack.EMPTY && !simulate) { - result = slottedStack.copy(); - if (amount >= slottedStack.getCount()) { - setInventorySlotContents(slot, ItemStack.EMPTY); - } else { - result.setCount(amount); - slottedStack.setCount(slottedStack.getCount() - amount); - setInventorySlotContents(slot, slottedStack); - } - } - } - return result; - } - - public int getSlotLimit(int slot) { - return 64; - } -} From d5dbe3a3329ae027673025022a25eaff37eedc2d Mon Sep 17 00:00:00 2001 From: bruberu <80226372+bruberu@users.noreply.github.com> Date: Sat, 17 Jul 2021 16:52:39 -0500 Subject: [PATCH 05/42] Wait, this shouldn't be an MTE :thonk: --- src/main/java/gregtech/GregTechMod.java | 2 + .../MetaTileEntityUIFactory.java | 1 - .../java/gregtech/api/util/GTUtility.java | 11 + .../java/gregtech/common/ClientProxy.java | 2 + .../gregtech/common/blocks/MetaBlocks.java | 6 + .../blocks/clipboard/BlockClipboard.java | 256 ++++++---------- .../clipboard/MetaTileEntityClipboard.java | 289 ------------------ .../blocks/clipboard/TileEntityClipboard.java | 65 ++++ .../TileEntityClipboardUIFactory.java | 37 +++ .../items/behaviors/ClipboardBehaviour.java | 4 +- .../metatileentities/MetaTileEntities.java | 5 +- .../MetaTileEntityClipboard.java | 68 ----- .../TileEntityClipboardRenderer.java | 74 ++++- .../gregtech/models/block/clipboard.json | 46 +-- 14 files changed, 312 insertions(+), 554 deletions(-) delete mode 100644 src/main/java/gregtech/common/blocks/clipboard/MetaTileEntityClipboard.java create mode 100644 src/main/java/gregtech/common/blocks/clipboard/TileEntityClipboard.java create mode 100644 src/main/java/gregtech/common/blocks/clipboard/TileEntityClipboardUIFactory.java delete mode 100644 src/main/java/gregtech/common/metatileentities/MetaTileEntityClipboard.java diff --git a/src/main/java/gregtech/GregTechMod.java b/src/main/java/gregtech/GregTechMod.java index 23de8084032..9381954931e 100644 --- a/src/main/java/gregtech/GregTechMod.java +++ b/src/main/java/gregtech/GregTechMod.java @@ -23,6 +23,7 @@ import gregtech.common.MetaEntities; import gregtech.common.MetaFluids; import gregtech.common.blocks.MetaBlocks; +import gregtech.common.blocks.clipboard.TileEntityClipboardUIFactory; import gregtech.common.blocks.modelfactories.BlockCompressedFactory; import gregtech.common.blocks.modelfactories.BlockFrameFactory; import gregtech.common.blocks.modelfactories.BlockOreFactory; @@ -73,6 +74,7 @@ public void onPreInit(FMLPreInitializationEvent event) { MetaTileEntityUIFactory.INSTANCE.init(); PlayerInventoryUIFactory.INSTANCE.init(); CoverBehaviorUIFactory.INSTANCE.init(); + TileEntityClipboardUIFactory.INSTANCE.init(); SimpleCapabilityManager.init(); OreDictUnifier.init(); NBTUtil.registerSerializers(); diff --git a/src/main/java/gregtech/api/metatileentity/MetaTileEntityUIFactory.java b/src/main/java/gregtech/api/metatileentity/MetaTileEntityUIFactory.java index f3351548a03..6a73f9f16c6 100644 --- a/src/main/java/gregtech/api/metatileentity/MetaTileEntityUIFactory.java +++ b/src/main/java/gregtech/api/metatileentity/MetaTileEntityUIFactory.java @@ -25,7 +25,6 @@ public void init() { } @Override - @SuppressWarnings("unchecked") protected ModularUI createUITemplate(MetaTileEntityHolder holder, EntityPlayer entityPlayer) { return holder.getMetaTileEntity().createUI(entityPlayer); } diff --git a/src/main/java/gregtech/api/util/GTUtility.java b/src/main/java/gregtech/api/util/GTUtility.java index 9c8e42fef22..9caf05081fd 100644 --- a/src/main/java/gregtech/api/util/GTUtility.java +++ b/src/main/java/gregtech/api/util/GTUtility.java @@ -897,4 +897,15 @@ public static boolean isFluidStackAmountDivisible(FluidStack fluidStack, int div public static boolean isItemStackCountDivisible(ItemStack itemStack, int divisor) { return itemStack.getCount() % divisor == 0 && itemStack.getCount() % divisor != itemStack.getCount() && itemStack.getCount() / divisor != 0; } + + public static AxisAlignedBB rotateAroundYAxis(AxisAlignedBB aabb, EnumFacing from, EnumFacing to) { + if(from == EnumFacing.UP || from == EnumFacing.DOWN || to == EnumFacing.UP || to == EnumFacing.DOWN) + throw new IllegalArgumentException("Either the second or third parameters were EnumFacing.DOWN or EnumFacing.UP."); + AxisAlignedBB rotatedAABB = new AxisAlignedBB(aabb.minX, aabb.minY, aabb.minZ, aabb.maxX, aabb.maxY, aabb.maxZ); + while(from != to) { + from.rotateY(); + rotatedAABB = new AxisAlignedBB(1 - rotatedAABB.maxZ, rotatedAABB.minY, rotatedAABB.minX, 1 - rotatedAABB.minZ, rotatedAABB.maxY, rotatedAABB.maxX); + } + return rotatedAABB; + } } diff --git a/src/main/java/gregtech/common/ClientProxy.java b/src/main/java/gregtech/common/ClientProxy.java index 2541cd446fa..c15ea8c2b15 100644 --- a/src/main/java/gregtech/common/ClientProxy.java +++ b/src/main/java/gregtech/common/ClientProxy.java @@ -20,6 +20,7 @@ import gregtech.common.render.CableRenderer; import gregtech.common.render.FluidPipeRenderer; import gregtech.common.render.StoneRenderer; +import gregtech.common.render.clipboard.TileEntityClipboardRenderer; import net.minecraft.block.BlockColored; import net.minecraft.block.state.IBlockState; import net.minecraft.client.Minecraft; @@ -100,6 +101,7 @@ public void onPreLoad() { CableRenderer.preInit(); FluidPipeRenderer.preInit(); StoneRenderer.preInit(); + TileEntityClipboardRenderer.preInit(); MetaEntities.initRenderers(); TextureUtils.addIconRegister(MetaFluids::registerSprites); MinecraftForge.EVENT_BUS.register(ToolRenderHandler.INSTANCE); diff --git a/src/main/java/gregtech/common/blocks/MetaBlocks.java b/src/main/java/gregtech/common/blocks/MetaBlocks.java index 9bbc9dc8912..d1e3402fc96 100644 --- a/src/main/java/gregtech/common/blocks/MetaBlocks.java +++ b/src/main/java/gregtech/common/blocks/MetaBlocks.java @@ -16,6 +16,8 @@ import gregtech.api.unification.material.type.SolidMaterial; import gregtech.api.unification.ore.OrePrefix; import gregtech.api.unification.ore.StoneType; +import gregtech.common.blocks.clipboard.BlockClipboard; +import gregtech.common.blocks.clipboard.TileEntityClipboard; import gregtech.common.blocks.foam.BlockFoam; import gregtech.common.blocks.foam.BlockPetrifiedFoam; import gregtech.common.blocks.modelfactories.BakedModelHandler; @@ -104,6 +106,7 @@ private MetaBlocks() { public static BlockGregSapling SAPLING; public static BlockSurfaceRock SURFACE_ROCK; + public static BlockClipboard CLIPBOARD_BLOCK; public static Map COMPRESSED = new HashMap<>(); public static Map FRAMES = new HashMap<>(); @@ -167,6 +170,8 @@ public static void init() { SURFACE_ROCK = new BlockSurfaceRock(); SURFACE_ROCK.setRegistryName("surface_rock_new"); + CLIPBOARD_BLOCK = new BlockClipboard(); + CLIPBOARD_BLOCK.setRegistryName("gt_clipboard"); StoneType.init(); @@ -280,6 +285,7 @@ public static void registerTileEntity() { GameRegistry.registerTileEntity(TileEntityFluidPipe.class, new ResourceLocation(GTValues.MODID, "fluid_pipe")); GameRegistry.registerTileEntity(TileEntityFluidPipeTickable.class, new ResourceLocation(GTValues.MODID, "fluid_pipe_active")); GameRegistry.registerTileEntity(TileEntitySurfaceRock.class, new ResourceLocation(GTValues.MODID, "surface_rock")); + GameRegistry.registerTileEntity(TileEntityClipboard.class, new ResourceLocation(GTValues.MODID, "clipboard")); } @SideOnly(Side.CLIENT) diff --git a/src/main/java/gregtech/common/blocks/clipboard/BlockClipboard.java b/src/main/java/gregtech/common/blocks/clipboard/BlockClipboard.java index a6f75b7b65a..0aefe0eb490 100644 --- a/src/main/java/gregtech/common/blocks/clipboard/BlockClipboard.java +++ b/src/main/java/gregtech/common/blocks/clipboard/BlockClipboard.java @@ -1,196 +1,130 @@ package gregtech.common.blocks.clipboard; -/* +import gregtech.api.metatileentity.MetaTileEntityHolder; +import gregtech.api.util.GTUtility; +import gregtech.common.render.clipboard.TileEntityClipboardRenderer; +import net.minecraft.block.Block; +import net.minecraft.block.ITileEntityProvider; +import net.minecraft.block.SoundType; +import net.minecraft.block.material.Material; +import net.minecraft.block.state.BlockFaceShape; +import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.EnumBlockRenderType; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.NonNullList; import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.RayTraceResult; +import net.minecraft.world.IBlockAccess; +import net.minecraft.world.World; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; -public class BlockClipboard extends BiblioBlock { - public static final String name = "Clipboard"; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; - public static final BlockClipboard instance = new BlockClipboard(); +public class BlockClipboard extends Block implements ITileEntityProvider { + + private static final AxisAlignedBB CLIPBOARD_AABB = new AxisAlignedBB(5.25 / 16.0, 0.0, 0.0, 5.5 / 16.0, 8.0 / 16.0, 0.3 / 16.0); + + protected ThreadLocal tileEntities = new ThreadLocal<>(); public BlockClipboard() { - super(Material.WOOD, SoundType.WOOD, null, "Clipboard"); + super(Material.WOOD); + setHardness(1.5f); + setSoundType(SoundType.WOOD); + setTranslationKey("clipboard"); + setLightOpacity(1); + setHarvestLevel("pickaxe", 1); } - public List getDrops(IBlockAccess world, BlockPos pos, IBlockState state, int fortune) { - return new ArrayList<>(); + @Override + @Nonnull + public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos) { + return GTUtility.rotateAroundYAxis(CLIPBOARD_AABB, EnumFacing.NORTH, getTileEntity(source, pos).getFrontFacing()); } - public boolean onBlockActivatedCustomCommands(World world, BlockPos pos, IBlockState state, EntityPlayer player, EnumFacing face, float hitX, float hitY, float hitZ) { - if (player.isSneaking() && !world.isRemote) { - dropStackInSlot(world, pos, 0, pos); - world.setBlockToAir(pos); - return true; - } - if (!player.isSneaking() && world.isRemote) { - TileEntity tile = world.getTileEntity(pos); - if (tile != null && tile instanceof MetaTileEntityClipboard) { - MetaTileEntityClipboard clipboard = (MetaTileEntityClipboard)tile; - int updatePos = getSelectionPointFromFace(face, hitX, hitY, hitZ); - ByteBuf buffer = Unpooled.buffer(); - buffer.writeInt(pos.getX()); - buffer.writeInt(pos.getY()); - buffer.writeInt(pos.getZ()); - buffer.writeInt(updatePos); - BiblioCraft.ch_BiblioClipboard.sendToServer(new FMLProxyPacket(new PacketBuffer(buffer), "BiblioClipboard")); - return true; - } + private ItemStack getDropStack(IBlockAccess blockAccess, BlockPos pos, IBlockState blockState) { + if(this.hasTileEntity(blockState)) { + return this.tileEntities.get().getMetaTileEntity().getItemInventory().getStackInSlot(0); } - return false; + return ItemStack.EMPTY; } - private int getSelectionPointFromFace(EnumFacing face, float hitx, float hity, float hitz) { - switch (face) { - case NORTH: - return getSelectionPoint(1.0F - hitx, 1.0F - hity); - case SOUTH: - return getSelectionPoint(hitx, 1.0F - hity); - case WEST: - return getSelectionPoint(hitz, 1.0F - hity); - case EAST: - return getSelectionPoint(1.0F - hitz, 1.0F - hity); - } - return -1; + @Override + @Nonnull + public ItemStack getPickBlock(IBlockState state, RayTraceResult target, World world, BlockPos pos, EntityPlayer player) { + return getDropStack(world, pos, state); } - private int getSelectionPoint(float x, float y) { - if (x > 0.21F && x < 0.272F) { - float spacing = 0.0655F; - for (int i = 0; i < 9; i++) { - if (y > 0.23D + (i * spacing) && y < 0.285F + i * spacing) - return i; - } - } - if (y > 0.83D && y < 0.868F) { - if (x > 0.296F && x < 0.387F) - return 10; - if (x > 0.599F && x < 0.843F) - return 11; - } - return -1; + @Override + public void getDrops(NonNullList drops, IBlockAccess world, BlockPos pos, IBlockState state, int fortune) { + drops.add(this.getDropStack(world, pos, state)); } - public TileEntity createNewTileEntity(World worldIn, int meta) { - return (TileEntity)new MetaTileEntityClipboard(); + @Override + public boolean isFullCube(IBlockState state) { + return false; } - public List getModelParts(BiblioTileEntity tile) { - List modelParts = new ArrayList<>(); - modelParts.add("Clipboard"); - if (tile instanceof MetaTileEntityClipboard) { - MetaTileEntityClipboard clipboard = (MetaTileEntityClipboard)tile; - clipboard.getNBTData(); - switch (clipboard.button0state) { - case 1: - modelParts.add("box1c"); - break; - case 2: - modelParts.add("box1x"); - break; - } - switch (clipboard.button1state) { - case 1: - modelParts.add("box2c"); - break; - case 2: - modelParts.add("box2x"); - break; - } - switch (clipboard.button2state) { - case 1: - modelParts.add("box3c"); - break; - case 2: - modelParts.add("box3x"); - break; - } - switch (clipboard.button3state) { - case 1: - modelParts.add("box4c"); - break; - case 2: - modelParts.add("box4x"); - break; - } - switch (clipboard.button4state) { - case 1: - modelParts.add("box5c"); - break; - case 2: - modelParts.add("box5x"); - break; - } - switch (clipboard.button5state) { - case 1: - modelParts.add("box6c"); - break; - case 2: - modelParts.add("box6x"); - break; - } - switch (clipboard.button6state) { - case 1: - modelParts.add("box7c"); - break; - case 2: - modelParts.add("box7x"); - break; - } - switch (clipboard.button7state) { - case 1: - modelParts.add("box8c"); - break; - case 2: - modelParts.add("box8x"); - break; - } - } - return modelParts; + @Override + public boolean isOpaqueCube(IBlockState state) { + return false; } - public void additionalPlacementCommands(BiblioTileEntity biblioTile, EntityLivingBase player) {} + @Override + @Nonnull + @SideOnly(Side.CLIENT) + public EnumBlockRenderType getRenderType(IBlockState state) { + return TileEntityClipboardRenderer.BLOCK_RENDER_TYPE; + } - public ItemStack getPickBlockExtras(ItemStack stack, World world, BlockPos pos) { - return stack; + @Override + public void neighborChanged(IBlockState state, World worldIn, BlockPos pos, Block blockIn, BlockPos fromPos) { + EnumFacing directionHangedFrom = getTileEntity(worldIn, pos).getFrontFacing().getOpposite(); + if (pos.offset(directionHangedFrom).equals(fromPos)) { + if (worldIn.getBlockState(fromPos).getBlockFaceShape(worldIn, fromPos, EnumFacing.UP) != BlockFaceShape.SOLID) { + worldIn.destroyBlock(pos, true); + } + } } - public ExtendedBlockState getExtendedBlockStateAlternate(ExtendedBlockState state) { - return state; + @Override + @Nonnull + public BlockFaceShape getBlockFaceShape(IBlockAccess worldIn, IBlockState state, BlockPos pos, EnumFacing face) { + return BlockFaceShape.UNDEFINED; } - public IExtendedBlockState getIExtendedBlockStateAlternate(BiblioTileEntity biblioTile, IExtendedBlockState state) { - return state; + @Override + public void breakBlock(World worldIn, BlockPos pos, IBlockState state) { + TileEntityClipboard tileEntity = getTileEntity(worldIn, pos); + if (tileEntity != null) { + tileEntities.set(tileEntity.getHolder()); + } + + super.breakBlock(worldIn, pos, state); } - public TRSRTransformation getAdditionalTransforms(TRSRTransformation transform, BiblioTileEntity tile) { - return transform; + @Override + public void harvestBlock(World worldIn, EntityPlayer player, BlockPos pos, IBlockState state, @Nullable TileEntity te, ItemStack stack) { + tileEntities.set(te == null ? tileEntities.get() : (MetaTileEntityHolder) te); + super.harvestBlock(worldIn, player, pos, state, te, stack); + tileEntities.set(null); } - public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess blockAccess, BlockPos pos) { - AxisAlignedBB output = getBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F); - TileEntity tile = blockAccess.getTileEntity(pos); - if (tile != null && tile instanceof MetaTileEntityClipboard) { - MetaTileEntityClipboard clipboard = (MetaTileEntityClipboard)tile; - switch (clipboard.getAngle()) { - case SOUTH: - output = getBlockBounds(0.97F, 0.08F, 0.15F, 1.0F, 0.92F, 0.85F); - break; - case WEST: - output = getBlockBounds(0.15F, 0.08F, 0.97F, 0.85F, 0.92F, 1.0F); - break; - case NORTH: - output = getBlockBounds(0.0F, 0.08F, 0.15F, 0.03F, 0.92F, 0.85F); - break; - case EAST: - output = getBlockBounds(0.15F, 0.08F, 0.0F, 0.85F, 0.92F, 0.03F); - break; - } - } - return output; + public static TileEntityClipboard getTileEntity(IBlockAccess world, BlockPos pos) { + TileEntity tileEntity = world.getTileEntity(pos); + if (tileEntity instanceof MetaTileEntityHolder) + return (TileEntityClipboard) ((MetaTileEntityHolder) tileEntity).getMetaTileEntity(); + return null; } - public IBlockState getFinalBlockstate(IBlockState state, IBlockState newState) { - return newState; + @Nullable + @Override + public TileEntity createNewTileEntity(World worldIn, int meta) { + return new MetaTileEntityHolder(); } } -*/ diff --git a/src/main/java/gregtech/common/blocks/clipboard/MetaTileEntityClipboard.java b/src/main/java/gregtech/common/blocks/clipboard/MetaTileEntityClipboard.java deleted file mode 100644 index a700f1bc389..00000000000 --- a/src/main/java/gregtech/common/blocks/clipboard/MetaTileEntityClipboard.java +++ /dev/null @@ -1,289 +0,0 @@ -package gregtech.common.blocks.clipboard; - -import gregtech.api.gui.ModularUI; -import gregtech.api.metatileentity.MetaTileEntity; -import gregtech.api.metatileentity.MetaTileEntityHolder; -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.ResourceLocation; -import net.minecraft.util.text.ITextComponent; -import net.minecraft.util.text.TextComponentString; -import net.minecraftforge.items.IItemHandler; - -public class MetaTileEntityClipboard extends MetaTileEntity { - public int button0state = 0; - - public int button1state = 0; - - public int button2state = 0; - - public int button3state = 0; - - public int button4state = 0; - - public int button5state = 0; - - public int button6state = 0; - - public int button7state = 0; - - public String button0text = " "; - - public String button1text = " "; - - public String button2text = " "; - - public String button3text = " "; - - public String button4text = " "; - - public String button5text = " "; - - public String button6text = " "; - - public String button7text = " "; - - public String titletext = " "; - - public int currentPage = 1; - - public int totalPages = 1; - - public MetaTileEntityClipboard(ResourceLocation metaTileEntityId) { - super(metaTileEntityId); - } - - public void updateClipboardFromPlayerSelection(int selection) { - if (selection >= 0 && selection <= 8) { - checkCheckBox(selection); - } else if (selection == 10) { - changePage(false); - } else if (selection == 11) { - changePage(true); - } - getWorld().notifyBlockUpdate(getPos(), getWorld().getBlockState(getPos()), getWorld().getBlockState(getPos()), 3); - } - - public void checkCheckBox(int box) { - switch (box) { - case 0: - if (this.button0state >= 2) { - this.button0state = 0; - break; - } - this.button0state++; - break; - case 1: - if (this.button1state >= 2) { - this.button1state = 0; - break; - } - this.button1state++; - break; - case 2: - if (this.button2state >= 2) { - this.button2state = 0; - break; - } - this.button2state++; - break; - case 3: - if (this.button3state >= 2) { - this.button3state = 0; - break; - } - this.button3state++; - break; - case 4: - if (this.button4state >= 2) { - this.button4state = 0; - break; - } - this.button4state++; - break; - case 5: - if (this.button5state >= 2) { - this.button5state = 0; - break; - } - this.button5state++; - break; - case 6: - if (this.button6state >= 2) { - this.button6state = 0; - break; - } - this.button6state++; - break; - case 7: - if (this.button7state >= 2) { - this.button7state = 0; - break; - } - this.button7state++; - break; - } - ItemStack clipStack = itemInventory.getStackInSlot(0); - if (clipStack != ItemStack.EMPTY) { - NBTTagCompound cliptags = clipStack.getTagCompound(); - if (cliptags != null) { - String pagenum = "page" + cliptags.getInteger("currentPage"); - NBTTagCompound pagetag = cliptags.getCompoundTag(pagenum); - if (pagetag != null) { - int[] taskstat = pagetag.getIntArray("taskStates"); - taskstat[0] = this.button0state; - taskstat[1] = this.button1state; - taskstat[2] = this.button2state; - taskstat[3] = this.button3state; - taskstat[4] = this.button4state; - taskstat[5] = this.button5state; - taskstat[6] = this.button6state; - taskstat[7] = this.button7state; - pagetag.setIntArray("taskStates", taskstat); - clipStack.setTagCompound(cliptags); - itemInventory.extractItem(0, 1, false); - itemInventory.insertItem(0, clipStack, false); - getNBTData(); - getWorld().notifyBlockUpdate(getPos(), getWorld().getBlockState(getPos()), getWorld().getBlockState(getPos()), 3); - } - } - } - } - - - public void changePage(boolean nextPage) { - if (nextPage) { - if (this.currentPage < this.totalPages) - this.currentPage++; - } else if (this.currentPage > 1) { - this.currentPage--; - } - ItemStack clipStack = itemInventory.getStackInSlot(0); - if (clipStack != ItemStack.EMPTY) { - NBTTagCompound cliptags = clipStack.getTagCompound(); - if (cliptags != null) { - String pagenum = "page" + this.currentPage; - NBTTagCompound pagetag = cliptags.getCompoundTag(pagenum); - if (pagetag != null) { - cliptags.setInteger("currentPage", this.currentPage); - clipStack.setTagCompound(cliptags); - itemInventory.extractItem(0, 1, false); - itemInventory.insertItem(0, clipStack, false); - getNBTData(); - getWorld().notifyBlockUpdate(getPos(), getWorld().getBlockState(getPos()), getWorld().getBlockState(getPos()), 3); - } - } - } - } - - public void getNBTData() { - ItemStack clipStack = itemInventory.getStackInSlot(0); - if (clipStack != ItemStack.EMPTY) { - NBTTagCompound cliptags = clipStack.getTagCompound(); - if (cliptags != null) { - this.currentPage = cliptags.getInteger("currentPage"); - this.totalPages = cliptags.getInteger("totalPages"); - String pagenum = "page" + this.currentPage; - NBTTagCompound pagetag = cliptags.getCompoundTag(pagenum); - if (pagetag != null) { - int[] taskstat = pagetag.getIntArray("taskStates"); - if (taskstat.length > 0) { - this.button0state = taskstat[0]; - this.button1state = taskstat[1]; - this.button2state = taskstat[2]; - this.button3state = taskstat[3]; - this.button4state = taskstat[4]; - this.button5state = taskstat[5]; - this.button6state = taskstat[6]; - this.button7state = taskstat[7]; - } - NBTTagCompound tasks = pagetag.getCompoundTag("tasks"); - this.button0text = tasks.getString("task1"); - this.button1text = tasks.getString("task2"); - this.button2text = tasks.getString("task3"); - this.button3text = tasks.getString("task4"); - this.button4text = tasks.getString("task5"); - this.button5text = tasks.getString("task6"); - this.button6text = tasks.getString("task7"); - this.button7text = tasks.getString("task8"); - this.titletext = pagetag.getString("title"); - } - } - } - } - - public int getInventoryStackLimit() { - return 1; - } - - public boolean isItemValidForSlot(int slot, ItemStack itemstack) { - return false; - } - - public String getName() { - return "Clipboard"; - } - - public void setInventorySlotContentsAdditionalCommands(int slot, ItemStack stack) {} - - public void loadCustomNBTData(NBTTagCompound nbt) { - this.button0state = nbt.getInteger("button0state"); - this.button1state = nbt.getInteger("button1state"); - this.button2state = nbt.getInteger("button2state"); - this.button3state = nbt.getInteger("button3state"); - this.button4state = nbt.getInteger("button4state"); - this.button5state = nbt.getInteger("button5state"); - this.button6state = nbt.getInteger("button6state"); - this.button7state = nbt.getInteger("button7state"); - this.button0text = nbt.getString("button0text"); - this.button1text = nbt.getString("button1text"); - this.button2text = nbt.getString("button2text"); - this.button3text = nbt.getString("button3text"); - this.button4text = nbt.getString("button4text"); - this.button5text = nbt.getString("button5text"); - this.button6text = nbt.getString("button6text"); - this.button7text = nbt.getString("button7text"); - this.currentPage = nbt.getInteger("currentPage"); - this.totalPages = nbt.getInteger("totalPages"); - this.titletext = nbt.getString("titletext"); - } - - public NBTTagCompound writeCustomNBTData(NBTTagCompound nbt) { - nbt.setInteger("button0state", this.button0state); - nbt.setInteger("button1state", this.button1state); - nbt.setInteger("button2state", this.button2state); - nbt.setInteger("button3state", this.button3state); - nbt.setInteger("button4state", this.button4state); - nbt.setInteger("button5state", this.button5state); - nbt.setInteger("button6state", this.button6state); - nbt.setInteger("button7state", this.button7state); - nbt.setString("button0text", this.button0text); - nbt.setString("button1text", this.button1text); - nbt.setString("button2text", this.button2text); - nbt.setString("button3text", this.button3text); - nbt.setString("button4text", this.button4text); - nbt.setString("button5text", this.button5text); - nbt.setString("button6text", this.button6text); - nbt.setString("button7text", this.button7text); - nbt.setInteger("currentPage", this.currentPage); - nbt.setInteger("totalPages", this.totalPages); - nbt.setString("titletext", this.titletext); - return nbt; - } - - public ITextComponent getDisplayName() { - return (ITextComponent)new TextComponentString(getName()); - } - - @Override - public MetaTileEntity createMetaTileEntity(MetaTileEntityHolder holder) { - return null; - } - - @Override - protected ModularUI createUI(EntityPlayer entityPlayer) { - return null; - } -} diff --git a/src/main/java/gregtech/common/blocks/clipboard/TileEntityClipboard.java b/src/main/java/gregtech/common/blocks/clipboard/TileEntityClipboard.java new file mode 100644 index 00000000000..4f2a151218e --- /dev/null +++ b/src/main/java/gregtech/common/blocks/clipboard/TileEntityClipboard.java @@ -0,0 +1,65 @@ +package gregtech.common.blocks.clipboard; + +import codechicken.lib.raytracer.CuboidRayTraceResult; +import codechicken.lib.render.CCRenderState; +import codechicken.lib.vec.Matrix4; +import gregtech.api.capability.impl.FluidHandlerProxy; +import gregtech.api.gui.IUIHolder; +import gregtech.api.gui.ModularUI; +import gregtech.api.items.gui.PlayerInventoryHolder; +import gregtech.api.items.itemhandlers.InaccessibleItemStackHandler; +import gregtech.api.items.metaitem.MetaItem; +import gregtech.api.items.metaitem.stats.IItemBehaviour; +import gregtech.api.metatileentity.MetaTileEntity; +import gregtech.api.metatileentity.MetaTileEntityHolder; +import gregtech.common.items.behaviors.ClipboardBehaviour; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.BlockRenderLayer; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.EnumHand; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.items.ItemStackHandler; + +import java.util.List; +import java.util.Optional; + +import static gregtech.common.items.MetaItems.CLIPBOARD; + +public class TileEntityClipboard extends TileEntity, implements IUIHolder { + + private ItemStack clipboardStack; + protected EnumFacing frontFacing = EnumFacing.NORTH; + + protected ModularUI createUI(EntityPlayer entityPlayer) { + if(clipboardStack == ItemStack.EMPTY) { + clipboardStack = CLIPBOARD.getStackForm(); + } + if(clipboardStack.isItemEqual(CLIPBOARD.getStackForm())) { + List behaviours = ((MetaItem) clipboardStack.getItem()).getBehaviours(clipboardStack); + Optional clipboardBehaviour = behaviours.stream().filter((x) -> x instanceof ClipboardBehaviour).findFirst(); + if(!clipboardBehaviour.isPresent()) + return null; + if(clipboardBehaviour.get() instanceof ClipboardBehaviour) { + return ((ClipboardBehaviour) clipboardBehaviour.get()).createUI(new PlayerInventoryHolder(entityPlayer, entityPlayer.getActiveHand(), clipboardStack), entityPlayer); + } + } + return null; + } + + @Override + public boolean isValid() { + return false; + } + + @Override + public boolean isRemote() { + return false; + } + + @Override + public void markAsDirty() { + + } +} diff --git a/src/main/java/gregtech/common/blocks/clipboard/TileEntityClipboardUIFactory.java b/src/main/java/gregtech/common/blocks/clipboard/TileEntityClipboardUIFactory.java new file mode 100644 index 00000000000..e52a4d91b0d --- /dev/null +++ b/src/main/java/gregtech/common/blocks/clipboard/TileEntityClipboardUIFactory.java @@ -0,0 +1,37 @@ +package gregtech.common.blocks.clipboard; + +import gregtech.api.GTValues; +import gregtech.api.gui.ModularUI; +import gregtech.api.gui.UIFactory; +import gregtech.api.metatileentity.MetaTileEntityHolder; +import gregtech.api.metatileentity.MetaTileEntityUIFactory; +import net.minecraft.client.Minecraft; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.network.PacketBuffer; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +public class TileEntityClipboardUIFactory extends UIFactory { + public static final TileEntityClipboardUIFactory INSTANCE = new TileEntityClipboardUIFactory(); + + public void init() { + UIFactory.FACTORY_REGISTRY.register(3, new ResourceLocation(GTValues.MODID, "clipboard_factory"), this); + } + + @Override + protected ModularUI createUITemplate(TileEntityClipboard clipboard, EntityPlayer entityPlayer) { + return clipboard.createUI(entityPlayer); + } + + @Override + @SideOnly(Side.CLIENT) + protected TileEntityClipboard readHolderFromSyncData(PacketBuffer syncData) { + return (TileEntityClipboard) Minecraft.getMinecraft().world.getTileEntity(syncData.readBlockPos()); + } + + @Override + protected void writeHolderToSyncData(PacketBuffer syncData, TileEntityClipboard holder) { + syncData.writeBlockPos(holder.getPos()); + } +} diff --git a/src/main/java/gregtech/common/items/behaviors/ClipboardBehaviour.java b/src/main/java/gregtech/common/items/behaviors/ClipboardBehaviour.java index ce371abaf4d..79621584c9c 100644 --- a/src/main/java/gregtech/common/items/behaviors/ClipboardBehaviour.java +++ b/src/main/java/gregtech/common/items/behaviors/ClipboardBehaviour.java @@ -34,8 +34,8 @@ public ModularUI createUI(PlayerInventoryHolder holder, EntityPlayer entityPlaye int finalI = i; builder.widget(new ImageCycleButtonWidget(5, 37 + 20 * i, 15, 15, GuiTextures.CLIPBOARD_CHECKBOX, 2, () -> getButtonState(holder, finalI), (x) -> toggleButton(holder, finalI))); - builder.widget(new TextFieldWidget(21, 40 + 20 * i, 140, 6, true, - () -> getString(holder, finalI), (x) -> setString(holder, finalI, x), 40, 5) + builder.widget(new TextFieldWidget(21, 40 + 20 * i, 140, 10, true, + () -> getString(holder, finalI), (x) -> setString(holder, finalI, x), 23, 8) .setValidator((x) -> true)); } diff --git a/src/main/java/gregtech/common/metatileentities/MetaTileEntities.java b/src/main/java/gregtech/common/metatileentities/MetaTileEntities.java index 3b957205b09..6ea43f6e418 100644 --- a/src/main/java/gregtech/common/metatileentities/MetaTileEntities.java +++ b/src/main/java/gregtech/common/metatileentities/MetaTileEntities.java @@ -11,6 +11,7 @@ import gregtech.api.unification.material.Materials; import gregtech.api.util.GTLog; import gregtech.common.ConfigHolder; +import gregtech.common.blocks.clipboard.TileEntityClipboard; import gregtech.common.metatileentities.electric.*; import gregtech.common.metatileentities.electric.multiblockpart.MetaTileEntityEnergyHatch; import gregtech.common.metatileentities.electric.multiblockpart.MetaTileEntityFluidHatch; @@ -196,7 +197,7 @@ public class MetaTileEntities { public static MetaTileEntityInfiniteEmitter INFINITE_EMITTER; - public static MetaTileEntityClipboard CLIPBOARD_TILE; + public static TileEntityClipboard CLIPBOARD_TILE; public static void init() { GTLog.logger.info("Registering MetaTileEntities"); @@ -687,7 +688,7 @@ public static void init() { INFINITE_EMITTER = GregTechAPI.registerMetaTileEntity(1630, new MetaTileEntityInfiniteEmitter(gregtechId("infinite_emitter"))); - CLIPBOARD_TILE = GregTechAPI.registerMetaTileEntity(1631, new MetaTileEntityClipboard(gregtechId("clipboard"))); + CLIPBOARD_TILE = GregTechAPI.registerMetaTileEntity(1631, new TileEntityClipboard(gregtechId("clipboard"))); /* * FOR ADDON DEVELOPERS: diff --git a/src/main/java/gregtech/common/metatileentities/MetaTileEntityClipboard.java b/src/main/java/gregtech/common/metatileentities/MetaTileEntityClipboard.java deleted file mode 100644 index 5e413c5b715..00000000000 --- a/src/main/java/gregtech/common/metatileentities/MetaTileEntityClipboard.java +++ /dev/null @@ -1,68 +0,0 @@ -package gregtech.common.metatileentities; - -import codechicken.lib.render.CCRenderState; -import codechicken.lib.render.pipeline.IVertexOperation; -import codechicken.lib.vec.Matrix4; -import gregtech.api.capability.impl.FluidHandlerProxy; -import gregtech.api.gui.ModularUI; -import gregtech.api.items.gui.PlayerInventoryHolder; -import gregtech.api.items.itemhandlers.InaccessibleItemStackHandler; -import gregtech.api.items.metaitem.MetaItem; -import gregtech.api.items.metaitem.stats.IItemBehaviour; -import gregtech.api.metatileentity.MetaTileEntity; -import gregtech.api.metatileentity.MetaTileEntityHolder; -import gregtech.common.items.MetaItems; -import gregtech.common.items.behaviors.ClipboardBehaviour; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.util.ResourceLocation; -import net.minecraftforge.items.IItemHandler; - -import javax.annotation.Nonnull; - -import java.util.List; -import java.util.Optional; - -import static gregtech.common.items.MetaItems.CLIPBOARD; - -public class MetaTileEntityClipboard extends MetaTileEntity { - - public MetaTileEntityClipboard(ResourceLocation metaTileEntityId) { - super(metaTileEntityId); - } - - @Override - public MetaTileEntity createMetaTileEntity(MetaTileEntityHolder holder) { - return new MetaTileEntityClipboard(metaTileEntityId); - } - - @Override - protected ModularUI createUI(EntityPlayer entityPlayer) { - if(itemInventory.getStackInSlot(0) == ItemStack.EMPTY) { - ((InaccessibleItemStackHandler) itemInventory).setStackInSlot(0, CLIPBOARD.getStackForm()); - } - if(itemInventory.getStackInSlot(0).isItemEqual(CLIPBOARD.getStackForm())) { - List behaviours = ((MetaItem) itemInventory.getStackInSlot(0).getItem()).getBehaviours(itemInventory.getStackInSlot(0)); - Optional clipboardBehaviour = behaviours.stream().filter((x) -> x instanceof ClipboardBehaviour).findFirst(); - if(!clipboardBehaviour.isPresent()) - return null; - if(clipboardBehaviour.get() instanceof ClipboardBehaviour) { - return ((ClipboardBehaviour) clipboardBehaviour.get()).createUI(new PlayerInventoryHolder(entityPlayer, entityPlayer.getActiveHand(), itemInventory.getStackInSlot(0)), entityPlayer); - } - } - return null; - } - - @Override - protected void initializeInventory() { - this.itemInventory = new InaccessibleItemStackHandler(); - - this.importItems = createImportItemHandler(); - this.exportItems = createExportItemHandler(); - this.importFluids = createImportFluidHandler(); - this.exportFluids = createExportFluidHandler(); - this.fluidInventory = new FluidHandlerProxy(importFluids, exportFluids); - } -} diff --git a/src/main/java/gregtech/common/render/clipboard/TileEntityClipboardRenderer.java b/src/main/java/gregtech/common/render/clipboard/TileEntityClipboardRenderer.java index 5e4a2120cf4..1b6b0046aca 100644 --- a/src/main/java/gregtech/common/render/clipboard/TileEntityClipboardRenderer.java +++ b/src/main/java/gregtech/common/render/clipboard/TileEntityClipboardRenderer.java @@ -1,12 +1,70 @@ package gregtech.common.render.clipboard; -import gregtech.api.items.metaitem.MetaItem; -import gregtech.api.metatileentity.MetaTileEntity; -import gregtech.api.render.MetaTileEntityRenderer; -import gregtech.common.blocks.clipboard.MetaTileEntityClipboard; -import net.minecraft.client.gui.FontRenderer; -import net.minecraft.client.renderer.GlStateManager; -import net.minecraft.tileentity.TileEntity; -public class TileEntityClipboardRenderer extends MetaTileEntityRenderer { +import codechicken.lib.render.BlockRenderer; +import codechicken.lib.render.CCModel; +import codechicken.lib.render.CCRenderState; +import codechicken.lib.render.block.BlockRenderingRegistry; +import codechicken.lib.render.block.ICCBlockRenderer; +import codechicken.lib.vec.Cuboid6; +import codechicken.lib.vec.Vector3; +import codechicken.lib.vec.uv.IconTransformation; +import gregtech.common.render.StoneRenderer; +import net.minecraft.block.state.IBlockState; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.BufferBuilder; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.client.renderer.texture.TextureMap; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.util.EnumBlockRenderType; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.IBlockAccess; +import org.lwjgl.opengl.GL11; +import java.util.Random; + +public class TileEntityClipboardRenderer implements ICCBlockRenderer { + private static final TileEntityClipboardRenderer INSTANCE = new TileEntityClipboardRenderer(); + public static EnumBlockRenderType BLOCK_RENDER_TYPE; + + public static void preInit() { + BLOCK_RENDER_TYPE = BlockRenderingRegistry.createRenderType("gt_clipboard"); + BlockRenderingRegistry.registerRenderer(BLOCK_RENDER_TYPE, INSTANCE); + } + + + @Override + public void handleRenderBlockDamage(IBlockAccess world, BlockPos pos, IBlockState state, TextureAtlasSprite sprite, BufferBuilder buffer) { + CCRenderState renderState = CCRenderState.instance(); + renderState.reset(); + renderState.bind(buffer); + renderState.setPipeline(new Vector3(new Vec3d(pos)).translation(), new IconTransformation(sprite)); + Cuboid6 baseBox = new Cuboid6(state.getBoundingBox(world, pos)); + BlockRenderer.renderCuboid(renderState, baseBox, 0); + } + + @Override + public boolean renderBlock(IBlockAccess world, BlockPos pos, IBlockState state, BufferBuilder buffer) { + Tessellator tessellator = Tessellator.getInstance(); + Minecraft.getMinecraft().getBlockRendererDispatcher().renderBlock(state, pos, world, buffer); + + + //Second: + //render your gui here + tessellator.draw(); + return false; + } + + @Override + public void renderBrightness(IBlockState state, float v) { + Tessellator tessellator = Tessellator.getInstance(); + tessellator.getBuffer().begin(GL11.GL_QUADS, DefaultVertexFormats.BLOCK); + renderBlock(null, BlockPos.ORIGIN, state, tessellator.getBuffer()); + tessellator.draw(); + } + + @Override + public void registerTextures(TextureMap textureMap) { // Deprecated + } } diff --git a/src/main/resources/assets/gregtech/models/block/clipboard.json b/src/main/resources/assets/gregtech/models/block/clipboard.json index 7be55aa10b1..cb7dbf91285 100644 --- a/src/main/resources/assets/gregtech/models/block/clipboard.json +++ b/src/main/resources/assets/gregtech/models/block/clipboard.json @@ -1,15 +1,15 @@ { "credit": "Made with Blockbench", "textures": { - "0": "gregtech:items/metaitems/clipboard/clipboard", - "1": "gregtech:items/metaitems/clipboard/page", - "particle": "gregtech:items/metaitems/clipboard/clipboard" + "0": "clipboard/clipboard", + "1": "clipboard/page", + "particle": "clipboard/clipboard" }, "elements": [ { - "from": [6, 1, 9.025], - "to": [11, 8, 9.075], - "rotation": {"angle": 0, "axis": "y", "origin": [8.5, 6.59375, 9.0125]}, + "from": [5.5, 0.25, 0.25], + "to": [10.5, 7.25, 0.3], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 6.59375, 9.0125]}, "faces": { "north": {"uv": [8.5, 8.5, 13.5, 15.5], "texture": "#0"}, "east": {"uv": [8.5, 8.5, 8.55, 15.5], "texture": "#0"}, @@ -20,9 +20,9 @@ } }, { - "from": [5.75, 0.75, 8.775], - "to": [11.25, 8.5, 9.025], - "rotation": {"angle": 0, "axis": "y", "origin": [8.5, 6.59375, 9.0125]}, + "from": [5.25, 0, 0], + "to": [10.75, 7.75, 0.25], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 6.59375, 9.0125]}, "faces": { "north": {"uv": [8.5, 0, 14, 7.75], "texture": "#0"}, "east": {"uv": [8.5, 0, 8.75, 7.75], "texture": "#0"}, @@ -33,9 +33,9 @@ } }, { - "from": [6.75, 8, 9.025], - "to": [10.25, 8.75, 9.175], - "rotation": {"angle": 0, "axis": "y", "origin": [8.5, 6.59375, 9.0125]}, + "from": [6.25, 7.25, 0.25], + "to": [9.75, 8, 0.4], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 6.59375, 9.0125]}, "faces": { "north": {"uv": [0.5, 0.5, 4, 1.25], "texture": "#0"}, "east": {"uv": [0.5, 0.5, 0.65, 1.25], "texture": "#0"}, @@ -46,9 +46,9 @@ } }, { - "from": [8, 8.5, 8.875], - "to": [9, 9.25, 9.125], - "rotation": {"angle": 0, "axis": "y", "origin": [8.5, 6.59375, 9.0125]}, + "from": [7.5, 7.75, 0.1], + "to": [8.5, 8.5, 0.35], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 6.59375, 9.0125]}, "faces": { "north": {"uv": [0.5, 0.5, 1.5, 1.25], "texture": "#0"}, "east": {"uv": [0.5, 0.5, 0.75, 1.25], "texture": "#0"}, @@ -61,33 +61,33 @@ ], "display": { "thirdperson_righthand": { - "translation": [-0.5, 7, -0.5] + "translation": [0, 7.75, 7.75] }, "thirdperson_lefthand": { - "translation": [0.5, 7, -0.5] + "translation": [0, 7.75, 7.75] }, "firstperson_righthand": { "rotation": [-10, 0, 0], - "translation": [-3, 10, 2.5] + "translation": [-1.5, 11.5, 10] }, "firstperson_lefthand": { "rotation": [-10, 0, 0], - "translation": [-2, 10, 2.5] + "translation": [-1.5, 11.5, 10] }, "ground": { - "translation": [0, 3.75, 0] + "translation": [0, 4.75, 7.75] }, "gui": { - "translation": [-1, 5.5, 0], + "translation": [0.25, 7, 0], "scale": [1.75, 1.75, 1.75] }, "head": { - "translation": [-1, 5.75, 5], + "translation": [0, 5.75, 22.25], "scale": [2, 2, 2] }, "fixed": { "rotation": [0, -180, 0], - "translation": [1.25, 8.25, 1.5], + "translation": [0, 10, -20.25], "scale": [2.5, 2.5, 2.5] } } From 42efbaa0191609840edc4090a40bd626cede3fd7 Mon Sep 17 00:00:00 2001 From: bruberu <80226372+bruberu@users.noreply.github.com> Date: Tue, 20 Jul 2021 17:18:49 -0500 Subject: [PATCH 06/42] Fiddle around with blockstates --- .../java/gregtech/common/CommonProxy.java | 1 + .../gregtech/common/blocks/MetaBlocks.java | 4 +- .../blocks/clipboard/BlockClipboard.java | 26 +++++++---- .../blocks/clipboard/TileEntityClipboard.java | 45 ++++++++++++++----- .../items/behaviors/ClipboardBehaviour.java | 34 ++++++++++++++ .../metatileentities/MetaTileEntities.java | 2 - .../TileEntityClipboardRenderer.java | 40 +++++++++++++++-- .../gregtech/blockstates/clipboard.json | 27 +++++++++++ .../gregtech/models/block/clipboard.json | 6 +-- 9 files changed, 156 insertions(+), 29 deletions(-) create mode 100644 src/main/resources/assets/gregtech/blockstates/clipboard.json diff --git a/src/main/java/gregtech/common/CommonProxy.java b/src/main/java/gregtech/common/CommonProxy.java index 3a9228759ef..b99eb92d18b 100644 --- a/src/main/java/gregtech/common/CommonProxy.java +++ b/src/main/java/gregtech/common/CommonProxy.java @@ -82,6 +82,7 @@ public static void registerBlocks(RegistryEvent.Register event) { registry.register(LEAVES); registry.register(SAPLING); registry.register(SURFACE_ROCK); + registry.register(CLIPBOARD_BLOCK); COMPRESSED.values().stream().distinct().forEach(registry::register); FRAMES.values().stream().distinct().forEach(registry::register); diff --git a/src/main/java/gregtech/common/blocks/MetaBlocks.java b/src/main/java/gregtech/common/blocks/MetaBlocks.java index d1e3402fc96..931cd910d28 100644 --- a/src/main/java/gregtech/common/blocks/MetaBlocks.java +++ b/src/main/java/gregtech/common/blocks/MetaBlocks.java @@ -171,7 +171,7 @@ public static void init() { SURFACE_ROCK = new BlockSurfaceRock(); SURFACE_ROCK.setRegistryName("surface_rock_new"); CLIPBOARD_BLOCK = new BlockClipboard(); - CLIPBOARD_BLOCK.setRegistryName("gt_clipboard"); + CLIPBOARD_BLOCK.setRegistryName("clipboard"); StoneType.init(); @@ -394,6 +394,8 @@ protected ModelResourceLocation getModelResourceLocation(IBlockState state) { FLUID_BLOCKS.forEach(modelHandler::addFluidBlock); modelHandler.addBuiltInBlock(SURFACE_ROCK, "stone_andesite"); + modelHandler.addBuiltInBlock(CLIPBOARD_BLOCK, "stone_andesite"); + ClientRegistry.bindTileEntitySpecialRenderer(MetaTileEntityHolder.class, new MetaTileEntityTESR()); } diff --git a/src/main/java/gregtech/common/blocks/clipboard/BlockClipboard.java b/src/main/java/gregtech/common/blocks/clipboard/BlockClipboard.java index 0aefe0eb490..f7b562371d6 100644 --- a/src/main/java/gregtech/common/blocks/clipboard/BlockClipboard.java +++ b/src/main/java/gregtech/common/blocks/clipboard/BlockClipboard.java @@ -30,15 +30,16 @@ public class BlockClipboard extends Block implements ITileEntityProvider { private static final AxisAlignedBB CLIPBOARD_AABB = new AxisAlignedBB(5.25 / 16.0, 0.0, 0.0, 5.5 / 16.0, 8.0 / 16.0, 0.3 / 16.0); - protected ThreadLocal tileEntities = new ThreadLocal<>(); + public static final BlockClipboard INSTANCE = new BlockClipboard(); // Mainly to access the default state. + + protected ThreadLocal tileEntities = new ThreadLocal<>(); public BlockClipboard() { super(Material.WOOD); - setHardness(1.5f); + setHardness(0); setSoundType(SoundType.WOOD); setTranslationKey("clipboard"); setLightOpacity(1); - setHarvestLevel("pickaxe", 1); } @Override @@ -49,7 +50,7 @@ public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, Bloc private ItemStack getDropStack(IBlockAccess blockAccess, BlockPos pos, IBlockState blockState) { if(this.hasTileEntity(blockState)) { - return this.tileEntities.get().getMetaTileEntity().getItemInventory().getStackInSlot(0); + return this.tileEntities.get().getClipboard(); } return ItemStack.EMPTY; } @@ -102,7 +103,7 @@ public BlockFaceShape getBlockFaceShape(IBlockAccess worldIn, IBlockState state, public void breakBlock(World worldIn, BlockPos pos, IBlockState state) { TileEntityClipboard tileEntity = getTileEntity(worldIn, pos); if (tileEntity != null) { - tileEntities.set(tileEntity.getHolder()); + tileEntities.set(tileEntity); } super.breakBlock(worldIn, pos, state); @@ -110,21 +111,28 @@ public void breakBlock(World worldIn, BlockPos pos, IBlockState state) { @Override public void harvestBlock(World worldIn, EntityPlayer player, BlockPos pos, IBlockState state, @Nullable TileEntity te, ItemStack stack) { - tileEntities.set(te == null ? tileEntities.get() : (MetaTileEntityHolder) te); + tileEntities.set(te == null ? tileEntities.get() : (TileEntityClipboard) te); super.harvestBlock(worldIn, player, pos, state, te, stack); tileEntities.set(null); } public static TileEntityClipboard getTileEntity(IBlockAccess world, BlockPos pos) { TileEntity tileEntity = world.getTileEntity(pos); - if (tileEntity instanceof MetaTileEntityHolder) - return (TileEntityClipboard) ((MetaTileEntityHolder) tileEntity).getMetaTileEntity(); + if (tileEntity instanceof TileEntityClipboard) + return ((TileEntityClipboard)tileEntity); return null; } @Nullable @Override public TileEntity createNewTileEntity(World worldIn, int meta) { - return new MetaTileEntityHolder(); + return new TileEntityClipboard(); + } + + @Override + public boolean hasTileEntity() { + return true; } + + } diff --git a/src/main/java/gregtech/common/blocks/clipboard/TileEntityClipboard.java b/src/main/java/gregtech/common/blocks/clipboard/TileEntityClipboard.java index 4f2a151218e..1809fd6b549 100644 --- a/src/main/java/gregtech/common/blocks/clipboard/TileEntityClipboard.java +++ b/src/main/java/gregtech/common/blocks/clipboard/TileEntityClipboard.java @@ -12,14 +12,21 @@ import gregtech.api.items.metaitem.stats.IItemBehaviour; import gregtech.api.metatileentity.MetaTileEntity; import gregtech.api.metatileentity.MetaTileEntityHolder; +import gregtech.api.unification.material.Materials; +import gregtech.api.unification.material.type.Material; import gregtech.common.items.behaviors.ClipboardBehaviour; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTBase; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraft.nbt.NBTTagString; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.BlockRenderLayer; import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumHand; import net.minecraft.util.ResourceLocation; +import net.minecraftforge.common.util.Constants; import net.minecraftforge.items.ItemStackHandler; import java.util.List; @@ -27,39 +34,57 @@ import static gregtech.common.items.MetaItems.CLIPBOARD; -public class TileEntityClipboard extends TileEntity, implements IUIHolder { +public class TileEntityClipboard extends TileEntity implements IUIHolder { - private ItemStack clipboardStack; + private ItemStackHandler clipboardStackHandler = new ItemStackHandler(1); protected EnumFacing frontFacing = EnumFacing.NORTH; protected ModularUI createUI(EntityPlayer entityPlayer) { - if(clipboardStack == ItemStack.EMPTY) { - clipboardStack = CLIPBOARD.getStackForm(); + if(clipboardStackHandler.getStackInSlot(0) == ItemStack.EMPTY) { + clipboardStackHandler.setStackInSlot(0, CLIPBOARD.getStackForm()); } - if(clipboardStack.isItemEqual(CLIPBOARD.getStackForm())) { - List behaviours = ((MetaItem) clipboardStack.getItem()).getBehaviours(clipboardStack); + if(clipboardStackHandler.getStackInSlot(0).isItemEqual(CLIPBOARD.getStackForm())) { + List behaviours = ((MetaItem) clipboardStackHandler.getStackInSlot(0).getItem()).getBehaviours(clipboardStackHandler.getStackInSlot(0)); Optional clipboardBehaviour = behaviours.stream().filter((x) -> x instanceof ClipboardBehaviour).findFirst(); if(!clipboardBehaviour.isPresent()) return null; if(clipboardBehaviour.get() instanceof ClipboardBehaviour) { - return ((ClipboardBehaviour) clipboardBehaviour.get()).createUI(new PlayerInventoryHolder(entityPlayer, entityPlayer.getActiveHand(), clipboardStack), entityPlayer); + return ((ClipboardBehaviour) clipboardBehaviour.get()).createUI(new PlayerInventoryHolder(entityPlayer, entityPlayer.getActiveHand(), clipboardStackHandler.getStackInSlot(0)), entityPlayer); } } return null; } + public ItemStack getClipboard() { + return this.clipboardStackHandler.getStackInSlot(0).copy(); + } + + public void setClipboard(ItemStack stack) { + this.clipboardStackHandler.setStackInSlot(0, stack); + } + + public EnumFacing getFrontFacing() { + return frontFacing; + } + + public void setFrontFacing(EnumFacing facing) { + if(facing == EnumFacing.UP || facing == EnumFacing.DOWN) + throw new IllegalArgumentException("Clipboards can't face up or down!"); + frontFacing = facing; + } + @Override public boolean isValid() { - return false; + return true; } @Override public boolean isRemote() { - return false; + return this.getWorld().isRemote; } @Override public void markAsDirty() { - + super.markDirty(); } } diff --git a/src/main/java/gregtech/common/items/behaviors/ClipboardBehaviour.java b/src/main/java/gregtech/common/items/behaviors/ClipboardBehaviour.java index 79621584c9c..f30ebbf1353 100644 --- a/src/main/java/gregtech/common/items/behaviors/ClipboardBehaviour.java +++ b/src/main/java/gregtech/common/items/behaviors/ClipboardBehaviour.java @@ -9,13 +9,21 @@ import gregtech.api.items.gui.ItemUIFactory; import gregtech.api.items.gui.PlayerInventoryHolder; import gregtech.api.items.metaitem.stats.IItemBehaviour; +import gregtech.common.blocks.clipboard.BlockClipboard; +import gregtech.common.blocks.clipboard.TileEntityClipboard; import gregtech.common.items.MetaItems; +import net.minecraft.block.Block; +import net.minecraft.block.state.IBlockState; +import net.minecraft.client.Minecraft; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.ActionResult; import net.minecraft.util.EnumActionResult; +import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumHand; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.RayTraceResult; import net.minecraft.world.World; public class ClipboardBehaviour implements IItemBehaviour, ItemUIFactory { @@ -177,4 +185,30 @@ public ActionResult onItemRightClick(World world, EntityPlayer player } return ActionResult.newResult(EnumActionResult.SUCCESS, heldItem); } + + @Override + public ActionResult onItemUse(EntityPlayer player, World world, BlockPos pos, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ) { + ItemStack heldItem = player.getHeldItem(hand); + EnumFacing playerFacing = player.getHorizontalFacing(); + // Make sure it's the right block + Block testBlock = world.getBlockState(pos).getBlock(); + if (!testBlock.isAir(world.getBlockState(pos), world, pos)) { + // Step away from the block so you don't replace it, and then give it our fun blockstate + BlockPos shiftedPos = pos.offset(playerFacing.getOpposite()); + Block shiftedBlock = world.getBlockState(shiftedPos).getBlock(); + if(shiftedBlock.isAir(world.getBlockState(shiftedPos), world, shiftedPos)) { + IBlockState state = BlockClipboard.INSTANCE.getDefaultState(); + world.setBlockState(shiftedPos, state); + // Get new TE + shiftedBlock.createTileEntity(world, state); + // And manipulate it to our liking + TileEntityClipboard clipboard = (TileEntityClipboard) world.getTileEntity(pos); + if (clipboard != null) { + clipboard.setFrontFacing(playerFacing); + clipboard.setClipboard(heldItem); + } + } + } + return ActionResult.newResult(EnumActionResult.SUCCESS, heldItem); + } } diff --git a/src/main/java/gregtech/common/metatileentities/MetaTileEntities.java b/src/main/java/gregtech/common/metatileentities/MetaTileEntities.java index 9a05be802e7..dde71672508 100644 --- a/src/main/java/gregtech/common/metatileentities/MetaTileEntities.java +++ b/src/main/java/gregtech/common/metatileentities/MetaTileEntities.java @@ -688,8 +688,6 @@ public static void init() { INFINITE_EMITTER = GregTechAPI.registerMetaTileEntity(1630, new MetaTileEntityInfiniteEmitter(gregtechId("infinite_emitter"))); - CLIPBOARD_TILE = GregTechAPI.registerMetaTileEntity(1631, new TileEntityClipboard(gregtechId("clipboard"))); - /* * FOR ADDON DEVELOPERS: * diff --git a/src/main/java/gregtech/common/render/clipboard/TileEntityClipboardRenderer.java b/src/main/java/gregtech/common/render/clipboard/TileEntityClipboardRenderer.java index 1b6b0046aca..ec492de43e6 100644 --- a/src/main/java/gregtech/common/render/clipboard/TileEntityClipboardRenderer.java +++ b/src/main/java/gregtech/common/render/clipboard/TileEntityClipboardRenderer.java @@ -5,28 +5,44 @@ import codechicken.lib.render.CCRenderState; import codechicken.lib.render.block.BlockRenderingRegistry; import codechicken.lib.render.block.ICCBlockRenderer; +import codechicken.lib.render.item.IItemRenderer; +import codechicken.lib.render.pipeline.ColourMultiplier; +import codechicken.lib.render.pipeline.IVertexOperation; +import codechicken.lib.texture.TextureUtils; import codechicken.lib.vec.Cuboid6; +import codechicken.lib.vec.Matrix4; +import codechicken.lib.vec.TransformationList; import codechicken.lib.vec.Vector3; import codechicken.lib.vec.uv.IconTransformation; +import gregtech.api.GTValues; +import gregtech.common.items.MetaItem1; import gregtech.common.render.StoneRenderer; import net.minecraft.block.state.IBlockState; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.block.model.ModelResourceLocation; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.renderer.texture.TextureMap; import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.util.EnumBlockRenderType; +import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; import net.minecraft.world.IBlockAccess; +import net.minecraftforge.client.event.ModelBakeEvent; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import org.lwjgl.opengl.GL11; import java.util.Random; +import static gregtech.common.items.MetaItems.CLIPBOARD; + public class TileEntityClipboardRenderer implements ICCBlockRenderer { private static final TileEntityClipboardRenderer INSTANCE = new TileEntityClipboardRenderer(); public static EnumBlockRenderType BLOCK_RENDER_TYPE; + public static ModelResourceLocation MODEL_LOCATION = new ModelResourceLocation(new ResourceLocation(GTValues.MODID, "gt_clipboard"), "normal"); + public static void preInit() { BLOCK_RENDER_TYPE = BlockRenderingRegistry.createRenderType("gt_clipboard"); @@ -46,14 +62,30 @@ public void handleRenderBlockDamage(IBlockAccess world, BlockPos pos, IBlockStat @Override public boolean renderBlock(IBlockAccess world, BlockPos pos, IBlockState state, BufferBuilder buffer) { - Tessellator tessellator = Tessellator.getInstance(); - Minecraft.getMinecraft().getBlockRendererDispatcher().renderBlock(state, pos, world, buffer); + CCRenderState renderState = CCRenderState.instance(); + renderState.reset(); + renderState.bind(buffer); + Matrix4 translation = new Matrix4(); + translation.translate(pos.getX(), pos.getY(), pos.getZ()); + TextureAtlasSprite clipboardSprite = TextureUtils.getItemTexture("gregtech:metaitems/clipboard/clipboard"); + + IVertexOperation[] operations = new IVertexOperation[] { + new IconTransformation(clipboardSprite), + new TransformationList(translation)}; + if (world != null) { + renderState.setBrightness(world, pos); + } + renderState.setPipeline(operations); + renderState.render(); + //Second: //render your gui here - tessellator.draw(); - return false; + + Tessellator tessellator = Tessellator.getInstance(); + + return true; } @Override diff --git a/src/main/resources/assets/gregtech/blockstates/clipboard.json b/src/main/resources/assets/gregtech/blockstates/clipboard.json new file mode 100644 index 00000000000..40227bafdf1 --- /dev/null +++ b/src/main/resources/assets/gregtech/blockstates/clipboard.json @@ -0,0 +1,27 @@ +{ + "forge_marker": 1, + "defaults": { + "model": "gregtech:clipboard", + "textures": { + "0": "gregtech:items/metaitems/clipboard/clipboard", + "1": "gregtech:items/metaitems/clipboard/page", + "particle": "gregtech:items/metaitems/clipboard/clipboard" + } + }, + "variants": { + "normal": [{}], + "inventory": [{}], + "facing": { + "north": {}, + "south": { + "y": 180 + }, + "west": { + "y": 270 + }, + "east": { + "y": 90 + } + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/gregtech/models/block/clipboard.json b/src/main/resources/assets/gregtech/models/block/clipboard.json index cb7dbf91285..2a941c34fd3 100644 --- a/src/main/resources/assets/gregtech/models/block/clipboard.json +++ b/src/main/resources/assets/gregtech/models/block/clipboard.json @@ -1,9 +1,9 @@ { "credit": "Made with Blockbench", "textures": { - "0": "clipboard/clipboard", - "1": "clipboard/page", - "particle": "clipboard/clipboard" + "0": "gregtech:items/metaitems/clipboard/clipboard", + "1": "gregtech:items/metaitems/clipboard/page", + "particle": "gregtech:items/metaitems/clipboard/clipboard" }, "elements": [ { From a02561560b4b6d780b21c9d0d30c72a780d2679d Mon Sep 17 00:00:00 2001 From: bruberu <80226372+bruberu@users.noreply.github.com> Date: Thu, 22 Jul 2021 23:17:38 -0500 Subject: [PATCH 07/42] Add proper clipboard-placing behavior --- .../java/gregtech/api/util/GTUtility.java | 2 +- .../blocks/clipboard/BlockClipboard.java | 41 +++++++++++++++-- .../blocks/clipboard/TileEntityClipboard.java | 9 ++++ .../items/behaviors/ClipboardBehaviour.java | 6 +-- .../TileEntityClipboardRenderer.java | 5 ++- .../gregtech/blockstates/clipboard.json | 21 +-------- .../resources/assets/gregtech/lang/en_us.lang | 3 ++ .../gregtech/models/block/clipboard.json | 45 ++++++++++--------- 8 files changed, 82 insertions(+), 50 deletions(-) diff --git a/src/main/java/gregtech/api/util/GTUtility.java b/src/main/java/gregtech/api/util/GTUtility.java index 9caf05081fd..158cc8533e6 100644 --- a/src/main/java/gregtech/api/util/GTUtility.java +++ b/src/main/java/gregtech/api/util/GTUtility.java @@ -903,7 +903,7 @@ public static AxisAlignedBB rotateAroundYAxis(AxisAlignedBB aabb, EnumFacing fro throw new IllegalArgumentException("Either the second or third parameters were EnumFacing.DOWN or EnumFacing.UP."); AxisAlignedBB rotatedAABB = new AxisAlignedBB(aabb.minX, aabb.minY, aabb.minZ, aabb.maxX, aabb.maxY, aabb.maxZ); while(from != to) { - from.rotateY(); + from = from.rotateY(); rotatedAABB = new AxisAlignedBB(1 - rotatedAABB.maxZ, rotatedAABB.minY, rotatedAABB.minX, 1 - rotatedAABB.minZ, rotatedAABB.maxY, rotatedAABB.maxX); } return rotatedAABB; diff --git a/src/main/java/gregtech/common/blocks/clipboard/BlockClipboard.java b/src/main/java/gregtech/common/blocks/clipboard/BlockClipboard.java index f7b562371d6..9ccaa40e4bf 100644 --- a/src/main/java/gregtech/common/blocks/clipboard/BlockClipboard.java +++ b/src/main/java/gregtech/common/blocks/clipboard/BlockClipboard.java @@ -1,6 +1,10 @@ package gregtech.common.blocks.clipboard; +import codechicken.lib.raytracer.CuboidRayTraceResult; +import codechicken.lib.raytracer.RayTracer; +import gregtech.api.metatileentity.MetaTileEntity; import gregtech.api.metatileentity.MetaTileEntityHolder; +import gregtech.api.metatileentity.MetaTileEntityUIFactory; import gregtech.api.util.GTUtility; import gregtech.common.render.clipboard.TileEntityClipboardRenderer; import net.minecraft.block.Block; @@ -10,10 +14,12 @@ import net.minecraft.block.state.BlockFaceShape; import net.minecraft.block.state.IBlockState; import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumBlockRenderType; import net.minecraft.util.EnumFacing; +import net.minecraft.util.EnumHand; import net.minecraft.util.NonNullList; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; @@ -28,7 +34,7 @@ public class BlockClipboard extends Block implements ITileEntityProvider { - private static final AxisAlignedBB CLIPBOARD_AABB = new AxisAlignedBB(5.25 / 16.0, 0.0, 0.0, 5.5 / 16.0, 8.0 / 16.0, 0.3 / 16.0); + private static final AxisAlignedBB CLIPBOARD_AABB = new AxisAlignedBB(2.75 / 16.0, 0.0, 0.0, 13.25 / 16.0, 1.0, 0.4 / 16.0); public static final BlockClipboard INSTANCE = new BlockClipboard(); // Mainly to access the default state. @@ -45,7 +51,11 @@ public BlockClipboard() { @Override @Nonnull public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos) { - return GTUtility.rotateAroundYAxis(CLIPBOARD_AABB, EnumFacing.NORTH, getTileEntity(source, pos).getFrontFacing()); + if(getTileEntity(source, pos) != null) { + return GTUtility.rotateAroundYAxis(CLIPBOARD_AABB, EnumFacing.NORTH, getTileEntity(source, pos).getFrontFacing()); + } else { + return CLIPBOARD_AABB; + } } private ItemStack getDropStack(IBlockAccess blockAccess, BlockPos pos, IBlockState blockState) { @@ -126,7 +136,18 @@ public static TileEntityClipboard getTileEntity(IBlockAccess world, BlockPos pos @Nullable @Override public TileEntity createNewTileEntity(World worldIn, int meta) { - return new TileEntityClipboard(); + TileEntityClipboard clipboard = new TileEntityClipboard(); + clipboard.setWorld(worldIn); + tileEntities.set(new TileEntityClipboard()); + return tileEntities.get(); + } + + public TileEntity createNewTileEntity(World worldIn, int meta, BlockPos pos) { + TileEntityClipboard clipboard = new TileEntityClipboard(); + clipboard.setWorld(worldIn); + clipboard.setPos(pos); + tileEntities.set(new TileEntityClipboard()); + return tileEntities.get(); } @Override @@ -134,5 +155,17 @@ public boolean hasTileEntity() { return true; } - + @Override + public boolean onBlockActivated(World worldIn, BlockPos pos, IBlockState state, EntityPlayer playerIn, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ) { + TileEntityClipboard tileEntity = getTileEntity(worldIn, pos); + RayTraceResult rayTraceResult = RayTracer.retraceBlock(worldIn, playerIn, pos); + ItemStack itemStack = playerIn.getHeldItem(hand); + if (tileEntity == null || rayTraceResult == null) { + return false; + } + if(tileEntity.getWorld() != null && !tileEntity.getWorld().isRemote) { + TileEntityClipboardUIFactory.INSTANCE.openUI(this.tileEntities.get(), (EntityPlayerMP) playerIn); + } + return true; + } } diff --git a/src/main/java/gregtech/common/blocks/clipboard/TileEntityClipboard.java b/src/main/java/gregtech/common/blocks/clipboard/TileEntityClipboard.java index 1809fd6b549..6d1974f98f2 100644 --- a/src/main/java/gregtech/common/blocks/clipboard/TileEntityClipboard.java +++ b/src/main/java/gregtech/common/blocks/clipboard/TileEntityClipboard.java @@ -4,6 +4,8 @@ import codechicken.lib.render.CCRenderState; import codechicken.lib.vec.Matrix4; import gregtech.api.capability.impl.FluidHandlerProxy; +import gregtech.api.cover.CoverBehavior; +import gregtech.api.cover.CoverBehaviorUIFactory; import gregtech.api.gui.IUIHolder; import gregtech.api.gui.ModularUI; import gregtech.api.items.gui.PlayerInventoryHolder; @@ -16,6 +18,7 @@ import gregtech.api.unification.material.type.Material; import gregtech.common.items.behaviors.ClipboardBehaviour; import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTBase; import net.minecraft.nbt.NBTTagCompound; @@ -39,6 +42,12 @@ public class TileEntityClipboard extends TileEntity implements IUIHolder { private ItemStackHandler clipboardStackHandler = new ItemStackHandler(1); protected EnumFacing frontFacing = EnumFacing.NORTH; + + + public void openUI(EntityPlayerMP player) { + TileEntityClipboardUIFactory.INSTANCE.openUI( this, player); + } + protected ModularUI createUI(EntityPlayer entityPlayer) { if(clipboardStackHandler.getStackInSlot(0) == ItemStack.EMPTY) { clipboardStackHandler.setStackInSlot(0, CLIPBOARD.getStackForm()); diff --git a/src/main/java/gregtech/common/items/behaviors/ClipboardBehaviour.java b/src/main/java/gregtech/common/items/behaviors/ClipboardBehaviour.java index f30ebbf1353..c24d0b65b6f 100644 --- a/src/main/java/gregtech/common/items/behaviors/ClipboardBehaviour.java +++ b/src/main/java/gregtech/common/items/behaviors/ClipboardBehaviour.java @@ -202,13 +202,13 @@ public ActionResult onItemUse(EntityPlayer player, World world, Block // Get new TE shiftedBlock.createTileEntity(world, state); // And manipulate it to our liking - TileEntityClipboard clipboard = (TileEntityClipboard) world.getTileEntity(pos); + TileEntityClipboard clipboard = (TileEntityClipboard) world.getTileEntity(shiftedPos); if (clipboard != null) { clipboard.setFrontFacing(playerFacing); - clipboard.setClipboard(heldItem); + clipboard.setClipboard(heldItem.copy()); } } } - return ActionResult.newResult(EnumActionResult.SUCCESS, heldItem); + return ActionResult.newResult(EnumActionResult.SUCCESS, player.isCreative() ? heldItem : ItemStack.EMPTY); } } diff --git a/src/main/java/gregtech/common/render/clipboard/TileEntityClipboardRenderer.java b/src/main/java/gregtech/common/render/clipboard/TileEntityClipboardRenderer.java index ec492de43e6..5ecff896253 100644 --- a/src/main/java/gregtech/common/render/clipboard/TileEntityClipboardRenderer.java +++ b/src/main/java/gregtech/common/render/clipboard/TileEntityClipboardRenderer.java @@ -41,7 +41,7 @@ public class TileEntityClipboardRenderer implements ICCBlockRenderer { private static final TileEntityClipboardRenderer INSTANCE = new TileEntityClipboardRenderer(); public static EnumBlockRenderType BLOCK_RENDER_TYPE; - public static ModelResourceLocation MODEL_LOCATION = new ModelResourceLocation(new ResourceLocation(GTValues.MODID, "gt_clipboard"), "normal"); + public static ModelResourceLocation MODEL_LOCATION = new ModelResourceLocation(new ResourceLocation(GTValues.MODID, "clipboard"), "normal"); public static void preInit() { @@ -76,7 +76,8 @@ public boolean renderBlock(IBlockAccess world, BlockPos pos, IBlockState state, renderState.setBrightness(world, pos); } renderState.setPipeline(operations); - renderState.render(); + //renderState.setModel(/*????????*/); + //renderState.render(); diff --git a/src/main/resources/assets/gregtech/blockstates/clipboard.json b/src/main/resources/assets/gregtech/blockstates/clipboard.json index 40227bafdf1..607049158bf 100644 --- a/src/main/resources/assets/gregtech/blockstates/clipboard.json +++ b/src/main/resources/assets/gregtech/blockstates/clipboard.json @@ -1,27 +1,10 @@ { "forge_marker": 1, "defaults": { - "model": "gregtech:clipboard", - "textures": { - "0": "gregtech:items/metaitems/clipboard/clipboard", - "1": "gregtech:items/metaitems/clipboard/page", - "particle": "gregtech:items/metaitems/clipboard/clipboard" - } + "model": "gregtech:clipboard" }, "variants": { "normal": [{}], - "inventory": [{}], - "facing": { - "north": {}, - "south": { - "y": 180 - }, - "west": { - "y": 270 - }, - "east": { - "y": 90 - } - } + "inventory": [{}] } } \ No newline at end of file diff --git a/src/main/resources/assets/gregtech/lang/en_us.lang b/src/main/resources/assets/gregtech/lang/en_us.lang index ef708af5dea..2a2e27ab109 100644 --- a/src/main/resources/assets/gregtech/lang/en_us.lang +++ b/src/main/resources/assets/gregtech/lang/en_us.lang @@ -809,6 +809,9 @@ metaitem.turbine_rotor.name=%s Turbine Rotor metaitem.turbine_rotor.tooltip=Turbine Rotors for your power station metaitem.tool.magnifying_glass.name=%s Magnifying Glass +metaitem.clipboard.name=Clipboard +metaitem.clipboard.tooltip=Can be written on (without any writing Instrument) + metaitem.drill.mode.three_cube=3x3x3 Cube metaitem.drill.mode.five_cube=5x5x5 Cube metaitem.drill.mode.seven_cube=7x7x7 Cube diff --git a/src/main/resources/assets/gregtech/models/block/clipboard.json b/src/main/resources/assets/gregtech/models/block/clipboard.json index 2a941c34fd3..34b1288b6b3 100644 --- a/src/main/resources/assets/gregtech/models/block/clipboard.json +++ b/src/main/resources/assets/gregtech/models/block/clipboard.json @@ -1,14 +1,14 @@ { "credit": "Made with Blockbench", "textures": { - "0": "gregtech:items/metaitems/clipboard/clipboard", - "1": "gregtech:items/metaitems/clipboard/page", - "particle": "gregtech:items/metaitems/clipboard/clipboard" + "0": "clipboard/clipboard", + "1": "clipboard/page", + "particle": "clipboard/clipboard" }, "elements": [ { - "from": [5.5, 0.25, 0.25], - "to": [10.5, 7.25, 0.3], + "from": [3, 0.25, 0.25], + "to": [13, 14.25, 0.3], "rotation": {"angle": 0, "axis": "y", "origin": [8, 6.59375, 9.0125]}, "faces": { "north": {"uv": [8.5, 8.5, 13.5, 15.5], "texture": "#0"}, @@ -20,8 +20,8 @@ } }, { - "from": [5.25, 0, 0], - "to": [10.75, 7.75, 0.25], + "from": [2.75, 0, 0], + "to": [13.25, 15.25, 0.25], "rotation": {"angle": 0, "axis": "y", "origin": [8, 6.59375, 9.0125]}, "faces": { "north": {"uv": [8.5, 0, 14, 7.75], "texture": "#0"}, @@ -33,8 +33,8 @@ } }, { - "from": [6.25, 7.25, 0.25], - "to": [9.75, 8, 0.4], + "from": [5.75, 14.75, 0.25], + "to": [10.25, 15.5, 0.4], "rotation": {"angle": 0, "axis": "y", "origin": [8, 6.59375, 9.0125]}, "faces": { "north": {"uv": [0.5, 0.5, 4, 1.25], "texture": "#0"}, @@ -46,8 +46,8 @@ } }, { - "from": [7.5, 7.75, 0.1], - "to": [8.5, 8.5, 0.35], + "from": [7, 15.25, 0.1], + "to": [9, 16, 0.35], "rotation": {"angle": 0, "axis": "y", "origin": [8, 6.59375, 9.0125]}, "faces": { "north": {"uv": [0.5, 0.5, 1.5, 1.25], "texture": "#0"}, @@ -61,34 +61,37 @@ ], "display": { "thirdperson_righthand": { - "translation": [0, 7.75, 7.75] + "translation": [0, 4, 4], + "scale": [0.5, 0.5, 0.5] }, "thirdperson_lefthand": { - "translation": [0, 7.75, 7.75] + "translation": [0, 4, 4], + "scale": [0.5, 0.5, 0.5] }, "firstperson_righthand": { "rotation": [-10, 0, 0], - "translation": [-1.5, 11.5, 10] + "translation": [-1.5, 7.25, 7], + "scale": [0.5, 0.5, 0.5] }, "firstperson_lefthand": { "rotation": [-10, 0, 0], - "translation": [-1.5, 11.5, 10] + "translation": [-1.5, 7.25, 7], + "scale": [0.5, 0.5, 0.5] }, "ground": { - "translation": [0, 4.75, 7.75] + "translation": [0, 0.75, 4], + "scale": [0.5, 0.5, 0.5] }, "gui": { - "translation": [0.25, 7, 0], - "scale": [1.75, 1.75, 1.75] + "translation": [0.25, 0.25, 0] }, "head": { - "translation": [0, 5.75, 22.25], + "translation": [0, -8.25, 22.25], "scale": [2, 2, 2] }, "fixed": { "rotation": [0, -180, 0], - "translation": [0, 10, -20.25], - "scale": [2.5, 2.5, 2.5] + "translation": [0, 0.25, -8] } } } \ No newline at end of file From a3f8a5f410933a083439d17d54ceaa2fc6ed4af3 Mon Sep 17 00:00:00 2001 From: bruberu <80226372+bruberu@users.noreply.github.com> Date: Fri, 23 Jul 2021 13:48:20 -0500 Subject: [PATCH 08/42] Add a clipboard back --- src/main/java/gregtech/common/items/MetaItem1.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/gregtech/common/items/MetaItem1.java b/src/main/java/gregtech/common/items/MetaItem1.java index e6a40c568a3..b8d95981739 100644 --- a/src/main/java/gregtech/common/items/MetaItem1.java +++ b/src/main/java/gregtech/common/items/MetaItem1.java @@ -505,6 +505,8 @@ public void registerSubItems() { CARBON_FIBERS = addItem(355, "carbon.fibers"); CARBON_MESH = addItem(356, "carbon.mesh"); CARBON_PLATE = addItem(357, "carbon.plate"); + + CLIPBOARD = addItem(362, "clipboard").addComponents(new ClipboardBehaviour()); } public void registerRecipes() { From 36f5101967ec5b348bd0a8aadf5ba4fd8cfc6029 Mon Sep 17 00:00:00 2001 From: bruberu <80226372+bruberu@users.noreply.github.com> Date: Mon, 26 Jul 2021 00:22:19 -0500 Subject: [PATCH 09/42] Begin movement to MTE, by Yefancy's request --- .../api/block/machines/BlockMachine.java | 1 - .../InaccessibleItemStackHandler.java | 3 + .../items/behaviors/ClipboardBehaviour.java | 25 ++-- .../metatileentities/MetaTileEntities.java | 4 +- .../MetaTileEntityClipboard.java | 139 ++++++++++++++++++ 5 files changed, 160 insertions(+), 12 deletions(-) create mode 100644 src/main/java/gregtech/common/metatileentities/MetaTileEntityClipboard.java diff --git a/src/main/java/gregtech/api/block/machines/BlockMachine.java b/src/main/java/gregtech/api/block/machines/BlockMachine.java index e2c7b212697..497261cd064 100755 --- a/src/main/java/gregtech/api/block/machines/BlockMachine.java +++ b/src/main/java/gregtech/api/block/machines/BlockMachine.java @@ -83,7 +83,6 @@ public BlockMachine() { setHardness(6.0f); setResistance(6.0f); setTranslationKey("unnamed"); - setHarvestLevel("wrench", 1); setDefaultState(getDefaultState().withProperty(OPAQUE, true)); } diff --git a/src/main/java/gregtech/api/items/itemhandlers/InaccessibleItemStackHandler.java b/src/main/java/gregtech/api/items/itemhandlers/InaccessibleItemStackHandler.java index a7c30277482..2044c3fc642 100644 --- a/src/main/java/gregtech/api/items/itemhandlers/InaccessibleItemStackHandler.java +++ b/src/main/java/gregtech/api/items/itemhandlers/InaccessibleItemStackHandler.java @@ -16,4 +16,7 @@ public ItemStack extractItem(int slot, int amount, boolean simulate) { return ItemStack.EMPTY; } + public void setStackInSlot(int slot, ItemStack stack) { + this.stacks.set(slot, stack); + } } diff --git a/src/main/java/gregtech/common/items/behaviors/ClipboardBehaviour.java b/src/main/java/gregtech/common/items/behaviors/ClipboardBehaviour.java index c24d0b65b6f..6f80d3771f8 100644 --- a/src/main/java/gregtech/common/items/behaviors/ClipboardBehaviour.java +++ b/src/main/java/gregtech/common/items/behaviors/ClipboardBehaviour.java @@ -9,12 +9,11 @@ import gregtech.api.items.gui.ItemUIFactory; import gregtech.api.items.gui.PlayerInventoryHolder; import gregtech.api.items.metaitem.stats.IItemBehaviour; -import gregtech.common.blocks.clipboard.BlockClipboard; -import gregtech.common.blocks.clipboard.TileEntityClipboard; +import gregtech.api.metatileentity.MetaTileEntityHolder; import gregtech.common.items.MetaItems; +import gregtech.common.metatileentities.MetaTileEntityClipboard; import net.minecraft.block.Block; import net.minecraft.block.state.IBlockState; -import net.minecraft.client.Minecraft; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; @@ -23,9 +22,11 @@ import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumHand; import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.RayTraceResult; import net.minecraft.world.World; +import static gregtech.common.blocks.MetaBlocks.MACHINE; +import static gregtech.common.metatileentities.MetaTileEntities.CLIPBOARD_TILE; + public class ClipboardBehaviour implements IItemBehaviour, ItemUIFactory { public static final int MAX_PAGES = 25; @@ -196,16 +197,20 @@ public ActionResult onItemUse(EntityPlayer player, World world, Block // Step away from the block so you don't replace it, and then give it our fun blockstate BlockPos shiftedPos = pos.offset(playerFacing.getOpposite()); Block shiftedBlock = world.getBlockState(shiftedPos).getBlock(); - if(shiftedBlock.isAir(world.getBlockState(shiftedPos), world, shiftedPos)) { - IBlockState state = BlockClipboard.INSTANCE.getDefaultState(); + if (shiftedBlock.isAir(world.getBlockState(shiftedPos), world, shiftedPos)) { + IBlockState state = MACHINE.getDefaultState(); world.setBlockState(shiftedPos, state); // Get new TE shiftedBlock.createTileEntity(world, state); // And manipulate it to our liking - TileEntityClipboard clipboard = (TileEntityClipboard) world.getTileEntity(shiftedPos); - if (clipboard != null) { - clipboard.setFrontFacing(playerFacing); - clipboard.setClipboard(heldItem.copy()); + MetaTileEntityHolder holder = (MetaTileEntityHolder) world.getTileEntity(shiftedPos); + if (holder != null) { + holder.setMetaTileEntity(CLIPBOARD_TILE); + MetaTileEntityClipboard clipboard = (MetaTileEntityClipboard) holder.getMetaTileEntity(); + if (clipboard != null) { + clipboard.setFrontFacing(playerFacing); + clipboard.setClipboard(heldItem); + } } } } diff --git a/src/main/java/gregtech/common/metatileentities/MetaTileEntities.java b/src/main/java/gregtech/common/metatileentities/MetaTileEntities.java index e2a74a38510..df94c073638 100644 --- a/src/main/java/gregtech/common/metatileentities/MetaTileEntities.java +++ b/src/main/java/gregtech/common/metatileentities/MetaTileEntities.java @@ -200,7 +200,7 @@ public class MetaTileEntities { public static MetaTileEntityInfiniteEmitter INFINITE_EMITTER; - public static TileEntityClipboard CLIPBOARD_TILE; + public static MetaTileEntityClipboard CLIPBOARD_TILE; public static void init() { GTLog.logger.info("Registering MetaTileEntities"); @@ -675,6 +675,8 @@ public static void init() { STEAM_IMPORT_BUS = GregTechAPI.registerMetaTileEntity(1632, new MetaTileEntitySteamItemBus(gregtechId("steam_import_bus"), false)); STEAM_HATCH = GregTechAPI.registerMetaTileEntity(1633, new MetaTileEntitySteamHatch(gregtechId("steam_hatch"))); + CLIPBOARD_TILE = GregTechAPI.registerMetaTileEntity(1640, new MetaTileEntityClipboard(gregtechId("clipboard"))); + /* * FOR ADDON DEVELOPERS: * diff --git a/src/main/java/gregtech/common/metatileentities/MetaTileEntityClipboard.java b/src/main/java/gregtech/common/metatileentities/MetaTileEntityClipboard.java new file mode 100644 index 00000000000..1ffc9e324c0 --- /dev/null +++ b/src/main/java/gregtech/common/metatileentities/MetaTileEntityClipboard.java @@ -0,0 +1,139 @@ +package gregtech.common.metatileentities; + +import codechicken.lib.raytracer.CuboidRayTraceResult; +import codechicken.lib.raytracer.IndexedCuboid6; +import codechicken.lib.render.CCRenderState; +import codechicken.lib.render.pipeline.IVertexOperation; +import codechicken.lib.vec.Matrix4; +import gregtech.api.gui.ModularUI; +import gregtech.api.items.gui.PlayerInventoryHolder; +import gregtech.api.items.itemhandlers.InaccessibleItemStackHandler; +import gregtech.api.items.metaitem.MetaItem; +import gregtech.api.items.metaitem.stats.IItemBehaviour; +import gregtech.api.metatileentity.IRenderMetaTileEntity; +import gregtech.api.metatileentity.MetaTileEntity; +import gregtech.api.metatileentity.MetaTileEntityHolder; +import gregtech.api.metatileentity.MetaTileEntityUIFactory; +import gregtech.api.util.GTUtility; +import gregtech.common.items.behaviors.ClipboardBehaviour; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.item.ItemStack; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.EnumHand; +import net.minecraft.util.NonNullList; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.world.World; +import net.minecraftforge.items.ItemStackHandler; + +import javax.annotation.Nullable; + +import java.util.List; +import java.util.Optional; + +import static gregtech.common.items.MetaItems.CLIPBOARD; + +public class MetaTileEntityClipboard extends MetaTileEntity implements IRenderMetaTileEntity { + private static final AxisAlignedBB CLIPBOARD_AABB = new AxisAlignedBB(2.75 / 16.0, 0.0, 0.0, 13.25 / 16.0, 1.0, 0.4 / 16.0); + + + public MetaTileEntityClipboard(ResourceLocation metaTileEntityId) { + super(metaTileEntityId); + } + + @Override + public void renderMetaTileEntityDynamic(double x, double y, double z, float partialTicks) { + + } + + @Override + public void renderMetaTileEntity(CCRenderState renderState, Matrix4 translation, IVertexOperation[] pipeline) { + } + + @Override + public AxisAlignedBB getRenderBoundingBox() { + return GTUtility.rotateAroundYAxis(CLIPBOARD_AABB, EnumFacing.NORTH, this.getFrontFacing()); + } + + @Override + public boolean isOpaqueCube() { + return false; + } + + + + @Override + public MetaTileEntity createMetaTileEntity(MetaTileEntityHolder holder) { + return new MetaTileEntityClipboard(metaTileEntityId); + } + + @Override + protected ModularUI createUI(EntityPlayer entityPlayer) { + if(getClipboard().isItemEqual(CLIPBOARD.getStackForm())) { + List behaviours = ((MetaItem) getClipboard().getItem()).getBehaviours(getClipboard()); + Optional clipboardBehaviour = behaviours.stream().filter((x) -> x instanceof ClipboardBehaviour).findFirst(); + if(!clipboardBehaviour.isPresent()) + return null; + if(clipboardBehaviour.get() instanceof ClipboardBehaviour) { + return ((ClipboardBehaviour) clipboardBehaviour.get()).createUI(new PlayerInventoryHolder(entityPlayer, entityPlayer.getActiveHand(), getClipboard()), entityPlayer); + } + } + return null; + } + + @Override + protected void initializeInventory() { + super.initializeInventory(); + this.itemInventory = new InaccessibleItemStackHandler(); + } + + public ItemStack getClipboard() { + if(this.itemInventory.getStackInSlot(0) == ItemStack.EMPTY) { + ((InaccessibleItemStackHandler) this.itemInventory).setStackInSlot(0, CLIPBOARD.getStackForm()); + } + return this.itemInventory.getStackInSlot(0); + } + + public void setClipboard(ItemStack stack) { + ((InaccessibleItemStackHandler) this.itemInventory).setStackInSlot(0, stack.copy()); + } + + @Override + public void getDrops(NonNullList dropsList, @Nullable EntityPlayer harvester) { + dropsList.add(this.getClipboard()); + } + + @Override + public float getBlockHardness() { + return 0; + } + + @Override + public int getHarvestLevel() { + return 10; + } + + @Override + public boolean onRightClick(EntityPlayer playerIn, EnumHand hand, EnumFacing facing, CuboidRayTraceResult hitResult) { + if(playerIn.isSneaking()) { + if (getWorld() != null && !getWorld().isRemote) { + MetaTileEntityUIFactory.INSTANCE.openUI(getHolder(), (EntityPlayerMP) playerIn); + } + } else { + getWorld().destroyBlock(this.getPos(), true); + } + return true; + } + + + @Override + public String getHarvestTool() { + return "wrench"; + } + + @Override + public void addCollisionBoundingBox(List collisionList) { + collisionList.add(new IndexedCuboid6(null, GTUtility.rotateAroundYAxis(CLIPBOARD_AABB, EnumFacing.NORTH, this.getFrontFacing()))); + } +} From fa52af7632d9f1626709a99804001b194921490f Mon Sep 17 00:00:00 2001 From: bruberu <80226372+bruberu@users.noreply.github.com> Date: Mon, 26 Jul 2021 23:00:12 -0500 Subject: [PATCH 10/42] Remove aged TE code --- src/main/java/gregtech/GregTechMod.java | 2 - .../java/gregtech/common/CommonProxy.java | 1 - .../gregtech/common/blocks/MetaBlocks.java | 7 - .../blocks/clipboard/BlockClipboard.java | 171 ------------------ .../blocks/clipboard/TileEntityClipboard.java | 99 ---------- .../TileEntityClipboardUIFactory.java | 37 ---- .../metatileentities/MetaTileEntities.java | 1 - 7 files changed, 318 deletions(-) delete mode 100644 src/main/java/gregtech/common/blocks/clipboard/BlockClipboard.java delete mode 100644 src/main/java/gregtech/common/blocks/clipboard/TileEntityClipboard.java delete mode 100644 src/main/java/gregtech/common/blocks/clipboard/TileEntityClipboardUIFactory.java diff --git a/src/main/java/gregtech/GregTechMod.java b/src/main/java/gregtech/GregTechMod.java index 9381954931e..23de8084032 100644 --- a/src/main/java/gregtech/GregTechMod.java +++ b/src/main/java/gregtech/GregTechMod.java @@ -23,7 +23,6 @@ import gregtech.common.MetaEntities; import gregtech.common.MetaFluids; import gregtech.common.blocks.MetaBlocks; -import gregtech.common.blocks.clipboard.TileEntityClipboardUIFactory; import gregtech.common.blocks.modelfactories.BlockCompressedFactory; import gregtech.common.blocks.modelfactories.BlockFrameFactory; import gregtech.common.blocks.modelfactories.BlockOreFactory; @@ -74,7 +73,6 @@ public void onPreInit(FMLPreInitializationEvent event) { MetaTileEntityUIFactory.INSTANCE.init(); PlayerInventoryUIFactory.INSTANCE.init(); CoverBehaviorUIFactory.INSTANCE.init(); - TileEntityClipboardUIFactory.INSTANCE.init(); SimpleCapabilityManager.init(); OreDictUnifier.init(); NBTUtil.registerSerializers(); diff --git a/src/main/java/gregtech/common/CommonProxy.java b/src/main/java/gregtech/common/CommonProxy.java index e95d321ad1a..1fea04fc5e0 100644 --- a/src/main/java/gregtech/common/CommonProxy.java +++ b/src/main/java/gregtech/common/CommonProxy.java @@ -82,7 +82,6 @@ public static void registerBlocks(RegistryEvent.Register event) { registry.register(LEAVES); registry.register(SAPLING); registry.register(SURFACE_ROCK); - registry.register(CLIPBOARD_BLOCK); COMPRESSED.values().stream().distinct().forEach(registry::register); FRAMES.values().stream().distinct().forEach(registry::register); diff --git a/src/main/java/gregtech/common/blocks/MetaBlocks.java b/src/main/java/gregtech/common/blocks/MetaBlocks.java index 25a1d914e7d..f13e754b681 100644 --- a/src/main/java/gregtech/common/blocks/MetaBlocks.java +++ b/src/main/java/gregtech/common/blocks/MetaBlocks.java @@ -16,8 +16,6 @@ import gregtech.api.unification.material.type.SolidMaterial; import gregtech.api.unification.ore.OrePrefix; import gregtech.api.unification.ore.StoneType; -import gregtech.common.blocks.clipboard.BlockClipboard; -import gregtech.common.blocks.clipboard.TileEntityClipboard; import gregtech.common.blocks.foam.BlockFoam; import gregtech.common.blocks.foam.BlockPetrifiedFoam; import gregtech.common.blocks.modelfactories.BakedModelHandler; @@ -106,7 +104,6 @@ private MetaBlocks() { public static BlockGregSapling SAPLING; public static BlockSurfaceRock SURFACE_ROCK; - public static BlockClipboard CLIPBOARD_BLOCK; public static Map COMPRESSED = new HashMap<>(); public static Map FRAMES = new HashMap<>(); @@ -176,8 +173,6 @@ public static void init() { SURFACE_ROCK = new BlockSurfaceRock(); SURFACE_ROCK.setRegistryName("surface_rock_new"); - CLIPBOARD_BLOCK = new BlockClipboard(); - CLIPBOARD_BLOCK.setRegistryName("clipboard"); StoneType.init(); @@ -299,7 +294,6 @@ public static void registerTileEntity() { GameRegistry.registerTileEntity(TileEntityFluidPipe.class, new ResourceLocation(GTValues.MODID, "fluid_pipe")); GameRegistry.registerTileEntity(TileEntityFluidPipeTickable.class, new ResourceLocation(GTValues.MODID, "fluid_pipe_active")); GameRegistry.registerTileEntity(TileEntitySurfaceRock.class, new ResourceLocation(GTValues.MODID, "surface_rock")); - GameRegistry.registerTileEntity(TileEntityClipboard.class, new ResourceLocation(GTValues.MODID, "clipboard")); } @SideOnly(Side.CLIENT) @@ -412,7 +406,6 @@ protected ModelResourceLocation getModelResourceLocation(IBlockState state) { FLUID_BLOCKS.forEach(modelHandler::addFluidBlock); modelHandler.addBuiltInBlock(SURFACE_ROCK, "stone_andesite"); - modelHandler.addBuiltInBlock(CLIPBOARD_BLOCK, "stone_andesite"); ClientRegistry.bindTileEntitySpecialRenderer(MetaTileEntityHolder.class, new MetaTileEntityTESR()); diff --git a/src/main/java/gregtech/common/blocks/clipboard/BlockClipboard.java b/src/main/java/gregtech/common/blocks/clipboard/BlockClipboard.java deleted file mode 100644 index 9ccaa40e4bf..00000000000 --- a/src/main/java/gregtech/common/blocks/clipboard/BlockClipboard.java +++ /dev/null @@ -1,171 +0,0 @@ -package gregtech.common.blocks.clipboard; - -import codechicken.lib.raytracer.CuboidRayTraceResult; -import codechicken.lib.raytracer.RayTracer; -import gregtech.api.metatileentity.MetaTileEntity; -import gregtech.api.metatileentity.MetaTileEntityHolder; -import gregtech.api.metatileentity.MetaTileEntityUIFactory; -import gregtech.api.util.GTUtility; -import gregtech.common.render.clipboard.TileEntityClipboardRenderer; -import net.minecraft.block.Block; -import net.minecraft.block.ITileEntityProvider; -import net.minecraft.block.SoundType; -import net.minecraft.block.material.Material; -import net.minecraft.block.state.BlockFaceShape; -import net.minecraft.block.state.IBlockState; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.entity.player.EntityPlayerMP; -import net.minecraft.item.ItemStack; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.EnumBlockRenderType; -import net.minecraft.util.EnumFacing; -import net.minecraft.util.EnumHand; -import net.minecraft.util.NonNullList; -import net.minecraft.util.math.AxisAlignedBB; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.RayTraceResult; -import net.minecraft.world.IBlockAccess; -import net.minecraft.world.World; -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -public class BlockClipboard extends Block implements ITileEntityProvider { - - private static final AxisAlignedBB CLIPBOARD_AABB = new AxisAlignedBB(2.75 / 16.0, 0.0, 0.0, 13.25 / 16.0, 1.0, 0.4 / 16.0); - - public static final BlockClipboard INSTANCE = new BlockClipboard(); // Mainly to access the default state. - - protected ThreadLocal tileEntities = new ThreadLocal<>(); - - public BlockClipboard() { - super(Material.WOOD); - setHardness(0); - setSoundType(SoundType.WOOD); - setTranslationKey("clipboard"); - setLightOpacity(1); - } - - @Override - @Nonnull - public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos) { - if(getTileEntity(source, pos) != null) { - return GTUtility.rotateAroundYAxis(CLIPBOARD_AABB, EnumFacing.NORTH, getTileEntity(source, pos).getFrontFacing()); - } else { - return CLIPBOARD_AABB; - } - } - - private ItemStack getDropStack(IBlockAccess blockAccess, BlockPos pos, IBlockState blockState) { - if(this.hasTileEntity(blockState)) { - return this.tileEntities.get().getClipboard(); - } - return ItemStack.EMPTY; - } - - @Override - @Nonnull - public ItemStack getPickBlock(IBlockState state, RayTraceResult target, World world, BlockPos pos, EntityPlayer player) { - return getDropStack(world, pos, state); - } - - @Override - public void getDrops(NonNullList drops, IBlockAccess world, BlockPos pos, IBlockState state, int fortune) { - drops.add(this.getDropStack(world, pos, state)); - } - - @Override - public boolean isFullCube(IBlockState state) { - return false; - } - - @Override - public boolean isOpaqueCube(IBlockState state) { - return false; - } - - @Override - @Nonnull - @SideOnly(Side.CLIENT) - public EnumBlockRenderType getRenderType(IBlockState state) { - return TileEntityClipboardRenderer.BLOCK_RENDER_TYPE; - } - - @Override - public void neighborChanged(IBlockState state, World worldIn, BlockPos pos, Block blockIn, BlockPos fromPos) { - EnumFacing directionHangedFrom = getTileEntity(worldIn, pos).getFrontFacing().getOpposite(); - if (pos.offset(directionHangedFrom).equals(fromPos)) { - if (worldIn.getBlockState(fromPos).getBlockFaceShape(worldIn, fromPos, EnumFacing.UP) != BlockFaceShape.SOLID) { - worldIn.destroyBlock(pos, true); - } - } - } - - @Override - @Nonnull - public BlockFaceShape getBlockFaceShape(IBlockAccess worldIn, IBlockState state, BlockPos pos, EnumFacing face) { - return BlockFaceShape.UNDEFINED; - } - - @Override - public void breakBlock(World worldIn, BlockPos pos, IBlockState state) { - TileEntityClipboard tileEntity = getTileEntity(worldIn, pos); - if (tileEntity != null) { - tileEntities.set(tileEntity); - } - - super.breakBlock(worldIn, pos, state); - } - - @Override - public void harvestBlock(World worldIn, EntityPlayer player, BlockPos pos, IBlockState state, @Nullable TileEntity te, ItemStack stack) { - tileEntities.set(te == null ? tileEntities.get() : (TileEntityClipboard) te); - super.harvestBlock(worldIn, player, pos, state, te, stack); - tileEntities.set(null); - } - - public static TileEntityClipboard getTileEntity(IBlockAccess world, BlockPos pos) { - TileEntity tileEntity = world.getTileEntity(pos); - if (tileEntity instanceof TileEntityClipboard) - return ((TileEntityClipboard)tileEntity); - return null; - } - - @Nullable - @Override - public TileEntity createNewTileEntity(World worldIn, int meta) { - TileEntityClipboard clipboard = new TileEntityClipboard(); - clipboard.setWorld(worldIn); - tileEntities.set(new TileEntityClipboard()); - return tileEntities.get(); - } - - public TileEntity createNewTileEntity(World worldIn, int meta, BlockPos pos) { - TileEntityClipboard clipboard = new TileEntityClipboard(); - clipboard.setWorld(worldIn); - clipboard.setPos(pos); - tileEntities.set(new TileEntityClipboard()); - return tileEntities.get(); - } - - @Override - public boolean hasTileEntity() { - return true; - } - - @Override - public boolean onBlockActivated(World worldIn, BlockPos pos, IBlockState state, EntityPlayer playerIn, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ) { - TileEntityClipboard tileEntity = getTileEntity(worldIn, pos); - RayTraceResult rayTraceResult = RayTracer.retraceBlock(worldIn, playerIn, pos); - ItemStack itemStack = playerIn.getHeldItem(hand); - if (tileEntity == null || rayTraceResult == null) { - return false; - } - if(tileEntity.getWorld() != null && !tileEntity.getWorld().isRemote) { - TileEntityClipboardUIFactory.INSTANCE.openUI(this.tileEntities.get(), (EntityPlayerMP) playerIn); - } - return true; - } -} diff --git a/src/main/java/gregtech/common/blocks/clipboard/TileEntityClipboard.java b/src/main/java/gregtech/common/blocks/clipboard/TileEntityClipboard.java deleted file mode 100644 index 6d1974f98f2..00000000000 --- a/src/main/java/gregtech/common/blocks/clipboard/TileEntityClipboard.java +++ /dev/null @@ -1,99 +0,0 @@ -package gregtech.common.blocks.clipboard; - -import codechicken.lib.raytracer.CuboidRayTraceResult; -import codechicken.lib.render.CCRenderState; -import codechicken.lib.vec.Matrix4; -import gregtech.api.capability.impl.FluidHandlerProxy; -import gregtech.api.cover.CoverBehavior; -import gregtech.api.cover.CoverBehaviorUIFactory; -import gregtech.api.gui.IUIHolder; -import gregtech.api.gui.ModularUI; -import gregtech.api.items.gui.PlayerInventoryHolder; -import gregtech.api.items.itemhandlers.InaccessibleItemStackHandler; -import gregtech.api.items.metaitem.MetaItem; -import gregtech.api.items.metaitem.stats.IItemBehaviour; -import gregtech.api.metatileentity.MetaTileEntity; -import gregtech.api.metatileentity.MetaTileEntityHolder; -import gregtech.api.unification.material.Materials; -import gregtech.api.unification.material.type.Material; -import gregtech.common.items.behaviors.ClipboardBehaviour; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.entity.player.EntityPlayerMP; -import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NBTBase; -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.nbt.NBTTagList; -import net.minecraft.nbt.NBTTagString; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.BlockRenderLayer; -import net.minecraft.util.EnumFacing; -import net.minecraft.util.EnumHand; -import net.minecraft.util.ResourceLocation; -import net.minecraftforge.common.util.Constants; -import net.minecraftforge.items.ItemStackHandler; - -import java.util.List; -import java.util.Optional; - -import static gregtech.common.items.MetaItems.CLIPBOARD; - -public class TileEntityClipboard extends TileEntity implements IUIHolder { - - private ItemStackHandler clipboardStackHandler = new ItemStackHandler(1); - protected EnumFacing frontFacing = EnumFacing.NORTH; - - - - public void openUI(EntityPlayerMP player) { - TileEntityClipboardUIFactory.INSTANCE.openUI( this, player); - } - - protected ModularUI createUI(EntityPlayer entityPlayer) { - if(clipboardStackHandler.getStackInSlot(0) == ItemStack.EMPTY) { - clipboardStackHandler.setStackInSlot(0, CLIPBOARD.getStackForm()); - } - if(clipboardStackHandler.getStackInSlot(0).isItemEqual(CLIPBOARD.getStackForm())) { - List behaviours = ((MetaItem) clipboardStackHandler.getStackInSlot(0).getItem()).getBehaviours(clipboardStackHandler.getStackInSlot(0)); - Optional clipboardBehaviour = behaviours.stream().filter((x) -> x instanceof ClipboardBehaviour).findFirst(); - if(!clipboardBehaviour.isPresent()) - return null; - if(clipboardBehaviour.get() instanceof ClipboardBehaviour) { - return ((ClipboardBehaviour) clipboardBehaviour.get()).createUI(new PlayerInventoryHolder(entityPlayer, entityPlayer.getActiveHand(), clipboardStackHandler.getStackInSlot(0)), entityPlayer); - } - } - return null; - } - - public ItemStack getClipboard() { - return this.clipboardStackHandler.getStackInSlot(0).copy(); - } - - public void setClipboard(ItemStack stack) { - this.clipboardStackHandler.setStackInSlot(0, stack); - } - - public EnumFacing getFrontFacing() { - return frontFacing; - } - - public void setFrontFacing(EnumFacing facing) { - if(facing == EnumFacing.UP || facing == EnumFacing.DOWN) - throw new IllegalArgumentException("Clipboards can't face up or down!"); - frontFacing = facing; - } - - @Override - public boolean isValid() { - return true; - } - - @Override - public boolean isRemote() { - return this.getWorld().isRemote; - } - - @Override - public void markAsDirty() { - super.markDirty(); - } -} diff --git a/src/main/java/gregtech/common/blocks/clipboard/TileEntityClipboardUIFactory.java b/src/main/java/gregtech/common/blocks/clipboard/TileEntityClipboardUIFactory.java deleted file mode 100644 index e52a4d91b0d..00000000000 --- a/src/main/java/gregtech/common/blocks/clipboard/TileEntityClipboardUIFactory.java +++ /dev/null @@ -1,37 +0,0 @@ -package gregtech.common.blocks.clipboard; - -import gregtech.api.GTValues; -import gregtech.api.gui.ModularUI; -import gregtech.api.gui.UIFactory; -import gregtech.api.metatileentity.MetaTileEntityHolder; -import gregtech.api.metatileentity.MetaTileEntityUIFactory; -import net.minecraft.client.Minecraft; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.network.PacketBuffer; -import net.minecraft.util.ResourceLocation; -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; - -public class TileEntityClipboardUIFactory extends UIFactory { - public static final TileEntityClipboardUIFactory INSTANCE = new TileEntityClipboardUIFactory(); - - public void init() { - UIFactory.FACTORY_REGISTRY.register(3, new ResourceLocation(GTValues.MODID, "clipboard_factory"), this); - } - - @Override - protected ModularUI createUITemplate(TileEntityClipboard clipboard, EntityPlayer entityPlayer) { - return clipboard.createUI(entityPlayer); - } - - @Override - @SideOnly(Side.CLIENT) - protected TileEntityClipboard readHolderFromSyncData(PacketBuffer syncData) { - return (TileEntityClipboard) Minecraft.getMinecraft().world.getTileEntity(syncData.readBlockPos()); - } - - @Override - protected void writeHolderToSyncData(PacketBuffer syncData, TileEntityClipboard holder) { - syncData.writeBlockPos(holder.getPos()); - } -} diff --git a/src/main/java/gregtech/common/metatileentities/MetaTileEntities.java b/src/main/java/gregtech/common/metatileentities/MetaTileEntities.java index df94c073638..654c83da3d4 100644 --- a/src/main/java/gregtech/common/metatileentities/MetaTileEntities.java +++ b/src/main/java/gregtech/common/metatileentities/MetaTileEntities.java @@ -11,7 +11,6 @@ import gregtech.api.unification.material.Materials; import gregtech.api.util.GTLog; import gregtech.common.ConfigHolder; -import gregtech.common.blocks.clipboard.TileEntityClipboard; import gregtech.common.metatileentities.electric.*; import gregtech.common.metatileentities.electric.multiblockpart.MetaTileEntityEnergyHatch; import gregtech.common.metatileentities.electric.multiblockpart.MetaTileEntityFluidHatch; From 68b3a32ccec2be2721f2b14aac4a6afdd1a0c637 Mon Sep 17 00:00:00 2001 From: bruberu <80226372+bruberu@users.noreply.github.com> Date: Wed, 28 Jul 2021 13:01:59 -0500 Subject: [PATCH 11/42] Complete step two of four --- .../java/gregtech/common/ClientProxy.java | 1 + .../gregtech/common/blocks/MetaBlocks.java | 6 +++++ .../items/behaviors/ClipboardBehaviour.java | 3 ++- .../MetaTileEntityClipboard.java | 27 ++++++++++++++++++- 4 files changed, 35 insertions(+), 2 deletions(-) diff --git a/src/main/java/gregtech/common/ClientProxy.java b/src/main/java/gregtech/common/ClientProxy.java index 16f7e1e62d7..16e81ac04a7 100644 --- a/src/main/java/gregtech/common/ClientProxy.java +++ b/src/main/java/gregtech/common/ClientProxy.java @@ -116,6 +116,7 @@ public void onPreLoad() { public void onLoad() { super.onLoad(); registerColors(); + MetaBlocks.registerSpecialModels(); } @Override diff --git a/src/main/java/gregtech/common/blocks/MetaBlocks.java b/src/main/java/gregtech/common/blocks/MetaBlocks.java index f13e754b681..10335352406 100644 --- a/src/main/java/gregtech/common/blocks/MetaBlocks.java +++ b/src/main/java/gregtech/common/blocks/MetaBlocks.java @@ -24,6 +24,7 @@ import gregtech.common.blocks.wood.BlockGregLeaves; import gregtech.common.blocks.wood.BlockGregLog; import gregtech.common.blocks.wood.BlockGregSapling; +import gregtech.common.metatileentities.MetaTileEntityClipboard; import gregtech.common.pipelike.cable.BlockCable; import gregtech.common.pipelike.cable.Insulation; import gregtech.common.pipelike.cable.WireProperties; @@ -325,6 +326,11 @@ public static void registerItemModels() { ORES.stream().distinct().forEach(MetaBlocks::registerItemModel); } + @SideOnly(Side.CLIENT) + public static void registerSpecialModels() { // For registering particular models in, usually for MTEs. + MetaTileEntityClipboard.initModel(); + } + @SideOnly(Side.CLIENT) private static void registerItemModel(Block block) { for (IBlockState state : block.getBlockState().getValidStates()) { diff --git a/src/main/java/gregtech/common/items/behaviors/ClipboardBehaviour.java b/src/main/java/gregtech/common/items/behaviors/ClipboardBehaviour.java index 6f80d3771f8..6f790d4f9da 100644 --- a/src/main/java/gregtech/common/items/behaviors/ClipboardBehaviour.java +++ b/src/main/java/gregtech/common/items/behaviors/ClipboardBehaviour.java @@ -210,10 +210,11 @@ public ActionResult onItemUse(EntityPlayer player, World world, Block if (clipboard != null) { clipboard.setFrontFacing(playerFacing); clipboard.setClipboard(heldItem); + return ActionResult.newResult(EnumActionResult.SUCCESS, player.isCreative() ? heldItem : ItemStack.EMPTY); } } } } - return ActionResult.newResult(EnumActionResult.SUCCESS, player.isCreative() ? heldItem : ItemStack.EMPTY); + return ActionResult.newResult(EnumActionResult.FAIL, heldItem); } } diff --git a/src/main/java/gregtech/common/metatileentities/MetaTileEntityClipboard.java b/src/main/java/gregtech/common/metatileentities/MetaTileEntityClipboard.java index 1ffc9e324c0..acd73c88729 100644 --- a/src/main/java/gregtech/common/metatileentities/MetaTileEntityClipboard.java +++ b/src/main/java/gregtech/common/metatileentities/MetaTileEntityClipboard.java @@ -4,6 +4,7 @@ import codechicken.lib.raytracer.IndexedCuboid6; import codechicken.lib.render.CCRenderState; import codechicken.lib.render.pipeline.IVertexOperation; +import codechicken.lib.texture.TextureUtils; import codechicken.lib.vec.Matrix4; import gregtech.api.gui.ModularUI; import gregtech.api.items.gui.PlayerInventoryHolder; @@ -14,8 +15,14 @@ import gregtech.api.metatileentity.MetaTileEntity; import gregtech.api.metatileentity.MetaTileEntityHolder; import gregtech.api.metatileentity.MetaTileEntityUIFactory; +import gregtech.api.util.GTLog; import gregtech.api.util.GTUtility; +import gregtech.common.blocks.models.ModelCache; import gregtech.common.items.behaviors.ClipboardBehaviour; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.block.model.IBakedModel; +import net.minecraft.client.renderer.block.model.ModelResourceLocation; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.item.ItemStack; @@ -25,6 +32,12 @@ import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.world.World; +import net.minecraftforge.client.model.IModel; +import net.minecraftforge.client.model.ModelLoader; +import net.minecraftforge.client.model.ModelLoaderRegistry; +import net.minecraftforge.common.model.TRSRTransformation; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; import net.minecraftforge.items.ItemStackHandler; import javax.annotation.Nullable; @@ -36,7 +49,8 @@ public class MetaTileEntityClipboard extends MetaTileEntity implements IRenderMetaTileEntity { private static final AxisAlignedBB CLIPBOARD_AABB = new AxisAlignedBB(2.75 / 16.0, 0.0, 0.0, 13.25 / 16.0, 1.0, 0.4 / 16.0); - + public static final ResourceLocation MODEL_RESOURCE_LOCATION = new ResourceLocation("gregtech", "block/clipboard"); + public static ModelCache cache = new ModelCache(); public MetaTileEntityClipboard(ResourceLocation metaTileEntityId) { super(metaTileEntityId); @@ -136,4 +150,15 @@ public String getHarvestTool() { public void addCollisionBoundingBox(List collisionList) { collisionList.add(new IndexedCuboid6(null, GTUtility.rotateAroundYAxis(CLIPBOARD_AABB, EnumFacing.NORTH, this.getFrontFacing()))); } + + @SideOnly(Side.CLIENT) + public static void initModel() { + try { + IModel model = ModelLoaderRegistry.getModel(MODEL_RESOURCE_LOCATION); + IBakedModel bakedModel = model.bake(TRSRTransformation.identity(), DefaultVertexFormats.BLOCK, location -> Minecraft.getMinecraft().getTextureMapBlocks().getAtlasSprite(location.toString())); + cache.addToCache(bakedModel, "bakedModel"); + } catch (Exception err) { + GTLog.logger.error("MetaTileEntityClipboard did not acquire model! " + err.getMessage()); + } + } } From 3d44654a606aff7d15ca6ec2c5beda0ed140d77e Mon Sep 17 00:00:00 2001 From: bruberu <80226372+bruberu@users.noreply.github.com> Date: Thu, 29 Jul 2021 20:53:47 -0500 Subject: [PATCH 12/42] A husk of a renderMetaTileEntityDynamic --- .../common/blocks/models/ModelCache.java | 2 +- .../common/blocks/models/ModelClipboard.java | 2 +- .../items/behaviors/ClipboardBehaviour.java | 3 +- .../MetaTileEntityClipboard.java | 38 +++++++++++++++---- 4 files changed, 34 insertions(+), 11 deletions(-) diff --git a/src/main/java/gregtech/common/blocks/models/ModelCache.java b/src/main/java/gregtech/common/blocks/models/ModelCache.java index f74b7d84681..dbdbed64843 100644 --- a/src/main/java/gregtech/common/blocks/models/ModelCache.java +++ b/src/main/java/gregtech/common/blocks/models/ModelCache.java @@ -13,7 +13,7 @@ public void addToCache(IBakedModel model, String name) { this.models.add(pack); } - public boolean hasModel(String name) { + public boolean findModel(String name) { boolean output = false; for (int i = 0; i < this.models.size(); i++) { ModelCachePackage pack = this.models.get(i); diff --git a/src/main/java/gregtech/common/blocks/models/ModelClipboard.java b/src/main/java/gregtech/common/blocks/models/ModelClipboard.java index d5adc23da94..c346cde8da0 100644 --- a/src/main/java/gregtech/common/blocks/models/ModelClipboard.java +++ b/src/main/java/gregtech/common/blocks/models/ModelClipboard.java @@ -77,7 +77,7 @@ private void getModel(IBlockState state, ItemStack stack) { } if (state == null /*&& stack.getItem() == ItemClipboard.instance*/) { String cacheName = "clipboard" + getModelPartsNumberString(stack); - if (this.cache.hasModel(cacheName)) { + if (this.cache.findModel(cacheName)) { this.baseModel = this.cache.getCurrentMatch(); } else { modelState = new OBJModel.OBJState(getModelParts(stack), true); diff --git a/src/main/java/gregtech/common/items/behaviors/ClipboardBehaviour.java b/src/main/java/gregtech/common/items/behaviors/ClipboardBehaviour.java index 6f790d4f9da..5a8afa270ef 100644 --- a/src/main/java/gregtech/common/items/behaviors/ClipboardBehaviour.java +++ b/src/main/java/gregtech/common/items/behaviors/ClipboardBehaviour.java @@ -189,7 +189,8 @@ public ActionResult onItemRightClick(World world, EntityPlayer player @Override public ActionResult onItemUse(EntityPlayer player, World world, BlockPos pos, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ) { - ItemStack heldItem = player.getHeldItem(hand); + ItemStack heldItem = player.getHeldItem(hand).copy(); + heldItem.setCount(1); // don't place multiple items at a time EnumFacing playerFacing = player.getHorizontalFacing(); // Make sure it's the right block Block testBlock = world.getBlockState(pos).getBlock(); diff --git a/src/main/java/gregtech/common/metatileentities/MetaTileEntityClipboard.java b/src/main/java/gregtech/common/metatileentities/MetaTileEntityClipboard.java index acd73c88729..603ce4075ef 100644 --- a/src/main/java/gregtech/common/metatileentities/MetaTileEntityClipboard.java +++ b/src/main/java/gregtech/common/metatileentities/MetaTileEntityClipboard.java @@ -6,23 +6,28 @@ import codechicken.lib.render.pipeline.IVertexOperation; import codechicken.lib.texture.TextureUtils; import codechicken.lib.vec.Matrix4; +import gregtech.api.block.machines.BlockMachine; import gregtech.api.gui.ModularUI; import gregtech.api.items.gui.PlayerInventoryHolder; import gregtech.api.items.itemhandlers.InaccessibleItemStackHandler; import gregtech.api.items.metaitem.MetaItem; import gregtech.api.items.metaitem.stats.IItemBehaviour; -import gregtech.api.metatileentity.IRenderMetaTileEntity; -import gregtech.api.metatileentity.MetaTileEntity; -import gregtech.api.metatileentity.MetaTileEntityHolder; -import gregtech.api.metatileentity.MetaTileEntityUIFactory; +import gregtech.api.metatileentity.*; import gregtech.api.util.GTLog; import gregtech.api.util.GTUtility; +import gregtech.common.blocks.MetaBlocks; import gregtech.common.blocks.models.ModelCache; import gregtech.common.items.behaviors.ClipboardBehaviour; +import net.minecraft.block.state.IBlockState; import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.BlockRendererDispatcher; +import net.minecraft.client.renderer.BufferBuilder; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.Tessellator; import net.minecraft.client.renderer.block.model.IBakedModel; import net.minecraft.client.renderer.block.model.ModelResourceLocation; import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.creativetab.CreativeTabs; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.item.ItemStack; @@ -39,6 +44,7 @@ import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; import net.minecraftforge.items.ItemStackHandler; +import org.lwjgl.opengl.GL11; import javax.annotation.Nullable; @@ -57,8 +63,25 @@ public MetaTileEntityClipboard(ResourceLocation metaTileEntityId) { } @Override - public void renderMetaTileEntityDynamic(double x, double y, double z, float partialTicks) { + public void getSubItems(CreativeTabs creativeTab, NonNullList subItems) { } + public void renderMetaTileEntityDynamic(double x, double y, double z, float partialTicks) { + if(this.getWorld() == null || !this.getWorld().isRemote) + return; + Tessellator tessellator = Tessellator.getInstance(); + BufferBuilder bufferBuilder = tessellator.getBuffer(); + IBlockState blockState = this.getWorld().getBlockState(this.getPos()); + BlockRendererDispatcher renderer = Minecraft.getMinecraft().getBlockRendererDispatcher(); + if(cache.findModel("bakedModel")) { + IBakedModel model = cache.getCurrentMatch(); + bufferBuilder.begin(GL11.GL_QUADS, DefaultVertexFormats.BLOCK); + GlStateManager.pushMatrix(); + GlStateManager.rotate((frontFacing.getHorizontalAngle()), 0.0F, 1.0F, 0.0F); + GlStateManager.translate(x, y, z); + renderer.getBlockModelRenderer().renderModel(this.getWorld(), model, blockState, this.getPos(), bufferBuilder, true); + tessellator.draw(); + GlStateManager.popMatrix(); + } } @Override @@ -75,8 +98,6 @@ public boolean isOpaqueCube() { return false; } - - @Override public MetaTileEntity createMetaTileEntity(MetaTileEntityHolder holder) { return new MetaTileEntityClipboard(metaTileEntityId); @@ -115,12 +136,13 @@ public void setClipboard(ItemStack stack) { @Override public void getDrops(NonNullList dropsList, @Nullable EntityPlayer harvester) { + dropsList.clear(); dropsList.add(this.getClipboard()); } @Override public float getBlockHardness() { - return 0; + return 10; } @Override From c6e40622dccd8341481b4090193841fe9d47e954 Mon Sep 17 00:00:00 2001 From: bruberu <80226372+bruberu@users.noreply.github.com> Date: Sat, 31 Jul 2021 14:16:48 -0500 Subject: [PATCH 13/42] Fix model rendering --- .../api/render/ClipboardRenderer.java | 67 ++++++++++++++ .../java/gregtech/api/render/Textures.java | 1 + .../java/gregtech/common/ClientProxy.java | 1 - .../gregtech/common/blocks/MetaBlocks.java | 5 - .../items/behaviors/ClipboardBehaviour.java | 9 +- .../MetaTileEntityClipboard.java | 86 +++++++----------- .../textures/blocks/clipboard/clip.png | Bin 0 -> 343 bytes .../textures/blocks/clipboard/page.png | Bin 0 -> 139 bytes .../textures/blocks/clipboard/wood.png | Bin 0 -> 438 bytes 9 files changed, 108 insertions(+), 61 deletions(-) create mode 100644 src/main/java/gregtech/api/render/ClipboardRenderer.java create mode 100644 src/main/resources/assets/gregtech/textures/blocks/clipboard/clip.png create mode 100644 src/main/resources/assets/gregtech/textures/blocks/clipboard/page.png create mode 100644 src/main/resources/assets/gregtech/textures/blocks/clipboard/wood.png diff --git a/src/main/java/gregtech/api/render/ClipboardRenderer.java b/src/main/java/gregtech/api/render/ClipboardRenderer.java new file mode 100644 index 00000000000..4e6471275be --- /dev/null +++ b/src/main/java/gregtech/api/render/ClipboardRenderer.java @@ -0,0 +1,67 @@ +package gregtech.api.render; + +import codechicken.lib.render.CCRenderState; +import codechicken.lib.render.pipeline.IVertexOperation; +import codechicken.lib.texture.TextureUtils; +import codechicken.lib.vec.Cuboid6; +import codechicken.lib.vec.Matrix4; +import codechicken.lib.vec.Rotation; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.client.renderer.texture.TextureMap; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; + +public class ClipboardRenderer implements TextureUtils.IIconRegister { + + private static final Cuboid6 pageBox = new Cuboid6(3 / 16.0, 0.25 / 16.0, 0.25 / 16.0, 13 / 16.0, 14.25 / 16.0, 0.3 / 16.0); + private static final Cuboid6 boardBox = new Cuboid6(2.75 / 16.0, 0 / 16.0, 0 / 16.0, 13.25 / 16.0, 15.25 / 16.0, 0.25 / 16.0); + private static final Cuboid6 clipBox = new Cuboid6(5.75 / 16.0, 14.75 / 16.0, 0.25 / 16.0, 10.25 / 16.0, 15.5 / 16.0, 0.4 / 16.0); + private static final Cuboid6 graspBox = new Cuboid6(7 / 16.0, 15.25 / 16.0, 0.1 / 16.0, 9 / 16.0, 16 / 16.0, 0.35 / 16.0); + + private static final List rotations = Arrays.asList(EnumFacing.NORTH, EnumFacing.WEST, EnumFacing.SOUTH, EnumFacing.EAST); + + private static HashMap boxTextureMap = new HashMap<>(); + + @SideOnly(Side.CLIENT) + private TextureAtlasSprite[] textures = new TextureAtlasSprite[3]; + + + public ClipboardRenderer() { + Textures.iconRegisters.add(this); + } + + @Override + public void registerIcons(TextureMap textureMap) { + this.textures[0] = textureMap.registerSprite(new ResourceLocation("gregtech:blocks/clipboard/wood")); + boxTextureMap.put(boardBox, this.textures[0]); + this.textures[1] = textureMap.registerSprite(new ResourceLocation("gregtech:blocks/clipboard/clip")); + boxTextureMap.put(clipBox, this.textures[1]); + boxTextureMap.put(graspBox, this.textures[1]); + this.textures[2] = textureMap.registerSprite(new ResourceLocation("gregtech:blocks/clipboard/page")); + boxTextureMap.put(pageBox, this.textures[2]); + } + + @SideOnly(Side.CLIENT) + public void render(CCRenderState renderState, Matrix4 translation, IVertexOperation[] pipeline, EnumFacing rotation) { + translation.translate(0.5, 0.5, 0.5); + translation.rotate(Math.toRadians(90.0 * rotations.indexOf(rotation)), Rotation.axes[1]); + translation.translate(-0.5, -0.5, -0.5); + + + for (EnumFacing renderSide : EnumFacing.VALUES) { + boxTextureMap.forEach((box, sprite) -> Textures.renderFace(renderState, translation, pipeline, renderSide, box, sprite)); + } + } + + + @SideOnly(Side.CLIENT) + public TextureAtlasSprite getParticleTexture() { + return textures[0]; + } +} diff --git a/src/main/java/gregtech/api/render/Textures.java b/src/main/java/gregtech/api/render/Textures.java index a59e7fa0ef2..5f7fe866bc9 100644 --- a/src/main/java/gregtech/api/render/Textures.java +++ b/src/main/java/gregtech/api/render/Textures.java @@ -170,6 +170,7 @@ public class Textures { public static SimpleOverlayRenderer BLOWER_ACTIVE_OVERLAY = new SimpleOverlayRenderer("overlay/machine/overlay_blower_active"); public static SimpleOverlayRenderer INFINITE_EMITTER_FACE = new SimpleOverlayRenderer("overlay/machine/energy_emitter"); public static SimpleOverlayRenderer STEAM_VENT_OVERLAY = new SimpleOverlayRenderer("overlay/machine/steam_vent"); + public static ClipboardRenderer CLIPBOARD_RENDERER = new ClipboardRenderer(); static { for (int i = 0; i < VOLTAGE_CASINGS.length; i++) { diff --git a/src/main/java/gregtech/common/ClientProxy.java b/src/main/java/gregtech/common/ClientProxy.java index 16e81ac04a7..16f7e1e62d7 100644 --- a/src/main/java/gregtech/common/ClientProxy.java +++ b/src/main/java/gregtech/common/ClientProxy.java @@ -116,7 +116,6 @@ public void onPreLoad() { public void onLoad() { super.onLoad(); registerColors(); - MetaBlocks.registerSpecialModels(); } @Override diff --git a/src/main/java/gregtech/common/blocks/MetaBlocks.java b/src/main/java/gregtech/common/blocks/MetaBlocks.java index 10335352406..cdd3a5ec393 100644 --- a/src/main/java/gregtech/common/blocks/MetaBlocks.java +++ b/src/main/java/gregtech/common/blocks/MetaBlocks.java @@ -326,11 +326,6 @@ public static void registerItemModels() { ORES.stream().distinct().forEach(MetaBlocks::registerItemModel); } - @SideOnly(Side.CLIENT) - public static void registerSpecialModels() { // For registering particular models in, usually for MTEs. - MetaTileEntityClipboard.initModel(); - } - @SideOnly(Side.CLIENT) private static void registerItemModel(Block block) { for (IBlockState state : block.getBlockState().getValidStates()) { diff --git a/src/main/java/gregtech/common/items/behaviors/ClipboardBehaviour.java b/src/main/java/gregtech/common/items/behaviors/ClipboardBehaviour.java index 5a8afa270ef..fe3cfaf2068 100644 --- a/src/main/java/gregtech/common/items/behaviors/ClipboardBehaviour.java +++ b/src/main/java/gregtech/common/items/behaviors/ClipboardBehaviour.java @@ -211,11 +211,16 @@ public ActionResult onItemUse(EntityPlayer player, World world, Block if (clipboard != null) { clipboard.setFrontFacing(playerFacing); clipboard.setClipboard(heldItem); - return ActionResult.newResult(EnumActionResult.SUCCESS, player.isCreative() ? heldItem : ItemStack.EMPTY); + ItemStack returnedStack = player.getHeldItem(hand); + if(!player.isCreative()) + { + returnedStack.setCount(player.getHeldItem(hand).getCount() - 1); + } + return ActionResult.newResult(EnumActionResult.SUCCESS, returnedStack); } } } } - return ActionResult.newResult(EnumActionResult.FAIL, heldItem); + return ActionResult.newResult(EnumActionResult.FAIL, player.getHeldItem(hand)); } } diff --git a/src/main/java/gregtech/common/metatileentities/MetaTileEntityClipboard.java b/src/main/java/gregtech/common/metatileentities/MetaTileEntityClipboard.java index 603ce4075ef..9452f5ef4ae 100644 --- a/src/main/java/gregtech/common/metatileentities/MetaTileEntityClipboard.java +++ b/src/main/java/gregtech/common/metatileentities/MetaTileEntityClipboard.java @@ -4,28 +4,26 @@ import codechicken.lib.raytracer.IndexedCuboid6; import codechicken.lib.render.CCRenderState; import codechicken.lib.render.pipeline.IVertexOperation; -import codechicken.lib.texture.TextureUtils; import codechicken.lib.vec.Matrix4; -import gregtech.api.block.machines.BlockMachine; import gregtech.api.gui.ModularUI; import gregtech.api.items.gui.PlayerInventoryHolder; import gregtech.api.items.itemhandlers.InaccessibleItemStackHandler; import gregtech.api.items.metaitem.MetaItem; import gregtech.api.items.metaitem.stats.IItemBehaviour; -import gregtech.api.metatileentity.*; -import gregtech.api.util.GTLog; +import gregtech.api.metatileentity.IFastRenderMetaTileEntity; +import gregtech.api.metatileentity.MetaTileEntity; +import gregtech.api.metatileentity.MetaTileEntityHolder; +import gregtech.api.metatileentity.MetaTileEntityUIFactory; import gregtech.api.util.GTUtility; -import gregtech.common.blocks.MetaBlocks; import gregtech.common.blocks.models.ModelCache; import gregtech.common.items.behaviors.ClipboardBehaviour; -import net.minecraft.block.state.IBlockState; import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.BlockRendererDispatcher; import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.RenderHelper; import net.minecraft.client.renderer.Tessellator; -import net.minecraft.client.renderer.block.model.IBakedModel; -import net.minecraft.client.renderer.block.model.ModelResourceLocation; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.client.renderer.texture.TextureMap; import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.creativetab.CreativeTabs; import net.minecraft.entity.player.EntityPlayer; @@ -36,61 +34,49 @@ import net.minecraft.util.NonNullList; import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.AxisAlignedBB; -import net.minecraft.world.World; -import net.minecraftforge.client.model.IModel; -import net.minecraftforge.client.model.ModelLoader; -import net.minecraftforge.client.model.ModelLoaderRegistry; -import net.minecraftforge.common.model.TRSRTransformation; -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; -import net.minecraftforge.items.ItemStackHandler; +import org.apache.commons.lang3.tuple.Pair; import org.lwjgl.opengl.GL11; import javax.annotation.Nullable; - import java.util.List; import java.util.Optional; +import static gregtech.api.render.Textures.CLIPBOARD_RENDERER; import static gregtech.common.items.MetaItems.CLIPBOARD; -public class MetaTileEntityClipboard extends MetaTileEntity implements IRenderMetaTileEntity { +public class MetaTileEntityClipboard extends MetaTileEntity implements IFastRenderMetaTileEntity { private static final AxisAlignedBB CLIPBOARD_AABB = new AxisAlignedBB(2.75 / 16.0, 0.0, 0.0, 13.25 / 16.0, 1.0, 0.4 / 16.0); public static final ResourceLocation MODEL_RESOURCE_LOCATION = new ResourceLocation("gregtech", "block/clipboard"); public static ModelCache cache = new ModelCache(); + public MetaTileEntityClipboard(ResourceLocation metaTileEntityId) { super(metaTileEntityId); } @Override - public void getSubItems(CreativeTabs creativeTab, NonNullList subItems) { } - - public void renderMetaTileEntityDynamic(double x, double y, double z, float partialTicks) { - if(this.getWorld() == null || !this.getWorld().isRemote) - return; - Tessellator tessellator = Tessellator.getInstance(); - BufferBuilder bufferBuilder = tessellator.getBuffer(); - IBlockState blockState = this.getWorld().getBlockState(this.getPos()); - BlockRendererDispatcher renderer = Minecraft.getMinecraft().getBlockRendererDispatcher(); - if(cache.findModel("bakedModel")) { - IBakedModel model = cache.getCurrentMatch(); - bufferBuilder.begin(GL11.GL_QUADS, DefaultVertexFormats.BLOCK); - GlStateManager.pushMatrix(); - GlStateManager.rotate((frontFacing.getHorizontalAngle()), 0.0F, 1.0F, 0.0F); - GlStateManager.translate(x, y, z); - renderer.getBlockModelRenderer().renderModel(this.getWorld(), model, blockState, this.getPos(), bufferBuilder, true); - tessellator.draw(); - GlStateManager.popMatrix(); - } + public void getSubItems(CreativeTabs creativeTab, NonNullList subItems) { } + @Override public void renderMetaTileEntity(CCRenderState renderState, Matrix4 translation, IVertexOperation[] pipeline) { + this.renderMetaTileEntityFast(renderState, translation, 0); + } + + @Override + public int getLightOpacity() { + return 0; + } + + @Override + public void renderMetaTileEntityFast(CCRenderState renderState, Matrix4 translation, float partialTicks) { + CLIPBOARD_RENDERER.render(renderState, translation, new IVertexOperation[]{}, getFrontFacing()); } @Override public AxisAlignedBB getRenderBoundingBox() { - return GTUtility.rotateAroundYAxis(CLIPBOARD_AABB, EnumFacing.NORTH, this.getFrontFacing()); + return new AxisAlignedBB(getPos().add(-1, 0, -1), getPos().add(2, 2, 2)); } @Override @@ -105,12 +91,12 @@ public MetaTileEntity createMetaTileEntity(MetaTileEntityHolder holder) { @Override protected ModularUI createUI(EntityPlayer entityPlayer) { - if(getClipboard().isItemEqual(CLIPBOARD.getStackForm())) { + if (getClipboard().isItemEqual(CLIPBOARD.getStackForm())) { List behaviours = ((MetaItem) getClipboard().getItem()).getBehaviours(getClipboard()); Optional clipboardBehaviour = behaviours.stream().filter((x) -> x instanceof ClipboardBehaviour).findFirst(); - if(!clipboardBehaviour.isPresent()) + if (!clipboardBehaviour.isPresent()) return null; - if(clipboardBehaviour.get() instanceof ClipboardBehaviour) { + if (clipboardBehaviour.get() instanceof ClipboardBehaviour) { return ((ClipboardBehaviour) clipboardBehaviour.get()).createUI(new PlayerInventoryHolder(entityPlayer, entityPlayer.getActiveHand(), getClipboard()), entityPlayer); } } @@ -124,7 +110,7 @@ protected void initializeInventory() { } public ItemStack getClipboard() { - if(this.itemInventory.getStackInSlot(0) == ItemStack.EMPTY) { + if (this.itemInventory.getStackInSlot(0) == ItemStack.EMPTY) { ((InaccessibleItemStackHandler) this.itemInventory).setStackInSlot(0, CLIPBOARD.getStackForm()); } return this.itemInventory.getStackInSlot(0); @@ -152,7 +138,7 @@ public int getHarvestLevel() { @Override public boolean onRightClick(EntityPlayer playerIn, EnumHand hand, EnumFacing facing, CuboidRayTraceResult hitResult) { - if(playerIn.isSneaking()) { + if (playerIn.isSneaking()) { if (getWorld() != null && !getWorld().isRemote) { MetaTileEntityUIFactory.INSTANCE.openUI(getHolder(), (EntityPlayerMP) playerIn); } @@ -173,14 +159,8 @@ public void addCollisionBoundingBox(List collisionList) { collisionList.add(new IndexedCuboid6(null, GTUtility.rotateAroundYAxis(CLIPBOARD_AABB, EnumFacing.NORTH, this.getFrontFacing()))); } - @SideOnly(Side.CLIENT) - public static void initModel() { - try { - IModel model = ModelLoaderRegistry.getModel(MODEL_RESOURCE_LOCATION); - IBakedModel bakedModel = model.bake(TRSRTransformation.identity(), DefaultVertexFormats.BLOCK, location -> Minecraft.getMinecraft().getTextureMapBlocks().getAtlasSprite(location.toString())); - cache.addToCache(bakedModel, "bakedModel"); - } catch (Exception err) { - GTLog.logger.error("MetaTileEntityClipboard did not acquire model! " + err.getMessage()); - } + @Override + public Pair getParticleTexture() { + return Pair.of(CLIPBOARD_RENDERER.getParticleTexture(), 0xFFFFFF); } } diff --git a/src/main/resources/assets/gregtech/textures/blocks/clipboard/clip.png b/src/main/resources/assets/gregtech/textures/blocks/clipboard/clip.png new file mode 100644 index 0000000000000000000000000000000000000000..fcc101e54f2ba230ab5fd5a5f9b9c4f8b596f37b GIT binary patch literal 343 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCij$3p^r=85sBufG}g$wN6f;;2TdD#}Etu*vZ^{hYWa}Z|8l#&bMdn2cGp^ zS(;C>)uk`2e?2SL`MoXMvpKmv7w>)djeDJNBjLod1?jyrWB zuO;leN#*?0)@b%0F%Ks6YK6%MCi+}_|G4jKQG+wr_307j($BL^5+h3YEb3xB`r-c{ z@qi~WtSet@|J?Up)LrAIyjHl7Y0mMeBkW=9nMy&)Rp&g}1QQtE%O6$jJYxOi$#f2n l4pqjEBNDZWJHOwvd-Rd_!mI2i=c)I$ztaD0e0ssfCAoc(N literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/blocks/clipboard/wood.png b/src/main/resources/assets/gregtech/textures/blocks/clipboard/wood.png new file mode 100644 index 0000000000000000000000000000000000000000..304d851ba107a228dea20391741c9dd622050464 GIT binary patch literal 438 zcmV;n0ZIOeP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGizyJUazyWI3i3tDz0ZU0lK~y+TUD8={ z!!Qg3P}|vare3N?>KXHs&2jV4U?vS`WJx3dF4p+-{k4qaIILEy;qiD3(=_FLyWMi0 z=XqF`Wq@HY>-9Q2-?Z6m60jF^y_TrQVn0^*aA zj}gR4#XtyE

BjNdng;emEQ=JQdt*gc5j(l~mzohGSDcdU>vvsGZIP`FuX-ULve{ zxJQ7hGC8$VF@8ILXGM?*(Fpi3q=JaFjh+q89o`+zecJE$|4J(e;Cw$DvOG3GK|n+csDx(fBRZW%>y+)t`fAT5iSr?S`tuUoZ~r|Z*`2k~Br?J=@%#~>{>la!f<+9* gLV{Dx-%RG=7lZ3hxKlNv^#A|>07*qoM6N<$g1-{Gh5!Hn literal 0 HcmV?d00001 From b2e47a258fb0f8a1840953f8e811be36fd257e2a Mon Sep 17 00:00:00 2001 From: bruberu <80226372+bruberu@users.noreply.github.com> Date: Mon, 2 Aug 2021 23:03:52 -0500 Subject: [PATCH 14/42] Pull in FakeModularGui and FakeModularUIContainer, and start on a few helper functions --- .../api/gui/impl/fakegui/FakeModularGui.java | 128 ++++++++++++++++ .../impl/fakegui/FakeModularUIContainer.java | 145 ++++++++++++++++++ .../api/render/ClipboardRenderer.java | 47 +++++- .../java/gregtech/api/util/RenderUtil.java | 124 +++++++++++++++ .../MetaTileEntityClipboard.java | 87 +++++++++-- 5 files changed, 520 insertions(+), 11 deletions(-) create mode 100644 src/main/java/gregtech/api/gui/impl/fakegui/FakeModularGui.java create mode 100644 src/main/java/gregtech/api/gui/impl/fakegui/FakeModularUIContainer.java diff --git a/src/main/java/gregtech/api/gui/impl/fakegui/FakeModularGui.java b/src/main/java/gregtech/api/gui/impl/fakegui/FakeModularGui.java new file mode 100644 index 00000000000..d79218a591c --- /dev/null +++ b/src/main/java/gregtech/api/gui/impl/fakegui/FakeModularGui.java @@ -0,0 +1,128 @@ +package gregtech.api.gui.impl.fakegui; + +import gregtech.api.gui.IRenderContext; +import gregtech.api.gui.ModularUI; +import gregtech.api.gui.Widget; +import gregtech.api.util.RenderUtil; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.RenderHelper; +import net.minecraft.client.util.ITooltipFlag; +import net.minecraft.inventory.Slot; +import net.minecraft.item.ItemStack; +import net.minecraft.network.PacketBuffer; +import net.minecraft.util.text.TextFormatting; +import net.minecraftforge.fml.client.config.GuiUtils; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +import java.util.List; + +@SideOnly(Side.CLIENT) +public class FakeModularGui implements IRenderContext { + public final ModularUI modularUI; + public FakeModularUIContainer container; + protected Minecraft mc; + protected FontRenderer fr; + + public FakeModularGui(ModularUI modularUI, FakeModularUIContainer fakeModularUIContainer){ + this.modularUI = modularUI; + this.container = fakeModularUIContainer; + this.modularUI.updateScreenSize(this.modularUI.getWidth(), this.modularUI.getHeight()); + this.mc = Minecraft.getMinecraft(); + this.fr = mc.fontRenderer; + } + + public void updateScreen() { + modularUI.guiWidgets.values().forEach(Widget::updateScreen); + } + + public void handleWidgetUpdate(int windowId, int widgetId, PacketBuffer updateData) { + if (windowId == container.windowId) { + Widget widget = modularUI.guiWidgets.get(widgetId); + int updateId = updateData.readVarInt(); + if (widget != null) { + widget.readUpdateInfo(updateId, updateData); + } + } + } + + public void drawScreen(double x, double y, float partialTicks) { + float halfW = modularUI.getWidth() / 2f; + float halfH = modularUI.getHeight() / 2f; + float scale = 0.5f / Math.max(halfW, halfH); + int mouseX = (int) ((x / scale) + (halfW > halfH? 0: (halfW - halfH))); + int mouseY = (int) ((y / scale) + (halfH > halfW? 0: (halfH - halfW))); + + GlStateManager.translate(-scale * halfW, -scale * halfH, 0.01); + GlStateManager.scale(scale, scale, 1); + GlStateManager.depthMask(false); + + drawGuiContainerBackgroundLayer(partialTicks, mouseX, mouseY); + + for (int i = 0; i < this.container.inventorySlots.size(); ++i) { + RenderUtil.renderSlot(this.container.inventorySlots.get(i), fr); + } + + + GlStateManager.scale(1, 1, 0); + drawGuiContainerForegroundLayer(mouseX, mouseY); + for (int i = 0; i < this.container.inventorySlots.size(); ++i) { + Slot slot = this.container.inventorySlots.get(i); + if (!slot.getStack().isEmpty() && slot.xPos < mouseX && mouseX < slot.xPos + 18 && slot.yPos < mouseY && mouseY < slot.yPos + 18) { + RenderUtil.renderRect(slot.xPos, slot.yPos, 18, 18, 0, 0X8fffffff); + renderToolTip(slot.getStack(), slot.xPos, slot.yPos); + } + } + + GlStateManager.depthMask(true); + GlStateManager.color(1.0f, 1.0f, 1.0f); + GlStateManager.disableLighting(); + } + + protected void renderToolTip(ItemStack stack, int x, int y) { + FontRenderer font = stack.getItem().getFontRenderer(stack); + GuiUtils.preItemToolTip(stack); + GuiUtils.drawHoveringText(this.getItemToolTip(stack), x, y, modularUI.getScreenWidth(), modularUI.getScreenHeight(), -1, (font == null ? fr : font)); + net.minecraftforge.fml.client.config.GuiUtils.postItemToolTip(); + } + + protected List getItemToolTip(ItemStack itemStack) { + List list = itemStack.getTooltip(mc.player, mc.gameSettings.advancedItemTooltips ? ITooltipFlag.TooltipFlags.ADVANCED : ITooltipFlag.TooltipFlags.NORMAL); + for (int i = 0; i < list.size(); ++i) { + if (i == 0) { + list.set(i, itemStack.getItem().getForgeRarity(itemStack).getColor() + list.get(i)); + } + else { + list.set(i, TextFormatting.GRAY + list.get(i)); + } + } + return list; + } + + public void drawGuiContainerBackgroundLayer(float partialTicks, int mouseX, int mouseY) { + modularUI.backgroundPath.draw(0, 0, modularUI.getWidth(), modularUI.getHeight()); + for (Widget widget : modularUI.guiWidgets.values()) { + GlStateManager.pushMatrix(); + GlStateManager.color(1.0f, 1.0f, 1.0f); + GlStateManager.enableBlend(); + widget.drawInBackground(mouseX, mouseY, this); + GlStateManager.popMatrix(); + } + } + + public void drawGuiContainerForegroundLayer(int mouseX, int mouseY) { + for (Widget widget : modularUI.guiWidgets.values()) { + GlStateManager.pushMatrix(); + GlStateManager.color(1.0f, 1.0f, 1.0f); + widget.drawInForeground(mouseX, mouseY); + GlStateManager.popMatrix(); + } + } + + public boolean mouseClicked(int mouseX, int mouseY, int mouseButton) { + return modularUI.guiWidgets.values().stream().anyMatch(widget -> widget.mouseClicked(mouseX, mouseY, mouseButton)); + } + +} diff --git a/src/main/java/gregtech/api/gui/impl/fakegui/FakeModularUIContainer.java b/src/main/java/gregtech/api/gui/impl/fakegui/FakeModularUIContainer.java new file mode 100644 index 00000000000..ca9b65e6a93 --- /dev/null +++ b/src/main/java/gregtech/api/gui/impl/fakegui/FakeModularUIContainer.java @@ -0,0 +1,145 @@ +package gregtech.api.gui.impl.fakegui; + +import com.google.common.collect.Lists; +import gregtech.api.gui.INativeWidget; +import gregtech.api.gui.ModularUI; +import gregtech.api.gui.Widget; +import gregtech.api.gui.widgets.WidgetUIAccess; +import net.minecraft.inventory.Slot; +import net.minecraft.item.ItemStack; +import net.minecraft.network.PacketBuffer; +import net.minecraft.util.NonNullList; +import net.minecraft.util.Tuple; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Consumer; + +public class FakeModularUIContainer implements WidgetUIAccess { + private final NonNullList inventoryItemStacks = NonNullList.create(); + public final List inventorySlots = Lists.newArrayList(); + public final ModularUI modularUI; + protected int windowId; + //private final FakeGuiPluginBehavior behavior; + public int syncId; + + public FakeModularUIContainer(ModularUI modularUI/*, FakeGuiPluginBehavior pluginBehavior*/) { + this.modularUI = modularUI; + //this.behavior = pluginBehavior; + modularUI.initWidgets(); + modularUI.guiWidgets.values().forEach(widget -> widget.setUiAccess(this)); + modularUI.guiWidgets.values().stream().flatMap(widget -> widget.getNativeWidgets().stream()).forEach(nativeWidget -> addSlotToContainer(nativeWidget.getHandle())); + modularUI.triggerOpenListeners(); + } + + protected void addSlotToContainer(Slot slotIn) { + slotIn.slotNumber = this.inventorySlots.size(); + this.inventorySlots.add(slotIn); + this.inventoryItemStacks.add(ItemStack.EMPTY); + } + + public void handleSlotUpdate(PacketBuffer updateData) { + try { + int size = updateData.readVarInt(); + for (int i = 0; i < size; i++) { + inventorySlots.get(updateData.readVarInt()).putStack(updateData.readItemStack()); + } + } catch (Exception ignored){ + + } + } + + public void handleClientAction(PacketBuffer buffer) { + int syncId = buffer.readVarInt(); + int windowId = buffer.readVarInt(); + if (syncId == this.syncId && windowId == this.windowId) { + Widget widget = modularUI.guiWidgets.get(buffer.readVarInt()); + if (widget != null) { + widget.handleClientAction(buffer.readVarInt(), buffer); + } + } + this.syncId = 0; + } + + public void detectAndSendChanges() { + List> toUpdate = new ArrayList<>(); + for (int i = 0; i < this.inventorySlots.size(); ++i) { + ItemStack real = this.inventorySlots.get(i).getStack(); + ItemStack fake = this.inventoryItemStacks.get(i); + + if (!ItemStack.areItemStacksEqual(fake, real)) { + boolean clientStackChanged = !ItemStack.areItemStacksEqualUsingNBTShareTag(fake, real); + fake = real.isEmpty() ? ItemStack.EMPTY : real.copy(); + this.inventoryItemStacks.set(i, fake); + + if (clientStackChanged) { + toUpdate.add(new Tuple<>(i, fake)); + } + } + } + /* + if (toUpdate.size() > 0 && this.behavior != null) { + behavior.writePluginData(-1, packetBuffer -> { + packetBuffer.writeVarInt(toUpdate.size()); + for (Tuple tuple : toUpdate) { + packetBuffer.writeVarInt(tuple.getFirst()); + packetBuffer.writeItemStack(tuple.getSecond()); + } + }); + } + */ + modularUI.guiWidgets.values().forEach(Widget::detectAndSendChanges); + } + + @Override + public void notifySizeChange() { + + } + + @Override + public void notifyWidgetChange() { + + } + + @Override + public boolean attemptMergeStack(ItemStack itemStack, boolean b, boolean b1) { + return false; + } + + @Override + public void sendSlotUpdate(INativeWidget iNativeWidget) { + } + + @Override + public void sendHeldItemUpdate() { + } + + @Override + public void writeClientAction(Widget widget, int updateId, Consumer payloadWriter) { + /* + if (behavior != null) { + behavior.writePluginAction(1, buffer -> { + buffer.writeVarInt(syncId); + buffer.writeVarInt(windowId); + buffer.writeVarInt(modularUI.guiWidgets.inverse().get(widget)); + buffer.writeVarInt(updateId); + payloadWriter.accept(buffer); + }); + } + */ + } + + @Override + public void writeUpdateInfo(Widget widget, int updateId, Consumer payloadWriter) { + /* + if(behavior != null) { + behavior.writePluginData(0, buf -> { + buf.writeVarInt(windowId); + buf.writeVarInt(modularUI.guiWidgets.inverse().get(widget)); + buf.writeVarInt(updateId); + payloadWriter.accept(buf); + }); + } + */ + } +} diff --git a/src/main/java/gregtech/api/render/ClipboardRenderer.java b/src/main/java/gregtech/api/render/ClipboardRenderer.java index 4e6471275be..34669a297b7 100644 --- a/src/main/java/gregtech/api/render/ClipboardRenderer.java +++ b/src/main/java/gregtech/api/render/ClipboardRenderer.java @@ -6,13 +6,25 @@ import codechicken.lib.vec.Cuboid6; import codechicken.lib.vec.Matrix4; import codechicken.lib.vec.Rotation; +import gregtech.api.gui.ModularUI; +import gregtech.api.gui.Widget; +import gregtech.api.gui.impl.fakegui.FakeModularGui; +import gregtech.api.gui.impl.fakegui.FakeModularUIContainer; +import gregtech.api.gui.widgets.SlotWidget; +import gregtech.api.util.GTLog; +import gregtech.api.util.GregFakePlayer; +import gregtech.common.metatileentities.MetaTileEntityClipboard; +import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.renderer.texture.TextureMap; +import net.minecraft.item.ItemStack; import net.minecraft.util.EnumFacing; import net.minecraft.util.ResourceLocation; +import net.minecraftforge.common.util.FakePlayer; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; +import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; @@ -48,17 +60,48 @@ public void registerIcons(TextureMap textureMap) { } @SideOnly(Side.CLIENT) - public void render(CCRenderState renderState, Matrix4 translation, IVertexOperation[] pipeline, EnumFacing rotation) { + public void render(CCRenderState renderState, Matrix4 translation, IVertexOperation[] pipeline, EnumFacing rotation, MetaTileEntityClipboard clipboard) { translation.translate(0.5, 0.5, 0.5); translation.rotate(Math.toRadians(90.0 * rotations.indexOf(rotation)), Rotation.axes[1]); translation.translate(-0.5, -0.5, -0.5); - + // Render Clipboard for (EnumFacing renderSide : EnumFacing.VALUES) { boxTextureMap.forEach((box, sprite) -> Textures.renderFace(renderState, translation, pipeline, renderSide, box, sprite)); } + + // Render ModularUI + FakeModularGui fakeGui = createFakeGui(clipboard); + if(fakeGui != null) { + + } } + public FakeModularGui createFakeGui(MetaTileEntityClipboard mte) { + try { + // Get a FakePlayer in the client's current dimension through this roundabout function + FakePlayer fakePlayer = GregFakePlayer.get(Minecraft.getMinecraft().getIntegratedServer().getWorld(Minecraft.getMinecraft().player.dimension)); + ModularUI ui = mte.createUI(fakePlayer); + List widgets = new ArrayList<>(); + // Don't worry about SlotWidgets, since the clipboard literally can't have them + boolean hasPlayerInventory = false; + + ModularUI.Builder builder = new ModularUI.Builder(ui.backgroundPath, ui.getWidth(), ui.getHeight() - (hasPlayerInventory? 80:0)); + for (Widget widget : widgets) { + builder.widget(widget); + } + ui = builder.build(ui.holder, ui.entityPlayer); + FakeModularUIContainer fakeModularUIContainer = new FakeModularUIContainer(ui); + if (mte.getWorld().isRemote) { + return new FakeModularGui(ui, fakeModularUIContainer); + } + } catch (Exception e) { + GTLog.logger.error(e); + } + return null; + } + + @SideOnly(Side.CLIENT) public TextureAtlasSprite getParticleTexture() { diff --git a/src/main/java/gregtech/api/util/RenderUtil.java b/src/main/java/gregtech/api/util/RenderUtil.java index 96b29c47a8e..1c3308bbab0 100644 --- a/src/main/java/gregtech/api/util/RenderUtil.java +++ b/src/main/java/gregtech/api/util/RenderUtil.java @@ -1,7 +1,17 @@ package gregtech.api.util; import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.client.gui.FontRenderer; import net.minecraft.client.gui.ScaledResolution; +import net.minecraft.client.renderer.BufferBuilder; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.RenderItem; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.inventory.Slot; +import net.minecraft.item.ItemStack; +import net.minecraft.util.math.MathHelper; import net.minecraftforge.client.GuiIngameForge; import org.lwjgl.opengl.GL11; @@ -86,4 +96,118 @@ private static void applyScissor(int x, int y, int w, int h) { GL11.glScissor(x*s, translatedY*s, w*s, h*s); } + + public static void renderSlot(Slot slot, FontRenderer fr) { + ItemStack stack = slot.getStack(); + if (!stack.isEmpty() && slot.isEnabled()) { + net.minecraft.client.renderer.RenderHelper.enableStandardItemLighting(); + GlStateManager.pushMatrix(); + GlStateManager.scale(1, 1, 0); + GlStateManager.translate(slot.xPos, slot.yPos, 0); + RenderItem renderItem = Minecraft.getMinecraft().getRenderItem(); + renderItem.renderItemAndEffectIntoGUI(stack, 0, 0); + String text = stack.getCount() > 1? Integer.toString(stack.getCount()) : null; + + if (!stack.isEmpty()) + { + if (stack.getCount() != 1) + { + String s = text == null ? String.valueOf(stack.getCount()) : text; + GlStateManager.disableLighting(); + GlStateManager.disableBlend(); + fr.drawStringWithShadow(s, (float)(17 - fr.getStringWidth(s)), (float)9, 16777215); + GlStateManager.enableLighting(); + GlStateManager.enableBlend(); + } + + if (stack.getItem().showDurabilityBar(stack)) + { + GlStateManager.disableLighting(); + GlStateManager.disableTexture2D(); + GlStateManager.disableAlpha(); + GlStateManager.disableBlend(); + Tessellator tessellator = Tessellator.getInstance(); + BufferBuilder bufferbuilder = tessellator.getBuffer(); + double health = stack.getItem().getDurabilityForDisplay(stack); + int rgbfordisplay = stack.getItem().getRGBDurabilityForDisplay(stack); + int i = Math.round(13.0F - (float)health * 13.0F); + draw(bufferbuilder, 2, 13, 13, 2, 0, 0, 0, 255); + draw(bufferbuilder, 2, 13, i, 1, rgbfordisplay >> 16 & 255, rgbfordisplay >> 8 & 255, rgbfordisplay & 255, 255); + GlStateManager.enableBlend(); + GlStateManager.enableAlpha(); + GlStateManager.enableTexture2D(); + GlStateManager.enableLighting(); + } + + EntityPlayerSP entityplayersp = Minecraft.getMinecraft().player; + float f3 = entityplayersp == null ? 0.0F : entityplayersp.getCooldownTracker().getCooldown(stack.getItem(), Minecraft.getMinecraft().getRenderPartialTicks()); + + if (f3 > 0.0F) + { + GlStateManager.disableLighting(); + GlStateManager.disableTexture2D(); + Tessellator tessellator = Tessellator.getInstance(); + BufferBuilder bufferBuilder = tessellator.getBuffer(); + draw(bufferBuilder, 0, MathHelper.floor(16.0F * (1.0F - f3)), 16, MathHelper.ceil(16.0F * f3), 255, 255, 255, 127); + GlStateManager.enableTexture2D(); + GlStateManager.enableLighting(); + } + } + + GlStateManager.popMatrix(); + net.minecraft.client.renderer.RenderHelper.disableStandardItemLighting(); + } + } + + private static void draw(BufferBuilder renderer, int x, int y, int width, int height, int red, int green, int blue, int alpha) + { + renderer.begin(7, DefaultVertexFormats.POSITION_COLOR); + renderer.pos(x, y, 0.0D).color(red, green, blue, alpha).endVertex(); + renderer.pos((x), y + height, 0.0D).color(red, green, blue, alpha).endVertex(); + renderer.pos((x + width), y + height, 0.0D).color(red, green, blue, alpha).endVertex(); + renderer.pos((x + width), y, 0.0D).color(red, green, blue, alpha).endVertex(); + Tessellator.getInstance().draw(); + } + + public static void renderRect(float x, float y, float width, float height, float z, int color) { + renderGradientRect(x, y, width, height, z, color, color, false); + } + + public static void renderGradientRect(float x, float y, float width, float height, float z, int startColor, int endColor, boolean horizontal) { + float startAlpha = (float) (startColor >> 24 & 255) / 255.0F; + float startRed = (float) (startColor >> 16 & 255) / 255.0F; + float startGreen = (float) (startColor >> 8 & 255) / 255.0F; + float startBlue = (float) (startColor & 255) / 255.0F; + float endAlpha = (float) (endColor >> 24 & 255) / 255.0F; + float endRed = (float) (endColor >> 16 & 255) / 255.0F; + float endGreen = (float) (endColor >> 8 & 255) / 255.0F; + float endBlue = (float) (endColor & 255) / 255.0F; + GlStateManager.disableTexture2D(); + GlStateManager.enableBlend(); + GlStateManager.disableAlpha(); + GlStateManager.tryBlendFuncSeparate(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ZERO); + GlStateManager.shadeModel(GL11.GL_SMOOTH); + Tessellator tessellator = Tessellator.getInstance(); + BufferBuilder buffer = tessellator.getBuffer(); + buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR); + if (horizontal) { + buffer.pos(x + width, y, z).color(endRed, endGreen, endBlue, endAlpha).endVertex(); + buffer.pos(x, y, z).color(startRed, startGreen, startBlue, startAlpha).endVertex(); + buffer.pos(x, y + height, z).color(startRed, startGreen, startBlue, startAlpha).endVertex(); + buffer.pos(x + width, y + height, z).color(endRed, endGreen, endBlue, endAlpha).endVertex(); + tessellator.draw(); + } else { + buffer.pos(x + width, y, z).color(startRed, startGreen, startBlue, startAlpha).endVertex(); + buffer.pos(x, y, z).color(startRed, startGreen, startBlue, startAlpha).endVertex(); + buffer.pos(x, y + height, z).color(endRed, endGreen, endBlue, endAlpha).endVertex(); + buffer.pos(x + width, y + height, z).color(endRed, endGreen, endBlue, endAlpha).endVertex(); + tessellator.draw(); + } + GlStateManager.shadeModel(GL11.GL_FLAT); + GlStateManager.disableBlend(); + GlStateManager.enableAlpha(); + GlStateManager.enableTexture2D(); + } + + } diff --git a/src/main/java/gregtech/common/metatileentities/MetaTileEntityClipboard.java b/src/main/java/gregtech/common/metatileentities/MetaTileEntityClipboard.java index 9452f5ef4ae..69d13c455bc 100644 --- a/src/main/java/gregtech/common/metatileentities/MetaTileEntityClipboard.java +++ b/src/main/java/gregtech/common/metatileentities/MetaTileEntityClipboard.java @@ -18,24 +18,21 @@ import gregtech.common.blocks.models.ModelCache; import gregtech.common.items.behaviors.ClipboardBehaviour; import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.BufferBuilder; -import net.minecraft.client.renderer.GlStateManager; -import net.minecraft.client.renderer.RenderHelper; -import net.minecraft.client.renderer.Tessellator; import net.minecraft.client.renderer.texture.TextureAtlasSprite; -import net.minecraft.client.renderer.texture.TextureMap; -import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.creativetab.CreativeTabs; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.item.ItemStack; +import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumHand; import net.minecraft.util.NonNullList; import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.util.math.RayTraceResult; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; import org.apache.commons.lang3.tuple.Pair; -import org.lwjgl.opengl.GL11; import javax.annotation.Nullable; import java.util.List; @@ -48,6 +45,7 @@ public class MetaTileEntityClipboard extends MetaTileEntity implements IFastRend private static final AxisAlignedBB CLIPBOARD_AABB = new AxisAlignedBB(2.75 / 16.0, 0.0, 0.0, 13.25 / 16.0, 1.0, 0.4 / 16.0); public static final ResourceLocation MODEL_RESOURCE_LOCATION = new ResourceLocation("gregtech", "block/clipboard"); public static ModelCache cache = new ModelCache(); + public static final float scale = 1; public MetaTileEntityClipboard(ResourceLocation metaTileEntityId) { @@ -71,7 +69,7 @@ public int getLightOpacity() { @Override public void renderMetaTileEntityFast(CCRenderState renderState, Matrix4 translation, float partialTicks) { - CLIPBOARD_RENDERER.render(renderState, translation, new IVertexOperation[]{}, getFrontFacing()); + CLIPBOARD_RENDERER.render(renderState, translation, new IVertexOperation[]{}, getFrontFacing(), this); } @Override @@ -90,7 +88,7 @@ public MetaTileEntity createMetaTileEntity(MetaTileEntityHolder holder) { } @Override - protected ModularUI createUI(EntityPlayer entityPlayer) { + public ModularUI createUI(EntityPlayer entityPlayer) { if (getClipboard().isItemEqual(CLIPBOARD.getStackForm())) { List behaviours = ((MetaItem) getClipboard().getItem()).getBehaviours(getClipboard()); Optional clipboardBehaviour = behaviours.stream().filter((x) -> x instanceof ClipboardBehaviour).findFirst(); @@ -163,4 +161,75 @@ public void addCollisionBoundingBox(List collisionList) { public Pair getParticleTexture() { return Pair.of(CLIPBOARD_RENDERER.getParticleTexture(), 0xFFFFFF); } + + @SideOnly(Side.CLIENT) + public Pair checkLookingAt(float partialTicks) { + EntityPlayer player = Minecraft.getMinecraft().player; + if (this.getWorld() != null && player != null) { + RayTraceResult rayTraceResult = player.rayTrace(Minecraft.getMinecraft().playerController.getBlockReachDistance(), partialTicks); + if (rayTraceResult != null && rayTraceResult.typeOfHit == RayTraceResult.Type.BLOCK && rayTraceResult.sideHit == this.getFrontFacing()) { + int i = -1, j = -1; + TileEntity tileEntity = this.getWorld().getTileEntity(rayTraceResult.getBlockPos()); + if (tileEntity instanceof MetaTileEntityHolder && ((MetaTileEntityHolder) tileEntity).getMetaTileEntity() instanceof MetaTileEntityClipboard) { + MetaTileEntityClipboard clipboardHit = (MetaTileEntityClipboard) ((MetaTileEntityHolder) tileEntity).getMetaTileEntity(); + double[] pos = handleRayTraceResult(rayTraceResult, this.getFrontFacing()); + pos[0] /= this.scale; + pos[1] /= this.scale; + if (pos[0] >= 0 && pos[0] <= 1 && pos[1] >= 0 && pos[1] <= 1) + return Pair.of(pos[0], pos[1]); + } + } + } + return null; + } + + private double[] handleRayTraceResult(RayTraceResult rayTraceResult, EnumFacing spin) { + double x = 0; + double y = 0; + double dX = rayTraceResult.sideHit.getAxis() == EnumFacing.Axis.X + ? rayTraceResult.hitVec.z - rayTraceResult.getBlockPos().getZ() + : rayTraceResult.hitVec.x - rayTraceResult.getBlockPos().getX(); + double dY = rayTraceResult.sideHit.getAxis() == EnumFacing.Axis.Y + ? rayTraceResult.hitVec.z - rayTraceResult.getBlockPos().getZ() + : rayTraceResult.hitVec.y - rayTraceResult.getBlockPos().getY(); + if (spin == EnumFacing.NORTH) { + x = 1 - dX; + y = 1 - dY; + if (rayTraceResult.sideHit.getYOffset() < 0) { + y = 1 - y; + } + } else if (spin == EnumFacing.SOUTH) { + x = dX; + y = dY; + if (rayTraceResult.sideHit.getYOffset() < 0) { + y = 1 - y; + } + } else if (spin == EnumFacing.EAST) { + x = 1 - dY; + y = dX; + if (rayTraceResult.sideHit.getXOffset() < 0 || rayTraceResult.sideHit.getZOffset() > 0) { + x = 1 - x; + y = 1 - y; + } else if (rayTraceResult.sideHit.getYOffset() < 0) { + y = 1 - y; + } + } else { + x = dY; + y = 1 - dX; + if (rayTraceResult.sideHit.getXOffset() < 0 || rayTraceResult.sideHit.getZOffset() > 0) { + x = 1 - x; + y = 1 - y; + } else if (rayTraceResult.sideHit.getYOffset() < 0) { + y = 1 - y; + } + } + if (rayTraceResult.sideHit == EnumFacing.WEST || rayTraceResult.sideHit == EnumFacing.SOUTH) { + x = 1 - x; + } else if (rayTraceResult.sideHit == EnumFacing.UP) { + x = 1 - x; + y = 1 - y; + } + return new double[]{x, y}; + } + } From 72d6cd355820efa25a7fc4acfe299fed0dd80470 Mon Sep 17 00:00:00 2001 From: bruberu <80226372+bruberu@users.noreply.github.com> Date: Wed, 4 Aug 2021 00:07:14 -0500 Subject: [PATCH 15/42] Create a Death Ray --- .../api/render/ClipboardRenderer.java | 61 ++++++++++++++++--- .../api/render/MetaTileEntityTESR.java | 7 +++ .../MetaTileEntityClipboard.java | 21 ++++--- 3 files changed, 73 insertions(+), 16 deletions(-) diff --git a/src/main/java/gregtech/api/render/ClipboardRenderer.java b/src/main/java/gregtech/api/render/ClipboardRenderer.java index 34669a297b7..e3995233b5e 100644 --- a/src/main/java/gregtech/api/render/ClipboardRenderer.java +++ b/src/main/java/gregtech/api/render/ClipboardRenderer.java @@ -10,19 +10,27 @@ import gregtech.api.gui.Widget; import gregtech.api.gui.impl.fakegui.FakeModularGui; import gregtech.api.gui.impl.fakegui.FakeModularUIContainer; -import gregtech.api.gui.widgets.SlotWidget; +import gregtech.api.metatileentity.MetaTileEntityHolder; import gregtech.api.util.GTLog; import gregtech.api.util.GregFakePlayer; import gregtech.common.metatileentities.MetaTileEntityClipboard; import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.BufferBuilder; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.RenderHelper; +import net.minecraft.client.renderer.Tessellator; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.renderer.texture.TextureMap; -import net.minecraft.item.ItemStack; +import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher; +import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.util.EnumFacing; import net.minecraft.util.ResourceLocation; import net.minecraftforge.common.util.FakePlayer; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; +import org.apache.commons.lang3.tuple.Pair; +import org.lwjgl.opengl.GL11; import java.util.ArrayList; import java.util.Arrays; @@ -60,21 +68,61 @@ public void registerIcons(TextureMap textureMap) { } @SideOnly(Side.CLIENT) - public void render(CCRenderState renderState, Matrix4 translation, IVertexOperation[] pipeline, EnumFacing rotation, MetaTileEntityClipboard clipboard) { + public void renderBoard(CCRenderState renderState, Matrix4 translation, IVertexOperation[] pipeline, EnumFacing rotation, MetaTileEntityClipboard clipboard, float partialTicks) { + Tessellator tessellator = Tessellator.getInstance(); + BufferBuilder buffer = tessellator.getBuffer(); + + + renderState.bind(buffer); + RenderHelper.disableStandardItemLighting(); + GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.enableBlend(); + GlStateManager.disableCull(); + + if (Minecraft.isAmbientOcclusionEnabled()) { + GlStateManager.shadeModel(GL11.GL_SMOOTH); + } + else { + GlStateManager.shadeModel(GL11.GL_FLAT); + } + buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.BLOCK); + translation.translate(0.5, 0.5, 0.5); translation.rotate(Math.toRadians(90.0 * rotations.indexOf(rotation)), Rotation.axes[1]); translation.translate(-0.5, -0.5, -0.5); + + // Render Clipboard for (EnumFacing renderSide : EnumFacing.VALUES) { boxTextureMap.forEach((box, sprite) -> Textures.renderFace(renderState, translation, pipeline, renderSide, box, sprite)); } - // Render ModularUI + buffer.setTranslation(0, 0, 0); + tessellator.draw(); + GlStateManager.enableCull(); + RenderHelper.enableStandardItemLighting(); + + + } + + + @SideOnly(Side.CLIENT) + public void renderGUI(Matrix4 translation, MetaTileEntityClipboard clipboard, float partialTicks) { + + translation.translate((1 - 1) * 0.5, (1 - 1) * 0.5, 0); + translation.scale(1, 1, 1); + FakeModularGui fakeGui = createFakeGui(clipboard); - if(fakeGui != null) { + if (fakeGui != null) { + Pair result = clipboard.checkLookingAt(partialTicks); + if (result == null) + fakeGui.drawScreen(0, 0, partialTicks); + else + fakeGui.drawScreen(result.getKey(), result.getValue(), partialTicks); } + } public FakeModularGui createFakeGui(MetaTileEntityClipboard mte) { @@ -86,7 +134,7 @@ public FakeModularGui createFakeGui(MetaTileEntityClipboard mte) { // Don't worry about SlotWidgets, since the clipboard literally can't have them boolean hasPlayerInventory = false; - ModularUI.Builder builder = new ModularUI.Builder(ui.backgroundPath, ui.getWidth(), ui.getHeight() - (hasPlayerInventory? 80:0)); + ModularUI.Builder builder = new ModularUI.Builder(ui.backgroundPath, ui.getWidth(), ui.getHeight() - (hasPlayerInventory ? 80 : 0)); for (Widget widget : widgets) { builder.widget(widget); } @@ -102,7 +150,6 @@ public FakeModularGui createFakeGui(MetaTileEntityClipboard mte) { } - @SideOnly(Side.CLIENT) public TextureAtlasSprite getParticleTexture() { return textures[0]; diff --git a/src/main/java/gregtech/api/render/MetaTileEntityTESR.java b/src/main/java/gregtech/api/render/MetaTileEntityTESR.java index c0897c2e82e..970a570a295 100644 --- a/src/main/java/gregtech/api/render/MetaTileEntityTESR.java +++ b/src/main/java/gregtech/api/render/MetaTileEntityTESR.java @@ -13,9 +13,11 @@ import net.minecraft.client.renderer.RenderHelper; import net.minecraft.client.renderer.Tessellator; import net.minecraft.client.renderer.texture.TextureMap; +import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher; import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer; import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.util.EnumFacing; +import net.minecraft.util.ResourceLocation; import net.minecraft.util.Tuple; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; @@ -143,4 +145,9 @@ public boolean isGlobalRenderer(MetaTileEntityHolder te) { } return false; } + + @Override + public void bindTexture(ResourceLocation location) { + super.bindTexture(location); + } } diff --git a/src/main/java/gregtech/common/metatileentities/MetaTileEntityClipboard.java b/src/main/java/gregtech/common/metatileentities/MetaTileEntityClipboard.java index 69d13c455bc..941f5660387 100644 --- a/src/main/java/gregtech/common/metatileentities/MetaTileEntityClipboard.java +++ b/src/main/java/gregtech/common/metatileentities/MetaTileEntityClipboard.java @@ -10,10 +10,7 @@ import gregtech.api.items.itemhandlers.InaccessibleItemStackHandler; import gregtech.api.items.metaitem.MetaItem; import gregtech.api.items.metaitem.stats.IItemBehaviour; -import gregtech.api.metatileentity.IFastRenderMetaTileEntity; -import gregtech.api.metatileentity.MetaTileEntity; -import gregtech.api.metatileentity.MetaTileEntityHolder; -import gregtech.api.metatileentity.MetaTileEntityUIFactory; +import gregtech.api.metatileentity.*; import gregtech.api.util.GTUtility; import gregtech.common.blocks.models.ModelCache; import gregtech.common.items.behaviors.ClipboardBehaviour; @@ -41,7 +38,7 @@ import static gregtech.api.render.Textures.CLIPBOARD_RENDERER; import static gregtech.common.items.MetaItems.CLIPBOARD; -public class MetaTileEntityClipboard extends MetaTileEntity implements IFastRenderMetaTileEntity { +public class MetaTileEntityClipboard extends MetaTileEntity implements IRenderMetaTileEntity { private static final AxisAlignedBB CLIPBOARD_AABB = new AxisAlignedBB(2.75 / 16.0, 0.0, 0.0, 13.25 / 16.0, 1.0, 0.4 / 16.0); public static final ResourceLocation MODEL_RESOURCE_LOCATION = new ResourceLocation("gregtech", "block/clipboard"); public static ModelCache cache = new ModelCache(); @@ -59,7 +56,8 @@ public void getSubItems(CreativeTabs creativeTab, NonNullList subItem @Override public void renderMetaTileEntity(CCRenderState renderState, Matrix4 translation, IVertexOperation[] pipeline) { - this.renderMetaTileEntityFast(renderState, translation, 0); + // Just gonna ignore all of those parameters lul + //this.renderMetaTileEntityDynamic(this.getPos().getX(), this.getPos().getY(), this.getPos().getZ(), Minecraft.getMinecraft().getRenderPartialTicks()); } @Override @@ -67,12 +65,17 @@ public int getLightOpacity() { return 0; } + @Override - public void renderMetaTileEntityFast(CCRenderState renderState, Matrix4 translation, float partialTicks) { - CLIPBOARD_RENDERER.render(renderState, translation, new IVertexOperation[]{}, getFrontFacing(), this); + public void renderMetaTileEntityDynamic(double x, double y, double z, float partialTicks) { + Matrix4 translation = new Matrix4().translate(x, y, z); + CCRenderState renderState = CCRenderState.instance(); + renderState.reset(); + CLIPBOARD_RENDERER.renderBoard(renderState, translation.copy(), new IVertexOperation[]{}, getFrontFacing(), this, partialTicks); + if(this.getClipboard() != null) + CLIPBOARD_RENDERER.renderGUI(translation, this, partialTicks); } - @Override public AxisAlignedBB getRenderBoundingBox() { return new AxisAlignedBB(getPos().add(-1, 0, -1), getPos().add(2, 2, 2)); } From 318724cd4f3660246d3f2492c4d141c8c43a9f61 Mon Sep 17 00:00:00 2001 From: bruberu <80226372+bruberu@users.noreply.github.com> Date: Sat, 7 Aug 2021 11:21:14 -0500 Subject: [PATCH 16/42] Complete check 3/4 --- .../impl/{fakegui => }/FakeModularGui.java | 10 +- .../api/metatileentity/MetaTileEntity.java | 2 + .../metatileentity/MetaTileEntityHolder.java | 6 +- .../java/gregtech/api/net/NetworkHandler.java | 30 ++++ .../net/PacketClipboardUIWidgetUpdate.java | 28 +++ .../api/render/ClipboardRenderer.java | 89 ++------- .../gregtech/api/util/GregFakePlayer.java | 36 +++- .../FakeModularUIContainerClipboard.java} | 39 ++-- .../items/behaviors/ClipboardBehaviour.java | 55 +++--- .../MetaTileEntityClipboard.java | 170 ++++++++++++++++-- .../TileEntityClipboardRenderer.java | 103 ----------- 11 files changed, 324 insertions(+), 244 deletions(-) rename src/main/java/gregtech/api/gui/impl/{fakegui => }/FakeModularGui.java (95%) create mode 100644 src/main/java/gregtech/api/net/PacketClipboardUIWidgetUpdate.java rename src/main/java/gregtech/{api/gui/impl/fakegui/FakeModularUIContainer.java => common/gui/impl/FakeModularUIContainerClipboard.java} (84%) delete mode 100644 src/main/java/gregtech/common/render/clipboard/TileEntityClipboardRenderer.java diff --git a/src/main/java/gregtech/api/gui/impl/fakegui/FakeModularGui.java b/src/main/java/gregtech/api/gui/impl/FakeModularGui.java similarity index 95% rename from src/main/java/gregtech/api/gui/impl/fakegui/FakeModularGui.java rename to src/main/java/gregtech/api/gui/impl/FakeModularGui.java index d79218a591c..c6a818f5fde 100644 --- a/src/main/java/gregtech/api/gui/impl/fakegui/FakeModularGui.java +++ b/src/main/java/gregtech/api/gui/impl/FakeModularGui.java @@ -1,13 +1,13 @@ -package gregtech.api.gui.impl.fakegui; +package gregtech.api.gui.impl; import gregtech.api.gui.IRenderContext; import gregtech.api.gui.ModularUI; import gregtech.api.gui.Widget; import gregtech.api.util.RenderUtil; +import gregtech.common.gui.impl.FakeModularUIContainerClipboard; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.FontRenderer; import net.minecraft.client.renderer.GlStateManager; -import net.minecraft.client.renderer.RenderHelper; import net.minecraft.client.util.ITooltipFlag; import net.minecraft.inventory.Slot; import net.minecraft.item.ItemStack; @@ -22,11 +22,11 @@ @SideOnly(Side.CLIENT) public class FakeModularGui implements IRenderContext { public final ModularUI modularUI; - public FakeModularUIContainer container; + public FakeModularUIContainerClipboard container; protected Minecraft mc; protected FontRenderer fr; - public FakeModularGui(ModularUI modularUI, FakeModularUIContainer fakeModularUIContainer){ + public FakeModularGui(ModularUI modularUI, FakeModularUIContainerClipboard fakeModularUIContainer){ this.modularUI = modularUI; this.container = fakeModularUIContainer; this.modularUI.updateScreenSize(this.modularUI.getWidth(), this.modularUI.getHeight()); @@ -105,7 +105,7 @@ public void drawGuiContainerBackgroundLayer(float partialTicks, int mouseX, int modularUI.backgroundPath.draw(0, 0, modularUI.getWidth(), modularUI.getHeight()); for (Widget widget : modularUI.guiWidgets.values()) { GlStateManager.pushMatrix(); - GlStateManager.color(1.0f, 1.0f, 1.0f); + GlStateManager.color(0.0f, 1.0f, 0.5f); GlStateManager.enableBlend(); widget.drawInBackground(mouseX, mouseY, this); GlStateManager.popMatrix(); diff --git a/src/main/java/gregtech/api/metatileentity/MetaTileEntity.java b/src/main/java/gregtech/api/metatileentity/MetaTileEntity.java index e92d9833afd..e22cd534229 100644 --- a/src/main/java/gregtech/api/metatileentity/MetaTileEntity.java +++ b/src/main/java/gregtech/api/metatileentity/MetaTileEntity.java @@ -1235,4 +1235,6 @@ public boolean keepsInventory() { public boolean getWitherProof(){ return false; } + + public void preInit(Object... data) {}; } diff --git a/src/main/java/gregtech/api/metatileentity/MetaTileEntityHolder.java b/src/main/java/gregtech/api/metatileentity/MetaTileEntityHolder.java index 25966e25263..f1af98f7a81 100644 --- a/src/main/java/gregtech/api/metatileentity/MetaTileEntityHolder.java +++ b/src/main/java/gregtech/api/metatileentity/MetaTileEntityHolder.java @@ -38,11 +38,15 @@ public MetaTileEntity getMetaTileEntity() { * Sets this holder's current meta tile entity to copy of given one * Note that this method copies given meta tile entity and returns actual instance * so it is safe to call it on sample meta tile entities + * Also can use certain data to p */ - public MetaTileEntity setMetaTileEntity(MetaTileEntity sampleMetaTileEntity) { + public MetaTileEntity setMetaTileEntity(MetaTileEntity sampleMetaTileEntity, Object... data) { Preconditions.checkNotNull(sampleMetaTileEntity, "metaTileEntity"); this.metaTileEntity = sampleMetaTileEntity.createMetaTileEntity(this); this.metaTileEntity.holder = this; + if(data.length != 0) { + this.metaTileEntity.preInit(data); + } this.metaTileEntity.onAttached(); if (hasWorld() && !getWorld().isRemote) { updateBlockOpacity(); diff --git a/src/main/java/gregtech/api/net/NetworkHandler.java b/src/main/java/gregtech/api/net/NetworkHandler.java index 9050a48222f..4290bd01a4d 100755 --- a/src/main/java/gregtech/api/net/NetworkHandler.java +++ b/src/main/java/gregtech/api/net/NetworkHandler.java @@ -7,8 +7,10 @@ import gregtech.api.gui.UIFactory; import gregtech.api.gui.impl.ModularUIContainer; import gregtech.api.gui.impl.ModularUIGui; +import gregtech.api.metatileentity.MetaTileEntityHolder; import gregtech.api.util.ClipboardUtil; import gregtech.api.util.GTLog; +import gregtech.common.metatileentities.MetaTileEntityClipboard; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import net.minecraft.block.state.IBlockState; @@ -20,6 +22,7 @@ import net.minecraft.network.INetHandler; import net.minecraft.network.NetHandlerPlayServer; import net.minecraft.network.PacketBuffer; +import net.minecraft.tileentity.TileEntity; import net.minecraft.util.IThreadListener; import net.minecraft.util.IntIdentityHashBiMap; import net.minecraft.util.math.BlockPos; @@ -195,6 +198,27 @@ public static void init() { (buf) -> new PacketClipboard(buf.readString(32767)) )); + registerPacket(6, PacketClipboardUIWidgetUpdate.class, new NetworkHandler.PacketCodec<>( + (packet, buf) -> { + buf.writeVarInt(packet.clipboard.getWorld().provider.getDimension()); + buf.writeBlockPos(packet.clipboard.getPos()); + buf.writeVarInt(packet.id); + if(packet.payloadWriter != null) { + packet.payloadWriter.accept(buf); + } + }, + (buf) -> { + int dim = buf.readVarInt(); + BlockPos pos = buf.readBlockPos(); + TileEntity te = FMLCommonHandler.instance().getMinecraftServerInstance().getWorld(dim).getTileEntity(pos); + if(te instanceof MetaTileEntityHolder && ((MetaTileEntityHolder) te).getMetaTileEntity() instanceof MetaTileEntityClipboard) { + return new PacketClipboardUIWidgetUpdate((MetaTileEntityClipboard) ((MetaTileEntityHolder) te).getMetaTileEntity(), buf); + } + return new PacketClipboardUIWidgetUpdate(null, buf); + } + )); + + registerServerExecutor(PacketUIClientAction.class, (packet, handler) -> { Container openContainer = handler.player.openContainer; if (openContainer instanceof ModularUIContainer && @@ -205,6 +229,12 @@ public static void init() { } }); + NetworkHandler.registerServerExecutor(PacketClipboardUIWidgetUpdate.class, (packet, handler) -> { + if (packet.clipboard != null) { + packet.clipboard.readUIAction(handler.player, packet.id, packet.buf); + } + }); + if (FMLCommonHandler.instance().getSide().isClient()) { initClient(); } diff --git a/src/main/java/gregtech/api/net/PacketClipboardUIWidgetUpdate.java b/src/main/java/gregtech/api/net/PacketClipboardUIWidgetUpdate.java new file mode 100644 index 00000000000..2200e17c68e --- /dev/null +++ b/src/main/java/gregtech/api/net/PacketClipboardUIWidgetUpdate.java @@ -0,0 +1,28 @@ +package gregtech.api.net; + +import gregtech.api.metatileentity.MetaTileEntityHolder; +import gregtech.common.metatileentities.MetaTileEntityClipboard; +import net.minecraft.network.PacketBuffer; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.math.BlockPos; +import net.minecraftforge.fml.common.FMLCommonHandler; + +import java.util.function.Consumer; + +public class PacketClipboardUIWidgetUpdate implements NetworkHandler.Packet { + public MetaTileEntityClipboard clipboard; + public int id; + public Consumer payloadWriter; + public PacketBuffer buf; + + public PacketClipboardUIWidgetUpdate(MetaTileEntityClipboard clipboard, int id, Consumer payloadWriter) { + this.clipboard = clipboard; + this.id = id; + this.payloadWriter = payloadWriter; + } + + public PacketClipboardUIWidgetUpdate(MetaTileEntityClipboard clipboard, PacketBuffer buf) { + this(clipboard, buf.readVarInt(), null); + this.buf = buf; + } +} diff --git a/src/main/java/gregtech/api/render/ClipboardRenderer.java b/src/main/java/gregtech/api/render/ClipboardRenderer.java index e3995233b5e..e676e04058a 100644 --- a/src/main/java/gregtech/api/render/ClipboardRenderer.java +++ b/src/main/java/gregtech/api/render/ClipboardRenderer.java @@ -8,29 +8,21 @@ import codechicken.lib.vec.Rotation; import gregtech.api.gui.ModularUI; import gregtech.api.gui.Widget; -import gregtech.api.gui.impl.fakegui.FakeModularGui; -import gregtech.api.gui.impl.fakegui.FakeModularUIContainer; -import gregtech.api.metatileentity.MetaTileEntityHolder; +import gregtech.api.gui.impl.FakeModularGui; +import gregtech.common.gui.impl.FakeModularUIContainerClipboard; import gregtech.api.util.GTLog; import gregtech.api.util.GregFakePlayer; import gregtech.common.metatileentities.MetaTileEntityClipboard; import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.client.renderer.GlStateManager; -import net.minecraft.client.renderer.RenderHelper; -import net.minecraft.client.renderer.Tessellator; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.renderer.texture.TextureMap; -import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher; -import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer; -import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.util.EnumFacing; import net.minecraft.util.ResourceLocation; import net.minecraftforge.common.util.FakePlayer; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; import org.apache.commons.lang3.tuple.Pair; -import org.lwjgl.opengl.GL11; import java.util.ArrayList; import java.util.Arrays; @@ -69,87 +61,44 @@ public void registerIcons(TextureMap textureMap) { @SideOnly(Side.CLIENT) public void renderBoard(CCRenderState renderState, Matrix4 translation, IVertexOperation[] pipeline, EnumFacing rotation, MetaTileEntityClipboard clipboard, float partialTicks) { - Tessellator tessellator = Tessellator.getInstance(); - BufferBuilder buffer = tessellator.getBuffer(); - - - renderState.bind(buffer); - RenderHelper.disableStandardItemLighting(); - GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); - GlStateManager.enableBlend(); - GlStateManager.disableCull(); - - if (Minecraft.isAmbientOcclusionEnabled()) { - GlStateManager.shadeModel(GL11.GL_SMOOTH); - } - else { - GlStateManager.shadeModel(GL11.GL_FLAT); - } - buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.BLOCK); - translation.translate(0.5, 0.5, 0.5); translation.rotate(Math.toRadians(90.0 * rotations.indexOf(rotation)), Rotation.axes[1]); translation.translate(-0.5, -0.5, -0.5); - - // Render Clipboard for (EnumFacing renderSide : EnumFacing.VALUES) { boxTextureMap.forEach((box, sprite) -> Textures.renderFace(renderState, translation, pipeline, renderSide, box, sprite)); } - - buffer.setTranslation(0, 0, 0); - tessellator.draw(); - GlStateManager.enableCull(); - RenderHelper.enableStandardItemLighting(); - - } @SideOnly(Side.CLIENT) - public void renderGUI(Matrix4 translation, MetaTileEntityClipboard clipboard, float partialTicks) { + public void renderGUI(double x, double y, double z, EnumFacing rotation, MetaTileEntityClipboard clipboard, float partialTicks) { + GlStateManager.pushMatrix(); - translation.translate((1 - 1) * 0.5, (1 - 1) * 0.5, 0); - translation.scale(1, 1, 1); + // All of these are done in reverse order, by the way, if you're reviewing this :P - FakeModularGui fakeGui = createFakeGui(clipboard); - if (fakeGui != null) { - Pair result = clipboard.checkLookingAt(partialTicks); - if (result == null) - fakeGui.drawScreen(0, 0, partialTicks); - else - fakeGui.drawScreen(result.getKey(), result.getValue(), partialTicks); - - } + GlStateManager.translate(x, y, z); + GlStateManager.translate(0.5, 0.5, 0.5); + GlStateManager.rotate((float) (270.0 * rotations.indexOf(rotation)), 0, 1, 0); + GlStateManager.translate(0, 0, -0.2); + GlStateManager.rotate(180, 1, 0, 0); + GlStateManager.scale(0.7, 0.7, 0.7); - } - - public FakeModularGui createFakeGui(MetaTileEntityClipboard mte) { - try { - // Get a FakePlayer in the client's current dimension through this roundabout function - FakePlayer fakePlayer = GregFakePlayer.get(Minecraft.getMinecraft().getIntegratedServer().getWorld(Minecraft.getMinecraft().player.dimension)); - ModularUI ui = mte.createUI(fakePlayer); - List widgets = new ArrayList<>(); - // Don't worry about SlotWidgets, since the clipboard literally can't have them - boolean hasPlayerInventory = false; - - ModularUI.Builder builder = new ModularUI.Builder(ui.backgroundPath, ui.getWidth(), ui.getHeight() - (hasPlayerInventory ? 80 : 0)); - for (Widget widget : widgets) { - builder.widget(widget); + if (clipboard.guiCache != null) { + Pair result = clipboard.checkLookingAt(partialTicks); + if (result == null) { + clipboard.guiCache.drawScreen(0, 0, partialTicks); } - ui = builder.build(ui.holder, ui.entityPlayer); - FakeModularUIContainer fakeModularUIContainer = new FakeModularUIContainer(ui); - if (mte.getWorld().isRemote) { - return new FakeModularGui(ui, fakeModularUIContainer); + else { + clipboard.guiCache.drawScreen(result.getKey(), result.getValue(), partialTicks); } - } catch (Exception e) { - GTLog.logger.error(e); } - return null; + GlStateManager.popMatrix(); } + @SideOnly(Side.CLIENT) public TextureAtlasSprite getParticleTexture() { return textures[0]; diff --git a/src/main/java/gregtech/api/util/GregFakePlayer.java b/src/main/java/gregtech/api/util/GregFakePlayer.java index 3b2144cd792..e764428e684 100644 --- a/src/main/java/gregtech/api/util/GregFakePlayer.java +++ b/src/main/java/gregtech/api/util/GregFakePlayer.java @@ -1,14 +1,24 @@ package gregtech.api.util; import com.mojang.authlib.GameProfile; +import net.minecraft.entity.Entity; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.server.MinecraftServer; +import net.minecraft.stats.StatBase; +import net.minecraft.util.DamageSource; +import net.minecraft.util.math.Vec3d; +import net.minecraft.util.text.ITextComponent; +import net.minecraft.world.World; import net.minecraft.world.WorldServer; import net.minecraftforge.common.util.FakePlayer; import net.minecraftforge.common.util.FakePlayerFactory; +import net.minecraftforge.common.util.ITeleporter; +import net.minecraftforge.fml.common.FMLCommonHandler; import java.lang.ref.WeakReference; import java.util.UUID; -public class GregFakePlayer { +public class GregFakePlayer extends EntityPlayer { private static GameProfile GREGTECH = new GameProfile(UUID.fromString("518FDF18-EC2A-4322-832A-58ED1721309B"), "[GregTech]"); private static WeakReference GREGTECH_PLAYER = null; @@ -22,4 +32,28 @@ public static FakePlayer get(WorldServer world) { return ret; } + public GregFakePlayer(World worldIn) { + super(worldIn, GREGTECH); + } + + @Override public boolean isSpectator() { + return false; + } + @Override public boolean isCreative() { + return false; + } + @Override public Vec3d getPositionVector(){ return new Vec3d(0, 0, 0); } + @Override public boolean canUseCommand(int i, String s){ return false; } + @Override public void sendStatusMessage(ITextComponent chatComponent, boolean actionBar){} + @Override public void sendMessage(ITextComponent component) {} + @Override public void addStat(StatBase par1StatBase, int par2){} + @Override public void openGui(Object mod, int modGuiId, World world, int x, int y, int z){} + @Override public boolean isEntityInvulnerable(DamageSource source){ return true; } + @Override public boolean canAttackPlayer(EntityPlayer player){ return false; } + @Override public void onDeath(DamageSource source){ return; } + @Override public void onUpdate(){ return; } + @Override public Entity changeDimension(int dim, ITeleporter teleporter){ return this; } + @Override public MinecraftServer getServer() { return FMLCommonHandler.instance().getMinecraftServerInstance(); } + + } diff --git a/src/main/java/gregtech/api/gui/impl/fakegui/FakeModularUIContainer.java b/src/main/java/gregtech/common/gui/impl/FakeModularUIContainerClipboard.java similarity index 84% rename from src/main/java/gregtech/api/gui/impl/fakegui/FakeModularUIContainer.java rename to src/main/java/gregtech/common/gui/impl/FakeModularUIContainerClipboard.java index ca9b65e6a93..b82fbca44f2 100644 --- a/src/main/java/gregtech/api/gui/impl/fakegui/FakeModularUIContainer.java +++ b/src/main/java/gregtech/common/gui/impl/FakeModularUIContainerClipboard.java @@ -1,10 +1,13 @@ -package gregtech.api.gui.impl.fakegui; +package gregtech.common.gui.impl; import com.google.common.collect.Lists; import gregtech.api.gui.INativeWidget; import gregtech.api.gui.ModularUI; import gregtech.api.gui.Widget; import gregtech.api.gui.widgets.WidgetUIAccess; +import gregtech.api.net.NetworkHandler; +import gregtech.api.net.PacketClipboardUIWidgetUpdate; +import gregtech.common.metatileentities.MetaTileEntityClipboard; import net.minecraft.inventory.Slot; import net.minecraft.item.ItemStack; import net.minecraft.network.PacketBuffer; @@ -15,17 +18,18 @@ import java.util.List; import java.util.function.Consumer; -public class FakeModularUIContainer implements WidgetUIAccess { + +// Note: when porting the central monitor, please make this more generic. +public class FakeModularUIContainerClipboard implements WidgetUIAccess { private final NonNullList inventoryItemStacks = NonNullList.create(); public final List inventorySlots = Lists.newArrayList(); public final ModularUI modularUI; - protected int windowId; - //private final FakeGuiPluginBehavior behavior; - public int syncId; + public int windowId; + public MetaTileEntityClipboard clipboard; - public FakeModularUIContainer(ModularUI modularUI/*, FakeGuiPluginBehavior pluginBehavior*/) { + public FakeModularUIContainerClipboard(ModularUI modularUI, MetaTileEntityClipboard clipboard) { this.modularUI = modularUI; - //this.behavior = pluginBehavior; + this.clipboard = clipboard; modularUI.initWidgets(); modularUI.guiWidgets.values().forEach(widget -> widget.setUiAccess(this)); modularUI.guiWidgets.values().stream().flatMap(widget -> widget.getNativeWidgets().stream()).forEach(nativeWidget -> addSlotToContainer(nativeWidget.getHandle())); @@ -50,15 +54,13 @@ public void handleSlotUpdate(PacketBuffer updateData) { } public void handleClientAction(PacketBuffer buffer) { - int syncId = buffer.readVarInt(); int windowId = buffer.readVarInt(); - if (syncId == this.syncId && windowId == this.windowId) { + if (windowId == this.windowId) { Widget widget = modularUI.guiWidgets.get(buffer.readVarInt()); if (widget != null) { widget.handleClientAction(buffer.readVarInt(), buffer); } } - this.syncId = 0; } public void detectAndSendChanges() { @@ -116,30 +118,23 @@ public void sendHeldItemUpdate() { @Override public void writeClientAction(Widget widget, int updateId, Consumer payloadWriter) { - /* - if (behavior != null) { - behavior.writePluginAction(1, buffer -> { - buffer.writeVarInt(syncId); + NetworkHandler.channel.sendToServer(new PacketClipboardUIWidgetUpdate(this.clipboard, updateId, buffer -> { buffer.writeVarInt(windowId); buffer.writeVarInt(modularUI.guiWidgets.inverse().get(widget)); buffer.writeVarInt(updateId); payloadWriter.accept(buffer); - }); - } - */ + }).toFMLPacket()); } @Override public void writeUpdateInfo(Widget widget, int updateId, Consumer payloadWriter) { - /* - if(behavior != null) { - behavior.writePluginData(0, buf -> { + + this.clipboard.writeCustomData(0, buf -> { buf.writeVarInt(windowId); buf.writeVarInt(modularUI.guiWidgets.inverse().get(widget)); buf.writeVarInt(updateId); payloadWriter.accept(buf); }); - } - */ + } } diff --git a/src/main/java/gregtech/common/items/behaviors/ClipboardBehaviour.java b/src/main/java/gregtech/common/items/behaviors/ClipboardBehaviour.java index fe3cfaf2068..1a1f05983ba 100644 --- a/src/main/java/gregtech/common/items/behaviors/ClipboardBehaviour.java +++ b/src/main/java/gregtech/common/items/behaviors/ClipboardBehaviour.java @@ -189,34 +189,35 @@ public ActionResult onItemRightClick(World world, EntityPlayer player @Override public ActionResult onItemUse(EntityPlayer player, World world, BlockPos pos, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ) { - ItemStack heldItem = player.getHeldItem(hand).copy(); - heldItem.setCount(1); // don't place multiple items at a time - EnumFacing playerFacing = player.getHorizontalFacing(); - // Make sure it's the right block - Block testBlock = world.getBlockState(pos).getBlock(); - if (!testBlock.isAir(world.getBlockState(pos), world, pos)) { - // Step away from the block so you don't replace it, and then give it our fun blockstate - BlockPos shiftedPos = pos.offset(playerFacing.getOpposite()); - Block shiftedBlock = world.getBlockState(shiftedPos).getBlock(); - if (shiftedBlock.isAir(world.getBlockState(shiftedPos), world, shiftedPos)) { - IBlockState state = MACHINE.getDefaultState(); - world.setBlockState(shiftedPos, state); - // Get new TE - shiftedBlock.createTileEntity(world, state); - // And manipulate it to our liking - MetaTileEntityHolder holder = (MetaTileEntityHolder) world.getTileEntity(shiftedPos); - if (holder != null) { - holder.setMetaTileEntity(CLIPBOARD_TILE); - MetaTileEntityClipboard clipboard = (MetaTileEntityClipboard) holder.getMetaTileEntity(); - if (clipboard != null) { - clipboard.setFrontFacing(playerFacing); - clipboard.setClipboard(heldItem); - ItemStack returnedStack = player.getHeldItem(hand); - if(!player.isCreative()) - { - returnedStack.setCount(player.getHeldItem(hand).getCount() - 1); + if(!world.isRemote) { + ItemStack heldItem = player.getHeldItem(hand).copy(); + heldItem.setCount(1); // don't place multiple items at a time + EnumFacing playerFacing = player.getHorizontalFacing(); + // Make sure it's the right block + Block testBlock = world.getBlockState(pos).getBlock(); + if (!testBlock.isAir(world.getBlockState(pos), world, pos)) { + // Step away from the block so you don't replace it, and then give it our fun blockstate + BlockPos shiftedPos = pos.offset(playerFacing.getOpposite()); + Block shiftedBlock = world.getBlockState(shiftedPos).getBlock(); + if (shiftedBlock.isAir(world.getBlockState(shiftedPos), world, shiftedPos)) { + IBlockState state = MACHINE.getDefaultState(); + world.setBlockState(shiftedPos, state); + // Get new TE + shiftedBlock.createTileEntity(world, state); + // And manipulate it to our liking + MetaTileEntityHolder holder = (MetaTileEntityHolder) world.getTileEntity(shiftedPos); + if (holder != null) { + holder.setMetaTileEntity(CLIPBOARD_TILE); + MetaTileEntityClipboard clipboard = (MetaTileEntityClipboard) holder.setMetaTileEntity(CLIPBOARD_TILE, heldItem); + if (clipboard != null) { + clipboard.setFrontFacing(playerFacing); + clipboard.setClipboard(heldItem); + ItemStack returnedStack = player.getHeldItem(hand); + if (!player.isCreative()) { + returnedStack.setCount(player.getHeldItem(hand).getCount() - 1); + } + return ActionResult.newResult(EnumActionResult.SUCCESS, returnedStack); } - return ActionResult.newResult(EnumActionResult.SUCCESS, returnedStack); } } } diff --git a/src/main/java/gregtech/common/metatileentities/MetaTileEntityClipboard.java b/src/main/java/gregtech/common/metatileentities/MetaTileEntityClipboard.java index 941f5660387..5e95696ebae 100644 --- a/src/main/java/gregtech/common/metatileentities/MetaTileEntityClipboard.java +++ b/src/main/java/gregtech/common/metatileentities/MetaTileEntityClipboard.java @@ -6,13 +6,20 @@ import codechicken.lib.render.pipeline.IVertexOperation; import codechicken.lib.vec.Matrix4; import gregtech.api.gui.ModularUI; +import gregtech.api.gui.Widget; +import gregtech.api.gui.impl.FakeModularGui; import gregtech.api.items.gui.PlayerInventoryHolder; import gregtech.api.items.itemhandlers.InaccessibleItemStackHandler; import gregtech.api.items.metaitem.MetaItem; import gregtech.api.items.metaitem.stats.IItemBehaviour; import gregtech.api.metatileentity.*; +import gregtech.api.net.NetworkHandler; +import gregtech.api.net.PacketClipboardUIWidgetUpdate; +import gregtech.api.util.GTLog; import gregtech.api.util.GTUtility; +import gregtech.api.util.GregFakePlayer; import gregtech.common.blocks.models.ModelCache; +import gregtech.common.gui.impl.FakeModularUIContainerClipboard; import gregtech.common.items.behaviors.ClipboardBehaviour; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.texture.TextureAtlasSprite; @@ -20,6 +27,10 @@ import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTBase; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagInt; +import net.minecraft.network.PacketBuffer; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumHand; @@ -27,22 +38,29 @@ import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.RayTraceResult; +import net.minecraftforge.common.util.FakePlayer; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; import org.apache.commons.lang3.tuple.Pair; import javax.annotation.Nullable; +import java.util.ArrayList; import java.util.List; import java.util.Optional; import static gregtech.api.render.Textures.CLIPBOARD_RENDERER; import static gregtech.common.items.MetaItems.CLIPBOARD; -public class MetaTileEntityClipboard extends MetaTileEntity implements IRenderMetaTileEntity { +public class MetaTileEntityClipboard extends MetaTileEntity implements IRenderMetaTileEntity, IFastRenderMetaTileEntity { private static final AxisAlignedBB CLIPBOARD_AABB = new AxisAlignedBB(2.75 / 16.0, 0.0, 0.0, 13.25 / 16.0, 1.0, 0.4 / 16.0); public static final ResourceLocation MODEL_RESOURCE_LOCATION = new ResourceLocation("gregtech", "block/clipboard"); - public static ModelCache cache = new ModelCache(); + public static ModelCache modelCache = new ModelCache(); public static final float scale = 1; + public FakeModularGui guiCache; + public FakeModularUIContainerClipboard guiContainerCache; + + private static final int RENDER_PASS_NORMAL = 0; + private static final NBTBase NO_CLIPBOARD_SIG = new NBTTagInt(0); public MetaTileEntityClipboard(ResourceLocation metaTileEntityId) { @@ -50,14 +68,19 @@ public MetaTileEntityClipboard(ResourceLocation metaTileEntityId) { } @Override - public void getSubItems(CreativeTabs creativeTab, NonNullList subItems) { - } + public void update() { + super.update(); + if (this.guiCache == null) + createFakeGui(); + if (this.getWorld().isRemote) { + if (guiCache != null) + guiCache.updateScreen(); - - @Override - public void renderMetaTileEntity(CCRenderState renderState, Matrix4 translation, IVertexOperation[] pipeline) { - // Just gonna ignore all of those parameters lul - //this.renderMetaTileEntityDynamic(this.getPos().getX(), this.getPos().getY(), this.getPos().getZ(), Minecraft.getMinecraft().getRenderPartialTicks()); + } else { + if (guiContainerCache != null) { + guiContainerCache.detectAndSendChanges(); + } + } } @Override @@ -65,21 +88,31 @@ public int getLightOpacity() { return 0; } - @Override public void renderMetaTileEntityDynamic(double x, double y, double z, float partialTicks) { - Matrix4 translation = new Matrix4().translate(x, y, z); - CCRenderState renderState = CCRenderState.instance(); - renderState.reset(); + if (this.getClipboard() != null) + CLIPBOARD_RENDERER.renderGUI(x, y, z, this.getFrontFacing(), this, partialTicks); + } + + @Override + public void renderMetaTileEntityFast(CCRenderState renderState, Matrix4 translation, float partialTicks) { CLIPBOARD_RENDERER.renderBoard(renderState, translation.copy(), new IVertexOperation[]{}, getFrontFacing(), this, partialTicks); - if(this.getClipboard() != null) - CLIPBOARD_RENDERER.renderGUI(translation, this, partialTicks); } public AxisAlignedBB getRenderBoundingBox() { return new AxisAlignedBB(getPos().add(-1, 0, -1), getPos().add(2, 2, 2)); } + @Override + public boolean shouldRenderInPass(int pass) { + return pass == RENDER_PASS_NORMAL; + } + + @Override + public boolean isGlobalRenderer() { + return false; + } + @Override public boolean isOpaqueCube() { return false; @@ -104,6 +137,30 @@ public ModularUI createUI(EntityPlayer entityPlayer) { return null; } + public void createFakeGui() { + // Basically just the original function from the PluginBehavior, but with a lot of now useless stuff stripped out. + try { + GregFakePlayer fakePlayer = new GregFakePlayer(this.getWorld()); + ModularUI ui = this.createUI(fakePlayer); + + ModularUI.Builder builder = new ModularUI.Builder(ui.backgroundPath, ui.getWidth(), ui.getHeight()); + + List widgets = new ArrayList<>(ui.guiWidgets.values()); + + for (Widget widget : widgets) { + builder.widget(widget); + } + ui = builder.build(ui.holder, ui.entityPlayer); + FakeModularUIContainerClipboard fakeModularUIContainer = new FakeModularUIContainerClipboard(ui, this); + this.guiContainerCache = fakeModularUIContainer; + this.guiCache = new FakeModularGui(ui, fakeModularUIContainer); + this.writeCustomData(1, buffer -> {}); + } catch (Exception e) { + GTLog.logger.error(e); + } + } + + @Override protected void initializeInventory() { super.initializeInventory(); @@ -235,4 +292,87 @@ private double[] handleRayTraceResult(RayTraceResult rayTraceResult, EnumFacing return new double[]{x, y}; } + @Override + public NBTTagCompound writeToNBT(NBTTagCompound data) { + super.writeToNBT(data); + if (this.getClipboard() != null && this.getClipboard().getTagCompound() != null) + data.setTag("clipboardNBT", this.getClipboard().getTagCompound()); + else + data.setTag("clipboardNBT", NO_CLIPBOARD_SIG); + return data; + } + + + @Override + public void readFromNBT(NBTTagCompound data) { + super.readFromNBT(data); + NBTBase clipboardNBT = data.getTag("clipboardNBT"); + if (clipboardNBT != NO_CLIPBOARD_SIG && clipboardNBT instanceof NBTTagCompound) { + ItemStack clipboard = this.getClipboard(); + clipboard.setTagCompound((NBTTagCompound) clipboardNBT); + this.setClipboard(clipboard); + } + } + + @Override + public void writeInitialSyncData(PacketBuffer buf) { + super.writeInitialSyncData(buf); + if (this.getClipboard() != null && this.getClipboard().getTagCompound() != null) + buf.writeCompoundTag(this.getClipboard().getTagCompound()); + else { + buf.writeCompoundTag(new NBTTagCompound()); + } + } + + @Override + public void receiveInitialSyncData(PacketBuffer buf) { + super.receiveInitialSyncData(buf); + try { + NBTTagCompound clipboardNBT = buf.readCompoundTag(); + if (clipboardNBT != new NBTTagCompound() && clipboardNBT != null) { + ItemStack clipboard = this.getClipboard(); + clipboard.setTagCompound(clipboardNBT); + this.setClipboard(clipboard); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Override + public void receiveCustomData(int dataId, PacketBuffer buf) { + super.receiveCustomData(dataId, buf); + if(dataId == 0) { + int windowID = buf.readVarInt(); + int widgetID = buf.readVarInt(); + if (guiCache != null) + guiCache.handleWidgetUpdate(windowID, widgetID, buf); + } else if (dataId == 1) { + createFakeGui(); + } + } + + + + @Override + public void preInit(Object... data) { + if (data.length != 0 && data[0] instanceof ItemStack) + this.setClipboard((ItemStack) data[0]); + } + + @Override + public void getSubItems(CreativeTabs creativeTab, NonNullList subItems) { // JEI shouldn't show this + } + + @Override + public void renderMetaTileEntity(CCRenderState renderState, Matrix4 translation, IVertexOperation[] pipeline) { + } + + public void readUIAction(EntityPlayerMP player, int id, PacketBuffer buf) { + if (id == 1) { + if (this.guiContainerCache != null) { + guiContainerCache.handleClientAction(buf); + } + } + } } diff --git a/src/main/java/gregtech/common/render/clipboard/TileEntityClipboardRenderer.java b/src/main/java/gregtech/common/render/clipboard/TileEntityClipboardRenderer.java deleted file mode 100644 index 5ecff896253..00000000000 --- a/src/main/java/gregtech/common/render/clipboard/TileEntityClipboardRenderer.java +++ /dev/null @@ -1,103 +0,0 @@ -package gregtech.common.render.clipboard; - -import codechicken.lib.render.BlockRenderer; -import codechicken.lib.render.CCModel; -import codechicken.lib.render.CCRenderState; -import codechicken.lib.render.block.BlockRenderingRegistry; -import codechicken.lib.render.block.ICCBlockRenderer; -import codechicken.lib.render.item.IItemRenderer; -import codechicken.lib.render.pipeline.ColourMultiplier; -import codechicken.lib.render.pipeline.IVertexOperation; -import codechicken.lib.texture.TextureUtils; -import codechicken.lib.vec.Cuboid6; -import codechicken.lib.vec.Matrix4; -import codechicken.lib.vec.TransformationList; -import codechicken.lib.vec.Vector3; -import codechicken.lib.vec.uv.IconTransformation; -import gregtech.api.GTValues; -import gregtech.common.items.MetaItem1; -import gregtech.common.render.StoneRenderer; -import net.minecraft.block.state.IBlockState; -import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.BufferBuilder; -import net.minecraft.client.renderer.Tessellator; -import net.minecraft.client.renderer.block.model.ModelResourceLocation; -import net.minecraft.client.renderer.texture.TextureAtlasSprite; -import net.minecraft.client.renderer.texture.TextureMap; -import net.minecraft.client.renderer.vertex.DefaultVertexFormats; -import net.minecraft.util.EnumBlockRenderType; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Vec3d; -import net.minecraft.world.IBlockAccess; -import net.minecraftforge.client.event.ModelBakeEvent; -import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; -import org.lwjgl.opengl.GL11; - -import java.util.Random; - -import static gregtech.common.items.MetaItems.CLIPBOARD; - -public class TileEntityClipboardRenderer implements ICCBlockRenderer { - private static final TileEntityClipboardRenderer INSTANCE = new TileEntityClipboardRenderer(); - public static EnumBlockRenderType BLOCK_RENDER_TYPE; - public static ModelResourceLocation MODEL_LOCATION = new ModelResourceLocation(new ResourceLocation(GTValues.MODID, "clipboard"), "normal"); - - - public static void preInit() { - BLOCK_RENDER_TYPE = BlockRenderingRegistry.createRenderType("gt_clipboard"); - BlockRenderingRegistry.registerRenderer(BLOCK_RENDER_TYPE, INSTANCE); - } - - - @Override - public void handleRenderBlockDamage(IBlockAccess world, BlockPos pos, IBlockState state, TextureAtlasSprite sprite, BufferBuilder buffer) { - CCRenderState renderState = CCRenderState.instance(); - renderState.reset(); - renderState.bind(buffer); - renderState.setPipeline(new Vector3(new Vec3d(pos)).translation(), new IconTransformation(sprite)); - Cuboid6 baseBox = new Cuboid6(state.getBoundingBox(world, pos)); - BlockRenderer.renderCuboid(renderState, baseBox, 0); - } - - @Override - public boolean renderBlock(IBlockAccess world, BlockPos pos, IBlockState state, BufferBuilder buffer) { - CCRenderState renderState = CCRenderState.instance(); - renderState.reset(); - renderState.bind(buffer); - Matrix4 translation = new Matrix4(); - translation.translate(pos.getX(), pos.getY(), pos.getZ()); - TextureAtlasSprite clipboardSprite = TextureUtils.getItemTexture("gregtech:metaitems/clipboard/clipboard"); - - IVertexOperation[] operations = new IVertexOperation[] { - new IconTransformation(clipboardSprite), - new TransformationList(translation)}; - if (world != null) { - renderState.setBrightness(world, pos); - } - renderState.setPipeline(operations); - //renderState.setModel(/*????????*/); - //renderState.render(); - - - - //Second: - //render your gui here - - Tessellator tessellator = Tessellator.getInstance(); - - return true; - } - - @Override - public void renderBrightness(IBlockState state, float v) { - Tessellator tessellator = Tessellator.getInstance(); - tessellator.getBuffer().begin(GL11.GL_QUADS, DefaultVertexFormats.BLOCK); - renderBlock(null, BlockPos.ORIGIN, state, tessellator.getBuffer()); - tessellator.draw(); - } - - @Override - public void registerTextures(TextureMap textureMap) { // Deprecated - } -} From 8ddc5da58216cab0770cd1acaad34896dc391419 Mon Sep 17 00:00:00 2001 From: bruberu <80226372+bruberu@users.noreply.github.com> Date: Sat, 7 Aug 2021 11:27:16 -0500 Subject: [PATCH 17/42] Fix references to removed class --- src/main/java/gregtech/api/render/ClipboardRenderer.java | 6 +++--- src/main/java/gregtech/common/ClientProxy.java | 2 -- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/main/java/gregtech/api/render/ClipboardRenderer.java b/src/main/java/gregtech/api/render/ClipboardRenderer.java index e676e04058a..08ad4b0e386 100644 --- a/src/main/java/gregtech/api/render/ClipboardRenderer.java +++ b/src/main/java/gregtech/api/render/ClipboardRenderer.java @@ -79,11 +79,11 @@ public void renderGUI(double x, double y, double z, EnumFacing rotation, MetaTil // All of these are done in reverse order, by the way, if you're reviewing this :P GlStateManager.translate(x, y, z); - GlStateManager.translate(0.5, 0.5, 0.5); + GlStateManager.translate(0.5, 0.4, 0.5); GlStateManager.rotate((float) (270.0 * rotations.indexOf(rotation)), 0, 1, 0); - GlStateManager.translate(0, 0, -0.2); + GlStateManager.translate(0, 0, -0.4); GlStateManager.rotate(180, 1, 0, 0); - GlStateManager.scale(0.7, 0.7, 0.7); + GlStateManager.scale(0.8, 0.8, 0.8); if (clipboard.guiCache != null) { Pair result = clipboard.checkLookingAt(partialTicks); diff --git a/src/main/java/gregtech/common/ClientProxy.java b/src/main/java/gregtech/common/ClientProxy.java index 6a32c57856d..a0c37e7ac90 100644 --- a/src/main/java/gregtech/common/ClientProxy.java +++ b/src/main/java/gregtech/common/ClientProxy.java @@ -21,7 +21,6 @@ import gregtech.common.render.FluidPipeRenderer; import gregtech.common.render.ItemPipeRenderer; import gregtech.common.render.StoneRenderer; -import gregtech.common.render.clipboard.TileEntityClipboardRenderer; import net.minecraft.block.BlockColored; import net.minecraft.block.state.IBlockState; import net.minecraft.client.Minecraft; @@ -108,7 +107,6 @@ public void onPreLoad() { FluidPipeRenderer.preInit(); ItemPipeRenderer.preInit(); StoneRenderer.preInit(); - TileEntityClipboardRenderer.preInit(); MetaEntities.initRenderers(); TextureUtils.addIconRegister(MetaFluids::registerSprites); MinecraftForge.EVENT_BUS.register(ToolRenderHandler.INSTANCE); From abfa0be5e8576ebba28bd6d94262547d16616f22 Mon Sep 17 00:00:00 2001 From: bruberu <80226372+bruberu@users.noreply.github.com> Date: Sat, 7 Aug 2021 12:27:07 -0500 Subject: [PATCH 18/42] Tweak clipboard's location --- src/main/java/gregtech/api/render/ClipboardRenderer.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/gregtech/api/render/ClipboardRenderer.java b/src/main/java/gregtech/api/render/ClipboardRenderer.java index 08ad4b0e386..ed725f7fc2b 100644 --- a/src/main/java/gregtech/api/render/ClipboardRenderer.java +++ b/src/main/java/gregtech/api/render/ClipboardRenderer.java @@ -79,11 +79,11 @@ public void renderGUI(double x, double y, double z, EnumFacing rotation, MetaTil // All of these are done in reverse order, by the way, if you're reviewing this :P GlStateManager.translate(x, y, z); - GlStateManager.translate(0.5, 0.4, 0.5); + GlStateManager.translate(0.5, 0.451, 0.5); GlStateManager.rotate((float) (270.0 * rotations.indexOf(rotation)), 0, 1, 0); - GlStateManager.translate(0, 0, -0.4); + GlStateManager.translate(0, 0, -0.468); GlStateManager.rotate(180, 1, 0, 0); - GlStateManager.scale(0.8, 0.8, 0.8); + GlStateManager.scale(0.875, 0.875, 0.875); if (clipboard.guiCache != null) { Pair result = clipboard.checkLookingAt(partialTicks); From bfe7e4d7ef6b84b2e8af76b61d0303e56e3753c3 Mon Sep 17 00:00:00 2001 From: bruberu <80226372+bruberu@users.noreply.github.com> Date: Sat, 7 Aug 2021 12:51:53 -0500 Subject: [PATCH 19/42] Remove more old code --- .../gregtech/api/gui/impl/FakeModularGui.java | 2 +- .../common/blocks/models/ModelClipboard.java | 210 ------------------ 2 files changed, 1 insertion(+), 211 deletions(-) delete mode 100644 src/main/java/gregtech/common/blocks/models/ModelClipboard.java diff --git a/src/main/java/gregtech/api/gui/impl/FakeModularGui.java b/src/main/java/gregtech/api/gui/impl/FakeModularGui.java index c6a818f5fde..2a02614efe0 100644 --- a/src/main/java/gregtech/api/gui/impl/FakeModularGui.java +++ b/src/main/java/gregtech/api/gui/impl/FakeModularGui.java @@ -105,7 +105,7 @@ public void drawGuiContainerBackgroundLayer(float partialTicks, int mouseX, int modularUI.backgroundPath.draw(0, 0, modularUI.getWidth(), modularUI.getHeight()); for (Widget widget : modularUI.guiWidgets.values()) { GlStateManager.pushMatrix(); - GlStateManager.color(0.0f, 1.0f, 0.5f); + GlStateManager.color(1.0f, 1.0f, 1.0f); GlStateManager.enableBlend(); widget.drawInBackground(mouseX, mouseY, this); GlStateManager.popMatrix(); diff --git a/src/main/java/gregtech/common/blocks/models/ModelClipboard.java b/src/main/java/gregtech/common/blocks/models/ModelClipboard.java deleted file mode 100644 index c346cde8da0..00000000000 --- a/src/main/java/gregtech/common/blocks/models/ModelClipboard.java +++ /dev/null @@ -1,210 +0,0 @@ -package gregtech.common.blocks.models; - - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Lists; -import net.minecraft.block.state.IBlockState; -import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.FontRenderer; -import net.minecraft.client.renderer.block.model.*; -import net.minecraft.client.renderer.texture.TextureAtlasSprite; -import net.minecraft.client.renderer.vertex.DefaultVertexFormats; -import net.minecraft.entity.EntityLivingBase; -import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.util.EnumFacing; -import net.minecraft.util.ResourceLocation; -import net.minecraft.world.World; -import net.minecraftforge.client.model.IModel; -import net.minecraftforge.client.model.ModelLoaderRegistry; -import net.minecraftforge.client.model.obj.OBJModel; -import net.minecraftforge.common.model.IModelState; -import net.minecraftforge.common.model.TRSRTransformation; -import net.minecraftforge.common.property.IExtendedBlockState; -import net.minecraftforge.common.property.IUnlistedProperty; -import org.apache.commons.lang3.tuple.Pair; - -import javax.annotation.Nonnull; -import javax.vecmath.Matrix4f; -import javax.vecmath.Quat4f; -import javax.vecmath.Vector3f; -import java.util.ArrayList; -import java.util.List; -import java.util.function.Function; - -public class ModelClipboard implements IBakedModel { - private IModel model = null; - - private IBakedModel baseModel; - - public static final ModelResourceLocation modelResourceLocation = new ModelResourceLocation("bibliocraft:Clipboard"); - - public static final ModelResourceLocation clipboardBasicModel = new ModelResourceLocation("bibliocraft:clipboardsimple"); - - private CustomItemOverrideList overrides = new CustomItemOverrideList(); - - public IBakedModel wrapper; - - private FontRenderer textRender; - - private ModelCache cache; - - private boolean gotOBJ = false; - - protected Function textureGetter; - - private void getModel(IBlockState state, ItemStack stack) { - if (this.model == null || (this.model != null && !this.model.toString().contains("obj.OBJModel"))) - try { - this.model = ModelLoaderRegistry.getModel(new ResourceLocation("bibliocraft:block/clipboard.obj")); - this.model = this.model.process(ImmutableMap.of("flip-v", "true")); - this.gotOBJ = true; - } catch (Exception e) { - this.model = ModelLoaderRegistry.getMissingModel(); - this.gotOBJ = false; - } - OBJModel.OBJState modelState = new OBJModel.OBJState(Lists.newArrayList("OBJModel.Group.All.Key"), true); - if (state != null && state instanceof IExtendedBlockState) { - IExtendedBlockState exState = (IExtendedBlockState) state; - if (exState.getUnlistedNames().contains(OBJModel.OBJProperty.INSTANCE)) { - modelState = exState.getValue(OBJModel.OBJProperty.INSTANCE); - IBakedModel bakedModel = this.model.bake(modelState, DefaultVertexFormats.ITEM, this.textureGetter); - this.baseModel = bakedModel; - } - if (modelState == null) - return; - } - if (state == null /*&& stack.getItem() == ItemClipboard.instance*/) { - String cacheName = "clipboard" + getModelPartsNumberString(stack); - if (this.cache.findModel(cacheName)) { - this.baseModel = this.cache.getCurrentMatch(); - } else { - modelState = new OBJModel.OBJState(getModelParts(stack), true); - IBakedModel bakedModel = this.model.bake(new OBJModel.OBJState(getModelParts(stack), true), DefaultVertexFormats.ITEM, (Function) this.textureGetter); - if (this.gotOBJ) - this.cache.addToCache(bakedModel, cacheName); - this.baseModel = bakedModel; - } - } - } - - private String getModelPartsNumberString(ItemStack stack) { - NBTTagCompound tags = stack.getTagCompound(); - String value = ""; - if (tags != null) { - int currentPage = tags.getInteger("currentPage"); - int totalPages = tags.getInteger("totalPages"); - String pagenum = "page" + currentPage; - NBTTagCompound pagetag = tags.getCompoundTag(pagenum); - if (pagetag != null) { - int[] states = pagetag.getIntArray("taskStates"); - if (states != null && states.length == 9) - for (int i = 0; i < states.length; i++) - value = value + states[i]; - } - } - return value; - } - - public List getModelParts(ItemStack stack) { - List modelParts = new ArrayList<>(); - NBTTagCompound tags = stack.getTagCompound(); - if (tags != null) { - int currentPage = tags.getInteger("currentPage"); - int totalPages = tags.getInteger("totalPages"); - String pagenum = "page" + currentPage; - NBTTagCompound pagetag = tags.getCompoundTag(pagenum); - if (pagetag != null) { - int[] states = pagetag.getIntArray("taskStates"); - if (states != null && states.length == 9) { - for (int i = 0; i < 9; i++) { - modelParts.add(states[i] == 1 ? String.format("box%sc", i) : String.format("box%sx", i)); - } // Look at that, Nuchaz. 70 lines reduced into one ternary. What were you thinking?????? - } - } - } - modelParts.add("Clipboard"); - return modelParts; - } - - public ModelClipboard() { - this.textureGetter = location -> Minecraft.getMinecraft().getTextureMapBlocks().getAtlasSprite("bibliocraft:models/clipboard"); - this.textRender = (Minecraft.getMinecraft()).fontRenderer; - this.wrapper = this; - this.cache = new ModelCache(); - } - - public boolean isAmbientOcclusion() { - return false; - } - - public boolean isGui3d() { - return false; - } - - public boolean isBuiltInRenderer() { - return false; - } - - public TextureAtlasSprite getParticleTexture() { - if (this.baseModel.getParticleTexture() == null) - return Minecraft.getMinecraft().getTextureMapBlocks().getAtlasSprite("minecraft:blocks/planks_oak"); - return this.baseModel.getParticleTexture(); - } - - public ItemCameraTransforms getItemCameraTransforms() { - return ItemCameraTransforms.DEFAULT; - } - - public Pair handlePerspective(ItemCameraTransforms.TransformType cameraTransformType) { - TRSRTransformation transform = new TRSRTransformation(new Vector3f(0.0F, 0.0F, 0.0F), new Quat4f(0.0F, 0.0F, 0.0F, 1.0F), new Vector3f(1.0F, 1.0F, 1.0F), new Quat4f(0.0F, 0.0F, 0.0F, 1.0F)); - switch (cameraTransformType) { - case FIRST_PERSON_RIGHT_HAND: - transform = new TRSRTransformation(new Vector3f(-0.05F, 0.25F, 0.3F), new Quat4f(0.0F, -1.0F, 0.0F, 1.0F), new Vector3f(0.5F, 0.5F, 0.5F), new Quat4f(0.0F, 0.0F, 0.0F, 1.0F)); - break; - case FIRST_PERSON_LEFT_HAND: - transform = new TRSRTransformation(new Vector3f(0.0F, 0.25F, 0.3F), new Quat4f(0.0F, 1.0F, 0.0F, 1.0F), new Vector3f(0.5F, 0.5F, 0.5F), new Quat4f(0.0F, 0.0F, 0.0F, 1.0F)); - break; - case THIRD_PERSON_RIGHT_HAND: - transform = new TRSRTransformation(new Vector3f(0.0F, 0.2F, 0.4F), new Quat4f(0.0F, -1.0F, 0.0F, 1.0F), new Vector3f(0.75F, 0.75F, 0.75F), new Quat4f(0.0F, 0.0F, 0.0F, 1.0F)); - break; - case THIRD_PERSON_LEFT_HAND: - transform = new TRSRTransformation(new Vector3f(0.0F, 0.2F, 0.4F), new Quat4f(0.0F, 1.0F, 0.0F, 1.0F), new Vector3f(0.75F, 0.75F, 0.75F), new Quat4f(0.0F, 0.0F, 0.0F, 1.0F)); - break; - case GUI: - transform = new TRSRTransformation(new Vector3f(0.0F, 0.0F, 0.0F), new Quat4f(0.0F, -1.0F, 0.0F, 1.0F), new Vector3f(1.0F, 1.0F, 1.0F), new Quat4f(0.0F, 0.0F, 0.0F, 1.0F)); - break; - case GROUND: - transform = new TRSRTransformation(new Vector3f(0.35F, 0.15F, 0.0F), new Quat4f(0.0F, 0.0F, 0.0F, 1.0F), new Vector3f(0.75F, 0.75F, 0.75F), new Quat4f(0.0F, 0.0F, 0.0F, 1.0F)); - break; - } - return Pair.of(this, transform.getMatrix()); - } - - public List getQuads(IBlockState state, EnumFacing side, long rand) { - getModel(state, ItemStack.EMPTY); - try { - List q = this.baseModel.getQuads(state, side, rand); - return q; - } catch (NullPointerException e) { - return new ArrayList<>(); - } - } - - public ItemOverrideList getOverrides() { - return this.overrides; - } - - private class CustomItemOverrideList extends ItemOverrideList { - private CustomItemOverrideList() { - super(ImmutableList.of()); - } - - @Nonnull - public IBakedModel handleItemState(@Nonnull IBakedModel originalModel, ItemStack stack, @Nonnull World world, @Nonnull EntityLivingBase entity) { - ModelClipboard.this.getModel(null, stack); - return ModelClipboard.this.wrapper; - } - } -} From 7329d1486511f01839a78c38b92864b4ddd8acda Mon Sep 17 00:00:00 2001 From: bruberu <80226372+bruberu@users.noreply.github.com> Date: Sun, 8 Aug 2021 17:55:28 -0500 Subject: [PATCH 20/42] Get GUI interactivity online! (4/4) :lets: --- .../api/render/ClipboardRenderer.java | 4 +- .../java/gregtech/common/items/MetaItem1.java | 2 +- .../MetaTileEntityClipboard.java | 102 +++++++++++------- 3 files changed, 66 insertions(+), 42 deletions(-) diff --git a/src/main/java/gregtech/api/render/ClipboardRenderer.java b/src/main/java/gregtech/api/render/ClipboardRenderer.java index ed725f7fc2b..0e71f2afb9e 100644 --- a/src/main/java/gregtech/api/render/ClipboardRenderer.java +++ b/src/main/java/gregtech/api/render/ClipboardRenderer.java @@ -80,13 +80,13 @@ public void renderGUI(double x, double y, double z, EnumFacing rotation, MetaTil GlStateManager.translate(x, y, z); GlStateManager.translate(0.5, 0.451, 0.5); - GlStateManager.rotate((float) (270.0 * rotations.indexOf(rotation)), 0, 1, 0); + GlStateManager.rotate((float) (90.0 * rotations.indexOf(rotation)), 0, 1, 0); GlStateManager.translate(0, 0, -0.468); GlStateManager.rotate(180, 1, 0, 0); GlStateManager.scale(0.875, 0.875, 0.875); if (clipboard.guiCache != null) { - Pair result = clipboard.checkLookingAt(partialTicks); + Pair result = clipboard.checkLookingAt(); if (result == null) { clipboard.guiCache.drawScreen(0, 0, partialTicks); } diff --git a/src/main/java/gregtech/common/items/MetaItem1.java b/src/main/java/gregtech/common/items/MetaItem1.java index 901bbad1203..93527575056 100644 --- a/src/main/java/gregtech/common/items/MetaItem1.java +++ b/src/main/java/gregtech/common/items/MetaItem1.java @@ -520,7 +520,7 @@ public void registerSubItems() { VOLTAGE_COIL_UV = addItem(368, "voltage_coil.uv"); /* IDs 368-373 (incl.) reserved for UHV-MAX tier voltage coils */ - CLIPBOARD = addItem(380, "clipboard").addComponents(new ClipboardBehaviour()); + CLIPBOARD = addItem(466, "clipboard").addComponents(new ClipboardBehaviour()); } public void registerRecipes() { diff --git a/src/main/java/gregtech/common/metatileentities/MetaTileEntityClipboard.java b/src/main/java/gregtech/common/metatileentities/MetaTileEntityClipboard.java index 5e95696ebae..d1c660c6de0 100644 --- a/src/main/java/gregtech/common/metatileentities/MetaTileEntityClipboard.java +++ b/src/main/java/gregtech/common/metatileentities/MetaTileEntityClipboard.java @@ -4,7 +4,9 @@ import codechicken.lib.raytracer.IndexedCuboid6; import codechicken.lib.render.CCRenderState; import codechicken.lib.render.pipeline.IVertexOperation; +import codechicken.lib.vec.Cuboid6; import codechicken.lib.vec.Matrix4; +import codechicken.lib.vec.Vector3; import gregtech.api.gui.ModularUI; import gregtech.api.gui.Widget; import gregtech.api.gui.impl.FakeModularGui; @@ -13,8 +15,6 @@ import gregtech.api.items.metaitem.MetaItem; import gregtech.api.items.metaitem.stats.IItemBehaviour; import gregtech.api.metatileentity.*; -import gregtech.api.net.NetworkHandler; -import gregtech.api.net.PacketClipboardUIWidgetUpdate; import gregtech.api.util.GTLog; import gregtech.api.util.GTUtility; import gregtech.api.util.GregFakePlayer; @@ -37,10 +37,7 @@ import net.minecraft.util.NonNullList; import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.AxisAlignedBB; -import net.minecraft.util.math.RayTraceResult; -import net.minecraftforge.common.util.FakePlayer; -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; +import net.minecraft.util.math.Vec3d; import org.apache.commons.lang3.tuple.Pair; import javax.annotation.Nullable; @@ -48,6 +45,7 @@ import java.util.List; import java.util.Optional; +import static codechicken.lib.raytracer.RayTracer.*; import static gregtech.api.render.Textures.CLIPBOARD_RENDERER; import static gregtech.common.items.MetaItems.CLIPBOARD; @@ -58,6 +56,8 @@ public class MetaTileEntityClipboard extends MetaTileEntity implements IRenderMe public static final float scale = 1; public FakeModularGui guiCache; public FakeModularUIContainerClipboard guiContainerCache; + private static final Cuboid6 pageBox = new Cuboid6(3 / 16.0, 0.25 / 16.0, 0.25 / 16.0, 13 / 16.0, 14.25 / 16.0, 0.3 / 16.0); + private static final int RENDER_PASS_NORMAL = 0; private static final NBTBase NO_CLIPBOARD_SIG = new NBTTagInt(0); @@ -75,7 +75,6 @@ public void update() { if (this.getWorld().isRemote) { if (guiCache != null) guiCache.updateScreen(); - } else { if (guiContainerCache != null) { guiContainerCache.detectAndSendChanges(); @@ -154,7 +153,8 @@ public void createFakeGui() { FakeModularUIContainerClipboard fakeModularUIContainer = new FakeModularUIContainerClipboard(ui, this); this.guiContainerCache = fakeModularUIContainer; this.guiCache = new FakeModularGui(ui, fakeModularUIContainer); - this.writeCustomData(1, buffer -> {}); + this.writeCustomData(1, buffer -> { + }); } catch (Exception e) { GTLog.logger.error(e); } @@ -217,24 +217,25 @@ public void addCollisionBoundingBox(List collisionList) { collisionList.add(new IndexedCuboid6(null, GTUtility.rotateAroundYAxis(CLIPBOARD_AABB, EnumFacing.NORTH, this.getFrontFacing()))); } + public IndexedCuboid6 getPageCuboid() { + return new IndexedCuboid6(null, GTUtility.rotateAroundYAxis(pageBox.aabb(), EnumFacing.NORTH, this.getFrontFacing())); + } + @Override public Pair getParticleTexture() { return Pair.of(CLIPBOARD_RENDERER.getParticleTexture(), 0xFFFFFF); } - @SideOnly(Side.CLIENT) - public Pair checkLookingAt(float partialTicks) { + public Pair checkLookingAt() { EntityPlayer player = Minecraft.getMinecraft().player; if (this.getWorld() != null && player != null) { - RayTraceResult rayTraceResult = player.rayTrace(Minecraft.getMinecraft().playerController.getBlockReachDistance(), partialTicks); - if (rayTraceResult != null && rayTraceResult.typeOfHit == RayTraceResult.Type.BLOCK && rayTraceResult.sideHit == this.getFrontFacing()) { - int i = -1, j = -1; + Vec3d startVec = getStartVec(player); + Vec3d endVec = getEndVec(player); + CuboidRayTraceResult rayTraceResult = rayTrace(this.getPos(), new Vector3(startVec), new Vector3(endVec), getPageCuboid()); + if (rayTraceResult != null && rayTraceResult.sideHit == this.getFrontFacing().getOpposite()) { TileEntity tileEntity = this.getWorld().getTileEntity(rayTraceResult.getBlockPos()); if (tileEntity instanceof MetaTileEntityHolder && ((MetaTileEntityHolder) tileEntity).getMetaTileEntity() instanceof MetaTileEntityClipboard) { - MetaTileEntityClipboard clipboardHit = (MetaTileEntityClipboard) ((MetaTileEntityHolder) tileEntity).getMetaTileEntity(); - double[] pos = handleRayTraceResult(rayTraceResult, this.getFrontFacing()); - pos[0] /= this.scale; - pos[1] /= this.scale; + double[] pos = handleRayTraceResult(rayTraceResult, this.getFrontFacing().getOpposite()); if (pos[0] >= 0 && pos[0] <= 1 && pos[1] >= 0 && pos[1] <= 1) return Pair.of(pos[0], pos[1]); } @@ -243,9 +244,8 @@ public Pair checkLookingAt(float partialTicks) { return null; } - private double[] handleRayTraceResult(RayTraceResult rayTraceResult, EnumFacing spin) { - double x = 0; - double y = 0; + private double[] handleRayTraceResult(CuboidRayTraceResult rayTraceResult, EnumFacing spin) { + double x, y; double dX = rayTraceResult.sideHit.getAxis() == EnumFacing.Axis.X ? rayTraceResult.hitVec.z - rayTraceResult.getBlockPos().getZ() : rayTraceResult.hitVec.x - rayTraceResult.getBlockPos().getX(); @@ -255,23 +255,15 @@ private double[] handleRayTraceResult(RayTraceResult rayTraceResult, EnumFacing if (spin == EnumFacing.NORTH) { x = 1 - dX; y = 1 - dY; - if (rayTraceResult.sideHit.getYOffset() < 0) { - y = 1 - y; - } } else if (spin == EnumFacing.SOUTH) { x = dX; y = dY; - if (rayTraceResult.sideHit.getYOffset() < 0) { - y = 1 - y; - } } else if (spin == EnumFacing.EAST) { x = 1 - dY; y = dX; if (rayTraceResult.sideHit.getXOffset() < 0 || rayTraceResult.sideHit.getZOffset() > 0) { x = 1 - x; y = 1 - y; - } else if (rayTraceResult.sideHit.getYOffset() < 0) { - y = 1 - y; } } else { x = dY; @@ -279,16 +271,17 @@ private double[] handleRayTraceResult(RayTraceResult rayTraceResult, EnumFacing if (rayTraceResult.sideHit.getXOffset() < 0 || rayTraceResult.sideHit.getZOffset() > 0) { x = 1 - x; y = 1 - y; - } else if (rayTraceResult.sideHit.getYOffset() < 0) { - y = 1 - y; } } - if (rayTraceResult.sideHit == EnumFacing.WEST || rayTraceResult.sideHit == EnumFacing.SOUTH) { - x = 1 - x; - } else if (rayTraceResult.sideHit == EnumFacing.UP) { - x = 1 - x; - y = 1 - y; - } + + y = 1 - y; // Since y values are quite weird here + + // Scale these to be 0 - 1 + x -= 3.0 / 16; + y -= 1.75 / 16; + x /= 14.0 / 16; + y /= 14.0 / 16; + return new double[]{x, y}; } @@ -337,23 +330,34 @@ public void receiveInitialSyncData(PacketBuffer buf) { } catch (Exception e) { e.printStackTrace(); } + + // Reset caches + this.guiCache = null; + this.guiContainerCache = null; } @Override public void receiveCustomData(int dataId, PacketBuffer buf) { super.receiveCustomData(dataId, buf); - if(dataId == 0) { + if (dataId == 0) { int windowID = buf.readVarInt(); int widgetID = buf.readVarInt(); if (guiCache != null) guiCache.handleWidgetUpdate(windowID, widgetID, buf); + this.scheduleRenderUpdate(); } else if (dataId == 1) { createFakeGui(); + this.scheduleRenderUpdate(); + } else if (dataId == 2) { + int mouseX = buf.readVarInt(); + int mouseY = buf.readVarInt(); + if (guiCache != null && guiContainerCache != null) { + guiCache.mouseClicked(mouseX, mouseY, 0); // Left mouse button + } + this.scheduleRenderUpdate(); } } - - @Override public void preInit(Object... data) { if (data.length != 0 && data[0] instanceof ItemStack) @@ -375,4 +379,24 @@ public void readUIAction(EntityPlayerMP player, int id, PacketBuffer buf) { } } } + + @Override + public void onLeftClick(EntityPlayer player, EnumFacing facing, CuboidRayTraceResult hitResult) { + if (this.getWorld().isRemote) return; + Pair clickCoords = this.checkLookingAt(); + if (this.guiContainerCache != null) { + int width = guiContainerCache.modularUI.getWidth(); + int height = guiContainerCache.modularUI.getHeight(); + double scale = 1.0 / Math.max(width, height); + int mouseX = (int) ((clickCoords.getLeft() / scale)); + int mouseY = (int) ((clickCoords.getRight() / scale)); + if (0 <= mouseX && mouseX <= width && 0 <= mouseY && mouseY <= height) { + this.writeCustomData(2, buf -> { + buf.writeVarInt(mouseX); + buf.writeVarInt(mouseY); + }); + } + } + + } } From 432d404e20289e76973a196d6ba071cb97b0b7a3 Mon Sep 17 00:00:00 2001 From: bruberu <80226372+bruberu@users.noreply.github.com> Date: Sun, 8 Aug 2021 22:56:40 -0500 Subject: [PATCH 21/42] Add crafting recipe, and fix some minor issues --- .../metatileentity/MetaTileEntityHolder.java | 4 ++-- .../gregtech/api/render/ClipboardRenderer.java | 7 +++++-- .../java/gregtech/common/items/MetaItem1.java | 2 +- .../items/behaviors/ClipboardBehaviour.java | 4 +++- .../MetaTileEntityClipboard.java | 17 ++++------------- .../loaders/recipe/CraftingRecipeLoader.java | 3 +++ 6 files changed, 18 insertions(+), 19 deletions(-) diff --git a/src/main/java/gregtech/api/metatileentity/MetaTileEntityHolder.java b/src/main/java/gregtech/api/metatileentity/MetaTileEntityHolder.java index 586d211bb6f..847b0854f13 100644 --- a/src/main/java/gregtech/api/metatileentity/MetaTileEntityHolder.java +++ b/src/main/java/gregtech/api/metatileentity/MetaTileEntityHolder.java @@ -244,8 +244,8 @@ public void onChunkUnload() { } @Override - public boolean shouldRefresh(@Nonnull World world, @Nonnull BlockPos pos, IBlockState oldState, IBlockState newSate) { - return oldState.getBlock() != newSate.getBlock(); //MetaTileEntityHolder should never refresh (until block changes) + public boolean shouldRefresh(@Nonnull World world, @Nonnull BlockPos pos, IBlockState oldState, IBlockState newState) { + return oldState.getBlock() != newState.getBlock(); //MetaTileEntityHolder should never refresh (until block changes) } @Override diff --git a/src/main/java/gregtech/api/render/ClipboardRenderer.java b/src/main/java/gregtech/api/render/ClipboardRenderer.java index 0e71f2afb9e..5b158d3b649 100644 --- a/src/main/java/gregtech/api/render/ClipboardRenderer.java +++ b/src/main/java/gregtech/api/render/ClipboardRenderer.java @@ -15,6 +15,7 @@ import gregtech.common.metatileentities.MetaTileEntityClipboard; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.RenderHelper; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.renderer.texture.TextureMap; import net.minecraft.util.EnumFacing; @@ -75,6 +76,7 @@ public void renderBoard(CCRenderState renderState, Matrix4 translation, IVertexO @SideOnly(Side.CLIENT) public void renderGUI(double x, double y, double z, EnumFacing rotation, MetaTileEntityClipboard clipboard, float partialTicks) { GlStateManager.pushMatrix(); + RenderHelper.disableStandardItemLighting(); // All of these are done in reverse order, by the way, if you're reviewing this :P @@ -89,11 +91,12 @@ public void renderGUI(double x, double y, double z, EnumFacing rotation, MetaTil Pair result = clipboard.checkLookingAt(); if (result == null) { clipboard.guiCache.drawScreen(0, 0, partialTicks); - } - else { + } else { clipboard.guiCache.drawScreen(result.getKey(), result.getValue(), partialTicks); } } + + RenderHelper.enableStandardItemLighting(); GlStateManager.popMatrix(); } diff --git a/src/main/java/gregtech/common/items/MetaItem1.java b/src/main/java/gregtech/common/items/MetaItem1.java index bbce471d0f0..cf451080181 100644 --- a/src/main/java/gregtech/common/items/MetaItem1.java +++ b/src/main/java/gregtech/common/items/MetaItem1.java @@ -373,7 +373,7 @@ public void registerSubItems() { NANO_SABER = addItem(463, "nano_saber").addComponents(ElectricStats.createElectricItem(4000000L, GTValues.HV)).addComponents(new NanoSaberBehavior()).setMaxStackSize(1); ENERGY_FIELD_PROJECTOR = addItem(464, "energy_field_projector").addComponents(ElectricStats.createElectricItem(16000000L, GTValues.EV)).setMaxStackSize(1); SCANNER = addItem(465, "scanner").addComponents(ElectricStats.createElectricItem(200_000L, GTValues.LV), new ScannerBehavior(50)); - CLIPBOARD = addItem(466, "clipboard").addComponents(new ClipboardBehaviour()); + CLIPBOARD = addItem(466, "clipboard").addComponents(new ClipboardBehaviour()).setMaxStackSize(1); // Misc Crafting Items: ID 491-515 ENERGIUM_DUST = addItem(491, "energium_dust"); diff --git a/src/main/java/gregtech/common/items/behaviors/ClipboardBehaviour.java b/src/main/java/gregtech/common/items/behaviors/ClipboardBehaviour.java index 1a1f05983ba..85f6c0b7532 100644 --- a/src/main/java/gregtech/common/items/behaviors/ClipboardBehaviour.java +++ b/src/main/java/gregtech/common/items/behaviors/ClipboardBehaviour.java @@ -1,5 +1,6 @@ package gregtech.common.items.behaviors; +import codechicken.lib.raytracer.RayTracer; import gregtech.api.gui.GuiTextures; import gregtech.api.gui.ModularUI; import gregtech.api.gui.widgets.ClickButtonWidget; @@ -22,6 +23,7 @@ import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumHand; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.RayTraceResult; import net.minecraft.world.World; import static gregtech.common.blocks.MetaBlocks.MACHINE; @@ -180,7 +182,7 @@ private static void incrPageNum(PlayerInventoryHolder holder, int increment) { @Override public ActionResult onItemRightClick(World world, EntityPlayer player, EnumHand hand) { ItemStack heldItem = player.getHeldItem(hand); - if (!world.isRemote) { + if (!world.isRemote && RayTracer.retrace(player).typeOfHit != RayTraceResult.Type.BLOCK) { // So that the player doesn't place a clipboard before suddenly getting the GUI PlayerInventoryHolder holder = new PlayerInventoryHolder(player, hand); holder.openUI(); } diff --git a/src/main/java/gregtech/common/metatileentities/MetaTileEntityClipboard.java b/src/main/java/gregtech/common/metatileentities/MetaTileEntityClipboard.java index d1c660c6de0..071bb89df52 100644 --- a/src/main/java/gregtech/common/metatileentities/MetaTileEntityClipboard.java +++ b/src/main/java/gregtech/common/metatileentities/MetaTileEntityClipboard.java @@ -51,7 +51,6 @@ public class MetaTileEntityClipboard extends MetaTileEntity implements IRenderMetaTileEntity, IFastRenderMetaTileEntity { private static final AxisAlignedBB CLIPBOARD_AABB = new AxisAlignedBB(2.75 / 16.0, 0.0, 0.0, 13.25 / 16.0, 1.0, 0.4 / 16.0); - public static final ResourceLocation MODEL_RESOURCE_LOCATION = new ResourceLocation("gregtech", "block/clipboard"); public static ModelCache modelCache = new ModelCache(); public static final float scale = 1; public FakeModularGui guiCache; @@ -109,7 +108,7 @@ public boolean shouldRenderInPass(int pass) { @Override public boolean isGlobalRenderer() { - return false; + return true; } @Override @@ -254,27 +253,21 @@ private double[] handleRayTraceResult(CuboidRayTraceResult rayTraceResult, EnumF : rayTraceResult.hitVec.y - rayTraceResult.getBlockPos().getY(); if (spin == EnumFacing.NORTH) { x = 1 - dX; - y = 1 - dY; } else if (spin == EnumFacing.SOUTH) { x = dX; - y = dY; } else if (spin == EnumFacing.EAST) { x = 1 - dY; - y = dX; if (rayTraceResult.sideHit.getXOffset() < 0 || rayTraceResult.sideHit.getZOffset() > 0) { x = 1 - x; - y = 1 - y; } } else { x = dY; - y = 1 - dX; if (rayTraceResult.sideHit.getXOffset() < 0 || rayTraceResult.sideHit.getZOffset() > 0) { x = 1 - x; - y = 1 - y; } } - y = 1 - y; // Since y values are quite weird here + y = 1 - dY; // Since y values are quite weird here // Scale these to be 0 - 1 x -= 3.0 / 16; @@ -315,6 +308,8 @@ public void writeInitialSyncData(PacketBuffer buf) { else { buf.writeCompoundTag(new NBTTagCompound()); } + + this.createFakeGui(); } @Override @@ -330,10 +325,6 @@ public void receiveInitialSyncData(PacketBuffer buf) { } catch (Exception e) { e.printStackTrace(); } - - // Reset caches - this.guiCache = null; - this.guiContainerCache = null; } @Override diff --git a/src/main/java/gregtech/loaders/recipe/CraftingRecipeLoader.java b/src/main/java/gregtech/loaders/recipe/CraftingRecipeLoader.java index 68c5ba7d4b1..67550c3f673 100644 --- a/src/main/java/gregtech/loaders/recipe/CraftingRecipeLoader.java +++ b/src/main/java/gregtech/loaders/recipe/CraftingRecipeLoader.java @@ -25,6 +25,7 @@ import net.minecraftforge.oredict.OreIngredient; import static gregtech.api.unification.material.Materials.*; +import static gregtech.api.unification.ore.OrePrefix.plate; public class CraftingRecipeLoader { @@ -64,6 +65,8 @@ private static void loadCraftingRecipes() { ModHandler.addSmeltingRecipe(new UnificationEntry(OrePrefix.nugget, Materials.Iron), OreDictUnifier.get(OrePrefix.nugget, Materials.WroughtIron)); + ModHandler.addShapedRecipe("clipboard", MetaItems.CLIPBOARD.getStackForm(), " Sd", "BWR", "PPP", 'P', Items.PAPER, 'R', new UnificationEntry(OrePrefix.springSmall, Iron), 'B', new UnificationEntry(OrePrefix.bolt, Iron), 'S', new UnificationEntry(OrePrefix.screw, Iron), 'W', new UnificationEntry(plate, Wood)); + for (MetaValueItem batteryItem : ToolRecipeHandler.batteryItems[0]) { ModHandler.addShapedEnergyTransferRecipe("scanner_" + batteryItem.unlocalizedName, MetaItems.SCANNER.getStackForm(), batteryItem::isItemEqual, true, From bd3e7110c2ac56146f665c1f554981f975a02ab4 Mon Sep 17 00:00:00 2001 From: bruberu <80226372+bruberu@users.noreply.github.com> Date: Mon, 9 Aug 2021 15:34:43 -0500 Subject: [PATCH 22/42] ...Why was that there? --- .../java/gregtech/common/items/behaviors/ClipboardBehaviour.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/gregtech/common/items/behaviors/ClipboardBehaviour.java b/src/main/java/gregtech/common/items/behaviors/ClipboardBehaviour.java index 85f6c0b7532..39814cf6bc3 100644 --- a/src/main/java/gregtech/common/items/behaviors/ClipboardBehaviour.java +++ b/src/main/java/gregtech/common/items/behaviors/ClipboardBehaviour.java @@ -209,7 +209,6 @@ public ActionResult onItemUse(EntityPlayer player, World world, Block // And manipulate it to our liking MetaTileEntityHolder holder = (MetaTileEntityHolder) world.getTileEntity(shiftedPos); if (holder != null) { - holder.setMetaTileEntity(CLIPBOARD_TILE); MetaTileEntityClipboard clipboard = (MetaTileEntityClipboard) holder.setMetaTileEntity(CLIPBOARD_TILE, heldItem); if (clipboard != null) { clipboard.setFrontFacing(playerFacing); From 3674b33981e4fb7302678b951cfbd64e697b8c3a Mon Sep 17 00:00:00 2001 From: bruberu <80226372+bruberu@users.noreply.github.com> Date: Mon, 9 Aug 2021 20:15:59 -0500 Subject: [PATCH 23/42] Fix more various bugs --- .../items/behaviors/ClipboardBehaviour.java | 3 ++- .../MetaTileEntityClipboard.java | 19 +++++++++++++------ .../resources/assets/gregtech/lang/en_us.lang | 2 ++ 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/main/java/gregtech/common/items/behaviors/ClipboardBehaviour.java b/src/main/java/gregtech/common/items/behaviors/ClipboardBehaviour.java index 39814cf6bc3..bfcf3fde9ec 100644 --- a/src/main/java/gregtech/common/items/behaviors/ClipboardBehaviour.java +++ b/src/main/java/gregtech/common/items/behaviors/ClipboardBehaviour.java @@ -197,7 +197,8 @@ public ActionResult onItemUse(EntityPlayer player, World world, Block EnumFacing playerFacing = player.getHorizontalFacing(); // Make sure it's the right block Block testBlock = world.getBlockState(pos).getBlock(); - if (!testBlock.isAir(world.getBlockState(pos), world, pos)) { + IBlockState testState = testBlock.getDefaultState(); + if (!testBlock.isAir(world.getBlockState(pos), world, pos) && testState.isSideSolid(world, pos, playerFacing)) { // Step away from the block so you don't replace it, and then give it our fun blockstate BlockPos shiftedPos = pos.offset(playerFacing.getOpposite()); Block shiftedBlock = world.getBlockState(shiftedPos).getBlock(); diff --git a/src/main/java/gregtech/common/metatileentities/MetaTileEntityClipboard.java b/src/main/java/gregtech/common/metatileentities/MetaTileEntityClipboard.java index 071bb89df52..059393a351b 100644 --- a/src/main/java/gregtech/common/metatileentities/MetaTileEntityClipboard.java +++ b/src/main/java/gregtech/common/metatileentities/MetaTileEntityClipboard.java @@ -21,6 +21,7 @@ import gregtech.common.blocks.models.ModelCache; import gregtech.common.gui.impl.FakeModularUIContainerClipboard; import gregtech.common.items.behaviors.ClipboardBehaviour; +import net.minecraft.block.Block; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.creativetab.CreativeTabs; @@ -152,8 +153,7 @@ public void createFakeGui() { FakeModularUIContainerClipboard fakeModularUIContainer = new FakeModularUIContainerClipboard(ui, this); this.guiContainerCache = fakeModularUIContainer; this.guiCache = new FakeModularGui(ui, fakeModularUIContainer); - this.writeCustomData(1, buffer -> { - }); + this.writeCustomData(1, buffer -> { }); } catch (Exception e) { GTLog.logger.error(e); } @@ -200,7 +200,11 @@ public boolean onRightClick(EntityPlayer playerIn, EnumHand hand, EnumFacing fac MetaTileEntityUIFactory.INSTANCE.openUI(getHolder(), (EntityPlayerMP) playerIn); } } else { - getWorld().destroyBlock(this.getPos(), true); + NonNullList drops = NonNullList.create(); + getDrops(drops, playerIn); + + Block.spawnAsEntity(playerIn.world, this.getPos(), drops.get(0)); + getWorld().destroyBlock(this.getPos(), false); } return true; } @@ -308,8 +312,6 @@ public void writeInitialSyncData(PacketBuffer buf) { else { buf.writeCompoundTag(new NBTTagCompound()); } - - this.createFakeGui(); } @Override @@ -375,7 +377,7 @@ public void readUIAction(EntityPlayerMP player, int id, PacketBuffer buf) { public void onLeftClick(EntityPlayer player, EnumFacing facing, CuboidRayTraceResult hitResult) { if (this.getWorld().isRemote) return; Pair clickCoords = this.checkLookingAt(); - if (this.guiContainerCache != null) { + if (this.guiContainerCache != null && guiContainerCache.modularUI != null) { int width = guiContainerCache.modularUI.getWidth(); int height = guiContainerCache.modularUI.getHeight(); double scale = 1.0 / Math.max(width, height); @@ -390,4 +392,9 @@ public void onLeftClick(EntityPlayer player, EnumFacing facing, CuboidRayTraceRe } } + + @Override + public boolean canPlaceCoverOnSide(EnumFacing side) { + return false; + } } diff --git a/src/main/resources/assets/gregtech/lang/en_us.lang b/src/main/resources/assets/gregtech/lang/en_us.lang index 50beb6fc995..ae35fb445af 100644 --- a/src/main/resources/assets/gregtech/lang/en_us.lang +++ b/src/main/resources/assets/gregtech/lang/en_us.lang @@ -2128,6 +2128,8 @@ gregtech.machine.stainless_steel_tank.name=Stainless Steel Tank gregtech.machine.titanium_tank.name=Titanium Tank gregtech.machine.tungstensteel_tank.name=Tungstensteel Tank +gregtech.machine.clipboard.name=Clipboard + # Granite blocks tile.granite.black_granite.normal.name=Black Granite tile.granite.black_granite.cracked.name=Black Granite Cobblestone From 59b044f44712b760f300d86b1d1ee3d0b1741f95 Mon Sep 17 00:00:00 2001 From: bruberu <80226372+bruberu@users.noreply.github.com> Date: Tue, 10 Aug 2021 12:06:55 -0500 Subject: [PATCH 24/42] Fix more bugs --- .../java/gregtech/api/gui/GuiTextures.java | 4 ++ .../api/gui/widgets/SimpleTextWidget.java | 14 ++++-- .../api/metatileentity/MetaTileEntity.java | 7 ++- .../impl/FakeModularUIContainerClipboard.java | 26 +++++----- .../items/behaviors/ClipboardBehaviour.java | 32 +++++++++++-- .../MetaTileEntityClipboard.java | 45 +++++++++++------- .../common/render/WrenchOverlayRenderer.java | 2 +- .../gregtech/textures/gui/base/blank.png | Bin 0 -> 119 bytes 8 files changed, 90 insertions(+), 40 deletions(-) create mode 100644 src/main/resources/assets/gregtech/textures/gui/base/blank.png diff --git a/src/main/java/gregtech/api/gui/GuiTextures.java b/src/main/java/gregtech/api/gui/GuiTextures.java index d3ae1344157..5429b6554dc 100644 --- a/src/main/java/gregtech/api/gui/GuiTextures.java +++ b/src/main/java/gregtech/api/gui/GuiTextures.java @@ -4,6 +4,8 @@ import gregtech.api.gui.resources.SizedTextureArea; import gregtech.api.gui.resources.TextureArea; +import javax.xml.soap.Text; + public class GuiTextures { //GREGTECH @@ -21,6 +23,8 @@ public class GuiTextures { public static final TextureArea SLOT = AdoptableTextureArea.fullImage("textures/gui/base/slot.png", 18, 18, 1, 1); public static final TextureArea SLOT_DARKENED = TextureArea.fullImage("textures/gui/base/darkened_slot.png"); + public static final TextureArea BLANK = AdoptableTextureArea.fullImage("textures/gui/base/blank.png", 1, 1, 0, 0); + //FLUID & ITEM OUTPUT BUTTONS public static final TextureArea BLOCKS_INPUT = TextureArea.fullImage("textures/gui/widget/button_blocks_input.png"); public static final TextureArea BUTTON = TextureArea.fullImage("textures/gui/widget/button.png"); diff --git a/src/main/java/gregtech/api/gui/widgets/SimpleTextWidget.java b/src/main/java/gregtech/api/gui/widgets/SimpleTextWidget.java index 7381d723882..0d9eda34a41 100644 --- a/src/main/java/gregtech/api/gui/widgets/SimpleTextWidget.java +++ b/src/main/java/gregtech/api/gui/widgets/SimpleTextWidget.java @@ -24,16 +24,22 @@ public class SimpleTextWidget extends Widget { protected final int color; protected final Supplier textSupplier; protected String lastText = ""; + protected boolean isCentered = true; - public SimpleTextWidget(int xPosition, int yPosition, String formatLocale, int color, Supplier textSupplier) { + public SimpleTextWidget(int xPosition, int yPosition, String formatLocale, int color, Supplier textSupplier, boolean isCentered) { super(new Position(xPosition, yPosition), Size.ZERO); this.color = color; this.formatLocale = formatLocale; this.textSupplier = textSupplier; + this.isCentered = isCentered; + } + + public SimpleTextWidget(int xPosition, int yPosition, String formatLocale, int color, Supplier textSupplier) { + this(xPosition, yPosition, formatLocale, color, textSupplier, true); } public SimpleTextWidget(int xPosition, int yPosition, String formatLocale, Supplier textSupplier) { - this(xPosition, yPosition, formatLocale, 0x404040, textSupplier); + this(xPosition, yPosition, formatLocale, 0x404040, textSupplier, true); } private void updateSize() { @@ -51,8 +57,8 @@ public void drawInBackground(int mouseX, int mouseY, IRenderContext context) { String text = formatLocale.isEmpty() ? (I18n.hasKey(lastText) ? I18n.format(lastText) : lastText) : I18n.format(formatLocale, lastText); Position position = getPosition(); fontRenderer.drawString(text, - position.x - fontRenderer.getStringWidth(text) / 2, - position.y - fontRenderer.FONT_HEIGHT / 2, color); + isCentered ? position.x - fontRenderer.getStringWidth(text) / 2 : position.x, + isCentered ? position.y - fontRenderer.FONT_HEIGHT / 2 : position.y, color); GlStateManager.color(rColorForOverlay, gColorForOverlay, bColorForOverlay, 1.0F); } diff --git a/src/main/java/gregtech/api/metatileentity/MetaTileEntity.java b/src/main/java/gregtech/api/metatileentity/MetaTileEntity.java index e425cee94c1..04d26f95cee 100644 --- a/src/main/java/gregtech/api/metatileentity/MetaTileEntity.java +++ b/src/main/java/gregtech/api/metatileentity/MetaTileEntity.java @@ -1237,5 +1237,10 @@ public boolean getWitherProof() { return false; } - public void preInit(Object... data) {}; + public void preInit(Object... data) { + } + + public boolean canRenderWrenchOverlay() { + return true; + } } diff --git a/src/main/java/gregtech/common/gui/impl/FakeModularUIContainerClipboard.java b/src/main/java/gregtech/common/gui/impl/FakeModularUIContainerClipboard.java index b82fbca44f2..cfa9d8e85df 100644 --- a/src/main/java/gregtech/common/gui/impl/FakeModularUIContainerClipboard.java +++ b/src/main/java/gregtech/common/gui/impl/FakeModularUIContainerClipboard.java @@ -48,7 +48,7 @@ public void handleSlotUpdate(PacketBuffer updateData) { for (int i = 0; i < size; i++) { inventorySlots.get(updateData.readVarInt()).putStack(updateData.readItemStack()); } - } catch (Exception ignored){ + } catch (Exception ignored) { } } @@ -119,22 +119,20 @@ public void sendHeldItemUpdate() { @Override public void writeClientAction(Widget widget, int updateId, Consumer payloadWriter) { NetworkHandler.channel.sendToServer(new PacketClipboardUIWidgetUpdate(this.clipboard, updateId, buffer -> { - buffer.writeVarInt(windowId); - buffer.writeVarInt(modularUI.guiWidgets.inverse().get(widget)); - buffer.writeVarInt(updateId); - payloadWriter.accept(buffer); - }).toFMLPacket()); + buffer.writeVarInt(windowId); + buffer.writeVarInt(modularUI.guiWidgets.inverse().get(widget)); + buffer.writeVarInt(updateId); + payloadWriter.accept(buffer); + }).toFMLPacket()); } @Override public void writeUpdateInfo(Widget widget, int updateId, Consumer payloadWriter) { - - this.clipboard.writeCustomData(0, buf -> { - buf.writeVarInt(windowId); - buf.writeVarInt(modularUI.guiWidgets.inverse().get(widget)); - buf.writeVarInt(updateId); - payloadWriter.accept(buf); - }); - + this.clipboard.writeCustomData(0, buf -> { + buf.writeVarInt(windowId); + buf.writeVarInt(modularUI.guiWidgets.inverse().get(widget)); + buf.writeVarInt(updateId); + payloadWriter.accept(buf); + }); } } diff --git a/src/main/java/gregtech/common/items/behaviors/ClipboardBehaviour.java b/src/main/java/gregtech/common/items/behaviors/ClipboardBehaviour.java index bfcf3fde9ec..666ebcd0116 100644 --- a/src/main/java/gregtech/common/items/behaviors/ClipboardBehaviour.java +++ b/src/main/java/gregtech/common/items/behaviors/ClipboardBehaviour.java @@ -3,10 +3,7 @@ import codechicken.lib.raytracer.RayTracer; import gregtech.api.gui.GuiTextures; import gregtech.api.gui.ModularUI; -import gregtech.api.gui.widgets.ClickButtonWidget; -import gregtech.api.gui.widgets.ImageCycleButtonWidget; -import gregtech.api.gui.widgets.SimpleTextWidget; -import gregtech.api.gui.widgets.TextFieldWidget; +import gregtech.api.gui.widgets.*; import gregtech.api.items.gui.ItemUIFactory; import gregtech.api.items.gui.PlayerInventoryHolder; import gregtech.api.items.metaitem.stats.IItemBehaviour; @@ -60,6 +57,33 @@ public ModularUI createUI(PlayerInventoryHolder holder, EntityPlayer entityPlaye return builder.build(holder, entityPlayer); } + public ModularUI createMTEUI(PlayerInventoryHolder holder, EntityPlayer entityPlayer) { // So that people don't click on any text fields + initNBT(holder.getSampleItem()); + ModularUI.Builder builder = ModularUI.builder(GuiTextures.BACKGROUND, 170, 238); + + builder.widget(new SimpleTextWidget(20, 10, "", 0x000000, () -> getTitle(holder), false)); + builder.image(20, 21, 130, 4, GuiTextures.BLANK); // To create an underline + + + for (int i = 0; i < 8; i++) { + int finalI = i; + builder.widget(new ImageCycleButtonWidget(5, 37 + 20 * i, 15, 15, GuiTextures.CLIPBOARD_CHECKBOX, 2, + () -> getButtonState(holder, finalI), (x) -> toggleButton(holder, finalI))); + builder.widget(new SimpleTextWidget(21, 40 + 20 * i, "", 0x000000, () -> getString(holder, finalI), false)); + builder.image(21, 51 + 20 * i, 140, 4, GuiTextures.BLANK); // To create an underline + } + + builder.widget(new ClickButtonWidget(30, 200, 16, 16, "", (x) -> incrPageNum(holder, -1)) + .setButtonTexture(GuiTextures.BUTTON_LEFT)); + builder.widget(new ClickButtonWidget(124, 200, 16, 16, "", (x) -> incrPageNum(holder, 1)) + .setButtonTexture(GuiTextures.BUTTON_RIGHT)); + builder.widget(new SimpleTextWidget(85, 208, "", 0x000000, + () -> (getPageNum(holder) + 1) + " / " + MAX_PAGES)); + + return builder.build(holder, entityPlayer); + } + + private static NBTTagCompound getPageCompound(ItemStack stack) { if (!MetaItems.CLIPBOARD.isItemEqual(stack)) throw new IllegalArgumentException("Given item stack is not a clipboard!"); diff --git a/src/main/java/gregtech/common/metatileentities/MetaTileEntityClipboard.java b/src/main/java/gregtech/common/metatileentities/MetaTileEntityClipboard.java index 059393a351b..0ef3c7c477a 100644 --- a/src/main/java/gregtech/common/metatileentities/MetaTileEntityClipboard.java +++ b/src/main/java/gregtech/common/metatileentities/MetaTileEntityClipboard.java @@ -27,18 +27,18 @@ import net.minecraft.creativetab.CreativeTabs; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.init.Blocks; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTBase; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagInt; import net.minecraft.network.PacketBuffer; import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.EnumFacing; -import net.minecraft.util.EnumHand; -import net.minecraft.util.NonNullList; -import net.minecraft.util.ResourceLocation; +import net.minecraft.util.*; import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; import org.apache.commons.lang3.tuple.Pair; import javax.annotation.Nullable; @@ -57,7 +57,7 @@ public class MetaTileEntityClipboard extends MetaTileEntity implements IRenderMe public FakeModularGui guiCache; public FakeModularUIContainerClipboard guiContainerCache; private static final Cuboid6 pageBox = new Cuboid6(3 / 16.0, 0.25 / 16.0, 0.25 / 16.0, 13 / 16.0, 14.25 / 16.0, 0.3 / 16.0); - + private boolean isClientReceivingUpdates = false; private static final int RENDER_PASS_NORMAL = 0; private static final NBTBase NO_CLIPBOARD_SIG = new NBTTagInt(0); @@ -70,15 +70,14 @@ public MetaTileEntityClipboard(ResourceLocation metaTileEntityId) { @Override public void update() { super.update(); - if (this.guiCache == null) - createFakeGui(); if (this.getWorld().isRemote) { if (guiCache != null) guiCache.updateScreen(); } else { - if (guiContainerCache != null) { + if (!isClientReceivingUpdates && getOffsetTimer() % 20 == 0) + createFakeGui(); + if (guiContainerCache != null) guiContainerCache.detectAndSendChanges(); - } } } @@ -130,7 +129,7 @@ public ModularUI createUI(EntityPlayer entityPlayer) { if (!clipboardBehaviour.isPresent()) return null; if (clipboardBehaviour.get() instanceof ClipboardBehaviour) { - return ((ClipboardBehaviour) clipboardBehaviour.get()).createUI(new PlayerInventoryHolder(entityPlayer, entityPlayer.getActiveHand(), getClipboard()), entityPlayer); + return ((ClipboardBehaviour) clipboardBehaviour.get()).createMTEUI(new PlayerInventoryHolder(entityPlayer, entityPlayer.getActiveHand(), getClipboard()), entityPlayer); } } return null; @@ -185,12 +184,12 @@ public void getDrops(NonNullList dropsList, @Nullable EntityPlayer ha @Override public float getBlockHardness() { - return 10; + return 100; } @Override public int getHarvestLevel() { - return 10; + return 4; } @Override @@ -200,11 +199,19 @@ public boolean onRightClick(EntityPlayer playerIn, EnumHand hand, EnumFacing fac MetaTileEntityUIFactory.INSTANCE.openUI(getHolder(), (EntityPlayerMP) playerIn); } } else { + BlockPos pos = this.getPos(); // Saving this for later so it doesn't get mangled + World world = this.getWorld(); // Same here NonNullList drops = NonNullList.create(); getDrops(drops, playerIn); + world.playEvent(2001, pos, Block.getStateId(world.getBlockState(pos))); Block.spawnAsEntity(playerIn.world, this.getPos(), drops.get(0)); - getWorld().destroyBlock(this.getPos(), false); + this.dropAllCovers(); + this.onRemoval(); + + this.getHolder().setMetaTileEntity(this); + world.removeTileEntity(pos); + world.setBlockState(pos, Blocks.AIR.getDefaultState(), 3); } return true; } @@ -212,7 +219,7 @@ public boolean onRightClick(EntityPlayer playerIn, EnumHand hand, EnumFacing fac @Override public String getHarvestTool() { - return "wrench"; + return "axe"; } @Override @@ -260,12 +267,12 @@ private double[] handleRayTraceResult(CuboidRayTraceResult rayTraceResult, EnumF } else if (spin == EnumFacing.SOUTH) { x = dX; } else if (spin == EnumFacing.EAST) { - x = 1 - dY; + x = 1 - dX; if (rayTraceResult.sideHit.getXOffset() < 0 || rayTraceResult.sideHit.getZOffset() > 0) { x = 1 - x; } } else { - x = dY; + x = dX; if (rayTraceResult.sideHit.getXOffset() < 0 || rayTraceResult.sideHit.getZOffset() > 0) { x = 1 - x; } @@ -332,6 +339,7 @@ public void receiveInitialSyncData(PacketBuffer buf) { @Override public void receiveCustomData(int dataId, PacketBuffer buf) { super.receiveCustomData(dataId, buf); + isClientReceivingUpdates = true; if (dataId == 0) { int windowID = buf.readVarInt(); int widgetID = buf.readVarInt(); @@ -397,4 +405,9 @@ public void onLeftClick(EntityPlayer player, EnumFacing facing, CuboidRayTraceRe public boolean canPlaceCoverOnSide(EnumFacing side) { return false; } + + @Override + public boolean canRenderWrenchOverlay() { + return false; + } } diff --git a/src/main/java/gregtech/common/render/WrenchOverlayRenderer.java b/src/main/java/gregtech/common/render/WrenchOverlayRenderer.java index 3222e6aead3..52902b7ebb1 100644 --- a/src/main/java/gregtech/common/render/WrenchOverlayRenderer.java +++ b/src/main/java/gregtech/common/render/WrenchOverlayRenderer.java @@ -110,7 +110,7 @@ public static boolean shouldDrawOverlayForItem(ItemStack itemStack, TileEntity t } // MetaTileEntities - if (tileEntity instanceof MetaTileEntityHolder && + if (tileEntity instanceof MetaTileEntityHolder && ((MetaTileEntityHolder) tileEntity).getMetaTileEntity().canRenderWrenchOverlay() && itemStack.hasCapability(GregtechCapabilities.CAPABILITY_WRENCH, null)) return true; diff --git a/src/main/resources/assets/gregtech/textures/gui/base/blank.png b/src/main/resources/assets/gregtech/textures/gui/base/blank.png new file mode 100644 index 0000000000000000000000000000000000000000..598fdc2de573fae8eca9cf331ee73e5fb7c06ad4 GIT binary patch literal 119 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx1SBVv2j2s6ii6yp7}lMWc?smOq&xaLGB9lH z=l+w(3gmMZctjR6FbI`^Fyp;6`3j&QkEe@ch(vgDLP7#a3j<@!+5ee97K5j&pUXO@ GgeCxVr5W}B literal 0 HcmV?d00001 From 1c437c19c5230ed192336abfbd38984b607ec99b Mon Sep 17 00:00:00 2001 From: bruberu <80226372+bruberu@users.noreply.github.com> Date: Tue, 10 Aug 2021 12:26:11 -0500 Subject: [PATCH 25/42] Fix more bugs --- src/main/java/gregtech/api/cover/ICoverable.java | 4 ++++ .../gregtech/api/metatileentity/MetaTileEntity.java | 4 ---- .../common/items/behaviors/ClipboardBehaviour.java | 4 ++-- .../gregtech/common/render/WrenchOverlayRenderer.java | 11 ++++++++--- 4 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/main/java/gregtech/api/cover/ICoverable.java b/src/main/java/gregtech/api/cover/ICoverable.java index 061223ca08f..c4dc61a4b32 100644 --- a/src/main/java/gregtech/api/cover/ICoverable.java +++ b/src/main/java/gregtech/api/cover/ICoverable.java @@ -198,4 +198,8 @@ static Cuboid6 getCoverPlateBox(EnumFacing side, double plateThickness) { throw new UnsupportedOperationException(); } } + + public default boolean canRenderWrenchOverlay() { + return true; + } } diff --git a/src/main/java/gregtech/api/metatileentity/MetaTileEntity.java b/src/main/java/gregtech/api/metatileentity/MetaTileEntity.java index 04d26f95cee..1a0ca0eb6dc 100644 --- a/src/main/java/gregtech/api/metatileentity/MetaTileEntity.java +++ b/src/main/java/gregtech/api/metatileentity/MetaTileEntity.java @@ -1239,8 +1239,4 @@ public boolean getWitherProof() { public void preInit(Object... data) { } - - public boolean canRenderWrenchOverlay() { - return true; - } } diff --git a/src/main/java/gregtech/common/items/behaviors/ClipboardBehaviour.java b/src/main/java/gregtech/common/items/behaviors/ClipboardBehaviour.java index 666ebcd0116..f079bb51bcf 100644 --- a/src/main/java/gregtech/common/items/behaviors/ClipboardBehaviour.java +++ b/src/main/java/gregtech/common/items/behaviors/ClipboardBehaviour.java @@ -62,7 +62,7 @@ public ModularUI createMTEUI(PlayerInventoryHolder holder, EntityPlayer entityPl ModularUI.Builder builder = ModularUI.builder(GuiTextures.BACKGROUND, 170, 238); builder.widget(new SimpleTextWidget(20, 10, "", 0x000000, () -> getTitle(holder), false)); - builder.image(20, 21, 130, 4, GuiTextures.BLANK); // To create an underline + builder.image(20, 19, 130, 4, GuiTextures.BLANK); // To create an underline for (int i = 0; i < 8; i++) { @@ -70,7 +70,7 @@ public ModularUI createMTEUI(PlayerInventoryHolder holder, EntityPlayer entityPl builder.widget(new ImageCycleButtonWidget(5, 37 + 20 * i, 15, 15, GuiTextures.CLIPBOARD_CHECKBOX, 2, () -> getButtonState(holder, finalI), (x) -> toggleButton(holder, finalI))); builder.widget(new SimpleTextWidget(21, 40 + 20 * i, "", 0x000000, () -> getString(holder, finalI), false)); - builder.image(21, 51 + 20 * i, 140, 4, GuiTextures.BLANK); // To create an underline + builder.image(21, 49 + 20 * i, 140, 2, GuiTextures.BLANK); // To create an underline } builder.widget(new ClickButtonWidget(30, 200, 16, 16, "", (x) -> incrPageNum(holder, -1)) diff --git a/src/main/java/gregtech/common/render/WrenchOverlayRenderer.java b/src/main/java/gregtech/common/render/WrenchOverlayRenderer.java index 52902b7ebb1..b8a2dd94421 100644 --- a/src/main/java/gregtech/common/render/WrenchOverlayRenderer.java +++ b/src/main/java/gregtech/common/render/WrenchOverlayRenderer.java @@ -4,6 +4,7 @@ import codechicken.lib.vec.Vector3; import gregtech.api.capability.GregtechCapabilities; import gregtech.api.capability.GregtechTileCapabilities; +import gregtech.api.cover.ICoverable; import gregtech.api.cover.ICoverable.PrimaryBoxData; import gregtech.api.metatileentity.MetaTileEntityHolder; import gregtech.api.pipenet.tile.TileEntityPipeBase; @@ -92,6 +93,11 @@ public static boolean useGridForRayTraceResult(RayTraceResult result) { } public static boolean shouldDrawOverlayForItem(ItemStack itemStack, TileEntity tileEntity) { + if (tileEntity instanceof ICoverable) { + if(!((ICoverable) tileEntity).canRenderWrenchOverlay()) + return false; + } + if (tileEntity instanceof TileEntityPipeBase) { TileEntityPipeBase pipeTE = (TileEntityPipeBase) tileEntity; Class pipeClass = pipeTE.getPipeBlock().getPipeTypeClass(); @@ -110,9 +116,8 @@ public static boolean shouldDrawOverlayForItem(ItemStack itemStack, TileEntity t } // MetaTileEntities - if (tileEntity instanceof MetaTileEntityHolder && ((MetaTileEntityHolder) tileEntity).getMetaTileEntity().canRenderWrenchOverlay() && - itemStack.hasCapability(GregtechCapabilities.CAPABILITY_WRENCH, null)) - return true; + if (tileEntity instanceof MetaTileEntityHolder && itemStack.hasCapability(GregtechCapabilities.CAPABILITY_WRENCH, null)) + return ((MetaTileEntityHolder) tileEntity).getMetaTileEntity().canRenderWrenchOverlay(); // ICoverable if (tileEntity.hasCapability(GregtechTileCapabilities.CAPABILITY_COVERABLE, null)) From cff5a3d6b5de1912687fdeeaa84f2d5f9c100376 Mon Sep 17 00:00:00 2001 From: bruberu <80226372+bruberu@users.noreply.github.com> Date: Tue, 10 Aug 2021 13:12:02 -0500 Subject: [PATCH 26/42] Fix non-in-world GUI, and add explainer text to tooltip --- .../common/metatileentities/MetaTileEntityClipboard.java | 9 ++++++--- src/main/resources/assets/gregtech/lang/en_us.lang | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/main/java/gregtech/common/metatileentities/MetaTileEntityClipboard.java b/src/main/java/gregtech/common/metatileentities/MetaTileEntityClipboard.java index 0ef3c7c477a..ea6af06be5e 100644 --- a/src/main/java/gregtech/common/metatileentities/MetaTileEntityClipboard.java +++ b/src/main/java/gregtech/common/metatileentities/MetaTileEntityClipboard.java @@ -129,7 +129,11 @@ public ModularUI createUI(EntityPlayer entityPlayer) { if (!clipboardBehaviour.isPresent()) return null; if (clipboardBehaviour.get() instanceof ClipboardBehaviour) { - return ((ClipboardBehaviour) clipboardBehaviour.get()).createMTEUI(new PlayerInventoryHolder(entityPlayer, entityPlayer.getActiveHand(), getClipboard()), entityPlayer); + if(entityPlayer instanceof GregFakePlayer) { + return ((ClipboardBehaviour) clipboardBehaviour.get()).createMTEUI(new PlayerInventoryHolder(entityPlayer, entityPlayer.getActiveHand(), getClipboard()), entityPlayer); + } else { + return ((ClipboardBehaviour) clipboardBehaviour.get()).createUI(new PlayerInventoryHolder(entityPlayer, entityPlayer.getActiveHand(), getClipboard()), entityPlayer); + } } } return null; @@ -194,7 +198,7 @@ public int getHarvestLevel() { @Override public boolean onRightClick(EntityPlayer playerIn, EnumHand hand, EnumFacing facing, CuboidRayTraceResult hitResult) { - if (playerIn.isSneaking()) { + if (!playerIn.isSneaking()) { if (getWorld() != null && !getWorld().isRemote) { MetaTileEntityUIFactory.INSTANCE.openUI(getHolder(), (EntityPlayerMP) playerIn); } @@ -209,7 +213,6 @@ public boolean onRightClick(EntityPlayer playerIn, EnumHand hand, EnumFacing fac this.dropAllCovers(); this.onRemoval(); - this.getHolder().setMetaTileEntity(this); world.removeTileEntity(pos); world.setBlockState(pos, Blocks.AIR.getDefaultState(), 3); } diff --git a/src/main/resources/assets/gregtech/lang/en_us.lang b/src/main/resources/assets/gregtech/lang/en_us.lang index ae35fb445af..9362c0f5548 100644 --- a/src/main/resources/assets/gregtech/lang/en_us.lang +++ b/src/main/resources/assets/gregtech/lang/en_us.lang @@ -830,7 +830,7 @@ metaitem.turbine_rotor.tooltip=Turbine Rotors for your power station metaitem.tool.magnifying_glass.name=%s Magnifying Glass metaitem.clipboard.name=Clipboard -metaitem.clipboard.tooltip=Can be written on (without any writing Instrument) +metaitem.clipboard.tooltip=Can be written on (without any writing Instrument)\nRight-click on Wall to place, and Shift-Right-Click to remove metaitem.drill.mode.three_cube=3x3x3 Cube metaitem.drill.mode.five_cube=5x5x5 Cube From d56a6d11c12b93750dea2e96e8a33570ca029e79 Mon Sep 17 00:00:00 2001 From: bruberu <80226372+bruberu@users.noreply.github.com> Date: Tue, 10 Aug 2021 21:17:49 -0500 Subject: [PATCH 27/42] Fix certain formatting and extraneous import problems --- src/main/java/gregtech/api/gui/GuiTextures.java | 2 -- .../java/gregtech/api/gui/impl/FakeModularGui.java | 11 +++-------- .../api/gui/widgets/ImageCycleButtonWidget.java | 3 +-- .../api/metatileentity/MetaTileEntityHolder.java | 2 +- .../java/gregtech/api/render/MetaTileEntityTESR.java | 6 ------ src/main/java/gregtech/common/blocks/MetaBlocks.java | 1 - .../gregtech/common/render/WrenchOverlayRenderer.java | 5 +++-- 7 files changed, 8 insertions(+), 22 deletions(-) diff --git a/src/main/java/gregtech/api/gui/GuiTextures.java b/src/main/java/gregtech/api/gui/GuiTextures.java index 5429b6554dc..379e6ee2fa0 100644 --- a/src/main/java/gregtech/api/gui/GuiTextures.java +++ b/src/main/java/gregtech/api/gui/GuiTextures.java @@ -4,8 +4,6 @@ import gregtech.api.gui.resources.SizedTextureArea; import gregtech.api.gui.resources.TextureArea; -import javax.xml.soap.Text; - public class GuiTextures { //GREGTECH diff --git a/src/main/java/gregtech/api/gui/impl/FakeModularGui.java b/src/main/java/gregtech/api/gui/impl/FakeModularGui.java index 2a02614efe0..a2e6ae07620 100644 --- a/src/main/java/gregtech/api/gui/impl/FakeModularGui.java +++ b/src/main/java/gregtech/api/gui/impl/FakeModularGui.java @@ -90,13 +90,9 @@ protected void renderToolTip(ItemStack stack, int x, int y) { protected List getItemToolTip(ItemStack itemStack) { List list = itemStack.getTooltip(mc.player, mc.gameSettings.advancedItemTooltips ? ITooltipFlag.TooltipFlags.ADVANCED : ITooltipFlag.TooltipFlags.NORMAL); - for (int i = 0; i < list.size(); ++i) { - if (i == 0) { - list.set(i, itemStack.getItem().getForgeRarity(itemStack).getColor() + list.get(i)); - } - else { - list.set(i, TextFormatting.GRAY + list.get(i)); - } + list.set(0, itemStack.getItem().getForgeRarity(itemStack).getColor() + list.get(0)); + for (int i = 1; i < list.size(); ++i) { + list.set(i, TextFormatting.GRAY + list.get(i)); } return list; } @@ -124,5 +120,4 @@ public void drawGuiContainerForegroundLayer(int mouseX, int mouseY) { public boolean mouseClicked(int mouseX, int mouseY, int mouseButton) { return modularUI.guiWidgets.values().stream().anyMatch(widget -> widget.mouseClicked(mouseX, mouseY, mouseButton)); } - } diff --git a/src/main/java/gregtech/api/gui/widgets/ImageCycleButtonWidget.java b/src/main/java/gregtech/api/gui/widgets/ImageCycleButtonWidget.java index 05e24f7b85f..3af8493ca4a 100644 --- a/src/main/java/gregtech/api/gui/widgets/ImageCycleButtonWidget.java +++ b/src/main/java/gregtech/api/gui/widgets/ImageCycleButtonWidget.java @@ -126,8 +126,7 @@ public boolean mouseClicked(int mouseX, int mouseY, int button) { if(button == RIGHT_MOUSE) { //Wrap from the first option to the last if needed this.currentOption = currentOption == 0 ? optionCount - 1 : currentOption - 1; - } - else { + } else { this.currentOption = (currentOption + 1) % optionCount; } writeClientAction(1, buf -> buf.writeVarInt(currentOption)); diff --git a/src/main/java/gregtech/api/metatileentity/MetaTileEntityHolder.java b/src/main/java/gregtech/api/metatileentity/MetaTileEntityHolder.java index 847b0854f13..ad29f206306 100644 --- a/src/main/java/gregtech/api/metatileentity/MetaTileEntityHolder.java +++ b/src/main/java/gregtech/api/metatileentity/MetaTileEntityHolder.java @@ -41,7 +41,7 @@ public MetaTileEntity getMetaTileEntity() { * Sets this holder's current meta tile entity to copy of given one * Note that this method copies given meta tile entity and returns actual instance * so it is safe to call it on sample meta tile entities - * Also can use certain data to p + * Also can use certain data to preinit the block before data is synced */ public MetaTileEntity setMetaTileEntity(MetaTileEntity sampleMetaTileEntity, Object... data) { Preconditions.checkNotNull(sampleMetaTileEntity, "metaTileEntity"); diff --git a/src/main/java/gregtech/api/render/MetaTileEntityTESR.java b/src/main/java/gregtech/api/render/MetaTileEntityTESR.java index a3c0bfdfeb0..d2d3134716a 100644 --- a/src/main/java/gregtech/api/render/MetaTileEntityTESR.java +++ b/src/main/java/gregtech/api/render/MetaTileEntityTESR.java @@ -13,7 +13,6 @@ import net.minecraft.client.renderer.RenderHelper; import net.minecraft.client.renderer.Tessellator; import net.minecraft.client.renderer.texture.TextureMap; -import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher; import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer; import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.util.EnumFacing; @@ -145,9 +144,4 @@ public boolean isGlobalRenderer(@Nonnull MetaTileEntityHolder te) { } return false; } - - @Override - public void bindTexture(ResourceLocation location) { - super.bindTexture(location); - } } diff --git a/src/main/java/gregtech/common/blocks/MetaBlocks.java b/src/main/java/gregtech/common/blocks/MetaBlocks.java index 5e0e3d49aad..c54aff7d94c 100644 --- a/src/main/java/gregtech/common/blocks/MetaBlocks.java +++ b/src/main/java/gregtech/common/blocks/MetaBlocks.java @@ -436,7 +436,6 @@ protected ModelResourceLocation getModelResourceLocation(IBlockState state) { modelHandler.addBuiltInBlock(SURFACE_ROCK, "stone_andesite"); - ClientRegistry.bindTileEntitySpecialRenderer(MetaTileEntityHolder.class, new MetaTileEntityTESR()); } diff --git a/src/main/java/gregtech/common/render/WrenchOverlayRenderer.java b/src/main/java/gregtech/common/render/WrenchOverlayRenderer.java index b8a2dd94421..357d438bf61 100644 --- a/src/main/java/gregtech/common/render/WrenchOverlayRenderer.java +++ b/src/main/java/gregtech/common/render/WrenchOverlayRenderer.java @@ -116,8 +116,9 @@ public static boolean shouldDrawOverlayForItem(ItemStack itemStack, TileEntity t } // MetaTileEntities - if (tileEntity instanceof MetaTileEntityHolder && itemStack.hasCapability(GregtechCapabilities.CAPABILITY_WRENCH, null)) - return ((MetaTileEntityHolder) tileEntity).getMetaTileEntity().canRenderWrenchOverlay(); + if (tileEntity instanceof MetaTileEntityHolder && + itemStack.hasCapability(GregtechCapabilities.CAPABILITY_WRENCH, null)) + return true; // ICoverable if (tileEntity.hasCapability(GregtechTileCapabilities.CAPABILITY_COVERABLE, null)) From cb5169886a085b016bd6b962accce98b421acb76 Mon Sep 17 00:00:00 2001 From: bruberu <80226372+bruberu@users.noreply.github.com> Date: Tue, 10 Aug 2021 21:34:01 -0500 Subject: [PATCH 28/42] Fix certain formatting and extraneous import problems --- src/main/java/gregtech/api/render/MetaTileEntityTESR.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/gregtech/api/render/MetaTileEntityTESR.java b/src/main/java/gregtech/api/render/MetaTileEntityTESR.java index d2d3134716a..28603fca290 100644 --- a/src/main/java/gregtech/api/render/MetaTileEntityTESR.java +++ b/src/main/java/gregtech/api/render/MetaTileEntityTESR.java @@ -16,7 +16,6 @@ import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer; import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.util.EnumFacing; -import net.minecraft.util.ResourceLocation; import net.minecraft.util.Tuple; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; From 60b409ed1ba5452281a9fcc8bf5dab4ad086a72f Mon Sep 17 00:00:00 2001 From: bruberu <80226372+bruberu@users.noreply.github.com> Date: Tue, 10 Aug 2021 21:37:52 -0500 Subject: [PATCH 29/42] Reformat GregFakePlayer --- .../gregtech/api/util/GregFakePlayer.java | 75 +++++++++++++++---- 1 file changed, 61 insertions(+), 14 deletions(-) diff --git a/src/main/java/gregtech/api/util/GregFakePlayer.java b/src/main/java/gregtech/api/util/GregFakePlayer.java index 9a78bc978dd..572899ad447 100644 --- a/src/main/java/gregtech/api/util/GregFakePlayer.java +++ b/src/main/java/gregtech/api/util/GregFakePlayer.java @@ -36,24 +36,71 @@ public GregFakePlayer(World worldIn) { super(worldIn, GREGTECH); } - @Override public boolean isSpectator() { + @Override + public boolean isSpectator() { return false; } - @Override public boolean isCreative() { + + @Override + public boolean isCreative() { return false; } - @Override public Vec3d getPositionVector(){ return new Vec3d(0, 0, 0); } - @Override public boolean canUseCommand(int i, String s){ return false; } - @Override public void sendStatusMessage(ITextComponent chatComponent, boolean actionBar){} - @Override public void sendMessage(ITextComponent component) {} - @Override public void addStat(StatBase par1StatBase, int par2){} - @Override public void openGui(Object mod, int modGuiId, World world, int x, int y, int z){} - @Override public boolean isEntityInvulnerable(DamageSource source){ return true; } - @Override public boolean canAttackPlayer(EntityPlayer player){ return false; } - @Override public void onDeath(DamageSource source){ return; } - @Override public void onUpdate(){ return; } - @Override public Entity changeDimension(int dim, ITeleporter teleporter){ return this; } - @Override public MinecraftServer getServer() { return FMLCommonHandler.instance().getMinecraftServerInstance(); } + + @Override + public Vec3d getPositionVector() { + return new Vec3d(0, 0, 0); + } + + @Override + public boolean canUseCommand(int i, String s) { + return false; + } + + @Override + public void sendStatusMessage(ITextComponent chatComponent, boolean actionBar) { + } + + @Override + public void sendMessage(ITextComponent component) { + } + + @Override + public void addStat(StatBase par1StatBase, int par2) { + } + + @Override + public void openGui(Object mod, int modGuiId, World world, int x, int y, int z) { + } + + @Override + public boolean isEntityInvulnerable(DamageSource source) { + return true; + } + + @Override + public boolean canAttackPlayer(EntityPlayer player) { + return false; + } + + @Override + public void onDeath(DamageSource source) { + return; + } + + @Override + public void onUpdate() { + return; + } + + @Override + public Entity changeDimension(int dim, ITeleporter teleporter) { + return this; + } + + @Override + public MinecraftServer getServer() { + return FMLCommonHandler.instance().getMinecraftServerInstance(); + } } From b251eb5eba8e0433ddc83d47e4fbbcde8814ca16 Mon Sep 17 00:00:00 2001 From: bruberu <80226372+bruberu@users.noreply.github.com> Date: Tue, 10 Aug 2021 21:40:41 -0500 Subject: [PATCH 30/42] Yeet ModelCache.java --- .../common/blocks/models/ModelCache.java | 52 ------------------- .../MetaTileEntityClipboard.java | 2 - 2 files changed, 54 deletions(-) delete mode 100644 src/main/java/gregtech/common/blocks/models/ModelCache.java diff --git a/src/main/java/gregtech/common/blocks/models/ModelCache.java b/src/main/java/gregtech/common/blocks/models/ModelCache.java deleted file mode 100644 index dbdbed64843..00000000000 --- a/src/main/java/gregtech/common/blocks/models/ModelCache.java +++ /dev/null @@ -1,52 +0,0 @@ -package gregtech.common.blocks.models; - -import java.util.ArrayList; -import net.minecraft.client.renderer.block.model.IBakedModel; - -public class ModelCache { - private ArrayList models = new ArrayList<>(); - - private IBakedModel currentMatch = null; - - public void addToCache(IBakedModel model, String name) { - ModelCachePackage pack = new ModelCachePackage(model, name); - this.models.add(pack); - } - - public boolean findModel(String name) { - boolean output = false; - for (int i = 0; i < this.models.size(); i++) { - ModelCachePackage pack = this.models.get(i); - if (pack.getTextureName().contentEquals(name)) { - output = true; - this.currentMatch = pack.getModel(); - break; - } - } - return output; - } - - public IBakedModel getCurrentMatch() { - return this.currentMatch; - } - - public static class ModelCachePackage { - private IBakedModel model; - - private String name; - - public ModelCachePackage(IBakedModel modelIn, String nameIn) { - this.model = modelIn; - this.name = nameIn; - } - - public IBakedModel getModel() { - return this.model; - } - - public String getTextureName() { - return this.name; - } - } - -} diff --git a/src/main/java/gregtech/common/metatileentities/MetaTileEntityClipboard.java b/src/main/java/gregtech/common/metatileentities/MetaTileEntityClipboard.java index ea6af06be5e..31f17b96d90 100644 --- a/src/main/java/gregtech/common/metatileentities/MetaTileEntityClipboard.java +++ b/src/main/java/gregtech/common/metatileentities/MetaTileEntityClipboard.java @@ -18,7 +18,6 @@ import gregtech.api.util.GTLog; import gregtech.api.util.GTUtility; import gregtech.api.util.GregFakePlayer; -import gregtech.common.blocks.models.ModelCache; import gregtech.common.gui.impl.FakeModularUIContainerClipboard; import gregtech.common.items.behaviors.ClipboardBehaviour; import net.minecraft.block.Block; @@ -52,7 +51,6 @@ public class MetaTileEntityClipboard extends MetaTileEntity implements IRenderMetaTileEntity, IFastRenderMetaTileEntity { private static final AxisAlignedBB CLIPBOARD_AABB = new AxisAlignedBB(2.75 / 16.0, 0.0, 0.0, 13.25 / 16.0, 1.0, 0.4 / 16.0); - public static ModelCache modelCache = new ModelCache(); public static final float scale = 1; public FakeModularGui guiCache; public FakeModularUIContainerClipboard guiContainerCache; From ac44dc12c638114aa1065d000e22293aab869c5d Mon Sep 17 00:00:00 2001 From: bruberu <80226372+bruberu@users.noreply.github.com> Date: Tue, 10 Aug 2021 21:52:05 -0500 Subject: [PATCH 31/42] Keep removing useless imports --- src/main/java/gregtech/common/blocks/MetaBlocks.java | 1 - .../gui/impl/FakeModularUIContainerClipboard.java | 11 ----------- src/main/java/gregtech/common/items/MetaItem2.java | 0 .../gregtech/loaders/recipe/CraftingRecipeLoader.java | 3 +-- 4 files changed, 1 insertion(+), 14 deletions(-) delete mode 100644 src/main/java/gregtech/common/items/MetaItem2.java diff --git a/src/main/java/gregtech/common/blocks/MetaBlocks.java b/src/main/java/gregtech/common/blocks/MetaBlocks.java index c54aff7d94c..17385b1f89f 100644 --- a/src/main/java/gregtech/common/blocks/MetaBlocks.java +++ b/src/main/java/gregtech/common/blocks/MetaBlocks.java @@ -23,7 +23,6 @@ import gregtech.common.blocks.wood.BlockGregLeaves; import gregtech.common.blocks.wood.BlockGregLog; import gregtech.common.blocks.wood.BlockGregSapling; -import gregtech.common.metatileentities.MetaTileEntityClipboard; import gregtech.common.pipelike.cable.BlockCable; import gregtech.common.pipelike.cable.Insulation; import gregtech.common.pipelike.cable.tile.TileEntityCable; diff --git a/src/main/java/gregtech/common/gui/impl/FakeModularUIContainerClipboard.java b/src/main/java/gregtech/common/gui/impl/FakeModularUIContainerClipboard.java index cfa9d8e85df..6b95f557ace 100644 --- a/src/main/java/gregtech/common/gui/impl/FakeModularUIContainerClipboard.java +++ b/src/main/java/gregtech/common/gui/impl/FakeModularUIContainerClipboard.java @@ -79,17 +79,6 @@ public void detectAndSendChanges() { } } } - /* - if (toUpdate.size() > 0 && this.behavior != null) { - behavior.writePluginData(-1, packetBuffer -> { - packetBuffer.writeVarInt(toUpdate.size()); - for (Tuple tuple : toUpdate) { - packetBuffer.writeVarInt(tuple.getFirst()); - packetBuffer.writeItemStack(tuple.getSecond()); - } - }); - } - */ modularUI.guiWidgets.values().forEach(Widget::detectAndSendChanges); } diff --git a/src/main/java/gregtech/common/items/MetaItem2.java b/src/main/java/gregtech/common/items/MetaItem2.java deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/src/main/java/gregtech/loaders/recipe/CraftingRecipeLoader.java b/src/main/java/gregtech/loaders/recipe/CraftingRecipeLoader.java index 67550c3f673..61db15f0142 100644 --- a/src/main/java/gregtech/loaders/recipe/CraftingRecipeLoader.java +++ b/src/main/java/gregtech/loaders/recipe/CraftingRecipeLoader.java @@ -25,7 +25,6 @@ import net.minecraftforge.oredict.OreIngredient; import static gregtech.api.unification.material.Materials.*; -import static gregtech.api.unification.ore.OrePrefix.plate; public class CraftingRecipeLoader { @@ -65,7 +64,7 @@ private static void loadCraftingRecipes() { ModHandler.addSmeltingRecipe(new UnificationEntry(OrePrefix.nugget, Materials.Iron), OreDictUnifier.get(OrePrefix.nugget, Materials.WroughtIron)); - ModHandler.addShapedRecipe("clipboard", MetaItems.CLIPBOARD.getStackForm(), " Sd", "BWR", "PPP", 'P', Items.PAPER, 'R', new UnificationEntry(OrePrefix.springSmall, Iron), 'B', new UnificationEntry(OrePrefix.bolt, Iron), 'S', new UnificationEntry(OrePrefix.screw, Iron), 'W', new UnificationEntry(plate, Wood)); + ModHandler.addShapedRecipe("clipboard", MetaItems.CLIPBOARD.getStackForm(), " Sd", "BWR", "PPP", 'P', Items.PAPER, 'R', new UnificationEntry(OrePrefix.springSmall, Iron), 'B', new UnificationEntry(OrePrefix.bolt, Iron), 'S', new UnificationEntry(OrePrefix.screw, Iron), 'W', new UnificationEntry(OrePrefix.plate, Wood)); for (MetaValueItem batteryItem : ToolRecipeHandler.batteryItems[0]) { ModHandler.addShapedEnergyTransferRecipe("scanner_" + batteryItem.unlocalizedName, MetaItems.SCANNER.getStackForm(), From 88a63c0abf852a1c4daf51934ee20d482d31b949 Mon Sep 17 00:00:00 2001 From: bruberu <80226372+bruberu@users.noreply.github.com> Date: Tue, 10 Aug 2021 21:57:59 -0500 Subject: [PATCH 32/42] Behaviour -> Behavior (as per Tech's request) --- ...{ClipboardBehaviour.java => ClipboardBehavior.java} | 2 +- .../metatileentities/MetaTileEntityClipboard.java | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) rename src/main/java/gregtech/common/items/behaviors/{ClipboardBehaviour.java => ClipboardBehavior.java} (99%) diff --git a/src/main/java/gregtech/common/items/behaviors/ClipboardBehaviour.java b/src/main/java/gregtech/common/items/behaviors/ClipboardBehavior.java similarity index 99% rename from src/main/java/gregtech/common/items/behaviors/ClipboardBehaviour.java rename to src/main/java/gregtech/common/items/behaviors/ClipboardBehavior.java index f079bb51bcf..ef9e290c8b2 100644 --- a/src/main/java/gregtech/common/items/behaviors/ClipboardBehaviour.java +++ b/src/main/java/gregtech/common/items/behaviors/ClipboardBehavior.java @@ -26,7 +26,7 @@ import static gregtech.common.blocks.MetaBlocks.MACHINE; import static gregtech.common.metatileentities.MetaTileEntities.CLIPBOARD_TILE; -public class ClipboardBehaviour implements IItemBehaviour, ItemUIFactory { +public class ClipboardBehavior implements IItemBehaviour, ItemUIFactory { public static final int MAX_PAGES = 25; @Override diff --git a/src/main/java/gregtech/common/metatileentities/MetaTileEntityClipboard.java b/src/main/java/gregtech/common/metatileentities/MetaTileEntityClipboard.java index 31f17b96d90..6b5f1e93b4c 100644 --- a/src/main/java/gregtech/common/metatileentities/MetaTileEntityClipboard.java +++ b/src/main/java/gregtech/common/metatileentities/MetaTileEntityClipboard.java @@ -19,7 +19,7 @@ import gregtech.api.util.GTUtility; import gregtech.api.util.GregFakePlayer; import gregtech.common.gui.impl.FakeModularUIContainerClipboard; -import gregtech.common.items.behaviors.ClipboardBehaviour; +import gregtech.common.items.behaviors.ClipboardBehavior; import net.minecraft.block.Block; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.texture.TextureAtlasSprite; @@ -123,14 +123,14 @@ public MetaTileEntity createMetaTileEntity(MetaTileEntityHolder holder) { public ModularUI createUI(EntityPlayer entityPlayer) { if (getClipboard().isItemEqual(CLIPBOARD.getStackForm())) { List behaviours = ((MetaItem) getClipboard().getItem()).getBehaviours(getClipboard()); - Optional clipboardBehaviour = behaviours.stream().filter((x) -> x instanceof ClipboardBehaviour).findFirst(); + Optional clipboardBehaviour = behaviours.stream().filter((x) -> x instanceof ClipboardBehavior).findFirst(); if (!clipboardBehaviour.isPresent()) return null; - if (clipboardBehaviour.get() instanceof ClipboardBehaviour) { + if (clipboardBehaviour.get() instanceof ClipboardBehavior) { if(entityPlayer instanceof GregFakePlayer) { - return ((ClipboardBehaviour) clipboardBehaviour.get()).createMTEUI(new PlayerInventoryHolder(entityPlayer, entityPlayer.getActiveHand(), getClipboard()), entityPlayer); + return ((ClipboardBehavior) clipboardBehaviour.get()).createMTEUI(new PlayerInventoryHolder(entityPlayer, entityPlayer.getActiveHand(), getClipboard()), entityPlayer); } else { - return ((ClipboardBehaviour) clipboardBehaviour.get()).createUI(new PlayerInventoryHolder(entityPlayer, entityPlayer.getActiveHand(), getClipboard()), entityPlayer); + return ((ClipboardBehavior) clipboardBehaviour.get()).createUI(new PlayerInventoryHolder(entityPlayer, entityPlayer.getActiveHand(), getClipboard()), entityPlayer); } } } From 610f2a1fa6c3de2674ca75f0e94e89b249b5728b Mon Sep 17 00:00:00 2001 From: bruberu <80226372+bruberu@users.noreply.github.com> Date: Tue, 10 Aug 2021 22:26:15 -0500 Subject: [PATCH 33/42] Implement @Tech22's suggestions --- src/main/java/gregtech/api/cover/ICoverable.java | 2 +- src/main/java/gregtech/api/gui/GuiTextures.java | 6 +++--- src/main/java/gregtech/api/render/Textures.java | 8 ++++---- .../common/metatileentities/MetaTileEntities.java | 2 +- .../common/metatileentities/MetaTileEntityClipboard.java | 2 +- .../gregtech/common/render/WrenchOverlayRenderer.java | 2 +- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/main/java/gregtech/api/cover/ICoverable.java b/src/main/java/gregtech/api/cover/ICoverable.java index c4dc61a4b32..0157a00c632 100644 --- a/src/main/java/gregtech/api/cover/ICoverable.java +++ b/src/main/java/gregtech/api/cover/ICoverable.java @@ -199,7 +199,7 @@ static Cuboid6 getCoverPlateBox(EnumFacing side, double plateThickness) { } } - public default boolean canRenderWrenchOverlay() { + public default boolean canRenderMachineGrid() { return true; } } diff --git a/src/main/java/gregtech/api/gui/GuiTextures.java b/src/main/java/gregtech/api/gui/GuiTextures.java index 379e6ee2fa0..786e8d11415 100644 --- a/src/main/java/gregtech/api/gui/GuiTextures.java +++ b/src/main/java/gregtech/api/gui/GuiTextures.java @@ -14,6 +14,7 @@ public class GuiTextures { public static final TextureArea BORDERED_BACKGROUND = AdoptableTextureArea.fullImage("textures/gui/base/bordered_background.png", 195, 136, 4, 4); public static final TextureArea BOXED_BACKGROUND = AdoptableTextureArea.fullImage("textures/gui/base/boxed_background.png", 256, 174, 11, 11); + public static final TextureArea BLANK = AdoptableTextureArea.fullImage("textures/gui/base/blank.png", 1, 1, 0, 0); public static final TextureArea DISPLAY = TextureArea.fullImage("textures/gui/base/display.png"); public static final TextureArea FLUID_SLOT = AdoptableTextureArea.fullImage("textures/gui/base/fluid_slot.png", 18, 18, 1, 1); public static final TextureArea FLUID_TANK_BACKGROUND = TextureArea.fullImage("textures/gui/base/fluid_tank_background.png"); @@ -21,7 +22,6 @@ public class GuiTextures { public static final TextureArea SLOT = AdoptableTextureArea.fullImage("textures/gui/base/slot.png", 18, 18, 1, 1); public static final TextureArea SLOT_DARKENED = TextureArea.fullImage("textures/gui/base/darkened_slot.png"); - public static final TextureArea BLANK = AdoptableTextureArea.fullImage("textures/gui/base/blank.png", 1, 1, 0, 0); //FLUID & ITEM OUTPUT BUTTONS public static final TextureArea BLOCKS_INPUT = TextureArea.fullImage("textures/gui/widget/button_blocks_input.png"); @@ -33,16 +33,16 @@ public class GuiTextures { public static final TextureArea BUTTON_FILTER_NBT = TextureArea.fullImage("textures/gui/widget/button_filter_nbt.png"); public static final TextureArea BUTTON_FLUID_OUTPUT = TextureArea.fullImage("textures/gui/widget/button_fluid_output.png"); public static final TextureArea BUTTON_ITEM_OUTPUT = TextureArea.fullImage("textures/gui/widget/button_item_output.png"); - public static final TextureArea BUTTON_OVERCLOCK = TextureArea.fullImage("textures/gui/widget/button_overclock.png"); public static final TextureArea BUTTON_LEFT = TextureArea.fullImage("textures/gui/widget/left.png"); + public static final TextureArea BUTTON_OVERCLOCK = TextureArea.fullImage("textures/gui/widget/button_overclock.png"); public static final TextureArea BUTTON_RIGHT = TextureArea.fullImage("textures/gui/widget/right.png"); public static final TextureArea BUTTON_SWITCH_VIEW = TextureArea.fullImage("textures/gui/widget/button_switch_view.png"); + public static final TextureArea CLIPBOARD_CHECKBOX = TextureArea.fullImage("textures/gui/widget/clipboard_checkbox.png"); public static final TextureArea DISTRIBUTION_MODE = TextureArea.fullImage("textures/gui/widget/button_distribution_mode.png"); public static final TextureArea LOCK = TextureArea.fullImage("textures/gui/widget/lock.png"); public static final TextureArea SWITCH = TextureArea.fullImage("textures/gui/widget/switch.png"); public static final TextureArea SWITCH_HORIZONTAL = TextureArea.fullImage("textures/gui/widget/switch_horizontal.png"); public static final SizedTextureArea VANILLA_BUTTON = SizedTextureArea.fullImage("textures/gui/widget/vanilla_button.png", 200, 40); - public static final TextureArea CLIPBOARD_CHECKBOX = TextureArea.fullImage("textures/gui/widget/clipboard_checkbox.png"); //INDICATORS & ICONS public static final TextureArea INDICATOR_NO_ENERGY = TextureArea.fullImage("textures/gui/base/indicator_no_energy.png"); diff --git a/src/main/java/gregtech/api/render/Textures.java b/src/main/java/gregtech/api/render/Textures.java index f4943a5cd1b..0b4b55cf24d 100644 --- a/src/main/java/gregtech/api/render/Textures.java +++ b/src/main/java/gregtech/api/render/Textures.java @@ -29,13 +29,14 @@ public class Textures { private static final ThreadLocal blockFaces = ThreadLocal.withInitial(BlockFace::new); public static final List iconRegisters = new ArrayList<>(); - public static final SafeRenderer SAFE = new SafeRenderer("storage/safe"); + public static ClipboardRenderer CLIPBOARD_RENDERER = new ClipboardRenderer(); + public static final CrateRenderer WOODEN_CRATE = new CrateRenderer("storage/crates/wooden_crate"); + public static final CrateRenderer METAL_CRATE = new CrateRenderer("storage/crates/metal_crate"); public static final DrumRenderer WOODEN_DRUM = new DrumRenderer("storage/drums/wooden_drum"); public static final DrumRenderer DRUM = new DrumRenderer("storage/drums/drum"); + public static final SafeRenderer SAFE = new SafeRenderer("storage/safe"); public static final TankRenderer WOODEN_TANK = new TankRenderer("storage/tank/wooden"); public static final TankRenderer METAL_TANK = new TankRenderer("storage/tank/metal"); - public static final CrateRenderer WOODEN_CRATE = new CrateRenderer("storage/crates/wooden_crate"); - public static final CrateRenderer METAL_CRATE = new CrateRenderer("storage/crates/metal_crate"); public static final SimpleSidedCubeRenderer STEAM_CASING_BRONZE = new SimpleSidedCubeRenderer("casings/steam/bronze"); public static final SimpleSidedCubeRenderer STEAM_CASING_STEEL = new SimpleSidedCubeRenderer("casings/steam/steel"); public static final SimpleSidedCubeRenderer STEAM_BRICKED_CASING_BRONZE = new SimpleSidedCubeRenderer("casings/steam/bricked_bronze"); @@ -175,7 +176,6 @@ public class Textures { public static final SimpleOverlayRenderer STEAM_VENT_OVERLAY = new SimpleOverlayRenderer("overlay/machine/steam_vent"); public static final SimpleOverlayRenderer QUANTUM_TANK_OVERLAY = new SimpleOverlayRenderer("overlay/machine/overlay_qtank"); public static final SimpleOverlayRenderer QUANTUM_CHEST_OVERLAY = new SimpleOverlayRenderer("overlay/machine/overlay_qchest"); - public static ClipboardRenderer CLIPBOARD_RENDERER = new ClipboardRenderer(); static { for (int i = 0; i < VOLTAGE_CASINGS.length; i++) { diff --git a/src/main/java/gregtech/common/metatileentities/MetaTileEntities.java b/src/main/java/gregtech/common/metatileentities/MetaTileEntities.java index 9d508b20393..0c2dfbcebd3 100644 --- a/src/main/java/gregtech/common/metatileentities/MetaTileEntities.java +++ b/src/main/java/gregtech/common/metatileentities/MetaTileEntities.java @@ -658,7 +658,7 @@ public static void init() { STEAM_IMPORT_BUS = GregTechAPI.registerMetaTileEntity(1632, new MetaTileEntitySteamItemBus(gregtechId("steam_import_bus"), false)); STEAM_HATCH = GregTechAPI.registerMetaTileEntity(1633, new MetaTileEntitySteamHatch(gregtechId("steam_hatch"))); - CLIPBOARD_TILE = GregTechAPI.registerMetaTileEntity(1640, new MetaTileEntityClipboard(gregtechId("clipboard"))); + CLIPBOARD_TILE = GregTechAPI.registerMetaTileEntity(1636, new MetaTileEntityClipboard(gregtechId("clipboard"))); /* * FOR ADDON DEVELOPERS: diff --git a/src/main/java/gregtech/common/metatileentities/MetaTileEntityClipboard.java b/src/main/java/gregtech/common/metatileentities/MetaTileEntityClipboard.java index 6b5f1e93b4c..97a47227087 100644 --- a/src/main/java/gregtech/common/metatileentities/MetaTileEntityClipboard.java +++ b/src/main/java/gregtech/common/metatileentities/MetaTileEntityClipboard.java @@ -408,7 +408,7 @@ public boolean canPlaceCoverOnSide(EnumFacing side) { } @Override - public boolean canRenderWrenchOverlay() { + public boolean canRenderMachineGrid() { return false; } } diff --git a/src/main/java/gregtech/common/render/WrenchOverlayRenderer.java b/src/main/java/gregtech/common/render/WrenchOverlayRenderer.java index 357d438bf61..d8814a371fb 100644 --- a/src/main/java/gregtech/common/render/WrenchOverlayRenderer.java +++ b/src/main/java/gregtech/common/render/WrenchOverlayRenderer.java @@ -94,7 +94,7 @@ public static boolean useGridForRayTraceResult(RayTraceResult result) { public static boolean shouldDrawOverlayForItem(ItemStack itemStack, TileEntity tileEntity) { if (tileEntity instanceof ICoverable) { - if(!((ICoverable) tileEntity).canRenderWrenchOverlay()) + if(!((ICoverable) tileEntity).canRenderMachineGrid()) return false; } From ad8de610762799fdadf776e65b84bacfa97cdfdb Mon Sep 17 00:00:00 2001 From: bruberu <80226372+bruberu@users.noreply.github.com> Date: Wed, 11 Aug 2021 10:21:27 -0500 Subject: [PATCH 34/42] Continue transition to behavior --- src/main/java/gregtech/common/items/MetaItem1.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/gregtech/common/items/MetaItem1.java b/src/main/java/gregtech/common/items/MetaItem1.java index cf451080181..7d370f8ea07 100644 --- a/src/main/java/gregtech/common/items/MetaItem1.java +++ b/src/main/java/gregtech/common/items/MetaItem1.java @@ -373,7 +373,7 @@ public void registerSubItems() { NANO_SABER = addItem(463, "nano_saber").addComponents(ElectricStats.createElectricItem(4000000L, GTValues.HV)).addComponents(new NanoSaberBehavior()).setMaxStackSize(1); ENERGY_FIELD_PROJECTOR = addItem(464, "energy_field_projector").addComponents(ElectricStats.createElectricItem(16000000L, GTValues.EV)).setMaxStackSize(1); SCANNER = addItem(465, "scanner").addComponents(ElectricStats.createElectricItem(200_000L, GTValues.LV), new ScannerBehavior(50)); - CLIPBOARD = addItem(466, "clipboard").addComponents(new ClipboardBehaviour()).setMaxStackSize(1); + CLIPBOARD = addItem(466, "clipboard").addComponents(new ClipboardBehavior()).setMaxStackSize(1); // Misc Crafting Items: ID 491-515 ENERGIUM_DUST = addItem(491, "energium_dust"); From 5c54da4af5d8d836739bbfeba242a56e3debe81c Mon Sep 17 00:00:00 2001 From: bruberu <80226372+bruberu@users.noreply.github.com> Date: Wed, 11 Aug 2021 21:15:54 -0500 Subject: [PATCH 35/42] Apply all of Kila's suggestions that could be simply implemented --- .../java/gregtech/api/gui/widgets/TextFieldWidget.java | 7 +------ .../gregtech/api/items/gui/PlayerInventoryHolder.java | 8 +------- src/main/resources/assets/gregtech/lang/en_us.lang | 2 +- 3 files changed, 3 insertions(+), 14 deletions(-) diff --git a/src/main/java/gregtech/api/gui/widgets/TextFieldWidget.java b/src/main/java/gregtech/api/gui/widgets/TextFieldWidget.java index 666e5e62ca4..9264368b4ce 100644 --- a/src/main/java/gregtech/api/gui/widgets/TextFieldWidget.java +++ b/src/main/java/gregtech/api/gui/widgets/TextFieldWidget.java @@ -22,7 +22,6 @@ public class TextFieldWidget extends Widget { protected GuiTextField textField; protected int maxStringLength = 32; - protected int fontSize = 9; protected Predicate textValidator; protected final Supplier textSupplier; protected final Consumer textResponder; @@ -42,7 +41,7 @@ public TextFieldWidget(int xPosition, int yPosition, int width, int height, bool this.textResponder = textResponder; } - public TextFieldWidget(int xPosition, int yPosition, int width, int height, boolean enableBackground, Supplier textSupplier, Consumer textResponder, int maxStringLength, int fontSize) { + public TextFieldWidget(int xPosition, int yPosition, int width, int height, boolean enableBackground, Supplier textSupplier, Consumer textResponder, int maxStringLength) { super(new Position(xPosition, yPosition), new Size(width, height)); if (isClientSide()) { FontRenderer fontRenderer = Minecraft.getMinecraft().fontRenderer; @@ -51,7 +50,6 @@ public TextFieldWidget(int xPosition, int yPosition, int width, int height, bool this.textField.setEnableBackgroundDrawing(enableBackground); this.textField.setMaxStringLength(maxStringLength); this.maxStringLength = maxStringLength; - this.fontSize = fontSize; this.textField.setGuiResponder(MCGuiUtil.createTextFieldResponder(this::onTextChanged)); } this.textSupplier = textSupplier; @@ -81,10 +79,7 @@ protected void onSizeUpdate() { @Override public void drawInBackground(int mouseX, int mouseY, IRenderContext context) { super.drawInBackground(mouseX, mouseY, context); - FontRenderer fontRenderer = Minecraft.getMinecraft().fontRenderer; - fontRenderer.FONT_HEIGHT = fontSize; this.textField.drawTextBox(); - fontRenderer.FONT_HEIGHT = 9; } @Override diff --git a/src/main/java/gregtech/api/items/gui/PlayerInventoryHolder.java b/src/main/java/gregtech/api/items/gui/PlayerInventoryHolder.java index 28c3393db3d..6d093510b2b 100644 --- a/src/main/java/gregtech/api/items/gui/PlayerInventoryHolder.java +++ b/src/main/java/gregtech/api/items/gui/PlayerInventoryHolder.java @@ -17,7 +17,7 @@ public class PlayerInventoryHolder implements IUIHolder { /*package-local*/ ItemStack sampleItem; @SideOnly(Side.CLIENT) - public PlayerInventoryHolder(EntityPlayer player, EnumHand hand, ItemStack sampleItem) { + /*package-local*/ public PlayerInventoryHolder(EntityPlayer player, EnumHand hand, ItemStack sampleItem) { this.player = player; this.hand = hand; this.sampleItem = sampleItem; @@ -27,8 +27,6 @@ public PlayerInventoryHolder(EntityPlayer entityPlayer, EnumHand hand) { this.player = entityPlayer; this.hand = hand; this.sampleItem = player.getHeldItem(hand); - Preconditions.checkArgument(sampleItem.getItem() instanceof ItemUIFactory, - "Current Item should implement ItemUIFactory"); } public static void openHandItemUI(EntityPlayer player, EnumHand hand) { @@ -56,10 +54,6 @@ public boolean isRemote() { return player.getEntityWorld().isRemote; } - public ItemStack getSampleItem() { - return sampleItem; - } - public ItemStack getCurrentItem() { ItemStack itemStack = player.getHeldItem(hand); if (!ItemStack.areItemsEqual(sampleItem, itemStack)) diff --git a/src/main/resources/assets/gregtech/lang/en_us.lang b/src/main/resources/assets/gregtech/lang/en_us.lang index 9362c0f5548..5e228117688 100644 --- a/src/main/resources/assets/gregtech/lang/en_us.lang +++ b/src/main/resources/assets/gregtech/lang/en_us.lang @@ -830,7 +830,7 @@ metaitem.turbine_rotor.tooltip=Turbine Rotors for your power station metaitem.tool.magnifying_glass.name=%s Magnifying Glass metaitem.clipboard.name=Clipboard -metaitem.clipboard.tooltip=Can be written on (without any writing Instrument)\nRight-click on Wall to place, and Shift-Right-Click to remove +metaitem.clipboard.tooltip=Can be written on (without any writing Instrument). Right-click on Wall to place, and Shift-Right-Click to remove metaitem.drill.mode.three_cube=3x3x3 Cube metaitem.drill.mode.five_cube=5x5x5 Cube From 8f40c6b88df80ba07cb4778da105815adbfe7fc4 Mon Sep 17 00:00:00 2001 From: bruberu <80226372+bruberu@users.noreply.github.com> Date: Wed, 11 Aug 2021 21:17:44 -0500 Subject: [PATCH 36/42] Fix up ClipboardBehavior.java --- .../items/behaviors/ClipboardBehavior.java | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/main/java/gregtech/common/items/behaviors/ClipboardBehavior.java b/src/main/java/gregtech/common/items/behaviors/ClipboardBehavior.java index ef9e290c8b2..92a13e8565e 100644 --- a/src/main/java/gregtech/common/items/behaviors/ClipboardBehavior.java +++ b/src/main/java/gregtech/common/items/behaviors/ClipboardBehavior.java @@ -31,11 +31,11 @@ public class ClipboardBehavior implements IItemBehaviour, ItemUIFactory { @Override public ModularUI createUI(PlayerInventoryHolder holder, EntityPlayer entityPlayer) { - initNBT(holder.getSampleItem()); + initNBT(holder.getCurrentItem()); ModularUI.Builder builder = ModularUI.builder(GuiTextures.BACKGROUND, 170, 238); builder.widget(new TextFieldWidget(20, 10, 130, 13, true, - () -> getTitle(holder), (x) -> setTitle(holder, x), 23, 12) + () -> getTitle(holder), (x) -> setTitle(holder, x), 23) .setValidator((x) -> true)); for (int i = 0; i < 8; i++) { @@ -43,7 +43,7 @@ public ModularUI createUI(PlayerInventoryHolder holder, EntityPlayer entityPlaye builder.widget(new ImageCycleButtonWidget(5, 37 + 20 * i, 15, 15, GuiTextures.CLIPBOARD_CHECKBOX, 2, () -> getButtonState(holder, finalI), (x) -> toggleButton(holder, finalI))); builder.widget(new TextFieldWidget(21, 40 + 20 * i, 140, 10, true, - () -> getString(holder, finalI), (x) -> setString(holder, finalI, x), 23, 8) + () -> getString(holder, finalI), (x) -> setString(holder, finalI, x), 23) .setValidator((x) -> true)); } @@ -58,7 +58,7 @@ public ModularUI createUI(PlayerInventoryHolder holder, EntityPlayer entityPlaye } public ModularUI createMTEUI(PlayerInventoryHolder holder, EntityPlayer entityPlayer) { // So that people don't click on any text fields - initNBT(holder.getSampleItem()); + initNBT(holder.getCurrentItem()); ModularUI.Builder builder = ModularUI.builder(GuiTextures.BACKGROUND, 170, 238); builder.widget(new SimpleTextWidget(20, 10, "", 0x000000, () -> getTitle(holder), false)); @@ -125,7 +125,7 @@ private static void initNBT(ItemStack stack) { } private static void toggleButton(PlayerInventoryHolder holder, int pos) { - ItemStack stack = holder.getSampleItem(); + ItemStack stack = holder.getCurrentItem(); if (!MetaItems.CLIPBOARD.isItemEqual(stack)) throw new IllegalArgumentException("Given item stack is not a clipboard!"); NBTTagCompound tagCompound = getPageCompound(stack); @@ -137,7 +137,7 @@ private static void toggleButton(PlayerInventoryHolder holder, int pos) { } private static boolean getButtonState(PlayerInventoryHolder holder, int pos) { - ItemStack stack = holder.getSampleItem(); + ItemStack stack = holder.getCurrentItem(); if (!MetaItems.CLIPBOARD.isItemEqual(stack)) throw new IllegalArgumentException("Given item stack is not a clipboard!"); NBTTagCompound tagCompound = getPageCompound(stack); @@ -147,7 +147,7 @@ private static boolean getButtonState(PlayerInventoryHolder holder, int pos) { } private static void setString(PlayerInventoryHolder holder, int pos, String newString) { - ItemStack stack = holder.getSampleItem(); + ItemStack stack = holder.getCurrentItem(); if (!MetaItems.CLIPBOARD.isItemEqual(stack)) throw new IllegalArgumentException("Given item stack is not a clipboard!"); NBTTagCompound tagCompound = getPageCompound(stack); @@ -156,7 +156,7 @@ private static void setString(PlayerInventoryHolder holder, int pos, String newS } private static String getString(PlayerInventoryHolder holder, int pos) { - ItemStack stack = holder.getSampleItem(); + ItemStack stack = holder.getCurrentItem(); if (!MetaItems.CLIPBOARD.isItemEqual(stack)) throw new IllegalArgumentException("Given item stack is not a clipboard!"); NBTTagCompound tagCompound = getPageCompound(stack); @@ -164,7 +164,7 @@ private static String getString(PlayerInventoryHolder holder, int pos) { } private static void setTitle(PlayerInventoryHolder holder, String newString) { - ItemStack stack = holder.getSampleItem(); + ItemStack stack = holder.getCurrentItem(); if (!MetaItems.CLIPBOARD.isItemEqual(stack)) throw new IllegalArgumentException("Given item stack is not a clipboard!"); NBTTagCompound tagCompound = getPageCompound(stack); @@ -174,7 +174,7 @@ private static void setTitle(PlayerInventoryHolder holder, String newString) { } private static String getTitle(PlayerInventoryHolder holder) { - ItemStack stack = holder.getSampleItem(); + ItemStack stack = holder.getCurrentItem(); if (!MetaItems.CLIPBOARD.isItemEqual(stack)) throw new IllegalArgumentException("Given item stack is not a clipboard!"); NBTTagCompound tagCompound = getPageCompound(stack); @@ -182,7 +182,7 @@ private static String getTitle(PlayerInventoryHolder holder) { } private static int getPageNum(PlayerInventoryHolder holder) { - ItemStack stack = holder.getSampleItem(); + ItemStack stack = holder.getCurrentItem(); if (!MetaItems.CLIPBOARD.isItemEqual(stack)) throw new IllegalArgumentException("Given item stack is not a clipboard!"); NBTTagCompound tagCompound = stack.getTagCompound(); @@ -190,7 +190,7 @@ private static int getPageNum(PlayerInventoryHolder holder) { } private static void incrPageNum(PlayerInventoryHolder holder, int increment) { - ItemStack stack = holder.getSampleItem(); + ItemStack stack = holder.getCurrentItem(); if (!MetaItems.CLIPBOARD.isItemEqual(stack)) throw new IllegalArgumentException("Given item stack is not a clipboard!"); NBTTagCompound tagCompound = stack.getTagCompound(); From 4c19bd15dfb66419573fae9b44b0fc20a39cb6ba Mon Sep 17 00:00:00 2001 From: bruberu <80226372+bruberu@users.noreply.github.com> Date: Wed, 11 Aug 2021 21:45:50 -0500 Subject: [PATCH 37/42] Fix up MetaTileEntityClipboard.java --- .../common/metatileentities/MetaTileEntityClipboard.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/gregtech/common/metatileentities/MetaTileEntityClipboard.java b/src/main/java/gregtech/common/metatileentities/MetaTileEntityClipboard.java index 97a47227087..b41373013fd 100644 --- a/src/main/java/gregtech/common/metatileentities/MetaTileEntityClipboard.java +++ b/src/main/java/gregtech/common/metatileentities/MetaTileEntityClipboard.java @@ -127,10 +127,12 @@ public ModularUI createUI(EntityPlayer entityPlayer) { if (!clipboardBehaviour.isPresent()) return null; if (clipboardBehaviour.get() instanceof ClipboardBehavior) { + PlayerInventoryHolder holder = new PlayerInventoryHolder(entityPlayer, entityPlayer.getActiveHand()); + holder.setCurrentItem(this.getClipboard()); if(entityPlayer instanceof GregFakePlayer) { - return ((ClipboardBehavior) clipboardBehaviour.get()).createMTEUI(new PlayerInventoryHolder(entityPlayer, entityPlayer.getActiveHand(), getClipboard()), entityPlayer); + return ((ClipboardBehavior) clipboardBehaviour.get()).createMTEUI(holder, entityPlayer); } else { - return ((ClipboardBehavior) clipboardBehaviour.get()).createUI(new PlayerInventoryHolder(entityPlayer, entityPlayer.getActiveHand(), getClipboard()), entityPlayer); + return ((ClipboardBehavior) clipboardBehaviour.get()).createUI(holder, entityPlayer); } } } From 088e6be56cabee820a5c19060ea8d8d658a2dd6a Mon Sep 17 00:00:00 2001 From: bruberu <80226372+bruberu@users.noreply.github.com> Date: Thu, 12 Aug 2021 10:01:51 -0500 Subject: [PATCH 38/42] Continue removing unnecessary checks from PlayerInventoryHolder.java --- .../api/items/gui/PlayerInventoryHolder.java | 5 ----- .../java/gregtech/api/util/GregFakePlayer.java | 4 +++- .../MetaTileEntityClipboard.java | 14 +++++++------- .../textures/gui/widget/clipboard_button.png | Bin 0 -> 1070 bytes .../textures/gui/widget/clipboard_text_box.png | Bin 0 -> 166 bytes 5 files changed, 10 insertions(+), 13 deletions(-) create mode 100644 src/main/resources/assets/gregtech/textures/gui/widget/clipboard_button.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/widget/clipboard_text_box.png diff --git a/src/main/java/gregtech/api/items/gui/PlayerInventoryHolder.java b/src/main/java/gregtech/api/items/gui/PlayerInventoryHolder.java index 6d093510b2b..ac15eb23795 100644 --- a/src/main/java/gregtech/api/items/gui/PlayerInventoryHolder.java +++ b/src/main/java/gregtech/api/items/gui/PlayerInventoryHolder.java @@ -66,11 +66,6 @@ public ItemStack getCurrentItem() { * will also update sample item to this item */ public void setCurrentItem(ItemStack item) { - ItemStack itemStack = player.getHeldItem(hand); - if (!ItemStack.areItemsEqual(sampleItem, itemStack)) - return; - Preconditions.checkArgument(item.getItem() instanceof ItemUIFactory, - "Current Item should implement ItemUIFactory"); this.sampleItem = item; player.setHeldItem(hand, item); } diff --git a/src/main/java/gregtech/api/util/GregFakePlayer.java b/src/main/java/gregtech/api/util/GregFakePlayer.java index 572899ad447..6c534956679 100644 --- a/src/main/java/gregtech/api/util/GregFakePlayer.java +++ b/src/main/java/gregtech/api/util/GregFakePlayer.java @@ -3,6 +3,7 @@ import com.mojang.authlib.GameProfile; import net.minecraft.entity.Entity; import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; import net.minecraft.server.MinecraftServer; import net.minecraft.stats.StatBase; import net.minecraft.util.DamageSource; @@ -102,5 +103,6 @@ public MinecraftServer getServer() { return FMLCommonHandler.instance().getMinecraftServerInstance(); } - + @Override + protected void playEquipSound(ItemStack stack) { } } diff --git a/src/main/java/gregtech/common/metatileentities/MetaTileEntityClipboard.java b/src/main/java/gregtech/common/metatileentities/MetaTileEntityClipboard.java index b41373013fd..bc899d33161 100644 --- a/src/main/java/gregtech/common/metatileentities/MetaTileEntityClipboard.java +++ b/src/main/java/gregtech/common/metatileentities/MetaTileEntityClipboard.java @@ -7,6 +7,7 @@ import codechicken.lib.vec.Cuboid6; import codechicken.lib.vec.Matrix4; import codechicken.lib.vec.Vector3; +import gregtech.api.block.BlockCustomParticle; import gregtech.api.gui.ModularUI; import gregtech.api.gui.Widget; import gregtech.api.gui.impl.FakeModularGui; @@ -55,7 +56,6 @@ public class MetaTileEntityClipboard extends MetaTileEntity implements IRenderMe public FakeModularGui guiCache; public FakeModularUIContainerClipboard guiContainerCache; private static final Cuboid6 pageBox = new Cuboid6(3 / 16.0, 0.25 / 16.0, 0.25 / 16.0, 13 / 16.0, 14.25 / 16.0, 0.3 / 16.0); - private boolean isClientReceivingUpdates = false; private static final int RENDER_PASS_NORMAL = 0; private static final NBTBase NO_CLIPBOARD_SIG = new NBTTagInt(0); @@ -72,7 +72,7 @@ public void update() { if (guiCache != null) guiCache.updateScreen(); } else { - if (!isClientReceivingUpdates && getOffsetTimer() % 20 == 0) + if (getOffsetTimer() % 20 == 0) createFakeGui(); if (guiContainerCache != null) guiContainerCache.detectAndSendChanges(); @@ -127,9 +127,9 @@ public ModularUI createUI(EntityPlayer entityPlayer) { if (!clipboardBehaviour.isPresent()) return null; if (clipboardBehaviour.get() instanceof ClipboardBehavior) { - PlayerInventoryHolder holder = new PlayerInventoryHolder(entityPlayer, entityPlayer.getActiveHand()); + PlayerInventoryHolder holder = new PlayerInventoryHolder(new GregFakePlayer(entityPlayer.world), EnumHand.MAIN_HAND); // We can't have this actually set the player's hand holder.setCurrentItem(this.getClipboard()); - if(entityPlayer instanceof GregFakePlayer) { + if(entityPlayer instanceof GregFakePlayer) { // This is how to tell if this is being called in-world or not return ((ClipboardBehavior) clipboardBehaviour.get()).createMTEUI(holder, entityPlayer); } else { return ((ClipboardBehavior) clipboardBehaviour.get()).createUI(holder, entityPlayer); @@ -143,6 +143,7 @@ public void createFakeGui() { // Basically just the original function from the PluginBehavior, but with a lot of now useless stuff stripped out. try { GregFakePlayer fakePlayer = new GregFakePlayer(this.getWorld()); + fakePlayer.setHeldItem(EnumHand.MAIN_HAND, this.getClipboard()); ModularUI ui = this.createUI(fakePlayer); ModularUI.Builder builder = new ModularUI.Builder(ui.backgroundPath, ui.getWidth(), ui.getHeight()); @@ -205,10 +206,10 @@ public boolean onRightClick(EntityPlayer playerIn, EnumHand hand, EnumFacing fac } else { BlockPos pos = this.getPos(); // Saving this for later so it doesn't get mangled World world = this.getWorld(); // Same here + NonNullList drops = NonNullList.create(); getDrops(drops, playerIn); - world.playEvent(2001, pos, Block.getStateId(world.getBlockState(pos))); Block.spawnAsEntity(playerIn.world, this.getPos(), drops.get(0)); this.dropAllCovers(); this.onRemoval(); @@ -275,7 +276,7 @@ private double[] handleRayTraceResult(CuboidRayTraceResult rayTraceResult, EnumF x = 1 - x; } } else { - x = dX; + x = 1 - dX; if (rayTraceResult.sideHit.getXOffset() < 0 || rayTraceResult.sideHit.getZOffset() > 0) { x = 1 - x; } @@ -342,7 +343,6 @@ public void receiveInitialSyncData(PacketBuffer buf) { @Override public void receiveCustomData(int dataId, PacketBuffer buf) { super.receiveCustomData(dataId, buf); - isClientReceivingUpdates = true; if (dataId == 0) { int windowID = buf.readVarInt(); int widgetID = buf.readVarInt(); diff --git a/src/main/resources/assets/gregtech/textures/gui/widget/clipboard_button.png b/src/main/resources/assets/gregtech/textures/gui/widget/clipboard_button.png new file mode 100644 index 0000000000000000000000000000000000000000..09ab41fb475f10a7cbe741cac57766488d06bb03 GIT binary patch literal 1070 zcmV+}1kwA6P)u*#=7{~Gc#rOu2?l}ivsPwv>-OkKX5EBv`xfEL3y7a=WG_@(nO;8k}(MAm#HE1-^ zL=%7J)cDNFboQK?-RZM0*cYEykmr}(Lg1TohTfVukA4_>bL4%uEKaU~lNoMZg`{QnPJ_=6eAk0>kq-n469|- z8PV{hS_UUGESE6Jh=wQR5;)QD`1B$;nc?OYj5DI)vE~(UGQ*7pj4`6&(Z)PDnPD-H zQARX8A})iI8J@a?5k@q8qJ9aS3d3_aQRhR$?@V3$YQ*5GP#SiXqQ0&XgX^{#wn|a0Ys6%iC=J`C zC|4C?vhSN=s}!eK6k@VVl!on6Y_=6*vhUNdU5brmg_!L7X4oo4v8WJ}U7|GXD#fV< zg&177&9I{s>z5T`a8)P`cPhonIf-6$x@(3@N^#)^i}&5-tMk|51(5!Tvd0^z7z;ibkKSED174SQKC@AzE8uhqI*!2xbNX!O`?qJwi$LjTfAG7$ldXhb3-!x;`u`-)g0wu}|Tx4@<0h@VQ09A*I(Io`y@v ojl%HY+2Y~85=&q8YgLQ?0taDr`>VTCp#T5?07*qoM6N<$f+^t*MF0Q* literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/widget/clipboard_text_box.png b/src/main/resources/assets/gregtech/textures/gui/widget/clipboard_text_box.png new file mode 100644 index 0000000000000000000000000000000000000000..fb5502dbc9c4e48e7e5ffaa324f19f49510309d0 GIT binary patch literal 166 zcmeAS@N?(olHy`uVBq!ia0vp^{6H+n!3HEh$GDULDaPU;cPEB*=VV?2ISHOFjv*Gk z$vN+$KF(+4|IvTWDd_AWeT5c({kQ|4{@cfOXD*-FnKO6FtuswRHA`;$Y>Q(PW9xF7 zEtDR-V0zMQ%}>TZ6Bu%r=~VJvWsq(>IeF2chD}Ks9%6g* Date: Thu, 12 Aug 2021 15:50:17 -0500 Subject: [PATCH 39/42] Add Max's textures! --- .../java/gregtech/api/gui/GuiTextures.java | 3 +- .../gregtech/api/gui/impl/FakeModularGui.java | 3 ++ .../api/gui/widgets/ImageTextFieldWidget.java | 33 +++++++++++++ .../items/behaviors/ClipboardBehavior.java | 45 ++++++++++-------- .../textures/gui/widget/clipboard_button.png | Bin 1070 -> 7214 bytes .../gui/widget/clipboard_text_box.png | Bin 166 -> 5637 bytes 6 files changed, 62 insertions(+), 22 deletions(-) create mode 100644 src/main/java/gregtech/api/gui/widgets/ImageTextFieldWidget.java diff --git a/src/main/java/gregtech/api/gui/GuiTextures.java b/src/main/java/gregtech/api/gui/GuiTextures.java index 786e8d11415..664bd29b4bc 100644 --- a/src/main/java/gregtech/api/gui/GuiTextures.java +++ b/src/main/java/gregtech/api/gui/GuiTextures.java @@ -37,7 +37,8 @@ public class GuiTextures { public static final TextureArea BUTTON_OVERCLOCK = TextureArea.fullImage("textures/gui/widget/button_overclock.png"); public static final TextureArea BUTTON_RIGHT = TextureArea.fullImage("textures/gui/widget/right.png"); public static final TextureArea BUTTON_SWITCH_VIEW = TextureArea.fullImage("textures/gui/widget/button_switch_view.png"); - public static final TextureArea CLIPBOARD_CHECKBOX = TextureArea.fullImage("textures/gui/widget/clipboard_checkbox.png"); + public static final TextureArea CLIPBOARD_BUTTON = TextureArea.fullImage("textures/gui/widget/clipboard_button.png"); + public static final SizedTextureArea CLIPBOARD_TEXT_BOX = AdoptableTextureArea.fullImage("textures/gui/widget/clipboard_text_box.png", 9, 18, 1, 1); public static final TextureArea DISTRIBUTION_MODE = TextureArea.fullImage("textures/gui/widget/button_distribution_mode.png"); public static final TextureArea LOCK = TextureArea.fullImage("textures/gui/widget/lock.png"); public static final TextureArea SWITCH = TextureArea.fullImage("textures/gui/widget/switch.png"); diff --git a/src/main/java/gregtech/api/gui/impl/FakeModularGui.java b/src/main/java/gregtech/api/gui/impl/FakeModularGui.java index a2e6ae07620..84952e8b86d 100644 --- a/src/main/java/gregtech/api/gui/impl/FakeModularGui.java +++ b/src/main/java/gregtech/api/gui/impl/FakeModularGui.java @@ -19,6 +19,8 @@ import java.util.List; +import static gregtech.api.gui.impl.ModularUIGui.*; + @SideOnly(Side.CLIENT) public class FakeModularGui implements IRenderContext { public final ModularUI modularUI; @@ -98,6 +100,7 @@ protected List getItemToolTip(ItemStack itemStack) { } public void drawGuiContainerBackgroundLayer(float partialTicks, int mouseX, int mouseY) { + GlStateManager.color(rColorForOverlay, gColorForOverlay, bColorForOverlay, 1.0F); modularUI.backgroundPath.draw(0, 0, modularUI.getWidth(), modularUI.getHeight()); for (Widget widget : modularUI.guiWidgets.values()) { GlStateManager.pushMatrix(); diff --git a/src/main/java/gregtech/api/gui/widgets/ImageTextFieldWidget.java b/src/main/java/gregtech/api/gui/widgets/ImageTextFieldWidget.java new file mode 100644 index 00000000000..5b16a980ddf --- /dev/null +++ b/src/main/java/gregtech/api/gui/widgets/ImageTextFieldWidget.java @@ -0,0 +1,33 @@ +package gregtech.api.gui.widgets; + +import gregtech.api.gui.IRenderContext; +import gregtech.api.gui.resources.SizedTextureArea; + +import java.util.function.Consumer; +import java.util.function.Supplier; + +public class ImageTextFieldWidget extends TextFieldWidget { + SizedTextureArea textureArea; + + public ImageTextFieldWidget(int xPosition, int yPosition, int width, int height, SizedTextureArea textureArea, Supplier textSupplier, Consumer textResponder) { + super(xPosition, yPosition, width, height, false, textSupplier, textResponder); + this.textureArea = textureArea; + } + + public ImageTextFieldWidget(int xPosition, int yPosition, int width, int height, SizedTextureArea textureArea, Supplier textSupplier, Consumer textResponder, int maxStringLength) { + super(xPosition, yPosition, width, height, false, textSupplier, textResponder, maxStringLength); + this.textureArea = textureArea; + } + + public ImageTextFieldWidget(int xPosition, int yPosition, int width, int height, SizedTextureArea textureArea, Supplier textSupplier, Consumer textResponder, int maxStringLength, int color) { + this(xPosition, yPosition, width, height, textureArea, textSupplier, textResponder, maxStringLength); + this.textField.setTextColor(color); + } + + + @Override + public void drawInBackground(int mouseX, int mouseY, IRenderContext context) { + this.textureArea.drawHorizontalCutArea(this.getPosition().x - 2, this.getPosition().y - 2, this.getSize().width, this.getSize().height); + super.drawInBackground(mouseX, mouseY, context); + } +} diff --git a/src/main/java/gregtech/common/items/behaviors/ClipboardBehavior.java b/src/main/java/gregtech/common/items/behaviors/ClipboardBehavior.java index 92a13e8565e..e1f1daf3d25 100644 --- a/src/main/java/gregtech/common/items/behaviors/ClipboardBehavior.java +++ b/src/main/java/gregtech/common/items/behaviors/ClipboardBehavior.java @@ -34,16 +34,16 @@ public ModularUI createUI(PlayerInventoryHolder holder, EntityPlayer entityPlaye initNBT(holder.getCurrentItem()); ModularUI.Builder builder = ModularUI.builder(GuiTextures.BACKGROUND, 170, 238); - builder.widget(new TextFieldWidget(20, 10, 130, 13, true, - () -> getTitle(holder), (x) -> setTitle(holder, x), 23) + builder.widget(new ImageTextFieldWidget(20, 10, 130, 12, GuiTextures.CLIPBOARD_TEXT_BOX, + () -> getTitle(holder), (x) -> setTitle(holder, x), 23, 0xFFFFFF) .setValidator((x) -> true)); for (int i = 0; i < 8; i++) { int finalI = i; - builder.widget(new ImageCycleButtonWidget(5, 37 + 20 * i, 15, 15, GuiTextures.CLIPBOARD_CHECKBOX, 2, - () -> getButtonState(holder, finalI), (x) -> toggleButton(holder, finalI))); - builder.widget(new TextFieldWidget(21, 40 + 20 * i, 140, 10, true, - () -> getString(holder, finalI), (x) -> setString(holder, finalI, x), 23) + builder.widget(new ImageCycleButtonWidget(6, 37 + 20 * i, 15, 15, GuiTextures.CLIPBOARD_BUTTON, 4, + () -> getButtonState(holder, finalI), (x) -> setButton(holder, finalI, x))); + builder.widget(new ImageTextFieldWidget(24, 40 + 20 * i, 140, 12, GuiTextures.CLIPBOARD_TEXT_BOX, + () -> getString(holder, finalI), (x) -> setString(holder, finalI, x), 23, 0xFFFFFF) .setValidator((x) -> true)); } @@ -51,7 +51,7 @@ public ModularUI createUI(PlayerInventoryHolder holder, EntityPlayer entityPlaye .setButtonTexture(GuiTextures.BUTTON_LEFT)); builder.widget(new ClickButtonWidget(124, 200, 16, 16, "", (x) -> incrPageNum(holder, 1)) .setButtonTexture(GuiTextures.BUTTON_RIGHT)); - builder.widget(new SimpleTextWidget(85, 208, "", 0x000000, + builder.widget(new SimpleTextWidget(85, 208, "", 0xFFFFFF, () -> (getPageNum(holder) + 1) + " / " + MAX_PAGES)); return builder.build(holder, entityPlayer); @@ -61,23 +61,23 @@ public ModularUI createMTEUI(PlayerInventoryHolder holder, EntityPlayer entityPl initNBT(holder.getCurrentItem()); ModularUI.Builder builder = ModularUI.builder(GuiTextures.BACKGROUND, 170, 238); - builder.widget(new SimpleTextWidget(20, 10, "", 0x000000, () -> getTitle(holder), false)); - builder.image(20, 19, 130, 4, GuiTextures.BLANK); // To create an underline + builder.image(18, 8, 130, 14, GuiTextures.CLIPBOARD_TEXT_BOX); + builder.widget(new SimpleTextWidget(20, 10, "", 0xFFFFFF, () -> getTitle(holder), false)); for (int i = 0; i < 8; i++) { int finalI = i; - builder.widget(new ImageCycleButtonWidget(5, 37 + 20 * i, 15, 15, GuiTextures.CLIPBOARD_CHECKBOX, 2, - () -> getButtonState(holder, finalI), (x) -> toggleButton(holder, finalI))); - builder.widget(new SimpleTextWidget(21, 40 + 20 * i, "", 0x000000, () -> getString(holder, finalI), false)); - builder.image(21, 49 + 20 * i, 140, 2, GuiTextures.BLANK); // To create an underline + builder.widget(new ImageCycleButtonWidget(6, 37 + 20 * i, 15, 15, GuiTextures.CLIPBOARD_BUTTON, 4, + () -> getButtonState(holder, finalI), (x) -> setButton(holder, finalI, x))); + builder.image(22, 38 + 20 * i, 140, 12, GuiTextures.CLIPBOARD_TEXT_BOX); + builder.widget(new SimpleTextWidget(24, 40 + 20 * i, "", 0xFFFFFF, () -> getString(holder, finalI), false)); } builder.widget(new ClickButtonWidget(30, 200, 16, 16, "", (x) -> incrPageNum(holder, -1)) .setButtonTexture(GuiTextures.BUTTON_LEFT)); builder.widget(new ClickButtonWidget(124, 200, 16, 16, "", (x) -> incrPageNum(holder, 1)) .setButtonTexture(GuiTextures.BUTTON_RIGHT)); - builder.widget(new SimpleTextWidget(85, 208, "", 0x000000, + builder.widget(new SimpleTextWidget(85, 208, "", 0xFFFFFF, () -> (getPageNum(holder) + 1) + " / " + MAX_PAGES)); return builder.build(holder, entityPlayer); @@ -111,7 +111,7 @@ private static void initNBT(ItemStack stack) { NBTTagCompound pageCompound = new NBTTagCompound(); pageCompound.setShort("ButStat", (short) 0); - pageCompound.setString("PageTitle", ""); + pageCompound.setString("Title", ""); for (int i = 0; i < 8; i++) { pageCompound.setString("Task" + i, ""); } @@ -124,26 +124,29 @@ private static void initNBT(ItemStack stack) { } } - private static void toggleButton(PlayerInventoryHolder holder, int pos) { + private static void setButton(PlayerInventoryHolder holder, int pos, int newState) { ItemStack stack = holder.getCurrentItem(); if (!MetaItems.CLIPBOARD.isItemEqual(stack)) throw new IllegalArgumentException("Given item stack is not a clipboard!"); NBTTagCompound tagCompound = getPageCompound(stack); short buttonState; - buttonState = tagCompound.getByte("ButStat"); - buttonState ^= 1 << pos; + buttonState = tagCompound.getShort("ButStat"); + + short clearedState = (short) (buttonState & ~(3 << (pos * 2))); // Clear out the desired slot + buttonState = (short) (clearedState | (newState << (pos * 2))); // And add the new state back in + tagCompound.setShort("ButStat", buttonState); setPageCompound(stack, tagCompound); } - private static boolean getButtonState(PlayerInventoryHolder holder, int pos) { + private static int getButtonState(PlayerInventoryHolder holder, int pos) { ItemStack stack = holder.getCurrentItem(); if (!MetaItems.CLIPBOARD.isItemEqual(stack)) throw new IllegalArgumentException("Given item stack is not a clipboard!"); NBTTagCompound tagCompound = getPageCompound(stack); - short buttonState = 0; + short buttonState; buttonState = tagCompound.getShort("ButStat"); - return ((buttonState >> pos) & 1) != 0; + return ((buttonState >> pos * 2) & 3); } private static void setString(PlayerInventoryHolder holder, int pos, String newString) { diff --git a/src/main/resources/assets/gregtech/textures/gui/widget/clipboard_button.png b/src/main/resources/assets/gregtech/textures/gui/widget/clipboard_button.png index 09ab41fb475f10a7cbe741cac57766488d06bb03..cc5d98d8aaa2ead5951d4d778c2452c2da7744c2 100644 GIT binary patch literal 7214 zcmeHKc{r5o`yV>lWlcym1|i0njhV4!%~*;dTcKIrVZzLq8OB;Fm909JBo#@rg`;Fo zB}`gnYf~IiN~AhjlKQ?wr}X=t-}(N|b^X5o<+{eqb3dQ^bKlSBx$ozF-ekA+>tvCE7nHQ`5RtUIBV85xO>zkKNn-#(tI zZ+En^tCutJiR28AWENlEK1&eKDSJO_b|7Rbl#g14fVnnp91~=%n#~#g9eXAIW$(+! zYd;{}RC5r1F=>I9Wt88fX4*$yUb*O^V6EbtWxpfWUOqa+Eg6cJr1sqxOja+SGBeBn z$e5^pv2!v5b)dOMC+UTT&Qr0Z*D;Uu@V=i`0(`vfyvhPsi=|i9H z7B-AECcvhdd`uhxeYwo4N_@8CvueA)(YE7i1oNQJ!3RcL%H(t(e>t)734SKPe}mf5 z=YrGO&b4F1IG@VRIl%s=z*@xpd${6Vmz1s_&DqAj)o$}kh7!pqcdyb!#7Q!Rl47P( zhFqU;zG{t56>c$IoEVv?l#20%ssf_r?dpM5i6KuTT}^F)fu+N0i*_x}+j*gLd-x~L zDQ?<3&8e6feKku>bxGv4UoW69MJe1lyeON;*VlwK>xsk;+de~gPOus0&EkE7Q z@8!m=#eQ7)#kxmZSrw84h4AW*ts$lS)uU;>({-J>lL~v&FuXx`hZSLeNXFB%2=5Iq z)IFpJhPT=1dIbR8-CliU+x(MNV+}XU>PNSodUWvc{_MCLMFl56+rVoKUN==g%gIy8 zE^Lw3AMpt&e9O?ktGTl+S)C4bXo9?@NMt6c(Hr-qpGFVMp!;C%xe5l|SA4I^FS=T3 z+ocrnV0L$}IMXP9`|eF~uop6QUqtai?X#k_Z)#=}9-R+GU#gMTl(yv-FKc3bsI?i1 zenIfQ+ECZ0K8)5L>U9{=+c(+JWxnTd)uSSV6)u7HcV*0x_GW?gUuJ#E(jp^q=t*<$ zLrtZFv6xI80Ab@hF$V)7zf#@U0Dc7;x_&~iz~LmhSu8(n>(L*4(V=a@8Wx^nT% zZ?2OPv3F$;R}UwQ$+(%V4^%B7$vtZuKGXUvA=OZY9J!*UQn|yVwxTG4B39G2-oHBI zZu3ro0tDw}b%`N~3$|TlI?cnW zFuILRd6X890=Bny#H~=js%3sT&s$1=tB;GWDm>HPWN-a^IP;NV2KHoMTut18KVYAJr*~y3PWc2S-_5uF3nClCyeL!k%$ld}hzAz9yR2 zzQ(Sft<06q52G)OJuc!F@42>T{T6E}t2H92p6Rycwim-iap|^C_$Ilj#@R()F(fkSX>;ET|&8_H*6@LucppjTfY1jAtIcdU~8&^scl8+E2O$}VfR8^ zlG2N&{fuTvQFlL%Xg{)!*S2eOS1dJ7rQa|#DMKGBYdR^hh+*i`w{D9;@eP$Emm~X} z{dCW*c^xm`tZ^+@-CChaf2F~72-I-`*EL={)3~f+$7;na{=2N&9s~EWV-MKVPev7n zbUv2G;k`aw46BqgfSq5qMOH@Pb}I^sO80uzaO9j%-jcJiY6e5T$m1ug-Ww{SkC&PX zvU?uwJ$FqX<%An7=+@KGmvx_zHKu9%xFqXdIP7*1AQ2;B%}(#nH2JyS+H`Bh1aSvy z=Q3x#LEkFLDiQqRh5{?<))QR`!_w|J!_d+#)xRx`QVc-eNF>i#t7v-2pOC_K*y)8p z_qxfr*aR!(CfE^9WDXuOHP}F%t`*c2N)HojHX3Zw(_D1Szm!=z>>L_hfZb{gKYS$( zcX1=9coBoE9&Y1r^U?`VW}=)j_H8J#^m(J6{<$~cp7O!5#u4&0dVQ#!xCs9`|9&97 zWCnlLLT5BBrMumr;EkGK7B<97P83+_&+3^kX^}kstaV9_cE$CIAq$ULn0rOJrr9(0 zE7f4439dw;a=U2O^y}G~nb9~1L}WL^*4B+^Yy0O-1H50Hh(BoIcx|mlOQ1)-{TeAR z`S9y*Ck>NQk`8-TNT@h%%H1e_*x4#^wJb3uHLu@~Jx;B7)jx2qWLF7PVp~E@EndIQ zG5L$L6r5s?8xz#W9;oLhxFOKpuT>X$-bRt$W@g?lP1@o8i-HZ}BT@_LvEj@z)VN0A zhBYb~vXz_)6`@YZqv^%$<>cn%xZO!J2 zq+brnYv!fMrjs?DN*q#>l}82UpLXrHA{rgrynM@G=DNjev;}gX#V^-mrInsBNqSO7?FTE33@7OcFn9MJ&Hqd0nCXg6!ta)tG3xnqCpHY+l>1 z8f_aq^pq1O(I3xhwDYBTrFECEli?pBw8E17<^BEgs`{jfEJ6LQ(Mz+jXCL;-m9%pj z*$;0=f>*&44Djmb@%^_O8# z2F(KIjdeA4W!nP5496G_;1RRllNu93#nWI`mQv(WqEbIplF3&#ld%VB&;Cg~La0Ch9vLZNCz&;XS^0XEPWrs#^7sia> z0z%VV-k~%)0!(Ty@iZnJt&99tBB{+bbWU$;AVdNkH z!Da@{xd=Cg04@iVmMrWJka^Ayu7+UC0mwWS$CJehwSWn;g$gO>nhI+EwOt4Xa3)KzC*vUSaW!M7AIr_X9Hy`K;`{C&tHMR zF_FO2j?3dj6aT}a{s+!{zF-|eUlu2NL3|G&e10^4B!x2Oq=G`{jsXIhIxjz$90|;q z8mQy^6g8O43P2o7O1>krb83_Pr44#59 zncLuR>|7R|$0u_D>maZOzyA6r*L}CdjECFc> zo8N7yIYM~C{<&In;Th!WN?53ex$ul45QT;45y57MG62qxI{jHU{|jz`|JNG*Pwoq0 z^WL^Bb~M<#br(FL?fqw-4SzSNn`bP@ia7I#`IIpvVbU`K|3W2h^)}Td_?dZ#eK%|v~9}!5_302T2&Lg_oiw{Z2 zD61)`)4a+c5K&d4owcW-pqs4&27I$$855sF3M3P5$2B&@L2m38_H2_v#Vm4;ddHvF=&H9XoO#ayAs+HR@WuM5O1pmp!*fBAa5QZoNKq*k@JZ zt2E;0&8rgg{Yj4}cCq{==o0i$yk(Wfs-0>Aym!a&`2!bmB!xa)qu(DrZ@WMFX)LWD zbn0zMlGIw=P#&{;|5WZP{cSp9ue{>V^{i&ay}YZxi5sIoz1$&>c_h2FBONRo2+@AM KU75|6o&N&&9c(QC literal 1070 zcmV+}1kwA6P)u*#=7{~Gc#rOu2?l}ivsPwv>-OkKX5EBv`xfEL3y7a=WG_@(nO;8k}(MAm#HE1-^ zL=%7J)cDNFboQK?-RZM0*cYEykmr}(Lg1TohTfVukA4_>bL4%uEKaU~lNoMZg`{QnPJ_=6eAk0>kq-n469|- z8PV{hS_UUGESE6Jh=wQR5;)QD`1B$;nc?OYj5DI)vE~(UGQ*7pj4`6&(Z)PDnPD-H zQARX8A})iI8J@a?5k@q8qJ9aS3d3_aQRhR$?@V3$YQ*5GP#SiXqQ0&XgX^{#wn|a0Ys6%iC=J`C zC|4C?vhSN=s}!eK6k@VVl!on6Y_=6*vhUNdU5brmg_!L7X4oo4v8WJ}U7|GXD#fV< zg&177&9I{s>z5T`a8)P`cPhonIf-6$x@(3@N^#)^i}&5-tMk|51(5!Tvd0^z7z;ibkKSED174SQKC@AzE8uhqI*!2xbNX!O`?qJwi$LjTfAG7$ldXhb3-!x;`u`-)g0wu}|Tx4@<0h@VQ09A*I(Io`y@v ojl%HY+2Y~85=&q8YgLQ?0taDr`>VTCp#T5?07*qoM6N<$f+^t*MF0Q* diff --git a/src/main/resources/assets/gregtech/textures/gui/widget/clipboard_text_box.png b/src/main/resources/assets/gregtech/textures/gui/widget/clipboard_text_box.png index fb5502dbc9c4e48e7e5ffaa324f19f49510309d0..21e4e0c365a6bab0a5eeec528ee93785c05bdcd6 100644 GIT binary patch literal 5637 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 ALI3~& literal 166 zcmeAS@N?(olHy`uVBq!ia0vp^{6H+n!3HEh$GDULDaPU;cPEB*=VV?2ISHOFjv*Gk z$vN+$KF(+4|IvTWDd_AWeT5c({kQ|4{@cfOXD*-FnKO6FtuswRHA`;$Y>Q(PW9xF7 zEtDR-V0zMQ%}>TZ6Bu%r=~VJvWsq(>IeF2chD}Ks9%6g* Date: Sat, 21 Aug 2021 16:40:20 +0800 Subject: [PATCH 40/42] Squashed commit of the following: commit 713fd9e2c64ff981b318f201966ee7ab450a0424 Author: ALongStringOfNumbers <31759736+ALongStringOfNumbers@users.noreply.github.com> Date: Fri Aug 20 23:33:54 2021 -0700 Fix for null materials being entered into the washedIn pair (#98) commit e0d55c8ce2cdfd245125cfc959887d083eac28f3 Author: ALongStringOfNumbers <31759736+ALongStringOfNumbers@users.noreply.github.com> Date: Fri Aug 20 22:59:08 2021 -0700 Allow specifying the amount of fluid for chemical bath processing (#97) commit 98e3befed157f56ac3859ee19d4a8b0954fed113 Author: froot <66188216+kumquat-ir@users.noreply.github.com> Date: Fri Aug 20 22:38:12 2021 -0700 Material Tree JEI page returns (#66) commit 0f6c8b7f800791d30ee98c77814c533731868765 Author: KilaBash Date: Sat Aug 21 13:11:31 2021 +0800 GuideBook stuff (#46) commit 63adb22f554e72115c27131c2d0756004eab1ef5 Author: ALongStringOfNumbers <31759736+ALongStringOfNumbers@users.noreply.github.com> Date: Fri Aug 20 22:05:50 2021 -0700 Fix infinite Energy emitter decrement amperage not working (#94) commit f0c9a841c883fc9a87f57a3cfb7bbc7021986b79 Author: DStrand1 Date: Fri Aug 20 23:54:37 2021 -0500 fix oilsands recipe commit 0dc9f97a5758d6dfe123b4d8d2cd993626362633 Author: ALongStringOfNumbers <31759736+ALongStringOfNumbers@users.noreply.github.com> Date: Fri Aug 20 21:44:06 2021 -0700 Fix Infinite Emitter breaking particles (#93) commit f8f1284d6da7a7607dfe3856cdfe18ea40434b8f Author: DStrand1 Date: Fri Aug 20 23:08:35 2021 -0500 remove multi fluid pipes for Wood commit 0672a79fb4c92ea8b3b4c14ac1c36e8e0eb2e641 Author: DStrand1 Date: Fri Aug 20 22:21:01 2021 -0500 fix primitive multis workable fix diamond composition commit c50fdb272f84ba6f251d39a70f395c07a957b28a Author: BraggestSage833 <46819052+BraggestSage833@users.noreply.github.com> Date: Fri Aug 20 23:18:33 2021 -0400 fix the default output side on quantum tanks/chest (#92) commit 5c464537fe6f115266cda3e22e23bdf16ed37221 Author: PrototypeTrousers Date: Fri Aug 20 23:24:16 2021 -0300 "Better Idling" for MTEs (#91) Co-authored-by: Exa <11907282+Exaxxion@users.noreply.github.com> commit 835b5b9da923d22d826595e3b211498d73f14246 Author: DStrand1 Date: Fri Aug 20 21:12:55 2021 -0500 make battery tooltips better commit 78e37f755b8c452e3c18ccd81c871697fb9354cb Author: Tech22 Date: Fri Aug 20 03:53:31 2021 -0400 add tiered superconductors commit 4eb9133e25eeb2b1b86bbef410cf374a6353d05d Author: DStrand1 Date: Fri Aug 20 02:13:06 2021 -0500 add new EV-UV batteries commit 1e6ff1ebcbb9e7b1e6a7f824ad01f0425d8811dc Author: DStrand1 Date: Fri Aug 20 01:00:52 2021 -0500 remove line from build.gradle commit 312c188175afd8a5e4cfe4e424a24b9b3d636202 Author: DStrand1 Date: Thu Aug 19 19:39:11 2021 -0500 fix log warning about missing recipe property commit d76afa3c4aa7a3bdac550ee7bac5905d13400d38 Author: Rongmario Date: Thu Aug 19 07:32:25 2021 +0100 Add config to turn on/off GT adding loot (#87) commit 4fa4e3f57a91213f36b7f0a6c03f56396cd1d149 Author: brachy84 <45517902+brachy84@users.noreply.github.com> Date: Thu Aug 19 08:30:20 2021 +0200 Fix issue from #80 (#88) commit c7e9f84e368ef1d7ee8354b88c0a4d883f7c4b62 Author: brachy84 <45517902+brachy84@users.noreply.github.com> Date: Thu Aug 19 08:27:07 2021 +0200 Pipefixes (#80) * i forgor release() commit aba97f094c3a92f7ce7332a2148cf48919db6594 Author: DStrand1 Date: Wed Aug 18 23:23:30 2021 -0500 clean out dead prefixes (will cause ID shift) commit 0bbdc6542670b0a5a9007b87f73310514ac90302 Author: DStrand1 Date: Wed Aug 18 23:21:03 2021 -0500 clean up current batteries commit b59f0dc859f2d1121d85886732b722b76b243587 Author: DStrand1 Date: Wed Aug 18 22:13:06 2021 -0500 finish Supercon value on WireProperty commit 5018bbedac00daf0f47e5afb207ebd13461728bc Author: DStrand1 Date: Tue Aug 17 23:24:12 2021 -0500 add some missing iconset files from gregicality commit ce2d5febfe8c334d7ff141a9dbbd7aa42d3acf28 Author: DStrand1 Date: Tue Aug 17 22:39:13 2021 -0500 add `heat` getter to fusion reactor commit 3e599b5156eae971e7fdf86dbdb2d86ba3d34930 Author: DStrand1 Date: Tue Aug 17 20:50:58 2021 -0500 remove ExNi stuff (in Gregification) commit 0cb6427133f7a9eea3789aa84d50161c462c6fef Author: Dane Strandboge Date: Tue Aug 17 01:21:31 2021 -0500 Primitive Multi Rewrite (#85) * new PBF working * implement primitive recipes * finish PBF * refactor Coke Oven * update changelog * fix tech memeing on me commit 61a52dbb2337e31ee9a5183d3a8251c105c0fdcc Author: DStrand1 Date: Mon Aug 16 21:47:28 2021 -0500 update changelog for #75 commit d51ae3e0b76826c962d224725b258c6095aa3867 Author: bruberu <80226372+bruberu@users.noreply.github.com> Date: Mon Aug 16 21:46:42 2021 -0500 Add Highlighting to the Crafting Station (#75) commit 36ef03982dda421870e2f9f5e12b33bad7981b8f Author: DStrand1 Date: Mon Aug 16 21:03:29 2021 -0500 relocate `RecipeMapSteamMultiblockController` commit 13b7827f22611f57a72c88b5ba6b15ac5c238de0 Author: DStrand1 Date: Mon Aug 16 02:00:04 2021 -0500 clean up components, make constructor public commit 77ce62e91effb5369b91794a20d1a97e2e287ddf Author: brachy84 <45517902+brachy84@users.noreply.github.com> Date: Mon Aug 16 08:58:55 2021 +0200 rework creative energy (#84) commit 48b12848628cc79737fd4a02c05712b0836f8602 Author: DStrand1 Date: Mon Aug 16 01:33:26 2021 -0500 add circuit markers to CraftingComponent commit 2100c869ec1cad8fd3b2ad566bd9c099a1813b6a Author: DStrand1 Date: Mon Aug 16 00:55:09 2021 -0500 rework crafting component loading commit 612bc74d22ed9efc9e990156c509e295406436bc Author: Rongmario Date: Mon Aug 16 02:11:59 2021 +0100 De-enumify MaterialIconSet + MaterialIconType (#82) - Names are converted to the right format in the ctor commit 826556ad1fadf19ed721fe2ce74365b947b5aa60 Author: DStrand1 Date: Sun Aug 15 17:11:57 2021 -0500 pull changes from upstream #1710 commit 0ef0b33af613e4593326af41d86a98d91c91cb74 Author: DStrand1 Date: Sun Aug 15 17:08:44 2021 -0500 add some MetaItem MaterialInfos commit 523627d76f2390ea0d23a70418c87077e40c3288 Author: Rongmario Date: Sun Aug 15 16:33:16 2021 +0100 No longer hardcode biomes for primitive water pump (#81) - Now utilizes Forge's BiomeDictionary types - Ocean/River => `Type.WATER` (1000) - Swamp => `Type.SWAMP` and `Type.WET` (800) - Jungle => `Type.JUNGLE` (350) - Snow => `Type.SNOWY` (300) - Plains/Forest => `Type.PLAINS` and `Type.FOREST` (250) - Taiga => `Type.COLD` (175) - Beach => `Type.BEACH` (170) commit 85b3e98bb6ea95703cbb1e5dddedfd46fbe9e333 Author: DStrand1 Date: Sun Aug 15 01:34:08 2021 -0500 update changelog for EnergyNet updates commit 7a9b1db57d47d8552d66b99dda44862facce20ab Author: brachy84 <45517902+brachy84@users.noreply.github.com> Date: Sun Aug 15 08:32:02 2021 +0200 Electric pipes rework (#78) commit 757264a432126cb4be703901c67c3afe9daaa999 Author: BraggestSage833 <46819052+BraggestSage833@users.noreply.github.com> Date: Sun Aug 15 02:17:23 2021 -0400 reinstate metaArmor classes (#79) commit 11ecde267d5b66eeac199fce931c42d4b05e70a3 Author: DStrand1 Date: Sun Aug 15 00:57:00 2021 -0500 remove energy field projector, cleanup commit 73f6bdc9fcd103c235a2c3fe0cc4a874fd866f26 Author: DStrand1 Date: Sat Aug 14 22:38:35 2021 -0500 update changelog for buffers commit dc81fa8947860508ab8f5b905e7cebc634f80dc6 Author: DStrand1 Date: Sat Aug 14 22:37:29 2021 -0500 port the Buffer to CEu commit fa1b388a4e15f85357db84e236cab00804376de4 Author: DStrand1 Date: Sat Aug 14 19:59:18 2021 -0500 pull changes from upstream #1701 commit 2bede3b403d98755efb2b2b1ee09c033f8e90b3c Author: DStrand1 Date: Sat Aug 14 19:48:36 2021 -0500 merge changes from upstream #1709 commit db8a4a94c8f445b3ce4a551ef6a85706116eb000 Author: Tech22 Date: Sat Aug 14 20:45:52 2021 -0400 change isotope element symbols to a dash commit 6eff9e6bf5f8407fd3611278c0a0e82740480979 Author: DStrand1 Date: Sat Aug 14 19:45:39 2021 -0500 fix Water missing fluid tooltip commit ecae98a388ec75f1349a1de7f5e170ca7b347fa6 Author: DStrand1 Date: Sat Aug 14 19:14:34 2021 -0500 add `.chancedOutputs` builder call for List commit 5a403541c1a02b9505c22f512db7656c587e9090 Author: DStrand1 Date: Sat Aug 14 18:08:29 2021 -0500 add some missing material flags commit 59fb179b13309f1d7da251c349e3f1a542811116 Author: DStrand1 Date: Sat Aug 14 14:43:23 2021 -0500 buff Indium (small over tiny dust) commit 6f828573ecbb5d22addbf5c975fc532e3f6ddd4c Author: Tech22 Date: Sat Aug 14 12:49:04 2021 -0400 change distillation EUt to reflect config commit 9e10cf273c49a29191cbd1b0fac14fc84b02040e Author: DStrand1 Date: Sat Aug 14 02:27:23 2021 -0500 add more changes, fix some mistakes commit 82fb2546e35ca6519cf385268bf5a9452d99d1a1 Author: Dane Strandboge Date: Sat Aug 14 02:03:55 2021 -0500 fix some changelog mistakes commit 4289c6589a9e3db82ff35569bc67f8feae5e2d57 Author: DStrand1 Date: Sat Aug 14 02:01:26 2021 -0500 add GTCEu changelog (probably missed something) commit 90c4e2fde3a1136599c4e165db5e9b2a8b9938f2 Author: DStrand1 Date: Sat Aug 14 00:55:44 2021 -0500 fix DT outputs sometimes on wrong layers commit 859bcb99a432bed96d0402f6c70287e12fdedf29 Author: brachy84 <45517902+brachy84@users.noreply.github.com> Date: Sat Aug 14 07:03:57 2021 +0200 Fluid pipes rework, MultiFluid Pipes (#53) commit ba74b2f71aebaf030784685c6f71c89d8f240c77 Author: Rongmario Date: Fri Aug 13 21:56:25 2021 +0100 Made material tool enchantability not implicitly tied to icon sets (#76) * Made material tool enchantability not implicitly tied to icon sets - Nano Saber gets 33 enchantability, it inherited platinum's enchantability before but right now platinum doesn't have the tool property - Deprecated old static helper method to get a material enchantability (delete outright?) * Remove deprecated method commit 1b3c24112e9b98eed37eb31133a6e70018582958 Author: Tech22 Date: Fri Aug 13 02:58:17 2021 -0400 infinite water cover tweaks commit 9a7af7d463c8f11f054cc6017e5a841609615c58 Author: Tech22 Date: Fri Aug 13 02:30:35 2021 -0400 add recipes to adjustables, simple washer commit d4b0dfa3e3166a81caf913f51d8956cdfbb298af Author: DStrand1 Date: Fri Aug 13 01:22:47 2021 -0500 add infinite water cover commit 664bd32ab946b96a90ed419a4ef86f743522f629 Author: Tech22 Date: Fri Aug 13 00:44:57 2021 -0400 add simple washer commit 807092abb4a393a63283b7be89691840139d83c6 Author: DStrand1 Date: Thu Aug 12 23:42:24 2021 -0500 Revert "remove RecipeMap minimums" This reverts commit 201c564b510a778c154bfec9b03e9ab88d87d1c7. commit 806dfd21c36e4a946cb68e1a5b978d480167edcc Author: DStrand1 Date: Thu Aug 12 22:08:39 2021 -0500 small cleanup on OreProperty commit bf2e3976ba3337ea31fed21bcaddc9b2772b5c29 Author: DStrand1 Date: Thu Aug 12 22:06:24 2021 -0500 require DustProperty for oreByProducts commit eb03b825cf6dff659614abc91be2f29be7301997 Author: DStrand1 Date: Thu Aug 12 21:57:28 2021 -0500 port Native EU to FE commit d1bceee12d78073c24601e9cf9f4701ab30ec05b Author: DStrand1 Date: Thu Aug 12 21:39:32 2021 -0500 port Diodes from Gregicality commit 3c4a9cf2d6094ce8484817eb12ceb6d816888c12 Author: DStrand1 Date: Thu Aug 12 21:06:28 2021 -0500 Squashed commit of the following: commit 22cf3164da2ca2c2d9baf2c0fa20c386aa861cc3 Author: DStrand1 Date: Thu Aug 12 21:05:58 2021 -0500 Revert "clean up duplicated code in energy hatch" This reverts commit 44b1b7f746dfc4551a078029c4df8811af4750a8. commit 44b1b7f746dfc4551a078029c4df8811af4750a8 Author: DStrand1 Date: Thu Aug 12 20:07:39 2021 -0500 clean up duplicated code in energy hatch commit 016376420385061837d3ba957966f990fa77379a Author: Tech22 Date: Thu Aug 12 15:51:32 2021 -0400 adjustable energy hatches commit 6acee8685ef6975176f107a723eca20b905c512d Author: Tech22 Date: Thu Aug 12 14:57:21 2021 -0400 adjustable transformers commit 45e27fa221abe8191d0eb1f707670e33597c5554 Author: Tech22 Date: Thu Aug 12 03:28:29 2021 -0400 fix off-centered lignite gem texture commit 254ea67091920f0223e1e707b055f2c6e73b50aa Author: Tech22 Date: Thu Aug 12 03:26:32 2021 -0400 better coke oven jei page commit 19ce5157287becff8285442ab81094b1c4464039 Author: DStrand1 Date: Thu Aug 12 02:05:19 2021 -0500 add method for addons to register MTEs easily commit f0c75f2db1419765200156b72125d784eec0b2e0 Author: DStrand1 Date: Thu Aug 12 00:19:46 2021 -0500 merge material changes from multi PR commit 308d43659dbf92a0862e3b47d22e7b8e7eab5141 Author: DStrand1 Date: Wed Aug 11 23:06:11 2021 -0500 more code cleanup commit 3789f4b569cf133fb5348b67b36cc786ca15ca15 Author: DStrand1 Date: Wed Aug 11 22:40:41 2021 -0500 clean up configs a bit commit 052fd4eef6a48b175fc625753dc341724a7cb4b5 Author: DStrand1 Date: Wed Aug 11 20:36:08 2021 -0500 add registration, CT method commit b6cad8cd54834ddd62692bea7e2495fe540d8b34 Author: DStrand1 Date: Wed Aug 11 20:30:45 2021 -0500 port MetaOreDictItem commit c1e978085979b53d1f12b836254c8a582158b82a Author: DStrand1 Date: Wed Aug 11 19:58:54 2021 -0500 make addOrePrefix take varargs commit afe3e353f1a74fb529543423a9a9b46b70d47ea1 Author: DStrand1 Date: Wed Aug 11 19:54:46 2021 -0500 make `addOrePrefix` public commit 09600d227030e266e084afb13cf31c371b63b08f Author: DStrand1 Date: Wed Aug 11 19:30:58 2021 -0500 make OrePrefix constructor public commit cde0631e469d8266ffef1898ed977875c379aa3f Author: Tech22 Date: Wed Aug 11 18:59:45 2021 -0400 fix extra facade material recipes being registered commit 292ff214ef05a3fa5b6f71ce3feb1b2d82af75ea Author: Tech22 Date: Wed Aug 11 18:47:10 2021 -0400 use dimension names for gas collector property commit 189f6458bbcc15138e49a6555f984938dc4b7d87 Author: Tech22 Date: Wed Aug 11 10:41:27 2021 -0400 fix missing resource location commit 724b20ec068df578837916be465cb6391ccd8b36 Author: Tech22 Date: Wed Aug 11 10:36:10 2021 -0400 add missing components to H2S and FeCl3 commit 18c4373aa4e8e7329c536e07ea7e0aa32ba89641 Author: Tech22 Date: Wed Aug 11 02:19:53 2021 -0400 prevent DT jei page overlaps commit 201c564b510a778c154bfec9b03e9ab88d87d1c7 Author: DStrand1 Date: Wed Aug 11 01:20:18 2021 -0500 remove RecipeMap minimums commit 9a307e10138de2937a0250844e3dc2b8ed1e8f17 Author: TechLord22 <37029404+TechLord22@users.noreply.github.com> Date: Wed Aug 11 01:30:34 2021 -0400 Add Cryogenic Air Recipes (#74) commit d1a5619d58cc4d0046c4e3edef3f353317eaaf8b Author: DStrand1 Date: Tue Aug 10 23:58:21 2021 -0500 clean up tool classes impl commit 41ff7ce843cb1b620ef5a36a542ceccb8a5f4f5d Author: BraggestSage833 <46819052+BraggestSage833@users.noreply.github.com> Date: Wed Aug 11 00:51:19 2021 -0400 Update ToolWrench.java (#70) commit cdd99234beb7611cd0787addb55fc0b84a64f7c7 Author: DStrand1 Date: Tue Aug 10 23:46:33 2021 -0500 clean up steam-era recipe duration and EUt commit e53885d870706dd03d72af29db2d11de7cdf9b3c Author: DStrand1 Date: Tue Aug 10 23:19:16 2021 -0500 :monkey: dust blocks :monkey: commit 81f2eef6a9f6af6dd718d35ec886995e20974491 Author: DStrand1 Date: Tue Aug 10 23:13:29 2021 -0500 rename bricked steel hull commit 8f5ad1df8e1cab3f21666afb6ec8dff841b66302 Author: DStrand1 Date: Tue Aug 10 22:58:53 2021 -0500 make steam great again commit 346ce2ceb8789e60057205837c3127f4030e24dd Author: DStrand1 Date: Tue Aug 10 21:05:59 2021 -0500 rework Steam Machine logic commit 8288ff0f6d1cb49ebda3cac16a4263ead468cf4a Author: DStrand1 Date: Tue Aug 10 20:22:02 2021 -0500 wipe recipe cache on multiblock deformation commit f1e6a956df487c17230793c029bf83c1bd182adb Author: Tech22 Date: Tue Aug 10 19:10:51 2021 -0400 make NaOH not power positive, change cumene to consume H3PO4 commit b37cdf2e3c4b7a2b73db881c26c0c92886fa9587 Author: DStrand1 Date: Mon Aug 9 22:49:04 2021 -0500 fix issues in UniversalDistillationBuilder commit 30cf93ccd3f6f81bee442e48ebcb22e3b3ee7798 Author: BraggestSage833 <46819052+BraggestSage833@users.noreply.github.com> Date: Mon Aug 9 20:28:52 2021 -0400 Quantum Tanks/Chests can now disallow input from their export face via screwdriver (#69) commit 95d1f58c202cc257b6ccefa0eba9165776e2f9bb Author: Tech22 Date: Mon Aug 9 18:54:31 2021 -0400 fix crate guis commit a4634bd877020371dfdea795d99d1d4a8420db11 Author: Tech22 Date: Mon Aug 9 17:56:17 2021 -0400 fix drum TOP display commit b1ac5e5338c5804d76086789f9876b1032195656 Author: Tech22 Date: Mon Aug 9 02:23:41 2021 -0400 add toolstats to Flint commit a22aa3587c3d0b880ba198d058a11d8b88a187ea Author: Tech22 Date: Mon Aug 9 02:12:04 2021 -0400 fix missing filter and crate recipes commit 019ed5349f9f5035849bf4caa9bc879e137baee4 Author: DStrand1 Date: Mon Aug 9 01:04:54 2021 -0500 remove ULV from overclock button commit 98a6ca6552f710a5c4008aa8144da7baa891bb46 Author: TechLord22 <37029404+TechLord22@users.noreply.github.com> Date: Mon Aug 9 02:04:08 2021 -0400 Add Gas Collectors (#68) * add dimension-specific gas collectors commit 17d8f742f317d3ae4ada4f3d243215ca9a63313c Author: Tech22 Date: Mon Aug 9 01:53:14 2021 -0400 add polished stone autoclave recipes commit 90b8e041f5483a91d008aacdada61c55626017dd Author: DStrand1 Date: Mon Aug 9 00:25:49 2021 -0500 trim lossless wire configs commit 4f36d36b2e3235fdfa9464bcae3d303e288a9fbf Author: DStrand1 Date: Mon Aug 9 00:16:30 2021 -0500 clean up MetaTileEntities commit 161a216a3b98d8a94612e7eb63f0bce48315eaf9 Author: DStrand1 Date: Sun Aug 8 23:12:45 2021 -0500 add UV-UXV circuit assembler lang keys commit a65bbaa4ba779a428061b520498a4fab97e22dce Author: DStrand1 Date: Sun Aug 8 22:05:16 2021 -0500 fix crash on furnace recipe removal commit 932be0f8786e574c49485f165bc7489c6e4ced0d Author: DStrand1 Date: Sun Aug 8 21:57:13 2021 -0500 add debug logging to recipe removals commit 7f557a9bf2b4efe571ca44cae46fa7879ef5405c Author: DStrand1 Date: Sun Aug 8 21:09:03 2021 -0500 config to disable in-world concrete commit 2cd6159e7b8197a1bb3ab308e0df7fb7cf840fdb Author: ALongStringOfNumbers <31759736+ALongStringOfNumbers@users.noreply.github.com> Date: Sun Aug 8 18:29:28 2021 -0700 A bunch of small cleanups (#67) * Slight cleanup of unused constructors Slight fix to Assembly Line JEI page Remove Legacy method of specifying surface rocks * Fix typo in Electric Furnace recipe map localization --- CHANGELOG-GTCEU.md | 216 ++++++ build.gradle.kts | 1 - src/main/java/gregtech/GregTechMod.java | 8 + src/main/java/gregtech/api/GTValues.java | 44 +- src/main/java/gregtech/api/GregTechAPI.java | 1 - .../api/capability/GregtechCapabilities.java | 14 + .../api/capability/IEnergyContainer.java | 34 +- .../api/capability/INotifiableHandler.java | 33 + .../api/capability/impl/AbstractFuelInfo.java | 4 - .../capability/impl/AbstractRecipeLogic.java | 153 ++-- .../api/capability/impl/EUToFEProvider.java | 67 ++ .../impl/EnergyContainerBatteryBuffer.java | 17 +- .../impl/EnergyContainerHandler.java | 11 +- .../api/capability/impl/GTEnergyWrapper.java | 338 ++++++++ .../impl/MultiblockRecipeLogic.java | 8 +- .../impl/NotifiableFilteredFluidHandler.java | 27 + .../capability/impl/NotifiableFluidTank.java | 28 + .../impl/NotifiableItemStackHandler.java | 29 + .../capability/impl/PrimitiveRecipeLogic.java | 58 ++ .../api/capability/impl/RecipeLogicSteam.java | 10 +- .../capability/impl/SteamMultiWorkable.java | 45 +- .../impl/SteamMultiblockRecipeLogic.java | 9 +- .../java/gregtech/api/gui/GuiTextures.java | 19 + src/main/java/gregtech/api/gui/ModularUI.java | 1 + src/main/java/gregtech/api/gui/Widget.java | 282 ++++++- .../gregtech/api/gui/impl/ModularUIGui.java | 72 +- .../api/gui/impl/ModularUIGuiHandler.java | 6 +- .../IRecipeTransferHandlerWidget.java | 3 +- .../api/gui/resources/ColorRectTexture.java | 63 ++ .../api/gui/resources/FileTexture.java | 107 +++ .../api/gui/resources/IGuiTexture.java | 6 + .../api/gui/resources/ItemStackTexture.java | 48 ++ .../api/gui/resources/ModifyGuiTexture.java | 102 +++ .../api/gui/resources/RenderUtil.java | 7 +- .../api/gui/resources/TextTexture.java | 29 + .../api/gui/resources/TextureArea.java | 3 +- .../api/gui/resources/URLTexture.java | 79 ++ .../AnimatedPictureTexture.java | 66 ++ .../picturetexture/OrdinaryTexture.java | 23 + .../picturetexture/PictureTexture.java | 65 ++ .../picturetexture/VideoTexture.java | 19 + .../gui/resources/utils/DownloadThread.java | 225 ++++++ .../api/gui/resources/utils/GifDecoder.java | 721 ++++++++++++++++++ .../api/gui/resources/utils/ImageUtils.java | 57 ++ .../resources/utils/ProcessedImageData.java | 137 ++++ .../api/gui/resources/utils/TextureCache.java | 150 ++++ .../api/gui/widgets/AbstractWidgetGroup.java | 135 +++- .../api/gui/widgets/ClickButtonWidget.java | 9 + .../CraftingStationInputWidgetGroup.java | 70 ++ .../gregtech/api/gui/widgets/ImageWidget.java | 23 +- .../gregtech/api/gui/widgets/LabelWidget.java | 50 +- .../api/gui/widgets/PhantomFluidWidget.java | 53 +- .../api/gui/widgets/PhantomSlotWidget.java | 2 + .../api/gui/widgets/ScrollableListWidget.java | 5 +- .../api/gui/widgets/SimpleTextWidget.java | 32 +- .../gregtech/api/gui/widgets/SlotWidget.java | 102 ++- .../gregtech/api/gui/widgets/TabGroup.java | 71 +- .../gregtech/api/gui/widgets/TankWidget.java | 40 +- .../api/gui/widgets/TextFieldWidget.java | 93 ++- .../TextFieldWidgetInfiniteEnergy.java | 61 -- .../gregtech/api/gui/widgets/WidgetGroup.java | 21 + .../gui/widgets/tab/IGuiTextureTabInfo.java | 36 + .../api/gui/widgets/tab/ITabInfo.java | 4 +- .../api/gui/widgets/tab/ItemTabInfo.java | 15 +- .../api/gui/widgets/tab/TabListRenderer.java | 2 +- .../gregtech/api/items/armor/ArmorHooks.java | 22 + .../api/items/armor/ArmorMetaItem.java | 192 +++++ .../api/items/armor/ArmorRenderHooks.java | 72 ++ .../api/items/armor/DummyArmorLogic.java | 36 + .../gregtech/api/items/armor/IArmorItem.java | 18 + .../gregtech/api/items/armor/IArmorLogic.java | 65 ++ .../api/items/armor/ISpecialArmorLogic.java | 46 ++ .../items/crafttweaker/CTItemRegistry.java | 20 + .../items/materialitem/MetaPrefixItem.java | 14 +- .../api/items/metaitem/ElectricStats.java | 24 + .../gregtech/api/items/metaitem/MetaItem.java | 50 +- .../api/items/metaitem/MetaOreDictItem.java | 109 +++ .../api/items/toolitem/ToolMetaItem.java | 29 +- .../InfiniteEnergyTileEntityBase.java | 64 -- .../api/metatileentity/MetaTileEntity.java | 52 +- .../metatileentity/MetaTileEntityHolder.java | 13 +- .../WorkableTieredMetaTileEntity.java | 29 +- .../multiblock/IMultiblockPart.java | 5 + .../multiblock/MultiblockControllerBase.java | 17 +- ...ecipeMapPrimitiveMultiblockController.java | 50 ++ .../RecipeMapSteamMultiblockController.java | 8 +- .../gregtech/api/multiblock/BlockPattern.java | 24 +- .../api/multiblock/FactoryBlockPattern.java | 4 +- .../api/pipenet/MonolithicPipeNet.java | 65 -- .../gregtech/api/pipenet/PipeGatherer.java | 66 ++ .../gregtech/api/pipenet/PipeNetWalker.java | 186 +++++ .../gregtech/api/pipenet/block/BlockPipe.java | 6 +- .../block/material/ItemBlockMaterialPipe.java | 3 - .../tickable/TickableWorldPipeNet.java | 12 +- .../gregtech/api/pipenet/tile/IPipeTile.java | 8 +- .../tile/PipeCoverableImplementation.java | 8 +- .../api/pipenet/tile/TileEntityPipeBase.java | 69 +- .../gregtech/api/recipes/GTRecipeHandler.java | 96 +++ .../java/gregtech/api/recipes/ModHandler.java | 73 +- .../java/gregtech/api/recipes/Recipe.java | 8 + .../gregtech/api/recipes/RecipeBuilder.java | 5 + .../java/gregtech/api/recipes/RecipeMap.java | 13 +- .../java/gregtech/api/recipes/RecipeMaps.java | 38 +- .../builders/CokeOvenRecipeBuilder.java | 137 ---- .../builders/GasCollectorRecipeBuilder.java | 68 ++ .../recipes/builders/PBFRecipeBuilder.java | 139 ---- .../builders/PrimitiveRecipeBuilder.java | 37 + .../UniversalDistillationRecipeBuilder.java | 20 +- .../crafttweaker/CokeOvenRecipeExpansion.java | 17 - .../crafttweaker/PBFRecipeExpansion.java | 17 - .../api/recipes/machines/FuelRecipeMap.java | 7 +- .../machines/RecipeMapDistillationTower.java | 61 ++ .../GasCollectorDimensionProperty.java | 47 ++ .../recipeproperties/PrimitiveProperty.java | 27 + .../RecipePropertyStorage.java | 4 + .../java/gregtech/api/render/Textures.java | 7 + .../api/terminal/TerminalRegistry.java | 49 ++ .../api/terminal/app/AbstractApplication.java | 75 ++ .../terminal/gui/CustomTabListRenderer.java | 41 + .../gregtech/api/terminal/gui/IDraggable.java | 8 + .../gui/widgets/AnimaWidgetGroup.java | 100 +++ .../gui/widgets/CircleButtonWidget.java | 149 ++++ .../api/terminal/gui/widgets/ColorWidget.java | 285 +++++++ .../gui/widgets/CustomPositionSizeWidget.java | 211 +++++ .../DraggableScrollableWidgetGroup.java | 351 +++++++++ .../gui/widgets/RectButtonWidget.java | 132 ++++ .../terminal/gui/widgets/SelectorWidget.java | 120 +++ .../gui/widgets/TextEditorWidget.java | 325 ++++++++ .../terminal/gui/widgets/TreeListWidget.java | 239 ++++++ .../terminal/os/TerminalDesktopWidget.java | 44 ++ .../api/terminal/os/TerminalDialogWidget.java | 285 +++++++ .../api/terminal/os/TerminalOSWidget.java | 246 ++++++ .../api/terminal/os/TerminalTheme.java | 71 ++ .../api/terminal/os/menu/IMenuComponent.java | 15 + .../terminal/os/menu/TerminalMenuWidget.java | 173 +++++ .../gregtech/api/terminal/util/FileTree.java | 50 ++ .../gregtech/api/terminal/util/FileUtils.java | 39 + .../api/terminal/util/GuideJsonLoader.java | 46 ++ .../gregtech/api/terminal/util/ISearch.java | 8 + .../api/terminal/util/SearchEngine.java | 37 + .../gregtech/api/terminal/util/TreeNode.java | 75 ++ .../gregtech/api/unification/Elements.java | 12 +- .../unification/material/MarkerMaterials.java | 1 - .../api/unification/material/Material.java | 22 +- .../api/unification/material/Materials.java | 14 +- .../material/info/MaterialIconSet.java | 81 +- .../material/info/MaterialIconType.java | 238 +++--- .../material/materials/ElementMaterials.java | 77 +- .../materials/FirstDegreeMaterials.java | 153 +++- .../materials/HigherDegreeMaterials.java | 16 +- .../materials/OrganicChemistryMaterials.java | 10 +- .../materials/SecondDegreeMaterials.java | 73 +- .../UnknownCompositionMaterials.java | 3 +- .../properties/FluidPipeProperties.java | 16 +- .../material/properties/OreProperty.java | 25 +- .../material/properties/ToolProperty.java | 13 +- .../material/properties/WireProperties.java | 13 +- .../api/unification/ore/OrePrefix.java | 40 +- .../gregtech/api/util/BaseCreativeTab.java | 4 - .../gregtech/api/util/DirectionHelper.java | 70 -- .../gregtech/api/util/FirstTickScheduler.java | 48 -- .../gregtech/api/util/FluidTooltipUtil.java | 4 +- .../gregtech/api/util/IFirstTickTask.java | 10 - .../gregtech/api/util/LocalizationUtils.java | 49 ++ .../gregtech/api/util/RelativeDirection.java | 36 + src/main/java/gregtech/api/util/SlotUtil.java | 3 +- .../api/util/TickingObjectHolder.java | 55 ++ .../java/gregtech/api/util/function/Task.java | 1 + .../gregtech/api/util/interpolate/Eases.java | 24 + .../gregtech/api/util/interpolate/IEase.java | 5 + .../api/util/interpolate/Interpolator.java | 56 ++ .../worldgen/config/OreDepositDefinition.java | 8 - .../populator/SurfaceRockPopulator.java | 2 +- .../java/gregtech/common/ClientProxy.java | 4 +- .../java/gregtech/common/CommonProxy.java | 7 + .../java/gregtech/common/ConfigHolder.java | 170 +---- src/main/java/gregtech/common/MetaFluids.java | 1 + .../common/asm/ConcretePowderVisitor.java | 22 + .../gregtech/common/asm/GTCETransformer.java | 8 + .../common/blocks/CompressedItemBlock.java | 4 - .../common/blocks/FrameItemBlock.java | 3 - .../gregtech/common/blocks/MetaBlocks.java | 11 +- .../gregtech/common/blocks/OreItemBlock.java | 5 - .../common/covers/CoverBehaviors.java | 1 + .../gregtech/common/covers/CoverConveyor.java | 19 +- .../common/covers/CoverFluidFilter.java | 4 + .../common/covers/CoverFluidRegulator.java | 75 +- .../common/covers/CoverInfiniteWater.java | 42 + .../common/covers/CoverItemFilter.java | 4 + .../gregtech/common/covers/CoverPump.java | 45 +- .../common/covers/DistributionMode.java | 6 + .../common/gui/widget/CraftingSlotWidget.java | 6 +- .../sources/InventoryItemSource.java | 21 +- .../items/FieldProjectorEventHandler.java | 142 ---- .../java/gregtech/common/items/MetaItem1.java | 279 +++---- .../java/gregtech/common/items/MetaItems.java | 46 +- .../AbstractMaterialPartBehavior.java | 6 +- .../common/items/behaviors/FacadeItem.java | 4 +- .../items/behaviors/NanoSaberBehavior.java | 4 +- .../items/behaviors/TerminalBehaviour.java | 54 ++ .../metatileentities/MetaTileEntities.java | 355 ++++----- .../MetaTileEntityAdjustableTransformer.java | 195 +++++ .../electric/MetaTileEntityAirCollector.java | 116 --- .../electric/MetaTileEntityDiode.java | 152 ++++ .../electric/MetaTileEntityGasCollector.java | 97 +++ .../MetaTileEntityInfiniteEmitter.java | 247 ------ .../electric/MetaTileEntityMacerator.java | 4 +- .../MetaTileEntitySimpleOreWasher.java | 28 + .../electric/MetaTileEntityTransformer.java | 12 +- .../MetaTileEntityAdjustableEnergyHatch.java | 188 +++++ .../MetaTileEntityFluidHatch.java | 17 +- .../multiblockpart/MetaTileEntityItemBus.java | 19 +- .../multi/MetaTileEntityCokeOven.java | 240 +----- .../MetaTileEntityPrimitiveBlastFurnace.java | 387 +--------- .../MetaTileEntityPrimitiveWaterPump.java | 21 +- .../electric/MetaTileEntityAssemblyLine.java | 2 +- .../MetaTileEntityDistillationTower.java | 9 +- .../electric/MetaTileEntityFusionReactor.java | 6 +- .../electric/MetaTileEntityMultiFurnace.java | 42 +- .../generator/MetaTileEntityLargeTurbine.java | 4 + .../steam/MetaTileEntitySteamGrinder.java | 8 +- .../multi/steam/MetaTileEntitySteamOven.java | 9 +- .../steam/SteamAlloySmelter.java | 10 +- .../steam/SteamCompressor.java | 10 +- .../steam/SteamExtractor.java | 10 +- .../metatileentities/steam/SteamFurnace.java | 10 +- .../metatileentities/steam/SteamHammer.java | 10 +- .../steam/SteamMacerator.java | 10 +- .../steam/boiler/SteamBoiler.java | 56 +- .../steam/boiler/SteamCoalBoiler.java | 7 +- .../steam/boiler/SteamLavaBoiler.java | 11 +- .../steam/boiler/SteamSolarBoiler.java | 7 +- .../MetaTileEntitySteamHatch.java | 2 +- .../MetaTileEntitySteamItemBus.java | 2 +- .../storage/CachedRecipeData.java | 19 +- .../storage/CraftingRecipeResolver.java | 12 +- .../storage/MetaTileEntityBuffer.java | 134 ++++ .../storage/MetaTileEntityCrate.java | 7 +- .../storage/MetaTileEntityCreativeEnergy.java | 210 +++++ .../storage/MetaTileEntityDrum.java | 30 +- .../storage/MetaTileEntityQuantumChest.java | 51 +- .../storage/MetaTileEntityQuantumTank.java | 78 +- .../storage/MetaTileEntityWorkbench.java | 10 +- .../traits/TraitInfiniteEmitter.java | 141 ---- .../traits/TraitInfiniteEnergy.java | 57 -- .../common/pipelike/cable/BlockCable.java | 48 +- .../common/pipelike/cable/Insulation.java | 7 +- .../common/pipelike/cable/ItemBlockCable.java | 3 +- .../common/pipelike/cable/net/EnergyNet.java | 79 +- .../pipelike/cable/net/EnergyNetHandler.java | 127 +++ .../pipelike/cable/net/EnergyNetWalker.java | 65 ++ .../common/pipelike/cable/net/RoutePath.java | 87 ++- .../cable/tile/CableEnergyContainer.java | 169 ---- .../pipelike/cable/tile/TileEntityCable.java | 59 +- .../pipelike/fluidpipe/BlockFluidPipe.java | 135 ++-- .../pipelike/fluidpipe/FluidPipeType.java | 14 +- .../fluidpipe/ItemBlockFluidPipe.java | 1 + .../fluidpipe/net/FluidNetHandler.java | 318 ++++++++ .../pipelike/fluidpipe/net/FluidNetTank.java | 75 -- .../fluidpipe/net/FluidNetWalker.java | 145 ++++ .../pipelike/fluidpipe/net/FluidPipeNet.java | 190 ++--- .../fluidpipe/net/WorldFluidPipeNet.java | 2 +- .../fluidpipe/tile/FluidPipeFluidHandler.java | 69 -- .../fluidpipe/tile/TileEntityFluidPipe.java | 157 +++- .../tile/TileEntityFluidPipeTickable.java | 62 -- .../pipelike/itempipe/BlockItemPipe.java | 63 +- .../pipelike/itempipe/net/ItemNetHandler.java | 96 ++- .../pipelike/itempipe/net/ItemNetWalker.java | 104 +-- .../itempipe/tile/TileEntityItemPipe.java | 14 - .../tile/TileEntityItemPipeTickable.java | 13 +- .../gregtech/common/render/CableRenderer.java | 40 +- .../common/render/FluidPipeRenderer.java | 38 +- .../common/render/ItemPipeRenderer.java | 64 +- .../common/terminal/app/ThemeSettingApp.java | 156 ++++ .../common/terminal/app/guide/GuideApp.java | 208 +++++ .../terminal/app/guide/ItemGuideApp.java | 98 +++ .../app/guide/MultiBlockGuideApp.java | 46 ++ .../app/guide/SimpleMachineGuideApp.java | 46 ++ .../terminal/app/guide/TutorialGuideApp.java | 30 + .../terminal/app/guide/widget/CardWidget.java | 108 +++ .../app/guide/widget/GuidePageWidget.java | 185 +++++ .../app/guide/widget/GuideWidget.java | 183 +++++ .../app/guide/widget/GuideWidgetGroup.java | 195 +++++ .../app/guide/widget/IGuideWidget.java | 48 ++ .../app/guide/widget/ImageWidget.java | 107 +++ .../app/guide/widget/SlotListWidget.java | 114 +++ .../app/guide/widget/TankListWidget.java | 116 +++ .../app/guide/widget/TextBoxWidget.java | 120 +++ .../app/guideeditor/GuideEditorApp.java | 66 ++ .../guideeditor/widget/GuideConfigEditor.java | 225 ++++++ .../widget/GuidePageEditorWidget.java | 395 ++++++++++ .../configurator/BooleanConfigurator.java | 35 + .../configurator/ColorConfigurator.java | 27 + .../configurator/ConfiguratorWidget.java | 126 +++ .../configurator/FluidStackConfigurator.java | 99 +++ .../configurator/ItemStackConfigurator.java | 101 +++ .../configurator/NumberConfigurator.java | 70 ++ .../configurator/SelectorConfigurator.java | 36 + .../configurator/StringConfigurator.java | 44 ++ .../configurator/TextListConfigurator.java | 44 ++ .../app/recipechart/RecipeChartApp.java | 173 +++++ .../app/recipechart/widget/PhantomWidget.java | 87 +++ .../app/recipechart/widget/RGContainer.java | 204 +++++ .../app/recipechart/widget/RGLine.java | 218 ++++++ .../app/recipechart/widget/RGNode.java | 564 ++++++++++++++ .../terminal/component/ClickComponent.java | 45 ++ .../terminal/component/SearchComponent.java | 114 +++ .../component/setting/GuiTextureSetter.java | 32 + .../terminal/component/setting/ISetting.java | 10 + .../component/setting/IWidgetSettings.java | 7 + .../component/setting/SettingComponent.java | 29 + .../java/gregtech/common/tools/ToolAxe.java | 2 +- .../gregtech/common/tools/ToolCrowbar.java | 2 +- .../java/gregtech/common/tools/ToolFile.java | 2 +- .../gregtech/common/tools/ToolHardHammer.java | 9 +- .../java/gregtech/common/tools/ToolHoe.java | 2 +- .../common/tools/ToolMiningHammer.java | 8 +- .../gregtech/common/tools/ToolPickaxe.java | 2 +- .../java/gregtech/common/tools/ToolSaw.java | 9 +- .../java/gregtech/common/tools/ToolScoop.java | 2 +- .../common/tools/ToolScrewdriver.java | 2 +- .../gregtech/common/tools/ToolShovel.java | 2 +- .../java/gregtech/common/tools/ToolSword.java | 2 +- .../common/tools/ToolUniversalSpade.java | 16 +- .../gregtech/common/tools/ToolWireCutter.java | 2 +- .../gregtech/common/tools/ToolWrench.java | 9 +- .../tools/largedrills/ToolDrillLarge.java | 40 +- .../gregtech/integration/jei/GTJeiPlugin.java | 35 +- .../integration/jei/GTOreCategory.java | 21 +- .../multiblock/infos/AssemblyLineInfo.java | 2 +- .../multiblock/infos/SteamGrinderInfo.java | 2 +- .../jei/multiblock/infos/SteamOvenInfo.java | 2 +- .../jei/recipe/FacadeRegistryPlugin.java | 5 +- .../jei/recipe/GTRecipeWrapper.java | 14 +- .../primitive/CokeOvenRecipeCategory.java | 59 -- .../primitive/CokeOvenRecipeWrapper.java | 53 -- .../jei/recipe/primitive/MaterialTree.java | 123 +++ .../primitive/MaterialTreeCategory.java | 290 +++++++ .../PrimitiveBlastRecipeCategory.java | 55 -- .../PrimitiveBlastRecipeWrapper.java | 57 -- .../primitive/PrimitiveRecipeCategory.java | 1 + .../jei/utils/render/DrawableRegistry.java | 24 + .../theoneprobe/TheOneProbeCompatibility.java | 1 + .../provider/DebugPipeNetInfoProvider.java | 4 +- .../provider/DiodeInfoProvider.java | 39 + .../loaders/dungeon/DungeonLootLoader.java | 151 ++-- .../oreprocessing/OreRecipeHandler.java | 24 +- .../oreprocessing/PipeRecipeHandler.java | 35 + .../oreprocessing/ToolRecipeHandler.java | 6 +- .../oreprocessing/WireRecipeHandler.java | 2 + .../loaders/recipe/AssemblyLineLoader.java | 21 +- .../loaders/recipe/BatteryRecipes.java | 253 ++++-- .../loaders/recipe/CircuitRecipes.java | 6 +- .../loaders/recipe/CraftingComponent.java | 48 +- .../loaders/recipe/CraftingRecipeLoader.java | 5 - .../loaders/recipe/MachineRecipeLoader.java | 83 +- .../loaders/recipe/MetaTileEntityLoader.java | 83 +- .../MetaTileEntityMachineRecipeLoader.java | 289 ++++++- .../recipe/VanillaOverrideRecipes.java | 5 + .../recipe/VanillaStandardRecipes.java | 26 +- .../recipe/chemistry/ChemistryRecipes.java | 31 +- .../recipe/chemistry/DistillationRecipes.java | 36 + .../recipe/chemistry/MixerRecipes.java | 86 +++ .../recipe/chemistry/ReactorRecipes.java | 12 +- .../recipe/chemistry/SeparationRecipes.java | 34 +- .../AnnotatedComponentHandlerLoader.java | 82 ++ .../recipe/component/IComponentHandler.java | 28 + .../blockstates/fluid_pipe_nonuple.json | 17 + .../blockstates/fluid_pipe_quadruple.json | 17 + .../resources/assets/gregtech/lang/en_us.lang | 266 ++++++- .../resources/assets/gregtech/lang/ru_ru.lang | 2 +- .../resources/assets/gregtech/lang/zh_cn.lang | 156 +++- .../material_sets/diamond/plate_double.json | 7 + .../material_sets/emerald/plate_double.json | 7 + .../gem_horizontal/plate_double.json | 7 + .../gem_vertical/plate_double.json | 7 + .../material_sets/lapis/plate_double.json | 6 + .../netherstar/plate_double.json | 7 + .../item/material_sets/opal/plate_double.json | 7 + .../item/material_sets/ruby/plate_double.json | 7 + .../item/metaitems/battery.ev.vanadium/1.json | 6 + .../item/metaitems/battery.ev.vanadium/2.json | 6 + .../item/metaitems/battery.ev.vanadium/3.json | 6 + .../item/metaitems/battery.ev.vanadium/4.json | 6 + .../item/metaitems/battery.ev.vanadium/5.json | 6 + .../item/metaitems/battery.ev.vanadium/6.json | 6 + .../item/metaitems/battery.ev.vanadium/7.json | 6 + .../item/metaitems/battery.ev.vanadium/8.json | 6 + .../item/metaitems/battery.hull.ev.json | 6 + .../item/metaitems/battery.hull.iv.json | 6 + .../item/metaitems/battery.hull.luv.json | 6 + .../item/metaitems/battery.hull.uv.json | 6 + .../item/metaitems/battery.hull.zpm.json | 6 + .../item/metaitems/battery.iv.vanadium/1.json | 6 + .../item/metaitems/battery.iv.vanadium/2.json | 6 + .../item/metaitems/battery.iv.vanadium/3.json | 6 + .../item/metaitems/battery.iv.vanadium/4.json | 6 + .../item/metaitems/battery.iv.vanadium/5.json | 6 + .../item/metaitems/battery.iv.vanadium/6.json | 6 + .../item/metaitems/battery.iv.vanadium/7.json | 6 + .../item/metaitems/battery.iv.vanadium/8.json | 6 + .../metaitems/battery.luv.vanadium/1.json | 6 + .../metaitems/battery.luv.vanadium/2.json | 6 + .../metaitems/battery.luv.vanadium/3.json | 6 + .../metaitems/battery.luv.vanadium/4.json | 6 + .../metaitems/battery.luv.vanadium/5.json | 6 + .../metaitems/battery.luv.vanadium/6.json | 6 + .../metaitems/battery.luv.vanadium/7.json | 6 + .../metaitems/battery.luv.vanadium/8.json | 6 + .../item/metaitems/battery.su.hv.mercury.json | 6 - .../metaitems/battery.su.hv.sulfuricacid.json | 6 - .../item/metaitems/battery.su.lv.mercury.json | 6 - .../metaitems/battery.su.lv.sulfuricacid.json | 6 - .../item/metaitems/battery.su.mv.mercury.json | 6 - .../metaitems/battery.su.mv.sulfuricacid.json | 6 - .../metaitems/battery.uv.naquadria/1.json | 6 + .../metaitems/battery.uv.naquadria/2.json | 6 + .../metaitems/battery.uv.naquadria/3.json | 6 + .../metaitems/battery.uv.naquadria/4.json | 6 + .../metaitems/battery.uv.naquadria/5.json | 6 + .../metaitems/battery.uv.naquadria/6.json | 6 + .../metaitems/battery.uv.naquadria/7.json | 6 + .../metaitems/battery.uv.naquadria/8.json | 6 + .../metaitems/battery.zpm.naquadria/1.json | 6 + .../metaitems/battery.zpm.naquadria/2.json | 6 + .../metaitems/battery.zpm.naquadria/3.json | 6 + .../metaitems/battery.zpm.naquadria/4.json | 6 + .../metaitems/battery.zpm.naquadria/5.json | 6 + .../metaitems/battery.zpm.naquadria/6.json | 6 + .../metaitems/battery.zpm.naquadria/7.json | 6 + .../metaitems/battery.zpm.naquadria/8.json | 6 + .../item/metaitems/cover.infinite_water.json | 6 + .../metaitems/energy_field_projector.json | 6 - .../models/item/metaitems/terminal.json | 6 + .../terminal/guide/items/en_us/test.json | 33 + .../terminal/guide/items/zh_cn/test.json | 33 + .../en_us/steam_boiler_coal_bronze.json | 33 + .../en_us/electric_blast_furnace.json | 33 + .../tutorials/en_us/api_0_guidepage.json | 148 ++++ .../guide/tutorials/en_us/api_1_widget.json | 304 ++++++++ .../guide/tutorials/en_us/api_2_textbox.json | 256 +++++++ .../guide/tutorials/en_us/api_3_image.json | 207 +++++ .../blocks/cover/overlay_fluid_filter.png | Bin 0 -> 287 bytes .../blocks/cover/overlay_infinite_water.png | Bin 0 -> 2661 bytes .../cover/overlay_infinite_water.png.mcmeta | 5 + .../machines/gas_collector/overlay_back.png | Bin 0 -> 209 bytes .../gas_collector/overlay_back_active.png | Bin 0 -> 209 bytes .../machines/gas_collector/overlay_bottom.png | Bin 0 -> 279 bytes .../gas_collector/overlay_bottom_active.png | Bin 0 -> 279 bytes .../machines/gas_collector/overlay_front.png | Bin 0 -> 209 bytes .../gas_collector/overlay_front_active.png | Bin 0 -> 209 bytes .../machines/gas_collector/overlay_side.png | Bin 0 -> 209 bytes .../gas_collector/overlay_side_active.png | Bin 0 -> 209 bytes .../machines/gas_collector/overlay_top.png | Bin 0 -> 279 bytes .../gas_collector/overlay_top_active.png | Bin 0 -> 279 bytes .../blocks/overlay/machine/overlay_buffer.png | Bin 0 -> 443 bytes .../overlay/machine/overlay_energy_in_hi.png | Bin 0 -> 1147 bytes .../machine/overlay_energy_in_ultra.png | Bin 0 -> 455 bytes .../overlay/machine/overlay_energy_out_hi.png | Bin 0 -> 1147 bytes .../machine/overlay_energy_out_ultra.png | Bin 0 -> 1665 bytes .../blocks/overlay/machine/overlay_filter.png | Bin 0 -> 279 bytes .../gregtech/textures/gui/arrows/2d12.png | Bin 0 -> 115 bytes .../gregtech/textures/gui/arrows/2d16.png | Bin 0 -> 115 bytes .../gregtech/textures/gui/arrows/2r16d37.png | Bin 0 -> 148 bytes .../gregtech/textures/gui/arrows/d14.png | Bin 0 -> 106 bytes .../gregtech/textures/gui/arrows/d7r25u6.png | Bin 0 -> 119 bytes .../gregtech/textures/gui/arrows/d7r50d7.png | Bin 0 -> 133 bytes .../gregtech/textures/gui/arrows/d7r50u6.png | Bin 0 -> 131 bytes .../gregtech/textures/gui/arrows/d7r75d7.png | Bin 0 -> 149 bytes .../gregtech/textures/gui/arrows/d7r75u6.png | Bin 0 -> 140 bytes .../textures/gui/arrows/d7r87u22r4.png | Bin 0 -> 189 bytes .../textures/gui/arrows/d7r87u46r4.png | Bin 0 -> 241 bytes .../gregtech/textures/gui/arrows/l7.png | Bin 0 -> 108 bytes .../gregtech/textures/gui/arrows/r3d16r4.png | Bin 0 -> 116 bytes .../gregtech/textures/gui/arrows/r3d26r4.png | Bin 0 -> 118 bytes .../gregtech/textures/gui/arrows/r3u15r4.png | Bin 0 -> 121 bytes .../gregtech/textures/gui/arrows/r3u32r4.png | Bin 0 -> 125 bytes .../gregtech/textures/gui/arrows/r3u57r4.png | Bin 0 -> 129 bytes .../gregtech/textures/gui/arrows/r7.png | Bin 0 -> 108 bytes .../gregtech/textures/gui/arrows/u12.png | Bin 0 -> 108 bytes .../gregtech/textures/gui/arrows/u7r25d6.png | Bin 0 -> 115 bytes .../gregtech/textures/gui/arrows/u7r50d6.png | Bin 0 -> 124 bytes .../gregtech/textures/gui/arrows/u7r50u5.png | Bin 0 -> 143 bytes .../gregtech/textures/gui/arrows/u7r75d6.png | Bin 0 -> 132 bytes .../gregtech/textures/gui/arrows/u7r75u5.png | Bin 0 -> 152 bytes .../textures/gui/arrows/u7r87d15r4.png | Bin 0 -> 164 bytes .../textures/gui/arrows/u7r87u8r4.png | Bin 0 -> 171 bytes .../progress_bar/progress_bar_coke_oven.png | Bin 0 -> 2028 bytes .../progress_bar_distillation_tower.png | Bin 0 -> 2069 bytes .../progress_bar_gas_collector.png | Bin 0 -> 2131 bytes .../gui/terminal/guide_editor/icon.png | Bin 0 -> 32504 bytes .../icon/Communicate/calendar_hover.png | Bin 0 -> 846 bytes .../icon/Communicate/calendar_normal.png | Bin 0 -> 1382 bytes .../icon/Communicate/clock1_hover.png | Bin 0 -> 917 bytes .../icon/Communicate/clock1_normal.png | Bin 0 -> 1774 bytes .../icon/Communicate/clock2_hover.png | Bin 0 -> 712 bytes .../icon/Communicate/clock2_normal.png | Bin 0 -> 1114 bytes .../icon/Communicate/gmail-copy_hover.png | Bin 0 -> 817 bytes .../icon/Communicate/gmail-copy_normal.png | Bin 0 -> 1393 bytes .../icon/Communicate/gmail2-copy_hover.png | Bin 0 -> 860 bytes .../icon/Communicate/gmail2-copy_normal.png | Bin 0 -> 1427 bytes .../icon/Communicate/kontakts_hover.png | Bin 0 -> 778 bytes .../icon/Communicate/kontakts_normal.png | Bin 0 -> 1236 bytes .../terminal/icon/Communicate/mail1_hover.png | Bin 0 -> 838 bytes .../icon/Communicate/mail1_normal.png | Bin 0 -> 1429 bytes .../terminal/icon/Communicate/mail2_hover.png | Bin 0 -> 760 bytes .../icon/Communicate/mail2_normal.png | Bin 0 -> 1230 bytes .../icon/Communicate/mail_open_hover.png | Bin 0 -> 867 bytes .../icon/Communicate/mail_open_normal.png | Bin 0 -> 1398 bytes .../icon/Communicate/mail_sent_hover.png | Bin 0 -> 884 bytes .../icon/Communicate/mail_sent_normal.png | Bin 0 -> 1526 bytes .../terminal/icon/Communicate/msg2_hover.png | Bin 0 -> 840 bytes .../terminal/icon/Communicate/msg2_normal.png | Bin 0 -> 1376 bytes .../terminal/icon/Communicate/msg3_hover.png | Bin 0 -> 893 bytes .../terminal/icon/Communicate/msg3_normal.png | Bin 0 -> 1487 bytes .../terminal/icon/Communicate/msg_hover.png | Bin 0 -> 784 bytes .../terminal/icon/Communicate/msg_normal.png | Bin 0 -> 1211 bytes .../terminal/icon/Communicate/note1_hover.png | Bin 0 -> 899 bytes .../icon/Communicate/note1_normal.png | Bin 0 -> 1471 bytes .../terminal/icon/Communicate/note2_hover.png | Bin 0 -> 920 bytes .../icon/Communicate/note2_normal.png | Bin 0 -> 1552 bytes .../terminal/icon/Communicate/pen_hover.png | Bin 0 -> 759 bytes .../terminal/icon/Communicate/pen_normal.png | Bin 0 -> 1262 bytes .../terminal/icon/Communicate/phone_hover.png | Bin 0 -> 824 bytes .../icon/Communicate/phone_normal.png | Bin 0 -> 1350 bytes .../icon/Communicate/profiles_hover.png | Bin 0 -> 812 bytes .../icon/Communicate/profiles_normal.png | Bin 0 -> 1317 bytes .../terminal/icon/Communicate/skype_hover.png | Bin 0 -> 943 bytes .../icon/Communicate/skype_normal.png | Bin 0 -> 1616 bytes .../terminal/icon/Communicate/tasks_hover.png | Bin 0 -> 870 bytes .../icon/Communicate/tasks_normal.png | Bin 0 -> 1427 bytes .../icon/Communicate/voicemail-12_hover.png | Bin 0 -> 822 bytes .../icon/Communicate/voicemail-12_normal.png | Bin 0 -> 1403 bytes .../icon/Communicate/voicemaill_hover.png | Bin 0 -> 816 bytes .../icon/Communicate/voicemaill_normal.png | Bin 0 -> 1358 bytes .../gui/terminal/icon/Media/Camera_hover.png | Bin 0 -> 855 bytes .../gui/terminal/icon/Media/Camera_normal.png | Bin 0 -> 1390 bytes .../icon/Media/Champions_League_hover.png | Bin 0 -> 1119 bytes .../icon/Media/Champions_League_normal.png | Bin 0 -> 1945 bytes .../gui/terminal/icon/Media/TV2_hover.png | Bin 0 -> 1001 bytes .../gui/terminal/icon/Media/TV2_normal.png | Bin 0 -> 1623 bytes .../gui/terminal/icon/Media/TV_hover.png | Bin 0 -> 959 bytes .../gui/terminal/icon/Media/TV_normal.png | Bin 0 -> 1634 bytes .../icon/Media/VideoRecorder_hover.png | Bin 0 -> 808 bytes .../icon/Media/VideoRecorder_normal.png | Bin 0 -> 1359 bytes .../gui/terminal/icon/Media/WMP_hover.png | Bin 0 -> 767 bytes .../gui/terminal/icon/Media/WMP_normal.png | Bin 0 -> 1219 bytes .../gui/terminal/icon/Media/YT1_hover.png | Bin 0 -> 853 bytes .../gui/terminal/icon/Media/YT1_normal.png | Bin 0 -> 1473 bytes .../gui/terminal/icon/Media/YT2_hover.png | Bin 0 -> 813 bytes .../gui/terminal/icon/Media/YT2_normal.png | Bin 0 -> 1295 bytes .../terminal/icon/Media/blank-cd_hover.png | Bin 0 -> 874 bytes .../terminal/icon/Media/blank-cd_normal.png | Bin 0 -> 1495 bytes .../gui/terminal/icon/Media/camera3_hover.png | Bin 0 -> 830 bytes .../terminal/icon/Media/camera3_normal.png | Bin 0 -> 1402 bytes .../gui/terminal/icon/Media/ea_hover.png | Bin 0 -> 980 bytes .../gui/terminal/icon/Media/ea_normal.png | Bin 0 -> 1697 bytes .../gui/terminal/icon/Media/iTunes_hover.png | Bin 0 -> 892 bytes .../gui/terminal/icon/Media/iTunes_normal.png | Bin 0 -> 1440 bytes .../terminal/icon/Media/landskape_hover.png | Bin 0 -> 871 bytes .../terminal/icon/Media/landskape_normal.png | Bin 0 -> 1447 bytes .../gui/terminal/icon/Media/lastfm_hover.png | Bin 0 -> 812 bytes .../gui/terminal/icon/Media/lastfm_normal.png | Bin 0 -> 1344 bytes .../gui/terminal/icon/Media/listen_hover.png | Bin 0 -> 935 bytes .../gui/terminal/icon/Media/listen_normal.png | Bin 0 -> 1574 bytes .../gui/terminal/icon/Media/macro_hover.png | Bin 0 -> 885 bytes .../gui/terminal/icon/Media/macro_normal.png | Bin 0 -> 1489 bytes .../gui/terminal/icon/Media/photo_hover.png | Bin 0 -> 859 bytes .../gui/terminal/icon/Media/photo_normal.png | Bin 0 -> 1373 bytes .../gui/terminal/icon/Media/radio_hover.png | Bin 0 -> 918 bytes .../gui/terminal/icon/Media/radio_normal.png | Bin 0 -> 1585 bytes .../gui/terminal/icon/Media/sound2_hover.png | Bin 0 -> 966 bytes .../gui/terminal/icon/Media/sound2_normal.png | Bin 0 -> 1622 bytes .../gui/terminal/icon/Media/sound_hover.png | Bin 0 -> 948 bytes .../gui/terminal/icon/Media/sound_normal.png | Bin 0 -> 1586 bytes .../gui/terminal/icon/Media/touch_hover.png | Bin 0 -> 961 bytes .../gui/terminal/icon/Media/touch_normal.png | Bin 0 -> 1667 bytes .../terminal/icon/Media/video_rec_hover.png | Bin 0 -> 904 bytes .../terminal/icon/Media/video_rec_normal.png | Bin 0 -> 1440 bytes .../gui/terminal/icon/Media/viewer_hover.png | Bin 0 -> 906 bytes .../gui/terminal/icon/Media/viewer_normal.png | Bin 0 -> 1535 bytes .../gui/terminal/icon/Media/walkman_hover.png | Bin 0 -> 883 bytes .../terminal/icon/Media/walkman_normal.png | Bin 0 -> 1537 bytes .../gui/terminal/icon/Media/winamp_hover.png | Bin 0 -> 814 bytes .../gui/terminal/icon/Media/winamp_normal.png | Bin 0 -> 1324 bytes .../gui/terminal/icon/Media/zune1_hover.png | Bin 0 -> 1013 bytes .../gui/terminal/icon/Media/zune1_normal.png | Bin 0 -> 1750 bytes .../gui/terminal/icon/Media/zune2_hover.png | Bin 0 -> 824 bytes .../gui/terminal/icon/Media/zune2_normal.png | Bin 0 -> 1371 bytes .../gui/terminal/icon/Media/zune3_hover.png | Bin 0 -> 814 bytes .../gui/terminal/icon/Media/zune3_normal.png | Bin 0 -> 1385 bytes .../gui/terminal/icon/Navigate/Bing_hover.png | Bin 0 -> 873 bytes .../terminal/icon/Navigate/Bing_normal.png | Bin 0 -> 1460 bytes .../terminal/icon/Navigate/COMPAS2_hover.png | Bin 0 -> 974 bytes .../terminal/icon/Navigate/COMPAS2_normal.png | Bin 0 -> 1674 bytes .../icon/Navigate/Canada_flag_hover.png | Bin 0 -> 884 bytes .../icon/Navigate/Canada_flag_normal.png | Bin 0 -> 1519 bytes .../gui/terminal/icon/Navigate/EAAA_hover.png | Bin 0 -> 1031 bytes .../terminal/icon/Navigate/EAAA_normal.png | Bin 0 -> 1758 bytes .../gui/terminal/icon/Navigate/EU_hover.png | Bin 0 -> 1029 bytes .../gui/terminal/icon/Navigate/EU_normal.png | Bin 0 -> 1770 bytes .../gui/terminal/icon/Navigate/NSA_hover.png | Bin 0 -> 975 bytes .../gui/terminal/icon/Navigate/NSA_normal.png | Bin 0 -> 1630 bytes .../terminal/icon/Navigate/Navteq1_hover.png | Bin 0 -> 860 bytes .../terminal/icon/Navigate/Navteq1_normal.png | Bin 0 -> 1450 bytes .../gui/terminal/icon/Navigate/POI2_hover.png | Bin 0 -> 883 bytes .../terminal/icon/Navigate/POI2_normal.png | Bin 0 -> 1422 bytes .../icon/Navigate/Sattelite_hover.png | Bin 0 -> 910 bytes .../icon/Navigate/Sattelite_normal.png | Bin 0 -> 1579 bytes .../terminal/icon/Navigate/compas1_hover.png | Bin 0 -> 1020 bytes .../terminal/icon/Navigate/compas1_normal.png | Bin 0 -> 1844 bytes .../terminal/icon/Navigate/compas3_hover.png | Bin 0 -> 1003 bytes .../terminal/icon/Navigate/compas3_normal.png | Bin 0 -> 1825 bytes .../terminal/icon/Navigate/gmaps_hover.png | Bin 0 -> 885 bytes .../terminal/icon/Navigate/gmaps_normal.png | Bin 0 -> 1487 bytes .../icon/Navigate/navigation_hover.png | Bin 0 -> 801 bytes .../icon/Navigate/navigation_normal.png | Bin 0 -> 1283 bytes .../terminal/icon/Navigate/navteq_hover.png | Bin 0 -> 789 bytes .../terminal/icon/Navigate/navteq_normal.png | Bin 0 -> 1298 bytes .../gui/terminal/icon/Navigate/path_hover.png | Bin 0 -> 870 bytes .../terminal/icon/Navigate/path_normal.png | Bin 0 -> 1404 bytes .../gui/terminal/icon/Navigate/poi_hover.png | Bin 0 -> 746 bytes .../gui/terminal/icon/Navigate/poi_normal.png | Bin 0 -> 1203 bytes .../terminal/icon/Navigate/world1_hover.png | Bin 0 -> 918 bytes .../terminal/icon/Navigate/world1_normal.png | Bin 0 -> 1591 bytes .../terminal/icon/Navigate/world_hover.png | Bin 0 -> 1063 bytes .../terminal/icon/Navigate/world_normal.png | Bin 0 -> 1841 bytes .../gui/terminal/icon/Network/BT2_hover.png | Bin 0 -> 856 bytes .../gui/terminal/icon/Network/BT2_normal.png | Bin 0 -> 1457 bytes .../terminal/icon/Network/Chrome_hover.png | Bin 0 -> 974 bytes .../terminal/icon/Network/Chrome_normal.png | Bin 0 -> 1728 bytes .../terminal/icon/Network/Firefox_hover.png | Bin 0 -> 988 bytes .../terminal/icon/Network/Firefox_normal.png | Bin 0 -> 1715 bytes .../gui/terminal/icon/Network/Hand_hover.png | Bin 0 -> 1011 bytes .../gui/terminal/icon/Network/Hand_normal.png | Bin 0 -> 1663 bytes .../gui/terminal/icon/Network/USB1_hover.png | Bin 0 -> 852 bytes .../gui/terminal/icon/Network/USB1_normal.png | Bin 0 -> 1396 bytes .../gui/terminal/icon/Network/att2_hover.png | Bin 0 -> 828 bytes .../gui/terminal/icon/Network/att2_normal.png | Bin 0 -> 1354 bytes .../gui/terminal/icon/Network/att_hover.png | Bin 0 -> 853 bytes .../gui/terminal/icon/Network/att_normal.png | Bin 0 -> 1483 bytes .../gui/terminal/icon/Network/bt_hover.png | Bin 0 -> 974 bytes .../gui/terminal/icon/Network/bt_normal.png | Bin 0 -> 1602 bytes .../terminal/icon/Network/facebook2_hover.png | Bin 0 -> 803 bytes .../icon/Network/facebook2_normal.png | Bin 0 -> 1329 bytes .../terminal/icon/Network/facebook_hover.png | Bin 0 -> 814 bytes .../terminal/icon/Network/facebook_normal.png | Bin 0 -> 1305 bytes .../terminal/icon/Network/firefox2_hover.png | Bin 0 -> 1019 bytes .../terminal/icon/Network/firefox2_normal.png | Bin 0 -> 1759 bytes .../terminal/icon/Network/g-google_hover.png | Bin 0 -> 969 bytes .../terminal/icon/Network/g-google_normal.png | Bin 0 -> 1585 bytes .../terminal/icon/Network/globul_hover.png | Bin 0 -> 849 bytes .../terminal/icon/Network/globul_normal.png | Bin 0 -> 1411 bytes .../terminal/icon/Network/gmail2_hover.png | Bin 0 -> 854 bytes .../terminal/icon/Network/gmail2_normal.png | Bin 0 -> 1436 bytes .../gui/terminal/icon/Network/gmail_hover.png | Bin 0 -> 828 bytes .../terminal/icon/Network/gmail_normal.png | Bin 0 -> 1408 bytes .../terminal/icon/Network/google_hover.png | Bin 0 -> 851 bytes .../terminal/icon/Network/google_normal.png | Bin 0 -> 1418 bytes .../gui/terminal/icon/Network/ie_hover.png | Bin 0 -> 984 bytes .../gui/terminal/icon/Network/ie_normal.png | Bin 0 -> 1666 bytes .../gui/terminal/icon/Network/mtel_hover.png | Bin 0 -> 834 bytes .../gui/terminal/icon/Network/mtel_normal.png | Bin 0 -> 1376 bytes .../gui/terminal/icon/Network/net3_hover.png | Bin 0 -> 922 bytes .../gui/terminal/icon/Network/net3_normal.png | Bin 0 -> 1601 bytes .../gui/terminal/icon/Network/net_hover.png | Bin 0 -> 1121 bytes .../gui/terminal/icon/Network/net_normal.png | Bin 0 -> 1918 bytes .../terminal/icon/Network/netw_conn_hover.png | Bin 0 -> 986 bytes .../icon/Network/netw_conn_normal.png | Bin 0 -> 1713 bytes .../gui/terminal/icon/Network/opera_hover.png | Bin 0 -> 914 bytes .../terminal/icon/Network/opera_normal.png | Bin 0 -> 1572 bytes .../gui/terminal/icon/Network/rss_hover.png | Bin 0 -> 921 bytes .../gui/terminal/icon/Network/rss_normal.png | Bin 0 -> 1567 bytes .../terminal/icon/Network/search_hover.png | Bin 0 -> 943 bytes .../terminal/icon/Network/search_normal.png | Bin 0 -> 1515 bytes .../terminal/icon/Network/signal1_hover.png | Bin 0 -> 797 bytes .../terminal/icon/Network/signal1_normal.png | Bin 0 -> 1299 bytes .../terminal/icon/Network/signal2_hover.png | Bin 0 -> 954 bytes .../terminal/icon/Network/signal2_normal.png | Bin 0 -> 1612 bytes .../terminal/icon/Network/signal4_hover.png | Bin 0 -> 960 bytes .../terminal/icon/Network/signal4_normal.png | Bin 0 -> 1600 bytes .../terminal/icon/Network/signal_hover.png | Bin 0 -> 951 bytes .../terminal/icon/Network/signal_normal.png | Bin 0 -> 1550 bytes .../terminal/icon/Network/skype1_hover.png | Bin 0 -> 954 bytes .../terminal/icon/Network/skype1_normal.png | Bin 0 -> 1637 bytes .../terminal/icon/Network/skype2_hover.png | Bin 0 -> 1003 bytes .../terminal/icon/Network/skype2_normal.png | Bin 0 -> 1718 bytes .../gui/terminal/icon/Network/t-m_hover.png | Bin 0 -> 757 bytes .../gui/terminal/icon/Network/t-m_normal.png | Bin 0 -> 1253 bytes .../terminal/icon/Network/twitter1_hover.png | Bin 0 -> 795 bytes .../terminal/icon/Network/twitter1_normal.png | Bin 0 -> 1347 bytes .../terminal/icon/Network/twitter2_hover.png | Bin 0 -> 776 bytes .../terminal/icon/Network/twitter2_normal.png | Bin 0 -> 1291 bytes .../terminal/icon/Network/twitter3_hover.png | Bin 0 -> 924 bytes .../terminal/icon/Network/twitter3_normal.png | Bin 0 -> 1515 bytes .../terminal/icon/Network/verizon_hover.png | Bin 0 -> 774 bytes .../terminal/icon/Network/verizon_normal.png | Bin 0 -> 1274 bytes .../terminal/icon/Network/vivacom_hover.png | Bin 0 -> 735 bytes .../terminal/icon/Network/vivacom_normal.png | Bin 0 -> 1202 bytes .../terminal/icon/Network/vodafone1_hover.png | Bin 0 -> 840 bytes .../icon/Network/vodafone1_normal.png | Bin 0 -> 1429 bytes .../terminal/icon/Network/vodafone2_hover.png | Bin 0 -> 749 bytes .../icon/Network/vodafone2_normal.png | Bin 0 -> 1223 bytes .../terminal/icon/Network/vodafone3_hover.png | Bin 0 -> 903 bytes .../icon/Network/vodafone3_normal.png | Bin 0 -> 1604 bytes .../gui/terminal/icon/Network/wi-fi_hover.png | Bin 0 -> 856 bytes .../terminal/icon/Network/wi-fi_normal.png | Bin 0 -> 1450 bytes .../icon/Network/wifi-router_hover.png | Bin 0 -> 1025 bytes .../icon/Network/wifi-router_normal.png | Bin 0 -> 1724 bytes .../gui/terminal/icon/Other/Favs1_hover.png | Bin 0 -> 837 bytes .../gui/terminal/icon/Other/Favs1_normal.png | Bin 0 -> 1381 bytes .../gui/terminal/icon/Other/LIBRARY_hover.png | Bin 0 -> 795 bytes .../terminal/icon/Other/LIBRARY_normal.png | Bin 0 -> 1306 bytes .../gui/terminal/icon/Other/Llama_hover.png | Bin 0 -> 855 bytes .../gui/terminal/icon/Other/Llama_normal.png | Bin 0 -> 1375 bytes .../icon/Other/MB_0027_LIBRARY_hover.png | Bin 0 -> 769 bytes .../icon/Other/MB_0027_LIBRARY_normal.png | Bin 0 -> 1261 bytes .../gui/terminal/icon/Other/Marvel_hover.png | Bin 0 -> 910 bytes .../gui/terminal/icon/Other/Marvel_normal.png | Bin 0 -> 1541 bytes .../terminal/icon/Other/Translate_hover.png | Bin 0 -> 1036 bytes .../terminal/icon/Other/Translate_normal.png | Bin 0 -> 1947 bytes .../terminal/icon/Other/Visitors_hover.png | Bin 0 -> 911 bytes .../terminal/icon/Other/Visitors_normal.png | Bin 0 -> 1626 bytes .../gui/terminal/icon/Other/apple_hover.png | Bin 0 -> 902 bytes .../gui/terminal/icon/Other/apple_normal.png | Bin 0 -> 1452 bytes .../gui/terminal/icon/Other/b_hover.png | Bin 0 -> 847 bytes .../gui/terminal/icon/Other/b_normal.png | Bin 0 -> 1367 bytes .../gui/terminal/icon/Other/book_hover.png | Bin 0 -> 941 bytes .../gui/terminal/icon/Other/book_normal.png | Bin 0 -> 1567 bytes .../terminal/icon/Other/calculator_hover.png | Bin 0 -> 875 bytes .../terminal/icon/Other/calculator_normal.png | Bin 0 -> 1437 bytes .../gui/terminal/icon/Other/cloud_hover.png | Bin 0 -> 886 bytes .../gui/terminal/icon/Other/cloud_normal.png | Bin 0 -> 1481 bytes .../terminal/icon/Other/convertor_hover.png | Bin 0 -> 1035 bytes .../terminal/icon/Other/convertor_normal.png | Bin 0 -> 1923 bytes .../icon/Other/currency-e-d_hover.png | Bin 0 -> 1042 bytes .../icon/Other/currency-e-d_normal.png | Bin 0 -> 1944 bytes .../icon/Other/currency-e-j_hover.png | Bin 0 -> 1047 bytes .../icon/Other/currency-e-j_normal.png | Bin 0 -> 1928 bytes .../icon/Other/currency-e-p_hover.png | Bin 0 -> 1048 bytes .../icon/Other/currency-e-p_normal.png | Bin 0 -> 1920 bytes .../gui/terminal/icon/Other/da1_hover.png | Bin 0 -> 851 bytes .../gui/terminal/icon/Other/da1_normal.png | Bin 0 -> 1403 bytes .../gui/terminal/icon/Other/da2_hover.png | Bin 0 -> 893 bytes .../gui/terminal/icon/Other/da2_normal.png | Bin 0 -> 1500 bytes .../gui/terminal/icon/Other/favs2_hover.png | Bin 0 -> 882 bytes .../gui/terminal/icon/Other/favs2_normal.png | Bin 0 -> 1465 bytes .../gui/terminal/icon/Other/iBOOKS_hover.png | Bin 0 -> 767 bytes .../gui/terminal/icon/Other/iBOOKS_normal.png | Bin 0 -> 1244 bytes .../gui/terminal/icon/Other/java_hover.png | Bin 0 -> 941 bytes .../gui/terminal/icon/Other/java_normal.png | Bin 0 -> 1505 bytes .../gui/terminal/icon/Other/light_hover.png | Bin 0 -> 818 bytes .../gui/terminal/icon/Other/light_normal.png | Bin 0 -> 1358 bytes .../gui/terminal/icon/Other/pin_hover.png | Bin 0 -> 846 bytes .../gui/terminal/icon/Other/pin_normal.png | Bin 0 -> 1407 bytes .../gui/terminal/icon/Other/pliok2_hover.png | Bin 0 -> 1006 bytes .../gui/terminal/icon/Other/pliok2_normal.png | Bin 0 -> 1704 bytes .../gui/terminal/icon/Other/pliok_hover.png | Bin 0 -> 949 bytes .../gui/terminal/icon/Other/pliok_normal.png | Bin 0 -> 1552 bytes .../gui/terminal/icon/Other/plus_hover.png | Bin 0 -> 805 bytes .../gui/terminal/icon/Other/plus_normal.png | Bin 0 -> 1290 bytes .../gui/terminal/icon/Other/range_hover.png | Bin 0 -> 1014 bytes .../gui/terminal/icon/Other/range_normal.png | Bin 0 -> 1756 bytes .../gui/terminal/icon/Other/sim_hover.png | Bin 0 -> 675 bytes .../gui/terminal/icon/Other/sim_normal.png | Bin 0 -> 1044 bytes .../terminal/icon/Other/weather1_hover.png | Bin 0 -> 852 bytes .../terminal/icon/Other/weather1_normal.png | Bin 0 -> 1402 bytes .../gui/terminal/icon/Suite/3dmax_hover.png | Bin 0 -> 1037 bytes .../gui/terminal/icon/Suite/3dmax_normal.png | Bin 0 -> 1764 bytes .../gui/terminal/icon/Suite/AE_hover.png | Bin 0 -> 923 bytes .../gui/terminal/icon/Suite/AE_normal.png | Bin 0 -> 1578 bytes .../gui/terminal/icon/Suite/AIR_hover.png | Bin 0 -> 939 bytes .../gui/terminal/icon/Suite/AIR_normal.png | Bin 0 -> 1629 bytes .../gui/terminal/icon/Suite/Ai_hover.png | Bin 0 -> 898 bytes .../gui/terminal/icon/Suite/Ai_normal.png | Bin 0 -> 1484 bytes .../gui/terminal/icon/Suite/Apps_hover.png | Bin 0 -> 834 bytes .../gui/terminal/icon/Suite/Apps_normal.png | Bin 0 -> 1362 bytes .../gui/terminal/icon/Suite/Autocad_hover.png | Bin 0 -> 897 bytes .../terminal/icon/Suite/Autocad_normal.png | Bin 0 -> 1524 bytes .../gui/terminal/icon/Suite/Br_hover.png | Bin 0 -> 858 bytes .../gui/terminal/icon/Suite/Br_normal.png | Bin 0 -> 1425 bytes .../gui/terminal/icon/Suite/Dw_hover.png | Bin 0 -> 917 bytes .../gui/terminal/icon/Suite/Dw_normal.png | Bin 0 -> 1534 bytes .../gui/terminal/icon/Suite/Excel_hover.png | Bin 0 -> 974 bytes .../gui/terminal/icon/Suite/Excel_normal.png | Bin 0 -> 1681 bytes .../gui/terminal/icon/Suite/Fl_hover.png | Bin 0 -> 832 bytes .../gui/terminal/icon/Suite/Fl_normal.png | Bin 0 -> 1314 bytes .../gui/terminal/icon/Suite/Flash_hover.png | Bin 0 -> 865 bytes .../gui/terminal/icon/Suite/Flash_normal.png | Bin 0 -> 1395 bytes .../gui/terminal/icon/Suite/Fw_hover.png | Bin 0 -> 899 bytes .../gui/terminal/icon/Suite/Fw_normal.png | Bin 0 -> 1523 bytes .../gui/terminal/icon/Suite/Fx_hover.png | Bin 0 -> 887 bytes .../gui/terminal/icon/Suite/Fx_normal.png | Bin 0 -> 1462 bytes .../gui/terminal/icon/Suite/IC_hover.png | Bin 0 -> 819 bytes .../gui/terminal/icon/Suite/IC_normal.png | Bin 0 -> 1350 bytes .../gui/terminal/icon/Suite/ID_hover.png | Bin 0 -> 812 bytes .../gui/terminal/icon/Suite/ID_normal.png | Bin 0 -> 1341 bytes .../gui/terminal/icon/Suite/LR_hover.png | Bin 0 -> 830 bytes .../gui/terminal/icon/Suite/LR_normal.png | Bin 0 -> 1376 bytes .../gui/terminal/icon/Suite/Office1_hover.png | Bin 0 -> 752 bytes .../terminal/icon/Suite/Office1_normal.png | Bin 0 -> 1205 bytes .../terminal/icon/Suite/Office2010_hover.png | Bin 0 -> 762 bytes .../terminal/icon/Suite/Office2010_normal.png | Bin 0 -> 1224 bytes .../terminal/icon/Suite/One-Note_hover.png | Bin 0 -> 946 bytes .../terminal/icon/Suite/One-Note_normal.png | Bin 0 -> 1604 bytes .../gui/terminal/icon/Suite/Outlook_hover.png | Bin 0 -> 1019 bytes .../terminal/icon/Suite/Outlook_normal.png | Bin 0 -> 1797 bytes .../terminal/icon/Suite/Power-Point_hover.png | Bin 0 -> 903 bytes .../icon/Suite/Power-Point_normal.png | Bin 0 -> 1478 bytes .../gui/terminal/icon/Suite/Ps_hover.png | Bin 0 -> 874 bytes .../gui/terminal/icon/Suite/Ps_normal.png | Bin 0 -> 1469 bytes .../gui/terminal/icon/Suite/Sb_hover.png | Bin 0 -> 946 bytes .../gui/terminal/icon/Suite/Sb_normal.png | Bin 0 -> 1616 bytes .../gui/terminal/icon/Suite/Word_hover.png | Bin 0 -> 975 bytes .../gui/terminal/icon/Suite/Word_normal.png | Bin 0 -> 1670 bytes .../icon/Suite/adobe-acrobat_hover.png | Bin 0 -> 843 bytes .../icon/Suite/adobe-acrobat_normal.png | Bin 0 -> 1362 bytes .../terminal/icon/Suite/android2_hover.png | Bin 0 -> 919 bytes .../terminal/icon/Suite/android2_normal.png | Bin 0 -> 1541 bytes .../gui/terminal/icon/Suite/android_hover.png | Bin 0 -> 795 bytes .../terminal/icon/Suite/android_normal.png | Bin 0 -> 1282 bytes .../gui/terminal/icon/Suite/office_hover.png | Bin 0 -> 932 bytes .../gui/terminal/icon/Suite/office_normal.png | Bin 0 -> 1587 bytes .../terminal/icon/Suite/programs_hover.png | Bin 0 -> 925 bytes .../terminal/icon/Suite/programs_normal.png | Bin 0 -> 1580 bytes .../gui/terminal/icon/Suite/ps.com_hover.png | Bin 0 -> 911 bytes .../gui/terminal/icon/Suite/ps.com_normal.png | Bin 0 -> 1497 bytes .../terminal/icon/Suite/smartbuble_hover.png | Bin 0 -> 847 bytes .../terminal/icon/Suite/smartbuble_normal.png | Bin 0 -> 1387 bytes .../gui/terminal/icon/System/3D_hover.png | Bin 0 -> 978 bytes .../gui/terminal/icon/System/3D_normal.png | Bin 0 -> 1652 bytes .../terminal/icon/System/APP-info_hover.png | Bin 0 -> 988 bytes .../terminal/icon/System/APP-info_normal.png | Bin 0 -> 1693 bytes .../gui/terminal/icon/System/Base_hover.png | Bin 0 -> 752 bytes .../gui/terminal/icon/System/Base_normal.png | Bin 0 -> 1155 bytes .../terminal/icon/System/Computer_hover.png | Bin 0 -> 776 bytes .../terminal/icon/System/Computer_normal.png | Bin 0 -> 1246 bytes .../icon/System/Control-Panel1_hover.png | Bin 0 -> 849 bytes .../icon/System/Control-Panel1_normal.png | Bin 0 -> 1407 bytes .../icon/System/Control-Panel2_hover.png | Bin 0 -> 966 bytes .../icon/System/Control-Panel2_normal.png | Bin 0 -> 1661 bytes .../terminal/icon/System/Desktop_hover.png | Bin 0 -> 742 bytes .../terminal/icon/System/Desktop_normal.png | Bin 0 -> 1197 bytes .../terminal/icon/System/HDD-system_hover.png | Bin 0 -> 723 bytes .../icon/System/HDD-system_normal.png | Bin 0 -> 1166 bytes .../gui/terminal/icon/System/HDD_hover.png | Bin 0 -> 648 bytes .../gui/terminal/icon/System/HDD_normal.png | Bin 0 -> 1060 bytes .../terminal/icon/System/HW_info_hover.png | Bin 0 -> 1016 bytes .../terminal/icon/System/HW_info_normal.png | Bin 0 -> 1737 bytes .../gui/terminal/icon/System/LOCK_hover.png | Bin 0 -> 840 bytes .../gui/terminal/icon/System/LOCK_normal.png | Bin 0 -> 1311 bytes .../terminal/icon/System/SW-info_hover.png | Bin 0 -> 884 bytes .../terminal/icon/System/SW-info_normal.png | Bin 0 -> 1472 bytes .../gui/terminal/icon/System/apps4_hover.png | Bin 0 -> 822 bytes .../gui/terminal/icon/System/apps4_normal.png | Bin 0 -> 1295 bytes .../gui/terminal/icon/System/apps9_hover.png | Bin 0 -> 1007 bytes .../gui/terminal/icon/System/apps9_normal.png | Bin 0 -> 1736 bytes .../gui/terminal/icon/System/back_hover.png | Bin 0 -> 846 bytes .../gui/terminal/icon/System/back_normal.png | Bin 0 -> 1412 bytes .../gui/terminal/icon/System/bat1_hover.png | Bin 0 -> 893 bytes .../gui/terminal/icon/System/bat1_normal.png | Bin 0 -> 1486 bytes .../terminal/icon/System/expand2_hover.png | Bin 0 -> 986 bytes .../terminal/icon/System/expand2_normal.png | Bin 0 -> 1702 bytes .../terminal/icon/System/expand3_hover.png | Bin 0 -> 986 bytes .../terminal/icon/System/expand3_normal.png | Bin 0 -> 1709 bytes .../gui/terminal/icon/System/help_hover.png | Bin 0 -> 856 bytes .../gui/terminal/icon/System/help_normal.png | Bin 0 -> 1374 bytes .../gui/terminal/icon/System/home2_hover.png | Bin 0 -> 868 bytes .../gui/terminal/icon/System/home2_normal.png | Bin 0 -> 1436 bytes .../gui/terminal/icon/System/info2_hover.png | Bin 0 -> 716 bytes .../gui/terminal/icon/System/info2_normal.png | Bin 0 -> 1151 bytes .../gui/terminal/icon/System/info3_hover.png | Bin 0 -> 820 bytes .../gui/terminal/icon/System/info3_normal.png | Bin 0 -> 1336 bytes .../gui/terminal/icon/System/info_hover.png | Bin 0 -> 708 bytes .../gui/terminal/icon/System/info_normal.png | Bin 0 -> 1114 bytes .../terminal/icon/System/keyboard2_hover.png | Bin 0 -> 806 bytes .../terminal/icon/System/keyboard2_normal.png | Bin 0 -> 1251 bytes .../terminal/icon/System/keyboard_hover.png | Bin 0 -> 859 bytes .../terminal/icon/System/keyboard_normal.png | Bin 0 -> 1389 bytes .../terminal/icon/System/loading_hover.png | Bin 0 -> 936 bytes .../terminal/icon/System/loading_normal.png | Bin 0 -> 1586 bytes .../icon/System/memory_card_hover.png | Bin 0 -> 875 bytes .../icon/System/memory_card_normal.png | Bin 0 -> 1464 bytes .../terminal/icon/System/multitask1_hover.png | Bin 0 -> 866 bytes .../icon/System/multitask1_normal.png | Bin 0 -> 1432 bytes .../gui/terminal/icon/System/off_hover.png | Bin 0 -> 968 bytes .../gui/terminal/icon/System/off_normal.png | Bin 0 -> 1703 bytes .../gui/terminal/icon/System/print_hover.png | Bin 0 -> 934 bytes .../gui/terminal/icon/System/print_normal.png | Bin 0 -> 1557 bytes .../gui/terminal/icon/System/reload_hover.png | Bin 0 -> 974 bytes .../terminal/icon/System/reload_normal.png | Bin 0 -> 1646 bytes .../gui/terminal/icon/System/rotate_hover.png | Bin 0 -> 898 bytes .../terminal/icon/System/rotate_normal.png | Bin 0 -> 1546 bytes .../gui/terminal/icon/System/save_hover.png | Bin 0 -> 839 bytes .../gui/terminal/icon/System/save_normal.png | Bin 0 -> 1371 bytes .../gui/terminal/icon/System/sd_hover.png | Bin 0 -> 745 bytes .../gui/terminal/icon/System/sd_normal.png | Bin 0 -> 1210 bytes .../terminal/icon/System/sett-big_hover.png | Bin 0 -> 927 bytes .../terminal/icon/System/sett-big_normal.png | Bin 0 -> 1576 bytes .../terminal/icon/System/sett_small_hover.png | Bin 0 -> 836 bytes .../icon/System/sett_small_normal.png | Bin 0 -> 1416 bytes .../terminal/icon/System/shut-down_hover.png | Bin 0 -> 944 bytes .../terminal/icon/System/shut-down_normal.png | Bin 0 -> 1583 bytes .../gui/terminal/icon/System/sim_hover.png | Bin 0 -> 696 bytes .../gui/terminal/icon/System/sim_normal.png | Bin 0 -> 1097 bytes .../terminal/icon/System/skaner-1_hover.png | Bin 0 -> 770 bytes .../terminal/icon/System/skaner-1_normal.png | Bin 0 -> 1238 bytes .../gui/terminal/icon/System/skaner_hover.png | Bin 0 -> 783 bytes .../terminal/icon/System/skaner_normal.png | Bin 0 -> 1252 bytes .../icon/System/taskmgr-copy_hover.png | Bin 0 -> 876 bytes .../icon/System/taskmgr-copy_normal.png | Bin 0 -> 1465 bytes .../terminal/icon/System/taskmgr_hover.png | Bin 0 -> 880 bytes .../terminal/icon/System/taskmgr_normal.png | Bin 0 -> 1483 bytes .../gui/terminal/icon/System/tok_hover.png | Bin 0 -> 866 bytes .../gui/terminal/icon/System/tok_normal.png | Bin 0 -> 1440 bytes .../gui/terminal/icon/System/tools_hover.png | Bin 0 -> 871 bytes .../gui/terminal/icon/System/tools_normal.png | Bin 0 -> 1451 bytes .../terminal/icon/System/windows_hover.png | Bin 0 -> 931 bytes .../terminal/icon/System/windows_normal.png | Bin 0 -> 1562 bytes .../textures/gui/terminal/icon/add_hover.png | Bin 0 -> 897 bytes .../textures/gui/terminal/icon/add_normal.png | Bin 0 -> 1483 bytes .../gui/terminal/icon/appearance_hover.png | Bin 0 -> 911 bytes .../gui/terminal/icon/appearance_normal.png | Bin 0 -> 1626 bytes .../gui/terminal/icon/cancel_disable.png | Bin 0 -> 3159 bytes .../gui/terminal/icon/cancel_hover.png | Bin 0 -> 3070 bytes .../gui/terminal/icon/cancel_normal.png | Bin 0 -> 3082 bytes .../gui/terminal/icon/default_hover.png | Bin 0 -> 1835 bytes .../gui/terminal/icon/default_normal.png | Bin 0 -> 1191 bytes .../gui/terminal/icon/default_press.png | Bin 0 -> 1810 bytes .../textures/gui/terminal/icon/down_hover.png | Bin 0 -> 2307 bytes .../gui/terminal/icon/down_normal.png | Bin 0 -> 2770 bytes .../gui/terminal/icon/equipment_hover.png | Bin 0 -> 499 bytes .../gui/terminal/icon/equipment_normal.png | Bin 0 -> 1140 bytes .../textures/gui/terminal/icon/file_hover.png | Bin 0 -> 722 bytes .../gui/terminal/icon/file_normal.png | Bin 0 -> 1306 bytes .../gui/terminal/icon/folder_hover.png | Bin 0 -> 708 bytes .../gui/terminal/icon/folder_normal.png | Bin 0 -> 1114 bytes .../gui/terminal/icon/graphics_hover.png | Bin 0 -> 978 bytes .../gui/terminal/icon/graphics_normal.png | Bin 0 -> 1652 bytes .../gui/terminal/icon/guide_hover.png | Bin 0 -> 955 bytes .../gui/terminal/icon/guide_normal.png | Bin 0 -> 1551 bytes .../textures/gui/terminal/icon/help_hover.png | Bin 0 -> 903 bytes .../gui/terminal/icon/help_normal.png | Bin 0 -> 1442 bytes .../gui/terminal/icon/items_hover.png | Bin 0 -> 897 bytes .../gui/terminal/icon/items_normal.png | Bin 0 -> 1483 bytes .../textures/gui/terminal/icon/left_hover.png | Bin 0 -> 2307 bytes .../gui/terminal/icon/left_normal.png | Bin 0 -> 2796 bytes .../gui/terminal/icon/logout_hover.png | Bin 0 -> 917 bytes .../gui/terminal/icon/logout_normal.png | Bin 0 -> 1472 bytes .../gui/terminal/icon/modify_hover.png | Bin 0 -> 865 bytes .../gui/terminal/icon/modify_normal.png | Bin 0 -> 1365 bytes .../textures/gui/terminal/icon/move_hover.png | Bin 0 -> 858 bytes .../gui/terminal/icon/move_normal.png | Bin 0 -> 1353 bytes .../textures/gui/terminal/icon/next_hover.png | Bin 0 -> 1612 bytes .../gui/terminal/icon/next_normal.png | Bin 0 -> 986 bytes .../textures/gui/terminal/icon/next_press.png | Bin 0 -> 1479 bytes .../textures/gui/terminal/icon/ok_disable.png | Bin 0 -> 3322 bytes .../textures/gui/terminal/icon/ok_hover.png | Bin 0 -> 3261 bytes .../textures/gui/terminal/icon/ok_normal.png | Bin 0 -> 3278 bytes .../gui/terminal/icon/option_hover.png | Bin 0 -> 1022 bytes .../gui/terminal/icon/option_normal.png | Bin 0 -> 1705 bytes .../textures/gui/terminal/icon/prev_hover.png | Bin 0 -> 1618 bytes .../gui/terminal/icon/prev_normal.png | Bin 0 -> 1006 bytes .../textures/gui/terminal/icon/prev_press.png | Bin 0 -> 1488 bytes .../gui/terminal/icon/remove_hover.png | Bin 0 -> 757 bytes .../gui/terminal/icon/remove_normal.png | Bin 0 -> 1131 bytes .../gui/terminal/icon/right_hover.png | Bin 0 -> 2300 bytes .../gui/terminal/icon/right_normal.png | Bin 0 -> 2788 bytes .../textures/gui/terminal/icon/run_hover.png | Bin 0 -> 864 bytes .../textures/gui/terminal/icon/run_normal.png | Bin 0 -> 1351 bytes .../gui/terminal/icon/skills_hover.png | Bin 0 -> 863 bytes .../gui/terminal/icon/skills_normal.png | Bin 0 -> 1014 bytes .../gui/terminal/icon/sound_hover.png | Bin 0 -> 948 bytes .../gui/terminal/icon/sound_normal.png | Bin 0 -> 1586 bytes .../gui/terminal/icon/theme_hover.png | Bin 0 -> 978 bytes .../gui/terminal/icon/theme_normal.png | Bin 0 -> 1516 bytes .../textures/gui/terminal/icon/up_hover.png | Bin 0 -> 2305 bytes .../textures/gui/terminal/icon/up_normal.png | Bin 0 -> 2758 bytes .../gui/terminal/recipe_graph/icon.png | Bin 0 -> 27259 bytes .../gui/terminal/terminal_background.png | Bin 0 -> 398697 bytes .../textures/gui/terminal/terminal_dialog.png | Bin 0 -> 5193 bytes .../textures/gui/terminal/terminal_frame.png | Bin 0 -> 24072 bytes .../textures/gui/widget/formatting.png | Bin 0 -> 1890 bytes .../gregtech/textures/gui/widget/palette.png | Bin 0 -> 1921 bytes .../material_sets/diamond/plate_double.png | Bin 0 -> 1691 bytes .../diamond/plate_double_overlay.png | Bin 0 -> 1623 bytes .../material_sets/emerald/plate_double.png | Bin 0 -> 1691 bytes .../emerald/plate_double_overlay.png | Bin 0 -> 1623 bytes .../gem_horizontal/plate_double.png | Bin 0 -> 1691 bytes .../gem_horizontal/plate_double_overlay.png | Bin 0 -> 1623 bytes .../gem_vertical/plate_double.png | Bin 0 -> 1691 bytes .../gem_vertical/plate_double_overlay.png | Bin 0 -> 1623 bytes .../material_sets/lapis/plate_double.png | Bin 0 -> 1896 bytes .../items/material_sets/lignite/gem.png | Bin 466 -> 1595 bytes .../material_sets/netherstar/plate_double.png | Bin 0 -> 1691 bytes .../netherstar/plate_double_overlay.png | Bin 0 -> 1623 bytes .../items/material_sets/opal/plate_double.png | Bin 0 -> 1691 bytes .../opal/plate_double_overlay.png | Bin 0 -> 1623 bytes .../items/material_sets/ruby/plate_double.png | Bin 0 -> 1691 bytes .../ruby/plate_double_overlay.png | Bin 0 -> 1623 bytes .../items/metaitems/battery.ev.vanadium/1.png | Bin 0 -> 325 bytes .../items/metaitems/battery.ev.vanadium/2.png | Bin 0 -> 326 bytes .../items/metaitems/battery.ev.vanadium/3.png | Bin 0 -> 336 bytes .../items/metaitems/battery.ev.vanadium/4.png | Bin 0 -> 334 bytes .../items/metaitems/battery.ev.vanadium/5.png | Bin 0 -> 335 bytes .../items/metaitems/battery.ev.vanadium/6.png | Bin 0 -> 333 bytes .../items/metaitems/battery.ev.vanadium/7.png | Bin 0 -> 333 bytes .../items/metaitems/battery.ev.vanadium/8.png | Bin 0 -> 327 bytes .../items/metaitems/battery.hull.ev.png | Bin 0 -> 326 bytes .../items/metaitems/battery.hull.iv.png | Bin 0 -> 352 bytes .../items/metaitems/battery.hull.luv.png | Bin 0 -> 350 bytes .../items/metaitems/battery.hull.uv.png | Bin 0 -> 361 bytes .../items/metaitems/battery.hull.zpm.png | Bin 0 -> 335 bytes .../items/metaitems/battery.iv.vanadium/1.png | Bin 0 -> 346 bytes .../items/metaitems/battery.iv.vanadium/2.png | Bin 0 -> 346 bytes .../items/metaitems/battery.iv.vanadium/3.png | Bin 0 -> 346 bytes .../items/metaitems/battery.iv.vanadium/4.png | Bin 0 -> 347 bytes .../items/metaitems/battery.iv.vanadium/5.png | Bin 0 -> 347 bytes .../items/metaitems/battery.iv.vanadium/6.png | Bin 0 -> 349 bytes .../items/metaitems/battery.iv.vanadium/7.png | Bin 0 -> 346 bytes .../items/metaitems/battery.iv.vanadium/8.png | Bin 0 -> 348 bytes .../metaitems/battery.luv.vanadium/1.png | Bin 0 -> 352 bytes .../metaitems/battery.luv.vanadium/2.png | Bin 0 -> 353 bytes .../metaitems/battery.luv.vanadium/3.png | Bin 0 -> 358 bytes .../metaitems/battery.luv.vanadium/4.png | Bin 0 -> 357 bytes .../metaitems/battery.luv.vanadium/5.png | Bin 0 -> 357 bytes .../metaitems/battery.luv.vanadium/6.png | Bin 0 -> 356 bytes .../metaitems/battery.luv.vanadium/7.png | Bin 0 -> 358 bytes .../metaitems/battery.luv.vanadium/8.png | Bin 0 -> 361 bytes .../items/metaitems/battery.su.hv.mercury.png | Bin 358 -> 0 bytes .../metaitems/battery.su.hv.sulfuricacid.png | Bin 363 -> 0 bytes .../items/metaitems/battery.su.lv.mercury.png | Bin 316 -> 0 bytes .../metaitems/battery.su.lv.sulfuricacid.png | Bin 317 -> 0 bytes .../items/metaitems/battery.su.mv.mercury.png | Bin 345 -> 0 bytes .../metaitems/battery.su.mv.sulfuricacid.png | Bin 350 -> 0 bytes .../metaitems/battery.uv.naquadria/1.png | Bin 0 -> 362 bytes .../metaitems/battery.uv.naquadria/2.png | Bin 0 -> 362 bytes .../metaitems/battery.uv.naquadria/3.png | Bin 0 -> 361 bytes .../metaitems/battery.uv.naquadria/4.png | Bin 0 -> 361 bytes .../metaitems/battery.uv.naquadria/5.png | Bin 0 -> 361 bytes .../metaitems/battery.uv.naquadria/6.png | Bin 0 -> 361 bytes .../metaitems/battery.uv.naquadria/7.png | Bin 0 -> 363 bytes .../metaitems/battery.uv.naquadria/8.png | Bin 0 -> 364 bytes .../metaitems/battery.zpm.naquadria/1.png | Bin 0 -> 337 bytes .../metaitems/battery.zpm.naquadria/2.png | Bin 0 -> 336 bytes .../metaitems/battery.zpm.naquadria/3.png | Bin 0 -> 336 bytes .../metaitems/battery.zpm.naquadria/4.png | Bin 0 -> 335 bytes .../metaitems/battery.zpm.naquadria/5.png | Bin 0 -> 338 bytes .../metaitems/battery.zpm.naquadria/6.png | Bin 0 -> 338 bytes .../metaitems/battery.zpm.naquadria/7.png | Bin 0 -> 340 bytes .../metaitems/battery.zpm.naquadria/8.png | Bin 0 -> 340 bytes .../items/metaitems/cover.infinite_water.png | Bin 0 -> 2484 bytes .../metaitems/magnetic_field_projector.png | Bin 748 -> 0 bytes .../items/metaitems/tool.terminal.png | Bin 0 -> 2868 bytes src/main/resources/gregtech_at.cfg | 6 + .../impl/AbstractRecipeLogicTest.java | 132 ++++ .../impl/MultiblockRecipeLogicTest.java | 266 +++++++ 1057 files changed, 20983 insertions(+), 5186 deletions(-) create mode 100644 CHANGELOG-GTCEU.md create mode 100644 src/main/java/gregtech/api/capability/INotifiableHandler.java mode change 100755 => 100644 src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java create mode 100644 src/main/java/gregtech/api/capability/impl/EUToFEProvider.java create mode 100644 src/main/java/gregtech/api/capability/impl/GTEnergyWrapper.java create mode 100644 src/main/java/gregtech/api/capability/impl/NotifiableFilteredFluidHandler.java create mode 100644 src/main/java/gregtech/api/capability/impl/NotifiableFluidTank.java create mode 100644 src/main/java/gregtech/api/capability/impl/NotifiableItemStackHandler.java create mode 100644 src/main/java/gregtech/api/capability/impl/PrimitiveRecipeLogic.java create mode 100644 src/main/java/gregtech/api/gui/resources/ColorRectTexture.java create mode 100644 src/main/java/gregtech/api/gui/resources/FileTexture.java create mode 100644 src/main/java/gregtech/api/gui/resources/IGuiTexture.java create mode 100644 src/main/java/gregtech/api/gui/resources/ItemStackTexture.java create mode 100644 src/main/java/gregtech/api/gui/resources/ModifyGuiTexture.java create mode 100644 src/main/java/gregtech/api/gui/resources/TextTexture.java create mode 100644 src/main/java/gregtech/api/gui/resources/URLTexture.java create mode 100644 src/main/java/gregtech/api/gui/resources/picturetexture/AnimatedPictureTexture.java create mode 100644 src/main/java/gregtech/api/gui/resources/picturetexture/OrdinaryTexture.java create mode 100644 src/main/java/gregtech/api/gui/resources/picturetexture/PictureTexture.java create mode 100644 src/main/java/gregtech/api/gui/resources/picturetexture/VideoTexture.java create mode 100644 src/main/java/gregtech/api/gui/resources/utils/DownloadThread.java create mode 100644 src/main/java/gregtech/api/gui/resources/utils/GifDecoder.java create mode 100644 src/main/java/gregtech/api/gui/resources/utils/ImageUtils.java create mode 100644 src/main/java/gregtech/api/gui/resources/utils/ProcessedImageData.java create mode 100644 src/main/java/gregtech/api/gui/resources/utils/TextureCache.java create mode 100644 src/main/java/gregtech/api/gui/widgets/CraftingStationInputWidgetGroup.java delete mode 100644 src/main/java/gregtech/api/gui/widgets/TextFieldWidgetInfiniteEnergy.java create mode 100644 src/main/java/gregtech/api/gui/widgets/tab/IGuiTextureTabInfo.java create mode 100644 src/main/java/gregtech/api/items/armor/ArmorHooks.java create mode 100644 src/main/java/gregtech/api/items/armor/ArmorMetaItem.java create mode 100644 src/main/java/gregtech/api/items/armor/ArmorRenderHooks.java create mode 100644 src/main/java/gregtech/api/items/armor/DummyArmorLogic.java create mode 100644 src/main/java/gregtech/api/items/armor/IArmorItem.java create mode 100644 src/main/java/gregtech/api/items/armor/IArmorLogic.java create mode 100644 src/main/java/gregtech/api/items/armor/ISpecialArmorLogic.java create mode 100644 src/main/java/gregtech/api/items/crafttweaker/CTItemRegistry.java create mode 100644 src/main/java/gregtech/api/items/metaitem/MetaOreDictItem.java delete mode 100644 src/main/java/gregtech/api/metatileentity/InfiniteEnergyTileEntityBase.java create mode 100644 src/main/java/gregtech/api/metatileentity/multiblock/RecipeMapPrimitiveMultiblockController.java rename src/main/java/gregtech/api/{capability/impl => metatileentity/multiblock}/RecipeMapSteamMultiblockController.java (93%) delete mode 100644 src/main/java/gregtech/api/pipenet/MonolithicPipeNet.java create mode 100644 src/main/java/gregtech/api/pipenet/PipeGatherer.java create mode 100644 src/main/java/gregtech/api/pipenet/PipeNetWalker.java create mode 100644 src/main/java/gregtech/api/recipes/GTRecipeHandler.java delete mode 100644 src/main/java/gregtech/api/recipes/builders/CokeOvenRecipeBuilder.java create mode 100644 src/main/java/gregtech/api/recipes/builders/GasCollectorRecipeBuilder.java delete mode 100644 src/main/java/gregtech/api/recipes/builders/PBFRecipeBuilder.java create mode 100644 src/main/java/gregtech/api/recipes/builders/PrimitiveRecipeBuilder.java delete mode 100644 src/main/java/gregtech/api/recipes/crafttweaker/CokeOvenRecipeExpansion.java delete mode 100644 src/main/java/gregtech/api/recipes/crafttweaker/PBFRecipeExpansion.java create mode 100644 src/main/java/gregtech/api/recipes/recipeproperties/GasCollectorDimensionProperty.java create mode 100644 src/main/java/gregtech/api/recipes/recipeproperties/PrimitiveProperty.java create mode 100644 src/main/java/gregtech/api/terminal/TerminalRegistry.java create mode 100644 src/main/java/gregtech/api/terminal/app/AbstractApplication.java create mode 100644 src/main/java/gregtech/api/terminal/gui/CustomTabListRenderer.java create mode 100644 src/main/java/gregtech/api/terminal/gui/IDraggable.java create mode 100644 src/main/java/gregtech/api/terminal/gui/widgets/AnimaWidgetGroup.java create mode 100644 src/main/java/gregtech/api/terminal/gui/widgets/CircleButtonWidget.java create mode 100644 src/main/java/gregtech/api/terminal/gui/widgets/ColorWidget.java create mode 100644 src/main/java/gregtech/api/terminal/gui/widgets/CustomPositionSizeWidget.java create mode 100644 src/main/java/gregtech/api/terminal/gui/widgets/DraggableScrollableWidgetGroup.java create mode 100644 src/main/java/gregtech/api/terminal/gui/widgets/RectButtonWidget.java create mode 100644 src/main/java/gregtech/api/terminal/gui/widgets/SelectorWidget.java create mode 100644 src/main/java/gregtech/api/terminal/gui/widgets/TextEditorWidget.java create mode 100644 src/main/java/gregtech/api/terminal/gui/widgets/TreeListWidget.java create mode 100644 src/main/java/gregtech/api/terminal/os/TerminalDesktopWidget.java create mode 100644 src/main/java/gregtech/api/terminal/os/TerminalDialogWidget.java create mode 100644 src/main/java/gregtech/api/terminal/os/TerminalOSWidget.java create mode 100644 src/main/java/gregtech/api/terminal/os/TerminalTheme.java create mode 100644 src/main/java/gregtech/api/terminal/os/menu/IMenuComponent.java create mode 100644 src/main/java/gregtech/api/terminal/os/menu/TerminalMenuWidget.java create mode 100644 src/main/java/gregtech/api/terminal/util/FileTree.java create mode 100644 src/main/java/gregtech/api/terminal/util/FileUtils.java create mode 100644 src/main/java/gregtech/api/terminal/util/GuideJsonLoader.java create mode 100644 src/main/java/gregtech/api/terminal/util/ISearch.java create mode 100644 src/main/java/gregtech/api/terminal/util/SearchEngine.java create mode 100644 src/main/java/gregtech/api/terminal/util/TreeNode.java delete mode 100644 src/main/java/gregtech/api/util/DirectionHelper.java delete mode 100644 src/main/java/gregtech/api/util/FirstTickScheduler.java delete mode 100644 src/main/java/gregtech/api/util/IFirstTickTask.java create mode 100644 src/main/java/gregtech/api/util/LocalizationUtils.java create mode 100644 src/main/java/gregtech/api/util/RelativeDirection.java create mode 100644 src/main/java/gregtech/api/util/TickingObjectHolder.java create mode 100644 src/main/java/gregtech/api/util/interpolate/Eases.java create mode 100644 src/main/java/gregtech/api/util/interpolate/IEase.java create mode 100644 src/main/java/gregtech/api/util/interpolate/Interpolator.java create mode 100644 src/main/java/gregtech/common/asm/ConcretePowderVisitor.java create mode 100644 src/main/java/gregtech/common/covers/CoverInfiniteWater.java create mode 100644 src/main/java/gregtech/common/covers/DistributionMode.java delete mode 100644 src/main/java/gregtech/common/items/FieldProjectorEventHandler.java create mode 100644 src/main/java/gregtech/common/items/behaviors/TerminalBehaviour.java create mode 100644 src/main/java/gregtech/common/metatileentities/electric/MetaTileEntityAdjustableTransformer.java delete mode 100644 src/main/java/gregtech/common/metatileentities/electric/MetaTileEntityAirCollector.java create mode 100644 src/main/java/gregtech/common/metatileentities/electric/MetaTileEntityDiode.java create mode 100644 src/main/java/gregtech/common/metatileentities/electric/MetaTileEntityGasCollector.java delete mode 100644 src/main/java/gregtech/common/metatileentities/electric/MetaTileEntityInfiniteEmitter.java create mode 100644 src/main/java/gregtech/common/metatileentities/electric/MetaTileEntitySimpleOreWasher.java create mode 100644 src/main/java/gregtech/common/metatileentities/electric/multiblockpart/MetaTileEntityAdjustableEnergyHatch.java create mode 100644 src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityBuffer.java create mode 100644 src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityCreativeEnergy.java delete mode 100644 src/main/java/gregtech/common/metatileentities/traits/TraitInfiniteEmitter.java delete mode 100644 src/main/java/gregtech/common/metatileentities/traits/TraitInfiniteEnergy.java create mode 100644 src/main/java/gregtech/common/pipelike/cable/net/EnergyNetHandler.java create mode 100644 src/main/java/gregtech/common/pipelike/cable/net/EnergyNetWalker.java delete mode 100644 src/main/java/gregtech/common/pipelike/cable/tile/CableEnergyContainer.java mode change 100755 => 100644 src/main/java/gregtech/common/pipelike/fluidpipe/BlockFluidPipe.java create mode 100644 src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidNetHandler.java delete mode 100644 src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidNetTank.java create mode 100644 src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidNetWalker.java delete mode 100644 src/main/java/gregtech/common/pipelike/fluidpipe/tile/FluidPipeFluidHandler.java create mode 100644 src/main/java/gregtech/common/terminal/app/ThemeSettingApp.java create mode 100644 src/main/java/gregtech/common/terminal/app/guide/GuideApp.java create mode 100644 src/main/java/gregtech/common/terminal/app/guide/ItemGuideApp.java create mode 100644 src/main/java/gregtech/common/terminal/app/guide/MultiBlockGuideApp.java create mode 100644 src/main/java/gregtech/common/terminal/app/guide/SimpleMachineGuideApp.java create mode 100644 src/main/java/gregtech/common/terminal/app/guide/TutorialGuideApp.java create mode 100644 src/main/java/gregtech/common/terminal/app/guide/widget/CardWidget.java create mode 100644 src/main/java/gregtech/common/terminal/app/guide/widget/GuidePageWidget.java create mode 100644 src/main/java/gregtech/common/terminal/app/guide/widget/GuideWidget.java create mode 100644 src/main/java/gregtech/common/terminal/app/guide/widget/GuideWidgetGroup.java create mode 100644 src/main/java/gregtech/common/terminal/app/guide/widget/IGuideWidget.java create mode 100644 src/main/java/gregtech/common/terminal/app/guide/widget/ImageWidget.java create mode 100644 src/main/java/gregtech/common/terminal/app/guide/widget/SlotListWidget.java create mode 100644 src/main/java/gregtech/common/terminal/app/guide/widget/TankListWidget.java create mode 100644 src/main/java/gregtech/common/terminal/app/guide/widget/TextBoxWidget.java create mode 100644 src/main/java/gregtech/common/terminal/app/guideeditor/GuideEditorApp.java create mode 100644 src/main/java/gregtech/common/terminal/app/guideeditor/widget/GuideConfigEditor.java create mode 100644 src/main/java/gregtech/common/terminal/app/guideeditor/widget/GuidePageEditorWidget.java create mode 100644 src/main/java/gregtech/common/terminal/app/guideeditor/widget/configurator/BooleanConfigurator.java create mode 100644 src/main/java/gregtech/common/terminal/app/guideeditor/widget/configurator/ColorConfigurator.java create mode 100644 src/main/java/gregtech/common/terminal/app/guideeditor/widget/configurator/ConfiguratorWidget.java create mode 100644 src/main/java/gregtech/common/terminal/app/guideeditor/widget/configurator/FluidStackConfigurator.java create mode 100644 src/main/java/gregtech/common/terminal/app/guideeditor/widget/configurator/ItemStackConfigurator.java create mode 100644 src/main/java/gregtech/common/terminal/app/guideeditor/widget/configurator/NumberConfigurator.java create mode 100644 src/main/java/gregtech/common/terminal/app/guideeditor/widget/configurator/SelectorConfigurator.java create mode 100644 src/main/java/gregtech/common/terminal/app/guideeditor/widget/configurator/StringConfigurator.java create mode 100644 src/main/java/gregtech/common/terminal/app/guideeditor/widget/configurator/TextListConfigurator.java create mode 100644 src/main/java/gregtech/common/terminal/app/recipechart/RecipeChartApp.java create mode 100644 src/main/java/gregtech/common/terminal/app/recipechart/widget/PhantomWidget.java create mode 100644 src/main/java/gregtech/common/terminal/app/recipechart/widget/RGContainer.java create mode 100644 src/main/java/gregtech/common/terminal/app/recipechart/widget/RGLine.java create mode 100644 src/main/java/gregtech/common/terminal/app/recipechart/widget/RGNode.java create mode 100644 src/main/java/gregtech/common/terminal/component/ClickComponent.java create mode 100644 src/main/java/gregtech/common/terminal/component/SearchComponent.java create mode 100644 src/main/java/gregtech/common/terminal/component/setting/GuiTextureSetter.java create mode 100644 src/main/java/gregtech/common/terminal/component/setting/ISetting.java create mode 100644 src/main/java/gregtech/common/terminal/component/setting/IWidgetSettings.java create mode 100644 src/main/java/gregtech/common/terminal/component/setting/SettingComponent.java delete mode 100644 src/main/java/gregtech/integration/jei/recipe/primitive/CokeOvenRecipeCategory.java delete mode 100644 src/main/java/gregtech/integration/jei/recipe/primitive/CokeOvenRecipeWrapper.java create mode 100644 src/main/java/gregtech/integration/jei/recipe/primitive/MaterialTree.java create mode 100644 src/main/java/gregtech/integration/jei/recipe/primitive/MaterialTreeCategory.java delete mode 100644 src/main/java/gregtech/integration/jei/recipe/primitive/PrimitiveBlastRecipeCategory.java delete mode 100644 src/main/java/gregtech/integration/jei/recipe/primitive/PrimitiveBlastRecipeWrapper.java create mode 100644 src/main/java/gregtech/integration/jei/utils/render/DrawableRegistry.java create mode 100644 src/main/java/gregtech/integration/theoneprobe/provider/DiodeInfoProvider.java create mode 100644 src/main/java/gregtech/loaders/recipe/component/AnnotatedComponentHandlerLoader.java create mode 100644 src/main/java/gregtech/loaders/recipe/component/IComponentHandler.java create mode 100644 src/main/resources/assets/gregtech/blockstates/fluid_pipe_nonuple.json create mode 100644 src/main/resources/assets/gregtech/blockstates/fluid_pipe_quadruple.json create mode 100644 src/main/resources/assets/gregtech/models/item/material_sets/diamond/plate_double.json create mode 100644 src/main/resources/assets/gregtech/models/item/material_sets/emerald/plate_double.json create mode 100644 src/main/resources/assets/gregtech/models/item/material_sets/gem_horizontal/plate_double.json create mode 100644 src/main/resources/assets/gregtech/models/item/material_sets/gem_vertical/plate_double.json create mode 100644 src/main/resources/assets/gregtech/models/item/material_sets/lapis/plate_double.json create mode 100644 src/main/resources/assets/gregtech/models/item/material_sets/netherstar/plate_double.json create mode 100644 src/main/resources/assets/gregtech/models/item/material_sets/opal/plate_double.json create mode 100644 src/main/resources/assets/gregtech/models/item/material_sets/ruby/plate_double.json create mode 100644 src/main/resources/assets/gregtech/models/item/metaitems/battery.ev.vanadium/1.json create mode 100644 src/main/resources/assets/gregtech/models/item/metaitems/battery.ev.vanadium/2.json create mode 100644 src/main/resources/assets/gregtech/models/item/metaitems/battery.ev.vanadium/3.json create mode 100644 src/main/resources/assets/gregtech/models/item/metaitems/battery.ev.vanadium/4.json create mode 100644 src/main/resources/assets/gregtech/models/item/metaitems/battery.ev.vanadium/5.json create mode 100644 src/main/resources/assets/gregtech/models/item/metaitems/battery.ev.vanadium/6.json create mode 100644 src/main/resources/assets/gregtech/models/item/metaitems/battery.ev.vanadium/7.json create mode 100644 src/main/resources/assets/gregtech/models/item/metaitems/battery.ev.vanadium/8.json create mode 100644 src/main/resources/assets/gregtech/models/item/metaitems/battery.hull.ev.json create mode 100644 src/main/resources/assets/gregtech/models/item/metaitems/battery.hull.iv.json create mode 100644 src/main/resources/assets/gregtech/models/item/metaitems/battery.hull.luv.json create mode 100644 src/main/resources/assets/gregtech/models/item/metaitems/battery.hull.uv.json create mode 100644 src/main/resources/assets/gregtech/models/item/metaitems/battery.hull.zpm.json create mode 100644 src/main/resources/assets/gregtech/models/item/metaitems/battery.iv.vanadium/1.json create mode 100644 src/main/resources/assets/gregtech/models/item/metaitems/battery.iv.vanadium/2.json create mode 100644 src/main/resources/assets/gregtech/models/item/metaitems/battery.iv.vanadium/3.json create mode 100644 src/main/resources/assets/gregtech/models/item/metaitems/battery.iv.vanadium/4.json create mode 100644 src/main/resources/assets/gregtech/models/item/metaitems/battery.iv.vanadium/5.json create mode 100644 src/main/resources/assets/gregtech/models/item/metaitems/battery.iv.vanadium/6.json create mode 100644 src/main/resources/assets/gregtech/models/item/metaitems/battery.iv.vanadium/7.json create mode 100644 src/main/resources/assets/gregtech/models/item/metaitems/battery.iv.vanadium/8.json create mode 100644 src/main/resources/assets/gregtech/models/item/metaitems/battery.luv.vanadium/1.json create mode 100644 src/main/resources/assets/gregtech/models/item/metaitems/battery.luv.vanadium/2.json create mode 100644 src/main/resources/assets/gregtech/models/item/metaitems/battery.luv.vanadium/3.json create mode 100644 src/main/resources/assets/gregtech/models/item/metaitems/battery.luv.vanadium/4.json create mode 100644 src/main/resources/assets/gregtech/models/item/metaitems/battery.luv.vanadium/5.json create mode 100644 src/main/resources/assets/gregtech/models/item/metaitems/battery.luv.vanadium/6.json create mode 100644 src/main/resources/assets/gregtech/models/item/metaitems/battery.luv.vanadium/7.json create mode 100644 src/main/resources/assets/gregtech/models/item/metaitems/battery.luv.vanadium/8.json delete mode 100644 src/main/resources/assets/gregtech/models/item/metaitems/battery.su.hv.mercury.json delete mode 100644 src/main/resources/assets/gregtech/models/item/metaitems/battery.su.hv.sulfuricacid.json delete mode 100644 src/main/resources/assets/gregtech/models/item/metaitems/battery.su.lv.mercury.json delete mode 100644 src/main/resources/assets/gregtech/models/item/metaitems/battery.su.lv.sulfuricacid.json delete mode 100644 src/main/resources/assets/gregtech/models/item/metaitems/battery.su.mv.mercury.json delete mode 100644 src/main/resources/assets/gregtech/models/item/metaitems/battery.su.mv.sulfuricacid.json create mode 100644 src/main/resources/assets/gregtech/models/item/metaitems/battery.uv.naquadria/1.json create mode 100644 src/main/resources/assets/gregtech/models/item/metaitems/battery.uv.naquadria/2.json create mode 100644 src/main/resources/assets/gregtech/models/item/metaitems/battery.uv.naquadria/3.json create mode 100644 src/main/resources/assets/gregtech/models/item/metaitems/battery.uv.naquadria/4.json create mode 100644 src/main/resources/assets/gregtech/models/item/metaitems/battery.uv.naquadria/5.json create mode 100644 src/main/resources/assets/gregtech/models/item/metaitems/battery.uv.naquadria/6.json create mode 100644 src/main/resources/assets/gregtech/models/item/metaitems/battery.uv.naquadria/7.json create mode 100644 src/main/resources/assets/gregtech/models/item/metaitems/battery.uv.naquadria/8.json create mode 100644 src/main/resources/assets/gregtech/models/item/metaitems/battery.zpm.naquadria/1.json create mode 100644 src/main/resources/assets/gregtech/models/item/metaitems/battery.zpm.naquadria/2.json create mode 100644 src/main/resources/assets/gregtech/models/item/metaitems/battery.zpm.naquadria/3.json create mode 100644 src/main/resources/assets/gregtech/models/item/metaitems/battery.zpm.naquadria/4.json create mode 100644 src/main/resources/assets/gregtech/models/item/metaitems/battery.zpm.naquadria/5.json create mode 100644 src/main/resources/assets/gregtech/models/item/metaitems/battery.zpm.naquadria/6.json create mode 100644 src/main/resources/assets/gregtech/models/item/metaitems/battery.zpm.naquadria/7.json create mode 100644 src/main/resources/assets/gregtech/models/item/metaitems/battery.zpm.naquadria/8.json create mode 100644 src/main/resources/assets/gregtech/models/item/metaitems/cover.infinite_water.json delete mode 100644 src/main/resources/assets/gregtech/models/item/metaitems/energy_field_projector.json create mode 100644 src/main/resources/assets/gregtech/models/item/metaitems/terminal.json create mode 100644 src/main/resources/assets/gregtech/terminal/guide/items/en_us/test.json create mode 100644 src/main/resources/assets/gregtech/terminal/guide/items/zh_cn/test.json create mode 100644 src/main/resources/assets/gregtech/terminal/guide/machines/en_us/steam_boiler_coal_bronze.json create mode 100644 src/main/resources/assets/gregtech/terminal/guide/multiblocks/en_us/electric_blast_furnace.json create mode 100644 src/main/resources/assets/gregtech/terminal/guide/tutorials/en_us/api_0_guidepage.json create mode 100644 src/main/resources/assets/gregtech/terminal/guide/tutorials/en_us/api_1_widget.json create mode 100644 src/main/resources/assets/gregtech/terminal/guide/tutorials/en_us/api_2_textbox.json create mode 100644 src/main/resources/assets/gregtech/terminal/guide/tutorials/en_us/api_3_image.json create mode 100644 src/main/resources/assets/gregtech/textures/blocks/cover/overlay_fluid_filter.png create mode 100644 src/main/resources/assets/gregtech/textures/blocks/cover/overlay_infinite_water.png create mode 100644 src/main/resources/assets/gregtech/textures/blocks/cover/overlay_infinite_water.png.mcmeta create mode 100644 src/main/resources/assets/gregtech/textures/blocks/machines/gas_collector/overlay_back.png create mode 100644 src/main/resources/assets/gregtech/textures/blocks/machines/gas_collector/overlay_back_active.png create mode 100644 src/main/resources/assets/gregtech/textures/blocks/machines/gas_collector/overlay_bottom.png create mode 100644 src/main/resources/assets/gregtech/textures/blocks/machines/gas_collector/overlay_bottom_active.png create mode 100644 src/main/resources/assets/gregtech/textures/blocks/machines/gas_collector/overlay_front.png create mode 100644 src/main/resources/assets/gregtech/textures/blocks/machines/gas_collector/overlay_front_active.png create mode 100644 src/main/resources/assets/gregtech/textures/blocks/machines/gas_collector/overlay_side.png create mode 100644 src/main/resources/assets/gregtech/textures/blocks/machines/gas_collector/overlay_side_active.png create mode 100644 src/main/resources/assets/gregtech/textures/blocks/machines/gas_collector/overlay_top.png create mode 100644 src/main/resources/assets/gregtech/textures/blocks/machines/gas_collector/overlay_top_active.png create mode 100644 src/main/resources/assets/gregtech/textures/blocks/overlay/machine/overlay_buffer.png create mode 100644 src/main/resources/assets/gregtech/textures/blocks/overlay/machine/overlay_energy_in_hi.png create mode 100644 src/main/resources/assets/gregtech/textures/blocks/overlay/machine/overlay_energy_in_ultra.png create mode 100644 src/main/resources/assets/gregtech/textures/blocks/overlay/machine/overlay_energy_out_hi.png create mode 100644 src/main/resources/assets/gregtech/textures/blocks/overlay/machine/overlay_energy_out_ultra.png create mode 100644 src/main/resources/assets/gregtech/textures/blocks/overlay/machine/overlay_filter.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/arrows/2d12.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/arrows/2d16.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/arrows/2r16d37.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/arrows/d14.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/arrows/d7r25u6.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/arrows/d7r50d7.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/arrows/d7r50u6.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/arrows/d7r75d7.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/arrows/d7r75u6.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/arrows/d7r87u22r4.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/arrows/d7r87u46r4.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/arrows/l7.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/arrows/r3d16r4.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/arrows/r3d26r4.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/arrows/r3u15r4.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/arrows/r3u32r4.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/arrows/r3u57r4.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/arrows/r7.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/arrows/u12.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/arrows/u7r25d6.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/arrows/u7r50d6.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/arrows/u7r50u5.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/arrows/u7r75d6.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/arrows/u7r75u5.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/arrows/u7r87d15r4.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/arrows/u7r87u8r4.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/progress_bar/progress_bar_coke_oven.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/progress_bar/progress_bar_distillation_tower.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/progress_bar/progress_bar_gas_collector.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/guide_editor/icon.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Communicate/calendar_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Communicate/calendar_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Communicate/clock1_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Communicate/clock1_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Communicate/clock2_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Communicate/clock2_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Communicate/gmail-copy_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Communicate/gmail-copy_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Communicate/gmail2-copy_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Communicate/gmail2-copy_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Communicate/kontakts_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Communicate/kontakts_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Communicate/mail1_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Communicate/mail1_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Communicate/mail2_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Communicate/mail2_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Communicate/mail_open_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Communicate/mail_open_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Communicate/mail_sent_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Communicate/mail_sent_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Communicate/msg2_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Communicate/msg2_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Communicate/msg3_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Communicate/msg3_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Communicate/msg_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Communicate/msg_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Communicate/note1_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Communicate/note1_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Communicate/note2_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Communicate/note2_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Communicate/pen_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Communicate/pen_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Communicate/phone_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Communicate/phone_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Communicate/profiles_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Communicate/profiles_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Communicate/skype_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Communicate/skype_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Communicate/tasks_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Communicate/tasks_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Communicate/voicemail-12_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Communicate/voicemail-12_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Communicate/voicemaill_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Communicate/voicemaill_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/Camera_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/Camera_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/Champions_League_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/Champions_League_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/TV2_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/TV2_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/TV_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/TV_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/VideoRecorder_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/VideoRecorder_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/WMP_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/WMP_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/YT1_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/YT1_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/YT2_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/YT2_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/blank-cd_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/blank-cd_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/camera3_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/camera3_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/ea_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/ea_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/iTunes_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/iTunes_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/landskape_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/landskape_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/lastfm_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/lastfm_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/listen_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/listen_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/macro_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/macro_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/photo_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/photo_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/radio_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/radio_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/sound2_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/sound2_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/sound_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/sound_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/touch_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/touch_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/video_rec_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/video_rec_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/viewer_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/viewer_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/walkman_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/walkman_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/winamp_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/winamp_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/zune1_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/zune1_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/zune2_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/zune2_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/zune3_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/zune3_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Navigate/Bing_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Navigate/Bing_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Navigate/COMPAS2_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Navigate/COMPAS2_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Navigate/Canada_flag_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Navigate/Canada_flag_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Navigate/EAAA_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Navigate/EAAA_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Navigate/EU_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Navigate/EU_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Navigate/NSA_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Navigate/NSA_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Navigate/Navteq1_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Navigate/Navteq1_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Navigate/POI2_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Navigate/POI2_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Navigate/Sattelite_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Navigate/Sattelite_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Navigate/compas1_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Navigate/compas1_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Navigate/compas3_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Navigate/compas3_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Navigate/gmaps_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Navigate/gmaps_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Navigate/navigation_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Navigate/navigation_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Navigate/navteq_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Navigate/navteq_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Navigate/path_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Navigate/path_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Navigate/poi_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Navigate/poi_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Navigate/world1_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Navigate/world1_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Navigate/world_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Navigate/world_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/BT2_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/BT2_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/Chrome_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/Chrome_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/Firefox_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/Firefox_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/Hand_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/Hand_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/USB1_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/USB1_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/att2_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/att2_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/att_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/att_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/bt_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/bt_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/facebook2_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/facebook2_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/facebook_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/facebook_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/firefox2_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/firefox2_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/g-google_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/g-google_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/globul_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/globul_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/gmail2_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/gmail2_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/gmail_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/gmail_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/google_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/google_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/ie_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/ie_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/mtel_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/mtel_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/net3_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/net3_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/net_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/net_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/netw_conn_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/netw_conn_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/opera_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/opera_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/rss_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/rss_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/search_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/search_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/signal1_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/signal1_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/signal2_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/signal2_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/signal4_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/signal4_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/signal_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/signal_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/skype1_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/skype1_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/skype2_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/skype2_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/t-m_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/t-m_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/twitter1_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/twitter1_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/twitter2_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/twitter2_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/twitter3_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/twitter3_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/verizon_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/verizon_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/vivacom_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/vivacom_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/vodafone1_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/vodafone1_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/vodafone2_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/vodafone2_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/vodafone3_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/vodafone3_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/wi-fi_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/wi-fi_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/wifi-router_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/wifi-router_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/Favs1_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/Favs1_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/LIBRARY_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/LIBRARY_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/Llama_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/Llama_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/MB_0027_LIBRARY_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/MB_0027_LIBRARY_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/Marvel_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/Marvel_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/Translate_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/Translate_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/Visitors_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/Visitors_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/apple_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/apple_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/b_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/b_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/book_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/book_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/calculator_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/calculator_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/cloud_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/cloud_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/convertor_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/convertor_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/currency-e-d_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/currency-e-d_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/currency-e-j_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/currency-e-j_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/currency-e-p_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/currency-e-p_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/da1_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/da1_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/da2_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/da2_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/favs2_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/favs2_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/iBOOKS_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/iBOOKS_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/java_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/java_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/light_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/light_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/pin_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/pin_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/pliok2_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/pliok2_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/pliok_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/pliok_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/plus_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/plus_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/range_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/range_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/sim_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/sim_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/weather1_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/weather1_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/3dmax_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/3dmax_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/AE_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/AE_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/AIR_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/AIR_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/Ai_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/Ai_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/Apps_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/Apps_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/Autocad_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/Autocad_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/Br_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/Br_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/Dw_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/Dw_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/Excel_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/Excel_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/Fl_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/Fl_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/Flash_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/Flash_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/Fw_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/Fw_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/Fx_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/Fx_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/IC_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/IC_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/ID_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/ID_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/LR_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/LR_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/Office1_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/Office1_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/Office2010_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/Office2010_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/One-Note_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/One-Note_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/Outlook_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/Outlook_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/Power-Point_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/Power-Point_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/Ps_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/Ps_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/Sb_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/Sb_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/Word_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/Word_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/adobe-acrobat_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/adobe-acrobat_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/android2_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/android2_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/android_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/android_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/office_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/office_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/programs_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/programs_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/ps.com_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/ps.com_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/smartbuble_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/smartbuble_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/3D_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/3D_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/APP-info_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/APP-info_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/Base_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/Base_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/Computer_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/Computer_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/Control-Panel1_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/Control-Panel1_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/Control-Panel2_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/Control-Panel2_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/Desktop_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/Desktop_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/HDD-system_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/HDD-system_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/HDD_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/HDD_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/HW_info_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/HW_info_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/LOCK_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/LOCK_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/SW-info_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/SW-info_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/apps4_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/apps4_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/apps9_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/apps9_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/back_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/back_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/bat1_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/bat1_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/expand2_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/expand2_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/expand3_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/expand3_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/help_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/help_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/home2_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/home2_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/info2_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/info2_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/info3_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/info3_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/info_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/info_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/keyboard2_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/keyboard2_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/keyboard_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/keyboard_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/loading_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/loading_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/memory_card_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/memory_card_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/multitask1_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/multitask1_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/off_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/off_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/print_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/print_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/reload_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/reload_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/rotate_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/rotate_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/save_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/save_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/sd_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/sd_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/sett-big_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/sett-big_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/sett_small_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/sett_small_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/shut-down_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/shut-down_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/sim_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/sim_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/skaner-1_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/skaner-1_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/skaner_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/skaner_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/taskmgr-copy_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/taskmgr-copy_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/taskmgr_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/taskmgr_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/tok_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/tok_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/tools_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/tools_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/windows_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/windows_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/add_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/add_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/appearance_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/appearance_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/cancel_disable.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/cancel_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/cancel_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/default_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/default_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/default_press.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/down_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/down_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/equipment_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/equipment_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/file_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/file_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/folder_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/folder_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/graphics_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/graphics_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/guide_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/guide_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/help_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/help_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/items_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/items_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/left_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/left_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/logout_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/logout_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/modify_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/modify_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/move_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/move_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/next_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/next_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/next_press.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/ok_disable.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/ok_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/ok_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/option_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/option_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/prev_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/prev_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/prev_press.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/remove_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/remove_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/right_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/right_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/run_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/run_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/skills_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/skills_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/sound_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/sound_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/theme_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/theme_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/up_hover.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/icon/up_normal.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/recipe_graph/icon.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/terminal_background.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/terminal_dialog.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/terminal/terminal_frame.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/widget/formatting.png create mode 100644 src/main/resources/assets/gregtech/textures/gui/widget/palette.png create mode 100644 src/main/resources/assets/gregtech/textures/items/material_sets/diamond/plate_double.png create mode 100644 src/main/resources/assets/gregtech/textures/items/material_sets/diamond/plate_double_overlay.png create mode 100644 src/main/resources/assets/gregtech/textures/items/material_sets/emerald/plate_double.png create mode 100644 src/main/resources/assets/gregtech/textures/items/material_sets/emerald/plate_double_overlay.png create mode 100644 src/main/resources/assets/gregtech/textures/items/material_sets/gem_horizontal/plate_double.png create mode 100644 src/main/resources/assets/gregtech/textures/items/material_sets/gem_horizontal/plate_double_overlay.png create mode 100644 src/main/resources/assets/gregtech/textures/items/material_sets/gem_vertical/plate_double.png create mode 100644 src/main/resources/assets/gregtech/textures/items/material_sets/gem_vertical/plate_double_overlay.png create mode 100644 src/main/resources/assets/gregtech/textures/items/material_sets/lapis/plate_double.png create mode 100644 src/main/resources/assets/gregtech/textures/items/material_sets/netherstar/plate_double.png create mode 100644 src/main/resources/assets/gregtech/textures/items/material_sets/netherstar/plate_double_overlay.png create mode 100644 src/main/resources/assets/gregtech/textures/items/material_sets/opal/plate_double.png create mode 100644 src/main/resources/assets/gregtech/textures/items/material_sets/opal/plate_double_overlay.png create mode 100644 src/main/resources/assets/gregtech/textures/items/material_sets/ruby/plate_double.png create mode 100644 src/main/resources/assets/gregtech/textures/items/material_sets/ruby/plate_double_overlay.png create mode 100644 src/main/resources/assets/gregtech/textures/items/metaitems/battery.ev.vanadium/1.png create mode 100644 src/main/resources/assets/gregtech/textures/items/metaitems/battery.ev.vanadium/2.png create mode 100644 src/main/resources/assets/gregtech/textures/items/metaitems/battery.ev.vanadium/3.png create mode 100644 src/main/resources/assets/gregtech/textures/items/metaitems/battery.ev.vanadium/4.png create mode 100644 src/main/resources/assets/gregtech/textures/items/metaitems/battery.ev.vanadium/5.png create mode 100644 src/main/resources/assets/gregtech/textures/items/metaitems/battery.ev.vanadium/6.png create mode 100644 src/main/resources/assets/gregtech/textures/items/metaitems/battery.ev.vanadium/7.png create mode 100644 src/main/resources/assets/gregtech/textures/items/metaitems/battery.ev.vanadium/8.png create mode 100644 src/main/resources/assets/gregtech/textures/items/metaitems/battery.hull.ev.png create mode 100644 src/main/resources/assets/gregtech/textures/items/metaitems/battery.hull.iv.png create mode 100644 src/main/resources/assets/gregtech/textures/items/metaitems/battery.hull.luv.png create mode 100644 src/main/resources/assets/gregtech/textures/items/metaitems/battery.hull.uv.png create mode 100644 src/main/resources/assets/gregtech/textures/items/metaitems/battery.hull.zpm.png create mode 100644 src/main/resources/assets/gregtech/textures/items/metaitems/battery.iv.vanadium/1.png create mode 100644 src/main/resources/assets/gregtech/textures/items/metaitems/battery.iv.vanadium/2.png create mode 100644 src/main/resources/assets/gregtech/textures/items/metaitems/battery.iv.vanadium/3.png create mode 100644 src/main/resources/assets/gregtech/textures/items/metaitems/battery.iv.vanadium/4.png create mode 100644 src/main/resources/assets/gregtech/textures/items/metaitems/battery.iv.vanadium/5.png create mode 100644 src/main/resources/assets/gregtech/textures/items/metaitems/battery.iv.vanadium/6.png create mode 100644 src/main/resources/assets/gregtech/textures/items/metaitems/battery.iv.vanadium/7.png create mode 100644 src/main/resources/assets/gregtech/textures/items/metaitems/battery.iv.vanadium/8.png create mode 100644 src/main/resources/assets/gregtech/textures/items/metaitems/battery.luv.vanadium/1.png create mode 100644 src/main/resources/assets/gregtech/textures/items/metaitems/battery.luv.vanadium/2.png create mode 100644 src/main/resources/assets/gregtech/textures/items/metaitems/battery.luv.vanadium/3.png create mode 100644 src/main/resources/assets/gregtech/textures/items/metaitems/battery.luv.vanadium/4.png create mode 100644 src/main/resources/assets/gregtech/textures/items/metaitems/battery.luv.vanadium/5.png create mode 100644 src/main/resources/assets/gregtech/textures/items/metaitems/battery.luv.vanadium/6.png create mode 100644 src/main/resources/assets/gregtech/textures/items/metaitems/battery.luv.vanadium/7.png create mode 100644 src/main/resources/assets/gregtech/textures/items/metaitems/battery.luv.vanadium/8.png delete mode 100644 src/main/resources/assets/gregtech/textures/items/metaitems/battery.su.hv.mercury.png delete mode 100644 src/main/resources/assets/gregtech/textures/items/metaitems/battery.su.hv.sulfuricacid.png delete mode 100644 src/main/resources/assets/gregtech/textures/items/metaitems/battery.su.lv.mercury.png delete mode 100644 src/main/resources/assets/gregtech/textures/items/metaitems/battery.su.lv.sulfuricacid.png delete mode 100644 src/main/resources/assets/gregtech/textures/items/metaitems/battery.su.mv.mercury.png delete mode 100644 src/main/resources/assets/gregtech/textures/items/metaitems/battery.su.mv.sulfuricacid.png create mode 100644 src/main/resources/assets/gregtech/textures/items/metaitems/battery.uv.naquadria/1.png create mode 100644 src/main/resources/assets/gregtech/textures/items/metaitems/battery.uv.naquadria/2.png create mode 100644 src/main/resources/assets/gregtech/textures/items/metaitems/battery.uv.naquadria/3.png create mode 100644 src/main/resources/assets/gregtech/textures/items/metaitems/battery.uv.naquadria/4.png create mode 100644 src/main/resources/assets/gregtech/textures/items/metaitems/battery.uv.naquadria/5.png create mode 100644 src/main/resources/assets/gregtech/textures/items/metaitems/battery.uv.naquadria/6.png create mode 100644 src/main/resources/assets/gregtech/textures/items/metaitems/battery.uv.naquadria/7.png create mode 100644 src/main/resources/assets/gregtech/textures/items/metaitems/battery.uv.naquadria/8.png create mode 100644 src/main/resources/assets/gregtech/textures/items/metaitems/battery.zpm.naquadria/1.png create mode 100644 src/main/resources/assets/gregtech/textures/items/metaitems/battery.zpm.naquadria/2.png create mode 100644 src/main/resources/assets/gregtech/textures/items/metaitems/battery.zpm.naquadria/3.png create mode 100644 src/main/resources/assets/gregtech/textures/items/metaitems/battery.zpm.naquadria/4.png create mode 100644 src/main/resources/assets/gregtech/textures/items/metaitems/battery.zpm.naquadria/5.png create mode 100644 src/main/resources/assets/gregtech/textures/items/metaitems/battery.zpm.naquadria/6.png create mode 100644 src/main/resources/assets/gregtech/textures/items/metaitems/battery.zpm.naquadria/7.png create mode 100644 src/main/resources/assets/gregtech/textures/items/metaitems/battery.zpm.naquadria/8.png create mode 100644 src/main/resources/assets/gregtech/textures/items/metaitems/cover.infinite_water.png delete mode 100644 src/main/resources/assets/gregtech/textures/items/metaitems/magnetic_field_projector.png create mode 100644 src/main/resources/assets/gregtech/textures/items/metaitems/tool.terminal.png create mode 100644 src/test/java/gregtech/api/capability/impl/AbstractRecipeLogicTest.java create mode 100644 src/test/java/gregtech/api/capability/impl/MultiblockRecipeLogicTest.java diff --git a/CHANGELOG-GTCEU.md b/CHANGELOG-GTCEU.md new file mode 100644 index 00000000000..2648556b1dc --- /dev/null +++ b/CHANGELOG-GTCEU.md @@ -0,0 +1,216 @@ +## Changes made by GregTech: CE Unofficial + +### Features +- Shadows of Greg content was almost entirely merged in, including: + - Assembly Line + - Fusion Reactors (MK 1-3) + - Replicators, Mass Fabricators + - Crates, Drums (now with an Aluminium variant) + - Higher Tier Machines + - Cluster Mill NOT moved over +- Russian Localization updated +- Machine Tank Sizes are now configurable (default unchanged) +- Pipes now have proper models +- GT6-Style Pipe and Cable connections config option (default false) +- Pipes and Cables now have the "Machine Grid" when holding a tool or Cover +- Cables now require Wire Cutters to connect and disconnect +- Machines can require a Wrench to break with a config option (default false) +- New Programmed Circuit texture (credit IMPACT) +- Added Huge Pipes +- Frame texture reworked, Colored Frames removed to reduce clutter +- TheOneProbe now displays if a multiblock is formed or not +- Many fluid textures were updated to be more unique +- Added the Large Chemical Reactor (LCR), a multiblock Chemical Reactor with some custom recipes and perfect overclocking (4x the power, /4 the duration) +- EBF coils have new textures, and have connected textures +- Fusion and Superconductor coils for EBF replaced with Diamericium Titanium and Fluxed Electrum (tentative replacements) +- Tanks in Machines now display their total fluid amount without needing the tooltip +- Circuits have been entirely overhauled, with an inspiration from Omnifactory and IMPACT +- New Boule, Neutronium Boule, as well as new SMD components, circuit boards, silicon chips, etc. +- Fusion Reactor now illuminates its "rings" with a bright yellow texture +- Multiblock Parts can now be placed facing directly up or down (instead of only towards the side) +- Machines and Cables have a configurable color tint (default none, like GTCE) +- Shadows of Greg Bundler recipes added to Packer and Unpacker +- New tiers of Cells to hold much larger quantities of fluids +- EBF now has coil bonuses: + - Every 900K above the recipe temperature applies a multiplicative 5% energy discount + - Every 1800K above the recipe temperature applies a "perfect overclock" (/4 duration instead of /2) + - Every voltage tier above MV increases the total temperature by 100K +- Transformers now have the "lower voltage side" on 5 sides, with higher voltage on one side +- Infinite Energy Emitter for debug and Creative (or expert-pack endgame) +- Added 3x3 Hammers (like Tinker's Hammers) +- Added Electric Drills up to IV, can be as large as 9x9x9 (can be set in the tool with shift-right-click) +- Added Super Tanks and Super Chests, starting at MV. Quantum Tanks and Chests are now later and much, much larger +- Fluids can now be manually removed from Singleblock Generators +- Advancements (achievements) were added all the way from Bronze to MK3 Fusion Reactor and Wetware Mainframe +- TheOneProbe now displays recipe time in ticks when duration is short, to be more accurate +- Progress Bars in JEI now are active (like Vanilla Furnace progress bar in JEI) +- "Allow Input from Output Side" now defaults to True +- Energy Output Hatches (now called Dynamo Hatches) now only output energy on one side (Energy Input unchanged) +- Scanner from GT5U added, for Matter Replication among other things +- Overclocking logic was changed: + - Default logic is a flat /2 (from 2/2.8 split previously) + - Config option is available, allowing a range from 2.0 to 3.0 + - ULV -> LV no longer overclocks, keeping ULV recipes much more energy efficient +- Primitive Water Pump was added (credit IMPACT) + - Craftable before Steam-Era, requiring only Iron, Wood, and Stone + - Outputs up to 3B/s of water, or as low as 150mB depending on the Hatch used and the Biome it is placed in + - Look at JEI Info Tab for more details +- Steam Machines now have a more distinct texture on their Venting Output +- Drums and Tanks can now be cleared via a crafting recipe (like EIO Tanks), similar to Quantum/Super Tanks +- Some Steam-Era Multiblock Machines were added: + - Steam Grinder: + - Multiblock Macerator at Steam-Age + - Consumes 2x the base rate of Steam, at 1.5x the base duration, but up to 8 items at a time + - Steam Oven: + - Multiblock Furnace at Steam-Age + - Consumes 2x the base rate of Steam, at 1.5x the base duration, but up to 8 items at a time +- Tools can now be enchanted with Unbreaking, and Wrenches can have Efficiency as well +- Item Pipes have been added + - Much larger throughput compared to options from other Mods + - More efficient (TPS) than EnderIO Conduits + - Two Modes with a Conveyor or Robot Arm cover: + - Priority: + - Each Pipe has a "priority" value + - Items will go to the lowest priority value first + - Restrictive Pipes can be used to drastically increase priority value (lower priority) + - Round Robin + - Items will be evenly distributed to each destination + - Unlike EnderIO, a single "group" of items extracted will be split across destinations + - If an uneven amount of items to destinations, priority will break the tie +- Many more materials now have Fluid Pipes and Item Pipes +- Multiblocks can now share ALL hatches (energy, item in/out, fluid in/out) excluding Rotor Holders +- Mixer now has 2 more Item Input slots +- Chemical Reactor now has 1 more Item Output Slot +- Distillery now has an Item Output Slot +- GT Wrenches will now work for: BuildCraft, EnderIO, Thermal Expansion, Applied Energistics +- New Covers: + - Computer Monitor: a decorative cover + - Energy Detector Cover: outputs redstone signal based on energy stored (has a few modes) + - Fluid Detector Cover: outputs redstone signal based on fluid stored (has a few modes) + - Item Detector Cover: outputs redstone signal based on items stored (has a few modes) + - Crafting Station Cover: a GT Crafting Station, as a Cover! + - Infinite Water Cover: creates 16 Buckets of water every second +- Air Collectors reworked to Gas Collectors: + - Have different Gases in each dimension + - Use a Programmed Circuit, so can collect different gases in each dimension + - Can be added to by CraftTweaker +- Steam Era reworked: + - Steam Machines: + - Bronze Steam Machines now have double the duration of LV/Steel Steam Machines + - Steel Steam Machines have normal LV duration but 2x the Steam Consumption + - In total, Bronze/Steel/LV machines all have equivalent Steam Consumption (if using Steam Turbine for LV) + - Many early game recipes tweaked to make the Bronze Machine nerf not as bad + - Steel Steam Machine recipes are much more reasonable, requiring at most 1 Steel per machine, and being "direct upgrade" recipes for Bronze Machines + - Steam Boilers: + - Added Steel Solar Boiler + - Boilers have a more clear steam production, now per second instead of 25/10 ticks + - Lava generators buffed by 3x + - Bronze Solar Steam Boiler buffed by 2x +- Many JEI pages reworked (distillation tower, coke oven, assembly line) to be fancier +- Cable Loss reworked: + - Lossless wires will now no longer damage you + - Cables will always have lossy wires, unless they are "Superconductors" + - Superconductors are available at every tier, and are available only wires to reduce clutter +- High-Amp Energy Hatches added (can be configured with a Screwdriver, with amperages: 2, 4, 8, 16) +- High-Amp Transformers added (can be configured with a Screwdriver, with ranges: 1->4, 2->8, 4->16, 16->64) +- Diodes Added, which allow energy flow in one direction and restrict amperage (can be configured with a Screwdriver, with amperages: 1, 2, 4, 8, 16) +- GT Cables and wires can now natively power RF-consuming machines (with config, default true) +- Simple Ore Washer added + - Ore Washer, but only at ULV + - Consumes 100mB of Water per recipe + - Is much faster than an Ore Washer, but grants no byproducts + - Can do: crushed -> crushedPurified, impureDust -> dust, pureDust -> dust + - Effectively an Electric Cauldron +- Fluid Pipe Algorithm fully reworked: + - Pipes will behave similar to GT5, but without sloshing + - Fluids will be evenly split across all directions at a pipe "junction" + - Can also be set to Round Robin (with Pump cover) +- Added Quadruple (4) and Nonuple (9) Pipes, which can move multiple fluid types through them at once +- Distillation Tower Fluid Input Hatch can be placed on any block on the bottom layer. Energy Input Hatch can be placed on any block in the structure +- Added Buffers, which can hold both a small amount of a few types of each Items and Fluids, meant for use in machine automation +- Crafting Station now highlights missing items in saved recipes in red + +### Major Recipe Changes +- Many, many new recipes for Vanilla items and blocks, with various configs to toggle +- Casings now only make 2 per craft (instead of 3), Frames are cheaper to craft +- Polybenzimidazole (PBI) has been added as a late-game polymer +- Some processes have been rebalanced to be better to play with (Sulfuric and Nitric Acids, among others) +- Singleblock Distilleries are now much faster, but do less fluid at a time +- LCR has many recipes to "short-cut" processes (Epoxy, Polyethylene, etc.) +- Uraninite processing is now slightly more complex (2 recipes total) +- Electrolysis recipes are now on average 4x less duration +- Ores that can be "directly smelted" into their materials have been reworked, so that dusts, crushed ore, etc will also direct smelt to the material +- Decomposition Recipes (electrolysis, centrifuging) will now divide down to as few inputs as possible, still retaining full dusts and full buckets of outputs +- Double Plates and Rounds were added, used in specific recipes +- Many, many, many progression-related recipes were fixed (mostly from SoG) to allow full progression in the base mod +- EBF coils now have slightly more complex recipes (configurable, default true) +- Coal Gas and Coal Tar were added as another optional but very beneficial source of resources +- Singleblock Distilleries will now always output the Item in the Distillation Recipe +- Alloys can no longer be handcrafted past Stainless Steel, and require an on-tier Mixer to make +- Harder recipes for Energy Hatches (configurable, default false) +- Config to disable in-world Concrete Powder -> Concrete conversion +- Indium now outputs 1 Small Dust each recipe instead of 1 Tiny Dust +- High Octane Gasoline (HOG) and Nitrobenzene were added as more power options (as well as normal Gasoline) + +### Bug Fixes +- Electric Tools now properly use power over durability +- Many textures were fixed to be more consistent (z-fighting, improper coloration, etc.) +- Drums and Tanks now respect sneaking and will not fill a bucket when sneaking +- Steam Machines are no longer the Icon in JEI for machine categories +- All tiers of wood pipes can now be crafted by hand +- Fix Transformers not updating textures, and not properly sending a chat message +- Machines with lots of slots causing the "Title" to overlap now have a larger GUI (no overlap) +- Fix rare world corruption bug with Redstone cache +- Fix Rubber Trees spawning in a perfect grid pattern +- Drums now properly display their Tank contents in TheOneProbe +- Tools now properly override `getToolClasses()`, leading to better mod compatibility +- Fix Distillation Tower not respecting the output order in some arrangements of output hatches +- Fix GT items being improperly sorted in JEI +- Fix recipes being improperly sorted in each category + - Sorted in groups of voltage-tier, with duration increasing within each tier +- Fix recipes in JEI taking an odd number of ticks rounding up + - 1 tick recipes properly display as 0.05s (instead of 0.1s) + - Example: 19 ticks will show as 0.95s (before would have been 1s) +- Cables and Wires now properly respect amperage on the line +- Machines (and other Energy-acceptors) now no longer accept their maximum amount of amps per side, instead its per container +- Cables will no longer burn improper parts of the network, and now is only the overamped/overvolted portion + +### CraftTweaker +- Materials can now automatically generate IDs + - Be careful, as changing the order of this will cause items in-world to disappear +- Coke Oven and PBF have normal RecipeMaps now, instead of using custom ones + +### Removals +- Potion Fluids placeable in-world were removed +- Fluid Extractor and Extractor were combined into one machine (now Extractor) +- Both Arc Furnaces were combined into one machine (now Arc Furnace) +- Canning Machine and Fluid Canning Machine were combined (now Canning Machine) +- Microwave, Amplifabricator, and Tesla Coil were removed +- Dust-only Materials no longer generate blocks +- GT Chests were removed (in favor of Crates, Super Chests, Quantum Chests) +- Single-Use Batteries were removed (Except the ZPM) +- Energy Field Projector was removed +- Re-breather was removed + +### Misc Changes +- Many Material colors and IconSets (their overall appearance) have been updated +- Machine UIs were updated to be much cleaner, new progress bars, slot icons, better layouts +- Electrolyzer and Centrifuge now show all 12 slots at once + +### Internal Changes +- UHV - UXV Tiers are supported natively by GTCEu for addons to take advantage of +- `Elements` is no longer an Enum +- Machines can now be indestructable and Wither Proof, if properly set in the Class +- Material ID limit was raised from 1,000 to 32,767 + - GTCEu uses 1-2,999 + - Gregicality/SoG uses 3,000-19,999 + - 20,000-32,767 available for modpacks or other addons, not yet claimed +- Material API was rewritten from scratch: + - TODO +- OrePrefix is no longer an Enum, and can easily be added to by addons +- Shaped and Shapeless Recipe methods in `ModHandler` can now accept more types +- `debug` config will now log failed recipe removals and additions +- There is now a "PrimitiveMultiblockController" base class, which uses a normal RecipeMap. When paired with the `PrimitiveRecipeBuilder`, it will: + - Allow recipes to be run without power + - (by default) Initialize inventory for items and fluids to the Controller instead of Multiblock Parts (overridable) + - Hide the EU/t and Total EU info from the JEI page diff --git a/build.gradle.kts b/build.gradle.kts index 5683f955cd0..a75ebbd1565 100755 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -69,7 +69,6 @@ minecraft { mappings = "stable_39" runDir = "run" isUseDepAts = true - makeObfSourceJar = false } repositories { diff --git a/src/main/java/gregtech/GregTechMod.java b/src/main/java/gregtech/GregTechMod.java index 93c20d87cfc..925807f0356 100644 --- a/src/main/java/gregtech/GregTechMod.java +++ b/src/main/java/gregtech/GregTechMod.java @@ -10,6 +10,7 @@ import gregtech.api.model.ResourcePackHook; import gregtech.api.net.NetworkHandler; import gregtech.api.recipes.RecipeMap; +import gregtech.api.terminal.util.GuideJsonLoader; import gregtech.api.unification.OreDictUnifier; import gregtech.api.unification.material.IMaterialHandler; import gregtech.api.unification.material.MaterialRegistry; @@ -36,6 +37,9 @@ import gregtech.common.worldgen.WorldGenRubberTree; import gregtech.integration.theoneprobe.TheOneProbeCompatibility; import gregtech.loaders.dungeon.DungeonLootLoader; +import net.minecraft.client.Minecraft; +import net.minecraft.client.resources.SimpleReloadableResourceManager; +import gregtech.loaders.recipe.component.AnnotatedComponentHandlerLoader; import net.minecraftforge.classloading.FMLForgePlugin; import net.minecraftforge.fluids.FluidRegistry; import net.minecraftforge.fml.common.FMLCommonHandler; @@ -62,6 +66,7 @@ public class GregTechMod { BlockOreFactory.init(); BlockCompressedFactory.init(); BlockFrameFactory.init(); + ((SimpleReloadableResourceManager)Minecraft.getMinecraft().getResourceManager()).registerReloadListener(new GuideJsonLoader()); } } @@ -103,6 +108,9 @@ public void onPreInit(FMLPreInitializationEvent event) { MetaTileEntities.init(); MetaEntities.init(); + // discover annotated crafting component handlers + AnnotatedComponentHandlerLoader.discoverAndLoadAnnotatedComponentHandlers(event.getAsmData()); + proxy.onPreLoad(); } diff --git a/src/main/java/gregtech/api/GTValues.java b/src/main/java/gregtech/api/GTValues.java index 03749fca777..eda97d15f67 100644 --- a/src/main/java/gregtech/api/GTValues.java +++ b/src/main/java/gregtech/api/GTValues.java @@ -1,7 +1,6 @@ package gregtech.api; import gregtech.api.util.XSTR; -import gregtech.common.ConfigHolder; import net.minecraftforge.fml.common.Loader; import net.minecraftforge.oredict.OreDictionary; @@ -91,7 +90,8 @@ public class GTValues { MODID_EIO = "enderio", MODID_BC = "buildcraftcore", MODID_COFH = "cofhcore", - MODID_APPENG = "appliedenergistics2"; + MODID_APPENG = "appliedenergistics2", + MODID_JEI = "jei"; //because forge is too fucking retarded to cache results or at least do not create fucking //immutable collections every time you retrieve indexed mod list @@ -115,43 +115,5 @@ public static boolean isModLoaded(String modid) { /** * Used to tell if any high-tier machine (UHV+) was registered. */ - public static final boolean HT = - ConfigHolder.U.machines.highTierMachines || - ConfigHolder.U.machines.highTierAlloySmelter || - ConfigHolder.U.machines.highTierArcFurnaces || - ConfigHolder.U.machines.highTierAssemblers || - ConfigHolder.U.machines.highTierAutoclaves || - ConfigHolder.U.machines.highTierBenders || - ConfigHolder.U.machines.highTierBreweries || - ConfigHolder.U.machines.highTierCanners || - ConfigHolder.U.machines.highTierCentrifuges || - ConfigHolder.U.machines.highTierChemicalBaths || - ConfigHolder.U.machines.highTierChemicalReactors || - ConfigHolder.U.machines.highTierCompressors || - ConfigHolder.U.machines.highTierCutters || - ConfigHolder.U.machines.highTierDistilleries || - ConfigHolder.U.machines.highTierElectricFurnace || - ConfigHolder.U.machines.highTierElectrolyzers || - ConfigHolder.U.machines.highTierElectromagneticSeparators || - ConfigHolder.U.machines.highTierExtractors || - ConfigHolder.U.machines.highTierExtruders || - ConfigHolder.U.machines.highTierFermenters || - ConfigHolder.U.machines.highTierFluidHeaters || - ConfigHolder.U.machines.highTierFluidSolidifiers || - ConfigHolder.U.machines.highTierForgeHammers || - ConfigHolder.U.machines.highTierFormingPresses || - ConfigHolder.U.machines.highTierLathes || - ConfigHolder.U.machines.highTierMixers || - ConfigHolder.U.machines.highTierOreWashers || - ConfigHolder.U.machines.highTierPackers || - ConfigHolder.U.machines.highTierPolarizers || - ConfigHolder.U.machines.highTierLaserEngravers || - ConfigHolder.U.machines.highTierSifters || - ConfigHolder.U.machines.highTierThermalCentrifuges || - ConfigHolder.U.machines.highTierMacerators || - ConfigHolder.U.machines.highTierUnpackers || - ConfigHolder.U.machines.highTierWiremills || - ConfigHolder.U.machines.highTierMassFabricators || - ConfigHolder.U.machines.highTierReplicators || - ConfigHolder.U.machines.highTierScanners; + public static boolean HT = false; } diff --git a/src/main/java/gregtech/api/GregTechAPI.java b/src/main/java/gregtech/api/GregTechAPI.java index 0467fa1f05d..2b7342f9a81 100644 --- a/src/main/java/gregtech/api/GregTechAPI.java +++ b/src/main/java/gregtech/api/GregTechAPI.java @@ -34,5 +34,4 @@ public static T registerMetaTileEntity(int id, T samp META_TILE_ENTITY_REGISTRY.register(id, sampleMetaTileEntity.metaTileEntityId, sampleMetaTileEntity); return sampleMetaTileEntity; } - } diff --git a/src/main/java/gregtech/api/capability/GregtechCapabilities.java b/src/main/java/gregtech/api/capability/GregtechCapabilities.java index a12a0f5d04a..dd765489b68 100644 --- a/src/main/java/gregtech/api/capability/GregtechCapabilities.java +++ b/src/main/java/gregtech/api/capability/GregtechCapabilities.java @@ -1,12 +1,20 @@ package gregtech.api.capability; +import gregtech.api.GTValues; +import gregtech.api.capability.impl.EUToFEProvider; import gregtech.api.capability.tool.ICutterItem; import gregtech.api.capability.tool.IScrewdriverItem; import gregtech.api.capability.tool.ISoftHammerItem; import gregtech.api.capability.tool.IWrenchItem; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.ResourceLocation; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.capabilities.CapabilityInject; +import net.minecraftforge.event.AttachCapabilitiesEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +@Mod.EventBusSubscriber(modid = GTValues.MODID) public class GregtechCapabilities { @CapabilityInject(IEnergyContainer.class) @@ -33,4 +41,10 @@ public class GregtechCapabilities { @CapabilityInject(IMultiblockController.class) public static Capability CAPABILITY_MULTIBLOCK_CONTROLLER = null; + private static final ResourceLocation CAPABILITY_EU_TO_FE = new ResourceLocation(GTValues.MODID, "fe_capability"); + + @SubscribeEvent + public static void attachTileCapability(AttachCapabilitiesEvent event) { + event.addCapability(CAPABILITY_EU_TO_FE, new EUToFEProvider(event.getObject())); + } } diff --git a/src/main/java/gregtech/api/capability/IEnergyContainer.java b/src/main/java/gregtech/api/capability/IEnergyContainer.java index 241104c2c81..71050a78a1c 100644 --- a/src/main/java/gregtech/api/capability/IEnergyContainer.java +++ b/src/main/java/gregtech/api/capability/IEnergyContainer.java @@ -5,17 +5,32 @@ public interface IEnergyContainer { /** + * This method is basically {@link #changeEnergy(long)}, but it also handles amperes. + * This method should always be used when energy is passed between blocks. + * + * @param voltage amount of energy packets (energy to add / input voltage) + * @param amperage packet size (energy to add / input amperage) * @return amount of used amperes. 0 if not accepted anything. */ long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage); + /** + * @return if this container accepts energy from the given side + */ boolean inputsEnergy(EnumFacing side); + /** + * @return if this container can output energy to the given side + */ default boolean outputsEnergy(EnumFacing side) { return false; } /** + * This changes the amount stored. + * This should only be used internally (f.e. draining while working or filling while generating). + * For transfer between blocks use {@link #acceptEnergyFromNetwork(EnumFacing, long, long)}!!! + * * @param differenceAmount amount of energy to add (>0) or remove (<0) * @return amount of energy added or removed */ @@ -41,45 +56,52 @@ default long removeEnergy(long energyToRemove) { return changeEnergy(-energyToRemove); } + /** + * @return the maximum amount of energy that can be inserted + */ default long getEnergyCanBeInserted() { return getEnergyCapacity() - getEnergyStored(); } /** - * Gets the stored electric energy + * @return amount of currently stored energy */ long getEnergyStored(); /** - * Gets the largest electric energy capacity + * @return maximum amount of storable energy */ long getEnergyCapacity(); /** - * Gets the amount of energy packets per tick. + * @return maximum amount of outputable energy packets per tick */ default long getOutputAmperage() { return 0L; } /** - * Gets the output in energy units per energy packet. + * @return output energy packet size */ default long getOutputVoltage() { return 0L; } /** - * Gets the amount of energy packets this machine can receive + * @return maximum amount of receivable energy packets per tick */ long getInputAmperage(); /** - * Gets the maximum voltage this machine can receive in one energy packet. + * @return output energy packet size * Overflowing this value will explode machine. */ long getInputVoltage(); + /** + * @return true if information like energy capacity should be hidden from TOP. + * Useful for cables + */ default boolean isOneProbeHidden() { return false; } diff --git a/src/main/java/gregtech/api/capability/INotifiableHandler.java b/src/main/java/gregtech/api/capability/INotifiableHandler.java new file mode 100644 index 00000000000..34cf1c36351 --- /dev/null +++ b/src/main/java/gregtech/api/capability/INotifiableHandler.java @@ -0,0 +1,33 @@ +package gregtech.api.capability; + +import gregtech.api.metatileentity.MetaTileEntity; + +/** + * For Item and Fluid handlers capable of notifying entities when + * their contents change + */ +public interface INotifiableHandler { + + /** + * Adds the notified handler to the notified list + * + * @param isExport boolean specifying if a handler is an output handler + */ + + default void addToNotifiedList(MetaTileEntity metaTileEntity, T handler, boolean isExport) { + if (metaTileEntity != null && metaTileEntity.isValid()) { + if (isExport) { + metaTileEntity.addNotifiedOutput(handler); + } else { + metaTileEntity.addNotifiedInput(handler); + } + } + } + + /** + * @param metaTileEntity MetaTileEntity to be notified + */ + default void setNotifiableMetaTileEntity(MetaTileEntity metaTileEntity) { + + } +} diff --git a/src/main/java/gregtech/api/capability/impl/AbstractFuelInfo.java b/src/main/java/gregtech/api/capability/impl/AbstractFuelInfo.java index 5f2e817682d..3edf744a7d1 100755 --- a/src/main/java/gregtech/api/capability/impl/AbstractFuelInfo.java +++ b/src/main/java/gregtech/api/capability/impl/AbstractFuelInfo.java @@ -12,10 +12,6 @@ public abstract class AbstractFuelInfo implements IFuelInfo { private int fuelMinConsumed; private long fuelBurnTime; - public AbstractFuelInfo(final int fuelRemaining, final int fuelCapacity, final int fuelMinConsumed, final int fuelBurnTime) { - this(fuelRemaining, fuelCapacity, fuelMinConsumed, (long) fuelBurnTime); - } - public AbstractFuelInfo(final int fuelRemaining, final int fuelCapacity, final int fuelMinConsumed, final long fuelBurnTime) { this.fuelRemaining = fuelRemaining; this.fuelCapacity = fuelCapacity; diff --git a/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java b/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java old mode 100755 new mode 100644 index 64a6da05fe4..1b5811c764b --- a/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java +++ b/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java @@ -16,6 +16,7 @@ import net.minecraft.nbt.NBTTagList; import net.minecraft.network.PacketBuffer; import net.minecraft.util.NonNullList; +import net.minecraft.world.*; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.util.Constants; import net.minecraftforge.fluids.FluidStack; @@ -24,7 +25,6 @@ import net.minecraftforge.items.IItemHandlerModifiable; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; import java.util.Random; import java.util.function.LongSupplier; @@ -36,9 +36,6 @@ public abstract class AbstractRecipeLogic extends MTETrait implements IWorkable public final RecipeMap recipeMap; - protected boolean forceRecipeRecheck; - protected ItemStack[] lastItemInputs; - protected FluidStack[] lastFluidInputs; protected Recipe previousRecipe; protected boolean allowOverclocking = true; private long overclockVoltage = 0; @@ -55,6 +52,8 @@ public abstract class AbstractRecipeLogic extends MTETrait implements IWorkable protected boolean workingEnabled = true; protected boolean hasNotEnoughEnergy; protected boolean wasActiveAndNeedsUpdate; + protected boolean isOutputsFull; + protected boolean invalidInputsForRecipes; protected boolean hasPerfectOC = false; @@ -115,12 +114,14 @@ public T getCapability(Capability capability) { @Override public void update() { - if (!getMetaTileEntity().getWorld().isRemote) { + World world = getMetaTileEntity().getWorld(); + if (world != null && !world.isRemote) { if (workingEnabled) { if (progressTime > 0) { updateRecipeProgress(); } - if (progressTime == 0) { + //check everything that would make a recipe never start here. + if (progressTime == 0 && shouldSearchForRecipes()) { trySearchNewRecipe(); } } @@ -131,6 +132,40 @@ public void update() { } } + protected boolean shouldSearchForRecipes() { + return canWorkWithInputs() && canFitNewOutputs(); + } + + protected boolean hasNotifiedInputs() { + return (metaTileEntity.getNotifiedItemInputList().size() > 0 || + metaTileEntity.getNotifiedFluidInputList().size() > 0); + } + + protected boolean hasNotifiedOutputs() { + return (metaTileEntity.getNotifiedItemOutputList().size() > 0 || + metaTileEntity.getNotifiedFluidOutputList().size() > 0); + } + + protected boolean canFitNewOutputs() { + // if the output is full check if the output changed so we can process recipes results again. + if (this.isOutputsFull && !hasNotifiedOutputs()) return false; + else { + this.isOutputsFull = false; + metaTileEntity.getNotifiedItemOutputList().clear(); + metaTileEntity.getNotifiedFluidOutputList().clear(); + } + return true; + } + + protected boolean canWorkWithInputs() { + // if the inputs were bad last time, check if they've changed before trying to find a new recipe. + if (this.invalidInputsForRecipes && !hasNotifiedInputs()) return false; + else { + this.invalidInputsForRecipes = false; + } + return true; + } + protected void updateRecipeProgress() { boolean drawEnergy = drawEnergy(recipeEUt); if (drawEnergy || (recipeEUt < 0)) { @@ -158,27 +193,26 @@ protected void trySearchNewRecipe() { Recipe currentRecipe = null; IItemHandlerModifiable importInventory = getInputInventory(); IMultipleTankHandler importFluids = getInputTank(); - if (previousRecipe != null && previousRecipe.matches(false, importInventory, importFluids)) { - //if previous recipe still matches inputs, try to use it - currentRecipe = previousRecipe; - } else { - boolean dirty = checkRecipeInputsDirty(importInventory, importFluids); - if (dirty || forceRecipeRecheck) { - this.forceRecipeRecheck = false; - //else, try searching new recipe for given inputs - currentRecipe = findRecipe(maxVoltage, importInventory, importFluids, MatchingMode.DEFAULT); - if (currentRecipe != null) { - this.previousRecipe = currentRecipe; - } - } + + // see if the last recipe we used still works + if (this.previousRecipe != null && this.previousRecipe.matches(false, importInventory, importFluids)) + currentRecipe = this.previousRecipe; + // If there is no active recipe, then we need to find one. + else { + currentRecipe = findRecipe(maxVoltage, importInventory, importFluids, MatchingMode.DEFAULT); } - if (currentRecipe != null && setupAndConsumeRecipeInputs(currentRecipe)) { - setupRecipe(currentRecipe); + // If a recipe was found, then inputs were valid. Cache found recipe. + if (currentRecipe != null) { + this.previousRecipe = currentRecipe; } - } + this.invalidInputsForRecipes = (currentRecipe == null); - public void forceRecipeRecheck() { - this.forceRecipeRecheck = true; + // proceed if we have a usable recipe. + if (currentRecipe != null && setupAndConsumeRecipeInputs(currentRecipe)) + setupRecipe(currentRecipe); + // Inputs have been inspected. + metaTileEntity.getNotifiedItemInputList().clear(); + metaTileEntity.getNotifiedFluidInputList().clear(); } protected int getMinTankCapacity(IMultipleTankHandler tanks) { @@ -196,42 +230,6 @@ protected Recipe findRecipe(long maxVoltage, IItemHandlerModifiable inputs, IMul return recipeMap.findRecipe(maxVoltage, inputs, fluidInputs, getMinTankCapacity(getOutputTank()), mode); } - protected boolean checkRecipeInputsDirty(IItemHandler inputs, IMultipleTankHandler fluidInputs) { - boolean shouldRecheckRecipe = false; - if (lastItemInputs == null || lastItemInputs.length != inputs.getSlots()) { - this.lastItemInputs = new ItemStack[inputs.getSlots()]; - Arrays.fill(lastItemInputs, ItemStack.EMPTY); - } - if (lastFluidInputs == null || lastFluidInputs.length != fluidInputs.getTanks()) { - this.lastFluidInputs = new FluidStack[fluidInputs.getTanks()]; - } - for (int i = 0; i < lastItemInputs.length; i++) { - ItemStack currentStack = inputs.getStackInSlot(i); - ItemStack lastStack = lastItemInputs[i]; - if (!areItemStacksEqual(currentStack, lastStack)) { - this.lastItemInputs[i] = currentStack.isEmpty() ? ItemStack.EMPTY : currentStack.copy(); - shouldRecheckRecipe = true; - } else if (currentStack.getCount() != lastStack.getCount()) { - lastStack.setCount(currentStack.getCount()); - shouldRecheckRecipe = true; - } - } - for (int i = 0; i < lastFluidInputs.length; i++) { - FluidStack currentStack = fluidInputs.getTankAt(i).getFluid(); - FluidStack lastStack = lastFluidInputs[i]; - if ((currentStack == null && lastStack != null) || - (currentStack != null && !currentStack.isFluidEqual(lastStack))) { - this.lastFluidInputs[i] = currentStack == null ? null : currentStack.copy(); - shouldRecheckRecipe = true; - } else if (currentStack != null && lastStack != null && - currentStack.amount != lastStack.amount) { - lastStack.amount = currentStack.amount; - shouldRecheckRecipe = true; - } - } - return shouldRecheckRecipe; - } - protected static boolean areItemStacksEqual(ItemStack stackA, ItemStack stackB) { return (stackA.isEmpty() && stackB.isEmpty()) || (ItemStack.areItemsEqual(stackA, stackB) && @@ -245,11 +243,20 @@ protected boolean setupAndConsumeRecipeInputs(Recipe recipe) { IItemHandlerModifiable exportInventory = getOutputInventory(); IMultipleTankHandler importFluids = getInputTank(); IMultipleTankHandler exportFluids = getOutputTank(); - return (totalEUt >= 0 ? getEnergyStored() >= (totalEUt > getEnergyCapacity() / 2 ? resultOverclock[0] : totalEUt) : - (getEnergyStored() - resultOverclock[0] <= getEnergyCapacity())) && - MetaTileEntity.addItemsToItemHandler(exportInventory, true, recipe.getAllItemOutputs(exportInventory.getSlots())) && - MetaTileEntity.addFluidsToFluidHandler(exportFluids, true, recipe.getFluidOutputs()) && - recipe.matches(true, importInventory, importFluids); + if (!(totalEUt >= 0 ? getEnergyStored() >= (totalEUt > getEnergyCapacity() / 2 ? resultOverclock[0] : totalEUt) : + (getEnergyStored() - resultOverclock[0] <= getEnergyCapacity()))) { + return false; + } + if (!MetaTileEntity.addItemsToItemHandler(exportInventory, true, recipe.getAllItemOutputs(exportInventory.getSlots()))) { + this.isOutputsFull = true; + return false; + } + if (!MetaTileEntity.addFluidsToFluidHandler(exportFluids, true, recipe.getFluidOutputs())) { + this.isOutputsFull = true; + return false; + } + this.isOutputsFull = false; + return recipe.matches(true, importInventory, importFluids); } protected int[] calculateOverclock(int EUt, int duration) { @@ -294,9 +301,9 @@ protected long getVoltageByTier(final int tier) { public String[] getAvailableOverclockingTiers() { final int maxTier = getOverclockingTier(getMaxVoltage()); - final String[] result = new String[maxTier + 2]; + final String[] result = new String[maxTier + 1]; result[0] = "gregtech.gui.overclock.off"; - if (maxTier + 1 >= 0) System.arraycopy(GTValues.VN, 0, result, 1, maxTier + 1); + if (maxTier >= 0) System.arraycopy(GTValues.VN, 1, result, 1, maxTier); return result; } @@ -329,9 +336,6 @@ protected void completeRecipe() { this.itemOutputs = null; this.hasNotEnoughEnergy = false; this.wasActiveAndNeedsUpdate = true; - //force recipe recheck because inputs could have changed since last time - //we checked them before starting our recipe, especially if recipe took long time - this.forceRecipeRecheck = true; } public double getProgressPercent() { @@ -364,7 +368,8 @@ public void setMaxProgress(int maxProgress) { protected void setActive(boolean active) { this.isActive = active; metaTileEntity.markDirty(); - if (!metaTileEntity.getWorld().isRemote) { + World world = metaTileEntity.getWorld(); + if (world != null && !world.isRemote) { writeCustomData(1, buf -> buf.writeBoolean(active)); } } @@ -422,13 +427,11 @@ public void enableOverclockVoltage() { setOverclockVoltage(getMaxVoltage()); } - // The overclocking tier - // it is 1 greater than the index into GTValues.V since here the "0 tier" represents 0 EU or no overclock public int getOverclockTier() { if (this.overclockVoltage == 0) { return 0; } - return 1 + getOverclockingTier(this.overclockVoltage); + return getOverclockingTier(this.overclockVoltage); } public void setOverclockTier(final int tier) { @@ -436,7 +439,7 @@ public void setOverclockTier(final int tier) { setOverclockVoltage(0); return; } - setOverclockVoltage(getVoltageByTier(tier - 1)); + setOverclockVoltage(getVoltageByTier(tier)); } @Override diff --git a/src/main/java/gregtech/api/capability/impl/EUToFEProvider.java b/src/main/java/gregtech/api/capability/impl/EUToFEProvider.java new file mode 100644 index 00000000000..70a62ed3287 --- /dev/null +++ b/src/main/java/gregtech/api/capability/impl/EUToFEProvider.java @@ -0,0 +1,67 @@ +package gregtech.api.capability.impl; + +import gregtech.api.capability.GregtechCapabilities; +import gregtech.common.ConfigHolder; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.EnumFacing; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.capabilities.ICapabilityProvider; +import net.minecraftforge.energy.CapabilityEnergy; + +import javax.annotation.Nonnull; +import java.util.concurrent.locks.ReentrantLock; + +public class EUToFEProvider implements ICapabilityProvider { + + private final TileEntity tileEntity; + private GTEnergyWrapper wrapper; + + /** + * Lock used for concurrency protection between hasCapability and getCapability. + */ + ReentrantLock lock = new ReentrantLock(); + + public EUToFEProvider(TileEntity tileEntity) { + this.tileEntity = tileEntity; + } + + @Override + public boolean hasCapability(@Nonnull Capability capability, EnumFacing facing) { + + if (!ConfigHolder.U.energyOptions.nativeEUToFE) + return false; + + if (lock.isLocked() || (capability != CapabilityEnergy.ENERGY && capability != GregtechCapabilities.CAPABILITY_ENERGY_CONTAINER)) + return false; + + // Wrap FE Machines with a GTEU EnergyContainer + if (wrapper == null) wrapper = new GTEnergyWrapper(tileEntity); + + lock.lock(); + try { + return wrapper.isValid(facing); + } finally { + lock.unlock(); + } + } + + @Override + @SuppressWarnings("unchecked") + public T getCapability(@Nonnull Capability capability, EnumFacing facing) { + + if (!ConfigHolder.U.energyOptions.nativeEUToFE) + return null; + + if (lock.isLocked() || !hasCapability(capability, facing)) + return null; + + if (wrapper == null) wrapper = new GTEnergyWrapper(tileEntity); + + lock.lock(); + try { + return wrapper.isValid(facing) ? (T) wrapper : null; + } finally { + lock.unlock(); + } + } +} diff --git a/src/main/java/gregtech/api/capability/impl/EnergyContainerBatteryBuffer.java b/src/main/java/gregtech/api/capability/impl/EnergyContainerBatteryBuffer.java index 2432653ee7d..f50a6e67bba 100644 --- a/src/main/java/gregtech/api/capability/impl/EnergyContainerBatteryBuffer.java +++ b/src/main/java/gregtech/api/capability/impl/EnergyContainerBatteryBuffer.java @@ -23,6 +23,7 @@ public class EnergyContainerBatteryBuffer extends MTETrait implements IEnergyCon private final BitSet batterySlotsUsedThisTick = new BitSet(); private final int tier; + private long amps = 0; public EnergyContainerBatteryBuffer(MetaTileEntity metaTileEntity, int tier) { super(metaTileEntity); @@ -31,11 +32,14 @@ public EnergyContainerBatteryBuffer(MetaTileEntity metaTileEntity, int tier) { @Override public long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage) { - long initialAmperage = amperage; + long usedAmps = 0; + amperage -= amps; + if(amperage <= 0) + return 0; if (side == null || inputsEnergy(side)) { if (voltage > getInputVoltage()) { GTUtility.doOvervoltageExplosion(metaTileEntity, voltage); - return Math.min(amperage, getInputAmperage()); + return Math.min(amperage, getInputAmperage() - amps); } IItemHandlerModifiable inventory = getInventory(); for (int i = 0; i < inventory.getSlots(); i++) { @@ -47,15 +51,15 @@ public long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage chargeItemWithVoltage(electricItem, voltage, getTier(), false); inventory.setStackInSlot(i, batteryStack); this.batterySlotsUsedThisTick.set(i); - if (--amperage == 0) break; + if(++usedAmps == amperage) break; } } } - long amperageUsed = initialAmperage - amperage; - if (amperageUsed > 0L) { + if (usedAmps > 0L) { notifyEnergyListener(false); } - return amperageUsed; + amps += usedAmps; + return usedAmps; } private static boolean chargeItemWithVoltage(IElectricItem electricItem, long voltage, int tier, boolean simulate) { @@ -73,6 +77,7 @@ private static long chargeItem(IElectricItem electricItem, long amount, int tier @Override public void update() { + amps = 0; if (!metaTileEntity.getWorld().isRemote) { this.batterySlotsUsedThisTick.clear(); EnumFacing outFacing = metaTileEntity.getFrontFacing(); diff --git a/src/main/java/gregtech/api/capability/impl/EnergyContainerHandler.java b/src/main/java/gregtech/api/capability/impl/EnergyContainerHandler.java index 9a22a0cd20b..666b8442ccf 100644 --- a/src/main/java/gregtech/api/capability/impl/EnergyContainerHandler.java +++ b/src/main/java/gregtech/api/capability/impl/EnergyContainerHandler.java @@ -29,6 +29,8 @@ public class EnergyContainerHandler extends MTETrait implements IEnergyContainer private Predicate sideInputCondition; private Predicate sideOutputCondition; + private long amps = 0; + public EnergyContainerHandler(MetaTileEntity tileEntity, long maxCapacity, long maxInputVoltage, long maxInputAmperage, long maxOutputVoltage, long maxOutputAmperage) { super(tileEntity); this.maxCapacity = maxCapacity; @@ -133,6 +135,7 @@ public boolean dischargeOrRechargeEnergyContainers(IItemHandlerModifiable itemHa @Override public void update() { + amps = 0; if (getMetaTileEntity().getWorld().isRemote) return; if (getEnergyStored() >= getOutputVoltage() && getOutputVoltage() > 0 && getOutputAmperage() > 0) { @@ -159,16 +162,18 @@ public void update() { @Override public long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage) { + if(amps >= getInputAmperage()) return 0; long canAccept = getEnergyCapacity() - getEnergyStored(); - if (voltage > 0L && amperage > 0L && (side == null || inputsEnergy(side))) { + if (voltage > 0L && (side == null || inputsEnergy(side))) { if (voltage > getInputVoltage()) { GTUtility.doOvervoltageExplosion(metaTileEntity, voltage); - return Math.min(amperage, getInputAmperage()); + return Math.min(amperage, getInputAmperage() - amps); } if (canAccept >= voltage) { - long amperesAccepted = Math.min(canAccept / voltage, Math.min(amperage, getInputAmperage())); + long amperesAccepted = Math.min(canAccept / voltage, Math.min(amperage, getInputAmperage() - amps)); if (amperesAccepted > 0) { setEnergyStored(getEnergyStored() + voltage * amperesAccepted); + amps += amperesAccepted; return amperesAccepted; } } diff --git a/src/main/java/gregtech/api/capability/impl/GTEnergyWrapper.java b/src/main/java/gregtech/api/capability/impl/GTEnergyWrapper.java new file mode 100644 index 00000000000..e758843f3ce --- /dev/null +++ b/src/main/java/gregtech/api/capability/impl/GTEnergyWrapper.java @@ -0,0 +1,338 @@ +package gregtech.api.capability.impl; + +import gregtech.api.GTValues; +import gregtech.api.capability.IEnergyContainer; +import gregtech.api.util.GTUtility; +import gregtech.common.ConfigHolder; +import net.minecraft.util.EnumFacing; +import net.minecraftforge.common.capabilities.ICapabilityProvider; +import net.minecraftforge.energy.CapabilityEnergy; +import net.minecraftforge.energy.IEnergyStorage; + +import javax.annotation.Nullable; + +public class GTEnergyWrapper implements IEnergyContainer { + + /** + * Capability Provider of the FE TileEntity for the EU-capability. + */ + private final ICapabilityProvider upvalue; + + /** + * Capability holder for the FE-capability. + */ + private final IEnergyStorage[] facesFE = new IEnergyStorage[7]; + + /** + * Internally used FE Buffer so that a very large packet of EU is not partially destroyed + * on the conversion to FE. This is hidden from the player, but ensures that no energy + * is ever lost on conversion, no matter the voltage tier or FE storage abilities. + */ + private long feBuffer = 0; + + protected GTEnergyWrapper(ICapabilityProvider upvalue) { + this.upvalue = upvalue; + } + + /** + * Test this EnergyContainer for sided Capabilities. + * + * @param side The side of the TileEntity to test for the Capability + * @return True if side has Capability, false otherwise + */ + protected boolean isValid(EnumFacing side) { + + if (upvalue.hasCapability(CapabilityEnergy.ENERGY, side)) + return true; + + if (side == null) { + for (EnumFacing face2 : EnumFacing.VALUES) { + if (upvalue.hasCapability(CapabilityEnergy.ENERGY, face2)) { + return true; + } + } + } + return false; + } + + private IEnergyStorage getStorageCap() { + + IEnergyStorage container = def(); + + if (container != null && container.getMaxEnergyStored() > 0) + return container; + + for (EnumFacing face : EnumFacing.VALUES) { + container = facesFE[face.getIndex()]; + + if (container == null) { + container = upvalue.getCapability(CapabilityEnergy.ENERGY, face); + facesFE[face.getIndex()] = container; + } + + if (container != null && container.getMaxEnergyStored() > 0) + return container; + } + + return container; + } + + private IEnergyStorage getAcceptingCap() { + + IEnergyStorage container = def(); + + if (container != null && container.canReceive()) + return container; + + for (EnumFacing face : EnumFacing.VALUES) { + container = facesFE[face.getIndex()]; + + if (container == null) { + container = upvalue.getCapability(CapabilityEnergy.ENERGY, face); + facesFE[face.getIndex()] = container; + } + + if (container != null && container.canReceive()) + return container; + } + + return container; + } + + @Override + public long acceptEnergyFromNetwork(EnumFacing facing, long voltage, long amperage) { + + int faceID = facing == null ? 6 : facing.getIndex(); + IEnergyStorage container = facesFE[faceID]; + + if (container == null) { + container = upvalue.getCapability(CapabilityEnergy.ENERGY, facing); + facesFE[faceID] = container; + } + + if (container == null) + return 0L; + + int receive = 0; + + // Try to use the internal buffer before consuming a new packet + if (feBuffer > 0) { + + receive = container.receiveEnergy(safeCastLongToInt(feBuffer), true); + + if (receive == 0) + return 0; + + // Internal Buffer could provide the max RF the consumer could consume + if (feBuffer > receive) { + feBuffer -= receive; + container.receiveEnergy(receive, false); + return 0; + + // Buffer could not provide max value, save the remainder and continue processing + } else { + receive = safeCastLongToInt(feBuffer); + feBuffer = 0; + } + } + + long maxPacket = (long) (voltage * ConfigHolder.U.energyOptions.rfRatio); + long maximalValue = maxPacket * amperage; + + // Try to consume our remainder buffer plus a fresh packet + if (receive != 0) { + + int consumable = container.receiveEnergy(safeCastLongToInt(maximalValue + receive), true); + + // Machine unable to consume any power + // Probably unnecessary in this case, but just to be safe + if (consumable == 0) + return 0; + + // Only able to consume our buffered amount + if (consumable == receive) { + container.receiveEnergy(consumable, false); + return 0; + } + + // Able to consume our full packet as well as our remainder buffer + if (consumable == maximalValue + receive) { + container.receiveEnergy(consumable, false); + return amperage; + } + + int newPower = consumable - receive; + + // Able to consume buffered amount plus an even amount of packets (no buffer needed) + if (newPower % maxPacket == 0) { + return container.receiveEnergy(consumable, false) / maxPacket; + } + + // Able to consume buffered amount plus some amount of power with a packet remainder + int ampsToConsume = safeCastLongToInt((newPower / maxPacket) + 1); + feBuffer = safeCastLongToInt((maxPacket * ampsToConsume) - consumable); + container.receiveEnergy(consumable, false); + return ampsToConsume; + + // Else try to draw 1 full packet + } else { + + int consumable = container.receiveEnergy(safeCastLongToInt(maximalValue), true); + + // Machine unable to consume any power + if (consumable == 0) + return 0; + + // Able to accept the full amount of power + if (consumable == maximalValue) { + container.receiveEnergy(consumable, false); + return amperage; + } + + // Able to consume an even amount of packets + if (consumable % maxPacket == 0) { + return container.receiveEnergy(consumable, false) / maxPacket; + } + + // Able to consume power with some amount of power remainder in the packet + int ampsToConsume = safeCastLongToInt((consumable / maxPacket) + 1); + feBuffer = safeCastLongToInt((maxPacket * ampsToConsume) - consumable); + container.receiveEnergy(consumable, false); + return ampsToConsume; + } + } + + @Override + public long changeEnergy(long delta) { + + IEnergyStorage container = getStorageCap(); + + if (container == null || delta == 0) + return 0; + + long energyValue = (long) (delta * ConfigHolder.U.energyOptions.rfRatio); + if (energyValue > Integer.MAX_VALUE) + energyValue = Integer.MAX_VALUE; + + if (delta < 0L) { + + int extract = container.extractEnergy(safeCastLongToInt(energyValue), true); + + if (extract != ConfigHolder.U.energyOptions.rfRatio) + extract -= extract % ConfigHolder.U.energyOptions.rfRatio; + + return (long) (container.extractEnergy(extract, false) / ConfigHolder.U.energyOptions.rfRatio); + + } else { + + int receive = container.receiveEnergy((int) energyValue, true); + + if (receive != ConfigHolder.U.energyOptions.rfRatio) + receive -= receive % ConfigHolder.U.energyOptions.rfRatio; + + return (long) (container.receiveEnergy(receive, false) / ConfigHolder.U.energyOptions.rfRatio); + } + } + + @Nullable + private IEnergyStorage def() { + + if (facesFE[6] == null) + facesFE[6] = upvalue.getCapability(CapabilityEnergy.ENERGY, null); + + return facesFE[6]; + } + + @Override + public long getEnergyCapacity() { + IEnergyStorage cap = getStorageCap(); + + if (cap == null) + return 0L; + + return (long) (cap.getMaxEnergyStored() / ConfigHolder.U.energyOptions.rfRatio); + } + + @Override + public long getEnergyStored() { + IEnergyStorage cap = getStorageCap(); + + if (cap == null) + return 0L; + + return (long) (cap.getEnergyStored() / ConfigHolder.U.energyOptions.rfRatio); + } + + @Override + public long getInputAmperage() { + IEnergyStorage container = getAcceptingCap(); + + if (container == null) + return 0; + + long voltage = getInputVoltage(); + + return voltage == 0 ? 0 : 2; + } + + @Override + public long getInputVoltage() { + IEnergyStorage container = getStorageCap(); + + if (container == null) + return 0; + + long maxInput = container.receiveEnergy(Integer.MAX_VALUE, true); + + if (maxInput == 0) + return 0; + + maxInput = (long) (maxInput / ConfigHolder.U.energyOptions.rfRatio); + return GTValues.V[GTUtility.getTierByVoltage(maxInput)]; + } + + @Override + public boolean inputsEnergy(EnumFacing facing) { + + int faceID = facing == null ? 6 : facing.getIndex(); + IEnergyStorage container = facesFE[faceID]; + + if (container == null) { + container = upvalue.getCapability(CapabilityEnergy.ENERGY, facing); + facesFE[faceID] = container; + } + + if (container == null) + return false; + + return container.canReceive(); + } + + /** + * Wrapped FE-consumers should not be able to output EU. + */ + @Override + public boolean outputsEnergy(EnumFacing facing) { + return false; + } + + /** + * Hide this TileEntity EU-capability in TOP. Allows FE-machines to + * "silently" accept EU without showing their charge in EU in TOP. + * Let the machine display it in FE instead, however it chooses to. + */ + @Override + public boolean isOneProbeHidden() { + return true; + } + + /** + * Safely cast a Long to an Int without overflow. + * + * @param v The Long value to cast to an Int. + * @return v, casted to Int, or Integer.MAX_VALUE if it would overflow. + */ + public static int safeCastLongToInt(long v) { + return v > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) v; + } +} diff --git a/src/main/java/gregtech/api/capability/impl/MultiblockRecipeLogic.java b/src/main/java/gregtech/api/capability/impl/MultiblockRecipeLogic.java index 7dc2a72f927..77c2b437576 100644 --- a/src/main/java/gregtech/api/capability/impl/MultiblockRecipeLogic.java +++ b/src/main/java/gregtech/api/capability/impl/MultiblockRecipeLogic.java @@ -29,7 +29,13 @@ public void updateWorkable() { * Used to reset cached values in the Recipe Logic on structure deform */ public void invalidate() { - + previousRecipe = null; + progressTime = 0; + maxProgressTime = 0; + recipeEUt = 0; + fluidOutputs = null; + itemOutputs = null; + setActive(false); // this marks dirty for us } public IEnergyContainer getEnergyContainer() { diff --git a/src/main/java/gregtech/api/capability/impl/NotifiableFilteredFluidHandler.java b/src/main/java/gregtech/api/capability/impl/NotifiableFilteredFluidHandler.java new file mode 100644 index 00000000000..7e5d3ab4554 --- /dev/null +++ b/src/main/java/gregtech/api/capability/impl/NotifiableFilteredFluidHandler.java @@ -0,0 +1,27 @@ +package gregtech.api.capability.impl; + +import gregtech.api.capability.INotifiableHandler; +import gregtech.api.metatileentity.MetaTileEntity; + +public class NotifiableFilteredFluidHandler extends FilteredFluidHandler implements INotifiableHandler { + + MetaTileEntity notifiableEntity; + private final boolean isExport; + + public NotifiableFilteredFluidHandler(int capacity, MetaTileEntity entityToNotify, boolean isExport) { + super(capacity); + this.notifiableEntity = entityToNotify; + this.isExport = isExport; + } + + @Override + protected void onContentsChanged() { + super.onContentsChanged(); + addToNotifiedList(notifiableEntity, this, isExport); + } + + @Override + public void setNotifiableMetaTileEntity(MetaTileEntity metaTileEntity) { + this.notifiableEntity = metaTileEntity; + } +} diff --git a/src/main/java/gregtech/api/capability/impl/NotifiableFluidTank.java b/src/main/java/gregtech/api/capability/impl/NotifiableFluidTank.java new file mode 100644 index 00000000000..2c54e096dbc --- /dev/null +++ b/src/main/java/gregtech/api/capability/impl/NotifiableFluidTank.java @@ -0,0 +1,28 @@ +package gregtech.api.capability.impl; + +import gregtech.api.capability.INotifiableHandler; +import gregtech.api.metatileentity.MetaTileEntity; +import net.minecraftforge.fluids.FluidTank; + +public class NotifiableFluidTank extends FluidTank implements INotifiableHandler { + + MetaTileEntity notifiableEntity; + private final boolean isExport; + + public NotifiableFluidTank(int capacity, MetaTileEntity entityToNotify, boolean isExport) { + super(capacity); + this.notifiableEntity = entityToNotify; + this.isExport = isExport; + } + + @Override + protected void onContentsChanged() { + super.onContentsChanged(); + addToNotifiedList(notifiableEntity, this, isExport); + } + + @Override + public void setNotifiableMetaTileEntity(MetaTileEntity metaTileEntity) { + this.notifiableEntity = metaTileEntity; + } +} diff --git a/src/main/java/gregtech/api/capability/impl/NotifiableItemStackHandler.java b/src/main/java/gregtech/api/capability/impl/NotifiableItemStackHandler.java new file mode 100644 index 00000000000..88e3c58e07b --- /dev/null +++ b/src/main/java/gregtech/api/capability/impl/NotifiableItemStackHandler.java @@ -0,0 +1,29 @@ +package gregtech.api.capability.impl; + +import gregtech.api.capability.INotifiableHandler; +import gregtech.api.metatileentity.MetaTileEntity; +import net.minecraftforge.items.IItemHandlerModifiable; +import net.minecraftforge.items.ItemStackHandler; + +public class NotifiableItemStackHandler extends ItemStackHandler implements IItemHandlerModifiable, INotifiableHandler { + + MetaTileEntity notifiableEntity; + private final boolean isExport; + + public NotifiableItemStackHandler(int slots, MetaTileEntity entityToNotify, boolean isExport) { + super(slots); + this.notifiableEntity = entityToNotify; + this.isExport = isExport; + } + + @Override + public void onContentsChanged(int slot) { + super.onContentsChanged(slot); + addToNotifiedList(notifiableEntity, this, isExport); + } + + @Override + public void setNotifiableMetaTileEntity(MetaTileEntity metaTileEntity) { + this.notifiableEntity = metaTileEntity; + } +} diff --git a/src/main/java/gregtech/api/capability/impl/PrimitiveRecipeLogic.java b/src/main/java/gregtech/api/capability/impl/PrimitiveRecipeLogic.java new file mode 100644 index 00000000000..76568261c2e --- /dev/null +++ b/src/main/java/gregtech/api/capability/impl/PrimitiveRecipeLogic.java @@ -0,0 +1,58 @@ +package gregtech.api.capability.impl; + +import gregtech.api.GTValues; +import gregtech.api.metatileentity.multiblock.RecipeMapPrimitiveMultiblockController; +import gregtech.api.recipes.RecipeMap; + +/** + * Recipe Logic for a Multiblock that does not require power. + */ +public class PrimitiveRecipeLogic extends AbstractRecipeLogic { + + public PrimitiveRecipeLogic(RecipeMapPrimitiveMultiblockController tileEntity, RecipeMap recipeMap) { + super(tileEntity, recipeMap); + } + + @Override + protected long getEnergyStored() { + return Integer.MAX_VALUE; + } + + @Override + protected long getEnergyCapacity() { + return Integer.MAX_VALUE; + } + + @Override + protected boolean drawEnergy(int recipeEUt) { + return true; // spoof energy being drawn + } + + @Override + protected long getMaxVoltage() { + return GTValues.LV; + } + + @Override + protected int[] calculateOverclock(int EUt, long voltage, int duration) { + return new int[]{1, duration}; + } + + @Override + protected int getOverclockingTier(long voltage) { + return GTValues.LV; // just return something reasonable + } + + /** + * Used to reset cached values in the Recipe Logic on structure deform + */ + public void invalidate() { + previousRecipe = null; + progressTime = 0; + maxProgressTime = 0; + recipeEUt = 0; + fluidOutputs = null; + itemOutputs = null; + setActive(false); // this marks dirty for us + } +} diff --git a/src/main/java/gregtech/api/capability/impl/RecipeLogicSteam.java b/src/main/java/gregtech/api/capability/impl/RecipeLogicSteam.java index c33252a0bdb..6e3055d8510 100644 --- a/src/main/java/gregtech/api/capability/impl/RecipeLogicSteam.java +++ b/src/main/java/gregtech/api/capability/impl/RecipeLogicSteam.java @@ -160,11 +160,11 @@ protected void completeRecipe() { @Override protected int[] calculateOverclock(int EUt, long voltage, int duration) { - if (!isHighPressure) { - //disallow overclocking for low pressure bronze machines - return new int[]{EUt, duration}; - } - return super.calculateOverclock(EUt, voltage, duration); + // double duration for normal Steam machines, double EUt for HP Steam + return new int[]{ + isHighPressure ? EUt * 2 : EUt, + isHighPressure ? duration : duration * 2 + }; } @Override diff --git a/src/main/java/gregtech/api/capability/impl/SteamMultiWorkable.java b/src/main/java/gregtech/api/capability/impl/SteamMultiWorkable.java index 3bb9f1f8d7f..451d280d563 100644 --- a/src/main/java/gregtech/api/capability/impl/SteamMultiWorkable.java +++ b/src/main/java/gregtech/api/capability/impl/SteamMultiWorkable.java @@ -1,6 +1,7 @@ package gregtech.api.capability.impl; import gregtech.api.capability.IMultipleTankHandler; +import gregtech.api.metatileentity.multiblock.RecipeMapSteamMultiblockController; import gregtech.api.recipes.CountableIngredient; import gregtech.api.recipes.MatchingMode; import gregtech.api.recipes.Recipe; @@ -33,22 +34,29 @@ protected void trySearchNewRecipe() { long maxVoltage = getMaxVoltage(); // Will always be LV voltage Recipe currentRecipe = null; IItemHandlerModifiable importInventory = getInputInventory(); - boolean dirty = checkRecipeInputsDirty(importInventory, null); - - if (dirty || forceRecipeRecheck) { - this.forceRecipeRecheck = false; - - currentRecipe = findRecipe(maxVoltage, importInventory, null, MatchingMode.DEFAULT); - if (currentRecipe != null) { - this.previousRecipe = currentRecipe; - } - } else if (previousRecipe != null && previousRecipe.matches(false, importInventory, new FluidTankList(false))) { + IMultipleTankHandler importFluids = getInputTank(); + + //inverse of logic in normal AbstractRecipeLogic + //for MultiSmelter, we can reuse previous recipe if inputs didn't change + //otherwise, we need to recompute it for new ingredients + //but technically, it means we can cache multi smelter recipe, but changing inputs have more priority + if (hasNotifiedInputs() || + previousRecipe == null || + !previousRecipe.matches(false, importInventory, importFluids, MatchingMode.IGNORE_FLUIDS)) { + //Inputs changed, try searching new recipe for given inputs + currentRecipe = findRecipe(maxVoltage, importInventory, importFluids, MatchingMode.IGNORE_FLUIDS); + } else { + //if previous recipe still matches inputs, try to use it currentRecipe = previousRecipe; } - - if (currentRecipe != null && setupAndConsumeRecipeInputs(currentRecipe)) { + if (currentRecipe != null) + // replace old recipe with new one + this.previousRecipe = currentRecipe; + // proceed if we have a usable recipe. + if (currentRecipe != null && setupAndConsumeRecipeInputs(currentRecipe)) setupRecipe(currentRecipe); - } + // Inputs have been inspected. + metaTileEntity.getNotifiedItemInputList().clear(); } @Override @@ -63,6 +71,9 @@ protected Recipe findRecipe(long maxVoltage, IItemHandlerModifiable inputs, IMul /* Iterate over input items looking for more items to process until we * have touched every item, or are at maximum item capacity */ + boolean matchedRecipe = false; + boolean canFitOutputs = true; + for (int index = 0; index < inputs.getSlots() && currentItemsEngaged < MAX_PROCESSES; index++) { final ItemStack currentInputItem = inputs.getStackInSlot(index); @@ -77,6 +88,7 @@ protected Recipe findRecipe(long maxVoltage, IItemHandlerModifiable inputs, IMul MatchingMode.DEFAULT); CountableIngredient inputIngredient; if (matchingRecipe != null) { + matchedRecipe = true; if (matchingRecipe.getOutputs().isEmpty()) return doChancedOnlyRecipe(matchingRecipe, currentInputItem); inputIngredient = matchingRecipe.getInputs().get(0); @@ -103,7 +115,7 @@ protected Recipe findRecipe(long maxVoltage, IItemHandlerModifiable inputs, IMul computeOutputItemStacks(temp, matchingRecipe.getOutputs().get(0), recipeMultiplier); // Check to see if we have output space available for the recipe - boolean canFitOutputs = InventoryUtils.simulateItemStackMerge(temp, this.getOutputInventory()); + canFitOutputs = InventoryUtils.simulateItemStackMerge(temp, this.getOutputInventory()); if (!canFitOutputs) break; @@ -119,9 +131,10 @@ protected Recipe findRecipe(long maxVoltage, IItemHandlerModifiable inputs, IMul } } - // No recipe was found + this.invalidInputsForRecipes = !matchedRecipe; + this.isOutputsFull = !canFitOutputs; + if (recipeInputs.isEmpty()) { - forceRecipeRecheck = true; return null; } diff --git a/src/main/java/gregtech/api/capability/impl/SteamMultiblockRecipeLogic.java b/src/main/java/gregtech/api/capability/impl/SteamMultiblockRecipeLogic.java index b77f1a1e72f..fc77af94a8f 100644 --- a/src/main/java/gregtech/api/capability/impl/SteamMultiblockRecipeLogic.java +++ b/src/main/java/gregtech/api/capability/impl/SteamMultiblockRecipeLogic.java @@ -2,6 +2,7 @@ import gregtech.api.GTValues; import gregtech.api.capability.IMultipleTankHandler; +import gregtech.api.metatileentity.multiblock.RecipeMapSteamMultiblockController; import gregtech.api.recipes.Recipe; import gregtech.api.recipes.RecipeMap; import net.minecraft.block.Block; @@ -52,7 +53,7 @@ protected IItemHandlerModifiable getOutputInventory() { protected IMultipleTankHandler getSteamFluidTank() { RecipeMapSteamMultiblockController controller = (RecipeMapSteamMultiblockController) metaTileEntity; - return controller.steamFluidTank; + return controller.getSteamFluidTank(); } private void combineSteamTanks() { @@ -115,12 +116,6 @@ protected boolean setupAndConsumeRecipeInputs(Recipe recipe) { } else return false; } - // Do this to casually ignore fluids from steam multiblocks - @Override - protected boolean checkRecipeInputsDirty(IItemHandler inputs, IMultipleTankHandler fluidInputs) { - return super.checkRecipeInputsDirty(inputs, new FluidTankList(false)); - } - @Override protected void completeRecipe() { super.completeRecipe(); diff --git a/src/main/java/gregtech/api/gui/GuiTextures.java b/src/main/java/gregtech/api/gui/GuiTextures.java index 664bd29b4bc..0f54787ef42 100644 --- a/src/main/java/gregtech/api/gui/GuiTextures.java +++ b/src/main/java/gregtech/api/gui/GuiTextures.java @@ -1,6 +1,7 @@ package gregtech.api.gui; import gregtech.api.gui.resources.AdoptableTextureArea; +import gregtech.api.gui.resources.IGuiTexture; import gregtech.api.gui.resources.SizedTextureArea; import gregtech.api.gui.resources.TextureArea; @@ -146,12 +147,15 @@ public class GuiTextures { public static final TextureArea PROGRESS_BAR_CANNER = TextureArea.fullImage("textures/gui/progress_bar/progress_bar_canner.png"); public static final TextureArea PROGRESS_BAR_CIRCUIT = TextureArea.fullImage("textures/gui/progress_bar/progress_bar_circuit.png"); public static final TextureArea PROGRESS_BAR_CIRCUIT_ASSEMBLER = TextureArea.fullImage("textures/gui/progress_bar/progress_bar_circuit_assembler.png"); + public static final TextureArea PROGRESS_BAR_COKE_OVEN = TextureArea.fullImage("textures/gui/progress_bar/progress_bar_coke_oven.png"); public static final TextureArea PROGRESS_BAR_COMPRESS = TextureArea.fullImage("textures/gui/progress_bar/progress_bar_compress.png"); public static final TextureArea PROGRESS_BAR_CRACKING = TextureArea.fullImage("textures/gui/progress_bar/progress_bar_cracking.png"); public static final TextureArea PROGRESS_BAR_CRYSTALLIZATION = TextureArea.fullImage("textures/gui/progress_bar/progress_bar_crystallization.png"); + public static final TextureArea PROGRESS_BAR_DISTILLATION_TOWER = TextureArea.fullImage("textures/gui/progress_bar/progress_bar_distillation_tower.png"); public static final TextureArea PROGRESS_BAR_EXTRACT = TextureArea.fullImage("textures/gui/progress_bar/progress_bar_extract.png"); public static final TextureArea PROGRESS_BAR_EXTRUDER = TextureArea.fullImage("textures/gui/progress_bar/progress_bar_extruder.png"); public static final TextureArea PROGRESS_BAR_FUSION = TextureArea.fullImage("textures/gui/progress_bar/progress_bar_fusion.png"); + public static final TextureArea PROGRESS_BAR_GAS_COLLECTOR = TextureArea.fullImage("textures/gui/progress_bar/progress_bar_gas_collector.png"); public static final TextureArea PROGRESS_BAR_HAMMER = TextureArea.fullImage("textures/gui/progress_bar/progress_bar_hammer.png"); public static final TextureArea PROGRESS_BAR_HAMMER_BASE = TextureArea.fullImage("textures/gui/progress_bar/progress_bar_hammer_base.png"); public static final TextureArea PROGRESS_BAR_LATHE = TextureArea.fullImage("textures/gui/progress_bar/progress_bar_lathe.png"); @@ -173,4 +177,19 @@ public class GuiTextures { public static final TextureArea INFO_ICON = TextureArea.fullImage("textures/gui/widget/information.png"); public static final TextureArea MULTIBLOCK_CATEGORY = TextureArea.fullImage("textures/gui/icon/coke_oven.png"); + //Terminal + public static final TextureArea ICON_REMOVE = TextureArea.fullImage("textures/gui/terminal/icon/remove_hover.png"); + public static final TextureArea ICON_UP = TextureArea.fullImage("textures/gui/terminal/icon/up_hover.png"); + public static final TextureArea ICON_DOWN = TextureArea.fullImage("textures/gui/terminal/icon/down_hover.png"); + public static final TextureArea ICON_RIGHT = TextureArea.fullImage("textures/gui/terminal/icon/right_hover.png"); + public static final TextureArea ICON_LEFT = TextureArea.fullImage("textures/gui/terminal/icon/left_hover.png"); + public static final TextureArea ICON_ADD = TextureArea.fullImage("textures/gui/terminal/icon/add_hover.png"); + + public final static TextureArea ICON_NEW_PAGE = TextureArea.fullImage("textures/gui/terminal/icon/system/memory_card_hover.png"); + public final static TextureArea ICON_LOAD = TextureArea.fullImage("textures/gui/terminal/icon/folder_hover.png"); + public final static TextureArea ICON_SAVE = TextureArea.fullImage("textures/gui/terminal/icon/system/save_hover.png"); + public final static TextureArea ICON_LOCATION = TextureArea.fullImage("textures/gui/terminal/icon/guide_hover.png"); + public final static TextureArea ICON_VISIBLE = TextureArea.fullImage("textures/gui/terminal/icon/appearance_hover.png"); + public final static TextureArea ICON_CALCULATOR = TextureArea.fullImage("textures/gui/terminal/icon/other/calculator_hover.png"); + } diff --git a/src/main/java/gregtech/api/gui/ModularUI.java b/src/main/java/gregtech/api/gui/ModularUI.java index 6296f508292..588d28d0ad5 100644 --- a/src/main/java/gregtech/api/gui/ModularUI.java +++ b/src/main/java/gregtech/api/gui/ModularUI.java @@ -57,6 +57,7 @@ public List getFlatVisibleWidgetCollection() { List widgetList = new ArrayList<>(guiWidgets.size()); for (Widget widget : guiWidgets.values()) { + if (!widget.isVisible()) continue; widgetList.add(widget); if (widget instanceof AbstractWidgetGroup) diff --git a/src/main/java/gregtech/api/gui/Widget.java b/src/main/java/gregtech/api/gui/Widget.java index 0b4213fe7b9..efdc9688432 100644 --- a/src/main/java/gregtech/api/gui/Widget.java +++ b/src/main/java/gregtech/api/gui/Widget.java @@ -1,6 +1,7 @@ package gregtech.api.gui; import com.google.common.base.Preconditions; +import gregtech.api.gui.resources.RenderUtil; import gregtech.api.gui.widgets.WidgetUIAccess; import gregtech.api.util.Position; import gregtech.api.util.Size; @@ -8,14 +9,13 @@ import net.minecraft.client.audio.PositionedSoundRecord; import net.minecraft.client.gui.FontRenderer; import net.minecraft.client.gui.Gui; -import net.minecraft.client.renderer.GlStateManager; -import net.minecraft.client.renderer.OpenGlHelper; -import net.minecraft.client.renderer.RenderHelper; -import net.minecraft.client.renderer.RenderItem; +import net.minecraft.client.renderer.*; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.client.util.ITooltipFlag; import net.minecraft.init.SoundEvents; import net.minecraft.item.ItemStack; import net.minecraft.network.PacketBuffer; +import net.minecraft.util.math.Vec2f; import net.minecraft.util.text.TextFormatting; import net.minecraftforge.fml.client.config.GuiUtils; import net.minecraftforge.fml.common.FMLCommonHandler; @@ -25,10 +25,12 @@ import javax.annotation.Nullable; import java.awt.*; +import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.function.Consumer; import java.util.function.Supplier; +import org.lwjgl.opengl.GL11; /** * Widget is functional element of ModularUI @@ -37,13 +39,15 @@ */ public abstract class Widget { - protected ModularUI gui; - protected ISizeProvider sizes; - protected WidgetUIAccess uiAccess; - private Position parentPosition = Position.ORIGIN; - private Position selfPosition; - private Position position; - private Size size; + protected transient ModularUI gui; + protected transient ISizeProvider sizes; + protected transient WidgetUIAccess uiAccess; + private transient Position parentPosition = Position.ORIGIN; + private transient Position selfPosition; + private transient Position position; + private transient Size size; + private transient boolean isVisible; + private transient boolean isActive; public Widget(Position selfPosition, Size size) { Preconditions.checkNotNull(selfPosition, "selfPosition"); @@ -51,6 +55,12 @@ public Widget(Position selfPosition, Size size) { this.selfPosition = selfPosition; this.size = size; this.position = this.parentPosition.add(selfPosition); + this.isVisible = true; + this.isActive = true; + } + + public Widget(int x, int y, int width, int height) { + this(new Position(x, y), new Size(width, height)); } public void setGui(ModularUI gui) { @@ -71,13 +81,23 @@ public void setParentPosition(Position parentPosition) { recomputePosition(); } - protected void setSelfPosition(Position selfPosition) { + public void setSelfPosition(Position selfPosition) { Preconditions.checkNotNull(selfPosition, "selfPosition"); this.selfPosition = selfPosition; recomputePosition(); } - protected void setSize(Size size) { + public Position addSelfPosition(int addX, int addY) { + this.selfPosition = new Position(selfPosition.x + addX, selfPosition.y + addY); + recomputePosition(); + return this.selfPosition; + } + + public Position getSelfPosition() { + return selfPosition; + } + + public void setSize(Size size) { Preconditions.checkNotNull(size, "size"); this.size = size; onSizeUpdate(); @@ -91,20 +111,33 @@ public final Size getSize() { return size; } + public boolean isVisible() { + return isVisible; + } + + public void setVisible(boolean visible) { + isVisible = visible; + } + + public boolean isActive() { + return isActive; + } + + public void setActive(boolean active) { + isActive = active; + } + public Rectangle toRectangleBox() { Position pos = getPosition(); Size size = getSize(); return new Rectangle(pos.x, pos.y, size.width, size.height); } - private void recomputePosition() { + protected void recomputePosition() { this.position = this.parentPosition.add(selfPosition); onPositionUpdate(); } - public void applyScissor(final int parentX, final int parentY, final int parentWidth, final int parentHeight) { - } - protected void onPositionUpdate() { } @@ -112,7 +145,7 @@ protected void onSizeUpdate() { } public boolean isMouseOverElement(int mouseX, int mouseY, boolean correctPositionOnMouseWheelMoveEvent) { - mouseX = correctPositionOnMouseWheelMoveEvent ? mouseX + getPosition().x : mouseX; + mouseX = correctPositionOnMouseWheelMoveEvent ? mouseX + this.gui.getGuiLeft(): mouseX; return isMouseOverElement(mouseX, mouseY); } @@ -152,12 +185,21 @@ public void drawInForeground(int mouseX, int mouseY) { } /** - * Called each draw tick to draw this widget in GUI + * Called each draw tick to draw this widget in GUI (@Deprecated) */ + @Deprecated @SideOnly(Side.CLIENT) public void drawInBackground(int mouseX, int mouseY, IRenderContext context) { } + /** + * Called each draw tick to draw this widget in GUI + */ + @SideOnly(Side.CLIENT) + public void drawInBackground(int mouseX, int mouseY, float partialTicks, IRenderContext context) { + drawInBackground(mouseX, mouseY, context); + } + /** * Called when mouse wheel is moved in GUI * For some -redacted- reason mouseX position is relative against GUI not game window as in other mouse events @@ -219,19 +261,27 @@ public List getNativeWidgets() { /** * Writes data to be sent to client's {@link #readUpdateInfo} */ - protected final void writeUpdateInfo(int id, Consumer packetBufferWriter) { + protected void writeUpdateInfo(int id, Consumer packetBufferWriter) { if (uiAccess != null && gui != null) { uiAccess.writeUpdateInfo(this, id, packetBufferWriter); } } @SideOnly(Side.CLIENT) - protected final void writeClientAction(int id, Consumer packetBufferWriter) { + protected void writeClientAction(int id, Consumer packetBufferWriter) { if (uiAccess != null) { uiAccess.writeClientAction(this, id, packetBufferWriter); } } + @SideOnly(Side.CLIENT) + protected void drawBorder(int x, int y, int width, int height, int stroke, int stroke_width) { + drawGradientRect(x - stroke_width, y - stroke_width, width + 2 * stroke_width, stroke_width, stroke, stroke); + drawGradientRect(x - stroke_width, y + height, width + 2 * stroke_width, stroke_width, stroke, stroke); + drawGradientRect(x - stroke_width, y - stroke_width, stroke_width, height + 2 * stroke_width, stroke, stroke); + drawGradientRect(x + width, y - stroke_width, stroke_width, height + 2 * stroke_width, stroke, stroke); + } + @SideOnly(Side.CLIENT) protected void drawHoveringText(ItemStack itemStack, List tooltip, int maxTextWidth, int mouseX, int mouseY) { Minecraft mc = Minecraft.getMinecraft(); @@ -314,8 +364,179 @@ protected static void drawSolidRect(int x, int y, int width, int height, int col @SideOnly(Side.CLIENT) protected static void drawGradientRect(int x, int y, int width, int height, int startColor, int endColor) { - GuiUtils.drawGradientRect(0, x, y, x + width, y + height, startColor, endColor); + drawGradientRect(x, y, width, height, startColor, endColor, false); + } + + @SideOnly(Side.CLIENT) + public static void drawGradientRect(float x, float y, float width, float height, int startColor, int endColor, boolean horizontal) { + float startAlpha = (float) (startColor >> 24 & 255) / 255.0F; + float startRed = (float) (startColor >> 16 & 255) / 255.0F; + float startGreen = (float) (startColor >> 8 & 255) / 255.0F; + float startBlue = (float) (startColor & 255) / 255.0F; + float endAlpha = (float) (endColor >> 24 & 255) / 255.0F; + float endRed = (float) (endColor >> 16 & 255) / 255.0F; + float endGreen = (float) (endColor >> 8 & 255) / 255.0F; + float endBlue = (float) (endColor & 255) / 255.0F; + GlStateManager.disableTexture2D(); GlStateManager.enableBlend(); + GlStateManager.disableAlpha(); + GlStateManager.tryBlendFuncSeparate(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ZERO); + GlStateManager.shadeModel(GL11.GL_SMOOTH); + Tessellator tessellator = Tessellator.getInstance(); + BufferBuilder buffer = tessellator.getBuffer(); + buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR); + if (horizontal) { + buffer.pos(x + width, y, 0).color(endRed, endGreen, endBlue, endAlpha).endVertex(); + buffer.pos(x, y, 0).color(startRed, startGreen, startBlue, startAlpha).endVertex(); + buffer.pos(x, y + height, 0).color(startRed, startGreen, startBlue, startAlpha).endVertex(); + buffer.pos(x + width, y + height, 0).color(endRed, endGreen, endBlue, endAlpha).endVertex(); + tessellator.draw(); + } else { + buffer.pos(x + width, y, 0).color(startRed, startGreen, startBlue, startAlpha).endVertex(); + buffer.pos(x, y, 0).color(startRed, startGreen, startBlue, startAlpha).endVertex(); + buffer.pos(x, y + height, 0).color(endRed, endGreen, endBlue, endAlpha).endVertex(); + buffer.pos(x + width, y + height, 0).color(endRed, endGreen, endBlue, endAlpha).endVertex(); + tessellator.draw(); + } + GlStateManager.shadeModel(GL11.GL_FLAT); + GlStateManager.enableAlpha(); + GlStateManager.enableTexture2D(); + } + + @SideOnly(Side.CLIENT) + public static void setColor(int color) { // ARGB + GlStateManager.color((color >> 16 & 255) / 255.0F, + (color >> 8 & 255) / 255.0F, + (color & 255) / 255.0F, + (color >> 24 & 255) / 255.0F); + } + + @SideOnly(Side.CLIENT) + public static void drawCircle(float x, float y, float r, int color, int segments) { + if (color == 0) return; + Tessellator tessellator = Tessellator.getInstance(); + BufferBuilder bufferbuilder = tessellator.getBuffer(); + GlStateManager.enableBlend(); + GlStateManager.disableTexture2D(); + GlStateManager.tryBlendFuncSeparate(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ZERO); + setColor(color); + bufferbuilder.begin(GL11.GL_POLYGON, DefaultVertexFormats.POSITION); + for (int i = 0; i < segments; i++) { + bufferbuilder.pos(x + r * Math.cos(-2 * Math.PI * i / segments), y + r * Math.sin(-2 * Math.PI * i / segments), 0.0D).endVertex(); + } + tessellator.draw(); + GlStateManager.enableTexture2D(); + GlStateManager.color(1,1,1,1); + } + + @SideOnly(Side.CLIENT) + public static void drawSector(float x, float y, float r, int color, int segments, int from, int to) { + if (from > to || from < 0 || color == 0) return; + if(to > segments) to = segments; + Tessellator tessellator = Tessellator.getInstance(); + BufferBuilder bufferbuilder = tessellator.getBuffer(); + GlStateManager.enableBlend(); + GlStateManager.disableTexture2D(); + GlStateManager.tryBlendFuncSeparate(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ZERO); + setColor(color); + bufferbuilder.begin(GL11.GL_TRIANGLES, DefaultVertexFormats.POSITION); + for (int i = from; i < to; i++) { + bufferbuilder.pos(x + r * Math.cos(-2 * Math.PI * i / segments), y + r * Math.sin(-2 * Math.PI * i / segments), 0.0D).endVertex(); + bufferbuilder.pos(x + r * Math.cos(-2 * Math.PI * (i + 1) / segments), y + r * Math.sin(-2 * Math.PI * (i + 1) / segments), 0.0D).endVertex(); + bufferbuilder.pos(x, y, 0.0D).endVertex(); + } + tessellator.draw(); + GlStateManager.enableTexture2D(); + GlStateManager.color(1,1,1,1); + } + + public static void drawTorus(float x, float y, float outer, float inner, int color, int segments, int from, int to) { + Tessellator tessellator = Tessellator.getInstance(); + BufferBuilder bufferbuilder = tessellator.getBuffer(); + GlStateManager.enableBlend(); + GlStateManager.disableTexture2D(); + GlStateManager.tryBlendFuncSeparate(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ZERO); + setColor(color); + bufferbuilder.begin(GL11.GL_QUAD_STRIP, DefaultVertexFormats.POSITION); + for (int i = from; i <= to; i++) { + float angle = ( i / (float)segments ) * 3.14159f * 2.0f; + bufferbuilder.pos( x + inner * Math.cos(-angle), y + inner * Math.sin(-angle), 0).endVertex(); + bufferbuilder.pos( x + outer * Math.cos(-angle), y + outer * Math.sin(-angle), 0).endVertex(); + } + tessellator.draw(); + GlStateManager.enableTexture2D(); + GlStateManager.color(1,1,1,1); + } + + @SideOnly(Side.CLIENT) + public static void drawLines(List points, int startColor, int endColor, float width) { + Tessellator tessellator = Tessellator.getInstance(); + BufferBuilder bufferbuilder = tessellator.getBuffer(); + GlStateManager.enableBlend(); + GlStateManager.disableTexture2D(); + GlStateManager.tryBlendFuncSeparate(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ZERO); + GlStateManager.glLineWidth(width); + if (startColor == endColor) { + setColor(startColor); + bufferbuilder.begin(GL11.GL_LINE_STRIP, DefaultVertexFormats.POSITION); + for (Vec2f point : points) { + bufferbuilder.pos(point.x, point.y, 0).endVertex(); + } + } else { + float startAlpha = (float) (startColor >> 24 & 255) / 255.0F; + float startRed = (float) (startColor >> 16 & 255) / 255.0F; + float startGreen = (float) (startColor >> 8 & 255) / 255.0F; + float startBlue = (float) (startColor & 255) / 255.0F; + float endAlpha = (float) (endColor >> 24 & 255) / 255.0F; + float endRed = (float) (endColor >> 16 & 255) / 255.0F; + float endGreen = (float) (endColor >> 8 & 255) / 255.0F; + float endBlue = (float) (endColor & 255) / 255.0F; + bufferbuilder.begin(GL11.GL_LINE_STRIP, DefaultVertexFormats.POSITION_COLOR); + int size = points.size(); + + for (int i = 0; i < size; i++) { + float p = i * 1.0f / size; + bufferbuilder.pos(points.get(i).x, points.get(i).y, 0) + .color(startRed + (endRed - startRed) * p, + startGreen + (endGreen - startGreen) * p, + startBlue + (endBlue - startBlue) * p, + startAlpha + (endAlpha - startAlpha) * p) + .endVertex(); + } + } + tessellator.draw(); + GlStateManager.enableTexture2D(); + GlStateManager.color(1, 1, 1, 1); + } + + @SideOnly(Side.CLIENT) + public static List genBezierPoints(Vec2f from, Vec2f to, boolean horizontal, float u) { + Vec2f c1; + Vec2f c2; + if (horizontal) { + c1 = new Vec2f((from.x + to.x) / 2, from.y); + c2 = new Vec2f((from.x + to.x) / 2, to.y); + } else { + c1 = new Vec2f(from.x, (from.y + to.y) / 2); + c2 = new Vec2f(to.x, (from.y + to.y) / 2); + } + Vec2f[] controlPoint = new Vec2f[]{from,c1,c2,to}; + int n = controlPoint.length - 1; + int i, r; + List bezierPoints = new ArrayList<>(); + for (u = 0; u <= 1; u += 0.01) { + Vec2f[] p = new Vec2f[n + 1]; + for (i = 0; i <= n; i++) { + p[i] = new Vec2f(controlPoint[i].x, controlPoint[i].y); + } + for (r = 1; r <= n; r++) { + for (i = 0; i <= n - r; i++) { + p[i] = new Vec2f((1 - u) * p[i].x + u * p[i + 1].x, (1 - u) * p[i].y + u * p[i + 1].y); + } + } + bezierPoints.add(p[0]); + } + return bezierPoints; } @SideOnly(Side.CLIENT) @@ -333,6 +554,10 @@ protected boolean isCtrlDown() { return Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) || Keyboard.isKeyDown(Keyboard.KEY_RCONTROL); } + protected boolean isRemote() { + return gui.holder.isRemote(); + } + protected static boolean isClientSide() { return FMLCommonHandler.instance().getSide().isClient(); } @@ -341,24 +566,35 @@ public static final class ClickData { public final int button; public final boolean isShiftClick; public final boolean isCtrlClick; + public final boolean isClient; public ClickData(int button, boolean isShiftClick, boolean isCtrlClick) { this.button = button; this.isShiftClick = isShiftClick; this.isCtrlClick = isCtrlClick; + this.isClient = false; + } + + public ClickData(int button, boolean isShiftClick, boolean isCtrlClick, boolean isClient) { + this.button = button; + this.isShiftClick = isShiftClick; + this.isCtrlClick = isCtrlClick; + this.isClient = isClient; } public void writeToBuf(PacketBuffer buf) { buf.writeVarInt(button); buf.writeBoolean(isShiftClick); buf.writeBoolean(isCtrlClick); + buf.writeBoolean(isClient); } public static ClickData readFromBuf(PacketBuffer buf) { int button = buf.readVarInt(); boolean shiftClick = buf.readBoolean(); boolean ctrlClick = buf.readBoolean(); - return new ClickData(button, shiftClick, ctrlClick); + boolean isClient = buf.readBoolean(); + return new ClickData(button, shiftClick, ctrlClick, isClient); } } diff --git a/src/main/java/gregtech/api/gui/impl/ModularUIGui.java b/src/main/java/gregtech/api/gui/impl/ModularUIGui.java index bc6c3508969..ed3f213925b 100644 --- a/src/main/java/gregtech/api/gui/impl/ModularUIGui.java +++ b/src/main/java/gregtech/api/gui/impl/ModularUIGui.java @@ -1,11 +1,10 @@ package gregtech.api.gui.impl; import gregtech.api.gui.IRenderContext; -import gregtech.api.gui.IScissored; import gregtech.api.gui.ModularUI; import gregtech.api.gui.Widget; +import gregtech.api.gui.widgets.SlotWidget; import gregtech.api.net.PacketUIWidgetUpdate; -import gregtech.api.util.RenderUtil; import gregtech.common.ConfigHolder; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.inventory.GuiContainer; @@ -21,7 +20,6 @@ import org.lwjgl.input.Keyboard; import org.lwjgl.input.Mouse; -import java.awt.*; import java.io.IOException; public class ModularUIGui extends GuiContainer implements IRenderContext { @@ -94,23 +92,14 @@ public void drawScreen(int mouseX, int mouseY, float partialTicks) { for (int i = 0; i < this.inventorySlots.inventorySlots.size(); ++i) { Slot slot = this.inventorySlots.inventorySlots.get(i); - Rectangle scissor = null; - if (slot instanceof IScissored) { - scissor = ((IScissored) slot).getScissor(); - if (scissor != null) { - RenderUtil.pushScissorFrame(scissor.x, scissor.y, scissor.width, scissor.height); + if (slot instanceof SlotWidget.ISlotWidget) { + if (((SlotWidget.ISlotWidget) slot).isHover()) { + setHoveredSlot(slot); } - } - if (slot.isEnabled()) { - this.drawSlotContents(slot); - } - if (isPointInRegion(slot.xPos, slot.yPos, 16, 16, mouseX, mouseY) && slot.isEnabled()) { + } else if (isPointInRegion(slot.xPos, slot.yPos, 16, 16, mouseX, mouseY) && slot.isEnabled()) { renderSlotOverlay(slot); setHoveredSlot(slot); } - if (scissor != null) { - RenderUtil.popScissorFrame(); - } } RenderHelper.disableStandardItemLighting(); @@ -140,6 +129,7 @@ public void setHoveredSlot(Slot hoveredSlot) { this.hoveredSlot = hoveredSlot; } + @Deprecated public void drawSlotContents(Slot slot) { GlStateManager.enableDepth(); RenderHelper.enableGUIStandardItemLighting(); @@ -151,6 +141,7 @@ public void drawSlotContents(Slot slot) { GlStateManager.disableLighting(); } + @Deprecated public void renderSlotOverlay(Slot slot) { GlStateManager.disableDepth(); int slotX = slot.xPos; @@ -199,6 +190,7 @@ private void renderReturningItemStack() { @Override protected void drawGuiContainerForegroundLayer(int mouseX, int mouseY) { modularUI.guiWidgets.values().forEach(widget -> { + if (!widget.isVisible()) return; GlStateManager.pushMatrix(); GlStateManager.color(1.0f, 1.0f, 1.0f); widget.drawInForeground(mouseX, mouseY); @@ -214,9 +206,10 @@ protected void drawGuiContainerBackgroundLayer(float partialTicks, int mouseX, i GlStateManager.popMatrix(); modularUI.backgroundPath.draw(guiLeft, guiTop, xSize, ySize); modularUI.guiWidgets.values().forEach(widget -> { + if (!widget.isVisible()) return; GlStateManager.pushMatrix(); GlStateManager.enableBlend(); - widget.drawInBackground(mouseX, mouseY, this); + widget.drawInBackground(mouseX, mouseY, partialTicks,this); GlStateManager.color(rColorForOverlay, gColorForOverlay, bColorForOverlay, 1.0F); GlStateManager.popMatrix(); }); @@ -234,41 +227,56 @@ public void handleMouseInput() throws IOException { } protected void mouseWheelMove(int mouseX, int mouseY, int wheelDelta) { - //noinspection ResultOfMethodCallIgnored - modularUI.guiWidgets.values().stream().anyMatch(widget -> widget.mouseWheelMove(mouseX, mouseY, wheelDelta)); + for (int i = modularUI.guiWidgets.size() - 1; i >= 0; i--) { + Widget widget = modularUI.guiWidgets.get(i); + if(widget.isVisible() && widget.isActive() && widget.mouseWheelMove(mouseX, mouseY, wheelDelta)) { + return; + } + } } @Override protected void mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException { - boolean result = modularUI.guiWidgets.values().stream().anyMatch(widget -> widget.mouseClicked(mouseX, mouseY, mouseButton)); - if (!result) { - super.mouseClicked(mouseX, mouseY, mouseButton); + for (int i = modularUI.guiWidgets.size() - 1; i >= 0; i--) { + Widget widget = modularUI.guiWidgets.get(i); + if(widget.isVisible() && widget.isActive() && widget.mouseClicked(mouseX, mouseY, mouseButton)) { + return; + } } + super.mouseClicked(mouseX, mouseY, mouseButton); } @Override protected void mouseClickMove(int mouseX, int mouseY, int clickedMouseButton, long timeSinceLastClick) { - boolean result = modularUI.guiWidgets.values().stream().anyMatch(widget -> - widget.mouseDragged(mouseX, mouseY, clickedMouseButton, timeSinceLastClick)); - if (!result) { - super.mouseClickMove(mouseX, mouseY, clickedMouseButton, timeSinceLastClick); + for (int i = modularUI.guiWidgets.size() - 1; i >= 0; i--) { + Widget widget = modularUI.guiWidgets.get(i); + if(widget.isVisible() && widget.isActive() && widget.mouseDragged(mouseX, mouseY, clickedMouseButton, timeSinceLastClick)) { + return; + } } + super.mouseClickMove(mouseX, mouseY, clickedMouseButton, timeSinceLastClick); } @Override protected void mouseReleased(int mouseX, int mouseY, int state) { - boolean result = modularUI.guiWidgets.values().stream().anyMatch(widget -> widget.mouseReleased(mouseX, mouseY, state)); - if (!result) { - super.mouseReleased(mouseX, mouseY, state); + for (int i = modularUI.guiWidgets.size() - 1; i >= 0; i--) { + Widget widget = modularUI.guiWidgets.get(i); + if(widget.isVisible() && widget.isActive() && widget.mouseReleased(mouseX, mouseY, state)) { + return; + } } + super.mouseReleased(mouseX, mouseY, state); } @Override protected void keyTyped(char typedChar, int keyCode) throws IOException { - boolean result = modularUI.guiWidgets.values().stream().anyMatch(widget -> widget.keyTyped(typedChar, keyCode)); - if (!result) { - super.keyTyped(typedChar, keyCode); + for (int i = modularUI.guiWidgets.size() - 1; i >= 0; i--) { + Widget widget = modularUI.guiWidgets.get(i); + if(widget.isVisible() && widget.isActive() && widget.keyTyped(typedChar, keyCode)) { + return; + } } + super.keyTyped(typedChar, keyCode); } } diff --git a/src/main/java/gregtech/api/gui/impl/ModularUIGuiHandler.java b/src/main/java/gregtech/api/gui/impl/ModularUIGuiHandler.java index b2de47b31dd..14890e9a66c 100644 --- a/src/main/java/gregtech/api/gui/impl/ModularUIGuiHandler.java +++ b/src/main/java/gregtech/api/gui/impl/ModularUIGuiHandler.java @@ -6,13 +6,11 @@ import gregtech.api.gui.ingredient.IRecipeTransferHandlerWidget; import mezz.jei.api.gui.IAdvancedGuiHandler; import mezz.jei.api.gui.IGhostIngredientHandler; -import mezz.jei.api.gui.IGuiIngredient; import mezz.jei.api.gui.IRecipeLayout; import mezz.jei.api.recipe.transfer.IRecipeTransferError; import mezz.jei.api.recipe.transfer.IRecipeTransferHandler; import mezz.jei.api.recipe.transfer.IRecipeTransferHandlerHelper; import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.item.ItemStack; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -51,9 +49,7 @@ public IRecipeTransferError transferRecipe(ModularUIContainer container, @Nonnul if (!transferHandler.isPresent()) { return transferHelper.createInternalError(); } - Map> group = new HashMap<>(recipeLayout.getItemStacks().getGuiIngredients()); - group.values().removeIf(it -> it.getAllIngredients().isEmpty()); - String errorTooltip = transferHandler.get().transferRecipe(container, group, player, maxTransfer, doTransfer); + String errorTooltip = transferHandler.get().transferRecipe(container, recipeLayout, player, maxTransfer, doTransfer); if (errorTooltip == null) { return null; } diff --git a/src/main/java/gregtech/api/gui/ingredient/IRecipeTransferHandlerWidget.java b/src/main/java/gregtech/api/gui/ingredient/IRecipeTransferHandlerWidget.java index ed2907ef0e0..20f451a8ac2 100644 --- a/src/main/java/gregtech/api/gui/ingredient/IRecipeTransferHandlerWidget.java +++ b/src/main/java/gregtech/api/gui/ingredient/IRecipeTransferHandlerWidget.java @@ -2,6 +2,7 @@ import gregtech.api.gui.impl.ModularUIContainer; import mezz.jei.api.gui.IGuiIngredient; +import mezz.jei.api.gui.IRecipeLayout; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; @@ -9,5 +10,5 @@ public interface IRecipeTransferHandlerWidget { - String transferRecipe(ModularUIContainer container, Map> ingredients, EntityPlayer player, boolean maxTransfer, boolean doTransfer); + String transferRecipe(ModularUIContainer container, IRecipeLayout recipeLayout, EntityPlayer player, boolean maxTransfer, boolean doTransfer); } diff --git a/src/main/java/gregtech/api/gui/resources/ColorRectTexture.java b/src/main/java/gregtech/api/gui/resources/ColorRectTexture.java new file mode 100644 index 00000000000..0a1edaca220 --- /dev/null +++ b/src/main/java/gregtech/api/gui/resources/ColorRectTexture.java @@ -0,0 +1,63 @@ +package gregtech.api.gui.resources; + +import net.minecraft.client.renderer.BufferBuilder; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; + +import java.awt.*; + +public class ColorRectTexture implements IGuiTexture{ + public int color; + + public ColorRectTexture(int color) { + this.color = color; + } + + public ColorRectTexture(Color color) { + this.color = color.getRGB(); + } + + public void setColor(int color) { + this.color = color; + } + + public int getColor() { + return color; + } + + @Override + public void draw(double x, double y, int width, int height) { + double j; + double right = x + width; + double bottom = y + height; + if (x < right) { + j = x; + x = right; + right = j; + } + + if (y < bottom) { + j = y; + y = bottom; + bottom = j; + } + float f3 = (float)(color >> 24 & 255) / 255.0F; + float f = (float)(color >> 16 & 255) / 255.0F; + float f1 = (float)(color >> 8 & 255) / 255.0F; + float f2 = (float)(color & 255) / 255.0F; + Tessellator tessellator = Tessellator.getInstance(); + BufferBuilder bufferbuilder = tessellator.getBuffer(); + GlStateManager.enableBlend(); + GlStateManager.disableTexture2D(); + GlStateManager.tryBlendFuncSeparate(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ZERO); + GlStateManager.color(f, f1, f2, f3); + bufferbuilder.begin(7, DefaultVertexFormats.POSITION); + bufferbuilder.pos(x, bottom, 0.0D).endVertex(); + bufferbuilder.pos(right, bottom, 0.0D).endVertex(); + bufferbuilder.pos(right, y, 0.0D).endVertex(); + bufferbuilder.pos(x, y, 0.0D).endVertex(); + tessellator.draw(); + GlStateManager.enableTexture2D(); + } +} diff --git a/src/main/java/gregtech/api/gui/resources/FileTexture.java b/src/main/java/gregtech/api/gui/resources/FileTexture.java new file mode 100644 index 00000000000..94cac96e4f2 --- /dev/null +++ b/src/main/java/gregtech/api/gui/resources/FileTexture.java @@ -0,0 +1,107 @@ +package gregtech.api.gui.resources; + +import gregtech.api.gui.Widget; +import gregtech.api.gui.resources.picturetexture.AnimatedPictureTexture; +import gregtech.api.gui.resources.picturetexture.OrdinaryTexture; +import gregtech.api.gui.resources.picturetexture.PictureTexture; +import gregtech.api.gui.resources.utils.GifDecoder; +import gregtech.api.gui.resources.utils.ImageUtils; +import gregtech.api.gui.resources.utils.ProcessedImageData; +import net.minecraft.client.Minecraft; +import net.minecraft.client.resources.I18n; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; +import org.apache.commons.compress.utils.IOUtils; + +import javax.imageio.ImageIO; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; + +public class FileTexture implements IGuiTexture{ + public final File file; + @SideOnly(Side.CLIENT) + private PictureTexture texture; + @SideOnly(Side.CLIENT) + private ProcessedImageData imageData; + private Thread downloadThread; + private boolean failed; + + public FileTexture(File file) { + this.file = file; + } + + @SideOnly(Side.CLIENT) + public void loadFile(){ + if (imageData != null) { + if (imageData.isAnimated()) { + texture = new AnimatedPictureTexture(imageData); + texture.tick(); + } else { + texture = new OrdinaryTexture(imageData); + } + imageData = null; + downloadThread = null; + } else if (downloadThread == null) { + downloadThread = new Thread(() -> { + FileInputStream inputStream = null; + try { + inputStream = new FileInputStream(file); + String type = ImageUtils.readType(inputStream); + if (type.equalsIgnoreCase("gif")) { + GifDecoder gif = new GifDecoder(); + inputStream.close(); + inputStream = new FileInputStream(file); + int status = gif.read(inputStream); + if (status == GifDecoder.STATUS_OK) { + imageData = new ProcessedImageData(gif); + } else { + failed = true; + } + } else { + inputStream.close(); + inputStream = new FileInputStream(file); + BufferedImage image = ImageIO.read(inputStream); + if (image != null) { + imageData = new ProcessedImageData(image); + } else { + failed = true; + } + } + } catch (IOException e) { + failed = true; + texture = null; + } finally { + IOUtils.closeQuietly(inputStream); + } + }); + downloadThread.start(); + } + } + + @SideOnly(Side.CLIENT) + @Override + public void updateTick() { + if(this.texture != null) { + texture.tick(); // gif\video update + } + } + + @Override + public void draw(double x, double y, int width, int height) { + if (texture != null && texture.hasTexture()) { + texture.render((float)x, (float)y, width, height, 0, 1, 1, false, false); + } else { + if (failed || file == null) { + Minecraft.getMinecraft().fontRenderer.drawString(I18n.format("texture.url_texture.fail"), (int)x + 2, (int)(y + height / 2.0 - 4), 0xffff0000); + } else { + this.loadFile(); + int s = (int) Math.floorMod(System.currentTimeMillis() / 200, 24); + Widget.drawSector((float)(x + width / 2.0), (float)(y + height / 2.0), (float)(Math.min(width, height) / 4.0), + 0xFF94E2C1, 24, s, s + 5); + } + } + } + +} diff --git a/src/main/java/gregtech/api/gui/resources/IGuiTexture.java b/src/main/java/gregtech/api/gui/resources/IGuiTexture.java new file mode 100644 index 00000000000..ee40a3b2004 --- /dev/null +++ b/src/main/java/gregtech/api/gui/resources/IGuiTexture.java @@ -0,0 +1,6 @@ +package gregtech.api.gui.resources; + +public interface IGuiTexture { + void draw(double x, double y, int width, int height); + default void updateTick() { } +} diff --git a/src/main/java/gregtech/api/gui/resources/ItemStackTexture.java b/src/main/java/gregtech/api/gui/resources/ItemStackTexture.java new file mode 100644 index 00000000000..429676a3b1d --- /dev/null +++ b/src/main/java/gregtech/api/gui/resources/ItemStackTexture.java @@ -0,0 +1,48 @@ +package gregtech.api.gui.resources; + +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.item.Item; +import net.minecraft.item.ItemStack; + +public class ItemStackTexture implements IGuiTexture{ + private final ItemStack[] itemStack; + private int index = 0; + private int ticks = 0; + + public ItemStackTexture(ItemStack stack, ItemStack... itemStack) { + this.itemStack = new ItemStack[itemStack.length + 1]; + this.itemStack[0] = stack; + System.arraycopy(itemStack, 0, this.itemStack, 1, itemStack.length); + } + + public ItemStackTexture(Item item, Item... items) { + this.itemStack = new ItemStack[items.length + 1]; + this.itemStack[0] = new ItemStack(item); + for(int i = 0; i < items.length; i++) { + itemStack[i+1] = new ItemStack(items[i]); + } + } + + @Override + public void updateTick() { + if(itemStack.length > 1 && ++ticks % 20 == 0) + if(++index == itemStack.length) + index = 0; + } + + @Override + public void draw(double x, double y, int width, int height) { + RenderHelper.enableGUIStandardItemLighting(); + GlStateManager.pushMatrix(); + GlStateManager.scale(width / 16f, height / 16f, 0.0001); + GlStateManager.translate(x * 16 / width, y * 16 / height, 0); + RenderItem itemRender = Minecraft.getMinecraft().getRenderItem(); + itemRender.renderItemAndEffectIntoGUI(itemStack[index], 0, 0); + GlStateManager.enableAlpha(); + GlStateManager.popMatrix(); + RenderHelper.disableStandardItemLighting(); + } +} diff --git a/src/main/java/gregtech/api/gui/resources/ModifyGuiTexture.java b/src/main/java/gregtech/api/gui/resources/ModifyGuiTexture.java new file mode 100644 index 00000000000..6df10d314f0 --- /dev/null +++ b/src/main/java/gregtech/api/gui/resources/ModifyGuiTexture.java @@ -0,0 +1,102 @@ +package gregtech.api.gui.resources; + +import com.google.gson.JsonObject; +import net.minecraft.util.ResourceLocation; + +import java.io.File; +import java.util.Arrays; +import java.util.List; + +public class ModifyGuiTexture implements IGuiTexture{ + public static List TYPES = Arrays.asList("resource", "url", "text", "color", "file"); + private IGuiTexture texture; + + public ModifyGuiTexture(IGuiTexture texture) { + this.texture = texture; + if (texture == null) { + this.texture = new TextTexture("texture.modify_gui_texture.missing"); + } + } + + public IGuiTexture getTexture() { + return texture; + } + + public void setTexture(IGuiTexture texture) { + if (texture != null) { + this.texture = texture; + } + } + + public String getTypeName() { + if (texture instanceof TextureArea) { + return "resource"; + } else if (texture instanceof URLTexture) { + return "url"; + } else if (texture instanceof TextTexture) { + return "text"; + } else if (texture instanceof ColorRectTexture) { + return "color"; + } else if (texture instanceof FileTexture) { + return "file"; + } else { + return null; + } + } + + @Override + public void draw(double x, double y, int width, int height) { + texture.draw(x, y, width, height); + } + + @Override + public void updateTick() { + texture.updateTick(); + } + + public JsonObject saveConfig() { + JsonObject config = new JsonObject(); + if (texture instanceof TextureArea) { + config.addProperty("type", "resource"); + config.addProperty("resource", ((TextureArea) texture).imageLocation.toString()); + } else if (texture instanceof URLTexture) { + config.addProperty("type", "url"); + config.addProperty("url", ((URLTexture) texture).url); + } else if (texture instanceof TextTexture) { + config.addProperty("type", "text"); + config.addProperty("text", ((TextTexture) texture).text); + config.addProperty("color", ((TextTexture) texture).color); + } else if (texture instanceof ColorRectTexture) { + config.addProperty("type", "color"); + config.addProperty("color", ((ColorRectTexture) texture).color); + } else if (texture instanceof FileTexture) { + config.addProperty("type", "file"); + if (((FileTexture) texture).file != null) { + config.addProperty("file", ((FileTexture) texture).file.getPath()); + } else { + config.addProperty("file", (String)null); + } + } else { + return null; + } + return config; + } + + public void loadConfig(JsonObject config) { + try { + switch (config.get("type").getAsString()) { + case "resource": + setTexture(new TextureArea(new ResourceLocation(config.get("resource").getAsString()), 0.0, 0.0, 1.0, 1.0)); + case "url": + setTexture(new URLTexture(config.get("url").getAsString())); + case "text": + setTexture(new TextTexture(config.get("text").getAsString(), config.get("color").getAsInt())); + case "color": + setTexture(new ColorRectTexture(config.get("color").getAsInt())); + case "file": + setTexture(new FileTexture(new File(config.get("file").getAsString()))); + } + } catch (Exception ignored) { + } + } +} diff --git a/src/main/java/gregtech/api/gui/resources/RenderUtil.java b/src/main/java/gregtech/api/gui/resources/RenderUtil.java index ebc04858cd4..63960272bdc 100644 --- a/src/main/java/gregtech/api/gui/resources/RenderUtil.java +++ b/src/main/java/gregtech/api/gui/resources/RenderUtil.java @@ -3,16 +3,21 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.RenderItem; import net.minecraft.client.renderer.Tessellator; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.renderer.texture.TextureMap; import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.item.ItemStack; import net.minecraft.util.ResourceLocation; import net.minecraftforge.fluids.Fluid; import net.minecraftforge.fluids.FluidRegistry; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; +import net.minecraft.client.renderer.GlStateManager.DestFactor; +import net.minecraft.client.renderer.GlStateManager.SourceFactor; +import org.lwjgl.opengl.GL11; @SideOnly(Side.CLIENT) public class RenderUtil { @@ -102,6 +107,4 @@ private static void drawFluidTexture(double xCoord, double yCoord, TextureAtlasS buffer.pos(xCoord, yCoord + maskTop, zLevel).tex(uMin, vMin).endVertex(); tessellator.draw(); } - - } diff --git a/src/main/java/gregtech/api/gui/resources/TextTexture.java b/src/main/java/gregtech/api/gui/resources/TextTexture.java new file mode 100644 index 00000000000..1a7c18fc7f2 --- /dev/null +++ b/src/main/java/gregtech/api/gui/resources/TextTexture.java @@ -0,0 +1,29 @@ +package gregtech.api.gui.resources; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.resources.I18n; +import net.minecraftforge.fml.common.FMLCommonHandler; + +public class TextTexture implements IGuiTexture{ + public final String text; + public final int color; + + public TextTexture(String text) { + this.text = text; + this.color = 0xff000000; + } + + public TextTexture(String text, int color) { + this.text = text; + this.color = color; + } + + + @Override + public void draw(double x, double y, int width, int height) { + FontRenderer fontRenderer = Minecraft.getMinecraft().fontRenderer; + String resultText = I18n.format(text); + fontRenderer.drawString(resultText, (float) (x + (width - fontRenderer.getStringWidth(resultText)) / 2), (float) (y + (height - fontRenderer.FONT_HEIGHT) / 2 + 2), color, false); + } +} diff --git a/src/main/java/gregtech/api/gui/resources/TextureArea.java b/src/main/java/gregtech/api/gui/resources/TextureArea.java index 4edfd4991b9..0fc6278276e 100644 --- a/src/main/java/gregtech/api/gui/resources/TextureArea.java +++ b/src/main/java/gregtech/api/gui/resources/TextureArea.java @@ -4,6 +4,7 @@ import codechicken.lib.vec.Transformation; import codechicken.lib.vec.Translation; import codechicken.lib.vec.Vector3; +import com.google.gson.JsonObject; import gregtech.api.GTValues; import gregtech.api.util.Position; import gregtech.api.util.PositionedRect; @@ -22,7 +23,7 @@ * This representation doesn't take image size in account, so all image variables are * 0.0 - 1.0 bounds */ -public class TextureArea { +public class TextureArea implements IGuiTexture { public final ResourceLocation imageLocation; diff --git a/src/main/java/gregtech/api/gui/resources/URLTexture.java b/src/main/java/gregtech/api/gui/resources/URLTexture.java new file mode 100644 index 00000000000..4bac1590806 --- /dev/null +++ b/src/main/java/gregtech/api/gui/resources/URLTexture.java @@ -0,0 +1,79 @@ +package gregtech.api.gui.resources; + +import gregtech.api.gui.Widget; +import gregtech.api.gui.resources.picturetexture.PictureTexture; +import gregtech.api.gui.resources.utils.DownloadThread; +import net.minecraft.client.Minecraft; +import net.minecraft.client.resources.I18n; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +public class URLTexture implements IGuiTexture{ + public final String url; + @SideOnly(Side.CLIENT) + private DownloadThread downloader; + @SideOnly(Side.CLIENT) + private PictureTexture texture; + @SideOnly(Side.CLIENT) + private boolean failed; + @SideOnly(Side.CLIENT) + private String error; + + + public URLTexture(String url) { + this.url = url; + } + + @SideOnly(Side.CLIENT) + @Override + public void updateTick() { + if(this.texture != null) { + texture.tick(); // gif\video update + } + } + + @Override + public void draw(double x, double y, int width, int height) { + if (texture != null && texture.hasTexture()) { + texture.render((float)x, (float)y, width, height, 0, 1, 1, false, false); + } else { + if (failed || url == null || this.url.equals("")) { + Minecraft.getMinecraft().fontRenderer.drawString(I18n.format("texture.url_texture.fail"), (int)x + 2, (int)(y + height / 2.0 - 4), 0xffff0000); + } else { + this.loadTexture(); + int s = (int) Math.floorMod(System.currentTimeMillis() / 200, 24); + Widget.drawSector((float)(x + width / 2.0), (float)(y + height / 2.0), (float)(Math.min(width, height) / 4.0), + 0xFF94E2C1, 24, s, s + 5); + } + } + } + + @SideOnly(Side.CLIENT) + public void loadTexture() { + if (texture == null && !failed) { + if (downloader == null && DownloadThread.activeDownloads < DownloadThread.MAXIMUM_ACTIVE_DOWNLOADS) { + PictureTexture loadedTexture = DownloadThread.loadedImages.get(url); + if (loadedTexture == null) { + synchronized (DownloadThread.LOCK) { + if (!DownloadThread.loadingImages.contains(url)) { + downloader = new DownloadThread(url); + return; + } + } + } else { + texture = loadedTexture; + } + } + if (downloader != null && downloader.hasFinished()) { + if (downloader.hasFailed()) { + failed = true; + error = downloader.getError(); + DownloadThread.LOGGER.error("Could not load image of " + url + " : " + error); + } else { + texture = DownloadThread.loadImage(downloader); + } + downloader = null; + } + } + } +} diff --git a/src/main/java/gregtech/api/gui/resources/picturetexture/AnimatedPictureTexture.java b/src/main/java/gregtech/api/gui/resources/picturetexture/AnimatedPictureTexture.java new file mode 100644 index 00000000000..a8b4526edef --- /dev/null +++ b/src/main/java/gregtech/api/gui/resources/picturetexture/AnimatedPictureTexture.java @@ -0,0 +1,66 @@ +package gregtech.api.gui.resources.picturetexture; + + +import gregtech.api.gui.resources.utils.ProcessedImageData; +import net.minecraft.client.renderer.GlStateManager; + +import java.util.Arrays; + +public class AnimatedPictureTexture extends PictureTexture { + private final int[] textureIDs; + private final long[] delay; + private final long duration; + + private int completedFrames; + private ProcessedImageData imageData; + + public AnimatedPictureTexture(ProcessedImageData image) { + super(image.getWidth(), image.getHeight()); + imageData = image; + textureIDs = new int[image.getFrameCount()]; + delay = image.getDelay(); + duration = image.getDuration(); + Arrays.fill(textureIDs, -1); + } + + @Override + public void tick() { + if (imageData != null) { + long startTime = System.currentTimeMillis(); + int index = 0; + while (completedFrames < textureIDs.length && index < textureIDs.length && System.currentTimeMillis() - startTime < 10) { + while (textureIDs[index] != -1 && index < textureIDs.length - 1) + index++; + if (textureIDs[index] == -1) + textureIDs[index] = uploadFrame(index); + } + } + } + + @Override + public int getTextureID() { + long time = duration > 0 ? System.currentTimeMillis() % duration : 0; + int index = 0; + for (int i = 0; i < delay.length; i++) { + if (delay[i] >= time) { + index = i; + break; + } + } + return textureIDs[index]; + } + + private int uploadFrame(int index) { + int id = imageData.uploadFrame(index); + textureIDs[index] = id; + if (++completedFrames >= imageData.getFrameCount()) { + imageData = null; + } + return id; + } + + @Override + public void release() { + for (int textureID : textureIDs) GlStateManager.deleteTexture(textureID); + } +} diff --git a/src/main/java/gregtech/api/gui/resources/picturetexture/OrdinaryTexture.java b/src/main/java/gregtech/api/gui/resources/picturetexture/OrdinaryTexture.java new file mode 100644 index 00000000000..31d2e2a3983 --- /dev/null +++ b/src/main/java/gregtech/api/gui/resources/picturetexture/OrdinaryTexture.java @@ -0,0 +1,23 @@ +package gregtech.api.gui.resources.picturetexture; + +import gregtech.api.gui.resources.utils.ProcessedImageData; + +public class OrdinaryTexture extends PictureTexture { + + private final int textureID; + + public OrdinaryTexture(ProcessedImageData image) { + super(image.getWidth(), image.getHeight()); + textureID = image.uploadFrame(0); + } + + @Override + public void tick() { + } + + @Override + public int getTextureID() { + return textureID; + } +} + diff --git a/src/main/java/gregtech/api/gui/resources/picturetexture/PictureTexture.java b/src/main/java/gregtech/api/gui/resources/picturetexture/PictureTexture.java new file mode 100644 index 00000000000..8d614fbecac --- /dev/null +++ b/src/main/java/gregtech/api/gui/resources/picturetexture/PictureTexture.java @@ -0,0 +1,65 @@ +package gregtech.api.gui.resources.picturetexture; + +import gregtech.api.gui.resources.IGuiTexture; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.OpenGlHelper; +import org.lwjgl.opengl.GL11; + +public abstract class PictureTexture implements IGuiTexture { + public int width; + public int height; + + public PictureTexture(int width, int height) { + this.width = width; + this.height = height; + + } + + public void beforeRender() { + + } + + @Override + public void draw(double x, double y, int width, int height) { + render((float)x, (float)y, 1, 1, 0, width, height, false, false); + } + + public void render(float x, float y, float width, float height, float rotation, float scaleX, float scaleY, boolean flippedX, boolean flippedY) { + this.beforeRender(); + GlStateManager.color(1,1,1,1); + GlStateManager.enableBlend(); + OpenGlHelper.glBlendFunc(770, 771, 1, 0); + GlStateManager.bindTexture(this.getTextureID()); + GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_NEAREST); + GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST); + GlStateManager.pushMatrix(); + GL11.glRotated(rotation, 0, 0, 1); + GlStateManager.enableRescaleNormal(); + GL11.glScaled(scaleX, scaleY, 1); + GL11.glBegin(GL11.GL_POLYGON); + GL11.glTexCoord3f(flippedY ? 1 : 0, flippedX ? 1 : 0, 0); + GL11.glVertex3f(x, y, 0.01f); + GL11.glTexCoord3f(flippedY ? 1 : 0, flippedX ? 0 : 1, 0); + GL11.glVertex3f(x, y + height, 0.01f); + GL11.glTexCoord3f(flippedY ? 0 : 1, flippedX ? 0 : 1, 0); + GL11.glVertex3f(x + width, y + height, 0.01f); + GL11.glTexCoord3f(flippedY ? 0 : 1, flippedX ? 1 : 0, 0); + GL11.glVertex3f(x + width, y, 0.01f); + GL11.glEnd(); + GlStateManager.popMatrix(); + GlStateManager.disableRescaleNormal(); + GlStateManager.disableBlend(); + } + + public abstract void tick(); + + public abstract int getTextureID(); + + public boolean hasTexture() { + return getTextureID() != -1; + } + + public void release() { + GlStateManager.deleteTexture(getTextureID()); + } +} diff --git a/src/main/java/gregtech/api/gui/resources/picturetexture/VideoTexture.java b/src/main/java/gregtech/api/gui/resources/picturetexture/VideoTexture.java new file mode 100644 index 00000000000..70f1dc7aebf --- /dev/null +++ b/src/main/java/gregtech/api/gui/resources/picturetexture/VideoTexture.java @@ -0,0 +1,19 @@ +package gregtech.api.gui.resources.picturetexture; + +public class VideoTexture extends PictureTexture { + //TODO implementations of it in the future + + public VideoTexture(String url) { + super(100, 100); + } + + @Override + public void tick() { + + } + + @Override + public int getTextureID() { + return 0; + } +} diff --git a/src/main/java/gregtech/api/gui/resources/utils/DownloadThread.java b/src/main/java/gregtech/api/gui/resources/utils/DownloadThread.java new file mode 100644 index 00000000000..e2fdb63be5f --- /dev/null +++ b/src/main/java/gregtech/api/gui/resources/utils/DownloadThread.java @@ -0,0 +1,225 @@ +package gregtech.api.gui.resources.utils; + +import gregtech.GregTechMod; +import gregtech.api.gui.resources.picturetexture.AnimatedPictureTexture; +import gregtech.api.gui.resources.picturetexture.OrdinaryTexture; +import gregtech.api.gui.resources.picturetexture.PictureTexture; +import gregtech.api.gui.resources.picturetexture.VideoTexture; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; +import org.apache.commons.compress.utils.IOUtils; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import javax.imageio.ImageIO; +import javax.imageio.ImageReadParam; +import javax.imageio.ImageReader; +import javax.imageio.stream.ImageInputStream; +import java.awt.image.BufferedImage; +import java.io.*; +import java.net.HttpURLConnection; +import java.net.URL; +import java.net.URLConnection; +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.*; + +@SideOnly(Side.CLIENT) +public class DownloadThread extends Thread { + public static final Logger LOGGER = LogManager.getLogger(GregTechMod.class); + + public static final TextureCache TEXTURE_CACHE = new TextureCache(); + public static final DateFormat FORMAT = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z"); + public static final Object LOCK = new Object(); + public static final int MAXIMUM_ACTIVE_DOWNLOADS = 5; + + public static int activeDownloads = 0; + + public static HashMap loadedImages = new HashMap<>(); + public static Set loadingImages = new HashSet<>(); + + private final String url; + + private ProcessedImageData processedImage; + private String error; + private boolean complete; + private boolean isVideo; + + public DownloadThread(String url) { + this.url = url; + synchronized (DownloadThread.LOCK) { + DownloadThread.loadingImages.add(url); + DownloadThread.activeDownloads++; + } + setName("OPF Download \"" + url + "\""); + setDaemon(true); + start(); + } + + public boolean hasFinished() { + return complete; + } + + public boolean hasFailed() { + return hasFinished() && error != null; + } + + public boolean isVideo() { + return isVideo; + } + + public String getError() { + return error; + } + + @Override + public void run() { + Exception exception = null; + try { + byte[] data = load(url); + String type = ImageUtils.readType(data); + ByteArrayInputStream in = null; + try { + in = new ByteArrayInputStream(data); + if (type.equalsIgnoreCase("gif")) { + GifDecoder gif = new GifDecoder(); + int status = gif.read(in); + if (status == GifDecoder.STATUS_OK) { + processedImage = new ProcessedImageData(gif); + } else { + LOGGER.error("Failed to read gif: {}", status); + } + } else { + try { + BufferedImage image = ImageIO.read(in); + if (image != null) { + processedImage = new ProcessedImageData(image); + } + } catch (IOException e1) { + exception = e1; + LOGGER.error("Failed to parse BufferedImage from stream", e1); + } + } + } finally { + IOUtils.closeQuietly(in); + } + } catch (FoundVideoException e) { + isVideo = true; + } catch (Exception e) { + exception = e; + LOGGER.error("An exception occurred while loading OPFrame image", e); + } + if (!isVideo && processedImage == null) { + if (exception == null) + error = "download.exception.gif"; + else if (exception.getMessage() == null) + error = "download.exception.invalid"; + else if (exception.getMessage().startsWith("Server returned HTTP response code: 403")) + error = "download.exception.forbidden"; + else if (exception.getMessage().startsWith("Server returned HTTP response code: 404")) + error = "download.exception.notfound"; + else + error = "download.exception.invalid"; + TEXTURE_CACHE.deleteEntry(url); + } + complete = true; + + synchronized (DownloadThread.LOCK) { + DownloadThread.loadingImages.remove(url); + DownloadThread.activeDownloads--; + } + } + + public static byte[] load(String url) throws IOException, FoundVideoException { + TextureCache.CacheEntry entry = TEXTURE_CACHE.getEntry(url); + long requestTime = System.currentTimeMillis(); + URLConnection connection = new URL(url).openConnection(); + connection.addRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:25.0) Gecko/20100101 Firefox/25.0"); + int responseCode = -1; + if (connection instanceof HttpURLConnection) { + HttpURLConnection httpConnection = (HttpURLConnection) connection; + if (entry != null) { + if (entry.getEtag() != null) { + httpConnection.setRequestProperty("If-None-Match", entry.getEtag()); + } else if (entry.getTime() != -1) { + httpConnection.setRequestProperty("If-Modified-Since", FORMAT.format(new Date(entry.getTime()))); + } + } + responseCode = httpConnection.getResponseCode(); + } + InputStream in = null; + try { + in = connection.getInputStream(); + if (!connection.getContentType().startsWith("image")) + throw new FoundVideoException(); + String etag = connection.getHeaderField("ETag"); + long lastModifiedTimestamp; + long expireTimestamp = -1; + String maxAge = connection.getHeaderField("max-age"); + if (maxAge != null && !maxAge.isEmpty()) { + try { + expireTimestamp = requestTime + Long.parseLong(maxAge) * 1000; + } catch (NumberFormatException ignored) {} + } + String expires = connection.getHeaderField("Expires"); + if (expires != null && !expires.isEmpty()) { + try { + expireTimestamp = FORMAT.parse(expires).getTime(); + } catch (ParseException ignored) {} + } + String lastModified = connection.getHeaderField("Last-Modified"); + if (lastModified != null && !lastModified.isEmpty()) { + try { + lastModifiedTimestamp = FORMAT.parse(lastModified).getTime(); + } catch (ParseException e) { + lastModifiedTimestamp = requestTime; + } + } else { + lastModifiedTimestamp = requestTime; + } + if (entry != null) { + if (etag != null && !etag.isEmpty()) { + entry.setEtag(etag); + } + entry.setTime(lastModifiedTimestamp); + if (responseCode == HttpURLConnection.HTTP_NOT_MODIFIED) { + File file = entry.getFile(); + if (file.exists()) { + try (FileInputStream fileStream = new FileInputStream(file)) { + return IOUtils.toByteArray(fileStream); + } + + } + } + } + byte[] data = IOUtils.toByteArray(in); + TEXTURE_CACHE.save(url, etag, lastModifiedTimestamp, expireTimestamp, data); + return data; + } finally { + IOUtils.closeQuietly(in); + } + } + + public static PictureTexture loadImage(DownloadThread thread) { + PictureTexture texture = null; + + if (!thread.hasFailed()) { + if (thread.isVideo()) + texture = new VideoTexture(thread.url); + else if (thread.processedImage.isAnimated()) + texture = new AnimatedPictureTexture(thread.processedImage); + else + texture = new OrdinaryTexture(thread.processedImage); + } + if (texture != null) + synchronized (LOCK) { + loadedImages.put(thread.url, texture); + } + return texture; + } + + public static class FoundVideoException extends Exception { + + } +} diff --git a/src/main/java/gregtech/api/gui/resources/utils/GifDecoder.java b/src/main/java/gregtech/api/gui/resources/utils/GifDecoder.java new file mode 100644 index 00000000000..69a25f3e217 --- /dev/null +++ b/src/main/java/gregtech/api/gui/resources/utils/GifDecoder.java @@ -0,0 +1,721 @@ +package gregtech.api.gui.resources.utils; + +import java.awt.*; +import java.awt.image.BufferedImage; +import java.awt.image.DataBufferInt; +import java.io.BufferedInputStream; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.util.ArrayList; + +/** Class GifDecoder - Decodes a GIF file into one or more frames. + * + * Example: + * + *

+ * {
+ *     @code
+ *     GifDecoder d = new GifDecoder();
+ *     d.read("sample.gif");
+ *     int n = d.getFrameCount();
+ *     for (int i = 0; i < n; i++) {
+ *         BufferedImage frame = d.getFrame(i); // frame i
+ *         int t = d.getDelay(i); // display duration of frame in milliseconds
+ *         // do something with frame
+ *     }
+ * }
+ * 
+ * + * No copyright asserted on the source code of this class. May be used for + * any purpose, however, refer to the Unisys LZW patent for any additional + * restrictions. Please forward any corrections to questions at fmsware.com. + * + * @author Kevin Weiner, FM Software; LZW decoder adapted from John Cristy's ImageMagick. + * @version 1.03 November 2003 */ + +public class GifDecoder { + + /** File read status: No errors. */ + public static final int STATUS_OK = 0; + + /** File read status: Error decoding file (may be partially decoded) */ + public static final int STATUS_FORMAT_ERROR = 1; + + /** File read status: Unable to open source. */ + public static final int STATUS_OPEN_ERROR = 2; + + protected BufferedInputStream in; + protected int status; + + protected int width; // full image width + protected int height; // full image height + protected boolean gctFlag; // global color table used + protected int gctSize; // size of global color table + protected int loopCount = 1; // iterations; 0 = repeat forever + + protected int[] gct; // global color table + protected int[] lct; // local color table + protected int[] act; // active color table + + protected int bgIndex; // background color index + protected int bgColor; // background color + protected int lastBgColor; // previous bg color + protected int pixelAspect; // pixel aspect ratio + + protected boolean lctFlag; // local color table flag + protected boolean interlace; // interlace flag + protected int lctSize; // local color table size + + protected int ix, iy, iw, ih; // current image rectangle + protected Rectangle lastRect; // last image rect + protected BufferedImage image; // current frame + protected BufferedImage lastImage; // previous frame + + protected byte[] block = new byte[256]; // current data block + protected int blockSize = 0; // block size + + // last graphic control extension info + protected int dispose = 0; + // 0=no action; 1=leave in place; 2=restore to bg; 3=restore to prev + protected int lastDispose = 0; + protected boolean transparency = false; // use transparent color + protected int delay = 0; // delay in milliseconds + protected int transIndex; // transparent color index + + protected static final int MaxStackSize = 4096; + // max decoder pixel stack size + + // LZW decoder working arrays + protected short[] prefix; + protected byte[] suffix; + protected byte[] pixelStack; + protected byte[] pixels; + + protected ArrayList frames; // frames read from current file + protected int frameCount; + + static class GifFrame { + public GifFrame(BufferedImage im, int del) { + image = im; + delay = del; + } + + public BufferedImage image; + public int delay; + } + + /** Gets display duration for specified frame. + * + * @param n + * int index of frame + * @return delay in milliseconds */ + public int getDelay(int n) { + // + delay = -1; + if ((n >= 0) && (n < frameCount)) { + delay = ((GifFrame) frames.get(n)).delay; + } + return delay; + } + + /** Gets the number of frames read from file. + * + * @return frame count */ + public int getFrameCount() { + return frameCount; + } + + /** Gets the first (or only) image read. + * + * @return BufferedImage containing first frame, or null if none. */ + public BufferedImage getImage() { + return getFrame(0); + } + + /** Gets the "Netscape" iteration count, if any. + * A count of 0 means repeat indefinitiely. + * + * @return iteration count if one was specified, else 1. */ + public int getLoopCount() { + return loopCount; + } + + /** Creates new frame image from current data (and previous + * frames as specified by their disposition codes). */ + protected void setPixels() { + // expose destination image's pixels as int array + int[] dest = ((DataBufferInt) image.getRaster().getDataBuffer()).getData(); + + // fill in starting image contents based on last image's dispose code + if (lastDispose > 0) { + if (lastDispose == 3) { + // use image before last + int n = frameCount - 2; + if (n > 0) { + lastImage = getFrame(n - 1); + } else { + lastImage = null; + } + } + + if (lastImage != null) { + int[] prev = ((DataBufferInt) lastImage.getRaster().getDataBuffer()).getData(); + System.arraycopy(prev, 0, dest, 0, width * height); + // copy pixels + + if (lastDispose == 2) { + // fill last image rect area with background color + Graphics2D g = image.createGraphics(); + Color c = null; + if (transparency) { + c = new Color(0, 0, 0, 0); // assume background is transparent + } else { + c = new Color(lastBgColor); // use given background color + } + g.setColor(c); + g.setComposite(AlphaComposite.Src); // replace area + g.fill(lastRect); + g.dispose(); + } + } + } + + // copy each source line to the appropriate place in the destination + int pass = 1; + int inc = 8; + int iline = 0; + for (int i = 0; i < ih; i++) { + int line = i; + if (interlace) { + if (iline >= ih) { + pass++; + switch (pass) { + case 2: + iline = 4; + break; + case 3: + iline = 2; + inc = 4; + break; + case 4: + iline = 1; + inc = 2; + } + } + line = iline; + iline += inc; + } + line += iy; + if (line < height) { + int k = line * width; + int dx = k + ix; // start of line in dest + int dlim = dx + iw; // end of dest line + if ((k + width) < dlim) { + dlim = k + width; // past dest edge + } + int sx = i * iw; // start of line in source + while (dx < dlim) { + // map color and insert in destination + int index = (pixels[sx++]) & 0xff; + int c = act[index]; + if (c != 0) { + dest[dx] = c; + } + dx++; + } + } + } + } + + /** Gets the image contents of frame n. + * + * @return BufferedImage representation of frame, or null if n is invalid. */ + public BufferedImage getFrame(int n) { + BufferedImage im = null; + if ((n >= 0) && (n < frameCount)) { + im = ((GifFrame) frames.get(n)).image; + } + return im; + } + + /** Gets image size. + * + * @return GIF image dimensions */ + public Dimension getFrameSize() { + return new Dimension(width, height); + } + + /** Reads GIF image from stream + * + * @param is + * BufferedInputStream containing GIF file. + * @return read status code (0 = no errors) */ + public int read(BufferedInputStream is) { + init(); + if (is != null) { + in = is; + readHeader(); + if (!err()) { + readContents(); + if (frameCount < 0) { + status = STATUS_FORMAT_ERROR; + } + } + } else { + status = STATUS_OPEN_ERROR; + } + try { + is.close(); + } catch (IOException e) { + } + return status; + } + + /** Reads GIF image from stream + * + * @param is + * InputStream containing GIF file. + * @return read status code (0 = no errors) */ + public int read(InputStream is) { + init(); + if (is != null) { + if (!(is instanceof BufferedInputStream)) + is = new BufferedInputStream(is); + in = (BufferedInputStream) is; + readHeader(); + if (!err()) { + readContents(); + if (frameCount < 0) { + status = STATUS_FORMAT_ERROR; + } + } + } else { + status = STATUS_OPEN_ERROR; + } + try { + is.close(); + } catch (IOException e) { + } + return status; + } + + /** Reads GIF file from specified file/URL source + * (URL assumed if name contains ":/" or "file:") + * + * @param name + * String containing source + * @return read status code (0 = no errors) */ + public int read(String name) { + status = STATUS_OK; + try { + name = name.trim().toLowerCase(); + if ((name.indexOf("file:") >= 0) || (name.indexOf(":/") > 0)) { + URL url = new URL(name); + in = new BufferedInputStream(url.openStream()); + } else { + in = new BufferedInputStream(new FileInputStream(name)); + } + status = read(in); + } catch (IOException e) { + status = STATUS_OPEN_ERROR; + } + + return status; + } + + /** Decodes LZW image data into pixel array. + * Adapted from John Cristy's ImageMagick. */ + protected void decodeImageData() { + int NullCode = -1; + int npix = iw * ih; + int available, clear, code_mask, code_size, end_of_information, in_code, old_code, bits, code, count, i, datum, + data_size, first, top, bi, pi; + + if ((pixels == null) || (pixels.length < npix)) { + pixels = new byte[npix]; // allocate new pixel array + } + if (prefix == null) + prefix = new short[MaxStackSize]; + if (suffix == null) + suffix = new byte[MaxStackSize]; + if (pixelStack == null) + pixelStack = new byte[MaxStackSize + 1]; + + // Initialize GIF data stream decoder. + + data_size = read(); + clear = 1 << data_size; + end_of_information = clear + 1; + available = clear + 2; + old_code = NullCode; + code_size = data_size + 1; + code_mask = (1 << code_size) - 1; + for (code = 0; code < clear; code++) { + prefix[code] = 0; + suffix[code] = (byte) code; + } + + // Decode GIF pixel stream. + + datum = bits = count = first = top = pi = bi = 0; + + for (i = 0; i < npix;) { + if (top == 0) { + if (bits < code_size) { + // Load bytes until there are enough bits for a code. + if (count == 0) { + // Read a new data block. + count = readBlock(); + if (count <= 0) + break; + bi = 0; + } + datum += ((block[bi]) & 0xff) << bits; + bits += 8; + bi++; + count--; + continue; + } + + // Get the next code. + + code = datum & code_mask; + datum >>= code_size; + bits -= code_size; + + // Interpret the code + + if ((code > available) || (code == end_of_information)) + break; + if (code == clear) { + // Reset decoder. + code_size = data_size + 1; + code_mask = (1 << code_size) - 1; + available = clear + 2; + old_code = NullCode; + continue; + } + if (old_code == NullCode) { + pixelStack[top++] = suffix[code]; + old_code = code; + first = code; + continue; + } + in_code = code; + if (code == available) { + pixelStack[top++] = (byte) first; + code = old_code; + } + while (code > clear) { + pixelStack[top++] = suffix[code]; + code = prefix[code]; + } + first = (suffix[code]) & 0xff; + + // Add a new string to the string table, + + if (available >= MaxStackSize) { + pixelStack[top++] = (byte) first; + continue; + } + pixelStack[top++] = (byte) first; + prefix[available] = (short) old_code; + suffix[available] = (byte) first; + available++; + if (((available & code_mask) == 0) && (available < MaxStackSize)) { + code_size++; + code_mask += available; + } + old_code = in_code; + } + + // Pop a pixel off the pixel stack. + + top--; + pixels[pi++] = pixelStack[top]; + i++; + } + + for (i = pi; i < npix; i++) { + pixels[i] = 0; // clear missing pixels + } + + } + + /** Returns true if an error was encountered during reading/decoding */ + protected boolean err() { + return status != STATUS_OK; + } + + /** Initializes or re-initializes reader */ + protected void init() { + status = STATUS_OK; + frameCount = 0; + frames = new ArrayList(); + gct = null; + lct = null; + } + + /** Reads a single byte from the input stream. */ + protected int read() { + int curByte = 0; + try { + curByte = in.read(); + } catch (IOException e) { + status = STATUS_FORMAT_ERROR; + } + return curByte; + } + + /** Reads next variable length block from input. + * + * @return number of bytes stored in "buffer" */ + protected int readBlock() { + blockSize = read(); + int n = 0; + if (blockSize > 0) { + try { + int count = 0; + while (n < blockSize) { + count = in.read(block, n, blockSize - n); + if (count == -1) + break; + n += count; + } + } catch (IOException e) { + } + + if (n < blockSize) { + status = STATUS_FORMAT_ERROR; + } + } + return n; + } + + /** Reads color table as 256 RGB integer values + * + * @param ncolors + * int number of colors to read + * @return int array containing 256 colors (packed ARGB with full alpha) */ + protected int[] readColorTable(int ncolors) { + int nbytes = 3 * ncolors; + int[] tab = null; + byte[] c = new byte[nbytes]; + int n = 0; + try { + n = in.read(c); + } catch (IOException e) { + } + if (n < nbytes) { + status = STATUS_FORMAT_ERROR; + } else { + tab = new int[256]; // max size to avoid bounds checks + int i = 0; + int j = 0; + while (i < ncolors) { + int r = (c[j++]) & 0xff; + int g = (c[j++]) & 0xff; + int b = (c[j++]) & 0xff; + tab[i++] = 0xff000000 | (r << 16) | (g << 8) | b; + } + } + return tab; + } + + /** Main file parser. Reads GIF content blocks. */ + protected void readContents() { + // read GIF file content blocks + boolean done = false; + while (!(done || err())) { + int code = read(); + switch (code) { + + case 0x2C: // image separator + readImage(); + break; + + case 0x21: // extension + code = read(); + switch (code) { + case 0xf9: // graphics control extension + readGraphicControlExt(); + break; + + case 0xff: // application extension + readBlock(); + String app = ""; + for (int i = 0; i < 11; i++) { + app += (char) block[i]; + } + if (app.equals("NETSCAPE2.0")) { + readNetscapeExt(); + } else + skip(); // don't care + break; + + default: // uninteresting extension + skip(); + } + break; + + case 0x3b: // terminator + done = true; + break; + + case 0x00: // bad byte, but keep going and see what happens + break; + + default: + status = STATUS_FORMAT_ERROR; + } + } + } + + /** Reads Graphics Control Extension values */ + protected void readGraphicControlExt() { + read(); // block size + int packed = read(); // packed fields + dispose = (packed & 0x1c) >> 2; // disposal method + if (dispose == 0) { + dispose = 1; // elect to keep old image if discretionary + } + transparency = (packed & 1) != 0; + delay = readShort() * 10; // delay in milliseconds + transIndex = read(); // transparent color index + read(); // block terminator + } + + /** Reads GIF file header information. */ + protected void readHeader() { + String id = ""; + for (int i = 0; i < 6; i++) { + id += (char) read(); + } + if (!id.startsWith("GIF")) { + status = STATUS_FORMAT_ERROR; + return; + } + + readLSD(); + if (gctFlag && !err()) { + gct = readColorTable(gctSize); + bgColor = gct[bgIndex]; + } + } + + /** Reads next frame image */ + protected void readImage() { + ix = readShort(); // (sub)image position & size + iy = readShort(); + iw = readShort(); + ih = readShort(); + + int packed = read(); + lctFlag = (packed & 0x80) != 0; // 1 - local color table flag + interlace = (packed & 0x40) != 0; // 2 - interlace flag + // 3 - sort flag + // 4-5 - reserved + lctSize = 2 << (packed & 7); // 6-8 - local color table size + + if (lctFlag) { + lct = readColorTable(lctSize); // read table + act = lct; // make local table active + } else { + act = gct; // make global table active + if (bgIndex == transIndex) + bgColor = 0; + } + int save = 0; + if (transparency) { + save = act[transIndex]; + act[transIndex] = 0; // set transparent color if specified + } + + if (act == null) { + status = STATUS_FORMAT_ERROR; // no color table defined + } + + if (err()) + return; + + decodeImageData(); // decode pixel data + skip(); + + if (err()) + return; + + frameCount++; + + // create new image to receive frame data + image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB_PRE); + + setPixels(); // transfer pixel data to image + + frames.add(new GifFrame(image, delay)); // add image to frame list + + if (transparency) { + act[transIndex] = save; + } + resetFrame(); + + } + + /** Reads Logical Screen Descriptor */ + protected void readLSD() { + + // logical screen size + width = readShort(); + height = readShort(); + + // packed fields + int packed = read(); + gctFlag = (packed & 0x80) != 0; // 1 : global color table flag + // 2-4 : color resolution + // 5 : gct sort flag + gctSize = 2 << (packed & 7); // 6-8 : gct size + + bgIndex = read(); // background color index + pixelAspect = read(); // pixel aspect ratio + } + + /** Reads Netscape extenstion to obtain iteration count */ + protected void readNetscapeExt() { + do { + readBlock(); + if (block[0] == 1) { + // loop count sub-block + int b1 = (block[1]) & 0xff; + int b2 = (block[2]) & 0xff; + loopCount = (b2 << 8) | b1; + } + } while ((blockSize > 0) && !err()); + } + + /** Reads next 16-bit value, LSB first */ + protected int readShort() { + // read 16-bit value, LSB first + return read() | (read() << 8); + } + + /** Resets frame state for reading next image. */ + protected void resetFrame() { + lastDispose = dispose; + lastRect = new Rectangle(ix, iy, iw, ih); + lastImage = image; + lastBgColor = bgColor; + int dispose = 0; + boolean transparency = false; + int delay = 0; + lct = null; + } + + /** Skips variable length blocks up to and including + * next zero length block. */ + protected void skip() { + do { + readBlock(); + } while ((blockSize > 0) && !err()); + } +} diff --git a/src/main/java/gregtech/api/gui/resources/utils/ImageUtils.java b/src/main/java/gregtech/api/gui/resources/utils/ImageUtils.java new file mode 100644 index 00000000000..af980ff8eaf --- /dev/null +++ b/src/main/java/gregtech/api/gui/resources/utils/ImageUtils.java @@ -0,0 +1,57 @@ +package gregtech.api.gui.resources.utils; + +import gregtech.GregTechMod; +import org.apache.commons.compress.utils.IOUtils; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import javax.imageio.ImageIO; +import javax.imageio.ImageReadParam; +import javax.imageio.ImageReader; +import javax.imageio.stream.ImageInputStream; +import java.io.ByteArrayInputStream; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.Iterator; + +public class ImageUtils { + public static final Logger LOGGER = LogManager.getLogger(GregTechMod.class); + + public static String readType(byte[] input) throws IOException { + InputStream in = null; + try { + in = new ByteArrayInputStream(input); + return readType(in); + } finally { + IOUtils.closeQuietly(in); + } + } + + public static String readType(InputStream input) throws IOException { + ImageInputStream stream = ImageIO.createImageInputStream(input); + Iterator iter = ImageIO.getImageReaders(stream); + if (!iter.hasNext()) { + return ""; + } + ImageReader reader = iter.next(); + + if (reader.getFormatName().equalsIgnoreCase("gif")) + return "gif"; + + ImageReadParam param = reader.getDefaultReadParam(); + reader.setInput(stream, true, true); + try { + reader.read(0, param); + } catch (IOException e) { + LOGGER.error("Failed to parse input format", e); + } finally { + reader.dispose(); + IOUtils.closeQuietly(stream); + } + if (!(input instanceof FileInputStream)) { + input.reset(); + } + return reader.getFormatName(); + } +} diff --git a/src/main/java/gregtech/api/gui/resources/utils/ProcessedImageData.java b/src/main/java/gregtech/api/gui/resources/utils/ProcessedImageData.java new file mode 100644 index 00000000000..81a354d91a2 --- /dev/null +++ b/src/main/java/gregtech/api/gui/resources/utils/ProcessedImageData.java @@ -0,0 +1,137 @@ +package gregtech.api.gui.resources.utils; + +import org.lwjgl.BufferUtils; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL12; + +import java.awt.*; +import java.awt.image.BufferedImage; +import java.nio.ByteBuffer; + + +public class ProcessedImageData { + private final int width; + private final int height; + private final Frame[] frames; + private final long[] delay; + private final long duration; + + public ProcessedImageData(BufferedImage image) { + width = image.getWidth(); + height = image.getHeight(); + frames = new Frame[] { loadFrom(image) }; + delay = new long[] { 0 }; + duration = 0; + } + + public ProcessedImageData(GifDecoder decoder) { + Dimension frameSize = decoder.getFrameSize(); + width = (int) frameSize.getWidth(); + height = (int) frameSize.getHeight(); + frames = new Frame[decoder.getFrameCount()]; + delay = new long[decoder.getFrameCount()]; + long time = 0; + for (int i = 0; i < decoder.getFrameCount(); i++) { + frames[i] = loadFrom(decoder.getFrame(i)); + delay[i] = time; + time += decoder.getDelay(i); + } + duration = time; + } + + public int getWidth() { + return width; + } + + public int getHeight() { + return height; + } + + public long[] getDelay() { + return delay; + } + + public long getDuration() { + return duration; + } + + public boolean isAnimated() { + return frames.length > 1; + } + + public int getFrameCount() { + return frames.length; + } + + public int uploadFrame(int index) { + if (index >= 0 && index < frames.length) { + Frame frame = frames[index]; + if (frame != null) { + frames[index] = null; + return uploadFrame(frame.buffer, frame.hasAlpha, width, height); + } + } + return -1; + } + + private static int uploadFrame(ByteBuffer buffer, boolean hasAlpha, int width, int height) { + int textureID = GL11.glGenTextures(); //Generate texture ID + GL11.glBindTexture(GL11.GL_TEXTURE_2D, textureID); //Bind texture ID + + //Setup wrap mode + GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL12.GL_CLAMP_TO_EDGE); + GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL12.GL_CLAMP_TO_EDGE); + + //Setup texture scaling filtering + GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR); + GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR); + + if (!hasAlpha) { + GL11.glPixelStorei(GL11.GL_UNPACK_ALIGNMENT, 1); + } + + //Send texel data to OpenGL + GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, hasAlpha ? GL11.GL_RGBA8 : GL11.GL_RGB8, width, height, 0, hasAlpha ? GL11.GL_RGBA : GL11.GL_RGB, GL11.GL_UNSIGNED_BYTE, buffer); + + //Return the texture ID so we can bind it later again + return textureID; + } + + private static Frame loadFrom(BufferedImage image) { + int width = image.getWidth(); + int height = image.getHeight(); + int[] pixels = new int[width * height]; + image.getRGB(0, 0, width, height, pixels, 0, width); + boolean hasAlpha = false; + if (image.getColorModel().hasAlpha()) { + for (int pixel : pixels) { + if ((pixel >> 24 & 0xFF) < 0xFF) { + hasAlpha = true; + break; + } + } + } + int bytesPerPixel = hasAlpha ? 4 : 3; + ByteBuffer buffer = BufferUtils.createByteBuffer(width * height * bytesPerPixel); + for (int pixel : pixels) { + buffer.put((byte) ((pixel >> 16) & 0xFF)); // Red component + buffer.put((byte) ((pixel >> 8) & 0xFF)); // Green component + buffer.put((byte) (pixel & 0xFF)); // Blue component + if (hasAlpha) { + buffer.put((byte) ((pixel >> 24) & 0xFF)); // Alpha component. Only for RGBA + } + } + buffer.flip(); + return new Frame(buffer, hasAlpha); + } + + private static class Frame { + private final ByteBuffer buffer; + private final boolean hasAlpha; + + public Frame(ByteBuffer buffer, boolean alpha) { + this.buffer = buffer; + this.hasAlpha = alpha; + } + } +} diff --git a/src/main/java/gregtech/api/gui/resources/utils/TextureCache.java b/src/main/java/gregtech/api/gui/resources/utils/TextureCache.java new file mode 100644 index 00000000000..3bdc29701a1 --- /dev/null +++ b/src/main/java/gregtech/api/gui/resources/utils/TextureCache.java @@ -0,0 +1,150 @@ +package gregtech.api.gui.resources.utils; + +import net.minecraft.client.Minecraft; +import org.apache.commons.codec.binary.Base64; +import org.apache.commons.io.IOUtils; + +import java.io.*; +import java.util.HashMap; +import java.util.Map; +import java.util.zip.GZIPInputStream; +import java.util.zip.GZIPOutputStream; + +public class TextureCache { + private File cacheDirectory = new File(Minecraft.getMinecraft().gameDir, "opframe_cache"); + private File index = new File(cacheDirectory, "index"); + + private Map entries = new HashMap(); + + public TextureCache() { + if (!cacheDirectory.exists()) { + cacheDirectory.mkdirs(); + } + loadIndex(); + } + + public void save(String url, String etag, long time, long expireTime, byte[] data) { + CacheEntry entry = new CacheEntry(url, etag, time, expireTime); + boolean saved = false; + OutputStream out = null; + try { + out = new FileOutputStream(entry.getFile()); + out.write(data); + saved = true; + } catch (IOException e) { + DownloadThread.LOGGER.error("Failed to save cache entry {}", e, url); + } finally { + IOUtils.closeQuietly(out); + } + if (saved) { + entries.put(url, entry); + saveIndex(); + } + } + + public CacheEntry getEntry(String url) { + return entries.get(url); + } + + private void loadIndex() { + if (index.exists()) { + Map previousEntries = entries; + entries = new HashMap(); + DataInputStream in = null; + try { + in = new DataInputStream(new GZIPInputStream(new FileInputStream(index))); + int length = in.readInt(); + for (int i = 0; i < length; i++) { + String url = in.readUTF(); + String etag = in.readUTF(); + long time = in.readLong(); + long expireTime = in.readLong(); + CacheEntry entry = new CacheEntry(url, etag.length() > 0 ? etag : null, time, expireTime); + entries.put(entry.getUrl(), entry); + } + } catch (IOException e) { + DownloadThread.LOGGER.error("Failed to load cache index", e); + entries = previousEntries; + } finally { + IOUtils.closeQuietly(in); + } + } + } + + private void saveIndex() { + DataOutputStream out = null; + try { + out = new DataOutputStream(new GZIPOutputStream(new FileOutputStream(index))); + out.writeInt(entries.size()); + for (Map.Entry mapEntry : entries.entrySet()) { + CacheEntry entry = mapEntry.getValue(); + out.writeUTF(entry.getUrl()); + out.writeUTF(entry.getEtag() == null ? "" : entry.getEtag()); + out.writeLong(entry.getTime()); + out.writeLong(entry.getExpireTime()); + } + } catch (IOException e) { + DownloadThread.LOGGER.error("Failed to save cache index", e); + } finally { + IOUtils.closeQuietly(out); + } + } + + public void deleteEntry(String url) { + entries.remove(url); + File file = getFile(url); + if (file.exists()) { + file.delete(); + } + } + + private static File getFile(String url) { + return new File(DownloadThread.TEXTURE_CACHE.cacheDirectory, Base64.encodeBase64String(url.getBytes())); + } + + public static class CacheEntry { + private String url; + private String etag; + private long time; + private long expireTime; + + public CacheEntry(String url, String etag, long time, long expireTime) { + this.url = url; + this.etag = etag; + this.time = time; + this.expireTime = expireTime; + } + + public void setEtag(String etag) { + this.etag = etag; + } + + public void setTime(long time) { + this.time = time; + } + + public void setExpireTime(long expireTime) { + this.expireTime = expireTime; + } + + public String getUrl() { + return url; + } + + public String getEtag() { + return etag; + } + + public long getTime() { + return time; + } + + public long getExpireTime() { + return expireTime; + } + + public File getFile() { + return TextureCache.getFile(url); + } + } +} diff --git a/src/main/java/gregtech/api/gui/widgets/AbstractWidgetGroup.java b/src/main/java/gregtech/api/gui/widgets/AbstractWidgetGroup.java index 9644b91401d..9c2c75af9c6 100644 --- a/src/main/java/gregtech/api/gui/widgets/AbstractWidgetGroup.java +++ b/src/main/java/gregtech/api/gui/widgets/AbstractWidgetGroup.java @@ -21,11 +21,12 @@ public class AbstractWidgetGroup extends Widget implements IGhostIngredientTarget, IIngredientSlot { - protected final List widgets = new ArrayList<>(); - private final WidgetGroupUIAccess groupUIAccess = new WidgetGroupUIAccess(); - private boolean isVisible = true; - private final boolean isDynamicSized; - private boolean initialized = false; + public transient final List widgets = new ArrayList<>(); + private transient final WidgetGroupUIAccess groupUIAccess = new WidgetGroupUIAccess(); + private transient final boolean isDynamicSized; + private transient boolean initialized = false; + protected transient List waitToRemoved; + public AbstractWidgetGroup(Position position) { super(position, Size.ZERO); @@ -41,8 +42,8 @@ public List getContainedWidgets(boolean includeHidden) { ArrayList containedWidgets = new ArrayList<>(widgets.size()); for (Widget widget : widgets) { + if (!widget.isVisible() && !includeHidden) continue; containedWidgets.add(widget); - if (widget instanceof AbstractWidgetGroup) containedWidgets.addAll(((AbstractWidgetGroup) widget).getContainedWidgets(includeHidden)); } @@ -59,12 +60,6 @@ protected void onPositionUpdate() { recomputeSize(); } - public void applyScissor(final int parentX, final int parentY, final int parentWidth, final int parentHeight) { - for (Widget widget : getContainedWidgets(true)) { - widget.applyScissor(parentX, parentY, parentWidth, parentHeight); - } - } - protected boolean recomputeSize() { if (isDynamicSized) { Size currentSize = getSize(); @@ -95,12 +90,10 @@ protected Size computeDynamicSize() { } public void setVisible(boolean visible) { - this.isVisible = visible; - widgets.stream().flatMap(it -> it.getNativeWidgets().stream()).forEach(it -> it.setEnabled(visible)); - } - - public boolean isVisible() { - return isVisible; + if (this.isVisible() == visible) { + return; + } + super.setVisible(visible); } protected void addWidget(Widget widget) { @@ -124,6 +117,34 @@ protected void addWidget(Widget widget) { } } + protected void addWidget(int index, Widget widget) { + if (widget == this) { + throw new IllegalArgumentException("Cannot add self"); + } + if (widgets.contains(widget)) { + throw new IllegalArgumentException("Already added"); + } + this.widgets.add(index, widget); + widget.setUiAccess(groupUIAccess); + widget.setGui(gui); + widget.setSizes(sizes); + widget.setParentPosition(getPosition()); + if (initialized) { + widget.initWidget(); + } + recomputeSize(); + if (uiAccess != null) { + uiAccess.notifyWidgetChange(); + } + } + + protected void waitToRemoved(Widget widget) { + if (waitToRemoved == null) { + waitToRemoved = new ArrayList<>(); + } + waitToRemoved.add(widget); + } + protected void removeWidget(Widget widget) { if (!widgets.contains(widget)) { throw new IllegalArgumentException("Not added"); @@ -153,12 +174,8 @@ protected void clearAllWidgets() { } } - public boolean isWidgetVisible(Widget widget) { - return this.isVisible; - } - public boolean isWidgetClickable(Widget widget) { - return isWidgetVisible(widget); + return isVisible(); } @Override @@ -185,12 +202,12 @@ public List getNativeWidgets() { @Override public List> getPhantomTargets(Object ingredient) { - if (!isVisible) { + if (!isVisible()) { return Collections.emptyList(); } ArrayList> targets = new ArrayList<>(); for (Widget widget : widgets) { - if (widget instanceof IGhostIngredientTarget) { + if (widget.isVisible() && widget instanceof IGhostIngredientTarget) { targets.addAll(((IGhostIngredientTarget) widget).getPhantomTargets(ingredient)); } } @@ -199,11 +216,11 @@ public List> getPhantomTargets(Object ingredient) { @Override public Object getIngredientOverMouse(int mouseX, int mouseY) { - if (!isVisible) { + if (!isVisible()) { return Collections.emptyList(); } for (Widget widget : widgets) { - if (widget instanceof IIngredientSlot) { + if (widget.isVisible() && widget instanceof IIngredientSlot) { IIngredientSlot ingredientSlot = (IIngredientSlot) widget; Object result = ingredientSlot.getIngredientOverMouse(mouseX, mouseY); if (result != null) return result; @@ -215,31 +232,43 @@ public Object getIngredientOverMouse(int mouseX, int mouseY) { @Override public void detectAndSendChanges() { for (Widget widget : widgets) { - widget.detectAndSendChanges(); + if (widget.isActive()) { + widget.detectAndSendChanges(); + } + } + if (waitToRemoved != null) { + waitToRemoved.forEach(this::removeWidget); + waitToRemoved = null; } } @Override public void updateScreen() { for (Widget widget : widgets) { - widget.updateScreen(); + if (widget.isActive()) { + widget.updateScreen(); + } + } + if (waitToRemoved != null) { + waitToRemoved.forEach(this::removeWidget); + waitToRemoved = null; } } @Override public void drawInForeground(int mouseX, int mouseY) { for (Widget widget : widgets) { - if (isWidgetVisible(widget)) { + if (widget.isVisible()) { widget.drawInForeground(mouseX, mouseY); } } } @Override - public void drawInBackground(int mouseX, int mouseY, IRenderContext context) { + public void drawInBackground(int mouseX, int mouseY, float partialTicks, IRenderContext context) { for (Widget widget : widgets) { - if (isWidgetVisible(widget)) { - widget.drawInBackground(mouseX, mouseY, context); + if (widget.isVisible()) { + widget.drawInBackground(mouseX, mouseY, partialTicks, context); } } GlStateManager.color(rColorForOverlay, gColorForOverlay, bColorForOverlay, 1.0F); @@ -247,27 +276,57 @@ public void drawInBackground(int mouseX, int mouseY, IRenderContext context) { @Override public boolean mouseWheelMove(int mouseX, int mouseY, int wheelDelta) { - return widgets.stream().filter(this::isWidgetClickable).anyMatch(it -> it.mouseWheelMove(mouseX, mouseY, wheelDelta)); + for (int i = widgets.size() - 1; i >= 0; i--) { + Widget widget = widgets.get(i); + if(widget.isVisible() && widget.isActive() && widget.mouseWheelMove(mouseX, mouseY, wheelDelta)) { + return true; + } + } + return false; } @Override public boolean mouseClicked(int mouseX, int mouseY, int button) { - return widgets.stream().filter(this::isWidgetClickable).anyMatch(it -> it.mouseClicked(mouseX, mouseY, button)); + for (int i = widgets.size() - 1; i >= 0; i--) { + Widget widget = widgets.get(i); + if(widget.isVisible() && widget.isActive() && widget.mouseClicked(mouseX, mouseY, button)) { + return true; + } + } + return false; } @Override public boolean mouseDragged(int mouseX, int mouseY, int button, long timeDragged) { - return widgets.stream().filter(this::isWidgetClickable).anyMatch(it -> it.mouseDragged(mouseX, mouseY, button, timeDragged)); + for (int i = widgets.size() - 1; i >= 0; i--) { + Widget widget = widgets.get(i); + if(widget.isVisible() && widget.isActive() && widget.mouseDragged(mouseX, mouseY, button, timeDragged)) { + return true; + } + } + return false; } @Override public boolean mouseReleased(int mouseX, int mouseY, int button) { - return widgets.stream().filter(this::isWidgetClickable).anyMatch(it -> it.mouseReleased(mouseX, mouseY, button)); + for (int i = widgets.size() - 1; i >= 0; i--) { + Widget widget = widgets.get(i); + if(widget.isVisible() && widget.isActive() && widget.mouseReleased(mouseX, mouseY, button)) { + return true; + } + } + return false; } @Override public boolean keyTyped(char charTyped, int keyCode) { - return widgets.stream().filter(this::isWidgetClickable).anyMatch(it -> it.keyTyped(charTyped, keyCode)); + for (int i = widgets.size() - 1; i >= 0; i--) { + Widget widget = widgets.get(i); + if(widget.isVisible() && widget.isActive() && widget.keyTyped(charTyped, keyCode)) { + return true; + } + } + return false; } @Override diff --git a/src/main/java/gregtech/api/gui/widgets/ClickButtonWidget.java b/src/main/java/gregtech/api/gui/widgets/ClickButtonWidget.java index 3b6f45f8b46..b9285632b55 100644 --- a/src/main/java/gregtech/api/gui/widgets/ClickButtonWidget.java +++ b/src/main/java/gregtech/api/gui/widgets/ClickButtonWidget.java @@ -24,6 +24,7 @@ public class ClickButtonWidget extends Widget { protected final String displayText; protected int textColor = 0xFFFFFF; protected final Consumer onPressCallback; + protected boolean shouldClientCallback; public ClickButtonWidget(int xPosition, int yPosition, int width, int height, String displayText, Consumer onPressed) { super(new Position(xPosition, yPosition), new Size(width, height)); @@ -31,6 +32,11 @@ public ClickButtonWidget(int xPosition, int yPosition, int width, int height, St this.onPressCallback = onPressed; } + public ClickButtonWidget setShouldClientCallback(boolean shouldClientCallback) { + this.shouldClientCallback = shouldClientCallback; + return this; + } + public ClickButtonWidget setButtonTexture(TextureArea buttonTexture) { this.buttonTexture = buttonTexture; return this; @@ -71,6 +77,9 @@ public boolean mouseClicked(int mouseX, int mouseY, int button) { protected void triggerButton() { ClickData clickData = new ClickData(Mouse.getEventButton(), isShiftDown(), isCtrlDown()); writeClientAction(1, clickData::writeToBuf); + if (shouldClientCallback) { + onPressCallback.accept(clickData); + } playButtonClickSound(); } diff --git a/src/main/java/gregtech/api/gui/widgets/CraftingStationInputWidgetGroup.java b/src/main/java/gregtech/api/gui/widgets/CraftingStationInputWidgetGroup.java new file mode 100644 index 00000000000..1d9b24efa69 --- /dev/null +++ b/src/main/java/gregtech/api/gui/widgets/CraftingStationInputWidgetGroup.java @@ -0,0 +1,70 @@ +package gregtech.api.gui.widgets; + +import gregtech.api.gui.GuiTextures; +import gregtech.api.gui.IRenderContext; +import gregtech.api.gui.Widget; +import gregtech.api.util.Position; +import gregtech.common.metatileentities.storage.CraftingRecipeResolver; +import net.minecraft.network.PacketBuffer; +import net.minecraftforge.items.ItemStackHandler; + +public class CraftingStationInputWidgetGroup extends AbstractWidgetGroup { + protected CraftingRecipeResolver recipeResolver; + protected short tintLocations; + public static final int LIGHT_RED = 0x66FF0000; + + public CraftingStationInputWidgetGroup(int x, int y, ItemStackHandler craftingGrid, CraftingRecipeResolver recipeResolver) { + super(new Position(x, y)); + + //crafting grid + for (int i = 0; i < 3; ++i) { + for (int j = 0; j < 3; ++j) { + this.addWidget(new PhantomSlotWidget(craftingGrid, j + i * 3, x + j * 18, y + i * 18).setBackgroundTexture(GuiTextures.SLOT)); + } + } + + this.recipeResolver = recipeResolver; + } + + @Override + public void drawInBackground(int mouseX, int mouseY, IRenderContext context) { + super.drawInBackground(mouseX, mouseY, context); + if(this.widgets.size() == 9) { // In case someone added more... + for (int i = 0; i < 9; i++) { + Widget widget = widgets.get(i); + if (widget instanceof PhantomSlotWidget && ((tintLocations >> i) & 1) == 0) { // In other words, is this slot usable? + int color = LIGHT_RED; + + PhantomSlotWidget phantomSlotWidget = (PhantomSlotWidget) widget; + drawSolidRect(phantomSlotWidget.getPosition().x, phantomSlotWidget.getPosition().y, + phantomSlotWidget.getSize().getWidth() - 1, phantomSlotWidget.getSize().getWidth() - 1, color); + } + } + } + } + + @Override + public void detectAndSendChanges() { + super.detectAndSendChanges(); + short newTintLocations = getTintLocations(); + if (tintLocations != newTintLocations) { + this.tintLocations = newTintLocations; + writeUpdateInfo(2, buffer -> buffer.writeShort(tintLocations)); + } + } + + private short getTintLocations() { + if(recipeResolver.getCachedRecipeData() != null) { + return recipeResolver.getCachedRecipeData().attemptMatchRecipe(); + } else { + return 511; + } + } + + public void readUpdateInfo(int id, PacketBuffer buffer) { + super.readUpdateInfo(id, buffer); + if (id == 2) { + tintLocations = buffer.readShort(); + } + } +} diff --git a/src/main/java/gregtech/api/gui/widgets/ImageWidget.java b/src/main/java/gregtech/api/gui/widgets/ImageWidget.java index 7f1cb903702..a4c98417aef 100644 --- a/src/main/java/gregtech/api/gui/widgets/ImageWidget.java +++ b/src/main/java/gregtech/api/gui/widgets/ImageWidget.java @@ -2,6 +2,7 @@ import gregtech.api.gui.IRenderContext; import gregtech.api.gui.Widget; +import gregtech.api.gui.resources.IGuiTexture; import gregtech.api.gui.resources.TextureArea; import gregtech.api.util.Position; import gregtech.api.util.Size; @@ -16,16 +17,18 @@ public class ImageWidget extends Widget { - protected TextureArea area; + protected IGuiTexture area; private BooleanSupplier predicate; private boolean isVisible = true; + private int border; + private int borderColor; public ImageWidget(int xPosition, int yPosition, int width, int height) { super(new Position(xPosition, yPosition), new Size(width, height)); } - public ImageWidget(int xPosition, int yPosition, int width, int height, TextureArea area) { + public ImageWidget(int xPosition, int yPosition, int width, int height, IGuiTexture area) { this(xPosition, yPosition, width, height); this.area = area; } @@ -35,12 +38,25 @@ public ImageWidget setImage(TextureArea area) { return this; } + public ImageWidget setBorder(int border, int color) { + this.border = border; + this.borderColor = color; + return this; + } + public ImageWidget setPredicate(BooleanSupplier predicate) { this.predicate = predicate; this.isVisible = false; return this; } + @Override + public void updateScreen() { + if (area != null) { + area.updateTick(); + } + } + @Override public void detectAndSendChanges() { super.detectAndSendChanges(); @@ -65,6 +81,9 @@ public void drawInBackground(int mouseX, int mouseY, IRenderContext context) { Position position = getPosition(); Size size = getSize(); area.draw(position.x, position.y, size.width, size.height); + if (border > 0) { + drawBorder(position.x, position.y, size.width, size.height, borderColor, border); + } GlStateManager.color(rColorForOverlay, gColorForOverlay, bColorForOverlay, 1.0F); } diff --git a/src/main/java/gregtech/api/gui/widgets/LabelWidget.java b/src/main/java/gregtech/api/gui/widgets/LabelWidget.java index 2086ce2b9a7..57a7988549b 100644 --- a/src/main/java/gregtech/api/gui/widgets/LabelWidget.java +++ b/src/main/java/gregtech/api/gui/widgets/LabelWidget.java @@ -11,15 +11,24 @@ import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + import static gregtech.api.gui.impl.ModularUIGui.*; public class LabelWidget extends Widget { - protected boolean xCentered = false; + protected boolean xCentered; + protected boolean yCentered; + protected int width; protected final String text; protected final Object[] formatting; private final int color; + private boolean dropShadow; + @SideOnly(Side.CLIENT) + private List texts; public LabelWidget(int xPosition, int yPosition, String text, Object... formatting) { this(xPosition, yPosition, text, 0x404040, formatting); @@ -34,9 +43,34 @@ public LabelWidget(int xPosition, int yPosition, String text, int color, Object[ this.text = text; this.color = color; this.formatting = formatting; + if (isClientSide()) { + texts = Collections.singletonList(getResultText()); + } recomputeSize(); } + public LabelWidget setShadow(boolean dropShadow){ + this.dropShadow = dropShadow; + return this; + } + + public LabelWidget setWidth(int width) { + this.width = width; + if (isClientSide()) { + if (this.width > 0) { + texts = Minecraft.getMinecraft().fontRenderer.listFormattedStringToWidth(getResultText(), width); + } else { + texts = Collections.singletonList(getResultText()); + } + } + return this; + } + + public LabelWidget setYCentered(boolean yCentered) { + this.yCentered = yCentered; + return this; + } + private String getResultText() { return I18n.format(text, formatting); } @@ -60,15 +94,17 @@ public LabelWidget setXCentered(boolean xCentered) { @Override @SideOnly(Side.CLIENT) public void drawInBackground(int mouseX, int mouseY, IRenderContext context) { - String resultText = getResultText(); FontRenderer fontRenderer = Minecraft.getMinecraft().fontRenderer; Position pos = getPosition(); - if (!xCentered) { - fontRenderer.drawString(resultText, pos.x, pos.y, color); - } else { - fontRenderer.drawString(resultText, - pos.x - fontRenderer.getStringWidth(resultText) / 2, pos.y, color); + int height = fontRenderer.FONT_HEIGHT * texts.size(); + for (int i = 0; i < texts.size(); i++) { + String resultText = texts.get(i); + int width = fontRenderer.getStringWidth(resultText);; + float x = pos.x - (xCentered ? width / 2f : 0); + float y = pos.y - (yCentered ? height / 2f : 0) + i * fontRenderer.FONT_HEIGHT; + fontRenderer.drawString(resultText, x, y, color, dropShadow); } + GlStateManager.color(rColorForOverlay, gColorForOverlay, bColorForOverlay, 1.0F); } diff --git a/src/main/java/gregtech/api/gui/widgets/PhantomFluidWidget.java b/src/main/java/gregtech/api/gui/widgets/PhantomFluidWidget.java index 518f20674a4..9a0430674ad 100644 --- a/src/main/java/gregtech/api/gui/widgets/PhantomFluidWidget.java +++ b/src/main/java/gregtech/api/gui/widgets/PhantomFluidWidget.java @@ -6,11 +6,15 @@ import gregtech.api.gui.Widget; import gregtech.api.gui.ingredient.IGhostIngredientTarget; import gregtech.api.gui.ingredient.IIngredientSlot; +import gregtech.api.gui.resources.IGuiTexture; import gregtech.api.gui.resources.RenderUtil; import gregtech.api.gui.resources.TextureArea; import gregtech.api.util.Position; import gregtech.api.util.Size; +import gregtech.api.util.TextFormattingUtil; import mezz.jei.api.gui.IGhostIngredientHandler.Target; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; @@ -31,10 +35,12 @@ public class PhantomFluidWidget extends Widget implements IIngredientSlot, IGhostIngredientTarget { - protected TextureArea backgroundTexture = GuiTextures.FLUID_SLOT; + protected IGuiTexture backgroundTexture = GuiTextures.FLUID_SLOT; - private final Supplier fluidStackSupplier; - private final Consumer fluidStackUpdater; + private Supplier fluidStackSupplier; + private Consumer fluidStackUpdater; + private boolean isClient; + private boolean showTip; protected FluidStack lastFluidStack; public PhantomFluidWidget(int xPosition, int yPosition, int width, int height, Supplier fluidStackSupplier, Consumer fluidStackUpdater) { @@ -52,6 +58,22 @@ private FluidStack drainFrom(Object ingredient) { } return null; } + public PhantomFluidWidget showTip(boolean showTip) { + this.showTip = showTip; + return this; + } + + public PhantomFluidWidget setFluidStackSupplier(Supplier fluidStackSupplier, boolean isClient) { + this.fluidStackSupplier = fluidStackSupplier; + this.isClient = isClient; + return this; + } + + public PhantomFluidWidget setFluidStackUpdater(Consumer fluidStackUpdater, boolean isClient) { + this.fluidStackUpdater = fluidStackUpdater; + this.isClient = isClient; + return this; + } @Override public List> getPhantomTargets(Object ingredient) { @@ -79,6 +101,10 @@ public void accept(@Nonnull Object ingredient) { NBTTagCompound tagCompound = ingredientStack.writeToNBT(new NBTTagCompound()); writeClientAction(2, buffer -> buffer.writeCompoundTag(tagCompound)); } + + if (isClient && fluidStackUpdater != null) { + fluidStackUpdater.accept(ingredientStack); + } } }); } @@ -91,11 +117,19 @@ public Object getIngredientOverMouse(int mouseX, int mouseY) { return null; } - public PhantomFluidWidget setBackgroundTexture(TextureArea backgroundTexture) { + public PhantomFluidWidget setBackgroundTexture(IGuiTexture backgroundTexture) { this.backgroundTexture = backgroundTexture; return this; } + @Override + public void updateScreen() { + super.updateScreen(); + if (isClient && fluidStackSupplier != null) { + this.lastFluidStack = fluidStackSupplier.get(); + } + } + @Override public void detectAndSendChanges() { FluidStack currentStack = fluidStackSupplier.get(); @@ -157,6 +191,9 @@ public boolean mouseClicked(int mouseX, int mouseY, int button) { if (isMouseOverElement(mouseX, mouseY)) { writeClientAction(1, buffer -> { }); + if (isClient && fluidStackUpdater != null) { + fluidStackUpdater.accept(null); + } return true; } return false; @@ -172,6 +209,14 @@ public void drawInBackground(int mouseX, int mouseY, IRenderContext context) { if (lastFluidStack != null) { GlStateManager.disableBlend(); RenderUtil.drawFluidForGui(lastFluidStack, lastFluidStack.amount, pos.x + 1, pos.y + 1, size.width - 1, size.height - 1); + if(showTip) { + GlStateManager.pushMatrix(); + GlStateManager.scale(0.5, 0.5, 1); + String s = TextFormattingUtil.formatLongToCompactString(lastFluidStack.amount, 4) + "L"; + FontRenderer fontRenderer = Minecraft.getMinecraft().fontRenderer; + fontRenderer.drawStringWithShadow(s, (pos.x + (size.width / 3)) * 2 - fontRenderer.getStringWidth(s) + 21, (pos.y + (size.height / 3) + 6) * 2, 0xFFFFFF); + GlStateManager.popMatrix(); + } GlStateManager.enableBlend(); GlStateManager.color(rColorForOverlay, gColorForOverlay, bColorForOverlay, 1.0F); } diff --git a/src/main/java/gregtech/api/gui/widgets/PhantomSlotWidget.java b/src/main/java/gregtech/api/gui/widgets/PhantomSlotWidget.java index b8824f995da..df3a8bfa465 100644 --- a/src/main/java/gregtech/api/gui/widgets/PhantomSlotWidget.java +++ b/src/main/java/gregtech/api/gui/widgets/PhantomSlotWidget.java @@ -53,6 +53,8 @@ public void accept(@Nonnull Object ingredient) { if (ingredient instanceof ItemStack) { int mouseButton = Mouse.getEventButton(); boolean shiftDown = Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) || Keyboard.isKeyDown(Keyboard.KEY_RSHIFT); + ClickType clickType = shiftDown ? ClickType.QUICK_MOVE : ClickType.PICKUP; + SlotUtil.slotClickPhantom(slotReference, mouseButton, clickType, (ItemStack)ingredient); writeClientAction(1, buffer -> { buffer.writeItemStack((ItemStack) ingredient); buffer.writeVarInt(mouseButton); diff --git a/src/main/java/gregtech/api/gui/widgets/ScrollableListWidget.java b/src/main/java/gregtech/api/gui/widgets/ScrollableListWidget.java index 14677eb98bd..ff38eb6c99f 100644 --- a/src/main/java/gregtech/api/gui/widgets/ScrollableListWidget.java +++ b/src/main/java/gregtech/api/gui/widgets/ScrollableListWidget.java @@ -66,7 +66,6 @@ private void updateElementPositions() { currentPosY += widget.getSize().getHeight(); totalListHeight += widget.getSize().getHeight(); final Size size = getSize(); - widget.applyScissor(position.x, position.y, size.width - scrollPaneWidth, size.height); } this.totalListHeight = totalListHeight; this.slotHeight = widgets.isEmpty() ? 0 : totalListHeight / widgets.size(); @@ -85,7 +84,7 @@ public void drawInForeground(int mouseX, int mouseY) { } @Override - public void drawInBackground(int mouseX, int mouseY, IRenderContext context) { + public void drawInBackground(int mouseX, int mouseY, float partialTicks, IRenderContext context) { //make sure mouse is not hovered on any element when outside of bounds if (!isPositionInsideScissor(mouseX, mouseY)) { mouseX = Integer.MAX_VALUE; @@ -107,7 +106,7 @@ public void drawInBackground(int mouseX, int mouseY, IRenderContext context) { drawGradientRect(scrollX + 1, scrollSliderY, paneSize - 2, scrollSliderHeight, 0xFF555555, 0xFF454545); RenderUtil.useScissor(position.x, position.y, size.width - paneSize, size.height, () -> - super.drawInBackground(finalMouseX, finalMouseY, context)); + super.drawInBackground(finalMouseX, finalMouseY, partialTicks, context)); GlStateManager.color(rColorForOverlay, gColorForOverlay, bColorForOverlay, 1.0F); } diff --git a/src/main/java/gregtech/api/gui/widgets/SimpleTextWidget.java b/src/main/java/gregtech/api/gui/widgets/SimpleTextWidget.java index 0d9eda34a41..34c988a81bb 100644 --- a/src/main/java/gregtech/api/gui/widgets/SimpleTextWidget.java +++ b/src/main/java/gregtech/api/gui/widgets/SimpleTextWidget.java @@ -25,6 +25,8 @@ public class SimpleTextWidget extends Widget { protected final Supplier textSupplier; protected String lastText = ""; protected boolean isCentered = true; + protected boolean clientWidget; + protected boolean isShadow; public SimpleTextWidget(int xPosition, int yPosition, String formatLocale, int color, Supplier textSupplier, boolean isCentered) { super(new Position(xPosition, yPosition), Size.ZERO); @@ -38,10 +40,23 @@ public SimpleTextWidget(int xPosition, int yPosition, String formatLocale, int c this(xPosition, yPosition, formatLocale, color, textSupplier, true); } + public SimpleTextWidget(int xPosition, int yPosition, String formatLocale, int color, Supplier textSupplier, boolean clientWidget) { + super(new Position(xPosition, yPosition), Size.ZERO); + this.color = color; + this.formatLocale = formatLocale; + this.textSupplier = textSupplier; + this.clientWidget = clientWidget; + } + public SimpleTextWidget(int xPosition, int yPosition, String formatLocale, Supplier textSupplier) { this(xPosition, yPosition, formatLocale, 0x404040, textSupplier, true); } + public SimpleTextWidget setShadow(boolean shadow) { + isShadow = shadow; + return this; + } + private void updateSize() { FontRenderer fontRenderer = Minecraft.getMinecraft().fontRenderer; int stringWidth = fontRenderer.getStringWidth(lastText); @@ -51,14 +66,27 @@ private void updateSize() { } } + @Override + public void updateScreen() { + super.updateScreen(); + if (clientWidget && textSupplier != null) { + String newString = textSupplier.get(); + if (!newString.equals(lastText)) { + lastText = newString; + updateSize(); + } + lastText = newString; + } + } + @Override public void drawInBackground(int mouseX, int mouseY, IRenderContext context) { FontRenderer fontRenderer = Minecraft.getMinecraft().fontRenderer; String text = formatLocale.isEmpty() ? (I18n.hasKey(lastText) ? I18n.format(lastText) : lastText) : I18n.format(formatLocale, lastText); Position position = getPosition(); fontRenderer.drawString(text, - isCentered ? position.x - fontRenderer.getStringWidth(text) / 2 : position.x, - isCentered ? position.y - fontRenderer.FONT_HEIGHT / 2 : position.y, color); + isCentered ? position.x - fontRenderer.getStringWidth(text) / 2 : position.x, + isCentered ? position.y - fontRenderer.FONT_HEIGHT / 2 : position.y, color, isShadow); GlStateManager.color(rColorForOverlay, gColorForOverlay, bColorForOverlay, 1.0F); } diff --git a/src/main/java/gregtech/api/gui/widgets/SlotWidget.java b/src/main/java/gregtech/api/gui/widgets/SlotWidget.java index 041c84ca0d5..1d72ce11d5a 100644 --- a/src/main/java/gregtech/api/gui/widgets/SlotWidget.java +++ b/src/main/java/gregtech/api/gui/widgets/SlotWidget.java @@ -2,11 +2,15 @@ import gregtech.api.gui.INativeWidget; import gregtech.api.gui.IRenderContext; -import gregtech.api.gui.IScissored; +import gregtech.api.gui.ISizeProvider; import gregtech.api.gui.Widget; -import gregtech.api.gui.resources.TextureArea; +import gregtech.api.gui.resources.IGuiTexture; import gregtech.api.util.Position; import gregtech.api.util.Size; +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.entity.player.EntityPlayer; import net.minecraft.inventory.ClickType; import net.minecraft.inventory.IInventory; @@ -19,7 +23,6 @@ import net.minecraftforge.items.SlotItemHandler; import javax.annotation.Nonnull; -import java.awt.*; public class SlotWidget extends Widget implements INativeWidget { @@ -30,11 +33,9 @@ public class SlotWidget extends Widget implements INativeWidget { protected final boolean canPutItems; protected SlotLocationInfo locationInfo = new SlotLocationInfo(false, false); - protected TextureArea[] backgroundTexture; + protected IGuiTexture[] backgroundTexture; protected Runnable changeListener; - protected Rectangle scissor; - public SlotWidget(IInventory inventory, int slotIndex, int xPosition, int yPosition, boolean canTakeItems, boolean canPutItems) { super(new Position(xPosition, yPosition), new Size(18, 18)); this.canTakeItems = canTakeItems; @@ -49,6 +50,12 @@ public SlotWidget(IItemHandler itemHandler, int slotIndex, int xPosition, int yP this.slotReference = createSlot(itemHandler, slotIndex); } + @Override + public void setSizes(ISizeProvider sizes) { + super.setSizes(sizes); + onPositionUpdate(); + } + protected Slot createSlot(IInventory inventory, int index) { return new WidgetSlot(inventory, index, 0, 0); } @@ -63,9 +70,35 @@ public void drawInBackground(int mouseX, int mouseY, IRenderContext context) { if (isEnabled() && backgroundTexture != null) { Position pos = getPosition(); Size size = getSize(); - for (TextureArea backgroundTexture : this.backgroundTexture) { + for (IGuiTexture backgroundTexture : this.backgroundTexture) { backgroundTexture.draw(pos.x, pos.y, size.width, size.height); } + + RenderHelper.enableGUIStandardItemLighting(); + GlStateManager.pushMatrix(); + RenderItem itemRender = Minecraft.getMinecraft().getRenderItem(); + itemRender.renderItemAndEffectIntoGUI(slotReference.getStack(), pos.x + 1, pos.y + 1); + itemRender.renderItemOverlayIntoGUI(Minecraft.getMinecraft().fontRenderer, slotReference.getStack(), pos.x + 1, pos.y + 1, null); + GlStateManager.enableAlpha(); + GlStateManager.popMatrix(); + RenderHelper.disableStandardItemLighting(); + } + } + + @Override + public void drawInForeground(int mouseX, int mouseY) { + if (slotReference instanceof ISlotWidget) { + if (isMouseOverElement(mouseX, mouseY)) { + ((ISlotWidget) slotReference).setHover(true); + 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 { + ((ISlotWidget) slotReference).setHover(false); + } } } @@ -88,11 +121,6 @@ public void setEnabled(boolean enabled) { isEnabled = enabled; } - @Override - public void applyScissor(final int parentX, final int parentY, final int parentWidth, final int parentHeight) { - this.scissor = new Rectangle(parentX, parentY, parentWidth, parentHeight); - } - @Override public void detectAndSendChanges() { } @@ -109,7 +137,7 @@ public SlotWidget(IInventory inventory, int slotIndex, int xPosition, int yPosit * Sets array of background textures used by slot * they are drawn on top of each other */ - public SlotWidget setBackgroundTexture(TextureArea... backgroundTexture) { + public SlotWidget setBackgroundTexture(IGuiTexture... backgroundTexture) { this.backgroundTexture = backgroundTexture; return this; } @@ -133,13 +161,7 @@ public boolean canTakeStack(EntityPlayer player) { } public boolean isEnabled() { - if (!this.isEnabled) { - return false; - } - if (this.scissor == null) { - return true; - } - return scissor.intersects(toRectangleBox()); + return this.isEnabled; } @Override @@ -161,11 +183,28 @@ public final Slot getHandle() { return slotReference; } - protected class WidgetSlot extends Slot implements IScissored { + public interface ISlotWidget { + void setHover(boolean isHover); + boolean isHover(); + } + + protected class WidgetSlot extends Slot implements ISlotWidget { + boolean isHover; + public WidgetSlot(IInventory inventory, int index, int xPosition, int yPosition) { super(inventory, index, xPosition, yPosition); } + @Override + public void setHover(boolean isHover) { + this.isHover = isHover; + } + + @Override + public boolean isHover() { + return isHover; + } + @Override public boolean isItemValid(@Nonnull ItemStack stack) { return SlotWidget.this.canPutStack(stack) && super.isItemValid(stack); @@ -200,18 +239,25 @@ public boolean isEnabled() { return SlotWidget.this.isEnabled(); } - @Override - public Rectangle getScissor() { - return SlotWidget.this.scissor; - } } - protected class WidgetSlotItemHandler extends SlotItemHandler implements IScissored { + protected class WidgetSlotItemHandler extends SlotItemHandler implements ISlotWidget { + boolean isHover; public WidgetSlotItemHandler(IItemHandler itemHandler, int index, int xPosition, int yPosition) { super(itemHandler, index, xPosition, yPosition); } + @Override + public void setHover(boolean isHover) { + this.isHover = isHover; + } + + @Override + public boolean isHover() { + return isHover; + } + @Override public boolean isItemValid(@Nonnull ItemStack stack) { return SlotWidget.this.canPutStack(stack) && super.isItemValid(stack); @@ -246,9 +292,5 @@ public boolean isEnabled() { return SlotWidget.this.isEnabled(); } - @Override - public Rectangle getScissor() { - return SlotWidget.this.scissor; - } } } diff --git a/src/main/java/gregtech/api/gui/widgets/TabGroup.java b/src/main/java/gregtech/api/gui/widgets/TabGroup.java index bbe6cfedf71..de108f336aa 100644 --- a/src/main/java/gregtech/api/gui/widgets/TabGroup.java +++ b/src/main/java/gregtech/api/gui/widgets/TabGroup.java @@ -16,50 +16,78 @@ import net.minecraft.util.Tuple; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; +import java.util.function.BiConsumer; import java.util.function.Supplier; import static gregtech.api.gui.impl.ModularUIGui.*; -public class TabGroup extends AbstractWidgetGroup { +public class TabGroup extends AbstractWidgetGroup { private final List tabInfos = new ArrayList<>(); - private final Map tabWidgets = new HashMap<>(); - private int selectedTabIndex = 0; + private final List tabWidgets = new ArrayList<>(); + protected int selectedTabIndex = 0; private final TabListRenderer tabListRenderer; + private BiConsumer onTabChanged; + + public TabGroup(int x, int y, TabListRenderer tabListRenderer) { + super(new Position(x, y)); + this.tabListRenderer = tabListRenderer; + } public TabGroup(TabLocation tabLocation, Position position) { super(position); this.tabListRenderer = tabLocation.supplier.get(); } - public TabGroup(TabLocation tabLocation) { - this(tabLocation, Position.ORIGIN); - } - - public void addTab(ITabInfo tabInfo, AbstractWidgetGroup tabWidget) { + public void addTab(ITabInfo tabInfo, T tabWidget) { this.tabInfos.add(tabInfo); int tabIndex = tabInfos.size() - 1; - this.tabWidgets.put(tabIndex, tabWidget); + this.tabWidgets.add(tabWidget); tabWidget.setVisible(tabIndex == selectedTabIndex); + tabWidget.setActive(tabIndex == selectedTabIndex); addWidget(tabWidget); } + public void removeTab(int index) { + this.tabInfos.remove(index); + T tab = this.tabWidgets.remove(index); + this.removeWidget(tab); + if (selectedTabIndex >= index && selectedTabIndex > 0) { + selectedTabIndex--; + } + for (int i = 0; i < this.tabWidgets.size(); i++) { + tabWidgets.get(i).setActive(i == selectedTabIndex); + tabWidgets.get(i).setVisible(i == selectedTabIndex); + } + } + + public TabGroup setOnTabChanged(BiConsumer onTabChanged) { + this.onTabChanged = onTabChanged; + return this; + } + + public T getCurrentTag() { + return tabWidgets.get(selectedTabIndex); + } + + public List getAllTag() { + return tabWidgets; + } + @Override public List getContainedWidgets(boolean includeHidden) { ArrayList containedWidgets = new ArrayList<>(widgets.size()); if (includeHidden) { - for (Widget widget : tabWidgets.values()) { + for (Widget widget : tabWidgets) { containedWidgets.add(widget); if (widget instanceof AbstractWidgetGroup) containedWidgets.addAll(((AbstractWidgetGroup) widget).getContainedWidgets(true)); } } else { - AbstractWidgetGroup widgetGroup = tabWidgets.get(selectedTabIndex); + T widgetGroup = tabWidgets.get(selectedTabIndex); containedWidgets.add(widgetGroup); containedWidgets.addAll(widgetGroup.getContainedWidgets(false)); } @@ -68,8 +96,8 @@ public List getContainedWidgets(boolean includeHidden) { } @Override - public void drawInBackground(int mouseX, int mouseY, IRenderContext context) { - super.drawInBackground(mouseX, mouseY, context); + public void drawInBackground(int mouseX, int mouseY, float partialTicks, IRenderContext context) { + super.drawInBackground(mouseX, mouseY, partialTicks, context); this.tabListRenderer.renderTabs(getPosition(), tabInfos, sizes.getWidth(), sizes.getHeight(), selectedTabIndex); GlStateManager.color(rColorForOverlay, gColorForOverlay, bColorForOverlay, 1.0F); } @@ -88,7 +116,7 @@ public void drawInForeground(int mouseX, int mouseY) { @Override public boolean mouseClicked(int mouseX, int mouseY, int button) { - super.mouseClicked(mouseX, mouseY, button); + boolean flag = super.mouseClicked(mouseX, mouseY, button); Tuple tabOnMouse = getTabOnMouse(mouseX, mouseY); if (tabOnMouse != null) { ITabInfo tabInfo = tabOnMouse.getFirst(); @@ -100,13 +128,19 @@ public boolean mouseClicked(int mouseX, int mouseY, int button) { return true; } } - return false; + return flag; } private void setSelectedTab(int tabIndex) { + int old = selectedTabIndex; this.tabWidgets.get(selectedTabIndex).setVisible(false); + this.tabWidgets.get(selectedTabIndex).setActive(false); this.tabWidgets.get(tabIndex).setVisible(true); + this.tabWidgets.get(tabIndex).setActive(true); this.selectedTabIndex = tabIndex; + if (this.onTabChanged != null) { + onTabChanged.accept(old, tabIndex); + } } @Override @@ -141,9 +175,8 @@ private static boolean isMouseOverTab(int mouseX, int mouseY, int[] tabSizes) { return mouseX >= minX && mouseY >= minY && mouseX < maxX && mouseY < maxY; } - @Override public boolean isWidgetVisible(Widget widget) { - return tabWidgets.containsKey(selectedTabIndex) && tabWidgets.get(selectedTabIndex) == widget; + return tabWidgets.get(selectedTabIndex) == widget; } public enum TabLocation { diff --git a/src/main/java/gregtech/api/gui/widgets/TankWidget.java b/src/main/java/gregtech/api/gui/widgets/TankWidget.java index 149b1699543..59e239c5e8d 100644 --- a/src/main/java/gregtech/api/gui/widgets/TankWidget.java +++ b/src/main/java/gregtech/api/gui/widgets/TankWidget.java @@ -4,8 +4,8 @@ import gregtech.api.gui.IRenderContext; import gregtech.api.gui.Widget; import gregtech.api.gui.ingredient.IIngredientSlot; +import gregtech.api.gui.resources.IGuiTexture; import gregtech.api.gui.resources.RenderUtil; -import gregtech.api.gui.resources.TextureArea; import gregtech.api.util.FluidTooltipUtil; import gregtech.api.util.Position; import gregtech.api.util.Size; @@ -44,15 +44,23 @@ public class TankWidget extends Widget implements IIngredientSlot { private boolean allowClickFilling; private boolean allowClickEmptying; - private TextureArea[] backgroundTexture; - private TextureArea overlayTexture; + private IGuiTexture[] backgroundTexture; + private IGuiTexture overlayTexture; private FluidStack lastFluidInTank; private int lastTankCapacity; + private boolean isClient; public TankWidget(IFluidTank fluidTank, int x, int y, int width, int height) { super(new Position(x, y), new Size(width, height)); this.fluidTank = fluidTank; + this.lastFluidInTank = fluidTank != null ? fluidTank.getFluid() != null ? fluidTank.getFluid().copy() : null : null; + this.lastTankCapacity = fluidTank != null ? fluidTank.getCapacity() : 0; + } + + public TankWidget setClient() { + this.isClient = true; + return this; } public TankWidget setHideTooltip(boolean hideTooltip) { @@ -65,12 +73,12 @@ public TankWidget setAlwaysShowFull(boolean alwaysShowFull) { return this; } - public TankWidget setBackgroundTexture(TextureArea... backgroundTexture) { + public TankWidget setBackgroundTexture(IGuiTexture... backgroundTexture) { this.backgroundTexture = backgroundTexture; return this; } - public TankWidget setOverlayTexture(TextureArea overlayTexture) { + public TankWidget setOverlayTexture(IGuiTexture overlayTexture) { this.overlayTexture = overlayTexture; return this; } @@ -109,7 +117,7 @@ public void drawInBackground(int mouseX, int mouseY, IRenderContext context) { Position pos = getPosition(); Size size = getSize(); if (backgroundTexture != null) { - for (TextureArea textureArea : backgroundTexture) { + for (IGuiTexture textureArea : backgroundTexture) { textureArea.draw(pos.x, pos.y, size.width, size.height); } } @@ -173,6 +181,26 @@ public void drawInForeground(int mouseX, int mouseY) { } } + @Override + public void updateScreen() { + if (isClient) { + FluidStack fluidStack = fluidTank.getFluid(); + if (fluidTank.getCapacity() != lastTankCapacity) { + this.lastTankCapacity = fluidTank.getCapacity(); + } + if (fluidStack == null && lastFluidInTank != null) { + this.lastFluidInTank = null; + + } else if (fluidStack != null) { + if (!fluidStack.isFluidEqual(lastFluidInTank)) { + this.lastFluidInTank = fluidStack.copy(); + } else if (fluidStack.amount != lastFluidInTank.amount) { + this.lastFluidInTank.amount = fluidStack.amount; + } + } + } + } + @Override public void detectAndSendChanges() { FluidStack fluidStack = fluidTank.getFluid(); diff --git a/src/main/java/gregtech/api/gui/widgets/TextFieldWidget.java b/src/main/java/gregtech/api/gui/widgets/TextFieldWidget.java index 9264368b4ce..3ebf530ac18 100644 --- a/src/main/java/gregtech/api/gui/widgets/TextFieldWidget.java +++ b/src/main/java/gregtech/api/gui/widgets/TextFieldWidget.java @@ -2,12 +2,14 @@ import gregtech.api.gui.IRenderContext; import gregtech.api.gui.Widget; +import gregtech.api.gui.resources.IGuiTexture; import gregtech.api.util.MCGuiUtil; import gregtech.api.util.Position; import gregtech.api.util.Size; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.FontRenderer; import net.minecraft.client.gui.GuiTextField; +import net.minecraft.client.renderer.GlStateManager; import net.minecraft.network.PacketBuffer; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; @@ -23,15 +25,23 @@ public class TextFieldWidget extends Widget { protected int maxStringLength = 32; protected Predicate textValidator; - protected final Supplier textSupplier; - protected final Consumer textResponder; + protected Supplier textSupplier; + protected Consumer textResponder; protected String currentString; + private IGuiTexture background; + private boolean enableBackground; + private boolean isClient; public TextFieldWidget(int xPosition, int yPosition, int width, int height, boolean enableBackground, Supplier textSupplier, Consumer textResponder) { super(new Position(xPosition, yPosition), new Size(width, height)); if (isClientSide()) { + this.enableBackground = enableBackground; FontRenderer fontRenderer = Minecraft.getMinecraft().fontRenderer; - this.textField = new GuiTextField(0, fontRenderer, xPosition, yPosition, width, height); + if (enableBackground) { + this.textField = new GuiTextField(0, fontRenderer, xPosition, yPosition, width, height); + } else { + this.textField = new GuiTextField(0, fontRenderer, xPosition + 1, yPosition + (height - fontRenderer.FONT_HEIGHT) / 2 + 1, width - 2, height); + } this.textField.setCanLoseFocus(true); this.textField.setEnableBackgroundDrawing(enableBackground); this.textField.setMaxStringLength(this.maxStringLength); @@ -56,30 +66,84 @@ public TextFieldWidget(int xPosition, int yPosition, int width, int height, bool this.textResponder = textResponder; } + public TextFieldWidget(int xPosition, int yPosition, int width, int height, IGuiTexture background, Supplier textSupplier, Consumer textResponder) { + super(new Position(xPosition, yPosition), new Size(width, height)); + if (isClientSide()) { + this.enableBackground = false; + FontRenderer fontRenderer = Minecraft.getMinecraft().fontRenderer; + this.textField = new GuiTextField(0, fontRenderer, xPosition + 1, yPosition + (height - fontRenderer.FONT_HEIGHT) / 2 + 1, width - 2, height); + this.textField.setCanLoseFocus(true); + this.textField.setEnableBackgroundDrawing(false); + this.textField.setMaxStringLength(maxStringLength); + this.textField.setGuiResponder(MCGuiUtil.createTextFieldResponder(this::onTextChanged)); + } + this.background = background; + this.textSupplier = textSupplier; + this.textResponder = textResponder; + } + + public TextFieldWidget setTextSupplier(Supplier textSupplier, boolean isClient) { + this.isClient = isClient; + this.textSupplier = textSupplier; + return this; + } + + public TextFieldWidget setTextResponder(Consumer textResponder, boolean isClient) { + this.isClient = isClient; + this.textResponder = textResponder; + return this; + } + + public TextFieldWidget setCurrentString(String currentString) { + this.currentString = currentString; + this.textField.setText(currentString); + return this; + } + + public String getCurrentString() { + if (isRemote()) { + return this.textField.getText(); + } + return this.currentString; + } + @Override protected void onPositionUpdate() { if (isClientSide() && textField != null) { + FontRenderer fontRenderer = Minecraft.getMinecraft().fontRenderer; Position position = getPosition(); + Size size = getSize(); GuiTextField textField = this.textField; - textField.x = position.x; - textField.y = position.y; + textField.x = enableBackground ? position.x : position.x + 1; + textField.y = enableBackground ? position.y : position.y + (size.height - fontRenderer.FONT_HEIGHT) / 2 + 1; } } @Override protected void onSizeUpdate() { if (isClientSide() && textField != null) { + FontRenderer fontRenderer = Minecraft.getMinecraft().fontRenderer; + Position position = getPosition(); Size size = getSize(); GuiTextField textField = this.textField; - textField.width = size.width; + textField.width = enableBackground ? size.width : size.width - 2; textField.height = size.height; + textField.y = enableBackground ? position.y : position.y + (getSize().height - fontRenderer.FONT_HEIGHT) / 2 + 1; + } } @Override public void drawInBackground(int mouseX, int mouseY, IRenderContext context) { super.drawInBackground(mouseX, mouseY, context); + if (background != null) { + Position position = getPosition(); + Size size = getSize(); + background.draw(position.x, position.y, size.width, size.height); + } this.textField.drawTextBox(); + GlStateManager.enableBlend(); + GlStateManager.color(1,1,1,1); } @Override @@ -92,10 +156,18 @@ public boolean keyTyped(char charTyped, int keyCode) { return this.textField.textboxKeyTyped(charTyped, keyCode); } + @Override + public void updateScreen() { + if (textSupplier != null && isClient) { + this.currentString = textSupplier.get(); + this.textField.setText(currentString); + } + } + @Override public void detectAndSendChanges() { super.detectAndSendChanges(); - if (!textSupplier.get().equals(currentString)) { + if (textSupplier != null && !textSupplier.get().equals(currentString)) { this.currentString = textSupplier.get(); writeUpdateInfo(1, buffer -> buffer.writeString(currentString)); } @@ -112,6 +184,9 @@ public void readUpdateInfo(int id, PacketBuffer buffer) { protected void onTextChanged(String newTextString) { if (textValidator.test(newTextString)) { + if (isClient && textResponder != null) { + textResponder.accept(newTextString); + } writeClientAction(1, buffer -> buffer.writeString(newTextString)); } } @@ -124,7 +199,9 @@ public void handleClientAction(int id, PacketBuffer buffer) { clientText = clientText.substring(0, Math.min(clientText.length(), maxStringLength)); if (textValidator.test(clientText)) { this.currentString = clientText; - this.textResponder.accept(clientText); + if (textResponder != null) { + this.textResponder.accept(clientText); + } } } } diff --git a/src/main/java/gregtech/api/gui/widgets/TextFieldWidgetInfiniteEnergy.java b/src/main/java/gregtech/api/gui/widgets/TextFieldWidgetInfiniteEnergy.java deleted file mode 100644 index 74367199174..00000000000 --- a/src/main/java/gregtech/api/gui/widgets/TextFieldWidgetInfiniteEnergy.java +++ /dev/null @@ -1,61 +0,0 @@ -package gregtech.api.gui.widgets; - -import gregtech.common.metatileentities.electric.MetaTileEntityInfiniteEmitter; -import net.minecraft.client.Minecraft; -import net.minecraft.network.PacketBuffer; -import net.minecraftforge.fml.common.FMLCommonHandler; -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; -import org.lwjgl.input.Keyboard; - -public class TextFieldWidgetInfiniteEnergy extends TextFieldWidget { - private final MetaTileEntityInfiniteEmitter.InfiniteEnergyUIData data; - - public TextFieldWidgetInfiniteEnergy( - int xPosition, - int yPosition, - int width, - int height, - boolean enableBackground, - MetaTileEntityInfiniteEmitter.InfiniteEnergyUIData data) { - super(xPosition, yPosition, width, height, enableBackground, data::getEnergyText, data::setEnergyText); - this.data = data; - if (FMLCommonHandler.instance().getSide().isClient()) { - this.textField.setCanLoseFocus(false); - this.textField.setFocused(true); - } - } - - @Override - public void handleClientAction(int id, PacketBuffer buffer) { - super.handleClientAction(id, buffer); - if (id == 35) { - if (buffer.readBoolean()) data.markDirty(false); - this.gui.entityPlayer.closeScreen(); - } - } - - @Override - public boolean keyTyped(char charTyped, int keyCode) { - if (!super.keyTyped(charTyped, keyCode)) { - GuiCloseAction action = GuiCloseAction.getFromKey(keyCode); - if (action == GuiCloseAction.NONE) return false; - else writeClientAction(35, buffer -> buffer.writeBoolean(action == GuiCloseAction.CLOSE_WITHOUT_SAVE)); - } - return true; - } - - @SideOnly(Side.CLIENT) - private enum GuiCloseAction { - CLOSE, - CLOSE_WITHOUT_SAVE, - NONE; - - private static GuiCloseAction getFromKey(int keyCode) { - if (keyCode == Keyboard.KEY_RETURN) return CLOSE; - else if (keyCode == 1 || Minecraft.getMinecraft().gameSettings.keyBindInventory.isActiveAndMatches(keyCode)) - return CLOSE_WITHOUT_SAVE; - else return NONE; - } - } -} diff --git a/src/main/java/gregtech/api/gui/widgets/WidgetGroup.java b/src/main/java/gregtech/api/gui/widgets/WidgetGroup.java index 0bea41fee67..5bfef5d0d26 100644 --- a/src/main/java/gregtech/api/gui/widgets/WidgetGroup.java +++ b/src/main/java/gregtech/api/gui/widgets/WidgetGroup.java @@ -4,6 +4,8 @@ import gregtech.api.util.Position; import gregtech.api.util.Size; +import java.util.ArrayList; + public class WidgetGroup extends AbstractWidgetGroup { public WidgetGroup() { @@ -18,8 +20,27 @@ public WidgetGroup(Position position, Size size) { super(position, size); } + public WidgetGroup(int x, int y, int width, int height) { + super(new Position(x, y), new Size(width, height)); + } + @Override public void addWidget(Widget widget) { super.addWidget(widget); } + + @Override + public void removeWidget(Widget widget) { + super.removeWidget(widget); + } + + @Override + public void waitToRemoved(Widget widget) { + super.waitToRemoved(widget); + } + + @Override + public void clearAllWidgets() { + super.clearAllWidgets(); + } } diff --git a/src/main/java/gregtech/api/gui/widgets/tab/IGuiTextureTabInfo.java b/src/main/java/gregtech/api/gui/widgets/tab/IGuiTextureTabInfo.java new file mode 100644 index 00000000000..e254d652605 --- /dev/null +++ b/src/main/java/gregtech/api/gui/widgets/tab/IGuiTextureTabInfo.java @@ -0,0 +1,36 @@ +package gregtech.api.gui.widgets.tab; + +import com.google.common.collect.Lists; +import gregtech.api.gui.resources.IGuiTexture; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.ScaledResolution; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.resources.I18n; +import net.minecraftforge.fml.client.config.GuiUtils; + +import static gregtech.api.gui.impl.ModularUIGui.*; + +public class IGuiTextureTabInfo implements ITabInfo { + private final IGuiTexture texture; + private final String nameLocale; + + public IGuiTextureTabInfo(IGuiTexture texture, String nameLocale) { + this.texture = texture; + this.nameLocale = nameLocale; + } + + @Override + public void renderTab(IGuiTexture tabTexture, int posX, int posY, int xSize, int ySize, boolean isSelected) { + tabTexture.draw(posX, posY, xSize, ySize); + texture.draw(posX, posY, xSize, ySize); + GlStateManager.color(rColorForOverlay, gColorForOverlay, bColorForOverlay, 1.0F); + } + + @Override + public void renderHoverText(int posX, int posY, int xSize, int ySize, int guiWidth, int guiHeight, boolean isSelected, int mouseX, int mouseY) { + String localizedText = I18n.format(nameLocale); + Minecraft mc = Minecraft.getMinecraft(); + ScaledResolution resolution = new ScaledResolution(mc); + GuiUtils.drawHoveringText(Lists.newArrayList(localizedText), mouseX, mouseY, resolution.getScaledWidth(), resolution.getScaledHeight(), -1, mc.fontRenderer); + } +} diff --git a/src/main/java/gregtech/api/gui/widgets/tab/ITabInfo.java b/src/main/java/gregtech/api/gui/widgets/tab/ITabInfo.java index f5c7c961745..28fb8daace7 100644 --- a/src/main/java/gregtech/api/gui/widgets/tab/ITabInfo.java +++ b/src/main/java/gregtech/api/gui/widgets/tab/ITabInfo.java @@ -1,10 +1,10 @@ package gregtech.api.gui.widgets.tab; -import gregtech.api.gui.resources.TextureArea; +import gregtech.api.gui.resources.IGuiTexture; public interface ITabInfo { - void renderTab(TextureArea tabTexture, int posX, int posY, int xSize, int ySize, boolean isSelected); + void renderTab(IGuiTexture tabTexture, int posX, int posY, int xSize, int ySize, boolean isSelected); void renderHoverText(int posX, int posY, int xSize, int ySize, int guiWidth, int guiHeight, boolean isSelected, int mouseX, int mouseY); diff --git a/src/main/java/gregtech/api/gui/widgets/tab/ItemTabInfo.java b/src/main/java/gregtech/api/gui/widgets/tab/ItemTabInfo.java index 7d8266f1afa..d8ff74a3f4e 100644 --- a/src/main/java/gregtech/api/gui/widgets/tab/ItemTabInfo.java +++ b/src/main/java/gregtech/api/gui/widgets/tab/ItemTabInfo.java @@ -1,6 +1,7 @@ package gregtech.api.gui.widgets.tab; import com.google.common.collect.Lists; +import gregtech.api.gui.resources.IGuiTexture; import gregtech.api.gui.resources.TextureArea; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.ScaledResolution; @@ -23,7 +24,7 @@ public ItemTabInfo(String nameLocale, ItemStack iconStack) { } @Override - public void renderTab(TextureArea tabTexture, int posX, int posY, int xSize, int ySize, boolean isSelected) { + public void renderTab(IGuiTexture tabTexture, int posX, int posY, int xSize, int ySize, boolean isSelected) { tabTexture.draw(posX, posY, xSize, ySize); GlStateManager.enableRescaleNormal(); RenderHelper.enableGUIStandardItemLighting(); @@ -35,10 +36,12 @@ public void renderTab(TextureArea tabTexture, int posX, int posY, int xSize, int @Override public void renderHoverText(int posX, int posY, int xSize, int ySize, int guiWidth, int guiHeight, boolean isSelected, int mouseX, int mouseY) { - String localizedText = I18n.format(nameLocale); - Minecraft mc = Minecraft.getMinecraft(); - ScaledResolution resolution = new ScaledResolution(mc); - GuiUtils.drawHoveringText(Lists.newArrayList(localizedText), mouseX, mouseY, - resolution.getScaledWidth(), resolution.getScaledHeight(), -1, mc.fontRenderer); + if (nameLocale != null) { + String localizedText = I18n.format(nameLocale); + Minecraft mc = Minecraft.getMinecraft(); + ScaledResolution resolution = new ScaledResolution(mc); + GuiUtils.drawHoveringText(Lists.newArrayList(localizedText), mouseX, mouseY, + resolution.getScaledWidth(), resolution.getScaledHeight(), -1, mc.fontRenderer); + } } } diff --git a/src/main/java/gregtech/api/gui/widgets/tab/TabListRenderer.java b/src/main/java/gregtech/api/gui/widgets/tab/TabListRenderer.java index 381a7ea153f..55cd1ef8360 100644 --- a/src/main/java/gregtech/api/gui/widgets/tab/TabListRenderer.java +++ b/src/main/java/gregtech/api/gui/widgets/tab/TabListRenderer.java @@ -19,6 +19,6 @@ public abstract class TabListRenderer { public abstract void renderTabs(Position offset, List tabInfos, int guiWidth, int guiHeight, int selectedTabIndex); - public abstract int[] getTabPos(int guiWidth, int guiHeight, int tabIndex); + public abstract int[] getTabPos(int tabIndex, int guiWidth, int guiHeight); } diff --git a/src/main/java/gregtech/api/items/armor/ArmorHooks.java b/src/main/java/gregtech/api/items/armor/ArmorHooks.java new file mode 100644 index 00000000000..00c2f4b1ca6 --- /dev/null +++ b/src/main/java/gregtech/api/items/armor/ArmorHooks.java @@ -0,0 +1,22 @@ +package gregtech.api.items.armor; + +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.item.ItemStack; +import net.minecraft.util.DamageSource; +import net.minecraft.util.NonNullList; + +public class ArmorHooks { + + public static void damageArmor(float damage, EntityLivingBase entity, NonNullList inventory, DamageSource damageSource) { + double armorDamage = Math.max(1.0F, damage / 4.0F); + for (int i = 0; i < inventory.size(); i++) { + ItemStack itemStack = inventory.get(i); + if (itemStack.getItem() instanceof IArmorItem) { + ((IArmorItem) itemStack.getItem()).damageArmor(entity, itemStack, damageSource, (int) armorDamage, i); + if (inventory.get(i).getCount() == 0) { + inventory.set(i, ItemStack.EMPTY); + } + } + } + } +} diff --git a/src/main/java/gregtech/api/items/armor/ArmorMetaItem.java b/src/main/java/gregtech/api/items/armor/ArmorMetaItem.java new file mode 100644 index 00000000000..f459bc0e620 --- /dev/null +++ b/src/main/java/gregtech/api/items/armor/ArmorMetaItem.java @@ -0,0 +1,192 @@ +package gregtech.api.items.armor; + +import com.google.common.base.Preconditions; +import com.google.common.collect.Multimap; +import com.google.common.collect.Streams; +import gregtech.api.items.metaitem.MetaItem; +import gregtech.api.items.metaitem.stats.IEnchantabilityHelper; +import gregtech.api.items.metaitem.stats.IItemComponent; +import net.minecraft.client.gui.ScaledResolution; +import net.minecraft.client.model.ModelBiped; +import net.minecraft.enchantment.Enchantment; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.ai.attributes.AttributeModifier; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.Items; +import net.minecraft.inventory.EntityEquipmentSlot; +import net.minecraft.item.ItemStack; +import net.minecraft.util.DamageSource; +import net.minecraft.world.World; +import net.minecraftforge.common.ISpecialArmor; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public class ArmorMetaItem.ArmorMetaValueItem> extends MetaItem implements IArmorItem, ISpecialArmor, IEnchantabilityHelper { + + public ArmorMetaItem() { + super((short) 0); + } + + @SuppressWarnings("unchecked") + @Override + protected T constructMetaValueItem(short metaValue, String unlocalizedName) { + return (T) new ArmorMetaValueItem(metaValue, unlocalizedName); + } + + @Nonnull + private IArmorLogic getArmorLogic(ItemStack itemStack) { + T metaValueItem = getItem(itemStack); + return metaValueItem == null ? new DummyArmorLogic() : metaValueItem.getArmorLogic(); + } + + @Override + public Multimap getAttributeModifiers(EntityEquipmentSlot slot, ItemStack stack) { + Multimap multimap = super.getAttributeModifiers(slot, stack); + IArmorLogic armorLogic = getArmorLogic(stack); + multimap.putAll(armorLogic.getAttributeModifiers(slot, stack)); + return multimap; + } + + @Override + public ArmorProperties getProperties(EntityLivingBase player, @Nonnull ItemStack armor, DamageSource source, double damage, int slot) { + IArmorLogic armorLogic = getArmorLogic(armor); + if (armorLogic instanceof ISpecialArmorLogic) { + return ((ISpecialArmorLogic) armorLogic).getProperties(player, armor, source, damage, getSlotByIndex(slot)); + } + return new ArmorProperties(0, 0, Integer.MAX_VALUE); + } + + @Override + public int getArmorDisplay(EntityPlayer player, @Nonnull ItemStack armor, int slot) { + IArmorLogic armorLogic = getArmorLogic(armor); + if (armorLogic instanceof ISpecialArmorLogic) { + return ((ISpecialArmorLogic) armorLogic).getArmorDisplay(player, armor, slot); + } + return 0; + } + + @Override + public void damageArmor(EntityLivingBase entity, @Nonnull ItemStack stack, DamageSource source, int damage, int slot) { + IArmorLogic armorLogic = getArmorLogic(stack); + armorLogic.damageArmor(entity, stack, source, damage, getSlotByIndex(slot)); + } + + @Override + public boolean handleUnblockableDamage(EntityLivingBase entity, @Nonnull ItemStack armor, DamageSource source, double damage, int slot) { + IArmorLogic armorLogic = getArmorLogic(armor); + if (armorLogic instanceof ISpecialArmorLogic) { + return ((ISpecialArmorLogic) armorLogic).handleUnblockableDamage(entity, armor, source, damage, getSlotByIndex(slot)); + } + return false; + } + + @Override + public void onArmorTick(World world, EntityPlayer player, ItemStack itemStack) { + IArmorLogic armorLogic = getArmorLogic(itemStack); + armorLogic.onArmorTick(world, player, itemStack); + } + + @Override + public boolean isValidArmor(ItemStack stack, EntityEquipmentSlot armorType, Entity entity) { + IArmorLogic armorLogic = getArmorLogic(stack); + return super.isValidArmor(stack, armorType, entity) && + armorLogic.isValidArmor(stack, entity, armorType); + } + + @Nullable + @Override + public EntityEquipmentSlot getEquipmentSlot(ItemStack stack) { + IArmorLogic armorLogic = getArmorLogic(stack); + return armorLogic.getEquipmentSlot(stack); + } + + @Nullable + @Override + public String getArmorTexture(ItemStack stack, Entity entity, EntityEquipmentSlot slot, String type) { + IArmorLogic armorLogic = getArmorLogic(stack); + return armorLogic.getArmorTexture(stack, entity, slot, type); + } + + @Nullable + @Override + @SideOnly(Side.CLIENT) + public ModelBiped getArmorModel(EntityLivingBase entityLiving, ItemStack itemStack, EntityEquipmentSlot armorSlot, ModelBiped _default) { + IArmorLogic armorLogic = getArmorLogic(itemStack); + return armorLogic.getArmorModel(entityLiving, itemStack, armorSlot, _default); + } + + @Override + public int getArmorLayersAmount(ItemStack itemStack) { + IArmorLogic armorLogic = getArmorLogic(itemStack); + return armorLogic.getArmorLayersAmount(itemStack); + } + + @Override + public int getArmorLayerColor(ItemStack itemStack, int layerIndex) { + IArmorLogic armorLogic = getArmorLogic(itemStack); + return armorLogic.getArmorLayerColor(itemStack, layerIndex); + } + + @Override + public void renderHelmetOverlay(ItemStack stack, EntityPlayer player, ScaledResolution resolution, float partialTicks) { + IArmorLogic armorLogic = getArmorLogic(stack); + armorLogic.renderHelmetOverlay(stack, player, resolution, partialTicks); + } + + private static EntityEquipmentSlot getSlotByIndex(int index) { + switch (index) { + case 0: return EntityEquipmentSlot.FEET; + case 1: return EntityEquipmentSlot.LEGS; + case 2: return EntityEquipmentSlot.CHEST; + default: return EntityEquipmentSlot.HEAD; + } + } + + public class ArmorMetaValueItem extends MetaValueItem { + + private IArmorLogic armorLogic = new DummyArmorLogic(); + + protected ArmorMetaValueItem(int metaValue, String unlocalizedName) { + super(metaValue, unlocalizedName); + setMaxStackSize(1); + } + + @Nonnull + public IArmorLogic getArmorLogic() { + return armorLogic; + } + + public ArmorMetaValueItem setArmorLogic(IArmorLogic armorLogic) { + Preconditions.checkNotNull(armorLogic, "Cannot set armorLogic to null"); + this.armorLogic = armorLogic; + this.armorLogic.addToolComponents(this); + return this; + } + + + @Override + public ArmorMetaValueItem addComponents(IItemComponent... stats) { + super.addComponents(stats); + return this; + } + } + @Override + public boolean isEnchantable(ItemStack stack) { + return true; + } + + @Override + public int getItemEnchantability(ItemStack stack) { + + return 50; + } +//TODO add Enchantability list by armor type + @Override + public boolean canApplyAtEnchantingTable(ItemStack stack, Enchantment enchantment) { + return enchantment.isAllowedOnBooks(); + } +} diff --git a/src/main/java/gregtech/api/items/armor/ArmorRenderHooks.java b/src/main/java/gregtech/api/items/armor/ArmorRenderHooks.java new file mode 100644 index 00000000000..fe02f2871a1 --- /dev/null +++ b/src/main/java/gregtech/api/items/armor/ArmorRenderHooks.java @@ -0,0 +1,72 @@ +package gregtech.api.items.armor; + +import net.minecraft.client.model.ModelBase; +import net.minecraft.client.model.ModelBiped; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.GlStateManager.DestFactor; +import net.minecraft.client.renderer.GlStateManager.SourceFactor; +import net.minecraft.client.renderer.entity.layers.LayerArmorBase; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.inventory.EntityEquipmentSlot; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.client.ForgeHooksClient; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +@SideOnly(Side.CLIENT) +public class ArmorRenderHooks { + + public static boolean shouldNotRenderHeadItem(EntityLivingBase entityLivingBase) { + ItemStack itemStack = entityLivingBase.getItemStackFromSlot(EntityEquipmentSlot.HEAD); + return isArmorItem(itemStack, EntityEquipmentSlot.HEAD); + } + + public static boolean isArmorItem(ItemStack itemStack, EntityEquipmentSlot slot) { + return (itemStack.getItem() instanceof IArmorItem && itemStack.getItem().getEquipmentSlot(itemStack) == slot); + } + + public static void renderArmorLayer(LayerArmorBase layer, EntityLivingBase entity, float limbSwing, float limbSwingAmount, float partialTicks, float ageInTicks, float netHeadYaw, float headPitch, float scale, EntityEquipmentSlot slotIn) { + ItemStack itemStack = entity.getItemStackFromSlot(slotIn); + + if (isArmorItem(itemStack, slotIn)) { + IArmorItem armorItem = (IArmorItem) itemStack.getItem(); + ModelBase armorModel = layer.getModelFromSlot(slotIn); + if (armorModel instanceof ModelBiped) { + armorModel = ForgeHooksClient.getArmorModel(entity, itemStack, slotIn, (ModelBiped) armorModel); + } + armorModel.setModelAttributes(layer.renderer.getMainModel()); + armorModel.setLivingAnimations(entity, limbSwing, limbSwingAmount, partialTicks); + layer.setModelSlotVisible(armorModel, slotIn); + + GlStateManager.enableBlend(); + GlStateManager.blendFunc(SourceFactor.ONE, DestFactor.ONE_MINUS_SRC_ALPHA); + + int layers = armorItem.getArmorLayersAmount(itemStack); + for (int layerIndex = 0; layerIndex < layers; layerIndex++) { + int i = armorItem.getArmorLayerColor(itemStack, layerIndex); + float f = (float) (i >> 16 & 255) / 255.0F; + float f1 = (float) (i >> 8 & 255) / 255.0F; + float f2 = (float) (i & 255) / 255.0F; + GlStateManager.color(f, f1, f2, 1.0f); + String type = layerIndex == 0 ? null : "layer_" + layerIndex; + layer.renderer.bindTexture(getArmorTexture(entity, itemStack, slotIn, type)); + armorModel.render(entity, limbSwing, limbSwingAmount, ageInTicks, netHeadYaw, headPitch, scale); + } + if (itemStack.hasEffect()) { + LayerArmorBase.renderEnchantedGlint(layer.renderer, entity, armorModel, limbSwing, limbSwingAmount, partialTicks, ageInTicks, netHeadYaw, headPitch, scale); + } + } + } + + private static boolean isLegSlot(EntityEquipmentSlot equipmentSlot) { + return equipmentSlot == EntityEquipmentSlot.LEGS; + } + + private static ResourceLocation getArmorTexture(EntityLivingBase entity, ItemStack itemStack, EntityEquipmentSlot slot, String type) { + ResourceLocation registryName = itemStack.getItem().getRegistryName(); + String s1 = String.format("%s:textures/models/armor/%s_layer_%d%s.png", registryName.getNamespace(), registryName.getPath(), + (isLegSlot(slot) ? 2 : 1), type == null ? "" : String.format("_%s", type)); + return new ResourceLocation(ForgeHooksClient.getArmorTexture(entity, itemStack, s1, slot, type)); + } +} diff --git a/src/main/java/gregtech/api/items/armor/DummyArmorLogic.java b/src/main/java/gregtech/api/items/armor/DummyArmorLogic.java new file mode 100644 index 00000000000..e27f1c6cb7d --- /dev/null +++ b/src/main/java/gregtech/api/items/armor/DummyArmorLogic.java @@ -0,0 +1,36 @@ +package gregtech.api.items.armor; + +import com.google.common.collect.ImmutableMultimap; +import com.google.common.collect.Multimap; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.ai.attributes.AttributeModifier; +import net.minecraft.inventory.EntityEquipmentSlot; +import net.minecraft.item.ItemStack; +import net.minecraft.util.DamageSource; + +class DummyArmorLogic implements IArmorLogic { + @Override + public EntityEquipmentSlot getEquipmentSlot(ItemStack itemStack) { + return EntityEquipmentSlot.HEAD; + } + + @Override + public void damageArmor(EntityLivingBase entity, ItemStack itemStack, DamageSource source, int damage, EntityEquipmentSlot equipmentSlot) { + } + + @Override + public Multimap getAttributeModifiers(EntityEquipmentSlot slot, ItemStack stack) { + return ImmutableMultimap.of(); + } + + @Override + public boolean isValidArmor(ItemStack itemStack, Entity entity, EntityEquipmentSlot equipmentSlot) { + return false; + } + + @Override + public String getArmorTexture(ItemStack stack, Entity entity, EntityEquipmentSlot slot, String type) { + return "minecraft:textures/models/armor/diamond_layer_0.png"; + } +} diff --git a/src/main/java/gregtech/api/items/armor/IArmorItem.java b/src/main/java/gregtech/api/items/armor/IArmorItem.java new file mode 100644 index 00000000000..afde8b798d9 --- /dev/null +++ b/src/main/java/gregtech/api/items/armor/IArmorItem.java @@ -0,0 +1,18 @@ +package gregtech.api.items.armor; + +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.item.ItemStack; +import net.minecraft.util.DamageSource; + +public interface IArmorItem { + + default int getArmorLayersAmount(ItemStack itemStack) { + return 1; + } + + default int getArmorLayerColor(ItemStack itemStack, int layerIndex) { + return 0xFFFFFF; + } + + void damageArmor(EntityLivingBase entity, ItemStack itemStack, DamageSource source, int damage, int slot); +} diff --git a/src/main/java/gregtech/api/items/armor/IArmorLogic.java b/src/main/java/gregtech/api/items/armor/IArmorLogic.java new file mode 100644 index 00000000000..2da38860a94 --- /dev/null +++ b/src/main/java/gregtech/api/items/armor/IArmorLogic.java @@ -0,0 +1,65 @@ +package gregtech.api.items.armor; + +import com.google.common.collect.Multimap; +import gregtech.api.items.armor.ArmorMetaItem.ArmorMetaValueItem; +import net.minecraft.client.gui.ScaledResolution; +import net.minecraft.client.model.ModelBiped; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.ai.attributes.AttributeModifier; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.EntityEquipmentSlot; +import net.minecraft.item.ItemStack; +import net.minecraft.util.DamageSource; +import net.minecraft.world.World; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +import javax.annotation.Nullable; +import java.util.UUID; + +/** + * Defines abstract armor logic that can be added to ArmorMetaItem to control it + * It can implement {@link net.minecraftforge.common.ISpecialArmor} for extended damage calculations + * supported instead of using vanilla attributes + */ +public interface IArmorLogic { + + UUID ATTACK_DAMAGE_MODIFIER = UUID.fromString("CB3F55D3-645C-4F38-A144-9C13A33DB5CF"); + UUID ATTACK_SPEED_MODIFIER = UUID.fromString("FA233E1C-4180-4288-B05C-BCCE9785ACA3"); + + default void addToolComponents(ArmorMetaValueItem metaValueItem) { + } + + EntityEquipmentSlot getEquipmentSlot(ItemStack itemStack); + + void damageArmor(EntityLivingBase entity, ItemStack itemStack, DamageSource source, int damage, EntityEquipmentSlot equipmentSlot); + + Multimap getAttributeModifiers(EntityEquipmentSlot slot, ItemStack stack); + + default boolean isValidArmor(ItemStack itemStack, Entity entity, EntityEquipmentSlot equipmentSlot) { + return getEquipmentSlot(itemStack) == equipmentSlot; + } + + default void onArmorTick(World world, EntityPlayer player, ItemStack itemStack) { + } + + @SideOnly(Side.CLIENT) + default void renderHelmetOverlay(ItemStack itemStack, EntityPlayer player, ScaledResolution resolution, float partialTicks) { + } + + default int getArmorLayersAmount(ItemStack itemStack) { + return 1; + } + + default int getArmorLayerColor(ItemStack itemStack, int layerIndex) { + return 0xFFFFFF; + } + + String getArmorTexture(ItemStack stack, Entity entity, EntityEquipmentSlot slot, String type); + + @Nullable + default ModelBiped getArmorModel(EntityLivingBase entityLiving, ItemStack itemStack, EntityEquipmentSlot armorSlot, ModelBiped defaultModel) { + return null; + } +} diff --git a/src/main/java/gregtech/api/items/armor/ISpecialArmorLogic.java b/src/main/java/gregtech/api/items/armor/ISpecialArmorLogic.java new file mode 100644 index 00000000000..09c532ed8bb --- /dev/null +++ b/src/main/java/gregtech/api/items/armor/ISpecialArmorLogic.java @@ -0,0 +1,46 @@ +package gregtech.api.items.armor; + +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.EntityEquipmentSlot; +import net.minecraft.item.ItemStack; +import net.minecraft.util.DamageSource; +import net.minecraftforge.common.ISpecialArmor.ArmorProperties; + +import javax.annotation.Nonnull; + +/** + * Armor logic that wraps {@link net.minecraftforge.common.ISpecialArmor} methods + * to allow full control over damage absorption additionally to vanilla attribute values + */ +public interface ISpecialArmorLogic extends IArmorLogic { + + /** + * Retrieves the modifiers to be used when calculating armor damage. + * + * Armor will higher priority will have damage applied to them before + * lower priority ones. If there are multiple pieces of armor with the + * same priority, damage will be distributed between them based on there + * absorption ratio. + */ + ArmorProperties getProperties(EntityLivingBase player, @Nonnull ItemStack armor, DamageSource source, double damage, EntityEquipmentSlot equipmentSlot); + + /** + * Get the displayed effective armor. + * + * @return The number of armor points for display, 2 per shield. + */ + int getArmorDisplay(EntityPlayer player, @Nonnull ItemStack armor, int slot); + + /** + * Simple check to see if the armor should interact with "Unblockable" damage + * sources. A fair number of vanilla damage sources have this tag, such as + * Anvils, Falling, Fire, and Magic. + * + * Returning true here means that the armor is able to meaningfully respond + * to this damage source. Otherwise, no interaction is allowed. + */ + default boolean handleUnblockableDamage(EntityLivingBase entity, @Nonnull ItemStack armor, DamageSource source, double damage, EntityEquipmentSlot equipmentSlot) { + return false; + } +} diff --git a/src/main/java/gregtech/api/items/crafttweaker/CTItemRegistry.java b/src/main/java/gregtech/api/items/crafttweaker/CTItemRegistry.java new file mode 100644 index 00000000000..5f0df69e00d --- /dev/null +++ b/src/main/java/gregtech/api/items/crafttweaker/CTItemRegistry.java @@ -0,0 +1,20 @@ +package gregtech.api.items.crafttweaker; + +import crafttweaker.annotations.ZenRegister; +import gregtech.api.items.metaitem.MetaOreDictItem; +import gregtech.api.unification.material.info.MaterialIconSet; +import gregtech.api.unification.ore.OrePrefix; +import stanhebben.zenscript.annotations.ZenClass; +import stanhebben.zenscript.annotations.ZenMethod; + +@ZenClass("mods.gregtech.item.ItemRegistry") +@ZenRegister +@SuppressWarnings("unused") +public class CTItemRegistry { + + @ZenMethod("registerItem") + public static void registerItem(String name, short id, int rgb, String materialIconSet, String orePrefix) { + new MetaOreDictItem.OreDictValueItem( + id, name, rgb, MaterialIconSet.ICON_SETS.get(materialIconSet), OrePrefix.getPrefix(orePrefix)); + } +} diff --git a/src/main/java/gregtech/api/items/materialitem/MetaPrefixItem.java b/src/main/java/gregtech/api/items/materialitem/MetaPrefixItem.java index 83f9397c32e..f489f84e64c 100644 --- a/src/main/java/gregtech/api/items/materialitem/MetaPrefixItem.java +++ b/src/main/java/gregtech/api/items/materialitem/MetaPrefixItem.java @@ -71,15 +71,10 @@ public void registerOreDict() { } private void registerSpecialOreDict(ItemStack item, Material material, OrePrefix prefix) { + if (prefix.getAlternativeOreName() != null) { + OreDictUnifier.registerOre(item, prefix.getAlternativeOreName(), material); + } if (prefix.equals(OrePrefix.dust)) OreDictUnifier.registerOre(item, OrePrefix.DUST_REGULAR, material); - else if (prefix.equals(OrePrefix.oreChunk)) - OreDictUnifier.registerOre(item, OrePrefix.oreGravel.name(), material); - else if (prefix.equals(OrePrefix.oreEnderChunk)) - OreDictUnifier.registerOre(item, OrePrefix.oreEndstone.name(), material); - else if (prefix.equals(OrePrefix.oreNetherChunk)) - OreDictUnifier.registerOre(item, OrePrefix.oreNetherrack.name(), material); - else if (prefix.equals(OrePrefix.oreSandyChunk)) - OreDictUnifier.registerOre(item, OrePrefix.oreSand.name(), material); if (material == Materials.Plutonium239) { OreDictUnifier.registerOre(item, prefix.name() + material.toCamelCaseString() + "239"); @@ -97,7 +92,6 @@ protected boolean canGenerate(OrePrefix orePrefix, Material material) { } @Override - @SideOnly(Side.CLIENT) public String getItemStackDisplayName(ItemStack itemStack) { Material material = MaterialRegistry.MATERIAL_REGISTRY.getObjectById(itemStack.getItemDamage()); if (material == null || prefix == null) return ""; @@ -125,7 +119,7 @@ public void registerModels() { for (short metaItem : generatedItems) { MaterialIconSet materialIconSet = MaterialRegistry.MATERIAL_REGISTRY.getObjectById(metaItem).getMaterialIconSet(); - short registrationKey = (short) (prefix.id + materialIconSet.ordinal()); + short registrationKey = (short) (prefix.id + materialIconSet.id); if (!alreadyRegistered.containsKey(registrationKey)) { ResourceLocation resourceLocation = prefix.materialIconType.getItemModelPath(materialIconSet); ModelBakery.registerItemVariants(this, resourceLocation); diff --git a/src/main/java/gregtech/api/items/metaitem/ElectricStats.java b/src/main/java/gregtech/api/items/metaitem/ElectricStats.java index a22d268069d..d13d7104352 100644 --- a/src/main/java/gregtech/api/items/metaitem/ElectricStats.java +++ b/src/main/java/gregtech/api/items/metaitem/ElectricStats.java @@ -1,5 +1,6 @@ package gregtech.api.items.metaitem; +import gregtech.api.GTValues; import gregtech.api.capability.GregtechCapabilities; import gregtech.api.capability.IElectricItem; import gregtech.api.capability.impl.ElectricItem; @@ -20,6 +21,8 @@ import net.minecraft.world.World; import net.minecraftforge.common.capabilities.ICapabilityProvider; +import java.time.Duration; +import java.time.Instant; import java.util.List; public class ElectricStats implements IItemComponent, IItemCapabilityProvider, IItemMaxStackSizeProvider, IItemBehaviour { @@ -114,10 +117,31 @@ private static void setInDischargeMode(ItemStack itemStack, boolean isDischargeM public void addInformation(ItemStack itemStack, List lines) { IElectricItem electricItem = itemStack.getCapability(GregtechCapabilities.CAPABILITY_ELECTRIC_ITEM, null); if (electricItem != null && electricItem.canProvideChargeExternally()) { + addTotalChargeTooltip(lines, electricItem.getMaxCharge(), electricItem.getTier()); lines.add(I18n.format("metaitem.electric.discharge_mode.tooltip")); } } + private static void addTotalChargeTooltip(List tooltip, long maxCharge, int tier) { + Instant start = Instant.now(); + Instant end = Instant.now().plusSeconds((long) ((maxCharge * 1.0) / GTValues.V[tier] / 20)); + Duration duration = Duration.between(start, end); + + long chargeTime; + String unit; + if (duration.getSeconds() <= 180) { + chargeTime = duration.getSeconds(); + unit = "sec"; + } else if (duration.toMinutes() <= 180) { + chargeTime = duration.toMinutes(); + unit = "min"; + } else { + chargeTime = duration.toHours(); + unit = "hr"; + } + tooltip.add(I18n.format("metaitem.battery.charge_time", chargeTime, unit, GTValues.VN[tier])); + } + private static boolean isInDischargeMode(ItemStack itemStack) { NBTTagCompound tagCompound = itemStack.getTagCompound(); return tagCompound != null && tagCompound.getBoolean("DischargeMode"); diff --git a/src/main/java/gregtech/api/items/metaitem/MetaItem.java b/src/main/java/gregtech/api/items/metaitem/MetaItem.java index 24f989f3058..9cc951dbf7a 100644 --- a/src/main/java/gregtech/api/items/metaitem/MetaItem.java +++ b/src/main/java/gregtech/api/items/metaitem/MetaItem.java @@ -22,6 +22,7 @@ import gregtech.api.unification.material.Material; import gregtech.api.unification.ore.OrePrefix; import gregtech.api.unification.stack.ItemMaterialInfo; +import gregtech.api.util.LocalizationUtils; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.block.model.ModelBakery; import net.minecraft.client.renderer.block.model.ModelResourceLocation; @@ -57,6 +58,8 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; +import java.time.Duration; +import java.time.Instant; import java.util.*; /** @@ -71,7 +74,6 @@ * {@code addItem(0, "test_item").addStats(new ElectricStats(10000, 1, false)) } * This will add single-use (not rechargeable) LV battery with initial capacity 10000 EU */ -@SuppressWarnings("deprecation") public abstract class MetaItem.MetaValueItem> extends Item implements ItemUIFactory { private static final List> META_ITEMS = new ArrayList<>(); @@ -486,7 +488,6 @@ public boolean shouldCauseReequipAnimation(@Nonnull ItemStack oldStack, @Nonnull @Nonnull @Override - @SideOnly(Side.CLIENT) public String getItemStackDisplayName(ItemStack stack) { if (stack.getItemDamage() >= metaItemOffset) { T item = getItem(stack); @@ -501,9 +502,11 @@ public String getItemStackDisplayName(ItemStack stack) { .getCapability(CapabilityFluidHandler.FLUID_HANDLER_ITEM_CAPABILITY, null); if (fluidHandlerItem != null) { FluidStack fluidInside = fluidHandlerItem.drain(Integer.MAX_VALUE, false); - return I18n.format(unlocalizedName, fluidInside == null ? I18n.format("metaitem.fluid_cell.empty") : fluidInside.getLocalizedName()); + return LocalizationUtils.format(unlocalizedName, fluidInside == null ? + LocalizationUtils.format("metaitem.fluid_cell.empty") : + fluidInside.getLocalizedName()); } - return I18n.format(unlocalizedName); + return LocalizationUtils.format(unlocalizedName); } return super.getItemStackDisplayName(stack); } @@ -520,10 +523,14 @@ public void addInformation(@Nonnull ItemStack itemStack, @Nullable World worldIn IElectricItem electricItem = itemStack.getCapability(GregtechCapabilities.CAPABILITY_ELECTRIC_ITEM, null); if (electricItem != null) { - lines.add(I18n.format("metaitem.generic.electric_item.tooltip", - electricItem.getCharge(), - electricItem.getMaxCharge(), - GTValues.VN[electricItem.getTier()])); + if (electricItem.canProvideChargeExternally()) { + addDischargeItemTooltip(lines, electricItem.getMaxCharge(), electricItem.getCharge(), electricItem.getTier()); + } else { + lines.add(I18n.format("metaitem.generic.electric_item.tooltip", + electricItem.getCharge(), + electricItem.getMaxCharge(), + GTValues.VN[electricItem.getTier()])); + } } IFluidHandlerItem fluidHandler = ItemHandlerHelper.copyStackWithSize(itemStack, 1) @@ -544,6 +551,33 @@ public void addInformation(@Nonnull ItemStack itemStack, @Nullable World worldIn } } + private static void addDischargeItemTooltip(List tooltip, long maxCharge, long currentCharge, int tier) { + if (currentCharge == 0) { // do not display when empty + tooltip.add(I18n.format("metaitem.generic.electric_item.tooltip", currentCharge, maxCharge, GTValues.VN[tier])); + return; + } + Instant start = Instant.now(); + Instant end = Instant.now().plusSeconds((long)((currentCharge * 1.0) / GTValues.V[tier] / 20)); + Duration duration = Duration.between(start, end); + double percentRemaining = currentCharge * 1.0 / maxCharge * 100; // used for color + + long timeRemaining; + String unit; + if (duration.getSeconds() <= 180) { + timeRemaining = duration.getSeconds(); + unit = "sec"; + } else if (duration.toMinutes() <= 180) { + timeRemaining = duration.toMinutes(); + unit = "min"; + } else { + timeRemaining = duration.toHours(); + unit = "hr"; + } + tooltip.add(I18n.format("metaitem.battery.charge_detailed", currentCharge, maxCharge, GTValues.VN[tier], + percentRemaining < 30 ? 'c' : percentRemaining < 60 ? 'e' : 'a', + timeRemaining, unit)); + } + @Override public boolean hasContainerItem(@Nonnull ItemStack itemStack) { T item = getItem(itemStack); diff --git a/src/main/java/gregtech/api/items/metaitem/MetaOreDictItem.java b/src/main/java/gregtech/api/items/metaitem/MetaOreDictItem.java new file mode 100644 index 00000000000..10f92969624 --- /dev/null +++ b/src/main/java/gregtech/api/items/metaitem/MetaOreDictItem.java @@ -0,0 +1,109 @@ +package gregtech.api.items.metaitem; + +import com.google.common.base.CaseFormat; +import com.google.common.collect.ImmutableList; +import gnu.trove.map.hash.TIntObjectHashMap; +import gregtech.api.unification.OreDictUnifier; +import gregtech.api.unification.material.info.MaterialIconSet; +import gregtech.api.unification.material.info.MaterialIconType; +import gregtech.api.unification.ore.OrePrefix; +import net.minecraft.client.renderer.block.model.ModelBakery; +import net.minecraft.client.renderer.block.model.ModelResourceLocation; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class MetaOreDictItem extends StandardMetaItem { + + private static final Map ITEMS = new HashMap<>(); + private static final List DISALLOWED_TYPES = ImmutableList.of( + MaterialIconType.block, MaterialIconType.foilBlock, MaterialIconType.wire, + MaterialIconType.ore, MaterialIconType.frameGt, MaterialIconType.pipeHuge, + MaterialIconType.pipeLarge, MaterialIconType.pipeSide, MaterialIconType.pipeSmall, + MaterialIconType.pipeMedium, MaterialIconType.pipeTiny); + + public MetaOreDictItem(short metaItemOffset) { + super(metaItemOffset); + } + + @Override + public void registerSubItems() { + for (OreDictValueItem item : ITEMS.values()) { + addItem(item.id, item.getName()); + OreDictUnifier.registerOre(new ItemStack(this, 1, item.id), item.getOre()); + } + } + + @Override + @SideOnly(Side.CLIENT) + protected int getColorForItemStack(ItemStack stack, int tintIndex) { + if (tintIndex == 0) { + OreDictValueItem item = ITEMS.get((short) stack.getItemDamage()); + return item == null ? 0xFFFFFF : item.materialRGB; + } + return super.getColorForItemStack(stack, tintIndex); + } + + @Override + @SideOnly(Side.CLIENT) + public void registerModels() { + super.registerModels(); + TIntObjectHashMap alreadyRegistered = new TIntObjectHashMap<>(); + for (Map.Entry metaItem : ITEMS.entrySet()) { + OrePrefix prefix = metaItem.getValue().orePrefix; + MaterialIconSet materialIconSet = metaItem.getValue().materialIconSet; + if (prefix.materialIconType == null || DISALLOWED_TYPES.contains(prefix.materialIconType)) + continue; + int registrationKey = prefix.id * 1000 + materialIconSet.id; + if (!alreadyRegistered.containsKey(registrationKey)) { + prefix.materialIconType.getItemModelPath(materialIconSet); + ResourceLocation resourceLocation = prefix.materialIconType.getItemModelPath(materialIconSet); + ModelBakery.registerItemVariants(this, resourceLocation); + alreadyRegistered.put(registrationKey, new ModelResourceLocation(resourceLocation, "inventory")); + } + ModelResourceLocation resourceLocation = alreadyRegistered.get(registrationKey); + metaItemsModels.put(metaItem.getKey(), resourceLocation); + } + } + + public static class OreDictValueItem { + + private final String materialName; + private final int materialRGB; + private final MaterialIconSet materialIconSet; + private final short id; + private final OrePrefix orePrefix; + + public OreDictValueItem(short id, String materialName, int materialRGB, MaterialIconSet materialIconSet, OrePrefix orePrefix) { + this.id = id; + this.materialName = materialName; + this.materialRGB = materialRGB; + this.materialIconSet = materialIconSet; + this.orePrefix = orePrefix; + ITEMS.put(id, this); + } + + public String getOre() { + return orePrefix.name() + CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, materialName); + } + + public ItemStack getItemStack(int amount) { + ItemStack stack = OreDictUnifier.get(getOre()); + stack.setCount(amount); + return stack; + } + + public ItemStack getItemStack() { + return getItemStack(1); + } + + public String getName() { + return materialName + '_' + CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, orePrefix.name()); + } + } +} diff --git a/src/main/java/gregtech/api/items/toolitem/ToolMetaItem.java b/src/main/java/gregtech/api/items/toolitem/ToolMetaItem.java index 8837f57839e..5857bbbf32c 100755 --- a/src/main/java/gregtech/api/items/toolitem/ToolMetaItem.java +++ b/src/main/java/gregtech/api/items/toolitem/ToolMetaItem.java @@ -20,12 +20,12 @@ import gregtech.api.unification.material.Material; import gregtech.api.unification.material.MaterialRegistry; import gregtech.api.unification.material.Materials; -import gregtech.api.unification.material.info.MaterialIconSet; import gregtech.api.unification.material.properties.DustProperty; import gregtech.api.unification.material.properties.PropertyKey; import gregtech.api.unification.material.properties.ToolProperty; import gregtech.api.util.GTLog; import gregtech.api.util.GTUtility; +import gregtech.api.util.LocalizationUtils; import gregtech.common.ConfigHolder; import gregtech.common.tools.DamageValues; import gregtech.common.tools.ToolWrench; @@ -423,7 +423,6 @@ public ICapabilityProvider initCapabilities(ItemStack stack, @Nullable NBTTagCom } @Override - @SideOnly(Side.CLIENT) public String getItemStackDisplayName(ItemStack stack) { if (stack.getItemDamage() >= metaItemOffset) { T item = getItem(stack); @@ -432,7 +431,7 @@ public String getItemStackDisplayName(ItemStack stack) { } Material primaryMaterial = getToolMaterial(stack); String materialName = primaryMaterial == null ? "" : String.valueOf(primaryMaterial.getLocalizedName()); - return I18n.format("metaitem." + item.unlocalizedName + ".name", materialName); + return LocalizationUtils.format("metaitem." + item.unlocalizedName + ".name", materialName); } return super.getItemStackDisplayName(stack); } @@ -464,8 +463,7 @@ public boolean isEnchantable(ItemStack stack) { @Override public int getItemEnchantability(ItemStack stack) { - Material primaryMaterial = getToolMaterial(stack); - return getMaterialEnchantability(primaryMaterial); + return getToolMaterial(stack).getProperty(PropertyKey.TOOL).toolEnchantability; } @Override @@ -477,27 +475,6 @@ public boolean canApplyAtEnchantingTable(ItemStack stack, Enchantment enchantmen return false; } - public static int getMaterialEnchantability(Material material) { - if (material.getMaterialIconSet() == MaterialIconSet.SHINY || - material.getMaterialIconSet() == MaterialIconSet.RUBY) { - return 33; //all shiny metals have gold enchantability - } else if (material.getMaterialIconSet() == MaterialIconSet.DULL || - material.getMaterialIconSet() == MaterialIconSet.METALLIC) { - return 21; //dull metals have iron enchantability - } else if (material.getMaterialIconSet() == MaterialIconSet.GEM_VERTICAL || - material.getMaterialIconSet() == MaterialIconSet.GEM_HORIZONTAL || - material.getMaterialIconSet() == MaterialIconSet.DIAMOND || - material.getMaterialIconSet() == MaterialIconSet.OPAL || - material.getMaterialIconSet() == MaterialIconSet.NETHERSTAR) { - return 15; //standard gems have diamond enchantability - } else if (material.getMaterialIconSet() == MaterialIconSet.WOOD || - material.getMaterialIconSet() == MaterialIconSet.ROUGH || - material.getMaterialIconSet() == MaterialIconSet.FINE) { - return 11; //wood and stone has their default enchantability - } - return 10; //otherwise return lowest enchantability - } - @Override public int getMaxItemDamage(ItemStack itemStack) { T metaToolValueItem = getItem(itemStack); diff --git a/src/main/java/gregtech/api/metatileentity/InfiniteEnergyTileEntityBase.java b/src/main/java/gregtech/api/metatileentity/InfiniteEnergyTileEntityBase.java deleted file mode 100644 index 200c28fc64d..00000000000 --- a/src/main/java/gregtech/api/metatileentity/InfiniteEnergyTileEntityBase.java +++ /dev/null @@ -1,64 +0,0 @@ -package gregtech.api.metatileentity; - -import codechicken.lib.raytracer.CuboidRayTraceResult; -import codechicken.lib.render.CCRenderState; -import codechicken.lib.render.pipeline.IVertexOperation; -import codechicken.lib.vec.Matrix4; -import gregtech.api.GTValues; -import gregtech.api.render.SimpleOverlayRenderer; -import gregtech.api.render.SimpleSidedCubeRenderer; -import gregtech.api.render.Textures; -import gregtech.common.metatileentities.traits.TraitInfiniteEnergy; -import net.minecraft.client.renderer.texture.TextureAtlasSprite; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.util.EnumFacing; -import net.minecraft.util.EnumHand; -import net.minecraft.util.ResourceLocation; -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; -import org.apache.commons.lang3.tuple.Pair; - -import java.text.DateFormat; -import java.text.SimpleDateFormat; - -public abstract class InfiniteEnergyTileEntityBase extends MetaTileEntity { - private static final DateFormat DATE_FORMAT = new SimpleDateFormat("yyyy_MM_dd_HH_mm_ss"); - - protected final TRAIT trait; - - public InfiniteEnergyTileEntityBase(ResourceLocation metaTileEntityId) { - super(metaTileEntityId); - trait = createTrait(); - } - - protected abstract TRAIT createTrait(); - - @Override - public void renderMetaTileEntity(CCRenderState renderState, Matrix4 translation, IVertexOperation[] pipeline) { - Textures.VOLTAGE_CASINGS[GTValues.MAX].render(renderState, translation, pipeline); - for (EnumFacing facing : EnumFacing.VALUES) - getOverlay().renderSided(facing, renderState, translation, pipeline); - } - - @Override - public boolean onWrenchClick(EntityPlayer player, EnumHand hand, EnumFacing wrenchSide, CuboidRayTraceResult hitResult) { - if (!player.isCreative() || player.isSneaking()) - return super.onWrenchClick(player, hand, wrenchSide, hitResult); - return true; - } - - @Override - public void update() { - super.update(); - } - - - @SideOnly(Side.CLIENT) - protected abstract SimpleOverlayRenderer getOverlay(); - - @Override - @SideOnly(Side.CLIENT) - public Pair getParticleTexture() { - return Pair.of(Textures.VOLTAGE_CASINGS[GTValues.MAX].getSpriteOnSide(SimpleSidedCubeRenderer.RenderSide.TOP), 0xFFFFFF); - } -} diff --git a/src/main/java/gregtech/api/metatileentity/MetaTileEntity.java b/src/main/java/gregtech/api/metatileentity/MetaTileEntity.java index 1a0ca0eb6dc..6809093e3b2 100644 --- a/src/main/java/gregtech/api/metatileentity/MetaTileEntity.java +++ b/src/main/java/gregtech/api/metatileentity/MetaTileEntity.java @@ -12,9 +12,7 @@ import gregtech.api.GregTechAPI; import gregtech.api.capability.GregtechTileCapabilities; import gregtech.api.capability.IEnergyContainer; -import gregtech.api.capability.impl.FluidHandlerProxy; -import gregtech.api.capability.impl.FluidTankList; -import gregtech.api.capability.impl.ItemHandlerProxy; +import gregtech.api.capability.impl.*; import gregtech.api.cover.CoverBehavior; import gregtech.api.cover.CoverDefinition; import gregtech.api.cover.ICoverable; @@ -43,6 +41,7 @@ import net.minecraftforge.common.util.Constants.NBT; import net.minecraftforge.fluids.FluidActionResult; import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.FluidTank; import net.minecraftforge.fluids.FluidUtil; import net.minecraftforge.fluids.capability.CapabilityFluidHandler; import net.minecraftforge.fluids.capability.IFluidHandler; @@ -53,8 +52,7 @@ import org.apache.commons.lang3.tuple.Pair; import javax.annotation.Nullable; -import java.util.ArrayList; -import java.util.List; +import java.util.*; import java.util.function.Consumer; import static gregtech.api.util.InventoryUtils.simulateItemStackMerge; @@ -91,6 +89,10 @@ public abstract class MetaTileEntity implements ICoverable { protected boolean isFragile = false; private final CoverBehavior[] coverBehaviors = new CoverBehavior[6]; + protected List notifiedItemOutputList = new ArrayList<>(); + protected List notifiedItemInputList = new ArrayList<>(); + protected List notifiedFluidInputList = new ArrayList<>(); + protected List notifiedFluidOutputList = new ArrayList<>(); public MetaTileEntity(ResourceLocation metaTileEntityId) { this.metaTileEntityId = metaTileEntityId; @@ -250,6 +252,30 @@ public final String getMetaFullName() { return getMetaName() + ".name"; } + public void addNotifiedInput(T input) { + if (input instanceof IItemHandlerModifiable) { + if (!notifiedItemInputList.contains(input)) { + this.notifiedItemInputList.add((IItemHandlerModifiable) input); + } + } else if (input instanceof FluidTank) { + if (!notifiedFluidInputList.contains(input)) { + this.notifiedFluidInputList.add((FluidTank) input); + } + } + } + + public void addNotifiedOutput(T output) { + if (output instanceof IItemHandlerModifiable) { + if (!notifiedItemOutputList.contains(output)) { + this.notifiedItemOutputList.add((IItemHandlerModifiable) output); + } + } else if (output instanceof NotifiableFluidTank) { + if (!notifiedFluidOutputList.contains(output)) { + this.notifiedFluidOutputList.add((NotifiableFluidTank) output); + } + } + } + /** * Adds a trait to this meta tile entity * traits are objects linked with meta tile entity and performing certain @@ -1206,6 +1232,22 @@ public FluidTankList getExportFluids() { return exportFluids; } + public List getNotifiedItemOutputList() { + return notifiedItemOutputList; + } + + public List getNotifiedItemInputList() { + return notifiedItemInputList; + } + + public List getNotifiedFluidInputList() { + return notifiedFluidInputList; + } + + public List getNotifiedFluidOutputList() { + return notifiedFluidOutputList; + } + public boolean isFragile() { return isFragile; } diff --git a/src/main/java/gregtech/api/metatileentity/MetaTileEntityHolder.java b/src/main/java/gregtech/api/metatileentity/MetaTileEntityHolder.java index ad29f206306..014ac24481d 100644 --- a/src/main/java/gregtech/api/metatileentity/MetaTileEntityHolder.java +++ b/src/main/java/gregtech/api/metatileentity/MetaTileEntityHolder.java @@ -6,10 +6,8 @@ import gregtech.api.block.machines.BlockMachine; import gregtech.api.cover.CoverBehavior; import gregtech.api.gui.IUIHolder; -import gregtech.api.util.FirstTickScheduler; import gregtech.api.util.GTControlledRegistry; import gregtech.api.util.GTLog; -import gregtech.api.util.IFirstTickTask; import net.minecraft.block.state.IBlockState; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.network.PacketBuffer; @@ -28,7 +26,7 @@ import java.util.List; import java.util.stream.Collectors; -public class MetaTileEntityHolder extends TickableTileEntityBase implements IUIHolder, IFirstTickTask { +public class MetaTileEntityHolder extends TickableTileEntityBase implements IUIHolder { private MetaTileEntity metaTileEntity; private boolean needToUpdateLightning = false; @@ -224,14 +222,7 @@ public void markAsDirty() { public void onLoad() { super.onLoad(); if (metaTileEntity != null) { - FirstTickScheduler.addTask(this); - } - } - - @Override - public void handleFirstTick() { - if (this.metaTileEntity != null) { - this.metaTileEntity.onLoad(); + metaTileEntity.onLoad(); } } diff --git a/src/main/java/gregtech/api/metatileentity/WorkableTieredMetaTileEntity.java b/src/main/java/gregtech/api/metatileentity/WorkableTieredMetaTileEntity.java index a6f507c7164..e72cf5f5726 100644 --- a/src/main/java/gregtech/api/metatileentity/WorkableTieredMetaTileEntity.java +++ b/src/main/java/gregtech/api/metatileentity/WorkableTieredMetaTileEntity.java @@ -4,9 +4,7 @@ import codechicken.lib.render.pipeline.IVertexOperation; import codechicken.lib.vec.Matrix4; import gregtech.api.GTValues; -import gregtech.api.capability.impl.FilteredFluidHandler; -import gregtech.api.capability.impl.FluidTankList; -import gregtech.api.capability.impl.RecipeLogicEnergy; +import gregtech.api.capability.impl.*; import gregtech.api.recipes.Recipe; import gregtech.api.recipes.RecipeMap; import gregtech.api.render.OrientedOverlayRenderer; @@ -42,6 +40,23 @@ protected RecipeLogicEnergy createWorkable(RecipeMap recipeMap) { return new RecipeLogicEnergy(this, recipeMap, () -> energyContainer); } + @Override + protected void reinitializeEnergyContainer() { + long tierVoltage = GTValues.V[getTier()]; + if (isEnergyEmitter()) { + this.energyContainer = EnergyContainerHandler.emitterContainer(this, + tierVoltage * 64L, tierVoltage, getMaxInputOutputAmperage()); + } else this.energyContainer = new EnergyContainerHandler(this, tierVoltage * 64L, tierVoltage, 2, 0L, 0L) { + @Override + public long getInputAmperage() { + if(getEnergyCapacity() / 2 > getEnergyStored() && workable.isActive()) { + return 2; + } + return 1; + } + }; + } + @Override protected long getMaxInputOutputAmperage() { return 2L; @@ -56,13 +71,13 @@ public void renderMetaTileEntity(CCRenderState renderState, Matrix4 translation, @Override protected IItemHandlerModifiable createImportItemHandler() { if (workable == null) return new ItemStackHandler(0); - return new ItemStackHandler(workable.recipeMap.getMaxInputs()); + return new NotifiableItemStackHandler(workable.recipeMap.getMaxInputs(), this, false); } @Override protected IItemHandlerModifiable createExportItemHandler() { if (workable == null) return new ItemStackHandler(0); - return new ItemStackHandler(workable.recipeMap.getMaxOutputs()); + return new NotifiableItemStackHandler(workable.recipeMap.getMaxOutputs(), this, true); } @Override @@ -70,7 +85,7 @@ protected FluidTankList createImportFluidHandler() { if (workable == null) return new FluidTankList(false); FilteredFluidHandler[] fluidImports = new FilteredFluidHandler[workable.recipeMap.getMaxFluidInputs()]; for (int i = 0; i < fluidImports.length; i++) { - FilteredFluidHandler filteredFluidHandler = new FilteredFluidHandler(getInputTankCapacity(i)); + NotifiableFilteredFluidHandler filteredFluidHandler = new NotifiableFilteredFluidHandler(getInputTankCapacity(i), this, false); filteredFluidHandler.setFillPredicate(this::canInputFluid); fluidImports[i] = filteredFluidHandler; } @@ -82,7 +97,7 @@ protected FluidTankList createExportFluidHandler() { if (workable == null) return new FluidTankList(false); FluidTank[] fluidExports = new FluidTank[workable.recipeMap.getMaxFluidOutputs()]; for (int i = 0; i < fluidExports.length; i++) { - fluidExports[i] = new FluidTank(getOutputTankCapacity(i)); + fluidExports[i] = new NotifiableFluidTank(getOutputTankCapacity(i), this, true); } return new FluidTankList(false, fluidExports); } diff --git a/src/main/java/gregtech/api/metatileentity/multiblock/IMultiblockPart.java b/src/main/java/gregtech/api/metatileentity/multiblock/IMultiblockPart.java index ca3213547fe..1d343bbb68d 100644 --- a/src/main/java/gregtech/api/metatileentity/multiblock/IMultiblockPart.java +++ b/src/main/java/gregtech/api/metatileentity/multiblock/IMultiblockPart.java @@ -1,5 +1,7 @@ package gregtech.api.metatileentity.multiblock; +import gregtech.api.metatileentity.MetaTileEntity; + public interface IMultiblockPart { boolean isAttachedToMultiBlock(); @@ -8,4 +10,7 @@ public interface IMultiblockPart { void removeFromMultiBlock(MultiblockControllerBase controllerBase); + default void setupNotifiableMetaTileEntity(MetaTileEntity metaTileEntity) { + } + } diff --git a/src/main/java/gregtech/api/metatileentity/multiblock/MultiblockControllerBase.java b/src/main/java/gregtech/api/metatileentity/multiblock/MultiblockControllerBase.java index e7e54ad0176..0238c023354 100644 --- a/src/main/java/gregtech/api/metatileentity/multiblock/MultiblockControllerBase.java +++ b/src/main/java/gregtech/api/metatileentity/multiblock/MultiblockControllerBase.java @@ -26,6 +26,7 @@ import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumFacing; import net.minecraft.util.ResourceLocation; +import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import net.minecraftforge.common.capabilities.Capability; import org.apache.commons.lang3.ArrayUtils; @@ -35,6 +36,7 @@ import javax.annotation.Nullable; import java.util.*; import java.util.function.BiFunction; +import java.util.function.Function; import java.util.function.Predicate; public abstract class MultiblockControllerBase extends MetaTileEntity implements IMultiblockController { @@ -170,14 +172,18 @@ public Pair getParticleTexture() { } /** - * if true allows all hatches to share but energy hatches and rotor holders - * defualt true - * - * @return + * Override to disable MultiblockPart sharing for this Multiblock. (Rotor Holders always disallowed). */ public boolean canShare() { return true; + } + /** + * Used if MultiblockPart Abilities need to be sorted a certain way, like + * Distillation Tower and Assembly Line. + */ + protected Function multiblockPartSorter() { + return BlockPos::hashCode; } protected void checkStructurePattern() { @@ -186,7 +192,7 @@ protected void checkStructurePattern() { if (context != null && !structureFormed) { Set rawPartsSet = context.getOrCreate("MultiblockParts", HashSet::new); ArrayList parts = new ArrayList<>(rawPartsSet); - parts.sort(Comparator.comparing(it -> ((MetaTileEntity) it).getPos().hashCode())); + parts.sort(Comparator.comparing(it -> multiblockPartSorter().apply(((MetaTileEntity) it).getPos()))); for (IMultiblockPart part : parts) { if (part.isAttachedToMultiBlock()) { if (!canShare() || part instanceof MetaTileEntityRotorHolder) { @@ -204,6 +210,7 @@ protected void checkStructurePattern() { } if (checkStructureComponents(parts, abilities)) { parts.forEach(part -> part.addToMultiBlock(this)); + parts.forEach(part -> part.setupNotifiableMetaTileEntity(this)); this.multiblockParts.addAll(parts); this.multiblockAbilities.putAll(abilities); this.structureFormed = true; diff --git a/src/main/java/gregtech/api/metatileentity/multiblock/RecipeMapPrimitiveMultiblockController.java b/src/main/java/gregtech/api/metatileentity/multiblock/RecipeMapPrimitiveMultiblockController.java new file mode 100644 index 00000000000..75e13f4e469 --- /dev/null +++ b/src/main/java/gregtech/api/metatileentity/multiblock/RecipeMapPrimitiveMultiblockController.java @@ -0,0 +1,50 @@ +package gregtech.api.metatileentity.multiblock; + +import gregtech.api.capability.impl.*; +import gregtech.api.recipes.RecipeMap; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.fluids.FluidTank; + +import java.util.ArrayList; +import java.util.List; + +public abstract class RecipeMapPrimitiveMultiblockController extends MultiblockWithDisplayBase { + + protected PrimitiveRecipeLogic recipeMapWorkable; + + public RecipeMapPrimitiveMultiblockController(ResourceLocation metaTileEntityId, RecipeMap recipeMap) { + super(metaTileEntityId); + this.recipeMapWorkable = new PrimitiveRecipeLogic(this, recipeMap); + initializeAbilities(); + } + + // just initialize inventories based on RecipeMap values by default + protected void initializeAbilities() { + this.importItems = new NotifiableItemStackHandler(recipeMapWorkable.recipeMap.getMaxInputs(), this, false); + this.importFluids = new FluidTankList(true, makeFluidTanks(recipeMapWorkable.recipeMap.getMaxFluidInputs(), false)); + this.exportItems = new NotifiableItemStackHandler(recipeMapWorkable.recipeMap.getMaxOutputs(), this, true); + this.exportFluids = new FluidTankList(false, makeFluidTanks(recipeMapWorkable.recipeMap.getMaxFluidOutputs(), true)); + + this.itemInventory = new ItemHandlerProxy(this.importItems, this.exportItems); + this.fluidInventory = new FluidHandlerProxy(this.importFluids, this.exportFluids); + } + + private List makeFluidTanks(int length, boolean isExport) { + List fluidTankList = new ArrayList<>(length); + for (int i = 0; i < length; i++) { + fluidTankList.add(new NotifiableFluidTank(32000, this, isExport)); + } + return fluidTankList; + } + + @Override + protected void updateFormedValid() { + recipeMapWorkable.update(); + } + + @Override + public void invalidateStructure() { + super.invalidateStructure(); + recipeMapWorkable.invalidate(); + } +} diff --git a/src/main/java/gregtech/api/capability/impl/RecipeMapSteamMultiblockController.java b/src/main/java/gregtech/api/metatileentity/multiblock/RecipeMapSteamMultiblockController.java similarity index 93% rename from src/main/java/gregtech/api/capability/impl/RecipeMapSteamMultiblockController.java rename to src/main/java/gregtech/api/metatileentity/multiblock/RecipeMapSteamMultiblockController.java index 249807a586e..b46dcfbb84a 100644 --- a/src/main/java/gregtech/api/capability/impl/RecipeMapSteamMultiblockController.java +++ b/src/main/java/gregtech/api/metatileentity/multiblock/RecipeMapSteamMultiblockController.java @@ -1,12 +1,16 @@ -package gregtech.api.capability.impl; +package gregtech.api.metatileentity.multiblock; import gregtech.api.capability.IMultipleTankHandler; +import gregtech.api.capability.impl.FluidTankList; +import gregtech.api.capability.impl.ItemHandlerList; +import gregtech.api.capability.impl.SteamMultiblockRecipeLogic; import gregtech.api.metatileentity.multiblock.IMultiblockPart; import gregtech.api.metatileentity.multiblock.MultiblockAbility; import gregtech.api.metatileentity.multiblock.MultiblockWithDisplayBase; import gregtech.api.multiblock.PatternMatchContext; import gregtech.api.recipes.Recipe; import gregtech.api.recipes.RecipeMap; +import gregtech.common.ConfigHolder; import net.minecraft.util.ResourceLocation; import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.Style; @@ -23,6 +27,8 @@ public abstract class RecipeMapSteamMultiblockController extends MultiblockWithDisplayBase { + protected static final double CONVERSION_RATE = ConfigHolder.U.multiblockSteamToEU; + public final RecipeMap recipeMap; protected SteamMultiblockRecipeLogic recipeMapWorkable; diff --git a/src/main/java/gregtech/api/multiblock/BlockPattern.java b/src/main/java/gregtech/api/multiblock/BlockPattern.java index 83f1eaf84ee..2da1b45e0cc 100644 --- a/src/main/java/gregtech/api/multiblock/BlockPattern.java +++ b/src/main/java/gregtech/api/multiblock/BlockPattern.java @@ -3,6 +3,7 @@ import gnu.trove.map.TIntObjectMap; import gnu.trove.map.hash.TIntObjectHashMap; import gregtech.api.util.IntRange; +import gregtech.api.util.RelativeDirection; import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos.MutableBlockPos; @@ -197,27 +198,4 @@ private MutableBlockPos setActualRelativeOffset(MutableBlockPos pos, int x, int } return pos.setPos(c1[0], c1[1], c1[2]); } - - /** - * Relative direction when facing horizontally - */ - public enum RelativeDirection { - UP(f -> EnumFacing.UP), - DOWN(f -> EnumFacing.DOWN), - LEFT(EnumFacing::rotateYCCW), - RIGHT(EnumFacing::rotateY), - FRONT(Function.identity()), - BACK(EnumFacing::getOpposite); - - final Function actualFacing; - - RelativeDirection(Function actualFacing) { - this.actualFacing = actualFacing; - } - - public EnumFacing getActualFacing(EnumFacing facing) { - return actualFacing.apply(facing); - } - } - } diff --git a/src/main/java/gregtech/api/multiblock/FactoryBlockPattern.java b/src/main/java/gregtech/api/multiblock/FactoryBlockPattern.java index 6bdc1e053c1..34f874b006f 100644 --- a/src/main/java/gregtech/api/multiblock/FactoryBlockPattern.java +++ b/src/main/java/gregtech/api/multiblock/FactoryBlockPattern.java @@ -3,7 +3,7 @@ import com.google.common.base.Joiner; import gnu.trove.map.TIntObjectMap; import gnu.trove.map.hash.TIntObjectHashMap; -import gregtech.api.multiblock.BlockPattern.RelativeDirection; +import gregtech.api.util.RelativeDirection; import gregtech.api.util.IntRange; import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.StringUtils; @@ -17,7 +17,7 @@ import java.util.Map.Entry; import java.util.function.Predicate; -import static gregtech.api.multiblock.BlockPattern.RelativeDirection.*; +import static gregtech.api.util.RelativeDirection.*; public class FactoryBlockPattern { diff --git a/src/main/java/gregtech/api/pipenet/MonolithicPipeNet.java b/src/main/java/gregtech/api/pipenet/MonolithicPipeNet.java deleted file mode 100644 index e9292af0b55..00000000000 --- a/src/main/java/gregtech/api/pipenet/MonolithicPipeNet.java +++ /dev/null @@ -1,65 +0,0 @@ -package gregtech.api.pipenet; - -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.util.math.BlockPos; - -import java.util.Map; - -/** - * Represents a pipe net where all nodes have same type - * and cannot connect when their types are not equal - * useful for fluid and item-based pipes, which assume that all nodes have same type, - * saving performance very much during iterations and item/fluid dispatching - */ -public abstract class MonolithicPipeNet extends PipeNet { - - /** - * Represents type of nodes in this network - * all nodes are guaranteed to have this type and node.data.equals(nodeData) - * note that it is null until first node is added to this network - */ - protected NodeDataType nodeData; - - public MonolithicPipeNet(WorldPipeNet world) { - super(world); - } - - public NodeDataType getNodeData() { - return nodeData; - } - - @Override - protected void addNode(BlockPos nodePos, Node node) { - if (nodeData == null) { - this.nodeData = node.data; - } else if (!nodeData.equals(node.data)) { - throw new IllegalArgumentException("Attempted to add node with different type to monolithic net!"); - } - super.addNode(nodePos, node); - } - - @Override - protected void transferNodeData(Map> transferredNodes, PipeNet parentNet) { - if (nodeData == null && !transferredNodes.isEmpty()) { - this.nodeData = transferredNodes.values().iterator().next().data; - } - super.transferNodeData(transferredNodes, parentNet); - } - - @Override - public void deserializeNBT(NBTTagCompound nbt) { - super.deserializeNBT(nbt); - //since net cannot exist in world without at least one node - this.nodeData = getAllNodes().values().iterator().next().data; - } - - @Override - protected boolean areNodesCustomContactable(NodeDataType first, NodeDataType second, PipeNet secondNodeNet) { - return nodeData == null || (first.equals(nodeData) && second.equals(nodeData)); - } - - @Override - protected boolean canAttachNode(NodeDataType nodeData) { - return this.nodeData == null || nodeData.equals(this.nodeData); - } -} diff --git a/src/main/java/gregtech/api/pipenet/PipeGatherer.java b/src/main/java/gregtech/api/pipenet/PipeGatherer.java new file mode 100644 index 00000000000..99e6a87a413 --- /dev/null +++ b/src/main/java/gregtech/api/pipenet/PipeGatherer.java @@ -0,0 +1,66 @@ +package gregtech.api.pipenet; + +import gregtech.api.pipenet.tile.IPipeTile; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +import javax.annotation.Nullable; +import java.util.ArrayList; +import java.util.List; +import java.util.function.Predicate; + +public class PipeGatherer extends PipeNetWalker { + + @Nullable + public static IPipeTile findFirstMatching(PipeNet net, World world, BlockPos sourcePipe, Predicate> pipePredicate) { + PipeGatherer gatherer = new PipeGatherer(net, world, sourcePipe, 1, pipePredicate, new ArrayList<>()); + gatherer.returnAfterFirst = true; + gatherer.traversePipeNet(); + return gatherer.pipes.size() > 0 ? gatherer.pipes.get(0) : null; + } + + public static List> gatherPipes(PipeNet net, World world, BlockPos sourcePipe, Predicate> pipePredicate) { + PipeGatherer gatherer = new PipeGatherer(net, world, sourcePipe, 1, pipePredicate, new ArrayList<>()); + gatherer.traversePipeNet(); + return gatherer.pipes; + } + + public static List> gatherPipesInDistance(PipeNet net, World world, BlockPos sourcePipe, Predicate> pipePredicate, int distance) { + PipeGatherer gatherer = new PipeGatherer(net, world, sourcePipe, 1, pipePredicate, new ArrayList<>()); + gatherer.traversePipeNet(distance); + return gatherer.pipes; + } + + private final Predicate> pipePredicate; + private final List> pipes; + private boolean returnAfterFirst = false; + + protected PipeGatherer(PipeNet net, World world, BlockPos sourcePipe, int walkedBlocks, Predicate> pipePredicate, List> pipes) { + super(net, world, sourcePipe, walkedBlocks); + this.pipePredicate = pipePredicate; + this.pipes = pipes; + } + + @Override + protected PipeNetWalker createSubWalker(PipeNet net, World world, BlockPos nextPos, int walkedBlocks) { + return new PipeGatherer(net, world, nextPos, walkedBlocks, pipePredicate, pipes); + } + + @Override + protected void checkPipe(IPipeTile pipeTile, BlockPos pos) { + if (pipePredicate.test(pipeTile)) { + pipes.add(pipeTile); + } + } + + @Override + protected void checkNeighbour(IPipeTile pipeTile, BlockPos pipePos, EnumFacing faceToNeighbour, @Nullable TileEntity neighbourTile) { + } + + @Override + protected boolean isValidPipe(IPipeTile currentPipe, IPipeTile neighbourPipe, BlockPos pipePos, EnumFacing faceToNeighbour) { + return (!returnAfterFirst || pipes.size() <= 0) && pipePredicate.test(neighbourPipe); + } +} diff --git a/src/main/java/gregtech/api/pipenet/PipeNetWalker.java b/src/main/java/gregtech/api/pipenet/PipeNetWalker.java new file mode 100644 index 00000000000..4fd426b54fa --- /dev/null +++ b/src/main/java/gregtech/api/pipenet/PipeNetWalker.java @@ -0,0 +1,186 @@ +package gregtech.api.pipenet; + +import gregtech.api.pipenet.tile.IPipeTile; +import gregtech.api.util.GTLog; +import gregtech.common.pipelike.fluidpipe.net.FluidNetWalker; +import gregtech.common.pipelike.itempipe.net.ItemNetWalker; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +import javax.annotation.Nullable; +import java.util.*; + +/** + * This is a helper class to get information about a pipe net + *

The walker is written that it will always find the shortest path to any destination + *

On the way it can collect information about the pipes and it's neighbours + *

After creating a walker simply call {@link #traversePipeNet()} to start walking, then you can just collect the data + *

Do not walk a walker more than once + *

For example implementations look at {@link ItemNetWalker} and {@link FluidNetWalker} + */ +public abstract class PipeNetWalker { + + private final PipeNet net; + private final World world; + private final Set> walked = new HashSet<>(); + private final List pipes = new ArrayList<>(); + private List walkers; + private final BlockPos.MutableBlockPos currentPos; + private int walkedBlocks; + private boolean invalid; + + protected PipeNetWalker(PipeNet net, World world, BlockPos sourcePipe, int walkedBlocks) { + this.world = Objects.requireNonNull(world); + this.net = Objects.requireNonNull(net); + this.walkedBlocks = walkedBlocks; + this.currentPos = new BlockPos.MutableBlockPos(Objects.requireNonNull(sourcePipe)); + } + + /** + * Creates a sub walker + * Will be called when a pipe has multiple valid pipes + * + * @param net pipe net + * @param world world + * @param nextPos next pos to check + * @param walkedBlocks distance from source in blocks + * @return new sub walker + */ + protected abstract PipeNetWalker createSubWalker(PipeNet net, World world, BlockPos nextPos, int walkedBlocks); + + /** + * You can increase walking stats here. for example + * + * @param pipeTile current checking pipe + * @param pos current pipe pos + */ + protected abstract void checkPipe(IPipeTile pipeTile, BlockPos pos); + + /** + * Checks the neighbour of the current pos + * neighbourTile is NEVER an instance of {@link IPipeTile} + * + * @param pipePos current pos + * @param faceToNeighbour face to neighbour + * @param neighbourTile neighbour tile + */ + protected abstract void checkNeighbour(IPipeTile pipeTile, BlockPos pipePos, EnumFacing faceToNeighbour, @Nullable TileEntity neighbourTile); + + /** + * If the pipe is valid to perform a walk on + * + * @param currentPipe current pipe + * @param neighbourPipe neighbour pipe to check + * @param pipePos current pos (tile.getPipePos() != pipePos) + * @param faceToNeighbour face to pipeTile + * @return if the pipe is valid + */ + protected abstract boolean isValidPipe(IPipeTile currentPipe, IPipeTile neighbourPipe, BlockPos pipePos, EnumFacing faceToNeighbour); + + public void traversePipeNet() { + traversePipeNet(Integer.MAX_VALUE); + } + + /** + * Starts walking the pipe net and gathers information. + * + * @param maxWalks max walks to prevent possible stack overflow + * @throws IllegalStateException if the walker already walked + */ + public void traversePipeNet(int maxWalks) { + if (invalid) + throw new IllegalStateException("This walker already walked. Create a new one if you want to walk again"); + int i = 0; + while (!walk() && i++ < maxWalks) ; + walked.forEach(IPipeTile::resetWalk); + invalid = true; + } + + private boolean walk() { + if (walkers == null) + checkPos(); + + if (pipes.size() == 0) + return true; + if (pipes.size() == 1) { + currentPos.move(pipes.get(0)); + walkedBlocks++; + return false; + } + + if (walkers == null) { + walkers = new ArrayList<>(); + for (EnumFacing side : pipes) { + walkers.add(Objects.requireNonNull(createSubWalker(net, world, currentPos.offset(side), walkedBlocks + 1), "Walker can't be null")); + } + } else { + Iterator iterator = walkers.iterator(); + while (iterator.hasNext()) { + PipeNetWalker walker = iterator.next(); + if (walker.walk()) { + walked.addAll(walker.walked); + iterator.remove(); + } + } + } + + return walkers.size() == 0; + } + + private void checkPos() { + pipes.clear(); + TileEntity thisPipe = world.getTileEntity(currentPos); + IPipeTile pipeTile = (IPipeTile) thisPipe; + if (pipeTile == null) { + if (walkedBlocks == 1) { + // if it is the first block, it wasn't already checked + GTLog.logger.warn("First PipeTile is null during walk"); + return; + } else + throw new IllegalStateException("PipeTile was not null last walk, but now is"); + } + checkPipe(pipeTile, currentPos); + pipeTile.markWalked(); + walked.add(pipeTile); + + BlockPos.PooledMutableBlockPos pos = BlockPos.PooledMutableBlockPos.retain(); + // check for surrounding pipes and item handlers + for (EnumFacing accessSide : EnumFacing.VALUES) { + //skip sides reported as blocked by pipe network + if (!pipeTile.isConnectionOpenAny(accessSide)) + continue; + + pos.setPos(currentPos).move(accessSide); + TileEntity tile = world.getTileEntity(pos); + if (tile instanceof IPipeTile) { + IPipeTile otherPipe = (IPipeTile) tile; + if (otherPipe.isWalked()) + continue; + if (isValidPipe(pipeTile, otherPipe, currentPos, accessSide)) { + pipes.add(accessSide); + continue; + } + } + checkNeighbour(pipeTile, currentPos, accessSide, tile); + } + pos.release(); + } + + public PipeNet getNet() { + return net; + } + + public World getWorld() { + return world; + } + + public BlockPos getCurrentPos() { + return currentPos; + } + + public int getWalkedBlocks() { + return walkedBlocks; + } +} diff --git a/src/main/java/gregtech/api/pipenet/block/BlockPipe.java b/src/main/java/gregtech/api/pipenet/block/BlockPipe.java index cfcbd9f64c3..e3e4e6a5ab7 100644 --- a/src/main/java/gregtech/api/pipenet/block/BlockPipe.java +++ b/src/main/java/gregtech/api/pipenet/block/BlockPipe.java @@ -83,6 +83,7 @@ public BlockPipe() { protected abstract NodeDataType getFallbackType(); + // TODO this has no reason to need an ItemStack parameter public abstract PipeType getItemPipeType(ItemStack itemStack); public abstract void setTileEntityData(TileEntityPipeBase pipeTile, ItemStack itemStack); @@ -160,7 +161,7 @@ public void neighborChanged(@Nonnull IBlockState state, @Nonnull World worldIn, } } if (facing == null) throw new NullPointerException("Facing is null"); - boolean open = pipeTile.isConnectionOpenVisual(facing); + boolean open = pipeTile.isConnectionOpenAny(facing); boolean canConnect = canConnect(pipeTile, facing); if (!open && canConnect && !ConfigHolder.U.GT6.gt6StylePipesCables) pipeTile.setConnectionBlocked(AttachmentType.PIPE, facing, false, false); @@ -193,7 +194,6 @@ public int getWeakPower(@Nonnull IBlockState blockState, @Nonnull IBlockAccess b public void updateActiveNodeStatus(World worldIn, BlockPos pos, IPipeTile pipeTile) { PipeNet pipeNet = getWorldPipeNet(worldIn).getNetFromPos(pos); if (pipeNet != null && pipeTile != null) { - //int activeConnections = ~getActiveNodeConnections(worldIn, pos, pipeTile); int activeConnections = pipeTile.getOpenConnections(); //remove blocked connections boolean isActiveNodeNow = activeConnections != 0; boolean modeChanged = pipeNet.markNodeAsActive(pos, isActiveNodeNow); @@ -407,7 +407,7 @@ public int getVisualConnections(IPipeTile selfTile) { int connections = selfTile.getOpenConnections(); for (EnumFacing facing : EnumFacing.values()) { // continue if connection is already open - if (selfTile.isConnectionOpenVisual(facing)) continue; + if (selfTile.isConnectionOpenAny(facing)) continue; CoverBehavior cover = selfTile.getCoverableImplementation().getCoverAtSide(facing); if (cover == null) continue; // adds side to open connections of it isn't already open & has a cover diff --git a/src/main/java/gregtech/api/pipenet/block/material/ItemBlockMaterialPipe.java b/src/main/java/gregtech/api/pipenet/block/material/ItemBlockMaterialPipe.java index 3ac1fd27c9f..4aa2d6dd04a 100644 --- a/src/main/java/gregtech/api/pipenet/block/material/ItemBlockMaterialPipe.java +++ b/src/main/java/gregtech/api/pipenet/block/material/ItemBlockMaterialPipe.java @@ -3,8 +3,6 @@ import gregtech.api.pipenet.block.ItemBlockPipe; import gregtech.api.unification.material.Material; import net.minecraft.item.ItemStack; -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; import javax.annotation.Nonnull; @@ -17,7 +15,6 @@ public ItemBlockMaterialPipe(BlockMaterialPipe block) @Nonnull @SuppressWarnings("unchecked") @Override - @SideOnly(Side.CLIENT) public String getItemStackDisplayName(@Nonnull ItemStack stack) { PipeType pipeType = blockPipe.getItemPipeType(stack); Material material = ((BlockMaterialPipe) blockPipe).getItemMaterial(stack); diff --git a/src/main/java/gregtech/api/pipenet/tickable/TickableWorldPipeNet.java b/src/main/java/gregtech/api/pipenet/tickable/TickableWorldPipeNet.java index a55e98cd819..e16e5515adc 100644 --- a/src/main/java/gregtech/api/pipenet/tickable/TickableWorldPipeNet.java +++ b/src/main/java/gregtech/api/pipenet/tickable/TickableWorldPipeNet.java @@ -8,16 +8,13 @@ import net.minecraft.world.chunk.Chunk; import org.apache.commons.lang3.tuple.Pair; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.stream.Collectors; public abstract class TickableWorldPipeNet & ITickable> extends WorldPipeNet { private final Map> loadedChunksByPipeNet = new HashMap<>(); - private final List tickingPipeNets = new ArrayList<>(); + private final Set tickingPipeNets = new HashSet<>(); public TickableWorldPipeNet(String name) { super(name); @@ -25,6 +22,7 @@ public TickableWorldPipeNet(String name) { private boolean isChunkLoaded(ChunkPos chunkPos) { WorldServer worldServer = (WorldServer) getWorld(); + if (worldServer == null) return false; return worldServer.getChunkProvider().chunkExists(chunkPos.x, chunkPos.z); } @@ -32,13 +30,14 @@ private boolean isChunkLoaded(ChunkPos chunkPos) { public void update() { if (getWorld().getTotalWorldTime() % getUpdateRate() == 0L) { - tickingPipeNets.forEach(ITickable::update); + tickingPipeNets.forEach(net -> net.update()); } } public void onChunkLoaded(Chunk chunk) { ChunkPos chunkPos = chunk.getPos(); List pipeNetsInThisChunk = this.pipeNetsByChunk.get(chunkPos); + if (pipeNetsInThisChunk == null) return; for (T pipeNet : pipeNetsInThisChunk) { List loadedChunks = getOrCreateChunkListForPipeNet(pipeNet); if (loadedChunks.isEmpty()) { @@ -51,6 +50,7 @@ public void onChunkLoaded(Chunk chunk) { public void onChunkUnloaded(Chunk chunk) { ChunkPos chunkPos = chunk.getPos(); List pipeNetsInThisChunk = this.pipeNetsByChunk.get(chunkPos); + if (pipeNetsInThisChunk == null) return; for (T pipeNet : pipeNetsInThisChunk) { List loadedChunks = this.loadedChunksByPipeNet.get(pipeNet); if (loadedChunks != null && loadedChunks.contains(chunkPos)) { diff --git a/src/main/java/gregtech/api/pipenet/tile/IPipeTile.java b/src/main/java/gregtech/api/pipenet/tile/IPipeTile.java index ca487f59787..2fe4712c7f9 100644 --- a/src/main/java/gregtech/api/pipenet/tile/IPipeTile.java +++ b/src/main/java/gregtech/api/pipenet/tile/IPipeTile.java @@ -42,7 +42,7 @@ default long getTickTimer() { boolean isConnectionOpen(AttachmentType type, EnumFacing side); - default boolean isConnectionOpenVisual(EnumFacing side) { + default boolean isConnectionOpenAny(EnumFacing side) { return (getOpenConnections() & 1 << side.getIndex()) > 0; } @@ -73,4 +73,10 @@ default boolean isConnectionOpenVisual(EnumFacing side) { boolean isValidTile(); void scheduleChunkForRenderUpdate(); + + void markWalked(); + + boolean isWalked(); + + void resetWalk(); } diff --git a/src/main/java/gregtech/api/pipenet/tile/PipeCoverableImplementation.java b/src/main/java/gregtech/api/pipenet/tile/PipeCoverableImplementation.java index 7b41b498cdf..173b7910f9f 100644 --- a/src/main/java/gregtech/api/pipenet/tile/PipeCoverableImplementation.java +++ b/src/main/java/gregtech/api/pipenet/tile/PipeCoverableImplementation.java @@ -69,8 +69,9 @@ public final boolean placeCoverOnSide(EnumFacing side, ItemStack itemStack, Cove buffer.writeVarInt(CoverDefinition.getNetworkIdForCover(coverDefinition)); coverBehavior.writeInitialSyncData(buffer); }); + holder.setConnectionBlocked(AttachmentType.COVER, side, false, false); if (!coverBehavior.canPipePassThrough()) { - holder.setConnectionBlocked(AttachmentType.COVER, side, true, false); + holder.setConnectionBlocked(AttachmentType.PIPE, side, true, false); } holder.notifyBlockUpdate(); holder.markAsDirty(); @@ -91,8 +92,9 @@ public final boolean removeCover(EnumFacing side) { Block.spawnAsEntity(getWorld(), getPos(), dropStack); } writeCustomData(2, buffer -> buffer.writeByte(side.getIndex())); - BlockPipe pipeBlock = (BlockPipe) getWorld().getBlockState(getPos()).getBlock(); - holder.setConnectionBlocked(AttachmentType.COVER, side, !pipeBlock.canConnect(holder, side), false); + BlockPipe blockPipe = holder.getPipeBlock(); + holder.setConnectionBlocked(AttachmentType.COVER, side, true, false); + holder.setConnectionBlocked(AttachmentType.PIPE, side, !blockPipe.canConnect(holder, side), false); holder.notifyBlockUpdate(); holder.markAsDirty(); return true; diff --git a/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java b/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java index 10a54e29c9f..b99275fa97e 100644 --- a/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java +++ b/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java @@ -8,8 +8,6 @@ import gregtech.api.pipenet.WorldPipeNet; import gregtech.api.pipenet.block.BlockPipe; import gregtech.api.pipenet.block.IPipeType; -import gregtech.api.util.FirstTickScheduler; -import gregtech.api.util.IFirstTickTask; import gregtech.common.ConfigHolder; import net.minecraft.block.Block; import net.minecraft.block.state.IBlockState; @@ -27,10 +25,11 @@ import javax.annotation.Nullable; import java.util.function.Consumer; -public abstract class TileEntityPipeBase & IPipeType, NodeDataType> extends SyncedTileEntityBase implements IPipeTile, IFirstTickTask { +public abstract class TileEntityPipeBase & IPipeType, NodeDataType> extends SyncedTileEntityBase implements IPipeTile { private TIntIntMap openConnectionsMap = new TIntIntHashMap(); private int openConnections = 0; + private boolean walked = false; protected int insulationColor = DEFAULT_INSULATION_COLOR; protected final PipeCoverableImplementation coverableImplementation = new PipeCoverableImplementation(this); @@ -41,10 +40,8 @@ public abstract class TileEntityPipeBase & IPipe private boolean wasInDetachedConversionMode; public TileEntityPipeBase() { - if (ConfigHolder.U.GT6.gt6StylePipesCables) { - openConnectionsMap.put(AttachmentType.PIPE.ordinal(), 0); - recomputeBlockedConnections(); - } + openConnectionsMap.put(AttachmentType.PIPE.ordinal(), 0); + recomputeBlockedConnections(); } public void setDetachedConversionMode(boolean detachedConversionMode) { @@ -56,6 +53,21 @@ public boolean wasInDetachedConversionMode() { return wasInDetachedConversionMode; } + @Override + public void markWalked() { + walked = true; + } + + @Override + public boolean isWalked() { + return walked; + } + + @Override + public void resetWalk() { + walked = false; + } + public void setPipeData(BlockPipe pipeBlock, PipeType pipeType) { this.pipeBlock = pipeBlock; this.pipeType = pipeType; @@ -159,23 +171,30 @@ public boolean isConnectionOpen(AttachmentType type, EnumFacing side) { @Override public void setConnectionBlocked(AttachmentType attachmentType, EnumFacing side, boolean blocked, boolean fromNeighbor) { // fix desync between two connections. Can happen if a pipe side is blocked, and a new pipe is placed next to it. - if (attachmentType == AttachmentType.PIPE && isConnectionOpen(attachmentType, side) == isNeighborPipeBlocked(attachmentType, side) && !fromNeighbor) { + TileEntity tile = getWorld().getTileEntity(getPos().offset(side)); + IPipeTile neighbourPipe = null; + if (tile instanceof IPipeTile) + neighbourPipe = (IPipeTile) tile; + if (neighbourPipe != null && !fromNeighbor && attachmentType == AttachmentType.PIPE && isConnectionOpenAny(side) != neighbourPipe.isConnectionOpenAny(side.getOpposite())) { syncPipeConnections(attachmentType, side); return; } - - int openConnections = openConnectionsMap.get(attachmentType.ordinal()); - this.openConnectionsMap.put(attachmentType.ordinal(), withSideConnectionBlocked(openConnections, side, blocked)); + int at = attachmentType.ordinal(); + int openConnections = withSideConnectionBlocked(openConnectionsMap.get(at), side, blocked); + this.openConnectionsMap.put(at, openConnections); recomputeBlockedConnections(); if (!getWorld().isRemote) { if (!detachedConversionMode) { updateSideBlockedConnection(side); } - writeCustomData(-2, buffer -> buffer.writeVarInt(this.openConnections)); + writeCustomData(-2, buffer -> { + buffer.writeVarInt(at); + buffer.writeVarInt(openConnections); + }); markDirty(); - } - if (attachmentType == AttachmentType.PIPE && !fromNeighbor) { - setNeighborPipeBlocked(attachmentType, side, blocked); + if (neighbourPipe != null && attachmentType == AttachmentType.PIPE && !fromNeighbor) { + setNeighborPipeBlocked(attachmentType, side, blocked); + } } } @@ -188,17 +207,17 @@ private void setNeighborPipeBlocked(AttachmentType type, EnumFacing side, boolea } } - private boolean isNeighborPipeBlocked(AttachmentType type, EnumFacing side) { + private boolean isNeighborPipeOpen(AttachmentType type, EnumFacing side) { TileEntity te = this.getWorld().getTileEntity(this.getPipePos().offset(side)); - if (te instanceof TileEntityPipeBase) { - TileEntityPipeBase pipeTe = (TileEntityPipeBase) te; - return !pipeTe.isConnectionOpen(type, side.getOpposite()); + if (te instanceof IPipeTile) { + IPipeTile pipeTe = (IPipeTile) te; + return pipeTe.isConnectionOpen(type, side.getOpposite()); } return false; } private void syncPipeConnections(AttachmentType type, EnumFacing side) { - if (isNeighborPipeBlocked(type, side) && isConnectionOpen(type, side)) { + if (!isNeighborPipeOpen(type, side) && isConnectionOpen(type, side)) { setNeighborPipeBlocked(type, side, false); } else { setConnectionBlocked(type, side, false, true); @@ -269,7 +288,7 @@ public final T getCapability(@Nonnull Capability capability, @Nullable En } if (coverBehavior == null && facing != null) { //boolean isBlocked = (getBlockedConnections() & 1 << facing.getIndex()) > 0; - return isConnectionOpenVisual(facing) ? defaultValue : null; + return isConnectionOpenAny(facing) ? defaultValue : null; } if (coverBehavior != null) { return coverBehavior.getCapability(capability, defaultValue); @@ -327,11 +346,6 @@ public void readFromNBT(@Nonnull NBTTagCompound compound) { @Override public void onLoad() { super.onLoad(); - FirstTickScheduler.addTask(this); - } - - @Override - public void handleFirstTick() { this.coverableImplementation.onLoad(); } @@ -365,7 +379,8 @@ public void receiveCustomData(int discriminator, PacketBuffer buf) { this.insulationColor = buf.readInt(); scheduleChunkForRenderUpdate(); } else if (discriminator == -2) { - this.openConnections = buf.readVarInt(); + this.openConnectionsMap.put(buf.readVarInt(), buf.readVarInt()); + recomputeBlockedConnections(); scheduleChunkForRenderUpdate(); } else if (discriminator == -3) { this.coverableImplementation.readCustomData(buf.readVarInt(), buf); diff --git a/src/main/java/gregtech/api/recipes/GTRecipeHandler.java b/src/main/java/gregtech/api/recipes/GTRecipeHandler.java new file mode 100644 index 00000000000..dce2d14f0e3 --- /dev/null +++ b/src/main/java/gregtech/api/recipes/GTRecipeHandler.java @@ -0,0 +1,96 @@ +package gregtech.api.recipes; + +import gregtech.api.util.GTLog; +import gregtech.common.ConfigHolder; +import net.minecraft.item.ItemStack; +import net.minecraftforge.fluids.FluidStack; + +import java.util.ArrayList; +import java.util.List; + +@SuppressWarnings("unused") +public class GTRecipeHandler { + + /** + * Removes all Recipes matching given inputs and fluid inputs from a given RecipeMap. + * An example of how to use it: + * + * + * removeRecipesByInputs(RecipeMaps.CHEMICAL_RECIPES, + * new ItemStack[]{ + * OreDictUnifier.get(OrePrefix.dust, Materials.SodiumHydroxide, 3) + * }, + * new FluidStack[]{ + * Materials.HypochlorousAcid.getFluid(1000), + * Materials.AllylChloride.getFluid(1000) + * }); + * + * + * This method also has varargs parameter methods for when there is only ItemStack or FluidStack inputs. + * + * @param map The RecipeMap to search over. + * @param itemInputs The ItemStack[] containing all Recipe item inputs. + * @param fluidInputs The FluidStack[] containing all Recipe fluid inputs. + * + * @return true if a recipe was removed, false otherwise. + */ + public static > boolean removeRecipesByInputs(RecipeMap map, ItemStack[] itemInputs, FluidStack[] fluidInputs) { + + List fluidNames = new ArrayList<>(); + List itemNames = new ArrayList<>(); + + List itemIn = new ArrayList<>(); + for (ItemStack s : itemInputs) { + itemIn.add(s); + if(ConfigHolder.debug) { + itemNames.add(String.format("%s x %d", s.getDisplayName(), s.getCount())); + } + } + + List fluidIn = new ArrayList<>(); + for (FluidStack s : fluidInputs) { + fluidIn.add(s); + if(ConfigHolder.debug) { + fluidNames.add(String.format("%s x %d", s.getFluid().getName(), s.amount)); + } + } + + boolean wasRemoved = map.removeRecipe(map.findRecipe(Long.MAX_VALUE, itemIn, fluidIn, Integer.MAX_VALUE, MatchingMode.DEFAULT)); + if (ConfigHolder.debug) { + if (wasRemoved) + GTLog.logger.info("Removed Recipe for inputs: Items: {} Fluids: {}", itemNames, fluidNames); + else GTLog.logger.error("Failed to Remove Recipe for inputs: Items: {} Fluids: {}", itemNames, fluidNames); + } + return wasRemoved; + } + + public static > boolean removeRecipesByInputs(RecipeMap map, ItemStack... itemInputs) { + return removeRecipesByInputs(map, itemInputs, new FluidStack[0]); + } + + public static > boolean removeRecipesByInputs(RecipeMap map, FluidStack... fluidInputs) { + return removeRecipesByInputs(map, new ItemStack[0], fluidInputs); + } + + /** + * Removes all Recipes from a given RecipeMap. This method cannot fail at recipe removal, but if called at + * the wrong time during recipe registration, it may be an incomplete or overly-complete recipe removal. + * An example of how to use it: + * + * + * removeAllRecipes(RecipeMaps.BREWING_RECIPES); + * + * + * @param map The RecipeMap to clear all recipes from. + */ + public static > void removeAllRecipes(RecipeMap map) { + + List recipes = new ArrayList<>(map.getRecipeList()); + + for (Recipe r : recipes) + map.removeRecipe(r); + + if(ConfigHolder.debug) + GTLog.logger.info("Removed all recipes for Recipe Map: {}", map.unlocalizedName); + } +} diff --git a/src/main/java/gregtech/api/recipes/ModHandler.java b/src/main/java/gregtech/api/recipes/ModHandler.java index cb504c99126..41f9723e234 100644 --- a/src/main/java/gregtech/api/recipes/ModHandler.java +++ b/src/main/java/gregtech/api/recipes/ModHandler.java @@ -14,6 +14,7 @@ import gregtech.api.util.GTLog; import gregtech.api.util.ShapedOreEnergyTransferRecipe; import gregtech.api.util.world.DummyWorld; +import gregtech.common.ConfigHolder; import net.minecraft.block.Block; import net.minecraft.creativetab.CreativeTabs; import net.minecraft.inventory.InventoryCrafting; @@ -478,28 +479,33 @@ public static boolean removeFurnaceSmelting(ItemStack input) { RecipeMap.setFoundInvalidRecipe(true); return false; } + + boolean wasRemoved = false; for (ItemStack stack : FurnaceRecipes.instance().getSmeltingList().keySet()) { if (ItemStack.areItemStacksEqual(input, stack)) { FurnaceRecipes.instance().getSmeltingList().remove(stack); - return true; + wasRemoved = true; + break; } } - return false; - } + if (ConfigHolder.debug) { + if (wasRemoved) + GTLog.logger.info("Removed Smelting Recipe for Input: {}", input.getDisplayName()); + else GTLog.logger.error("Failed to Remove Smelting Recipe for Input: {}", input.getDisplayName()); + } - public static int removeRecipes(Item output) { - return removeRecipes(recipe -> { - ItemStack recipeOutput = recipe.getRecipeOutput(); - return !recipeOutput.isEmpty() && recipeOutput.getItem() == output; - }); + return wasRemoved; } public static int removeRecipes(ItemStack output) { - return removeRecipes(recipe -> ItemStack.areItemStacksEqual(recipe.getRecipeOutput(), output)); - } + int recipesRemoved = removeRecipes(recipe -> ItemStack.areItemStacksEqual(recipe.getRecipeOutput(), output)); - public static int removeRecipes(Class recipeClass) { - return removeRecipes(recipeClass::isInstance); + if (ConfigHolder.debug) { + if (recipesRemoved != 0) + GTLog.logger.info("Removed {} Recipe(s) with Output: {}", recipesRemoved, output.getDisplayName()); + else GTLog.logger.error("Failed to Remove Recipe with Output: {}", output.getDisplayName()); + } + return recipesRemoved; } public static int removeRecipes(Predicate predicate) { @@ -520,10 +526,53 @@ public static int removeRecipes(Predicate predicate) { return recipesRemoved; } + /** + * Removes a Crafting Table Recipe with the given name. + * + * @param location The ResourceLocation of the Recipe. + * Can also accept a String. + */ public static void removeRecipeByName(ResourceLocation location) { + if (ConfigHolder.debug) { + String recipeName = location.toString(); + if (ForgeRegistries.RECIPES.containsKey(location)) + GTLog.logger.info("Removed Recipe with Name: {}", recipeName); + else GTLog.logger.error("Failed to Remove Recipe with Name: {}", recipeName); + } ForgeRegistries.RECIPES.register(new DummyRecipe().setRegistryName(location)); } + public static void removeRecipeByName(String recipeName) { + removeRecipeByName(new ResourceLocation(recipeName)); + } + + /** + * Removes Crafting Table Recipes with a range of names, being {@link GTValues} voltage names. + * An example of how to use it: + * + * + * removeTieredRecipeByName("gregtech:transformer_", EV, UV); + * + * + * This will remove recipes with names: + * + * + * gregtech:transformer_ev + * gregtech:transformer_iv + * gregtech:transformer_luv + * gregtech:transformer_zpm + * gregtech:transformer_uv + * + * + * @param recipeName The base name of the Recipes to remove. + * @param startTier The starting tier index, inclusive. + * @param endTier The ending tier index, inclusive. + */ + public static void removeTieredRecipeByName(String recipeName, int startTier, int endTier) { + for (int i = startTier; i <= endTier; i++) + removeRecipeByName(String.format("%s%s", recipeName, GTValues.VN[i].toLowerCase())); + } + /////////////////////////////////////////////////// // Get Recipe Output Helpers // /////////////////////////////////////////////////// diff --git a/src/main/java/gregtech/api/recipes/Recipe.java b/src/main/java/gregtech/api/recipes/Recipe.java index 30d4f65335a..6daabb5c028 100644 --- a/src/main/java/gregtech/api/recipes/Recipe.java +++ b/src/main/java/gregtech/api/recipes/Recipe.java @@ -314,6 +314,10 @@ public Set getPropertyKeys() { return recipePropertyStorage.getRecipePropertyKeys(); } + public boolean hasProperty(RecipeProperty property) { + return recipePropertyStorage.hasRecipeProperty(property); + } + public int getPropertyCount() { return recipePropertyStorage.getSize(); } @@ -343,5 +347,9 @@ public int getChance() { public int getBoostPerTier() { return boostPerTier; } + + public ChanceEntry copy() { + return new ChanceEntry(itemStack, chance, boostPerTier); + } } } diff --git a/src/main/java/gregtech/api/recipes/RecipeBuilder.java b/src/main/java/gregtech/api/recipes/RecipeBuilder.java index 51f6c83ce74..e1f2c95a4d4 100644 --- a/src/main/java/gregtech/api/recipes/RecipeBuilder.java +++ b/src/main/java/gregtech/api/recipes/RecipeBuilder.java @@ -305,6 +305,11 @@ public R chancedOutput(MetaItem.MetaValueItem item, int chance, int tierChanc return chancedOutput(item, 1, chance, tierChanceBoost); } + public R chancedOutputs(List chancedOutputs) { + chancedOutputs.stream().map(ChanceEntry::copy).forEach(this.chancedOutputs::add); + return (R) this; + } + public R duration(int duration) { this.duration = duration; return (R) this; diff --git a/src/main/java/gregtech/api/recipes/RecipeMap.java b/src/main/java/gregtech/api/recipes/RecipeMap.java index 8072d0b14e2..0de8ec4e935 100644 --- a/src/main/java/gregtech/api/recipes/RecipeMap.java +++ b/src/main/java/gregtech/api/recipes/RecipeMap.java @@ -18,21 +18,16 @@ import gregtech.api.gui.widgets.SlotWidget; import gregtech.api.gui.widgets.TankWidget; import gregtech.api.recipes.builders.IntCircuitRecipeBuilder; +import gregtech.api.recipes.builders.PrimitiveRecipeBuilder; import gregtech.api.recipes.crafttweaker.CTRecipe; import gregtech.api.recipes.crafttweaker.CTRecipeBuilder; import gregtech.api.unification.material.Material; import gregtech.api.unification.ore.OrePrefix; -import gregtech.api.util.EnumValidationResult; -import gregtech.api.util.GTLog; -import gregtech.api.util.GTUtility; -import gregtech.api.util.ValidationResult; -import net.minecraft.client.resources.I18n; +import gregtech.api.util.*; import net.minecraft.item.ItemStack; import net.minecraftforge.fluids.Fluid; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fml.common.Optional.Method; -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; import net.minecraftforge.items.IItemHandlerModifiable; import stanhebben.zenscript.annotations.Optional; import stanhebben.zenscript.annotations.*; @@ -99,6 +94,7 @@ public static List> getRecipeMaps() { public static void sortMaps() { for (RecipeMap rmap : RECIPE_MAP_REGISTRY.values()) { + if (rmap.recipeBuilder() instanceof PrimitiveRecipeBuilder) continue; // just for cleanliness rmap.recipeList.sort(Comparator.comparingInt(Recipe::getDuration) .thenComparingInt(Recipe::getEUt)); } @@ -424,10 +420,9 @@ public List ccGetRecipeList() { .collect(Collectors.toList()); } - @SideOnly(Side.CLIENT) @ZenGetter("localizedName") public String getLocalizedName() { - return I18n.format("recipemap." + unlocalizedName + ".name"); + return LocalizationUtils.format("recipemap." + unlocalizedName + ".name"); } @ZenGetter("unlocalizedName") diff --git a/src/main/java/gregtech/api/recipes/RecipeMaps.java b/src/main/java/gregtech/api/recipes/RecipeMaps.java index da108de966d..f8d10e125be 100644 --- a/src/main/java/gregtech/api/recipes/RecipeMaps.java +++ b/src/main/java/gregtech/api/recipes/RecipeMaps.java @@ -693,36 +693,38 @@ public class RecipeMaps { .setProgressBar(GuiTextures.PROGRESS_BAR_ARROW, MoveType.HORIZONTAL); @ZenProperty - public static final FuelRecipeMap COMBUSTION_GENERATOR_FUELS = new FuelRecipeMap("combustion_generator"); + public static final RecipeMap GAS_COLLECTOR_RECIPES = new RecipeMap<>("gas_collector", 1, 1, 0, 0, 0, 0, 1, 1, new GasCollectorRecipeBuilder(), false) + .setSlotOverlay(false, false, GuiTextures.INT_CIRCUIT_OVERLAY) + .setSlotOverlay(true, true, GuiTextures.CENTRIFUGE_OVERLAY) + .setProgressBar(GuiTextures.PROGRESS_BAR_GAS_COLLECTOR, MoveType.HORIZONTAL); + public static final RecipeMap SIMPLE_WASHER_RECIPES = new RecipeMap<>("simple_washer", 1, 1, 1, 1, 1, 1, 0, 0, new SimpleRecipeBuilder(), true) + .setSlotOverlay(false, false, GuiTextures.CRUSHED_ORE_OVERLAY) + .setSlotOverlay(true, false, GuiTextures.DUST_OVERLAY) + .setProgressBar(GuiTextures.PROGRESS_BAR_BATH, MoveType.HORIZONTAL); @ZenProperty - public static final FuelRecipeMap GAS_TURBINE_FUELS = new FuelRecipeMap("gas_turbine"); - + public static final RecipeMap PRIMITIVE_BLAST_FURNACE_RECIPES = new RecipeMap<>("primitive_blast_furnace", 2, 2, 1, 2, 0, 0, 0, 0, new PrimitiveRecipeBuilder(), false); @ZenProperty - public static final FuelRecipeMap STEAM_TURBINE_FUELS = new FuelRecipeMap("steam_turbine"); + public static final RecipeMap COKE_OVEN_RECIPES = new RecipeMap<>("coke_oven", 1, 1, 0, 1, 0, 0, 0, 1, new PrimitiveRecipeBuilder(), false); - @ZenProperty - public static final FuelRecipeMap SEMI_FLUID_GENERATOR_FUELS = new FuelRecipeMap("semi_fluid_generator"); + ////////////////////////////////////// + // Fuel Recipe Maps // + ////////////////////////////////////// @ZenProperty - public static final FuelRecipeMap PLASMA_GENERATOR_FUELS = new FuelRecipeMap("plasma_generator"); + public static final FuelRecipeMap COMBUSTION_GENERATOR_FUELS = new FuelRecipeMap("combustion_generator"); @ZenProperty - public static final List PRIMITIVE_BLAST_FURNACE_RECIPES = new CopyOnWriteArrayList<>(); + public static final FuelRecipeMap GAS_TURBINE_FUELS = new FuelRecipeMap("gas_turbine"); @ZenProperty - public static final List COKE_OVEN_RECIPES = new CopyOnWriteArrayList<>(); - - @ZenMethod - public static List getPrimitiveBlastFurnaceRecipes() { - return PRIMITIVE_BLAST_FURNACE_RECIPES; - } + public static final FuelRecipeMap STEAM_TURBINE_FUELS = new FuelRecipeMap("steam_turbine"); - @ZenMethod - public static List getCokeOvenRecipes() { - return COKE_OVEN_RECIPES; - } + @ZenProperty + public static final FuelRecipeMap SEMI_FLUID_GENERATOR_FUELS = new FuelRecipeMap("semi_fluid_generator"); + @ZenProperty + public static final FuelRecipeMap PLASMA_GENERATOR_FUELS = new FuelRecipeMap("plasma_generator"); } diff --git a/src/main/java/gregtech/api/recipes/builders/CokeOvenRecipeBuilder.java b/src/main/java/gregtech/api/recipes/builders/CokeOvenRecipeBuilder.java deleted file mode 100644 index 7d361a547ee..00000000000 --- a/src/main/java/gregtech/api/recipes/builders/CokeOvenRecipeBuilder.java +++ /dev/null @@ -1,137 +0,0 @@ -package gregtech.api.recipes.builders; - -import crafttweaker.annotations.ZenRegister; -import crafttweaker.api.item.IIngredient; -import crafttweaker.api.item.IItemStack; -import crafttweaker.api.liquid.ILiquidStack; -import crafttweaker.api.minecraft.CraftTweakerMC; -import gregtech.api.GTValues; -import gregtech.api.recipes.CountableIngredient; -import gregtech.api.recipes.RecipeMaps; -import gregtech.api.recipes.crafttweaker.CTRecipeBuilder.CraftTweakerIngredientWrapper; -import gregtech.api.recipes.recipes.CokeOvenRecipe; -import gregtech.api.unification.material.Material; -import gregtech.api.unification.ore.OrePrefix; -import gregtech.api.util.EnumValidationResult; -import gregtech.api.util.GTLog; -import gregtech.api.util.ValidationResult; -import net.minecraft.item.ItemStack; -import net.minecraft.item.crafting.Ingredient; -import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.fml.common.Optional.Method; -import stanhebben.zenscript.annotations.ZenClass; -import stanhebben.zenscript.annotations.ZenMethod; - -@ZenClass("mods.gregtech.recipe.CokeOvenRecipeBuilder") -@ZenRegister -public class CokeOvenRecipeBuilder { - - private CountableIngredient input; - private ItemStack output; - private FluidStack fluidOutput; - private int duration = -1; - - private CokeOvenRecipeBuilder() { - } - - @ZenMethod - public static CokeOvenRecipeBuilder start() { - return new CokeOvenRecipeBuilder(); - } - - public CokeOvenRecipeBuilder input(Ingredient input, int amount) { - this.input = new CountableIngredient(input, amount); - return this; - } - - public CokeOvenRecipeBuilder input(ItemStack itemStack) { - this.input = CountableIngredient.from(itemStack); - return this; - } - - public CokeOvenRecipeBuilder input(OrePrefix orePrefix, Material material) { - this.input = CountableIngredient.from(orePrefix, material); - return this; - } - - public CokeOvenRecipeBuilder input(OrePrefix orePrefix, Material material, int amount) { - this.input = CountableIngredient.from(orePrefix, material, amount); - return this; - } - - @ZenMethod - public CokeOvenRecipeBuilder duration(int duration) { - this.duration = duration; - return this; - } - - public CokeOvenRecipeBuilder output(ItemStack output) { - this.output = output; - return this; - } - - public CokeOvenRecipeBuilder fluidOutput(FluidStack fluidOutput) { - this.fluidOutput = fluidOutput; - return this; - } - - public ValidationResult build() { - return ValidationResult.newResult(validate(), - new CokeOvenRecipe(input, output, fluidOutput, duration)); - } - - protected EnumValidationResult validate() { - EnumValidationResult result = EnumValidationResult.VALID; - - if (input == null) { - GTLog.logger.error("Input Ingredient cannot be null", new IllegalArgumentException()); - result = EnumValidationResult.INVALID; - } - - if (output == null || output.isEmpty()) { - GTLog.logger.error("Output ItemStack cannot be null or empty", new IllegalArgumentException()); - result = EnumValidationResult.INVALID; - } - - if (fluidOutput == null || fluidOutput.amount == 0) { - GTLog.logger.error("Output FluidStack cannot be null or empty", new IllegalArgumentException()); - result = EnumValidationResult.INVALID; - } - - if (duration <= 0) { - GTLog.logger.error("Duration cannot be less or equal to 0", new IllegalArgumentException()); - result = EnumValidationResult.INVALID; - } - - return result; - } - - @ZenMethod - public void buildAndRegister() { - ValidationResult result = build(); - - if (result.getType() == EnumValidationResult.VALID) { - CokeOvenRecipe recipe = result.getResult(); - RecipeMaps.COKE_OVEN_RECIPES.add(recipe); - } - } - - @ZenMethod - @Method(modid = GTValues.MODID_CT) - public CokeOvenRecipeBuilder input(IIngredient ingredient) { - return input(new CraftTweakerIngredientWrapper(ingredient), ingredient.getAmount()); - } - - @ZenMethod - @Method(modid = GTValues.MODID_CT) - public CokeOvenRecipeBuilder fluidOutput(ILiquidStack liquidStack) { - return fluidOutput(CraftTweakerMC.getLiquidStack(liquidStack)); - } - - @ZenMethod - @Method(modid = GTValues.MODID_CT) - public CokeOvenRecipeBuilder output(IItemStack itemStack) { - return output(CraftTweakerMC.getItemStack(itemStack)); - } - -} diff --git a/src/main/java/gregtech/api/recipes/builders/GasCollectorRecipeBuilder.java b/src/main/java/gregtech/api/recipes/builders/GasCollectorRecipeBuilder.java new file mode 100644 index 00000000000..d15a598eef7 --- /dev/null +++ b/src/main/java/gregtech/api/recipes/builders/GasCollectorRecipeBuilder.java @@ -0,0 +1,68 @@ +package gregtech.api.recipes.builders; + +import gregtech.api.recipes.Recipe; +import gregtech.api.recipes.RecipeBuilder; +import gregtech.api.recipes.RecipeMap; +import gregtech.api.recipes.recipeproperties.GasCollectorDimensionProperty; +import gregtech.api.util.EnumValidationResult; +import gregtech.api.util.ValidationResult; +import org.apache.commons.lang3.builder.ToStringBuilder; + +import java.util.ArrayList; +import java.util.List; + +public class GasCollectorRecipeBuilder extends RecipeBuilder { + + private List dimensionIDs; + + public GasCollectorRecipeBuilder() { + } + + public GasCollectorRecipeBuilder(Recipe recipe, RecipeMap recipeMap) { + super(recipe, recipeMap); + this.dimensionIDs = recipe.getProperty(GasCollectorDimensionProperty.getInstance(), new ArrayList()); + } + + public GasCollectorRecipeBuilder(RecipeBuilder recipeBuilder) { + super(recipeBuilder); + } + + @Override + public GasCollectorRecipeBuilder copy() { + return new GasCollectorRecipeBuilder(this); + } + + @Override + public boolean applyProperty(String key, Object value) { + if (key.equals(GasCollectorDimensionProperty.KEY)) { + this.dimension(((Number) value).intValue()); + return true; + } + return true; + } + + public GasCollectorRecipeBuilder dimension(int dimensionID) { + if (this.dimensionIDs == null) + this.dimensionIDs = new ArrayList<>(); + this.dimensionIDs.add(dimensionID); + return this; + } + + public ValidationResult build() { + Recipe recipe = new Recipe(inputs, outputs, chancedOutputs, fluidInputs, fluidOutputs, + duration, EUt, hidden); + if (!recipe.setProperty(GasCollectorDimensionProperty.getInstance(), dimensionIDs)) { + return ValidationResult.newResult(EnumValidationResult.INVALID, recipe); + } + + return ValidationResult.newResult(finalizeAndValidate(), recipe); + } + + @Override + public String toString() { + return new ToStringBuilder(this) + .appendSuper(super.toString()) + .append(GasCollectorDimensionProperty.getInstance().getKey(), dimensionIDs.toString()) + .toString(); + } +} diff --git a/src/main/java/gregtech/api/recipes/builders/PBFRecipeBuilder.java b/src/main/java/gregtech/api/recipes/builders/PBFRecipeBuilder.java deleted file mode 100644 index 1dbf928ba48..00000000000 --- a/src/main/java/gregtech/api/recipes/builders/PBFRecipeBuilder.java +++ /dev/null @@ -1,139 +0,0 @@ -package gregtech.api.recipes.builders; - -import crafttweaker.annotations.ZenRegister; -import crafttweaker.api.item.IIngredient; -import crafttweaker.api.item.IItemStack; -import crafttweaker.api.minecraft.CraftTweakerMC; -import gregtech.api.GTValues; -import gregtech.api.recipes.CountableIngredient; -import gregtech.api.recipes.RecipeMaps; -import gregtech.api.recipes.crafttweaker.CTRecipeBuilder.CraftTweakerIngredientWrapper; -import gregtech.api.recipes.recipes.PrimitiveBlastFurnaceRecipe; -import gregtech.api.unification.OreDictUnifier; -import gregtech.api.unification.material.Material; -import gregtech.api.unification.ore.OrePrefix; -import gregtech.api.util.EnumValidationResult; -import gregtech.api.util.GTLog; -import gregtech.api.util.ValidationResult; -import net.minecraft.item.ItemStack; -import net.minecraft.item.crafting.Ingredient; -import net.minecraftforge.fml.common.Optional.Method; -import stanhebben.zenscript.annotations.ZenClass; -import stanhebben.zenscript.annotations.ZenMethod; - -@ZenClass("mods.gregtech.recipe.PBFRecipeBuilder") -@ZenRegister -public class PBFRecipeBuilder { - - private CountableIngredient input; - private ItemStack output; - - private int duration = -1; - private int fuelAmount = -1; - - private PBFRecipeBuilder() { - } - - @ZenMethod - public static PBFRecipeBuilder start() { - return new PBFRecipeBuilder(); - } - - public PBFRecipeBuilder input(Ingredient input, int amount) { - this.input = new CountableIngredient(input, amount); - return this; - } - - public PBFRecipeBuilder input(ItemStack itemStack) { - this.input = CountableIngredient.from(itemStack); - return this; - } - - public PBFRecipeBuilder input(OrePrefix orePrefix, Material material) { - return input(orePrefix, material, 1); - } - - public PBFRecipeBuilder input(OrePrefix orePrefix, Material material, int amount) { - this.input = CountableIngredient.from(orePrefix, material, amount); - return this; - } - - @ZenMethod - public PBFRecipeBuilder duration(int duration) { - this.duration = duration; - return this; - } - - @ZenMethod - public PBFRecipeBuilder fuelAmount(int fuelAmount) { - this.fuelAmount = fuelAmount; - return this; - } - - public PBFRecipeBuilder output(ItemStack output) { - this.output = output; - return this; - } - - public PBFRecipeBuilder output(OrePrefix prefix, Material material, int amount) { - this.output = OreDictUnifier.get(prefix, material, amount); - return this; - } - - public PBFRecipeBuilder output(OrePrefix prefix, Material material) { - return output(prefix, material, 1); - } - - public ValidationResult build() { - return ValidationResult.newResult(validate(), - new PrimitiveBlastFurnaceRecipe(input, output, duration, fuelAmount)); - } - - protected EnumValidationResult validate() { - EnumValidationResult result = EnumValidationResult.VALID; - - if (input == null) { - GTLog.logger.error("Input Ingredient cannot be null", new IllegalArgumentException()); - result = EnumValidationResult.INVALID; - } - - if (output == null || output.isEmpty()) { - GTLog.logger.error("Output ItemStack cannot be null or empty", new IllegalArgumentException()); - result = EnumValidationResult.INVALID; - } - - if (fuelAmount <= 0) { - GTLog.logger.error("FuelAmount cannot be less or equal to 0", new IllegalArgumentException()); - result = EnumValidationResult.INVALID; - } - if (duration <= 0) { - GTLog.logger.error("Duration cannot be less or equal to 0", new IllegalArgumentException()); - result = EnumValidationResult.INVALID; - } - - return result; - } - - @ZenMethod - public void buildAndRegister() { - ValidationResult result = build(); - - if (result.getType() == EnumValidationResult.VALID) { - PrimitiveBlastFurnaceRecipe recipe = result.getResult(); - RecipeMaps.PRIMITIVE_BLAST_FURNACE_RECIPES.add(recipe); - } - } - - @ZenMethod - @Method(modid = GTValues.MODID_CT) - public PBFRecipeBuilder input(IIngredient ingredient) { - return input(new CraftTweakerIngredientWrapper(ingredient), ingredient.getAmount()); - } - - @ZenMethod - @Method(modid = GTValues.MODID_CT) - public PBFRecipeBuilder output(IItemStack itemStack) { - return output(CraftTweakerMC.getItemStack(itemStack)); - } - -} diff --git a/src/main/java/gregtech/api/recipes/builders/PrimitiveRecipeBuilder.java b/src/main/java/gregtech/api/recipes/builders/PrimitiveRecipeBuilder.java new file mode 100644 index 00000000000..dd1398066e3 --- /dev/null +++ b/src/main/java/gregtech/api/recipes/builders/PrimitiveRecipeBuilder.java @@ -0,0 +1,37 @@ +package gregtech.api.recipes.builders; + +import gregtech.api.recipes.Recipe; +import gregtech.api.recipes.RecipeBuilder; +import gregtech.api.recipes.RecipeMap; +import gregtech.api.recipes.recipeproperties.PrimitiveProperty; +import gregtech.api.util.EnumValidationResult; +import gregtech.api.util.ValidationResult; + +public class PrimitiveRecipeBuilder extends RecipeBuilder { + + public PrimitiveRecipeBuilder() { + } + + public PrimitiveRecipeBuilder(Recipe recipe, RecipeMap recipeMap) { + super(recipe, recipeMap); + } + + public PrimitiveRecipeBuilder(RecipeBuilder recipeBuilder) { + super(recipeBuilder); + } + + @Override + public PrimitiveRecipeBuilder copy() { + return new PrimitiveRecipeBuilder(this); + } + + @Override + public ValidationResult build() { + this.EUt(1); // secretly force to 1 to allow recipe matching to work properly + Recipe recipe = new Recipe(inputs, outputs, chancedOutputs, fluidInputs, fluidOutputs, duration, EUt, hidden); + if (!recipe.setProperty(PrimitiveProperty.getInstance(), true)) { + return ValidationResult.newResult(EnumValidationResult.INVALID, recipe); + } + return ValidationResult.newResult(finalizeAndValidate(), recipe); + } +} diff --git a/src/main/java/gregtech/api/recipes/builders/UniversalDistillationRecipeBuilder.java b/src/main/java/gregtech/api/recipes/builders/UniversalDistillationRecipeBuilder.java index 20eeea77c06..8ad49834932 100644 --- a/src/main/java/gregtech/api/recipes/builders/UniversalDistillationRecipeBuilder.java +++ b/src/main/java/gregtech/api/recipes/builders/UniversalDistillationRecipeBuilder.java @@ -6,11 +6,14 @@ import gregtech.api.recipes.RecipeMaps; import gregtech.api.util.GTUtility; import gregtech.api.util.ValidationResult; +import gregtech.common.ConfigHolder; import net.minecraft.item.ItemStack; import net.minecraftforge.fluids.FluidStack; public class UniversalDistillationRecipeBuilder extends RecipeBuilder { + private boolean doDistilleryRecipes = true; + public UniversalDistillationRecipeBuilder() { } @@ -29,12 +32,17 @@ public UniversalDistillationRecipeBuilder copy() { @Override public void buildAndRegister() { + if (!this.doDistilleryRecipes) { + super.buildAndRegister(); + return; + } + for (int i = 0; i < fluidOutputs.size(); i++) { - IntCircuitRecipeBuilder builder = RecipeMaps.DISTILLERY_RECIPES.recipeBuilder().copy().EUt(this.EUt / 4).circuitMeta(i + 1); + IntCircuitRecipeBuilder builder = RecipeMaps.DISTILLERY_RECIPES.recipeBuilder().copy().EUt(Math.max(1, this.EUt / 4)).circuitMeta(i + 1); int ratio = getRatioForDistillery(this.fluidInputs.get(0), this.fluidOutputs.get(i), this.outputs.size() > 0 ? this.outputs.get(0) : null); - int recipeDuration = this.EUt > 16 ? (int) (this.duration * 2.8f) : this.duration * 2; + int recipeDuration = (int) (this.duration * ConfigHolder.U.overclockDivisor); boolean shouldDivide = ratio != 1; @@ -47,7 +55,7 @@ public void buildAndRegister() { if (shouldDivide && fluidsDivisible) builder.fluidInputs(dividedInputFluid) .fluidOutputs(dividedOutputFluid) - .duration(recipeDuration / ratio); + .duration(Math.max(1, recipeDuration / ratio)); else if (!shouldDivide) { builder.fluidInputs(this.fluidInputs.get(0)) @@ -104,4 +112,10 @@ private boolean isFluidStackDivisibleForDistillery(FluidStack fluidStack, int di return GTUtility.isFluidStackAmountDivisible(fluidStack, divisor) && fluidStack.amount / divisor >= 25; } + // todo expose to CT + public UniversalDistillationRecipeBuilder disableDistilleryRecipes() { + this.doDistilleryRecipes = false; + return this; + } + } diff --git a/src/main/java/gregtech/api/recipes/crafttweaker/CokeOvenRecipeExpansion.java b/src/main/java/gregtech/api/recipes/crafttweaker/CokeOvenRecipeExpansion.java deleted file mode 100644 index 128feb3ad2e..00000000000 --- a/src/main/java/gregtech/api/recipes/crafttweaker/CokeOvenRecipeExpansion.java +++ /dev/null @@ -1,17 +0,0 @@ -package gregtech.api.recipes.crafttweaker; - -import crafttweaker.annotations.ZenRegister; -import gregtech.api.recipes.RecipeMaps; -import gregtech.api.recipes.recipes.CokeOvenRecipe; -import stanhebben.zenscript.annotations.ZenExpansion; -import stanhebben.zenscript.annotations.ZenMethod; - -@ZenExpansion("mods.gregtech.recipe.CokeOvenRecipe") -@ZenRegister -public class CokeOvenRecipeExpansion { - - @ZenMethod - public static void remove(CokeOvenRecipe recipe) { - RecipeMaps.getCokeOvenRecipes().remove(recipe); - } -} diff --git a/src/main/java/gregtech/api/recipes/crafttweaker/PBFRecipeExpansion.java b/src/main/java/gregtech/api/recipes/crafttweaker/PBFRecipeExpansion.java deleted file mode 100644 index 2a4aeda06e5..00000000000 --- a/src/main/java/gregtech/api/recipes/crafttweaker/PBFRecipeExpansion.java +++ /dev/null @@ -1,17 +0,0 @@ -package gregtech.api.recipes.crafttweaker; - -import crafttweaker.annotations.ZenRegister; -import gregtech.api.recipes.RecipeMaps; -import gregtech.api.recipes.recipes.PrimitiveBlastFurnaceRecipe; -import stanhebben.zenscript.annotations.ZenExpansion; -import stanhebben.zenscript.annotations.ZenMethod; - -@ZenExpansion("mods.gregtech.recipe.PrimitiveBlastFurnaceRecipe") -@ZenRegister -public class PBFRecipeExpansion { - - @ZenMethod - public static void remove(PrimitiveBlastFurnaceRecipe recipe) { - RecipeMaps.getPrimitiveBlastFurnaceRecipes().remove(recipe); - } -} diff --git a/src/main/java/gregtech/api/recipes/machines/FuelRecipeMap.java b/src/main/java/gregtech/api/recipes/machines/FuelRecipeMap.java index 5e95f907627..35cb973c718 100644 --- a/src/main/java/gregtech/api/recipes/machines/FuelRecipeMap.java +++ b/src/main/java/gregtech/api/recipes/machines/FuelRecipeMap.java @@ -6,11 +6,9 @@ import gregtech.api.GTValues; import gregtech.api.recipes.FluidKey; import gregtech.api.recipes.recipes.FuelRecipe; -import net.minecraft.client.resources.I18n; +import gregtech.api.util.LocalizationUtils; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fml.common.Optional.Method; -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; import stanhebben.zenscript.annotations.ZenClass; import stanhebben.zenscript.annotations.ZenGetter; import stanhebben.zenscript.annotations.ZenMethod; @@ -84,10 +82,9 @@ public List getRecipeList() { return Collections.unmodifiableList(recipeList); } - @SideOnly(Side.CLIENT) @ZenGetter("localizedName") public String getLocalizedName() { - return I18n.format("recipemap." + unlocalizedName + ".name"); + return LocalizationUtils.format("recipemap." + unlocalizedName + ".name"); } @ZenGetter("unlocalizedName") diff --git a/src/main/java/gregtech/api/recipes/machines/RecipeMapDistillationTower.java b/src/main/java/gregtech/api/recipes/machines/RecipeMapDistillationTower.java index 747140c1b54..d5a966291ad 100644 --- a/src/main/java/gregtech/api/recipes/machines/RecipeMapDistillationTower.java +++ b/src/main/java/gregtech/api/recipes/machines/RecipeMapDistillationTower.java @@ -4,12 +4,15 @@ import gregtech.api.gui.GuiTextures; import gregtech.api.gui.ModularUI; import gregtech.api.gui.resources.TextureArea; +import gregtech.api.gui.widgets.ImageWidget; import gregtech.api.gui.widgets.SlotWidget; import gregtech.api.gui.widgets.TankWidget; import gregtech.api.recipes.RecipeMap; import gregtech.api.recipes.builders.UniversalDistillationRecipeBuilder; import net.minecraftforge.items.IItemHandlerModifiable; +import java.util.function.DoubleSupplier; + public class RecipeMapDistillationTower extends RecipeMap { public RecipeMapDistillationTower(String unlocalizedName, int minInputs, int maxInputs, int minOutputs, int maxOutputs, int minFluidInputs, int maxFluidInputs, int minFluidOutputs, int maxFluidOutputs, UniversalDistillationRecipeBuilder defaultRecipe, boolean isHidden) { @@ -32,6 +35,7 @@ else if (slotIndex == 1 || slotIndex == 4 || slotIndex == 7 || slotIndex == 10) else if (slotIndex == 2 || slotIndex == 5 || slotIndex == 8 || slotIndex == 11) tankWidget.setBackgroundTexture(base, GuiTextures.BEAKER_OVERLAY_4); + tankWidget.setAlwaysShowFull(true); builder.widget(tankWidget); } else { SlotWidget slotWidget = new SlotWidget(itemHandler, slotIndex, x, y, true, !isOutputs); @@ -42,4 +46,61 @@ else if (slotIndex == 2 || slotIndex == 5 || slotIndex == 8 || slotIndex == 11) builder.widget(slotWidget); } } + + @Override + //this DOES NOT include machine control widgets or binds player inventory + public ModularUI.Builder createUITemplate(DoubleSupplier progressSupplier, IItemHandlerModifiable importItems, IItemHandlerModifiable exportItems, FluidTankList importFluids, FluidTankList exportFluids, int yOffset) { + ModularUI.Builder builder = ModularUI.defaultBuilder(yOffset); + builder.widget(new ImageWidget(41, 1, 72, 72, GuiTextures.PROGRESS_BAR_DISTILLATION_TOWER)); + addInventorySlotGroup(builder, importItems, importFluids, false, yOffset); + addInventorySlotGroup(builder, exportItems, exportFluids, true, yOffset); + if (this.specialTexture != null && this.specialTexturePosition != null) + addSpecialTexture(builder); + return builder; + } + + @Override + protected void addInventorySlotGroup(ModularUI.Builder builder, IItemHandlerModifiable itemHandler, FluidTankList fluidHandler, boolean isOutputs, int yOffset) { + int itemInputsCount = itemHandler.getSlots(); + int fluidInputsCount = fluidHandler.getTanks(); + boolean invertFluids = false; + if (itemInputsCount == 0) { + int tmp = itemInputsCount; + itemInputsCount = fluidInputsCount; + fluidInputsCount = tmp; + invertFluids = true; + } + int[] inputSlotGrid = determineSlotsGrid(itemInputsCount); + int itemSlotsToLeft = inputSlotGrid[0]; + int itemSlotsToDown = inputSlotGrid[1]; + int startInputsX = isOutputs ? 104 : 68 - itemSlotsToLeft * 18; + int startInputsY = 55 - (int) (itemSlotsToDown / 2.0 * 18) + yOffset; + boolean wasGroupOutput = itemHandler.getSlots() + fluidHandler.getTanks() == 12; + if (wasGroupOutput && isOutputs) startInputsY -= 9; + if (itemHandler.getSlots() == 6 && fluidHandler.getTanks() == 2 && !isOutputs) startInputsY -= 9; + if (!isOutputs) + addSlot(builder, 40, startInputsY + (itemSlotsToDown - 1) * 18 - 18, 0, itemHandler, fluidHandler, invertFluids, false); + else + addSlot(builder, 94, startInputsY + (itemSlotsToDown - 1) * 18, 0, itemHandler, fluidHandler, invertFluids, true); + + if (wasGroupOutput) startInputsY += 2; + + if (!isOutputs) + return; + + if (!invertFluids) { + startInputsY -= 18; + startInputsX += 9; + } + + if (fluidInputsCount > 0 || invertFluids) { + + int startSpecY = startInputsY + itemSlotsToDown * 18; + for (int i = 0; i < fluidInputsCount; i++) { + int x = startInputsX + 18 * (i % 3); + int y = startSpecY - (i / 3) * 18; + addSlot(builder, x, y, i, itemHandler, fluidHandler, true, true); + } + } + } } diff --git a/src/main/java/gregtech/api/recipes/recipeproperties/GasCollectorDimensionProperty.java b/src/main/java/gregtech/api/recipes/recipeproperties/GasCollectorDimensionProperty.java new file mode 100644 index 00000000000..8c29fe91404 --- /dev/null +++ b/src/main/java/gregtech/api/recipes/recipeproperties/GasCollectorDimensionProperty.java @@ -0,0 +1,47 @@ +package gregtech.api.recipes.recipeproperties; + +import gregtech.api.worldgen.config.WorldGenRegistry; +import net.minecraft.client.Minecraft; +import net.minecraft.client.resources.I18n; + +import java.util.List; +import java.util.Map; + +public class GasCollectorDimensionProperty extends RecipeProperty { + public static final String KEY = "dimension"; + + private static GasCollectorDimensionProperty INSTANCE; + + private GasCollectorDimensionProperty() { + super(KEY, List.class); + } + + public static GasCollectorDimensionProperty getInstance() { + if (INSTANCE == null) + INSTANCE = new GasCollectorDimensionProperty(); + return INSTANCE; + } + + @Override + public void drawInfo(Minecraft minecraft, int x, int y, int color, Object value) { + minecraft.fontRenderer.drawString(I18n.format("gregtech.recipe.dimensions", + getDimensionsForRecipe(castValue(value))), x, y, color); + } + + private String getDimensionsForRecipe(List value) { + Map dimNames = WorldGenRegistry.getNamedDimensions(); + StringBuilder builder = new StringBuilder(); + for (int i = 0; i < value.size(); i++) { + builder.append(dimNames.getOrDefault(value.get(i), "" + value.get(i))); + if (i != value.size() - 1) + builder.append(", "); + } + String str = builder.toString(); + + if (str.length() >= 13) { + str = str.substring(0, 10) + ".."; + } + return str; + } + +} diff --git a/src/main/java/gregtech/api/recipes/recipeproperties/PrimitiveProperty.java b/src/main/java/gregtech/api/recipes/recipeproperties/PrimitiveProperty.java new file mode 100644 index 00000000000..59dc9ca3270 --- /dev/null +++ b/src/main/java/gregtech/api/recipes/recipeproperties/PrimitiveProperty.java @@ -0,0 +1,27 @@ +package gregtech.api.recipes.recipeproperties; + +import net.minecraft.client.Minecraft; + +/** + * Simple Marker Property to tell JEI to not display Total EU and EU/t. + */ +public class PrimitiveProperty extends RecipeProperty { + + private static final String KEY = "primitive_property"; + private static PrimitiveProperty INSTANCE; + + private PrimitiveProperty() { + super(KEY, Boolean.class); + } + + public static PrimitiveProperty getInstance() { + if (INSTANCE == null) { + INSTANCE = new PrimitiveProperty(); + } + return INSTANCE; + } + + @Override + public void drawInfo(Minecraft minecraft, int x, int y, int color, Object value) { + } +} diff --git a/src/main/java/gregtech/api/recipes/recipeproperties/RecipePropertyStorage.java b/src/main/java/gregtech/api/recipes/recipeproperties/RecipePropertyStorage.java index 96597a7afac..b355115a5a2 100644 --- a/src/main/java/gregtech/api/recipes/recipeproperties/RecipePropertyStorage.java +++ b/src/main/java/gregtech/api/recipes/recipeproperties/RecipePropertyStorage.java @@ -94,6 +94,10 @@ public T getRecipePropertyValue(RecipeProperty recipeProperty, T defaultV return recipeProperty.castValue(value); } + public boolean hasRecipeProperty(RecipeProperty recipeProperty) { + return recipeProperties.containsKey(recipeProperty); + } + /** * Provides keys of all stored {@link RecipeProperty} * diff --git a/src/main/java/gregtech/api/render/Textures.java b/src/main/java/gregtech/api/render/Textures.java index 0b4b55cf24d..7015fcf8efd 100644 --- a/src/main/java/gregtech/api/render/Textures.java +++ b/src/main/java/gregtech/api/render/Textures.java @@ -119,6 +119,7 @@ public class Textures { public static final OrientedOverlayRenderer FLUID_SOLIDIFIER_OVERLAY = new OrientedOverlayRenderer("machines/fluid_solidifier", FRONT); public static final OrientedOverlayRenderer FORGE_HAMMER_OVERLAY = new OrientedOverlayRenderer("machines/forge_hammer", FRONT); public static final OrientedOverlayRenderer FORMING_PRESS_OVERLAY = new OrientedOverlayRenderer("machines/press", FRONT, SIDE, TOP); + public static final OrientedOverlayRenderer GAS_COLLECTOR_OVERLAY = new OrientedOverlayRenderer("machines/gas_collector", FRONT, SIDE, TOP, BOTTOM, BACK); public static final OrientedOverlayRenderer LATHE_OVERLAY = new OrientedOverlayRenderer("machines/lathe", FRONT); public static final OrientedOverlayRenderer MIXER_OVERLAY = new OrientedOverlayRenderer("machines/mixer", FRONT, SIDE, TOP); public static final OrientedOverlayRenderer ORE_WASHER_OVERLAY = new OrientedOverlayRenderer("machines/ore_washer", FRONT, SIDE); @@ -143,6 +144,7 @@ public class Textures { public static final SimpleOverlayRenderer DETECTOR_ITEM = new SimpleOverlayRenderer("cover/overlay_item_detector"); public static final SimpleOverlayRenderer CRAFTING = new SimpleOverlayRenderer("cover/overlay_crafting"); public static final SimpleOverlayRenderer SOLAR_PANEL = new SimpleOverlayRenderer("cover/overlay_solar_panel"); + public static final SimpleOverlayRenderer INFINITE_WATER = new SimpleOverlayRenderer("cover/overlay_infinite_water"); public static final SimpleOverlayRenderer ROCK_CRUSHER_OVERLAY = new SimpleOverlayRenderer("overlay/machine/overlay_rock_crusher"); public static final SimpleOverlayRenderer ROCK_CRUSHER_ACTIVE_OVERLAY = new SimpleOverlayRenderer("overlay/machine/overlay_rock_crusher_active"); public static final SimpleOverlayRenderer PIPE_OUT_OVERLAY = new SimpleOverlayRenderer("overlay/machine/overlay_pipe_out"); @@ -166,6 +168,10 @@ public class Textures { public static final SimpleOverlayRenderer ENERGY_IN = new SimpleOverlayRenderer("overlay/machine/overlay_energy_in"); public static final SimpleOverlayRenderer ENERGY_OUT_MULTI = new SimpleOverlayRenderer("overlay/machine/overlay_energy_out_multi"); public static final SimpleOverlayRenderer ENERGY_IN_MULTI = new SimpleOverlayRenderer("overlay/machine/overlay_energy_in_multi"); + public static final SimpleOverlayRenderer ENERGY_OUT_HI = new SimpleOverlayRenderer("overlay/machine/overlay_energy_out_hi"); + public static final SimpleOverlayRenderer ENERGY_IN_HI = new SimpleOverlayRenderer("overlay/machine/overlay_energy_in_hi"); + public static final SimpleOverlayRenderer ENERGY_OUT_ULTRA = new SimpleOverlayRenderer("overlay/machine/overlay_energy_out_ultra"); + public static final SimpleOverlayRenderer ENERGY_IN_ULTRA = new SimpleOverlayRenderer("overlay/machine/overlay_energy_in_ultra"); public static final SimpleOverlayRenderer CONVEYOR_OVERLAY = new SimpleOverlayRenderer("cover/overlay_conveyor"); public static final SimpleOverlayRenderer ARM_OVERLAY = new SimpleOverlayRenderer("cover/overlay_arm"); public static final SimpleOverlayRenderer PUMP_OVERLAY = new SimpleOverlayRenderer("cover/overlay_pump"); @@ -176,6 +182,7 @@ public class Textures { public static final SimpleOverlayRenderer STEAM_VENT_OVERLAY = new SimpleOverlayRenderer("overlay/machine/steam_vent"); public static final SimpleOverlayRenderer QUANTUM_TANK_OVERLAY = new SimpleOverlayRenderer("overlay/machine/overlay_qtank"); public static final SimpleOverlayRenderer QUANTUM_CHEST_OVERLAY = new SimpleOverlayRenderer("overlay/machine/overlay_qchest"); + public static final SimpleOverlayRenderer BUFFER_OVERLAY = new SimpleOverlayRenderer("overlay/machine/overlay_buffer"); static { for (int i = 0; i < VOLTAGE_CASINGS.length; i++) { diff --git a/src/main/java/gregtech/api/terminal/TerminalRegistry.java b/src/main/java/gregtech/api/terminal/TerminalRegistry.java new file mode 100644 index 00000000000..d0f1a7303c9 --- /dev/null +++ b/src/main/java/gregtech/api/terminal/TerminalRegistry.java @@ -0,0 +1,49 @@ +package gregtech.api.terminal; + +import gregtech.api.GTValues; +import gregtech.api.terminal.app.*; +import gregtech.common.terminal.app.ThemeSettingApp; +import gregtech.common.terminal.app.guide.ItemGuideApp; +import gregtech.common.terminal.app.guide.MultiBlockGuideApp; +import gregtech.common.terminal.app.guide.SimpleMachineGuideApp; +import gregtech.common.terminal.app.guide.TutorialGuideApp; +import gregtech.common.terminal.app.guideeditor.GuideEditorApp; +import gregtech.common.terminal.app.recipechart.RecipeChartApp; + +import java.util.*; + +public class TerminalRegistry { + private static final Map appRegister = new HashMap<>(); + private static final List defaultApps = new ArrayList<>(); + + public static void init() { + registerApp(new SimpleMachineGuideApp(), true); + registerApp(new MultiBlockGuideApp(), true); + registerApp(new ItemGuideApp(), true); + registerApp(new TutorialGuideApp(), true); + registerApp(new GuideEditorApp(), true); + registerApp(new ThemeSettingApp(), true); + if (GTValues.isModLoaded(GTValues.MODID_JEI)) { + registerApp(new RecipeChartApp(), true); + } + } + + public static void registerApp(AbstractApplication application, boolean isDefaultApp) { + appRegister.put(application.getRegistryName(), application); + if (isDefaultApp) { + defaultApps.add(application.getRegistryName()); + } + } + + public static List getDefaultApps() { + return defaultApps; + } + + public static List getAllApps() { + return new ArrayList<>(appRegister.keySet()); + } + + public static AbstractApplication getApplication(String name) { + return appRegister.get(name); + } +} diff --git a/src/main/java/gregtech/api/terminal/app/AbstractApplication.java b/src/main/java/gregtech/api/terminal/app/AbstractApplication.java new file mode 100644 index 00000000000..843c645e93e --- /dev/null +++ b/src/main/java/gregtech/api/terminal/app/AbstractApplication.java @@ -0,0 +1,75 @@ +package gregtech.api.terminal.app; + +import gregtech.api.gui.resources.IGuiTexture; +import gregtech.api.terminal.gui.widgets.AnimaWidgetGroup; +import gregtech.api.terminal.os.TerminalOSWidget; +import gregtech.api.terminal.os.menu.IMenuComponent; +import gregtech.api.util.Position; +import gregtech.api.util.Size; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.network.PacketBuffer; + +import java.util.Collections; +import java.util.List; +import java.util.function.Consumer; + +public abstract class AbstractApplication extends AnimaWidgetGroup { + protected final String name; + protected final IGuiTexture icon; + protected TerminalOSWidget os; + + public AbstractApplication(String name, IGuiTexture icon) { + super(Position.ORIGIN, new Size(333, 232)); + this.name = name; + this.icon = icon; + } + + public AbstractApplication setOs(TerminalOSWidget os) { + this.os = os; + return this; + } + + public String getRegistryName() { + return name; + } + + public String getUnlocalizedName() { + return "gregtech.terminal.app_name." + name; + } + + public IGuiTexture getIcon() { + return icon; + } + + public abstract AbstractApplication createApp(TerminalOSWidget os, boolean isClient, NBTTagCompound nbt); + + public NBTTagCompound closeApp(boolean isClient, NBTTagCompound nbt) { + return null; + } + + public boolean isBackgroundApp() { + return false; + } + + public boolean isClientSideApp() {return false;} + + public TerminalOSWidget getOs() { + return os; + } + + public List getMenuComponents() { + return Collections.emptyList(); + } + + public boolean canPlayerUse(EntityPlayer player) { + return true; + } + + @Override + protected void writeClientAction(int id, Consumer packetBufferWriter) { + if (!isClientSideApp()) { + super.writeClientAction(id, packetBufferWriter); + } + } +} diff --git a/src/main/java/gregtech/api/terminal/gui/CustomTabListRenderer.java b/src/main/java/gregtech/api/terminal/gui/CustomTabListRenderer.java new file mode 100644 index 00000000000..c84cfd66220 --- /dev/null +++ b/src/main/java/gregtech/api/terminal/gui/CustomTabListRenderer.java @@ -0,0 +1,41 @@ +package gregtech.api.terminal.gui; + +import gregtech.api.gui.resources.IGuiTexture; +import gregtech.api.gui.widgets.tab.ITabInfo; +import gregtech.api.gui.widgets.tab.TabListRenderer; +import gregtech.api.util.Position; + +import java.util.List; + +public class CustomTabListRenderer extends TabListRenderer { + private final IGuiTexture unSelected; + private final IGuiTexture selected; + private final int width; + private final int height; + + public CustomTabListRenderer(IGuiTexture unSelected, IGuiTexture selected, int width, int height){ + this.unSelected = unSelected; + this.selected = selected; + this.width = width; + this.height = height; + } + + @Override + public void renderTabs(Position offset, List tabInfos, int guiWidth, int guiHeight, int selectedTabIndex) { + int y = offset.y - height; + for (int i = 0; i < tabInfos.size(); i++) { + int x = offset.x + i * width; + if (selectedTabIndex == i && selected != null) { + tabInfos.get(i).renderTab(selected, x, y, width, height, true); + } + if (selectedTabIndex != i && unSelected != null) { + tabInfos.get(i).renderTab(unSelected, x, y, width, height, false); + } + } + } + + @Override + public int[] getTabPos(int guiWidth, int guiHeight, int tabIndex) { + return new int[]{width * guiWidth, -height, width, height}; + } +} diff --git a/src/main/java/gregtech/api/terminal/gui/IDraggable.java b/src/main/java/gregtech/api/terminal/gui/IDraggable.java new file mode 100644 index 00000000000..5366276a536 --- /dev/null +++ b/src/main/java/gregtech/api/terminal/gui/IDraggable.java @@ -0,0 +1,8 @@ +package gregtech.api.terminal.gui; + +public interface IDraggable { + boolean allowDrag(int mouseX, int mouseY, int button); + default void startDrag(int mouseX, int mouseY) {} + default boolean dragging(int mouseX, int mouseY, int deltaX, int deltaY) {return true;} + default void endDrag(int mouseX, int mouseY) {} +} diff --git a/src/main/java/gregtech/api/terminal/gui/widgets/AnimaWidgetGroup.java b/src/main/java/gregtech/api/terminal/gui/widgets/AnimaWidgetGroup.java new file mode 100644 index 00000000000..bdf943daf6e --- /dev/null +++ b/src/main/java/gregtech/api/terminal/gui/widgets/AnimaWidgetGroup.java @@ -0,0 +1,100 @@ +package gregtech.api.terminal.gui.widgets; + +import gregtech.api.gui.IRenderContext; +import gregtech.api.gui.widgets.WidgetGroup; +import gregtech.api.util.Position; +import gregtech.api.util.Size; +import gregtech.api.util.interpolate.Eases; +import gregtech.api.util.interpolate.Interpolator; +import net.minecraft.client.renderer.GlStateManager; + +import java.util.function.Consumer; + +public abstract class AnimaWidgetGroup extends WidgetGroup { + protected Interpolator interpolator; + protected float scale; + + public AnimaWidgetGroup(Position position, Size size) { + super(position, size); + } + + public AnimaWidgetGroup(int x, int y, int width, int height) { + super(new Position(x, y), new Size(width, height)); + } + + @Override + public void updateScreen() { + if (interpolator != null) { + interpolator.update(); + } + super.updateScreen(); + } + + public void maximizeWidget(Consumer callback) { + this.scale = 0; + setVisible(true); + interpolator = new Interpolator(0, 1, 10, Eases.EaseLinear, + value-> scale = value.floatValue(), + value-> { + interpolator = null; + if (callback != null) { + callback.accept(this); + } + }); + interpolator.start(); + } + + public void minimizeWidget(Consumer callback) { + this.scale = 1; + interpolator = new Interpolator(1, 0, 10, Eases.EaseLinear, + value-> scale = value.floatValue(), + value-> { + setVisible(false); + interpolator = null; + if (callback != null) { + callback.accept(this); + } + }); + interpolator.start(); + } + + protected void hookDrawInBackground(int mouseX, int mouseY, float partialTicks, IRenderContext context) { + super.drawInBackground(mouseX, mouseY, partialTicks, context); + } + + protected void hookDrawInForeground(int mouseX, int mouseY) { + super.drawInForeground(mouseX, mouseY); + } + + @Override + public final void drawInForeground(int mouseX, int mouseY) { + if (scale == 0) { + return; + } if (scale != 1) { + GlStateManager.pushMatrix(); + GlStateManager.translate((this.gui.getScreenWidth() - this.gui.getScreenWidth() * scale) / 2, + (this.gui.getScreenHeight() - this.gui.getScreenHeight() * scale) / 2, 0); + GlStateManager.scale(scale, scale, 1); + hookDrawInForeground(0, 0); + GlStateManager.popMatrix(); + } else { + hookDrawInForeground(mouseX, mouseY); + } + } + + @Override + public final void drawInBackground(int mouseX, int mouseY, float partialTicks, IRenderContext context) { + if (scale == 0) { + return; + }if (scale != 1) { + GlStateManager.pushMatrix(); + GlStateManager.translate((this.gui.getScreenWidth() - this.gui.getScreenWidth() * scale) / 2, + (this.gui.getScreenHeight() - this.gui.getScreenHeight() * scale) / 2, 0); + GlStateManager.scale(scale, scale, 1); + hookDrawInBackground(0, 0, partialTicks, context); + GlStateManager.popMatrix(); + } else { + hookDrawInBackground(mouseX, mouseY, partialTicks, context); + } + } +} diff --git a/src/main/java/gregtech/api/terminal/gui/widgets/CircleButtonWidget.java b/src/main/java/gregtech/api/terminal/gui/widgets/CircleButtonWidget.java new file mode 100644 index 00000000000..5e508518c45 --- /dev/null +++ b/src/main/java/gregtech/api/terminal/gui/widgets/CircleButtonWidget.java @@ -0,0 +1,149 @@ +package gregtech.api.terminal.gui.widgets; + +import gregtech.api.gui.IRenderContext; +import gregtech.api.gui.Widget; +import gregtech.api.gui.resources.IGuiTexture; +import gregtech.api.util.Position; +import gregtech.api.util.Size; +import net.minecraft.client.resources.I18n; +import net.minecraft.item.ItemStack; +import net.minecraft.network.PacketBuffer; +import org.lwjgl.input.Mouse; + +import java.awt.*; +import java.util.Collections; +import java.util.function.Consumer; + +public class CircleButtonWidget extends Widget { + protected int border; + protected int hoverTick; + protected boolean isHover; + protected String hoverText; + protected IGuiTexture icon; + protected IGuiTexture hover; + protected final int iconSize; + protected Consumer onPressCallback; + protected final int[] colors = { + new Color(146, 146, 146).getRGB(), + new Color(39, 232, 141).getRGB(), + new Color(255, 255, 255).getRGB(), + }; + + public CircleButtonWidget(int x, int y, int r, int border, int iconSize) { + super(new Position(x - r, y - r), new Size(2 * r, 2 * r)); + this.border = border; + this.iconSize = iconSize; + } + + public CircleButtonWidget(int x, int y) { + this(x, y, 12, 2, 16); + } + + public CircleButtonWidget setIcon(IGuiTexture icon) { + this.icon = icon; + return this; + } + + public CircleButtonWidget setHoverText(String hoverText) { + this.hoverText = hoverText; + return this; + } + + public CircleButtonWidget setColors(int stroke, int strokeAnima, int fill) { + colors[0] = stroke; + colors[1] = strokeAnima; + colors[2] = fill; + return this; + } + + public CircleButtonWidget setStroke(int stroke) { + colors[0] = stroke; + return this; + } + + public CircleButtonWidget setStrokeAnima(int strokeAnima) { + colors[1] = strokeAnima; + return this; + } + + public CircleButtonWidget setFill(int fill) { + colors[2] = fill; + return this; + } + + public CircleButtonWidget setClickListener(Consumer onPressed) { + this.onPressCallback = onPressed; + return this; + } + + public CircleButtonWidget setHoverIcon(IGuiTexture hover) { + this.hover = hover; + return this; + } + + @Override + public void updateScreen() { + if (isHover) { + if (hoverTick < 8) { + hoverTick += 1; + } + } else { + if (hoverTick > 0) { + hoverTick -= 1; + } + } + } + + @Override + public void drawInBackground(int mouseX, int mouseY, float partialTicks, IRenderContext context) { + int r = this.getSize().getHeight() / 2; + int x = this.getPosition().x + r; + int y = this.getPosition().y + r; + int segments = 24; + + drawTorus(x, y, r, r - border, colors[0], segments, 0, segments); + isHover = this.isMouseOverElement(mouseX, mouseY); + if (isHover || hoverTick != 0) { + drawTorus(x, y, r, r - border, colors[1], segments, 0, (int) (segments * ((hoverTick + partialTicks) / 8))); + } + drawCircle(x, y, r - border, colors[2], segments); + if (isHover && hover != null) { + hover.draw(x - iconSize / 2f, y - iconSize / 2f, iconSize, iconSize); + } + if (icon != null) { + icon.draw(x - iconSize / 2f, y - iconSize / 2f, iconSize, iconSize); + } + } + + @Override + public void drawInForeground(int mouseX, int mouseY) { + if (hoverText != null && this.isMouseOverElement(mouseX, mouseY)) { + this.drawHoveringText(ItemStack.EMPTY, Collections.singletonList(I18n.format(hoverText)), 300, mouseX, mouseY); + } + } + + @Override + public boolean mouseClicked(int mouseX, int mouseY, int button) { + if (isMouseOverElement(mouseX, mouseY)) { + ClickData clickData = new ClickData(Mouse.getEventButton(), isShiftDown(), isCtrlDown(), false); + writeClientAction(1, clickData::writeToBuf); + playButtonClickSound(); + if (onPressCallback != null) { + onPressCallback.accept(new ClickData(Mouse.getEventButton(), isShiftDown(), isCtrlDown(), true)); + } + return true; + } + return false; + } + + @Override + public void handleClientAction(int id, PacketBuffer buffer) { + if (id == 1) { + ClickData clickData = ClickData.readFromBuf(buffer); + if (onPressCallback != null) { + onPressCallback.accept(clickData); + } + } + } + +} diff --git a/src/main/java/gregtech/api/terminal/gui/widgets/ColorWidget.java b/src/main/java/gregtech/api/terminal/gui/widgets/ColorWidget.java new file mode 100644 index 00000000000..0dfc53e292f --- /dev/null +++ b/src/main/java/gregtech/api/terminal/gui/widgets/ColorWidget.java @@ -0,0 +1,285 @@ +package gregtech.api.terminal.gui.widgets; + +import gregtech.api.gui.IRenderContext; +import gregtech.api.gui.Widget; +import gregtech.api.gui.resources.ColorRectTexture; +import gregtech.api.gui.resources.IGuiTexture; +import gregtech.api.gui.widgets.TextFieldWidget; +import gregtech.api.gui.widgets.WidgetGroup; +import gregtech.api.util.Position; +import gregtech.api.util.Size; +import net.minecraft.network.PacketBuffer; +import net.minecraft.util.math.MathHelper; + +import java.util.function.Consumer; +import java.util.function.Supplier; + +public class ColorWidget extends WidgetGroup { + private int red = 255; + private int green = 255; + private int blue = 255; + private int alpha = 255; + private Consumer onColorChanged; + private final int barWidth; + private final int barHeight; + private final CircleButtonWidget redButton; + private final CircleButtonWidget greenButton; + private final CircleButtonWidget blueButton; + private final CircleButtonWidget alphaButton; + private int lastMouseX; + private CircleButtonWidget dragged; + private Supplier colorSupplier; + private boolean isClient; + + public ColorWidget(int x, int y, int barWidth, int barHeight){ + super(new Position(x, y), new Size(barWidth + 35, 3 * (barHeight + 5) + 10)); + this.barWidth = barWidth; + this.barHeight= barHeight; + IGuiTexture textFieldBackground = new ColorRectTexture(0x9f000000); + TextFieldWidget redField = new TextFieldWidget(barWidth + 5, 0, 30, barHeight, textFieldBackground, null, null) + .setTextResponder((t) -> { + setRed(t.isEmpty()? 0 : Integer.parseInt(t)); + if (onColorChanged != null) { + onColorChanged.accept(getColor()); + } + writeClientAction(2, buffer -> buffer.writeInt(getColor())); + }, true) + .setTextSupplier(() -> Integer.toString(red), true) + .setValidator(this::checkValid); + TextFieldWidget greenField = new TextFieldWidget(barWidth + 5, barHeight + 5, 30, barHeight, textFieldBackground, null, null) + .setTextResponder((t) -> { + setGreen(t.isEmpty()? 0 : Integer.parseInt(t)); + if (onColorChanged != null) { + onColorChanged.accept(getColor()); + } + writeClientAction(2, buffer -> buffer.writeInt(getColor())); + }, true) + .setTextSupplier(() -> Integer.toString(green), true) + .setValidator(this::checkValid); + TextFieldWidget blueField = new TextFieldWidget(barWidth + 5, (barHeight + 5) * 2, 30, barHeight, textFieldBackground, null, null) + .setTextResponder((t) -> { + setBlue(t.isEmpty()? 0 : Integer.parseInt(t)); + if (onColorChanged != null) { + onColorChanged.accept(getColor()); + } + writeClientAction(2, buffer -> buffer.writeInt(getColor())); + }, true) + .setTextSupplier(() -> Integer.toString(blue), true) + .setValidator(this::checkValid); + TextFieldWidget alphaField = new TextFieldWidget(barWidth + 5, (barHeight + 5) * 3, 30, barHeight, textFieldBackground, null, null) + .setTextResponder((t) -> { + setAlpha(t.isEmpty()? 0 : Integer.parseInt(t)); + if (onColorChanged != null) { + onColorChanged.accept(getColor()); + } + writeClientAction(2, buffer -> buffer.writeInt(getColor())); + }, true) + .setTextSupplier(() -> Integer.toString(alpha), true) + .setValidator(this::checkValid); + this.addWidget(redField); + this.addWidget(greenField); + this.addWidget(blueField); + this.addWidget(alphaField); + redButton = new CircleButtonWidget(barWidth, barHeight / 2, 4, 1, 0).setFill(0xffff0000).setStrokeAnima(-1); + greenButton = new CircleButtonWidget(barWidth, barHeight / 2 + barHeight + 5, 4, 1, 0).setFill(0xff00ff00).setStrokeAnima(-1); + blueButton = new CircleButtonWidget(barWidth, barHeight / 2 + 2 * (barHeight + 5), 4, 1, 0).setFill(0xff0000ff).setStrokeAnima(-1); + alphaButton = new CircleButtonWidget(barWidth, barHeight / 2 + 3 * (barHeight + 5), 4, 1, 0).setFill(-1).setStrokeAnima(-1); + this.addWidget(redButton); + this.addWidget(greenButton); + this.addWidget(blueButton); + this.addWidget(alphaButton); + } + + public ColorWidget setOnColorChanged(Consumer onColorChanged) { + this.onColorChanged = onColorChanged; + return this; + } + + public ColorWidget setColorSupplier(Supplier colorSupplier, boolean isClient) { + this.colorSupplier = colorSupplier; + this.isClient = isClient; + return this; + } + + public int getColor() { + return (alpha << 24) | (red << 16) | (green << 8) | (blue); + } + + @Override + public void detectAndSendChanges() { + super.detectAndSendChanges(); + if (!isClient && colorSupplier!= null) { + int c = colorSupplier.get(); + int r = (c & 0x00ff0000) >>> 16; + int g = (c & 0x0000ff00) >>> 8; + int b = (c & 0x000000ff); + int a = (c & 0xff000000) >>> 24; + if (r != red || g != green || b != blue || a !=alpha) { + setRed(r); + setGreen(g); + setBlue(b); + setAlpha(a); + writeUpdateInfo(2, buffer -> buffer.writeInt(c)); + } + } + } + + @Override + public void updateScreen() { + super.updateScreen(); + if (isClient && colorSupplier!= null) { + int c = colorSupplier.get(); + int r = (c & 0x00ff0000) >>> 16; + int g = (c & 0x0000ff00) >>> 8; + int b = (c & 0x000000ff); + int a = (c & 0xff000000) >>> 24; + if (r != red || g != green || b != blue || a != alpha) { + setRed(r); + setGreen(g); + setBlue(b); + setAlpha(a); + writeClientAction(2, buffer -> buffer.writeInt(c)); + } + } + } + + @Override + public void readUpdateInfo(int id, PacketBuffer buffer) { + handleColor(id, buffer); + } + + private void handleColor(int id, PacketBuffer buffer) { + if (id == 2) { + int c = buffer.readInt(); + int r = (c & 0x00ff0000) >>> 16; + int g = (c & 0x0000ff00) >>> 8; + int b = (c & 0x000000ff); + int a = (c & 0xff000000) >>> 24; + if (r != red || g != green || b != blue || a != alpha) { + setRed(r); + setGreen(g); + setBlue(b); + setAlpha(a); + if (onColorChanged != null) { + onColorChanged.accept(getColor()); + } + } + } + } + + @Override + public void handleClientAction(int id, PacketBuffer buffer) { + handleColor(id, buffer); + } + + private void setRed(int red) { + if (this.red != red) { + this.red = red; + redButton.setSelfPosition(new Position(red * barWidth / 255 - 4, redButton.getSelfPosition().y)); + } + } + + private void setGreen(int green) { + if (this.green != green) { + this.green = green; + greenButton.setSelfPosition(new Position(green * barWidth / 255 - 4, greenButton.getSelfPosition().y)); + } + } + + private void setBlue(int blue) { + if (this.blue != blue) { + this.blue = blue; + blueButton.setSelfPosition(new Position(blue * barWidth / 255 - 4, blueButton.getSelfPosition().y)); + } + } + + private void setAlpha(int alpha) { + if (this.alpha != alpha) { + this.alpha = alpha; + alphaButton.setSelfPosition(new Position(alpha * barWidth / 255 - 4, alphaButton.getSelfPosition().y)); + } + } + + private boolean checkValid(String input) { + if (input.length() > 3) return false; + if (input.isEmpty()) return true; + try { + int value = Integer.parseInt(input); + if(value >= 0 && value <= 255) { + return true; + } + } catch (Exception e) { + return false; + } + return false; + } + + @Override + public void drawInBackground(int mouseX, int mouseY, float partialTicks, IRenderContext context) { + int x = getPosition().x; + int y = getPosition().y; + drawGradientRect(x, y + 2, barWidth, 5, (255 << 24) | (0) | (green << 8) | (blue), (255 << 24) | (255 << 16) | (green << 8) | (blue), true); + drawGradientRect(x, y + barHeight + 5 + 2, barWidth, 5, (255 << 24) | (red << 16) | (0) | (blue), (255 << 24) | (red << 16) | (255 << 8) | (blue), true); + drawGradientRect(x, y + 2 * (barHeight + 5) + 2, barWidth, 5, (255 << 24) | (red << 16) | (green << 8) | (0), (255 << 24) | (red << 16) | (green << 8) | (255), true); + drawGradientRect(x, y + 3 * (barHeight + 5) + 2, barWidth, 5, (0) | (red << 16) | (green << 8) | (blue), (255 << 24) | (red << 16) | (green << 8) | (blue), true); + super.drawInBackground(mouseX, mouseY, partialTicks, context); + } + + @Override + public boolean mouseClicked(int mouseX, int mouseY, int button) { + lastMouseX = mouseX; + dragged = null; + if (redButton.isMouseOverElement(mouseX, mouseY)) { + dragged = redButton; + return true; + } else if (greenButton.isMouseOverElement(mouseX, mouseY)) { + dragged = greenButton; + return true; + } else if (blueButton.isMouseOverElement(mouseX, mouseY)) { + dragged = blueButton; + return true; + } else if (alphaButton.isMouseOverElement(mouseX, mouseY)) { + dragged = alphaButton; + return true; + } + boolean flag = false; + for (int i = widgets.size() - 1; i >= 0; i--) { + Widget widget = widgets.get(i); + if(widget.isVisible() && widget.mouseClicked(mouseX, mouseY, button)) { + flag = true; + } + } + return flag; + } + + @Override + public boolean mouseDragged(int mouseX, int mouseY, int button, long timeDragged) { + int xDelta = mouseX - lastMouseX; + lastMouseX = mouseX; + if (dragged != null) { + int newX = MathHelper.clamp(dragged.getSelfPosition().x + 4 + xDelta, 0, barWidth); + if (dragged == redButton) { + setRed(newX * 255 / barWidth); + } else if (dragged == greenButton) { + setGreen(newX * 255 / barWidth); + } else if (dragged == blueButton) { + setBlue(newX * 255 / barWidth); + } else if (dragged == alphaButton) { + setAlpha(newX * 255 / barWidth); + } + if (onColorChanged != null) { + onColorChanged.accept(getColor()); + } + writeClientAction(2, buffer -> buffer.writeInt(getColor())); + dragged.setSelfPosition(new Position(newX - 4, dragged.getSelfPosition().y)); + return true; + } + return super.mouseDragged(mouseX, mouseY, button, timeDragged); + } + + @Override + public boolean mouseReleased(int mouseX, int mouseY, int button) { + dragged = null; + return super.mouseReleased(mouseX, mouseY, button); + } +} diff --git a/src/main/java/gregtech/api/terminal/gui/widgets/CustomPositionSizeWidget.java b/src/main/java/gregtech/api/terminal/gui/widgets/CustomPositionSizeWidget.java new file mode 100644 index 00000000000..8de8f36477e --- /dev/null +++ b/src/main/java/gregtech/api/terminal/gui/widgets/CustomPositionSizeWidget.java @@ -0,0 +1,211 @@ +package gregtech.api.terminal.gui.widgets; + +import gregtech.api.gui.IRenderContext; +import gregtech.api.gui.Widget; +import gregtech.api.terminal.gui.IDraggable; +import gregtech.api.util.Position; +import gregtech.api.util.Size; + +import java.util.function.BiConsumer; + +public class CustomPositionSizeWidget extends Widget implements IDraggable { + private Widget controlled; + private final int borderColor; + private final int hoverColor; + private final int border; + private boolean dragUp; + private boolean dragDown; + private boolean dragLeft; + private boolean dragRight; + private boolean dragPos; + + private BiConsumer onUpdated; + + + public CustomPositionSizeWidget(Widget controlled, int borderColor, int hoverColor, int border) { + super(controlled.getSelfPosition(), controlled.getSize()); + this.controlled = controlled; + this.borderColor = borderColor; + this.hoverColor = hoverColor; + this.border = border; + } + + public CustomPositionSizeWidget(int borderColor, int hoverColor, int border) { + super(Position.ORIGIN, Size.ZERO); + this.borderColor = borderColor; + this.hoverColor = hoverColor; + this.border = border; + } + + public CustomPositionSizeWidget setControlled(Widget controlled) { + this.controlled = controlled; + if (controlled != null) { + this.setSelfPosition(controlled.getSelfPosition()); + this.setSize(controlled.getSize()); + } + return this; + } + + public Widget getControlled() { + return controlled; + } + + public CustomPositionSizeWidget setOnUpdated(BiConsumer onUpdated) { + this.onUpdated = onUpdated; + return this; + } + + @Override + public void updateScreen() { + if (controlled != null) { + Position pos = controlled.getSelfPosition(); + Size size = controlled.getSize(); + if (!this.getSelfPosition().equals(pos)) { + this.setSelfPosition(pos); + } + if (this.getSize().equals(size)) { + this.setSize(size); + } + } + } + + private boolean hoverUp(int x, int y, int width, int height, int mouseX, int mouseY) { + return isMouseOver(x, y, width / 5, border, mouseX, mouseY) || + isMouseOver(x + width * 2 / 5, y, width / 5, border, mouseX, mouseY) || + isMouseOver(x + width * 4 / 5, y, width / 5, border, mouseX, mouseY) || + isMouseOver(x, y, border, height / 5, mouseX, mouseY) || + isMouseOver(x + width - border, y, border, height / 5, mouseX, mouseY); + } + + private boolean hoverDown(int x, int y, int width, int height, int mouseX, int mouseY) { + return isMouseOver(x, y + height - border, width / 5, border, mouseX, mouseY) || + isMouseOver(x + width * 2 / 5, y + height - border, width / 5, border, mouseX, mouseY) || + isMouseOver(x + width * 4 / 5, y + height - border, width / 5, border, mouseX, mouseY) || + isMouseOver(x, y + height * 4 / 5, border, height / 5, mouseX, mouseY) || + isMouseOver(x + width - border, y + height * 4 / 5, border, height / 5, mouseX, mouseY); + } + + private boolean hoverLeft(int x, int y, int width, int height, int mouseX, int mouseY) { + return isMouseOver(x, y, border, height / 5, mouseX, mouseY) || + isMouseOver(x, y + height * 2 / 5, border, height / 5, mouseX, mouseY) || + isMouseOver(x, y + height * 4 / 5, border, height / 5, mouseX, mouseY) || + isMouseOver(x, y, width / 5, border, mouseX, mouseY) || + isMouseOver(x, y + height - border, width / 5, border, mouseX, mouseY); + } + + private boolean hoverRight(int x, int y, int width, int height, int mouseX, int mouseY) { + return isMouseOver(x + width - border, y, border, height / 5, mouseX, mouseY) || + isMouseOver(x + width - border, y + height * 2 / 5, border, height / 5, mouseX, mouseY) || + isMouseOver(x + width - border, y + height * 4 / 5, border, height / 5, mouseX, mouseY) || + isMouseOver(x + width * 4 / 5, y, width / 5, border, mouseX, mouseY) || + isMouseOver(x + width * 4 / 5, y + height - border, width / 5, border, mouseX, mouseY); + } + + @Override + public void drawInBackground(int mouseX, int mouseY, float partialTicks, IRenderContext context) { + if (controlled == null) return; + int x = controlled.getPosition().x; + int y = controlled.getPosition().y; + int width = controlled.getSize().width; + int height = controlled.getSize().height; + + boolean hoverUp = false; + boolean hoverDown = false; + boolean hoverLeft = false; + boolean hoverRight = false; + // UP + if (dragUp || hoverUp(x, y, width, height, mouseX, mouseY)) { + hoverUp = true; + } + if (dragDown || hoverDown(x, y, width, height, mouseX, mouseY)) { + hoverDown = true; + } + if (dragLeft || hoverLeft(x, y, width, height, mouseX, mouseY)) { + hoverLeft = true; + } + if (dragRight || hoverRight(x, y, width, height, mouseX, mouseY)) { + hoverRight = true; + } + // UP + drawSolidRect(x, y, width / 5, border, hoverUp && !hoverRight ? hoverColor : borderColor); + drawSolidRect(x + width * 2 / 5, y, width / 5, border, hoverUp && !hoverLeft && !hoverRight ? hoverColor : borderColor); + drawSolidRect(x + width * 4 / 5, y, width / 5, border, hoverUp && !hoverLeft ? hoverColor : borderColor); + // DOWN + drawSolidRect(x, y + height - border, width / 5, border, hoverDown && !hoverRight ? hoverColor : borderColor); + drawSolidRect(x + width * 2 / 5, y + height - border, width / 5, border, hoverDown && !hoverLeft && !hoverRight ? hoverColor : borderColor); + drawSolidRect(x + width * 4 / 5, y + height - border, width / 5, border, hoverDown && !hoverLeft ? hoverColor : borderColor); + // LEFT + drawSolidRect(x, y, border, height / 5, hoverLeft && !hoverDown ? hoverColor : borderColor); + drawSolidRect(x, y + height * 2 / 5, border, height / 5, hoverLeft && !hoverDown && !hoverUp ? hoverColor : borderColor); + drawSolidRect(x, y + height * 4 / 5, border, height / 5, hoverLeft && !hoverUp ? hoverColor : borderColor); + // RIGHT + drawSolidRect(x + width - border, y, border, height / 5, hoverRight && !hoverDown ? hoverColor : borderColor); + drawSolidRect(x + width - border, y + height * 2 / 5, border, height / 5, hoverRight && !hoverDown && !hoverUp ? hoverColor : borderColor); + drawSolidRect(x + width - border, y + height * 4 / 5, border, height / 5, hoverRight && !hoverUp ? hoverColor : borderColor); + } + + @Override + public boolean allowDrag(int mouseX, int mouseY, int button) { + if (controlled == null || !isActive()) return false; + int x = controlled.getPosition().x; + int y = controlled.getPosition().y; + int width = controlled.getSize().width; + int height = controlled.getSize().height; + if (isMouseOver(x, y, width, height, mouseX, mouseY)) { + // UP + dragUp = hoverUp(x, y, width, height, mouseX, mouseY); + // DOWN + dragDown = hoverDown(x, y, width, height, mouseX, mouseY); + // LEFT + dragLeft = hoverLeft(x, y, width, height, mouseX, mouseY); + // RIGHT + dragRight = hoverRight(x, y, width, height, mouseX, mouseY); + dragPos = !dragUp && !dragDown && !dragLeft && !dragRight; + return true; + } + return false; + } + + @Override + public boolean dragging(int mouseX, int mouseY, int deltaX, int deltaY) { + if (controlled == null || !isActive()) return false; + int width = controlled.getSize().width; + int height = controlled.getSize().height; + int addX = 0, addY = 0; + if (!dragPos) { + if (dragUp) { + addY = deltaY; + height = Math.max(1, height - deltaY); + } + if (dragDown) { + height = Math.max(1, height + deltaY); + } + if (dragLeft) { + addX = deltaX; + width = Math.max(1, width - deltaX); + } + if (dragRight) { + width = Math.max(1, width + deltaX); + } + controlled.addSelfPosition(addX, addY); + controlled.setSize(new Size(width, height)); + } else { + controlled.addSelfPosition(deltaX, deltaY); + } + if (onUpdated != null) { + onUpdated.accept(controlled.getSelfPosition(), controlled.getSize()); + } + this.setSelfPosition(controlled.getSelfPosition()); + this.setSize(controlled.getSize()); + return false; + } + + @Override + public void endDrag(int mouseX, int mouseY) { + dragDown = false; + dragUp = false; + dragLeft = false; + dragRight = false; + dragPos = false; + } +} diff --git a/src/main/java/gregtech/api/terminal/gui/widgets/DraggableScrollableWidgetGroup.java b/src/main/java/gregtech/api/terminal/gui/widgets/DraggableScrollableWidgetGroup.java new file mode 100644 index 00000000000..6d28f4efb82 --- /dev/null +++ b/src/main/java/gregtech/api/terminal/gui/widgets/DraggableScrollableWidgetGroup.java @@ -0,0 +1,351 @@ +package gregtech.api.terminal.gui.widgets; + +import gregtech.api.gui.IRenderContext; +import gregtech.api.gui.Widget; +import gregtech.api.gui.resources.IGuiTexture; +import gregtech.api.gui.widgets.WidgetGroup; +import gregtech.api.terminal.gui.IDraggable; +import gregtech.api.util.Position; +import gregtech.api.util.RenderUtil; +import gregtech.api.util.Size; +import net.minecraft.util.math.MathHelper; + +public class DraggableScrollableWidgetGroup extends WidgetGroup { + protected int scrollXOffset; + protected int scrollYOffset; + protected int xBarHeight; + protected int yBarWidth; + protected boolean draggable; + protected IGuiTexture background; + protected int maxHeight; + protected int maxWidth; + protected IGuiTexture xBarB; + protected IGuiTexture xBarF; + protected IGuiTexture yBarB; + protected IGuiTexture yBarF; + protected boolean focus; + protected Widget draggedWidget; + + private int lastMouseX; + private int lastMouseY; + private boolean draggedPanel; + private boolean draggedOnXScrollBar; + private boolean draggedOnYScrollBar; + + + public DraggableScrollableWidgetGroup(int x, int y, int width, int height) { + super(new Position(x, y), new Size(width, height)); + maxHeight = height; + maxWidth = width; + } + + public DraggableScrollableWidgetGroup setXScrollBarHeight(int xBar) { + this.xBarHeight = xBar; + return this; + } + + public DraggableScrollableWidgetGroup setYScrollBarWidth(int yBar) { + this.yBarWidth = yBar; + return this; + } + + public DraggableScrollableWidgetGroup setDraggable(boolean draggable) { + this.draggable = draggable; + return this; + } + + public DraggableScrollableWidgetGroup setBackground(IGuiTexture background) { + this.background = background; + return this; + } + + public DraggableScrollableWidgetGroup setXBarStyle(IGuiTexture background, IGuiTexture bar) { + this.xBarB = background; + this.xBarF = bar; + return this; + } + + public DraggableScrollableWidgetGroup setYBarStyle(IGuiTexture background, IGuiTexture bar) { + this.yBarB = background; + this.yBarF = bar; + return this; + } + + public int getScrollYOffset() { + return scrollYOffset; + } + + public int getScrollXOffset() { + return scrollXOffset; + } + + @Override + public void addWidget(Widget widget) { + maxHeight = Math.max(maxHeight, widget.getSize().height + widget.getSelfPosition().y); + maxWidth = Math.max(maxWidth, widget.getSize().width + widget.getSelfPosition().x); + widget.addSelfPosition(- scrollXOffset, - scrollYOffset); + super.addWidget(widget); + } + + @Override + public void removeWidget(Widget widget) { + super.removeWidget(widget); + computeMax(); + } + + @Override + public void clearAllWidgets() { + super.clearAllWidgets(); + maxHeight = getSize().height; + maxWidth = getSize().width; + scrollXOffset = 0; + scrollYOffset = 0; + } + + @Override + public void setSize(Size size) { + super.setSize(size); + computeMax(); + } + + protected void computeMax() { + int mh = 0; + int mw = 0; + for (Widget widget : widgets) { + mh = Math.max(mh, widget.getSize().height + widget.getSelfPosition().y + scrollYOffset); + mw = Math.max(mw, widget.getSize().width + widget.getSelfPosition().x + scrollXOffset); + } + int offsetY = 0; + int offsetX = 0; + if (mh > getSize().height) { + offsetY = maxHeight - mh; + maxHeight = mh; + if (scrollYOffset - offsetY < 0) { + offsetY = scrollYOffset; + } + scrollYOffset -= offsetY; + } else if (mh < getSize().height) { + offsetY = maxHeight - getSize().height; + maxHeight = getSize().height; + if (scrollYOffset - offsetY < 0) { + offsetY = scrollYOffset; + } + scrollYOffset -= offsetY; + } + if (mw > getSize().width) { + offsetX = maxWidth - mw; + maxWidth = mw; + if (scrollXOffset - offsetX < 0) { + offsetX = scrollXOffset; + } + scrollXOffset -= offsetX; + }else if (mw < getSize().width) { + offsetX = maxWidth - getSize().width; + maxWidth = getSize().width; + if (scrollXOffset - offsetX < 0) { + offsetX = scrollXOffset; + } + scrollXOffset -= offsetX; + } + if (offsetX != 0 || offsetY != 0) { + for (Widget widget : widgets) { + Position newPos = widget.addSelfPosition(offsetX, offsetY); + widget.setVisible(newPos.x < getSize().width - yBarWidth && newPos.x + widget.getSize().width > 0); + widget.setVisible(newPos.y < getSize().height - xBarHeight && newPos.y + widget.getSize().height > 0); + } + } + } + + protected int getMaxHeight() { + return maxHeight + xBarHeight; + } + + protected int getMaxWidth() { + return maxWidth + yBarWidth; + } + + public int getWidgetBottomHeight() { + int y = 0; + for (Widget widget : widgets) { + y = Math.max(y, widget.getSize().height + widget.getSelfPosition().y); + } + return y; + } + + protected void setScrollXOffset(int scrollXOffset) { + if (scrollXOffset == this.scrollXOffset) return; + int offset = scrollXOffset - this.scrollXOffset; + this.scrollXOffset = scrollXOffset; + for (Widget widget : widgets) { + Position newPos = widget.addSelfPosition( - offset, 0); + widget.setVisible(newPos.x < getSize().width - yBarWidth && newPos.x + widget.getSize().width > 0); + } + } + + protected void setScrollYOffset(int scrollYOffset) { + if (scrollYOffset == this.scrollYOffset) return; + if (scrollYOffset < 0) scrollYOffset = 0; + int offset = scrollYOffset - this.scrollYOffset; + this.scrollYOffset = scrollYOffset; + for (Widget widget : widgets) { + Position newPos = widget.addSelfPosition(0, - offset); + widget.setVisible(newPos.y < getSize().height - xBarHeight && newPos.y + widget.getSize().height > 0); + } + } + + private boolean isOnXScrollPane(int mouseX, int mouseY) { + Position pos = getPosition(); + Size size = getSize(); + return isMouseOver(pos.x, pos.y + size.height - xBarHeight, size.width, xBarHeight, mouseX, mouseY); + } + + private boolean isOnYScrollPane(int mouseX, int mouseY) { + Position pos = getPosition(); + Size size = getSize(); + return isMouseOver(pos.x + size.width - yBarWidth, pos.y, yBarWidth, size.height, mouseX, mouseY); + } + + protected boolean hookDrawInBackground(int mouseX, int mouseY, float partialTicks, IRenderContext context) { + return false; + } + + @Override + public void drawInBackground(int mouseX, int mouseY, float partialTicks, IRenderContext context) { + int x = getPosition().x; + int y = getPosition().y; + int width = getSize().width; + int height = getSize().height; + if (background != null) { + background.draw(x, y, width, height); + } + RenderUtil.useScissor(x, y, width - yBarWidth, height - xBarHeight, ()->{ + if(!hookDrawInBackground(mouseX, mouseY, partialTicks, context)) { + super.drawInBackground(mouseX, mouseY, partialTicks, context); + } + }); + if (xBarHeight > 0) { + if (xBarB != null) { + xBarB.draw(x, y - xBarHeight, width, xBarHeight); + } + if (xBarF != null) { + int barWidth = (int) (width * 1.0f / getMaxWidth() * width); + xBarF.draw(x + scrollXOffset * width * 1.0f / getMaxWidth(), y + height - xBarHeight, barWidth, xBarHeight); + } + } + if (yBarWidth > 0) { + if (yBarB != null) { + yBarB.draw(x + width - yBarWidth, y, yBarWidth, height); + } + if (yBarF != null) { + int barHeight = (int) (height * 1.0f / getMaxHeight() * height); + yBarF.draw(x + width - yBarWidth, y + scrollYOffset * height * 1.0f / getMaxHeight(), yBarWidth, barHeight); + } + } + } + + @Override + public boolean mouseClicked(int mouseX, int mouseY, int button) { + lastMouseX = mouseX; + lastMouseY = mouseY; + if (xBarHeight > 0 && isOnXScrollPane(mouseX, mouseY)) { + this.draggedOnXScrollBar = true; + focus = true; + return true; + } + else if (yBarWidth > 0 && isOnYScrollPane(mouseX, mouseY)) { + this.draggedOnYScrollBar = true; + focus = true; + return true; + } else if(isMouseOverElement(mouseX, mouseY)){ + focus = true; + if (checkClickedDragged(mouseX, mouseY, button)) { + return true; + } + if (draggable) { + this.draggedPanel = true; + return true; + } + return false; + } else if (checkClickedDragged(mouseX, mouseY, button)) { + return true; + } + focus = false; + return false; + } + + private boolean checkClickedDragged(int mouseX, int mouseY, int button) { + draggedWidget = null; + for (int i = widgets.size() - 1; i >= 0; i--) { + Widget widget = widgets.get(i); + if(widget.isVisible()) { + if(widget.mouseClicked(mouseX, mouseY, button)) { + return true; + } else if (widget instanceof IDraggable && ((IDraggable) widget).allowDrag(mouseX, mouseY, button)) { + draggedWidget = widget; + ((IDraggable) widget).startDrag(mouseX, mouseY); + return true; + } + } + } + return false; + } + + @Override + public boolean mouseWheelMove(int mouseX, int mouseY, int wheelDelta) { + if (this.isMouseOverElement(mouseX, mouseY, true)) { + if (super.mouseWheelMove(mouseX, mouseY, wheelDelta)) { + return true; + } + int moveDelta = -MathHelper.clamp(wheelDelta, -1, 1) * 5; + if (getMaxHeight() - getSize().height > 0 || scrollYOffset > getMaxHeight() - getSize().height) { + setScrollYOffset(MathHelper.clamp(scrollYOffset + moveDelta, 0, getMaxHeight() - getSize().height)); + } + return true; + } + focus = false; + return false; + } + + @Override + public boolean mouseDragged(int mouseX, int mouseY, int button, long timeDragged) { + int deltaX = mouseX - lastMouseX; + int deltaY = mouseY - lastMouseY; + lastMouseX = mouseX; + lastMouseY = mouseY; + if (draggedOnXScrollBar && (getMaxWidth() - getSize().width > 0 || scrollYOffset > getMaxWidth() - getSize().width)) { + setScrollXOffset(MathHelper.clamp(scrollXOffset + deltaX * getMaxWidth() / getSize().width, 0, getMaxWidth() - getSize().width)); + return true; + } else if (draggedOnYScrollBar && (getMaxHeight() - getSize().height > 0 || scrollYOffset > getMaxHeight() - getSize().height)) { + setScrollYOffset(MathHelper.clamp(scrollYOffset + deltaY * getMaxHeight() / getSize().height, 0, getMaxHeight() - getSize().height)); + return true; + } else if (draggedWidget != null) { + if (((IDraggable)draggedWidget).dragging(mouseX, mouseY, deltaX, deltaY)) { + draggedWidget.addSelfPosition(deltaX, deltaY); + } + computeMax(); + return true; + } else if (draggedPanel) { + setScrollXOffset(MathHelper.clamp(scrollXOffset - deltaX, 0, Math.max(getMaxWidth() - yBarWidth - getSize().width, 0))); + setScrollYOffset(MathHelper.clamp(scrollYOffset - deltaY, 0, Math.max(getMaxHeight() - xBarHeight - getSize().height, 0))); + return true; + } + return super.mouseDragged(mouseX, mouseY, button, timeDragged); + } + + @Override + public boolean mouseReleased(int mouseX, int mouseY, int button) { + if (draggedOnXScrollBar) { + draggedOnXScrollBar = false; + } else if (draggedOnYScrollBar) { + draggedOnYScrollBar = false; + } else if (draggedWidget != null) { + ((IDraggable)draggedWidget).endDrag(mouseX, mouseY); + draggedWidget = null; + } else if (draggedPanel) { + draggedPanel = false; + } else { + return super.mouseReleased(mouseX, mouseY, button); + } + return true; + } +} diff --git a/src/main/java/gregtech/api/terminal/gui/widgets/RectButtonWidget.java b/src/main/java/gregtech/api/terminal/gui/widgets/RectButtonWidget.java new file mode 100644 index 00000000000..6dde56eb33e --- /dev/null +++ b/src/main/java/gregtech/api/terminal/gui/widgets/RectButtonWidget.java @@ -0,0 +1,132 @@ +package gregtech.api.terminal.gui.widgets; + +import gregtech.api.gui.IRenderContext; +import gregtech.api.gui.resources.IGuiTexture; +import gregtech.api.util.Position; +import gregtech.api.util.Size; +import net.minecraft.network.PacketBuffer; +import org.lwjgl.input.Mouse; + +import java.util.function.BiConsumer; +import java.util.function.Supplier; + +public class RectButtonWidget extends CircleButtonWidget{ + private IGuiTexture pressedIcon; + private BiConsumer onPressed; + private boolean isPressed; + private Supplier supplier; + private boolean isClient; + + + public RectButtonWidget(int x, int y, int width, int height) { + this(x, y, width, height,2); + } + + public RectButtonWidget(int x, int y, int width, int height, int border) { + super(x, y); + setSelfPosition(new Position(x, y)); + setSize(new Size(width, height)); + this.border = border; + } + + public RectButtonWidget setToggleButton(IGuiTexture pressedIcon, BiConsumer onPressed) { + this.pressedIcon = pressedIcon; + this.onPressed = onPressed; + return this; + } + + public RectButtonWidget setValueSupplier(boolean isClient, Supplier supplier) { + this.isClient = isClient; + this.supplier = supplier; + return this; + } + + @Override + public void updateScreen() { + super.updateScreen(); + if (isClient && supplier != null) { + isPressed = supplier.get(); + } + } + + @Override + public void detectAndSendChanges() { + if (!isClient && supplier != null) { + if(supplier.get() != isPressed) { + isPressed = !isPressed; + writeUpdateInfo(1, buffer -> buffer.writeBoolean(isPressed)); + } + } + } + + @Override + public void readUpdateInfo(int id, PacketBuffer buffer) { + if (id == 1) { + isPressed = buffer.readBoolean(); + } + } + + @Override + public boolean mouseClicked(int mouseX, int mouseY, int button) { + if (onPressed == null) { + return super.mouseClicked(mouseX, mouseY, button); + } else { + if (isMouseOverElement(mouseX, mouseY)) { + isPressed = !isPressed; + ClickData clickData = new ClickData(Mouse.getEventButton(), isShiftDown(), isCtrlDown(), false); + writeClientAction(1, buffer -> { + clickData.writeToBuf(buffer); + buffer.writeBoolean(isPressed); + }); + playButtonClickSound(); + onPressed.accept(new ClickData(Mouse.getEventButton(), isShiftDown(), isCtrlDown(), true), isPressed); + return true; + } + return false; + } + } + + @Override + public void handleClientAction(int id, PacketBuffer buffer) { + if (onPressed == null) { + super.handleClientAction(id, buffer); + } else { + if (id == 1) { + ClickData clickData = ClickData.readFromBuf(buffer); + isPressed = buffer.readBoolean(); + if (onPressCallback != null) { + onPressed.accept(clickData, isPressed); + } + } + } + } + + @Override + public void drawInBackground(int mouseX, int mouseY, float partialTicks, IRenderContext context) { + int x = this.getPosition().x; + int y = this.getPosition().y; + int width = this.getSize().width; + int height = this.getSize().height; + + drawSolidRect(x, y, width, height, colors[0]); + isHover = this.isMouseOverElement(mouseX, mouseY); + if (isHover || hoverTick != 0) { + float per = Math. min ((hoverTick + partialTicks) / 8, 1); + drawSolidRect(x, y, (int) (width * per), border, colors[1]); + drawSolidRect(x + width - border, y, border, (int) (height * per), colors[1]); + drawSolidRect((int) ((1 - per) * width) + x, y + height - border, (int) (width * per), border, colors[1]); + drawSolidRect(x, (int) ((1 - per) * height) + y, border, (int) (height * per), colors[1]); + } + drawSolidRect(x + border, y + border, width - 2 * border, height - 2 * border, colors[2]); + if (isHover && hover != null) { + hover.draw(x + border, y + border, width - 2 * border, height - 2 * border); + } + if (isPressed) { + if (pressedIcon != null) { + pressedIcon.draw(x + border, y + border, width - 2 * border, height - 2 * border); + } + } else if (icon != null) { + icon.draw(x + border, y + border, width - 2 * border, height - 2 * border); + } + } +} diff --git a/src/main/java/gregtech/api/terminal/gui/widgets/SelectorWidget.java b/src/main/java/gregtech/api/terminal/gui/widgets/SelectorWidget.java new file mode 100644 index 00000000000..3b22e532f8e --- /dev/null +++ b/src/main/java/gregtech/api/terminal/gui/widgets/SelectorWidget.java @@ -0,0 +1,120 @@ +package gregtech.api.terminal.gui.widgets; + +import gregtech.api.gui.resources.IGuiTexture; +import gregtech.api.gui.widgets.SimpleTextWidget; +import gregtech.api.gui.widgets.WidgetGroup; +import gregtech.api.util.Position; +import gregtech.api.util.Size; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.network.PacketBuffer; + +import java.util.List; +import java.util.function.Consumer; +import java.util.function.Supplier; + +public class SelectorWidget extends WidgetGroup { + protected RectButtonWidget button; + protected List candidates; + protected boolean isShow; + private IGuiTexture background; + private Consumer onChanged; + private boolean isUp; + private final int fontColor; + + public SelectorWidget(int x, int y, int width, int height, List candidates, int fontColor, Supplier supplier, boolean isClient) { + super(new Position(x, y), new Size(width, height)); + this.button = new RectButtonWidget(0,0,width,height); + this.candidates = candidates; + this.fontColor = fontColor; + button.setClickListener(d->isShow = !isShow); + this.addWidget(button); + this.addWidget(new SimpleTextWidget(width / 2, height / 2, "", fontColor, supplier, isClient)); + } + + public SelectorWidget setIsUp(boolean isUp) { + this.isUp = isUp; + return this; + } + + public SelectorWidget setOnChanged(Consumer onChanged) { + this.onChanged = onChanged; + return this; + } + + public SelectorWidget setColors(int stroke, int anima, int fill) { + button.setColors(stroke, anima, fill); + return this; + } + + public SelectorWidget setButtonBackground(IGuiTexture guiTexture) { + button.setIcon(guiTexture); + return this; + } + + public SelectorWidget setBackground(IGuiTexture background) { + this.background = background; + return this; + } + + @Override + public void drawInForeground(int mouseX, int mouseY) { + super.drawInForeground(mouseX, mouseY); + if(isShow) { + int x = getPosition().x; + int width = getSize().width; + int height = getSize().height; + int y = (isUp ? -candidates.size() : 1) * height + getPosition().y; + FontRenderer fontRenderer = Minecraft.getMinecraft().fontRenderer; + for (String candidate : candidates) { + if (background != null) { + background.draw(x, y, width, height); + } else { + drawSolidRect(x, y, width, height, 0xAA000000); + } + fontRenderer.drawString(candidate, x + 4, y + (height - fontRenderer.FONT_HEIGHT) / 2 + 1, fontColor); + y += height; + } + y = (isUp ? -candidates.size() : 1) * height + getPosition().y; + for (String ignored : candidates) { + if (isMouseOver(x, y, width, height, mouseX, mouseY)) { + drawBorder(x, y, width, height, -1, 1); + } + y += height; + } + } + } + + @Override + public boolean mouseClicked(int mouseX, int mouseY, int button) { + if (isShow) { + int x = getPosition().x; + int width = getSize().width; + int height = getSize().height; + int y = (isUp ? -candidates.size() : 1) * height + getPosition().y; + for (String candidate : candidates) { + if (isMouseOver(x, y, width, height, mouseX, mouseY)) { + if (onChanged != null) { + onChanged.accept(candidate); + } + writeClientAction(2, buffer -> buffer.writeString(candidate)); + isShow = false; + return true; + } + y += height; + } + } + isShow = false; + return super.mouseClicked(mouseX, mouseY, button); + } + + @Override + public void handleClientAction(int id, PacketBuffer buffer) { + super.handleClientAction(id, buffer); + if (id == 2) { + if (onChanged != null) { + onChanged.accept(buffer.readString(Short.MAX_VALUE)); + } + } + } +} diff --git a/src/main/java/gregtech/api/terminal/gui/widgets/TextEditorWidget.java b/src/main/java/gregtech/api/terminal/gui/widgets/TextEditorWidget.java new file mode 100644 index 00000000000..d2db1989d4f --- /dev/null +++ b/src/main/java/gregtech/api/terminal/gui/widgets/TextEditorWidget.java @@ -0,0 +1,325 @@ +package gregtech.api.terminal.gui.widgets; + +import gregtech.api.gui.IRenderContext; +import gregtech.api.gui.resources.IGuiTexture; +import gregtech.api.gui.resources.TextureArea; +import gregtech.api.gui.widgets.WidgetGroup; +import gregtech.api.util.Position; +import gregtech.api.util.Size; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.util.ChatAllowedCharacters; +import net.minecraft.util.text.TextFormatting; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +import java.util.*; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.Consumer; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class TextEditorWidget extends WidgetGroup { + private static final TextureArea PALETTE = TextureArea.fullImage("textures/gui/widget/palette.png"); + private static final TextureArea STYLE = TextureArea.fullImage("textures/gui/widget/formatting.png"); + private final TextPanelWidget textPanelWidget; + + public TextEditorWidget(int x, int y, int width, int height,Consumer stringUpdate, boolean allowToolBox) { + super(new Position(x, y), new Size(Math.max(width, allowToolBox ? 80 : width), Math.max(height, allowToolBox ? 32 : height))); + textPanelWidget = new TextPanelWidget(0, 32, Math.max(width, allowToolBox ? 80 : width), Math.max(height, allowToolBox ? 32 : height) - 32, stringUpdate); + this.addWidget(textPanelWidget); + if (allowToolBox) { + initToolBox(); + } + } + + public TextEditorWidget setBackground(IGuiTexture background) { + textPanelWidget.setBackground(background); + return this; + } + + public TextEditorWidget setContent(String content) { + textPanelWidget.pageSetCurrent(content); + return this; + } + + @Override + public void setActive(boolean active) { + super.setActive(active); + textPanelWidget.setActive(active); + } + + private void initToolBox() { + TextFormatting[] formatting = TextFormatting.values(); + // palette + for (int y = 0; y < 4; y++) { + for (int x = 0; x < 4; x++) { + TextFormatting colorFormatting = formatting[y * 4 + x]; + this.addWidget(new RectButtonWidget(x * 8, y * 8, 8, 8, 1) + .setToggleButton(PALETTE.getSubArea(0.5 + x * 0.125, y * 0.25, 0.125, 0.25), + (cd, pressed)-> { + if (pressed) { + textPanelWidget.addFormatting(colorFormatting); + } else { + textPanelWidget.removeFormatting(colorFormatting); + } + }) + .setValueSupplier(true, ()-> colorFormatting == textPanelWidget.getFrontColorFormatting()) + .setIcon(PALETTE.getSubArea(x * 0.125, y * 0.25, 0.125, 0.25)) + .setColors(0, -1, 0)); + } + } + // style + for (int y = 0; y < 2; y++) { + for (int x = 0; x < 3; x++) { + TextFormatting styleFormatting = formatting[16 + y * 3 + x]; + if (styleFormatting == TextFormatting.RESET) return; + this.addWidget(new RectButtonWidget(x * 16 + 32, y * 16, 16, 16, 1) + .setToggleButton(STYLE.getSubArea(0.5 + x * 1.0 / 6, y * 0.5, 1.0 / 6, 0.5), + (cd, pressed)-> { + if (pressed) { + textPanelWidget.addFormatting(styleFormatting); + } else { + textPanelWidget.removeFormatting(styleFormatting); + } + }) + .setValueSupplier(true, ()-> textPanelWidget.getFrontStyleFormatting().contains(styleFormatting)) + .setIcon(STYLE.getSubArea(x * 1.0 / 6, y * 0.5, 1.0 / 6, 0.5)) + .setColors(0, -1, 0)); + } + } + } + + private static class TextPanelWidget extends DraggableScrollableWidgetGroup { + public final static int SPACE = 0; + public int updateCount; + public String content; + public int textHeight; + public final Consumer stringUpdate; + public TextFormatting frontColor; + public List frontStyle; + + private static final char SECTION_SIGN = '\u00A7'; + + @SideOnly(Side.CLIENT) + public FontRenderer fontRenderer; + @SideOnly(Side.CLIENT) + private static final Pattern R_CODE_PATTERN = Pattern.compile("(?i)" + SECTION_SIGN + "[R]"); + @SideOnly(Side.CLIENT) + private static final Pattern COLOR_CODE_PATTERN = Pattern.compile("(?i)" + SECTION_SIGN + "[0-9A-F]"); + + + public TextPanelWidget(int x, int y, int width, int height, Consumer stringUpdate) { + super(x, y, width, height); + this.stringUpdate = stringUpdate; + this.content = ""; + if (isClientSide()) { + fontRenderer = Minecraft.getMinecraft().fontRenderer; + textHeight = fontRenderer.getWordWrappedHeight(content, width - yBarWidth); + frontColor = null; + frontStyle = new ArrayList<>(); + } + } + + @Override + public int getMaxHeight() { + return textHeight + SPACE + xBarHeight; + } + + public void updateScreen() { + super.updateScreen(); + ++this.updateCount; + } + + @Override + public boolean keyTyped(char typedChar, int keyCode) { + if(!focus || !isActive()) return false; + if (GuiScreen.isKeyComboCtrlV(keyCode)) { + this.pageInsertIntoCurrent(GuiScreen.getClipboardString()); + findFrontFormatting(); + } else { + switch(keyCode) { + case 14: + if (!content.isEmpty()) { + this.pageSetCurrent(content.substring(0, content.length() - 1)); + } + break; + case 28: + case 156: + this.pageInsertIntoCurrent("\n"); + break; + default: + if (ChatAllowedCharacters.isAllowedCharacter(typedChar)) { + this.pageInsertIntoCurrent(Character.toString(typedChar)); + } + } + } + if (getMaxHeight() > getSize().height) { + setScrollYOffset(getMaxHeight() - getSize().height); + } else { + setScrollYOffset(0); + } + return true; + } + + private static TextFormatting lookAheadChars(final String content, int index) { + if (index > 1 && content.charAt(index - 2) == SECTION_SIGN) { + int t = content.charAt(index - 1); + if ('0' <= t && t <= '9'){ + return TextFormatting.values()[t - '0']; + } else if ('a' <= t && t <= 'f'){ + return TextFormatting.values()[t - 'a' + 10]; + } else if ('k' <= t && t <= 'o') { + return TextFormatting.values()[t - 'k' + 16]; + } else if (t == 'r') { + return TextFormatting.values()[21]; + } + } + return null; + } + + public static String cleanUpFormatting(final String content) { + Set removed = new HashSet<>(); + Matcher marcher = R_CODE_PATTERN.matcher(content); + while (marcher.find()) { + int index = marcher.start(); + while (index > 1) { + TextFormatting ahead = lookAheadChars(content, index); + if (ahead != null) { + removed.add(index - 2); + } else { + break; + } + index -= 2; + } + } + marcher = COLOR_CODE_PATTERN.matcher(content); + while (marcher.find()) { + int index = marcher.start(); + while (index > 1) { + TextFormatting ahead = lookAheadChars(content, index); + if (ahead == null) { + break; + } else if (TextFormatting.RESET != ahead){ + if (!removed.add(index - 2)) { + break; + } + } else { + break; + } + index -= 2; + } + } + StringBuilder builder = new StringBuilder(); + AtomicInteger start = new AtomicInteger(); + removed.stream().sorted().forEach(remove->{ + builder.append(content, start.get(), remove); + start.set(remove + 2); + }); + builder.append(content, start.get(), content.length()); + return builder.toString(); + } + + private void findFrontFormatting() { + int lastReset = content.lastIndexOf(SECTION_SIGN + "r"); + int lastColor = -1; + frontColor = null; + frontStyle.clear(); + for (TextFormatting value : TextFormatting.values()) { + int index = content.lastIndexOf(value.toString()); + if (index > lastReset) { + if (value.isColor()) { + if (index > lastColor) { + lastColor = index; + frontColor = value; + } + } else if (value.isFancyStyling() && index > lastColor) { + frontStyle.add(value); + } + } + } + } + + public void addFormatting(TextFormatting formatting) { + if (formatting.isColor()) { + frontColor = formatting; + pageInsertIntoCurrent(formatting.toString()); + for (TextFormatting style : frontStyle) { + pageInsertIntoCurrent(style.toString()); + } + } else if (formatting.isFancyStyling()){ + if (frontStyle.contains(formatting)) { + return; + } + frontStyle.add(formatting); + pageInsertIntoCurrent(formatting.toString()); + } + } + + public void removeFormatting(TextFormatting formatting) { + if (formatting.isColor()) { + frontColor = null; + pageInsertIntoCurrent(TextFormatting.RESET.toString()); + frontStyle.forEach(style->pageInsertIntoCurrent(style.toString())); + } else if (formatting.isFancyStyling()) { + pageInsertIntoCurrent(TextFormatting.RESET.toString()); + if (frontColor != null) { + pageInsertIntoCurrent(frontColor.toString()); + } + frontStyle.remove(formatting); + frontStyle.forEach(style->pageInsertIntoCurrent(style.toString())); + } + } + + public TextFormatting getFrontColorFormatting() { + return frontColor; + } + + public List getFrontStyleFormatting() { + return frontStyle; + } + + public void pageSetCurrent(String string) { + if (!content.equals(string)) { + content = cleanUpFormatting(string); + findFrontFormatting(); + if(stringUpdate != null) { + stringUpdate.accept(content); + } + textHeight = this.fontRenderer.getWordWrappedHeight(content + "" + TextFormatting.BLACK + "_", this.getSize().width - yBarWidth); + } + } + + public void pageInsertIntoCurrent(String string) { + content = cleanUpFormatting(content + string); + if(stringUpdate != null) { + stringUpdate.accept(content); + } + textHeight = this.fontRenderer.getWordWrappedHeight(content + "" + TextFormatting.BLACK + "_", this.getSize().width - yBarWidth); + } + + @Override + public boolean hookDrawInBackground(int mouseX, int mouseY, float partialTicks, IRenderContext context) { + String contentString = content; + if (focus && isActive()) { + if (this.fontRenderer.getBidiFlag()) { + contentString += "_"; + } else if (this.updateCount / 6 % 2 == 0) { + contentString += TextFormatting.BLACK + "_"; + } else { + contentString += TextFormatting.GRAY + "_"; + } + } + int x = getPosition().x - scrollXOffset; + int y = getPosition().y + SPACE - scrollYOffset; + for (String textLine : this.fontRenderer.listFormattedStringToWidth(contentString, getSize().width - yBarWidth)) { + fontRenderer.drawString(textLine, x, y, 0xff000000, false); + y += fontRenderer.FONT_HEIGHT; + } + return true; + } + } +} + + diff --git a/src/main/java/gregtech/api/terminal/gui/widgets/TreeListWidget.java b/src/main/java/gregtech/api/terminal/gui/widgets/TreeListWidget.java new file mode 100644 index 00000000000..2303c7f6d0a --- /dev/null +++ b/src/main/java/gregtech/api/terminal/gui/widgets/TreeListWidget.java @@ -0,0 +1,239 @@ +package gregtech.api.terminal.gui.widgets; + +import gregtech.api.gui.IRenderContext; +import gregtech.api.gui.Widget; +import gregtech.api.gui.resources.IGuiTexture; +import gregtech.api.terminal.util.TreeNode; +import gregtech.api.util.Position; +import gregtech.api.util.RenderUtil; +import gregtech.api.util.Size; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.resources.I18n; +import net.minecraft.util.math.MathHelper; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Consumer; +import java.util.function.Function; + +public class TreeListWidget extends Widget { + private static final int ITEM_HEIGHT = 11; + protected int scrollOffset; + protected List> list; + protected TreeNode selected; + protected IGuiTexture background; + protected IGuiTexture nodeTexture; + protected IGuiTexture leafTexture; + protected Consumer> onSelected; + protected Function keyIconSupplier; + protected Function keyNameSupplier; + protected Function contentIconSupplier; + protected Function contentNameSupplier; + protected boolean canSelectNode; + private int tick; + + public TreeListWidget(int xPosition, int yPosition, int width, int height, + TreeNode root, + Consumer> onSelected) { + super(new Position(xPosition, yPosition), new Size(width, height)); + list = new ArrayList<>(); + if (root.getChildren() != null) { + list.addAll(root.getChildren()); + } + this.onSelected = onSelected; + } + + public TreeListWidget canSelectNode(boolean canSelectNode) { + this.canSelectNode = canSelectNode; + return this; + } + + public TreeListWidget setBackground(IGuiTexture background) { + this.background = background; + return this; + } + + public TreeListWidget setNodeTexture(IGuiTexture nodeTexture) { + this.nodeTexture = nodeTexture; + return this; + } + + public TreeListWidget setLeafTexture(IGuiTexture leafTexture) { + this.leafTexture = leafTexture; + return this; + } + + public TreeListWidget setContentIconSupplier(Function iconSupplier) { + contentIconSupplier = iconSupplier; + return this; + } + + public TreeListWidget setKeyIconSupplier(Function iconSupplier) { + keyIconSupplier = iconSupplier; + return this; + } + + public TreeListWidget setContentNameSupplier(Function nameSupplier) { + contentNameSupplier = nameSupplier; + return this; + } + + public TreeListWidget setKeyNameSupplier(Function nameSupplier) { + keyNameSupplier = nameSupplier; + return this; + } + + @Override + public void updateScreen() { + tick++; + } + + @Override + public boolean mouseWheelMove(int mouseX, int mouseY, int wheelDelta) { + if (this.isMouseOverElement(mouseX, mouseY, true)) { + int moveDelta = -MathHelper.clamp(wheelDelta, -1, 1) * 5; + this.scrollOffset = MathHelper.clamp(scrollOffset + moveDelta, 0, Math.max(list.size() * ITEM_HEIGHT - getSize().height, 0)); + return true; + } + return false; + } + + @Override + public void drawInBackground(int mouseX, int mouseY, float partialTicks, IRenderContext context) { + int x = getPosition().x; + int y = getPosition().y; + int width = getSize().width; + int height = getSize().height; + if (background != null) { + background.draw(x, y, width, height); + } else { + drawGradientRect(x, y, width, height, 0x8f000000, 0x8f000000); + } + RenderUtil.useScissor(x, y, width, height, ()->{ + FontRenderer fr = Minecraft.getMinecraft().fontRenderer; + int minToRender = scrollOffset / ITEM_HEIGHT; + int maxToRender = Math.min(list.size(), height / ITEM_HEIGHT + 2 + minToRender); + for (int i = minToRender; i < maxToRender; i++) { + GlStateManager.color(1,1,1,1); + TreeNode node = list.get(i); + int sX = x + 10 * node.dimension; + int sY = y - scrollOffset + i * ITEM_HEIGHT; + String name = node.toString(); + if (node.isLeaf()) { + if (leafTexture != null) { + leafTexture.draw(x, sY, width, ITEM_HEIGHT); + } else { + drawSolidRect(x, sY, width, ITEM_HEIGHT, 0xffff0000); + } + if (node.getContent() != null) { + String nameS = contentNameSupplier == null ? null : contentNameSupplier.apply(node.getContent()); + name = nameS == null ? name : nameS; + IGuiTexture icon = contentIconSupplier == null ? null : contentIconSupplier.apply(node.getContent()); + if (icon != null) { + icon.draw(sX - 9, sY + 1, 8, 8); + } + } + } else { + if (nodeTexture != null) { + nodeTexture.draw(x, sY, width, ITEM_HEIGHT); + } else { + drawSolidRect(x, sY, width, ITEM_HEIGHT, 0xffffff00); + } + String nameS = keyNameSupplier == null ? null : keyNameSupplier.apply(node.getKey()); + name = nameS == null ? name : nameS; + IGuiTexture icon = keyIconSupplier == null ? null : keyIconSupplier.apply(node.getKey()); + if (icon != null) { + icon.draw(sX - 9, sY + 1, 8, 8); + } + } + if (node == selected) { + drawSolidRect(x, sY, width, ITEM_HEIGHT, 0x7f000000); + } + int textW = Math.max(width - 10 * node.dimension, 10); + List list = fr.listFormattedStringToWidth(I18n.format(name), textW); + fr.drawString(list.get(Math.abs((tick / 20) % list.size())), sX, sY + 2, 0xff000000); + } + }); + GlStateManager.enableBlend(); + GlStateManager.color(1,1,1,1); + } + + public TreeNode jumpTo(List path) { + list.removeIf(node->node.dimension != 1); + this.selected = null; + int dim = 1; + int index = 0; + boolean flag = false; + TreeNode node = null; + for (K key : path) { + flag = false; + for (int i = index; i < list.size(); i++) { + node = list.get(i); + if (node.dimension != dim) { + return null; + } else if (node.getKey().equals(key)) { //expand + if(!node.isLeaf() && path.size() > dim) { + for (int j = 0; j < node.getChildren().size(); j++) { + list.add(index + 1 + j, node.getChildren().get(j)); + } + } + index = i + 1; + dim++; + flag = true; + break; + } + } + if (!flag) return null; + } + if (flag) { + this.selected = node; + this.scrollOffset = MathHelper.clamp(ITEM_HEIGHT * (index - 1), 0, Math.max(list.size() * ITEM_HEIGHT - getSize().height, 0)); + return this.selected; + } + return null; + } + + @Override + public boolean mouseClicked(int mouseX, int mouseY, int button) { + if (this.isMouseOverElement(mouseX, mouseY)) { + int index = ((mouseY - getPosition().y) + scrollOffset) / ITEM_HEIGHT; + if (index < list.size()) { + TreeNode node = list.get(index); + if (node.isLeaf()) { + if (node != this.selected) { + this.selected = node; + if (onSelected != null){ + onSelected.accept(node); + } + } + } else { + if (canSelectNode && this.selected != node) { + this.selected = node; + if (onSelected != null){ + onSelected.accept(node); + } + } else if (node.getChildren().size() > 0 && list.contains(node.getChildren().get(0))){ + removeNode(node); + } else { + for (int i = 0; i < node.getChildren().size(); i++) { + list.add(index + 1 + i, node.getChildren().get(i)); + } + } + } + playButtonClickSound(); + } + return true; + } + return false; + } + + private void removeNode(TreeNode node) { + if(node.isLeaf()) return; + for (TreeNode child : node.getChildren()) { + list.remove(child); + removeNode(child); + } + } +} diff --git a/src/main/java/gregtech/api/terminal/os/TerminalDesktopWidget.java b/src/main/java/gregtech/api/terminal/os/TerminalDesktopWidget.java new file mode 100644 index 00000000000..0cd106e3bc6 --- /dev/null +++ b/src/main/java/gregtech/api/terminal/os/TerminalDesktopWidget.java @@ -0,0 +1,44 @@ +package gregtech.api.terminal.os; + +import gregtech.api.gui.widgets.WidgetGroup; +import gregtech.api.terminal.app.AbstractApplication; +import gregtech.api.terminal.gui.widgets.CircleButtonWidget; +import gregtech.api.util.Position; +import gregtech.api.util.Size; + +public class TerminalDesktopWidget extends WidgetGroup { + private final TerminalOSWidget os; + private final WidgetGroup appDiv; + + public TerminalDesktopWidget(Position position, Size size, TerminalOSWidget os) { + super(position, size); + this.os = os; + this.appDiv = new WidgetGroup(); + this.addWidget(appDiv); + } + + public void installApplication(AbstractApplication application){ + int r = 12; + int index = appDiv.widgets.size(); + int x = this.getSize().width / 2 + (3 * r) * (index - 3); + int y = (index / 7) * (3 * r) + 40; + CircleButtonWidget button = new CircleButtonWidget(x,y) + .setColors(TerminalTheme.COLOR_B_2.getColor(), + TerminalTheme.COLOR_F_1.getColor(), + TerminalTheme.COLOR_B_2.getColor()) + .setIcon(application.getIcon()) + .setHoverText(application.getUnlocalizedName()); + button.setClickListener(clickData -> os.openApplication(application, clickData.isClient)); + appDiv.addWidget(button); + } + + public void showDesktop() { + appDiv.setActive(true); + appDiv.setVisible(true); + } + + public void hideDesktop() { + appDiv.setActive(false); + appDiv.setVisible(false); + } +} diff --git a/src/main/java/gregtech/api/terminal/os/TerminalDialogWidget.java b/src/main/java/gregtech/api/terminal/os/TerminalDialogWidget.java new file mode 100644 index 00000000000..b2793b595b3 --- /dev/null +++ b/src/main/java/gregtech/api/terminal/os/TerminalDialogWidget.java @@ -0,0 +1,285 @@ +package gregtech.api.terminal.os; + +import gregtech.api.gui.GuiTextures; +import gregtech.api.gui.IRenderContext; +import gregtech.api.gui.Widget; +import gregtech.api.gui.resources.ColorRectTexture; +import gregtech.api.gui.resources.IGuiTexture; +import gregtech.api.gui.resources.TextureArea; +import gregtech.api.gui.widgets.*; +import gregtech.api.terminal.gui.widgets.AnimaWidgetGroup; +import gregtech.api.terminal.gui.widgets.CircleButtonWidget; +import gregtech.api.terminal.gui.widgets.ColorWidget; +import gregtech.api.terminal.gui.widgets.TreeListWidget; +import gregtech.api.terminal.util.FileTree; +import gregtech.api.util.Size; +import gregtech.api.util.interpolate.Interpolator; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.resources.I18n; +import net.minecraft.inventory.IInventory; +import net.minecraft.network.PacketBuffer; + +import java.awt.*; +import java.io.File; +import java.io.IOException; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Consumer; +import java.util.function.Predicate; + +public class TerminalDialogWidget extends AnimaWidgetGroup { + private static final IGuiTexture DIALOG_BACKGROUND = TextureArea.fullImage("textures/gui/terminal/terminal_dialog.png"); + private static final IGuiTexture OK_NORMAL = TextureArea.fullImage("textures/gui/terminal/icon/ok_normal.png"); + private static final IGuiTexture OK_HOVER = TextureArea.fullImage("textures/gui/terminal/icon/ok_hover.png"); + private static final IGuiTexture OK_DISABLE = TextureArea.fullImage("textures/gui/terminal/icon/ok_disable.png"); + private static final IGuiTexture CANCEL_NORMAL = TextureArea.fullImage("textures/gui/terminal/icon/cancel_normal.png"); + private static final IGuiTexture CANCEL_HOVER = TextureArea.fullImage("textures/gui/terminal/icon/cancel_hover.png"); + private static final IGuiTexture CANCEL_DISABLE = TextureArea.fullImage("textures/gui/terminal/icon/cancel_disable.png"); + private static final int HEIGHT = 128; + private static final int WIDTH = 184; + + protected Interpolator interpolator; + private final TerminalOSWidget os; + private IGuiTexture background; + private boolean isClient; + + private TerminalDialogWidget(TerminalOSWidget os, int x, int y, int width, int height) { + super(x, y, width, height); + this.os = os; + } + + public boolean isClient() { + return isClient; + } + + public void open(){ + os.openDialog(this); + } + + public TerminalDialogWidget setClientSide() { + this.isClient = true; + return this; + } + + public TerminalDialogWidget setBackground(IGuiTexture background) { + this.background = background; + return this; + } + + public TerminalDialogWidget addOkButton() { + addWidget(new CircleButtonWidget(WIDTH / 2, HEIGHT - 22, 12, 0, 24) + .setClickListener(cd -> os.closeDialog(this)) + .setColors(0, 0, 0) + .setIcon(OK_NORMAL) + .setHoverIcon(OK_HOVER)); + return this; + } + + public TerminalDialogWidget addConfirmButton(Consumer result) { + addWidget(new CircleButtonWidget(WIDTH / 2 - 30, HEIGHT - 22, 12, 0, 24) + .setClickListener(cd -> { + os.closeDialog(this); + if (result != null) + result.accept(true); + }) + .setColors(0, 0, 0) + .setIcon(OK_NORMAL) + .setHoverIcon(OK_HOVER)); + addWidget(new CircleButtonWidget(WIDTH / 2 + 30, HEIGHT - 22, 12, 0, 24) + .setClickListener(cd -> { + os.closeDialog(this); + if (result != null) + result.accept(false); + }) + .setColors(0, 0, 0) + .setIcon(CANCEL_NORMAL) + .setHoverIcon(CANCEL_HOVER)); + return this; + } + + public TerminalDialogWidget addTitle(String title) { + this.addWidget(new LabelWidget(WIDTH / 2, 11, title, -1).setXCentered(true)); + return this; + } + + public TerminalDialogWidget addInfo(String info) { + this.addWidget(new LabelWidget(WIDTH / 2, HEIGHT / 2, info, -1).setWidth(WIDTH - 10).setYCentered(true).setXCentered(true)); + return this; + } + + public TerminalDialogWidget addPlayerInventory() { + IInventory inventoryPlayer = os.getModularUI().entityPlayer.inventory; + int x = 20; + int y = 20; + for (int row = 0; row < 3; row++) { + for (int col = 0; col < 9; col++) { + this.addWidget(new SlotWidget(inventoryPlayer, col + (row + 1) * 9, x + col * 18, y + row * 18, true, true) + .setBackgroundTexture(GuiTextures.SLOT) + .setLocationInfo(true, false)); + } + } + y+=58; + for (int slot = 0; slot < 9; slot++) { + this.addWidget(new SlotWidget(inventoryPlayer, slot, x + slot * 18, y, true, true) + .setBackgroundTexture(GuiTextures.SLOT) + .setLocationInfo(true, true)); + } + return this; + } + + public static TerminalDialogWidget createEmptyTemplate(TerminalOSWidget os) { + Size size = os.getSize(); + return new TerminalDialogWidget(os, (size.width - WIDTH) / 2, (size.height - HEIGHT) / 2, WIDTH, HEIGHT).setBackground(DIALOG_BACKGROUND); + } + + public static TerminalDialogWidget showInfoDialog(TerminalOSWidget os, String title, String info) { + return createEmptyTemplate(os).addTitle(title).addInfo(info).addOkButton(); + } + + public static TerminalDialogWidget showConfirmDialog(TerminalOSWidget os, String title, String info, Consumer result) { + return createEmptyTemplate(os).addConfirmButton(result).addTitle(title).addInfo(info); + } + + public static TerminalDialogWidget showTextFieldDialog(TerminalOSWidget os, String title, Predicate validator, Consumer result) { + TextFieldWidget textFieldWidget = new TextFieldWidget(WIDTH / 2 - 50, HEIGHT / 2 - 15, 100, 20, new ColorRectTexture(0x2fffffff), null, null).setValidator(validator); + TerminalDialogWidget dialog = createEmptyTemplate(os).addTitle(title).addConfirmButton(b -> { + if (b) { + if (result != null) + result.accept(textFieldWidget.getCurrentString()); + } else { + if (result != null) + result.accept(null); + } + }); + dialog.addWidget(textFieldWidget); + return dialog; + } + + public static TerminalDialogWidget showColorDialog(TerminalOSWidget os, String title, Consumer result) { + TerminalDialogWidget dialog = createEmptyTemplate(os).addTitle(title); + ColorWidget colorWidget = new ColorWidget(WIDTH / 2 - 60, HEIGHT / 2 - 35, 80, 10); + dialog.addWidget(colorWidget); + dialog.addConfirmButton(b -> { + if (b) { + if (result != null) + result.accept(colorWidget.getColor()); + } else { + if (result != null) + result.accept(null); + } + }); + return dialog; + } + + public static TerminalDialogWidget showFileDialog(TerminalOSWidget os, String title, File dir, boolean isSelector, Consumer result) { + Size size = os.getSize(); + TerminalDialogWidget dialog = new TerminalDialogWidget(os, 0, 0, size.width, size.height) + .setBackground(new ColorRectTexture(0x4f000000)); + if (!dir.isDirectory()) { + if (!dir.mkdirs()) { + return dialog.addInfo(I18n.format("terminal.dialog.error_path") + dir.getPath()).addOkButton(); + } + } + AtomicReference selected = new AtomicReference<>(); + selected.set(dir); + dialog.addWidget(new TreeListWidget<>(0, 0, 130, size.height, new FileTree(dir), node -> selected.set(node.getKey())).setNodeTexture(GuiTextures.BORDERED_BACKGROUND) + .canSelectNode(true) + .setLeafTexture(GuiTextures.SLOT_DARKENED)); + int x = 130 + (size.width - 133 - WIDTH) / 2; + int y = (size.height - HEIGHT) / 2; + dialog.addWidget(new ImageWidget(x, y, WIDTH, HEIGHT, DIALOG_BACKGROUND)); + dialog.addWidget(new CircleButtonWidget(x + WIDTH / 2 - 30, y + HEIGHT - 22, 12, 0, 24) + .setClickListener(cd -> { + os.closeDialog(dialog); + if (result != null) + result.accept(selected.get()); + }) + .setColors(0, 0, 0) + .setIcon(OK_NORMAL) + .setHoverIcon(OK_HOVER)); + dialog.addWidget(new CircleButtonWidget(x + WIDTH / 2 + 30, y + HEIGHT - 22, 12, 0, 24) + .setClickListener(cd -> { + os.closeDialog(dialog); + if (result != null) + result.accept(null); + }) + .setColors(0, 0, 0) + .setIcon(CANCEL_NORMAL) + .setHoverIcon(CANCEL_HOVER)); + if (isSelector) { + dialog.addWidget(new SimpleTextWidget(x + WIDTH / 2, y + HEIGHT / 2 - 5, "", -1, () -> { + if (selected.get() != null) { + return selected.get().toString(); + } + return "terminal.dialog.no_file_selected"; + }, true)); + } else { + dialog.addWidget(new TextFieldWidget(x + WIDTH / 2 - 38, y + HEIGHT / 2 - 10, 76, 20, new ColorRectTexture(0x4f000000), null, null) + .setTextResponder(res->{ + File file = selected.get(); + if (file == null) return; + if (file.isDirectory()) { + selected.set(new File(file, res)); + } else { + selected.set(new File(file.getParent(), res)); + } + },true) + .setTextSupplier(()->{ + File file = selected.get(); + if (file != null && !file.isDirectory()) { + return selected.get().getName(); + } + return ""; + }, true) + .setMaxStringLength(Integer.MAX_VALUE) + .setValidator(s->true)); + } + dialog.addWidget(new CircleButtonWidget(x + 17, y + 15, 10, 1, 16) + .setClickListener(cd -> { + File file = selected.get(); + if (file != null) { + try { + Desktop.getDesktop().open(file.isDirectory() ? file : file.getParentFile()); + } catch (IOException e) { + e.printStackTrace(); + } + } + }) + .setColors(0, 0xFFFFFFFF, 0) + .setHoverText("terminal.dialog.folder") + .setIcon(GuiTextures.ICON_LOAD)); + dialog.addWidget(new LabelWidget(x + WIDTH / 2, y + 11, title, -1).setXCentered(true)); + os.menu.hideMenu(); + return dialog.setClientSide(); + } + + @Override + public void hookDrawInBackground(int mouseX, int mouseY, float partialTicks, IRenderContext context) { + GlStateManager.translate(0,0,1000); + if (background != null) { + background.draw(getPosition().x, getPosition().y, getSize().width, getSize().height); + } + super.hookDrawInBackground(mouseX, mouseY, partialTicks, context); + GlStateManager.translate(0,0,-1000); + } + + @Override + public boolean mouseClicked(int mouseX, int mouseY, int button) { + for (int i = widgets.size() - 1; i >= 0; i--) { + Widget widget = widgets.get(i); + if (widget.isVisible()) { + if (widget instanceof SlotWidget) { + return false; + } else if(widget.mouseClicked(mouseX, mouseY, button)){ + return true; + } + } + } + return true; + } + + @Override + protected void writeClientAction(int id, Consumer packetBufferWriter) { + if (isClient) return; + super.writeClientAction(id, packetBufferWriter); + } +} diff --git a/src/main/java/gregtech/api/terminal/os/TerminalOSWidget.java b/src/main/java/gregtech/api/terminal/os/TerminalOSWidget.java new file mode 100644 index 00000000000..445861ca7d2 --- /dev/null +++ b/src/main/java/gregtech/api/terminal/os/TerminalOSWidget.java @@ -0,0 +1,246 @@ +package gregtech.api.terminal.os; + +import gregtech.api.gui.IRenderContext; +import gregtech.api.gui.ModularUI; +import gregtech.api.gui.resources.IGuiTexture; +import gregtech.api.gui.widgets.AbstractWidgetGroup; +import gregtech.api.terminal.TerminalRegistry; +import gregtech.api.terminal.app.AbstractApplication; +import gregtech.api.terminal.os.menu.TerminalMenuWidget; +import gregtech.api.util.Position; +import gregtech.api.util.RenderUtil; +import gregtech.api.util.Size; +import net.minecraft.nbt.NBTBase; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraft.nbt.NBTTagString; +import net.minecraft.network.PacketBuffer; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +public class TerminalOSWidget extends AbstractWidgetGroup { + private IGuiTexture background; + public final List openedApps; + public AbstractApplication focusApp; + public final TerminalMenuWidget menu; + public final TerminalDesktopWidget desktop; + private final NBTTagCompound tabletNBT; + + public TerminalOSWidget(int xPosition, int yPosition, int width, int height, NBTTagCompound tabletNBT) { + super(new Position(xPosition, yPosition), new Size(width, height)); + this.openedApps = new ArrayList<>(); + this.desktop = new TerminalDesktopWidget(Position.ORIGIN, new Size(333, 232), this); + this.menu = new TerminalMenuWidget(Position.ORIGIN, new Size(31, 232), this).setBackground(TerminalTheme.COLOR_B_2); + this.addWidget(desktop); + this.addWidget(menu); + this.tabletNBT = tabletNBT; + TerminalRegistry.getDefaultApps().forEach(name-> installApplication(TerminalRegistry.getApplication(name))); + NBTTagList installed = tabletNBT.getTagList("installed", 8); + for (NBTBase nbtBase : installed) { + if (nbtBase instanceof NBTTagString) { + AbstractApplication app = TerminalRegistry.getApplication(((NBTTagString) nbtBase).getString()); + if (app != null) { + installApplication(app); + } + } + } + } + + public ModularUI getModularUI(){ + return this.gui; + } + + public TerminalOSWidget setBackground(IGuiTexture background) { + this.background = background; + return this; + } + + public void installApplication(AbstractApplication application){ + desktop.installApplication(application); + } + + public void openApplication(AbstractApplication application, boolean isClient) { + if (focusApp != null ) { + closeApplication(focusApp, isClient); + } + for (AbstractApplication app : openedApps) { + if (app.getClass() == application.getClass()) { + maximizeApplication(app, isClient); + return; + } + } + AbstractApplication app = application.createApp(this, isClient, tabletNBT.getCompoundTag(application.getRegistryName())).setOs(this); + if (app != null) { + openedApps.add(app); + desktop.addWidget(app); + maximizeApplication(app, isClient); + } + } + + public void maximizeApplication(AbstractApplication application, boolean isClient) { + application.setActive(true); + if (isClient) { + application.maximizeWidget(app->desktop.hideDesktop()); + if (!menu.isHide) { + menu.hideMenu(); + } + } + focusApp = application; + menu.loadComponents(focusApp); + desktop.hideDesktop(); + } + + public void minimizeApplication(AbstractApplication application, boolean isClient) { + if (application != null) { + if (application.isBackgroundApp()) { + application.setActive(false); + } + if (isClient) { + application.minimizeWidget(null); + } + if(focusApp == application) { + focusApp = null; + } + menu.removeComponents(); + desktop.showDesktop(); + } + } + + public NBTTagCompound closeApplication(AbstractApplication application, boolean isClient) { + if (application != null) { + NBTTagCompound nbt = application.closeApp(isClient, tabletNBT.getCompoundTag(application.getRegistryName())); + if (nbt != null) { + tabletNBT.setTag(application.getRegistryName(), nbt); + } + if (isClient) { + application.minimizeWidget(desktop::waitToRemoved); + } else { + desktop.waitToRemoved(application); + } + openedApps.remove(application); + if(focusApp == application) { + focusApp = null; + } + menu.removeComponents(); + desktop.showDesktop(); + return nbt; + } + return null; + } + + public void homeTrigger(boolean isClient) { + if(isClient) { + if (menu.isHide) { + menu.showMenu(); + } else { + menu.hideMenu(); + } + } + } + + @SideOnly(Side.CLIENT) + private void shutdown() { + NBTTagCompound nbt = new NBTTagCompound(); + for (AbstractApplication openedApp : openedApps) { + String appName = openedApp.getRegistryName(); + NBTTagCompound synced = openedApp.closeApp(true, tabletNBT.getCompoundTag(appName)); + if (synced != null && !synced.isEmpty()) { + tabletNBT.setTag(appName, synced); + if (openedApp.isClientSideApp()) {//if its a clientSideApp and the nbt not null, meaning this nbt should be synced to the server side. + nbt.setTag(appName, synced); + } + } + } + writeClientAction(-1, buffer -> buffer.writeCompoundTag(nbt)); + } + + protected TerminalDialogWidget openDialog(TerminalDialogWidget widget) { + if (isRemote()) { + widget.maximizeWidget(null); + } else if(widget.isClient()) { + return widget; + } + desktop.addWidget(widget); + return widget; + } + + protected TerminalDialogWidget closeDialog(TerminalDialogWidget widget) { + if (isRemote()) { + widget.minimizeWidget(desktop::waitToRemoved); + } else if(widget.isClient()) { + desktop.waitToRemoved(widget); + } + return widget; + } + + @Override + public void handleClientAction(int id, PacketBuffer buffer) { + if (id == -1) { //shutdown + NBTTagCompound nbt = null; + try { + nbt = buffer.readCompoundTag(); + } catch (IOException e) { + e.printStackTrace(); + } + for (AbstractApplication openedApp : openedApps) { + String appName = openedApp.getRegistryName(); + NBTTagCompound data = openedApp.closeApp(false, tabletNBT.getCompoundTag(appName)); + if (data != null && !data.isEmpty()) { + tabletNBT.setTag(appName, data); + } else if (nbt != null && openedApp.isClientSideApp() && nbt.hasKey(appName)) { + tabletNBT.setTag(appName, nbt.getCompoundTag(appName)); + } + } + this.getModularUI().entityPlayer.closeScreen(); // must close tablet from server side. + } + super.handleClientAction(id, buffer); + } + + @Override + public void updateScreen() { + super.updateScreen(); + if( background != null) { + background.updateTick(); + } + } + + @Override + public void drawInBackground(int mouseX, int mouseY, float partialTicks, IRenderContext context) { + Position position = getPosition(); + Size size = getSize(); + if( background != null) { + background.draw(position.x, position.y, size.width, size.height); + } else { + drawGradientRect(position.x, position.y, size.width, size.height, -1, -1); + } + RenderUtil.useScissor(position.x, position.y, size.width, size.height, ()->{ + super.drawInBackground(mouseX, mouseY, partialTicks, context); + }); + } + + boolean waitShutdown; + @Override + public boolean keyTyped(char charTyped, int keyCode) { + if (keyCode == 1) { // hook esc + if (waitShutdown) { + shutdown(); + } else { + waitShutdown = true; + TerminalDialogWidget.showConfirmDialog(this, "terminal.component.warning", "terminal.os.shutdown_confirm", result->{ + if (result) { + shutdown(); + } else { + waitShutdown = false; + } + }).setClientSide().open(); + } + return true; + } + waitShutdown = false; + return super.keyTyped(charTyped, keyCode); + } +} diff --git a/src/main/java/gregtech/api/terminal/os/TerminalTheme.java b/src/main/java/gregtech/api/terminal/os/TerminalTheme.java new file mode 100644 index 00000000000..fdebd8a4b1c --- /dev/null +++ b/src/main/java/gregtech/api/terminal/os/TerminalTheme.java @@ -0,0 +1,71 @@ +package gregtech.api.terminal.os; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import gregtech.api.gui.resources.ColorRectTexture; +import gregtech.api.gui.resources.ModifyGuiTexture; +import gregtech.api.gui.resources.TextureArea; +import gregtech.api.terminal.util.FileUtils; + +import java.awt.*; +import java.io.File; + +public class TerminalTheme { + private static final String FILE_PATH = "terminal\\config\\theme.json"; + public static final ColorRectTexture COLOR_1 = new ColorRectTexture(new Color(144, 243, 116)); + public static final ColorRectTexture COLOR_2 = new ColorRectTexture(new Color(243, 208, 116)); + public static final ColorRectTexture COLOR_3 = new ColorRectTexture(new Color(231, 95, 95)); + public static final ColorRectTexture COLOR_4 = new ColorRectTexture(new Color(0, 115, 255)); + public static final ColorRectTexture COLOR_5 = new ColorRectTexture(new Color(113, 27, 217)); + public static final ColorRectTexture COLOR_6 = new ColorRectTexture(new Color(0, 0, 0, 255)); + public static final ColorRectTexture COLOR_7 = new ColorRectTexture(new Color(255, 255, 255, 255)); + + public static final ColorRectTexture COLOR_F_1 = new ColorRectTexture(new Color(148, 226, 193)); + public static final ColorRectTexture COLOR_F_2 = new ColorRectTexture(new Color(175, 0, 0, 131)); + + public static final ColorRectTexture COLOR_B_1 = new ColorRectTexture(new Color(0, 0, 0, 79)); + public static final ColorRectTexture COLOR_B_2 = new ColorRectTexture(new Color(0, 0, 0, 159)); + public static final ColorRectTexture COLOR_B_3 = new ColorRectTexture(new Color(246, 120, 120, 190)); + + public static final ModifyGuiTexture WALL_PAPER = new ModifyGuiTexture(TextureArea.fullImage("textures/gui/terminal/terminal_background.png")); + + static { + JsonElement element = FileUtils.loadJson(new File(FILE_PATH)); + if (element == null || !element.isJsonObject()) { + saveConfig(); + } else { + JsonObject config = element.getAsJsonObject(); + if (config.has("COLOR_1")) { COLOR_1.setColor(config.get("COLOR_1").getAsInt()); } + if (config.has("COLOR_2")) { COLOR_2.setColor(config.get("COLOR_2").getAsInt()); } + if (config.has("COLOR_3")) { COLOR_3.setColor(config.get("COLOR_3").getAsInt()); } + if (config.has("COLOR_4")) { COLOR_4.setColor(config.get("COLOR_4").getAsInt()); } + if (config.has("COLOR_5")) { COLOR_5.setColor(config.get("COLOR_5").getAsInt()); } + if (config.has("COLOR_6")) { COLOR_6.setColor(config.get("COLOR_6").getAsInt()); } + if (config.has("COLOR_7")) { COLOR_7.setColor(config.get("COLOR_7").getAsInt()); } + if (config.has("COLOR_F_1")) { COLOR_F_1.setColor(config.get("COLOR_F_1").getAsInt()); } + if (config.has("COLOR_F_2")) { COLOR_F_2.setColor(config.get("COLOR_F_2").getAsInt()); } + if (config.has("COLOR_B_1")) { COLOR_B_1.setColor(config.get("COLOR_B_1").getAsInt()); } + if (config.has("COLOR_B_2")) { COLOR_B_2.setColor(config.get("COLOR_B_2").getAsInt()); } + if (config.has("COLOR_B_3")) { COLOR_B_3.setColor(config.get("COLOR_B_3").getAsInt()); } + if (config.has("WALL_PAPER")) { WALL_PAPER.loadConfig(config.get("WALL_PAPER").getAsJsonObject()); } + } + } + + public static boolean saveConfig() { + JsonObject config = new JsonObject(); + config.addProperty("COLOR_1", COLOR_1.getColor()); + config.addProperty("COLOR_2", COLOR_2.getColor()); + config.addProperty("COLOR_3", COLOR_3.getColor()); + config.addProperty("COLOR_4", COLOR_4.getColor()); + config.addProperty("COLOR_5", COLOR_5.getColor()); + config.addProperty("COLOR_6", COLOR_6.getColor()); + config.addProperty("COLOR_7", COLOR_7.getColor()); + config.addProperty("COLOR_F_1", COLOR_F_1.getColor()); + config.addProperty("COLOR_F_2", COLOR_F_2.getColor()); + config.addProperty("COLOR_B_1", COLOR_B_1.getColor()); + config.addProperty("COLOR_B_2", COLOR_B_2.getColor()); + config.addProperty("COLOR_B_3", COLOR_B_3.getColor()); + config.add("WALL_PAPER", WALL_PAPER.saveConfig()); + return FileUtils.saveJson(new File(FILE_PATH), config); + } +} diff --git a/src/main/java/gregtech/api/terminal/os/menu/IMenuComponent.java b/src/main/java/gregtech/api/terminal/os/menu/IMenuComponent.java new file mode 100644 index 00000000000..22c5ef1d47f --- /dev/null +++ b/src/main/java/gregtech/api/terminal/os/menu/IMenuComponent.java @@ -0,0 +1,15 @@ +package gregtech.api.terminal.os.menu; + +import gregtech.api.gui.Widget; +import gregtech.api.gui.resources.ColorRectTexture; +import gregtech.api.gui.resources.IGuiTexture; + +public interface IMenuComponent { + default IGuiTexture buttonIcon() { + return new ColorRectTexture(0); + } + default String hoverText() { + return null; + } + default void click(Widget.ClickData clickData){} +} diff --git a/src/main/java/gregtech/api/terminal/os/menu/TerminalMenuWidget.java b/src/main/java/gregtech/api/terminal/os/menu/TerminalMenuWidget.java new file mode 100644 index 00000000000..dcca9976041 --- /dev/null +++ b/src/main/java/gregtech/api/terminal/os/menu/TerminalMenuWidget.java @@ -0,0 +1,173 @@ +package gregtech.api.terminal.os.menu; + +import gregtech.api.gui.IRenderContext; +import gregtech.api.gui.Widget; +import gregtech.api.gui.resources.IGuiTexture; +import gregtech.api.gui.widgets.WidgetGroup; +import gregtech.api.terminal.app.AbstractApplication; +import gregtech.api.terminal.gui.widgets.CircleButtonWidget; +import gregtech.api.terminal.os.TerminalOSWidget; +import gregtech.api.terminal.os.TerminalTheme; +import gregtech.api.util.Position; +import gregtech.api.util.Size; +import gregtech.api.util.interpolate.Eases; +import gregtech.api.util.interpolate.Interpolator; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.util.Tuple; + +import java.awt.*; +import java.util.ArrayList; +import java.util.List; + + +public class TerminalMenuWidget extends WidgetGroup { + private Interpolator interpolator; + private IGuiTexture background; + private final TerminalOSWidget os; + private final List> components; + public boolean isHide; + + + public TerminalMenuWidget(Position position, Size size, TerminalOSWidget os) { + super(position, size); + this.os = os; + components = new ArrayList<>(); + this.addWidget(new CircleButtonWidget(5, 10, 4, 1, 0) + .setColors(new Color(255, 255, 255, 0).getRGB(), + TerminalTheme.COLOR_7.getColor(), + TerminalTheme.COLOR_3.getColor()) + .setHoverText("terminal.menu.close") + .setClickListener(this::close)); + this.addWidget(new CircleButtonWidget(15, 10, 4, 1, 0) + .setColors(new Color(255, 255, 255, 0).getRGB(), + TerminalTheme.COLOR_7.getColor(), + TerminalTheme.COLOR_2.getColor()) + .setHoverText("terminal.menu.minimize") + .setClickListener(this::minimize)); + this.addWidget(new CircleButtonWidget(25, 10, 4, 1, 0) + .setColors(new Color(255, 255, 255, 0).getRGB(), + TerminalTheme.COLOR_7.getColor(), + TerminalTheme.COLOR_1.getColor()) + .setHoverText("terminal.menu.maximize") + .setClickListener(this::maximize)); + } + + public TerminalMenuWidget setBackground(IGuiTexture background) { + this.background = background; + return this; + } + + public void close(ClickData clickData) { + os.closeApplication(os.focusApp, clickData.isClient); + } + + public void minimize(ClickData clickData) { + os.minimizeApplication(os.focusApp, clickData.isClient); + } + + public void maximize(ClickData clickData) { } + + public void addComponent(IMenuComponent component) { + WidgetGroup group = new WidgetGroup(); + int x = 15; + int y = 40 + components.size() * 25; + CircleButtonWidget button = new CircleButtonWidget(x, y, 10, 1, 16) + .setColors(0, 0xFFFFFFFF, 0) + .setHoverText(component.hoverText()) + .setIcon(component.buttonIcon()); + button.setClickListener(c->{ + components.forEach(tuple -> { + if (tuple.getFirst() instanceof Widget && tuple.getFirst() != component){ + ((Widget) tuple.getFirst()).setActive(false); + ((Widget) tuple.getFirst()).setVisible(false); + } + }); + if (component instanceof Widget) { + Widget widget = (Widget)component; + widget.setVisible(!widget.isVisible()); + widget.setActive(!widget.isActive()); + button.setFill(widget.isVisible() ? 0xFF94E2C1 : 0); + } + component.click(c); + }); + group.addWidget(button); + if (component instanceof Widget) { + Widget widget = (Widget)component; + widget.setSelfPosition(new Position(x + 20, 0)); + widget.setVisible(false); + widget.setActive(false); + group.addWidget(widget); + } + this.addWidget(group); + components.add(new Tuple<>(component, group)); + } + + public void loadComponents(AbstractApplication app) { + removeComponents(); + if (app != null) { + app.getMenuComponents().forEach(this::addComponent); + } + } + + public void removeComponents() { + components.forEach(component->this.removeWidget(component.getSecond())); + components.clear(); + } + + public void hideMenu() { + if (!isHide && interpolator == null) { + int y = getSelfPosition().y; + interpolator = new Interpolator(getSelfPosition().x, getSelfPosition().x - getSize().width, 10, Eases.EaseLinear, + value-> setSelfPosition(new Position(value.intValue(), y)), + value-> { + setVisible(false); + interpolator = null; + isHide = true; + }); + interpolator.start(); + } + } + + public void showMenu() { + if (isHide && interpolator == null) { + setVisible(true); + int y = getSelfPosition().y; + interpolator = new Interpolator(getSelfPosition().x, getSelfPosition().x + getSize().width, 10, Eases.EaseLinear, + value-> setSelfPosition(new Position(value.intValue(), y)), + value-> { + interpolator = null; + isHide = false; + }); + interpolator.start(); + } + } + + @Override + public void updateScreen() { + if(interpolator != null) interpolator.update(); + super.updateScreen(); + } + + @Override + public void drawInBackground(int mouseX, int mouseY, float partialTicks, IRenderContext context) { + GlStateManager.color(1,1,1,0.5f); + if( background != null) { + background.draw(this.getPosition().x, this.getPosition().y, this.getSize().width, this.getSize().height); + } else { + drawGradientRect(this.getPosition().x, this.getPosition().y, this.getSize().width, this.getSize().height, 0xff000000, 0xff000000); + } + GlStateManager.color(1,1,1,1); + super.drawInBackground(mouseX, mouseY, partialTicks, context); + } + + @Override + public boolean mouseClicked(int mouseX, int mouseY, int button) { + if (!super.mouseClicked(mouseX, mouseY, button)) { + if (!isMouseOverElement(mouseX, mouseY) && !isHide) { + hideMenu(); + } + return false; + } + return true; + } +} diff --git a/src/main/java/gregtech/api/terminal/util/FileTree.java b/src/main/java/gregtech/api/terminal/util/FileTree.java new file mode 100644 index 00000000000..192b6495a7e --- /dev/null +++ b/src/main/java/gregtech/api/terminal/util/FileTree.java @@ -0,0 +1,50 @@ +package gregtech.api.terminal.util; + +import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class FileTree extends TreeNode { + + public FileTree(File dir){ + this(0, dir); + } + + private FileTree(int dimension, File key) { + super(dimension, key); + } + + @Override + public boolean isLeaf() { + return getKey().isFile(); + } + + @Override + public File getContent() { + return isLeaf() ? getKey() : null; + } + + @Override + public List> getChildren() { + if (children == null && !isLeaf()) { + children = new ArrayList<>(); + Arrays.stream(key.listFiles()).sorted((a, b)->{ + if (a.isFile() && b.isFile()) { + return a.compareTo(b); + } else if (a.isDirectory() && b.isDirectory()) { + return a.compareTo(b); + } else if(a.isDirectory()) { + return -1; + } + return 1; + }).forEach(file -> children.add(new FileTree(dimension + 1, file))); + } + return super.getChildren(); + } + + @Override + public String toString() { + return getKey().getName(); + } +} diff --git a/src/main/java/gregtech/api/terminal/util/FileUtils.java b/src/main/java/gregtech/api/terminal/util/FileUtils.java new file mode 100644 index 00000000000..245cd7c0587 --- /dev/null +++ b/src/main/java/gregtech/api/terminal/util/FileUtils.java @@ -0,0 +1,39 @@ +package gregtech.api.terminal.util; + +import com.google.gson.Gson; +import com.google.gson.JsonElement; +import com.google.gson.JsonParser; +import com.google.gson.stream.JsonReader; + +import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; + +public class FileUtils { + public static JsonElement loadJson(File file) { + try { + FileReader reader = new FileReader(file); + JsonElement json = new JsonParser().parse(new JsonReader(reader)); + reader.close(); + return json; + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + public static boolean saveJson(File file, JsonElement element) { + try { + if (!file.getParentFile().isDirectory()) { + file.getParentFile().mkdirs(); + } + FileWriter writer = new FileWriter(file); + writer.write(new Gson().toJson(element)); + writer.close(); + return true; + } catch (Exception e) { + e.printStackTrace(); + } + return false; + } +} diff --git a/src/main/java/gregtech/api/terminal/util/GuideJsonLoader.java b/src/main/java/gregtech/api/terminal/util/GuideJsonLoader.java new file mode 100644 index 00000000000..af2ccced8c8 --- /dev/null +++ b/src/main/java/gregtech/api/terminal/util/GuideJsonLoader.java @@ -0,0 +1,46 @@ +package gregtech.api.terminal.util; + +import com.google.gson.JsonObject; +import gregtech.api.terminal.TerminalRegistry; +import gregtech.common.terminal.app.guide.GuideApp; +import net.minecraft.client.Minecraft; +import net.minecraft.client.resources.IResourceManager; +import net.minecraft.client.resources.IResourceManagerReloadListener; +import net.minecraftforge.common.crafting.CraftingHelper; +import net.minecraftforge.fml.common.Loader; + +import java.nio.file.Files; +import java.util.ArrayList; +import java.util.List; + +public class GuideJsonLoader implements IResourceManagerReloadListener { + + @Override + public void onResourceManagerReload(IResourceManager manager) { + if(Loader.instance().activeModContainer() == null) return; + if (Minecraft.getMinecraft().getLanguageManager().getCurrentLanguage() == null) return; + String lang = Minecraft.getMinecraft().getLanguageManager().getCurrentLanguage().getLanguageCode(); + for (String appName : TerminalRegistry.getAllApps()) { + if (TerminalRegistry.getApplication(appName) instanceof GuideApp) { + List jsons = new ArrayList<>(); + GuideApp app = (GuideApp) TerminalRegistry.getApplication(appName); + CraftingHelper.findFiles(Loader.instance().activeModContainer(), "assets/gregtech/terminal/guide/" + appName + "/en_us", Files::exists, (path, file) -> { + if(file.toString().endsWith(".json")) { + String fileName = file.getFileName().toString(); + JsonObject json = app.getConfig(fileName, lang); + if (json == null) { + json = app.getConfig(fileName, "en_us"); + } + if (json != null) { + jsons.add(json); + } + } + return true; + },false, true); + app.loadJsonFiles(jsons); + } + } + + + } +} diff --git a/src/main/java/gregtech/api/terminal/util/ISearch.java b/src/main/java/gregtech/api/terminal/util/ISearch.java new file mode 100644 index 00000000000..eaa8e0abd85 --- /dev/null +++ b/src/main/java/gregtech/api/terminal/util/ISearch.java @@ -0,0 +1,8 @@ +package gregtech.api.terminal.util; + +import java.util.function.Consumer; + +public interface ISearch { + default boolean isManualInterrupt() {return false;} + void search(String word, Consumer find); +} diff --git a/src/main/java/gregtech/api/terminal/util/SearchEngine.java b/src/main/java/gregtech/api/terminal/util/SearchEngine.java new file mode 100644 index 00000000000..1cfe7a28bb1 --- /dev/null +++ b/src/main/java/gregtech/api/terminal/util/SearchEngine.java @@ -0,0 +1,37 @@ +package gregtech.api.terminal.util; + +import javax.annotation.Nonnull; +import java.util.function.Consumer; + +public class SearchEngine { + private final ISearch search; + private final Consumer result; + private Thread thread; + + public SearchEngine(@Nonnull ISearch search, @Nonnull Consumer result){ + this.search = search; + this.result = result; + } + + public void searchWord(String word) { + dispose(); + thread = new Thread(()-> search.search(word, result)); + thread.start(); + } + + public boolean isSearching() { + return thread != null && thread.isAlive(); + } + + public void dispose() { + if (isSearching()) { + if (search.isManualInterrupt()) { + thread.interrupt(); + } else { + thread.stop(); + } + } + thread = null; + } + +} diff --git a/src/main/java/gregtech/api/terminal/util/TreeNode.java b/src/main/java/gregtech/api/terminal/util/TreeNode.java new file mode 100644 index 00000000000..d54b56d9925 --- /dev/null +++ b/src/main/java/gregtech/api/terminal/util/TreeNode.java @@ -0,0 +1,75 @@ +package gregtech.api.terminal.util; + + +import java.util.ArrayList; +import java.util.List; + +/*** + * Tree + * @param key + * @param leaf + */ +public class TreeNode { + public final int dimension; + protected final T key; + protected K content; + protected List> children; + + + public TreeNode(int dimension, T key) { + this.dimension = dimension; + this.key = key; + } + + public boolean isLeaf(){ + return getChildren() == null || getChildren().isEmpty(); + } + + public TreeNode getOrCreateChild (T childKey) { + TreeNode result; + if (getChildren() != null) { + result = getChildren().stream().filter(child->child.key.equals(childKey)).findFirst().orElseGet(()->{ + TreeNode newNode = new TreeNode<>(dimension + 1, childKey); + getChildren().add(newNode); + return newNode; + }); + } else { + children = new ArrayList<>(); + result = new TreeNode<>(dimension + 1, childKey); + getChildren().add(result); + } + return result; + } + + public TreeNode getChild(T key) { + if (getChildren() != null) { + for (TreeNode child : getChildren()) { + if (child.key.equals(key)) { + return child; + } + } + } + return null; + } + + public void addContent (T key, K content) { + getOrCreateChild(key).content = content; + } + + public T getKey() { + return key; + } + + public K getContent() { + return content; + } + + public List> getChildren() { + return children; + } + + @Override + public String toString() { + return key.toString(); + } +} diff --git a/src/main/java/gregtech/api/unification/Elements.java b/src/main/java/gregtech/api/unification/Elements.java index e6b699d7128..6368e567277 100644 --- a/src/main/java/gregtech/api/unification/Elements.java +++ b/src/main/java/gregtech/api/unification/Elements.java @@ -20,7 +20,7 @@ private Elements() { public static final Element D = add(1, 1, -1, "H", "Deuterium", "D", true); public static final Element T = add(1, 2, -1, "D", "Tritium", "T", true); public static final Element He = add(2, 2, -1, null, "Helium", "He", false); - public static final Element He3 = add(2, 1, -1, "H&D", "Helium-3", "He_3", true); + public static final Element He3 = add(2, 1, -1, "H&D", "Helium-3", "He-3", true); public static final Element Li = add(3, 4, -1, null, "Lithium", "Li", false); public static final Element Be = add(4, 5, -1, null, "Beryllium", "Be", false); public static final Element B = add(5, 5, -1, null, "Boron", "B", false); @@ -57,7 +57,7 @@ private Elements() { public static final Element Kr = add(36, 48, -1, null, "Krypton", "Kr", false); public static final Element Rb = add(37, 48, -1, null, "Rubidium", "Rb", false); public static final Element Sr = add(38, 49, -1, null, "Strontium", "Sr", false); - public static final Element Yt = add(39, 50, -1, null, "Yttrium", "Yt", false); + public static final Element Y = add(39, 50, -1, null, "Yttrium", "Y", false); public static final Element Zr = add(40, 51, -1, null, "Zirconium", "Zr", false); public static final Element Nb = add(41, 53, -1, null, "Niobium", "Nb", false); public static final Element Mo = add(42, 53, -1, null, "Molybdenum", "Mo", false); @@ -111,12 +111,12 @@ private Elements() { public static final Element Th = add(90, 140, -1, null, "Thorium", "Th", false); public static final Element Pa = add(91, 138, -1, null, "Protactinium", "Pa", false); public static final Element U = add(92, 146, -1, null, "Uranium", "U", false); - public static final Element U238 = add(92, 146, -1, null, "Uranium-238", "U_238", false); - public static final Element U235 = add(92, 143, -1, null, "Uranium-235", "U_235", true); + public static final Element U238 = add(92, 146, -1, null, "Uranium-238", "U-238", false); + public static final Element U235 = add(92, 143, -1, null, "Uranium-235", "U-235", true); public static final Element Np = add(93, 144, -1, null, "Neptunium", "Np", false); public static final Element Pu = add(94, 152, -1, null, "Plutonium", "Pu", false); - public static final Element Pu239 = add(94, 145, -1, null, "Plutonium-239", "Pu_239", false); - public static final Element Pu241 = add(94, 149, -1, null, "Plutonium-241", "Pu_241", true); + public static final Element Pu239 = add(94, 145, -1, null, "Plutonium-239", "Pu-239", false); + public static final Element Pu241 = add(94, 149, -1, null, "Plutonium-241", "Pu-241", true); public static final Element Am = add(95, 150, -1, null, "Americium", "Am", false); public static final Element Cm = add(96, 153, -1, null, "Curium", "Cm", false); public static final Element Bk = add(97, 152, -1, null, "Berkelium", "Bk", false); diff --git a/src/main/java/gregtech/api/unification/material/MarkerMaterials.java b/src/main/java/gregtech/api/unification/material/MarkerMaterials.java index a05ed42eae2..91cb012a0b6 100644 --- a/src/main/java/gregtech/api/unification/material/MarkerMaterials.java +++ b/src/main/java/gregtech/api/unification/material/MarkerMaterials.java @@ -92,7 +92,6 @@ public static class Tier { public static final Material Master = new MarkerMaterial("master"); public static final Material Ultimate = new MarkerMaterial("ultimate"); public static final Material Superconductor = new MarkerMaterial("superconductor"); - //new Material(387, "superconductor", 0xFFFFFF, MaterialIconSet.NONE, of(), 0L, null) {}; public static final Material Infinite = new MarkerMaterial("infinite"); public static Material Ultra = new MarkerMaterial("ultra"); diff --git a/src/main/java/gregtech/api/unification/material/Material.java b/src/main/java/gregtech/api/unification/material/Material.java index 8df98a59263..c84b74e88ea 100644 --- a/src/main/java/gregtech/api/unification/material/Material.java +++ b/src/main/java/gregtech/api/unification/material/Material.java @@ -10,13 +10,11 @@ import gregtech.api.unification.material.info.MaterialIconSet; import gregtech.api.unification.material.properties.*; import gregtech.api.unification.stack.MaterialStack; +import gregtech.api.util.LocalizationUtils; import gregtech.api.util.SmallDigits; -import net.minecraft.client.resources.I18n; import net.minecraft.enchantment.Enchantment; import net.minecraftforge.fluids.Fluid; import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; import stanhebben.zenscript.annotations.OperatorType; import stanhebben.zenscript.annotations.ZenOperator; @@ -301,10 +299,9 @@ public String getUnlocalizedName() { return "material." + materialInfo.name; } - @SideOnly(Side.CLIENT) //@ZenGetter("localizedName") public String getLocalizedName() { - return I18n.format(getUnlocalizedName()); + return LocalizationUtils.format(getUnlocalizedName()); } @Override @@ -667,8 +664,8 @@ public Builder element(Element element) { return this; } - public Builder toolStats(float speed, float damage, int durability) { - properties.setProperty(PropertyKey.TOOL, new ToolProperty(speed, damage, durability)); + public Builder toolStats(float speed, float damage, int durability, int enchantability) { + properties.setProperty(PropertyKey.TOOL, new ToolProperty(speed, damage, durability, enchantability)); return this; } @@ -699,6 +696,12 @@ public Builder washedIn(Material m) { return this; } + public Builder washedIn(Material m, int washedAmount) { + properties.ensureSet(PropertyKey.ORE); + properties.getProperty(PropertyKey.ORE).setWashedIn(m, washedAmount); + return this; + } + public Builder separatedInto(Material... m) { properties.ensureSet(PropertyKey.ORE); properties.getProperty(PropertyKey.ORE).setSeparatedInto(m); @@ -746,6 +749,11 @@ public Builder cableProperties(long voltage, int amperage, int loss) { return this; } + public Builder cableProperties(long voltage, int amperage, int loss, boolean isSuperCon) { + properties.setProperty(PropertyKey.WIRE, new WireProperties((int) voltage, amperage, loss, isSuperCon)); + return this; + } + public Builder fluidPipeProperties(int maxTemp, int throughput, boolean gasProof) { properties.setProperty(PropertyKey.FLUID_PIPE, new FluidPipeProperties(maxTemp, throughput, gasProof)); return this; diff --git a/src/main/java/gregtech/api/unification/material/Materials.java b/src/main/java/gregtech/api/unification/material/Materials.java index d70c70deadd..8e847627341 100644 --- a/src/main/java/gregtech/api/unification/material/Materials.java +++ b/src/main/java/gregtech/api/unification/material/Materials.java @@ -415,6 +415,15 @@ public static void register() { public static Material DistilledWater; public static Material SodiumPotassium; public static Material SamariumMagnetic; + public static Material ManganesePhosphide; + public static Material MagnesiumDiboride; + public static Material MercuryBariumCalciumCuprate; + public static Material UraniumTriplatinum; + public static Material SamariumIronArsenicOxide; + public static Material IndiumTinBariumTitaniumCuprate; + public static Material UraniumRhodiumDinaquadide; + public static Material EnrichedNaquadahTriniumEuropiumDuranide; + public static Material RutheniumTriniumAmericiumNeutronate; /** * Organic chemistry @@ -635,9 +644,12 @@ public static void register() { public static Material DilutedSulfuricAcid; public static Material DilutedHydrochloricAcid; public static Material Flint; - public static Material NobleGases; public static Material Air; public static Material LiquidAir; + public static Material NetherAir; + public static Material LiquidNetherAir; + public static Material EnderAir; + public static Material LiquidEnderAir; /** * Third Degree Materials diff --git a/src/main/java/gregtech/api/unification/material/info/MaterialIconSet.java b/src/main/java/gregtech/api/unification/material/info/MaterialIconSet.java index 85981e989c8..622c2a183d2 100644 --- a/src/main/java/gregtech/api/unification/material/info/MaterialIconSet.java +++ b/src/main/java/gregtech/api/unification/material/info/MaterialIconSet.java @@ -1,50 +1,69 @@ package gregtech.api.unification.material.info; +import com.google.common.base.Preconditions; import crafttweaker.annotations.ZenRegister; import stanhebben.zenscript.annotations.ZenClass; import stanhebben.zenscript.annotations.ZenGetter; import stanhebben.zenscript.annotations.ZenMethod; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; + @ZenClass("mods.gregtech.material.MaterialIconSet") @ZenRegister -public enum MaterialIconSet { - - NONE, - METALLIC, - DULL, - MAGNETIC, - QUARTZ, - DIAMOND, - EMERALD, - SHINY, - SHARDS, - ROUGH, - FINE, - SAND, - FLINT, - RUBY, - LAPIS, - FLUID, - GAS, - LIGNITE, - OPAL, - GLASS, - WOOD, - LEAF, - GEM_HORIZONTAL, - GEM_VERTICAL, - PAPER, - NETHERSTAR, - BRIGHT; +public class MaterialIconSet { + + public static final Map ICON_SETS = new HashMap<>(); + + static int idCounter = 0; + + public static final MaterialIconSet NONE = new MaterialIconSet("NONE"); + public static final MaterialIconSet METALLIC = new MaterialIconSet("METALLIC"); + public static final MaterialIconSet DULL = new MaterialIconSet("DULL"); + public static final MaterialIconSet MAGNETIC = new MaterialIconSet("MAGNETIC"); + public static final MaterialIconSet QUARTZ = new MaterialIconSet("QUARTZ"); + public static final MaterialIconSet DIAMOND = new MaterialIconSet("DIAMOND"); + public static final MaterialIconSet EMERALD = new MaterialIconSet("EMERALD"); + public static final MaterialIconSet SHINY = new MaterialIconSet("SHINY"); + public static final MaterialIconSet SHARDS = new MaterialIconSet("SHARDS"); + public static final MaterialIconSet ROUGH = new MaterialIconSet("ROUGH"); + public static final MaterialIconSet FINE = new MaterialIconSet("FINE"); + public static final MaterialIconSet SAND = new MaterialIconSet("SAND"); + public static final MaterialIconSet FLINT = new MaterialIconSet("FLINT"); + public static final MaterialIconSet RUBY = new MaterialIconSet("RUBY"); + public static final MaterialIconSet LAPIS = new MaterialIconSet("LAPIS"); + public static final MaterialIconSet FLUID = new MaterialIconSet("FLUID"); + public static final MaterialIconSet GAS = new MaterialIconSet("GAS"); + public static final MaterialIconSet LIGNITE = new MaterialIconSet("LIGNITE"); + public static final MaterialIconSet OPAL = new MaterialIconSet("OPAL"); + public static final MaterialIconSet GLASS = new MaterialIconSet("GLASS"); + public static final MaterialIconSet WOOD = new MaterialIconSet("WOOD"); + public static final MaterialIconSet LEAF = new MaterialIconSet("LEAF"); + public static final MaterialIconSet GEM_HORIZONTAL = new MaterialIconSet("GEM_HORIZONTAL"); + public static final MaterialIconSet GEM_VERTICAL = new MaterialIconSet("GEM_VERTICAL"); + public static final MaterialIconSet PAPER = new MaterialIconSet("PAPER"); + public static final MaterialIconSet NETHERSTAR = new MaterialIconSet("NETHERSTAR"); + public static final MaterialIconSet BRIGHT = new MaterialIconSet("BRIGHT"); + + public final String name; + public final int id; + + public MaterialIconSet(String name) { + this.name = name.toLowerCase(Locale.ROOT); + Preconditions.checkArgument(!ICON_SETS.containsKey(this.name), "MaterialIconSet " + this.name + " already registered!"); + this.id = idCounter++; + ICON_SETS.put(this.name, this); + } @ZenGetter("name") public String getName() { - return name().toLowerCase(); + return name; } @ZenMethod("get") public static MaterialIconSet getByName(String name) { - return valueOf(name.toUpperCase()); + return ICON_SETS.get(name); } @Override diff --git a/src/main/java/gregtech/api/unification/material/info/MaterialIconType.java b/src/main/java/gregtech/api/unification/material/info/MaterialIconType.java index 534546bc117..e589d5ee856 100644 --- a/src/main/java/gregtech/api/unification/material/info/MaterialIconType.java +++ b/src/main/java/gregtech/api/unification/material/info/MaterialIconType.java @@ -1,133 +1,141 @@ package gregtech.api.unification.material.info; import com.google.common.base.CaseFormat; -import com.google.common.collect.ImmutableMap; +import com.google.common.base.Preconditions; import gregtech.api.GTValues; import net.minecraft.util.ResourceLocation; -public enum MaterialIconType { - - //ITEM TEXTURES - dustTiny, - dustSmall, - dust, - dustImpure, - dustPure, - crushed, - crushedPurified, - crushedCentrifuged, - gem, - nugget, - ingot, - ingotHot, - ingotDouble, - ingotTriple, - ingotQuadruple, - ingotQuintuple, - plate, - plateDouble, - plateTriple, - plateQuadruple, - plateQuintuple, - plateDense, - stick, - lens, - round, - bolt, - screw, - ring, - cell, - cellPlasma, - toolHeadSword, - toolHeadPickaxe, - toolHeadShovel, - toolHeadAxe, - toolHeadHoe, - toolHeadHammer, - toolHeadFile, - toolHeadSaw, - toolHeadBuzzSaw, - toolHeadDrill, - toolHeadChainsaw, - toolHeadSense, - toolHeadArrow, - toolHeadScrewdriver, - toolHeadBuzSaw, - toolHeadSoldering, - toolHeadWrench, - toolHeadUniversalSpade, - wireFine, - gearSmall, - rotor, - stickLong, - springSmall, - spring, - arrow, - gemChipped, - gemFlawed, - gemFlawless, - gemExquisite, - gear, - foil, - crateGtDust, - crateGtIngot, - crateGtGem, - crateGtPlate, - turbineBlade, - handleMallet, - toolHeadMallet, - plateCurved, - coke, - - //BLOCK TEXTURES - block, - fluid, - foilBlock, //todo unused - wire, //todo unused - ore, - frameGt, - pipeSide, //todo unused - pipeTiny, - pipeSmall, - pipeMedium, - pipeLarge, - pipeHuge, - - //USED FOR GREGIFICATION ADDON - oreChunk, - oreEnderChunk, - oreNetherChunk, - oreSandyChunk, - seed, - crop, - essence; - - public static final ImmutableMap values; - - static { - ImmutableMap.Builder builder = ImmutableMap.builder(); - for (MaterialIconType value : values()) { - builder.put(CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, value.name()), value); - } - values = builder.build(); +import java.util.HashMap; +import java.util.Map; + +public class MaterialIconType { + + public static final Map ICON_TYPES = new HashMap<>(); + + static int idCounter = 0; + + public static final MaterialIconType dustTiny = new MaterialIconType("dustTiny"); + public static final MaterialIconType dustSmall = new MaterialIconType("dustSmall"); + public static final MaterialIconType dust = new MaterialIconType("dust"); + public static final MaterialIconType dustImpure = new MaterialIconType("dustImpure"); + public static final MaterialIconType dustPure = new MaterialIconType("dustPure"); + + public static final MaterialIconType crushed = new MaterialIconType("crushed"); + public static final MaterialIconType crushedPurified = new MaterialIconType("crushedPurified"); + public static final MaterialIconType crushedCentrifuged = new MaterialIconType("crushedCentrifuged"); + + public static final MaterialIconType gem = new MaterialIconType("gem"); + public static final MaterialIconType gemChipped = new MaterialIconType("gemChipped"); + public static final MaterialIconType gemFlawed = new MaterialIconType("gemFlawed"); + public static final MaterialIconType gemFlawless = new MaterialIconType("gemFlawless"); + public static final MaterialIconType gemExquisite = new MaterialIconType("gemExquisite"); + + public static final MaterialIconType nugget = new MaterialIconType("nugget"); + + public static final MaterialIconType ingot = new MaterialIconType("ingot"); + public static final MaterialIconType ingotHot = new MaterialIconType("ingotHot"); + public static final MaterialIconType ingotDouble = new MaterialIconType("ingotDouble"); + public static final MaterialIconType ingotTriple = new MaterialIconType("ingotTriple"); + public static final MaterialIconType ingotQuadruple = new MaterialIconType("ingotQuadruple"); + public static final MaterialIconType ingotQuintuple = new MaterialIconType("ingotQuintuple"); + + public static final MaterialIconType plate = new MaterialIconType("plate"); + public static final MaterialIconType plateDouble = new MaterialIconType("plateDouble"); + public static final MaterialIconType plateTriple = new MaterialIconType("plateTriple"); + public static final MaterialIconType plateQuadruple = new MaterialIconType("plateQuadruple"); + public static final MaterialIconType plateQuintuple = new MaterialIconType("plateQuintuple"); + public static final MaterialIconType plateDense = new MaterialIconType("plateDense"); + + public static final MaterialIconType stick = new MaterialIconType("stick"); + public static final MaterialIconType lens = new MaterialIconType("lens"); + public static final MaterialIconType round = new MaterialIconType("round"); + public static final MaterialIconType bolt = new MaterialIconType("bolt"); + public static final MaterialIconType screw = new MaterialIconType("screw"); + public static final MaterialIconType ring = new MaterialIconType("ring"); + public static final MaterialIconType wireFine = new MaterialIconType("wireFine"); + public static final MaterialIconType gearSmall = new MaterialIconType("gearSmall"); + public static final MaterialIconType rotor = new MaterialIconType("rotor"); + public static final MaterialIconType stickLong = new MaterialIconType("stickLong"); + public static final MaterialIconType springSmall = new MaterialIconType("springSmall"); + public static final MaterialIconType spring = new MaterialIconType("spring"); + public static final MaterialIconType arrow = new MaterialIconType("arrow"); + public static final MaterialIconType gear = new MaterialIconType("gear"); + public static final MaterialIconType foil = new MaterialIconType("foil"); + + public static final MaterialIconType cell = new MaterialIconType("cell"); + public static final MaterialIconType cellPlasma = new MaterialIconType("cellPlasma"); + + public static final MaterialIconType toolHeadSword = new MaterialIconType("toolHeadSword"); + public static final MaterialIconType toolHeadPickaxe = new MaterialIconType("toolHeadPickaxe"); + public static final MaterialIconType toolHeadShovel = new MaterialIconType("toolHeadShovel"); + public static final MaterialIconType toolHeadAxe = new MaterialIconType("toolHeadAxe"); + public static final MaterialIconType toolHeadHoe = new MaterialIconType("toolHeadHoe"); + public static final MaterialIconType toolHeadHammer = new MaterialIconType("toolHeadHammer"); + public static final MaterialIconType toolHeadFile = new MaterialIconType("toolHeadFile"); + public static final MaterialIconType toolHeadSaw = new MaterialIconType("toolHeadSaw"); + public static final MaterialIconType toolHeadBuzzSaw = new MaterialIconType("toolHeadBuzzSaw"); + public static final MaterialIconType toolHeadDrill = new MaterialIconType("toolHeadDrill"); + public static final MaterialIconType toolHeadChainsaw = new MaterialIconType("toolHeadChainsaw"); + public static final MaterialIconType toolHeadSense = new MaterialIconType("toolHeadSense"); + public static final MaterialIconType toolHeadArrow = new MaterialIconType("toolHeadArrow"); + public static final MaterialIconType toolHeadScrewdriver = new MaterialIconType("toolHeadScrewdriver"); + public static final MaterialIconType toolHeadSoldering = new MaterialIconType("toolHeadSoldering"); + public static final MaterialIconType toolHeadWrench = new MaterialIconType("toolHeadWrench"); + public static final MaterialIconType toolHeadUniversalSpade = new MaterialIconType("toolHeadUniversalSpade"); + + public static final MaterialIconType crateGtDust = new MaterialIconType("crateGtDust"); + public static final MaterialIconType crateGtIngot = new MaterialIconType("crateGtIngot"); + public static final MaterialIconType crateGtGem = new MaterialIconType("crateGtGem"); + public static final MaterialIconType crateGtPlate = new MaterialIconType("crateGtPlate"); + + public static final MaterialIconType turbineBlade = new MaterialIconType("turbineBlade"); + public static final MaterialIconType handleMallet = new MaterialIconType("handleMallet"); + public static final MaterialIconType toolHeadMallet = new MaterialIconType("toolHeadMallet"); + public static final MaterialIconType plateCurved = new MaterialIconType("plateCurved"); + public static final MaterialIconType coke = new MaterialIconType("coke"); + + // BLOCK TEXTURES + public static final MaterialIconType block = new MaterialIconType("block"); + public static final MaterialIconType fluid = new MaterialIconType("fluid"); + public static final MaterialIconType foilBlock = new MaterialIconType("foilBlock"); + public static final MaterialIconType wire = new MaterialIconType("wire"); // TODO unused + public static final MaterialIconType ore = new MaterialIconType("ore"); + public static final MaterialIconType frameGt = new MaterialIconType("frameGt"); + + public static final MaterialIconType pipeSide = new MaterialIconType("pipeSide"); // TODO unused + public static final MaterialIconType pipeTiny = new MaterialIconType("pipeTiny"); + public static final MaterialIconType pipeSmall = new MaterialIconType("pipeSmall"); + public static final MaterialIconType pipeMedium = new MaterialIconType("pipeMedium"); + public static final MaterialIconType pipeLarge = new MaterialIconType("pipeLarge"); + public static final MaterialIconType pipeHuge = new MaterialIconType("pipeHuge"); + public static final MaterialIconType pipeQuadruple = new MaterialIconType("pipeQuadruple"); + public static final MaterialIconType pipeNonuple = new MaterialIconType("pipeNonuple"); + + // USED FOR GREGIFICATION ADDON + public static final MaterialIconType seed = new MaterialIconType("seed"); + public static final MaterialIconType crop = new MaterialIconType("crop"); + public static final MaterialIconType essence = new MaterialIconType("essence"); + + public final String name; + public final int id; + + public MaterialIconType(String name) { + this.name = CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, name); + Preconditions.checkArgument(!ICON_TYPES.containsKey(this.name), "MaterialIconType " + this.name + " already registered!"); + this.id = idCounter++; + ICON_TYPES.put(this.name, this); } public ResourceLocation getBlockPath(MaterialIconSet materialIconSet) { - String iconSet = materialIconSet.name().toLowerCase(); - String iconType = CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, name()); - return new ResourceLocation(GTValues.MODID, "blocks/material_sets/" + iconSet + "/" + iconType); + return new ResourceLocation(GTValues.MODID, "blocks/material_sets/" + materialIconSet.name + "/" + this.name); } public ResourceLocation getItemModelPath(MaterialIconSet materialIconSet) { - String iconSet = materialIconSet.name().toLowerCase(); - String iconType = CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, name()); - return new ResourceLocation(GTValues.MODID, "material_sets/" + iconSet + "/" + iconType); + return new ResourceLocation(GTValues.MODID, "material_sets/" + materialIconSet.name + "/" + this.name); } public ResourceLocation getItemOverlayPath(MaterialIconSet materialIconSet) { - String iconSet = materialIconSet.name().toLowerCase(); - String iconType = CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, name()); - return new ResourceLocation(GTValues.MODID, "material_sets/" + iconSet + "/" + iconType + "_overlay"); + return new ResourceLocation(GTValues.MODID, "material_sets/" + materialIconSet.name + "/" + this.name + "_overlay"); } } diff --git a/src/main/java/gregtech/api/unification/material/materials/ElementMaterials.java b/src/main/java/gregtech/api/unification/material/materials/ElementMaterials.java index d74e813dbb6..c6b40c99054 100644 --- a/src/main/java/gregtech/api/unification/material/materials/ElementMaterials.java +++ b/src/main/java/gregtech/api/unification/material/materials/ElementMaterials.java @@ -21,9 +21,9 @@ public static void register() { Aluminium = new Material.Builder(2, "aluminium") .ingot().fluid().ore() .color(0x80C8F0) - .flags(EXT2_METAL, GENERATE_SMALL_GEAR, GENERATE_RING, GENERATE_FRAME, GENERATE_SPRING) + .flags(EXT2_METAL, GENERATE_SMALL_GEAR, GENERATE_RING, GENERATE_FRAME, GENERATE_SPRING, GENERATE_SPRING_SMALL) .element(Elements.Al) - .toolStats(10.0f, 2.0f, 128) + .toolStats(10.0f, 2.0f, 128, 21) .cableProperties(GTValues.V[4], 1, 1) .fluidPipeProperties(1166, 35, true) .blastTemp(1700) @@ -66,6 +66,7 @@ public static void register() { .ingot().fluid() .color(0x83824C).iconSet(METALLIC) .element(Elements.Ba) + .flags(GENERATE_FOIL) .build(); Berkelium = new Material.Builder(9, "berkelium") @@ -98,6 +99,7 @@ public static void register() { .dust() .color(0xD2FAD2) .element(Elements.B) + .flags(GENERATE_ROD) .build(); Bromine = new Material.Builder(14, "bromine") @@ -116,6 +118,7 @@ public static void register() { .ingot().fluid() .color(0xFFF5F5).iconSet(METALLIC) .element(Elements.Ca) + .flags(GENERATE_FOIL) .build(); Californium = new Material.Builder(17, "californium") @@ -141,6 +144,7 @@ public static void register() { .ingot().fluid() .iconSet(METALLIC) .element(Elements.Ce) + .flags(GENERATE_FINE_WIRE) .blastTemp(1068) .build(); @@ -154,7 +158,7 @@ public static void register() { .color(0xFFE6E6).iconSet(SHINY) .flags(EXT2_METAL, GENERATE_ROTOR, GENERATE_DENSE) .element(Elements.Cr) - .toolStats(12.0f, 3.0f, 512) + .toolStats(12.0f, 3.0f, 512, 33) .fluidPipeProperties(2725, 40, true) .blastTemp(1700) .build(); @@ -162,9 +166,9 @@ public static void register() { Cobalt = new Material.Builder(23, "cobalt") .ingot().fluid().ore() .color(0x5050FA).iconSet(METALLIC) - .flags(STD_METAL) + .flags(STD_METAL, GENERATE_GEAR, GENERATE_BOLT_SCREW) .element(Elements.Co) - .toolStats(10.0f, 3.0f, 256) + .toolStats(10.0f, 3.0f, 256, 21) .cableProperties(GTValues.V[1], 2, 2) .itemPipeProperties(2560, 2.0f) .build(); @@ -178,7 +182,7 @@ public static void register() { Copper = new Material.Builder(25, "copper") .ingot(1).fluid().ore() .color(0xFF6400).iconSet(SHINY) - .flags(EXT2_METAL, MORTAR_GRINDABLE, GENERATE_DENSE, GENERATE_SPRING) + .flags(EXT2_METAL, MORTAR_GRINDABLE, GENERATE_DENSE, GENERATE_SPRING, GENERATE_SPRING_SMALL) .element(Elements.Cu) .cableProperties(GTValues.V[2], 1, 2) .fluidPipeProperties(1696, 10, true) @@ -234,7 +238,7 @@ public static void register() { Europium = new Material.Builder(33, "europium") .ingot().fluid() .iconSet(METALLIC) - .flags(STD_METAL, GENERATE_ROD, GENERATE_FINE_WIRE) + .flags(STD_METAL, GENERATE_LONG_ROD, GENERATE_FINE_WIRE, GENERATE_SPRING_SMALL) .element(Elements.Eu) .cableProperties(GTValues.V[GTValues.UHV], 2, 32) .fluidPipeProperties(7780, 1200, true) @@ -348,7 +352,7 @@ public static void register() { .color(0xF0F0F5) .flags(EXT2_METAL, GENERATE_ROTOR, GENERATE_DENSE) .element(Elements.Ir) - .toolStats(7.0f, 3.0f, 2560) + .toolStats(7.0f, 3.0f, 2560, 21) .fluidPipeProperties(3398, 140, true) .blastTemp(2719) .build(); @@ -359,7 +363,7 @@ public static void register() { .flags(EXT2_METAL, MORTAR_GRINDABLE, GENERATE_DENSE, GENERATE_FRAME, GENERATE_ROTOR, GENERATE_SMALL_GEAR, GENERATE_SPRING, GENERATE_SPRING_SMALL, EXCLUDE_BLOCK_CRAFTING_BY_HAND_RECIPES, BLAST_FURNACE_CALCITE_TRIPLE) .element(Elements.Fe) - .toolStats(7.0f, 2.5f, 256) + .toolStats(7.0f, 2.5f, 256, 21) .cableProperties(GTValues.V[2], 2, 3) .build(); @@ -385,7 +389,7 @@ public static void register() { Lead = new Material.Builder(55, "lead") .ingot(1).fluid().ore() .color(0x8C648C) - .flags(EXT2_METAL, MORTAR_GRINDABLE, GENERATE_DENSE, GENERATE_ROTOR, GENERATE_SPRING) + .flags(EXT2_METAL, MORTAR_GRINDABLE, GENERATE_DENSE, GENERATE_ROTOR, GENERATE_SPRING, GENERATE_SPRING_SMALL) .element(Elements.Pb) .cableProperties(GTValues.V[1], 2, 2) .fluidPipeProperties(1200, 15, true) @@ -427,9 +431,9 @@ public static void register() { Manganese = new Material.Builder(61, "manganese") .ingot().fluid() .color(0xFAFAFA) - .flags(STD_METAL, GENERATE_FOIL) + .flags(STD_METAL, GENERATE_FOIL, GENERATE_DENSE, GENERATE_BOLT_SCREW) .element(Elements.Mn) - .toolStats(7.0f, 2.0f, 512) + .toolStats(7.0f, 2.0f, 512, 21) .build(); Meitnerium = new Material.Builder(62, "meitnerium") @@ -448,7 +452,8 @@ public static void register() { .ingot().fluid().ore() .color(0xB4B4DC).iconSet(SHINY) .element(Elements.Mo) - .toolStats(7.0f, 2.0f, 512) + .flags(GENERATE_FOIL, GENERATE_BOLT_SCREW) + .toolStats(7.0f, 2.0f, 512, 33) .build(); Moscovium = new Material.Builder(65, "moscovium") @@ -460,9 +465,9 @@ public static void register() { Neodymium = new Material.Builder(66, "neodymium") .ingot().fluid().ore() .color(0x646464).iconSet(METALLIC) - .flags(STD_METAL, GENERATE_ROD) + .flags(STD_METAL, GENERATE_ROD, GENERATE_BOLT_SCREW) .element(Elements.Nd) - .toolStats(7.0f, 2.0f, 512) + .toolStats(7.0f, 2.0f, 512, 21) .blastTemp(1297) .build(); @@ -526,7 +531,7 @@ public static void register() { .color(0x3232FF).iconSet(METALLIC) .flags(EXT2_METAL, GENERATE_ROTOR, GENERATE_DENSE) .element(Elements.Os) - .toolStats(16.0f, 4.0f, 1280) + .toolStats(16.0f, 4.0f, 1280, 21) .cableProperties(GTValues.V[5], 4, 2) .itemPipeProperties(256, 8.0f) .blastTemp(3306) @@ -543,7 +548,7 @@ public static void register() { .color(0x808080).iconSet(SHINY) .flags(EXT2_METAL) .element(Elements.Pd) - .toolStats(8.0f, 2.0f, 512) + .toolStats(8.0f, 2.0f, 512, 33) .cableProperties(GTValues.V[5], 2, 1) .blastTemp(1228) .build(); @@ -727,7 +732,7 @@ public static void register() { .build(); Sulfur = new Material.Builder(103, "sulfur") - .dust().ore() + .dust().ore().fluid() .color(0xC8C800) .flags(FLAMMABLE) .element(Elements.S) @@ -770,9 +775,9 @@ public static void register() { Thorium = new Material.Builder(109, "thorium") .ingot().fluid().ore() .color(0x001E00).iconSet(SHINY) - .flags(STD_METAL) + .flags(STD_METAL, GENERATE_ROD) .element(Elements.Th) - .toolStats(6.0f, 2.0f, 512) + .toolStats(6.0f, 2.0f, 512, 33) .build(); Thallium = new Material.Builder(110, "thallium") @@ -792,7 +797,7 @@ public static void register() { Tin = new Material.Builder(112, "tin") .ingot(1).fluid().ore() .color(0xDCDCDC) - .flags(EXT2_METAL, MORTAR_GRINDABLE, GENERATE_ROTOR, GENERATE_SPRING) + .flags(EXT2_METAL, MORTAR_GRINDABLE, GENERATE_ROTOR, GENERATE_SPRING, GENERATE_SPRING_SMALL) .element(Elements.Sn) .cableProperties(GTValues.V[1], 1, 1) .itemPipeProperties(4096, 0.5f) @@ -803,7 +808,7 @@ public static void register() { .color(0xDCA0F0).iconSet(METALLIC) .flags(EXT2_METAL, GENERATE_ROTOR, GENERATE_SMALL_GEAR, GENERATE_SPRING, GENERATE_FRAME, GENERATE_DENSE) .element(Elements.Ti) - .toolStats(7.0f, 3.0f, 1600) + .toolStats(7.0f, 3.0f, 1600, 21) .cableProperties(GTValues.V[4], 4, 2) .fluidPipeProperties(2426, 80, true) .blastTemp(1941) @@ -818,9 +823,9 @@ public static void register() { Tungsten = new Material.Builder(115, "tungsten") .ingot(3).fluid() .color(0x323232).iconSet(METALLIC) - .flags(EXT2_METAL, GENERATE_SPRING) + .flags(EXT2_METAL, GENERATE_SPRING, GENERATE_SPRING_SMALL) .element(Elements.W) - .toolStats(7.0f, 3.0f, 2560) + .toolStats(7.0f, 3.0f, 2560, 21) .cableProperties(GTValues.V[5], 2, 2) .fluidPipeProperties(4618, 90, true) .blastTemp(3000) @@ -831,7 +836,7 @@ public static void register() { .color(0x32F032).iconSet(METALLIC) .flags(STD_METAL) .element(Elements.U238) - .toolStats(6.0f, 3.0f, 512) + .toolStats(6.0f, 3.0f, 512, 21) .build(); Uranium235 = new Material.Builder(117, "uranium235") @@ -839,7 +844,7 @@ public static void register() { .color(0x46FA46).iconSet(SHINY) .flags(STD_METAL, GENERATE_ROD) .element(Elements.U235) - .toolStats(6.0f, 3.0f, 512) + .toolStats(6.0f, 3.0f, 512, 33) .build(); Vanadium = new Material.Builder(118, "vanadium") @@ -868,14 +873,14 @@ public static void register() { .ingot().fluid() .color(0xDCFADC).iconSet(METALLIC) .flags(STD_METAL) - .element(Elements.Yt) + .element(Elements.Y) .blastTemp(1799) .build(); Zinc = new Material.Builder(122, "zinc") .ingot(1).fluid().ore() .color(0xFAF0F0).iconSet(METALLIC) - .flags(STD_METAL, MORTAR_GRINDABLE, GENERATE_FOIL, GENERATE_RING) + .flags(STD_METAL, MORTAR_GRINDABLE, GENERATE_FOIL, GENERATE_RING, GENERATE_FINE_WIRE) .element(Elements.Zn) .cableProperties(GTValues.V[1], 1, 1) .build(); @@ -892,7 +897,7 @@ public static void register() { .color(0x323232).iconSet(METALLIC) .flags(EXT_METAL, GENERATE_FOIL, GENERATE_SPRING) .element(Elements.Nq) - .toolStats(6.0f, 4.0f, 1280) + .toolStats(6.0f, 4.0f, 1280, 21) .cableProperties(GTValues.V[7], 2, 2) .fluidPipeProperties(19200, 1500, true) .blastTemp(5400) @@ -903,14 +908,14 @@ public static void register() { .color(0x3C3C3C).iconSet(METALLIC) .flags(EXT_METAL, GENERATE_FOIL) .element(Elements.Nq1) - .toolStats(6.0f, 4.0f, 1280) + .toolStats(6.0f, 4.0f, 1280, 21) .blastTemp(4500) .build(); Naquadria = new Material.Builder(126, "naquadria") .ingot(3).fluid() .color(0x1E1E1E).iconSet(SHINY) - .flags(EXT_METAL, GENERATE_FOIL) + .flags(EXT_METAL, GENERATE_FOIL, GENERATE_GEAR, GENERATE_DENSE) .element(Elements.Nq2) .blastTemp(9000) .build(); @@ -920,24 +925,24 @@ public static void register() { .color(0xFAFAFA) .flags(EXT2_METAL, GENERATE_ROTOR, GENERATE_SMALL_GEAR, GENERATE_FRAME) .element(Elements.Nt) - .toolStats(24.0f, 12.0f, 655360) + .toolStats(24.0f, 12.0f, 655360, 21) .fluidPipeProperties(1000000, 2800, true) .build(); Tritanium = new Material.Builder(128, "tritanium") .ingot(6).fluid() .color(0x600000).iconSet(METALLIC) - .flags(EXT_METAL, GENERATE_FRAME) + .flags(EXT_METAL, GENERATE_FRAME, GENERATE_ROUND) .element(Elements.Tr) - .toolStats(20.0f, 6.0f, 10240) + .toolStats(20.0f, 6.0f, 10240, 21) .build(); Duranium = new Material.Builder(129, "duranium") .ingot(5).fluid() .color(0x4BAFAF).iconSet(METALLIC) - .flags(EXT_METAL, GENERATE_FOIL) + .flags(EXT_METAL, GENERATE_FOIL, GENERATE_FINE_WIRE) .element(Elements.Dr) - .toolStats(16.0f, 5.0f, 5120) + .toolStats(16.0f, 5.0f, 5120, 21) .cableProperties(GTValues.V[8], 1, 8) .fluidPipeProperties(100000, 2000, true) .build(); diff --git a/src/main/java/gregtech/api/unification/material/materials/FirstDegreeMaterials.java b/src/main/java/gregtech/api/unification/material/materials/FirstDegreeMaterials.java index 68e5acf36e7..9ff0f871006 100644 --- a/src/main/java/gregtech/api/unification/material/materials/FirstDegreeMaterials.java +++ b/src/main/java/gregtech/api/unification/material/materials/FirstDegreeMaterials.java @@ -67,7 +67,7 @@ public static void register() { .color(0x7B96DC).iconSet(GEM_HORIZONTAL) .flags(NO_SMASHING, NO_SMELTING, HIGH_SIFTER_OUTPUT) .components(Aluminium, 2, Silicon, 1, Fluorine, 2, Hydrogen, 2, Oxygen, 6) - .toolStats(7.0f, 3.0f, 256) + .toolStats(7.0f, 3.0f, 256, 15) .build(); Bone = new Material.Builder(258, "bone") @@ -82,7 +82,7 @@ public static void register() { .color(0xFFB400).iconSet(METALLIC) .flags(EXT2_METAL, MORTAR_GRINDABLE, GENERATE_RING) .components(Zinc, 1, Copper, 3) - .toolStats(8.0f, 3.0f, 152) + .toolStats(8.0f, 3.0f, 152, 21) .itemPipeProperties(2048, 1) .build(); @@ -91,7 +91,7 @@ public static void register() { .color(0xFF8000).iconSet(METALLIC) .flags(EXT2_METAL, MORTAR_GRINDABLE, GENERATE_ROTOR, GENERATE_FRAME) .components(Tin, 1, Copper, 3) - .toolStats(6.0f, 2.5f, 192) + .toolStats(6.0f, 2.5f, 192, 21) .fluidPipeProperties(1696, 20, true) .build(); @@ -182,7 +182,7 @@ public static void register() { Cupronickel = new Material.Builder(274, "cupronickel") .ingot(1).fluid() .color(0xE39680).iconSet(METALLIC) - .flags(EXT_METAL, GENERATE_SPRING) + .flags(EXT_METAL, GENERATE_SPRING, GENERATE_FINE_WIRE) .components(Copper, 1, Nickel, 1) .itemPipeProperties(2048, 1) .cableProperties(GTValues.V[1], 1, 1) @@ -200,7 +200,8 @@ public static void register() { .color(0xC8FFFF).iconSet(DIAMOND) .flags(GENERATE_BOLT_SCREW, GENERATE_LENS, GENERATE_GEAR, NO_SMASHING, NO_SMELTING, FLAMMABLE, HIGH_SIFTER_OUTPUT, DISABLE_DECOMPOSITION, EXCLUDE_BLOCK_CRAFTING_BY_HAND_RECIPES) - .toolStats(8.0f, 3.0f, 1280) + .components(Carbon, 1) + .toolStats(8.0f, 3.0f, 1280, 15) .build(); Electrum = new Material.Builder(277, "electrum") @@ -215,9 +216,9 @@ public static void register() { Emerald = new Material.Builder(278, "emerald") .gem().ore() .color(0x50FF50).iconSet(EMERALD) - .flags(NO_SMASHING, NO_SMELTING, HIGH_SIFTER_OUTPUT, EXCLUDE_BLOCK_CRAFTING_BY_HAND_RECIPES) + .flags(NO_SMASHING, NO_SMELTING, HIGH_SIFTER_OUTPUT, EXCLUDE_BLOCK_CRAFTING_BY_HAND_RECIPES, GENERATE_PLATE) .components(Beryllium, 3, Aluminium, 2, Silicon, 6, Oxygen, 18) - .toolStats(10.0f, 2.0f, 368) + .toolStats(10.0f, 2.0f, 368, 15) .build(); Galena = new Material.Builder(279, "galena") @@ -238,7 +239,7 @@ public static void register() { .color(0x64C882).iconSet(GEM_HORIZONTAL) .flags(NO_SMASHING, NO_SMELTING, HIGH_SIFTER_OUTPUT, GENERATE_LENS) .components(Aluminium, 2, Oxygen, 3) - .toolStats(8.0f, 3.0f, 368) + .toolStats(8.0f, 3.0f, 368, 15) .build(); Grossular = new Material.Builder(282, "grossular") @@ -280,7 +281,7 @@ public static void register() { .color(0xB4B478).iconSet(METALLIC) .flags(EXT2_METAL, MORTAR_GRINDABLE, GENERATE_RING, GENERATE_FRAME) .components(Iron, 2, Nickel, 1) - .toolStats(7.0f, 3.0f, 512) + .toolStats(7.0f, 3.0f, 512, 21) .addDefaultEnchant(Enchantments.BANE_OF_ARTHROPODS, 3) .fluidPipeProperties(2395, 40, true) .build(); @@ -306,7 +307,7 @@ public static void register() { .color(0xC8BEFF) .flags(EXT2_METAL) .components(Magnesium, 1, Aluminium, 2) - .toolStats(6.0f, 2.0f, 256) + .toolStats(6.0f, 2.0f, 256, 21) .itemPipeProperties(1024, 2) .build(); @@ -342,13 +343,14 @@ public static void register() { .color(0x1D291D) .flags(EXT_METAL) .components(Niobium, 1, Nitrogen, 1) + .cableProperties(GTValues.V[6], 1, 1) .blastTemp(2573) .build(); NiobiumTitanium = new Material.Builder(296, "niobium_titanium") .ingot().fluid() .color(0x1D1D29) - .flags(EXT2_METAL, GENERATE_SPRING) + .flags(EXT2_METAL, GENERATE_SPRING, GENERATE_SPRING_SMALL) .components(Niobium, 1, Titanium, 1) .fluidPipeProperties(2900, 150, true) .cableProperties(GTValues.V[6], 4, 2) @@ -374,7 +376,7 @@ public static void register() { .color(0xC8B4B4).iconSet(METALLIC) .flags(EXT_METAL, GENERATE_RING, BLAST_FURNACE_CALCITE_TRIPLE) .components(Iron, 1) - .toolStats(6.0f, 4.0f, 384) + .toolStats(6.0f, 4.0f, 384, 21) .build(); SterlingSilver = new Material.Builder(300, "sterling_silver") @@ -382,7 +384,7 @@ public static void register() { .color(0xFADCE1).iconSet(SHINY) .flags(EXT2_METAL) .components(Copper, 1, Silver, 4) - .toolStats(13.0f, 2.0f, 196) + .toolStats(13.0f, 2.0f, 196, 33) .itemPipeProperties(1024, 2) .blastTemp(1700) .build(); @@ -392,7 +394,7 @@ public static void register() { .color(0xFFE61E).iconSet(SHINY) .flags(EXT2_METAL) .components(Copper, 1, Gold, 4) - .toolStats(14.0f, 2.0f, 152) + .toolStats(14.0f, 2.0f, 152, 33) .addDefaultEnchant(Enchantments.SMITE, 4) .itemPipeProperties(1024, 2) .blastTemp(1600) @@ -403,7 +405,7 @@ public static void register() { .color(0x64327D) .flags(EXT2_METAL) .components(Gold, 1, Silver, 1, Copper, 3) - .toolStats(12.0f, 2.0f, 256) + .toolStats(12.0f, 2.0f, 256, 21) .addDefaultEnchant(Enchantments.SMITE, 2) .itemPipeProperties(1024, 2) .blastTemp(2000) @@ -414,7 +416,7 @@ public static void register() { .color(0x647D7D) .flags(EXT2_METAL) .components(Bismuth, 1, Zinc, 1, Copper, 3) - .toolStats(8.0f, 3.0f, 256) + .toolStats(8.0f, 3.0f, 256, 21) .addDefaultEnchant(Enchantments.BANE_OF_ARTHROPODS, 5) .blastTemp(1100) .build(); @@ -465,7 +467,7 @@ public static void register() { .color(0xFF6464).iconSet(RUBY) .flags(NO_SMASHING, NO_SMELTING, HIGH_SIFTER_OUTPUT) .components(Chrome, 1, Aluminium, 2, Oxygen, 3) - .toolStats(8.5f, 3.0f, 256) + .toolStats(8.5f, 3.0f, 256, 33) .build(); Salt = new Material.Builder(312, "salt") @@ -487,7 +489,7 @@ public static void register() { .color(0x6464C8).iconSet(GEM_VERTICAL) .flags(NO_SMASHING, NO_SMELTING, HIGH_SIFTER_OUTPUT, GENERATE_LENS) .components(Aluminium, 2, Oxygen, 3) - .toolStats(7.5f, 4.0f, 256) + .toolStats(7.5f, 4.0f, 256, 15) .build(); Scheelite = new Material.Builder(315, "scheelite") @@ -508,7 +510,7 @@ public static void register() { .ingot(4).fluid() .color(0x755280).iconSet(METALLIC) .components(Americium, 2, Titanium, 1) - .toolStats(6.0f, 6.0f, 2200) + .toolStats(6.0f, 6.0f, 2200, 21) .itemPipeProperties(32, 128) .cableProperties(GTValues.V[10], 8, 16) .blastTemp(10400) @@ -551,9 +553,9 @@ public static void register() { StainlessSteel = new Material.Builder(323, "stainless_steel") .ingot().fluid() .color(0xC8C8DC).iconSet(SHINY) - .flags(EXT2_METAL, GENERATE_ROTOR, GENERATE_SMALL_GEAR, GENERATE_FRAME, GENERATE_LONG_ROD) + .flags(EXT2_METAL, GENERATE_ROTOR, GENERATE_SMALL_GEAR, GENERATE_FRAME, GENERATE_LONG_ROD, GENERATE_DENSE) .components(Iron, 7, Chrome, 1, Manganese, 1, Nickel, 1) - .toolStats(7.0f, 4.0f, 480) + .toolStats(7.0f, 4.0f, 480, 33) .fluidPipeProperties(2428, 60, true) .blastTemp(1700) .build(); @@ -564,7 +566,7 @@ public static void register() { .flags(EXT2_METAL, MORTAR_GRINDABLE, GENERATE_ROTOR, GENERATE_SMALL_GEAR, GENERATE_DENSE, GENERATE_SPRING, GENERATE_SPRING_SMALL, GENERATE_FRAME, DISABLE_DECOMPOSITION) .components(Iron, 1) - .toolStats(6.0f, 3.0f, 512) + .toolStats(6.0f, 3.0f, 512, 21) .fluidPipeProperties(2557, 40, true) .cableProperties(GTValues.V[4], 2, 2) .blastTemp(1000) @@ -582,7 +584,7 @@ public static void register() { .color(0x4000C8).iconSet(GEM_VERTICAL) .flags(EXT_METAL, NO_SMASHING, NO_SMELTING, HIGH_SIFTER_OUTPUT, GENERATE_LENS) .components(Calcium, 2, Aluminium, 3, Silicon, 3, Hydrogen, 1) - .toolStats(7.0f, 2.0f, 256) + .toolStats(7.0f, 2.0f, 256, 15) .build(); Tetrahedrite = new Material.Builder(327, "tetrahedrite") @@ -604,7 +606,7 @@ public static void register() { .color(0xFF8000).iconSet(GEM_HORIZONTAL) .flags(NO_SMASHING, NO_SMELTING, HIGH_SIFTER_OUTPUT, GENERATE_LENS) .components(Aluminium, 2, Silicon, 1, Fluorine, 1, Hydrogen, 2) - .toolStats(7.0f, 2.0f, 256) + .toolStats(7.0f, 2.0f, 256, 15) .build(); Tungstate = new Material.Builder(330, "tungstate") @@ -619,7 +621,7 @@ public static void register() { .color(0xB4B4E6).iconSet(SHINY) .flags(EXT2_METAL) .components(Cobalt, 5, Chrome, 2, Nickel, 1, Molybdenum, 1) - .toolStats(9.0f, 4.0f, 2048) + .toolStats(9.0f, 4.0f, 2048, 33) .itemPipeProperties(128, 16) .blastTemp(2700) .build(); @@ -641,9 +643,9 @@ public static void register() { VanadiumGallium = new Material.Builder(334, "vanadium_gallium") .ingot().fluid() .color(0x80808C).iconSet(SHINY) - .flags(STD_METAL, GENERATE_FOIL, GENERATE_SPRING) + .flags(STD_METAL, GENERATE_FOIL, GENERATE_SPRING, GENERATE_SPRING_SMALL) .components(Vanadium, 3, Gallium, 1) - .cableProperties(GTValues.V[6], 4, 2) + .cableProperties(GTValues.V[7], 4, 2) .blastTemp(4500) .build(); @@ -652,10 +654,11 @@ public static void register() { .color(0xC8B4B4).iconSet(METALLIC) .flags(EXT2_METAL, MORTAR_GRINDABLE, GENERATE_RING, GENERATE_LONG_ROD, DISABLE_DECOMPOSITION, BLAST_FURNACE_CALCITE_TRIPLE) .components(Iron, 1) - .toolStats(6.0f, 3.5f, 384) + .toolStats(6.0f, 3.5f, 384, 21) .fluidPipeProperties(2387, 30, true) .build(); Iron.getProperty(PropertyKey.INGOT).setSmeltingInto(WroughtIron); + Iron.getProperty(PropertyKey.INGOT).setArcSmeltingInto(WroughtIron); Wulfenite = new Material.Builder(336, "wulfenite") .dust(3).ore() @@ -673,9 +676,9 @@ public static void register() { YttriumBariumCuprate = new Material.Builder(338, "yttrium_barium_cuprate") .ingot().fluid() .color(0x504046).iconSet(METALLIC) - .flags(EXT_METAL, GENERATE_FINE_WIRE, GENERATE_SPRING) + .flags(EXT_METAL, GENERATE_FINE_WIRE, GENERATE_SPRING, GENERATE_SPRING_SMALL) .components(Yttrium, 1, Barium, 2, Copper, 3, Oxygen, 7) - .cableProperties(GTValues.V[6], 4, 4) + .cableProperties(GTValues.V[8], 4, 4) .build(); NetherQuartz = new Material.Builder(339, "nether_quartz") @@ -725,7 +728,7 @@ public static void register() { .color(0x6464FF).iconSet(METALLIC) .flags(EXT2_METAL) .components(Iridium, 3, Osmium, 1) - .toolStats(9.0f, 3.0f, 3152) + .toolStats(9.0f, 3.0f, 3152, 21) .itemPipeProperties(64, 32) .blastTemp(2500) .build(); @@ -1054,7 +1057,7 @@ public static void register() { .color(0x330066).iconSet(METALLIC) .flags(EXT2_METAL) .components(Tungsten, 1, Carbon, 1) - .toolStats(12.0f, 4.0f, 1280) + .toolStats(12.0f, 4.0f, 1280, 21) .fluidPipeProperties(7568, 125, true) .blastTemp(2460) .build(); @@ -1080,6 +1083,8 @@ public static void register() { HydrogenSulfide = new Material.Builder(400, "hydrogen_sulfide") .fluid(Material.FluidType.GAS) + .flags(DISABLE_DECOMPOSITION) + .components(Hydrogen, 2, Sulfur, 1) .build(); NitricAcid = new Material.Builder(401, "nitric_acid") @@ -1145,6 +1150,7 @@ public static void register() { .fluid() .color(0x060B0B) .flags(DECOMPOSITION_BY_ELECTROLYZING) + .components(Iron, 1, Chlorine, 3) .build(); UraniumHexafluoride = new Material.Builder(412, "uranium_hexafluoride") @@ -1239,5 +1245,88 @@ public static void register() { .blastTemp(1345) .build(); Samarium.getProperty(PropertyKey.INGOT).setMagneticMaterial(SamariumMagnetic); + + ManganesePhosphide = new Material.Builder(424, "manganese_phosphide") + .ingot() + .color(0xE1B454).iconSet(METALLIC) + .flags(DECOMPOSITION_BY_ELECTROLYZING) + .components(Manganese, 1, Phosphorus, 1) + .cableProperties(GTValues.V[GTValues.LV], 2, 0, true) + .blastTemp(1200) + .build(); + + MagnesiumDiboride = new Material.Builder(425, "magnesium_diboride") + .ingot() + .color(0x331900).iconSet(METALLIC) + .flags(DECOMPOSITION_BY_ELECTROLYZING) + .components(Magnesium, 1, Boron, 2) + .cableProperties(GTValues.V[GTValues.MV], 4, 0, true) + .blastTemp(2500) + .build(); + + MercuryBariumCalciumCuprate = new Material.Builder(426, "mercury_barium_calcium_cuprate") + .ingot() + .color(0x555555).iconSet(SHINY) + .flags(DECOMPOSITION_BY_ELECTROLYZING) + .components(Mercury, 1, Barium, 2, Calcium, 2, Copper, 3, Oxygen, 8) + .cableProperties(GTValues.V[GTValues.HV], 4, 0, true) + .blastTemp(3300) + .build(); + + UraniumTriplatinum = new Material.Builder(427, "uranium_triplatinum") + .ingot() + .color(0x008700).iconSet(SHINY) + .flags(DECOMPOSITION_BY_CENTRIFUGING) + .components(Uranium238, 1, Platinum, 3) + .cableProperties(GTValues.V[GTValues.EV], 6, 0, true) + .blastTemp(4400) + .build() + .setFormula("UPt3", true); + + SamariumIronArsenicOxide = new Material.Builder(428, "samarium_iron_arsenic_oxide") + .ingot() + .color(0x330033).iconSet(SHINY) + .flags(DECOMPOSITION_BY_CENTRIFUGING) + .components(Samarium, 1, Iron, 1, Arsenic, 1, Oxygen, 1) + .cableProperties(GTValues.V[GTValues.IV], 6, 0, true) + .blastTemp(5200) + .build(); + + IndiumTinBariumTitaniumCuprate = new Material.Builder(429, "indium_tin_barium_titanium_cuprate") + .ingot() + .color(0x994C00).iconSet(METALLIC) + .flags(DECOMPOSITION_BY_ELECTROLYZING) + .components(Indium, 4, Tin, 2, Barium, 2, Titanium, 1, Copper, 7, Oxygen, 14) + .cableProperties(GTValues.V[GTValues.LuV], 8, 0, true) + .blastTemp(6000) + .build(); + + UraniumRhodiumDinaquadide = new Material.Builder(430, "uranium_rhodium_dinaquadide") + .ingot() + .color(0x0A0A0A) + .flags(DECOMPOSITION_BY_CENTRIFUGING) + .components(Uranium238, 1, Rhodium, 1, Naquadah, 2) + .cableProperties(GTValues.V[GTValues.ZPM], 8, 0, true) + .blastTemp(9000) + .build() + .setFormula("URhNq2", true); + + EnrichedNaquadahTriniumEuropiumDuranide = new Material.Builder(431, "enriched_naquadah_trinium_europium_duranide") + .ingot() + .color(0x7D9673).iconSet(METALLIC) + .flags(DECOMPOSITION_BY_CENTRIFUGING) + .components(NaquadahEnriched, 4, Trinium, 3, Europium, 2, Duranium, 1) + .cableProperties(GTValues.V[GTValues.UV], 16, 0, true) + .blastTemp(9900) + .build(); + + RutheniumTriniumAmericiumNeutronate = new Material.Builder(432, "ruthenium_trinium_americium_neutronate") + .ingot() + .color(0xFFFFFF).iconSet(BRIGHT) + .flags(DECOMPOSITION_BY_ELECTROLYZING) + .components(Ruthenium, 1, Trinium, 2, Americium, 1, Neutronium, 2, Oxygen, 8) + .cableProperties(GTValues.V[GTValues.MAX], 24, 0, true) + .blastTemp(10800) + .build(); } } diff --git a/src/main/java/gregtech/api/unification/material/materials/HigherDegreeMaterials.java b/src/main/java/gregtech/api/unification/material/materials/HigherDegreeMaterials.java index ffb7c240862..31e757bba4a 100644 --- a/src/main/java/gregtech/api/unification/material/materials/HigherDegreeMaterials.java +++ b/src/main/java/gregtech/api/unification/material/materials/HigherDegreeMaterials.java @@ -35,18 +35,18 @@ public static void register() { RedSteel = new Material.Builder(2510, "red_steel") .ingot().fluid() .color(0x8C6464).iconSet(METALLIC) - .flags(EXT_METAL) + .flags(EXT_METAL, GENERATE_GEAR) .components(SterlingSilver, 1, BismuthBronze, 1, Steel, 2, BlackSteel, 4) - .toolStats(7.0f, 4.5f, 896) + .toolStats(7.0f, 4.5f, 896, 21) .blastTemp(1300) .build(); BlueSteel = new Material.Builder(2511, "blue_steel") .ingot().fluid() .color(0x64648C).iconSet(METALLIC) - .flags(EXT_METAL, GENERATE_FRAME) + .flags(EXT_METAL, GENERATE_FRAME, GENERATE_GEAR) .components(RoseGold, 1, Brass, 1, Steel, 2, BlackSteel, 4) - .toolStats(7.5f, 5.0f, 1024) + .toolStats(7.5f, 5.0f, 1024, 21) .blastTemp(1400) .build(); @@ -82,7 +82,7 @@ public static void register() { .color(0x999900).iconSet(METALLIC) .flags(EXT2_METAL, GENERATE_ROTOR, GENERATE_SMALL_GEAR, GENERATE_FRAME, GENERATE_SPRING) .components(TungstenSteel, 5, Chrome, 1, Molybdenum, 2, Vanadium, 1) - .toolStats(10.0f, 5.5f, 4000) + .toolStats(10.0f, 5.5f, 4000, 21) .cableProperties(GTValues.V[6], 4, 2) .blastTemp(4200) .build(); @@ -110,7 +110,7 @@ public static void register() { .color(0x336600).iconSet(METALLIC) .flags(EXT2_METAL, GENERATE_ROTOR, GENERATE_SMALL_GEAR, GENERATE_FRAME) .components(HSSG, 6, Cobalt, 1, Manganese, 1, Silicon, 1) - .toolStats(10.0f, 8.0f, 5120) + .toolStats(10.0f, 8.0f, 5120, 21) .blastTemp(5000) .build(); @@ -119,7 +119,7 @@ public static void register() { .color(0x660033).iconSet(METALLIC) .flags(EXT2_METAL, GENERATE_SMALL_GEAR) .components(HSSG, 6, Iridium, 2, Osmium, 1) - .toolStats(15.0f, 7.0f, 3000) + .toolStats(15.0f, 7.0f, 3000, 21) .blastTemp(5000) .build(); @@ -128,7 +128,7 @@ public static void register() { .color(0xf2ef27).iconSet(METALLIC) .flags(EXT2_METAL) .components(Electrum, 1, NaquadahAlloy, 1, BlueSteel, 1, RedSteel, 1) - .toolStats(11.0f, 6.0f, 2100) + .toolStats(11.0f, 6.0f, 2100, 21) .cableProperties(GTValues.V[8], 3, 2) .itemPipeProperties(128, 16) .blastTemp(9000) diff --git a/src/main/java/gregtech/api/unification/material/materials/OrganicChemistryMaterials.java b/src/main/java/gregtech/api/unification/material/materials/OrganicChemistryMaterials.java index 3ef35493ccf..d53c2417f1f 100644 --- a/src/main/java/gregtech/api/unification/material/materials/OrganicChemistryMaterials.java +++ b/src/main/java/gregtech/api/unification/material/materials/OrganicChemistryMaterials.java @@ -56,7 +56,7 @@ public static void register() { ReinforcedEpoxyResin = new Material.Builder(1006, "reinforced_epoxy_resin") .ingot().fluid() .color(0xA07A10) - .flags(STD_METAL, DISABLE_DECOMPOSITION, NO_SMASHING) + .flags(STD_METAL, DISABLE_DECOMPOSITION, NO_SMASHING, GENERATE_FINE_WIRE, GENERATE_ROD) .components(Carbon, 6, Hydrogen, 4, Oxygen, 1) .build(); @@ -99,7 +99,7 @@ public static void register() { Polyethylene = new Material.Builder(1012, "plastic") //todo add polyethylene oredicts .ingot(1).fluid() .color(0xC8C8C8) - .flags(GENERATE_FOIL, FLAMMABLE, NO_SMASHING, DISABLE_DECOMPOSITION) + .flags(GENERATE_FOIL, GENERATE_ROTOR, FLAMMABLE, NO_SMASHING, DISABLE_DECOMPOSITION) .components(Carbon, 1, Hydrogen, 2) .fluidPipeProperties(350, 60, true) .build(); @@ -121,14 +121,14 @@ public static void register() { Polycaprolactam = new Material.Builder(1015, "polycaprolactam") .ingot(1).fluid() .color(0x323232) - .flags(STD_METAL, DISABLE_DECOMPOSITION, NO_SMASHING) + .flags(STD_METAL, DISABLE_DECOMPOSITION, NO_SMASHING, GENERATE_FOIL) .components(Carbon, 6, Hydrogen, 11, Nitrogen, 1, Oxygen, 1) .build(); Polytetrafluoroethylene = new Material.Builder(1016, "polytetrafluoroethylene") .ingot(1).fluid() .color(0x646464) - .flags(STD_METAL, GENERATE_FRAME, DISABLE_DECOMPOSITION, NO_SMASHING) + .flags(STD_METAL, GENERATE_FRAME, DISABLE_DECOMPOSITION, NO_SMASHING, GENERATE_FOIL) .components(Carbon, 2, Fluorine, 4) .fluidPipeProperties(600, 80, true) .build(); @@ -470,7 +470,7 @@ public static void register() { Rubber = new Material.Builder(1068, "rubber") .ingot(0).fluid() .color(0x000000).iconSet(SHINY) - .flags(GENERATE_GEAR, GENERATE_RING, FLAMMABLE, NO_SMASHING, DISABLE_DECOMPOSITION) + .flags(GENERATE_GEAR, GENERATE_RING, FLAMMABLE, NO_SMASHING, DISABLE_DECOMPOSITION, GENERATE_FOIL, GENERATE_BOLT_SCREW) .components(Carbon, 5, Hydrogen, 8) .build(); } diff --git a/src/main/java/gregtech/api/unification/material/materials/SecondDegreeMaterials.java b/src/main/java/gregtech/api/unification/material/materials/SecondDegreeMaterials.java index 2d7c0f873b4..95d2f8e297e 100644 --- a/src/main/java/gregtech/api/unification/material/materials/SecondDegreeMaterials.java +++ b/src/main/java/gregtech/api/unification/material/materials/SecondDegreeMaterials.java @@ -41,9 +41,9 @@ public static void register() { Olivine = new Material.Builder(2004, "olivine") .gem().ore(2, 1) .color(0x96FF96).iconSet(RUBY) - .flags(NO_SMASHING, NO_SMELTING, HIGH_SIFTER_OUTPUT) + .flags(NO_SMASHING, NO_SMELTING, HIGH_SIFTER_OUTPUT, GENERATE_PLATE) .components(Magnesium, 2, Iron, 1, SiliconDioxide, 2) - .toolStats(7.5f, 3.0f, 312) + .toolStats(7.5f, 3.0f, 312, 33) .build(); Opal = new Material.Builder(2005, "opal") @@ -51,7 +51,7 @@ public static void register() { .color(0x0000FF).iconSet(OPAL) .flags(NO_SMASHING, NO_SMELTING, HIGH_SIFTER_OUTPUT, DECOMPOSITION_BY_CENTRIFUGING, GENERATE_LENS) .components(SiliconDioxide, 1) - .toolStats(7.5f, 3.0f, 312) + .toolStats(7.5f, 3.0f, 312, 15) .build(); Amethyst = new Material.Builder(2006, "amethyst") @@ -59,13 +59,14 @@ public static void register() { .color(0xD232D2).iconSet(RUBY) .flags(NO_SMASHING, NO_SMELTING, HIGH_SIFTER_OUTPUT, GENERATE_LENS) .components(SiliconDioxide, 4, Iron, 1) - .toolStats(7.5f, 3.0f, 312) + .toolStats(7.5f, 3.0f, 312, 33) .build(); Lapis = new Material.Builder(2007, "lapis") .gem(1).ore(6, 4) .color(0x4646DC).iconSet(LAPIS) - .flags(NO_SMASHING, NO_SMELTING, CRYSTALLIZABLE, NO_WORKING, DECOMPOSITION_BY_ELECTROLYZING, EXCLUDE_BLOCK_CRAFTING_BY_HAND_RECIPES) + .flags(NO_SMASHING, NO_SMELTING, CRYSTALLIZABLE, NO_WORKING, DECOMPOSITION_BY_ELECTROLYZING, EXCLUDE_BLOCK_CRAFTING_BY_HAND_RECIPES, + GENERATE_PLATE) .components(Lazurite, 12, Sodalite, 2, Pyrite, 1, Calcite, 1) .build(); @@ -86,16 +87,16 @@ public static void register() { Apatite = new Material.Builder(2010, "apatite") .gem(1).ore(4, 2) .color(0xC8C8FF).iconSet(DIAMOND) - .flags(NO_SMASHING, NO_SMELTING, CRYSTALLIZABLE) + .flags(NO_SMASHING, NO_SMELTING, CRYSTALLIZABLE, GENERATE_BOLT_SCREW) .components(Calcium, 5, Phosphate, 3, Chlorine, 1) .build(); BlackSteel = new Material.Builder(2011, "black_steel") .ingot().fluid() .color(0x646464).iconSet(METALLIC) - .flags(EXT_METAL, GENERATE_FINE_WIRE) + .flags(EXT_METAL, GENERATE_FINE_WIRE, GENERATE_GEAR) .components(Nickel, 1, BlackBronze, 1, Steel, 3) - .toolStats(6.5f, 6.5f, 768) + .toolStats(6.5f, 6.5f, 768, 21) .cableProperties(GTValues.V[4], 3, 2) .blastTemp(1200) .build(); @@ -105,7 +106,7 @@ public static void register() { .color(0x6E6E6E).iconSet(METALLIC) .flags(EXT_METAL) .components(Steel, 1) - .toolStats(8.0f, 5.0f, 1280) + .toolStats(8.0f, 5.0f, 1280, 21) .blastTemp(1500) .build(); @@ -114,7 +115,7 @@ public static void register() { .color(0x6464A0).iconSet(METALLIC) .flags(EXT2_METAL, GENERATE_ROTOR, GENERATE_SMALL_GEAR, GENERATE_DENSE, GENERATE_FRAME, GENERATE_SPRING) .components(Steel, 1, Tungsten, 1) - .toolStats(8.0f, 4.0f, 2560) + .toolStats(8.0f, 4.0f, 2560, 21) .fluidPipeProperties(7568, 100, true) .cableProperties(GTValues.V[5], 3, 2) .blastTemp(3000) @@ -125,7 +126,7 @@ public static void register() { .color(0xB4B4A0).iconSet(METALLIC) .flags(EXT2_METAL) .components(Brass, 7, Aluminium, 1, Cobalt, 1) - .toolStats(8.0f, 2.0f, 256) + .toolStats(8.0f, 2.0f, 256, 21) .itemPipeProperties(2048, 1) .build(); @@ -141,7 +142,7 @@ public static void register() { .color(0xC85050).iconSet(RUBY) .flags(STD_SOLID, GENERATE_LENS, NO_SMASHING, NO_SMELTING, HIGH_SIFTER_OUTPUT, DECOMPOSITION_BY_CENTRIFUGING) .components(Pyrope, 3, Almandine, 5, Spessartine, 8) - .toolStats(7.5f, 3.0f, 156) + .toolStats(7.5f, 3.0f, 156, 33) .build(); GarnetYellow = new Material.Builder(2017, "garnet_yellow") @@ -149,7 +150,7 @@ public static void register() { .color(0xC8C850).iconSet(RUBY) .flags(STD_SOLID, GENERATE_LENS, NO_SMASHING, NO_SMELTING, HIGH_SIFTER_OUTPUT, DECOMPOSITION_BY_CENTRIFUGING) .components(Andradite, 5, Grossular, 8, Uvarovite, 3) - .toolStats(7.5f, 3.0f, 156) + .toolStats(7.5f, 3.0f, 156, 33) .build(); Marble = new Material.Builder(2018, "marble") @@ -279,7 +280,7 @@ public static void register() { .color(0xc0c0c0).iconSet(METALLIC) .flags(EXT2_METAL) .components(Vanadium, 1, Chrome, 1, Steel, 7) - .toolStats(7.0f, 3.0f, 1920) + .toolStats(7.0f, 3.0f, 1920, 21) .fluidPipeProperties(2073, 100, true) .blastTemp(1453) .build(); @@ -295,7 +296,7 @@ public static void register() { BorosilicateGlass = new Material.Builder(2038, "borosilicate_glass") .ingot(1).fluid() .color(0xE6F3E6).iconSet(SHINY) - .flags(GENERATE_FINE_WIRE) + .flags(GENERATE_FINE_WIRE, GENERATE_PLATE) .components(Boron, 1, SiliconDioxide, 7) .build(); @@ -320,7 +321,7 @@ public static void register() { .color(0x282828).iconSet(METALLIC) .flags(EXT2_METAL, GENERATE_SPRING) .components(Naquadah, 1, Osmiridium, 1) - .toolStats(8.0f, 5.0f, 5120) + .toolStats(8.0f, 5.0f, 5120, 21) .cableProperties(GTValues.V[8], 2, 4) .blastTemp(7200) .build(); @@ -369,27 +370,49 @@ public static void register() { .gem(1) .color(0x002040).iconSet(FLINT) .flags(NO_SMASHING, MORTAR_GRINDABLE, DECOMPOSITION_BY_CENTRIFUGING) + .toolStats(6, 4, 80, 10) .build(); - //todo this is stupid - NobleGases = new Material.Builder(2050, "noble_gases") + Air = new Material.Builder(2050, "air") .fluid(Material.FluidType.GAS) .color(0xA9D0F5) - .components(CarbonDioxide, 25, Helium, 11, Methane, 4, Deuterium, 2, Radon, 1) + .flags(DISABLE_DECOMPOSITION) + .components(Nitrogen, 78, Oxygen, 21, Argon, 9) .build(); - Air = new Material.Builder(2051, "air") - .fluid(Material.FluidType.GAS) + LiquidAir = new Material.Builder(2051, "liquid_air") + .fluid() .color(0xA9D0F5) .flags(DISABLE_DECOMPOSITION) - .components(Nitrogen, 40, Oxygen, 11, Argon, 1, NobleGases, 1) + .components(Nitrogen, 143, Oxygen, 45, CarbonDioxide, 10, Helium, 1, Argon, 1, Ice, 1) .build(); - LiquidAir = new Material.Builder(2052, "liquid_air") + NetherAir = new Material.Builder(2052, "nether_air") + .fluid(Material.FluidType.GAS) + .color(0x4C3434) + .flags(DISABLE_DECOMPOSITION) + .components(CarbonMonoxide, 78, HydrogenSulfide, 21, Neon, 9) + .build(); + + LiquidNetherAir = new Material.Builder(2053, "liquid_nether_air") .fluid() - .color(0xA9D0F5) + .color(0x4C3434) + .flags(DISABLE_DECOMPOSITION) + .components(CarbonMonoxide, 144, CoalGas, 20, HydrogenSulfide, 15, SulfurDioxide, 15, Helium3, 5, Neon, 1, Ash, 1) + .build(); + + EnderAir = new Material.Builder(2054, "ender_air") + .fluid(Material.FluidType.GAS) + .color(0x283454) + .flags(DISABLE_DECOMPOSITION) + .components(NitrogenDioxide, 78, Deuterium, 21, Xenon, 9) + .build(); + + LiquidEnderAir = new Material.Builder(2055, "liquid_ender_air") + .fluid() + .color(0x283454) .flags(DISABLE_DECOMPOSITION) - .components(Nitrogen, 40, Oxygen, 11, Argon, 1, NobleGases, 1) + .components(NitrogenDioxide, 122, Deuterium, 50, Helium, 15, Tritium, 10, Krypton, 1, Xenon, 1, Radon, 1, EnderPearl, 1) .build(); } } diff --git a/src/main/java/gregtech/api/unification/material/materials/UnknownCompositionMaterials.java b/src/main/java/gregtech/api/unification/material/materials/UnknownCompositionMaterials.java index 24a09e1e83e..39929d451b3 100644 --- a/src/main/java/gregtech/api/unification/material/materials/UnknownCompositionMaterials.java +++ b/src/main/java/gregtech/api/unification/material/materials/UnknownCompositionMaterials.java @@ -236,7 +236,6 @@ public static void register() { Oilsands = new Material.Builder(1597, "oilsands") .dust(1).ore() .color(0x0A0A0A).iconSet(SAND) - .components(Oil, 1) .build(); RareEarth = new Material.Builder(1598, "rare_earth") @@ -316,7 +315,7 @@ public static void register() { .gem(3).ore() .color(0x64C8FF).iconSet(EMERALD) .flags(STD_GEM, NO_SMASHING, NO_SMELTING) - .toolStats(12.0f, 3.0f, 128) + .toolStats(12.0f, 3.0f, 128, 15) .addDefaultEnchant(Enchantments.FORTUNE, 2) .build(); diff --git a/src/main/java/gregtech/api/unification/material/properties/FluidPipeProperties.java b/src/main/java/gregtech/api/unification/material/properties/FluidPipeProperties.java index 72198f3f769..a0afb16faf6 100644 --- a/src/main/java/gregtech/api/unification/material/properties/FluidPipeProperties.java +++ b/src/main/java/gregtech/api/unification/material/properties/FluidPipeProperties.java @@ -7,11 +7,20 @@ public class FluidPipeProperties implements IMaterialProperty mat.hasFlag(GENERATE_PLATE) && !mat.hasFlag(NO_SMASHING))); // Regular Plate made of one Ingot/Dust. Introduced by Calclavia public static final OrePrefix plate = new OrePrefix("plate", M, null, MaterialIconType.plate, ENABLE_UNIFICATION, mat -> mat.hasFlag(GENERATE_PLATE)); - // Compressed Material, worth 1 Unit. Introduced by Galacticraft - public static final OrePrefix compressed = new OrePrefix("compressed", M * 2, null, null, ENABLE_UNIFICATION, null); // Round made of 1 Nugget public static final OrePrefix round = new OrePrefix("round", M / 9, null, MaterialIconType.round, OrePrefix.Flags.ENABLE_UNIFICATION, mat -> mat.hasFlag(GENERATE_ROUND)); @@ -166,7 +163,6 @@ public class OrePrefix { // made of 5 Ingots. public static final OrePrefix turbineBlade = new OrePrefix("turbineBlade", M * 10, null, MaterialIconType.turbineBlade, ENABLE_UNIFICATION, hasToolProperty.and(m -> m.hasFlags(GENERATE_BOLT_SCREW, GENERATE_PLATE))); - public static final OrePrefix glass = new OrePrefix("glass", -1, Materials.Glass, null, SELF_REFERENCING, null); public static final OrePrefix paneGlass = new OrePrefix("paneGlass", -1, MarkerMaterials.Color.Colorless, null, SELF_REFERENCING, null); public static final OrePrefix blockGlass = new OrePrefix("blockGlass", -1, MarkerMaterials.Color.Colorless, null, SELF_REFERENCING, null); @@ -182,7 +178,6 @@ public class OrePrefix { public static final OrePrefix stone = new OrePrefix("stone", -1, Materials.Stone, null, SELF_REFERENCING, null); public static final OrePrefix cobblestone = new OrePrefix("cobblestone", -1, Materials.Stone, null, SELF_REFERENCING, null); // Prefix to determine which kind of Rock this is. - public static final OrePrefix rock = new OrePrefix("rock", -1, Materials.Stone, null, SELF_REFERENCING, null); // Cobblestone Prefix for all Cobblestones. public static final OrePrefix stoneCobble = new OrePrefix("stoneCobble", -1, Materials.Stone, null, SELF_REFERENCING, null); @@ -193,6 +188,8 @@ public class OrePrefix { public static final OrePrefix pipeNormalFluid = new OrePrefix("pipeNormalFluid", M * 3, null, MaterialIconType.pipeMedium, ENABLE_UNIFICATION, null); public static final OrePrefix pipeLargeFluid = new OrePrefix("pipeLargeFluid", M * 6, null, MaterialIconType.pipeLarge, ENABLE_UNIFICATION, null); public static final OrePrefix pipeHugeFluid = new OrePrefix("pipeHugeFluid", M * 12, null, MaterialIconType.pipeHuge, ENABLE_UNIFICATION, null); + public static final OrePrefix pipeQuadrupleFluid = new OrePrefix("pipeQuadrupleFluid", M * 12, null, MaterialIconType.pipeQuadruple, ENABLE_UNIFICATION, null); + public static final OrePrefix pipeNonupleFluid = new OrePrefix("pipeNonupleFluid", M * 12, null, MaterialIconType.pipeQuadruple, ENABLE_UNIFICATION, null); public static final OrePrefix pipeTinyItem = new OrePrefix("pipeTinyItem", M / 2, null, MaterialIconType.pipeTiny, ENABLE_UNIFICATION, null); public static final OrePrefix pipeSmallItem = new OrePrefix("pipeSmallItem", M, null, MaterialIconType.pipeSmall, ENABLE_UNIFICATION, null); @@ -226,23 +223,14 @@ public class OrePrefix { * * @see MarkerMaterials.Tier */ - public static final OrePrefix batterySingleUse = new OrePrefix("batterySingleUse", -1, null, null, 0, null); // Introduced by Calclavia public static final OrePrefix battery = new OrePrefix("battery", -1, null, null, 0, null); // Introduced by Calclavia public static final OrePrefix circuit = new OrePrefix("circuit", -1, null, null, ENABLE_UNIFICATION, null); - // Introduced by Buildcraft - public static final OrePrefix chipset = new OrePrefix("chipset", -1, null, null, ENABLE_UNIFICATION, null); public static final OrePrefix component = new OrePrefix("component", -1, null, null, ENABLE_UNIFICATION, null); // Used for Gregification Addon TODO Don't do these here post De-Enum - // Ex Nihilo Compat - public static final OrePrefix oreChunk = new OrePrefix("oreChunk", -1, null, MaterialIconType.oreChunk, ENABLE_UNIFICATION, null); - public static final OrePrefix oreEnderChunk = new OrePrefix("oreEnderChunk", -1, null, MaterialIconType.oreEnderChunk, ENABLE_UNIFICATION, null); - public static final OrePrefix oreNetherChunk = new OrePrefix("oreNetherChunk", -1, null, MaterialIconType.oreNetherChunk, ENABLE_UNIFICATION, null); - public static final OrePrefix oreSandyChunk = new OrePrefix("oreSandyChunk", -1, null, MaterialIconType.oreSandyChunk, ENABLE_UNIFICATION, null); - // Myst Ag Compat public static final OrePrefix seed = new OrePrefix("seed", -1, null, MaterialIconType.seed, ENABLE_UNIFICATION, null); public static final OrePrefix crop = new OrePrefix("crop", -1, null, MaterialIconType.crop, ENABLE_UNIFICATION, null); @@ -292,10 +280,8 @@ public static class Conditions { craftingLens.setMarkerPrefix(true); dye.setMarkerPrefix(true); - batterySingleUse.setMarkerPrefix(true); battery.setMarkerPrefix(true); circuit.setMarkerPrefix(true); - chipset.setMarkerPrefix(true); gem.setIgnored(Materials.Diamond); gem.setIgnored(Materials.Emerald); @@ -380,6 +366,8 @@ public static class Conditions { pipeTinyFluid.setIgnored(Materials.Wood); pipeHugeFluid.setIgnored(Materials.Wood); + pipeQuadrupleFluid.setIgnored(Materials.Wood); + pipeNonupleFluid.setIgnored(Materials.Wood); plate.setIgnored(Materials.BorosilicateGlass); foil.setIgnored(Materials.BorosilicateGlass); } @@ -423,7 +411,9 @@ private static void excludeAllGems(Material material) { public final List secondaryMaterials = new ArrayList<>(); public float heatDamage = 0.0F; // Negative for Frost Damage - OrePrefix(String name, long materialAmount, @Nullable Material material, @Nullable MaterialIconType materialIconType, long flags, @Nullable Predicate condition) { + private String alternativeOreName = null; + + public OrePrefix(String name, long materialAmount, @Nullable Material material, @Nullable MaterialIconType materialIconType, long flags, @Nullable Predicate condition) { Preconditions.checkArgument(!PREFIXES.containsKey(name), "OrePrefix " + name + " already registered!"); this.name = name; this.id = idCounter.getAndIncrement(); @@ -544,13 +534,21 @@ private void runGeneratedMaterialHandlers() { currentProcessingPrefix.set(null); } - @SideOnly(Side.CLIENT) // todo clean this up + public void setAlternativeOreName(String name) { + this.alternativeOreName = name; + } + + public String getAlternativeOreName() { + return alternativeOreName; + } + + // todo clean this up public String getLocalNameForItem(Material material) { String specifiedUnlocalized = "item." + material.toString() + "." + this.name; - if (I18n.hasKey(specifiedUnlocalized)) return I18n.format(specifiedUnlocalized); + if (LocalizationUtils.hasKey(specifiedUnlocalized)) return I18n.format(specifiedUnlocalized); String unlocalized = "item.material.oreprefix." + this.name; String matLocalized = material.getLocalizedName(); - String formatted = I18n.format(unlocalized, matLocalized); + String formatted = LocalizationUtils.format(unlocalized, matLocalized); return formatted.equals(unlocalized) ? matLocalized : formatted; } diff --git a/src/main/java/gregtech/api/util/BaseCreativeTab.java b/src/main/java/gregtech/api/util/BaseCreativeTab.java index 8782cbf8428..22d02449fc3 100644 --- a/src/main/java/gregtech/api/util/BaseCreativeTab.java +++ b/src/main/java/gregtech/api/util/BaseCreativeTab.java @@ -12,10 +12,6 @@ public class BaseCreativeTab extends CreativeTabs { private final boolean hasSearchBar; private final Supplier iconSupplier; - public BaseCreativeTab(String tabName, Supplier iconSupplier) { - this(tabName, iconSupplier, false); - } - public BaseCreativeTab(String TabName, Supplier iconSupplier, boolean hasSearchBar) { super(TabName); this.iconSupplier = iconSupplier; diff --git a/src/main/java/gregtech/api/util/DirectionHelper.java b/src/main/java/gregtech/api/util/DirectionHelper.java deleted file mode 100644 index 6fd1443b258..00000000000 --- a/src/main/java/gregtech/api/util/DirectionHelper.java +++ /dev/null @@ -1,70 +0,0 @@ -package gregtech.api.util; - -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.util.EnumFacing; -import net.minecraft.util.math.Vec3d; -import net.minecraft.util.math.Vec3i; - -public class DirectionHelper { - - private DirectionHelper() { - } - - public static EnumFacing getRelativeUp(EntityPlayer player) { - return getRelativeDown(player).getOpposite(); - } - - public static EnumFacing getRelativeDown(EntityPlayer player) { - Vec3d facingVec = player.getLookVec(); - EnumFacing facing = EnumFacing.getFacingFromVector((float) facingVec.x, (float) facingVec.y, (float) facingVec.z); - - EnumFacing down; - switch (facing) { - case UP: - down = player.getHorizontalFacing(); - break; - case DOWN: - down = player.getHorizontalFacing().getOpposite(); - break; - default: - down = EnumFacing.DOWN; - } - return down; - } - - public static EnumFacing getRelativeLeft(EntityPlayer player) { - return getRelativeRight(player).getOpposite(); - } - - public static EnumFacing getRelativeRight(EntityPlayer player) { - Vec3d facingVec = player.getLookVec(); - EnumFacing facing = EnumFacing.getFacingFromVector((float) facingVec.x, (float) facingVec.y, (float) facingVec.z); - - EnumFacing right; - switch (facing) { - case UP: - case DOWN: - facing = player.getHorizontalFacing(); - default: - right = facing.rotateAround(EnumFacing.Axis.Y); - } - return right; - } - - public static EnumFacing getRelativeForward(EntityPlayer player) { - Vec3d facingVec = player.getLookVec(); - return EnumFacing.getFacingFromVector((float) facingVec.x, (float) facingVec.y, (float) facingVec.z); - } - - public static EnumFacing getRelativeBackward(EntityPlayer player) { - return getRelativeForward(player).getOpposite(); - } - - public static Vec3i multiplyVec(Vec3i start, int multiplier) { - return new Vec3i( - start.getX() * multiplier, - start.getY() * multiplier, - start.getZ() * multiplier - ); - } -} diff --git a/src/main/java/gregtech/api/util/FirstTickScheduler.java b/src/main/java/gregtech/api/util/FirstTickScheduler.java deleted file mode 100644 index 1e6f87ae7f6..00000000000 --- a/src/main/java/gregtech/api/util/FirstTickScheduler.java +++ /dev/null @@ -1,48 +0,0 @@ -package gregtech.api.util; - -import com.google.common.collect.Maps; -import com.google.common.collect.Queues; -import gregtech.api.GTValues; -import net.minecraft.world.World; -import net.minecraftforge.event.world.WorldEvent; -import net.minecraftforge.fml.common.Mod; -import net.minecraftforge.fml.common.eventhandler.EventPriority; -import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; -import net.minecraftforge.fml.common.gameevent.TickEvent; - -import java.util.Map; -import java.util.Queue; - -@Mod.EventBusSubscriber(modid = GTValues.MODID) -public class FirstTickScheduler { - - private static final Map> tasksByWorld = Maps.newConcurrentMap(); - - public static void addTask(final IFirstTickTask task) { - final World world = task.getWorld(); - if (!world.isRemote) { - final Queue tasks = tasksByWorld.computeIfAbsent(world, - k -> Queues.newConcurrentLinkedQueue()); - tasks.add(task); - } else task.handleFirstTick(); - } - - @SubscribeEvent - public static void onWorldUnload(WorldEvent.Unload event) { - tasksByWorld.remove(event.getWorld()); - } - - @SubscribeEvent(priority = EventPriority.HIGHEST) - public static void onWorldTick(TickEvent.WorldTickEvent event) { - if (event.phase == TickEvent.Phase.START) { - final Queue tasks = tasksByWorld.get(event.world); - if (tasks != null) { - IFirstTickTask task = tasks.poll(); - while (task != null) { - task.handleFirstTick(); - task = tasks.poll(); - } - } - } - } -} diff --git a/src/main/java/gregtech/api/util/FluidTooltipUtil.java b/src/main/java/gregtech/api/util/FluidTooltipUtil.java index 5722be0c774..8a6800ce8a9 100644 --- a/src/main/java/gregtech/api/util/FluidTooltipUtil.java +++ b/src/main/java/gregtech/api/util/FluidTooltipUtil.java @@ -1,7 +1,6 @@ package gregtech.api.util; import gregtech.api.unification.material.Materials; -import gregtech.api.unification.stack.MaterialStack; import net.minecraftforge.fluids.Fluid; import net.minecraftforge.fluids.FluidRegistry; import net.minecraftforge.fluids.FluidStack; @@ -78,7 +77,6 @@ public static String getFluidTooltip(String fluidName) { * @return "H₂O" */ public static String getWaterTooltip() { - // Done like this to not return parenthesis around the tooltip - return (new MaterialStack(Materials.Hydrogen, 2)).toString() + "O"; + return Materials.Water.getChemicalFormula(); } } diff --git a/src/main/java/gregtech/api/util/IFirstTickTask.java b/src/main/java/gregtech/api/util/IFirstTickTask.java deleted file mode 100644 index 38f5fb2a7fe..00000000000 --- a/src/main/java/gregtech/api/util/IFirstTickTask.java +++ /dev/null @@ -1,10 +0,0 @@ -package gregtech.api.util; - -import net.minecraft.world.World; - -public interface IFirstTickTask { - - void handleFirstTick(); - - World getWorld(); -} diff --git a/src/main/java/gregtech/api/util/LocalizationUtils.java b/src/main/java/gregtech/api/util/LocalizationUtils.java new file mode 100644 index 00000000000..2ec1a6bb386 --- /dev/null +++ b/src/main/java/gregtech/api/util/LocalizationUtils.java @@ -0,0 +1,49 @@ +package gregtech.api.util; + +import net.minecraftforge.fml.common.FMLCommonHandler; +import net.minecraftforge.fml.relauncher.Side; + +@SuppressWarnings("deprecation") +public class LocalizationUtils { + + /** + * This function calls `net.minecraft.client.resources.I18n.format` when called on client + * or `net.minecraft.util.text.translation.I18n.translateToLocalFormatted` when called on server. + *

    + *
  • It is intended that translations should be done using `I18n` on the client.
  • + *
  • For setting up translations on the server you should use `TextComponentTranslatable`.
  • + *
  • `LocalisationUtils` is only for cases where some kind of translation is required on the server and there is no client/player in context.
  • + *
  • `LocalisationUtils` is "best effort" and will probably only work properly with en-us.
  • + *
+ * @param localisationKey the localisation key passed to the underlying format function + * @param substitutions the substitutions passed to the underlying format function + * @return the localized string. + */ + public static String format(String localisationKey, Object... substitutions) { + if (FMLCommonHandler.instance().getEffectiveSide() == Side.SERVER) { + return net.minecraft.util.text.translation.I18n.translateToLocalFormatted(localisationKey, substitutions); + } else { + return net.minecraft.client.resources.I18n.format(localisationKey, substitutions); + } + } + + /** + * This function calls `net.minecraft.client.resources.I18n.hasKey` when called on client + * or `net.minecraft.util.text.translation.I18n.canTranslate` when called on server. + *
    + *
  • It is intended that translations should be done using `I18n` on the client.
  • + *
  • For setting up translations on the server you should use `TextComponentTranslatable`.
  • + *
  • `LocalisationUtils` is only for cases where some kind of translation is required on the server and there is no client/player in context.
  • + *
  • `LocalisationUtils` is "best effort" and will probably only work properly with en-us.
  • + *
+ * @param localisationKey the localisation key passed to the underlying hasKey function + * @return a boolean indicating if the given localisation key has localisations + */ + public static boolean hasKey(String localisationKey) { + if (FMLCommonHandler.instance().getEffectiveSide() == Side.SERVER) { + return net.minecraft.util.text.translation.I18n.canTranslate(localisationKey); + } else { + return net.minecraft.client.resources.I18n.hasKey(localisationKey); + } + } +} diff --git a/src/main/java/gregtech/api/util/RelativeDirection.java b/src/main/java/gregtech/api/util/RelativeDirection.java new file mode 100644 index 00000000000..f3e2baca3f3 --- /dev/null +++ b/src/main/java/gregtech/api/util/RelativeDirection.java @@ -0,0 +1,36 @@ +package gregtech.api.util; + +import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.Vec3i; + +import java.util.function.Function; + +/** + * Relative direction when facing horizontally + */ +public enum RelativeDirection { + UP(f -> EnumFacing.UP), + DOWN(f -> EnumFacing.DOWN), + LEFT(EnumFacing::rotateYCCW), + RIGHT(EnumFacing::rotateY), + FRONT(Function.identity()), + BACK(EnumFacing::getOpposite); + + final Function actualFacing; + + RelativeDirection(Function actualFacing) { + this.actualFacing = actualFacing; + } + + public EnumFacing getActualFacing(EnumFacing facing) { + return actualFacing.apply(facing); + } + + public EnumFacing apply(EnumFacing facing) { + return actualFacing.apply(facing); + } + + public Vec3i applyVec3i(EnumFacing facing) { + return apply(facing).getDirectionVec(); + } +} diff --git a/src/main/java/gregtech/api/util/SlotUtil.java b/src/main/java/gregtech/api/util/SlotUtil.java index 77886e5e750..348daaa7e88 100644 --- a/src/main/java/gregtech/api/util/SlotUtil.java +++ b/src/main/java/gregtech/api/util/SlotUtil.java @@ -27,9 +27,8 @@ public static ItemStack slotClickPhantom(Slot slot, int mouseButton, ClickType c } else if (slot.isItemValid(stackHeld)) { if (areItemsEqual(stackSlot, stackHeld)) { adjustPhantomSlot(slot, mouseButton, clickTypeIn); - } else { - fillPhantomSlot(slot, stackHeld, mouseButton); } + fillPhantomSlot(slot, stackHeld, mouseButton); } } else if (mouseButton == 5) { if (!slot.getHasStack()) { diff --git a/src/main/java/gregtech/api/util/TickingObjectHolder.java b/src/main/java/gregtech/api/util/TickingObjectHolder.java new file mode 100644 index 00000000000..71b477405c9 --- /dev/null +++ b/src/main/java/gregtech/api/util/TickingObjectHolder.java @@ -0,0 +1,55 @@ +package gregtech.api.util; + +import net.minecraft.world.World; + +import java.util.Optional; + +public class TickingObjectHolder { + + private T object; + private long lastUpdateTime; + private final long defaultLifeTime; + private long lifeTime; + + public TickingObjectHolder(T t, long lifeTime) { + this.object = t; + this.defaultLifeTime = lifeTime; + this.lifeTime = lifeTime; + } + + private void checkState(World world) { + if(lifeTime <= 0) return; + long worldTime = world.getTotalWorldTime(); + if(lastUpdateTime != worldTime) { + lifeTime -= (worldTime - lastUpdateTime); + if(lifeTime <= 0) + object = null; + lastUpdateTime = worldTime; + } + } + + public Optional get(World world) { + checkState(world); + return object == null ? Optional.empty() : Optional.of(object); + } + + public T getNullable(World world) { + checkState(world); + return object; + } + + public long getRemainingTime(World world) { + checkState(world); + return Math.max(0, lifeTime); + } + + public void reset(T object, long lifeTime) { + this.object = object; + this.lifeTime = lifeTime; + } + + public void reset(T object) { + this.object = object; + this.lifeTime = defaultLifeTime; + } +} diff --git a/src/main/java/gregtech/api/util/function/Task.java b/src/main/java/gregtech/api/util/function/Task.java index ebbc58da116..a317c1abfb0 100644 --- a/src/main/java/gregtech/api/util/function/Task.java +++ b/src/main/java/gregtech/api/util/function/Task.java @@ -1,5 +1,6 @@ package gregtech.api.util.function; +@FunctionalInterface public interface Task { boolean run(); diff --git a/src/main/java/gregtech/api/util/interpolate/Eases.java b/src/main/java/gregtech/api/util/interpolate/Eases.java new file mode 100644 index 00000000000..87f74763cb4 --- /dev/null +++ b/src/main/java/gregtech/api/util/interpolate/Eases.java @@ -0,0 +1,24 @@ +package gregtech.api.util.interpolate; + +public enum Eases implements IEase{ + EaseLinear(input-> input), + EaseQuadIn(input-> input * input), + EaseQuadInOut(input->{ + if((input /= 0.5f) < 1) { + return 0.5f * input * input; + } + return -0.5f * ((--input) * (input - 2) - 1); + }), + EaseQuadOut(input->-input * (input - 2)); + + + IEase ease; + + Eases(IEase ease){ + this.ease = ease; + } + @Override + public float getInterpolation(float t) { + return ease.getInterpolation(t); + } +} diff --git a/src/main/java/gregtech/api/util/interpolate/IEase.java b/src/main/java/gregtech/api/util/interpolate/IEase.java new file mode 100644 index 00000000000..cb4c02b0e4e --- /dev/null +++ b/src/main/java/gregtech/api/util/interpolate/IEase.java @@ -0,0 +1,5 @@ +package gregtech.api.util.interpolate; + +public interface IEase { + float getInterpolation(float t); +} diff --git a/src/main/java/gregtech/api/util/interpolate/Interpolator.java b/src/main/java/gregtech/api/util/interpolate/Interpolator.java new file mode 100644 index 00000000000..2c79a927ad0 --- /dev/null +++ b/src/main/java/gregtech/api/util/interpolate/Interpolator.java @@ -0,0 +1,56 @@ +package gregtech.api.util.interpolate; + +import crafttweaker.IAction; +import gregtech.api.util.function.BooleanConsumer; +import net.minecraft.util.ITickable; +import scala.Function; +import scala.swing.Action; + +import java.util.function.Consumer; + +public class Interpolator implements ITickable { + private final float from; + private final float to; + private final int duration; + private final IEase ease; + private final Consumer interpolate; + private final Consumer callback; + + private int tick = 0; + + public Interpolator(float from, float to, int duration, IEase ease, Consumer interpolate) { + this(from, to, duration, ease, interpolate, null); + } + + public Interpolator(float from, float to, int duration, IEase ease, Consumer interpolate, Consumer callback) { + this.from = from; + this.to = to; + this.duration = duration; + this.ease = ease; + this.interpolate = interpolate; + this.callback = callback; + } + + public void reset() { + tick = 0; + } + + public Interpolator start() { + tick = 1; + return this; + } + + public boolean isFinish(){ + return tick == duration; + } + + @Override + public void update() { + if (tick < 1 || tick > duration) return; + if (tick == duration) { + callback.accept(ease.getInterpolation(tick * 1.0f / duration) * (to - from) + from); + } + interpolate.accept(ease.getInterpolation(tick * 1.0f / duration) * (to - from) + from); + tick++; + } +} diff --git a/src/main/java/gregtech/api/worldgen/config/OreDepositDefinition.java b/src/main/java/gregtech/api/worldgen/config/OreDepositDefinition.java index d9ef9e08b16..45889db0615 100644 --- a/src/main/java/gregtech/api/worldgen/config/OreDepositDefinition.java +++ b/src/main/java/gregtech/api/worldgen/config/OreDepositDefinition.java @@ -88,14 +88,6 @@ public void initializeFromConfig(JsonObject configRoot) { if (configRoot.has("generation_predicate")) { this.generationPredicate = PredicateConfigUtils.createBlockStatePredicate(configRoot.get("generation_predicate")); } - //legacy surface rock specifier support - if (configRoot.has("surface_stone_material")) { - Material surfaceStoneMaterial = OreConfigUtils.getMaterialByName(configRoot.get("surface_stone_material").getAsString()); - if (!surfaceStoneMaterial.hasProperty(PropertyKey.ORE)) { - throw new IllegalArgumentException("Material " + surfaceStoneMaterial + " doesn't have surface rock variant"); - } - this.veinPopulator = new SurfaceRockPopulator(surfaceStoneMaterial); - } if (configRoot.has("vein_populator")) { JsonObject object = configRoot.get("vein_populator").getAsJsonObject(); this.veinPopulator = WorldGenRegistry.INSTANCE.createVeinPopulator(object); diff --git a/src/main/java/gregtech/api/worldgen/populator/SurfaceRockPopulator.java b/src/main/java/gregtech/api/worldgen/populator/SurfaceRockPopulator.java index d4f9b4a36d1..6c5550e2c6e 100644 --- a/src/main/java/gregtech/api/worldgen/populator/SurfaceRockPopulator.java +++ b/src/main/java/gregtech/api/worldgen/populator/SurfaceRockPopulator.java @@ -59,7 +59,7 @@ private Set findUndergroundMaterials(Collection generated } else { ItemStack itemStack = new ItemStack(blockState.getBlock(), 1, blockState.getBlock().damageDropped(blockState)); UnificationEntry entry = OreDictUnifier.getUnificationEntry(itemStack); - resultMaterial = entry == null ? null : (Material) entry.material; + resultMaterial = entry == null ? null : entry.material; } if (resultMaterial != null) { result.add(resultMaterial); diff --git a/src/main/java/gregtech/common/ClientProxy.java b/src/main/java/gregtech/common/ClientProxy.java index 074e154abbd..afc45f2aaeb 100644 --- a/src/main/java/gregtech/common/ClientProxy.java +++ b/src/main/java/gregtech/common/ClientProxy.java @@ -151,7 +151,7 @@ public static void addMaterialFormulaHandler(ItemTooltipEvent event) { if (unificationEntry != null && unificationEntry.material != null) { chemicalFormula = unificationEntry.material.getChemicalFormula(); - // Test for Fluids + // Test for Fluids } else if (ItemNBTUtils.hasTag(itemStack)) { // Vanilla bucket @@ -165,7 +165,7 @@ public static void addMaterialFormulaHandler(ItemTooltipEvent event) { } } - // Water buckets have a separate registry name from other buckets + // Water buckets have a separate registry name from other buckets } else if (itemStack.getItem().equals(Items.WATER_BUCKET)) { chemicalFormula = FluidTooltipUtil.getWaterTooltip(); } diff --git a/src/main/java/gregtech/common/CommonProxy.java b/src/main/java/gregtech/common/CommonProxy.java index bbf7ae04ffc..b0c300105c4 100644 --- a/src/main/java/gregtech/common/CommonProxy.java +++ b/src/main/java/gregtech/common/CommonProxy.java @@ -7,6 +7,8 @@ import gregtech.api.recipes.crafttweaker.MetaItemBracketHandler; import gregtech.api.recipes.recipeproperties.BlastTemperatureProperty; import gregtech.api.recipes.recipeproperties.FusionEUToStartProperty; +import gregtech.api.terminal.TerminalRegistry; +import gregtech.api.terminal.util.GuideJsonLoader; import gregtech.api.unification.material.Material; import gregtech.api.unification.material.properties.DustProperty; import gregtech.api.unification.material.properties.PropertyKey; @@ -29,6 +31,8 @@ import gregtech.loaders.oreprocessing.RecipeHandlerList; import gregtech.loaders.oreprocessing.ToolRecipeHandler; import gregtech.loaders.recipe.*; +import gregtech.loaders.recipe.component.AnnotatedComponentHandlerLoader; +import gregtech.loaders.recipe.component.IComponentHandler; import net.minecraft.block.Block; import net.minecraft.block.state.IBlockState; import net.minecraft.enchantment.Enchantment; @@ -152,6 +156,7 @@ public static void registerItems(RegistryEvent.Register event) { @SubscribeEvent(priority = EventPriority.HIGHEST) public static void initComponents(RegistryEvent.Register event) { CraftingComponent.initializeComponents(); + IComponentHandler.runComponentHandlers(); } //this is called with normal priority, so most mods working with @@ -270,5 +275,7 @@ public void onLoad() { public void onPostLoad() { WoodMachineRecipes.postInit(); + TerminalRegistry.init(); + new GuideJsonLoader().onResourceManagerReload(null); } } diff --git a/src/main/java/gregtech/common/ConfigHolder.java b/src/main/java/gregtech/common/ConfigHolder.java index d8fd4b50ac0..70ab9b0335d 100644 --- a/src/main/java/gregtech/common/ConfigHolder.java +++ b/src/main/java/gregtech/common/ConfigHolder.java @@ -10,14 +10,6 @@ public class ConfigHolder { @Config.Name("Unofficial Options") public static UnofficialOptions U = new UnofficialOptions(); - @Config.Comment("Whether to enable that Steam Multiblocks use Steel instead of Bronze. Default: false") - @Config.RequiresMcRestart - public static boolean steelSteamMultiblocks = false; - - @Config.Comment("Steam to EU multiplier for Steam Multiblocks. 1.0 means 1 Steam -> 1 EU. 0.5 means 2 Steam -> 1 EU") - @Config.RequiresMcRestart - public static double multiblockSteamtoEU = 0.5; - @Config.Comment("Whether to enable more verbose logging. Default: false") public static boolean debug = false; @@ -113,16 +105,6 @@ public class ConfigHolder { @Config.RequiresMcRestart public static int gasTurbineBonusOutput = 6144; - @Config.Comment("If true, powered zero loss wires will damage the player. Default: false") - public static boolean doLosslessWiresDamage = false; - - @Config.Comment("If true, lossless cables will have lossy wires. Default: false") - @Config.RequiresMcRestart - public static boolean doLosslessWiresMakeLossyCables = false; - - @Config.Comment("Array of blacklisted dimension IDs in which Air Collector does not work. Default: none") - public static int[] airCollectorDimensionBlacklist = new int[]{}; - public static class VanillaRecipes { @Config.Comment("Whether to make glass related recipes harder. Default: true") @@ -157,6 +139,9 @@ public static class VanillaRecipes { @Config.Comment("Whether to make vanilla tools and armor recipes harder. Excludes flint and steel, and buckets. Default: false") public boolean hardToolArmorRecipes = false; + + @Config.Comment("Whether to disable the vanilla Concrete from Powder with Water behavior, forcing the GT recipe. Default: false") + public boolean disableConcreteInWorld = false; } public static class NanoSaberConfiguration { @@ -182,11 +167,6 @@ public static class NanoSaberConfiguration { public static class UnofficialOptions { - @Config.Comment("Config category for enabling higher-tier machines.") - @Config.Name("Higher Tier Machines") - @Config.RequiresMcRestart - public HighTierMachines machines = new HighTierMachines(); - @Config.Comment("Config category for GT5u inspired features.") @Config.Name("GregTech 5 Unofficial Options") public GT5U GT5u = new GT5U(); @@ -195,13 +175,13 @@ public static class UnofficialOptions { @Config.Name("GregTech 6 Options") public GT6 GT6 = new GT6(); - @Config.Comment("Should Drums be enabled? Default: true") - @Config.RequiresMcRestart - public boolean registerDrums = true; + @Config.Comment("Config category for energy compatibility features") + @Config.Name("Energy Compatibility Options") + public EnergyCompatibility energyOptions = new EnergyCompatibility(); - @Config.Comment("Should Crates be enabled? Default: true") + @Config.Comment("Allow GregTech to add additional loot. Default: true") @Config.RequiresMcRestart - public boolean registerCrates = true; + public static boolean addLoot = true; @Config.Comment("Should recipes for EV and IV Drills be enabled, which may cause large amounts of lag when used on some low-end devices? Default: true") @Config.RequiresMcRestart @@ -211,28 +191,26 @@ public static class UnofficialOptions { @Config.RequiresMcRestart public boolean registerRecipesForMiningHammers = true; - @Config.Comment("Divisor for Recipe Duration per Overclock. This will be removed eventually, once a value is chosen. Default: 2.0") + @Config.Comment("Divisor for Recipe Duration per Overclock. Default: 2.0") @Config.RangeDouble(min = 2.0, max = 3.0) public double overclockDivisor = 2.0; - public static class GT5U { + @Config.Comment("Whether to enable that Steam Multiblocks use Steel instead of Bronze. Default: false") + @Config.RequiresMcRestart + public boolean steelSteamMultiblocks = false; - @Config.Comment("Enable an extra ZPM and UV Battery (this also makes the Ultimate Battery harder to make). Default: false") - @Config.RequiresMcRestart - public boolean enableZPMandUVBats = false; + @Config.Comment("Steam to EU multiplier for Steam Multiblocks. 1.0 means 1 Steam -> 1 EU. 0.5 means 2 Steam -> 1 EU. Default: 0.5") + @Config.RequiresWorldRestart + public double multiblockSteamToEU = 0.5; - @Config.Comment("Replace the Ultimate Battery with a MAX Battery. Default: false") - @Config.RequiresMcRestart - public boolean replaceUVwithMAXBat = false; + public static class GT5U { - @Config.Comment("This config requires 'B:Use custom machine tank sizes' = true to take effect. Changes the input tank size to the first value, and out tank size to the second value for nearly every single block machine. Units are millibuckets.") - @Config.Name("Custom machine fluid tank sizes") + @Config.Comment("This config requires 'B:Use custom machine tank sizes' = true to take effect. Changes the input tank size to the first value, and out tank size to the second value for nearly every single block machine. Units are millibuckets. Default: {64000, 64000}") @Config.RangeInt(min = 1) @Config.RequiresMcRestart public int[] customMachineTankSizes = new int[]{64000, 64000}; - @Config.Comment("This config enables the customization of nearly every single block machine's input and output fluid tank sizes.") - @Config.Name("Use custom machine tank sizes") + @Config.Comment("This config enables the customization of nearly every single block machine's input and output fluid tank sizes. Default: false") @Config.RequiresMcRestart public boolean useCustomMachineTankSizes = false; @@ -240,33 +218,32 @@ public static class GT5U { public boolean requireWrenchForMachines = false; @Config.Comment("Change the recipe of rods to result in 1 stick and 2 small piles of dusts. Default: false") + @Config.RequiresMcRestart public boolean harderRods = false; @Config.Comment("Whether or not to use polymers instead of rare metals for Carbon Fibers. REMOVES THE CHANCED OUTPUT! Default: false") + @Config.RequiresMcRestart public boolean polymerCarbonFiber = false; @Config.Comment("The default color to overlay onto machines. \n16777215 (0xFFFFFF in decimal) is no coloring (default), and 13819135 (0xD2DCFF in decimal) is the classic blue from GT5. THIS IS SERVER SIDE!!!") - @Config.Name("Default Machine Color") @Config.RequiresMcRestart public int defaultPaintingColor = 0xFFFFFF; @Config.Comment("The default color to overlay onto cable insulation. \n7829367 (0x777777 in decimal) is no coloring (default), and 4210752 (0x404040 in decimal) is the classic black from GT5. THIS IS SERVER SIDE!!!") - @Config.Name("Default Cable Color") @Config.RequiresMcRestart public int defaultInsulationColor = 0x777777; @Config.Comment("Enable temperature based bonuses for the Electric Blast Furnace. Default: true") - @Config.Name("Use electric blast furnace temperature bonuses") @Config.RequiresMcRestart public boolean ebfTemperatureBonuses = true; @Config.Comment("Enable more challenging recipes for Electric Blast Furnace Coils. Default: true") - @Config.Name("Enable harder heating coil recipes") + @Config.RequiresMcRestart public boolean harderHeatingCoils = true; @Config.Comment("Enable more challenging recipes for Energy Input and Output hatches. Default: false") - @Config.Name("Enable harder energy hatch recipes") - public boolean harderEnergyHatches = true; + @Config.RequiresMcRestart + public boolean harderEnergyHatches = false; } public static class GT6 { @@ -280,99 +257,14 @@ public static class GT6 { public boolean plateWrenches = false; } - public static class HighTierMachines { - - @Config.Comment("Enable all LuV-UV Machines, overrides individual values if true. Default: false") - @Config.Name("LuV-UV Machines") - public boolean midTierMachines = false; - - @Config.Comment("Enable all UHV-UXV Machines, overrides individual values if true. THESE WILL HAVE NO RECIPES BY DEFAULT WITHOUT GREGICALITY! Default: false") - @Config.Name("UHV-UXV Machines") - public boolean highTierMachines = false; - - @Config.Comment("Should higher tier Pumps be registered (IV-UV)? Separate from other configs. Default: false") - public boolean highTierPumps = false; - - @Config.Comment("Should higher tier Air Collectors be registered (IV, LuV)? Separate from other configs. Default: false") - public boolean highTierAirCollectors = false; - - @Config.Comment("Set these to true to enable LuV-UV tiers of machines. Default (all): false") - public boolean midTierAlloySmelter = false; - public boolean midTierArcFurnaces = false; - public boolean midTierAssemblers = false; - public boolean midTierAutoclaves = false; - public boolean midTierBenders = false; - public boolean midTierBreweries = false; - public boolean midTierCanners = false; - public boolean midTierCentrifuges = false; - public boolean midTierChemicalBaths = false; - public boolean midTierChemicalReactors = false; - public boolean midTierCompressors = false; - public boolean midTierCutters = false; - public boolean midTierDistilleries = false; - public boolean midTierElectricFurnace = false; - public boolean midTierElectrolyzers = false; - public boolean midTierElectromagneticSeparators = false; - public boolean midTierExtractors = false; - public boolean midTierExtruders = false; - public boolean midTierFermenters = false; - public boolean midTierFluidHeaters = false; - public boolean midTierFluidSolidifiers = false; - public boolean midTierForgeHammers = false; - public boolean midTierFormingPresses = false; - public boolean midTierLathes = false; - public boolean midTierMixers = false; - public boolean midTierOreWashers = false; - public boolean midTierPackers = false; - public boolean midTierPolarizers = false; - public boolean midTierLaserEngravers = false; - public boolean midTierSifters = false; - public boolean midTierThermalCentrifuges = false; - public boolean midTierMacerators = false; - public boolean midTierUnpackers = false; - public boolean midTierWiremills = false; - public boolean midTierMassFabricators = false; - public boolean midTierReplicators = false; - public boolean midTierScanners = false; - - @Config.Comment("Set these to true to enable UHV-UXV tiers of machines. THESE WILL HAVE NO RECIPES BY DEFAULT WITHOUT GREGICALITY! Default (all): false") - public boolean highTierAlloySmelter = false; - public boolean highTierArcFurnaces = false; - public boolean highTierAssemblers = false; - public boolean highTierAutoclaves = false; - public boolean highTierBenders = false; - public boolean highTierBreweries = false; - public boolean highTierCanners = false; - public boolean highTierCentrifuges = false; - public boolean highTierChemicalBaths = false; - public boolean highTierChemicalReactors = false; - public boolean highTierCompressors = false; - public boolean highTierCutters = false; - public boolean highTierDistilleries = false; - public boolean highTierElectricFurnace = false; - public boolean highTierElectrolyzers = false; - public boolean highTierElectromagneticSeparators = false; - public boolean highTierExtractors = false; - public boolean highTierExtruders = false; - public boolean highTierFermenters = false; - public boolean highTierFluidHeaters = false; - public boolean highTierFluidSolidifiers = false; - public boolean highTierForgeHammers = false; - public boolean highTierFormingPresses = false; - public boolean highTierLathes = false; - public boolean highTierMixers = false; - public boolean highTierOreWashers = false; - public boolean highTierPackers = false; - public boolean highTierPolarizers = false; - public boolean highTierLaserEngravers = false; - public boolean highTierSifters = false; - public boolean highTierThermalCentrifuges = false; - public boolean highTierMacerators = false; - public boolean highTierUnpackers = false; - public boolean highTierWiremills = false; - public boolean highTierMassFabricators = false; - public boolean highTierReplicators = false; - public boolean highTierScanners = false; + public static class EnergyCompatibility { + + @Config.Comment("Enable Native GTEU to Forge Energy (RF and alike) on GT Cables and Wires. Default: true") + public boolean nativeEUToFE = true; + + @Config.Comment("GTEU to Forge Energy (RF and alike) ratio. Default: 4 FE to 1 EU") + @Config.RangeDouble() // to ensure positive number + public double rfRatio = 4; } } } diff --git a/src/main/java/gregtech/common/MetaFluids.java b/src/main/java/gregtech/common/MetaFluids.java index 3c1627b2aaa..9f31bcf06f1 100644 --- a/src/main/java/gregtech/common/MetaFluids.java +++ b/src/main/java/gregtech/common/MetaFluids.java @@ -164,6 +164,7 @@ public static void init() { // handle vanilla fluids Materials.Water.getProperty(PropertyKey.FLUID).setFluid(FluidRegistry.WATER); + FluidTooltipUtil.registerTooltip(FluidRegistry.WATER, Materials.Water.getChemicalFormula()); Materials.Lava.getProperty(PropertyKey.FLUID).setFluid(FluidRegistry.LAVA); //alternative names for forestry fluids diff --git a/src/main/java/gregtech/common/asm/ConcretePowderVisitor.java b/src/main/java/gregtech/common/asm/ConcretePowderVisitor.java new file mode 100644 index 00000000000..7cfd1b2b92b --- /dev/null +++ b/src/main/java/gregtech/common/asm/ConcretePowderVisitor.java @@ -0,0 +1,22 @@ +package gregtech.common.asm; + +import gregtech.common.asm.util.ObfMapping; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; + +public class ConcretePowderVisitor extends MethodVisitor implements Opcodes { + + public static final String TARGET_CLASS_NAME = "net/minecraft/block/BlockConcretePowder"; + public static final String TARGET_SIGNATURE = "(Lnet/minecraft/world/World;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/state/IBlockState;)Z"; + public static final ObfMapping TARGET_METHOD = new ObfMapping(TARGET_CLASS_NAME, "tryTouchWater", TARGET_SIGNATURE); + + public ConcretePowderVisitor(MethodVisitor mv) { + super(Opcodes.ASM5, mv); + } + + @Override + public void visitCode() { + mv.visitInsn(Opcodes.ICONST_0); + mv.visitInsn(Opcodes.IRETURN); + } +} diff --git a/src/main/java/gregtech/common/asm/GTCETransformer.java b/src/main/java/gregtech/common/asm/GTCETransformer.java index c8b02f73817..68905f2248d 100644 --- a/src/main/java/gregtech/common/asm/GTCETransformer.java +++ b/src/main/java/gregtech/common/asm/GTCETransformer.java @@ -1,5 +1,6 @@ package gregtech.common.asm; +import gregtech.common.ConfigHolder; import gregtech.common.asm.util.TargetClassVisitor; import net.minecraft.launchwrapper.IClassTransformer; import org.objectweb.asm.ClassReader; @@ -16,6 +17,13 @@ public byte[] transform(String name, String transformedName, byte[] basicClass) ClassWriter classWriter = new ClassWriter(0); classReader.accept(new TargetClassVisitor(classWriter, JEIVisitor.TARGET_METHOD, JEIVisitor::new), 0); return classWriter.toByteArray(); + } else if (internalName.equals(ConcretePowderVisitor.TARGET_CLASS_NAME)) { + if (ConfigHolder.vanillaRecipes.disableConcreteInWorld) { + ClassReader classReader = new ClassReader(basicClass); + ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); + classReader.accept(new TargetClassVisitor(classWriter, ConcretePowderVisitor.TARGET_METHOD, ConcretePowderVisitor::new), 0); + return classWriter.toByteArray(); + } } return basicClass; } diff --git a/src/main/java/gregtech/common/blocks/CompressedItemBlock.java b/src/main/java/gregtech/common/blocks/CompressedItemBlock.java index 58e8d697302..881c01ae919 100644 --- a/src/main/java/gregtech/common/blocks/CompressedItemBlock.java +++ b/src/main/java/gregtech/common/blocks/CompressedItemBlock.java @@ -5,8 +5,6 @@ import net.minecraft.block.state.IBlockState; import net.minecraft.item.ItemBlock; import net.minecraft.item.ItemStack; -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; import javax.annotation.Nonnull; @@ -25,14 +23,12 @@ public int getMetadata(int damage) { return damage; } - @SuppressWarnings("deprecation") public IBlockState getBlockState(ItemStack stack) { return compressedBlock.getStateFromMeta(getMetadata(stack.getItemDamage())); } @Nonnull @Override - @SideOnly(Side.CLIENT) public String getItemStackDisplayName(@Nonnull ItemStack stack) { Material material = getBlockState(stack).getValue(compressedBlock.variantProperty); return OrePrefix.block.getLocalNameForItem(material); diff --git a/src/main/java/gregtech/common/blocks/FrameItemBlock.java b/src/main/java/gregtech/common/blocks/FrameItemBlock.java index 50d917643fc..959954ad897 100644 --- a/src/main/java/gregtech/common/blocks/FrameItemBlock.java +++ b/src/main/java/gregtech/common/blocks/FrameItemBlock.java @@ -5,8 +5,6 @@ import net.minecraft.block.state.IBlockState; import net.minecraft.item.ItemBlock; import net.minecraft.item.ItemStack; -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; import javax.annotation.Nonnull; @@ -31,7 +29,6 @@ public IBlockState getBlockState(ItemStack stack) { @Nonnull @Override - @SideOnly(Side.CLIENT) public String getItemStackDisplayName(@Nonnull ItemStack stack) { Material material = frameBlock.frameMaterial; return OrePrefix.frameGt.getLocalNameForItem(material); diff --git a/src/main/java/gregtech/common/blocks/MetaBlocks.java b/src/main/java/gregtech/common/blocks/MetaBlocks.java index 17385b1f89f..693f28f5210 100644 --- a/src/main/java/gregtech/common/blocks/MetaBlocks.java +++ b/src/main/java/gregtech/common/blocks/MetaBlocks.java @@ -78,7 +78,7 @@ private MetaBlocks() { public static BlockMachine MACHINE; public static final BlockCable[] CABLES = new BlockCable[10]; - public static final BlockFluidPipe[] FLUID_PIPES = new BlockFluidPipe[5]; + public static final BlockFluidPipe[] FLUID_PIPES = new BlockFluidPipe[7]; public static final BlockItemPipe[] ITEM_PIPES = new BlockItemPipe[6]; public static BlockBoilerCasing BOILER_CASING; @@ -185,7 +185,8 @@ public static void init() { StoneType.init(); createGeneratedBlock( - material -> material.hasProperty(PropertyKey.DUST) && !OrePrefix.block.isIgnored(material), + material -> (material.hasProperty(PropertyKey.INGOT) || material.hasProperty(PropertyKey.GEM)) + && !OrePrefix.block.isIgnored(material), MetaBlocks::createCompressedBlock); for (Material material : MaterialRegistry.MATERIAL_REGISTRY) { @@ -200,8 +201,10 @@ public static void init() { } if (material.hasProperty(PropertyKey.WIRE)) { - for (BlockCable cable : CABLES) - cable.addCableMaterial(material, material.getProperty(PropertyKey.WIRE)); + for (BlockCable cable : CABLES) { + if (!cable.getItemPipeType(null).isCable() || !material.getProperty(PropertyKey.WIRE).isSuperconductor) + cable.addCableMaterial(material, material.getProperty(PropertyKey.WIRE)); + } } if (material.hasProperty(PropertyKey.FLUID_PIPE)) { for (BlockFluidPipe pipe : FLUID_PIPES) diff --git a/src/main/java/gregtech/common/blocks/OreItemBlock.java b/src/main/java/gregtech/common/blocks/OreItemBlock.java index e2662db182f..170d00112dc 100644 --- a/src/main/java/gregtech/common/blocks/OreItemBlock.java +++ b/src/main/java/gregtech/common/blocks/OreItemBlock.java @@ -6,8 +6,6 @@ import net.minecraft.creativetab.CreativeTabs; import net.minecraft.item.ItemBlock; import net.minecraft.item.ItemStack; -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; import javax.annotation.Nonnull; @@ -32,18 +30,15 @@ public CreativeTabs[] getCreativeTabs() { return new CreativeTabs[]{CreativeTabs.SEARCH, GregTechAPI.TAB_GREGTECH_ORES}; } - @SuppressWarnings("deprecation") protected IBlockState getBlockState(ItemStack stack) { return oreBlock.getStateFromMeta(getMetadata(stack.getItemDamage())); } @Nonnull @Override - @SideOnly(Side.CLIENT) public String getItemStackDisplayName(@Nonnull ItemStack stack) { IBlockState blockState = getBlockState(stack); StoneType stoneType = blockState.getValue(oreBlock.STONE_TYPE); return stoneType.processingPrefix.getLocalNameForItem(oreBlock.material); } - } diff --git a/src/main/java/gregtech/common/covers/CoverBehaviors.java b/src/main/java/gregtech/common/covers/CoverBehaviors.java index 16ca5a0922d..23aa96ddc38 100644 --- a/src/main/java/gregtech/common/covers/CoverBehaviors.java +++ b/src/main/java/gregtech/common/covers/CoverBehaviors.java @@ -64,6 +64,7 @@ public static void init() { registerBehavior(51, new ResourceLocation(GTValues.MODID, "fluid_detector"), MetaItems.COVER_FLUID_DETECTOR, CoverDetectorFluid::new); registerBehavior(52, new ResourceLocation(GTValues.MODID, "item_detector"), MetaItems.COVER_ITEM_DETECTOR, CoverDetectorItem::new); registerBehavior(53, new ResourceLocation(GTValues.MODID, "crafting_table"), MetaItems.COVER_CRAFTING, CoverCraftingTable::new); + registerBehavior(54, new ResourceLocation(GTValues.MODID, "infinite_water"), MetaItems.COVER_INFINITE_WATER, CoverInfiniteWater::new); for (int i = 0; i < COVERS_PER_ITEM; i++) { int throughput = (int) (Math.pow(4, i) * 1280); diff --git a/src/main/java/gregtech/common/covers/CoverConveyor.java b/src/main/java/gregtech/common/covers/CoverConveyor.java index 65626b6fe32..4fc60d2e397 100644 --- a/src/main/java/gregtech/common/covers/CoverConveyor.java +++ b/src/main/java/gregtech/common/covers/CoverConveyor.java @@ -48,7 +48,7 @@ public class CoverConveyor extends CoverBehavior implements CoverWithUI, ITickab public final int maxItemTransferRate; protected int transferRate; protected ConveyorMode conveyorMode; - protected ItemDistributionMode distributionMode; + protected DistributionMode distributionMode; protected boolean blocksInput; protected ManualImportExportMode manualImportExportMode = ManualImportExportMode.DISABLED; protected final ItemFilterContainer itemFilterContainer; @@ -63,7 +63,7 @@ public CoverConveyor(ICoverable coverable, EnumFacing attachedSide, int tier, in this.transferRate = maxItemTransferRate; this.itemsLeftToTransferLastSecond = transferRate; this.conveyorMode = ConveyorMode.EXPORT; - this.distributionMode = ItemDistributionMode.INSERT_FIRST; + this.distributionMode = DistributionMode.INSERT_FIRST; this.blocksInput = true; this.itemFilterContainer = new ItemFilterContainer(this); } @@ -86,11 +86,11 @@ public ConveyorMode getConveyorMode() { return conveyorMode; } - public ItemDistributionMode getDistributionMode() { + public DistributionMode getDistributionMode() { return distributionMode; } - public void setDistributionMode(ItemDistributionMode distributionMode) { + public void setDistributionMode(DistributionMode distributionMode) { this.distributionMode = distributionMode; coverHolder.markDirty(); } @@ -460,8 +460,8 @@ public ModularUI createUI(EntityPlayer player) { TileEntity otherTile = coverHolder.getWorld().getTileEntity(coverHolder.getPos().offset(attachedSide)); if (!(this instanceof CoverRoboticArm) && coverTile instanceof TileEntityItemPipe ^ otherTile instanceof TileEntityItemPipe) { primaryGroup.addWidget(new ToggleButtonWidget(149, 166, 20, 20, GuiTextures.DISTRIBUTION_MODE, - () -> distributionMode == ItemDistributionMode.INSERT_FIRST, - val -> distributionMode = val ? ItemDistributionMode.INSERT_FIRST : ItemDistributionMode.ROUND_ROBIN) + () -> distributionMode == DistributionMode.INSERT_FIRST, + val -> distributionMode = val ? DistributionMode.INSERT_FIRST : DistributionMode.ROUND_ROBIN) .setTooltipText("cover.conveyor.distribution")); } @@ -500,7 +500,7 @@ public void readFromNBT(NBTTagCompound tagCompound) { super.readFromNBT(tagCompound); this.transferRate = tagCompound.getInteger("TransferRate"); this.conveyorMode = ConveyorMode.values()[tagCompound.getInteger("ConveyorMode")]; - this.distributionMode = ItemDistributionMode.values()[tagCompound.getInteger("DistributionMode")]; + this.distributionMode = DistributionMode.values()[tagCompound.getInteger("DistributionMode")]; this.blocksInput = tagCompound.getBoolean("BlocksInput"); //LEGACY SAVE FORMAT SUPPORT if (tagCompound.hasKey("AllowManualIO")) { @@ -545,11 +545,6 @@ public String getName() { } } - public enum ItemDistributionMode { - INSERT_FIRST, - ROUND_ROBIN - } - private class CoverableItemHandlerWrapper extends ItemHandlerDelegate { public CoverableItemHandlerWrapper(IItemHandler delegate) { diff --git a/src/main/java/gregtech/common/covers/CoverFluidFilter.java b/src/main/java/gregtech/common/covers/CoverFluidFilter.java index 93608ca042a..0ea6b649d4f 100644 --- a/src/main/java/gregtech/common/covers/CoverFluidFilter.java +++ b/src/main/java/gregtech/common/covers/CoverFluidFilter.java @@ -59,6 +59,10 @@ public FluidFilterMode getFilterMode() { return filterMode; } + public boolean testFluidStack(FluidStack stack) { + return fluidFilter.testFluidStack(stack); + } + public boolean canAttach() { return this.coverHolder.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, this.attachedSide) != null; } diff --git a/src/main/java/gregtech/common/covers/CoverFluidRegulator.java b/src/main/java/gregtech/common/covers/CoverFluidRegulator.java index 52562af7372..f3fcd56afba 100644 --- a/src/main/java/gregtech/common/covers/CoverFluidRegulator.java +++ b/src/main/java/gregtech/common/covers/CoverFluidRegulator.java @@ -30,16 +30,17 @@ public class CoverFluidRegulator extends CoverPump { protected TransferMode transferMode; - protected int keepAmount = 0; - protected int supplyAmount = 0; - private static final String supplyKey = "SupplyAmount"; - private static final String keepKey = "KeepAmount"; + protected int transferAmount = 0; public CoverFluidRegulator(ICoverable coverHolder, EnumFacing attachedSide, int tier, int mbPerTick) { super(coverHolder, attachedSide, tier, mbPerTick); this.transferMode = TransferMode.TRANSFER_ANY; } + public int getTransferAmount() { + return transferAmount; + } + @Override protected int doTransferFluidsInternal(IFluidHandler myFluidHandler, IFluidHandler fluidHandler, int transferLimit) { IFluidHandler sourceHandler; @@ -55,12 +56,9 @@ protected int doTransferFluidsInternal(IFluidHandler myFluidHandler, IFluidHandl return 0; } switch (transferMode) { - case TRANSFER_ANY: - return GTFluidUtils.transferFluids(sourceHandler, destHandler, transferLimit, fluidFilter::testFluidStack); - case KEEP_EXACT: - return doKeepExact(transferLimit, sourceHandler, destHandler, fluidFilter::testFluidStack, this.keepAmount); - case TRANSFER_EXACT: - return doTransferExact(transferLimit, sourceHandler, destHandler, fluidFilter::testFluidStack, this.supplyAmount); + case TRANSFER_ANY: return GTFluidUtils.transferFluids(sourceHandler, destHandler, transferLimit, fluidFilter::testFluidStack); + case KEEP_EXACT: return doKeepExact(transferLimit, sourceHandler, destHandler, fluidFilter::testFluidStack, this.transferAmount); + case TRANSFER_EXACT: return doTransferExact(transferLimit, sourceHandler, destHandler, fluidFilter::testFluidStack, this.transferAmount); } return 0; } @@ -123,17 +121,7 @@ private boolean checkTransferMode() { } private String getTransferSizeString() { - int val; - switch (transferMode) { - case KEEP_EXACT: - val = keepAmount; - break; - case TRANSFER_EXACT: - val = supplyAmount; - break; - default: - val = -1; - } + int val = transferAmount; if (this.bucketMode == BucketMode.BUCKET) { val /= 1000; } @@ -141,48 +129,33 @@ private String getTransferSizeString() { } protected void getHoverString(List textList) { - switch (this.transferMode) { - case KEEP_EXACT: - ITextComponent keepComponent = new TextComponentString(getTransferSizeString()); - TextComponentTranslation hoverKeep = new TextComponentTranslation("cover.fluid_regulator.keep_exact", this.keepAmount); - keepComponent.getStyle().setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, hoverKeep)); - textList.add(keepComponent); - break; - case TRANSFER_EXACT: - ITextComponent supplyComponent = new TextComponentString(getTransferSizeString()); - TextComponentTranslation hoverSupply = new TextComponentTranslation("cover.fluid_regulator.supply_exact", this.supplyAmount); - supplyComponent.getStyle().setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, hoverSupply)); - textList.add(supplyComponent); - break; - } + ITextComponent keepComponent = new TextComponentString(getTransferSizeString()); + TextComponentTranslation hoverKeep = new TextComponentTranslation("cover.fluid_regulator." + transferMode.name().toLowerCase(), this.transferAmount); + keepComponent.getStyle().setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, hoverKeep)); + textList.add(keepComponent); } @Override public void setBucketMode(BucketMode bucketMode) { super.setBucketMode(bucketMode); if (this.bucketMode == BucketMode.BUCKET) { - setKeepAmount(keepAmount / 1000 * 1000); - setSupplyAmount(supplyAmount / 1000 * 1000); + setTransferAmount(transferRate / 1000 * 1000); } } private void adjustTransferSize(int amount) { - amount *= this.bucketMode == BucketMode.BUCKET ? 1000 : 1; - switch (this.transferMode) { + if(bucketMode == BucketMode.BUCKET) + amount *= 1000; + switch(this.transferMode) { case TRANSFER_EXACT: - setSupplyAmount(MathHelper.clamp(this.supplyAmount + amount, 0, this.transferRate)); + setTransferAmount(MathHelper.clamp(this.transferAmount + amount, 0, this.transferRate)); case KEEP_EXACT: - setKeepAmount(MathHelper.clamp(this.keepAmount + amount, 0, Integer.MAX_VALUE)); + setTransferAmount(MathHelper.clamp(this.transferAmount + amount, 0, Integer.MAX_VALUE)); } } - private void setKeepAmount(int keepAmount) { - this.keepAmount = keepAmount; - coverHolder.markDirty(); - } - - private void setSupplyAmount(int supplyAmount) { - this.supplyAmount = supplyAmount; + private void setTransferAmount(int transferAmount) { + this.transferAmount = transferAmount; coverHolder.markDirty(); } @@ -211,16 +184,14 @@ protected ModularUI buildUI(ModularUI.Builder builder, EntityPlayer player) { public void writeToNBT(NBTTagCompound tagCompound) { super.writeToNBT(tagCompound); tagCompound.setInteger("TransferMode", transferMode.ordinal()); - tagCompound.setInteger(keepKey, keepAmount); - tagCompound.setInteger(supplyKey, supplyAmount); + tagCompound.setInteger("TransferAmount", transferAmount); } @Override public void readFromNBT(NBTTagCompound tagCompound) { super.readFromNBT(tagCompound); this.transferMode = TransferMode.values()[tagCompound.getInteger("TransferMode")]; - this.keepAmount = tagCompound.getInteger(keepKey); - this.supplyAmount = tagCompound.getInteger(supplyKey); + this.transferAmount = tagCompound.getInteger("TransferAmount"); } @Override diff --git a/src/main/java/gregtech/common/covers/CoverInfiniteWater.java b/src/main/java/gregtech/common/covers/CoverInfiniteWater.java new file mode 100644 index 00000000000..6b8b96c7672 --- /dev/null +++ b/src/main/java/gregtech/common/covers/CoverInfiniteWater.java @@ -0,0 +1,42 @@ +package gregtech.common.covers; + +import codechicken.lib.render.CCRenderState; +import codechicken.lib.render.pipeline.IVertexOperation; +import codechicken.lib.vec.Cuboid6; +import codechicken.lib.vec.Matrix4; +import gregtech.api.cover.CoverBehavior; +import gregtech.api.cover.ICoverable; +import gregtech.api.render.Textures; +import net.minecraft.util.BlockRenderLayer; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.ITickable; +import net.minecraftforge.fluids.FluidRegistry; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.capability.CapabilityFluidHandler; +import net.minecraftforge.fluids.capability.IFluidHandler; + +public class CoverInfiniteWater extends CoverBehavior implements ITickable { + + public CoverInfiniteWater(ICoverable coverHolder, EnumFacing attachedSide) { + super(coverHolder, attachedSide); + } + + @Override + public boolean canAttach() { + return this.coverHolder.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, attachedSide) != null; + } + + @Override + public void renderCover(CCRenderState ccRenderState, Matrix4 matrix4, IVertexOperation[] iVertexOperations, Cuboid6 cuboid6, BlockRenderLayer blockRenderLayer) { + Textures.INFINITE_WATER.renderSided(attachedSide, cuboid6, ccRenderState, iVertexOperations, matrix4); + } + + @Override + public void update() { + if (!coverHolder.getWorld().isRemote && coverHolder.getOffsetTimer() % 20 == 0) { + IFluidHandler fluidHandler = coverHolder.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, attachedSide); + if(fluidHandler != null) + fluidHandler.fill(new FluidStack(FluidRegistry.WATER, 16000), true); + } + } +} diff --git a/src/main/java/gregtech/common/covers/CoverItemFilter.java b/src/main/java/gregtech/common/covers/CoverItemFilter.java index 431535f76fd..0ccf73552e8 100644 --- a/src/main/java/gregtech/common/covers/CoverItemFilter.java +++ b/src/main/java/gregtech/common/covers/CoverItemFilter.java @@ -71,6 +71,10 @@ public EnumActionResult onScrewdriverClick(EntityPlayer playerIn, EnumHand hand, return EnumActionResult.SUCCESS; } + public boolean testItemStack(ItemStack stack) { + return itemFilter.testItemStack(stack); + } + @Override public ModularUI createUI(EntityPlayer player) { WidgetGroup filterGroup = new WidgetGroup(); diff --git a/src/main/java/gregtech/common/covers/CoverPump.java b/src/main/java/gregtech/common/covers/CoverPump.java index 79cc346c58a..da995b11183 100644 --- a/src/main/java/gregtech/common/covers/CoverPump.java +++ b/src/main/java/gregtech/common/covers/CoverPump.java @@ -20,6 +20,7 @@ import gregtech.api.render.Textures; import gregtech.api.util.GTFluidUtils; import gregtech.common.covers.filter.FluidFilterContainer; +import gregtech.common.pipelike.fluidpipe.tile.TileEntityFluidPipe; import net.minecraft.block.Block; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.entity.player.EntityPlayer; @@ -47,6 +48,8 @@ public class CoverPump extends CoverBehavior implements CoverWithUI, ITickable, protected int transferRate; protected PumpMode pumpMode; protected ManualImportExportMode manualImportExportMode = ManualImportExportMode.DISABLED; + protected DistributionMode distributionMode; + protected boolean blocksInput; protected int fluidLeftToTransferLastSecond; private CoverableFluidHandlerWrapper fluidHandlerWrapper; protected boolean isWorkingAllowed = true; @@ -60,6 +63,8 @@ public CoverPump(ICoverable coverHolder, EnumFacing attachedSide, int tier, int this.transferRate = mbPerTick; this.fluidLeftToTransferLastSecond = transferRate; this.pumpMode = PumpMode.EXPORT; + this.distributionMode = DistributionMode.INSERT_FIRST; + this.blocksInput = true; this.bucketMode = BucketMode.MILLI_BUCKET; this.fluidFilter = new FluidFilterContainer(this); } @@ -83,6 +88,15 @@ public PumpMode getPumpMode() { return pumpMode; } + public DistributionMode getDistributionMode() { + return distributionMode; + } + + public void setDistributionMode(DistributionMode distributionMode) { + this.distributionMode = distributionMode; + coverHolder.markDirty(); + } + public void setBucketMode(BucketMode bucketMode) { this.bucketMode = bucketMode; if (this.bucketMode == BucketMode.BUCKET) @@ -103,6 +117,14 @@ protected void setManualImportExportMode(ManualImportExportMode manualImportExpo coverHolder.markDirty(); } + public FluidFilterContainer getFluidFilterContainer() { + return fluidFilter; + } + + public boolean blocksInput() { + return blocksInput; + } + @Override public void update() { long timer = coverHolder.getOffsetTimer(); @@ -168,9 +190,20 @@ public ModularUI createUI(EntityPlayer player) { PumpMode.class, this::getPumpMode, this::setPumpMode)); primaryGroup.addWidget(new CycleButtonWidget(7, 160, 116, 20, - ManualImportExportMode.class, this::getManualImportExportMode, this::setManualImportExportMode) - .setTooltipHoverString("cover.universal.manual_import_export.mode.description")); - + ManualImportExportMode.class, this::getManualImportExportMode, this::setManualImportExportMode) + .setTooltipHoverString("cover.universal.manual_import_export.mode.description")); + + primaryGroup.addWidget(new ToggleButtonWidget(130, 160, 20, 20, GuiTextures.BLOCKS_INPUT, () -> blocksInput, val -> blocksInput = val).setTooltipText("cover.conveyor.blocks_input")); + + TileEntity coverTile = coverHolder.getWorld().getTileEntity(coverHolder.getPos()); + TileEntity otherTile = coverHolder.getWorld().getTileEntity(coverHolder.getPos().offset(attachedSide)); + if(!(this instanceof CoverFluidRegulator) && coverTile instanceof TileEntityFluidPipe ^ otherTile instanceof TileEntityFluidPipe) { + primaryGroup.addWidget(new ToggleButtonWidget(149, 160, 20, 20, GuiTextures.DISTRIBUTION_MODE, + () -> distributionMode == DistributionMode.INSERT_FIRST, + val -> distributionMode = val ? DistributionMode.INSERT_FIRST : DistributionMode.ROUND_ROBIN) + .setTooltipText("cover.conveyor.distribution")); + } + this.fluidFilter.initUI(88, primaryGroup::addWidget); ModularUI.Builder builder = ModularUI.builder(GuiTextures.BACKGROUND, 176, 184 + 82) @@ -241,6 +274,8 @@ public void writeToNBT(NBTTagCompound tagCompound) { super.writeToNBT(tagCompound); tagCompound.setInteger("TransferRate", transferRate); tagCompound.setInteger("PumpMode", pumpMode.ordinal()); + tagCompound.setInteger("DistributionMode", distributionMode.ordinal()); + tagCompound.setBoolean("BlocksInput", blocksInput); tagCompound.setBoolean("WorkingAllowed", isWorkingAllowed); tagCompound.setInteger("ManualImportExportMode", manualImportExportMode.ordinal()); tagCompound.setTag("Filter", fluidFilter.serializeNBT()); @@ -251,6 +286,8 @@ public void readFromNBT(NBTTagCompound tagCompound) { super.readFromNBT(tagCompound); this.transferRate = tagCompound.getInteger("TransferRate"); this.pumpMode = PumpMode.values()[tagCompound.getInteger("PumpMode")]; + this.distributionMode = DistributionMode.values()[tagCompound.getInteger("DistributionMode")]; + this.blocksInput = tagCompound.getBoolean("BlocksInput"); //LEGACY SAVE FORMAT SUPPORT if (tagCompound.hasKey("AllowManualIO")) { this.manualImportExportMode = tagCompound.getBoolean("AllowManualIO") @@ -319,7 +356,7 @@ public CoverableFluidHandlerWrapper(IFluidHandler delegate) { @Override public int fill(FluidStack resource, boolean doFill) { - if (pumpMode == PumpMode.EXPORT && manualImportExportMode == ManualImportExportMode.DISABLED) { + if (blocksInput && pumpMode == PumpMode.EXPORT && manualImportExportMode == ManualImportExportMode.DISABLED) { return 0; } if (!checkInputFluid(resource) && manualImportExportMode == ManualImportExportMode.FILTERED) { diff --git a/src/main/java/gregtech/common/covers/DistributionMode.java b/src/main/java/gregtech/common/covers/DistributionMode.java new file mode 100644 index 00000000000..9bb75778c18 --- /dev/null +++ b/src/main/java/gregtech/common/covers/DistributionMode.java @@ -0,0 +1,6 @@ +package gregtech.common.covers; + +public enum DistributionMode { + INSERT_FIRST, + ROUND_ROBIN +} diff --git a/src/main/java/gregtech/common/gui/widget/CraftingSlotWidget.java b/src/main/java/gregtech/common/gui/widget/CraftingSlotWidget.java index efc351da0ac..a17fb11d866 100644 --- a/src/main/java/gregtech/common/gui/widget/CraftingSlotWidget.java +++ b/src/main/java/gregtech/common/gui/widget/CraftingSlotWidget.java @@ -6,6 +6,7 @@ import gregtech.api.gui.widgets.SlotWidget; import gregtech.common.metatileentities.storage.CraftingRecipeResolver; import mezz.jei.api.gui.IGuiIngredient; +import mezz.jei.api.gui.IRecipeLayout; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.inventory.IInventory; import net.minecraft.inventory.InventoryCraftResult; @@ -106,11 +107,12 @@ public ItemStack onItemTake(EntityPlayer thePlayer, ItemStack stack, boolean sim } @Override - public String transferRecipe(ModularUIContainer container, Map> ingredients, EntityPlayer player, boolean maxTransfer, boolean doTransfer) { + public String transferRecipe(ModularUIContainer container, IRecipeLayout recipeLayout, EntityPlayer player, boolean maxTransfer, boolean doTransfer) { if (!doTransfer) { return null; } - ingredients.values().removeIf(it -> !it.isInput()); + Map> ingredients = new HashMap<>(recipeLayout.getItemStacks().getGuiIngredients()); + ingredients.values().removeIf(it -> it.getAllIngredients().isEmpty() || !it.isInput()); writeClientAction(1, buf -> { buf.writeVarInt(ingredients.size()); for (Entry> entry : ingredients.entrySet()) { diff --git a/src/main/java/gregtech/common/inventory/itemsource/sources/InventoryItemSource.java b/src/main/java/gregtech/common/inventory/itemsource/sources/InventoryItemSource.java index 92da85fc946..258680e467d 100644 --- a/src/main/java/gregtech/common/inventory/itemsource/sources/InventoryItemSource.java +++ b/src/main/java/gregtech/common/inventory/itemsource/sources/InventoryItemSource.java @@ -21,9 +21,6 @@ public abstract class InventoryItemSource extends ItemSource { private StoredItemsChangeCallback changeCallback = null; protected IItemHandler itemHandler = EmptyHandler.INSTANCE; private Map itemStackByAmountMap = new HashMap<>(); - private long lastItemHandlerUpdateTick = -1L; - private long lastStoredItemListUpdateTick = -1L; - private boolean cachedRefreshResult = false; public InventoryItemSource(World world, int priority) { this.world = world; @@ -57,13 +54,11 @@ public void setStoredItemsChangeCallback(StoredItemsChangeCallback callback) { } private boolean refreshItemHandler(boolean simulated) { - this.lastItemHandlerUpdateTick = world.getTotalWorldTime(); IItemHandler newItemHandler = computeItemHandler(); if (newItemHandler == null) { if (!simulated && invalidationCallback != null) { invalidationCallback.run(); } - this.cachedRefreshResult = false; return false; } if (!newItemHandler.equals(itemHandler) || newItemHandler.getSlots() != itemHandler.getSlots()) { @@ -71,29 +66,18 @@ private boolean refreshItemHandler(boolean simulated) { if (!simulated) { recomputeItemStackCount(); } - this.cachedRefreshResult = false; return false; } - this.cachedRefreshResult = true; return true; } @Override public UpdateResult update() { - //update stored item list once a second - long currentTick = world.getTotalWorldTime(); - if (currentTick - lastStoredItemListUpdateTick >= 20) { - return recomputeItemStackCount() ? UpdateResult.CHANGED : UpdateResult.STANDBY; - } - return UpdateResult.STANDBY; + return recomputeItemStackCount() ? UpdateResult.CHANGED : UpdateResult.STANDBY; } private boolean checkItemHandlerValid(boolean simulated) { - long currentUpdateTick = world.getTotalWorldTime(); - if (currentUpdateTick != lastItemHandlerUpdateTick) { - return refreshItemHandler(simulated); - } - return cachedRefreshResult; + return refreshItemHandler(simulated); } /** @@ -150,7 +134,6 @@ private boolean recomputeItemStackCount() { if (!checkItemHandlerValid(false)) { return false; } - this.lastStoredItemListUpdateTick = world.getTotalWorldTime(); HashMap amountMap = new HashMap<>(); for (int i = 0; i < itemHandler.getSlots(); i++) { ItemStack itemStack = itemHandler.getStackInSlot(i); diff --git a/src/main/java/gregtech/common/items/FieldProjectorEventHandler.java b/src/main/java/gregtech/common/items/FieldProjectorEventHandler.java deleted file mode 100644 index 2fe9e1c7a11..00000000000 --- a/src/main/java/gregtech/common/items/FieldProjectorEventHandler.java +++ /dev/null @@ -1,142 +0,0 @@ -package gregtech.common.items; - -import gregtech.api.GTValues; -import gregtech.api.capability.GregtechCapabilities; -import gregtech.api.capability.IElectricItem; -import net.minecraft.entity.Entity; -import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.IProjectile; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.entity.projectile.EntityArrow; -import net.minecraft.entity.projectile.EntityFireball; -import net.minecraft.entity.projectile.EntityPotion; -import net.minecraft.entity.projectile.EntityThrowable; -import net.minecraft.inventory.EntityEquipmentSlot; -import net.minecraft.inventory.IInventory; -import net.minecraft.item.ItemStack; -import net.minecraft.potion.PotionEffect; -import net.minecraft.potion.PotionUtils; -import net.minecraft.util.EnumParticleTypes; -import net.minecraft.util.math.MathHelper; -import net.minecraft.util.math.Vec3d; -import net.minecraft.world.WorldServer; -import net.minecraftforge.event.entity.ProjectileImpactEvent; -import net.minecraftforge.fml.common.Mod.EventBusSubscriber; -import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; -import net.minecraftforge.fml.common.registry.IThrowableEntity; -import org.apache.commons.lang3.tuple.Pair; - -import java.util.List; - -@EventBusSubscriber(modid = GTValues.MODID) -public class FieldProjectorEventHandler { - - private static final long EU_PER_PROJECTILE_DEFLECT = 1024L; - - @SubscribeEvent - public static void onProjectileImpact(ProjectileImpactEvent event) { - Entity hitEntity = event.getRayTraceResult().entityHit; - if (hitEntity instanceof EntityLivingBase && canReflectProjectile((EntityLivingBase) hitEntity, true)) { - Pair projectileData = isHostileProjectile(event.getEntity(), hitEntity); - if (projectileData.getLeft()) { - Entity shooterEntity = projectileData.getRight(); - Vec3d resultHitPosition; - if (shooterEntity != null) { - double posY = shooterEntity.posY + shooterEntity.height / 3.0; - resultHitPosition = new Vec3d(shooterEntity.posX, posY, shooterEntity.posZ); - } else { - Vec3d lookVector = hitEntity.getLookVec(); - resultHitPosition = hitEntity.getPositionVector().add(lookVector.scale(5.0)); - } - if (canReflectProjectile((EntityLivingBase) hitEntity, false)) { - redirectProjectile(event.getEntity(), resultHitPosition); - if (!hitEntity.world.isRemote) { - Vec3d arrowPos = event.getEntity().getPositionVector(); - ((WorldServer) hitEntity.world).spawnParticle(EnumParticleTypes.SPELL_WITCH, false, - arrowPos.x, arrowPos.y, arrowPos.z, 4, 0.0, 0.0, 0.0, 0.1); - } - event.setCanceled(true); - } - } - } - } - - private static boolean canReflectProjectile(EntityLivingBase entity, boolean simulate) { - if (entity instanceof EntityPlayer) { - IInventory inventory = ((EntityPlayer) entity).inventory; - for (int i = 0; i < inventory.getSizeInventory(); i++) { - ItemStack itemStack = inventory.getStackInSlot(i); - if (tryDrainProjector(itemStack, simulate)) return true; - } - } else { - for (EntityEquipmentSlot equipmentSlot : EntityEquipmentSlot.values()) { - ItemStack itemStack = entity.getItemStackFromSlot(equipmentSlot); - if (tryDrainProjector(itemStack, simulate)) return true; - } - } - return false; - } - - private static boolean tryDrainProjector(ItemStack itemStack, boolean simulate) { - if (!MetaItems.ENERGY_FIELD_PROJECTOR.isItemEqual(itemStack)) { - return false; - } - IElectricItem electricItem = itemStack.getCapability(GregtechCapabilities.CAPABILITY_ELECTRIC_ITEM, null); - return electricItem != null && electricItem.discharge(EU_PER_PROJECTILE_DEFLECT, - electricItem.getTier(), true, false, simulate) >= EU_PER_PROJECTILE_DEFLECT; - } - - private static Pair isHostileProjectile(Entity entity, Entity owner) { - if (entity instanceof EntityFireball) { - EntityLivingBase shooter = ((EntityFireball) entity).shootingEntity; - return Pair.of(!owner.isEntityEqual(shooter), shooter); - - } else if (entity instanceof EntityArrow) { - Entity shooter = ((EntityArrow) entity).shootingEntity; - return Pair.of(!owner.isEntityEqual(shooter), shooter); - - } else if (entity instanceof EntityPotion) { - EntityLivingBase shooter = ((EntityPotion) entity).getThrower(); - ItemStack potionStack = ((EntityPotion) entity).getPotion(); - List effectList = PotionUtils.getEffectsFromStack(potionStack); - boolean hasBadEffects = effectList.stream().anyMatch(it -> it.getPotion().isBadEffect()); - //potions without bad effects are not hostile, so do not touch them - return Pair.of(!owner.isEntityEqual(shooter) && hasBadEffects, shooter); - - } else if (entity instanceof EntityThrowable) { - EntityLivingBase shooter = ((EntityThrowable) entity).getThrower(); - return Pair.of(!owner.isEntityEqual(shooter), shooter); - - } else if (entity instanceof IThrowableEntity) { - Entity shooter = ((IThrowableEntity) entity).getThrower(); - return Pair.of(!owner.isEntityEqual(shooter), shooter); - - } else if (entity instanceof IProjectile) { - return Pair.of(true, null); //unknown projectiles are always hostile - } - return Pair.of(false, null); - } - - private static void redirectProjectile(Entity entity, Vec3d targetPosition) { - if (entity instanceof EntityFireball) { - Vec3d directionVector = targetPosition.subtract(entity.getPositionVector()).normalize(); - //compute length of motion vector, and change direction keeping motion vector length - float motionLength = MathHelper.sqrt(entity.motionX * entity.motionX + entity.motionY * entity.motionY + entity.motionZ * entity.motionZ) * 2.0f; - entity.motionX = directionVector.x * motionLength; - entity.motionY = directionVector.y * motionLength; - entity.motionZ = directionVector.z * motionLength; - //then, modify acceleration to point target entity - ((EntityFireball) entity).accelerationX = directionVector.x * 0.1; - ((EntityFireball) entity).accelerationY = directionVector.y * 0.1; - ((EntityFireball) entity).accelerationZ = directionVector.z * 0.1; - - } else if (entity instanceof IProjectile) { - Vec3d distanceVector = targetPosition.subtract(entity.getPositionVector()); - float motionLength = MathHelper.sqrt(entity.motionX * entity.motionX + entity.motionY * entity.motionY + entity.motionZ * entity.motionZ) * 2.0f; - double verticalAccl = MathHelper.sqrt(distanceVector.x * distanceVector.x + distanceVector.z * distanceVector.z); - ((IProjectile) entity).shoot(distanceVector.x, distanceVector.y + verticalAccl * 0.1, distanceVector.z, motionLength, 0.0f); - } - entity.velocityChanged = true; - } - -} diff --git a/src/main/java/gregtech/common/items/MetaItem1.java b/src/main/java/gregtech/common/items/MetaItem1.java index 7d370f8ea07..3a14e45a2ae 100644 --- a/src/main/java/gregtech/common/items/MetaItem1.java +++ b/src/main/java/gregtech/common/items/MetaItem1.java @@ -9,13 +9,13 @@ import gregtech.api.items.metaitem.stats.IItemComponent; import gregtech.api.items.metaitem.stats.IItemContainerItemProvider; import gregtech.api.unification.OreDictUnifier; -import gregtech.api.unification.material.MarkerMaterials; +import gregtech.api.unification.material.MarkerMaterials.Tier; +import gregtech.api.unification.material.MarkerMaterials.Component; import gregtech.api.unification.material.Materials; import gregtech.api.unification.ore.OrePrefix; import gregtech.api.unification.stack.ItemMaterialInfo; import gregtech.api.unification.stack.MaterialStack; import gregtech.api.util.RandomPotionEffect; -import gregtech.common.ConfigHolder; import gregtech.common.items.behaviors.*; import net.minecraft.init.Items; import net.minecraft.init.MobEffects; @@ -34,83 +34,83 @@ public MetaItem1() { @Override public void registerSubItems() { // Credits: ID 0-10 - CREDIT_COPPER = addItem(0, "credit.copper"); - CREDIT_CUPRONICKEL = addItem(1, "credit.cupronickel").setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Cupronickel, 907200L))); - CREDIT_SILVER = addItem(2, "credit.silver"); - CREDIT_GOLD = addItem(3, "credit.gold"); - CREDIT_PLATINUM = addItem(4, "credit.platinum"); - CREDIT_OSMIUM = addItem(5, "credit.osmium"); - CREDIT_NAQUADAH = addItem(6, "credit.naquadah"); - CREDIT_NEUTRONIUM = addItem(7, "credit.neutronium"); + CREDIT_COPPER = addItem(0, "credit.copper").setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Copper, GTValues.M / 4))); + CREDIT_CUPRONICKEL = addItem(1, "credit.cupronickel").setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Cupronickel, GTValues.M / 4))); + CREDIT_SILVER = addItem(2, "credit.silver").setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Silver, GTValues.M / 4))); + CREDIT_GOLD = addItem(3, "credit.gold").setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Gold, GTValues.M / 4))); + CREDIT_PLATINUM = addItem(4, "credit.platinum").setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Platinum, GTValues.M / 4))); + CREDIT_OSMIUM = addItem(5, "credit.osmium").setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Osmium, GTValues.M / 4))); + CREDIT_NAQUADAH = addItem(6, "credit.naquadah").setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Naquadah, GTValues.M / 4))); + CREDIT_NEUTRONIUM = addItem(7, "credit.neutronium").setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Neutronium, GTValues.M / 4))); COIN_GOLD_ANCIENT = addItem(8, "coin.gold.ancient"). - setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Gold, 907200L))); + setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Gold, GTValues.M / 4))); COIN_DOGE = addItem(9, "coin.doge") - .setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Brass, 907200L))); + .setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Brass, GTValues.M / 4))); COIN_CHOCOLATE = addItem(10, "coin.chocolate") - .setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Gold, OrePrefix.foil.materialAmount))) + .setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Gold, GTValues.M / 4))) .addComponents(new FoodStats(1, 0.1F, false, true, OreDictUnifier.get(OrePrefix.foil, Materials.Gold), new RandomPotionEffect(MobEffects.SPEED, 200, 1, 10))); // Solidifier Shapes: ID 11-30 - SHAPE_EMPTY = addItem(11, "shape.empty"); - - SHAPE_MOLDS[0] = SHAPE_MOLD_PLATE = addItem(12, "shape.mold.plate"); - SHAPE_MOLDS[1] = SHAPE_MOLD_GEAR = addItem(13, "shape.mold.gear"); - SHAPE_MOLDS[2] = SHAPE_MOLD_CREDIT = addItem(14, "shape.mold.credit"); - SHAPE_MOLDS[3] = SHAPE_MOLD_BOTTLE = addItem(15, "shape.mold.bottle"); - SHAPE_MOLDS[4] = SHAPE_MOLD_INGOT = addItem(16, "shape.mold.ingot"); - SHAPE_MOLDS[5] = SHAPE_MOLD_BALL = addItem(17, "shape.mold.ball"); - SHAPE_MOLDS[6] = SHAPE_MOLD_BLOCK = addItem(18, "shape.mold.block"); - SHAPE_MOLDS[7] = SHAPE_MOLD_NUGGET = addItem(19, "shape.mold.nugget"); - SHAPE_MOLDS[8] = SHAPE_MOLD_CYLINDER = addItem(20, "shape.mold.cylinder"); - SHAPE_MOLDS[9] = SHAPE_MOLD_ANVIL = addItem(21, "shape.mold.anvil"); - SHAPE_MOLDS[10] = SHAPE_MOLD_NAME = addItem(22, "shape.mold.name"); - SHAPE_MOLDS[11] = SHAPE_MOLD_GEAR_SMALL = addItem(23, "shape.mold.gear.small"); - SHAPE_MOLDS[12] = SHAPE_MOLD_ROTOR = addItem(24, "shape.mold.rotor"); + SHAPE_EMPTY = addItem(11, "shape.empty").setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Steel, GTValues.M * 4))); + + SHAPE_MOLDS[0] = SHAPE_MOLD_PLATE = addItem(12, "shape.mold.plate").setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Steel, GTValues.M * 4))); + SHAPE_MOLDS[1] = SHAPE_MOLD_GEAR = addItem(13, "shape.mold.gear").setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Steel, GTValues.M * 4))); + SHAPE_MOLDS[2] = SHAPE_MOLD_CREDIT = addItem(14, "shape.mold.credit").setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Steel, GTValues.M * 4))); + SHAPE_MOLDS[3] = SHAPE_MOLD_BOTTLE = addItem(15, "shape.mold.bottle").setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Steel, GTValues.M * 4))); + SHAPE_MOLDS[4] = SHAPE_MOLD_INGOT = addItem(16, "shape.mold.ingot").setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Steel, GTValues.M * 4))); + SHAPE_MOLDS[5] = SHAPE_MOLD_BALL = addItem(17, "shape.mold.ball").setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Steel, GTValues.M * 4))); + SHAPE_MOLDS[6] = SHAPE_MOLD_BLOCK = addItem(18, "shape.mold.block").setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Steel, GTValues.M * 4))); + SHAPE_MOLDS[7] = SHAPE_MOLD_NUGGET = addItem(19, "shape.mold.nugget").setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Steel, GTValues.M * 4))); + SHAPE_MOLDS[8] = SHAPE_MOLD_CYLINDER = addItem(20, "shape.mold.cylinder").setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Steel, GTValues.M * 4))); + SHAPE_MOLDS[9] = SHAPE_MOLD_ANVIL = addItem(21, "shape.mold.anvil").setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Steel, GTValues.M * 4))); + SHAPE_MOLDS[10] = SHAPE_MOLD_NAME = addItem(22, "shape.mold.name").setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Steel, GTValues.M * 4))); + SHAPE_MOLDS[11] = SHAPE_MOLD_GEAR_SMALL = addItem(23, "shape.mold.gear.small").setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Steel, GTValues.M * 4))); + SHAPE_MOLDS[12] = SHAPE_MOLD_ROTOR = addItem(24, "shape.mold.rotor").setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Steel, GTValues.M * 4))); // Extruder Shapes: ID 31-60 - SHAPE_EXTRUDERS[0] = SHAPE_EXTRUDER_PLATE = addItem(31, "shape.extruder.plate"); - SHAPE_EXTRUDERS[1] = SHAPE_EXTRUDER_ROD = addItem(32, "shape.extruder.rod"); - SHAPE_EXTRUDERS[2] = SHAPE_EXTRUDER_BOLT = addItem(33, "shape.extruder.bolt"); - SHAPE_EXTRUDERS[3] = SHAPE_EXTRUDER_RING = addItem(34, "shape.extruder.ring"); - SHAPE_EXTRUDERS[4] = SHAPE_EXTRUDER_CELL = addItem(35, "shape.extruder.cell"); - SHAPE_EXTRUDERS[5] = SHAPE_EXTRUDER_INGOT = addItem(36, "shape.extruder.ingot"); - SHAPE_EXTRUDERS[6] = SHAPE_EXTRUDER_WIRE = addItem(37, "shape.extruder.wire"); - SHAPE_EXTRUDERS[7] = SHAPE_EXTRUDER_PIPE_TINY = addItem(38, "shape.extruder.pipe.tiny"); - SHAPE_EXTRUDERS[8] = SHAPE_EXTRUDER_PIPE_SMALL = addItem(39, "shape.extruder.pipe.small"); - SHAPE_EXTRUDERS[9] = SHAPE_EXTRUDER_PIPE_MEDIUM = addItem(40, "shape.extruder.pipe.medium"); - SHAPE_EXTRUDERS[10] = SHAPE_EXTRUDER_PIPE_LARGE = addItem(41, "shape.extruder.pipe.large"); - SHAPE_EXTRUDERS[11] = SHAPE_EXTRUDER_PIPE_HUGE = addItem(42, "shape.extruder.pipe.huge"); - SHAPE_EXTRUDERS[12] = SHAPE_EXTRUDER_BLOCK = addItem(43, "shape.extruder.block"); - SHAPE_EXTRUDERS[13] = SHAPE_EXTRUDER_SWORD = addItem(44, "shape.extruder.sword"); - SHAPE_EXTRUDERS[14] = SHAPE_EXTRUDER_PICKAXE = addItem(45, "shape.extruder.pickaxe"); - SHAPE_EXTRUDERS[15] = SHAPE_EXTRUDER_SHOVEL = addItem(46, "shape.extruder.shovel"); - SHAPE_EXTRUDERS[16] = SHAPE_EXTRUDER_AXE = addItem(47, "shape.extruder.axe"); - SHAPE_EXTRUDERS[17] = SHAPE_EXTRUDER_HOE = addItem(48, "shape.extruder.hoe"); - SHAPE_EXTRUDERS[18] = SHAPE_EXTRUDER_HAMMER = addItem(49, "shape.extruder.hammer"); - SHAPE_EXTRUDERS[19] = SHAPE_EXTRUDER_FILE = addItem(50, "shape.extruder.file"); - SHAPE_EXTRUDERS[20] = SHAPE_EXTRUDER_SAW = addItem(51, "shape.extruder.saw"); - SHAPE_EXTRUDERS[21] = SHAPE_EXTRUDER_GEAR = addItem(52, "shape.extruder.gear"); - SHAPE_EXTRUDERS[22] = SHAPE_EXTRUDER_BOTTLE = addItem(53, "shape.extruder.bottle"); - SHAPE_EXTRUDERS[23] = SHAPE_EXTRUDER_FOIL = addItem(54, "shape.extruder.foil"); - SHAPE_EXTRUDERS[24] = SHAPE_EXTRUDER_GEAR_SMALL = addItem(55, "shape.extruder.gear_small"); - SHAPE_EXTRUDERS[25] = SHAPE_EXTRUDER_ROD_LONG = addItem(56, "shape.extruder.rod_long"); + SHAPE_EXTRUDERS[0] = SHAPE_EXTRUDER_PLATE = addItem(31, "shape.extruder.plate").setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Steel, GTValues.M * 4))); + SHAPE_EXTRUDERS[1] = SHAPE_EXTRUDER_ROD = addItem(32, "shape.extruder.rod").setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Steel, GTValues.M * 4))); + SHAPE_EXTRUDERS[2] = SHAPE_EXTRUDER_BOLT = addItem(33, "shape.extruder.bolt").setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Steel, GTValues.M * 4))); + SHAPE_EXTRUDERS[3] = SHAPE_EXTRUDER_RING = addItem(34, "shape.extruder.ring").setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Steel, GTValues.M * 4))); + SHAPE_EXTRUDERS[4] = SHAPE_EXTRUDER_CELL = addItem(35, "shape.extruder.cell").setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Steel, GTValues.M * 4))); + SHAPE_EXTRUDERS[5] = SHAPE_EXTRUDER_INGOT = addItem(36, "shape.extruder.ingot").setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Steel, GTValues.M * 4))); + SHAPE_EXTRUDERS[6] = SHAPE_EXTRUDER_WIRE = addItem(37, "shape.extruder.wire").setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Steel, GTValues.M * 4))); + SHAPE_EXTRUDERS[7] = SHAPE_EXTRUDER_PIPE_TINY = addItem(38, "shape.extruder.pipe.tiny").setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Steel, GTValues.M * 4))); + SHAPE_EXTRUDERS[8] = SHAPE_EXTRUDER_PIPE_SMALL = addItem(39, "shape.extruder.pipe.small").setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Steel, GTValues.M * 4))); + SHAPE_EXTRUDERS[9] = SHAPE_EXTRUDER_PIPE_MEDIUM = addItem(40, "shape.extruder.pipe.medium").setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Steel, GTValues.M * 4))); + SHAPE_EXTRUDERS[10] = SHAPE_EXTRUDER_PIPE_LARGE = addItem(41, "shape.extruder.pipe.large").setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Steel, GTValues.M * 4))); + SHAPE_EXTRUDERS[11] = SHAPE_EXTRUDER_PIPE_HUGE = addItem(42, "shape.extruder.pipe.huge").setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Steel, GTValues.M * 4))); + SHAPE_EXTRUDERS[12] = SHAPE_EXTRUDER_BLOCK = addItem(43, "shape.extruder.block").setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Steel, GTValues.M * 4))); + SHAPE_EXTRUDERS[13] = SHAPE_EXTRUDER_SWORD = addItem(44, "shape.extruder.sword").setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Steel, GTValues.M * 4))); + SHAPE_EXTRUDERS[14] = SHAPE_EXTRUDER_PICKAXE = addItem(45, "shape.extruder.pickaxe").setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Steel, GTValues.M * 4))); + SHAPE_EXTRUDERS[15] = SHAPE_EXTRUDER_SHOVEL = addItem(46, "shape.extruder.shovel").setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Steel, GTValues.M * 4))); + SHAPE_EXTRUDERS[16] = SHAPE_EXTRUDER_AXE = addItem(47, "shape.extruder.axe").setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Steel, GTValues.M * 4))); + SHAPE_EXTRUDERS[17] = SHAPE_EXTRUDER_HOE = addItem(48, "shape.extruder.hoe").setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Steel, GTValues.M * 4))); + SHAPE_EXTRUDERS[18] = SHAPE_EXTRUDER_HAMMER = addItem(49, "shape.extruder.hammer").setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Steel, GTValues.M * 4))); + SHAPE_EXTRUDERS[19] = SHAPE_EXTRUDER_FILE = addItem(50, "shape.extruder.file").setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Steel, GTValues.M * 4))); + SHAPE_EXTRUDERS[20] = SHAPE_EXTRUDER_SAW = addItem(51, "shape.extruder.saw").setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Steel, GTValues.M * 4))); + SHAPE_EXTRUDERS[21] = SHAPE_EXTRUDER_GEAR = addItem(52, "shape.extruder.gear").setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Steel, GTValues.M * 4))); + SHAPE_EXTRUDERS[22] = SHAPE_EXTRUDER_BOTTLE = addItem(53, "shape.extruder.bottle").setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Steel, GTValues.M * 4))); + SHAPE_EXTRUDERS[23] = SHAPE_EXTRUDER_FOIL = addItem(54, "shape.extruder.foil").setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Steel, GTValues.M * 4))); + SHAPE_EXTRUDERS[24] = SHAPE_EXTRUDER_GEAR_SMALL = addItem(55, "shape.extruder.gear_small").setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Steel, GTValues.M * 4))); + SHAPE_EXTRUDERS[25] = SHAPE_EXTRUDER_ROD_LONG = addItem(56, "shape.extruder.rod_long").setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Steel, GTValues.M * 4))); // Spray Cans: ID 61-77 SPRAY_EMPTY = addItem(61, "spray.empty") - .setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Tin, OrePrefix.plate.materialAmount * 2L), new MaterialStack(Materials.Redstone, OrePrefix.dust.materialAmount))); + .setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Tin, GTValues.M * 2), new MaterialStack(Materials.Redstone, GTValues.M))); for (int i = 0; i < EnumDyeColor.values().length; i++) { - EnumDyeColor dyeColor = EnumDyeColor.values()[i]; - SPRAY_CAN_DYES[i] = addItem(62 + i, "spray.can.dyes." + dyeColor.getName()).setMaxStackSize(1); - ColorSprayBehaviour behaviour = new ColorSprayBehaviour(SPRAY_EMPTY.getStackForm(), 512, i); - SPRAY_CAN_DYES[i].addComponents(behaviour); + SPRAY_CAN_DYES[i] = addItem(62 + i, "spray.can.dyes." + EnumDyeColor.values()[i].getName()).setMaxStackSize(1) + .addComponents(new ColorSprayBehaviour(SPRAY_EMPTY.getStackForm(), 512, i)); } // Fluid Cells: ID 78-88 - FLUID_CELL = addItem(78, "fluid_cell").addComponents(new FluidStats(1000, Integer.MIN_VALUE, Integer.MAX_VALUE, false)); + FLUID_CELL = addItem(78, "fluid_cell").addComponents(new FluidStats(1000, Integer.MIN_VALUE, Integer.MAX_VALUE, false)) + .setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Tin, GTValues.M * 2))); - UNIVERSAL_FLUID_CELL = addItem(79, "fluid_cell.universal").addComponents(new FluidStats(1000, Integer.MIN_VALUE, Integer.MAX_VALUE, true)); + UNIVERSAL_FLUID_CELL = addItem(79, "fluid_cell.universal").addComponents(new FluidStats(1000, Integer.MIN_VALUE, Integer.MAX_VALUE, true)) + .setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Tin, GTValues.M * 2))); LARGE_FLUID_CELL_STEEL = addItem(80, "large_fluid_cell.steel") .addComponents(new FluidStats(8000, Integer.MIN_VALUE, Integer.MAX_VALUE, true)) @@ -160,24 +160,24 @@ public void registerSubItems() { TOOL_MATCHBOX = addItem(90, "tool.matchbox") .addComponents(new LighterBehaviour(16)).setMaxStackSize(1); TOOL_LIGHTER_INVAR = addItem(91, "tool.lighter.invar") - .setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Invar, GTValues.L * 2))) + .setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Invar, GTValues.M * 2))) .addComponents(new LighterBehaviour(100)).setMaxStackSize(1); TOOL_LIGHTER_PLATINUM = addItem(92, "tool.lighter.platinum") - .setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Platinum, GTValues.L * 2))) + .setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Platinum, GTValues.M * 2))) .addComponents(new LighterBehaviour(1000)).setMaxStackSize(1); BOTTLE_PURPLE_DRINK = addItem(93, "bottle.purple.drink").addComponents(new FoodStats(8, 0.2F, true, true, new ItemStack(Items.GLASS_BOTTLE), new RandomPotionEffect(MobEffects.HASTE, 800, 1, 90))); // Voltage Coils: ID 96-110 - VOLTAGE_COIL_ULV = addItem(96, "voltage_coil.ulv"); - VOLTAGE_COIL_LV = addItem(97, "voltage_coil.lv"); - VOLTAGE_COIL_MV = addItem(98, "voltage_coil.mv"); - VOLTAGE_COIL_HV = addItem(99, "voltage_coil.hv"); - VOLTAGE_COIL_EV = addItem(100, "voltage_coil.ev"); - VOLTAGE_COIL_IV = addItem(101, "voltage_coil.iv"); - VOLTAGE_COIL_LUV = addItem(102, "voltage_coil.luv"); - VOLTAGE_COIL_ZPM = addItem(103, "voltage_coil.zpm"); - VOLTAGE_COIL_UV = addItem(104, "voltage_coil.uv"); + VOLTAGE_COIL_ULV = addItem(96, "voltage_coil.ulv").setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Lead, GTValues.M * 2), new MaterialStack(Materials.IronMagnetic, GTValues.M / 2))); + VOLTAGE_COIL_LV = addItem(97, "voltage_coil.lv").setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Steel, GTValues.M * 2), new MaterialStack(Materials.IronMagnetic, GTValues.M / 2))); + VOLTAGE_COIL_MV = addItem(98, "voltage_coil.mv").setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Aluminium, GTValues.M * 2), new MaterialStack(Materials.SteelMagnetic, GTValues.M / 2))); + VOLTAGE_COIL_HV = addItem(99, "voltage_coil.hv").setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.BlackSteel, GTValues.M * 2), new MaterialStack(Materials.SteelMagnetic, GTValues.M / 2))); + VOLTAGE_COIL_EV = addItem(100, "voltage_coil.ev").setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.TungstenSteel, GTValues.M * 2), new MaterialStack(Materials.NeodymiumMagnetic, GTValues.M / 2))); + VOLTAGE_COIL_IV = addItem(101, "voltage_coil.iv").setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Iridium, GTValues.M * 2), new MaterialStack(Materials.NeodymiumMagnetic, GTValues.M / 2))); + VOLTAGE_COIL_LUV = addItem(102, "voltage_coil.luv").setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Osmiridium, GTValues.M * 2), new MaterialStack(Materials.SamariumMagnetic, GTValues.M / 2))); + VOLTAGE_COIL_ZPM = addItem(103, "voltage_coil.zpm").setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Europium, GTValues.M * 2), new MaterialStack(Materials.SamariumMagnetic, GTValues.M / 2))); + VOLTAGE_COIL_UV = addItem(104, "voltage_coil.uv").setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.FluxedElectrum, GTValues.M * 2), new MaterialStack(Materials.SamariumMagnetic, GTValues.M / 2))); // ???: ID 111-125 @@ -276,9 +276,12 @@ public void registerSubItems() { TOOL_DATA_ORB = addItem(262, "tool.dataorb"); // Special Machine Components: ID 266-280 - COMPONENT_SAW_BLADE_DIAMOND = addItem(266, "component.sawblade.diamond").addOreDict(OreDictNames.craftingDiamondBlade); - COMPONENT_GRINDER_DIAMOND = addItem(267, "component.grinder.diamond").addOreDict(OreDictNames.craftingGrinder); - COMPONENT_GRINDER_TUNGSTEN = addItem(268, "component.grinder.tungsten").addOreDict(OreDictNames.craftingGrinder); + COMPONENT_SAW_BLADE_DIAMOND = addItem(266, "component.sawblade.diamond").addOreDict(OreDictNames.craftingDiamondBlade) + .setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Invar, GTValues.M * 4), new MaterialStack(Materials.Diamond, GTValues.M))); + COMPONENT_GRINDER_DIAMOND = addItem(267, "component.grinder.diamond").addOreDict(OreDictNames.craftingGrinder) + .setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Steel, GTValues.M * 4), new MaterialStack(Materials.Diamond, GTValues.M * 5))); + COMPONENT_GRINDER_TUNGSTEN = addItem(268, "component.grinder.tungsten").addOreDict(OreDictNames.craftingGrinder) + .setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Tungsten, GTValues.M * 4), new MaterialStack(Materials.Steel, GTValues.M * 4), new MaterialStack(Materials.Diamond, GTValues.M))); // Special Eyes/Stars: ID 281-289 QUANTUM_EYE = addItem(281, "quantumeye"); @@ -301,6 +304,7 @@ public void registerSubItems() { COVER_CRAFTING = addItem(307, "cover.crafting"); COVER_DRAIN = addItem(308, "cover.drain"); COVER_SHUTTER = addItem(309, "cover.shutter"); + COVER_INFINITE_WATER = addItem(310, "cover.infinite_water"); COVER_FACADE = addItem(330, "cover.facade").addComponents(new FacadeItem()).disableModelLoading(); // Solar Panels: ID 331-346 @@ -371,9 +375,10 @@ public void registerSubItems() { INTEGRATED_CIRCUIT = addItem(461, "circuit.integrated").addComponents(new IntCircuitBehaviour()).setModelAmount(33); FOAM_SPRAYER = addItem(462, "foam_sprayer").addComponents(new FoamSprayerBehavior()).setMaxStackSize(1); NANO_SABER = addItem(463, "nano_saber").addComponents(ElectricStats.createElectricItem(4000000L, GTValues.HV)).addComponents(new NanoSaberBehavior()).setMaxStackSize(1); - ENERGY_FIELD_PROJECTOR = addItem(464, "energy_field_projector").addComponents(ElectricStats.createElectricItem(16000000L, GTValues.EV)).setMaxStackSize(1); + // Free ID 464 SCANNER = addItem(465, "scanner").addComponents(ElectricStats.createElectricItem(200_000L, GTValues.LV), new ScannerBehavior(50)); CLIPBOARD = addItem(466, "clipboard").addComponents(new ClipboardBehavior()).setMaxStackSize(1); + TERMINAL = addItem(467, "terminal").addComponents(new TerminalBehaviour()); // Misc Crafting Items: ID 491-515 ENERGIUM_DUST = addItem(491, "energium_dust"); @@ -389,17 +394,17 @@ public void registerSubItems() { CARBON_PLATE = addItem(501, "carbon.plate"); // Circuit Components: ID 516-565 - VACUUM_TUBE = addItem(516, "circuit.vacuum_tube").setUnificationData(OrePrefix.circuit, MarkerMaterials.Tier.Primitive); + VACUUM_TUBE = addItem(516, "circuit.vacuum_tube").setUnificationData(OrePrefix.circuit, Tier.Primitive); GLASS_TUBE = addItem(517, "component.glass.tube"); SMALL_COIL = addItem(518, "component.small_coil"); - TRANSISTOR = addItem(519, "component.transistor").setUnificationData(OrePrefix.component, MarkerMaterials.Component.Transistor); - RESISTOR = addItem(520, "component.resistor").setUnificationData(OrePrefix.component, MarkerMaterials.Component.Resistor); - CAPACITOR = addItem(521, "component.capacitor").setUnificationData(OrePrefix.component, MarkerMaterials.Component.Capacitor); - DIODE = addItem(522, "component.diode").setUnificationData(OrePrefix.component, MarkerMaterials.Component.Diode); - SMD_TRANSISTOR = addItem(523, "component.smd.transistor").setUnificationData(OrePrefix.component, MarkerMaterials.Component.Transistor); - SMD_RESISTOR = addItem(524, "component.smd.resistor").setUnificationData(OrePrefix.component, MarkerMaterials.Component.Resistor); - SMD_CAPACITOR = addItem(525, "component.smd.capacitor").setUnificationData(OrePrefix.component, MarkerMaterials.Component.Capacitor); - SMD_DIODE = addItem(526, "component.smd.diode").setUnificationData(OrePrefix.component, MarkerMaterials.Component.Diode); + TRANSISTOR = addItem(519, "component.transistor").setUnificationData(OrePrefix.component, Component.Transistor); + RESISTOR = addItem(520, "component.resistor").setUnificationData(OrePrefix.component, Component.Resistor); + CAPACITOR = addItem(521, "component.capacitor").setUnificationData(OrePrefix.component, Component.Capacitor); + DIODE = addItem(522, "component.diode").setUnificationData(OrePrefix.component, Component.Diode); + SMD_TRANSISTOR = addItem(523, "component.smd.transistor").setUnificationData(OrePrefix.component, Component.Transistor); + SMD_RESISTOR = addItem(524, "component.smd.resistor").setUnificationData(OrePrefix.component, Component.Resistor); + SMD_CAPACITOR = addItem(525, "component.smd.capacitor").setUnificationData(OrePrefix.component, Component.Capacitor); + SMD_DIODE = addItem(526, "component.smd.diode").setUnificationData(OrePrefix.component, Component.Diode); ADVANCED_SMD_TRANSISTOR = addItem(527, "component.advanced_smd.transistor"); ADVANCED_SMD_RESISTOR = addItem(528, "component.advanced_smd.resistor"); ADVANCED_SMD_CAPACITOR = addItem(529, "component.advanced_smd.capacitor"); @@ -444,47 +449,47 @@ public void registerSubItems() { // Circuits: ID 621-700 // T1: Electronic - ELECTRONIC_CIRCUIT_LV = addItem(621, "circuit.electronic").setUnificationData(OrePrefix.circuit, MarkerMaterials.Tier.Basic); - ELECTRONIC_CIRCUIT_MV = addItem(622, "circuit.good_electronic").setUnificationData(OrePrefix.circuit, MarkerMaterials.Tier.Good); + ELECTRONIC_CIRCUIT_LV = addItem(621, "circuit.electronic").setUnificationData(OrePrefix.circuit, Tier.Basic); + ELECTRONIC_CIRCUIT_MV = addItem(622, "circuit.good_electronic").setUnificationData(OrePrefix.circuit, Tier.Good); // T2: Integrated - INTEGRATED_CIRCUIT_LV = addItem(623, "circuit.basic_integrated").setUnificationData(OrePrefix.circuit, MarkerMaterials.Tier.Basic); - INTEGRATED_CIRCUIT_MV = addItem(624, "circuit.good_integrated").setUnificationData(OrePrefix.circuit, MarkerMaterials.Tier.Good); - INTEGRATED_CIRCUIT_HV = addItem(625, "circuit.advanced_integrated").setUnificationData(OrePrefix.circuit, MarkerMaterials.Tier.Advanced); + INTEGRATED_CIRCUIT_LV = addItem(623, "circuit.basic_integrated").setUnificationData(OrePrefix.circuit, Tier.Basic); + INTEGRATED_CIRCUIT_MV = addItem(624, "circuit.good_integrated").setUnificationData(OrePrefix.circuit, Tier.Good); + INTEGRATED_CIRCUIT_HV = addItem(625, "circuit.advanced_integrated").setUnificationData(OrePrefix.circuit, Tier.Advanced); // Misc Unlocks - NAND_CHIP_ULV = addItem(626, "circuit.nand_chip").setUnificationData(OrePrefix.circuit, MarkerMaterials.Tier.Primitive); - MICROPROCESSOR_LV = addItem(627, "circuit.microprocessor").setUnificationData(OrePrefix.circuit, MarkerMaterials.Tier.Basic); + NAND_CHIP_ULV = addItem(626, "circuit.nand_chip").setUnificationData(OrePrefix.circuit, Tier.Primitive); + MICROPROCESSOR_LV = addItem(627, "circuit.microprocessor").setUnificationData(OrePrefix.circuit, Tier.Basic); // T3: Processor - PROCESSOR_MV = addItem(628, "circuit.processor").setUnificationData(OrePrefix.circuit, MarkerMaterials.Tier.Good); - PROCESSOR_ASSEMBLY_HV = addItem(629, "circuit.assembly").setUnificationData(OrePrefix.circuit, MarkerMaterials.Tier.Advanced); - WORKSTATION_EV = addItem(630, "circuit.workstation").setUnificationData(OrePrefix.circuit, MarkerMaterials.Tier.Extreme); - MAINFRAME_IV = addItem(631, "circuit.mainframe").setUnificationData(OrePrefix.circuit, MarkerMaterials.Tier.Elite); + PROCESSOR_MV = addItem(628, "circuit.processor").setUnificationData(OrePrefix.circuit, Tier.Good); + PROCESSOR_ASSEMBLY_HV = addItem(629, "circuit.assembly").setUnificationData(OrePrefix.circuit, Tier.Advanced); + WORKSTATION_EV = addItem(630, "circuit.workstation").setUnificationData(OrePrefix.circuit, Tier.Extreme); + MAINFRAME_IV = addItem(631, "circuit.mainframe").setUnificationData(OrePrefix.circuit, Tier.Elite); // T4: Nano - NANO_PROCESSOR_HV = addItem(632, "circuit.nano_processor").setUnificationData(OrePrefix.circuit, MarkerMaterials.Tier.Advanced); - NANO_PROCESSOR_ASSEMBLY_EV = addItem(633, "circuit.nano_assembly").setUnificationData(OrePrefix.circuit, MarkerMaterials.Tier.Extreme); - NANO_COMPUTER_IV = addItem(634, "circuit.nano_computer").setUnificationData(OrePrefix.circuit, MarkerMaterials.Tier.Elite); - NANO_MAINFRAME_LUV = addItem(635, "circuit.nano_mainframe").setUnificationData(OrePrefix.circuit, MarkerMaterials.Tier.Master); + NANO_PROCESSOR_HV = addItem(632, "circuit.nano_processor").setUnificationData(OrePrefix.circuit, Tier.Advanced); + NANO_PROCESSOR_ASSEMBLY_EV = addItem(633, "circuit.nano_assembly").setUnificationData(OrePrefix.circuit, Tier.Extreme); + NANO_COMPUTER_IV = addItem(634, "circuit.nano_computer").setUnificationData(OrePrefix.circuit, Tier.Elite); + NANO_MAINFRAME_LUV = addItem(635, "circuit.nano_mainframe").setUnificationData(OrePrefix.circuit, Tier.Master); // T5: Quantum - QUANTUM_PROCESSOR_EV = addItem(636, "circuit.quantum_processor").setUnificationData(OrePrefix.circuit, MarkerMaterials.Tier.Extreme); - QUANTUM_ASSEMBLY_IV = addItem(637, "circuit.quantum_assembly").setUnificationData(OrePrefix.circuit, MarkerMaterials.Tier.Elite); - QUANTUM_COMPUTER_LUV = addItem(638, "circuit.quantum_computer").setUnificationData(OrePrefix.circuit, MarkerMaterials.Tier.Master); - QUANTUM_MAINFRAME_ZPM = addItem(639, "circuit.quantum_mainframe").setUnificationData(OrePrefix.circuit, MarkerMaterials.Tier.Ultimate); + QUANTUM_PROCESSOR_EV = addItem(636, "circuit.quantum_processor").setUnificationData(OrePrefix.circuit, Tier.Extreme); + QUANTUM_ASSEMBLY_IV = addItem(637, "circuit.quantum_assembly").setUnificationData(OrePrefix.circuit, Tier.Elite); + QUANTUM_COMPUTER_LUV = addItem(638, "circuit.quantum_computer").setUnificationData(OrePrefix.circuit, Tier.Master); + QUANTUM_MAINFRAME_ZPM = addItem(639, "circuit.quantum_mainframe").setUnificationData(OrePrefix.circuit, Tier.Ultimate); // T6: Crystal - CRYSTAL_PROCESSOR_IV = addItem(640, "circuit.crystal_processor").setUnificationData(OrePrefix.circuit, MarkerMaterials.Tier.Elite); - CRYSTAL_ASSEMBLY_LUV = addItem(641, "circuit.crystal_assembly").setUnificationData(OrePrefix.circuit, MarkerMaterials.Tier.Master); - CRYSTAL_COMPUTER_ZPM = addItem(642, "circuit.crystal_computer").setUnificationData(OrePrefix.circuit, MarkerMaterials.Tier.Ultimate); - CRYSTAL_MAINFRAME_UV = addItem(643, "circuit.crystal_mainframe").setUnificationData(OrePrefix.circuit, MarkerMaterials.Tier.Superconductor); + CRYSTAL_PROCESSOR_IV = addItem(640, "circuit.crystal_processor").setUnificationData(OrePrefix.circuit, Tier.Elite); + CRYSTAL_ASSEMBLY_LUV = addItem(641, "circuit.crystal_assembly").setUnificationData(OrePrefix.circuit, Tier.Master); + CRYSTAL_COMPUTER_ZPM = addItem(642, "circuit.crystal_computer").setUnificationData(OrePrefix.circuit, Tier.Ultimate); + CRYSTAL_MAINFRAME_UV = addItem(643, "circuit.crystal_mainframe").setUnificationData(OrePrefix.circuit, Tier.Superconductor); // T7: Wetware - WETWARE_PROCESSOR_LUV = addItem(644, "circuit.wetware_processor").setUnificationData(OrePrefix.circuit, MarkerMaterials.Tier.Master); - WETWARE_PROCESSOR_ASSEMBLY_ZPM = addItem(645, "circuit.wetware_assembly").setUnificationData(OrePrefix.circuit, MarkerMaterials.Tier.Ultimate); - WETWARE_SUPER_COMPUTER_UV = addItem(646, "circuit.wetware_computer").setUnificationData(OrePrefix.circuit, MarkerMaterials.Tier.Superconductor); - WETWARE_MAINFRAME_UHV = addItem(647, "circuit.wetware_mainframe").setUnificationData(OrePrefix.circuit, MarkerMaterials.Tier.Infinite); + WETWARE_PROCESSOR_LUV = addItem(644, "circuit.wetware_processor").setUnificationData(OrePrefix.circuit, Tier.Master); + WETWARE_PROCESSOR_ASSEMBLY_ZPM = addItem(645, "circuit.wetware_assembly").setUnificationData(OrePrefix.circuit, Tier.Ultimate); + WETWARE_SUPER_COMPUTER_UV = addItem(646, "circuit.wetware_computer").setUnificationData(OrePrefix.circuit, Tier.Superconductor); + WETWARE_MAINFRAME_UHV = addItem(647, "circuit.wetware_mainframe").setUnificationData(OrePrefix.circuit, Tier.Infinite); // T8: Bioware @@ -517,34 +522,44 @@ public void registerSubItems() { BATTERY_HULL_LV = addItem(717, "battery.hull.lv").setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.BatteryAlloy, OrePrefix.plate.materialAmount))); BATTERY_HULL_MV = addItem(718, "battery.hull.mv").setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.BatteryAlloy, OrePrefix.plate.materialAmount * 3L))); BATTERY_HULL_HV = addItem(719, "battery.hull.hv").setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.BatteryAlloy, OrePrefix.plate.materialAmount * 9L))); + BATTERY_HULL_SMALL_VANADIUM = addItem(720, "battery.hull.ev").setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.BlueSteel, GTValues.M * 2))); + BATTERY_HULL_MEDIUM_VANADIUM = addItem(721, "battery.hull.iv").setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.RoseGold, GTValues.M * 6))); + BATTERY_HULL_LARGE_VANADIUM = addItem(722, "battery.hull.luv").setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.RedSteel, GTValues.M * 18))); + BATTERY_HULL_MEDIUM_NAQUADRIA = addItem(723, "battery.hull.zpm").setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Europium, GTValues.M * 6))); + BATTERY_HULL_LARGE_NAQUADRIA = addItem(724, "battery.hull.uv").setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Americium, GTValues.M * 18))); // Batteries: 731-775 - BATTERY_RE_ULV_TANTALUM = addItem(731, "battery.re.ulv.tantalum").addComponents(ElectricStats.createRechargeableBattery(1000, 0)); + BATTERY_ULV_TANTALUM = addItem(731, "battery.re.ulv.tantalum").addComponents(ElectricStats.createRechargeableBattery(1000, GTValues.ULV)).setUnificationData(OrePrefix.battery, Tier.Primitive); - BATTERY_RE_LV_SODIUM = addItem(732, "battery.re.lv.sodium").addComponents(ElectricStats.createRechargeableBattery(80000, 1)).setModelAmount(8); - BATTERY_RE_MV_SODIUM = addItem(733, "battery.re.mv.sodium").addComponents(ElectricStats.createRechargeableBattery(360000, 2)).setModelAmount(8); - BATTERY_RE_HV_SODIUM = addItem(734, "battery.re.hv.sodium").addComponents(ElectricStats.createRechargeableBattery(1200000, 3)).setModelAmount(8); + BATTERY_LV_SODIUM = addItem(732, "battery.re.lv.sodium").addComponents(ElectricStats.createRechargeableBattery(80000, GTValues.LV)).setUnificationData(OrePrefix.battery, Tier.Basic).setModelAmount(8); + BATTERY_MV_SODIUM = addItem(733, "battery.re.mv.sodium").addComponents(ElectricStats.createRechargeableBattery(360000, GTValues.MV)).setUnificationData(OrePrefix.battery, Tier.Good).setModelAmount(8); + BATTERY_HV_SODIUM = addItem(734, "battery.re.hv.sodium").addComponents(ElectricStats.createRechargeableBattery(1200000, GTValues.HV)).setUnificationData(OrePrefix.battery, Tier.Advanced).setModelAmount(8); - BATTERY_RE_LV_LITHIUM = addItem(735, "battery.re.lv.lithium").addComponents(ElectricStats.createRechargeableBattery(100000, 1)).setModelAmount(8); - BATTERY_RE_MV_LITHIUM = addItem(736, "battery.re.mv.lithium").addComponents(ElectricStats.createRechargeableBattery(400000, 2)).setModelAmount(8); - BATTERY_RE_HV_LITHIUM = addItem(737, "battery.re.hv.lithium").addComponents(ElectricStats.createRechargeableBattery(1600000, 3)).setModelAmount(8); + BATTERY_LV_LITHIUM = addItem(735, "battery.re.lv.lithium").addComponents(ElectricStats.createRechargeableBattery(100000, GTValues.LV)).setUnificationData(OrePrefix.battery, Tier.Basic).setModelAmount(8); + BATTERY_MV_LITHIUM = addItem(736, "battery.re.mv.lithium").addComponents(ElectricStats.createRechargeableBattery(400000, GTValues.MV)).setUnificationData(OrePrefix.battery, Tier.Good).setModelAmount(8); + BATTERY_HV_LITHIUM = addItem(737, "battery.re.hv.lithium").addComponents(ElectricStats.createRechargeableBattery(1600000, GTValues.HV)).setUnificationData(OrePrefix.battery, Tier.Advanced).setModelAmount(8); - BATTERY_RE_LV_CADMIUM = addItem(738, "battery.re.lv.cadmium").addComponents(ElectricStats.createRechargeableBattery(120000, 1)).setModelAmount(8); - BATTERY_RE_MV_CADMIUM = addItem(739, "battery.re.mv.cadmium").addComponents(ElectricStats.createRechargeableBattery(420000, 2)).setModelAmount(8); - BATTERY_RE_HV_CADMIUM = addItem(740, "battery.re.hv.cadmium").addComponents(ElectricStats.createRechargeableBattery(1800000, 3)).setModelAmount(8); + BATTERY_LV_CADMIUM = addItem(738, "battery.re.lv.cadmium").addComponents(ElectricStats.createRechargeableBattery(120000, GTValues.LV)).setUnificationData(OrePrefix.battery, Tier.Basic).setModelAmount(8); + BATTERY_MV_CADMIUM = addItem(739, "battery.re.mv.cadmium").addComponents(ElectricStats.createRechargeableBattery(420000, GTValues.MV)).setUnificationData(OrePrefix.battery, Tier.Good).setModelAmount(8); + BATTERY_HV_CADMIUM = addItem(740, "battery.re.hv.cadmium").addComponents(ElectricStats.createRechargeableBattery(1800000, GTValues.HV)).setUnificationData(OrePrefix.battery, Tier.Advanced).setModelAmount(8); - ENERGY_CRYSTAL = addItem(741, "energy_crystal").addComponents(ElectricStats.createRechargeableBattery(4000000L, GTValues.HV)).setModelAmount(8).setMaxStackSize(1); - LAPOTRON_CRYSTAL = addItem(742, "lapotron_crystal").addComponents(ElectricStats.createRechargeableBattery(10000000L, GTValues.EV)).setModelAmount(8).setMaxStackSize(1); + ENERGY_CRYSTAL = addItem(741, "energy_crystal").addComponents(ElectricStats.createRechargeableBattery(6400000L, GTValues.HV)).setUnificationData(OrePrefix.battery, Tier.Advanced).setModelAmount(8).setMaxStackSize(1); + LAPOTRON_CRYSTAL = addItem(742, "lapotron_crystal").addComponents(ElectricStats.createRechargeableBattery(16000000L, GTValues.EV)).setUnificationData(OrePrefix.battery, Tier.Extreme).setModelAmount(8).setMaxStackSize(1); - ENERGY_LAPOTRONIC_ORB = addItem(743, "energy.lapotronicorb").addComponents(ElectricStats.createRechargeableBattery(100000000, 5)).setUnificationData(OrePrefix.battery, MarkerMaterials.Tier.Ultimate).setModelAmount(8); - ENERGY_LAPOTRONIC_ORB2 = addItem(744, "energy.lapotronicorb2").addComponents(ElectricStats.createRechargeableBattery(1000000000, 6)).setUnificationData(OrePrefix.battery, MarkerMaterials.Tier.Ultimate).setModelAmount(8); + BATTERY_EV_VANADIUM = addItem(743, "battery.ev.vanadium").addComponents(ElectricStats.createRechargeableBattery(10240000L, GTValues.EV)).setUnificationData(OrePrefix.battery, Tier.Extreme).setModelAmount(8); + BATTERY_IV_VANADIUM = addItem(744, "battery.iv.vanadium").addComponents(ElectricStats.createRechargeableBattery(40960000L, GTValues.IV)).setUnificationData(OrePrefix.battery, Tier.Elite).setModelAmount(8); + BATTERY_LUV_VANADIUM = addItem(745, "battery.luv.vanadium").addComponents(ElectricStats.createRechargeableBattery(163840000L, GTValues.LuV)).setUnificationData(OrePrefix.battery, Tier.Master).setModelAmount(8); - if (ConfigHolder.U.GT5u.enableZPMandUVBats) { - ENERGY_LAPOTRONIC_MODULE = addItem(745, "energy.module").addComponents(new IItemComponent[]{ElectricStats.createRechargeableBattery(10000000000L, GTValues.ZPM)}).setModelAmount(8); - ENERGY_LAPOTRONIC_CLUSTER = addItem(746, "energy.cluster").addComponents(new IItemComponent[]{ElectricStats.createRechargeableBattery(100000000000L, GTValues.UV)}).setModelAmount(8); - } + BATTERY_ZPM_NAQUADRIA = addItem(746, "battery.zpm.naquadria").addComponents(ElectricStats.createRechargeableBattery(655360000L, GTValues.ZPM)).setUnificationData(OrePrefix.battery, Tier.Ultimate).setModelAmount(8); + BATTERY_UV_NAQUADRIA = addItem(747, "battery.uv.naquadria").addComponents(ElectricStats.createRechargeableBattery(2621440000L, GTValues.UV)).setUnificationData(OrePrefix.battery, Tier.Superconductor).setModelAmount(8); + + ENERGY_LAPOTRONIC_ORB = addItem(748, "energy.lapotronicorb").addComponents(ElectricStats.createRechargeableBattery(100000000L, GTValues.IV)).setUnificationData(OrePrefix.battery, Tier.Elite).setModelAmount(8); + ENERGY_LAPOTRONIC_ORB2 = addItem(749, "energy.lapotronicorb2").addComponents(ElectricStats.createRechargeableBattery(1000000000L, GTValues.LuV)).setUnificationData(OrePrefix.battery, Tier.Master).setModelAmount(8); + + ENERGY_LAPOTRONIC_MODULE = addItem(750, "energy.module").addComponents(new IItemComponent[]{ElectricStats.createRechargeableBattery(10000000000L, GTValues.ZPM)}).setUnificationData(OrePrefix.battery, Tier.Ultimate).setModelAmount(8); + ENERGY_LAPOTRONIC_CLUSTER = addItem(751, "energy.cluster").addComponents(new IItemComponent[]{ElectricStats.createRechargeableBattery(100000000000L, GTValues.UV)}).setUnificationData(OrePrefix.battery, Tier.Superconductor).setModelAmount(8); - ZERO_POINT_MODULE = addItem(747, "zpm").addComponents(ElectricStats.createBattery(2000000000000L, GTValues.ZPM, false)).setModelAmount(8); - ULTIMATE_BATTERY = addItem(748, "max.battery").addComponents(ElectricStats.createRechargeableBattery(Long.MAX_VALUE, ConfigHolder.U.GT5u.replaceUVwithMAXBat ? GTValues.MAX : GTValues.UV)).setModelAmount(8); + ZERO_POINT_MODULE = addItem(752, "zpm").addComponents(ElectricStats.createBattery(2000000000000L, GTValues.ZPM, false)).setModelAmount(8); + ULTIMATE_BATTERY = addItem(753, "max.battery").addComponents(ElectricStats.createRechargeableBattery(Long.MAX_VALUE, GTValues.MAX)).setUnificationData(OrePrefix.battery, Tier.Maximum).setModelAmount(8); } } diff --git a/src/main/java/gregtech/common/items/MetaItems.java b/src/main/java/gregtech/common/items/MetaItems.java index 76a7b336f6b..ff4ce16f24e 100644 --- a/src/main/java/gregtech/common/items/MetaItems.java +++ b/src/main/java/gregtech/common/items/MetaItems.java @@ -4,6 +4,7 @@ import gregtech.api.items.materialitem.MetaPrefixItem; import gregtech.api.items.metaitem.MetaItem; import gregtech.api.items.metaitem.MetaItem.MetaValueItem; +import gregtech.api.items.metaitem.MetaOreDictItem; import gregtech.api.items.toolitem.ToolMetaItem; import gregtech.api.unification.ore.OrePrefix; import gregtech.api.util.GTLog; @@ -19,6 +20,7 @@ import net.minecraftforge.fml.relauncher.SideOnly; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; public final class MetaItems { @@ -128,20 +130,31 @@ private MetaItems() { public static MetaItem.MetaValueItem BATTERY_HULL_LV; public static MetaItem.MetaValueItem BATTERY_HULL_MV; public static MetaItem.MetaValueItem BATTERY_HULL_HV; - - public static MetaItem.MetaValueItem BATTERY_RE_ULV_TANTALUM; - public static MetaItem.MetaValueItem BATTERY_RE_LV_CADMIUM; - public static MetaItem.MetaValueItem BATTERY_RE_LV_LITHIUM; - public static MetaItem.MetaValueItem BATTERY_RE_LV_SODIUM; - public static MetaItem.MetaValueItem BATTERY_RE_MV_CADMIUM; - public static MetaItem.MetaValueItem BATTERY_RE_MV_LITHIUM; - public static MetaItem.MetaValueItem BATTERY_RE_MV_SODIUM; - public static MetaItem.MetaValueItem BATTERY_RE_HV_CADMIUM; - public static MetaItem.MetaValueItem BATTERY_RE_HV_LITHIUM; - public static MetaItem.MetaValueItem BATTERY_RE_HV_SODIUM; + public static MetaItem.MetaValueItem BATTERY_HULL_SMALL_VANADIUM; + public static MetaItem.MetaValueItem BATTERY_HULL_MEDIUM_VANADIUM; + public static MetaItem.MetaValueItem BATTERY_HULL_LARGE_VANADIUM; + public static MetaItem.MetaValueItem BATTERY_HULL_MEDIUM_NAQUADRIA; + public static MetaItem.MetaValueItem BATTERY_HULL_LARGE_NAQUADRIA; + + public static MetaItem.MetaValueItem BATTERY_ULV_TANTALUM; + public static MetaItem.MetaValueItem BATTERY_LV_CADMIUM; + public static MetaItem.MetaValueItem BATTERY_LV_LITHIUM; + public static MetaItem.MetaValueItem BATTERY_LV_SODIUM; + public static MetaItem.MetaValueItem BATTERY_MV_CADMIUM; + public static MetaItem.MetaValueItem BATTERY_MV_LITHIUM; + public static MetaItem.MetaValueItem BATTERY_MV_SODIUM; + public static MetaItem.MetaValueItem BATTERY_HV_CADMIUM; + public static MetaItem.MetaValueItem BATTERY_HV_LITHIUM; + public static MetaItem.MetaValueItem BATTERY_HV_SODIUM; public static MetaItem.MetaValueItem ENERGY_CRYSTAL; public static MetaItem.MetaValueItem LAPOTRON_CRYSTAL; + public static MetaItem.MetaValueItem BATTERY_EV_VANADIUM; + public static MetaItem.MetaValueItem BATTERY_IV_VANADIUM; + public static MetaItem.MetaValueItem BATTERY_LUV_VANADIUM; + public static MetaItem.MetaValueItem BATTERY_ZPM_NAQUADRIA; + public static MetaItem.MetaValueItem BATTERY_UV_NAQUADRIA; + public static MetaItem.MetaValueItem ENERGY_LAPOTRONIC_ORB; public static MetaItem.MetaValueItem ENERGY_LAPOTRONIC_ORB2; public static MetaItem.MetaValueItem ZERO_POINT_MODULE; @@ -387,6 +400,7 @@ private MetaItems() { public static MetaItem.MetaValueItem COVER_SCREEN; public static MetaItem.MetaValueItem COVER_CRAFTING; public static MetaItem.MetaValueItem COVER_DRAIN; + public static MetaItem.MetaValueItem COVER_INFINITE_WATER; public static MetaItem.MetaValueItem COVER_SOLAR_PANEL; public static MetaItem.MetaValueItem COVER_SOLAR_PANEL_ULV; @@ -412,8 +426,8 @@ private MetaItems() { public static MetaItem.MetaValueItem POWER_UNIT_IV; public static MetaItem.MetaValueItem NANO_SABER; - public static MetaItem.MetaValueItem ENERGY_FIELD_PROJECTOR; public static MetaItem.MetaValueItem SCANNER; + public static MetaItem.MetaValueItem TERMINAL; public static final MetaItem.MetaValueItem[] DYE_ONLY_ITEMS = new MetaItem.MetaValueItem[EnumDyeColor.values().length]; public static final MetaItem.MetaValueItem[] SPRAY_CAN_DYES = new MetaItem.MetaValueItem[EnumDyeColor.values().length]; @@ -511,7 +525,6 @@ private MetaItems() { add(OrePrefix.wireFine); add(OrePrefix.rotor); add(OrePrefix.lens); - add(OrePrefix.oreChunk); add(OrePrefix.turbineBlade); add(OrePrefix.toolHeadSword); add(OrePrefix.toolHeadPickaxe); @@ -534,6 +547,8 @@ public static void init() { first.setRegistryName("meta_item_1"); MetaTool tool = new MetaTool(); tool.setRegistryName("meta_tool"); + MetaOreDictItem oreDictItem = new MetaOreDictItem((short) 0); + oreDictItem.setRegistryName("meta_oredict_item"); for (OrePrefix prefix : orePrefixes) { String regName = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, prefix.name()); MetaPrefixItem metaOrePrefix = new MetaPrefixItem(prefix); @@ -588,7 +603,8 @@ private static void registerSpecialItemModel(ModelBakeEvent event, MetaValueItem event.getModelRegistry().putObject(modelResourceLocation, bakedModel); } - private static void addOrePrefix(OrePrefix orePrefix) { - orePrefixes.add(orePrefix); + @SuppressWarnings("unused") + public static void addOrePrefix(OrePrefix... prefixes) { + orePrefixes.addAll(Arrays.asList(prefixes)); } } diff --git a/src/main/java/gregtech/common/items/behaviors/AbstractMaterialPartBehavior.java b/src/main/java/gregtech/common/items/behaviors/AbstractMaterialPartBehavior.java index 6195604b786..1ae9b244090 100644 --- a/src/main/java/gregtech/common/items/behaviors/AbstractMaterialPartBehavior.java +++ b/src/main/java/gregtech/common/items/behaviors/AbstractMaterialPartBehavior.java @@ -8,13 +8,12 @@ import gregtech.api.unification.material.MaterialRegistry; import gregtech.api.unification.material.Materials; import gregtech.api.unification.material.properties.PropertyKey; +import gregtech.api.util.LocalizationUtils; import net.minecraft.client.resources.I18n; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.math.MathHelper; import net.minecraftforge.common.util.Constants.NBT; -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; import java.util.List; @@ -65,10 +64,9 @@ public void setPartDamage(ItemStack itemStack, int rotorDamage) { } @Override - @SideOnly(Side.CLIENT) public String getItemStackDisplayName(ItemStack itemStack, String unlocalizedName) { Material material = getPartMaterial(itemStack); - return I18n.format(unlocalizedName, material.getLocalizedName()); + return LocalizationUtils.format(unlocalizedName, material.getLocalizedName()); } @Override diff --git a/src/main/java/gregtech/common/items/behaviors/FacadeItem.java b/src/main/java/gregtech/common/items/behaviors/FacadeItem.java index d215473d050..46f7f0b6174 100644 --- a/src/main/java/gregtech/common/items/behaviors/FacadeItem.java +++ b/src/main/java/gregtech/common/items/behaviors/FacadeItem.java @@ -3,9 +3,9 @@ import com.google.common.collect.ImmutableList; import gregtech.api.items.metaitem.stats.IItemNameProvider; import gregtech.api.items.metaitem.stats.ISubItemHandler; +import gregtech.api.util.LocalizationUtils; import gregtech.common.ConfigHolder; import gregtech.common.covers.facade.FacadeHelper; -import net.minecraft.client.resources.I18n; import net.minecraft.creativetab.CreativeTabs; import net.minecraft.init.Blocks; import net.minecraft.init.Items; @@ -24,7 +24,7 @@ public class FacadeItem implements IItemNameProvider, ISubItemHandler { public String getItemStackDisplayName(ItemStack itemStack, String unlocalizedName) { ItemStack facadeStack = getFacadeStack(itemStack); String name = facadeStack.getItem().getItemStackDisplayName(facadeStack); - return I18n.format(unlocalizedName, name); + return LocalizationUtils.format(unlocalizedName, name); } @Override diff --git a/src/main/java/gregtech/common/items/behaviors/NanoSaberBehavior.java b/src/main/java/gregtech/common/items/behaviors/NanoSaberBehavior.java index 3a63f5022ab..7f1b4921cf0 100644 --- a/src/main/java/gregtech/common/items/behaviors/NanoSaberBehavior.java +++ b/src/main/java/gregtech/common/items/behaviors/NanoSaberBehavior.java @@ -5,8 +5,6 @@ import gregtech.api.GTValues; import gregtech.api.items.metaitem.MetaItem.MetaValueItem; import gregtech.api.items.metaitem.stats.IEnchantabilityHelper; -import gregtech.api.items.toolitem.ToolMetaItem; -import gregtech.api.unification.material.Materials; import gregtech.common.ConfigHolder; import net.minecraft.enchantment.Enchantment; import net.minecraft.entity.SharedMonsterAttributes; @@ -57,7 +55,7 @@ public boolean isEnchantable(ItemStack stack) { @Override public int getItemEnchantability(ItemStack stack) { - return ToolMetaItem.getMaterialEnchantability(Materials.Platinum); + return 33; } @Override diff --git a/src/main/java/gregtech/common/items/behaviors/TerminalBehaviour.java b/src/main/java/gregtech/common/items/behaviors/TerminalBehaviour.java new file mode 100644 index 00000000000..255cf5a9b34 --- /dev/null +++ b/src/main/java/gregtech/common/items/behaviors/TerminalBehaviour.java @@ -0,0 +1,54 @@ +package gregtech.common.items.behaviors; + +import gregtech.api.gui.ModularUI; +import gregtech.api.gui.resources.EmptyTextureArea; +import gregtech.api.gui.resources.TextureArea; +import gregtech.api.gui.widgets.ImageWidget; +import gregtech.api.items.gui.ItemUIFactory; +import gregtech.api.items.gui.PlayerInventoryHolder; +import gregtech.api.items.metaitem.stats.IItemBehaviour; +import gregtech.api.terminal.gui.widgets.CircleButtonWidget; +import gregtech.api.terminal.os.TerminalOSWidget; +import gregtech.api.terminal.os.TerminalTheme; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ActionResult; +import net.minecraft.util.EnumActionResult; +import net.minecraft.util.EnumHand; +import net.minecraft.world.World; + +import java.awt.*; +import java.util.List; + +public class TerminalBehaviour implements IItemBehaviour, ItemUIFactory { + private static final TextureArea TERMINAL_FRAME = TextureArea.fullImage("textures/gui/terminal/terminal_frame.png"); + + + @Override + public ActionResult onItemRightClick(World world, EntityPlayer player, EnumHand hand) { + ItemStack itemStack = player.getHeldItem(hand); + if (!world.isRemote) { + PlayerInventoryHolder holder = new PlayerInventoryHolder(player, hand); + holder.openUI(); + } + return ActionResult.newResult(EnumActionResult.SUCCESS, itemStack); + } + + @Override + public void addInformation(ItemStack itemStack, List lines) { + } + + @Override + public ModularUI createUI(PlayerInventoryHolder holder, EntityPlayer entityPlayer) { + TerminalOSWidget os = new TerminalOSWidget(12, 11, 333, 232, holder.getCurrentItem().getOrCreateSubCompound("terminal")) + .setBackground(TerminalTheme.WALL_PAPER); + CircleButtonWidget home = new CircleButtonWidget(363, 126, 11, 2, 0) + .setColors(0, TerminalTheme.COLOR_F_1.getColor(), 0) + .setClickListener(clickData -> os.homeTrigger(clickData.isClient)); + return ModularUI.builder(new EmptyTextureArea(380, 256), 380, 256) + .widget(os) + .widget(new ImageWidget(0, 0, 380, 256, TERMINAL_FRAME)) + .widget(home) + .build(holder, entityPlayer); + } +} diff --git a/src/main/java/gregtech/common/metatileentities/MetaTileEntities.java b/src/main/java/gregtech/common/metatileentities/MetaTileEntities.java index 0c2dfbcebd3..caccd28be27 100644 --- a/src/main/java/gregtech/common/metatileentities/MetaTileEntities.java +++ b/src/main/java/gregtech/common/metatileentities/MetaTileEntities.java @@ -10,12 +10,8 @@ import gregtech.api.render.Textures; import gregtech.api.unification.material.Materials; import gregtech.api.util.GTLog; -import gregtech.common.ConfigHolder; import gregtech.common.metatileentities.electric.*; -import gregtech.common.metatileentities.electric.multiblockpart.MetaTileEntityEnergyHatch; -import gregtech.common.metatileentities.electric.multiblockpart.MetaTileEntityFluidHatch; -import gregtech.common.metatileentities.electric.multiblockpart.MetaTileEntityItemBus; -import gregtech.common.metatileentities.electric.multiblockpart.MetaTileEntityRotorHolder; +import gregtech.common.metatileentities.electric.multiblockpart.*; import gregtech.common.metatileentities.multi.*; import gregtech.common.metatileentities.multi.MetaTileEntityLargeBoiler.BoilerType; import gregtech.common.metatileentities.multi.electric.*; @@ -33,11 +29,17 @@ import gregtech.common.metatileentities.storage.*; import net.minecraft.util.ResourceLocation; +import java.util.HashMap; +import java.util.Map; +import java.util.function.Function; + public class MetaTileEntities { //HULLS public static final MetaTileEntityHull[] HULL = new MetaTileEntityHull[GTValues.V.length]; public static final MetaTileEntityTransformer[] TRANSFORMER = new MetaTileEntityTransformer[GTValues.V.length - 1]; // no ULV, no MAX + public static final MetaTileEntityAdjustableTransformer[] ADJUSTABLE_TRANSFORMER = new MetaTileEntityAdjustableTransformer[GTValues.V.length - 1]; // no ULV, no MAX + public static final MetaTileEntityDiode[] DIODES = new MetaTileEntityDiode[GTValues.V.length]; public static final MetaTileEntityBatteryBuffer[][] BATTERY_BUFFER = new MetaTileEntityBatteryBuffer[GTValues.V.length][]; public static final MetaTileEntityCharger[] CHARGER = new MetaTileEntityCharger[GTValues.V.length]; @@ -45,6 +47,7 @@ public class MetaTileEntities { public static SteamCoalBoiler STEAM_BOILER_COAL_BRONZE; public static SteamCoalBoiler STEAM_BOILER_COAL_STEEL; public static SteamSolarBoiler STEAM_BOILER_SOLAR_BRONZE; + public static SteamSolarBoiler STEAM_BOILER_SOLAR_STEEL; public static SteamLavaBoiler STEAM_BOILER_LAVA_BRONZE; public static SteamLavaBoiler STEAM_BOILER_LAVA_STEEL; public static SteamExtractor STEAM_EXTRACTOR_BRONZE; @@ -98,10 +101,12 @@ public class MetaTileEntities { public static final SimpleMachineMetaTileEntity[] SIFTER = new SimpleMachineMetaTileEntity[GTValues.V.length - 1]; public static final SimpleMachineMetaTileEntity[] THERMAL_CENTRIFUGE = new SimpleMachineMetaTileEntity[GTValues.V.length - 1]; public static final SimpleMachineMetaTileEntity[] WIREMILL = new SimpleMachineMetaTileEntity[GTValues.V.length - 1]; - public static final SimpleMachineMetaTileEntity[] CIRCUIT_ASSEMBLER = new SimpleMachineMetaTileEntity[GTValues.UV]; + public static final SimpleMachineMetaTileEntity[] CIRCUIT_ASSEMBLER = new SimpleMachineMetaTileEntity[GTValues.V.length - 1]; public static final SimpleMachineMetaTileEntity[] MASS_FABRICATOR = new SimpleMachineMetaTileEntity[GTValues.V.length - 1]; public static final SimpleMachineMetaTileEntity[] REPLICATOR = new SimpleMachineMetaTileEntity[GTValues.V.length - 1]; public static final SimpleMachineMetaTileEntity[] SCANNER = new SimpleMachineMetaTileEntity[GTValues.V.length - 1]; + public static final SimpleMachineMetaTileEntity[] GAS_COLLECTOR = new SimpleMachineMetaTileEntity[GTValues.V.length - 1]; + public static MetaTileEntitySimpleOreWasher SIMPLE_ORE_WASHER; //GENERATORS SECTION public static final SimpleGeneratorMetaTileEntity[] COMBUSTION_GENERATOR = new SimpleGeneratorMetaTileEntity[4]; @@ -115,12 +120,14 @@ public class MetaTileEntities { public static final MetaTileEntityFluidHatch[] FLUID_IMPORT_HATCH = new MetaTileEntityFluidHatch[GTValues.UHV + 1]; public static final MetaTileEntityFluidHatch[] FLUID_EXPORT_HATCH = new MetaTileEntityFluidHatch[GTValues.UHV + 1]; public static final MetaTileEntityEnergyHatch[] ENERGY_INPUT_HATCH = new MetaTileEntityEnergyHatch[GTValues.V.length]; + public static final MetaTileEntityAdjustableEnergyHatch[] ENERGY_INPUT_HATCH_ADJUSTABLE = new MetaTileEntityAdjustableEnergyHatch[GTValues.V.length]; public static final MetaTileEntityEnergyHatch[] ENERGY_OUTPUT_HATCH = new MetaTileEntityEnergyHatch[GTValues.V.length]; - public static final MetaTileEntityRotorHolder[] ROTOR_HOLDER = new MetaTileEntityRotorHolder[3]; //HV, LuV, MAX + public static final MetaTileEntityAdjustableEnergyHatch[] ENERGY_OUTPUT_HATCH_ADJUSTABLE = new MetaTileEntityAdjustableEnergyHatch[GTValues.V.length]; public static MetaTileEntityCokeOvenHatch COKE_OVEN_HATCH; public static MetaTileEntitySteamItemBus STEAM_EXPORT_BUS; public static MetaTileEntitySteamItemBus STEAM_IMPORT_BUS; public static MetaTileEntitySteamHatch STEAM_HATCH; + public static final MetaTileEntityRotorHolder[] ROTOR_HOLDER = new MetaTileEntityRotorHolder[3]; //HV, LuV, MAX //MULTIBLOCKS SECTION public static MetaTileEntityPrimitiveBlastFurnace PRIMITIVE_BLAST_FURNACE; @@ -180,16 +187,16 @@ public class MetaTileEntities { public static final MetaTileEntityQuantumChest[] QUANTUM_CHEST = new MetaTileEntityQuantumChest[10]; public static final MetaTileEntityQuantumTank[] QUANTUM_TANK = new MetaTileEntityQuantumTank[10]; + public static final MetaTileEntityBuffer[] BUFFER = new MetaTileEntityBuffer[3]; //MISC MACHINES SECTION public static MetaTileEntityWorkbench WORKBENCH; public static final MetaTileEntityPump[] PUMP = new MetaTileEntityPump[8]; public static final MetaTileEntityBlockBreaker[] BLOCK_BREAKER = new MetaTileEntityBlockBreaker[4]; - public static final MetaTileEntityAirCollector[] AIR_COLLECTOR = new MetaTileEntityAirCollector[6]; public static final MetaTileEntityItemCollector[] ITEM_COLLECTOR = new MetaTileEntityItemCollector[4]; public static final MetaTileEntityFisher[] FISHER = new MetaTileEntityFisher[4]; - public static MetaTileEntityInfiniteEmitter INFINITE_EMITTER; + public static MetaTileEntityCreativeEnergy CREATIVE_ENERGY; public static MetaTileEntityClipboard CLIPBOARD_TILE; @@ -200,6 +207,7 @@ public static void init() { STEAM_BOILER_COAL_STEEL = GregTechAPI.registerMetaTileEntity(2, new SteamCoalBoiler(gregtechId("steam_boiler_coal_steel"), true)); STEAM_BOILER_SOLAR_BRONZE = GregTechAPI.registerMetaTileEntity(3, new SteamSolarBoiler(gregtechId("steam_boiler_solar_bronze"), false)); + STEAM_BOILER_SOLAR_STEEL = GregTechAPI.registerMetaTileEntity(4, new SteamSolarBoiler(gregtechId("steam_boiler_solar_steel"), true)); STEAM_BOILER_LAVA_BRONZE = GregTechAPI.registerMetaTileEntity(5, new SteamLavaBoiler(gregtechId("steam_boiler_lava_bronze"), false)); STEAM_BOILER_LAVA_STEEL = GregTechAPI.registerMetaTileEntity(6, new SteamLavaBoiler(gregtechId("steam_boiler_lava_steel"), true)); @@ -223,8 +231,7 @@ public static void init() { STEAM_ALLOY_SMELTER_STEEL = GregTechAPI.registerMetaTileEntity(18, new SteamAlloySmelter(gregtechId("steam_alloy_smelter_steel"), true)); // Electric Furnace, IDs 50-64 - registerSimpleMetaTileEntity(ELECTRIC_FURNACE, 50, "electric_furnace", RecipeMaps.FURNACE_RECIPES, Textures.ELECTRIC_FURNACE_OVERLAY, - ConfigHolder.U.machines.midTierElectricFurnace, ConfigHolder.U.machines.highTierElectricFurnace); + registerSimpleMetaTileEntity(ELECTRIC_FURNACE, 50, "electric_furnace", RecipeMaps.FURNACE_RECIPES, Textures.ELECTRIC_FURNACE_OVERLAY); // Macerator, IDs 65-79 MACERATOR[0] = GregTechAPI.registerMetaTileEntity(65, new MetaTileEntityMacerator(gregtechId("macerator.lv"), RecipeMaps.MACERATOR_RECIPES, 1, Textures.MACERATOR_OVERLAY, 1)); @@ -232,12 +239,12 @@ public static void init() { MACERATOR[2] = GregTechAPI.registerMetaTileEntity(67, new MetaTileEntityMacerator(gregtechId("macerator.hv"), RecipeMaps.MACERATOR_RECIPES, 3, Textures.MACERATOR_OVERLAY, 3)); MACERATOR[3] = GregTechAPI.registerMetaTileEntity(68, new MetaTileEntityMacerator(gregtechId("macerator.ev"), RecipeMaps.MACERATOR_RECIPES, 3, Textures.MACERATOR_OVERLAY, 4)); MACERATOR[4] = GregTechAPI.registerMetaTileEntity(69, new MetaTileEntityMacerator(gregtechId("macerator.iv"), RecipeMaps.MACERATOR_RECIPES, 3, Textures.MACERATOR_OVERLAY, 5)); - if (ConfigHolder.U.machines.midTierMachines || ConfigHolder.U.machines.midTierMacerators) { + if (getMidTier("macerator")) { MACERATOR[5] = GregTechAPI.registerMetaTileEntity(70, new MetaTileEntityMacerator(gregtechId("macerator.luv"), RecipeMaps.MACERATOR_RECIPES, 3, Textures.MACERATOR_OVERLAY, 6)); MACERATOR[6] = GregTechAPI.registerMetaTileEntity(71, new MetaTileEntityMacerator(gregtechId("macerator.zpm"), RecipeMaps.MACERATOR_RECIPES, 3, Textures.MACERATOR_OVERLAY, 7)); MACERATOR[7] = GregTechAPI.registerMetaTileEntity(72, new MetaTileEntityMacerator(gregtechId("macerator.uv"), RecipeMaps.MACERATOR_RECIPES, 3, Textures.MACERATOR_OVERLAY, 8)); } - if (ConfigHolder.U.machines.highTierMachines || ConfigHolder.U.machines.highTierMacerators) { + if (getHighTier("macerator")) { MACERATOR[8] = GregTechAPI.registerMetaTileEntity(73, new MetaTileEntityMacerator(gregtechId("macerator.uhv"), RecipeMaps.MACERATOR_RECIPES, 3, Textures.MACERATOR_OVERLAY, 9)); MACERATOR[9] = GregTechAPI.registerMetaTileEntity(74, new MetaTileEntityMacerator(gregtechId("macerator.uev"), RecipeMaps.MACERATOR_RECIPES, 3, Textures.MACERATOR_OVERLAY, 10)); MACERATOR[10] = GregTechAPI.registerMetaTileEntity(75, new MetaTileEntityMacerator(gregtechId("macerator.uiv"), RecipeMaps.MACERATOR_RECIPES, 3, Textures.MACERATOR_OVERLAY, 11)); @@ -246,155 +253,117 @@ public static void init() { } // Alloy Smelter, IDs 80-94 - registerSimpleMetaTileEntity(ALLOY_SMELTER, 80, "alloy_smelter", RecipeMaps.ALLOY_SMELTER_RECIPES, Textures.ALLOY_SMELTER_OVERLAY, - ConfigHolder.U.machines.midTierAlloySmelter, ConfigHolder.U.machines.highTierAlloySmelter); + registerSimpleMetaTileEntity(ALLOY_SMELTER, 80, "alloy_smelter", RecipeMaps.ALLOY_SMELTER_RECIPES, Textures.ALLOY_SMELTER_OVERLAY); // Free Range, IDs 95-109 - // Can add higher tier machines if desired, space is left for it // Arc Furnace, IDs 110-124 - registerSimpleMetaTileEntity(ARC_FURNACE, 110, "arc_furnace", RecipeMaps.ARC_FURNACE_RECIPES, Textures.ARC_FURNACE_OVERLAY, - ConfigHolder.U.machines.midTierArcFurnaces, ConfigHolder.U.machines.highTierArcFurnaces, false, false); + registerSimpleMetaTileEntity(ARC_FURNACE, 110, "arc_furnace", RecipeMaps.ARC_FURNACE_RECIPES, Textures.ARC_FURNACE_OVERLAY, false); // Assembler, IDs 125-139 - registerSimpleMetaTileEntity(ASSEMBLER, 125, "assembler", RecipeMaps.ASSEMBLER_RECIPES, Textures.ASSEMBLER_OVERLAY, - ConfigHolder.U.machines.midTierAssemblers, ConfigHolder.U.machines.highTierAssemblers); + registerSimpleMetaTileEntity(ASSEMBLER, 125, "assembler", RecipeMaps.ASSEMBLER_RECIPES, Textures.ASSEMBLER_OVERLAY); // Autoclave, IDs 140-154 - registerSimpleMetaTileEntity(AUTOCLAVE, 140, "autoclave", RecipeMaps.AUTOCLAVE_RECIPES, Textures.AUTOCLAVE_OVERLAY, - ConfigHolder.U.machines.midTierAutoclaves, ConfigHolder.U.machines.highTierAutoclaves, false, false); + registerSimpleMetaTileEntity(AUTOCLAVE, 140, "autoclave", RecipeMaps.AUTOCLAVE_RECIPES, Textures.AUTOCLAVE_OVERLAY, false); // Bender, IDs 155-169 - registerSimpleMetaTileEntity(BENDER, 155, "bender", RecipeMaps.BENDER_RECIPES, Textures.BENDER_OVERLAY, - ConfigHolder.U.machines.midTierBenders, ConfigHolder.U.machines.highTierBenders); + registerSimpleMetaTileEntity(BENDER, 155, "bender", RecipeMaps.BENDER_RECIPES, Textures.BENDER_OVERLAY); // Brewery, IDs 170-184 - registerSimpleMetaTileEntity(BREWERY, 170, "brewery", RecipeMaps.BREWING_RECIPES, Textures.BREWERY_OVERLAY, - ConfigHolder.U.machines.midTierBreweries, ConfigHolder.U.machines.highTierBreweries); + registerSimpleMetaTileEntity(BREWERY, 170, "brewery", RecipeMaps.BREWING_RECIPES, Textures.BREWERY_OVERLAY); // Canner, IDs 185-199 - registerSimpleMetaTileEntity(CANNER, 185, "canner", RecipeMaps.CANNER_RECIPES, Textures.CANNER_OVERLAY, - ConfigHolder.U.machines.midTierCanners, ConfigHolder.U.machines.highTierCanners); + registerSimpleMetaTileEntity(CANNER, 185, "canner", RecipeMaps.CANNER_RECIPES, Textures.CANNER_OVERLAY); // Centrifuge, IDs 200-214 - registerSimpleMetaTileEntity(CENTRIFUGE, 200, "centrifuge", RecipeMaps.CENTRIFUGE_RECIPES, Textures.CENTRIFUGE_OVERLAY, - ConfigHolder.U.machines.midTierCentrifuges, ConfigHolder.U.machines.highTierCentrifuges, false, false); + registerSimpleMetaTileEntity(CENTRIFUGE, 200, "centrifuge", RecipeMaps.CENTRIFUGE_RECIPES, Textures.CENTRIFUGE_OVERLAY, false); // Chemical Bath, IDs 215-229 - registerSimpleMetaTileEntity(CHEMICAL_BATH, 215, "chemical_bath", RecipeMaps.CHEMICAL_BATH_RECIPES, Textures.CHEMICAL_BATH_OVERLAY, - ConfigHolder.U.machines.midTierChemicalBaths, ConfigHolder.U.machines.highTierChemicalBaths); + registerSimpleMetaTileEntity(CHEMICAL_BATH, 215, "chemical_bath", RecipeMaps.CHEMICAL_BATH_RECIPES, Textures.CHEMICAL_BATH_OVERLAY); // Chemical Reactor, IDs 230-244 - registerSimpleMetaTileEntity(CHEMICAL_REACTOR, 230, "chemical_reactor", RecipeMaps.CHEMICAL_RECIPES, Textures.CHEMICAL_REACTOR_OVERLAY, - ConfigHolder.U.machines.midTierChemicalReactors, ConfigHolder.U.machines.highTierChemicalReactors); + registerSimpleMetaTileEntity(CHEMICAL_REACTOR, 230, "chemical_reactor", RecipeMaps.CHEMICAL_RECIPES, Textures.CHEMICAL_REACTOR_OVERLAY); // Compressor, IDs 245-259 - registerSimpleMetaTileEntity(COMPRESSOR, 245, "compressor", RecipeMaps.COMPRESSOR_RECIPES, Textures.COMPRESSOR_OVERLAY, - ConfigHolder.U.machines.midTierCompressors, ConfigHolder.U.machines.highTierCompressors); + registerSimpleMetaTileEntity(COMPRESSOR, 245, "compressor", RecipeMaps.COMPRESSOR_RECIPES, Textures.COMPRESSOR_OVERLAY); // Cutter, IDs 260-274 - registerSimpleMetaTileEntity(CUTTER, 260, "cutter", RecipeMaps.CUTTER_RECIPES, Textures.CUTTER_OVERLAY, - ConfigHolder.U.machines.midTierCutters, ConfigHolder.U.machines.highTierCutters); + registerSimpleMetaTileEntity(CUTTER, 260, "cutter", RecipeMaps.CUTTER_RECIPES, Textures.CUTTER_OVERLAY); // Distillery, IDs 275-289 - registerSimpleMetaTileEntity(DISTILLERY, 275, "distillery", RecipeMaps.DISTILLERY_RECIPES, Textures.DISTILLERY_OVERLAY, - ConfigHolder.U.machines.midTierDistilleries, ConfigHolder.U.machines.highTierDistilleries); + registerSimpleMetaTileEntity(DISTILLERY, 275, "distillery", RecipeMaps.DISTILLERY_RECIPES, Textures.DISTILLERY_OVERLAY); // Electrolyzer, IDs 290-304 - registerSimpleMetaTileEntity(ELECTROLYZER, 290, "electrolyzer", RecipeMaps.ELECTROLYZER_RECIPES, Textures.ELECTROLYZER_OVERLAY, - ConfigHolder.U.machines.midTierElectrolyzers, ConfigHolder.U.machines.highTierElectrolyzers, false, false); + registerSimpleMetaTileEntity(ELECTROLYZER, 290, "electrolyzer", RecipeMaps.ELECTROLYZER_RECIPES, Textures.ELECTROLYZER_OVERLAY, false); // Electromagnetic Separator, IDs 305-319 - registerSimpleMetaTileEntity(ELECTROMAGNETIC_SEPARATOR, 305, "electromagnetic_separator", RecipeMaps.ELECTROMAGNETIC_SEPARATOR_RECIPES, Textures.ELECTROMAGNETIC_SEPARATOR_OVERLAY, - ConfigHolder.U.machines.midTierElectromagneticSeparators, ConfigHolder.U.machines.highTierElectromagneticSeparators); + registerSimpleMetaTileEntity(ELECTROMAGNETIC_SEPARATOR, 305, "electromagnetic_separator", RecipeMaps.ELECTROMAGNETIC_SEPARATOR_RECIPES, Textures.ELECTROMAGNETIC_SEPARATOR_OVERLAY); // Extractor, IDs 320-334 - registerSimpleMetaTileEntity(EXTRACTOR, 320, "extractor", RecipeMaps.EXTRACTOR_RECIPES, Textures.EXTRACTOR_OVERLAY, - ConfigHolder.U.machines.midTierExtractors, ConfigHolder.U.machines.highTierExtractors); + registerSimpleMetaTileEntity(EXTRACTOR, 320, "extractor", RecipeMaps.EXTRACTOR_RECIPES, Textures.EXTRACTOR_OVERLAY); // Extruder, IDs 335-349 - registerSimpleMetaTileEntity(EXTRUDER, 335, "extruder", RecipeMaps.EXTRUDER_RECIPES, Textures.EXTRUDER_OVERLAY, - ConfigHolder.U.machines.midTierExtruders, ConfigHolder.U.machines.highTierExtruders); + registerSimpleMetaTileEntity(EXTRUDER, 335, "extruder", RecipeMaps.EXTRUDER_RECIPES, Textures.EXTRUDER_OVERLAY); // Fermenter, IDs 350-364 - registerSimpleMetaTileEntity(FERMENTER, 350, "fermenter", RecipeMaps.FERMENTING_RECIPES, Textures.FERMENTER_OVERLAY, - ConfigHolder.U.machines.midTierFermenters, ConfigHolder.U.machines.highTierFermenters); + registerSimpleMetaTileEntity(FERMENTER, 350, "fermenter", RecipeMaps.FERMENTING_RECIPES, Textures.FERMENTER_OVERLAY); // Mass Fabricator, IDs 365-379 - registerSimpleMetaTileEntity(MASS_FABRICATOR, 365, "mass_fabricator", RecipeMaps.MASS_FABRICATOR_RECIPES, Textures.MASS_FABRICATOR_OVERLAY, - ConfigHolder.U.machines.midTierMassFabricators, ConfigHolder.U.machines.highTierMassFabricators); + registerSimpleMetaTileEntity(MASS_FABRICATOR, 365, "mass_fabricator", RecipeMaps.MASS_FABRICATOR_RECIPES, Textures.MASS_FABRICATOR_OVERLAY); // Replicator, IDs 380-394 - registerSimpleMetaTileEntity(REPLICATOR, 380, "replicator", RecipeMaps.REPLICATOR_RECIPES, Textures.REPLICATOR_OVERLAY, - ConfigHolder.U.machines.midTierReplicators, ConfigHolder.U.machines.highTierReplicators); + registerSimpleMetaTileEntity(REPLICATOR, 380, "replicator", RecipeMaps.REPLICATOR_RECIPES, Textures.REPLICATOR_OVERLAY); // Fluid Heater, IDs 395-409 - registerSimpleMetaTileEntity(FLUID_HEATER, 395, "fluid_heater", RecipeMaps.FLUID_HEATER_RECIPES, Textures.FLUID_HEATER_OVERLAY, - ConfigHolder.U.machines.midTierFluidHeaters, ConfigHolder.U.machines.highTierFluidHeaters); + registerSimpleMetaTileEntity(FLUID_HEATER, 395, "fluid_heater", RecipeMaps.FLUID_HEATER_RECIPES, Textures.FLUID_HEATER_OVERLAY); // Fluid Solidifier, IDs 410-424 - registerSimpleMetaTileEntity(FLUID_SOLIDIFIER, 410, "fluid_solidifier", RecipeMaps.FLUID_SOLIDFICATION_RECIPES, Textures.FLUID_SOLIDIFIER_OVERLAY, - ConfigHolder.U.machines.midTierFluidSolidifiers, ConfigHolder.U.machines.highTierFluidSolidifiers); + registerSimpleMetaTileEntity(FLUID_SOLIDIFIER, 410, "fluid_solidifier", RecipeMaps.FLUID_SOLIDFICATION_RECIPES, Textures.FLUID_SOLIDIFIER_OVERLAY); // Forge Hammer, IDs 425-439 - registerSimpleMetaTileEntity(FORGE_HAMMER, 425, "forge_hammer", RecipeMaps.FORGE_HAMMER_RECIPES, Textures.FORGE_HAMMER_OVERLAY, - ConfigHolder.U.machines.midTierForgeHammers, ConfigHolder.U.machines.highTierForgeHammers); + registerSimpleMetaTileEntity(FORGE_HAMMER, 425, "forge_hammer", RecipeMaps.FORGE_HAMMER_RECIPES, Textures.FORGE_HAMMER_OVERLAY); // Forming Press, IDs 440-454 - registerSimpleMetaTileEntity(FORMING_PRESS, 440, "forming_press", RecipeMaps.FORMING_PRESS_RECIPES, Textures.FORMING_PRESS_OVERLAY, - ConfigHolder.U.machines.midTierFormingPresses, ConfigHolder.U.machines.highTierFormingPresses); + registerSimpleMetaTileEntity(FORMING_PRESS, 440, "forming_press", RecipeMaps.FORMING_PRESS_RECIPES, Textures.FORMING_PRESS_OVERLAY); // Lathe, IDs 455-469 - registerSimpleMetaTileEntity(LATHE, 455, "lathe", RecipeMaps.LATHE_RECIPES, Textures.LATHE_OVERLAY, - ConfigHolder.U.machines.midTierLathes, ConfigHolder.U.machines.highTierLathes); + registerSimpleMetaTileEntity(LATHE, 455, "lathe", RecipeMaps.LATHE_RECIPES, Textures.LATHE_OVERLAY); // Scanner, IDs 470-484 - registerSimpleMetaTileEntity(SCANNER, 470, "scanner", RecipeMaps.SCANNER_RECIPES, Textures.SCANNER_OVERLAY, - ConfigHolder.U.machines.midTierScanners, ConfigHolder.U.machines.highTierScanners); + registerSimpleMetaTileEntity(SCANNER, 470, "scanner", RecipeMaps.SCANNER_RECIPES, Textures.SCANNER_OVERLAY); // Mixer, IDs 485-499 - registerSimpleMetaTileEntity(MIXER, 485, "mixer", RecipeMaps.MIXER_RECIPES, Textures.MIXER_OVERLAY, - ConfigHolder.U.machines.midTierMixers, ConfigHolder.U.machines.highTierMixers, false, false); + registerSimpleMetaTileEntity(MIXER, 485, "mixer", RecipeMaps.MIXER_RECIPES, Textures.MIXER_OVERLAY, false); // Ore Washer, IDs 500-514 - registerSimpleMetaTileEntity(ORE_WASHER, 500, "ore_washer", RecipeMaps.ORE_WASHER_RECIPES, Textures.ORE_WASHER_OVERLAY, - ConfigHolder.U.machines.midTierOreWashers, ConfigHolder.U.machines.highTierOreWashers); + registerSimpleMetaTileEntity(ORE_WASHER, 500, "ore_washer", RecipeMaps.ORE_WASHER_RECIPES, Textures.ORE_WASHER_OVERLAY); // Packer, IDs 515-529 - registerSimpleMetaTileEntity(PACKER, 515, "packer", RecipeMaps.PACKER_RECIPES, Textures.PACKER_OVERLAY, - ConfigHolder.U.machines.midTierPackers, ConfigHolder.U.machines.highTierPackers); + registerSimpleMetaTileEntity(PACKER, 515, "packer", RecipeMaps.PACKER_RECIPES, Textures.PACKER_OVERLAY); // Unpacker, IDs 530-544 - registerSimpleMetaTileEntity(UNPACKER, 530, "unpacker", RecipeMaps.UNPACKER_RECIPES, Textures.UNPACKER_OVERLAY, - ConfigHolder.U.machines.midTierUnpackers, ConfigHolder.U.machines.highTierUnpackers); + registerSimpleMetaTileEntity(UNPACKER, 530, "unpacker", RecipeMaps.UNPACKER_RECIPES, Textures.UNPACKER_OVERLAY); - // Free Range, IDs 545-559 + // Gas Collectors, IDs 545-559 + registerSimpleMetaTileEntity(GAS_COLLECTOR, 545, "gas_collector", RecipeMaps.GAS_COLLECTOR_RECIPES, Textures.GAS_COLLECTOR_OVERLAY, false); // Polarizer, IDs 560-574 - registerSimpleMetaTileEntity(POLARIZER, 560, "polarizer", RecipeMaps.POLARIZER_RECIPES, Textures.POLARIZER_OVERLAY, - ConfigHolder.U.machines.midTierPolarizers, ConfigHolder.U.machines.highTierPolarizers); + registerSimpleMetaTileEntity(POLARIZER, 560, "polarizer", RecipeMaps.POLARIZER_RECIPES, Textures.POLARIZER_OVERLAY); // Laser Engraver, IDs 575-589 - registerSimpleMetaTileEntity(LASER_ENGRAVER, 575, "laser_engraver", RecipeMaps.LASER_ENGRAVER_RECIPES, Textures.LASER_ENGRAVER_OVERLAY, - ConfigHolder.U.machines.midTierLaserEngravers, ConfigHolder.U.machines.highTierLaserEngravers); + registerSimpleMetaTileEntity(LASER_ENGRAVER, 575, "laser_engraver", RecipeMaps.LASER_ENGRAVER_RECIPES, Textures.LASER_ENGRAVER_OVERLAY); // Sifter, IDs 590-604 - registerSimpleMetaTileEntity(SIFTER, 590, "sifter", RecipeMaps.SIFTER_RECIPES, Textures.SIFTER_OVERLAY, - ConfigHolder.U.machines.midTierSifters, ConfigHolder.U.machines.highTierSifters); + registerSimpleMetaTileEntity(SIFTER, 590, "sifter", RecipeMaps.SIFTER_RECIPES, Textures.SIFTER_OVERLAY); // Thermal Centrifuge, IDs 605-619 - registerSimpleMetaTileEntity(THERMAL_CENTRIFUGE, 605, "thermal_centrifuge", RecipeMaps.THERMAL_CENTRIFUGE_RECIPES, Textures.THERMAL_CENTRIFUGE_OVERLAY, - ConfigHolder.U.machines.midTierThermalCentrifuges, ConfigHolder.U.machines.highTierThermalCentrifuges); + registerSimpleMetaTileEntity(THERMAL_CENTRIFUGE, 605, "thermal_centrifuge", RecipeMaps.THERMAL_CENTRIFUGE_RECIPES, Textures.THERMAL_CENTRIFUGE_OVERLAY); // Wire Mill, IDs 620-634 - registerSimpleMetaTileEntity(WIREMILL, 620, "wiremill", RecipeMaps.WIREMILL_RECIPES, Textures.WIREMILL_OVERLAY, - ConfigHolder.U.machines.midTierWiremills, ConfigHolder.U.machines.highTierWiremills); - - // Free Range, IDs 635-650 + registerSimpleMetaTileEntity(WIREMILL, 620, "wiremill", RecipeMaps.WIREMILL_RECIPES, Textures.WIREMILL_OVERLAY); // Circuit Assembler, IDs 650-664 - registerSimpleMetaTileEntity(CIRCUIT_ASSEMBLER, 650, "circuit_assembler", RecipeMaps.CIRCUIT_ASSEMBLER_RECIPES, Textures.ASSEMBLER_OVERLAY, - true, false, true, true); + registerSimpleMetaTileEntity(CIRCUIT_ASSEMBLER, 635, "circuit_assembler", RecipeMaps.CIRCUIT_ASSEMBLER_RECIPES, Textures.ASSEMBLER_OVERLAY, true); // Some space here for more SimpleMachines @@ -465,15 +434,30 @@ public static void init() { STEAM_OVEN = GregTechAPI.registerMetaTileEntity(1023, new MetaTileEntitySteamOven(gregtechId("steam_oven"))); STEAM_GRINDER = GregTechAPI.registerMetaTileEntity(1024, new MetaTileEntitySteamGrinder(gregtechId("steam_grinder"))); - // MISC MTE's START: IDs 1300-2000 - // Transformer, IDs 1300-1314 - endPos = GTValues.HT ? TRANSFORMER.length : Math.min(TRANSFORMER.length, GTValues.UV); + // MISC MTE's START: IDs 1285-2000 + + + // Transformer, IDs 1270-1299 + endPos = GTValues.HT ? TRANSFORMER.length - 1 : Math.min(TRANSFORMER.length - 1, GTValues.UV); for (int i = 0; i <= endPos; i++) { MetaTileEntityTransformer transformer = new MetaTileEntityTransformer(gregtechId("transformer." + GTValues.VN[i].toLowerCase()), i); - TRANSFORMER[i] = GregTechAPI.registerMetaTileEntity(1300 + (i), transformer); + TRANSFORMER[i] = GregTechAPI.registerMetaTileEntity(1270 + (i), transformer); + MetaTileEntityAdjustableTransformer adjustableTransformer = new MetaTileEntityAdjustableTransformer(gregtechId("transformer.adjustable." + GTValues.VN[i].toLowerCase()), i); + ADJUSTABLE_TRANSFORMER[i] = GregTechAPI.registerMetaTileEntity(1285 + (i), adjustableTransformer); } + // Diode, IDs 1300-1314 + endPos = GTValues.HT ? DIODES.length - 1 : Math.min(DIODES.length - 1, GTValues.UV + 1); + for (int i = 0; i < endPos; i++) { + String diodeId = "diode." + GTValues.VN[i].toLowerCase(); + MetaTileEntityDiode diode = new MetaTileEntityDiode(gregtechId(diodeId), i); + DIODES[i] = GregTechAPI.registerMetaTileEntity(1300 + i, diode); + } + // MAX Diode + MetaTileEntityDiode diode = new MetaTileEntityDiode(gregtechId("diode.max"), DIODES.length - 1); + DIODES[DIODES.length - 1] = GregTechAPI.registerMetaTileEntity(1300 + DIODES.length - 1, diode); + // Battery Buffer, IDs 1315-1374 endPos = GTValues.HT ? BATTERY_BUFFER.length - 1 : Math.min(BATTERY_BUFFER.length - 1, GTValues.UV + 1); int[] batteryBufferSlots = new int[]{1, 4, 9, 16}; @@ -528,38 +512,36 @@ public static void init() { GregTechAPI.registerMetaTileEntity(1420 + 9, FLUID_IMPORT_HATCH[9]); GregTechAPI.registerMetaTileEntity(1435 + 9, FLUID_EXPORT_HATCH[9]); - // Energy Input/Output Hatches, IDs 1450-1479 + // Energy Input/Output Hatches, IDs 1450-1509 endPos = GTValues.HT ? ENERGY_INPUT_HATCH.length - 1 : Math.min(ENERGY_INPUT_HATCH.length - 1, GTValues.UV + 1); for (int i = 0; i < endPos; i++) { String voltageName = GTValues.VN[i].toLowerCase(); ENERGY_INPUT_HATCH[i] = new MetaTileEntityEnergyHatch(gregtechId("energy_hatch.input." + voltageName), i, false); + ENERGY_INPUT_HATCH_ADJUSTABLE[i] = new MetaTileEntityAdjustableEnergyHatch(gregtechId("energy_hatch.adjustable.input." + voltageName), i, false); ENERGY_OUTPUT_HATCH[i] = new MetaTileEntityEnergyHatch(gregtechId("energy_hatch.output." + voltageName), i, true); + ENERGY_OUTPUT_HATCH_ADJUSTABLE[i] = new MetaTileEntityAdjustableEnergyHatch(gregtechId("energy_hatch.adjustable.output." + voltageName), i, true); GregTechAPI.registerMetaTileEntity(1450 + i, ENERGY_INPUT_HATCH[i]); - GregTechAPI.registerMetaTileEntity(1465 + i, ENERGY_OUTPUT_HATCH[i]); + GregTechAPI.registerMetaTileEntity(1465 + i, ENERGY_INPUT_HATCH_ADJUSTABLE[i]); + GregTechAPI.registerMetaTileEntity(1480 + i, ENERGY_OUTPUT_HATCH[i]); + GregTechAPI.registerMetaTileEntity(1495 + i, ENERGY_OUTPUT_HATCH_ADJUSTABLE[i]); } // MAX Hatches ENERGY_INPUT_HATCH[ENERGY_INPUT_HATCH.length - 1] = new MetaTileEntityEnergyHatch(gregtechId("energy_hatch.input.max"), ENERGY_INPUT_HATCH.length - 1, false); + ENERGY_INPUT_HATCH_ADJUSTABLE[ENERGY_INPUT_HATCH_ADJUSTABLE.length - 1] = new MetaTileEntityAdjustableEnergyHatch(gregtechId("energy_hatch.adjustable.input.max"), ENERGY_INPUT_HATCH_ADJUSTABLE.length - 1, false); ENERGY_OUTPUT_HATCH[ENERGY_OUTPUT_HATCH.length - 1] = new MetaTileEntityEnergyHatch(gregtechId("energy_hatch.output.max"), ENERGY_OUTPUT_HATCH.length - 1, true); + ENERGY_OUTPUT_HATCH_ADJUSTABLE[ENERGY_OUTPUT_HATCH_ADJUSTABLE.length - 1] = new MetaTileEntityAdjustableEnergyHatch(gregtechId("energy_hatch.adjustable.output.max"), ENERGY_OUTPUT_HATCH_ADJUSTABLE.length - 1, true); GregTechAPI.registerMetaTileEntity(1450 + ENERGY_INPUT_HATCH.length - 1, ENERGY_INPUT_HATCH[ENERGY_INPUT_HATCH.length - 1]); - GregTechAPI.registerMetaTileEntity(1465 + ENERGY_OUTPUT_HATCH.length - 1, ENERGY_OUTPUT_HATCH[ENERGY_OUTPUT_HATCH.length - 1]); + GregTechAPI.registerMetaTileEntity(1465 + ENERGY_INPUT_HATCH_ADJUSTABLE.length - 1, ENERGY_INPUT_HATCH_ADJUSTABLE[ENERGY_INPUT_HATCH_ADJUSTABLE.length - 1]); + GregTechAPI.registerMetaTileEntity(1480 + ENERGY_INPUT_HATCH.length - 1, ENERGY_INPUT_HATCH[ENERGY_INPUT_HATCH.length - 1]); + GregTechAPI.registerMetaTileEntity(1495 + ENERGY_OUTPUT_HATCH_ADJUSTABLE.length - 1, ENERGY_OUTPUT_HATCH_ADJUSTABLE[ENERGY_OUTPUT_HATCH_ADJUSTABLE.length - 1]); - // Rotor Holder, IDs 1480-1484 - ROTOR_HOLDER[0] = GregTechAPI.registerMetaTileEntity(1480, new MetaTileEntityRotorHolder(gregtechId("rotor_holder.hv"), GTValues.HV, 1.0f)); - ROTOR_HOLDER[1] = GregTechAPI.registerMetaTileEntity(1481, new MetaTileEntityRotorHolder(gregtechId("rotor_holder.luv"), GTValues.LuV, 1.15f)); - ROTOR_HOLDER[2] = GregTechAPI.registerMetaTileEntity(1482, new MetaTileEntityRotorHolder(gregtechId("rotor_holder.uhv"), GTValues.UHV, 1.25f)); + BUFFER[0] = GregTechAPI.registerMetaTileEntity(1510, new MetaTileEntityBuffer(gregtechId("buffer.lv"), 1)); + BUFFER[1] = GregTechAPI.registerMetaTileEntity(1511, new MetaTileEntityBuffer(gregtechId("buffer.mv"), 2)); + BUFFER[2] = GregTechAPI.registerMetaTileEntity(1512, new MetaTileEntityBuffer(gregtechId("buffer.hv"), 3)); - // Free Range, IDs 1485-1499 - - // Tanks, IDs 1500-1514 - WOODEN_TANK = GregTechAPI.registerMetaTileEntity(1500, new MetaTileEntityTank(gregtechId("wooden_tank"), Materials.Wood, 4000, 1, 3)); - BRONZE_TANK = GregTechAPI.registerMetaTileEntity(1501, new MetaTileEntityTank(gregtechId("bronze_tank"), Materials.Bronze, 8000, 4, 3)); - STEEL_TANK = GregTechAPI.registerMetaTileEntity(1502, new MetaTileEntityTank(gregtechId("steel_tank"), Materials.Steel, 16000, 7, 5)); - ALUMINIUM_TANK = GregTechAPI.registerMetaTileEntity(1503, new MetaTileEntityTank(gregtechId("aluminium_tank"), Materials.Aluminium, 32000, 8, 5)); - STAINLESS_STEEL_TANK = GregTechAPI.registerMetaTileEntity(1504, new MetaTileEntityTank(gregtechId("stainless_steel_tank"), Materials.StainlessSteel, 64000, 9, 7)); - TITANIUM_TANK = GregTechAPI.registerMetaTileEntity(1505, new MetaTileEntityTank(gregtechId("titanium_tank"), Materials.Titanium, 128000, 12, 9)); - TUNGSTENSTEEL_TANK = GregTechAPI.registerMetaTileEntity(1506, new MetaTileEntityTank(gregtechId("tungstensteel_tank"), Materials.TungstenSteel, 512000, 16, 9)); + // Free Range: 1513-1514 // Fishers, IDs 1515-1529 FISHER[0] = GregTechAPI.registerMetaTileEntity(1515, new MetaTileEntityFisher(gregtechId("fisher.lv"), 1)); @@ -572,22 +554,6 @@ public static void init() { PUMP[1] = GregTechAPI.registerMetaTileEntity(1531, new MetaTileEntityPump(gregtechId("pump.mv"), 2)); PUMP[2] = GregTechAPI.registerMetaTileEntity(1532, new MetaTileEntityPump(gregtechId("pump.hv"), 3)); PUMP[3] = GregTechAPI.registerMetaTileEntity(1533, new MetaTileEntityPump(gregtechId("pump.ev"), 4)); - if (ConfigHolder.U.machines.highTierPumps) { - PUMP[4] = GregTechAPI.registerMetaTileEntity(1534, new MetaTileEntityPump(gregtechId("pump.iv"), 5)); - PUMP[5] = GregTechAPI.registerMetaTileEntity(1535, new MetaTileEntityPump(gregtechId("pump.luv"), 6)); - PUMP[6] = GregTechAPI.registerMetaTileEntity(1536, new MetaTileEntityPump(gregtechId("pump.zpm"), 7)); - PUMP[7] = GregTechAPI.registerMetaTileEntity(1537, new MetaTileEntityPump(gregtechId("pump.uv"), 8)); - } - - // Air Collectors, IDs 1545-1559 - AIR_COLLECTOR[0] = GregTechAPI.registerMetaTileEntity(1545, new MetaTileEntityAirCollector(gregtechId("air_collector.lv"), 1)); - AIR_COLLECTOR[1] = GregTechAPI.registerMetaTileEntity(1546, new MetaTileEntityAirCollector(gregtechId("air_collector.mv"), 2)); - AIR_COLLECTOR[2] = GregTechAPI.registerMetaTileEntity(1547, new MetaTileEntityAirCollector(gregtechId("air_collector.hv"), 3)); - AIR_COLLECTOR[3] = GregTechAPI.registerMetaTileEntity(1548, new MetaTileEntityAirCollector(gregtechId("air_collector.ev"), 4)); - if (ConfigHolder.U.machines.highTierAirCollectors) { - AIR_COLLECTOR[4] = GregTechAPI.registerMetaTileEntity(1549, new MetaTileEntityAirCollector(gregtechId("air_collector.iv"), 5)); - AIR_COLLECTOR[5] = GregTechAPI.registerMetaTileEntity(1550, new MetaTileEntityAirCollector(gregtechId("air_collector.luv"), 6)); - } // Super / Quantum Chests, IDs 1560-1574 for (int i = 0; i < 5; i++) { @@ -624,39 +590,50 @@ public static void init() { GregTechAPI.registerMetaTileEntity(1590 + i, BLOCK_BREAKER[i]); } - // Drums, IDs 1595-1609 - if (ConfigHolder.U.registerDrums) { - WOODEN_DRUM = GregTechAPI.registerMetaTileEntity(1595, new MetaTileEntityDrum(gregtechId("drum.wood"), Materials.Wood, 4000)); - BRONZE_DRUM = GregTechAPI.registerMetaTileEntity(1596, new MetaTileEntityDrum(gregtechId("drum.bronze"), Materials.Bronze, 8000)); - STEEL_DRUM = GregTechAPI.registerMetaTileEntity(1597, new MetaTileEntityDrum(gregtechId("drum.steel"), Materials.Steel, 16000)); - ALUMINIUM_DRUM = GregTechAPI.registerMetaTileEntity(1598, new MetaTileEntityDrum(gregtechId("drum.aluminium"), Materials.Aluminium, 32000)); - STAINLESS_STEEL_DRUM = GregTechAPI.registerMetaTileEntity(1599, new MetaTileEntityDrum(gregtechId("drum.stainless_steel"), Materials.StainlessSteel, 64000)); - TITANIUM_DRUM = GregTechAPI.registerMetaTileEntity(1600, new MetaTileEntityDrum(gregtechId("drum.titanium"), Materials.Titanium, 128000)); - TUNGSTENSTEEL_DRUM = GregTechAPI.registerMetaTileEntity(1601, new MetaTileEntityDrum(gregtechId("drum.tungstensteel"), Materials.TungstenSteel, 512000)); - } - - // Crates, IDs 1610-1624 - if (ConfigHolder.U.registerCrates) { - WOODEN_CRATE = GregTechAPI.registerMetaTileEntity(1610, new MetaTileEntityCrate(gregtechId("crate.wood"), Materials.Wood, 27)); - BRONZE_CRATE = GregTechAPI.registerMetaTileEntity(1611, new MetaTileEntityCrate(gregtechId("crate.bronze"), Materials.Bronze, 54)); - STEEL_CRATE = GregTechAPI.registerMetaTileEntity(1612, new MetaTileEntityCrate(gregtechId("crate.steel"), Materials.Steel, 72)); - ALUMINIUM_CRATE = GregTechAPI.registerMetaTileEntity(1613, new MetaTileEntityCrate(gregtechId("crate.aluminium"), Materials.Aluminium, 90)); - STAINLESS_STEEL_CRATE = GregTechAPI.registerMetaTileEntity(1614, new MetaTileEntityCrate(gregtechId("crate.stainless_steel"), Materials.StainlessSteel, 108)); - TITANIUM_CRATE = GregTechAPI.registerMetaTileEntity(1615, new MetaTileEntityCrate(gregtechId("crate.titanium"), Materials.Titanium, 144)); - TUNGSTENSTEEL_CRATE = GregTechAPI.registerMetaTileEntity(1616, new MetaTileEntityCrate(gregtechId("crate.tungstensteel"), Materials.TungstenSteel, 168)); - } - - // Misc, IDs 1625-1999 - LOCKED_SAFE = GregTechAPI.registerMetaTileEntity(1626, new MetaTileEntityLockedSafe(gregtechId("locked_safe"))); - WORKBENCH = GregTechAPI.registerMetaTileEntity(1627, new MetaTileEntityWorkbench(gregtechId("workbench"))); - PRIMITIVE_WATER_PUMP = GregTechAPI.registerMetaTileEntity(1628, new MetaTileEntityPrimitiveWaterPump(gregtechId("primitive_water_pump"))); - PUMP_OUTPUT_HATCH = GregTechAPI.registerMetaTileEntity(1629, new MetaTileEntityPumpHatch(gregtechId("pump_hatch"))); - - INFINITE_EMITTER = GregTechAPI.registerMetaTileEntity(1630, new MetaTileEntityInfiniteEmitter(gregtechId("infinite_emitter"))); + // Tanks, IDs 1595-1609 + WOODEN_TANK = GregTechAPI.registerMetaTileEntity(1595, new MetaTileEntityTank(gregtechId("wooden_tank"), Materials.Wood, 4000, 1, 3)); + BRONZE_TANK = GregTechAPI.registerMetaTileEntity(1596, new MetaTileEntityTank(gregtechId("bronze_tank"), Materials.Bronze, 8000, 4, 3)); + STEEL_TANK = GregTechAPI.registerMetaTileEntity(1597, new MetaTileEntityTank(gregtechId("steel_tank"), Materials.Steel, 16000, 7, 5)); + ALUMINIUM_TANK = GregTechAPI.registerMetaTileEntity(1598, new MetaTileEntityTank(gregtechId("aluminium_tank"), Materials.Aluminium, 32000, 8, 5)); + STAINLESS_STEEL_TANK = GregTechAPI.registerMetaTileEntity(1599, new MetaTileEntityTank(gregtechId("stainless_steel_tank"), Materials.StainlessSteel, 64000, 9, 7)); + TITANIUM_TANK = GregTechAPI.registerMetaTileEntity(1600, new MetaTileEntityTank(gregtechId("titanium_tank"), Materials.Titanium, 128000, 12, 9)); + TUNGSTENSTEEL_TANK = GregTechAPI.registerMetaTileEntity(1601, new MetaTileEntityTank(gregtechId("tungstensteel_tank"), Materials.TungstenSteel, 512000, 16, 9)); + + // Drums, IDs 1610-1624 + WOODEN_DRUM = GregTechAPI.registerMetaTileEntity(1610, new MetaTileEntityDrum(gregtechId("drum.wood"), Materials.Wood, 4000)); + BRONZE_DRUM = GregTechAPI.registerMetaTileEntity(1611, new MetaTileEntityDrum(gregtechId("drum.bronze"), Materials.Bronze, 8000)); + STEEL_DRUM = GregTechAPI.registerMetaTileEntity(1612, new MetaTileEntityDrum(gregtechId("drum.steel"), Materials.Steel, 16000)); + ALUMINIUM_DRUM = GregTechAPI.registerMetaTileEntity(1613, new MetaTileEntityDrum(gregtechId("drum.aluminium"), Materials.Aluminium, 32000)); + STAINLESS_STEEL_DRUM = GregTechAPI.registerMetaTileEntity(1614, new MetaTileEntityDrum(gregtechId("drum.stainless_steel"), Materials.StainlessSteel, 64000)); + TITANIUM_DRUM = GregTechAPI.registerMetaTileEntity(1615, new MetaTileEntityDrum(gregtechId("drum.titanium"), Materials.Titanium, 128000)); + TUNGSTENSTEEL_DRUM = GregTechAPI.registerMetaTileEntity(1616, new MetaTileEntityDrum(gregtechId("drum.tungstensteel"), Materials.TungstenSteel, 512000)); + + // Crates, IDs 1625-1639 + WOODEN_CRATE = GregTechAPI.registerMetaTileEntity(1625, new MetaTileEntityCrate(gregtechId("crate.wood"), Materials.Wood, 27)); + BRONZE_CRATE = GregTechAPI.registerMetaTileEntity(1626, new MetaTileEntityCrate(gregtechId("crate.bronze"), Materials.Bronze, 54)); + STEEL_CRATE = GregTechAPI.registerMetaTileEntity(1627, new MetaTileEntityCrate(gregtechId("crate.steel"), Materials.Steel, 72)); + ALUMINIUM_CRATE = GregTechAPI.registerMetaTileEntity(1628, new MetaTileEntityCrate(gregtechId("crate.aluminium"), Materials.Aluminium, 90)); + STAINLESS_STEEL_CRATE = GregTechAPI.registerMetaTileEntity(1629, new MetaTileEntityCrate(gregtechId("crate.stainless_steel"), Materials.StainlessSteel, 108)); + TITANIUM_CRATE = GregTechAPI.registerMetaTileEntity(1630, new MetaTileEntityCrate(gregtechId("crate.titanium"), Materials.Titanium, 126)); + TUNGSTENSTEEL_CRATE = GregTechAPI.registerMetaTileEntity(1631, new MetaTileEntityCrate(gregtechId("crate.tungstensteel"), Materials.TungstenSteel, 144)); + + // Rotor Holder, IDs 1640-1644 + ROTOR_HOLDER[0] = GregTechAPI.registerMetaTileEntity(1640, new MetaTileEntityRotorHolder(gregtechId("rotor_holder.hv"), GTValues.HV, 1.0f)); + ROTOR_HOLDER[1] = GregTechAPI.registerMetaTileEntity(1641, new MetaTileEntityRotorHolder(gregtechId("rotor_holder.luv"), GTValues.LuV, 1.15f)); + ROTOR_HOLDER[2] = GregTechAPI.registerMetaTileEntity(1642, new MetaTileEntityRotorHolder(gregtechId("rotor_holder.uhv"), GTValues.UHV, 1.25f)); + + // Misc, IDs 1645-1999 + LOCKED_SAFE = GregTechAPI.registerMetaTileEntity(1645, new MetaTileEntityLockedSafe(gregtechId("locked_safe"))); + WORKBENCH = GregTechAPI.registerMetaTileEntity(1646, new MetaTileEntityWorkbench(gregtechId("workbench"))); + PRIMITIVE_WATER_PUMP = GregTechAPI.registerMetaTileEntity(1647, new MetaTileEntityPrimitiveWaterPump(gregtechId("primitive_water_pump"))); + PUMP_OUTPUT_HATCH = GregTechAPI.registerMetaTileEntity(1648, new MetaTileEntityPumpHatch(gregtechId("pump_hatch"))); + + CREATIVE_ENERGY = GregTechAPI.registerMetaTileEntity(1649, new MetaTileEntityCreativeEnergy()); // Steam Hatches/Buses - STEAM_EXPORT_BUS = GregTechAPI.registerMetaTileEntity(1631, new MetaTileEntitySteamItemBus(gregtechId("steam_export_bus"), true)); - STEAM_IMPORT_BUS = GregTechAPI.registerMetaTileEntity(1632, new MetaTileEntitySteamItemBus(gregtechId("steam_import_bus"), false)); - STEAM_HATCH = GregTechAPI.registerMetaTileEntity(1633, new MetaTileEntitySteamHatch(gregtechId("steam_hatch"))); + STEAM_EXPORT_BUS = GregTechAPI.registerMetaTileEntity(1650, new MetaTileEntitySteamItemBus(gregtechId("steam_export_bus"), true)); + STEAM_IMPORT_BUS = GregTechAPI.registerMetaTileEntity(1651, new MetaTileEntitySteamItemBus(gregtechId("steam_import_bus"), false)); + STEAM_HATCH = GregTechAPI.registerMetaTileEntity(1652, new MetaTileEntitySteamHatch(gregtechId("steam_hatch"))); + SIMPLE_ORE_WASHER = GregTechAPI.registerMetaTileEntity(1653, new MetaTileEntitySimpleOreWasher(gregtechId("ore_washer.simple"), RecipeMaps.SIMPLE_WASHER_RECIPES, Textures.ORE_WASHER_OVERLAY, 0)); CLIPBOARD_TILE = GregTechAPI.registerMetaTileEntity(1636, new MetaTileEntityClipboard(gregtechId("clipboard"))); @@ -681,33 +658,59 @@ private static void registerSimpleMetaTileEntity(SimpleMachineMetaTileEntity[] m String name, RecipeMap map, OrientedOverlayRenderer texture, - boolean midTier, - boolean highTier, - boolean hasFrontFacing, - boolean ignoreConfig) { - for (int i = 0; i < machines.length - 1; i++) { - if (!ignoreConfig) { - if (i > 4 && !(ConfigHolder.U.machines.midTierMachines || midTier)) continue; - if (i > 7 && !(ConfigHolder.U.machines.highTierMachines || highTier)) break; - } - - String voltageName = GTValues.VN[i + 1].toLowerCase(); - machines[i] = GregTechAPI.registerMetaTileEntity(startId + i, - new SimpleMachineMetaTileEntity(gregtechId(String.format("%s.%s", name, voltageName)), map, texture, i + 1, hasFrontFacing)); - } + boolean hasFrontFacing) { + registerSimpleMetaTileEntity(machines, startId, name, map, texture, hasFrontFacing, MetaTileEntities::gregtechId); } private static void registerSimpleMetaTileEntity(SimpleMachineMetaTileEntity[] machines, int startId, String name, RecipeMap map, - OrientedOverlayRenderer texture, - boolean midTier, - boolean highTier) { - registerSimpleMetaTileEntity(machines, startId, name, map, texture, midTier, highTier, true, false); + OrientedOverlayRenderer texture) { + registerSimpleMetaTileEntity(machines, startId, name, map, texture, true); + } + + public static void registerSimpleMetaTileEntity(SimpleMachineMetaTileEntity[] machines, + int startId, + String name, + RecipeMap map, + OrientedOverlayRenderer texture, + boolean hasFrontFacing, + Function resourceId) { + for (int i = 0; i < machines.length - 1; i++) { + if (i > 4 && !getMidTier(name)) continue; + if (i > 7 && !getHighTier(name)) break; + + String voltageName = GTValues.VN[i + 1].toLowerCase(); + machines[i] = GregTechAPI.registerMetaTileEntity(startId + i, + new SimpleMachineMetaTileEntity(resourceId.apply(String.format("%s.%s", name, voltageName)), map, texture, i + 1, hasFrontFacing)); + } } private static ResourceLocation gregtechId(String name) { return new ResourceLocation(GTValues.MODID, name); } + + // Used for addons if they wish to disable certain tiers of machines + private static final Map MID_TIER = new HashMap<>(); + private static final Map HIGH_TIER = new HashMap<>(); + + @SuppressWarnings("unused") + public static void setMidTier(String key, boolean enabled) { + MID_TIER.put(key, enabled); + } + + @SuppressWarnings("unused") + public static void setHighTier(String key, boolean enabled) { + HIGH_TIER.put(key, enabled); + GTValues.HT = enabled || HIGH_TIER.containsValue(true); + } + + public static boolean getMidTier(String key) { + return MID_TIER.getOrDefault(key, true); + } + + public static boolean getHighTier(String key) { + return HIGH_TIER.getOrDefault(key, false); + } } diff --git a/src/main/java/gregtech/common/metatileentities/electric/MetaTileEntityAdjustableTransformer.java b/src/main/java/gregtech/common/metatileentities/electric/MetaTileEntityAdjustableTransformer.java new file mode 100644 index 00000000000..607c5947e38 --- /dev/null +++ b/src/main/java/gregtech/common/metatileentities/electric/MetaTileEntityAdjustableTransformer.java @@ -0,0 +1,195 @@ +package gregtech.common.metatileentities.electric; + +import codechicken.lib.raytracer.CuboidRayTraceResult; +import codechicken.lib.render.CCRenderState; +import codechicken.lib.render.pipeline.IVertexOperation; +import codechicken.lib.vec.Matrix4; +import gregtech.api.GTValues; +import gregtech.api.capability.GregtechCapabilities; +import gregtech.api.capability.impl.EnergyContainerHandler; +import gregtech.api.capability.tool.ISoftHammerItem; +import gregtech.api.metatileentity.MetaTileEntity; +import gregtech.api.metatileentity.MetaTileEntityHolder; +import gregtech.api.render.SimpleOverlayRenderer; +import gregtech.api.render.Textures; +import gregtech.api.util.PipelineUtil; +import gregtech.common.tools.DamageValues; +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.network.PacketBuffer; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.EnumHand; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.text.TextComponentTranslation; +import net.minecraft.world.World; + +import javax.annotation.Nullable; +import java.util.Arrays; +import java.util.List; + +public class MetaTileEntityAdjustableTransformer extends MetaTileEntityTransformer { + + private static final int[] hiAmpsRange = {1, 2, 4, 16}; + private static final int[] loAmpsRange = {4, 8, 16, 64}; + private int ampIndex; + + public MetaTileEntityAdjustableTransformer(ResourceLocation metaTileEntityId, int tier) { + super(metaTileEntityId, tier); + this.ampIndex = 2; + } + + @Override + public MetaTileEntity createMetaTileEntity(MetaTileEntityHolder holder) { + return new MetaTileEntityAdjustableTransformer(metaTileEntityId, getTier()); + } + + @Override + public NBTTagCompound writeToNBT(NBTTagCompound data) { + super.writeToNBT(data); + data.setInteger("ampIndex", ampIndex); + return data; + } + + @Override + public void readFromNBT(NBTTagCompound data) { + super.readFromNBT(data); + this.ampIndex = data.getInteger("ampIndex"); + reinitializeEnergyContainer(); + } + + @Override + public void writeInitialSyncData(PacketBuffer buf) { + super.writeInitialSyncData(buf); + buf.writeInt(ampIndex); + } + + @Override + public void receiveInitialSyncData(PacketBuffer buf) { + super.receiveInitialSyncData(buf); + this.ampIndex = buf.readInt(); + } + + @Override + public void receiveCustomData(int dataId, PacketBuffer buf) { + super.receiveCustomData(dataId, buf); + if (dataId == 101) { + this.ampIndex = buf.readInt(); + scheduleRenderUpdate(); + } + } + + protected void incrementAmpIndex() { + this.ampIndex = (this.ampIndex + 1) % hiAmpsRange.length; + if (!getWorld().isRemote) { + reinitializeEnergyContainer(); + writeCustomData(101, b -> b.writeInt(ampIndex)); + getHolder().notifyBlockUpdate(); + markDirty(); + } + } + + @Override + protected void reinitializeEnergyContainer() { + long tierVoltage = GTValues.V[getTier()]; + if (isInverted()) { + //storage = 1 amp high; input = tier / 4; amperage = loAmpsRange[ampIndex]; output = tier; amperage = hiAmpsRange[ampIndex] + this.energyContainer = new EnergyContainerHandler(this, tierVoltage * 128L, tierVoltage, loAmpsRange[ampIndex], tierVoltage * 4, hiAmpsRange[ampIndex]); + ((EnergyContainerHandler) this.energyContainer).setSideInputCondition(s -> s != getFrontFacing()); + ((EnergyContainerHandler) this.energyContainer).setSideOutputCondition(s -> s == getFrontFacing()); + } else { + //storage = 1 amp high; input = tier; amperage = hiAmpsRange[ampIndex]; output = tier / 4; amperage = loAmpsRange[ampIndex] + this.energyContainer = new EnergyContainerHandler(this, tierVoltage * 128L, tierVoltage * 4, hiAmpsRange[ampIndex], tierVoltage, loAmpsRange[ampIndex]); + ((EnergyContainerHandler) this.energyContainer).setSideInputCondition(s -> s == getFrontFacing()); + ((EnergyContainerHandler) this.energyContainer).setSideOutputCondition(s -> s != getFrontFacing()); + } + } + + @Override + public void renderMetaTileEntity(CCRenderState renderState, Matrix4 translation, IVertexOperation[] pipeline) { + super.renderMetaTileEntity(renderState, translation, pipeline); + + SimpleOverlayRenderer otherFaceTexture; + SimpleOverlayRenderer frontFaceTexture; + switch (this.ampIndex) { + case 1: + otherFaceTexture = isInverted() ? Textures.ENERGY_IN_MULTI : Textures.ENERGY_OUT_MULTI; + frontFaceTexture = isInverted() ? Textures.ENERGY_IN_HI : Textures.ENERGY_IN_HI; + break; + case 2: + otherFaceTexture = isInverted() ? Textures.ENERGY_IN_HI : Textures.ENERGY_OUT_HI; + frontFaceTexture = isInverted() ? Textures.ENERGY_OUT_ULTRA : Textures.ENERGY_IN_ULTRA; + break; + case 3: + otherFaceTexture = isInverted() ? Textures.ENERGY_IN_ULTRA : Textures.ENERGY_OUT_ULTRA; + frontFaceTexture = isInverted() ? Textures.ENERGY_OUT_ULTRA : Textures.ENERGY_IN_ULTRA; + break; + default: + otherFaceTexture = isInverted() ? Textures.ENERGY_IN : Textures.ENERGY_OUT; + frontFaceTexture = isInverted() ? Textures.ENERGY_OUT_MULTI : Textures.ENERGY_IN_MULTI; + } + + frontFaceTexture.renderSided(frontFacing, renderState, translation, PipelineUtil.color(pipeline, GTValues.VC[getTier() + 1])); + Arrays.stream(EnumFacing.values()).filter(f -> f != frontFacing) + .forEach((f -> otherFaceTexture.renderSided(f, renderState, translation, PipelineUtil.color(pipeline, GTValues.VC[getTier()])))); + } + + @Override + public boolean onRightClick(EntityPlayer playerIn, EnumHand hand, EnumFacing facing, CuboidRayTraceResult hitResult) { + ItemStack itemStack = playerIn.getHeldItem(hand); + if (!itemStack.isEmpty() && itemStack.hasCapability(GregtechCapabilities.CAPABILITY_MALLET, null)) { + ISoftHammerItem softHammerItem = itemStack.getCapability(GregtechCapabilities.CAPABILITY_MALLET, null); + + if (getWorld().isRemote) { + scheduleRenderUpdate(); + return true; + } + if (!softHammerItem.damageItem(DamageValues.DAMAGE_FOR_SOFT_HAMMER, false)) { + return false; + } + + if (isInverted()) { + setTransformUp(false); + playerIn.sendMessage(new TextComponentTranslation("gregtech.machine.transformer.message_transform_down", + energyContainer.getInputVoltage(), energyContainer.getInputAmperage(), energyContainer.getOutputVoltage(), energyContainer.getOutputAmperage())); + } else { + setTransformUp(true); + playerIn.sendMessage(new TextComponentTranslation("gregtech.machine.transformer.message_transform_up", + energyContainer.getInputVoltage(), energyContainer.getInputAmperage(), energyContainer.getOutputVoltage(), energyContainer.getOutputAmperage())); + } + return true; + } + return false; + } + + @Override + public boolean onScrewdriverClick(EntityPlayer playerIn, EnumHand hand, EnumFacing facing, CuboidRayTraceResult hitResult) { + if (getWorld().isRemote) { + scheduleRenderUpdate(); + return true; + } + + incrementAmpIndex(); + playerIn.sendMessage(new TextComponentTranslation("gregtech.machine.transformer_adjustable.message_adjust", + energyContainer.getInputVoltage(), energyContainer.getInputAmperage(), energyContainer.getOutputVoltage(), energyContainer.getOutputAmperage())); + + return true; + } + + @Override + public void addInformation(ItemStack stack, @Nullable World player, List tooltip, boolean advanced) { + String lowerTierName = GTValues.VN[getTier()]; + String higherTierName = GTValues.VN[getTier() + 1]; + long lowerVoltage = energyContainer.getOutputVoltage(); + long higherVoltage = energyContainer.getInputVoltage(); + long lowerAmperage = energyContainer.getInputAmperage(); + long higherAmperage = energyContainer.getOutputAmperage(); + + tooltip.add(I18n.format("gregtech.machine.transformer.tooltip_tool_usage")); + tooltip.add(I18n.format("gregtech.machine.transformer_adjustable.tooltip_tool_usage")); + tooltip.add(I18n.format("gregtech.universal.tooltip.energy_storage_capacity", energyContainer.getEnergyCapacity())); + tooltip.add(I18n.format("gregtech.machine.transformer.tooltip_transform_down", lowerAmperage, higherVoltage, higherTierName, higherAmperage, lowerVoltage, lowerTierName)); + tooltip.add(I18n.format("gregtech.machine.transformer.tooltip_transform_up", higherAmperage, lowerVoltage, lowerTierName, lowerAmperage, higherVoltage, higherTierName)); + } +} diff --git a/src/main/java/gregtech/common/metatileentities/electric/MetaTileEntityAirCollector.java b/src/main/java/gregtech/common/metatileentities/electric/MetaTileEntityAirCollector.java deleted file mode 100644 index 76efb8e2dbf..00000000000 --- a/src/main/java/gregtech/common/metatileentities/electric/MetaTileEntityAirCollector.java +++ /dev/null @@ -1,116 +0,0 @@ -package gregtech.common.metatileentities.electric; - -import codechicken.lib.render.CCRenderState; -import codechicken.lib.render.pipeline.IVertexOperation; -import codechicken.lib.vec.Matrix4; -import gregtech.api.GTValues; -import gregtech.api.capability.impl.FluidTankList; -import gregtech.api.gui.ModularUI; -import gregtech.api.metatileentity.MetaTileEntity; -import gregtech.api.metatileentity.MetaTileEntityHolder; -import gregtech.api.metatileentity.TieredMetaTileEntity; -import gregtech.api.render.Textures; -import gregtech.api.unification.material.Materials; -import gregtech.common.ConfigHolder; -import net.minecraft.client.resources.I18n; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.item.ItemStack; -import net.minecraft.util.EnumFacing; -import net.minecraft.util.ResourceLocation; -import net.minecraft.world.World; -import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.fluids.FluidTank; - -import javax.annotation.Nullable; -import java.util.List; -import java.util.stream.IntStream; - -public class MetaTileEntityAirCollector extends TieredMetaTileEntity { - private static final int PRODUCTION_CYCLE_LENGTH = 20; - - public MetaTileEntityAirCollector(ResourceLocation metaTileEntityId, int tier) { - super(metaTileEntityId, tier); - } - - @Override - public MetaTileEntity createMetaTileEntity(MetaTileEntityHolder holder) { - return new MetaTileEntityAirCollector(metaTileEntityId, getTier()); - } - - @Override - protected FluidTankList createExportFluidHandler() { - return new FluidTankList(false, new FluidTank(32000)); - } - - @Override - public void update() { - super.update(); - - if (!getWorld().isRemote) { - long energyToConsume = GTValues.V[getTier()]; - if (checkDimension() && checkOpenSides() && getOffsetTimer() % PRODUCTION_CYCLE_LENGTH == 0L && energyContainer.getEnergyStored() >= energyToConsume) { - int fluidAmount = getCollectedFluidAmount(); - FluidStack fluidStack = Materials.Air.getFluid(fluidAmount); - if (exportFluids.fill(fluidStack, false) == fluidAmount) { - exportFluids.fill(fluidStack, true); - energyContainer.removeEnergy(energyToConsume); - } - } - if (getOffsetTimer() % 5 == 0) { - pushFluidsIntoNearbyHandlers(getFrontFacing()); - } - } - } - - private boolean checkOpenSides() { - EnumFacing frontFacing = getFrontFacing(); - for (EnumFacing side : EnumFacing.VALUES) { - if (side == frontFacing) continue; - if (getWorld().isAirBlock(getPos().offset(side))) - return true; - } - return false; - } - - private boolean checkDimension() { - int dimensionId = getWorld().provider.getDimension(); - return IntStream.of(ConfigHolder.airCollectorDimensionBlacklist).noneMatch(x -> x == dimensionId); - } - - private int getCollectedFluidAmount() { - return 500 * (1 << getTier()); - } - - @Override - public void renderMetaTileEntity(CCRenderState renderState, Matrix4 translation, IVertexOperation[] pipeline) { - super.renderMetaTileEntity(renderState, translation, pipeline); - EnumFacing frontFacing = getFrontFacing(); - for (EnumFacing side : EnumFacing.VALUES) { - if (side.getAxis().isHorizontal()) { - Textures.AIR_VENT_OVERLAY.renderSided(side, renderState, translation, pipeline); - } else { - Textures.FILTER_OVERLAY.renderSided(side, renderState, translation, pipeline); - } - } - Textures.PIPE_OUT_OVERLAY.renderSided(frontFacing, renderState, translation, pipeline); - } - - @Override - protected ModularUI createUI(EntityPlayer entityPlayer) { - return null; - } - - @Override - protected boolean openGUIOnRightClick() { - return false; - } - - @Override - public void addInformation(ItemStack stack, @Nullable World player, List tooltip, boolean advanced) { - tooltip.add(I18n.format("gregtech.machine.air_collector.tooltip")); - tooltip.add(I18n.format("gregtech.machine.air_collector.collection_speed", getCollectedFluidAmount(), PRODUCTION_CYCLE_LENGTH)); - tooltip.add(I18n.format("gregtech.universal.tooltip.voltage_in", energyContainer.getInputVoltage(), GTValues.VN[getTier()])); - tooltip.add(I18n.format("gregtech.universal.tooltip.energy_storage_capacity", energyContainer.getEnergyCapacity())); - tooltip.add(I18n.format("gregtech.universal.tooltip.fluid_storage_capacity", exportFluids.getTankAt(0).getCapacity())); - } -} diff --git a/src/main/java/gregtech/common/metatileentities/electric/MetaTileEntityDiode.java b/src/main/java/gregtech/common/metatileentities/electric/MetaTileEntityDiode.java new file mode 100644 index 00000000000..e43017bdda0 --- /dev/null +++ b/src/main/java/gregtech/common/metatileentities/electric/MetaTileEntityDiode.java @@ -0,0 +1,152 @@ +package gregtech.common.metatileentities.electric; + +import codechicken.lib.raytracer.CuboidRayTraceResult; +import codechicken.lib.render.CCRenderState; +import codechicken.lib.render.pipeline.IVertexOperation; +import codechicken.lib.vec.Matrix4; +import gregtech.api.GTValues; +import gregtech.api.capability.GregtechCapabilities; +import gregtech.api.capability.impl.EnergyContainerHandler; +import gregtech.api.capability.tool.ISoftHammerItem; +import gregtech.api.gui.ModularUI; +import gregtech.api.metatileentity.MetaTileEntity; +import gregtech.api.metatileentity.MetaTileEntityHolder; +import gregtech.api.metatileentity.TieredMetaTileEntity; +import gregtech.api.render.Textures; +import gregtech.api.util.PipelineUtil; +import gregtech.common.tools.DamageValues; +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.network.PacketBuffer; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.EnumHand; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.text.TextComponentTranslation; +import net.minecraft.world.World; + +import javax.annotation.Nullable; +import java.util.Arrays; +import java.util.List; + +public class MetaTileEntityDiode extends TieredMetaTileEntity { + + private static final String AMP_NBT_KEY = "amp_mode"; + private int amps; + + public MetaTileEntityDiode(ResourceLocation metaTileEntityId, int tier) { + super(metaTileEntityId, tier); + amps = 1; + reinitializeEnergyContainer(); + } + + @Override + public MetaTileEntity createMetaTileEntity(MetaTileEntityHolder holder) { + return new MetaTileEntityDiode(metaTileEntityId, getTier()); + } + + @Override + public NBTTagCompound writeToNBT(NBTTagCompound data) { + super.writeToNBT(data); + data.setInteger(AMP_NBT_KEY, amps); + return data; + } + + @Override + public void readFromNBT(NBTTagCompound data) { + super.readFromNBT(data); + this.amps = data.getInteger(AMP_NBT_KEY); + reinitializeEnergyContainer(); + } + + @Override + public void writeInitialSyncData(PacketBuffer buf) { + super.writeInitialSyncData(buf); + buf.writeInt(amps); + } + + @Override + public void receiveInitialSyncData(PacketBuffer buf) { + super.receiveInitialSyncData(buf); + this.amps = buf.readInt(); + } + + @Override + public void receiveCustomData(int dataId, PacketBuffer buf) { + super.receiveCustomData(dataId, buf); + if (dataId == 101) { + this.amps = buf.readInt(); + } + } + + private void setAmpMode() { + amps = amps == 16 ? 1 : amps << 1; + if (!getWorld().isRemote) { + reinitializeEnergyContainer(); + writeCustomData(101, b -> b.writeInt(amps)); + getHolder().notifyBlockUpdate(); + markDirty(); + } + } + + @Override + protected void reinitializeEnergyContainer() { + long tierVoltage = GTValues.V[getTier()]; + this.energyContainer = new EnergyContainerHandler(this, tierVoltage * 8, tierVoltage, amps, tierVoltage, amps); + ((EnergyContainerHandler) this.energyContainer).setSideInputCondition(s -> s != getFrontFacing()); + ((EnergyContainerHandler) this.energyContainer).setSideOutputCondition(s -> s == getFrontFacing()); + } + + @Override + public void renderMetaTileEntity(CCRenderState renderState, Matrix4 translation, IVertexOperation[] pipeline) { + super.renderMetaTileEntity(renderState, translation, pipeline); + Textures.ENERGY_IN_MULTI.renderSided(getFrontFacing(), renderState, translation, PipelineUtil.color(pipeline, GTValues.VC[getTier()])); + Arrays.stream(EnumFacing.values()).filter(f -> f != frontFacing).forEach(f -> + Textures.ENERGY_OUT.renderSided(f, renderState, translation, PipelineUtil.color(pipeline, GTValues.VC[getTier()]))); + } + + @Override + public boolean isValidFrontFacing(EnumFacing facing) { + return true; + } + + @Override + public boolean onRightClick(EntityPlayer playerIn, EnumHand hand, EnumFacing facing, CuboidRayTraceResult hitResult) { + ItemStack itemStack = playerIn.getHeldItem(hand); + if(!itemStack.isEmpty() && itemStack.hasCapability(GregtechCapabilities.CAPABILITY_MALLET, null)) { + ISoftHammerItem softHammerItem = itemStack.getCapability(GregtechCapabilities.CAPABILITY_MALLET, null); + + if (getWorld().isRemote) { + scheduleRenderUpdate(); + return true; + } + if(!softHammerItem.damageItem(DamageValues.DAMAGE_FOR_SOFT_HAMMER, false)) { + return false; + } + + setAmpMode(); + playerIn.sendMessage(new TextComponentTranslation("gregtech.machine.diode.message", amps)); + return true; + } + return false; + } + + @Override + protected boolean openGUIOnRightClick() { + return false; + } + + @Override + protected ModularUI createUI(EntityPlayer entityPlayer) { + return null; + } + + @Override + public void addInformation(ItemStack stack, @Nullable World player, List tooltip, boolean advanced) { + tooltip.add(I18n.format("gregtech.machine.diode.tooltip_general")); + tooltip.add(I18n.format("gregtech.machine.diode.tooltip_tool_usage")); + tooltip.add(I18n.format("gregtech.universal.tooltip.voltage_in", + energyContainer.getInputVoltage(), GTValues.VN[getTier()])); + } +} diff --git a/src/main/java/gregtech/common/metatileentities/electric/MetaTileEntityGasCollector.java b/src/main/java/gregtech/common/metatileentities/electric/MetaTileEntityGasCollector.java new file mode 100644 index 00000000000..5e34d91802c --- /dev/null +++ b/src/main/java/gregtech/common/metatileentities/electric/MetaTileEntityGasCollector.java @@ -0,0 +1,97 @@ +package gregtech.common.metatileentities.electric; + +import gregtech.api.capability.IEnergyContainer; +import gregtech.api.capability.IMultipleTankHandler; +import gregtech.api.capability.impl.RecipeLogicEnergy; +import gregtech.api.metatileentity.MetaTileEntity; +import gregtech.api.metatileentity.MetaTileEntityHolder; +import gregtech.api.metatileentity.SimpleMachineMetaTileEntity; +import gregtech.api.recipes.MatchingMode; +import gregtech.api.recipes.Recipe; +import gregtech.api.recipes.RecipeMap; +import gregtech.api.recipes.RecipeMaps; +import gregtech.api.recipes.recipeproperties.GasCollectorDimensionProperty; +import gregtech.api.render.OrientedOverlayRenderer; +import gregtech.api.render.Textures; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.items.IItemHandlerModifiable; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Supplier; + +public class MetaTileEntityGasCollector extends SimpleMachineMetaTileEntity { + + private int currentDimension; + + public MetaTileEntityGasCollector(ResourceLocation metaTileEntityId, RecipeMap recipeMap, OrientedOverlayRenderer renderer, int tier, boolean hasFrontFacing) { + super(metaTileEntityId, recipeMap, renderer, tier, hasFrontFacing); + } + + @Override + public MetaTileEntity createMetaTileEntity(MetaTileEntityHolder holder) { + return new MetaTileEntityGasCollector(this.metaTileEntityId, RecipeMaps.GAS_COLLECTOR_RECIPES, Textures.GAS_COLLECTOR_OVERLAY, this.getTier(), hasFrontFacing()); + } + + @Override + public void update() { + super.update(); + if (getOffsetTimer() % 20 == 0) + this.currentDimension = this.getWorld().provider.getDimension(); + } + + @Override + protected RecipeLogicEnergy createWorkable(RecipeMap recipeMap) { + final RecipeLogicEnergy result = new GasCollectorRecipeLogic(this, RecipeMaps.GAS_COLLECTOR_RECIPES, () -> energyContainer); + result.enableOverclockVoltage(); + return result; + } + + protected int getCurrentDimension() { + return this.currentDimension; + } + + private class GasCollectorRecipeLogic extends RecipeLogicEnergy { + + public GasCollectorRecipeLogic(MetaTileEntity metaTileEntity, RecipeMap recipeMap, Supplier energyContainer) { + super(metaTileEntity, recipeMap, energyContainer); + } + + @Override + protected void trySearchNewRecipe() { + long maxVoltage = getMaxVoltage(); + Recipe currentRecipe = null; + IItemHandlerModifiable importInventory = getInputInventory(); + IMultipleTankHandler importFluids = getInputTank(); + + // see if the last recipe we used still works + if (this.previousRecipe != null && this.previousRecipe.matches(false, importInventory, importFluids, MatchingMode.IGNORE_FLUIDS)) + currentRecipe = this.previousRecipe; + // If there is no active recipe, then we need to find one. + else { + currentRecipe = findRecipe(maxVoltage, importInventory, importFluids, MatchingMode.IGNORE_FLUIDS); + if (currentRecipe != null) { + List recipeDimensions = currentRecipe.getProperty(GasCollectorDimensionProperty.getInstance(), new ArrayList<>()); + boolean isDimensionValid = false; + for (Integer dimension : recipeDimensions) { + if (dimension == getCurrentDimension()) { + this.previousRecipe = currentRecipe; + isDimensionValid = true; + break; + } + } + if (!isDimensionValid) + currentRecipe = null; + } + } + this.invalidInputsForRecipes = (currentRecipe == null); + + // proceed if we have a usable recipe. + if (currentRecipe != null && setupAndConsumeRecipeInputs(currentRecipe)) + setupRecipe(currentRecipe); + // Inputs have been inspected. + metaTileEntity.getNotifiedItemInputList().clear(); + metaTileEntity.getNotifiedFluidInputList().clear(); + } + } +} diff --git a/src/main/java/gregtech/common/metatileentities/electric/MetaTileEntityInfiniteEmitter.java b/src/main/java/gregtech/common/metatileentities/electric/MetaTileEntityInfiniteEmitter.java deleted file mode 100644 index ea045d6b23f..00000000000 --- a/src/main/java/gregtech/common/metatileentities/electric/MetaTileEntityInfiniteEmitter.java +++ /dev/null @@ -1,247 +0,0 @@ -package gregtech.common.metatileentities.electric; - -import gregtech.api.GTValues; -import gregtech.api.gui.IUIHolder; -import gregtech.api.gui.ModularUI; -import gregtech.api.gui.Widget; -import gregtech.api.gui.resources.EmptyTextureArea; -import gregtech.api.gui.widgets.ClickButtonWidget; -import gregtech.api.gui.widgets.CycleButtonWidget; -import gregtech.api.gui.widgets.LabelWidget; -import gregtech.api.gui.widgets.TextFieldWidgetInfiniteEnergy; -import gregtech.api.metatileentity.InfiniteEnergyTileEntityBase; -import gregtech.api.metatileentity.MetaTileEntity; -import gregtech.api.metatileentity.MetaTileEntityHolder; -import gregtech.api.render.SimpleOverlayRenderer; -import gregtech.api.render.Textures; -import gregtech.api.util.function.BooleanConsumer; -import gregtech.common.metatileentities.traits.TraitInfiniteEmitter; -import net.minecraft.client.Minecraft; -import net.minecraft.client.resources.I18n; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.network.PacketBuffer; -import net.minecraft.util.ResourceLocation; -import net.minecraftforge.fml.client.config.GuiUtils; - -import java.math.BigInteger; -import java.util.ArrayDeque; -import java.util.Collections; -import java.util.function.Consumer; -import java.util.function.IntConsumer; -import java.util.function.Predicate; -import java.util.regex.Pattern; - -public class MetaTileEntityInfiniteEmitter extends InfiniteEnergyTileEntityBase { - public MetaTileEntityInfiniteEmitter(ResourceLocation metaTileEntityId) { - super(metaTileEntityId); - } - - @Override - protected TraitInfiniteEmitter createTrait() { - return new TraitInfiniteEmitter(this); - } - - @Override - public MetaTileEntity createMetaTileEntity(MetaTileEntityHolder holder) { - return new MetaTileEntityInfiniteEmitter(metaTileEntityId); - } - - @Override - protected ModularUI createUI(EntityPlayer entityPlayer) { - InfiniteEnergyUIData d = new InfiniteEnergyUIData(); - d.setEnergy(trait.getEnergy()); - d.setInfinite(trait.isInfinite()); - d.setTier(trait.getTier()); - return d.guiBuilder() - .buttonInfinite(trait::setInfinite) - .energyInput("EU", trait::setEnergy) - .buttonTier(trait::setTier) - .buttonAcceptDecline() - .createUI(getHolder(), entityPlayer); - } - - @Override - protected SimpleOverlayRenderer getOverlay() { - return Textures.INFINITE_EMITTER_FACE; - } - - public static class InfiniteEnergyUIData { - private static final Pattern NUMBER_PATTERN = Pattern.compile("[0-9]*"); - private static final Predicate NUMBER_PATTERN_VALIDATOR = s -> NUMBER_PATTERN.matcher(s).matches(); - private static final String[] TRANSLATABLE_VOLTAGE_NAMES; - - static { - TRANSLATABLE_VOLTAGE_NAMES = new String[GTValues.V.length]; - for (int i = 0; i < GTValues.V.length; i++) - TRANSLATABLE_VOLTAGE_NAMES[i] = "info.infinite_energy." + GTValues.VN[i].toLowerCase(); - } - - private boolean isDirty; - - private String energyText; - private int tier; - private boolean isInfinite; - - public InfiniteEnergyGuiBuilder guiBuilder() { - return new InfiniteEnergyGuiBuilder(); - } - - public void markDirty(boolean isDirty) { - this.isDirty = isDirty; - } - - public boolean isDirty() { - return this.isDirty; - } - - public String getEnergyText() { - return energyText; - } - - public void setEnergyText(String energyText) { - markDirty(true); - this.energyText = energyText; - } - - public BigInteger parseEnergyFromText() { - return energyText.isEmpty() ? BigInteger.ZERO : new BigInteger(energyText); - } - - public void setEnergy(BigInteger energy) { - setEnergyText(energy.toString()); - } - - public int getTier() { - return tier; - } - - public void setTier(int tier) { - markDirty(true); - this.tier = tier; - } - - public boolean isInfinite() { - return isInfinite; - } - - public void setInfinite(boolean infinite) { - markDirty(true); - isInfinite = infinite; - } - - public final class InfiniteEnergyGuiBuilder { - private final ArrayDeque widgets = new ArrayDeque<>(); - - private int y; - private boolean infinite; - private boolean energy; - private boolean tier; - - private BooleanConsumer applyInfiniteFlagChange; - private Consumer applyEnergyChange; - private IntConsumer applyTierChange; - - public InfiniteEnergyGuiBuilder buttonInfinite(BooleanConsumer applyInfiniteFlagChange) { - this.applyInfiniteFlagChange = applyInfiniteFlagChange; - if (!widgets.isEmpty()) y += 4; - widgets.add(new CycleButtonWidget( - 0, - y, - 200, - 20, - new String[]{"info.infinite_energy.finite", "info.infinite_energy.infinite"}, - () -> isInfinite() ? 1 : 0, - i -> setInfinite(i != 0) - )); - y += 20; - infinite = true; - return this; - } - - public InfiniteEnergyGuiBuilder energyInput(String labelText, Consumer applyEnergyChange) { - this.applyEnergyChange = applyEnergyChange; - if (!widgets.isEmpty()) y += 4; - widgets.add(new TextFieldWidgetInfiniteEnergy( - 2, - y, - 180, - 12, - true, - InfiniteEnergyUIData.this - ).setValidator(NUMBER_PATTERN_VALIDATOR)); - widgets.add(new LabelWidget(188, y + 2, labelText, -1)); - y += 12; - energy = true; - return this; - } - - public InfiniteEnergyGuiBuilder buttonTier(IntConsumer applyTierChange) { - this.applyTierChange = applyTierChange; - if (!widgets.isEmpty()) y += 4; - widgets.add(new CycleButtonWidget( - 0, - y, - 200, - 20, - TRANSLATABLE_VOLTAGE_NAMES, - InfiniteEnergyUIData.this::getTier, - InfiniteEnergyUIData.this::setTier - )); - y += 20; - tier = true; - return this; - } - - public InfiniteEnergyGuiBuilder buttonAcceptDecline() { - if (!widgets.isEmpty()) y += 16; - buttonClose(true); - buttonClose(false); - y += 20; - return this; - } - - private void buttonClose(boolean setDirty) { - widgets.add(new ClickButtonWidget( - setDirty ? 0 : 200 - 98, y, - 98, - 20, - setDirty ? "info.infinite_energy.accept" : "info.infinite_energy.decline", - c -> markDirty(setDirty)) { - @Override - public void handleClientAction(int id, PacketBuffer buffer) { - super.handleClientAction(id, buffer); - this.gui.entityPlayer.closeScreen(); - } - - @Override - public void drawInForeground(int mouseX, int mouseY) { - if (isMouseOver(getPosition().x, getPosition().y, getSize().width, getSize().height, mouseX, mouseY)) { - GuiUtils.drawHoveringText( - Collections.singletonList(I18n.format(setDirty ? "info.button.accept" : "info.button.decline")), - mouseX, - mouseY, - this.gui.getScreenWidth(), - this.gui.getScreenHeight(), - -1, - Minecraft.getMinecraft().fontRenderer); - } - } - }); - } - - public ModularUI createUI(IUIHolder holder, EntityPlayer player) { - ModularUI.Builder b = new ModularUI.Builder(new EmptyTextureArea(200, y), 200, y); - for (Widget w : widgets) b.widget(w); - b.bindCloseListener(() -> { - if (!player.world.isRemote && isDirty()) { - if (infinite) applyInfiniteFlagChange.apply(isInfinite()); - if (energy) applyEnergyChange.accept(parseEnergyFromText()); - if (tier) applyTierChange.accept(getTier()); - } - }); - return b.build(holder, player); - } - } - } - -} diff --git a/src/main/java/gregtech/common/metatileentities/electric/MetaTileEntityMacerator.java b/src/main/java/gregtech/common/metatileentities/electric/MetaTileEntityMacerator.java index d2008fb3537..b10b12e9c90 100644 --- a/src/main/java/gregtech/common/metatileentities/electric/MetaTileEntityMacerator.java +++ b/src/main/java/gregtech/common/metatileentities/electric/MetaTileEntityMacerator.java @@ -9,12 +9,12 @@ import gregtech.api.recipes.RecipeMap; import gregtech.api.render.OrientedOverlayRenderer; import gregtech.api.util.GTUtility; +import gregtech.api.capability.impl.NotifiableItemStackHandler; import net.minecraft.client.resources.I18n; import net.minecraft.item.ItemStack; import net.minecraft.util.ResourceLocation; import net.minecraft.world.World; import net.minecraftforge.items.IItemHandlerModifiable; -import net.minecraftforge.items.ItemStackHandler; import javax.annotation.Nullable; import java.util.List; @@ -47,7 +47,7 @@ protected int getMachineTierForRecipe(Recipe recipe) { @Override protected IItemHandlerModifiable createExportItemHandler() { - return new ItemStackHandler(outputAmount); + return new NotifiableItemStackHandler(outputAmount, this, true); } @Override diff --git a/src/main/java/gregtech/common/metatileentities/electric/MetaTileEntitySimpleOreWasher.java b/src/main/java/gregtech/common/metatileentities/electric/MetaTileEntitySimpleOreWasher.java new file mode 100644 index 00000000000..f5d1430ef74 --- /dev/null +++ b/src/main/java/gregtech/common/metatileentities/electric/MetaTileEntitySimpleOreWasher.java @@ -0,0 +1,28 @@ +package gregtech.common.metatileentities.electric; + +import gregtech.api.capability.impl.NotifiableItemStackHandler; +import gregtech.api.metatileentity.MetaTileEntity; +import gregtech.api.metatileentity.MetaTileEntityHolder; +import gregtech.api.metatileentity.SimpleMachineMetaTileEntity; +import gregtech.api.recipes.RecipeMap; +import gregtech.api.render.OrientedOverlayRenderer; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.items.IItemHandlerModifiable; +import net.minecraftforge.items.ItemStackHandler; +public class MetaTileEntitySimpleOreWasher extends SimpleMachineMetaTileEntity { + + public MetaTileEntitySimpleOreWasher(ResourceLocation metaTileEntityId, RecipeMap recipeMap, OrientedOverlayRenderer renderer, int tier) { + super(metaTileEntityId, recipeMap, renderer, tier, true); + initializeInventory(); + } + + @Override + protected IItemHandlerModifiable createExportItemHandler() { + return new NotifiableItemStackHandler(1, this, true); + } + + @Override + public MetaTileEntity createMetaTileEntity(MetaTileEntityHolder holder) { + return new MetaTileEntitySimpleOreWasher(metaTileEntityId, workable.recipeMap, renderer, getTier()); + } +} diff --git a/src/main/java/gregtech/common/metatileentities/electric/MetaTileEntityTransformer.java b/src/main/java/gregtech/common/metatileentities/electric/MetaTileEntityTransformer.java index 6a33cac60f1..cce722986e4 100644 --- a/src/main/java/gregtech/common/metatileentities/electric/MetaTileEntityTransformer.java +++ b/src/main/java/gregtech/common/metatileentities/electric/MetaTileEntityTransformer.java @@ -175,15 +175,7 @@ public void addInformation(ItemStack stack, @Nullable World player, List tooltip.add(I18n.format("gregtech.machine.transformer.tooltip_tool_usage")); tooltip.add(I18n.format("gregtech.universal.tooltip.energy_storage_capacity", energyContainer.getEnergyCapacity())); - tooltip.add(I18n.format("gregtech.machine.transformer.tooltip_transform_down")); - tooltip.add(I18n.format("gregtech.universal.tooltip.voltage_in", higherVoltage, higherTierName)); - tooltip.add(I18n.format("gregtech.universal.tooltip.voltage_out", lowerVoltage, lowerTierName)); - tooltip.add(I18n.format("gregtech.universal.tooltip.amperage_in", lowerAmperage)); - tooltip.add(I18n.format("gregtech.universal.tooltip.amperage_out", higherAmperage)); - tooltip.add(I18n.format("gregtech.machine.transformer.tooltip_transform_up")); - tooltip.add(I18n.format("gregtech.universal.tooltip.voltage_in", lowerVoltage, lowerTierName)); - tooltip.add(I18n.format("gregtech.universal.tooltip.voltage_out", higherVoltage, higherTierName)); - tooltip.add(I18n.format("gregtech.universal.tooltip.amperage_in", higherAmperage)); - tooltip.add(I18n.format("gregtech.universal.tooltip.amperage_out", lowerAmperage)); + tooltip.add(I18n.format("gregtech.machine.transformer.tooltip_transform_down", lowerAmperage, higherVoltage, higherTierName, higherAmperage, lowerVoltage, lowerTierName)); + tooltip.add(I18n.format("gregtech.machine.transformer.tooltip_transform_up", higherAmperage, lowerVoltage, lowerTierName, lowerAmperage, higherVoltage, higherTierName)); } } diff --git a/src/main/java/gregtech/common/metatileentities/electric/multiblockpart/MetaTileEntityAdjustableEnergyHatch.java b/src/main/java/gregtech/common/metatileentities/electric/multiblockpart/MetaTileEntityAdjustableEnergyHatch.java new file mode 100644 index 00000000000..d70f7d75be1 --- /dev/null +++ b/src/main/java/gregtech/common/metatileentities/electric/multiblockpart/MetaTileEntityAdjustableEnergyHatch.java @@ -0,0 +1,188 @@ +package gregtech.common.metatileentities.electric.multiblockpart; + +import codechicken.lib.raytracer.CuboidRayTraceResult; +import codechicken.lib.render.CCRenderState; +import codechicken.lib.render.pipeline.IVertexOperation; +import codechicken.lib.vec.Matrix4; +import gregtech.api.GTValues; +import gregtech.api.capability.IEnergyContainer; +import gregtech.api.capability.impl.EnergyContainerHandler; +import gregtech.api.gui.ModularUI; +import gregtech.api.metatileentity.MetaTileEntity; +import gregtech.api.metatileentity.MetaTileEntityHolder; +import gregtech.api.metatileentity.multiblock.IMultiblockAbilityPart; +import gregtech.api.metatileentity.multiblock.MultiblockAbility; +import gregtech.api.render.SimpleOverlayRenderer; +import gregtech.api.render.Textures; +import gregtech.api.util.PipelineUtil; +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.network.PacketBuffer; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.EnumHand; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.text.TextComponentTranslation; +import net.minecraft.world.World; + +import javax.annotation.Nullable; +import java.util.List; + +public class MetaTileEntityAdjustableEnergyHatch extends MetaTileEntityMultiblockPart implements IMultiblockAbilityPart { + + private static final int[] ampRange = {2, 4, 8, 16}; + private int ampIndex; + + private final boolean isExportHatch; + private IEnergyContainer energyContainer; + + public MetaTileEntityAdjustableEnergyHatch(ResourceLocation metaTileEntityId, int tier, boolean isExportHatch) { + super(metaTileEntityId, tier); + this.isExportHatch = isExportHatch; + this.ampIndex = 1; + if (isExportHatch) { + this.energyContainer = EnergyContainerHandler.emitterContainer(this, GTValues.V[tier] * 32L, GTValues.V[tier], 2); + ((EnergyContainerHandler) this.energyContainer).setSideOutputCondition(s -> s == getFrontFacing()); + } else { + this.energyContainer = EnergyContainerHandler.receiverContainer(this, GTValues.V[tier] * 32L, GTValues.V[tier], 2); + } + } + + @Override + public MetaTileEntity createMetaTileEntity(MetaTileEntityHolder holder) { + return new MetaTileEntityAdjustableEnergyHatch(metaTileEntityId, getTier(), isExportHatch); + } + + @Override + public void renderMetaTileEntity(CCRenderState renderState, Matrix4 translation, IVertexOperation[] pipeline) { + super.renderMetaTileEntity(renderState, translation, pipeline); + if (shouldRenderOverlay()) { + SimpleOverlayRenderer renderer; + switch (ampIndex) { + case 1: + renderer = isExportHatch ? Textures.ENERGY_OUT_MULTI : Textures.ENERGY_IN_MULTI; + break; + + case 2: + renderer = isExportHatch ? Textures.ENERGY_OUT_HI : Textures.ENERGY_IN_HI; + break; + case 3: + renderer = isExportHatch ? Textures.ENERGY_OUT_ULTRA : Textures.ENERGY_IN_ULTRA; + break; + default: + renderer = isExportHatch ? Textures.ENERGY_OUT : Textures.ENERGY_IN; + } + + renderer.renderSided(getFrontFacing(), renderState, translation, PipelineUtil.color(pipeline, GTValues.VC[getTier()])); + } + } + + @Override + public NBTTagCompound writeToNBT(NBTTagCompound data) { + super.writeToNBT(data); + data.setInteger("ampIndex", ampIndex); + return data; + } + + @Override + public void readFromNBT(NBTTagCompound data) { + super.readFromNBT(data); + this.ampIndex = data.getInteger("ampIndex"); + reinitializeEnergyContainer(); + } + + @Override + public void writeInitialSyncData(PacketBuffer buf) { + super.writeInitialSyncData(buf); + buf.writeInt(ampIndex); + } + + @Override + public void receiveInitialSyncData(PacketBuffer buf) { + super.receiveInitialSyncData(buf); + this.ampIndex = buf.readInt(); + } + + @Override + public void receiveCustomData(int dataId, PacketBuffer buf) { + super.receiveCustomData(dataId, buf); + if (dataId == 101) { + this.ampIndex = buf.readInt(); + scheduleRenderUpdate(); + } + } + + protected void incrementAmpIndex() { + this.ampIndex = (this.ampIndex + 1) % ampRange.length; + if (!getWorld().isRemote) { + reinitializeEnergyContainer(); + writeCustomData(101, b -> b.writeInt(ampIndex)); + getHolder().notifyBlockUpdate(); + markDirty(); + } + } + + protected void reinitializeEnergyContainer() { + long tierVoltage = GTValues.V[getTier()]; + if (isExportHatch) { + this.energyContainer = EnergyContainerHandler.emitterContainer(this, tierVoltage * 32L, tierVoltage, ampRange[ampIndex]); + ((EnergyContainerHandler) this.energyContainer).setSideOutputCondition(s -> s == getFrontFacing()); + } else { + this.energyContainer = EnergyContainerHandler.receiverContainer(this, tierVoltage * 32L, tierVoltage, ampRange[ampIndex]); + } + } + + @Override + public boolean onScrewdriverClick(EntityPlayer playerIn, EnumHand hand, EnumFacing facing, CuboidRayTraceResult hitResult) { + if (getWorld().isRemote) { + scheduleRenderUpdate(); + return true; + } + + incrementAmpIndex(); + playerIn.sendMessage(new TextComponentTranslation("gregtech.machine.energy_hatch_adjustable.message_adjust", + isExportHatch ? energyContainer.getOutputAmperage() : energyContainer.getInputAmperage())); + + return true; + } + + @Override + public MultiblockAbility getAbility() { + return isExportHatch ? MultiblockAbility.OUTPUT_ENERGY : MultiblockAbility.INPUT_ENERGY; + } + + @Override + public void registerAbilities(List abilityList) { + abilityList.add(energyContainer); + } + + @Override + protected boolean openGUIOnRightClick() { + return false; + } + + @Override + protected ModularUI createUI(EntityPlayer entityPlayer) { + return null; + } + + @Override + public void addInformation(ItemStack stack, @Nullable World player, List tooltip, boolean advanced) { + String tierName = GTValues.VN[getTier()]; + + tooltip.add(I18n.format("gregtech.machine.transformer_adjustable.tooltip_tool_usage")); + + if (isExportHatch) { + tooltip.add(I18n.format("gregtech.machine.energy_hatch.adjustable.output.tooltip")); + tooltip.add(I18n.format("gregtech.universal.tooltip.voltage_out", energyContainer.getOutputVoltage(), tierName)); + tooltip.add(I18n.format("gregtech.universal.tooltip.amperage_out_till", energyContainer.getOutputAmperage())); + } else { + tooltip.add(I18n.format("gregtech.machine.energy_hatch.adjustable.input.tooltip")); + tooltip.add(I18n.format("gregtech.universal.tooltip.voltage_in", energyContainer.getInputVoltage(), tierName)); + tooltip.add(I18n.format("gregtech.universal.tooltip.amperage_in_till", energyContainer.getInputAmperage())); + } + tooltip.add(I18n.format("gregtech.universal.tooltip.energy_storage_capacity", energyContainer.getEnergyCapacity())); + tooltip.add(I18n.format("gregtech.universal.enabled")); + } +} diff --git a/src/main/java/gregtech/common/metatileentities/electric/multiblockpart/MetaTileEntityFluidHatch.java b/src/main/java/gregtech/common/metatileentities/electric/multiblockpart/MetaTileEntityFluidHatch.java index 2b3d7304aab..5fc2021ee4e 100644 --- a/src/main/java/gregtech/common/metatileentities/electric/multiblockpart/MetaTileEntityFluidHatch.java +++ b/src/main/java/gregtech/common/metatileentities/electric/multiblockpart/MetaTileEntityFluidHatch.java @@ -17,6 +17,7 @@ import gregtech.api.metatileentity.multiblock.MultiblockAbility; import gregtech.api.render.SimpleOverlayRenderer; import gregtech.api.render.Textures; +import gregtech.api.capability.impl.NotifiableFluidTank; import net.minecraft.client.resources.I18n; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; @@ -43,7 +44,7 @@ public MetaTileEntityFluidHatch(ResourceLocation metaTileEntityId, int tier, boo super(metaTileEntityId, tier); this.containerInventory = new ItemStackHandler(2); this.isExportHatch = isExportHatch; - this.fluidTank = new FluidTank(getInventorySize()); + this.fluidTank = new NotifiableFluidTank(getInventorySize(), this, isExportHatch); initializeInventory(); } @@ -122,6 +123,20 @@ public void registerAbilities(List abilityList) { abilityList.addAll(isExportHatch ? this.exportFluids.getFluidTanks() : this.importFluids.getFluidTanks()); } + @Override + public void setupNotifiableMetaTileEntity(MetaTileEntity metaTileEntity) { + NotifiableFluidTank handler = null; + if (isExportHatch) { + handler = (NotifiableFluidTank) getExportFluids().getTankAt(0); + } else { + handler = (NotifiableFluidTank) getImportFluids().getTankAt(0); + } + if (handler != null) { + handler.setNotifiableMetaTileEntity(metaTileEntity); + handler.addToNotifiedList(this, handler, isExportHatch); + } + } + @Override protected ModularUI createUI(EntityPlayer entityPlayer) { return createTankUI((isExportHatch ? exportFluids : importFluids).getTankAt(0), containerInventory, getMetaFullName(), entityPlayer) diff --git a/src/main/java/gregtech/common/metatileentities/electric/multiblockpart/MetaTileEntityItemBus.java b/src/main/java/gregtech/common/metatileentities/electric/multiblockpart/MetaTileEntityItemBus.java index 1e243d96394..7f1d62ea9f7 100644 --- a/src/main/java/gregtech/common/metatileentities/electric/multiblockpart/MetaTileEntityItemBus.java +++ b/src/main/java/gregtech/common/metatileentities/electric/multiblockpart/MetaTileEntityItemBus.java @@ -13,6 +13,7 @@ import gregtech.api.metatileentity.multiblock.MultiblockAbility; import gregtech.api.render.SimpleOverlayRenderer; import gregtech.api.render.Textures; +import gregtech.api.capability.impl.NotifiableItemStackHandler; import net.minecraft.client.resources.I18n; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; @@ -70,12 +71,12 @@ private int getInventorySize() { @Override protected IItemHandlerModifiable createExportItemHandler() { - return isExportHatch ? new ItemStackHandler(getInventorySize()) : new ItemStackHandler(0); + return isExportHatch ? new NotifiableItemStackHandler(getInventorySize(), getController(), true) : new ItemStackHandler(0); } @Override protected IItemHandlerModifiable createImportItemHandler() { - return isExportHatch ? new ItemStackHandler(0) : new ItemStackHandler(getInventorySize()); + return isExportHatch ? new ItemStackHandler(0) : new NotifiableItemStackHandler(getInventorySize(), getController(), false); } @Override @@ -88,6 +89,20 @@ public void registerAbilities(List abilityList) { abilityList.add(isExportHatch ? this.exportItems : this.importItems); } + @Override + public void setupNotifiableMetaTileEntity(MetaTileEntity metaTileEntity) { + NotifiableItemStackHandler handler = null; + if (isExportHatch && getExportItems() instanceof NotifiableItemStackHandler) { + handler = (NotifiableItemStackHandler) getExportItems(); + } else if (!isExportHatch && getImportItems() instanceof NotifiableItemStackHandler) { + handler = (NotifiableItemStackHandler) getImportItems(); + } + if (handler != null) { + handler.setNotifiableMetaTileEntity(metaTileEntity); + handler.addToNotifiedList(this, handler, isExportHatch); + } + } + @Override protected ModularUI createUI(EntityPlayer entityPlayer) { int rowSize = (int) Math.sqrt(getInventorySize()); diff --git a/src/main/java/gregtech/common/metatileentities/multi/MetaTileEntityCokeOven.java b/src/main/java/gregtech/common/metatileentities/multi/MetaTileEntityCokeOven.java index b451814a15b..c4924f82934 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/MetaTileEntityCokeOven.java +++ b/src/main/java/gregtech/common/metatileentities/multi/MetaTileEntityCokeOven.java @@ -3,205 +3,57 @@ import codechicken.lib.render.CCRenderState; import codechicken.lib.render.pipeline.IVertexOperation; import codechicken.lib.vec.Matrix4; -import gregtech.api.capability.impl.FluidTankList; import gregtech.api.gui.GuiTextures; import gregtech.api.gui.ModularUI; -import gregtech.api.gui.widgets.ProgressWidget.MoveType; +import gregtech.api.gui.widgets.ProgressWidget; import gregtech.api.gui.widgets.SlotWidget; import gregtech.api.gui.widgets.TankWidget; import gregtech.api.metatileentity.MetaTileEntity; import gregtech.api.metatileentity.MetaTileEntityHolder; import gregtech.api.metatileentity.multiblock.IMultiblockPart; -import gregtech.api.metatileentity.multiblock.MultiblockControllerBase; +import gregtech.api.metatileentity.multiblock.RecipeMapPrimitiveMultiblockController; import gregtech.api.multiblock.BlockPattern; -import gregtech.api.multiblock.BlockWorldState; import gregtech.api.multiblock.FactoryBlockPattern; import gregtech.api.recipes.RecipeMaps; -import gregtech.api.recipes.recipes.CokeOvenRecipe; import gregtech.api.render.ICubeRenderer; import gregtech.api.render.Textures; -import gregtech.common.blocks.BlockMetalCasing.MetalCasingType; +import gregtech.common.blocks.BlockMetalCasing; import gregtech.common.blocks.MetaBlocks; import net.minecraft.block.state.IBlockState; import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.network.PacketBuffer; -import net.minecraft.util.EnumFacing; import net.minecraft.util.ResourceLocation; -import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.fluids.FluidTank; -import net.minecraftforge.fluids.capability.CapabilityFluidHandler; -import net.minecraftforge.items.CapabilityItemHandler; -import net.minecraftforge.items.IItemHandlerModifiable; -import net.minecraftforge.items.ItemHandlerHelper; -import net.minecraftforge.items.ItemStackHandler; -import java.util.function.Predicate; - -public class MetaTileEntityCokeOven extends MultiblockControllerBase { - - private int maxProgressDuration; - private int currentProgress; - private ItemStack outputStack; - private FluidStack outputFluid; - private boolean isActive; - private boolean wasActiveAndNeedUpdate; - - private ItemStack lastInputStack = ItemStack.EMPTY; - private CokeOvenRecipe previousRecipe; +public class MetaTileEntityCokeOven extends RecipeMapPrimitiveMultiblockController { public MetaTileEntityCokeOven(ResourceLocation metaTileEntityId) { - super(metaTileEntityId); - } - - @Override - protected void updateFormedValid() { - if (maxProgressDuration == 0) { - if (tryPickNewRecipe()) { - if (wasActiveAndNeedUpdate) { - this.wasActiveAndNeedUpdate = false; - } else setActive(true); - } - } else if (++currentProgress >= maxProgressDuration) { - finishCurrentRecipe(); - this.wasActiveAndNeedUpdate = true; - return; - } - if (wasActiveAndNeedUpdate) { - this.wasActiveAndNeedUpdate = false; - setActive(false); - } - } - - private void finishCurrentRecipe() { - this.maxProgressDuration = 0; - this.currentProgress = 0; - ItemHandlerHelper.insertItemStacked(exportItems, outputStack, false); - this.exportFluids.fill(outputFluid, true); - markDirty(); - } - - private CokeOvenRecipe getOrRefreshRecipe(ItemStack inputStack) { - CokeOvenRecipe currentRecipe = null; - if (previousRecipe != null && - previousRecipe.getInput().getIngredient().apply(inputStack)) { - currentRecipe = previousRecipe; - } else if (!areItemStacksEqual(inputStack, lastInputStack)) { - this.lastInputStack = inputStack.isEmpty() ? ItemStack.EMPTY : inputStack.copy(); - currentRecipe = RecipeMaps.COKE_OVEN_RECIPES.stream() - .filter(it -> it.getInput().getIngredient().test(inputStack)) - .findFirst().orElse(null); - if (currentRecipe != null) { - this.previousRecipe = currentRecipe; - } - } - return currentRecipe; - } - - private static boolean areItemStacksEqual(ItemStack stackA, ItemStack stackB) { - return (stackA.isEmpty() && stackB.isEmpty()) || - (ItemStack.areItemsEqual(stackA, stackB) && - ItemStack.areItemStackTagsEqual(stackA, stackB)); - } - - private boolean setupRecipe(ItemStack inputStack, CokeOvenRecipe recipe) { - return inputStack.getCount() >= recipe.getInput().getCount() && - ItemHandlerHelper.insertItemStacked(exportItems, recipe.getOutput(), true).isEmpty() && - exportFluids.fill(recipe.getFluidOutput(), false) == recipe.getFluidOutput().amount; - } - - private boolean tryPickNewRecipe() { - ItemStack inputStack = importItems.getStackInSlot(0); - if (inputStack.isEmpty()) { - return false; - } - CokeOvenRecipe currentRecipe = getOrRefreshRecipe(inputStack); - if (currentRecipe != null && setupRecipe(inputStack, currentRecipe)) { - inputStack.shrink(currentRecipe.getInput().getCount()); - this.maxProgressDuration = currentRecipe.getDuration(); - this.currentProgress = 0; - this.outputStack = currentRecipe.getOutput().copy(); - this.outputFluid = currentRecipe.getFluidOutput().copy(); - markDirty(); - return true; - } - return false; - } - - @Override - public NBTTagCompound writeToNBT(NBTTagCompound data) { - super.writeToNBT(data); - data.setBoolean("Active", isActive); - data.setBoolean("WasActive", wasActiveAndNeedUpdate); - data.setInteger("MaxProgress", maxProgressDuration); - if (maxProgressDuration > 0) { - data.setInteger("Progress", currentProgress); - data.setTag("OutputItem", outputStack.writeToNBT(new NBTTagCompound())); - data.setTag("OutputFluid", outputFluid.writeToNBT(new NBTTagCompound())); - } - return data; + super(metaTileEntityId, RecipeMaps.COKE_OVEN_RECIPES); } @Override - public void readFromNBT(NBTTagCompound data) { - super.readFromNBT(data); - this.isActive = data.getBoolean("Active"); - this.wasActiveAndNeedUpdate = data.getBoolean("WasActive"); - this.maxProgressDuration = data.getInteger("MaxProgress"); - if (maxProgressDuration > 0) { - this.currentProgress = data.getInteger("Progress"); - this.outputStack = new ItemStack(data.getCompoundTag("OutputItem")); - this.outputFluid = FluidStack.loadFluidStackFromNBT(data.getCompoundTag("OutputFluid")); - } - } - - @Override - public void writeInitialSyncData(PacketBuffer buf) { - super.writeInitialSyncData(buf); - buf.writeBoolean(isActive); - } - - @Override - public void receiveInitialSyncData(PacketBuffer buf) { - super.receiveInitialSyncData(buf); - this.isActive = buf.readBoolean(); + public MetaTileEntity createMetaTileEntity(MetaTileEntityHolder holder) { + return new MetaTileEntityCokeOven(metaTileEntityId); } @Override - public void receiveCustomData(int dataId, PacketBuffer buf) { - super.receiveCustomData(dataId, buf); - if (dataId == 100) { - this.isActive = buf.readBoolean(); - getWorld().checkLight(getPos()); - getHolder().scheduleChunkForRenderUpdate(); - } - } - - public void setActive(boolean active) { - this.isActive = active; - if (!getWorld().isRemote) { - writeCustomData(100, b -> b.writeBoolean(isActive)); - getWorld().checkLight(getPos()); - } + protected BlockPattern createStructurePattern() { + return FactoryBlockPattern.start() + .aisle("XXX", "XZX", "XXX") + .aisle("XZX", "Z#Z", "XZX") + .aisle("XXX", "XYX", "XXX") + .where('Z', statePredicate(getCasingState()).or(tilePredicate((state, tile) -> tile instanceof MetaTileEntityCokeOvenHatch))) + .where('X', statePredicate(getCasingState())) + .where('#', isAirPredicate()) + .where('Y', selfPredicate()) + .build(); } - public boolean isActive() { - return isActive; + protected IBlockState getCasingState() { + return MetaBlocks.METAL_CASING.getState(BlockMetalCasing.MetalCasingType.COKE_BRICKS); } @Override public int getLightValueForPart(IMultiblockPart sourcePart) { - return sourcePart == null && isActive ? 15 : 0; - } - - public double getProgressScaled() { - return maxProgressDuration == 0 ? 0.0 : (currentProgress / (maxProgressDuration * 1.0)); - } - - protected IBlockState getCasingState() { - return MetaBlocks.METAL_CASING.getState(MetalCasingType.COKE_BRICKS); + return sourcePart == null && recipeMapWorkable.isActive() ? 15 : 0; } @Override @@ -212,65 +64,21 @@ public ICubeRenderer getBaseTexture(IMultiblockPart sourcePart) { @Override public void renderMetaTileEntity(CCRenderState renderState, Matrix4 translation, IVertexOperation[] pipeline) { super.renderMetaTileEntity(renderState, translation, pipeline); - Textures.COKE_OVEN_OVERLAY.render(renderState, translation, pipeline, getFrontFacing(), isActive()); - } - - @Override - public T getCapability(Capability capability, EnumFacing side) { - if (capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY || - capability == CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY) { - return null; - } - return super.getCapability(capability, side); - } - - @Override - protected IItemHandlerModifiable createImportItemHandler() { - return new ItemStackHandler(1); - } - - @Override - protected IItemHandlerModifiable createExportItemHandler() { - return new ItemStackHandler(1); - } - - @Override - protected FluidTankList createExportFluidHandler() { - return new FluidTankList(false, new FluidTank(32000)); - } - - @Override - protected BlockPattern createStructurePattern() { - Predicate hatchPredicate = tilePredicate((state, tile) -> tile instanceof MetaTileEntityCokeOvenHatch); - return FactoryBlockPattern.start() - .aisle("XXX", "XZX", "XXX") - .aisle("XZX", "Z#Z", "XZX") - .aisle("XXX", "XYX", "XXX") - .where('Z', statePredicate(getCasingState()).or(hatchPredicate)) - .where('X', statePredicate(getCasingState())) - .where('#', isAirPredicate()) - .where('Y', selfPredicate()) - .build(); - } - - @Override - public MetaTileEntity createMetaTileEntity(MetaTileEntityHolder holder) { - return new MetaTileEntityCokeOven(metaTileEntityId); + Textures.COKE_OVEN_OVERLAY.render(renderState, translation, pipeline, getFrontFacing(), recipeMapWorkable.isActive()); } @Override - protected ModularUI createUI(EntityPlayer entityPlayer) { + protected ModularUI.Builder createUITemplate(EntityPlayer entityPlayer) { return ModularUI.builder(GuiTextures.BACKGROUND, 176, 166) .widget(new SlotWidget(importItems, 0, 33, 30, true, true) .setBackgroundTexture(GuiTextures.SLOT, GuiTextures.FURNACE_OVERLAY)) - .progressBar(this::getProgressScaled, 58, 30, 20, 15, GuiTextures.BRONZE_BLAST_FURNACE_PROGRESS_BAR, MoveType.HORIZONTAL) + .progressBar(recipeMapWorkable::getProgressPercent, 58, 30, 20, 15, GuiTextures.BRONZE_BLAST_FURNACE_PROGRESS_BAR, ProgressWidget.MoveType.HORIZONTAL) .widget(new SlotWidget(exportItems, 0, 85, 30, true, false) .setBackgroundTexture(GuiTextures.SLOT, GuiTextures.FURNACE_OVERLAY)) .widget(new TankWidget(exportFluids.getTankAt(0), 133, 13, 20, 58) .setBackgroundTexture(GuiTextures.FLUID_TANK_BACKGROUND) .setOverlayTexture(GuiTextures.FLUID_TANK_OVERLAY) .setContainerClicking(true, false)) - .bindPlayerInventory(entityPlayer.inventory, GuiTextures.SLOT, 0) - .build(getHolder(), entityPlayer); + .bindPlayerInventory(entityPlayer.inventory, GuiTextures.SLOT, 0); } } diff --git a/src/main/java/gregtech/common/metatileentities/multi/MetaTileEntityPrimitiveBlastFurnace.java b/src/main/java/gregtech/common/metatileentities/multi/MetaTileEntityPrimitiveBlastFurnace.java index 9a3cf77a0b7..988b35bc9de 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/MetaTileEntityPrimitiveBlastFurnace.java +++ b/src/main/java/gregtech/common/metatileentities/multi/MetaTileEntityPrimitiveBlastFurnace.java @@ -5,376 +5,35 @@ import codechicken.lib.texture.TextureUtils; import codechicken.lib.vec.Cuboid6; import codechicken.lib.vec.Matrix4; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import gregtech.api.GTValues; -import gregtech.api.capability.impl.ItemHandlerProxy; import gregtech.api.gui.GuiTextures; import gregtech.api.gui.ModularUI; -import gregtech.api.gui.widgets.ProgressWidget.MoveType; +import gregtech.api.gui.widgets.ProgressWidget; import gregtech.api.gui.widgets.SlotWidget; import gregtech.api.metatileentity.MetaTileEntity; import gregtech.api.metatileentity.MetaTileEntityHolder; import gregtech.api.metatileentity.multiblock.IMultiblockPart; -import gregtech.api.metatileentity.multiblock.MultiblockControllerBase; +import gregtech.api.metatileentity.multiblock.RecipeMapPrimitiveMultiblockController; import gregtech.api.multiblock.BlockPattern; import gregtech.api.multiblock.FactoryBlockPattern; import gregtech.api.recipes.RecipeMaps; -import gregtech.api.recipes.recipes.PrimitiveBlastFurnaceRecipe; import gregtech.api.render.ICubeRenderer; import gregtech.api.render.Textures; -import gregtech.api.unification.OreDictUnifier; -import gregtech.api.unification.material.Material; -import gregtech.api.unification.material.Materials; -import gregtech.api.unification.ore.OrePrefix; -import gregtech.api.unification.stack.MaterialStack; -import gregtech.api.unification.stack.UnificationEntry; -import gregtech.common.blocks.BlockMetalCasing.MetalCasingType; +import gregtech.common.blocks.BlockMetalCasing; import gregtech.common.blocks.MetaBlocks; -import net.minecraft.block.state.IBlockState; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.nbt.NBTTagList; -import net.minecraft.network.PacketBuffer; import net.minecraft.util.EnumFacing; -import net.minecraft.util.NonNullList; import net.minecraft.util.ResourceLocation; -import net.minecraft.util.math.MathHelper; -import net.minecraftforge.common.util.Constants.NBT; -import net.minecraftforge.items.IItemHandlerModifiable; -import net.minecraftforge.items.ItemStackHandler; -import javax.annotation.Nonnull; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Objects; - -import static gregtech.api.util.InventoryUtils.simulateItemStackMerge; - -public class MetaTileEntityPrimitiveBlastFurnace extends MultiblockControllerBase { - - private static final List FUEL_DISPLAY_PREFIXES = ImmutableList.of( - OrePrefix.gem, OrePrefix.dust, OrePrefix.block); - - private static final Map ALTERNATIVE_MATERIAL_NAMES = ImmutableMap.of( - "fuelCoke", new MaterialStack(Materials.Coke, GTValues.M), - "blockFuelCoke", new MaterialStack(Materials.Coke, GTValues.M * 9L)); - - private static final Map MATERIAL_FUEL_MAP = ImmutableMap.of( - Materials.Lignite, 0.7f, - Materials.Charcoal, 1.0f, - Materials.Coal, 1.0f, - Materials.Coke, 2.0f); - - private int maxProgressDuration; - private int currentProgress; - private NonNullList outputsList; - private float fuelUnitsLeft; - private boolean isActive; - private boolean wasActiveAndNeedUpdate; - - private ItemStack lastInputStack = ItemStack.EMPTY; - private PrimitiveBlastFurnaceRecipe previousRecipe; +public class MetaTileEntityPrimitiveBlastFurnace extends RecipeMapPrimitiveMultiblockController { public MetaTileEntityPrimitiveBlastFurnace(ResourceLocation metaTileEntityId) { - super(metaTileEntityId); - } - - @Override - protected void updateFormedValid() { - if (maxProgressDuration == 0) { - if (tryPickNewRecipe()) { - if (wasActiveAndNeedUpdate) { - this.wasActiveAndNeedUpdate = false; - } else setActive(true); - } - } else if (++currentProgress >= maxProgressDuration) { - finishCurrentRecipe(); - this.wasActiveAndNeedUpdate = true; - return; - } - if (wasActiveAndNeedUpdate) { - this.wasActiveAndNeedUpdate = false; - setActive(false); - } - } - - private void finishCurrentRecipe() { - this.maxProgressDuration = 0; - this.currentProgress = 0; - MetaTileEntity.addItemsToItemHandler(exportItems, false, outputsList); - this.outputsList = null; - markDirty(); - } - - private PrimitiveBlastFurnaceRecipe getOrRefreshRecipe(ItemStack inputStack) { - PrimitiveBlastFurnaceRecipe currentRecipe = null; - if (previousRecipe != null && - previousRecipe.getInput().getIngredient().apply(inputStack)) { - currentRecipe = previousRecipe; - } else if (!areItemStacksEqual(inputStack, lastInputStack)) { - this.lastInputStack = inputStack.isEmpty() ? ItemStack.EMPTY : inputStack.copy(); - currentRecipe = RecipeMaps.PRIMITIVE_BLAST_FURNACE_RECIPES.stream() - .filter(it -> it.getInput().getIngredient().test(inputStack)) - .findFirst().orElse(null); - if (currentRecipe != null) { - this.previousRecipe = currentRecipe; - } - } - return currentRecipe; - } - - private static boolean areItemStacksEqual(ItemStack stackA, ItemStack stackB) { - return (stackA.isEmpty() && stackB.isEmpty()) || - (ItemStack.areItemsEqual(stackA, stackB) && - ItemStack.areItemStackTagsEqual(stackA, stackB)); - } - - private boolean setupRecipe(ItemStack inputStack, int fuelAmount, PrimitiveBlastFurnaceRecipe recipe) { - List outputs = new ArrayList<>(); - outputs.add(recipe.getOutput()); - outputs.add(getAshForRecipeFuelConsumption(recipe.getFuelAmount())); - return inputStack.getCount() >= recipe.getInput().getCount() && fuelAmount >= recipe.getFuelAmount() && - simulateItemStackMerge(outputs, exportItems); - } - - private boolean tryPickNewRecipe() { - ItemStack inputStack = importItems.getStackInSlot(0); - ItemStack fuelStack = importItems.getStackInSlot(1); - if (inputStack.isEmpty() || (fuelStack.isEmpty() && fuelUnitsLeft == 0)) { - return false; - } - float fuelUnitsPerItem = getFuelUnits(fuelStack); - float totalFuelUnits = fuelUnitsLeft + fuelUnitsPerItem * fuelStack.getCount(); - PrimitiveBlastFurnaceRecipe currentRecipe = getOrRefreshRecipe(inputStack); - if (currentRecipe != null && setupRecipe(inputStack, (int) totalFuelUnits, currentRecipe)) { - inputStack.shrink(currentRecipe.getInput().getCount()); - float fuelUnitsToConsume = currentRecipe.getFuelAmount(); - float remainderConsumed = Math.min(fuelUnitsToConsume, fuelUnitsLeft); - fuelUnitsToConsume -= remainderConsumed; - - int fuelItemsToConsume = (int) Math.ceil(fuelUnitsToConsume / (fuelUnitsPerItem * 1.0)); - float remainderAdded = fuelItemsToConsume * fuelUnitsPerItem - fuelUnitsToConsume; - - this.fuelUnitsLeft += (remainderAdded - remainderConsumed); - fuelStack.shrink(fuelItemsToConsume); - this.maxProgressDuration = currentRecipe.getDuration(); - this.currentProgress = 0; - NonNullList outputs = NonNullList.create(); - outputs.add(currentRecipe.getOutput().copy()); - outputs.add(getAshForRecipeFuelConsumption(currentRecipe.getFuelAmount())); - this.outputsList = outputs; - markDirty(); - return true; - } - return false; - } - - @Override - public NBTTagCompound writeToNBT(NBTTagCompound data) { - super.writeToNBT(data); - data.setBoolean("Active", isActive); - data.setBoolean("WasActive", wasActiveAndNeedUpdate); - data.setFloat("FuelUnitsLeft", fuelUnitsLeft); - data.setInteger("MaxProgress", maxProgressDuration); - if (maxProgressDuration > 0) { - data.setInteger("Progress", currentProgress); - NBTTagList itemOutputs = new NBTTagList(); - for (ItemStack itemStack : outputsList) { - itemOutputs.appendTag(itemStack.writeToNBT(new NBTTagCompound())); - } - data.setTag("Outputs", itemOutputs); - } - return data; + super(metaTileEntityId, RecipeMaps.PRIMITIVE_BLAST_FURNACE_RECIPES); } @Override - public void readFromNBT(NBTTagCompound data) { - super.readFromNBT(data); - this.isActive = data.getBoolean("Active"); - this.wasActiveAndNeedUpdate = data.getBoolean("WasActive"); - this.fuelUnitsLeft = data.getFloat("FuelUnitsLeft"); - this.maxProgressDuration = data.getInteger("MaxProgress"); - if (maxProgressDuration > 0) { - this.currentProgress = data.getInteger("Progress"); - NBTTagList itemOutputs = data.getTagList("Outputs", NBT.TAG_COMPOUND); - this.outputsList = NonNullList.create(); - for (int i = 0; i < itemOutputs.tagCount(); i++) { - this.outputsList.add(new ItemStack(itemOutputs.getCompoundTagAt(i))); - } - } - } - - @Override - public void writeInitialSyncData(PacketBuffer buf) { - super.writeInitialSyncData(buf); - buf.writeBoolean(isActive); - } - - @Override - public void receiveInitialSyncData(PacketBuffer buf) { - super.receiveInitialSyncData(buf); - this.isActive = buf.readBoolean(); - } - - @Override - public void receiveCustomData(int dataId, PacketBuffer buf) { - super.receiveCustomData(dataId, buf); - if (dataId == 100) { - this.isActive = buf.readBoolean(); - getWorld().checkLight(getPos()); - getHolder().scheduleChunkForRenderUpdate(); - } - } - - public void setActive(boolean active) { - this.isActive = active; - if (!getWorld().isRemote) { - writeCustomData(100, b -> b.writeBoolean(isActive)); - getWorld().checkLight(getPos()); - } - } - - public boolean isActive() { - return isActive; - } - - public double getProgressScaled() { - return maxProgressDuration == 0 ? 0.0 : (currentProgress / (maxProgressDuration * 1.0)); - } - - @Override - public int getLightValueForPart(IMultiblockPart sourcePart) { - return sourcePart == null && isActive ? 15 : 0; - } - - public static float getFuelUnits(ItemStack fuelType) { - if (fuelType.isEmpty()) { - return 0; - } - MaterialStack materialStack = OreDictUnifier.getMaterial(fuelType); - if (materialStack == null) { - //try alternative material names if we can't find valid standard one - materialStack = OreDictUnifier.getOreDictionaryNames(fuelType).stream() - .map(ALTERNATIVE_MATERIAL_NAMES::get) - .filter(Objects::nonNull) - .findFirst().orElse(null); - } - - if (materialStack != null && materialStack.amount >= GTValues.M) { - int materialAmount = (int) (materialStack.amount / GTValues.M); - Float materialMultiplier = MATERIAL_FUEL_MAP.get(materialStack.material); - return materialMultiplier == null ? 0 : materialAmount * materialMultiplier; - } - return 0; - } - - public static List getDisplayFuelsForRecipe(int recipeFuelUnits) { - ArrayList resultStacks = new ArrayList<>(); - - for (OrePrefix orePrefix : FUEL_DISPLAY_PREFIXES) { - int materialAmount = (int) (orePrefix.materialAmount / GTValues.M); - for (Material fuelMaterial : MATERIAL_FUEL_MAP.keySet()) { - float materialMultiplier = MATERIAL_FUEL_MAP.get(fuelMaterial); - float materialFuelUnits = materialAmount * materialMultiplier; - int stackSize = (int) Math.ceil(recipeFuelUnits / materialFuelUnits); - - List materialStacks = OreDictUnifier.getAll(new UnificationEntry(orePrefix, fuelMaterial)); - for (ItemStack materialStack : materialStacks) { - materialStack.setCount(stackSize); - resultStacks.add(materialStack); - } - } - } - - for (String specialFuelName : ALTERNATIVE_MATERIAL_NAMES.keySet()) { - List allItemStacks = OreDictUnifier.getAllWithOreDictionaryName(specialFuelName); - MaterialStack materialStack = ALTERNATIVE_MATERIAL_NAMES.get(specialFuelName); - int materialAmount = (int) (materialStack.amount / GTValues.M); - float materialMultiplier = MATERIAL_FUEL_MAP.getOrDefault(materialStack.material, 0.0f); - float materialFuelUnits = materialAmount * materialMultiplier; - int stackSize = (int) Math.ceil(recipeFuelUnits / materialFuelUnits); - - for (ItemStack itemStack : allItemStacks) { - itemStack.setCount(stackSize); - resultStacks.add(itemStack); - } - } - - //de-duplicate items in the result list - int currentIndex = 0; - loop: - while (currentIndex < resultStacks.size()) { - ItemStack itemStack = resultStacks.get(currentIndex); - - for (int i = 0; i < currentIndex; i++) { - ItemStack otherStack = resultStacks.get(i); - if (ItemStack.areItemsEqual(itemStack, otherStack)) { - resultStacks.remove(currentIndex); //remove duplicate item - continue loop; - } - } - //increment index only if we didn't remove item - currentIndex++; - } - - return resultStacks; - } - - public static ItemStack getAshForRecipeFuelConsumption(int fuelUnitsConsumed) { - int ashAmount = MathHelper.clamp(1 + fuelUnitsConsumed, 2, 8); - return OreDictUnifier.get(OrePrefix.dustTiny, Materials.DarkAsh, ashAmount); - } - - protected IBlockState getCasingState() { - return MetaBlocks.METAL_CASING.getState(MetalCasingType.PRIMITIVE_BRICKS); - } - - @Override - public ICubeRenderer getBaseTexture(IMultiblockPart sourcePart) { - return Textures.PRIMITIVE_BRICKS; - } - - @Override - public void renderMetaTileEntity(CCRenderState renderState, Matrix4 translation, IVertexOperation[] pipeline) { - super.renderMetaTileEntity(renderState, translation, pipeline); - Textures.PRIMITIVE_BLAST_FURNACE_OVERLAY.render(renderState, translation, pipeline, getFrontFacing(), isActive()); - if (isActive() && isStructureFormed()) { - EnumFacing back = getFrontFacing().getOpposite(); - Matrix4 offset = translation.copy().translate(back.getXOffset(), -0.3, back.getZOffset()); - TextureAtlasSprite sprite = TextureUtils.getBlockTexture("lava_still"); - renderState.brightness = 0xF000F0; - renderState.colour = 0xFFFFFFFF; - Textures.renderFace(renderState, offset, new IVertexOperation[0], EnumFacing.UP, Cuboid6.full, sprite); - } - } - - @Override - protected void initializeInventory() { - super.initializeInventory(); - ItemStackHandler emptyHandler = new ItemStackHandler(0); - this.itemInventory = new ItemHandlerProxy(emptyHandler, emptyHandler); - } - - @Override - protected IItemHandlerModifiable createImportItemHandler() { - return new ItemStackHandler(2) { - @Nonnull - @Override - public ItemStack insertItem(int slot, @Nonnull ItemStack stack, boolean simulate) { - if (slot == 1 && getFuelUnits(stack) == 0) - return stack; - return super.insertItem(slot, stack, simulate); - } - }; - } - - @Override - protected IItemHandlerModifiable createExportItemHandler() { - return new ItemStackHandler(2); + public MetaTileEntity createMetaTileEntity(MetaTileEntityHolder holder) { + return new MetaTileEntityPrimitiveBlastFurnace(metaTileEntityId); } @Override @@ -383,30 +42,48 @@ protected BlockPattern createStructurePattern() { .aisle("XXX", "XXX", "XXX", "XXX") .aisle("XXX", "X#X", "X#X", "X#X") .aisle("XXX", "XYX", "XXX", "XXX") - .where('X', statePredicate(getCasingState())) + .where('X', statePredicate(MetaBlocks.METAL_CASING.getState(BlockMetalCasing.MetalCasingType.PRIMITIVE_BRICKS))) .where('#', isAirPredicate()) .where('Y', selfPredicate()) .build(); } @Override - public MetaTileEntity createMetaTileEntity(MetaTileEntityHolder holder) { - return new MetaTileEntityPrimitiveBlastFurnace(metaTileEntityId); + public ICubeRenderer getBaseTexture(IMultiblockPart sourcePart) { + return Textures.PRIMITIVE_BRICKS; + } + + @Override + public int getLightValueForPart(IMultiblockPart sourcePart) { + return sourcePart == null && recipeMapWorkable.isActive() ? 15 : 0; } @Override - protected ModularUI createUI(EntityPlayer entityPlayer) { + protected ModularUI.Builder createUITemplate(EntityPlayer entityPlayer) { return ModularUI.builder(GuiTextures.BACKGROUND, 176, 166) .widget(new SlotWidget(importItems, 0, 33, 15, true, true) .setBackgroundTexture(GuiTextures.SLOT, GuiTextures.INGOT_OVERLAY)) .widget(new SlotWidget(importItems, 1, 33, 33, true, true) .setBackgroundTexture(GuiTextures.SLOT, GuiTextures.FURNACE_OVERLAY)) - .progressBar(this::getProgressScaled, 58, 24, 20, 15, GuiTextures.BRONZE_BLAST_FURNACE_PROGRESS_BAR, MoveType.HORIZONTAL) + .progressBar(recipeMapWorkable::getProgressPercent, 58, 24, 20, 15, GuiTextures.BRONZE_BLAST_FURNACE_PROGRESS_BAR, ProgressWidget.MoveType.HORIZONTAL) .widget(new SlotWidget(exportItems, 0, 85, 24, true, false) .setBackgroundTexture(GuiTextures.SLOT, GuiTextures.INGOT_OVERLAY)) .widget(new SlotWidget(exportItems, 1, 103, 24, true, false) .setBackgroundTexture(GuiTextures.SLOT, GuiTextures.DUST_OVERLAY)) - .bindPlayerInventory(entityPlayer.inventory, GuiTextures.SLOT, 0) - .build(getHolder(), entityPlayer); + .bindPlayerInventory(entityPlayer.inventory, GuiTextures.SLOT, 0); + } + + @Override + public void renderMetaTileEntity(CCRenderState renderState, Matrix4 translation, IVertexOperation[] pipeline) { + super.renderMetaTileEntity(renderState, translation, pipeline); + Textures.PRIMITIVE_BLAST_FURNACE_OVERLAY.render(renderState, translation, pipeline, getFrontFacing(), recipeMapWorkable.isActive()); + if (recipeMapWorkable.isActive() && isStructureFormed()) { + EnumFacing back = getFrontFacing().getOpposite(); + Matrix4 offset = translation.copy().translate(back.getXOffset(), -0.3, back.getZOffset()); + TextureAtlasSprite sprite = TextureUtils.getBlockTexture("lava_still"); + renderState.brightness = 0xF000F0; + renderState.colour = 0xFFFFFFFF; + Textures.renderFace(renderState, offset, new IVertexOperation[0], EnumFacing.UP, Cuboid6.full, sprite); + } } } diff --git a/src/main/java/gregtech/common/metatileentities/multi/MetaTileEntityPrimitiveWaterPump.java b/src/main/java/gregtech/common/metatileentities/multi/MetaTileEntityPrimitiveWaterPump.java index 37b536dfa28..70e572ea29b 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/MetaTileEntityPrimitiveWaterPump.java +++ b/src/main/java/gregtech/common/metatileentities/multi/MetaTileEntityPrimitiveWaterPump.java @@ -24,11 +24,13 @@ import net.minecraft.entity.player.EntityPlayer; import net.minecraft.util.ResourceLocation; import net.minecraft.world.biome.*; +import net.minecraftforge.common.BiomeDictionary; import net.minecraftforge.fluids.FluidTank; import net.minecraftforge.fluids.IFluidTank; import javax.annotation.Nonnull; import java.util.List; +import java.util.Set; import java.util.function.Predicate; public class MetaTileEntityPrimitiveWaterPump extends MultiblockControllerBase { @@ -59,24 +61,23 @@ public void update() { } private static int getAmountForBiome(Biome biome) { - Class biomeClass = biome.getBiomeClass(); - if (biomeClass == BiomeOcean.class || biomeClass == BiomeRiver.class) { + Set biomeTypes = BiomeDictionary.getTypes(biome); + if (biomeTypes.contains(BiomeDictionary.Type.WATER)) { return 1000; - } else if (biomeClass == BiomeSwamp.class) { + } else if (biomeTypes.contains(BiomeDictionary.Type.SWAMP) || biomeTypes.contains(BiomeDictionary.Type.WET)) { return 800; - } else if (biomeClass == BiomeJungle.class) { + } else if (biomeTypes.contains(BiomeDictionary.Type.JUNGLE)) { return 350; - } else if (biomeClass == BiomeSnow.class) { + } else if (biomeTypes.contains(BiomeDictionary.Type.SNOWY)) { return 300; - } else if (biomeClass == BiomePlains.class || biomeClass == BiomeForest.class) { + } else if (biomeTypes.contains(BiomeDictionary.Type.PLAINS) || biomeTypes.contains(BiomeDictionary.Type.FOREST)) { return 250; - } else if (biomeClass == BiomeTaiga.class) { + } else if (biomeTypes.contains(BiomeDictionary.Type.COLD)) { return 175; - } else if (biomeClass == BiomeBeach.class) { + } else if (biomeTypes.contains(BiomeDictionary.Type.BEACH)) { return 170; - } else { - return 100; } + return 100; } @Override diff --git a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityAssemblyLine.java b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityAssemblyLine.java index 5b2252d30a5..ecd87ca6ef7 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityAssemblyLine.java +++ b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityAssemblyLine.java @@ -18,7 +18,7 @@ import net.minecraft.block.state.IBlockState; import net.minecraft.util.ResourceLocation; -import static gregtech.api.multiblock.BlockPattern.RelativeDirection.*; +import static gregtech.api.util.RelativeDirection.*; public class MetaTileEntityAssemblyLine extends RecipeMapMultiblockController { diff --git a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityDistillationTower.java b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityDistillationTower.java index 14ea2070d0c..d0026b920bf 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityDistillationTower.java +++ b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityDistillationTower.java @@ -17,15 +17,17 @@ import gregtech.common.blocks.MetaBlocks; import net.minecraft.block.state.IBlockState; import net.minecraft.util.ResourceLocation; +import net.minecraft.util.math.BlockPos; import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.TextComponentTranslation; import net.minecraftforge.fluids.FluidStack; import javax.annotation.Nonnull; import java.util.List; +import java.util.function.Function; import java.util.function.Predicate; -import static gregtech.api.multiblock.BlockPattern.RelativeDirection.*; +import static gregtech.api.util.RelativeDirection.*; public class MetaTileEntityDistillationTower extends RecipeMapMultiblockController { @@ -38,6 +40,11 @@ public MetaTileEntity createMetaTileEntity(MetaTileEntityHolder holder) { return new MetaTileEntityDistillationTower(metaTileEntityId); } + @Override + protected Function multiblockPartSorter() { + return BlockPos::getY; // todo this needs to be "relative up" with Freedom Wrench + } + @Override protected void addDisplayText(List textList) { if (isStructureFormed()) { diff --git a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityFusionReactor.java b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityFusionReactor.java index 3327aaa5343..579f5a69471 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityFusionReactor.java +++ b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityFusionReactor.java @@ -34,7 +34,7 @@ import java.util.List; -import static gregtech.api.multiblock.BlockPattern.RelativeDirection.*; +import static gregtech.api.util.RelativeDirection.*; public class MetaTileEntityFusionReactor extends RecipeMapMultiblockController { @@ -199,6 +199,10 @@ public void renderMetaTileEntity(CCRenderState renderState, Matrix4 translation, Textures.FUSION_REACTOR_OVERLAY.render(renderState, translation, pipeline, this.getFrontFacing(), this.recipeMapWorkable.isActive()); } + public long getHeat() { + return heat; + } + private class FusionRecipeLogic extends MultiblockRecipeLogic { public FusionRecipeLogic(MetaTileEntityFusionReactor tileEntity) { diff --git a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityMultiFurnace.java b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityMultiFurnace.java index a6b167be7df..2cabbc60431 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityMultiFurnace.java +++ b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityMultiFurnace.java @@ -119,25 +119,28 @@ protected void trySearchNewRecipe() { Recipe currentRecipe = null; IItemHandlerModifiable importInventory = getInputInventory(); IMultipleTankHandler importFluids = getInputTank(); - boolean dirty = checkRecipeInputsDirty(importInventory, importFluids); + //inverse of logic in normal AbstractRecipeLogic //for MultiSmelter, we can reuse previous recipe if inputs didn't change //otherwise, we need to recompute it for new ingredients //but technically, it means we can cache multi smelter recipe, but changing inputs have more priority - if (dirty || forceRecipeRecheck) { - this.forceRecipeRecheck = false; - //else, try searching new recipe for given inputs - currentRecipe = findRecipe(maxVoltage, importInventory, importFluids, MatchingMode.DEFAULT); - if (currentRecipe != null) { - this.previousRecipe = currentRecipe; - } - } else if (previousRecipe != null && previousRecipe.matches(false, importInventory, importFluids)) { + if (hasNotifiedInputs() || + previousRecipe == null || + !previousRecipe.matches(false, importInventory, importFluids)) { + //Inputs changed, try searching new recipe for given inputs + currentRecipe = findRecipe(maxVoltage, importInventory, importFluids, MatchingMode.IGNORE_FLUIDS); + } else { //if previous recipe still matches inputs, try to use it currentRecipe = previousRecipe; } - if (currentRecipe != null && setupAndConsumeRecipeInputs(currentRecipe)) { + if (currentRecipe != null) + // replace old recipe with new one + this.previousRecipe = currentRecipe; + // proceed if we have a usable recipe. + if (currentRecipe != null && setupAndConsumeRecipeInputs(currentRecipe)) setupRecipe(currentRecipe); - } + // Inputs have been inspected. + metaTileEntity.getNotifiedItemInputList().clear(); } @Override @@ -152,7 +155,10 @@ protected Recipe findRecipe(long maxVoltage, /* Iterate over the input items looking for more things to add until we run either out of input items * or we have exceeded the number of items permissible from the smelting bonus */ - for (int index = 0; index < inputs.getSlots() && currentItemsEngaged < maxItemsLimit; index++) { + boolean matchedRecipe = false; + boolean canFitOutputs = true; + + for(int index = 0; index < inputs.getSlots() && currentItemsEngaged < maxItemsLimit; index++) { // Skip this slot if it is empty. final ItemStack currentInputItem = inputs.getStackInSlot(index); @@ -164,8 +170,10 @@ protected Recipe findRecipe(long maxVoltage, Collections.singletonList(currentInputItem), Collections.emptyList(), 0, MatchingMode.DEFAULT); CountableIngredient inputIngredient; - if (matchingRecipe != null) + if(matchingRecipe != null) { inputIngredient = matchingRecipe.getInputs().get(0); + matchedRecipe = true; + } else continue; @@ -192,7 +200,7 @@ protected Recipe findRecipe(long maxVoltage, computeOutputItemStacks(temp, matchingRecipe.getOutputs().get(0), recipeMultiplier); // determine if there is enough room in the output to fit all of this - boolean canFitOutputs = InventoryUtils.simulateItemStackMerge(temp, this.getOutputInventory()); + canFitOutputs = InventoryUtils.simulateItemStackMerge(temp, this.getOutputInventory()); // if there isn't, we can't process this recipe. if (!canFitOutputs) @@ -210,10 +218,10 @@ protected Recipe findRecipe(long maxVoltage, } } - // If there were no accepted ingredients, then there is no recipe to process. + this.invalidInputsForRecipes = !matchedRecipe; + this.isOutputsFull = !canFitOutputs; + if (recipeInputs.isEmpty()) { - //Set here to prevent recipe deadlock on world load with full output bus - forceRecipeRecheck = true; return null; } diff --git a/src/main/java/gregtech/common/metatileentities/multi/electric/generator/MetaTileEntityLargeTurbine.java b/src/main/java/gregtech/common/metatileentities/multi/electric/generator/MetaTileEntityLargeTurbine.java index f10c7c03e47..9dc6beef80a 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/electric/generator/MetaTileEntityLargeTurbine.java +++ b/src/main/java/gregtech/common/metatileentities/multi/electric/generator/MetaTileEntityLargeTurbine.java @@ -119,6 +119,10 @@ protected void addDisplayText(List textList) { MIN_DURABILITY_TO_WARN, rotorDurability).setStyle(new Style().setColor(TextFormatting.RED))); } } + if(!isRotorFaceFree()) { + textList.add(new TextComponentTranslation("gregtech.multiblock.turbine.obstructed") + .setStyle(new Style().setColor(TextFormatting.RED))); + } } super.addDisplayText(textList); } diff --git a/src/main/java/gregtech/common/metatileentities/multi/steam/MetaTileEntitySteamGrinder.java b/src/main/java/gregtech/common/metatileentities/multi/steam/MetaTileEntitySteamGrinder.java index 0e89567ccb7..6750edbb07e 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/steam/MetaTileEntitySteamGrinder.java +++ b/src/main/java/gregtech/common/metatileentities/multi/steam/MetaTileEntitySteamGrinder.java @@ -3,7 +3,7 @@ import codechicken.lib.render.CCRenderState; import codechicken.lib.render.pipeline.IVertexOperation; import codechicken.lib.vec.Matrix4; -import gregtech.api.capability.impl.RecipeMapSteamMultiblockController; +import gregtech.api.metatileentity.multiblock.RecipeMapSteamMultiblockController; import gregtech.api.capability.impl.SteamMultiWorkable; import gregtech.api.metatileentity.MetaTileEntity; import gregtech.api.metatileentity.MetaTileEntityHolder; @@ -25,8 +25,6 @@ public class MetaTileEntitySteamGrinder extends RecipeMapSteamMultiblockController { - private static final double CONVERSION_RATE = ConfigHolder.multiblockSteamtoEU; - private static final MultiblockAbility[] ALLOWED_ABILITIES = { MultiblockAbility.STEAM_IMPORT_ITEMS, MultiblockAbility.STEAM_EXPORT_ITEMS, MultiblockAbility.STEAM }; @@ -56,12 +54,12 @@ protected BlockPattern createStructurePattern() { } public IBlockState getCasingState() { - return ConfigHolder.steelSteamMultiblocks ? MetaBlocks.METAL_CASING.getState(BlockMetalCasing.MetalCasingType.STEEL_SOLID) : MetaBlocks.METAL_CASING.getState(BlockMetalCasing.MetalCasingType.BRONZE_BRICKS); + return ConfigHolder.U.steelSteamMultiblocks ? MetaBlocks.METAL_CASING.getState(BlockMetalCasing.MetalCasingType.STEEL_SOLID) : MetaBlocks.METAL_CASING.getState(BlockMetalCasing.MetalCasingType.BRONZE_BRICKS); } @Override public ICubeRenderer getBaseTexture(IMultiblockPart sourcePart) { - return ConfigHolder.steelSteamMultiblocks ? SOLID_STEEL_CASING : BRONZE_PLATED_BRICKS; + return ConfigHolder.U.steelSteamMultiblocks ? SOLID_STEEL_CASING : BRONZE_PLATED_BRICKS; } @Override diff --git a/src/main/java/gregtech/common/metatileentities/multi/steam/MetaTileEntitySteamOven.java b/src/main/java/gregtech/common/metatileentities/multi/steam/MetaTileEntitySteamOven.java index 067dccf0ffa..535a4f5bd1c 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/steam/MetaTileEntitySteamOven.java +++ b/src/main/java/gregtech/common/metatileentities/multi/steam/MetaTileEntitySteamOven.java @@ -4,7 +4,7 @@ import codechicken.lib.render.CCRenderState; import codechicken.lib.render.pipeline.IVertexOperation; import codechicken.lib.vec.Matrix4; -import gregtech.api.capability.impl.RecipeMapSteamMultiblockController; +import gregtech.api.metatileentity.multiblock.RecipeMapSteamMultiblockController; import gregtech.api.capability.impl.SteamMultiWorkable; import gregtech.api.metatileentity.MetaTileEntity; import gregtech.api.metatileentity.MetaTileEntityHolder; @@ -27,7 +27,6 @@ public class MetaTileEntitySteamOven extends RecipeMapSteamMultiblockController { - private static final double CONVERSION_RATE = ConfigHolder.multiblockSteamtoEU; private boolean isActive; public MetaTileEntitySteamOven(ResourceLocation metaTileEntityId) { @@ -71,13 +70,13 @@ protected BlockPattern createStructurePattern() { } public IBlockState getCasingState() { - return ConfigHolder.steelSteamMultiblocks ? + return ConfigHolder.U.steelSteamMultiblocks ? MetaBlocks.METAL_CASING.getState(BlockMetalCasing.MetalCasingType.STEEL_SOLID) : MetaBlocks.METAL_CASING.getState(BlockMetalCasing.MetalCasingType.BRONZE_BRICKS); } public IBlockState getFireboxState() { - return ConfigHolder.steelSteamMultiblocks ? + return ConfigHolder.U.steelSteamMultiblocks ? MetaBlocks.BOILER_FIREBOX_CASING.getState(BlockFireboxCasing.FireboxCasingType.STEEL_FIREBOX) : MetaBlocks.BOILER_FIREBOX_CASING.getState(BlockFireboxCasing.FireboxCasingType.BRONZE_FIREBOX); } @@ -88,7 +87,7 @@ private boolean isFireboxPart(IMultiblockPart sourcePart) { @Override public ICubeRenderer getBaseTexture(IMultiblockPart sourcePart) { - if (ConfigHolder.steelSteamMultiblocks) { + if (ConfigHolder.U.steelSteamMultiblocks) { if (sourcePart != null && isFireboxPart(sourcePart)) { return isActive ? Textures.STEEL_FIREBOX_ACTIVE : Textures.STEEL_FIREBOX; } diff --git a/src/main/java/gregtech/common/metatileentities/steam/SteamAlloySmelter.java b/src/main/java/gregtech/common/metatileentities/steam/SteamAlloySmelter.java index e89739a8bdb..37db0e5cdf9 100644 --- a/src/main/java/gregtech/common/metatileentities/steam/SteamAlloySmelter.java +++ b/src/main/java/gregtech/common/metatileentities/steam/SteamAlloySmelter.java @@ -1,5 +1,6 @@ package gregtech.common.metatileentities.steam; +import gregtech.api.capability.impl.NotifiableItemStackHandler; import gregtech.api.gui.ModularUI; import gregtech.api.gui.resources.TextureArea; import gregtech.api.gui.widgets.ProgressWidget; @@ -13,7 +14,6 @@ import net.minecraft.entity.player.EntityPlayer; import net.minecraft.util.ResourceLocation; import net.minecraftforge.items.IItemHandlerModifiable; -import net.minecraftforge.items.ItemStackHandler; public class SteamAlloySmelter extends SteamMetaTileEntity { @@ -32,13 +32,13 @@ protected boolean isBrickedCasing() { } @Override - public IItemHandlerModifiable createImportItemHandler() { - return new ItemStackHandler(2); + protected IItemHandlerModifiable createImportItemHandler() { + return new NotifiableItemStackHandler(2, this, false); } @Override - public IItemHandlerModifiable createExportItemHandler() { - return new ItemStackHandler(1); + protected IItemHandlerModifiable createExportItemHandler() { + return new NotifiableItemStackHandler(1, this, true); } @Override diff --git a/src/main/java/gregtech/common/metatileentities/steam/SteamCompressor.java b/src/main/java/gregtech/common/metatileentities/steam/SteamCompressor.java index 13ba51831cc..e016557810d 100644 --- a/src/main/java/gregtech/common/metatileentities/steam/SteamCompressor.java +++ b/src/main/java/gregtech/common/metatileentities/steam/SteamCompressor.java @@ -1,5 +1,6 @@ package gregtech.common.metatileentities.steam; +import gregtech.api.capability.impl.NotifiableItemStackHandler; import gregtech.api.gui.ModularUI; import gregtech.api.gui.widgets.ProgressWidget; import gregtech.api.gui.widgets.ProgressWidget.MoveType; @@ -12,7 +13,6 @@ import net.minecraft.entity.player.EntityPlayer; import net.minecraft.util.ResourceLocation; import net.minecraftforge.items.IItemHandlerModifiable; -import net.minecraftforge.items.ItemStackHandler; public class SteamCompressor extends SteamMetaTileEntity { @@ -26,13 +26,13 @@ public MetaTileEntity createMetaTileEntity(MetaTileEntityHolder holder) { } @Override - public IItemHandlerModifiable createImportItemHandler() { - return new ItemStackHandler(1); + protected IItemHandlerModifiable createImportItemHandler() { + return new NotifiableItemStackHandler(1, this, false); } @Override - public IItemHandlerModifiable createExportItemHandler() { - return new ItemStackHandler(1); + protected IItemHandlerModifiable createExportItemHandler() { + return new NotifiableItemStackHandler(1, this, true); } @Override diff --git a/src/main/java/gregtech/common/metatileentities/steam/SteamExtractor.java b/src/main/java/gregtech/common/metatileentities/steam/SteamExtractor.java index 02174e5a6dc..f17942fbeb7 100644 --- a/src/main/java/gregtech/common/metatileentities/steam/SteamExtractor.java +++ b/src/main/java/gregtech/common/metatileentities/steam/SteamExtractor.java @@ -1,5 +1,6 @@ package gregtech.common.metatileentities.steam; +import gregtech.api.capability.impl.NotifiableItemStackHandler; import gregtech.api.gui.ModularUI; import gregtech.api.gui.widgets.ProgressWidget; import gregtech.api.gui.widgets.SlotWidget; @@ -11,7 +12,6 @@ import net.minecraft.entity.player.EntityPlayer; import net.minecraft.util.ResourceLocation; import net.minecraftforge.items.IItemHandlerModifiable; -import net.minecraftforge.items.ItemStackHandler; public class SteamExtractor extends SteamMetaTileEntity { @@ -25,13 +25,13 @@ public MetaTileEntity createMetaTileEntity(MetaTileEntityHolder holder) { } @Override - public IItemHandlerModifiable createImportItemHandler() { - return new ItemStackHandler(1); + protected IItemHandlerModifiable createImportItemHandler() { + return new NotifiableItemStackHandler(1, this, false); } @Override - public IItemHandlerModifiable createExportItemHandler() { - return new ItemStackHandler(1); + protected IItemHandlerModifiable createExportItemHandler() { + return new NotifiableItemStackHandler(1, this, true); } @Override diff --git a/src/main/java/gregtech/common/metatileentities/steam/SteamFurnace.java b/src/main/java/gregtech/common/metatileentities/steam/SteamFurnace.java index 1e42b622935..68305c610bd 100644 --- a/src/main/java/gregtech/common/metatileentities/steam/SteamFurnace.java +++ b/src/main/java/gregtech/common/metatileentities/steam/SteamFurnace.java @@ -1,5 +1,6 @@ package gregtech.common.metatileentities.steam; +import gregtech.api.capability.impl.NotifiableItemStackHandler; import gregtech.api.gui.ModularUI; import gregtech.api.gui.widgets.ProgressWidget; import gregtech.api.gui.widgets.ProgressWidget.MoveType; @@ -12,7 +13,6 @@ import net.minecraft.entity.player.EntityPlayer; import net.minecraft.util.ResourceLocation; import net.minecraftforge.items.IItemHandlerModifiable; -import net.minecraftforge.items.ItemStackHandler; public class SteamFurnace extends SteamMetaTileEntity { @@ -31,13 +31,13 @@ protected boolean isBrickedCasing() { } @Override - public IItemHandlerModifiable createImportItemHandler() { - return new ItemStackHandler(1); + protected IItemHandlerModifiable createImportItemHandler() { + return new NotifiableItemStackHandler(1, this, false); } @Override - public IItemHandlerModifiable createExportItemHandler() { - return new ItemStackHandler(1); + protected IItemHandlerModifiable createExportItemHandler() { + return new NotifiableItemStackHandler(1, this, true); } @Override diff --git a/src/main/java/gregtech/common/metatileentities/steam/SteamHammer.java b/src/main/java/gregtech/common/metatileentities/steam/SteamHammer.java index 0af37c20400..c8a3bbc5a0f 100644 --- a/src/main/java/gregtech/common/metatileentities/steam/SteamHammer.java +++ b/src/main/java/gregtech/common/metatileentities/steam/SteamHammer.java @@ -1,5 +1,6 @@ package gregtech.common.metatileentities.steam; +import gregtech.api.capability.impl.NotifiableItemStackHandler; import gregtech.api.gui.ModularUI; import gregtech.api.gui.widgets.ImageWidget; import gregtech.api.gui.widgets.ProgressWidget; @@ -12,7 +13,6 @@ import net.minecraft.entity.player.EntityPlayer; import net.minecraft.util.ResourceLocation; import net.minecraftforge.items.IItemHandlerModifiable; -import net.minecraftforge.items.ItemStackHandler; public class SteamHammer extends SteamMetaTileEntity { @@ -26,13 +26,13 @@ public MetaTileEntity createMetaTileEntity(MetaTileEntityHolder holder) { } @Override - public IItemHandlerModifiable createImportItemHandler() { - return new ItemStackHandler(1); + protected IItemHandlerModifiable createImportItemHandler() { + return new NotifiableItemStackHandler(1, this, false); } @Override - public IItemHandlerModifiable createExportItemHandler() { - return new ItemStackHandler(1); + protected IItemHandlerModifiable createExportItemHandler() { + return new NotifiableItemStackHandler(1, this, true); } @Override diff --git a/src/main/java/gregtech/common/metatileentities/steam/SteamMacerator.java b/src/main/java/gregtech/common/metatileentities/steam/SteamMacerator.java index 29e4264a570..9870187b1ff 100644 --- a/src/main/java/gregtech/common/metatileentities/steam/SteamMacerator.java +++ b/src/main/java/gregtech/common/metatileentities/steam/SteamMacerator.java @@ -1,5 +1,6 @@ package gregtech.common.metatileentities.steam; +import gregtech.api.capability.impl.NotifiableItemStackHandler; import gregtech.api.capability.impl.RecipeLogicSteam; import gregtech.api.gui.ModularUI; import gregtech.api.gui.widgets.ProgressWidget; @@ -12,7 +13,6 @@ import net.minecraft.entity.player.EntityPlayer; import net.minecraft.util.ResourceLocation; import net.minecraftforge.items.IItemHandlerModifiable; -import net.minecraftforge.items.ItemStackHandler; public class SteamMacerator extends SteamMetaTileEntity { @@ -28,13 +28,13 @@ public MetaTileEntity createMetaTileEntity(MetaTileEntityHolder holder) { } @Override - public IItemHandlerModifiable createImportItemHandler() { - return new ItemStackHandler(1); + protected IItemHandlerModifiable createImportItemHandler() { + return new NotifiableItemStackHandler(1, this, false); } @Override - public IItemHandlerModifiable createExportItemHandler() { - return new ItemStackHandler(1); + protected IItemHandlerModifiable createExportItemHandler() { + return new NotifiableItemStackHandler(1, this, true); } @Override diff --git a/src/main/java/gregtech/common/metatileentities/steam/boiler/SteamBoiler.java b/src/main/java/gregtech/common/metatileentities/steam/boiler/SteamBoiler.java index d6bd965a379..c0f180f3769 100644 --- a/src/main/java/gregtech/common/metatileentities/steam/boiler/SteamBoiler.java +++ b/src/main/java/gregtech/common/metatileentities/steam/boiler/SteamBoiler.java @@ -40,8 +40,6 @@ public abstract class SteamBoiler extends MetaTileEntity { private static final EnumFacing[] STEAM_PUSH_DIRECTIONS = ArrayUtils.add(EnumFacing.HORIZONTALS, EnumFacing.UP); - public static final int BOILING_CYCLE_LENGTH = 25; - public static final int HIGH_PRESSURE_BOILING_CYCLE_LENGTH = 10; public final TextureArea BRONZE_BACKGROUND_TEXTURE; public final TextureArea BRONZE_SLOT_BACKGROUND_TEXTURE; @@ -49,7 +47,6 @@ public abstract class SteamBoiler extends MetaTileEntity { public final TextureArea SLOT_FURNACE_BACKGROUND; protected final boolean isHighPressure; - protected final int baseSteamOutput; private final OrientedOverlayRenderer renderer; protected FluidTank waterFluidTank; @@ -65,11 +62,10 @@ public abstract class SteamBoiler extends MetaTileEntity { private boolean wasBurningAndNeedsUpdate; private final ItemStackHandler containerInventory; - public SteamBoiler(ResourceLocation metaTileEntityId, boolean isHighPressure, OrientedOverlayRenderer renderer, int baseSteamOutput) { + public SteamBoiler(ResourceLocation metaTileEntityId, boolean isHighPressure, OrientedOverlayRenderer renderer) { super(metaTileEntityId); this.renderer = renderer; this.isHighPressure = isHighPressure; - this.baseSteamOutput = baseSteamOutput; BRONZE_BACKGROUND_TEXTURE = getGuiTexture("%s_gui"); BRONZE_SLOT_BACKGROUND_TEXTURE = getGuiTexture("slot_%s"); SLOT_FURNACE_BACKGROUND = getGuiTexture("slot_%s_furnace_background"); @@ -155,7 +151,9 @@ public void update() { super.update(); if (!getWorld().isRemote) { updateCurrentTemperature(); - generateSteam(); + if (getOffsetTimer() % 10 == 0) { + generateSteam(); + } fillInternalTankFromFluidContainer(containerInventory, containerInventory, 0, 1); @@ -198,30 +196,28 @@ private void updateCurrentTemperature() { } else --timeBeforeCoolingDown; } + protected abstract int getBaseSteamOutput(); + private void generateSteam() { if (currentTemperature >= 100) { - if (getOffsetTimer() % getBoilingCycleLength() == 0) { - int fillAmount = (int) (baseSteamOutput * (currentTemperature / (getMaxTemperate() * 1.0))); - boolean hasDrainedWater = waterFluidTank.drain(1, true) != null; - int filledSteam = 0; - if (hasDrainedWater) { - filledSteam = steamFluidTank.fill(ModHandler.getSteam(fillAmount), true); - } - if (this.hasNoWater && hasDrainedWater) { - getWorld().setBlockToAir(getPos()); - getWorld().createExplosion(null, - getPos().getX() + 0.5, getPos().getY() + 0.5, getPos().getZ() + 0.5, - 2.0f, true); - } else this.hasNoWater = !hasDrainedWater; - if (filledSteam == 0 && hasDrainedWater) { - getWorld().playSound(null, getPos().getX() + 0.5, getPos().getY() + 0.5, getPos().getZ() + 0.5, - SoundEvents.BLOCK_LAVA_EXTINGUISH, SoundCategory.BLOCKS, 1.0f, 1.0f); - steamFluidTank.drain(4000, true); - } + int fillAmount = (int) (getBaseSteamOutput() * (currentTemperature / (getMaxTemperate() * 1.0)) / 2); + boolean hasDrainedWater = waterFluidTank.drain(1, true) != null; + int filledSteam = 0; + if (hasDrainedWater) { + filledSteam = steamFluidTank.fill(ModHandler.getSteam(fillAmount), true); } - } else { - this.hasNoWater = false; - } + if (this.hasNoWater && hasDrainedWater) { + getWorld().setBlockToAir(getPos()); + getWorld().createExplosion(null, + getPos().getX() + 0.5, getPos().getY() + 0.5, getPos().getZ() + 0.5, + 2.0f, true); + } else this.hasNoWater = !hasDrainedWater; + if (filledSteam == 0 && hasDrainedWater) { + getWorld().playSound(null, getPos().getX() + 0.5, getPos().getY() + 0.5, getPos().getZ() + 0.5, + SoundEvents.BLOCK_LAVA_EXTINGUISH, SoundCategory.BLOCKS, 1.0f, 1.0f); + steamFluidTank.drain(4000, true); + } + } else this.hasNoWater = false; } public boolean isBurning() { @@ -292,12 +288,8 @@ public ModularUI.Builder createUITemplate(EntityPlayer player) { .bindPlayerInventory(player.inventory, BRONZE_SLOT_BACKGROUND_TEXTURE, 0); } - private int getBoilingCycleLength() { - return isHighPressure ? HIGH_PRESSURE_BOILING_CYCLE_LENGTH : BOILING_CYCLE_LENGTH; - } - @Override public void addInformation(ItemStack stack, @Nullable World player, List tooltip, boolean advanced) { - tooltip.add(I18n.format("gregtech.machine.steam_boiler.tooltip_produces", baseSteamOutput, getBoilingCycleLength())); + tooltip.add(I18n.format("gregtech.machine.steam_boiler.tooltip_produces", getBaseSteamOutput())); } } diff --git a/src/main/java/gregtech/common/metatileentities/steam/boiler/SteamCoalBoiler.java b/src/main/java/gregtech/common/metatileentities/steam/boiler/SteamCoalBoiler.java index 5f1dad05ad7..183d0085f96 100755 --- a/src/main/java/gregtech/common/metatileentities/steam/boiler/SteamCoalBoiler.java +++ b/src/main/java/gregtech/common/metatileentities/steam/boiler/SteamCoalBoiler.java @@ -28,7 +28,7 @@ public class SteamCoalBoiler extends SteamBoiler implements IFuelable { public SteamCoalBoiler(ResourceLocation metaTileEntityId, boolean isHighPressure) { - super(metaTileEntityId, isHighPressure, Textures.COAL_BOILER_OVERLAY, 150); + super(metaTileEntityId, isHighPressure, Textures.COAL_BOILER_OVERLAY); } @Override @@ -36,6 +36,11 @@ public MetaTileEntity createMetaTileEntity(MetaTileEntityHolder holder) { return new SteamCoalBoiler(metaTileEntityId, isHighPressure); } + @Override + protected int getBaseSteamOutput() { + return isHighPressure ? 300 : 120; + } + @Override protected void tryConsumeNewFuel() { ItemStack fuelInSlot = importItems.extractItem(0, 1, true); diff --git a/src/main/java/gregtech/common/metatileentities/steam/boiler/SteamLavaBoiler.java b/src/main/java/gregtech/common/metatileentities/steam/boiler/SteamLavaBoiler.java index ec415879c7a..1b153ec85cd 100755 --- a/src/main/java/gregtech/common/metatileentities/steam/boiler/SteamLavaBoiler.java +++ b/src/main/java/gregtech/common/metatileentities/steam/boiler/SteamLavaBoiler.java @@ -27,7 +27,7 @@ public class SteamLavaBoiler extends SteamBoiler implements IFuelable { private FluidTank lavaFluidTank; public SteamLavaBoiler(ResourceLocation metaTileEntityId, boolean isHighPressure) { - super(metaTileEntityId, isHighPressure, Textures.LAVA_BOILER_OVERLAY, 100); + super(metaTileEntityId, isHighPressure, Textures.LAVA_BOILER_OVERLAY); } @Override @@ -35,6 +35,11 @@ public MetaTileEntity createMetaTileEntity(MetaTileEntityHolder holder) { return new SteamLavaBoiler(metaTileEntityId, isHighPressure); } + @Override + protected int getBaseSteamOutput() { + return isHighPressure ? 600 : 240; + } + @Override protected FluidTankList createImportFluidHandler() { FluidTankList superHandler = super.createImportFluidHandler(); @@ -44,7 +49,7 @@ protected FluidTankList createImportFluidHandler() { } - public static final int LAVA_PER_OPERATION = 100; + public static final int LAVA_PER_OPERATION = 100; // todo this may be too good? @Override protected void tryConsumeNewFuel() { @@ -71,7 +76,7 @@ public Collection getFuels() { return Collections.emptySet(); final int fuelRemaining = lava.amount; final int fuelCapacity = lavaFluidTank.getCapacity(); - final long burnTime = fuelRemaining * (this.isHighPressure ? 6 : 12); // 100 mb lasts 600 or 1200 ticks + final long burnTime = (long) fuelRemaining * (this.isHighPressure ? 6 : 12); // 100 mb lasts 600 or 1200 ticks return Collections.singleton(new FluidFuelInfo(lava, fuelRemaining, fuelCapacity, LAVA_PER_OPERATION, burnTime)); } diff --git a/src/main/java/gregtech/common/metatileentities/steam/boiler/SteamSolarBoiler.java b/src/main/java/gregtech/common/metatileentities/steam/boiler/SteamSolarBoiler.java index 3d44d8a9fa3..c906efd72e7 100644 --- a/src/main/java/gregtech/common/metatileentities/steam/boiler/SteamSolarBoiler.java +++ b/src/main/java/gregtech/common/metatileentities/steam/boiler/SteamSolarBoiler.java @@ -13,7 +13,7 @@ public class SteamSolarBoiler extends SteamBoiler { public SteamSolarBoiler(ResourceLocation metaTileEntityId, boolean isHighPressure) { - super(metaTileEntityId, isHighPressure, Textures.SOLAR_BOILER_OVERLAY, 55); + super(metaTileEntityId, isHighPressure, Textures.SOLAR_BOILER_OVERLAY); } @Override @@ -21,6 +21,11 @@ public MetaTileEntity createMetaTileEntity(MetaTileEntityHolder holder) { return new SteamSolarBoiler(metaTileEntityId, isHighPressure); } + @Override + protected int getBaseSteamOutput() { + return isHighPressure ? 360 : 120; + } + protected boolean checkCanSeeSun() { BlockPos blockPos = getPos().up(); if (!getWorld().canBlockSeeSky(blockPos)) diff --git a/src/main/java/gregtech/common/metatileentities/steam/multiblockpart/MetaTileEntitySteamHatch.java b/src/main/java/gregtech/common/metatileentities/steam/multiblockpart/MetaTileEntitySteamHatch.java index e2ac1f3d5da..4489b2d4ccb 100644 --- a/src/main/java/gregtech/common/metatileentities/steam/multiblockpart/MetaTileEntitySteamHatch.java +++ b/src/main/java/gregtech/common/metatileentities/steam/multiblockpart/MetaTileEntitySteamHatch.java @@ -137,7 +137,7 @@ public void renderMetaTileEntity(CCRenderState renderState, Matrix4 translation, public ICubeRenderer getBaseTexture() { MultiblockControllerBase controller = getController(); if (controller == null) - return ConfigHolder.steelSteamMultiblocks ? Textures.SOLID_STEEL_CASING : Textures.BRONZE_PLATED_BRICKS; + return ConfigHolder.U.steelSteamMultiblocks ? Textures.SOLID_STEEL_CASING : Textures.BRONZE_PLATED_BRICKS; return controller.getBaseTexture(this); } diff --git a/src/main/java/gregtech/common/metatileentities/steam/multiblockpart/MetaTileEntitySteamItemBus.java b/src/main/java/gregtech/common/metatileentities/steam/multiblockpart/MetaTileEntitySteamItemBus.java index ce0a1fad472..d157030cbc5 100644 --- a/src/main/java/gregtech/common/metatileentities/steam/multiblockpart/MetaTileEntitySteamItemBus.java +++ b/src/main/java/gregtech/common/metatileentities/steam/multiblockpart/MetaTileEntitySteamItemBus.java @@ -53,7 +53,7 @@ public void registerAbilities(List abilityList) { public ICubeRenderer getBaseTexture() { MultiblockControllerBase controller = getController(); if (controller == null) - return ConfigHolder.steelSteamMultiblocks ? Textures.SOLID_STEEL_CASING : Textures.BRONZE_PLATED_BRICKS; + return ConfigHolder.U.steelSteamMultiblocks ? Textures.SOLID_STEEL_CASING : Textures.BRONZE_PLATED_BRICKS; return controller.getBaseTexture(this); } diff --git a/src/main/java/gregtech/common/metatileentities/storage/CachedRecipeData.java b/src/main/java/gregtech/common/metatileentities/storage/CachedRecipeData.java index f1830831f9f..0c4b39775c3 100755 --- a/src/main/java/gregtech/common/metatileentities/storage/CachedRecipeData.java +++ b/src/main/java/gregtech/common/metatileentities/storage/CachedRecipeData.java @@ -61,15 +61,17 @@ public boolean performRecipe(EntityPlayer player) { return true; } - public boolean attemptMatchRecipe() { - this.ingredientsMatched = false; + public short attemptMatchRecipe() { + ingredientsMatched = true; + short itemsFound = 0; this.requiredItems.clear(); for (int i = 0; i < inventory.getSizeInventory(); i++) { - if (!getIngredientEquivalent(i)) - return false; //ingredient didn't match, return false + if (getIngredientEquivalent(i)) + itemsFound += 1 << i; //ingredient was found, and indicate in the short of this fact + else + ingredientsMatched = false; } - this.ingredientsMatched = true; - return true; + return itemsFound; } public boolean checkRecipeValid() { @@ -96,12 +98,12 @@ private boolean consumeRecipeItems(boolean simulate) { return true; } - private boolean getIngredientEquivalent(int slot) { + public boolean getIngredientEquivalent(int slot) { ItemStack currentStack = inventory.getStackInSlot(slot); if (currentStack.isEmpty()) { return true; //stack is empty, nothing to return } - ItemStackKey currentStackKey = new ItemStackKey(currentStack); + ItemStackKey currentStackKey = new ItemStackKey(currentStack.copy()); if (simulateExtractItem(currentStackKey)) { //we can extract ingredient equal to the one in the crafting grid, //so just return it without searching equivalent @@ -119,6 +121,7 @@ private boolean getIngredientEquivalent(int slot) { return true; } } + inventory.setInventorySlotContents(slot, currentStack); } //nothing matched, so return null return false; diff --git a/src/main/java/gregtech/common/metatileentities/storage/CraftingRecipeResolver.java b/src/main/java/gregtech/common/metatileentities/storage/CraftingRecipeResolver.java index 7c741171bf5..f1a074915a7 100644 --- a/src/main/java/gregtech/common/metatileentities/storage/CraftingRecipeResolver.java +++ b/src/main/java/gregtech/common/metatileentities/storage/CraftingRecipeResolver.java @@ -31,7 +31,6 @@ public class CraftingRecipeResolver { private final InventoryCrafting inventoryCrafting = new InventoryCrafting(new DummyContainer(), 3, 3); private IRecipe cachedRecipe = null; private final IInventory craftingResultInventory = new InventoryCraftResult(); - private long timer = 0L; private CachedRecipeData cachedRecipeData = null; private int itemsCrafted = 0; private final CraftingRecipeMemory recipeMemory; @@ -151,16 +150,13 @@ private void updateCurrentRecipe() { } public void update() { - //update item sources every second, it is enough + //update item sources every tick for fast tinting updates //if they are being modified, they will update themselves anyway - if (timer % 20 == 0L) { - this.itemSourceList.update(); - } + this.itemSourceList.update(); //update crafting inventory state if (updateInventoryCrafting()) { updateCurrentRecipe(); } - this.timer++; } public void checkNeighbourInventories(BlockPos blockPos) { @@ -169,4 +165,8 @@ public void checkNeighbourInventories(BlockPos blockPos) { this.itemSourceList.addItemHandler(itemSource); } } + + public CachedRecipeData getCachedRecipeData() { + return this.cachedRecipeData; + } } diff --git a/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityBuffer.java b/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityBuffer.java new file mode 100644 index 00000000000..be260046035 --- /dev/null +++ b/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityBuffer.java @@ -0,0 +1,134 @@ +package gregtech.common.metatileentities.storage; + +import codechicken.lib.render.CCRenderState; +import codechicken.lib.render.pipeline.ColourMultiplier; +import codechicken.lib.render.pipeline.IVertexOperation; +import codechicken.lib.vec.Matrix4; +import gregtech.api.capability.impl.FilteredFluidHandler; +import gregtech.api.capability.impl.FluidTankList; +import gregtech.api.gui.GuiTextures; +import gregtech.api.gui.ModularUI; +import gregtech.api.gui.widgets.TankWidget; +import gregtech.api.metatileentity.ITieredMetaTileEntity; +import gregtech.api.metatileentity.MetaTileEntity; +import gregtech.api.metatileentity.MetaTileEntityHolder; +import gregtech.api.render.Textures; +import gregtech.api.util.GTUtility; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +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.EnumFacing; +import net.minecraft.util.ResourceLocation; +import net.minecraft.world.World; +import net.minecraftforge.items.ItemStackHandler; +import org.apache.commons.lang3.ArrayUtils; +import org.apache.commons.lang3.tuple.Pair; + +import javax.annotation.Nullable; +import java.util.List; + +public class MetaTileEntityBuffer extends MetaTileEntity implements ITieredMetaTileEntity { + + private final int tier; + + private FluidTankList fluidTankList; + private ItemStackHandler itemStackHandler; + + public MetaTileEntityBuffer(ResourceLocation metaTileEntityId, int tier) { + super(metaTileEntityId); + this.tier = tier; + initializeInventory(); + } + + @Override + protected void initializeInventory() { + super.initializeInventory(); + FilteredFluidHandler[] fluidHandlers = new FilteredFluidHandler[tier + 2]; + for (int i = 0; i < tier + 2; i++) { + fluidHandlers[i] = new FilteredFluidHandler(64000); + } + fluidInventory = fluidTankList = new FluidTankList(false, fluidHandlers); + itemInventory = itemStackHandler = new ItemStackHandler((int)Math.pow(tier + 2, 2)); + } + + @Override + public MetaTileEntity createMetaTileEntity(MetaTileEntityHolder holder) { + return new MetaTileEntityBuffer(metaTileEntityId, tier); + } + + @Override + public Pair getParticleTexture() { + return Pair.of(Textures.VOLTAGE_CASINGS[tier].getParticleSprite(), this.getPaintingColor()); + } + + @Override + protected ModularUI createUI(EntityPlayer entityPlayer) { + int invTier = tier + 2; + ModularUI.Builder builder = ModularUI.builder(GuiTextures.BACKGROUND, + 176, Math.max(166, 18 + 18 * invTier + 94));//176, 166 + for (int i = 0; i < this.fluidTankList.getTanks(); i++) { + builder.widget(new TankWidget(this.fluidTankList.getTankAt(i), 176 - 8 - 18, 18 + 18 * i, 18, 18) + .setAlwaysShowFull(true) + .setBackgroundTexture(GuiTextures.FLUID_SLOT) + .setContainerClicking(true, true)); + } + for (int y = 0; y < invTier; y++) { + for (int x = 0; x < invTier; x++) { + int index = y * invTier + x; + builder.slot(itemStackHandler, index, 8 + x * 18, 18 + y * 18, GuiTextures.SLOT); + } + } + return builder.label(6, 6, getMetaFullName()) + .bindPlayerInventory(entityPlayer.inventory, GuiTextures.SLOT, 8, 18 + 18 * invTier + 12) + .build(getHolder(), entityPlayer); + } + + @Override + public int getTier() { + return tier; + } + + @Override + public void renderMetaTileEntity(CCRenderState renderState, Matrix4 translation, IVertexOperation[] pipeline) { + Textures.VOLTAGE_CASINGS[tier].render(renderState, translation, ArrayUtils.add(pipeline, + new ColourMultiplier(GTUtility.convertRGBtoOpaqueRGBA_CL(getPaintingColorForRendering())))); + for (EnumFacing facing : EnumFacing.VALUES) { + Textures.BUFFER_OVERLAY.renderSided(facing, renderState, translation, pipeline); + } + } + + @Override + public NBTTagCompound writeToNBT(NBTTagCompound tag) { + super.writeToNBT(tag); + tag.setTag("Inventory", itemStackHandler.serializeNBT()); + tag.setTag("FluidInventory", fluidTankList.serializeNBT()); + return tag; + } + + @Override + public void readFromNBT(NBTTagCompound tag) { + super.readFromNBT(tag); + this.itemStackHandler.deserializeNBT(tag.getCompoundTag("Inventory")); + this.fluidTankList.deserializeNBT(tag.getCompoundTag("FluidInventory")); + } + + @Override + protected boolean shouldSerializeInventories() { + return false; + } + + @Override + public boolean hasFrontFacing() { + return false; + } + + @Override + public void addInformation(ItemStack stack, @Nullable World player, List tooltip, boolean advanced) { + super.addInformation(stack, player, tooltip, advanced); + tooltip.add(I18n.format("gregtech.machine.buffer.tooltip")); + tooltip.add(I18n.format("gregtech.machine.buffer.inventory", (int)Math.pow(tier + 2, 2))); + tooltip.add(I18n.format("gregtech.machine.buffer.tanks", tier + 2)); + } +} diff --git a/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityCrate.java b/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityCrate.java index 7da197c3cda..9d53072f882 100644 --- a/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityCrate.java +++ b/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityCrate.java @@ -111,11 +111,12 @@ public void renderMetaTileEntity(CCRenderState renderState, Matrix4 translation, @Override protected ModularUI createUI(EntityPlayer entityPlayer) { - Builder builder = ModularUI.builder(GuiTextures.BACKGROUND, 338, 8 + inventorySize + 104).label(5, 5, getMetaFullName()); + int factor = inventorySize / 9 > 8 ? 18 : 9; + Builder builder = ModularUI.builder(GuiTextures.BACKGROUND, 176 + (factor == 18 ? 176 : 0), 8 + inventorySize / factor * 18 + 104).label(5, 5, getMetaFullName()); for (int i = 0; i < inventorySize; i++) { - builder.slot(inventory, i, 8 + i % 18 * 18, 18 + i / 18 * 18, GuiTextures.SLOT); + builder.slot(inventory, i, 7 * (factor == 18 ? 2 : 1) + i % factor * 18, 18 + i / factor * 18, GuiTextures.SLOT); } - builder.bindPlayerInventory(entityPlayer.inventory, GuiTextures.SLOT, 90, 18 + inventorySize + 12); + builder.bindPlayerInventory(entityPlayer.inventory, GuiTextures.SLOT, 7 + (factor == 18 ? 88 : 0), 18 + inventorySize / factor * 18 + 11); return builder.build(getHolder(), entityPlayer); } diff --git a/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityCreativeEnergy.java b/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityCreativeEnergy.java new file mode 100644 index 00000000000..267b0b488e1 --- /dev/null +++ b/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityCreativeEnergy.java @@ -0,0 +1,210 @@ +package gregtech.common.metatileentities.storage; + +import codechicken.lib.render.CCRenderState; +import codechicken.lib.render.pipeline.ColourMultiplier; +import codechicken.lib.render.pipeline.IVertexOperation; +import codechicken.lib.vec.Cuboid6; +import codechicken.lib.vec.Matrix4; +import com.google.common.collect.Lists; +import gregtech.api.GTValues; +import gregtech.api.capability.GregtechCapabilities; +import gregtech.api.capability.IEnergyContainer; +import gregtech.api.gui.ModularUI; +import gregtech.api.gui.widgets.ClickButtonWidget; +import gregtech.api.gui.widgets.CycleButtonWidget; +import gregtech.api.gui.widgets.TextFieldWidget; +import gregtech.api.metatileentity.MetaTileEntity; +import gregtech.api.metatileentity.MetaTileEntityHolder; +import gregtech.api.render.Textures; +import gregtech.api.util.GTUtility; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +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.tileentity.TileEntity; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.ResourceLocation; +import net.minecraft.world.World; +import net.minecraftforge.common.capabilities.Capability; +import org.apache.commons.lang3.ArrayUtils; +import org.apache.commons.lang3.tuple.Pair; + +import javax.annotation.Nullable; +import java.util.List; + +public class MetaTileEntityCreativeEnergy extends MetaTileEntity implements IEnergyContainer { + + private long voltage = 0; + private int amps = 1; + + private int setTier = 0; + private boolean active = false; + + private final List ALLOWED_CHARS = Lists.newArrayList('0', '1', '2', '3', '4', '5', '6', '7', '8', '9'); + + public MetaTileEntityCreativeEnergy() { + super(new ResourceLocation(GTValues.MODID, "infinite_energy")); + } + + @Override + public void renderMetaTileEntity(CCRenderState renderState, Matrix4 translation, IVertexOperation[] pipeline) { + IVertexOperation[] renderPipeline = ArrayUtils.add(pipeline, new ColourMultiplier(GTUtility.convertRGBtoOpaqueRGBA_CL(getPaintingColorForRendering()))); + Textures.VOLTAGE_CASINGS[14].render(renderState, translation, renderPipeline, Cuboid6.full); + for (EnumFacing face : EnumFacing.VALUES) { + Textures.INFINITE_EMITTER_FACE.renderSided(face, renderState, translation, pipeline); + } + } + + @Override + public Pair getParticleTexture() { + return Pair.of(Textures.VOLTAGE_CASINGS[this.setTier].getParticleSprite(), this.getPaintingColor()); + } + + @Override + public MetaTileEntity createMetaTileEntity(MetaTileEntityHolder holder) { + return new MetaTileEntityCreativeEnergy(); + } + + @Override + public T getCapability(Capability capability, EnumFacing side) { + if (capability == GregtechCapabilities.CAPABILITY_ENERGY_CONTAINER) + return GregtechCapabilities.CAPABILITY_ENERGY_CONTAINER.cast(this); + return super.getCapability(capability, side); + } + + @Override + public void addInformation(ItemStack stack, @Nullable World player, List tooltip, boolean advanced) { + tooltip.add(I18n.format("gregtech.machine.infinite_energy.tooltip")); + } + + @Override + protected ModularUI createUI(EntityPlayer entityPlayer) { + String[] V = {"NAN", "ULV", "LV", "MV", "HV", "EV", "IV", "LuV", "ZPM", "UV", "UHV", "UEV", "UIV", "UMV", "UXV", "MAX"}; + ModularUI.Builder builder = ModularUI.defaultBuilder() + .widget(new CycleButtonWidget(7, 7, 30, 20, V, () -> setTier, tier -> { + setTier = tier; + if (tier > 0) + voltage = GTValues.V[setTier - 1]; + else + voltage = 0; + })); + builder.label(7, 32, "Voltage"); + builder.widget(new TextFieldWidget(7, 44, 156, 20, true, () -> String.valueOf(voltage), value -> { + voltage = Integer.parseInt(value); + setTier = 0; + }).setValidator(value -> { + for (int i = 0; i < value.length(); i++) { + char c = value.charAt(i); + if (!ALLOWED_CHARS.contains(c)) + return false; + } + return true; + })); + builder.label(7, 74, "Amperage"); + builder.widget(new ClickButtonWidget(7, 87, 20, 20, "-", data -> amps = amps-- == -1 ? 0 : amps--)); + builder.widget(new TextFieldWidget(29, 87, 118, 20, true, () -> String.valueOf(amps), value -> { + amps = Integer.parseInt(value); + }).setValidator(value -> { + for (int i = 0; i < value.length(); i++) { + char c = value.charAt(i); + if (!ALLOWED_CHARS.contains(c)) + return false; + } + return true; + })); + builder.widget(new ClickButtonWidget(149, 87, 20, 20, "+", data -> amps++)); + + builder.widget(new CycleButtonWidget(7, 139, 162, 20, () -> active, value -> active = value, "Not active", "Active")); + + return builder.build(getHolder(), entityPlayer); + } + + @Override + public void update() { + super.update(); + if (!active || voltage <= 0 || amps <= 0) return; + int ampsUsed = 0; + for (EnumFacing facing : EnumFacing.values()) { + EnumFacing opposite = facing.getOpposite(); + TileEntity tile = getWorld().getTileEntity(getPos().offset(facing)); + if (tile != null) { + IEnergyContainer container = tile.getCapability(GregtechCapabilities.CAPABILITY_ENERGY_CONTAINER, opposite); + if (container == null || !container.inputsEnergy(opposite) || container.getEnergyCanBeInserted() == 0) + continue; + ampsUsed += container.acceptEnergyFromNetwork(opposite, voltage, amps - ampsUsed); + if (ampsUsed >= amps) + break; + } + } + } + + @Override + public NBTTagCompound writeToNBT(NBTTagCompound data) { + data.setLong("Voltage", voltage); + data.setInteger("Amps", amps); + data.setByte("Tier", (byte) setTier); + data.setBoolean("Active", active); + return super.writeToNBT(data); + } + + @Override + public void readFromNBT(NBTTagCompound data) { + voltage = data.getLong("Voltage"); + amps = data.getInteger("Amps"); + setTier = data.getByte("Tier"); + active = data.getBoolean("Active"); + super.readFromNBT(data); + } + + @Override + public long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage) { + return 0; + } + + @Override + public boolean inputsEnergy(EnumFacing side) { + return false; + } + + @Override + public boolean outputsEnergy(EnumFacing side) { + return true; + } + + @Override + public long changeEnergy(long differenceAmount) { + return 0; + } + + @Override + public long getEnergyStored() { + return 69; + } + + @Override + public long getEnergyCapacity() { + return 420; + } + + @Override + public long getInputAmperage() { + return 0; + } + + @Override + public long getInputVoltage() { + return 0; + } + + @Override + public long getOutputVoltage() { + return voltage; + } + + @Override + public long getOutputAmperage() { + return amps; + } + +} diff --git a/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityDrum.java b/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityDrum.java index f32ec4a4760..45161858dcb 100644 --- a/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityDrum.java +++ b/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityDrum.java @@ -122,12 +122,38 @@ public void writeItemStackData(NBTTagCompound itemStack) { public ICapabilityProvider initItemStackCapabilities(ItemStack itemStack) { return new FluidHandlerItemStack(itemStack, tankSize) { @Override - protected void setContainerToEmpty() { - this.container.setTagCompound(null); + public FluidStack drain(FluidStack resource, boolean doDrain) { + FluidStack drained = super.drain(resource, doDrain); + this.removeTagWhenEmptied(doDrain); + return drained; + } + + @Override + public FluidStack drain(int maxDrain, boolean doDrain) { + FluidStack drained = super.drain(maxDrain, doDrain); + this.removeTagWhenEmptied(doDrain); + return drained; + } + + private void removeTagWhenEmptied(boolean doDrain) { + if (doDrain && this.getFluid() == null) { + this.container.setTagCompound(null); + } + } + + @Override + public boolean canFillFluidType(FluidStack fluid) { + return MetaTileEntityDrum.this.canFillFluidType(fluid); } }; } + protected boolean canFillFluidType(FluidStack fluid) { + return !ModHandler.isMaterialWood(material) && + !material.hasFlag(FLAMMABLE) || + fluid.getFluid().getTemperature(fluid) <= 325; + } + @Override public void writeInitialSyncData(PacketBuffer buf) { super.writeInitialSyncData(buf); diff --git a/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityQuantumChest.java b/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityQuantumChest.java index a7b235d9be4..96d0a4034f5 100644 --- a/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityQuantumChest.java +++ b/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityQuantumChest.java @@ -7,6 +7,8 @@ import codechicken.lib.vec.Matrix4; import gregtech.api.capability.GregtechTileCapabilities; import gregtech.api.capability.IActiveOutputSide; +import gregtech.api.capability.impl.ItemHandlerProxy; +import gregtech.api.cover.ICoverable; import gregtech.api.gui.GuiTextures; import gregtech.api.gui.ModularUI; import gregtech.api.gui.ModularUI.Builder; @@ -35,6 +37,7 @@ import net.minecraft.world.World; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.util.Constants.NBT; +import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.IItemHandlerModifiable; import net.minecraftforge.items.ItemStackHandler; @@ -58,6 +61,7 @@ public class MetaTileEntityQuantumChest extends MetaTileEntity implements ITiere private static final String NBT_ITEMSTACK = "ItemStack"; private static final String NBT_PARTIALSTACK = "PartialStack"; private static final String NBT_ITEMCOUNT = "ItemAmount"; + protected IItemHandler outputItemInventory; public MetaTileEntityQuantumChest(ResourceLocation metaTileEntityId, int tier, long maxStoredItems) { super(metaTileEntityId); @@ -185,6 +189,7 @@ public void addInformation(ItemStack stack, @Nullable World player, List protected void initializeInventory() { super.initializeInventory(); this.itemInventory = new QuantumChestItemHandler(); + this.outputItemInventory = new ItemHandlerProxy(new ItemStackHandler(0), exportItems); } @Override @@ -270,7 +275,7 @@ protected ModularUI createUI(EntityPlayer entityPlayer) { } public EnumFacing getOutputFacing() { - return outputFacing == null ? EnumFacing.SOUTH : outputFacing; + return outputFacing == null ? frontFacing.getOpposite() : outputFacing; } public void setOutputFacing(EnumFacing outputFacing) { @@ -285,6 +290,9 @@ public void setOutputFacing(EnumFacing outputFacing) { @Override public boolean onWrenchClick(EntityPlayer playerIn, EnumHand hand, EnumFacing facing, CuboidRayTraceResult hitResult) { if (!playerIn.isSneaking()) { + if (getOutputFacing() == facing || getFrontFacing() == facing) { + return false; + } if (!getWorld().isRemote) { setOutputFacing(facing); } @@ -342,17 +350,14 @@ public T getCapability(Capability capability, EnumFacing side) { } return null; } - return super.getCapability(capability, side); - - } - - @Override - public boolean canPlaceCoverOnSide(EnumFacing side) { - //Done to prevent loops as output always acts as input - if (side == getOutputFacing()) { - return false; + else if (capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) { + IItemHandler itemHandler = (side == getOutputFacing() && !isAllowInputFromOutputSide()) ? outputItemInventory : itemInventory; + if (itemHandler.getSlots() > 0) { + return CapabilityItemHandler.ITEM_HANDLER_CAPABILITY.cast(itemHandler); + } + return null; } - return true; + return super.getCapability(capability, side); } @Override @@ -383,6 +388,30 @@ public void clearMachineInventory(NonNullList itemBuffer) { clearInventory(itemBuffer, importItems); } + @Override + public boolean onScrewdriverClick(EntityPlayer playerIn, EnumHand hand, EnumFacing facing, CuboidRayTraceResult hitResult) { + EnumFacing hitFacing = ICoverable.determineGridSideHit(hitResult); + if (facing == getOutputFacing() || (hitFacing == getOutputFacing() && playerIn.isSneaking())) { + if (!getWorld().isRemote) { + if (isAllowInputFromOutputSide()) { + setAllowInputFromOutputSide(false); + playerIn.sendMessage(new TextComponentTranslation("gregtech.machine.basic.input_from_output_side.disallow")); + } else { + setAllowInputFromOutputSide(true); + playerIn.sendMessage(new TextComponentTranslation("gregtech.machine.basic.input_from_output_side.allow")); + } + } + return true; + } + return super.onScrewdriverClick(playerIn, hand, facing, hitResult); + } + public void setAllowInputFromOutputSide(boolean allowInputFromOutputSide) { + this.allowInputFromOutputSide = allowInputFromOutputSide; + if (!getWorld().isRemote) { + markDirty(); + } + } + private class QuantumChestItemHandler implements IItemHandler { @Override diff --git a/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityQuantumTank.java b/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityQuantumTank.java index d05adb16972..ab23969d755 100644 --- a/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityQuantumTank.java +++ b/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityQuantumTank.java @@ -7,7 +7,9 @@ import codechicken.lib.vec.Matrix4; import gregtech.api.capability.GregtechTileCapabilities; import gregtech.api.capability.IActiveOutputSide; +import gregtech.api.capability.impl.FluidHandlerProxy; import gregtech.api.capability.impl.FluidTankList; +import gregtech.api.cover.ICoverable; import gregtech.api.gui.GuiTextures; import gregtech.api.gui.ModularUI; import gregtech.api.gui.ModularUI.Builder; @@ -28,11 +30,14 @@ import net.minecraft.util.NonNullList; import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.MathHelper; +import net.minecraft.util.text.TextComponentTranslation; import net.minecraft.world.World; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.fluids.FluidRegistry; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.FluidTank; +import net.minecraftforge.fluids.capability.CapabilityFluidHandler; +import net.minecraftforge.fluids.capability.IFluidHandler; import net.minecraftforge.items.ItemStackHandler; import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.tuple.Pair; @@ -49,7 +54,8 @@ public class MetaTileEntityQuantumTank extends MetaTileEntity implements ITiered private final ItemStackHandler containerInventory; private boolean autoOutputFluids; private EnumFacing outputFacing; - private final boolean allowInputFromOutputSide = true; + private boolean allowInputFromOutputSide = true; + protected IFluidHandler outputFluidInventory; public MetaTileEntityQuantumTank(ResourceLocation metaTileEntityId, int tier, int maxFluidCapacity) { super(metaTileEntityId); @@ -71,6 +77,7 @@ protected void initializeInventory() { this.fluidInventory = fluidTank; this.importFluids = new FluidTankList(false, fluidTank); this.exportFluids = new FluidTankList(false, fluidTank); + this.outputFluidInventory = new FluidHandlerProxy(new FluidTankList(false), exportFluids); } @Override @@ -89,10 +96,9 @@ public void update() { if (!getWorld().isRemote) { fillContainerFromInternalTank(containerInventory, containerInventory, 0, 1); fillInternalTankFromFluidContainer(containerInventory, containerInventory, 0, 1); - - } - if (isAutoOutputFluids()) { - pushFluidsIntoNearbyHandlers(currentOutputFacing); + if (isAutoOutputFluids()) { + pushFluidsIntoNearbyHandlers(currentOutputFacing); + } } } @@ -153,11 +159,6 @@ protected FluidTankList createExportFluidHandler() { return new FluidTankList(false, fluidTank); } - @Override - public boolean hasFrontFacing() { - return false; - } - @Override public void renderMetaTileEntity(CCRenderState renderState, Matrix4 translation, IVertexOperation[] pipeline) { Textures.VOLTAGE_CASINGS[tier].render(renderState, translation, ArrayUtils.add(pipeline, @@ -220,9 +221,17 @@ public void writeInitialSyncData(PacketBuffer buf) { } public EnumFacing getOutputFacing() { - return outputFacing == null ? EnumFacing.SOUTH : outputFacing; + return outputFacing == null ? frontFacing.getOpposite() : outputFacing; } + @Override + public void setFrontFacing(EnumFacing frontFacing) { + super.setFrontFacing(EnumFacing.UP); + if (this.outputFacing == null) { + //set initial output facing as opposite to front + setOutputFacing(frontFacing.getOpposite()); + } + } @Override public boolean isAutoOutputItems() { @@ -235,7 +244,7 @@ public boolean isAutoOutputFluids() { @Override public boolean isAllowInputFromOutputSide() { - return true; + return allowInputFromOutputSide; } @Override @@ -279,22 +288,24 @@ public T getCapability(Capability capability, EnumFacing side) { } return null; } - return super.getCapability(capability, side); - - } + else if (capability == CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY) { + IFluidHandler fluidHandler = (side == getOutputFacing() && !isAllowInputFromOutputSide()) ? outputFluidInventory : fluidInventory; + if (fluidHandler.getTankProperties().length > 0) { + return CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY.cast(fluidHandler); + } - @Override - public boolean canPlaceCoverOnSide(EnumFacing side) { - //Done to prevent loops as output always acts as input - if (side == getOutputFacing()) { - return false; + return null; } - return true; + return super.getCapability(capability, side); + } @Override public boolean onWrenchClick(EntityPlayer playerIn, EnumHand hand, EnumFacing facing, CuboidRayTraceResult hitResult) { if (!playerIn.isSneaking()) { + if (getOutputFacing() == facing || getFrontFacing() == facing) { + return false; + } if (!getWorld().isRemote) { setOutputFacing(facing); } @@ -303,7 +314,30 @@ public boolean onWrenchClick(EntityPlayer playerIn, EnumHand hand, EnumFacing fa return super.onWrenchClick(playerIn, hand, facing, hitResult); } + @Override + public boolean onScrewdriverClick(EntityPlayer playerIn, EnumHand hand, EnumFacing facing, CuboidRayTraceResult hitResult) { + EnumFacing hitFacing = ICoverable.determineGridSideHit(hitResult); + if (facing == getOutputFacing() || (hitFacing == getOutputFacing() && playerIn.isSneaking())) { + if (!getWorld().isRemote) { + if (isAllowInputFromOutputSide()) { + setAllowInputFromOutputSide(false); + playerIn.sendMessage(new TextComponentTranslation("gregtech.machine.basic.input_from_output_side.disallow")); + } else { + setAllowInputFromOutputSide(true); + playerIn.sendMessage(new TextComponentTranslation("gregtech.machine.basic.input_from_output_side.allow")); + } + } + return true; + } + return super.onScrewdriverClick(playerIn, hand, facing, hitResult); + } + public void setAllowInputFromOutputSide(boolean allowInputFromOutputSide) { + this.allowInputFromOutputSide = allowInputFromOutputSide; + if (!getWorld().isRemote) { + markDirty(); + } + } public void setAutoOutputFluids(boolean autoOutputFluids) { this.autoOutputFluids = autoOutputFluids; if (!getWorld().isRemote) { @@ -311,6 +345,4 @@ public void setAutoOutputFluids(boolean autoOutputFluids) { markDirty(); } } - - } diff --git a/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityWorkbench.java b/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityWorkbench.java index c8b71f494dd..76ded1f9140 100644 --- a/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityWorkbench.java +++ b/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityWorkbench.java @@ -17,6 +17,7 @@ import gregtech.api.metatileentity.MetaTileEntity; import gregtech.api.metatileentity.MetaTileEntityHolder; import gregtech.api.render.Textures; +import gregtech.api.terminal.app.AbstractApplication; import gregtech.api.unification.material.Materials; import gregtech.api.util.GTUtility; import gregtech.api.util.Position; @@ -153,11 +154,8 @@ public static AbstractWidgetGroup createWorkbenchTab(CraftingRecipeResolver reci widgetGroup.addWidget(new CraftingSlotWidget(recipeResolver, 0, 88 - 9, 44 - 9)); //crafting grid - for (int i = 0; i < 3; ++i) { - for (int j = 0; j < 3; ++j) { - widgetGroup.addWidget(new PhantomSlotWidget(craftingGrid, j + i * 3, 8 + j * 18, 17 + i * 18).setBackgroundTexture(GuiTextures.SLOT)); - } - } + widgetGroup.addWidget(new CraftingStationInputWidgetGroup(5, 8, craftingGrid, recipeResolver)); + Supplier textSupplier = () -> Integer.toString(recipeResolver.getItemsCrafted()); widgetGroup.addWidget(new SimpleTextWidget(88, 44 + 20, "", textSupplier)); @@ -199,7 +197,7 @@ protected ModularUI createUI(EntityPlayer entityPlayer) { .bindPlayerInventory(entityPlayer.inventory, 140); builder.label(5, 5, getMetaFullName()); - TabGroup tabGroup = new TabGroup(TabLocation.HORIZONTAL_TOP_LEFT, Position.ORIGIN); + TabGroup tabGroup = new TabGroup<>(TabLocation.HORIZONTAL_TOP_LEFT, Position.ORIGIN); tabGroup.addTab(new ItemTabInfo("gregtech.machine.workbench.tab.workbench", new ItemStack(Blocks.CRAFTING_TABLE)), createWorkbenchTab(getRecipeResolver(), craftingGrid, recipeMemory, toolInventory, internalInventory)); tabGroup.addTab(new ItemTabInfo("gregtech.machine.workbench.tab.item_list", new ItemStack(Blocks.CHEST)), createItemListTab()); builder.widget(tabGroup); diff --git a/src/main/java/gregtech/common/metatileentities/traits/TraitInfiniteEmitter.java b/src/main/java/gregtech/common/metatileentities/traits/TraitInfiniteEmitter.java deleted file mode 100644 index 7f1562f47f7..00000000000 --- a/src/main/java/gregtech/common/metatileentities/traits/TraitInfiniteEmitter.java +++ /dev/null @@ -1,141 +0,0 @@ -package gregtech.common.metatileentities.traits; - -import gregtech.api.GTValues; -import gregtech.api.capability.GregtechCapabilities; -import gregtech.api.capability.IEnergyContainer; -import gregtech.api.metatileentity.InfiniteEnergyTileEntityBase; -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.EnumFacing; -import net.minecraftforge.common.capabilities.Capability; - -import javax.annotation.Nullable; -import java.math.BigInteger; - - -public class TraitInfiniteEmitter extends TraitInfiniteEnergy implements IEnergyContainer { - private boolean isInfinite; - private int tier = GTValues.MAX; - private long voltage = GTValues.V[GTValues.MAX]; - - public TraitInfiniteEmitter(InfiniteEnergyTileEntityBase mte) { - super(mte); - } - - public boolean isInfinite() { - return isInfinite; - } - - public void setInfinite(boolean infinite) { - this.isInfinite = infinite; - } - - @Override - public void update() { - if (!metaTileEntity.getWorld().isRemote) { - if (isInfinite) for (EnumFacing facing : EnumFacing.VALUES) send(facing); - else if (energy.signum() == 1) for (EnumFacing facing : EnumFacing.VALUES) - if (send(facing) && energy.signum() != 1) break; - } - } - - - public int getTier() { - return tier; - } - - public void setTier(int tier) { - voltage = GTValues.V[this.tier = tier]; - } - - @Override - public String getName() { - return "infinite_gteu_emitter"; - } - - @Override - public int getNetworkID() { - return TraitNetworkIds.TRAIT_ID_ENERGY_CONTAINER; - } - - protected boolean send(EnumFacing facing) { - TileEntity te = metaTileEntity.getWorld().getTileEntity(this.metaTileEntity.getPos().offset(facing)); - if (te != null) { - IEnergyContainer s = te.getCapability(GregtechCapabilities.CAPABILITY_ENERGY_CONTAINER, facing.getOpposite()); - if (s != null && s.inputsEnergy(facing.getOpposite())) { - long stored = getEnergyStored(), voltage = Math.min(this.voltage, s.getInputVoltage()); - if (stored / voltage > 0) { - long accepted = s.acceptEnergyFromNetwork(facing.getOpposite(), voltage, Math.min(s.getInputAmperage(), stored / voltage)) * voltage; - if (accepted > 0) { - if (!isInfinite()) subtract(BigInteger.valueOf(accepted)); - return true; - } - } - } - } - return false; - } - - @Override - public long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage) { - return 0; - } - - @Override - public boolean inputsEnergy(EnumFacing side) { - return false; - } - - @Override - public boolean outputsEnergy(EnumFacing side) { - return true; - } - - @Override - public long changeEnergy(long differenceAmount) { - add(BigInteger.valueOf(differenceAmount)); - return differenceAmount; - } - - @Override - public long getInputAmperage() { - return 64; - } - - @Override - public long getInputVoltage() { - return voltage; - } - - @Override - public long getEnergyStored() { - return isInfinite() || energy.compareTo(BigInteger.valueOf(Long.MAX_VALUE)) >= 0 ? Long.MAX_VALUE : energy.longValueExact(); - } - - @Override - public long getEnergyCapacity() { - return getEnergyStored(); - } - - @Nullable - @Override - @SuppressWarnings("unchecked") - public T getCapability(Capability capability) { - return capability == GregtechCapabilities.CAPABILITY_ENERGY_CONTAINER ? (T) this : null; - } - - @Override - public NBTTagCompound serializeNBT() { - NBTTagCompound nbt = super.serializeNBT(); - if (isInfinite) nbt.setBoolean("infinite", true); - nbt.setByte("tier", (byte) tier); - return nbt; - } - - @Override - public void deserializeNBT(NBTTagCompound nbt) { - super.deserializeNBT(nbt); - setInfinite(nbt.getBoolean("infinite")); - setTier(nbt.getByte("tier")); - } -} diff --git a/src/main/java/gregtech/common/metatileentities/traits/TraitInfiniteEnergy.java b/src/main/java/gregtech/common/metatileentities/traits/TraitInfiniteEnergy.java deleted file mode 100644 index fd924599064..00000000000 --- a/src/main/java/gregtech/common/metatileentities/traits/TraitInfiniteEnergy.java +++ /dev/null @@ -1,57 +0,0 @@ -package gregtech.common.metatileentities.traits; - -import gregtech.api.metatileentity.InfiniteEnergyTileEntityBase; -import gregtech.api.metatileentity.MTETrait; -import net.minecraft.nbt.NBTTagCompound; -import net.minecraftforge.common.util.Constants.NBT; - -import java.math.BigInteger; - -public abstract class TraitInfiniteEnergy extends MTETrait { - protected final InfiniteEnergyTileEntityBase mte; - protected BigInteger energy = BigInteger.ZERO; - - public TraitInfiniteEnergy(InfiniteEnergyTileEntityBase mte) { - super(mte); - this.mte = mte; - } - - public BigInteger getEnergy() { - return energy; - } - - public void setEnergy(BigInteger bigInteger) { - energy = bigInteger.signum() == 1 ? bigInteger : BigInteger.ZERO; - } - - protected void add(BigInteger bInt) { - switch (bInt.signum()) { - case 1: - energy = energy.add(bInt); - break; - case -1: - subtract(bInt.negate()); - } - } - - protected void subtract(BigInteger bInt) { - if (energy.compareTo(bInt) > 0) { - energy = energy.subtract(bInt); - } else energy = BigInteger.ZERO; - } - - @Override - public NBTTagCompound serializeNBT() { - NBTTagCompound nbt = new NBTTagCompound(); - if (energy.signum() > 0) nbt.setByteArray("energy", energy.toByteArray()); - return nbt; - } - - @Override - public void deserializeNBT(NBTTagCompound nbt) { - if (nbt.hasKey("energy", NBT.TAG_BYTE_ARRAY)) { - byte[] bArr = nbt.getByteArray("energy"); - energy = bArr.length > 0 ? new BigInteger(bArr) : BigInteger.ZERO; - } else energy = BigInteger.ZERO; - } -} diff --git a/src/main/java/gregtech/common/pipelike/cable/BlockCable.java b/src/main/java/gregtech/common/pipelike/cable/BlockCable.java index c1f2d1124db..f9e86ea8148 100644 --- a/src/main/java/gregtech/common/pipelike/cable/BlockCable.java +++ b/src/main/java/gregtech/common/pipelike/cable/BlockCable.java @@ -3,6 +3,7 @@ import com.google.common.base.Preconditions; import gregtech.api.capability.GregtechCapabilities; import gregtech.api.capability.tool.ICutterItem; +import gregtech.api.cover.CoverBehavior; import gregtech.api.damagesources.DamageSources; import gregtech.api.pipenet.block.material.BlockMaterialPipe; import gregtech.api.pipenet.tile.AttachmentType; @@ -12,13 +13,14 @@ import gregtech.api.unification.material.MaterialRegistry; import gregtech.api.unification.material.properties.WireProperties; import gregtech.api.util.GTUtility; -import gregtech.common.ConfigHolder; import gregtech.common.pipelike.cable.net.EnergyNet; import gregtech.common.pipelike.cable.net.WorldENet; import gregtech.common.pipelike.cable.tile.TileEntityCable; import gregtech.common.pipelike.cable.tile.TileEntityCableTickable; +import gregtech.common.pipelike.fluidpipe.net.FluidPipeNet; import gregtech.common.render.CableRenderer; import gregtech.common.tools.DamageValues; +import net.minecraft.block.Block; import net.minecraft.block.ITileEntityProvider; import net.minecraft.block.state.IBlockState; import net.minecraft.client.renderer.texture.TextureAtlasSprite; @@ -110,9 +112,20 @@ public int onPipeToolUsed(ItemStack stack, EnumFacing coverSide, IPipeTile selfTile, EnumFacing side, IPipeTile sideTile) { - return true; + return selfTile instanceof TileEntityCable && sideTile instanceof TileEntityCable; } @Override @@ -124,13 +137,12 @@ public boolean canPipeConnectToBlock(IPipeTile selfT public void onEntityCollision(World worldIn, @Nonnull BlockPos pos, @Nonnull IBlockState state, @Nonnull Entity entityIn) { if (worldIn.isRemote) return; Insulation insulation = getPipeTileEntity(worldIn, pos).getPipeType(); - boolean damageOnLossless = ConfigHolder.doLosslessWiresDamage; - if (!worldIn.isRemote && insulation.insulationLevel == -1 && entityIn instanceof EntityLivingBase) { + if (insulation.insulationLevel == -1 && entityIn instanceof EntityLivingBase) { EntityLivingBase entityLiving = (EntityLivingBase) entityIn; - EnergyNet energyNet = getWorldPipeNet(worldIn).getNetFromPos(pos); - if (energyNet != null && (damageOnLossless || energyNet.getAllNodes().get(pos).data.lossPerBlock > 0)) { - long voltage = energyNet.getLastMaxVoltage(); - long amperage = energyNet.getLastAmperage(); + TileEntityCable cable = (TileEntityCable) getPipeTileEntity(worldIn, pos); + if (cable != null && cable.getNodeData().lossPerBlock > 0) { + long voltage = cable.getCurrentVoltage(); + long amperage = cable.getCurrentAmperage(); if (voltage > 0L && amperage > 0L) { float damageAmount = (GTUtility.getTierByVoltage(voltage) + 1) * amperage * 4; entityLiving.attackEntityFrom(DamageSources.getElectricDamage(), damageAmount); @@ -139,6 +151,26 @@ public void onEntityCollision(World worldIn, @Nonnull BlockPos pos, @Nonnull IBl } } + @Override + public int getVisualConnections(IPipeTile selfTile) { + int connections = selfTile.getOpenConnections(); + float selfTHICCness = selfTile.getPipeType().getThickness(); + for (EnumFacing facing : EnumFacing.values()) { + CoverBehavior cover = selfTile.getCoverableImplementation().getCoverAtSide(facing); + if (cover != null) { + // adds side to open connections of it isn't already open & has a cover + connections |= 1 << facing.getIndex(); + continue; + } + // check if neighbour is a smaller cable + TileEntity neighbourTile = selfTile.getPipeWorld().getTileEntity(selfTile.getPipePos().offset(facing)); + if (neighbourTile instanceof TileEntityCable && ((TileEntityCable) neighbourTile).getPipeType().getThickness() < selfTHICCness) { + connections |= 1 << (facing.getIndex() + 6); + } + } + return connections; + } + @Nonnull @Override @SideOnly(Side.CLIENT) diff --git a/src/main/java/gregtech/common/pipelike/cable/Insulation.java b/src/main/java/gregtech/common/pipelike/cable/Insulation.java index 2dd737df190..cf4a12ec2a5 100644 --- a/src/main/java/gregtech/common/pipelike/cable/Insulation.java +++ b/src/main/java/gregtech/common/pipelike/cable/Insulation.java @@ -53,16 +53,19 @@ public OrePrefix getOrePrefix() { return orePrefix; } + public boolean isCable() { + return ordinal() > 4; + } @Override public WireProperties modifyProperties(WireProperties baseProperties) { int lossPerBlock; - if (ConfigHolder.doLosslessWiresMakeLossyCables && baseProperties.lossPerBlock == 0) + if (!baseProperties.isSuperconductor && baseProperties.lossPerBlock == 0) lossPerBlock = (int) (0.75 * lossMultiplier); else lossPerBlock = baseProperties.lossPerBlock * lossMultiplier; - return new WireProperties(baseProperties.voltage, baseProperties.amperage * amperage, lossPerBlock); + return new WireProperties(baseProperties.voltage, baseProperties.amperage * amperage, lossPerBlock, baseProperties.isSuperconductor); } @Override diff --git a/src/main/java/gregtech/common/pipelike/cable/ItemBlockCable.java b/src/main/java/gregtech/common/pipelike/cable/ItemBlockCable.java index 886b2da8a54..41d77f8dc8d 100644 --- a/src/main/java/gregtech/common/pipelike/cable/ItemBlockCable.java +++ b/src/main/java/gregtech/common/pipelike/cable/ItemBlockCable.java @@ -23,9 +23,10 @@ public ItemBlockCable(BlockCable block) { @Override @SideOnly(Side.CLIENT) - public void addInformation(@Nonnull ItemStack stack, @Nullable World worldIn, List tooltip, @Nonnull ITooltipFlag flagIn) { + public void addInformation(@Nonnull ItemStack stack, @Nullable World worldIn, @Nonnull List tooltip, @Nonnull ITooltipFlag flagIn) { WireProperties wireProperties = blockPipe.createItemProperties(stack); String voltageName = GTValues.VN[GTUtility.getTierByVoltage(wireProperties.voltage)]; + if (wireProperties.isSuperconductor) tooltip.add(I18n.format("gregtech.cable.superconductor", voltageName)); tooltip.add(I18n.format("gregtech.cable.voltage", wireProperties.voltage, voltageName)); tooltip.add(I18n.format("gregtech.cable.amperage", wireProperties.amperage)); tooltip.add(I18n.format("gregtech.cable.loss_per_block", wireProperties.lossPerBlock)); diff --git a/src/main/java/gregtech/common/pipelike/cable/net/EnergyNet.java b/src/main/java/gregtech/common/pipelike/cable/net/EnergyNet.java index 09d7123d7d3..bc3f5f0386a 100644 --- a/src/main/java/gregtech/common/pipelike/cable/net/EnergyNet.java +++ b/src/main/java/gregtech/common/pipelike/cable/net/EnergyNet.java @@ -4,83 +4,50 @@ import gregtech.api.pipenet.PipeNet; import gregtech.api.pipenet.WorldPipeNet; import gregtech.api.unification.material.properties.WireProperties; -import gregtech.api.util.PerTickLongCounter; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.BlockPos.MutableBlockPos; -import java.util.ArrayList; -import java.util.HashSet; +import java.util.Comparator; +import java.util.HashMap; import java.util.List; -import java.util.Stack; +import java.util.Map; public class EnergyNet extends PipeNet { - private final PerTickLongCounter currentAmperageCounter = new PerTickLongCounter(0L); - private final PerTickLongCounter currentMaxVoltageCounter = new PerTickLongCounter(0L); + private final Map> NET_DATA = new HashMap<>(); protected EnergyNet(WorldPipeNet world) { super(world); } - public long getLastAmperage() { - return currentAmperageCounter.getLast(worldData.getWorld()); + public List getNetData(BlockPos pipePos) { + List data = NET_DATA.get(pipePos); + if (data == null) { + data = EnergyNetWalker.createNetData(this, getWorldData(), pipePos); + data.sort(Comparator.comparingInt(RoutePath::getDistance)); + NET_DATA.put(pipePos, data); + } + return data; } - public long getLastMaxVoltage() { - return currentMaxVoltageCounter.getLast(worldData.getWorld()); + public void nodeNeighbourChanged(BlockPos pos) { + NET_DATA.clear(); } - public void incrementCurrentAmperage(long amperage, long voltage) { - currentAmperageCounter.increment(worldData.getWorld(), amperage); - long currentMaxVoltage = currentMaxVoltageCounter.get(worldData.getWorld()); - if (voltage > currentMaxVoltage) { - currentMaxVoltageCounter.set(worldData.getWorld(), voltage); - } + @Override + protected void updateBlockedConnections(BlockPos nodePos, EnumFacing facing, boolean isBlocked) { + super.updateBlockedConnections(nodePos, facing, isBlocked); + NET_DATA.clear(); } - public List computePatches(BlockPos startPos) { - ArrayList readyPaths = new ArrayList<>(); - RoutePath currentPath = new RoutePath(); - Node firstNode = getNodeAt(startPos); - currentPath.path.put(startPos, firstNode.data); - readyPaths.add(currentPath.cloneAndCompute(startPos)); - HashSet observedSet = new HashSet<>(); - observedSet.add(startPos); - MutableBlockPos currentPos = new MutableBlockPos(startPos); - Stack moveStack = new Stack<>(); - main: - while (true) { - for (EnumFacing facing : EnumFacing.VALUES) { - currentPos.move(facing); - Node secondNode = getNodeAt(currentPos); - if (secondNode != null && canNodesConnect(firstNode, facing, secondNode, this) && !observedSet.contains(currentPos)) { - BlockPos immutablePos = currentPos.toImmutable(); - observedSet.add(immutablePos); - firstNode = secondNode; - moveStack.push(facing.getOpposite()); - currentPath.path.put(immutablePos, getNodeAt(immutablePos).data); - if (secondNode.isActive) { - //if we are on active node, this is end of our path - RoutePath finalizedPath = currentPath.cloneAndCompute(immutablePos); - readyPaths.add(finalizedPath); - } - continue main; - } else { - currentPos.move(facing.getOpposite()); - } - } - if (!moveStack.isEmpty()) { - currentPos.move(moveStack.pop()); - //also remove already visited block from path - currentPath.path.remove(currentPos); - } else break; - } - return readyPaths; + @Override + protected void transferNodeData(Map> transferredNodes, PipeNet parentNet) { + super.transferNodeData(transferredNodes, parentNet); + NET_DATA.clear(); + ((EnergyNet) parentNet).NET_DATA.clear(); } - @Override protected void writeNodeData(WireProperties nodeData, NBTTagCompound tagCompound) { tagCompound.setInteger("voltage", nodeData.voltage); diff --git a/src/main/java/gregtech/common/pipelike/cable/net/EnergyNetHandler.java b/src/main/java/gregtech/common/pipelike/cable/net/EnergyNetHandler.java new file mode 100644 index 00000000000..09d16ade961 --- /dev/null +++ b/src/main/java/gregtech/common/pipelike/cable/net/EnergyNetHandler.java @@ -0,0 +1,127 @@ +package gregtech.common.pipelike.cable.net; + +import gregtech.api.capability.IEnergyContainer; +import gregtech.api.util.GTLog; +import gregtech.api.util.GTUtility; +import gregtech.common.pipelike.cable.tile.TileEntityCable; +import net.minecraft.init.Blocks; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.EnumParticleTypes; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import net.minecraft.world.WorldServer; + +import java.util.List; +import java.util.Objects; + +public class EnergyNetHandler implements IEnergyContainer { + + private final EnergyNet net; + private final TileEntityCable cable; + private final EnumFacing facing; + + public EnergyNetHandler(EnergyNet net, TileEntityCable cable, EnumFacing facing) { + this.net = Objects.requireNonNull(net); + this.cable = Objects.requireNonNull(cable); + this.facing = facing; + } + + @Override + public long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage) { + if (side == null) { + if (facing == null) return 0; + side = facing; + } + + long amperesUsed = 0L; + List paths = net.getNetData(cable.getPos()); + outer: + for (RoutePath path : paths) { + if (path.getMaxLoss() >= voltage) + continue; + if (GTUtility.arePosEqual(cable.getPos(), path.getPipePos()) && side == path.getFaceToHandler()) { + //Do not insert into source handler + continue; + } + IEnergyContainer dest = path.getHandler(cable.getWorld()); + EnumFacing facing = path.getFaceToHandler().getOpposite(); + if (dest == null || !dest.inputsEnergy(facing) || dest.getEnergyCanBeInserted() <= 0) continue; + long amps = dest.acceptEnergyFromNetwork(facing, voltage - path.getMaxLoss(), amperage - amperesUsed); + amperesUsed += amps; + boolean didBurn = false; + + for (TileEntityCable cable : path.getPath()) { + if (cable.getMaxVoltage() < voltage) { + for (TileEntityCable cable1 : path.getPath()) { + burnCable(cable1.getWorld(), cable1.getPos()); + } + break outer; + } + if (!cable.checkAmperage(amps)) { + didBurn = true; + burnCable(cable.getWorld(), cable.getPos()); + } + } + if(didBurn) break; + for(TileEntityCable cable : path.getPath()) { + cable.incrementAmperage(amps, voltage); + } + + if (amperage == amperesUsed) + break; + } + return amperesUsed; + } + + private void burnCable(World world, BlockPos pos) { + world.setBlockState(pos, Blocks.FIRE.getDefaultState()); + if (!world.isRemote) { + ((WorldServer) world).spawnParticle(EnumParticleTypes.SMOKE_LARGE, + pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5, + 5 + world.rand.nextInt(3), 0.0, 0.0, 0.0, 0.1); + } + } + + @Override + public long getInputAmperage() { + return cable.getNodeData().amperage; + } + + @Override + public long getInputVoltage() { + return cable.getNodeData().voltage; + } + + @Override + public long getEnergyCapacity() { + return getInputVoltage() * getInputAmperage(); + } + + @Override + public long changeEnergy(long energyToAdd) { + GTLog.logger.fatal("Do not use changeEnergy() for cables! Use acceptEnergyFromNetwork()"); + return acceptEnergyFromNetwork(facing == null ? EnumFacing.UP : facing, + energyToAdd / getInputAmperage(), + energyToAdd / getInputVoltage()) * getInputVoltage(); + } + + @Override + public boolean outputsEnergy(EnumFacing side) { + return true; + } + + @Override + public boolean inputsEnergy(EnumFacing side) { + return true; + } + + @Override + public long getEnergyStored() { + return 0; + } + + @Override + public boolean isOneProbeHidden() { + return true; + } +} diff --git a/src/main/java/gregtech/common/pipelike/cable/net/EnergyNetWalker.java b/src/main/java/gregtech/common/pipelike/cable/net/EnergyNetWalker.java new file mode 100644 index 00000000000..fd0a1298296 --- /dev/null +++ b/src/main/java/gregtech/common/pipelike/cable/net/EnergyNetWalker.java @@ -0,0 +1,65 @@ +package gregtech.common.pipelike.cable.net; + +import gregtech.api.capability.GregtechCapabilities; +import gregtech.api.capability.IEnergyContainer; +import gregtech.api.pipenet.PipeNet; +import gregtech.api.pipenet.PipeNetWalker; +import gregtech.api.pipenet.tile.IPipeTile; +import gregtech.common.pipelike.cable.tile.TileEntityCable; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +import javax.annotation.Nullable; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class EnergyNetWalker extends PipeNetWalker { + + public static List createNetData(PipeNet net, World world, BlockPos sourcePipe) { + EnergyNetWalker walker = new EnergyNetWalker(net, world, sourcePipe, 1, new ArrayList<>()); + walker.traversePipeNet(); + return walker.routes; + } + + private final List routes; + private Set pipes = new HashSet<>(); + private int loss; + + protected EnergyNetWalker(PipeNet net, World world, BlockPos sourcePipe, int walkedBlocks, List routes) { + super(net, world, sourcePipe, walkedBlocks); + this.routes = routes; + } + + @Override + protected PipeNetWalker createSubWalker(PipeNet net, World world, BlockPos nextPos, int walkedBlocks) { + EnergyNetWalker walker = new EnergyNetWalker(net, world, nextPos, walkedBlocks, routes); + walker.loss = loss; + walker.pipes = new HashSet<>(pipes); + return walker; + } + + @Override + protected void checkPipe(IPipeTile pipeTile, BlockPos pos) { + pipes.add((TileEntityCable) pipeTile); + loss += ((TileEntityCable) pipeTile).getNodeData().lossPerBlock; + } + + @Override + protected void checkNeighbour(IPipeTile pipeTile, BlockPos pipePos, EnumFacing faceToNeighbour, @Nullable TileEntity neighbourTile) { + if (neighbourTile != null) { + IEnergyContainer container = neighbourTile.getCapability(GregtechCapabilities.CAPABILITY_ENERGY_CONTAINER, faceToNeighbour.getOpposite()); + if (container != null) { + routes.add(new RoutePath(new BlockPos(pipePos), faceToNeighbour, new HashSet<>(pipes), getWalkedBlocks(), loss)); + } + } + } + + @Override + protected boolean isValidPipe(IPipeTile currentPipe, IPipeTile neighbourPipe, BlockPos pipePos, EnumFacing faceToNeighbour) { + return neighbourPipe instanceof TileEntityCable; + } +} diff --git a/src/main/java/gregtech/common/pipelike/cable/net/RoutePath.java b/src/main/java/gregtech/common/pipelike/cable/net/RoutePath.java index a4d3915156e..ee1cee68a89 100644 --- a/src/main/java/gregtech/common/pipelike/cable/net/RoutePath.java +++ b/src/main/java/gregtech/common/pipelike/cable/net/RoutePath.java @@ -1,54 +1,59 @@ package gregtech.common.pipelike.cable.net; -import gregtech.api.unification.material.properties.WireProperties; +import gregtech.api.capability.GregtechCapabilities; +import gregtech.api.capability.IEnergyContainer; import gregtech.common.pipelike.cable.tile.TileEntityCable; -import net.minecraft.init.Blocks; import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.EnumParticleTypes; +import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; -import net.minecraft.world.WorldServer; -import java.util.HashMap; +import java.util.Set; public class RoutePath { + private final BlockPos destPipePos; + private final EnumFacing destFacing; + private final int distance; + private final Set path; + private final long maxLoss; + + public RoutePath(BlockPos destPipePos, EnumFacing destFacing, Set path, int distance, long maxLoss) { + this.destPipePos = destPipePos; + this.destFacing = destFacing; + this.path = path; + this.distance = distance; + this.maxLoss = maxLoss; + } - public BlockPos destination; - public HashMap path = new HashMap<>(); - public int maxAmperage = Integer.MAX_VALUE; - public int minVoltage = Integer.MAX_VALUE; - public int totalLoss; - - public RoutePath cloneAndCompute(BlockPos destination) { - RoutePath newPath = new RoutePath(); - newPath.path = new HashMap<>(path); - newPath.destination = destination; - for (WireProperties wireProperties : path.values()) { - newPath.maxAmperage = Math.min(newPath.maxAmperage, wireProperties.amperage); - newPath.minVoltage = Math.min(newPath.minVoltage, wireProperties.voltage); - newPath.totalLoss += wireProperties.lossPerBlock; - } - return newPath; - } - - public boolean burnCablesInPath(World world, long voltage, long amperage) { - for (BlockPos blockPos : path.keySet()) { - WireProperties wireProperties = path.get(blockPos); - if (voltage > wireProperties.voltage || amperage > wireProperties.amperage) { - TileEntity tileEntity = world.getTileEntity(blockPos); - if (tileEntity instanceof TileEntityCable) { - world.setBlockToAir(blockPos); - world.setBlockState(blockPos, Blocks.FIRE.getDefaultState()); - - if (!world.isRemote) { - ((WorldServer) world).spawnParticle(EnumParticleTypes.SMOKE_LARGE, - blockPos.getX() + 0.5, blockPos.getY() + 0.5, blockPos.getZ() + 0.5, - 5 + world.rand.nextInt(3), 0.0, 0.0, 0.0, 0.1); - } - } - } - } - return true; + public int getDistance() { + return distance; + } + + public long getMaxLoss() { + return maxLoss; + } + + public Set getPath() { + return path; } + public BlockPos getPipePos() { + return destPipePos; + } + + public EnumFacing getFaceToHandler() { + return destFacing; + } + + public BlockPos getHandlerPos() { + return destPipePos.offset(destFacing); + } + + public IEnergyContainer getHandler(World world) { + TileEntity tile = world.getTileEntity(getHandlerPos()); + if(tile != null) { + return tile.getCapability(GregtechCapabilities.CAPABILITY_ENERGY_CONTAINER, destFacing.getOpposite()); + } + return null; + } } diff --git a/src/main/java/gregtech/common/pipelike/cable/tile/CableEnergyContainer.java b/src/main/java/gregtech/common/pipelike/cable/tile/CableEnergyContainer.java deleted file mode 100644 index 4c50867f6b0..00000000000 --- a/src/main/java/gregtech/common/pipelike/cable/tile/CableEnergyContainer.java +++ /dev/null @@ -1,169 +0,0 @@ -package gregtech.common.pipelike.cable.tile; - -import gregtech.api.capability.GregtechCapabilities; -import gregtech.api.capability.IEnergyContainer; -import gregtech.api.pipenet.tile.IPipeTile; -import gregtech.api.unification.material.properties.WireProperties; -import gregtech.common.pipelike.cable.Insulation; -import gregtech.common.pipelike.cable.net.EnergyNet; -import gregtech.common.pipelike.cable.net.RoutePath; -import gregtech.common.pipelike.cable.net.WorldENet; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.EnumFacing; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.BlockPos.PooledMutableBlockPos; -import net.minecraft.world.World; - -import java.lang.ref.WeakReference; -import java.util.Collections; -import java.util.List; - -public class CableEnergyContainer implements IEnergyContainer { - - private final IPipeTile tileEntityCable; - private WeakReference currentEnergyNet = new WeakReference<>(null); - private long lastCachedUpdate; - private List pathsCache; - - public CableEnergyContainer(IPipeTile tileEntityCable) { - this.tileEntityCable = tileEntityCable; - } - - @Override - public long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage) { - EnergyNet energyNet = getEnergyNet(); - if (energyNet == null) { - return 0L; - } - List paths = getPaths(); - long amperesUsed = 0; - for (RoutePath routePath : paths) { - if (routePath.totalLoss >= voltage) { - continue; //do not emit if loss is too high - } - BlockPos destinationPos = routePath.destination; - int openConnections = energyNet.getAllNodes().get(destinationPos).openConnections; - amperesUsed += dispatchEnergyToNode(destinationPos, openConnections, - voltage - routePath.totalLoss, amperage - amperesUsed); - - if (voltage > routePath.minVoltage || - amperesUsed > routePath.maxAmperage) { - burnAllPaths(paths, voltage, amperage, amperesUsed); - break; //break after burning all paths - } - - if (amperesUsed == amperage) { - break; //do not continue if all amperes are exhausted - } - } - energyNet.incrementCurrentAmperage(amperage, voltage); - return amperesUsed; - } - - private void burnAllPaths(List paths, long voltage, long amperage, long lastAmperage) { - for (RoutePath pathToBurn : paths) { - if (voltage > pathToBurn.minVoltage || amperage > pathToBurn.maxAmperage || lastAmperage > pathToBurn.maxAmperage) { - pathToBurn.burnCablesInPath(tileEntityCable.getPipeWorld(), voltage, Math.max(amperage, lastAmperage)); - } - } - } - - private long dispatchEnergyToNode(BlockPos nodePos, int nodeOpenConnections, long voltage, long amperage) { - long amperesUsed = 0L; - //use pooled mutable to avoid creating new objects every tick - World world = tileEntityCable.getPipeWorld(); - PooledMutableBlockPos blockPos = PooledMutableBlockPos.retain(); - for (EnumFacing facing : EnumFacing.VALUES) { - if ((nodeOpenConnections & 1 << facing.getIndex()) == 0) { - continue; //do not dispatch energy to blocked sides - } - blockPos.setPos(nodePos).move(facing); - if (!world.isBlockLoaded(nodePos)) { - continue; //do not allow cables to load chunks - } - TileEntity tileEntity = world.getTileEntity(blockPos); - if (tileEntity == null || tileEntityCable.getPipeBlock().getPipeTileEntity(tileEntity) != null) { - continue; //do not emit into other cable tile entities - } - IEnergyContainer energyContainer = tileEntity.getCapability(GregtechCapabilities.CAPABILITY_ENERGY_CONTAINER, facing.getOpposite()); - if (energyContainer == null) continue; - amperesUsed += energyContainer.acceptEnergyFromNetwork(facing.getOpposite(), voltage, amperage - amperesUsed); - if (amperesUsed == amperage) - break; - } - blockPos.release(); - return amperesUsed; - } - - @Override - public long getInputAmperage() { - return tileEntityCable.getNodeData().amperage; - } - - @Override - public long getInputVoltage() { - return tileEntityCable.getNodeData().voltage; - } - - @Override - public long getEnergyCapacity() { - return getInputVoltage() * getInputAmperage(); - } - - @Override - public long changeEnergy(long energyToAdd) { - //just a fallback case if somebody will call this method - return acceptEnergyFromNetwork(EnumFacing.UP, - energyToAdd / getInputVoltage(), - energyToAdd / getInputAmperage()) * getInputVoltage(); - } - - @Override - public boolean outputsEnergy(EnumFacing side) { - return true; - } - - @Override - public boolean inputsEnergy(EnumFacing side) { - return true; - } - - @Override - public long getEnergyStored() { - return 0; - } - - private void recomputePaths(EnergyNet energyNet) { - this.lastCachedUpdate = energyNet.getLastUpdate(); - this.pathsCache = energyNet.computePatches(tileEntityCable.getPipePos()); - } - - private List getPaths() { - EnergyNet energyNet = getEnergyNet(); - if (energyNet == null) { - return Collections.emptyList(); - } - if (pathsCache == null || energyNet.getLastUpdate() > lastCachedUpdate) { - recomputePaths(energyNet); - } - return pathsCache; - } - - private EnergyNet getEnergyNet() { - EnergyNet currentEnergyNet = this.currentEnergyNet.get(); - if (currentEnergyNet != null && currentEnergyNet.isValid() && - currentEnergyNet.containsNode(tileEntityCable.getPipePos())) - return currentEnergyNet; //return current net if it is still valid - WorldENet worldENet = (WorldENet) tileEntityCable.getPipeBlock().getWorldPipeNet(tileEntityCable.getPipeWorld()); - currentEnergyNet = worldENet.getNetFromPos(tileEntityCable.getPipePos()); - if (currentEnergyNet != null) { - this.currentEnergyNet = new WeakReference<>(currentEnergyNet); - } - return currentEnergyNet; - } - - @Override - public boolean isOneProbeHidden() { - return true; - } -} diff --git a/src/main/java/gregtech/common/pipelike/cable/tile/TileEntityCable.java b/src/main/java/gregtech/common/pipelike/cable/tile/TileEntityCable.java index 06740774218..ab4913ac9fb 100644 --- a/src/main/java/gregtech/common/pipelike/cable/tile/TileEntityCable.java +++ b/src/main/java/gregtech/common/pipelike/cable/tile/TileEntityCable.java @@ -1,25 +1,25 @@ package gregtech.common.pipelike.cable.tile; import gregtech.api.capability.GregtechCapabilities; -import gregtech.api.capability.IEnergyContainer; import gregtech.api.pipenet.block.material.TileEntityMaterialPipeBase; import gregtech.api.unification.material.properties.WireProperties; +import gregtech.api.util.PerTickLongCounter; import gregtech.common.pipelike.cable.Insulation; +import gregtech.common.pipelike.cable.net.EnergyNet; +import gregtech.common.pipelike.cable.net.EnergyNetHandler; +import gregtech.common.pipelike.cable.net.WorldENet; import net.minecraft.util.EnumFacing; import net.minecraftforge.common.capabilities.Capability; import javax.annotation.Nullable; +import java.lang.ref.WeakReference; public class TileEntityCable extends TileEntityMaterialPipeBase { - private IEnergyContainer energyContainer; + private WeakReference currentEnergyNet = new WeakReference<>(null); - private IEnergyContainer getEnergyContainer() { - if (energyContainer == null) { - energyContainer = new CableEnergyContainer(this); - } - return energyContainer; - } + private final PerTickLongCounter amperageCounter = new PerTickLongCounter(0); + private final PerTickLongCounter voltageCounter = new PerTickLongCounter(0); @Override public Class getPipeTypeClass() { @@ -31,13 +31,54 @@ public boolean supportsTicking() { return false; } + public boolean checkAmperage(long amps) { + return getMaxAmperage() >= amperageCounter.get(getWorld()) + amps; + } + + public void incrementAmperage(long amps, long voltage) { + if(voltage > voltageCounter.get(getWorld())) { + voltageCounter.set(getWorld(), voltage); + } + amperageCounter.increment(getWorld(), amps); + } + + public long getCurrentAmperage() { + return amperageCounter.get(getWorld()); + } + + public long getCurrentVoltage() { + return voltageCounter.get(getWorld()); + } + + public long getMaxAmperage() { + return getNodeData().amperage; + } + + public long getMaxVoltage() { + return getNodeData().voltage; + } + @Nullable @Override public T getCapabilityInternal(Capability capability, @Nullable EnumFacing facing) { if (capability == GregtechCapabilities.CAPABILITY_ENERGY_CONTAINER) { - return GregtechCapabilities.CAPABILITY_ENERGY_CONTAINER.cast(getEnergyContainer()); + return GregtechCapabilities.CAPABILITY_ENERGY_CONTAINER.cast(new EnergyNetHandler(getEnergyNet(), this, facing)); } return super.getCapabilityInternal(capability, facing); } + private EnergyNet getEnergyNet() { + EnergyNet currentEnergyNet = this.currentEnergyNet.get(); + if (currentEnergyNet != null && currentEnergyNet.isValid() && + currentEnergyNet.containsNode(getPos())) + return currentEnergyNet; //return current net if it is still valid + WorldENet worldENet = WorldENet.getWorldENet(getWorld()); + currentEnergyNet = worldENet.getNetFromPos(getPos()); + if (currentEnergyNet != null) { + this.currentEnergyNet = new WeakReference<>(currentEnergyNet); + } + return currentEnergyNet; + } + + } diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/BlockFluidPipe.java b/src/main/java/gregtech/common/pipelike/fluidpipe/BlockFluidPipe.java old mode 100755 new mode 100644 index fc7e6a7d36a..50848b04623 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/BlockFluidPipe.java +++ b/src/main/java/gregtech/common/pipelike/fluidpipe/BlockFluidPipe.java @@ -1,7 +1,9 @@ package gregtech.common.pipelike.fluidpipe; import com.google.common.base.Preconditions; +import gregtech.api.cover.CoverBehavior; import gregtech.api.damagesources.DamageSources; +import gregtech.api.pipenet.PipeGatherer; import gregtech.api.pipenet.block.material.BlockMaterialPipe; import gregtech.api.pipenet.tile.IPipeTile; import gregtech.api.pipenet.tile.TileEntityPipeBase; @@ -10,10 +12,10 @@ import gregtech.api.unification.material.properties.FluidPipeProperties; import gregtech.common.pipelike.fluidpipe.net.FluidPipeNet; import gregtech.common.pipelike.fluidpipe.net.WorldFluidPipeNet; -import gregtech.common.pipelike.fluidpipe.tile.FluidPipeFluidHandler; import gregtech.common.pipelike.fluidpipe.tile.TileEntityFluidPipe; import gregtech.common.pipelike.fluidpipe.tile.TileEntityFluidPipeTickable; import gregtech.common.render.FluidPipeRenderer; +import net.minecraft.block.Block; import net.minecraft.block.state.IBlockState; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.creativetab.CreativeTabs; @@ -28,7 +30,6 @@ import net.minecraft.world.World; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.capability.CapabilityFluidHandler; -import net.minecraftforge.fluids.capability.IFluidHandler; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; import org.apache.commons.lang3.tuple.Pair; @@ -90,9 +91,20 @@ public void getSubBlocks(CreativeTabs itemIn, NonNullList items) { } } + @Override + public void neighborChanged(IBlockState state, World worldIn, BlockPos pos, Block blockIn, BlockPos fromPos) { + super.neighborChanged(state, worldIn, pos, blockIn, fromPos); + if (!worldIn.isRemote) { + FluidPipeNet itemPipeNet = getWorldPipeNet(worldIn).getNetFromPos(pos); + if (itemPipeNet != null) { + itemPipeNet.nodeNeighbourChanged(pos); + } + } + } + @Override public boolean canPipesConnect(IPipeTile selfTile, EnumFacing side, IPipeTile sideTile) { - return selfTile.getNodeData().equals(sideTile.getNodeData()); + return selfTile instanceof TileEntityFluidPipe && sideTile instanceof TileEntityFluidPipe; } @Override @@ -100,82 +112,28 @@ public boolean canPipeConnectToBlock(IPipeTile selfTile) { - return selfTile.getBlockedConnections(); - int activeNodeConnections = 0; - for (EnumFacing side : EnumFacing.VALUES) { - BlockPos offsetPos = selfTile.getPipePos().offset(side); - TileEntity tileEntity = selfTile.getPipeWorld().getTileEntity(offsetPos); - if(tileEntity != null) { - EnumFacing opposite = side.getOpposite(); - IFluidHandler sourceHandler = selfTile.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, side); - IFluidHandler receivedHandler = tileEntity.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, opposite); - if (sourceHandler != null && receivedHandler != null) { - activeNodeConnections |= 1 << side.getIndex(); - } - } - } - return activeNodeConnections; - }*/ - - /*@Override - public int getActiveNodeConnections(IBlockAccess world, BlockPos nodePos, IPipeTile selfTileEntity) { - return getPipeTileEntity(world, nodePos).getBlockedConnections(); - /*int activeNodeConnections = 0; - for (EnumFacing side : EnumFacing.VALUES) { - BlockPos offsetPos = nodePos.offset(side); - TileEntity tileEntity = world.getTileEntity(offsetPos); - if(tileEntity != null) { - EnumFacing opposite = side.getOpposite(); - IFluidHandler sourceHandler = selfTileEntity.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, side); - IFluidHandler receivedHandler = tileEntity.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, opposite); - if (sourceHandler != null && receivedHandler != null && canPushIntoFluidHandler(selfTileEntity, tileEntity, sourceHandler, receivedHandler)) { - activeNodeConnections |= 1 << side.getIndex(); - } - } - } - return activeNodeConnections; - }*/ - - public boolean canPushIntoFluidHandler(IPipeTile selfTileEntity, TileEntity otherTileEntity, IFluidHandler sourceHandler, IFluidHandler destinationHandler) { - boolean isSourcePipe = sourceHandler instanceof FluidPipeFluidHandler; - boolean isDestPipe = destinationHandler instanceof FluidPipeFluidHandler; - if (isSourcePipe && isDestPipe) { - float sourceThickness = selfTileEntity.getPipeType().getThickness(); - IPipeTile otherPipe = getPipeTileEntity(otherTileEntity); - if (otherPipe == null) { - return false; - } - float destThickness = otherPipe.getPipeType().getThickness(); - return sourceThickness > destThickness; - } - return true; - } - @Override public void onEntityCollision(World worldIn, @Nonnull BlockPos pos, @Nonnull IBlockState state, @Nonnull Entity entityIn) { if (worldIn.isRemote) return; if (entityIn instanceof EntityLivingBase && entityIn.world.getWorldTime() % 20 == 0L) { EntityLivingBase entityLiving = (EntityLivingBase) entityIn; FluidPipeNet pipeNet = getWorldPipeNet(worldIn).getNetFromPos(pos); - if (pipeNet != null) { - FluidStack fluidStack = pipeNet.getFluidNetTank().getFluid(); - if (fluidStack == null) { - return; //pipe network is empty - } - int fluidTemperature = fluidStack.getFluid().getTemperature(fluidStack); - if (fluidTemperature >= 373) { - //100C, temperature of boiling water - float damageAmount = (fluidTemperature - 363) / 4.0f; - entityLiving.attackEntityFrom(DamageSources.getHeatDamage(), damageAmount); - - } else if (fluidTemperature <= 183) { - //-90C, temperature of freezing of most gaseous elements - float damageAmount = fluidTemperature / 4.0f; - entityLiving.attackEntityFrom(DamageSources.getFrostDamage(), damageAmount); - - } + if (pipeNet == null) return; + TileEntityFluidPipeTickable pipeTile = (TileEntityFluidPipeTickable) PipeGatherer.findFirstMatching(pipeNet, worldIn, pos, pipe -> pipe instanceof TileEntityFluidPipeTickable); + if (pipeTile == null || pipeTile.getNodeData().tanks > 1) return; + FluidStack fluidStack = pipeTile.getContainedFluid(0); + if (fluidStack == null) + return; //pipe network is empty + int fluidTemperature = fluidStack.getFluid().getTemperature(fluidStack); + if (fluidTemperature >= 373) { + //100C, temperature of boiling water + float damageAmount = (fluidTemperature - 363) / 4.0f; + entityLiving.attackEntityFrom(DamageSources.getHeatDamage(), damageAmount); + + } else if (fluidTemperature <= 183) { + //-90C, temperature of freezing of most gaseous elements + float damageAmount = fluidTemperature / 4.0f; + entityLiving.attackEntityFrom(DamageSources.getFrostDamage(), damageAmount); } } } @@ -185,21 +143,30 @@ public TileEntityPipeBase createNewTileEntit return supportsTicking ? new TileEntityFluidPipeTickable() : new TileEntityFluidPipe(); } + @Nonnull + @SuppressWarnings("deprecation") @Override - protected void onActiveModeChange(World world, BlockPos pos, boolean isActiveNow, boolean isInitialChange) { - TileEntityFluidPipe oldTileEntity = (TileEntityFluidPipe) world.getTileEntity(pos); - if (!(oldTileEntity instanceof TileEntityFluidPipeTickable) && isActiveNow) { - TileEntityFluidPipeTickable newTileEntity = new TileEntityFluidPipeTickable(); - newTileEntity.transferDataFrom(oldTileEntity); - newTileEntity.setActive(true); - world.setTileEntity(pos, newTileEntity); - } else if (oldTileEntity instanceof TileEntityFluidPipeTickable) { - ((TileEntityFluidPipeTickable) oldTileEntity).setActive(isActiveNow); + public int getVisualConnections(IPipeTile selfTile) { + int connections = selfTile.getOpenConnections(); + float selfTHICCness = selfTile.getPipeType().getThickness(); + for (EnumFacing facing : EnumFacing.values()) { + CoverBehavior cover = selfTile.getCoverableImplementation().getCoverAtSide(facing); + if (cover != null) { + // adds side to open connections of it isn't already open & has a cover + connections |= 1 << facing.getIndex(); + continue; + } + // check if neighbour is a smaller item pipe + TileEntity neighbourTile = selfTile.getPipeWorld().getTileEntity(selfTile.getPipePos().offset(facing)); + if (neighbourTile instanceof TileEntityFluidPipe && + ((TileEntityFluidPipe) neighbourTile).isConnectionOpenAny(facing.getOpposite()) && + ((TileEntityFluidPipe) neighbourTile).getPipeType().getThickness() < selfTHICCness) { + connections |= 1 << (facing.getIndex() + 6); + } } + return connections; } - @Nonnull - @SuppressWarnings("deprecation") @Override @SideOnly(Side.CLIENT) public EnumBlockRenderType getRenderType(@Nonnull IBlockState state) { diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/FluidPipeType.java b/src/main/java/gregtech/common/pipelike/fluidpipe/FluidPipeType.java index 3d210a2f10c..530e88c5725 100644 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/FluidPipeType.java +++ b/src/main/java/gregtech/common/pipelike/fluidpipe/FluidPipeType.java @@ -12,20 +12,29 @@ public enum FluidPipeType implements IMaterialPipeType { SMALL_OPAQUE("small", 0.375f, 2, OrePrefix.pipeSmallFluid, true), NORMAL_OPAQUE("normal", 0.5f, 6, OrePrefix.pipeNormalFluid, true), LARGE_OPAQUE("large", 0.75f, 12, OrePrefix.pipeLargeFluid, true), - HUGE_OPAQUE("huge", 0.875f, 24, OrePrefix.pipeHugeFluid, true); + HUGE_OPAQUE("huge", 0.875f, 24, OrePrefix.pipeHugeFluid, true), + + QUADRUPLE("quadruple", 0.95f, 6, OrePrefix.pipeQuadrupleFluid, true, 4), + NONUPLE("nonuple", 0.95f, 2, OrePrefix.pipeNonupleFluid, true, 9); public final String name; public final float thickness; public final int capacityMultiplier; public final OrePrefix orePrefix; public final boolean opaque; + public final int channels; FluidPipeType(String name, float thickness, int capacityMultiplier, OrePrefix orePrefix, boolean opaque) { + this(name, thickness, capacityMultiplier, orePrefix, opaque, 1); + } + + FluidPipeType(String name, float thickness, int capacityMultiplier, OrePrefix orePrefix, boolean opaque, int channels) { this.name = name; this.thickness = thickness; this.capacityMultiplier = capacityMultiplier; this.orePrefix = orePrefix; this.opaque = opaque; + this.channels = channels; } @Nonnull @@ -49,7 +58,8 @@ public FluidPipeProperties modifyProperties(FluidPipeProperties baseProperties) return new FluidPipeProperties( baseProperties.maxFluidTemperature, baseProperties.throughput * capacityMultiplier, - baseProperties.gasProof); + baseProperties.gasProof, + channels); } @Override diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/ItemBlockFluidPipe.java b/src/main/java/gregtech/common/pipelike/fluidpipe/ItemBlockFluidPipe.java index d9d2a45889b..5c50abc6187 100644 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/ItemBlockFluidPipe.java +++ b/src/main/java/gregtech/common/pipelike/fluidpipe/ItemBlockFluidPipe.java @@ -26,5 +26,6 @@ public void addInformation(@Nonnull ItemStack stack, @Nullable World worldIn, Li tooltip.add(I18n.format("gregtech.fluid_pipe.throughput", pipeProperties.throughput * 20)); tooltip.add(I18n.format("gregtech.fluid_pipe.max_temperature", pipeProperties.maxFluidTemperature)); if (!pipeProperties.gasProof) tooltip.add(I18n.format("gregtech.fluid_pipe.non_gas_proof")); + if (pipeProperties.tanks > 1) tooltip.add(I18n.format("gregtech.fluid_pipe.channels", pipeProperties.tanks)); } } diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidNetHandler.java b/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidNetHandler.java new file mode 100644 index 00000000000..bbcf4d205b9 --- /dev/null +++ b/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidNetHandler.java @@ -0,0 +1,318 @@ +package gregtech.common.pipelike.fluidpipe.net; + +import gregtech.api.capability.GregtechTileCapabilities; +import gregtech.api.cover.CoverBehavior; +import gregtech.api.cover.ICoverable; +import gregtech.api.unification.material.properties.FluidPipeProperties; +import gregtech.common.covers.*; +import gregtech.common.pipelike.fluidpipe.tile.TileEntityFluidPipe; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.BlockPos; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.capability.FluidTankProperties; +import net.minecraftforge.fluids.capability.IFluidHandler; +import net.minecraftforge.fluids.capability.IFluidTankProperties; + +import javax.annotation.Nullable; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Objects; + +public class FluidNetHandler implements IFluidHandler { + + private final FluidPipeNet net; + private final TileEntityFluidPipe pipe; + private final EnumFacing facing; + private int simulatedTransfers = 0; + + public FluidNetHandler(FluidPipeNet net, TileEntityFluidPipe pipe, EnumFacing facing) { + this.net = net; + this.pipe = Objects.requireNonNull(pipe); + this.facing = facing; + } + + @Override + public IFluidTankProperties[] getTankProperties() { + FluidStack[] netFluids = pipe.getContainedFluids(); + FluidTankProperties[] properties = new FluidTankProperties[netFluids.length]; + for (int i = 0; i < netFluids.length; i++) { + properties[i] = new FluidTankProperties(netFluids[i], Integer.MAX_VALUE, true, false); + } + return properties; + } + + @Override + public int fill(FluidStack resource, boolean doFill) { + if (resource == null || resource.amount <= 0 || resource.getFluid() == null) return 0; + if ((pipe.findChannel(resource)) < 0) return 0; + simulatedTransfers = 0; + CoverBehavior pipeCover = getCoverOnPipe(pipe.getPipePos(), facing); + CoverBehavior tileCover = getCoverOnNeighbour(pipe.getPipePos(), facing); + + boolean pipePump = pipeCover instanceof CoverPump, tilePump = tileCover instanceof CoverPump; + // abort if there are two conveyors + if (pipePump && tilePump) return 0; + + if (tileCover != null && !checkImportCover(tileCover, false, resource)) + return 0; + + if (!pipePump && !tilePump) + return insertFirst(resource, doFill); + + CoverPump pump = (CoverPump) (pipePump ? pipeCover : tileCover); + if (pump.getPumpMode() == (pipePump ? CoverPump.PumpMode.IMPORT : CoverPump.PumpMode.EXPORT) && + pump.getDistributionMode() == DistributionMode.ROUND_ROBIN) { + return insertRoundRobin(resource, doFill); + } + + return insertFirst(resource, doFill); + } + + public boolean checkImportCover(CoverBehavior cover, boolean onPipe, FluidStack stack) { + if (cover instanceof CoverFluidFilter) { + CoverFluidFilter filter = (CoverFluidFilter) cover; + return (filter.getFilterMode() != FluidFilterMode.FILTER_BOTH && + (filter.getFilterMode() != FluidFilterMode.FILTER_FILL || !onPipe) && + (filter.getFilterMode() != FluidFilterMode.FILTER_DRAIN || onPipe)) || filter.testFluidStack(stack); + } + return true; + } + + protected List createHandlers() { + List handlers = new ArrayList<>(); + for (FluidPipeNet.Inventory inv : net.getNetData(pipe.getPipePos())) { + if (pipe.getPipePos().equals(inv.getPipePos()) && (facing == null || facing == inv.getFaceToHandler())) + continue; + IFluidHandler handler = inv.getHandler(pipe.getPipeWorld()); + if (handler != null) + handlers.add(new Handler(handler, inv)); + } + return handlers; + } + + protected int insertFirst(FluidStack stack, boolean doFill) { + int amount = stack.amount; + for (Handler handler : createHandlers()) { + stack.amount -= insert(handler, stack, doFill); + if (stack.amount == 0) + return amount; + } + return amount - stack.amount; + } + + protected int insertRoundRobin(FluidStack stack, boolean doFill) { + List handlers = createHandlers(); + int amount = stack.amount; + + if (handlers.size() == 0) + return 0; + if (handlers.size() == 1) + return insert(handlers.get(0), stack, doFill); + stack.amount -= insertToHandlers(handlers, stack, doFill); + if (stack.amount != 0 && handlers.size() > 0) + stack.amount -= insertToHandlers(handlers, stack, doFill); + return amount - stack.amount; + } + + public int insertToHandlers(List handlers, FluidStack stack, boolean doFill) { + Iterator handlerIterator = handlers.iterator(); + int inserted = 0; + int count = stack.amount; + int c = count / handlers.size(); + int m = count % handlers.size(); + while (handlerIterator.hasNext()) { + int amount = c; + if (m > 0) { + amount++; + m--; + } + if (amount == 0) break; + FluidStack toInsert = stack.copy(); + toInsert.amount = amount; + Handler handler = handlerIterator.next(); + int i = insert(handler, toInsert, doFill); + if (i > 0) + inserted += i; + if (i < amount) + handlerIterator.remove(); + } + return inserted; + } + + private int insert(Handler handler, FluidStack stack, boolean doFill) { + int allowed = checkTransferable(pipe, handler.getMinThroughput(), stack.amount, doFill); + if (allowed == 0) return 0; + CoverBehavior pipeCover = getCoverOnPipe(handler.getPipePos(), handler.getFaceToHandler()); + CoverBehavior tileCover = getCoverOnNeighbour(handler.getPipePos(), handler.getFaceToHandler()); + if (pipeCover instanceof CoverFluidRegulator && tileCover instanceof CoverFluidRegulator) + return 0; + if (pipeCover != null && !checkExportCover(pipeCover, true, stack)) + return 0; + + if (pipeCover instanceof CoverFluidRegulator && ((CoverFluidRegulator) pipeCover).getPumpMode() == CoverPump.PumpMode.EXPORT) + return insertOverRegulator(handler, (CoverFluidRegulator) pipeCover, stack, doFill, allowed); + if (tileCover instanceof CoverFluidRegulator && ((CoverFluidRegulator) tileCover).getPumpMode() == CoverPump.PumpMode.IMPORT) + return insertOverRegulator(handler, (CoverFluidRegulator) tileCover, stack, doFill, allowed); + + return insert(handler, stack, doFill, allowed); + } + + private int insert(Handler handler, FluidStack stack, boolean doFill, int max) { + if(stack == null || stack.amount <= 0 || max <= 0) return 0; + + for (TileEntityFluidPipe tickingPipe : handler.getHoldingPipes()) + if (!tickingPipe.findAndSetChannel(stack)) + return 0; + + IFluidHandler fluidHandler = handler.handler; + // check every pipe in path, but only if the last transferred fluid is not the same as the current + if (!stack.isFluidEqual(handler.getLastTransferredFluid())) { + boolean isGaseous = stack.getFluid().isGaseous(stack); + int temp = stack.getFluid().getTemperature(stack); + for (Object o : handler.getObjectsInPath()) { + if (o instanceof TileEntityFluidPipe) { + TileEntityFluidPipe pipe = (TileEntityFluidPipe) o; + FluidPipeProperties properties = pipe.getNodeData(); + boolean isLeakingPipe = isGaseous && !properties.gasProof; + boolean isBurningPipe = temp > properties.maxFluidTemperature; + if (isLeakingPipe || isBurningPipe) { + net.destroyNetwork(pipe.getPos(), isLeakingPipe, isBurningPipe, temp); + return 0; + } + } else if (o instanceof CoverFluidFilter) { + if (!((CoverFluidFilter) o).testFluidStack(stack)) + return 0; + } + } + handler.setLastTransferredFluid(stack); + } + + if (max >= stack.amount) { + int inserted = fluidHandler.fill(stack, doFill); + if (inserted > 0) { + stack.amount = inserted; + if (doFill) + for (TileEntityFluidPipe tickingPipe : handler.getHoldingPipes()) + tickingPipe.setContainingFluid(stack, tickingPipe.getCurrentChannel()); + transfer(pipe, doFill, inserted); + } + return inserted; + } + FluidStack toInsert = stack.copy(); + toInsert.amount = Math.min(max, stack.amount); + int inserted = fluidHandler.fill(toInsert, doFill); + if (inserted > 0) { + toInsert.amount = inserted; + if (doFill) + for (TileEntityFluidPipe tickingPipe : handler.getHoldingPipes()) + tickingPipe.setContainingFluid(toInsert, tickingPipe.getCurrentChannel()); + transfer(pipe, doFill, inserted); + } + return inserted; + } + + public int insertOverRegulator(Handler handler, CoverFluidRegulator regulator, FluidStack stack, boolean doFill, int allowed) { + int rate = regulator.getTransferAmount(); + int count; + switch (regulator.getTransferMode()) { + case TRANSFER_ANY: + return insert(handler, stack, doFill, allowed); + case KEEP_EXACT: + count = rate - countStack(handler.handler, stack, regulator); + if (count <= 0) return 0; + count = Math.min(allowed, Math.min(stack.amount, count)); + return insert(handler, stack, doFill, count); + case TRANSFER_EXACT: + //int max = allowed + regulator.getBuffer(); + count = Math.min(allowed, Math.min(rate, stack.amount)); + if (count < rate) { + return 0; + } + if (insert(handler, stack, false, count) != rate) { + return 0; + } + return insert(handler, stack, doFill, count); + } + return 0; + } + + public int countStack(IFluidHandler handler, FluidStack stack, CoverFluidRegulator arm) { + if (arm == null) return 0; + int count = 0; + for (IFluidTankProperties property : handler.getTankProperties()) { + FluidStack tank = property.getContents(); + if (tank == null) continue; + if (tank.isFluidEqual(stack)) { + count += tank.amount; + } + } + return count; + } + + public boolean checkExportCover(CoverBehavior cover, boolean onPipe, FluidStack stack) { + if (cover instanceof CoverFluidFilter) { + CoverFluidFilter filter = (CoverFluidFilter) cover; + return (filter.getFilterMode() != FluidFilterMode.FILTER_BOTH && + (filter.getFilterMode() != FluidFilterMode.FILTER_FILL || onPipe) && + (filter.getFilterMode() != FluidFilterMode.FILTER_DRAIN || !onPipe)) || filter.testFluidStack(stack); + } + return true; + } + + public CoverBehavior getCoverOnPipe(BlockPos pos, EnumFacing handlerFacing) { + TileEntity tile = pipe.getWorld().getTileEntity(pos); + if (tile instanceof TileEntityFluidPipe) { + ICoverable coverable = ((TileEntityFluidPipe) tile).getCoverableImplementation(); + return coverable.getCoverAtSide(handlerFacing); + } + return null; + } + + public CoverBehavior getCoverOnNeighbour(BlockPos pos, EnumFacing handlerFacing) { + TileEntity tile = pipe.getWorld().getTileEntity(pos.offset(handlerFacing)); + if (tile != null) { + ICoverable coverable = tile.getCapability(GregtechTileCapabilities.CAPABILITY_COVERABLE, handlerFacing.getOpposite()); + if (coverable == null) return null; + return coverable.getCoverAtSide(handlerFacing.getOpposite()); + } + return null; + } + + private int checkTransferable(TileEntityFluidPipe pipe, int throughput, int amount, boolean doFill) { + if (doFill) + return Math.max(0, Math.min(throughput - pipe.getTransferredFluids(), amount)); + else + return Math.max(0, Math.min(throughput - (pipe.getTransferredFluids() + simulatedTransfers), amount)); + } + + private void transfer(TileEntityFluidPipe pipe, boolean doFill, int amount) { + if (doFill) { + pipe.transferFluid(amount); + } else + simulatedTransfers += amount; + } + + @Nullable + @Override + public FluidStack drain(FluidStack resource, boolean doDrain) { + return null; + } + + @Nullable + @Override + public FluidStack drain(int maxDrain, boolean doDrain) { + return null; + } + + private static class Handler extends FluidPipeNet.Inventory { + private final IFluidHandler handler; + + public Handler(IFluidHandler handler, FluidPipeNet.Inventory inv) { + super(inv.getPipePos(), inv.getFaceToHandler(), inv.getDistance(), inv.getObjectsInPath(), inv.getMinThroughput(), inv.getHoldingPipes()); + setLastTransferredFluid(inv.getLastTransferredFluid()); + this.handler = handler; + } + } +} diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidNetTank.java b/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidNetTank.java deleted file mode 100644 index 0541021a3ab..00000000000 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidNetTank.java +++ /dev/null @@ -1,75 +0,0 @@ -package gregtech.common.pipelike.fluidpipe.net; - -import com.google.common.base.Preconditions; -import gregtech.api.unification.material.properties.FluidPipeProperties; -import gregtech.api.util.PerTickIntCounter; -import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.fluids.FluidTank; - -public class FluidNetTank extends FluidTank { - - private final FluidPipeNet handle; - private final PerTickIntCounter drainedThisTick = new PerTickIntCounter(0); - - public FluidNetTank(FluidPipeNet handle) { - super(0); - this.handle = handle; - } - - private int getMaxThroughput() { - return handle.getMaxThroughput(); - } - - @Override - public int fill(FluidStack resource, boolean doFill) { - Preconditions.checkNotNull(resource, "resource"); - FluidStack copyStack = resource.copy(); - copyStack.amount = Math.min(copyStack.amount, getMaxThroughput()); - FluidPipeProperties properties = handle.getNodeData(); - boolean isLeakingPipe = copyStack.getFluid().isGaseous(copyStack) && !properties.gasProof; - boolean isBurningPipe = copyStack.getFluid().getTemperature(copyStack) > properties.maxFluidTemperature; - if (isLeakingPipe || isBurningPipe) { - handle.destroyNetwork(isLeakingPipe, isBurningPipe); - return copyStack.amount; - } - return super.fill(copyStack, doFill); - } - - @Override - public FluidStack drain(FluidStack resource, boolean doDrain) { - if (resource == null) { - return null; - } - int maxDrainLeftThisTick = getMaxThroughput() - drainedThisTick.get(handle.getWorldData()); - int originalAmount = resource.amount; - resource.amount = Math.min(originalAmount, maxDrainLeftThisTick); - FluidStack resultDrained = super.drain(resource, doDrain); - resource.amount = originalAmount; - if (resultDrained != null && doDrain) { - drainedThisTick.increment(handle.getWorldData(), resultDrained.amount); - } - return resultDrained; - } - - @Override - public FluidStack drain(int maxDrain, boolean doDrain) { - int maxDrainLeftThisTick = getMaxThroughput() - drainedThisTick.get(handle.getWorldData()); - maxDrain = Math.min(maxDrain, maxDrainLeftThisTick); - if (maxDrain == 0) { - return null; - } - FluidStack resultDrained = super.drain(maxDrain, doDrain); - if (resultDrained != null && doDrain) { - drainedThisTick.increment(handle.getWorldData(), resultDrained.amount); - } - return resultDrained; - } - - public void updateTankCapacity(int newTankCapacity) { - this.capacity = newTankCapacity; - if (this.fluid != null) { - this.fluid.amount = Math.min(this.fluid.amount, newTankCapacity); - } - } - -} diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidNetWalker.java b/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidNetWalker.java new file mode 100644 index 00000000000..764b8771017 --- /dev/null +++ b/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidNetWalker.java @@ -0,0 +1,145 @@ +package gregtech.common.pipelike.fluidpipe.net; + +import gregtech.api.capability.GregtechTileCapabilities; +import gregtech.api.cover.CoverBehavior; +import gregtech.api.cover.ICoverable; +import gregtech.api.pipenet.PipeNet; +import gregtech.api.pipenet.PipeNetWalker; +import gregtech.api.pipenet.tile.IPipeTile; +import gregtech.common.covers.CoverFluidFilter; +import gregtech.common.pipelike.fluidpipe.tile.TileEntityFluidPipe; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import net.minecraftforge.fluids.capability.CapabilityFluidHandler; +import net.minecraftforge.fluids.capability.IFluidHandler; + +import javax.annotation.Nullable; +import java.util.*; + +public class FluidNetWalker extends PipeNetWalker { + + public static List createNetData(FluidPipeNet net, World world, BlockPos sourcePipe) { + FluidNetWalker walker = new FluidNetWalker(net, world, sourcePipe, 1, new ArrayList<>(), new HashSet<>(), Integer.MAX_VALUE, new ArrayList<>()); + TileEntity tile = world.getTileEntity(sourcePipe); + if(tile instanceof TileEntityFluidPipe) + walker.holdingPipes.add((TileEntityFluidPipe) tile); + walker.traversePipeNet(); + return walker.inventories; + } + + private final List inventories; + private final Set pathObjects; + private final List holdingPipes; + private final Map> covers = new HashMap<>(); + private LinkedList checkedCovers = new LinkedList<>(); + private int rate; + + protected FluidNetWalker(PipeNet net, World world, BlockPos sourcePipe, int walkedBlocks, List inventories, Set pathObjects, int rate, List holdingPipes) { + super(net, world, sourcePipe, walkedBlocks); + this.inventories = inventories; + this.pathObjects = pathObjects; + this.rate = rate; + this.holdingPipes = holdingPipes; + } + + @Override + protected PipeNetWalker createSubWalker(PipeNet net, World world, BlockPos nextPos, int walkedBlocks) { + Set pathObjectsCopy = new HashSet<>(pathObjects); + List fluidFilter = covers.get(nextPos); + if(fluidFilter != null) + pathObjectsCopy.addAll(fluidFilter); + FluidNetWalker walker = new FluidNetWalker(net, world, nextPos, walkedBlocks, inventories, pathObjectsCopy, rate, new ArrayList<>(holdingPipes)); + walker.checkedCovers = checkedCovers; + return walker; + } + + @Override + protected void checkPipe(IPipeTile pipeTile, BlockPos pos) { + pathObjects.addAll(covers.values()); + covers.clear(); + pathObjects.add(pipeTile); + while (checkedCovers.size() > 12) { + checkedCovers.removeFirst(); + } + this.rate = Math.min(this.rate, ((TileEntityFluidPipe) pipeTile).getNodeData().throughput); + int validPipes = 0; + for (EnumFacing facing : EnumFacing.values()) { + BlockPos offset = pos.offset(facing); + EnumFacing opposite = facing.getOpposite(); + TileEntity tile = pipeTile.getPipeWorld().getTileEntity(offset); + if (tile instanceof TileEntityFluidPipe) { + if(!checkedCovers.contains(new PosFace(pos, facing))) { + CoverBehavior cover = pipeTile.getCoverableImplementation().getCoverAtSide(facing); + if(cover instanceof CoverFluidFilter) + putFilter(offset, cover); + } + ICoverable coverable = tile.getCapability(GregtechTileCapabilities.CAPABILITY_COVERABLE, opposite); + PosFace posFace = new PosFace(offset, opposite); + if(!checkedCovers.contains(posFace)) + checkedCovers.addLast(posFace); + if(coverable != null) { + CoverBehavior cover2 = coverable.getCoverAtSide(opposite); + if(cover2 instanceof CoverFluidFilter) + putFilter(offset, cover2); + } + validPipes++; + } + } + if (validPipes > 2) { + holdingPipes.add((TileEntityFluidPipe) pipeTile); + } + } + + private void putFilter(BlockPos pos, CoverBehavior cover) { + List coverFluidFilters = covers.get(pos); + if(coverFluidFilters == null) + coverFluidFilters = new ArrayList<>(); + coverFluidFilters.add((CoverFluidFilter) cover); + covers.put(pos, coverFluidFilters); + } + + @Override + protected void checkNeighbour(IPipeTile pipeTile, BlockPos pipePos, EnumFacing faceToNeighbour, @Nullable TileEntity neighbourTile) { + if (neighbourTile == null) return; + IFluidHandler handler = neighbourTile.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, faceToNeighbour.getOpposite()); + if (handler != null) { + Set pathObjectsCopy = new HashSet<>(pathObjects); + List fluidFilter = covers.get(pipePos.offset(faceToNeighbour)); + if(fluidFilter != null) + pathObjectsCopy.addAll(fluidFilter); + List holders = new ArrayList<>(holdingPipes); + holders.add((TileEntityFluidPipe) pipeTile); + inventories.add(new FluidPipeNet.Inventory(new BlockPos(pipePos), faceToNeighbour, getWalkedBlocks(), pathObjectsCopy, rate, holders)); + } + } + + @Override + protected boolean isValidPipe(IPipeTile currentPipe, IPipeTile neighbourPipe, BlockPos pipePos, EnumFacing faceToNeighbour) { + return neighbourPipe instanceof TileEntityFluidPipe; + } + + private static class PosFace { + private final BlockPos pos; + private final EnumFacing face; + + private PosFace(BlockPos pos, EnumFacing face) { + this.pos = pos; + this.face = face; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + PosFace posFace = (PosFace) o; + return Objects.equals(pos, posFace.pos) && face == posFace.face; + } + + @Override + public int hashCode() { + return Objects.hash(pos, face); + } + } +} diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidPipeNet.java b/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidPipeNet.java index 1f655b7890e..d9ff384d4d5 100644 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidPipeNet.java +++ b/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidPipeNet.java @@ -1,11 +1,13 @@ package gregtech.common.pipelike.fluidpipe.net; -import gregtech.api.pipenet.MonolithicPipeNet; import gregtech.api.pipenet.Node; +import gregtech.api.pipenet.PipeGatherer; import gregtech.api.pipenet.PipeNet; import gregtech.api.pipenet.WorldPipeNet; +import gregtech.api.pipenet.tile.IPipeTile; import gregtech.api.unification.material.properties.FluidPipeProperties; import gregtech.common.pipelike.fluidpipe.tile.TileEntityFluidPipe; +import gregtech.common.pipelike.fluidpipe.tile.TileEntityFluidPipeTickable; import net.minecraft.init.Blocks; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; @@ -14,107 +16,71 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.fluids.FluidTank; +import net.minecraftforge.fluids.capability.CapabilityFluidHandler; +import net.minecraftforge.fluids.capability.IFluidHandler; -import java.util.Map; -import java.util.Random; +import java.util.*; -public class FluidPipeNet extends MonolithicPipeNet { +public class FluidPipeNet extends PipeNet { - private final FluidNetTank fluidNetTank = new FluidNetTank(this); + private final Map> NET_DATA = new HashMap<>(); public FluidPipeNet(WorldPipeNet world) { super(world); } - public FluidTank getFluidNetTank() { - return fluidNetTank; + public List getNetData(BlockPos pipePos) { + return NET_DATA.computeIfAbsent(pipePos, pos -> { + List data = FluidNetWalker.createNetData(this, getWorldData(), pos); + data.sort(Comparator.comparingInt(inv -> inv.distance)); + return data; + }); } - public int getMaxThroughput() { - if (fluidNetTank.getCapacity() == 0) { - return 0; - } - return nodeData.throughput; + public void nodeNeighbourChanged(BlockPos pos) { + NET_DATA.clear(); } - public void destroyNetwork(boolean isLeaking, boolean isBurning) { - World world = worldData.getWorld(); - ((WorldFluidPipeNet) (Object) worldData).removePipeNet(this); - for (BlockPos nodePos : getAllNodes().keySet()) { - TileEntity tileEntity = world.getTileEntity(nodePos); - if (tileEntity instanceof TileEntityFluidPipe) { - if (isBurning) { - world.setBlockState(nodePos, Blocks.FIRE.getDefaultState()); - } else { - world.setBlockToAir(nodePos); - } - } + @Override + protected void updateBlockedConnections(BlockPos nodePos, EnumFacing facing, boolean isBlocked) { + super.updateBlockedConnections(nodePos, facing, isBlocked); + NET_DATA.clear(); + } + public void destroyNetwork(BlockPos source, boolean isLeaking, boolean isBurning, int temp) { + World world = getWorldData(); + List> pipes = PipeGatherer.gatherPipesInDistance(this, world, source, pipe -> { + if (pipe instanceof TileEntityFluidPipe) { + TileEntityFluidPipe fluidPipe = (TileEntityFluidPipe) pipe; + return (isBurning && fluidPipe.getNodeData().maxFluidTemperature < temp) || (isLeaking && !fluidPipe.getNodeData().gasProof); + } + return false; + }, 2 + world.rand.nextInt(4)); + for (IPipeTile pipeTile : pipes) { + BlockPos pos = pipeTile.getPipePos(); Random random = world.rand; if (isBurning) { - TileEntityFluidPipe.spawnParticles(world, nodePos, EnumFacing.UP, + world.setBlockState(pos, Blocks.FIRE.getDefaultState()); + TileEntityFluidPipe.spawnParticles(world, pos, EnumFacing.UP, EnumParticleTypes.FLAME, 3 + random.nextInt(2), random); - if (random.nextInt(4) == 0) { - TileEntityFluidPipe.setNeighboursToFire(world, nodePos); - } - } + if (random.nextInt(4) == 0) + TileEntityFluidPipe.setNeighboursToFire(world, pos); + } else + world.setBlockToAir(pos); if (isLeaking && world.rand.nextInt(isBurning ? 3 : 7) == 0) { world.createExplosion(null, - nodePos.getX() + 0.5, nodePos.getY() + 0.5, nodePos.getZ() + 0.5, + pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5, 1.0f + world.rand.nextFloat(), false); } } } - @Override - protected void onConnectionsUpdate() { - super.onConnectionsUpdate(); - //monolithic net always contains exactly one kind of nodes, so this is always safe - int newTankCapacity = nodeData.throughput * getAllNodes().size(); - fluidNetTank.updateTankCapacity(newTankCapacity); - } - @Override protected void transferNodeData(Map> transferredNodes, PipeNet parentNet1) { super.transferNodeData(transferredNodes, parentNet1); FluidPipeNet parentNet = (FluidPipeNet) parentNet1; - FluidStack parentFluid = parentNet.getFluidNetTank().getFluid(); - if (parentFluid != null && parentFluid.amount > 0) { - if (parentNet.getAllNodes().isEmpty()) { - //if this is merge of pipe nets, just add all fluid to our internal tank - //use fillInternal to ignore throughput restrictions - getFluidNetTank().fillInternal(parentFluid, true); - } else { - //otherwise, it is donating of some nodes to our net in result of split - //so, we should establish equal amount of fluid in networks - int firstNetCapacity = getAllNodes().size() * getNodeData().throughput; - int secondNetCapacity = parentNet.getAllNodes().size() * parentNet.getNodeData().throughput; - int totalFluidAmount = getFluidNetTank().getFluidAmount() + parentFluid.amount; - int fluidAmount1 = totalFluidAmount * firstNetCapacity / (firstNetCapacity + secondNetCapacity); - int fluidAmount2 = totalFluidAmount - fluidAmount1; - - if (fluidAmount1 > 0) { - FluidStack fluidStack1 = parentFluid.copy(); - fluidStack1.amount = fluidAmount1; - fluidNetTank.setFluid(fluidStack1); - } else fluidNetTank.setFluid(null); - - if (fluidAmount2 > 0) { - FluidStack fluidStack2 = parentFluid.copy(); - fluidStack2.amount = fluidAmount2; - parentNet.getFluidNetTank().setFluid(fluidStack2); - } else parentNet.getFluidNetTank().setFluid(null); - } - } - } - - @Override - protected boolean areNodesCustomContactable(FluidPipeProperties first, FluidPipeProperties second, PipeNet secondNodeNet) { - FluidPipeNet fluidPipeNet = (FluidPipeNet) secondNodeNet; - return super.areNodesCustomContactable(first, second, secondNodeNet) && - (secondNodeNet == null || getFluidNetTank().getFluid() == null || fluidPipeNet.getFluidNetTank().getFluid() == null || - getFluidNetTank().getFluid().isFluidEqual(fluidPipeNet.getFluidNetTank().getFluid())); + NET_DATA.clear(); + parentNet.NET_DATA.clear(); } @Override @@ -122,6 +88,7 @@ protected void writeNodeData(FluidPipeProperties nodeData, NBTTagCompound tagCom tagCompound.setInteger("max_temperature", nodeData.maxFluidTemperature); tagCompound.setInteger("throughput", nodeData.throughput); tagCompound.setBoolean("gas_proof", nodeData.gasProof); + tagCompound.setInteger("channels", nodeData.tanks); } @Override @@ -129,21 +96,70 @@ protected FluidPipeProperties readNodeData(NBTTagCompound tagCompound) { int maxTemperature = tagCompound.getInteger("max_temperature"); int throughput = tagCompound.getInteger("throughput"); boolean gasProof = tagCompound.getBoolean("gas_proof"); - return new FluidPipeProperties(maxTemperature, throughput, gasProof); + int channels = tagCompound.getInteger("channels"); + return new FluidPipeProperties(maxTemperature, throughput, gasProof, channels); } - @Override - public NBTTagCompound serializeNBT() { - NBTTagCompound nbt = super.serializeNBT(); - nbt.setTag("FluidTankNet", this.fluidNetTank.writeToNBT(new NBTTagCompound())); - return nbt; - } + public static class Inventory { + private final BlockPos pipePos; + private final EnumFacing faceToHandler; + private final int distance; + private final Set objectsInPath; + private final int minRate; + private FluidStack lastTransferredFluid; + private final List holdingPipes; + + public Inventory(BlockPos pipePos, EnumFacing facing, int distance, Set objectsInPath, int minRate, List holdingPipes) { + this.pipePos = pipePos; + this.faceToHandler = facing; + this.distance = distance; + this.objectsInPath = objectsInPath; + this.minRate = minRate; + this.holdingPipes = holdingPipes; + } - @Override - public void deserializeNBT(NBTTagCompound nbt) { - super.deserializeNBT(nbt); - if (nbt.hasKey("FluidTankNet")) - this.fluidNetTank.readFromNBT(nbt.getCompoundTag("FluidTankNet")); + public void setLastTransferredFluid(FluidStack lastTransferredFluid) { + this.lastTransferredFluid = lastTransferredFluid; + } + + public FluidStack getLastTransferredFluid() { + return lastTransferredFluid; + } + + public Set getObjectsInPath() { + return objectsInPath; + } + + public int getMinThroughput() { + return minRate; + } + + public List getHoldingPipes() { + return holdingPipes; + } + + public BlockPos getPipePos() { + return pipePos; + } + + public EnumFacing getFaceToHandler() { + return faceToHandler; + } + + public int getDistance() { + return distance; + } + + public BlockPos getHandlerPos() { + return pipePos.offset(faceToHandler); + } + + public IFluidHandler getHandler(World world) { + TileEntity tile = world.getTileEntity(getHandlerPos()); + if (tile != null) + return tile.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, faceToHandler.getOpposite()); + return null; + } } } diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/net/WorldFluidPipeNet.java b/src/main/java/gregtech/common/pipelike/fluidpipe/net/WorldFluidPipeNet.java index a9dcb7269fe..274336c456d 100644 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/net/WorldFluidPipeNet.java +++ b/src/main/java/gregtech/common/pipelike/fluidpipe/net/WorldFluidPipeNet.java @@ -9,7 +9,7 @@ public class WorldFluidPipeNet extends WorldPipeNet pipeTile; - private WeakReference currentPipeNet = new WeakReference<>(null); - - public FluidPipeFluidHandler(IPipeTile pipeTile) { - this.pipeTile = pipeTile; - } - - @Override - public IFluidTankProperties[] getTankProperties() { - FluidTank fluidTank = getNetFluidTank(); - return fluidTank == null ? new IFluidTankProperties[0] : fluidTank.getTankProperties(); - } - - @Override - public int fill(FluidStack resource, boolean doFill) { - FluidTank fluidTank = getNetFluidTank(); - return fluidTank == null ? 0 : fluidTank.fill(resource, doFill); - } - - @Nullable - @Override - public FluidStack drain(FluidStack resource, boolean doDrain) { - FluidTank fluidTank = getNetFluidTank(); - return fluidTank == null ? null : fluidTank.drain(resource, doDrain); - } - - @Nullable - @Override - public FluidStack drain(int maxDrain, boolean doDrain) { - FluidTank fluidTank = getNetFluidTank(); - return fluidTank == null ? null : fluidTank.drain(maxDrain, doDrain); - } - - protected FluidTank getNetFluidTank() { - FluidPipeNet fluidPipeNet = getFluidPipeNet(); - return fluidPipeNet == null ? null : fluidPipeNet.getFluidNetTank(); - } - - public FluidPipeNet getFluidPipeNet() { - FluidPipeNet currentPipeNet = this.currentPipeNet.get(); - if (currentPipeNet != null && currentPipeNet.isValid() && - currentPipeNet.containsNode(pipeTile.getPipePos())) - return currentPipeNet; //if current net is valid and does contain position, return it - WorldFluidPipeNet worldFluidPipeNet = (WorldFluidPipeNet) pipeTile.getPipeBlock().getWorldPipeNet(pipeTile.getPipeWorld()); - currentPipeNet = worldFluidPipeNet.getNetFromPos(pipeTile.getPipePos()); - if (currentPipeNet != null) { - this.currentPipeNet = new WeakReference<>(currentPipeNet); - } - return currentPipeNet; - } - -} diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/tile/TileEntityFluidPipe.java b/src/main/java/gregtech/common/pipelike/fluidpipe/tile/TileEntityFluidPipe.java index 05a27794db0..732387580f7 100644 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/tile/TileEntityFluidPipe.java +++ b/src/main/java/gregtech/common/pipelike/fluidpipe/tile/TileEntityFluidPipe.java @@ -2,24 +2,35 @@ import gregtech.api.pipenet.block.material.TileEntityMaterialPipeBase; import gregtech.api.unification.material.properties.FluidPipeProperties; +import gregtech.api.util.PerTickIntCounter; +import gregtech.api.util.TickingObjectHolder; import gregtech.common.pipelike.fluidpipe.FluidPipeType; +import gregtech.common.pipelike.fluidpipe.net.FluidNetHandler; +import gregtech.common.pipelike.fluidpipe.net.FluidPipeNet; +import gregtech.common.pipelike.fluidpipe.net.WorldFluidPipeNet; import net.minecraft.block.state.IBlockState; import net.minecraft.init.Blocks; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumParticleTypes; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.capability.CapabilityFluidHandler; -import net.minecraftforge.fluids.capability.IFluidHandler; import javax.annotation.Nullable; +import java.lang.ref.WeakReference; import java.util.Random; public class TileEntityFluidPipe extends TileEntityMaterialPipeBase { + private WeakReference currentPipeNet = new WeakReference<>(null); private static final Random random = new Random(); - private IFluidHandler fluidHandler; + private TickingObjectHolder[] fluidHolders; + private final PerTickIntCounter transferredFluids = new PerTickIntCounter(0); + private int currentChannel = -1; public TileEntityFluidPipe() { } @@ -34,22 +45,148 @@ public boolean supportsTicking() { return false; } - protected IFluidHandler getFluidHandler() { - if (fluidHandler == null) { - this.fluidHandler = new FluidPipeFluidHandler(this); - } - return fluidHandler; - } - @Nullable @Override public T getCapabilityInternal(Capability capability, @Nullable EnumFacing facing) { if (capability == CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY) { - return CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY.cast(getFluidHandler()); + FluidPipeNet net = getFluidPipeNet(); + if (net == null) return null; + return CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY.cast(new FluidNetHandler(net, this, facing)); } return super.getCapabilityInternal(capability, facing); } + public void transferFluid(int amount) { + transferredFluids.increment(getWorld(), amount); + } + + public int getTransferredFluids() { + return transferredFluids.get(getWorld()); + } + + public int getCurrentChannel() { + return currentChannel; + } + + public FluidStack getContainedFluid(int channel) { + if (channel < 0) return null; + return getFluidHolders()[channel].getNullable(getWorld()); + } + + protected TickingObjectHolder[] getFluidHolders() { + if(fluidHolders == null) { + this.fluidHolders = new TickingObjectHolder[getNodeData().tanks]; + for(int i = 0; i < fluidHolders.length; i++) { + fluidHolders[i] = new TickingObjectHolder<>(null, 20); + } + } + return fluidHolders; + } + + public FluidStack[] getContainedFluids() { + FluidStack[] fluids = new FluidStack[getFluidHolders().length]; + for(int i = 0; i < fluids.length; i++) { + fluids[i] = fluidHolders[i].getNullable(getWorld()); + } + return fluids; + } + + public void setContainingFluid(FluidStack stack, int channel) { + if (channel < 0) return; + getFluidHolders()[channel].reset(stack); + this.currentChannel = -1; + } + + private void emptyTank(int channel) { + if (channel < 0) return; + this.getContainedFluids()[channel] = null; + } + + public boolean areTanksEmpty() { + for (FluidStack fluidStack : getContainedFluids()) + if (fluidStack != null) + return false; + return true; + } + + public boolean findAndSetChannel(FluidStack stack) { + int c = findChannel(stack); + this.currentChannel = c; + return c >= 0 && c < fluidHolders.length; + } + + /** + * Finds a channel for the given fluid + * + * @param stack to find a channel fot + * @return channel + */ + public int findChannel(FluidStack stack) { + if (getFluidHolders().length == 1) { + FluidStack channelStack = getContainedFluid(0); + return (channelStack == null || /*channelStack.amount <= 0 || */channelStack.isFluidEqual(stack)) ? 0 : -1; + } + int emptyTank = -1; + for (int i = fluidHolders.length - 1; i >= 0; i--) { + FluidStack channelStack = getContainedFluid(i); + if (channelStack == null/* || channelStack.amount <= 0*/) + emptyTank = i; + else if (channelStack.isFluidEqual(stack)) + return i; + } + return emptyTank; + } + + @Override + public NBTTagCompound writeToNBT(NBTTagCompound nbt) { + super.writeToNBT(nbt); + NBTTagList list = new NBTTagList(); + for (int i = 0; i < getFluidHolders().length; i++) { + FluidStack stack1 = getContainedFluid(i); + NBTTagCompound fluidTag = new NBTTagCompound(); + fluidTag.setLong("Timer", fluidHolders[i].getRemainingTime(getWorld())); + if (stack1 == null) + fluidTag.setBoolean("isNull", true); + else + stack1.writeToNBT(fluidTag); + list.appendTag(fluidTag); + } + nbt.setTag("Fluids", list); + return nbt; + } + + @Override + public void readFromNBT(NBTTagCompound nbt) { + super.readFromNBT(nbt); + NBTTagList list = (NBTTagList) nbt.getTag("Fluids"); + //fluids = new FluidStack[list.tagCount()]; + fluidHolders = new TickingObjectHolder[list.tagCount()]; + for(int i = 0; i < fluidHolders.length; i++) { + fluidHolders[i] = new TickingObjectHolder<>(null, 20); + } + //emptyTimer = new int[list.tagCount()]; + for (int i = 0; i < list.tagCount(); i++) { + NBTTagCompound tag = list.getCompoundTagAt(i); + //emptyTimer[i] = tag.getInteger("Timer"); + if (!tag.getBoolean("isNull")) { + fluidHolders[i].reset(FluidStack.loadFluidStackFromNBT(tag), tag.getInteger("Timer")); + } + } + } + + public FluidPipeNet getFluidPipeNet() { + FluidPipeNet currentPipeNet = this.currentPipeNet.get(); + if (currentPipeNet != null && currentPipeNet.isValid() && + currentPipeNet.containsNode(getPipePos())) + return currentPipeNet; //if current net is valid and does contain position, return it + WorldFluidPipeNet worldFluidPipeNet = (WorldFluidPipeNet) getPipeBlock().getWorldPipeNet(getPipeWorld()); + currentPipeNet = worldFluidPipeNet.getNetFromPos(getPipePos()); + if (currentPipeNet != null) { + this.currentPipeNet = new WeakReference<>(currentPipeNet); + } + return currentPipeNet; + } + public static void setNeighboursToFire(World world, BlockPos selfPos) { for (EnumFacing side : EnumFacing.VALUES) { if (!random.nextBoolean()) continue; diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/tile/TileEntityFluidPipeTickable.java b/src/main/java/gregtech/common/pipelike/fluidpipe/tile/TileEntityFluidPipeTickable.java index bdc7252151d..fbfedad51ba 100644 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/tile/TileEntityFluidPipeTickable.java +++ b/src/main/java/gregtech/common/pipelike/fluidpipe/tile/TileEntityFluidPipeTickable.java @@ -1,78 +1,16 @@ package gregtech.common.pipelike.fluidpipe.tile; -import gregtech.api.pipenet.tile.IPipeTile; -import gregtech.api.unification.material.properties.FluidPipeProperties; -import gregtech.api.util.GTFluidUtils; -import gregtech.common.pipelike.fluidpipe.BlockFluidPipe; -import gregtech.common.pipelike.fluidpipe.FluidPipeType; -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.EnumFacing; import net.minecraft.util.ITickable; -import net.minecraft.util.math.BlockPos.PooledMutableBlockPos; -import net.minecraftforge.fluids.capability.CapabilityFluidHandler; -import net.minecraftforge.fluids.capability.IFluidHandler; public class TileEntityFluidPipeTickable extends TileEntityFluidPipe implements ITickable { - private boolean isActive; - - public boolean isActive() { - return isActive; - } - - public void setActive(boolean active) { - isActive = active; - } - @Override public void update() { getCoverableImplementation().update(); - if (isActive) { - pushFluidsFromTank(this); - } } @Override public boolean supportsTicking() { return true; } - - @Override - public NBTTagCompound writeToNBT(NBTTagCompound compound) { - super.writeToNBT(compound); - compound.setBoolean("ActiveNode", isActive); - return compound; - } - - @Override - public void readFromNBT(NBTTagCompound compound) { - super.readFromNBT(compound); - this.isActive = compound.getBoolean("ActiveNode"); - } - - public static void pushFluidsFromTank(IPipeTile pipeTile) { - PooledMutableBlockPos blockPos = PooledMutableBlockPos.retain(); - BlockFluidPipe blockFluidPipe = (BlockFluidPipe) pipeTile.getPipeBlock(); - for (EnumFacing side : EnumFacing.VALUES) { - if (!pipeTile.isConnectionOpenVisual(side)) { - continue; //do not dispatch energy to blocked sides - } - blockPos.setPos(pipeTile.getPipePos()).move(side); - if (!pipeTile.getPipeWorld().isBlockLoaded(blockPos)) { - continue; //do not allow cables to load chunks - } - TileEntity tileEntity = pipeTile.getPipeWorld().getTileEntity(blockPos); - if (tileEntity == null) { - continue; //do not emit into multiparts or other fluid pipes - } - IFluidHandler sourceHandler = pipeTile.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, side); - IFluidHandler receiverHandler = tileEntity.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, side.getOpposite()); - if (sourceHandler != null && receiverHandler != null && blockFluidPipe.canPushIntoFluidHandler(pipeTile, tileEntity, sourceHandler, receiverHandler)) { - GTFluidUtils.transferFluids(sourceHandler, receiverHandler, Integer.MAX_VALUE); - } - } - blockPos.release(); - } - } diff --git a/src/main/java/gregtech/common/pipelike/itempipe/BlockItemPipe.java b/src/main/java/gregtech/common/pipelike/itempipe/BlockItemPipe.java index 134132f26be..104c27bb8a1 100644 --- a/src/main/java/gregtech/common/pipelike/itempipe/BlockItemPipe.java +++ b/src/main/java/gregtech/common/pipelike/itempipe/BlockItemPipe.java @@ -1,6 +1,7 @@ package gregtech.common.pipelike.itempipe; import com.google.common.base.Preconditions; +import gregtech.api.cover.CoverBehavior; import gregtech.api.pipenet.block.material.BlockMaterialPipe; import gregtech.api.pipenet.tile.IPipeTile; import gregtech.api.pipenet.tile.TileEntityPipeBase; @@ -66,20 +67,6 @@ public void neighborChanged(IBlockState state, World worldIn, BlockPos pos, Bloc } } - /*@Override - public int getActiveNodeConnections(IBlockAccess world, BlockPos nodePos, IPipeTile selfTileEntity) { - return getPipeTileEntity(world, nodePos).getBlockedConnections(); - /*int activeNodeConnections = 0; - for (EnumFacing side : EnumFacing.VALUES) { - BlockPos offsetPos = nodePos.offset(side); - TileEntity tileEntity = world.getTileEntity(offsetPos); - if (tileEntity != null && tileEntity.hasCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, side.getOpposite())) { - activeNodeConnections |= 1 << side.getIndex(); - } - } - return activeNodeConnections; - }*/ - @Override public Class getPipeTypeClass() { return ItemPipeType.class; @@ -135,39 +122,29 @@ public boolean canPipeConnectToBlock(IPipeTile return tile != null && tile.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, side.getOpposite()) != null; } - /*@Override - public int getActiveVisualConnections(IPipeTile selfTile) { - return selfTile.getBlockedConnections(); - /*int activeNodeConnections = 0; - for (EnumFacing side : EnumFacing.VALUES) { - BlockPos offsetPos = selfTile.getPipePos().offset(side); - TileEntity tileEntity = selfTile.getPipeWorld().getTileEntity(offsetPos); - if (tileEntity != null) { - EnumFacing opposite = side.getOpposite(); - IItemHandler sourceHandler = selfTile.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, side); - IItemHandler receivedHandler = tileEntity.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, opposite); - if (sourceHandler != null && receivedHandler != null) { - activeNodeConnections |= 1 << side.getIndex(); - } - } - } - return activeNodeConnections; - }*/ - + @Nonnull @Override - protected void onActiveModeChange(World world, BlockPos pos, boolean isActiveNow, boolean isInitialChange) { - TileEntityItemPipe oldTileEntity = (TileEntityItemPipe) world.getTileEntity(pos); - if (!(oldTileEntity instanceof TileEntityItemPipeTickable) && isActiveNow) { - TileEntityItemPipeTickable newTileEntity = new TileEntityItemPipeTickable(); - newTileEntity.transferDataFrom(oldTileEntity); - newTileEntity.setActive(true); - world.setTileEntity(pos, newTileEntity); - } else if (oldTileEntity instanceof TileEntityItemPipeTickable) { - ((TileEntityItemPipeTickable) oldTileEntity).setActive(isActiveNow); + public int getVisualConnections(IPipeTile selfTile) { + int connections = selfTile.getOpenConnections(); + float selfTHICCness = selfTile.getPipeType().getThickness(); + for (EnumFacing facing : EnumFacing.values()) { + CoverBehavior cover = selfTile.getCoverableImplementation().getCoverAtSide(facing); + if (cover != null) { + // adds side to open connections of it isn't already open & has a cover + connections |= 1 << facing.getIndex(); + continue; + } + // check if neighbour is a smaller item pipe + TileEntity neighbourTile = selfTile.getPipeWorld().getTileEntity(selfTile.getPipePos().offset(facing)); + if (neighbourTile instanceof TileEntityItemPipe && + ((TileEntityItemPipe) neighbourTile).isConnectionOpenAny(facing.getOpposite()) && + ((TileEntityItemPipe) neighbourTile).getPipeType().getThickness() < selfTHICCness) { + connections |= 1 << (facing.getIndex() + 6); + } } + return connections; } - @Nonnull @Override @SideOnly(Side.CLIENT) public EnumBlockRenderType getRenderType(@Nonnull IBlockState state) { diff --git a/src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetHandler.java b/src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetHandler.java index 9dc73b5b1e5..242a051a6c0 100644 --- a/src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetHandler.java +++ b/src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetHandler.java @@ -5,14 +5,12 @@ import gregtech.api.cover.ICoverable; import gregtech.api.util.GTUtility; import gregtech.api.util.ItemStackKey; -import gregtech.common.covers.CoverConveyor; -import gregtech.common.covers.CoverRoboticArm; +import gregtech.common.covers.*; import gregtech.common.pipelike.itempipe.tile.TileEntityItemPipe; import gregtech.common.pipelike.itempipe.tile.TileEntityItemPipeTickable; import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumFacing; -import net.minecraft.util.Tuple; import net.minecraft.util.math.BlockPos; import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.ItemHandlerHelper; @@ -44,15 +42,39 @@ public ItemNetHandler(ItemPipeNet net, TileEntityItemPipe pipe, EnumFacing facin public ItemStack insertItem(int slot, @Nonnull ItemStack stack, boolean simulate) { if (stack.isEmpty()) return stack; simulatedTransfers = 0; - Tuple tuple = getCoverAtPipe(pipe.getPos(), facing); - if (exportsToPipe(tuple)) { - if (tuple.getFirst().getDistributionMode() == CoverConveyor.ItemDistributionMode.ROUND_ROBIN) { - return insertRoundRobin(stack, simulate); - } + CoverBehavior pipeCover = getCoverOnPipe(pipe.getPipePos(), facing); + CoverBehavior tileCover = getCoverOnNeighbour(pipe.getPipePos(), facing); + + boolean pipeConveyor = pipeCover instanceof CoverConveyor, tileConveyor = tileCover instanceof CoverConveyor; + // abort if there are two conveyors + if (pipeConveyor && tileConveyor) return stack; + + if (tileCover != null && !checkImportCover(tileCover, false, stack)) + return stack; + + if (!pipeConveyor && !tileConveyor) + return insertFirst(stack, simulate); + + CoverConveyor conveyor = (CoverConveyor) (pipeConveyor ? pipeCover : tileCover); + if (conveyor.getConveyorMode() == (pipeConveyor ? CoverConveyor.ConveyorMode.IMPORT : CoverConveyor.ConveyorMode.EXPORT) && + conveyor.getDistributionMode() == DistributionMode.ROUND_ROBIN) { + return insertRoundRobin(stack, simulate); } + return insertFirst(stack, simulate); } + public boolean checkImportCover(CoverBehavior cover, boolean onPipe, ItemStack stack) { + if (cover == null) return true; + if (cover instanceof CoverItemFilter) { + CoverItemFilter filter = (CoverItemFilter) cover; + return (filter.getFilterMode() != ItemFilterMode.FILTER_BOTH && + (filter.getFilterMode() != ItemFilterMode.FILTER_INSERT || !onPipe) && + (filter.getFilterMode() != ItemFilterMode.FILTER_EXTRACT || onPipe)) || filter.testItemStack(stack); + } + return true; + } + public ItemStack insertFirst(ItemStack stack, boolean simulate) { for (ItemPipeNet.Inventory inv : net.getNetData(pipe.getPipePos())) { if (GTUtility.arePosEqual(pipe.getPipePos(), inv.getPipePos()) && (facing == null || facing == inv.getFaceToHandler())) @@ -132,19 +154,31 @@ public ItemStack insertToHandlers(List handlers, ItemStack stack, boole public ItemStack insert(Handler handler, ItemStack stack, boolean simulate) { int allowed = checkTransferable(pipe, handler.getProperties().transferRate, stack.getCount(), simulate); if (allowed == 0) return stack; - Tuple tuple = getCoverAtPipe(handler.getPipePos(), handler.getFaceToHandler()); - if (tuple != null) { - if (!tuple.getFirst().getItemFilterContainer().testItemStack(stack)) - return stack; - boolean exportsFromPipe = exportsToPipe(tuple); - if (tuple.getFirst() instanceof CoverRoboticArm && !exportsFromPipe) - return insertOverRobotArm(handler.handler, (CoverRoboticArm) tuple.getFirst(), tuple.getSecond(), stack, simulate, allowed); - if (exportsFromPipe && tuple.getFirst().blocksInput()) - return stack; - } + CoverBehavior pipeCover = getCoverOnPipe(handler.getPipePos(), handler.getFaceToHandler()); + CoverBehavior tileCover = getCoverOnNeighbour(handler.getPipePos(), handler.getFaceToHandler()); + if (pipeCover instanceof CoverRoboticArm && tileCover instanceof CoverRoboticArm) + return stack; + if (pipeCover != null && !checkExportCover(pipeCover, true, stack)) + return stack; + + if (pipeCover instanceof CoverRoboticArm && ((CoverRoboticArm) pipeCover).getConveyorMode() == CoverConveyor.ConveyorMode.EXPORT) + return insertOverRobotArm(handler.handler, (CoverRoboticArm) pipeCover, stack, simulate, allowed); + if (tileCover instanceof CoverRoboticArm && ((CoverRoboticArm) tileCover).getConveyorMode() == CoverConveyor.ConveyorMode.IMPORT) + return insertOverRobotArm(handler.handler, (CoverRoboticArm) tileCover, stack, simulate, allowed); + return insert(handler.handler, stack, simulate, allowed); } + public boolean checkExportCover(CoverBehavior cover, boolean onPipe, ItemStack stack) { + if (cover instanceof CoverItemFilter) { + CoverItemFilter filter = (CoverItemFilter) cover; + return (filter.getFilterMode() != ItemFilterMode.FILTER_BOTH && + (filter.getFilterMode() != ItemFilterMode.FILTER_INSERT || onPipe) && + (filter.getFilterMode() != ItemFilterMode.FILTER_EXTRACT || !onPipe)) || filter.testItemStack(stack); + } + return true; + } + private ItemStack insert(IItemHandler handler, ItemStack stack, boolean simulate, int allowed) { if (stack.getCount() == allowed) { ItemStack re = ItemHandlerHelper.insertItemStacked(handler, stack, simulate); @@ -160,30 +194,26 @@ private ItemStack insert(IItemHandler handler, ItemStack stack, boolean simulate return remainder; } - public Tuple getCoverAtPipe(BlockPos pipePos, EnumFacing handlerFacing) { - TileEntity tile = pipe.getWorld().getTileEntity(pipePos); + public CoverBehavior getCoverOnPipe(BlockPos pos, EnumFacing handlerFacing) { + TileEntity tile = pipe.getWorld().getTileEntity(pos); if (tile instanceof TileEntityItemPipe) { ICoverable coverable = ((TileEntityItemPipe) tile).getCoverableImplementation(); - CoverBehavior cover = coverable.getCoverAtSide(handlerFacing); - if (cover instanceof CoverConveyor) return new Tuple<>((CoverConveyor) cover, true); + return coverable.getCoverAtSide(handlerFacing); } - tile = pipe.getWorld().getTileEntity(pipePos.offset(handlerFacing)); + return null; + } + + public CoverBehavior getCoverOnNeighbour(BlockPos pos, EnumFacing handlerFacing) { + TileEntity tile = pipe.getWorld().getTileEntity(pos.offset(handlerFacing)); if (tile != null) { - ICoverable coverable = tile.getCapability(GregtechTileCapabilities.CAPABILITY_COVERABLE, null); + ICoverable coverable = tile.getCapability(GregtechTileCapabilities.CAPABILITY_COVERABLE, handlerFacing.getOpposite()); if (coverable == null) return null; - CoverBehavior cover = coverable.getCoverAtSide(handlerFacing.getOpposite()); - if (cover instanceof CoverConveyor) return new Tuple<>((CoverConveyor) cover, false); + return coverable.getCoverAtSide(handlerFacing.getOpposite()); } return null; } - public boolean exportsToPipe(Tuple tuple) { - return tuple != null && (tuple.getSecond() ? - tuple.getFirst().getConveyorMode() == CoverConveyor.ConveyorMode.IMPORT : - tuple.getFirst().getConveyorMode() == CoverConveyor.ConveyorMode.EXPORT); - } - - public ItemStack insertOverRobotArm(IItemHandler handler, CoverRoboticArm arm, boolean isOnPipe, ItemStack stack, boolean simulate, int allowed) { + public ItemStack insertOverRobotArm(IItemHandler handler, CoverRoboticArm arm, ItemStack stack, boolean simulate, int allowed) { int rate; boolean isStackSpecific = false; Object index = arm.getItemFilterContainer().matchItemStack(stack); diff --git a/src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetWalker.java b/src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetWalker.java index 7480551752c..479c0601857 100644 --- a/src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetWalker.java +++ b/src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetWalker.java @@ -1,6 +1,8 @@ package gregtech.common.pipelike.itempipe.net; -import gregtech.api.pipenet.Node; +import gregtech.api.pipenet.PipeNet; +import gregtech.api.pipenet.PipeNetWalker; +import gregtech.api.pipenet.tile.IPipeTile; import gregtech.api.unification.material.properties.ItemPipeProperties; import gregtech.common.pipelike.itempipe.tile.TileEntityItemPipe; import net.minecraft.tileentity.TileEntity; @@ -10,101 +12,51 @@ import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.IItemHandler; -import java.util.*; +import javax.annotation.Nullable; +import java.util.ArrayList; +import java.util.List; -public class ItemNetWalker { +public class ItemNetWalker extends PipeNetWalker { public static List createNetData(ItemPipeNet net, World world, BlockPos sourcePipe) { ItemNetWalker walker = new ItemNetWalker(net, world, sourcePipe, 1, new ArrayList<>(), null); - while (!walker.walk()) ; - walker.walked.forEach(TileEntityItemPipe::resetWalk); + walker.traversePipeNet(); return walker.inventories; } - private final ItemPipeNet net; - private final World world; - private final List pipes = new ArrayList<>(); - private List walkers; - - private BlockPos currentPos; - - private int distance; private ItemPipeProperties minProperties; private final List inventories; - private final Set walked = new HashSet<>(); - - protected ItemNetWalker(ItemPipeNet net, World world, BlockPos sourcePipe, int distance, List inventories, ItemPipeProperties properties) { - this.world = world; - this.net = net; - this.distance = distance; + protected ItemNetWalker(PipeNet net, World world, BlockPos sourcePipe, int distance, List inventories, ItemPipeProperties properties) { + super(net, world, sourcePipe, distance); this.inventories = inventories; - this.currentPos = sourcePipe; this.minProperties = properties; } - private boolean walk() { - if (walkers == null) - checkPos(currentPos); - - if (pipes.size() == 0) - return true; - if (pipes.size() == 1) { - currentPos = currentPos.offset(pipes.get(0)); - distance++; - return false; - } - - if (walkers == null) { - walkers = new ArrayList<>(); - for (EnumFacing side : pipes) { - walkers.add(new ItemNetWalker(net, world, currentPos.offset(side), distance + 1, inventories, minProperties)); - } - } else { - Iterator iterator = walkers.iterator(); - while (iterator.hasNext()) { - ItemNetWalker walker = iterator.next(); - if (walker.walk()) { - walked.addAll(walker.walked); - iterator.remove(); - } - } - } - - return walkers.size() == 0; + @Override + protected PipeNetWalker createSubWalker(PipeNet net, World world, BlockPos nextPos, int walkedBlocks) { + return new ItemNetWalker(net, world, nextPos, walkedBlocks, inventories, minProperties); } - private void checkPos(BlockPos pos) { - pipes.clear(); - Node node = net.getNodeAt(pos); - if (node == null) return; - - TileEntity thisPipe = world.getTileEntity(pos); - if (!(thisPipe instanceof TileEntityItemPipe)) - return; - ItemPipeProperties pipeProperties = ((TileEntityItemPipe) thisPipe).getNodeData(); + @Override + protected void checkPipe(IPipeTile pipeTile, BlockPos pos) { + ItemPipeProperties pipeProperties = ((TileEntityItemPipe) pipeTile).getNodeData(); if (minProperties == null) minProperties = pipeProperties; else minProperties = new ItemPipeProperties(minProperties.priority + pipeProperties.priority, Math.min(minProperties.transferRate, pipeProperties.transferRate)); - ((TileEntityItemPipe) thisPipe).markWalked(); - walked.add((TileEntityItemPipe) thisPipe); + } + + @Override + protected void checkNeighbour(IPipeTile pipeTile, BlockPos pipePos, EnumFacing faceToNeighbour, @Nullable TileEntity neighbourTile) { + if (neighbourTile == null) return; + IItemHandler handler = neighbourTile.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, faceToNeighbour.getOpposite()); + if (handler != null) + inventories.add(new ItemPipeNet.Inventory(new BlockPos(pipePos), faceToNeighbour, getWalkedBlocks(), minProperties)); + } - // check for surrounding pipes and item handlers - for (EnumFacing accessSide : EnumFacing.VALUES) { - //skip sides reported as blocked by pipe network - if (node.isBlocked(accessSide)) - continue; - TileEntity tile = world.getTileEntity(pos.offset(accessSide)); - if (tile == null) continue; - if (tile instanceof TileEntityItemPipe) { - if (!((TileEntityItemPipe) tile).isWalked()) - pipes.add(accessSide); - continue; - } - IItemHandler handler = tile.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, accessSide.getOpposite()); - if (handler != null) - inventories.add(new ItemPipeNet.Inventory(pos, accessSide, distance, minProperties)); - } + @Override + protected boolean isValidPipe(IPipeTile currentPipe, IPipeTile neighbourPipe, BlockPos pipePos, EnumFacing faceToNeighbour) { + return neighbourPipe instanceof TileEntityItemPipe; } } diff --git a/src/main/java/gregtech/common/pipelike/itempipe/tile/TileEntityItemPipe.java b/src/main/java/gregtech/common/pipelike/itempipe/tile/TileEntityItemPipe.java index 6d6ff1f8f73..4ab02155b30 100644 --- a/src/main/java/gregtech/common/pipelike/itempipe/tile/TileEntityItemPipe.java +++ b/src/main/java/gregtech/common/pipelike/itempipe/tile/TileEntityItemPipe.java @@ -17,20 +17,6 @@ public class TileEntityItemPipe extends TileEntityMaterialPipeBase currentPipeNet = new WeakReference<>(null); - private boolean walked; - - public void markWalked() { - this.walked = true; - } - - public void resetWalk() { - this.walked = false; - } - - public boolean isWalked() { - return walked; - } - @Override public Class getPipeTypeClass() { return ItemPipeType.class; diff --git a/src/main/java/gregtech/common/pipelike/itempipe/tile/TileEntityItemPipeTickable.java b/src/main/java/gregtech/common/pipelike/itempipe/tile/TileEntityItemPipeTickable.java index e355041a7aa..202d62884ce 100644 --- a/src/main/java/gregtech/common/pipelike/itempipe/tile/TileEntityItemPipeTickable.java +++ b/src/main/java/gregtech/common/pipelike/itempipe/tile/TileEntityItemPipeTickable.java @@ -4,24 +4,13 @@ public class TileEntityItemPipeTickable extends TileEntityItemPipe implements ITickable { - private boolean isActive; - - public boolean isActive() { - return isActive; - } - - public void setActive(boolean active) { - isActive = active; - } - private int transferredItems = 0; private long timer = 0; @Override public void update() { - if (++timer == 1000000000) timer = 0; getCoverableImplementation().update(); - if (timer % 20 == 0) { + if (++timer % 20 == 0) { transferredItems = 0; } } diff --git a/src/main/java/gregtech/common/render/CableRenderer.java b/src/main/java/gregtech/common/render/CableRenderer.java index 26fabe967bc..0be46c54953 100644 --- a/src/main/java/gregtech/common/render/CableRenderer.java +++ b/src/main/java/gregtech/common/render/CableRenderer.java @@ -99,9 +99,10 @@ public void renderItem(ItemStack rawItemStack, TransformType transformType) { Insulation insulation = blockCable.getItemPipeType(stack); Material material = blockCable.getItemMaterial(stack); if (insulation != null && material != null) { - renderCableBlock(material, insulation, IPipeTile.DEFAULT_INSULATION_COLOR, renderState, new IVertexOperation[0], - 1 << EnumFacing.SOUTH.getIndex() | 1 << EnumFacing.NORTH.getIndex() | - 1 << (6 + EnumFacing.SOUTH.getIndex()) | 1 << (6 + EnumFacing.NORTH.getIndex())); + int connections = 1 << EnumFacing.SOUTH.getIndex() | 1 << EnumFacing.NORTH.getIndex() | + 1 << (6 + EnumFacing.SOUTH.getIndex()) | 1 << (6 + EnumFacing.NORTH.getIndex()); + connections |= 1 << 12; + renderCableBlock(material, insulation, IPipeTile.DEFAULT_INSULATION_COLOR, renderState, new IVertexOperation[0], connections); } renderState.draw(); GlStateManager.disableBlend(); @@ -152,39 +153,32 @@ public void renderCableBlock(Material material, Insulation insulation1, int insu for (EnumFacing renderedSide : EnumFacing.VALUES) { if ((connectMask & 1 << renderedSide.getIndex()) == 0) { int oppositeIndex = renderedSide.getOpposite().getIndex(); - if ((connectMask & 1 << oppositeIndex) > 0 && (connectMask & ~(1 << oppositeIndex)) == 0) { + if ((connectMask & 1 << oppositeIndex) > 0 && (connectMask & 63 & ~(1 << oppositeIndex)) == 0) { //if there is something on opposite side, render overlay + wire renderCableSide(state, wire, renderedSide, cuboid6); renderCableSide(state, overlays, renderedSide, cuboid6); } else { renderCableSide(state, insulation, renderedSide, cuboid6); } + } else { + renderCableCube(connectMask, state, insulation, wire, overlays, renderedSide, thickness); } } - - renderCableCube(connectMask, state, insulation, wire, overlays, EnumFacing.DOWN, thickness); - renderCableCube(connectMask, state, insulation, wire, overlays, EnumFacing.UP, thickness); - renderCableCube(connectMask, state, insulation, wire, overlays, EnumFacing.WEST, thickness); - renderCableCube(connectMask, state, insulation, wire, overlays, EnumFacing.EAST, thickness); - renderCableCube(connectMask, state, insulation, wire, overlays, EnumFacing.NORTH, thickness); - renderCableCube(connectMask, state, insulation, wire, overlays, EnumFacing.SOUTH, thickness); } private static void renderCableCube(int connections, CCRenderState renderState, IVertexOperation[] pipeline, IVertexOperation[] wire, IVertexOperation[] overlays, EnumFacing side, float thickness) { - if ((connections & 1 << side.getIndex()) > 0) { - boolean renderFrontSide = (connections & 1 << (6 + side.getIndex())) > 0; - Cuboid6 cuboid6 = BlockCable.getSideBox(side, thickness); - for (EnumFacing renderedSide : EnumFacing.VALUES) { - if (renderedSide == side) { - if (renderFrontSide) { - renderCableSide(renderState, wire, renderedSide, cuboid6); - renderCableSide(renderState, overlays, renderedSide, cuboid6); - } - } else if (renderedSide != side.getOpposite()) { - renderCableSide(renderState, pipeline, renderedSide, cuboid6); - } + Cuboid6 cuboid6 = BlockCable.getSideBox(side, thickness); + for (EnumFacing renderedSide : EnumFacing.VALUES) { + if (renderedSide.getAxis() != side.getAxis()) { + renderCableSide(renderState, pipeline, renderedSide, cuboid6); } } + if ((connections & 1 << 12) > 0) { + renderCableSide(renderState, wire, side, cuboid6); + renderCableSide(renderState, overlays, side, cuboid6); + } else if ((connections & 1 << (6 + side.getIndex())) > 0) { + renderCableSide(renderState, pipeline, side, cuboid6); + } } private static void renderCableSide(CCRenderState renderState, IVertexOperation[] pipeline, EnumFacing side, Cuboid6 cuboid6) { diff --git a/src/main/java/gregtech/common/render/FluidPipeRenderer.java b/src/main/java/gregtech/common/render/FluidPipeRenderer.java index 068b2b5313c..25a170cec44 100644 --- a/src/main/java/gregtech/common/render/FluidPipeRenderer.java +++ b/src/main/java/gregtech/common/render/FluidPipeRenderer.java @@ -109,9 +109,10 @@ public void renderItem(ItemStack rawItemStack, TransformType transformType) { FluidPipeType pipeType = blockFluidPipe.getItemPipeType(stack); Material material = blockFluidPipe.getItemMaterial(stack); if (pipeType != null && material != null) { - renderPipeBlock(material, pipeType, IPipeTile.DEFAULT_INSULATION_COLOR, renderState, new IVertexOperation[0], - 1 << EnumFacing.SOUTH.getIndex() | 1 << EnumFacing.NORTH.getIndex() | - 1 << (6 + EnumFacing.SOUTH.getIndex()) | 1 << (6 + EnumFacing.NORTH.getIndex())); + int connections = 1 << EnumFacing.SOUTH.getIndex() | 1 << EnumFacing.NORTH.getIndex() | + 1 << (6 + EnumFacing.SOUTH.getIndex()) | 1 << (6 + EnumFacing.NORTH.getIndex()); + connections |= 1 << 12; + renderPipeBlock(material, pipeType, IPipeTile.DEFAULT_INSULATION_COLOR, renderState, new IVertexOperation[0], connections); } renderState.draw(); GlStateManager.disableBlend(); @@ -172,36 +173,31 @@ public void renderPipeBlock(Material material, FluidPipeType pipeType, int insul for (EnumFacing renderedSide : EnumFacing.VALUES) { if ((connectMask & 1 << renderedSide.getIndex()) == 0) { int oppositeIndex = renderedSide.getOpposite().getIndex(); - if ((connectMask & 1 << oppositeIndex) > 0 && (connectMask & ~(1 << oppositeIndex)) == 0) { + if ((connectMask & 1 << oppositeIndex) > 0 && (connectMask & 63 & ~(1 << oppositeIndex)) == 0) { renderPipeSide(state, pipeConnectSide, renderedSide, cuboid6); } else { renderPipeSide(state, pipeSide, renderedSide, cuboid6); } + } else { + renderPipeCube(connectMask, state, pipeSide, pipeConnectSide, renderedSide, thickness); } } - renderPipeCube(connectMask, state, pipeSide, pipeConnectSide, EnumFacing.DOWN, thickness); - renderPipeCube(connectMask, state, pipeSide, pipeConnectSide, EnumFacing.UP, thickness); - renderPipeCube(connectMask, state, pipeSide, pipeConnectSide, EnumFacing.WEST, thickness); - renderPipeCube(connectMask, state, pipeSide, pipeConnectSide, EnumFacing.EAST, thickness); - renderPipeCube(connectMask, state, pipeSide, pipeConnectSide, EnumFacing.NORTH, thickness); - renderPipeCube(connectMask, state, pipeSide, pipeConnectSide, EnumFacing.SOUTH, thickness); } } private static void renderPipeCube(int connections, CCRenderState renderState, IVertexOperation[] pipeline, IVertexOperation[] pipeConnectSide, EnumFacing side, float thickness) { - if ((connections & 1 << side.getIndex()) > 0) { - boolean renderFrontSide = (connections & 1 << (6 + side.getIndex())) > 0; - Cuboid6 cuboid6 = BlockFluidPipe.getSideBox(side, thickness); - for (EnumFacing renderedSide : EnumFacing.VALUES) { - if (renderedSide == side) { - if (renderFrontSide) { - renderPipeSide(renderState, pipeConnectSide, renderedSide, cuboid6); - } - } else if (renderedSide != side.getOpposite()) { - renderPipeSide(renderState, pipeline, renderedSide, cuboid6); - } + Cuboid6 cuboid6 = BlockFluidPipe.getSideBox(side, thickness); + for (EnumFacing renderedSide : EnumFacing.VALUES) { + if (renderedSide.getAxis() != side.getAxis()) { + renderPipeSide(renderState, pipeline, renderedSide, cuboid6); } } + if ((connections & 1 << 12) > 0) { + renderPipeSide(renderState, pipeConnectSide, side, cuboid6); + } else if ((connections & 1 << (6 + side.getIndex())) > 0) { + // if neighbour pipe is smaller, render closed texture + renderPipeSide(renderState, pipeline, side, cuboid6); + } } private static void renderPipeSide(CCRenderState renderState, IVertexOperation[] pipeline, EnumFacing side, Cuboid6 cuboid6) { diff --git a/src/main/java/gregtech/common/render/ItemPipeRenderer.java b/src/main/java/gregtech/common/render/ItemPipeRenderer.java index 5316bb27bac..aa4bedbb720 100644 --- a/src/main/java/gregtech/common/render/ItemPipeRenderer.java +++ b/src/main/java/gregtech/common/render/ItemPipeRenderer.java @@ -110,9 +110,10 @@ public void renderItem(ItemStack rawItemStack, TransformType transformType) { ItemPipeType pipeType = blockFluidPipe.getItemPipeType(stack); Material material = blockFluidPipe.getItemMaterial(stack); if (pipeType != null && material != null) { - renderPipeBlock(material, pipeType, IPipeTile.DEFAULT_INSULATION_COLOR, renderState, new IVertexOperation[0], - 1 << EnumFacing.SOUTH.getIndex() | 1 << EnumFacing.NORTH.getIndex() | - 1 << (6 + EnumFacing.SOUTH.getIndex()) | 1 << (6 + EnumFacing.NORTH.getIndex())); + int connections = 1 << EnumFacing.SOUTH.getIndex() | 1 << EnumFacing.NORTH.getIndex() | + 1 << (6 + EnumFacing.SOUTH.getIndex()) | 1 << (6 + EnumFacing.NORTH.getIndex()); + connections |= 1 << 12; + renderPipeBlock(material, pipeType, IPipeTile.DEFAULT_INSULATION_COLOR, renderState, new IVertexOperation[0], connections); } renderState.draw(); GlStateManager.disableBlend(); @@ -168,49 +169,48 @@ public void renderPipeBlock(Material material, ItemPipeType pipeType, int insula Cuboid6 cuboid6 = BlockItemPipe.getSideBox(null, thickness); if (connectMask == 0) { + // base pipe without connections for (EnumFacing renderedSide : EnumFacing.VALUES) { renderPipeSide(state, pipeConnectSide, renderedSide, cuboid6); - if (restrictive) - renderPipeSide(state, pipeRestrictive, renderedSide, cuboid6); } } else { for (EnumFacing renderedSide : EnumFacing.VALUES) { - //if ((connectMask & 1 << renderedSide.getIndex()) == 0) { - int oppositeIndex = renderedSide.getOpposite().getIndex(); - if ((connectMask & 1 << oppositeIndex) > 0 && (connectMask & ~(1 << oppositeIndex)) == 0) { - renderPipeSide(state, pipeConnectSide, renderedSide, cuboid6); + // if connection is blocked + if ((connectMask & 1 << renderedSide.getIndex()) == 0) { + int oppositeIndex = renderedSide.getOpposite().getIndex(); + if ((connectMask & 1 << oppositeIndex) > 0 && (connectMask & 63 & ~(1 << oppositeIndex)) == 0) { + // render open texture if opposite is open and no other + renderPipeSide(state, pipeConnectSide, renderedSide, cuboid6); + } else { + // else render pipe side + renderPipeSide(state, pipeSide, renderedSide, cuboid6); + } } else { - renderPipeSide(state, pipeSide, renderedSide, cuboid6); - if (restrictive) - renderPipeSide(state, pipeRestrictive, renderedSide, cuboid6); + // else render connection cuboid + renderPipeCube(connectMask, state, pipeSide, pipeConnectSide, pipeRestrictive, renderedSide, thickness, restrictive); } - //} } - renderPipeCube(connectMask, state, pipeSide, pipeConnectSide, pipeRestrictive, EnumFacing.DOWN, thickness, restrictive); - renderPipeCube(connectMask, state, pipeSide, pipeConnectSide, pipeRestrictive, EnumFacing.UP, thickness, restrictive); - renderPipeCube(connectMask, state, pipeSide, pipeConnectSide, pipeRestrictive, EnumFacing.WEST, thickness, restrictive); - renderPipeCube(connectMask, state, pipeSide, pipeConnectSide, pipeRestrictive, EnumFacing.EAST, thickness, restrictive); - renderPipeCube(connectMask, state, pipeSide, pipeConnectSide, pipeRestrictive, EnumFacing.NORTH, thickness, restrictive); - renderPipeCube(connectMask, state, pipeSide, pipeConnectSide, pipeRestrictive, EnumFacing.SOUTH, thickness, restrictive); } } private void renderPipeCube(int connections, CCRenderState renderState, IVertexOperation[] pipeline, IVertexOperation[] pipeConnectSide, IVertexOperation[] pipeRestrictive, EnumFacing side, float thickness, boolean isRestrictive) { - if ((connections & 1 << side.getIndex()) > 0) { - boolean renderFrontSide = (connections & 1 << (6 + side.getIndex())) > 0; - Cuboid6 cuboid6 = BlockItemPipe.getSideBox(side, thickness); - for (EnumFacing renderedSide : EnumFacing.VALUES) { - if (renderedSide == side) { - if (renderFrontSide) { - renderPipeSide(renderState, pipeConnectSide, renderedSide, cuboid6); - } - } else if (renderedSide != side.getOpposite()) { - renderPipeSide(renderState, pipeline, renderedSide, cuboid6); - if (isRestrictive) - renderPipeSide(renderState, pipeRestrictive, renderedSide, cuboid6); - } + Cuboid6 cuboid6 = BlockItemPipe.getSideBox(side, thickness); + // render connection cuboid + for (EnumFacing renderedSide : EnumFacing.VALUES) { + if (renderedSide.getAxis() != side.getAxis()) { + // render base side texture + renderPipeSide(renderState, pipeline, renderedSide, cuboid6); + if (isRestrictive) + // render restrictive texture + renderPipeSide(renderState, pipeRestrictive, renderedSide, cuboid6); } } + if ((connections & 1 << 12) > 0) { + renderPipeSide(renderState, pipeConnectSide, side, cuboid6); + } else if ((connections & 1 << (6 + side.getIndex())) > 0) { + // if neighbour pipe is smaller, render closed texture + renderPipeSide(renderState, pipeline, side, cuboid6); + } } private void renderPipeSide(CCRenderState renderState, IVertexOperation[] pipeline, EnumFacing side, Cuboid6 cuboid6) { diff --git a/src/main/java/gregtech/common/terminal/app/ThemeSettingApp.java b/src/main/java/gregtech/common/terminal/app/ThemeSettingApp.java new file mode 100644 index 00000000000..48b738e9c72 --- /dev/null +++ b/src/main/java/gregtech/common/terminal/app/ThemeSettingApp.java @@ -0,0 +1,156 @@ +package gregtech.common.terminal.app; + +import gregtech.api.gui.GuiTextures; +import gregtech.api.gui.resources.*; +import gregtech.api.gui.widgets.ImageWidget; +import gregtech.api.gui.widgets.LabelWidget; +import gregtech.api.gui.widgets.TextFieldWidget; +import gregtech.api.gui.widgets.WidgetGroup; +import gregtech.api.terminal.app.AbstractApplication; +import gregtech.api.terminal.gui.widgets.CircleButtonWidget; +import gregtech.api.terminal.gui.widgets.ColorWidget; +import gregtech.api.terminal.gui.widgets.RectButtonWidget; +import gregtech.api.terminal.gui.widgets.SelectorWidget; +import gregtech.api.terminal.os.TerminalDialogWidget; +import gregtech.api.terminal.os.TerminalOSWidget; +import gregtech.api.terminal.os.TerminalTheme; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.ResourceLocation; + +import java.awt.*; +import java.io.File; +import java.util.Arrays; +import java.util.function.Consumer; + +public class ThemeSettingApp extends AbstractApplication { + public ThemeSettingApp() { + super("theme_settings", GuiTextures.GREGTECH_LOGO); + } + + private WidgetGroup textureGroup; + + @Override + public AbstractApplication createApp(TerminalOSWidget os, boolean isClient, NBTTagCompound nbt) { + ThemeSettingApp app = new ThemeSettingApp(); + if (isClient) { //333 232 + float x = 333 * 1.0f / 13; + int y = 50; + app.addWidget(new ImageWidget(5, 5, 333 - 10, 232 - 10, TerminalTheme.COLOR_B_2)); + app.addWidget(new LabelWidget(333 / 2, 20, "terminal.theme_settings.color", -1).setXCentered(true)); + app.addColorButton(TerminalTheme.COLOR_1, "COLOR_1", (int) x, y); + app.addColorButton(TerminalTheme.COLOR_2, "COLOR_2", (int) (x * 2), y); + app.addColorButton(TerminalTheme.COLOR_3, "COLOR_3", (int) (x * 3), y); + app.addColorButton(TerminalTheme.COLOR_4, "COLOR_4", (int) (x * 4), y); + app.addColorButton(TerminalTheme.COLOR_5, "COLOR_5", (int) (x * 5), y); + app.addColorButton(TerminalTheme.COLOR_6, "COLOR_6", (int) (x * 6), y); + app.addColorButton(TerminalTheme.COLOR_7, "COLOR_7", (int) (x * 7), y); + app.addColorButton(TerminalTheme.COLOR_F_1, "COLOR_F_1", (int) (x * 8), y); + app.addColorButton(TerminalTheme.COLOR_F_2, "COLOR_F_2", (int) (x * 9), y); + app.addColorButton(TerminalTheme.COLOR_B_1, "COLOR_B_1", (int) (x * 10), y); + app.addColorButton(TerminalTheme.COLOR_B_2, "COLOR_B_2", (int) (x * 11), y); + app.addColorButton(TerminalTheme.COLOR_B_3, "COLOR_B_3", (int) (x * 12), y); + app.addWidget(new LabelWidget(333 / 2, 85, "terminal.theme_settings.wallpaper", -1).setXCentered(true)); + app.addWidget(new ImageWidget((int) x, 105, 150, 105, TerminalTheme.WALL_PAPER).setBorder(2, -1)); + app.addWidget(new SelectorWidget((int) (x + 170), 105, 116, 20, Arrays.asList("resource", "url", "color", "file"), -1, TerminalTheme.WALL_PAPER::getTypeName, true) + .setIsUp(true) + .setOnChanged(type->onModifyTextureChanged(type, app)) + .setColors(TerminalTheme.COLOR_B_2.getColor(), TerminalTheme.COLOR_F_1.getColor(), 0) + .setBackground(TerminalTheme.COLOR_B_1)); + textureGroup = new WidgetGroup((int) (x + 170), 132, (int) (x * 11 - 170), 65); + app.addWidget(textureGroup); + } + return app; + } + + private void addColorButton(ColorRectTexture texture, String name, int x, int y) { + CircleButtonWidget buttonWidget = new CircleButtonWidget(x, y, 8, 1, 0).setFill(texture.getColor()).setStrokeAnima(-1).setHoverText(name); + buttonWidget.setClickListener(cd -> { + TerminalDialogWidget.showColorDialog(getOs(), name, color -> { + if (color != null) { + buttonWidget.setFill(color); + texture.setColor(color); + if (!TerminalTheme.saveConfig()) { + TerminalDialogWidget.showInfoDialog(getOs(), "terminal.component.error", "terminal.component.save_file.error").setClientSide().open(); + } + } + }).setClientSide().open(); + }); + addWidget(buttonWidget); + } + + private void onModifyTextureChanged(String type, AbstractApplication app) { + textureGroup.clearAllWidgets(); + switch (type) { + case "resource": + if (!(TerminalTheme.WALL_PAPER.getTexture() instanceof TextureArea)) { + TerminalTheme.WALL_PAPER.setTexture(new TextureArea(new ResourceLocation("gregtech:textures/gui/terminal/terminal_background.png"), 0.0, 0.0, 1.0, 1.0)); + TerminalTheme.saveConfig(); + } + addStringSetting(((TextureArea)TerminalTheme.WALL_PAPER.getTexture()).imageLocation.toString(), + s -> { + TerminalTheme.WALL_PAPER.setTexture(new TextureArea(new ResourceLocation(s), 0.0, 0.0, 1.0, 1.0)); + TerminalTheme.saveConfig(); + }); + break; + case "url": + if (!(TerminalTheme.WALL_PAPER.getTexture() instanceof URLTexture)) { + TerminalTheme.WALL_PAPER.setTexture(new URLTexture(null)); + TerminalTheme.saveConfig(); + } + addStringSetting(((URLTexture)TerminalTheme.WALL_PAPER.getTexture()).url, s -> { + TerminalTheme.WALL_PAPER.setTexture(new URLTexture(s)); + TerminalTheme.saveConfig(); + }); + break; + case "color": + ColorRectTexture texture; + if (!(TerminalTheme.WALL_PAPER.getTexture() instanceof ColorRectTexture)) { + texture = new ColorRectTexture(-1); + TerminalTheme.WALL_PAPER.setTexture(texture); + TerminalTheme.saveConfig(); + } else { + texture = (ColorRectTexture) TerminalTheme.WALL_PAPER.getTexture(); + } + textureGroup.addWidget(new ColorWidget(0, 0, 80, 10) + .setColorSupplier(texture::getColor, true) + .setOnColorChanged(texture::setColor)); + break; + case "file": + if (!(TerminalTheme.WALL_PAPER.getTexture() instanceof FileTexture)) { + TerminalTheme.WALL_PAPER.setTexture(new FileTexture(null)); + TerminalTheme.saveConfig(); + } + textureGroup.addWidget(new RectButtonWidget(0, 0, 116, 20) + .setColors(TerminalTheme.COLOR_B_1.getColor(), + TerminalTheme.COLOR_1.getColor(), + new Color(255, 255, 255, 0).getRGB()) + .setClickListener(cd-> TerminalDialogWidget.showFileDialog(app.getOs(), "terminal.theme_settings.image", new File("terminal"), true, file->{ + if (file != null && file.isFile()) { + TerminalTheme.WALL_PAPER.setTexture(new FileTexture(file)); + TerminalTheme.saveConfig(); + } + }).setClientSide().open()) + .setIcon(new TextTexture("terminal.theme_settings.select", -1))); + break; + } + } + + private void addStringSetting(String init, Consumer callback) { + TextFieldWidget textFieldWidget = new TextFieldWidget(0, 0, 76, 20, TerminalTheme.COLOR_B_2, null, null) + .setMaxStringLength(Integer.MAX_VALUE) + .setValidator(s -> true) + .setCurrentString(init == null ? "" : init); + textureGroup.addWidget(textFieldWidget); + textureGroup.addWidget(new RectButtonWidget(76, 0, 40, 20) + .setColors(TerminalTheme.COLOR_B_1.getColor(), + TerminalTheme.COLOR_1.getColor(), + new Color(255, 255, 255, 0).getRGB()) + .setClickListener(cd->callback.accept(textFieldWidget.getCurrentString())) + .setIcon(new TextTexture("terminal.guide_editor.update", -1))); + } + + @Override + public boolean isClientSideApp() { + return true; + } +} diff --git a/src/main/java/gregtech/common/terminal/app/guide/GuideApp.java b/src/main/java/gregtech/common/terminal/app/guide/GuideApp.java new file mode 100644 index 00000000000..0d55a95e205 --- /dev/null +++ b/src/main/java/gregtech/common/terminal/app/guide/GuideApp.java @@ -0,0 +1,208 @@ +package gregtech.common.terminal.app.guide; + +import com.google.gson.Gson; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import gregtech.api.GTValues; +import gregtech.api.gui.GuiTextures; +import gregtech.api.gui.resources.IGuiTexture; +import gregtech.api.terminal.app.AbstractApplication; +import gregtech.common.terminal.app.guide.widget.GuidePageWidget; +import gregtech.api.terminal.gui.widgets.TreeListWidget; +import gregtech.api.terminal.os.TerminalOSWidget; +import gregtech.api.terminal.os.menu.IMenuComponent; +import gregtech.common.terminal.component.SearchComponent; +import gregtech.api.terminal.util.TreeNode; +import net.minecraft.client.Minecraft; +import net.minecraft.client.resources.I18n; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.fml.common.FMLCommonHandler; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.*; +import java.util.function.Consumer; +import java.util.stream.Collectors; + +public abstract class GuideApp extends AbstractApplication implements + SearchComponent.IWidgetSearch>> { + private GuidePageWidget pageWidget; + private TreeListWidget tree; + private TreeNode ROOT; + private Map jsonObjectMap; + public GuideApp(String name, IGuiTexture icon) { + super(name, icon); + ROOT = new TreeNode<>(0, "root"); + jsonObjectMap = new HashMap<>(); + } + + @Override + public AbstractApplication createApp(TerminalOSWidget os, boolean isClient, NBTTagCompound nbt) { + try { + GuideApp app = this.getClass().newInstance(); + app.ROOT = ROOT; + app.jsonObjectMap = jsonObjectMap; + if (isClient && getTree() != null) { + app.tree = new TreeListWidget<>(0, 0, 133, 232, getTree(), app::loadPage).setContentIconSupplier(this::itemIcon) + .setContentNameSupplier(this::itemName) + .setKeyNameSupplier(key -> key) + .setNodeTexture(GuiTextures.BORDERED_BACKGROUND) + .setLeafTexture(GuiTextures.SLOT_DARKENED); + app.addWidget(app.tree); + } + return app; + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + protected void loadPage(TreeNode leaf) { + if (leaf == null) { + return; + } + if (this.pageWidget != null) { + this.removeWidget(this.pageWidget); + } + this.pageWidget = new GuidePageWidget(133, 0, 200, 232, 5); + if (leaf.isLeaf() && leaf.getContent() != null) { + JsonObject page = jsonObjectMap.get(leaf.getContent()); + if (page != null) { + this.pageWidget.loadJsonConfig(page); + } + } + this.addWidget(this.pageWidget); + } + + @Override + public boolean isClientSideApp() { + return true; + } + + protected IGuiTexture itemIcon(T item) { + return null; + } + + /** + * Should return a localised representation of the item + * @param item item + * @return localised name + */ + protected abstract String itemName(T item); + + protected abstract String rawItemName(T item); + + protected final TreeNode getTree() { + return ROOT; + } + + public final void loadJsonFiles(List jsons) { + ROOT = new TreeNode<>(0, "root"); + jsonObjectMap = new HashMap<>(); + for (JsonObject json : jsons) { + T t = ofJson(json); + if(t != null) { + registerItem(t, json.get("section").getAsString()); + jsonObjectMap.put(t, json); + } + } + } + + protected abstract T ofJson(JsonObject json); + + public JsonObject getConfig(String fileName, String lang) { + try { + InputStream inputStream = Minecraft.getMinecraft().getResourceManager().getResource(new ResourceLocation(GTValues.MODID, "terminal/guide/" + getRegistryName() + "/" + lang + "/" + fileName)).getInputStream(); + BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); + JsonElement je = new Gson().fromJson(reader, JsonElement.class); + reader.close(); + inputStream.close(); + return je.getAsJsonObject(); + } catch (IOException e) { + return null; + } + } + + // ISearch + @Override + public boolean isManualInterrupt() { + return true; + } + + @Override + public void search(String word, Consumer>> find) { + Stack> stack = new Stack<>(); + stack.push(getTree()); + dfsSearch(Thread.currentThread(), stack, word.toLowerCase(), find); + } + + private boolean dfsSearch(Thread thread, Stack> stack, String regex, Consumer>> find) { + if (thread.isInterrupted()) { + return true; + } else { + TreeNode node = stack.peek(); + if (!node.isLeaf() && I18n.format(node.getKey()).toLowerCase().contains(regex)) { + find.accept((Stack>) stack.clone()); + } else if (node.isLeaf()) { + String name = itemName(node.getContent()); + if (name == null) { + name = node.getKey(); + } + if (I18n.format(name).toLowerCase().contains(regex)) { + find.accept((Stack>) stack.clone()); + } + } + if (node.getChildren() != null) { + for (TreeNode child : node.getChildren()) { + stack.push(child); + if (dfsSearch(thread, stack, regex, find)) return true; + stack.pop(); + } + } + } + return false; + } + + protected void registerItem(T item, String path) { + if (FMLCommonHandler.instance().getSide().isClient()) { + String[] parts = path.split("/"); + TreeNode child = ROOT; + for(String sub : parts) { + child = child.getOrCreateChild(sub); + } + child.addContent(rawItemName(item), item); + } + } + + @Override + public void selectResult(Stack> result) { + if (result.size() > 0 && tree != null) { + List path = result.stream().map(TreeNode::getKey).collect(Collectors.toList()); + path.remove(0); + loadPage(tree.jumpTo(path)); + } + } + + @Override + public String resultDisplay(Stack> result) { + Iterator> iterator = result.iterator(); + if(!iterator.hasNext()) return ""; + iterator.next(); // skip root + StringBuilder builder = new StringBuilder(); + while (iterator.hasNext()) { + TreeNode node = iterator.next(); + builder.append(node.getContent() == null ? node.getKey() : itemName(node.getContent())); + if(iterator.hasNext()) + builder.append(" / "); + } + return builder.toString(); + } + + @Override + public List getMenuComponents() { + return Collections.singletonList(new SearchComponent<>(this)); + } +} diff --git a/src/main/java/gregtech/common/terminal/app/guide/ItemGuideApp.java b/src/main/java/gregtech/common/terminal/app/guide/ItemGuideApp.java new file mode 100644 index 00000000000..516cd42e60f --- /dev/null +++ b/src/main/java/gregtech/common/terminal/app/guide/ItemGuideApp.java @@ -0,0 +1,98 @@ +package gregtech.common.terminal.app.guide; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import gregtech.api.gui.resources.IGuiTexture; +import gregtech.api.gui.resources.ItemStackTexture; +import gregtech.api.items.metaitem.MetaItem; +import gregtech.common.items.MetaItems; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; + +import java.util.Objects; + +public class ItemGuideApp extends GuideApp { + + public ItemGuideApp() { + super("items", new ItemStackTexture(MetaItems.SCANNER.getStackForm())); + } + + @Override + protected String itemName(GuideItem item) { + return item.stack.getDisplayName(); + } + + @Override + protected String rawItemName(GuideItem item) { + if (item.stack.getItem() instanceof MetaItem) { + return ((MetaItem) item.stack.getItem()).getItem((short) item.stack.getMetadata()).unlocalizedName; + } + return item.stack.getTranslationKey(); + } + + @Override + protected IGuiTexture itemIcon(GuideItem item) { + return new ItemStackTexture(item.stack); + } + + @Override + protected GuideItem ofJson(JsonObject json) { + return GuideItem.ofJson(json); + } + + public static class GuideItem { + private final ItemStack stack; + private final String name; + + public GuideItem(ItemStack stack, String name) { + this.stack = stack; + this.name = name; + } + + public GuideItem(ItemStack stack) { + this(stack, stack.getItem().getRegistryName().toString() + ":" + stack.getMetadata()); + } + + public GuideItem(MetaItem.MetaValueItem item) { + this(item.getStackForm(), item.unlocalizedName); + } + + public static GuideItem ofJson(JsonObject json) { + if (json.has("item")) { + JsonElement element = json.get("item"); + if (element.isJsonPrimitive()) { + String[] s = json.getAsString().split(":"); + if (s.length < 2) return null; + Item item = Item.getByNameOrId(s[0] + ":" + s[1]); + if (item == null) return null; + int meta = 0; + if (s.length > 2) + meta = Integer.parseInt(s[2]); + return new GuideItem(new ItemStack(item, 1, meta)); + } + } + if (json.has("metaitem")) { + String metaItemId = json.get("metaitem").getAsString(); + for (MetaItem metaItem : MetaItem.getMetaItems()) { + MetaItem.MetaValueItem metaValueItem = metaItem.getAllItems().stream().filter(m -> m.unlocalizedName.equals(metaItemId)).findFirst().orElse(null); + if (metaValueItem != null) return new GuideItem(metaValueItem); + ; + } + } + return null; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + GuideItem guideItem = (GuideItem) o; + return Objects.equals(stack, guideItem.stack) && Objects.equals(name, guideItem.name); + } + + @Override + public int hashCode() { + return Objects.hash(stack, name); + } + } +} diff --git a/src/main/java/gregtech/common/terminal/app/guide/MultiBlockGuideApp.java b/src/main/java/gregtech/common/terminal/app/guide/MultiBlockGuideApp.java new file mode 100644 index 00000000000..edee321db22 --- /dev/null +++ b/src/main/java/gregtech/common/terminal/app/guide/MultiBlockGuideApp.java @@ -0,0 +1,46 @@ +package gregtech.common.terminal.app.guide; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import gregtech.api.GTValues; +import gregtech.api.GregTechAPI; +import gregtech.api.gui.resources.IGuiTexture; +import gregtech.api.gui.resources.ItemStackTexture; +import gregtech.api.metatileentity.MetaTileEntity; +import gregtech.common.metatileentities.MetaTileEntities; +import net.minecraft.util.ResourceLocation; + +public class MultiBlockGuideApp extends GuideApp { + + public MultiBlockGuideApp() { + super("multiblocks", new ItemStackTexture(MetaTileEntities.ELECTRIC_BLAST_FURNACE.getStackForm())); + } + + @Override + protected MetaTileEntity ofJson(JsonObject json) { + String[] valids = {"multiblock", "metatileentity"}; + if (json.isJsonObject()) { + for (String valid : valids) { + JsonElement id = json.getAsJsonObject().get(valid); + if (id != null && id.isJsonPrimitive()) + return GregTechAPI.META_TILE_ENTITY_REGISTRY.getObject(new ResourceLocation(GTValues.MODID, id.getAsString())); + } + } + return null; + } + + @Override + protected IGuiTexture itemIcon(MetaTileEntity item) { + return new ItemStackTexture(item.getStackForm()); + } + + @Override + protected String itemName(MetaTileEntity item) { + return item.getStackForm().getDisplayName(); + } + + @Override + protected String rawItemName(MetaTileEntity item) { + return item.metaTileEntityId.getPath(); + } +} diff --git a/src/main/java/gregtech/common/terminal/app/guide/SimpleMachineGuideApp.java b/src/main/java/gregtech/common/terminal/app/guide/SimpleMachineGuideApp.java new file mode 100644 index 00000000000..c6483b4cff2 --- /dev/null +++ b/src/main/java/gregtech/common/terminal/app/guide/SimpleMachineGuideApp.java @@ -0,0 +1,46 @@ +package gregtech.common.terminal.app.guide; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import gregtech.api.GTValues; +import gregtech.api.GregTechAPI; +import gregtech.api.gui.resources.IGuiTexture; +import gregtech.api.gui.resources.ItemStackTexture; +import gregtech.api.metatileentity.MetaTileEntity; +import gregtech.common.metatileentities.MetaTileEntities; +import net.minecraft.util.ResourceLocation; + +public class SimpleMachineGuideApp extends GuideApp { + + public SimpleMachineGuideApp() { + super("machines", new ItemStackTexture(MetaTileEntities.CHEMICAL_REACTOR[0].getStackForm())); + } + + @Override + protected IGuiTexture itemIcon(MetaTileEntity item) { + return new ItemStackTexture(item.getStackForm()); + } + + @Override + protected String itemName(MetaTileEntity item) { + return item.getStackForm().getDisplayName(); + } + + @Override + protected String rawItemName(MetaTileEntity item) { + return item.metaTileEntityId.getPath(); + } + + @Override + protected MetaTileEntity ofJson(JsonObject json) { + String[] valids = {"machine", "generator", "metatileentity"}; + if (json.isJsonObject()) { + for (String valid : valids) { + JsonElement id = json.getAsJsonObject().get(valid); + if (id != null && id.isJsonPrimitive()) + return GregTechAPI.META_TILE_ENTITY_REGISTRY.getObject(new ResourceLocation(GTValues.MODID, id.getAsString())); + } + } + return null; + } +} diff --git a/src/main/java/gregtech/common/terminal/app/guide/TutorialGuideApp.java b/src/main/java/gregtech/common/terminal/app/guide/TutorialGuideApp.java new file mode 100644 index 00000000000..4092d7641f7 --- /dev/null +++ b/src/main/java/gregtech/common/terminal/app/guide/TutorialGuideApp.java @@ -0,0 +1,30 @@ +package gregtech.common.terminal.app.guide; + +import com.google.gson.JsonObject; +import gregtech.api.gui.resources.ItemStackTexture; +import net.minecraft.client.resources.I18n; +import net.minecraft.init.Items; + +public class TutorialGuideApp extends GuideApp { + + public TutorialGuideApp() { + super("tutorials", new ItemStackTexture(Items.PAPER)); + } + + @Override + protected String itemName(String item) { + return I18n.format(item); + } + + @Override + protected String rawItemName(String item) { + return item; + } + + @Override + protected String ofJson(JsonObject json) { + if (json.has("tutorial")) + return json.get("tutorial").getAsString(); + return json.get("title").getAsString(); + } +} diff --git a/src/main/java/gregtech/common/terminal/app/guide/widget/CardWidget.java b/src/main/java/gregtech/common/terminal/app/guide/widget/CardWidget.java new file mode 100644 index 00000000000..e2832411242 --- /dev/null +++ b/src/main/java/gregtech/common/terminal/app/guide/widget/CardWidget.java @@ -0,0 +1,108 @@ +package gregtech.common.terminal.app.guide.widget; + +import com.google.gson.JsonObject; +import gregtech.api.gui.IRenderContext; +import gregtech.api.gui.Widget; +import gregtech.api.terminal.gui.widgets.DraggableScrollableWidgetGroup; +import gregtech.common.terminal.app.guideeditor.widget.configurator.BooleanConfigurator; +import gregtech.common.terminal.app.guideeditor.widget.configurator.NumberConfigurator; +import gregtech.api.util.Position; +import gregtech.api.util.Size; +import net.minecraft.client.renderer.BufferBuilder; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import org.lwjgl.opengl.GL11; + +import java.util.function.Consumer; + +public class CardWidget extends GuideWidget{ + public final static String NAME = "card"; + + //config + public int width; + public int height; + public boolean isShadow; + + @Override + public String getRegistryName() { + return NAME; + } + + @Override + public JsonObject getTemplate(boolean isFixed) { + JsonObject template = super.getTemplate(isFixed); + template.addProperty("fill", -3745585); + template.addProperty("width", 120); + template.addProperty("height", 60); + template.addProperty("isShadow", true); + return template; + } + + @Override + public void loadConfigurator(DraggableScrollableWidgetGroup group, JsonObject config, boolean isFixed, Consumer needUpdate) { + super.loadConfigurator(group, config, isFixed, needUpdate); + if (!isFixed) { + group.addWidget(new NumberConfigurator(group, config, "width").setOnUpdated(needUpdate)); + group.addWidget(new NumberConfigurator(group, config, "height").setOnUpdated(needUpdate)); + } + group.addWidget(new BooleanConfigurator(group, config, "isShadow", true).setOnUpdated(needUpdate)); + } + + @Override + protected Widget initStream() { + int pageWidth = getSize().width; + int x = getSelfPosition().x; + int y = getSelfPosition().y; + if (page != null) { + x = page.getMargin(); + pageWidth = page.getPageWidth() - 2 * x; + } + this.setSelfPosition(new Position(x + (pageWidth - width) / 2, y)); + return initFixed(); + } + + @Override + protected Widget initFixed() { + this.setSize(new Size(width, height)); + return this; + } + + @Override + public void drawInBackground(int mouseX, int mouseY, float partialTicks, IRenderContext context) { + if (isShadow) { + int x = getPosition().x; + int y = getPosition().y; + int width = getSize().width; + int height = getSize().height; + drawGradientRect(x + 5, y + height, width - 5, 5, 0x4f000000, 0, false); + drawGradientRect(x + width, y + 5, 5, height - 5, 0x4f000000, 0, true); + + float startAlpha = (float) (0x4f) / 255.0F; + GlStateManager.disableTexture2D(); + GlStateManager.enableBlend(); + GlStateManager.disableAlpha(); + GlStateManager.tryBlendFuncSeparate(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ZERO); + GlStateManager.shadeModel(GL11.GL_SMOOTH); + Tessellator tessellator = Tessellator.getInstance(); + BufferBuilder buffer = tessellator.getBuffer(); + buffer.begin(GL11.GL_TRIANGLES, DefaultVertexFormats.POSITION_COLOR); + x += width; + y += height; + width = 5; + height = 5; + buffer.pos(x, y, 0).color(0, 0, 0, startAlpha).endVertex(); + buffer.pos(x, y + height, 0).color(0, 0, 0, 0).endVertex(); + buffer.pos(x + width, y + height, 0).color(0, 0, 0, 0).endVertex(); + + buffer.pos(x, y, 0).color(0, 0, 0, startAlpha).endVertex(); + buffer.pos(x + width, y + height, 0).color(0, 0, 0, 0).endVertex(); + buffer.pos(x + width, y, 0).color(0, 0, 0, 0).endVertex(); + tessellator.draw(); + GlStateManager.shadeModel(GL11.GL_FLAT); + GlStateManager.enableAlpha(); + GlStateManager.enableTexture2D(); + } + super.drawInBackground(mouseX, mouseY, partialTicks, context); + } +} diff --git a/src/main/java/gregtech/common/terminal/app/guide/widget/GuidePageWidget.java b/src/main/java/gregtech/common/terminal/app/guide/widget/GuidePageWidget.java new file mode 100644 index 00000000000..ddbd26f5d19 --- /dev/null +++ b/src/main/java/gregtech/common/terminal/app/guide/widget/GuidePageWidget.java @@ -0,0 +1,185 @@ +package gregtech.common.terminal.app.guide.widget; + + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import gregtech.api.gui.Widget; +import gregtech.api.gui.resources.ColorRectTexture; +import gregtech.api.terminal.gui.widgets.DraggableScrollableWidgetGroup; +import gregtech.api.util.Position; +import gregtech.api.util.Size; +import gregtech.api.util.interpolate.Eases; +import gregtech.api.util.interpolate.Interpolator; + +import java.awt.*; +import java.util.*; +import java.util.List; + +public class GuidePageWidget extends DraggableScrollableWidgetGroup { + public static final Map REGISTER_WIDGETS = new HashMap<>(); + static { //register guide widgets + REGISTER_WIDGETS.put(TextBoxWidget.NAME, new TextBoxWidget()); + REGISTER_WIDGETS.put(ImageWidget.NAME, new ImageWidget()); + REGISTER_WIDGETS.put(CardWidget.NAME, new CardWidget()); + REGISTER_WIDGETS.put(SlotListWidget.NAME, new SlotListWidget()); + REGISTER_WIDGETS.put(TankListWidget.NAME, new TankListWidget()); + } + protected TextBoxWidget title; + protected List stream = new ArrayList<>(); + protected List fixed = new ArrayList<>(); + protected Interpolator interpolator; + private final int margin; + + public GuidePageWidget(int xPosition, int yPosition, int width, int height, int margin) { + super(xPosition, yPosition, width, height); + this.margin = margin; + this.setBackground(new ColorRectTexture(-1)) + .setDraggable(true) + .setYScrollBarWidth(4) + .setYBarStyle(new ColorRectTexture(new Color(142, 142, 142)), + new ColorRectTexture(new Color(148, 226, 193))); + + } + + public int getPageWidth() { + return this.getSize().width - yBarWidth; + } + + public int getMargin() { + return margin; + } + + public void setTitle(String config) { + int x = 5; + int y = 2; + int width = this.getSize().width - yBarWidth - 10; + int height = 0; + if (title != null) { + height = title.getSize().height; + x = title.getSelfPosition().x; + y = title.getSelfPosition().y; + removeWidget(title); + } + title = new TextBoxWidget(5, 2, width, + Collections.singletonList(config), + 0, 15, 0xffffffff, 0x6fff0000, 0xff000000, + true, true); + this.addWidget(title); + title.setSelfPosition(new Position(x, y)); + int offset = title.getSize().height - height; + if (offset != 0) { + for (Widget widget : stream) { + widget.addSelfPosition(0, offset); + } + } + } + + public String getTitle() { + return title == null ? "" : String.join("\n", title.content); + } + + public String loadJsonConfig(String config) { + try { + loadJsonConfig(new JsonParser().parse(config).getAsJsonObject()); + } catch (Exception e) { + this.clearAllWidgets(); + return e.getMessage(); + } + return null; + } + + public void loadJsonConfig(JsonObject config) { + this.stream.clear(); + this.fixed.clear(); + this.title = null; + this.clearAllWidgets(); + int pageWidth = getPageWidth(); + int margin = getMargin(); + // add title + setTitle(config.get("title").getAsString()); + + // add stream widgets + if (config.has("stream")) { + stream = new ArrayList<>(); + int y = title.getSize().height + 10; + for (JsonElement element : config.getAsJsonArray("stream")) { + JsonObject widgetConfig = element.getAsJsonObject(); + Widget widget = REGISTER_WIDGETS.get(widgetConfig.get("type").getAsString()).updateOrCreateStreamWidget(margin, y, pageWidth - 2 * margin, widgetConfig); + y += widget.getSize().height + 5; + stream.add(widget); + this.addWidget(widget); + } + } + // add fixed widgets + if (config.has("fixed")) { + fixed = new ArrayList<>(); + for (JsonElement element : config.getAsJsonArray("fixed")) { + JsonObject widgetConfig = element.getAsJsonObject(); + Widget widget = REGISTER_WIDGETS.get(widgetConfig.get("type").getAsString()).updateOrCreateFixedWidget( + widgetConfig.get("x").getAsInt(), + widgetConfig.get("y").getAsInt(), + widgetConfig.get("width").getAsInt(), + widgetConfig.get("height").getAsInt(), + widgetConfig); + fixed.add(widget); + this.addWidget(widget); + } + } + } + + public void onSizeUpdate(Widget widget, Size oldSize) { + int offset = widget.getSize().height - oldSize.height; + maxHeight = Math.max(maxHeight, widget.getSize().height + widget.getSelfPosition().y); + int index = stream.indexOf(widget); + if (index < 0) return; + for (int i = stream.size() - 1; i > index; i--) { + Widget nextWidget = stream.get(i); + nextWidget.addSelfPosition(0, offset); + } + } + + public void onPositionUpdate(Widget widget, Position oldPosition) { + if (oldPosition.y + widget.getSize().height == maxHeight) { + maxHeight = 0; + for (Widget widget1 : widgets) { + maxHeight = Math.max(maxHeight, widget1.getSize().height + widget1.getSelfPosition().y + scrollYOffset); + } + } + } + + protected int getStreamBottom() { + if (stream!= null && stream.size() > 0) { + Widget widget = stream.get(stream.size() - 1); + return widget.getSize().height + widget.getSelfPosition().y; + } else { + return title.getSize().height + 10; + } + } + + @Override + public void updateScreen() { + if (interpolator != null) interpolator.update(); + super.updateScreen(); + } + + public void jumpToRef(String ref){ + if (interpolator != null && !interpolator.isFinish()) return; + for (Widget widget : widgets) { + if (widget instanceof IGuideWidget && ref.equals(((IGuideWidget) widget).getRef())) { + interpolator = new Interpolator(scrollYOffset, widget.getSelfPosition().y + scrollYOffset, 20, Eases.EaseQuadOut, + value-> setScrollYOffset(value.intValue()), + value-> interpolator = null); + interpolator.start(); + } + } + } + + @Override + public void addWidget(Widget widget) { + super.addWidget(widget); + if (widget instanceof IGuideWidget) { + ((IGuideWidget) widget).setPage(this); + } + } +} diff --git a/src/main/java/gregtech/common/terminal/app/guide/widget/GuideWidget.java b/src/main/java/gregtech/common/terminal/app/guide/widget/GuideWidget.java new file mode 100644 index 00000000000..be8892b28e1 --- /dev/null +++ b/src/main/java/gregtech/common/terminal/app/guide/widget/GuideWidget.java @@ -0,0 +1,183 @@ +package gregtech.common.terminal.app.guide.widget; + +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import gregtech.api.gui.IRenderContext; +import gregtech.api.gui.Widget; +import gregtech.api.terminal.gui.widgets.DraggableScrollableWidgetGroup; +import gregtech.common.terminal.app.guideeditor.widget.configurator.ColorConfigurator; +import gregtech.common.terminal.app.guideeditor.widget.configurator.NumberConfigurator; +import gregtech.common.terminal.app.guideeditor.widget.configurator.StringConfigurator; +import gregtech.common.terminal.app.guideeditor.widget.configurator.TextListConfigurator; +import gregtech.api.util.Position; +import gregtech.api.util.Size; +import net.minecraft.item.ItemStack; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Consumer; + +public abstract class GuideWidget extends Widget implements IGuideWidget { + //config + public String ref; + public int fill; + public int stroke; + public int stroke_width = 1; + public String link; + public List hover_text; + + private transient boolean isFixed; + protected transient GuidePageWidget page; + protected transient JsonObject config; + + public GuideWidget(int x, int y, int width, int height) { + super(x, y, width, height); + } + + public GuideWidget(){ + super(Position.ORIGIN, Size.ZERO); + } + + public abstract String getRegistryName(); + + @Override + public JsonObject getConfig() { + return config; + } + + @Override + public boolean isFixed() { + return isFixed; + } + + protected abstract Widget initFixed(); + + protected Widget initStream(){ + return initFixed(); + } + + @Override + public void setStroke(int color) { + this.stroke = color; + } + + @Override + public void setSize(Size size) { + Size oldSize = this.getSize(); + super.setSize(size); + if (page != null) { + page.onSizeUpdate(this, oldSize); + } + } + + @Override + protected void recomputePosition() { + Position oldPosition = getPosition(); + super.recomputePosition(); + if (page != null) { + page.onPositionUpdate(this, oldPosition); + } + } + + @Override + public JsonObject getTemplate(boolean isFixed) { + JsonObject template = new JsonObject(); + template.addProperty("type", getRegistryName()); + if (isFixed) { + template.addProperty("x", 0); + template.addProperty("y", 0); + template.addProperty("width", 100); + template.addProperty("height", 100); + } + template.addProperty("ref", (String) null); + template.addProperty("stroke", (String) null); + template.addProperty("stroke_width", (String) null); + template.addProperty("fill", (String) null); + template.addProperty("link", (String) null); + template.add("hover_text", new Gson().toJsonTree(hover_text)); + return template; + } + + @Override + public void loadConfigurator(DraggableScrollableWidgetGroup group, JsonObject config, boolean isFixed, Consumer needUpdate) { + group.addWidget(new ColorConfigurator(group, config, "fill", 0).setOnUpdated(needUpdate)); + group.addWidget(new ColorConfigurator(group, config, "stroke", 0).setOnUpdated(needUpdate)); + group.addWidget(new NumberConfigurator(group, config, "stroke_width", 1).setOnUpdated(needUpdate)); + group.addWidget(new StringConfigurator(group, config, "ref", "").setOnUpdated(needUpdate)); + group.addWidget(new StringConfigurator(group, config, "link", "").setOnUpdated(needUpdate)); + group.addWidget(new TextListConfigurator(group, 40, config, "hover_text", "").setOnUpdated(needUpdate)); + } + + @Override + public String getRef() { + return ref; + } + + @Override + public Widget updateOrCreateStreamWidget(int x, int y, int pageWidth, JsonObject config) { + if (config == null) { + return initStream(); + } + GuideWidget widget = new Gson().fromJson(config, this.getClass()); + widget.isFixed = false; + widget.setSelfPosition(new Position(x, y)); + widget.setSize(new Size(pageWidth, 0)); + widget.config = config; + return widget.initStream(); + } + + @Override + public Widget updateOrCreateFixedWidget(int x, int y, int width, int height, JsonObject config) { + if (config == null) { + return initFixed(); + } + GuideWidget widget = new Gson().fromJson(config, this.getClass()); + widget.isFixed = true; + widget.setSelfPosition(new Position(x, y)); + widget.setSize(new Size(width, height)); + widget.config = config; + return widget.initFixed(); + } + + @Override + public void setPage(GuidePageWidget page) { + this.page = page; + } + + @Override + public void drawInForeground(int mouseX, int mouseY) { + if (link != null && isMouseOverElement(mouseX, mouseY)) { + Position position = getPosition(); + Size size = getSize(); + drawBorder(position.x, position.y, size.width, size.height, 0xff0000ff, stroke_width); + } + if ((hover_text != null || link != null) && isMouseOverElement(mouseX, mouseY)) { + List tooltip = hover_text == null ? new ArrayList<>() : new ArrayList<>(hover_text); + if (link != null) { + tooltip.add("§9Ctrl+Click§r §e(" + link + ")§r"); + } + drawHoveringText(ItemStack.EMPTY, tooltip, 100, mouseX, mouseY); + } + } + + @Override + public void drawInBackground(int mouseX, int mouseY, float partialTicks, IRenderContext context) { + Position position = getPosition(); + Size size = getSize(); + if(stroke != 0) { + drawBorder(position.x, position.y, size.width, size.height, stroke, stroke_width); + } + if (fill != 0) { + drawSolidRect(position.x, position.y, size.width, size.height, fill); + } + } + + @Override + public boolean mouseClicked(int mouseX, int mouseY, int button) { + if (link != null && isMouseOverElement(mouseX, mouseY) && isCtrlDown()) { + page.jumpToRef(link); + return true; + } + return false; + } +} diff --git a/src/main/java/gregtech/common/terminal/app/guide/widget/GuideWidgetGroup.java b/src/main/java/gregtech/common/terminal/app/guide/widget/GuideWidgetGroup.java new file mode 100644 index 00000000000..4b765ce106f --- /dev/null +++ b/src/main/java/gregtech/common/terminal/app/guide/widget/GuideWidgetGroup.java @@ -0,0 +1,195 @@ +package gregtech.common.terminal.app.guide.widget; + +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import gregtech.api.gui.IRenderContext; +import gregtech.api.gui.Widget; +import gregtech.api.gui.widgets.WidgetGroup; +import gregtech.api.terminal.gui.widgets.DraggableScrollableWidgetGroup; +import gregtech.common.terminal.app.guideeditor.widget.configurator.ColorConfigurator; +import gregtech.common.terminal.app.guideeditor.widget.configurator.NumberConfigurator; +import gregtech.common.terminal.app.guideeditor.widget.configurator.StringConfigurator; +import gregtech.common.terminal.app.guideeditor.widget.configurator.TextListConfigurator; +import gregtech.api.util.Position; +import gregtech.api.util.Size; +import net.minecraft.item.ItemStack; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Consumer; + +public abstract class GuideWidgetGroup extends WidgetGroup implements IGuideWidget { + //config + public String ref; + public int fill; + public int stroke; + public int stroke_width = 1; + public String link; + public List hover_text; + + private transient boolean isFixed; + protected transient GuidePageWidget page; + protected transient JsonObject config; + + public GuideWidgetGroup(int x, int y, int width, int height) { + super(x, y, width, height); + } + + public GuideWidgetGroup(){ + super(Position.ORIGIN, Size.ZERO); + } + + public abstract String getRegistryName(); + + @Override + public JsonObject getConfig() { + return config; + } + + @Override + public boolean isFixed() { + return isFixed; + } + + @Override + public void setStroke(int color) { + this.stroke = color; + } + + @Override + public void setSize(Size size) { + Size oldSize = this.getSize(); + super.setSize(size); + if (page != null) { + page.onSizeUpdate(this, oldSize); + } + } + + @Override + protected void recomputePosition() { + Position oldPosition = getPosition(); + super.recomputePosition(); + if (page != null) { + page.onPositionUpdate(this, oldPosition); + } + } + + @Override + public JsonObject getTemplate(boolean isFixed) { + JsonObject template = new JsonObject(); + template.addProperty("type", getRegistryName()); + if (isFixed) { + template.addProperty("x", 0); + template.addProperty("y", 0); + template.addProperty("width", 100); + template.addProperty("height", 100); + } + template.addProperty("ref", (String) null); + template.addProperty("stroke", (String) null); + template.addProperty("stroke_width", (String) null); + template.addProperty("fill", (String) null); + template.addProperty("link", (String) null); + template.add("hover_text", new Gson().toJsonTree(hover_text)); + return template; + } + + @Override + public void loadConfigurator(DraggableScrollableWidgetGroup group, JsonObject config, boolean isFixed, Consumer needUpdate) { + group.addWidget(new ColorConfigurator(group, config, "fill", 0).setOnUpdated(needUpdate)); + group.addWidget(new ColorConfigurator(group, config, "stroke", 0).setOnUpdated(needUpdate)); + group.addWidget(new NumberConfigurator(group, config, "stroke_width", 1).setOnUpdated(needUpdate)); + group.addWidget(new StringConfigurator(group, config, "ref", "").setOnUpdated(needUpdate)); + group.addWidget(new StringConfigurator(group, config, "link", "").setOnUpdated(needUpdate)); + group.addWidget(new TextListConfigurator(group, 40, config, "hover_text", "").setOnUpdated(needUpdate)); + } + + @Override + public String getRef() { + return ref; + } + + protected Widget initStream() { + return initFixed(); + } + + protected abstract Widget initFixed(); + + @Override + public Widget updateOrCreateStreamWidget(int x, int y, int pageWidth, JsonObject config) { + if (config == null) { + return initStream(); + } + GuideWidgetGroup widget = new Gson().fromJson(config, this.getClass()); + widget.isFixed = false; + widget.setSelfPosition(new Position(x, y)); + widget.setSize(new Size(pageWidth, 0)); + widget.config = config; + return widget.initStream(); + } + + @Override + public Widget updateOrCreateFixedWidget(int x, int y, int width, int height, JsonObject config) { + if (config == null) { + return initFixed(); + } + GuideWidgetGroup widget = new Gson().fromJson(config, this.getClass()); + widget.isFixed = true; + widget.setSelfPosition(new Position(x, y)); + widget.setSize(new Size(width, height)); + widget.config = config; + return widget.initFixed(); + } + + @Override + public void setPage(GuidePageWidget page) { + this.page = page; + } + + @Override + public void addWidget(Widget widget) { + super.addWidget(widget); + if (widget instanceof IGuideWidget) { + ((IGuideWidget) widget).setPage(page); + } + } + + @Override + public void drawInForeground(int mouseX, int mouseY) { + if (link != null && isMouseOverElement(mouseX, mouseY)) { + Position position = getPosition(); + Size size = getSize(); + drawBorder(position.x, position.y, size.width, size.height, 0xff0000ff, stroke_width); + } + if ((hover_text != null || link != null) && isMouseOverElement(mouseX, mouseY)) { + List tooltip = hover_text == null ? new ArrayList<>() : new ArrayList<>(hover_text); + if (link != null) { + tooltip.add("§9Ctrl+Click§r §e(" + link + ")§r"); + } + drawHoveringText(ItemStack.EMPTY, tooltip, 100, mouseX, mouseY); + } + super.drawInForeground(mouseX, mouseY); + } + + @Override + public void drawInBackground(int mouseX, int mouseY, float partialTicks, IRenderContext context) { + Position position = getPosition(); + Size size = getSize(); + if(stroke != 0) { + drawBorder(position.x, position.y, size.width, size.height, stroke, stroke_width); + } + if (fill != 0) { + drawSolidRect(position.x, position.y, size.width, size.height, fill); + } + super.drawInBackground(mouseX, mouseY, partialTicks, context); + } + + @Override + public boolean mouseClicked(int mouseX, int mouseY, int button) { + if (link != null && isMouseOverElement(mouseX, mouseY) && isCtrlDown()) { + page.jumpToRef(link); + return true; + } + return super.mouseClicked(mouseX, mouseY, button); + } + +} diff --git a/src/main/java/gregtech/common/terminal/app/guide/widget/IGuideWidget.java b/src/main/java/gregtech/common/terminal/app/guide/widget/IGuideWidget.java new file mode 100644 index 00000000000..d1c754ef30b --- /dev/null +++ b/src/main/java/gregtech/common/terminal/app/guide/widget/IGuideWidget.java @@ -0,0 +1,48 @@ +package gregtech.common.terminal.app.guide.widget; + +import com.google.gson.Gson; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import gregtech.api.gui.Widget; +import gregtech.api.terminal.gui.widgets.DraggableScrollableWidgetGroup; +import gregtech.api.util.Position; +import gregtech.api.util.Size; + +import java.lang.reflect.Field; +import java.util.function.Consumer; + +public interface IGuideWidget { + String getRegistryName(); + JsonObject getConfig(); + boolean isFixed(); + Widget updateOrCreateStreamWidget(int x, int y, int pageWidth, JsonObject config); + Widget updateOrCreateFixedWidget(int x, int y, int width, int height, JsonObject config); + void setPage(GuidePageWidget page); + default void updateValue(String field){ + JsonObject config = getConfig(); + if (config != null && config.has(field)) { + try { + Field f = this.getClass().getField(field); + JsonElement value = config.get(field); + if (value.isJsonNull()) { // default + f.set(this, f.get(GuidePageWidget.REGISTER_WIDGETS.get(getRegistryName()))); + } else { + f.set(this, new Gson().fromJson(value, f.getGenericType())); + } + if (isFixed()) { + updateOrCreateFixedWidget(0,0,0,0,null); + } else { + updateOrCreateStreamWidget(0,0,0,null); + } + } catch (Exception e) { + } + } + } + String getRef(); + JsonObject getTemplate(boolean isFixed); + void loadConfigurator(DraggableScrollableWidgetGroup group, JsonObject config, boolean isFixed, Consumer needUpdate); + void setStroke(int color); + default void onFixedPositionSizeChanged(Position position, Size size) { + updateOrCreateFixedWidget(0,0,0,0,null); + } +} diff --git a/src/main/java/gregtech/common/terminal/app/guide/widget/ImageWidget.java b/src/main/java/gregtech/common/terminal/app/guide/widget/ImageWidget.java new file mode 100644 index 00000000000..620fe8bcfe8 --- /dev/null +++ b/src/main/java/gregtech/common/terminal/app/guide/widget/ImageWidget.java @@ -0,0 +1,107 @@ +package gregtech.common.terminal.app.guide.widget; + +import com.google.gson.JsonObject; +import gregtech.api.gui.IRenderContext; +import gregtech.api.gui.Widget; +import gregtech.api.gui.resources.IGuiTexture; +import gregtech.api.gui.resources.ItemStackTexture; +import gregtech.api.gui.resources.TextureArea; +import gregtech.api.gui.resources.URLTexture; +import gregtech.api.terminal.gui.widgets.DraggableScrollableWidgetGroup; +import gregtech.common.terminal.app.guideeditor.widget.configurator.NumberConfigurator; +import gregtech.common.terminal.app.guideeditor.widget.configurator.SelectorConfigurator; +import gregtech.common.terminal.app.guideeditor.widget.configurator.StringConfigurator; +import gregtech.api.util.Position; +import gregtech.api.util.Size; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.item.Item; +import net.minecraft.util.ResourceLocation; + +import java.util.Arrays; +import java.util.function.Consumer; + +public class ImageWidget extends GuideWidget{ + public final static String NAME = "image"; + //config + public String form; + public String source; + public int width; + public int height; + + public transient IGuiTexture image; + + @Override + public String getRegistryName() { + return NAME; + } + + @Override + public JsonObject getTemplate(boolean isFixed) { + JsonObject template = super.getTemplate(isFixed); + template.addProperty("form", "resource"); + template.addProperty("source", "gregtech:textures/gui/icon/gregtech_logo.png"); + template.addProperty("width", 50); + template.addProperty("height", 50); + return template; + } + + @Override + public void loadConfigurator(DraggableScrollableWidgetGroup group, JsonObject config, boolean isFixed, Consumer needUpdate) { + super.loadConfigurator(group, config, isFixed, needUpdate); + group.addWidget(new SelectorConfigurator(group, config, "form", Arrays.asList("url", "item", "resource")).setOnUpdated(needUpdate)); + group.addWidget(new StringConfigurator(group, config, "source").setOnUpdated(needUpdate)); + if (!isFixed) { + group.addWidget(new NumberConfigurator(group, config, "width").setOnUpdated(needUpdate)); + group.addWidget(new NumberConfigurator(group, config, "height").setOnUpdated(needUpdate)); + } + } + + @Override + public void updateScreen() { + if (image != null) { + image.updateTick(); + } + } + + @Override + protected Widget initStream() { + int pageWidth = getSize().width; + int x = getSelfPosition().x; + int y = getSelfPosition().y; + if (page != null) { + x = page.getMargin(); + pageWidth = page.getPageWidth() - 2 * x; + } + this.setSelfPosition(new Position(x + (pageWidth - Math.max(0, width)) / 2, y)); + return initFixed(); + } + + @Override + protected Widget initFixed() { + width = Math.max(0, width); + height = Math.max(0, height); + this.setSize(new Size(width, height)); + switch (form) { + case "url": + image = new URLTexture(source); + break; + case "item": + image = new ItemStackTexture(Item.getByNameOrId(source)); + break; + case "resource": + image = new TextureArea(new ResourceLocation(source), 0.0, 0.0, 1.0, 1.0); + break; + } + return this; + } + + @Override + public void drawInBackground(int mouseX, int mouseY, float partialTicks, IRenderContext context) { + if (image != null) { + super.drawInBackground(mouseX, mouseY, partialTicks,context); + GlStateManager.color(1,1,1,1); + Position position = getPosition(); + image.draw(position.x, position.y, getSize().width, getSize().height); + } + } +} diff --git a/src/main/java/gregtech/common/terminal/app/guide/widget/SlotListWidget.java b/src/main/java/gregtech/common/terminal/app/guide/widget/SlotListWidget.java new file mode 100644 index 00000000000..7b5e20d5cbf --- /dev/null +++ b/src/main/java/gregtech/common/terminal/app/guide/widget/SlotListWidget.java @@ -0,0 +1,114 @@ +package gregtech.common.terminal.app.guide.widget; + +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import gregtech.api.gui.Widget; +import gregtech.api.gui.resources.ColorRectTexture; +import gregtech.api.gui.resources.IGuiTexture; +import gregtech.api.gui.widgets.SlotWidget; +import gregtech.api.terminal.gui.widgets.DraggableScrollableWidgetGroup; +import gregtech.common.terminal.app.guideeditor.widget.configurator.ItemStackConfigurator; +import gregtech.api.util.Size; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.items.ItemStackHandler; + +import java.util.Collections; +import java.util.List; +import java.util.function.Consumer; + +public class SlotListWidget extends GuideWidgetGroup { + public final static String NAME = "slots"; + + // config + public List item_list; + + @Override + public Widget initFixed() { + this.clearAllWidgets(); + ItemStackHandler itemStackHandler = new ItemStackHandler(item_list.size()); + IGuiTexture background = new ColorRectTexture(0x4f000000); + int size = item_list.size(); + int maxXSize = getSize().width / 18; + int xPos; + if (maxXSize < 1) { + maxXSize = 1; + xPos = 0; + } else { + xPos = (getSize().width - (Math.min(size, maxXSize)) * 18) / 2; + } + int maxYSize = size / maxXSize + ((size % maxXSize) == 0 ? 0 : 1); + for (int y = 0; y <= size / maxXSize; y++) { + for (int x = 0; x < maxXSize; x++) { + int i = x + y * maxXSize; + if (i < size) { + itemStackHandler.setStackInSlot(i, item_list.get(i).getInstance()); + SlotWidget widget = new SlotWidget(itemStackHandler, i, xPos + x * 18, y * 18, false, false); + widget.setBackgroundTexture(background); + this.addWidget(widget); + } + } + } + setSize(new Size(getSize().width / 18 > 0 ? getSize().width : 18, maxYSize * 18)); + return this; + } + + @Override + public String getRegistryName() { + return NAME; + } + + @Override + public JsonObject getTemplate(boolean isFixed) { + JsonObject template = super.getTemplate(isFixed); + template.add("item_list", new Gson().toJsonTree(Collections.singletonList(new ItemStackInfo("minecraft:ender_pearl", 0, 1)))); + return template; + } + + @Override + public void loadConfigurator(DraggableScrollableWidgetGroup group, JsonObject config, boolean isFixed, Consumer needUpdate) { + super.loadConfigurator(group, config, isFixed, needUpdate); + group.addWidget(new ItemStackConfigurator(group, config, "item_list").setOnUpdated(needUpdate)); + } + + public static class ItemStackInfo { + // config + public String id; + public int damage; + public int count = 1; + + private transient ItemStack itemStack; + + public ItemStackInfo() { + + } + + public void update(ItemStack itemStack) { + ResourceLocation resourceLocation = itemStack.getItem().getRegistryName(); + id = resourceLocation == null ? "minecraft:air" : resourceLocation.toString(); + damage = itemStack.getItemDamage(); + count = itemStack.getCount(); + } + + public ItemStackInfo(String id, int damage, int count) { + this.id = id; + this.damage = damage; + this.count = count; + } + + public ItemStack getInstance() { + if (itemStack == null && id != null) { + Item item = Item.getByNameOrId(id); + if (item == null) { + itemStack = ItemStack.EMPTY; + return itemStack; + } + itemStack = item.getDefaultInstance(); + itemStack.setCount(count); + itemStack.setItemDamage(damage); + } + return itemStack == null ? ItemStack.EMPTY : itemStack; + } + } +} diff --git a/src/main/java/gregtech/common/terminal/app/guide/widget/TankListWidget.java b/src/main/java/gregtech/common/terminal/app/guide/widget/TankListWidget.java new file mode 100644 index 00000000000..2d8eeadf282 --- /dev/null +++ b/src/main/java/gregtech/common/terminal/app/guide/widget/TankListWidget.java @@ -0,0 +1,116 @@ +package gregtech.common.terminal.app.guide.widget; + +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import gregtech.api.gui.Widget; +import gregtech.api.gui.resources.ColorRectTexture; +import gregtech.api.gui.resources.IGuiTexture; +import gregtech.api.gui.widgets.TankWidget; +import gregtech.api.terminal.gui.widgets.DraggableScrollableWidgetGroup; +import gregtech.common.terminal.app.guideeditor.widget.configurator.FluidStackConfigurator; +import gregtech.api.util.Size; +import net.minecraftforge.fluids.Fluid; +import net.minecraftforge.fluids.FluidRegistry; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.FluidTank; + +import java.awt.*; +import java.util.Collections; +import java.util.List; +import java.util.function.Consumer; + +public class TankListWidget extends GuideWidgetGroup { + public final static String NAME = "tanks"; + + // config + public List fluid_list; + + protected transient Rectangle scissor; + + @Override + public Widget initFixed() { + this.clearAllWidgets(); + IGuiTexture background = new ColorRectTexture(0x4f000000); + int size = fluid_list.size(); + int maxXSize = getSize().width / 18; + int xPos; + if (maxXSize < 1) { + maxXSize = 1; + xPos = 0; + } else { + xPos = (getSize().width - (Math.min(size, maxXSize)) * 18) / 2; + } + int maxYSize = size / maxXSize + ((size % maxXSize) == 0 ? 0 : 1); + for (int y = 0; y <= size / maxXSize; y++) { + for (int x = 0; x < maxXSize; x++) { + int i = x + y * maxXSize; + if (i < size) { + FluidStack fluidStack = fluid_list.get(i).getInstance(); + TankWidget widget = new TankWidget(new FluidTank(fluidStack, fluid_list.get(i).amount), xPos + x * 18, y * 18, 18, 18); + widget.setBackgroundTexture(background).setAlwaysShowFull(true); + this.addWidget(widget); + } + } + } + setSize(new Size(getSize().width / 18 > 0 ? getSize().width : 18, maxYSize * 18)); + return this; + } + + @Override + public String getRegistryName() { + return NAME; + } + + @Override + public JsonObject getTemplate(boolean isFixed) { + JsonObject template = super.getTemplate(isFixed); + template.add("fluid_list", new Gson().toJsonTree(Collections.singletonList(new FluidStackInfo("distilled_water", 1)))); + return template; + } + + @Override + public void loadConfigurator(DraggableScrollableWidgetGroup group, JsonObject config, boolean isFixed, Consumer needUpdate) { + super.loadConfigurator(group, config, isFixed, needUpdate); + group.addWidget(new FluidStackConfigurator(group, config, "fluid_list").setOnUpdated(needUpdate)); + } + + public static class FluidStackInfo { + // config + public String id; + public int amount = 1; + + private transient FluidStack fluidStack; + + public FluidStackInfo() { + + } + + public void update(FluidStack itemStack) { + if (itemStack != null) { + id = FluidRegistry.getFluidName(itemStack.getFluid()); + amount = itemStack.amount; + } else { + id = null; + fluidStack = null; + amount = 0; + } + } + + public FluidStackInfo(String id, int amount) { + this.id = id; + this.amount = amount; + } + + public FluidStack getInstance() { + if (fluidStack == null && id != null) { + Fluid fluid = FluidRegistry.getFluid(id); + if (fluid != null) { + fluidStack = new FluidStack(fluid, amount); + } else { + id = null; + } + } + return fluidStack; + } + } +} diff --git a/src/main/java/gregtech/common/terminal/app/guide/widget/TextBoxWidget.java b/src/main/java/gregtech/common/terminal/app/guide/widget/TextBoxWidget.java new file mode 100644 index 00000000000..8bcf3bd4bca --- /dev/null +++ b/src/main/java/gregtech/common/terminal/app/guide/widget/TextBoxWidget.java @@ -0,0 +1,120 @@ +package gregtech.common.terminal.app.guide.widget; + +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import gregtech.api.gui.IRenderContext; +import gregtech.api.gui.Widget; +import gregtech.api.terminal.gui.widgets.DraggableScrollableWidgetGroup; +import gregtech.common.terminal.app.guideeditor.widget.configurator.BooleanConfigurator; +import gregtech.common.terminal.app.guideeditor.widget.configurator.ColorConfigurator; +import gregtech.common.terminal.app.guideeditor.widget.configurator.NumberConfigurator; +import gregtech.common.terminal.app.guideeditor.widget.configurator.TextListConfigurator; +import gregtech.api.util.Position; +import gregtech.api.util.Size; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.resources.I18n; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.function.Consumer; + +public class TextBoxWidget extends GuideWidget { + public final static String NAME = "textbox"; + + // config + public List content; + public int space = 1; + public int fontSize = 9; + public int fontColor = 0xff000000; + public boolean isShadow = false; + public boolean isCenter = false; + + private transient List textLines; + + public TextBoxWidget(int x, int y, int width, List content, int space, int fontSize, int fontColor, int fill, int stroke, boolean isCenter, boolean isShadow) { + super(x, y, width, 0); + this.content = content; + this.space = space; + this.fontSize = fontSize; + this.fontColor = fontColor; + this.fill = fill; + this.stroke = stroke; + this.isCenter = isCenter; + this.isShadow = isShadow; + this.initFixed(); + } + + public TextBoxWidget() {} + + @Override + public String getRegistryName() { + return NAME; + } + + @Override + public JsonObject getTemplate(boolean isFixed) { + JsonObject template = super.getTemplate(isFixed); + template.addProperty("space", (String) null); + template.addProperty("fontSize", (String) null); + template.addProperty("fontColor", (String) null); + template.addProperty("isCenter", (String) null); + template.addProperty("isShadow", (String) null); + template.add("content", new Gson().toJsonTree(Arrays.asList("this is a", "textbox!"))); + return template; + } + + @Override + public void loadConfigurator(DraggableScrollableWidgetGroup group, JsonObject config, boolean isFixed, Consumer needUpdate) { + super.loadConfigurator(group, config, isFixed, needUpdate); + group.addWidget(new NumberConfigurator(group, config, "space", 1).setOnUpdated(needUpdate)); + group.addWidget(new NumberConfigurator(group, config, "fontSize", 9).setOnUpdated(needUpdate)); + group.addWidget(new ColorConfigurator(group, config, "fontColor", 0xff000000).setOnUpdated(needUpdate)); + group.addWidget(new BooleanConfigurator(group, config, "isShadow", false).setOnUpdated(needUpdate)); + group.addWidget(new BooleanConfigurator(group, config, "isCenter", false).setOnUpdated(needUpdate)); + group.addWidget(new TextListConfigurator(group, 200, config, "content").setOnUpdated(needUpdate)); + } + + @Override + protected Widget initFixed() { + this.textLines = new ArrayList<>(); + FontRenderer font = Minecraft.getMinecraft().fontRenderer; + this.space = Math.max(space, 0); + this.fontSize = Math.max(fontSize, 1); + int wrapWidth = getSize().width * font.FONT_HEIGHT / fontSize; + if (content != null) { + for (String textLine : content) { + this.textLines.addAll(font.listFormattedStringToWidth(I18n.format(textLine), wrapWidth)); + } + } + this.setSize(new Size(this.getSize().width, this.textLines.size() * (fontSize + space))); + return this; + } + + @Override + public void drawInBackground(int mouseX, int mouseY, float partialTicks, IRenderContext context) { + super.drawInBackground(mouseX, mouseY, partialTicks, context); + if (!textLines.isEmpty()) { + Position position = getPosition(); + Size size = getSize(); + FontRenderer font = Minecraft.getMinecraft().fontRenderer; + float scale = fontSize * 1.0f / font.FONT_HEIGHT; + GlStateManager.pushMatrix(); + GlStateManager.scale(scale, scale, 1); + GlStateManager.translate(position.x / scale, position.y / scale, 0); + float x = 0; + float y = 0; + float ySpace = font.FONT_HEIGHT + space / scale; + for (String textLine : textLines) { + if (isCenter) { + x = (size.width / scale - font.getStringWidth(textLine)) / 2; + } + font.drawString(textLine, x, y, fontColor, isShadow); + y += ySpace; + } + GlStateManager.popMatrix(); + } + } +} diff --git a/src/main/java/gregtech/common/terminal/app/guideeditor/GuideEditorApp.java b/src/main/java/gregtech/common/terminal/app/guideeditor/GuideEditorApp.java new file mode 100644 index 00000000000..ac84b3cac0c --- /dev/null +++ b/src/main/java/gregtech/common/terminal/app/guideeditor/GuideEditorApp.java @@ -0,0 +1,66 @@ +package gregtech.common.terminal.app.guideeditor; + +import gregtech.api.gui.GuiTextures; +import gregtech.api.gui.resources.TextureArea; +import gregtech.api.terminal.app.AbstractApplication; +import gregtech.common.terminal.app.guideeditor.widget.GuideConfigEditor; +import gregtech.common.terminal.app.guideeditor.widget.GuidePageEditorWidget; +import gregtech.api.terminal.os.TerminalOSWidget; +import gregtech.common.terminal.component.ClickComponent; +import gregtech.api.terminal.os.menu.IMenuComponent; +import net.minecraft.nbt.NBTTagCompound; + +import java.util.Arrays; +import java.util.List; + +public class GuideEditorApp extends AbstractApplication { + public static final TextureArea ICON = TextureArea.fullImage("textures/gui/terminal/guide_editor/icon.png"); + + + private GuideConfigEditor configEditor; + + + public GuideEditorApp() { + super("guide_editor", ICON); + } + + @Override + public AbstractApplication createApp(TerminalOSWidget os, boolean isClient, NBTTagCompound nbt) { + GuideEditorApp app = new GuideEditorApp(); + if (isClient) { + app.configEditor = new GuideConfigEditor(0, 0, 133, 232, app); + GuidePageEditorWidget pageEditor = new GuidePageEditorWidget(133, 0, 200, 232, 5); + app.configEditor.setGuidePageEditorWidget(pageEditor); + pageEditor.setGuideConfigEditor(app.configEditor); + app.addWidget(pageEditor); + app.addWidget(app.configEditor); + } + return app; + } + + @Override + public List getMenuComponents() { + ClickComponent newPage = new ClickComponent().setIcon(GuiTextures.ICON_NEW_PAGE).setHoverText("terminal.component.new_page").setClickConsumer(cd->{ + if (configEditor != null) { + configEditor.newPage(cd); + } + }); + ClickComponent importPage = new ClickComponent().setIcon(GuiTextures.ICON_LOAD).setHoverText("terminal.component.load_file").setClickConsumer(cd->{ + if (configEditor != null) { + configEditor.loadJson(cd); + } + }); + ClickComponent exportPage = new ClickComponent().setIcon(GuiTextures.ICON_SAVE).setHoverText("terminal.component.save_file").setClickConsumer(cd->{ + if (configEditor != null) { + configEditor.saveJson(cd); + } + }); + return Arrays.asList(newPage, importPage, exportPage); + } + + @Override + public boolean isClientSideApp() { + return true; + } + +} diff --git a/src/main/java/gregtech/common/terminal/app/guideeditor/widget/GuideConfigEditor.java b/src/main/java/gregtech/common/terminal/app/guideeditor/widget/GuideConfigEditor.java new file mode 100644 index 00000000000..0bfe6c1aac5 --- /dev/null +++ b/src/main/java/gregtech/common/terminal/app/guideeditor/widget/GuideConfigEditor.java @@ -0,0 +1,225 @@ +package gregtech.common.terminal.app.guideeditor.widget; + +import com.google.gson.JsonObject; +import gregtech.api.gui.GuiTextures; +import gregtech.api.gui.Widget; +import gregtech.api.gui.resources.ColorRectTexture; +import gregtech.api.gui.resources.TextTexture; +import gregtech.api.gui.widgets.*; +import gregtech.api.gui.widgets.tab.IGuiTextureTabInfo; +import gregtech.common.terminal.app.guide.widget.GuidePageWidget; +import gregtech.common.terminal.app.guide.widget.IGuideWidget; +import gregtech.common.terminal.app.guideeditor.GuideEditorApp; +import gregtech.api.terminal.gui.CustomTabListRenderer; +import gregtech.api.terminal.gui.widgets.CircleButtonWidget; +import gregtech.api.terminal.gui.widgets.DraggableScrollableWidgetGroup; +import gregtech.api.terminal.gui.widgets.TextEditorWidget; +import gregtech.api.terminal.os.TerminalDialogWidget; +import gregtech.api.terminal.os.TerminalTheme; +import gregtech.api.terminal.util.FileUtils; +import gregtech.api.util.Position; +import gregtech.api.util.Size; + +import java.awt.*; +import java.io.File; +import java.util.Map; +import java.util.Objects; + +public class GuideConfigEditor extends TabGroup { + public String json; + private IGuideWidget selected; + private GuidePageEditorWidget pageEditor; + private TextEditorWidget titleEditor; + private final DraggableScrollableWidgetGroup widgetSelector; + private final DraggableScrollableWidgetGroup widgetConfigurator; + private final CircleButtonWidget[] addButton; + private final GuideEditorApp app; + + public GuideConfigEditor(int x, int y, int width, int height, GuideEditorApp app) { + super(x, y + 10, new CustomTabListRenderer(TerminalTheme.COLOR_F_2, TerminalTheme.COLOR_B_3, 30, 10)); + setSize(new Size(width, height)); + addButton = new CircleButtonWidget[2]; + widgetSelector = createWidgetSelector(); + widgetConfigurator = createConfigurator(); + this.addTab(new IGuiTextureTabInfo(new TextTexture("P", -1), "terminal.guide_editor.page_config"), createPageConfig()); + this.addTab(new IGuiTextureTabInfo(new TextTexture("W", -1), "terminal.guide_editor.widgets_box"), widgetSelector); + this.addTab(new IGuiTextureTabInfo(new TextTexture("C", -1), "terminal.guide_editor.widget_config"), widgetConfigurator); + this.setOnTabChanged((oldIndex, newIndex)->{ + if (newIndex == 1) { + addButton[0].setVisible(true); + addButton[1].setVisible(true); + } else { + addButton[0].setVisible(false); + addButton[1].setVisible(false); + } + }); + addButton[0] = new CircleButtonWidget(115, 15, 8, 1, 8) + .setColors(new Color(255, 255, 255, 0).getRGB(), + TerminalTheme.COLOR_7.getColor(), + TerminalTheme.COLOR_4.getColor()) + .setIcon(GuiTextures.ICON_ADD) + .setHoverText("terminal.guide_editor.add_stream") + .setClickListener(this::addStream); + addButton[1] = new CircleButtonWidget(115, 35, 8, 1, 8) + .setColors(new Color(255, 255, 255, 0).getRGB(), + TerminalTheme.COLOR_7.getColor(), + TerminalTheme.COLOR_5.getColor()) + .setIcon(GuiTextures.ICON_ADD) + .setHoverText("terminal.guide_editor.add_fixed") + .setClickListener(this::addFixed); + addButton[0].setVisible(false); + addButton[1].setVisible(false); + this.app = app; + this.addWidget(addButton[0]); + this.addWidget(addButton[1]); + } + + public void setGuidePageEditorWidget(GuidePageEditorWidget pageEditor) { + this.pageEditor = pageEditor; + } + + public GuidePageEditorWidget getPageEditor() { + return pageEditor; + } + + private DraggableScrollableWidgetGroup createPageConfig() { + DraggableScrollableWidgetGroup group = new DraggableScrollableWidgetGroup(0, 0, getSize().width, getSize().height - 10) + .setBackground(TerminalTheme.COLOR_B_3) + .setYScrollBarWidth(4) + .setYBarStyle(null, TerminalTheme.COLOR_F_1); + group.addWidget(new LabelWidget(5, 5, "section", -1).setShadow(true)); + group.addWidget(new TextFieldWidget(5, 15, 116, 20, new ColorRectTexture(0x9f000000), null, null) + .setTextResponder(s->{ + if (pageEditor != null) { + pageEditor.setSection(s); + } + }, true) + .setTextSupplier(()-> getPageEditor().getSection(), true) + .setMaxStringLength(Integer.MAX_VALUE) + .setValidator(s->true)); + group.addWidget(new ImageWidget(5, 48,116, 1, new ColorRectTexture(-1))); + group.addWidget(new LabelWidget(5, 55, "title", -1).setShadow(true)); + titleEditor = new TextEditorWidget(5, 65, 116, 70, s->{ + if (pageEditor != null) { + pageEditor.setTitle(s); + } + }, true).setContent("Template").setBackground(new ColorRectTexture(0xA3FFFFFF)); + group.addWidget(titleEditor); + return group; + } + + public void updateTitle(String title) { + titleEditor.setContent(title); + } + + private DraggableScrollableWidgetGroup createWidgetSelector() { + DraggableScrollableWidgetGroup group = new DraggableScrollableWidgetGroup(0, 0, getSize().width, getSize().height - 10) + .setBackground(TerminalTheme.COLOR_B_3) + .setYScrollBarWidth(4) + .setYBarStyle(null, TerminalTheme.COLOR_F_1); + int y = 10; //133 + for (Map.Entry entry : GuidePageWidget.REGISTER_WIDGETS.entrySet()) { + IGuideWidget widgetTemplate = entry.getValue(); + JsonObject template = widgetTemplate.getTemplate(false); + Widget guideWidget = widgetTemplate.updateOrCreateStreamWidget(5, y + 10, getSize().width - 14, template); + group.addWidget(new LabelWidget(getSize().width / 2 - 1, y - 3, entry.getKey(), -1).setXCentered(true).setShadow(true)); + y += guideWidget.getSize().height + 25; + group.addWidget(guideWidget); + } + group.addWidget(new WidgetGroup(new Position(5, group.getWidgetBottomHeight() + 5), Size.ZERO)); + return group; + } + + private DraggableScrollableWidgetGroup createConfigurator() { + return new DraggableScrollableWidgetGroup(0, 0, getSize().width, getSize().height - 10) + .setBackground(TerminalTheme.COLOR_B_3) + .setYScrollBarWidth(4) + .setYBarStyle(null, TerminalTheme.COLOR_F_1); + } + + public void loadConfigurator(IGuideWidget widget) { + widgetConfigurator.clearAllWidgets(); + if (widget != null) { + widget.loadConfigurator(widgetConfigurator, widget.getConfig(), widget.isFixed(), widget::updateValue); + widgetConfigurator.addWidget(new WidgetGroup(new Position(5, widgetConfigurator.getWidgetBottomHeight() + 5), Size.ZERO)); + } + } + + public void newPage(ClickData data) { + TerminalDialogWidget.showConfirmDialog(app.getOs(), "terminal.component.new_page", "terminal.component.confirm", res->{ + if (res) { + pageEditor.loadJsonConfig("{\"section\":\"default\",\"title\":\"Template\",\"stream\":[],\"fixed\":[]}"); + getPageEditor().setSection("default"); + updateTitle("Template"); + } + }).setClientSide().open(); + } + + public void loadJson(ClickData data) { + if (pageEditor != null) { + File file = new File("terminal\\guide_editor"); + TerminalDialogWidget.showFileDialog(app.getOs(), "terminal.component.load_file", file, true, result->{ + if (result != null && result.isFile()) { + try { + JsonObject config = Objects.requireNonNull(FileUtils.loadJson(result)).getAsJsonObject(); + pageEditor.loadJsonConfig(config); + getPageEditor().setSection(config.get("section").getAsString()); + updateTitle(config.get("title").getAsString()); + } catch (Exception e) { + TerminalDialogWidget.showInfoDialog(app.getOs(), "terminal.component.error", "terminal.component.load_file.error").setClientSide().open(); + } + } + }).setClientSide().open(); + } + } + + public void saveJson(ClickData data) { + if(pageEditor != null) { + File file = new File("terminal\\guide_editor"); + TerminalDialogWidget.showFileDialog(app.getOs(), "terminal.component.save_file", file, false, result->{ + if (result != null) { + if(!FileUtils.saveJson(result, pageEditor.getJsonConfig())) { + TerminalDialogWidget.showInfoDialog(app.getOs(), "terminal.component.error", "terminal.component.save_file.error").setClientSide().open(); + } + } + }).setClientSide().open(); + } + } + + private void addFixed(ClickData data) { + if (pageEditor != null && selected != null) { + selected.setStroke(0); + pageEditor.addGuideWidget(selected, true); + selected.setStroke(0xFF7CA1FF); + } + } + + private void addStream(ClickData data) { + if (pageEditor != null && selected != null) { + selected.setStroke(0); + pageEditor.addGuideWidget(selected, false); + selected.setStroke(0xFF7CA1FF); + } + } + + @Override + public boolean mouseClicked(int mouseX, int mouseY, int button) { + boolean flag = super.mouseClicked(mouseX, mouseY, button); + if (selectedTabIndex == 1 && widgetSelector != null) { + for (Widget widget : widgetSelector.widgets) { + if (widget.isMouseOverElement(mouseX, mouseY)) { + if (widget instanceof IGuideWidget) { + if (selected != null) { + selected.setStroke(0); + } + ((IGuideWidget) widget).setStroke(0xFF7CA1FF); + selected = (IGuideWidget) widget; + } + playButtonClickSound(); + return true; + } + } + } + return flag; + } +} diff --git a/src/main/java/gregtech/common/terminal/app/guideeditor/widget/GuidePageEditorWidget.java b/src/main/java/gregtech/common/terminal/app/guideeditor/widget/GuidePageEditorWidget.java new file mode 100644 index 00000000000..31e517ea79f --- /dev/null +++ b/src/main/java/gregtech/common/terminal/app/guideeditor/widget/GuidePageEditorWidget.java @@ -0,0 +1,395 @@ +package gregtech.common.terminal.app.guideeditor.widget; + + +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import gregtech.api.gui.GuiTextures; +import gregtech.api.gui.IRenderContext; +import gregtech.api.gui.Widget; +import gregtech.api.gui.widgets.WidgetGroup; +import gregtech.common.terminal.app.guide.widget.GuidePageWidget; +import gregtech.common.terminal.app.guide.widget.IGuideWidget; +import gregtech.api.terminal.gui.widgets.CircleButtonWidget; +import gregtech.api.terminal.gui.widgets.CustomPositionSizeWidget; +import gregtech.api.terminal.os.TerminalTheme; +import gregtech.api.util.Position; +import gregtech.api.util.Size; +import gregtech.api.util.interpolate.Eases; +import gregtech.api.util.interpolate.Interpolator; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.renderer.GlStateManager; + +import java.awt.*; + +import static gregtech.api.gui.impl.ModularUIGui.*; + +public class GuidePageEditorWidget extends GuidePageWidget { + private Widget selected; + private final WidgetGroup toolButtons; + private final CustomPositionSizeWidget customPositionSizeWidget; + private GuideConfigEditor configEditor; + private String section = "default"; + + public GuidePageEditorWidget(int xPosition, int yPosition, int width, int height, int margin) { + super(xPosition, yPosition, width, height, margin); + this.setDraggable(false); + setTitle("Template"); + customPositionSizeWidget = new CustomPositionSizeWidget(0xff0000ff, 0xffff0000, 2).setOnUpdated(this::onPosSizeChanged); + toolButtons = new WidgetGroup(Position.ORIGIN, Size.ZERO); + toolButtons.setVisible(false); + toolButtons.addWidget(new CircleButtonWidget(-20, -4, 8, 1, 12) + .setColors(new Color(255, 255, 255, 0).getRGB(), + TerminalTheme.COLOR_B_2.getColor(), + TerminalTheme.COLOR_1.getColor()) + .setIcon(GuiTextures.ICON_UP) + .setHoverText("terminal.guide_editor.up") + .setClickListener(this::moveUp)); + toolButtons.addWidget(new CircleButtonWidget(0, -4, 8, 1, 12) + .setColors(new Color(255, 255, 255, 0).getRGB(), + TerminalTheme.COLOR_B_2.getColor(), + TerminalTheme.COLOR_2.getColor()) + .setIcon(GuiTextures.ICON_DOWN) + .setHoverText("terminal.guide_editor.down") + .setClickListener(this::moveDown)); + toolButtons.addWidget(new CircleButtonWidget(20, -4, 8, 1, 12) + .setColors(new Color(255, 255, 255, 0).getRGB(), + TerminalTheme.COLOR_B_2.getColor(), + TerminalTheme.COLOR_3.getColor()) + .setIcon(GuiTextures.ICON_REMOVE) + .setHoverText("terminal.guide_editor.remove") + .setClickListener(this::delete)); + addWidget(customPositionSizeWidget); + addWidget(toolButtons); + } + + public void setSection(String section) { + this.section = section; + } + + public String getSection() { + return section; + } + + private void onPosSizeChanged(Position pos, Size size) { + Widget widget = customPositionSizeWidget.getControlled(); + if (widget instanceof IGuideWidget && ((IGuideWidget) widget).isFixed()) { + JsonObject config = ((IGuideWidget) widget).getConfig(); + if (config.has("x")) { + config.addProperty("x", pos.x + scrollXOffset); + ((IGuideWidget) widget).updateValue("x"); + } + if (config.has("y")) { + config.addProperty("y", pos.y + scrollYOffset); + ((IGuideWidget) widget).updateValue("y"); + } + if (config.has("width")) { + config.addProperty("width", size.width); + ((IGuideWidget) widget).updateValue("width"); + } + if (config.has("height")) { + config.addProperty("height", size.height); + ((IGuideWidget) widget).updateValue("height"); + } + ((IGuideWidget) widget).onFixedPositionSizeChanged(pos, size); + } + toolButtons.setSelfPosition(new Position(pos.x + size.width / 2, pos.y)); + } + + public void setGuideConfigEditor(GuideConfigEditor configEditor) { + this.configEditor = configEditor; + } + + private void setToolButton(Widget widget) { + customPositionSizeWidget.setControlled(widget); + customPositionSizeWidget.setVisible(true); + customPositionSizeWidget.setActive(!(widget instanceof IGuideWidget) || ((IGuideWidget) widget).isFixed()); + toolButtons.setVisible(true); + toolButtons.setSelfPosition(new Position(widget.getSelfPosition().x + widget.getSize().width / 2, widget.getSelfPosition().y)); + } + + private void delete(ClickData clickData) { + removeWidget(selected); + selected = null; + configEditor.loadConfigurator(null); + toolButtons.setSelfPosition(new Position(-scrollYOffset, -scrollYOffset)); + customPositionSizeWidget.setControlled(null); + toolButtons.setVisible(false); + } + + private void moveUp(ClickData clickData) { + moveUp(selected); + } + + private void moveDown(ClickData clickData) { + moveDown(selected); + } + + public JsonObject getJsonConfig() { + JsonObject json = new JsonObject(); + json.addProperty("section", section); + json.addProperty("title", title.content.get(0)); + JsonArray array = new JsonArray(); + json.add("stream", array); + stream.forEach(widget -> { + if (widget instanceof IGuideWidget) { + array.add(((IGuideWidget) widget).getConfig()); + } + }); + + JsonArray array2 = new JsonArray(); + json.add("fixed", array2); + fixed.forEach(widget -> { + if (widget instanceof IGuideWidget) { + array2.add(((IGuideWidget) widget).getConfig()); + } + }); + + return json; + } + + public JsonObject addGuideWidget(IGuideWidget widget, boolean isFixed) { + int pageWidth = getPageWidth(); + int margin = getMargin(); + JsonObject widgetConfig = widget.getTemplate(isFixed); + Widget guideWidget; + if (isFixed) { + int width = widgetConfig.get("width").getAsInt(); + int height = widgetConfig.get("height").getAsInt(); + + guideWidget = widget.updateOrCreateFixedWidget( + (pageWidth - width) / 2 + 5, + this.scrollYOffset + (this.getSize().height - height) / 2, + width, + height, + widgetConfig); + fixed.add(guideWidget); + this.addWidget(guideWidget); + } else { + int y = getStreamBottom(); + guideWidget = widget.updateOrCreateStreamWidget(margin, y + 5, pageWidth - 2 * margin, widgetConfig); + stream.add(guideWidget); + this.addWidget(guideWidget); + } + return widgetConfig; + } + + + public void moveUp(Widget widget) { + int index = stream.indexOf(widget); + if (index > 0) { + Widget target = stream.get(index - 1); + if (interpolator == null) { + int offsetD = 5 + widget.getSize().height; + int offsetU = widget.getPosition().y - target.getPosition().y; + int y1 = widget.getSelfPosition().y; + int y2 = target.getSelfPosition().y; + interpolator = new Interpolator(0, 1, 10, Eases.EaseLinear, value->{ + widget.setSelfPosition(new Position(widget.getSelfPosition().x, (int) (y1 - value.floatValue() * offsetU))); + target.setSelfPosition(new Position(target.getSelfPosition().x, (int) (y2 + value.floatValue() * offsetD))); + if (widget == selected) { + setToolButton(selected); + } + widget.setVisible(widget.getSelfPosition().y < scrollYOffset + getSize().height && widget.getSelfPosition().y + widget.getSize().height > 0); + target.setVisible(target.getSelfPosition().y < scrollYOffset + getSize().height && target.getSelfPosition().y + target.getSize().height > 0); + }, value->{ + interpolator = null; + stream.remove(widget); + stream.add(index - 1, widget); + }).start(); + } + } else { + int index2 = fixed.indexOf(widget); + if (index2 >= 0 && index2 < fixed.size() - 1) { + Widget target = fixed.get(index2 + 1); + fixed.remove(widget); + fixed.add(index2 + 1, widget); + } + } + } + + public void moveDown(Widget widget) { + int index = stream.indexOf(widget); + if (index >= 0 && index < stream.size() - 1) { + Widget target = stream.get(index + 1); + if (interpolator == null) { + int offsetD = 5 + target.getSize().height; + int offsetU = target.getPosition().y - widget.getPosition().y; + int y1 = widget.getSelfPosition().y; + int y2 = target.getSelfPosition().y; + interpolator = new Interpolator(0, 1, 10, Eases.EaseLinear, value->{ + widget.setSelfPosition(new Position(widget.getSelfPosition().x, (int) (y1 + value.floatValue() * offsetD))); + target.setSelfPosition(new Position(target.getSelfPosition().x, (int) (y2 - value.floatValue() * offsetU))); + if (widget == selected) { + setToolButton(selected); + } + widget.setVisible(widget.getSelfPosition().y < getSize().height - xBarHeight && widget.getSelfPosition().y + widget.getSize().height > 0); + target.setVisible(target.getSelfPosition().y < getSize().height - xBarHeight && target.getSelfPosition().y + target.getSize().height > 0); + }, value->{ + interpolator = null; + stream.remove(widget); + stream.add(index + 1, widget); + }).start(); + } + } else { + int index2 = fixed.indexOf(widget); + if (index2 > 0) { + Widget target = fixed.get(index2 - 1); + fixed.remove(widget); + fixed.add(index2 - 1, widget); + } + } + } + + @Override + protected void setScrollYOffset(int scrollYOffset) { + if (scrollYOffset == this.scrollYOffset) return; + int offset = scrollYOffset - this.scrollYOffset; + this.scrollYOffset = scrollYOffset; + for (Widget widget : widgets) { + Position newPos = widget.addSelfPosition(0, -offset); + if (widget != toolButtons) { + widget.setVisible(newPos.y < getSize().height - xBarHeight && newPos.y + widget.getSize().height > 0); + } + } + } + + @Override + public void removeWidget(Widget widget) { + int index = stream.indexOf(widget); + if (index >= 0) { + int offset = widget.getSize().height + 5; + for (int i = stream.size() - 1; i > index; i--) { + Widget bottom = stream.get(i); + Position newPos = bottom.addSelfPosition(0, -offset); + bottom.setVisible(newPos.y < getSize().height - xBarHeight && newPos.y + widget.getSize().height > 0); + } + stream.remove(widget); + } else { + fixed.remove(widget); + } + super.removeWidget(widget); + } + + @Override + public boolean mouseClicked(int mouseX, int mouseY, int button) { + if (super.mouseClicked(mouseX, mouseY, button)) { + return true; + } + boolean flag = false; + for (int i = fixed.size() - 1; i >= 0; i--) { + Widget widget = fixed.get(i); + if (widget.isMouseOverElement(mouseX, mouseY)) { + if (widget instanceof IGuideWidget && widget != selected) { + configEditor.loadConfigurator((IGuideWidget) widget); + selected = widget; + setToolButton(selected); + } + playButtonClickSound(); + flag = true; + break; + } + } + if (!flag) { + for (Widget widget : stream) { + if (widget.isMouseOverElement(mouseX, mouseY)) { + if (widget instanceof IGuideWidget && widget != selected) { + configEditor.loadConfigurator((IGuideWidget) widget); + selected = widget; + setToolButton(selected); + } + playButtonClickSound(); + flag = true; + break; + } + } + } + return flag; + } + + @Override + protected boolean hookDrawInBackground(int mouseX, int mouseY, float partialTicks, IRenderContext context) { + int x = getPosition().x; + int y = getPosition().y; + int width = getSize().width; + int height = getSize().height; + if(title.isVisible()) { + title.drawInBackground(mouseX, mouseY, partialTicks, context); + } + for (Widget widget : stream) { + if (widget.isVisible()) { + widget.drawInBackground(mouseX, mouseY, partialTicks, context); + } + } + + boolean flag = false; + for (Widget widget : fixed) { + if (widget.isVisible()) { + widget.drawInBackground(mouseX, mouseY, partialTicks, context); + if (widget.isMouseOverElement(mouseX, mouseY)) { + if (widget != selected) { + Position pos = widget.getPosition(); + Size s = widget.getSize(); + if (stream.contains(widget)) { + drawSolidRect(x, pos.y, width - yBarWidth, s.height, 0x6f000000); + + } else { + drawSolidRect(pos.x, pos.y, s.width, s.height, 0x6f000000); + } + } + flag = true; + } + } + } + if (!flag) { + for (Widget widget : stream) { + if (widget.isVisible() && widget != selected && widget.isMouseOverElement(mouseX, mouseY)) { + Position pos = widget.getPosition(); + Size s = widget.getSize(); + if (stream.contains(widget)) { + drawSolidRect(x, pos.y, width - yBarWidth, s.height, 0x6f000000); + } else { + drawSolidRect(pos.x, pos.y, s.width, s.height, 0x6f000000); + } + } + } + } + + if (selected != null) { + FontRenderer fontRenderer = Minecraft.getMinecraft().fontRenderer; + int index = fixed.indexOf(selected); + String layer = "L: " + (index >= 0 ? index : stream.indexOf(selected)); + fontRenderer.drawString(layer, + selected.getPosition().x + (selected.getSize().width - fontRenderer.getStringWidth(layer)) / 2, + selected.getPosition().y - 20, + 0xffff0000, true); + } + if(toolButtons.isVisible()) { + customPositionSizeWidget.drawInBackground(mouseX, mouseY, partialTicks, context); + toolButtons.drawInBackground(mouseX, mouseY, partialTicks, context); + } + GlStateManager.color(rColorForOverlay, gColorForOverlay, bColorForOverlay, 1.0F); + return true; + } + + @Override + public boolean mouseDragged(int mouseX, int mouseY, int button, long timeDragged) { + if (super.mouseDragged(mouseX, mouseY, button, timeDragged) && toolButtons.isVisible()) { + setToolButton(selected); + return true; + } + return false; + } + + @Override + public void clearAllWidgets() { + super.clearAllWidgets(); + selected = null; + configEditor.loadConfigurator(null); + toolButtons.setSelfPosition(new Position(-scrollYOffset, -scrollYOffset)); + customPositionSizeWidget.setControlled(null); + toolButtons.setVisible(false); + addWidget(customPositionSizeWidget); + addWidget(toolButtons); + } +} diff --git a/src/main/java/gregtech/common/terminal/app/guideeditor/widget/configurator/BooleanConfigurator.java b/src/main/java/gregtech/common/terminal/app/guideeditor/widget/configurator/BooleanConfigurator.java new file mode 100644 index 00000000000..50b1d7cf2b8 --- /dev/null +++ b/src/main/java/gregtech/common/terminal/app/guideeditor/widget/configurator/BooleanConfigurator.java @@ -0,0 +1,35 @@ +package gregtech.common.terminal.app.guideeditor.widget.configurator; + +import com.google.gson.JsonObject; +import gregtech.api.gui.resources.ColorRectTexture; +import gregtech.api.terminal.gui.widgets.DraggableScrollableWidgetGroup; +import gregtech.api.terminal.gui.widgets.RectButtonWidget; +import gregtech.api.terminal.os.TerminalTheme; + +import java.awt.*; + +public class BooleanConfigurator extends ConfiguratorWidget{ + + public BooleanConfigurator(DraggableScrollableWidgetGroup group, JsonObject config, String name) { + super(group, config, name); + } + + public BooleanConfigurator(DraggableScrollableWidgetGroup group, JsonObject config, String name, boolean defaultValue) { + super(group, config, name, defaultValue); + } + + protected void init(){ + this.addWidget(new RectButtonWidget(0, 15, 10, 10, 2) + .setToggleButton(new ColorRectTexture(new Color(198, 198, 198).getRGB()), (c, p)->updateValue(p)) + .setValueSupplier(true, ()->{ + if(config.get(name).isJsonNull()) { + return defaultValue; + } + return config.get(name).getAsBoolean(); + }) + .setColors(TerminalTheme.COLOR_B_1.getColor(), + TerminalTheme.COLOR_1.getColor(), + new Color(255, 255, 255, 0).getRGB()) + .setIcon(new ColorRectTexture(new Color(0, 0, 0, 74).getRGB()))); + } +} diff --git a/src/main/java/gregtech/common/terminal/app/guideeditor/widget/configurator/ColorConfigurator.java b/src/main/java/gregtech/common/terminal/app/guideeditor/widget/configurator/ColorConfigurator.java new file mode 100644 index 00000000000..fa36c712544 --- /dev/null +++ b/src/main/java/gregtech/common/terminal/app/guideeditor/widget/configurator/ColorConfigurator.java @@ -0,0 +1,27 @@ +package gregtech.common.terminal.app.guideeditor.widget.configurator; + +import com.google.gson.JsonObject; +import gregtech.api.terminal.gui.widgets.ColorWidget; +import gregtech.api.terminal.gui.widgets.DraggableScrollableWidgetGroup; + +public class ColorConfigurator extends ConfiguratorWidget{ + + public ColorConfigurator(DraggableScrollableWidgetGroup group, JsonObject config, String name, int defaultValue) { + super(group, config, name, defaultValue); + } + + public ColorConfigurator(DraggableScrollableWidgetGroup group, JsonObject config, String name) { + super(group, config, name); + } + + protected void init(){ + this.addWidget(new ColorWidget(0, 15, 85, 10).setColorSupplier(()->{ + if(config.get(name).isJsonNull()) { + return defaultValue; + } + return config.get(name).getAsInt(); + },true).setOnColorChanged(this::updateValue)); + } + + +} diff --git a/src/main/java/gregtech/common/terminal/app/guideeditor/widget/configurator/ConfiguratorWidget.java b/src/main/java/gregtech/common/terminal/app/guideeditor/widget/configurator/ConfiguratorWidget.java new file mode 100644 index 00000000000..706efc8f659 --- /dev/null +++ b/src/main/java/gregtech/common/terminal/app/guideeditor/widget/configurator/ConfiguratorWidget.java @@ -0,0 +1,126 @@ +package gregtech.common.terminal.app.guideeditor.widget.configurator; + +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import gregtech.api.gui.IRenderContext; +import gregtech.api.gui.widgets.LabelWidget; +import gregtech.api.gui.widgets.WidgetGroup; +import gregtech.api.terminal.gui.widgets.DraggableScrollableWidgetGroup; +import gregtech.api.util.Position; +import net.minecraft.client.Minecraft; +import net.minecraft.client.resources.I18n; +import net.minecraft.item.ItemStack; + +import java.util.Collections; +import java.util.function.Consumer; + +public class ConfiguratorWidget extends WidgetGroup { + protected T defaultValue; + protected String name; + protected boolean canDefault; + protected boolean isDefault; + protected JsonObject config; + protected DraggableScrollableWidgetGroup group; + private int nameWidth; + private Consumer onUpdated; + + public ConfiguratorWidget(DraggableScrollableWidgetGroup group, JsonObject config, String name) { + this(group, config, name, null); + } + + public ConfiguratorWidget(DraggableScrollableWidgetGroup group, JsonObject config, String name, T defaultValue) { + super(new Position(5, group.getWidgetBottomHeight() + 5)); + this.group = group; + this.defaultValue = defaultValue; + this.name = name; + this.canDefault = defaultValue != null; + this.config = config; + if (config.get(name) == null) { + config.addProperty(name, (String)null); + } + if (canDefault && config.get(name).isJsonNull()) { + isDefault = true; + } + this.addWidget(new LabelWidget(0, 4, name, -1).setShadow(true)); + if (isClientSide()) { + nameWidth = Minecraft.getMinecraft().fontRenderer.getStringWidth(name); + } + init(); + } + + protected void init() { + + } + + protected void updateValue(T value) { + if (canDefault && isDefault) return; + config.add(name, new Gson().toJsonTree(value)); + update(); + } + + public ConfiguratorWidget setOnUpdated(Consumer onUpdated) { + this.onUpdated = onUpdated; + return this; + } + + protected void update(){ + if (onUpdated != null) { + onUpdated.accept(name); + } + } + + @Override + public void drawInForeground(int mouseX, int mouseY) { + int x = getPosition().x; + int y = getPosition().y; + if (canDefault && isMouseOver(x + nameWidth + 4, y + 6, 5, 5, mouseX, mouseY)) { + drawHoveringText(ItemStack.EMPTY, Collections.singletonList(I18n.format("terminal.guide_editor.default")), 100, mouseX, mouseY); + } + if (!isDefault) { + super.drawInForeground(mouseX, mouseY); + } + } + + @Override + public void drawInBackground(int mouseX, int mouseY, float partialTicks, IRenderContext context) { + int x = getPosition().x; + int y = getPosition().y; + drawSolidRect(x, y, this.getSize().width, 1, -1); + if (canDefault) { + drawBorder(x + nameWidth + 4, y + 6, 5, 5, -1, 1); + if (isDefault) { + drawSolidRect(x + nameWidth + 5, y + 7, 3, 3, -1); + } + } + if (canDefault && isDefault) { + super.drawInBackground(-100, -100, partialTicks, context); + drawSolidRect(x, y + 15, this.getSize().width, this.getSize().height - 15, 0x99000000); + } else { + super.drawInBackground(mouseX, mouseY, partialTicks, context); + } + + } + + @Override + public boolean mouseClicked(int mouseX, int mouseY, int button) { + int x = getPosition().x; + int y = getPosition().y; + if (!isDefault && super.mouseClicked(mouseX, mouseY, button)) { + return true; + } + if (canDefault && isMouseOver(x + nameWidth + 4, y + 6, 5, 5, mouseX, mouseY)) { + isDefault = !isDefault; + if (isDefault) { + config.addProperty(name, (String) null); + update(); + onDefault(); + } + playButtonClickSound(); + return true; + } + return false; + } + + protected void onDefault() { + } +} diff --git a/src/main/java/gregtech/common/terminal/app/guideeditor/widget/configurator/FluidStackConfigurator.java b/src/main/java/gregtech/common/terminal/app/guideeditor/widget/configurator/FluidStackConfigurator.java new file mode 100644 index 00000000000..9ce264b4fe0 --- /dev/null +++ b/src/main/java/gregtech/common/terminal/app/guideeditor/widget/configurator/FluidStackConfigurator.java @@ -0,0 +1,99 @@ +package gregtech.common.terminal.app.guideeditor.widget.configurator; + +import com.google.gson.Gson; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import gregtech.api.gui.GuiTextures; +import gregtech.api.gui.resources.TextTexture; +import gregtech.api.gui.widgets.*; +import gregtech.api.terminal.gui.widgets.DraggableScrollableWidgetGroup; +import gregtech.api.terminal.gui.widgets.RectButtonWidget; +import gregtech.common.terminal.app.guide.widget.TankListWidget; +import gregtech.api.terminal.os.TerminalTheme; + +import java.awt.*; +import java.util.ArrayList; +import java.util.List; + +public class FluidStackConfigurator extends ConfiguratorWidget>{ + DraggableScrollableWidgetGroup container; + List tanks; + + public FluidStackConfigurator(DraggableScrollableWidgetGroup group, JsonObject config, String name) { + super(group, config, name); + } + + protected void init() { + container = new DraggableScrollableWidgetGroup(0, 27,116, 100); + this.addWidget(container); + this.addWidget(new RectButtonWidget(0, 15, 116, 10, 1) + .setIcon(new TextTexture("terminal.guide_editor.add_slot", -1)) + .setClickListener(cd->{ + addSlot(container, new TankListWidget.FluidStackInfo(null, 0)); + updateValue(); + }) + .setColors(TerminalTheme.COLOR_B_1.getColor(), + TerminalTheme.COLOR_1.getColor(), + new Color(255, 255, 255, 0).getRGB())); + tanks = new ArrayList<>(); + if (!config.get(name).isJsonNull()) { + Gson gson = new Gson(); + for (JsonElement o : config.get(name).getAsJsonArray()) { + addSlot(container, gson.fromJson(o, TankListWidget.FluidStackInfo.class)); + } + } + } + + private void addSlot(DraggableScrollableWidgetGroup container, TankListWidget.FluidStackInfo fluidStackInfo) { + WidgetGroup group = new WidgetGroup(0, tanks.size() * 20, 116, 20); + tanks.add(fluidStackInfo); + group.addWidget(new PhantomFluidWidget(1, 1, 18, 18, null, null) + .setBackgroundTexture(TerminalTheme.COLOR_B_2) + .setFluidStackSupplier(fluidStackInfo::getInstance, true) + .setFluidStackUpdater(fluidStack->{ + fluidStackInfo.update(fluidStack); + updateValue(); + }, true)); + group.addWidget(new RectButtonWidget(20, 0, 20, 20) + .setColors(TerminalTheme.COLOR_B_1.getColor(), + TerminalTheme.COLOR_1.getColor(), + new Color(255, 255, 255, 0).getRGB()) + .setClickListener(data -> { + fluidStackInfo.amount = Math.max(0, fluidStackInfo.amount - (data.isShiftClick ? data.isCtrlClick ? 1000 : 10 : data.isCtrlClick? 100: 1)); + updateValue(); + }) + .setHoverText("Shift -10|Ctrl -100|Shift+Ctrl -1000") + .setIcon(new TextTexture("-1", -1))); + group.addWidget(new RectButtonWidget(76, 0, 20, 20) + .setColors(TerminalTheme.COLOR_B_1.getColor(), + TerminalTheme.COLOR_1.getColor(), + new Color(255, 255, 255, 0).getRGB()) + .setClickListener(data -> { + fluidStackInfo.amount = Math.max(0, fluidStackInfo.amount + (data.isShiftClick ? data.isCtrlClick ? 1000 : 10 : data.isCtrlClick? 100: 1)); + updateValue(); + }) + .setHoverText("Shift +10|Ctrl +100|Shift+Ctrl +1000") + .setIcon(new TextTexture("+1", -1))); + group.addWidget(new ImageWidget(40, 0, 36, 20, TerminalTheme.COLOR_B_2)); + group.addWidget(new SimpleTextWidget(58, 10, "", 0xFFFFFF, () -> Integer.toString(fluidStackInfo.amount), true)); + group.addWidget(new RectButtonWidget(96, 0, 20, 20) + .setColors(TerminalTheme.COLOR_B_1.getColor(), + TerminalTheme.COLOR_1.getColor(), + new Color(255, 255, 255, 0).getRGB()) + .setClickListener(data -> { + container.waitToRemoved(group); + tanks.remove(fluidStackInfo); + int index = container.widgets.indexOf(group); + for (int i = container.widgets.size() - 1; i > index; i--) { + container.widgets.get(i).addSelfPosition(0, -20); + } + updateValue(); + }) + .setIcon(GuiTextures.ICON_REMOVE)); + container.addWidget(group); + } + + private void updateValue() { + updateValue(tanks); + } +} diff --git a/src/main/java/gregtech/common/terminal/app/guideeditor/widget/configurator/ItemStackConfigurator.java b/src/main/java/gregtech/common/terminal/app/guideeditor/widget/configurator/ItemStackConfigurator.java new file mode 100644 index 00000000000..69c773c1507 --- /dev/null +++ b/src/main/java/gregtech/common/terminal/app/guideeditor/widget/configurator/ItemStackConfigurator.java @@ -0,0 +1,101 @@ +package gregtech.common.terminal.app.guideeditor.widget.configurator; + +import com.google.gson.Gson; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import gregtech.api.gui.GuiTextures; +import gregtech.api.gui.resources.TextTexture; +import gregtech.api.gui.widgets.ImageWidget; +import gregtech.api.gui.widgets.PhantomSlotWidget; +import gregtech.api.gui.widgets.SimpleTextWidget; +import gregtech.api.gui.widgets.WidgetGroup; +import gregtech.api.terminal.gui.widgets.DraggableScrollableWidgetGroup; +import gregtech.api.terminal.gui.widgets.RectButtonWidget; +import gregtech.common.terminal.app.guide.widget.SlotListWidget; +import gregtech.api.terminal.os.TerminalTheme; +import gregtech.common.inventory.handlers.SingleItemStackHandler; +import net.minecraftforge.items.IItemHandlerModifiable; + +import java.awt.*; +import java.util.ArrayList; +import java.util.List; + +public class ItemStackConfigurator extends ConfiguratorWidget>{ + DraggableScrollableWidgetGroup container; + List slots; + + public ItemStackConfigurator(DraggableScrollableWidgetGroup group, JsonObject config, String name) { + super(group, config, name); + } + + protected void init() { + container = new DraggableScrollableWidgetGroup(0, 27,116, 100); + this.addWidget(container); + this.addWidget(new RectButtonWidget(0, 15, 116, 10, 1) + .setIcon(new TextTexture("terminal.guide_editor.add_slot", -1)) + .setClickListener(cd->{ + addSlot(container, new SlotListWidget.ItemStackInfo("minecraft:air", 0, 0)); + updateValue(); + }) + .setColors(TerminalTheme.COLOR_B_1.getColor(), + TerminalTheme.COLOR_1.getColor(), + new Color(255, 255, 255, 0).getRGB())); + slots = new ArrayList<>(); + if (!config.get(name).isJsonNull()) { + Gson gson = new Gson(); + for (JsonElement o : config.get(name).getAsJsonArray()) { + addSlot(container, gson.fromJson(o, SlotListWidget.ItemStackInfo.class)); + } + } + } + + private void addSlot(DraggableScrollableWidgetGroup container, SlotListWidget.ItemStackInfo itemStackInfo) { + WidgetGroup group = new WidgetGroup(0,slots.size() * 20, 116, 20); + slots.add(itemStackInfo); + IItemHandlerModifiable handler = new SingleItemStackHandler(1); + handler.setStackInSlot(0, itemStackInfo.getInstance()); + group.addWidget(new PhantomSlotWidget(handler, 0, 1, 1).setBackgroundTexture(TerminalTheme.COLOR_B_2).setChangeListener(()->{ + itemStackInfo.update(handler.getStackInSlot(0)); + updateValue(); + })); + group.addWidget(new RectButtonWidget(20, 0, 20, 20) + .setColors(TerminalTheme.COLOR_B_1.getColor(), + TerminalTheme.COLOR_1.getColor(), + new Color(255, 255, 255, 0).getRGB()) + .setClickListener(data -> { + itemStackInfo.count = Math.max(0, itemStackInfo.count - (data.isShiftClick ? 10 : 1)); + updateValue(); + }) + .setIcon(new TextTexture("-1", -1))); + group.addWidget(new RectButtonWidget(76, 0, 20, 20) + .setColors(TerminalTheme.COLOR_B_1.getColor(), + TerminalTheme.COLOR_1.getColor(), + new Color(255, 255, 255, 0).getRGB()) + .setClickListener(data -> { + itemStackInfo.count = Math.max(0, itemStackInfo.count + (data.isShiftClick ? 10 : 1)); + updateValue(); + }) + .setIcon(new TextTexture("+1", -1))); + group.addWidget(new ImageWidget(40, 0, 36, 20, TerminalTheme.COLOR_B_2)); + group.addWidget(new SimpleTextWidget(58, 10, "", 0xFFFFFF, () -> Integer.toString(itemStackInfo.count), true)); + group.addWidget(new RectButtonWidget(96, 0, 20, 20) + .setColors(TerminalTheme.COLOR_B_1.getColor(), + TerminalTheme.COLOR_1.getColor(), + new Color(255, 255, 255, 0).getRGB()) + .setClickListener(data -> { + container.waitToRemoved(group); + slots.remove(itemStackInfo); + int index = container.widgets.indexOf(group); + for (int i = container.widgets.size() - 1; i > index; i--) { + container.widgets.get(i).addSelfPosition(0, -20); + } + updateValue(); + }) + .setIcon(GuiTextures.ICON_REMOVE)); + container.addWidget(group); + } + + private void updateValue() { + updateValue(slots); + } +} diff --git a/src/main/java/gregtech/common/terminal/app/guideeditor/widget/configurator/NumberConfigurator.java b/src/main/java/gregtech/common/terminal/app/guideeditor/widget/configurator/NumberConfigurator.java new file mode 100644 index 00000000000..1d7fb271d3a --- /dev/null +++ b/src/main/java/gregtech/common/terminal/app/guideeditor/widget/configurator/NumberConfigurator.java @@ -0,0 +1,70 @@ +package gregtech.common.terminal.app.guideeditor.widget.configurator; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import gregtech.api.gui.resources.TextTexture; +import gregtech.api.gui.widgets.ImageWidget; +import gregtech.api.gui.widgets.SimpleTextWidget; +import gregtech.api.terminal.gui.widgets.DraggableScrollableWidgetGroup; +import gregtech.api.terminal.gui.widgets.RectButtonWidget; +import gregtech.api.terminal.os.TerminalTheme; + +import java.awt.*; + +public class NumberConfigurator extends ConfiguratorWidget{ + + public NumberConfigurator(DraggableScrollableWidgetGroup group, JsonObject config, String name) { + super(group, config, name); + } + + public NumberConfigurator(DraggableScrollableWidgetGroup group, JsonObject config, String name, int defaultValue) { + super(group, config, name, defaultValue); + } + + protected void init(){ + int y = 15; + this.addWidget(new RectButtonWidget(0, y, 20, 20) + .setColors(TerminalTheme.COLOR_B_1.getColor(), + TerminalTheme.COLOR_1.getColor(), + new Color(255, 255, 255, 0).getRGB()) + .setClickListener(data -> adjustTransferRate(data.isShiftClick ? -100 : -10)) + .setIcon(new TextTexture("-10", -1))); + this.addWidget(new RectButtonWidget(96, y, 20, 20) + .setColors(TerminalTheme.COLOR_B_1.getColor(), + TerminalTheme.COLOR_1.getColor(), + new Color(255, 255, 255, 0).getRGB()) + .setClickListener(data -> adjustTransferRate(data.isShiftClick ? +100 : +10)) + .setIcon(new TextTexture("+10", -1))); + this.addWidget(new RectButtonWidget(20, y, 20, 20) + .setColors(TerminalTheme.COLOR_B_1.getColor(), + TerminalTheme.COLOR_1.getColor(), + new Color(255, 255, 255, 0).getRGB()) + .setClickListener(data -> adjustTransferRate(data.isShiftClick ? -5 : -1)) + .setIcon(new TextTexture("-1", -1))); + this.addWidget(new RectButtonWidget(76, y, 20, 20) + .setColors(TerminalTheme.COLOR_B_1.getColor(), + TerminalTheme.COLOR_1.getColor(), + new Color(255, 255, 255, 0).getRGB()) + .setClickListener(data -> adjustTransferRate(data.isShiftClick ? +5 : +1)) + .setIcon(new TextTexture("+1", -1))); + this.addWidget(new ImageWidget(40, y, 36, 20, TerminalTheme.COLOR_B_2)); + this.addWidget(new SimpleTextWidget(58, 25, "", 0xFFFFFF, () -> { + JsonElement element = config.get(name); + if (element.isJsonNull()) { + return Integer.toString(defaultValue); + } + return element.getAsString(); + }, true)); + } + + private void adjustTransferRate(int added) { + JsonElement element = config.get(name); + int num = 0; + if (!element.isJsonNull()) { + num = element.getAsInt(); + } else { + num = defaultValue; + } + updateValue(num + added); + } +} diff --git a/src/main/java/gregtech/common/terminal/app/guideeditor/widget/configurator/SelectorConfigurator.java b/src/main/java/gregtech/common/terminal/app/guideeditor/widget/configurator/SelectorConfigurator.java new file mode 100644 index 00000000000..5b17ebd417f --- /dev/null +++ b/src/main/java/gregtech/common/terminal/app/guideeditor/widget/configurator/SelectorConfigurator.java @@ -0,0 +1,36 @@ +package gregtech.common.terminal.app.guideeditor.widget.configurator; + +import com.google.gson.JsonObject; +import gregtech.api.terminal.gui.widgets.DraggableScrollableWidgetGroup; +import gregtech.api.terminal.gui.widgets.SelectorWidget; +import gregtech.api.terminal.os.TerminalTheme; + +import java.awt.*; +import java.util.List; + +public class SelectorConfigurator extends ConfiguratorWidget{ + public SelectorConfigurator(DraggableScrollableWidgetGroup group, JsonObject config, String name, List candidates, String defaultValue) { + super(group, config, name, defaultValue); + init(candidates); + } + + public SelectorConfigurator(DraggableScrollableWidgetGroup group, JsonObject config, String name, List candidates) { + super(group, config, name); + init(candidates); + } + + protected void init(List candidates){ + this.addWidget(new SelectorWidget(0, 15, 80, 20, candidates, -1, ()->{ + if(config.get(name).isJsonNull()) { + return defaultValue; + } + return config.get(name).getAsString(); + }, true) + .setColors(TerminalTheme.COLOR_B_1.getColor(), + TerminalTheme.COLOR_1.getColor(), + new Color(255, 255, 255, 0).getRGB()) + .setIsUp(true) + .setOnChanged(this::updateValue)); + } + +} diff --git a/src/main/java/gregtech/common/terminal/app/guideeditor/widget/configurator/StringConfigurator.java b/src/main/java/gregtech/common/terminal/app/guideeditor/widget/configurator/StringConfigurator.java new file mode 100644 index 00000000000..e0ca118aa56 --- /dev/null +++ b/src/main/java/gregtech/common/terminal/app/guideeditor/widget/configurator/StringConfigurator.java @@ -0,0 +1,44 @@ +package gregtech.common.terminal.app.guideeditor.widget.configurator; + +import com.google.gson.JsonObject; +import gregtech.api.gui.resources.TextTexture; +import gregtech.api.gui.widgets.TextFieldWidget; +import gregtech.api.terminal.gui.widgets.DraggableScrollableWidgetGroup; +import gregtech.api.terminal.gui.widgets.RectButtonWidget; +import gregtech.api.terminal.os.TerminalTheme; + +import java.awt.*; + +public class StringConfigurator extends ConfiguratorWidget{ + private TextFieldWidget textFieldWidget; + + public StringConfigurator(DraggableScrollableWidgetGroup group, JsonObject config, String name) { + super(group, config, name); + } + + public StringConfigurator(DraggableScrollableWidgetGroup group, JsonObject config, String name, String defaultValue) { + super(group, config, name, defaultValue); + } + + protected void init() { + this.addWidget(new RectButtonWidget(76, 15, 40, 20) + .setColors(TerminalTheme.COLOR_B_1.getColor(), + TerminalTheme.COLOR_1.getColor(), + new Color(255, 255, 255, 0).getRGB()) + .setClickListener(data -> updateString()) + .setIcon(new TextTexture("terminal.guide_editor.update", -1))); + textFieldWidget = new TextFieldWidget(0, 15, 76, 20, TerminalTheme.COLOR_B_2, null, null) + .setMaxStringLength(Integer.MAX_VALUE) + .setValidator(s->true); + this.addWidget(textFieldWidget); + } + + private void updateString() { + updateValue(textFieldWidget.getCurrentString()); + } + + @Override + protected void onDefault() { + textFieldWidget.setCurrentString(defaultValue); + } +} diff --git a/src/main/java/gregtech/common/terminal/app/guideeditor/widget/configurator/TextListConfigurator.java b/src/main/java/gregtech/common/terminal/app/guideeditor/widget/configurator/TextListConfigurator.java new file mode 100644 index 00000000000..1d41381a464 --- /dev/null +++ b/src/main/java/gregtech/common/terminal/app/guideeditor/widget/configurator/TextListConfigurator.java @@ -0,0 +1,44 @@ +package gregtech.common.terminal.app.guideeditor.widget.configurator; + +import com.google.gson.*; +import gregtech.api.gui.resources.ColorRectTexture; +import gregtech.api.terminal.gui.widgets.DraggableScrollableWidgetGroup; +import gregtech.api.terminal.gui.widgets.TextEditorWidget; + +import java.util.Collections; +import java.util.List; + +public class TextListConfigurator extends ConfiguratorWidget>{ + private TextEditorWidget editor; + + public TextListConfigurator(DraggableScrollableWidgetGroup group, int height, JsonObject config, String name) { + super(group, config, name); + init(height); + } + + public TextListConfigurator(DraggableScrollableWidgetGroup group, int height, JsonObject config, String name, String defaultValue) { + super(group, config, name, Collections.singletonList(defaultValue)); + init(height); + } + + protected void init(int height) { + JsonElement element = config.get(name); + String initValue = ""; + if (!element.isJsonNull()) { + List init = new Gson().fromJson(element, List.class); + initValue = String.join("\n", init); + + } + editor = new TextEditorWidget(0, 15, 116, height, this::updateTextList, true).setContent(initValue).setBackground(new ColorRectTexture(0xA3FFFFFF)); + this.addWidget(editor); + } + + private void updateTextList(String saved) { + updateValue(Collections.singletonList(saved)); + } + + @Override + protected void onDefault() { + editor.setContent(defaultValue.get(0)); + } +} diff --git a/src/main/java/gregtech/common/terminal/app/recipechart/RecipeChartApp.java b/src/main/java/gregtech/common/terminal/app/recipechart/RecipeChartApp.java new file mode 100644 index 00000000000..b633c0a8dc9 --- /dev/null +++ b/src/main/java/gregtech/common/terminal/app/recipechart/RecipeChartApp.java @@ -0,0 +1,173 @@ +package gregtech.common.terminal.app.recipechart; + +import gregtech.api.gui.GuiTextures; +import gregtech.api.gui.Widget; +import gregtech.api.gui.impl.ModularUIContainer; +import gregtech.api.gui.ingredient.IRecipeTransferHandlerWidget; +import gregtech.api.gui.resources.TextTexture; +import gregtech.api.gui.resources.TextureArea; +import gregtech.api.gui.widgets.TabGroup; +import gregtech.api.gui.widgets.tab.IGuiTextureTabInfo; +import gregtech.api.terminal.app.AbstractApplication; +import gregtech.api.terminal.gui.CustomTabListRenderer; +import gregtech.api.terminal.os.TerminalDialogWidget; +import gregtech.api.terminal.os.TerminalOSWidget; +import gregtech.api.terminal.os.TerminalTheme; +import gregtech.api.terminal.os.menu.IMenuComponent; +import gregtech.common.terminal.app.recipechart.widget.RGContainer; +import gregtech.common.terminal.app.recipechart.widget.RGNode; +import gregtech.common.terminal.component.ClickComponent; +import mezz.jei.api.gui.IRecipeLayout; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.nbt.CompressedStreamTools; +import net.minecraft.nbt.NBTBase; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraftforge.common.util.Constants; + +import java.io.File; +import java.io.IOException; +import java.util.Arrays; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +public class RecipeChartApp extends AbstractApplication implements IRecipeTransferHandlerWidget { + public static final TextureArea ICON = TextureArea.fullImage("textures/gui/terminal/recipe_graph/icon.png"); + + private TabGroup tabGroup; + private Map containers; + + public RecipeChartApp() { + super("recipe_chart", ICON); + } + + @Override + public AbstractApplication createApp(TerminalOSWidget os, boolean isClient, NBTTagCompound nbt) { + RecipeChartApp app = new RecipeChartApp(); + if (isClient) { + app.setOs(os); + app.containers = new LinkedHashMap<>(); + app.tabGroup = new TabGroup<>(0, 10, new CustomTabListRenderer(TerminalTheme.COLOR_F_2, TerminalTheme.COLOR_B_3, 60, 10)); + app.addWidget(app.tabGroup); + if (nbt.isEmpty()) { + app.addTab("default"); + } else { + for (NBTBase l : nbt.getTagList("list", Constants.NBT.TAG_COMPOUND)) { + NBTTagCompound container = (NBTTagCompound) l; + app.addTab(container.getString("name")).loadFromNBT((NBTTagCompound) container.getTag("data")); + } + } + } + return app; + } + + private RGContainer addTab(String name) { + name = name.isEmpty()? "default" : name; + RGContainer container = new RGContainer(0, 0, 333, 222, getOs()); + container.setBackground(TerminalTheme.COLOR_B_3); + tabGroup.addTab(new IGuiTextureTabInfo(new TextTexture(name, -1), name), container); + containers.put(container, name); + return container; + } + + @Override + public List getMenuComponents() { + ClickComponent newPage = new ClickComponent().setIcon(GuiTextures.ICON_NEW_PAGE).setHoverText("terminal.component.new_page").setClickConsumer(cd->{ + if (tabGroup == null) return; + if (tabGroup.getAllTag().size() < 5) { + TerminalDialogWidget.showTextFieldDialog(getOs(), "terminal.component.page_name", s -> true, s -> { + if (s != null) { + addTab(s); + } + }).setClientSide().open(); + } else { + TerminalDialogWidget.showInfoDialog(getOs(), "terminal.component.warning", "terminal.recipe_chart.limit").setClientSide().open(); + } + }); + ClickComponent deletePage = new ClickComponent().setIcon(GuiTextures.ICON_REMOVE).setHoverText("terminal.recipe_chart.delete").setClickConsumer(cd->{ + if (tabGroup == null) return; + if (tabGroup.getAllTag().size() > 1) { + TerminalDialogWidget.showConfirmDialog(getOs(), "terminal.recipe_chart.delete", "terminal.component.confirm", r->{ + if (r) { + containers.remove(tabGroup.getCurrentTag()); + tabGroup.removeTab(tabGroup.getAllTag().indexOf(tabGroup.getCurrentTag())); + } + }).setClientSide().open(); + } else { + TerminalDialogWidget.showInfoDialog(getOs(), "terminal.component.warning", "terminal.recipe_chart.limit").setClientSide().open(); + } + }); + ClickComponent addSlot = new ClickComponent().setIcon(GuiTextures.ICON_ADD).setHoverText("terminal.recipe_chart.add_slot").setClickConsumer(cd->{ + if (tabGroup == null) return; + if (tabGroup.getCurrentTag() != null) { + tabGroup.getCurrentTag().addNode(50, 100); + } + }); + ClickComponent importPage = new ClickComponent().setIcon(GuiTextures.ICON_LOAD).setHoverText("terminal.component.load_file").setClickConsumer(cd->{ + if (tabGroup == null) return; + if (tabGroup.getAllTag().size() < 5) { + File file = new File("terminal\\recipe_chart"); + TerminalDialogWidget.showFileDialog(getOs(), "terminal.component.load_file", file, true, result->{ + if (result != null && result.isFile()) { + try { + NBTTagCompound nbt = CompressedStreamTools.read(result); + addTab(result.getName()).loadFromNBT(nbt); + } catch (IOException e) { + TerminalDialogWidget.showInfoDialog(getOs(), "terminal.component.error", "terminal.component.load_file.error").setClientSide().open(); + } + } + }).setClientSide().open(); + } else { + TerminalDialogWidget.showInfoDialog(getOs(), "terminal.component.warning", "terminal.recipe_chart.limit").setClientSide().open(); + } + }); + ClickComponent exportPage = new ClickComponent().setIcon(GuiTextures.ICON_SAVE).setHoverText("terminal.component.save_file").setClickConsumer(cd->{ + if (tabGroup == null) return; + if (tabGroup.getCurrentTag() != null) { + File file = new File("terminal\\recipe_chart"); + TerminalDialogWidget.showFileDialog(getOs(), "terminal.component.save_file", file, false, result->{ + if (result != null) { + try { + CompressedStreamTools.safeWrite(tabGroup.getCurrentTag().saveAsNBT(), result); + } catch (IOException e) { + TerminalDialogWidget.showInfoDialog(getOs(), "terminal.component.error", "terminal.component.save_file.error").setClientSide().open(); + } + } + }).setClientSide().open(); + } + }); + return Arrays.asList(newPage, deletePage, addSlot, importPage, exportPage); + } + + @Override + public NBTTagCompound closeApp(boolean isClient, NBTTagCompound nbt) { //synced data to server side. + if (isClient) { + NBTTagList list = new NBTTagList(); + for (Map.Entry entry : containers.entrySet()) { + NBTTagCompound container = new NBTTagCompound(); + container.setString("name", entry.getValue()); + container.setTag("data", entry.getKey().saveAsNBT()); + list.appendTag(container); + } + nbt.setTag("list", list); + return nbt; + } + return super.closeApp(false, nbt); + } + + @Override + public boolean isClientSideApp() { + return true; + } + + @Override + public String transferRecipe(ModularUIContainer container, IRecipeLayout recipeLayout, EntityPlayer player, boolean maxTransfer, boolean doTransfer) { + for (Widget widget : getContainedWidgets(false)) { + if (widget instanceof RGNode && ((RGNode) widget).transferRecipe(container, recipeLayout, player, maxTransfer, doTransfer)) { + return null; + } + } + return "please select a node."; + } +} diff --git a/src/main/java/gregtech/common/terminal/app/recipechart/widget/PhantomWidget.java b/src/main/java/gregtech/common/terminal/app/recipechart/widget/PhantomWidget.java new file mode 100644 index 00000000000..3c82b81b3da --- /dev/null +++ b/src/main/java/gregtech/common/terminal/app/recipechart/widget/PhantomWidget.java @@ -0,0 +1,87 @@ +package gregtech.common.terminal.app.recipechart.widget; + +import gregtech.api.gui.Widget; +import gregtech.api.gui.ingredient.IGhostIngredientTarget; +import gregtech.api.gui.widgets.PhantomFluidWidget; +import gregtech.api.gui.widgets.PhantomSlotWidget; +import gregtech.api.gui.widgets.WidgetGroup; +import gregtech.api.terminal.os.TerminalTheme; +import gregtech.common.inventory.handlers.SingleItemStackHandler; +import mezz.jei.api.gui.IGhostIngredientHandler; +import net.minecraft.item.ItemStack; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.items.IItemHandlerModifiable; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.function.Consumer; + +public class PhantomWidget extends WidgetGroup implements IGhostIngredientTarget { + private final IItemHandlerModifiable itemHandler; + private FluidStack fluidStack; + private PhantomFluidWidget fluidWidget; + private PhantomSlotWidget slotWidget; + private Consumer onChanged; + + public PhantomWidget(int x, int y, Object defaultObj) { + super(x, y, 18, 18); + itemHandler = new SingleItemStackHandler(1); + fluidStack = null; + fluidWidget = new PhantomFluidWidget(0, 0, 18, 18, null, null) + .setFluidStackUpdater(fluid -> { + fluidStack = fluid.copy(); + if (fluidStack != null && fluidStack.amount > 0) { + itemHandler.setStackInSlot(0, ItemStack.EMPTY); + slotWidget.setVisible(false); + fluidWidget.setVisible(true); + if (onChanged != null) { + onChanged.accept(fluidStack); + } + } + }, true).setBackgroundTexture(TerminalTheme.COLOR_B_2).showTip(true) + .setFluidStackSupplier(() -> fluidStack,true); + slotWidget = new PhantomSlotWidget(itemHandler, 0, 0, 0); + slotWidget.setChangeListener(()-> { + if (!itemHandler.getStackInSlot(0).isEmpty()) { + fluidStack = null; + fluidWidget.setVisible(false); + slotWidget.setVisible(true); + if (onChanged != null) { + onChanged.accept(itemHandler.getStackInSlot(0)); + } + } + }).setBackgroundTexture(TerminalTheme.COLOR_B_2); + this.addWidget(fluidWidget); + this.addWidget(slotWidget); + + if (defaultObj instanceof ItemStack) { + itemHandler.setStackInSlot(0, (ItemStack) defaultObj); + fluidWidget.setVisible(false); + slotWidget.setVisible(true); + } else if (defaultObj instanceof FluidStack) { + fluidStack = (FluidStack) defaultObj; + slotWidget.setVisible(false); + fluidWidget.setVisible(true); + } + } + + public PhantomWidget setChangeListener(Consumer onChanged) { + this.onChanged = onChanged; + return this; + } + + @Override + public List> getPhantomTargets(Object ingredient) { + if (!isVisible()) { + return Collections.emptyList(); + } + ArrayList> targets = new ArrayList<>(); + for (Widget widget : widgets) { + if (widget instanceof IGhostIngredientTarget) { + targets.addAll(((IGhostIngredientTarget) widget).getPhantomTargets(ingredient)); + } + } + return targets; + } +} diff --git a/src/main/java/gregtech/common/terminal/app/recipechart/widget/RGContainer.java b/src/main/java/gregtech/common/terminal/app/recipechart/widget/RGContainer.java new file mode 100644 index 00000000000..a3d925daf4d --- /dev/null +++ b/src/main/java/gregtech/common/terminal/app/recipechart/widget/RGContainer.java @@ -0,0 +1,204 @@ +package gregtech.common.terminal.app.recipechart.widget; + +import gregtech.api.gui.IRenderContext; +import gregtech.api.gui.Widget; +import gregtech.api.terminal.gui.widgets.DraggableScrollableWidgetGroup; +import gregtech.api.terminal.os.TerminalDialogWidget; +import gregtech.api.terminal.os.TerminalOSWidget; +import gregtech.api.terminal.os.TerminalTheme; +import net.minecraft.nbt.NBTBase; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraftforge.common.util.Constants; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Optional; + +public class RGContainer extends DraggableScrollableWidgetGroup { + protected TerminalOSWidget os; + private RGNode selectedNode; + private RGLine selectedLine; + protected final List nodes; + protected final List lines; + + public RGContainer(int x, int y, int width, int height, TerminalOSWidget os) { + super(x, y, width, height); + this.os = os; + this.setDraggable(true); + this.setXScrollBarHeight(4); + this.setYScrollBarWidth(4); + this.setXBarStyle(null, TerminalTheme.COLOR_F_1); + this.setYBarStyle(null, TerminalTheme.COLOR_F_1); + nodes = new ArrayList<>(); + lines = new ArrayList<>(); + } + + public RGNode getSelectedNode() { + return selectedNode; + } + + public void setSelectedNode(RGNode selectedNode) { + if (this.selectedNode != null) { + this.selectedNode.updateSelected(false); + } + this.selectedNode = selectedNode; + if (this.selectedNode != null) { + this.selectedNode.updateSelected(true); + } + } + + public RGLine getSelectedLine() { + return selectedLine; + } + + public void setSelectedLine(RGLine selectedLine) { + if (this.selectedLine != null) { + this.selectedLine.updateSelected(false); + } + this.selectedLine = selectedLine; + if (this.selectedLine != null) { + this.selectedLine.updateSelected(true); + } + } + + public RGNode addNode(int x, int y) { + RGNode node = new RGNode(x + getScrollXOffset(), y + getScrollYOffset(), this, null, true); + nodes.add(node); + this.addWidget(node); + return node; + } + + public RGNode addNode(int x, int y, Object object) { + RGNode node = new RGNode(x + getScrollXOffset(), y + getScrollYOffset(), this, object, false); + nodes.add(node); + this.addWidget(node); + return node; + } + + public void removeNode(RGNode node) { + nodes.remove(node); + this.waitToRemoved(node); + } + + public void addOrUpdateLine(RGNode parent, RGNode child) { + Optional optional = lines.stream().filter(line -> line.getParent() == parent && line.getChild() == child).findFirst(); + if (!optional.isPresent()) { + RGLine line = new RGLine(parent, child, this); + lines.add(line); + this.addWidget(0, line); + } else { + optional.get().updateLine(); + } + } + + public RGLine getLine(RGNode parent, RGNode child) { + Optional optional = lines.stream().filter(line -> line.getParent() == parent && line.getChild() == child).findFirst(); + return optional.orElse(null); + } + + public void removeLine(RGNode parent, RGNode child) { + lines.removeIf(line -> { + if (line.getParent() == parent && line.getChild() == child) { + RGContainer.this.waitToRemoved(line); + return true; + } + return false; + }); + } + + public void loadFromNBT(NBTTagCompound nbt) { + try { + this.clearAllWidgets(); + this.nodes.clear(); + this.lines.clear(); + NBTTagList nodesList = nbt.getTagList("nodes", Constants.NBT.TAG_COMPOUND); + for (NBTBase node : nodesList) { // build nodes + nodes.add(RGNode.deserializeNodeNBT((NBTTagCompound)node, this)); + } + Iterator iterator = nodesList.iterator(); // build relations + for (RGNode node : nodes) { + NBTTagCompound nodeTag = (NBTTagCompound)iterator.next(); + node.deserializeRelationNBT(nodeTag.getTagList("parents", Constants.NBT.TAG_INT_ARRAY), + nodeTag.getTagList("children", Constants.NBT.TAG_INT_ARRAY)); + this.addWidget(node); + } + for (RGLine line : lines) { + removeWidget(line); + } + lines.clear(); + NBTTagList linesList = nbt.getTagList("lines", Constants.NBT.TAG_COMPOUND); + for (NBTBase node : linesList) { // build nodes + RGLine line = RGLine.deserializeLineNBT((NBTTagCompound)node, this); + lines.add(line); + this.addWidget(0, line); + } + } catch (Exception e) { + TerminalDialogWidget.showInfoDialog(os, "ERROR", e.getMessage()).setClientSide().open(); + } + } + + public NBTTagCompound saveAsNBT() { + NBTTagCompound nbt = new NBTTagCompound(); + NBTTagList nodesTag = new NBTTagList(); + for (RGNode node : nodes) { + nodesTag.appendTag(node.serializeNodeNBT()); + } + nbt.setTag("nodes", nodesTag); + NBTTagList linesTag = new NBTTagList(); + for (RGLine line : lines) { + linesTag.appendTag(line.serializeLineNBT()); + } + nbt.setTag("lines", linesTag); + return nbt; + } + + @Override + protected int getMaxHeight() { + return super.getMaxHeight() + 20; + } + + @Override + protected int getMaxWidth() { + return super.getMaxWidth() + 20; + } + + @Override + protected boolean hookDrawInBackground(int mouseX, int mouseY, float partialTicks, IRenderContext context) { + if (draggedWidget != null && draggedWidget == selectedNode) { + for (RGNode node : nodes) { + if (node != selectedNode && node.canMerge(selectedNode)) { + drawBorder(node.getPosition().x, node.getPosition().y, 18, 18, 0XFF0000FF, 2); + break; + } + } + } + return super.hookDrawInBackground(mouseX, mouseY, partialTicks, context); + } + + @Override + public boolean mouseReleased(int mouseX, int mouseY, int button) { + if (draggedWidget != null && draggedWidget == selectedNode) { + for (RGNode node : nodes) { + if (node != selectedNode && node.canMerge(selectedNode)) { + node.mergeNode(selectedNode); + break; + } + } + } + return super.mouseReleased(mouseX, mouseY, button); + } + + @Override + public boolean mouseWheelMove(int mouseX, int mouseY, int wheelDelta) { + for (int i = widgets.size() - 1; i >= 0; i--) { + Widget widget = widgets.get(i); + if (widget.isVisible() && widget.isActive() && widget.mouseWheelMove(mouseX, mouseY, wheelDelta)) { + return true; + } + } + return false; + } + +} diff --git a/src/main/java/gregtech/common/terminal/app/recipechart/widget/RGLine.java b/src/main/java/gregtech/common/terminal/app/recipechart/widget/RGLine.java new file mode 100644 index 00000000000..a345479fe2b --- /dev/null +++ b/src/main/java/gregtech/common/terminal/app/recipechart/widget/RGLine.java @@ -0,0 +1,218 @@ +package gregtech.common.terminal.app.recipechart.widget; + +import gregtech.api.GTValues; +import gregtech.api.block.machines.MachineItemBlock; +import gregtech.api.gui.GuiTextures; +import gregtech.api.gui.IRenderContext; +import gregtech.api.gui.resources.ColorRectTexture; +import gregtech.api.gui.widgets.LabelWidget; +import gregtech.api.gui.widgets.SimpleTextWidget; +import gregtech.api.gui.widgets.SlotWidget; +import gregtech.api.gui.widgets.WidgetGroup; +import gregtech.api.metatileentity.MetaTileEntity; +import gregtech.api.metatileentity.SimpleMachineMetaTileEntity; +import gregtech.api.terminal.gui.widgets.CircleButtonWidget; +import gregtech.api.terminal.os.TerminalDialogWidget; +import gregtech.api.terminal.os.TerminalTheme; +import gregtech.api.util.Position; +import gregtech.api.util.Size; +import net.minecraft.client.resources.I18n; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.math.Vec2f; +import net.minecraftforge.items.ItemStackHandler; + +import java.util.ArrayList; +import java.util.List; + +public class RGLine extends WidgetGroup { + protected final RGNode parent; + protected final RGNode child; + protected final ItemStack catalyst; + protected int ratio; + private boolean isSelected; + private final List points; + private final RGContainer container; + private final WidgetGroup infoGroup; + private final WidgetGroup toolGroup; + + public RGLine(RGNode parent, RGNode child, RGContainer container) { + super(0, 0, 0, 0); + this.parent = parent; + this.child = child; + this.container = container; + this.points = new ArrayList<>(); + this.catalyst = parent.catalyst; + + infoGroup = new WidgetGroup(0, 0, 0, 0); + if (catalyst != null) { + ItemStackHandler handler = new ItemStackHandler(); + handler.setStackInSlot(0, catalyst); + infoGroup.addWidget(new SlotWidget(handler, 0, 0, 0, false, false).setBackgroundTexture(new ColorRectTexture(0))); + MetaTileEntity mte = MachineItemBlock.getMetaTileEntity(catalyst); + if (mte instanceof SimpleMachineMetaTileEntity) { + infoGroup.addWidget(new LabelWidget(9, -10, I18n.format("terminal.recipe_chart.tier") + GTValues.VN[((SimpleMachineMetaTileEntity) mte).getTier()], -1).setXCentered(true).setShadow(true)); + } + } + + infoGroup.setVisible(false); + infoGroup.setActive(false); + this.addWidget(infoGroup); + + toolGroup = new WidgetGroup(0, 0, 0, 0); + toolGroup.addWidget(new CircleButtonWidget(-8, 0, 8, 1, 12) + .setColors(0, TerminalTheme.COLOR_7.getColor(), 0) + .setIcon(GuiTextures.ICON_VISIBLE) + .setHoverText("terminal.recipe_chart.visible") + .setClickListener(cd -> { + infoGroup.setActive(!infoGroup.isActive()); + infoGroup.setVisible(!infoGroup.isVisible()); + })); + toolGroup.addWidget(new CircleButtonWidget(8, 0, 8, 1, 12) + .setColors(0, TerminalTheme.COLOR_7.getColor(), 0) + .setIcon(GuiTextures.ICON_CALCULATOR) + .setHoverText("terminal.recipe_chart.ratio") + .setClickListener(cd -> TerminalDialogWidget.showTextFieldDialog(container.os, "terminal.recipe_chart.ratio", s->{ + try { + return Integer.parseInt(s) > 0; + } catch (Exception ignored){ + return false; + } + }, s -> { + if (s != null) { + ratio = Integer.parseInt(s); + parent.updateDemand(parent.getHeadDemand()); + } + }).setClientSide().open())); + toolGroup.addWidget(new SimpleTextWidget(0, -18, "", -1, () -> Integer.toString(ratio), true).setShadow(true)); + toolGroup.setVisible(false); + this.addWidget(toolGroup); + this.ratio = 1; + updateLine(); + } + + public static RGLine deserializeLineNBT(NBTTagCompound nbt, RGContainer container) { + RGLine line = new RGLine(container.nodes.get(nbt.getInteger("parent")), container.nodes.get(nbt.getInteger("child")), container); + line.ratio = nbt.getInteger("ratio"); + boolean visible = nbt.getBoolean("visible"); + line.infoGroup.setVisible(visible); + line.infoGroup.setActive(visible); + return line; + } + + public NBTTagCompound serializeLineNBT() { + NBTTagCompound nbt = new NBTTagCompound(); + nbt.setInteger("parent", container.nodes.indexOf(parent)); + nbt.setInteger("child", container.nodes.indexOf(child)); + nbt.setInteger("ratio", ratio); + nbt.setBoolean("visible", infoGroup.isVisible()); + return nbt; + } + + public RGNode getParent() { + return parent; + } + + public RGNode getChild() { + return child; + } + + public List getPoints() { + return points; + } + + public ItemStack getCatalyst() { + return catalyst; + } + + public void updateSelected(boolean isSelected) { + this.isSelected = isSelected; + toolGroup.setVisible(this.isSelected); + } + + public void updateLine() { + this.points.clear(); + Position pos1 = parent.getNodePosition(child); + Position pos2 = child.getNodePosition(null); + int x1, x2, y1, y2; + if (Math.abs(pos1.x - pos2.x) > Math.abs(pos1.y - pos2.y)) { + if (pos1.x > pos2.x) { + x1 = pos1.x; + y1 = pos1.y + 9; + x2 = pos2.x + 18; + } else { + x1 = pos1.x + 18; + y1 = pos1.y + 9; + x2 = pos2.x; + } + y2 = pos2.y + 9; + points.addAll(genBezierPoints(new Vec2f(x1, y1), new Vec2f(x2, y2), true, 0.01f)); + } else { + if (pos1.y > pos2.y) { + x1 = pos1.x + 9; + y1 = pos1.y; + y2 = pos2.y + 18; + } else { + x1 = pos1.x + 9; + y1 = pos1.y + 18; + y2 = pos2.y; + } + x2 = pos2.x + 9; + points.addAll(genBezierPoints(new Vec2f(x1, y1), new Vec2f(x2, y2), false, 0.01f)); + } + Position position = pos2.subtract(child.getSelfPosition()); + this.setSelfPosition(new Position(Math.min(x1, x2), Math.min(y1, y2)).subtract(position)); + int width = Math.abs(x1 - x2); + int height = Math.abs(y1 - y2); + this.setSize(new Size(width, height)); + this.setVisible(true); + this.setActive(true); + toolGroup.setSelfPosition(new Position((width) / 2, 0)); + infoGroup.setSelfPosition(new Position((width - 18) / 2, (height - 18) / 2)); + } + + public boolean isMouseOver(int mouseX, int mouseY) { + if (points == null || points.size() == 0) return false; + float x = points.get(0).x; + float y = points.get(0).y; + float x2 = points.get(points.size() - 1).x; + float y2 = points.get(points.size() - 1).y; + if (mouseX >= Math.min(x, x2) && mouseY >= Math.min(y, y2) && Math.max(x, x2) > mouseX && Math.max(y, y2) > mouseY) { + for (Vec2f point : points) { + if ((mouseX - point.x) * (mouseX - point.x) + (mouseY - point.y) * (mouseY - point.y) < 4) { + return true; + } + } + } + return false; + } + + @Override + public void drawInBackground(int mouseX, int mouseY, float partialTicks, IRenderContext context) { + if (parent.isVisible() || child.isVisible()) { + if (isSelected) { + drawSolidRect(getPosition().x, getPosition().y, getSize().width, getSize().height, 0x2fffffff); + drawLines(points, 0x2fff0000, 0xffff0000, 2); + } else { + drawLines(points, 0x2fffff00, 0xff00ff00, 2); + } + Vec2f point = points.get(points.size() - 1); + drawSolidRect((int)(point.x - 1.5), (int)(point.y - 1.5), 3, 3, 0XFF00FF00); + } + super.drawInBackground(mouseX, mouseY, partialTicks, context); + } + + @Override + public boolean mouseClicked(int mouseX, int mouseY, int button) { + if (super.mouseClicked(mouseX, mouseY, button)){ + return true; + } else if (isMouseOver(mouseX, mouseY)) { + if (!isSelected) { + container.setSelectedLine(this); + } + } else if (isSelected) { + container.setSelectedLine(null); + } + return false; + } +} diff --git a/src/main/java/gregtech/common/terminal/app/recipechart/widget/RGNode.java b/src/main/java/gregtech/common/terminal/app/recipechart/widget/RGNode.java new file mode 100644 index 00000000000..b9b45db6c2a --- /dev/null +++ b/src/main/java/gregtech/common/terminal/app/recipechart/widget/RGNode.java @@ -0,0 +1,564 @@ +package gregtech.common.terminal.app.recipechart.widget; + +import gregtech.api.block.machines.MachineItemBlock; +import gregtech.api.gui.GuiTextures; +import gregtech.api.gui.IRenderContext; +import gregtech.api.gui.Widget; +import gregtech.api.gui.impl.ModularUIContainer; +import gregtech.api.gui.widgets.SimpleTextWidget; +import gregtech.api.gui.widgets.SlotWidget; +import gregtech.api.gui.widgets.TankWidget; +import gregtech.api.gui.widgets.WidgetGroup; +import gregtech.api.metatileentity.MetaTileEntity; +import gregtech.api.metatileentity.SimpleMachineMetaTileEntity; +import gregtech.api.recipes.Recipe; +import gregtech.api.terminal.gui.IDraggable; +import gregtech.api.terminal.gui.widgets.CircleButtonWidget; +import gregtech.api.terminal.os.TerminalDialogWidget; +import gregtech.api.terminal.os.TerminalTheme; +import gregtech.api.util.GTUtility; +import gregtech.api.util.Position; +import gregtech.integration.jei.GTJeiPlugin; +import gregtech.integration.jei.recipe.GTRecipeWrapper; +import mezz.jei.api.gui.IRecipeLayout; +import mezz.jei.api.recipe.IFocus; +import mezz.jei.api.recipe.IRecipeCategory; +import mezz.jei.api.recipe.IRecipeWrapper; +import mezz.jei.gui.Focus; +import mezz.jei.gui.recipes.RecipeLayout; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTBase; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagIntArray; +import net.minecraft.nbt.NBTTagList; +import net.minecraft.util.math.MathHelper; +import net.minecraftforge.common.util.Constants; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.FluidTank; +import net.minecraftforge.fml.common.ObfuscationReflectionHelper; +import net.minecraftforge.items.ItemStackHandler; + +import java.util.*; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.Collectors; + +public class RGNode extends WidgetGroup implements IDraggable { + protected Object head; + protected int recipePer; + protected ItemStack catalyst; + private boolean isSelected; + private WidgetGroup toolGroup; + private WidgetGroup inputsGroup; + private RGContainer container; + private SimpleTextWidget textWidget; + protected Map parentNodes; + protected Map> children; + + public RGNode(int x, int y, RGContainer container, Object head, boolean isPhantom) { + super(x, y, 18, 18); + init(container); + this.head = head; + if (isPhantom) { + this.addWidget(new PhantomWidget(0, 0, head).setChangeListener(object -> RGNode.this.head = object)); + toolGroup.addWidget(new CircleButtonWidget(-11, 49, 8, 1, 12) + .setColors(0, TerminalTheme.COLOR_7.getColor(), 0) + .setIcon(GuiTextures.ICON_CALCULATOR) + .setHoverText("terminal.recipe_chart.calculator") + .setClickListener(cd -> TerminalDialogWidget.showTextFieldDialog(container.os, "terminal.recipe_chart.demand", s->{ + try { + return Integer.parseInt(s) > 0; + } catch (Exception ignored){ + return false; + } + }, s -> { + if (s != null) { + updateDemand(Integer.parseInt(s)); + } + }).setClientSide().open())); + } else { + if (head instanceof ItemStack) { + ItemStackHandler handler = new ItemStackHandler(1); + handler.setStackInSlot(0, (ItemStack) head); + this.addWidget(new SlotWidget(handler, 0, 0, 0, false, false).setBackgroundTexture(TerminalTheme.COLOR_B_2)); + } else if (head instanceof FluidStack) { + FluidTank tank = new FluidTank((FluidStack) head, Integer.MAX_VALUE); + this.addWidget(new TankWidget(tank, 0, 0, 18, 18).setAlwaysShowFull(true).setBackgroundTexture(TerminalTheme.COLOR_B_2).setClient()); + } + } + } + + private void init(RGContainer container) { + this.container = container; + textWidget = new SimpleTextWidget(9, -5, "", -1, () -> { + if (head instanceof ItemStack) { + return ((ItemStack) head).getDisplayName(); + } else if (head instanceof FluidStack) { + return ((FluidStack) head).getLocalizedName(); + } + return "terminal.recipe_chart.drag"; + }, true).setShadow(true); + textWidget.setVisible(false); + textWidget.setActive(false); + this.addWidget(textWidget); + inputsGroup = new WidgetGroup(0, 0, 0, 0); + this.addWidget(inputsGroup); + toolGroup = new WidgetGroup(0, 0, 0, 0); + this.addWidget(toolGroup); + toolGroup.addWidget(new CircleButtonWidget(-11, 9, 8, 1, 12) + .setColors(0, TerminalTheme.COLOR_7.getColor(), TerminalTheme.COLOR_3.getColor()) + .setIcon(GuiTextures.ICON_REMOVE) + .setHoverText("terminal.guide_editor.remove") + .setClickListener(cd -> remove())); + toolGroup.addWidget(new CircleButtonWidget(-11, 29, 8, 1, 12) + .setColors(0, TerminalTheme.COLOR_7.getColor(), 0) + .setIcon(GuiTextures.ICON_VISIBLE) + .setHoverText("terminal.recipe_chart.visible") + .setClickListener(cd -> { + textWidget.setActive(!textWidget.isActive()); + textWidget.setVisible(!textWidget.isVisible()); + })); + toolGroup.addWidget(new CircleButtonWidget(9, 29, 8, 1, 12) + .setColors(0, TerminalTheme.COLOR_7.getColor(), 0) + .setIcon(GuiTextures.ICON_LOCATION) + .setHoverText("terminal.recipe_chart.jei") + .setClickListener(cd -> { + if (GTJeiPlugin.jeiRuntime != null && head != null) { + GTJeiPlugin.jeiRuntime.getRecipesGui().show(new Focus<>(IFocus.Mode.OUTPUT, head)); + } + })); + inputsGroup.setVisible(false); + inputsGroup.setActive(false); + toolGroup.setVisible(false); + toolGroup.setActive(false); + parentNodes = new HashMap<>(); + children = new LinkedHashMap<>(); // important + } + + public int getHeadDemand() { + if (head instanceof ItemStack) { + return ((ItemStack) head).getCount(); + } else if (head instanceof FluidStack) { + return ((FluidStack) head).amount; + } + return 0; + } + + public int getChildDemand(RGNode child) { + for (Map.Entry> entry : children.entrySet()) { + if (entry.getValue().contains(child)) { + int perC = 0; + if (entry.getKey() instanceof SlotWidget) { + perC = ((SlotWidget) entry.getKey()).getHandle().getStack().getCount(); + } else if(entry.getKey() instanceof TankWidget) { + perC = ((TankWidget) entry.getKey()).fluidTank.getFluidAmount(); + } + int ratioSum = entry.getValue().stream().mapToInt(it->container.getLine(RGNode.this, it).ratio).sum(); + return MathHelper.ceil(perC * MathHelper.ceil(getHeadDemand() / (float)recipePer) * container.getLine(RGNode.this, child).ratio / (float)ratioSum); + } + } + return 0; + } + + public boolean canMerge(RGNode node) { + if (this.head instanceof ItemStack && node.head instanceof ItemStack && ((ItemStack) this.head).isItemEqual((ItemStack) node.head)) { + Position pos1 = this.getPosition(); + Position pos2 = node.getPosition(); + return Math.abs(pos1.x - pos2.x) < 18 && Math.abs(pos1.y - pos2.y) < 18; + } else if (this.head instanceof FluidStack && node.head instanceof FluidStack && ((FluidStack) this.head).isFluidEqual((FluidStack) node.head)) { + Position pos1 = this.getPosition(); + Position pos2 = node.getPosition(); + return Math.abs(pos1.x - pos2.x) < 18 && Math.abs(pos1.y - pos2.y) < 18; + } + return false; + } + + public void mergeNode(RGNode node) { + for (RGNode parentNode : node.parentNodes.keySet()) { + for (Set value : parentNode.children.values()) { + if (value.remove(node)) { + value.add(this); + addParent(parentNode); + parentNode.updateDemand(parentNode.getHeadDemand()); + break; + } + } + } + node.remove(); + } + + public void remove() { + if (isSelected) { + container.setSelectedNode(null); + } + container.removeNode(this); + for (RGNode parentNode : parentNodes.keySet()) { + container.removeLine(parentNode, this); + parentNode.onChildRemoved(this); + } + parentNodes.clear(); + for (Set childs : children.values()) { + for (RGNode child : childs) { + child.removeParent(this); + } + } + children.clear(); + } + + public Position getNodePosition(RGNode child) { + if (child != null && isSelected) { + for (Map.Entry> nodeEntry : children.entrySet()) { + if (nodeEntry.getValue().contains(child)) { + return nodeEntry.getKey().getPosition(); + } + } + } + return this.getPosition(); + } + + public void addParent(RGNode parent) { + container.addOrUpdateLine(parent, this); + this.parentNodes.put(parent, parent.getChildDemand(this)); + updateDemand(parentNodes.values().stream().mapToInt(it->it).sum()); + } + + public void updateDemand(int demand) { + if (head instanceof ItemStack) { + ((ItemStack) head).setCount(demand); + } else if (head instanceof FluidStack) { + ((FluidStack) head).amount = demand; + } + for (Set children : children.values()) { + for (RGNode child : children) { + child.parentNodes.put(this, this.getChildDemand(child)); + child.updateDemand(child.parentNodes.values().stream().mapToInt(it->it).sum()); + } + } + } + + public void removeParent(RGNode parent) { + this.parentNodes.remove(parent); + if (parentNodes.size() == 0) { + for (Set childs : children.values()) { + for (RGNode child : childs) { + child.removeParent(RGNode.this); + } + } + children.clear(); + container.removeNode(this); + } else { + updateDemand(parentNodes.values().stream().mapToInt(it->it).sum()); + } + container.removeLine(parent, this); + } + + public void onChildRemoved(RGNode child) { + for (Set childs : children.values()) { + if (childs.remove(child)) { + updateDemand(getHeadDemand()); + break; + } + } + } + + @Override + protected void onPositionUpdate() { + super.onPositionUpdate(); + for (RGNode parentNode : parentNodes.keySet()) { + container.addOrUpdateLine(parentNode, this); + } + for (Set childs : children.values()) { + for (RGNode child : childs) { + container.addOrUpdateLine(this, child); + } + } + } + + public boolean transferRecipe(ModularUIContainer x, IRecipeLayout recipeLayout, EntityPlayer player, boolean maxTransfer, boolean doTransfer) { + if (isSelected) { + Object obj = recipeLayout.getFocus() == null ? null : recipeLayout.getFocus().getValue(); + if (head instanceof ItemStack && obj instanceof ItemStack) { + if(!((ItemStack) head).isItemEqual((ItemStack) obj)) { + return false; + } + } else if (head instanceof FluidStack && obj instanceof FluidStack) { + if(!((FluidStack) head).isFluidEqual((FluidStack)obj)) { + return false; + } + } else { + return false; + } + if (!doTransfer) return true; + RGNode.this.recipePer = 0; + + // items + List itemInputs = new ArrayList<>(); + recipeLayout.getItemStacks().getGuiIngredients().values().forEach(it->{ + if (it.isInput() && it.getDisplayedIngredient()!= null) { + ItemStack input = it.getDisplayedIngredient(); + for (ItemStack itemInput : itemInputs) { + if (itemInput.isItemEqual(input)) { + itemInput.setCount(itemInput.getCount() + input.getCount()); + return; + } + } + itemInputs.add(input.copy()); + } else if (head instanceof ItemStack && !it.isInput()) { + for (ItemStack ingredient : it.getAllIngredients()) { + if (((ItemStack) head).isItemEqual(ingredient)) { + RGNode.this.recipePer += ingredient.getCount(); + break; + } + } + } + }); + + // fluids + List fluidInputs = new ArrayList<>(); + recipeLayout.getFluidStacks().getGuiIngredients().values().forEach(it->{ + if (it.isInput() && it.getDisplayedIngredient()!= null) { + FluidStack input = it.getDisplayedIngredient(); + for (FluidStack fluidInput : fluidInputs) { + if (fluidInput.isFluidEqual(input)) { + fluidInput.amount += input.amount; + return; + } + } + fluidInputs.add(input.copy()); + } else if (head instanceof FluidStack && !it.isInput()) { + for (FluidStack ingredient : it.getAllIngredients()) { + if (((FluidStack) head).isFluidEqual(ingredient)) { + RGNode.this.recipePer += ingredient.amount; + break; + } + } + } + }); + // CHECK GTCE RECIPES + Recipe recipe = null; + if (recipeLayout instanceof RecipeLayout) { + IRecipeWrapper recipeWrapper = ObfuscationReflectionHelper.getPrivateValue(RecipeLayout.class, (RecipeLayout)recipeLayout, "recipeWrapper"); + if (recipeWrapper instanceof GTRecipeWrapper) { + recipe = ((GTRecipeWrapper) recipeWrapper).getRecipe(); + } + } + IRecipeCategory category = recipeLayout.getRecipeCategory(); + List catalysts = GTJeiPlugin.jeiRuntime.getRecipeRegistry().getRecipeCatalysts(category); + ItemStack catalyst = null; + + if (recipe != null) { // GT + int tierRequire = GTUtility.getTierByVoltage(recipe.getEUt()); + for (Object o : catalysts) { + if (o instanceof ItemStack) { + MetaTileEntity mte = MachineItemBlock.getMetaTileEntity((ItemStack) o); + if (mte instanceof SimpleMachineMetaTileEntity) { + if (tierRequire < ((SimpleMachineMetaTileEntity) mte).getTier()) { + catalyst = (ItemStack) o; + break; + } + } + } + } + } + + if (catalyst == null) { + for (Object o : catalysts) { + if (o instanceof ItemStack) { + catalyst = (ItemStack) o; + break; + } + } + } + setRecipe(itemInputs, fluidInputs, catalyst, recipePer); + return true; + } + return false; + } + + public void deserializeRelationNBT(NBTTagList parentsTag, NBTTagList childrenTag) { + for (NBTBase nbtBase : parentsTag) { + int[] nbt = ((NBTTagIntArray) nbtBase).getIntArray(); + parentNodes.put(container.nodes.get(nbt[0]), nbt[1]); + } + Iterator iterator = children.keySet().iterator(); + for (NBTBase nbtBase : childrenTag) { + int[] nbt = ((NBTTagIntArray) nbtBase).getIntArray(); + children.get(iterator.next()).addAll(Arrays.stream(nbt).mapToObj(it->container.nodes.get(it)).collect(Collectors.toList())); + } + } + + public static RGNode deserializeNodeNBT(NBTTagCompound nodeTag, RGContainer container) { + byte type = nodeTag.getByte("type"); // 0-null 1-itemstack 2-fluidstack + Object head = null; + if (type == 1) { + head = new ItemStack(nodeTag.getCompoundTag("nbt")); + ((ItemStack)head).setCount(nodeTag.getInteger("count")); + } else if (type == 2) { + head = FluidStack.loadFluidStackFromNBT(nodeTag.getCompoundTag("nbt")); + assert head != null; + ((FluidStack)head).amount = nodeTag.getInteger("count"); + } + RGNode node; + if (nodeTag.getBoolean("phantom")) { + node = new RGNode(nodeTag.getInteger("x"), nodeTag.getInteger("y"), container, head, true); + } else { + node = new RGNode(nodeTag.getInteger("x"), nodeTag.getInteger("y"), container, head, false); + } + NBTTagList itemsList = nodeTag.getTagList("items", Constants.NBT.TAG_COMPOUND); + NBTTagList fluidsList = nodeTag.getTagList("fluids", Constants.NBT.TAG_COMPOUND); + node.setRecipe(itemsList.tagList.stream().map(it->new ItemStack((NBTTagCompound) it)).collect(Collectors.toList()), + fluidsList.tagList.stream().map(it->FluidStack.loadFluidStackFromNBT((NBTTagCompound) it)).collect(Collectors.toList()), + nodeTag.hasKey("catalyst") ? new ItemStack(nodeTag.getCompoundTag("catalyst")) : null, + nodeTag.getInteger("per")); + boolean visible = nodeTag.getBoolean("visible"); + node.textWidget.setVisible(visible); + node.textWidget.setActive(visible); + return node; + } + + public NBTTagCompound serializeNodeNBT() { + //head + NBTTagCompound nbt = new NBTTagCompound(); + nbt.setInteger("x", getSelfPosition().x); + nbt.setInteger("y", getSelfPosition().y); + nbt.setByte("type", head instanceof ItemStack ? (byte)1 : head instanceof FluidStack ? (byte)2 : 0); + if (head instanceof ItemStack) { + nbt.setTag("nbt", ((ItemStack) head).serializeNBT()); + nbt.setInteger("count", ((ItemStack) head).getCount()); + } else if (head instanceof FluidStack) { + nbt.setTag("nbt", ((FluidStack) head).writeToNBT(new NBTTagCompound())); + nbt.setInteger("count", ((FluidStack) head).amount); + } + nbt.setBoolean("phantom", widgets.stream().anyMatch(it->it instanceof PhantomWidget)); + // recipe + children + NBTTagList itemsList = new NBTTagList(); + NBTTagList fluidsList = new NBTTagList(); + NBTTagList childrenList = new NBTTagList(); + for (Map.Entry> entry : children.entrySet()) { + Widget widget = entry.getKey(); + if (widget instanceof SlotWidget) { + itemsList.appendTag(((SlotWidget) widget).getHandle().getStack().serializeNBT()); + } else if (widget instanceof TankWidget) { + fluidsList.appendTag(((TankWidget) widget).fluidTank.getFluid().writeToNBT(new NBTTagCompound())); + } else { + continue; + } + NBTTagIntArray childList = new NBTTagIntArray(entry.getValue().stream().mapToInt(it->container.nodes.indexOf(it)).toArray()); + childrenList.appendTag(childList); + } + nbt.setTag("items", itemsList); + nbt.setTag("fluids", fluidsList); + nbt.setTag("children", childrenList); + if (catalyst != null) { + nbt.setTag("catalyst", catalyst.serializeNBT()); + } + nbt.setInteger("per", recipePer); + // parent + NBTTagList parentsList = new NBTTagList(); + for (Map.Entry entry : parentNodes.entrySet()) { + parentsList.appendTag(new NBTTagIntArray(new int[]{container.nodes.indexOf(entry.getKey()), entry.getValue()})); + } + nbt.setTag("parents", parentsList); + nbt.setBoolean("visible", textWidget.isVisible()); + return nbt; + } + + private void setRecipe(List itemInputs, List fluidInputs, ItemStack catalyst, int recipePer) { + this.recipePer = recipePer; + this.catalyst = catalyst; + inputsGroup.clearAllWidgets(); + for (Set childs : children.values()) { + for (RGNode child : childs) { + child.removeParent(this); + } + } + children.clear(); + AtomicInteger y = new AtomicInteger(-20); + for (ItemStack itemInput : itemInputs) { + ItemStackHandler handler = new ItemStackHandler(1); + handler.setStackInSlot(0, itemInput); + Widget widget = new SlotWidget(handler, 0, 0, y.addAndGet(20), false, false) { + @Override + public boolean mouseClicked(int mouseX, int mouseY, int button) { + return RGNode.this.handleTipsSlotClick(mouseX, mouseY,this, handler.getStackInSlot(0).copy()); + } + }.setBackgroundTexture(TerminalTheme.COLOR_B_2); + inputsGroup.addWidget(widget); + children.put(widget, new HashSet<>()); + } + for (FluidStack fluidInput : fluidInputs) { + FluidTank tank = new FluidTank(fluidInput, Integer.MAX_VALUE); + Widget widget = new TankWidget(tank, 0, y.addAndGet(20), 18, 18) { + @Override + public boolean mouseClicked(int mouseX, int mouseY, int button) { + return RGNode.this.handleTipsSlotClick(mouseX, mouseY,this, tank.getFluid().copy()); + } + }.setAlwaysShowFull(true).setBackgroundTexture(TerminalTheme.COLOR_B_2); + inputsGroup.addWidget(widget); + children.put(widget, new HashSet<>()); + } + inputsGroup.setSelfPosition(new Position(25, -(inputsGroup.widgets.size() * 20) / 2 + 8)); + } + + private boolean handleTipsSlotClick(int mouseX, int mouseY, Widget slot, Object object){ + if (slot.isMouseOverElement(mouseX, mouseY)) { + Position position = inputsGroup.getSelfPosition(); + RGNode child = container.addNode(RGNode.this.getSelfPosition().x + 50, RGNode.this.getSelfPosition().y + position.y + slot.getSelfPosition().y, object); + Set childs = RGNode.this.children.get(slot); + childs.add(child); + + child.addParent(RGNode.this); + RGNode.this.updateDemand(RGNode.this.getHeadDemand()); + return true; + } + return false; + } + + public void updateSelected(boolean selected) { + isSelected = selected; + if (selected) { + toolGroup.setActive(true); + toolGroup.setVisible(true); + inputsGroup.setActive(true); + inputsGroup.setVisible(true); + } else { + toolGroup.setActive(false); + toolGroup.setVisible(false); + inputsGroup.setActive(false); + inputsGroup.setVisible(false); + } + children.forEach((widget, rgNode) -> rgNode.forEach(child -> container.addOrUpdateLine(RGNode.this, child))); + } + + @Override + public void drawInBackground(int mouseX, int mouseY, float partialTicks, IRenderContext context) { + int x = getPosition().x; + int y = getPosition().y; + int width = getSize().width; + int height = getSize().height; + if (isSelected) { + drawBorder(x, y, width, height, 0xff00ff00, 2); + } + super.drawInBackground(mouseX, mouseY, partialTicks, context); + } + + @Override + public boolean allowDrag(int mouseX, int mouseY, int button) { + return isMouseOverElement(mouseX, mouseY); + } + + @Override + public boolean mouseClicked(int mouseX, int mouseY, int button) { + if (isMouseOverElement(mouseX, mouseY)) { + if (!isSelected) { + container.setSelectedNode(this); + } + return false; + } else if (super.mouseClicked(mouseX, mouseY, button)) { + return true; + } else if (isSelected) { + container.setSelectedNode(null); + } + return false; + } +} diff --git a/src/main/java/gregtech/common/terminal/component/ClickComponent.java b/src/main/java/gregtech/common/terminal/component/ClickComponent.java new file mode 100644 index 00000000000..4e41ac96637 --- /dev/null +++ b/src/main/java/gregtech/common/terminal/component/ClickComponent.java @@ -0,0 +1,45 @@ +package gregtech.common.terminal.component; + +import gregtech.api.gui.Widget; +import gregtech.api.gui.resources.IGuiTexture; +import gregtech.api.terminal.os.menu.IMenuComponent; + +import java.util.function.Consumer; + +public class ClickComponent implements IMenuComponent { + private IGuiTexture icon; + private String hoverText; + private Consumer consumer; + + public ClickComponent setIcon(IGuiTexture icon) { + this.icon = icon; + return this; + } + + public ClickComponent setHoverText(String hoverText) { + this.hoverText = hoverText; + return this; + } + + public ClickComponent setClickConsumer(Consumer consumer) { + this.consumer = consumer; + return this; + } + + @Override + public IGuiTexture buttonIcon() { + return icon; + } + + @Override + public String hoverText() { + return hoverText; + } + + @Override + public void click(Widget.ClickData clickData) { + if (consumer != null) { + consumer.accept(clickData); + } + } +} diff --git a/src/main/java/gregtech/common/terminal/component/SearchComponent.java b/src/main/java/gregtech/common/terminal/component/SearchComponent.java new file mode 100644 index 00000000000..3f61dfafcff --- /dev/null +++ b/src/main/java/gregtech/common/terminal/component/SearchComponent.java @@ -0,0 +1,114 @@ +package gregtech.common.terminal.component; + +import gregtech.api.gui.IRenderContext; +import gregtech.api.gui.resources.ColorRectTexture; +import gregtech.api.gui.resources.IGuiTexture; +import gregtech.api.gui.resources.TextureArea; +import gregtech.api.gui.widgets.TextFieldWidget; +import gregtech.api.gui.widgets.WidgetGroup; +import gregtech.api.terminal.os.menu.IMenuComponent; +import gregtech.api.terminal.util.ISearch; +import gregtech.api.terminal.util.SearchEngine; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.util.Tuple; +import net.minecraft.util.math.MathHelper; + +import java.util.ArrayList; +import java.util.List; + +public class SearchComponent extends WidgetGroup implements IMenuComponent { + private final static TextureArea SEARCHING = TextureArea.fullImage("textures/gui/terminal/icon/network/search_hover.png"); + private final static int SIZE = 10; + private final SearchEngine engine; + private final List> results; + private final IWidgetSearch search; + private boolean isUp; + private int offset; + + public SearchComponent(IWidgetSearch search){ + super(0,0,280,20); + this.search = search; + results = new ArrayList<>(); + engine = new SearchEngine<>(search, r -> results.add(new Tuple<>(r, search.resultDisplay(r)))); + this.addWidget(new TextFieldWidget(0, 5, 280, 20, new ColorRectTexture(0xcf000000), null, null) + .setValidator(s->true) + .setTextResponder(s->{ + results.clear(); + engine.searchWord(s); + offset = 0; + }, true)); + } + + @Override + public IGuiTexture buttonIcon() { + return SEARCHING; + } + + @Override + public String hoverText() { + return "terminal.component.searching"; + } + + public void setUp(boolean up) { + isUp = up; + } + + @Override + public void drawInBackground(int mouseX, int mouseY, float partialTicks, IRenderContext context) { + super.drawInBackground(mouseX, mouseY, partialTicks, context); + int x = getPosition().x; + int width = getSize().width; + int height = getSize().height; + int y = (isUp ? -results.size() : 1) * height + getPosition().y; + int max = Math.min(offset + SIZE, results.size()); + for (int i = offset; i < max; i++) { + Tuple result = results.get(i); + drawSolidRect(x, y, width, height, 0xAA000000); + FontRenderer fontRenderer = Minecraft.getMinecraft().fontRenderer; + fontRenderer.drawString(result.getSecond(), x + 4, y + (height - fontRenderer.FONT_HEIGHT) / 2 + 1, -1); + if (isMouseOver(x, y, width, height, mouseX, mouseY)) { + drawBorder(x + 1, y + 1, width - 2, height - 2, -1, 1); + } + y += height; + } + } + + @Override + public boolean mouseClicked(int mouseX, int mouseY, int button) { + int x = getPosition().x; + int width = getSize().width; + int height = getSize().height; + int y = (isUp ? -results.size() : 1) * height + getPosition().y; + int max = Math.min(offset + SIZE, results.size()); + for (int i = offset; i < max; i++) { + Tuple result = results.get(i); + if (isMouseOver(x, y, width, height, mouseX, mouseY)) { + search.selectResult(result.getFirst()); + engine.dispose(); + return true; + } + y += height; + } + return super.mouseClicked(mouseX, mouseY, button); + } + + @Override + public boolean mouseWheelMove(int mouseX, int mouseY, int wheelDelta) { + int x = getPosition().x; + int width = getSize().width; + int height = getSize().height; + int y = (isUp ? -results.size() : 1) * height + getPosition().y; + int max = Math.min(offset + SIZE, results.size()); + if (isMouseOver(x, y, width, height * (max - offset), mouseX, mouseY)) { + offset = MathHelper.clamp(offset + (wheelDelta > 0 ? -1 : +1), 0, Math.max(0, results.size() - SIZE)); + return true; + } + return super.mouseWheelMove(mouseX, mouseY, wheelDelta); + } + + public interface IWidgetSearch extends ISearch{ + String resultDisplay(T result); + void selectResult(T result); + } +} diff --git a/src/main/java/gregtech/common/terminal/component/setting/GuiTextureSetter.java b/src/main/java/gregtech/common/terminal/component/setting/GuiTextureSetter.java new file mode 100644 index 00000000000..bd0618ccf28 --- /dev/null +++ b/src/main/java/gregtech/common/terminal/component/setting/GuiTextureSetter.java @@ -0,0 +1,32 @@ +package gregtech.common.terminal.component.setting; + +import gregtech.api.gui.Widget; +import gregtech.api.gui.resources.IGuiTexture; +import gregtech.api.gui.widgets.WidgetGroup; + +import java.util.function.Consumer; + +public class GuiTextureSetter extends WidgetGroup implements ISetting{ + private final String name; + private Consumer updated; + + public GuiTextureSetter(String name, Consumer updated) { + this.name = name; + this.updated = updated; + } + + @Override + public String getName() { + return name; + } + + @Override + public IGuiTexture getIcon() { + return null; + } + + @Override + public Widget getWidget() { + return null; + } +} diff --git a/src/main/java/gregtech/common/terminal/component/setting/ISetting.java b/src/main/java/gregtech/common/terminal/component/setting/ISetting.java new file mode 100644 index 00000000000..db0649d75b0 --- /dev/null +++ b/src/main/java/gregtech/common/terminal/component/setting/ISetting.java @@ -0,0 +1,10 @@ +package gregtech.common.terminal.component.setting; + +import gregtech.api.gui.Widget; +import gregtech.api.gui.resources.IGuiTexture; + +public interface ISetting { + String getName(); + IGuiTexture getIcon(); + Widget getWidget(); +} diff --git a/src/main/java/gregtech/common/terminal/component/setting/IWidgetSettings.java b/src/main/java/gregtech/common/terminal/component/setting/IWidgetSettings.java new file mode 100644 index 00000000000..94a2f13db4a --- /dev/null +++ b/src/main/java/gregtech/common/terminal/component/setting/IWidgetSettings.java @@ -0,0 +1,7 @@ +package gregtech.common.terminal.component.setting; + +import gregtech.api.terminal.util.TreeNode; + +public interface IWidgetSettings { + TreeNode getSettings(); +} diff --git a/src/main/java/gregtech/common/terminal/component/setting/SettingComponent.java b/src/main/java/gregtech/common/terminal/component/setting/SettingComponent.java new file mode 100644 index 00000000000..74397632eae --- /dev/null +++ b/src/main/java/gregtech/common/terminal/component/setting/SettingComponent.java @@ -0,0 +1,29 @@ +package gregtech.common.terminal.component.setting; + +import gregtech.api.gui.GuiTextures; +import gregtech.api.gui.Widget; +import gregtech.api.gui.widgets.WidgetGroup; +import gregtech.api.terminal.gui.widgets.TreeListWidget; +import gregtech.api.terminal.os.menu.IMenuComponent; + +public class SettingComponent extends WidgetGroup implements IMenuComponent { + private Widget settingWidget; + + public SettingComponent(IWidgetSettings settings) { + this.addWidget(new TreeListWidget<>(0, 0, 130, 232, settings.getSettings(), (selected) -> { + if (selected.getContent() != null) { + if (settingWidget != null) { + removeWidget(settingWidget); + } + settingWidget = selected.getContent().getWidget(); + if (settingWidget != null) { + addWidget(settingWidget); + } + } + }).setContentIconSupplier(ISetting::getIcon) + .setContentNameSupplier(ISetting::getName) + .setNodeTexture(GuiTextures.BORDERED_BACKGROUND) + .setLeafTexture(GuiTextures.SLOT_DARKENED)); + } + +} diff --git a/src/main/java/gregtech/common/tools/ToolAxe.java b/src/main/java/gregtech/common/tools/ToolAxe.java index d1a3f0f6cb0..d1c373afb9e 100644 --- a/src/main/java/gregtech/common/tools/ToolAxe.java +++ b/src/main/java/gregtech/common/tools/ToolAxe.java @@ -53,7 +53,7 @@ public float getAttackSpeed(ItemStack stack) { @Override public boolean canMineBlock(IBlockState block, ItemStack stack) { String tool = block.getBlock().getHarvestTool(block); - return (tool != null && tool.equals("axe")) || + return (tool != null && AXE_TOOL_CLASSES.contains(tool)) || block.getMaterial() == Material.WOOD; } diff --git a/src/main/java/gregtech/common/tools/ToolCrowbar.java b/src/main/java/gregtech/common/tools/ToolCrowbar.java index 7f4bd1a6ed0..902cad98cf5 100644 --- a/src/main/java/gregtech/common/tools/ToolCrowbar.java +++ b/src/main/java/gregtech/common/tools/ToolCrowbar.java @@ -41,7 +41,7 @@ public void onStatsAddedToTool(MetaValueItem item) { @Override public boolean canMineBlock(IBlockState block, ItemStack stack) { String tool = block.getBlock().getHarvestTool(block); - return (tool != null && tool.equals("crowbar")) || + return (tool != null && CROWBAR_TOOL_CLASSES.contains(tool)) || block.getMaterial() == Material.CIRCUITS; } diff --git a/src/main/java/gregtech/common/tools/ToolFile.java b/src/main/java/gregtech/common/tools/ToolFile.java index cd0e5eb7d4d..7346e72760a 100644 --- a/src/main/java/gregtech/common/tools/ToolFile.java +++ b/src/main/java/gregtech/common/tools/ToolFile.java @@ -29,7 +29,7 @@ public float getBaseDamage(ItemStack stack) { @Override public boolean canMineBlock(IBlockState block, ItemStack stack) { String tool = block.getBlock().getHarvestTool(block); - return (tool != null && tool.equals("file")) || + return (tool != null && FILE_TOOL_CLASSES.contains(tool)) || block.getMaterial() == Material.CIRCUITS; } diff --git a/src/main/java/gregtech/common/tools/ToolHardHammer.java b/src/main/java/gregtech/common/tools/ToolHardHammer.java index 811877422b5..4dfe1db1116 100644 --- a/src/main/java/gregtech/common/tools/ToolHardHammer.java +++ b/src/main/java/gregtech/common/tools/ToolHardHammer.java @@ -1,5 +1,6 @@ package gregtech.common.tools; +import com.google.common.collect.ImmutableSet; import gregtech.api.recipes.MatchingMode; import gregtech.api.recipes.RecipeMaps; import net.minecraft.block.material.Material; @@ -16,16 +17,12 @@ import net.minecraft.world.World; import java.util.Collections; -import java.util.HashSet; import java.util.List; import java.util.Set; public class ToolHardHammer extends ToolBase { - private static final Set HAMMER_TOOL_CLASSES = new HashSet() {{ - add("hammer"); - add("pickaxe"); - }}; + private static final Set HAMMER_TOOL_CLASSES = ImmutableSet.of("hammer", "pickaxe"); @Override public boolean canApplyEnchantment(ItemStack stack, Enchantment enchantment) { @@ -78,7 +75,7 @@ public float getAttackSpeed(ItemStack stack) { public boolean canMineBlock(IBlockState block, ItemStack stack) { String tool = block.getBlock().getHarvestTool(block); ItemStack itemStack = new ItemStack(block.getBlock(), 1, block.getBlock().getMetaFromState(block)); - return (tool != null && (tool.equals("hammer") || tool.equals("pickaxe"))) || + return (tool != null && HAMMER_TOOL_CLASSES.contains(tool)) || block.getMaterial() == Material.ROCK || block.getMaterial() == Material.GLASS || block.getMaterial() == Material.ICE || diff --git a/src/main/java/gregtech/common/tools/ToolHoe.java b/src/main/java/gregtech/common/tools/ToolHoe.java index c05261643b5..f0cbff2fb1c 100644 --- a/src/main/java/gregtech/common/tools/ToolHoe.java +++ b/src/main/java/gregtech/common/tools/ToolHoe.java @@ -26,7 +26,7 @@ public float getBaseDamage(ItemStack stack) { @Override public boolean canMineBlock(IBlockState block, ItemStack stack) { String tool = block.getBlock().getHarvestTool(block); - return (tool != null && tool.equals("hoe")) || + return (tool != null && HOE_TOOL_CLASSES.contains(tool)) || block.getMaterial() == Material.GROUND; } diff --git a/src/main/java/gregtech/common/tools/ToolMiningHammer.java b/src/main/java/gregtech/common/tools/ToolMiningHammer.java index fc5cb42a4ba..71aff587583 100644 --- a/src/main/java/gregtech/common/tools/ToolMiningHammer.java +++ b/src/main/java/gregtech/common/tools/ToolMiningHammer.java @@ -1,5 +1,6 @@ package gregtech.common.tools; +import com.google.common.collect.ImmutableSet; import gregtech.api.items.toolitem.ToolMetaItem; import gregtech.api.util.GTUtility; import gregtech.common.items.behaviors.ModeSwitchBehavior; @@ -20,10 +21,7 @@ public class ToolMiningHammer extends ToolBase { - private static final Set HAMMER_TOOL_CLASSES = new HashSet() {{ - add("pickaxe"); - add("hammer"); - }}; + private static final Set HAMMER_TOOL_CLASSES = ImmutableSet.of("pickaxe", "hammer"); public enum MiningHammerMode implements ModeSwitchBehavior.ILocalizationKey { THREE_BY_THREE("metaitem.drill.mode.three_by_three", 3, 3, 0.75f), @@ -89,7 +87,7 @@ public float getMaxDurabilityMultiplier(ItemStack stack) { @Override public boolean canMineBlock(IBlockState block, ItemStack stack) { String tool = block.getBlock().getHarvestTool(block); - return (tool != null && (tool.equals("hammer") || tool.equals("pickaxe"))) || + return (tool != null && HAMMER_TOOL_CLASSES.contains(tool)) || block.getMaterial() == Material.ROCK || block.getMaterial() == Material.GLASS || block.getMaterial() == Material.ICE || diff --git a/src/main/java/gregtech/common/tools/ToolPickaxe.java b/src/main/java/gregtech/common/tools/ToolPickaxe.java index 947d4c9126f..7ea64387c49 100644 --- a/src/main/java/gregtech/common/tools/ToolPickaxe.java +++ b/src/main/java/gregtech/common/tools/ToolPickaxe.java @@ -36,7 +36,7 @@ public float getDigSpeedMultiplier(ItemStack stack) { @Override public boolean canMineBlock(IBlockState block, ItemStack stack) { String tool = block.getBlock().getHarvestTool(block); - return (tool != null && tool.equals("pickaxe")) || + return (tool != null && PICK_TOOL_CLASSES.contains(tool)) || block.getMaterial() == Material.ROCK || block.getMaterial() == Material.IRON || block.getMaterial() == Material.ANVIL || diff --git a/src/main/java/gregtech/common/tools/ToolSaw.java b/src/main/java/gregtech/common/tools/ToolSaw.java index a5ab1cb7ee3..0aa85345053 100644 --- a/src/main/java/gregtech/common/tools/ToolSaw.java +++ b/src/main/java/gregtech/common/tools/ToolSaw.java @@ -1,5 +1,6 @@ package gregtech.common.tools; +import com.google.common.collect.ImmutableSet; import gregtech.api.items.toolitem.ToolMetaItem; import net.minecraft.block.material.Material; import net.minecraft.block.state.IBlockState; @@ -18,16 +19,12 @@ import javax.annotation.Nullable; import javax.annotation.ParametersAreNonnullByDefault; -import java.util.HashSet; import java.util.List; import java.util.Set; public class ToolSaw extends ToolBase { - private static final Set SAW_TOOL_CLASSES = new HashSet() {{ - add("axe"); - add("saw"); - }}; + private static final Set SAW_TOOL_CLASSES = ImmutableSet.of("axe", "saw"); @Override public boolean canApplyEnchantment(ItemStack stack, Enchantment enchantment) { @@ -52,7 +49,7 @@ public float getBaseDamage(ItemStack stack) { @Override public boolean canMineBlock(IBlockState block, ItemStack stack) { String tool = block.getBlock().getHarvestTool(block); - return (tool != null && (tool.equals("axe") || tool.equals("saw"))) || + return (tool != null && SAW_TOOL_CLASSES.contains(tool)) || block.getMaterial() == Material.LEAVES || block.getMaterial() == Material.VINE || block.getMaterial() == Material.WOOD || diff --git a/src/main/java/gregtech/common/tools/ToolScoop.java b/src/main/java/gregtech/common/tools/ToolScoop.java index 1c5c95214b0..e5e74af64d0 100644 --- a/src/main/java/gregtech/common/tools/ToolScoop.java +++ b/src/main/java/gregtech/common/tools/ToolScoop.java @@ -20,7 +20,7 @@ public int getToolDamagePerBlockBreak(ItemStack stack) { @Override public boolean canMineBlock(IBlockState block, ItemStack stack) { String tool = block.getBlock().getHarvestTool(block); - return tool != null && tool.equals("scoop"); + return tool != null && SCOOP_TOOL_CLASSES.contains(tool); } @Override diff --git a/src/main/java/gregtech/common/tools/ToolScrewdriver.java b/src/main/java/gregtech/common/tools/ToolScrewdriver.java index ec1319aa306..434a101dbe3 100644 --- a/src/main/java/gregtech/common/tools/ToolScrewdriver.java +++ b/src/main/java/gregtech/common/tools/ToolScrewdriver.java @@ -37,7 +37,7 @@ public float getBaseDamage(ItemStack stack) { @Override public boolean canMineBlock(IBlockState block, ItemStack stack) { String tool = block.getBlock().getHarvestTool(block); - return (tool != null && tool.equals("screwdriver")) || + return (tool != null && DRIVER_TOOL_CLASSES.contains(tool)) || block.getMaterial() == Material.CIRCUITS; } diff --git a/src/main/java/gregtech/common/tools/ToolShovel.java b/src/main/java/gregtech/common/tools/ToolShovel.java index ac8e64213cb..54b5a477ead 100644 --- a/src/main/java/gregtech/common/tools/ToolShovel.java +++ b/src/main/java/gregtech/common/tools/ToolShovel.java @@ -41,7 +41,7 @@ public float getDigSpeedMultiplier(ItemStack stack) { @Override public boolean canMineBlock(IBlockState block, ItemStack stack) { String tool = block.getBlock().getHarvestTool(block); - return (tool != null && tool.equals("shovel")) || + return (tool != null && SHOVEL_TOOL_CLASSES.contains(tool)) || block.getMaterial() == Material.SAND || block.getMaterial() == Material.GRASS || block.getMaterial() == Material.GROUND || diff --git a/src/main/java/gregtech/common/tools/ToolSword.java b/src/main/java/gregtech/common/tools/ToolSword.java index 056fbddf197..b3b3a753294 100644 --- a/src/main/java/gregtech/common/tools/ToolSword.java +++ b/src/main/java/gregtech/common/tools/ToolSword.java @@ -51,7 +51,7 @@ public boolean canPerformSweepAttack(ItemStack stack) { @Override public boolean canMineBlock(IBlockState block, ItemStack stack) { String tool = block.getBlock().getHarvestTool(block); - return (tool != null && tool.equals("sword")) || + return (tool != null && SWORD_TOOL_CLASSES.contains(tool)) || block.getMaterial() == Material.LEAVES || block.getMaterial() == Material.GOURD || block.getMaterial() == Material.VINE || diff --git a/src/main/java/gregtech/common/tools/ToolUniversalSpade.java b/src/main/java/gregtech/common/tools/ToolUniversalSpade.java index e83853e231e..3add2207871 100644 --- a/src/main/java/gregtech/common/tools/ToolUniversalSpade.java +++ b/src/main/java/gregtech/common/tools/ToolUniversalSpade.java @@ -1,23 +1,17 @@ package gregtech.common.tools; +import com.google.common.collect.ImmutableSet; import gregtech.api.items.metaitem.MetaItem.MetaValueItem; import gregtech.common.items.behaviors.CrowbarBehaviour; import net.minecraft.block.material.Material; import net.minecraft.block.state.IBlockState; import net.minecraft.item.ItemStack; -import java.util.HashSet; import java.util.Set; public class ToolUniversalSpade extends ToolBase { - private static final Set SPADE_TOOL_CLASSES = new HashSet() {{ - add("shovel"); - add("axe"); - add("saw"); - add("sword"); - add("crowbar"); - }}; + private static final Set SPADE_TOOL_CLASSES = ImmutableSet.of("shovel", "axe", "saw", "sword", "crowbar"); @Override public int getToolDamagePerBlockBreak(ItemStack stack) { @@ -47,11 +41,7 @@ public float getDigSpeedMultiplier(ItemStack stack) { @Override public boolean canMineBlock(IBlockState block, ItemStack stack) { String tool = block.getBlock().getHarvestTool(block); - return (tool != null && (tool.equals("shovel") || - tool.equals("axe") || - tool.equals("saw") || - tool.equals("sword") || - tool.equals("crowbar"))) || + return (tool != null && SPADE_TOOL_CLASSES.contains(tool)) || block.getMaterial() == Material.SAND || block.getMaterial() == Material.GRASS || block.getMaterial() == Material.GROUND || diff --git a/src/main/java/gregtech/common/tools/ToolWireCutter.java b/src/main/java/gregtech/common/tools/ToolWireCutter.java index 48e8c73dafb..0e15fe598e7 100644 --- a/src/main/java/gregtech/common/tools/ToolWireCutter.java +++ b/src/main/java/gregtech/common/tools/ToolWireCutter.java @@ -28,7 +28,7 @@ public float getBaseDamage(ItemStack stack) { @Override public boolean canMineBlock(IBlockState block, ItemStack stack) { String tool = block.getBlock().getHarvestTool(block); - return tool != null && tool.equals("cutter"); + return tool != null && CUTTER_TOOL_CLASSES.contains(tool); } @Override diff --git a/src/main/java/gregtech/common/tools/ToolWrench.java b/src/main/java/gregtech/common/tools/ToolWrench.java index 3649dd86802..efce22a1377 100644 --- a/src/main/java/gregtech/common/tools/ToolWrench.java +++ b/src/main/java/gregtech/common/tools/ToolWrench.java @@ -5,8 +5,10 @@ import net.minecraft.block.Block; import net.minecraft.block.material.Material; import net.minecraft.block.state.IBlockState; +import net.minecraft.enchantment.Enchantment; import net.minecraft.entity.EntityLivingBase; import net.minecraft.init.Blocks; +import net.minecraft.init.Enchantments; import net.minecraft.item.ItemStack; import java.util.Collections; @@ -37,7 +39,7 @@ public float getBaseDamage(ItemStack stack) { public boolean canMineBlock(IBlockState blockState, ItemStack stack) { Block block = blockState.getBlock(); String tool = block.getHarvestTool(blockState); - return (tool != null && tool.equals("wrench")) + return (tool != null && WRENCH_TOOL_CLASSES.contains(tool)) || blockState.getMaterial() == Material.PISTON || block == Blocks.HOPPER || block == Blocks.DISPENSER @@ -50,6 +52,11 @@ public void onStatsAddedToTool(MetaValueItem item) { item.addComponents(new WrenchBehaviour(DamageValues.DAMAGE_FOR_WRENCH)); } + @Override + public boolean canApplyEnchantment(ItemStack stack, Enchantment enchantment) { + return enchantment == Enchantments.UNBREAKING || enchantment == Enchantments.EFFICIENCY; + } + @Override public Set getToolClasses(ItemStack stack) { return WRENCH_TOOL_CLASSES; diff --git a/src/main/java/gregtech/common/tools/largedrills/ToolDrillLarge.java b/src/main/java/gregtech/common/tools/largedrills/ToolDrillLarge.java index 79ce666467d..4986dde59a6 100644 --- a/src/main/java/gregtech/common/tools/largedrills/ToolDrillLarge.java +++ b/src/main/java/gregtech/common/tools/largedrills/ToolDrillLarge.java @@ -5,8 +5,8 @@ import gregtech.api.capability.IElectricItem; import gregtech.api.items.metaitem.MetaItem; import gregtech.api.items.toolitem.ToolMetaItem; -import gregtech.api.util.DirectionHelper; import gregtech.api.util.GTUtility; +import gregtech.api.util.RelativeDirection; import gregtech.common.items.behaviors.ModeSwitchBehavior; import gregtech.common.tools.ToolBase; import net.minecraft.block.material.Material; @@ -137,7 +137,7 @@ private List getAOEBlocks(int max, EntityPlayer player, BlockPos hitPo Vec3d lookVec = player.getLookVec(); EnumFacing facing = EnumFacing.getFacingFromVector((float) lookVec.x, (float) lookVec.y, (float) lookVec.z); BlockPos corner = findCorner(max, hitPos, player, facing); - BlockPos oppositeCorner = findOppositeCorner(max, corner, player); + BlockPos oppositeCorner = findOppositeCorner(max, corner, facing); List posList = Lists.newArrayList(BlockPos.getAllInBox(corner, oppositeCorner)); return posList.stream() @@ -155,22 +155,22 @@ private List getAOEBlocks(int max, EntityPlayer player, BlockPos hitPo * Returns the relative bottom left closest corner of the possible mining area for the drill. */ private static BlockPos findCorner(int max, BlockPos startPos, EntityPlayer player, EnumFacing facing) { - Vec3i leftVec = DirectionHelper.getRelativeLeft(player).getDirectionVec(); - Vec3i downVec = DirectionHelper.getRelativeDown(player).getDirectionVec(); + Vec3i leftVec = RelativeDirection.LEFT.applyVec3i(facing); + Vec3i downVec = RelativeDirection.DOWN.applyVec3i(facing); switch (facing) { case UP: case DOWN: // treat up and down as standard cube. just acquire leftmost corner, ignoring floor level return startPos - .add(DirectionHelper.multiplyVec(leftVec, max / 2)) - .add(DirectionHelper.multiplyVec(downVec, max / 2)); + .add(multiplyVec(leftVec, max / 2)) + .add(multiplyVec(downVec, max / 2)); default: // try to find lowest pos - Vec3i towardsVec = DirectionHelper.getRelativeForward(player).getDirectionVec(); + Vec3i towardsVec = RelativeDirection.FRONT.applyVec3i(facing); // Find the relative downwards offset for (int i = 1; i <= max; i++) { - BlockPos currentPos = startPos.add(DirectionHelper.multiplyVec(downVec, i)); + BlockPos currentPos = startPos.add(multiplyVec(downVec, i)); BlockPos forwardPos = currentPos.add(towardsVec); IBlockState state = player.world.getBlockState(forwardPos); @@ -181,19 +181,27 @@ private static BlockPos findCorner(int max, BlockPos startPos, EntityPlayer play } // Find the relative leftmost BlockPos - return startPos.add(DirectionHelper.multiplyVec(leftVec, max / 2)); + return startPos.add(multiplyVec(leftVec, max / 2)); } } - private static BlockPos findOppositeCorner(int max, BlockPos corner, EntityPlayer player) { - Vec3i rightVec = DirectionHelper.getRelativeRight(player).getDirectionVec(); - Vec3i forwardVec = DirectionHelper.getRelativeForward(player).getDirectionVec(); - Vec3i upVec = DirectionHelper.getRelativeUp(player).getDirectionVec(); + private static BlockPos findOppositeCorner(int max, BlockPos corner, EnumFacing facing) { + Vec3i rightVec = RelativeDirection.RIGHT.applyVec3i(facing); + Vec3i forwardVec = RelativeDirection.FRONT.applyVec3i(facing); + Vec3i upVec = RelativeDirection.UP.applyVec3i(facing); return corner - .add(DirectionHelper.multiplyVec(rightVec, max - 1)) - .add(DirectionHelper.multiplyVec(forwardVec, max - 1)) - .add(DirectionHelper.multiplyVec(upVec, max - 1)); + .add(multiplyVec(rightVec, max - 1)) + .add(multiplyVec(forwardVec, max - 1)) + .add(multiplyVec(upVec, max - 1)); + } + + private static Vec3i multiplyVec(Vec3i start, int multiplier) { + return new Vec3i( + start.getX() * multiplier, + start.getY() * multiplier, + start.getZ() * multiplier + ); } @Override diff --git a/src/main/java/gregtech/integration/jei/GTJeiPlugin.java b/src/main/java/gregtech/integration/jei/GTJeiPlugin.java index 3634b7a1cd1..72b34be1d94 100755 --- a/src/main/java/gregtech/integration/jei/GTJeiPlugin.java +++ b/src/main/java/gregtech/integration/jei/GTJeiPlugin.java @@ -17,7 +17,6 @@ import gregtech.api.recipes.machines.RecipeMapFurnace; import gregtech.api.unification.material.Material; import gregtech.api.unification.material.MaterialRegistry; -import gregtech.api.unification.material.Materials; import gregtech.api.unification.material.properties.PropertyKey; import gregtech.api.worldgen.config.OreDepositDefinition; import gregtech.api.worldgen.config.WorldGenRegistry; @@ -39,6 +38,7 @@ import mezz.jei.api.ingredients.VanillaTypes; import mezz.jei.api.recipe.IRecipeCategoryRegistration; import mezz.jei.api.recipe.VanillaRecipeCategoryUid; +import mezz.jei.config.Constants; import net.minecraft.client.resources.I18n; import net.minecraft.item.Item; import net.minecraft.util.ResourceLocation; @@ -54,6 +54,12 @@ public class GTJeiPlugin implements IModPlugin { public static IIngredientRegistry ingredientRegistry; + public static IJeiRuntime jeiRuntime; + + @Override + public void onRuntimeAvailable(IJeiRuntime jeiRuntime) { + GTJeiPlugin.jeiRuntime = jeiRuntime; + } @Override public void registerItemSubtypes(@Nonnull ISubtypeRegistry subtypeRegistry) { @@ -76,10 +82,9 @@ public void registerCategories(IRecipeCategoryRegistration registry) { for (FuelRecipeMap fuelRecipeMap : FuelRecipeMap.getRecipeMaps()) { registry.addRecipeCategories(new FuelRecipeMapCategory(fuelRecipeMap, registry.getJeiHelpers().getGuiHelper())); } - registry.addRecipeCategories(new PrimitiveBlastRecipeCategory(registry.getJeiHelpers().getGuiHelper())); - registry.addRecipeCategories(new CokeOvenRecipeCategory(registry.getJeiHelpers().getGuiHelper())); registry.addRecipeCategories(new OreByProductCategory(registry.getJeiHelpers().getGuiHelper())); registry.addRecipeCategories(new GTOreCategory(registry.getJeiHelpers().getGuiHelper())); + registry.addRecipeCategories(new MaterialTreeCategory(registry.getJeiHelpers().getGuiHelper())); } @Override @@ -94,7 +99,7 @@ public void register(IModRegistry registry) { ModularUIGuiHandler modularUIGuiHandler = new ModularUIGuiHandler(jeiHelpers.recipeTransferHandlerHelper()); registry.addAdvancedGuiHandlers(modularUIGuiHandler); registry.addGhostIngredientHandler(modularUIGuiHandler.getGuiContainerClass(), modularUIGuiHandler); - registry.getRecipeTransferRegistry().addRecipeTransferHandler(modularUIGuiHandler, VanillaRecipeCategoryUid.CRAFTING); + registry.getRecipeTransferRegistry().addRecipeTransferHandler(modularUIGuiHandler, Constants.UNIVERSAL_RECIPE_TRANSFER_UID); for (RecipeMap recipeMap : RecipeMap.getRecipeMaps()) { List recipesList = recipeMap.getRecipeList() @@ -149,21 +154,8 @@ public void register(IModRegistry registry) { registry.addRecipeCatalyst(MetaTileEntities.LARGE_TITANIUM_BOILER.getStackForm(), semiFluidMapId); registry.addRecipeCatalyst(MetaTileEntities.LARGE_TUNGSTENSTEEL_BOILER.getStackForm(), semiFluidMapId); - registry.addIngredientInfo(Objects.requireNonNull(Materials.Air.getFluid(1000)), VanillaTypes.FLUID, I18n.format("gregtech.machine.air_collector.jei_description")); registry.addIngredientInfo(Objects.requireNonNull(MetaItems.FLUID_CELL.getStackForm()), VanillaTypes.ITEM, I18n.format("gregtech.item.fluid_cell.jei_description")); - String primitiveBlastId = GTValues.MODID + ":" + "primitive_blast_furnace"; - registry.addRecipes(RecipeMaps.PRIMITIVE_BLAST_FURNACE_RECIPES.stream() - .map(PrimitiveBlastRecipeWrapper::new) - .collect(Collectors.toList()), primitiveBlastId); - registry.addRecipeCatalyst(MetaTileEntities.PRIMITIVE_BLAST_FURNACE.getStackForm(), primitiveBlastId); - - String cokeOvenId = GTValues.MODID + ":" + "coke_oven"; - registry.addRecipes(RecipeMaps.COKE_OVEN_RECIPES.stream() - .map(CokeOvenRecipeWrapper::new) - .collect(Collectors.toList()), cokeOvenId); - registry.addRecipeCatalyst(MetaTileEntities.COKE_OVEN.getStackForm(), cokeOvenId); - //TODO, add Electromagnetic Separator to the Ore Byproduct page List oreByproductList = new CopyOnWriteArrayList<>(); for (Material material : MaterialRegistry.MATERIAL_REGISTRY) { @@ -196,6 +188,15 @@ public void register(IModRegistry registry) { registry.addRecipeCatalyst(machine.getStackForm(), oreByProductId); } + //Material Tree + List materialTreeList = new CopyOnWriteArrayList<>(); + for (Material material : MaterialRegistry.MATERIAL_REGISTRY) { + if (material.hasProperty(PropertyKey.DUST)) { + materialTreeList.add(new MaterialTree(material)); + } + } + registry.addRecipes(materialTreeList, GTValues.MODID + ":" + "material_tree"); + //Ore Veins List oreVeins = WorldGenRegistry.getOreDeposits(); List oreInfoList = new CopyOnWriteArrayList<>(); diff --git a/src/main/java/gregtech/integration/jei/GTOreCategory.java b/src/main/java/gregtech/integration/jei/GTOreCategory.java index 2a248251607..56d60eca006 100644 --- a/src/main/java/gregtech/integration/jei/GTOreCategory.java +++ b/src/main/java/gregtech/integration/jei/GTOreCategory.java @@ -36,7 +36,6 @@ public class GTOreCategory extends PrimitiveRecipeCategory protected List dimensionIDs; protected final int FONT_HEIGHT = Minecraft.getMinecraft().fontRenderer.FONT_HEIGHT; protected final Map namedDimensions = WorldGenRegistry.getNamedDimensions(); - private final Map dimMap = DimensionManager.getRegisteredDimensions(); private final Supplier> dimension = this::getAllRegisteredDimensions; private final int NUM_OF_SLOTS = 5; private final int SLOT_WIDTH = 18; @@ -193,30 +192,22 @@ private void drawVeinName(final FontRenderer fontRenderer) { public List getAllRegisteredDimensions() { List dims = new ArrayList<>(); + /* + Gather the registered dimensions here instead of at the top of the class to catch very late registered dimensions + such as Advanced Rocketry + */ + Map dimMap = DimensionManager.getRegisteredDimensions(); dimMap.values().stream() .flatMap(Collection::stream) .mapToInt(Integer::intValue) .filter(num -> definition.getDimensionFilter().test(DimensionManager.createProviderFor(num))) .forEach(dims::add); + //Slight cleanup of the list if Advanced Rocketry is installed if (isModLoaded(MODID_AR)) { try { - int[] plantDims = DimensionManager.getDimensions(DimensionType.byName("planet")); - int[] asteroidDims = DimensionManager.getDimensions(DimensionType.byName("asteroid")); int[] spaceDims = DimensionManager.getDimensions(DimensionType.byName("space")); - //Add the Planets to the dimension list - Arrays.stream(plantDims) - .filter(num -> !dims.contains(num)) - .filter(num -> definition.getDimensionFilter().test(DimensionManager.createProviderFor(num))) - .forEach(dims::add); - - //Add the Asteroids to the dimension list - Arrays.stream(asteroidDims) - .filter(num -> !dims.contains(num)) - .filter(num -> definition.getDimensionFilter().test(DimensionManager.createProviderFor(num))) - .forEach(dims::add); - //Remove Space from the dimension list for (int spaceDim : spaceDims) { if (dims.contains(spaceDim)) { diff --git a/src/main/java/gregtech/integration/jei/multiblock/infos/AssemblyLineInfo.java b/src/main/java/gregtech/integration/jei/multiblock/infos/AssemblyLineInfo.java index 3dfa7c985a3..a6ee626371b 100644 --- a/src/main/java/gregtech/integration/jei/multiblock/infos/AssemblyLineInfo.java +++ b/src/main/java/gregtech/integration/jei/multiblock/infos/AssemblyLineInfo.java @@ -75,7 +75,7 @@ protected void generateBlockTooltips() { ITextComponent inputTooltip = new TextComponentTranslation( "gregtech.multiblock.preview.only", - new TextComponentTranslation("gregtech.machine.item_bus.export.ulv.name")) + new TextComponentTranslation("gregtech.machine.item_bus.import.ulv.name")) .setStyle(new Style().setColor(TextFormatting.RED)); for (int i = 0; i < GTValues.UHV + 1; i++) { diff --git a/src/main/java/gregtech/integration/jei/multiblock/infos/SteamGrinderInfo.java b/src/main/java/gregtech/integration/jei/multiblock/infos/SteamGrinderInfo.java index debadf50cf4..07642818277 100644 --- a/src/main/java/gregtech/integration/jei/multiblock/infos/SteamGrinderInfo.java +++ b/src/main/java/gregtech/integration/jei/multiblock/infos/SteamGrinderInfo.java @@ -26,7 +26,7 @@ public MultiblockControllerBase getController() { public List getMatchingShapes() { ArrayList shapeInfo = new ArrayList<>(); - if (ConfigHolder.steelSteamMultiblocks) { + if (ConfigHolder.U.steelSteamMultiblocks) { shapeInfo.add(MultiblockShapeInfo.builder() .aisle("XXX", "IXX", "XXX") .aisle("HXX", "S#X", "XXX") diff --git a/src/main/java/gregtech/integration/jei/multiblock/infos/SteamOvenInfo.java b/src/main/java/gregtech/integration/jei/multiblock/infos/SteamOvenInfo.java index 927650958e5..0044bc00ac8 100644 --- a/src/main/java/gregtech/integration/jei/multiblock/infos/SteamOvenInfo.java +++ b/src/main/java/gregtech/integration/jei/multiblock/infos/SteamOvenInfo.java @@ -27,7 +27,7 @@ public MultiblockControllerBase getController() { public List getMatchingShapes() { ArrayList shapeInfo = new ArrayList<>(); - if (ConfigHolder.steelSteamMultiblocks) { + if (ConfigHolder.U.steelSteamMultiblocks) { shapeInfo.add(MultiblockShapeInfo.builder() .aisle("FFF", "IXX", "###") .aisle("HFF", "S#X", "XXX") diff --git a/src/main/java/gregtech/integration/jei/recipe/FacadeRegistryPlugin.java b/src/main/java/gregtech/integration/jei/recipe/FacadeRegistryPlugin.java index 58f3d9e98e6..1b7a484eeac 100644 --- a/src/main/java/gregtech/integration/jei/recipe/FacadeRegistryPlugin.java +++ b/src/main/java/gregtech/integration/jei/recipe/FacadeRegistryPlugin.java @@ -66,10 +66,7 @@ public List getRecipeWrappers(IRecipeCategory createFacadeRecipes(ItemStack itemStack) { - return Lists.newArrayList( - createFacadeRecipe(itemStack, Materials.Aluminium, 5), - createFacadeRecipe(itemStack, Materials.WroughtIron, 3), - createFacadeRecipe(itemStack, Materials.Iron, 2)); + return Lists.newArrayList(createFacadeRecipe(itemStack, Materials.Iron, 4)); } private static IRecipeWrapper createFacadeRecipe(ItemStack itemStack, Material material, int facadeAmount) { diff --git a/src/main/java/gregtech/integration/jei/recipe/GTRecipeWrapper.java b/src/main/java/gregtech/integration/jei/recipe/GTRecipeWrapper.java index e18b4509c06..e276564bb27 100644 --- a/src/main/java/gregtech/integration/jei/recipe/GTRecipeWrapper.java +++ b/src/main/java/gregtech/integration/jei/recipe/GTRecipeWrapper.java @@ -3,6 +3,7 @@ import gregtech.api.recipes.CountableIngredient; import gregtech.api.recipes.Recipe; import gregtech.api.recipes.Recipe.ChanceEntry; +import gregtech.api.recipes.recipeproperties.PrimitiveProperty; import gregtech.api.recipes.recipeproperties.RecipeProperty; import gregtech.api.unification.OreDictUnifier; import gregtech.api.util.ItemStackHashStrategy; @@ -37,6 +38,10 @@ public GTRecipeWrapper(Recipe recipe) { this.recipe = recipe; } + public Recipe getRecipe() { + return recipe; + } + @Override public void getIngredients(@Nonnull IIngredients ingredients) { if (!recipe.getInputs().isEmpty()) { @@ -123,11 +128,12 @@ public void addTooltip(int slotIndex, boolean input, Object ingredient, List= 0 ? "gregtech.recipe.eu" : "gregtech.recipe.eu_inverted", Math.abs(recipe.getEUt()), JEIHelpers.getMinTierForVoltage(recipe.getEUt())), 0, yPosition += LINE_HEIGHT, 0x111111); + if (!recipe.hasProperty(PrimitiveProperty.getInstance())) { + minecraft.fontRenderer.drawString(I18n.format("gregtech.recipe.total", Math.abs((long) recipe.getEUt()) * recipe.getDuration()), 0, yPosition, 0x111111); + minecraft.fontRenderer.drawString(I18n.format(recipe.getEUt() >= 0 ? "gregtech.recipe.eu" : "gregtech.recipe.eu_inverted", Math.abs(recipe.getEUt()), JEIHelpers.getMinTierForVoltage(recipe.getEUt())), 0, yPosition += LINE_HEIGHT, 0x111111); + } else yPosition -= LINE_HEIGHT * 2; minecraft.fontRenderer.drawString(I18n.format("gregtech.recipe.duration", recipe.getDuration() / 20f), 0, yPosition += LINE_HEIGHT, 0x111111); for (Map.Entry, Object> propertyEntry : recipe.getPropertyValues()) { if (!propertyEntry.getKey().isHidden()) { diff --git a/src/main/java/gregtech/integration/jei/recipe/primitive/CokeOvenRecipeCategory.java b/src/main/java/gregtech/integration/jei/recipe/primitive/CokeOvenRecipeCategory.java deleted file mode 100644 index 9f9c23dea41..00000000000 --- a/src/main/java/gregtech/integration/jei/recipe/primitive/CokeOvenRecipeCategory.java +++ /dev/null @@ -1,59 +0,0 @@ -package gregtech.integration.jei.recipe.primitive; - -import gregtech.api.gui.GuiTextures; -import gregtech.api.recipes.recipes.CokeOvenRecipe; -import mezz.jei.api.IGuiHelper; -import mezz.jei.api.gui.IDrawable; -import mezz.jei.api.gui.IGuiFluidStackGroup; -import mezz.jei.api.gui.IGuiItemStackGroup; -import mezz.jei.api.gui.IRecipeLayout; -import mezz.jei.api.ingredients.IIngredients; -import mezz.jei.api.recipe.IRecipeWrapper; -import net.minecraft.client.Minecraft; - -import javax.annotation.Nonnull; - -public class CokeOvenRecipeCategory extends PrimitiveRecipeCategory { - - protected final IDrawable slot; - protected final IDrawable progressBar; - protected final IDrawable fluidTank; - protected final IDrawable fluidTankOverlay; - - - public CokeOvenRecipeCategory(IGuiHelper guiHelper) { - super("coke_oven", - "gregtech.machine.coke_oven.name", - guiHelper.createBlankDrawable(176, 166), guiHelper); - - this.slot = guiHelper.drawableBuilder(GuiTextures.SLOT.imageLocation, 0, 0, 18, 18).setTextureSize(18, 18).build(); - this.progressBar = guiHelper.drawableBuilder(GuiTextures.BRONZE_BLAST_FURNACE_PROGRESS_BAR.imageLocation, 0, 0, 20, 15).setTextureSize(20, 30).build(); - this.fluidTank = guiHelper.drawableBuilder(GuiTextures.FLUID_TANK_BACKGROUND.imageLocation, 0, 0, 20, 58).setTextureSize(20, 58).build(); - this.fluidTankOverlay = guiHelper.drawableBuilder(GuiTextures.FLUID_TANK_OVERLAY.imageLocation, 0, 0, 20, 58).setTextureSize(20, 58).build(); - } - - @Override - public void setRecipe(IRecipeLayout recipeLayout, @Nonnull CokeOvenRecipeWrapper recipeWrapper, @Nonnull IIngredients ingredients) { - IGuiItemStackGroup itemStackGroup = recipeLayout.getItemStacks(); - IGuiFluidStackGroup fluidStackGroup = recipeLayout.getFluidStacks(); - itemStackGroup.init(0, true, 32, 19); - itemStackGroup.init(1, false, 84, 19); - itemStackGroup.set(ingredients); - fluidStackGroup.init(0, false, 133, 3, 20, 58, 32000, true, this.fluidTankOverlay); - fluidStackGroup.set(ingredients); - } - - @Nonnull - @Override - public IRecipeWrapper getRecipeWrapper(@Nonnull CokeOvenRecipe recipe) { - return new CokeOvenRecipeWrapper(recipe); - } - - @Override - public void drawExtras(Minecraft minecraft) { - this.slot.draw(minecraft, 32, 19); - this.slot.draw(minecraft, 84, 19); - this.progressBar.draw(minecraft, 57, 20); - this.fluidTank.draw(minecraft, 133, 3); - } -} diff --git a/src/main/java/gregtech/integration/jei/recipe/primitive/CokeOvenRecipeWrapper.java b/src/main/java/gregtech/integration/jei/recipe/primitive/CokeOvenRecipeWrapper.java deleted file mode 100644 index 4dddf516b0b..00000000000 --- a/src/main/java/gregtech/integration/jei/recipe/primitive/CokeOvenRecipeWrapper.java +++ /dev/null @@ -1,53 +0,0 @@ -package gregtech.integration.jei.recipe.primitive; - -import gregtech.api.recipes.CountableIngredient; -import gregtech.api.recipes.recipes.CokeOvenRecipe; -import gregtech.api.unification.OreDictUnifier; -import mezz.jei.api.ingredients.IIngredients; -import mezz.jei.api.ingredients.VanillaTypes; -import mezz.jei.api.recipe.IRecipeWrapper; -import net.minecraft.client.Minecraft; -import net.minecraft.client.resources.I18n; -import net.minecraft.item.ItemStack; -import net.minecraftforge.fluids.FluidStack; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.stream.Collectors; - -public class CokeOvenRecipeWrapper implements IRecipeWrapper { - - private final CokeOvenRecipe recipe; - private final List> matchingInputs = new ArrayList<>(); - private final List outputs = new ArrayList<>(); - private final List fluidOutputs = new ArrayList<>(); - - public CokeOvenRecipeWrapper(CokeOvenRecipe recipe) { - this.recipe = recipe; - CountableIngredient ingredient = recipe.getInput(); - - List ingredientValues = Arrays.stream(ingredient.getIngredient().getMatchingStacks()) - .map(ItemStack::copy) - .sorted(OreDictUnifier.getItemStackComparator()) - .collect(Collectors.toList()); - ingredientValues.forEach(stack -> stack.setCount(ingredient.getCount())); - - this.matchingInputs.add(ingredientValues); - this.outputs.add(recipe.getOutput()); - this.fluidOutputs.add(recipe.getFluidOutput()); - } - - @Override - public void getIngredients(IIngredients ingredients) { - ingredients.setInputLists(VanillaTypes.ITEM, this.matchingInputs); - ingredients.setOutputs(VanillaTypes.ITEM, this.outputs); - ingredients.setOutputs(VanillaTypes.FLUID, this.fluidOutputs); - } - - @Override - public void drawInfo(Minecraft minecraft, int recipeWidth, int recipeHeight, int mouseX, int mouseY) { - minecraft.fontRenderer.drawString(I18n.format("gregtech.recipe.duration", this.recipe.getDuration() / 20f), 0, 60, 0x111111); - } - -} diff --git a/src/main/java/gregtech/integration/jei/recipe/primitive/MaterialTree.java b/src/main/java/gregtech/integration/jei/recipe/primitive/MaterialTree.java new file mode 100644 index 00000000000..46e7e653e29 --- /dev/null +++ b/src/main/java/gregtech/integration/jei/recipe/primitive/MaterialTree.java @@ -0,0 +1,123 @@ +package gregtech.integration.jei.recipe.primitive; + +import com.google.common.collect.ImmutableList; +import gregtech.api.unification.OreDictUnifier; +import gregtech.api.unification.material.Material; +import gregtech.api.unification.material.properties.PropertyKey; +import gregtech.api.unification.ore.OrePrefix; +import mezz.jei.api.ingredients.IIngredients; +import mezz.jei.api.ingredients.VanillaTypes; +import mezz.jei.api.recipe.IRecipeWrapper; +import net.minecraft.item.ItemStack; +import net.minecraftforge.fluids.FluidStack; + +import java.util.List; +import java.util.ArrayList; + +public class MaterialTree implements IRecipeWrapper { + private final static ImmutableList PREFIXES = ImmutableList.of( + OrePrefix.dustTiny, + OrePrefix.dust, + OrePrefix.dustSmall, + OrePrefix.cableGtSingle, + OrePrefix.ingotHot, + OrePrefix.ingot, + OrePrefix.gem, + OrePrefix.block, + OrePrefix.wireGtSingle, + OrePrefix.stick, + OrePrefix.nugget, + OrePrefix.plate, + OrePrefix.wireFine, + OrePrefix.frameGt, + OrePrefix.round, + OrePrefix.pipeNormalFluid, + OrePrefix.pipeNormalItem, + OrePrefix.screw, + OrePrefix.bolt, + OrePrefix.gear, + OrePrefix.plateDouble, + OrePrefix.spring, + OrePrefix.stickLong, + OrePrefix.gearSmall, + OrePrefix.plateDense, + OrePrefix.springSmall, + OrePrefix.ring, + // fluid, + OrePrefix.lens, + OrePrefix.foil + ); + + private final List> itemInputs = new ArrayList<>(); + private final List> fluidInputs = new ArrayList<>(); + + private final String name; + private final String formula; + private final int blastTemp; + private final long avgM; + private final long avgP; + private final long avgN; + + public MaterialTree(Material material) { + // adding an empty list to itemInputs/fluidInputs makes checking if a prefix exists later much easier + List inputDusts = new ArrayList<>(); + for (OrePrefix prefix : PREFIXES) { + inputDusts.add(OreDictUnifier.get(prefix, material)); + } + for (ItemStack stack : inputDusts) { + List matItemsStack = new ArrayList<>(); + matItemsStack.add(stack); + this.itemInputs.add(matItemsStack); + } + + List matFluidsStack = new ArrayList<>(); + if (material.hasProperty(PropertyKey.FLUID)) { + matFluidsStack.add(material.getFluid(1000)); + } + this.fluidInputs.add(matFluidsStack); + + name = material.getLocalizedName(); + formula = material.getChemicalFormula(); + avgM = material.getAverageMass(); + avgP = material.getAverageProtons(); + avgN = material.getAverageNeutrons(); + if (material.hasProperty(PropertyKey.BLAST)) { + blastTemp = material.getBlastTemperature(); + } else { + blastTemp = 0; + } + } + + @Override + public void getIngredients(IIngredients ingredients) { + ingredients.setInputLists(VanillaTypes.ITEM, this.itemInputs); + ingredients.setInputLists(VanillaTypes.FLUID, this.fluidInputs); + // these don't get displayed, but allow the material tree to show up on left *or* right click + ingredients.setOutputLists(VanillaTypes.ITEM, this.itemInputs); + ingredients.setOutputLists(VanillaTypes.FLUID, this.fluidInputs); + } + + public String getMaterialName() { + return name; + } + + public String getMaterialFormula() { + return formula; + } + + public long getAvgM() { + return avgM; + } + + public long getAvgP() { + return avgP; + } + + public long getAvgN() { + return avgN; + } + + public int getBlastTemp() { + return blastTemp; + } +} diff --git a/src/main/java/gregtech/integration/jei/recipe/primitive/MaterialTreeCategory.java b/src/main/java/gregtech/integration/jei/recipe/primitive/MaterialTreeCategory.java new file mode 100644 index 00000000000..0469becd8d1 --- /dev/null +++ b/src/main/java/gregtech/integration/jei/recipe/primitive/MaterialTreeCategory.java @@ -0,0 +1,290 @@ +package gregtech.integration.jei.recipe.primitive; + +import com.google.common.collect.ImmutableList; +import gregtech.api.GTValues; +import gregtech.api.gui.GuiTextures; +import gregtech.api.recipes.recipeproperties.BlastTemperatureProperty; +import gregtech.api.unification.OreDictUnifier; +import gregtech.api.unification.material.Materials; +import gregtech.api.unification.ore.OrePrefix; +import gregtech.integration.jei.utils.render.DrawableRegistry; +import mezz.jei.api.IGuiHelper; +import mezz.jei.api.gui.IDrawable; +import mezz.jei.api.gui.IGuiFluidStackGroup; +import mezz.jei.api.gui.IGuiItemStackGroup; +import mezz.jei.api.gui.IRecipeLayout; +import mezz.jei.api.ingredients.IIngredients; +import mezz.jei.api.ingredients.VanillaTypes; +import mezz.jei.api.recipe.IRecipeWrapper; +import net.minecraft.client.Minecraft; +import net.minecraft.client.resources.I18n; +import net.minecraft.item.ItemStack; +import net.minecraftforge.fluids.FluidStack; + +import javax.annotation.Nullable; +import java.util.List; +import java.util.ArrayList; + +public class MaterialTreeCategory extends PrimitiveRecipeCategory { + + protected String materialName; + protected String materialFormula; + protected int materialBFTemp; + protected String materialAvgM; + protected String materialAvgP; + protected String materialAvgN; + + protected final IDrawable slot; + protected final IDrawable icon; + protected final int FONT_HEIGHT = Minecraft.getMinecraft().fontRenderer.FONT_HEIGHT; + + protected List itemExists = new ArrayList<>(); + protected List fluidExists = new ArrayList<>(); + // XY positions of ingredients + protected final static ImmutableList ITEM_LOCATIONS = ImmutableList.of( + // corresponds pair-to-one with PREFIXES in MaterialTree.java + 4, 67, // dustTiny 0 + 4, 101, // dust + 4, 135, // dustSmall + 29, 55, // cableGtSingle + 29, 85, // ingotHot + 29, 117, // ingot 5 + 29, 117, // gem + 29, 147, // block + 54, 55, // wireGtSingle + 54, 85, // stick + 54, 117, // nugget 10 + 54, 147, // plate + 79, 55, // wireFine + 79, 85, // frameGt + 79, 117, // round + 79, 147, // pipeNormalFluid 15 + 79, 147, // pipeNormalItem + 104, 55, // screw + 104, 85, // bolt + 104, 117, // gear + 104, 147, // plateDouble 20 + 129, 55, // spring + 129, 85, // stickLong + 129, 117, // gearSmall + 129, 147, // plateDense + 154, 55, // springSmall 25 + 154, 78, // ring + 154, 124, // lens + 154, 147 // foil + ); + protected ImmutableList FLUID_LOCATIONS = ImmutableList.of( + 154, 101 // fluid + ); + + public MaterialTreeCategory(IGuiHelper guiHelper) { + super("material_tree", + "recipemap.materialtree.name", + guiHelper.createBlankDrawable(176, 166), + guiHelper); + + this.slot = guiHelper.drawableBuilder(GuiTextures.SLOT.imageLocation, 0, 0, 18, 18).setTextureSize(18, 18).build(); + this.icon = guiHelper.createDrawableIngredient(OreDictUnifier.get(OrePrefix.ingot, Materials.Aluminium)); + + /* couldn't think of a better way to register all these + generated with bash, requires imagemagick and sed + for file in ./*.png; do + dimstring=$(identify -ping -format '%w, %h' "$file") + basename "$file" .png | sed "s/\(.*\)/registerArrow(guiHelper, \"\1\", $dimstring);/" + done + */ + registerArrow(guiHelper, "2d12", 5, 12); + registerArrow(guiHelper, "2d16", 5, 16); + registerArrow(guiHelper, "2r16d37", 18, 40); + registerArrow(guiHelper, "d14", 5, 14); + registerArrow(guiHelper, "d7r25u6", 28, 7); + registerArrow(guiHelper, "d7r50d7", 53, 14); + registerArrow(guiHelper, "d7r50u6", 53, 7); + registerArrow(guiHelper, "d7r75d7", 78, 14); + registerArrow(guiHelper, "d7r75u6", 78, 7); + registerArrow(guiHelper, "d7r87u22r4", 92, 25); + registerArrow(guiHelper, "d7r87u46r4", 92, 49); + registerArrow(guiHelper, "l7", 7, 5); + registerArrow(guiHelper, "r3d16r4", 7, 19); + registerArrow(guiHelper, "r3d26r4", 7, 29); + registerArrow(guiHelper, "r3u15r4", 7, 18); + registerArrow(guiHelper, "r3u32r4", 7, 35); + registerArrow(guiHelper, "r3u57r4", 7, 60); + registerArrow(guiHelper, "r7", 7, 5); + registerArrow(guiHelper, "u12", 5, 12); + registerArrow(guiHelper, "u7r25d6", 28, 7); + registerArrow(guiHelper, "u7r50d6", 53, 7); + registerArrow(guiHelper, "u7r50u5", 53, 12); + registerArrow(guiHelper, "u7r75d6", 78, 7); + registerArrow(guiHelper, "u7r75u5", 78, 12); + registerArrow(guiHelper, "u7r87d15r4", 92, 18); + registerArrow(guiHelper, "u7r87u8r4", 92, 17); + } + + @Override + public void setRecipe(IRecipeLayout recipeLayout, MaterialTree recipeWrapper, IIngredients ingredients) { + // place and check existence of items + IGuiItemStackGroup itemStackGroup = recipeLayout.getItemStacks(); + List> itemInputs = ingredients.getInputs(VanillaTypes.ITEM); + itemExists.clear(); + for (int i = 0; i < ITEM_LOCATIONS.size(); i += 2) { + itemStackGroup.init(i, true, ITEM_LOCATIONS.get(i), ITEM_LOCATIONS.get(i + 1)); + itemExists.add(itemInputs.get(i / 2).size() > 0); + } + itemStackGroup.set(ingredients); + + // place and check existence of fluid(s) + IGuiFluidStackGroup fluidStackGroup = recipeLayout.getFluidStacks(); + List> fluidInputs = ingredients.getInputs(VanillaTypes.FLUID); + fluidExists.clear(); + for (int i = 0; i < FLUID_LOCATIONS.size(); i += 2) { + // fluids annoyingly need to be offset by 1 to fit in the slot graphic + fluidStackGroup.init(0, true, FLUID_LOCATIONS.get(i) + 1, FLUID_LOCATIONS.get(i + 1) + 1); + fluidExists.add(fluidInputs.get(i / 2).size() > 0); + } + fluidStackGroup.set(ingredients); + + // set info of current material + materialName = recipeWrapper.getMaterialName(); + materialFormula = recipeWrapper.getMaterialFormula(); + materialBFTemp = recipeWrapper.getBlastTemp(); + materialAvgM = I18n.format("gregtech.jei.materials.average_mass", recipeWrapper.getAvgM()); + materialAvgP = I18n.format("gregtech.jei.materials.average_protons", recipeWrapper.getAvgP()); + materialAvgN = I18n.format("gregtech.jei.materials.average_neutrons", recipeWrapper.getAvgN()); + } + + @Override + public IRecipeWrapper getRecipeWrapper(MaterialTree recipe) { + return recipe; + } + + @Nullable + @Override + public IDrawable getIcon() { + return icon; + } + + @Override + public void drawExtras(Minecraft minecraft) { + // item slot rendering + for (int i = 0; i < ITEM_LOCATIONS.size(); i += 2) { + if (itemExists.get(i / 2)) + this.slot.draw(minecraft, ITEM_LOCATIONS.get(i), ITEM_LOCATIONS.get(i + 1)); + } + + // fluid slot rendering + for (int i = 0; i < FLUID_LOCATIONS.size(); i += 2) { + if (fluidExists.get(i / 2)) + this.slot.draw(minecraft, FLUID_LOCATIONS.get(i), FLUID_LOCATIONS.get(i + 1)); + } + + // arrow rendering, aka hardcoded jank + // indeces are from ITEM_LOCATIONS / MaterialTree.PREFIXES + // dustTiny <-> dust + drawArrow(minecraft, "2d16", 10, 85, itemExists.get(0) && itemExists.get(1)); + // dust <-> dustSmall + drawArrow(minecraft, "2d16", 10, 119, itemExists.get(1) && itemExists.get(2)); + // dust <-> block (if no ingot or gem) + drawArrow(minecraft, "2r16d37", 22, 107, !itemExists.get(5) && + !itemExists.get(6) && itemExists.get(1) && itemExists.get(7)); + // dust -> ingotHot + drawArrow(minecraft, "r3u15r4", 22, 92, itemExists.get(1) && itemExists.get(4)); + // dust -> ingot/gem (if no ingotHot) + drawArrow(minecraft, "r3d16r4", 22, 109, !itemExists.get(4) && + itemExists.get(1) && (itemExists.get(5) || itemExists.get(6))); + // ingotHot -> ingot + drawArrow(minecraft, "d14", 35, 103, itemExists.get(4) && itemExists.get(5)); + // ingot/gem <-> block + drawArrow(minecraft, "2d12", 35, 135, itemExists.get(7) && + (itemExists.get(5) || itemExists.get(6))); + // ingot -> wireGtSingle + drawArrow(minecraft, "r3u57r4", 47, 66, itemExists.get(5) && itemExists.get(8)); + // ingot/gem -> stick + drawArrow(minecraft, "r3u32r4", 47, 91, itemExists.get(9) && + (itemExists.get(5) || itemExists.get(6))); + // ingot -> nugget + drawArrow(minecraft, "r7", 47, 123, itemExists.get(5) && itemExists.get(10)); + // ingot -> plate + drawArrow(minecraft, "r3d26r4", 47, 125, itemExists.get(5) && itemExists.get(11)); + // block -> plate + drawArrow(minecraft, "r7", 47, 158, itemExists.get(7) && itemExists.get(11)); + // wireGtSingle -> cableGtSingle + drawArrow(minecraft, "l7", 47, 57, itemExists.get(8) && itemExists.get(3)); + // wireGtSingle -> wireFine + drawArrow(minecraft, "r7", 72, 61, itemExists.get(8) && itemExists.get(12)); + // stick -> frameGt + drawArrow(minecraft, "d7r25u6", 62, 103, itemExists.get(9) && itemExists.get(13)); + // stick -> bolt + drawArrow(minecraft, "d7r50u6", 62, 103, itemExists.get(9) && itemExists.get(18)); + // stick -> gear + drawArrow(minecraft, "d7r50d7", 62, 103, itemExists.get(9) && itemExists.get(19)); + // stick -> stickLong + drawArrow(minecraft, "d7r75u6", 62, 103, itemExists.get(9) && itemExists.get(22)); + // stick -> gearSmall + drawArrow(minecraft, "d7r75d7", 62, 103, itemExists.get(9) && itemExists.get(23)); + // stick -> springSmall + drawArrow(minecraft, "d7r87u46r4", 62, 61, itemExists.get(9) && itemExists.get(25)); + // stick -> ring + drawArrow(minecraft, "d7r87u22r4", 62, 85, itemExists.get(9) && itemExists.get(26)); + // nugget -> round + drawArrow(minecraft, "r7", 72, 123, itemExists.get(10) && itemExists.get(14)); + // plate -> pipeNormalFluid/pipeNormalItem + drawArrow(minecraft, "u7r25d6", 62, 140, itemExists.get(11) && + (itemExists.get(15) || itemExists.get(16))); + // plate -> gear + drawArrow(minecraft, "u7r50u5", 62, 135, itemExists.get(11) && itemExists.get(19)); + // plate -> plateDouble + drawArrow(minecraft, "u7r50d6", 62, 140, itemExists.get(11) && itemExists.get(20)); + // plate -> gearSmall + drawArrow(minecraft, "u7r75u5", 62, 135, itemExists.get(11) && itemExists.get(23)); + // plate -> plateDense + drawArrow(minecraft, "u7r75d6", 62, 140, itemExists.get(11) && itemExists.get(24)); + // plate -> lens + drawArrow(minecraft, "u7r87u8r4", 62, 130, itemExists.get(11) && itemExists.get(27)); + // plate -> foil + drawArrow(minecraft, "u7r87d15r4", 62, 140, itemExists.get(11) && itemExists.get(28)); + // bolt -> screw + drawArrow(minecraft, "u12", 110, 73, itemExists.get(18) && itemExists.get(17)); + // stickLong -> spring + drawArrow(minecraft, "u12", 135, 73, itemExists.get(22) && itemExists.get(21)); + + // material info rendering + int linesDrawn = 0; + if (minecraft.fontRenderer.getStringWidth(materialName) > 176) { + minecraft.fontRenderer.drawString(minecraft.fontRenderer.trimStringToWidth(materialName, 171) + "...", + 0, 0, 0x111111); + linesDrawn++; + } else if (materialName.length() != 0) { + minecraft.fontRenderer.drawString(materialName, 0, 0, 0x111111); + linesDrawn++; + } + if (minecraft.fontRenderer.getStringWidth(materialFormula) > 176) { + minecraft.fontRenderer.drawString(minecraft.fontRenderer.trimStringToWidth(materialFormula, 171) + "...", + 0, FONT_HEIGHT * linesDrawn, 0x111111); + linesDrawn++; + } else if (materialFormula.length() != 0) { + minecraft.fontRenderer.drawString(materialFormula, 0, FONT_HEIGHT * linesDrawn, 0x111111); + linesDrawn++; + } + // don't think theres a good way to get the coil tier other than this + if (materialBFTemp != 0) { + BlastTemperatureProperty.getInstance().drawInfo(minecraft, 0, FONT_HEIGHT * linesDrawn, 0x111111, materialBFTemp); + linesDrawn++; + } + minecraft.fontRenderer.drawString(materialAvgM, 0, FONT_HEIGHT * linesDrawn, 0x111111); + linesDrawn++; + minecraft.fontRenderer.drawString(materialAvgN, 0, FONT_HEIGHT * linesDrawn, 0x111111); + linesDrawn++; + minecraft.fontRenderer.drawString(materialAvgP, 0, FONT_HEIGHT * linesDrawn, 0x111111); + } + + // a couple wrappers to make the code look less terrible + private void registerArrow(IGuiHelper guiHelper, String name, int width, int height) { + DrawableRegistry.initDrawable(guiHelper, GTValues.MODID + ":textures/gui/arrows/" + name + ".png", width, height, name); + } + + private void drawArrow(Minecraft minecraft, String name, int x, int y, boolean shown) { + if (shown) + DrawableRegistry.drawDrawable(minecraft, name, x, y); + } +} diff --git a/src/main/java/gregtech/integration/jei/recipe/primitive/PrimitiveBlastRecipeCategory.java b/src/main/java/gregtech/integration/jei/recipe/primitive/PrimitiveBlastRecipeCategory.java deleted file mode 100644 index b6156b9bb55..00000000000 --- a/src/main/java/gregtech/integration/jei/recipe/primitive/PrimitiveBlastRecipeCategory.java +++ /dev/null @@ -1,55 +0,0 @@ -package gregtech.integration.jei.recipe.primitive; - -import gregtech.api.gui.GuiTextures; -import gregtech.api.recipes.recipes.PrimitiveBlastFurnaceRecipe; -import mezz.jei.api.IGuiHelper; -import mezz.jei.api.gui.IDrawable; -import mezz.jei.api.gui.IGuiItemStackGroup; -import mezz.jei.api.gui.IRecipeLayout; -import mezz.jei.api.ingredients.IIngredients; -import mezz.jei.api.recipe.IRecipeWrapper; -import net.minecraft.client.Minecraft; - -import javax.annotation.Nonnull; - -public class PrimitiveBlastRecipeCategory extends PrimitiveRecipeCategory { - - protected final IDrawable slot; - protected final IDrawable progressBar; - - public PrimitiveBlastRecipeCategory(IGuiHelper guiHelper) { - super("primitive_blast_furnace", - "gregtech.machine.primitive_blast_furnace.bronze.name", - guiHelper.createBlankDrawable(140, 60), guiHelper); - - this.slot = guiHelper.drawableBuilder(GuiTextures.SLOT.imageLocation, 0, 0, 18, 18).setTextureSize(18, 18).build(); - this.progressBar = guiHelper.drawableBuilder(GuiTextures.BRONZE_BLAST_FURNACE_PROGRESS_BAR.imageLocation, 0, 0, 20, 15).setTextureSize(20, 30).build(); - } - - @Override - public void setRecipe(IRecipeLayout recipeLayout, @Nonnull PrimitiveBlastRecipeWrapper recipeWrapper, - @Nonnull IIngredients ingredients) { - IGuiItemStackGroup itemStackGroup = recipeLayout.getItemStacks(); - itemStackGroup.init(0, true, 32, 4); - itemStackGroup.init(1, true, 32, 22); - - itemStackGroup.init(2, false, 84, 13); - itemStackGroup.init(3, false, 102, 13); - itemStackGroup.set(ingredients); - } - - @Nonnull - @Override - public IRecipeWrapper getRecipeWrapper(@Nonnull PrimitiveBlastFurnaceRecipe recipe) { - return new PrimitiveBlastRecipeWrapper(recipe); - } - - @Override - public void drawExtras(Minecraft minecraft) { - this.slot.draw(minecraft, 32, 4); - this.slot.draw(minecraft, 32, 22); - this.slot.draw(minecraft, 84, 13); - this.slot.draw(minecraft, 102, 13); - this.progressBar.draw(minecraft, 57, 14); - } -} diff --git a/src/main/java/gregtech/integration/jei/recipe/primitive/PrimitiveBlastRecipeWrapper.java b/src/main/java/gregtech/integration/jei/recipe/primitive/PrimitiveBlastRecipeWrapper.java deleted file mode 100644 index 1f39349b4de..00000000000 --- a/src/main/java/gregtech/integration/jei/recipe/primitive/PrimitiveBlastRecipeWrapper.java +++ /dev/null @@ -1,57 +0,0 @@ -package gregtech.integration.jei.recipe.primitive; - -import com.google.common.collect.ImmutableList; -import gregtech.api.recipes.CountableIngredient; -import gregtech.api.recipes.recipes.PrimitiveBlastFurnaceRecipe; -import gregtech.api.unification.OreDictUnifier; -import gregtech.common.metatileentities.multi.MetaTileEntityPrimitiveBlastFurnace; -import mezz.jei.api.ingredients.IIngredients; -import mezz.jei.api.ingredients.VanillaTypes; -import mezz.jei.api.recipe.IRecipeWrapper; -import net.minecraft.client.Minecraft; -import net.minecraft.client.resources.I18n; -import net.minecraft.item.ItemStack; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.stream.Collectors; - -public class PrimitiveBlastRecipeWrapper implements IRecipeWrapper { - - private final PrimitiveBlastFurnaceRecipe recipe; - private final List> matchingInputs = new ArrayList<>(); - private final List> outputs = new ArrayList<>(); - - public PrimitiveBlastRecipeWrapper(PrimitiveBlastFurnaceRecipe recipe) { - this.recipe = recipe; - CountableIngredient ingredient = recipe.getInput(); - - List ingredientValues = Arrays.stream(ingredient.getIngredient().getMatchingStacks()) - .map(ItemStack::copy) - .sorted(OreDictUnifier.getItemStackComparator()) - .collect(Collectors.toList()); - ingredientValues.forEach(stack -> stack.setCount(ingredient.getCount())); - - this.matchingInputs.add(ingredientValues); - - List displayFuelStacks = MetaTileEntityPrimitiveBlastFurnace.getDisplayFuelsForRecipe(recipe.getFuelAmount()); - this.matchingInputs.add(displayFuelStacks); - - ItemStack ashesItemStack = MetaTileEntityPrimitiveBlastFurnace.getAshForRecipeFuelConsumption(recipe.getFuelAmount()); - this.outputs.add(ImmutableList.of(recipe.getOutput())); - this.outputs.add(ImmutableList.of(ashesItemStack)); - } - - @Override - public void getIngredients(IIngredients ingredients) { - ingredients.setInputLists(VanillaTypes.ITEM, this.matchingInputs); - ingredients.setOutputLists(VanillaTypes.ITEM, this.outputs); - } - - @Override - public void drawInfo(Minecraft minecraft, int recipeWidth, int recipeHeight, int mouseX, int mouseY) { - minecraft.fontRenderer.drawString(I18n.format("gregtech.recipe.duration", this.recipe.getDuration() / 20f), 0, 55, 0x111111); - } - -} diff --git a/src/main/java/gregtech/integration/jei/recipe/primitive/PrimitiveRecipeCategory.java b/src/main/java/gregtech/integration/jei/recipe/primitive/PrimitiveRecipeCategory.java index 3ecd7654e0b..4f2c691c6ad 100644 --- a/src/main/java/gregtech/integration/jei/recipe/primitive/PrimitiveRecipeCategory.java +++ b/src/main/java/gregtech/integration/jei/recipe/primitive/PrimitiveRecipeCategory.java @@ -14,6 +14,7 @@ import java.util.Collections; import java.util.List; +// TODO Should be renamed to "BasicRecipeCategory" public abstract class PrimitiveRecipeCategory implements IRecipeCategory, IRecipeWrapperFactory { public final String uniqueName; diff --git a/src/main/java/gregtech/integration/jei/utils/render/DrawableRegistry.java b/src/main/java/gregtech/integration/jei/utils/render/DrawableRegistry.java new file mode 100644 index 00000000000..8d5cf5d12c2 --- /dev/null +++ b/src/main/java/gregtech/integration/jei/utils/render/DrawableRegistry.java @@ -0,0 +1,24 @@ +package gregtech.integration.jei.utils.render; + +import mezz.jei.api.IGuiHelper; +import mezz.jei.api.gui.IDrawable; +import net.minecraft.client.Minecraft; +import net.minecraft.util.ResourceLocation; + +import java.util.Map; +import java.util.HashMap; + +/** + * HashMap of IDrawables for JEI rendering + */ +public class DrawableRegistry { + private static final Map drawableMap = new HashMap<>(); + + public static void initDrawable(IGuiHelper guiHelper, String textureLocation, int width, int height, String key) { + drawableMap.put(key, guiHelper.drawableBuilder(new ResourceLocation(textureLocation), 0, 0, width, height).setTextureSize(width, height).build()); + } + + public static void drawDrawable(Minecraft minecraft, String key, int x, int y) { + drawableMap.get(key).draw(minecraft, x, y); + } +} diff --git a/src/main/java/gregtech/integration/theoneprobe/TheOneProbeCompatibility.java b/src/main/java/gregtech/integration/theoneprobe/TheOneProbeCompatibility.java index 4ead093c8fd..0dc64e1808a 100644 --- a/src/main/java/gregtech/integration/theoneprobe/TheOneProbeCompatibility.java +++ b/src/main/java/gregtech/integration/theoneprobe/TheOneProbeCompatibility.java @@ -14,6 +14,7 @@ public static void registerCompatibility() { oneProbe.registerProvider(new ControllableInfoProvider()); oneProbe.registerProvider(new DebugPipeNetInfoProvider()); oneProbe.registerProvider(new TransformerInfoProvider()); + oneProbe.registerProvider(new DiodeInfoProvider()); oneProbe.registerProvider(new MultiblockInfoProvider()); } } diff --git a/src/main/java/gregtech/integration/theoneprobe/provider/DebugPipeNetInfoProvider.java b/src/main/java/gregtech/integration/theoneprobe/provider/DebugPipeNetInfoProvider.java index 6624bcc8cac..33c6305b962 100644 --- a/src/main/java/gregtech/integration/theoneprobe/provider/DebugPipeNetInfoProvider.java +++ b/src/main/java/gregtech/integration/theoneprobe/provider/DebugPipeNetInfoProvider.java @@ -58,11 +58,11 @@ public void addProbeInfo(ProbeMode mode, IProbeInfo probeInfo, EntityPlayer play probeInfo.text(builder.toString()); } probeInfo.text("tile open: " + pipeTile.getOpenConnections()); - if (blockPipe instanceof BlockFluidPipe) { + /*if (blockPipe instanceof BlockFluidPipe) { if (pipeTile instanceof TileEntityFluidPipeTickable) { probeInfo.text("tile active: " + ((TileEntityFluidPipeTickable) pipeTile).isActive()); } - } + }*/ } } } diff --git a/src/main/java/gregtech/integration/theoneprobe/provider/DiodeInfoProvider.java b/src/main/java/gregtech/integration/theoneprobe/provider/DiodeInfoProvider.java new file mode 100644 index 00000000000..395bbf62779 --- /dev/null +++ b/src/main/java/gregtech/integration/theoneprobe/provider/DiodeInfoProvider.java @@ -0,0 +1,39 @@ +package gregtech.integration.theoneprobe.provider; + +import gregtech.api.capability.IEnergyContainer; +import gregtech.api.metatileentity.MetaTileEntity; +import gregtech.api.metatileentity.MetaTileEntityHolder; +import gregtech.common.metatileentities.electric.MetaTileEntityDiode; +import mcjty.theoneprobe.api.ElementAlignment; +import mcjty.theoneprobe.api.IProbeInfo; +import mcjty.theoneprobe.api.TextStyleClass; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.EnumFacing; + +public class DiodeInfoProvider extends ElectricContainerInfoProvider { + + @Override + public String getID() { + return "gregtech:diode_info_provider"; + } + + @Override + protected void addProbeInfo(IEnergyContainer capability, IProbeInfo probeInfo, TileEntity tileEntity, EnumFacing sideHit) { + if (tileEntity instanceof MetaTileEntityHolder) { + MetaTileEntity metaTileEntity = ((MetaTileEntityHolder) tileEntity).getMetaTileEntity(); + if (metaTileEntity instanceof MetaTileEntityDiode) { + long inputAmperage = capability.getInputAmperage(); + long outputAmperage = capability.getOutputAmperage(); + IProbeInfo horizontalPane = probeInfo.vertical(probeInfo.defaultLayoutStyle().alignment(ElementAlignment.ALIGN_CENTER)); + String transformInfo; + if (capability.inputsEnergy(sideHit)) { + transformInfo = "{*gregtech.top.transform_input*} " + inputAmperage + "A"; + horizontalPane.text(TextStyleClass.INFO + transformInfo); + } else if (capability.outputsEnergy(sideHit)) { + transformInfo = "{*gregtech.top.transform_output*} " + outputAmperage + "A"; + horizontalPane.text(TextStyleClass.INFO + transformInfo); + } + } + } + } +} diff --git a/src/main/java/gregtech/loaders/dungeon/DungeonLootLoader.java b/src/main/java/gregtech/loaders/dungeon/DungeonLootLoader.java index 1ba81ec1c54..4090857eccb 100644 --- a/src/main/java/gregtech/loaders/dungeon/DungeonLootLoader.java +++ b/src/main/java/gregtech/loaders/dungeon/DungeonLootLoader.java @@ -13,8 +13,83 @@ public class DungeonLootLoader { public static void init() { - GTLog.logger.info("Registering dungeon loot..."); - ChestGenHooks.init(); + if (ConfigHolder.UnofficialOptions.addLoot || ConfigHolder.increaseDungeonLoot) { + GTLog.logger.info("Registering dungeon loot..."); + ChestGenHooks.init(); + } + if (ConfigHolder.UnofficialOptions.addLoot) { + ChestGenHooks.addItem(LootTableList.CHESTS_SPAWN_BONUS_CHEST, MetaItems.BOTTLE_PURPLE_DRINK.getStackForm(), 8, 16, 2); + + ChestGenHooks.addItem(LootTableList.CHESTS_SIMPLE_DUNGEON, MetaItems.BOTTLE_PURPLE_DRINK.getStackForm(), 8, 16, 40); + ChestGenHooks.addItem(LootTableList.CHESTS_SIMPLE_DUNGEON, OreDictUnifier.get(OrePrefix.ingot, Materials.Silver, 1), 1, 6, 30); + ChestGenHooks.addItem(LootTableList.CHESTS_SIMPLE_DUNGEON, OreDictUnifier.get(OrePrefix.ingot, Materials.Lead, 1), 1, 6, 7); + ChestGenHooks.addItem(LootTableList.CHESTS_SIMPLE_DUNGEON, OreDictUnifier.get(OrePrefix.ingot, Materials.Steel, 1), 1, 6, 15); + ChestGenHooks.addItem(LootTableList.CHESTS_SIMPLE_DUNGEON, OreDictUnifier.get(OrePrefix.ingot, Materials.Bronze, 1), 1, 6, 15); + ChestGenHooks.addItem(LootTableList.CHESTS_SIMPLE_DUNGEON, OreDictUnifier.get(OrePrefix.ingot, Materials.Manganese, 1), 1, 6, 15); + ChestGenHooks.addItem(LootTableList.CHESTS_SIMPLE_DUNGEON, OreDictUnifier.get(OrePrefix.ingot, Materials.DamascusSteel, 1), 1, 6, 5); + ChestGenHooks.addItem(LootTableList.CHESTS_SIMPLE_DUNGEON, OreDictUnifier.get(OrePrefix.gem, Materials.Vinteum, 1), 2, 5, 3); + ChestGenHooks.addItem(LootTableList.CHESTS_SIMPLE_DUNGEON, OreDictUnifier.get(OrePrefix.gem, Materials.Emerald, 1), 1, 6, 5); + ChestGenHooks.addItem(LootTableList.CHESTS_SIMPLE_DUNGEON, OreDictUnifier.get(OrePrefix.gem, Materials.Ruby, 1), 1, 6, 5); + ChestGenHooks.addItem(LootTableList.CHESTS_SIMPLE_DUNGEON, OreDictUnifier.get(OrePrefix.gem, Materials.Sapphire, 1), 1, 6, 5); + ChestGenHooks.addItem(LootTableList.CHESTS_SIMPLE_DUNGEON, OreDictUnifier.get(OrePrefix.gem, Materials.GreenSapphire, 1), 1, 6, 5); + ChestGenHooks.addItem(LootTableList.CHESTS_SIMPLE_DUNGEON, OreDictUnifier.get(OrePrefix.gem, Materials.Olivine, 1), 1, 6, 5); + ChestGenHooks.addItem(LootTableList.CHESTS_SIMPLE_DUNGEON, OreDictUnifier.get(OrePrefix.gem, Materials.GarnetRed, 1), 1, 6, 10); + ChestGenHooks.addItem(LootTableList.CHESTS_SIMPLE_DUNGEON, OreDictUnifier.get(OrePrefix.gem, Materials.GarnetYellow, 1), 1, 6, 10); + ChestGenHooks.addItem(LootTableList.CHESTS_SIMPLE_DUNGEON, OreDictUnifier.get(OrePrefix.dust, Materials.Aluminium, 1), 1, 6, 10); + ChestGenHooks.addItem(LootTableList.CHESTS_SIMPLE_DUNGEON, OreDictUnifier.get(OrePrefix.dust, Materials.Neodymium, 1), 1, 6, 10); + ChestGenHooks.addItem(LootTableList.CHESTS_SIMPLE_DUNGEON, OreDictUnifier.get(OrePrefix.dust, Materials.Chrome, 1), 1, 3, 10); + + ChestGenHooks.addItem(LootTableList.CHESTS_DESERT_PYRAMID, OreDictUnifier.get(OrePrefix.ingot, Materials.Silver, 1), 4, 16, 6); + ChestGenHooks.addItem(LootTableList.CHESTS_DESERT_PYRAMID, OreDictUnifier.get(OrePrefix.ingot, Materials.Platinum, 1), 2, 8, 3); + ChestGenHooks.addItem(LootTableList.CHESTS_DESERT_PYRAMID, OreDictUnifier.get(OrePrefix.gem, Materials.Ruby, 1), 2, 8, 1); + ChestGenHooks.addItem(LootTableList.CHESTS_DESERT_PYRAMID, OreDictUnifier.get(OrePrefix.gem, Materials.Sapphire, 1), 2, 8, 3); + ChestGenHooks.addItem(LootTableList.CHESTS_DESERT_PYRAMID, OreDictUnifier.get(OrePrefix.gem, Materials.GreenSapphire, 1), 2, 8, 4); + ChestGenHooks.addItem(LootTableList.CHESTS_DESERT_PYRAMID, OreDictUnifier.get(OrePrefix.gem, Materials.Olivine, 1), 2, 8, 4); + ChestGenHooks.addItem(LootTableList.CHESTS_DESERT_PYRAMID, OreDictUnifier.get(OrePrefix.gem, Materials.GarnetRed, 1), 2, 8, 3); + ChestGenHooks.addItem(LootTableList.CHESTS_DESERT_PYRAMID, OreDictUnifier.get(OrePrefix.gem, Materials.GarnetYellow, 1), 2, 8, 3); + + ChestGenHooks.addItem(LootTableList.CHESTS_JUNGLE_TEMPLE, MetaItems.COIN_GOLD_ANCIENT.getStackForm(), 16, 64, 5); + ChestGenHooks.addItem(LootTableList.CHESTS_JUNGLE_TEMPLE, MetaItems.ZERO_POINT_MODULE.getChargedStack(Long.MAX_VALUE), 1, 1, 1); + ChestGenHooks.addItem(LootTableList.CHESTS_JUNGLE_TEMPLE, OreDictUnifier.get(OrePrefix.ingot, Materials.Bronze, 1), 4, 16, 12); + ChestGenHooks.addItem(LootTableList.CHESTS_JUNGLE_TEMPLE, OreDictUnifier.get(OrePrefix.gem, Materials.Ruby, 1), 2, 8, 2); + ChestGenHooks.addItem(LootTableList.CHESTS_JUNGLE_TEMPLE, OreDictUnifier.get(OrePrefix.gem, Materials.Sapphire, 1), 2, 8, 2); + ChestGenHooks.addItem(LootTableList.CHESTS_JUNGLE_TEMPLE, OreDictUnifier.get(OrePrefix.gem, Materials.GreenSapphire, 1), 2, 8, 2); + ChestGenHooks.addItem(LootTableList.CHESTS_JUNGLE_TEMPLE, OreDictUnifier.get(OrePrefix.gem, Materials.Olivine, 1), 2, 8, 2); + ChestGenHooks.addItem(LootTableList.CHESTS_JUNGLE_TEMPLE, OreDictUnifier.get(OrePrefix.gem, Materials.GarnetRed, 1), 2, 8, 4); + ChestGenHooks.addItem(LootTableList.CHESTS_JUNGLE_TEMPLE, OreDictUnifier.get(OrePrefix.gem, Materials.GarnetYellow, 1), 2, 8, 4); + + ChestGenHooks.addItem(LootTableList.CHESTS_JUNGLE_TEMPLE_DISPENSER, new ItemStack(Items.FIRE_CHARGE, 1), 2, 7, 17); + + ChestGenHooks.addItem(LootTableList.CHESTS_ABANDONED_MINESHAFT, OreDictUnifier.get(OrePrefix.ingot, Materials.Silver, 1), 1, 4, 6); + ChestGenHooks.addItem(LootTableList.CHESTS_ABANDONED_MINESHAFT, OreDictUnifier.get(OrePrefix.ingot, Materials.Lead, 1), 1, 4, 3); + ChestGenHooks.addItem(LootTableList.CHESTS_ABANDONED_MINESHAFT, OreDictUnifier.get(OrePrefix.ingot, Materials.Steel, 1), 1, 4, 6); + ChestGenHooks.addItem(LootTableList.CHESTS_ABANDONED_MINESHAFT, OreDictUnifier.get(OrePrefix.ingot, Materials.Bronze, 1), 1, 4, 6); + ChestGenHooks.addItem(LootTableList.CHESTS_ABANDONED_MINESHAFT, OreDictUnifier.get(OrePrefix.gem, Materials.Sapphire, 1), 1, 4, 2); + ChestGenHooks.addItem(LootTableList.CHESTS_ABANDONED_MINESHAFT, OreDictUnifier.get(OrePrefix.gem, Materials.GreenSapphire, 1), 1, 4, 2); + ChestGenHooks.addItem(LootTableList.CHESTS_ABANDONED_MINESHAFT, OreDictUnifier.get(OrePrefix.gem, Materials.Olivine, 1), 1, 4, 2); + ChestGenHooks.addItem(LootTableList.CHESTS_ABANDONED_MINESHAFT, OreDictUnifier.get(OrePrefix.gem, Materials.GarnetRed, 1), 1, 4, 4); + ChestGenHooks.addItem(LootTableList.CHESTS_ABANDONED_MINESHAFT, OreDictUnifier.get(OrePrefix.gem, Materials.GarnetYellow, 1), 1, 4, 4); + ChestGenHooks.addItem(LootTableList.CHESTS_ABANDONED_MINESHAFT, OreDictUnifier.get(OrePrefix.gem, Materials.Ruby, 1), 1, 4, 2); + ChestGenHooks.addItem(LootTableList.CHESTS_ABANDONED_MINESHAFT, OreDictUnifier.get(OrePrefix.gem, Materials.Emerald, 1), 1, 4, 2); + ChestGenHooks.addItem(LootTableList.CHESTS_ABANDONED_MINESHAFT, OreDictUnifier.get(OrePrefix.toolHeadPickaxe, Materials.DamascusSteel, 1), 1, 4, 1); + ChestGenHooks.addItem(LootTableList.CHESTS_ABANDONED_MINESHAFT, OreDictUnifier.get(OrePrefix.toolHeadShovel, Materials.DamascusSteel, 1), 1, 4, 1); + ChestGenHooks.addItem(LootTableList.CHESTS_ABANDONED_MINESHAFT, OreDictUnifier.get(OrePrefix.toolHeadPickaxe, Materials.Vinteum, 1), 1, 2, 2); + ChestGenHooks.addItem(LootTableList.CHESTS_ABANDONED_MINESHAFT, OreDictUnifier.get(OrePrefix.toolHeadShovel, Materials.Vinteum, 1), 1, 2, 2); + + ChestGenHooks.addItem(LootTableList.CHESTS_VILLAGE_BLACKSMITH, OreDictUnifier.get(OrePrefix.dust, Materials.Chrome, 1), 1, 4, 3); + ChestGenHooks.addItem(LootTableList.CHESTS_VILLAGE_BLACKSMITH, OreDictUnifier.get(OrePrefix.dust, Materials.Neodymium, 1), 2, 8, 3); + ChestGenHooks.addItem(LootTableList.CHESTS_VILLAGE_BLACKSMITH, OreDictUnifier.get(OrePrefix.ingot, Materials.Manganese, 1), 2, 8, 6); + ChestGenHooks.addItem(LootTableList.CHESTS_VILLAGE_BLACKSMITH, OreDictUnifier.get(OrePrefix.ingot, Materials.Steel, 1), 4, 12, 6); + ChestGenHooks.addItem(LootTableList.CHESTS_VILLAGE_BLACKSMITH, OreDictUnifier.get(OrePrefix.ingot, Materials.Bronze, 1), 4, 12, 6); + ChestGenHooks.addItem(LootTableList.CHESTS_VILLAGE_BLACKSMITH, OreDictUnifier.get(OrePrefix.ingot, Materials.Brass, 1), 4, 12, 6); + ChestGenHooks.addItem(LootTableList.CHESTS_VILLAGE_BLACKSMITH, OreDictUnifier.get(OrePrefix.ingot, Materials.DamascusSteel, 1), 4, 12, 3); + ChestGenHooks.addItem(LootTableList.CHESTS_VILLAGE_BLACKSMITH, OreDictUnifier.get(OrePrefix.gem, Materials.Vinteum, 1), 3, 10, 2); + + ChestGenHooks.addItem(LootTableList.CHESTS_STRONGHOLD_CORRIDOR, OreDictUnifier.get(OrePrefix.toolHeadSword, Materials.DamascusSteel, 1), 1, 4, 4); + ChestGenHooks.addItem(LootTableList.CHESTS_STRONGHOLD_CORRIDOR, OreDictUnifier.get(OrePrefix.toolHeadAxe, Materials.DamascusSteel, 1), 1, 4, 4); + ChestGenHooks.addItem(LootTableList.CHESTS_STRONGHOLD_CORRIDOR, OreDictUnifier.get(OrePrefix.toolHeadPickaxe, Materials.Vinteum, 1), 1, 2, 3); + ChestGenHooks.addItem(LootTableList.CHESTS_STRONGHOLD_CORRIDOR, OreDictUnifier.get(OrePrefix.toolHeadShovel, Materials.Vinteum, 1), 1, 2, 3); + } if (ConfigHolder.increaseDungeonLoot) { ChestGenHooks.addRolls(LootTableList.CHESTS_SPAWN_BONUS_CHEST, 2, 4); ChestGenHooks.addRolls(LootTableList.CHESTS_SIMPLE_DUNGEON, 1, 3); @@ -27,78 +102,6 @@ public static void init() { ChestGenHooks.addRolls(LootTableList.CHESTS_STRONGHOLD_CORRIDOR, 2, 4); ChestGenHooks.addRolls(LootTableList.CHESTS_STRONGHOLD_LIBRARY, 4, 8); } - - ChestGenHooks.addItem(LootTableList.CHESTS_SPAWN_BONUS_CHEST, MetaItems.BOTTLE_PURPLE_DRINK.getStackForm(), 8, 16, 2); - - ChestGenHooks.addItem(LootTableList.CHESTS_SIMPLE_DUNGEON, MetaItems.BOTTLE_PURPLE_DRINK.getStackForm(), 8, 16, 40); - ChestGenHooks.addItem(LootTableList.CHESTS_SIMPLE_DUNGEON, OreDictUnifier.get(OrePrefix.ingot, Materials.Silver, 1), 1, 6, 30); - ChestGenHooks.addItem(LootTableList.CHESTS_SIMPLE_DUNGEON, OreDictUnifier.get(OrePrefix.ingot, Materials.Lead, 1), 1, 6, 7); - ChestGenHooks.addItem(LootTableList.CHESTS_SIMPLE_DUNGEON, OreDictUnifier.get(OrePrefix.ingot, Materials.Steel, 1), 1, 6, 15); - ChestGenHooks.addItem(LootTableList.CHESTS_SIMPLE_DUNGEON, OreDictUnifier.get(OrePrefix.ingot, Materials.Bronze, 1), 1, 6, 15); - ChestGenHooks.addItem(LootTableList.CHESTS_SIMPLE_DUNGEON, OreDictUnifier.get(OrePrefix.ingot, Materials.Manganese, 1), 1, 6, 15); - ChestGenHooks.addItem(LootTableList.CHESTS_SIMPLE_DUNGEON, OreDictUnifier.get(OrePrefix.ingot, Materials.DamascusSteel, 1), 1, 6, 5); - ChestGenHooks.addItem(LootTableList.CHESTS_SIMPLE_DUNGEON, OreDictUnifier.get(OrePrefix.gem, Materials.Vinteum, 1), 2, 5, 3); - ChestGenHooks.addItem(LootTableList.CHESTS_SIMPLE_DUNGEON, OreDictUnifier.get(OrePrefix.gem, Materials.Emerald, 1), 1, 6, 5); - ChestGenHooks.addItem(LootTableList.CHESTS_SIMPLE_DUNGEON, OreDictUnifier.get(OrePrefix.gem, Materials.Ruby, 1), 1, 6, 5); - ChestGenHooks.addItem(LootTableList.CHESTS_SIMPLE_DUNGEON, OreDictUnifier.get(OrePrefix.gem, Materials.Sapphire, 1), 1, 6, 5); - ChestGenHooks.addItem(LootTableList.CHESTS_SIMPLE_DUNGEON, OreDictUnifier.get(OrePrefix.gem, Materials.GreenSapphire, 1), 1, 6, 5); - ChestGenHooks.addItem(LootTableList.CHESTS_SIMPLE_DUNGEON, OreDictUnifier.get(OrePrefix.gem, Materials.Olivine, 1), 1, 6, 5); - ChestGenHooks.addItem(LootTableList.CHESTS_SIMPLE_DUNGEON, OreDictUnifier.get(OrePrefix.gem, Materials.GarnetRed, 1), 1, 6, 10); - ChestGenHooks.addItem(LootTableList.CHESTS_SIMPLE_DUNGEON, OreDictUnifier.get(OrePrefix.gem, Materials.GarnetYellow, 1), 1, 6, 10); - ChestGenHooks.addItem(LootTableList.CHESTS_SIMPLE_DUNGEON, OreDictUnifier.get(OrePrefix.dust, Materials.Aluminium, 1), 1, 6, 10); - ChestGenHooks.addItem(LootTableList.CHESTS_SIMPLE_DUNGEON, OreDictUnifier.get(OrePrefix.dust, Materials.Neodymium, 1), 1, 6, 10); - ChestGenHooks.addItem(LootTableList.CHESTS_SIMPLE_DUNGEON, OreDictUnifier.get(OrePrefix.dust, Materials.Chrome, 1), 1, 3, 10); - - ChestGenHooks.addItem(LootTableList.CHESTS_DESERT_PYRAMID, OreDictUnifier.get(OrePrefix.ingot, Materials.Silver, 1), 4, 16, 6); - ChestGenHooks.addItem(LootTableList.CHESTS_DESERT_PYRAMID, OreDictUnifier.get(OrePrefix.ingot, Materials.Platinum, 1), 2, 8, 3); - ChestGenHooks.addItem(LootTableList.CHESTS_DESERT_PYRAMID, OreDictUnifier.get(OrePrefix.gem, Materials.Ruby, 1), 2, 8, 1); - ChestGenHooks.addItem(LootTableList.CHESTS_DESERT_PYRAMID, OreDictUnifier.get(OrePrefix.gem, Materials.Sapphire, 1), 2, 8, 3); - ChestGenHooks.addItem(LootTableList.CHESTS_DESERT_PYRAMID, OreDictUnifier.get(OrePrefix.gem, Materials.GreenSapphire, 1), 2, 8, 4); - ChestGenHooks.addItem(LootTableList.CHESTS_DESERT_PYRAMID, OreDictUnifier.get(OrePrefix.gem, Materials.Olivine, 1), 2, 8, 4); - ChestGenHooks.addItem(LootTableList.CHESTS_DESERT_PYRAMID, OreDictUnifier.get(OrePrefix.gem, Materials.GarnetRed, 1), 2, 8, 3); - ChestGenHooks.addItem(LootTableList.CHESTS_DESERT_PYRAMID, OreDictUnifier.get(OrePrefix.gem, Materials.GarnetYellow, 1), 2, 8, 3); - - ChestGenHooks.addItem(LootTableList.CHESTS_JUNGLE_TEMPLE, MetaItems.COIN_GOLD_ANCIENT.getStackForm(), 16, 64, 5); - ChestGenHooks.addItem(LootTableList.CHESTS_JUNGLE_TEMPLE, MetaItems.ZERO_POINT_MODULE.getChargedStack(Long.MAX_VALUE), 1, 1, 1); - ChestGenHooks.addItem(LootTableList.CHESTS_JUNGLE_TEMPLE, OreDictUnifier.get(OrePrefix.ingot, Materials.Bronze, 1), 4, 16, 12); - ChestGenHooks.addItem(LootTableList.CHESTS_JUNGLE_TEMPLE, OreDictUnifier.get(OrePrefix.gem, Materials.Ruby, 1), 2, 8, 2); - ChestGenHooks.addItem(LootTableList.CHESTS_JUNGLE_TEMPLE, OreDictUnifier.get(OrePrefix.gem, Materials.Sapphire, 1), 2, 8, 2); - ChestGenHooks.addItem(LootTableList.CHESTS_JUNGLE_TEMPLE, OreDictUnifier.get(OrePrefix.gem, Materials.GreenSapphire, 1), 2, 8, 2); - ChestGenHooks.addItem(LootTableList.CHESTS_JUNGLE_TEMPLE, OreDictUnifier.get(OrePrefix.gem, Materials.Olivine, 1), 2, 8, 2); - ChestGenHooks.addItem(LootTableList.CHESTS_JUNGLE_TEMPLE, OreDictUnifier.get(OrePrefix.gem, Materials.GarnetRed, 1), 2, 8, 4); - ChestGenHooks.addItem(LootTableList.CHESTS_JUNGLE_TEMPLE, OreDictUnifier.get(OrePrefix.gem, Materials.GarnetYellow, 1), 2, 8, 4); - - ChestGenHooks.addItem(LootTableList.CHESTS_JUNGLE_TEMPLE_DISPENSER, new ItemStack(Items.FIRE_CHARGE, 1), 2, 7, 17); - - ChestGenHooks.addItem(LootTableList.CHESTS_ABANDONED_MINESHAFT, OreDictUnifier.get(OrePrefix.ingot, Materials.Silver, 1), 1, 4, 6); - ChestGenHooks.addItem(LootTableList.CHESTS_ABANDONED_MINESHAFT, OreDictUnifier.get(OrePrefix.ingot, Materials.Lead, 1), 1, 4, 3); - ChestGenHooks.addItem(LootTableList.CHESTS_ABANDONED_MINESHAFT, OreDictUnifier.get(OrePrefix.ingot, Materials.Steel, 1), 1, 4, 6); - ChestGenHooks.addItem(LootTableList.CHESTS_ABANDONED_MINESHAFT, OreDictUnifier.get(OrePrefix.ingot, Materials.Bronze, 1), 1, 4, 6); - ChestGenHooks.addItem(LootTableList.CHESTS_ABANDONED_MINESHAFT, OreDictUnifier.get(OrePrefix.gem, Materials.Sapphire, 1), 1, 4, 2); - ChestGenHooks.addItem(LootTableList.CHESTS_ABANDONED_MINESHAFT, OreDictUnifier.get(OrePrefix.gem, Materials.GreenSapphire, 1), 1, 4, 2); - ChestGenHooks.addItem(LootTableList.CHESTS_ABANDONED_MINESHAFT, OreDictUnifier.get(OrePrefix.gem, Materials.Olivine, 1), 1, 4, 2); - ChestGenHooks.addItem(LootTableList.CHESTS_ABANDONED_MINESHAFT, OreDictUnifier.get(OrePrefix.gem, Materials.GarnetRed, 1), 1, 4, 4); - ChestGenHooks.addItem(LootTableList.CHESTS_ABANDONED_MINESHAFT, OreDictUnifier.get(OrePrefix.gem, Materials.GarnetYellow, 1), 1, 4, 4); - ChestGenHooks.addItem(LootTableList.CHESTS_ABANDONED_MINESHAFT, OreDictUnifier.get(OrePrefix.gem, Materials.Ruby, 1), 1, 4, 2); - ChestGenHooks.addItem(LootTableList.CHESTS_ABANDONED_MINESHAFT, OreDictUnifier.get(OrePrefix.gem, Materials.Emerald, 1), 1, 4, 2); - ChestGenHooks.addItem(LootTableList.CHESTS_ABANDONED_MINESHAFT, OreDictUnifier.get(OrePrefix.toolHeadPickaxe, Materials.DamascusSteel, 1), 1, 4, 1); - ChestGenHooks.addItem(LootTableList.CHESTS_ABANDONED_MINESHAFT, OreDictUnifier.get(OrePrefix.toolHeadShovel, Materials.DamascusSteel, 1), 1, 4, 1); - ChestGenHooks.addItem(LootTableList.CHESTS_ABANDONED_MINESHAFT, OreDictUnifier.get(OrePrefix.toolHeadPickaxe, Materials.Vinteum, 1), 1, 2, 2); - ChestGenHooks.addItem(LootTableList.CHESTS_ABANDONED_MINESHAFT, OreDictUnifier.get(OrePrefix.toolHeadShovel, Materials.Vinteum, 1), 1, 2, 2); - - ChestGenHooks.addItem(LootTableList.CHESTS_VILLAGE_BLACKSMITH, OreDictUnifier.get(OrePrefix.dust, Materials.Chrome, 1), 1, 4, 3); - ChestGenHooks.addItem(LootTableList.CHESTS_VILLAGE_BLACKSMITH, OreDictUnifier.get(OrePrefix.dust, Materials.Neodymium, 1), 2, 8, 3); - ChestGenHooks.addItem(LootTableList.CHESTS_VILLAGE_BLACKSMITH, OreDictUnifier.get(OrePrefix.ingot, Materials.Manganese, 1), 2, 8, 6); - ChestGenHooks.addItem(LootTableList.CHESTS_VILLAGE_BLACKSMITH, OreDictUnifier.get(OrePrefix.ingot, Materials.Steel, 1), 4, 12, 6); - ChestGenHooks.addItem(LootTableList.CHESTS_VILLAGE_BLACKSMITH, OreDictUnifier.get(OrePrefix.ingot, Materials.Bronze, 1), 4, 12, 6); - ChestGenHooks.addItem(LootTableList.CHESTS_VILLAGE_BLACKSMITH, OreDictUnifier.get(OrePrefix.ingot, Materials.Brass, 1), 4, 12, 6); - ChestGenHooks.addItem(LootTableList.CHESTS_VILLAGE_BLACKSMITH, OreDictUnifier.get(OrePrefix.ingot, Materials.DamascusSteel, 1), 4, 12, 3); - ChestGenHooks.addItem(LootTableList.CHESTS_VILLAGE_BLACKSMITH, OreDictUnifier.get(OrePrefix.gem, Materials.Vinteum, 1), 3, 10, 2); - - ChestGenHooks.addItem(LootTableList.CHESTS_STRONGHOLD_CORRIDOR, OreDictUnifier.get(OrePrefix.toolHeadSword, Materials.DamascusSteel, 1), 1, 4, 4); - ChestGenHooks.addItem(LootTableList.CHESTS_STRONGHOLD_CORRIDOR, OreDictUnifier.get(OrePrefix.toolHeadAxe, Materials.DamascusSteel, 1), 1, 4, 4); - ChestGenHooks.addItem(LootTableList.CHESTS_STRONGHOLD_CORRIDOR, OreDictUnifier.get(OrePrefix.toolHeadPickaxe, Materials.Vinteum, 1), 1, 2, 3); - ChestGenHooks.addItem(LootTableList.CHESTS_STRONGHOLD_CORRIDOR, OreDictUnifier.get(OrePrefix.toolHeadShovel, Materials.Vinteum, 1), 1, 2, 3); } } diff --git a/src/main/java/gregtech/loaders/oreprocessing/OreRecipeHandler.java b/src/main/java/gregtech/loaders/oreprocessing/OreRecipeHandler.java index 1f028dc49ea..53b44dd0fd5 100644 --- a/src/main/java/gregtech/loaders/oreprocessing/OreRecipeHandler.java +++ b/src/main/java/gregtech/loaders/oreprocessing/OreRecipeHandler.java @@ -14,6 +14,7 @@ import gregtech.api.unification.stack.UnificationEntry; import gregtech.api.util.GTUtility; import net.minecraft.item.ItemStack; +import org.apache.commons.lang3.tuple.Pair; import java.util.List; @@ -143,6 +144,12 @@ public static void processCrushedOre(OrePrefix crushedPrefix, Material material, OreDictUnifier.get(OrePrefix.dust, Materials.Stone)) .buildAndRegister(); + RecipeMaps.SIMPLE_WASHER_RECIPES.recipeBuilder() + .input(crushedPrefix, material) + .fluidInputs(Materials.Water.getFluid(100)) + .outputs(crushedPurifiedOre) + .duration(8).EUt(1).buildAndRegister(); + RecipeMaps.ORE_WASHER_RECIPES.recipeBuilder() .input(crushedPrefix, material) .fluidInputs(Materials.DistilledWater.getFluid(1000)) @@ -160,11 +167,12 @@ public static void processCrushedOre(OrePrefix crushedPrefix, Material material, OreDictUnifier.get(OrePrefix.dust, Materials.Stone)) .buildAndRegister(); - if (property.getWashedIn() != null) { + if (property.getWashedIn().getKey() != null) { Material washingByproduct = GTUtility.selectItemInList(3, material, property.getOreByProducts(), Material.class); + Pair washedInTuple = property.getWashedIn(); RecipeMaps.CHEMICAL_BATH_RECIPES.recipeBuilder() .input(crushedPrefix, material) - .fluidInputs(property.getWashedIn().getFluid(property.getWashedIn() == Materials.SodiumPersulfate ? 100 : 1000)) + .fluidInputs(washedInTuple.getKey().getFluid(washedInTuple.getValue())) .outputs(crushedPurifiedOre) .chancedOutput(OreDictUnifier.get(OrePrefix.dust, washingByproduct, property.getByProductMultiplier()), 7000, 580) .chancedOutput(OreDictUnifier.get(OrePrefix.dust, Materials.Stone), 4000, 650) @@ -224,6 +232,12 @@ public static void processCrushedPurified(OrePrefix purifiedPrefix, Material mat .EUt(12) .buildAndRegister(); + RecipeMaps.SIMPLE_WASHER_RECIPES.recipeBuilder() + .input(purifiedPrefix, material) + .fluidInputs(Materials.Water.getFluid(100)) + .outputs(dustStack) + .duration(8).EUt(1).buildAndRegister(); + ModHandler.addShapelessRecipe(String.format("purified_ore_to_dust_%s", material), dustStack, 'h', new UnificationEntry(purifiedPrefix, material)); @@ -289,6 +303,12 @@ public static void processDirtyDust(OrePrefix dustPrefix, Material material, Ore builder.buildAndRegister(); + RecipeMaps.SIMPLE_WASHER_RECIPES.recipeBuilder() + .input(dustPrefix, material) + .fluidInputs(Materials.Water.getFluid(100)) + .outputs(dustStack) + .duration(8).EUt(1).buildAndRegister(); + //dust gains same amount of material as normal dust processMetalSmelting(dustPrefix, material, property); } diff --git a/src/main/java/gregtech/loaders/oreprocessing/PipeRecipeHandler.java b/src/main/java/gregtech/loaders/oreprocessing/PipeRecipeHandler.java index 6a622eed513..ac497178991 100644 --- a/src/main/java/gregtech/loaders/oreprocessing/PipeRecipeHandler.java +++ b/src/main/java/gregtech/loaders/oreprocessing/PipeRecipeHandler.java @@ -6,6 +6,7 @@ import gregtech.api.unification.OreDictUnifier; import gregtech.api.unification.material.Material; import gregtech.api.unification.material.Materials; +import gregtech.api.unification.material.properties.FluidPipeProperties; import gregtech.api.unification.material.properties.IMaterialProperty; import gregtech.api.unification.material.properties.ItemPipeProperties; import gregtech.api.unification.material.properties.PropertyKey; @@ -24,6 +25,9 @@ public static void register() { OrePrefix.pipeLargeFluid.addProcessingHandler(PropertyKey.FLUID_PIPE, PipeRecipeHandler::processPipeLarge); OrePrefix.pipeHugeFluid.addProcessingHandler(PropertyKey.FLUID_PIPE, PipeRecipeHandler::processPipeHuge); + OrePrefix.pipeQuadrupleFluid.addProcessingHandler(PropertyKey.FLUID_PIPE, PipeRecipeHandler::processPipeQuadruple); + OrePrefix.pipeNonupleFluid.addProcessingHandler(PropertyKey.FLUID_PIPE, PipeRecipeHandler::processPipeNonuple); + OrePrefix.pipeTinyItem.addProcessingHandler(PropertyKey.ITEM_PIPE, PipeRecipeHandler::processPipeTiny); OrePrefix.pipeSmallItem.addProcessingHandler(PropertyKey.ITEM_PIPE, PipeRecipeHandler::processPipeSmall); OrePrefix.pipeNormalItem.addProcessingHandler(PropertyKey.ITEM_PIPE, PipeRecipeHandler::processPipeNormal); @@ -130,6 +134,37 @@ private static void processPipeHuge(OrePrefix pipePrefix, Material material, IMa 'X', new UnificationEntry(OrePrefix.plateDouble, material)); } + private static void processPipeQuadruple(OrePrefix pipePrefix, Material material, FluidPipeProperties property) { + ItemStack normalPipe = OreDictUnifier.get(OrePrefix.pipeNormalFluid, material); + ItemStack quadPipe = OreDictUnifier.get(pipePrefix, material); + ModHandler.addShapedRecipe(String.format("quadruple_%s_pipe", material.toString()), + quadPipe, "XX", "XX", + 'X', normalPipe); + + RecipeMaps.ASSEMBLER_RECIPES.recipeBuilder() + .inputs(GTUtility.copyAmount(4, normalPipe)) + .circuitMeta(1) + .outputs(quadPipe) + .duration(30) + .EUt(8) + .buildAndRegister(); + } + + private static void processPipeNonuple(OrePrefix pipePrefix, Material material, FluidPipeProperties property) { + ItemStack smallPipe = OreDictUnifier.get(OrePrefix.pipeSmallFluid, material); + ItemStack nonuplePipe = OreDictUnifier.get(pipePrefix, material); + ModHandler.addShapedRecipe(String.format("nonuple_%s_pipe", material.toString()), + nonuplePipe, "XXX", "XXX", "XXX", + 'X', smallPipe); + + RecipeMaps.ASSEMBLER_RECIPES.recipeBuilder() + .inputs(GTUtility.copyAmount(9, smallPipe)) + .circuitMeta(2) + .outputs(nonuplePipe) + .duration(40) + .EUt(8) + .buildAndRegister(); + } private static int getVoltageMultiplier(Material material) { return material.getBlastTemperature() >= 2800 ? 32 : 8; diff --git a/src/main/java/gregtech/loaders/oreprocessing/ToolRecipeHandler.java b/src/main/java/gregtech/loaders/oreprocessing/ToolRecipeHandler.java index c1f15b90cb3..0cc9f43bad9 100644 --- a/src/main/java/gregtech/loaders/oreprocessing/ToolRecipeHandler.java +++ b/src/main/java/gregtech/loaders/oreprocessing/ToolRecipeHandler.java @@ -60,9 +60,9 @@ public static void initializeMetaItems() { baseMaterials = new Material[]{Materials.Aluminium, Materials.StainlessSteel, Materials.Titanium, Materials.TungstenSteel, Materials.HSSS}; powerUnitItems = new MetaValueItem[]{MetaItems.POWER_UNIT_LV, MetaItems.POWER_UNIT_MV, MetaItems.POWER_UNIT_HV, MetaItems.POWER_UNIT_EV, MetaItems.POWER_UNIT_IV}; batteryItems = new MetaValueItem[][]{ - {MetaItems.BATTERY_RE_LV_LITHIUM, MetaItems.BATTERY_RE_LV_CADMIUM, MetaItems.BATTERY_RE_LV_SODIUM}, - {MetaItems.BATTERY_RE_MV_LITHIUM, MetaItems.BATTERY_RE_MV_CADMIUM, MetaItems.BATTERY_RE_MV_SODIUM}, - {MetaItems.BATTERY_RE_HV_LITHIUM, MetaItems.BATTERY_RE_HV_CADMIUM, MetaItems.BATTERY_RE_HV_SODIUM}, + {MetaItems.BATTERY_LV_LITHIUM, MetaItems.BATTERY_LV_CADMIUM, MetaItems.BATTERY_LV_SODIUM}, + {MetaItems.BATTERY_MV_LITHIUM, MetaItems.BATTERY_MV_CADMIUM, MetaItems.BATTERY_MV_SODIUM}, + {MetaItems.BATTERY_HV_LITHIUM, MetaItems.BATTERY_HV_CADMIUM, MetaItems.BATTERY_HV_SODIUM}, {MetaItems.LAPOTRON_CRYSTAL}, {MetaItems.ENERGY_LAPOTRONIC_ORB}}; } diff --git a/src/main/java/gregtech/loaders/oreprocessing/WireRecipeHandler.java b/src/main/java/gregtech/loaders/oreprocessing/WireRecipeHandler.java index 281c7933bbe..3576a86003e 100644 --- a/src/main/java/gregtech/loaders/oreprocessing/WireRecipeHandler.java +++ b/src/main/java/gregtech/loaders/oreprocessing/WireRecipeHandler.java @@ -79,6 +79,7 @@ public static void processWireSingle(OrePrefix wirePrefix, Material material, Wi } public static void generateWireRecipe(OrePrefix wirePrefix, Material material, WireProperties property) { + if (property.isSuperconductor) return; int cableAmount = (int) (wirePrefix.materialAmount * 2 / M); OrePrefix cablePrefix = OrePrefix.getPrefix("cable" + wirePrefix.name().substring(4)); ItemStack cableStack = OreDictUnifier.get(cablePrefix, material); @@ -154,6 +155,7 @@ public static void generateWireCombiningRecipe(OrePrefix wirePrefix, Material ma } public static void generateCableCombiningRecipe(OrePrefix cablePrefix, Material material, WireProperties property) { + if (property.isSuperconductor) return; int cableIndex = ArrayUtils.indexOf(CABLE_DOUBLING_ORDER, cablePrefix); if (cableIndex < CABLE_DOUBLING_ORDER.length - 1) { diff --git a/src/main/java/gregtech/loaders/recipe/AssemblyLineLoader.java b/src/main/java/gregtech/loaders/recipe/AssemblyLineLoader.java index 778473ecc3b..b332d009e18 100644 --- a/src/main/java/gregtech/loaders/recipe/AssemblyLineLoader.java +++ b/src/main/java/gregtech/loaders/recipe/AssemblyLineLoader.java @@ -5,7 +5,6 @@ import gregtech.api.unification.material.MarkerMaterials; import gregtech.api.unification.material.Materials; import gregtech.api.unification.ore.OrePrefix; -import gregtech.common.ConfigHolder; import gregtech.common.blocks.BlockFusionCoil; import gregtech.common.blocks.MetaBlocks; import gregtech.common.items.MetaItems; @@ -59,7 +58,7 @@ public static void init() { .buildAndRegister(); RecipeMaps.ASSEMBLY_LINE_RECIPES.recipeBuilder().inputs(OreDictUnifier.get(OrePrefix.stickLong, Materials.NeodymiumMagnetic, 2), OreDictUnifier.get(OrePrefix.stickLong, Materials.HSSE, 4), OreDictUnifier.get(OrePrefix.ring, Materials.HSSE, 4), OreDictUnifier.get(OrePrefix.round, Materials.HSSE, 16), OreDictUnifier.get(OrePrefix.wireFine, Materials.Platinum, 64), OreDictUnifier.get(OrePrefix.wireFine, Materials.Platinum, 64), OreDictUnifier.get(OrePrefix.wireFine, Materials.Platinum, 64), OreDictUnifier.get(OrePrefix.wireFine, Materials.Platinum, 64), OreDictUnifier.get(OrePrefix.cableGtDouble, Materials.VanadiumGallium, 2)).fluidInputs(Materials.SolderingAlloy.getFluid(288), Materials.Lubricant.getFluid(750)).outputs(MetaItems.ELECTRIC_MOTOR_ZPM.getStackForm()).duration(600).EUt(40960).buildAndRegister(); - RecipeMaps.ASSEMBLY_LINE_RECIPES.recipeBuilder().inputs(OreDictUnifier.get(OrePrefix.block, Materials.NeodymiumMagnetic, 1), OreDictUnifier.get(OrePrefix.stickLong, Materials.Neutronium, 4), OreDictUnifier.get(OrePrefix.ring, Materials.Neutronium, 4), OreDictUnifier.get(OrePrefix.round, Materials.Neutronium, 16), /* OreDictUnifier.get(OrePrefix.wireGtSingle, MarkerMaterials.Tier.Superconductor, 64), OreDictUnifier.get(OrePrefix.wireGtSingle, MarkerMaterials.Tier.Superconductor, 64), OreDictUnifier.get(OrePrefix.wireGtSingle, MarkerMaterials.Tier.Superconductor, 64), OreDictUnifier.get(OrePrefix.wireGtSingle, MarkerMaterials.Tier.Superconductor, 64), */ OreDictUnifier.get(OrePrefix.cableGtQuadruple, Materials.NiobiumTitanium, 2)).fluidInputs(Materials.SolderingAlloy.getFluid(1296), Materials.Lubricant.getFluid(2000)).outputs(MetaItems.ELECTRIC_MOTOR_UV.getStackForm()).duration(600).EUt(163840).buildAndRegister(); // todo fix + RecipeMaps.ASSEMBLY_LINE_RECIPES.recipeBuilder().inputs(OreDictUnifier.get(OrePrefix.block, Materials.NeodymiumMagnetic, 1), OreDictUnifier.get(OrePrefix.stickLong, Materials.Neutronium, 4), OreDictUnifier.get(OrePrefix.ring, Materials.Neutronium, 4), OreDictUnifier.get(OrePrefix.round, Materials.Neutronium, 16), OreDictUnifier.get(OrePrefix.wireGtSingle, Materials.EnrichedNaquadahTriniumEuropiumDuranide, 64), OreDictUnifier.get(OrePrefix.wireGtSingle, Materials.EnrichedNaquadahTriniumEuropiumDuranide, 64), OreDictUnifier.get(OrePrefix.wireGtSingle, Materials.EnrichedNaquadahTriniumEuropiumDuranide, 64), OreDictUnifier.get(OrePrefix.wireGtSingle, Materials.EnrichedNaquadahTriniumEuropiumDuranide, 64), OreDictUnifier.get(OrePrefix.cableGtQuadruple, Materials.NiobiumTitanium, 2)).fluidInputs(Materials.SolderingAlloy.getFluid(1296), Materials.Lubricant.getFluid(2000)).outputs(MetaItems.ELECTRIC_MOTOR_UV.getStackForm()).duration(600).EUt(163840).buildAndRegister(); RecipeMaps.ASSEMBLY_LINE_RECIPES.recipeBuilder().inputs(MetaItems.ELECTRIC_MOTOR_LUV.getStackForm(), OreDictUnifier.get(OrePrefix.plate, Materials.HSSG, 2), OreDictUnifier.get(OrePrefix.pipeSmallFluid, Materials.Naquadah, 2), OreDictUnifier.get(OrePrefix.screw, Materials.HSSG, 8), OreDictUnifier.get(OrePrefix.ring, Materials.SiliconeRubber, 4), OreDictUnifier.get(OrePrefix.rotor, Materials.HSSG, 2), OreDictUnifier.get(OrePrefix.cableGtSingle, Materials.YttriumBariumCuprate, 2)).fluidInputs(Materials.SolderingAlloy.getFluid(144), Materials.Lubricant.getFluid(250)).outputs(MetaItems.ELECTRIC_PUMP_LUV.getStackForm()).duration(600).EUt(15360).buildAndRegister(); RecipeMaps.ASSEMBLY_LINE_RECIPES.recipeBuilder().inputs(MetaItems.ELECTRIC_MOTOR_ZPM.getStackForm(), OreDictUnifier.get(OrePrefix.plate, Materials.HSSE, 2), OreDictUnifier.get(OrePrefix.pipeNormalFluid, Materials.Naquadah, 2), OreDictUnifier.get(OrePrefix.screw, Materials.HSSE, 8), OreDictUnifier.get(OrePrefix.ring, Materials.SiliconeRubber, 16), OreDictUnifier.get(OrePrefix.rotor, Materials.HSSE, 2), OreDictUnifier.get(OrePrefix.cableGtDouble, Materials.VanadiumGallium, 2)).fluidInputs(Materials.SolderingAlloy.getFluid(288), Materials.Lubricant.getFluid(750)).outputs(MetaItems.ELECTRIC_PUMP_ZPM.getStackForm()).duration(600).EUt(61440).buildAndRegister(); @@ -89,18 +88,12 @@ public static void init() { RecipeMaps.ASSEMBLY_LINE_RECIPES.recipeBuilder().inputs(OreDictUnifier.get(OrePrefix.frameGt, Materials.HSSE, 1), OreDictUnifier.get(OrePrefix.plate, Materials.HSSE, 6), MetaItems.QUANTUM_STAR.getStackForm(4), MetaItems.EMITTER_ZPM.getStackForm(4), OreDictUnifier.get(OrePrefix.wireFine, Materials.Osmium, 64), OreDictUnifier.get(OrePrefix.wireFine, Materials.Osmium, 64), OreDictUnifier.get(OrePrefix.wireFine, Materials.Osmium, 64), OreDictUnifier.get(OrePrefix.wireFine, Materials.Osmium, 64), OreDictUnifier.get(OrePrefix.wireFine, Materials.Osmium, 64), OreDictUnifier.get(OrePrefix.wireFine, Materials.Osmium, 64), OreDictUnifier.get(OrePrefix.wireFine, Materials.Osmium, 64), OreDictUnifier.get(OrePrefix.wireFine, Materials.Osmium, 64), OreDictUnifier.get(OrePrefix.cableGtDouble, Materials.YttriumBariumCuprate, 8)).input(OrePrefix.circuit, MarkerMaterials.Tier.Master, 16).fluidInputs(Materials.SolderingAlloy.getFluid(1152)).outputs(MetaItems.FIELD_GENERATOR_ZPM.getStackForm()).duration(600).EUt(245760).buildAndRegister(); RecipeMaps.ASSEMBLY_LINE_RECIPES.recipeBuilder().inputs(OreDictUnifier.get(OrePrefix.frameGt, Materials.Neutronium, 1), OreDictUnifier.get(OrePrefix.plate, Materials.Neutronium, 6), MetaItems.GRAVI_STAR.getStackForm(), MetaItems.EMITTER_UV.getStackForm(4), OreDictUnifier.get(OrePrefix.wireFine, Materials.Osmium, 64), OreDictUnifier.get(OrePrefix.wireFine, Materials.Osmium, 64), OreDictUnifier.get(OrePrefix.wireFine, Materials.Osmium, 64), OreDictUnifier.get(OrePrefix.wireFine, Materials.Osmium, 64), OreDictUnifier.get(OrePrefix.wireFine, Materials.Osmium, 64), OreDictUnifier.get(OrePrefix.wireFine, Materials.Osmium, 64), OreDictUnifier.get(OrePrefix.wireFine, Materials.Osmium, 64), OreDictUnifier.get(OrePrefix.wireFine, Materials.Osmium, 64), OreDictUnifier.get(OrePrefix.cableGtQuadruple, Materials.YttriumBariumCuprate, 8)).input(OrePrefix.circuit, MarkerMaterials.Tier.Master, 64).fluidInputs(Materials.SolderingAlloy.getFluid(2304)).outputs(MetaItems.FIELD_GENERATOR_UV.getStackForm()).duration(600).EUt(491520).buildAndRegister(); - if (ConfigHolder.U.GT5u.enableZPMandUVBats) { -// RecipeMaps.ASSEMBLY_LINE_RECIPES.recipeBuilder().inputs(OreDictUnifier.get(OrePrefix.plate, Materials.Europium, 16), MetaItems.WETWARE_SUPER_COMPUTER_UV.getStackForm(4), MetaItems.ENERGY_LAPOTRONIC_ORB2.getStackForm(8), MetaItems.FIELD_GENERATOR_LUV.getStackForm(2), MetaItems.NANO_CENTRAL_PROCESSING_UNIT.getStackForm(64), MetaItems.NANO_CENTRAL_PROCESSING_UNIT.getStackForm(64), MetaItems.SMD_DIODE.getStackForm(8), OreDictUnifier.get(OrePrefix.cableGtSingle, Materials.Naquadah, 32)).fluidInputs(Materials.SolderingAlloy.getFluid(2880), Materials.Polybenzimidazole.getFluid(288)).outputs(MetaItems.ENERGY_LAPOTRONIC_MODULE.getStackForm()).duration(2000).EUt(100000).buildAndRegister(); -// -// RecipeMaps.ASSEMBLY_LINE_RECIPES.recipeBuilder().inputs(OreDictUnifier.get(OrePrefix.plate, Materials.Americium, 16), MetaItems.WETWARE_SUPER_COMPUTER_UV.getStackForm(4), MetaItems.ENERGY_LAPOTRONIC_MODULE.getStackForm(8), MetaItems.FIELD_GENERATOR_ZPM.getStackForm(2), MetaItems.HIGH_POWER_INTEGRATED_CIRCUIT.getStackForm(64), MetaItems.HIGH_POWER_INTEGRATED_CIRCUIT.getStackForm(64), MetaItems.SMD_DIODE.getStackForm(16), OreDictUnifier.get(OrePrefix.cableGtSingle, Materials.NaquadahAlloy, 32)).fluidInputs(Materials.SolderingAlloy.getFluid(2880), Materials.Polybenzimidazole.getFluid(576)).outputs(MetaItems.ENERGY_LAPOTRONIC_CLUSTER.getStackForm()).duration(2000).EUt(200000).buildAndRegister(); + RecipeMaps.ASSEMBLY_LINE_RECIPES.recipeBuilder().inputs(OreDictUnifier.get(OrePrefix.plate, Materials.Europium, 16), MetaItems.WETWARE_SUPER_COMPUTER_UV.getStackForm(4), MetaItems.ENERGY_LAPOTRONIC_ORB2.getStackForm(8), MetaItems.FIELD_GENERATOR_LUV.getStackForm(2), MetaItems.NANO_CENTRAL_PROCESSING_UNIT.getStackForm(64), MetaItems.NANO_CENTRAL_PROCESSING_UNIT.getStackForm(64), MetaItems.SMD_DIODE.getStackForm(8), OreDictUnifier.get(OrePrefix.cableGtSingle, Materials.Naquadah, 32)).fluidInputs(Materials.SolderingAlloy.getFluid(2880), Materials.Polybenzimidazole.getFluid(288)).outputs(MetaItems.ENERGY_LAPOTRONIC_MODULE.getStackForm()).duration(2000).EUt(100000).buildAndRegister(); + RecipeMaps.ASSEMBLY_LINE_RECIPES.recipeBuilder().inputs(OreDictUnifier.get(OrePrefix.plate, Materials.Americium, 16), MetaItems.WETWARE_SUPER_COMPUTER_UV.getStackForm(4), MetaItems.ENERGY_LAPOTRONIC_MODULE.getStackForm(8), MetaItems.FIELD_GENERATOR_ZPM.getStackForm(2), MetaItems.HIGH_POWER_INTEGRATED_CIRCUIT.getStackForm(64), MetaItems.HIGH_POWER_INTEGRATED_CIRCUIT.getStackForm(64), MetaItems.SMD_DIODE.getStackForm(16), OreDictUnifier.get(OrePrefix.cableGtSingle, Materials.NaquadahAlloy, 32)).fluidInputs(Materials.SolderingAlloy.getFluid(2880), Materials.Polybenzimidazole.getFluid(576)).outputs(MetaItems.ENERGY_LAPOTRONIC_CLUSTER.getStackForm()).duration(2000).EUt(200000).buildAndRegister(); + RecipeMaps.ASSEMBLY_LINE_RECIPES.recipeBuilder().inputs(OreDictUnifier.get(OrePrefix.plate, Materials.Neutronium, 16), MetaItems.WETWARE_MAINFRAME_UHV.getStackForm(), MetaItems.WETWARE_MAINFRAME_UHV.getStackForm(), MetaItems.WETWARE_MAINFRAME_UHV.getStackForm(), MetaItems.WETWARE_MAINFRAME_UHV.getStackForm(), MetaItems.ENERGY_LAPOTRONIC_CLUSTER.getStackForm(8), MetaItems.FIELD_GENERATOR_UV.getStackForm(2), MetaItems.HIGH_POWER_INTEGRATED_CIRCUIT_WAFER.getStackForm(64), MetaItems.HIGH_POWER_INTEGRATED_CIRCUIT_WAFER.getStackForm(64), MetaItems.SMD_DIODE.getStackForm(16), OreDictUnifier.get(OrePrefix.wireGtSingle, Materials.EnrichedNaquadahTriniumEuropiumDuranide, 32)).fluidInputs(Materials.SolderingAlloy.getFluid(2880), Materials.Polybenzimidazole.getFluid(1000), Materials.Naquadria.getFluid(1152)).outputs(MetaItems.ULTIMATE_BATTERY.getStackForm()).duration(2000).EUt(300000).buildAndRegister(); -// RecipeMaps.ASSEMBLY_LINE_RECIPES.recipeBuilder().inputs(OreDictUnifier.get(OrePrefix.plate, Materials.Neutronium, 16), MetaItems.WETWARE_MAINFRAME_UHV.getStackForm(), MetaItems.WETWARE_MAINFRAME_UHV.getStackForm(), MetaItems.WETWARE_MAINFRAME_UHV.getStackForm(), MetaItems.WETWARE_MAINFRAME_UHV.getStackForm(), MetaItems.ENERGY_LAPOTRONIC_CLUSTER.getStackForm(8), MetaItems.FIELD_GENERATOR_UV.getStackForm(2), MetaItems.HIGH_POWER_INTEGRATED_CIRCUIT_WAFER.getStackForm(64), MetaItems.HIGH_POWER_INTEGRATED_CIRCUIT_WAFER.getStackForm(64), MetaItems.SMD_DIODE.getStackForm(16), OreDictUnifier.get(OrePrefix.wireGtSingle, MarkerMaterials.Tier.Superconductor, 32)).fluidInputs(Materials.SolderingAlloy.getFluid(2880), Materials.Polybenzimidazole.getFluid(1000), Materials.Naquadria.getFluid(1152)).outputs(MetaItems.ULTIMATE_BATTERY.getStackForm()).duration(2000).EUt(300000).buildAndRegister(); - } else { - RecipeMaps.ASSEMBLY_LINE_RECIPES.recipeBuilder().inputs(OreDictUnifier.get(OrePrefix.plate, Materials.Neutronium, 16), MetaItems.WETWARE_MAINFRAME_UHV.getStackForm(), MetaItems.WETWARE_MAINFRAME_UHV.getStackForm(), MetaItems.WETWARE_MAINFRAME_UHV.getStackForm(), MetaItems.WETWARE_MAINFRAME_UHV.getStackForm(), MetaItems.ENERGY_LAPOTRONIC_ORB2.getStackForm(8), MetaItems.FIELD_GENERATOR_UV.getStackForm(2), MetaItems.HIGH_POWER_INTEGRATED_CIRCUIT_WAFER.getStackForm(64), MetaItems.HIGH_POWER_INTEGRATED_CIRCUIT_WAFER.getStackForm(64), MetaItems.SMD_DIODE.getStackForm(16)/*, OreDictUnifier.get(OrePrefix.wireGtSingle, MarkerMaterials.Tier.Superconductor, 32)*/).fluidInputs(Materials.SolderingAlloy.getFluid(2880), Materials.Polybenzimidazole.getFluid(1000)).outputs(MetaItems.ULTIMATE_BATTERY.getStackForm()).duration(2000).EUt(300000).buildAndRegister(); //todo fix - } - - RecipeMaps.ASSEMBLY_LINE_RECIPES.recipeBuilder().inputs(MetaBlocks.FUSION_COIL.getItemVariant(BlockFusionCoil.CoilType.FUSION_COIL), OreDictUnifier.get(OrePrefix.plate, Materials.Plutonium241), OreDictUnifier.get(OrePrefix.plate, Materials.NetherStar), MetaItems.FIELD_GENERATOR_IV.getStackForm(2), MetaItems.HIGH_POWER_INTEGRATED_CIRCUIT_WAFER.getStackForm(32)/*, OreDictUnifier.get(OrePrefix.wireGtSingle, MarkerMaterials.Tier.Superconductor, 32)*/).input(OrePrefix.circuit, MarkerMaterials.Tier.Ultimate, 1).input(OrePrefix.circuit, MarkerMaterials.Tier.Ultimate, 1).input(OrePrefix.circuit, MarkerMaterials.Tier.Ultimate, 1).input(OrePrefix.circuit, MarkerMaterials.Tier.Ultimate, 1).fluidInputs(Materials.SolderingAlloy.getFluid(2880)).outputs(MetaTileEntities.FUSION_REACTOR[0].getStackForm()).duration(1000).EUt(30000).buildAndRegister(); //todo fix - RecipeMaps.ASSEMBLY_LINE_RECIPES.recipeBuilder().inputs(MetaBlocks.FUSION_COIL.getItemVariant(BlockFusionCoil.CoilType.FUSION_COIL), OreDictUnifier.get(OrePrefix.plate, Materials.Europium, 4), MetaItems.FIELD_GENERATOR_LUV.getStackForm(2), MetaItems.HIGH_POWER_INTEGRATED_CIRCUIT_WAFER.getStackForm(48))/* OreDictUnifier.get(OrePrefix.wireGtDouble, MarkerMaterials.Tier.Superconductor, 32)).input(OrePrefix.circuit, MarkerMaterials.Tier.Superconductor, 1).input(OrePrefix.circuit, MarkerMaterials.Tier.Superconductor, 1).input(OrePrefix.circuit, MarkerMaterials.Tier.Superconductor, 1).input(OrePrefix.circuit, MarkerMaterials.Tier.Superconductor, 1)*/.fluidInputs(Materials.SolderingAlloy.getFluid(2880)).outputs(MetaTileEntities.FUSION_REACTOR[1].getStackForm()).duration(1000).EUt(60000).buildAndRegister(); //todo fix - RecipeMaps.ASSEMBLY_LINE_RECIPES.recipeBuilder().inputs(MetaBlocks.FUSION_COIL.getItemVariant(BlockFusionCoil.CoilType.FUSION_COIL), OreDictUnifier.get(OrePrefix.plate, Materials.Americium, 4), MetaItems.FIELD_GENERATOR_ZPM.getStackForm(2), MetaItems.HIGH_POWER_INTEGRATED_CIRCUIT_WAFER.getStackForm(64), MetaItems.WETWARE_MAINFRAME_UHV.getStackForm(1), MetaItems.WETWARE_MAINFRAME_UHV.getStackForm(1), MetaItems.WETWARE_MAINFRAME_UHV.getStackForm(1), MetaItems.WETWARE_MAINFRAME_UHV.getStackForm(1)/*, OreDictUnifier.get(OrePrefix.wireGtQuadruple, MarkerMaterials.Tier.Superconductor, 32)*/).fluidInputs(Materials.SolderingAlloy.getFluid(2880)).outputs(MetaTileEntities.FUSION_REACTOR[2].getStackForm()).duration(1000).EUt(90000).buildAndRegister(); //todo fix + RecipeMaps.ASSEMBLY_LINE_RECIPES.recipeBuilder().inputs(MetaBlocks.FUSION_COIL.getItemVariant(BlockFusionCoil.CoilType.FUSION_COIL), OreDictUnifier.get(OrePrefix.plate, Materials.Plutonium241), OreDictUnifier.get(OrePrefix.plate, Materials.NetherStar), MetaItems.FIELD_GENERATOR_IV.getStackForm(2), MetaItems.HIGH_POWER_INTEGRATED_CIRCUIT_WAFER.getStackForm(32), OreDictUnifier.get(OrePrefix.wireGtSingle, Materials.IndiumTinBariumTitaniumCuprate, 32)).input(OrePrefix.circuit, MarkerMaterials.Tier.Ultimate, 1).input(OrePrefix.circuit, MarkerMaterials.Tier.Ultimate, 1).input(OrePrefix.circuit, MarkerMaterials.Tier.Ultimate, 1).input(OrePrefix.circuit, MarkerMaterials.Tier.Ultimate, 1).fluidInputs(Materials.SolderingAlloy.getFluid(2880)).outputs(MetaTileEntities.FUSION_REACTOR[0].getStackForm()).duration(1000).EUt(30000).buildAndRegister(); + RecipeMaps.ASSEMBLY_LINE_RECIPES.recipeBuilder().inputs(MetaBlocks.FUSION_COIL.getItemVariant(BlockFusionCoil.CoilType.FUSION_COIL), OreDictUnifier.get(OrePrefix.plate, Materials.Europium, 4), MetaItems.FIELD_GENERATOR_LUV.getStackForm(2), MetaItems.HIGH_POWER_INTEGRATED_CIRCUIT_WAFER.getStackForm(48)).input(OrePrefix.wireGtDouble, Materials.UraniumRhodiumDinaquadide, 32).input(OrePrefix.circuit, MarkerMaterials.Tier.Superconductor, 1).input(OrePrefix.circuit, MarkerMaterials.Tier.Superconductor, 1).input(OrePrefix.circuit, MarkerMaterials.Tier.Superconductor, 1).input(OrePrefix.circuit, MarkerMaterials.Tier.Superconductor, 1).fluidInputs(Materials.SolderingAlloy.getFluid(2880)).outputs(MetaTileEntities.FUSION_REACTOR[1].getStackForm()).duration(1000).EUt(60000).buildAndRegister(); + RecipeMaps.ASSEMBLY_LINE_RECIPES.recipeBuilder().inputs(MetaBlocks.FUSION_COIL.getItemVariant(BlockFusionCoil.CoilType.FUSION_COIL), OreDictUnifier.get(OrePrefix.plate, Materials.Americium, 4), MetaItems.FIELD_GENERATOR_ZPM.getStackForm(2), MetaItems.HIGH_POWER_INTEGRATED_CIRCUIT_WAFER.getStackForm(64), OreDictUnifier.get(OrePrefix.circuit, MarkerMaterials.Tier.Infinite), OreDictUnifier.get(OrePrefix.circuit, MarkerMaterials.Tier.Infinite), OreDictUnifier.get(OrePrefix.circuit, MarkerMaterials.Tier.Infinite), OreDictUnifier.get(OrePrefix.circuit, MarkerMaterials.Tier.Infinite), OreDictUnifier.get(OrePrefix.wireGtQuadruple, Materials.EnrichedNaquadahTriniumEuropiumDuranide, 32)).fluidInputs(Materials.SolderingAlloy.getFluid(2880)).outputs(MetaTileEntities.FUSION_REACTOR[2].getStackForm()).duration(1000).EUt(90000).buildAndRegister(); } } diff --git a/src/main/java/gregtech/loaders/recipe/BatteryRecipes.java b/src/main/java/gregtech/loaders/recipe/BatteryRecipes.java index 764910723a0..10968f4b861 100644 --- a/src/main/java/gregtech/loaders/recipe/BatteryRecipes.java +++ b/src/main/java/gregtech/loaders/recipe/BatteryRecipes.java @@ -1,130 +1,221 @@ package gregtech.loaders.recipe; -import gregtech.api.recipes.RecipeMaps; -import gregtech.api.unification.material.Materials; -import gregtech.api.unification.ore.OrePrefix; -import gregtech.common.items.MetaItems; +import gregtech.api.recipes.ModHandler; +import gregtech.api.unification.stack.UnificationEntry; +import static gregtech.api.recipes.RecipeMaps.*; +import static gregtech.api.unification.material.Materials.*; +import static gregtech.api.unification.ore.OrePrefix.*; import static gregtech.common.items.MetaItems.*; public class BatteryRecipes { public static void init() { + // Tantalum Battery (since it doesn't fit elsewhere) + ASSEMBLER_RECIPES.recipeBuilder().duration(30).EUt(4) + .input(dust, Tantalum) + .input(foil, Manganese) + .fluidInputs(Polyethylene.getFluid(144)) + .outputs(BATTERY_ULV_TANTALUM.getStackForm(8)) + .buildAndRegister(); + + // Battery Hull Recipes + + // LV + ModHandler.addShapedRecipe("battery_hull_lv", BATTERY_HULL_LV.getStackForm(), + "C", "P", "P", + 'C', new UnificationEntry(cableGtSingle, Tin), + 'P', new UnificationEntry(plate, BatteryAlloy)); + + ASSEMBLER_RECIPES.recipeBuilder().duration(400).EUt(1) + .input(cableGtSingle, Tin) + .input(plate, BatteryAlloy) + .fluidInputs(Polyethylene.getFluid(144)) + .output(BATTERY_HULL_LV) + .buildAndRegister(); - RecipeMaps.ASSEMBLER_RECIPES.recipeBuilder().duration(30).EUt(4) - .input(OrePrefix.dust, Materials.Tantalum) - .input(OrePrefix.foil, Materials.Manganese) - .fluidInputs(Materials.Polyethylene.getFluid(144)) - .outputs(MetaItems.BATTERY_RE_ULV_TANTALUM.getStackForm(8)) + // MV + ModHandler.addShapedRecipe("battery_hull_mv", BATTERY_HULL_MV.getStackForm(), + "C C", "PPP", "PPP", + 'C', new UnificationEntry(cableGtSingle, Copper), + 'P', new UnificationEntry(plate, BatteryAlloy)); + + ASSEMBLER_RECIPES.recipeBuilder().duration(100).EUt(2) + .input(cableGtSingle, Copper, 2) + .input(plate, BatteryAlloy, 3) + .fluidInputs(Polyethylene.getFluid(432)) + .output(BATTERY_HULL_MV) .buildAndRegister(); - RecipeMaps.EXTRACTOR_RECIPES.recipeBuilder() - .inputs(BATTERY_RE_LV_CADMIUM.getStackForm()) - .outputs(BATTERY_HULL_LV.getStackForm()) + ASSEMBLER_RECIPES.recipeBuilder().duration(200).EUt(2) + .input(cableGtSingle, AnnealedCopper, 2) + .input(plate, BatteryAlloy, 3) + .fluidInputs(Polyethylene.getFluid(432)) + .output(BATTERY_HULL_MV) .buildAndRegister(); - RecipeMaps.EXTRACTOR_RECIPES.recipeBuilder() - .inputs(BATTERY_RE_LV_LITHIUM.getStackForm()) - .outputs(BATTERY_HULL_LV.getStackForm()) + // HV + ASSEMBLER_RECIPES.recipeBuilder().duration(300).EUt(4) + .input(cableGtSingle, Gold, 4) + .input(plate, BatteryAlloy, 9) + .fluidInputs(Polyethylene.getFluid(1296)) + .output(BATTERY_HULL_HV) .buildAndRegister(); - RecipeMaps.EXTRACTOR_RECIPES.recipeBuilder() - .inputs(BATTERY_RE_LV_SODIUM.getStackForm()) - .outputs(BATTERY_HULL_LV.getStackForm()) + // EV + ASSEMBLER_RECIPES.recipeBuilder().duration(100).EUt(480) + .input(cableGtSingle, Aluminium, 2) + .input(plate, BlueSteel, 2) + .fluidInputs(Polytetrafluoroethylene.getFluid(144)) + .output(BATTERY_HULL_SMALL_VANADIUM) .buildAndRegister(); - RecipeMaps.EXTRACTOR_RECIPES.recipeBuilder() - .inputs(BATTERY_RE_MV_CADMIUM.getStackForm()) - .outputs(BATTERY_HULL_MV.getStackForm()) + // IV + ASSEMBLER_RECIPES.recipeBuilder().duration(200).EUt(1920) + .input(cableGtSingle, Platinum, 2) + .input(plate, RoseGold, 6) + .fluidInputs(Polytetrafluoroethylene.getFluid(288)) + .output(BATTERY_HULL_MEDIUM_VANADIUM) .buildAndRegister(); - RecipeMaps.EXTRACTOR_RECIPES.recipeBuilder() - .inputs(BATTERY_RE_MV_LITHIUM.getStackForm()) - .outputs(BATTERY_HULL_MV.getStackForm()) + // LuV + ASSEMBLER_RECIPES.recipeBuilder().duration(300).EUt(7680) + .input(cableGtSingle, NiobiumTitanium, 2) + .input(plate, RedSteel, 18) + .fluidInputs(Polybenzimidazole.getFluid(144)) + .output(BATTERY_HULL_LARGE_VANADIUM) .buildAndRegister(); - RecipeMaps.EXTRACTOR_RECIPES.recipeBuilder() - .inputs(BATTERY_RE_MV_SODIUM.getStackForm()) - .outputs(BATTERY_HULL_MV.getStackForm()) + // ZPM + ASSEMBLER_RECIPES.recipeBuilder().duration(200).EUt(30720) + .input(cableGtSingle, Naquadah, 2) + .input(plate, Europium, 6) + .fluidInputs(Polybenzimidazole.getFluid(288)) + .output(BATTERY_HULL_MEDIUM_NAQUADRIA) .buildAndRegister(); - RecipeMaps.EXTRACTOR_RECIPES.recipeBuilder() - .inputs(BATTERY_RE_HV_CADMIUM.getStackForm()) - .outputs(BATTERY_HULL_HV.getStackForm()) + // UV + ASSEMBLER_RECIPES.recipeBuilder().duration(300).EUt(122880) + .input(cableGtSingle, NaquadahAlloy, 2) + .input(plate, Americium, 18) + .fluidInputs(Polybenzimidazole.getFluid(576)) + .output(BATTERY_HULL_LARGE_NAQUADRIA) .buildAndRegister(); - RecipeMaps.EXTRACTOR_RECIPES.recipeBuilder() - .inputs(BATTERY_RE_HV_LITHIUM.getStackForm()) - .outputs(BATTERY_HULL_HV.getStackForm()) + // Battery Filling Recipes + + // LV + CANNER_RECIPES.recipeBuilder().duration(100).EUt(2) + .input(BATTERY_HULL_LV) + .input(dust, Cadmium, 2) + .output(BATTERY_LV_CADMIUM) .buildAndRegister(); - RecipeMaps.EXTRACTOR_RECIPES.recipeBuilder() - .inputs(BATTERY_RE_HV_SODIUM.getStackForm()) - .outputs(BATTERY_HULL_HV.getStackForm()) + CANNER_RECIPES.recipeBuilder().duration(100).EUt(2) + .input(BATTERY_HULL_LV) + .input(dust, Lithium, 2) + .output(BATTERY_LV_LITHIUM) .buildAndRegister(); - RecipeMaps.CANNER_RECIPES.recipeBuilder() - .inputs(BATTERY_HULL_LV.getStackForm()) - .input(OrePrefix.dust, Materials.Cadmium, 2) - .outputs(BATTERY_RE_LV_CADMIUM.getStackForm()) - .duration(100).EUt(2) + CANNER_RECIPES.recipeBuilder().duration(100).EUt(2) + .input(BATTERY_HULL_LV) + .input(dust, Sodium, 2) + .output(BATTERY_LV_SODIUM) .buildAndRegister(); - RecipeMaps.CANNER_RECIPES.recipeBuilder() - .inputs(BATTERY_HULL_LV.getStackForm()) - .input(OrePrefix.dust, Materials.Lithium, 2) - .outputs(BATTERY_RE_LV_LITHIUM.getStackForm()) - .duration(100).EUt(2) + // MV + CANNER_RECIPES.recipeBuilder().duration(400).EUt(2) + .input(BATTERY_HULL_MV) + .input(dust, Cadmium, 8) + .output(BATTERY_MV_CADMIUM) .buildAndRegister(); - RecipeMaps.CANNER_RECIPES.recipeBuilder() - .inputs(BATTERY_HULL_LV.getStackForm()) - .input(OrePrefix.dust, Materials.Sodium, 2) - .outputs(BATTERY_RE_LV_SODIUM.getStackForm()) - .duration(100).EUt(2) + CANNER_RECIPES.recipeBuilder().duration(400).EUt(2) + .input(BATTERY_HULL_MV) + .input(dust, Lithium, 8) + .output(BATTERY_MV_LITHIUM) .buildAndRegister(); - RecipeMaps.CANNER_RECIPES.recipeBuilder() - .inputs(BATTERY_HULL_MV.getStackForm()) - .input(OrePrefix.dust, Materials.Cadmium, 8) - .outputs(BATTERY_RE_MV_CADMIUM.getStackForm()) - .duration(400).EUt(2) + CANNER_RECIPES.recipeBuilder().duration(400).EUt(2) + .input(BATTERY_HULL_MV) + .input(dust, Sodium, 8) + .output(BATTERY_MV_SODIUM) .buildAndRegister(); - RecipeMaps.CANNER_RECIPES.recipeBuilder() - .inputs(BATTERY_HULL_MV.getStackForm()) - .input(OrePrefix.dust, Materials.Lithium, 8) - .outputs(BATTERY_RE_MV_LITHIUM.getStackForm()) - .duration(400).EUt(2) + // HV + CANNER_RECIPES.recipeBuilder().duration(1600).EUt(2) + .input(BATTERY_HULL_HV) + .input(dust, Cadmium, 16) + .output(BATTERY_HV_CADMIUM) .buildAndRegister(); - RecipeMaps.CANNER_RECIPES.recipeBuilder() - .inputs(BATTERY_HULL_MV.getStackForm()) - .input(OrePrefix.dust, Materials.Sodium, 8) - .outputs(BATTERY_RE_MV_SODIUM.getStackForm()) - .duration(400).EUt(2) + CANNER_RECIPES.recipeBuilder().duration(1600).EUt(2) + .input(BATTERY_HULL_HV) + .input(dust, Lithium, 16) + .output(BATTERY_HV_LITHIUM) .buildAndRegister(); - RecipeMaps.CANNER_RECIPES.recipeBuilder() - .inputs(BATTERY_HULL_HV.getStackForm()) - .input(OrePrefix.dust, Materials.Cadmium, 16) - .outputs(BATTERY_RE_HV_CADMIUM.getStackForm()) - .duration(1600).EUt(2) + CANNER_RECIPES.recipeBuilder().duration(1600).EUt(2) + .input(BATTERY_HULL_HV) + .input(dust, Sodium, 16) + .output(BATTERY_HV_SODIUM) .buildAndRegister(); - RecipeMaps.CANNER_RECIPES.recipeBuilder() - .inputs(BATTERY_HULL_HV.getStackForm()) - .input(OrePrefix.dust, Materials.Lithium, 16) - .outputs(BATTERY_RE_HV_LITHIUM.getStackForm()) - .duration(1600).EUt(2) + // EV + CANNER_RECIPES.recipeBuilder().duration(100).EUt(480) + .input(BATTERY_HULL_SMALL_VANADIUM) + .input(dust, Vanadium, 2) + .output(BATTERY_EV_VANADIUM) .buildAndRegister(); - RecipeMaps.CANNER_RECIPES.recipeBuilder() - .inputs(BATTERY_HULL_HV.getStackForm()) - .input(OrePrefix.dust, Materials.Sodium, 16) - .outputs(BATTERY_RE_HV_SODIUM.getStackForm()) - .duration(1600).EUt(2) + // IV + CANNER_RECIPES.recipeBuilder().duration(150).EUt(1024) + .input(BATTERY_HULL_MEDIUM_VANADIUM) + .input(dust, Vanadium, 8) + .output(BATTERY_IV_VANADIUM) .buildAndRegister(); + + // LuV + CANNER_RECIPES.recipeBuilder().duration(200).EUt(1920) + .input(BATTERY_HULL_LARGE_VANADIUM) + .input(dust, Vanadium, 16) + .output(BATTERY_LUV_VANADIUM) + .buildAndRegister(); + + // ZPM + CANNER_RECIPES.recipeBuilder().duration(250).EUt(4096) + .input(BATTERY_HULL_MEDIUM_NAQUADRIA) + .input(dust, Naquadria, 8) + .output(BATTERY_ZPM_NAQUADRIA) + .buildAndRegister(); + + // UV + CANNER_RECIPES.recipeBuilder().duration(300).EUt(7680) + .input(BATTERY_HULL_LARGE_NAQUADRIA) + .input(dust, Naquadria, 16) + .output(BATTERY_UV_NAQUADRIA) + .buildAndRegister(); + + + // Battery Recycling Recipes + EXTRACTOR_RECIPES.recipeBuilder().input(BATTERY_LV_CADMIUM).output(BATTERY_HULL_LV).buildAndRegister(); + EXTRACTOR_RECIPES.recipeBuilder().input(BATTERY_LV_LITHIUM).output(BATTERY_HULL_LV).buildAndRegister(); + EXTRACTOR_RECIPES.recipeBuilder().input(BATTERY_LV_SODIUM).output(BATTERY_HULL_LV).buildAndRegister(); + + EXTRACTOR_RECIPES.recipeBuilder().input(BATTERY_MV_CADMIUM).output(BATTERY_HULL_MV).buildAndRegister(); + EXTRACTOR_RECIPES.recipeBuilder().input(BATTERY_MV_LITHIUM).output(BATTERY_HULL_MV).buildAndRegister(); + EXTRACTOR_RECIPES.recipeBuilder().input(BATTERY_MV_SODIUM).output(BATTERY_HULL_MV).buildAndRegister(); + + EXTRACTOR_RECIPES.recipeBuilder().input(BATTERY_HV_CADMIUM).output(BATTERY_HULL_HV).buildAndRegister(); + EXTRACTOR_RECIPES.recipeBuilder().input(BATTERY_HV_LITHIUM).output(BATTERY_HULL_HV).buildAndRegister(); + EXTRACTOR_RECIPES.recipeBuilder().input(BATTERY_HV_SODIUM).output(BATTERY_HULL_HV).buildAndRegister(); + + EXTRACTOR_RECIPES.recipeBuilder().input(BATTERY_EV_VANADIUM).output(BATTERY_HULL_SMALL_VANADIUM).buildAndRegister(); + EXTRACTOR_RECIPES.recipeBuilder().input(BATTERY_IV_VANADIUM).output(BATTERY_HULL_MEDIUM_VANADIUM).buildAndRegister(); + EXTRACTOR_RECIPES.recipeBuilder().input(BATTERY_LUV_VANADIUM).output(BATTERY_HULL_LARGE_VANADIUM).buildAndRegister(); + + EXTRACTOR_RECIPES.recipeBuilder().input(BATTERY_ZPM_NAQUADRIA).output(BATTERY_HULL_MEDIUM_NAQUADRIA).buildAndRegister(); + EXTRACTOR_RECIPES.recipeBuilder().input(BATTERY_UV_NAQUADRIA).output(BATTERY_HULL_LARGE_NAQUADRIA).buildAndRegister(); } } diff --git a/src/main/java/gregtech/loaders/recipe/CircuitRecipes.java b/src/main/java/gregtech/loaders/recipe/CircuitRecipes.java index 8644b33876f..8ae1c678b01 100644 --- a/src/main/java/gregtech/loaders/recipe/CircuitRecipes.java +++ b/src/main/java/gregtech/loaders/recipe/CircuitRecipes.java @@ -56,7 +56,7 @@ private static void waferRecipes() { BLAST_RECIPES.recipeBuilder().duration(18000).EUt(7680) .input(block, Silicon, 32) .input(ingot, Neutronium, 4) - .fluidInputs(Radon.getFluid(8000)) + .fluidInputs(Xenon.getFluid(8000)) .output(NEUTRONIUM_BOULE) .blastFurnaceTemp(6484) .buildAndRegister(); @@ -198,7 +198,7 @@ private static void componentRecipes() { .output(VACUUM_TUBE, 6) .buildAndRegister(); - ALLOY_SMELTER_RECIPES.recipeBuilder().duration(240).EUt(8) + ALLOY_SMELTER_RECIPES.recipeBuilder().duration(160).EUt(16) .input(dust, Glass) .notConsumable(SHAPE_MOLD_BALL) .output(GLASS_TUBE) @@ -1360,7 +1360,7 @@ private static void circuitRecipes() { .input(ADVANCED_SMD_RESISTOR, 32) .input(foil, SiliconeRubber, 64) .input(RANDOM_ACCESS_MEMORY, 32) - .input(wireGtDouble, Tier.Superconductor, 16) + .input(wireGtDouble, EnrichedNaquadahTriniumEuropiumDuranide, 16) .input(plate, Europium, 8) .fluidInputs(SolderingAlloy.getFluid(L * 20)) .fluidInputs(Polybenzimidazole.getFluid(L * 8)) diff --git a/src/main/java/gregtech/loaders/recipe/CraftingComponent.java b/src/main/java/gregtech/loaders/recipe/CraftingComponent.java index c4f02a998e7..407d57e90a6 100644 --- a/src/main/java/gregtech/loaders/recipe/CraftingComponent.java +++ b/src/main/java/gregtech/loaders/recipe/CraftingComponent.java @@ -17,8 +17,6 @@ import java.util.stream.Collectors; import java.util.stream.Stream; -import static gregtech.common.blocks.HermeticCasings.HermeticCasingsType.*; - public class CraftingComponent { public static Component CIRCUIT; @@ -50,7 +48,6 @@ public class CraftingComponent { public static Component STICK_ELECTROMAGNETIC; public static Component STICK_RADIOACTIVE; public static Component PIPE_REACTOR; - public static Component HERMETIC_CASINGS; public static void initializeComponents() { @@ -70,6 +67,11 @@ public static void initializeComponents() { {7, new UnificationEntry(OrePrefix.circuit, Tier.Ultimate)}, {8, new UnificationEntry(OrePrefix.circuit, Tier.Superconductor)}, {9, new UnificationEntry(OrePrefix.circuit, Tier.Infinite)}, + {10, new UnificationEntry(OrePrefix.circuit, Tier.Ultra)}, + {11, new UnificationEntry(OrePrefix.circuit, Tier.Insane)}, + {12, new UnificationEntry(OrePrefix.circuit, Tier.UMVCircuit)}, + {13, new UnificationEntry(OrePrefix.circuit, Tier.UXVCircuit)}, + {14, new UnificationEntry(OrePrefix.circuit, Tier.Maximum)} }).collect(Collectors.toMap(data -> (Integer) data[0], data -> data[1]))); @@ -84,6 +86,11 @@ public static void initializeComponents() { {6, new UnificationEntry(OrePrefix.circuit, Tier.Ultimate)}, {7, new UnificationEntry(OrePrefix.circuit, Tier.Superconductor)}, {8, new UnificationEntry(OrePrefix.circuit, Tier.Infinite)}, + {9, new UnificationEntry(OrePrefix.circuit, Tier.Ultra)}, + {10, new UnificationEntry(OrePrefix.circuit, Tier.Insane)}, + {11, new UnificationEntry(OrePrefix.circuit, Tier.UMVCircuit)}, + {12, new UnificationEntry(OrePrefix.circuit, Tier.UXVCircuit)}, + {13, new UnificationEntry(OrePrefix.circuit, Tier.Maximum)} }).collect(Collectors.toMap(data -> (Integer) data[0], data -> data[1]))); @@ -223,14 +230,14 @@ public static void initializeComponents() { MOTOR = new Component(Stream.of(new Object[][]{ - {1, MetaItems.ELECTRIC_MOTOR_LV.getStackForm(),}, - {2, MetaItems.ELECTRIC_MOTOR_MV.getStackForm(),}, - {3, MetaItems.ELECTRIC_MOTOR_HV.getStackForm(),}, - {4, MetaItems.ELECTRIC_MOTOR_EV.getStackForm(),}, - {5, MetaItems.ELECTRIC_MOTOR_IV.getStackForm(),}, - {6, MetaItems.ELECTRIC_MOTOR_LUV.getStackForm(),}, - {7, MetaItems.ELECTRIC_MOTOR_ZPM.getStackForm(),}, - {8, MetaItems.ELECTRIC_MOTOR_UV.getStackForm(),}, + {1, MetaItems.ELECTRIC_MOTOR_LV.getStackForm()}, + {2, MetaItems.ELECTRIC_MOTOR_MV.getStackForm()}, + {3, MetaItems.ELECTRIC_MOTOR_HV.getStackForm()}, + {4, MetaItems.ELECTRIC_MOTOR_EV.getStackForm()}, + {5, MetaItems.ELECTRIC_MOTOR_IV.getStackForm()}, + {6, MetaItems.ELECTRIC_MOTOR_LUV.getStackForm()}, + {7, MetaItems.ELECTRIC_MOTOR_ZPM.getStackForm()}, + {8, MetaItems.ELECTRIC_MOTOR_UV.getStackForm()}, }).collect(Collectors.toMap(data -> (Integer) data[0], data -> data[1]))); @@ -452,23 +459,6 @@ public static void initializeComponents() { {GTValues.FALLBACK, new UnificationEntry(OrePrefix.pipeNormalFluid, Materials.Polyethylene)}, }).collect(Collectors.toMap(data -> (Integer) data[0], data -> data[1]))); - - - HERMETIC_CASINGS = new Component(Stream.of(new Object[][]{ - - {1, MetaBlocks.HERMETIC_CASING.getItemVariant(HERMETIC_LV)}, - {2, MetaBlocks.HERMETIC_CASING.getItemVariant(HERMETIC_MV)}, - {3, MetaBlocks.HERMETIC_CASING.getItemVariant(HERMETIC_HV)}, - {4, MetaBlocks.HERMETIC_CASING.getItemVariant(HERMETIC_EV)}, - {5, MetaBlocks.HERMETIC_CASING.getItemVariant(HERMETIC_IV)}, - {6, MetaBlocks.HERMETIC_CASING.getItemVariant(HERMETIC_LUV)}, - {7, MetaBlocks.HERMETIC_CASING.getItemVariant(HERMETIC_ZPM)}, - {8, MetaBlocks.HERMETIC_CASING.getItemVariant(HERMETIC_UV)}, - {14, MetaBlocks.HERMETIC_CASING.getItemVariant(HERMETIC_MAX)}, - - {GTValues.FALLBACK, new UnificationEntry(OrePrefix.pipeNormalFluid, Materials.Polyethylene)}, - - }).collect(Collectors.toMap(data -> (Integer) data[0], data -> data[1]))); } @@ -476,7 +466,7 @@ public static class Component { private final Map ingredients; - private Component(Map craftingComponents) { + public Component(Map craftingComponents) { ingredients = craftingComponents; } diff --git a/src/main/java/gregtech/loaders/recipe/CraftingRecipeLoader.java b/src/main/java/gregtech/loaders/recipe/CraftingRecipeLoader.java index 61db15f0142..0795b8a96a4 100644 --- a/src/main/java/gregtech/loaders/recipe/CraftingRecipeLoader.java +++ b/src/main/java/gregtech/loaders/recipe/CraftingRecipeLoader.java @@ -109,17 +109,12 @@ private static void loadCraftingRecipes() { ModHandler.addShapelessRecipe("dust_cobalt_brass", OreDictUnifier.get(OrePrefix.dust, Materials.CobaltBrass, 8), new UnificationEntry(OrePrefix.dust, Materials.Brass), new UnificationEntry(OrePrefix.dust, Materials.Brass), new UnificationEntry(OrePrefix.dust, Materials.Brass), new UnificationEntry(OrePrefix.dust, Materials.Brass), new UnificationEntry(OrePrefix.dust, Materials.Brass), new UnificationEntry(OrePrefix.dust, Materials.Brass), new UnificationEntry(OrePrefix.dust, Materials.Brass), new UnificationEntry(OrePrefix.dust, Materials.Aluminium), new UnificationEntry(OrePrefix.dust, Materials.Cobalt)); ModHandler.addShapelessRecipe("dust_stainless_steel", OreDictUnifier.get(OrePrefix.dust, Materials.StainlessSteel, 8), new UnificationEntry(OrePrefix.dust, Materials.Iron), new UnificationEntry(OrePrefix.dust, Materials.Iron), new UnificationEntry(OrePrefix.dust, Materials.Iron), new UnificationEntry(OrePrefix.dust, Materials.Iron), new UnificationEntry(OrePrefix.dust, Materials.Iron), new UnificationEntry(OrePrefix.dust, Materials.Iron), new UnificationEntry(OrePrefix.dust, Materials.Nickel), new UnificationEntry(OrePrefix.dust, Materials.Manganese), new UnificationEntry(OrePrefix.dust, Materials.Chrome)); - ModHandler.addShapedRecipe("battery_hull_lv", MetaItems.BATTERY_HULL_LV.getStackForm(), "C", "P", "P", 'C', new UnificationEntry(OrePrefix.cableGtSingle, Materials.Tin), 'P', new UnificationEntry(OrePrefix.plate, Materials.BatteryAlloy)); - ModHandler.addShapedRecipe("battery_hull_mv", MetaItems.BATTERY_HULL_MV.getStackForm(), "C C", "PPP", "PPP", 'C', new UnificationEntry(OrePrefix.cableGtSingle, Materials.Copper), 'P', new UnificationEntry(OrePrefix.plate, Materials.BatteryAlloy)); - ModHandler.addShapedRecipe("carbon_mesh", MetaItems.CARBON_MESH.getStackForm(), "XX", 'X', MetaItems.CARBON_FIBERS.getStackForm()); ModHandler.addShapedRecipe("component_grinder_diamond", MetaItems.COMPONENT_GRINDER_DIAMOND.getStackForm(), "XSX", "SDS", "XSX", 'X', new UnificationEntry(OrePrefix.dust, Materials.Diamond), 'S', new UnificationEntry(OrePrefix.plate, Materials.Steel), 'D', new UnificationEntry(OrePrefix.gem, Materials.Diamond)); ModHandler.addShapedRecipe("component_grinder_tungsten", MetaItems.COMPONENT_GRINDER_TUNGSTEN.getStackForm(), "WSW", "SDS", "WSW", 'W', new UnificationEntry(OrePrefix.plate, Materials.Tungsten), 'S', new UnificationEntry(OrePrefix.plate, Materials.Steel), 'D', new UnificationEntry(OrePrefix.gem, Materials.Diamond)); ModHandler.addShapedRecipe("component_sawblade_diamond", MetaItems.COMPONENT_SAW_BLADE_DIAMOND.getStackForm(), " D ", "DGD", " D ", 'D', new UnificationEntry(OrePrefix.dustSmall, Materials.Diamond), 'G', new UnificationEntry(OrePrefix.gear, Materials.CobaltBrass)); - ModHandler.addShapedRecipe("energy_field_projector", MetaItems.ENERGY_FIELD_PROJECTOR.getStackForm(), "PLP", "LFL", "PLP", 'P', MetaItems.PLATE_IRIDIUM_ALLOY.getStackForm(), 'L', MetaItems.LAPOTRON_CRYSTAL.getStackForm(), 'F', MetaItems.FIELD_GENERATOR_EV); - ModHandler.addShapedRecipe("ingot_iridium_alloy", MetaItems.INGOT_IRIDIUM_ALLOY.getStackForm(), "IWI", "WDW", "IWI", 'I', new UnificationEntry(OrePrefix.plate, Materials.Iridium), 'W', MetaItems.ADVANCED_ALLOY_PLATE, 'D', new ItemStack(Items.DIAMOND)); ModHandler.addShapedRecipe("nano_saber", MetaItems.NANO_SABER.getStackForm(), "PIC", "PIC", "XEX", 'P', new UnificationEntry(OrePrefix.plate, Materials.Platinum), 'I', MetaItems.PLATE_IRIDIUM_ALLOY.getStackForm(), 'C', MetaItems.CARBON_PLATE.getStackForm(), 'X', new UnificationEntry(OrePrefix.circuit, Tier.Extreme), 'E', MetaItems.ENERGY_CRYSTAL.getStackForm()); diff --git a/src/main/java/gregtech/loaders/recipe/MachineRecipeLoader.java b/src/main/java/gregtech/loaders/recipe/MachineRecipeLoader.java index 9af147b3bcc..a7cee977160 100644 --- a/src/main/java/gregtech/loaders/recipe/MachineRecipeLoader.java +++ b/src/main/java/gregtech/loaders/recipe/MachineRecipeLoader.java @@ -4,8 +4,6 @@ import gregtech.api.items.metaitem.MetaItem; import gregtech.api.recipes.ModHandler; import gregtech.api.recipes.RecipeMaps; -import gregtech.api.recipes.builders.CokeOvenRecipeBuilder; -import gregtech.api.recipes.builders.PBFRecipeBuilder; import gregtech.api.recipes.ingredients.IntCircuitIngredient; import gregtech.api.unification.OreDictUnifier; import gregtech.api.unification.material.MarkerMaterials; @@ -85,7 +83,7 @@ private static void registerBendingCompressingRecipes() { COMPRESSOR_RECIPES.recipeBuilder() .input(OrePrefix.dust, Materials.Fireclay) .outputs(MetaItems.COMPRESSED_FIRECLAY.getStackForm()) - .duration(100).EUt(2) + .duration(80).EUt(4) .buildAndRegister(); FORMING_PRESS_RECIPES.recipeBuilder() @@ -199,17 +197,35 @@ private static void registerBendingCompressingRecipes() { .duration(400).EUt(2).buildAndRegister(); } + // todo this should be done better but will work for now private static void registerPrimitiveBlastFurnaceRecipes() { - PBFRecipeBuilder.start().input(ingot, Iron).output(ingot, Steel).duration(1500).fuelAmount(2).buildAndRegister(); - PBFRecipeBuilder.start().input(block, Iron).output(block, Steel).duration(13500).fuelAmount(18).buildAndRegister(); - PBFRecipeBuilder.start().input(ingot, WroughtIron).output(ingot, Steel).duration(600).fuelAmount(2).buildAndRegister(); - PBFRecipeBuilder.start().input(block, WroughtIron).output(block, Steel).duration(5600).fuelAmount(18).buildAndRegister(); + PRIMITIVE_BLAST_FURNACE_RECIPES.recipeBuilder().input(ingot, Iron).input(gem, Coal, 2).output(ingot, Steel).duration(1500).buildAndRegister(); + PRIMITIVE_BLAST_FURNACE_RECIPES.recipeBuilder().input(ingot, Iron).input(dust, Coal, 2).output(ingot, Steel).duration(1500).buildAndRegister(); + PRIMITIVE_BLAST_FURNACE_RECIPES.recipeBuilder().input(ingot, Iron).input(gem, Charcoal, 2).output(ingot, Steel).duration(1500).buildAndRegister(); + PRIMITIVE_BLAST_FURNACE_RECIPES.recipeBuilder().input(ingot, Iron).input(dust, Charcoal, 2).output(ingot, Steel).duration(1500).buildAndRegister(); + PRIMITIVE_BLAST_FURNACE_RECIPES.recipeBuilder().input(ingot, Iron).input(gem, Lignite, 3).output(ingot, Steel).duration(1500).buildAndRegister(); + PRIMITIVE_BLAST_FURNACE_RECIPES.recipeBuilder().input(ingot, Iron).input(dust, Lignite, 3).output(ingot, Steel).duration(1500).buildAndRegister(); + + PRIMITIVE_BLAST_FURNACE_RECIPES.recipeBuilder().input(block, Iron).input(block, Coal, 2).output(block, Steel).duration(13500).buildAndRegister(); + PRIMITIVE_BLAST_FURNACE_RECIPES.recipeBuilder().input(block, Iron).input(block, Charcoal, 2).output(block, Steel).duration(13500).buildAndRegister(); + PRIMITIVE_BLAST_FURNACE_RECIPES.recipeBuilder().input(block, Iron).input(block, Lignite, 3).output(block, Steel).duration(13500).buildAndRegister(); + + PRIMITIVE_BLAST_FURNACE_RECIPES.recipeBuilder().input(ingot, WroughtIron).input(gem, Coal, 2).output(ingot, Steel).duration(600).buildAndRegister(); + PRIMITIVE_BLAST_FURNACE_RECIPES.recipeBuilder().input(ingot, WroughtIron).input(dust, Coal, 2).output(ingot, Steel).duration(600).buildAndRegister(); + PRIMITIVE_BLAST_FURNACE_RECIPES.recipeBuilder().input(ingot, WroughtIron).input(gem, Charcoal, 2).output(ingot, Steel).duration(600).buildAndRegister(); + PRIMITIVE_BLAST_FURNACE_RECIPES.recipeBuilder().input(ingot, WroughtIron).input(dust, Charcoal, 2).output(ingot, Steel).duration(600).buildAndRegister(); + PRIMITIVE_BLAST_FURNACE_RECIPES.recipeBuilder().input(ingot, WroughtIron).input(gem, Lignite, 3).output(ingot, Steel).duration(600).buildAndRegister(); + PRIMITIVE_BLAST_FURNACE_RECIPES.recipeBuilder().input(ingot, WroughtIron).input(dust, Lignite, 3).output(ingot, Steel).duration(600).buildAndRegister(); + + PRIMITIVE_BLAST_FURNACE_RECIPES.recipeBuilder().input(block, WroughtIron).input(block, Coal, 2).output(block, Steel).duration(5600).buildAndRegister(); + PRIMITIVE_BLAST_FURNACE_RECIPES.recipeBuilder().input(block, WroughtIron).input(block, Charcoal, 2).output(block, Steel).duration(5600).buildAndRegister(); + PRIMITIVE_BLAST_FURNACE_RECIPES.recipeBuilder().input(block, WroughtIron).input(block, Lignite, 3).output(block, Steel).duration(5600).buildAndRegister(); } private static void registerCokeOvenRecipes() { - CokeOvenRecipeBuilder.start().input(OrePrefix.log, Materials.Wood).output(OreDictUnifier.get(OrePrefix.gem, Materials.Charcoal)).fluidOutput(Materials.Creosote.getFluid(250)).duration(900).buildAndRegister(); - CokeOvenRecipeBuilder.start().input(OrePrefix.gem, Materials.Coal).output(OreDictUnifier.get(OrePrefix.gem, Materials.Coke)).fluidOutput(Materials.Creosote.getFluid(500)).duration(900).buildAndRegister(); - CokeOvenRecipeBuilder.start().input(OrePrefix.block, Materials.Coal).output(OreDictUnifier.get(OrePrefix.block, Materials.Coke)).fluidOutput(Materials.Creosote.getFluid(4500)).duration(8100).buildAndRegister(); + COKE_OVEN_RECIPES.recipeBuilder().input(log, Wood).output(gem, Charcoal).fluidOutputs(Creosote.getFluid(250)).duration(900).buildAndRegister(); + COKE_OVEN_RECIPES.recipeBuilder().input(gem, Coal).output(gem, Coke).fluidOutputs(Creosote.getFluid(500)).duration(900).buildAndRegister(); + COKE_OVEN_RECIPES.recipeBuilder().input(block, Coal).output(block, Coke).fluidOutputs(Creosote.getFluid(4500)).duration(8100).buildAndRegister(); } private static void registerStoneBricksRecipes() { @@ -229,14 +245,6 @@ private static void registerStoneBricksRecipes() { private static void registerMixingCrystallizationRecipes() { - RecipeMaps.MIXER_RECIPES.recipeBuilder() - .input(OrePrefix.dust, Materials.Lead, 2) - .input(OrePrefix.dust, Materials.Bronze, 2) - .input(OrePrefix.dust, Materials.Tin, 1) - .output(OrePrefix.dust, Materials.Potin, 5) - .duration(500).EUt(8) - .buildAndRegister(); - RecipeMaps.MIXER_RECIPES.recipeBuilder() .input(OrePrefix.dust, Materials.Stone, 1) .fluidInputs(Materials.Lubricant.getFluid(20), Materials.Water.getFluid(4980)) @@ -269,9 +277,9 @@ private static void registerMixingCrystallizationRecipes() { .buildAndRegister(); RecipeMaps.MIXER_RECIPES.recipeBuilder() - .duration(1200).EUt(16) - .input(OrePrefix.dust, Materials.Ruby, 9) - .input(OrePrefix.dust, Materials.Redstone, 9) + .duration(600).EUt(120) + .input(OrePrefix.dust, Materials.Ruby, 4) + .input(OrePrefix.dust, Materials.Redstone, 5) .outputs(MetaItems.ENERGIUM_DUST.getStackForm(9)) .buildAndRegister(); @@ -383,8 +391,8 @@ private static void registerAlloyRecipes() { ALLOY_SMELTER_RECIPES.recipeBuilder().duration(400).EUt(4).input(OrePrefix.dust, Materials.Glass, 3).inputs(MetaItems.ADVANCED_ALLOY_PLATE.getStackForm()).outputs(MetaBlocks.TRANSPARENT_CASING.getItemVariant(BlockTransparentCasing.CasingType.REINFORCED_GLASS, 4)).buildAndRegister(); ALLOY_SMELTER_RECIPES.recipeBuilder().duration(400).EUt(4).inputs(new ItemStack(Blocks.GLASS)).inputs(MetaItems.ADVANCED_ALLOY_PLATE.getStackForm()).outputs(MetaBlocks.TRANSPARENT_CASING.getItemVariant(BlockTransparentCasing.CasingType.REINFORCED_GLASS, 4)).buildAndRegister(); - ALLOY_SMELTER_RECIPES.recipeBuilder().duration(10).EUt(8).input(OrePrefix.ingot, Materials.Rubber, 2).notConsumable(MetaItems.SHAPE_MOLD_PLATE).output(OrePrefix.plate, Materials.Rubber).buildAndRegister(); - ALLOY_SMELTER_RECIPES.recipeBuilder().duration(100).EUt(1).input(OrePrefix.dust, Materials.Sulfur).input(OrePrefix.dust, Materials.RawRubber, 3).output(OrePrefix.ingot, Materials.Rubber).buildAndRegister(); + ALLOY_SMELTER_RECIPES.recipeBuilder().duration(10).EUt(7).input(OrePrefix.ingot, Materials.Rubber, 2).notConsumable(MetaItems.SHAPE_MOLD_PLATE).output(OrePrefix.plate, Materials.Rubber).buildAndRegister(); + ALLOY_SMELTER_RECIPES.recipeBuilder().duration(100).EUt(7).input(OrePrefix.dust, Materials.Sulfur).input(OrePrefix.dust, Materials.RawRubber, 3).output(OrePrefix.ingot, Materials.Rubber).buildAndRegister(); } private static void registerAssemblerRecipes() { @@ -397,18 +405,6 @@ private static void registerAssemblerRecipes() { .buildAndRegister(); } - //todo fix -// for (Material cableMaterial : new Material[]{Materials.YttriumBariumCuprate, Materials.NiobiumTitanium, Materials.VanadiumGallium, Materials.Naquadah}) { -// RecipeMaps.ASSEMBLER_RECIPES.recipeBuilder() -// .input(OrePrefix.wireGtSingle, cableMaterial, 3) -// .input(OrePrefix.pipeTinyFluid, Materials.TungstenSteel, 2) -// .inputs(MetaItems.ELECTRIC_PUMP_LV.getStackForm(2)) -// .fluidInputs(Materials.Nitrogen.getFluid(2000)) -// .outputs(OreDictUnifier.get(OrePrefix.wireGtSingle, Tier.Superconductor, 3)) -// .duration(20).EUt(512) -// .buildAndRegister(); -// } - Material[] coverMaterials = new Material[]{Materials.Iron, Materials.WroughtIron, Materials.Aluminium}; for (Material material : coverMaterials) { @@ -471,6 +467,14 @@ private static void registerAssemblerRecipes() { .EUt(16).duration(50) .buildAndRegister(); + ASSEMBLER_RECIPES.recipeBuilder() + .input(ELECTRIC_PUMP_HV, 2) + .inputs(new ItemStack(Items.CAULDRON)) + .input(circuit, MarkerMaterials.Tier.Advanced) + .output(COVER_INFINITE_WATER) + .EUt(480).duration(200) + .buildAndRegister(); + RecipeMaps.ASSEMBLER_RECIPES.recipeBuilder().EUt(16).input(OrePrefix.plate, Materials.WroughtIron, 8).outputs(MetaBlocks.MACHINE_CASING.getItemVariant(MachineCasingType.ULV)).circuitMeta(8).duration(25).buildAndRegister(); RecipeMaps.ASSEMBLER_RECIPES.recipeBuilder().EUt(16).input(OrePrefix.plate, Materials.Steel, 8).outputs(MetaBlocks.MACHINE_CASING.getItemVariant(MachineCasingType.LV)).circuitMeta(8).duration(50).buildAndRegister(); RecipeMaps.ASSEMBLER_RECIPES.recipeBuilder().EUt(16).input(OrePrefix.plate, Materials.Aluminium, 8).outputs(MetaBlocks.MACHINE_CASING.getItemVariant(MachineCasingType.MV)).circuitMeta(8).duration(50).buildAndRegister(); @@ -549,11 +553,6 @@ private static void registerAssemblerRecipes() { RecipeMaps.ASSEMBLER_RECIPES.recipeBuilder().duration(50).EUt(16).inputs(MetaBlocks.MACHINE_CASING.getItemVariant(MachineCasingType.MAX)).input(OrePrefix.wireGtSingle, MarkerMaterials.Tier.Superconductor, 2).outputs(MetaTileEntities.HULL[14].getStackForm()).buildAndRegister(); } - ASSEMBLER_RECIPES.recipeBuilder().duration(800).EUt(1).input(cableGtSingle, Tin).input(plate, BatteryAlloy).fluidInputs(Polyethylene.getFluid(144)).output(BATTERY_HULL_LV).buildAndRegister(); - ASSEMBLER_RECIPES.recipeBuilder().duration(1600).EUt(2).input(cableGtSingle, Copper, 2).input(plate, BatteryAlloy, 3).fluidInputs(Polyethylene.getFluid(432)).output(BATTERY_HULL_MV).buildAndRegister(); - ASSEMBLER_RECIPES.recipeBuilder().duration(1600).EUt(2).input(cableGtSingle, AnnealedCopper, 2).input(plate, BatteryAlloy, 3).fluidInputs(Polyethylene.getFluid(432)).output(BATTERY_HULL_MV).buildAndRegister(); - ASSEMBLER_RECIPES.recipeBuilder().duration(3200).EUt(4).input(cableGtSingle, Gold, 4).input(plate, BatteryAlloy, 9).fluidInputs(Polyethylene.getFluid(1296)).output(BATTERY_HULL_HV).buildAndRegister(); - ASSEMBLER_RECIPES.recipeBuilder().EUt(2).inputs(new ItemStack(Blocks.CHEST, 1, GTValues.W)).input(plate, Iron, 5).outputs(new ItemStack(Blocks.HOPPER)).duration(800).buildAndRegister(); ASSEMBLER_RECIPES.recipeBuilder().EUt(2).inputs(new ItemStack(Blocks.TRAPPED_CHEST, 1, GTValues.W)).input(plate, Iron, 5).outputs(new ItemStack(Blocks.HOPPER)).duration(800).buildAndRegister(); ASSEMBLER_RECIPES.recipeBuilder().EUt(2).input(gear, CobaltBrass).input(dust, Diamond).output(COMPONENT_SAW_BLADE_DIAMOND).duration(1600).buildAndRegister(); @@ -648,8 +647,8 @@ private static void registerDecompositionRecipes() { EXTRACTOR_RECIPES.recipeBuilder() .inputs(RUBBER_DROP.getStackForm()) - .output(dust, RawRubber, 4) - .duration(300).EUt(2) + .output(dust, RawRubber, 3) + .duration(150).EUt(2) .buildAndRegister(); EXTRACTOR_RECIPES.recipeBuilder().duration(300).EUt(2) diff --git a/src/main/java/gregtech/loaders/recipe/MetaTileEntityLoader.java b/src/main/java/gregtech/loaders/recipe/MetaTileEntityLoader.java index df570b40c30..ff4c2f38a80 100644 --- a/src/main/java/gregtech/loaders/recipe/MetaTileEntityLoader.java +++ b/src/main/java/gregtech/loaders/recipe/MetaTileEntityLoader.java @@ -24,9 +24,7 @@ import net.minecraft.init.Blocks; import net.minecraft.item.ItemStack; -import java.util.ArrayList; import java.util.Arrays; -import java.util.List; import static gregtech.common.blocks.BlockBoilerCasing.BoilerCasingType.*; import static gregtech.common.blocks.BlockFireboxCasing.FireboxCasingType.*; @@ -43,7 +41,7 @@ public class MetaTileEntityLoader { public static void init() { - if (ConfigHolder.steelSteamMultiblocks) { + if (ConfigHolder.U.steelSteamMultiblocks) { ModHandler.addShapedRecipe("steam_oven", MetaTileEntities.STEAM_OVEN.getStackForm(), "CGC", "FMF", "CGC", 'F', MetaBlocks.BOILER_FIREBOX_CASING.getItemVariant(STEEL_FIREBOX), 'C', MetaBlocks.METAL_CASING.getItemVariant(STEEL_SOLID), 'M', MetaTileEntities.STEAM_FURNACE_STEEL.getStackForm(), 'G', new UnificationEntry(OrePrefix.gear, Materials.Invar)); ModHandler.addShapedRecipe("steam_grinder", MetaTileEntities.STEAM_GRINDER.getStackForm(), "CGC", "CFC", "CGC", 'G', new UnificationEntry(OrePrefix.gear, Materials.Potin), 'F', MetaTileEntities.STEAM_MACERATOR_STEEL.getStackForm(), 'C', MetaBlocks.METAL_CASING.getItemVariant(STEEL_SOLID)); ModHandler.addShapedRecipe("steam_hatch", MetaTileEntities.STEAM_HATCH.getStackForm(), "BPB", "BTB", "BPB", 'B', new UnificationEntry(OrePrefix.plate, Materials.Steel), 'P', new UnificationEntry(OrePrefix.pipeNormalFluid, Materials.Steel), 'T', MetaTileEntities.STEEL_TANK.getStackForm()); @@ -292,21 +290,16 @@ public static void init() { ModHandler.addShapedRecipe("battery_buffer_uv_4x4", MetaTileEntities.BATTERY_BUFFER[GTValues.UV][3].getStackForm(), "WTW", "WMW", 'M', MetaTileEntities.HULL[GTValues.UV].getStackForm(), 'W', new UnificationEntry(OrePrefix.wireGtHex, Materials.NaquadahAlloy), 'T', OreDictNames.chestWood); ModHandler.addShapedRecipe("battery_buffer_max_4x4", MetaTileEntities.BATTERY_BUFFER[GTValues.MAX][3].getStackForm(), "WTW", "WMW", 'M', MetaTileEntities.HULL[GTValues.MAX].getStackForm(), 'W', new UnificationEntry(OrePrefix.wireGtHex, MarkerMaterials.Tier.Superconductor), 'T', OreDictNames.chestWood); - List batteries = new ArrayList() {{ - add(ConfigHolder.U.GT5u.enableZPMandUVBats ? MetaItems.ENERGY_LAPOTRONIC_MODULE.getStackForm() : MetaItems.ENERGY_LAPOTRONIC_ORB2.getStackForm()); - add(ConfigHolder.U.GT5u.enableZPMandUVBats ? MetaItems.ENERGY_LAPOTRONIC_CLUSTER.getStackForm() : MetaItems.ULTIMATE_BATTERY.getStackForm()); - add(MetaItems.ULTIMATE_BATTERY.getStackForm()); - }}; - ModHandler.addShapedRecipe("charger_ulv", MetaTileEntities.CHARGER[GTValues.ULV].getStackForm(), "WTW", "WMW", "BCB", 'M', MetaTileEntities.HULL[GTValues.ULV].getStackForm(), 'W', new UnificationEntry(OrePrefix.wireGtHex, Materials.Lead), 'T', OreDictNames.chestWood, 'B', MetaItems.BATTERY_RE_ULV_TANTALUM, 'C', new UnificationEntry(OrePrefix.circuit, MarkerMaterials.Tier.Primitive)); - ModHandler.addShapedRecipe("charger_lv", MetaTileEntities.CHARGER[GTValues.LV].getStackForm(), "WTW", "WMW", "BCB", 'M', MetaTileEntities.HULL[GTValues.LV].getStackForm(), 'W', new UnificationEntry(OrePrefix.wireGtHex, Materials.Tin), 'T', OreDictNames.chestWood, 'B', MetaItems.BATTERY_RE_LV_LITHIUM, 'C', new UnificationEntry(OrePrefix.circuit, MarkerMaterials.Tier.Basic)); - ModHandler.addShapedRecipe("charger_mv", MetaTileEntities.CHARGER[GTValues.MV].getStackForm(), "WTW", "WMW", "BCB", 'M', MetaTileEntities.HULL[GTValues.MV].getStackForm(), 'W', new UnificationEntry(OrePrefix.wireGtHex, Materials.Copper), 'T', OreDictNames.chestWood, 'B', MetaItems.BATTERY_RE_MV_LITHIUM, 'C', new UnificationEntry(OrePrefix.circuit, MarkerMaterials.Tier.Good)); - ModHandler.addShapedRecipe("charger_hv", MetaTileEntities.CHARGER[GTValues.HV].getStackForm(), "WTW", "WMW", "BCB", 'M', MetaTileEntities.HULL[GTValues.HV].getStackForm(), 'W', new UnificationEntry(OrePrefix.wireGtHex, Materials.Gold), 'T', OreDictNames.chestWood, 'B', MetaItems.BATTERY_RE_HV_LITHIUM, 'C', new UnificationEntry(OrePrefix.circuit, MarkerMaterials.Tier.Advanced)); + ModHandler.addShapedRecipe("charger_ulv", MetaTileEntities.CHARGER[GTValues.ULV].getStackForm(), "WTW", "WMW", "BCB", 'M', MetaTileEntities.HULL[GTValues.ULV].getStackForm(), 'W', new UnificationEntry(OrePrefix.wireGtHex, Materials.Lead), 'T', OreDictNames.chestWood, 'B', MetaItems.BATTERY_ULV_TANTALUM, 'C', new UnificationEntry(OrePrefix.circuit, MarkerMaterials.Tier.Primitive)); + ModHandler.addShapedRecipe("charger_lv", MetaTileEntities.CHARGER[GTValues.LV].getStackForm(), "WTW", "WMW", "BCB", 'M', MetaTileEntities.HULL[GTValues.LV].getStackForm(), 'W', new UnificationEntry(OrePrefix.wireGtHex, Materials.Tin), 'T', OreDictNames.chestWood, 'B', MetaItems.BATTERY_LV_LITHIUM, 'C', new UnificationEntry(OrePrefix.circuit, MarkerMaterials.Tier.Basic)); + ModHandler.addShapedRecipe("charger_mv", MetaTileEntities.CHARGER[GTValues.MV].getStackForm(), "WTW", "WMW", "BCB", 'M', MetaTileEntities.HULL[GTValues.MV].getStackForm(), 'W', new UnificationEntry(OrePrefix.wireGtHex, Materials.Copper), 'T', OreDictNames.chestWood, 'B', MetaItems.BATTERY_MV_LITHIUM, 'C', new UnificationEntry(OrePrefix.circuit, MarkerMaterials.Tier.Good)); + ModHandler.addShapedRecipe("charger_hv", MetaTileEntities.CHARGER[GTValues.HV].getStackForm(), "WTW", "WMW", "BCB", 'M', MetaTileEntities.HULL[GTValues.HV].getStackForm(), 'W', new UnificationEntry(OrePrefix.wireGtHex, Materials.Gold), 'T', OreDictNames.chestWood, 'B', MetaItems.BATTERY_HV_LITHIUM, 'C', new UnificationEntry(OrePrefix.circuit, MarkerMaterials.Tier.Advanced)); ModHandler.addShapedRecipe("charger_ev", MetaTileEntities.CHARGER[GTValues.EV].getStackForm(), "WTW", "WMW", "BCB", 'M', MetaTileEntities.HULL[GTValues.EV].getStackForm(), 'W', new UnificationEntry(OrePrefix.wireGtHex, Materials.Aluminium), 'T', OreDictNames.chestWood, 'B', MetaItems.LAPOTRON_CRYSTAL, 'C', new UnificationEntry(OrePrefix.circuit, MarkerMaterials.Tier.Extreme)); ModHandler.addShapedRecipe("charger_iv", MetaTileEntities.CHARGER[GTValues.IV].getStackForm(), "WTW", "WMW", "BCB", 'M', MetaTileEntities.HULL[GTValues.IV].getStackForm(), 'W', new UnificationEntry(OrePrefix.wireGtHex, Materials.Tungsten), 'T', OreDictNames.chestWood, 'B', MetaItems.ENERGY_LAPOTRONIC_ORB, 'C', new UnificationEntry(OrePrefix.circuit, MarkerMaterials.Tier.Elite)); ModHandler.addShapedRecipe("charger_luv", MetaTileEntities.CHARGER[GTValues.LuV].getStackForm(), "WTW", "WMW", "BCB", 'M', MetaTileEntities.HULL[GTValues.LuV].getStackForm(), 'W', new UnificationEntry(OrePrefix.wireGtHex, Materials.VanadiumGallium), 'T', OreDictNames.chestWood, 'B', MetaItems.ENERGY_LAPOTRONIC_ORB2, 'C', new UnificationEntry(OrePrefix.circuit, Tier.Master)); - ModHandler.addShapedRecipe("charger_zpm", MetaTileEntities.CHARGER[GTValues.ZPM].getStackForm(), "WTW", "WMW", "BCB", 'M', MetaTileEntities.HULL[GTValues.ZPM].getStackForm(), 'W', new UnificationEntry(OrePrefix.wireGtHex, Materials.Naquadah), 'T', OreDictNames.chestWood, 'B', batteries.get(0), 'C', new UnificationEntry(OrePrefix.circuit, Tier.Ultimate)); - ModHandler.addShapedRecipe("charger_uv", MetaTileEntities.CHARGER[GTValues.UV].getStackForm(), "WTW", "WMW", "BCB", 'M', MetaTileEntities.HULL[GTValues.UV].getStackForm(), 'W', new UnificationEntry(OrePrefix.wireGtHex, Materials.NaquadahAlloy), 'T', OreDictNames.chestWood, 'B', batteries.get(1), 'C', new UnificationEntry(OrePrefix.circuit, MarkerMaterials.Tier.Superconductor)); - ModHandler.addShapedRecipe("charger_max", MetaTileEntities.CHARGER[GTValues.MAX].getStackForm(), "WTW", "WMW", "BCB", 'M', MetaTileEntities.HULL[GTValues.MAX].getStackForm(), 'W', new UnificationEntry(OrePrefix.wireGtHex, MarkerMaterials.Tier.Superconductor), 'T', OreDictNames.chestWood, 'B', batteries.get(2), 'C', new UnificationEntry(OrePrefix.circuit, MarkerMaterials.Tier.Infinite)); + ModHandler.addShapedRecipe("charger_zpm", MetaTileEntities.CHARGER[GTValues.ZPM].getStackForm(), "WTW", "WMW", "BCB", 'M', MetaTileEntities.HULL[GTValues.ZPM].getStackForm(), 'W', new UnificationEntry(OrePrefix.wireGtHex, Materials.Naquadah), 'T', OreDictNames.chestWood, 'B', MetaItems.ENERGY_LAPOTRONIC_MODULE, 'C', new UnificationEntry(OrePrefix.circuit, Tier.Ultimate)); + ModHandler.addShapedRecipe("charger_uv", MetaTileEntities.CHARGER[GTValues.UV].getStackForm(), "WTW", "WMW", "BCB", 'M', MetaTileEntities.HULL[GTValues.UV].getStackForm(), 'W', new UnificationEntry(OrePrefix.wireGtHex, Materials.NaquadahAlloy), 'T', OreDictNames.chestWood, 'B', MetaItems.ENERGY_LAPOTRONIC_CLUSTER, 'C', new UnificationEntry(OrePrefix.circuit, MarkerMaterials.Tier.Superconductor)); + ModHandler.addShapedRecipe("charger_max", MetaTileEntities.CHARGER[GTValues.MAX].getStackForm(), "WTW", "WMW", "BCB", 'M', MetaTileEntities.HULL[GTValues.MAX].getStackForm(), 'W', new UnificationEntry(OrePrefix.wireGtHex, MarkerMaterials.Tier.Superconductor), 'T', OreDictNames.chestWood, 'B', MetaItems.ULTIMATE_BATTERY, 'C', new UnificationEntry(OrePrefix.circuit, MarkerMaterials.Tier.Infinite)); ModHandler.addShapedRecipe("rotor_holder_hv", MetaTileEntities.ROTOR_HOLDER[0].getStackForm(), "WHW", "WRW", "WWW", 'H', MetaTileEntities.HULL[GTValues.HV].getStackForm(), 'W', new UnificationEntry(OrePrefix.wireGtHex, Materials.Gold), 'R', new UnificationEntry(OrePrefix.gear, Materials.StainlessSteel)); ModHandler.addShapedRecipe("rotor_holder_luv", MetaTileEntities.ROTOR_HOLDER[1].getStackForm(), "WHW", "WRW", "WWW", 'H', MetaTileEntities.HULL[GTValues.LuV].getStackForm(), 'W', new UnificationEntry(OrePrefix.wireGtHex, Materials.YttriumBariumCuprate), 'R', new UnificationEntry(OrePrefix.gear, Materials.Chrome)); @@ -316,26 +309,27 @@ public static void init() { ModHandler.addShapedRecipe("bronze_hull", MetaBlocks.STEAM_CASING.getItemVariant(BRONZE_HULL), "PPP", "PhP", "PPP", 'P', new UnificationEntry(OrePrefix.plate, Materials.Bronze)); ModHandler.addShapedRecipe("bronze_bricks_hull", MetaBlocks.STEAM_CASING.getItemVariant(BRONZE_BRICKS_HULL), "PPP", "PhP", "BBB", 'P', new UnificationEntry(OrePrefix.plate, Materials.Bronze), 'B', new ItemStack(Blocks.BRICK_BLOCK)); ModHandler.addShapedRecipe("steel_hull", MetaBlocks.STEAM_CASING.getItemVariant(STEEL_HULL), "PPP", "PhP", "PPP", 'P', new UnificationEntry(OrePrefix.plate, Materials.Steel)); - ModHandler.addShapedRecipe("steel_bricks_hull", MetaBlocks.STEAM_CASING.getItemVariant(STEEL_BRICKS_HULL), "PPP", "PhP", "BBB", 'P', new UnificationEntry(OrePrefix.plate, Materials.Steel), 'B', new ItemStack(Blocks.BRICK_BLOCK)); + ModHandler.addShapedRecipe("steel_bricks_hull", MetaBlocks.STEAM_CASING.getItemVariant(STEEL_BRICKS_HULL), "PPP", "PhP", "BBB", 'P', new UnificationEntry(OrePrefix.plate, Materials.WroughtIron), 'B', new ItemStack(Blocks.BRICK_BLOCK)); - ModHandler.addShapedRecipe("steam_boiler_coal_bronze", MetaTileEntities.STEAM_BOILER_COAL_BRONZE.getStackForm(), "PPP", "P P", "BFB", 'F', OreDictNames.craftingFurnace, 'P', new UnificationEntry(OrePrefix.plate, Materials.Bronze), 'B', new ItemStack(Blocks.BRICK_BLOCK)); - ModHandler.addShapedRecipe("steam_boiler_coal_steel", MetaTileEntities.STEAM_BOILER_COAL_STEEL.getStackForm(), "PPP", "P P", "BFB", 'F', OreDictNames.craftingFurnace, 'P', new UnificationEntry(OrePrefix.plate, Materials.Steel), 'B', new ItemStack(Blocks.BRICK_BLOCK)); - ModHandler.addShapedRecipe("steam_boiler_lava_bronze", MetaTileEntities.STEAM_BOILER_LAVA_BRONZE.getStackForm(), "PPP", "GGG", "PMP", 'M', MetaBlocks.STEAM_CASING.getItemVariant(BRONZE_BRICKS_HULL), 'P', new UnificationEntry(OrePrefix.plate, Materials.Bronze), 'G', new ItemStack(Blocks.GLASS, 1)); - ModHandler.addShapedRecipe("steam_boiler_lava_steel", MetaTileEntities.STEAM_BOILER_LAVA_STEEL.getStackForm(), "PPP", "GGG", "PMP", 'M', MetaBlocks.STEAM_CASING.getItemVariant(STEEL_BRICKS_HULL), 'P', new UnificationEntry(OrePrefix.plate, Materials.Steel), 'G', new ItemStack(Blocks.GLASS, 1)); + ModHandler.addShapedRecipe("steam_boiler_coal_bronze", MetaTileEntities.STEAM_BOILER_COAL_BRONZE.getStackForm(), "PPP", "PwP", "BFB", 'F', OreDictNames.craftingFurnace, 'P', new UnificationEntry(OrePrefix.plate, Materials.Bronze), 'B', new ItemStack(Blocks.BRICK_BLOCK)); + ModHandler.addShapedRecipe("steam_boiler_coal_steel", MetaTileEntities.STEAM_BOILER_COAL_STEEL.getStackForm(), "PPP", "PwP", "BFB", 'F', OreDictNames.craftingFurnace, 'P', new UnificationEntry(OrePrefix.plate, Materials.Steel), 'B', new ItemStack(Blocks.BRICK_BLOCK)); + ModHandler.addShapedRecipe("steam_boiler_lava_bronze", MetaTileEntities.STEAM_BOILER_LAVA_BRONZE.getStackForm(), "PPP", "PGP", "PMP", 'M', MetaBlocks.STEAM_CASING.getItemVariant(BRONZE_BRICKS_HULL), 'P', new UnificationEntry(OrePrefix.plate, Materials.Bronze), 'G', new ItemStack(Blocks.GLASS, 1)); + ModHandler.addShapedRecipe("steam_boiler_lava_steel", MetaTileEntities.STEAM_BOILER_LAVA_STEEL.getStackForm(), "PPP", "PGP", "PMP", 'M', MetaBlocks.STEAM_CASING.getItemVariant(STEEL_BRICKS_HULL), 'P', new UnificationEntry(OrePrefix.plate, Materials.Steel), 'G', new ItemStack(Blocks.GLASS, 1)); ModHandler.addShapedRecipe("steam_boiler_solar_bronze", MetaTileEntities.STEAM_BOILER_SOLAR_BRONZE.getStackForm(), "GGG", "SSS", "PMP", 'M', MetaBlocks.STEAM_CASING.getItemVariant(BRONZE_BRICKS_HULL), 'P', new UnificationEntry(OrePrefix.pipeSmallFluid, Materials.Bronze), 'S', new UnificationEntry(OrePrefix.plate, Materials.Silver), 'G', new ItemStack(Blocks.GLASS)); + ModHandler.addShapedRecipe("steam_boiler_solar_steel", MetaTileEntities.STEAM_BOILER_SOLAR_STEEL.getStackForm(), "GGG", "SSS", "PMP", 'M', MetaBlocks.STEAM_CASING.getItemVariant(STEEL_BRICKS_HULL), 'P', new UnificationEntry(OrePrefix.pipeSmallFluid, Materials.Steel), 'S', new UnificationEntry(OrePrefix.plateDouble, Materials.Silver), 'G', new ItemStack(Blocks.GLASS)); ModHandler.addShapedRecipe("steam_furnace_bronze", MetaTileEntities.STEAM_FURNACE_BRONZE.getStackForm(), "XXX", "XMX", "XFX", 'M', MetaBlocks.STEAM_CASING.getItemVariant(BRONZE_BRICKS_HULL), 'X', new UnificationEntry(OrePrefix.pipeSmallFluid, Materials.Bronze), 'F', OreDictNames.craftingFurnace); - ModHandler.addShapedRecipe("steam_furnace_steel", MetaTileEntities.STEAM_FURNACE_STEEL.getStackForm(), "XXX", "XMX", "XFX", 'M', MetaBlocks.STEAM_CASING.getItemVariant(STEEL_BRICKS_HULL), 'X', new UnificationEntry(OrePrefix.pipeSmallFluid, Materials.Steel), 'F', OreDictNames.craftingFurnace); + ModHandler.addShapedRecipe("steam_furnace_steel", MetaTileEntities.STEAM_FURNACE_STEEL.getStackForm(), "XSX", "PMP", "XXX", 'M', MetaTileEntities.STEAM_FURNACE_BRONZE.getStackForm(), 'X', new UnificationEntry(OrePrefix.pipeSmallFluid, Materials.WroughtIron), 'S', new UnificationEntry(OrePrefix.plate, Materials.Steel), 'P', new UnificationEntry(OrePrefix.plate, Materials.WroughtIron)); ModHandler.addShapedRecipe("steam_macerator_bronze", MetaTileEntities.STEAM_MACERATOR_BRONZE.getStackForm(), "DXD", "XMX", "PXP", 'M', MetaBlocks.STEAM_CASING.getItemVariant(BRONZE_HULL), 'X', new UnificationEntry(OrePrefix.pipeSmallFluid, Materials.Bronze), 'P', OreDictNames.craftingPiston, 'D', new UnificationEntry(OrePrefix.gem, Materials.Diamond)); - ModHandler.addShapedRecipe("steam_macerator_steel", MetaTileEntities.STEAM_MACERATOR_STEEL.getStackForm(), "DXD", "XMX", "PXP", 'M', MetaBlocks.STEAM_CASING.getItemVariant(STEEL_HULL), 'X', new UnificationEntry(OrePrefix.pipeSmallFluid, Materials.Steel), 'P', OreDictNames.craftingPiston, 'D', new UnificationEntry(OrePrefix.gem, Materials.Diamond)); + ModHandler.addShapedRecipe("steam_macerator_steel", MetaTileEntities.STEAM_MACERATOR_STEEL.getStackForm(), "WSW", "PMP", "WWW", 'M', MetaTileEntities.STEAM_MACERATOR_BRONZE.getStackForm(), 'W', new UnificationEntry(OrePrefix.plate, Materials.WroughtIron), 'S', new UnificationEntry(OrePrefix.plate, Materials.Steel), 'P', new UnificationEntry(OrePrefix.pipeSmallFluid, Materials.WroughtIron)); ModHandler.addShapedRecipe("steam_extractor_bronze", MetaTileEntities.STEAM_EXTRACTOR_BRONZE.getStackForm(), "XXX", "PMG", "XXX", 'M', MetaBlocks.STEAM_CASING.getItemVariant(BRONZE_HULL), 'X', new UnificationEntry(OrePrefix.pipeSmallFluid, Materials.Bronze), 'P', OreDictNames.craftingPiston, 'G', new ItemStack(Blocks.GLASS)); - ModHandler.addShapedRecipe("steam_extractor_steel", MetaTileEntities.STEAM_EXTRACTOR_STEEL.getStackForm(), "XXX", "PMG", "XXX", 'M', MetaBlocks.STEAM_CASING.getItemVariant(STEEL_HULL), 'X', new UnificationEntry(OrePrefix.pipeSmallFluid, Materials.Steel), 'P', OreDictNames.craftingPiston, 'G', new ItemStack(Blocks.GLASS)); + ModHandler.addShapedRecipe("steam_extractor_steel", MetaTileEntities.STEAM_EXTRACTOR_STEEL.getStackForm(), "PSP", "WMW", "PPP", 'M', MetaTileEntities.STEAM_EXTRACTOR_BRONZE.getStackForm(), 'P', new UnificationEntry(OrePrefix.pipeSmallFluid, Materials.WroughtIron), 'S', new UnificationEntry(OrePrefix.plate, Materials.Steel), 'W', new UnificationEntry(OrePrefix.plate, Materials.WroughtIron)); ModHandler.addShapedRecipe("steam_hammer_bronze", MetaTileEntities.STEAM_HAMMER_BRONZE.getStackForm(), "XPX", "XMX", "XAX", 'M', MetaBlocks.STEAM_CASING.getItemVariant(BRONZE_HULL), 'X', new UnificationEntry(OrePrefix.pipeSmallFluid, Materials.Bronze), 'P', OreDictNames.craftingPiston, 'A', OreDictNames.craftingAnvil); - ModHandler.addShapedRecipe("steam_hammer_steel", MetaTileEntities.STEAM_HAMMER_STEEL.getStackForm(), "XPX", "XMX", "XAX", 'M', MetaBlocks.STEAM_CASING.getItemVariant(STEEL_HULL), 'X', new UnificationEntry(OrePrefix.pipeSmallFluid, Materials.Steel), 'P', OreDictNames.craftingPiston, 'A', OreDictNames.craftingAnvil); + ModHandler.addShapedRecipe("steam_hammer_steel", MetaTileEntities.STEAM_HAMMER_STEEL.getStackForm(), "WSW", "PMP", "WWW", 'M', MetaTileEntities.STEAM_HAMMER_BRONZE.getStackForm(), 'S', new UnificationEntry(OrePrefix.plate, Materials.Steel), 'W', new UnificationEntry(OrePrefix.plate, Materials.WroughtIron), 'P', new UnificationEntry(OrePrefix.pipeSmallFluid, Materials.WroughtIron)); ModHandler.addShapedRecipe("steam_compressor_bronze", MetaTileEntities.STEAM_COMPRESSOR_BRONZE.getStackForm(), "XXX", "PMP", "XXX", 'M', MetaBlocks.STEAM_CASING.getItemVariant(BRONZE_HULL), 'X', new UnificationEntry(OrePrefix.pipeSmallFluid, Materials.Bronze), 'P', OreDictNames.craftingPiston); - ModHandler.addShapedRecipe("steam_compressor_steel", MetaTileEntities.STEAM_COMPRESSOR_STEEL.getStackForm(), "XXX", "PMP", "XXX", 'M', MetaBlocks.STEAM_CASING.getItemVariant(STEEL_HULL), 'X', new UnificationEntry(OrePrefix.pipeSmallFluid, Materials.Steel), 'P', OreDictNames.craftingPiston); + ModHandler.addShapedRecipe("steam_compressor_steel", MetaTileEntities.STEAM_COMPRESSOR_STEEL.getStackForm(), "PSP", "WMW", "PPP", 'M', MetaTileEntities.STEAM_COMPRESSOR_BRONZE.getStackForm(), 'S', new UnificationEntry(OrePrefix.plate, Materials.Steel), 'W', new UnificationEntry(OrePrefix.plate, Materials.WroughtIron), 'P', new UnificationEntry(OrePrefix.pipeSmallFluid, Materials.WroughtIron)); ModHandler.addShapedRecipe("steam_alloy_smelter_bronze", MetaTileEntities.STEAM_ALLOY_SMELTER_BRONZE.getStackForm(), "XXX", "FMF", "XXX", 'M', MetaBlocks.STEAM_CASING.getItemVariant(BRONZE_BRICKS_HULL), 'X', new UnificationEntry(OrePrefix.pipeSmallFluid, Materials.Bronze), 'F', OreDictNames.craftingFurnace); - ModHandler.addShapedRecipe("steam_alloy_smelter_steel", MetaTileEntities.STEAM_ALLOY_SMELTER_STEEL.getStackForm(), "XXX", "FMF", "XXX", 'M', MetaBlocks.STEAM_CASING.getItemVariant(STEEL_BRICKS_HULL), 'X', new UnificationEntry(OrePrefix.pipeSmallFluid, Materials.Steel), 'F', OreDictNames.craftingFurnace); + ModHandler.addShapedRecipe("steam_alloy_smelter_steel", MetaTileEntities.STEAM_ALLOY_SMELTER_STEEL.getStackForm(), "WSW", "WMW", "WPW", 'M', MetaTileEntities.STEAM_ALLOY_SMELTER_BRONZE.getStackForm(), 'S', new UnificationEntry(OrePrefix.plate, Materials.Steel), 'W', new UnificationEntry(OrePrefix.plate, Materials.WroughtIron), 'P', new UnificationEntry(OrePrefix.pipeSmallFluid, Materials.WroughtIron)); // MULTI BLOCK CONTROLLERS ModHandler.addShapedRecipe("bronze_primitive_blast_furnace", MetaTileEntities.PRIMITIVE_BLAST_FURNACE.getStackForm(), "hRS", "PBR", "dRS", 'R', new UnificationEntry(OrePrefix.stick, Materials.Iron), 'S', new UnificationEntry(OrePrefix.screw, Materials.Iron), 'P', new UnificationEntry(OrePrefix.plate, Materials.Iron), 'B', MetaBlocks.METAL_CASING.getItemVariant(PRIMITIVE_BRICKS)); @@ -425,21 +419,22 @@ public static void init() { registerMachineRecipe(MetaTileEntities.MASS_FABRICATOR, "CFC", "QMQ", "CFC", 'M', HULL, 'Q', CABLE_QUAD, 'C', BETTER_CIRCUIT, 'F', FIELD_GENERATOR); registerMachineRecipe(MetaTileEntities.REPLICATOR, "EFE", "CMC", "EQE", 'M', HULL, 'Q', CABLE_QUAD, 'C', BETTER_CIRCUIT, 'F', FIELD_GENERATOR, 'E', EMITTER); registerMachineRecipe(MetaTileEntities.SCANNER, "CEC", "WHW", "CSC", 'C', BETTER_CIRCUIT, 'E', EMITTER, 'W', CABLE, 'H', HULL, 'S', SENSOR); + registerMachineRecipe(MetaTileEntities.GAS_COLLECTOR, "WFW", "PHP", "WCW", 'W', Blocks.IRON_BARS, 'F', MetaItems.FLUID_FILTER, 'P', PUMP, 'H', HULL, 'C', CIRCUIT); registerMachineRecipe(MetaTileEntities.PUMP, "WGW", "GMG", "TGT", 'M', HULL, 'W', CIRCUIT, 'G', PUMP, 'T', PIPE_LARGE); registerMachineRecipe(MetaTileEntities.FISHER, "WTW", "PMP", "TGT", 'M', HULL, 'W', CIRCUIT, 'G', PUMP, 'T', MOTOR, 'P', PISTON); - registerMachineRecipe(MetaTileEntities.AIR_COLLECTOR, "WFW", "PHP", "WCW", 'W', Blocks.IRON_BARS, 'F', MetaItems.ITEM_FILTER, 'P', PUMP, 'H', HULL, 'C', CIRCUIT); registerMachineRecipe(MetaTileEntities.ITEM_COLLECTOR, "MRM", "RHR", "CWC", 'M', MOTOR, 'R', ROTOR, 'H', HULL, 'C', CIRCUIT, 'W', CABLE); registerMachineRecipe(MetaTileEntities.BLOCK_BREAKER, "MGM", "CHC", "WSW", 'M', MOTOR, 'H', HULL, 'C', CIRCUIT, 'W', CABLE, 'S', Blocks.CHEST, 'G', GRINDER); - if (ConfigHolder.U.registerCrates) { - ModHandler.addShapedRecipe("wooden_crate", MetaTileEntities.WOODEN_CRATE.getStackForm(), "RPR", "PsP", "RPR", 'P', "plankWood", 'R', new UnificationEntry(OrePrefix.screw, Materials.Iron)); - ModHandler.addShapedRecipe("bronze_crate", MetaTileEntities.BRONZE_CRATE.getStackForm(), "RPR", "PhP", "RPR", 'P', new UnificationEntry(OrePrefix.plate, Materials.Bronze), 'R', new UnificationEntry(OrePrefix.stickLong, Materials.Bronze)); - ModHandler.addShapedRecipe("steel_crate", MetaTileEntities.STEEL_CRATE.getStackForm(), "RPR", "PhP", "RPR", 'P', new UnificationEntry(OrePrefix.plate, Materials.Steel), 'R', new UnificationEntry(OrePrefix.stickLong, Materials.Steel)); - ModHandler.addShapedRecipe("stainless_steel_crate", MetaTileEntities.STAINLESS_STEEL_CRATE.getStackForm(), "RPR", "PhP", "RPR", 'P', new UnificationEntry(OrePrefix.plate, Materials.StainlessSteel), 'R', new UnificationEntry(OrePrefix.stickLong, Materials.StainlessSteel)); - ModHandler.addShapedRecipe("titanium_crate", MetaTileEntities.TITANIUM_CRATE.getStackForm(), "RPR", "PhP", "RPR", 'P', new UnificationEntry(OrePrefix.plate, Materials.Titanium), 'R', new UnificationEntry(OrePrefix.stickLong, Materials.Titanium)); - ModHandler.addShapedRecipe("tungstensteel_crate", MetaTileEntities.TUNGSTENSTEEL_CRATE.getStackForm(), "RPR", "PhP", "RPR", 'P', new UnificationEntry(OrePrefix.plate, Materials.TungstenSteel), 'R', new UnificationEntry(OrePrefix.stickLong, Materials.TungstenSteel)); - } + ModHandler.addShapedRecipe("gregtech.machine.simple_washer.lv", MetaTileEntities.SIMPLE_ORE_WASHER.getStackForm(), "WPW", "WBW", "WHW", 'W', new UnificationEntry(OrePrefix.plate, Materials.WroughtIron), 'P', MetaItems.ELECTRIC_PUMP_LV.getStackForm(), 'B', new UnificationEntry(OrePrefix.pipeNormalFluid, Materials. Bronze), 'H', MetaTileEntities.HULL[GTValues.ULV].getStackForm()); + + ModHandler.addShapedRecipe("wooden_crate", MetaTileEntities.WOODEN_CRATE.getStackForm(), "RPR", "PsP", "RPR", 'P', "plankWood", 'R', new UnificationEntry(OrePrefix.screw, Materials.Iron)); + ModHandler.addShapedRecipe("bronze_crate", MetaTileEntities.BRONZE_CRATE.getStackForm(), "RPR", "PhP", "RPR", 'P', new UnificationEntry(OrePrefix.plate, Materials.Bronze), 'R', new UnificationEntry(OrePrefix.stickLong, Materials.Bronze)); + ModHandler.addShapedRecipe("steel_crate", MetaTileEntities.STEEL_CRATE.getStackForm(), "RPR", "PhP", "RPR", 'P', new UnificationEntry(OrePrefix.plate, Materials.Steel), 'R', new UnificationEntry(OrePrefix.stickLong, Materials.Steel)); + ModHandler.addShapedRecipe("aluminium_crate", MetaTileEntities.ALUMINIUM_CRATE.getStackForm(), "RPR", "PhP", "RPR", 'P', new UnificationEntry(OrePrefix.plate, Materials.Aluminium), 'R', new UnificationEntry(OrePrefix.stickLong, Materials.Aluminium)); + ModHandler.addShapedRecipe("stainless_steel_crate", MetaTileEntities.STAINLESS_STEEL_CRATE.getStackForm(), "RPR", "PhP", "RPR", 'P', new UnificationEntry(OrePrefix.plate, Materials.StainlessSteel), 'R', new UnificationEntry(OrePrefix.stickLong, Materials.StainlessSteel)); + ModHandler.addShapedRecipe("titanium_crate", MetaTileEntities.TITANIUM_CRATE.getStackForm(), "RPR", "PhP", "RPR", 'P', new UnificationEntry(OrePrefix.plate, Materials.Titanium), 'R', new UnificationEntry(OrePrefix.stickLong, Materials.Titanium)); + ModHandler.addShapedRecipe("tungstensteel_crate", MetaTileEntities.TUNGSTENSTEEL_CRATE.getStackForm(), "RPR", "PhP", "RPR", 'P', new UnificationEntry(OrePrefix.plate, Materials.TungstenSteel), 'R', new UnificationEntry(OrePrefix.stickLong, Materials.TungstenSteel)); ModHandler.addShapedRecipe("wooden_tank", MetaTileEntities.WOODEN_TANK.getStackForm(), "XYX", "Y Y", "XYX", 'X', new UnificationEntry(OrePrefix.plank, Materials.Wood), 'Y', new UnificationEntry(OrePrefix.blockGlass)); ModHandler.addShapedRecipe("bronze_tank", MetaTileEntities.BRONZE_TANK.getStackForm(), "XYX", "Y Y", "XYX", 'X', new UnificationEntry(OrePrefix.plate, Materials.Bronze), 'Y', new UnificationEntry(OrePrefix.blockGlass)); @@ -448,14 +443,12 @@ public static void init() { ModHandler.addShapedRecipe("titanium_tank", MetaTileEntities.TITANIUM_TANK.getStackForm(), "XYX", "Y Y", "XYX", 'X', new UnificationEntry(OrePrefix.plate, Materials.Titanium), 'Y', new UnificationEntry(OrePrefix.blockGlass)); ModHandler.addShapedRecipe("tungsten_steel_tank", MetaTileEntities.TUNGSTENSTEEL_TANK.getStackForm(), "XYX", "Y Y", "XYX", 'X', new UnificationEntry(OrePrefix.plate, Materials.TungstenSteel), 'Y', new UnificationEntry(OrePrefix.blockGlass)); - if (ConfigHolder.U.registerDrums) { - ModHandler.addShapedRecipe("wooden_barrel", MetaTileEntities.WOODEN_DRUM.getStackForm(), "rSs", "PRP", "PRP", 'S', "slimeball", 'P', "plankWood", 'R', new UnificationEntry(OrePrefix.stickLong, Materials.Iron)); - ModHandler.addShapedRecipe("bronze_drum", MetaTileEntities.BRONZE_DRUM.getStackForm(), " h ", "PRP", "PRP", 'P', new UnificationEntry(OrePrefix.plate, Materials.Bronze), 'R', new UnificationEntry(OrePrefix.stickLong, Materials.Bronze)); - ModHandler.addShapedRecipe("steel_drum", MetaTileEntities.STEEL_DRUM.getStackForm(), " h ", "PRP", "PRP", 'P', new UnificationEntry(OrePrefix.plate, Materials.Steel), 'R', new UnificationEntry(OrePrefix.stickLong, Materials.Steel)); - ModHandler.addShapedRecipe("stainless_steel_drum", MetaTileEntities.STAINLESS_STEEL_DRUM.getStackForm(), " h ", "PRP", "PRP", 'P', new UnificationEntry(OrePrefix.plate, Materials.StainlessSteel), 'R', new UnificationEntry(OrePrefix.stickLong, Materials.StainlessSteel)); - ModHandler.addShapedRecipe("titanium_drum", MetaTileEntities.TITANIUM_DRUM.getStackForm(), " h ", "PRP", "PRP", 'P', new UnificationEntry(OrePrefix.plate, Materials.Titanium), 'R', new UnificationEntry(OrePrefix.stickLong, Materials.Titanium)); - ModHandler.addShapedRecipe("tungstensteel_drum", MetaTileEntities.TUNGSTENSTEEL_DRUM.getStackForm(), " h ", "PRP", "PRP", 'P', new UnificationEntry(OrePrefix.plate, Materials.TungstenSteel), 'R', new UnificationEntry(OrePrefix.stickLong, Materials.TungstenSteel)); - } + ModHandler.addShapedRecipe("wooden_barrel", MetaTileEntities.WOODEN_DRUM.getStackForm(), "rSs", "PRP", "PRP", 'S', "slimeball", 'P', "plankWood", 'R', new UnificationEntry(OrePrefix.stickLong, Materials.Iron)); + ModHandler.addShapedRecipe("bronze_drum", MetaTileEntities.BRONZE_DRUM.getStackForm(), " h ", "PRP", "PRP", 'P', new UnificationEntry(OrePrefix.plate, Materials.Bronze), 'R', new UnificationEntry(OrePrefix.stickLong, Materials.Bronze)); + ModHandler.addShapedRecipe("steel_drum", MetaTileEntities.STEEL_DRUM.getStackForm(), " h ", "PRP", "PRP", 'P', new UnificationEntry(OrePrefix.plate, Materials.Steel), 'R', new UnificationEntry(OrePrefix.stickLong, Materials.Steel)); + ModHandler.addShapedRecipe("stainless_steel_drum", MetaTileEntities.STAINLESS_STEEL_DRUM.getStackForm(), " h ", "PRP", "PRP", 'P', new UnificationEntry(OrePrefix.plate, Materials.StainlessSteel), 'R', new UnificationEntry(OrePrefix.stickLong, Materials.StainlessSteel)); + ModHandler.addShapedRecipe("titanium_drum", MetaTileEntities.TITANIUM_DRUM.getStackForm(), " h ", "PRP", "PRP", 'P', new UnificationEntry(OrePrefix.plate, Materials.Titanium), 'R', new UnificationEntry(OrePrefix.stickLong, Materials.Titanium)); + ModHandler.addShapedRecipe("tungstensteel_drum", MetaTileEntities.TUNGSTENSTEEL_DRUM.getStackForm(), " h ", "PRP", "PRP", 'P', new UnificationEntry(OrePrefix.plate, Materials.TungstenSteel), 'R', new UnificationEntry(OrePrefix.stickLong, Materials.TungstenSteel)); // Super / Quantum Chests ModHandler.addShapedRecipe("super_chest_lv", MetaTileEntities.QUANTUM_CHEST[0].getStackForm(), "CPC", "PFP", "CPC", 'C', new UnificationEntry(OrePrefix.circuit, Tier.Basic), 'P', new UnificationEntry(OrePrefix.plate, Materials.Steel), 'F', MetaTileEntities.STEEL_CRATE.getStackForm()); @@ -493,6 +486,10 @@ public static void init() { ModHandler.addShapedRecipe("hermetic_casing_zpm", MetaBlocks.HERMETIC_CASING.getItemVariant(HERMETIC_ZPM), "PPP", "PFP", "PPP", 'P', new UnificationEntry(OrePrefix.plate, Materials.Iridium), 'F', new UnificationEntry(OrePrefix.pipeLargeFluid, Materials.NiobiumTitanium)); ModHandler.addShapedRecipe("hermetic_casing_uv", MetaBlocks.HERMETIC_CASING.getItemVariant(HERMETIC_UV), "PPP", "PFP", "PPP", 'P', new UnificationEntry(OrePrefix.plate, Materials.Osmium), 'F', new UnificationEntry(OrePrefix.pipeLargeFluid, Materials.Naquadah)); ModHandler.addShapedRecipe("hermetic_casing_max", MetaBlocks.HERMETIC_CASING.getItemVariant(HERMETIC_MAX), "PPP", "PFP", "PPP", 'P', new UnificationEntry(OrePrefix.plate, Materials.Neutronium), 'F', new UnificationEntry(OrePrefix.pipeLargeFluid, Materials.Ultimet)); + + ModHandler.addShapedRecipe("buffer_lv", MetaTileEntities.BUFFER[0].getStackForm(), "HP", "CV", 'H', MetaTileEntities.HULL[GTValues.LV].getStackForm(), 'P', MetaItems.ELECTRIC_PUMP_LV.getStackForm(), 'V', MetaItems.CONVEYOR_MODULE_LV.getStackForm(), 'C', new UnificationEntry(OrePrefix.circuit, MarkerMaterials.Tier.Basic)); + ModHandler.addShapedRecipe("buffer_mv", MetaTileEntities.BUFFER[1].getStackForm(), "HP", "CV", 'H', MetaTileEntities.HULL[GTValues.MV].getStackForm(), 'P', MetaItems.ELECTRIC_PUMP_MV.getStackForm(), 'V', MetaItems.CONVEYOR_MODULE_MV.getStackForm(), 'C', new UnificationEntry(OrePrefix.circuit, MarkerMaterials.Tier.Basic)); + ModHandler.addShapedRecipe("buffer_hv", MetaTileEntities.BUFFER[2].getStackForm(), "HP", "CV", 'H', MetaTileEntities.HULL[GTValues.HV].getStackForm(), 'P', MetaItems.ELECTRIC_PUMP_HV.getStackForm(), 'V', MetaItems.CONVEYOR_MODULE_HV.getStackForm(), 'C', new UnificationEntry(OrePrefix.circuit, MarkerMaterials.Tier.Basic)); } public static void registerMachineRecipe(T[] metaTileEntities, Object... recipe) { diff --git a/src/main/java/gregtech/loaders/recipe/MetaTileEntityMachineRecipeLoader.java b/src/main/java/gregtech/loaders/recipe/MetaTileEntityMachineRecipeLoader.java index 5ec9aea1801..ffa0b3dbbbf 100644 --- a/src/main/java/gregtech/loaders/recipe/MetaTileEntityMachineRecipeLoader.java +++ b/src/main/java/gregtech/loaders/recipe/MetaTileEntityMachineRecipeLoader.java @@ -9,7 +9,7 @@ import gregtech.common.items.MetaItems; import gregtech.common.metatileentities.MetaTileEntities; -import static gregtech.common.metatileentities.MetaTileEntities.HULL; +import static gregtech.common.metatileentities.MetaTileEntities.*; public class MetaTileEntityMachineRecipeLoader { @@ -343,6 +343,293 @@ public static void init() { .fluidInputs(Materials.SolderingAlloy.getFluid(2880)) .outputs(MetaTileEntities.ENERGY_INPUT_HATCH[GTValues.UV].getStackForm()) .duration(800).EUt(491520).buildAndRegister(); + } + + // Adjustable Transformers + + RecipeMaps.ASSEMBLER_RECIPES.recipeBuilder() + .inputs(TRANSFORMER[GTValues.ULV].getStackForm()) + .inputs(MetaItems.ELECTRIC_PUMP_LV.getStackForm()) + .input(OrePrefix.wireGtQuadruple, Materials.Tin) + .input(OrePrefix.wireGtOctal, Materials.Lead) + .input(OrePrefix.springSmall, Materials.Lead) + .input(OrePrefix.spring, Materials.Tin) + .fluidInputs(Materials.Lubricant.getFluid(2000)) + .outputs(ADJUSTABLE_TRANSFORMER[GTValues.ULV].getStackForm()) + .duration(200).EUt(7).buildAndRegister(); + + RecipeMaps.ASSEMBLER_RECIPES.recipeBuilder() + .inputs(TRANSFORMER[GTValues.LV].getStackForm()) + .inputs(MetaItems.ELECTRIC_PUMP_LV.getStackForm()) + .input(OrePrefix.wireGtQuadruple, Materials.Copper) + .input(OrePrefix.wireGtOctal, Materials.Tin) + .input(OrePrefix.springSmall, Materials.Tin) + .input(OrePrefix.spring, Materials.Copper) + .fluidInputs(Materials.Lubricant.getFluid(2000)) + .outputs(ADJUSTABLE_TRANSFORMER[GTValues.LV].getStackForm()) + .duration(200).EUt(30).buildAndRegister(); + + RecipeMaps.ASSEMBLER_RECIPES.recipeBuilder() + .inputs(TRANSFORMER[GTValues.MV].getStackForm()) + .inputs(MetaItems.ELECTRIC_PUMP_MV.getStackForm()) + .input(OrePrefix.wireGtQuadruple, Materials.Gold) + .input(OrePrefix.wireGtOctal, Materials.Copper) + .input(OrePrefix.springSmall, Materials.Copper) + .input(OrePrefix.spring, Materials.Gold) + .fluidInputs(Materials.Lubricant.getFluid(2000)) + .outputs(ADJUSTABLE_TRANSFORMER[GTValues.MV].getStackForm()) + .duration(200).EUt(120).buildAndRegister(); + + RecipeMaps.ASSEMBLER_RECIPES.recipeBuilder() + .inputs(TRANSFORMER[GTValues.HV].getStackForm()) + .inputs(MetaItems.ELECTRIC_PUMP_MV.getStackForm()) + .input(OrePrefix.wireGtQuadruple, Materials.Aluminium) + .input(OrePrefix.wireGtOctal, Materials.Gold) + .input(OrePrefix.springSmall, Materials.Gold) + .input(OrePrefix.spring, Materials.Aluminium) + .fluidInputs(Materials.Lubricant.getFluid(2000)) + .outputs(ADJUSTABLE_TRANSFORMER[GTValues.HV].getStackForm()) + .duration(200).EUt(480).buildAndRegister(); + + RecipeMaps.ASSEMBLER_RECIPES.recipeBuilder() + .inputs(TRANSFORMER[GTValues.EV].getStackForm()) + .inputs(MetaItems.ELECTRIC_PUMP_HV.getStackForm()) + .input(OrePrefix.wireGtQuadruple, Materials.Tungsten) + .input(OrePrefix.wireGtOctal, Materials.Aluminium) + .input(OrePrefix.springSmall, Materials.Aluminium) + .input(OrePrefix.spring, Materials.Tungsten) + .fluidInputs(Materials.Lubricant.getFluid(2000)) + .outputs(ADJUSTABLE_TRANSFORMER[GTValues.EV].getStackForm()) + .duration(200).EUt(1920).buildAndRegister(); + + RecipeMaps.ASSEMBLER_RECIPES.recipeBuilder() + .inputs(TRANSFORMER[GTValues.IV].getStackForm()) + .inputs(MetaItems.ELECTRIC_PUMP_HV.getStackForm()) + .input(OrePrefix.wireGtQuadruple, Materials.YttriumBariumCuprate) + .input(OrePrefix.wireGtOctal, Materials.Tungsten) + .input(OrePrefix.springSmall, Materials.Tungsten) + .input(OrePrefix.spring, Materials.YttriumBariumCuprate) + .fluidInputs(Materials.Lubricant.getFluid(2000)) + .outputs(ADJUSTABLE_TRANSFORMER[GTValues.IV].getStackForm()) + .duration(200).EUt(7680).buildAndRegister(); + + RecipeMaps.ASSEMBLER_RECIPES.recipeBuilder() + .inputs(TRANSFORMER[GTValues.LuV].getStackForm()) + .inputs(MetaItems.ELECTRIC_PUMP_EV.getStackForm()) + .input(OrePrefix.wireGtQuadruple, Materials.VanadiumGallium) + .input(OrePrefix.wireGtOctal, Materials.YttriumBariumCuprate) + .input(OrePrefix.springSmall, Materials.YttriumBariumCuprate) + .input(OrePrefix.spring, Materials.VanadiumGallium) + .fluidInputs(Materials.Lubricant.getFluid(2000)) + .outputs(ADJUSTABLE_TRANSFORMER[GTValues.LuV].getStackForm()) + .duration(200).EUt(32768).buildAndRegister(); + + RecipeMaps.ASSEMBLER_RECIPES.recipeBuilder() + .inputs(TRANSFORMER[GTValues.ZPM].getStackForm()) + .inputs(MetaItems.ELECTRIC_PUMP_EV.getStackForm()) + .input(OrePrefix.wireGtQuadruple, Materials.NiobiumTitanium) + .input(OrePrefix.wireGtOctal, Materials.VanadiumGallium) + .input(OrePrefix.springSmall, Materials.VanadiumGallium) + .input(OrePrefix.spring, Materials.NiobiumTitanium) + .fluidInputs(Materials.Lubricant.getFluid(2000)) + .outputs(ADJUSTABLE_TRANSFORMER[GTValues.ZPM].getStackForm()) + .duration(200).EUt(131072).buildAndRegister(); + + RecipeMaps.ASSEMBLER_RECIPES.recipeBuilder() + .inputs(TRANSFORMER[GTValues.UV].getStackForm()) + .inputs(MetaItems.ELECTRIC_PUMP_IV.getStackForm()) + .input(OrePrefix.wireGtQuadruple, Materials.Europium) + .input(OrePrefix.wireGtOctal, Materials.NiobiumTitanium) + .input(OrePrefix.springSmall, Materials.NiobiumTitanium) + .input(OrePrefix.spring, Materials.Europium) + .fluidInputs(Materials.Lubricant.getFluid(2000)) + .outputs(ADJUSTABLE_TRANSFORMER[GTValues.UV].getStackForm()) + .duration(200).EUt(524288).buildAndRegister(); + + // Adjustable Input Hatches + + RecipeMaps.ASSEMBLER_RECIPES.recipeBuilder() + .inputs(ADJUSTABLE_TRANSFORMER[GTValues.ULV].getStackForm()) + .inputs(ENERGY_INPUT_HATCH[GTValues.ULV].getStackForm()) + .inputs(MetaItems.VOLTAGE_COIL_ULV.getStackForm(2)) + .input(OrePrefix.cableGtSingle, Materials.Lead, 2) + .input(OrePrefix.wireGtQuadruple, Materials.RedAlloy, 4) + .input(OrePrefix.plateDouble, Materials.WroughtIron) + .outputs(ENERGY_INPUT_HATCH_ADJUSTABLE[GTValues.ULV].getStackForm()) + .duration(100).EUt(7).buildAndRegister(); + + RecipeMaps.ASSEMBLER_RECIPES.recipeBuilder() + .inputs(ADJUSTABLE_TRANSFORMER[GTValues.LV].getStackForm()) + .inputs(ENERGY_INPUT_HATCH[GTValues.LV].getStackForm()) + .inputs(MetaItems.VOLTAGE_COIL_LV.getStackForm(2)) + .input(OrePrefix.cableGtSingle, Materials.Tin, 2) + .input(OrePrefix.wireGtQuadruple, Materials.Copper, 4) + .input(OrePrefix.plateDouble, Materials.Steel) + .outputs(ENERGY_INPUT_HATCH_ADJUSTABLE[GTValues.LV].getStackForm()) + .duration(100).EUt(30).buildAndRegister(); + + RecipeMaps.ASSEMBLER_RECIPES.recipeBuilder() + .inputs(ADJUSTABLE_TRANSFORMER[GTValues.MV].getStackForm()) + .inputs(ENERGY_INPUT_HATCH[GTValues.MV].getStackForm()) + .inputs(MetaItems.VOLTAGE_COIL_MV.getStackForm(2)) + .inputs(MetaItems.SMALL_COIL.getStackForm(2)) + .input(OrePrefix.wireGtQuadruple, Materials.Cupronickel, 4) + .input(OrePrefix.plateDouble, Materials.Aluminium) + .outputs(ENERGY_INPUT_HATCH_ADJUSTABLE[GTValues.MV].getStackForm()) + .duration(100).EUt(120).buildAndRegister(); + + RecipeMaps.ASSEMBLER_RECIPES.recipeBuilder() + .inputs(ADJUSTABLE_TRANSFORMER[GTValues.HV].getStackForm()) + .inputs(ENERGY_INPUT_HATCH[GTValues.HV].getStackForm()) + .inputs(MetaItems.VOLTAGE_COIL_HV.getStackForm(2)) + .inputs(MetaItems.ULTRA_LOW_POWER_INTEGRATED_CIRCUIT.getStackForm(2)) + .input(OrePrefix.wireGtQuadruple, Materials.Kanthal, 4) + .input(OrePrefix.plateDouble, Materials.StainlessSteel) + .outputs(ENERGY_INPUT_HATCH_ADJUSTABLE[GTValues.HV].getStackForm()) + .duration(100).EUt(480).buildAndRegister(); + + RecipeMaps.ASSEMBLER_RECIPES.recipeBuilder() + .inputs(ADJUSTABLE_TRANSFORMER[GTValues.EV].getStackForm()) + .inputs(ENERGY_INPUT_HATCH[GTValues.EV].getStackForm()) + .inputs(MetaItems.VOLTAGE_COIL_EV.getStackForm(2)) + .inputs(MetaItems.LOW_POWER_INTEGRATED_CIRCUIT.getStackForm(2)) + .input(OrePrefix.wireGtQuadruple, Materials.Nichrome, 4) + .input(OrePrefix.plateDouble, Materials.Titanium) + .outputs(ENERGY_INPUT_HATCH_ADJUSTABLE[GTValues.EV].getStackForm()) + .duration(100).EUt(1920).buildAndRegister(); + + RecipeMaps.ASSEMBLER_RECIPES.recipeBuilder() + .inputs(ADJUSTABLE_TRANSFORMER[GTValues.IV].getStackForm()) + .inputs(ENERGY_INPUT_HATCH[GTValues.IV].getStackForm()) + .inputs(MetaItems.VOLTAGE_COIL_IV.getStackForm(2)) + .inputs(MetaItems.POWER_INTEGRATED_CIRCUIT.getStackForm(2)) + .input(OrePrefix.wireGtQuadruple, Materials.TungstenSteel, 4) + .input(OrePrefix.plateDouble, Materials.TungstenSteel) + .outputs(ENERGY_INPUT_HATCH_ADJUSTABLE[GTValues.IV].getStackForm()) + .duration(100).EUt(7680).buildAndRegister(); + + RecipeMaps.ASSEMBLER_RECIPES.recipeBuilder() + .inputs(ADJUSTABLE_TRANSFORMER[GTValues.LuV].getStackForm()) + .inputs(ENERGY_INPUT_HATCH[GTValues.LuV].getStackForm()) + .inputs(MetaItems.VOLTAGE_COIL_LUV.getStackForm(2)) + .inputs(MetaItems.HIGH_POWER_INTEGRATED_CIRCUIT.getStackForm(2)) + .input(OrePrefix.wireGtQuadruple, Materials.HSSG, 4) + .input(OrePrefix.plateDouble, Materials.Chrome) + .outputs(ENERGY_INPUT_HATCH_ADJUSTABLE[GTValues.LuV].getStackForm()) + .duration(100).EUt(32768).buildAndRegister(); + + RecipeMaps.ASSEMBLER_RECIPES.recipeBuilder() + .inputs(ADJUSTABLE_TRANSFORMER[GTValues.ZPM].getStackForm()) + .inputs(ENERGY_INPUT_HATCH[GTValues.ZPM].getStackForm()) + .inputs(MetaItems.VOLTAGE_COIL_ZPM.getStackForm(2)) + .inputs(MetaItems.HIGH_POWER_INTEGRATED_CIRCUIT.getStackForm(2)) + .input(OrePrefix.wireGtQuadruple, Materials.Naquadah, 4) + .input(OrePrefix.plateDouble, Materials.Iridium) + .outputs(ENERGY_INPUT_HATCH_ADJUSTABLE[GTValues.ZPM].getStackForm()) + .duration(100).EUt(131072).buildAndRegister(); + + RecipeMaps.ASSEMBLER_RECIPES.recipeBuilder() + .inputs(ADJUSTABLE_TRANSFORMER[GTValues.UV].getStackForm()) + .inputs(ENERGY_INPUT_HATCH[GTValues.UV].getStackForm()) + .inputs(MetaItems.VOLTAGE_COIL_UV.getStackForm(2)) + .inputs(MetaItems.HIGH_POWER_INTEGRATED_CIRCUIT.getStackForm(2)) + .input(OrePrefix.wireGtQuadruple, Materials.NaquadahAlloy, 4) + .input(OrePrefix.plateDouble, Materials.Osmium) + .outputs(ENERGY_INPUT_HATCH_ADJUSTABLE[GTValues.UV].getStackForm()) + .duration(100).EUt(524288).buildAndRegister(); + + // Adjustable Output Hatches + + RecipeMaps.ASSEMBLER_RECIPES.recipeBuilder() + .inputs(ADJUSTABLE_TRANSFORMER[GTValues.ULV].getStackForm()) + .inputs(ENERGY_OUTPUT_HATCH[GTValues.ULV].getStackForm()) + .inputs(MetaItems.VOLTAGE_COIL_ULV.getStackForm(2)) + .input(OrePrefix.cableGtSingle, Materials.Lead, 2) + .input(OrePrefix.wireGtQuadruple, Materials.RedAlloy, 4) + .input(OrePrefix.plateDouble, Materials.WroughtIron) + .outputs(ENERGY_OUTPUT_HATCH_ADJUSTABLE[GTValues.ULV].getStackForm()) + .duration(100).EUt(7).buildAndRegister(); + + RecipeMaps.ASSEMBLER_RECIPES.recipeBuilder() + .inputs(ADJUSTABLE_TRANSFORMER[GTValues.LV].getStackForm()) + .inputs(ENERGY_OUTPUT_HATCH[GTValues.LV].getStackForm()) + .inputs(MetaItems.VOLTAGE_COIL_LV.getStackForm(2)) + .input(OrePrefix.cableGtSingle, Materials.Tin, 2) + .input(OrePrefix.wireGtQuadruple, Materials.Copper, 4) + .input(OrePrefix.plateDouble, Materials.Steel) + .outputs(ENERGY_OUTPUT_HATCH_ADJUSTABLE[GTValues.LV].getStackForm()) + .duration(100).EUt(30).buildAndRegister(); + + RecipeMaps.ASSEMBLER_RECIPES.recipeBuilder() + .inputs(ADJUSTABLE_TRANSFORMER[GTValues.MV].getStackForm()) + .inputs(ENERGY_OUTPUT_HATCH[GTValues.MV].getStackForm()) + .inputs(MetaItems.VOLTAGE_COIL_MV.getStackForm(2)) + .inputs(MetaItems.SMALL_COIL.getStackForm(2)) + .input(OrePrefix.wireGtQuadruple, Materials.Cupronickel, 4) + .input(OrePrefix.plateDouble, Materials.Aluminium) + .outputs(ENERGY_OUTPUT_HATCH_ADJUSTABLE[GTValues.MV].getStackForm()) + .duration(100).EUt(120).buildAndRegister(); + + RecipeMaps.ASSEMBLER_RECIPES.recipeBuilder() + .inputs(ADJUSTABLE_TRANSFORMER[GTValues.HV].getStackForm()) + .inputs(ENERGY_OUTPUT_HATCH[GTValues.HV].getStackForm()) + .inputs(MetaItems.VOLTAGE_COIL_HV.getStackForm(2)) + .inputs(MetaItems.ULTRA_LOW_POWER_INTEGRATED_CIRCUIT.getStackForm(2)) + .input(OrePrefix.wireGtQuadruple, Materials.Kanthal, 4) + .input(OrePrefix.plateDouble, Materials.StainlessSteel) + .outputs(ENERGY_OUTPUT_HATCH_ADJUSTABLE[GTValues.HV].getStackForm()) + .duration(100).EUt(480).buildAndRegister(); + + RecipeMaps.ASSEMBLER_RECIPES.recipeBuilder() + .inputs(ADJUSTABLE_TRANSFORMER[GTValues.EV].getStackForm()) + .inputs(ENERGY_OUTPUT_HATCH[GTValues.EV].getStackForm()) + .inputs(MetaItems.VOLTAGE_COIL_EV.getStackForm(2)) + .inputs(MetaItems.LOW_POWER_INTEGRATED_CIRCUIT.getStackForm(2)) + .input(OrePrefix.wireGtQuadruple, Materials.Nichrome, 4) + .input(OrePrefix.plateDouble, Materials.Titanium) + .outputs(ENERGY_OUTPUT_HATCH_ADJUSTABLE[GTValues.EV].getStackForm()) + .duration(100).EUt(1920).buildAndRegister(); + + RecipeMaps.ASSEMBLER_RECIPES.recipeBuilder() + .inputs(ADJUSTABLE_TRANSFORMER[GTValues.IV].getStackForm()) + .inputs(ENERGY_OUTPUT_HATCH[GTValues.IV].getStackForm()) + .inputs(MetaItems.VOLTAGE_COIL_IV.getStackForm(2)) + .inputs(MetaItems.POWER_INTEGRATED_CIRCUIT.getStackForm(2)) + .input(OrePrefix.wireGtQuadruple, Materials.TungstenSteel, 4) + .input(OrePrefix.plateDouble, Materials.TungstenSteel) + .outputs(ENERGY_OUTPUT_HATCH_ADJUSTABLE[GTValues.IV].getStackForm()) + .duration(100).EUt(7680).buildAndRegister(); + + RecipeMaps.ASSEMBLER_RECIPES.recipeBuilder() + .inputs(ADJUSTABLE_TRANSFORMER[GTValues.LuV].getStackForm()) + .inputs(ENERGY_OUTPUT_HATCH[GTValues.LuV].getStackForm()) + .inputs(MetaItems.VOLTAGE_COIL_LUV.getStackForm(2)) + .inputs(MetaItems.HIGH_POWER_INTEGRATED_CIRCUIT.getStackForm(2)) + .input(OrePrefix.wireGtQuadruple, Materials.HSSG, 4) + .input(OrePrefix.plateDouble, Materials.Chrome) + .outputs(ENERGY_OUTPUT_HATCH_ADJUSTABLE[GTValues.LuV].getStackForm()) + .duration(100).EUt(32768).buildAndRegister(); + + RecipeMaps.ASSEMBLER_RECIPES.recipeBuilder() + .inputs(ADJUSTABLE_TRANSFORMER[GTValues.ZPM].getStackForm()) + .inputs(ENERGY_OUTPUT_HATCH[GTValues.ZPM].getStackForm()) + .inputs(MetaItems.VOLTAGE_COIL_ZPM.getStackForm(2)) + .inputs(MetaItems.HIGH_POWER_INTEGRATED_CIRCUIT.getStackForm(2)) + .input(OrePrefix.wireGtQuadruple, Materials.Naquadah, 4) + .input(OrePrefix.plateDouble, Materials.Iridium) + .outputs(ENERGY_OUTPUT_HATCH_ADJUSTABLE[GTValues.ZPM].getStackForm()) + .duration(100).EUt(131072).buildAndRegister(); + + RecipeMaps.ASSEMBLER_RECIPES.recipeBuilder() + .inputs(ADJUSTABLE_TRANSFORMER[GTValues.UV].getStackForm()) + .inputs(ENERGY_OUTPUT_HATCH[GTValues.UV].getStackForm()) + .inputs(MetaItems.VOLTAGE_COIL_UV.getStackForm(2)) + .inputs(MetaItems.HIGH_POWER_INTEGRATED_CIRCUIT.getStackForm(2)) + .input(OrePrefix.wireGtQuadruple, Materials.NaquadahAlloy, 4) + .input(OrePrefix.plateDouble, Materials.Osmium) + .outputs(ENERGY_OUTPUT_HATCH_ADJUSTABLE[GTValues.UV].getStackForm()) + .duration(100).EUt(524288).buildAndRegister(); + } } diff --git a/src/main/java/gregtech/loaders/recipe/VanillaOverrideRecipes.java b/src/main/java/gregtech/loaders/recipe/VanillaOverrideRecipes.java index 10127822b60..3ab1c75246a 100644 --- a/src/main/java/gregtech/loaders/recipe/VanillaOverrideRecipes.java +++ b/src/main/java/gregtech/loaders/recipe/VanillaOverrideRecipes.java @@ -583,6 +583,7 @@ private static void metalRecipes() { * - Removes Vanilla Glistering Melon Recipe * - Removes Vanilla Golden Carrot Recipe * - Removes Vanilla Magma Cream Recipe + * - Removes Vanilla Polished Stone Variant Recipes */ private static void miscRecipes() { ModHandler.removeRecipeByName(new ResourceLocation("minecraft:tnt")); @@ -684,6 +685,10 @@ private static void miscRecipes() { RecipeMaps.ASSEMBLER_RECIPES.recipeBuilder().duration(80).EUt(6).input("logWood", 1).inputs(new ItemStack(Items.FLINT)).outputs(new ItemStack(Blocks.CRAFTING_TABLE)).buildAndRegister(); ModHandler.removeFurnaceSmelting(new ItemStack(Blocks.STONEBRICK)); + + ModHandler.removeRecipeByName(new ResourceLocation("minecraft:polished_granite")); + ModHandler.removeRecipeByName(new ResourceLocation("minecraft:polished_diorite")); + ModHandler.removeRecipeByName(new ResourceLocation("minecraft:polished_andesite")); } /** diff --git a/src/main/java/gregtech/loaders/recipe/VanillaStandardRecipes.java b/src/main/java/gregtech/loaders/recipe/VanillaStandardRecipes.java index 33b2dbd699c..d322070df39 100644 --- a/src/main/java/gregtech/loaders/recipe/VanillaStandardRecipes.java +++ b/src/main/java/gregtech/loaders/recipe/VanillaStandardRecipes.java @@ -16,6 +16,7 @@ import net.minecraft.init.Items; import net.minecraft.item.EnumDyeColor; import net.minecraft.item.ItemStack; +import net.minecraftforge.fluids.FluidStack; import static gregtech.api.GTValues.L; import static gregtech.api.recipes.RecipeMaps.*; @@ -127,7 +128,7 @@ private static void glassRecipes() { .outputs(new ItemStack(Blocks.GLASS, 2)) .buildAndRegister(); - RecipeMaps.FORMING_PRESS_RECIPES.recipeBuilder().duration(100).EUt(30) + RecipeMaps.FORMING_PRESS_RECIPES.recipeBuilder().duration(80).EUt(30) .input(dust, Materials.Glass) .notConsumable(SHAPE_MOLD_BLOCK.getStackForm()) .outputs(new ItemStack(Blocks.GLASS, 1)) @@ -157,7 +158,7 @@ private static void glassRecipes() { .outputs(new ItemStack(Blocks.GLASS)) .buildAndRegister(); - RecipeMaps.ALLOY_SMELTER_RECIPES.recipeBuilder().duration(200).EUt(16) + RecipeMaps.ALLOY_SMELTER_RECIPES.recipeBuilder().duration(120).EUt(16) .input(dust, Materials.Glass) .notConsumable(SHAPE_MOLD_BLOCK.getStackForm()) .outputs(new ItemStack(Blocks.GLASS, 1)) @@ -783,6 +784,7 @@ private static void metalRecipes() { * Adds anvil recipes * Adds Slime to rubber * Adds alternative gunpowder recipes + * Adds polished stone variant autoclave recipes */ private static void miscRecipes() { ASSEMBLER_RECIPES.recipeBuilder() @@ -952,6 +954,26 @@ private static void miscRecipes() { 'R', new UnificationEntry(ring, Iron), 'S', new ItemStack(Items.STRING) ); + + for (FluidStack fluidStack : new FluidStack[]{Water.getFluid(200), DistilledWater.getFluid(36)}) { + AUTOCLAVE_RECIPES.recipeBuilder() + .inputs(new ItemStack(Blocks.STONE, 1, 1)) + .fluidInputs(fluidStack) + .outputs(new ItemStack(Blocks.STONE, 1, 2)) + .duration(100).EUt(8).buildAndRegister(); + + AUTOCLAVE_RECIPES.recipeBuilder() + .inputs(new ItemStack(Blocks.STONE, 1, 3)) + .fluidInputs(fluidStack) + .outputs(new ItemStack(Blocks.STONE, 1, 4)) + .duration(100).EUt(8).buildAndRegister(); + + AUTOCLAVE_RECIPES.recipeBuilder() + .inputs(new ItemStack(Blocks.STONE, 1, 5)) + .fluidInputs(fluidStack) + .outputs(new ItemStack(Blocks.STONE, 1, 6)) + .duration(100).EUt(8).buildAndRegister(); + } } /** diff --git a/src/main/java/gregtech/loaders/recipe/chemistry/ChemistryRecipes.java b/src/main/java/gregtech/loaders/recipe/chemistry/ChemistryRecipes.java index b43e5540af5..5a6f0c180f1 100644 --- a/src/main/java/gregtech/loaders/recipe/chemistry/ChemistryRecipes.java +++ b/src/main/java/gregtech/loaders/recipe/chemistry/ChemistryRecipes.java @@ -1,5 +1,6 @@ package gregtech.loaders.recipe.chemistry; +import gregtech.api.recipes.ingredients.IntCircuitIngredient; import net.minecraft.init.Items; import static gregtech.api.recipes.RecipeMaps.*; @@ -46,7 +47,17 @@ public static void init() { VACUUM_RECIPES.recipeBuilder() .fluidInputs(Air.getFluid(4000)) .fluidOutputs(LiquidAir.getFluid(4000)) - .duration(400).EUt(30).buildAndRegister(); + .duration(80).EUt(480).buildAndRegister(); + + VACUUM_RECIPES.recipeBuilder() + .fluidInputs(NetherAir.getFluid(4000)) + .fluidOutputs(LiquidNetherAir.getFluid(4000)) + .duration(80).EUt(1920).buildAndRegister(); + + VACUUM_RECIPES.recipeBuilder() + .fluidInputs(EnderAir.getFluid(4000)) + .fluidOutputs(LiquidEnderAir.getFluid(4000)) + .duration(80).EUt(7680).buildAndRegister(); BLAST_RECIPES.recipeBuilder() .input(dust, FerriteMixture) @@ -78,5 +89,23 @@ public static void init() { .output(ingot, RedAlloy, 2) .blastFurnaceTemp(1200) .duration(884).EUt(120).buildAndRegister(); + + GAS_COLLECTOR_RECIPES.recipeBuilder() + .notConsumable(new IntCircuitIngredient(1)) + .fluidOutputs(Air.getFluid(10000)) + .dimension(0) + .duration(200).EUt(16).buildAndRegister(); + + GAS_COLLECTOR_RECIPES.recipeBuilder() + .notConsumable(new IntCircuitIngredient(1)) + .fluidOutputs(NetherAir.getFluid(10000)) + .dimension(-1) + .duration(200).EUt(64).buildAndRegister(); + + GAS_COLLECTOR_RECIPES.recipeBuilder() + .notConsumable(new IntCircuitIngredient(1)) + .fluidOutputs(EnderAir.getFluid(10000)) + .dimension(1) + .duration(200).EUt(256).buildAndRegister(); } } diff --git a/src/main/java/gregtech/loaders/recipe/chemistry/DistillationRecipes.java b/src/main/java/gregtech/loaders/recipe/chemistry/DistillationRecipes.java index 7b6f83ceb94..63d13ace703 100644 --- a/src/main/java/gregtech/loaders/recipe/chemistry/DistillationRecipes.java +++ b/src/main/java/gregtech/loaders/recipe/chemistry/DistillationRecipes.java @@ -404,5 +404,41 @@ public static void init() { .fluidInputs(OilHeavy.getFluid(100)) .fluidOutputs(Oil.getFluid(100)) .duration(16).EUt(24).buildAndRegister(); + + DISTILLATION_RECIPES.recipeBuilder() + .fluidInputs(LiquidAir.getFluid(50000)) + .fluidOutputs(Nitrogen.getFluid(35750)) + .fluidOutputs(Oxygen.getFluid(11250)) + .fluidOutputs(CarbonDioxide.getFluid(2500)) + .fluidOutputs(Helium.getFluid(250)) + .fluidOutputs(Argon.getFluid(250)) + .chancedOutput(dust, Ice, 9000, 0) + .disableDistilleryRecipes() + .duration(2000).EUt(480).buildAndRegister(); + + DISTILLATION_RECIPES.recipeBuilder() + .fluidInputs(LiquidNetherAir.getFluid(100000)) + .fluidOutputs(CarbonMonoxide.getFluid(72000)) + .fluidOutputs(CoalGas.getFluid(10000)) + .fluidOutputs(HydrogenSulfide.getFluid(7500)) + .fluidOutputs(SulfurDioxide.getFluid(7500)) + .fluidOutputs(Helium3.getFluid(2500)) + .fluidOutputs(Neon.getFluid(500)) + .chancedOutput(dustSmall, Ash, 9000, 0) + .disableDistilleryRecipes() + .duration(2000).EUt(1920).buildAndRegister(); + + DISTILLATION_RECIPES.recipeBuilder() + .fluidInputs(LiquidEnderAir.getFluid(200000)) + .fluidOutputs(NitrogenDioxide.getFluid(122000)) + .fluidOutputs(Deuterium.getFluid(50000)) + .fluidOutputs(Helium.getFluid(15000)) + .fluidOutputs(Tritium.getFluid(10000)) + .fluidOutputs(Krypton.getFluid(1000)) + .fluidOutputs(Xenon.getFluid(1000)) + .fluidOutputs(Radon.getFluid(1000)) + .chancedOutput(dustTiny, EnderPearl, 9000, 0) + .disableDistilleryRecipes() + .duration(2000).EUt(7680).buildAndRegister(); } } diff --git a/src/main/java/gregtech/loaders/recipe/chemistry/MixerRecipes.java b/src/main/java/gregtech/loaders/recipe/chemistry/MixerRecipes.java index 3c741fc80e0..4474b7fda52 100644 --- a/src/main/java/gregtech/loaders/recipe/chemistry/MixerRecipes.java +++ b/src/main/java/gregtech/loaders/recipe/chemistry/MixerRecipes.java @@ -184,6 +184,14 @@ public static void init() { .output(dust, Bronze, 4) .buildAndRegister(); + MIXER_RECIPES.recipeBuilder().duration(400).EUt(8) + .input(dust, Lead, 2) + .input(dust, Bronze, 2) + .input(dust, Tin, 1) + .notConsumable(new IntCircuitIngredient(1)) + .output(dust, Potin, 5) + .buildAndRegister(); + MIXER_RECIPES.recipeBuilder().duration(200).EUt(24) .input(dust, Copper) .input(dust, Nickel) @@ -369,5 +377,83 @@ public static void init() { .notConsumable(new IntCircuitIngredient(1)) .output(dust, Graphene) .buildAndRegister(); + + MIXER_RECIPES.recipeBuilder().duration(600).EUt(24) + .input(dust, Manganese) + .input(dust, Phosphorus) + .notConsumable(new IntCircuitIngredient(2)) + .output(dust, ManganesePhosphide, 2) + .buildAndRegister(); + + MIXER_RECIPES.recipeBuilder().duration(600).EUt(120) + .input(dust, Magnesium) + .input(dust, Boron, 2) + .notConsumable(new IntCircuitIngredient(2)) + .output(dust, MagnesiumDiboride, 2) + .buildAndRegister(); + + MIXER_RECIPES.recipeBuilder().duration(400).EUt(480) + .input(dust, Barium, 2) + .input(dust, Calcium, 2) + .input(dust, Copper, 3) + .fluidInputs(Mercury.getFluid(1000)) + .fluidInputs(Oxygen.getFluid(8000)) + .notConsumable(new IntCircuitIngredient(2)) + .output(dust, MercuryBariumCalciumCuprate, 16) + .buildAndRegister(); + + MIXER_RECIPES.recipeBuilder().duration(200).EUt(1920) + .input(dust, Uranium238) + .input(dust, Platinum, 3) + .notConsumable(new IntCircuitIngredient(2)) + .output(dust, UraniumTriplatinum, 4) + .buildAndRegister(); + + MIXER_RECIPES.recipeBuilder().duration(100).EUt(7680) + .input(dust, Samarium) + .input(dust, Iron) + .input(dust, Arsenic) + .fluidInputs(Oxygen.getFluid(1000)) + .notConsumable(new IntCircuitIngredient(2)) + .output(dust, SamariumIronArsenicOxide, 4) + .buildAndRegister(); + + MIXER_RECIPES.recipeBuilder().duration(600).EUt(30720) + .input(dust, Indium, 4) + .input(dust, Tin, 2) + .input(dust, Barium, 2) + .input(dust, Titanium) + .input(dust, Copper, 7) + .fluidInputs(Oxygen.getFluid(14000)) + .notConsumable(new IntCircuitIngredient(2)) + .output(dust, IndiumTinBariumTitaniumCuprate, 16) + .buildAndRegister(); + + MIXER_RECIPES.recipeBuilder().duration(150).EUt(122880) + .input(dust, Uranium238) + .input(dust, Rhodium) + .input(dust, Naquadah, 2) + .notConsumable(new IntCircuitIngredient(2)) + .output(dust, UraniumRhodiumDinaquadide, 4) + .buildAndRegister(); + + MIXER_RECIPES.recipeBuilder().duration(175).EUt(491520) + .input(dust, NaquadahEnriched, 4) + .input(dust, Trinium, 3) + .input(dust, Europium, 2) + .input(dust, Duranium) + .notConsumable(new IntCircuitIngredient(2)) + .output(dust, EnrichedNaquadahTriniumEuropiumDuranide, 10) + .buildAndRegister(); + + MIXER_RECIPES.recipeBuilder().duration(400).EUt(491520) + .input(dust, Ruthenium) + .input(dust, Trinium, 2) + .input(dust, Americium) + .input(dust, Neutronium, 2) + .fluidInputs(Oxygen.getFluid(8000)) + .notConsumable(new IntCircuitIngredient(2)) + .output(dust, RutheniumTriniumAmericiumNeutronate, 14) + .buildAndRegister(); } } diff --git a/src/main/java/gregtech/loaders/recipe/chemistry/ReactorRecipes.java b/src/main/java/gregtech/loaders/recipe/chemistry/ReactorRecipes.java index b82a69831fa..f548b7d358d 100644 --- a/src/main/java/gregtech/loaders/recipe/chemistry/ReactorRecipes.java +++ b/src/main/java/gregtech/loaders/recipe/chemistry/ReactorRecipes.java @@ -334,7 +334,7 @@ public static void init() { .fluidInputs(Water.getFluid(1000)) .output(dust, SodiumHydroxide, 3) .fluidOutputs(Hydrogen.getFluid(1000)) - .duration(40).EUt(8).buildAndRegister(); + .duration(80).EUt(30).buildAndRegister(); CHEMICAL_RECIPES.recipeBuilder() .notConsumable(new IntCircuitIngredient(1)) @@ -611,7 +611,7 @@ public static void init() { .buildAndRegister(); CHEMICAL_RECIPES.recipeBuilder() - .notConsumable(PhosphoricAcid.getFluid(0)) + .fluidInputs(PhosphoricAcid.getFluid(1000)) .fluidInputs(Benzene.getFluid(8000)) .fluidInputs(Propene.getFluid(8000)) .fluidOutputs(Cumene.getFluid(8000)) @@ -654,7 +654,7 @@ public static void init() { CHEMICAL_RECIPES.recipeBuilder() .input(dust, Aluminium, 4) .fluidInputs(IndiumConcentrate.getFluid(1000)) - .output(dustTiny, Indium) + .output(dustSmall, Indium) .fluidOutputs(LeadZincSolution.getFluid(1000)) .duration(50).EUt(600).buildAndRegister(); @@ -1098,5 +1098,11 @@ public static void init() { .fluidInputs(GlycerylTrinitrate.getFluid(500)) .output(MetaItems.DYNAMITE) .duration(160).EUt(4).buildAndRegister(); + + CHEMICAL_RECIPES.recipeBuilder() + .input(dust, Niobium) + .fluidInputs(Nitrogen.getFluid(1000)) + .output(dust, NiobiumNitride, 2) + .duration(200).EUt(480).buildAndRegister(); } } diff --git a/src/main/java/gregtech/loaders/recipe/chemistry/SeparationRecipes.java b/src/main/java/gregtech/loaders/recipe/chemistry/SeparationRecipes.java index a0b1b4168b1..91eed36a3d6 100644 --- a/src/main/java/gregtech/loaders/recipe/chemistry/SeparationRecipes.java +++ b/src/main/java/gregtech/loaders/recipe/chemistry/SeparationRecipes.java @@ -38,23 +38,6 @@ public static void init() { .fluidOutputs(LPG.getFluid(4000)) .duration(200).EUt(5).buildAndRegister(); - CENTRIFUGE_RECIPES.recipeBuilder() - .fluidInputs(LiquidAir.getFluid(53000)) - .fluidOutputs(Nitrogen.getFluid(32000)) - .fluidOutputs(Nitrogen.getFluid(8000)) - .fluidOutputs(Oxygen.getFluid(11000)) - .fluidOutputs(Argon.getFluid(1000)) - .fluidOutputs(NobleGases.getFluid(1000)) - .duration(1484).EUt(5).buildAndRegister(); - - CENTRIFUGE_RECIPES.recipeBuilder() - .fluidInputs(NobleGases.getFluid(34000)) - .fluidOutputs(CarbonDioxide.getFluid(21000)) - .fluidOutputs(Helium.getFluid(9000)) - .fluidOutputs(Methane.getFluid(3000)) - .fluidOutputs(Deuterium.getFluid(1000)) - .duration(680).EUt(5).buildAndRegister(); - CENTRIFUGE_RECIPES.recipeBuilder() .fluidInputs(Butane.getFluid(320)) .fluidOutputs(LPG.getFluid(370)) @@ -297,6 +280,18 @@ public static void init() { .fluidOutputs(Oxygen.getFluid(1000)) .buildAndRegister(); + CENTRIFUGE_RECIPES.recipeBuilder().duration(1600).EUt(30) + .fluidInputs(NetherAir.getFluid(10000)) + .fluidOutputs(CarbonMonoxide.getFluid(3900)) + .fluidOutputs(SulfurDioxide.getFluid(1000)) + .buildAndRegister(); + + CENTRIFUGE_RECIPES.recipeBuilder().duration(1600).EUt(480) + .fluidInputs(EnderAir.getFluid(10000)) + .fluidOutputs(NitrogenDioxide.getFluid(3900)) + .fluidOutputs(Deuterium.getFluid(1000)) + .buildAndRegister(); + // Stone Dust CENTRIFUGE_RECIPES.recipeBuilder().duration(480).EUt(120) .input(dust, Stone) @@ -318,6 +313,11 @@ public static void init() { .chancedOutput(dustTiny, Ilmenite, 5000, 500) .buildAndRegister(); + CENTRIFUGE_RECIPES.recipeBuilder().duration(800).EUt(5) + .input(dust, Oilsands) + .fluidOutputs(Oil.getFluid(1000)) + .buildAndRegister(); + // Electrolyzer ELECTROLYZER_RECIPES.recipeBuilder() diff --git a/src/main/java/gregtech/loaders/recipe/component/AnnotatedComponentHandlerLoader.java b/src/main/java/gregtech/loaders/recipe/component/AnnotatedComponentHandlerLoader.java new file mode 100644 index 00000000000..eafdd2ee2aa --- /dev/null +++ b/src/main/java/gregtech/loaders/recipe/component/AnnotatedComponentHandlerLoader.java @@ -0,0 +1,82 @@ +package gregtech.loaders.recipe.component; + +import gregtech.api.util.GTLog; +import net.minecraftforge.fml.common.discovery.ASMDataTable; +import net.minecraftforge.fml.common.discovery.ASMDataTable.ASMData; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.util.Set; + +public class AnnotatedComponentHandlerLoader { + + public static void discoverAndLoadAnnotatedComponentHandlers(ASMDataTable asmDataTable) { + Set annotations = asmDataTable.getAll(IComponentHandler.RegisterComponentHandler.class.getName()); + int componentHandlersRegistered = 0; + for (ASMData annotationData :annotations) { + String componentHandlerClassName = annotationData.getClassName(); + Class componentHandlerClass; + try { + componentHandlerClass = Class.forName(componentHandlerClassName); + } catch (ClassNotFoundException e) { + GTLog.logger.error("Failed to load annotated component handler class {}. FML annotation data is broken perhaps?", componentHandlerClassName); + continue; + } + String denyReason = null; + Throwable loadingError = null; + + Field instanceField = null; + Constructor constructor = null; + + if (!IComponentHandler.class.isAssignableFrom(componentHandlerClass)) { + denyReason = "class does not implement IComponentHandler"; + } else if (Modifier.isAbstract(componentHandlerClass.getModifiers())) { + denyReason = "class is abstract and cannot be initialized"; + } + try { + instanceField = componentHandlerClass.getField("INSTANCE"); + if (instanceField.getType() != componentHandlerClass) { + denyReason = "found INSTANCE field, but it's type is not the same as class type"; + } else if (!Modifier.isStatic(instanceField.getModifiers())) { + denyReason = "found INSTANCE field, but it's not static and cannot be used"; + } + } catch (NoSuchFieldException noSuchField) { + try { + constructor = componentHandlerClass.getConstructor(); + } catch (NoSuchMethodException noSuchMethod) { + denyReason = "didn't found public static final INSTANCE field or public no-arg constructor for initialization"; + } + } + + IComponentHandler componentHandler = null; + if (denyReason == null) { + if (instanceField != null) { + try { + componentHandler = (IComponentHandler) instanceField.get(null); + } catch (ReflectiveOperationException e) { + denyReason = "failed to retrieve INSTANCE field value"; + loadingError = e; + } + } else { + try { + componentHandler = (IComponentHandler) constructor.newInstance(); + } catch (ReflectiveOperationException e) { + denyReason = "failed to initialize component handler"; + loadingError = e; + } + } + } + if (denyReason == null) { + GTLog.logger.info("Registered component handler {}", componentHandler.getClass().getName()); + IComponentHandler.registerComponentHandler(componentHandler); + componentHandlersRegistered++; + } else { + GTLog.logger.error("Failed to load material handler class {} from {}: {}", + componentHandlerClassName, annotationData.getCandidate().getModContainer().getName(), denyReason, loadingError); + GTLog.logger.error("Consult the mod author for a fix on their side."); + } + } + GTLog.logger.info("{} annotated component handlers registered", componentHandlersRegistered); + } +} diff --git a/src/main/java/gregtech/loaders/recipe/component/IComponentHandler.java b/src/main/java/gregtech/loaders/recipe/component/IComponentHandler.java new file mode 100644 index 00000000000..bceb703cf13 --- /dev/null +++ b/src/main/java/gregtech/loaders/recipe/component/IComponentHandler.java @@ -0,0 +1,28 @@ +package gregtech.loaders.recipe.component; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.util.ArrayList; +import java.util.List; + +public interface IComponentHandler { + + List componentHandlers = new ArrayList<>(); + + static void registerComponentHandler(IComponentHandler componentHandler) { + componentHandlers.add(componentHandler); + } + + static void runComponentHandlers() { + componentHandlers.forEach(IComponentHandler::onComponentsInit); + } + + void onComponentsInit(); + + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.TYPE) + @interface RegisterComponentHandler { + } +} diff --git a/src/main/resources/assets/gregtech/blockstates/fluid_pipe_nonuple.json b/src/main/resources/assets/gregtech/blockstates/fluid_pipe_nonuple.json new file mode 100644 index 00000000000..86cb52c5cc7 --- /dev/null +++ b/src/main/resources/assets/gregtech/blockstates/fluid_pipe_nonuple.json @@ -0,0 +1,17 @@ +{ + "forge_marker": 1, + "defaults": { + "model": "minecraft:cube_all", + "textures": { + "all": "blocks/iron_block" + } + }, + "variants": { + "normal": [ + {} + ], + "inventory": [ + {} + ] + } +} diff --git a/src/main/resources/assets/gregtech/blockstates/fluid_pipe_quadruple.json b/src/main/resources/assets/gregtech/blockstates/fluid_pipe_quadruple.json new file mode 100644 index 00000000000..86cb52c5cc7 --- /dev/null +++ b/src/main/resources/assets/gregtech/blockstates/fluid_pipe_quadruple.json @@ -0,0 +1,17 @@ +{ + "forge_marker": 1, + "defaults": { + "model": "minecraft:cube_all", + "textures": { + "all": "blocks/iron_block" + } + }, + "variants": { + "normal": [ + {} + ], + "inventory": [ + {} + ] + } +} diff --git a/src/main/resources/assets/gregtech/lang/en_us.lang b/src/main/resources/assets/gregtech/lang/en_us.lang index 5e228117688..b07f882e64c 100644 --- a/src/main/resources/assets/gregtech/lang/en_us.lang +++ b/src/main/resources/assets/gregtech/lang/en_us.lang @@ -260,15 +260,23 @@ metaitem.battery.hull.mv.name=Medium Battery Hull metaitem.battery.hull.mv.tooltip=An empty MV Battery Hull metaitem.battery.hull.hv.name=Large Battery Hull metaitem.battery.hull.hv.tooltip=An empty HV Battery Hull +metaitem.battery.hull.ev.name=Small Vanadium Battery Hull +metaitem.battery.hull.ev.tooltip=An empty EV Battery Hull +metaitem.battery.hull.iv.name=Medium Vanadium Battery Hull +metaitem.battery.hull.iv.tooltip=An empty IV Battery Hull +metaitem.battery.hull.luv.name=Large Vanadium Battery Hull +metaitem.battery.hull.luv.tooltip=An empty LuV Battery Hull +metaitem.battery.hull.zpm.name=Medium Naquadria Battery Hull +metaitem.battery.hull.zpm.tooltip=An empty ZPM Battery Hull +metaitem.battery.hull.uv.name=Large Naquadria Battery Hull +metaitem.battery.hull.uv.tooltip=An empty UV Battery Hull + +metaitem.battery.charge_time=§aHolds %,d%s of Power +metaitem.battery.charge_detailed=%,d/%,d EU - Tier §e%s §r(§%c%,d%s remaining§r) metaitem.battery.re.ulv.tantalum.name=Tantalum Capacitor metaitem.battery.re.ulv.tantalum.tooltip=Reusable Battery -metaitem.battery.su.lv.sulfuricacid.name=Small Acid Battery -metaitem.battery.su.lv.sulfuricacid.tooltip=Single Use Battery -metaitem.battery.su.lv.mercury.name=Small Mercury Battery -metaitem.battery.su.lv.mercury.tooltip=Single Use Battery - metaitem.battery.re.lv.cadmium.name=Small Cadmium Battery metaitem.battery.re.lv.cadmium.tooltip=Reusable Battery metaitem.battery.re.lv.lithium.name=Small Lithium Battery @@ -276,11 +284,6 @@ metaitem.battery.re.lv.lithium.tooltip=Reusable Battery metaitem.battery.re.lv.sodium.name=Small Sodium Battery metaitem.battery.re.lv.sodium.tooltip=Reusable Battery -metaitem.battery.su.mv.sulfuricacid.name=Medium Acid Battery -metaitem.battery.su.mv.sulfuricacid.tooltip=Single Use Battery -metaitem.battery.su.mv.mercury.name=Medium Mercury Battery -metaitem.battery.su.mv.mercury.tooltip=Single Use Battery - metaitem.battery.re.mv.cadmium.name=Medium Cadmium Battery metaitem.battery.re.mv.cadmium.tooltip=Reusable Battery metaitem.battery.re.mv.lithium.name=Medium Lithium Battery @@ -288,11 +291,6 @@ metaitem.battery.re.mv.lithium.tooltip=Reusable Battery metaitem.battery.re.mv.sodium.name=Medium Sodium Battery metaitem.battery.re.mv.sodium.tooltip=Reusable Battery -metaitem.battery.su.hv.sulfuricacid.name=Large Acid Battery -metaitem.battery.su.hv.sulfuricacid.tooltip=Single Use Battery -metaitem.battery.su.hv.mercury.name=Large Mercury Battery -metaitem.battery.su.hv.mercury.tooltip=Single Use Battery - metaitem.battery.re.hv.cadmium.name=Large Cadmium Battery metaitem.battery.re.hv.cadmium.tooltip=Reusable Battery metaitem.battery.re.hv.lithium.name=Large Lithium Battery @@ -300,6 +298,18 @@ metaitem.battery.re.hv.lithium.tooltip=Reusable Battery metaitem.battery.re.hv.sodium.name=Large Sodium Battery metaitem.battery.re.hv.sodium.tooltip=Reusable Battery +metaitem.battery.ev.vanadium.name=Small Vanadium Battery +metaitem.battery.ev.vanadium.tooltip=Reusable Battery +metaitem.battery.iv.vanadium.name=Medium Vanadium Battery +metaitem.battery.iv.vanadium.tooltip=Reusable Battery +metaitem.battery.luv.vanadium.name=Large Vanadium Battery +metaitem.battery.luv.vanadium.tooltip=Reusable Battery + +metaitem.battery.zpm.naquadria.name=Medium Naquadria Battery +metaitem.battery.zpm.naquadria.tooltip=Reusable Battery +metaitem.battery.uv.naquadria.name=Large Naquadria Battery +metaitem.battery.uv.naquadria.tooltip=Reusable Battery + metaitem.energy_crystal.name=Energy Crystal metaitem.energy_crystal.tooltip=Reusable Battery metaitem.lapotron_crystal.name=Lapotron Crystal @@ -311,9 +321,11 @@ metaitem.energy.lapotronicorb2.tooltip=Reusable Battery metaitem.zpm.name=Zero Point Module metaitem.zpm.tooltip=Single Use Battery metaitem.energy.module.name=Energy Module +metaitem.energy.module.tooltip=Reusable Battery metaitem.energy.cluster.name=Energy Cluster +metaitem.energy.cluster.tooltip=Reusable Battery metaitem.max.battery.name=Ultimate Battery -metaitem.max.battery.tooltip=Fill this to win minecraft +metaitem.max.battery.tooltip=Fill this to win Minecraft metaitem.electric.motor.lv.name=LV Electric Motor metaitem.electric.motor.mv.name=MV Electric Motor @@ -728,6 +740,9 @@ metaitem.cover.solar.panel.ulv.tooltip=8 Volt Solar Panel metaitem.cover.solar.panel.lv.name=Solar Panel (LV) metaitem.cover.solar.panel.lv.tooltip=Low Voltage Solar Panel +metaitem.cover.infinite_water.name=Infinite Water Cover +metaitem.cover.infinite_water.tooltip=Creates 16 Buckets of Water every second (as Cover) + metaitem.gelled_toluene.name=Gelled Toluene metaitem.gelled_toluene.tooltip=Raw Explosive @@ -1057,6 +1072,8 @@ item.material.oreprefix.pipeSmallFluid=Small %s Fluid Pipe item.material.oreprefix.pipeNormalFluid=Normal %s Fluid Pipe item.material.oreprefix.pipeLargeFluid=Large %s Fluid Pipe item.material.oreprefix.pipeHugeFluid=Huge %s Fluid Pipe +item.material.oreprefix.pipeQuadrupleFluid=Quadruple %s Fluid Pipe +item.material.oreprefix.pipeNonupleFluid=Nonuple %s Fluid Pipe item.material.oreprefix.pipeTinyItem=Tiny %s Item Pipe item.material.oreprefix.pipeSmallItem=Small %s Item Pipe item.material.oreprefix.pipeNormalItem=Normal %s Item Pipe @@ -1246,9 +1263,12 @@ material.tennantite=Tennantite material.methane=Methane material.carbon_dioxide=Carbon Dioxide -material.noble_gases=Noble Gases material.air=Air material.liquid_air=Liquid Air +material.nether_air=Nether Air +material.liquid_nether_air=Liquid Nether Air +material.ender_air=Ender Air +material.liquid_ender_air=Liquid Ender Air material.almandine=Almandine material.andradite=Andradite material.annealed_copper=Annealed Copper @@ -1661,6 +1681,16 @@ material.coal_tar=Coal Tar material.ethylbenzene=Ethylbenzene material.naphthalene=Naphthalene +material.manganese_phosphide=Manganese Phosphide +material.magnesium_diboride=Magnesium Diboride +material.mercury_barium_calcium_cuprate=Mercury Barium Calcium Cuprate +material.uranium_triplatinum=Uranium Triplatinum +material.samarium_iron_arsenic_oxide=Samarium Iron Arsenic Oxide +material.indium_tin_barium_titanium_cuprate=Indium Tin Barium Titanium Cuprate +material.uranium_rhodium_dinaquadide=Uranium Rhodium Dinaquadide +material.enriched_naquadah_trinium_europium_duranide=Enriched Naquadah Trinium Europium Duranide +material.ruthenium_trinium_americium_neutronate=Ruthenium Trinium Americium Neutronate + item.nether_quartz.oreNetherrack=Nether Quartz Ore item.gunpowder.dustTiny=Tiny Pile of Gunpowder item.gunpowder.dustSmall=Small Pile of Gunpowder @@ -1872,7 +1902,7 @@ recipemap.ore_washer.name=Ore Washer recipemap.thermal_centrifuge.name=Thermal Centrifuge recipemap.extractor.name=Extractor recipemap.recycler.name=Recycler -recipemap.electic_furnace.name=Furnace +recipemap.electric_furnace.name=Furnace recipemap.scanner.name=Scanner recipemap.rockbreaker.name=Rock Breaker recipemap.byproductlist.name=Ore Byproduct List @@ -1930,6 +1960,10 @@ recipemap.semi_fluid_generator.name=Semi Fluid Fuels recipemap.plasma_generator.name=Plasma Generator recipemap.circuit_assembler.name=Circuit Assembler recipemap.mass_fabricator.name=Mass Fabricator +recipemap.materialtree.name=Material Tree +recipemap.gas_collector.name=Gas Collector +recipemap.primitive_blast_furnace.name=Primitive Blast Furnace +recipemap.coke_oven.name=Coke Oven behaviour.hoe=Can till dirt behaviour.soft_hammer=Activates and Deactivates Machines @@ -1963,6 +1997,9 @@ behavior.scanner.analyzing_failed=Analyzing failed! behavior.scanner.analyzing_complete=Analyzing complete! behavior.scanner.not_enough_energy=Analyzing failed: Not Enough Energy! +metaitem.terminal.name=Terminal +metaitem.terminal.tooltip=Hope it will help you + tile.casing.ulv=ULV Machine Casing tile.casing.lv=LV Machine Casing tile.casing.mv=MV Machine Casing @@ -2053,7 +2090,7 @@ tile.machine_casing.maximum_voltage.name=MAX Machine Casing tile.steam_casing.bronze_hull.name=Bronze Hull tile.steam_casing.bronze_bricks_hull.name=Bricked Bronze Hull tile.steam_casing.steel_hull.name=Steel Hull -tile.steam_casing.steel_bricks_hull.name=Bricked Steel Hull +tile.steam_casing.steel_bricks_hull.name=Bricked Wrought Iron Hull tile.steam_casing.bronze.tooltip=For your first Steam Machines tile.steam_casing.steel.tooltip=For improved Steam Machines tile.steam_casing.pump_deck.name=Pump Deck @@ -2188,7 +2225,7 @@ tile.concrete.dark_bricks.mossy.name=Mossy Dark Concrete Bricks tile.concrete.dark_bricks.chiseled.name=Chiseled Dark Concrete Bricks # Steam machines -gregtech.machine.steam_boiler.tooltip_produces=Produces %,dL of steam in %,d ticks +gregtech.machine.steam_boiler.tooltip_produces=Produces %,dL of Steam per second gregtech.machine.steam_boiler_coal_bronze.name=Small Steam Coal Boiler gregtech.machine.steam_boiler_coal_bronze.tooltip=An early way to get Steam Power @@ -2196,6 +2233,8 @@ gregtech.machine.steam_boiler_coal_steel.name=High Pressure Steam Coal Boiler gregtech.machine.steam_boiler_coal_steel.tooltip=Faster than the Small Steam Coal Boiler gregtech.machine.steam_boiler_solar_bronze.name=Steam Solar Boiler gregtech.machine.steam_boiler_solar_bronze.tooltip=Steam Power by Sun +gregtech.machine.steam_boiler_solar_steel.name=High Pressure Steam Solar Boiler +gregtech.machine.steam_boiler_solar_steel.tooltip=Steam Power by Sun gregtech.machine.steam_boiler_lava_bronze.name=Small Steam Lava Boiler gregtech.machine.steam_boiler_lava_bronze.tooltip=A Boiler running off Lava gregtech.machine.steam_boiler_lava_steel.name=High Pressure Steam Lava Boiler @@ -2703,6 +2742,9 @@ gregtech.machine.ore_washer.uiv.name=High-Tech Ore Washing Plant III gregtech.machine.ore_washer.umv.name=High-Tech Ore Washing Plant IV gregtech.machine.ore_washer.uxv.name=Ultimate Ore Washing Plant +gregtech.machine.ore_washer.simple.name=Simple Ore Washing Plant +gregtech.machine.ore_washer.simple.tooltip=It's like an automatic Cauldron for Washing. Grants no Byproducts, but it is fast. + gregtech.machine.packer.tooltip=Puts things into Boxes gregtech.machine.packer.lv.name=Basic Packager @@ -2824,6 +2866,12 @@ gregtech.machine.circuit_assembler.ev.name=Advanced Circuit Assembler III gregtech.machine.circuit_assembler.iv.name=Elite Circuit Assembler gregtech.machine.circuit_assembler.luv.name=Elite Circuit Assembler II gregtech.machine.circuit_assembler.zpm.name=Elite Circuit Assembler III +gregtech.machine.circuit_assembler.uv.name=Elite Circuit Assembler IV +gregtech.machine.circuit_assembler.uhv.name=High-Tech Circuit Assembler +gregtech.machine.circuit_assembler.uev.name=High-Tech Circuit Assembler II +gregtech.machine.circuit_assembler.uiv.name=High-Tech Circuit Assembler III +gregtech.machine.circuit_assembler.umv.name=High-Tech Circuit Assembler IV +gregtech.machine.circuit_assembler.uxv.name=Ultimate Circuit Assembler gregtech.machine.mass_fabricator.tooltip=UUM = Matter * Fabrication Squared @@ -2873,8 +2921,8 @@ gregtech.machine.scanner.uiv.name=High-Tech Scanner III gregtech.machine.scanner.umv.name=High-Tech Scanner IV gregtech.machine.scanner.uxv.name=Ultimate Scanner -gregtech.machine.infinite_emitter.name=Infinite GT Energy Unit Emitter -gregtech.machine.infinite_emitter.tooltip=§fYou just need §5C§dr§4e§ca§et§ai§bv§3e §7m§1o§5d§de§f to use this +gregtech.machine.infinite_energy.name=Infinite GT Energy Unit Emitter +gregtech.machine.infinite_energy.tooltip=§8You just need §o§5C§dr§4e§ca§et§ai§bv§3e §7m§1o§5d§de§r§8 to use this # Machine hulls gregtech.machine.hull.tooltip=§fYou just need §5I§dm§4a§cg§ei§an§ba§3t§7i§1o§5n§f to use this @@ -2973,10 +3021,12 @@ gregtech.machine.battery_buffer.max.16.name=MAX Voltage Battery Buffer # Transformers gregtech.machine.transformer.tooltip_tool_usage=Use Soft Hammer to invert (Starts as Transform Down) -gregtech.machine.transformer.tooltip_transform_down=Transform Down: +gregtech.machine.transformer.tooltip_transform_down=Transform Down: §a%dA %dV (%d)§7 -> §a%dA %dV (%d) gregtech.machine.transformer.message_transform_down=Transforming Down, In: %dV %dA, Out: %dV %dA -gregtech.machine.transformer.tooltip_transform_up=Transform Up: +gregtech.machine.transformer.tooltip_transform_up=Transform Up: §a%dA %dV (%d)§7 -> §a%dA %dV (%d) gregtech.machine.transformer.message_transform_up=Transforming Up, In: %dV %dA, Out: %dV %dA +gregtech.machine.transformer_adjustable.tooltip_tool_usage=Use Screwdriver to cycle amperage (Starts as 4 Amps) +gregtech.machine.transformer_adjustable.message_adjust=Adjusted Hi-Amp to %dV %dA, Lo-Amp to %dV %dA gregtech.machine.transformer.ulv.name=Ultra Low Voltage Transformer gregtech.machine.transformer.lv.name=Low Voltage Transformer @@ -2993,6 +3043,42 @@ gregtech.machine.transformer.uiv.name=UIV Voltage Transformer gregtech.machine.transformer.umv.name=UMV Voltage Transformer gregtech.machine.transformer.uxv.name=UXV Voltage Transformer +gregtech.machine.transformer.adjustable.ulv.name=Ultra Low Voltage Adjustable Transformer +gregtech.machine.transformer.adjustable.lv.name=Low Voltage Adjustable Transformer +gregtech.machine.transformer.adjustable.mv.name=Medium Voltage Adjustable Transformer +gregtech.machine.transformer.adjustable.hv.name=High Voltage Adjustable Transformer +gregtech.machine.transformer.adjustable.ev.name=Extreme Voltage Adjustable Transformer +gregtech.machine.transformer.adjustable.iv.name=Insane Voltage Adjustable Transformer +gregtech.machine.transformer.adjustable.luv.name=Ludicrous Voltage Adjustable Transformer +gregtech.machine.transformer.adjustable.zpm.name=ZPM Voltage Adjustable Transformer +gregtech.machine.transformer.adjustable.uv.name=Ultimate Voltage Adjustable Transformer +gregtech.machine.transformer.adjustable.uhv.name=UHV Voltage Adjustable Transformer +gregtech.machine.transformer.adjustable.uev.name=UEV Voltage Adjustable Transformer +gregtech.machine.transformer.adjustable.uiv.name=UIV Voltage Adjustable Transformer +gregtech.machine.transformer.adjustable.umv.name=UMV Voltage Adjustable Transformer +gregtech.machine.transformer.adjustable.uxv.name=UXV Voltage Adjustable Transformer + +# Diodes +gregtech.machine.diode.message=Max Amperage throughput: %s +gregtech.machine.diode.tooltip_general=A simple Diode that will allow Energy Flow in only one direction. +gregtech.machine.diode.tooltip_tool_usage=Hit with a Soft Hammer to toggle Amperage flow. + +gregtech.machine.diode.ulv.name=Ultra Low Voltage Diode +gregtech.machine.diode.lv.name=Low Voltage Diode +gregtech.machine.diode.mv.name=Medium Voltage Diode +gregtech.machine.diode.hv.name=High Voltage Diode +gregtech.machine.diode.ev.name=Extreme Voltage Diode +gregtech.machine.diode.iv.name=Insane Voltage Diode +gregtech.machine.diode.luv.name=Ludicrous Voltage Diode +gregtech.machine.diode.zpm.name=ZPM Voltage Diode +gregtech.machine.diode.uv.name=Ultimate Voltage Diode +gregtech.machine.diode.uhv.name=UHV Voltage Diode +gregtech.machine.diode.uev.name=UEV Voltage Diode +gregtech.machine.diode.uiv.name=UIV Voltage Diode +gregtech.machine.diode.umv.name=UMV Voltage Diode +gregtech.machine.diode.uxv.name=UXV Voltage Diode +gregtech.machine.diode.max.name=MAX Voltage Diode + # Chargers gregtech.machine.charger.ulv.name=Ultra Low Voltage Battery Charger gregtech.machine.charger.lv.name=Low Voltage Battery Charger @@ -3066,6 +3152,14 @@ gregtech.machine.quantum_tank.zpm.name=Quantum Tank III gregtech.machine.quantum_tank.uv.name=Quantum Tank IV gregtech.machine.quantum_tank.uhv.name=Quantum Tank V +#Buffers +gregtech.machine.buffer.tooltip=A Small Buffer to store Items and Fluids +gregtech.machine.buffer.inventory=Item Capacity: %d Slots +gregtech.machine.buffer.tanks=Fluid Capacity: %d Tanks at 64,000L each +gregtech.machine.buffer.lv.name=Basic Buffer +gregtech.machine.buffer.mv.name=Advanced Buffer +gregtech.machine.buffer.hv.name=Advanced Buffer II + #Hermetic Casing tile.hermetic_casing.hermetic_casing_lv.name=Hermetic Casing I tile.hermetic_casing.hermetic_casing_mv.name=Hermetic Casing II @@ -3078,15 +3172,15 @@ tile.hermetic_casing.hermetic_casing_uv.name=Hermetic Casing VIII tile.hermetic_casing.hermetic_casing_max.name=Hermetic Casing IX #Air Collectors -gregtech.machine.air_collector.lv.name=Basic Air Collector -gregtech.machine.air_collector.mv.name=Advanced Air Collector -gregtech.machine.air_collector.hv.name=Advanced Air Collector II -gregtech.machine.air_collector.ev.name=Advanced Air Collector III -gregtech.machine.air_collector.iv.name=Atmosphere Collector -gregtech.machine.air_collector.luv.name=Atmosphere Collector II -gregtech.machine.air_collector.tooltip=Collects air from adjacent blocks at the expense of energy -gregtech.machine.air_collector.collection_speed=Produces %,d L of Air every %,d ticks -gregtech.machine.air_collector.jei_description=The Air Collector collects air from adjacent blocks for a little bit of EU +gregtech.machine.gas_collector.lv.name=Basic Gas Collector +gregtech.machine.gas_collector.mv.name=Advanced Gas Collector +gregtech.machine.gas_collector.hv.name=Advanced Gas Collector II +gregtech.machine.gas_collector.ev.name=Advanced Gas Collector III +gregtech.machine.gas_collector.iv.name=Atmosphere Collector +gregtech.machine.gas_collector.luv.name=Atmosphere Collector II +gregtech.machine.gas_collector.zpm.name=Atmosphere Collector III +gregtech.machine.gas_collector.uv.name=Atmosphere Collector IV +gregtech.machine.gas_collector.tooltip=Collects gas from adjacent blocks at the expense of energy, depending on the dimension #Fisher gregtech.machine.fisher.lv.name=Basic Fisher @@ -3421,6 +3515,24 @@ gregtech.machine.energy_hatch.input.umv.name=UMV Energy Hatch gregtech.machine.energy_hatch.input.uxv.name=UXV Energy Hatch gregtech.machine.energy_hatch.input.max.name=MAX Energy Hatch +gregtech.machine.energy_hatch.adjustable.input.tooltip=Adjustable Ampere Energy Input for Multiblocks + +gregtech.machine.energy_hatch.adjustable.input.ulv.name=ULV Adjustable Energy Hatch +gregtech.machine.energy_hatch.adjustable.input.lv.name=LV Adjustable Energy Hatch +gregtech.machine.energy_hatch.adjustable.input.mv.name=MV Adjustable Energy Hatch +gregtech.machine.energy_hatch.adjustable.input.hv.name=HV Adjustable Energy Hatch +gregtech.machine.energy_hatch.adjustable.input.ev.name=EV Adjustable Energy Hatch +gregtech.machine.energy_hatch.adjustable.input.iv.name=IV Adjustable Energy Hatch +gregtech.machine.energy_hatch.adjustable.input.luv.name=LuV Adjustable Energy Hatch +gregtech.machine.energy_hatch.adjustable.input.zpm.name=ZPM Adjustable Energy Hatch +gregtech.machine.energy_hatch.adjustable.input.uv.name=UV Adjustable Energy Hatch +gregtech.machine.energy_hatch.adjustable.input.uhv.name=UHV Adjustable Energy Hatch +gregtech.machine.energy_hatch.adjustable.input.uev.name=UEV Adjustable Energy Hatch +gregtech.machine.energy_hatch.adjustable.input.uiv.name=UIV Adjustable Energy Hatch +gregtech.machine.energy_hatch.adjustable.input.umv.name=UMV Adjustable Energy Hatch +gregtech.machine.energy_hatch.adjustable.input.uxv.name=UXV Adjustable Energy Hatch +gregtech.machine.energy_hatch.adjustable.input.max.name=MAX Adjustable Energy Hatch + gregtech.machine.energy_hatch.output.tooltip=Energy Output for Multiblocks gregtech.machine.energy_hatch.output.ulv.name=ULV Dynamo Hatch @@ -3439,6 +3551,26 @@ gregtech.machine.energy_hatch.output.umv.name=UMV Dynamo Hatch gregtech.machine.energy_hatch.output.uxv.name=UXV Dynamo Hatch gregtech.machine.energy_hatch.output.max.name=MAX Dynamo Hatch +gregtech.machine.energy_hatch.adjustable.output.tooltip=Adjustable Ampere Energy Output for Multiblocks + +gregtech.machine.energy_hatch.adjustable.output.ulv.name=ULV Adjustable Dynamo Hatch +gregtech.machine.energy_hatch.adjustable.output.lv.name=LV Adjustable Dynamo Hatch +gregtech.machine.energy_hatch.adjustable.output.mv.name=MV Adjustable Dynamo Hatch +gregtech.machine.energy_hatch.adjustable.output.hv.name=HV Adjustable Dynamo Hatch +gregtech.machine.energy_hatch.adjustable.output.ev.name=EV Adjustable Dynamo Hatch +gregtech.machine.energy_hatch.adjustable.output.iv.name=IV Adjustable Dynamo Hatch +gregtech.machine.energy_hatch.adjustable.output.luv.name=LuV Adjustable Dynamo Hatch +gregtech.machine.energy_hatch.adjustable.output.zpm.name=ZPM Adjustable Dynamo Hatch +gregtech.machine.energy_hatch.adjustable.output.uv.name=UV Adjustable Dynamo Hatch +gregtech.machine.energy_hatch.adjustable.output.uhv.name=UHV Adjustable Dynamo Hatch +gregtech.machine.energy_hatch.adjustable.output.uev.name=UEV Adjustable Dynamo Hatch +gregtech.machine.energy_hatch.adjustable.output.uiv.name=UIV Adjustable Dynamo Hatch +gregtech.machine.energy_hatch.adjustable.output.umv.name=UMV Adjustable Dynamo Hatch +gregtech.machine.energy_hatch.adjustable.output.uxv.name=UXV Adjustable Dynamo Hatch +gregtech.machine.energy_hatch.adjustable.output.max.name=MAX Adjustable Dynamo Hatch + +gregtech.machine.energy_hatch_adjustable.message_adjust=Adjusted Amperage to %dA + gregtech.machine.rotor_holder.tooltip1=Rotor Holder for Multiblocks gregtech.machine.rotor_holder.tooltip2=Holds Rotor in place so it will not fly away @@ -3477,6 +3609,7 @@ gregtech.recipe.chance=Chance: %s%% +%s%%/tier gregtech.recipe.blast_furnace_temperature=Temperature: %,dK (%s) gregtech.recipe.explosive=Explosive: %s gregtech.recipe.eu_to_start=Energy To Start: %sEU +gregtech.recipe.dimensions=Dimensions: %s gregtech.fluid.click_to_fill=§7Click with a empty fluid container to fill it from tank. gregtech.fluid.click_to_fill.shift=§7(Shift-clicking will fill all containers in your hand) @@ -3514,16 +3647,22 @@ gregtech.jei.ore.surface_rock_2=They can be broken for 3 Tiny Piles of the dust, gregtech.jei.ore.biome_weighting=%s Weight: %d gregtech.jei.ore.biome_weighting_no_spawn=%s Weight: Cannot Spawn +gregtech.jei.materials.average_mass=Average mass: %,d +gregtech.jei.materials.average_protons=Average protons: %,d +gregtech.jei.materials.average_neutrons=Average neutrons: %,d + gregtech.item_filter.empty_item=Empty (No Item) gregtech.item_filter.footer=§eClick with item to override gregtech.cable.voltage=Max Voltage: §a%,d §a(%s) gregtech.cable.amperage=Max Amperage: §e%,d gregtech.cable.loss_per_block=Loss/Meter/Ampere: §c%,d§7 EU-Volt +gregtech.cable.superconductor=§d%s Superconductor gregtech.fluid_pipe.throughput=§9Transfer Rate: %,d L/s gregtech.fluid_pipe.max_temperature=§cTemperature Limit: %,dK gregtech.fluid_pipe.non_gas_proof=§aCan't transfer gases. +gregtech.fluid_pipe.channels=§eChannels: %d gregtech.item_pipe.rate_items=§9Transfer Rate: %d items/s gregtech.item_pipe.rate_stacks=§9Transfer Rate: %d stacks/s @@ -3570,6 +3709,7 @@ gregtech.multiblock.turbine.rotor_speed=Rotor Speed: %s / %s RPM gregtech.multiblock.turbine.rotor_efficiency=Rotor Efficiency: %s%% gregtech.multiblock.turbine.rotor_durability=Rotor Durability: %s%% gregtech.multiblock.turbine.low_rotor_durability=WARNING: Rotor Durability below %s%% (%s%%) +gregtech.multiblock.turbine.obstructed=Turbine Face Obstructed gregtech.multiblock.large_boiler.temperature=Temperature: %s / %s C gregtech.multiblock.large_boiler.steam_output=Steam Output: %s L/t @@ -3629,3 +3769,63 @@ gregtech.cover.fluid_detector.message_fluid_storage_inverted=Monitoring Inverted gregtech.cover.item_detector.message_item_storage_normal=Monitoring Normal Item Storage gregtech.cover.item_detector.message_item_storage_inverted=Monitoring Inverted Item Storage + +gregtech.terminal.app_name.items=Item Guides +gregtech.terminal.app_name.machines=Machine Guides +gregtech.terminal.app_name.multiblocks=Multiblock Guides +gregtech.terminal.app_name.tutorials=Tutorials +gregtech.terminal.app_name.theme_settings=Theme Settings +gregtech.terminal.app_name.guide_editor=Guide Editor +gregtech.terminal.app_name.recipe_chart=Recipe Chart + +texture.modify_gui_texture.missing=Missing Texture +texture.url_texture.fail=Load Failed + +terminal.os.shutdown_confirm=Confirm the shutdown? (Press ESC again to see ok) + +terminal.menu.close=Close +terminal.menu.minimize=Minimize +terminal.menu.maximize=Maximize + +terminal.component.new_page=New Page +terminal.component.page_name=Page Name +terminal.component.load_file=Load File +terminal.component.load_file.error=An error occurred while loading the file. +terminal.component.save_file=Save File +terminal.component.save_file.error=An error occurred while saving the file. +terminal.component.confirm=Are you sure? +terminal.component.error=ERROR +terminal.component.warning=WARNING +terminal.component.searching=searching + +terminal.dialog.error_path=error file path: +terminal.dialog.no_file_selected=No file selected. +terminal.dialog.folder=Open Folder + +terminal.guide_editor.up=Up +terminal.guide_editor.down=Down +terminal.guide_editor.remove=Remove +terminal.guide_editor.add_stream=Add to stream +terminal.guide_editor.add_fixed=Add to fixed +terminal.guide_editor.update=Update +terminal.guide_editor.add_slot=Add Slot +terminal.guide_editor.default=Default Value +terminal.guide_editor.page_config=Page Config +terminal.guide_editor.widgets_box=Widgets Box +terminal.guide_editor.widget_config=Widget Config + +terminal.theme_settings.color=Theme Color Settings +terminal.theme_settings.wallpaper=Wallpaper Settings +terminal.theme_settings.select=Select +terminal.theme_settings.image=Image File + +terminal.recipe_chart.limit=Page limit. +terminal.recipe_chart.delete=Delete Page +terminal.recipe_chart.add_slot=Add Root Slot +terminal.recipe_chart.demand=Demand +terminal.recipe_chart.calculator=Calculator +terminal.recipe_chart.drag=Drag ingredients here. +terminal.recipe_chart.visible=Visible +terminal.recipe_chart.jei=JEI Focus +terminal.recipe_chart.tier=Tier: +terminal.recipe_chart.ratio=Ratio diff --git a/src/main/resources/assets/gregtech/lang/ru_ru.lang b/src/main/resources/assets/gregtech/lang/ru_ru.lang index e1dcfcf7029..bc41b0277b3 100644 --- a/src/main/resources/assets/gregtech/lang/ru_ru.lang +++ b/src/main/resources/assets/gregtech/lang/ru_ru.lang @@ -1607,7 +1607,7 @@ recipemap.ore_washer.name=Рудопромывщик recipemap.thermal_centrifuge.name=Термальная центрифуга recipemap.extractor.name=Экстрактор recipemap.recycler.name=Переработчик -recipemap.electic_furnace.name=Печь +recipemap.electric_furnace.name=Печь recipemap.scanner.name=Сканер recipemap.rockbreaker.name=Разрушитель породы recipemap.byproductlist.name=Список побочных продуктов руды diff --git a/src/main/resources/assets/gregtech/lang/zh_cn.lang b/src/main/resources/assets/gregtech/lang/zh_cn.lang index 348d82f4b35..57581ab6e6a 100644 --- a/src/main/resources/assets/gregtech/lang/zh_cn.lang +++ b/src/main/resources/assets/gregtech/lang/zh_cn.lang @@ -1392,7 +1392,7 @@ recipemap.ore_washer.name=洗矿场 recipemap.thermal_centrifuge.name=热力离心机 recipemap.extractor.name=提取机 recipemap.recycler.name=回收机 -recipemap.electic_furnace.name=炉 +recipemap.electric_furnace.name=炉 recipemap.scanner.name=扫描仪 recipemap.rockbreaker.name=碎石机 recipemap.byproductlist.name=矿物副产列表 @@ -3405,4 +3405,156 @@ info.infinite_energy.umv=Voltage: UMV info.infinite_energy.uxv=Voltage: UXV info.infinite_energy.max=Voltage: MAX gregtech.universal.clear_nbt_recipe.tooltip=§cThis will destroy all contents! -gregtech.multiblock.primitive_water_pump.description=The Primitive Water Pump is a pre-Steam Era multiblock that collects water once per second, depending on the Biome it is in. It can use a Pump, ULV, or LV Output Hatch, increasing the amount of water per tier. Follows the formula: Biome Coefficient * Hatch Multiplier. +gregtech.multiblock.primitive_water_pump.description=The Primitive Water Pump is a pre-Steam Era multiblock that collects water once per second, depending on the Biome it is in. It can use a Pump, ULV, or LV Output Hatch, increasing the amount of water per tier. Follows the formula: Biome Coefficient * Hatch Multiplier.gregtech.machine.steam_grinder.name=Steam Grinder +gregtech.machine.steam_grinder.tooltip=Macerates up to 8 items per craft. Takes 1.5x base duration to process, not affected by number of items. Requires §eSteam Hatches and Buses +gregtech.multiblock.steam_grinder.description=A Multiblock Macerator at the Steam Age. Requires at least 14 Bronze Casings to form. Cannot use normal Input/Output busses, nor Fluid Hatches other than the Steam Hatch. +gregtech.multiblock.steam.low_steam=Not enough Steam to run! +gregtech.multiblock.steam.steam_stored=Steam: %s / %s mb +gregtech.machine.steam_hatch.name=Steam Hatch +gregtech.machine.steam.steam_hatch.tooltip=Accepted Fluid: §eSteam +gregtech.machine.steam_import_bus.name=Input Bus (Steam) +gregtech.machine.steam_export_bus.name=Output Bus (Steam) +gregtech.machine.steam_bus.tooltip=Does not work with non-steam multiblocks +gregtech.machine.steam_oven.name=Steam Oven +gregtech.machine.steam_oven.tooltip=Smelts up to 8 items per craft. Takes 1.5x base duration to process, not affected by number of items. Requires §eSteam Hatches and Buses +gregtech.multiblock.steam_oven.description=A Multi Smelter at the Steam Age. Requires at least 6 Bronze Casings to form. Cannot use normal Input/Output busses, nor Fluid Hatches other than the Steam Hatch. Steam Hatch must be on the bottom layer, no more than one. +metaitem.credit.neutronium.name=Neutronium Credit +metaitem.credit.neutronium.tooltip=262144 Credits +metaitem.shape.extruder.gear_small.name=Extruder Shape (Small Gear) +metaitem.shape.extruder.gear_small.tooltip=Extruder Shape for making Small Gears +metaitem.shape.extruder.foil.name=Extruder Shape (Foil) +metaitem.shape.extruder.foil.tooltip=Extruder Shape for making Foils from Non-Metals +metaitem.shape.extruder.rod_long.name=Extruder Shape (Long Rod) +metaitem.shape.extruder.rod_long.tooltip=Extruder Shape for making Long Rods +metaitem.max.battery.tooltip=Fill this to win minecraft +metaitem.voltage_coil.ulv.name=Ultra Low Voltage Coil +metaitem.voltage_coil.ulv.tooltip=Primitive Coil +metaitem.voltage_coil.lv.name=Low Voltage Coil +metaitem.voltage_coil.lv.tooltip=Basic Coil +metaitem.voltage_coil.mv.name=Medium Voltage Coil +metaitem.voltage_coil.mv.tooltip=Good Coil +metaitem.voltage_coil.hv.name=High Voltage Coil +metaitem.voltage_coil.hv.tooltip=Advanced Coil +metaitem.voltage_coil.ev.name=Extreme Voltage Coil +metaitem.voltage_coil.ev.tooltip=Extreme Coil +metaitem.voltage_coil.iv.name=Insane Voltage Coil +metaitem.voltage_coil.iv.tooltip=Elite Coil +metaitem.voltage_coil.luv.name=Ludicrous Voltage Coil +metaitem.voltage_coil.luv.tooltip=Master Coil +metaitem.voltage_coil.zpm.name=ZPM Voltage Coil +metaitem.voltage_coil.zpm.tooltip=Ultimate Coil +metaitem.voltage_coil.uv.name=Ultimate Voltage Coil +metaitem.voltage_coil.uv.tooltip=Superconductor Coil +metaitem.voltage_coil.uhv.name=Highly Ultimate Voltage Coil +metaitem.voltage_coil.uhv.tooltip=Infinite Coil +metaitem.voltage_coil.uev.name=Extremely Ultimate Voltage Coil +metaitem.voltage_coil.uev.tooltip=Ultra Coil +metaitem.voltage_coil.uiv.name=Insanely Ultimate Voltage Coil +metaitem.voltage_coil.uiv.tooltip=Insane Coil +metaitem.voltage_coil.umv.name=Mega Ultimate Voltage Coil +metaitem.voltage_coil.umv.tooltip=UMV Coil +metaitem.voltage_coil.uxv.name=Extended Mega Ultimate Voltage Coil +metaitem.voltage_coil.uxv.tooltip=UXV Coil +metaitem.voltage_coil.max.name=Maximum Voltage Coil +metaitem.voltage_coil.max.tooltip=Maximum Coil +cover.conveyor.distribution.enabled=Item distribution mode for item pipes/n§bInsert First +cover.conveyor.distribution.disabled=Item distribution mode for item pipes/n§bRound Robin +cover.conveyor.blocks_input.enabled=If enabled, items will not be inserted when cover is set to pull items from the inventory into pipe./n§aEnabled +cover.conveyor.blocks_input.disabled=If enabled, items will not be inserted when cover is set to pull items from the inventory into pipe./n§cDisabled +item.material.oreprefix.pipeTinyFluid=Tiny %s Fluid Pipe +item.material.oreprefix.pipeSmallFluid=Small %s Fluid Pipe +item.material.oreprefix.pipeNormalFluid=Normal %s Fluid Pipe +item.material.oreprefix.pipeLargeFluid=Large %s Fluid Pipe +item.material.oreprefix.pipeHugeFluid=Huge %s Fluid Pipe +item.material.oreprefix.pipeTinyItem=Tiny %s Item Pipe +item.material.oreprefix.pipeSmallItem=Small %s Item Pipe +item.material.oreprefix.pipeNormalItem=Normal %s Item Pipe +item.material.oreprefix.pipeLargeItem=Large %s Item Pipe +item.material.oreprefix.pipeHugeItem=Huge %s Item Pipe +item.material.oreprefix.pipeTinyRestrictive=Tiny Restrictive %s Item Pipe +item.material.oreprefix.pipeSmallRestrictive=Small Restrictive %s Item Pipe +item.material.oreprefix.pipeNormalRestrictive=Normal Restrictive %s Item Pipe +item.material.oreprefix.pipeLargeRestrictive=Large Restrictive %s Item Pipe +item.material.oreprefix.pipeHugeRestrictive=Huge Restrictive %s Item Pipe +material.diesel=Diesel +material.distilled_water=Distilled Water +material.sodium_potassium=Sodium Potassium +material.samarium_magnetic=Magnetic Samarium +material.monochloramine=Monochloramine +material.dimethylhydrazine=1,1-Dimethylhydrazine +material.silicone_rubber=Silicone Rubber +material.copper_sulfate_water_solution=Copper Sulfate Water Solution +material.potin=Potin +material.raw_gasoline=Raw Gasoline +material.gasoline=Gasoline +material.nitrous_oxide=Nitrous Oxide +material.octane=Octane +material.ethyl_tertbutyl_ether=Ethyl Tert-Butyl Ether +material.gasoline_premium=High Octane Gasoline +material.nitrobenzene=Nitrobenzene +material.coal_gas=Coal Gas +material.coal_tar=Coal Tar +material.ethylbenzene=Ethylbenzene +material.naphthalene=Naphthalene +item.silicone_rubber.dustTiny=Tiny Pile of Silicone Rubber Pulp +item.silicone_rubber.dustSmall=Small Pile of Silicone Rubber Pulp +item.silicone_rubber.dust=Silicone Rubber Pulp +item.silicone_rubber.nugget=Silicone Rubber Chip +item.silicone_rubber.ingot=Silicone Rubber Bar +item.silicone_rubber.plate=Silicone Rubber Sheet +item.silicone_rubber.foil=Thin Silicone Rubber Sheet +recipemap.mass_fabricator.name=Mass Fabricator +gregtech.machine.mass_fabricator.tooltip=UUM +gregtech.machine.mass_fabricator.lv.name=Basic Mass Fabricator +gregtech.machine.mass_fabricator.mv.name=Advanced Mass Fabricator +gregtech.machine.mass_fabricator.hv.name=Advanced Mass Fabricator II +gregtech.machine.mass_fabricator.ev.name=Advanced Mass Fabricator III +gregtech.machine.mass_fabricator.iv.name=Elite Mass Fabricator +gregtech.machine.mass_fabricator.luv.name=Elite Mass Fabricator II +gregtech.machine.mass_fabricator.zpm.name=Elite Mass Fabricator III +gregtech.machine.mass_fabricator.uv.name=Elite Mass Fabricator IV +gregtech.machine.mass_fabricator.uhv.name=High-Tech Mass Fabricator +gregtech.machine.mass_fabricator.uev.name=High-Tech Mass Fabricator II +gregtech.machine.mass_fabricator.uiv.name=High-Tech Mass Fabricator III +gregtech.machine.mass_fabricator.umv.name=High-Tech Mass Fabricator IV +gregtech.machine.mass_fabricator.uxv.name=Ultimate Mass Fabricator +gregtech.machine.replicator.tooltip=Producing the Purest of Elements +gregtech.machine.replicator.lv.name=Basic Replicator +gregtech.machine.replicator.mv.name=Advanced Replicator +gregtech.machine.replicator.hv.name=Advanced Replicator II +gregtech.machine.replicator.ev.name=Advanced Replicator III +gregtech.machine.replicator.iv.name=Elite Replicator +gregtech.machine.replicator.luv.name=Elite Replicator II +gregtech.machine.replicator.zpm.name=Elite Replicator III +gregtech.machine.replicator.uv.name=Elite Replicator IV +gregtech.machine.replicator.uhv.name=High-Tech Replicator +gregtech.machine.replicator.uev.name=High-Tech Replicator II +gregtech.machine.replicator.uiv.name=High-Tech Replicator III +gregtech.machine.replicator.umv.name=High-Tech Replicator IV +gregtech.machine.replicator.uxv.name=Ultimate Replicator +gregtech.machine.scanner.tooltip=Scans Materials and other things +gregtech.machine.scanner.lv.name=Basic Scanner +gregtech.machine.scanner.mv.name=Advanced Scanner +gregtech.machine.scanner.hv.name=Advanced Scanner II +gregtech.machine.scanner.ev.name=Advanced Scanner III +gregtech.machine.scanner.iv.name=Elite Scanner +gregtech.machine.scanner.luv.name=Elite Scanner II +gregtech.machine.scanner.zpm.name=Elite Scanner III +gregtech.machine.scanner.uv.name=Elite Scanner IV +gregtech.machine.scanner.uhv.name=High-Tech Scanner +gregtech.machine.scanner.uev.name=High-Tech Scanner II +gregtech.machine.scanner.uiv.name=High-Tech Scanner III +gregtech.machine.scanner.umv.name=High-Tech Scanner IV +gregtech.machine.scanner.uxv.name=Ultimate Scanner +gregtech.machine.transformer.ulv.name=Ultra Low Voltage Transformer +gregtech.universal.disabled=Sharing between Multiblocks: §4Disabled +gregtech.universal.enabled=Sharing between Multiblocks: §aEnabled +gregtech.item_pipe.rate_items=§9Transfer Rate: %d items/s +gregtech.item_pipe.rate_stacks=§9Transfer Rate: %d stacks/s +gregtech.item_pipe.priority=§9Priority: %d +gregtech.cover.energy_detector.message_electricity_storage_normal=Monitoring Normal Electricity Storage +gregtech.cover.energy_detector.message_electricity_storage_inverted=Monitoring Inverted Electricity Storage +gregtech.cover.fluid_detector.message_fluid_storage_normal=Monitoring Normal Fluid Storage +gregtech.cover.fluid_detector.message_fluid_storage_inverted=Monitoring Inverted Fluid Storage +gregtech.cover.item_detector.message_item_storage_normal=Monitoring Normal Item Storage +gregtech.cover.item_detector.message_item_storage_inverted=Monitoring Inverted Item Storage diff --git a/src/main/resources/assets/gregtech/models/item/material_sets/diamond/plate_double.json b/src/main/resources/assets/gregtech/models/item/material_sets/diamond/plate_double.json new file mode 100644 index 00000000000..50b3ca6ace8 --- /dev/null +++ b/src/main/resources/assets/gregtech/models/item/material_sets/diamond/plate_double.json @@ -0,0 +1,7 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "gregtech:items/material_sets/diamond/plate_double", + "layer1": "gregtech:items/material_sets/diamond/plate_double_overlay" + } +} diff --git a/src/main/resources/assets/gregtech/models/item/material_sets/emerald/plate_double.json b/src/main/resources/assets/gregtech/models/item/material_sets/emerald/plate_double.json new file mode 100644 index 00000000000..01923dbf600 --- /dev/null +++ b/src/main/resources/assets/gregtech/models/item/material_sets/emerald/plate_double.json @@ -0,0 +1,7 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "gregtech:items/material_sets/emerald/plate_double", + "layer1": "gregtech:items/material_sets/emerald/plate_double_overlay" + } +} diff --git a/src/main/resources/assets/gregtech/models/item/material_sets/gem_horizontal/plate_double.json b/src/main/resources/assets/gregtech/models/item/material_sets/gem_horizontal/plate_double.json new file mode 100644 index 00000000000..1cf657165c5 --- /dev/null +++ b/src/main/resources/assets/gregtech/models/item/material_sets/gem_horizontal/plate_double.json @@ -0,0 +1,7 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "gregtech:items/material_sets/gem_horizontal/plate_double", + "layer1": "gregtech:items/material_sets/gem_horizontal/plate_double_overlay" + } +} diff --git a/src/main/resources/assets/gregtech/models/item/material_sets/gem_vertical/plate_double.json b/src/main/resources/assets/gregtech/models/item/material_sets/gem_vertical/plate_double.json new file mode 100644 index 00000000000..9932f1d3b91 --- /dev/null +++ b/src/main/resources/assets/gregtech/models/item/material_sets/gem_vertical/plate_double.json @@ -0,0 +1,7 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "gregtech:items/material_sets/gem_vertical/plate_double", + "layer1": "gregtech:items/material_sets/gem_vertical/plate_double_overlay" + } +} diff --git a/src/main/resources/assets/gregtech/models/item/material_sets/lapis/plate_double.json b/src/main/resources/assets/gregtech/models/item/material_sets/lapis/plate_double.json new file mode 100644 index 00000000000..c19a2b86715 --- /dev/null +++ b/src/main/resources/assets/gregtech/models/item/material_sets/lapis/plate_double.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "gregtech:items/material_sets/lapis/plate_double" + } +} diff --git a/src/main/resources/assets/gregtech/models/item/material_sets/netherstar/plate_double.json b/src/main/resources/assets/gregtech/models/item/material_sets/netherstar/plate_double.json new file mode 100644 index 00000000000..d852fc785d4 --- /dev/null +++ b/src/main/resources/assets/gregtech/models/item/material_sets/netherstar/plate_double.json @@ -0,0 +1,7 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "gregtech:items/material_sets/netherstar/plate_double", + "layer1": "gregtech:items/material_sets/netherstar/plate_double_overlay" + } +} diff --git a/src/main/resources/assets/gregtech/models/item/material_sets/opal/plate_double.json b/src/main/resources/assets/gregtech/models/item/material_sets/opal/plate_double.json new file mode 100644 index 00000000000..09d09a730ac --- /dev/null +++ b/src/main/resources/assets/gregtech/models/item/material_sets/opal/plate_double.json @@ -0,0 +1,7 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "gregtech:items/material_sets/opal/plate_double", + "layer1": "gregtech:items/material_sets/opal/plate_double_overlay" + } +} diff --git a/src/main/resources/assets/gregtech/models/item/material_sets/ruby/plate_double.json b/src/main/resources/assets/gregtech/models/item/material_sets/ruby/plate_double.json new file mode 100644 index 00000000000..a2abf4705f4 --- /dev/null +++ b/src/main/resources/assets/gregtech/models/item/material_sets/ruby/plate_double.json @@ -0,0 +1,7 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "gregtech:items/material_sets/ruby/plate_double", + "layer1": "gregtech:items/material_sets/ruby/plate_double_overlay" + } +} diff --git a/src/main/resources/assets/gregtech/models/item/metaitems/battery.ev.vanadium/1.json b/src/main/resources/assets/gregtech/models/item/metaitems/battery.ev.vanadium/1.json new file mode 100644 index 00000000000..0db0cecb422 --- /dev/null +++ b/src/main/resources/assets/gregtech/models/item/metaitems/battery.ev.vanadium/1.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "gregtech:items/metaitems/battery.ev.vanadium/1" + } +} diff --git a/src/main/resources/assets/gregtech/models/item/metaitems/battery.ev.vanadium/2.json b/src/main/resources/assets/gregtech/models/item/metaitems/battery.ev.vanadium/2.json new file mode 100644 index 00000000000..02eeb3bec2e --- /dev/null +++ b/src/main/resources/assets/gregtech/models/item/metaitems/battery.ev.vanadium/2.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "gregtech:items/metaitems/battery.ev.vanadium/2" + } +} diff --git a/src/main/resources/assets/gregtech/models/item/metaitems/battery.ev.vanadium/3.json b/src/main/resources/assets/gregtech/models/item/metaitems/battery.ev.vanadium/3.json new file mode 100644 index 00000000000..84fb055a847 --- /dev/null +++ b/src/main/resources/assets/gregtech/models/item/metaitems/battery.ev.vanadium/3.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "gregtech:items/metaitems/battery.ev.vanadium/3" + } +} diff --git a/src/main/resources/assets/gregtech/models/item/metaitems/battery.ev.vanadium/4.json b/src/main/resources/assets/gregtech/models/item/metaitems/battery.ev.vanadium/4.json new file mode 100644 index 00000000000..f10577aa0ec --- /dev/null +++ b/src/main/resources/assets/gregtech/models/item/metaitems/battery.ev.vanadium/4.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "gregtech:items/metaitems/battery.ev.vanadium/4" + } +} diff --git a/src/main/resources/assets/gregtech/models/item/metaitems/battery.ev.vanadium/5.json b/src/main/resources/assets/gregtech/models/item/metaitems/battery.ev.vanadium/5.json new file mode 100644 index 00000000000..9a4a54b9b18 --- /dev/null +++ b/src/main/resources/assets/gregtech/models/item/metaitems/battery.ev.vanadium/5.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "gregtech:items/metaitems/battery.ev.vanadium/5" + } +} diff --git a/src/main/resources/assets/gregtech/models/item/metaitems/battery.ev.vanadium/6.json b/src/main/resources/assets/gregtech/models/item/metaitems/battery.ev.vanadium/6.json new file mode 100644 index 00000000000..24595da723d --- /dev/null +++ b/src/main/resources/assets/gregtech/models/item/metaitems/battery.ev.vanadium/6.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "gregtech:items/metaitems/battery.ev.vanadium/6" + } +} diff --git a/src/main/resources/assets/gregtech/models/item/metaitems/battery.ev.vanadium/7.json b/src/main/resources/assets/gregtech/models/item/metaitems/battery.ev.vanadium/7.json new file mode 100644 index 00000000000..369db3c3f7a --- /dev/null +++ b/src/main/resources/assets/gregtech/models/item/metaitems/battery.ev.vanadium/7.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "gregtech:items/metaitems/battery.ev.vanadium/7" + } +} diff --git a/src/main/resources/assets/gregtech/models/item/metaitems/battery.ev.vanadium/8.json b/src/main/resources/assets/gregtech/models/item/metaitems/battery.ev.vanadium/8.json new file mode 100644 index 00000000000..4eb00d5dace --- /dev/null +++ b/src/main/resources/assets/gregtech/models/item/metaitems/battery.ev.vanadium/8.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "gregtech:items/metaitems/battery.ev.vanadium/8" + } +} diff --git a/src/main/resources/assets/gregtech/models/item/metaitems/battery.hull.ev.json b/src/main/resources/assets/gregtech/models/item/metaitems/battery.hull.ev.json new file mode 100644 index 00000000000..7bec3aab574 --- /dev/null +++ b/src/main/resources/assets/gregtech/models/item/metaitems/battery.hull.ev.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "gregtech:items/metaitems/battery.hull.ev" + } +} diff --git a/src/main/resources/assets/gregtech/models/item/metaitems/battery.hull.iv.json b/src/main/resources/assets/gregtech/models/item/metaitems/battery.hull.iv.json new file mode 100644 index 00000000000..a0b009eae9a --- /dev/null +++ b/src/main/resources/assets/gregtech/models/item/metaitems/battery.hull.iv.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "gregtech:items/metaitems/battery.hull.iv" + } +} diff --git a/src/main/resources/assets/gregtech/models/item/metaitems/battery.hull.luv.json b/src/main/resources/assets/gregtech/models/item/metaitems/battery.hull.luv.json new file mode 100644 index 00000000000..624133f57d8 --- /dev/null +++ b/src/main/resources/assets/gregtech/models/item/metaitems/battery.hull.luv.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "gregtech:items/metaitems/battery.hull.luv" + } +} diff --git a/src/main/resources/assets/gregtech/models/item/metaitems/battery.hull.uv.json b/src/main/resources/assets/gregtech/models/item/metaitems/battery.hull.uv.json new file mode 100644 index 00000000000..f242c2a53fe --- /dev/null +++ b/src/main/resources/assets/gregtech/models/item/metaitems/battery.hull.uv.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "gregtech:items/metaitems/battery.hull.uv" + } +} diff --git a/src/main/resources/assets/gregtech/models/item/metaitems/battery.hull.zpm.json b/src/main/resources/assets/gregtech/models/item/metaitems/battery.hull.zpm.json new file mode 100644 index 00000000000..89cd081ea2a --- /dev/null +++ b/src/main/resources/assets/gregtech/models/item/metaitems/battery.hull.zpm.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "gregtech:items/metaitems/battery.hull.zpm" + } +} diff --git a/src/main/resources/assets/gregtech/models/item/metaitems/battery.iv.vanadium/1.json b/src/main/resources/assets/gregtech/models/item/metaitems/battery.iv.vanadium/1.json new file mode 100644 index 00000000000..7110f406c97 --- /dev/null +++ b/src/main/resources/assets/gregtech/models/item/metaitems/battery.iv.vanadium/1.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "gregtech:items/metaitems/battery.iv.vanadium/1" + } +} diff --git a/src/main/resources/assets/gregtech/models/item/metaitems/battery.iv.vanadium/2.json b/src/main/resources/assets/gregtech/models/item/metaitems/battery.iv.vanadium/2.json new file mode 100644 index 00000000000..c6f8685bd1c --- /dev/null +++ b/src/main/resources/assets/gregtech/models/item/metaitems/battery.iv.vanadium/2.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "gregtech:items/metaitems/battery.iv.vanadium/2" + } +} diff --git a/src/main/resources/assets/gregtech/models/item/metaitems/battery.iv.vanadium/3.json b/src/main/resources/assets/gregtech/models/item/metaitems/battery.iv.vanadium/3.json new file mode 100644 index 00000000000..be5f4dc40d2 --- /dev/null +++ b/src/main/resources/assets/gregtech/models/item/metaitems/battery.iv.vanadium/3.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "gregtech:items/metaitems/battery.iv.vanadium/3" + } +} diff --git a/src/main/resources/assets/gregtech/models/item/metaitems/battery.iv.vanadium/4.json b/src/main/resources/assets/gregtech/models/item/metaitems/battery.iv.vanadium/4.json new file mode 100644 index 00000000000..8625d8a1941 --- /dev/null +++ b/src/main/resources/assets/gregtech/models/item/metaitems/battery.iv.vanadium/4.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "gregtech:items/metaitems/battery.iv.vanadium/4" + } +} diff --git a/src/main/resources/assets/gregtech/models/item/metaitems/battery.iv.vanadium/5.json b/src/main/resources/assets/gregtech/models/item/metaitems/battery.iv.vanadium/5.json new file mode 100644 index 00000000000..ce989c9ea91 --- /dev/null +++ b/src/main/resources/assets/gregtech/models/item/metaitems/battery.iv.vanadium/5.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "gregtech:items/metaitems/battery.iv.vanadium/5" + } +} diff --git a/src/main/resources/assets/gregtech/models/item/metaitems/battery.iv.vanadium/6.json b/src/main/resources/assets/gregtech/models/item/metaitems/battery.iv.vanadium/6.json new file mode 100644 index 00000000000..1bfbed5fa8c --- /dev/null +++ b/src/main/resources/assets/gregtech/models/item/metaitems/battery.iv.vanadium/6.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "gregtech:items/metaitems/battery.iv.vanadium/6" + } +} diff --git a/src/main/resources/assets/gregtech/models/item/metaitems/battery.iv.vanadium/7.json b/src/main/resources/assets/gregtech/models/item/metaitems/battery.iv.vanadium/7.json new file mode 100644 index 00000000000..d17fc92fb76 --- /dev/null +++ b/src/main/resources/assets/gregtech/models/item/metaitems/battery.iv.vanadium/7.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "gregtech:items/metaitems/battery.iv.vanadium/7" + } +} diff --git a/src/main/resources/assets/gregtech/models/item/metaitems/battery.iv.vanadium/8.json b/src/main/resources/assets/gregtech/models/item/metaitems/battery.iv.vanadium/8.json new file mode 100644 index 00000000000..b57ca45ad7e --- /dev/null +++ b/src/main/resources/assets/gregtech/models/item/metaitems/battery.iv.vanadium/8.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "gregtech:items/metaitems/battery.iv.vanadium/8" + } +} diff --git a/src/main/resources/assets/gregtech/models/item/metaitems/battery.luv.vanadium/1.json b/src/main/resources/assets/gregtech/models/item/metaitems/battery.luv.vanadium/1.json new file mode 100644 index 00000000000..00ea04f36c8 --- /dev/null +++ b/src/main/resources/assets/gregtech/models/item/metaitems/battery.luv.vanadium/1.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "gregtech:items/metaitems/battery.luv.vanadium/1" + } +} diff --git a/src/main/resources/assets/gregtech/models/item/metaitems/battery.luv.vanadium/2.json b/src/main/resources/assets/gregtech/models/item/metaitems/battery.luv.vanadium/2.json new file mode 100644 index 00000000000..7d75b42f155 --- /dev/null +++ b/src/main/resources/assets/gregtech/models/item/metaitems/battery.luv.vanadium/2.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "gregtech:items/metaitems/battery.luv.vanadium/2" + } +} diff --git a/src/main/resources/assets/gregtech/models/item/metaitems/battery.luv.vanadium/3.json b/src/main/resources/assets/gregtech/models/item/metaitems/battery.luv.vanadium/3.json new file mode 100644 index 00000000000..8f870a9e7ea --- /dev/null +++ b/src/main/resources/assets/gregtech/models/item/metaitems/battery.luv.vanadium/3.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "gregtech:items/metaitems/battery.luv.vanadium/3" + } +} diff --git a/src/main/resources/assets/gregtech/models/item/metaitems/battery.luv.vanadium/4.json b/src/main/resources/assets/gregtech/models/item/metaitems/battery.luv.vanadium/4.json new file mode 100644 index 00000000000..5327e378763 --- /dev/null +++ b/src/main/resources/assets/gregtech/models/item/metaitems/battery.luv.vanadium/4.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "gregtech:items/metaitems/battery.luv.vanadium/4" + } +} diff --git a/src/main/resources/assets/gregtech/models/item/metaitems/battery.luv.vanadium/5.json b/src/main/resources/assets/gregtech/models/item/metaitems/battery.luv.vanadium/5.json new file mode 100644 index 00000000000..8214427664f --- /dev/null +++ b/src/main/resources/assets/gregtech/models/item/metaitems/battery.luv.vanadium/5.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "gregtech:items/metaitems/battery.luv.vanadium/5" + } +} diff --git a/src/main/resources/assets/gregtech/models/item/metaitems/battery.luv.vanadium/6.json b/src/main/resources/assets/gregtech/models/item/metaitems/battery.luv.vanadium/6.json new file mode 100644 index 00000000000..127a6ff5675 --- /dev/null +++ b/src/main/resources/assets/gregtech/models/item/metaitems/battery.luv.vanadium/6.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "gregtech:items/metaitems/battery.luv.vanadium/6" + } +} diff --git a/src/main/resources/assets/gregtech/models/item/metaitems/battery.luv.vanadium/7.json b/src/main/resources/assets/gregtech/models/item/metaitems/battery.luv.vanadium/7.json new file mode 100644 index 00000000000..5aeaca50b20 --- /dev/null +++ b/src/main/resources/assets/gregtech/models/item/metaitems/battery.luv.vanadium/7.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "gregtech:items/metaitems/battery.luv.vanadium/7" + } +} diff --git a/src/main/resources/assets/gregtech/models/item/metaitems/battery.luv.vanadium/8.json b/src/main/resources/assets/gregtech/models/item/metaitems/battery.luv.vanadium/8.json new file mode 100644 index 00000000000..ae8d36b9e3c --- /dev/null +++ b/src/main/resources/assets/gregtech/models/item/metaitems/battery.luv.vanadium/8.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "gregtech:items/metaitems/battery.luv.vanadium/8" + } +} diff --git a/src/main/resources/assets/gregtech/models/item/metaitems/battery.su.hv.mercury.json b/src/main/resources/assets/gregtech/models/item/metaitems/battery.su.hv.mercury.json deleted file mode 100644 index f0dc2131601..00000000000 --- a/src/main/resources/assets/gregtech/models/item/metaitems/battery.su.hv.mercury.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "item/generated", - "textures": { - "layer0": "gregtech:items/metaitems/battery.su.hv.mercury" - } -} diff --git a/src/main/resources/assets/gregtech/models/item/metaitems/battery.su.hv.sulfuricacid.json b/src/main/resources/assets/gregtech/models/item/metaitems/battery.su.hv.sulfuricacid.json deleted file mode 100644 index a87b35a6419..00000000000 --- a/src/main/resources/assets/gregtech/models/item/metaitems/battery.su.hv.sulfuricacid.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "item/generated", - "textures": { - "layer0": "gregtech:items/metaitems/battery.su.hv.sulfuricacid" - } -} diff --git a/src/main/resources/assets/gregtech/models/item/metaitems/battery.su.lv.mercury.json b/src/main/resources/assets/gregtech/models/item/metaitems/battery.su.lv.mercury.json deleted file mode 100644 index d1fdd7aa8f7..00000000000 --- a/src/main/resources/assets/gregtech/models/item/metaitems/battery.su.lv.mercury.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "item/generated", - "textures": { - "layer0": "gregtech:items/metaitems/battery.su.lv.mercury" - } -} diff --git a/src/main/resources/assets/gregtech/models/item/metaitems/battery.su.lv.sulfuricacid.json b/src/main/resources/assets/gregtech/models/item/metaitems/battery.su.lv.sulfuricacid.json deleted file mode 100644 index 6d772c2fcc4..00000000000 --- a/src/main/resources/assets/gregtech/models/item/metaitems/battery.su.lv.sulfuricacid.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "item/generated", - "textures": { - "layer0": "gregtech:items/metaitems/battery.su.lv.sulfuricacid" - } -} diff --git a/src/main/resources/assets/gregtech/models/item/metaitems/battery.su.mv.mercury.json b/src/main/resources/assets/gregtech/models/item/metaitems/battery.su.mv.mercury.json deleted file mode 100644 index 677fac00fc8..00000000000 --- a/src/main/resources/assets/gregtech/models/item/metaitems/battery.su.mv.mercury.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "item/generated", - "textures": { - "layer0": "gregtech:items/metaitems/battery.su.mv.mercury" - } -} diff --git a/src/main/resources/assets/gregtech/models/item/metaitems/battery.su.mv.sulfuricacid.json b/src/main/resources/assets/gregtech/models/item/metaitems/battery.su.mv.sulfuricacid.json deleted file mode 100644 index 332edd98478..00000000000 --- a/src/main/resources/assets/gregtech/models/item/metaitems/battery.su.mv.sulfuricacid.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "item/generated", - "textures": { - "layer0": "gregtech:items/metaitems/battery.su.mv.sulfuricacid" - } -} diff --git a/src/main/resources/assets/gregtech/models/item/metaitems/battery.uv.naquadria/1.json b/src/main/resources/assets/gregtech/models/item/metaitems/battery.uv.naquadria/1.json new file mode 100644 index 00000000000..0c28ba4ba76 --- /dev/null +++ b/src/main/resources/assets/gregtech/models/item/metaitems/battery.uv.naquadria/1.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "gregtech:items/metaitems/battery.uv.naquadria/1" + } +} diff --git a/src/main/resources/assets/gregtech/models/item/metaitems/battery.uv.naquadria/2.json b/src/main/resources/assets/gregtech/models/item/metaitems/battery.uv.naquadria/2.json new file mode 100644 index 00000000000..07754c9f7b0 --- /dev/null +++ b/src/main/resources/assets/gregtech/models/item/metaitems/battery.uv.naquadria/2.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "gregtech:items/metaitems/battery.uv.naquadria/2" + } +} diff --git a/src/main/resources/assets/gregtech/models/item/metaitems/battery.uv.naquadria/3.json b/src/main/resources/assets/gregtech/models/item/metaitems/battery.uv.naquadria/3.json new file mode 100644 index 00000000000..419aa4d9373 --- /dev/null +++ b/src/main/resources/assets/gregtech/models/item/metaitems/battery.uv.naquadria/3.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "gregtech:items/metaitems/battery.uv.naquadria/3" + } +} diff --git a/src/main/resources/assets/gregtech/models/item/metaitems/battery.uv.naquadria/4.json b/src/main/resources/assets/gregtech/models/item/metaitems/battery.uv.naquadria/4.json new file mode 100644 index 00000000000..2ec280775a1 --- /dev/null +++ b/src/main/resources/assets/gregtech/models/item/metaitems/battery.uv.naquadria/4.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "gregtech:items/metaitems/battery.uv.naquadria/4" + } +} diff --git a/src/main/resources/assets/gregtech/models/item/metaitems/battery.uv.naquadria/5.json b/src/main/resources/assets/gregtech/models/item/metaitems/battery.uv.naquadria/5.json new file mode 100644 index 00000000000..e4cae05ef32 --- /dev/null +++ b/src/main/resources/assets/gregtech/models/item/metaitems/battery.uv.naquadria/5.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "gregtech:items/metaitems/battery.uv.naquadria/5" + } +} diff --git a/src/main/resources/assets/gregtech/models/item/metaitems/battery.uv.naquadria/6.json b/src/main/resources/assets/gregtech/models/item/metaitems/battery.uv.naquadria/6.json new file mode 100644 index 00000000000..44be600fa2a --- /dev/null +++ b/src/main/resources/assets/gregtech/models/item/metaitems/battery.uv.naquadria/6.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "gregtech:items/metaitems/battery.uv.naquadria/6" + } +} diff --git a/src/main/resources/assets/gregtech/models/item/metaitems/battery.uv.naquadria/7.json b/src/main/resources/assets/gregtech/models/item/metaitems/battery.uv.naquadria/7.json new file mode 100644 index 00000000000..6cc6d0d65f2 --- /dev/null +++ b/src/main/resources/assets/gregtech/models/item/metaitems/battery.uv.naquadria/7.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "gregtech:items/metaitems/battery.uv.naquadria/7" + } +} diff --git a/src/main/resources/assets/gregtech/models/item/metaitems/battery.uv.naquadria/8.json b/src/main/resources/assets/gregtech/models/item/metaitems/battery.uv.naquadria/8.json new file mode 100644 index 00000000000..bf297b971fe --- /dev/null +++ b/src/main/resources/assets/gregtech/models/item/metaitems/battery.uv.naquadria/8.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "gregtech:items/metaitems/battery.uv.naquadria/8" + } +} diff --git a/src/main/resources/assets/gregtech/models/item/metaitems/battery.zpm.naquadria/1.json b/src/main/resources/assets/gregtech/models/item/metaitems/battery.zpm.naquadria/1.json new file mode 100644 index 00000000000..d417e2a9816 --- /dev/null +++ b/src/main/resources/assets/gregtech/models/item/metaitems/battery.zpm.naquadria/1.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "gregtech:items/metaitems/battery.zpm.naquadria/1" + } +} diff --git a/src/main/resources/assets/gregtech/models/item/metaitems/battery.zpm.naquadria/2.json b/src/main/resources/assets/gregtech/models/item/metaitems/battery.zpm.naquadria/2.json new file mode 100644 index 00000000000..875fe9d6644 --- /dev/null +++ b/src/main/resources/assets/gregtech/models/item/metaitems/battery.zpm.naquadria/2.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "gregtech:items/metaitems/battery.zpm.naquadria/2" + } +} diff --git a/src/main/resources/assets/gregtech/models/item/metaitems/battery.zpm.naquadria/3.json b/src/main/resources/assets/gregtech/models/item/metaitems/battery.zpm.naquadria/3.json new file mode 100644 index 00000000000..715f1c7fdd3 --- /dev/null +++ b/src/main/resources/assets/gregtech/models/item/metaitems/battery.zpm.naquadria/3.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "gregtech:items/metaitems/battery.zpm.naquadria/3" + } +} diff --git a/src/main/resources/assets/gregtech/models/item/metaitems/battery.zpm.naquadria/4.json b/src/main/resources/assets/gregtech/models/item/metaitems/battery.zpm.naquadria/4.json new file mode 100644 index 00000000000..91d189aa355 --- /dev/null +++ b/src/main/resources/assets/gregtech/models/item/metaitems/battery.zpm.naquadria/4.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "gregtech:items/metaitems/battery.zpm.naquadria/4" + } +} diff --git a/src/main/resources/assets/gregtech/models/item/metaitems/battery.zpm.naquadria/5.json b/src/main/resources/assets/gregtech/models/item/metaitems/battery.zpm.naquadria/5.json new file mode 100644 index 00000000000..11cef5ecb78 --- /dev/null +++ b/src/main/resources/assets/gregtech/models/item/metaitems/battery.zpm.naquadria/5.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "gregtech:items/metaitems/battery.zpm.naquadria/5" + } +} diff --git a/src/main/resources/assets/gregtech/models/item/metaitems/battery.zpm.naquadria/6.json b/src/main/resources/assets/gregtech/models/item/metaitems/battery.zpm.naquadria/6.json new file mode 100644 index 00000000000..529a3071648 --- /dev/null +++ b/src/main/resources/assets/gregtech/models/item/metaitems/battery.zpm.naquadria/6.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "gregtech:items/metaitems/battery.zpm.naquadria/6" + } +} diff --git a/src/main/resources/assets/gregtech/models/item/metaitems/battery.zpm.naquadria/7.json b/src/main/resources/assets/gregtech/models/item/metaitems/battery.zpm.naquadria/7.json new file mode 100644 index 00000000000..49fe6720f16 --- /dev/null +++ b/src/main/resources/assets/gregtech/models/item/metaitems/battery.zpm.naquadria/7.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "gregtech:items/metaitems/battery.zpm.naquadria/7" + } +} diff --git a/src/main/resources/assets/gregtech/models/item/metaitems/battery.zpm.naquadria/8.json b/src/main/resources/assets/gregtech/models/item/metaitems/battery.zpm.naquadria/8.json new file mode 100644 index 00000000000..d7c658771a1 --- /dev/null +++ b/src/main/resources/assets/gregtech/models/item/metaitems/battery.zpm.naquadria/8.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "gregtech:items/metaitems/battery.zpm.naquadria/8" + } +} diff --git a/src/main/resources/assets/gregtech/models/item/metaitems/cover.infinite_water.json b/src/main/resources/assets/gregtech/models/item/metaitems/cover.infinite_water.json new file mode 100644 index 00000000000..c0dd2f63af9 --- /dev/null +++ b/src/main/resources/assets/gregtech/models/item/metaitems/cover.infinite_water.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "gregtech:items/metaitems/cover.infinite_water" + } +} diff --git a/src/main/resources/assets/gregtech/models/item/metaitems/energy_field_projector.json b/src/main/resources/assets/gregtech/models/item/metaitems/energy_field_projector.json deleted file mode 100644 index 41ab5566934..00000000000 --- a/src/main/resources/assets/gregtech/models/item/metaitems/energy_field_projector.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "item/generated", - "textures": { - "layer0": "gregtech:items/metaitems/magnetic_field_projector" - } -} \ No newline at end of file diff --git a/src/main/resources/assets/gregtech/models/item/metaitems/terminal.json b/src/main/resources/assets/gregtech/models/item/metaitems/terminal.json new file mode 100644 index 00000000000..e79e3e6866a --- /dev/null +++ b/src/main/resources/assets/gregtech/models/item/metaitems/terminal.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "gregtech:items/metaitems/tool.terminal" + } +} diff --git a/src/main/resources/assets/gregtech/terminal/guide/items/en_us/test.json b/src/main/resources/assets/gregtech/terminal/guide/items/en_us/test.json new file mode 100644 index 00000000000..9f26d707b45 --- /dev/null +++ b/src/main/resources/assets/gregtech/terminal/guide/items/en_us/test.json @@ -0,0 +1,33 @@ +{ + "metaitem": "tool.wrench", + "section": "Items/Tools", + "title": "Wrench", + "stream": [ + { + "type": "textbox", + "isCenter": false, + "content": [ + "Wrench this, wrench that" + ] + }, + { + "type": "textbox", + "isCenter": true, + "fontSize": 5, + "content": [ + "§nMinecraft Formatting", + "§r§00 §11 §22 §33", + "§44 §55 §66 §77", + "§88 §99 §aa §bb", + "§cc §dd §ee §ff", + "§r§0k §kMinecraft", + "§rl §lMinecraft", + "§rm §mMinecraft", + "§rn §nMinecraft", + "§ro §oMinecraft", + "§rr §rMinecraft" + ] + } + ], + "fixed": [] +} diff --git a/src/main/resources/assets/gregtech/terminal/guide/items/zh_cn/test.json b/src/main/resources/assets/gregtech/terminal/guide/items/zh_cn/test.json new file mode 100644 index 00000000000..dcd7cbf459d --- /dev/null +++ b/src/main/resources/assets/gregtech/terminal/guide/items/zh_cn/test.json @@ -0,0 +1,33 @@ +{ + "metaitem": "tool.wrench", + "section": "物品/工具", + "title": "Wrench", + "stream": [ + { + "type": "textbox", + "isCenter": false, + "content": [ + "扳扳这,扳扳那" + ] + }, + { + "type": "textbox", + "isCenter": true, + "fontSize": 5, + "content": [ + "§nMinecraft Formatting", + "§r§00 §11 §22 §33", + "§44 §55 §66 §77", + "§88 §99 §aa §bb", + "§cc §dd §ee §ff", + "§r§0k §kMinecraft", + "§rl §lMinecraft", + "§rm §mMinecraft", + "§rn §nMinecraft", + "§ro §oMinecraft", + "§rr §rMinecraft" + ] + } + ], + "fixed": [] +} diff --git a/src/main/resources/assets/gregtech/terminal/guide/machines/en_us/steam_boiler_coal_bronze.json b/src/main/resources/assets/gregtech/terminal/guide/machines/en_us/steam_boiler_coal_bronze.json new file mode 100644 index 00000000000..5a35a77e167 --- /dev/null +++ b/src/main/resources/assets/gregtech/terminal/guide/machines/en_us/steam_boiler_coal_bronze.json @@ -0,0 +1,33 @@ +{ + "machine": "steam_boiler_coal_bronze", + "section": "Machines/Steam", + "title": "Small Steam Coal Boiler", + "stream": [ + { + "type": "textbox", + "isCenter": false, + "content": [ + "Wrench this, wrench that" + ] + }, + { + "type": "textbox", + "isCenter": true, + "fontSize": 5, + "content": [ + "§nMinecraft Formatting", + "§r§00 §11 §22 §33", + "§44 §55 §66 §77", + "§88 §99 §aa §bb", + "§cc §dd §ee §ff", + "§r§0k §kMinecraft", + "§rl §lMinecraft", + "§rm §mMinecraft", + "§rn §nMinecraft", + "§ro §oMinecraft", + "§rr §rMinecraft" + ] + } + ], + "fixed": [] +} diff --git a/src/main/resources/assets/gregtech/terminal/guide/multiblocks/en_us/electric_blast_furnace.json b/src/main/resources/assets/gregtech/terminal/guide/multiblocks/en_us/electric_blast_furnace.json new file mode 100644 index 00000000000..3a3dff05723 --- /dev/null +++ b/src/main/resources/assets/gregtech/terminal/guide/multiblocks/en_us/electric_blast_furnace.json @@ -0,0 +1,33 @@ +{ + "multiblock": "electric_blast_furnace", + "section": "Multi-Block Machines/Electric", + "title": "Electric Blast Furnace", + "stream": [ + { + "type": "textbox", + "isCenter": false, + "content": [ + "Wrench this, wrench that" + ] + }, + { + "type": "textbox", + "isCenter": true, + "fontSize": 5, + "content": [ + "§nMinecraft Formatting", + "§r§00 §11 §22 §33", + "§44 §55 §66 §77", + "§88 §99 §aa §bb", + "§cc §dd §ee §ff", + "§r§0k §kMinecraft", + "§rl §lMinecraft", + "§rm §mMinecraft", + "§rn §nMinecraft", + "§ro §oMinecraft", + "§rr §rMinecraft" + ] + } + ], + "fixed": [] +} diff --git a/src/main/resources/assets/gregtech/terminal/guide/tutorials/en_us/api_0_guidepage.json b/src/main/resources/assets/gregtech/terminal/guide/tutorials/en_us/api_0_guidepage.json new file mode 100644 index 00000000000..8fe3a94e403 --- /dev/null +++ b/src/main/resources/assets/gregtech/terminal/guide/tutorials/en_us/api_0_guidepage.json @@ -0,0 +1,148 @@ +{ + "section": "Guide Widget Api", + "title": "Guide Page", + "stream": [ + { + "type": "textbox", + "content": [ + "In this page we'll learn how to write a guide page.", + "-------------------------------", + "Let's take a look at an example config file for a guide page.", + "§lJSON§r:", + "{", + " \"section\": \"section name here\",", + " \"title\": \"title here\",", + " \"stream\": [", + " {", + " \"type\": \"textbox\",", + " \"content\": [\"TextBox widget\"]", + " }", + " ],", + " \"fixed\": [", + " {", + " \"x\": 50,", + " \"y\": 100,", + " \"width\": 150,", + " \"height\": 40,", + " \"type\": 0,", + " \"content\": [\"TextBox widget\"]", + " }", + " ]", + "}", + "-------------------------------", + "§lContents§r" + ] + }, + { + "type": "textbox", + "link": "section", + "content": [ + " 1.§nsection§r" + ] + }, + { + "type": "textbox", + "link": "title", + "content": [ + " 2.§ntitle§r" + ] + }, + { + "type": "textbox", + "link": "stream", + "content": [ + " 3.§nstream§r" + ] + }, + { + "type": "textbox", + "link": "fixed", + "content": [ + " 4.§nfixed§r" + ] + }, + { + "type": "textbox", + "ref": "section", + "content": [ + "-------------------------------", + "", + "§lAttr§r: §nsection§r (§4required§r)", + "§ltype§r: String", + "§lillustrate§r: Specifies which section of the application the page belongs to.", + "The application automatically merges pages of the same section name and builds a directory tree." + ] + }, + { + "type": "textbox", + "ref": "title", + "content": [ + "-------------------------------", + "", + "§lAttr§r: §ntitle§r (§4required§r)", + "§ltype§r: String", + "§lillustrate§r: The page title." + ] + }, + { + "type": "textbox", + "ref": "stream", + "content": [ + "-------------------------------", + "", + "§lAttr§r: §nstream§r (§4required§r)", + "§ltype§r: Array", + "§lillustrate§r: Widgets in streaming layout. You don't need to care the position and size of widgets in stream, all typography will be done automatically." + ] + }, + { + "type": "textbox", + "ref": "fixed", + "content": [ + "-------------------------------", + "", + "§lAttr§r: §nfixed§r (§4required§r)", + "§ltype§r: Array", + "§lillustrate§r: Widgets in fixed layout. You need to specify the position and size of each widget." + ] + }, + { + "type": "textbox", + "isCenter": true, + "content": [ + "§lDemo§r: fixed and stream" + ] + }, + { + "type": "textbox", + "isCenter": true, + "hover_text": ["stream widget"], + "content": [ + "§nMinecraft Formatting", + "§r§00 §11 §22 §33", + "§44 §55 §66 §77", + "§88 §99 §aa §bb", + "§cc §dd §ee §ff", + "§r§0k §kMinecraft", + "§rl §lMinecraft", + "§rm §mMinecraft", + "§rn §nMinecraft", + "§ro §oMinecraft", + "§rr §rMinecraft" + ] + } + ], + "fixed": [ + { + "type": "image", + "x": 30, + "y": 800, + "stroke": 4278190335, + "hover_text": ["fixed widget", "\"x\": 30","\"y\": 800","\"width\": 100","\"width\": 100"], + "form": "item", + "source": "minecraft:ender_pearl", + "width": 100, + "height": 100 + } + ] +} diff --git a/src/main/resources/assets/gregtech/terminal/guide/tutorials/en_us/api_1_widget.json b/src/main/resources/assets/gregtech/terminal/guide/tutorials/en_us/api_1_widget.json new file mode 100644 index 00000000000..7d8d23bea8c --- /dev/null +++ b/src/main/resources/assets/gregtech/terminal/guide/tutorials/en_us/api_1_widget.json @@ -0,0 +1,304 @@ +{ + "section": "Guide Widget Api", + "title": "Guide Widget", + "stream": [ + { + "type": "textbox", + "content": [ + "In this page we'll learn what is §4§lGuide Widget§r, and its public attributes.", + "Widgets are rendered in the Guide Page, which is the basis for your custom pages. §nTextbox§r, §nImage§r, etc", + "To use it, just add the related JSON code under the §l\"fixed\"§r or §l\"stream\"§r.", + "There are some attributes effects (styles) that are valid for all widgets", + "-------------------------------", + "§lJSON§r:", + "{", + " \"type\": \"type here\",", + " \"x\": 50,", + " \"y\": 100,", + " \"width\": 150,", + " \"height\": 40,", + " \"ref\": \"ref\",", + " \"stroke\": 0,", + " \"stroke_width\": 1,", + " \"fill\": 0,", + " \"link\": \"ref\"", + " \"hover_text\": [\"text here\"]", + "}", + "-------------------------------", + "§lContents§r" + ] + }, + { + "type": "textbox", + "link": "type", + "content": [ + " 1.§ntype§r" + ] + }, + { + "type": "textbox", + "link": "xywh", + "content": [ + " 2.§nx, y, width, height§r" + ] + }, + { + "type": "textbox", + "link": "ref", + "content": [ + " 3.§nref§r" + ] + }, + { + "type": "textbox", + "link": "fill", + "content": [ + " 4.§nfill§r" + ] + }, + { + "type": "textbox", + "link": "stroke", + "content": [ + " 5.§nstroke§r" + ] + }, + { + "type": "textbox", + "link": "stroke_width", + "content": [ + " 6.§nstroke_width§r" + ] + }, + { + "type": "textbox", + "link": "link", + "content": [ + " 7.§nlink§r" + ] + }, + { + "type": "textbox", + "link": "hover", + "content": [ + " 8.§nhover_text§r" + ] + }, + { + "type": "textbox", + "ref": "type", + "content": [ + "-------------------------------", + "", + "§lAttr§r: §ntype§r (§4required§r)", + "§ltype§r: String", + "§lillustrate§r: This is the unique id of the widget. See the API documentation for each widget." + ] + }, + { + "type": "textbox", + "ref": "xywh", + "content": [ + "-------------------------------", + "", + "§lAttr§r: §nx, y, width, height§r (§4optional§r)", + "§ltype§r: Integer", + "§lillustrate§r: The position and size of the widget. In a stream layout, you usually don't need to set it (the image widget needs to set width and height). Under fixed layout you must set these four attributes." + ] + }, + { + "type": "textbox", + "ref": "ref", + "content": [ + "-------------------------------", + "", + "§lAttr§r: §nref§r (§4optional§r)", + "§ltype§r: String", + "§ldefault§r: null", + "§lillustrate§r: This is a tag of this widget. The ref should be unique on the same page." + ] + }, + { + "type": "textbox", + "ref": "fill", + "content": [ + "-------------------------------", + "", + "§lAttr§r: §nfill§r (§6optional§r)", + "§ltype§r: Number", + "§ldefault§r: 0", + "§lillustrate§r: The background color." + ] + }, + { + "type": "textbox", + "isCenter": true, + "content": [ + "§lDemo§r: 4278190335 (0xFF0000FF)" + ] + }, + { + "type": "textbox", + "isCenter": true, + "fill": 4278190335, + "content": [ + "§nMinecraft Formatting", + "§r§00 §11 §22 §33", + "§44 §55 §66 §77", + "§88 §99 §aa §bb", + "§cc §dd §ee §ff", + "§r§0k §kMinecraft", + "§rl §lMinecraft", + "§rm §mMinecraft", + "§rn §nMinecraft", + "§ro §oMinecraft", + "§rr §rMinecraft" + ] + }, + { + "type": "textbox", + "ref": "stroke", + "content": [ + "-------------------------------", + "", + "§lAttr§r: §nstroke§r (§6optional§r)", + "§ltype§r: Number", + "§ldefault§r: 0", + "§lillustrate§r: The border color." + ] + }, + { + "type": "textbox", + "isCenter": true, + "content": [ + "§lDemo§r: 4278190335 (0xFF0000FF)" + ] + }, + { + "type": "image", + "form": "item", + "source": "minecraft:ender_pearl", + "stroke": 4278190335, + "width": 50, + "height": 50 + }, + { + "type": "textbox", + "ref": "stroke_width", + "content": [ + "-------------------------------", + "", + "§lAttr§r: §nstroke_width§r (§6optional§r)", + "§ltype§r: Number", + "§ldefault§r: 1", + "§lillustrate§r: The border width." + ] + }, + { + "type": "textbox", + "isCenter": true, + "content": [ + "§lDemo§r: 5" + ] + }, + { + "type": "image", + "form": "item", + "source": "minecraft:ender_pearl", + "stroke": 4278190335, + "stroke_width": 5, + "width": 50, + "height": 50 + }, + { + "type": "textbox", + "ref": "link", + "content": [ + "-------------------------------", + "", + "§lAttr§r: §nlink§r (§6optional§r)", + "§ltype§r: String", + "§ldefault§r: null", + "§lillustrate§r: Click to jump to the specified location. Need to be used with ref, target is ref." + ] + }, + { + "type": "textbox", + "isCenter": true, + "content": [ + "§lDemo§r: \"P2\"" + ] + }, + { + "type": "textbox", + "isCenter": true, + "fill": 4286430975, + "hover_text": ["\"ref\": \"P1\""], + "ref": "P1", + "link": "P2", + "content": ["Click Me!"] + }, + { + "type": "textbox", + "content": [ + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "" + ] + }, + { + "type": "textbox", + "isCenter": true, + "content": [ + "§lDemo§r: \"P1\"" + ] + }, + { + "type": "textbox", + "isCenter": true, + "fill": 4286430975, + "hover_text": ["\"ref\": \"P2\""], + "ref": "P2", + "link": "P1", + "content": ["Click Me!"] + }, + { + "type": "textbox", + "ref": "hover", + "content": [ + "-------------------------------", + "", + "§lAttr§r: §nhover_text§r (§6optional§r)", + "§ltype§r: Array", + "§ldefault§r: null", + "§lillustrate§r: Displays text when the mouse is over the widget." + ] + }, + { + "type": "textbox", + "isCenter": true, + "content": [ + "§lDemo§r: [\"THIS IS\",\"GT ICON\"]" + ] + }, + { + "type": "image", + "hover_text": ["THIS IS","GT ICON"], + "form": "resource", + "source": "gregtech:textures/gui/icon/gregtech_logo.png", + "width": 100, + "height": 100 + } + ], + "fixed": [] +} diff --git a/src/main/resources/assets/gregtech/terminal/guide/tutorials/en_us/api_2_textbox.json b/src/main/resources/assets/gregtech/terminal/guide/tutorials/en_us/api_2_textbox.json new file mode 100644 index 00000000000..f67b885350a --- /dev/null +++ b/src/main/resources/assets/gregtech/terminal/guide/tutorials/en_us/api_2_textbox.json @@ -0,0 +1,256 @@ +{ + "section": "Guide Widget Api", + "title": "1. TextBox Widget", + "stream": [ + { + "type": "textbox", + "content": [ + "In this page we'll learn how to use the powerful §4§lTextBox§r, which is the most commonly used. So you should read the API documentation carefully.", + "-------------------------------", + "§lWidget Type§r: §ntextbox§r", + "-------------------------------", + "§lJSON§r:", + "{", + " \"type\": \"textbox\",", + " \"space\": 1,", + " \"fontSize\": 9,", + " \"fontColor\": 4278190080,", + " \"isCenter\": false,", + " \"isShadow\": false,", + " \"content\": [\"content here!\"]", + "}", + "-------------------------------", + "§lContents§r" + ] + }, + { + "type": "textbox", + "link": "content", + "content": [ + " 1.§ncontent§r" + ] + }, + { + "type": "textbox", + "link": "space", + "content": [ + " 2.§nspace§r" + ] + }, + { + "type": "textbox", + "link": "fontSize", + "content": [ + " 3.§nfontSize§r" + ] + }, + { + "type": "textbox", + "link": "fontColor", + "content": [ + " 4.§nfontColor§r" + ] + }, + { + "type": "textbox", + "link": "isCenter", + "content": [ + " 5.§nisCenter§r" + ] + }, + { + "type": "textbox", + "link": "isShadow", + "content": [ + " 6.§nisShadow§r" + ] + }, + { + "type": "textbox", + "ref": "content", + "content": [ + "-------------------------------", + "", + "§lAttr§r: §ncontent§r (§4required§r)", + "§ltype§r: Array", + "§lillustrate§r: Text contents, each item will be a newline.Text that is too long will auto wrap itself. (Supporting Minecraft Formatting Code)" + ] + }, + { + "type": "textbox", + "isCenter": true, + "stroke": 4294901760, + "content": [ + "§lDemo§r: [...]", + "§nMinecraft Formatting", + "§r§00 §11 §22 §33", + "§44 §55 §66 §77", + "§88 §99 §aa §bb", + "§cc §dd §ee §ff", + "§r§0k §kMinecraft", + "§rl §lMinecraft", + "§rm §mMinecraft", + "§rn §nMinecraft", + "§ro §oMinecraft", + "§rr §rMinecraft" + ] + }, + { + "type": "textbox", + "ref": "space", + "content": [ + "-------------------------------", + "", + "§lAttr§r: §nspace§r (§6optional§r)", + "§ltype§r: Number", + "§ldefault§r: 1", + "§lillustrate§r: The spacing between lines of text." + ] + }, + { + "type": "textbox", + "isCenter": true, + "stroke": 4294901760, + "space": 5, + "content": [ + "§lDemo§r: 5", + "§nMinecraft Formatting", + "§r§00 §11 §22 §33", + "§44 §55 §66 §77", + "§88 §99 §aa §bb", + "§cc §dd §ee §ff", + "§r§0k §kMinecraft", + "§rl §lMinecraft", + "§rm §mMinecraft", + "§rn §nMinecraft", + "§ro §oMinecraft", + "§rr §rMinecraft" + ] + },{ + "type": "textbox", + "ref": "fontSize", + "content": [ + "-------------------------------", + "", + "§lAttr§r: §nfontSize§r (§6optional§r)", + "§ltype§r: Number", + "§ldefault§r: 9", + "§lillustrate§r: The font size. (Actually it's the height of the font)" + ] + }, + { + "type": "textbox", + "isCenter": true, + "stroke": 4294901760, + "fontSize": 5, + "content": [ + "§lDemo§r: 5", + "§nMinecraft Formatting", + "§r§00 §11 §22 §33", + "§44 §55 §66 §77", + "§88 §99 §aa §bb", + "§cc §dd §ee §ff", + "§r§0k §kMinecraft", + "§rl §lMinecraft", + "§rm §mMinecraft", + "§rn §nMinecraft", + "§ro §oMinecraft", + "§rr §rMinecraft" + ] + },{ + "type": "textbox", + "ref": "fontColor", + "content": [ + "-------------------------------", + "", + "§lAttr§r: §nfontColor§r (§6optional§r)", + "§ltype§r: Number", + "§ldefault§r: 4278190080", + "§lillustrate§r: The default color of the content. You can also set the colors with special symbols (provided by Minecraft).But maybe you need it sometimes." + ] + }, + { + "type": "textbox", + "isCenter": true, + "stroke": 4294901760, + "fontColor": 5, + "content": [ + "§lDemo§r: 4294901760 (0xFFFF0000)", + "§nMinecraft Formatting", + "§r§00 §11 §22 §33", + "§44 §55 §66 §77", + "§88 §99 §aa §bb", + "§cc §dd §ee §ff", + "§r§0k §kMinecraft", + "§rl §lMinecraft", + "§rm §mMinecraft", + "§rn §nMinecraft", + "§ro §oMinecraft", + "§rr §rMinecraft" + ] + }, + { + "type": "textbox", + "ref": "isCenter", + "content": [ + "-------------------------------", + "", + "§lAttr§r: §nisCenter§r (§6optional§r)", + "§ltype§r: Boolean", + "§ldefault§r: false", + "§lillustrate§r: Text-align center." + ] + }, + { + "type": "textbox", + "isCenter": false, + "stroke": 4294901760, + "content": [ + "§lDemo§r: false", + "§nMinecraft Formatting", + "§r§00 §11 §22 §33", + "§44 §55 §66 §77", + "§88 §99 §aa §bb", + "§cc §dd §ee §ff", + "§r§0k §kMinecraft", + "§rl §lMinecraft", + "§rm §mMinecraft", + "§rn §nMinecraft", + "§ro §oMinecraft", + "§rr §rMinecraft" + ] + },{ + "type": "textbox", + "ref": "isShadow", + "content": [ + "-------------------------------", + "", + "§lAttr§r: §nisShadow§r (§6optional§r)", + "§ltype§r: Boolean", + "§ldefault§r: false", + "§lillustrate§r: Render shadow." + ] + }, + { + "type": "textbox", + "isCenter": true, + "stroke": 4294901760, + "isShadow": true, + "content": [ + "§lDemo§r: true", + "§nMinecraft Formatting", + "§r§00 §11 §22 §33", + "§44 §55 §66 §77", + "§88 §99 §aa §bb", + "§cc §dd §ee §ff", + "§r§0k §kMinecraft", + "§rl §lMinecraft", + "§rm §mMinecraft", + "§rn §nMinecraft", + "§ro §oMinecraft", + "§rr §rMinecraft" + ] + } + ], + "fixed": [] +} diff --git a/src/main/resources/assets/gregtech/terminal/guide/tutorials/en_us/api_3_image.json b/src/main/resources/assets/gregtech/terminal/guide/tutorials/en_us/api_3_image.json new file mode 100644 index 00000000000..93aba81b064 --- /dev/null +++ b/src/main/resources/assets/gregtech/terminal/guide/tutorials/en_us/api_3_image.json @@ -0,0 +1,207 @@ +{ + "section": "Guide Widget Api", + "title": "2. Image Widget", + "stream": [ + { + "type": "textbox", + "content": [ + "In this page we'll learn how to add an §4§lImage§r. There are three different forms of image supported here: §4Url§r, §4Item§r, and §4ResourceLocation§r. Don't worry, it's easy", + "-------------------------------", + "§lWidget Type§r: §nimage§r", + "-------------------------------", + "§lJSON§r:", + "{", + " \"type\": \"image\",", + " \"form\": \"Item\",", + " \"source\": \"minecraft:ender_pearl\",", + " \"width\": 100,", + " \"height\": 100", + "}", + "-------------------------------", + "§lContents§r" + ] + }, + { + "type": "textbox", + "link": "form", + "content": [ + " 1.§nform§r" + ] + }, + { + "type": "textbox", + "link": "source", + "content": [ + " 2.§nsource§r" + ] + }, + { + "type": "textbox", + "link": "wh", + "content": [ + " 3.§nwidth, height§r" + ] + }, + { + "type": "textbox", + "ref": "form", + "content": [ + "-------------------------------", + "", + "§lAttr§r: §nform§r (§4required§r)", + "§ltype§r: String", + "§lillustrate§r: It can only be set one of §4Url§r, §4Item§r, or §4ResourceLocation§r.", + " \"url\" -- image url.", + " \"item\" -- The registered name of the Item in game.", + " \"resource\" -- The resource location." + ] + }, + { + "type": "textbox", + "isCenter": true, + "content": [ + "§lDemo§r: \"url\"" + ] + }, + { + "type": "image", + "hover_text": ["https://z3.ax1x.com/2021/07/29/Wb4Djs.gif"], + "form": "url", + "source": "https://z3.ax1x.com/2021/07/29/Wb4Djs.gif", + "stroke": 4278190080, + "stroke_width": 2, + "width": 100, + "height": 100 + }, + { + "type": "textbox", + "isCenter": true, + "content": [ + "§lDemo§r: \"item\"" + ] + }, + { + "type": "image", + "hover_text": ["minecraft:ender_pearl"], + "form": "item", + "source": "minecraft:ender_pearl", + "width": 100, + "height": 100 + }, + { + "type": "textbox", + "isCenter": true, + "content": [ + "§lDemo§r: \"resource\"" + ] + }, + { + "type": "image", + "hover_text": ["gregtech:textures/gui/icon/coke_oven.png"], + "form": "resource", + "source": "gregtech:textures/gui/icon/coke_oven.png", + "width": 100, + "height": 100 + }, + { + "type": "textbox", + "ref": "source", + "content": [ + "-------------------------------", + "", + "§lAttr§r: §nsource§r (§4required§r)", + "§ltype§r: String", + "§lillustrate§r: The source of the picture. The three images above correspond to the following sources:" + ] + }, + { + "type": "textbox", + "isCenter": true, + "content": [ + "§lDemo§r: \"https://z3.ax1x.com/2021/07/29/Wb4Djs.gif\"" + ] + }, + { + "type": "image", + "hover_text": ["https://z3.ax1x.com/2021/07/29/Wb4Djs.gif"], + "form": "url", + "source": "https://z3.ax1x.com/2021/07/29/Wb4Djs.gif", + "stroke": 4278190080, + "stroke_width": 2, + "width": 100, + "height": 100 + }, + { + "type": "textbox", + "isCenter": true, + "content": [ + "§lDemo§r: \"minecraft:ender_pearl\"" + ] + }, + { + "type": "image", + "hover_text": ["minecraft:ender_pearl"], + "form": "item", + "source": "minecraft:ender_pearl", + "width": 100, + "height": 100 + }, + { + "type": "textbox", + "isCenter": true, + "content": [ + "§lDemo§r: \"gregtech:textures/gui/icon/coke_oven.png\"" + ] + }, + { + "type": "image", + "hover_text": ["gregtech:textures/gui/icon/coke_oven.png"], + "form": "resource", + "source": "gregtech:textures/gui/icon/coke_oven.png", + "width": 100, + "height": 100 + }, + { + "type": "textbox", + "ref": "wh", + "content": [ + "-------------------------------", + "", + "§lAttr§r: §nwidth, height§r (§4required§r)", + "§ltype§r: Integer", + "§lillustrate§r: The Size of the picture." + ] + }, + { + "type": "textbox", + "isCenter": true, + "content": [ + "§lDemo§r: \"50, 50\"" + ] + }, + { + "type": "image", + "hover_text": ["minecraft:ender_pearl"], + "form": "item", + "source": "minecraft:ender_pearl", + "width": 50, + "height": 50 + }, + { + "type": "textbox", + "isCenter": true, + "content": [ + "§lDemo§r: \"100, 50\"" + ] + }, + { + "type": "image", + "hover_text": ["minecraft:ender_pearl"], + "form": "item", + "source": "minecraft:ender_pearl", + "width": 100, + "height": 50 + } + ], + "fixed": [] +} diff --git a/src/main/resources/assets/gregtech/textures/blocks/cover/overlay_fluid_filter.png b/src/main/resources/assets/gregtech/textures/blocks/cover/overlay_fluid_filter.png new file mode 100644 index 0000000000000000000000000000000000000000..42e1be54672ee66dc223d23855146eac5ae200cd GIT binary patch literal 287 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCij$3p^r=85p<)L71^VC4M4MkiEpy*OmPq7Z(?Y(08f8H9#SW64!{5;QX|b z^2DN4hJwV*yb`^<)Di^~JwrXiWUV>gKsB|VE{-7<{#$!5avo6Nafw|l|1LmaSJUcU zsi#DP_-s{kUmkz#Wb%H}%vvYC`33x2!(MAH^_kf8H{-gZ(EJHD#a@if{@P0z%KU4b zzMY*H)X=Wc%;0@>S=ottmcVUuwmNM6*yHT48PTZh#y4zT3)eZD~8U zJH&($FOs0S5F^Hbxfn^r4`_@U|0O`+gMKiW5S1?w0x<>+f(AS>G5WmSpWDGemUL~O z_xJpszwgs`-(Y|5!uiYQ`+UBI@xJaMxIYS4XIl&WFWx=#2He`MzO9bWw_q{3=K0<_ z^f<^K(32zXNMe($nt8vXnJMfq3R1?F6pQ8k9GlORxIDDu_Ur`ZsvAwwPIBDB>=1U$g0147o!D?! z*3^6BiNU%y2_mECEiVknYu$*Z)-hJW&Ux#a%HkZ(1DOLp@pUZd)xk~OshN&jt||b! zr!?z7WJUGZ9am!;04(CTFvB4RNp(Y3uHZCUDma*kJoTKGW=Q}fSv7mEo}R7O9M8zg z9H^BwUDL^$cZsCFTvvjM$=#+}AnAyAM`)5oSu<5#lfB1Oh?BxXN?}kc6k>!x5HaDf z$T1Sa5=w=GVpzk(Pr?&799J<^On5-z*MS5{LJ09nfDtv&N@;?~D5(I?XsVzDLmJ}K zVyLD+VC%4flw6}fghvA&O$>{CSV%J=krx?3QW2Aq1fIb`q>2Ixpr8gkq$%X+U_3%2 zKUaMn%qec#wDYhZbwe|YPF0@N^LW@*NYQzb4}?Oz#0f}}LSndz*n({bTAh&boF5^Y z(o}gPP$^J%J+EXiYZ)0&N(|g41<&P}jTP6llct%A(8M{4P&d#QR#&~-GRWztD|Qa@2EcIbjsWK zvZ7Y3I?7J0(N&?ERg4UV(Fwg@f$2?pisv*D2`S73C9E+54g?rUNJAPl6jB4Ch5}-$ zrtg?(x2V`Snt?#UWoU1&2Gr_mH>{~4i&;!c?NtJXsFXxV4u)kU(CmHr-ptec>;6il zjrMDuFsHl~*lht-J`IDlZBHTIkM4}EA+IDDmJIJoO~|l;tvg$;hS?==GF7iPyf(&K zH4R-##v{2mvf1iz)+`$L!BWFDazt&nXxd`~_CRVoR^5BB+=*=D8G?_rXf!u<2g1|aq^sC) z%%;vYta-I>_>hBJo(N6{-94JIb7| zXV;RJ-la>w_?qsxG}QWg8$zeb9Uq=M+Hq<6?NW2lVpYyGG`B!0pIx@Qd z%0q{oBcqFYCZd}+KXY>3!#B(4U;1FlgJ+L!oBH|lKNcMwxLM90pe~#qT|1e5LRmi9 zR`$LA_x1GyZ0X6qlliWV?QJWzTz{&3@W%AEiOY*DZkGv2q?mKq&&6&`c{v2)8`e7|*f%gpqd g<2Noo^6%km>2LS;$G_k85jhCPd-}VNb&Zz)10ZX21poj5 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/blocks/cover/overlay_infinite_water.png.mcmeta b/src/main/resources/assets/gregtech/textures/blocks/cover/overlay_infinite_water.png.mcmeta new file mode 100644 index 00000000000..ddda8625a64 --- /dev/null +++ b/src/main/resources/assets/gregtech/textures/blocks/cover/overlay_infinite_water.png.mcmeta @@ -0,0 +1,5 @@ +{ + "animation":{ + "frametime": 5 + } +} diff --git a/src/main/resources/assets/gregtech/textures/blocks/machines/gas_collector/overlay_back.png b/src/main/resources/assets/gregtech/textures/blocks/machines/gas_collector/overlay_back.png new file mode 100644 index 0000000000000000000000000000000000000000..8ff62200602339d405e76673d3aef603f1c68fa8 GIT binary patch literal 209 zcmV;?051QDP)4>P&k58O0p~qj4`OS(nhiw(E4CzQA%N&rcv`eKP^&9@~Ql4c|8OG zF-GaVzXdF%&~An`_+iK&EZood%n*XK)=r6>bI3XG-|;Meg9~^7>lP$#2QxGz00000 LNkvXXu0mjf)e=+h literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/blocks/machines/gas_collector/overlay_back_active.png b/src/main/resources/assets/gregtech/textures/blocks/machines/gas_collector/overlay_back_active.png new file mode 100644 index 0000000000000000000000000000000000000000..8ff62200602339d405e76673d3aef603f1c68fa8 GIT binary patch literal 209 zcmV;?051QDP)4>P&k58O0p~qj4`OS(nhiw(E4CzQA%N&rcv`eKP^&9@~Ql4c|8OG zF-GaVzXdF%&~An`_+iK&EZood%n*XK)=r6>bI3XG-|;Meg9~^7>lP$#2QxGz00000 LNkvXXu0mjf)e=+h literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/blocks/machines/gas_collector/overlay_bottom.png b/src/main/resources/assets/gregtech/textures/blocks/machines/gas_collector/overlay_bottom.png new file mode 100644 index 0000000000000000000000000000000000000000..d6bf79a979cd982881df2f0fe56d7578564c94f3 GIT binary patch literal 279 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4%caKYZ?lYt_f1s;*b z3=G^tAk28_ZrvZCAbW|YuPggKE-o$(q3=?GYk)#aJY5_^EKVPte3tjH0#B=a==2wg z!3X#@7+F7173%crkiFyGTQKRFyUeT8)iM+8?VA(Rdaf`xe-#mSy0PF&RDGO}rX&M{ zar4ZFd(#FVdQ&MBb@0F`TL-v9sr literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/blocks/machines/gas_collector/overlay_bottom_active.png b/src/main/resources/assets/gregtech/textures/blocks/machines/gas_collector/overlay_bottom_active.png new file mode 100644 index 0000000000000000000000000000000000000000..d6bf79a979cd982881df2f0fe56d7578564c94f3 GIT binary patch literal 279 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4%caKYZ?lYt_f1s;*b z3=G^tAk28_ZrvZCAbW|YuPggKE-o$(q3=?GYk)#aJY5_^EKVPte3tjH0#B=a==2wg z!3X#@7+F7173%crkiFyGTQKRFyUeT8)iM+8?VA(Rdaf`xe-#mSy0PF&RDGO}rX&M{ zar4ZFd(#FVdQ&MBb@0F`TL-v9sr literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/blocks/machines/gas_collector/overlay_front.png b/src/main/resources/assets/gregtech/textures/blocks/machines/gas_collector/overlay_front.png new file mode 100644 index 0000000000000000000000000000000000000000..8ff62200602339d405e76673d3aef603f1c68fa8 GIT binary patch literal 209 zcmV;?051QDP)4>P&k58O0p~qj4`OS(nhiw(E4CzQA%N&rcv`eKP^&9@~Ql4c|8OG zF-GaVzXdF%&~An`_+iK&EZood%n*XK)=r6>bI3XG-|;Meg9~^7>lP$#2QxGz00000 LNkvXXu0mjf)e=+h literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/blocks/machines/gas_collector/overlay_front_active.png b/src/main/resources/assets/gregtech/textures/blocks/machines/gas_collector/overlay_front_active.png new file mode 100644 index 0000000000000000000000000000000000000000..8ff62200602339d405e76673d3aef603f1c68fa8 GIT binary patch literal 209 zcmV;?051QDP)4>P&k58O0p~qj4`OS(nhiw(E4CzQA%N&rcv`eKP^&9@~Ql4c|8OG zF-GaVzXdF%&~An`_+iK&EZood%n*XK)=r6>bI3XG-|;Meg9~^7>lP$#2QxGz00000 LNkvXXu0mjf)e=+h literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/blocks/machines/gas_collector/overlay_side.png b/src/main/resources/assets/gregtech/textures/blocks/machines/gas_collector/overlay_side.png new file mode 100644 index 0000000000000000000000000000000000000000..8ff62200602339d405e76673d3aef603f1c68fa8 GIT binary patch literal 209 zcmV;?051QDP)4>P&k58O0p~qj4`OS(nhiw(E4CzQA%N&rcv`eKP^&9@~Ql4c|8OG zF-GaVzXdF%&~An`_+iK&EZood%n*XK)=r6>bI3XG-|;Meg9~^7>lP$#2QxGz00000 LNkvXXu0mjf)e=+h literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/blocks/machines/gas_collector/overlay_side_active.png b/src/main/resources/assets/gregtech/textures/blocks/machines/gas_collector/overlay_side_active.png new file mode 100644 index 0000000000000000000000000000000000000000..8ff62200602339d405e76673d3aef603f1c68fa8 GIT binary patch literal 209 zcmV;?051QDP)4>P&k58O0p~qj4`OS(nhiw(E4CzQA%N&rcv`eKP^&9@~Ql4c|8OG zF-GaVzXdF%&~An`_+iK&EZood%n*XK)=r6>bI3XG-|;Meg9~^7>lP$#2QxGz00000 LNkvXXu0mjf)e=+h literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/blocks/machines/gas_collector/overlay_top.png b/src/main/resources/assets/gregtech/textures/blocks/machines/gas_collector/overlay_top.png new file mode 100644 index 0000000000000000000000000000000000000000..d6bf79a979cd982881df2f0fe56d7578564c94f3 GIT binary patch literal 279 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4%caKYZ?lYt_f1s;*b z3=G^tAk28_ZrvZCAbW|YuPggKE-o$(q3=?GYk)#aJY5_^EKVPte3tjH0#B=a==2wg z!3X#@7+F7173%crkiFyGTQKRFyUeT8)iM+8?VA(Rdaf`xe-#mSy0PF&RDGO}rX&M{ zar4ZFd(#FVdQ&MBb@0F`TL-v9sr literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/blocks/machines/gas_collector/overlay_top_active.png b/src/main/resources/assets/gregtech/textures/blocks/machines/gas_collector/overlay_top_active.png new file mode 100644 index 0000000000000000000000000000000000000000..d6bf79a979cd982881df2f0fe56d7578564c94f3 GIT binary patch literal 279 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4%caKYZ?lYt_f1s;*b z3=G^tAk28_ZrvZCAbW|YuPggKE-o$(q3=?GYk)#aJY5_^EKVPte3tjH0#B=a==2wg z!3X#@7+F7173%crkiFyGTQKRFyUeT8)iM+8?VA(Rdaf`xe-#mSy0PF&RDGO}rX&M{ zar4ZFd(#FVdQ&MBb@0F`TL-v9sr literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/blocks/overlay/machine/overlay_buffer.png b/src/main/resources/assets/gregtech/textures/blocks/overlay/machine/overlay_buffer.png new file mode 100644 index 0000000000000000000000000000000000000000..66a6c97838d7c47afb7d890ca8354bb530ac663c GIT binary patch literal 443 zcmV;s0Yv_ZP)B3JyR?sZ9U?0Z2(i zK~y-)#goBG9YGL9&wYvr`56}mL9!9aCL(@FJ}2w!+yxBAO%?%v!(RwQ2#L>`uIiba zMbFE7;+vHV8ybqD>ej7$yJee~oCPmDyQ|>tvm6OgH*Ri^OTx!b))RoJkOTa9W93wQ zbl*U4H*$x+q_0*R)QGh=f0n=v!E`F7#y*$PkI&4_bRaP3}hs z=0q%j@ZTOydpc^H90`jB?m84ZGa{Z#zI= lMLXMVxw5L;0MM)d#(zP374%87VJZLs002ovPDHLkV1l?Cvf}^% literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/blocks/overlay/machine/overlay_energy_in_hi.png b/src/main/resources/assets/gregtech/textures/blocks/overlay/machine/overlay_energy_in_hi.png new file mode 100644 index 0000000000000000000000000000000000000000..02393fe829a68e4219ad34e617bbf508a56f3be3 GIT binary patch literal 1147 zcmdr~y-EW?5dIb~CVB}(i6Ls?YuG9g4MGq}lR~0CfnaZ8XYC8v+4%;h^92M;!52uP zJF^#V@4`A8G~`UM*FE+IhWY;H?&heuUs~Q+22g4o)Q_c>{VgoYdyCwel*RMI{W_d~ z?jG-NrL%N#(7pu1Re#m<>s1N_n~nNTYkNhNgFzxQfBmR=0fxh&OKbw0ScGASIF4bh zMYUR;nGfa>r0EDkqSzQ$DCA+HNHLL{H=AMf$|C`D#4v1>F$R^j3P>}Ev?C()dOfsS ztqCsUz}t*O*%%=(5hCWX0|Bb9>*Hjc%n%p>iLzIBEJV3{9?ay`6=`x_Wcp+X{KE1A z&{`vx%OMCBuwJWyq#uSw6pNum=uhL3A+RqdzpnAqEPxkqr9*Pj#Y{j2~0 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/blocks/overlay/machine/overlay_energy_in_ultra.png b/src/main/resources/assets/gregtech/textures/blocks/overlay/machine/overlay_energy_in_ultra.png new file mode 100644 index 0000000000000000000000000000000000000000..56b02d1914ebe509958353d7ec639b651b803717 GIT binary patch literal 455 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCij$3p^r=85p<)L71^VC4M4MkiEpy*OmPqix8hV`}^K++kirnC9V-A!TD(= z<%vb93~dIoximRGKAN&#A=;_2cTV&T8E->|sJLBQ?je^y&n!);Ad zni5ivF>`CSBrAw2Y;!t!X8La9?Tt!)i;m8Y%>Qod#(cp0Ox>5i4cX9C43HE^HzqJ4$3#QbQl9 zEb0F{PlL-Z>d01> zaD$C;Vyfjq3Fi&G4|c3;V%lW0c6ZXsiIdz;K6=0B=C&rL`+~|m&TFpgiFLC+WVhQG vwKm~?>ZgneFAjXk?c(#fpT_>5{h0Wkg@&w67ui~Xfy&_N>gTe~DWM4fkB+W> literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/blocks/overlay/machine/overlay_energy_out_hi.png b/src/main/resources/assets/gregtech/textures/blocks/overlay/machine/overlay_energy_out_hi.png new file mode 100644 index 0000000000000000000000000000000000000000..399b32696d30da3d1425800a6ab7f8be5b37ab33 GIT binary patch literal 1147 zcmds1y-or_5dMgFfE*-fkboAvf_Ao=GeAs;G1pk3mR2VA6ebqFiiNEmuV7+f=OZA= z?(C7FwG$6U|d1aK#9*^*u#$(Ar^sUT_B<Gl2KWuN~SK=-8QKObM-e*tyW>em1O literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/blocks/overlay/machine/overlay_energy_out_ultra.png b/src/main/resources/assets/gregtech/textures/blocks/overlay/machine/overlay_energy_out_ultra.png new file mode 100644 index 0000000000000000000000000000000000000000..6989d706e74e7e9ded2728eafb80b32624666775 GIT binary patch literal 1665 zcmbVNe{2&~9KQvJbH74i!AXoeZjz0J>;32t)^n9@ZC#t#(TyfdgMsVaYkRJD@3_0t zcIpHS;0Q7zOgJ);YTfr~;-=8?gY%*OzwDlq~tyOHz21k{jVq@8W?e!$}iX)r1! z(1G69-Gv8y9w*~+I!V^br*G(YjSS3m1SdkWNVw5LcHV`F&%icyt zfP*JRKI)_$tc`I+KG;Y&ieONz7A|^|#o(dgZXRe9dQXCqDju`Fp)s>(uE#Y(d-Jq3KIs z$=@Aot!}Sd_hr|vb3-lj?UpC*y!Lw2=AL zVNU`y}KS?(DwY;d}rq`nWw&vtvE7fxq5nd;>L}4ex9A%7g&0* g{&4M+xtVu=!>+G!FVdQ&MBb@0F`TL-v9sr literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/arrows/2d12.png b/src/main/resources/assets/gregtech/textures/gui/arrows/2d12.png new file mode 100644 index 0000000000000000000000000000000000000000..01de41f761d672cd197306379f1843606f2b22ef GIT binary patch literal 115 zcmeAS@N?(olHy`uVBq!ia0vp^tU%1e!3HE(C6wy|Db50q$YLN30*nkTmEs_ds;7%% zNX4Awga#%@$AkZQPB5r29F}0x5Q^A(*;Qcq#v#vq&N#aB8!1E2rx3VREmQ*Zk{fV zAr*7pUNhukFyL^$7<2Hq{I;bR9t2sfc+AhCXJ@2!*X2l%IeVtF+bZKrFDi}MLYY{g jV9J5-tZS0ih8^3JKU2tebF`&^KFDlOS3j3^P6MO`FPgg&ebxsLQ0LMKfrvLx| literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/arrows/d7r50u6.png b/src/main/resources/assets/gregtech/textures/gui/arrows/d7r50u6.png new file mode 100644 index 0000000000000000000000000000000000000000..3bb3fb7d71174b8872e83a5d17ad59870a3bfb51 GIT binary patch literal 131 zcmeAS@N?(olHy`uVBq!ia0vp^ra;Wj!3HE(gs@%%Qk(@Ik;On71Q;1wD#bw@Q%@Ji zkcv6U0wN-R&KvMBblJBxFL$VGNZfINVRxre!yCmN$J=%-Pe{0-YA+xmIZsMY;+Z;w X#Py)+lkDqnfQ<5V^>bP0l+XkKhcqNt literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/arrows/d7r75d7.png b/src/main/resources/assets/gregtech/textures/gui/arrows/d7r75d7.png new file mode 100644 index 0000000000000000000000000000000000000000..aecdd695f52275e2fd2671c70c1cf209b5d5581c GIT binary patch literal 149 zcmeAS@N?(olHy`uVBq!ia0vp^en8B}!3HE7KWP;LDb50q$YLN30*nkTmEs_dyQhm| zNX4ADS2uDp7;vx#h8O%#RDKzBY%@n=^#^eaZe`=}73T{kJXARB*w)O${SG{Pkiyi{ gAbs>ma>Ncs20fvISb^fpUqEJhy85}Sb4q9e0Pm$H*#H0l literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/arrows/d7r87u22r4.png b/src/main/resources/assets/gregtech/textures/gui/arrows/d7r87u22r4.png new file mode 100644 index 0000000000000000000000000000000000000000..55cae69f6f1c1694f05d952157306d1da48d5db0 GIT binary patch literal 189 zcmeAS@N?(olHy`uVBq!ia0vp^F+eQI!3HGvRC%@oDb50q$YLN30*nkTmEs^yzNd?0 zNX4AD7dLVqFyLVgT)*INd#OjFfSP70({H{y{dvbWd{Rm(yI&BhzvG1ix7GUJ%N9o; zNODg7@Gg3tM~210hb-;FGJXZc6BRpOGT-G@yGywp@K|-ql literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/arrows/d7r87u46r4.png b/src/main/resources/assets/gregtech/textures/gui/arrows/d7r87u46r4.png new file mode 100644 index 0000000000000000000000000000000000000000..458f0b05b42949935bb351b3c83d4068d194e047 GIT binary patch literal 241 zcmeAS@N?(olHy`uVBq!ia0vp^F+gm{!3HG5ThHAAQk(@Ik;On71Q;1wD#byZ#hxyX zAr*7pUUcL-Y#_kmSnv41evLC9TjHd}Q3>IP?@Yh-_`;`S63^dB$6Xbdsk*>woB!Rn z{~c4CtZDQ6eNROj`TIAcHA0(bli;v>Wn2L0yFdtLVZAA_LE VX5XEncP@b(?&<31vd$@?2>?u_S#_E)Q!3HEdXMMW?q&N#aB8!1E2rx3VREmQ*a-J@Z zAr*6y6B?Kt9S{EJxxwJUv|7c7N&47&;rVkJsvG&c`6gwgf%JH~`njxgN@xNAnIReZ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/arrows/r3d16r4.png b/src/main/resources/assets/gregtech/textures/gui/arrows/r3d16r4.png new file mode 100644 index 0000000000000000000000000000000000000000..9ae92750312c030b05acd470b1b419336520ce47 GIT binary patch literal 116 zcmeAS@N?(olHy`uVBq!ia0vp^>_9Bc!3HE_M8)HP6lZ})WHFEi0Y-+FN^uZJ&C|s( zq+(98fQZN+{=+;w4y<^>;GGoOqSLvM!7{G!nEt&E_h}3ale(2wmoH-D0O|E~^>bP0 Hl+XkK0Tmnd literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/arrows/r3d26r4.png b/src/main/resources/assets/gregtech/textures/gui/arrows/r3d26r4.png new file mode 100644 index 0000000000000000000000000000000000000000..b5eb9ae95eed21502a80b7003f67831f0c2ed3fd GIT binary patch literal 118 zcmeAS@N?(olHy`uVBq!ia0vp^>_9Bb!3HGL_9BU!3HF!dmi}>q&N#aB8!1E2rx3VREmQ*+MX_s zAr*6y6C9YEnwtJ!JQ|>4C~|;hqG4O1Md_n0lNUI_Du{!3HEF@&!HvDb50q$YLN30*nkTmEs_dzNd?0 zNX4Aw1PA7(rl$WFj|Qk1iX32>XxLV0QTk}h_BY8!3HE(y2>S5MX3zsT2osj6Gc( zLn`JZCpa)SH8uUecr-x8P~-s1M8md1i_%A1CNFSyQ+0>I2`bmT*ti%HZUnE@oU()w OWRRz;pUXO@geCxhwIYQ8 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/arrows/r7.png b/src/main/resources/assets/gregtech/textures/gui/arrows/r7.png new file mode 100644 index 0000000000000000000000000000000000000000..601cca74151ee746a34ac1145d1aa5952b58cf2f GIT binary patch literal 108 zcmeAS@N?(olHy`uVBq!ia0vp^>_E)Q!3HEdXMMW?q&N#aB8!1E2rx3VREmQ*a-J@Z yAr*6y6C9YEnwtJ!JQ|?#kSjqZM`FKUO&Jq|J|lm(K!4M3kRDH0KbLh*2~7aC{u-+Q literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/arrows/u12.png b/src/main/resources/assets/gregtech/textures/gui/arrows/u12.png new file mode 100644 index 0000000000000000000000000000000000000000..fbdc56b120d35a38621e0aadd58bf8938fbd1ae6 GIT binary patch literal 108 zcmeAS@N?(olHy`uVBq!ia0vp^tU%1e!3HE(C6wy|Db50q$YLN30*nkTmEs_doTrOp yNX4Awga#%@$AkZQPB5r29F}0x5Q^B!&*;c-;E8B!Re<;*kRDH0KbLh*2~7YVU>Dl} literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/arrows/u7r25d6.png b/src/main/resources/assets/gregtech/textures/gui/arrows/u7r25d6.png new file mode 100644 index 0000000000000000000000000000000000000000..ca73d554fb5a30171fb093fd006495a91119608b GIT binary patch literal 115 zcmeAS@N?(olHy`uVBq!ia0vp^GC<7E!3HFyWpvK~Db50q$YLN30*nkTmEs_ds;7%% zNX49F0TGcu{`_Ycm^Eai8UwjkW(m5*T)NdR!P$P#k&D5$)nw+EtNt1wt)8xaF6*2U FngFIj8aV&} literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/arrows/u7r50d6.png b/src/main/resources/assets/gregtech/textures/gui/arrows/u7r50d6.png new file mode 100644 index 0000000000000000000000000000000000000000..fbb46d963e6262936ccc38598b444171e9507f0c GIT binary patch literal 124 zcmeAS@N?(olHy`uVBq!ia0vp^ra;Wj!3HE(gs@%%Qk(@Ik;On71Q;1wD#bw@Jx>?M zkcv6U0wN-R>|+d=c@`A38AyD+62N%)RB*)SYXRRyI1)s}4j&9wXn4cVu*5#7+MrVL PH^>Z6S3j3^P6aiP#X#Y^U?TfF{q8i4;_p{$4_m0;iv6yeyys$vy21>N smecnp{GA@|BKy##MOe_!#X|6*iS%>vd~HLot^|zopr0E87TCjbBd literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/arrows/u7r87d15r4.png b/src/main/resources/assets/gregtech/textures/gui/arrows/u7r87d15r4.png new file mode 100644 index 0000000000000000000000000000000000000000..18ff831765e09475034542c660f783e675c3fd4b GIT binary patch literal 164 zcmeAS@N?(olHy`uVBq!ia0vp^F+eQD!3HF+?cM1Dq&N#aB8!1E2rx3VREmQ*VV*9I zAr*7p-dM=***;3bNAE)z4*} HQ$iB}PtZ9| literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/progress_bar/progress_bar_coke_oven.png b/src/main/resources/assets/gregtech/textures/gui/progress_bar/progress_bar_coke_oven.png new file mode 100644 index 0000000000000000000000000000000000000000..248356608ce15f5bf91dad746476da8c85ae7b16 GIT binary patch literal 2028 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

ZF7ts5!GU< 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 Y0sIFoO~hf2_W%F@07*qoM6N<$f-EPHq5uE@ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Communicate/calendar_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Communicate/calendar_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..26d710c6db0a272640943512a0de27b3aebe7c1c GIT binary patch literal 1382 zcmV-s1)2JZP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-x;7LS5R7i=XR!?XgRUH2P-pt#X*-dA5CRrgO@lp&zbF@V~ zloSmiF=-O4h$v{WQ1oC=YLT8qJP6W56=|d%ym)fc#+dXEgya-TPE}|k3b`mqc6Vl9 zoxktRdmh|PH)#^L_`$#&-uu4y{eEx0`Jqw@y20_|$NMUk%Al0e1ppv~_}kmtn|JTt zt#z{>4-=Z6p4OF8FLBOa9@$ zoL`8dXedb%$vID?lmY^ROREs+``765>BlhHEG*O!5jp2k9LL9cdU{R)z!CufkW!AsaV$IfPKJht4t0Wv zaKJs$+Anb&ODW|D005piaiY(*?eBcwACyvZLWt?Q?)@Z5Mm^7aEz7bulv2D{EK)+q zgE)>+)3hE+sSf~32;oIhl<2ztU~zHr+}POItBkQP!Z2)VnnqpM-DHftNj%RR%=6rB zeT+L;U0sDN%Lbw-8p-p#k8^&NF?Llc^@5Z#@O^)_(P(@vrTi;Nl94Eio&x|45mno< zlv3n*?z*l!NR(1;D^?!4#!4wJrHq9THKmlhwYBwIp-}i^eSQ4{*LC0O?d^T%-o1Mt zQcC}nQfBR{?xs)%0J!>I^1XeKQpRBzK2HcSbX{Kt0KLDzznrG&9Yh>pjHQU!L`35- zE`o?YBBpyzvI|0pOb8L`x-OF>q5b{+-x!ARv=Czb=+UE3DWxh(seJ#lVhR90X*3#} znx^@Lkp0}DQc6QajSwO?Ha4O>&o$0D(=_exJkNixR4VVsaeSn+T&%Qfb>XP3gMs6#y7B48t##N}b6L z0H7$PCZ+WL+S*!82LK?1+_Eg|^(0B!izEQR#>U2#fq{YVl~Q?t`1p9NIS zp6A)NZO;-y&abSj?25Dlhm)zPsR<#(g(!-Sbvc~;qU-wQxw*Od{rCC{~aLz0o9n#XcYS)#sB~S07*qoM6N<$g3ecsf&c&j literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Communicate/clock1_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Communicate/clock1_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..c8a2dd7813c92a61f7b2d976b00da80fda75961e GIT binary patch literal 917 zcmV;G18V$000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-w4@pEpR7i=XmQ71lQ51%s`{7sSzpT@8KSg_g()*75qJ%}0=7ybNh&3m zC5=kTOIne%U|F(+-z&BmwNFvJM3K-XfqTGJ|Mezt5Xb}HfkoS8fJUGOSOF@$+5zA? zuw8CNX-PwpHY9zMv?}Sdq&`U}C1oU~EE&)B*=E%~8^%aSvExMdBP2OVPb3{K6W&mo zZJUdb-7iIS(XkFmdShTslDa*A$L~!so8AanUecvFQKh7}-sDwD0}q+61vC9N4K zd`?@JjMxttW67A6QKC*e&P$qb{E<{4X;{*hPuPs46OtZCTDJX`Z7S@OHO9O#J0+3y zndtB-sRf=zPF4@l4g7G9Yy$6rS?Ab>byt9!_E|7StuZ^oqucX;v@o6{=-4wu?fNo@RDF( ziu$L`yl#gKK{)cj6orsseHAc7ux|-V2zUy3;rAM2Z5w+j4UF5d5oq@EKLBrlp9bGF zz#oFmO~qE527Un}{%$pvj6I$t=qFyea**bkN~LAU_s zCCwS6FIF%cC3Q)O**DvXdb~e6Y#Ts9+R-OXxvb&Y9QM{E`v%8hwa4Hl=nQ(-clbrUxoaFQmmy_tI r0M4_&>(&T`#NIXbB8raxx000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-zXh}ptR7i=XR$XWu*A@Qmoxh#k+1VNGN{%bP)Jf|a+$Rem zg25U#sn>RQ2a-KX1s9LScLWr>>NxqjP$zjG=Q3#;{03jrjB&ne&%BPB=d`JlS zV0wBw{n|j)YV~B2B(HS4-R}lLz>_42dcSCI&Y~^SraJ>ox(Lu`H_r;I%K@=+voGC!#3&Q=`#nTb5f~ILN z&CSitZv%~vj;gs_?(Z8L8{bk@RqgBR`)jRM`#As{J9dngN~KrBF#I87Y@aO4JWW%Y zrYX;4G8>wvU3u`}!Q~q_Ztx!1uUf6v58^nE`}_O<<@^5kuU)$qQvfgwO6fYKR2D+Sj^jM^Jn!t_;NYtOu(Y()lqBgdnx^G~AmE(yaR8trBO|3G zNe(AT5^0*|#c{j@0OfM|Kpe;CJkM(qLbl)Z;K761jv^w25V)?}isSfPxm-Q~0C5~I zYMSOHNfISVa(HB9q(uAr`VKM1Yygx}y549sKEtEUXb=QN&Us39AaVYvPYEG9AtXa7 z)rAmpx7#fdLPi0g(P(@|DP0FZ8Dq9>+lQzS!WKekgb)g#Rj=1W01!faGmhiOX+to^ zpeV|J48!@PvtW{N2LqfCWN#IA(0S*1F(-CJ({W4>mecJuBxhtqG;AFs%DDoL&FP6*YJ^;9P@7`s@Fs@pbH9!ba#bZV( zRV~XJ$mjD{@7}$8834-Vav$gX#VCq=UDqk4bP4D+Y^T%tD4Wf$QcC4cr!%Ok>O}y! zb?a8Twzl@NX_}WxrIMG==dDa8V`nlMJD<;6rBcZ=P4iN{UVnLIWhDgwRaGx~o;OG- zm9yFGYNylrXe$)}{zs~to15((bMGS66DLmWBZNH57<&c)BuTm>g!sq&{QSc$pGu{2 zq0{O7)NvfQR4NrRnaoSGv$ONNfB@k1>CxTdmgXJ7a%glvk@&iF5u&x7$7E zy6*NUR}>|bWqH>qPt$ZDNs`RgC^t=0&1SP#BuTn3H8sVa2()FBlar^?G<~Jp?H+kd zoNP6!0CtI!Rautbo|&1M`?7dXlv|UNlQMuk$t?gM%*@PueYy3x{l5b8zey8;N{oA3 QDF6Tf07*qoM6N<$f&t-7^8f$< literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Communicate/clock2_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Communicate/clock2_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..0a61c50f76337af7b74269b4ce4fb38019856a38 GIT binary patch literal 712 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Communicate/gmail-copy_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Communicate/gmail-copy_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..206dcbb0017fbc9cfa4ea0d907d7326c900e9ec3 GIT binary patch literal 1393 zcmV-%1&;cOP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-x>q$gGR7i=XmQRQjM-;}tSJgE$)iYBwJ-U}Dfe48R=8}Uf z1Tia#2peVBQ^+k|BFRN_3qc48xkgX92qvc>gk%>ti=yJP9un~C67iVi5b)2=Z0~GO z*Hl-%9PHVwiz~b4UApO4_5J!)z4v&;%-D_{I&^6F*x1fE zW!al~o(Jb#9zrMpj5d%EB2r4#YPFh(f+4I%&*%59Y20tRIAl*27|#zX_^k5 zb6FVyJx_p30i{%IjHzg?zqi(YasB%BuqEiokt0!(B;T#9tei^IbQwU{3a|xG7-KrE zR_mAL<>gQA+_|%Ul+nh;tyb&n67smz-xdT|k2s`h`WV2ecDwxqz~>{s7`>c4d2%w( z^V4aXKG`W`GcQfkCwZQqK5^p2G%3S8N-?a?WLg!Qfz{(Kxye3LzXD33Da0~#V@$vE9#+U=nxtxe#jHxynjcZcMKt!Do z!q3*)H+sF^aciv=LX1>VMh^fGLZDi$R;83SilWC^mL<-)+&On(e0+R&)ai8gTWb^V zeWA6EwbpYXgopip|6^+{YpwSJ=mHQ*sYX#0YeYm*6vZKgOb8JHP?bu>HyVwf;yB)u z=lO3%QJn4f``&w>BuTPAV&t=%J~d@YXS2T>F)dGC)h zvlBvGBciv7=pQ0_q?9^btJUgJ6j7FCp-hTUY9|}(hyaA5D0;P8Ef+#WAq1rM1@g;yC_FYc1nAo*WK`b!Oh%Y&PGKQg*GizbmEo6-BW!N&*03 zgT4jO70b)Z52Tb`DP@%BdEa|~hKQ8b`pdDgv3tgt3Nyb7puW1gYP;R;WUtpdY^@zi zDMbk3Z|^;%lv*jJ07OEF3IG;DNGWBv+wDFeX2#^?xmN%Tz4t|yWlTh<*XtyNr~&8!7y?KDH~@l~eU@cfO4;mmI#=fB=Rb?e)V!g! z{?J;B5JHirsTV@Lj;Br6GjmZMLyd?S0M^#lh?xTsC1tt?B2vuEL_{G3-)uI85aPyq z!S?(8+gj@-rBuA3J{&U-0eB)p+5bXWxQwTr9RPf}X7r7j*;gu+SZlr1@Aq%7gBBJR zhD3D17*j2?Z$~X>lQ94?##Dt67Zw&4hU*{zn46oM*IHjT#_TGq{bgXx%rM66(pq1> zdiCo3$RRea>h*f(TdmfNF=ni6sN05>jaV3C##*h`Ot05FztR5;XmN3|AfhwIm`j~b z$CP)*F9MGIN~yTh=@?_oB_YI_#l^*E29+&`lc}kx6Gc&+&9dy^Hiwg?D2gu5&d$y~ zPw$1}*3{Hg1Yld^7J!?xv$H!Nw>I1V9U%V&1&h$1=;#D<00000NkvXXu0mjfK9Y?C literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Communicate/gmail2-copy_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Communicate/gmail2-copy_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..510bb3874bb0f1792cd2341e897dc20a4584bff4 GIT binary patch literal 860 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 IM6N<$f}DkBb^rhX literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Communicate/kontakts_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Communicate/kontakts_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..377848d0254b7ae496a805154b934c688e69f52a GIT binary patch literal 1236 zcmV;_1S|WAP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-xPDw;TR7i=nRzYYRR}h_<-7l@y@?UEu-`bOlqd*ek9E@(p zAq{p@JGRfI&_E&WA>`VYoJuM56eyHJN^|JhmJ_!|BrQRv2jfF7Erj$CD5cO6Tarbr z)$ZT_r-$yUvSXz-Y2R)3&&=CD^Z)yU%nV1t2ywayIrG{>KbEW07wInh-@K*<2VkvuKSY^;%2p4{q{&iGcz-k&1OFdg5aHYyB#T| zI>`?3umqeW5JI?8%1kboyB&t%N3~kb3?!PGnz9Rp!WX-{yG!kMy8!@Z5WxUKl2ZDf z=dCmvjrTV;HhQJB`<*?{`#2#<8@%sF5Rn1kP+~+xW;RLe(#Xij4gh@c+>Ykw=Pz}; z-LH3cc3J?ywr$&)OeUZDMNzb;wbn#5lwJ}2mm#z zR4OH<)JdgOx9^1Y?#f|}e*t>_h=@w5u2Sk`rBW%8@B1gT)`jFUJ{RyZFvi4M>q4PW zI6=%@NMz+`qIW!SlDk0vL-IpGh}cBL5dNcb9RMb|o78AD9$S{xBqIA?!;T3evMtMM zHk-}Iw7I#tok+dI&r5mF_I=-)n3xz!?Q*%CJ$v?Sc91_avk<}&LOj~s+}x&w`CcxU zJJ>Is-XQ>hN~LnTTrPi>+Goz3d24)p{JjG)`&y98<%o#x0SuNPF+4o{hvPW6Ez2^@ zY%z2A?Af#5hlhvDh^V6|`crEiyRQ3+F(wj1gh3EoXt&$bQ4|FSC8#H=b8~Z-!Z7R? zRV$Op$h6#!<1`WR*Dwqxm>C_%dBV(b7>47_90LGot%E3v0%oRSu{h#5&Xv1&@BSmI zDK1~W{As)0ez*UbNK1~077^K6>o6&|001<`ME!mM08+}5l=9Y{J9m1|#J;|?TCE$N z=T)VYqsba0V*0uoV@#BYE;4h>%qlTc5|UDmdY)HpwOTj&bMGUn*XuDNUX@bb@_k-z?kfy2qd!opk}$JaZZ&Z#2~CqLV^eRFknb?vZx yFC4cP78Yy(IMTQU0QXl{SC2n#9mLBHkbePkih5q3!V-o60000000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-vz)3_wR7i=X)<29?RTKvB-@F}mk<}RFPj82yl86ObV5x2c zRtt%V0ttyRny3W{386C(f>di^qlJlDiIRYc6^)dH|Itb+LKaww;7V{y)7ufxpj z15a|ZnSJMc=bU@L^WEF(^?DlGIy{Fp`TG{GVzxo4KE<0=MYrlb2;yf4e z40ho}nP?nm1bsXB4WEefxu@CoJt2s37%vEdT*Yfxtm*x_VAmX;!Zn=5v)G0^Bf4t~ zBAmue{EC+|W^-bntP@T30jk0lxt}$H1tGQj%md;3G%_sJ{3L6C_Ylk{f2gmR^eh^!D4r|l@M{E_!Z~_N1 zuH2dX>ASJQY9TA7Lo2KQ3-94)L5gkoS}4FYHi)y_j@w0SS?~l_FQ;`~L6BGQOD5f$ z-}d2CL5AA{qYG;%&;p+HFth6F?%-)LXUDM~d$QxZg4TmZpi1nyHm(T9tS=JPQ#>x_ zqtvNG>G!7~#8~=__r=O@w{WE`B;zt(5))n8H9_Hp0o9f^f#3W7*UJJfW41n{Q+TIv zsAu8rWfBZaT6a|?_CN`m7YsXtzdf3IuN0EAD!X|gL8Ykfz&C;%Eg?lU&6`*`5?wJi z4~c4R$ML?UYocj4WmkmS%;2L3RSdZJz7oTD)8k!yYsJO)t`QesN04Gh%*|v1)N2rU zy(TkeCNci=P-*fwc~NvW>Ty!xf=7Iul(qtIYWCbZjemv#EtjaY|Mh_U7f}e~*fmOa Qg#Z8m07*qoM6N<$f_xo!ga7~l literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Communicate/mail1_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Communicate/mail1_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..cc862ac6299b03dbe9372a252cb6f805172e24f2 GIT binary patch literal 1429 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Communicate/mail_open_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Communicate/mail_open_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..e3b2f22872c79e3a9ad455f36ef1df98ada77b1f GIT binary patch literal 867 zcmV-p1DyPcP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-v-AP12R7i=X)<0-oWfTVR-}g0*e^Mev)5Sp@ZNC@$5mBG^f+*eY&9jKQQf{gcKvZI8oyZt~`GZ}Nc$ zE+5}L=RD6n?|I(yzJrJ`qD|phJf8or;#Vw>k~}toe;P02xg>cgeRq=V7krEJxYvsm z5q-~WL|lxB^@z9?5i1d~6cNk$yOi&4Wz5CQ>BJj!EZqu*}{q%1GZ78eGDzPf{=iH45RYL``UV+$J#$ZMx209$sfgH!h(BA;&4{=Z z5zkbyCvwS_GG?)g-$<-Y?3(0ACN8!T8$42*v&q{ z2|QYfM`BJls++*eeQiup*Hs*75!E)IWM{In8N7lc z%Gl|%J&Ao~OgT?3;{|1i_SqNMz<0_ybQCvshz~^=m$BUR=sezR1$CW>U*d24)gMvQe9azUscWeZSPUUgb|D<^{G!`CXh;dT>)Y0^Z5@?W3g2LTUPo`8!Z# zeX{xB_Q7`w?sqPT% zWx1z_Voq7U30uPGs;u@+WX@b-Y`ds*-5DC2#Rqs^sqEiOZW0E{3Ot-2{Ik-Nue!i? tBBG3;!$!MqeWUENPTP&Bw*Pg3{0~9Wa7U2hWd;BM002ovPDHLkV1ky)myG}b literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Communicate/mail_open_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Communicate/mail_open_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..03a190ffd133365d838003f7fb1738a5c38f7289 GIT binary patch literal 1398 zcmV-+1&R8JP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-x@JU2LR7i=Xmd}sVMij^2j5Cg%#Iv@Ot)PEE5fZ(k?E%oD zf>wm2`{UBIT#7(~p5TZo)K*o+74^UmA&S~Vd&rLs&{YvsNPCMANJv4ji(1;!<8FRU ze%RiLXL?v?>kS)N)F)Z;_}T9>-+9k74@oIuJGOW4-qiT`_%0!Y1pt6CZmg`VEI)Yg zV0Am+qt}6EW@aK%%0ry<4>{+%ecw+?DWd=Y2q8~Vlo}!A86o61gwVbD`T71^gJx!C zj&jb=^m@JbUDp+yb5{t#0YCu&5vYm~LNra&a4Z(95<)J{&(Hs|Ezs1|6plut-#U)- z8DngXbKV>HG)>dv@p!}c{RCr73L*S~j}Q{0l&ZR}-|#%|i#vDjh;UpS9vnDuAfjp7 z6~@@fTCK)7=RJfF0szo;ohFmXmz2_vOw+tz+cw1*E5R}%&Uvp^t1-sdNlnwP?BBmX z5{|uTFg7;!O{>+KWsI!`@j*%{bzL`X+x}Bk)nkQ1;co!AJ~uZP1%NN>^*WPM`oV+* zV{8=wW=+$q0l>Le6lJs7wClRZ8Dq5of~1t7>pHb<`>$v;nhPKR08lIzFC`L*uWj3= z2q8tT=KvvufH78cUH5no1%{h02HO88zbq&L4Hk(cFO^|_Un&ujYQ743elyXpsF6Vsr#Kc4j+qS*S_kBwU z(T8;si9{m5`@Ub?v17;2>2!MMn;^Md?li_Y+ithNBZTOK=R%0S@B5ZzS-Y^5(h9bf zjXxJ-94{7&KY5;a-89V~j~qEN5|+#5P9ublK7IQ1gy(rRAp{AzWf0rKBfdxb_U()0 z^ZBCdx>qgB`XQZ8zdH)@;>C+k9zTBEQxrwtDi{C&MhGaLvL){mrA8#0K1+}r+4OZxf2MX zsprq1=N>(J)Eub-jx7)pBn&z(naHv|X9((xk zAsh96@SA9akY|-jWfceHySlF9&`vHf#;-ujs2^ z1qe3PPN#D}9*;licDwKO`+XlFBr25(-)g1{3k#J|DiA_0#u%iOQdQNMuIo=aoz8uL z(0P=}WYV7JeP6HFJCxEo#`v-jVhx6lk`X2qMezXO1IKY@d%d2UN~KIq(~jS|b!%Z0 z2mm0P&0c7?+b27nPF+=11BNQ`O(uj`TU%S}QcA}urPprWyt#2qY^t5UQX+&frSzS#v9VI4(KsLWZ(5ec#l=2C=oF>&S~8iWs;b6dJ;4$o z1Y2DLzpAP++qNmC^cu$a)Z*gerbcCCb22?Wo$2@cXL`Nfo=|hrhyN-I4K*iEB9X|& za=Cnat9Y+%x2C73BLJ|ib_)RRmCNO~Z?}f+|2B~S0!G%AyAWubvH$=807*qoM6N<$ Ef000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-v?ny*JR7i=X)=!AlRTKyC&wKNm8FjLhQK4v4Ns#}7B*>r; zf-*M|EgET&5fp@NT$JG6sKD9?(MFd>fl6S1poP$`RsSq-QL7-erhij2&zawAanAMq z=FRi*rVd_u@(#T}4Eu^t; z@G;I~@kT(cArU=^S8*?vFrPqWLn|FwgE4%G*KuZ4Lv0+#3+Q03so$sD+&qN|yoE?S>H*+4l5RRVjrZ`J29@nTeZ5lN5ZP^J7WVBO-5WlIkLD9LwKV^ZP3|T4OT%MPad93-d2W5A*SS}1s44&J0r@W?ll9SQxiH@V0000< KMNUMnLSTZU^P}_t literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Communicate/mail_sent_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Communicate/mail_sent_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..24e72506b86f1882c928208c39cee9abddb2a308 GIT binary patch literal 1526 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 Ze*qeiY|;I3dJq5r002ovPDHLkV1i0NG&2AI literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Communicate/note1_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Communicate/note1_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..4ad0921bde9b155fcf66b356fce98461b864c173 GIT binary patch literal 899 zcmV-}1AP36P)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-v{YgYYR7i=X)=!L`V-yDP-@S7?)0(O@o#}>Ps})+SiiH)S zC1pcrg-C3ybfJkR7XBkzx%!CJnuQ@d7tyPBEp0=k87}}-haheoS($GGr{-6xDD49$V`1(DX`D+E>5F6 zDo|@oMt9=`uE!ddD^Sm&RU6rkDSV1&@aCjIZ9IpEu!@V#^#g00&a;@tOE`}8aX=ls zjC*BS)`tWiWl@{lgV*tZMkxn-^em3yTsdtopi%YhZDLJk-@;#5kR&-iETf}%4NCUiq7Fh)@!IiR)pWvWm=`p;Ot0F|ibVPg<5f>ujr-(Qg5exPITtv)|c;+HvM?@Tn zh#$*GM7$jls}*xPA~rI*v+BB3<@y>o;sqS4a*WDmrZV{qAJ_X+RfWrBzfbjgbXcDy ztt!`yr1t(1K!Kh30Vico?y0~lk_hV+`&6fD*$dX|MZ114H=aR|OQkYAf#0NR9Fe5x z>Jwu><~!IYDY-VHJc9tR3t!^t0y&5WvCU@ktX1rNZS1ZxZ8~6MY?qXsUM7cd08h#T z+hpi^#ooP@)(vJeTOcQ8c@9X~If~zn(aw%!+KOy!GplH<>D2oLe2Bfc0*{w(N1nSu zYuERs4$erq*=u@yun%P(+)WK1ucDap1EWK(~} z<#TE;iHRW^BNId*M6S5X`6XHO@i~eA2$z!vi zM0Ic;J&%Xwn3$2Oyp^>I;G#a6=CO!JHWm#Te6L8o`o(`6d~;Hu@7EZ7gC*%oQY=d4 zoz-X4u;JJIHd{W66=TyyWs=LubuzPYmy@;}6aVUR(zI>3-DKCTcch>WwXJ}f_P;KW Z{{WIlL$ro|M34Xg002ovPDHLkV1kZ_p!5I$ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Communicate/note1_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Communicate/note1_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..ac5935865870b60ede956e11fdd898e2a49b2d34 GIT binary patch literal 1471 zcmV;w1wi_VP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-yIY~r8R7i=XR!xW$M-+bb(|^-F-P5xxNF+IG1SeiZ_7aRs zR+qS|yGsHgkbr@J>*(_IfO(INr>VhU}k!I zx}E9i>gukSLuO=Fch{9XXy~G#ZfTnK10iH#c6K&@YNF}s z=?N+2(IiP~X__i2WvZ0Q0ieHuP)fO`X{KqKv{Wknu4&ro+1c4k8zLGXAE$<4eA?}H z565wwNhy<_0^z zAf)ATxmu}I&WB<6?&9L&Ls#;_#h&MV5=GHW6h%!!2qlD=8{t7j1ppZ#gmgNcE+OPq z&-0o9@Zn>M4jw#sAWhS=K@hYUW7KgRMk&1m01^P!V?#tNNh!DJx-K~9zjeFa7YxG~ zHVotN+}zydheUh#?$vGE{=V64Zk1A|l}d$`%jIKt@7}%GXf(>}sk(pvelj*T_M+oB zUxi`#@xsEwx$*Jw@8UQf^?m=>BuQSmcI{fm0RSAw8BLO8N0wzR#+bnv`?FrJpPQVV z{GwW|?ovvnYe}iqYP#on0ukp*r4pT(n0PbK^PNJ7l^sIKb-5d|U&01$&jN-5NJ-SIr{HX@!v#LzU&ZE+lr zM^PjZF(-r&DP=09+&(fgGR&*h>NX*S-%G|P86qN>rdjqp?+*a@oKhOvw!O0`inoFw z;7TdkPYI<|UKEAz`~EhHh<>lEJhA8@B3PDHu2d?wlv1ZS=PlDTcX7^ZK@gl`jOnm4 zLa~SK^EEJ6m7?o1OAL&S&>vL+rUgoK0;0RZ-(DndyA zpCckCgrMU%v2EKw<#|5b>2$UzrQUz=;6Y+p7H5pHq9`84Cq3+tE-x?NW{icD(iNu> zLJ&$RGRE#HrS2JqK{)5LaU5SNisE%4#Ct&yBuc5gcPEb}8>N&p#=GTT4qz zP2OX^Vp-N3Y5FiPvDIn`0Qie@K3c6-bwsog(UMZ;jIq>loPKbCrfFH4rjL~>%d#k? z^a?<)sJ7eftF~?5>~uO?rIZ2@pWVNI|MPe5-1&@i{w)AVL{vpl03ie@r4PZfEQ9OU zum3SIF>x#m!$CDA%d&2^+wH3W14VUma`J!>;%pEEEnU~Oa=HAEQtE1!Wr7gGRt=^9 zTveE+`COjoFU4_OD5Vep$k5PG#Wc;gFJ8QOc?A&wz@bBjPR4QkP83B=#+XhiwKnif z5JW7BqUiLV3vgX`*md1A7cN}*pucEEq_tYD>)oRt%G_BMFKtc$t_VwpAO)FKaRo8XhGnCRJgRg5} z_NvF5nwpx-^ZaO%Bs(_PoZRG`pRU*IbF1O4+ip!wO>qF&P`d>H3-x;a>D#SG?f*8A Z{{oyW`Ta41Jv#sZ002ovPDHLkV1nxxv||7O literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Communicate/note2_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Communicate/note2_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..253a81d6b72a17be7ed32964ca55cee5f5779f0e GIT binary patch literal 920 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 IM6N<$f{LVlB>(^b literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Communicate/profiles_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Communicate/profiles_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..0c9aebbf0fe2bf904da6b3807d11ddf7611b0a44 GIT binary patch literal 812 zcmV+{1JnG8P)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-vrb$FWR7i=X)-jA!RTReY-@Kh&L=;1CF(I+A1dMhjR)&Vv zZPdzE3N0)wv{+(dXCZ~qSP%-Op`en41hAu^Fmw>bXwQnS28}GR?Cu@h85`q3 zot727izU2@O*~3ae?li6c?vVQiIezlTA>D~@F5;!HGxm(eFOhif_>YAIh@5O=(P!T z@h#rNpXv2;N*u1^MhY+C*&$e@llyT2$JM_wBI@gOM65@|orqY8h`%G^R7AW~eX}vIgv0TS;&+_hfkex@%ZTgIAvjaG) zgkg8GSNd_dY;;Wik9~}T%F3H$58&S`{bY}wt!e=u;h$vPO!h$NvC_2qDLqMS)c7L4 zQDPIxI+^Tkzw08-;Q1C<|NZ^y`9*w*^9g^Hj5DgDJgV`Xv(@-|wx@c72lztSkgwql zyrBH9P&V`hysv6}qgwe4zOucQ*Va+?+-!m#000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-xpGibPR7i=Xmd}e6M-<0jy{ek->K(hMXLmyaISL{e1Ov;$ z5@bwPlw@^A|A8dr5IiJGAP__d1aASoL}H1bBZ7yb2B>^*z-?D2yK4?26< zPj&+}8V#nkUX)UPAf-H*=lQhO+5i9`gd~*GP0slv&iQYIkh?1@E7>c98jZ$BQp)pT z7`_w7u}af4R!U_6pa~%W00a>k=iD?+6D`a7i*tT;Wo6};J%LV~IDv*?T#lmX6VLO~ zG)==oP*6%4r8G;D#Lu!!7yC5;0O#DYZM!6d_&G_Ei??szRue%-j~->N>s}iS24_6a z+XMh&S(Yt?=rG3qK*T@OG!3&XyWn|V830CN1rTl9t~!p>>~_27?%%&ZI!ZQ9bsXor z!C-J^Fc@?gW2H)^!c5a#CWQQWI(6#QhjAP)Z*Fe(DW$wxt>%_xoo_aqx5k}0eE9I2l}hE;AP5`)*y-nMtu>jR zo~{^%@oBr=z6FI>P^;BSN~sH;=Oq9@ib%fL3K=@L!?&&L+Vi|bYki?stCdEea=Cmg zilReFl7v%JQ??M|daKo1eTm>?5+OuN8Aefbs9Y`|8-bKk$HOpGh{%KxPt!EL_PUU9 zi=s#=rH%st;QajjjFj@Alrk=rN&*poUtL{&vdjKGm69T=SW0tq z=NKUb7-P9R@j?FyJb)oIDaiJ)RLap`JjIpmA$H5&GPzVwDzJHEV z`cz6uw>YEA<#LLMH30bD_x)(N#t0!jLP!DtQ%WfnhT%S#aD}zjln}y`Bzdy2vGLEO z<2`xuWJzmX0)V*C?qRpveM~9sAtEaPd2u8YAI2El88LEbF3U27h>TL&>-Bn%aeaNg zQCIp-$l{L%XQdItdj5b=%>V%tA?9TP%)9!1exN~z4U zEJVaR07b(3zJE^$@sM+Fy+Tym?DXl=?cf7 z1BzPp63uPvjYi{mnx;SW`+Wrf+O};25wEPRt)(Ln06@Flz9ocMwrzX52x>c*k`u+YT*L7zAVA%Ln(PseQ zMV=rc?%%(EX=!Q6$n*T&JkJ-RD0(9Z0uKPR<2bX9<1~A{-lcKvZLPe~Xi%lph=0kmSyL| zFgz5;v651bhLd6sK}1$6m4?H~L&n(ER;$(CNpIJ2t6r}&0NB&G1ps$jt=6lLTU+h_ b4v_x>8On>Ri>=cA00000NkvXXu0mjf$#Yzg literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Communicate/skype_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Communicate/skype_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..690619adcc3ca25f6e8731f37f4297f19cfac459 GIT binary patch literal 943 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Communicate/voicemail-12_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Communicate/voicemail-12_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..dcfed9aad9d5e2b943ed41a1345efe78b46db47c GIT binary patch literal 822 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 JPDHLkV1lJzi2ncp literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Communicate/voicemaill_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Communicate/voicemaill_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..4fbe387f63113d6adb1b5ecca92fd9c962e1aa93 GIT binary patch literal 816 zcmV-01JC@4P)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-vs!2paR7i=X*1wCCXAlSQ&%U>wnp1;#3W1b@KQWLZpp9Sx zMv+LGsFm8-1_ENGV3Fbou@R%Bi69|~g*iAl?ZhIGDnXM|@DH$2IR($tbAMROyzYC) z-m<$6yu7>bGxMEiX1+7eQ){=|`jm~>h7I}uDIVZ)KgRVw)(_%K>`W&sbM19H`yaP3 zjmC07wH^_DjWhTJO}t8=(x8?bS%neY#RUHB*HM8BIE4kwRrQzXR*lCnil6ZvTD=_A z@e7WKw6wZ_FDLEX~C7TuH zl9s>Xd@4`jctz)1T*nsCcR%I#YX3A7dwU_+v2uyRJU+ud?8YIS#kt(^hhl1+5^4GZ z-v~0js^GK|d;M~=t}U3?z_a}J3@^pBXo?y<&$Z`iQ@40pypy_MT1m$;s@3=lGx$4y zAHgI1DDq$68g67nxAC9F^(qp3wvPK^+-#~iT9LaxEaui$QLh@tQ)fDX*5L{+=J%0` zqmjhEUl$`|2A^hHRNnLWzFR7K$eVn(MP_F3xUA8%4x<{_jE{7v+OIV5u?}mC#O^wR z=0xpY8gAaL5@{dPWdtpVru;1(H1WX@PNZ#3(0U@V7abFmqNw8{zl}5+oopKjpgGnO`&5@XRtrJu{mE)iL;%SnNI u2E3e9Wd#oC@49tUr-uf1RF(I-K)wYW&EXwQCuMs80000000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-x$Vo&&R7i=XmQQRGM-;}tnccB>9cLUniBzc)mr7WXs4De< za)3rq2(+%PYy?rst@J{Bfm_v9oG3j}#HoiOQuSCh;1CCh00D^_DdkjDT13MExUz{I z%YSw~yYqU$P7RHz(>`f0`)0o1yf^cn9wQ=jV>@^592guNOlz%^0KhpfK701;;oZA; z-EQ`?SAiVIF^OouQfi-4YA6iDejSmbv}ezrNKa4CRo8X5E2V0dWkn3b*fNMQh9C&Y z^E_V&(K9eG@MpDJegF3D+YJ){;_>+2TCKLD(P)$`%Zm5*_Fjxeqf@n7EkZ<$F-AnR zDY)fhjFD~I%J==_VHoafG#b@;czA%PQmJ$phDoh;(0a*?u@C?bA3l5`5{Z0a zn&wbE9{Ds6tt#uHFVKSLara2KMn{8#I zpu#Y$XEK?$iRhijk00-!o}QklR4S(!W1nr?woUBXwMzmxQLR>wPft&O=(=uBYwhgb zy*o`rep}Gg)K2masU{+_0ECYoJz56HX1+O=!TLWn;`M@Mfuj&oKBaYiY{9mhGH%jLfEJdc^C`Q7;V z_&4cvdd@V>pYPnc^E>A}+NRH%+C{#$w)W64j3VdUY#oM(3?kA`o;;asG#Zz*)^Q^G z3BY2rgZDAUt`pI07>2z{sS7JBD<8Mcxe*2DrePSxVzKzpTwY#wGnvc-A;eo@7&e+~ z8UV1gv{VOhrbBu=nQG-;2w@2!9xN{}yJnMo-L~yX&-0+Q4gtI|IXU@SsZ8xMJJ(l$5d` z05Qe_##p$;F91MN%6{9nr&^E~KmbrGl};uSiM*6@kcfDvn%KWWHk4U Q000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-v(Md!>R7i=X)=!AlRTKyC&-?kDF&`2#O@xa!(IP8Fmj>A~ zmBCzuiHmIGCZY_&wQV#6r_Cg|F-6ceY6#X=iZ*RD8iQK2(7>2NB6R*Z^KOfKe!lCk z_hz1T;PT$@-gCa^+;hL@+}lbi8B)ga0>TDpC}2T6(`$M6N-QKYhJC?CgL@&R|laVN&wa5^a0t+1I1jN^lLv>O+2SI&6{ zcQ75_ZETUxeoE=L_&pT!&C!Z6XiZA#)0EP^0&60r^ze*!Hq!A2cEv6)=oM*-F^2c> zG2SfJ$Skc1)D3KvT=6erR`0M=r14d}hIK^{TVz&sa2>DU^GFr>JO$QlV2@YW7!fWN z3N5*Y9z=w7w4*o@;}|aD1N?&b8#@!2W7t^9>=-qeNu@lGzwu3D{tRC3zj47 zk}P6%pZSrM3@f>A=KZ^PYbhiAS&njlL+22_jsImQsRH|M8#m>ec{)I9GOUT{pDcpt z;v;;9ZTJ;iaSJE=I9e6hH`{W{m=1%5P^==tGx$A}Yq^C9xszediPM;= z@1v`DyHI!rXYpN;g7WTK!k3N6>-lwh#Hs?jZws2mecaYdSxxy;%Cjr$?^!wJYZWc1 zY^rbIyiATtrsdH0d?E8;*SD$GGKqKf-T}kjMYYsmVRb~zD1c7Q!=ePdb#hH#&WF_HdBG|$U|kA$H^vnXUjcKD*WIvA19@(#ty?hx4ts? hLR`^NDgWyM`46wnF#yeHONjsg002ovPDHLkV1m=Dngsv= literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/Camera_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/Camera_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..77154afd6c5a2f682e93cc4f79b8939006729e80 GIT binary patch literal 1390 zcmV-!1(EuRP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-x=t)FDR7i=XmQ8G1MG(hl_wCxxj=hfUxDpbVREQ>WA-Bc{ zq$(9e5lvjDQY7jNq7qWoQzf`mP;o$rUVu`ma0qG-NJeTa?8c!)Eu~5?m|Tk}MdE@$ z5j6gY-S@eEI~;h=bwa)>=C<$c&Tn^T=D$M_5%yw-4jmfGWHJYoQb_;+N@?@aqel-{ zR#w*bvYzY&nw_0xi1><>@?|OIsONcUL<|D}5JDVH)9Re_2b}Zo2qCx2<#P9_L9?^7 z(^ASarfI%l+qRNY+DfS|00avNrIc~bbzRqKG#b6nIloXYmlyX0nwpxT;c)l^%d*~R zx7)6i()3S2wsL^J1I~F=2oZ`zB3B&8d1q;9No@-{eE2X+CX=77udg3(x7!T>Pyo;a zY{TjYQXxbtkw|>qXf#gWyLYd5m8^eqB9VCChpYhrP)Zr4R1dDp^E_)ayl)c(5tYC8 z_~77R9RSY$=S2B@{-|x+m+SR<3jj36STq)k{T&L0enCWvh?;HNW2R|_2_ahs77+mv z9Yj>=bb2rx4xg-6tKalM6B84mfq{XWYin!IE2ZpsJl@fDy%7q9zAcx_ANxCI`Fwuf zvaDwSKnA}1PKSgLbX|A2)9L7pF@0!g=vTuqUcGzwuFC)bVzJl}(=-pduG<jdeU{>Gn%ITRj=3IT3K0X1c1rO$y6$pnxmAayWQ^3SFc{J1Z+e!f>Tkn6cLlYtn4a!`}gmE4iSw$ z2mk=AuCA5SYX8^Pj*g@r#$rP6Dz>wa$-hGE-x!sg@q@g8rZR8$3ASg+iwQX#CDI}4iE$Y5JC(IA?9z~ zxY2tiHq=q8)jF3*B+5dF3;@ur#B&!26+&bZiA1^8YMtx6X3A%vKxl%85%Uf$5CY}=d^3Wb?&w|mAk&4YVvPJUvHU8qzl)vf&P w*lraH1qJ|nYPSI3cBN8z`gUux{oe-iAGY?$vltM81poj507*qoM6N<$f?;WY3;+NC literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/Champions_League_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/Champions_League_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..23ffe9d5a907c6147c6cb8010dbc6b06029f26b8 GIT binary patch literal 1119 zcmV-l1fctgP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-w*-1n}R7i=XmRX3FRT#&A^Uc@jxDYCaR%S&7jUp{XQ5Qnp zq!KAXfna5{KoEpobQ4r`QC`>rUJY3YMx}(%;!-z7hN00SX<%x$%(%?xSj>$2&GPHw z{6FVYW^AAXhxfeidCvbi&+~tlw@GE3VV}CJlFEBq!CS>ny zl>H2B1GWHzVS?uC?N*PfN7Q4P-Pt=G*=1wlHI3rB3h+AcBv1qTfGNNw z*{=a7fu>kj2bc`B0PVmkV7L+VLPb^JUEra(#VFnZ90U#nyMQZzHNd4nGcXXjVPHD& zA+Yj1S6*P^8)_{sIvzK5t8EQ3SE;MiP3j@_bM-g%K;%2rfnc4(Zd7u=+TXy#2RXD> zeMw!Q&QbqV&#GOK-KZ{6=c(_9uZ}#IUZ|)=-KqAded;sno$5jL4|Pc0p{~niIvVDn z`e|@3SNExZ2Ww}r&ndbu06pq6b-*HEA#l1Os;Y^`c3^hCe-G>jmIAwhClVCh!5a=XRZ7OsV^>_g$ zC3KGiuK))UiFW{Nftv&R0`LxS8*nBUod?XU0Bw|v9{{H2@cxA9p> za_F^O<{zLJXaydjA=QVew@NNP&n#|=0RW% zaCbn~0JrBrCF|=czTcKh?FN3zC0i-gV?D5y!qu!`_f&y>lpwe)2j&BR0edJBQ=#y5 zhSDZhMB!ZE9!l+71H8&e$ypBEMB(ZLu&+w#CwqZgfPM-mE3-Zp*VQr~1g@hL)%s`x zUW{yezCA{XxYl5I)j8Udo1X>liqEeBzNQq}AxcHwmA$$G!b2x;1b7&DmJ(^TU~Ykt z>fHi-71#7dV33lKD=6f50-Jy(6khA2m68rqV{L!tWJ(8K2-NBp)hN+6AvbM~dp-+L zXXLhJU8S^$*}&Vt_FU|6yiy6)>R^xACOXn4PO1CVm(_{tqw0_9F7@eD{Cch2-cSc? z7i$x!Rdqx9NxhhMr7e7+ewp=db+P(@`jMrr_vFk#FshB%qqXv8O1L(*@;Vnolv33j z4yH$@AD9?-wFA#Z_S_gvQGF}}o(C3C%F~(fFdPo*b7G!*!pY{*z%Hf;$`8pR#`n9m lHP((g{!3Bg_+LMe{{mcYQ^DCmL~;NC002ovPDHLkV1i|(|HuFU literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/Champions_League_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/Champions_League_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..7737680a4f717ab14a4a4ab5b092ff3f96ff8b34 GIT binary patch literal 1945 zcmV;K2WI$*P)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-!6G=otR7i=XR&9(_R~dfK*ZrEAd+*H7QYoP^sT5IasgZS~ zqy%Eg3PaeXV2EwvN1{J8nwn^A(=;|wG%=_k!2LQkr54zp% zxzndl_ipArx)IUT)D+cP-z$Xph!A3plyXFCZ2|xwgbG4PpE33tW9&FW==tgC>GEw8 zO-)U;gb)v=X?katWl9K*_LHt$8la|jP0AAo<4k2L=zJe*fh<( zS(be&iXtwANC_boN+~0R0Hss_z#vHyB&9R}Km!0U#vIpm4coS#E{fujqeqXb|4FoQ z<3?Jq*PjZ*aAz2X0RU**wo#>0nWvP#0RVq<9Ovac&uReu_sEeW=N2HB^k03N2|w!*tX4F*Zmsj{FSmSf5P)eJoX@(eM1ONnM><~hNq9}g0ZrwU^`0(LNrfJ^q zdEN!BwM^4=ZM9n63;=)u0F+W&vMf`EVPGM|vtwgp_a;fQp(u(BW2^xHwAQrS?S9vB zoM%QxMwa`&uRYKEBV+75=X~3W6)S$%YPCL*Bnd(Y1puJ3EK^FUEdT&?e0;p=y6zew z1XoH0)oOJ&V{By@h6{`R(~L34aU7En(mi$R)VDWm*zh_+=%u14*5`Ttog_)_0s!gz z{#Ojccs7pXyQP$c);bqLtQj94Z{kLyv06%5*IIKaWkpK4UTb~cw(W*#nvUZ*dSqne z6~}SDXc)%pyuh&;ot#w^% zZECG`wOXy3rum~djt_XA_gBlZR$z?p(po>&ZnuAP?J8)kS8J_rQA&jfA<$ZbQVIdU zWlE_bgt$#9RV;p}j;}t%7&F5#E(SrcuhZ%LInVR&6GCo_qG)-Z=Rat*TE`|PCf>QY z*p=DY*~5g8FVt!^000LeWL2xxx?vdYMx$||R;zU}#$;(>5kdomP@$BPQpy$0X7e5Z zm~$NGoBe)&eUc=X0RStdK46;W?OV5Q&3)f*PfSd_skMIDFpRUV>oQ8IW!v@}y$(Gs@v@>Q4AV5Mbc{s+4+vk|a;(dA^4+cDYiiR4Ap)vMj+En~I`nbCzWTDP!{KnOEK7wkUgmk;FMZ!n5kmI?z{5$B zypMDKUH}jXAp`(gDMgB+xTKW&=dNA5_GDRB&+~jlN?FuuH49^WY-wTRIDXM_oU@EE zC(m=Cl+uP_3@Vk%=$SKT_A$)b!_=!%Z!>`k$9Xob>D~h7eL{ZeE zlrr14nPpi$%d&oD+xFvGmhH^4?DJY{P6*j=S=K+Mr>Bp!TCI;FggzSt!F#eS1JCnD zT-W{a?Ck84O#GW3Ei5cNTCdle0I)NPqJ9)bB1sazTCIMGbN)dg1dZc(mGAq1LI_=y zQd--#ZTmUrd_0b0#yKxM&ue&|H$4~(9=$g9by7YxHAR$Cd($-iw!9(HRZLD!ZZFI7!8A?R=6S9- z=egFp1ONp9SZj?i#)L6u*|v=x$2m(W-8VBcGxy)(-Oz4LPEJw)xGB2@0MF0N%)EWO f^`H2E4dlN7AXE5WZ@ify00000NkvXXu0mjfd}*Da literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/TV2_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/TV2_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..8ace46fe3c10071c5d7a8499592aa3309565ed95 GIT binary patch literal 1001 zcmV000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-wV@X6oR7i=XmR*QdRTze!vuAtEj+CP_m4P5iazO(x!i-GmT9QHl_OI%#-jm$??K=yP;EsyZ()BsuoYNul7-$IH`(vN z1>ig|H6Ku^iAOtuL%>tOG%#kMs8F&Y4*+ezufS)(x2+Ooz~{ibzyxqFm2Z$ul`B9Q zI0hU5>dlC9-~_OX5SF@$7n^X}WKpT&f201N5yE>0=phMZ)?i^Tu$z$JIw2$@z&GAs zkdQ0^egG~L!dJ3R)fm0AeV5|%vZPT-xBT3ebVt&4NvkAnmGrNqs-!VVrzEvW`dZRm z%iogpx8I|Zc0~M0QkL|Sq+v<@l7=J=nrKAQUy@cz+9GKpA^B3$q{*u`4I4gykm?rz%`0qtNTB>71t$|6N_Lou+NoKa}hiSTyzBvSiT#0 z9{3YDnxwyE%ymF#4y<)aPA3AHy%=|84FC@jnl=ZXvoSgF3$WVN8TI3uHul;aXt%4g z8Y~IpkA#`_vyHj|ya9Yfm;xW#n8sF#p<4*FH=A`LOol_igTRZxL7)S8&Ce&m`?k8j z2^JYJLl>%CAXD-0M9s7CBOS^#H2yD*t&Z*>SG%*;Hcd6cb#G$E;4pC zhUjkoXSr6e}}R9W(4Or_)ZcIz5$BFwz6cyI|wuHZJHc>Q@~rmVZsot zP?YOjmy2|-Vx7arm~~NU<#Mu-B0Te5PBP#(?(=ezt_8q0TDxw2Pm!bhCQ8@;x000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-y(Md!>R7i=XmQ83K*A>Ulxp(fHk2mkmd-J45;2KjCVhrx0 z)G=C=IyQ+aD$7V<OSrm5q`>;#C(7fzr@TyJ!}rn^3i@hEnhomK;P(fH+H zFnBqNqAma!#u($A`&#SR7^6!X5fNCHRRsX8wN8l$0f0#QGc?EYPA{$L2zqhW8)gS@gm8V|e+&Ru8Dr0C zt$#;Et@ZWwwECdi|RZA3prS+}zyHl~S)G;);~= zMMRtpg5a%Mt(GDpAB{#ynx^M`-@m+7Nl&1<#V5+csWah!EJ z9jTQ1eYe}4IDPu`kA}nHcL#&Pe~O|wTNK5s^?LnVYinya7-N4&L>mzyO;clxnE?Q> zrl+STq?Bj#JXd8!86x6Z>le~Ay*?U^5@SqCM5fp4J!9MUYM$q@QmP98u(PxCb;j5? zf*|7^ZFbvORS=K0<5z6XeMNwpkIP^Ski!s(^jMcQ( z3K0b&KA&Y7^E{8+w*42S)M>5taO^)W0Aoy{wQe*TjWZSzHA-1I(78keoO3RO_@n1} z_wV1o|L0SuPMxtV>tDv0?=Z%GXxsLUBuRekIL8cIRJPI0Dkr8(W4K;FuXS$4u9(V{%cC9kcc$r{7K<}Az}{^v;9{dr@$Bk zX_}@=sU2fX9LI4xNs_OfJbChh5aLp;R%>Qi_DY(j!^85l?-?=x=vm!v_konM#~AyP zF(xllNQh`L#vI02n&-K$R;zC+rJjxBxMNw?+ffuv8exw^>R4*mYf2z8(fa@cfArCvHk9U$AX^+4H(uvs zR;g4z0{}%t)g(!#lu}0(4EnymBZT-b0Dv)ODvo2BWm$e$g7(J5{QUe}mSroQPNxsM zL#G<3sTCa>$)pr$N>-lK)>IAHwc23lyVYw8}N9W3zU;^ckoRHLD1^= z`|s}megL$&xmh6MvXt_JFbt&-!lUt|dkTPvNC@GDVJM}PA27z2H#avAEGkc2P8Jpx z=8K}Zo+Qb+V=gCuvn=cV)z#ItqvAbv-C9^!umIp#>lOffvbwtZ#n-LF=l@+G{|Bz2 VX#vYK=4}7~002ovPDHLkV1iAM0>1zN literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/TV_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/TV_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..6ab0bb1953d8a7e22a9c9b0a5cebb8bd90fc5fd7 GIT binary patch literal 959 zcmV;w13>(VP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-wIY~r8R7i=X)=OxdRTKyCU%t*XjWNbjQx&un!B-Fkb)~p) zBN{2{N^#+1BL!D=Z7F0p_b#TepYSD) zVres=p)D+W3@_piEaRU9>RlL0MRs8ae!wgEWKcm3Uc+-(#NYM#zO(h^QS8LqcmXS0 z32NaTJg(5vJ3N%Lsf0!DM&^?YP@oBL?LPYG0h+`3P zE+V=S@p44$&Asi+y?M8rSjQ53RnUQmn2(6rh&UAyBmY52Z;nL7uZcCE*sDI8O2_WN z4DLy%ZWjA(e1}u{eKYP#=U>1X+>)46_*_IxM8r1{(Mgj(iinS+jPuo8jEJSwG9uzg zWyR5mSjqK65iy-uoy4AKVKTK}PE8l^J8r;LN@NC3WYq1)81Bp8N!*Kb_ziF3?qug; zVox^Mt(27&B@bG7DNSBT;SCPr{sbD$=sJL>a(@JGDIwm=yOqS=-Slx^XZ~{aJyiMY zLnTKRl{|SMeRC4;RrlBVw?Q{eY$^?;>HTNn4}7JRoBaxXyVBD6JTshvn#Arl3iopf zyrLvpPos7HIwG#m^<5D$77zz zwZ9*|j_1=iy$(8@zrCpJ^{A#=TT-H{*MTQ+*d}d40v=Hs-`NDI8{I}7w%%`)YBG&y zQ~}hVuuFJ4wHa4Jx9*@Djo$uf-Z`8Y>mDkDJWg&;%eH!)H2BdrA1C!_;~|4Rx4y8} heYY*B9{=kB`7a9?gZ;P(E0q8M002ovPDHLkV1m60x-kF% literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/TV_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/TV_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..54d50ff61174720f491a77b4ab38fddbc5633d62 GIT binary patch literal 1634 zcmV-o2A%ndP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-y+(|@1R7i=XR$XWu*A+hJ{>;qI?#^gdT89eS8k$B~aO$`q zcLN6FR1QuX+meYx>6=4B(>$dwg;MfVLLQT+LU3`O3Z<$eS#FE0)V8FDc5&+$Cy+R_ zrB*|Tv#VXrtaf(p-oHM0R+b$r$n=BDg_(QLch9-!eD|QW7IuS!2M>-_tJMi(OauTx z2D;G3JBhGvuC`d>$GhK@e2JFnq7wZoj&^y1Ergww*N$!(YX5d@7FP79oT)#(c&Y zr<7_!NJa=rt+g`ukQ-xsV~nS@rb;QPloD|qw*cVO$jHb#0Q}-h9vwe^{D(q_bM1CJ zE*6Wv>$*)!=?8?68vyXJ*7`HXSW77-0RR|dTq!k1DIEuZ$Bi-H(ON$tgsAp2m8A_D+0#ypc{nIVKw0JuFlIeGBt(W8+ucN1qAVnno*Qb#Fu z{mPXq{{{ed>J>n@XwMgpe@HGE*oNo&kVGRSN5khKG z%1laGtJmvetWv2=2q7Y4j3R_^M9dIzjS%v8Aw)$8!5qi2#bWU$V=NUyd?QJcGGpwi z$;ru5wOW0AFc^HV+wI1Vh*fGSS)&+^K)x!Ygry` zyc2Qj0zgD|x>&}ThP%aykQc8I;t!tZt!G&#q?E6wY5IL*j4TuipLDz3-)}Q>#2To&W&c{PO92+ynq%X=&+G$8oMwN}W!p^UWklN`*qfqm=$;d3kx5sap}sZFfk! z-M&dF?GQqkwboc`gKZ~b0KoIHrFDq-JKy)wS__OZzfdTA+-kLE0RTAXXsr#bwT2MF zD5afFr*o4u8jV&i^`0?C8)HUlwHlRD%3`tDilXR?a=H8kB5vu{jT<-qS|}7&Mn^}J zN~N+vDSfBWXrurD2M!$Yj4>m|7|l8NIOiWV8jThM03d`cd7k&OB}uYwt(EEyhFN(3E4%%h1ppF; z;aC`k?{zwz*S9acr(joBRum$>5(L57N~IET&i&kg%{_$s#<2D*=iIMUDnSqgX9*#% ztgNiu)2Qs&oJ>zoA6H7fmZs^xT{b5lGREGXpP#?@AbVfgZcR^5GXU6Cy9EI6&(F_4 ge7ki&{@(`je?#3Ny^EgX-~a#s07*qoM6N<$g5S;pe*gdg literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/VideoRecorder_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/VideoRecorder_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..ba6799d3ded636dc7cee8ed2d4fa109da0e7188f GIT binary patch literal 808 zcmV+@1K0eCP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-vqDe$SR7i=X)=P+uVHgMS-?=atM$;HdSt6HMTgc93QnGSO zNGaJ_u(Ox4n_Lzy*{~2rgK|mP$%2GZin4GSLvlOJ9E4eV_kx z`#;b7mg@DoHl-I!&=cQ-c#aS4C|BE9@56d54#NLt6-5OYp#Vn#txQLDKq z)7k+1p;4!T7Czvof%+6^8mW zYEr=i9KdSKFq&Nzyv9r1lBj)nqd#Eb0WiXV#O5>*&+wtDNtSjTKl$PtUb`ei-S?Zs1=F}jb6%Bg=J0prpc>6rO zX*Nhp5@NyGfL-x>SSsME40x;*Y5XBg_>Td+DE_Z$w88+b zN6=*FTpo3&l$AB86|AdChgL`C?f)1l1=i8P9@P(5aT0Sfg~=EZ7$*Z0%@4kF67xQq z+`%_TI{0=Q=ivJzk)j{7r99WOrx|$hbcRlUV2o<^b}lC?q{zm*oRpML%ICd1@bQnVB9000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-x$w@>(R7i=XRzYYSWfXqzpZRBYW;g$2w@E;IG&L3~^pcXC zN`ltFnl`&9D|kpnDB__NFCxW*=rQfdOQ9YF5fOK{YhY=mn*{2i2N7(e6+}V7LpHm~ znEW&U{4@XWp|fQZvvI2r27Y++-uJ)nz5l(3T5A|YPMtb6GCDdsp_Ix401!et8yg!B z@7=rC8pIwC11gnDrq=pJDdh`N%Hv6r9MM|a004+648z!@l>SI5{RRG?U3>i0isPP)e^=DwVGX0-BqfBerdS7zDwh z@B5LIlBW^iK@N24fKuu*#w^EiJ`qB^*Jw0UU!c>cPn-FC{^RZK?XvItZ2(aH0QvwD z##q7gysz5r_M2;KYmcckdw=#k?}HSimHHnD1mJPR%J=;i0F;M^hc^M>-L9T=4`8Jy9V5fbaX8VHjSRpPw)80h*bav6NDmecu-Vpa~(wFboF~5BoBy zbDh#=n5OBPrs<|<i0_W@g3$NU6)^amo)oN>qXwS~hE(byIOc;jB zahx*%&@iW_rbZZJ$EB2^Wm!Y6>wY>uKK{O87%ycqnYSpVD{&mtG-nzS2_fXQqeqXv z0RW{S2$GeRl}`5-larI(vPLOoD5X3;H8nM277B$4Aw*s&6(b_iTKh{&OJTWOb~)$G zTCMice(KJjKYz{hJgZ)>|FK^ugfNDNhA?F+PLd>_&*vwI);gcIl`cJ`n`AR_w(X&OKL7dh^77jz001H6mg6|D3LyXy6VACEhT-JD(5{tIApk@{ z5Nw8FND%Q@n!*SGwBtC05OND3?F>6RJ9o0#?ET%{-Djng91*orDi|=&-3G6<)}ni$ zl)8@N+~3*RxdSPe&}=p%M7+uvvs0=Do9}%h1ps7>*@Td*&1N%t3TMRcNKdc!`9Z;70>f3jImLzHR(>zK@qgpgfTYid0u5} zYwJp{eh<*<>S~OL7a3#M3xxusl)61*;4lD9DRm2l0%MF_Cxl#FU0vO?sPtV<78Vxf z<2b&=IX^Mra&q4^&1=|?@^9owo~Gt@ R_PGE6002ovPDHLkV1gR0Zv_AV literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/WMP_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/WMP_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..022c7df6f415aa93f6a41202db2dcde4d020ff10 GIT binary patch literal 767 zcmV000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-vc}YY;R7i=X)=h6sQ4|K?=bWn2R;1`$Vubqm2P6hQCKwS0 z7!ZkpFp>BNBB_Bi5(W$z5d$_Q8_ z1E>lpVj*kLhu64%b4p%vzN74X#Mq@eIa7nzSw=W-2hQ=gyqyFwR>zMMd`8!u|Li%*Z>D35@eN zGVciKR^x?qe5Wmzr$9gUVimIBz@^I3Y4F{X z2H$53MO*|?tAU^*DX~c!e5Z98e1D~yn812T=L)0~NjrOnB4#2m7F|?&xt#2b%(`7p xO1!bc%SmqiIHHgx0$PqJxBt38{sRPy!Gl{%7%Bh&002ovPDHLkV1j{LRC)ja literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/WMP_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/WMP_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..7dd3a609f3128a14178c1b7b575255ad93701ff5 GIT binary patch literal 1219 zcmV;!1U&nRP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-xJxN4CR7i=XR!wLdR}h|gyHD1x)F`1&|7bjEH@OBl(;q&jOne0;CqX~wzSf#w7b&N zzUd)rvsNTmrr$|ucIKOz_ue;yL?o!DxB~1K zfZ_n0b6W_JvMlSzcDw!c*4CCDNHjAuV>*uWeWTG>ky6$GK%Ws15g;M~z-5F?2;t^( zxl*lG`*L@8_q>&6^5a}C_b4VgjpHK#5F!HSJk#xV+gj^xzv|-uw3PA`09Nw(d=&t` zIU#$4i^y-q?FY#3|AKx7H(W1 znw_0ZX|3-`Dcf;?WX5QkrWJX(RJNl^7*`rh$i*9wup#IDL)8;$!s=z?VLz!eLV;Q z-RqD95g`D;=H})}rBb;igm_pe6!>MW41z#wt*-+Bu<7aPQKi&`QYsvDh5MmgE`MiP z*3Ckp@K+|2$@jK0t}0YYO-xTuk22SF$D=56;>UO;l*{GcIp>Rx<2*ZSWs*#5-HoEi zaU5ry5s?$i%5b9hCfRAFQu#s%abF10LPR5BrZ~341_ih(i0C)NFd6`0^s_TW^boNP z177?vC>D!1+wJyNv)O!yh&l-q#<4xKR;wKfAw0&|+eDeCtFbvQ0yhFCPw|5##eY)S97=)#zrS}lARIk@R_dKr=MNub7LPW$lPjk*+ z?d|QIvY7d~Wm!X?SFu?9q|@m)k=>ppecM$Qh5Mm^D zq8`6?I-P$1=;-Jt&+~5AYBiZ?Rc}%R04RhQVT?WA-rnv2^vt8BrKNABl(&1v1Q>=9 z*|yC(olYhU!&bj45=ns&VpIsRUa3^h$HawsRIk?`IF2(404q|;D!d+i5Jiz8rDOom z`j1J=gb;;XE?4qA??KXj;R5XJ>~siHLw|m$3{mCJhlLON000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-v&q+iF|qoy6pN zqYn(sJkL4*^Y%Yyo}w&EU9Lgw#D@Hy#5g9pQEql|K8!=ylSX>;Y&MPE!5{by^D6-r z9U?l4AMgcU;Y9*f3Pn2dAwIyrxPXyv4K;8HXE2B7b@?T-b>%+v;Afn}LMKB_T*Wbw zmW5@&S6XE{xdGR3S}m20CBi@AxG3;yj7Zsq)IFY9?Za9`-{V(IrFW|_QeTyBKTcq@ zZm0*>1%01)Fw(69rKs6B4q&dL_d&s~sSZF3f?*%!ds*8rw9C*CBzl&Z2QgL|8Wt38 z391$;{3_qeH1Yr!@l^CvsZIHc=Dj$D{prMTWoQt)b8{U3VFr7#8UH6h3qN5SHi@2j zlwSAa&sy}iL@6ZpU=zCpCFj$d5v&n)yPv?*d3Fzve48Lo((|+U7&|hxGx#L2`zW zWVGkgfhke1nT&28UuR02Vj>ixK6f!uO@U~Ow zAKyGq;<9Mcz67YA<-n__FLf>_#-fW#HjQlS~#q`>(=k0x0YRR fGgM#ib%A^h&vD|JafVd)00000NkvXXu0mjf!hV6I literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/YT1_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/YT1_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..c1b1ef2397a61fb27322934b9227f3913778fea0 GIT binary patch literal 1473 zcmV;y1wQ(TP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-yJ4r-AR7i=XmQ9Ep)fUIkxgT9!HJw{sHPhoG=E)19VKjmw z2?Ijnh?+bm8D@eD(Un<95CnB6;!50VaN$Bhx326Val+s{GE6{(2yfv8o)P2vVP?8} z%I^BQbp|N0{{!(N`FM~_alTCGDw6afGTA-Xqj-n@SG z>eY?CtjD{778Vv1Ge2joeb!n#<(wO5W)A=W5eq5hrq=p@TI>HH;!3;SuI?GMu&{8- zTKh(trjO-$PS)C-h$;XWEkGfJ(puN+^|}axU|nl{zTIwrwI|TYlP87edGBXg_DYf@ zrL{I4W`K7Jz{3Dq>%bUO^L_vGqA1>3US6hMLC23DS5XvwytTD;CP|VG0MKrLU4X(E z6Nh2=WvA15?aGxa+oe>uejJA3dqc>^F#et(0NWW;k|Y}daHiR8ZUVsDqj@oUnVXxN z&GY!wrh6s*18K2Wgrf zZZsOt0Kl>W03f30vn+E;DJ7*;0D#W9(mCgbVAfiD&1UlkB7T&nX}Ps9ubv9^l+!s$>TVV znfY7K^SZw8AF$T`s+4MJt!-JBKQi+~v)O!_nPcZ%4-qj4f>)V&OeytH6h-|k%TfRc zhmsX-A8!BvYpwP???EZ$KL8-|Jnvu5xssXpF|!^XUyX&w`4a$?h*&Sn z@|&uvQbgPlTOeW=5exWTC3tulYDCnr*8Z%N3bHKwF94K8B!m!%h#-U*uh;935Rvsf z?{NSS&bdt~<^4hkKtws*SOEZC)#-Gu8)Lds%E_v#21NAle!m|u^P|k%t*YuFW}Yg` za!LsC{rdX)5)pkjIXNlAFl?-^uWuYVa^(ISH*WmgYPEv>`}a>Wa~%LC5K%}eyWMX0 zIx;iN&dz?&?RH-*iXxFx)|i?()OG`^{DF6T=#Mi#>zf=?j5Rn~TP&X1>M9iFX-05^8rPS*} z2oPdN3lIR9h=7RDIX9@Ps)(W}5JG&ttqlEs|MJ+_*tNl6@UXQu9Vzy$>M*>xRaur> zcTlH4sYtC>8}ohtTEE}FJdzDqU0p2^@k3*bH`?89K@jn;1|uRGV>}_mhpVfr-FBfb$$nEZEdYW#B;`&PvbZ?TI+yE|AxB*SZf``acqn+p9&$)t*x!? zFe000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-vr%6OXR7i=X*1L;UR}=>D-#IhRL`D>GtWpSeQDaJrKw=Tl zq)`iTVxu-Oa!a6ViWNJ7Gh(iVF=FXyzbo=dmZkcGxyxw z(FL3H*lT@jKfd+tU8R(aY5VaR_Qm(Vc#2o!1W%69{~b=^NFS z#Ej11D!xDuD*@C5R56fGFoAz?9e<3QsK$@Dj5REm{w?1!cm`9rjVtJnN;HXIa86#9 z{t)mkOEJiOxPwcIrL0@dH!vq}@OF|2-+si-1=gUmn9(WxjzydIp(@_HX3~CE*o*Hm zUnZKu-!grhJ=qn{jTmXq<~?bW*D@I<2}(KOEEY{V=F<_Y{Mr6i^FQ%Y$mrSvkT^g5;VAf+@FecNsKQc8<~wG`NDx#ADw zU5s!F&tz)1?MoaS^1rl4fl&qKVeGGQNTy^j9BV9ffE<(e^7x2ED+bHk3+zL+%#LY; z0;{mz0rCc)%KLZCa3=PO_kLjSZP(E_R>`&U!d4b`+N8|1RhiEH2%hNh-;MineLU~* zsax->Sgi3xmYW7V$@Cs(ck#`LBxE8qGo1+RC$+o`kFhfx)^VT%O`D0Bn}M00000NkvXXu0mjfwN`x# literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/YT2_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/YT2_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..3ac89b9972b9f06de30151e5b281aed3df3c3984 GIT binary patch literal 1295 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/camera3_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/camera3_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..0f48e55f93753f3650c2fa688e3eeed0e28ebcf1 GIT binary patch literal 830 zcmV-E1Ht@>P)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-vxJg7oR7i=f*1d~VXA}nT-<_S^bzO<*t|?54D5mfmtOc<$ zkw_9OVk)( zJENXz=Dz1V=i`0OId4&xr5(tPaGw2_&i=x$xPqDa zfQl{|eT_rdj8}M>K$Ss}fh@uR{=iZE)T^Tgj^hBPF;&-}qgyu~#SqTmd$hVaYT^fc zBg)e106w3T8RQr)V!v7`8*`M8VUM`rew;|%R@&}KtoC6oqc3p*lNsHpsJ#T3%I^y~ zuXL8-TTIj)4dHh|-zhA{&5W+V2iTU5yY)kX|M4sXy_a^=6}@)|c1>agH}FLoRdNU) zCRmXUOF{Ei23z72Y{&D&+=0uLqn+9;8OCX>!Y)DU0#9(xn+>`i%d-M6vnt#3td-c8 zo1){_ zB?s{_R%S-G@f|K@IS12r4C|VL9mBQK6&d{_T-RB~u{uFEiu>4xtJs<)98An%ESuX$ zy~!T{5_4& z1!ER3;A}=v_<1_`RFI<@Q;o##ID)G2QFVGRQlEh>JT+$o)raa=I4>^ueaNh#T4&mX z7(L_KbF5#f?8XyoqB`ib_+yDRo07*qo IM6N<$f}ahA>i_@% literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/camera3_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/camera3_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..0812614595cabb90c79aabbba7b73baf97b1c989 GIT binary patch literal 1402 zcmV-=1%>*FP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-x^hrcPR7i=XmQ83>R}{zp_r7=E*Ua2EZzcn2K`bp8MZ485 zL`kSRBoj$=Q7Ckwb|Kx=Z7FVAx-G6+il9gfy2_-cCaJcu5f?$MlvYTi5Xj1i$;|UH zAMf+tF7hTCn=kPXZ}rYSzkBXI=iEc2l-Q2;@8925DwTSK5DoxPO6$*_J)66C@7~gO z)|1UZ!^6X>l=4UvMIS~{v?ocDqLfkx076KhD9SQpY?d+h8zJOYwOWl|8#FvTT#2IS zT&vZ3-}ikHMUgLrhyipK5K5`a7&8pRpq6F*!x+0ztyX{87N}eh0~-GMUWy($dndD2iH{OvcnS z?ST+t82~7yTnKS62m*>1$*^ugwux)ND5UZ{NNhssND9X8T&L*1j+d zU0v6WTrT(L{QUe!v$L~N$3wYXKBuZ`i4a1hl$}!*LWodGDJZ2(Q4}eq+}UU}4z^ab zFPqKw0hm-%>!a;nn-pd80>AcTOF(py+q`04TE$7>3-x3_nX zWm)<0@$m;z%HY_sW4jn*699-8QXL}Xc3jxly7o6YtJ zA-;{G$OQmh*DWdK$NqFjx*{yod zcQ%{-)HKa%5CkCrRR|F$N#Zz;)1yi$owTj2Ry-j@nV6WU1GvB5jUPI6sJLUtj(0rI zE4r?`Hw?pek|YOB)11!d^B+8U@}vzQhn4cu0XTG%4BAkPF)ht7JxP){-MK1+pp;S- z>trS+gwzQk0k*D>RZUGzElMd}%d!?Y=dNwrS|*dZ&lpoY&-<5Bs;8zT^Qmwc1@mhyehUQdLoudc9tsqcbxz zOKGb&e{tySMvFMgq21h8Dj=xY<6a5W=T!S zH%-(0*!O)TNfH4#QmIsg@B8Lvu)e;&cyV#j7ecf(O?$V$zyCc#$lfGLD1gK;3`!}z z38YQ6(P&I%GMR_XW^-2%1WnKL231u(xz!N@fTAc+6a_*EG@DH#gh<-$c0(amm^TdL^!4l4Zven*dXJ5b-7rn_66d@KKoUYEAq21a zNdS^_UNlYfQU|gI1OTqE9kJpcdz07*qo IM6N<$g6W%=X8-^I literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/ea_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/ea_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..37eb375bf546c590cd83c977913c8b0d846e0dbf GIT binary patch literal 980 zcmV;_11tQAP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-wPDw;TR7i=X)=OxeRS*a8Uv6%bmQ*FCDfL0cSMfy!#hnn{ zh*qq+kf>0fAZ``WmAF(9-AJKyVeQ5TT^J~+P!JR}h*I&LWOOf{!}VCg-w9M1bY&o`(T%V1GT!UdQ3J2x2`u2xx_*mp-M9}u*omjH zypp3Pc41hdWw{ObnItmE0lbSx)u?Q((JQzgzvgo{&P``^%9b&QRZ6X*_I@fcj^e3y z8QqO{Fq4MeN?ms0uZ*@H{bTqYmt^E!wQpVM#{(ECZzDuRPehDH#B4-Nng8VUG9f<`_sV`IL5J)Jy`H}Im;+S5*#<;31AA_gPklZcqg zv}Yn>Pefdpw62MWO%ZW%MC^=+LrKSN5iuVTcc$LHHWW@J_MnIuiiiUdak!>58xi+q z5Mxo~ME>5Ij=oKus?M7e_(%=saAFTNlgHi~b?0C=_9*l1ne4hIX7L4H!bRAM2QiLk z@w~D{=4#aSqQ7+?HSh=aEAwqJdGEz<%DCBvCsTJg!L}y&D1OdnIbH{DDxEfuwMvJ5 znbBU0o3RF;D*I+P9!kJ597~%kunCvpt7PTI3}zlPO&rXq*Qe1qZom(i#E+TbP54Y1 zu;ZD@Oa^d1wx`2&${>zRWEuw>%E&m7kyrE`N`(=8ugtHvaEmfpE>Ha~OyDP6ko1nH zV@dS^Oto&~3Dl|EorI?k$**K9H zJ1Qr%Klt8Mcs=Uu4!(6ty&q9K_!=$Bi+EUR)$^2Qh}vogUah{g*`64uT~s=`oNQJy zTj_Grz&HNm<)kjFaEH#WTOTML*;f9|QCeCcoqW0000000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-z8%ab#R7i=XR&QusXBmH<_s==^+&}NV=O!s*3U?EYI9T`4w;Dwjx_dCzu_lHCT+p#@+_Vf=73=BHwLI429 zSo`kXyEhjX7nir=j~_=gHZ~@R=#Vky8^)MjS(fz?kq-cXh$-j1DW$w2rTh~jzBxHL zX+JU1*x1;U#+Xxa96y#Mi8IC|&N&MJ>kh~m6H>}Tp-^DOV)36+%2y^QC#SbXboA&^ z=KKCjTI**zolegf6Xy}&{QxKjkWv~e^z7`cdmz#N{rg22hCg3jT^;Xq zIxPTj0B~P|oO~-GQ%cpV)#`;-tM!AcSFdiQQfzjtR;w@OB+CE*oO3RvtmI@HDFXm! zt?d$#bk6kvfbxi4?mJ$q)tUhC-2X&$?AWp4BuUOTo6QvfAjTN4)oO{9@-;-%M6~hy z&N&c5eAimr)mnc#ilS^&uOktWl(N|0-+wEL zqHoU4&GiHTK)GB#7{~E$W6TO70wOXgB?o|Shhg|styW_>fLU5v>Q*Y1hms`uPNUKI zaCmt5g-WF|-Rt#)bIxLJ#+X=Zy}Mj49|V9|mZ##d*4pI-X0=+)l*{Fp8DlRSV_vY< z{*Z{Cv)2An2=SRTO@Dp<{P`;r6BAEgzI^$Xl=5fga#?L{7Ok~&&K(8-U_(Pg{l=JG z#+U>EP)b?wegBYpn)=gISgh9XWF3t$q9U z%_d1Q=$z{@#-uUk$ta4jP$;~lwf_Ev3m5*F2XI;`)o3=Gf`}{tpmWYgRWO)V`gVVb5tilS&ZP1A`eioSO7;>EWH2M13#o6U!t&E^w_4jp=J zWMt&U>FMcrg%Ce2l}g1;9ZETNc+VUG01JX3Di(`>KY8-x*LUvRnHghReSLkN*1D~f z@<&ESPFQQ7>2|ve5y#^=c0vew;>3xLQtGeP+B;Dc?QqT|n}G!)wh=J}fD-521AxDA z&L1YCT|$T<&Us+1UGO~b=_E;h$2mV~tz8Vm@RqfCh>zuK%pf8M07gW;EXz{Q^GZPwTwhyTy8-~f008FZ z=6Z;DMk!Tr&SloxuC+F@)@mZk006ADiF3{%A`p?wvaDyVjjgp&e%9+}_~^Ot8DnSW z=H_}EL;wJdMq?%jg0o7gzI?K2^Lw-P-OG34){g)Hlu~^`5S+bq>C()`+-!DUSy_3$ zTCGkhr3Q$It*?{q7=2_+DK${7Rwq|hR-WH{e-F|8{JcfPXO&W~*6Vd8r7Y$E4~$;8 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/iTunes_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/iTunes_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..1134a1d05dd0efeb2178ec3340f4ae27b3bd4aa2 GIT binary patch literal 892 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/landskape_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/landskape_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..306680d6c22b8c9418ad0d351e2cc4dca354fa94 GIT binary patch literal 1447 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/listen_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/listen_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..44e895fb3af2b533c157716a00792b851bf4b550 GIT binary patch literal 935 zcmV;Y16cftP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-wAxT6*R7i=X)=OxeRS*a8-@QqiwlSt5=|ZipL@@Y5aalwV z)L?z!!n(3<+_;e{b>m({lx_;*MiE2>#YiFArQ%AoSg|d*5}_idT3-oCo7{16<}~NF z*LcN&!~MSdo%zqqe;(&_BEpce8#iJm-+#erEDfVPI>h&R+=rXe$asEROJm>S6D(r= zpMW}BMDz%r$F11FY64Y-PCBw3BRGMV@ZqqAx_A{&;XIbx{g>=*l_#(buj3$kTNxU~ z8+c5irI+B5znyeMM%hLe`E3U8;YkgZRjJC$*smnG^=JaS6pEG=8h2tkqo@XZsk=Y1 z21fJ{-o?2_aV(8|hPUt~e$U9S!o4_vYx4g#!f8B?h1SqEe5#ah&B=Jua}aN1FCM_P zO2wVP`)S~Cg8tSRn^4OCE}Rz;B4S@etVG0_Tt7v`Qbg>Hi0Ozpn%`F<;*W^xo}WZx+j zbWbW(W8*l938dg3|!+C(_$JlSZTCzUZZr?4S07i+k1Oc^P41g$E$x?X9%8HI+HmRh=d z@_mLwEN82v-_VZ5V%0`wBFn}*uSAm7(*7EpVn^bOTE!3%gzY19f*PtY-!OPvba zmHc#V(mR`23w86LgYQk{;5%!x+=r2Bcvd<14%p)0TgMa1jGIz;j%E!4uWKT8jwD9k zMP-=F$t_A`TU}1N_{M*{oU}5A`we&9`q&nI_iu(;`Ck{vzX3%>P6a5Q!{7h_002ov JPDHLkV1jV!w;uoi literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/listen_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/listen_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..d57503834e91af197989509a9c514166a8e73e8b GIT binary patch literal 1574 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 LNkvXXu0mjfAaa-X literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/macro_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/macro_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..51b4e5c0f289f87c97e63bd59a760c32a805476b GIT binary patch literal 1489 zcmV;?1upuDP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-yOG!jQR7i=XR!xW;)fPVI)V;T=ZuhI2>h5v%^eq%aByPiO zLTphP)XYyH7@uy8C?YN*F2p}X#6LvH%1uOZr}JcfI&WZ5Q6?Y^d5Z@c&}1Ws8_jh0 zbY;4_t8UdjE>bi0jFULxfr6?!_k7i$l=3>8{^~S2duRb000qnuUxru z>B5Bz>-(|C8xhUU&I)F}*BEn;G3H=V6m@2H0RRv&bsVQHrTkt>`6VKLv9Pd^|7D`t z+1Uq;F{hIxxpO!iT4T)6TAKsFmH`rxkWzY{=aJU>J1OOvg@uLx?u%%0a*|xvePb{f zJQl}sW{gQn4{$F4E&-&JItT*g`~F91n!dEMvSP1GboA&^5k=Aay2KxBP0QU*crOO|CTd7d*O5;McrT0{h921ML?w^B++N_l@A z$2DV2Ua!~3T-QBy?%cU$00062Xf~V5TKjAq$0;*|@B29byrZ>Vmr^=H2&=W0T5G3L zsR+;Ws8Xp&&+|wKVU<$C_x+!Q5bycEPs|J@*0arKQ*DQ?TCLulB*`IT%myL~MEsSR zy);c|A^w$R+5Zvo5db)qrs-8< zOy;^SZP^0=3Mj6y-Wc;JGv9JUEJW-gVhVeA03;&4yuAE&Q4}8l zz!_uALwTM*&&;Q@EPJNaYJE&Z;qHiR*_YT|>U27n9LMPrk=X4zGZ)NU0{~cBT6$4R z`Kb^>xvuLuj`MP>)%vX2Z2q$-iV9q7SEIH-M8a{LZnxXLL~Cnn>t(C=Ms~#j0M=T= z%r_r7a-;zO;5g1lzVBC<`IGti`8NRolv1}@Ysaj$77=+ALrUpMDZgJ^TU!_9S$yvM z{=d^S-QExpv6NC5MNw}w8t$-O+rC#m#``YuotR&eE zi|_kHM4tncondox^Q%gwaS(Rs9}b6gMASlv$C>#mGj~s(Jo&KJ zIzq%-5%CAD^|!9;{+y;MF>}bwxl&5|zJGCZbMq^Jk(4}k?AQZonts@Bw>MnZRbd!j z27m=?Efqz903hL7%`hUWYmv1n5fwzlWpjO~*X!MEj4}0kea!Q`Q>|8Oc?S^y!1VO= zTX7se(d+fDNGUxbgnylE+Dp(FljM1xhG94!1i{&*rKRm_Vn-cqY;3#|MNtC)j>mD_ zHpZmayIFS&GczJm7=|~6VL0FIc3&CQ)9AS~UNPX$46wpObJN-14>#9MdI?q^G{ zl+v|YEeL|(ED=4my1Ke!P`U1KGBY!CEYI`PNs=7e=WudS2ytd{aq-+000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-v)k#D_R7i=X*2{}sMGyw?-#v4aF^ndJak6mfLNGCA?aG}m z2#G7>LW~;`Tq)#%i0%Xt6d$7@APR!UMTnpncjBL5Fma(FAowB~hQ!S1j5AX%x|)0D z>9`5~wQlawE533g6;YoSD>6gV*siRMZ*`mZ_ zCI8h#TIy`L>h8qj_^fScE51?Ex5lIfyUFJQj^d&c{AnD)16WR-HG|m9DCvJcR_m@F zRI+Qa<&td)zLdK=iPJXAi`cCsO%HeE`+Dl_OYF}@got=ABCbco&pEC}#QPDkE9bXI zL_goVV|zsGh=|)F;)#g(JtBThoa>3LQ5e4me;NdN4R7Nrj_3C%GG5Ddf8ZlrNVoP9 za}Va4Jo;=Nx5lQv--?@S<1C&WVfb%@L|RYm-Tn0cw9N$TDH*n)5Et%JV)O}q z#0%Jgw>o<54BSZUoj0p>ZFvS?7>?;#x$!G=ewd#(fd-Q$+lhSj&k$vIO<=-#LXRQ$yTSIj8l#SE0hH zP6=uk)q_gvwu|bvG%{(wug!5}QLXX@o;A1!Oxla8RIoYBjRZceUa?&V?^RF%^ZP|i{O?KTn ls}$6sax+71`Ck{ve*oD`hf+%=Gspk{002ovPDHLkV1kd#l!E{O literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/photo_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/photo_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..d30d6f538084a479b9c33496171e1cc2ff427a45 GIT binary patch literal 1373 zcmV-j1)}000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-x*GWV{R7i=XR!wLdR}h{zyKi^(_oS6A<6{qPOha;Y3Oxje zRM@p0TRFr~=%Il^$R&YXT1r}IX?o}-Q0Nb76G}@Dwrg2-TufYI>|9KaZ6I|hX)Ymw z=+COXtJT|m(?eE{tk{l1zvJ6C^Uci8`(_vsK_}?%@9)lJGJQ%Z8vp`$t^E6E>anA2@&VOf&E#>oh|D}m?x!j19 z^1S0XhwJsal2X={Qa%7Q4HzQooO8>vER05@e{#+*=kxjN9T5!<4x(wApS!O6UaeMZ zNGY8#1Gbw33LS9Hqe2KH5{X>%Jny5$#YMFz(b1zvb=$VT-q_eUS*z8`0HF3F*n<#- z5b0zxIa4l|&#tbnZkJMTy_`%YKMP5Up?}uqh_#-Dfix3l0HA8MS`h$Frc$XA0DSmd zMkh|37_QgrS4*W*l`%%`B)YEiNF-u1#v0+V)@U@C=XqNIfNjaKuCA_>X_}|!=jRu; zi3SD+j94u8Td`O?AfEfFE?}mfOtH9%yFDUQp##r0*b|A5yLP_j4?;kw3J~O zKhDj~6!x~^*G zZCO@K2vHD1WS5qf-c(Axar5TQui6`6VPWB~jg5@~UDvZcJw3-0iNptqM1m0!0sy$K ztCUh%004I6$dPU##7~t`+!(UoJyLb9s5W3;^c<07gbeUQMM^KQ|hU zX(GCBn&yR5r%oj%CnvvaBWmwJ698--I)rJOrya*xotc@r1OPBJH1t3S@nvss@3qH| zA2(iPkBqSjW6Xn{4{-7ml>_x;O*L5#VPELNmUj;bl7U%r#+S*!C51DU7B9V7I&wF}<$Phvd77B$w#>U3B zEvKia{|11wdwCui8R;jY*NDg?B8WsHh=?};_K+Y%WQjz=&~^O|5&auJz@~Z zm6eqpi^`tM$@uvAsPFsd9mhG;;c{|E*Y(S@v$ONN`P+Bh8Xq6m0idIG3jmg8XJ=o2 f-D=1GT_FDhe}%uK=>guX00000NkvXXu0mjf7u;!f literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/radio_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/radio_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..15f71f790d7466f323667a48b5b7b52d8656fba7 GIT binary patch literal 918 zcmV;H18Mw;P)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-w5J^NqR7i=X)=P+7MHB|$uRFJU61z2-#EC+{Cy0q+z;(c_ z21H$D1o5$vfS{-gv({AzL{MfUXtFbL6Cn`ILPQX^J}`;Ig^FT=iJABq$LXhwI@hkg z>1kR#(9pN4&i~gr=dV*$8xDtNv<2+Mw)p-P=WuBj=VFHWy?7A!2FYB^tp(ZF_znm$>=N6iH3ol_Xji|s8 z?32alD@sHSvig-xZ@m7cuuIe#8&BA}MbNZo~G7q7$j= z22o3r{{!fhL=Q`OT@I1~uHq+r9^`G@f?KgU)^sDHGA%b?OMDL_s(mvj{sx|q+J0SXQy&NE^+xTcv{j?7&+Us~uYMkwCJg?oP@A7|7I$H}^vd%R@O65_h5neX^ z;;Y(FO7D%5I-izZd{y1|B-t)W9lB+d^GT13e6AHfOMx-=P?_a%a-S60w8u$ZI&c5! sagtjD51H+`^?_?uI5Sah|LXzy59VF|(km8mqyPW_07*qoM6N<$g6MCjB>(^b literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/radio_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/radio_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..c6896aae47468d0326fc1d2befdf312319e46401 GIT binary patch literal 1585 zcmV-12G043P)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-yt4TybR7i=XR$XWu*A@QGoqOkR*Rz_{%B6LQV@Pe;xD*T) zs$YylD;uY_B^wqO{L+MilTZkSK9n{OrIgaQJoE=@NJ?qJ*kDOk)rO?RmQAU!pJKZN zyXixINYYr^UG0wM&di;;w-25bD_b@SJuonE@BO}WzH`sHhm0}UjE#+rHAY58c4@6c z0AP%@@87?F_r{GIOPe`QPa>L{n&QToZ!4v~rIgxT6vePH#sL5#N-fJ;7DBuyg!nrV zy*)iWoqu7Xsi~>&D5YMB}axntY55kj;a$NAK8oX?{udaBduFaRfqhK7~_{P>ZGjvqh%T#_WOFE1~5h{*Iw z`rwQ)!8sQ~h|IR_&urWNPzdo~A}aDc|4N#sPsec_rfEvX7z_^&4>^wW{M_8!{2I}r zLx=22rSjLMrKO!pskoGjm&vwm+m3_~9}6Kq5<;}K){au@%UPB^m1Wt8Qi|nyo*83u zBFg(YYcv}7R##V#Ub%85;{Z^tR-cXIcyE?v9mW`Wo~K>cz0Vl?gfaH6@B6Ec<5Y?0 zt7)2!N-1kaQD^{NAwN}N^89}j$@}NiubkFiip4%gXej;5K9QviUJ zQoF7@0pLwOK0e+Ef?&5&Dk<|qTI*h=QhBB*ik})|R-}~ct||anmL)jn_monhl(JE+ zR;AYZ4Xt$sz#$?ir4pso?(y;Q2CvuayV5ib%VHcfS1ILXS++_<8V|0UD4j8Rp7SJ0 z2!Lgbv9;EQF(!(lSOd^n=S5M3VHob>#+a~dD{BQsL~ayCH$2b#l@P-9egA7(>r_g4 z&v6`PjNw_9aUzO{$R;9BDYY!6{LFD2@lZuL0K#>3G(couzkdCLiHV7&ZQHiJ$T|PF z*4izKqH^KFh2Pt@%?}?w{AVfU5P+PBxaWEAM^W@g^O&B-iKtCPDS*mARK?DnJMDe@ z_We*wd1-cb_Fn+dY&K6do6Q$SM@Rp}7;AIR6@Y?>IAd%D0DIJDN&&QatJS(21VNiI zwpDAb%6Rkb+qdu1T6g;-0C4f*#Y@d*^Jlkj-_CB`x^?zpuMZqJ@C`iZHUqak?aLsky=PzHrJim?z08X4Z@yl+v`~6<8 z*S0LHQtEBWZVqG2hHq1!t8^?1f}jxu!MWMl*|le4oyMI`=hZL_8vssryWQnd!Y6?b zngPIqAQ-9DYM0vW_N#-7>+b!+!a`0&XM-R(SFhItA%tH7n6lwM^7Yq+5PrR04}u^# z#~3@iu&}T$e~%qbCMPG4<$3-}9LIY%Ih@?#oWC|RGc&gl-V?{I$;n9$U{m83fVXF6 jX1@5i^|1ZF1LXezz@QZbTW55`00000NkvXXu0mjf?mz-~ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/sound2_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/sound2_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..6ed9dd281f2af29624557ffd9a4716597e304d1d GIT binary patch literal 966 zcmV;%13CPOP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-wKuJVFR7i=X)=h|(RTKyC-}{cE{>({Ny9d6T9lP7 z`n1tSpM`+{~s^dUkmB4QF9Wm3nPoMz^bRVllW&VI&c zIE2}yfI7?UXd9l#jhMsV3Dg*LGLXwKfFJM*KJ3>~7q8(d%;0>j-_os(hp-ZF;Tg;? z=V%4?;UR^VMtLPxr=x#zZ7>~8Wk5}k>+mj~R8iSJqgU}TPFC_O@H>v+JN%KdYj6{` z;98tZ;PJ#bg{OOak7&LJB4Ros{)~vRh&UY);}P* zDI1K4HzMLpMtLs3>D1dB5vx;oYw9(uOeOY3>h?s$WD3tl#KDT1y%8}V5yz`Q8ldA5 zF&7d0D*XeAF_xHnB0^WG_>GuO3I^~&{@;eja6-wzI=wr&b^;G(Qo#F((MimW80lhz zl9F?k@Ru~YHI3R%YG+BW)XsyNP`f z{IGJL3{}z0U{{`v%236By}nE7?2Y|UVjgDUH8GkIPv~XWkdjRwV-p_LD}wVjApHcXSP&lsLy0=+V0SLsPywV*`(}jxyMNtKf1)nNj(N} oxBi}6pX$9QF4<8%{?`NYU!O8PF#cEpIRF3v07*qoM6N<$g3vqG0ssI2 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/sound2_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/sound2_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..a3ffdca622604cdb2618821c729ed229665cff00 GIT binary patch literal 1622 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/touch_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/touch_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..c37f8ea0f2817246be953a2508109eff32c5109d GIT binary patch literal 961 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/viewer_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/viewer_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..f93b7aebf2794ec52e788c005c8aefc4eeea961e GIT binary patch literal 1535 zcmV000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-yc}YY;R7i=XmOX47MHI*1%+B22-rBRbYdZx6P!ZX23Md?l zCUO)kf1b{UB76u$C@8^B;Fwo4*3`4}{q?E^{l>JGP^dO=R06+){HBH;(od3!>Um}DomP)1gkwG&v zGgDH^)1K!Y4uU{QDFdZc3;>-M2&I&9&a>HUmgaJ~JDl?irBdnYzCdGRV^r7mk9^;M z-F4kaO6jE;kOu|8Gyvy3CxplthVfMxhG!QR7Sx`gqeqW2+qOS%G#az6>sA3k?FHBa zNQDrNWm$98YW3}#H*ap0l5O8?S=NUs$f#c z`wkI*4uaq>L~Iy_5!UN<)3U6`0boEWH5NtDvq2DKecx}URRQ1kRW_R)1%L%QJUrYh zrR7)a&*6wY9bN#l^+nmzI|58yg!L%d$kJQu!&0 zqVKO=yY`A{nxnRDf9p6-7h@~~03f9dq?G-`!^6GQah!umlGsYAm@%d~j^kUF^*!addR_dDAq%EEEctIp?BWF2B{?-TkKH zI5ox?Q%c22lGwIwAEbzABchIon8{?!OeS-2Zf@@D+1c6mJa} zgpfZerS}l=UaQs8H#av&8;wS}SS)@rH#c{cG4`>p>qdHrbO5lo?hzpb!Z2)mp7-MT z`1r9P2!@)?rk^B9l`&@9wtWHsKD%}6RssNT5JF&LVxs8#{vqG@t3eQGQp(rH$Hxbg zBr&5X^0%LRMhK}9LP7vAl~PHg(dZ?FJO%*G?(XgyAw)3>Rlm3jZ%655hWrfNs{=6VHl=q z-qtj2DT<=QN~wOO)C6N}5&$qs5)BboP1F2^F?J`8{wc%9fOJ zxAr9f5C8zCV$hKvKt$x6=M2MGZ?#%C08*`6US5s}A?JkOohH*&<(UaDBe`aDA1Q9_9(PJ3Kr7KsiR5}ZE`>uMue$KM2 zk`ST~5$P^f{!aoTQXxd2Wm%_%1TTKIVFU+=s1qxoaeUxBOU@k&Uwyp z93h0bNGUzFva+(nsO)J@ipAn|9LJ|U&l}vQIaz0nU6`MrFFz>WL+w_vSY!aOFS`W* li}UmIk8ZbikN;~R{{|mnHa{W{nR5UD002ovPDHLkV1f;$v$y~N literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/walkman_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/walkman_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..f6fd543ffe7029b8b40cc5758702baa41cdfe057 GIT binary patch literal 883 zcmV-(1C0EMP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-v?MXyIR7i=X)=O)hWe^AO-#N`ija5rpi)f>-ej7FRPggx9cF zre$#%@Rcaa$#J}aC$&=9?GrwTeX_t8VnoRM>gp-H+EXUEZx_q+h1_Zhkl6 zQ58o|f1eP;(WvH=_Q>NKO5g^)EnfnAtyQg@H+u6`qpcbCiViaJ9w{|E6Po-ZQ} zUZ=2j7WV&hv`4Q?M$6mTQrv*|u@w_?elEp+**Ne4uE*o}tL5loVIS+tiQkU1W#lJ( zg5iqf6+B#?|5-9;@o8T=e=DaN>Xh7eZ0VMl&03kkBX$0%h~F;WX?$0*zu;sG^lI5@ zqqwS^3_0lIm>81X(WL7S{94Li;#z#)0^E-;iNRnBqAmw z;^&AsS?9%w*cK5R>)a3#pGU;A5utT~vfvLDzoAK7 zSB{^-@u33#5w}!M&&lGxSweTomK~N0^CMZ;J1gRl^YS4+lg+TJ{vR#usb(|WCl}## z%d5*O$_7k*kI8PDwRC%rl+J?e*oAUvFOIEu1+7IZuAq5&X^rabs*5qwDXas9z2urW zio@94Qdo}>g>kqrvHZn%MCSFh^<8|MWxb!U%EfnH&dVV=BV&3Sd$|bPys^?bR2WMh zDuX;uZkCa)_BiRvJ$ONnlQs?GUV}Zi-jy@BEUjgzO&9fm{11idJ?)UZ$TR=|002ov JPDHLkV1i5eq^SS^ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/walkman_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/walkman_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..a0e6ebea25f47048a9990760a32f7ac88981603e GIT binary patch literal 1537 zcmV+c2LAbpP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-ydr3q=R7i=XmQ9Ep*Ad67UcdgHc|ASal}SVhImEI+J_rkW zF~(wzwG3LXc2)`43bBoSvVHQ$!5AZa5I&d~e;opeL4lBvoU*H#>`GZjTCKnY@4*5` zD9BeMf3Vv5=;@jMc-^mZaQ8A2UbDgv8k$$H{=cqQT}2@g!EV-(BS$7CCnxtSrF;MY z##ncAbMwZ=#>TDP_~Q?O78Vvb5gn6KJ|?9+kmvaxA~FF05HZm-ZA;hn|LMB^Z$$if zad9!bYtX{N!sAlPmqw$}{c#*CDP^pb$^f8rK*ku?b=|Toi#d+-UtQPVUtC=L=dM7F zMuVBA`BoG~&jvw|N-0N01o(XdR0!z0?g$|a+qVCdB*_~WE?iJMf{q?N%6;GeeZSv7 z83aKG0Mt%^9e_*-QTIIWADvF;#Vc2?Y+ofGKkRwlnF4aF(BBmVU^`+J1i>u;I9aRJ zwgBMu($3146DLm0#&P^y5CmJhgb)!y`M`I%Lqvoi2)5!ler|4VZuU0N^z^i$lzKS` zf~0h~LlN%CB_X0_+qS4wDpkjE1R}CAUkZXCA)=S3r>Bi=P^D6NG>W2wQpyn`j^~X4 z0Cin=HBGaMJdmbon(zBrtycSRVq)UAwOZ|Wp696o28f7K%257zqX0#Ylu|QM z6e$1z#+ZqSTAt@aL}Wq;W*EjLrPRc5IJ|E(8l|r5I+kU<)@rr>Qhd;*Mx(KhbABpK z(?R+FL{X$H%bEdz3v6m?YC=kRAWhTQvMjS+uYXai)jlyzQ#Vc1bsXmp=g*&inuwlq z9H)zjhNfvzzu*7Q_+4gM_B9b{$+iCmZxc&PDG@X z%JMw-ec#{DiO44+6A>9AZk{`L?rQ*m`T6RJ~kSS$CD&E)9?3PAq2Rt`&Z8S zpL@ODrsFuk7~5+Y#vi4W?RLBUK?yy6{P+O?Xb*?OpSiAkc4cMdh0-=ZKmR}&hJWkz zdgysxXqx6}hKOB6OaK4|g8>Z&gIDuBfBW*~%i+q(N=QUcbUK|!q?D)j?b|nA;J*yR zP$WsxOOoX3c)nV#)>X#Xw}_}0+FjP^bZ%&x)@6)wB7)&?xS1r$FJ@+DsznXm7e&!# znx=aX9Xj-IDTas-W?7agr6R*Hn$2c&?^r~$d7l5YD1~mf+r5EA1hccV?{>T0CzB)z z0011vFoSF6>KbAAN?YH=Jt6oz4@lp@= zhx`3LYMSQO>-E1cFE78si`rSWZTmM#k^mw?6h%pzriT$x%d#v40FYA3Ua#kJ&VNNj zD$BBA(IFs;q9{p{dpPG$ls2VQUaeLcV{CQ1V8bxHwwA<}v+qTaNA@+=Qvf^)x>E@32rTWot~>R5 zT?ipQVvIe%zP^6jpt9p|(rh;8vMhUPG#VY;<#2M1bN>F)(o*~T^nP&MYBrl30CqKQ n0l>#gOG|e@Zr!;U2Goi00000NkvXXu0mjfoR!lg literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/winamp_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/winamp_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..2beabeeba3788962c184d151a9e8c91fc28e9afd GIT binary patch literal 814 zcmV+}1JV46P)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-vs7XXYR7i=X)=O(tSri4}uWn)`61#mX_z!%egG{9dJ`qF_ z)RBtdsIkFG>#&`OG>8*H0!{Z&M+O8R;6xN0iFD)RA2`uyK!T}gQa#xFnwzq!yy-r0 z236~+5$xyDflI#WU<1W7R0&4Wh z=rDf8cFbZrfy#hJZe$n(_#0PnyDm|It2m1pOjW<{__i86f+ogr9&`PO2Jt7330da4 zfcF~h+~jK9!f6#Li;jVqngnn+{A|rtV2=;FBK9`V_E*c5+^XO zvWq4z2q)DcY3FPv;4?fBrYP52!c5I7(O%)MshT7OR^g*K_&eC0*_4t`CFb5L(E%MU z=|KQL2uuHgQGCWFA>ZeYjm{;uLR9=_eCm-+DbrFR(-R!T&za4bIGawAMq+Np+Cgj* zmYnTD(h%L?l_D)9zqa1N7L(j|T_ zu~&Yt*GcdlqTfy7NCFJtmz*QQWj&2lh`MR{ws@I0z>55C4;~8>JiujfcC9}6Eqo}1 z_7mo7pmPk1!#*g^<2TW%NAb?Q3A$x7kl3#VMay`JouY}B0d1l0G>&G_Qz7GIC5v8i zl}>$$x20TnEtIaT`j5CMiteGf_$Gv#dSy`^MPh&Lbxq-{jpD$I%;dhX|7d1Wx6!tR zL0)4QX38vPM2!qpfM!HhZ^ipXl9aV~C247UktDZpN}r4G3r^xXmJ6NRmDvrvoFf@?JuwzMRO&oVwu#L8Jx&VzW08-O s>R5vP>OHsaiQ?@#zDHCY|LXzyFGH%;v?ilCumAu607*qoM6N<$f`^21Gynhq literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/winamp_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/winamp_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..6e3e6cf373cc00849794ce8c73a569c53e05a523 GIT binary patch literal 1324 zcmV+{1=IS8P)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-xrb$FWR7i=Xmd|S&M-<23%h<~uQpyWa z6upxqiIP$#N~sh8h7N>Msx!ul#bS|Kmi0Gd>{_GI_-!K4$&)9kVHiKgar|iz1Oq8$ zlxIL*7Xb4Bj4_LIUNBAbXCcJp_4Rc%7If^`G2L;T>)memOb`S<0H|?*F+j>WcgyAS zufFep@#xW`-BRkK#^rMPhaA$%;~xk@2!S97S^#indV0DI0GEa~bog=l^yyPclAH^I zpnU)cA|e(F1+!EtrJAPo0e}WU&`y%%+|tt0sh2fL5#387bvqDP=My8$?9Zb-g$}Jw5HZ?jKWAQy(^)&95!X z`ceq-lkfY9QYszw&$CLTl!vR;>WuEX?wk<9$qiqD5JHG;+Xc(Awi#pBR#sNl003&W z+AL%25FzBRLZMI@3)9Jix7{+niwj)i`&LSdK zt5rHXJNtQ>rk}@gYyrRk_UTrg5Yi!p2mmO(CM(Rc45XB0+qQS2DEeq^ZS85jUO!r? zRK5#>pxW#8dP=Fmm}Vt;?2hjH{x;{lLn%Fkh;mQfpzFHfd7jX9{p0!h`KQav%iktR z@>#FfD+nQcLdaMhq?GEKrgb`<&NkiJ+G^!eU&ImN%R9~RJWl|?SxwXEi z(|p$N_a6e}%CNDqF(8Co<(wPCQwkwuyWKwF`~KVge!l~gKN$!BgmZ3CO0RBgYz%fm z00672t9MM(yvaHD06=9~#=|fyNGan<$~2M;aLzr`G;iL%ef!REgN|D5?Ce}Am&*;# zc_r_Q13i3*NIB<~a=F~t+1a@=y8jYrb8|B#gq-J`-*8=*GsY|&s_Fg!WQvGQd z4NB?x&CSi129>eHNv&2}O4Ia06h%iS98R9;x_+(MY_7g8-oE2jtya?kV4`sg0PZ!L i&4Z6yd)NORApZpqAEczX`H=000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-wZ%IT!R7i=X)=6kxWfTYSU*1a^n>1>v6-q13j{D^awf zRa6j%g^3kGixd^lU zjjxrm1F37qh%Ux+7}L%}PrkR|9qh(eX=DLj$2p>4TIr08a3QY1OLar@QqjtUqa&ku zA5URPLh%^(;DS{0HJ;8W*5MTVoJM;^`LDr5W#}S->sT6TVl#fnl{gjmrErg^z{^C5 z_u^ALlTmC)`Br}S1@@Xt<RpWtYmhHvuwa{N*=GKD%t^2SA9w6v$d52A1G#>;pCXW>?n zt8uKykGL6!V(&CVjpQ3^U^pRa))@NmV0t)&cT?GV9GMVp5@r8}7^L4N3Pro&o2h%a zA)4)TfqM~{4&(l0JX?&OrT8s9oDk#ZOOdm4aR**Z`6|crQ};-fqaE6FuNscW<0{eF z`%}48vIwsvTx&$HEED6Vj!YwU&pLv-MVUU5@D1Rk6nqF>3Duw&Q`<#j_ot(?jv%;1 zR9Q7tyOMb~p2rcm5wD4U=}$QS5V>1{U$xi9l%cAWQhzp=QYK0%duq?#Qp#8!{mIn%*C)z%7Y@gH`M;T_FDkKIU&000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-zP)S5VR7i=XR$XizR}r3>J!jAU+}(R^--uK}fKVt33K2XI z97V`DB2h%RjvW;hq)LF*s{EA}!Aq1!8dc>Xst~`bfL6Q!DYoOAl+Zvz@_?L>N+43& zlpmp1@DSVg+I#o!?%6%VL+`b0lvb{or+wI&Z{|BQ-wZM{Y{&NR-{0J^W5@fAF(Uu~ zMAThgUcPxRDXuR4zNJ=?aQjpO)TwrzjLah$0nN$Po?$AfB36h$il zaH7#@tOCHvVQdhk|gWK7$c?hn$6~` zNs@f>%9Sex0RYr$wL@8!?HxQk`o1rG-~YC4+vfpbmYE;#^?H|>`Mp}}!^W6?p65}g z(+T1@{u(piFNFA25Cms}AgBO=KPOVmBrPKldELBzY`&O&< z#eTp49%IZp0HD@7*IMrxA0Ka8`}Xbou-5u`mSyS<96)9^X_~T>@{sTQuiv?I=UJtc zqmwcG7~EG{m-B!qZ3B7PJRZ)>ez(psO$vMkyJvc&`< zb`h};0REsVCL-bc{vBq%83e)UBuUPdWw}_E<-t~~^-UtGRaMm|qOTz0vQp}i<>lqT z7}Fg#%8;2s>@IaWo!gdWb%{s}mB9D?8WH{2^SoYFRX<|pKOo{GaU9QPS+*m~vRy?{ zoV0EGBiFBAzg$(-`5*{h^L;-YCJO*SM8dMHZnxXLO-oBlD+8%_2G!WMZNJj%^`17y zP?97Qd7hu@bUOE>X}V^NDU2}%0CbZidG)}718rl>q-9xWf*@!sr4%zGGqaS^ky5_A zw6wHB1LPN6*QH@a%xt-?`vD^QEHfWWk|Zz7vKZ(edY(6`lzJWjf;3GhnE8lOYFEGC zzaWIzcz4%ziHKg<7}z+DFT1XL%eHNgnTsSz-bqByWLfrSA;ihi(b2z!VOU2*VT`d{ z*Znsl-VB1^VWm{t81rbJ=S?CylVw>S09Z=txvqOFj^oQ4S_c5oYPF8_`~9D+uCA^P zD3reMd#>x=B%(QEOcN0wCZbr>3SpuC@MZzu!L? z$8lCwRWbAl!>}2K;nU~No!eLwcUycv80@4~0NBt!$8l=D?{}H`cZgVL=0kBDLs1l) zH!y`^I99LM=ephQm#$vDTHX~10AOZj#xlm7PSf=Byg z^nxI;J%e s0Je2*0l=k&g@w0&ZvC(QzX#-h0ZuWXdp~2(ivR!s07*qoM6N<$g7NQ0l>h($ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/zune2_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/zune2_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..d8e8883877619e7e1d0792fa883fe99200b5083e GIT binary patch literal 824 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/zune3_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/zune3_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..f36a6eb826b5be922729ab4e9322848a37e175a6 GIT binary patch literal 814 zcmV+}1JV46P)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-vs7XXYR7i=v*4vAXQ5XjB-`@6~jd7ZolpM;T7&0Lx7vw?? zHdfxY4?+(`1do&p5g|sVQ@5{(ikV& ziDT%-FZ>9g+@KU2nTQE^j2>KWmZ*#qID$I97uOG4TQqJ*8&2aW8eoixgcs$z&;-a-&vTDX_W&`;U*dOCel~xtq8b-?dT5nwe_^ zwz8D*%Q1jAL2wy;xQ`D~o@7!~R%0x_YXO+&R8CMse_(f3&?SZBFFeOLDKJ*xJb!(GOv| zl!N`T=?8Jj8aj%1T?Mx=CnRm)9X8=D&R~B?+=q|S%~1{eJkq9Oew@5N2QN!`Qx6GV zg)CbzJNoUAvkNb!R9JwkSc~;xI}iIX1D_4u6hHB`lx0~bE`?9}@GN}w2nVn@Bx?&v z2IBPP7-s=imBPAOn42Kw(ymJQ;TcwiL)V1^H-`lEFsc`19$pSgg}H%(lv4t`H_xMM z!9Ex=ERuYcJ9fM`MLDql{}oi1idHR1#&hiyNlJm$6WD*1i7PmTSp|dfkO+)Zfr*g| z-#Mx9eKx+rH%lsf2aQqq2BnZbDP?+l0OWln@VvK&&B?&{D>9pToUD{iHrC^$j3-)r soD^FX+cfvwx^5_kS|%#Ce|kXv1~C@nc#FY+y8r+H07*qoM6N<$f?J1VH2?qr literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/zune3_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Media/zune3_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..4ca073c8fd28f777c44b9a10fb09ba03825f82eb GIT binary patch literal 1385 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Navigate/COMPAS2_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Navigate/COMPAS2_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..9e064785b510eed388234bcd37475666142b6891 GIT binary patch literal 1674 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 V8SWV8f>r(ry3% literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Navigate/EAAA_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Navigate/EAAA_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..1a46e448a8272f4022e0a45c413e7b6374c58365 GIT binary patch literal 1031 zcmV+i1o-=jP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-wfk{L`R7i=XmQ9G&RT##9_dj>$I*u`oI+O;X++xH40WEkzQjOCuee+JI?sD zc%T2BGsDdFMlT%h$2sSD-}jv7ecn@$M4i?SECgoxcQ0@q=&5IOv5xr-z&hY%J1Kdt zVrM@B=YdXOWGbLSjf~y|_5w?RQDDeG`G$f6nFcff-vft%ll3~vfKP#)1|0?l6Y$j1 z%`HF^@D=b8@TiufBJee^8Mp`h2K)l7^!%uu6@W%N8u4#A$XUQ~U>nI%W)mXp0Nx=k zxDhx9l>I$lUvfad0(TRK1!vJ?jE<=?+6a6L^m$_gFktZM2I>cH0n2~~z$IXnBhS1q zciINL3!F+bY6A8VOv*iv05gHPK(p6eHNYV74X__L3(O<#GB+7(ulH3Qtp%14%*yFo zBJODiaLnLO0zVL!-2vPHJ_n8fH@&9C89g8vyEa@)NcvLJkfh6!j!Np4bWhR;lIBTz zP106LPf2Q(v`|v!z4=%mX_KUDlKLgxl{8>%kkl^eqNG11bxXP~=?_V#C2f%OiKHhc zfYutVlD0^?A*s*U?L}Y_LCJ?i@wJ!~PXmjA3ns3M0l|RP^PR7+-t~ zfL%bh7r#odt(LA05e$6Rjw%km1hh@mx>2GoF4)oY{yv`|#8i%6BJ{B2wL=pZWJKLm z2&QDt;3n_|a0OUF6z9*tb5l5a9oXZ*@)F7MDnMTm=ps~j4sk~vzzG8!^5-%_z1s*K zJV2cNAkjXyd2W=kddi5R?*+PwK8~M&R~Ua!sdWL%f%k#84Dcc$Pi044_Wv^&lcQ#1 z_v8iJ=?DgZ?L@VoA z9t2t$V^iA7^JbU+H=AgD?~ydV$y#{>p~gE6UP(3-h-xn;j&e&|`Nss+t5(nBWC_8d zT91000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-zSV=@dR7i=XmR)EZ*A>Ulxp(f&+}YV#&C0H}hPb%?s*6LD z7$iRgn@wdQp?38FelRql4RuOiN(_ajgglireQM%2Lm&!*hh$X zacXKxd}+|c#Kd>9EPFkQqG#hc&a*6w^E?*-u5REZrnx;uC%euiBdv9uL>Q5U2 z4G#|!!!X{CqUZ;$R!aduCZ&wJ_i**zIzI&fz!iyX zpk|upi697$Hk-{B=lpiLT>gl2j!G$1N=cHB`eFbsopej(5Eq7Xs@06_>Llv1XYQnqdXlMupv->*n1 zGekrH$b%rL1HfcYPfr5?e*T5f)oQiTIF3JPG#X7rRES6@rJ0PamSt|SSo}mO^+B;%>|a<| zIDY;5_4bqM<8j-zZJV=e*RG)?N!|#Wp9MkivQ{pacPB~W=6RlVIvrCfWtB>$ zQ;y?&g;KgFj^n>?1Tr)2&(yI8FdSbhTaW zvHOxz%EB=Gc>DJ4Kisin$JfTj#y&O-V@sh>_#FT|5p?L#p`C{hA0CXN$n-pKixBjf2cJVkWQ_F`3WZla&wIyp-Et5F z9ZG30A|7ir8heBg5&+V5AHiJLy%Pk%%i7%BTzzzO^cG|6TL6#~@<{sw007IfZflzM ze43`;^E_{oF-D^(`Z^)x0q6YlcDtQ0#{Q%0I_-2iMWqxdrE*=@O~%-*xw*MI=_bGh z&N)fbw4Ef$E5pOXf2`GNf2dZgTL1vgoH-L`S+*^X<8OPOx7chp_t)$7zUAd*D+mJQ zoacRgeV;mxa|aQz+jx<4P6#0v0J<%x-ELpDEbFGGY25dHZDnO;f4kitvTb_=9tN72 zrum8xA_V|Q(=-!8B#5{J5%)_eKRkKz$+7gmp?HK<0n$e<6#)S5QbqUgizg#0z?GPc}^*H z(lmuE%Q{lZ+;N<;<2di1K7D#^OgvIY&1Um0*L61mz+?~v^&kkI<(&T|j$FKji z(tGN000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-we@R3^R7i=XmR)Gobr{D#=j?bk-6pQJd|ea?z7Tm|`Ep^t zEWv3|6K}j~3WAnM)@=~fs7NnFy%9`7RKyEsClgd_^2Dqsmv>F++E4d^LEI90%X4X_S)+e(UkH)LgZ zfM0+{V0c0#NfSMrB;Amdk<>4#S5mj6PDu|X_4uscJU1*8i~kKHz##A$unX7={04La(|{7-CZV)%1Es)jU;*$G za0r-btS^i`rf4m&3>ffP1~>xDF?c8NyF)XL&{LHT;U(Y$%bu{o&4j{PX6&(IIOsC% zZ~@$u^tGgmlHN7X`@Y{P=`|;Np`_)K-jei2B>8p5>o+zDNmalZLf1dDB`I5b3%KI% zVM1g6%FAgMa2=R$?>YM7MSdUUs0b*xMY{+kJ0(g1j|in$M(}C|ArI$(6}BuBBm27f@5kJg z0gDKE9ReO9sY+6lM@WYU zJW1ex;B=mK2MEo#*=K8kH-S^YSA*1jg1x8n{a6r9m_90~Qmi@|uN83FBo0aM@n1w(LdVOGjiO zVS=;)D}ih@wzbYrmt*^lq**b!Dwp)9q!vl{Bt7;d+3)v0uZxT^k@Uho`Z2PLo_YkW z%Hyf_zG;sXP`5`{ho7vmCfu+o;3)8ki=>oL!haA(Q48?EXSIZN5&cg{0Ivckfo;*d zxK&;Rd{0>AS>P$5w~C$ktQCziKDMw?X&1?!yt`OMIod=h>30k|XyKed!bX)43Z(`3 zmM{}vpve?LsGRi__Pce#9>>zl6h&!DKakG>`^VLPW52_Q00000NkvXXu0mjfbm`7P literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Navigate/EU_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Navigate/EU_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..ba8ed727ef69999b2fb5fc8bd0440f616f8a9475 GIT binary patch literal 1770 zcmV000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-zWJyFpR7i=XmR)FFSry0E-uvu(&fe$ae&i<6i7ka2*t zXvkG~NqX|6V<4dQlP{BYGTNC;*PDwx}bVfxD zhK?_lNUbC{H|N}Q&)MhfbN2S3Nx4%pLyG^m4Qs96-fY%df26gB?P&l0{nhU7?g6D# z82|ud++0~%xqt88z18jHqfZ0X>vcnG{eqP8D^kiYo%5SRGYJxGAjYh){g5YJ#vL*%x2aQhz6^q3;ecyl4_x)7>AdchYl+tsY^WWOG z?EnB^j1|VX%sD@8nx>qYnfX5F{G{u;{{;Zk_x*f_JdZd^?FZF&-a#=mKG2~|3L^DT5B_o<3C9$?`K)| z*M0l;*-4VT0szkyi^YjzvG|VTIIi#eLMe5AXlSVL1mrl*kvNX`q-h!jT@iP0o3Nb6zz~vw|@$@7}$8T5EkI&+{lrlF8ZG**9$4UIYM$ zqG*rfI7gmia3rh_xAR-Ip-Iol;544 zoV>KQwl*n*_@NMDC`ppq%*@OKtuYQo{fM=)i#kRnPN&-E1}owAK;; zG$F(=45RG2?q4|PbBr+~%d(sha_8#RtM6~sC!HD`94uLub$fk%{j;S~X)y?bZ{SL$ zGLYwad7~Kt08o}?xs-B!qak^cBr9PUUfB)=0APN8ejOq75kiP$SynEW%L9hiy1X$~ zHak}X08&b+BuPHAzP|piTeogaYzNROgwP{|5CQ-b0Lpl)AjTNsoI7cn_8Erp?ZLr8 z>sdih%RmS<5kd(7*jj5%DP^{8zt1_Jl~O*BF@7{ZKQErTEesD2e=bc^b@%Swhffzh zdGe&Kwf?+PD%+^tG}hME?t7ls#2EJ|rBX_%MJfGgYHI2V09@Hj9vK;VzECKfC4`{U zr%(TJb#?V0eSLjD+p%NE=<@P%b2Dyqbd(Z8CgM2Wr?pNAAPt$ZPj$^@+SS!nvMlS|_3PJX06M1kjT<*+7-JVb z&#Q!CD8n%P&aPd%F4ybzFLi%Q+dOw;7HZRjiBjsVD2l!r1VJjLj47pzQfd-HGOcwA07`4E zk|fFVJO=;(N-1|;x4=2SL=pprnVz10cDwbo{$B(6KWWxtIuSJf6951J M07*qoM6N<$f+AQyE&u=k literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Navigate/NSA_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Navigate/NSA_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..2b3978e4ed51b8a86cad81c593ce47193662b845 GIT binary patch literal 975 zcmV;=12FuFP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-wNl8ROR7i=X)=g+#RS*a8-%FlJLs1M()P+J9g0>YDUAS-| zC|E6`1QlI~RFP0zT2Mhjx>QgRN)ZL^#)XQQjkOC!T!>w0MX*s`;cW4}0?e@AwAiccR?h!TurKj%(6Lf9@@&v9EC& zr?9dWP-`2HM(`xA#VY2G$Qs!#BfBkBjQ*@%%sk8Vy$D>$#6H0*qlX?9`xf&h5x_|-t3_K*Q8Hk9Kk0T zQ*HF&sdT-esG;(2oW&QI!d*#Eljewg zGGrDn;1B$$WYj7?#RGUuN#CWs$Sq2S4Ww>OdrP7H0EXMxpC0t#b-bnof3mvSUM0Av z)5Ej4Hw{Hn+fY`^YGUv2!C(T<;Z}U6w3U%c;RoD^SMV)9O8PFsau)+Nb^REu(|ZNi z<>mk$wYi-%#d$&r@TwA%t&D7v9;GH0m3mpq8_p_0ej?9Zi92x|k0>1Z=s;4fmP zjd7*jTw+lyWvB!IqDn6&sRd?o9C2sfOq1+$G(|9}2 z4klQ)5fG_!4(FRXI%T7#8fgmmFQp7_N~M!Z{O-ZKN`3X}EIqcj!jL zf)clPs`n?9E-}~P&2D7^-;AZkizQ`f^;e#B$_g&U;p*K{r3~ts)f8=iVlFkVH8Q5u z$xx+GOB1&Vr3jDXSYoVo=nN&+*t&9;!FN&_eA6}$K1y&uRL1tR9cP-UJEXLw!>Ym8 zZIt&a{cfvKzN#d^kP_PlV7HA?epF}bcTCuNjYPzmh**e-xty?*xuzpxDxY(C=1l5z x#oO*H2rj@KcJ{gTfznmF%6}QE<$rxZ{tI^?o$9)p=8FIT002ovPDHLkV1n$T%)bBt literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Navigate/NSA_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Navigate/NSA_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..cc66f9d3e73ea8ab0eda7a8bba349220fd822868 GIT binary patch literal 1630 zcmV-k2BG000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-y*hxe|R7i=XmQ9RXR~5(4{d!-v-}9Rfia=rkL=ja=gOCzd zM3W&UGp(I*qimp5B^3zqp|*=Ipy~puiUktw3KmF^szM3`#WQ1~L~T@$0unHrw(3YF z>H>sDRWg&Y{jTlzb?>`}MeN|XNtBASe0t~n?*E*7&p8AU;ePDUp+j@?^Yi+5q8jS`=#A8aSuPLRzP!z>1BH91|gpiCewkL#mUkGuT5b|cT z+0-8!)MzvwQ%XG>$MHjHni{24YK+kUFm@o6QqDPdT-T+Z=e;L{c(vJV{`tN@$B!SU zwr#(hB+0j>l(|wW9w{K>fAFRgA%qCV7)3-v2%$j`2-kIgmu1-tmo8m0cLg0ea)gIr z_^T+29+y&f0Kkj^>c ztJUfr0Q~qPpnARjXqu*{rIdS9SzMvIPZjE_>OJcyOh#prPR#g z;^NFCD9f@>E2Rvj6afIGlo=vEx3I8a-BMI8mygDAd?3&B9wCGvA~MFTa=E*BG-eP16UJQePKB5CHf!0Knqn;yyyiqSm??-y5Y=oFvJCa=CmI04`Ag0AtJ} zNs<(dF>c#-;JR*DtyZ16xw*d};@d)qYg+3aW6ZTEik=~ad?1AQJOIGSlP3>)p7*mX z%RYsO`J~DuNsKY(5dZ*k`0(L5-}hhd^?DDMN~MnDIA<7RT>#hyfZf4hP*6%U*L6=; ztJO#2I6jl-`45Vs_(xF`e-J{PiK58KvaCOqb|8d^FbuCsDZj;MW@h$hSr!sPEK2F? zmSw$WjImp-*7dQ&($dmrN~O~2;c$3a2=R8F=kIE*Pbj6nDy1}9YdLxbWKxkaMi)g9 zhGDp$B4UV$jxlDawLX%j>19OxTcgpajU6sty!fA;ot>kI_}i_mtq%ZTBhT}H4+evZ z)>=QW8;vnKj^i&5heIQTaA#*{p9Fx`*kfa3<3mEojaset%fVo9G)aw6wIZTCH9OfG;IU@<5*F*DT8_ zE2R=dEbg8)07@xmjCH%+?p3zEy&a!Dd-ltDo*&d&XA?y=S(d4yC>~DJbYC3D1IKax zRjE{7a~x-A+xF)WF(`^ckCfd;L`1YKt5hnLHrnlWla9!5xUNg@ARE&(?Mo@S*7_@q zv45_wumAqSg$qA)UH6IE+1d4KwYtL?V|N-iuIo}t=^Fr}7Bm$+Qm!Qic1pmw{R6GC3`ecy(O zjy*wxqA0YK@&RMaH^<-W_4<$EIDRb8^LVlm0|4=T-=>tl(r&kNfT?+O;>3xcODVrI zH73TV1kQQc_x(R{&VMR|_(>ec--x0pMnpY6AR>bA`*XhU|7LA%?bevMtuDP@@5LYp zn!fMPBO;wlBOwG3QERQMgpjBE{r*$kZg((-;7y~x@6QK8(CqbkFW#1w=^{274Q7ma zIgaC}`u+Y#M!9X<1*LQ+Ns?JawBUb((W_J{mgjkA7-KJ-KYzZsCunRdD=Rgv^|Nst zADCKB0B(+#f>O$a5RT(G)bqS8&iSjWtE;U$#k=RawX(9p0pPyYEdY3Pb#?XQuUpgh c|1OaK1%7x*(%IRS#{d8T07*qoM6N<$f*dUd#{d8T literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Navigate/Navteq1_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Navigate/Navteq1_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..cce839ada3af1869edc8b592cd43ea18e71c993f GIT binary patch literal 860 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 JPDHLkV1jpKp*8>j literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Navigate/POI2_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Navigate/POI2_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..b35d07baf130c0c31d652be10bc8b2cb766ac2a3 GIT binary patch literal 1422 zcmV;91#$X`P)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-y2uVaiR7i=XR!?XgRT%%iH*a=!Ch=`{H?^0ZM5xhfi`5u} zQn#2;*re$xo6Lw{aWih003jG{rK_Y2kYzW z8@qXr&myW;tDJ~trIhbVDW{SoDH4$d0Dy?GVHi!*H1C_Hc?%J5)@n8NpNXo~>b#Wl zOb`UGMp2}tl#$k2QThN8kuk`y-UDGr#*J`zuT@f8Weww=Wdi~*uTneSsPt9iYl{k)r z)Icm2ixZY*eX_i~Tn7MP005;@DWkPM>v>)b00aOC0O&YQmUDh_kOUFgzJ2?w{&%fb z^N8px$8nMr4*`HY&x?uZY^hYrY!Qu*j~@%e@PL#uKtxOdIp_S3M~@!e=z}gSEW9v3 zKfiS7(4kx9a`~;kd}U>2-7t*1hGFzeAElH*7={PN$H$Lt5oxXG!Z6%cC5$l>5&vp5 z8t#DX!)~{G%yr$@IOm@YMe(6w80KJcg<+_*)^h*=d}d~5QV206rHuOC000n?27qk8 zC;$MIQoq=?{WlTWN~xa*SrE~t0hZLONJ=?1Gcz;E3WdV{BuVmG>up`FweD%HUn-Z& zulHs3di^$IY>sn2SFhK9?8|3oXZI4(v{EV@uobk{DoK)jKA+#uh$x?qmEjSggCH;& zV;AP<=eOFRUa$YYva)h_P|KDWJl}hD(-}leCuIs_SZSj=70MKTw zR_lRb7;VNF9|lSlsnhASgCO{PVPRpme^D-%r{XyN&UM{@h?1QQWsGsdFxu^Q`vGe- z8XM`T&(hAL9EnJGIvtrL$=T`YX#)VjFpSgPZudE*R1bHE84;0bnpx8{?>8Ea4VE(B zux8nUMqpLpZgwta7NbMy8V(dz1I4-qd3AuLE|)lQB{DI)+l z%sDUhdObPHAOJuigvA)Uw7R<5+adx0SYBSP+qQjG2vJO(+D3+mptbIWVfdo&`-hcM z(GIyGA_5^q(YEcYOG``j{>8RRb6xjBKA)cifRmo*H32{mf$1O!##67iRazQyCWI*F za=B~mcKgC0_O=38TU%3zcuELyrBEn{e$IySMv(q_`vm=*6bc0)gt)>OJGHj9wrxs` zTuv&L%7RkrOb`SI2A7k8kPa^=_c-U57Z(?ocfxz-x>c!EH~{Qw-2#A{i;Ii@ecc*9 c|964>2M;&T4asJ-a{vGU07*qoM6N<$f-QcN3jhEB literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Navigate/Sattelite_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Navigate/Sattelite_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..6b6296f5c2951ccdd9d6f997bf44f59298ae4894 GIT binary patch literal 910 zcmV;919AL`P)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-w2uVaiR7i=X*2{|>RS*X7U-$H6OvW*ZNqmF25)+MofS_cj z5m8qYK~Oh>h=?w95pXGppc`i+i0(8Xs3_wLUm&80Lc}DBe}Tj>gka|3eYmJ<@5xQy z>lF_)xBH$`Uwu`l>N}?z4u@tO`*0KXB#nTu}bJXB< zEQ_=ZI>0B5VUpZ~V|YZ7%6e?^i#Q@SxO6fsfOh0l7yrw(gS0)8Se+5wi?^`W!M4IK zoWoDa^p<3QHowOs-;D?GZs}+nz7pko9+xK5fvB=Iyn;{gLjoPZAv}reL=_V0KPQUh z7uTXD3+4(iDb6i5h=Wp1g;X*_bZ+keYcc$@3(t&*l17s_zYj;M|_YB z7dxC(_)GNAclbWvH^d$e5?hm=4`4mhHJ1@yCiZ1-zV|yE4Kqc{iBsbmY)>caiM_AE z{!CFn7xpuadvQI!!0ozKq)xEca8T^^w|FWE_Y!-5BdTMeNL`HwGrv1=L;iNj%OKf5 zmVgy*6y@JHDyH4zEZe-kml0iy&vDz7h&J%1sMvXYgC{bgf70EE(%lp#JxJq28PVlp z4|bTmM+-u9uT1czv}v(6vDV3}PO3&x~mdR4o6UW6y5u}a5haIzMX zaYE#}9sT0z74KaUwey2~%5~cl`*fT4RXmi77KCh63DkD_F8n^`XkHv6pJvph?rn+Q zTV*7wAB*#(ZOSIYp3Cp6@mxnl&xrPDTVpP5tHe5<*cXWEeWH5Sl3A(Tl_-`k@piJk zTQv5%i5h}4F8dsO2Mu_Ax{&4ZZ*A;0wSBw5T zhKEf#_000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-yrAb6VR7i=XmO*G7*%5~Sdi~yX&vd6pGa4s?TmmLi9K7Iw zv2{soFPn`w8`~O5VAxv>0h3Gi5CS2X974z~>?wyBHitlP5;PjitF_QBHnItk9Y_K( z*jmUTMC>7&(Tuu#db<1ddoKsIl#y0mwB$jby1Krq>Uw__8DnsqbMD-^#)%UrrnJ^I z0AP&uwzjr5o<4orInMX=X`p7a$&E4Jlv2JXr97pS8aKw+06;{kWm#Pz#B(9UheY(j z;^JcdnL*8F^E*({>) zMbQJ!`4_a-mQv~?%d&pj@An&V9G~_)?^OUR3;?v&uO~^OiHL*{YIAdQ4ZxoP{C#U2^r9{M%B+**y*8zY}Pfs^|-#;a# zOaK@nvL+`d-zb$z9ubYr&d!bl_}pMHP=`Ts&9$yv^MgLBTB&E`ZHh7J*FDPp`p4`lB&s2*A=>=SrzstyY`j#+X_mD+YiTLRiga^E&6;BO-rpZthEte& z9VIWCG3GRz%^RHay61UpZf@?&L{tW#cAL=H0BY=T*^M#k$&)AV_jC!!t^r2yQb=4^U;`s+dn4?t~x ze%>ac%5XS5>K}nIR=Rlc;%kht&ugvO{QSJv@Aqv0y6Be_K#y&2Z*N$Z)nklt>|Qz( zhT%V@l>f@}{Nur3@B%<4gm{_OsVIsz@;v`{mSvl99B%-~QHZW(S-oDbx53ue*E@yO zJH{Ajt&wG!%JW=FDV3B`8DmtZ)A>Y3X7}WIo~z=~X`1F*>ph`$gb>fy*Vj9|NPpFF zoVU_6RdF2Kwr&3|2m&g6@h}X-si~`B5r7|#g3g~m|AU>Kov9!QVj|jW zEW&R0mMfLYvnYxl03)J$<;s;e(=>gz+wJy=$Y4ad0g&(eZn<23%otk&kQrmXH5?A# z2!dc}jL|r#^fW#`KIS;ijisff5W+2$N&*1#JXcwkMSFpa z+WEfU@O}UG-Me@9$HalV(eL+f)oQf{fY~4jy7=GVBO-#7av-JLce?j(pRhal#;et8 ztJmw@8ufkP!mh2Yj2< z)($AiOP7RES_jXuSXc002ovPDHLkV1h4c5*Gjf literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Navigate/compas1_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Navigate/compas1_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..4ba5243306e499624d35753a98c3c2289aeeb072 GIT binary patch literal 1020 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 P00000NkvXXu0mjfRvCHZ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Navigate/gmaps_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Navigate/gmaps_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..f25c882e25c1715a1453a9bf53251fb29be005d1 GIT binary patch literal 885 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Navigate/navigation_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Navigate/navigation_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..099991664a9adf8573331dfa178462c922f88a7f GIT binary patch literal 1283 zcmV+e1^oJnP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-xeMv+?R7i=XR!wXhMHGH-c4ueT>x{ilf;hmHQmI_4+^SSi zRZ1KsMM$VOda5|J91sZggpd#i+7p+G!jV($<_GcvwGydPso;R9fR-adMM~|p*UpZ2 zXLp7J>&SMqRw~|Uv~S+`&3p6a+lN|fIF6k@eR^hgcJ_o)$^!r(g!udW`;Q(xc<}T% z@i>WSWo5=r! zW*Oj706GJplomMWmg6{IMN#z8=H{l#B|3BFjOlsa7oAS$LJ$Nk08n`ZIfR6BUMZDI zw_B~&yL)?khov-!Hlr^Ej2Kq?4=rvPxFTrM{O;KPBR3>HgE zOAGye|56YH%^VT{0OGptf$O?GL?lP}5fLE>f@Z(pzf`SO7e}C zq-lEFw(TS*Yd}PlQiei^Q^jKO>>-g->YNZl9Thal#xM+vG4{CI?f%^9bbhfc>krd3 zSx!~}03d`=N~v=I0Ay}%ZbnLZQcBsM)M1RVf?*h2_wL=3_wV0VhGBfm7<2OWXIb^7 zlqcur=4MExQaO>Psh2&*JR`Pk_tG?79ejx6c%3oU$!Q7z08mOLX_|VT=ba#0YcG?P zBTJyQ)|66*Qu@>8=H_pM@7vqke^N?+q?Ec7%BM4IFZVRVX4^JJ#MN;;!!YW$Z5ugZ zBSsL>N5lwnI*1TrGRB^SVYof+>-Bm+Fvk8OgwPy(%&>j4)oMNBocn~37qr%Lcvtpz zT+6cVY;A4rFD@>=Xqx6{h-f59@_wVy_`6!I?l8tK2_f3!%|r+>4a4w#-+zQ!YgkxV z_}usXx1%TuhBs@ip za?kU=+1S{4k7Uf-j^jLYUx;XGtsfT(g}1uh?$^y`b2bdab{K}8X0urig5XQW*hMMj zV?=zWe2(J~LdZ5iCaS$&@2=~*4-XCwUKvw|LxFlLI|O?9{FVq)H;r1p_DR) zV*mg-=Zp|?z0qjIheQAXYiny8j^o_ooKI(MtOs}#)O>_HO9nXS(~jfZT3ub;7&u4n zrQL2{E0sz$&iSm?noQEMant`9;hfKwN~K!6-M%*LA0gV^-AxejGUxnerBdOP(n1E1 zOE~aTN(+@rg>%kt5<)KT?(U9ATJCVNyu4gZlH^JlhNq4>oIEs5^G3a1UpoqK;<&ZE tyleu%vBoU`*s0g+&p&RB+y5OP{{_MYh)j=Kl#2iW002ovPDHLkV1n{LRgwSz literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Navigate/navteq_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Navigate/navteq_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..2bd2616ece7ccc644fc97c95cba65cd9445caf09 GIT binary patch literal 789 zcmV+w1M2*VP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-vk4Z#9R7i=v*1Ky|Q4j|3->#e8==vZeu@LNRd=M)iSf~gR zwGpvUE42}85&RoOunUNdDOD83A}ZL3ofe|_CS(fQg`mqtc@&6m%;!7vSl@9g~;Q+P-NiFu8LG}s{FoM=xK&5$3bOaZ$ z6~8bZK)FFF9O=d~yud}=>6EC9%Q%AxG>ZB&bc@DyRB;vO(4LQ|f@?S?g{3_U_*{~O zlfAfs(+Z(1&rrUE<5GebLLzkAVS7BVrZx*FI*jZ19^Ng4q$s&<4^H52k*JEtQu#KP zKvE>DOXa@@6M5(crRw?@Bm$!mn1f8^=#c4E(s38hVUz!E2eyjT@tZLg#8s(hs+bI& zU$IW2D?n;tQw_i-mdD;i=#B+;e+8SQl5EFuUtlMmVFNy44c=oQ_8WMEz4#EMyKoCX zu^(&0!Cq`COVyE&l?=nU7r^6E13n86ZwBxdjA9+0Vg(*bQ(~7i9m?T+4LvjaXdJsk z;jPrPtML)*@f_PDM5|)01W`9W;}KTQz*Uj@rWuCy@OB_V+Q8We2b`C3+QN?TdRt)Z z!xOxVQ{|JQiSMN>%ldI!>YHHoFs=k9X21A`rHk*Y#a(=T(#3bmJQrUJCov?AoxF7O zZ#MA!tB1`{U`%_cbn-YEkWMz=bqIxZ$w2|(gX509VOr* T000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-xj7da6R7i=XmQ83}RTRh1xgRs{%}nofrU{6+aucd?Rc(S$ zYl4T=CiU{n-jvqfhGCDds#>_1M0HsuSWo6~*!-o%7_p=}O z0?p0M84>xIh(02sqalPNB2onaK*U08y=JX_Vy*od5$|<69e-fZ+}zwJM06od(|7Vb zXClg(*#p2}11hDAwKj^PNY!e!N7mXaolfW0zCfo>pH|gs^}8&~K1-6MB%-u`0(?;b z=?AdZ)|_*dIF7FuMe)s@J9l_j(8-f0O{>-VzSrxWOOj+A0C+dREI4t;c>D$Pfkqk|aqXA{VEorYb{FqtTeo zvTU4)(*3^4o+LyhqBP60@kXODJp?iHsVvJF0AP?D+ml2@cFgbc$+mR@0FY%FGxI3` z05dr`IpUl4Uay}3fJ0jAPEiy!X8xdBt^O_|uT?6Q8})j9nuva3=16P(cABQQ z@;pCJM4>NPtzmli?>~>C=zSt$BKoUVt99czKBScTPbu|Anx=oGX?m>J>qXxCMo|=z zh-hZ6BVtu+y`q#_M8q0Am$?QJyNFmIVk3l5>-BnXdGE)KF=NJIxPgvqij1-GmKfG$o&v|yWMt!H`@z1@LOwZ?RMKa=dLQHzF1mX+R>=&+MLYJ&dzx6FQjQYzR%|5 zu`%Y#{QUgFi{kCsZq3fl8UWZ=y9EIE=I7@R-flf_ui8NV4|AmO3%QWrLI3~&07*qo IM6N<$f{3zbEdT%j literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Navigate/path_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Navigate/path_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..2a6491355e3eab6b04fab63f0b97e424c4c8ff09 GIT binary patch literal 870 zcmV-s1DX7ZP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-v;7LS5R7i=X*2|CNQxpgAPd&POXwp+@BN541S(x!i*ojB% z7({Fgt6^hfgN?1QAw4lG7B*}Iu`tQRU?cGlNJbbo;;|yFb%Y+>HPuxX=iIK_zp1LJ z;Utw`{eJhH?>YB-9{09Jqmen~5N^S0zHi_=tj}ZIon!qN9>lHbWGUBn(%Coo3}-Qz z2Gp9dqsQ?Q?!Yd#6Q~%pGLQr4;2d7Z$MZUB;|)BEKDKK8hHh=Vj77YS7crdWsEc=S zT+lL{06tAd8RRNH#4{=?+YRM4JSh^~bTSeY^>B5**HO08W<4?1rtRo4e1Od=y4q0( zf8agbg?k0HMRprbdw2?`Ye$RtQk3sj72SmdXyG8KzJc>yF*3fzouboA z9xmpu$YS+A%3T*nMVce)s>EI|v+k@*=iVe4HJ+D~c4F^=e=g3G<;#GSwZ5Qbnr^As zbBVoIL49#(y>Bwt@V7W=f5hEsyFEd#*e)ezpG(i9Q+Uq!9?;}`LG)EW9Z%9Brp=pp zp)5=~_}&$R@OS_1;JZ!?=%>v%_y#zU(X1Hfta-@Q;Pn()N!t?|7nOM~C%228&AObl w@wF?woYb;_hs<}~`qciuyCO%m{I3h-zpbtN`sC#jVE_OC07*qoM6N<$f+Q88sQ>@~ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Navigate/path_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Navigate/path_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..065107a11a0b8383923fda0e04fc3f10c846e105 GIT binary patch literal 1404 zcmV-?1%vvDP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-x_DMuRR7i=XR?UkPM-+drx~scuy0?0I92ax&6o^O+xykB9 zlxUXStnTh#kO)FPF6NjIPhupOCaLfA-J6+-t}A&^P*7FBU%l^#LnUcnv~KKLVPzE3_e?3UDeMeI(F=s83e&MTU%R;Q51y$pvMWS`{TSNA(K)z zeBZwjhT(_z?%mrqr8#`r_x+0{NxK9ZMx)YH6Gc%B@;r~L&kkviI_oIZVeHcivBQ50<=A`lT9UWjN(DYt?k_^Mv7|6*B|&{`YiIaVe_M2MnjGfmU8 zb8~aEBc?lk{J7=1?vL$u`!%IhY#0U#A+%|lF%fAZLe9AqLVUZjvhwB8qeu7qzJD`K z(*h9-0C2J_t0zekm!AaAd9B%O{@L&MXIiaRW&!|so_8XS<3mcRE&w3s+!aE6Z&}uF zd7i&QL>d5$!C(;1%*@Pso+pUty5l&=7()QqsMTsmEX!Jqq9{T{t(1zBBst`H-U$F$ zH30y$)~Avr8IBSpqHdODi*XzuA)*014Qmq-IRI!P$}01_t{WSM@wMx^j}624XlrXL zEs7#fl0-X>a|!@f&8exWrj+uaQYuBnDhde^jV#M_9LG5kRnb!bzyL;t(loVw-~Zfo z-Rq9yd_hF#y4|j)luDIS2dAc{nyk@i94Lw+D3ftpqtda2i14CS6h)q8naLPCQWV7> zjIja zdi%82N$CO`0D_S`8WKiC+BD6dgb;rdkpci9B94d#5dk8mhzN`^)3)u$L=*zR#V`zO zN~vVX4Nn0Pv4e;M7)s7O&ts+3v{LF#!!T^aFg)9~_j#W8>)pF|KiJsVxFm#-j4_Fb zc9vzYCrR>Y7=~6wQfXgecg!#hA4w@YjIl`~QkBi0JbAJo5nqL}x>%M~_kI5_0D#HK z$skFRxBLA*BBBNWDosVhC5tg;8ivv7bUKgN`ucjiEcFikt1A+b(pvYm)^WM|T5AOW zP!t7>oh8FTRGOJM=MLxm;rjY|o0ZJBgb>^1Xa}JRWEXcq2*DU*w*bmo*X#A}2q7MD z&TB6Ksp{DP5e*oNzAwUhmE}QLEL;5b=tX(uQY*Z|S#wp64fLXJ_AaUH9Xn zC=3A5|6zIh7NwLnW9&++)ye?I`q7y)XD&xkbZ&<>!8zxi);d#4^{ao3DFafrrlD@@rGD6zCFJ0-{^EY7lzMA0$^=z zEl0%nrIgnijfSjzHte^m>Qc8J^G4}r2+S000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-vWJyFpR7i=X*3EBCK^O+`-#x8XQ$f*Kuoor#7fMBZEPTWQ z3-)aI7o>@uL~PgyUFoV=5wWwXP>ICKvZV=%(%Wk>?`=<^Ou=vxf3w|I&vEL8zDY80KsbsR(!zXGT| zp%Dw&h#pMiCLVW7l;IYx;5QcX;|pW+lLyg+|5#|FZucW=&7BD;`=Av};WZgUPiPqq-4 zqj{n+g)FHc8;IXWT*fiH#Mby;RJR=1GU>$c!_Nveb@2*EB}=Czo7xzSz}$!73?ouX zHrGj#j}MqDS!gq`M|!1A?bq45vKYZtoRX~l9^c!9%Yi-Asn(UnB6bJCc_|sbN+qh& z`d;bWEMk++s(whGzrd~_n2)|Pk}R<2Gt5Zkrl$)vOV}y-{w3Ot8YMk}J(Ef2=aF@D%24OtbxFuZJ(nl|JJ=?EJ-%3Cuy?4UIBk5or6K;s+!n_J-W-#R$xsB_L`!4 z0uNOeRgz_GqAJ^Ji>ml=2RjPj?Py4z*QsgG*%4TiE0aquzWdU}H`ih1Wh7aUOyHuL zi*E@Ra2s2!?pf7km+u>lIky92%|oS|$H@UnS>59#!yD^-oaAEzj_B^W^~CC}yKbU< c{MQ5WFI;%VV%9v~(EtDd07*qoM6N<$g0*m0Bme*a literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Navigate/poi_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Navigate/poi_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..28c2f358aa4f5dcc9eb2b49592c86aaea4362041 GIT binary patch literal 1203 zcmV;k1WfyhP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-xElET{R7i=XmQ83IR}jZ%-tNFm9D@nV0Tc$@{= z*w`?M=mVwH`%0RzZnN3koC|d6(j{hD);Chh&%-c0QcA^z0-Th9 ziUgcPEa0DuwOak%vaEU#1V02pU|W_|B_gD;Vk06drD7@Nxk{ySVFc1zUzAenlYkRu znx^Rxk+ZqE`PYL7559C=_mhQ%gu4d7k^e?=P7|JI6o_~0F*aLv908CWE7&8sS==FNNJ+`y6vtNvQ zn@;&TF~*RH^3wnSuZzPuw>jr8cXoF6S&`t0<2YF-T?snG+3d=bsT3milS#D(AL)05hC6ZLRe7Ds$mc! zLZ0V`Qp#1O)b~000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-w5J^NqR7i=X*3WBPRTKyC&wG;vF zoG~{;GEVitW!}7Z?)Q7{_ndp~t-9T=A#DQJV_W{8!x@|#X7b1o-=}aFZcLKV{I-;2 zpW_|8h2`~tssSsy4@Yq`E@Cl(dK0P)WFs2*6wl)IVTo!yk4MqQLh0Y8pmXey)oE~9ARlO&$RR=k%aRZ4t0 z&Wf`B7+2*O$8J29zEeG-3EYs8eTi4aCj1ExWz@IgiInby*ehrIa`Qu~F`X-G;*Z3h zsIg0w|J#(byOs{fnP)d_u>jX zojNb%YG?5y{=}WQIx!x`;~C&$l6Mk&yua6VQl3pXF7mW9-&ME<+wmsu$1!}9@-{`0 zT$W_3tQPxbDWB_H)grFMo|NNgO7;w1%DH>60oREfw(*rHrV@V%^EFP3cGD;vswCSY z%J>+*70DeJ4R<$wE26&%FW@O5b2BmLaC#({{RM8xsLC#|F{Rsw+eE>%@N!1m7S-Cx z=R+y?T*|m3vCs87!$DD9^H#T&F5bmG1!!fZua)hn7P+l(UR2z6Jb>9jEr`|qY`xxA zTIsV{q-8(az3$x>ht_C1mS;!R_dCeSxy{6Ev-+5r5f#hxJ`lhPj+fij@tzoYeTtC0000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-yu}MThR7i=XmQ83K*A>UlIdkuPXy)B{^PW}IMV*+28rLbM zkVqo5sIuZr`=5haYdDI{&dwg2o}NCblnMX< zh^V)>w|8@AXQy+N@9{yP)zwv|wLV*x<&$Muo{~~Fwbm8@03zmwVeE6xKjEDJ84*8P zTU)EXFlcpk^_j9PUrCbW8(EgAvMe*DR0ROz50Ho$=iIh!o2I6wu5->WuC1-TeW7`a&3nMOl`~r~>?~0D2UFb3P@6FdfJFO`hkkudlDG`+^o07FZAjzZ?t( z&xT>x1pswFzO)EX!VOwOUUf z0xd2sno6lx!!XQ80T2MlG)>EOUFQ2f3LzK~8Ju%vnr1ah!~g(;G3FtnIZjAxt-~

&YBQ#3);Z^o5zz~2 znu6mvPXWL>o1dRQCWJUuRh4oa=byD&?cKp(@Nu5!9mjE=C!&1-_?GYcFI81lIgaz& z+qZAOzq`A8Yw|Gc?CjiKTwL^A*L^NYl82;}ysE0CEXz~#^Yh23(P*5MQU+yNhH)G} zF&qwm=Xu_n*REa5!!UgJ)~#Fb4Tr-<6h&VrqPs+N_r!@4b7#+?K@Pol%@SQBnq*AJqQU*Z~oMc+-U?eL#&vVN2yr;GP_VV)bY!C$hbzS$z{eFK5 z0AeEgy;ACrjIp^SN%Fb5xrOuR&+odf8+o4hy(o%ailV3(9lz0m)D{2)hwc#~Dy_AQ zqR8<)?-xXLT`BcdB9e#*M0DJ;teH!fF8!(1YOMgk&$ZV7j^ntKrl}c4QOP;CrIf|J zio+1Ghln`?e$|CjemCw(ZCF_V&y; zjvq$EuSh9(8;!=lY};ntZuj9V%f|OA2Y?=RyWN|HVf2WIO;mzSe`9xIAssFW(Clu)nNPg|DtD*$-iw(S@ZO(J53Vf1>v-c8!x-tLT~ z-qwffRZ1zls;Wm?t=4O4n$Afn!!%8sNs?UbbUI%vih>YPBciIRssw=Nl~Ui8QudTm z9nQJSIsasPd%ME`0Ep;A$8o-&=lP*6Q%Vhp=$lEBEDwjnXw+8S@Ank|R3m*u08mMi zI7LyMF$`m=D2f39RF2~S5q)?dK~WTKIF56Jb3Qe$3K1dCbLjPYPljPwPDm4ss+bg9 z)LQGJDB?6tV<{ywO|#)R&h;pYHV#0Wo0|n9z9odPM#1!`caUY-STsLZ$?;Ru002S= zlZf8h+}tb3`+o<>{{e}cMrjd2=ac{d002ovPDHLkV1f)Z^n3sS literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Navigate/world_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Navigate/world_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..50a292d22c24ecffd38e5379249f82510493dd1b GIT binary patch literal 1063 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/BT2_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/BT2_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..c5762ceaf56653beda8aa92df66e2261b1d32824 GIT binary patch literal 856 zcmV-e1E>6nP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-v(n&-?R7i=X*1d~dWfTVR-`t(d<^$19vi4~N6NzFkN+3kH zhzbz}F=``eY)ldVg%A}jG-4Ai1XCqNNCF~ap`;5+KKuieAnUpi*|om|Lv%-~0y#)WB#Dtv&q(8o$Ur}5lO-i01M!#h}?MAXGO zyewo{F97%QxnKBJ33<=sO${ll)@sk-717`}3DKVm_zgQ+6?HOaF)_|G6PrZOKDY=LZ;Sf>(ugXoBG*UFem zR*j_kE35w-FD1sd0@+Gp9%&LSXt^X~2X5jiVc(rXvOV|~cZ6{Uw)R_MF4RQxIFKuC zSF?tLIFt#ugmhi}g1gu~Mukpd9>9DT`*VeZF)Qlell(o5C-FyCc@!VwPi2=55_^Az zInmIPbe;V3U3@HhatYVOhW;o?24kwK%`#WgwG;!<@I(3jkk~6j6XshpDlCg$lt^nQ z?ZuaPRcPK9GX5-jHVJ`Fa9Ewtj(fSnD`Mj=DG%YjiFL6~EFFBGi~04tt-F0)7-YRw zWld5g$$25^#vUsj000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-yD@jB_R7i=XR!?XgRUH1kH}iJp?QY)e%%-PadXYBR;wdFi zwWQP-j7gKV2N4vkDAkLtcv31z>8;ozsE1NO$6Q6a=YnxM#Uo)D?iWG?o$dkvpp=4b+mT@yrcz3^TCK2B zsf;B_k^sParBVrLnx=Og3J^j_2oZ!~xW8B|9@!9*QjUaS*p(%jtIT4t_-CO|7_}^G z$uvz%O4$m6z#)WO7ef52Y1;dJeSK0Xg?smhVJM}PBLDz+XlSTk2r(dph!$cUxu`dd*HsWeTu?QfmH2q70C6mNGT0072Vxv#J9m%DfGemF5P zv2S^Kx%Kqv(_^Jl=`TvD^^C@hGHw^w>-C44rnwkneXBniWBF34^i#E3{djP2@VusJ zNB8X6Gr4>B?l+Poso1vtw`rPrwS^kSSl2YobzS!%URYRI&02kLl>^3@=5o0O+qS2ifqiV$KFLLMwEEUe;;@Ft~nQ@o^< zaTta#JbCh@+GsQ?ob#HL5}Br%LkL|7g5bVk7;h&@(gy&WvW`-UF~&CmvV!$}|2Cy` zi4fB30@-Xf3-x+^U$fct5kiO%Qcz0G+`D)0Q%%#p;+&u3oaeI4>$E0MDP8h?|MrH^ z+}vCXA#{N;WC8dlziaEd-7X}6fes*2=okpWk?@4b30EjVWV2m%!&CRto zga81l)#`Oh>1D=PIWuZgaHW(10K6Q>@vrrI{iSBJSw{$UHDRR`FviN1(#zMbUAx}i z+m&gJM&pca+x-Ag;hfi?$+z;xw{fzetted z2%Th%U2+_UwPV&1Hyp=t+=MTKwmjweZSDhPu8 zI~-1ybX~tVJ3Cw5itm}@*5u@*4gfnEw*cVQ?Ck9Gk6XR?zXRldb}#d}^+X@J00000 LNkvXXu0mjfJRYmR literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/Chrome_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/Chrome_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..faa353840da66df3130557753fe73a5824771d9d GIT binary patch literal 974 zcmV;<12O!GP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-wNJ&INR7i=XmP>4uRTRg6Gfb&f5-p`dR4@t(7BMltH?ma| z1DKc?!-54t4Z6{l(WNA^P*z%%g^Q|0Shz91(gHp z13m#h0%qzWsrBY2^?-U&omFSz_n3M?EvwV&q&lG<44+)QLQd+6z^lMEU=}b=-4FZ# zoR3JC0e1lFffZp}1aPTShszr>{DL5=u75ZMoFpkh z?KlOD$2Q%uS+jQ&um~8;tR0TO*8o!_$?7cD zI8NjceF3&7PmHfKn8(FfcXC+-674}z_Auvd_> zPzFXzz;TiauLM@taoR^p;TOP_z?(4#8U%4SN&AL@$eN8O0&6y~|0O|X^{Bci);rWA>QgO5QJMFc z1o=W%f+`VB0XrkAHNeZUK0~U+8(N40;7(G}w3FWD&cM!X6VstlJ2LtHMSY`kx}4c& z64}%0s7=~LrSZMveB1s&U8i0fdbY>Zu9vEvYLB{I-S2#hnF@@m#+TR17XYu2T6ue1 zen0Rz>76|eTtSkaCBRiAZ7Tu`fwzF?q7ddsgG=2M%3L;$nMliEoO~qaxc~9vBs000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-zI!Q!9R7i=XmR)QdR~5(4{g~OAyX)Qc?xt}RBUMx;bt#lD zIZ3IAW3BCIZN^?($y10358*>XP^kq~MTn>^yr8xZKw5-IK~aKKnOJnAvImsmo-hh zj1YR;wr&2YLFICJFplFNd!F}&IF7YD=~yWh|A&J#DJ1~_X&8oJj4f%J_Nr~$Qx60> za^wh3BoZ(AzJJp9eWB|*Boc`aDW&sL%4N^<8iWvH7{+b@_!8&*sW1%N<2aV7R0=c3 z&T`J5uT(1Xo}fdA4$;=u*5B3Z^^r!S@kvWdOPEflf0oH)E}c7fZbw^2Mn(#p^ApWx z^LzDr-7rnl%x1Ip+S=L==I7@(HS}&#CX;!gUayb%zTZfv(^Av452mK3CX`b5^#0<- zi>m-uZSWD++T4I!m`x~Hc{-vp&n zsh%JR9w&rg(=?}T+n!WPMM|k@LddrU2M3?Z<#H85NRe}X9RNN~Boe<#M^dYMR#cegE-fGTF0vM^ehZAP5v=EaIHMwjuI7@0X0RCn=>Dgb){Nwc1as z)oK6$P%4%7rc$Xt4-XIj<=C-f|CCaG0sxE6X7hTXP`JSud&G6!M@`f01AsU2fddB$ zaU6Flr9jiP8#6OA*Ec}3v$Ow_Qrbd@#>~vjvl|cqfa&S!k7~8rGg8WZuIs)}DP1Lm z9B*%Le=~}rPzZ4u08kV~o%{FiFVI{rw=WFC);l&XDW$gdKSC=QCc{000aO417f?)kFwAh7b}$h}K*#w~s2NT9r}>LI^0OKH6SPDdiAC z9;TEgIOkhnd-m*kgi@N4QhvOVt5ho20RZ~?`q~H~ky6S4fYy!nMhGFm7>Cj0p1U0+^USXjjX z02t%948xGkW^=D;nge%>1_uW}o6qNMDP{G-g$pNUXJ?&z0X8C;Or8wGaIaw)0%QCZ zz@3-Db=@nbX)bZj5$F6=u~Zv;Vb=KT5dr~elK0AOfn=xb3FeK(F{ zVVdTW>$+DqL349+5ytox#+dRv?{kc?(*OX?W|Jd?0!rz_4+60)>&tN*zrMb{o=Bxq z1Y`Wl+}vCQu4;zqM`qg;J@MFBA%MobxM-i;F*5Sy_p;1CAd* zu6dq!A_#(K>-D;67zWE^GJm*q>C)ymu?5uK-Ayx@%$Y``F^Ul4$z<}frfDyRVd&)Z z`O``%$~m`P*IlgDYEfHTTbq>f8=Uh|-}j$zUDr=0lj&?WYdenf{c5$!cLV_djE;_y zIF4WPegE506eVx{8CG);Sc zY-~*2UH6{D$?)*-H{&?|Q4j=Q000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-wR!KxbR7i=XmP=?{RT#&A^KjbQM6EG(AwJNR(bg`yREpiG zf!ahjg1B&Fp__uG+GV$;RuPI-5sMIzA}DUGZbT7L@j-2+1*P~P8N^PKs$-g&X8gH0 z-%T#pJL7;K9ELgPJOBUpKDVMWq>KZ10%P%i9ykwN9OiO;i1SI{LE!EnSr=!WAo~t@ zA9xQ~=?7F9;L$YjEN~Cd1C|3QyHE*3)&n)*Ti`J8&agyP;CbLFpbPw!*DvViFK+}I zz^lO1z~6(2>c9!$F;ZB1CE$6IT7dU}E1^3EoCKaE7s_hk@{s~b-s&tw+5al35WWQF zfYBiREijJcf%8PWfjy*Lyak*kRoZpHwZPZFkE|7tVf{H^C-6AX4Bb{>O=aL&=o-Ms zr1FJSWt)M0z%OC-3UDaGlX+DGeg$3uUIK0dUI*?XRp)tN2hc@D-K8$6O|_+Njs5(3 z%_J>#R-KF0QoHI&wXWWweyT16<}P(Lbd#hiX@vVt{w>eMIurS-#Og$-b_08X3#6Xf z5SWu$j>f~)a$t{FfeBJld%#iv_LCE&2EJU_ z?}fqH-Ls@3sRi~#9oR%lT#r%cHkH(;T7O&QjfJm z|MoC$C9oH(q*%_gHclo=hydOuHQ>v@R$yCrw;uR`G{rNy54a`_p9jumJ#t)atBdLf zB|U_Ct9n%ZOzp(FqQ0r_R5yfPRsATi+JQ}3!~UU8mJrp{ht+r0)9M%MLA6oPdm^yr z@(r6EHp0?N(b1>X8~S*LI#NP_dW(7?rp2YeY~+bhr_{?~Nn8C;9UnkeT$|NTA|lPe zn##_L$}hy+nhmnA)Ez^R+#9;>xZ4dZ`VrODnMiUo61ot3kC+DLn0mc>v-*H(*tSBq z8Fyy_YZbffDX#%XNl$r)G_OXYUlxJiNyBoKG+wH}pHb%PNKg5G)*j9z1Hv(_ejb(6 z4y!N5Z?@*+Y$000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-zElET{R7i=XmR)FE#}&uV%-p$q?|$67AKDbhHAMx*61E$t z!BJ^itl-*I(%M>?^r25pNul(iByTMtekp;z#gGzO45=RqrKQ!bB}*|@LB`Os7#uKl zVpJMTQb$XXwD;a!@BNsWJEsrXH5)}S4n0qoVdnokbM8534nahC5<79?#8|ajJ*>4Z z0RT`+z3uJo&0Du_?L5hO@;FevUN;c&ds50%Qp%|`O)H3)0RSL`B#g0L&iOsg`QHd3 z>y1W3eQ8j=UZ0mzz7mGvu{e&klrq*@D*zZCAe2&rb8cCdMYGxLKRM?Y8;!=*Cjy;0 zbB0=$^+ps$FLk?JA*BolHz4~7;6Q+Lo^>3@v~BzMNs_#F?bg)EEabG;Fm*fI{c{B zYI9K({WwXI*m0a@u~>ZHvaB)FG+ozqopQN+$F}W{hRz`(T9#EVm&=>?@87Q#i^ZRm z%jLFZS%q%5+lk}&rCO~v_ZiU4%#4YMuXej#!8zATsXyDceW_BZ{G(JVH425o1zEKiq?D=Wc~2{)eqF28o`3M*!OP?0 z<3BGH3cu@gI?se*cr>5SzW@N&C;))g`g9aU+As{$vaB`$wDx?mTbe()^EKSq@_`ZK+96BW6bkBZ_{YCT03)dbN4vs&k7*~0GuX-{C01% zot>RMR4f*M8iwI>4<9~!HVi`;bnPpMczJ7U>ka_G#KZ)hn3!0I<2d1*Tb%QItyXKt z7hx1Rw3U9DC>F%08uv)TMyJplk5KYl#d zZnx#u)|MDupP!#Uq_tkz+1YUjAx5=Y{a3%=pWWEl5EKAlV`D=QLf&*;HzTEtgCH13 z#LMT-ovZ8zx_$e0e=lTVVWCPXy%Yq&m{Ll*uA8BhzPYinApl0Y_sYu3s%_ivxUM_a z@Are<-QDA9n*Mchaq;>6V57FUxcDul)L%T$`$iN+J=b+Bwr#(&yu7?R-1C|D$oKu% zOQq5n0MvsZ*i}k>-Eo{h)M~YLO6jtc@~-duK^(_;@ZiBLV{9@_(}g&W=X<>#6GHS{ z*R8s)+weT^^-=B5J>~U!ooTJ#2*dD4-ELPXrDD@GbD2zrP)dERbr%3Mr8KX#E(;-O zk|Yle!>}C3F|*n1WyaWROG``XV?iS^uPLQo3B&Mc6h&G}84q9E!4@Qh5YD+}+cwQ+ zvv&={xY%qqSN79;?6|eCuwVed6OCH{u-S002ov JPDHLkV1mcUI|2Xz literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/Hand_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/Hand_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..ab35cd13af0973371a84a3935b718965d9b74959 GIT binary patch literal 1011 zcmV000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-wZAnByR7i=X)=6kxWfTYS-+P(bCMu;y#Ti$%741Tl?p!F< zpxCNlK@huepc_#^T`H&`4z(LmSGrSN=^|Q}MWKkIqOC*0jYP#XNo(`+nwR0Y_|9$a zdrdIt2bVj1_x#T}|1*7!h_KEzifgeY->2{+Cf6g}zmEMe+>Y(I5W@(}rLrIJDaNt5 zCQ?MKb?u3WBN5S#h}noZ5fRf7@l8Y=kBFIwn9RL){<~)_yv8cjHSszgK?f}~unBMB zXPm)3gS z7k}k@Us`-1L4M2c8}J2Q#7^9R`SfBkF;3u#)jYZzk6Fp0MpE%DrtusuRp?y8CD@9C zSjhhyDLa{1yL%N4;@Pw+Y68{TqR>=j+@g}|w<)v^;ryChB-S&DeOA$~bidW}bLH7` zdQlnCNY57VdwTnJ8qm!BR$}g|D;m?CCCf@229-Ef;O$hlkXI(ArC1Ut%9?Dph<`i9=O8m3IrNY*q>QRC@L>-dAE%$;_v+ z>b*++qnNA!$DK>vD1K3bSufNUu2N!Ed9#EGT%E?%sT;3ben{!YRf{>Jbm-5m^s&07 zgSa)HH>K>HQZrQ{59jwobwwS#oYq(EWd|2#m>wg^}{{eEK^!6i2w^INB002ovPDHLkV1oIO;vN71 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/Hand_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/Hand_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..4488cdbf7914fc361b2039594893a9630744d554 GIT binary patch literal 1663 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 M07*qoM6N<$f~UxP5dZ)H literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/att_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/att_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..7e31a4be46c30509b423becf73cb03a4a010fd06 GIT binary patch literal 853 zcmV-b1FHOqP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-v&q+ih&M zi0BaMCACABprA`9q1$3XhrpCN6osG{H5Ds7Nr%pc|1Ns-^Xu?DKjz(K zb{k#rg&*_#&HFsx@ALnC8&y>qa&5*ln9T1PT*ve<%B>;x_h2`kO_EOTb(8E0e#Qmd zUkRwOibrqZ6FiSa{F6YnLL&_s#Rx9rFisCk)WjEf9}Ac-<(J8p%HwF`YkZ8}YD6u3 zi+4m=dIP{$T2&f3iIX^}2xW7b@aNbo68s<}Qnr`6dlRd_S$Om&PGByrdk~Ux)w&bd zhchKn8<#}+&aZ)_BpVmy{|XlB(Cre{wGv5%bs~p@%Cr)d*DgGoPt0BPbF@dlN~%J* zQIOoi?R>8jKT?qViJQ4!uU=wnijLojdxbY+39yI_qDhb9#{_DNhMg6C)WI+KvM{8P zm^-n#g&m?K7n5W?&f!%4_jW2@z()KfO7~OT#fKsv-(B9?MWpiYncn z9-qz>jHM^DmbFMz^i4P4+qi+_Vw6lJaZi8Njil8_@oIYVWXjytAG$Su7jw;YeI@~V z=|u}iGTyh6;AMP|v)Gy*&!+5UypX?BmR98qt~JHTxSDSNn|YW@i{8TzX~1q#0MlZs zZ^ujGh7*m^g!D*ixZddI^Ze49kR4_M{k zyN~^%v>z97u8L<6c>Rp0&XL4ea#0!Pa`K#|4Lj&^($pV6LtjqHwGOWt?z;7p=)-~Q f|A@-9rVHeMm>2ACMCgz&00000NkvXXu0mjf>OPFf literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/att_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/att_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..24a57b4f5a7fe84d1ccf1684776fad63b8303f56 GIT binary patch literal 1483 zcmV;+1vL7JP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-yMM*?KR7i=XmQ9EpMHI*1tLo~R?&+zXp8Y@)a!3xwgs6*3 zSQH5xGzrAST|F7}U_2xULP9_g35X&hhzTNIg3+77KxWArSQ5>+K@j4>LpDg&I?Hendv0)Xc#mC76dywUZu z?qdJ`{djM&DQqhT1PaJ$(51=5270EJ*}? z-7cYyArYZ5h8Sa(l=2VH^JWoIbPEpvoQMb!x#xKcQp(>LW1`z&aU2_C%q{=`Yj}9L zUrM<}DV21$?Kn$2;*3zbUc#Ux4IV~oX?WgS99&lvN0v)PQQ)#@?VbzfIX1;&_MYaIkZu-PJ_pfgqo z07z@CIOjv9QfU+C{Fj-TnUm|+um6&Wc5}|}%d+e+5&cjs7CB>VW0qw%0N^!5e8Knq zX|46!Ns<@<(49II03hhKch`!=q6GloHyVwP7Z(?=D5Z++b{myaZjvNktJNwq#)9kD zuYcEUHm~*d^*usF=ZL63%Q7bn!yt}hwz6p$A~p~)h1+Mqwk+%CR;zW^b={AI5N`<~ z1R|0#CJ{p9p67XUb8{z$hK4?rQa(8|Gjqsw-9Z4*jIr2p9EY*q|6?b1gU!#+-{71# z7-JUP9y!vsZO#}w6-CjpMx*gNBIdSjKi+D!z9^T=X9oudH)yTvMATTfZk?sIp0+G& zsNHT~a~$V`QmI5l#28~1=e*HqG;Z*lH*ZE~&YXEP%d(+7&tpXN3x&eNN~vEFad!{| z&qq<@X|1=FN~H}+k~E0ur6`L2Qc7(EfMe};J5ow*bzS$dJkS3$#%#{AjN7*DmP(~> z>-Bog0svr)U347hK$@ly$8nlv*(T2UR%1+Rj6otw0U%0}WCQ>}YaMgW4*-DCTBnHk zgfS*&j6J|Pe<;uMMF23jv&b$2bcSlH)w*0Nm8RS6_Weq!$QYApt+P&&d-+~+Wq?wu z)m;;j1_0Drr&{Y207wYoI*v2lYPBx+CPTem&k*s1l(Nu0w1@~Rr_s`9ckvSdpp>$} z7&}p~*Rvi70AONb;)3Hir=^sAoe{D&F|pi;h(Jo&=Qz&k^XJcB=sK32qh_;t-1q&O zlyZQGSoii^D}jiZlyboL{aUlxJigSw3^X-0l_TO|DdnkZwJL=WZg;}|3xI?WZnavK zQp!_|vBOhSQ_Fy=SQL_+O|epO>zqW lE{%_m-@DveY5!M1{tcX72<~aAQ9b|w002ovPDHLkV1m1SyORI_ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/bt_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/bt_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..e13a490120fc335f54aeafc85c13a97c9e455642 GIT binary patch literal 974 zcmV;<12O!GP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-wNJ&INR7i=X*3XNURTKyC&-41~G)`hNjnyV-poL=;LYpaC zL_aK{vQ^ZgY||z;6=jS50ikk{6a>)^iVzB+$bJ&iP7=#V2iml#86igo(#ag1IW6va z-nov>^hO6RJonslzvn#Xe(yQAi3okl2sU9j=ch1%ll^S&_OZSV_u-~=GLUQM(%H}W z0tawmIiO~RKYAFua0}+~cLKE=nhfL$tin<3#{PaCb?_>l!W?F6`&@^G$|($C4c^4F zxxTEUF5bo?N?H~w{W_e-U+Hil$7}}F204sa+xT>1p5D|wWVy4PPWFr9Y$)WWRDga4>cCp)Vx1j&kES<81Xe zkz*p~oA3#?EB9#%FX3K1mNpYgx>}4TF*jqRi!p_g^Hn5`LfI2J{|r0umU3Q0$~D-V z1Ew>G_KYOvFvhyrkm;yX*Q8N>S>MfwUsI~V8+f5wKd;=I)s>@##NN=cytL`7<$Ih_ zQhvA(`<`?Z7M-(5jCRv1g?X)vDHrwve#h&0v|8`xp4wR_v1htCu9TaN7Sk6>3Py6i z1>fMkw7nG{Db=Eb50rZ~V6hxY$ER?-qx6$w8GS4<8qM$Z_)sY+P1@e5l&Z9nmZkyu9)yXR<5X<7r7;X;DGtkAiYDWysrsdT$>okH=pRt}`ToLNs`H=KnOv$D3osrG@q%egK1m&b1p7veLYTYPOz08CmsCc wKR!-sS*@_CpXb)+`G=R4e{)pJ|9U|F1Cr&IrB)9AkpKVy07*qoM6N<$f|*pw1poj5 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/bt_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/bt_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..3ba525e457d357b4d831dcd09c31ab80df4a9af2 GIT binary patch literal 1602 zcmV-I2EF--P)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-yyh%hsR7i=XmR)QdR~5(q=ia&Vwd+}L?1Vg^kVqgC2qG^D z=E>c z=^K$Ksci2$v%9l1duQ(9!L!S{Z7Nq>Xa3_4PY9Zrs?|jh;RVRIAl2W+qA$d8Y_!&~F(w7j7myIbQcAh5>k8lZ-%?7QTU=aR-WBNN$&%%{rbR_)-bhH zD*YsfY!DHc8MbYErBbP*lzKr3vD#|2-t#=q2qE?n(U-N>-)Oa3`{Fq65RnPPa09^X z=;-JsfTurT(dpBtzZ%E!i<_I9TSUan49l{dv9Ym+@B2^8&(Hr80IJpMR1`(GR#sNR zT=yws%!`di<1-tv3TI<7;lau3O&z?OKS(cUa%Q#39DWzuS_W)pFVd0ft zuXonA?OzblbR5T@*uQ`OFNF~2?%uuo>s+%5U;xTJm1bF1E|<#_f|<*CSsA{$1RxVa zbov|f^YeeyT7M6~5o65fvn+dgZf@=eH*enT0f5$8Gjlo&+BTFO0A+y(FD9ZLWn*h= z>mLBxxm#}S_;~xCJg{&IB5D%R4wG|%==FMDf8*4tQxoIk<4Z)8G4s2g=l!f+uh;wU zZQHg0>_`S|hbjTk6pcpXj+C+~gcz<8oMoAkQjP&YwOak+=;-Jx0A4o6{K5DAcRHQU z4~giv^?LpB{KOF=+7SXFge9eHHk-{mVr^}0BQNzX|F7_oF-8*6K>%g~0)wGAsLzv_A3HZ zoIij54FGQdK$c~inWrqvI-I6yeQ|N|tz7aYt@Vz$c%CPO5U&FHg>ARnE1u`wR!aHI z%tVAVO`|N!CacxzXNSeE>-vR4p&Q5X*ZYv^>FIG}%p*gUg_Tmi=Xtl=?e@w5w7R<5 zBckVnAaL@eU}iR*PRApnXDgM8+Xwl+{~y~NQp#r*78bJMb00XI%*@O@mZs^GQ4}57<#2M_vaEAUOG}qN z?7WX0w`OK$EC9P2w*b7hw6yf`$F29T|961=FGxZp3Q>ApJOBUy07*qoM6N<$f(Gmi AA^-pY literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/facebook2_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/facebook2_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..fc52a590582c185dc0a44cf09fe84c5c23175a8d GIT binary patch literal 803 zcmV+;1Kj+HP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-vok>JNR7i=v*3XMpWfTYS&wahlWUr9FCMmR_jWmWr+n|=3 z8<7?nF0@U%Hf{O?B1D2{BZvgLXpvwj1e#0tE;JHB6e5TujX`j9=AD`MZSj0Bb7y>K zct^zp7w&zYbH3km&OPTmPc;|}j3^U$7hCiFA8z6PD8}^&`vo3!78+S2=)A$Pg)re}G z!KX@E`a{51l0lr@igWl}E0vvP%HQFz@`KkxBD($99uC&xW-FqD_!(32ZY?BjX>2#+ zGhA#Fjp3?NzSGY^(kAOF<^K_SP3rb3)%7As1YCO|Xl%%S zld@M^d;MVRC>_5WPoi`|X~5U9K5Gs61g_x@Hf3$2QmvbmD*HA1buf2hqQ<0Bk`?~N z4@%XXi_)KXh@E&8qTBc~-+$u+oDa?wY>T6BWo@!ns$<+@Id8`nT*gm{;t0OQhD5L( z-vq21l6P<~1u%=LYA_f~;FlQo;!Qu1%*Vr~ z>+7VWj&2p;UQ*PIoGN(*sU h`)f@^ZF#N>000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-xt4TybR7i=fmQQFMMI6U}zuB3$JDbgH_9d^_HU%#dBK0Jc zfQOQzrBYLpdhp=MUM!y4qewvzJ&4er^iZhaQP7t*7E7xQDIP*E9$F{`4=N&-%*UNT3kwUJh~Cgzzpk~OuBvLBh-?4=M9eMA>Ifko2qAt##9QrlyWBHqVPWAd zt@XJiNnXja%xJAMV@wGEg9*qO<3b3>aUABl?mZ#IrFOgh!>&LlPMl!2ZGW1k>3dNW z6y+5ANK#Gu%qPd9d&MpVW}`I{vO80K*lVD2mnr;PlwoSO)+;9QfIwaq85m zlUbIXiK3{pSICpRD2h5+mYtcKn>)D$G&?)nFvgsZq9}*Q$$l2d5C#AgMNv*f=VxbU z8$*!idB@T;JzOV#$0JWf@LzsJM6Gp_rs-kN^NtNc#+c)2ni>EA+qT_CqhUjx-zPpJ zgs_DWf*#vuA0Z;zw(TM!0RW_FYK$?*0RZ^S%*=#RYPu+jOiC#|&sze3Mv^28S(a@u z#yBD(5gE&}T*q;Ku`El)as09|ra(lis;bfEj^kWwoocP8XJ%$5 zc(d7@%JVz`0FY9yg<<&B%h8e@JNA0L0es;a)$ z`fuB|XYxG1IyySqEX(reAPAbqm{z~vKU7s!5Cp*#C!&CeY$7s5gtl$(Ycv``S(dl* zJpUFE$CXm=bUK|cIOmQr#v2_SZ6!(ax#Kt!oO3Tt)2p86y_o0uqkg|1yRQ3<<2awi zaa`4s74S_-thCm_$jHb`TI+xM{r>N^ZBLeEDU30XIOodu{Z>&F!Wgs8Io}TeR#jE0 z<2d_`F%jonx~_|y^F~>geE^Vy_#6>?h?payR}_VAG#c;5aqJ-CYh_usj4^2#h8vb; zecb7E{@|RyP*v4mjIpUa&l6)zmvcT$yRCPNC0NONuFsBkiI6{aAtE;Q)3;=*J zc2i0@l%xO4q?C*?c5`@P<2b%8rMxeMa0jygJVrz$gm9&l_v1LeJp?T;FBgb-Q7L6Z ztyRy%0RU7=*^IG^%gf8f5Cj0Qw6t_xN_j;oHC`|3Szts&pp+VyQeL@s?b`K$V@qDb zFudUVep@NkA|kezZLGDADWzJz@3+G+ys+871+=oVQX=A6rPSqSv#AC-+X*=E3nAQQ zv#FF)ml000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-vs7XXYR7i=X)=i6DMGywy=bpLAC{Z++fPyPsnGpqlgOHew zQ4q;W-H5IP1*723m590(H|jErU{Ht#e}Fq7l8>!|$-+@aF_VuwbEjN%_1vE0y)!4I zpy6~^*ZX$Wsjli#L>MTC@dO^q`Cqt#)gi{?0s7-Oh9{F`Id!*_>>_@^IczQh8tvlI z3pjN`|&H@#P8|pG*A3M>RX%D#5&Q2ssg>IWK#4< zD4BK$sVFTC(-TJc{qC z^0;1>^ki(7X%*-O{!Oxe1gdN$wy|>KSMpSSgK>KKijrwne#WzT>bLL`uJ>$5iMfKq zV;oUZaysWkqg?;7x4wp-^81!@Vdu#-v5$;#Q2E*OLbsK=5AX}V&GpCdqS=4AxqztJ zAKa_fO_dw}Ase0YcQnZP`({^DYP0ZU^>u^~qH;dvt zL>76ol-QR$ek@qG(aLTFJZNY>zw(ayIbiJdmH?`(oYT;=G9(%BC#$c_BPQ( zX%{g_X;UhU7HvisLn?s3pwkqZ|zOR(V_orFo zt6ogBxv_BiR35_Lz9 slUDZOIm4b?-`m-000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-xlSxEDR7i=XR?lw}M-=|v?2gy#b=FzOh--TSDo}4Ihad=Q z!4ge~x%Ap{>B(dX-vp+n$^LohI zHNi=Z`WGs6X5V|n%oqpf&!4ZHIC0{X*4hIAAw+v?YwOLcSFg6miKpX;YPFil z%%3ZzK2u7aNz-(SnJoYyqS!Eu9Vz8&DdlfOw7#^olzcEztycR&DRnCdf^$(6X{A)8 zwN3!^14syAN-6XCd|ng^g+HZ~50{pfo{U9QtyYC)S@***{Mz^Zo>D4!CxA#2kpuu{ z*36s$NTien*L8EYZT}p{@tu0Tu8$0oTdmeNFJHbKSSf~COQq7ijAWaL`XpdxIF93Z zp7*3sC|rB-;>Goijg9N4PoJ(zDSyc2a)kr2q$GPqMew^7fAYo=0hLHpC*T%+12mmuPGo{JN$y)$&Ns@e`lnRHh0|5KJA6F`s z+q1K?>y1XEX97U6SiBqr!C9r$Zr`pxPj-(6fPvqoQt8tuioWf3yD@+uNs^F=2JR3M zDW!ri49^ye#mfNd0syquSHduS=auv!rG(=+hLlncpIQhJNGbP(5b>}B!wADrYpt&U zfS8`1t|+C>D5au9Y5>4=9B0q6tS^;PKlT@Qc6RJ(t5q#7+!2Po4Wvh2Y_m|8WE8(N|Dw&Nz>HxJnxjr z%wASjMwJMywa#6=di6U1n`>)p&zKpPE?xRaN;wB0VCHjannoiI2>_hs_RLXVhmdx= zT_>NcBh++WF2vww%VrK4GmbE`@ zNw3%24Z|=bA{?OxIJl}9KwGq0tv7~Yw1p5O)%6n{PIhR0B$E)rGz_ENZnxivX0y4S zmHIr7+nmM#GqaR3FQt6lY&N$=#=K_Rw)n5$4~1>pLI|-2WVNo_?LN0{ds9kT7*o}; zdoncz+qO5m-R|=NQKQl55zzzJbuDDIYDD~?auCsxoivLj*L5u+#Dhko(Hjr}!0PJi zQ`@#5yRJKxi5e!;T5D@&X6EFD3l~oIdcBj(JgQ_dGsAV=DciOmudJ**?SFXZrS0zS z-t|1M0^o-4`#Z=QUz(=-K@d!vrui!~BaUMc$8kLT5;Mz%>$+2=QfaZ>Zr>fw{a!1t z)oO;;`hE}uU+wMf4YzVJ>j`dC<4m`jr6 zRuBYd#~e;JP1Ah1yu7?RD&Mi=*22Pq31F;o3&8sF^74m|TZi#~2grW_g>`000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-wbxA})R7i=XmQRS4RT##9_ug@4(lm9l43vn9$^sWsM4KWC zOfbhFY8yrow5b*?+F6?@lb{eJsL0J!RGZAGO|(!Hig3_^T8QJ|c=*#;Ua2mL!z22@*OMZ1AlfvvzCFdd-Qgjy2m1scFFz?;CA%O$D7frG%y@hwW!1$+oRO_60T8BYUefN@|pAPry*a2v1=m`noK0|US_v`N`X zv>$jeBqqZ_UfVD)#ds2li!Qogm2UIt#s#G_f|-pFg7E=qZS47>%b2R;F| zC7IK}gFq7%b*K8bI;@VWTjQ_i7xjIMjj2P4J*Qq!o9frcAFC$InqJ=FbX}mVHDifGZvTxnNA?{a4^8O7HanTk4d}?n&?}N;P%b z{lFgJQnGBs-|CGzMTKkfK0%SN5$tvCXI+ibjAtu|ZU#OG$s7wO!&LrX3w%YX&KA~Y z+8VYV_8Atm?yevj0G^_>!0QzG-c7c(tYnC?j{qAfO*|Xyi8^qK(j$$K+*v^cr4Y7L z4$eN{4ob!K0>hLBZ`pmo4f#I?oND#R0d-Qnn0}z**`)4OkEoZ`8Fg0uPTi$m*A_dV z{uRsvDpd`8Nqw|}s7rlP{a*b|J*nKmI4{h+(W^-id}V;H-LSVt9&NU>NMX7 z9S000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-zSxH1eR7i=XmS2cmR~^TH=iGbl|C~FMncX!u*nij%jVQLJ zOQf(9k}SA8%gh!jzNPU^5z{xNkgqcnUL191boo6E-8{1 z*=VvmGk5OJ{d?{?KOdZ3*0IJEe@~aoz2DC{zyAag;c@Kf(WBLgiHSo>sWJcnrL@1f zxq0{Y?b}T2zj^FY89Uv z)ND5Ag%D@sIQ~+arb-BrN+}CM2m$~gBB7M(hGAHiWl_g*?l8vQY_(dydo0lG>@2k` z>wJKp`SfN~x3*rIZ2@m0=hT=iIPu`|T{tUcYwjn)7Hovh3+JO-pH-4iOQ2 z->>+-ztrpXzH{r=tzB2@d#RlBH^MM{InVQ+X`09wvpDB}F->zr2=PRkrcb45YDg)y zIF572aqd+rm0!nk{A8A8_3iC#H5d#w0bsFIDs=(ihdbJI=b>J&&m~E6CQZ}S^SrB5 zQ&V>)CMG^IO_K;A7K)-UlO&0fB;k3Un?VrxK@c1jLOiv)y869Rsq{*&ZN}JV5K#gE5JF_0 z=S37nUs+gK`0k}km;RvZdb3igyzja$3Byn*rCzJmYR0bXJkL8GMbVKw&j+sS8kS`Z zE?>TUhY<38L{tC(i;IgtDT?B0P1F9Nlu8L9R4G*iK`>bq#kqxrg|7=CP7^}TdY<>Q zZnyh<9LGmI&pQqP*C+shQtDKaB#JS{EX#U`hz~|7yqh__UhhY~@Be^v{%1|otWgpX zrBogSK{t-$n(Mk}+wJxSA}%w=j3h~vQtA`{0G*zmt_mRz3n5b5woOF*X}jHiI9>-g zZ{8dTA(nMrCjdb9W-cLw7De%3I2`_Qbij4SSSp0bgb;_Pr>CoQ|Ni}lq?Bc)l+txQ zQc7)(L-r`X6-CjDMNuS#>}7!@gzQ&JMF0Roh>uOv{1c^Amr|C?$-d#Fh4*40;Ti|Q51z~nx=@T0RR$05D|&4>(p_ahq|uY007soUk_$yXE!LNUmIzc z=^j0zlq#|;+ZYEi#y$rC7laVUZQEv?bJKAgXLKvnb=?Jk&i3~9?Hykt;uBKJ-GZfr zkUk+K8~L3QLX2@xtJPX6isDm+Gi&xCr@Wt z_Cgdz(@_*L!!W4py6*wNg)j_1*o^@p-^{WM7-JS=Y<+EQZHoc`P)gsiZJP=ql046+ z=jP^Wo4Vbemu*vp>5lg zQu+?SsC(CHHN$n?_U7j1bA%AAR;%|kO>11aa%C_M1OPa3;zU_WS#&y`?Y-}3W@h$z zo_BR?YwH5^UU# z9Xn=JtJPlyL2zm~9ER0uwPab=nX6Z?t^(}o-YY9BtF~=lr$p{g((Kml}=6 zSN|7eadGk4N~Q9f!C){u91aJ*?^kTwzPJMc7@J2y5S%NQ%T)kq4hDm6Q50X?w{PEX z>-GAIrfJJk%JuvA@AqxnmYj3XvaDx|qL|OJ?3LkgSWc2;;QM~n_x)DC-#@ok`#(l` zv)R;?Qs?71J{^W(UKB-US(axQMxkliCZ)6s00knJq?A*6o;zup4mC|PIOm4rIKR>~ z?e(RlCHY9ujx`#MdQlW-<2XK&B#9D2q=*QF5DNb)ZUq3q7&C0!)*Q$AP}lW0mzS4U zK1uJ9>sF)D&;j7F)-3>dcX@gF)300O_Wv%B{{$%qkbMgP-x2@-002ovPDHLkV1gX| BGgSZp literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/g-google_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/g-google_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..27dba6d79085889edbd6a97fd76ea26345ebfbf0 GIT binary patch literal 969 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 R1~~u#002ovPDHLkV1ho8l!pKS literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/gmail2_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/gmail2_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..7fb8ee3f9c36f00c59f0a13b4a0e28704455c0fc GIT binary patch literal 854 zcmV-c1F8IpP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-v&`Cr=R7i=X*1?O_RTKyC&-~t-nQXFDnD9M0oi^fz+U z#z%NnY)gL(_#_!*kR5!AH&t8Nj3}SMF_GZSIFY*jv^|zs>x&hmm+%RetLRD~cPq^j z&_LvK2HS8POSPjpd@IU#B^6h5G-6Bt8N+gb`zr@6%;tPSl>hVSm52|E>MBmQ;wwCh z12`qBYfY4O84uta9K67&@QN~RrrjknQFy_<&f z-cRgHjX3d7q;kD2#o*d?0f0 zw5Y5{@wxRjG+H!kiM^{Ws$<^B0js2&>!0Brkq07o7qN(6MuIESPup#G>vcui_+D(| zPW+k-uVH_(9LHz~VA*;Fjbqiucesw{M0NGWw)`L(YHtFgCb5?rTovu6HKJ6ayPn@e z`Mo7dw~M{llMKg6E3vOOB9T|H#W3~Kr#d1Zy^OeYj8^`882eJUTiFj1^9pX199_oi zmC_wNf*0^uvaUgD`90STCBr+_T9eolTM&`pEn<)VHo3tLQuo1Rcsu`(Z9zS8Y0X!F zt0Eu03}kk~m`j^m8I+vQCuXluE3$+S#knYvZdQuTVqz_og>e_($KvAq!~eVZ7RAN) zh7B&hRZ$dYMGsp@fHKB`m$8sGXA@)Sp)$?mF9(9=A(zA#+c gn{rgkJv|`*1G}!_aku8HWB>pF07*qoM6N<$f^N5qz5oCK literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/gmail2_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/gmail2_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..ab8bb0f3302f327832ded99ce8713b3b0e68b709 GIT binary patch literal 1436 zcmV;N1!MY&P)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-y7D+@wR7i=XR!xW;RS>Rv-EaDD_VxU2jGL<@1fqyP>k@^y ziwV(ne>kqy?!3jv&>F*;{*%((7gKUtEyL3uTUuk{mAg}aA9z8@IV~LSpWb+h_}AJzINx% zooYXLd=yc!Sk#qLM>*%Oan27)Df3Dx0{{RKLrv3al+t^Y(wm5Qqg*bF$0jNki*Ity z&-lLobi3V-Ip^&-js*a807wYYDW#@qn#8v4Un!**%H{I+eGwf$ew-MF@ktN_?=%{X zh;!~I5#UY+RAPWqYBR=CmSuevhT+-e<>h!+q9aF+=-F)c^Ucl86OBfr4gm3P1iKIt z##qjE-MMwYr~k z?js^vmL*fElmGw}Lg=kl%U3-Ys+3Z;ZQF)n03u2$CGmZq3LzAw)GibXzqeYgH!77% zL;wKN>GW6-1c#D~M_t#`sZ{FL-o1N|4Gj$)WsH5A$z)7KluD@x0HQdKqk(~ebfHlA zkuf&DZ{NP7sZ{EsVHjxuK+d@z1i_(nIz6^^M{yh<3xc4#N(cZ1SFT+7C;9(!YHBL2 zY1%o@^BO`3$r#IJGMNe?% zTrPJ&N|{ZXaa$oJfIXb^*~!Vt*XQQuz8Dx7_&A@>FD@=FzCAH9@stqaS{R0hyNY2; z;y4yk%4{~9J)kS4vdLK4aYRH>6tr3`YTNeLrBdnr+1c5P005;@=|x2RwpOdw;`i%$w6{xnVVBmk^YN?*`4jsBMn9T7c53<1FDiAn(g zn5L;aj`I`e{IB)(^_My4FCn68G#WCUPXAme6mB9S@5XcqCbm7jUazk)#ympE9;FoT zQ3THU-*Fs6yS{F^^=3~) zio~Vd=H}*bv)POi4@vTAQ4~d<=RM*3{__c@-6>q9l%kZHl+t^vtE*K#VZLrz)>~m1 zc9b|G4wXu!SA`J!qbT}KDbj&rxwYVGHo`%+5Z_x-~{h%qT;7)4P_)3o$MEJ+HR&E|8Q^KYb-JPbo0;K8$D zS=QZVvv~_3X|PJA5+UMw#+cE`a~Ou={{8z+-}kvvDwR03(?_Ey!bCTeQUU-VW6U6g zoUc?W(H0Q^z|zvvRm-w2Gsf~tDL_Pph|te-)X__(J}}1emStUDTwJ``(IMS{jg5_S zuIrW=V}nX5(mSmmCF+3?#@L|iy5)_HjdR`S+lW?HRsFMbSA;cNq_Yd{CoZQuQ{lfhG{L)VL9=UE!PfzOr q(AT;J05|66=O2IF>XrYyK>iE4@6b?601=h|0000000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-vwn;=mR7i=%)<0-fcN7Qk&%1dh(T7wque4NZ*Q)5~C{F%a zq*KyC)J5p(;@YJJDRdG4;Gm+2IvEtxE)Jy#odj*w;?fp6nMky0+PrA;9L~ACYl!j2 z4F2Hp?!CX?`F_v&o$oonU!&XYsyW*D92@feDIQ_Gj&ZZb{66f#)+8CoxlWS(h95D8 zmu~`UED_NcIEL+*!%PB|290!N5Pi6Z}&g*DqLGHEy9FXK@tsOA$43 z9>Zc=<`)5f)99v?8*mMWRkpHNu=qQShy*W(M6R7r+mXcTO;#e>kE@tW@0LSS9i{Dh ze2LL2Q9phX@||7*NtLW6Z&Hb5IJk4VeNuTo9V>dU4jv{QmUj+NOl5$ z2wAVL8AUl(>E&!+Nz}#`{Gab#T*j{=u_th=CRu-C{GB*6iQR5uvykK**5DL|ggEB# zDW=lHwfHxmTVi{fNdTAd32uv8Y9{vPLa3u`E0g#IyYNr`Hewro7pi=bWLNME4{#$% zhbp9U>jtpC+Upt_!4uKPJ`kPZFMNpmxR~E&aTA+z?oK*6lTr6upxh!CbaGGIxmD*X z-rd2s>DjOlOItMBDg2Dj@I3K~jHK)o9ZVK@DB4Y5e*9W=D7SfQFjw)D5LD;_Y!1Yh-V!C;Ukg1BLCN7oe;=ZWsb&h zFrPcQc!yrzUZewqdi7G|+{cx5YxG*sT&@}8J+z=%acB+bwVaiZG!pB0V!w7wjN**Q zNonvdBogCHVq)=w?}Cu=gm*jmhQz^l$Px$NOCgGrqF`HkoqMqet8=ZiIhh!*T~z8^ zPPU22mb#o2qH`?ka#9_uL~+)+Zv7z2VA1h5qUu=D1@aYK(d4-OMaUii0000000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-x`bk7VR7i=XmOX47RS?H#-pB6k-uj*I?Bh#`L>EO0R4B4& zf&+;x8Ao7q?Grhl;0!b%}%Fd_6?ewn|obreKyOo z7mA{ATI<3&X8>TZ0U2XLN?EJbYAg)HU!|0nI-Sn9LxHBIrkL;h7xFxRJ4uqh);g;y zz{d$tB_O2?l~P_11YeeA`O(tSlG_t>?AS5UY&JjN+}u2!B*_K-0GU#%)o3)X zZES43d;9k79V^AdiyMu`#}#C~(jN)}uv4*1l4KnKPLGa`J^+9Z2YEL5ICbjObWs#% zk|cSsU&y1pBuO3=MR8_kW@dU9XmWDWbIzShlB9&~!~QRj9T)&mk|ZS&otvDT^maf| z6dlj={D{^%LqwqMU;rS92rK`GdvH}*TI(#&^CM9d9S5k+$T@d1&vRET;$awiLWsWs zpa%d?_4|EQ6h;0o`b0!nX$Sx?d7iskt#%Rsmc+!w#JE!Gu-3XjM5dIYD2l#ejEy71({x&EZG7K9;G9c|2&I&fF{X!zAcUwp=Q73^2LR9WJP5<^>t?h0 z?AF%SinaE=q9~-bw%Kep4+$b_R&52PlwD)Y&j4^CP16JbY+07iF~(#RMfaqXca1Tx z5|L(%eTRrIBjOq&{>eFirB@Gjrl+Sri{tpsq9_v2^Za_fZWv>~ zFviF^H>R~dKt!c;&SqJLj4=$u&({R@4ifC)Ro!m)e529mD5cs�G!QVF^UUlv3?RqtWShyXPOy z?*gr?tQbUmM=5o=)oLjzWmpO92^{35lwqsYQc9`IjInoCR#tWmDtitmv$L}^#+b8N zmK_;#I9U}!T$-PsUwE9}6UVLD*;xSqLycPiaC3fse*fdvqw#+S$bSG@p6_p$h?YeF O0000000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-v%}GQ-R7i=X*3XNTRTu~G&wIUdZ#I=qGb18Fi$KU?CX~uu z5JWX#5iS}*Fe6&DtBrqxh}cdMDGEWzAR3~kAX>Q5ji!Y^TC~Vq1dTG&!lt>7_ib^W z*L&tNj`z+ytM|OmdA{H0=Q*b+%TkXril;Fg>sz>nnO=@t49 zG#2j%RICuuTR4Dm+{J$ZR2dZE$U|6%UvLOt_exa5$9Nwt+|KuR?ahq`(ZC6Og!W2A zb$o`mrL?q{0l%M=;p8w*W4|nwwXV&FF)0cDtPM0)v+P2XJ(hFhk zXgjdgrHOwA^8x-FZsH$2fiayzw=f{hO)G#K(hwiR4m^)Lp`Q=z(Hgc%Em_9}T*Qm< z|85Xm!XJ1Hf8l)mui*-=2WS&Fq}r5WKa6d4sXLnC=@}`f19&pL`2;)hEzV&x9*zi} z!bW@-|1ZV*ckBv`CWi7kD)A`J2KhA{3F9$5hcBfeoWLBeO5OEB*k6_A=)*|+oeI1r z&CNoDJ{k2n89+_Ej8kEBFw*o5-oOX=G*YxaBA>yJQrFc3d$uUcaui=lGt>^{pOL;z zvHm+ee+2)AQ*-zUd!@7SU5rG;bCH#S$jt6qcyJ{=S_}`iWJdFm_jN&1U_(T^h@bIF z?5P^$@kr(Rz@DjUG;Qg*S9Kem)~>!ut-A^DVJo(0`%0bJs|EI&j-YBdiwwNTbjuz= zE$Px~W`+-v9JG5~1lFOzUXrdU9G7a71N0-6%}8KP-ScXhi|=#k;=5^e7vG3<@x5b( zi*FJ8a8&B7L7n_B7h$d&44b2YvE-rB%j0BBifpCFNe#d1^Kp{P0AAPIbL)HAk<%|x dE^B%~{tw1Q?>$82EIa@J002ovPDHLkV1n#uhf)9l literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/google_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/google_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..9e6fc3964cddf37f6c76e0bd78598e97cec8b262 GIT binary patch literal 1418 zcmV;51$Fv~P)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-y1W80eR7i=XmQ83KRTO~Fxifce?!56%<|U!1D7tBhrbtoS ztSqUvRAXvV7lKg1;-YlbE=3B0xNbplQ>kDVf(u`0EcQnlQxIYnf;JElqu3kwS? zy`0DUfu^RWTp~KCwSGx!JzSRM01*iQ07T3k$64i^FLBPlMa1j1TFpE#XliQeRju`@ zBuRE>S!T7?nYGpcK<5B5#$3*MUteDz^L_so=loo)R{Odq(BZ>}nGoW`G)>=*%qV6yd41$5u}vhdETaMq-kocwTA!z+|kj|L8a8N);g_JDt*51|EjfKl~Oje){izC zji<}9L_{QOZ2U^d!F~H=Xp;eV!zhIT0wQrSW+0a@?Wmy`=nC;jQ5lAT+W9(Y@!Zw@D8&b+e&bd#$jRQ2sm}awS(==7a zn9e)Zfe`21mr^b^o6Q?t(CqANfrw|7QesO4+mr4JAR=uU!UO=QloE`wv$M0aMHd7B zFf%iASxR|9DK*fUSv^FyRfvc{DK#Laym0B#rOO=!+h|p<*UyAuSW`+35fSS#ja>o} zF{RW{7>2cay?$n+eiLYJZq6X$38mEeYPG65HM<|MqvxFa)oN8KrOq?PPRz~CZCX^e zT}~z^Cnt2Wz(bY1t{^z`)1z5LyG-I|=7bOE5JbqfHlPft%j_`0=K{_g_$ Y4~dZSF42i_bpQYW07*qoM6N<$f)B`(r~m)} literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/ie_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/ie_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..460d781c08af3b92f06478464bec3bcb72454736 GIT binary patch literal 984 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 M07*qoM6N<$f&{e~RsaA1 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/mtel_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/mtel_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..2309aaafd6dfd342ab914b776c5ce938980e528d GIT binary patch literal 834 zcmV-I1HJr-P)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-vyh%hsR7i=X)=!AkWf%wW&&^p+ko* z3Pt9Chy=Nv(o4qs(icn?ch$n|@4bK@rJ_#7W#r5{lZ zr*S|^%Ss9OTG9z8CvYBzWT~w7C?ChPRN!Gqgzie%P6t-^FpFp(&S5^h8-^s8!gd_* zU?wN3V^(V4g+3&?1O1%oNHx2LomeVTw_ED2ek6qyUDi)3fwd#BAJwR(r%QUg8;S2a ze2W_%KZ63ZRS->KEAA<8-x~f2-8(oI0ELqktJ^$}>Rw<^Rk1~C$>kD~s+58+!l9G+ z9WP3C9SyK*k6j_lfxV?Bbw@*a>Nem@T*hzsG#s0ihIu}8TDtWelh#w=cmw0TbCi44 zz-^qu6}%sS|KWdJ4f1Crq74z@9KO?2!&-RN#`^H09)E2dktX~jynz>R7JuTy&|j9) zIg6k13U=wHzK!`xr_-6jSCNu7ehKn9Y?lW4S8T#fyo$f$yAgj#b$T5K@jUJZQC*s) zw`$VL_z5rLzHVb2!gKgH0Pn{4EIz^Y0DBE@q~I3m?-Dbp4DMhPz?`6rG$*M9*3lx; zyuD}e876yxhLOT%GO%VId02Asossf-+ml^T~fuz`Hmh4PaBZ4rLMMXU(uV z5g4l;DuX;uwo8%qdz@79gCQR$xr}0u!Jb>+NOM>!k0Z+EsUDCI0gFQF&2ieI`v3p{ M07*qoM6N<$g6y_<^#A|> literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/mtel_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/mtel_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..b5972b5c926070d1d32fc43e28cd1de59046ccd6 GIT binary patch literal 1376 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/net3_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/net3_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..0a75a91c2139f7ad1c744cbb7d1a9c5784d0b103 GIT binary patch literal 1601 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/net_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/net_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..7c72be1d81db55e30a5bb2aa84c0a6b8d9baf7fc GIT binary patch literal 1918 zcmV-^2Z8vBP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-z_(?=TR7i=XmRpQnRUO9v>$dk^`#R^G88ldm;4}rSz9`Ma z8tXJbFxWU#FHIovLLx>I69~a5H8GJ8l?Uk)J{a*5@Xb!cP%{C-q!n=57c)+^#aJe- zTw3PLoU_l_XYak%+H3uNV4MJ{q{Q!et@X>gecwkA5w1kLckdpbn3&kPTR zKT=iIxAHvKP1Dq#=S8090b?vj#2z9#N@>eEmno&V*1F)F`&pKGQp(>br4B7DEV%y( z+PilzZ?#&F=Xri0&+~QP_ro}j%OD7zH^wX|rQQgFphYQ-%d$MjIp6Mi-e;SpxnndM zb*icwrD@vEvh2vl#>TxTPMp{}O8QP}mSqp;d46Cp7~_1qK*R^LESt}=EE)_38+o1|7#kaV__90NzkmN7N~tHh z-EKe2vNVq4-wPrB(KJm70ACV9q{HFx#j2_vXqv_)N%DszNdf@aRoC_5AP6RkqG%ao zzL)2D+39pL-}mpHpPxUrwWI0jX%7+a&+}YKDWfQg7NnH_mQvngt-XN|a#v9lCxj4t z0f16UK?pHj6veXE`ZJW$eV*stG&VLCODTUBMNypRxkAMIr>CdAEl?cC`^vK1Wvx|7 zl5BLl-NQ}O!0PJiUzySc9bGKDh<$T`{5%H<<@$oyYwG&|&md?5FP)b)j zoz827kgp=50RTY6sNHT4gb+6wV{X3cs;fM$b-I1~_Cur5=#Ns$LseBdDdlYdut2A# zrpApiHyUG<=Xr&5?p5d9m#eB;ruG-;aVYUkV~ z=iGJ9Ibe*95HWJj2|@@XgfK*8&bb5;M~FzQwc7!pFvfU^MgDOZFL7oBtGl~Qj-QM5!UH2{E= zQm?M-^N0vR5G+wjM@p$~7=|aCrdcI~dG;R$Hys ztxeOM(ptY!Rnl#|n(^TS7v z9-Y73dhc7eW@ctM09;Ys0)Xd^9zFWO>(+bq{}#yq02ihx5>#0zRR91007*qoM6N<$ Ef@dA2S^xk5 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/netw_conn_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/netw_conn_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..1c3c961f99917b62fa25f50d427619e992339323 GIT binary patch literal 986 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 Hu0mjfJ{3ab literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/opera_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/opera_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..6f5799525288cb52665dfea674653d8a18f963d4 GIT binary patch literal 914 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 R&%poy002ovPDHLkV1hMs>c;>8 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/search_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/search_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..3c1350d7bd41497cb36f4e17fa2e26fc89598108 GIT binary patch literal 943 zcmV;g15o^lP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-wDM>^@R7i=X*3XNURTKyC&ph)wV@_0q8U#X{ATqHK#9Bp* zzy!@8${_l+2%?46LjQnP5flYhw5X_{gs4{9&?4GbV5M$a1!Ll9V>-?cb>7qBp2vCS zdEXgd>B8lG-uvTw&iS72x%Uo5gaO+|+=KP`{~S(YYLLyH0p@pMC$^-K(VSaIV}Ia# z9KqFozZ;fA5 zH-euO`CjTn*Jx7t1b)ZE*nx}q4wHBlZ{%1gIXj7maJi0VcSOwgiKOo5BjS-<`*C_Z z9}x=?aV8?3Y|PCh&SYZlj)-eH+NGtEM!N~W;0Nr_Bu{6AXBAPrhfR1_sjr%mZepvH zioX|gdgWWwdMv;9;NPTXDEmBaQ;Pb8B8E=R%_a863Y!&4F0K#}%hlJ&tf9S?^kN+b9|8AZ%^YpE!9wMXgIM?bQF~w$2R2Kq-hbnexOe!gL3TT*lfPAh5}SE_#|BcWH3RbpQQpHOOLEEmsO zs+}G9COx0Y`TEqZOQPTPF_st;EWal9;>)CD1i#{E*A@pLlLb058< zB=$^tv{s?z$_*Hy)Y2hE?)n+(;8W$|JFEBNyPlCsq4=#}wZ}000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-yWl2OqR7i=XmQ8FMMHGPF8_%qFH}-CJH|0?9Oo61Sg~=74NjGnR(y5pLy@0QVO;s`}XY{*|B5CZYiY$06+-wS5{W; z-nw(*1B0s7 z>R}ulq-nH zlu{#{^Bm{A0{}7%!v+8x86F;P0>E2qy2;wd9rWu~+#g5~A zXj#_tH*em2uH9~r7K_CruIqm9I8KoeLI425Fl@$ge4<<~mo|XL#>O-$<=HR{dFF;e zh@zC{9mi?ty8hD4%*^>DNp_V=r8jr(-1(}M@{hT>xs$eSziZp}Q08hCh9Or%Ubhm5<{%z7zz(TkUrHeJSNn$BrGVUcP+! zQ`0o-x~>-i0E7^|D2nzL3WXQeK~l=`D2n7J04Sw^QmRu*f1aJ4{jpN1yuP}+`bw+S z3Zf`#b-UeWqtVE9yWNi_CMF(ElH^lO)B0;3iK0kKDaQc-$mr2lO##vZntYwN)KGQa^)@nG!QWd04Rirg%Ep2M@L79>$A;E=794_bhTO4GDQ9mjd(_U+pj3x&dGp63+} z!*C0Qg6DZ&WEjTT`T6-j8Dpn8=X9$}Q$+L;kpsZc;D)udc3oFdO5eD2>C*4n(z(Nj z4}Yy`+Ovqbnk30wtyc4^)#{lzj!T^L)qz-JrrW2jR_m^1Sw11;A*GZUfatF43d1l? z)oQgL0073v$Dc4wb23fSZ#tdMXNahIp7&I_Tt3Ft-@i+j zmX;c&Qt1w3>`Bgf9}$64${fdu^ZER1wOVZv0AO-*@-a&3=RpwcB7_{*G%WxC76gII zIfu-Wb%;_*X_}@p#_lXFEj4IHzG@i8%basiN)gjE6{Ym`dcD2~08p(~pGcDAOW*fL zIOl&MB0=AR_Fy}m&JDvbmKkHFQVIzn5$Ajv0O07+qtEpF z{jYrA_xk;QmkQy2oY`dpts6Yr4)LeH>~UWiP_oN?>2w{04kNr2VoeVY`5Dhj4?Bp%jrpy ztfpz2JOBhN%NnsP>%z>;%zB&H(2s&3c*k*^5db(6hGBEfitRwMcoEC8JlnQwzVE*? zxW3`RE-Wl0hb literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/signal1_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/signal1_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..26f75f11b036f3d4046daea9225ee229d0827631 GIT binary patch literal 797 zcmV+&1LFLNP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-vmq|oHR7i=X*1wNcRS*a8&%67$>}DZAShTP+7V;xdVM2%@ zA@SEXYNa-UjfI^w@GlS&Iuc@`bYP{`LW%J&@CR6_rGZs9#<#%Y?p}+T%R9Wh_x7?( za*}h;J@cJ2bG|ckdQH>lC-KZZ!L}ej9Xa3`Xr#< z6p!A=c^tzA9wkt#(946&Vg^6pBEIQrsKRA@ipN+j_mAu?mFH383!KB|G(&xSg%3nn zHphTZk|qziA7A4WMJTJ0&6n_@xZo~EnjAIea&0*=E|nWgkKV-%tfX>RPv8%6hc5}T zG}woa@NMZ)jSGTFTN!DJJ$>Q%$9P>3VlMx$2{P5Cp|=FPRy%sqOR)A19;CrG+`Ys) zme@}WEgE6T1TSjAu33DJllUHcivyIhnb`Uw;}7HE6mQz~-!Q-{_&vwpB9F%DJWT8Z z6%GkXZcOl`P0AXd;WTa=mZEV+TG_~bhx&pYJB<%rCFnZ9i-vbnCf~F>-AwF#qj@yy z#csjI6QZ$`gFfR$!B<39~xBX}dXL9~P)T)>929Aq{ zcT&*$SCNRj@g`ow3%G|@3#0PTOAKpWjqeh0Ad+%UWcQ3<&MJ1~7^F^}>$M=zz>t~q zq6448EjH|5?#y7reqVfG{dyQ{FG`_Q@G`@8~ ziYwS7;@o(e!lU5rm`|N6iSg7!rOV^wsPJssA literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/signal1_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/signal1_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..b28eb80cc5f3aaf0b4903020e5554c773d185172 GIT binary patch literal 1299 zcmV+u1?>8XP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-xjY&j7R7i=Xmd}e6M-<23tM2Nm?w+ZhUmMtCE)l_als!eq zs99o0cKr(yFOi(|m;@mZauhs-T!c-?#am`^Vpy1n>=MG_As`XN9HJiM&aZ8D`p4FE zy&UY>?3$T%Odd28-Sxho_v**%heQOk*ohM-YIAdQM~pFL0072Ve`{;&@%{VvJG1!X zVW8#ZWt)i3YOT*`t&e6|RwW_<0Dy?8Wm#R$`6JHx&xqJ=Hk+f@1}!fyf1tI#5=GJ5 zNs<_?bz+Pe0l?S+8Dlo*TuLdK=Xt+#&TllE%^zn1EiNuHA;ed49Dfvs;jY#?$}_-8 z0+b7I&ON1+@B6ee{v86U*?cbuKy~?I7)$tNJP6~70>G#L%ILy{3+Iz0S?PAW z14N`5AV5SQgaFrd|6+_KX`0SQQ6z|ns?};q2yv;^YTW?*!T`LPTI$ z78VKxQc8_H&jZF-bo}^n0sxZ-iCXI@j^ks6LgDlt$QW}jj$?C}J^&CRI*8~AA*Ap7 zpUuzDpHoWx>Nrl2&pQxg9LL5Oa}EH2Ei5e5wAM$p*2y797#+vKVzKx%2!aQNLSY9H zpWM22>lq>r5Yc+s2N6+gooKC(E-Wn6Sfx@ql4V&rzl@VIu>n8|Asi{?)w_4^HayS! z#kTEAK8HDVPe-=e4-YNuDWxbDiyN-%{$`9hMMMKcd;kDvlO%bbW!V$kw%;|zJT=DrDWyD> zW!W#mF;2S5M-gTdfh5Cl!7)Ep5pniTdFqZh`MQgcBNGzWvhwf)}@fY#U7 zM~HY?DRr|_sVL65mkUe+AawkGKv+HNf^E!hAtQ@aHK?bX%Q*KfC8w*T8e{tdDefhirk&f)+7002ov JPDHLkV1jXCP@@0< literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/signal2_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/signal2_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..9da0376e2ce7712011ebc342260f0c228084a426 GIT binary patch literal 954 zcmV;r14aCaP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-wG)Y83R7i=X)=g+#RS*a8-%DN-HDX$7iiikmyAagsPUs?A zjRY$$tP8Df1X09x_>Ye zLruJa`;@S>dw{PektDa`T|BH7%I-6I7JKkp7eGS^Pcy%ia4zS!V%t`dV-IGrua`%6 z;~mV`6q~p_0cMlHxm+7nGI1Wx8?56MurgPp(u;Dba z6L;kpOCoLM%uZq)OCmx6!QOOO-?B--G_kD*i@FRZ0llUCZD@oB#?2kmmSVSC67V{A?QDeD1A`T_H z3lY)k8W(cywTReJ)0;@Fxx^k55#tf@Lqwd8h}nqvDk83lh}{wKbAl~I#9~CuM8tHC znf$j8_(jX5CdeKZ65!-QVR8%qYeA5T3>r*j6*LD$Qir(y5mQE@on!)#+WAVG_6I zd>S7ou@CXMQW8rwBLj&&-^2-}-E6bAKeezO@8O`*U~fxhN>P7<=kNq}C`DWMWH7N$ zR0aDg9#D#{Q3ImHc#~4~0~wae!*)jHqD~>#^+)j*9 zxu>pE$v|SSf`6vmCnMIj{<`9d63Sojs}ib}b@oPL9Z&2vO?5Zk)@iEU?Aq9jW4X3V zNtW(NRJuKzY9%k?F`ainH_M7CC1i~rdnj${73*9Rl!JX!x%g)Nw~Oyeo!VNx_`2O* z#@=Kzs&i)5=mlQ)bToDM>Uya3^EkOh@ob~V$pF6fFCQm$*@Qdw_uM+7)KgFSCqs4l cUk}K?03T=g3nT}U$^ZZW07*qoM6N<$f|&lai~s-t literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/signal2_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/signal2_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..261fd096528cf95c8147445f543ed7864209fe3a GIT binary patch literal 1612 zcmV-S2DABzP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-y#z{m$R7i=XR$qu6XB9u^oB8JN-I+TxcQKL&v7)V-P!LRz zJcJapCRsPT_dd0hJ~U`;`_iHamC`3s!G8oq5rP#|sxR5Qo7-%*S#8)LeaJ%<8qxMa zDMA#o_s;Cxd*{zLGvDzcbJx4;ZrS32c^KxL-|u{L&i6Y9i3kp3Cr+Gb&Cbp~ET!}S z02pK8{rmUdy>sWz)?woDgNWMgwn{{2i=y~qQ52u9swyBN9RL6kb45}5ob$hO&VP@H z8{KZV{Ln=0cKgdkQM{NW$?+`9WKk5El(GbXNdPj&RL;3!7zVQ}>mAPdLUH?v+rccLlEQ+E?>J#9808|5T&Mn7rG}APHndkY->+9?CK% Pph8i{cL-C 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 Z{sRe|nxF$_K1Kil002ovPDHLkV1g8fxElZf literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/signal_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/signal_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..7e2709140a971c853978502b4c6341203b01002d GIT binary patch literal 1550 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/skype1_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/skype1_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..3519e8cca465bfb0ac8067a9c8b3c3c63139149b GIT binary patch literal 1637 zcmV-r2AcVaP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-y-$_J4R7i=XmS1cfM;*t1Gdr`pvv)U_J^Ku9g8&sZL~$xr zsT>m|f=f~oj2$}0R0o&IF1_t zaCYCmeVYLAz1}?Sy-ZC_O{8i1VjRbtj|5^XDOwj*7}J~r*kOJ^Mgl^9vx)0TJ1oZrlIS)f#-R% zi;Ii1larHEK@fcQ%$YM`p65>>;$WpxIUfW8xpL*okEW)kzGba_=G?h+ElR1}*w}bw zXlUqJ&-1?2>2z)^EG+!-ZnDwUs{K7IN*#@Hw# zGDLI%Af(+AK%VEBwf1zL=T5ub{uuydMNxcSYh42XhKNn2)LZp>{kxp=4aV4C+wJzv zD2mpMF(Y}NmmSB+t+hAPG$ln*Or~i{2_XmoKnWpDLP%z-;U*!h8hfmb-^ zAFQvhFO7|jeZAdo|6EG>uGV@milToDA%xbNmP)19q9}TjQmP%tX*Qe9b%Ka6F){I* zX0v%dP1Ba|`#}%{icyv_1+MG9<9XgJW9&ey)yf^md0z-I5=GIb@B0^&Qb!Rn z1%Uq`;>VRzRi#wN_k9_L;UAWkmcGLP04Sx`g%DrOvW#R|rm`%fl+qDIEC9d?A-+~F zmq&}D_?5Nxknj5!o6Y7;LdfCG&CREjQXN7_KnOX6h#C<)gb)xyP)h0b{)OG%-o8;P zm2P)Bou{?d2_Xa#G3zN#k|cNYJpTw|>`g>0;y6}>kSS|zZmo@b+SvUt0J!(t5JKGE z-rl~^m!OrEm7EZAQA+9cv}%`75@U=`(=^JmtX&j^F~)QdQFm2)rvM`W5GkccDZRL| zvXb{f000XM3rj+X%TmgL-6Gn%0=vfp0ud3UlmkMD%h#@5Tk1{FovWfKdc9h$&Pgfj zh)8?#y_e_;E0t2#tJUgU6h*J^oWBpWy1HrzAumfQFV$)_$vF@D()?%ua?XQVttO?E zmnfw#udc4%XH*_)PNt`)Cyg<$CP^}~M{{zUF*Z9tKfmyxe2=tS)6>%o0QO|J0O0NU j`T57UTf5``HIV-UmFj6x*r7u_00000NkvXXu0mjfW4s6C literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/skype2_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/skype2_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..ddec144c66b5729ab948adbc3e4242adbf5034f3 GIT binary patch literal 1003 zcmV000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-wWl2OqR7i=X)=P+%WfTYS-+VKUc`31G2*SvSE?&BA3Q3A= zQ$}U0YE?nhA_%I5Py{VnbfJrZ1Z}E?L@Nuz+!TbBw5g2H3QC0>tWl?OMjdnJ-{N^* z=XK^&Cpz%*eb0NI^FQx%F8}lNBr!`F#4=n^*9Wl+!?Q8&n}vQYZpX^%WNy`sS7$$9 zE4JXo>4199aH4y$9@k<5$0|@`&{IF;9Q0xbUc%JW1=i?0N_aoO!&;%7o}*WAKYqs|?8Zmfi_4T;H8~on zd&cU?RmZ~>;{cwVI(yPQ_ar%*WGKnuB%6~AwDgk9OLA_K^OCGg@@$e{>i&JLXQ*PW zYit{U{v_Lz{F&sBB)hsekz{U?!6b`X?=DHQHOXkp$-auUy<(qqbXSrib;DSaH>Nol zOtK-#&q+oq*vCm$SN*~yUsUk6vm+H-r$%t?w8ZXj<*mOK$P+bJ8?X&`Dy4iqM)9=L z2A!7eWX0B}bo>e&txhJfw6*zCtj18Sq~GfM5j=*g@GZW^=eVsFNKeIFfx!-zD|M zt0!s7d#_U)b+TeFJ{#9H@)OqJMy$dO_0%saz4T1ow?KCW(NSVOZYqfs8o; z=kO_Bz}ThX*HqG3|AIC@sI~5l0t;z`{KWkc!7buBeSN|`;6;;366fJ#;zgi#N zTd{XGeezbT;r1mtnB~g zGbpG%Cf3z29C7NLS){P}he|^Z*E|g=B@Wl&d8NPpu2ETx2ddqSdGtCSH}f7a2Md)# z`KKoNFn+D!xg7KAI||!u)EX1r2H(4;2H&Kq(rtR9J>>eU?zkzQ8&KHdA+5pJZIt)o zRWnC9)0)ufM|nfAQ-)m}HPT#8uBj(G)8(Xt@BPQiNn7UN4zs&%eWK*AtDMbITmIJt Z@?WApjT=99^9=w1002ovPDHLkV1mcL-L?P# literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/skype2_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/skype2_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..fece1ebba8c6ee01e6fcd31f79f8eabc586f70b3 GIT binary patch literal 1718 zcmV;n21)seP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-zFiAu~R7i=XR$XWu*A+hZZ+2%#n$_%%3x(piw34yv^relu zg+|74WNc~ImgGJbS{n)`f#N>&A+%|rA%vDf424i|N%Im4CFo~Y79z3Yt_iVhN}$vb zoI+@VF-^Uz-5Jg9+?hLbZXY}=R%sm+dR~SL_nhyZGv|EgBU)?Nk4;TYxd#p$IE;u6 z005=5^WedQySH!OZtcgPd>+uk!UES?&nTsyR!SX7)3mI$&H(@rLL$akTL|%i5aJpk zU(kEi5cll~R}b{r=-pN>oZoL`(o+;6Ny)TnLfR=kv5sDEwUrad~-pd2L@n zr%s)sxm@n0FbvQ8z8}YN+|M!~0HCw)uIVg*5Tan)wqcs)AEPMx`NqZuJ`(8Iv18nE zoL4>1Tl9UuO(_+IVH7B(1QE4TDnvw`0VDu`87|2HscqY(VzIciy}kX+jT<+1OUZ{( zi^bxLp64xkp4YN0Yt*u=j~Qd@jImGBH2o?fJ}srp0RT`+%StIb48tBGstgc)-){lH z;@H?&8vvgBuZ+%|IWs4ve67`LbuG&p85ixA=`OG``b!R2bTYTmndkGrl5j^lhK zj^nu~ihd9T!GSOgcLr6}T9b0QJeJGlE;JgAtGhtQj~_QI%UW->S`$f7woNHv>H9{}LoxpN2OIDW_fQl?l_W{-?d=La?T4{Ysj*aN~t52O2wt6Qt5D-rcO4Dkfy05gj8l`W*h*3IF26}hVd^%EL)cK zhq<}AOSM{U+Vi~MB}wvRqtRF%JPHwSa?bhCIZ4yhaUAC`)ml3ltqkUaq-h$p+ieK| zaP8W)u4$SVEz7!th!rX2Z^AIFTbA`F#@KhJr>A!VXQdq;RGr0k_RP_6dkz!8{rmU- z(d~9?G)=#)l&U02@}h0qqX6)$%-_;llkCxZ7=#l-I)so204xB|h?pSa z0mpH^3;-X^&dxsJy6&6ha{2Yu)zudOpqX{zPkX)I3!L-s4VZ&5W_*UBNEW-px3{2x}G>DJa(E2H}Sz(GnWwbmDAXJ-p*YisWthVc^T+)UH- z4bSs#A>w;l>mON`^*$lww*z)T#E=l8va)F*L|zE-!PeGRivj>pO5ZX~lMZrCl0*hU zFwQyuH2^@pUcW4aI72DDjEJ|i)(y`2rGCF(U0YkbJE)Uk7?aszL;wKOG%2O@Er5(v zgCKavvaCD3UT;Dv)hC2Nuh;VkA>XgnYGy8%`(?dezXxhRTWYq#57Ldc-ip-?CkEz9~;2yqnv-c6FE%@{KQ;L~=y{o%ob z2SG~tI3hmh`~H(b5bOW|DVNJ*`F#FDyyJjB_4PO8*G}6cN7`hGAYx82|v-w(Z)sePwlZb$3ndnWJvE`@G{gE&we0zTbw2 zi;ZZl6Degk`^ke%%LyTq58t9=L<|Ta)VA$%u~=N{bUM!u$EL%FX0w?PLN402eWg?? z*+Phd&Wt=XAcW|_l0!s^h*E2fhG7&+rIKyi_7zI$#b&d)N2okfoXpS9*ODZ;)bIC? z?o*uH;hbMySy^fPuXvv;x8~>PIRNZSZUMmCD=RBsTyA~V{$Bz4A4C6$uhKvGtN;K2 M07*qoM6N<$g1f~kFaQ7m literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/t-m_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/t-m_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..235602c5a35648d4f922ef2519887cb8e5b25377 GIT binary patch literal 757 zcmV000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-vZ%IT!R7i=v)=h6rVH5}O-%O|N)JUizf{L)Bg75*@m2Sie zD{OoK8=pZWc1;=^maKGzjfj<%c!`&Vg?K5EYMO|8nVK1k=Ulz2Gj6MKlAF1Ao^$^H z^PF>@bDmPG)lyK_VFw1{dkW7nS;V+fV0{FKuq#Mju7r4BnfigVb5 z2EGMQW>5-8s_4QaoX7Q|L}gsW8PqY8*Po}GH?E-vmv9!%PDB-4#xW@@%>}^QNh_Qj zz%`tf3uSqp@&z2161*4^q1z1GR{s&OcLN_c`*K&{ujG4e3W-dn~=2giuNi(pOr4v7dui;5A`lJfX64*j_taqEM zu&!9I#CyJkOMy9rb!F_7O0pr9;{)8ogp@l0@)EQ0Tg4ZAinR%;h-%?L)^Qqvy|W@! zM{mx9r}&72Sd;VqHZ}$*yvJ+o#jDWSg4Otp&7s$e{(P@%#SW_RJ%AVS`wp9=Dyrfk zK41gxU=VNd23vz{dqm(@Y^S9LS;I=~mvXc@cF>IX`%*qXVMTaf51lL*RjK*bq~6#S z*wYm}liJPtFdW3TFwUeA4wNIr4Sybk?EkC*mx5>t∋Oc#3^N)Mx`VtGJY;RP+V* zWOj~j__OaVhm-^R|F@vJG_|;u5pZEZO&jRBm!eBFtPC9yCMy~ zkCrz0)=Go#ln#UM2To!XtE4!$a?e8G*;5Of(ZKlaqEh5?vRm3&r^`thk1g_Yl9z5A nR_wZUQ-`zmH=?}!(*^P;wiCy@`EdDv00000NkvXXu0mjf3Y1$* literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/t-m_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/t-m_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..d7520a6b2c1f7ebc3b3b9d7e7ae288fea14f1328 GIT binary patch literal 1253 zcmV000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-xUr9tkR7i=Xmd}e6M-<23dtJ5NH9M(x+Fhe=evn*b!34a> zUV^M7BAAt3|ATmvob)KcQ^;9Qxd`Sz$SiII(cosyW$_Y{2xcLdBq+k}&Wvr(^pC2p zm&5iQ%jZ$jmT~jvqfhH9b9j#5vah03f3F=H}+cg9i_`##xV} zKub$Yf|)-v#(ZjwnJvq5KQsFP0En1-p0_Qfd?cm(5fSe;n@ziC(9+V<=f;?eyDX%q~%^$`Boj!e@FENGWSt>j|aQcX^(Fb^G>hw=3wxi4&sHXngzZ*|T$T9Jc_#?FQHdNLuSC48!kR zt=5-7 z$uv!m8e@9n=42!Z5sfjuG)<4z>-CcZkaO--nx<~_^1UlfQ|FvJ1pq*Eb8}P1m|0^? zhCA|!C_qFH{<|}bh_d=w**{?b;8hU_MD%#*2v<>M#+cc;xw$D3MbVKw&l}FUG6;fl za&q!lA~JcNAMAF!hpn|n2;tT1^}mD=2g|bJ_k9Y(@F(B*4_RxU z6h#3<^puGHA)=3!Qh#^5T~bQDYm5n#BuR>*m;nH)N>)P*g$mBOi9FAJB4X!UBM5>& z0U!c^r-*nM05*gWzVG|LS!*{v&pTkP{n;2Z0xW_ApmdyF!TKR^Iz)q`jnJ1MnvVDdxwY&032lIjEH8l zEDMq(nRU+9m^lXks(iOatJT`jTDOVlKv|YWk|Z-k^nO{E*-&mvYwa;(3=$DCvxEPa zKXlHOWm%R0kRu`zk?=gP-EOxxXnlQst19&Y001+W*4n&sG!Ot7=Uico$*r}x33Sw!4*yey>@5z!r}?gAu9a!)Ds zP)b?jai81~s-meWr5+|pa&G`yU0p2@@v7F^hpJY+2?qdBYwZ)!)z#J2VgLdFSXo)Q zrIfm%wccL^^*S(SX3$#iS4!QudGqG2zJZ2kbvm6ZVHh^G*3-;Pd)Y?b5oxWb!!T@i zI-M)S_7^~FYikw}FKDf=M^U8vIU5D++ohDXD2lY!`Z^I^SX*0rp;6hjIayp>T(H(& z?Dcv_$81g>3L&m7FE6jW%HPO#YjJT=0Ki!7769B`US8gNyY;f(w1NB=wtu0)EXI!v P00000NkvXXu0mjfC_hPD literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/twitter1_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/twitter1_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..a72a9afe6b4f8138a097e1a5f269b6c9b61cb498 GIT binary patch literal 795 zcmV+$1LXXPP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-vl}SWFR7i=v);o-hQ4|O8-;CKAnJQN^8h40A!5S`*!()B{^ts`v#` zhCIPXDZW*WS{W0%cW^(v{fvhNz1+#%p(;KFc2@=SH7fpac(@{tJr(aUUP_W4T)<9D zz(Jf2g2$oXiMwdW?7*I13GZtf1@;_IrM9vSXRrlF!@Dx}VmW%T2NQ7%GcX62rCOXD z*prIAt`r`bE#m=};4R)1!Z~2D|J&-YM*}#-oPVfK#002ovPDHLkV1i#KWvBoE literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/twitter1_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/twitter1_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..8d798206713660f6a34187bad2d5e2a9a8836e90 GIT binary patch literal 1347 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 BU>5)Y literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/twitter3_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/twitter3_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..458569d25178c474df2af8460b2ac1a2ce557c0e GIT binary patch literal 924 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 QWdHyG07*qoM6N<$f_e2ec>n+a literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/vodafone1_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/vodafone1_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..f25df8c2466b6e2aca3983eef08ba0b2a9cc7677 GIT binary patch literal 840 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/vodafone3_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/vodafone3_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..ddf2a21a28b05120c5d1ee38c2e98c80d452e02b GIT binary patch literal 903 zcmV;219<$2P)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-w0ZBwbR7i=X);o-pRTKyC-+VLdF2U?dmi5(Wh>ai^t!yZa zjc#Jp!ibgH*eEgB&{!H1V{|KGq9#xnA2dEAVxz`_TBBH#=xPK6ltor|_gLKXF?VN& zVTdRBlJDGm&*Pr|dE8D!7?b932WFE$gP(9}9O2#=`}24Jcczia+*?j#Ki~^|j+HAZ z>WsM2qd0)Ou!>8ms1@j>BU9+&JG_Dq$2HX8bv%QAuvDKPI9m&E!35sK3s@UvsE0#% zTnWosr9AS#=3{_wl<YRv(%Z46`h>Lk(u`=>@?u&?fBjRKf`nXzezn6yS zxR|;xV>Ca2$rMgtU#{JR!->-$N`~zj!1qOblepEG%~O(L4mbQ~v@Oq4ojv7=G4 zV^TkKJ^YT}lAlyEZ?*EiljoOle`V+|{HovD)>3}!U>()e?k(pH>w0OaqaTTp)F^ec zTq$0`jY6^hV`W>N3-DevmyUr-sNDsGJACf}~@Y71nXVdV@ zO6P8A4{pQ1$#+xtiJsCje#AXW6QyL!b2x%ObL~JXZ5=p`zDA5N}T1r><78 z??yy#NO2DP7Dg59I4$V2h}bp4!1joE=V~peZmN$Y=z~plS}D{o@wHMXftwSP`NZse zC9|Qa4$h+mJZs}SpsTc&royo;$_qA*@HwTk?7wVz$lyDy48GHb55Ag)4Zdy4;Csr5 z!MB1Z)0-J3h1NOjx d>3=;S{{tYLHXU9uxS#+4002ovPDHLkV1k)yro;dM literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/vodafone3_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/vodafone3_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..53e64e0fdd87cc32358d99d244c739dbd02445c2 GIT binary patch literal 1604 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/wifi-router_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Network/wifi-router_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..d1a77e43821908e558e29709f80b232ce46a47c2 GIT binary patch literal 1724 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/LIBRARY_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/LIBRARY_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..af45968fafb6c78b1ea8cf8698a79a0b577de6f0 GIT binary patch literal 795 zcmV+$1LXXPP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-vl}SWFR7i=%*3FAfQ5*;G&wV`43}(SJhOF$w5JjTvX9HTq)y2`}-Xlg;%G)^}kC)&@y;tc?fRbKJr(eohBe%wW-8oWy$k z!uJ5m8;Ve5KIY*mPT_i|L^YhjF*Gq&m2Z=+Ztg)B&f)}GGZEEs9{VM?w59-`Zj_;9 zAFkl2iYsev!l!XS3h-=5glsGJ9tf<7#fn9Ha2X?^-E2szBk%3SLENYkb>W_rzGHtu zQYGt=(tit@*>&5c?D`iZ0%I&Nw=)r=U1lHnslMC)wE|mRs`xedCKcn45NuS0>+x<$ zZvGOog;cm*ZPqlU+WHpQ{dEjTDcQh9Y{X*Rjeqa35?}EaE2ONt6hQkih=o{=_c(+* z*c#XaH7Pr~LxY$299q7@>(Kr+-e3tHNtro{C!xr@@WNPp4+d^MuzTC000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-xlu1NER7i=XmOW@3M-+hHo1fjC(`i;6T#3$O+2^V+YF;fe1rVBnHP0hP1MNPPabY z?B2}HOX0mk5|%jG1CN>I?YwW^ym^m@La?O1Eu zg$MXD15_B0QkJyVfl}(nJkP(mefzfG6Lj+ANs%PU_swSWT$-jE0O0om>;Yt2>q;EQ zzie!5e6_T+)W1rx{pUE2zbznZh5dmb0DX^rnx<<2aBgH|WE}v$?&(=?arW%l=`72> zOw)Azppf0XG)>pDEc+{!G0A;9|i!FrfE(@7bhntgFdKS zE}u5W9JSWA2aUaF z-n7U0ogb+UnAxcupH;gf>Qp!)Ab4!gz;{)ehk|fDEBcgArr=lo2vbD8E#RJR%pn)e&oEX(w|J-ag z$HOq}Fvd~<2oO;fFY-AeR*1+J2XjP}XIZ9%5EukOr|?_>z;hzv0KkkfNJKJ8lE-P9 zelC`mm)EAJryp_7-)*&84iOW0k+i)c7z2QX7m4VKIYPv)a}KjC>y@#*h(|BseHez3 zl=9K?^70x30AP&WQA#mH^o0;2LLt7GY1`bpmj3tde*gfKQj9Tnr=PH`R_mTp>YbsNb40iPkW@&|U% QqW}N^07*qoM6N<$f)s;T`v3p{ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/Llama_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/Llama_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..851a84ce382f30a9b0d6490da46b6e55fe1626ec GIT binary patch literal 855 zcmV-d1E~CoP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-v(Md!>R7i=X)=P_AMHC0{-|g<{Q6oxB22sR?xX>gj=ob(- z(JXwdTqq(gL?pOSB!VD_ZnE&P6n6nPStYCJd~(%_RE?-{BIrX8|?) zc=Qs^;0f$tBZ0;WO&W3=`uG87aiJ?w51->r+``Rjt&h9%{|(%op54Hm7~*TZi%}c2 zmI2P;ZLB6qlWW8D=2In1oA?NexF^Y0Q}>*9S|XwzUqr-KL|n`9YmVy?@k>O!lKUQr zh*$G_AtKI4#B!y#l~}vjwMQ@DEt4v0YI`t;2bG*$#W%Tje|j{kbe0n9#dhe1_#nd( zEfPvG9L5_aRX3KW@C?=~10%7{B=#=RNu|2#oYc~!#eYp%8y7~ewf|;fo~(&ZX;sM# znP$X(GD>U%rQ?q)uDA2jC?zd_`?^b$n8&d&z%ixccV>{R=X_fUQCoUBX65z>jt!I~ z&zpp9+`&Wqj@NNb@qS0?ms&QkHiblD&g1a3v#v=Cuj4g*KV?rX7nJb4XL_-afXhlL z)>Sja=?)~Yg+ENsUoWwjd$^*U!u7@x9#NX}Ah{QhDP`W4eqvwgDP4RSx0~c=8z19n z2cqYcJhpQeiFp}I<8WQ_?*n!dPdnJFZ6$ouq?g#c;ET$Aawsj?QS$T|?rSMOgy*M# zwtMhUVlLK1x0Fk3zNN5+zgvJ$;*%Dr*1Soqvx&VYTo>_`NnS=u@0_-`P*!q`Wxe_y zlO9d1i{piMAHA;}NiQo!GKY6?hjOWn@UU_%e5mB-gvsgAOOo@6Rhh8&;u8`5i1;!h z)*@mhFTNW&Uyq2@i1@9VuSCSv{9Q}kejB&T0mjCsD{0DHYXibs8Lwx`M002ovPDHLkV1lU(lc)dy literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/Llama_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/Llama_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..788f922143ae6c0bc988dbe9fa48811005f75916 GIT binary patch literal 1375 zcmV-l1)%zgP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-x*-1n}R7i=XmQ9EpMHI(heRWUI?Dl*ms|OE)!H^}QD8xNw z*{}(V?uMD1a>zkFhz1V{=*5tWAxBB@ppZk56 z_EHo@Zy96IT5Aw7q5l>z&bd@dh`F#E_rPR&2xw)kSfu^RWxa+#twbma8LD03< zMq6`22(Fa!5z!)|5kmNg7+Y&QN~wbH`;O;%KgMx<<<6ZuxGQLUd|Z~xFs=*$<5|p9Dehyr<7H?-3$OB6{t}kt4Zh&z`LVz%Kv*VHmzj zL=_@R0e~^aCZfuMh{K8o; zfERL$h)J5J<#M@vR1#6SS62E0Ll zKf)LrB_jKR3(lnwqSb1(p7OP|wMMVh=ZJ_HV_=L)thHZB-ENrO zHXU_jHvcNfO7g-RZjVJdbnE?*jC` zi!coDd!F}LDV6WJ!Z?l{BDzjQuVfdGkB`4ztJOZpMn6~^dv5Zc=RFR?@O~e(va-@; zjNR~k-`!e}rYUs0-Kf!Mgjta5x^HvNuVfqyS|I>nzVEx7^BXHGE8RW_0AO)(aoO{{ z+rIBtdm?D9mDOtXQ^r{TM5Srk27q=(SZ5(b1itTAJ~a zRZ9KLIS&|PX_}^QNGab-)AUy%L}INS4T9jbF(zh=ao_i=#bR-`)oOkI@ZrN`M-Tu& zyn+ zX;ydF=A>4u%_K>3DT<=wTI+sulF7+nbMjb9d2@b#esL$gJ=?8XttJ8BK000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-vdr3q=R7i=v*3WNEQ4k04&wFmQ^(0jL!iGd75+#J#Sy&bu z5eqB?8Bo@5Z@1oVdYjNi0-B#P&(m2V@z4x4% z?{{X-%$ZZm^IXNz#5VND|2Rg`s-m1#SU-dV*byY%u{IfGFYpKtFuf2^Z4r--;1YIW z20sI+P^g6=Jy?NfxQu&MiR!qDvzWp}S$>XeS-F9gxQ>fxFGiH%298N#Y0m?`(8$Bc ze%!$srBK%A2w%Z*X@i$SB4pd4dpxi@izSZ^<2F8qbxR>Bk3zQ(Cvd+^v=UFH^qu$z zk}_FCO8@6Wg6|kmPr-A9Y3UcXiKiI2;pL`9rC$O zHg%N@te3uLLiT51H!}=MDcQz1sq!KtxKNzjN;%K~sRtlB4?S?{qo3}^-5Zfw9>JjO|E!Rm;}zLEZpyf?60#U4HI=ef5WqaN7*{|K6rnpSs^RPOH!kkkU}a$wI2*L{pgby6t& z4T-=Q2~5o2_-;y#Z_M8{z5%K6owi8ho5m>&V~tM170-O&#nT9#;lP-6QK@n{*(rIp z*yW^-=azUmDUU83RPDO;(CqqJ5>a{l(*^Q3rm@zGujxij00000NkvXXu0mjfa5H9& literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/MB_0027_LIBRARY_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/MB_0027_LIBRARY_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..778ddfc33c06eb685dc7ba3de04f09bd44cd45d8 GIT binary patch literal 1261 zcmV000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-xXGugsR7i=fmOW@(M-azn_T$~#m(xDoNwS-S5E3E`4u%xw zIwL1BCbEp=G-+c9IH~M11Xm%oO^P%QPM;zttQd?PEKX^J+X#%R6gDX$-PgOP_qA_# zQt0kt8%vz*3@j|n?);dY+1)=95lmvIPoJKho12?=&eZ?_7-QX?ot^DRj~?w#vL6ov zt*opFBKpJ_^RY4Jgtc~th$;X8h?sNE+fvHMQp(>E@jrkm;t^l z01X33DFdywrv|Z5zjivE zuQxU}#z!fhT^xqtcSFeTF#bdkfN{nyilSWrxHLUI-3EYfMt(M$T)cR3G0U>cQ53b0 z3VD$iMNvD;vdc?LON-Be78Vvf=iId@igMU5_Nzd~FaV$^igF^lwy?0^jX~9F^=z7^ zCyg=5q%}E|gowtNBu&$k)oS(Z804Hgm!_#ZeEZQYO;hKbI|l&38jZ%RG3JCZCIbLI zTtfiBh=>7z1OQG%2>Z<=hzN$=DuzA|0FsEsV@z(0Inih|W<|YTpU?BWhKP1* zYHF`23eQ^0gCIy4W8|FcBBEl9)vUEoVZW2#LPQGye=){t0D#uoHs^e1*yhIo;GZnZ zd~0pJR;$emBC0v(e9!ZIrPL2Zv?zo)RjE{dQc5L4h`pjHIOlv85ub9->t$KK=bRf< zDwQOTm7-KTu_b)$r^5hq5?MG>v28ieY z00bg-5izsYTF!Yx2(iT&+d;$+5s}KWYy&{RIX^{2$2jNVU@-VYDfRhaFnC8PRYgQE z%d!R$wc~ZWe1S2B0AS(2%Z#vJ7_HGR8hN#$=px#yRhHyWMTExw*N!xVZRON_i?x z(`b@=R1}37&C9YJzh}mnbkx~IM85C)Qp(4ho141~0Dv)eUn#{95&qAilwypr`!G75 zIF27GrM9G$0Uh)~9l?l*q?CbDYAcT8hhxzC`g(zgH?-E3VNG5KMgV|X>k4D+#`^kt zF$MtutgWrxRZ88~TF(rVdKDNE5ooPvlv20v+_`gih*fp!!T@Wt>=bM$;2?) zH>S0o3&XJ4>-DZb>wgZ^YPCv4yrQ+fRj=3esAh)&M}8?~P_Ngu*7_D>>`JTEdQPYu zC{C7_mzT=2yqYA*$qB{DmJs6R>gwv+%ix0aWe1prJWw*cV5>gwvz<<^V#x&rcF XhjyXGy1_h{00000NkvXXu0mjf%`r|l literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/Marvel_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/Marvel_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..2bbfe6dbbb012de93d807ff6b9a0b4e20a8ba84c GIT binary patch literal 910 zcmV;919AL`P)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-w2uVaiR7i=X)=!AlRTKyC&wKOcJ##F3jxXqsRwDheGJ~*9 z(9)WP;z|qpqYI-&n_A@3t%U8QXp<5|t{f=TZA1_f^oLLh(vrl99LztDX~yxr7U%qY zzZst68@+J3_jiBie9yV(e9yhN((QH)*jjiJqxn6FllW&4<=O!M$M7cZ`Qi$jwU5{PGT0^j`mg7*$6?((D z)=tb#^y+9#FDK`7{cfDY%2XOkBY)vOL3bk0mrBM7$}daIF?>}M75`K!Ht=pLzl}HX z1@>W;sIAvhepQZb9LH~X4tL=d?8H>cw5nJqC^?%3rf~w_=KKQw&2b{-oA@Pn{3jm5 z1K5o#iB%DWK8khKRBGrIUp+yO<@ebPRk7a4JUk<)d^P72_#t;xkg1dM&G~iI)g!! zMR9C>mtn0Z_Qk5m$7IQaYgmJg3HBr2zzd=-9>o3l9*?HsRz_ft$jRsUNic5`CyIjo z7_Vn&&Zd{cBC%KSM2>$a&~cHkhecst!|BwU5_#I34jjZgMNE%m7`s@TUbk}od>UNaFYBG|Ck69n1p)5KUSQwW5!6kvsRV9{f~}>qMd7ay#F=vh&4^2@kwUk+-)n*Z zqbb`I`B<9cG7-kTi9P3<7{@1qJ%#7}TH(m`>~ids)|!bmenY9x#dknld>7o_#kW#i zd~aFc;+qxc+kO$6kpw7uKk%ZDq|W}tnDbB>};XONmZPEi+Y@t+psu^2YGHC k6}0c$Ze^(4?&tyeKhzrXPwzX(0{{R307*qoM6N<$g6R#mk^lez literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/Marvel_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/Marvel_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..bc16d2274ed2ac879111991d7672ca204333932f GIT binary patch literal 1541 zcmV+g2KxDlP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-ye@R3^R7i=XmR)EZRTRh1xpVJ)?c{EDx9dk#QY>v+Z1F)U zc_@S|S_&~G5eh24w7wMap)L3z(kBt$L=b!t>znn-gw)VRO(A`dS}Z~>Xeyl6UG3y?9!g%GxF+st*{AB7MfOiWCCxh2q{Lx-4US?@+s zbTkNpL@5>KJHUGhP%a>ZaHW){<2awjas2j$3m5dJprN55UMiJ7T3%j$F$e-50Q6>n zO@K^FSuPffU--WN`lU;k);=X)|8TKbd?$z8$@RAc0a)9y4uaqg0KC}S+uHzux4M4T zy*YgN@JOfAITi##<3S<+<^@5}=yW>AMn^|SHh_kQhfS^Z$sh<~xcjsJ3uFxj02Bm4 zOhhM#hlkBIkmq@|D2nzbNfIKW002%z2moe&bS0Jan9egEQ@)bcXVZC<+$g0pER4z4_()N z+_vq}dcFRd5MmEw>@mx-c5AJ}FbuEWxN+l`fq{XiEz5H9L;k8#s-u+JGdMW7jg`yg zfh@~PTI&n|m}#1c*7|2e{Pz6$^9kp?(P%W5l~N7P`JxbFw`rQaw{PFRPDFnZ(SqlB zef|CYk5;SIQ(2a^0U!kc)LN%mmX%7S(f}i(Ql3^Q4;wKvGvhBTEX)D`WLfrmwOV}$ z08FiQLu+kmt$BZc|5Hhl+zG=lG)?m~+CJxprwSyt|GxO-<7@@$%)% z3w?ckC8g9Y!!UYt=*sNu?EK>5;-5V|J#XB+d2>-IMTq!#k|Y@bFs(H(#vDZC@K3q| zj)+Y}i~+zyL`u^XYqi?GD2hTML{Ah&zs}6eTAG&ci_N*okS!6fZMjcYFXAJ zN~xmOx@;K6V49}0g+k#wBB}*J(1VCA0BADb_va16Xfnn)-8EGx6t@k z+L0qiULG16de-;-`C_ryC#8HiP1Emp?AWng2(eRZT{(O9>_WX>f6un<^3>GS=ZN^D zVHgF&Fq+L~a~_EZMn*>7_kI5*B3ki0?{^`DMMQ##+K9M9M7sc>t+igVEUWB!-qkG2 z{4flkFiq33EGrd4{HC=w8DpI|j_swTrI9#}E9G+ev+3#SQyc(*G4_?~y05faEm~e) zelq{I1ON{K03)IV5i3OWu;Vz~FpSHqtE++U`$@H01D2?NoTCLWhBuOFw$lC38uTpBCQi^lV z86r{`-j#4&_jj>K_%rqO7$5b=Kbj);gMVmD&5JSA-?Y?Vqy+O~ac zYHDg4U|se;ckbM@<2Yxel$9L5S&hg1MY4PVB4&uF5itXROiEdD9Oq0IvH=7D&}y|# z7mLLSDP@(2Shsp^#qx+{Qp#$vSe$6JTBq0hH-P5m=2ApFE~WgqTrNu?gqsU&3herY z5N^3#mQu=(8Dq!i=H@muDw{SZV`F2ZX_}r0!*K5wo0IFD^A9E`C(qqW@4oHU*w`2c rfGxFK0PywX000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-whDk(0R7i=XmP=@zMHq&klUr+{U{Z=is$GeAp+Z!ubrDf0 zS{qV@2#O2Ag+jZkAi7cnD@4$ui-H$~)}3_KHdX3nBTb;iDr)LNs#w!ldrNGRlQyS) zT>S4Le-9^Vz=2`r|7YfXzsr2zHx-p7w$;ELz^Z(o1C9e{mU6gl3G17H$AG&-vMg(t zLiRK81uz8E7DQ4P>QAb}YE`YN=heT})9SfWpUR$*oN0>J>}QL*Q=L{XsgvsA5LDGM z^_V)UPNa`zoXOdi>k+l7d(_K0G^}n`E9zEtP+gn7?dl`yH__@Zbv$SH1ZzQ}_td$N z>{eGa(fCgFMRg$Gt?IsLeky$~SWSugLr_&eP#=zo4y#AiZP~ZgqRpvC)NXZ6$#;K7 zv#PqKk*FhPx)i6j2jDq%dw^dk3AHVf52|nF-zVzJ>aQW12xdo_s4v?5t8QvA)o%4r z69<17D|D*Mrn zv?b#20tCLw2yip-F7R=Jb5#O#1MoR;18@~M0Bi>~0w%n$FUDgm!!)jOQUq$`MA|o7E50=*UCeU}O zw1j;qrnwrE%>l0fYhu#-fE~aez+_2kDK5bv@CNfmu?Og-xL`xY&TCW9L{iJ|iTshQ zKdbIf5bjGhK)qG{F5^avtX;{TnoUwrJ#MNY8cPgJJD(U|Rew`w)z?cgQ#LQ^+u1W? zlcZWM6PH7DDuH@J-B8lJyX2qN27m1cLCrEsh6aD8hf5)P9^r%nA@q5*k z>I3SR(WDlPMGIfOknMCnIgVMp6{an+`}xc#v;KY7YtEPQ)<)dxJx)e)c*^1;oDS%C z#000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-!6-h)vR7i=XmVay&Sry06xifd}o9VnaZ(dsvT?x993U-6P zLd~+$(pb{HZ94RwYSNuasf{0EoynP4g(F6O_^s zL>w*@3h_Gz_4M>?5kfo_1i?d`b1H=JlOz%UPKM}8DL_O;DNUKCNi55{N-2H5P$-=-}n8#R4Vo2`t|Gex6Ekk)~yG8-~X~wDza^R z;Le>pdoNwOR9hUdWy_W(Lde5OlFSYc4i-8)I|(BGs#GeitJP{%0075v>eK1;;p4}T zKmA{z&d$!wVHm!|ImdK5eS~vt2oH z_|Y&7b*0p3wOXZ|^I9CodVPJp!x;P0i4!LV7fRRO-fl=K_Xa_rrPJwaQ&UsV0Ki|P zD0(3b!vR9bM}-gp0Kn0sM-L}S@?2&%z%d%$gKOb!eTypqXe9%7808yXsVdAPwQS^pk7_VnCnTzRk`tJY`3n5muw6rwnxm>P^bDkrFaHZ6h z`LDJt>tk^o=K!E1m&-jSrQF}$-8~k^@y|WaGldW}%d)bFcntt9<@5Pp0{|c*QA){8 zn>KwyDV2}oxIUN5HR%B0Dy32Y5CXu$-10o{cd1lrol*)kO$!-gYm`#?VzFp(&TF=9 zyRPg0$@9FOp68L~=H>^alr^PP2>?JTRgzK$h?oKZcX3l807Ubb^XJdc0l*vpz_xAM z)(9aEdY+dSLR4+r&bqGq$H~db&#zdqV&Af5%RbFHM?}1eh`W_iAf?2`{ig%K3?ha~ zsT?AHe8-L*QLR>^aU6r=IC_#KOQn=Q^gNG*VOX_oJDbbpuIRe{nCrR^CP~seGc(gc zDQ#tp?V9gPUDur`icCbD1%Me+DwS^Nx?bX(N7ZU|U$Iy`S*=!I)pdQ85VB9xw0{D? zxl}4;+P3Yuu6vabvisPvV`TuKgb;3;riq9KA}&+}5kCX~wx(&NQmJ%teb2RP@?`@Vlb(=_+)I9n6P@gusfhlG&V78-VLZtkpUn%5|$ z*4?hIT9)+$A>^=9DnY~#EM2 zrSD;keJ`KSKik;YNPOR?oO3>(Wmi|%H_PSn9!jZ9rBaX257qxz6J1?h2Ylb}^L@Xl zltM}=&E;|x##mo}fB(2`+s5kEtKISO@kvC)B}g|AmCl|52Q znog$=-E&O<0JOHY>aOels9Y{@^L^h_N+pJ2n2zHJ!!TY!#4}M8Rdii{KLG5elvV-Y ztBCkP&iT`Gb90X%qL#^IUM-i)PmGR^#`gpP0QB_qXj01kwOZ{9l}bejA!>vWEtN{y zgpdRPVgO)K6vc*N0AuVQNs=rRLgW}@QC(f#&lqF-^7(wSSobZ>Nq2X5XB@{*)oQio zFbw701sDUsd;k(cG{%_27?Y-HUe000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-w2}wjjR7i=XmQ9G2WfaGM_l`58-D(hLS`<-1i-b&S<43`) zBulJZRjU-jN>{mQ7qlyc#6SXr3=-6p1(7XWWE$m4O3n6-N{um^<4kk2`MG$`+njml z-sxHg9`1e5$N!w?JpbpTq0*y_04sqN@%=k+0T}Nkcu5cTXMv5tqmg7VY%`JU9PkzJ zC2+GFP-Br9Z2{f_Rs(+ne+Ez$(1=2o0)4;_zaUK2He_kry|8@Q4EYrZ+S1q=ZD zfnC7tVu_Xj2Y?qTZJF%=-c5`mR{%$VZKPHg(|ggV^;W3x)-_@O$P z9H!NSYAfu+>gQ@(9gERczfkW9pF7k8wPcfl4eE&cjXIu^e5y7Rz)AI2^*MDY#wPWW z`n`H*n%&1K*?3@&ppL5N)ywKt^=oxm3fyXu+`?+CQD@cHl5S8vu3ihw^Xh0b*fALF zngVtJ(`iwk1kM7dSSY7~Gr;*1m#2Z1>g`1 z4^=3PYlZHwq?5wRcIf`~P_1MSu#>rWK)#El`^DF&eUAY9fHy10P8Z)NloR<1|Lx)% zrkwO!S>)oo3A_^33{l!8^Dn000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-y)Ja4^R7i=XR$XiyR~7!wow++R`!lmYwg9P?%0p`fB?tkv z7b#Md3LA&6?cF*dqNoq88Wf5Ut;!3a3MzyuAt4nB@jy_6iue&k%-Y75V^>7>3r;8x z{Hbc6`cMc`*51w7J2Q9g-nl$<*L9YbG6Va}ZUefP|q`R+$rYaAygCMHHkM@Prg zG%W!DW2}AW&Yd@I-MZB}&U$)3qDG@(YOSZFl%JJSo={3vwAK~?5RotpV~2D8I_LaV zBHHkMzxRQO8jVIxO8HC}hNt2fJ= z%*+h4EbIGG6g?3HK_aCL`yJ4G0q8ye=RE7WZpLw(t3rrxudS`6M-rVmbH*%{Nyxzl_;hH~L_`JvqhGGH z)(U_oqCv-L5Ckm%j~0u?9RT0_pN{6{<{pXT_~o6QoemM{{xeNPER)IPGnoub)7&MZ zcE5w7QmP_^K$0Z;TI)ggT5C;}N~LI7)|1Q2%PR*&XV0F^MBbN*f5_x}U{)6>%*pP8AN?{Dxm-}l!6 ztS>AqJY-qc3qcTkYJY#fO+=7VhEWuq%;)nD16VTwAWhThD2melD?y=9C>4vvMJeU8 zzVCPE=jSV?Y5q8u%S}ls@ARi^^!)krf9&;oUu`yDJ4%PT7@-BYJdIi_j;62L@~B#*b-?a5ZFH7SJn zlGgeYhGG1sTCL{R*Vm)v<>jY6&%0JA6iNUfrHrMNC#u!zh*>U|$Au6jrBu(h?QEe? z_=}YC>o;%SOaWkQY^pSynj`u3qAy*@QH^;j;Kd$m%jd;!2!tu^N6=AJDS z3inAVKN&?)q?9U^N~Lk8wJ!B#g>2i7k|cR z3_}o+CL#f#O_P(8Bd+WIqTOzfE2R?KwsVzAbX#;~=u^&bGZc=2K-j^n4|IKC7FK_*F(JtAUSYwb7=V~ni>M@tZCtut282Or?~TQif@o$|1F-E`QulGzCh9{3{PX1w<=1a|HbNRjS-q&u`>va>rvFsLrjb^j?!R^*?{J#eB Yze{IW-&5Cwk^lez07*qoM6N<$f|pk%rvLx| literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/apple_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/apple_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..a2ac85ca3b6ed85df8bfb4936d903a1ab18b2c7e GIT binary patch literal 902 zcmV;119|+3P)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-w07*naR7i=X)<0<7RTKyC&wF`!NsNZZlEuYhQL!!6f`d8= zf(rhdjEi(~=p^l6ccCDnA}FF$1wp&0Sd2~%F6wBtb#W<@Dx{kJ3o+5;INbB=@8Vs)?PkW# zCstdEs&r4`BP{328em@Pfm6BKW>u5QN&5g_CF#SsUD=Nbe2!mmcV>40S1XKJJd4vJ zLPWe15!WJOG5umh{2UPv8YT4L*EIrd|<+KX`Hgh~8>&xU|)XMMbj`<1B z;vnu*_PDmq#GW1OBTC9EL%!e0rnM({SnuiPD%Prro49p{L}ze8DSKUsZelNYaZXX; zu^e2-UCMzN)t2#c5{*}6V~KsPt4PLKZNshMP8`}{Rv+R?MellvHI>*)O}Q4drE8k? z`5h8b$~UdesGHcDX6r}9H`#295%Ft8EJehjA&t46cOqgTBCaIHrNrzFgOrt(UMzQSnGWuSm`wrT0RSv{Q=6UVlRjyUNG#nypuP zFMVCBARTQB{DqseSNSomq-{&oSo1hJnBdzzPA2noow38mNp0hJ%xKT8FEX>C_FqJ` c{jUe)KSReF=WW+Y?*IS*07*qoM6N<$f_4L{n*aa+ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/apple_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/apple_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..3890d5b3f8bbfac90be910837f496b13b23c6605 GIT binary patch literal 1452 zcmV;d1ylNoP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-yCP_p=R7i=XmQ9EhM-<23tFG$ln(6J{nT(K&f*26PDhQ%` za#=}?GP>@V%MuSsBpz~8NXUoeB$AJdUV@SwqB#d=cN3CjO?EKku*gCVisD&91b3X> znwkEp?s_@cqwAtFOWv)UuJ`Nr{`EePh+q)gyLWGO)22<^jWJ~a0LEDR;lqdbZr;4P zJji)`8K_>bb0T_EYyF1SdPkOJuMklI000qV%d%QRh`U0F-x2Y8qtQq=464`bN3_e*Qv`@B8OgS67cK zrIr!VtO4{x0V(B>@B6=2tJPz(v$IziV@^L}L^MjN<<-^Ir8Nhy8TbxWmE$t{&iuOi~o!oos(YHI3j$8o-5jA5x%@;T>{ zo(fJ%shEh)jE|4o002DC`GFt^Mzq!|h=@c)LI}tA{fKk^9b@cIV+>=AjX939`NWA6 zml$I<0DLqwH1v-#<~3u?JH1}-^1@F3Fq7{ zm&+@*ZGSK`GqbcN)z|mz+2d9!6?cAq{=u5}f7NQWA4{duw@H#5Ns=T000_g-IF54= z0Ot7U=xEjRyd7HWsIQCby27^Y&(}c!0AOipsS5zz_3s&DThlb%N<_MUIkeW1)_TY2 z=xCKyDwXY7mX-5j1k17tobx-gv$MagclILNw{M>SfQy|@XSdcm>0ef3Oqyj`xm+%9 zXGB!a+Y03%8vyRnpiK|}s@3X97>2vTFkD$z5|sNcv*(;cL<|On}CJP5V4Jj zF+8ms0|4cXP=X-1Bc=RT2;r>D1m?cm?9rn~_bkh5GsZXoK$c|*5pCPKbEg;-)ND3a zY}@{(QmGV#5CU=;7-QVBtaiKIzQ-097nk!^?*IT9W0EvYw{70MdDljwYBU-@*|t69 zx~>8M-mgU=#NEZk#buV0=cSZ=y(o@j$Fi)cjer0E(lmX5h(*Xdyp)nL#^wR?7S!!_ z7o?Q8g%CvmfGCPONs=6|)oKGrl{eLMK@gOPD6?(5D5bpJ?RFQQfSS!_f`}J9&nv*= z8D%=1j?EbRx>l<>gMcO`CQkQyz5P)XbpZf9&nqy-E;O6X1Yq6ZJ9g~YmrAKqN~vWc zf}x=y-}n7L5b=wVk&%CH-MY0q%d)qK$YYHC%{iYFLd0<#zZ-_(C+&7SCZf#qysGDU z-_Oj#L1y}&Idv8UZ>MZk|YTbkt3p&_p$znMnvR9 zghZr;5YqEJyI3q7SqH@1^V3oMb#7y+dHZN0000000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-v$w@>(R7i=X*1eCFMHB|`-~C{h1x+BZv83cfqlwW%6B`;} z8>NDTLTGF(h+5#kurX?7W1|)ps0mak2_-gm8bK2Z3L`P>5+d%hF7EEJnDes3yYJn5 zjVHO8`<|J3&c{4+&h#R}gfff6*q7h;@Cz0u**u(Jeh$a+TpF3qxz#lGGrq$Wtc?Qd zZ4=Q+T)+!h$KMImZ0MyUJ2AkIn8&3_4fXL6-ohg+SHNA;0PMyTKE=D(*v`-ppW&2} zmUTRx0D%XogB>{sD|ncZ?ZZW!Q>C(fMjzlb?&kM2zQHZbqyu{r@HQ@|;aBjQlHP^H zSj0PYVz5l5>vKSac0L_COyiqaR{&C zfX#}~Pwe}B+*HcVV2pt&Jd^(iIHQ~|r3#$K7wNES-96kKDkb9vUQ`Zy)WPmlYS^k$ zKwrjnoK@1-G25+Nhk<%?-OAt7Dru8EPM*&wwtJlP@st1fIH_d^PMGYu^{v9nP8nyYmjCsD Z{1-93C4>`!qICcO002ovPDHLkV1ob8m?!`M literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/b_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/b_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..16c42f8ae61f917fd2bafedd916aa7e295764ad6 GIT binary patch literal 1367 zcmV-d1*rOoP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-x(Md!>R7i=XR!?XgRT%%h_vX#+Y}T3VH1(oKX$@8o0wH*4 zNztSb(5%RJtD-}}AqoA3R;k63GQ5R8tF4jn#x_^2_a0sxfK){`es9^Jcl zZ|xxVWIv+W*;&V0`?i$wEh*)&*7}gOwg3Qxkc2VTeMM(C=|Yo5C_Co3Ovj#!%MMkm) z0L5a_EtN`hgpfasF-4`+yX|&6pp>$5x%{W&I17Xjt+gI)x7%+@DZ80%b#QR73E;E* zY?=>FpFTa+?RL)!A)0xV9LFhg&VOh$8dnw<7caZ6D*!lz5Z86xzZ#9k*SBuny2?5K zl`-b!5f(x;yWQ^D>FMdIEkxtvntnE(JfHa0dSr5u)0cDH-83-a|Hj_=s`%&V@Ha(HZP zY>0+ocvNd$$sXgLh~qeAjHQGS<~RWWT1-8H#qqNqQN~Lm?T5Btrtn4d#D=RCC zb6yX_@K6v0DS#jQmZ`P2_jvm~&Cae+JO}3I=fCkh??X!I`wI&Tt34Jgrl1^~GIc+(V&ID1>2neR6WL_W1GRUpk%6w~Vo`s@3XCyY08uTF!ZqbN+C3b#=|j zm>ZtweUK!{o*ucbt2&*|pb+8}V@zy}X?mXb#=yY9Pm`0AD*!rL>k*|?C%5rDk5Wn- zKqji~cKgo2z`%n}r*mYxIuJrE0F+84E2UJ%n8;e25<(EiaVJTVK}u;A&oVDI#v}m1 zIWKvh_n_Tw-vKgZSXx?22_aW}-!CB3s+=f)U-$3d*8uv}gAhW9wN@#mHkDEv#+Wo; z^L@WSDZR3^w3Gtd>d~1qXD$mNKF-U8>$=SIyx%FMO#p71ro&MbdDuHUt+f`u?+^LD ze{F7Vu2&|uWZKiGPcKy}l_3CCAw)AxQ>~PGjS#{CSYu3-d9_0cvP7c3?;i?+;6|&} zy41hE<-sm5FDpXGdEfW1g<+`#vw{N>OGc)4=I8eI<;C8)UfBtrBJN|D2 Z`48XGnw!@VyEXs-002ovPDHLkV1j?)kO=?) literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/book_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/book_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..fcb6c48603d37427f7ae82b04e712fde20a76db0 GIT binary patch literal 941 zcmV;e15*5nP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-wCrLy>R7i=X*3E03RS*X7-@Um_n#O*_CaA@w3!6%H;l@p~ ztX7H$;s+GejSF?<#=oG8Qs}N&ic(PoU5J6=2ja%qRY6dxD1r+Y1|&+FrcF(nWL%s% zxo@sXxX}Zb%X?<#nK?7h%sH)y(B~S*VI0iwzwi@g`!VkHAwPk~@lZM$O4(96yM{0D z8CJFeYHf3(r|~8p#wz|!plZ;{Kz3sQ-{TBE>DN&k=kN-aajU7{quVqd!5}W;4XkbF zsDn#*PD#t!Cg5AG$RH2mBfPAU%654xH@TP00RxcXxLX-D{W>I119>?Jy1`&O-i=;ss1K9S!1Zg}%422jAgsOyhd$JeVmN$2+*% zaP&yZjw{63qtJg6%OXNVoQ#OYi1mju7!FVXT=nmDC;zMAN=6wj<9~_w@pHMdbTM2ttobVSTX#7t81bc4o25pg&o z4mI}bZ(l@AM8sHQZ!+mUlbF*HG2T{2#*YePYB3k``&`Pd;9Go!`!d?M6qJ!1N!o2Bj~0w zK3Z7psaa&LI!X`K3{(OPW}piSQPxLLWze#6X$@roZ|gR2voBgo^Un7KQ1$MllU8D# zN$d^R#1t-ItP%ZASG5^Stf}<~H@W!URr30$|90_>DfNEIHW%LtUc`Cbh721oyI%16 z8%dk P00000NkvXXu0mjfO?I}r literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/book_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/book_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..20ce652f6287c05c8f83cfee6ed554b68e86f41f GIT binary patch literal 1567 zcmV+)2H^RLP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-ynMp)JR7i=XR!wYNR~7!wegE&-cjnF5mCD8}LPLNmLW&}b zM2e!ck%>FbOvIuB7Jv|{SfGksg-RC)iEc<&uqX-$7IalR8QigKIwMDlgd)lUqE@Lu zVuwm>&zt9YzxTa+S@exHX~&T(j`UXNp6|Q&obQ}>NGXMr*!lD47Zw*6PfIC%0AP#_ zA3b{X@c#Y#dnbvfClPfz9bGB)yb$6!A;g)oESpLx3jl~H(==`0FpLij!}v21?X0h_ z7oVA^)9Jh*gm^iQ<7d+}l|qPAN?8Dy1Q26PHw?qJZJW8S`wzn~-dJB>|I>+xR#sM+ zWm!K@lH|K#80JEVxOxH20#FrzVHhsw+;kl0w^^3`WNT|n9!qrT(k0#Z{a=knqZ?ru z9srQX5gbFvIOmO8t@if8!NCvj-o1O2N`3lptycS4MKUQcDWwOu&nl#-@t zG612JGG>g~0P1<3t1QdL0MKkU>y~AGuiNcz9uZx>eA)Co@14E9y=R0F@%;R}>v`Va z4a4|-p6B;^z24~T*|X--($W{ovivp?EdcmK9LMkV`~B$R#fwg}*?hJrif^T9dSx^k zWtyfr3kwS$Mp1NaFc{>dltQc3T8ZQMcf;W@Fimr=Ua#ND^ZZBse!o~-Tf0yc#g~XE z6haKPx3~XWi9=gmUAxg``)D{EzI*T9z47(y*S{YG!E1+yhf%#=uX~>Noo=_g zr2~MJ@@kSKvI5Y{viw)S-!EFN)^Cy|X=hnhGR81BH#cs#+uumj^!-+=wRL!S_~oJ~ zl%{Fq`~JVLUAy)ifWI)t003#4O2=`o0@%`*mzNhf=Vycv=|o{fWCK8wBu@uH5G$qP zs+RTn`T4pK!YPX4>CtEu5>cU)VnkHab=@&d)11^_2$2dQ&MYr4FR(_Vak?x^ziP%$ zN>&gNs4@U$r7$(aH)-a{Wg(?3%Chu*-#^WiQhqg7J~blL$A+m-O+b$G&491~`1%Yd zCZvX8c&_W#iAYmQG0UkCgH$+qS=26on|ul1<@Lg+0^{ z4h|l2&WDV#r=*mkI=}$n_U+rRFD)%ur%s((0`SjXueUV?^2)h$=jLm*+UJB2@ArDW zw*jElYMrTa22Im+P1AWndA+x7=pmi=I7XXm3%r*kukqN_zwxVo;Vwr&5_b=}wY_V!#UeFr8em>9hFY3DfUKB-Xm3qb)+XkwkIv$Vvp65M?qUaeRL=;8Qx$$^RLWuo|gaN2H zjz>jNTp=Po&+`y~s(dm@k|59XhOX-`+TicV!&7Fm{!l~Tkxw-{qL2ZKR=L<9icZgqGyZhKkJ9ar~x7)3v zC|-`^_$wz|P9EsG{>H|}Mt2t86W6VFyR8E_(Ygg-XJcdIv#(p9wEuU3{2yrzO~_bl R7bgG!002ovPDHLkV1kq9`l0{; literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/calculator_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/calculator_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..3ecee9a146c5a0183183f5a2fe705f9186eefc23 GIT binary patch literal 875 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/convertor_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/convertor_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..ce7cda792c44d19440618ec927ee9f1dd5c02285 GIT binary patch literal 1035 zcmV+m1oZofP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-wg-Jv~R7i=XmQ840MHGggBwu1sTwdFQ+{=gc&yY*IRbJAsb$r+`slax;@Fn;7o}_5gPWXdpx{WJe%n^mjoaOTwYS5MifzN5~mOX^GjC*$zE z`ja}UURI~ovDnRLZsSHk74^8foJf99pN#&1`j&cYY@5~H>i6o^EMOvwJDxdf0v!p+ zym~awR@>a8zNGF?zf~PfL=)mN|Xm0=()c2#iNxfgaxyJ5Q3t3W6sqN}6^{>$T zN5HD;Q>%emvJcDZP{Mv#{W<$^Mtz_L?11{adRRRe-HGUb3sAYYEww;>S;1wsTWwH( zv^WssiE?li@5i!79igvL?MY?Gy|LjUJOVZ@L?SG0H0)TBQOBG0`viAfcXGy z2X@7GC!uO2N3^Ggnl|;2I-tHDU5|RvB2mwW+LP)Xbx!AQi)0>AyDLC@!d*y7DPq@Y8nz*2XG454_vLWYY5$wv1Ps*1aj2>S+kkI?L!q%P&bNfVm(%}O zD!_E2=>Q&zvz8cEfE~awV7VreA>i4JJ(?(10$47#GtpcGrYpd?P}T*!ok_&um%u@a z4d0s;4*^e8Y-$}GPe5N#zf(U~ zw?%(Cj4a2;x)&d6lf`vBANs~D-U@S}vb?gV)6QB{>_x9%c002ovPDHLk FV1lFg;8y?u literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/convertor_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/convertor_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..52e02f59cfb2c1c4703ee573022e30716ae0d73a GIT binary patch literal 1923 zcmV-}2YmR6P)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-z{YgYYR7i=XmR)QV*A>Ul{g}HmyE8kpYg2`WwM_G6YRg+K>^`!-=X^SFNl_E;3RwZqtmZVJ+sjXBa6SMvh6cDBnP;3QJ z1xpB3NW35;>>Yb&*K>F7%)PfSHZm6!vNMk3byCU(t#t|j03j3+Ldu3=+%yd1 zJVNN)@bGZ*xj_R113f~BgPimAQ4|?b6a`AD7yuB)m};#xLI@1QFfGf%>2&&rVHj@> z4-bz$7O1$lrF=?CnIVMu7~?qrFr}2MIpPfFJ3CFoFb2!z@^kfiog;*FHk)m59Ow5VBO{0Z zE2Bc8(9Jo2S!*pF$N5XCR61CxR8oaPVdLh_o1Nu%rfKd_N*xzMyuWwv-m|7@nn{v; z&vjj8+cqVH$RG&H^?Lo4LZQ(85U8!KjVYxLa?Yu3+t-31_(8E)Y_@ItBIkT8pUr)`wbKTiF9p zI-PFgoPUKe#sT2S^z?KRhT%_r-+$8g{YBsRpB6&=c*~Y81OQ-seEe<4aXyOU_@kMb znfLPfym{ipiPvhi+B8Ba3jiR52s!7^*tXsF0Hl;^kK;JS82fm9eEia;O`AL^Wup*c z5dgFhVo^%@1Y?W=02GVGEkO{pXswSmG&DTv`+mJpC~UKB`#mXT$}o%!Atc2)ms;y~ z007+F+}s$)@j3ud2%!l8fQ5yH3S(@-b=@y8#vIpm8x6zw+r-2KFBA%GobwOn=H}9~ zv$I(#<;h~PxZARCJup^G+cjxElNgT&KlgW5m>whYxJ{}qxI=Qkt zJ32acFvk9rBuPG>&#$EbkkeY501zRB%F7QgUAnXg06$qi_w@9%EkSS`$K1B+rdl+xeczkff8<9HczSt+$2A+%Zuv8`IIVuX;w7^iL9j+Pp%5dcht&@2GVW8e30 zQA&LwL{h8OepD`(M;8|tPf|)J5JHDA#-WEa#Lda8|=e@bGu&{H@ znl*p!?(WV30NlBA=XSkbe}OU9ZWuxm0RZ&%^&Jg@;6SBPnF9bY41?wK`KoD}uMH0mUquMP#*G`D>({SW zo0^&o06tE($R2sv7-)%I$wjchji?#gfCAy7+83(e(nzpGR#Uk`$ythJVm zF)N$R#*DEK5klt>LRGExmk>fPQc7nH!}yL6;;TZ4A6Bc?^%!I7dESQ$3k%=Ac=2NL zNDu(Pz`y`eN*xKq@TF?CDufUr#+am1DVq?Y06+nNA%qaAR7x|(W~7u)2q7}2Y069{ z^MPR)Zww6$$(3RXSe!2CZ_WugVe*;yvs89P&7x@4H002ov JPDHLkV1k&zk);3t literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/currency-e-d_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/currency-e-d_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..df74c2e1243f865208f008fb8e7a2e7784ed8a49 GIT binary patch literal 1042 zcmV+t1nv8YP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-wj7da6R7i=XmP=?|RTPH5+@#U8ptK=Ht>Un#MI0y=d=x1( zZ6Q=e>PQ5s1BX&j2RiWqcGOhG3J$8K0TD$xS z!TB#az1%#&4TpQqx_hmEJ@)$7ZcHzKm+VedI3<9GoQEpkm|2u*0z@~uQl>cS} zHUJz0jsVvdwWKcgJf)sdXVh!zm^!TfnfKZ=rB>Dc=rpv~NLW$3)qm7Ebs~VHF?dn^ zMIBVHs^jXV?3<2mWjUZ0wMU&#B&XFKYO}gmeOtXVdsnHQ>M3IaLY;ePcc_33=KsV5TAka{^b_AdssE1}P*2h=s{yXtr9JEe5IVzK5D@mh7G`d89> zAz)SY$$FsH)L~xzKC-uB@ckHXDmk@RJ+JOl--zsRGxP**&-sy-So2a@+M z)yEp7@K9>hp7d4JZHer%#Q~X)Z7MnCJJTQiz^S~?0nNY#;K#bI*aB^bM-Lk#(vg7L9r_sX3|M-5|A{7R`KC-O>WAO}I0ml-l|U*bJ-( z&V`0POBB`6Q6I1?+1L$yQPLmHzBXWOg&Wsw-S<>LI)R?lYz9~tkZ0oPG2lJmIB;8Z zo63e-fbl4|CxQyl3Yh;l0EbeyawNNfNnj7~IPhYk-T(|!)V__P*5jxhYG0adB)_BT zb@gj?llpm%|CIWzdTXf`TT|cP)aNbe3iUM$GVW75YMT$n$Yl!}nTYW+Irgf@)zx)H zU#;#`ze$5X8~MpNd$8O`N0PGI6s!WTQykCMq;wy}QJ<-+;~t4k7Bn_z0}8@|0IMbXm`LusTp-gy^>6jn zy7V=xoAdsm1u;+CfK_zq{*f4b*q3Ktn9jVH0;rEEeBLy|LX$zA8T>(QqP3b(f|Me M07*qoM6N<$f&fYFwg3PC literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/currency-e-d_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/currency-e-d_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..aa2a971feb804c11f49f6af0248874ff054b21a0 GIT binary patch literal 1944 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 JPDHLkV1mUEkdFWW literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/da2_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/da2_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..40d05bff7b502bf5394aff08c95b88fa64779b07 GIT binary patch literal 893 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 IM6N<$g4S=2%m4rY literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/favs2_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/favs2_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..de4fc57104456bdb16282b556e08381c48acb7ef GIT binary patch literal 1465 zcmV;q1xEUbP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-yGf6~2R7i=XmO+RUXB2?n|If@nGuz~!OyVB4hf+^gu=FO| z?qOMLU1htPEIss8s3+;6Xu+0JJQVTJgGCDMMX=D5P-|A>;-ZTXTWl+oJycj!aNEP; z!AvHZ-DLjBKl8sHoC(>u%1R%EWHRr)@4f%MdGiP&!ggfu-n~0UM@M%lrCb02N~!qc@7`@}$DX_hRH;;SM0`(5xnD}TJ4uofBANgIgpf$nG|w=M6~i!=2q8DC)oT3G zph~6kzLfHKx7&SF2%)5uLMaskKxRNFrMh7lmStIVWMt%T!!XWOtJQ1U0v$Yfkea4> zCJe)mgCOWhDZ6O~1ON~bX?m?vdjtS53}b|I&TQNMF^ZzE78e)Qb3v1nle+7=KeXHJ zxgZFd0H9JpUo6Xt5s^euqz(R`0x9Rb=s3>hX0!Rp?c2BeN2w1gJC1WYg)~zCWY7^~ zESJycuOQ+`k|gg+DZ5!9>9-1kpaB4Lg+jptfG;z9n*BI@`0$Jn;%E>A-Y_H+(=;`u z)D=R=b<;G>;rkgc2m((CaddWec4iZ3YHErprA`Dv5W&-8KLa6z7>u#ULWtj`l)o~@ zJVJ;zte4ti5Cjn-o|u}NVtr69m)jSH;hyv;0G`%P%RWjejWL$fb^VWey}rJ*wDg!U z_LpH8d8L##sGDUarR;`bxF?s(?d#V_DRm$WLzPBOEz4>%#sC29v_4>2mQE?{x2~pX zwL+mV8AXv8=$EdPl7?Z(5mALil+xjxe}Cl2k^M@kuWPm1-?BuUTr{g&_hA5cnvnwXfdhZU!%rwagZ(f9pBzVA1a zB$4U!^i0=MLWoZYiH2`xBPWjIo|JO+&Ye5quU3ZK6>fs^fLkgsMTrw&K{kN^09viqDaUcDobypcq=<;mY1?5Q;8UTT^HIlf zs;yS*)S%KPP`zG{2_eTg=jV&XBF}1u!&M$SzN{w2Vv%#s&r?c|)$8?5i^_AClXAH{ z8^`hSZnwK000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-vc}YY;R7i=v*1vB}VHgMS&$+$rEfvyK2a(W)LO2=Xm z3~It+Fk1W#BC!#%Ffxcvm?R<+5(d8`kqC>>A1w8w>K?=UoZNG-_PQXD}uucrheGw;r}*fz?O`#youoXCf`*?EgQ4W~D=`ra3oDCCLKobYM4yYaAD_x@52v5`l3c zFfsqZcUe04CN1sYTP+=YN3}Wl=5Pe(uu6(^UV7#OFP^@zITsjBmDtJUWUI8Zc9)Zi xG`1FXIVnpw_UP=obyFHk^U9xy%JNqi$X_9l)Q)86&O!hH002ovPDHLkV1kNASI7VW literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/iBOOKS_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/iBOOKS_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..cd50a9e254b70074e1c11b7f3e4c215a86a8abdf GIT binary patch literal 1244 zcmV<21S9*2P)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-xR!KxbR7i=Xmc45nR}jEwX7}CQo=$JICo3N&af%eOK_Nx3 zQ7R)RF$P6KGWiGM$^;j769~aoNNrbX3{IUUC!`pR9V||j;xq=E7!gt=#Fcb+(nGgj zv->86_6|w0j*~s`V3v7re$339w}T=A!^pXF=T1yaOiWs90{{Rb>TGUqZajYccx#yR zI0&@3xaf+=XUzO5GoQ)xd|X7z004-XIF8d&NT)oS&rQtEc2(fDO3(4|Y4s9Y|8A4SoZ#+a0u!y*EF znFA>tD5a`e>yqbrKPE}??fv`r?UA7K=g+%A5d5&Svvb)P(*^*06yOLTX|3zN@BiFx zx4&9jTkEIN-M`uQ{qG9MR^fjr2tYq#YmC_ffXicJV=Vyqre~*~GCw~*8^`e#V@&I~ zki$GD#D|2&mvj;#kGczS??G0m00(-@N6-XZj0Ah?uMC8WI%uJ~ds?};2q9~eT z=5W}W3?v~UGlx+WP1S0(3w@Ba_F@!8cJT4zOB6-cT6+-yfTpLXPcZWtW{wLxi3q{o zMR7$0df$Z(g^q_70f5unhls$;F*Bc;o}ND8*6a1jBuN5mZAL^?tyV*&l;nB70{{*Y zy(=Ou5orU!`v718;4dP28vtBp1|kB-abgk4L?mS9x8gWPYi*Y2c@PA_q$?tUh?GS{ zT-U7xLGW9tRC*f6@e9XsJP|pW=XqEzm&dX!Yg%iwQmLfVG;I-4Dk7(?wVRbn#p!mt zPki5hr_UNs`~0`3WL^ zAtD@x;U6NhX06@uJa1}rbo3N6w~6Rq$8p^KkAaJb9Yjn3V8mLRT5C@Oz?+EJ%Cf97 zGBWaYp6CB`yWO9N=o%3vVHn;eqRDEt`cayurvPBf81uqfdn(WKQD#1At<7*x5&-D9 z?RI-ZYu#}i=M83#jWHj0yIq2!m$EDqB05V%!ps&C(RJOk)>;Gro9B6ki0?U$Lq%&K zGiO8w6yXve*?#@g@pwd0EQa30N~-$($ewAt;6!V1LS|0jHh??$4CMI0000000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-wCrLy>R7i=X*3D~NWfTVR-%KWxRIN6es2~a=DmG$8aiO@^ zb|YP>D_yzJoi40@f)w2eq8qbQ@M|H_u5{5w5ky){1wXs+qiKw_G&N3|nb*ZRH*<3{ zQv)8jF!SE`JkNWc^YPwRDa9^r4)@@O{J)BCv9cTI&Mw{`!sEC%Nv85$FUh{aXIRAM zSfot6{X#XC*O?)`9ENJ%M*|z6M-b!5(~oW!#RNMHM!!@}0rc__!WX7e_=T zHA$-Xr}15qtmBay@V3L}S`RO$?-tQxIAEBQ<_Y_vwC~Q}$8&F6@A{0 z8dXvwslcwsgXw%L{!Xwzjqk@nVrz?zpBHj8qiLrEZ{u@O?yGnhzY1B7;b%-Xd|Qb* zkGT%^r!0Lttt8l^_&S~2xpyW{JSi%0lp>Yn``hU-HDY6>`y}oX{qqkl3)v>|7Y^Fq zxOE#O_RN)LT_xjkp7M-f$a zSllP~)d)9h;H^|(IwLtHa`MqAuqzP}5*@U=&#h0z)EH_1MO3%{^#S=W%9BBZ^eOZY P00000NkvXXu0mjfsr9ys literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/java_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/java_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..fbb53d23e0bf38c1e2fc40666529b0c242c7c71b GIT binary patch literal 1505 zcmV<71s?i|P)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-yTS-JgR7i=XR!eLf*A+eYeaM;Na43pWfTo{ClhhU9AVC*` zvaz8cF$^fOMK8N*0(hSwt0Ks%$U0dDDA3QM%UCkh07jBVi)>T_U9@%K8fem>3!|__ z(jHRtX6DU%Hwz6FkyZ@{J-Y#U@0oLdbBLMoBv@TtU0PmVKI6Ub0)P-=bpQVSJ2!9M zJb03LdK^)|-&f51so5oc5k=A8wbmbOZ*TwciHI&2t-8I+H5cwq-mO74T9jqbLY;fleuReI-Sn1 z9zJ|{B~89sszqu&^)y@XJROUAlB> zBhT|U(li~+k${;IMNtsP@ki};`%5Wh4B+mR0#z2Uuo zD^1g4`t~#R6+&yR|EZMvmvin%+6kUqBxFUHpZNt z_GB)Q{Sg+m*3U7sH^%&#h_X6f)nvzn)1Db)&c<>4@-dP3{(>>a<592>LNpo;RhDHp zP16_4vOF8d@zX?<5z%23MWbf3sZNQ7F~)oEF93j8TU%SQ)~;A<^HbD_R;yL?dcEIA zQS`-dIJCpzaHzFjbP3Ni8leo+*l=>%FfY zEohr>Hbl8l59PcgGS@h6vMSwuu{d+-0v z%>Q9#LqyJdpBiHbK#PdJhi^xG20{oWr5ue$qdRJUfB#@(W8=2g`h}t>%IV}WGl+r5RE8`6aco?rkGoFX68nt5ooP%@9*y)sG9kcFbscQ6vd2e zDJ7Ir`|WmnA!HSb!M)-_dRA_$n*TK-g~yz{zWO(;@OWH1E3^H znnH;8_xAS6V?_Y4ySw}G<;$0UlO)O2`qWFM)IA|YRusi6Wm*20nV$g=F!T4Vwa)=? zM6}?X3vslt%*;rVq!)(audiRf{_!;b%pN^>@ZjBUx4Q)3%6L3}V6C-TmThKPwo+9U zGjqwzOhiBQ-j`C!*8q6uoT*7fk|e!Or*myI8ofKy@cB=9zu%YM`}eXe`^983nR6C&#+b8n=42W`LI|a`4r+69 zODXli&d$#6Y55*&x3;#n6o4nPTL3=Y+1dH-c55F0uYvpqs|^c64sZw-00000NkvXX Hu0mjf`M1yK literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/light_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/light_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..ae6e9781d1b1b52302aa18c10e46bbd682903727 GIT binary patch literal 818 zcmV-21I_%2P)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-vtVu*cR7i=X*1wBYR}csA&%66e6D`DFAw>d03V)zrWu>5E z%%+H@Q3$9>k;X~|L;eC4Nm8Y;F_6m2N=+wXWx6D~7Qs%p*dGY8n{`+B9g8!^cfGm$ zeB!|6zISKl`#oo7&dlkglnf{vu@&p%|12J2dJyN~0rcZIj2%HT7P`eCyN^F`6E9Z+ z>h#&sQT%{iSjO`JDh{1k$SMrsFI>X)L5V8-jPJ38`MQ0>w(k5PMsWpa(d|bxjH@^% zhou|fDc)mxp<9YwrkYJ9hxZ!3RSRV^N0)INQ?(r=j9|5#kAFh9BcA7Y5w=~qIF4fm zXL@^2sXSk$lonD-lPRSqwf9u~KABP)t=W&Hl)gzRJx(c2H+&`o>qxOLp&P{=xqRmv zx%eQ$(3)g?iQi*quh%c<>>>7HsS3sCa&@(l-0edGH*hz*fm8emfSlm+zVZh}L?u)CJZ;U~jCjO)kmh7JvmDltZ|ZjNy_NjbO%Wj(s zYi&VG^3WR7>)1`lVSHWtb|eAX-RV{=r_oN@08l$Ya8W5_{sZ?@^cz3ZIH{!&RBWB%Sna5 wz2oJiE+cX-2DxtClDkN&yp5000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-x$Vo&&R7i=Xmd|TkRTRg+=e~F6ci-eqCTTW>>cS?pA-ggN zHl*0nnxxH?E=1iZ2t@@8u0#qI5tr@CO+fbrI|)%Kt#n8hAr!i@5-Ny)KqqgKH}mHG zxbNQUB5&eklBp@4-Mjak^SS4qch5PbwZ>88?Af#Bk&%&8N+}xv7-P*BFJ3%<^5jY5 zDE9O+P_qbI| zP7=WZT_S=`7CGlR%d%40Z1%@648MBt;DH(lnx39EZQK5SXJ_Y{>$(mAl>jsVG7KYa z7)BZZq?DnQG6bM|beLsXrDCyo-*KEz*4EbcuF~wK7K_Di5=euHx(CswY4UtNpW&Qu zGRFP@0Il^z6h)^!&kN!>7PM=iT-R*?xHdF2v<2YH0})-ha%DCMf*-cFwzi2#_d-gg zQk=rG zJnx-)y&f?DC=?3kecwOR58<3=Ip^zxAOKLS)gE%r*Er|7?(Gl}2_ZVZ@1H3Y3g-cU z0f18KqVM~v--%%uDF9CgLAs)~ergy7?_c+QUn!+70syO2DrF(Wgb*U=M$_wqhzkD& z0#Lxe@2fYeKnO8WsZ`3WR4Sd4QrgL5>{Wyi!q-~QoI7_eH;6DfIhod4&m;%kx2Kef zrIfa9+ozb;+D^*Kff6C5jDjF|V`ymTgF&E^Cr`c`hT-YtP4$aTeA{f0gKkuw=XpYi z&o5uT{CfZX+}zv=DdiWQ=Xo#l0|1POnnV-==+6%Tkd#uiTCI{{7`LaUri|{!`1m*@ zqT8)jYg9@p4#{tFRtf<$nd3Om4Z~_($K}6*Hek%;aH%CWD$GYodV`HO15WLmt zbXo%-V2qiDVKke~=5upnW1}%UJG;p_p9;e;8epWOC_$w{SB8P56U#>Pg&Ovn$j+3b5^cvwDn?UYg=qG_%5coJw?DRpQhUCCy%j4}2Q zNQ!E^-F}?U=bw3=x32{C2yxEIah%WA*Vq3BfJ&uuBA3fO#%^x+{juE=l+9+JwcG8- zKvEg%^?F1^cPz_FA7%&uQc81VWMsbkef;?GSt%tyL{|eK%d*mpu{-s8Jp%gr(bcP0 zzjIypL;JU6 z6VVOJvKC9Fl9g0s-R-bRB<(1QTHUqoKIc4FDwQnDvKAR*H&$0y_m{Lm!^y(J!h9UZ zH#?oqnIjG-&rH+2yR@`)XiItNxV5mbU;;SOxCP+R($dnak6Zone+S5a0IuP<;OsEi Q6951J07*qoM6N<$f|d1$fB*mh literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/pin_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/pin_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..1522768084d6a355e05853f99ee6a1d49017a9b3 GIT binary patch literal 846 zcmV-U1F`&xP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-v$Vo&&R7i=X)=!94RU8NK&%5(x#(yM}THByDX%x6lY9rc& zWNj=cDuQtBq6o!ZixS)k5}`tia1rXF$%Ts~Xc-ix7DTl%Xo{iK8b@bti{J0^j?a7F zyz&PR-aY4czTe;fb9!}M8&kI6QEbZZKX4iI;~egfu|JF5cq~b#bMI!7eT(y$!|g7h z-UyGL$J=-U%UDdH=0GnES%V3DjrVY7T%rm`@g|mVqtq|{*ZDo2-mSwFKEMI2j3Vme zB=(80tPFvdQm0WriQN5@x|?tsuPZ`X4IMs$7e#_sBUytVMgEQ(6v=#I94QZ!M9*Qr zK^1k8G;$w)#$R|Rf$vYu`NZ1WC^w;-!bK5+8>@IyW1|S!%lM|)KZry4Q{?Unp2AY& z(JoP4Z6w3hGJ_wmXNUye#anr1F)?>B2;HoqDk-dApB}8mg9*L|zjS#0A-)nhTuE$w z(ec|1s-}@%{x0AXT*V`zIj^=5JdMM6ATj?IDcOcCeQXsKvpjULN{^1>%UrwI;l(UY zU_%pv7>_kUcg6~6h&~$AQ~%)Ju}=#rS#IW4LFBqTXgo} zR01v<(GnFF#0cpk?TKpqt!3}ww0Nn5q)P0C3YWyVnHW;4MKW)tH&^f}-Y9f_6(R2O zWFoOI^+gwdhwX)Bbt+AY9NfegqM>()P@Tk+?k=Lz(6xy@--K(Y1Yps56#xJL07*qoM6N<$f&_Sp>;M1& literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/pin_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/pin_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..75ae6bbf5b2f5fd23543fcf5d18bdf51f4939a6d GIT binary patch literal 1407 zcmV-_1%UdAP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-x`AI}UR7i=XmQ83}RTRh1x$k4eQmHhh zlsX%R;R{g|X{A)8wN3zF+W;A3re#^#Y&Oesx!f<7WnHXRt3MtHbo}^nmdRv3?sPiu z20;)jrNV9m*k?=K?M#}c(zb0bgs?g1-%2SzSXx@r13^cR9yMLpz0_*8%0Un`06^~n z=z(&%9Lwc$e@ZFGgCOVt016>I$8qKxjmCR-@80c6$#z;gjx*PVY#`#k5Jb#mv)Mlo zvFy6;H=gHthzPA#Yopa_l?#Q!+)jfYXl7>SL=;7*gCMAP{SSfw5kV%C88!^#uNyaR zY|hWme>glm{JHD8E@O-ZK~RsP==AjT^od=dVzFpzt2+BSf|rDtdt7-<)X(6hzPXSz&UqDMn->hK58w zpXY@_;Tg~K?wh9h=GCiL|K2O)IF7%wZTn}_G&7w}M{BJo0RYU2iHT7m#37|rv@;qa zLe4n~A(l!y^lMMSEr3_ccyG63MRK@JcR zl~QrNUe7C~zOPg&ll^x}rBXSL<4cW3Lo21^K6M8S5q(6Iuz%fb5z%`8zLfI0cDtQP zk|Z7g!LDzgH5!eFhGF=OF|*G(8HQndo|o9R{rc9{)^C+c<%d$K^v?F3IFA1zqI6Is zj4{(N4Bz+thir9qb)(zrv-Dr%BSbV@*EIp)bR5UAWm!w>>+8iZ3_qz>(nKODVsq*Xw2+$6Jgs zrnOFd-%lHj#;G6(EO_#@Zby^joZoA=+jn}P<>loV5ibZKG5~;D>v(f>^I6~bPc@s( ztu#&5jyxa{k(9Enwce{Q5000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-wXh}ptR7i=X);ow^RS*a8-}mh!F)Nyw#9(EmU?K_@f`z0} zG%-HXsHE^!h|fYTL@dQZ18QM>HJVC%K$;MZRf3=qBpA^Z#7c-U?yfP<-Th2Z%W)oD#`;#=j%zE(3Un}4!G6H! z*oX5=B1Obf&-REo6cLjVaV8?hBjWdnI2IAd>wUb|Cd+pFQh1$3sO#c2Jc=I9_N@=$ zh@`R8njgV1-ovw)=?CqnYB!$1DV(eM25?B`PL}U(eQD_rv=jFi*dzwZ zA z5=z<-5eFjTbVPg`5r<2OZU1wHJxkqIeJZJ){e^AV(VAb0%jzVz;%2;!4Hk}>!qzSR zH_7C87BTMO-g@7GuW(4_s*CUNa8Y%kZ=;iiy?ziIrJ5R}Mory%MvD8*QVbXHx0Lae zthr6*lo>6I3x&P0i#4()8tOU)G$CtgKVFb+Xh@2sCzW*v&frD-BB^c!(NMPnYZmKu zodWz=D(hs;pEkb;hb!omtgRDx9IF<=)GdQ)b2T+13-vkN)v|qG=3_(AF(8X_8n@sb z*?8Nv)vfgtgBUHEF0UY+I{q|X#W(mF$8Z}S!8+{4mj!s0RO7h0Vpp4)!04dl`bXR# zxo-@61-MNnTsh5aEj13x{0v9|G(~$+VUIO*?X$4&X;ILTD%*#bE&Pv-%0{}nZ@ybT zvkv>swf?g$qjA~6_sTroj@@S*v?hF|d%uB@QV z25u}$_DFHe;7{3vPf6viD9j!f{P)2bD;M4 cUl+)K03^Jh`Rj3V;{X5v07*qoM6N<$g1PM7rT_o{ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/pliok2_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/pliok2_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..d93dcc6623749b6fc058edb073529e0a47d8bc2f GIT binary patch literal 1704 zcmV;Z23PrsP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-zB1uF+R7i=XR$XiyR~0_z-np|oyR$RiS*L{;q$sGyQVhH# zSVBtbsz^o<03jrTBISXHlsAO(P$J+3M2iqqw52bl5F}!+7wjmFDl8Pm3W|hC zq!1NQpOBEfJNE4S?wxxN51Dn>R$Hawyv?0^&Ueqf-#O<)B7!HelP6D(9yxMkOlw^S z0AP&y+uPfZ?%ut-^CbTGaX`z<%LWmhky1V{r5smEHHfGL0Dy=Y=e#3?cqoLpg^2I0 ztgPgp7-)HUd0t9+IgaCrG)=XXGSyn=06>f}MnoDBg%F}#E|*!QQn@dLczI=I<&RGU zG&?)XN~O{dk|g&-07zIWrs z4Lux}4S$?IecC9O%dZAOaIw?r^rVytBJP7Q#)NI#J3@$-5MpqJh=?eqj60o95Cp-+ za=HBKsZ*znj|6gE_v+r>-nk$Mb^st@jBx^gyR~n7R<#M_F zl~$|u9U_7|ckaZdY5uuVsnm%G5z#mUX2UvoLm?X(w9LKZGX7l`DeSCbpeCEuV`uh6%_Pu-emORg!HBIvk z!!VvY%-|$RwAOkW0Dw(SPL4_`$EB3%Ae&)}qDX43&jA1|E-t=s^ytx>oby`?3kyG< zn3%w8*RI`HN_{;H!zvM};e$#kQz_;6(ax+?&1s@-nCu(r1LFV1-=gfNOdz&RI)7}e|btkr70&N=@@ zsZ`n_B7Ha}0DysrJ|boSP=&|T*8P5;_xt^CJC5@{0Q?RBAkXu+YPDLEh(4d^d0wm4 za>FowcKi12?CjaI&uXoI8by&p#1uZDITo>f*6ns5an60l*q~*gQcC&0-;d+?`!h2$ zp9KI|Utj+(BA# zLWqZ3TU$Fufqc`ltgmHRw(pFHKt!Om#<{sUvY8_Giz=#>PM9 z=jY$9R4SLEDC!QX#Ih{L7`q8jbcQet->p`w527e~MoJkM8<}Ak9nN`7M8EI#de0_F z(y!HOGnQq&2LQjFpPxU5h+joSP)gmkZTm}EmOYc_c_xIYSeEr548wN;hUQVT*__L= z?AM)6XLkT3gm}MFsn}_nekM)R9uYyQRB~O{eH#(qLd4(ndcCKLIn^PezXw4urj)8Q z8V#phE?-z%Tl>=iAOL{H#l;^5L2$9?;28igM6`%V7T}18CD(QTYMQ3)`~F0hWnnS1 zI3l9fy6-s7(~jf(s?}Of8E5 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/pliok_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/pliok_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..09a395069c87f4762433002b83b98fd12bb62f17 GIT binary patch literal 949 zcmV;m14{gfP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-wFG)l}R7i=X);ow@RTKu`@0^)Tq9Z0T4r(WY0b|fkun-#y z6MRjjHbxtfh=mGTT8M=Pe1H$MGL`s%G!h?GQkg;m5i^2_g)o{p6Jy5A>n3xT#a?Ib znS1X{M%-}V-o4lQ|Fzfp_u9LP2%8)exDC7V|2h1GnawzlZeo2u?#JFF*@_BFN%kYY z#!*~e7bzmv`z9meL_{n`#Knl1jfgW5@kd0Q&EK=RwwSh)>)};HQdi?mJdF_i-%e+B>Rp7c+@*Xg#8b@k|;vQJ&05C$Iw_;yp~`&)i`<_YLt(Vm-3DkTn{^ zaV76fO~w-NRa~3DziolOjpuMS3A>8wsw5v*p$n~sS2i1=b1 zCEXYi$0FjNi1wwD z8e-g0iaTs9DpG$cQ?=3;=wf0|)Yzk_sWEDbTPwLA*OT(Faf{M58fCUIRuX$pjhzY9 zq^`mxrM=840(fZyqF?a}eo<1rqL-O&V(%Q*>#E$zXNs~eY(UaP|BjxduU5|Ano;9C zmi4yXO~V)Q&=p9Uai1cHz1E(sIRD!M?{@;)7}Tn!$T)N@=7!`sVBOS#|hE zul3KjjAoS%{-sifj&ewUPT<{mBJID!-HEZR9E($ly-L)<>-faltKm01i<^_Q3E-|w z$q}U^bn%zcgy$6HZB5J$1}?t05_mSFs?zCFi+meS;2PYCi@7$EK`h}Wyo=`>;C`Y} ze2hnvEDYW|a&A{r X!eEDFcSN#=00000NkvXXu0mjf!+*kd literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/pliok_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/pliok_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..3bfbfa6f3b382a37cb31f459b2bddf66fe4c7a33 GIT binary patch literal 1552 zcmV+r2JiWaP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-yib+I4R7i=XmQ83}*A>Ulx$oWgHBWCeZ{&PzLck%y!G^9} zt?VcyvXEwMDe$7g;#nmEtaHTJPGd+ECZYCQZQ$OR`!l@*yHZuuwK76{sdq zgcn)F8a>UO_c?d&JzeCDIvV^*&+cB{Ilp)A{oivA5)nL(9Y212?9ib@<67$)003hw zx_9s1osEr+oyYOVhk@qj=S?DdO-lKyl=6sDs!l{U001HuhGDcg=Ubff&k*s`g@uLQ z6NBdG=NnSWi)or3%kx}IDRZrL4*-ZU#)wEGBIletj^i-T^Zvy-e{W%7;qQ+Hnx39! zwr&45%d)qG5M3!{T4sPmM6T&#~{vIroAfuw2*uuqcXOt*or*!MJR2 zaq{Fz({Y^lg%IaktyV`$nIYmngfYf_-{0Y!FLBQMM~H}sQp&W|Y6&64dB<_yKXKxO z`9M&$TD{zEw_g`R>;OQ<7&8FCpdZp^K@fzNWnGJ+=u5*e2mtmoDtTH6vD0q1UmqPE zy?kHL>C>lY^E^K%glGW(8is*E5d1R?!_@cvu`morec%6Zd3pJ&*7`fsH19FSI2}BD zL_`omwDLSZ*K9Ut4}c~oCoQe@yF!Qp00kH5GYD9#HXd)s5fPR)FgeZvU-O0&G3jn|b0PubPl{8I{N-6gc5di>{Qr$R? z57%n7vo~(s_&E%jl=Al@BO}Kw%lZ*x?AxL!Sdt{qmTE*PWtwH#QQ!Ap0e}?-0HC#= z%ChW$N)QpVENiD}I^AqG&kloDR#v{>-rhbNhT*hjS=UU{d}>(1S(a(7^%MXAo0ymw zlTsd$Qs(_^1}#Yvsg!zScpm^@b8|Dhe*OBUQtD@M99M`)4gRQwnV6UuV__JM zE2V1XV}$aYfruCYaL&1B7>0E}5CFi`)YS7tbVMno%X`|7p|$QQrE0ZWZJZHNtt>13 zypb^`E0xM_7>1qE(b3OM)BN>=KzHxn-R7KMsn_fOv2D8z01Eymdn#ks%wb0&Ld&vv zwOU=s^Zbv?%gf?H5CDL!tt|q8KQ$VS9ox3g<$3NRqA~m(L&OLXi~e6AqV9IPtlRCr z69mD`!ytW|nVEUH*X#WuNs^Zkkq@3u89QRTySsM`!-yDT{p?UFrJ^Y6rfK?{Q>RY7 z@F);t>~NN4wv;mK$0+wr!!V*Kite!W_4S>y)I0rGj)>Un^}0!tjB?JW9|clMeP!Er zyDV9KF%jq7;hb-+udnZzCHWKAb>A$CV&54NfrvnB4YRYeXc)%ZN~vki`8Ps{->t5$ z?)RQsw{HEr(P(_^dESL2Np}0M#C2W982bdEtPF7+uU0CR%_K=)lv1YUhs-q1mSGqv z5nbOKdIjg)b6s~cj^kB; zfqv9%HfM{X_@LEl?e#&N^KH-b{5;Q}%k#WLL}1%?wOXxyjEEm0;$J(R&QoQdY7x;l zLWpstlvl6U1IKaB-Mo489|u4H0B6pexgvx(Usmt}eo&=LM6!eg&+w25{6;GId_Q&hI$T3DN#zP zOTkd7FfRp!%5$lF=h@7C!3~ezPGrz zxO~5O4;{DW=H^TQc&u>?06tw@Tzv9zYuNtZ0rI~fV+nbobw(Ee0000000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-vpGibPR7i=X*1c{OR}csA-(K#u0o#f!<34R5B2r$0;0B=- zkcv z&iwx~bLQhzbzPfK7V!}l;{9*@g^fv!`xE?M!e{t6NT%c8PLMsvV?4zEIH0N{qKo(e zpWpy*0w^0);mC0u!&5Bd_eqI*xQ(x|i|tasp<5cyU9i}$S-XR=;}d3=FC z%7~_LQ>vsk5>i^X@EyL9QafnTs{&(3DyFHD=$uqt+ha(w?jG*pzEp+H)R$!2fqAYZ zTGFVJ4zf9^m&TElG7M}zspHS!wNW%(o^~I~u{i?7VVirFIUUqsII`iXZUG9k|_-BmH zpDo{Rg;Phe)0g^YCp^kg9Z0GA#i+V+d4Dfe-;X#IQ4Zt(oWp~)7ucIsUDu2FO`Q01CJo93qcd%iRDrb|*hlu!9eita4`{B5Dm;aMjb9~;SjF}Hqiym1DlNX3EkIq8 z*T^X;>MwOHzI|K?Z$2Z^CUoRl)ad6QkY j9%(O*iHJ&huM6aVuBFz&6>0kR00000NkvXXu0mjfmQroi literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/plus_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/plus_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..c6b685a82b51f882db32df279109a74aeaf12c8c GIT binary patch literal 1290 zcmV+l1@-!gP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-xgh@m}R7i=XR?ll2M-={Mc1NpKq>*;*l$_FI2&A`Qd*`43tsghC-Xlv3J|LkT@5^w3M7?WIt9h#l;PkhC!lIfz^v2s!5xkS$p&c~`sh zF z0WB{tyF|30l=@I9bC640{ zhQpy%N)4^G8o=lR2x|@JbwImFO+Ukxn8e-pMz}W_KP4i=@?^-Mmo7eHj1Jx0GAq##x{U&-ePp&!iA59 z!{N`{+uJ)u14SUmaagHTssVsfYM`~Y)AWdl&CJX+JkR@VZEfvO0N?=7Y&J{Q+N)6% zr6bR$M91-cf45eveO0T~u2iel4r5GA(PIE8ilUT=t~Q&^(jHK?T0NU2$tk5&d_Yb( z=Ul&h`SSOB_wM~cL_;Ft(-awFOeqy7Nph-Mt)ATjveqspNn)p6nzV8J`0?toW5+yW z%zr+TBuT8bb`b#h{QUf^QtG5qYFJ=HM1*}lj4{TDh)p|3US~P0p;GGP{QUf^8;0SD zG))6*tu97Q2m#OY%6OA6;ro7~wMHDr@O|G0PyyhKoJ-SmsP&uXV6D~0m>>v(6D|=2 zd0Qz~u2ZR0hMwnrT`HB@)>@uBsb9T%wHrl|bzS$%TCL^*u$*&it*yGQd!yIuH2|1G zWIO=DSREB}K}7b+lP7=o`~Ch~hm2u;eZ4jL|H8t;b-d2InLKkDV_n8r3gAeAl}Xdo zJ$?H0kIiN?%`ZEi=M8$j-gl)^DLZ%W+>I>DLI4`CJBX{4s^-57KCu))*X?vVFQk-R z&iQ*pq(+ppEOWKi3jp}*+>>w|XDbZD>y1W(X|0=a9KR1BMP56`m|XySMa(&O9mnZ* zyWJPO)oN|!t-efe`U}gGxofTM8)F96+P<}Rmx#bQhcRYgjOiD@Q7CpIA|XUs2=Tnt zYHjfx`GN2IQ;Tm>9LKT7n8VZ@eBbAs^9RUdkHKK@$oKtcLWoL%)my?Cvr!bOcDt=G z{z}IrXH)Tg|Jh(Lc(ez!v9Xac#%@X}y`1_qBPPqTBjs}W*Tu!f-?Y{t05wIA05B<~ z$2q^bv9XZ>6K((E#fv{gQS|viW5RKq3IJxUjfrTodlL~sN;xZ~ynXlX-Muj}R!2KK zJJ*6Bm<4btilS|d4?YF}TI;Y_UZfeHZWhv$DFbw4= zXT`iR#!zfkqjModB@9C;rM%5Kzr4A*Iku?myPPa7Eq$W3z7ogrsY5O&&s^8NwYs{x zHqG9F>(lT2AtE;Q;zHUv*|6L&e1=KFNJ|z2@%K!iX07*qoM6N<$f|i_@% literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/range_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/range_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..337622f93e66ff74cdf25e6ec4e1913a057fca47 GIT binary patch literal 1014 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 JPDHLkV1jZkD&YVC literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/sim_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Other/sim_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..5ca72831cc7a8e7bb94a1dd561a626fc361f516e GIT binary patch literal 1044 zcmV+v1nc{WP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-wj!8s8R7i=nmc36LM;OMRd3Wd7U5;JugEEqv7$K1+1-c>< zU=j<(2JWo;2a+g~mC9{oxr(B+RB4c$&Lww{45aLk~1n&$610{qQ zD5WHTvki=hOwPGwSr$2t^E2msvr?&iHxg)db(JP2CcX^A@FU;%PlXUc;(%Qxpc4Vk zx#PNS%C_xqq9}U2x3{N;f)*DS%}gfqb+_An;QM|HfEorE0wmXUv!3T|w_2^w4h{~^ zkJ7xj*z>$E5=bM_9|;1SJ668$Hvl}Co}O+3`21gv*4NkX4F-d!jYgx(7^6|03~{D% zxtwQN*2lZMyWgLKmY0`Pj^q5$Y&LIm&P6Jf`a^52{zLOh4r7c*Q8X!~H1qlVul;`i z!~OmJQxgEv>GYj`zdsK^OifMwWLehZAPBV9dMsClVW?Cp#SO#QY`5DBK@iNR)9E_^ z_Dld!O5F{^P!SOaaJ0R>{rhXUIj^OqrQe9?y)X=wZQFMN>`|dm$O|Fngb;&d9lr?# z02pH?07xkZLWsFSp^&F+Hai=~aYiX6$GvISvlx_8GLGX+CX<;Zt#u}emC-_PywZtw zhW-cfD~lLoZN^xHzmM!qI%A1;n_8{bv0)f(A~KW5E8YY_YYieY4Z~=++wEhj*XxZW z>Mbc{0N{SPTz>0@oEQL1)3i9}NA-HWK>$ER&u!Z#DP`2{cHcfdJ$+U#mv6l;#W0L1 zt+ldkn~3N+kc4Wl*LyiRIr%CGg4)h-PxLx+=MvA8Cs zd=v!1{D{NJE7LSLtJUhaSLt0lZWW6~6TnF07JwJkYIXc^>z{Sg0rF3~=l5s(y{oqX O0000000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-v&PhZ;R7i=X)=y|$RTKvB-^5AM5{r~3ZVKu~p+zbbM8SpN zN+Y5L!AcQzqYJ@BUAPrDr3mgKMG(7G7i~d^?!@ZCg;xAmcjCebH4PC;nmSGMxw!Y4 zm+54jGzTujn|IFly>rfY?!BEPMzk3mz`pvtgkP~ZN^p0C_p^8$_g9k1`tF}f_A@@m zJl3`X>I})~2;Rg4xPfaGs0rxQ57~v=@B>cb?5IRzco(mrhn2Q}pKm*O3KMuA$FV+) zsEZHroKlwc0pMF%>PPOw$9P$*lw*C)@8GD?;O&s8zUwviXvNxi*~;i?e1v72OR}r3 zRYd>|Xs7z6?}M7>y?7qy+C&rhQjzaU3uHHb!*_TXcU7|6>+gip$7=(~rWE-8r zJeA~Xl7+hdOtPBf+a%M~XMd8flUz!2JjvlC&nCH$o5-#9(yozt|2%f1KreeuKuO&H? zeZLJ7${ZcTC8bIz1G{WvK6-dT zDbbVodm998TdKI-ioHCBi}gjLz$?{h4R7OaMTO(a+-$YRE5>f6NB1c`TEfL{P4yQX zt{FAMx`M~>1^#mLb~VV>m7d(ANPJJlUTm_M$BV6iHrW*J9f72=DE)3W*?ER}4vw2{qDNIDhkWX0Z8_j5Rf=~lq4kf<1^DkcUWe5aLz@3LDv_@*FP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-x^hrcPR7i=XmQiRNMHt7wncLaB-MgFXZW6(QqEHQLeNtNA zN?WZV*E=rNhoXpBM2a93eX3G?5Ph@lg9uuvqF4kmcP2SGTia_YB2*BfkrH3Tm%Q}u z_OjXA*}b`)&zIdaDNTCO?`4;rng8$mX21F7BZvsY*q%LmM#sj+#+6bQ005=bxq0*E z()H`tTf?j;TY;vgrZhx+MoRg#l=6`%ibfDI4FEt02~(+5n=y8SG4>-N48wOCjfUD3v~S-&&9bbIS5{VzxUSm)0JRxl z6CmZB+l4}5y3^^re(l<|wXM|FPc9S+@5PW-tiR^S-FUG>%5~iq036w|V@DeRPA20t zc`296#UKcdxvtwzL=h2Fsg$nkI;WKCc*_70N&Ljyd9LfWgCICoDwT>Gwr>Ca{dzW= z{l3*|JuId42_Xa#(KJoNG|j(Lsnmi}>PgS@?hC^(Gz=q42nhi|55ur8r3?XpB#|Q` zGRDl&(b2zpz20QA+3afo0J&W5fbaXerIg(`5@3wk`F#EcA>_Gwz1}Vsi#sjL`Wz7- zB!qmRY1&Uw6g?0{(OaJ9J*t$7q9_{l`+biP0#Zs}2(det%N+oKh6VtjlsY7YPyhhB zuIEhCOfkk5HBI|!W@e@h08p>jmn)UZ7p7^BUAS=Jqj*OaN~O|2mSr7_qUcvdd`bvW zTv=HO0RV*%DwD|^0)PhDyLay>=ln~@amG#4r1^aQXTvbQo12^aMhJlb0231v_u967 zm=LnB-EN<5G#bBcmK5c3`CZ3xUh{o_l~Sr(mbK)%?n|0&+v8yvS^%J>)9D-adi}-Z z|CY<;@oY9bX<61zA;e6t*ZX#1VZq-j`=pdrUDuEMzE6}=gD8qD%d*BbM6{B!f{6VD zQYw|kbGh6bK@fa;_3G6>9mk2b0wiV_#xi5Qaw*7XcQaKq#(em>0 zGF3`#Do!bdbUKZ@cI{%W>%J_ddEVCxo2goTn47wkf;;0sw?_o~D$ZX*QevH4p&6?CfmaFpTq@^O5*0{TCP_ zB5=+}48u4-Gc!|92I%@(-EQ|(p-`xD&c_gu-gX7tm4Jwpb3Rrm6sp~B_tg6F4WRk? z`2iv1IOqJFZQGnNX0Ba8TLX|WX4HtvN~JUy3{LpIzkA5$ zWKq+!v$a}n_D*_Rwp*1-MFW7L+ARRMRIAmt-)`M*|F?ns7a*D9{+MwfrvLx|07*qo IM6N<$f^{*I%>V!Z literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/3dmax_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/3dmax_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..d43184570cfda51663ea748ac891b2c6648338c4 GIT binary patch literal 1037 zcmV+o1oHcdP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-wheL%U zBH2xOSKSEJl|>XmS3yTI3PL(iU3gL5L=05cRR;}{pt1}CJ2E=WXfvkcDaWUa{eJvk z!}K@OhQ!<=Y0ULnhz+_Xu@!!nr z-_w9z;AP-`;AAI9-N5U>9h9`x%2lKl>27>G3H${dj_v^P7H~I>R8FtaGr)RaH1oNU zqre0(4*Zezy^&#HAMgZl9t9lh^KD~0ey!zJ^@zGBa!B2#Zd6yO3)HTL{&d-@j;q7j ze?(nZuh*&T1wN+0cM>=qcpi8(=UEA?237#)01LCHO4=qU@L!lz3e2Ox{~F+U?PzWC zIv#}`z#8BpN^!3R_5fc1Kcs#qqI&_bDrx(Zg3uZy{i*j*9ros=YFIt2Zpil`%Xmp$ z)FEv>>OJbHIubj>vAJ0Vbx{389ZPQasms*?^>=lrIwuAP)F;)?)lb!T)qB}IP z0~W;L%IN*d3>?}`LE153eoini;qHyWiyQhMMV0_p0r9HC8Bb%w?(U>60h ztwb~*I3M^C_$5)Sns&h36Tu|#8>JR?2Ks0dZ!5NURTRqjjzTpi%Bv{=*q-RN01pFK zC7L1NP2h0~TQ35>it#11S$=M8kJWv!HvKcK?pJrHE%kDBw>p)6I+67;+vA}6q1vx5 zR)0=g)IGVj69t_?p`T3@RNewyN}-v))NT~`3HXM>Bml2c2=xHdD5%-p>l&mwl9NBC zp4)*DQ0J+u)wdH}M^dfFbHIJ6TSbBH1h6|rA5Y74liJ30G zHz-87j{^5r4ENCPDdMn3TV4E$_QiJ>jf-!ltGop~%YR?x(1tOTn$%bM135%{;|z}K zQ9n+WC$dhDlZpb0Q+k{-+uLtDcfPbc%2FCxz00000NkvXX Hu0mjf76jQ_ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/3dmax_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/3dmax_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..f755cb8b42af62ff32c514c22fb13c5b9ae238ff GIT binary patch literal 1764 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/AIR_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/AIR_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..22f793d0391438fe07456721afb99686b51b5c08 GIT binary patch literal 939 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 b4v_x=$s;Pr#TU4l00000NkvXXu0mjf$o3y& literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/Ai_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/Ai_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..3568d538fdf9dc6c21a38b3f1fefc0b3e0d0030a GIT binary patch literal 898 zcmV-|1AY97P)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-v{7FPXR7i=X*3E02RTKvB-@NH0QCnk;0a2{DG%dOjaUs~H z7K#-Gs|%|LZd~a`{1Zf|Ah>a(J9VWXMB9~BD%FLhV$O~>uiyff$1&bD#{MBZi~|{DD)-hi*mw983%EMU zQD>VQJ%(3sFE;U4I;sYpJjgUAa1O8G!*K&OIF1*vfwi{&fNtCP22A2@yo}y_V$AK*DHD4PN0*Kt%y@J@nA-Co)rO<(=Z){P#;`&iA>)gbl%ZvGAY zZ7Xbhlsx^>(%*}x@KHO^Bu**xT^qPbHT+$HqKljLb1;dMx&K7!hmx}kcnBLJLPQ*n zh|3YN6cIlSd@B)gCL-n{;`)f#7ZHmQ@oRn;(}##S84;^#x0F5)N5sE5I%I$)t=mlF z>%@K?KjJK|Q)qu<=HwvmNLZ`%(ziyb`2DzIc=7|EWe%Rs-#*WE&C{z&N$k;QS|@$( z$6SMXg_4^?f=nnhKaJZn2Q|)rXEEO>?3gkfx@j!p7o|fS#6Dca z_i5K;u*-RiHY&Z;**jQAZHZJmo$LD*XdcMDGkK8E@0la(u2Je{-L=Kr$=_?BH}f_p za(&8hxCi~OW3^GBSyA%QmM)g?O|ECK8#m?pEBu^#qon3|u~BGyUZHDcQKj`+rP}B5 z1-`_`3WUq}Rv*4WiS&6M%N4E#TcPXZX%=#QpVAFBaF;Ths@;UbK(2+dsXl5FPbl-G z-GctaoeHHNS6H>FFzI>RhFg_dc_weZJ9TOcI+wn;G}R+`Prs>3!)`jek|*q?lPUdq zHIs+Clz~Pz)hch`Mg4ccu;v;@)3`dD!&`W%ZVVfI?<#}uH~($$-J%S>XKge1uHsmp zW=4T1THi3|?XfVEw#N)SRK|In+@suVyT?hRP<=;_leTp6i1D6VpV&Ggb`+>B|LXzy Y4>CqY2OFH6v;Y7A07*qoM6N<$g1i@`761SM literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/Ai_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/Ai_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..e1d9a1e77de6ccf65c83b37eae4d8227a639b9d7 GIT binary patch literal 1484 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 Ueoz&)=Kufz07*qoM6N<$f`MCjTL1t6 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/Autocad_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/Autocad_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..d14c52da3d5ada859448802a8c57ffe2ca25e3fb GIT binary patch literal 897 zcmV-{1AhF8P)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-v`$@9K%Pm8fx$wo=&ev2{uSW=PEd7x ztqjfMZ9FE@(%>|H!W#DAZmg!EdX$tO;sZRPPGu>jo{OcFQ7PrOoaag@N2~p7N-5u# zQvS^SQ@z>hjS_1UyQw^S2nTg6YCT@9Wd6m=f)M?PYMtf8dbr(a4Q616@+SZv_6(Hm-M4WJR|BhhrjWQ zI446v?|QV#S7oGQL7oM1b3EG$PHKGbh{m^^-t9;a*LC%p)FRr(w@Wm>$5oAQQY)Xs ztD=>!=`Pht2Bx+0=k%_$Sso{M=&qt^kCO)9yUfQ)J+_InGRt%8GhJ#g+fY6J*8}oD XBA-CiIvrtY00000NkvXXu0mjfqJ^iv literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/Autocad_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/Autocad_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..d938802ff3e2124d34ea6d382c4c1febd431cc17 GIT binary patch literal 1524 zcmV000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-yZb?KzR7i=XR!wLeM;88GbyrV!Pj`=IJQG3=yV#e(M)`pS zN8p1|aD;@`mgMX1vcwPwyWk{bFU#VSaeRyk?82@O%jOyq$#$r3R>3A2Yl46+a2 zHQ0tYmNZgj)PL1gm4kbPG%Fd0)TxSk@B3c8pL&msF?gPJ^ytxMtJP|2t?K~580$TG z^5pKVTenu9N1vWWG&eVA8)M#-Ql5}f9#%>nFve5>fQT~7ver1~E1dIx6VX@m^Yg_| zCYqa@`?Zwvy*Q3vPSaH9d7c_$3IGEIVvO0GbJulU=KKD)obyZb^YdRk7t!S8B&$>^ z7m_4-O9+t{MIjku6#xW4X|3adE&!MkfOGCgQRH}@_s=ZL{&M5S4ZSbX@#DwsdcFR) z&CSizLWp(CvRD{~-#dwma;^X9fI z?VZB4TJ3yEvRYahIgazMPN#Do0H&sAlP9Nl5sij?m0V`F1YDdk})Wjg#CBGR^P z3jlch`0-Yr=SL47JotM6*x1sCkY!ntG4=xh+`oTc6-9B*^Ss{z_)VIo z-vhw)>({@tZTnIX1i@a$me@UeeSQ6I6h%G8*bBxOIV6==DwPBP9zA-r1z=$>YgblQ zK54hxvuT?CD$BC|AgLH*wq;qpUaxo8US3{aot~av;hevkWm!HDA|f)zNTrknfJ284 zv1YT`48t&VUDq|n_(U{v=gys*_wL=xrl+URhhg|xp63jJHpakl9G7#xvb?;!%1Y)h zJwdB`F+9&> zjIl3)vS9oD{@0%8-R7Kc*8~v}V=R66@ZnZ@w&FN$2qCx-!U!SqwY9Z%rPLp%rlwi| zu(`Q;(f9p3j4_9E?t7khyWj7By-l>Vw3HLkM^O}2@U(RpB4Pmg4<0Wf=ot!Z55b#y(nFTFQZ;el#;Pb5RKKwh&^K zh%DdtMWs^tA7d;kilPz6aVX`kd@;rtSeE4z5eJ}^Qb`zwBT*DxzH;TtcAMDMk2W?o z&eiMnCV000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-v)Ja4^R7i=X*3FBRbrc8i&%JYJMzflH87wFwh#)5n72LR( zg%M@+wwfs@6Doot$VL4PAti`zT-a<<+msb(iy(raWfo}>(bh_1pc>7|xlfC89-iku z-g~=K2Ogfc^YT02bI$koYZXOdM486D*qHCX;X7O$#ke!V|2=pJ_hpdD{C72jeTz?U z8rKFnY7NQgNxXskv4X$SQEAZ1g{;9CzQ&vQVAMcuyp0#JjHSAML$_|c4ih+v{pb!0 z)WJKL6R>pqI3FZME^;H@!#*`A+YRLdm=^_JO%SQuP22hORsF1G^f*ppQ3c6b0Y@3I zi!1oM=Dc5KEv&~=I8_fcfzL(zE~R1{-{VJIP6yN2fm`wCzXV$++J6?yWuQj|u8TFp zwW77ZY&f|Mhwxwq8w78WS4|B_J4?(x+U-Bb4vw%H+}0Q z95Vv@(s}bfD+)X#=IWQ!{~e!Vd+MFS3z$;Xa|Y8LY!NNFG5`Yj89(80zCVIH1slAI zhjBKueFhsc&`SE=(h)dLHlQn|%;Cup-_E4NXB)n{`M$n6M}uS+o)+D9 z7O#jFFYPDsK8^|4uH(G6=(MY@A6}}WK96_t5pKqZ_(HTWY{uQVq?eZ3>3gw_^MY>1 zhGbMiaTjjL=ekXy8e%HQ$5QWnM^MH&(K*Zd&&5}wbr(dz$5a18BlEg#A!hL$E|zee z)*renc|VB9L>)Ha2<}la`;uPBN@=I>p%gTR&+vn2({bF6ow!5L(yys=6LzOgVF(4m z6F8xlRBu$ZaG@H)<^0ykAS;3?>JauN)lv@PWz{)gHQPkF7=mq%sAjM4#M||}bCl!O k8NEZhsz7!5UkAv407VY#F^q!a%m4rY07*qoM6N<$g7=w=d;kCd literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/Br_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/Br_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..7815eb5c517faefc27743c41d6a125a9b6515cdb GIT binary patch literal 1425 zcmV;C1#bF@P)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-y3rR#lR7i=XR!eAHRT%#MbMDE#b7wsBNCu@r7b4a|ePOME z3L(MN!6a>_vGMPyx zo%`sSdyWh5q?1XeqQv1l1%#*|X8DW&#AQPgjYu>pXHLeBY$5aPNJ;x{6?R4SEP4^31o7AKTa zr##PlHV6W(lnS)gEdXr?VvJcr2*+_8=DO}RA;h^-sWiVMqC%m-Y}@|K_x5;EgARXjRVq+MxzSgNG6k60dRUtMu!d^8V`ct zyOoudRU$F~z!*z#&igu|)=?A%T5Ht~q(^ep-`}6HZTrOB+}y$j(a6Y1Uox5ewOXw{ z9ruK6+h(a$>L%y>HUN)^V2tV4TEFOd-lLx9-R(tYj4?t8cVJ-PX0zFR+2?wNb~_fxm><9Iy#ygA0K}+iXt0;z7Jt+09mUW zyqgOE#>U2mCMG6!1wpVF1i`gTCi7t;k(eeT1^|UZ!4^XNxW2yritqa?09xoejf{xu zL=<*!06_ab2_fF~eg7xNaemHZGLOv9&o6M!mpJDx0C3Lpp65NewzgK&TAR%f6auKT zTCH}2b6#hR^~^4cA{~ZdOKbf^8yrB5F~&Q}tUAsT0RUsn;+)s(_4*CAw6s)>rQR`H zrJMkuudnZ~Y&JUs;Dec&nSb`}+b4+V`6!Bl7|?Xu$HYbm;RqqFFD)%qt=RBlB9VA2 z48zWx5k-*?0JF2R=K-7tfMdswr}JZ9Bww7;y+>8DnT2fIypHx z9){tDs1gx4=P4o*9o1-y>OCTA_aFrzYPDK-+of-ds^d5(W@l&bi)wovK79C#Mx*gw z`f z$;HLRO_J7gIGLK7nryXNr##QwyTjq+Z_BdImCNP1?eHErZcR;1Spar4ZUMMdE|(vE f-0EKccYypC2WZ(Kpx8-s00000NkvXXu0mjfmQtH% literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/Dw_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/Dw_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..987db6f2affbf070535775683a5b5662b0df5437 GIT binary patch literal 917 zcmV;G18V$000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-w4@pEpR7i=X*3YX|RTKyC&pq$H_tK}CsT4L!C#8}FNkx_w zlx72K;xi{1LeoGn!T&&_z=0qQ`T<2hCO(X`QP3cY27*$Gq!T9&%&xEU=Y99x25ar^ zd5`;^*V=G6=j^lg_q+C5-?h$ebh}*xjum(q%kup)&fwA@i<<*{--<0*mn5V4?Pikw zf^TsQQ*!||=GoC}*oXD#;6?(K1&ws%E)3x$4&cb3L>1o0TeyX*b^BSi^~GZt!3Wrb z>G_D7_z2@7EYp3!=NjE~av8qFn`)t~W*NVW9U{SZLLzOabM21A>V2&3XdAvjE4}L% zra_2{-BP@ci8|2;z8CVnip6Q%$@{Pf!`}lEc16z4U=wZ?d2bf#x{{y=@e}?O;eAlZ z{3RjlsoRh>(&6=q{dLLFRy~yriDZ5wBzqDcV>{kXM@G!7!Qot2c3a*%iLDY9zZTbP zUY4Rfir+-;mf#b7CTi-B8qx2$gCVqW5tE`k)?!74HA0e|J|P%Q@5iw}=O(ZV&j{g6 z;%V%~efSDb;5Zf}_L@qlW7Nz7D?6JO`M83oa&8hUg^VxaT<-2?A(j&voySBzN3nEv z9nCfBO6%hJd_I@JcjFpP;j9qPLrH|lQ7b3W@4YNM67>Jj|xG#AHZ%r znIYMPoeA=SkbWzHAH|QNn?Ek{v>>rBm2e%ag|3^ssPHL16oPpt-`YJw81Bl^BN$Nj-FBG(}$< z7j5Og{P>oOUb)LWKfWovfkQ&tV+l~Me&FRA%Qc4*W5z*cki*F%VrTOmPD=6K(cz>% rhVin&j$6k?&ianq5!J{4IzavdtIPoRjLd5u00000NkvXXu0mjf&NH)z literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/Dw_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/Dw_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..ce088ba38377d1d6a58425be25e5eeef66908de9 GIT binary patch literal 1534 zcmV000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-ycu7P-R7i=XR!xi)MHGHj-PKjyGgI@kJLsOogKkKG00(~J z>V!p+h_lQh-jx$_fy4wO1~1059E=`F@S?_eaF$s|2pGt6VFg1pVhBn!Bpytdou6iV zrn;-Uo(Fo!U;vl+l1{qvs@_-ie!lkzBEm{!^XARt<#Kt_7*hlQpporM|j3FWi03d{fmSrt5#;!BQz9)p7tJmxCV*}03&c3R( zKHTs3*D0lp)>;{3VgMK(Ae2&@F(!l%)bqSw7-Prl_4>Cf0@}4}7v-FPI2a7x^nE|l zTKCfzkOvvS)Bt15lTtda>wXr7;d^J!oG}jts#Gd=u~_`1*X!-|eZLI==3xL20i;sO zQa+#mrrmBIym;~AJy+VJoAden2PsG^wZ9?|fO{`CzVEjHU~i#NSOS1|hk82vnVFf{ zt(4mD`~FgTLxPAf@~tF22_Xc0-(ONn?XOm=yYDFw5w>sN?qo8V?^>s;i2ZO=dY&JU$0B0xwfH7vLQpx}T z*tTs0z&DLX<7}(d`b8;qte?RXeB%81^GlB7{Ovf-AI)a7n;<^ZwwR|Gawj>fF_Cc%isSg1BuS#- zIZ6oW5JEzDK+57>0U<<&bN*ZE&M~d^HbMv`gj|c`_{xS28@5kQPP&AUg*$id{N=jt zR1`%y0Kn9Chql}88=5o1mp-}kKw(XBo-Hsp#o~~3XlY_zFhg-L9 z-Qb+RJTWoxRIk@Nd+E}pWkj6PS|^lJ+p?@qr_;GX7Z(>>Db%Uj4)#supdOZk&IFre|&}cNS-Mo3T8;0SOWm)S_pFVwM)kYsDB7 zjIryBi;FD^06-}{D})%v3zH-%?%TJ|I(6#Q*Yor9pXYM9!pzLfp(u(@_`Yw2VW^BT z&mBB?(3_f?TG#LQC*nBXbmYhpv1-+-ZBZ0GX^e?o*QJ!wvj7jEAOIM6p64^hx`>z{ zqGybGLTjB@N-ZZz5)(p*5W+Z)(?vv~l*-z+9W%x{h?oh2z@?OmQ3|@(CaTry?l25b zE-fu}2_ZHi#7Yyyqzx|_VRS@9N(ixsB`{ngq5*(pY;3F`gxKF`G@1Y->^(m}-*jE~ zq?B?D5w$T!A)-RWh!8UDOT)}0DY62mqkl?HC3-R`kb{e3_S3kxwJf;xIH}cY)i{n1_xt^|D;!R)*|vRrZfOV07*qoM6N<$g29W-5C8xG literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/Excel_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/Excel_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..50fbb0c4e5ac271d08989e00debf55331ba9dcd6 GIT binary patch literal 974 zcmV;<12O!GP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-wNJ&INR7i=X)=6kyRTKyCU%m`A#8#715nNT=v=xgk+^Gvu zG!kuHXhqbDQW5FG33p0Saj4c+i@H$}oE9pAZFg311Q8V5f*^_zt#pVrW@?h}xVYz; zm#<&aPrPt=@7;Iq|IFu}u87d#T7z|1o!`fC7)Luf+|$ATVO)ocQ^<<^HxT!>hgb0sn#&35 z!E3k$f1^M5$7|N~Cq?qir2>&kuEx8#Tg{cNG1`eOIEioYZGzs2mFUGGe4fD9;)0s6 zrji_6a10MF*d9^QO%X8_5x+&mv55FOB6{=R)`*ykh$9iPF83}^-Xr;}Xf&Tw5wWSl zuUyxMPnGnoVlsp`l~}s?8f!6%hm~5nA^-oXl*&+IRRWv&J=k#isx(@KC-EcB!Hy*O3^(JA zRN_DieH_0iAz74(4JD{E`ChG+cptCi_sIm>h&yxdKBdp?!Ii1h32aT}RwU*O#(I=W zKaTU#)b0fS5SOM4n>E^jKa$?Uc08&i#~rD_`6-|`u@ChqE#n|AOE*-p+GXKNs9ZX$ zWZZtG|4k^@#Ll$hW!$9{{$DBlAdXh<+FNs7q*dKY538t8>3!GW1^lig(gEC#ukdub zcs#KhiM?bCYHcaip~(b(M~TM+>7KRe>RCLIe2ZF8{hHXM)XP{})vkXv(sl4Ne!}w> zI>tQ~VmgT1Qi0R%qnA?4Y7S^;S*1j;QafGvLMh<;m0B9YZnbNo-NpAhZdLA+<`TkM zh4w4%A5S6gDQW)i#n)P}b4u3iR*H1MLX|HyT!a#nS*6JLB*vmarIX?0lC*5O;iQ4@ w{m0>?zIt)J&c>~MX;s^GCPDS}zXr&E0L2@!J+WSnQ2+n{07*qoM6N<$f?wd%%m4rY literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/Excel_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/Excel_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..aa8539dc14c6e2e4042a4b438701bdd892a90562 GIT binary patch literal 1681 zcmV;C25$L@P)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-z3rR#lR7i=XR$Yi3SrtC#*1h#NUAMaCCj@-lhcOuOZ891m z%&N04GdwPlMb1kLJwbms73>1(MLK$PO>$=4E{eLmWUTrp;7Y+opu&_WV zr7!n-y|2b`Tu3Qj8ZDmTC2Vt0|10`J|2eQUmiSo@U3gtuI-1C z4x@%)_@hpzb27`aF6aE8j^n(owRX$0e6rK&RBYR}gCO`fW9;urDN_{1=ephQVXd|5 z-&n_Sd>;T#R;$$(0K7P`O$IMZOG^uRo}cb^yDei3FvhB_R_n(b8yhcro_D@ltwx-4 z;kxd(FI>3r14LZ2ENe<@JscuLM2O?KmFM~CTCKJ)0yH-_XKSs`#BnV8ArWbse&W!f zLq7umSX*2BLl}lveBb}g>gwvv`T6;P5c2bGx9b^WMsfiF2mmIIV_}RrGdDM9?*mmT zmB+IzJK9e?A|j+|+R3u)simc*MF4=^-QDN!-o5)80D$Yd-|Kd}9~VOO21PQ0goskg zUY2D?E0xOQ`#I8D&u3XS5`w;0Ib-aHi;IifTU%SV0RU>X+86UYeA5Y;5eeN~t0Ug10E8PlaLl^2Ef%9pCrK;8p`6h}cF%G5BGO0nhU) zzVENCudlxe0C4^K^>}l0^Giypqsz<7PxsHhljpgklzPP&^O?!X$?sPxl{RDSdEfWn zC4@NrR0#lR~uO`t5&OS5CmUVN=0=2)XQe-XLE_DP^T;YNcsfrfFIxNmAx{Zo97gw&!_u#@H`y+rDSp zb`=rd+S%FphEnPumSvsG^ZbdTC=vhw&+`Z&3QBZW6U2+b3`Ysujm_B^?@N1M(H;&_VDW$EoHnwg1p66{RNwNtrv?gk` z+JX?`jaIAGK}7Sxs_9oFVT_G=o(GQO+_7!@KSGFKxUO4xp7&%N$ES97c9_;$PfScy zUDrLmwzhV01PB0Nd3pIKaU6d=j^q2ojW>e!z5)_LsBPQKbzNYL-B3zhE{fvWBuOI9 zdBiz?eRXwpe@%?+qfV!DE{dW_05}=PaSPt>^bxS3O9MoQT$%Tk767;w&iM=5=7YinzS zs63LK)a&(HS(Y#KdcC6uBq!UH(pOhjR@NWt)Q8cndc95o;6QW>0Isa8tbBC3^+EZ6 b3FLnP5|3D4CGBhJ00000NkvXXu0mjfH_Ik1 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/Fl_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/Fl_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..9c061cdbb2903697a6a765e2d15bf1357ee4dec8 GIT binary patch literal 832 zcmV-G1Hb%000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-vx=BPqR7i=X*3XJuRS*X7U*GOzj2#U_CT?^ixG@^VC&*4r zAgCLSAZQSM0A2V7f(Y&c;zoBGK^zbgXDQ?b6chJCf)F)kOfs2dy356>+jF|px2K~8 zXL0YT`s&ob@0?ylSW=GQX&lb)Kk+NBEn_@bV*eyw!n5gQCHJ<|*)RA3=dsfT)LRhI ztN0MlV}v^i)Ee~iAP=FBpYSohTh>v7Pw^h^;#RFcqgxvfu^*q~eT)}58sH1OuB2r= z2fRxn4|y2pa7LBNW=8oFoK_0F$Vpee$7y>yu_jVS^fJE2^$Ms_($O%N0j>9 z%+t4eJ*?sltk;hA<42`^Z>3^S>8#%?W9j4|*6H<%AR_vy*RB^M;_rxfBEP?hh#Qsd)x^4;*poRrX{Jjm*~(~+Wtz6} zWJWejoqmVyII+JUC=>ro1z1b_y^3#B_g-~?S-n}?t;9ak;Hc7)qmEOxMh`2sIf#8q z9rog{QDPq*?;!-cg$74&GF{bgvm3C-&-ITqnWqVWax@0$y9fb|M31Znl+_ z%!_KI%*$CEQu6+k66IdfB=+?IE-Q5NScfA@O^&C|jxwxU9lEvj6Z>+bP{t)3&|Tb6 zrvE1XQBqm6#XP%6%uBe|a@~3N^B%jMxH$(b(kb2dP?Ok`f!$EkEYISI`1RZI$i7dOd-ow#_9Nm z>D0CJvzhyC>RO$(#9E&i%(?i!R4%?h{I`p5O}Y5qw&3F1!CQ7`W@wjcx;m>}!?Zb@ z7*h?h%;V%aC9*}2lLkL~z{g1~`*6Z?&#eolJMV!U)$+d{kpBWru`zS-{fi|40000< KMNUMnLSTZT293S| literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/Fl_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/Fl_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..2cbedfc97f0ac2b7c1b266fa0c38cd00e80aeb47 GIT binary patch literal 1314 zcmV+-1>O3IP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-xoJmAMR7i=XR!xW$M-+aqx~jWpdbVa~cJ`2yhd{){u%2Wg zh^%HE(Oq}ei;zo*5RfDXuOWB}A(sR^c6N5ZF{T6nz!>X1fByXG{rmTu zd$Gq?0j;jCaw1w(N`0u5I-s?lAtDC=01;!$vRXojCqjrn5b7P9?DX_>3jn@+DWfxI&YX^- z=*L#8)kVb214Bf643I&@ZQHgBh-fLLf+R_jG%z9}oSB)Kb{yyY`uh6y9iWAU1>5ty z-SiE_=s1q^cdOM};hd{`_wMN|oocnZVB7Z3-EQ}K zqtW=cTCJW#L=FIPYKuy#a4;AgEEEdI0HDDE0E{sw27|#!mtk@@O}SSuh*+?ZEfw-S}V&M+iW|+7~_^@ zbvm8SQ?|Le*-WY4rI)Fk(y)k#LSsx|jOi1Rg0%gI^+pU|JX%)>@nmyzv&mBA8@XJL zjS0#C06cp1Xe(O}`_fwX)3t^%lFQ{7W9$Y%N~-;S|CZ-@kAol>rl7lqmaU743D(Bo1LP!8G z+uPe)T5FS)j4_6`ZBM17+E0>Xr<@t7x~_Zv+O=!fM}PnTR#sNN^?m=-?3*B>ofnxt zPJ$s8*!4|NwkM^mNGY#ey?S-$n;5y5Znt}>SS;41l(R&{0Duq?h8SRk3bL~_C?Fyx zrJOAmi}h}|dudpA1ZZPpBSFLqQpzjka#;!?@{|fpknCItkuR6aQc8J+F?L~NV`GFi zCJraHT5UN=l8a#&9^B(_@|bged2MZNeVo5nj$5@_jRU}*#w`H2xwf|U=Hu3G`M(3? Yf4s<;lnb%OSpWb407*qoM6N<$g8Qp%zyJUM literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/Flash_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/Flash_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..90b5432b5a39c5e29e44f1eea46ce994fb25ab26 GIT binary patch literal 865 zcmV-n1D^beP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-v+et)0R7i=X)=!MxQxpgA&wKM`raGl*bZnFa3(?YUtXL2m z)B+*cVPk=X#)6HNM52FmRgs9Om5?SRlF}6tOPh+;j)W9RRjE#?n8LMdfmwYF*Blv4i8xr?QgN1AWViDvMsP*UTT zQMMHaakw>pgSe}bZApk}rgq)^LR|}END4ONTf9+?-zt>$HFhLHC$aV<_A1d{EtQP0 zX&f@RX|Y4YwF%hfamjNz7fC?_#Hj_>~P# zvl+*PYZ{;n@B6;TsI}+>R2__$9LKPJ?FHopV-^laWu?|2+S|> z;{@}ES`X)iJGNMVsz&Ms?^WaXif~xKzqk<>hv0V;`+QGa@Ht#p5!K3>$H(}p8hb&= z_MhCyl7XyiYg~T1D-?4ISG5SP#&+Sdm#XnQai6%Ci%GUTgrp?qDV%NY=(x3cZ&oD6 z$3=|P@_k*z(_A1e`C|a}DXLPs; zNAW!V+Taw8fMyeOnf3MPFkTd?{$2cpyM)TNV9kMN8!h3_(+#@k7{l&2d-QmQs5O30DKSo2Vs000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-x?MXyIR7i=XR!wMJRTMtwzIW&S%)IyJ&7^{gP#0PY?ZQos zP%ViXLKE{-$x=blQe3reij;y_)Rk1kpG8#!p&K< z+?jcQ_su;nI#Z`qON?;Ru}*pBVnx36c%jvc#{Qa%6xW2|!L&Yc@q zuU=ice0|#{9_rFd#l>PVZy3fqv$M1F_Zao{^<|V&$Al0u+`a70K!AuK zm&POhm`}`uZ{e06G9bE|=>Mf?$u7vf8CxKtzGv?2V!*LqrK8qLeZS!*EY7m+J?B^9%q$DK!v=q1p_f(=5y4 zjIpn7-MW>wTJ;0~oGq8j1Lbnrj^h~NzvmBO7%HXI0002%?d|Q6Qtp;gMq9DbG|e;& zx5i5uo13(rY zWJLgg*=$xJ;!kbo;NakXMEoF0l7^;fGELK`(lo7aQXgBjD|)$HzTvuVg)#OR5y=iB zKt$lWZjWVIQ|Hc|yK?XAbp3F(T74ys;~F9&5hX+vZ+uLQFei?#c0nr6oHyq`VKd+X-Sn-g<$b8GEBAmWKeqoKoH!QJv+EX!hyu?2vZGSut! zOWAC8rO{|Sn$(8|zf4X}Ug=C69Uc8x2(dqo}9 zI4q?Uj^q5uIsZc`^+KAaF9ktR41z#xq3mrk;JR*)>$+!VW@bKY2lUQU)oS%*p-|`% zLW~O`-eZjMX0zFpQU*lSX3|xr0D!r!Tl73{vQnv>?2O+xu%%Kd)imvh<2c{hwyjGk z<2a555v8p=c>si3#yPhOg@Wt4?it3|k;|7a-zRBZmy@xvvDecyJsJeTo^38CE3M^Z zcC&h0u3KYcV>$qAYuy5X3)9onkG^hgwEw$6{tMq5x!tC1vw;8r002ovPDHLkV1gV4 BjV}NI literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/Fw_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/Fw_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..e2e77f99c604fbee9c8b7431b743531e24a24247 GIT binary patch literal 899 zcmV-}1AP36P)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-v{YgYYR7i=X)=OxdRTKyC-%KY>LmF*OqaYO&RJ2xu6(9I2 zB52LVy0WfXH*Q?njT;wkRnS#7f>`Lnx>68gMKHJ(@!b|w>I)xG+o)|#GkHuG=UnH@ z_;otb1D8AB+f zbRnQdpNJmAvzWv(&LvP$Xrv<>unwQ&1-vz=p(b9&Q)uICb$`#^s`4n-<5ld(NJ)*#CF(UV_r0$-?>Mm9ydK8Cn3L_#7)o>dk zjY}7Cpp)yH@dVzk8d{GJ1%2E25He$o*&JBFQT7kWP|*fp1)9K?Yd zfP>hL(-$#RqMuCccZ#7Yt64IX^Ub(JoS8PR5_E3hOh!2-Nc2}mI+prp@_VWnn!rt% z*Uf#Ici}~GhSuR{ye3HWAU0tZzoqA6_y9lRF5HmV6D@2Ll&s79LXJPuPy^2=@L}8| z&dl+i@9*$_VvJ*3Q`BU*Cv`;*;dVTbDHux639|f}-osIG_I|>3BJJ~uy}9=s^~xN+ zNsqr5HMuX>j*GT4j4k*C-{zj3xTNZQE5R19u_mg$cn*Jxw2cTRH4=0l*Wg-whL2M3 zeo=~MV$ZcIAzxl&XcSx1iE@^%#`QRoQQe9if&{ba%nn@woy5_mXcz$PPjNTy6m*^yHQk!~M-ux)snLwpeeYb(3;r$3qE03H$xPp-jQCzrx6)*1 zsBb}w_&8I#J=3sQG1L^D;l1?up#+}AFM^?0CgwjasM=I_;|<-Wx*;R`yC>R?$o*LU zKAq8(4slkb`Z6_5wa6=YTK65WmTRIoL3EpGJX03xF1`ce;``lyyZE+L-;rp|O?ta_*n@;JFgMAq+d(!>|m_&BM`5FRnubL(BJ*|{b|Rry~J Z$nz$C{QhSUa>4)r002ovPDHLkV1h_*p-cb( literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/Fw_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/Fw_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..ca85a2ca4f167d6e62fa9361dc0f7b8c32c75fc1 GIT binary patch literal 1523 zcmV000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-yZAnByR7i=XR$XiqRTMt=&b>3UondBo+ZxgM7eNB4LV{ue zO#@Z3D1?^ai*J&c5MRU>jToMc(FY%RGBG5Y_@HmJ{AgP+l9t3Y#9)*nU?>VjRQj{K zv&`@PIX<{s+rl;_o@6qa+f|`3NGyQewk~4Q=i1?W?rb1poj_X?b#T^77fU zXQ!5Oo-78`+uO?!@kJrT3qpw1N~u;vv;Y7IA*o>))132*obzu9A*cHK`s6(W_4fAe z5JK#aqUgyaNwg3m(OOFYXdEDvQpP#AZQG_TEiLCc=ZE_G`c5nfs8lLZ%d$R*%=b5=&?(;NF-y0kp)J=i9y1H1QQ23-;t?mwjUKwf!1~;Y+7a zpUxNnfa|(jqbTagvaI4bPM$IL)xf~OmkSe=N~KRJr8}gQw;MnW(hI&xmSs^K#~rTg zZUulr1^}S7-WJF4>@6XL@Ot7kgpl=0smw5pOeyscrPSt}6RmZKh>|hp0szxm*AP)N z#vB0PTI(>5V`ba+HUJo8ot>R+p69I=LL_r)PXGWo=iRq&-~KpF(+U6>rfJ@EUH1z@ z2u;(pO9wbH zBVtA=tx!s(;GXHvj-A zrI$G8O8pkc@pUPsLc~n~0G4I_ zZdumYrAwF0wQJY5GRA(&<#JcAUArbJrJJRc%Mfw4?~D*qCWNE_;4EZSDwST%vh3|F z%c`bnk{}3d$8kCcA!N^EP%rtWEX<_ll$dP^L38 zGnWm+C{s$=LfunJwS-~#KoA7WYqi?_aU3h9)WhA~-7AtLxfle&_m1N{#Ta{TY;0^I zilQ?sR;;k4l;)OafZ$N)gpADv~HYgyLj6DLlL z4-F0dETw!lNs^~;-nJvh!=Xo{Dvc5w^JBp&MN-4{A-7}o?Ka(VRzFMs=r{kVwf+YNGUZ8!*BrrrIa;9M8=p)2w_U8P$?x_TU+zCZSOsH?AU*z+K64dc6}HG z!Rw7N0nO)KGmS$;1mE}DJkL9P^ytyqF){Bys#Gcmec$i%eZRfF*3?kc=hZxH0HD6_ zxBI@|SE*DE&Rv`bG(0>k2_gGD&pTW!7Cp{+3)Z6IP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-v@kvBMR7i=X);)+^RTKyC-^@<-BNL6A%@%4Y63mJzM6eJP zM2!(qK`;tI1(ASSC=y#cQ9-d-3qd0`Y9We&jg|qyN+fEMQX4Ul$YRWz&1N#s;+)I8 zoxGjQ>Ve0+dH068WlWjJEtt#yf8rF*jAPsxV|^d?;?{IBm1`H%*)RA8 zOXzI`)Ebe|V|WdFa2cx!R18`f$TTK!9B<;waUHes4xYyvR_gjgx^?3&Ch-AYL4TB^ z4i4i9QI>uK_(oD?kaPGP&#INOJ*50L_KOYPj1#HbPuu;8HCU`=^awt~az;0Stqow8 zaA8CcRj$qANqkjzG>K!PeOJ=SU-;Sjtb3x(cZ&wuNGh>sr*JpcN_#&bx@$S3nZj>) zya8k{zQ{l}l2!)1C$WzdNBazQNiCDDsoWMVerHC!J#EhCZx>rqXEkm6iG8FaO0nR| zx|jEPe2AGetnj0lo9(za*S^EAxCwU{?BxRHJEGomM%R2b9beAOX7Fl${}gwLkyydk zVoWZj{v39+#|Z^cD#`~@8i96@)GXHKef_LVfJcV*AkreL+#ty z{PuJ@JtoSwfI~Rf1k@3ob`jeevg+e{G3nESl6I!e4m_8RDm;W6@P|PowG(@}jgx|I zCN{`w5;tR)*w5Mg{}OWp%(|>yn>H8n*`a|{ zi@b{$4DJD&IVMWB1e+}4<+9Lp@O><%{H*_W@a+`i@Qe`$Ur!9;qTsP^0+go-ygc2s zSxk&|7nN}?C%1{rMqN(Y_{kW_(0l*@ N002ovPDHLkV1gkNm0SP- literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/Fx_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/Fx_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..d33792ad675861cecd01469062940f23cf25704e GIT binary patch literal 1462 zcmV;n1xfmeP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-yFiAu~R7i=XR!wMJRTMt=Z{C~tChyIgnV@b}Obc}*w9P`O z{jr_?B$<>3#YLe7X>ns$f=F;7)@?=5Mb&O9?wmAC$!W-^oa zd*8dq&6_lxOiGGp`R+O2cYfae?jeW>yRicY4wME52ZxkW4gdh9w7I&v`fz1srM{bZ z@-(9H@o|obZ%QeTNh$XxNm4{a4FG@;5;Dftgb;rUAr=TB^VMoKerBTa@$oZK$}67d zy&438l2QgrsTcsd0fbV@g%G-~>(nre`$C9o)oOKiS48DQu7 zq0wl(x3sjh*-F0E*|zOZQj+@9s_18_uS#Rj=JWYA0QhiQMWdsmr-LB)c5Q8~1pr70 zVU$t>9?zufFA*^SfSr;+L?p#xF|TRb#hICzA2*2(A3mHhO>?eZufHOt^eCmwG|e_+ z>;VAKEm_A(sgmb;d!&@fP6Z<(3L%VAsq~lYx~J~kxf5{!fLtzj#Phs;Qp#4^1&wq5 zXklUDd@o43Ts|tLyctDNJ06}W$f2)K*SIc14Q(bB#}Z0-F4l`TCH};w(Xyb z#iHl?{)M@@xeqi=lK{ZdPQ^)*IF92CQABi7S=lBLgb-4%*Z(Diyk(l^Sg}|4`v`TWNK0F=_NHBI|!X=%wD9UZ;o`~J}=iu|-Wm|{D;7rdA2-o1Mv0Q}nhaPs8I zwN9tA!8w0tWMpJ^W@hFtA!ONg-92#}zu)O}I{kn+A*4wN2?49I@+PxAa#ct9@qw$b2)})kftF9|! zuIs+kY&KtRG#Y!_?RFjjK-cvRDdjgQ8flpi zD)pNVJ#$j&FB>YQ0;N=Jnx?Jm`pwzd*_DZjiHURP&b_^`uuvC5e4fkYjP7uR5V{cJ z&*kOiI!&2xXS3O@3IL3;7y!WceU}h|-3mG9nqe3Zu3o)52>=j9(M2icB>;fw>FMuv zU7ycnG6o_-Hk+lC(%S$#OAxm#YgN;<`6Nklp68wLJWl`sa?UdY0|US5y1o*}@pC~C zoB{xr&1Qe%oc|q$;ZUd3c^whiRtee^)sc~r(_t8HiYjA_Gsbd=sFEb)|eix zLqr7Iwo8^}UB7kf*5)%ow*s_Utx4OqtCnRArf1ksp;O`PO#lIa+O|Dt+jh0pYE5oE ze1d3kaWN)@T(&IhdZAFTgb)U%wvFv^b=Z9t3Wb7YS=Mz*>E*@6#U~_f$K|9_sf@&N ze8uy;eY;#v{@|Qno0^)M>4*2!b*oaTZ~)lVx&;99Q&UsVzHar}|6L&e1F|R%!y07d QdH?_b07*qoM6N<$g7r+OzW@LL literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/IC_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/IC_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..717f0331a7106a525845dbc94de33da8b2b01627 GIT binary patch literal 819 zcmV-31I+x1P)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-vtw}^dR7i=X)<29@RS*X7-@ETE3$94`vo>}lmal(Vhw*HZEauuI$-c)`T*k^;K!Z6M zy^Qzq99Hpn0yPeU3}hpQ_y!;1Vqc;PAL9+&$GF_z+FLp=VFS+MT};v&i%hJm^7Q=bo*2 z6_-k)4fs;XciaNIo>3meQ)Yq~2ocCknll;X`jU|ULELXjcSxwKBx!&?z}xsiD6Ga~ zndu}m9TudG?>I3JF*~CpS}G|VmhyX;Bv0TwyoTqoPxRT(S((zNiESi0eh>cAUH|g8 zC47OS_%kEkfnTwy73?4}_h5O1-9nP99VDdJR!g1*iSUJ#{fg8M3? zt+5LSlCah>g36(K6rX!^s6H-gJuafH#29KO!2>ah%1g0xs5W*QZ<)OV)^klLh?a2% z?=%Zt7vHDi;=AL&U3@#l#dp%2i*H4U;taNkI@iTt7kGIlThjN0)I4NxbFY5Q)x*|l;Y5zu4+W&e${sSt8-=I;@G+O`w002ovPDHLkV1ihde7FDr literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/IC_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/IC_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..6e38d1483739678f5bd605d5d2a5a4a976e8741f GIT binary patch literal 1350 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/LR_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/LR_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..8167f2fc8360f24a54e342120bb0067a99c9dd12 GIT binary patch literal 830 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 T(_pm_00000NkvXXu0mjfy>THF literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/Office2010_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/Office2010_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..a50e50501b9f5ac326513420ef3cbeaadb51b814 GIT binary patch literal 762 zcmV000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-vbV)=(R7i=v*1Kv|K@Mc!^i^0W2)M z6(SaD6>WR~8=oNvc0#Z*r50j9h=QQlh^^wK(q5xP(HPC;Y>Qc&jK_F5x!{6zB`+_Y&ye*>t8Y|g~4}sAg{f+SH zjdX91^iCILSq??Yb_HN1@A>$y{)@=}LV(Xl|6;Z;&1`NFcyDmF9=U&wLlIRcb<}zt zELR#;(Z0r1wMUcwKKItcYJvU#kDxi}((3Vd;jM7G-wwIN2|)tli_JhL=|O sILWOGCv^7QdSI!DS4@=KnjVn90WGY~G^o$H@c;k-07*qoM6N<$f}x&Lwg3PC literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/Office2010_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/Office2010_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..657570e41ffb54e13f6ec9772dcc3dbae8aaf231 GIT binary patch literal 1224 zcmV;(1ULJMP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-xLPUx{JC@PGw0k?p6BDt9033z;!zL;2U5yiDdn$-__SKBW@iSitgL+DoV(NMbgo!y zy>rfb?=t`>9v~43Ddot>$Ox56r9Y*V531GbFGGPA78WRqqVLi){n8lIbRl~O+(9UXnMv9aM#1kKLQiX=(CKRi6VX^g1@fIkUv0+6)Ul{k)ns@LmZ zZEbD!Ln#I?$8r2^53=90KNJL@@3A+=>;u5fv9YlO0QkDlQ?a>mGO@8`*+@0`mA>@Xry5vqZ2;T1XOtaEN^W@hGss8lMG*4l)K zf;f)u*G4L=*rZ5K#d@=DjyW6fyG%03o$}Jc^<*0H|rLo8@vj6+)B{v4n_84}t&yL^KWnwm1t!Y#^fTcDsr9ex8|s^xj{3 z`SRr@W;OuuP7nN^bM7xGrOESrw%hH#tCadT3`1$H4Vl>>V$95kh*)CgHW9s#hz$T} zhJA-1=-_ZJrzccqk{SZj@QZkRgi_pn~s`D1!!W)8!!ET!Dt-rnA)UOb;D zr3ew>tm`yUN)Zt~0q7NMyWM`Kl-iL}mWsCjHp0v-r7S6>cG~Usvp%R+t923azScT| zV}*Af4gjFmIwGR`wOXy)2LS-AudhE=Nv5&jqqViQ$Ay9hZ#A3E zdvP3Bwbm2NOlJvWuQ!s`dLoYFYO~qAH>iINw7I#NA>wVV^}|Y~qKllJ1}yYa%2K6L z(OT<=M09&|bMv)9<;3A+d3kv$%d$J2PG@?^;bcb$@nCgzb^T5DP93+FmzM000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-wEJ;K`R7i=X*3E02RTKvB-%P$t(;Cw>1iR=$Txcr_BDj(+ zTLU5i@q;e>Ky;x9y74~{q@uV8g>G~ub)%x7?$lM6Qmb`i-AGb39g^CHBx5qy#W`>1 z?R1ikdf_tj-h1wI&Uwzc=iEjq#eic5_hLG~Tlg8vgB%_nV1EwBabGGK%e~E1_9MQ= zm)P0~sIiMj^LP^vU>h3=R2^ufA-7=&=kPW@9aK>h@8Tu2u~wJwk*yz|z$i}R4Rm%> zG>i}Ml%S>42Yjbd(#UCijOW#;Z1xDB#MAf_d$1pOq+BQ0rZAZX)U9l!%yMF!+{vTI zaRw`bg3m>uC-DOI=Gr;z!wKB3hoV&8NQ0iiXR%s}Qp#v4OQn>hJhxc;znYk%rIhQ`9TVBLrW=zzH7no2V*WlXQoMz4YH=9r z3B_7s9#h+x+kpZ}({Cc1?h-K@!6!-cnWXdk#2Cpbzvn7NGdO~E{WI)@h|dC+5@aJi zT*9w7n;w3I^SGFD>xn%xjKd-&w|f*+N*_wgPUDogFWYzveT6{$$!=c=(vUYEcy79zb zu1e5jq7bg=)~tO=)wML>swhoWp#MmVhw*!^O{8a4Voiwx{Y9l{6yJ#sTD67VJJk}G zbtvb>WMeu#znW(zQqhFyz(>)p5}+-b)>t0}@?a;uTgBz{_+ZjpCDgcXe8v*9&CUJj zJ-nj(4yY^b*A^Ngv$kscMO2#wynbD{PviSg@Os&QYkUVpyq~j6pF07*qoM6N<$f)~raD*ylh literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/One-Note_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/One-Note_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..6de98ea2801e2c0133e82bf2d8715bbccc5507ef GIT binary patch literal 1604 zcmV-K2D|x*P)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-yzDYzuR7i=XR$Yi)R~7!&K4+hwd+zKr=gyr;ipB>+ItfIi zBFRVs!xSxnXfn4CQ3M|pEXAkRH<9>Kr1)YB79Wg1h%Z9Lnap&Cu_+xUNFD+jYNH_! zRv%2PW^(V%nR|ZsJ$w1!xzn35DN|f<;K1JN`}SIUuWv14X6(mKoH)^*o}QjH#zX)h zgy`M7cklM~>({sU<4+$()ai6=X8wZK`tw@rV^vj6F|!K*L{wOobze$(OG^0`5nWkY zS{i<2qE4stMXmJ+Aat^t4m zfQ5wx#~AZs9LEI!wr$%ZqNSCUmDkqS*I)KLZ#4*l8Dq@a%F4=X8yg!xa2%(QQZ`11 zty9N!gdE3l!OSl%EG#&?M9pUN=`72RYpv7Kg%FWHI$~LtKXM%BZ;s=<)ai6Sd+^{v zM=8~fqUiUnR;vnv0Jd$r%q*B0Lpm6Y;(-EMc@7;`$$^ZNk)BBgv_S=L)Z2rx5@F~h2=q9}@HZDx*YS$U*HBuS!$ z5YHVxeE3(hv$H>A=7UF$9PyGQ(SyO@$uvzr76ic&t@R&0&&zjqcK%RR)f2{;s(yhk zfXIFn__&p2nKJWJM~@!utgWrR4xoGT&H*UmQ>xq89AC+a$Z_m!e3VgTfMp5y!e8@6r#No##(Fc^G> zna$+n9I_`WZM z5N`sts162$w}T+KnIy@RwK||~52F?V03|c~Wm$Gd;KrD3Aw)|E@kszXs0DzTA*F2i zzJGHt7`%ZS<;$0M+k_Z@ z&;5S?Vi<-?N~!5uAjg6C7BttVAJ*wI%uGtD=`akJ`u+aJ@y!nrZEbB0iRgKy)TLId zrKFS%t__c|(Ylnf(Q37nQtFZr;`yzut%oG-vBSyY;^LQv!{G~QnjYWhaB|bO?N^tV zmscN!_o3s~;^LwWU|-`FfGf+(%O8E*+H3#s0Qn!l1U-tPv5|}b0000000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-wbxA})R7i=XmRpFHRTPGw|C`^LA!kULM!e|4$}H_*MNpzc z-I-IC1(jV@P(dJw9SEYEh>8faE+PmzT!dgzQBXz@B^|twC@T%ZGKe|UIE|+nXU4{- zi@m;??Z^MuA1&B?`?TJ7@BOWJ?Oju8(RzX9Ku@$sfggd9R-EfCjQ0cA0T%~JM~qDc z*$==+z=yzJ&46nEu%nxSM}U>UDd0o^l@7I7NGH$+>;;|y-ffkr0Gz zolrMaiQ3iOG4Y7HBLm&4o>GU@Rnga{js?jP^$YbD^(u9<`g0I{71*;x>tkRbzV}D} z$^aaW-M$n3XQFo4RVn*?qksr?t=3Fegl zWX#zJyaZfM(%5F;EK)jJ2D}O^Aql(#SV)B6fr<{s)yJ}*dyd)_^`+|etc|)@y+(ah z-CNPw0d+$?&TfFVw|dBCkvjsZUbOJi&l*k32zC;LdDJWWcDABV%vDBYy1 zqQ6427`PKy3k;9~;#c64SoHkB9;pg;P(74ofNFV9U87#0zM$?>pH(l+=4=U}mf~OE zC$H{km??^=8(N!npya?jpPR8eQdWz*gYCSmk&HEVpJ?`Gd@*w5CL*m5-B4nLDy(kCOuUj{o>L$!#96 pj@F)AJ4r{^(Eg1mxBvBk{2R0Zd=Vf%@0S1o002ovPDHLkV1i9C&IkYi literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/Outlook_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/Outlook_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..0d2f77d0603d635962ac31eda78b7b17967e7fa6 GIT binary patch literal 1797 zcmV+g2m1JlP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-ze@R3^R7i=XmVayY` zlMwP-gwTAYQVHKPs8lNDf*?5Uy6#@j^H>lBlye>eKz{+k7>k4uMNt&2Y1$GYe|&0c>IG30zl9Jw)o!<) z*t0$a0RV5e+fB~-q-mNh0C?tqJSr3lSxV`PtyarPrBXyy)yHeK+8+S`ipAp5APD~1 zXf*x?0Fck;Uv9NpBfjr<0RTi%R1`&#F~&g{hJ;e;nWm{Jit^cdz1{!-zyJUvBO?-H z?CXx>_=FIZ5c0b|tC=eYtpi; z?^>4SxULI~vC|_XBho$4z`($$=Xra2y`D=55jp3t#}{J{rSyqrv)Qz5+hB}+4FI6k zYF!ru;VnYQfUfIrGRD3k%kp2!INnhh zhHuB;`#jH+IOkEX*IV~}f5)LihX$@(x#9u9iX=(ND2iSY1YucGlph~HeE9v7lasp} zjmDxN2)_@4Kw*qc007|O;o)=;1iOPEpeQzsasQG8{R2k`0me9Dj79O70sxqE?lu~Y zx5F@eecQHe4M~zd1pt6CZiivm3&U{t@bGXNr&6h1Q50E>u`u=m3xcpC7Qd=#T2~MR zSy2>IlB7RhzI@pm8yg$abv>C#Bsz&i;xU8}+_`h-Y`filYI=J5M-vkh1Dx}NVHkF! zD6%Ze+J!miR-9Hi06?4pK8X;*jYi{+EX&^?8XCf;X)Xc44*&ox%X&-@gkS2q{&88B zZ=5)B;?&lyTL(Gkf6eFfI}}CviRXDAjH1YowJp5q^&$je7*gN&KT;}{o(2G@R;#}d z1mP2_tE-RJ>-E3qa=GoIC}x(ImuF^XX5O5hp8lrmx@C;<2TaraimIx=b{uDXeSN*# z4?6&Wh!C<7LOuW_`d%@{Tu~H1IyE)*Ro8WA>h=0R00533KYm!(^(QH%KU`Q?SnrF> z&d#m?zzP8TA(zW_5JJzy4;aPTHad9lU^qkdNM;`%z zBZ45f0PtbP*lMTKIWs#uySy-v%;Np%2twNj~UI*+ljvCPGb7q4;7H`SXslpmv%{>HX# zFP%;silTg`R;x8OfdBvsg~D^4PUnlR>$<9{N|Ge~D~h5wVo?MDoH0f*#u5Ms8zBgx zfOGz#_4V~_s;VXp!+7ER`SbV6#HM=WIL>!W(;VWQmmJ4gMF^RKAdK`O_X}s=IOm9S z9_YG0U>HWlw(W0k+Q>Ugd8t$q7-MH#*L~7)oL(4)Zh!8B7ytmGC~C=MQqnZ-SA>vf z&z(CLZJhML=A>9G=EE>N?YizBN+}D1fX4aoLCwhxQ52uAR;%^<>Ah>aRV)@o0C=c& n3jpS;)#`h1x87<0Zv*)sw?Axz<-_U^00000NkvXXu0mjf@B2uW literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/Power-Point_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/Power-Point_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..0e6cf8e2aef75291c84f90db397bb66bfbe46636 GIT binary patch literal 903 zcmV;219<$2P)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-w0ZBwbR7i=X)<0-pRTKyC&+p}zq?#gx8nJ_e6bBozAVNEc zA_!_xL=mf71#xll&!AfeaS%}_7abII&`D8HK?f~r+=^l=2rf!QO-m}JF-gtuI-K*& z&F}Y;{-g&U@7??E{hmMfobS24Qi?HU4%cH(j?dsnERD0dKgR#VxC=L=lIi@nmdbv> zr}!BEYzNfa!K3@}EDm4;s|nO@=%pdMFoEyzBHkZYQG-|TIM#8#UO%+9-aLaTypE?a z*hx_zZ{mmu%b){%J1J@89=wM~RiPX{qnGe7{>+UtA~dx%J)54E%8*_fwv-sB@l=;b z_u*YEC%`UzjuWX+0u698ZtYN}8qeYpd=RsxD5Xr5QWi=nXG0J_J4{F8_E(< zCx>t_$JgR9yq!u1SlC8UD}%(=h>D-b-?qlO$+?vrw}-hKSLFAG?X$9%`{yy&$9|EL z8#`aCOl01Q@N&gy-3=0Z_F`P8 zvi3Sr0vE*D{ee4hIUW#)-WNqW63)J;o3*s6%d1w=yeMe+Ow+wgP-wJdbu}^ zTd|eNrxSCX(SGzQp0Ifj=wju`1X;$n_(f!3QyDmi*KE@!WSHI(aXqcO@wFQoao8<^ zwvF#fao$H&jjyYfPvB*j*22lJDB>7*LlUgQmxACr9pNN$2l#3~< d<&rLt{{p*6Lgu^n%)I~r002ovPDHLkV1f>Zr+@$e literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/Power-Point_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/Power-Point_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..0b2a165e642350d6f19d184841f128f286ce602c GIT binary patch literal 1478 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/Sb_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/Sb_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..519723ecf822a15b44406f18ed37b9703b40fb2b GIT binary patch literal 946 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/Word_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/Word_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..c9d033bee530836972eacc7e6638afbc3c3258f8 GIT binary patch literal 1670 zcmV;126_33P)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-z07*naR7i=XR!wXjR~0_z&i$Er?`7&3`{O-)$pTiQ_qP*|A4N1hJB5PuOu{00U;?vq)Td1FlGy|)0c9)OH7E`$ifFl3cV<)#qgm6@5D-)xKM#EBD3 zDfP0}`kQH*7RH!vc>~-UT*eXrfDob*$FYo}=ofjOfB(vrEB>KGM~)ofNs|0zWo6}b znx<_4U;sdf=t{tVh!`SzB65hxdoVlz_&AOS`uh6Lw_2_5EG#T+q>}ft_VxAsuq0_k zQKXep1rZ6Yb>y65Q4|%N^EKyOWUW;~h!hbC0LVFqTI*VxruPBhbbo(;69B%qj?LCT zPM$nDk!9JLG)7k}wE@Z}<22 zAKSBM&v><3{iT$02LM2trp+wN&P+~DPHZ9?8yl0}`xnzR%^#$m3=uuHu&|I{zI=Hp z2!eY;2EMD5fQ!j)>`|>?%lhG0RVy^cwb7{URhar3jpBSwQK(=isC&X#LJCFquOXR zs?NCs*4i8q0TIy{)74t1enBmdU(Lq+P*Y`T-l5!X~oSbvUIrmur z0O#Caz4yNd07#PL8(|m*-uoNQxvOPHo-xMQvOXWA#e3_VOOhnn%ZVr{*UF~Jb2mzI{&N~Ll@YyD}Z)bP^MlD>KKW=ARYl(lw2|vk5fAkE9W=&ls!xw$iQQ(cR_jg>1Z~C`-|A$HaRBgS&%cqP zDC~NZ000Of4hBIW5K+*BU9>^S7~??@wA=0W9V8-{n3(u+yWRd;p66-VdBhmwob!rO zs>L~f69AM_YL~V4eJSN$@BKf#_g+f*wzYQ681s3p^l6c}~Wde^#s2_YiRr03Iizk)kM`27uc_ zh0ateiTK&jiTs^ zG3JS)D4yJntG~OqtS36h*f>oz5IU&oePOIXRK% z`Ollp=5o1_k#im?rBEsLj+F9GK@j}gT04~I`7>JUPX$2$N~ym~DgTIw%}%HD)z#J2 z2mokcV4yz?!!s8zUc9u42ms*JsZ&2n)AUqHG z*6a0H2vMQZ@PUD~R%cnJz4usVga81flu^B2kK;K08Ds4E`T6-xLgk_2WNK<^(pvjM zx7*#nO>uIIbN000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-v#Ysd#R7i=X*1L~YRTKvB-#K%cVKN3nU7(y(dAUp~Stt_yBFj$xviH~Mbz+^yR=3a`m4tLK9 z_W`Wt-gEX@-?!G<-&%WDy*!`$={U7jYho zgMg|b8GV2wcpFRjKY<#DDg#-G30%QfI5RF$jj!=39$=yT9@Cl4Qp;}!llTUQ(H%zA z!3lgM%F<2n(k|mwtZ$L^GRUeXW3Hsd9&3Ux%y?`Jgata|DEAAZ6CoXh8FF>3zA zkD1vlZewHm*NJ_rgX?14tS^X~)Ekw3i#M~XO=l3l;|9LKLopp56yG)tz6r18HxCPpIm|bGbl&oDG$n@TuVNDH&j=fUstBn0 zT@-R&EZ)_L{TTd`I8SCW!X>dMH-ySIi}Pq$pOx0M!(&K*`9C#LY0q_md<6D4 V*ls>)1Xut7002ovPDHLkV1g17f64#= literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/adobe-acrobat_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/adobe-acrobat_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..4a38ed24ec9c97694901e0e087e1c507dbbc27dd GIT binary patch literal 1362 zcmV-Y1+DstP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-x%t=H+R7i=Xmd$HiRTRL_x$oY2bLZnuW+qY5iY|(!(jq7= zaaB@mEyOgL;y++PDB_~kl}J}bbk{D#O&9(Ff|H_)&`LuJN@y1rEW|7XsdOQo%;de7 zd2imkAIC-C#7UaO6wm6x;hf()pZ6dU!G7fU@#EtY6BCD=b9Dd!##rz1>k`KZ#%(T{V z9>LIgk%%%PvbjA000<#UN~waB^4l~`KVMi_aJzy|oH)Vj_4+qK5S$CcunPbVa{>{8 zl#(iy%Ka?MUWuY;B8Ne)CjekdsYb0<`@Y-lest%~oy}CTQEIJLyOKjXh`0&KBl3h0 ze^)A%6-4x&O3f2-VHkFTAUHQRHg;uHzX>{f_U!avFgPEE;o2}wJNPnbnil%~KHH_X zh=>q|;o4v@I6pHpGra{gH8oXm&Rq(_Foh?@-VOl(Z~!m{0INcX9soQQ)er^%6oz3+ zM3<(frV5*&N~Ll#Ns=R4>v%L>qe4WMh?>S2DijI;|90PwVQH=7BuS1`DwUI)Am`la zBuU(Eh9e?~h;z?qIqYx4KzF%UDEftH!S;m-GE|-6nQYz;h`%`5n%4ToG))lz9Aiv)p4aR3daHbSdATz^J-s4?cq2{I3=uKkYf>rod$n49 z7{~F$EXzKPloL0{~!*-IP+Y zJQNT@_)4i?o6Y7QM6_y*X+=@w06-(+aIfJoH~FWr)((isU2N zDdhtpM2Uz<2w|m^_pG&l_51x}Q4}3C#-w}ASq|OIyAYxzrF^ilv2lA7w79sKA>vh~ zl%Efpi=yaMr_(td1i{-$lJx(Bv89Iq0F_ccW9;hU;$jA{?LC^Eo&7Ql!w@da( z007RpY?p1mBZP=RDK)N?x_;xvjn9UPE$`9#`ugQst=3jbO*rRF4#E9E^6kKsQWLdW zt-Zd!etA^C1+=uZWDxO!QtEo6(NM#h?X^6IdLcxq(P${8)OE(#g{7sXEh}x;<794b zZpIjMF^=OS`#eq_aL%vI&(Hs`lfOOBt+}~54gmW)w*cVQ{QUg0pIh7I{~nP408?er U)Nhv$;{X5v07*qoM6N<$g8r|G0{{R3 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/android2_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/android2_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..dcff94d4398d380ca7618d388cda0b38bcdd0880 GIT binary patch literal 919 zcmV;I18Dq-P)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-w5lKWrR7i=X*3E02RTKvB-%Q5DG(@fG2Ne-25^em1H}J`*L~Xo{m(j&ib-J}Akc9Qx4vgbHyq23A0Ij8i zk8lFll4MMA(eK!sC)j~KIETNIXen(@B*s8khEMbkUcsNW4(`MUN<4ncwOKrjD-m%qBIc{#>k;v0M9fsW&9g5e-j9eILpB!^>sX`P7>q~6*@##i zGFXg=)2VYjA`Vp~k4D6E`Tv`UxSDpg?b*cc5zR%!aw;@LixIIJ5l?S%lHup2h**n= zg$iRnG3O$p7qBB$mbCKu9{1r9+?By?8_c>;>S=$*?hhQ+ucwW~KHX6&{(w>^t<0() zlp;NrBwr^{L(&T|Zem&~*e~%d9?T7_B=+u3?q&w-X*{N+DJ{{ohW;D!p2NBe8c57i=RVciNO;mu`}_;+|E5U7~SgcSNGlPk{Am zy`9(#ZJbvsyY}m@RJzB1cX+9@SLt}&{`e1-e*!U#l5N;AEH z2k>{UPbT)I#$9J@cHP0;-7`vxPUp7+O8UYbxv8T{cFij3-bg#Kdrfs*sg>E>T}wY9 zrqcKc{D|*x6?1qDpDEe3Y_OQ8lnMMey3HxN%FvpqNE)M+d~XtCT|e+QlcaH#%61|# zyUo!W`4p#=M5qly3F@wVpH{{O>`RPVSL&WhOttG8>EJ^=kIVW++)-xKWu=pZGMnyI z3cfjEJ4rsqi`Dv;qkIf+**wa}ldy@!q~f|J_*43${G`Ep8tHO!SU(P1T~2P#ll<%! tFDJF!hNp~n-TK^MYTpu3E&uBR`42XR+2wP2`LX~2002ovPDHLkV1j_qt}Flm literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/android2_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/android2_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..fd21455d5a71526ea3487d77eb2d1020ade9b990 GIT binary patch literal 1541 zcmV+g2KxDlP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-ye@R3^R7i=XR!wLf*A+hJ{>+=XlIFd6vV*{(B7xL)l|Z`@ zsy9YB7Ba5PdmBWLt+U+Ev|KAfm{!EC&EAj}l`{SZi|tKq;l?`@Z9O-apbbeS39v)jkpE^y$+g z2!g+MI-U6_igp3OA|kKVYFkRFsN3yM5>XETfH5}2Isd%d?T#5^ssLaCfcd^(uU4yz zySux;zj^cKK`O-{YPDLuQi5zF_8kW+gm}U8ybn3&AEjw}kBFF3>Zd}8pA*q!7=~ea z-bPWh4FL1CT5Sga{`5Z)UAS=Jyw>{K&d$yrB2xK}s@1CR`~Kg1pR6qPe-b z**K0r*xTFND^q}osFYH!<2b)wTU%Q_j7bBLy^*Hr`;Q(y>Jd?lh(JV8tJP{ssY~s4 zdsP4cSZimJBpowpRDQ9ru;3R(A&CeFS%-)ugvfl~Kb~dTJt^hC z(=?q(k|YNJNRq_5t~&z&t72+u>WJ_ACyg;0_V0!#rTk)TZEb#GVc~q9=d~z`{*`5! zD1ilTV`0i<`o1dTmK1q^ZQ51Cc?AZ1!Y?qyt%ym zih=dhgd<}As<455Ds2bs5G5D@CHQYmen{vE>wR=Y3=uJX%wV4w`C&?jqU`sn z-K=&Q+JdZKPJ^?5h((Cm;^E~g4lv4G3pS4zNt)p(Y zdkFxR$H&KCBq9ic;Qe~Neuao&e0=<6BKo+~>C9`bJ7pwDL?ES9p6A`^^?IKj0IjdD zXNY*!_x(y)Nb0wdIF5CaBvcfI0RYJJyeQu#AR?o+wn>ucvhn~WQ+?mBFvhN~udinZ zKmY*kc6-J1ylcMikCstU$r?gLp_Hm$ym%1-U|0y@0|0Q&$8cYu?;sI@@B5>k=Uuyg z{rXDZ{$UT_-^w>>2TGbtDaFXh$QI{(CywJ206=bErgTP)jEp!+ zsSh~kZ!az`7K3)5IGi*Zjk!F}-;Cq000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-vl}SWFR7i=v*1e0AR}=>D-^`Bg>IOx34Fr1qV-^IHLJQLvNR`CTLQ{nlx=Msu-O-t`xX&=J>+WV& z7Z1GfzVAKfdComw_tv`It^s8YHef8@lemM2gBUjkSl@%)*c_7KtWAgPCVs&cyqpWD zHqVZ}!BK2O8_xsOGpNOp5e(rE9K%n864h}WhtNW^sy{=wYCMXi_z_3YnUAP}Gx$~s zOJ^4FxuhE>$8ZtftAw&XL-_~nR}#Ds64C9%c7L$?i8YNtJ9=DgPa4^+LBxsjkH!5sYRqchS$$9y6+Bk)#uB4W;8Z;h7S`ktj`7 z-k)Px-k<6BP7_P=Oa-qNoayLp!kPv)DkWLReO!&<*SHbG?Kr1Qh22Vmr|=aX;4b#Y z{xR-hC$CFcX6J4Ei_hcG6a1$P;bEnL4>#h$WIX6Zp&g=jJYJ5EvOb+>DE}q=t%P)3$#*Ll zlek?E8ZTnp8#kSbjp)6IZYP+x@UWMoE8d)Yiy`%3zyA@`QVy-* zkPLjj&p}cP*0Er}7On}LQj*y-cpDPII2BCHe(;@D4!%d;?%*3&n)f^N9DFZv5GRzT z9o4VA*>+f68;#A0V7zuw8RT-ZRoU5mmy^0O9Ts#ssmc;%a1L_a`dR6rS>^wTs`5@3 Z$X5;W-Yf1x`lbK?002ovPDHLkV1m1pZ|?vA literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/android_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/android_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..1ccda8f96f5ef2417d678e054b07f9f126ad2d5d GIT binary patch literal 1282 zcmV+d1^xPoP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-xd`Uz>R7i=fmQQHhMHI*1doz>Y&h9ds-8OB(f=GiQ81W#~ zT(qXNwOSLBp1s&p@zfqgdJ@m=MK6VV_2h=eLTRNT0WkzU87;A54x*sV{>iVK{r!GB zf1ZczE=_4d()Pi?z?*rWdGlr-Uu0(3iyc3H{NT{g&`1cO3;;kxjfW2(t}ZVxukU3) z?gpBfnUTzV+FEb_FydqlijtybN>K{GQmA6jcKwcG92 z(=-j%+BAgV0HC)4iAXA?a=BcN^7;HPN~vqrYW2H4fzF;iOHmYkktE5-aU6H7we4;O z__P4r4WN|D8)F8v)?a5?_Sx;*x5JL06DLl{a=HA~#>U3^IF9Q85OxCW03>5frBo_? zTd&tYSzKJ~U!{C}aj8`LybD?H#@`bJpr3Jw<9Hna&JPX_)&Stso}YS?si~=RX_{V$ z7smuQl0~goxJKc9JAx#bWVf9~443lO#!CW_Xb!NsMS zwTYB+KnRfo0QTM|L=+(+gb-39(g1)Vgf02j5OI@;{zJqMlv00bt$!;N3WtRdD_ZM6l~Nn|eEt{_Eds#b0PwDq@~9A^>YRHM z5m8F{WB+-F5F`K`_1^y+MNx^Fvm{B5rD-}WrK~ga4U25}q?8qAemhOm0udc*x7$aY zbN?{&xh%_$S!)Nh)?>9=En{ZS%>RZEUR6rfiKywl*Uq`oG)=)6lLA0P*6a0EV@v}8 z4#jaCh-ef50&KM>4*;;axtT}A!_3SfgbV;O=bQk5eD^sIGP6a*G5}N%QF!k=M1(?! zMx)VKrKP2%^=_-r0YG48+dXBkQ!_LB5JIOL414XSH<;PN)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-w9!W$&R7i=X);)+^RTKyC-@KXK+0Cx`AXzb;piQ!x6p7eb zDbX})6)nUsu(1%ehzQ0?FhmTZ3u>dCT8KhqHFg%pLXh|sQKKM;h#OrK(M{H!c^2n9 z=FQCRFu@C#nfKnk|8wsD{LeYJQI@4K#~gNHdp`e;Z?H7Z=GGYB58_r_mqyz8?NS>1 z3Ljt*Ya0PIMx5wQ9L8RBa4~_Z4UKeU3Qc^Dqj+arLj|74Ls-S%_4Na5>zijViC6I$ zx}yxW@EQ&YS~eOLNZoLmPHx9rxL=LRVgTS6?h*km({Qsk3lXDlZMYln(o@|eo)AhZ)B8X1C7#7}zVF~ke1_}s zN6nE!FJ@(89TsX_tqdIy>RQ(0y-e@#!RCDKieO)X6F7p|G&YM@@+2K0qP>ZIqKeT$ z11hN*`wJIxo)0Oe$ElgvX9`g=zSc|1YE+3knX{dz`ZV9K;`?M}La&O~_fIGGQe}P7uwoju z->Eb-o&P2HDZC(*_{qS&ij_rrCFrE+C%Z&OH*z-d5pLG2W2f_khlH#@Ou%cfU$2bK zB<4x_i|QSCLx`hHu(N4sEe&^s(hdmmOz9WUib##ZKv5m+N5@65t2WV2&+1*ZE6P$; zDF#O=5_tiSRxj6Ue6J@h=SG07H>$?BLo~kojA(poLZ%DYQaepG*8{KSOzv4ojJ{qq z&gEo}IN7MnNr5k1=H;Y5CUBeau3PWxuXC4Ws6PJJ1@b@4_5WOI-5Znu0000000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-ytw}^dR7i=XR!xW;#}$6Bx~jXYd(yoREcdl39}ned((DzIs3Py@x~u2eFeUPfpLw%p5hwL;wJc zvB9H9kG5{#zP){r^Y~>%%gf80h<>P)`himFnAW;OL=FG|A{Lfq^@R`*gb;s4#E({2 zSF5i~w7k50Rw?y*nx@a?d2W$)!UJnx@Eh)b)htA9Qa(U~)6 znBzFV&9dy3IF3uDR9bt0PXeGCKnURlL10TM-z$pZmp5+QFi#~qb?Ow4qUaB!(P$-( z;~gS`r{J6V|L$T<$bukfhhg~s&d$zj>+9>gq2$feVHp0pCfT-a8-))+jR;62oZ^hu+!;GIgaz{_3PI^003YB01FEXwlU^n9LGhy*|IEa zc=ztz`-cu4`cW8$FNb0Ha<|)k<<6Zue`AdOT}s*VJdb?euj-G45EJhyj^l!eE-oxA z*t?-?wOY@oX*#Er8cyO)L^L-y*Uqx+#W;=wA|lW8%n|F8JXZ*jJC5_6PN(zkXf(b&n;uR4gV@x9Awav}V*A5>({7u(&b1CI_qbPa<03KSFWm>Hk z8;{3V5b?7#O+WE{|5rkY9~VV2o+w9+J>WY#J6k~z3>ah25Yg^yM?}jQ^S|TAkAKUu ztUqO0mRgq8uBz(ip67kf7;`_*^RHD^^+(1SwOXwUN~!-K;%=T8W8AW=!C)}hVjCM9 z+qKlYwBKh-DP<=~Vvj~6XFMKf4h9pUDNh$9MA-twnh{$fWMr)lAk%5NXG>n2Em=1#A^3|(XciY6CcQhOh-;Sba8UR+}IPPn$ORcr~ zA`&9*>$r`^HywuI`-8#Y?dJL($>{ZZ6(U{;g5Ywy-428h6K|*n-`8=eHX(%9ZnuLV z2re_mF7$f6J%h?qhm)nHrE^tPy`HA&+yRG^dz|x2Yin!QpM>|NYz#002ovPDHLkV1i0S_a^`V literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/programs_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/programs_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..4e598a52906a13223d5694bb2bc0913fee9b1abd GIT binary patch literal 925 zcmV;O17iG%P)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-w7fD1xR7i=X);ow@RTKu`@7%|XlbJ9HGZXQFA_^jkqF9I) zmeFZcEY!xt#zHF-pCE{Zs0l> z^l=zJ$65$j#PzYxR%9VsXIt?IKF(T_eEYnVNwpN*PjNYJ#ho~TZ#2Qrycs8-)$t9a zWSXFH-F7LvmJ1hb#$C8Z3iQ{(v@6!Dco|noiIc5(E9SF-xg7_yphc}LDJ<)S@J`G> zNU02Ga2dXh{dDkUSFQ#2!Jbs{H{yIj&<)ey#I_K26g$JxUVvmpCqlp$!*M$w*b7x% z*LR1xbA?qM{3c~i2I=5RDf0$FI~T&10=Nprx&_W@Jkbk(PPSaP8k!uC3b4W*cnQ1l zQ_w#X!k-PkS?q~0HN zK{p**Zq_75x1j4uF>2!vuw2!3y?_s;E8w3N(V6%vseZQMWYDc)J_P)!iP5Dk1&-sv z9LQt1&2W2}l3M?Jadtailwy`+^fa!(3&Ass*J54?jAK~JF*<}DBi!~YzKDGtRvp#E z=us*2K8yV(yizFJ3GDykazrY^TyS}Gi}j=wqp9L7x10<-qiI3Yfq8`Crg}f#my)BF ze18(Z2ha?zl^X52pt(8}IHBnt*GaXvMbT8-_t6`8Qu7Yz2NTULJ5_ih7jCw)mb$?_ z_FLzg5LUb^U3{nfzl(2PD)gO-i?3ZfD^gPImog{EEPtcG%b3gt?+&ep$~cdcnH+yLyxZ^%Kz?E+00000NkvXXu0mjf7-XYD literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/programs_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/programs_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..eee51c278c00ec30732906024990ef6c034e1c1d GIT binary patch literal 1580 zcmV+{2GjY8P)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-yrb$FWR7i=XR$XWu*A@QGnS1AFXFU6(wM&%l+ve`JmtlZ6bgNmWV=B^YDMKzsyZ(%b!rlt zLZQ$Gue9r7cV=hr&OLqbtXL&-Q0RTTbMHOheBXD^xramqhZ$$ioM|3Cdh{u4Z5;rZ zx%2Sh!}ssqyVpLA{UG?-!R6UD2ifAL_7c>qTF$u9j)~Pt@Uq-Xk&SK zdGwiq78e)4X^gp^rs=7{U|@|g18eOF!1w?$v(j4ozVCCTQu&+K`i$QcZ5IR;xcLLE5hCR+w2$NX4VkC@qS@ z0Qdx2`9n5Ik~V;AwOVZlz^k8NbmhvG`N3fDR=eHq20@^sDB57=e^_fZ05G#L#>^#2 z@|DqOWJ+dxeoc}CfT^jen&)}X-MMq;9ROeen4O(+VSxMbR^9nw~Vq zbjK1fbCjm(bid#KlJEOr7>4ggQREWQ4@aZXyUc8hqIea+7p%3{nOQ`n#>~Iy^?Eg9 zOqylc$ta4R0kEb3z*;+(W!b)4QZiGX=PB296*Dstky7gKtE;Q`0pP-g3y(zPbDNu+ ze+7VZ=gw7p-WIWG%lbM@JDLopE{siDz zV@!1X_;JVgeQC8?3IH8DcFYZeKw7O$;iaI5`06^?LQ9D0CdhZ6YFTEpg zH<%ekQN+yrIuTU?6nLCo9)SA3Jeo`k0G5dUwYeQ*A*=)Xs1M-ZCs6#~gL5tQ}MMNlNsfb7+A|VlR>8Aq#M5KsFd7f9D zROay#&vUQe?;kyK!icjxoh|@z97p-S|B>T3{}mAuk*Fw&FFTI&ArWN&Y*7?n z6cJx3^L^T3zaNIyWZw@Z@A`YimSA&&P3mv(ae8W6vgiI{;+QlSZQv$8mgMiIfc68=>H0000000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-w2}wjjR7i=X)=y|$RTKvB-#n8{HU4R>qoRl?Zmj=M5OJdm z1+@^=MQOx^Er=WGqHYBD3Svszh^`C@)qopaDP1XAUAQS471NrenrLEXP8avQ z&P$wRrg-2n^WMGZ`_4W0yXV|iL>SRJxD|Wz{S3ax!YIyTBaH9Iqqsdu+BvqCWZ&Xb z9LL6XK&>5C^dw%yUFhPU1gafc8OSbNgs<@`J{*;(!s~br>sV>d-!ix9Jc$Xsg%{A< ziD(RO*qFQnQnFGpL>-j%l36(LpPE9PeW> zqif?5Ea7Z^805>4Q9MZSNfLoT2(TRvJB4QyTmLlT#2$AoKh`EU9MZ|IxJJuNgD6tk2yHjDG zBFV0z!eJ|cTW~La%RT)Ak6=8st?Y;Vz1!wJsM|=l5l|>1If##I zG0Z9bWYXrEwyf;IEFQ{lD@uuJKCAkbz9yMW%sHH|4C_kMYBwgTey)*rrWT;VNan z4{0>Mtp|2PQQ1sJUGG^PO7p{q<>bx;-|2Ev;TsotIceHB9y8i? l>l39t476cHP5WOL$a5E8mWAd;-tYhb002ovPDHLkV1oB$r>y`0 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/ps.com_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/Suite/ps.com_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..102dfd39c80eeb3992a5b8e43490916293325549 GIT binary patch literal 1497 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 Ac>n+a literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/3D_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/3D_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..35d6b7603170d2e18690e746e4d0092804b17458 GIT binary patch literal 1652 zcmV-)28;QLP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-y?ny*JR7i=XmQ8G2R~5(4x$oZhF>n0de0V|@SICfP?>WB#0iXuo5 zA?>1FG!Z7_`OLgG@7<5XqBA8fcIApAz16+<|GVeibN}}s5y4L4(4j-arBZ3HF(wZH zz!+=XyLa#Q+S*!eC+qQ}K;?3o6Vanm%HvYXeOl`x5jg+=h?rQGwIPJKC4~4RBEC_n zRMf`?mCNNRDdn?K6dmaGdPYjwGsY+Y7%V`>7#BjguIsW)CUa8=@nWS?`NNJt6B856 zah&JlIDVqtZl_YpsGk9DB|v=vAw(t!0^9SvSCS<8{_^s&*%mZ9I?D6;{4ZLq)@-}o zt^q ztJSIjz-%s;+W>&?{ZB?GPMr91uh%CHXgBU+wy(?Cg=Q5h`3Hfdz4aN zjN|yz-EKGWegC~oCi5Fa1R{cd=0rp;B7RD1ef0kQ`z0x*DwRraM^W_HrAwDm4giqN zW{-8d-Tk(0>wG@{S{%neSXx?=gWaAydGhDBZJ$NNX8_>F#fukzwcT0G&CTs`9OuW4 zM&r>aiuU`ye+&SYIRJpxdOS%Ik(_sB=gyrUj*pKY zS4w3N5s8SVr>CEmQhp8qx{l-AR!aSLadGjzBS(%roy+AGI-Sml)_NQOmf6V2$goms zpE1S|(cjADvOhUFIT1zCnR>mxmx#V~;J|@B^nR=}#yIrvl2Ynur_=dbtJV5yr_*_X zG4|@{=%|17>QzZZFEPfnlycwU!-t1?p-|YHBuQRM*^Hv-SemA90zif__D(LBdlwO3 zPt){Y)6>(RH^zL%81v75g^@8PmQuEqQk^78006!)G&J-j09Z(p zM3g5YhlorRMIHcTIp^7YKL7irrKN8I0GvL3I+Ld96TM!qNJN`#1`!9BnbI^hp67kC zKh#9T4iR|(kmnC9Ajfesh-e#QWSXX*otm2ZwPjh??%uuo(zR>XzA-sDIm8(I#8yQ> zM8FtBL>v^6*Y`yO0KfpC0RXAzd2SE{ukG5k>$xBZ{@m;J9$sHxpG=bEr@MFW9wQ>1 zB*~&>Spxp+cMJe5BC>=K8Q=GNhh*g4Hd|d?tqCD+5fL)Ro;-N)pjE9_-*g=3RH0D#86rNuw6t_%e0t2HDdn3|fJh@$8ft+ft< z;1cKjg-WGzbFlMrxjdqjdam7Wk1@vnV%zppmSurbN+F^_MDl%KXssXCT7M-;l2eUF zBOMwV%KET!ZfUBBh>S72f7r$tlfwH?2J``&T)$s+)UPlD z09Y&*H<>CMOk7x4SoA#aTo{JMzIcy_Vj@ZqaqvtGvQQuX5K$wd0RRYspy+wtxdCJo z2mqkjY@Q9nuo4782>{sO_1sDHEs6y}PzuAa(rh-*J~+M!w6e0I5b;b91TPl~g+K_A z=?iQN9E=MgGKE4R2!h~c#@Lyam6gp7vYp1v%*?b>>e(oY_V2Jc`8((Q#rgU9>Q;Im y*>26u%y0nMQM&~IZ_LlnfBbgq!}0$%kpBVM6;-D4lEW(i0000KO9? literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/APP-info_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/APP-info_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..e22e99ad626e99ebf189e99d533753451fa1ae70 GIT binary patch literal 988 zcmV<210(#2P)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-wR!KxbR7i=X)?18TQxpgA-*@Jl(V1bYYABwBG*QxuxWAAH zrGz1pAt6Y_i=+u5E{TX}A~K0v+6P{U7n*2@QnwHy=|cr6T0HR93N5{NI&Ei`hrNzD z)6Pu4#!7Zh&fa_d*KPmT-mQqxp$y_Y%+LS7@iVq{qTKFaeHpID1!?4jTpLScKjCAn z!{M2LTC+rSD;~oVjN?E8)e5b2WDdHp5zph@P7PIf0T19H_D!SLgT6Edhw|Hv*YGeV zW;4{r>ljwjGSL95H_pZHcqhO8xCYl{!~7_#f3`h z9!kA2>`X^Trf5b)J#LAJ(TLa@5nJ-Rwei0zBHoXPfrwZW5r-mTWkjrxh(9CZ;)qxl z5xXPekHi|P@#~0s@OXL@8A)?gIX{9&aa*SLbNq-?@HW1~R~hA)a+rFWsavX?uDbAT zrLYq@Dr~`a+?+;g2iw?>vv4K8Rw%G9F_+eW6t2{#WDb78a)qP=%IUj1*LpI#3hS|` zfzy|f)H0FSYpVo1AETM3ZiVp`p1@VOAD5@%_c*Cxtfla16dRQ8F`o0Ii9J}QNAq*B zmKH9ZsSIcQ@b)g_MtA z4{ppfuE}Wkrn3`?J#VI7*PUs23NPVYyrR@+1s3AN1Rl+FeTj3h%hCMQ#tx-`CpMz$ zOGC?*(^PkA_%$OK#y?68FTw5{O_EoMy`zoI33OV+&|X}Nrt69 zqBPwjJ4sh!Z*D8?W)m(_ib*NrLcFOo$zd!`#b*?vKACe&lDsLAj%~uWI+yEA&1>C2 z7bx60BiFl>RQBR@$CfIw{{#O-xlj5V8$MMoyXSBCF4_o5Gita!3xCBy_KGWcMi7z_aPlSi?w5q0OBN7mvD+UQ`IWGr^iya~*w?Z*8Tn z2NS#o8^kK*`Y@fLHr`N*zrCS&EUEWZO2=4@d(Cq39mYNB&0K{~(HPSisOS4rXH{ZM zd8l;qI9aTuYqrNpg&!Q}iC6&qvvH!Sy5n0000< KMNUMnLSTYIEzlbP literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/APP-info_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/APP-info_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..ef71e010709563ecfebd9615b4e9757e35af81ef GIT binary patch literal 1693 zcmV;O24eY%P)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-z7fD1xR7i=XmS1Qb#~sIiGdr_8yVB0y>2#`9+0?f^)02;zC6z>i0A+S5JI|^Wz{+7A92qA zP6&BtZf;J0ZqW4f^z%xoGjSXrNYm6PrBY*z1^@&AKtw_*Wt?;2x-RuR@1LCW*XHKt z{_;ei(%07)c%F9`0IsEJ`U&UUV~icivh16!R!e)H z=a)*QH^VUe{?gLYMkv{4Y7hj!EFf!z{~iPo5q#edq?A{(EPF)=@fFu~zX1TB8e?8| z9OoI^wqLK;>xK|AQ!16}0PyqPdD?ra)oLfwG(8nXQT-7Rv~9c3_x+{Yw{O49Isc8; z`V9bZ5OD?(-!;b68Dl^4ecy?qC`{Az)a2yki7lXsi3!^n^HLN=-NG-~_D~@NbUK~i z9z1yPOcX_v?RLAK=lN2arvD1VFv#=#(%rjvZ*$JywJghtqNt0AFHKBL*c+h!{{H8Z zB-yW&iU}d$I1ZCiGAX5zQkozLsONeA>2|woN~!O(+wBHPL^eHk|g{4`}?2UxFciCu_Q@MkzJ1Gc^})h{Zp;=pk-OU);jZj|AkhoC5$mP zKFA;%hT$#G^F|3F+!zChD2y>_FI-8I7$L+l0JuTN$HxbiQu~xrX_3WTDfKa9jPBU6 z14OtJ*<>M&iRKzh<-#w&N(g4Fd;+|$MFY3h*3n$2_Zx&l`5t7jgOBH z(t&}2y?LIOi(>3uKCx~4Yf7nw%aQ*L@XC=<)Icq2ysuJK23e!ujG0DH$uq1 zJ$v>XU0q#0TB%fiz&ZaRBDS+EJCSACd!9wi9?4D{Y)wKA!F>TGcz+6 zjWJ?uZ0rT4)CZK(-S_U@`@QSBEKSq>TI(*QbPI)2$}G!jG#ZUNba{Dst!VWE{@0mv z&iT{Em^ZFmxpG!({kmmYU)EahZZ?~*UcGwt93n0a4-bzKLVys0+rw34rQn=@w7k5$ zMho)WuItiG4HgUCL$kB94r6S%7z>sVV)*3AlY%iegoyCCdFHwpriPx>p(++|lS4y2* zUtfPlYuzoPhlofjl}bqnaq9Z@>kC^z006aG?N_Z<>%};Z*M$%c0OUm&NueGApf}J6 z09aX;DWz0ad?O-)lyXo?dGXq{Ya3%?OC2?v&GY4Qc@Pn2qA02Z06wB59x_4*^!lHa zvJwQrn~g@}{N{hQ1bA_AQ4>ODgCMwAsZ^wG+isx(i|l&n>8aqHdjkUlQc8J|QaZc1 zxVU9e`OM{HYHDgyYkek;w n0)Ths=jT8Fy0zW@-v#o&{+(&Dn@!p300000NkvXXu0mjfC!#R% literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/Base_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/Base_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..b45728c57d33fa8ffba9f51582fd5ec17de76f85 GIT binary patch literal 752 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/Control-Panel1_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/Control-Panel1_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..32dfa26c6cd435bd3032ddddea2eb8ff6d8e4f28 GIT binary patch literal 849 zcmV-X1FrmuP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-v%Sl8*R7i=X)=!MxQxpgA&wKOwrc~4zwIE?55iM;Z5wVf5 zDP8!t5i2BuL?}(98;PVMh=f?of&~&mMMOn1M67j-bjlLj>VK1(>bz@l&QI_A<@d(x z^dvX$o%=iYd;Z>YZm*PLO4@>(FrWNU{DLFX93D*ZeHZS*&8cKIzpbRQL--bpI5!EX zw}wX#VlQ@J6@MpCbD)=oY{U$H!W;Np@EmsIcU*yA)5v*|>np__>QvgtanT_A z)qXGc{=#+X)tTzdKez$!<7<3{cX4eRS>vzZ_yC7RySdu=kPY!0p2hd+{+;Q~Fy-db zv+t7MBQ9y3f|E_jBzKvuU%cskZ0Q+oHW3P2u&>vMBil6UGE_F+X&Eo~&o^T_pzJW2(W|Zwa3h zMX?}U-;@B&>H=?86Rw5C7<;Hp^ElZqJX`B=(ii1^L64J~HsD^{r`L=R35J<7U00000NkvXXu0mjfqra4k literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/Control-Panel1_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/Control-Panel1_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..e8b36ef9de530319281293552cc6d3102fcd2c0a GIT binary patch literal 1407 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 YKSU`Jx%u&Lm;e9(07*qoM6N<$g5d5_r2qf` literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/Desktop_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/Desktop_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..0c25d7cc15924b9d400e1da6e906c98cf67a6390 GIT binary patch literal 1197 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/HDD_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/HDD_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..05aadee33337bc55bf1516c77342c1aff693caaa GIT binary patch literal 648 zcmV;30(bq1P)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-v0!c(cR7i=v*0D|$Q4|K?Z^02@ndVq!-^Y_!x$DzsC41C8QCAQB1^cZD5`d&V6$yX)*O@g$SX%)RIT?>+ZF z=bl=g=PKGfE?_pkckvxNRh+X5Y3}!UR5J6>qB&)$tsU(857^e%IWxa|2U&fyZbMBFgX*ccrkjdw}<|JQg{NH+ZNN z%6ix2XIPOAco-5fw;jGKfz=r-?dTR>V=q=W3`yAv-x=J)Mww^|TatVa#vmz^H6;08 zN2>_klBBMaAQ2b`fw@HIjFt_5CRNDVfi06Veo@MkA~(84GK?KbX)zg?iXGvYDprP)}@vaNos+$8ra9ewSjfal^jMP5g6-%iQX6AE9v6000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-wo=HSOR7i=fmceTqM-;}tnVpfeLYno;R*R248G{Rj1|xbg zirZjtZKV7M%_;Ph+*(R5Ej=fvUIJiT>e&T{ixULeI7-T)mlf^ zS_5FTfpN}-lroh{rFc4>{#Q!*tWv4`H5F)MV}mD?$zQ`T{4NNBzSg=otblze0SyyK zDbq@+gzLJ$$8r4A?(VL=7PPjuCVb!j?fm@weh>sL0QNe-H9)SE%6XpmXRFoves6DY ze3at-pFPj}We7PP=AQ}zj4QT55S#+IKQ}jb2H?k0oR2=Xx3@Q=D0&bC!P%^ktGplx z&Y~!Ku(h?dc?nc378BOm$3YOpc-QQkK*lft6a+y`M30NbVqy%+WHNWdFkI1E_onU1 zL=t06YuyXOa3zz;+#Q3gwfDj>v_!;+2p?&&Fbu7=_8tI;LZPsrlv*~%MCo*z0T9NR zn^wgD7{_rmV@&q@{YY!QTqqP4L@t+GilWE|z_Z!xTOq{TIF3O?{Qt6E5i!PyF_y_@ zv$>0li%_K= zbCOch`ue)(IF63vc&3UR$Dzf=#lc`ONLp)K$z+mo&d0BTV2rf^M2s<|wf>AT_H!J^ z4raXKgTVmD$HzoO)a`aViA3Vd;RTKWv_-4cI#Nott+k)D+wCs^+_Bb9&N^A6UReNE z2+?l0+ef_FY@SLf4}}mZV@zzV?E$#W3W+E(#>7GhS4w%wU)9Q>9cA!?)@- z8~{uymE@d1t=H@QF$e%^wc1P9bzdl@=7&Yy1V%&zrPRFZx-WKic3zGGmu98Y={)f~ zucDO76A_=~80nq3QY!CxUZvCNJb6EU3Djsb3}ft}QtEjwms6vjO#+VMQp$8Lms3iq z=bZD0jYi{=QMuNfluD&7W6YyoueUO#IXMtQJgZi#wGZW+XtzqGk^nH3-2(8sTCL7* ex32282J%11c}WC4hSt#l0000iSv8_ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/HW_info_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/HW_info_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..13caf5ea6159186ec3aedd4550d4a86b041a72f6 GIT binary patch literal 1016 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 ft-HtnDT%= literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/LOCK_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/LOCK_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..7ff44d4f533fdc3e473c9fbbc07d2496fc35a5a8 GIT binary patch literal 840 zcmV-O1GoH%P)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-v!bwCyR7i=X*1L;eRS*a8&%OKG#LXH*i2FyF_-KSwVkKxG z7%L+P(Lxce6vf6`5J9UnHi|*SN=1l9YX+GxMFtnKLs@L>Ng+xC;mJ`!des;uzt{i2WmY7FV)5xejXUc%-qMH9S>$Ca>b zCU~R)doZ88|KQpH&jEadr&XcspV6B*jz207LJ3cUZ}3C@y9W;>##-)gD#>vim+<1$ z_lRyi8WGncVkIJ$tLNp2_%$LPs(8C~I3mtQ#A;7wC9#fmyj|#a;cF#*JL@`+CQ4#_ zhga}qhUingmNH){3DKQPipXp^p#LKz&enedD z$u1}6(TLEd1xNIq?s6z*QX1y$k7OpEeWQM7i;Y5~K@Rmx_znoA2{j zs6ZB!B#}IOaHR@)lbDCFG{He7B{wRNCS(3OzRZ6g;H+}DI>o=``zfs8x%8|vbR)43 zPOx7oD|P6a1o}`ZG4O4!A^IM_<9X97Au)Gj|4>|Ox_z7dn)c4xY_X~w?vT=c$(cn% zylrBywm7Gho4Fl;j-|Q8KG!NG;}<21`W1F`v)V#-A+axZ;W}+NbZZ0uwxYEGWo=^r zS5(g^{iG{Flr(+@%cd23D_U35xUS@jiFt-w+r%*?omVT%?nq;{3t^+&nZJ^^QLfDs z_@u80-o^{2bHGlrPG!&%PO93(P~&?~X?&MVLorrKi#wIZ_mryf^%GznC(@dIN}Quw zL*U(7Oqr93am%1GW;nT5@od&`(&8sO98PMQ$0Np#Tc0a)#2{^_sHXolK>iED?s?!U Sy%WR$0000pLLP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-xnMp)JR7i=XR!xW;MHGJTRo8U)Os8h2XBGtUnk5)7D$C*} zY;Z#`yPKH=1o5IlA$ZUnL=efvA3S);$xA@bia4_~u7pIgOhB^6V*+8liegC5&(2PF zPfzt!dD!lCcidSfONd15pg6}8qT001IJjIkEy{2}N37eu^OtybeF7OGS#%TmfK zK@hw!7z~t@a-fuo0U#wH5gD9w%d#xWX0!J>=hv#$>Q7S%ojrS&Ow;@#48ym3z1~nt z8Kkxo4yyqGIOka*M8>x5Z=)#sTnVq44$g_V$Hduh#|ug@~xN)`&=k zVc3Ys6P}FYIM7<}*#H0uA>4dE|6{w|e(%nmJA0ut_N(Ue`Ogv&4-wOYXwJFmI1Xkq znP0Wm_qEoFh@O{HzS8ga*>E@v6MNO`^*jK$Ff%jL0)UVI=h5ow>bb#S@J*}L>LQ}v zFXFmxJCn(LSgX}G_8;ux#fvWwhr?^FR_nPaibC8~(^_jR7K<~cXu zsD!6E=h;%J^oQ^JuWf8>3<&_hah%g(7@iyx0mCpX#@O$P$QwZreCm1Lv!3TY$-DM6cv}G|k%y^ZQ&bcV8(rOoTZA{E3LLyuAEfHkq1gi_P<~t@k>|LM< zM9^9TV=OmmeH^A~I!CP&B6bilg2PM9q_T4u4&^6%cc|TNZ!yL?L}VOd_*5VwgE7|W zbUItKxw+{jrQXtG6*j%pX)tb^JX(u${%~`1)1yTBrfu6aMugF56u^{_Qu^a!wrvv; z-2_OAYQNvVoy+AO_`ZKUZ3|LL$ryWUX=&+ir4&C(got7QaN{`Ei8GpWp0#cJLBHSM zeI9AFR#sNdMNza@R1pyvW5*CNy}L-FAE+l1EoNwN;owj_io2_dept*z~~i39i2?RKx`^ZBX}VpeNS0H6^OrumYPkq}}w zpU+pj-R{)`;obk!Y&K&=yex#c?z*nvoM)3zOw7J?opYXbT~`Ppt`pJaX0v%98Wty{tGPi Vpbg}MXHEbB002ovPDHLkV1gYhYu*3= literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/SW-info_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/SW-info_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..31c57000b7a7e2d2238bd4e4e291a66003c12525 GIT binary patch literal 884 zcmV-)1B?8LP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-v?ny*JR7i=X);oxtRTKyC-^|Wt-5t?{bs|^@BKSxo;)7VI zXs2$W5d>5DXl$&ahG=1}BAP}KZH$$~LJQ4mu(Oa@iK6j=ji>>$=Fud(nXF!mbH3#6 z=j>#H2QJ)?^PR{2pZ`7Qc1kHGlmTwUe10Fp4_KPSxHo}*0r%sk3^J3tGa2kVe1=7= zuIH#T=0p!;4{pZaSV>2XK_?Tr1XK71ui&Fe19kB_p285P(|Ko|gc{u(HsBpRgMY>a z>fv2HioeouZk+&aSr%|!f&F+=1!cQNuVN>T3P`@jdt*)`b*pK2ry$49Omx?|ze*|1 zdZ?7LTuM1oO8F!AFID;rt=*-RvuS%I?RPZ#=0qFtd>*~QykI)@Z{d!FrIT0OkC_;Rgw!b>Hu34mT^UIOJA_-E<7%}#IJY}m*GJA--bThAK&6Z6?uAsX=en3#+|C&tA@B%)Z`6ux|8XAub}x#`aaRaVbO&*j|kK_?_;BY zVO2mig;`PC9&W|$xF&5*i~D&DhkK%Be4jrKtz}*V?aR1MT*N^pbUYI{gfCNn3;wJU zoK4?L&4pbQ6m3fr^gynwL|vw_FJYA+>w@(bdr3^4pR#H_iC6y_GjR8gKyL*pTcX_j`B&Q9_7z! zwX{hdC)@HA;~pnn(G4!@aZ<~)VAmwitxp9}M#_Z()$+d{kpBX|4>7sdOx)D~0000< KMNUMnLSTZcVwYq9 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/SW-info_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/SW-info_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..d9b30606a4cee1ed7361cbb12a69e5e6a25f9796 GIT binary patch literal 1472 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 AnE(I) literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/apps4_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/apps4_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..3120915c8bf3fa32e028d2088eeb88746f2a0666 GIT binary patch literal 1295 zcmV+q1@QWbP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-xiAh93R7i=XRy}MKR}lW@y?wX0=kuQL$B7h)Dh0Acnn*$J zEF%XFfx+i4Wr!l76cLn3M1`UhX{eAQOQfO3h6@;Qgk_{iC)yw(nkb5t%J%)NFT1yX zyKgA&_PASYV#IX2^Jc#JX6DTsVrCpgPM$njnVz0LZj31cfDod!y}kYN*|TRmN3o~3 z0o7_Xi5vlv2MF(Z=fPYV^)PwOZ}G*7}O?`=9iB zJ)^bm8Dk;c;Bo>TgE^s#dGQw(TE-Ao$YrynU^;KVU!y zIpBc!^4LU&7nYZb8}X)SiITkbe28OYcjJ*0}v4o$^tVp5ee6I zONBz=PP5tk=IPU?!&F+MhYN+m^#RDXQYt5<%qD&S5CGO%dqgBG%bHB-5Jk~{p66`? zSe}}i+6D048;mYoxNxr5>)qPf*=c7o8QXQ;KWy9H)LLf-Obh^Le}Dfg0G@5zx4AC_ z0G4HGt#z&4ZqGzfv|lclr)=B4RIk_X4;jtR&u1nkCa!v(7Xn}@rNhkY^?LnwIz`oL zbvcgXe;zz|a5Jr2SXlT-O8KeQI`lj*tW+vj=jZ1)Ha9o-1pwsp`BOmzUcv*@`HYO2^|kE)Fi^s8KQj zkl-IXcFbmGi-=V6kNN@t$Ye5VG*)9w6vuI~SS%i=YPEVk48!Z4PA8Wf5<<}ASRw?zO(P-=>`F-p-PTKK%Gjbe92q7L1 zBj|R!PaMa2u9V7+uzKSj0sZbeZn z`F#Fw01ab|LO)f8h$J&F0FXqqVT{p4B+&0j4dAnGxBGDvMNzq2p2}vkm+sxWcYh2B z04`p<_><>(UwfXnEv2-D5V>?Z;yB&|04e1p#)XVAK^(_D*L9~|*Il`L_wMkS80)ll zyM3)#ELH$4d!Dx&$8j5}!Y66dT6-xV1|VG5{h&}N+-bF1*G83N4Y0Mf6%o;8*L7D) zrIM?ZN*M9zC`tea-wc42Qn^y8(H102^y-Ywx~prR9AW$X9;bX(LJA53~RP002ovPDHLk FV1hRtR15$B literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/apps9_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/apps9_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..845c3dfec10243e11dfda6846f920503134919b4 GIT binary patch literal 1007 zcmV000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-wX-PyuR7i=XmQQF^R}jX3_a!fhiTWB7Ef)WPb)h0nTik?p zQH0v6h!F)9Dk?&YbRq4gbWteME{f2uic%;QN|7vDtBd*vHzFu56#SERq1%MQON<($ zM)Ul-nD6?I7kxbGfy=$;o|$jv%zQKFWRhrd%mtPMJ)VyN{{Yoylv|rvUk7{$thAAK zuT9z5b>JlM7cl)Ipsc};HUVD%eLxL(XrNpnvm+fq3vdPa4mjGZp%U;t@G1Ro+ zBz+}mG|_(`X&}eXjkHO+AnCTGVM$dl=<^sRl+sAq8{C>rWo&s+9yT?FdHrVam<^@c$>oUxrs=46Fg}IlQL{a`ad(4`0dHFWr{rd){uHsxgL*xgqTgr-<{U%bq;3ck{jen#0hOc--q8bbCJA zq0PhIWz19X>@hI_93jXdqBw5=XNklwb`JlrBU^0zCQ(bPfj6m>p&Qr^{8=;v@B{EE z^?N{vcQ$E&7J|YVaF<}`49h$uNCR=d_!0Ol2Y%kccbG`-s68*9sxKNMLfK0YV;2n$ zzG+~my{S;oS$e`2!PA^nthOw@y$m_?I@6 dj{kLm{14K;LlNti;i3Ql002ovPDHLkV1mcixDo&W literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/apps9_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/apps9_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..9b78feb2c0025ee2a9df51e612cc8e4bc48c2664 GIT binary patch literal 1736 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 YFUgSb2O^VgJpcdz07*qoM6N<$f-`i1CjbBd literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/back_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/back_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..e138d73ac1000d1ef4d9230b347574055602fe5e GIT binary patch literal 1412 zcmV-~1$+95P)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-x{z*hZR7i=XmQQFLRUF5Ezn6KLKf8ImGueO$f?f=TdTrBF zX-P|xCSkUv6$KBiASI`QCy^ek*sDE=3YGRCC|Hu+CMJZow4`_ly$H2fs$N7rbvL`& z&d$F#^L`$jt-G5|iTH!Z!0)~Je&+Y)y)Qo`BG^kDIB=jeHa0e{l(GQ;7-Nm6PoF+{ z@ZdphFYn`vK;?2-Bcfwc%1J5ZzBEloiAVrlzKtuIrx!L2$O! zYQ<7YKdS%-2~Z}$Ik$um!=`CokD}HP8N&BIskmI zqoVow`4eFnUaQyZO+=)A2!5N=Za)Kyf%aI$G3q{oKmR%Ib5_kt0Wj zbGh7FtyX(oO6hlP7ZDMdrYQ=A!fycZ84-nyF;6LVY(6X$zS65fRTU%RO=A3h-)QKcXD676F5D}%6 zeh>uv^ZEQy000I6pp-fu1VQ&HAtFK{#Hiyqcj7pH^Tv%Ee*yrwuDjrQ-t~IDo=cJ> zAtEFq=pLO2f1uIrbUmX^Nk7Fl0ke+U2%cc}Np^z`&=nx?%A04mee0l@A*nvkYxN<I5mgw55h706w*AVfQ>V@?E-wBK08lEG#?PEN z^U=)A%y1mX0b^{(-XUVDl(OPDR{y3j0)Pe{Jb17qg!sDAXp9q)gs!_&EEfOboWED8 zRDJ{ia9#IUk|bX=n@uMSLyxhZ0y|)(lnOG+ux;B-w~9+dmtIp`~f+E2Vs;RFFM=rBn!+5pd28&iUib&CMDE z0AP&WGEKAl^AHg+j^lQ{Ue|*l_^MnkzXbrWxVZRhyWMt$5I+nL59>sS*j1dtVbRTvL`X`tWVysXo zRGQ7^#qRkY(8k6_f{5pZ5LX??5u9@?6WA5lndh8aj^hX+#8t-F`HhW@o->W}~1K>iKU!wa{c Sh#lSl0000000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-v_en%SR7i=X);)|>RS*a8-@Ci8;4axExQQPLok77sX<=bu zq0*?8iG?4HF)o}FU-FdoLe>0~a~Hq+UU_zI_R zV-!$lOhk|4C=Q{AjeNES9n4@yKEKD?_-tB74c^6b=;CUA-#KL8W);Oew&NIHMt_{6 zSscd`3N8HvT*3!9nGy7`h!rJw>y`68_!Q5osf>tPS0dtiL|jPyEh1JU;(SEhKd@Is zoQQ~DBVw(xxsVtu_1@a((TG@&h>N-TVmf&~BIY9Ewuo4Yh=qvQ6%mUOac4vvjEHa2 zS#7%>5s$U_Ep^-RwNk!UGtt}d3!cQTr0b+o6fNI7@D%RDo4DK(l{q_y2heSD;UT5E zS|{?^OMM+b<6GQ~+f(;ut_CZrlURomTkGhsfhwsCHgOk@;1&Fyd%LMo;S5SYu{BE7 z98fB!Gs569UR0{`{fuIgbQ1FbmK*F>O0qY`poazJhx`aXDfyYyzj}$izrk*$tqh~C zcJ>z@#2pHSvqn?aNUo8hae10a?6ZwBPtGV!b5e5uRQljPyk=`;43kLAGgxiuI%PO@ zQEA5(Rd3(~zEi4k)B&5s{s;WDGEe3QjQaV$sN`fxq2m!etx(wR8$95AVxDGe!giH^ zQ$00000NkvXXu0mjfm9e1z literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/bat1_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/bat1_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..2e53d9d2c0ba01a2368a15dc1d4ce9610a6f705b GIT binary patch literal 1486 zcmV;<1u^=GP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-yNJ&INR7i=XR!xW;#})owRo8TPO>fW4&PXV%Z;m8{lv6;g z5JbpPjM!+UoxLQ-BqSsx7o7q@7~6y;ArS0S5-`{%kek>YY2&c6jR)zHjYL2YfukHk zFbD;-Gp*^K>A&i(%0WHydbKO9$%DQ$@2jug`|ACWF$VjwlP6Dh4jedeRBPP=0LEDG z=+UG5w{PFx+7F(dN7U_hEo02Llv3xEQpd`&Y#U>203f1_b3PD4d@6+an20`FTU#r> zG*P$Py`Yr39LMq3(lph1o~K&t5`YFk0EjWhYqgr=I1ZCi{zC}y_S)LopZ7&{{``4n z+xAM5B;OCiFjq>&L06G(R#1f`}=nPg@uLh5Yac% zG!wsQ04%|Fe}%{4on zPU^aD!8xZmj@fWH^ycQ~W^LR4?O-rCQWQl##kSk+rfu6lSYKcN;3?7BvuA7ddi^h3 zTU$peO^Ap@v)TOY;lqbNJbd`@OdQ8Wy1=PoF;h zvj-0zyy1D?77=N!bq+vHU*JwG03=DGwbri!0Gpqm?iqzQbl`XOEU;+0t6?TGgC$(pnee@wk5Q;K4WV-o5*t zl=9y~2;01XO>140W!Y-AT1S~Nrd73-JwZeSrPP=)cINo;<6qHQzb>V;0I(Nund$-=w73sc=5m7)y8J_g7JtNBVJSofao2O2ldI`W`08IdT z7g={eDFYC&;c$4La~?3ptmk;6(y7yKw|{>9`t=nl<$pNmw$^&j+%d*1&Up|7!F{&5 zxw%!fdgn#rCP@j)t}-Q3*VViog;uIuimm)Z7_ zF~&qu1k18szj5QnRVn4)q?Gl&F6g>0V~l+WRE0Jkk3Vr;_nr_!PC-Nj&bd)a8P2(H z+jhfooCW}16vc(b#l`RDdA=fq0G`aKozY0wb?=SG<4=I9d-wbOd~tE{E#LRw9SjCZ zMW!vw@_pZj<2ZjX#vB4r0x+C&yH=~ot5>gn3;+uY3vc4{@-P6%_kEi&_Ex{&&w(BD z=+dQ2zY4?fN7FGOrF4DY--zS*{qcAVBAT`=13-A5$LjU^%Sx%sK@iy01cvYX9pCrg zxpwW^(=qXdm-hJa0v5j+3%17Z_s~Y}~OrtA02I5M#^|LQI#FdzNLr-Rt$%cRTO7>(lT2IdcEG4U$=JJ|GPl`53?ckbH-^WYybcN07*qoM6N<$g7E#{TmS$7 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/expand2_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/expand2_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..cb84ce74bd7438cd6f04fd223c83ccdc02d74b94 GIT binary patch literal 986 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/expand3_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/expand3_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..c6332c2ed5fa7eb77c8d8c8b2f6311a1c2f6d4a6 GIT binary patch literal 986 zcmV<0110>4P)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-wR7pfZR7i=X);o+m%kUD$w280pGSlIG&(@jrN6Bgv&Q;0i7l;U#?6{7oboN^&5{nIywW&L`PXd;Moc zl3$aIB-xl`L6U(atCJi`a<0zypEHFyltiyASf#ORq^yYv8p9pfhr7z-_izN?;7_c? zK`iKaG*XzWa7ED?lUUMOcjGU-Tkk_!l83bV`VmiS9VMf92rm@qn`PxYW#tzocUfcI zVr;Gb;R@kcJxj2Buq>H1DRdX`M14C`@0-iYt@Zn9?T=~sc(nfij>pQ_@xop-Rj-?i zkF1D7m>N!aZ1? zpREY>zxN9JbPq?%+8G@K#}?JSvxVVbEAbR$u;xnW4!L#d%(O3*D?H|)zwn%4za9q zcDW8_c0#`LaR`&^x;n^M$Ww{(I0ALN(%Zf4W@QUCw|07*qo IM6N<$f>;95ssI20 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/expand3_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/expand3_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..3f5a095d3402adfc74ec962b64a32e7ae5193271 GIT binary patch literal 1709 zcmV;e22%NnP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-zCrLy>R7i=XR!wLf*A+hZ&fNKXqZ!SNWMf>4TS#pOcN1Ep zwhLD#KfZRAU!`?2YPn(IP?c zB6Uq^B3F8E-W$!Ezx#8#nJ1o{9~64G!}-2B-#Onohae*C=bb!xa%6OL^r%uQ005wr z##>ukcW&Rly}h4!@>xVPGc!6OKE^qJlyiPuN*N)d2>?I{DK$-NF~;6!jQyDqa$|me zUVLt%nVFgIaL!-Ovh1rxQ7F!Np_CE;&<`M#Qk^koS(Zf|$605LU7DYt|Kq-hCMG7R zX_|9+oI}#y0bmWl7;`+&Gi=-bZCRGDT)TEneJatZQ>XMG2!7q|c4w0$ zX(OU~kbn>Z{g}Z|H6ispFZ6xC*>1O=zj^cKu9W&9i0}Ka*CbnvF-y}lXHY7oR4#mO1{l57LO?C|h#3jlunv5cmsrk*T{;_X(e)nSYop66{?mUT-A z!2kd#r8{L=eyysi)23-Q4a4XPA-+*n)x%kqRh;vppCKZWD2j$n)4Z^>wDcYT00jUT zA0IcAQWujXDG?C~A+`|WAB&5NZ!Rw{&n+)6&jG*+A><)M)CnPf4}##$m6espeBb{; z6h;5GZQC0t1J+m<$H&KwT_V?YPv?1lf^(h`LI@(FQp)H@oj-s6pkWyArfK@cEX(3N z&tKWx-2BVL#Kb$Aru|0<@r3XDf3+-Y2oZr0LOADHp64fA*FC*Uq?CF*&+|Q9(tqd9 zo%`~wTetoT0Iv@X4FMsAG(8J2B65rIdOc z0Dz8-jg4^5kJlQLem4<9k~3${JR+sMF*Y{#TC>^wz3aL^3d7LUG)+fDSrkRL)oO9h z`L7(u@ik5Rxoz7{jX^l)1?T+u*x1+z4a4xLlrpHz*e_%1^^(Xtaf&G98J?MuCK5E$uNu$2_br|l#o&eK@c3Jh#1sk z1^d}3rOK+RzM1Fw7dYoxr_+g(Bza+WcJ?RDX0zF7G+qjVK-V-)BZNR%mc6Q~zK)0r z06w6U8nt>@V+ZuXnjj*WrfD07@s{H_zq2f>0RY(TcH7-<_l4Qn*|}!3dBrr%i;m-% zwMCRt%5`10p_J+Yz{jSDP6&w!AteAb2Fz&*AvP$bn}%ULQxpZ%WGw)Ac5-r33LzXJ zgsfH2G)?Q=zkfeDeE6_mXVx!O2>>x|x7&9#O^Yd|yHi34p)AY#_Pu-e)-B8WXi$o7 zw;Q+H?F-#*_q#<=l!%D7ZM(XzuO2#dsDX$NAz}ppKq=KVO^f3=zC+j6*0$?WZ`Ec6 zAw*9~`9u^&4PDnS`My6402C1c5uqrGURjp8QVLAdYz2my>FQO>&P1E!UAx15g*=RJP zD2iH!VLW~C;K5NL#EV&$rF|URwkf6b`mSNqG+nW6dxJ6N^s~zIJW11ZYI=HlZed~J z4d3^t!Z5rZ1i{wu@NgQ2;Rj(DzJ-Y2qLdb#^FMSt9j9*-#+YN<_C}hfD*yvSb#ij@ z$+9fpZnat+LdfpK9vT|*UDv(M82j1XyLbPll(K{nc2N}Zv17*?jIpQ6vV5`A={QwY zW%U{%Q4|eZmUUrqaq+!9L;wJ1&z}8hk|aM&l4N^e5`$qF4coSvo6sv6Dnd`C(t`n$^Wyb;gyE?>QRb$3nd*+-pD=hYwxMgU+oNs<--C_)ISs;XC2 z6`_=vF^Dc*B==Ez>8v+oK zODTI&%2X+p*WCsEnuKBKd7gKfQu^HL>gt|DFMc7A;imBmYvw=ak8Q7`lW@1 zg{4oz`^(g literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/help_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/help_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..504891275c2f71cfc92bca39a8eba082d31c1c28 GIT binary patch literal 856 zcmV-e1E>6nP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-v(n&-?R7i=X*3XNTWfTYS&%JX;i<^~>2JTu!)=?wuNMUh6%;0qj9xw740K86EIfNLdD0Zpett?Ikn_fqyiVhugf9(<1Z6t0y_ z;eK4jmE6zZUR+aRSo62A9tZJFt!NE?QquQELufkRKg5^#J-HvW0QJ`t*uo2Hr%o@!=~_azTby8^Z6*AtN3QEEdEwvZo{Sywkm;L z8e-8krJfEdaomu~FXGz@@G+(4nzWSITRTd2tTo(qOL#b~?d9{7;=&8b^DcIzQB9BZ z5_|n>y{?6Sa&?p<-j6vvh!5}*uCIclt<=qemBrhnuF^Q?a{n<7HK2grkh>x1iIBy{xJ3#b;JF)mqVC z_)3|!PbE`@iVGJE24a(k(ru38t^SW;gYSe=D}TDX!M9Nv ze6JZZ_!jYMTJwNG%<2Kx1n;kI${bIOWfzr6E+;#bla0Hav~k9NyqwfDjTcOI-TGc> iRYPetMK%4e3*^7Qy)SrU?Z7Jl0000000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-x*hxe|R7i=XR?lx6MHGHBvtxU`&f06c962CCR45V`N-nfY zg{z9xiQQf}z@e3ps!Em05usi{s2n)-LJw4eKLE*g6556YwMq_ER4zqCs#*zw#HCUk zd$V5eui2T$W!>6N98&RayEE_m=9_uH2qMB^?D+BH`<002s9cYAyL$-{>a z+lTQd2NBilbqx_KLWmE95J#nyB}7aE01!e##@G(${4wYJS3<~Iv)PPany6l{pA|w} z^*rzGAPAHYB2Y@j05EVMlv0gzp2=h~G@H%-!8yOtY&L&B6w#S8XJ|T|{@VBb3y$MN zLI^KWK=uQ`1b}m%HBB?6>-vvj7=E#`vZ5vuojiF`vn=c8?(Xh6$8kCUpe7MaAf%>g z7W4UhqtoeJ-q_f9ewEtr=6pW?RYKBE@X06+FhU4RzGZTdfnWjv%5j`F0Guln3OfMs z`5r~{^Ye2-5d5&SvttuNa6p2HNGWByu1|5!dz8{HA~L0v6-ALA1c8f)a!5HMA}N(h zg>*W7ad~<9_H&}y+1Zp~7Tl~U?7005ntnJEh) zjtU`y@d)FbQvi4X0C3{O2_uf<%iG)AhU>c1nx>r^I@B{l$Vgx%ssbUz(V3ZZ1l+v;+ zYg$7@D=8~`N<YIMQzu>yA`(JrY2_aoVNC+>Ib6?|} zX9*#zckkYPmi+q8ah#8A+wLKvn&3|o?5@`7be@=|*`<`ef{0=g5h6-N%$+}f{(ax~ zi%}H4)9dxx!^yoz1*IBetlRB&pU} zB1w`q!#RJvxw+Y<3G=G1>+}FMkWQzk2q8BcjmB&c1od<}-KCTs_{O@fQ%dP7000F5 za9#JFuIpQz^XvhtC}Zqz0D#ri)u)WH{=k2NnyjwtTdwQg0~ji*)oOJv48uJ|bzqD! zme1#RQ>oOVQtD0Db>Hjv`{9I;CZ$rTkjZ2&E-fwH9w7n%SXfxN?l{h;`?LuF0Hl;^ znx;)DrJ^{F`vb9KBw(6m*)+{ti;IiT+r-En+qQkpvaB)yoO2v!2SytoQA)`$4DIA9 zN0baTzEVD)Z*;reYs2d!cf7v79uq2F(*Z=?k literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/home2_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/home2_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..7bee766fea4a2874e0d0259d5fc89e77d846cc3f GIT binary patch literal 868 zcmV-q1DpJbP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-v-bqA3R7i=X*1L<`RTKyC&;Dkz4>uB5vzW#{4~hSU(cmLu zp*B7cY(zvG#X=BCArY<8Xc56ethA8TXm72e5fM?)q}gah*=%;RJJ;fz%lzh-$>bM2 z@ME}h?)jegId`szjAyh$*>tQug~vsLtCEu6Ui^(m@np*Wk)A(`uhOga z#5gs9TuQ0m!=;qXQp$x=%K6ss`BKV1rIepaDMwrP?=7W#*gC(K@>O=Tlyai-t4H&A zRa8=qd5!5l{DKGYUCYKVGZ(`ahL-G>D5m*#=#Gi%+UO`*!8dpiKf9LJjq^~ks-YW+ zd92MmZd@f*$?f9&=2yvYryNP|c5qVfJ4&AnxX|H#HYE#~p-;!|zi0SYK?n(@a zxqy{vv#y9(cYEw0-o}OG-H8|QYfG+4;L9B&3`M7JiM({1v`zc*8(vJnGwE5|opH+uFc7)bG|wS z=<1C75_665_&6&{`jF`8kr*8Z#9G)9$zK$GH_ZPJh(4=E4qBcqC+1lu*Te~YB#J|V zUrCT!Q3K=Bofmyl3uq)lRdc<9C-7-k5xk4%Mcx{d1yT~M{ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/home2_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/home2_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..db6e95275e385bd0a94a6daad362a183d28ae1d0 GIT binary patch literal 1436 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 R&2j($002ovPDHLkV1kw#33LDe literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/info3_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/info3_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..9ccca9cd20ea26595b3e4094d2e38fbf7a6c7177 GIT binary patch literal 820 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/keyboard2_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/keyboard2_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..94d55a63d8f9d8608c448f89acddb6dce4661bf4 GIT binary patch literal 806 zcmV+>1KIqEP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-vph-kQR7i=X);n)pRS*a8-(K5sj1f^V76KtaAriv8luv*} z1(A3a2vZ3tZ{&(hdBEpoiis!JB?|)$nx27?kpJM+kUc(FNWHI;l)7h{19yib%2h^F6 z(L1<^mvM-_1ZoXB8OU+W;U`?iH`6+5@F~vY06Vq*kZx_fjAQr=7to*NXda*AJ*6!D z5#Zw_GRPHtjdQ9}Hbcr+u&x~NEKa0uKW*0&Yp_{m^cKFtwo-!mjIyJgQCB&Sx&-^V z)&|^B%Ds=1cpu-^j*j66g}!^ZiQDO{kB9Iuepe1Y^7ko);=AdrizjeeVdoZJ!GVYn z5pP7qort&@5&uNQtGV9E-!l<$X=tqz5!WK((R^>8HzVTT#JZE%cT+xVz>>)H+yAO^ z)N7F$41bIDx%LxVqkQqtXZoFdhDp*GO^k86?cQ!;uQpgyD0x^Z?;N$YQ)N`k*iMjg znAmIc3Og1JO4q{&crn+zcm`+iCl-{lEht^1JHb&uF;0%^b)l5==~U|Bait`4`Lrdw ziofrX70N+wD`j~wBUr!&eysFP;ayyx2DFkUv9}v+D(z;jQg~pKKco0VIj@$YkKq@Shh-N} z;#os2sBWrn<4c7c$J0qGy#!gBBBO~-wUrHgY;X^lWlS(A`Km(wPuh)9gYOGv@ZI+R z2Hzvf;QPpg!Pmow8O;fW)?qyB>b>Q(xtbV9+S4?blb4jtCS6V%{A|X{Ni7R_-E`Nj k?@Z`>_i|LreO(~`16gAr));*jg#Z8m07*qoM6N<$f_Eo)7ytkO literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/keyboard2_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/keyboard2_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..ed55b66871cddb72d97e0cfb062093b5df2ada9d GIT binary patch literal 1251 zcmV<91RVQ`P)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-xT}ebiR7i=XR!wXhMHGJT?T)=`yF2kuBoHd9kRYlW;8yuo zr3z70626iB`1F3*p8!J z+dI4SIAquP!3mD|POF`n_s#p6?>%H@=m)oN-!2Re4i0Ipvj6}@RNvp<-`U#Qs`hgp zFC!|K%O*3wr<591O5F^@Fwe|M002bn7>02mgxD5B{EUb%DwRrbWukJqJfW0&3p)hysR%Ix^w4_nayUuK0G|U-)uH(0H7}-xPXux$H_@4 zf2h@JAFZ#icSC8O-Ylhj5|LCd^P(3J5t&&>XYUUT3>*N!$N%zZa&q$hPN(zj!NEZT z5d|WehzQYo$jkvECSz_shEGHm01zDK4w>24TKoBYeju4lK3H5_{IN?kGBT1#r_(=G ztJSvv&_85%oJUci0FC{1TUGn1ptJIN^AX^>$-0sVxmwe zymVdn-skj+A-;h$KlgZ?#OG``ZQ8>6%D!pS_*3{hG+>_X&YuB#f z#KgpxdwYAIZES4(9fxRibo8DOV%GD#qgJamoXKSF0>Cl>0BEhp+U<6?O0?GgsRRQe z`daHw^beRBn$0FNvr45>#zlE+wOU$hJq7?k#bU9bl)9;uY6C!=d^&v~3RkbfK&>^M z`$utcD5cs;shh=Ou|T<8ZYT`Htkyb+!xF!p7{2ej%VT#J2Nx$R}cguN}V90Tb}2s3z?3ip9Fxc*<(cm zz+eyruQPKZ48wqkUS(zk00RJw=$m}s|7Lf0w{Zzk7bYUs5wQaRX#iluFcL>cM_;Y1 zto#yh8XFtCA*C$O&CPw^kI_@W$abA-wc3th7(Aj^jA9MD%cNZSBmUa^Y}NDwQUKAb8|? z-f*A8$#14000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-v)k#D_R7i=X*1e0AR}=>D-^|YJu5Q#Ut45LtR!UY$Nd5t_ zQ$a$~Xo`F_0TC4hNtZqd7K*SWLeeB^AqtCMl~^T3ny681EK){gC4Q_syE|iX&YO96 z7{{5-fm_`7-t(NV=bZOeTCJ8oWgXtbMD8EqE*|uwT{D_ z?8u%OE3C8_~FK`|2B*4Geh@1Elmogh$a1@Wzv1VdV zS4GEf#cX=pLR~cEJxpafe@&w|FfAJObe^5Y9~osm9j+wiR;;UGQc!ZSbfJ;}AL4vQ zaiXIZ&CLHoI0Oo7LuzV}O!l%<*2M;4MMdcXQ3>*`ai{AWB!M38u|y7mr9!EBAH5oc*Fkburr-*o0q1Efy>t0L7%3 z!%Qtx@(Ak_xai=~^tgqmqT6?9Py9u!PJ=_a3PZ(I8A|LsH8C>&!bho8Pw#%mhLZ6y zLErLlY~ogFKP&obMc!MH*bfTtE{lFBls^|mzi+U~&=6@}DNi_PuEQ&x-&6002ovPDHLkV1nxmeP#dv literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/keyboard_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/keyboard_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..725948867813a800b64b7c287fc8c3f601b48c00 GIT binary patch literal 1389 zcmV-z1(N!SP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-x=Sf6CR7i=XmQ83~MHI*XbLP%{Z{ADp`%FYd-DpFh#a#%B zgchyEG$pA8QQTNmYBv@^M5HTm<-)E6DUDw{7rxL~4Q**jK?vEnu(VbM5nMGd@B4ne zxijOUH|3>G+C&fB)!cJ_^FQa@a}TrDVmmfIK3*Le85uLilmLK;nyag;H&<3x>f7;W z_XEw&&N|lG7nD-ZE2Va8tt-~r3;;03V$S)R5aNaq;u2%*Vy#w7b_|-Gojs(KIvE7P z-YANUQYtdWBmmYO7!f%_h-@~SrCcues}SOJtycSCTcCpn4^k$R`6LX(H#(h8Unv!& z3fN`=Y#Klak@Gyyl~R5g$MHvti;HGU(B$N#Q!14{Z@1e=I-O1ffY}PL1&}gwSZk9Vssa%` z83X|*qHMKV{oVKdm#$p7(sux0XlQ7E5CnVr{eDZ{wy%W{t6J-ai71mKNzZYdTnYwb zj2mMV5oNU2J^^S2f{F1?~=Y!>Yq4{ z-_=?lBBCM@y~!AR%yr#oT-O~3FeZd}5kQqO_BQ9dYOS5@_xm4MYr6p201!oyF~%GK z0GgPXs4As)E2W}=4s+u;R!Nfl*>1PbGRDGgxBHzjW<_iLa}-5Can7&bx^?Rt0AZ)o z`6@}0UzAeHS}Ri3Oeqy9rFKtDOjMn6xjYufaVh;6F;J5rilV(z%5RlYT1xq;QVP~u zo5^HY7>1@;EIykgiFRFgE(ikcI8Jx4Ta7V^*1A+GmBz?gTS~{uJtHEDBCfUWwA=01 zv)Sx#yM+KdjIkI%eiK#3_kBS`v&NYB9LHH{ zHk*QT&a>HUUn%uCfU~~u2LLnx+T^k^fTq)EG;VsH*Ce7*V~he|8Do}+GK?`7fQ{qW z7ec(OwSI1Rc-ToJ7y!e*@5kwdIT7)+Mg{~RNhw3Eb(b+Ft+iGNkrhJRSYBSP zJ1O~sl=8JGijX9U0r0BU`jYFqe?REQNJQ&7f-xqx)*kKm`w~Dbr6eM{0Hi~;*Xv!* z=kwQm-`}N_^4sn96OQAY*ra9;GN!dwN~zFw-Mp0YTCdl;3=9m_>FMdIIF8qcs>Od8 zsHs^1tWv2Iv)SyibLY;T2L`%iVPWCClyc7Vyh@r1%NWBB9}57U=T)SXbL)@|AOL8! zTBizyLe2BM5o;~k2Nh^g#%&|d^F|7VLao(mofL1>oZR{QS<>t-J02E|C8M(GA#5_HQqA00000NkvXXu0mjfRQrgT literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/loading_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/loading_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..684a670a190a00e580f7acf920303d9e7aada98a GIT binary patch literal 936 zcmV;Z16TZsP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-wB1uF+R7i=X)=i9_QxpgA-}^E1n(1g$W5mbOLfQ&tiG*0u z5RphMkq8YoYEd>8b{2GHK_VnJwerzqO4vxO1!;>2izX9fS~XMCc0RAgId`6?V>;f6 zlicKao_p{A-2XZM=bYOqr5Mttum_X*eilDqc9_lmA?6R@0o((jG@jDa)mlnH*B6^u`k&yB$KgZRTASM zzQV^fA2PNtC)k=u@Ge{<6nCQ##Uwt**LX1VG{A_ksLq+6aCWx$Y(A0J}GWjEFdYi(m77JJuD_zFzWFF||apPAbxn<5mulB1JYXK|`hJt-tC z7f%b3d@9s8jE#wcdP3x-G^+p!G+`EiBah;}^b`yKO zGK`A4v`74K15qKC@rMw|eoYVRYh*u{-*+ZX4c!jWf$zmqWw9ih)<9EU&gc6vJcOBK zHjAH<$%LpLALR3*CO?D3Txv6_b_CCBDtJ$*@@L#3itKCnLKN3kP01P8l(8wig%>OE zW{vNCQ3%iE#@enI5^z4BZ^-#x?yUv&T2Y{%)M|X2welX`uz4%5hpFLhTf3FNq^XZr zbX2WgPHxMSZ*@88;(Ob?oV0C3G`L}|TgQb;H?{wA)VBY1f&2$TH%;EJ`dY~V0000< KMNUMnLSTZq?y}2P)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-ytVu*cR7i=XR!xW(m`}Hg9|r`GcXM3qPt&ECXdW84+2V)jmQK-X2ckT zQON68uj{?KRdsLOdt7wAkTgzD2hXY~IOn_PeBZs_VMGK+iBqReEgw5}?6`9-1pq+A z?7@QvcW>RgH9kr{I}B)JV?z+pSBx=VHpV<_t$m7!d;kE(Sj{=#l~Uf3Qoh3&dwY9( zyLn=ujg5`38Dm~hO085?<%}_vbFQH_ficDqQAjC+AP6vuqW7efuWoN||LI6T=g*%< z-}hfG%ksNGwXCZ5QgCL_od3vL zo44H(0Jt{ya=+i-1%RI{YUASL(xpoms;au0=lO1XLg9Jd%sKb{;c)m%0QfEE{OPr| zwa;9+awX!NKTAXw02BaJ0Ki)6AkXvNs;aJDym;}#W1~BJ_N>?Gblw_|$IlpJ3MpkE zrR)Sjpo1XzVYl1;%VaY7nNsS4=Xw7@#CcuUpDv1`27m<@oQQxi21Gv;Y8zQ_psiPkzU%Q90+bs1wl=bUDY z0RZrYSi&&0P1B$;h8bg2S(Yc_IDQTQh6n)QoLeo+(g6T?o);nFn}fk%vnZM-{(`_HN#04*^qdf4 zlZZGGeJsdgd{Ro$@Au#DcDos4jPL&@9{|$FiZI3`BHr8F+xpL5Q~ zh`5mZ!w`(Ij4@U-#yZBBTq*VKbLY-|sjlm%wbrxtA|6iAJ_u;7>*;j*MItgp)Bpf7 z#%ch_a594tpYkBG=LP167XLqx$j&$2ALi#t0z z}2^DH6)-}i%VxBFTYMRyRgA)-&*zkmM=0PrayBF_1uwS$NR`xh3iwT*M`^F(wE04xzf7>0<5Hvrm4 zbv~cJ+v#*}7e(=mF{a4#{IgY6z1cKP6UXttrIh!|vRo;O0$Vk4BB~J)<2cR$0O#|0 zcRHP(1c1glXFbo0!Z5r&pU>X~Xdl(lXrviquOvz00|08R^=vkq6Ok8&;cz${ej^Bi z4}}n6k|g6aO+OGqa3Ms;^Ssx6-~YXovSY2)t!=O*Nqj_nWi%RTfCGNCwzl^3JkP(k zunEpNkK;Jwod2V)>(5zh`$>}gqAbf15p64_Y!pRv0AOWVM%G#f0FWffa*`y!xpwW^ zLz{TakEYY|1%a+x4O-dYyCr z;?~xdJrrmW>+9V3N9b8Us3n5+|3|6L&e3pH#=5_5(z-T(jq07*qoM6N<$f@<{SIsgCw literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/memory_card_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/memory_card_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..bc053921ae77c7c1bea1e4e8140b800ad751b41d GIT binary patch literal 875 zcmV-x1C;!UP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-vFI(5Z#En5CtLX(v@2)wyqUauxhN5G&9Z2xH#uFH*eky zQ#>%d%)R%V=bY!BkJ}rM$EK7e9KmA#{}Vsr@-)h`Q|zC_gSaa}=5nu}U_an1tYT{~ zL%j(RJ%-nC4~E!GLq(yNjvT-YF5pdkHZ4$tb9f#Dtk>sTXKUqo?8m!!1*1tovv?n; z1T9U6@fu{9-(G$jLGLGcRz+p|j^4rweov)!L0KDYgoC&x&lIqcNRAc!ftR}?dITS1 zO>lk%Po(0$7T5?Ig5pzYR25kdhwvmmuOr%z*F`233O4W?&f-p7tAGxQEIXa+PYJ4P z8v7!dRxv0*Cq#CwwLCw7<=nekt@m&o3wSOKKc3E&{q@v4fiIfeIH{E-6<|L>Hml!8 z()B7{N(zT|%P4JYM8z+svAr^^Erp&<+@1zUE&X2FT*gv^qar1{JnE9VVEec&z3$mr zSJLJpj?Rkgn6sO@NgxY({vSMmM@2G>1WQFmY5P#UIF0l~hQ5Ihaaa`P8GIwUL#H$% z)A}t>CY>MRQ@n_u@t)`=--#@3pYLOB7MDcWx7tZxSGO&7vWQ>sFn$#UKG&f$leRB4 zqVg|_B5WTV=lXnp%Y_d_FZ)T{(S0HVyL2z&a-nP0Zt7<6x9H;ci_TG6(N&SH-{KwH z>D`tlZC`IeUyFHiL{#)O(J;>?HCwo&GWKseaZF_1U*axG9gUNP3u*g0&_E2Wk3`j% zyI9G{B=~yjoW{KgHWWkhn4qud&ZW%(yXVo{c)|8NV6Q=UQ$|om$U-_&y2}#I+ha_W z2tTmh`rB=#fYlTghf3E!EC$~*s=?PzfGs?o-rOvB9#_AvC=1|x>YPs-J02?2JWlS; z$R<5b8hq~tA1Af!!$YQfZhdLzaJ(U)TK?Aq@;{Kv^R@?b1?K<&002ovPDHLkV1mz5 BiVOe% literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/memory_card_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/memory_card_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..2ad7cf6eb9b233ce8dcc6a5eed111cded25448e7 GIT binary patch literal 1464 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

  • a+@0sh?#>R#OfK#no0B~=6d;9CJTPNlJT_FDl;6+?X@tV!~00000NkvXX Hu0mjfoAK{u literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/reload_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/reload_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..047e63a879470e855ad1bfd96f5d1f4a7e0e1903 GIT binary patch literal 974 zcmV;<12O!GP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-wNJ&INR7i=X)=i9EV;BeU-@W(DOlNLsswqNz#7EE)p^@kU z5fRm-L`0NsYT=_hVNoIx3l`#gRcx>k^$|o25*FP^EE*NG-AORjX;r1}+%Yrez83Fu z%;}kHdc~WZ%(-*k=l_46|MR^6a~dfn1FqG$1gqlr5$wa^L4u0`o^QkkTpA=J@oXl@ zzQd;&$6x;j)L5dT+pry%V;+A7P#MsOM3$k2Z}2qUAC#zx=W!oqF;(4P+glB8V;HaE zA@r6aD)1Walx6Al0k0D^D)&uU-krEdMapI^@EL5D8(b$@YHCJfZ!cmu2Ug#TZpB+T z+9y+TFUBwzfWz^30()>Hrb}F`#9jEHN;HgJ^7u~GNE%pyy?7g6ql*i03$Dg`Jb^pV ziMX~r{?}nvN=Zs-Q%b3uQkqC99f)fpu1-qn#gtMz_SUZrDW$QL(qn;9jqe8bKRw#0 zHYKrE;5|GTmEMcb@ufU87t3d;iAJEj z?1|^i0Gx|zAC0U>V}B=zTNR96#I8J%*R|wB*NMssS?X?pF2l$85$j|>ob3lx$meDT z%WGA&@ddU;=JT=dS=^2x{31I*2k*xJszl9*Iog!Z$B|me<)$f2;-K8i=Ws?OaR?6t z$@RFw;vTgEdv76I#`n0gl1({1)e3h7!4-H1AK^EgCr@Cq*il9U`*3-V#w|3v`WooQ z{R_A%_C19+a13|LJvzsN{nS+%r@sXql>0RtVB7IH&c<&1BoDzwxKQrFOdlndt5{Io zRCmffnZ%h<`g8z|1wj#2&&X1j0Hq?GkoXi8Q?0%xKEw{3B_G0l@PDE5)|LX(tZ;@_Xi=O6A_y7O^07*qoM6N<$g1_6tD*ylh literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/reload_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/reload_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..dba70ce33fbc341a548f2f5217a054bd3e6a1ad7 GIT binary patch literal 1646 zcmV-!29f!RP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-y=t)FDR7i=XmR)EZ*A>VA_s-n;+?~n7PVHptC9B3$DO&S4;`76;uwdXx0&Joe{(+WIfoGup2UtHKR!7%HFa2P9RUF6 ze6YE>d1rlnz4s*N+2cU%cH1PPZz!csDy5E;W!WSm8vqz%nPC`PLWmE95Z4)F*E*d} z@u@-Wc6(MS^}3YuSem9bUIg`2-Iq|xNY0N zOp@f4IF56rl&m~pj}o9tKnURlL14MA`*xOP7gkqS^(TT(oH$`dQS{sG?d^p)j{5-g zCjkz?Pz&gz2=-VA%vrpN&)CN zj(Y$WCMG7f0KD-rkLKp)UP{yS;?~yIkTEtcN<;+1FdWOWT+=iaV@#K2Y2|sYg%BG- z5d1?*IkU5~lU91H*=$bOw*Bhz^76_<(9Fz?<@^3$dcEEkl~QsnTm*pmz8`p=cSi`( z(OSPxM3Qs(V3e!Z{{Wd)M~XC zrIbgNQp0fw5g`o2dc9u%1Aw1(yInaJwsio1YPZ`bhr?k%ilTdrF%$S-;V7kKk|alK zwc3jSR!soVTAxaiWM7pK5j@WeYPH&xZnyg*062H<+_#FNSg2$6G zK&#cNA1sn2NwniQrvR*))6>(FK@c2KN~Pl!#uzhP*X=8%egXjPcKglIX!N}-%TySK zeM8xdJjN(O*yt<`WiG%U;dJ^*H#W{oi>lv2I2EVmhB#{LYD4ItWgj~-!0 z6%y(DehNS+r6xzCk(5$y`@V0xuKQQhG(Sqy^vgw294U%IJ?f5g#@K){mSO+pgkc!I z>$>kY8jY{pwtXs&<1@qI@I)Af9oKbj%d+ZW820l#f9>kks~3b2TZ}R5fIh3V2WG$D zzY_$(fOGy75vje<5fRJtTwc0#=>Y(=TCEovjmBbmSxX!&fjB<{TqNwM9(Ruo|95$MNwqqO_+$Z5W*jCK@Xei z*|TR~%ChY3t*xyGM6}5{|BPW6j_>K z!P&p7wf;zJofwAk*&qm>4a4xygTdgsDDdo3!c6L;jWglv-?=!~0 z81u${P7_g9!Jo2i`}6gBU3i{%(J+h)moHx~9}C*E`T6;?MNxc5O8J#EO)1aw2U_bs z5$){|9_PGaS=N-}IL!0B_e|6L&C=4+@}u+~yKc?T&zk`D)~zpz}4+UI%b(X=&-xuUiN0|6L&e3m73whZr775dZ)H07*qoM6N<$g7Kjr2mk;8 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/rotate_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/rotate_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..f118b16b57fb6557fe949ba03872ecae6c0271cc GIT binary patch literal 898 zcmV-|1AY97P)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-v{7FPXR7i=X);ow@RTKu`@1FaZiKBU#OcW785hO8c5lCSZ z6d^i@k4mvo8xgEDg}t2wO_N3&ZA7$5AxyNeu=7z!jEVRt#2^|bnna9o?#;|ivDVJ) zxpOnQAqzH~bN1Q)TKnJsT5Gq4!=VXn7CW#t-~Yl7SeRsSXM*`TJc?cEWGd$t)7kg< z6!W-vC7{+iJ9-+g;{hz;{{$)vS{cYR+Bk|gad=Wk4c^8}=;M6-|H!}f;u-YtE?&d( zdX74H56=i%mahO_c5|_MA7+qS@ey8BQQ3@u9Kf^UfD6Dl>)})am48|p*g|3)s29|Z zp2W-fV>`d~F&G&$_!1uoCEk!h)qyP})>8$%P}jp3LcWXm6GsxLEFKC$Y!(We!FKGy zUU8N+jWa_2d(kiQ-Y3*`CY}C`yYu^nYS&Bn9J_I&ko?E^9naz4ipKMaxeuQd>gKFg zNuh2a&Y_G!()oCT+=n-C3_qb;?OtNe5oa`udo%L-@LSf3p_RMZjJt3y8F(09<7TV# z>_TGCHrOd7xn!-4%jV*2AgaW-_y@n?P(Bw%mJ)ksgDtsW*?8*+O4>P^>bWgc_p_ky z_5?0i%Za_^YPD_}-z3P!jPO_$@la5=8+QmX4UEaZPEIZg6^-tyjgx}sdxX6Ec*ts6 zd-xUa;E@clREkBMX>dZ6o3`=R&4pbn6m~~OC!K8{380|Gud_Ph$uf}?P`u{yRHl5 YB`J*RAcSQR2LJ#707*qoM6N<$f_CMh1ONa4 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/rotate_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/rotate_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..9dbdbb7635bd7541c9558b01920686de05dd0728 GIT binary patch literal 1546 zcmV+l2KD)gP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-ygh@m}R7i=XR?mwZ#})owRabZQkL~%fyCR1;kU%VpC}0wh z7eb=QI7W#hX-5Yia*7SPX+z+(Y&uOhswQalVoC^Seh-%LHSP1cv5aLfnbbD)S%Y0#? z(P;Ezt@SHqS$?ysDyy}wthENf;sPZLr-8?ANODWIbOTn8Y8h|)Cm!!UfiuItxs-n?o5C(+rnXT8B-@Y^iQF6Vi^55OKl z;GAxfdDWr~&rD;0s^?L8_@9+Qo?%lfwq4bs!dcEGSvn;!uW!YXwK+ZW35tbba z!_eoP|F^2D)EMIt(L%A!^L!7$<$k|E2Jp+zDY|&^;tN$(T^WzZQy~PCQd$5_(=?>D zhLjSVb1=qwQp!L3zQ3cCdUZOTHpZB;6HW`otE;R1AP8Q*apT5&2Sn%2o%7>3{=?qh z-jl|drr+;>nk30B=iJ(KI;Em0FdPnD9LH4<1pVoB`o}N~ZSC*#`TR$B?%ZiS07#PL*|IE8H%&9;ocoNieXaG^@;ra8X_}HThS_WeYi;ZM z{@pZ9pKh8avDTgo2JQ&q7c^F?{Uumnk319bM6-Rwbqr^ z`qak8#u^(AhbP;%9dyNbWSJ}<0A#IgjWL=r=6jy^0q1sVvLBE~TuJBxz=|*>~%@c1y|QCrR=z&-1Qu&c6>p zc39M5PrUv8{fB9qP8ee+thIVsk#i1pT??g@EQ&%n=h`p~xl&3frQA}YctH^OQ52mh zioz{L#N(V#CX>lSwzIRd*R}eE7XaXV-xom;M8+6ttrc+``(YSHM8t^5Ei&@Z@s}}# z5K;*7(az4!o(BMov0Gsn{-mm^g&Hn|xIG*W|5+5p$5P5CIOl&MqFrMQ0q~u3&2qnW z&RMPXc#&}c5QZURjNJmdrdkxm`*9rKpU>w{YOO0{%$J&`d4_XNQp#N+#0jnSI)I)r z<|_aK&+`rdiAXTUBx7vR>zwcVQ5c5zi=ucRSZb;lE?jt_uInq~@p#G@BhGoqIgfh1 z-YqHRZe7<;bRec}+eeBU0GCpJYOVd-d_Mn0mSz6x>S`*beEItI>+d~61OS&VUHVO) z=RfPl1c->maa{Sn|H+|jJe<97&cPV7qLexjhT&?Orf*%lcI{wHJW@x~>Gbu%V6X<@ za-Qd7=bW9-=dvuzlb=IAf(QUsR#wtpulMd`GI{+G=MInZ(P+f2wQrPV`P12Kb}-6u zL=i4H0KoISC{0s8ilTRf5U*XmdbNEl(ZV)2H!m1tUMb7+^f8x{`<~~$xxKx8<0!nx wu3MX%n;w8;ty=(YZ*OmZ@pbF4{l5$3XA0Ocx>s}K_W%F@07*qoM6N<$g7`G{G5`Po literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/save_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/save_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..8bc74925f6701442a8728d1cfdd18889709f8bb4 GIT binary patch literal 839 zcmV-N1GxN&P)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-v!AV3xR7i=f);*6EWfTYS-`qRw)df+4OJWCB@{(Zu1Oy9^ zMlFoeVWY8B3r+k4#%M<(6l#Z5Y$93Y6PQ?GBA8eZ3maKs0|_j{nttHv7_z_Fkm;_W! z@#sx_f}_~P!vrb{RT}aXhWG`aBs zngoAbBCF2cy|{>XbwW9wqc89d{=(DgU6a;LBCB#=mHTcb#^3m`&!gAzJytM}%Q%Z2 zA_v1BvI4##!u&zvJis2D#$wl_IeaQAsS%a+Gk(Ie_$EEv7WedIRfOptUcp-;uWO>1 zmatxkPKfGS(Z;)!@e4SXMvW5<6L4P=6`d-{jwbdGgIqY(15zri%Ku$zQE6+~Wx7}UZ7=bXpFgJP3=(^##tqSK_Dvz$CECi1sYsl?n<9Vr zC+H0m`^G@blj~{iq&721;AilhwquX-w@;eHypH9Pqb2{YsRT7FZUsk;d>Or2FcN}V#Zb|&Ukwl~!`a6uGDlLU`C zVJNMs(RS-*Y;7)eDq~Hx8?HrsEjk6!jfd%Vt(~ZIw$Gos^Ay9LPpriP-Z%KZ6NB%T zh<_=BlJxEdr4TVtdn4Ol3(+Lmy@pSz-!v;)`BQ&BCN~W>(&)*j-HsPEC1;N`468q-2xM` Riwgh%002ovPDHLkV1f{@h$jF5 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/save_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/save_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..325de0c61e5b4e8c0c137b7b88108395d446aea4 GIT binary patch literal 1371 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 Y03#t*b>;=Y5dZ)H07*qoM6N<$g8c_ES^xk5 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/sett-big_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/sett-big_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..a3438fb1ec68ded790b18948d3645404b51914b5 GIT binary patch literal 927 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/sim_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/sim_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..06120825bead13c18d038dc709e6c7bb87025012 GIT binary patch literal 696 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 AE&u=k literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/skaner-1_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/skaner-1_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..baf70020564cfdd59dd74f92fc7e9c619d028028 GIT binary patch literal 1238 zcmV;{1S$K8P)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-xP)S5VR7i=fR!wUhM-YA0GriNjyYBU_EP_eSF$U*qbTcxE zF*q`kkGaK{IDvqDN<#1{gyd$EgL5!({y|n)F$gDs+_#kOl8tu-h<~`Qp&sCZui%Tgf3scETSm-Hciuy<2W8!Ym@Q@bQl4b z1X9YnF{Y-q{yER{ua}pX{gFZ!E?fxP?e@Lx?d@xE9QOeDqXdo+6vmiNtJV6Y*Xw=u z?Af!urwqrFTdmeNrN~CfKamKqcVi#N@dkivCr_T-1n^b0E-G;K>eVY*mR*nIc=Na- z2le7O-psP>`rO>ym3>09v$Hkt{jE5TbL zsgyEd7=BT!)qYn>O^0FlU9DE@Dy2?KDepy5^plkGL}jovO}+R25&(#qnVD18+OyW$ ztb7szzA%9tspf7|7$J!Bl?`^et95b`Su1NsEVb>%mzx%qk z5F!kMpx^KJUx~G~wT-gXtLn7OER<63FmuSvUMcl90L9FOl=3uyCNn!B#9IIiGdm)h z0?=XRqC5~wDV3D+<=WcXMp!C8)>?m*=Q)VTCrP5c_dn)&9(eCZ0Dc&aMnO>&F*ASf zoD;T59s^}(7z_qa8;!<`;c)n_wKj3i(az3J zjfgw|-r3oyVYid>U@#cRVOa=291iy|Geb&Q*IK_A3=A0AOip>5ba?&9L& z(qVjW9Jl7@=R*J!javYoEG{k{f8074|8;=;3zUzKsjyrGegFUf07*qoM6N<$f)-Us AQ2+n{ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/skaner_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/skaner_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..dafa465afa34eff1541dae0eced6a83c47d5d0b1 GIT binary patch literal 783 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/tools_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/tools_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..e7eef2743eeda3c9002a500aaf39d27149968309 GIT binary patch literal 1451 zcmV;c1yuTpP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-yB}qgFI5VKegsOz3ce_m_9aj$g;FSSV?Ib&iy`7e@TFh_!KV@^^dXy> z&Ft>%%-lQo_QBmWiEfPaJfCxZ=XbtQDFu6x2qfn`kWvZ&=ola&M5mM{lgT7WrBZ)VN^h6T<(WMJ<@0%B7{>Kht99Pbkx!j$^MQh1R|z1P5WnRYU;bWxw(s$Wlg72DeEO8fdHU9 z&kL1OR|f|N6Pu|^r_-l=-#^SbuK@rWhM`Q;{7Xu?F9?DU&YU^(gi`vclyb~4jCXwB z-wy!1D-t4d&iz)abvT_)p8|k+0stVTJl$%wHoL?y3@W9(oJ=Nf5<>ceAb3O9^|Q0H zvmPQg5s~ahsUxjcOG+tE0|1bLfq`Dm`614E&@QNo<2Y%W=4-2~s}q)G{bpI#oRsq0 zd_Lc27{-2G*NJ*r{+_W4IOm531_pZdY&Lr!3`1K=DcYTeQ4|GAsp|(19=tv=F>wJA zH2{c}QcxPf!%bX}(*ONUx zJvycIJ|gz&y3U0V7iMQ?Yo$`@NEn7cxvtwMgx~-`q?E0lph_vQEXy|xW2{@Qk#ion zuG@4RXSiCe9&sG!JwnJYqobp}<#PE6A>`v+F86mfn_abSdxbHUK|~$?TT$DDAfk(i z;ZFLUmBTr23L#p)@4K~H?Whpq*J82QKQlA4vbMH1T&YxsE0sz!T>8NlNL;($Z3uw2>>OY3^kzTup=I?ASL z5<*A?puK_`jm87hG?yu*sohv1A_yT`K@hwfuIy?(4#s~wG^ zNCJSOl%`D6Ty8WP4>o}o78W8zyu}zZ+EMR1jP-imYcv{{3WdT~0PwyLA`!>2AIEXf ziHR|05JGM(EG$F-JMPiBbLVb&o_BG}ndrKq5m8Gd5000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-w9Z5t%R7i=X)=OwzRTKu`@1ES;q(;$8jdtKf5Nlg)1rAU{?FoDObsI39^iaC?#GP*G7@KV0rm~v z#!*~cNl|MRj~>Q8Y{3F%Ls2Qv3PVOQgp+s%Zwv}l;CVcWc}!RNYrIwAF?4VUd$G70 zP#Z7f5jiX+bF1=Av6?^&IlQl9mr5v$8uI}>Dkr!E>7a{C!jQ{i)jev3%v9(&u#!hR z@EXol6b$2cyn;{hC$7QcxJS;-Tn((GE*`_1*`$=DlsYM;6Dg(hDWzXiN~hyHlTz9p zJk>QC{6D0WW>ZQRQcBbD{W)aM2Tv!Zv=qAge!0>PV<+Cj zrJ-v}=w9lh?P^sb_sb+sH2~dz77_Y&E+(R8XA0^#_ zcN+}24eRB+wL<46jJL5-F3E+8K*HZxhnH|&fPE&1W?n9iI&GD!b2fk$LifhDTpc6& zLpOxKa0Vyvqg>KE0{9F3Qv+#XTg4lpa|GR{yDrIH{yv_roqdk0aXXITWBd_&>v3~L zVi^^3-^}T6-XVO@z~99Uco5Iw3S5itaa_)8wTX++eXcE6)mdB>t`=eChYdh?#@R2i zCMsty%6Y7MG!(i|74nraS+QmmU*bEtAJ$d`x8aip1J>Yf{gs-HXESpUQeLjHkU1DS`W`BS zJWe*to~`ycDe$%b_&BN3Fdi`2bL%b56*&-4mHyWQ@?Q^0LF~}&5EB3Z002ovPDHLk FV1nEGrB(m{ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/windows_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/System/windows_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..e2585a5db37a54edff632512cc090a98a7080052 GIT binary patch literal 1562 zcmV+#2IcvQP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-ylu1NER7i=XmR*P(RThBHxpi+_%~A zhz+|Klg-XfW=t{@A_+_ckCN}I@t7w$vVx#xWM+kNYHErT(O;yLJEfGHl~O}QWB~vmVr&>jTL^JY2=Or@ zel$Hjo&I9b)YR0|Qp%TtAb2E-A}ytiwALvAtSBI3j0+)b+qPM;So}r^acp{e`rMj8 zV`F2?vaHv_FnreYyhKVFWFFw%3{Yl32vKxh*DMqY@5XU_bar-D-xIWL+csXS)&9A> zyu8ozyd?n0FUD*V0MH;f12Wfj>y=97)Y8(@iMTLPOV%nADx+*`B&caa=C1cj*gz|^?K`~D7rsMl9VxqoO4o2b)zU^ zLWtt<@bE&v-ygqt@nXUO07|9OjvxrONGZFyvuCDh_O#ZY4hF!^ojV(rW!+Rt{mnGZ zXVNs?!Wi>8=l_YK=&wqtr;{YNpUmXtE|eP0ehKx_SEk|YWI7=4u4 zuHEsDRwSlr7CGm0Cr_SyeL(!x{{8#!-h4ER z+Cj6x5V3=Zac&o2nx=t>{~cUBGBQ%JEbHM`tMyDA$H$4NB82#@*7}C;`=2YN3i*?{ z?I^|o(BVrw5tB9sn+^$i~OV-;`3C z01&Kt!5B9TqtoehuCw|1`Nb^N+eAc$Vc3RYe0~1>`GwKZQD@h#U9}ZO+qR$5T7NOP zfkvZIP)aqDBnej{mxxFRVGALy&Cky-@{Igpp-?y!MG*jiR!ZrKiHWxnaYQL)O-xLD z$2ot`ah!*`-R}E?pnARjyEu*?&{{|N`zaI(j4}2hK$cW}-@o8EPOIPVZpU-OVm^_5Efg04>Yn<#M^tIsXI^ztvh-0pJf&6#c%}>*>rE5fKgz4OMO1e(ubf zGc$L9008#x-TQ{;dC%v{L_SW5h#;$~PL?SsP18gv6+u?JhzMNQ9d=#!#Oc$gSIfj5 z@2K1DzEZ2zh5=xo=Xq@a(7CjPhzLZa;yCv5df9(~+l6naQmLHkbULr(*RcG@+}vD> zh%dOVd!k;iyF!Q}Wn<9r%FH|^Aw;oWue+}6o?wiN8-5&!@I M07*qoM6N<$f`p;*jsO4v literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/add_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/add_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..ba108fff3a3ddc290e1b0f412e52f32a2f20bd60 GIT binary patch literal 897 zcmV-{1AhF8P))pT#-Xx%10!cIUule)rz+|KL0Ph|Ak47;baFghM!pyVJ;Q$6h+$@T*_ON77t*rgs>)|8&aLQ9OwkL>G~~BV04D*9}A#uFSb7nrWL( ztPD7h&noFipNCEoZ8S@wO`BocEQ$}JH{FO(ifR=Div)- zrI*!fyILCHGi;V;_(aT;vDrr1rbb}4xd7i1zQ?Cb-+L8riJn(HZ_`Bdwg+UkKvVa)*gJ<;scRUXI+UyBi^0Bwtd&f z4FZa1OsDhAJR-7g86T!V!K`@GGsURRu7b%fyo;x5BV7^I4!nrNqSa4CgDk~acuIfk z3*g_t`xg9jQqyiR+7IAP(I871Y=~k!gU`itt##;F$WWmHZpA&~|AI8~Eq?BbpiTb) X%Xir;BELij00000NkvXXu0mjfu+*KY literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/add_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/add_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..b86014d22fe6adff4a2f07c3e7e67011ccfcd3cd GIT binary patch literal 1483 zcmV;+1vL7JP)=~yT19GA6{$_g1(j4lr6#8eRiw%Zae+(KA4O^*h*n5pmz`P9?yTb(yNAq%$&e8G zBuit@^ZVZWp5L>P)*7Bc@X3=WpI=*Bdnt;dJOBX3nD5%P>(BG&&))-pXeR^cX+SeG zGuazAZoJ|9exDGcM@m^xN>Km+!!SZZh|3uJ+ceFk?(XiNCMPG|{|kgqoH+4ztyUZJ zeSg0YB9c-HrBnz2?F|THY!E^iV~kpsb=Ps6Z|3Iaz5@WYBhZyAS2FYS^PhX3_b%tW zC8Z1i01!fGE01(+fDn?&<#O3Vp|H@~+k1L^eB9p_Xm)niyng-qY^72;!a08g06GoO z)=%TcfXKG(&SJ5+bnxK8q4Du?zClqEba8R2fxkrCRGWod_WWob#&d zy8Y#H`Pe3)iHQk|bN&(MycK)-L_RRa)HKb93kwTp78VxHn5J357}K;~doSm_;d$PN zV`F254WN~kmDd`L#(pVfYrCYwdOll;d9am3?Xbcy6pcn>PqkV-(gwmo5WL!IwRS8z z06?DSA81i@jNx1^rvU&MW7u&V1dk6Cl2Vdpvl+B) zD5WAPWxmm993W8?IdNN25Z9Gynr2s5*QK7Go*$%?I*K9$0LU;5Stt}V0KmR|``(YD zhys8%3`0{&(em>0;Ogq?u^g5MhixoSvRO3ji=OGICZ3 zQPNt62qBFz#z7FgEQAn=6kv?8Gz`NdrfL38DRnW%d98H_01!n{SgX|vob%V)I}k!0 z`F#Gq@B8Nf0GiF_E3WJA)>^N%b;2-gX{{y1hX`YAP)ci=Oy)N{Jw1J&Qu-Gmgz3kP z4{5E#wY4=rIie`?F~)!~hA4{s^#9mV1h9T=DW!}twmdU4^DhQ~D4WeLF~**#a)i*P z0RY;zZEf4OZquClzezHg3^7e}5dahh04NrV*DTArn~G{naU4fGj`LKVIGT)QS{sZ<8yYa$J%2_c4Qnjru{5CkL)!zitzwFcX^i=|TO($%Y1PeWYr z$@@t4_V#{UEEbn++b+iKB}oyIQbzT9oz&}fBBk5}qSpo4wq5M%>blm~*Y_zT@2hl5 zrlzKHw{G3~s#dGL<@Jtm l(b4h8g$oz{*(!px{0HCy&&q;5f>Hng002ovPDHLkV1jhZra}M! literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/appearance_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/appearance_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..e103a71258ce788cbb76f5385564f484cb5bd797 GIT binary patch literal 911 zcmV;A191F_P)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-w2}wjjR7i=XmQ9G2WfaGM_l`58-D(hLS`<-1i-b&S<43`) zBulJZRjU-jN>{mQ7qlyc#6SXr3=-6p1(7XWWE$m4O3n6-N{um^<4kk2`MG$`+njml z-sxHg9`1e5$N!w?JpbpTq0*y_04sqN@%=k+0T}Nkcu5cTXMv5tqmg7VY%`JU9PkzJ zC2+GFP-Br9Z2{f_Rs(+ne+Ez$(1=2o0)4;_zaUK2He_kry|8@Q4EYrZ+S1q=ZD zfnC7tVu_Xj2Y?qTZJF%=-c5`mR{%$VZKPHg(|ggV^;W3x)-_@O$P z9H!NSYAfu+>gQ@(9gERczfkW9pF7k8wPcfl4eE&cjXIu^e5y7Rz)AI2^*MDY#wPWW z`n`H*n%&1K*?3@&ppL5N)ywKt^=oxm3fyXu+`?+CQD@cHl5S8vu3ihw^Xh0b*fALF zngVtJ(`iwk1kM7dSSY7~Gr;*1m#2Z1>g`1 z4^=3PYlZHwq?5wRcIf`~P_1MSu#>rWK)#El`^DF&eUAY9fHy10P8Z)NloR<1|Lx)% zrkwO!S>)oo3A_^33{l!8^Dn000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-y)Ja4^R7i=XR$XiyR~7!wow++R`!lmYwg9P?%0p`fB?tkv z7b#Md3LA&6?cF*dqNoq88Wf5Ut;!3a3MzyuAt4nB@jy_6iue&k%-Y75V^>7>3r;8x z{Hbc6`cMc`*51w7J2Q9g-nl$<*L9YbG6Va}ZUefP|q`R+$rYaAygCMHHkM@Prg zG%W!DW2}AW&Yd@I-MZB}&U$)3qDG@(YOSZFl%JJSo={3vwAK~?5RotpV~2D8I_LaV zBHHkMzxRQO8jVIxO8HC}hNt2fJ= z%*+h4EbIGG6g?3HK_aCL`yJ4G0q8ye=RE7WZpLw(t3rrxudS`6M-rVmbH*%{Nyxzl_;hH~L_`JvqhGGH z)(U_oqCv-L5Ckm%j~0u?9RT0_pN{6{<{pXT_~o6QoemM{{xeNPER)IPGnoub)7&MZ zcE5w7QmP_^K$0Z;TI)ggT5C;}N~LI7)|1Q2%PR*&XV0F^MBbN*f5_x}U{)6>%*pP8AN?{Dxm-}l!6 ztS>AqJY-qc3qcTkYJY#fO+=7VhEWuq%;)nD16VTwAWhThD2melD?y=9C>4vvMJeU8 zzVCPE=jSV?Y5q8u%S}ls@ARi^^!)krf9&;oUu`yDJ4%PT7@-BYJdIi_j;62L@~B#*b-?a5ZFH7SJn zlGgeYhGG1sTCL{R*Vm)v<>jY6&%0JA6iNUfrHrMNC#u!zh*>U|$Au6jrBu(h?QEe? z_=}YC>o;%SOaWkQY^pSynj`u3qAy*@QH^;j;Kd$m%jd;!2!tu^N6=AJDS z3inAVKN&?)q?9U^N~Lk8wJ!B#g>2i7k|cR z3_}o+CL#f#O_P(8Bd+WIqTOzfE2R?KwsVzAbX#;~=u^&bGZc=2K-j^n4|IKC7FK_*F(JtAUSYwb7=V~ni>M@tZCtut282Or?~TQif@o$|1F-E`QulGzCh9{3{PX1w<=1a|HbNRjS-q&u`>va>rvFsLrjb^j?!R^*?{J#eB Yze{IW-&5Cwk^lez07*qoM6N<$f|pk%rvLx| literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/cancel_disable.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/cancel_disable.png new file mode 100644 index 0000000000000000000000000000000000000000..e0ec424c75e01da23e0f7f7daa335c952ac54d4d GIT binary patch literal 3159 zcmV-d45;&oP)78q>K_FC<2fLfQVuH;Az`)Cm-v- zaQo}%r{Bba$7;8hTSBfOqH+KR02@FGfK31xFaZP!umJd)G2&>y>!IE={l8Pdj=Gix zONi|N0vg=sYTa|&wr}np`Zzh?_rIuUwn~GcrHVwYAgU#RUDjv6(R2FZZx!(M>P;n! z4eQ$kL>$(g?bn7r`N!0Co%{W-f@O01k`lc~R-7;xuV;0^$Yd+y;~ zSI>=nZNQGYmbC#PANE+EZ@qH*WbXS{DmN@FHLM0xh$=}`CO~1Lj88Me*WjdP9&=dt zPqoNX?vdSa(l)?t9<5dTtm1Ua#7;sMNF$_{@C|^mHEm z%77>9@BfA(Y8p-_f3|n<<7pzoiMp27kdQkSQ5Zm)0Y9hbF8XuI1pxt{*-2{u{nti@ zj{Qq~*#D=c^~TnPrGKKq*B`jtdE}k}kJq(qu!P+Cd1~s%`-Uzi|6}>;!205ny#XPc z2}s=o*xg_SfRL^AmBIA%OZx{uj{j>}z1mb#`WGJaC#^l5r{?}i%pG{MW=okRk(Sm`@CR7`L_89+K)?KU@%<#Wd^XcWePaX2!%YS}VRDJczu3LqKGEDZx5 zk-WXSy8QO46-!78A|a>%5)4d-q-tre*-{MvDbG8hh&DdAqRF@eu%&Ey9RTm4-ZNJL zV4-2QN|1q!-{h26DzHSpZb5%$-DpN3NdzoPnwGaM9{J08J^Iedf;q;BfWkWu_1f45X0@ z2xb;UJY5tDFKOGedex@&B|*#5jR&5rNpEV7W*`+wLy@h0k>1oCUDNhtttq80S-RA$ zd*FSk>iFL*=XSUilgs3@MwRt4~_{^UfLd*vI`SM0Zz~ZFmUIBn&Wvr2)z#PAV zpHB0F%BZz!^TtKKo;x?m^ovdJRiW!*Kgb)H((jcG^rqR zzmnv@Y-CDz_{=VYbGdImIF^P%Y3)m=Wy7k*w!L*qDX`X@I|x~8R!X6n^c)us{vM$Ar)n2}03hjkU3zxi2M~dY$hdwp&Lg8S zNTDF5ASK24n;n-%4;~tj;gFQ!kQ_aDXkh%!j!UGZASsCfAwA!Yq@8Ks_cJb6u)RLu zP5E9I0E7**7Qp0Fpa0K{4+4O%^<^bQ6960@8R~OcU!zQ@&)hSVBzt%yJ^auA`EmN% za7|SJb>Gu{=LZ2m5;b~ScjdV9orTeK>eJ<+aLb$3n-~B4^hoSj?bdeH+9v(ub5JENkvD#{`6@egE{1o(~QIzDse`qvKY(QFHY3nm~^in4I?9$&d}5emsH+{|?$0~fSeU+bQlJPH6E zb=w*VD0+WvNGS%7=5T}<0r9}7$4yFXrjpLt;DVq(;>Uv!zLDU&=4)5G1s<^|1J zEjti&SdZVZQ!jr1dRO|j%8ikLkdLK&|LEV1_s=R)?zq)Gc;$4L&$@SY@uH^y;PJlm z*Ka!MpE;~!1cVE$@KuG8xzLAgt%pBPCx5!T|HIhdE~t=8tiaPQ^SOt6&kWqLy1QN6 z-)q?32Eg5M`Gc1M;Q8pfqN-r{aZAW`0`NI=6ct+YZcxaASsIL#*5}Sm#*X~;&CB-R zELc3sPwu#`It5>b)a z0WW)3o?D&?%CtTV2D^^tzPRt6e6;s$F95t;xuIx<6>MYh$d1dMzq-o;zr1<$ZvFOM zf>4*z-Wv~JIok&SWkmE`&6b*wP>qJ5r~oY_f<+*aF&q2LNNezftM%ZN_PQSHJvWfk zdAzQr*%IPmkNN!0p3Zl_X#RU@zjf5LG+IJD#K4V&=f1P+>bZQU>M@eyndsW$h*Cw0 z$Y21TW+&l0iG4$#+%D9AtZrL0C}b;uaMJgVKGJ)3@XO}D=LY7FmNlAdix=z=M5`GX z_nALSxK97${TJe2^uPA%EsKIm)e53U0zy9XN3B;*ci!u~U%3VR?20CfjnggYQP^l8MSb)Nq xIlCRroN!skh7yU`GdC|eU!v-F1NeU-{|m$vd^GfAGo}Cl002ovPDHLkV1lLP5Xb-k literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/cancel_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/cancel_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..b4187a19abdab8caa3363dd76700a13b11cc28c7 GIT binary patch literal 3070 zcmVau{rjC~5=ekTd9->#ESx~elRVHXg({eM`}m{R_SQNo)z-Gy zhY!HE&J+rkzD5)juN|${PVY>eDZvD_fVGlvLQ;%Gv?wK=lW`1k0{n=};{oQ*nVrKk1H}yd{dFo?zzS+TGp%NkpfVAP*U@CF;%9sBT z`)7UAg+!2u=%wXr>n#$WAfkl;3IH$wH)|rZzZf&0aG9TP?>+s(O(!~&|5CtThwA)G z3X5-)L=6CvnmMf597$>Y#@SS=?{}{siyun%V_WDl?-ZZE#3SX!lBiM;Ehk{A0q;MP zOg^--^SS;H9I(5#;aWxFRt8>6YW>i%!%rU>Z*xO%rVL1l9Yd$|_-`G{*DeZ3wN8L) z95#=KTALpDKmhkF{m+60!NQ#cOpj`JQ^n!t&fK?f)m7y|Wz{L7rGjX-00jVm!AZm1 z<1lw8wR`BH6UW6@c}(RN~8*cRY9If&p7Aul#623fJWQ(KASAWhg)eVZMOn?FeXk_xw&#-apF%&0C=Ug z@is;D#i;9EUmk8gcHV$(Rabtr*z)|=VY4IDy7y542v@JEDz@w&+9c`;NHGu}2bJG) zj)?$213rh%(TMBZU2(Yi_WZbZ$9EKy zd7JAG-mjVW=is_)8}BMo)(%OeF90rQOAJH>C{ZBQ=Hs=E+W=r`+tW=Bo5!cw-Uo>$ zx|{%btft{w0%nBT_I?ilUao1lDJa!F03r-Hxxv6-oLd4iHlucgOs@6?r22MuZNnV^ z5Nd7uIRnnIplnopPV`8vo?wPY|f2DPT2|(*Aecg zRu^1!-D?8>qz>AEynSsJ)>`}d2c+_tVL5%fvo5x^W|%p$RDalzCt z06^SzcN5VSElV!KtL*g(F73710p~wMG4oT!P>Gw>Besc{X(Los?09lw0?@7UMyiuezZYA+%M&I zyB3t&740pr0f@{F1XoM|w1im6%wYiduQ?YjRf5VGh+$;6GFWR^#Z$$?|Ne|uf}!IH zwuHpoJ8ms9tLps#kTiw{Ys&&lHr^KWDg~WNu}P)5q-=@hnO-8;$=xS1d<-NMiBLuH zjB)^A=CC4p`2;{By3}QE2Y{fm>IEp6KT{A93&HBIr<}o`?v7~31=%*4bea_j%)R}q zg~|E~|6pavU%Fv^&?6;uD#c{m1OUB1`1xS^Xm^@CHeswpF#*1SRP_Mhvgshg{4s!g zLMyxg3esA?0RR?>rP6uY%2>%nD@<_3rp|(M$jV_bSgap z*S~E?B)0EhlDwXLU!zk8Tty-T04c3c0w{R8^fKQF;D@~aA^>J6mFQm=oCzY##^}x+ z4+-J*QljNxqIdhQ2mltAMJDaA?Xh8dGEpVVB7nJn+x?Mf^ZtYg21X}2vAKdU>&D%g zx@CdV?|!GiiiiA8YAZ8n_zHEkuYVm=lB`09c|(x zfPYUWh5)FkK40-8(K9fN)0p_6VgQhq%7}1XSzyVAjFjYZjF7yukL-JAg&`2_NdMgq5s|oBC%(lPb7c;LbC72yCMu? zvTZV{4CLI6>x*P)p^cO?{&GPE9F4lpivXaAs+sxKk+skLagBbSh-v_!W1zRwWz$W7 zZ^Ri98GwCf`kmzOo{btJkk6aZxve`gQWEeJdA*cqK9K0!zH=y}lQzM&$?ZCxrgzS` zkOFxVX95DQ;iG%rd9y1!OjX*L{SyFB#iD;CU}{IznoGa(Mn^iX^bQ-4`==bK&5t992r zVwgJ@w>IsZ5J3PKOs94WqT2SVtLA_Hl|%7}<7_m5piGru^j1s+xGvncdvq3Vya;C^ zX<3v$`if%)B4!deOM}w`PI|+gZ+1DI)oaTMSlAPfJ(kZj2C%N<*_ z%?F~|*~~ym);1rK$Wr-H8{Y^3k;lfkWn}=;07b*DdslV1

    c`K&h>cG54*0>A;wJ z&IB1l`0l90~`Ba^9&(1>4EQeg@ z8==;wtpISWw&6xWblF?+;jd3RyLWq-byTk{El}2zDWf+nY1_L806LeiT~(y4%@&De z1SGN#_xu;z1Sn*3*w26`&F0X6lipArZfOUA?%KwiETUWboYbf5+Mjv*ya02ML8Ttm z%ug(CZTcAiY+q3By=wZb>wH3fQ4y6A$eX=8I{8ol6a&(Lqb~E&xYoZYJN(RVG&=?W zj@LGB6+|og)2VCgj!X`BPCx*7zGC&vnI7Lm0GzX~v#~1N@;U&lE19QmnZLNoCsmyy z3JIcF1o8oZ0mlsUDVMn`>N^X{@=TUxZyj2nX z4+Cv6?f!4Y;pXGxZEl}BPsX&1oo9O{l;2*exw_gTGlvaxM^d{dqv_PZA5NT1c)T|1=6)m)u<&2q^DH4|x(R^e|z=pDU$bbi#d_2p{ucnPTuq@o% zdO_vp52DJyC$z#p%NHmVg8a-dnoa!ALjyzCy?!Kh?%w|ofd9(&4+uwZKT|7bX8-^I M07*qoM6N<$g0tPt>Hq)$ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/cancel_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/cancel_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..568c435b013efea20b9134c943729741968cb97a GIT binary patch literal 3082 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/default_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/default_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..ca7242d48d40b57be2c440e9c25561a085421498 GIT binary patch literal 1835 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 FV1i{*Coup3 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/default_press.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/default_press.png new file mode 100644 index 0000000000000000000000000000000000000000..f020b07e2d45b0b83c862b1193dbf0afc4fd183b GIT binary patch literal 1810 zcmV+t2krQYP)`9!13?1yLXqjCb``U34vf+UINl|jPhp0DPtwAR0b_r8EuClF+Pzp35dddcop*PHO1 zJqY-i1)q;#!ZrawtfnH!h+95II_+v zdiX(pYZ#1b?Vu|6+xEJHHNmkHM~Q_gejYJ2Mrwjo0I7((l9rwX2b#icDSkF`s%4v1 zo|{dLC+RrX%-n|;MLy(A2p(#^3k=k+Ht+x9cu}Y8SRY+w?zpn<{q~OZm+woX%rM9X zVkjIy_V&3;m@IK5F66&8qE6y9GOnfaw;R z(+C!iVZ-WY&9vUxeuoiXdC#gC5n|In+o&8qKfb=JHf3jeDl<^@Pfc;#EEyQ8FDn?0 zbL6R)Rq3Xs;=B14o3Gj|89qOGlru7iK0^DEc4Fze7KX zhuS-NBl}5vY3%prK11g-yBpNB**~*e2i)q(h2pD*&iLycR5z>-j?GG=97X#e(OYxv z`_g#&%qFwwT03iWozcak#bfP#d zOihr2O1`H<4~5hOfxI9Yj!TOGJ;mSqVbTU9ivI$3Ctsle{nq=Z0VEterSN<@1>rWj zq@oA$iHjOa2sEjPUy0D^HyEK5PBcy;37`51TPm*k3??kupu(P{1@QfctOER=rbk^x50B>uv=Siur}4t zqgURy%FCoTlUB|qdnB; z1*!S@GoonEapp$j96=BQbZ&kM?*u9Y27;XK81*l0Q}fRM$~PmF#V@;J)Gk` z!A-bDvSM>v^kfr@rKG*EfZ8#6>Vfn*skZql; z%9s;-;(MiH>I1|1z;S6hdR{Hr^5b;p!UC~F*9eB&smz}r*?eq+ zRWv%61pz}urJ(B^)qW^{ok9F+*+mO<(p(E3C*qC`1(p2E`LG< zUYxI$hBB!N_?glbqxSGQ_592gb~6o@;0uuf(4EWMzLNB*N6pmNDnx~qNu{CjpeMQL zxctTOIG5;Kdwm8Y{00*YgA!e%z;QWyy`9wsPrF-`>hL&h!L-P2#N7+}H!Y~>ZSek2 z&73b!6s1||d@bOkSQq3X(0kkCNJUGJLql69J9i#cdl%Q(9e3{ZUf^U51Fj{HUVq-q zm^=>CXJDWpmLO4gOhsPY(z_zvYuwW>%>N?(1+7)gAn`p=^#A|>07*qoM6N<$f^pw- ADgXcg literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/down_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/down_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..e59d07fa7e8ccddba7911c33cf91faaaf5c98313 GIT binary patch literal 2307 zcmb7G3s4kg96wPc!DrEnn%r3=A>7;DyS>-Osd#4`$srvSh)%h;``z8f-R`lwatCSw zMT(3=jXFN2CL=X7LrOE$#4w>TRK}VbE42Yl#vTY|F==Yw!f|OsubtW5@A2E;|M!1< z|JmBS+^h-lN%0zuW)O*yr^ojRrG_l|F z1w~4cGlyoyfR^DzH_(OyL5S99GG>K?3|j&e#0|W>U_~z-ID{fRXGIGQPQn?q0Uz(E zkU)M#ZUI|S!df_V)=VTLOhbYIP#7c}@Cz~>wxWZ)G#snTIEoBHloBhNsTxFzoOy^% zlmKGT8Znlnbco5KC5?ndN6kQV1Zlzv6He+ef}{x}t+ybN3x(Ds&O^KGk3?+2nHBXZ zN|46!P$;Ag>9wNd#Yv0Bf)hGir^6rulgkB#31fnsJj`GRGAr>xg%<@xWn|pq62*!_ zr9&ByQj)VyY3=cCwoYWGkOM^g;jpBk!B>$jsj>Ul=1c0E(5KBg}L7%9IvQPXQ z>ge_@24HBN&ZvzMwFClD6S6Y547w2s$cSjUpgah07m&pz5)0;*L7B;_H$mDa0Y(v} z0#Wo2Cn|4PGGenKsfE12i6J@dCOEJ&3b3L&LPuhR86&9zosQO#w4O>Q%rrp^L7gJU zd&)M2@px&;aghGP`wU%?zpdqgR~KzI27;{|w7@S;dGh_p@gixM;p)#-0u&$ij} zB+8=$i7_)Kqsc?E6f`uLFWN4$OVk2TzaKgaoXA3sKjrBS1_Mhn7L4Qw7URs6 z0dwmqIQ6hbH=xW0hNOns=1V+0j*S0iR#g=T8OyAo9JWDq8127s67AqXfYcJ~&t(TQAJb@JTC(k#1&-QvUmUM1 z1c`Bdod@-^KJHIxH>IXco)h0;thEb^5_9pz`3Y0f63LamJHFhu9J7})dxF#V`0|DL zo=K_2V>eFTpYC#XBu&q{cKq~RJ^N1RL%r9IckbSIdg+rbJumkx>y+zu>=>U`e{R7} z=cOCn-bMGdmn*T?lEV|O_9YrOuU7{8?tZ2<)Lgl*adunfs5-c4J0^e4yqMEvnfI`(Bc`1=dHykN&8hKA``a}K z*ak5AeYtjFbBU!qrRS=9>*eChcvtMPr(gX9{jGCt^R&Hvjul-q%4$=-UK`r|{8t>+ z)>67DOBjx!(Y9=)@p<;UDR&-8BJcKf_v3x9v&{qL)PU9|;~t79&KZ|b+rP6*^? zS8VW<#;)#Knvr(TnPW}2@4OM$nNWRw!w(l8{-Ll=IGFm%6mtBlDS$6eNGLs&@j`un zOY`yrv*S-*SW{i!(fhi-yKk literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/down_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/down_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..37081b918f41d70b2de09e9dbe1cbea652fdfccc GIT binary patch literal 2770 zcmb7G3se(V8Xi4Jqf|GZYNcXj2pkH<$z<}LDN!)t6%ArU1?p>PY++?i*sa(Nr`nr@7YHv_<|X4gHXBxsfw08AUu z#m3Qbs^u6#rEzf$l}K_eX+{PO0KrQvMx00`X)uvY(ivo&!E=oqP^Xb`){0a-l~GP6 z>msvFKsB5ti@{(E#t@{DG!9zQ^ae9#k#Rx5%NI^%019hZqE8wi;;M0vXJ{6ATK{Oqg^=T1Oc` z7bBiXWzaGXqjb!LG~*<#!8{%&CSb4yH^K;)=W=Njs39hC#tf5w)VPL#Nj;fH8fY_v zMJBPvWQwND$P%z;nANd-=mG7g`|MF-8lFVLMne(@ zoD3o+r}UJGG0dnFJUt&Jm&ceWtxnG@nAH(W!Kg5~7(vBih|fhv<*HOzl)+5n27-)I z$T&=BxH_E%(@M2yA`jt1h=5N*e4Y@8@I;b?v|=eL5r{;jM1oH2S5QQTs{ma4$IgO= zA{dUJ%h^{ z!EnNLBxD@IRSTqsGd`_*PCR~>3==~-hA6F zB1ZB>5!>FK`BFki?#mx2S^rwrG%Y=RK};y?e$&hos9#O7f7;6bNI-kZk%ghQt3?HZ zh3(lFoYGA@?`39rRetxUzVgBH!I5&S|1Q?KyxQ8@ok1n7x#r{UKuBOgP4U{gb!SaE zl7Wl71KACW=kK^dS32Oh)S)+1eHGsUKyFb!a{40L7#_I((#gC3{-ejd2T%M{g!Ah> ziN%o}bX8YRT&ms7eF0co9HXplLFX-Htze~hI_m{NK|zkpu#Z3b2s~y_+UI9Q3;UZB zj(SWx=ncFKRG4S)_yEow{?gOgJ>qm+2{{m6ePfk!Tk@H&cYZ7VRFJ<3@R|PkKi>-2 zy*0GC_3iJwpI-LiwdY#+CN>8BlrGkbuhdDll?JwUV+Hu%@9+tqKW zZhDPzbjv5hU}68vnyVMJr_eL+gecxCFFzWe3LEtLV2!P_hTUc@P`BRy@B&)uMfd@m z-pZ?R-WeVqR{1p3M>|{NP85`WCA^+wdvs2}mhHxN`>bx4#RCWiZe0s^10q=6)x~AS z>NU)7xlglab+P&dsRN$cgt`MojuB_Vz^kPo=SD?ND0}m@6#L`9R2?{f{``sHcGy3P z!%lAj5(erMY|&GiP)sI!vGzqT`FMU3Lu z+-u6L*`bOv4GpSOi*mMkuB>$Iw0Es|NFRJr(Y)Ji$bYzgePsK|_Uw zkDTrvtf#vl)CTO{aPNv25gl0bH&9fpZgtcki);QxoxDNv$JzaAOJXi+Qo3Z^AB(~$k32JXmGa*8-rk>L0y7c<=W-Hf z4VAH`Y|k$&bocf3?W>gKteN`Ya&>jYo~>u?_8+vUe|AU_dunG&h8qwQSTZ+t@JOhF z^|^7gUVqnd^XAR0Rz+RM;(`Oo3xLAr^!kh!udO$!B6~D z9eF~P4LLN}KApHcw57_!$6#t}jE|2WsrCNmi$2@_{jW5tYZsW>RId>J$Lu-m6Y2nA z{s}R0cZb7T+ArO}4nJ za0`Jj-xajStUWI!r{^V3So z6N^$A98>a>QWe}Xi&D$;i?WLqoP*6??Ag@Az`*G3>EamT(Ybfp#;n5z0&V*{@+ukZ z+vY3nmOrqYTlO=P+yx;oe zyDd`31^GoC_||;oxWJrlyRDdeO`1dW0+vlPOW7W*XpH4pab<#K1NRMvYWWLc_Vt0x zSHAI2Wncdq55-T`@7~3wlgm?*f7lfm~ryhZw=?5$3nY|4(wozV|td) zv*N)0+2&77_A;sa&*sq(x$g7*;<>7Nz73~EgTiW3)Blz?+_k#0c3Q9nihy=?$q1o_P+k`#0N7)62e9xy79; z&F92HRwm6Eh6&brN+r){geY%Z8&PJtvM^?UjKTzic@xAoePrPCn4$K)l8dFt!Dp+P mxW{7sB~|u}?<-;y>KSMpUXO@geCx5!@X<( literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/equipment_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/equipment_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..b8900825bd5d896d695c6d885670b9ab0fb4d9c1 GIT binary patch literal 1140 zcmV-)1dIELP)|X zFEKMBLSCx?0010xMObuGZ)S9NVRB^vL1b@YWgtdra%FdKa%*!SLsK^Byt0e{00YcP zL_t(YiLI8uZzDw%$KRXTS?}1Ju}w|_0Tm}AE-CUS#L{sgL=Y#DB7rCl3JN47bX-Xd zG=M;KG$$HBij&BW2uT#3l8A$?CktDN<9t(t*os0*4kNP%nf7AHEV5=hsM5WYtp-|Z4oWE76RH9CtbtelUK5Roy5piTl z$1x(3*7~$wufJ%m{j@uN0V5m zXl`yUNYnJT);exC_z#4Lh%v_V`FxViW@7;0gJ1vvTI;4U=Dkv>Gr z3wkzGuPbZq^Ru(FPqQ!#C#|(b=iER?a6b3gIj1KkCIkR*BC-Hrp#P=;008G)YOO5@ zAtsq~PPLB}H*5?5z!+n^`*|3o!y+Q#oXhpKJwzjaSG{74u_huK7%=Nc6hp*>F{YU@ z=AP$y^`5aj9?JQl`*)+!xW{&PcYpUh?-$SW0vh#l8bL%vLWn>JaeQ!a@FxQR;GEwL zfE!7&d$Oh2woRL{3?Xl<(%(S zDwSkVuc4rBl}e>&thIj~9Ua-Jsj27SeC+!0@bHgO>i+@wa_t&r@bi!W0000Kjs{jB19CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-vOi4sRR7i=f*2`{9Q5XmC-`+jdN>fQw$2-*hEvN|wE-`VL z5F?S$SI{6~g2adrhQuZ6A%rM>0|`|kap~=xW3bk4m(zVN)$^a6v)ASSU*BbY-^v<| zhAvUXc8tXD@A!z>ZZ=ms%x}Uz9Ec*L7>IKVn8OFWz-uhEBFfrWbO;mJgF6187XL$z zK5RyYx4435-3nE373boqe-&$69H<}|5MKeK^c~lwOjEB zr;h~LFBiw@%Dv?}bvIy01vlc4%m732|%)?;`g~=~%=h9taJtsCPAN z6H3vrwF%P@F6BrfRut7uk#m`Ut9OQ*IFHZCSRKDhL<&;z^jY#<#VuS|A#ZAY72L-W zAxSzlyaH+CtKuEAPiOoE6-%o>o49JGi7Nwyho~na~I)g!WO>{&A8EfuF>a zQo;`Jx&fhujAMuL=hn24SyMt%m70$>BPPV}e3asU7T07*qoM6N<$ Ef{#5vCIA2c literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/file_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/file_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..68c2577aef531a9f48163e8e4a2d1f14e3ed8d19 GIT binary patch literal 1306 zcmV+#1?BpQP)Kjs{jB19CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-xlu1NER7i=fmQ8OHXAsB#GrLcAv)H@q*vVG_Dtbk5fv7-< zgaUE$2@1Wmy_8#N)m}=a_ENP{4^>h74H83;+VIjy&IQD&Qc;2ST&Nny_CCS(#?S6f z53EC838?&~x$Hik-;C$knIRFuUOIB*2mn+@Mn?9FNC^OlsMTyXAKkrsx3Q-K0JIe} zIXQ{z*RKNr#>dBpipAnvS(d$Rj5&~|X-Pz!9JFRxR!b@MfSGSSvs9g>^RPs zTI(}Ol0400<8rxN+_!Jvg<7rlGXQY4T7`(%Ns@fHy1Lp2kZo{e1woLwuKU5&t5<&o zuma#QfWLEltdwerNQ;ODe=7mVwARKLb8&il+5!MuL_kERy4~&}V@zvMaS_4L&``m$ ztnX%LXKw?*;^N}A;+!~f0wQ8sovM`UQS>dg!_?E2VDVyLS&vL=cf%p6A_HN_ktdB4&Q!wP$7_qI8FB zJkRrfXXaY~VApCjOifK0+qS;tsjRN9TJ3h*kD{o!gZb@t z+wXR}0|@!PUkQR>E{@|*fGzWApwp*MBS{ifC=@RDdcAkF*6}Nja>sSupQ0%Gv|g`o zsx1T0#y9}nxN!she%}E2$aUQdl}hEWFbqqMJ0YEc`4Gmw2 QMF0Q*07*qoM6N<$f{Kt^c>n+a literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/folder_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/folder_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..af9a70aaee8be5b5a4c974cebf04a7294485658a GIT binary patch literal 708 zcmV;#0z3VQP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-vK1oDDR7i=n)=x{7K@T1MaV}eio;3ESwC++FCgKfH#=M#&$%FE)iY8O`Jdzzk;X@ zXv9JGq7UzI3oq+BDsUIqv5wX9{>t7mcnEv&05{O;=BOVJaZyf7s{{FVmg0~jc#dmI zsVpj+Z(~Zn;7(32?5{W)lvQ>oNE@<9&f#)I(~P}CviwhCy)ExaSzXHk?!!0C#k^4h&*5?90G}et z2^^ABxEh?3cqOGIrF1W)w31T#oKjj$DSb~VJ&Cp5j2D4j46c>nR>&`Y0zWJFQWZ)a zD`OhLIf1bPizUZy+jmm}ZsxF0ZLl(s}4$65>rO}DJJ%$1^9UNO4l{(GIaXGSX%}IgxcG;Yi qZ2)J~YqwtO^7eLeRJOlrApZdM@&%XJ6K>-G0000000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-w)Ja4^R7i=Xmd|S&M-<23%BCE!r#sfS8f^$(I_BcFsXJ;Y#K`X5-9WU<=a@ssBD z;FXab%a+nF>}lq`&&-?I?>t6CFo_ly7xS~TvvXQ&4*-C3-aa`wIX*ZzXigH(ZUdFe zWs`_LL&Q%JaegouYZGMRiUgm_V@RQ{X@R4f*`Wm!LkVfanA+dW6bAl?DHDFMX^ zgb+z7Wx{csS4ycLc6N63SkThalIeNgFK1_GkGtJ&3jp*uz!)HxQf6J({iD@teYd~A ze_2X%bh7KZKgN(|oc}t6i0DReJYRRa-6jA$o|&0B1%U70+0okC+M_6n)=y7QJB%^9 zzS|*4Tqp%2XQj11S4#B&fDadw%jIS)%X(6))iy6d%gf7&R4TRAY&P#9V!#*!#+b=D zcSb3kb1Rd{99fq2v(}mu5hM}`rIh;I_x&%!Fl++AfQUc{k<91w|MYsjmA$>aa}xj{ zolZXpf?xp=JM2O{lgYF!%lcbu&4(p43?pe6#%`@v`+al)D=RDidY+duO>^G&eHQ>U zA_id?E~L}x2LP~R0sv^OABJJ5<3j+$Fp`NxqQ1So{q0TXaa~(mTWteC^YY+sV z^!xoD06-Xq+P3Y70Ihip=IAg5M7*p_mrMgQj&fVs% zR_oX>j5g=oyfbV{an4P{Fxu^Q`}E@Oy@gb=n6;;7MRG|ia& z+Hst(lv2Ywj4_JMb()We2&9xb$8pw&kSibnfKI3L+;!cGlya7c zINk70j1ygmODShv*R6Cqo#&(DS3vc8z0VkXDy4jx&1R(#A{i$b3mlFMA(Gi_R!S*f za?YRD>-8(Qc5HJ}DwS6I{r geY-p+rk!JDOaK4?07*qoM6N<$f-I2w$N&HU literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/graphics_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/graphics_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..290c34a2f8072d2199e9bdb760769da60f05696f GIT binary patch literal 978 zcmV;@11000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-wOi4sRR7i=X)=P+%WfTYS-&`DL7_-b7vyF=gD!U17qJnCX zUFf>Wf*@;AP_5duYtgEZqDV<1vQ=Rr*`h3?AfZAqy4ht@i-N*TCbV%JozH)Z_k7Je zA2Tx6fy4K`&w0-OJeU7D=jlsgkur{pu(G}n;RhUCjPu|k?6=@1Tv9=nmTkI%?Z^9g z4>Jn^^_^lzci{ow|#^X47 zsz8I-h7FoyIXMsbLXukKN^HjiT1VO6GkFv4(OhslNP2$flfLpfSQwk;7+X8K18?9j z&AE@X=1rB-?0WeE!8$lvJ6VByv9ld$2%l)^JAkk70e;6C+<;3pg!mP&w04owVO)&s zv8saoh--0N5=m}Lax}@2BrhacQsZ46O0p@*Op@I_wq9M6WP4#v7PhYOr2^U8a(Fh$ z{v=P;cYl&^lYE+_uf`rrvMtHxB#$InR^v;O>`BroY?6%E;PE6|lZ+<0HOYxIGF_{b z)Te1IMv;u-LJ*7&C%pIHMT&U;&KcVT{$hUg-wz;Jg}}z>&gS(XMqdo88B81zyKq zY{o_ntyj+zs2%V`{U0f;&?M}Hra+G1RXmD4I3Ks;c@4cgcn3?&CT_nb9R_NV$24i8 z{KquMJ28mwHRa|4e2zEqi{`!t%66cfdlPlKfTr*Vp2nAD+n~v_t08hRhWS#{n68Y*|n-e+#n9ndg%sQiYt zN>IC~-l?JVL|yVw{dP1g?Dm&#!<$b!W~=_3qS|f~JF(Slu1wWMPuGguJD6EOyNeks ztesu(`5NDA8pizTzcs!wP2=0>6pe2N_hSpr)Z|85Iv;pfN6TkRVa$1`Eaq`?nPz9F zdYts*8>jg=Y0DDaY;n)6U1rPAX$NY{|9U|F1503v2XR}AW&i*H07*qoM6N<$g3Ha& Ac>n+a literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/graphics_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/graphics_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..35d6b7603170d2e18690e746e4d0092804b17458 GIT binary patch literal 1652 zcmV-)28;QLP)000W>0fLJSS^xk59CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gHt4*vi~s-y?ny*JR7i=XmQ8G2R~5(4x$oZhF>n0de0V|@SICfP?>WB#0iXuo5 zA?>1FG!Z7_`OLgG@7<5XqBA8fcIApAz16+<|GVeibN}}s5y4L4(4j-arBZ3HF(wZH zz!+=XyLa#Q+S*!eC+qQ}K;?3o6Vanm%HvYXeOl`x5jg+=h?rQGwIPJKC4~4RBEC_n zRMf`?mCNNRDdn?K6dmaGdPYjwGsY+Y7%V`>7#BjguIsW)CUa8=@nWS?`NNJt6B856 zah&JlIDVqtZl_YpsGk9DB|v=vAw(t!0^9SvSCS<8{_^s&*%mZ9I?D6;{4ZLq)@-}o zt^q ztJSIjz-%s;+W>&?{ZB?GPMr91uh%CHXgBU+wy(?Cg=Q5h`3Hfdz4aN zjN|yz-EKGWegC~oCi5Fa1R{cd=0rp;B7RD1ef0kQ`z0x*DwRraM^W_HrAwDm4giqN zW{-8d-Tk(0>wG@{S{%neSXx?=gWaAydGhDBZJ$NNX8_>F#fukzwcT0G&CTs`9OuW4 zM&r>aiuU`ye+&SYIRJpxdOS%Ik(_sB=gyrUj*pKY zS4w3N5s8SVr>CEmQhp8qx{l-AR!aSLadGjzBS(%roy+AGI-Sml)_NQOmf6V2$goms zpE1S|(cjADvOhUFIT1zCnR>mxmx#V~;J|@B^nR=}#yIrvl2Ynur_=dbtJV5yr_*_X zG4|@{=%|17>QzZZFEPfnlycwU!-t1?p-|YHBuQRM*^Hv-SemA90zif__D(LBdlwO3 zPt){Y)6>(RH^zL%81v75g^@8PmQuEqQk^78006!)G&J-j09Z(p zM3g5YhlorRMIHcTIp^7YKL7irrKN8I0GvL3I+Ld96TM!qNJN`#1`!9BnbI^hp67kC zKh#9T4iR|(kmnC9Ajfesh-e#QWSXX*otm2ZwPjh??%uuo(zR>XzA-sDIm8(I#8yQ> zM8FtBL>v^6*Y`yO0KfpC0RXAzd2SE{ukG5k>$xBZ{@m;J9$sHxpG=bEr@MFW9wQ>1 zB*~&>Spxp+cMJe5BC>=K8Q=GNhh*g4Hd|d?tqCD+5fL)Ro;-N)pjE9_-*g=3RH0D#86rNuw6t_%e0t2HDdn3|fJh@$8ft+ft< z;1cKjg-WGzbFlMrxjdqjdam7Wk1@vnV%zppmSurbN+F^_MDl%KXssXCT7M-;l2eUF zBOMwV%KET!ZfUBBh>S72f7r$tlfwH?2J``&T)$s+)UPlD z09Y&*H<>CMOk7x4SoA#aTo{JMzIcy_Vj@ZqaqvtGvQQuX5K$wd0RRYspy+wtxdCJo z2mqkjY@Q9nuo4782>{sO_1sDHEs6y}PzuAa(rh-*J~+M!w6e0I5b;b91TPl~g+K_A z=?iQN9E=MgGKE4R2!h~c#@Lyam6gp7vYp1v%*?b>>e(oY_V2Jc`8((Q#rgU9>Q;Im y*>26u%y0nMQM&~IZ_LlnfBbgq!}0$%kpBVM6;-D4lEW(i0000KO9? literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/guide_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/guide_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..21560907b769b787011f9c5c88038fed4d94e082 GIT binary patch literal 955 zcmV;s14R6ZP)nFsl9}i4JiwQsK%cVD;7dnu(Kc}NW@Ai z5s7G6h%_N#V`IU>t|}E`LnkUTt-OXe)9K8yxaZFN`udwUbCR3i{oV8bp6@xoUne4L zldi?BxFX-r;b;7@9p#BF_)|ETYZf!uk-Qb0!7um*U#9a`>Ws+og3~WJEE?+h!{r1d_GwR_x+^E!~S&z#UG~KSC?3IlCO$CKNV3z`v_4w1~Jnq1t zn~ZxDbd5TxL7cz>4&ybvp8JL5^+t3$O8suay-*z;#0BlNrl1LaS3t6ud&ygC(S!52 zn*!x)lxAFN$wr><&*;9#oq2u|H{%u?=xfVrAFk`-Hs!9zWi*5P8xBt9ehz!aWVD+6 z16>8SQ)7fFwR_mbwdms!{5wW(O_>^(cgF}-s#h?J2O8&xlq+4f`P5jaZbr0X0~nQR zr|(cQ>EQX4o5BkjaW7?>4coMT9)k(|gtIQLQ>0K=L07%j89bDZcBXDMcth^%*rI^# z431CWPi3^sDveo%_TW{#-H3EDvsz90+N2%4l=6#>U~3QlRmaKUh*-+;aVjFtMZ~ej zxM{AbTy4B#sax#~bF{6`y4?|RJR%k&;&ep(77=?lF*a`PP2JNGaW*1;jEH_jtbbt# zcncq7z2Jy4=e9&tkKpU6#&QNK@qp8qK1LLx){GG}l(h)q`bkdellb*zj$}n9~ro)AX z)2>p(em+m&4Se2aY@8#?2kky()bCe%YchGuN;95N{t>>)vsT*5QIoD$ejs<{`#;JL dG)>2~ z)+e>rFQsW(A)*2RaL%<5VoNEtDunnO5iQ=haijZxgJx!CrjjIiCkTQgQ50ob>&O_B z0_Zz1&bg3MT9#!g+qSAP9ciZnqg z&j&%!8T>=-c6$@R*ntBFJ_7LeHxx}zPfvtl_;It@++vJT4gnF7<2a>CrSezTbuV1G za-|0V=g*&ad%fPJR;x801VJ|k^<7Y{R!1DixzK1d{`3@d`t)f_O1ZeXx%oY<%gf6h z4giHh;k7Ufj|@X{P?3o4Ei5cF4;?x*8;0QrVHkceIyySLu&~f1qI-<7;*bwZ(=-ah z@UZXurvQKhfH7t~48sh&n_-N(`R@l(%12VlM*tq=L0tf5H^(T7be3hW0RTI8?ASre zvi|V+@#DiplpxOjhJV&eM%Fh4*4`Ps8)pHGtHFRfPVY0(TRlhtbV zD^QQXimSxREQS^e=I^IpquyM|LmocW17sh}Qw)w^d^^>cstFI`fzAJ=y?(W^YFR!n!k8f;joUGMqW4`ZS_B^lrG#x~wl(Ljk zD|hbP`L_fBA;f2vWxWx{F#wQl+g_;Qmm+mdsB3;la(x7$m$ZGS1Hv;auQaW;}9d2hE_wYIjV@87?#hu4V+Ns_$h zIL-zDsg$y9+g?eMf5&c z^G2gFzXJpS^?LpClP6Dp)NZ$%LI`U=WjmybvMh^y-yiXP|C2_e@vHvcj(H@de79UK zR{@Om2Osiru^$fpJNRzKas2BYiihuEdV1PojQzIT?Y`ORbb4u;M!@!myO#<8P)a$z z?^}-Jd({UE=$m^!PR^Y>_f{Oo7s4<+97T~%(=;;1WZ3yQkxD7cwryeC_DZ2p zxOnyI)f>CTd**X%YHF&)7<)a-vRAd%FQjQ&CL)z9Or(@8rPPX2>b4MKX>M*V*(=sF zL4$Vc)TwVtDStpjB>>=@Kk0V6_m-EJzuu4ke*kMG&D2wDiY@>E002ovPDHLkV1iQh B_(A{x literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/help_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/help_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..e7e98ffdcffb1f643e3ac3a5d14c8e71c4cfdce7 GIT binary patch literal 903 zcmV;219<$2P) z&(dLAv})**u*G* zw~B8P9iWdNaSX3+7pRAq@f6naZxy)7N`L{DaSDf$SS!#1UdKWFmF(L9n!q~Pix2T| z4K@vQ9M9nQYOIeXA=`BD9r^#9iKK8P-oTShKnF$Ie`kxoOa@Bydb38 zs(kn0X}neg4e$wW5Z|Q8wF~dyaqZT_S3F0~PE$7fhfmPNKjQCB~h$Te;M;U2u%!!@E9*Bcg> z082vu^VOPCTb&k=lGRPPu7}%_SyM(OK$+`Tf&1of{Y_ks13l~(yK7d>l<_m7_3X%J z9bFSSr)?_A1Csb*YzAHAwS`Xid zB5nIlwUthA3U`Qd7$%8LmrCCga(~^$ucFo0TeruQNg=j~pK%vPC8IUGl+Jb2 ztZjf7@t}#+Z6KYTKO&Ec>0{y*Jc>W6EQ)nS)~mQ%90g5B2V8{{c(zPT0}b((XtIA+ z?8>4gQGox5Z&VW*Cz(BX7mtap-3U~`PT-LYxZaRmQx>J^p2TyeN@dpN$v0QCGwKUBOYj-4tvV5OMH5AX@#+qCxg^?t&=B6>&#+KgSwv9#C!9iwoqgd_OBL dkgMBq{vQ1>8(KgAV35oJbL0q`#$`oRu8@1AxU-%+j0a{h zGv}V~e&>AWo{K~T2eGlSu}2Gq!c)eWJ^%njY-p`-FE20uagg=6AJEyeXKk(ZM3N-W zCrNTlYh5BD8vuYYmROcm6GE(8mh}@6U0+yOX#8)WGiT1sv|6pV!!R6CN~KAXC}WHU zfP4Wm#w^aclu`=Ub?-Qi^X1j6SHC+D(A?Y{2Y`>lFnlct0+l352mpYH*ew8M0XXNf zx3{;aP$>M6rs;*n#YMFz(A3nFa2)6BTCFx61i?nO`>p`H@$z`S?++A<#Z}9)UN4u+ zQSQLoy@e1TWFXa?fNk4c2;l)h+690C0K{?J&{`V+pdbjU0C2LeukRB8c4gUiHM-Tzkk5< zyz}$(^WQ%JI(6!l+J1f28UQmHh*w6yf*UO5{c9_B+sLqBhAZ4Cf` zh75^wE(Zn%{tClzqEe}B^DI5%&1Q2XNs_HyMb|`h=-jz;hpW}MNu^D`~D;VlsN!^F=ir)qK+CMBBW^=HJi<+@7}$;YK(D} zQcjwt1OVXsz9*$D-MV$__wn)ZuA)&&C7$Pv13;OdIC0_;Ddn*|WxISSiXx1n$O8Za z0AZePB1#c4I&$O)b_2;-X|0b=OiVn+3x&dnQmSN(NxQU4j;*tIkp)HAQ7p!B+_iRD zrc$kSQA#<&jWK?9tmKO7W@y_sc%HX~hzSu{Qc8x1G3We&3cFzukub*e@I4$ljEKN- z9NTf63#C%&*ZcSHL%m)%H*ellqobn-ioqCT4Ma>JYref0WlwPV^5rm&WAr@Fot~cV z9~>Nf1^|5cH@zM45wXP>3wW#5TH~D87-JgL>T763qBU*9FA)TmObNkne5*+kem zIXY6G9lBeMM&mcOva<3g=X{-WF6qCAQwjhO$FW`)DYVA=D$ zJ7E|OYOU2CBOxgki|^aEUEkc?e8L!`y7;uSab4G4YqeUd0GR+PmCCjd;&b2kd)gRu z7$Q2gTJ6K*$B)0FwO(h8$$i+P@B7lStdEzLmK4CQc{DdS_f@@Kf4OZ;V75c>JdgGC z^!&m(zZXT(vq2CX>eA#yMBw}WA>a4EnV+A(nE&YL0nYh5#bU7^08ZwE4|j~RaXyBK zJWbOk5$X06XF|#c-(noc?{#Ekx6o#1XC)$j)@U?d+TPx7YOV8HbZkAx$dxLD@O7?VQh<%A0%r0cqt>$+>UZGU>@ z%9Vv~@%FuL&CJXc5b=dHO`l7Wm5UZADEtkvX)?Tsp1!}j+ w$;rn#=T8z*0RVt8R&O*Kw=0#(y@Ra(2STr#^cHvOU;qFB07*qoM6N<$f_3Di5C8xG literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/items_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/items_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..ce332485503254bf1add7667bde60503601afddd GIT binary patch literal 897 zcmV-{1AhF8P)|X zFEKMBLSCx?0010xMObuGZ)S9NVRB^vL1b@YWgtdra%FdKa%*!SLsK^Byt0e{00P-b zL_t(YiIvt%tesO72k_r{w9YA2k5+^$F{nqVk;KGIB%~yi0TL1-BsCC;i7~;Tk%&o0 z6(NX-n7C;>BW9*mi5Rp==`H2pUXQl-aSYblIp5v=?mfpp`Enj>?fqYC?e$;#>x{=^ zGvYejhAZ;-628N!Sr+%F*tcSDKDXm4T#~kBjPN~<;)^72MQ4+Y9>puzgH`;SpKE1p z20FkN{D8Oc-mFA@yp3mZ4*xVZZbR8%fXna^UdX^UB-)A(un)gw^qt(SL_f}_mw_xd zd^*^PBY3PyRujF0{rIKIqL0(~3d8*WPuzn!tW??U!iRXKjc8w{{d*(2v8ewp%;QSj zoWx&dMvvocOJ-N&IlSK_8sKZ}7H87TKLnljn3U`XexxUJ5kX5)Fi>1Bq z7u_|o{?LawhBs`C!SXy-26n`C8=lGQDk>*Efg_&TFbMzn-8cojF|sk9%! z$^5>QzO~j?MFZ{W<8q;&waT$Xw9xqPBwlkd7ECJA)XSRa+Dp4Fiwb&J6b&*Bqx9`< z2CzIIX=Zhnbwqytq%AS&ebxe-NFh)@~Eo9BC3Q3SE>r zHWnHfiuN2%d5X`f$xt2Ob$M0P*TlPcQcUC0F(VguWQ{c;`l82ca1bvRhni@JPsETt zD{4ONy`o?xNp|9MF+nbDL{!KQ;tBjE6wmale48lOA-trL#bz%jPvd1V>X(ynrLl2W zWIW8z<9O3#=&r+NM6ewXim8387?4}ic3zxc>8yF}SH(<3P23<}Ah+l5Kg6v&lh*zN XI=kOSMyvVN00000NkvXXu0mjfSOcOZ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/items_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/items_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..14ae9e95d8675fff8ed0a12858030f95a6ba6a22 GIT binary patch literal 1483 zcmV;+1vL7JP)|X zFEKMBLSCx?0010xMObuGZ)S9NVRB^vL1b@YWgtdra%FdKa%*!SLsK^Byt0e{00kpS zL_t(YiIrAOh#b`x{?57gc2!MR*R&IPdH#Srqo`Q~5f`pPFuo*abb1n!C|M}tF5p51 zL0pQ6;twjkh49`(gty3RCYeb@hKbSv7cN|7;rJLG$-=}5ot~cRny%`;x9)W@)sLQb zCXQ!SRDIw1&N=smU5wGg7Mlv)x(eC?e3a&B%e`O`wjj~}1v_xmq*yWPE6mgQRO z%vx&z3<$)`LQ3iTzORBH_{sCUPtKh?_n#dJO;1lt0B?7@-RI*t&a~Fu0d|{U9RNrv z{Ys@$4#V)jd7i&=;lhP%TcM*zk1EgeK5e(#Psee56M!Qk0^p>SQYqyFumxObtutec zF8nwE6h+alYPEVv2=PL_UQY+U<*=$!>a9Ygx#52!5N1}DO69sz>Kkiq0Dy=nHpc94 zx7&AFYt0~_IF6eDo){k=e;>e^fo~o>)M~Y-(lmWOj^mpH5dcmIA% z5aMYm<#Z4PfAc)=$8x!RhY&&*B_tw39LLS|_4SjrTJ70Qr8{!uh%cr5ve|6jtF=yv zh@5i}Lda^hdMyZo^8o(moV!zNT?Rl(sg||&7a_#MX_`*8+wD8^JU2uH=bV#L`nz`R zy58+}4>cN%js$>GsdR9CeSNRidbKD41_!K^`hIqH_Wf-x0st&bPEOt@rMx%K^8`g& z#+WQk(>+lX9R^UB0AQ^>l%{Du>Vb&*p65lUPoI9%81wDfvuD2;{(kDzsYxm2W1iNf;sMG%a`*-`k|9Pv`+T)xv1CVphg<&}EdESd*7=Gt@-U|T!;+&f+ zF31#s8@*od-${}@+UxcHnIy^Da7BnnPE1Vv?3{Z}hGDoj%d*?7wfPVR*l0+tl4uQ8<2gv_yHHuP}33@P{XWbZLd(m`Z6aFTLWqf|&&)CR`~5{JWt*A*4=N5@FmrQhY02OZY-wr9 zFmscc#qdZghVE*TB;WJG!ooEv<&u=rcS9&<7DTkNrROb-h*m~|bxJ8;DYba{^5qo< z03pOzzVEAHq7Xtb^YxtyG4pjH#HP{(K_HoV0VvKTj^p_t2!0yQiin)G_UcZBthHB( z$PHx^1VOOa@AoeO#q@488l76L_E8i?pR`)73>#N8XXfC{nKSCjl`8_b*hl;J?aP@t z0FW14ilWFDLcDkJ;>8RY*+jI-QQn z^V~*JbbAy<|C*hheQki*w2!2euU4zo2>?&TaolXT+a+ec8=ISOOD$`y2H>J7y1iPh zUg-6DZ)^gLuJT%~<`dC}Ns^rCbUN!=>uhL0ZDkGslu~0+6!~LgW1j(d{rvg!o7!UA zpOa(9j-BrHdM~AEx+lvrZH&pRwSzMNHb#_GO8G$$h#&|SOQq5WGcz-DTc&)g->s>s zsgQ`C%=7$lt@ZuJn5uJ50UIksO1Y|(T2xA15<<+^>-FEQiX90J+u_59@0LADyX#Bbp{%@klfjqYIuS);`002ovPDHLkV1jPZ#=ign literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/left_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/left_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..8f5e09ebf89d06ab591d676231d4386c118781be GIT binary patch literal 2307 zcmb7GeNYr-9KK9VDM*qN%9L%<%xrIW?~B`&6Y=i!K##8|!4loueGfM8ZkOFX?zoT& zXOvS4HHbzVElSO%`a{Q@KBQ7KXat6u)Kb#0vNRL2DYMevh2zqOzIJAJ-+kZbeSXjH z_gm2mZ@-HoJZD80n_PrTw1INo z8J58P;oKrNyn>}TG;yfhrE(>RI@LX;I&G)pyz6ua^f zn;-$iq%&hIY1AX>l#VnLl-_tBq9@37oJhw>14fWEVWtff61`ApP2xOsp?!YT7W}fJ z<%%NGI35fJbwPtpkjik9q9~lu<9a;?5tv-%SC|mym(zwB>_BEEUQ~F&kEo1{TL>st z6e=BZ!6(LO{cpILG3^3w*$@$Pi1$uwuEO2y(gb zH`KA^>kPoqx?C|EBWm&aVkTt8Q3>6M24qCETvR0jyb#DjKw^QT63R?dy%A}f1Qm@-3HEW9^P*k*nnC9>i(g#zzHnm_*0&nu(fyzzI`Z%3B;nW9?Ee=Y4GCM$_{#w7 ztvIT>f~#F^!dw{8sb*-r$+%x=th~T&Ozvb5+gBGgmJjS@PO5 zQwOGPdEfcg)ybKsj+Qn~zIw4{R)RZo%fYT6Z+V7Tb^O`3qmg&8N0w%U$D~fH1&4Q> z%Q@m&ZSGmKwg2|k@0wnIqT-#%n8Vte_S)t=AMsflf*YABk;@fh*-L39CnL{KVd5K3 z$CY9oXSHAC4d}Or5nj8dxqG`kH?ML3^q!Q@b85rLPImSiN!`1G-C%#X9x2 zDetY)jds=dZ6DW>RlT^~SF+>w;sxki%m&m@*Q`3nFqhyyw9zD_~3E0 zVfNDn=QB1f4}@<$z3EsB$lPO_TG099uZ~6at!ob>HHYTh$2E8cBFAQYx+=GQ{^4~Q z-{02LPH(#_b^3v$i!OX@neo&3-j1C8+xq%n-F@@2y60AlU?BcfZOX2X-^%;p-XG4U zxJEB<@a*q>o0B&WcnjN`j&;8MTTOn_p_ybTdEpEG)EUAlD|xor{%UH{OM#w8Z~Qhq z@dI&ZFVkCB*Rj%Bf7#knF9&*)J3|W_`|Y2sdvZckXi4?luU+B1>bakvcl?t1)yws8zx(~) z|G0l*iHr#GnBp}B0057$P>Gy=dpU3SN%Zp{(r_F7nyd?rH2}c$ubsC`$@1y*0bt^Q zIy%M}BMZj}O2fgGl!D}BX>>Fi09FKK>2M;IG%^)rvRW%C!=yAqKTYT0#&jD-e#`I!e{~wX~daXnl!Be%M!DPc`uWirEN+z#t?7 zVSY4%U|2L5JrVU5aGbXa%D0sOlvUW zT7nFdh}m>#IBK;L6A(%PPoxroLIJD*6(T+lL?MI#RRRSmf)qT2P$|atODH14Spd%c zBWFQL5j4lI@^FGDf>b05iU^?qR4MpE5LeKpiXbW_Ux4~Uh)_7jwnnd}k0YM;DyvhK zl4cYkJRBx?Fo=p!1XPkV56a`KKt3PxR|s$jL1CV==!feF3soEF3}=rXqbM?cbd;uM z4wnvw6V4+cW)sd@AeHRVY4sc8@uw`0?l+~7H0keD$%u6Wr81guJ-I5Gj@=*BAosVV z8}Q8E7yjoGIil!I!e6V||6llMNQe|%n@rNZmCJUz!gY3`k%VynH&?@JuXL<2INb)F z!}0!0e~foHa*FT=W3|OgIuISrr{>v6fz-76i|3?)t`d&-SwBO2Pt561jbL zRN$(4Zl@Q7Jo$)QHbF9LZ6xzOMu3-Or+lKj@5<2GYuU^*hD&Jac3D0rKVVCXOYmLB zls#8tcMU#izH)Ec`=-X5=Va5)>j&!w_xU@nm?o*KaDO2T-~Y5P`!6N(O#r|MJXHK( zu(!82AamBPMH8{S=QaDto5hUoQw&ACH1>Mjel(O3=qkOtuo23;7B_UNrpEJSYU^pD zxqs_F|MNmr*xVzsnHd(j)OF>|El|@WmKkn3s_8I+moZasO9^F~SiXP151_*e4o6iy zl(^6AopW&QWaEJ?jEl=k3I?)o=eIqpi#W2kIKOa_SPEW#hPmg*+OlT=#(4)PY~S4F z{n@(D{HHZ$5jf7`yzIe~rFWO0N)Of}(RQ0h?;N+lP=n2$&lLGtSMcsV2X3VBRo$Yu z|AjhwpT5I-+J9Qpkyo{j7jFmiSZ0RKW`FkLrDgRe_iqVXi+n<2N=a|MZC3lnOm)EL zZ5zr}q~mtollJ!Z>bNRl-&fi)d4I2FB>+@BtY>t0S}Yd&XWa#WWDj*0y1eHGe&=1C z5Zvf%E$quKhM#<(E>HTr$M3;=-O6^^P?z4X!Rgq*T_F?sqxU z!nhc3uU^>v^xHGX4Q1S<#9QAd@3{5e;xKcM=p@kKiW={<&f0N0oh3n{cecg3HMJj) zUUr~IWD39je3^T`qqMYiHF)Px!qQ`V5Q<_VrX3jOXjuft1k-Fci-V;`t%K`Hyd>Y+m|tgI{6KhTL3n!n^P8|E|5gM#SS?S69bf*}G)TwL=yCtTS!p@{Lhas_Uza z0j?{s!Lv!$6q5>h-h0ITTjCLQ%XNNm@wL7Ldu|c@B=hXe^LMfn=d+@tq~zbXYC42a z({kV(qO+APY(6(X_}@|T7G*IuyUWaY!E|S^eu!;Oj|f@&XkB?_A%pFAv0!6bN8-Y1 zll)yCxZKIC-Cum|Y`tS{e@xC#he0=A@*A`(CMn5#YGdny0^bu;Rh~`z2J9!7%%Cge zqlmsu_Kd#VuCB5#`-^s2T#r_BvUKZnYf_D zQFOH`r|xH#x$>;vrdaoM=H)ZT|!NL@vP27#UM1d4$+wm;k zuLBM6EpE)nI%2;M;{fhVCv9y0%=>a}PL)1S;2w-hdEYOpYsDld9g(L;@OEQsiuG{{ zk0<+u8ly38!UOoYn+x_}qs7reMmf&N>(>Y;aZGG;$Ax)3hx_D&>x3A`=C3e9JE!oZ zV18MCFJOh$&A7gc+lAuW7!|8TN9bdSE3t&#I4H#Wov6^dZRXrvy&UYDt(iVPOpw#~ zB7sYHI4gAXWinXLbz8}NTi5@ydO&5X*2J!~2HV5mBH>G>i}IZ4eU&JX{rNn^*Z4+g za5q+KVBK6h>fw7K(ph=xm~2OhzMpIN;s)F+sE2vRU(-KY-?OY?8HMR8fxaJhp);591$hD!-abKF(fWk3YhGn+N&F$b zgU9M1ZH(&n6kZgqzI5;nlkMq>ybbey9IxQhHfOVdh>pBhwEA0wZWeQFU5K$%))D86 r`ac2HZKwEwEXTpB_<=kz&*Fap^i1ddK>f3?00000NkvXXu0mjfSRk+b literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/logout_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/logout_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..2f772da7064b0ac08973d1f55cb1a9421d0b9fa4 GIT binary patch literal 1472 zcmV;x1wZh-IxdevyHh5gu(BS#+degA1=Ob-A6A~v+vcNP~H|JaW|?gcbGJzdaRk1C~JQc4}x zS|701761SUA&OF3<(%K8l>Th3y*58T-}ui!r%s)kXti2z$8kI)rOcF4(io!wpzVN! z5Xu;HUDxG8h~FH?Ie+=`=)bL0=e#Hz=iV%*@Or?M2qP zlXL!I4zh-bfQW>1UP43y4^y_?Fw3%3YaIiCjiP7`0FL$a^n3~cZ|z`IE|@8b4V$*iT95Lh=|6RP0sn0QtC@7tWp zZJM*Th=^KinIy@fAPB|)V1@wz7-L40B*}IpACYERrs6oRHk-|8JCG0}qm-@y0BNVP zb6rZQJkL7{05fD{WaLq$)M2GmvResv`;Ca)^SpcYdi_lR*r1e_I>FkkwAKToqoYp{ z-}i^K)(4C+I~V}~yRg75pT@B3k~SoA2R&-eHDUszpT{apz0i|2Wz&UP`z zWLoQxb3Vk3F+naX2DS!FbrK|%$l|KTAHQ>V+=|u*{xf*;_>nE(?W<# zX_^igW74*}wU!%Wie!7>|6vvp!S{WMh`ODH?ZyZp4MbD`AfQWA5<(zN)4JBWtdz2F z|KiU8fE7XnLWre-fq~^XjxQ!j@@$r6wT`X@=&70GMgM&{dNiwp%GIP=0Y&06T$lpn2mk=3^e5MKc{dD1uJgZy`<754N!1 zUQy+8*+s<98;!=R^?JRT-&vlit-_J}S^xmfxfcY1>v`U{0Py~mD_6F(%C3)-si~>g z(=?hd^S5fJKrtdp3kj`i3uMOPh?s4qEc!= zYaLo^c}}mz7~ABWuW-(9P)ZkPW@cKu#o807)5gZe4l>3Dt+hS?03oE-Xf*CrDwV(Y a!*L18!5Jd!rB}KayNt*<2mPj&N)vf zBCG-xp2Bu)PTn<~!ymXk%D~u&{RzB@U3fm7tjoOtuHbi^!ne5|j))jWRYdHIh@T_k zMnqhXh^rAX6A`mXGs&Beh<-$zi-`THdymb|kkqZmXLt__xRI&(7vs3zh<1P;x*6#t zzQKW%UooPIh&UM$HzVRwL|n*|pNWXqB4Roswj@m_?@Y>Eh=_}+`+Y?8nzpNk&kl}Z zH)gPyybdBGTfohvI@)N-&ER!>&XWD6qrG@P1#8F6Lv)jB)a$k!%wi8dXgiw3M|sL< zDL*Lc$mVevQ%y&2V4L!z|BI8Rvp$~1TeYJ~sgsdK_YfFhC%P4$REn{0ZKA1BN3|7C zS9nRO_*-k}q{eM*!iyCi#UsjfUTZ8WMZTdLCAn6pFsJ;q|HEme6!+B%zu_Oti?NMR z(hwtfZHy@${nrYADy@F~DwM_>>v8uVGm$pWlO1E%O znLTq!J$#sZZTXHepN^*NvYYk=zQ&e@0?Yf>k%s({pX_zX|EV*P1qj3Qs&8Q z<8+aSTBr0b%70z3G`DJ*DSU@_EluO0qr9gKtvyQa`;EN~_$j|%m1#*#7`G_hG3?K|1&f+htXvlW}Ct9d&8l6_n00000NkvXXu0mjfpqY^8 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/modify_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/modify_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..454147eb5b1723ee4044c885c2d75242b708eefa GIT binary patch literal 1365 zcmV-b1*-aqP)nj32>E5+Niyns~?z(QH_S zu*&3^LCHZE7bTm$1RW&?OimIcGvpM=VRQ0}1;t&|TXsHD-P2uN-Ss?d&p0I6Y@+)= z7XNxbUcGwtiXb99glM^3ej*IRXW}@{002-*`L=D_ex0A6Uj=}8vjF5lpoN8n(Hl2z zyyCiUF$jX~Q50pBQY-;QjIoYk7{6PVb-hq1d|#{8I*$sXM~@zTt=(=nmZ%qAbhug%IJcUAsb9UkokF@(Cd-@elw& z&iNVuOx?P5>k|N|^pBDDDWy_rf2Y%Vopat=-!rHMAR>w5SVKfQv__M)fiD39=X|Zx z>Fh6+N^cH|4ggTCR&CDt4Cg!m033$=2N3`O&bim^cHf6E=N+}gfDKnnu?WA!Wr;}&po^IY6meQ3{DZ06LYeY3ofe)A&LI@oZ*?@w`gb?~hendpZm|+;k^1{Nx-#P%qqobqO4a3+MhT;7- zNJJdtoF5~Eq>dap@*DtwQYyKWkX(TI z`T2G_o&MZ$9J}uwPO8`IMXu`}Ycv|Ea=Gl4%Vn?GY^Ge-J=W{>qPzXDJ}ykhaXzip zYTf_@08p>jzsh7XR~*O5C#6Dw^$wR(3eNdNv)Me^_ct1ilbrJjDdq49AR>a}IJrzF z^G&^8ztZ;)7gJ46PQJgiw3G#aDb9Hd0FV$uD5cjMW4d~oQ{p@8DrRC&Q{%tC^LRl~;Y=pAtemC8f+LwSH46rIIn$ zHVk7ql}a`D?Add*QmOPdiuFLykhBvgP82xjJCsrmB7&~#osp4|U(TOD|JVI8xLf}K X41tH^eF3!C00000NkvXXu0mjf{E2S_ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/move_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/move_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..8d70c9f1681d7e473c977fe1d661c704c59cf61f GIT binary patch literal 858 zcmV-g1Eu_lP)pF7IZ~ebVG7wVRUJ4ZXi@?ZDjy3G%qkX zFEKSnS1wWj0010xMObuGZ)S9NVRB^vL1b@YWgtdra%FdKa%*!SLsK^Byt0e{00Oc} zL_t(YiN)5xYn^2j2k_6mxrvEsuA0^*I5>ntYrB|D!KDyLQwNcNI4IVk9o!1RKS2U6 zp@R;#=paH{IXmr zzUMq|ttbiyloxOs&3InN5BT{Y&W(T3_u~R4a0l2MyGRt9Si5-0~gfjiQU{FQ<0m1<@q$XX>xmZo$b^V+1?OFDek0%NvYMQ`DA{MsQ%A#KZ# zcqQI_i&1HNtF|>9$GiBdT+slgvDu}P8hY@dM2ziN_jIu>0&6<3_X15y^lf!;EHH!{ zSioTX7UJEI_W6~AwE}aJb{|bh)U5`nNoTQ(-*F8uhyFV}2wf8!9d=_Uux~anQmH0q zHyF=10`PL^a#N0m{u4ZhH%nVqt!ku>Gg8OzmMUpt1yi^fKn4Dg`eQ5BMd&Vu?MnFO zWOoDmOkLXJUi=-(AT^P3qDiZfi4e1LyHI z#-%=4lxA9)T}8ZG44d)rIUg7qe;XSOEJ;&%SYk;{x&ls0M7Sl9p^j&?$?$o`{+}=CyjdcPvs`=#q*>m&otY>^SF*nS#e|+-~V=%m*vnu kPRep5pIcS=Palwv0Vf~!efy?m^#A|>07*qoM6N<$f_WNxZ~y=R literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/move_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/move_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..3d7bb6c9f948d77039457d0b63570d1203b0792f GIT binary patch literal 1353 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 KMNUMnLSTZdTJO04 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/next_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/next_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..3c6aeabab484b15a6f7a3ec5022a5ad887476233 GIT binary patch literal 986 zcmV<0110>4P)H5l#qt@ z-2|Km8i8Kmg?)!iVHL0rXacqXAAsw?8{0oaTqMPRp`@&&R!Lta-IvrTsa#SU@~^-r9d^X zA9xQu2mS)nDM^A0ko=5dmj8A)3ueUj7^ zMJq~w;qF;4@Uei^KWtnE+yD;Z3PC1e{WS2|uF4)?3AhT<0KCLijik#t1>6QYaN#cl z+6}rQ1v(CN0=34N1yF?Tm|_KTrp_Yl(Yi}3>wDv2>60K#|j@%X zdJTAFd-A|dpgCcE0Q|OfIUg8Vv#=B`Ujn=i69Ff1XHZ4qYM%$z02hHnrf3W}gFCCZ z2v}v~aUVDW3Cp z-I4|kIvhr?~`g)4a+XWKhys714mB%~|ubU+&qkP3{@tKPy6STy7D0Xklzk zf+^Mymu0q$Pb;aW_sL1c4L z{q4e~ez#?1YKbfa^udw%4`Jah^FQVu!iy^_0+?ig62?Wzf4x4lc2)*o6aWAK07*qo IM6N<$f_YY(!vFvP literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/next_press.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/next_press.png new file mode 100644 index 0000000000000000000000000000000000000000..1d8f93e1a603cccabf5ba0592490ea9235dbbcbf GIT binary patch literal 1479 zcmV;&1vvVNP)#QmlIYzC{p>NsNH|+b${!^NJl;R~eiDWpx36E?eVt{8B6;Mq9D`+Z0~N^)W|#q5hX)>a&+69@tVC?Mn%ntmN$ zc$nDQt4J+H;zp5|C+h~T4?N$e(bf}WW_%mDbB@i~?c$N~B4nhNwM$?B0 z#7@%MeTlg{3+x^(Jsx;*KqI!Ukq5V4$IKo@IdKqKz%KjL#3%>QKt&MpA->QF+WSwD zNu+pgWC?UB@LaFPnhlL4ZoGw=d*4+=p$4StK&!z%Ab=4(LFY4H@o*wltyC_W|FRC+ zdP6+8^_mAWJ(%zw1xmTQsl4~4yX8G5ki*Kq%hc!_v^*W+*L913umWuD^)Y*AD`xhn zw|&-9RRV-xAPj-@3xw{0sRy=!0%qaX?gnOI5SAQ8G)1`3EQC3}$6Kii0{)hj?>*r1r*3+1C&PRzZ#Bl-iW+ zO=M>y{J9fJuu;10%IO4AeNd`^Lf{k?g-M6;PctOW6#l=y)F#uBB~zBbC~ zpqOqT*eE4>0IxR&sdSL~DxJKdFy-*~@hsCn7C?dY3wl3_()5ClB_*`D9KerLGSCcU z-4g!4mI8@wg48YCQjp7=B9K8rphM%S_ae0I3xEKps2KY=P4b-S+0}L;3FMKwgbQ zhe4(Rt&U1SDg14&y;D%!F2gd_%4*c1flT5L4`b#m78RxL+r*x@N+CT=$=nBGzRJ<7 zLnXQU^#b{c5}Cg&W`8PTXVePH0M&rz`+=seYs}rXq566n9SV@TKS*}&TTnsVu3yu< z4dLFw8mN*&*=3V@ccdR7=83c&B-(L_fwLx5pURorMOu3<;tQPs0-pNv)(SWOMOTqi zEW_$4Q-A^J_#&UvvSEaoF|+)!0^B>Hn7xyuqyH2}@Jk?sdzn@pbs=0AA!<$|RdxZu zhcEOQ?Hj*mdMw9F_bT~$WW>0fSuNZmck3l-GrRjg}2zX2zc0}X2u(@~Ak-|7nwv+f h0Qr=|&TFd<@-OquR9s=Cy>S2l002ovPDHLkV1i6*oFf1L literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/ok_disable.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/ok_disable.png new file mode 100644 index 0000000000000000000000000000000000000000..a876388f3ca4321085643e1202a342d5cfe36a30 GIT binary patch literal 3322 zcmVSPY<^1uw zERs}i)vfB+@7;4gXSwGt#LW2r+>GlL5MTS-2w9P8A{haZ4S)c+&?=+-@nrAT6{FW9 zpT3L-Th||mlNp*1qBwy}04{^a0dfHV%od130BisXtS@ump6PkM^TPisVB5ySv&nG2 z0>EMBZYcMh$_{r&?~7mU1%Q^v zch}2k)9pgq^B`m;KpKPq3=Nco5kLZf1XzM~mX-T~%8nfB-MXR|0OC*VsgaS!hnZD( zV$-dA{%XLsr;dGfX_J{zKKTde#h0z5NMh-Iv&O>uIF`xA$*boo!t6N+{HJ+xN(I8(O*^#?EXOzr24jzG&@??ADHr)fJ6l8RDOd4_h9eV6<4B*9}{-d{0GT!+5yg# zDPrWoAccT!o3Jedra@#HM7CwXwoOPOidk6%&3lzOOVVyOtJ@#0e_)f<_sXgC<73Et(okas8d_@wDkv7V z#qp+)HKnDlY4NP#n%53r>^?PI)o(~sO@d^QBpHe=Bcg6*?rD4Gc-pL)F$X}`gbNCw?O+-}8;Q}PPB&``OPrlU#0MP0*q&a6oh#S|uV%UxI zYL%Pb4*Kg&eHuoI1V#jh~V$4e$HcAsMO!8CE+0zubF7fDT-`dtt1#z9wo1fnqP<;Kv7t-`jd% zxH~cAWxas47qGrG=w)9zFnsJf4hj(kI0XPQTo)x04#1_|3K;MM=Bc%II2yKWFk>VgWDlK9U#YO9EDKjD zr3pZVCFP;B>5r3{U>wY-3|rRJIy>wu=85YLGZ8t$sfre!Qy>v3n zWffxX06*g`nzSlq3rNsskC@boU@n0CW>W`#A-qKv z0_C?OsT_NnnKgrB6*3gF16vA-Lcq$^vSzRp5>>XcV->POGnkoqY@9v1YUx!SV8zP! zkQd|t@U8-~&H@w#0G%7l0PL0x1_3N3=)z!-&bZoRX4F-MLJOO@QENp~3My6TB_iYC#36Npd;NuCzR`{`bzWYv<)j~-B=Tg8qAt9 zuJ-nHr9LX4O-Kg-1}pzks%rc-u3_(;^gW2hgS6)EQ}n zI*_*%D3lFT5}oSFrCvWdcJ^CKV)KeD~gk?R^8umVuFU4gl(_BTh?w%!ZJx zl!7FpT_=-g&-CU}jwwXRGf75Rv|3_NM@DWJ>X?74SHGRQ)6;ii{1-sFa3warX{}wfVQVkJO&QV zC!Xtgr})u?yP06L=df8lZA0t&{nL70Sbi}W?%rkA&2A=X)l4cq1b~f#;*W;B@$(K`e#+n^odhl&z9TIunsU$y^T0;lf(D!khvj z1Qq|_2YOyy{viOgeD_yTqq6N0W_>xaY00lX#lX+MJZgLT z-LDhLS=!IM-t+t&-2gyD6kqrD46-A0NtjcJL@a-KS)8q`m^lYlBdq*O+D)D5ed%i# zOESOz&H^&*yI2J$63^Xs@U!%Pq3gHSjfdw7Bea6S{d#<4fA7}2N;g%`v<^{o$3In) z6^)WK@;f5sdpb9oy8P-Br~3bb{m@ zKo3I)r}cR9Lhs8f$3D}zb-%A6D>9RWoC{C|>)>S1=8mIZRPSGX1>CsiC$?38;{phI z1A(Fp_5ezObsC^teu{GiKoKH}aDLM<0v()5zVoB^Q-9i~K2OJW0hYI>hjutdRZATS zvlb-6$Zyjb%pO>$So=fX;JKkIzgXveSsm8}_CffOaK4? literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/ok_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/ok_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..bb85e273318897a7a2ef859555f633438939b40e GIT binary patch literal 3261 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/ok_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/ok_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..bb73df64b8f23facfdb250bf3567b314cc4e29b6 GIT binary patch literal 3278 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 M07*qoM6N<$f(*(#D*ylh literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/option_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/option_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..07ce91319f9e13bf014fe6a9832eecebbff4c1ca GIT binary patch literal 1022 zcmVl?t$A8~t#>W_pOSx{;aN7_kAwsf6n=zbDlRPi4n?lU_LOx zzkdO5fR7_NoUO244XpOD0GJ4j^0fgV54;2J19u&~tfYqVXgzQQXaEL*UVj$DSvNEX zQ~~dSR^ZA=fwI6^U^`F%dLqT;Bq+!MV}a|yJ~wPgplaY6&=1Cr-@gKzfu|9zjqa6z-#{}kE(TiV z*7snXJOOqAr-8#*4J`)xT}cem;^!{-ToL1|0Mr9(VxZM-5pKy2;G2hIGSKB=86QQW z7C7o2v{F7{`hk^TsXP@c#)5Ae#E8F%@w3Q5_PMotfWF9+)BYSxfCR7R05h||LM$c! zL>u}su9o=wc3=#!8{?_NmA4K75@Zml0~*p8S=E#(K7bXYaLD)6cvv3;mnwkZI;w!0 zWF5s4if|He5lh#+ueJHy#01EY{VeNN4`88DbRd9S01hU+-HUNG0PM#&6V_DYgh*qd z@5%zNfbW!e8V&^DIF<hSd-0r)`Uh{t|&uu4cAIP)*EjFTm2jO|KjV#TK#pmFvT!MNQtW+tYy_< z9b-!jQqH4Twqf179xKcOr8)~nX0Rw^Fyc=Fx5`>n;lHjHSc|p#xo&Zluk~T!4Vl&E sb7iFxP%N{sAIMt&{(=2Kc8uikUzwcq6cZ_(5C8xG07*qoM6N<$f@nCw@Bjb+ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/option_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/option_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..94de36dfe67a2af394045cf7d3acd21439e9f78e GIT binary patch literal 1705 zcmV;a23GlrP)FMda9mly>YwZI7AYxKg)w`>!tN*%_{dhaj+}xZ| zRn>z^sV^v{K2=rK6cHH!0E{ukIgg~2?{Ut5MMQ6`tgIyeH)v*N=4e@#r_watpXYh4 zl*+Z%6#$GkAY+URAuP+Xq;1>po2L27;^N}Z?g-TFb_D=@H%-$M{eC}JN~MShh=|)I zpiu%Lgyp(!({Y^nx~`wOc=2MsBk0JHBhoa@SEDF;IF92FrIbtv;S@!YXszp=U;sc` zYXku1`~FlA1eZDIU+eXH**JhrMoTHrMp5)|zu&*fIhVfg|IPRPAGKPoT1qKt8=Z-W z5RrMFXF85EOp@foFbp54s_Lc5xLcr3r}M=u%TB~`d{YQv5|OU!`d&o*t8LpST-U7- zk!|H5A`gO~*=#nSa~$UlAw)Bdz zV=ODn^2IO=ha>ynGEAQ5s;=w%0RZse!GpUj%lhfY#>PG(ssMn55YlzsigW%K&iSWJ z(|mJbVd0sXnVIj!aeR`93d1m7;GCyrS)L8UFx$?Rh$vdE)<1~oQQt$J{MNyoMq9`MxZLP1huB)mFEX&%@ zwAS8etmui8AOPsPu7~3)iOBFg&z_&3e}Z%V2g5La7)4R0wXP@S+R7p#skLrywd+>v zVh{u^-}hhd^?E1IojVr+04y#p{*rV4y61TTd~^yJ^=`+($rxh^A}ZK?d5MV7_x+ad z`>!o5ES#RK_W1GRk1Z}Pp7MSFC#_a%SEJDgY}@t`QEa)?3=vDlSj>0t-d%9cAIkH* zHIk12U|h*22mrwK>(|c|Me*YK^XG$W*RGx3yLWGei1Up`6>1h#Dp#@Hno_a%P$J^< z{eJ(eNs_Q~bt1pp63Q4}KLJw%iu;#LU2 z|0W1S#QTV-)>;pJ-@hvef{R5_Jhv%$>s!|8bSy-CIZ2W)#c@2W>pCAvwc}GhGEu|x zJgd=YoCAPwE-fupw*`&Yv17-+TolEVS(fd~^ITO`m5;{F()Ir3D>bm~CQtA^`RRu&OM-`Srh)_zoCZ)X0IbZGddgV^JZVQ@R zhYlUOM+osrB60u#7-Rh;N#4D3<;s8VWdDBwmZU|-9|-Av00000NkvXXu0mjfzyUL0 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/prev_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/prev_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..67fd8ce96017953333ff7672d527049062f3c331 GIT binary patch literal 1618 zcmV-Y2CeytP)jo) zJtkJ~>T2em|L>i1&pqc5Gh?HRPi!Od$^_*S0Ki1BVbzL9zumA1-3piF<2?I+V~=R)$Bt^j7oN2Kf!F&0mFAzxlb`bY~%bzqD+*3{(R<++=R@M`_Z0J~v9chmRSg0O1jYLl7?I zGHnkDfB}%2r2dk*eqoOqxYJnyv>%TW*jAEo@esrIb$HeVra`(wdh}_nUAk}U1OU?tsT*jMH1-0vgjP1vy0Ecdcl$pr06~xJ_naU8CJ_FJBw3_966<}H01%T<25ADp;i4t4v_wKo1FTmX5`k0ZWYL;S z$D;Vm%Qe`TnKS4u2MX@JzYoYC5fJ|Bci0gcRzzZk+@2+l7OkLt=YisFbs_Y>0m!vM zAOa`MX3?5Ue~aQXzpWvQnAx!2a-iVsc(zDF=4ZQlsYt3b2>R>v@MIpsq-nHU{1gxi zIkeM|0I?E!`sEt3hyj4SL4oc~m0Mb(rk&yh;<^FyO2aq4O?B_>r{l18!e;RSfU0Xf z6#$zS^zyNg&4Lw`-8!9mH)3W&D;rlA`9Mhhp;H+-X{%GIKxcdU{C>yOW*!LZ*WLtk z89=;N01Pld3Lr^f3y=Uf%{#}6R^<>Vbc5TTaVnz|`0>9YptC*AO(wd3+bQh?ujZbw zN}#r%f_O!o-?Am10-+cGm$|)QL;Na%$ zvI_Vq_nWN?F-b4zGT5Fiq+&G26ks zgS6}HdLxDeH~_@Fb_##=hjzYYYqM4H$i?+XjOFltG%VGo9ez4@eoxd~IApEa2j<=` zLlm{%E=hoDLaGVJtNg{;wEfHM`h|vk{K~C|sP+oq_2CchbRbp9%zwAr#El27HM`l` zVE}&aX+$Jugj8pgQ=D)rqbDI`HJtrV?Ej?ERrr>Ju=!|+bl+A5H_&KY4>+pzuuU}p z5XqFh(h_WJ$}I{#g&9-sdI2H|eY{(UP6zapT${D+LWInT83zZ(|$AK2Q};I@`L Q=>Px#07*qoM6N<$g8yys2mk;8 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/prev_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/prev_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..83924b7bad38b86f9556ed53584ac8676fbc06bc GIT binary patch literal 1006 zcmVNO8L@@F0KwE8p25arxW8ZVy5-Zuc=bp3A`u19T?e#l}B>vJ8KpEE) zvbqTZf>nS96oRk*) zcLi_&SOh!*ZUWDN9}aB<<^!vNxxg*pIPf^Npg&DgJQ7KDk~$^5k#ts4i=?TNN|K6_ z3Ott-Z@?a` z)Q2+)s_4bC7FY^g^@18m&8Y(>0cU_;zz$$AT{MYr`V&bjeARg=n% zCmdD+x`ER<3mgG{0=+5B5g@0XTq#-;e|C1@>Y`B>^@8 z2Z34m%5y9Mru+3^8rX+*{dv?zJ%TmsE5Lq-4gp($BfxA%0b$0fJs|V zxEUM^xR2@CZoeL(_J{=N6|4m=0j`mKZcD&UOqB0bpG0cW>;Qkz5T{z0DBIIPoQNggl=aF;_nWNKbkhI(g2HC57PhaJ*50vtoP zdU`K<*AL)gG)j^hJay+};@#;!YV>rxkEn&%N7PD8MS8K1sLx&~O~4$i^qVntIF>4s zn(EC1rolx_Xxp%^KQq*uKmUTAvmW3sqiU1scsyWrp8r;`_7~dOAl4B2Q*+03I8k5> c|L0Hr-)|kTsy`LuxBvhE07*qoM6N<$g4Fx7_5c6? literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/prev_press.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/prev_press.png new file mode 100644 index 0000000000000000000000000000000000000000..2742ebcf89b009801ca47b44811dd743bbe5ca1f GIT binary patch literal 1488 zcmV;>1uy!EP)lsBfBROpK32u@Ugbok9u$xuhLhXs0vNxt%k6`*3E;v>gO>C6k;<)>_~G z*Is+?CB_(T+5Xrlxb1=+6#)D)l(L!!j^1(-xhe3#TA`!Q#!W`ZPk2;v33SZ{K-oTS zGEZAqfl}5ddpTg!>3>XkW8ja=g!E7pT}zR@ypihc7HYvdjP3@I4-7BERLHIM+%bx#Gx1}sEPVL5w=b$mv5 z|6wN1l-P8tc5~qG8!Qs(b}}P7@ry5GbSFpwXaviG9E}7v7!OeyBHsHfUGo*$OEWxl zavpR(@W7x&XJ3l36EEVIUIEHL^#-5@Oq#wSEVo4@{x0dEkGXbkhRvgMP&F62uTSW@ zGtT(P&N{4Ehsk1?G2u_wzvsX*x5#SoHLjd~nx55hep)dXc^%k25M^@oA*#if>On#4 z@)?8JprV2}f<&e6)=(&b4+K;TySaL91Kq15^MMD41fx@wW_E$@Y*N+&=78NUEPW!% zz#fm}IvW+0CZ!E%1*3Z@PCtvXk{nno0O5H`Ew{OLeq-2;Qed$)lnHi1k$%!;U{4a; zQ^fi#PP~wrgP;m;D-vMo`E0D(l_h(*H&h6%mvzWWFnM@sn9ht+9u# zz%{hLf!S*wf81MC#M%{=Tq3+dWI?0Ul{ra8dWTE@o)9KBWWFnM_MJTCF^#U6y2^z> z0rAm#8RcApSi7>Z9MClfh;sb~XYoYRYu>+)k_CGkGtIQs)yTap<>eH+sYJB zLD@b*6-8-A<0kVcH3r6+A1Hze41P|N`KHX-w?n82AiX_K|LY#^GS%W7Hq3yr5j9RU zk*7SP75DuK@g)V6a}=-^7eNH$8-ko>ya}oULwb9hzUSKztGOZz&Bn5i<8>9d=l6OE z{i08_Z6B!VIg+_;=NZ_ zzMz5Tm6x!2e1oa9g4uveB>o}Y0|%KLtuzu`2R?cUCPs@aUGp`O_`Bf>=Vq4$Un}*-p1skCVS({L zO%aKIMDO4i2i!JiB6n%YYb-aYEEMmVKN^+c2r+hf!9R z%*hImjkQdC^Fet38liKgP1JLkz3NfUCD4HrMq2@HGEbtrK&4P+>O#Q7r~cz0+{%7i qFT_#`#|{7MnxQylxbM&{C;1y=q*evUa{R#n0000pF7IZ~ebVG7wVRUJ4ZXi@?ZDjy3G%qkX zFEKSnS1wWj0010xMObuGZ)S9NVRB^vL1b@YWgtdra%FdKa%*!SLsK^Byt0e{00K=( zL_t(YiLKVZZ;fFT2k_5r-*S~UC<($wh#!N=AZATjio_t2CStK#`~zY@Vlpt0iY5lJ z5IT#&OeG>FQW8JYMqB#h8qV{iuiLA={qaq1-n{pD&-tG7Jl}K9Q>oQzn#4Bj#rpI< ziZ}SsjB&BR`YQCK-#%=_>a;eA?|6$rJWk{dQJE*BlemQan8tW|&ScvZXccXEhwHf8 zEKz|QIEM+0l^i!hc2LDS4B$cv?7u{-a1XusmZJY3K_kKnHsKjgm&sb{KE8$%__9b6 z>DyYe?Z(Z27E2lRinM=}qFV~GZ5Pg?zf4rcbL zz%CqP_KbQkwE_h7_=BT_l(&dtoG^Q!6|`HppzARub|w3mz;0|Wa6nXi&L|h+OMF6W zlO)sFii0Iz)7XIh1v*9jWI1=>A^H}XO~xIZ676V4bd9z3b+i&_D5e6xM1yP>dpjz` zF=**qmz!&g5X4A<*P=-CIn~nhkmZY^5FP$ifsdlq?@N*7)W_!fX&PC*RSe;CKBGY) zh?Pcxr_8pXPP`CPG}qH|P!nhV9!D^qGaA8FF;8;Z%ORabL`nY_Jp( z*o@nFlo#p;-x@p+P4=tBjfQ(Pd2n=$?ihPSM>Ate4c00000NkvXXu0mjf!j?~$ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/remove_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/remove_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..b69a612b704d34e89207fb4070e7604bdccfd711 GIT binary patch literal 1131 zcmV-x1eE)UP)pF7IZ~ebVG7wVRUJ4ZXi@?ZDjy3G%qkX zFEKSnS1wWj0010xMObuGZ)S9NVRB^vL1b@YWgtdra%FdKa%*!SLsK^Byt0e{00YBG zL_t(YiLI8;Ya~S!$KR{2np7n-?IgS49=rw7&B2TJFu0n;iDr^uKs>m3^dO>pT0Dyv ze;|SfZ;K$p4oN1Fm?2T-AMk1xmc^5@LN+^Accyx~s_S`3&oGHQv&pPqsMD+W{qSDb zt7;@7IFBlo%9UcV_@ejz82|u8jGc3Ln$6~)=gG%mptZHNf^%-pTKk%{_NsGkl86cb z0E{sk1VLK}aW@EpUy11Ft*x#2!l2dF)ul8|Kk9TkGf9$U*4o5-?*O2ifQ+$#b1tQn zLMe4`Y;5eCjg5^T&IMXtUgiMsS*O#vuC-3AwH*KeM8wA#P;S6Em!(o^qF5~6&a&*| z?d|PkAgEfcim|b=@7nG5n_BA!06>EP1ArKY;iYo9ydMO?d-ZzVbmOdlvk>Cb9CC<= z=Z17EMnuwDAGX`=SDkZT^v8RkTCMhmG3L6~`a$l0ZpaxPXsr*AkB`@Cwc6XKKnn{C zGRv|XTI&Q(KK3Y(9t;3LYkh33{jgH0lzN~-p>WL@Gh?ka7irf(5+XY15@XDC7>4sb zkoSJh7?bsHCZds6zmg=eS(aS`0KnPV*=MDc-yag~x?L-kN?a-R8vxuVB1S|*+nJwG4**w;F)u|?WOH!l zoGVKyXSnx1%&!$sL@0zPNh!B>c6Q#sNHtwmtJQCfF*R##oO=rI{RDer=Kmzl7>g0n z0)Rq9a?V9blFU`B)eRW2b03Zm0 zU!;`cY{Dq3UrH&?7~2EL2Ucs{R7&0BoJ%@8bt8y~NC=^nQU__8?)N~gRx1)hd>w}2 zM0fAgaNy**kU+!;%7qZ) zVHnEs@$p*#aC38W(+vf6wX(AE&Z9?^*FzwzgtU7OGQL{JOp2!dw4UQY*k4F&aU xet!Nr&iM;OR0IHEjQtbG@tszyb^kp1{{ldXHip*t8=U|E002ovPDHLkV1kyq{sI61 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/right_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/right_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..1ce563e4838b60398255152e74bacc767bbba750 GIT binary patch literal 2300 zcmb7G4Nw%<9ltpENl;Ou)rc(XC*t0I+;PWlya2f)-l0bjh=R$0d%N$r&3){$yLg9* zZNzb^rU|B6ZH=NqgS9r)LDoHC5e(tCR2$ON24a1n743Tv_lfRGrRlt zz2E!&fB%p7pIw)iJ3nsJsu3><6IIEwT^RIdfi z(hMR+&OF2_$^c2zn=plO}?ujB^o+Ak8>o#z_N4kPKmB3^WqCP-so&-Aumi z>4+`(WkEfvDls@73)0R|gTI9ZTXK@1=o zBkK|?R0|4~_PgMhqO<`e5+)chJj6;ksV6j-`hYwa#Yq*iug^Ho;lKy{AfPG`OGdGh zM^r_{BmMw&bol`TFtko*)W)D%{Qjs3Ma^Cg-G~HaP_$B5DFHkmC}M@of$Zf_<}}S4 ziLuInRYkc_6nz7U${Uc3SgpwHB|?A~gG$PMaA0FqU_mK@A~7NzBaMX=#ZV+;Fs2ge z3_;8LIrMWR7utfEhpp<$@b zaR0o+YR!{Hx8Q>dO8)$(5J$GvMA9Y`M(N2uxlSkJ2q-EW;DEzsL1Ae0g1|E%9T0Ak z;xSV?Nn;#mG-K&3X~fbEZWG}mc;Mz-1N&_vSD_Vvw!i-@@FE8}zL!TEIKoA{X^bRc zfx3awg}KaWZj9ng>9mPA@@AeMV0%Uu;BjPq_p@rMc*tntfRS?305hk%2#hltDX7W~ zM--a|fRQ#qQmyFw>WHxm3e0e25o)NzjZ})t3g% zZ~d!d-zJbSytiXv*niOLnY3y8!P(;s(j>>(nd4&HtE$j=w07s3rvGGk3NF=UcG-WO zH#YF+P1E1^e7;!B!(vC~A4>V`Z%r43@-yL;|GoX;?_MAM=+)+{l^xeDM~{5oyuDlU zhrfF9(OZ|!{4-9Pl+m4V#L-))w%Kk_PqyUF4KFPb z6S~xc)fKmgCWSi>W?H7Sy;0PfasC*VGW-Vl%J`5u@wxGyVJF@hv*p~K2Hnz^6Me^m zp@v~SuQlI|FZoMS<4E*kV%?RgFD*^=?pzs4E&XHM6Sc#R_c)eG@qc3PIkW5PtCM>7 z|K5>!O81L!@}dLB+gCO4zbz|i2|S+?e`h0VZZhL!ub>-cX7u1}DcV?VEe{T=@OFZTn zUi@bEK9ePD)f=yfxnFF2d+~L_@#)HmAD@Wbd*}3R(wLC8W8%h_&Ts9k?l^Z^wm028 z*ZYT41&2F*6IOpYeP8jtCi|()?K@A(Pm^&YKHQSKWA6IDA8(vmI_kYrV`WZtm0B(i zX-=LT)2KhmHg`KE43}4>)X_mMT}R!BMpqp!@63Bf7;euIyPy;#5(fZF}o(5uxab)M(>YrLx^&QNqNA&;z literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/right_normal.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/right_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..b990d329762e6eb8d7a115bf07e7167144f9da15 GIT binary patch literal 2788 zcmb7G3se(V8XgrD5m;C~l=29}lpYXGGLwXmjHXHmH30({siG^|VKRXskBONO9%8X> zR%4~;S`b^rTGq&-2U}$kmGY?dfGvU#9-{bI*CJIs+DZZO)t&IF?y--Zb7tn=x!?W% z@Ba6@|Cz1vv5VbYd|Utka8t--D(3CuxSgjl&+_Oct;}nNQNEG}0Qb|5ds5+CcV7UQ z+D9fNniG{vP@K|pFg2A-a5D8q1`PlU7G@eTTuYe2WFmz$NT3Hb^$nR=apMl&VQ2rtUC9iO=nI07+iB~XMT zAeg9(2O}vH0fupeY#b5rz;H1K5yE1gU>?YWk#H^?&PDia7(rnn$`^xU7sNy}sWqrd z_V!pTrYC_?&1NIY3X5=Cq*s-J$pcF~aOXvta zVKCDS7MZ{rQzCuA83u8N?k zbQ4ZQSs0mbI96jsBTWQmrc4PGr5oR<_;JZ#WF#1}f;6b940_HBa6*Qe2?@l5c?cU8 zu@ON6kB9OQlrNYIi%=LIg(@jEsmXd3lplujMK3`a!>BPc_Pby;j%p~A9%GhE>ai4p zYc!-l;6xJ9NJ>YUn81uW{)^ugk&*ExN<-?H0a~?K3M!%^g@{-vWb-)4h+L%-RTyY9 zX21!BOad{f;gF;n4Z}4eLZgA%I1#R96UhP%TZ|)Owk8?TsF@xtf`#MrWfY$7Fo0wJ z=vh!xIK%OaJdFS&!o)bAjjQ>|>~LIwu*EQASD{8A=D`}KnT(IK#hFOvIAXdNSskj> z3}dnYW2S_Kv3X${%yE{~Yz)W4*L_QRMD%1zvS8fU-(!`@Knr@LNK+J3ptj;byT6z4dMRpUX6^sP_f40Oc``E zC+aWLnW*4|fuS}r^_i!9`V#;+eX5W}B*?cG?rNcYqh>eUINRD))7PSDOSI>d9CY#7 zI%`F|fAmKlg`y7;w)2Hjml;8CITh{*ZMDq|*b?n0+8F<)`{ysQ=U{>C^fMKA*oV zy8KT&gI@o;O0!B!R)hiP5wJkD1-X6laI@rGP4T&2Zbw?xgC~=fadCX$kwCGtQtDh@ z6$=2)f$H$-U6uxKdiu0!E)gD2cMzAiY}>Z&XmF~@w6nK=`18Jj$J?Z~bf96)M%JP~ zZ@y`q9W^)q)|bfq`Nfu>{`DlKbvRgm#wTz;B@a%PI=cjR-W_<{-?;l+%|Q1)(}^6O zvaM2T8#tCbdFWw;bD*nd^>#9Vrq|qvwwf}*Wl8S zlZo@ZezujS?x5Fn&6GO_HhO=2;Lc6hwW&Iy^U4u{vhs;rh}|7Btf|X6vGh1MfEF`>#Kfe(fLEE?hm=m$UkWDQe0h zHz2JrnrI(-Mw6fHx+rLgnNw`ro&K$l#tTBp0`>E-m5t-y33(Y2&~o(xraZ;9&FF^yl}s*!_)JdAAT@?mvw!ZxdJja0>FW?vU)}_ zx4KD|@-YZa0=i4Smw+CdF~s$2>UMAM!n+}sc2E4Clrb;n?bR*0$GTI0xqa5AA*&Tj z%qvY@s(rSu`uY1y*KmrGq-ToO`PH}Ugw=V-QMYcofNp&TyC&Tjs-LoP+oi)v-Ah9y z0l{UlCD~OSX|=@%?qGB5!bZ7PKW%dv9;%-s(@9d+Ls758ORvcs`h8P%4#E ztvg;jI&XcfcEf4!S%DC>_@CZ*@t*#7T8BTlC5ox6tgPv5s@rFHJs==A4;gfVn4i>w ni*NfiRZ~}w|Cq6G@aM@a@BBU2cdrd_{D&%{Vr7S=?{4}p7K1LJ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/run_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/run_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..4027d0278b165a835f10332c9d87dd1241a3c952 GIT binary patch literal 864 zcmV-m1E2hfP)pF7IZ~ebVG7wVRUJ4ZXi@?ZDjy3G%qkX zFEKSnS1wWj0010xMObuGZ)S9NVRB^vL1b@YWgtdra%FdKa%*!SLsK^Byt0e{00Ov4 zL_t(YiKW)hisT=WTSm zT|>%xyos06{XJa5)nSZV1N0-9NWZtR7AumjgWI@_3pkg+tJ3Hb(Jp+0Etto{bbXR- zlcQ}c#}ypGiD7|S_#XQ)iwDKQHOU9GF^WkXN{%fFG=h`ZiCfA0r2uMx4UFLz>@LBY zJuiQUPjKToL8N!P$#xt+mdX-nC%#B8mWB;cgY5MnFt~}&u=lAVrLK)Xuu;^cjHHA6 zcwN+Nws2r6>83NUV>|BVh{i>C^@6O%uh@pK@VDU6=zs_t$)Qd7fQ8geV6I}YOmJle zNAWK9;bL;)MGGmefj-9j8R!*3##!}rly&UjG*5%3$-!i7ibL{)h#}Kd)TG0c^z&>8$MB6Vb6R^z!Kc$c#vBH3Kct zx*e=Cm?t$E#X%9(s|ip7Y>I}s+rnSCqko-hvRn}IOKcXCy9CLB+{T|xToa?dy+lN{ zXCLEtQIic~Ee*(E7_4Vm%=({1O2!I< zEb}RfVL;&J@G3E*?lAb581JrtX9G8yDf?8mRHUnNG+ zG3+TpY7v#P4~NC5?}#RuD?poKkgiPEX?%+_wZr-W5v$-sG3qyq0_Sb}NRTmi)>L{{ ql|ewIY!DxitJD3A_<+1VjPZY?7RN;YXZMo;0000pF7IZ~ebVG7wVRUJ4ZXi@?ZDjy3G%qkX zFEKSnS1wWj0010xMObuGZ)S9NVRB^vL1b@YWgtdra%FdKa%*!SLsK^Byt0e{00f^& zL_t(YiItYkZyQAvz~9Wy*t_e^X46=ue4VNa8i^BEP#sE>5S2KMF)awuq6!HlJ_MDJ zD$a-tABRdDIDk+k4kf9Z1cagl+WrCMNGg>cK_KPB9&dKXGqdwJ)DBJ?C+3}2^Y*>p zym|B98-j??kCaNKLqQNcX{{Xu03d|K#+chnOG|(DV^8)1RjbvUF=k9_eL`z})EF~_ zh&ccNN~v}nr_MRQ<2cT*i1_ou!b1GNK{GQmQ%b21k|Y_CQf69fX{|K?&@mvCQin0- zx~|JT&%2w?=P%W2weR}^O;1lV0QfXXlCwexskKf300<#uHwV~uz!-A}1_la25d4s3 z*@ugZi?SzZa&nUA^ZBpq_4h=2b#+c8$_1mCwxqLEB)3ZW|^|pTk_wqpqAq)|>k7*ws2qD(C zwzjI}a{0^-(8R=qn`PMrA%yHW?-&L_pbi{3upWltAY;ty14sY>gb-U=>-S5g(!e$- zm&+Yb({w~@opz235rK0a_`ZMr;K73@qA0ppEEfNWqG*tFUf2sr2qDH8nWpLCFbv1H zLDt%_G)=Sn4Jf4!B5q#3e7RAp)xIqh3KLNjyy=97Y2Wu>mr_n7Niry-=wKg-xM6TsNC_c|QYx5IYLzior<4vMqUjef zIy%atD0)RH^;VK3N8&h+t+m|{XgA%>IF5g(%gf7uF~;sN#@rrt@xWT8QaM>D6n<(n z8lSDLtvxD)*g!kGLwbl?q4ppnwr<79fq-i?Y zY&NMWT|&s0aU8$YY&N%y zF|rNYbCh$={V)t&-}k=*fQ#3zUE5JAJs&5hPMvzS)oQ()rs-iRr8dS$Yi$NQA191+ z?s}f*c%HYK%jLefdiCnUZvOUsZcR;11%!|nvMhT}YkkBR6ComRN2nNMo1F7i&iRVt zI7_p$v%A*EzMyUyA0K~=G4=!^1^@t*(ncJ|w{P6I@pnJ={{kKuj-1|@UmpMf002ov JPDHLkV1f{FWy=5n literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/skills_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/skills_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..660157ecfb91031a4b2ac3cbc0559a9482688415 GIT binary patch literal 863 zcmV-l1EBngP)8IJA;U@ z2RVd0bH0VOc@-DtIP(Zj;u!Al0A0rS_zFMW)=EUo8V^Op*@*ZpBDNypT0~rlh(B^% z$+fMBSdEB}BjV^RdxIIFdjW6b2-a~c*9Vy7e28e~OSq0@oaq`I_JF*C4=~1`9gx6{ z9Fc1h{A&JxAFp+db{Rd74{;4UjUj1xqXFKB13hPkxCbxcY#-2r_$HZbHw;=Pix}nq zt#sx<&)LPa`2;R79lF<*oOD4Z2{OWuIFHY8DV^HLGp){F>A-TA(Zl#Q6{6$aMjAYg zw;IRx<6S(J?7GYb$?OC!R7OuKRWtE#kcIUAlxf+-8%jRq*;aRgyVCYQp*x0~m8I## zFDN%aErM3om6G0<`z_c&NyB3m=%CW^H+w*8j>dKq+{!2&sm5C{O0Mq1(onfl_BV7} zkg9wTck}=qPW|YduLTn6%(#ZGE#VeKt{+OUt}Hb`OoL4|^-!sp%^WRAOMi?PlX;bU z@v_oOHGf@Zo5}9RP)X>|3EBl2=ln8`5rsl{*+ zUn@!9Nv~>;%qweoemiX(#+TL6_O3gnbos4ZUsFC4^U7-K43&udj(6&23v^MrQfkkv zrf2iYX6lTTl3&IzeL(P$a#0?!hlfWa>$n?l;`4T+?{V^;-3xKAatW{ETz6yEn}HI7 p?L7i5m=W&V0sW`a_c-}qq?PV&X5KfyH#_g0 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/icon/theme_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/icon/theme_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..4a8b9bb2c368c13af68d773d42aca62f5e648186 GIT binary patch literal 978 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 GfA}B%<0Qra literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/recipe_graph/icon.png b/src/main/resources/assets/gregtech/textures/gui/terminal/recipe_graph/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..c319617e70986d7469baa7cc05d9587a6ad4bbeb GIT binary patch literal 27259 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 LG(@UG!YJ^60Pb`k literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/terminal_background.png b/src/main/resources/assets/gregtech/textures/gui/terminal/terminal_background.png new file mode 100644 index 0000000000000000000000000000000000000000..e7a6cf37cdbec068c9478bf130b6cc07667a4e1c GIT binary patch literal 398697 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

    x|B~a+0992@8Cq0O_~UnW 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 tHo3?QDO7z`!Ew-J>Q|R{{ZX@#ajRX literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/terminal_dialog.png b/src/main/resources/assets/gregtech/textures/gui/terminal/terminal_dialog.png new file mode 100644 index 0000000000000000000000000000000000000000..d18efc6cbc13ee9bbc0bcfa3f1372fcfea7f9476 GIT binary patch literal 5193 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/widget/formatting.png b/src/main/resources/assets/gregtech/textures/gui/widget/formatting.png new file mode 100644 index 0000000000000000000000000000000000000000..b6841a6f00f64a2b79ac2d2b747cdda210e90cfc GIT binary patch literal 1890 zcmcIle{9rL9Pf;5lK>8I7(uiY|3F!uShgb!{}A4_?{3}h+OF+( zH$*VNAE1dw7bgB78qt7Dwy6PPLKFf6bb?4CQw-S*8t@-sC>j#S;_LmA7{L8wlh^lN z`+1-5=li4I?rdzRn>l^{bb=seM(U*|JOex`%1iORabV(OJUw96ud@ka){r|&b}gN? zfFPzF)1oa-i@ZuyjFbneMhtl}DHEd!qI!A8gi1Sd$QVj!dWgDq_y|R6YKU6vlYwl8 zQL9$J(L&7|8=}g_b|t7%%a@VW84(ktkORp~DyiFICPZa-#x+Q` z$c<#!un_6<_-TdZy<{NhVf`TJ<*P_9U;_*YFf2y{Rs?>L3zGSZ!qzM`E;dOk^S1CV zM727ODKbnto%W}B3bhal=YMTqRlxCJqjjuh}?p-TAMh8Fl1WNsY{woCp=S(nFNurWmPI{;_t4 z=uJ&$jyBzjFzG##pM%*(+(|LE$#oC@O(&>R;VWsZkY__ zy27~4C6^H9-?_@ZyR8uw;JCZF%VJx_n_^=|I;OU8+pRfq;9G(ySs9UPqV+ouu3`1# zU`BOm!}_24$G&OvOuHeJtlRG!`(oa^%@dVfAN4=wOMNxa`O=J6tDD~2^u(H4`Nr7e zYv%Gqg~Im$uH?SiOSmH!r29{k}UR_4IAsF>>tW`L@G^cXard*T?2;yWTeV2RiWcvU$UGfz78n&Pyj7iCbIx zmL477J~Yw+9_*jJzvYx#K@25l4V@l5Ua{U=_VN#7sw1Czdefmx?c--JADv&-T|Kw% zrd;_6*mE&hcJ0EO-gvO}fkw(mXh-KEtFzn@-p?yB#dXC~h7+aZ;IeWqvh+HR?r qTXd%K!=AC{hbIRk4Sx;WKb9S$KP`LY{K0MRUocYJAPub8u=Q_&5QaJc literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/gui/widget/palette.png b/src/main/resources/assets/gregtech/textures/gui/widget/palette.png new file mode 100644 index 0000000000000000000000000000000000000000..7accd700da76292a2da375d4e8ab73a4e66132f4 GIT binary patch literal 1921 zcmcIlTWs4@7CnDx4`?!6Ne7N$2P6`83REa7p!3$ zuXa3wAZ4G+;V!c)bbuGtq)U+02yms78bl*VOws0QI<7T%;Hp^>QwXB{`aT9HmLhOORfIa^ob$lPvG%(87g5Yq}KWJAzLX zY{8Wui<_p#6GSSNa;4lZRgV!A$8iKn6EuxO1a4#$Q%K{Av8Tuo1cs=~nklOaYB35C zwcqq(P-)(Uq*kI;j6#@Tz=*V<5tNIxTq*)Xq4lB3WC?AUO#{$MLGN9Ojc`T-L8#eTCvu)jA^{R031J2lMwLuyan)3fxOxviO4}uGG(MmM!Bq9I zswRqwYA>>&fdE={P*x;0W$d-|6yP8zn81(GBu(L@4=0&0#qbQrd)R8y$CG3p8iG|I z38t_yuqw&X%toN05Z|I0rl5$RCFsYXD3>ftycCsKw~wQ7Ho`=3hGyKj&j$qDO+`GS zo2D2x3Ua#O`JgKHTfwu==ZjWSMaWT#4==Hi2*jU1_(`wVd!l&0X3oOAytAgcU!d#*`XKBvH=s9DSREB;Q7KVA)~pH;|0;GbU!9q zDFzZ&crD*0dK=T3r%lBHBwZ)@d6=O_&6J>nh8T?Wf0Pz+FX@Ibu)gq(rTu>sUI?ie z7nB%)Et9}3R|u=QtJ6E~AI~q|D4!fH*Ewxp+C^crFKx!Sf-AnzpM-jvZ3%?;8 zAGta~wa(Sw-*g3i^Tp%)s=8f`(~AB8ADnNB4^+C|aA6PEZha{5QRlB_7R?OZTsbj0 zb>Zf&v5D8;UzypDleSly&mEp-;!|r2gnx8XG!)WpV9tw$AhS zuH}liXE)!N8-44{^zI|Jvpb}|`;K;_&z)Tnwd<3^+v+ztsupaOTGrm!P5!iMw~tr; z`33jAQ_Ef~+_010xIN^1j~hHqRsC@GtgnzFjj$)GgvsykYjhvh|Z}X=)9gY3zOB9|UQG A_W%F@ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/items/material_sets/diamond/plate_double.png b/src/main/resources/assets/gregtech/textures/items/material_sets/diamond/plate_double.png new file mode 100644 index 0000000000000000000000000000000000000000..3b0e5a5c9da8876b8f866b717436db192ec91bec GIT binary patch literal 1691 zcmcIlU5MON6pn*`TP;@nTYYKBBKWg+?oDQrnWUYTb+dH`%(`p`b_EOGx%bXY*hy|o zGCMPig~cDx2di&F5iE!=3JOB|P@&cr5%j_0t5os97eNIdeA%KW^An4->%KUU$xZUz z?|kQcCns;Lt~`D4z#|6~MLAescGuv1C_C=F9sUph@fU^DOtk!5q9}LWmmRk#XWyMw zl-s`Y8yo3{_l(12P^4ToMR5>BfL4^F#|IH*n<7=4qV0z@?YGZ9*HoX^v~|-XUbHAW z{_=J#PHwL>*!Cu~xpw@RdUW6bK_F794uWo&ID?ut;&ou1-Nu?af~1=@Z6OP&Zg{Ke zqKt)V6$xU57;42X>Q=dIk$Kf12EoL{x`A}dA!SFesFR-t(PG|m*4z`5Sa4O-I%yg? z829`AV!u?BaU1KlZDV3!!$5#Q$uLam0ENlil))7Vi~T6|WvFJ1v?+UOO#`Ll6oM$H z4U5L4{-b75c4h2I4mB@j-3;uI z#j>A(b;HT~aZKKOaD!Zb>;2zf9g+}$w55BuHb6LInRr==-UwEJHJXw9^i2KCz_D5g7 zeQfuh*RHPLf3{&>^S2M(yF|~Ox0>G+-cmk1e`fY;`5J}(m2)%EgFhGMzukRE>z%sr=zC{Axpp!8 PeAJg#+>f7n;pM*p()7_uRZk8OAZ0|X;-U+lDNK9AZa9h^S$rA@9Ev! z-uiU);`U>T6{)cxp?cC#duv_ki zw|uS=g9$a1#w^JIt!dZSW*OsqvP45Uiqk;<>*ohLibbH`X@w-rHsm<&9q01)@z#JJ z?{QD)Yd6sKnGXbsEE$?5leF+>fj;N;VO_m8bu@>Rdx5@Q1w^~yHri0RM6N+FCxoK5 zXIQS|xa4C*2_+_JnHI&C>l4Sf+NeHsh?a}U-|610W5H9PkIORiO>;V(8dKX)`N*_9 z&oc=%DaC-m#Zg+a8BU8UONOp2cphhEtWs1lvY|RC109quQb@9fHZAHhLBY%!%S_84 zRZ2@>7@iJIk_KIrn}-mk*85W8VsMm6b4M2HAm?)PP^RUTWiY{;z1cxNnP)1vDJL=k zSOLPUCR8?7r7Fhi6?rtDn`|qPm7YJT=u(x4x)@W7QVEi z;n0gLEFza;hdLAwqYlNku!Yz1NZYcUxh~k>Rs5hTU$uYHwnA~>Xe#7;HYY_s5WjvO0%7O`>15|(XK zo6E@4k>Gx$@`OR3#0eWoGfPK0dahM~oU&Z5kD${3*<9wU#24)Fbm?a^ z{(qESmz9rMI+8FrO}$FStVYbj6!YJH&A+`cj+Stkan-UJuJF)|XPE+Z4#W3@U&(zK z+^v3heb9M}KRr2FTlwg_Z{9xtZ0+u|r(gZJs>L@SefVDX$HRLk=+;l~^!EL5W&gLY dKVRuR(tdHZKh=}N->cEz-`win|K!VW{{j2h`quye literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/items/material_sets/emerald/plate_double.png b/src/main/resources/assets/gregtech/textures/items/material_sets/emerald/plate_double.png new file mode 100644 index 0000000000000000000000000000000000000000..3b0e5a5c9da8876b8f866b717436db192ec91bec GIT binary patch literal 1691 zcmcIlU5MON6pn*`TP;@nTYYKBBKWg+?oDQrnWUYTb+dH`%(`p`b_EOGx%bXY*hy|o zGCMPig~cDx2di&F5iE!=3JOB|P@&cr5%j_0t5os97eNIdeA%KW^An4->%KUU$xZUz z?|kQcCns;Lt~`D4z#|6~MLAescGuv1C_C=F9sUph@fU^DOtk!5q9}LWmmRk#XWyMw zl-s`Y8yo3{_l(12P^4ToMR5>BfL4^F#|IH*n<7=4qV0z@?YGZ9*HoX^v~|-XUbHAW z{_=J#PHwL>*!Cu~xpw@RdUW6bK_F794uWo&ID?ut;&ou1-Nu?af~1=@Z6OP&Zg{Ke zqKt)V6$xU57;42X>Q=dIk$Kf12EoL{x`A}dA!SFesFR-t(PG|m*4z`5Sa4O-I%yg? z829`AV!u?BaU1KlZDV3!!$5#Q$uLam0ENlil))7Vi~T6|WvFJ1v?+UOO#`Ll6oM$H z4U5L4{-b75c4h2I4mB@j-3;uI z#j>A(b;HT~aZKKOaD!Zb>;2zf9g+}$w55BuHb6LInRr==-UwEJHJXw9^i2KCz_D5g7 zeQfuh*RHPLf3{&>^S2M(yF|~Ox0>G+-cmk1e`fY;`5J}(m2)%EgFhGMzukRE>z%sr=zC{Axpp!8 PeAJg#+>f7n;pM*p()7_uRZk8OAZ0|X;-U+lDNK9AZa9h^S$rA@9Ev! z-uiU);`U>T6{)cxp?cC#duv_ki zw|uS=g9$a1#w^JIt!dZSW*OsqvP45Uiqk;<>*ohLibbH`X@w-rHsm<&9q01)@z#JJ z?{QD)Yd6sKnGXbsEE$?5leF+>fj;N;VO_m8bu@>Rdx5@Q1w^~yHri0RM6N+FCxoK5 zXIQS|xa4C*2_+_JnHI&C>l4Sf+NeHsh?a}U-|610W5H9PkIORiO>;V(8dKX)`N*_9 z&oc=%DaC-m#Zg+a8BU8UONOp2cphhEtWs1lvY|RC109quQb@9fHZAHhLBY%!%S_84 zRZ2@>7@iJIk_KIrn}-mk*85W8VsMm6b4M2HAm?)PP^RUTWiY{;z1cxNnP)1vDJL=k zSOLPUCR8?7r7Fhi6?rtDn`|qPm7YJT=u(x4x)@W7QVEi z;n0gLEFza;hdLAwqYlNku!Yz1NZYcUxh~k>Rs5hTU$uYHwnA~>Xe#7;HYY_s5WjvO0%7O`>15|(XK zo6E@4k>Gx$@`OR3#0eWoGfPK0dahM~oU&Z5kD${3*<9wU#24)Fbm?a^ z{(qESmz9rMI+8FrO}$FStVYbj6!YJH&A+`cj+Stkan-UJuJF)|XPE+Z4#W3@U&(zK z+^v3heb9M}KRr2FTlwg_Z{9xtZ0+u|r(gZJs>L@SefVDX$HRLk=+;l~^!EL5W&gLY dKVRuR(tdHZKh=}N->cEz-`win|K!VW{{j2h`quye literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/items/material_sets/gem_horizontal/plate_double.png b/src/main/resources/assets/gregtech/textures/items/material_sets/gem_horizontal/plate_double.png new file mode 100644 index 0000000000000000000000000000000000000000..3b0e5a5c9da8876b8f866b717436db192ec91bec GIT binary patch literal 1691 zcmcIlU5MON6pn*`TP;@nTYYKBBKWg+?oDQrnWUYTb+dH`%(`p`b_EOGx%bXY*hy|o zGCMPig~cDx2di&F5iE!=3JOB|P@&cr5%j_0t5os97eNIdeA%KW^An4->%KUU$xZUz z?|kQcCns;Lt~`D4z#|6~MLAescGuv1C_C=F9sUph@fU^DOtk!5q9}LWmmRk#XWyMw zl-s`Y8yo3{_l(12P^4ToMR5>BfL4^F#|IH*n<7=4qV0z@?YGZ9*HoX^v~|-XUbHAW z{_=J#PHwL>*!Cu~xpw@RdUW6bK_F794uWo&ID?ut;&ou1-Nu?af~1=@Z6OP&Zg{Ke zqKt)V6$xU57;42X>Q=dIk$Kf12EoL{x`A}dA!SFesFR-t(PG|m*4z`5Sa4O-I%yg? z829`AV!u?BaU1KlZDV3!!$5#Q$uLam0ENlil))7Vi~T6|WvFJ1v?+UOO#`Ll6oM$H z4U5L4{-b75c4h2I4mB@j-3;uI z#j>A(b;HT~aZKKOaD!Zb>;2zf9g+}$w55BuHb6LInRr==-UwEJHJXw9^i2KCz_D5g7 zeQfuh*RHPLf3{&>^S2M(yF|~Ox0>G+-cmk1e`fY;`5J}(m2)%EgFhGMzukRE>z%sr=zC{Axpp!8 PeAJg#+>f7n;pM*p()7_uRZk8OAZ0|X;-U+lDNK9AZa9h^S$rA@9Ev! z-uiU);`U>T6{)cxp?cC#duv_ki zw|uS=g9$a1#w^JIt!dZSW*OsqvP45Uiqk;<>*ohLibbH`X@w-rHsm<&9q01)@z#JJ z?{QD)Yd6sKnGXbsEE$?5leF+>fj;N;VO_m8bu@>Rdx5@Q1w^~yHri0RM6N+FCxoK5 zXIQS|xa4C*2_+_JnHI&C>l4Sf+NeHsh?a}U-|610W5H9PkIORiO>;V(8dKX)`N*_9 z&oc=%DaC-m#Zg+a8BU8UONOp2cphhEtWs1lvY|RC109quQb@9fHZAHhLBY%!%S_84 zRZ2@>7@iJIk_KIrn}-mk*85W8VsMm6b4M2HAm?)PP^RUTWiY{;z1cxNnP)1vDJL=k zSOLPUCR8?7r7Fhi6?rtDn`|qPm7YJT=u(x4x)@W7QVEi z;n0gLEFza;hdLAwqYlNku!Yz1NZYcUxh~k>Rs5hTU$uYHwnA~>Xe#7;HYY_s5WjvO0%7O`>15|(XK zo6E@4k>Gx$@`OR3#0eWoGfPK0dahM~oU&Z5kD${3*<9wU#24)Fbm?a^ z{(qESmz9rMI+8FrO}$FStVYbj6!YJH&A+`cj+Stkan-UJuJF)|XPE+Z4#W3@U&(zK z+^v3heb9M}KRr2FTlwg_Z{9xtZ0+u|r(gZJs>L@SefVDX$HRLk=+;l~^!EL5W&gLY dKVRuR(tdHZKh=}N->cEz-`win|K!VW{{j2h`quye literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/items/material_sets/gem_vertical/plate_double.png b/src/main/resources/assets/gregtech/textures/items/material_sets/gem_vertical/plate_double.png new file mode 100644 index 0000000000000000000000000000000000000000..3b0e5a5c9da8876b8f866b717436db192ec91bec GIT binary patch literal 1691 zcmcIlU5MON6pn*`TP;@nTYYKBBKWg+?oDQrnWUYTb+dH`%(`p`b_EOGx%bXY*hy|o zGCMPig~cDx2di&F5iE!=3JOB|P@&cr5%j_0t5os97eNIdeA%KW^An4->%KUU$xZUz z?|kQcCns;Lt~`D4z#|6~MLAescGuv1C_C=F9sUph@fU^DOtk!5q9}LWmmRk#XWyMw zl-s`Y8yo3{_l(12P^4ToMR5>BfL4^F#|IH*n<7=4qV0z@?YGZ9*HoX^v~|-XUbHAW z{_=J#PHwL>*!Cu~xpw@RdUW6bK_F794uWo&ID?ut;&ou1-Nu?af~1=@Z6OP&Zg{Ke zqKt)V6$xU57;42X>Q=dIk$Kf12EoL{x`A}dA!SFesFR-t(PG|m*4z`5Sa4O-I%yg? z829`AV!u?BaU1KlZDV3!!$5#Q$uLam0ENlil))7Vi~T6|WvFJ1v?+UOO#`Ll6oM$H z4U5L4{-b75c4h2I4mB@j-3;uI z#j>A(b;HT~aZKKOaD!Zb>;2zf9g+}$w55BuHb6LInRr==-UwEJHJXw9^i2KCz_D5g7 zeQfuh*RHPLf3{&>^S2M(yF|~Ox0>G+-cmk1e`fY;`5J}(m2)%EgFhGMzukRE>z%sr=zC{Axpp!8 PeAJg#+>f7n;pM*p()7_uRZk8OAZ0|X;-U+lDNK9AZa9h^S$rA@9Ev! z-uiU);`U>T6{)cxp?cC#duv_ki zw|uS=g9$a1#w^JIt!dZSW*OsqvP45Uiqk;<>*ohLibbH`X@w-rHsm<&9q01)@z#JJ z?{QD)Yd6sKnGXbsEE$?5leF+>fj;N;VO_m8bu@>Rdx5@Q1w^~yHri0RM6N+FCxoK5 zXIQS|xa4C*2_+_JnHI&C>l4Sf+NeHsh?a}U-|610W5H9PkIORiO>;V(8dKX)`N*_9 z&oc=%DaC-m#Zg+a8BU8UONOp2cphhEtWs1lvY|RC109quQb@9fHZAHhLBY%!%S_84 zRZ2@>7@iJIk_KIrn}-mk*85W8VsMm6b4M2HAm?)PP^RUTWiY{;z1cxNnP)1vDJL=k zSOLPUCR8?7r7Fhi6?rtDn`|qPm7YJT=u(x4x)@W7QVEi z;n0gLEFza;hdLAwqYlNku!Yz1NZYcUxh~k>Rs5hTU$uYHwnA~>Xe#7;HYY_s5WjvO0%7O`>15|(XK zo6E@4k>Gx$@`OR3#0eWoGfPK0dahM~oU&Z5kD${3*<9wU#24)Fbm?a^ z{(qESmz9rMI+8FrO}$FStVYbj6!YJH&A+`cj+Stkan-UJuJF)|XPE+Z4#W3@U&(zK z+^v3heb9M}KRr2FTlwg_Z{9xtZ0+u|r(gZJs>L@SefVDX$HRLk=+;l~^!EL5W&gLY dKVRuR(tdHZKh=}N->cEz-`win|K!VW{{j2h`quye literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/items/material_sets/lapis/plate_double.png b/src/main/resources/assets/gregtech/textures/items/material_sets/lapis/plate_double.png new file mode 100644 index 0000000000000000000000000000000000000000..0961923fc4e15a73016d263f609ab4e403e0bd6d GIT binary patch literal 1896 zcmcIleQeZZ81HZcnS2afHiw9{OT=aC_2YUUZFbDL+uRAa&FvyXLH4$NZ`bUu?b>d4 zH>V+sB*UQ+3I4GW8HO!54Q4DcCSch9KuwgOQ9(1N2tyJTK`}8#3BKKZNDLqQ$0lvx z_WeD-=l6W{>5is`$Cu`>%EvHlX`tTUjP3>YdG|teeemjafNqQR`b{Q=-E*&f=3s++ z@58XXkCjlX)f(I&NLtJRWKD#QL`+9$46Ce4=s@a#7B0eeMfDMvj~pX#MfMRJT|qji z*T9HU-($d*o`#Ur(;@LPQMC@QObCb|1}%UmVo}u;5?NEnlKrAIVNGb7q9;>d1iqtS&L0|HAkLYfxM z6sjr1g0qZ+#UI(IsInF}%WOqy1Ly}9^bx3P3`x64mJTrHL>jVgl4nJc1S}_$BH+BF$hjom<8m=B zw>+l{+50uA%TAwdpK4oKlMqKXLjo6uz$pV4DZ0Z>lJ#;T$-7-LYFyxP(J~Odyp&;U zG!*pZfar~^wkp|H#fhAg=XjEF0!W5E97lR(Crd(?+s$({WEdw>B}+nBGhzVsi4p_t zkkZw50{>S{jTY66peCc7JMC^p>?n$Q#YCk`roWFC*qL5M6@0Gg1R&YH?jt0-$PoES zy;g3Py?NdoETu=dl7=4|qn3&xI1-2?QJ&LcBd)($JH0=q`bqSHmu@m4&r z^7rSLKYZp=x4xx#EB3;*WbUYU-^ur%efR6jf1G{plqDSR`C!eioc{Bz+YbG7;QI$A zU)(VHYyZw|hbx{e-0lxMhsMVGp7?P5skirV<#O(qT_m=M+?9FKNLevlg^=X3k8KX>#avvrS?XXm-;yb$6v!=W-?)lbJKl zOqyf`5euTQNV}^(*oqZ>5wRlrA`xw|sJQr0RuL}`K8PX;S!l7+2kV*Kh*B+f;LN#w z=lk#fv-#;=8$!2-D2m#U&7=xsz9AUbUPJzOoxP}#Y0SyYdla>PV=zXjmyX>^QKL7T z#W{a2w;O8M;uIaLh-+95K~vQB$%dn7739+@Dw(#-v|ArBw5iL?Y%~XQP7;;P%z}&d zE=(7-g^Cu}naLgW_68&b7V;IkVO4DpHe{y53&}b-<{7#J@hdVj6$qr~a(Oz5T|`S9 zU^M_ldRv?mq)0>pTWJx9fCo`t5LrQjAOeMLbnjz`G*>rZA$5OG7TL*6+4mjD^Ywb2 ztA{!4mUtl^kMls}MUf>4)@$0n(qL_GqR)^*p5~g4Z(^Gc7!?)Qe3>Ddc1^IH0j=%z z+(aD4Hx!2#I1rfB0qWWS=hWP4N4T!>sERCP`yRmx1FTcVKK9D^U#JJye-l7lo68Mk zTv8Xy8i?@x^g&`q&mosYd&Q=M_yY29&DBu)AW?H7u*QK&7b!k=ix^k?fy(z)rbU4h z>3e2PTgP?p-k}F5rT9o@NYn%tNUSIo1pvh`Bx@2o0J_i|)=i^142`jZSOj4x#vqCG zFqEW>uK3Dj!MX+w>{<#j*tC=q;vKuh&;vKZB(7qY2qxNvhtIRgWZuPwStS==nYnko@*T{iD{qC6iIY}XF{pC)$hhKjon zCmkbL4q6r244NIXNr!VuD_dS&CascM$)=`?v6U~Dh0q~z)6?>vnKP|(4@@6OTs6LQ z>J)qEnKxUSQ(Jq1Uwi$l)1f=RJvsB`2ko#L}mW!#l`tnCiMHO_l=JIoE;gpzWW?phx7aPsf#yO-g+M0cFWrSEt{w( z*Bw5eSZXIGuOAIP+Isu__l~G1KYjU+cVGEs?BQ=dSsCB)T0Lm*+4OYk#Lh>a`U}|B B3I_lH delta 421 zcmV;W0b2gM4AKLTBo78+OGiWi{{a60|De66laV18e*gz`Nliru-T@yFI3VFIhQ$B? z0bfZ(K~y-)rIWF0!cY{3zr+xbOOObe95Y(zXcpZHeT5c>2pu}QG!J24phE|@zCxj6 zo}gGqH{pV!K`sG@=!x!2HIQwJtBQCq;e3?6T;OG&-^v9@iS zcsemIfA3#DKK}|-B@YIJpD5D*Ma;5<-u+nT=P(TMeIFqNK@iXnBVB2sA4WO|0({>G z(8J*nr4)|iuv)DULeTAYA^h#6U?ELYwAPG9BNmGVNs{2YE=iJbJRVuE*VRJ=5JIrq z?bz@40JyFTK&#av%Q8IA!}B~iSusk7xY=w9e_a7s)`@PKW_1TjDbh4OSIi-$i7}tg5kin<8O!AoDJ4=$Y}>|h94yO1DMjTF2#RQ zW<^ewg`AM@d%N8hUf?B+y1((uFZ>N;b(8kd-ELX{ P3jhEBNkvXXu0mjfp~}Ih diff --git a/src/main/resources/assets/gregtech/textures/items/material_sets/netherstar/plate_double.png b/src/main/resources/assets/gregtech/textures/items/material_sets/netherstar/plate_double.png new file mode 100644 index 0000000000000000000000000000000000000000..3b0e5a5c9da8876b8f866b717436db192ec91bec GIT binary patch literal 1691 zcmcIlU5MON6pn*`TP;@nTYYKBBKWg+?oDQrnWUYTb+dH`%(`p`b_EOGx%bXY*hy|o zGCMPig~cDx2di&F5iE!=3JOB|P@&cr5%j_0t5os97eNIdeA%KW^An4->%KUU$xZUz z?|kQcCns;Lt~`D4z#|6~MLAescGuv1C_C=F9sUph@fU^DOtk!5q9}LWmmRk#XWyMw zl-s`Y8yo3{_l(12P^4ToMR5>BfL4^F#|IH*n<7=4qV0z@?YGZ9*HoX^v~|-XUbHAW z{_=J#PHwL>*!Cu~xpw@RdUW6bK_F794uWo&ID?ut;&ou1-Nu?af~1=@Z6OP&Zg{Ke zqKt)V6$xU57;42X>Q=dIk$Kf12EoL{x`A}dA!SFesFR-t(PG|m*4z`5Sa4O-I%yg? z829`AV!u?BaU1KlZDV3!!$5#Q$uLam0ENlil))7Vi~T6|WvFJ1v?+UOO#`Ll6oM$H z4U5L4{-b75c4h2I4mB@j-3;uI z#j>A(b;HT~aZKKOaD!Zb>;2zf9g+}$w55BuHb6LInRr==-UwEJHJXw9^i2KCz_D5g7 zeQfuh*RHPLf3{&>^S2M(yF|~Ox0>G+-cmk1e`fY;`5J}(m2)%EgFhGMzukRE>z%sr=zC{Axpp!8 PeAJg#+>f7n;pM*p()7_uRZk8OAZ0|X;-U+lDNK9AZa9h^S$rA@9Ev! z-uiU);`U>T6{)cxp?cC#duv_ki zw|uS=g9$a1#w^JIt!dZSW*OsqvP45Uiqk;<>*ohLibbH`X@w-rHsm<&9q01)@z#JJ z?{QD)Yd6sKnGXbsEE$?5leF+>fj;N;VO_m8bu@>Rdx5@Q1w^~yHri0RM6N+FCxoK5 zXIQS|xa4C*2_+_JnHI&C>l4Sf+NeHsh?a}U-|610W5H9PkIORiO>;V(8dKX)`N*_9 z&oc=%DaC-m#Zg+a8BU8UONOp2cphhEtWs1lvY|RC109quQb@9fHZAHhLBY%!%S_84 zRZ2@>7@iJIk_KIrn}-mk*85W8VsMm6b4M2HAm?)PP^RUTWiY{;z1cxNnP)1vDJL=k zSOLPUCR8?7r7Fhi6?rtDn`|qPm7YJT=u(x4x)@W7QVEi z;n0gLEFza;hdLAwqYlNku!Yz1NZYcUxh~k>Rs5hTU$uYHwnA~>Xe#7;HYY_s5WjvO0%7O`>15|(XK zo6E@4k>Gx$@`OR3#0eWoGfPK0dahM~oU&Z5kD${3*<9wU#24)Fbm?a^ z{(qESmz9rMI+8FrO}$FStVYbj6!YJH&A+`cj+Stkan-UJuJF)|XPE+Z4#W3@U&(zK z+^v3heb9M}KRr2FTlwg_Z{9xtZ0+u|r(gZJs>L@SefVDX$HRLk=+;l~^!EL5W&gLY dKVRuR(tdHZKh=}N->cEz-`win|K!VW{{j2h`quye literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/items/material_sets/opal/plate_double.png b/src/main/resources/assets/gregtech/textures/items/material_sets/opal/plate_double.png new file mode 100644 index 0000000000000000000000000000000000000000..3b0e5a5c9da8876b8f866b717436db192ec91bec GIT binary patch literal 1691 zcmcIlU5MON6pn*`TP;@nTYYKBBKWg+?oDQrnWUYTb+dH`%(`p`b_EOGx%bXY*hy|o zGCMPig~cDx2di&F5iE!=3JOB|P@&cr5%j_0t5os97eNIdeA%KW^An4->%KUU$xZUz z?|kQcCns;Lt~`D4z#|6~MLAescGuv1C_C=F9sUph@fU^DOtk!5q9}LWmmRk#XWyMw zl-s`Y8yo3{_l(12P^4ToMR5>BfL4^F#|IH*n<7=4qV0z@?YGZ9*HoX^v~|-XUbHAW z{_=J#PHwL>*!Cu~xpw@RdUW6bK_F794uWo&ID?ut;&ou1-Nu?af~1=@Z6OP&Zg{Ke zqKt)V6$xU57;42X>Q=dIk$Kf12EoL{x`A}dA!SFesFR-t(PG|m*4z`5Sa4O-I%yg? z829`AV!u?BaU1KlZDV3!!$5#Q$uLam0ENlil))7Vi~T6|WvFJ1v?+UOO#`Ll6oM$H z4U5L4{-b75c4h2I4mB@j-3;uI z#j>A(b;HT~aZKKOaD!Zb>;2zf9g+}$w55BuHb6LInRr==-UwEJHJXw9^i2KCz_D5g7 zeQfuh*RHPLf3{&>^S2M(yF|~Ox0>G+-cmk1e`fY;`5J}(m2)%EgFhGMzukRE>z%sr=zC{Axpp!8 PeAJg#+>f7n;pM*p()7_uRZk8OAZ0|X;-U+lDNK9AZa9h^S$rA@9Ev! z-uiU);`U>T6{)cxp?cC#duv_ki zw|uS=g9$a1#w^JIt!dZSW*OsqvP45Uiqk;<>*ohLibbH`X@w-rHsm<&9q01)@z#JJ z?{QD)Yd6sKnGXbsEE$?5leF+>fj;N;VO_m8bu@>Rdx5@Q1w^~yHri0RM6N+FCxoK5 zXIQS|xa4C*2_+_JnHI&C>l4Sf+NeHsh?a}U-|610W5H9PkIORiO>;V(8dKX)`N*_9 z&oc=%DaC-m#Zg+a8BU8UONOp2cphhEtWs1lvY|RC109quQb@9fHZAHhLBY%!%S_84 zRZ2@>7@iJIk_KIrn}-mk*85W8VsMm6b4M2HAm?)PP^RUTWiY{;z1cxNnP)1vDJL=k zSOLPUCR8?7r7Fhi6?rtDn`|qPm7YJT=u(x4x)@W7QVEi z;n0gLEFza;hdLAwqYlNku!Yz1NZYcUxh~k>Rs5hTU$uYHwnA~>Xe#7;HYY_s5WjvO0%7O`>15|(XK zo6E@4k>Gx$@`OR3#0eWoGfPK0dahM~oU&Z5kD${3*<9wU#24)Fbm?a^ z{(qESmz9rMI+8FrO}$FStVYbj6!YJH&A+`cj+Stkan-UJuJF)|XPE+Z4#W3@U&(zK z+^v3heb9M}KRr2FTlwg_Z{9xtZ0+u|r(gZJs>L@SefVDX$HRLk=+;l~^!EL5W&gLY dKVRuR(tdHZKh=}N->cEz-`win|K!VW{{j2h`quye literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/items/material_sets/ruby/plate_double.png b/src/main/resources/assets/gregtech/textures/items/material_sets/ruby/plate_double.png new file mode 100644 index 0000000000000000000000000000000000000000..3b0e5a5c9da8876b8f866b717436db192ec91bec GIT binary patch literal 1691 zcmcIlU5MON6pn*`TP;@nTYYKBBKWg+?oDQrnWUYTb+dH`%(`p`b_EOGx%bXY*hy|o zGCMPig~cDx2di&F5iE!=3JOB|P@&cr5%j_0t5os97eNIdeA%KW^An4->%KUU$xZUz z?|kQcCns;Lt~`D4z#|6~MLAescGuv1C_C=F9sUph@fU^DOtk!5q9}LWmmRk#XWyMw zl-s`Y8yo3{_l(12P^4ToMR5>BfL4^F#|IH*n<7=4qV0z@?YGZ9*HoX^v~|-XUbHAW z{_=J#PHwL>*!Cu~xpw@RdUW6bK_F794uWo&ID?ut;&ou1-Nu?af~1=@Z6OP&Zg{Ke zqKt)V6$xU57;42X>Q=dIk$Kf12EoL{x`A}dA!SFesFR-t(PG|m*4z`5Sa4O-I%yg? z829`AV!u?BaU1KlZDV3!!$5#Q$uLam0ENlil))7Vi~T6|WvFJ1v?+UOO#`Ll6oM$H z4U5L4{-b75c4h2I4mB@j-3;uI z#j>A(b;HT~aZKKOaD!Zb>;2zf9g+}$w55BuHb6LInRr==-UwEJHJXw9^i2KCz_D5g7 zeQfuh*RHPLf3{&>^S2M(yF|~Ox0>G+-cmk1e`fY;`5J}(m2)%EgFhGMzukRE>z%sr=zC{Axpp!8 PeAJg#+>f7n;pM*p()7_uRZk8OAZ0|X;-U+lDNK9AZa9h^S$rA@9Ev! z-uiU);`U>T6{)cxp?cC#duv_ki zw|uS=g9$a1#w^JIt!dZSW*OsqvP45Uiqk;<>*ohLibbH`X@w-rHsm<&9q01)@z#JJ z?{QD)Yd6sKnGXbsEE$?5leF+>fj;N;VO_m8bu@>Rdx5@Q1w^~yHri0RM6N+FCxoK5 zXIQS|xa4C*2_+_JnHI&C>l4Sf+NeHsh?a}U-|610W5H9PkIORiO>;V(8dKX)`N*_9 z&oc=%DaC-m#Zg+a8BU8UONOp2cphhEtWs1lvY|RC109quQb@9fHZAHhLBY%!%S_84 zRZ2@>7@iJIk_KIrn}-mk*85W8VsMm6b4M2HAm?)PP^RUTWiY{;z1cxNnP)1vDJL=k zSOLPUCR8?7r7Fhi6?rtDn`|qPm7YJT=u(x4x)@W7QVEi z;n0gLEFza;hdLAwqYlNku!Yz1NZYcUxh~k>Rs5hTU$uYHwnA~>Xe#7;HYY_s5WjvO0%7O`>15|(XK zo6E@4k>Gx$@`OR3#0eWoGfPK0dahM~oU&Z5kD${3*<9wU#24)Fbm?a^ z{(qESmz9rMI+8FrO}$FStVYbj6!YJH&A+`cj+Stkan-UJuJF)|XPE+Z4#W3@U&(zK z+^v3heb9M}KRr2FTlwg_Z{9xtZ0+u|r(gZJs>L@SefVDX$HRLk=+;l~^!EL5W&gLY dKVRuR(tdHZKh=}N->cEz-`win|K!VW{{j2h`quye literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/items/metaitems/battery.ev.vanadium/1.png b/src/main/resources/assets/gregtech/textures/items/metaitems/battery.ev.vanadium/1.png new file mode 100644 index 0000000000000000000000000000000000000000..84cedc4f95c54bae8c2bfb82dd543c036dd55913 GIT binary patch literal 325 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE(}i@HZ!o?WGZg}if|Tq zL>4nJa0`JjpDV!LYF*U978NlZ=Gn%b;v=$?Y@NQ*V{=*wEevI=G*~$ zQP<*)WlHjri!<~}W4nv}*39*gIsPcO?40SwDB0OD%`8$Xo@T!Dmf13F(g|iS+xqC? zhBSi+CV{r!&rffg=kCW>AHN~3SVfo_sA9w{=#J7Gd zGp=jcmc=SC@jb)Z=`UEXc3tyRJuiOVIF3={v}S0ir2YZ!PZswD9Zdhbl+XGWXxP$x R$`t5322WQ%mvv4FO#t{fa~uEw literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/items/metaitems/battery.ev.vanadium/2.png b/src/main/resources/assets/gregtech/textures/items/metaitems/battery.ev.vanadium/2.png new file mode 100644 index 0000000000000000000000000000000000000000..ac659fcc3d2ba06db5876caf347b108904ba9261 GIT binary patch literal 326 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE(}i@HZ!o?WGZg}if|Tq zL>4nJa0`JjyU$h+kG{z zdq=c%j;!|ZSe*2jHD}8Pp^tpq$`mIkS2VFWIYjJf-pZ1q)0258>G64X=EDZ}XWy0l zvAiikGwS>kqj$An9&`WOp+%o4?-E0TGzqPJmuDEyg zR>gj8bBFL!rj8Tk4d=W|nr?MPomce?J1d#bkaBa*B8@4+4_GVbt!LRVt9}vt4nJa0`JjqKj=Lkl{~`GA{_bZEF=>Z1JU=k>ODV&w(^!h6fcU63H4Shk|d%POdu46tHqf`46TK zdp3W5{57kK@zg32htU1ZQ{o=ED=&F@YRhe5hF!7`i@X>GUQSjy>COF2_U5gL_s*BI e?>J+Bk#|B-P@v%Q&5}TmGI+ZBxvX4nJa0`JjHMgIEGl9-a65m>yU#$+x}jz zdxwH%?+_5wSDNH@)QvwOHTR)xj?SAS))CPX9ZeQX#Xm4GN^+a_YOC1QNk~llyT9_F z{nOvcTeq#3m#nQ{<2h+X$BM1ByiE?qvt3nsUz+$8iytX=y!EznR=HIw!y$tbF`Zp< z<+~+&kFhiaWqy8)RRDgxNCmxi=fO`6%0LwGUspRfnOqsk&XC;rwn3 z`?&RL(hBQ~7(>2VJG@h^GjWp9_t|X8v>;B<@3sWPM7=4nJa0`JjyU#$+x}jz zc?Yy3T3b8zrVC6o(K4%I(9Y(5pOBm=enk5PD-Vm~4DE=Dh6O#XvyO=h$=mbroc?!z z&x84&{&q%LU+C}IXMfSeH`L|ItwuJ-1v}3wO*)!0EoCS7qn!$K&ncbWeOHSiQNoIQ zT5SLCzjNG@xg3^msx8^}sNls@W`;G_l^GVT;6Ly&!{FG2?3U$z)2-HSV_gtZ^!@|u zgUa;h$6sH4!YmT1*s!XOU1QIYem9RvOEb-mGh8`!C~q=@!X@Rt$J52mSZ~_uym$V4 ezJi(ci=@B&4GMfw`AZGxPX4nJa0`Jj+5B*C7Xiw*9?b zP3#-FxCQ+awI``{^~xPMb?cDzjff?}(b@h93LJ-G4xKyH(9=5Wn5dAvJrB?6fA{x1 znE&bT$|&nA{XP5auj-r*ak+A9A)DiZ*0V~Jj@Qh4wv+qOPKCYqjL!f5%f^r>VZ|L5 z+yDD-Q&}~e!`f}tC1S-EE=L&{W}lU4_*%tq;A4itv4D)0<>$VN-95n+uyRNF52g=$ zCVzhXHLHv9)G85&(EZF);vTsxFL`;Y#7dZ9mUyD{a)u5U70*wXnkwD5l`Z-H`7Wd0 cXa5rBjo*R-168b;fWBn#boFyt=akR{0BSme_5c6? literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/items/metaitems/battery.ev.vanadium/7.png b/src/main/resources/assets/gregtech/textures/items/metaitems/battery.ev.vanadium/7.png new file mode 100644 index 0000000000000000000000000000000000000000..47f697cfbf2b4c99f51bc01018aeda36647d28c8 GIT binary patch literal 333 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE(}i@HZ!o?WGZg}if|Tq zL>4nJa0`JjHGeIEGl9-a65m>yU#$+x}jz zDvs>c8w5V8DP@}6c)=JH868o{C@pCHk#F7s2Z5HAZ*yB4dRk{46BUxT=ixd1@BW?# z^FRHKSljzWdGY(>vr=bvbwo*L3a~`o&{3-NS)Ms>x57N`OKQ`njxgN@xNASK582 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/items/metaitems/battery.ev.vanadium/8.png b/src/main/resources/assets/gregtech/textures/items/metaitems/battery.ev.vanadium/8.png new file mode 100644 index 0000000000000000000000000000000000000000..c68a9b70d48e0e7204d7819a3016045e29d14eb4 GIT binary patch literal 327 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE(}i@HZ!o?WGZg}if|Tq zL>4nJa0`Jj5UW^3mE zQ{KBT`s!q7^s7!KHL}alZA+Yo0L!BsvtuS3??3m=YpyUmky4cN>E#xF2Z^?8jj_>& zzWhDMqZz99djH)deEszqUWN%O+6<2>_#6T?rUY5kK3saR;7HYS#up`TtZSGn?w!3A z5qgUELfBdcrBAX8z6#A4nJa0`JjyU$h+kG{z zdn#8q39MI|h@;&{V5!ds!I)vz}@=g-fC1c_(Wo2{Au zPr0^IV)KOlo~Y$P*SAJwADz*9q)_KxT6V7Z?cA$R^*kOl`KbNYoA2k&pyK&R#-c#9 zJL!1E9>xRAC3YjL!D$w>$b{}KYgJ(H8 zQcu}mtd3(4{KIny(8+9~c2O*ZGl87p6p$QW SkaZjAJqAx#KbLh*2~7ZB^?a28 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/items/metaitems/battery.hull.iv.png b/src/main/resources/assets/gregtech/textures/items/metaitems/battery.hull.iv.png new file mode 100644 index 0000000000000000000000000000000000000000..cba4b8aaecb2609f6d8f9338f2f28154d85f5915 GIT binary patch literal 352 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE(}i@HZ!o?WGZg}if|Tq zL>4nJa0`JjhvNv7xasTSq$WR!({78z`w)(8X((%9J8+8QeT4fbBx|4_p@vBC77 zfz=n5r2EH2D%t*9@(1#QOl_!ap1^%?f7RIoCr)%^GB5+d;w}2hcFuNdeSV#9_+ZH_ z3=}&2dw$Q7qu>A6uV4#cI$`$U|Ns9}BpJ9}y7n^g@2x05{Ga=osi0^t-&}EtfJsK1 m6o2sS_#?GQX4y4nJa0`JjwYtt zM&|__P0TvN8cxeNyO|m5SD0$(u-vtKtj9Ho{vu1I!G$}Qtoj!Jm>Ab1_`_uQo z|Nr3c>#l6h$#nhLdy%uTvzmfn_)V7ujoB8$LWd%G7X1;#c#*H|5uS(l#Z`N>o9^J887+l1-M&MbQI(?Tx$^YYWI4ZaeaLRRrG zRD8eirJf;M*QrB`!J+T?BF?01+2OYxwLK%*V)D0_HT;%+eurPU;l0DZs(<@7XmG>` t9gojVoToCyZzo44)11#T2ipHHV&6O^MX0hr|2)v!44$rjF6*2UngIB*iT(fp literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/items/metaitems/battery.hull.uv.png b/src/main/resources/assets/gregtech/textures/items/metaitems/battery.hull.uv.png new file mode 100644 index 0000000000000000000000000000000000000000..9e66608c1e11f9630348ea7104015335123b4e38 GIT binary patch literal 361 zcmV-v0ha!WP)=g)R53poNI04v2A`vhL-~!#rh%u{C zosf(|U;J0?-dVvoklwH-RdnTx+s&5blrR}gXttVn0ADx8Cj1w zh`jE=cTxNA`MWUvurG_>#Zy~Yf3I&(*@u(?vSS9|n%`1a% literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/items/metaitems/battery.hull.zpm.png b/src/main/resources/assets/gregtech/textures/items/metaitems/battery.hull.zpm.png new file mode 100644 index 0000000000000000000000000000000000000000..49d8969b8d02edddbf1dabf7035c2bedc3e6dbed GIT binary patch literal 335 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE(}i@HZ!o?WGZg}if|Tq zL>4nJa0`Jj5A~8yGz|vPdUhDElI0{4vKdqM?dyidpZky_Y9{embvM|4(t&-FX|M zb3b>+`E{TE+4Hr|-#@=Mw7jTc%epB-44!8$f8=Ng$exq+_2smM*WNrbzIeb{Q+27! zhqmwo+QtqqzJ3;*_F2+*d;E<+nN|jqKbor>r?WDs7{=vp=sw@!A;<6_L@S78CQIYS zGmiyS87$@OtjcvJvHmfNXFj8Q?0UnJBlDH-+}>a<`}p_2==7K!dNafQoVys7pJjWH d_wRHJgF#cA#>VSWZ-M?~@O1TaS?83{1OO4nJa0`JjShWxj}1*(ktn^`J%fgi^`$5|fTI<0s9 zwBa#NcWJo^L0t1SuW0c$Y)@2@EfPyzitP5nZeW5&t;ucLK6TXVu>sO literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/items/metaitems/battery.iv.vanadium/2.png b/src/main/resources/assets/gregtech/textures/items/metaitems/battery.iv.vanadium/2.png new file mode 100644 index 0000000000000000000000000000000000000000..bfff7c02d9a929fb488d2e5813214bd3b286f308 GIT binary patch literal 346 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE(}i@HZ!o?WGZg}if|Tq zL>4nJa0`JjJQJ{WukcwvrEA5<4Sz36 q3Ewr{7QD^r4ukaHe|Jp&FU|X+9)4q!Q-&YV%M6~belF{r5}E)4Hj4}Z literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/items/metaitems/battery.iv.vanadium/3.png b/src/main/resources/assets/gregtech/textures/items/metaitems/battery.iv.vanadium/3.png new file mode 100644 index 0000000000000000000000000000000000000000..8a75730084dbf38dd0e492a3263df52cf45dd625 GIT binary patch literal 346 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE(}i@HZ!o?WGZg}if|Tq zL>4nJa0`JjeQD4g`Ru5IEGl9UOUO2+c8n(SpE7n zY`Z^+&hS)I`)}7UWlByBgQnWj91z zp3WSJ>+^dU9JntUDj4PoMnT@20$+}c)I$ztaD0e0sysugpdFL literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/items/metaitems/battery.iv.vanadium/4.png b/src/main/resources/assets/gregtech/textures/items/metaitems/battery.iv.vanadium/4.png new file mode 100644 index 0000000000000000000000000000000000000000..69292d461dd665ce52b99b4b90b049e83ca1e1a0 GIT binary patch literal 347 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE(}i@HZ!o?WGZg}if|Tq zL>4nJa0`JjH zt#L`*S6o6uB)A1SGfH$ER6Z=%aOB^}V0> zY`@3-NWc2oF!a=stL9Y~G+#|tl}XDf(w*8BW5cjqZ>b2wqr7*e3>LaPPA4B-*7N6P zew`5{^KN2LSA(uemT$xMG=|&_pWQB~drL(zopr04O4nJa0`Jje4Ap4tLJp6=P7(ZPA}rf9t8I zbfQejr)Jq8uZM=MQA_zgT;rMWI)AR9)nm)8F<+kcq}{$5na pdk>VI3Ok{FAZWj>`PurF+AS54EcOe(w*±OXk;vd$@?2>`#!gERmD literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/items/metaitems/battery.iv.vanadium/6.png b/src/main/resources/assets/gregtech/textures/items/metaitems/battery.iv.vanadium/6.png new file mode 100644 index 0000000000000000000000000000000000000000..27e5558eb718984fcfa5663bee466f0597e5f06a GIT binary patch literal 349 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE(}i@HZ!o?WGZg}if|Tq zL>4nJa0`Jj&+0P2V8D+3#A&mFkU*XLd~qV(8et^De^!3)u&qDf7!J z=kQ(Nm%4e6PjhL3q|?$6){1Pl6D8ZfajbpV4nJa0`JjwfJh z&b>#p1B3$u*Uo1b=*%dwY4BJP;??_rS75JGM!w1;MwW>;lDMZH3q7%EcJF=Dw>zKj zE>2_n7df>g;^}0;uf6ZKcD=pG#20)mD)wlzIQxNB-kPipJ7!z^GWdN~+!ygKbNce1 z0*_Zre*J!85Ldru$Z6At?P(1;`OkYU$my;~TdbdMa{KN->FG`>yQHld4)lCn$NYGO za!Uad!#2jZmX6H-mvHnysbJ{Y{3GxFt0eXvE9WzMX_hk-cdS#svpn3x^~!?lKQekd quL<4Oj8bq5AdWv4=n}GkCiCxvX4nJa0`Jjwayn zUU7lW@C9m%7Ja(@!bM3+mR~_gYif}43eyV4)(iJMjxc+491)AoSz0K%=}p?>a^LEA zKi|!n*;pT@D;#z-#ie#}_1dKJT}_YYlk$-D}2htfJ|Y%h6XVYdv%cm=6Z*fE#(;g>g>C{eb)`fyjSTBL8oL7$Siuz@%`o0AVE{9Ep}1K qi#8uCI~8_9`+(bSTl2H^E4A0Zh|qiJCbb3VX$DVMKbLh*2~7Zm{D}bo literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/items/metaitems/battery.luv.vanadium/1.png b/src/main/resources/assets/gregtech/textures/items/metaitems/battery.luv.vanadium/1.png new file mode 100644 index 0000000000000000000000000000000000000000..b9e356732903e3e6da5ba17f0b29647948af4ae9 GIT binary patch literal 352 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE(}i@HZ!o?WGZg}if|Tq zL>4nJa0`Jj^l!-ys8u*8O@i zjm`@=lGr2E0$O|~Yw|THJZ56)eZZjcWs|VU0mfNrT)oTEm>L&wB;4Gzal?V&+_-zw z_pi7A6Fm9hg+AN!+df*m7Ef1EP|cfmGj4k{qe$)2DGUOY6=uu|S7-f8_)vH%B)i8@ zhmU_v8`|eAu`&{g><7UH@B~kTkd;VnXUthMtTj-ENMO@$UTYp{_F($nIeP*c+ zGs8VwlfCi>B$@>laWNE3U+i|GY|pCq3#Q5}=h<;D?=8c3>ua~<)f)CNKfnG}{Jryo vO0&L2>+2Gwj!y~O$&tx4XEToi|9@BhH(|*_PruFtg$0ABtDnm{r-UW|T#JdR literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/items/metaitems/battery.luv.vanadium/2.png b/src/main/resources/assets/gregtech/textures/items/metaitems/battery.luv.vanadium/2.png new file mode 100644 index 0000000000000000000000000000000000000000..caae7e00d5d874b3d1a45f6a394534d9cc1e7ab8 GIT binary patch literal 353 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE(}i@HZ!o?WGZg}if|Tq zL>4nJa0`Jj&mJk>gy0la93`v&@3bWfwBC)C4%X7^dk;b938VefG5W z=kH&K?M>f(e|w=cS9bqI)9ryQL6^LRZs(bCH>_DdMTkL(_k0?|k*Lcr%k2FmvwIEO zjy`M%^0KhJ{#omAY8}^%95V&gjo0Qg>f7IV-z}T7xTEvEz5em!%zq_288&>gc^34H zk>S1Es(btiJ&qiKEDSwm&0Z%qZPj|eV493N|BickUm3nzU%Mr**06>7`Sq{j@0;K6 vGUI7lUzaG=_9V=bdnMDH$t()I|6TdNUP~6bvwl$l(B}-Eu6{1-oD!M4nJa0`Jj^m))?ovQqxD9X zP5c*Erkr5xQJm@YF~;aAgJe^6^SYN0j4RCS8a;{_6m3fRB-b8wZs!SXH#>H$zGLHk zm5&wncDA(!OYeni|9)0k)?vSTR^hCsDLP$;_U*`H4){7Xh{<8f!@GP9KG|{4KcCYy zUTb*lL!s5eDMEf{zy7^fFgu>fERZE=Qs!OWAKwo@-gwh-&a#}Q2k(pQwm;kdS*Ah% ze!70DEW?Kv3*Y}`I402|;LC8};jVXTJ2srLzilm{a(pFoUEcP@hTpQ;Z#y^_yg4Ab z``@EN4x968i9fFB=S*(7r4_DN+u$9@Fy*1=7w&&|Qq)pqXU7A*&*16m=d#Wzp$P!Y CWs)NR literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/items/metaitems/battery.luv.vanadium/4.png b/src/main/resources/assets/gregtech/textures/items/metaitems/battery.luv.vanadium/4.png new file mode 100644 index 0000000000000000000000000000000000000000..114823c5bad4ede01fd9587f998c49a84fd11c0c GIT binary patch literal 357 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE(}i@HZ!o?WGZg}if|Tq zL>4nJa0`Jj^oBxcJ);H_q z$)82f&$Q-e8Ohw*`1+PwopyHKB90|b%sq3q-_>K-v@ghup~J*xKC?i!@A~`e=NMg+ zO6KYQE4Oq?LD9PBSKChi5iy8e@934Zb~U5F{f)O>vN?-7R=&5_Yj@84SF)2~!zY`6 zOU^Je#MxfiD}O+uSzr+d!;ODEt2mio$V`7KYclEa6UP77vyBhDZQJ^-nN#8IfuALR zkG_7edmV4{gSGK9S`~MOo^yJ|@LYw_<8b^%*#O354}ESUX`t^JJYD@<);T3K0RSFG BitYda literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/items/metaitems/battery.luv.vanadium/5.png b/src/main/resources/assets/gregtech/textures/items/metaitems/battery.luv.vanadium/5.png new file mode 100644 index 0000000000000000000000000000000000000000..7189dd0b2a617a0f79edc6207acc90533cdd4792 GIT binary patch literal 357 zcmV-r0h<1aP)z%B_`RaJiz1McNs`#F!Jq;t`bsGQAoB2P z1wgDdqw%4nJa0`Jj3Vrl+aSX9Iy>^m)UbBJ3(fVyg zEi#LoLkzz#bTqD9HDj@lC4;kT{)L^+=MMB(G){fOFzx6SOXD~RBZDKdw-f~GLtO5q zyngxj%g>+9?pe}p@6LX|D^q{f?6M8}(u$Q@-?zklXUL7u)@5)J?n`FiO0M{}=b|Qe z@`h`l3au7y72EWf?O;m9iF}6LhZ(0VGDws8@Lc_P^8RL%^EX{DzJFRHccy;2Dnq>E zf!#r|3lvz=yBo4&&okf2vv@A%!{Eza^zv8t zZ^ciw(^XIIuS=YtS`xOCcP3NJDy{{b_Ad5rbCd0U9yJsPdY-}4)z4*}Q$iB}Y88v{ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/items/metaitems/battery.luv.vanadium/7.png b/src/main/resources/assets/gregtech/textures/items/metaitems/battery.luv.vanadium/7.png new file mode 100644 index 0000000000000000000000000000000000000000..4e771428cb007832a8d3112993d028c207373ebe GIT binary patch literal 358 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE(}i@HZ!o?WGZg}if|Tq zL>4nJa0`Jjj!o7ZYuFqcjdjyS-mqb+K>s7Es>ARvKjnnqxq3rp}# zsk6(Ue{3$#GMl+0|9*MxpZ-ld{e%L#3g_)!e{cbt#_yNf`mk>uz>% literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/items/metaitems/battery.luv.vanadium/8.png b/src/main/resources/assets/gregtech/textures/items/metaitems/battery.luv.vanadium/8.png new file mode 100644 index 0000000000000000000000000000000000000000..337786250780f4ef2be1a0885c17a8a9fa3edf27 GIT binary patch literal 361 zcmV-v0ha!WP)bCszFV5sN~(zOF;$c#9FmE-`H#nd@N zC%iCp$PjmEfARse;ADc_d z6RwO$LhXF9oTdQ>R4*`!S}bB_pRF9}UEZciaE8U yM*cHt-K5jMT1K(uM4j(*8HOdN)f=^cusyldlzZxa<36DG89ZJ6T-G@yGywphqKdKr diff --git a/src/main/resources/assets/gregtech/textures/items/metaitems/battery.su.hv.sulfuricacid.png b/src/main/resources/assets/gregtech/textures/items/metaitems/battery.su.hv.sulfuricacid.png deleted file mode 100644 index 0ea8aa896a7c6182fddc650a034373efbc67b637..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 363 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4%caKYZ?lYt_f1s;*b z3=G^tAk28_ZrvZCAbW|YuPggKR&Gu{{ew+kt^tL9c)B=-Se#xv*|4j{K&0(IPc@q$ zTg#jS(mwNzmKuEjz_Ts-74MpDK2LdrY_^FqC5c`zE4!(c7*l@e!JGJ}d)@c#v9C zUwkh!Fm!OFM%v}h?AV~gy=z_bwOMa<3eHWgbFP(Wo3XpaHTJr}v4)O$Oip`qqgh^G zY}zUoIZf4i#xl(&i|6j#k1f;~U+?<&x99e@qes3!*X7)KZ-3cG*8Eo{3Neo|8Is@B z>l_IbbNW#^FTSeP=KS}?GAb<|b-vlU3`fqgACUaZaBovn?)qO&4Ztv9@O1TaS?83{ F1OP2>l&Sy# diff --git a/src/main/resources/assets/gregtech/textures/items/metaitems/battery.su.lv.mercury.png b/src/main/resources/assets/gregtech/textures/items/metaitems/battery.su.lv.mercury.png deleted file mode 100644 index dfd36bb4d799f4bf32559f86609e85fdb3560e06..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 316 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4%caKYZ?lYt_f1s;*b z3=G^tAk28_ZrvZCAbW|YuPggKCSD;WE1|G0=YT>dJzX3_EKV<-WXsiJAmA21&9-H( zyTG27TSw2$t`It}@PwzDm0w^(;2NDZN7J?$ZFsZBr7R)A!$|-0XGy__^3^f1*GhF$ zBjf%nD8=Wk70q5Nb6oLWwPu&oCmZp%YiGUL%l~c;_eQqB=#1NDM?-{S8h;DfQ`+V-*YX|Q;b*+3P z_TZbq;ssHWp`j-?>BwjMOlnD#@DX{?GG`Ifl_%Z~YxXkg>d&va?>iw2=qUzIS3j3^ HP6`w$l7pTo=a(c@fl{a51K38`s&{qteu6{1- HoD!M<4%&C8 diff --git a/src/main/resources/assets/gregtech/textures/items/metaitems/battery.su.mv.mercury.png b/src/main/resources/assets/gregtech/textures/items/metaitems/battery.su.mv.mercury.png deleted file mode 100644 index 5ebf6f720b01882447b8112353ec2e17ea1fdc72..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 345 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4%caKYZ?lYt_f1s;*b z3=G^tAk28_ZrvZCAbW|YuPggKCO!s1y^kO60_7Q=dAc};Se#xud1G&jfq?7$i=vJ# zFB;VJ3SUg{TG7a4*2uTwfUiYCAB&UAGzHU{`bM{Gx4hx1d-5@3-touzf=&gF*o z4f$}7nPaW#|00Hi)&19^j?@ZT2Y9uvdo9t{xJl>arZ)w*itkA%mo)@wT`A>l*g9>I z#=UJhYf~e|Zf!d%p*(5Eid9?>k_{a$n;e(4cwTnG+V?Wc0gJvTm31;n_rEW1D2@HT zRp1c^!wb3o;1l_g`;KrP*p@rJc0xh$bjFMJ(-{jpwy)n19qA?ctn%M0$;&3STZ^Vl m`Sc~*>N&%=N6Zhp{xNi1%~#0Xlu-cmF@vY8pUXO@geCymx{k^K diff --git a/src/main/resources/assets/gregtech/textures/items/metaitems/battery.su.mv.sulfuricacid.png b/src/main/resources/assets/gregtech/textures/items/metaitems/battery.su.mv.sulfuricacid.png deleted file mode 100644 index f4136f52d1f6765ae75c059dff025c8df0395e38..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 350 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4%caKYZ?lYt_f1s;*b z3=G^tAk28_ZrvZCAbW|YuPggKCO!rs4vq`lzCfYZo-U3d7N?g^Hq2`=5OAFzZpjj) za)ft>W7TxMiADV99CoYTY0z4#|L~AkH;Yrqv<0SfgC*ax>2^K{m+OC4Y4cA^k!9VB zw}t^;tnY0bE<}CSW*6A=J!7rw9r2CKOG7elPuuriv#ZI(w|u$nvtGj_W{sszp`i>B z*(X2$Nj-fn>RIKoOsO8jM`FUMkxYLgc>=C~tz$d4llPO?V+$q&9_GktZ`*H_-c?M9 zoR+KGa)X&+-+TG?3E$7JU;cw_!@Ad*@^^NuxZLn!{^bUXBd5b}tkGG@bJ^tYYstwf rmD`G@O!@R7+v+*PwnwrLdg>UOw&p8T>i>NP^frU1tDnm{r-UW|y?czg diff --git a/src/main/resources/assets/gregtech/textures/items/metaitems/battery.uv.naquadria/1.png b/src/main/resources/assets/gregtech/textures/items/metaitems/battery.uv.naquadria/1.png new file mode 100644 index 0000000000000000000000000000000000000000..ca0c1c7cfb410093c7838bf893afdcd02cd14825 GIT binary patch literal 362 zcmV-w0hRuVP)0QX5m zK~y-)t&*W`0znXlza@PG5+0!jfk2U9!1R))Cs2e}AQ&D1awM3#25gZ?1l()vCMV9I zQJavQLSUxqHcL1zy_S*tXTJUanSp0kFbt&k(UU5=^2ObDM{-UWzl~|UHtqnvZj4b5 z5DWvEujT;gRMT#@AG*}3#%7jy5o3%|HD7GiTcyoKx&uU$h~%80Q~eN->xbyz-d_BC zgV6whn79yNj~0M%5wf4{Zvg=L9Ln+o*vz7ox(5Js-#ev{ug`Vy460QAy8~P=*Gd2p zK}7!Uz;{vm@At<8 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/items/metaitems/battery.uv.naquadria/2.png b/src/main/resources/assets/gregtech/textures/items/metaitems/battery.uv.naquadria/2.png new file mode 100644 index 0000000000000000000000000000000000000000..4f6bfbf67eaf5af4c744871d5fd64ac99a09d369 GIT binary patch literal 362 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE(}i@HZ!o?WGZg}if|Tq zL>4nJa0`Jj-YI zxaW@j=ePgQ^Vn=|N>teUeO}1Lsrq^5(UXD?{mAusytR<|LuqnPQA2{ni5yF2hvl=% zHrHNX>St=U`N(I9li|Muv)bPW$fM<+Mq zw**Fx=Zd@6-!)}WnC~1}$1po`O3-$OhIcE1xqkkO5k0@a>*;>$13$mVa4INuoOsMv zBfj+-vM6C(cx( zHX%8Mz)aO`mT+9S!pQwI-~Rv1z%wft1=4%#NfllB;&!toIVOw;V;arI6~NbxG0Fjg zQ6RIg82~!fbXuL8E_JH0nI)db7-Lk;7u)rAX>*b80MR5OIVR{--vs3PKH9st7eC+d zV+cS@TnMng7JzUbvisa!0s!(kl;sDonMEme4FGsubW0(t_wV8vRH^)T2RNV3l>j1w zi2UDy@1pkT`MWUvurJG>_f@`*&zdP%}=R62R~#Jf3LTX00000NkvXX Hu0mjf69tcZ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/items/metaitems/battery.uv.naquadria/4.png b/src/main/resources/assets/gregtech/textures/items/metaitems/battery.uv.naquadria/4.png new file mode 100644 index 0000000000000000000000000000000000000000..b2515d4f84ed105cac5709e8ea7986b1480f76c6 GIT binary patch literal 361 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE(}i@HZ!o?WGZg}if|Tq zL>4nJa0`JjDUST3_S$Z&3JJ0;fXa$xVVyrM@uQd>DsuH-rsayLz1W_n!W zlYcYw|JSEIm?`SREV++wY2UhkP|%ra{SlYS39POGcsj63Uk`rf@gdfvQpHiLlhbfz~a znFQ83@pU^3GE6wXP|LpItd7^pXodq1R>yPxd{IB``~ttH`>hXreICWFpww~Vzw8e^ zss4HUxsAEpH~owIpUHjud+x_6wH~4h*69rEerkT@=88`dZk+RWE-(ZbJYD@<);T3K F0RRkPi+%tA literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/items/metaitems/battery.uv.naquadria/5.png b/src/main/resources/assets/gregtech/textures/items/metaitems/battery.uv.naquadria/5.png new file mode 100644 index 0000000000000000000000000000000000000000..e3d0d5183ef82f05f3b7b70e38e1965a3e61697b GIT binary patch literal 361 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE(}i@HZ!o?WGZg}if|Tq zL>4nJa0`Jj>X0;}L-xz&6W@)vFVdQ&MBb@ E0H>gdPyhe` literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/items/metaitems/battery.uv.naquadria/6.png b/src/main/resources/assets/gregtech/textures/items/metaitems/battery.uv.naquadria/6.png new file mode 100644 index 0000000000000000000000000000000000000000..ae642e38309c70a32f730d8ec18df09313da201e GIT binary patch literal 361 zcmV-v0ha!WP)z4-b1 z!#)5BNh!b{ECA6gV*9nd1ppLtsLBsubBj{y9sm&R-zy>C%|-bP>QwQ&16r;chUIo`MWSd6v%uz|J4>&lhy4h`;aO?e#`+}^Hb^y5PxJ7&;5$i00000NkvXX Hu0mjfVj+>& literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/items/metaitems/battery.uv.naquadria/7.png b/src/main/resources/assets/gregtech/textures/items/metaitems/battery.uv.naquadria/7.png new file mode 100644 index 0000000000000000000000000000000000000000..b9ae7caa394282c084ad59cf020539242f57e8bb GIT binary patch literal 363 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE(}i@HZ!o?WGZg}if|Tq zL>4nJa0`Jj`;VJSInhw*9Jm z969?N92EklHoTDZTi_Ajc;ySDS079BQZW@F#_v+QPj(t#HN89KNeFA&s=UoDyS>*N z6#YN5{lC3&!FjG_jXcMgS1#6$zw`c^%JP<*mwU>V*Rp;nP3|dbNRT>FW6SQad{*7| z_*X&8rDjJya_up6Gp*V9{le-Ty-TtRRh=GwoK{ztHpJMwxqrX*<+JZRb%rBHS{Z&P zGIEG3wr@YI%AhdcIkb*pcI1?x>kJJSuP0kBWL^FK`yj=K9?u9Jq(yO`|12`8*1;y&D+Gkk||}rWJC5o@4rm^OH`8tDnm{ Hr-UW|ft-;I literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/items/metaitems/battery.uv.naquadria/8.png b/src/main/resources/assets/gregtech/textures/items/metaitems/battery.uv.naquadria/8.png new file mode 100644 index 0000000000000000000000000000000000000000..563cd0dbadab20f37d6d860b858e23c792803002 GIT binary patch literal 364 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE(}i@HZ!o?WGZg}if|Tq zL>4nJa0`Jj8~Qoh}FV9?L6!3L2&78)jP2} zrcL~vzVGkbG-Q0+;5@>uJ;QDsRS}bv=FW*1mi`+s>b{qm!HQ z+i50&bxwTi+r1ea?AllTVKCdQv2-0HgFkmjP}`y4~e=h#=`K|fPme$2E@0|o+vr>mdK II;Vst0I4C6y8r+H literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/items/metaitems/battery.zpm.naquadria/1.png b/src/main/resources/assets/gregtech/textures/items/metaitems/battery.zpm.naquadria/1.png new file mode 100644 index 0000000000000000000000000000000000000000..06bc6e1d9bfcac8b3c3aef0cf80aa36f624c4e9d GIT binary patch literal 337 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE(}i@HZ!o?WGZg}if|Tq zL>4nJa0`JjryS8Nlh3;87# zh$dA5p+rV82OY$?86aA9HWUlHtovUJmzj+QcA! fp1I>}{Y-78lvs^;k7HMXK4tK9^>bP0l+XkKbfkf{ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/items/metaitems/battery.zpm.naquadria/2.png b/src/main/resources/assets/gregtech/textures/items/metaitems/battery.zpm.naquadria/2.png new file mode 100644 index 0000000000000000000000000000000000000000..43fba74879774c966a12f76e5c912feb9e170283 GIT binary patch literal 336 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE(}i@HZ!o?WGZg}if|Tq zL>4nJa0`Jjcy|NUMM6uRr_;uvCadhH}bp@R+*t@}m8 z3s~F}Gzxg!)+=`Ub%%+|9CTeIaP{1ap0lDn>=V{Bx%jwo{QGwH_qY1@@jsr2{9=yH zEiaMVJ458|)26#0PdLbK30%FL!86uNlfflrp1(Rng;${d^!U7&nyvCJIqhaaUV$Af z)ium}jF~I8P3?Q2C%(l;d-LLi*NhiRo~>#BX3U__^)Zjxou?cD-T6k@?C;azl24nJa0`Jj ziza0Ovr?W%99v3RRLrJ@x)%tF9m^83Hr(rUm~l(8>g+9XL4&EiPgC9#K0ctQ3g*}KbLh*2~7a~J$`Ed literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/items/metaitems/battery.zpm.naquadria/4.png b/src/main/resources/assets/gregtech/textures/items/metaitems/battery.zpm.naquadria/4.png new file mode 100644 index 0000000000000000000000000000000000000000..67fb3f2210a0ed62bd90691536a06a76f0764995 GIT binary patch literal 335 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE(}i@HZ!o?WGZg}if|Tq zL>4nJa0`Jjg(4=Rl2&nR;#uvB&_h;b?e;|hRj$mO$L{oxHHQbD!eXcn#AS3)NGY^dvn|@$Sbgu zwYrFXk1=z_Hx2oNvATw90u$XI-eX?yTIWXJTO9_4zK?m#_B{elPZ$}F?TX`=DQ&&# zS7irR!;U%LbFFLk%wwpVxt{Tt;NxtEm`CRYCz(YpTPb_|=ZhZc(@LMGUY?+I;A;ho d$C>(>(mGFKH5Pb<`2zjP;OXk;vd$@?2>`>Lecb>6 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/items/metaitems/battery.zpm.naquadria/5.png b/src/main/resources/assets/gregtech/textures/items/metaitems/battery.zpm.naquadria/5.png new file mode 100644 index 0000000000000000000000000000000000000000..430cea2994e23c9b1d171b86fef135d74d3ecdef GIT binary patch literal 338 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE(}i@HZ!o?WGZg}if|Tq zL>4nJa0`Jj`-B!Gi%Jt^3uZ z0-6FFdvY$YE@tV}VAOuSfJHT&&A}4g5^!Ri4?aa@6tIySbIKQ$i zH+S2uU&4E5h)mzCdHXP9^xG|gn}Zsb=q(jtP%`p&b7rVny5ZE*>CwNuHuCG|{L%~Z z3hZDhFJOK$ld)#|^u7&qd^0Wfp6NT(%kOY^_J&ux&oeY=xZPv>{h>)fiI*Wm&uiv{ z!qnb{^6eT79hW~YE^hyRJ^6tCXH$p!$u+zkUVki|?zG)}nQ{K}J*&re3M+n{^7IgU hAj872@uz+4nJa0`Jj^l#-$4h7*8K-r zbz}|-a!3nJSFmNum1X2+*XVnoq_bt?j3a(N>lI`idRwuO$U*>-a3X0Kv_NLFB?bU+r-ZZWWSC&p;a&UQeGli#NwaD45uTQ6~3;J?yD7UkevThdKW7bFDez`x*E9VGYR^gofb306Y=j|&Jn#8)} g&3A^4KlO{5jagzf@|VqW1$vdi)78&qol`;+0MdPat^fc4 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/items/metaitems/battery.zpm.naquadria/7.png b/src/main/resources/assets/gregtech/textures/items/metaitems/battery.zpm.naquadria/7.png new file mode 100644 index 0000000000000000000000000000000000000000..40d21363bf42f0cdd35d492651930a3253a168cc GIT binary patch literal 340 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE(}i@HZ!o?WGZg}if|Tq zL>4nJa0`Jj^l>-@yQp*8SI| zW=A%u3aIhuG(|9ldOIXB9~H`JX)OC9Wc)GbfJ4W|Dz+_Jz4N!d`|_mb{k&rNKgC{i z*Xfx@TXoLs?&`idoC>4w|RyVv?2|0y}PGxg)Asf#E0 iH=Ism7MS(l$UJ*aoZ0osyNZCGW$<+Mb6Mw<&;$UQyMmbj literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/items/metaitems/battery.zpm.naquadria/8.png b/src/main/resources/assets/gregtech/textures/items/metaitems/battery.zpm.naquadria/8.png new file mode 100644 index 0000000000000000000000000000000000000000..eefcc8ea64e827a6dc3ef3664dfe9bb48d99973b GIT binary patch literal 340 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE(}i@HZ!o?WGZg}if|Tq zL>4nJa0`JjD- zow@nywfQf8Zh3Kb*_v`|ovl~hwoYSQQmVO>L11I0krdMdZP&FSRXdih7fCEhx>`OV zs4GUtqM7@_RLKM7RW~{A<#-)_XZuzo>LgTe~DWM4f(5Z(S literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/items/metaitems/cover.infinite_water.png b/src/main/resources/assets/gregtech/textures/items/metaitems/cover.infinite_water.png new file mode 100644 index 0000000000000000000000000000000000000000..4c853009a4b925be7ad75ef5d51ada5f6388224c GIT binary patch literal 2484 zcma)8&yU+g6ix+Nl~$ENa6lCju3HI^a6FzkPHZ)8x5;)lXw!{$BiOw_$1{_}Y~nHY zq{;TeQXwQHgb*A+2u|F4jgn{Ct5NRI6{-}~Ord7k&% zS65G+IDMi}D4c4pH8$b?q`HnT!T{!s*mfNj$ zkBVWDFyZs!WEcUuP&j{a5)rz~rRMWq5Z3fRzWH9)0#?&sE4NT9s`GxZb|dCnH?DT* zja}+8{o)1f{KNx-A(up(3%p@Uo4S@lFUGV)AwJRTRvrJ{&? zrscY>iLi;W0SF`63niHtVRClH(BKJ;gGdG<)D$D}#Yon4@N^o&Flx1O;xNe)1t~Kp zBr>fcGKWJISBg&L%5_lA+*pWCI(rc}H+dpPG36`Qc_`1$)K{CWcCM|0=moGuD=lnuz|>6-XF!ofTvrsDeE#Hv^h6y zZrKLmU1V@laS?KvZ?TfDsiyFj+s&Geizs_-4~XoFcnJG32$>isnYYr4i8L~<~IAUV({R;h!qS3+JHUTqI$(3W69cW)82T)r0yqk|Di{uiuT z$AgSR-HF=JkOf`K`@^e?fr!B_I0tz>lsD`3b}YKV02Y$X)yrCQrS4d+;}{T`niJDj zSPK$}doPXBge3< zl5bS2j&0bbGA@-k<;;arP4yGem17d~p)5euE0TT5#{_Zu)MI`sftUPT!$a7TF`Qa<_J8>kPCPr! z#&W0n6uow7|KObe%-w_E{(0dXVfEWLPgZ_EbGowe#!}_+TYta(o%`HZyO%!wDcJw; z$DMCK`+8{~oq6o;dp{s_?KXYq&by6Q@D-;pIKKYT_6OzFk3aeH*suIT?RD?xf7Q9F NxpK8}>+-dm{{g0ZAJYH; literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/items/metaitems/magnetic_field_projector.png b/src/main/resources/assets/gregtech/textures/items/metaitems/magnetic_field_projector.png deleted file mode 100644 index 8b661977397e6ac8f612dd1545379ecf97649bd8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 748 zcmVPx#1ZP1_K>z@;j|==^1poj532;bRa{vGf5C8xR5CN?ty>$Qp00(qQO+^RZ1qclR z7ki{vwEzGB7<5HgbW?9;ba!ELWdLwtX>N2bZe?^JG%hhNHDpIvQUCw~N=ZaPR5(vv zQcGwPQ53!VqEw+Mq7+0lMw*X_=7afYLSkAmFh^?Eoy{)QW$ z2-iOnuGX|hBLmlOCT7XaW)nNxJJ{dbN4wp|*MkGJS}pAD?qYju3s=g7%Wq{9$v{cx z$+h=2)a!L@Zfv4dDxp|hMWK*KCi5DNMg!{`>r#C(OOm+T?aBr`+5UsD_HGT8N@XZ6 zBA@5t3{uGy;)w*R)hf#63NF4RTzF3Z47hliZOr9zDse#;r;HYDg%DoON&cVlA0W=Y^Bp_4U;dDm=J~r{4)4c&CSgrCdM@6Vqz=4u%MwRia7gF zWngX-9?Z;Ob~eh6z08iCLW1=yitN~efN(gBU@!=`+avu)A4M_lSGB;0guk=T=R;_E z8i~bW&unufG8B8~_0!WWV1Bm&*m)Z5vD`laxGW7^W-W2Aq7tCi8?# zuLwGw4o0I9R;v|LhAF9Mo;+syFP%eagOeBekeq);n0QLkZI9n$;ybcXp~gTBwV7h5 e7Acf>6a59vVrY+A(6u%I0000KLZ*U+5Lu!Sk^o_Z5E4Meg@_7P6crJiNL9pw)e1;Xm069{HJUZAPk55R%$-RIA z6-eL&AQ0xu!e<4=008gy@A0LT~suv4>S3ILP<0Bm`DLLvaF4FK%)Nj?Pt*r}7;7Xa9z9H|HZjR63e zC`Tj$K)V27Re@400>HumpsYY5E(E}?0f1SyGDiY{y#)Yvj#!WnKwtoXnL;eg03bL5 z07D)V%>y7z1E4U{zu>7~aD})?0RX_umCct+(lZpemCzb@^6=o|A>zVpu|i=NDG+7} zl4`aK{0#b-!z=TL9Wt0BGO&T{GJWpjryhdijfaIQ&2!o}p04JRKYg3k&Tf zVxhe-O!X z{f;To;xw^bEES6JSc$k$B2CA6xl)ltA<32E66t?3@gJ7`36pmX0IY^jz)rRYwaaY4 ze(nJRiw;=Qb^t(r^DT@T3y}a2XEZW-_W%Hszxj_qD**t_m!#tW0KDiJT&R>6OvVTR z07RgHDzHHZ48atvzz&?j9lXF70$~P3Knx_nJP<+#`N z#-MZ2bTkiLfR>_b(HgWKJ%F~Nr_oF3b#wrIijHG|(J>BYjM-sajE6;FiC7vY#};Gd zST$CUHDeuEH+B^pz@B062qXfFfD`NpUW5?BY=V%GM_5c)L#QR}BeW8_2v-S%gfYS= zB9o|3v?Y2H`NVi)In3rTB8+ej^> zQ=~r95NVuDChL%G$=>7$vVg20myx%S50Foi`^m%Pw-h?Xh~i8Mq9jtJloCocWk2Nv zrJpiFnV_ms&8eQ$2&#xWpIS+6pmtC%Q-`S&GF4Q#^mhymh7E(qNMa}%YZ-ePrx>>xFPTiH1=E+A$W$=bG8>s^ zm=Bn5Rah$aDtr}@$`X}2l~$F0mFKEdRdZE8)p@E5RI61Ft6o-prbbn>P~)iy)E2AN zsU20jsWz_8Qg>31P|s0cqrPALg8E|(vWA65poU1JRAaZs8I2(p#xiB`SVGovRs-uS zYnV-9TeA7=Om+qP8+I>yOjAR1s%ETak!GFdam@h^# z)@rS0t$wXH+Irf)+G6c;?H29p+V6F6oj{!|o%K3xI`?%6x;DB|x`n#ibhIR?(H}Q3Gzd138Ei2)WAMz7W9Vy`X}HnwgyEn!VS)>mv$8&{hQn>w4zwy3R}t;BYlZQm5)6pty=DfLrs+A-|>>;~;Q z_F?uV_HFjh9n2gO9o9Q^JA86v({H5aB!kjoO6 zc9$1ZZKsN-Zl8L~mE{`ly3)1N^`o1+o7}D0ZPeY&J;i;i`%NyJ8_8Y6J?}yE@b_5a zam?eLr<8@mESk|3$_SkmS{wQ>%qC18))9_|&j{ZT zes8AvOzF(F2#DZEY>2oYX&IRp`F#{ADl)1r>QS^)ba8a|EY_^#S^HO&t^Rgqwv=MZThqqEWH8 zxJo>d=ABlR_Bh=;eM9Tw|Ih34~oTE|= zX_mAr*D$vzw@+p(E0Yc6dFE}(8oqt`+R{gE3x4zjX+Sb3_cYE^= zgB=w+-tUy`ytONMS8KgRef4hA?t0j zufM;t32jm~jUGrkaOInTZ`zyfns>EuS}G30LFK_G-==(f<51|K&cocp&EJ`SxAh3? zNO>#LI=^+SEu(FqJ)ynt=!~PC9bO$rzPJB=?=j6w@a-(u02P7 zaQ)#(uUl{HW%tYNS3ItC^iAtK(eKlL`f9+{bJzISE?u8_z3;~C8@FyI-5j_jy7l;W z_U#vU3hqqYU3!mrul&B+{ptt$59)uk{;_4iZQ%G|z+lhASr6|H35TBkl>gI*;nGLU zN7W-nBaM%pA0HbH8olyl&XeJ%vZoWz%6?Y=dFykl=imL}`%BMQ{Mhgd`HRoLu6e2R za__6DuR6yg#~-}Tc|Gx_{H@O0eebyMy5GmWADJlpK>kqk(fVV@r_fLLKIeS?{4e)} z^ZO;zpECde03c&XQcVB=dL;k=fP(-4`Tqa_faw4Lbua(`>RI+y?e7jKeZ#YO-C z0AWc)K~#9!V*LOAKLaIziGe~uu>mX$3=9m1_wFUjAGXfUj4UutTuL5EnitKPM58eH zasL_$O_BjW?q6fzP}E{zU|@jLBpJY=s709zkZmT*1p}9mkmHq9z&P|X6JP+ur5*1g Sd!AAN0000 map = new RecipeMap<>("chemical_reactor", + 0, + 2, + 0, + 2, + 0, + 3, + 0, + 2, + new SimpleRecipeBuilder().EUt(30), + false); + + MetaTileEntity at = + GregTechAPI.registerMetaTileEntity(190, + new SimpleMachineMetaTileEntity( + new ResourceLocation(GTValues.MODID, "chemical_reactor.lv"), + map, + Textures.CHEMICAL_REACTOR_OVERLAY, + 1)); + + MetaTileEntity atte = new MetaTileEntityHolder().setMetaTileEntity(at); + atte.getHolder().setWorld(world); + map.recipeBuilder() + .inputs(new ItemStack(Blocks.COBBLESTONE)) + .outputs(new ItemStack(Blocks.STONE)) + .EUt(1).duration(1) + .buildAndRegister(); + + AbstractRecipeLogic arl = new AbstractRecipeLogic(atte, map) { + @Override + protected long getEnergyStored() { + return Long.MAX_VALUE; + } + + @Override + protected long getEnergyCapacity() { + return Long.MAX_VALUE; + } + + @Override + protected boolean drawEnergy(int recipeEUt) { + return true; + } + + @Override + protected long getMaxVoltage() { + return 32; + } + }; + + arl.isOutputsFull = false; + arl.invalidInputsForRecipes = false; + arl.trySearchNewRecipe(); + + // no recipe found + assertTrue(arl.invalidInputsForRecipes); + assertFalse(arl.isActive); + assertNull(arl.previousRecipe); + + // put an item in the inventory that will trigger recipe recheck + arl.getInputInventory().insertItem(0, new ItemStack(Blocks.COBBLESTONE, 16), false); + // Inputs change. did we detect it ? + assertTrue(arl.hasNotifiedInputs()); + arl.trySearchNewRecipe(); + assertFalse(arl.invalidInputsForRecipes); + assertNotNull(arl.previousRecipe); + assertTrue(arl.isActive); + assertEquals(15, arl.getInputInventory().getStackInSlot(0).getCount()); + //assert the consumption of the inputs did not mark the arl to look for a new recipe + assertFalse(arl.hasNotifiedInputs()); + + // Save a reference to the old recipe so we can make sure it's getting reused + Recipe prev = arl.previousRecipe; + + // Finish the recipe, the output should generate, and the next iteration should begin + arl.update(); + assertEquals(prev, arl.previousRecipe); + assertTrue(AbstractRecipeLogic.areItemStacksEqual(arl.getOutputInventory().getStackInSlot(0), + new ItemStack(Blocks.STONE, 1))); + assertTrue(arl.isActive); + + // Complete the second iteration, but the machine stops because its output is now full + arl.getOutputInventory().setStackInSlot(0, new ItemStack(Blocks.STONE, 63)); + arl.getOutputInventory().setStackInSlot(1, new ItemStack(Blocks.STONE, 64)); + arl.update(); + assertFalse(arl.isActive); + assertTrue(arl.isOutputsFull); + + // Try to process again and get failed out because of full buffer. + arl.update(); + assertFalse(arl.isActive); + assertTrue(arl.isOutputsFull); + + // Some room is freed in the output bus, so we can continue now. + arl.getOutputInventory().setStackInSlot(1, ItemStack.EMPTY); + arl.update(); + assertTrue(arl.isActive); + assertFalse(arl.isOutputsFull); + assertTrue(AbstractRecipeLogic.areItemStacksEqual(arl.getOutputInventory().getStackInSlot(0), + new ItemStack(Blocks.STONE, 1))); + } +} diff --git a/src/test/java/gregtech/api/capability/impl/MultiblockRecipeLogicTest.java b/src/test/java/gregtech/api/capability/impl/MultiblockRecipeLogicTest.java new file mode 100644 index 00000000000..5592306d5a6 --- /dev/null +++ b/src/test/java/gregtech/api/capability/impl/MultiblockRecipeLogicTest.java @@ -0,0 +1,266 @@ +package gregtech.api.capability.impl; + +import gregtech.api.GTValues; +import gregtech.api.GregTechAPI; + +import gregtech.api.capability.IMultipleTankHandler; +import gregtech.api.metatileentity.MetaTileEntity; +import gregtech.api.metatileentity.MetaTileEntityHolder; +import gregtech.api.metatileentity.multiblock.*; +import gregtech.api.recipes.Recipe; +import gregtech.api.recipes.RecipeMap; +import gregtech.api.recipes.RecipeMaps; +import gregtech.api.recipes.builders.BlastRecipeBuilder; +import gregtech.api.util.world.DummyWorld; +import gregtech.common.metatileentities.electric.multiblockpart.MetaTileEntityFluidHatch; +import gregtech.common.metatileentities.electric.multiblockpart.MetaTileEntityItemBus; +import gregtech.common.metatileentities.electric.multiblockpart.MetaTileEntityMultiblockPart; +import gregtech.common.metatileentities.multi.electric.MetaTileEntityElectricBlastFurnace; +import net.minecraft.block.state.IBlockState; +import net.minecraft.init.Blocks; +import net.minecraft.init.Bootstrap; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ResourceLocation; +import net.minecraft.world.World; +import net.minecraftforge.items.IItemHandlerModifiable; + +import org.junit.BeforeClass; +import org.junit.Test; + +import java.lang.reflect.Field; + +import static org.junit.Assert.*; +import static org.junit.Assert.assertTrue; + +public class MultiblockRecipeLogicTest { + + @BeforeClass + public static void init() { + Bootstrap.register(); + } + + private static ResourceLocation gregtechId(String name) { + return new ResourceLocation(GTValues.MODID, name); + } + + @Test + public void trySearchNewRecipe() { + + World world = DummyWorld.INSTANCE; + + // Create an empty recipe map to work with + RecipeMap map = new RecipeMap<>("blast_furnace", + 1, + 3, + 1, + 2, + 0, + 1, + 0, + 1, + new BlastRecipeBuilder().EUt(32), + false); + + RecipeMaps.BLAST_RECIPES.recipeBuilder() + .inputs(new ItemStack(Blocks.COBBLESTONE)) + .outputs(new ItemStack(Blocks.STONE)) + .EUt(1).duration(1) + .blastFurnaceTemp(1) + .buildAndRegister(); + + RecipeMapMultiblockController mbt = + GregTechAPI.registerMetaTileEntity(511, + new MetaTileEntityElectricBlastFurnace( + // super function calls the world, which equal null in test + new ResourceLocation(GTValues.MODID, "electric_blast_furnace")) { + @Override + protected void reinitializeStructurePattern() { + + } + + // function checks for the temperature of the recipe against the coils + @Override + public boolean checkRecipe(Recipe recipe, boolean consumeIfSuccess) { + return true; + } + }); + + //isValid() check in the dirtying logic requires both a metatileentity and a holder + try { + Field field = MetaTileEntity.class.getDeclaredField("holder"); + field.setAccessible(true); + field.set(mbt, new MetaTileEntityHolder()); + } catch (NoSuchFieldException | IllegalAccessException e) { + e.printStackTrace(); + } + + try { + Field field = MetaTileEntityHolder.class.getDeclaredField("metaTileEntity"); + field.setAccessible(true); + field.set(mbt.getHolder(), mbt); + } catch (NoSuchFieldException | IllegalAccessException e) { + e.printStackTrace(); + } + + mbt.getHolder().setWorld(world); + + //Controller and isAttachedToMultiBlock need the world so we fake it here. + MetaTileEntityItemBus importItemBus = new MetaTileEntityItemBus(gregtechId("item_bus.export.lv"), 1, false) { + @Override + public boolean isAttachedToMultiBlock() { + return true; + } + + @Override + public MultiblockControllerBase getController() { + return mbt; + } + }; + MetaTileEntityItemBus exportItemBus = new MetaTileEntityItemBus(gregtechId("item_bus.export.lv"), 1, true) { + @Override + public boolean isAttachedToMultiBlock() { + return true; + } + + @Override + public MultiblockControllerBase getController() { + return mbt; + } + }; + MetaTileEntityFluidHatch importFluidBus = new MetaTileEntityFluidHatch(gregtechId("fluid_hatch.import.lv"), 1, false) { + @Override + public boolean isAttachedToMultiBlock() { + return true; + } + + @Override + public MultiblockControllerBase getController() { + return mbt; + } + }; + MetaTileEntityFluidHatch exportFluidBus = new MetaTileEntityFluidHatch(gregtechId("fluid_hatch.export.lv"), 1, true) { + @Override + public boolean isAttachedToMultiBlock() { + return true; + } + + @Override + public MultiblockControllerBase getController() { + return mbt; + } + }; + + //Controller is a private field but we need that information + try { + Field field = MetaTileEntityMultiblockPart.class.getDeclaredField("controllerTile"); + field.setAccessible(true); + field.set(importItemBus, mbt); + field.set(exportItemBus, mbt); + field.set(importFluidBus, mbt); + field.set(exportFluidBus, mbt); + } catch (NoSuchFieldException | IllegalAccessException e) { + e.printStackTrace(); + } + + MultiblockRecipeLogic mbl = new MultiblockRecipeLogic(mbt) { + + @Override + protected long getEnergyStored() { + return Long.MAX_VALUE; + } + + @Override + protected long getEnergyCapacity() { + return Long.MAX_VALUE; + } + + @Override + protected boolean drawEnergy(int recipeEUt) { + return true; + } + + @Override + protected long getMaxVoltage() { + return 32; + } + + // since the hatches were not really added to a valid multiblock structure, + // refer to their inventories directly + @Override + protected IItemHandlerModifiable getInputInventory() { + return importItemBus.getImportItems(); + } + + @Override + protected IItemHandlerModifiable getOutputInventory() { + return exportItemBus.getExportItems(); + } + + @Override + protected IMultipleTankHandler getInputTank() { + return importFluidBus.getImportFluids(); + } + + @Override + protected IMultipleTankHandler getOutputTank() { + return importFluidBus.getExportFluids(); + } + + }; + + mbl.isOutputsFull = false; + mbl.invalidInputsForRecipes = false; + mbl.trySearchNewRecipe(); + + // no recipe found + assertTrue(mbl.invalidInputsForRecipes); + assertFalse(mbl.isActive); + assertNull(mbl.previousRecipe); + + // put an item in the inventory that will trigger recipe recheck + mbl.getInputInventory().insertItem(0, new ItemStack(Blocks.COBBLESTONE, 16), false); + // Inputs change. did we detect it ? + assertTrue(mbl.hasNotifiedInputs()); + mbl.trySearchNewRecipe(); + assertFalse(mbl.invalidInputsForRecipes); + assertNotNull(mbl.previousRecipe); + assertTrue(mbl.isActive); + assertEquals(15, mbl.getInputInventory().getStackInSlot(0).getCount()); + //assert the consumption of the inputs did not mark the arl to look for a new recipe + assertFalse(mbl.hasNotifiedInputs()); + + // Save a reference to the old recipe so we can make sure it's getting reused + Recipe prev = mbl.previousRecipe; + + // Finish the recipe, the output should generate, and the next iteration should begin + mbl.updateWorkable(); + assertEquals(prev, mbl.previousRecipe); + assertTrue(AbstractRecipeLogic.areItemStacksEqual(mbl.getOutputInventory().getStackInSlot(0), + new ItemStack(Blocks.STONE, 1))); + assertTrue(mbl.isActive); + + // Complete the second iteration, but the machine stops because its output is now full + mbl.getOutputInventory().setStackInSlot(0, new ItemStack(Blocks.STONE, 63)); + mbl.getOutputInventory().setStackInSlot(1, new ItemStack(Blocks.STONE, 64)); + mbl.getOutputInventory().setStackInSlot(2, new ItemStack(Blocks.STONE, 64)); + mbl.getOutputInventory().setStackInSlot(3, new ItemStack(Blocks.STONE, 64)); + mbl.updateWorkable(); + assertFalse(mbl.isActive); + assertTrue(mbl.isOutputsFull); + + // Try to process again and get failed out because of full buffer. + mbl.updateWorkable(); + assertFalse(mbl.isActive); + assertTrue(mbl.isOutputsFull); + + // Some room is freed in the output bus, so we can continue now. + mbl.getOutputInventory().setStackInSlot(1, ItemStack.EMPTY); + assertTrue(mbl.hasNotifiedOutputs()); + mbl.updateWorkable(); + assertTrue(mbl.isActive); + assertFalse(mbl.isOutputsFull); + mbl.completeRecipe(); + assertTrue(AbstractRecipeLogic.areItemStacksEqual(mbl.getOutputInventory().getStackInSlot(0), + new ItemStack(Blocks.STONE, 1))); + } +} From 8da065b8355b62bdfc535063dbdfc7ee5b63f4d7 Mon Sep 17 00:00:00 2001 From: Yefancy Date: Sat, 21 Aug 2021 17:00:49 +0800 Subject: [PATCH 41/42] compatibility --- src/main/java/gregtech/api/gui/Widget.java | 18 +-- .../gregtech/api/gui/impl/FakeModularGui.java | 8 +- .../api/gui/widgets/SimpleTextWidget.java | 13 +- .../java/gregtech/api/util/RenderUtil.java | 115 ------------------ .../items/behaviors/ClipboardBehavior.java | 5 +- 5 files changed, 19 insertions(+), 140 deletions(-) diff --git a/src/main/java/gregtech/api/gui/Widget.java b/src/main/java/gregtech/api/gui/Widget.java index efdc9688432..81d52b17ba0 100644 --- a/src/main/java/gregtech/api/gui/Widget.java +++ b/src/main/java/gregtech/api/gui/Widget.java @@ -275,7 +275,7 @@ protected void writeClientAction(int id, Consumer packetBufferWrit } @SideOnly(Side.CLIENT) - protected void drawBorder(int x, int y, int width, int height, int stroke, int stroke_width) { + public void drawBorder(int x, int y, int width, int height, int stroke, int stroke_width) { drawGradientRect(x - stroke_width, y - stroke_width, width + 2 * stroke_width, stroke_width, stroke, stroke); drawGradientRect(x - stroke_width, y + height, width + 2 * stroke_width, stroke_width, stroke, stroke); drawGradientRect(x - stroke_width, y - stroke_width, stroke_width, height + 2 * stroke_width, stroke, stroke); @@ -283,7 +283,7 @@ protected void drawBorder(int x, int y, int width, int height, int stroke, int s } @SideOnly(Side.CLIENT) - protected void drawHoveringText(ItemStack itemStack, List tooltip, int maxTextWidth, int mouseX, int mouseY) { + public void drawHoveringText(ItemStack itemStack, List tooltip, int maxTextWidth, int mouseX, int mouseY) { Minecraft mc = Minecraft.getMinecraft(); GuiUtils.drawHoveringText(itemStack, tooltip, mouseX, mouseY, sizes.getScreenWidth(), @@ -291,7 +291,7 @@ protected void drawHoveringText(ItemStack itemStack, List tooltip, int m } @SideOnly(Side.CLIENT) - protected void drawStringSized(String text, double x, double y, int color, boolean dropShadow, float scale, boolean center) { + public void drawStringSized(String text, double x, double y, int color, boolean dropShadow, float scale, boolean center) { GlStateManager.pushMatrix(); FontRenderer fontRenderer = Minecraft.getMinecraft().fontRenderer; double scaledTextWidth = center ? fontRenderer.getStringWidth(text) * scale : 0.0; @@ -302,7 +302,7 @@ protected void drawStringSized(String text, double x, double y, int color, boole } @SideOnly(Side.CLIENT) - protected void drawStringFixedCorner(String text, double x, double y, int color, boolean dropShadow, float scale) { + public void drawStringFixedCorner(String text, double x, double y, int color, boolean dropShadow, float scale) { FontRenderer fontRenderer = Minecraft.getMinecraft().fontRenderer; double scaledWidth = fontRenderer.getStringWidth(text) * scale; double scaledHeight = fontRenderer.FONT_HEIGHT * scale; @@ -310,7 +310,7 @@ protected void drawStringFixedCorner(String text, double x, double y, int color, } @SideOnly(Side.CLIENT) - protected static void drawItemStack(ItemStack itemStack, int x, int y, @Nullable String altTxt) { + public static void drawItemStack(ItemStack itemStack, int x, int y, @Nullable String altTxt) { GlStateManager.pushMatrix(); GlStateManager.translate(0.0F, 0.0F, 32.0F); GlStateManager.color(1F, 1F, 1F, 1F); @@ -331,7 +331,7 @@ protected static void drawItemStack(ItemStack itemStack, int x, int y, @Nullable } @SideOnly(Side.CLIENT) - protected static List getItemToolTip(ItemStack itemStack) { + public static List getItemToolTip(ItemStack itemStack) { Minecraft mc = Minecraft.getMinecraft(); ITooltipFlag flag = mc.gameSettings.advancedItemTooltips ? ITooltipFlag.TooltipFlags.ADVANCED : ITooltipFlag.TooltipFlags.NORMAL; List tooltip = itemStack.getTooltip(mc.player, flag); @@ -346,7 +346,7 @@ protected static List getItemToolTip(ItemStack itemStack) { } @SideOnly(Side.CLIENT) - protected static void drawSelectionOverlay(int x, int y, int width, int height) { + public static void drawSelectionOverlay(int x, int y, int width, int height) { GlStateManager.disableDepth(); GlStateManager.colorMask(true, true, true, false); drawGradientRect(x, y, width, height, -2130706433, -2130706433); @@ -356,14 +356,14 @@ protected static void drawSelectionOverlay(int x, int y, int width, int height) } @SideOnly(Side.CLIENT) - protected static void drawSolidRect(int x, int y, int width, int height, int color) { + public static void drawSolidRect(int x, int y, int width, int height, int color) { Gui.drawRect(x, y, x + width, y + height, color); GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f); GlStateManager.enableBlend(); } @SideOnly(Side.CLIENT) - protected static void drawGradientRect(int x, int y, int width, int height, int startColor, int endColor) { + public static void drawGradientRect(int x, int y, int width, int height, int startColor, int endColor) { drawGradientRect(x, y, width, height, startColor, endColor, false); } diff --git a/src/main/java/gregtech/api/gui/impl/FakeModularGui.java b/src/main/java/gregtech/api/gui/impl/FakeModularGui.java index 84952e8b86d..33c7bb83fe2 100644 --- a/src/main/java/gregtech/api/gui/impl/FakeModularGui.java +++ b/src/main/java/gregtech/api/gui/impl/FakeModularGui.java @@ -63,17 +63,13 @@ public void drawScreen(double x, double y, float partialTicks) { drawGuiContainerBackgroundLayer(partialTicks, mouseX, mouseY); - for (int i = 0; i < this.container.inventorySlots.size(); ++i) { - RenderUtil.renderSlot(this.container.inventorySlots.get(i), fr); - } - - GlStateManager.scale(1, 1, 0); drawGuiContainerForegroundLayer(mouseX, mouseY); + for (int i = 0; i < this.container.inventorySlots.size(); ++i) { Slot slot = this.container.inventorySlots.get(i); if (!slot.getStack().isEmpty() && slot.xPos < mouseX && mouseX < slot.xPos + 18 && slot.yPos < mouseY && mouseY < slot.yPos + 18) { - RenderUtil.renderRect(slot.xPos, slot.yPos, 18, 18, 0, 0X8fffffff); + Widget.drawSolidRect(slot.xPos, slot.yPos, 18, 18, 0X8fffffff); renderToolTip(slot.getStack(), slot.xPos, slot.yPos); } } diff --git a/src/main/java/gregtech/api/gui/widgets/SimpleTextWidget.java b/src/main/java/gregtech/api/gui/widgets/SimpleTextWidget.java index 34c988a81bb..28062ad7ef6 100644 --- a/src/main/java/gregtech/api/gui/widgets/SimpleTextWidget.java +++ b/src/main/java/gregtech/api/gui/widgets/SimpleTextWidget.java @@ -28,14 +28,6 @@ public class SimpleTextWidget extends Widget { protected boolean clientWidget; protected boolean isShadow; - public SimpleTextWidget(int xPosition, int yPosition, String formatLocale, int color, Supplier textSupplier, boolean isCentered) { - super(new Position(xPosition, yPosition), Size.ZERO); - this.color = color; - this.formatLocale = formatLocale; - this.textSupplier = textSupplier; - this.isCentered = isCentered; - } - public SimpleTextWidget(int xPosition, int yPosition, String formatLocale, int color, Supplier textSupplier) { this(xPosition, yPosition, formatLocale, color, textSupplier, true); } @@ -57,6 +49,11 @@ public SimpleTextWidget setShadow(boolean shadow) { return this; } + public SimpleTextWidget setCenter(boolean isCentered) { + this.isCentered = isCentered; + return this; + } + private void updateSize() { FontRenderer fontRenderer = Minecraft.getMinecraft().fontRenderer; int stringWidth = fontRenderer.getStringWidth(lastText); diff --git a/src/main/java/gregtech/api/util/RenderUtil.java b/src/main/java/gregtech/api/util/RenderUtil.java index 59033cd1c0d..c150c1b1555 100644 --- a/src/main/java/gregtech/api/util/RenderUtil.java +++ b/src/main/java/gregtech/api/util/RenderUtil.java @@ -95,119 +95,4 @@ private static void applyScissor(int x, int y, int w, int h) { int translatedY = r.getScaledHeight() - y - h; GL11.glScissor(x * s, translatedY * s, w * s, h * s); } - - - public static void renderSlot(Slot slot, FontRenderer fr) { - ItemStack stack = slot.getStack(); - if (!stack.isEmpty() && slot.isEnabled()) { - net.minecraft.client.renderer.RenderHelper.enableStandardItemLighting(); - GlStateManager.pushMatrix(); - GlStateManager.scale(1, 1, 0); - GlStateManager.translate(slot.xPos, slot.yPos, 0); - RenderItem renderItem = Minecraft.getMinecraft().getRenderItem(); - renderItem.renderItemAndEffectIntoGUI(stack, 0, 0); - String text = stack.getCount() > 1? Integer.toString(stack.getCount()) : null; - - if (!stack.isEmpty()) - { - if (stack.getCount() != 1) - { - String s = text == null ? String.valueOf(stack.getCount()) : text; - GlStateManager.disableLighting(); - GlStateManager.disableBlend(); - fr.drawStringWithShadow(s, (float)(17 - fr.getStringWidth(s)), (float)9, 16777215); - GlStateManager.enableLighting(); - GlStateManager.enableBlend(); - } - - if (stack.getItem().showDurabilityBar(stack)) - { - GlStateManager.disableLighting(); - GlStateManager.disableTexture2D(); - GlStateManager.disableAlpha(); - GlStateManager.disableBlend(); - Tessellator tessellator = Tessellator.getInstance(); - BufferBuilder bufferbuilder = tessellator.getBuffer(); - double health = stack.getItem().getDurabilityForDisplay(stack); - int rgbfordisplay = stack.getItem().getRGBDurabilityForDisplay(stack); - int i = Math.round(13.0F - (float)health * 13.0F); - draw(bufferbuilder, 2, 13, 13, 2, 0, 0, 0, 255); - draw(bufferbuilder, 2, 13, i, 1, rgbfordisplay >> 16 & 255, rgbfordisplay >> 8 & 255, rgbfordisplay & 255, 255); - GlStateManager.enableBlend(); - GlStateManager.enableAlpha(); - GlStateManager.enableTexture2D(); - GlStateManager.enableLighting(); - } - - EntityPlayerSP entityplayersp = Minecraft.getMinecraft().player; - float f3 = entityplayersp == null ? 0.0F : entityplayersp.getCooldownTracker().getCooldown(stack.getItem(), Minecraft.getMinecraft().getRenderPartialTicks()); - - if (f3 > 0.0F) - { - GlStateManager.disableLighting(); - GlStateManager.disableTexture2D(); - Tessellator tessellator = Tessellator.getInstance(); - BufferBuilder bufferBuilder = tessellator.getBuffer(); - draw(bufferBuilder, 0, MathHelper.floor(16.0F * (1.0F - f3)), 16, MathHelper.ceil(16.0F * f3), 255, 255, 255, 127); - GlStateManager.enableTexture2D(); - GlStateManager.enableLighting(); - } - } - - GlStateManager.popMatrix(); - net.minecraft.client.renderer.RenderHelper.disableStandardItemLighting(); - } - } - - private static void draw(BufferBuilder renderer, int x, int y, int width, int height, int red, int green, int blue, int alpha) - { - renderer.begin(7, DefaultVertexFormats.POSITION_COLOR); - renderer.pos(x, y, 0.0D).color(red, green, blue, alpha).endVertex(); - renderer.pos((x), y + height, 0.0D).color(red, green, blue, alpha).endVertex(); - renderer.pos((x + width), y + height, 0.0D).color(red, green, blue, alpha).endVertex(); - renderer.pos((x + width), y, 0.0D).color(red, green, blue, alpha).endVertex(); - Tessellator.getInstance().draw(); - } - - public static void renderRect(float x, float y, float width, float height, float z, int color) { - renderGradientRect(x, y, width, height, z, color, color, false); - } - - public static void renderGradientRect(float x, float y, float width, float height, float z, int startColor, int endColor, boolean horizontal) { - float startAlpha = (float) (startColor >> 24 & 255) / 255.0F; - float startRed = (float) (startColor >> 16 & 255) / 255.0F; - float startGreen = (float) (startColor >> 8 & 255) / 255.0F; - float startBlue = (float) (startColor & 255) / 255.0F; - float endAlpha = (float) (endColor >> 24 & 255) / 255.0F; - float endRed = (float) (endColor >> 16 & 255) / 255.0F; - float endGreen = (float) (endColor >> 8 & 255) / 255.0F; - float endBlue = (float) (endColor & 255) / 255.0F; - GlStateManager.disableTexture2D(); - GlStateManager.enableBlend(); - GlStateManager.disableAlpha(); - GlStateManager.tryBlendFuncSeparate(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ZERO); - GlStateManager.shadeModel(GL11.GL_SMOOTH); - Tessellator tessellator = Tessellator.getInstance(); - BufferBuilder buffer = tessellator.getBuffer(); - buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR); - if (horizontal) { - buffer.pos(x + width, y, z).color(endRed, endGreen, endBlue, endAlpha).endVertex(); - buffer.pos(x, y, z).color(startRed, startGreen, startBlue, startAlpha).endVertex(); - buffer.pos(x, y + height, z).color(startRed, startGreen, startBlue, startAlpha).endVertex(); - buffer.pos(x + width, y + height, z).color(endRed, endGreen, endBlue, endAlpha).endVertex(); - tessellator.draw(); - } else { - buffer.pos(x + width, y, z).color(startRed, startGreen, startBlue, startAlpha).endVertex(); - buffer.pos(x, y, z).color(startRed, startGreen, startBlue, startAlpha).endVertex(); - buffer.pos(x, y + height, z).color(endRed, endGreen, endBlue, endAlpha).endVertex(); - buffer.pos(x + width, y + height, z).color(endRed, endGreen, endBlue, endAlpha).endVertex(); - tessellator.draw(); - } - GlStateManager.shadeModel(GL11.GL_FLAT); - GlStateManager.disableBlend(); - GlStateManager.enableAlpha(); - GlStateManager.enableTexture2D(); - } - - } diff --git a/src/main/java/gregtech/common/items/behaviors/ClipboardBehavior.java b/src/main/java/gregtech/common/items/behaviors/ClipboardBehavior.java index e1f1daf3d25..2231e5c415c 100644 --- a/src/main/java/gregtech/common/items/behaviors/ClipboardBehavior.java +++ b/src/main/java/gregtech/common/items/behaviors/ClipboardBehavior.java @@ -8,6 +8,7 @@ import gregtech.api.items.gui.PlayerInventoryHolder; import gregtech.api.items.metaitem.stats.IItemBehaviour; import gregtech.api.metatileentity.MetaTileEntityHolder; +import gregtech.api.util.RenderUtil; import gregtech.common.items.MetaItems; import gregtech.common.metatileentities.MetaTileEntityClipboard; import net.minecraft.block.Block; @@ -62,7 +63,7 @@ public ModularUI createMTEUI(PlayerInventoryHolder holder, EntityPlayer entityPl ModularUI.Builder builder = ModularUI.builder(GuiTextures.BACKGROUND, 170, 238); builder.image(18, 8, 130, 14, GuiTextures.CLIPBOARD_TEXT_BOX); - builder.widget(new SimpleTextWidget(20, 10, "", 0xFFFFFF, () -> getTitle(holder), false)); + builder.widget(new SimpleTextWidget(20, 10, "", 0xFFFFFF, () -> getTitle(holder)).setCenter(false)); for (int i = 0; i < 8; i++) { @@ -70,7 +71,7 @@ public ModularUI createMTEUI(PlayerInventoryHolder holder, EntityPlayer entityPl builder.widget(new ImageCycleButtonWidget(6, 37 + 20 * i, 15, 15, GuiTextures.CLIPBOARD_BUTTON, 4, () -> getButtonState(holder, finalI), (x) -> setButton(holder, finalI, x))); builder.image(22, 38 + 20 * i, 140, 12, GuiTextures.CLIPBOARD_TEXT_BOX); - builder.widget(new SimpleTextWidget(24, 40 + 20 * i, "", 0xFFFFFF, () -> getString(holder, finalI), false)); + builder.widget(new SimpleTextWidget(24, 40 + 20 * i, "", 0xFFFFFF, () -> getString(holder, finalI)).setCenter(false)); } builder.widget(new ClickButtonWidget(30, 200, 16, 16, "", (x) -> incrPageNum(holder, -1)) From 60b9c8f4b57e77479da6f8da4d0d3374b198fa2d Mon Sep 17 00:00:00 2001 From: bruberu <80226372+bruberu@users.noreply.github.com> Date: Sat, 21 Aug 2021 11:37:51 -0500 Subject: [PATCH 42/42] Fix remaining issues --- .../gregtech/api/gui/impl/FakeModularGui.java | 3 +- .../api/gui/widgets/ImageTextFieldWidget.java | 2 +- .../api/gui/widgets/SimpleTextWidget.java | 13 ------ .../api/gui/widgets/TextFieldWidget.java | 40 ------------------- .../items/behaviors/ClipboardBehavior.java | 8 ++-- .../MetaTileEntityClipboard.java | 5 +++ .../common/render/WrenchOverlayRenderer.java | 4 +- 7 files changed, 14 insertions(+), 61 deletions(-) diff --git a/src/main/java/gregtech/api/gui/impl/FakeModularGui.java b/src/main/java/gregtech/api/gui/impl/FakeModularGui.java index 33c7bb83fe2..5698981d9b0 100644 --- a/src/main/java/gregtech/api/gui/impl/FakeModularGui.java +++ b/src/main/java/gregtech/api/gui/impl/FakeModularGui.java @@ -18,6 +18,7 @@ import net.minecraftforge.fml.relauncher.SideOnly; import java.util.List; +import java.util.Optional; import static gregtech.api.gui.impl.ModularUIGui.*; @@ -42,7 +43,7 @@ public void updateScreen() { public void handleWidgetUpdate(int windowId, int widgetId, PacketBuffer updateData) { if (windowId == container.windowId) { - Widget widget = modularUI.guiWidgets.get(widgetId); + Widget widget = modularUI.guiWidgets.get(Optional.of(widgetId)); int updateId = updateData.readVarInt(); if (widget != null) { widget.readUpdateInfo(updateId, updateData); diff --git a/src/main/java/gregtech/api/gui/widgets/ImageTextFieldWidget.java b/src/main/java/gregtech/api/gui/widgets/ImageTextFieldWidget.java index 5b16a980ddf..b042e450846 100644 --- a/src/main/java/gregtech/api/gui/widgets/ImageTextFieldWidget.java +++ b/src/main/java/gregtech/api/gui/widgets/ImageTextFieldWidget.java @@ -27,7 +27,7 @@ public ImageTextFieldWidget(int xPosition, int yPosition, int width, int height, @Override public void drawInBackground(int mouseX, int mouseY, IRenderContext context) { - this.textureArea.drawHorizontalCutArea(this.getPosition().x - 2, this.getPosition().y - 2, this.getSize().width, this.getSize().height); + this.textureArea.drawHorizontalCutArea(this.getPosition().x - 2, this.getPosition().y, this.getSize().width, this.getSize().height); super.drawInBackground(mouseX, mouseY, context); } } diff --git a/src/main/java/gregtech/api/gui/widgets/SimpleTextWidget.java b/src/main/java/gregtech/api/gui/widgets/SimpleTextWidget.java index 543b7b22588..5bca44fa6e2 100644 --- a/src/main/java/gregtech/api/gui/widgets/SimpleTextWidget.java +++ b/src/main/java/gregtech/api/gui/widgets/SimpleTextWidget.java @@ -40,14 +40,6 @@ public SimpleTextWidget(int xPosition, int yPosition, String formatLocale, int c this.clientWidget = clientWidget; } - public SimpleTextWidget(int xPosition, int yPosition, String formatLocale, int color, Supplier textSupplier, boolean clientWidget) { - super(new Position(xPosition, yPosition), Size.ZERO); - this.color = color; - this.formatLocale = formatLocale; - this.textSupplier = textSupplier; - this.clientWidget = clientWidget; - } - public SimpleTextWidget(int xPosition, int yPosition, String formatLocale, Supplier textSupplier) { this(xPosition, yPosition, formatLocale, 0x404040, textSupplier, true); } @@ -62,11 +54,6 @@ public SimpleTextWidget setCenter(boolean isCentered) { return this; } - public SimpleTextWidget setShadow(boolean shadow) { - isShadow = shadow; - return this; - } - private void updateSize() { FontRenderer fontRenderer = Minecraft.getMinecraft().fontRenderer; int stringWidth = fontRenderer.getStringWidth(lastText); diff --git a/src/main/java/gregtech/api/gui/widgets/TextFieldWidget.java b/src/main/java/gregtech/api/gui/widgets/TextFieldWidget.java index efc270938af..1f68db69659 100644 --- a/src/main/java/gregtech/api/gui/widgets/TextFieldWidget.java +++ b/src/main/java/gregtech/api/gui/widgets/TextFieldWidget.java @@ -111,46 +111,6 @@ public String getCurrentString() { return this.currentString; } - public TextFieldWidget(int xPosition, int yPosition, int width, int height, IGuiTexture background, Supplier textSupplier, Consumer textResponder) { - super(new Position(xPosition, yPosition), new Size(width, height)); - if (isClientSide()) { - this.enableBackground = false; - FontRenderer fontRenderer = Minecraft.getMinecraft().fontRenderer; - this.textField = new GuiTextField(0, fontRenderer, xPosition + 1, yPosition + (height - fontRenderer.FONT_HEIGHT) / 2 + 1, width - 2, height); - this.textField.setCanLoseFocus(true); - this.textField.setEnableBackgroundDrawing(false); - this.textField.setMaxStringLength(maxStringLength); - this.textField.setGuiResponder(MCGuiUtil.createTextFieldResponder(this::onTextChanged)); - } - this.background = background; - this.textSupplier = textSupplier; - this.textResponder = textResponder; - } - - public TextFieldWidget setTextSupplier(Supplier textSupplier, boolean isClient) { - this.isClient = isClient; - this.textSupplier = textSupplier; - return this; - } - - public TextFieldWidget setTextResponder(Consumer textResponder, boolean isClient) { - this.isClient = isClient; - this.textResponder = textResponder; - return this; - } - - public TextFieldWidget setCurrentString(String currentString) { - this.currentString = currentString; - this.textField.setText(currentString); - return this; - } - - public String getCurrentString() { - if (isRemote()) { - return this.textField.getText(); - } - return this.currentString; - } @Override protected void onPositionUpdate() { diff --git a/src/main/java/gregtech/common/items/behaviors/ClipboardBehavior.java b/src/main/java/gregtech/common/items/behaviors/ClipboardBehavior.java index 2231e5c415c..e30b3e990f1 100644 --- a/src/main/java/gregtech/common/items/behaviors/ClipboardBehavior.java +++ b/src/main/java/gregtech/common/items/behaviors/ClipboardBehavior.java @@ -49,9 +49,9 @@ public ModularUI createUI(PlayerInventoryHolder holder, EntityPlayer entityPlaye } builder.widget(new ClickButtonWidget(30, 200, 16, 16, "", (x) -> incrPageNum(holder, -1)) - .setButtonTexture(GuiTextures.BUTTON_LEFT)); + .setButtonTexture(GuiTextures.BUTTON_LEFT).setShouldClientCallback(true)); builder.widget(new ClickButtonWidget(124, 200, 16, 16, "", (x) -> incrPageNum(holder, 1)) - .setButtonTexture(GuiTextures.BUTTON_RIGHT)); + .setButtonTexture(GuiTextures.BUTTON_RIGHT).setShouldClientCallback(true)); builder.widget(new SimpleTextWidget(85, 208, "", 0xFFFFFF, () -> (getPageNum(holder) + 1) + " / " + MAX_PAGES)); @@ -75,9 +75,9 @@ public ModularUI createMTEUI(PlayerInventoryHolder holder, EntityPlayer entityPl } builder.widget(new ClickButtonWidget(30, 200, 16, 16, "", (x) -> incrPageNum(holder, -1)) - .setButtonTexture(GuiTextures.BUTTON_LEFT)); + .setButtonTexture(GuiTextures.BUTTON_LEFT).setShouldClientCallback(true)); builder.widget(new ClickButtonWidget(124, 200, 16, 16, "", (x) -> incrPageNum(holder, 1)) - .setButtonTexture(GuiTextures.BUTTON_RIGHT)); + .setButtonTexture(GuiTextures.BUTTON_RIGHT).setShouldClientCallback(true)); builder.widget(new SimpleTextWidget(85, 208, "", 0xFFFFFF, () -> (getPageNum(holder) + 1) + " / " + MAX_PAGES)); diff --git a/src/main/java/gregtech/common/metatileentities/MetaTileEntityClipboard.java b/src/main/java/gregtech/common/metatileentities/MetaTileEntityClipboard.java index bc899d33161..d5175cb3827 100644 --- a/src/main/java/gregtech/common/metatileentities/MetaTileEntityClipboard.java +++ b/src/main/java/gregtech/common/metatileentities/MetaTileEntityClipboard.java @@ -413,4 +413,9 @@ public boolean canPlaceCoverOnSide(EnumFacing side) { public boolean canRenderMachineGrid() { return false; } + + @Override + public ItemStack getPickItem(CuboidRayTraceResult result, EntityPlayer player) { + return this.getClipboard(); + } } diff --git a/src/main/java/gregtech/common/render/WrenchOverlayRenderer.java b/src/main/java/gregtech/common/render/WrenchOverlayRenderer.java index d8814a371fb..eff34535b33 100644 --- a/src/main/java/gregtech/common/render/WrenchOverlayRenderer.java +++ b/src/main/java/gregtech/common/render/WrenchOverlayRenderer.java @@ -93,8 +93,8 @@ public static boolean useGridForRayTraceResult(RayTraceResult result) { } public static boolean shouldDrawOverlayForItem(ItemStack itemStack, TileEntity tileEntity) { - if (tileEntity instanceof ICoverable) { - if(!((ICoverable) tileEntity).canRenderMachineGrid()) + if (tileEntity instanceof MetaTileEntityHolder) { + if(!((MetaTileEntityHolder) tileEntity).getMetaTileEntity().canRenderMachineGrid()) return false; }