From 87291b32cd4fd0db6a9707d5cbbe1964c13033e8 Mon Sep 17 00:00:00 2001 From: GaLi <3096147684@qq.com> Date: Sat, 28 Mar 2026 13:58:39 +0800 Subject: [PATCH] =?UTF-8?q?=E6=A0=B7=E6=9D=BF=E7=BB=88=E7=AB=AF=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E7=B3=BB=E5=88=97=E6=8C=89=E9=92=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../gui/widgets/ScaledTextureButton.java | 98 ++++++++ .../com/extendedae_plus/init/ModNetwork.java | 6 + .../PatternEncodingTermMenuAccessor.java | 7 + .../PatternEncodingTermScaleButtonsMixin.java | 232 ++++++++++++++++++ .../ScaleEncodingPatternC2SPacket.java | 212 ++++++++++++++++ .../encoding/eaep_pattern_terminals.json | 37 +++ .../terminals/pattern_encoding_terminal.json | 118 +++++++++ .../extendedae_plus/textures/gui/beizeng.png | Bin 0 -> 345 bytes .../extendedae_plus/textures/gui/huanyuan.png | Bin 0 -> 175 bytes .../textures/gui/zhu_fu_qie_huan.png | Bin 0 -> 224 bytes .../resources/extendedae_plus.mixins.json | 1 + 11 files changed, 711 insertions(+) create mode 100644 src/main/java/com/extendedae_plus/client/gui/widgets/ScaledTextureButton.java create mode 100644 src/main/java/com/extendedae_plus/mixin/ae2/client/gui/PatternEncodingTermScaleButtonsMixin.java create mode 100644 src/main/java/com/extendedae_plus/network/ScaleEncodingPatternC2SPacket.java create mode 100644 src/main/resources/assets/ae2/screens/terminals/encoding/eaep_pattern_terminals.json create mode 100644 src/main/resources/assets/ae2/screens/terminals/pattern_encoding_terminal.json create mode 100644 src/main/resources/assets/extendedae_plus/textures/gui/beizeng.png create mode 100644 src/main/resources/assets/extendedae_plus/textures/gui/huanyuan.png create mode 100644 src/main/resources/assets/extendedae_plus/textures/gui/zhu_fu_qie_huan.png diff --git a/src/main/java/com/extendedae_plus/client/gui/widgets/ScaledTextureButton.java b/src/main/java/com/extendedae_plus/client/gui/widgets/ScaledTextureButton.java new file mode 100644 index 0000000..bc99ebb --- /dev/null +++ b/src/main/java/com/extendedae_plus/client/gui/widgets/ScaledTextureButton.java @@ -0,0 +1,98 @@ +package com.extendedae_plus.client.gui.widgets; + +import appeng.client.gui.Icon; +import com.mojang.blaze3d.systems.RenderSystem; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.components.Button; +import net.minecraft.client.gui.components.Tooltip; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; + +public class ScaledTextureButton extends Button { + private final OnPress delegateOnPress; + private final ResourceLocation texture; + private final int textureWidth; + private final int textureHeight; + private final int srcX; + private final int srcY; + private final int srcWidth; + private final int srcHeight; + private final float scale; + + public ScaledTextureButton(ResourceLocation texture, int textureWidth, int textureHeight, + int srcX, int srcY, int srcWidth, int srcHeight, float scale, + Component tooltipText, OnPress onPress) { + super(0, 0, Math.round(srcWidth * scale), Math.round(srcHeight * scale), + Component.empty(), btn -> { + }, DEFAULT_NARRATION); + this.delegateOnPress = onPress; + this.texture = texture; + this.textureWidth = textureWidth; + this.textureHeight = textureHeight; + this.srcX = srcX; + this.srcY = srcY; + this.srcWidth = srcWidth; + this.srcHeight = srcHeight; + this.scale = scale; + if (tooltipText != null) { + this.setTooltip(Tooltip.create(tooltipText)); + } + } + + public void setVisibility(boolean visible) { + this.visible = visible; + this.active = visible; + } + + @Override + public void onPress() { + this.delegateOnPress.onPress(this); + this.setFocused(false); + } + + @Override + public void onClick(double mouseX, double mouseY) { + super.onClick(mouseX, mouseY); + this.setFocused(false); + } + + @Override + public void onRelease(double mouseX, double mouseY) { + super.onRelease(mouseX, mouseY); + this.setFocused(false); + } + + @Override + public void renderWidget(GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTick) { + if (!this.visible) { + return; + } + + this.width = Math.round(this.srcWidth * this.scale); + this.height = Math.round(this.srcHeight * this.scale); + + int yOffset = this.isHovered() ? 1 : 0; + + RenderSystem.disableDepthTest(); + RenderSystem.enableBlend(); + + var pose = guiGraphics.pose(); + pose.pushPose(); + pose.translate(getX(), getY() + yOffset, 0.0F); + pose.scale(scale, scale, 1.0F); + + Icon.TOOLBAR_BUTTON_BACKGROUND.getBlitter().dest(0, 0).blit(guiGraphics); + + if (!this.active) { + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 0.5F); + } + guiGraphics.blit(this.texture, 0, 0, this.srcX, this.srcY, this.srcWidth, this.srcHeight, + this.textureWidth, this.textureHeight); + if (!this.active) { + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + } + + pose.popPose(); + RenderSystem.enableDepthTest(); + } +} diff --git a/src/main/java/com/extendedae_plus/init/ModNetwork.java b/src/main/java/com/extendedae_plus/init/ModNetwork.java index e2bd7f6..59b7d7d 100644 --- a/src/main/java/com/extendedae_plus/init/ModNetwork.java +++ b/src/main/java/com/extendedae_plus/init/ModNetwork.java @@ -58,6 +58,12 @@ public final class ModNetwork { .consumerNetworkThread(EncodeWithShiftFlagC2SPacket::handle) .add(); + CHANNEL.messageBuilder(ScaleEncodingPatternC2SPacket.class, nextId(), NetworkDirection.PLAY_TO_SERVER) + .encoder(ScaleEncodingPatternC2SPacket::encode) + .decoder(ScaleEncodingPatternC2SPacket::decode) + .consumerNetworkThread(ScaleEncodingPatternC2SPacket::handle) + .add(); + CHANNEL.messageBuilder(UploadEncodedPatternToProviderC2SPacket.class, nextId(), NetworkDirection.PLAY_TO_SERVER) .encoder(UploadEncodedPatternToProviderC2SPacket::encode) .decoder(UploadEncodedPatternToProviderC2SPacket::decode) diff --git a/src/main/java/com/extendedae_plus/mixin/ae2/accessor/PatternEncodingTermMenuAccessor.java b/src/main/java/com/extendedae_plus/mixin/ae2/accessor/PatternEncodingTermMenuAccessor.java index c87956a..74704b5 100644 --- a/src/main/java/com/extendedae_plus/mixin/ae2/accessor/PatternEncodingTermMenuAccessor.java +++ b/src/main/java/com/extendedae_plus/mixin/ae2/accessor/PatternEncodingTermMenuAccessor.java @@ -2,6 +2,7 @@ package com.extendedae_plus.mixin.ae2.accessor; import appeng.menu.me.items.PatternEncodingTermMenu; import appeng.menu.slot.RestrictedInputSlot; +import appeng.util.ConfigInventory; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; @@ -12,4 +13,10 @@ public interface PatternEncodingTermMenuAccessor { @Accessor(value = "blankPatternSlot",remap = false) RestrictedInputSlot eap$getBlankPatternSlot(); + + @Accessor(value = "encodedInputsInv", remap = false) + ConfigInventory eap$getEncodedInputsInv(); + + @Accessor(value = "encodedOutputsInv", remap = false) + ConfigInventory eap$getEncodedOutputsInv(); } diff --git a/src/main/java/com/extendedae_plus/mixin/ae2/client/gui/PatternEncodingTermScaleButtonsMixin.java b/src/main/java/com/extendedae_plus/mixin/ae2/client/gui/PatternEncodingTermScaleButtonsMixin.java new file mode 100644 index 0000000..89fcdaf --- /dev/null +++ b/src/main/java/com/extendedae_plus/mixin/ae2/client/gui/PatternEncodingTermScaleButtonsMixin.java @@ -0,0 +1,232 @@ +package com.extendedae_plus.mixin.ae2.client.gui; + +import appeng.client.gui.AEBaseScreen; +import appeng.client.gui.me.items.PatternEncodingTermScreen; +import appeng.client.gui.style.ScreenStyle; +import appeng.client.gui.style.WidgetStyle; +import appeng.parts.encoding.EncodingMode; +import com.google.gson.JsonObject; +import com.extendedae_plus.ExtendedAEPlus; +import com.extendedae_plus.client.gui.widgets.ScaledTextureButton; +import com.extendedae_plus.init.ModNetwork; +import com.extendedae_plus.mixin.ae2.accessor.AEBaseScreenAccessor; +import com.extendedae_plus.mixin.minecraft.accessor.AbstractContainerScreenAccessor; +import com.extendedae_plus.mixin.minecraft.accessor.ScreenAccessor; +import com.extendedae_plus.network.ScaleEncodingPatternC2SPacket; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.Rect2i; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@SuppressWarnings({"AddedMixinMembersNamePattern"}) +@Mixin(PatternEncodingTermScreen.class) +public abstract class PatternEncodingTermScaleButtonsMixin { + @Unique + private static final ResourceLocation EAP$SCALE_BUTTON_TEXTURE = + new ResourceLocation(ExtendedAEPlus.MODID, "textures/gui/beizeng.png"); + @Unique + private static final ResourceLocation EAP$SWAP_OUTPUT_TEXTURE = + new ResourceLocation(ExtendedAEPlus.MODID, "textures/gui/zhu_fu_qie_huan.png"); + @Unique + private static final ResourceLocation EAP$RESTORE_RATIO_TEXTURE = + new ResourceLocation(ExtendedAEPlus.MODID, "textures/gui/huanyuan.png"); + @Unique + private static final ResourceLocation EAP$LAYOUT_RESOURCE = + new ResourceLocation("ae2", "screens/terminals/encoding/eaep_pattern_terminals.json"); + + @Unique private ScaledTextureButton eap$mul2Button; + @Unique private ScaledTextureButton eap$mul3Button; + @Unique private ScaledTextureButton eap$mul5Button; + @Unique private ScaledTextureButton eap$div2Button; + @Unique private ScaledTextureButton eap$div3Button; + @Unique private ScaledTextureButton eap$div5Button; + @Unique private ScaledTextureButton eap$swapOutputsButton; + @Unique private ScaledTextureButton eap$restoreRatioButton; + @Unique private static JsonObject eap$layoutWidgets; + @Unique private static boolean eap$layoutWidgetsLoaded; + + @Inject(method = "", at = @At("TAIL")) + private void eap$createScaleButtons(CallbackInfo ci) { + if (this.eap$mul2Button == null) { + this.eap$mul2Button = eap$createScaleButton(0, 0, "x2", ScaleEncodingPatternC2SPacket.Operation.MUL2); + this.eap$mul3Button = eap$createScaleButton(16, 0, "x3", ScaleEncodingPatternC2SPacket.Operation.MUL3); + this.eap$mul5Button = eap$createScaleButton(32, 0, "x5", ScaleEncodingPatternC2SPacket.Operation.MUL5); + this.eap$div2Button = eap$createScaleButton(0, 16, "/2", ScaleEncodingPatternC2SPacket.Operation.DIV2); + this.eap$div3Button = eap$createScaleButton(16, 16, "/3", ScaleEncodingPatternC2SPacket.Operation.DIV3); + this.eap$div5Button = eap$createScaleButton(32, 16, "/5", ScaleEncodingPatternC2SPacket.Operation.DIV5); + this.eap$swapOutputsButton = eap$createStandaloneButton( + EAP$SWAP_OUTPUT_TEXTURE, "主副切换", ScaleEncodingPatternC2SPacket.Operation.SWAP_OUTPUTS); + this.eap$restoreRatioButton = eap$createStandaloneButton( + EAP$RESTORE_RATIO_TEXTURE, "恢复比例", ScaleEncodingPatternC2SPacket.Operation.RESTORE_RATIO); + } + + eap$ensureAdded(this.eap$mul2Button); + eap$ensureAdded(this.eap$mul3Button); + eap$ensureAdded(this.eap$mul5Button); + eap$ensureAdded(this.eap$div2Button); + eap$ensureAdded(this.eap$div3Button); + eap$ensureAdded(this.eap$div5Button); + eap$ensureAdded(this.eap$swapOutputsButton); + eap$ensureAdded(this.eap$restoreRatioButton); + } + + @Inject(method = "updateBeforeRender", at = @At("TAIL"), remap = false) + private void eap$updateScaleButtons(CallbackInfo ci) { + if (this.eap$mul2Button == null) { + return; + } + + var screen = (PatternEncodingTermScreen) (Object) this; + + eap$ensureAdded(this.eap$mul2Button); + eap$ensureAdded(this.eap$mul3Button); + eap$ensureAdded(this.eap$mul5Button); + eap$ensureAdded(this.eap$div2Button); + eap$ensureAdded(this.eap$div3Button); + eap$ensureAdded(this.eap$div5Button); + eap$ensureAdded(this.eap$swapOutputsButton); + eap$ensureAdded(this.eap$restoreRatioButton); + + boolean visible = screen.getMenu().getMode() == EncodingMode.PROCESSING; + this.eap$mul2Button.setVisibility(visible); + this.eap$mul3Button.setVisibility(visible); + this.eap$mul5Button.setVisibility(visible); + this.eap$div2Button.setVisibility(visible); + this.eap$div3Button.setVisibility(visible); + this.eap$div5Button.setVisibility(visible); + this.eap$swapOutputsButton.setVisibility(visible); + this.eap$restoreRatioButton.setVisibility(visible); + + if (!visible) { + return; + } + + Rect2i bounds = eap$getScreenBounds(); + eap$placeButton(this.eap$swapOutputsButton, "zhu_fu_qie_huan", bounds); + eap$placeButton(this.eap$restoreRatioButton, "huan_yuan_mo_ren", bounds); + eap$placeButton(this.eap$mul2Button, "cheng_2", bounds); + eap$placeButton(this.eap$mul3Button, "cheng_3", bounds); + eap$placeButton(this.eap$mul5Button, "cheng_5", bounds); + eap$placeButton(this.eap$div2Button, "chu_2", bounds); + eap$placeButton(this.eap$div3Button, "chu_3", bounds); + eap$placeButton(this.eap$div5Button, "chu_5", bounds); + } + + @Unique + private ScaledTextureButton eap$createScaleButton(int srcX, int srcY, String tooltipText, + ScaleEncodingPatternC2SPacket.Operation op) { + return new ScaledTextureButton( + EAP$SCALE_BUTTON_TEXTURE, + 48, + 32, + srcX, + srcY, + 16, + 16, + 0.375f, + Component.literal(tooltipText), + btn -> ModNetwork.CHANNEL.sendToServer(new ScaleEncodingPatternC2SPacket(op)) + ); + } + + @Unique + private ScaledTextureButton eap$createStandaloneButton(ResourceLocation texture, String tooltipText, + ScaleEncodingPatternC2SPacket.Operation op) { + return new ScaledTextureButton( + texture, + 16, + 16, + 0, + 0, + 16, + 16, + 0.375f, + Component.literal(tooltipText), + btn -> ModNetwork.CHANNEL.sendToServer(new ScaleEncodingPatternC2SPacket(op)) + ); + } + + @Unique + private Rect2i eap$getScreenBounds() { + var screen = (AbstractContainerScreenAccessor) this; + return new Rect2i(screen.eap$getLeftPos(), screen.eap$getTopPos(), + screen.eap$getImageWidth(), screen.eap$getImageHeight()); + } + + @Unique + private void eap$placeButton(ScaledTextureButton button, String widgetId, Rect2i bounds) { + try { + ScreenStyle style = ((AEBaseScreenAccessor) this).eap$getStyle(); + WidgetStyle widgetStyle = style.getWidget(widgetId); + var pos = widgetStyle.resolve(bounds); + button.setX(pos.getX()); + button.setY(pos.getY()); + } catch (IllegalStateException ignored) { + int left = eap$getFallbackWidgetValue(widgetId, "left"); + int bottom = eap$getFallbackWidgetValue(widgetId, "bottom"); + button.setX(bounds.getX() + left); + button.setY(bounds.getY() + bounds.getHeight() - bottom); + } + } + + @Unique + private int eap$getFallbackWidgetValue(String widgetId, String key) { + JsonObject widget = eap$getFallbackWidget(widgetId); + if (widget != null && widget.has(key)) { + return widget.get(key).getAsInt(); + } + + return switch (widgetId + "#" + key) { + case "zhu_fu_qie_huan#left", "cheng_2#left", "cheng_3#left", "cheng_5#left" -> 125; + case "huan_yuan_mo_ren#left", "chu_2#left", "chu_3#left", "chu_5#left" -> 101; + case "zhu_fu_qie_huan#bottom", "huan_yuan_mo_ren#bottom" -> 159; + case "cheng_2#bottom", "chu_2#bottom" -> 149; + case "cheng_3#bottom", "chu_3#bottom" -> 138; + case "cheng_5#bottom", "chu_5#bottom" -> 127; + default -> 0; + }; + } + + @Unique + private JsonObject eap$getFallbackWidget(String widgetId) { + if (!eap$layoutWidgetsLoaded) { + eap$layoutWidgetsLoaded = true; + try { + var resourceManager = Minecraft.getInstance().getResourceManager(); + try (var reader = resourceManager.openAsReader(EAP$LAYOUT_RESOURCE)) { + JsonObject root = ScreenStyle.GSON.fromJson(reader, JsonObject.class); + if (root != null && root.has("widgets") && root.get("widgets").isJsonObject()) { + eap$layoutWidgets = root.getAsJsonObject("widgets"); + } + } + } catch (Exception ignored) { + eap$layoutWidgets = null; + } + } + + if (eap$layoutWidgets == null || !eap$layoutWidgets.has(widgetId)) { + return null; + } + + var widget = eap$layoutWidgets.get(widgetId); + return widget != null && widget.isJsonObject() ? widget.getAsJsonObject() : null; + } + + @Unique + private void eap$ensureAdded(ScaledTextureButton button) { + var accessor = (ScreenAccessor) this; + var renderables = accessor.eap$getRenderables(); + var children = accessor.eap$getChildren(); + if (!renderables.contains(button)) { + renderables.add(button); + } + if (!children.contains(button)) { + children.add(button); + } + } +} diff --git a/src/main/java/com/extendedae_plus/network/ScaleEncodingPatternC2SPacket.java b/src/main/java/com/extendedae_plus/network/ScaleEncodingPatternC2SPacket.java new file mode 100644 index 0000000..bc21bb5 --- /dev/null +++ b/src/main/java/com/extendedae_plus/network/ScaleEncodingPatternC2SPacket.java @@ -0,0 +1,212 @@ +package com.extendedae_plus.network; + +import appeng.api.stacks.GenericStack; +import appeng.menu.me.items.PatternEncodingTermMenu; +import appeng.menu.slot.FakeSlot; +import appeng.parts.encoding.EncodingMode; +import appeng.util.ConfigInventory; +import com.extendedae_plus.mixin.ae2.accessor.PatternEncodingTermMenuAccessor; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.server.level.ServerPlayer; +import net.minecraftforge.network.NetworkEvent; + +import java.util.function.Supplier; + +public class ScaleEncodingPatternC2SPacket { + public enum Operation { + MUL2, DIV2, MUL3, DIV3, MUL5, DIV5, SWAP_OUTPUTS, RESTORE_RATIO + } + + private final Operation op; + + public ScaleEncodingPatternC2SPacket(Operation op) { + this.op = op; + } + + public static void encode(ScaleEncodingPatternC2SPacket msg, FriendlyByteBuf buf) { + buf.writeEnum(msg.op); + } + + public static ScaleEncodingPatternC2SPacket decode(FriendlyByteBuf buf) { + return new ScaleEncodingPatternC2SPacket(buf.readEnum(Operation.class)); + } + + public static void handle(ScaleEncodingPatternC2SPacket msg, Supplier ctxSupplier) { + var ctx = ctxSupplier.get(); + ctx.enqueueWork(() -> { + ServerPlayer player = ctx.getSender(); + if (player == null) { + return; + } + if (!(player.containerMenu instanceof PatternEncodingTermMenu menu)) { + return; + } + if (menu.getMode() != EncodingMode.PROCESSING) { + return; + } + + if (msg.op == Operation.SWAP_OUTPUTS) { + rotateProcessingOutputs(menu); + menu.broadcastChanges(); + return; + } + + if (msg.op == Operation.RESTORE_RATIO) { + var accessor = (PatternEncodingTermMenuAccessor) (Object) menu; + long gcd = computeSharedGcd(accessor.eap$getEncodedInputsInv(), accessor.eap$getEncodedOutputsInv()); + if (gcd <= 1L) { + return; + } + + var reducedOutputs = reduceInventory(accessor.eap$getEncodedOutputsInv(), gcd); + var reducedInputs = reduceInventory(accessor.eap$getEncodedInputsInv(), gcd); + applyScaled(accessor.eap$getEncodedOutputsInv(), reducedOutputs); + applyScaled(accessor.eap$getEncodedInputsInv(), reducedInputs); + menu.broadcastChanges(); + return; + } + + int scale = switch (msg.op) { + case MUL2, DIV2 -> 2; + case MUL3, DIV3 -> 3; + case MUL5, DIV5 -> 5; + default -> 1; + }; + boolean divide = switch (msg.op) { + case DIV2, DIV3, DIV5 -> true; + default -> false; + }; + + var accessor = (PatternEncodingTermMenuAccessor) (Object) menu; + var scaledOutputs = scaleInventory(accessor.eap$getEncodedOutputsInv(), scale, divide); + if (scaledOutputs == null) { + return; + } + + var scaledInputs = scaleInventory(accessor.eap$getEncodedInputsInv(), scale, divide); + if (scaledInputs == null) { + return; + } + + applyScaled(accessor.eap$getEncodedOutputsInv(), scaledOutputs); + applyScaled(accessor.eap$getEncodedInputsInv(), scaledInputs); + menu.broadcastChanges(); + }); + ctx.setPacketHandled(true); + } + + private static GenericStack[] scaleInventory(ConfigInventory inventory, int scale, boolean divide) { + var result = new GenericStack[inventory.size()]; + for (int slot = 0; slot < inventory.size(); slot++) { + GenericStack stack = inventory.getStack(slot); + if (stack == null) { + continue; + } + + long nextAmount; + if (divide) { + if (stack.amount() % scale != 0) { + return null; + } + nextAmount = stack.amount() / scale; + } else { + nextAmount = stack.amount() * scale; + if (nextAmount < 0L) { + return null; + } + } + + result[slot] = new GenericStack(stack.what(), nextAmount); + } + return result; + } + + private static GenericStack[] reduceInventory(ConfigInventory inventory, long gcd) { + var result = new GenericStack[inventory.size()]; + for (int slot = 0; slot < inventory.size(); slot++) { + GenericStack stack = inventory.getStack(slot); + if (stack == null) { + continue; + } + result[slot] = new GenericStack(stack.what(), stack.amount() / gcd); + } + return result; + } + + private static void applyScaled(ConfigInventory inventory, GenericStack[] scaledStacks) { + for (int slot = 0; slot < scaledStacks.length; slot++) { + if (scaledStacks[slot] != null) { + inventory.setStack(slot, scaledStacks[slot]); + } + } + } + + private static long computeSharedGcd(ConfigInventory inputs, ConfigInventory outputs) { + long gcd = 0L; + gcd = updateGcd(gcd, inputs); + gcd = updateGcd(gcd, outputs); + return gcd; + } + + private static long updateGcd(long currentGcd, ConfigInventory inventory) { + long gcd = currentGcd; + for (int slot = 0; slot < inventory.size(); slot++) { + GenericStack stack = inventory.getStack(slot); + if (stack == null || stack.amount() <= 0L) { + continue; + } + gcd = gcd == 0L ? stack.amount() : gcd(gcd, stack.amount()); + if (gcd == 1L) { + return 1L; + } + } + return gcd; + } + + private static long gcd(long a, long b) { + long left = Math.abs(a); + long right = Math.abs(b); + while (right != 0L) { + long temp = left % right; + left = right; + right = temp; + } + return left; + } + + private static void rotateProcessingOutputs(PatternEncodingTermMenu menu) { + FakeSlot[] outputSlots = menu.getProcessingOutputSlots(); + int nonEmptyCount = 0; + for (FakeSlot slot : outputSlots) { + if (!slot.getItem().isEmpty()) { + nonEmptyCount++; + } + } + if (nonEmptyCount < 2) { + return; + } + + var newOutputs = new net.minecraft.world.item.ItemStack[outputSlots.length]; + for (int i = 0; i < outputSlots.length; i++) { + newOutputs[i] = outputSlots[i].getItem().copy(); + } + + for (int i = 0; i < outputSlots.length; i++) { + if (outputSlots[i].getItem().isEmpty()) { + continue; + } + + for (int j = 1; j < outputSlots.length; j++) { + var nextItem = outputSlots[(i + j) % outputSlots.length].getItem(); + if (!nextItem.isEmpty()) { + newOutputs[i] = nextItem.copy(); + break; + } + } + } + + for (int i = 0; i < newOutputs.length; i++) { + outputSlots[i].set(newOutputs[i]); + } + } +} diff --git a/src/main/resources/assets/ae2/screens/terminals/encoding/eaep_pattern_terminals.json b/src/main/resources/assets/ae2/screens/terminals/encoding/eaep_pattern_terminals.json new file mode 100644 index 0000000..5c25b31 --- /dev/null +++ b/src/main/resources/assets/ae2/screens/terminals/encoding/eaep_pattern_terminals.json @@ -0,0 +1,37 @@ +{ + "$schema": "../../schema.json", + "widgets": { + "zhu_fu_qie_huan": { + "left": 127, + "bottom": 159 + }, + "huan_yuan_mo_ren": { + "left": 103, + "bottom": 159 + }, + "cheng_2": { + "left": 127, + "bottom": 149 + }, + "cheng_3": { + "left": 127, + "bottom": 138 + }, + "cheng_5": { + "left": 127, + "bottom": 127 + }, + "chu_2": { + "left": 103, + "bottom": 149 + }, + "chu_3": { + "left": 103, + "bottom": 138 + }, + "chu_5": { + "left": 103, + "bottom": 127 + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ae2/screens/terminals/pattern_encoding_terminal.json b/src/main/resources/assets/ae2/screens/terminals/pattern_encoding_terminal.json new file mode 100644 index 0000000..4c18cf1 --- /dev/null +++ b/src/main/resources/assets/ae2/screens/terminals/pattern_encoding_terminal.json @@ -0,0 +1,118 @@ +{ + "$schema": "../schema.json", + "includes": [ + "terminal.json", + "encoding/crafting.json", + "encoding/processing.json", + "encoding/smithing_table.json", + "encoding/stonecutting.json", + "encoding/eaep_pattern_terminals.json" + ], + "helpTopic": "items-blocks-machines/terminals.md#pattern-encoding-terminal-ui", + "slots": { + "BLANK_PATTERN": { + "left": 147, + "bottom": 165 + }, + "ENCODED_PATTERN": { + "left": 147, + "bottom": 118 + } + }, + "text": { + "dialog_title": { + "text": { + "translate": "gui.ae2.Terminal" + }, + "position": { + "left": 8, + "top": 6 + } + }, + "crafting_grid_title": { + "text": { + "translate": "gui.ae2.PatternEncoding" + }, + "position": { + "left": 8, + "bottom": 177 + } + } + }, + "terminalStyle": { + "header": { + "texture": "guis/pattern.png", + "srcRect": [0, 0, 195, 17] + }, + "firstRow": { + "texture": "guis/pattern.png", + "srcRect": [0, 17, 195, 18] + }, + "row": { + "texture": "guis/pattern.png", + "srcRect": [0, 35, 195, 18] + }, + "lastRow": { + "texture": "guis/pattern.png", + "srcRect": [0, 53, 195, 18] + }, + "bottom": { + "texture": "guis/pattern.png", + "srcRect": [0, 71, 195, 180] + } + }, + "widgets": { + "modeTabButton0": { + "left": 173, + "bottom": 174, + "width": 22, + "height": 22 + }, + "modeTabButton1": { + "left": 173, + "bottom": 153, + "width": 22, + "height": 22 + }, + "modeTabButton2": { + "left": 173, + "bottom": 132, + "width": 22, + "height": 22 + }, + "modeTabButton3": { + "left": 173, + "bottom": 111, + "width": 22, + "height": 22 + }, + "modePanel0": { + "left": 9, + "bottom": 166 + }, + "modePanel1": { + "left": 9, + "bottom": 166 + }, + "modePanel2": { + "left": 9, + "bottom": 166 + }, + "modePanel3": { + "left": 9, + "bottom": 166 + }, + "modePanel4": { + "left": 9, + "bottom": 166 + }, + "modePanel5": { + "left": 9, + "bottom": 166 + }, + "encodePattern": { + "left": 147, + "bottom": 145 + } + } +} diff --git a/src/main/resources/assets/extendedae_plus/textures/gui/beizeng.png b/src/main/resources/assets/extendedae_plus/textures/gui/beizeng.png new file mode 100644 index 0000000000000000000000000000000000000000..820a4f7a1bf6592ae764a88d460819049607fde0 GIT binary patch literal 345 zcmV-f0jBPx$6G=otR9J=Wm&*}^APk1V@l0n_U;$RJRcr-YfEC!84Y;T51jIaG5Z&Rwq50y( zJOE?5+RAbU+qUhg=gv8ny@DSkPVTJHpeP|Kyq>0404&S<;G`xGHnE?B1DvXOP1)Aw zDPIOM0MUUVj+TN!HTg3?kR6*c!l~0VVGBO!f%s2IYmnkKJ&?;6)gZ@nwxxW~10YQe za=fMoa`?w@WFzN*oWBCK=DWJOZm!3V(IGaLY&_J*uIAPIK=Le7kw5d3l=t)Q{j56o z)aJRY1UH~q&N(Zo;gkLL6i_!&*PI@vH3=F~- Wjb`XSk68+|l)=;0&t;ucLK6TDXFOT} literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/extendedae_plus/textures/gui/zhu_fu_qie_huan.png b/src/main/resources/assets/extendedae_plus/textures/gui/zhu_fu_qie_huan.png new file mode 100644 index 0000000000000000000000000000000000000000..a619a9679a944cb777568f07562259c996e200b0 GIT binary patch literal 224 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|W_h|ehFJI? zoqUnEL4n65kxo90+U%XnvVS66wf?wh(vKaBmcHLBuc`WZ zPDwCBmrVzkL-{)%fzuZmCL|R({=RgPcR{Cjq;vM~rwuWM9b647uIWyYI5cNEbG4DU zXak?X0^{>eyW65a@H@=@zgVC$;2QVSgNxEC*o`|xRx?P=eCFVHlx5G)1@H1dC#aW3 WrVHwqx?KmllEKr}&t;ucLK6V35mDs; literal 0 HcmV?d00001 diff --git a/src/main/resources/extendedae_plus.mixins.json b/src/main/resources/extendedae_plus.mixins.json index ad76aee..85c6487 100644 --- a/src/main/resources/extendedae_plus.mixins.json +++ b/src/main/resources/extendedae_plus.mixins.json @@ -14,6 +14,7 @@ "ae2.client.gui.CraftConfirmScreenMixin", "ae2.client.gui.InterfaceScreenMixin", "ae2.client.gui.PatternEncodingTermScreenMixin", + "ae2.client.gui.PatternEncodingTermScaleButtonsMixin", "ae2.client.gui.SlotGridLayoutMixin", "ae2.client.gui.patternProvider.PatternProviderHighlightCleanupMixin", "ae2.client.gui.patternProvider.PatternProviderScreenMixin",