From 4fde73918f97179d3aca330764e96004e8f629b4 Mon Sep 17 00:00:00 2001 From: mikerooni <139889766+mikerooni@users.noreply.github.com> Date: Mon, 24 Jul 2023 07:41:19 +0200 Subject: [PATCH] Robot arm cover (#192) * feat: basic UI for robot arm cover * feat: adjust item filter display for better UI in robot arm * fix: robot arm & conveyor UI fixes * refactor: extract stack size inputs from robot arm & conveyor covers * feat: icon buttons for robot arm & conveyor cover icons for IO modes by @Irgendwer01 * refactor: move source & target matching up into ConveyorCover.update() * feat: implement robot arm logic Ported from 1.12 * fix: robot arm cover syncs correctly & respects global transfer limit * feat: add tooltips to conveyor & robot arm selector buttons * feat: update keep_exact.png to better reflect its transfer mode * clean up --------- Co-authored-by: KilaBash --- .../gtceu/api/capability/recipe/IO.java | 19 +- .../gtceu/api/cover/filter/ItemFilter.java | 43 +++ .../api/cover/filter/SimpleItemFilter.java | 79 ++++-- .../gtceu/api/cover/filter/TagItemFilter.java | 5 + .../widget/CoverContainerConfigurator.java | 6 + .../gtceu/api/gui/widget/IntInputWidget.java | 150 +++++++++++ .../renderer/cover/RobotArmCoverRenderer.java | 56 ++++ .../gtceu/common/cover/ConveyorCover.java | 248 ++++++++++++++---- .../gtceu/common/cover/RobotArmCover.java | 192 ++++++++++++++ .../gtceu/common/cover/data/TransferMode.java | 20 ++ .../gtceu/common/data/GTCovers.java | 1 + .../gtceu/common/data/GTItems.java | 16 +- .../gtceu/common/data/GTMachines.java | 2 +- .../gtceu/data/lang/LangHandler.java | 6 + .../gtceu/textures/gui/icon/io_mode/both.png | Bin 0 -> 795 bytes .../textures/gui/icon/io_mode/export.png | Bin 0 -> 711 bytes .../textures/gui/icon/io_mode/import.png | Bin 0 -> 704 bytes .../gtceu/textures/gui/icon/io_mode/none.png | Bin 0 -> 751 bytes .../gui/icon/transfer_mode/keep_exact.png | Bin 0 -> 637 bytes .../gui/icon/transfer_mode/transfer_any.png | Bin 0 -> 600 bytes .../gui/icon/transfer_mode/transfer_exact.png | Bin 0 -> 634 bytes .../resources/assets/gtceu/lang/en_ud.json | 5 + .../resources/assets/gtceu/lang/en_us.json | 5 + .../resources/assets/gtceu/lang/en_ud.json | 5 + .../resources/assets/gtceu/lang/en_us.json | 5 + settings.gradle | 2 +- 26 files changed, 791 insertions(+), 74 deletions(-) create mode 100644 common/src/main/java/com/gregtechceu/gtceu/api/gui/widget/IntInputWidget.java create mode 100644 common/src/main/java/com/gregtechceu/gtceu/client/renderer/cover/RobotArmCoverRenderer.java create mode 100644 common/src/main/java/com/gregtechceu/gtceu/common/cover/RobotArmCover.java create mode 100644 common/src/main/java/com/gregtechceu/gtceu/common/cover/data/TransferMode.java create mode 100644 common/src/main/resources/assets/gtceu/textures/gui/icon/io_mode/both.png create mode 100644 common/src/main/resources/assets/gtceu/textures/gui/icon/io_mode/export.png create mode 100644 common/src/main/resources/assets/gtceu/textures/gui/icon/io_mode/import.png create mode 100644 common/src/main/resources/assets/gtceu/textures/gui/icon/io_mode/none.png create mode 100644 common/src/main/resources/assets/gtceu/textures/gui/icon/transfer_mode/keep_exact.png create mode 100644 common/src/main/resources/assets/gtceu/textures/gui/icon/transfer_mode/transfer_any.png create mode 100644 common/src/main/resources/assets/gtceu/textures/gui/icon/transfer_mode/transfer_exact.png diff --git a/common/src/main/java/com/gregtechceu/gtceu/api/capability/recipe/IO.java b/common/src/main/java/com/gregtechceu/gtceu/api/capability/recipe/IO.java index d9e6cd0659..bca5ef3e7d 100644 --- a/common/src/main/java/com/gregtechceu/gtceu/api/capability/recipe/IO.java +++ b/common/src/main/java/com/gregtechceu/gtceu/api/capability/recipe/IO.java @@ -1,13 +1,24 @@ package com.gregtechceu.gtceu.api.capability.recipe; +import com.lowdragmc.lowdraglib.gui.texture.IGuiTexture; +import com.lowdragmc.lowdraglib.gui.texture.ResourceTexture; + /** * The capability can be input or output or both */ public enum IO { - IN, - OUT, - BOTH, - NONE; + IN("gtceu.io.import", "import"), + OUT("gtceu.io.export", "export"), + BOTH("gtceu.io.both", "both"), + NONE("gtceu.io.none", "none"); + + public final String localeName; + public final IGuiTexture icon; + + IO(String localeName, String textureName) { + this.localeName = localeName; + this.icon = new ResourceTexture("gtceu:textures/gui/icon/io_mode/" + textureName + ".png"); + } public boolean support(IO io) { if (io == this) return true; diff --git a/common/src/main/java/com/gregtechceu/gtceu/api/cover/filter/ItemFilter.java b/common/src/main/java/com/gregtechceu/gtceu/api/cover/filter/ItemFilter.java index 9ef660a321..ffbbf42747 100644 --- a/common/src/main/java/com/gregtechceu/gtceu/api/cover/filter/ItemFilter.java +++ b/common/src/main/java/com/gregtechceu/gtceu/api/cover/filter/ItemFilter.java @@ -1,10 +1,14 @@ package com.gregtechceu.gtceu.api.cover.filter; +import com.lowdragmc.lowdraglib.gui.widget.WidgetGroup; +import net.minecraft.nbt.CompoundTag; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; +import org.apache.commons.lang3.NotImplementedException; import java.util.HashMap; import java.util.Map; +import java.util.function.Consumer; import java.util.function.Function; /** @@ -20,4 +24,43 @@ static ItemFilter loadFilter(ItemStack itemStack) { return FILTERS.get(itemStack.getItem()).apply(itemStack); } + /** + * Retrieves the configured item count for the supplied item. + * + * @return The amount configured for the supplied item stack.
+ * If the stack is not matched by this filter, 0 is returned instead. + */ + int testItemCount(ItemStack itemStack); + + default boolean isBlackList() { + return false; + } + + + /** + * An empty item filter that allows all items.
+ * ONLY TO BE USED FOR ITEM MATCHING! All other functionality will throw an exception. + */ + ItemFilter EMPTY = new ItemFilter() { + @Override public int testItemCount(ItemStack itemStack) { + return Integer.MAX_VALUE; + } + + @Override public boolean test(ItemStack itemStack) { + return true; + } + + @Override public WidgetGroup openConfigurator(int x, int y) { + throw new NotImplementedException("Not available for empty item filter"); + } + + @Override public CompoundTag saveFilter() { + throw new NotImplementedException("Not available for empty item filter"); + } + + @Override public void setOnUpdated(Consumer onUpdated) { + throw new NotImplementedException("Not available for empty item filter"); + } + }; + } diff --git a/common/src/main/java/com/gregtechceu/gtceu/api/cover/filter/SimpleItemFilter.java b/common/src/main/java/com/gregtechceu/gtceu/api/cover/filter/SimpleItemFilter.java index 678db41e9e..5eaaf22a54 100644 --- a/common/src/main/java/com/gregtechceu/gtceu/api/cover/filter/SimpleItemFilter.java +++ b/common/src/main/java/com/gregtechceu/gtceu/api/cover/filter/SimpleItemFilter.java @@ -26,7 +26,6 @@ @ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault public class SimpleItemFilter implements ItemFilter { - @Getter protected boolean isBlackList; @Getter protected boolean ignoreNbt; @@ -35,8 +34,13 @@ public class SimpleItemFilter implements ItemFilter { @Setter protected Consumer onUpdated; + @Getter + protected int maxStackSize; + + protected SimpleItemFilter() { Arrays.fill(matches, ItemStack.EMPTY); + maxStackSize = 1; } public static SimpleItemFilter loadFilter(ItemStack itemStack) { @@ -70,9 +74,19 @@ public CompoundTag saveFilter() { public void setBlackList(boolean blackList) { isBlackList = blackList; + if (blackList) { + setMaxStackSize(1); + } else { + setMaxStackSize(Integer.MAX_VALUE); + } onUpdated.accept(this); } + @Override + public boolean isBlackList() { + return isBlackList; + } + public void setIgnoreNbt(boolean ingoreNbt) { this.ignoreNbt = ingoreNbt; onUpdated.accept(this); @@ -80,12 +94,25 @@ public void setIgnoreNbt(boolean ingoreNbt) { public WidgetGroup openConfigurator(int x, int y) { WidgetGroup group = new WidgetGroup(x, y, 18 * 3 + 25, 18 * 3); // 80 55 + var filterSlots = new PhantomSlotWidget[9]; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { final int index = i * 3 + j; var handler = new ItemStackTransfer(matches[index]); - var slot = new PhantomSlotWidget(handler, 0, i * 18, j * 18); - slot.setMaxStackSize(1); + filterSlots[i] = new PhantomSlotWidget(handler, 0, i * 18, j * 18) { + @Override + public void updateScreen() { + super.updateScreen(); + setMaxStackSize(maxStackSize); + } + + @Override + public void detectAndSendChanges() { + super.detectAndSendChanges(); + setMaxStackSize(maxStackSize); + } + }; + var slot = filterSlots[i]; slot.setChangeListener(() -> { matches[index] = handler.getStackInSlot(0); onUpdated.accept(this); @@ -93,26 +120,48 @@ public WidgetGroup openConfigurator(int x, int y) { group.addWidget(slot); } } - group.addWidget(new ToggleButtonWidget(18 * 3 + 5, 0, 20, 20, + group.addWidget(new ToggleButtonWidget(18 * 3 + 2, 9, 18, 18, GuiTextures.BUTTON_BLACKLIST, this::isBlackList, this::setBlackList)); - group.addWidget(new ToggleButtonWidget(18 * 3 + 5, 20, 20, 20, + group.addWidget(new ToggleButtonWidget(18 * 3 + 2, (18) + 9, 18, 18, GuiTextures.BUTTON_FILTER_NBT, this::isIgnoreNbt, this::setIgnoreNbt)); return group; } @Override public boolean test(ItemStack itemStack) { - boolean found = false; - for (var match : matches) { - if (ignoreNbt) { - found = match.sameItem(itemStack); - } else { - found = ItemTransferHelper.canItemStacksStack(match, itemStack); - } - if (found) { - break; + return testItemCount(itemStack) > 0; + } + + @Override + public int testItemCount(ItemStack itemStack) { + int totalItemCount = getTotalConfiguredItemCount(itemStack); + + if (isBlackList) { + return (totalItemCount > 0) ? 0 : Integer.MAX_VALUE; + } + + return totalItemCount; + } + + public int getTotalConfiguredItemCount(ItemStack itemStack) { + int totalCount = 0; + + for (var candidate : matches) { + if (ignoreNbt && candidate.sameItem(itemStack)) { + totalCount += candidate.getCount(); + } else if (ItemTransferHelper.canItemStacksStack(candidate, itemStack)) { + totalCount += candidate.getCount(); } } - return isBlackList != found; + + return totalCount; + } + + public void setMaxStackSize(int maxStackSize) { + this.maxStackSize = maxStackSize; + + for (ItemStack match : matches) { + match.setCount(Math.min(match.getCount(), maxStackSize)); + } } } diff --git a/common/src/main/java/com/gregtechceu/gtceu/api/cover/filter/TagItemFilter.java b/common/src/main/java/com/gregtechceu/gtceu/api/cover/filter/TagItemFilter.java index 6b144bbc2d..eb40865283 100644 --- a/common/src/main/java/com/gregtechceu/gtceu/api/cover/filter/TagItemFilter.java +++ b/common/src/main/java/com/gregtechceu/gtceu/api/cover/filter/TagItemFilter.java @@ -51,4 +51,9 @@ public boolean test(ItemStack itemStack) { cache.put(itemStack.getItem(), false); return false; } + + @Override + public int testItemCount(ItemStack itemStack) { + return test(itemStack) ? Integer.MAX_VALUE : 0; + } } diff --git a/common/src/main/java/com/gregtechceu/gtceu/api/gui/widget/CoverContainerConfigurator.java b/common/src/main/java/com/gregtechceu/gtceu/api/gui/widget/CoverContainerConfigurator.java index 75192f3f24..8e723c0f8e 100644 --- a/common/src/main/java/com/gregtechceu/gtceu/api/gui/widget/CoverContainerConfigurator.java +++ b/common/src/main/java/com/gregtechceu/gtceu/api/gui/widget/CoverContainerConfigurator.java @@ -24,7 +24,9 @@ import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.server.level.ServerPlayer; +import net.minecraft.util.Mth; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.phys.Vec2; import javax.annotation.Nullable; import java.util.List; @@ -92,6 +94,10 @@ public void apply(boolean isTESR, RenderType layer) { .setBackgroundTexture(new GuiTextureGroup(GuiTextures.SLOT, GuiTextures.FILTER_SLOT_OVERLAY))); slotWidget.setVisible(false); slotWidget.setActive(false); + + + var playerRotation = gui.entityPlayer.getRotationVector(); + sceneWidget.setCameraYawAndPitch(playerRotation.x, playerRotation.y); } private void coverRemoved() { diff --git a/common/src/main/java/com/gregtechceu/gtceu/api/gui/widget/IntInputWidget.java b/common/src/main/java/com/gregtechceu/gtceu/api/gui/widget/IntInputWidget.java new file mode 100644 index 0000000000..b5afe1e915 --- /dev/null +++ b/common/src/main/java/com/gregtechceu/gtceu/api/gui/widget/IntInputWidget.java @@ -0,0 +1,150 @@ +package com.gregtechceu.gtceu.api.gui.widget; + +import com.gregtechceu.gtceu.api.gui.GuiTextures; +import com.gregtechceu.gtceu.utils.GTUtil; +import com.lowdragmc.lowdraglib.LDLib; +import com.lowdragmc.lowdraglib.gui.texture.GuiTextureGroup; +import com.lowdragmc.lowdraglib.gui.texture.IGuiTexture; +import com.lowdragmc.lowdraglib.gui.texture.TextTexture; +import com.lowdragmc.lowdraglib.gui.util.ClickData; +import com.lowdragmc.lowdraglib.gui.widget.ButtonWidget; +import com.lowdragmc.lowdraglib.gui.widget.TextFieldWidget; +import com.lowdragmc.lowdraglib.gui.widget.WidgetGroup; +import com.lowdragmc.lowdraglib.utils.Position; +import com.lowdragmc.lowdraglib.utils.Size; +import lombok.Getter; +import net.minecraft.client.Minecraft; +import net.minecraft.util.Mth; + +import java.util.function.Consumer; + +/** + * A widget containing an integer input field, as well as adjacent buttons for increasing or decreasing the value. + * + *

+ * The buttons' change amount can be altered with Ctrl, Shift, or both.
+ * The input is limited by a minimum and maximum value. + *

+ */ +public class IntInputWidget extends WidgetGroup { + + @Getter + private int value; + @Getter + private int min = 0; + @Getter + private int max = Integer.MAX_VALUE; + + private final Consumer onChanged; + + private TextFieldWidget textField; + + public IntInputWidget(int initialValue, Consumer onChanged) { + this(0, 0, 100, 20, initialValue, onChanged); + } + + public IntInputWidget(Position position, int initialValue, Consumer onChanged) { + this(position, new Size(100, 20), initialValue, onChanged); + } + + public IntInputWidget(Position position, Size size, int initialValue, Consumer onChanged) { + this(position.x, position.y, size.width, size.height, initialValue, onChanged); + } + + public IntInputWidget(int x, int y, int width, int height, int initialValue, Consumer onChanged) { + super(x, y, width, height); + + this.value = initialValue; + this.onChanged = onChanged; + + buildUI(); + } + + private void buildUI() { + int buttonWidth = Mth.clamp(this.getSize().width / 5, 15, 40); + int textFieldWidth = this.getSize().width - (2 * buttonWidth) - 4; + + this.addWidget(new ButtonWidget(0, 0, buttonWidth, 20, + new GuiTextureGroup(GuiTextures.VANILLA_BUTTON, getButtonTexture("-", buttonWidth)), + this::decrease + ).setHoverTooltips("gui.widget.incrementButton.default_tooltip")); + + + this.textField = new TextFieldWidget(buttonWidth + 2, 0, textFieldWidth, 20, + () -> String.valueOf(value), + stringValue -> this.setValue(Mth.clamp(Integer.parseInt(stringValue), min, max)) + ); + this.updateTextFieldRange(); + this.addWidget(this.textField); + + + this.addWidget(new ButtonWidget(buttonWidth + textFieldWidth + 4, 0, buttonWidth, 20, + new GuiTextureGroup(GuiTextures.VANILLA_BUTTON, getButtonTexture("+", buttonWidth)), + this::increase + ).setHoverTooltips("gui.widget.incrementButton.default_tooltip")); + } + + private IGuiTexture getButtonTexture(String prefix, int buttonWidth) { + var texture = new TextTexture(prefix + "1"); + + if (!LDLib.isRemote()) { + return texture; + } + + // Dynamic text is only necessary on the remote side: + + int maxTextWidth = buttonWidth - 4; + + texture.setSupplier(() -> { + int amount = GTUtil.isCtrlDown() ? GTUtil.isShiftDown() ? 512 : 64 : GTUtil.isShiftDown() ? 8 : 1; + String text = prefix + amount; + + texture.scale(maxTextWidth / (float) Math.max(Minecraft.getInstance().font.width(text), maxTextWidth)); + + return text; + }); + + return texture; + } + + private void increase(ClickData cd) { + this.changeValue(cd, 1); + } + + private void decrease(ClickData cd) { + this.changeValue(cd, -1); + } + + private void changeValue(ClickData cd, int multiplier) { + if (!cd.isRemote) { + int amount = cd.isCtrlClick ? cd.isShiftClick ? 512 : 64 : cd.isShiftClick ? 8 : 1; + this.setValue(Mth.clamp(value + (multiplier * amount), min, max)); + } + } + + public IntInputWidget setMin(int min) { + this.min = min; + updateTextFieldRange(); + + return this; + } + + public IntInputWidget setMax(int max) { + this.max = max; + updateTextFieldRange(); + + return this; + } + + public IntInputWidget setValue(int value) { + this.value = value; + onChanged.accept(value); + + return this; + } + + private void updateTextFieldRange() { + this.textField.setNumbersOnly(min, max); + this.setValue(Mth.clamp(this.value, min, max)); + } +} diff --git a/common/src/main/java/com/gregtechceu/gtceu/client/renderer/cover/RobotArmCoverRenderer.java b/common/src/main/java/com/gregtechceu/gtceu/client/renderer/cover/RobotArmCoverRenderer.java new file mode 100644 index 0000000000..70fbd3011c --- /dev/null +++ b/common/src/main/java/com/gregtechceu/gtceu/client/renderer/cover/RobotArmCoverRenderer.java @@ -0,0 +1,56 @@ +package com.gregtechceu.gtceu.client.renderer.cover; + + +import com.gregtechceu.gtceu.GTCEu; +import com.gregtechceu.gtceu.api.capability.recipe.IO; +import com.gregtechceu.gtceu.api.cover.CoverBehavior; +import com.gregtechceu.gtceu.common.cover.RobotArmCover; +import com.lowdragmc.lowdraglib.LDLib; +import com.lowdragmc.lowdraglib.client.bakedpipeline.FaceQuad; +import com.lowdragmc.lowdraglib.client.model.ModelFactory; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.client.renderer.block.model.BakedQuad; +import net.minecraft.client.renderer.texture.TextureAtlas; +import net.minecraft.client.resources.model.ModelState; +import net.minecraft.core.Direction; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.RandomSource; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; +import java.util.function.Consumer; + +public class RobotArmCoverRenderer implements ICoverRenderer { + + public final static RobotArmCoverRenderer INSTANCE = new RobotArmCoverRenderer(); + public final static ResourceLocation ARM_OVERLAY = GTCEu.id("block/cover/overlay_arm"); + public final static ResourceLocation ARM_OVERLAY_OUT = GTCEu.id("block/cover/overlay_arm_emissive"); + public final static ResourceLocation AR_OVERLAY_IN = GTCEu.id("block/cover/overlay_arm_inverted_emissive"); + + protected RobotArmCoverRenderer() { + if (LDLib.isClient()) { + registerEvent(); + } + } + + @Override + @Environment(EnvType.CLIENT) + public void renderCover(List quads, @Nullable Direction side, RandomSource rand, @NotNull CoverBehavior coverBehavior, @Nullable Direction modelFacing, ModelState modelState) { + if (side == coverBehavior.attachedSide && coverBehavior instanceof RobotArmCover robotArm && modelFacing != null) { + quads.add(FaceQuad.bakeFace(modelFacing, ModelFactory.getBlockSprite(ARM_OVERLAY), modelState)); + quads.add(FaceQuad.bakeFace(modelFacing, ModelFactory.getBlockSprite(robotArm.getIo() == IO.OUT ? ARM_OVERLAY_OUT : AR_OVERLAY_IN), modelState, -1, 15)); + } + } + + @Override + @Environment(EnvType.CLIENT) + public void onPrepareTextureAtlas(ResourceLocation atlasName, Consumer register) { + if (atlasName.equals(TextureAtlas.LOCATION_BLOCKS)) { + register.accept(ARM_OVERLAY); + register.accept(AR_OVERLAY_IN); + register.accept(ARM_OVERLAY_OUT); + } + } +} diff --git a/common/src/main/java/com/gregtechceu/gtceu/common/cover/ConveyorCover.java b/common/src/main/java/com/gregtechceu/gtceu/common/cover/ConveyorCover.java index f47716613c..7281fb90b0 100644 --- a/common/src/main/java/com/gregtechceu/gtceu/common/cover/ConveyorCover.java +++ b/common/src/main/java/com/gregtechceu/gtceu/common/cover/ConveyorCover.java @@ -9,11 +9,12 @@ import com.gregtechceu.gtceu.api.cover.IUICover; import com.gregtechceu.gtceu.api.cover.filter.ItemFilter; import com.gregtechceu.gtceu.api.gui.GuiTextures; +import com.gregtechceu.gtceu.api.gui.widget.IntInputWidget; import com.gregtechceu.gtceu.api.machine.TickableSubscription; import com.gregtechceu.gtceu.api.syncdata.RequireRerender; +import com.gregtechceu.gtceu.utils.ItemStackHashStrategy; import com.lowdragmc.lowdraglib.gui.texture.GuiTextureGroup; import com.lowdragmc.lowdraglib.gui.texture.ResourceBorderTexture; -import com.lowdragmc.lowdraglib.gui.texture.TextTexture; import com.lowdragmc.lowdraglib.gui.widget.*; import com.lowdragmc.lowdraglib.misc.ItemStackTransfer; import com.lowdragmc.lowdraglib.side.item.IItemTransfer; @@ -22,20 +23,25 @@ import com.lowdragmc.lowdraglib.syncdata.annotation.Persisted; import com.lowdragmc.lowdraglib.syncdata.field.ManagedFieldHolder; import com.lowdragmc.lowdraglib.utils.LocalizationUtils; +import it.unimi.dsi.fastutil.ints.IntArrayList; +import it.unimi.dsi.fastutil.ints.IntList; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenCustomHashMap; +import lombok.AllArgsConstructor; import lombok.Getter; import net.minecraft.MethodsReturnNonnullByDefault; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.server.TickTask; import net.minecraft.server.level.ServerLevel; -import net.minecraft.util.Mth; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.Block; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import javax.annotation.Nonnull; import javax.annotation.ParametersAreNonnullByDefault; import java.util.List; -import java.util.function.Predicate; +import java.util.Map; /** * @author KilaBash @@ -57,9 +63,10 @@ public class ConveyorCover extends CoverBehavior implements IUICover, IControlla @Persisted @DescSynced @Getter protected ItemStack filterItem; @Nullable - private ItemFilter filterHandler; + protected ItemFilter filterHandler; protected int itemsLeftToTransferLastSecond; private TickableSubscription subscription; + private Widget ioModeSwitch; public ConveyorCover(CoverDefinition definition, ICoverable coverHolder, Direction attachedSide, int tier) { super(definition, coverHolder, attachedSide); @@ -125,10 +132,10 @@ public List getAdditionalDrops() { //***** Transfer Logic *****// ////////////////////////////////////// - public Predicate getFilterHandler() { + public ItemFilter getFilterHandler() { if (filterHandler == null) { if (filterItem.isEmpty()) { - return itemStack -> true; + return ItemFilter.EMPTY; } else { filterHandler = ItemFilter.loadFilter(filterItem); } @@ -169,7 +176,11 @@ private void update() { var itemHandler = ItemTransferHelper.getItemTransfer(level, pos.relative(attachedSide), attachedSide.getOpposite()); var myItemHandler = ItemTransferHelper.getItemTransfer(level, pos, attachedSide); if (itemHandler != null && myItemHandler != null) { - int totalTransferred = doTransferItems(itemHandler, myItemHandler, itemsLeftToTransferLastSecond); + int totalTransferred = switch (io) { + case IN -> doTransferItems(itemHandler, myItemHandler, itemsLeftToTransferLastSecond); + case OUT -> doTransferItems(myItemHandler, itemHandler, itemsLeftToTransferLastSecond); + default -> 0; + }; this.itemsLeftToTransferLastSecond -= totalTransferred; } } @@ -180,17 +191,8 @@ private void update() { } } - protected int doTransferItems(IItemTransfer itemHandler, IItemTransfer myItemHandler, int maxTransferAmount) { - return doTransferItemsAny(itemHandler, myItemHandler, maxTransferAmount); - } - - protected int doTransferItemsAny(IItemTransfer itemHandler, IItemTransfer myItemHandler, int maxTransferAmount) { - if (io == IO.IN) { - return moveInventoryItems(itemHandler, myItemHandler, maxTransferAmount); - } else if (io == IO.OUT) { - return moveInventoryItems(myItemHandler, itemHandler, maxTransferAmount); - } - return 0; + protected int doTransferItems(IItemTransfer sourceInventory, IItemTransfer targetInventory, int maxTransferAmount) { + return moveInventoryItems(sourceInventory, targetInventory, maxTransferAmount); } protected int moveInventoryItems(IItemTransfer sourceInventory, IItemTransfer targetInventory, int maxTransferAmount) { @@ -223,6 +225,149 @@ protected int moveInventoryItems(IItemTransfer sourceInventory, IItemTransfer ta return maxTransferAmount - itemsLeftToTransfer; } + protected static boolean moveInventoryItemsExact(IItemTransfer sourceInventory, IItemTransfer targetInventory, TypeItemInfo itemInfo) { + //first, compute how much can we extract in reality from the machine, + //because totalCount is based on what getStackInSlot returns, which may differ from what + //extractItem() will return + ItemStack resultStack = itemInfo.itemStack.copy(); + int totalExtractedCount = 0; + int itemsLeftToExtract = itemInfo.totalCount; + + for (int i = 0; i < itemInfo.slots.size(); i++) { + int slotIndex = itemInfo.slots.get(i); + ItemStack extractedStack = sourceInventory.extractItem(slotIndex, itemsLeftToExtract, true); + if (!extractedStack.isEmpty() && + ItemStack.isSame(resultStack, extractedStack) && + ItemStack.tagMatches(resultStack, extractedStack)) { + totalExtractedCount += extractedStack.getCount(); + itemsLeftToExtract -= extractedStack.getCount(); + } + if (itemsLeftToExtract == 0) { + break; + } + } + //if amount of items extracted is not equal to the amount of items we + //wanted to extract, abort item extraction + if (totalExtractedCount != itemInfo.totalCount) { + return false; + } + //adjust size of the result stack accordingly + resultStack.setCount(totalExtractedCount); + + //now, see how much we can insert into destination inventory + //if we can't insert as much as itemInfo requires, and remainder is empty, abort, abort + ItemStack remainder = ItemTransferHelper.insertItem(targetInventory, resultStack, true); + if (!remainder.isEmpty()) { + return false; + } + + //otherwise, perform real insertion and then remove items from the source inventory + ItemTransferHelper.insertItem(targetInventory, resultStack, false); + + //perform real extraction of the items from the source inventory now + itemsLeftToExtract = itemInfo.totalCount; + for (int i = 0; i < itemInfo.slots.size(); i++) { + int slotIndex = itemInfo.slots.get(i); + ItemStack extractedStack = sourceInventory.extractItem(slotIndex, itemsLeftToExtract, false); + if (!extractedStack.isEmpty() && + ItemStack.isSame(resultStack, extractedStack) && + ItemStack.tagMatches(resultStack, extractedStack)) { + itemsLeftToExtract -= extractedStack.getCount(); + } + if (itemsLeftToExtract == 0) { + break; + } + } + return true; + } + + protected int moveInventoryItems(IItemTransfer sourceInventory, IItemTransfer targetInventory, Map itemInfos, int maxTransferAmount) { + int itemsLeftToTransfer = maxTransferAmount; + for (int i = 0; i < sourceInventory.getSlots(); i++) { + ItemStack itemStack = sourceInventory.getStackInSlot(i); + if (itemStack.isEmpty() || !getFilterHandler().test(itemStack) || !itemInfos.containsKey(itemStack)) { + continue; + } + + GroupItemInfo itemInfo = itemInfos.get(itemStack); + + ItemStack extractedStack = sourceInventory.extractItem(i, Math.min(itemInfo.totalCount, itemsLeftToTransfer), true); + + ItemStack remainderStack = ItemTransferHelper.insertItem(targetInventory, extractedStack, true); + int amountToInsert = extractedStack.getCount() - remainderStack.getCount(); + + if (amountToInsert > 0) { + extractedStack = sourceInventory.extractItem(i, amountToInsert, false); + + if (!extractedStack.isEmpty()) { + + ItemTransferHelper.insertItem(targetInventory, extractedStack, false); + itemsLeftToTransfer -= extractedStack.getCount(); + itemInfo.totalCount -= extractedStack.getCount(); + + if (itemInfo.totalCount == 0) { + itemInfos.remove(itemStack); + if (itemInfos.isEmpty()) { + break; + } + } + if (itemsLeftToTransfer == 0) { + break; + } + } + } + } + return maxTransferAmount - itemsLeftToTransfer; + } + + @Nonnull + protected Map countInventoryItemsByType(@Nonnull IItemTransfer inventory) { + Map result = new Object2ObjectOpenCustomHashMap<>(ItemStackHashStrategy.comparingAllButCount()); + + for (int srcIndex = 0; srcIndex < inventory.getSlots(); srcIndex++) { + ItemStack itemStack = inventory.getStackInSlot(srcIndex); + if (itemStack.isEmpty() || !getFilterHandler().test(itemStack)) { + continue; + } + + var itemInfo = result.computeIfAbsent(itemStack, s -> new TypeItemInfo(s, new IntArrayList(), 0)); + + itemInfo.totalCount += itemStack.getCount(); + itemInfo.slots.add(srcIndex); + } + + return result; + } + + @Nonnull + protected Map countInventoryItemsByMatchSlot(@Nonnull IItemTransfer inventory) { + Map result = new Object2ObjectOpenCustomHashMap<>(ItemStackHashStrategy.comparingAllButCount()); + for (int srcIndex = 0; srcIndex < inventory.getSlots(); srcIndex++) { + ItemStack itemStack = inventory.getStackInSlot(srcIndex); + if (itemStack.isEmpty() || !getFilterHandler().test(itemStack)) { + continue; + } + + var itemInfo = result.computeIfAbsent(itemStack, s -> new GroupItemInfo(s, 0)); + + itemInfo.totalCount += itemStack.getCount(); + } + return result; + } + + @AllArgsConstructor + protected static class TypeItemInfo { + public final ItemStack itemStack; + public final IntList slots; + public int totalCount; + } + + @AllArgsConstructor + protected static class GroupItemInfo { + public final ItemStack itemStack; + public int totalCount; + } + ////////////////////////////////////// //*********** GUI ***********// @@ -230,39 +375,35 @@ protected int moveInventoryItems(IItemTransfer sourceInventory, IItemTransfer ta @Override public Widget createUIWidget() { final var group = new WidgetGroup(0, 0, 176, 135); + var filterContainer = new ItemStackTransfer(filterItem); filterContainer.setFilter(itemStack -> ItemFilter.FILTERS.containsKey(itemStack.getItem())); var filterGroup = new WidgetGroup(0, 70, 176, 60); if (!filterItem.isEmpty()) { filterHandler = ItemFilter.loadFilter(filterItem); - filterGroup.addWidget(filterHandler.openConfigurator((176 - 80) / 2, (60 - 55) / 2)); + filterGroup.addWidget(filterHandler.openConfigurator(10, 0)); + configureFilterHandler(); } - group.addWidget(new LabelWidget(10, 5, LocalizationUtils.format("cover.conveyor.title", GTValues.VN[tier]))); - group.addWidget(new ButtonWidget(10, 20, 30, 20, - new GuiTextureGroup(GuiTextures.VANILLA_BUTTON, new TextTexture("-1")), cd -> { - if (!cd.isRemote) { - int amount = cd.isCtrlClick ? cd.isShiftClick ? 512 : 64 : cd.isShiftClick ? 8 : 1; - setTransferRate(Mth.clamp(getTransferRate() - amount, 1, maxItemTransferRate)); - } - }).setHoverTooltips("gui.widget.incrementButton.default_tooltip")); - group.addWidget(new ButtonWidget(136, 20, 30, 20, - new GuiTextureGroup(GuiTextures.VANILLA_BUTTON, new TextTexture("+1")), cd -> { - if (!cd.isRemote) { - int amount = cd.isCtrlClick ? cd.isShiftClick ? 512 : 64 : cd.isShiftClick ? 8 : 1; - setTransferRate(Mth.clamp(getTransferRate() + amount, 1, maxItemTransferRate)); - } - }).setHoverTooltips("gui.widget.incrementButton.default_tooltip")); - group.addWidget(new TextFieldWidget(42, 20, 92, 20, () -> String.valueOf(transferRate), val -> setTransferRate(Mth.clamp(Integer.parseInt(val), 1, maxItemTransferRate))).setNumbersOnly(1, maxItemTransferRate)); - group.addWidget(new SwitchWidget(10, 45, 75, 20, (clickData, value) -> { - if (!clickData.isRemote) { - setIo(value ? IO.IN : IO.OUT); - } - }) + + group.addWidget(new LabelWidget(10, 5, LocalizationUtils.format(getUITitle(), GTValues.VN[tier]))); + + group.addWidget(new IntInputWidget(10, 20, 156, 20, this.transferRate, this::setTransferRate) + .setMin(1).setMax(maxItemTransferRate)); + + ioModeSwitch = new SwitchWidget(10, 45, 20, 20, + (clickData, value) -> { + setIo(value ? IO.IN : IO.OUT); + ioModeSwitch.setHoverTooltips( + LocalizationUtils.format("cover.conveyor.mode", LocalizationUtils.format(io.localeName)) + ); + }) .setTexture( - new GuiTextureGroup(ResourceBorderTexture.BUTTON_COMMON, new TextTexture("cover.conveyor.mode.export")), - new GuiTextureGroup(ResourceBorderTexture.BUTTON_COMMON, new TextTexture("cover.conveyor.mode.import"))) - .setPressed(io == IO.IN)); - group.addWidget(new SlotWidget(filterContainer, 0, 90, 45) + new GuiTextureGroup(ResourceBorderTexture.BUTTON_COMMON, IO.OUT.icon), + new GuiTextureGroup(ResourceBorderTexture.BUTTON_COMMON, IO.IN.icon)) + .setPressed(io == IO.IN) + .setHoverTooltips(LocalizationUtils.format("cover.conveyor.mode", LocalizationUtils.format(io.localeName))); + group.addWidget(ioModeSwitch); + group.addWidget(new SlotWidget(filterContainer, 0, 148, 107) .setChangeListener(() -> { if (isRemote()) { if (!filterContainer.getStackInSlot(0).isEmpty() && !filterItem.isEmpty()) { @@ -274,11 +415,28 @@ public Widget createUIWidget() { filterGroup.clearAllWidgets(); if (!filterItem.isEmpty()) { filterHandler = ItemFilter.loadFilter(filterItem); - filterGroup.addWidget(filterHandler.openConfigurator((176 - 80) / 2, (60 - 55) / 2)); + filterGroup.addWidget(filterHandler.openConfigurator(10, 0)); + configureFilterHandler(); } }) .setBackgroundTexture(new GuiTextureGroup(GuiTextures.SLOT, GuiTextures.FILTER_SLOT_OVERLAY))); group.addWidget(filterGroup); + + buildAdditionalUI(group); + return group; } + + @NotNull + protected String getUITitle() { + return "cover.conveyor.title"; + } + + protected void buildAdditionalUI(WidgetGroup group) { + // Do nothing in the base implementation. This is intended to be overridden by subclasses. + } + + protected void configureFilterHandler() { + // Do nothing in the base implementation. This is intended to be overridden by subclasses. + } } diff --git a/common/src/main/java/com/gregtechceu/gtceu/common/cover/RobotArmCover.java b/common/src/main/java/com/gregtechceu/gtceu/common/cover/RobotArmCover.java new file mode 100644 index 0000000000..73a74ee718 --- /dev/null +++ b/common/src/main/java/com/gregtechceu/gtceu/common/cover/RobotArmCover.java @@ -0,0 +1,192 @@ +package com.gregtechceu.gtceu.common.cover; + +import com.gregtechceu.gtceu.api.capability.ICoverable; +import com.gregtechceu.gtceu.api.cover.CoverDefinition; +import com.gregtechceu.gtceu.api.cover.filter.ItemFilter; +import com.gregtechceu.gtceu.api.cover.filter.SimpleItemFilter; +import com.gregtechceu.gtceu.api.gui.widget.IntInputWidget; +import com.gregtechceu.gtceu.common.cover.data.TransferMode; +import com.lowdragmc.lowdraglib.gui.texture.GuiTextureGroup; +import com.lowdragmc.lowdraglib.gui.texture.ResourceBorderTexture; +import com.lowdragmc.lowdraglib.gui.widget.CycleButtonWidget; +import com.lowdragmc.lowdraglib.gui.widget.WidgetGroup; +import com.lowdragmc.lowdraglib.side.item.IItemTransfer; +import com.lowdragmc.lowdraglib.syncdata.annotation.DescSynced; +import com.lowdragmc.lowdraglib.syncdata.annotation.Persisted; +import com.lowdragmc.lowdraglib.syncdata.field.ManagedFieldHolder; +import com.lowdragmc.lowdraglib.utils.LocalizationUtils; +import lombok.Getter; +import net.minecraft.core.Direction; +import net.minecraft.world.item.ItemStack; +import org.jetbrains.annotations.NotNull; + +import java.util.Arrays; +import java.util.Comparator; +import java.util.Iterator; +import java.util.Map; + +public class RobotArmCover extends ConveyorCover { + public static final ManagedFieldHolder MANAGED_FIELD_HOLDER = new ManagedFieldHolder(RobotArmCover.class, ConveyorCover.MANAGED_FIELD_HOLDER); + + public static final TransferMode[] TRANSFER_MODES = Arrays.stream(TransferMode.values()) + .sorted(Comparator.comparingInt(Enum::ordinal)) + .toArray(TransferMode[]::new); + + @Persisted @DescSynced @Getter + protected TransferMode transferMode; + + @Persisted @Getter + protected int globalTransferLimit; + protected int itemsTransferBuffered; + + private IntInputWidget stackSizeInput; + private CycleButtonWidget transferModeSelector; + + public RobotArmCover(CoverDefinition definition, ICoverable coverHolder, Direction attachedSide, int tier) { + super(definition, coverHolder, attachedSide, tier); + setTransferMode(TransferMode.TRANSFER_ANY); + } + + @Override + public ManagedFieldHolder getFieldHolder() { + return MANAGED_FIELD_HOLDER; + } + + @Override + protected int doTransferItems(IItemTransfer sourceInventory, IItemTransfer targetInventory, int maxTransferAmount) { + return switch (transferMode) { + case TRANSFER_ANY -> moveInventoryItems(sourceInventory, targetInventory, maxTransferAmount); + case TRANSFER_EXACT -> doTransferExact(sourceInventory, targetInventory, maxTransferAmount); + case KEEP_EXACT -> doKeepExact(sourceInventory, targetInventory, maxTransferAmount); + }; + } + + protected int doTransferExact(IItemTransfer sourceInventory, IItemTransfer targetInventory, int maxTransferAmount) { + Map sourceItemAmount = countInventoryItemsByType(sourceInventory); + + Iterator iterator = sourceItemAmount.keySet().iterator(); + while (iterator.hasNext()) { + TypeItemInfo sourceInfo = sourceItemAmount.get(iterator.next()); + int itemAmount = sourceInfo.totalCount; + int itemToMoveAmount = getFilteredItemAmount(sourceInfo.itemStack); + + if (itemAmount >= itemToMoveAmount) { + sourceInfo.totalCount = itemToMoveAmount; + } else { + iterator.remove(); + } + } + + int itemsTransferred = 0; + int maxTotalTransferAmount = maxTransferAmount + itemsTransferBuffered; + boolean notEnoughTransferRate = false; + for (TypeItemInfo itemInfo : sourceItemAmount.values()) { + if (maxTotalTransferAmount >= itemInfo.totalCount) { + boolean result = moveInventoryItemsExact(sourceInventory, targetInventory, itemInfo); + itemsTransferred += result ? itemInfo.totalCount : 0; + maxTotalTransferAmount -= result ? itemInfo.totalCount : 0; + } else { + notEnoughTransferRate = true; + } + } + //if we didn't transfer anything because of too small transfer rate, buffer it + if (itemsTransferred == 0 && notEnoughTransferRate) { + itemsTransferBuffered += maxTransferAmount; + } else { + //otherwise, if transfer succeed, empty transfer buffer value + itemsTransferBuffered = 0; + } + return Math.min(itemsTransferred, maxTransferAmount); + } + + protected int doKeepExact(IItemTransfer sourceInventory, IItemTransfer targetInventory, int maxTransferAmount) { + Map targetItemAmounts = countInventoryItemsByMatchSlot(targetInventory); + Map sourceItemAmounts = countInventoryItemsByMatchSlot(sourceInventory); + + Iterator iterator = sourceItemAmounts.keySet().iterator(); + while (iterator.hasNext()) { + ItemStack filteredItem = iterator.next(); + GroupItemInfo sourceInfo = sourceItemAmounts.get(filteredItem); + int itemToKeepAmount = getFilteredItemAmount(sourceInfo.itemStack); + + int itemAmount = 0; + if (targetItemAmounts.containsKey(filteredItem)) { + GroupItemInfo destItemInfo = targetItemAmounts.get(filteredItem); + itemAmount = destItemInfo.totalCount; + } + if (itemAmount < itemToKeepAmount) { + sourceInfo.totalCount = itemToKeepAmount - itemAmount; + } else { + iterator.remove(); + } + } + + return moveInventoryItems(sourceInventory, targetInventory, sourceItemAmounts, maxTransferAmount); + } + + private int getFilteredItemAmount(ItemStack itemStack) { + ItemFilter filter = getFilterHandler(); + + return filter.isBlackList() ? globalTransferLimit : filter.testItemCount(itemStack); + } + + + ////////////////////////////////////// + //*********** GUI ***********// + ////////////////////////////////////// + + @Override + @NotNull + protected String getUITitle() { + return "cover.robotic_arm.title"; + } + + @Override + protected void buildAdditionalUI(WidgetGroup group) { + transferModeSelector = new CycleButtonWidget( + 146, 45, 20, 20, 3, + i -> new GuiTextureGroup(ResourceBorderTexture.BUTTON_COMMON, TRANSFER_MODES[i].icon), + i -> setTransferMode(TRANSFER_MODES[i]) + ); + transferModeSelector.setIndex(transferMode.ordinal()); + transferModeSelector.setHoverTooltips(LocalizationUtils.format(transferMode.localeName)); + + group.addWidget(transferModeSelector); + + this.stackSizeInput = new IntInputWidget(64, 45, 80, 20, + globalTransferLimit, val -> globalTransferLimit = val + ); + configureStackSizeInput(); + + group.addWidget(this.stackSizeInput); + } + + private void setTransferMode(TransferMode transferMode) { + this.transferMode = transferMode; + + if (transferModeSelector != null) + transferModeSelector.setHoverTooltips(LocalizationUtils.format(transferMode.localeName)); + + configureStackSizeInput(); + + if (!this.isRemote()) { + configureFilterHandler(); + } + } + + @Override + protected void configureFilterHandler() { + if (this.filterHandler instanceof SimpleItemFilter filter) { + filter.setMaxStackSize(transferMode.maxStackSize); + } + } + + private void configureStackSizeInput() { + if (this.stackSizeInput == null) + return; + + this.stackSizeInput.setVisible(this.transferMode != TransferMode.TRANSFER_ANY); + this.stackSizeInput.setMin(1); + this.stackSizeInput.setMax(this.transferMode.maxStackSize); + } +} diff --git a/common/src/main/java/com/gregtechceu/gtceu/common/cover/data/TransferMode.java b/common/src/main/java/com/gregtechceu/gtceu/common/cover/data/TransferMode.java new file mode 100644 index 0000000000..e2238ec17a --- /dev/null +++ b/common/src/main/java/com/gregtechceu/gtceu/common/cover/data/TransferMode.java @@ -0,0 +1,20 @@ +package com.gregtechceu.gtceu.common.cover.data; + +import com.lowdragmc.lowdraglib.gui.texture.IGuiTexture; +import com.lowdragmc.lowdraglib.gui.texture.ResourceTexture; + +public enum TransferMode { + TRANSFER_ANY("cover.robotic_arm.transfer_mode.transfer_any", "transfer_any", 1), + TRANSFER_EXACT("cover.robotic_arm.transfer_mode.transfer_exact", "transfer_exact", 1024), + KEEP_EXACT("cover.robotic_arm.transfer_mode.keep_exact", "keep_exact", 1024); + + public final String localeName; + public final IGuiTexture icon; + public final int maxStackSize; + + TransferMode(String localeName, String textureName, int maxStackSize) { + this.localeName = localeName; + this.maxStackSize = maxStackSize; + this.icon = new ResourceTexture("gtceu:textures/gui/icon/transfer_mode/" + textureName + ".png"); + } +} diff --git a/common/src/main/java/com/gregtechceu/gtceu/common/data/GTCovers.java b/common/src/main/java/com/gregtechceu/gtceu/common/data/GTCovers.java index 959d403ce9..997bd68ad7 100644 --- a/common/src/main/java/com/gregtechceu/gtceu/common/data/GTCovers.java +++ b/common/src/main/java/com/gregtechceu/gtceu/common/data/GTCovers.java @@ -24,6 +24,7 @@ public class GTCovers { public final static CoverDefinition FLUID_FILTER = register("fluid_filter", FluidFilterCover::new, new SimpleCoverRenderer(GTCEu.id("block/cover/overlay_fluid_filter"))); public final static CoverDefinition INFINITE_WATER = register("infinite_water", InfiniteWaterCover::new, new SimpleCoverRenderer(GTCEu.id("block/cover/overlay_infinite_water"))); public final static CoverDefinition[] CONVEYORS = registerTiered("conveyor", ConveyorCover::new, tier -> ConveyorCoverRenderer.INSTANCE, GTValues.LV, GTValues.MV, GTValues.HV, GTValues.EV, GTValues.IV, GTValues.LuV); + public final static CoverDefinition[] ROBOT_ARMS = registerTiered("robot_arm", RobotArmCover::new, tier -> RobotArmCoverRenderer.INSTANCE, GTValues.LV, GTValues.MV, GTValues.HV, GTValues.EV, GTValues.IV, GTValues.LuV); public final static CoverDefinition[] PUMPS = registerTiered("pump", PumpCover::new, tier -> PumpCoverRenderer.INSTANCE, GTValues.LV, GTValues.MV, GTValues.HV, GTValues.EV, GTValues.IV, GTValues.LuV); public static CoverDefinition register(String id, CoverDefinition.CoverBehaviourProvider behaviorCreator) { diff --git a/common/src/main/java/com/gregtechceu/gtceu/common/data/GTItems.java b/common/src/main/java/com/gregtechceu/gtceu/common/data/GTItems.java index db007cbbfd..35ec246dd0 100644 --- a/common/src/main/java/com/gregtechceu/gtceu/common/data/GTItems.java +++ b/common/src/main/java/com/gregtechceu/gtceu/common/data/GTItems.java @@ -711,35 +711,35 @@ public static ICustomDescriptionId cellName() { public static ItemEntry ELECTRIC_PISTON_ZPM= REGISTRATE.item("zpm_electric_piston", Item::new).lang("ZPM Electric Piston").register(); public static ItemEntry ELECTRIC_PISTON_UV= REGISTRATE.item("uv_electric_piston", Item::new).lang("UV Electric Piston").register(); - public static ItemEntry ROBOT_ARM_LV = REGISTRATE.item("lv_robot_arm", ComponentItem::create).lang("LV Robot Arm").onRegister(attach(new TooltipBehavior(lines -> { + public static ItemEntry ROBOT_ARM_LV = REGISTRATE.item("lv_robot_arm", ComponentItem::create).lang("LV Robot Arm").onRegister(attach(new CoverPlaceBehavior(GTCovers.ROBOT_ARMS[0]), new TooltipBehavior(lines -> { lines.add(Component.translatable("item.gtceu.robot.arm.tooltip")); lines.add(Component.translatable("gtceu.universal.tooltip.item_transfer_rate", 8)); }))).register(); - public static ItemEntry ROBOT_ARM_MV = REGISTRATE.item("mv_robot_arm", ComponentItem::create).lang("MV Robot Arm").onRegister(attach(new TooltipBehavior(lines -> { + public static ItemEntry ROBOT_ARM_MV = REGISTRATE.item("mv_robot_arm", ComponentItem::create).lang("MV Robot Arm").onRegister(attach(new CoverPlaceBehavior(GTCovers.ROBOT_ARMS[1]), new TooltipBehavior(lines -> { lines.add(Component.translatable("item.gtceu.robot.arm.tooltip")); lines.add(Component.translatable("gtceu.universal.tooltip.item_transfer_rate", 32)); }))).register(); - public static ItemEntry ROBOT_ARM_HV = REGISTRATE.item("hv_robot_arm", ComponentItem::create).lang("HV Robot Arm").onRegister(attach(new TooltipBehavior(lines -> { + public static ItemEntry ROBOT_ARM_HV = REGISTRATE.item("hv_robot_arm", ComponentItem::create).lang("HV Robot Arm").onRegister(attach(new CoverPlaceBehavior(GTCovers.ROBOT_ARMS[2]), new TooltipBehavior(lines -> { lines.add(Component.translatable("item.gtceu.robot.arm.tooltip")); lines.add(Component.translatable("gtceu.universal.tooltip.item_transfer_rate", 64)); }))).register(); - public static ItemEntry ROBOT_ARM_EV = REGISTRATE.item("ev_robot_arm", ComponentItem::create).lang("EV Robot Arm").onRegister(attach(new TooltipBehavior(lines -> { + public static ItemEntry ROBOT_ARM_EV = REGISTRATE.item("ev_robot_arm", ComponentItem::create).lang("EV Robot Arm").onRegister(attach(new CoverPlaceBehavior(GTCovers.ROBOT_ARMS[3]), new TooltipBehavior(lines -> { lines.add(Component.translatable("item.gtceu.robot.arm.tooltip")); lines.add(Component.translatable("gtceu.universal.tooltip.item_transfer_rate_stacks", 3)); }))).register(); - public static ItemEntry ROBOT_ARM_IV = REGISTRATE.item("iv_robot_arm", ComponentItem::create).lang("IV Robot Arm").onRegister(attach(new TooltipBehavior(lines -> { + public static ItemEntry ROBOT_ARM_IV = REGISTRATE.item("iv_robot_arm", ComponentItem::create).lang("IV Robot Arm").onRegister(attach(new CoverPlaceBehavior(GTCovers.ROBOT_ARMS[4]), new TooltipBehavior(lines -> { lines.add(Component.translatable("item.gtceu.robot.arm.tooltip")); lines.add(Component.translatable("gtceu.universal.tooltip.item_transfer_rate_stacks", 8)); }))).register(); - public static ItemEntry ROBOT_ARM_LuV = REGISTRATE.item("luv_robot_arm", ComponentItem::create).lang("LuV Robot Arm").onRegister(attach(new TooltipBehavior(lines -> { + public static ItemEntry ROBOT_ARM_LuV = REGISTRATE.item("luv_robot_arm", ComponentItem::create).lang("LuV Robot Arm").onRegister(attach(new CoverPlaceBehavior(GTCovers.ROBOT_ARMS[5]), new TooltipBehavior(lines -> { lines.add(Component.translatable("item.gtceu.robot.arm.tooltip")); lines.add(Component.translatable("gtceu.universal.tooltip.item_transfer_rate_stacks", 16)); }))).register(); - public static ItemEntry ROBOT_ARM_ZPM = REGISTRATE.item("zpm_robot_arm", ComponentItem::create).lang("ZPM Robot Arm").onRegister(attach(new TooltipBehavior(lines -> { + public static ItemEntry ROBOT_ARM_ZPM = REGISTRATE.item("zpm_robot_arm", ComponentItem::create).lang("ZPM Robot Arm").onRegister(attach(new CoverPlaceBehavior(GTCovers.ROBOT_ARMS[5]), new TooltipBehavior(lines -> { lines.add(Component.translatable("item.gtceu.robot.arm.tooltip")); lines.add(Component.translatable("gtceu.universal.tooltip.item_transfer_rate_stacks", 16)); }))).register(); - public static ItemEntry ROBOT_ARM_UV = REGISTRATE.item("uv_robot_arm", ComponentItem::create).lang("UV Robot Arm").onRegister(attach(new TooltipBehavior(lines -> { + public static ItemEntry ROBOT_ARM_UV = REGISTRATE.item("uv_robot_arm", ComponentItem::create).lang("UV Robot Arm").onRegister(attach(new CoverPlaceBehavior(GTCovers.ROBOT_ARMS[5]), new TooltipBehavior(lines -> { lines.add(Component.translatable("item.gtceu.robot.arm.tooltip")); lines.add(Component.translatable("gtceu.universal.tooltip.item_transfer_rate_stacks", 16)); }))).register(); diff --git a/common/src/main/java/com/gregtechceu/gtceu/common/data/GTMachines.java b/common/src/main/java/com/gregtechceu/gtceu/common/data/GTMachines.java index c5ca77c872..403e558959 100644 --- a/common/src/main/java/com/gregtechceu/gtceu/common/data/GTMachines.java +++ b/common/src/main/java/com/gregtechceu/gtceu/common/data/GTMachines.java @@ -1290,7 +1290,7 @@ public static BiConsumer> createTankTooltips(String n (tier, builder) -> builder .rotationState(RotationState.NON_Y_AXIS) .blockProp(p -> p.noOcclusion().isViewBlocking((state, level, pos) -> false)) - .shape(Shapes.box(-0.001, -0.001, -0.001, 1.001, 1.001, 1.001)) + .shape(Shapes.box(0.001, 0.001, 0.001, 0.999, 0.999, 0.999)) .appearanceBlock(() -> ProcessingArrayMachine.getCasingState(tier)) .recipeType(GTRecipeTypes.DUMMY_RECIPES) .recipeModifier(ProcessingArrayMachine::recipeModifier, true) diff --git a/common/src/main/java/com/gregtechceu/gtceu/data/lang/LangHandler.java b/common/src/main/java/com/gregtechceu/gtceu/data/lang/LangHandler.java index ee9cca1c40..deb619bc09 100644 --- a/common/src/main/java/com/gregtechceu/gtceu/data/lang/LangHandler.java +++ b/common/src/main/java/com/gregtechceu/gtceu/data/lang/LangHandler.java @@ -64,6 +64,11 @@ public static void init(RegistrateLangProvider provider) { provider.add("recipe.condition.rock_breaker.tooltip", "Fluid blocks around"); provider.add("recipe.condition.eu_to_start.tooltip", "EU to start: %d"); + provider.add("gtceu.io.import", "Import"); + provider.add("gtceu.io.export", "Export"); + provider.add("gtceu.io.both", "Both"); + provider.add("gtceu.io.none", "None"); + provider.add("enchantment.disjunction", "Disjunction"); provider.add("gtceu.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."); provider.add("gtceu.multiblock.steam.low_steam", "Not enough Steam to run!"); @@ -302,6 +307,7 @@ public static void init(RegistrateLangProvider provider) { multilineLang(provider, "cover.smart_item_filter.filtering_mode.description", "Select Machine this Smart Filter will use for filtering.\nIt will automatically pick right portions of items for robotic arm."); provider.add("cover.conveyor.title", "Conveyor Cover Settings (%s)"); provider.add("cover.conveyor.transfer_rate", "§7items/sec"); + provider.add("cover.conveyor.mode", "Mode: %s"); provider.add("cover.conveyor.mode.export", "Mode: Export"); provider.add("cover.conveyor.mode.import", "Mode: Import"); multilineLang(provider, "cover.conveyor.distribution.round_robin_enhanced", "Distribution Mode\n§bEnhanced Round Robin§r\n§7Splits items equally to all inventories"); diff --git a/common/src/main/resources/assets/gtceu/textures/gui/icon/io_mode/both.png b/common/src/main/resources/assets/gtceu/textures/gui/icon/io_mode/both.png new file mode 100644 index 0000000000000000000000000000000000000000..fa4e9df7780c84e2b88c2ca62dde5b13c6ea87c6 GIT binary patch literal 795 zcmV+$1LXXPP)aiXhWLtOD&7=s*NW+^ z@PTmDk^zM;m7ekVNpZpBH^o*mF#&$nGhFz=nIEhbEnT=@IHH%z+V?!_OM*FLc1CKK z>~3rlOcEnZhB8Z(a2SwkNM?Wg2CKd)mc^sV+hi3>90iKvjfz^9t~sfB(R1>YSXH_I z&eP5h4|&~#F=%*n-Pc|SY(r(sbw3YXw{iq^4{&bO{L7Nl=)34!H7&9ap>;UDsA-uU zINN~EdoyjNt5Th8e?AW{C(x3Dwrglw@Ur?o=lBkiYx0Y(V0RDtq6E~U7BO`sHRN#GM->MmN4tO8zW=5YC&5A_WC)xNqmX$@rFa3}x(002ovPDHLkV1f||W?ldQ literal 0 HcmV?d00001 diff --git a/common/src/main/resources/assets/gtceu/textures/gui/icon/io_mode/export.png b/common/src/main/resources/assets/gtceu/textures/gui/icon/io_mode/export.png new file mode 100644 index 0000000000000000000000000000000000000000..2ab77e3f6869850eb0c3493c53bebffecd1f1ebd GIT binary patch literal 711 zcmV;&0yzDNP)aiXhWLtOD&7=s*NW+^ z@PTmDk^zM;m7ekVNpZpBH^o*mF#&$nGhFz=nIEhbEnT=@IHH%z+V?!_OM*FLc1CKK z>~3rlOcEnZhB8Z(a2SwkNM?Wg2CKd)mc^sV+hi3>90iKvjfz^9t~sfB(R1>YSXH_I z&eP5h4|&~#F=%*n-Pc|SY(r(sbw3YXw{iq^4{&bO{L7Nl=)34!H7&9ap>;UDsA-uU zINN~EdoyjNt5Th8e?AW{C(x3Dwrglw@Ur?o=lBkiYx0Y(V0RDtK#l@Z+D!N)hRrQs)cbV(u%J z8sa+1F(mXBzaHP3*X`dl=OG) tOn8IbRrk#gWhgSdLFZ(B18aiXhWLtOD&7=s*NW+^ z@PTmDk^zM;m7ekVNpZpBH^o*mF#&$nGhFz=nIEhbEnT=@IHH%z+V?!_OM*FLc1CKK z>~3rlOcEnZhB8Z(a2SwkNM?Wg2CKd)mc^sV+hi3>90iKvjfz^9t~sfB(R1>YSXH_I z&eP5h4|&~#F=%*n-Pc|SY(r(sbw3YXw{iq^4{&bO{L7Nl=)34!H7&9ap>;UDsA-uU zINN~EdoyjNt5Th8e?AW{C(x3Dwrglw@Ur?o=lBkiYx0Y(V0RDtyQ7w@3e>a^ZESUq>D)lKwhHAgvrjc$Pjqv>dK zr9UI1c1gtH{5^Hi1g|hf?1#1nUIToK$$usu$Q*w)ybNj?}5g=FB|fUS@$ z90gc|>;XpuT9CcqM88(3o8K&D5eIK;F51ocBtU(sAw?FLYvyy^VjwX+b@qU@Ui`~# mR^6VxgY+2*fpB2y4maiXhWLtOD&7=s*NW+^ z@PTmDk^zM;m7ekVNpZpBH^o*mF#&$nGhFz=nIEhbEnT=@IHH%z+V?!_OM*FLc1CKK z>~3rlOcEnZhB8Z(a2SwkNM?Wg2CKd)mc^sV+hi3>90iKvjfz^9t~sfB(R1>YSXH_I z&eP5h4|&~#F=%*n-Pc|SY(r(sbw3YXw{iq^4{&bO{L7Nl=)34!H7&9ap>;UDsA-uU zINN~EdoyjNt5Th8e?AW{C(x3Dwrglw@Ur?o=lBkiYx0Y(V0RDtk z7aZxh0Xazey}WbM6`0k*TwMAHTH%@{~uR*z$Z6B?ai_1rCP1Tv=wpxG)WaPbaqloMJW_*Rp|{KY#s h>*=F-IPeb+d;n#P%_7%#ewY9N002ovPDHLkV1gKMRigj^ literal 0 HcmV?d00001 diff --git a/common/src/main/resources/assets/gtceu/textures/gui/icon/transfer_mode/keep_exact.png b/common/src/main/resources/assets/gtceu/textures/gui/icon/transfer_mode/keep_exact.png new file mode 100644 index 0000000000000000000000000000000000000000..143449badc6f6453f8a65bdeee461cc9c28d8d73 GIT binary patch literal 637 zcmV-@0)qXCP)(Hf0sTF)JNo-o7sUc~R;wrc}6dXhs zUxWXFu7azAASi-}o4cp|NAZSmhnd$G zh4+N}T^UgLTK4?@8Gmp^Dj$IqpzY@Yg%j<+ScIstfm=T zaIy~3TSs^GFDWcLWLfZZ1g*2sehE$UK~~@A9Ns`?ResS0Z0|s?+;3a>1j4vy?X`8x zp8x;=32;bRa{vGjVE_ORVF9Q=r)dBH0Jcd)K~z{r?UX?dz#s?&ZPWjMxed2!#1*KL zChJv&VL(gaq5&G90UDqI8pt$oBqYC;oL!bP0nn5(6Htu74tfE#Hks_q9QFcA>?ow% zhcP06UqC{Ma0ZkJZROrLAwa0ViM|B#f+g4wpnneSR~biuBO}{d9DO8Gtyaj?KZhC= z1za+BZ|KMjA~@?K>&o;RL~y8c+}~zkMXS(1hxV)Dy)(GYAOWMQX)tP#_i2Cz{%+s_ X(y0zEMA3><00000NkvXXu0mjfP?{eZ literal 0 HcmV?d00001 diff --git a/common/src/main/resources/assets/gtceu/textures/gui/icon/transfer_mode/transfer_any.png b/common/src/main/resources/assets/gtceu/textures/gui/icon/transfer_mode/transfer_any.png new file mode 100644 index 0000000000000000000000000000000000000000..82122f7ad85e1d321dbf254bcc09fc44d9e4e43d GIT binary patch literal 600 zcmV-e0;m0nP)1VIr*?Cjkd3FCc6NRZ?WZ|=u=?_BPj0ec{$WzCjZ$mR-0$nSG6M^@a< zSDf_G%?LA5&D7_D!2nIy*F82>@4Tv4^Lq_fM?7I_U~3be(sZLBEYlF!DCmlJgnPAg zG%kE3JZ8v%!q-ZVRry76s>&aVjc{ll?5d|bRmZV9*3w2+cvRSv%@no2dDNG<61k;C zsRObHF$v+vhnpBh*2z%7D>WyXHTI4F`WDEGN0YZs2}2wy(&8NxwJ2Q^Qj?-5sP$!Ypi^m0w}975L?oL|+n z*dAPLL;s^5HKM`@eG$HIU)d zNMXe7Uz>BE2i6)N0tg_000IagfWQw0j_6E#w6LHq6f!H|b(y?y{GZL|hRh211=tL^ z8J*qfp0lz?KclUAL#SC+5Hy2Zg5Jb(f0WZCwfep`&9Q=D7SbC~w>J99-9}Xf(Fa&{ mKYbBE009ILKmY**Zh;e!GZ6#%62qDR00001VIr*?Cjkd3FCc6NRZ?WZ|=u=?_BPj0ec{$WzCjZ$mR-0$nSG6M^@a< zSDf_G%?LA5&D7_D!2nIy*F82>@4Tv4^Lq_fM?7I_U~3be(sZLBEYlF!DCmlJgnPAg zG%kE3JZ8v%!q-ZVRry76s>&aVjc{ll?5d|bRmZV9*3w2+cvRSv%@no2dDNG<61k;C zsRObHF$v+vhnpBh*2z%7D>WyXHTI4F`WDEGN0YZs2}2wy(&8NxwJ2Q^Qj?-5sP$!Ypi^m0w}975L?oL|+n z*dAPLL;s^5HKMV U!s(2Ny#N3J07*qoM6N<$f^D`G#Q*>R literal 0 HcmV?d00001 diff --git a/fabric/src/generated/resources/assets/gtceu/lang/en_ud.json b/fabric/src/generated/resources/assets/gtceu/lang/en_ud.json index 9d1a6c1506..dcdc1387da 100644 --- a/fabric/src/generated/resources/assets/gtceu/lang/en_ud.json +++ b/fabric/src/generated/resources/assets/gtceu/lang/en_ud.json @@ -1003,6 +1003,7 @@ "cover.conveyor.distribution.round_robin_enhanced.1": "ɹ§uıqoᴚ punoᴚ pǝɔuɐɥuƎq§", "cover.conveyor.distribution.round_robin_enhanced.2": "sǝıɹoʇuǝʌuı ןןɐ oʇ ʎןןɐnbǝ sɯǝʇı sʇıןdSㄥ§", "cover.conveyor.item_filter.title": "ɹǝʇןıℲ ɯǝʇI", + "cover.conveyor.mode": "%s :ǝpoW", "cover.conveyor.mode.export": "ʇɹodxƎ :ǝpoW", "cover.conveyor.mode.import": "ʇɹodɯI :ǝpoW", "cover.conveyor.ore_dictionary.title.0": "ǝɯɐN ʎɹɐuoıʇɔıᗡ ǝɹO", @@ -1344,6 +1345,10 @@ "gtceu.gui.toggle_view.disabled": ")spınןℲ( ʍǝıΛ ǝןbbo⟘", "gtceu.gui.toggle_view.enabled": ")sɯǝʇI( ʍǝıΛ ǝןbbo⟘", "gtceu.implosion_compressor": "ɹossǝɹdɯoƆ uoısoןdɯI", + "gtceu.io.both": "ɥʇoᗺ", + "gtceu.io.export": "ʇɹodxƎ", + "gtceu.io.import": "ʇɹodɯI", + "gtceu.io.none": "ǝuoN", "gtceu.item_filter.empty_item": ")ɯǝʇI oN( ʎʇdɯƎ", "gtceu.item_filter.footer": "ǝpıɹɹǝʌo oʇ ɯǝʇı ɥʇıʍ ʞɔıןƆǝ§", "gtceu.item_list.item_stored": "%d :pǝɹoʇSㄥ§", diff --git a/fabric/src/generated/resources/assets/gtceu/lang/en_us.json b/fabric/src/generated/resources/assets/gtceu/lang/en_us.json index 2cc6821e62..2d5ae30061 100644 --- a/fabric/src/generated/resources/assets/gtceu/lang/en_us.json +++ b/fabric/src/generated/resources/assets/gtceu/lang/en_us.json @@ -1003,6 +1003,7 @@ "cover.conveyor.distribution.round_robin_enhanced.1": "§bEnhanced Round Robin§r", "cover.conveyor.distribution.round_robin_enhanced.2": "§7Splits items equally to all inventories", "cover.conveyor.item_filter.title": "Item Filter", + "cover.conveyor.mode": "Mode: %s", "cover.conveyor.mode.export": "Mode: Export", "cover.conveyor.mode.import": "Mode: Import", "cover.conveyor.ore_dictionary.title.0": "Ore Dictionary Name", @@ -1344,6 +1345,10 @@ "gtceu.gui.toggle_view.disabled": "Toggle View (Fluids)", "gtceu.gui.toggle_view.enabled": "Toggle View (Items)", "gtceu.implosion_compressor": "Implosion Compressor", + "gtceu.io.both": "Both", + "gtceu.io.export": "Export", + "gtceu.io.import": "Import", + "gtceu.io.none": "None", "gtceu.item_filter.empty_item": "Empty (No Item)", "gtceu.item_filter.footer": "§eClick with item to override", "gtceu.item_list.item_stored": "§7Stored: %d", diff --git a/forge/src/generated/resources/assets/gtceu/lang/en_ud.json b/forge/src/generated/resources/assets/gtceu/lang/en_ud.json index 9d1a6c1506..dcdc1387da 100644 --- a/forge/src/generated/resources/assets/gtceu/lang/en_ud.json +++ b/forge/src/generated/resources/assets/gtceu/lang/en_ud.json @@ -1003,6 +1003,7 @@ "cover.conveyor.distribution.round_robin_enhanced.1": "ɹ§uıqoᴚ punoᴚ pǝɔuɐɥuƎq§", "cover.conveyor.distribution.round_robin_enhanced.2": "sǝıɹoʇuǝʌuı ןןɐ oʇ ʎןןɐnbǝ sɯǝʇı sʇıןdSㄥ§", "cover.conveyor.item_filter.title": "ɹǝʇןıℲ ɯǝʇI", + "cover.conveyor.mode": "%s :ǝpoW", "cover.conveyor.mode.export": "ʇɹodxƎ :ǝpoW", "cover.conveyor.mode.import": "ʇɹodɯI :ǝpoW", "cover.conveyor.ore_dictionary.title.0": "ǝɯɐN ʎɹɐuoıʇɔıᗡ ǝɹO", @@ -1344,6 +1345,10 @@ "gtceu.gui.toggle_view.disabled": ")spınןℲ( ʍǝıΛ ǝןbbo⟘", "gtceu.gui.toggle_view.enabled": ")sɯǝʇI( ʍǝıΛ ǝןbbo⟘", "gtceu.implosion_compressor": "ɹossǝɹdɯoƆ uoısoןdɯI", + "gtceu.io.both": "ɥʇoᗺ", + "gtceu.io.export": "ʇɹodxƎ", + "gtceu.io.import": "ʇɹodɯI", + "gtceu.io.none": "ǝuoN", "gtceu.item_filter.empty_item": ")ɯǝʇI oN( ʎʇdɯƎ", "gtceu.item_filter.footer": "ǝpıɹɹǝʌo oʇ ɯǝʇı ɥʇıʍ ʞɔıןƆǝ§", "gtceu.item_list.item_stored": "%d :pǝɹoʇSㄥ§", diff --git a/forge/src/generated/resources/assets/gtceu/lang/en_us.json b/forge/src/generated/resources/assets/gtceu/lang/en_us.json index 2cc6821e62..2d5ae30061 100644 --- a/forge/src/generated/resources/assets/gtceu/lang/en_us.json +++ b/forge/src/generated/resources/assets/gtceu/lang/en_us.json @@ -1003,6 +1003,7 @@ "cover.conveyor.distribution.round_robin_enhanced.1": "§bEnhanced Round Robin§r", "cover.conveyor.distribution.round_robin_enhanced.2": "§7Splits items equally to all inventories", "cover.conveyor.item_filter.title": "Item Filter", + "cover.conveyor.mode": "Mode: %s", "cover.conveyor.mode.export": "Mode: Export", "cover.conveyor.mode.import": "Mode: Import", "cover.conveyor.ore_dictionary.title.0": "Ore Dictionary Name", @@ -1344,6 +1345,10 @@ "gtceu.gui.toggle_view.disabled": "Toggle View (Fluids)", "gtceu.gui.toggle_view.enabled": "Toggle View (Items)", "gtceu.implosion_compressor": "Implosion Compressor", + "gtceu.io.both": "Both", + "gtceu.io.export": "Export", + "gtceu.io.import": "Import", + "gtceu.io.none": "None", "gtceu.item_filter.empty_item": "Empty (No Item)", "gtceu.item_filter.footer": "§eClick with item to override", "gtceu.item_list.item_stored": "§7Stored: %d", diff --git a/settings.gradle b/settings.gradle index 123c2311e2..73a892328f 100644 --- a/settings.gradle +++ b/settings.gradle @@ -57,7 +57,7 @@ dependencyResolutionManagement { def architecturyLoomVersion = "1.0-SNAPSHOT" def vineFlowerVersion = "1.+" def macheteVersion = "1.+" - def ldLibVersion = "1.0.14" + def ldLibVersion = "1.0.14.a" fabric { def parchment = version("parchment", parchmentVersion)