diff --git a/src/generated/resources/assets/gtceu/lang/en_us.json b/src/generated/resources/assets/gtceu/lang/en_us.json index 3690217e840..350cc838ec2 100644 --- a/src/generated/resources/assets/gtceu/lang/en_us.json +++ b/src/generated/resources/assets/gtceu/lang/en_us.json @@ -2056,6 +2056,8 @@ "cover.ender_fluid_link.tooltip.clear_button": "Clear channel description", "cover.ender_fluid_link.tooltip.list_button": "Show channel list", "cover.ender_item_link.title": "Ender Item Link", + "cover.ender_link.channel_description": "Channel description", + "cover.ender_link.channel_name": "Channel name", "cover.ender_redstone_link.title": "Ender Redstone Link", "cover.filter.blacklist.disabled": "Whitelist", "cover.filter.blacklist.enabled": "Blacklist", diff --git a/src/main/java/com/gregtechceu/gtceu/api/misc/virtualregistry/entries/VirtualTank.java b/src/main/java/com/gregtechceu/gtceu/api/misc/virtualregistry/entries/VirtualTank.java index b142de09b9a..fcd28c77dba 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/misc/virtualregistry/entries/VirtualTank.java +++ b/src/main/java/com/gregtechceu/gtceu/api/misc/virtualregistry/entries/VirtualTank.java @@ -41,7 +41,10 @@ public void setFluid(FluidStack fluid) { @Override public boolean equals(Object o) { if (!(o instanceof VirtualTank other)) return false; - return this.fluidTank == other.fluidTank; + + if (this.fluidTank.getCapacity() != other.fluidTank.getCapacity()) return false; + if (!this.fluidTank.getFluid().equals(other.fluidTank.getFluid())) return false; + return true; } @Override diff --git a/src/main/java/com/gregtechceu/gtceu/api/mui/value/sync/DynamicLinkedSyncHandler.java b/src/main/java/com/gregtechceu/gtceu/api/mui/value/sync/DynamicLinkedSyncHandler.java index a950cbedc5e..e75a54f1498 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/mui/value/sync/DynamicLinkedSyncHandler.java +++ b/src/main/java/com/gregtechceu/gtceu/api/mui/value/sync/DynamicLinkedSyncHandler.java @@ -17,7 +17,6 @@ public class DynamicLinkedSyncHandler> extends Syn private IWidgetProvider widgetProvider; private Consumer onWidgetUpdate; - private boolean updateQueued; private IWidget lastRejectedWidget; private final S linkedValue; @@ -45,10 +44,7 @@ public void readOnServer(int id, FriendlyByteBuf buf) { @Override public void init(String key, PanelSyncManager syncManager) { super.init(key, syncManager); - if (this.updateQueued) { - notifyUpdate(true); - this.updateQueued = false; - } + notifyUpdate(false); } private IWidget parseWidget() { @@ -61,7 +57,7 @@ private IWidget parseWidget() { int unregistered = WidgetTree.countUnregisteredSyncHandlers(widget); if (unregistered > 0) { throw new IllegalStateException( - "Widgets created by DynamicSyncHandler can't have implicitly registered sync handlers. All" + + "Widgets created by DynamicSyncHandler can't have implicitly registered sync handlers. All " + "sync handlers must be registered with a variant of 'PanelSyncManager#getOrCreateSyncHandler(...)'."); } return widget; @@ -86,11 +82,7 @@ private void updateWidget(IWidget widget) { * initialised is effective. */ private void notifyUpdate(boolean sync) { - if (!isValid()) { - // sync handler not yet initialised - this.updateQueued = true; - return; - } + if (!isValid()) return; IWidget widget = parseWidget(); if (getSyncManager().isClient()) { updateWidget(widget); diff --git a/src/main/java/com/gregtechceu/gtceu/api/mui/value/sync/DynamicSyncHandler.java b/src/main/java/com/gregtechceu/gtceu/api/mui/value/sync/DynamicSyncHandler.java index 423b15f7f08..eb7c8d760a5 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/mui/value/sync/DynamicSyncHandler.java +++ b/src/main/java/com/gregtechceu/gtceu/api/mui/value/sync/DynamicSyncHandler.java @@ -66,7 +66,7 @@ private IWidget parseWidget(FriendlyByteBuf buf) { if (unregistered > 0) { throw new IllegalStateException( "Widgets created by DynamicSyncHandler can't have implicitly registered sync" + - " handlers. All sync handlers must be regisered witha variant of 'PanelSyncManager#getOrCreateSyncHandler(...)'."); + " handlers. All sync handlers must be registered with a variant of 'PanelSyncManager#getOrCreateSyncHandler(...)'."); } return widget; } diff --git a/src/main/java/com/gregtechceu/gtceu/api/mui/value/sync/GenericListSyncHandler.java b/src/main/java/com/gregtechceu/gtceu/api/mui/value/sync/GenericListSyncHandler.java index 487df9ccb23..3612b4374f3 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/mui/value/sync/GenericListSyncHandler.java +++ b/src/main/java/com/gregtechceu/gtceu/api/mui/value/sync/GenericListSyncHandler.java @@ -54,7 +54,8 @@ public List getValue() { @Override public void read(FriendlyByteBuf buffer) { this.cache.clear(); - for (int i = 0; i < buffer.readVarInt(); i++) { + int size = buffer.readVarInt(); + for (int i = 0; i < size; i++) { this.cache.add(deserializeValue(buffer)); } onSetCache(getValue(), true, false); diff --git a/src/main/java/com/gregtechceu/gtceu/common/cover/ender/AbstractEnderLinkCover.java b/src/main/java/com/gregtechceu/gtceu/common/cover/ender/AbstractEnderLinkCover.java index 9532f234cc1..42bae084677 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/cover/ender/AbstractEnderLinkCover.java +++ b/src/main/java/com/gregtechceu/gtceu/common/cover/ender/AbstractEnderLinkCover.java @@ -5,53 +5,73 @@ import com.gregtechceu.gtceu.api.capability.recipe.IO; import com.gregtechceu.gtceu.api.cover.CoverBehavior; import com.gregtechceu.gtceu.api.cover.CoverDefinition; -import com.gregtechceu.gtceu.api.cover.IUICover; +import com.gregtechceu.gtceu.api.cover.IMuiCover; import com.gregtechceu.gtceu.api.cover.filter.FilterHandler; -import com.gregtechceu.gtceu.api.gui.GuiTextures; -import com.gregtechceu.gtceu.api.gui.widget.ColorBlockWidget; -import com.gregtechceu.gtceu.api.gui.widget.ConfirmTextInputWidget; -import com.gregtechceu.gtceu.api.gui.widget.EnumSelectorWidget; -import com.gregtechceu.gtceu.api.gui.widget.ToggleButtonWidget; import com.gregtechceu.gtceu.api.machine.ConditionalSubscriptionHandler; import com.gregtechceu.gtceu.api.machine.MachineCoverContainer; import com.gregtechceu.gtceu.api.misc.virtualregistry.EntryTypes; import com.gregtechceu.gtceu.api.misc.virtualregistry.VirtualEnderRegistry; import com.gregtechceu.gtceu.api.misc.virtualregistry.VirtualEntry; -import com.gregtechceu.gtceu.api.misc.virtualregistry.entries.VirtualTank; +import com.gregtechceu.gtceu.api.mui.base.drawable.IDrawable; +import com.gregtechceu.gtceu.api.mui.base.drawable.IKey; +import com.gregtechceu.gtceu.api.mui.base.widget.IWidget; +import com.gregtechceu.gtceu.api.mui.drawable.Rectangle; +import com.gregtechceu.gtceu.api.mui.drawable.UITexture; +import com.gregtechceu.gtceu.api.mui.factory.SidedPosGuiData; +import com.gregtechceu.gtceu.api.mui.utils.Color; +import com.gregtechceu.gtceu.api.mui.utils.MouseData; +import com.gregtechceu.gtceu.api.mui.value.BoolValue; +import com.gregtechceu.gtceu.api.mui.value.sync.BooleanSyncValue; +import com.gregtechceu.gtceu.api.mui.value.sync.DynamicLinkedSyncHandler; +import com.gregtechceu.gtceu.api.mui.value.sync.EnumSyncValue; +import com.gregtechceu.gtceu.api.mui.value.sync.GenericListSyncHandler; +import com.gregtechceu.gtceu.api.mui.value.sync.GenericSyncValue; +import com.gregtechceu.gtceu.api.mui.value.sync.IntSyncValue; +import com.gregtechceu.gtceu.api.mui.value.sync.PanelSyncManager; +import com.gregtechceu.gtceu.api.mui.value.sync.StringSyncValue; +import com.gregtechceu.gtceu.api.mui.widget.EmptyWidget; +import com.gregtechceu.gtceu.api.mui.widget.ParentWidget; +import com.gregtechceu.gtceu.api.mui.widgets.ButtonWidget; +import com.gregtechceu.gtceu.api.mui.widgets.CycleButtonWidget; +import com.gregtechceu.gtceu.api.mui.widgets.DynamicSyncedWidget; +import com.gregtechceu.gtceu.api.mui.widgets.ListWidget; +import com.gregtechceu.gtceu.api.mui.widgets.ToggleButton; +import com.gregtechceu.gtceu.api.mui.widgets.layout.Flow; +import com.gregtechceu.gtceu.api.mui.widgets.textfield.TextFieldWidget; import com.gregtechceu.gtceu.api.sync_system.annotations.RerenderOnChanged; import com.gregtechceu.gtceu.api.sync_system.annotations.SaveField; import com.gregtechceu.gtceu.api.sync_system.annotations.SyncToClient; +import com.gregtechceu.gtceu.client.mui.screen.UISettings; import com.gregtechceu.gtceu.common.cover.data.ManualIOMode; +import com.gregtechceu.gtceu.common.mui.GTGuiTextures; +import com.gregtechceu.gtceu.utils.serialization.network.ByteBufAdapters; +import com.gregtechceu.gtceu.utils.serialization.network.IByteBufAdapter; -import com.lowdragmc.lowdraglib.gui.editor.ColorPattern; -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.widget.*; - -import net.minecraft.ChatFormatting; import net.minecraft.core.Direction; import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.item.ItemStack; import lombok.Getter; -import org.apache.commons.lang3.mutable.MutableBoolean; -import org.jetbrains.annotations.Contract; +import lombok.Setter; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.nio.charset.StandardCharsets; import java.util.*; +import java.util.function.IntSupplier; import java.util.regex.Pattern; @SuppressWarnings("SameParameterValue") public abstract class AbstractEnderLinkCover extends CoverBehavior - implements IUICover, IControllable { + implements IMuiCover, IControllable { public static final Pattern COLOR_INPUT_PATTERN = Pattern.compile("^[0-9a-fA-F]{0,8}$"); protected final ConditionalSubscriptionHandler subscriptionHandler; + @Getter @SaveField @SyncToClient protected String colorStr = VirtualEntry.DEFAULT_COLOR; @@ -71,9 +91,9 @@ public abstract class AbstractEnderLinkCover extends Cov @SyncToClient @RerenderOnChanged protected IO io = IO.OUT; - protected VirtualEntryWidget virtualEntryWidget; - @SyncToClient - boolean isAnyChanged = false; + @Getter + @Setter + private boolean isChannelListActive; public AbstractEnderLinkCover(CoverDefinition definition, ICoverable coverHolder, Direction attachedSide) { super(definition, coverHolder, attachedSide); @@ -98,7 +118,7 @@ public void onAttached(@NotNull ItemStack itemStack, @Nullable ServerPlayer play public void onRemoved() { super.onRemoved(); subscriptionHandler.unsubscribe(); - if (!isRemote()) { + if (!coverHolder.isRemote()) { VirtualEnderRegistry.getInstance() .deleteEntryIf(getOwner(), getEntryType(), getChannelName(), VirtualEntry::canRemove); } @@ -108,17 +128,12 @@ public void onRemoved() { public void onUnload() { super.onUnload(); subscriptionHandler.unsubscribe(); - if (!isRemote()) { + if (!coverHolder.isRemote()) { VirtualEnderRegistry.getInstance() .deleteEntryIf(getOwner(), getEntryType(), getChannelName(), VirtualEntry::canRemove); } } - @Override - public void onUIClosed() { - virtualEntryWidget = null; - } - @Override public void setWorkingEnabled(boolean isWorkingAllowed) { if (this.isWorkingEnabled != isWorkingAllowed) { @@ -128,9 +143,189 @@ public void setWorkingEnabled(boolean isWorkingAllowed) { } @Override - public Widget createUIWidget() { - virtualEntryWidget = new VirtualEntryWidget(this); - return virtualEntryWidget; + public ParentWidget createCoverUI(SidedPosGuiData data, PanelSyncManager syncManager, UISettings settings) { + var isChannelListActive = new BooleanSyncValue(this::isChannelListActive, this::setChannelListActive); + syncManager.syncValue("CLA", isChannelListActive); + var colorSyncer = new IntSyncValue(this::getColor); + syncManager.syncValue("color", colorSyncer); + + var entries = new GenericListSyncHandler.Builder() + .getter(this::getVirtualEntries) + .setter(this::setVirtualEntries) + .adapter(new VirtualEntryAdapter()) + .build(); + syncManager.syncValue("entries", entries); + + // TODO: Find out of this is needed + var owner = new GenericSyncValue.Builder<>(UUID.class) + .getter(() -> getOwner()) + .adapter(ByteBufAdapters.UUID) + .build(); + syncManager.syncValue("owner", owner); + + syncManager.registerServerSyncedAction("deleteDescription", (packet) -> { + var colorString = packet.readCharSequence(8, StandardCharsets.UTF_8).toString(); + VirtualEnderRegistry.getInstance().getEntry(getOwner(), getEntryType(), colorString).setDescription(""); + }); + + return Flow.column() + .child(new ToggleButton().value(BoolValue.wrap(isChannelListActive)) + .overlay(GTGuiTextures.MORE) + .tooltip(t -> t + .addLine(Component.translatable("cover.ender_fluid_link.tooltip.list_button"))) + .marginLeft(4) + .size(16, 16)) + .child(createChannelNameRow(syncManager, colorSyncer).setEnabledIf(f -> !isChannelListActive.getBoolValue())) + .child(createDescriptionField().setEnabledIf(f -> !isChannelListActive.getBoolValue())) + .child(createSettingsRow().setEnabledIf(f -> !isChannelListActive.getBoolValue())) + .child(createChannelList(entries).setEnabledIf(f -> isChannelListActive.getBoolValue())) + .rightRel(0.5F) + .top(3) + .childPadding(3) + .collapseDisabledChild() + .coverChildren(); + } + + public DynamicSyncedWidget createChannelList(GenericListSyncHandler entriesSyncer) { + DynamicLinkedSyncHandler> dynamicLinkedSyncHandler = new DynamicLinkedSyncHandler<>( + entriesSyncer) + .widgetProvider((manager, entriesListSyncer) -> { + if (entriesListSyncer == null || entriesListSyncer.getValue() == null) return new EmptyWidget(); + ListWidget list = new ListWidget<>(); + List entryList = entriesListSyncer.getValue(); + for (var i = 0; i < entryList.size(); i++) { + var entry = entryList.get(i); + list.child(createVirtualEntryRow(manager, entry, i)); + } + return list.childSeparator(GTGuiTextures.SEPERATOR_SIMPLE.asIcon().size(116, 5).margin(12, 0)) + .size(162, 58); + }); + return new DynamicSyncedWidget<>().syncHandler(dynamicLinkedSyncHandler).size(162, 58); + } + + public Flow createVirtualEntryRow(PanelSyncManager syncManager, VirtualEntry entry, int index) { + return Flow.row() + .child(createColorBlock(entry::getColor, 18).asWidget() + .tooltip(t -> t.addLine(entry.getColorStr())) + .size(18, 18)) + .child(IKey.str(entry.getDescription()).asWidget().size(92, 12)) + .child(createVirtualEntryWidget(syncManager, entry, 18, 18, index)) + .child(new ButtonWidget<>().overlay(GTGuiTextures.BUTTON_CROSS) + .onMousePressed((x, y, button) -> { + MouseData mouseData = MouseData.create(button); + if (mouseData.mouseButton() == 1) { + syncManager.callSyncedAction("deleteDescription", buffer -> { + buffer.writeCharSequence(entry.getColorStr(), StandardCharsets.UTF_8); + }); + return true; + } + return false; + })) + .alignX(0F) + .childPadding(3) + .coverChildren(); + } + + public Flow createChannelNameRow(PanelSyncManager syncManager, IntSyncValue colorSyncer) { + return Flow.row() + .child(createColorBlock(colorSyncer::getIntValue, 18).asWidget().size(18).marginRight(3)) + .child(new TextFieldWidget().value(new StringSyncValue(this::getColorStr, this::setChannelName)) + .setPattern(COLOR_INPUT_PATTERN) + .setValidator(String::toUpperCase) + .hintText(Component.translatable("cover.ender_link.channel_name")) + // .expanded() + .height(16)) + .child(createVirtualEntryWidget(syncManager, this.getEntry(), 18, 18, -1)) + .size(162, 18); + } + + public Flow createDescriptionField() { + return Flow.row() + .child(new TextFieldWidget() + .value(new StringSyncValue(() -> { + if (getEntry() == null) return "null"; + return getEntry().getDescription(); + }, (newVal) -> { + if (getEntry() != null) getEntry().setDescription(newVal); + })) + .hintText(Component.translatable("cover.ender_link.channel_description")) + .widthRel(1F) + .height(16)) + .widthRel(1F) + .coverChildrenHeight(); + } + + public Flow createSettingsRow() { + return Flow.row() + // Power button + .child(new ToggleButton().value(new BooleanSyncValue(this::isWorkingEnabled, this::setWorkingEnabled)) + // TODO: once the branch that has power overlays defined in GTGuiTextures is merged, we need to + // TODO: replace this temporary usage with those. or keep them. they are pretty cool + .overlay(false, GTGuiTextures.PLAY) + .overlay(true, GTGuiTextures.PLAY)) + // Import / Export button + .child(new CycleButtonWidget() + // There are "3" states here because otherwise there is a noticeable lag on the client when it + // goes from OUT to IN and initially doesn't know to go back to IN (because the enum has 4 + // states) so it displays no overlay or tooltip. Very annoying. + .stateCount(3) + .stateOverlay(IO.IN, GTGuiTextures.IO_IMPORT) + .stateOverlay(IO.OUT, GTGuiTextures.IO_EXPORT) + .stateOverlay(IO.BOTH, GTGuiTextures.IO_IMPORT) + .tooltip(0, t -> t.addLine(Component.translatable(IO.IN.tooltip))) + .tooltip(1, t -> t.addLine(Component.translatable(IO.OUT.tooltip))) + .tooltip(2, t -> t.addLine(Component.translatable(IO.IN.tooltip))) + .value(new EnumSyncValue<>(IO.class, this::getIo, this::reverseIO))) + // Public / Private button + .child(new CycleButtonWidget() + .stateCount(2) + .stateOverlay(Permissions.PUBLIC, Permissions.PUBLIC.icon) + .stateOverlay(Permissions.PRIVATE, Permissions.PRIVATE.icon) + .tooltip(0, t -> t.addLine(IKey.lang(Permissions.PUBLIC.tooltip + ".0")) + .addLine(IKey.lang(Permissions.PUBLIC.tooltip + ".1"))) + .tooltip(1, t -> t.addLine(IKey.lang(Permissions.PRIVATE.tooltip))) + .value(new EnumSyncValue<>(Permissions.class, this::getPermission, + this::setPermission))) + // Manual IO button + .child(new CycleButtonWidget() + .stateCount(3) + .stateOverlay(ManualIOMode.DISABLED, GTGuiTextures.MANUAL_IO_DISABLED) + .stateOverlay(ManualIOMode.FILTERED, GTGuiTextures.MANUAL_IO_FILTERED) + .stateOverlay(ManualIOMode.UNFILTERED, GTGuiTextures.MANUAL_IO_UNFILTERED) + .tooltip(0, t -> t.addLine(Component.translatable(ManualIOMode.DISABLED.getTooltip()))) + .tooltip(1, t -> t.addLine(Component.translatable(ManualIOMode.FILTERED.getTooltip()))) + .tooltip(2, t -> t.addLine(Component.translatable(ManualIOMode.UNFILTERED.getTooltip()))) + .value(new EnumSyncValue<>(ManualIOMode.class, this::getManualIOMode, this::setManualIOMode))) + // TODO: Add Filter slot here once kathryne's ui gets merged + .child(new ToggleButton().overlay(GTGuiTextures.EXCLAMATION) + .size(18, 18)) + .childPadding(18) + .widthRel(1F) + .coverChildrenHeight(); + } + + public IDrawable createColorBlock(IntSupplier colorSupplier, int size) { + return IDrawable.of( + // Border + (context, x, y, w, h, widgetTheme) -> new Rectangle().color(Color.BLACK.main) + .draw(context, x, y, size, size, widgetTheme), + // Colored block + (context, x, y, w, h, widgetTheme) -> new Rectangle().color(colorSupplier.getAsInt()) + .draw(context, x + 1, y + 1, size - 2, size - 2, widgetTheme)); + } + + public List getVirtualEntries() { + List entries = new ArrayList<>(); + for (String entryName : VirtualEnderRegistry.getInstance().getEntryNames(getOwner(), getEntryType())) { + entries.add(VirtualEnderRegistry.getInstance().getEntry(getOwner(), getEntryType(), entryName)); + } + return entries; + } + + public void setVirtualEntries(List entries) {} + + private void reverseIO(IO io) { + setIo(IO.values()[io.ordinal() % 2]); } public void setIo(IO io) { @@ -164,10 +359,13 @@ protected final String getChannelName() { } protected void setChannelName(String name) { - if (isRemote()) return; + if (coverHolder.isRemote()) return; VirtualEnderRegistry.getInstance().deleteEntryIf(getOwner(), getEntryType(), getChannelName(), VirtualEntry::canRemove); this.colorStr = name; + if (colorStr.length() < 8) { + colorStr += "F".repeat(8 - colorStr.length()); + } syncDataHolder.markClientSyncFieldDirty("colorStr"); setVirtualEntry(); } @@ -177,7 +375,7 @@ protected final String getChannelName(VirtualEntry entry) { } protected void setPermission(Permissions permission) { - if (isRemote()) return; + if (coverHolder.isRemote()) return; VirtualEnderRegistry.getInstance().deleteEntryIf(getOwner(), getEntryType(), getChannelName(), VirtualEntry::canRemove); this.permission = permission; @@ -189,8 +387,6 @@ protected void setPermission(Permissions permission) { protected void setVirtualEntry() { setEntry(VirtualEnderRegistry.getInstance().getOrCreateEntry(getOwner(), getEntryType(), getChannelName())); getEntry().setColor(this.colorStr); - syncDataHolder.markClientSyncFieldDirty("isAnyChanged"); - this.isAnyChanged = true; subscriptionHandler.updateSubscription(); } @@ -200,7 +396,7 @@ protected void update() { long timer = coverHolder.getOffsetTimer(); if (timer % 5 != 0) return; - if (isWorkingEnabled() && !isRemote()) { + if (isWorkingEnabled() && !coverHolder.isRemote()) { var entry = VirtualEnderRegistry.getInstance().getOrCreateEntry(getOwner(), getEntryType(), getChannelName()); if (!entry.getColorStr().equals(this.colorStr)) { @@ -211,11 +407,6 @@ protected void update() { } transfer(); } - - if (isAnyChanged) { - if (virtualEntryWidget != null) virtualEntryWidget.update(); - isAnyChanged = false; - } subscriptionHandler.updateSubscription(); } @@ -232,281 +423,81 @@ protected void setManualIOMode(ManualIOMode manualIOMode) { return null; } - protected abstract Widget addVirtualEntryWidget(VirtualEntry entry, int x, int y, int width, int height, - boolean canClick); - - protected abstract String getUITitle(); + /** + * All syncers registered through this method MUST use the {@link PanelSyncManager#getOrCreateSyncHandler} method + * for applying a syncer to a widget because it gets placed into a {@link DynamicSyncedWidget}. + * + * @return A widget to represent the entry type for this cover + */ + protected abstract IWidget createVirtualEntryWidget(PanelSyncManager manager, VirtualEntry entry, int w, int h, + int index); protected int getColor() { return VirtualEntry.parseColor(this.colorStr); } - protected enum Permissions implements EnumSelectorWidget.SelectableEnum { - - PUBLIC("cover.ender_fluid_link.private.tooltip.disabled", - GuiTextures.BUTTON_PUBLIC_PRIVATE.getSubTexture(0, 0, 1, 0.5)), + protected enum Permissions { - PRIVATE("cover.ender_fluid_link.private.tooltip.enabled", - GuiTextures.BUTTON_PUBLIC_PRIVATE.getSubTexture(0, 0.5, 1, 0.5)); + PUBLIC("cover.ender_fluid_link.private.tooltip.disabled", GTGuiTextures.OVERLAY_LOCK_OPEN), + PRIVATE("cover.ender_fluid_link.private.tooltip.enabled", GTGuiTextures.OVERLAY_LOCK_CLOSED); @Getter private final String tooltip; @Getter - private final IGuiTexture icon; + private final UITexture icon; - Permissions(String tooltip, IGuiTexture icon) { + Permissions(String tooltip, UITexture icon) { this.tooltip = tooltip; this.icon = icon; } } - protected static class VirtualEntryWidget extends WidgetGroup { - - private static final int WIDGET_BOARD = 20; - private static final int GROUP_WIDTH = 176; - private static final int TOTAL_WIDTH = 156; - private static final int BUTTON_SIZE = 16; - private final AbstractEnderLinkCover cover; - private final MutableBoolean showChannels; - private final WidgetGroup mainGroup; - private final WidgetGroup mainChannelGroup; - private final DraggableScrollableWidgetGroup channelsGroup; // client only - - VirtualEntryWidget(AbstractEnderLinkCover cover) { - super(0, 0, GROUP_WIDTH, 137); - this.cover = cover; - this.showChannels = new MutableBoolean(false); - mainGroup = new WidgetGroup(0, 0, GROUP_WIDTH, 137); - channelsGroup = new DraggableScrollableWidgetGroup(0, 20, 170, 110) - .setYScrollBarWidth(2).setYBarStyle(null, ColorPattern.T_WHITE.rectTexture().setRadius(1)); - mainChannelGroup = new WidgetGroup(10, 20, 156, 20); - initWidgets(); - } - - public void update() { - if (isRemote()) return; - widgets.clear(); - mainGroup.widgets.clear(); - channelsGroup.widgets.clear(); - mainChannelGroup.widgets.clear(); - initWidgets(); - this.detectAndSendChanges(); - } + private class VirtualEntryListAdapter implements IByteBufAdapter> { - private void initWidgets() { - int currentX = 0; - final var titleGroup = new WidgetGroup(10, 5, GROUP_WIDTH, 20); - - this.addWidget(titleGroup); - this.addWidget(mainGroup); - this.addWidget(channelsGroup.setVisible(false)); - - titleGroup.addWidget(createToggleButton()); - titleGroup.addWidget(new LabelWidget(15, 3, cover.getUITitle())); - - var toggleButtonWidget = createToggleButtonForPrivacy(currentX); - mainChannelGroup.addWidget(toggleButtonWidget); - currentX += WIDGET_BOARD + 2; - mainChannelGroup.addWidget(createColorBlockWidget(currentX)); - currentX += WIDGET_BOARD + 2; - mainChannelGroup.addWidget(createConfirmTextInputWidget(currentX)); - - mainChannelGroup.addWidget(new ConfirmTextInputWidget(0, WIDGET_BOARD + 2, GROUP_WIDTH - WIDGET_BOARD, - WIDGET_BOARD, cover.getEntry().getDescription(), cover.getEntry()::setDescription, - t -> t == null ? "" : t, null).setTooltip("cover.ender_fluid_link.tooltip.channel_description")); - - mainGroup.addWidget(mainChannelGroup); - mainGroup.addWidget(createWorkingEnabledButton()); - addEnumSelectorWidgets(); - mainGroup.addWidget( - cover.addVirtualEntryWidget(cover.getEntry(), 146, WIDGET_BOARD, WIDGET_BOARD, WIDGET_BOARD, true)); - - if (cover.getFilterHandler() != null) { - mainGroup.addWidget(cover.getFilterHandler().createFilterSlotUI(117, 108)); - mainGroup.addWidget(cover.getFilterHandler().createFilterConfigUI(10, 72, 156, 60)); + @Override + public List deserialize(FriendlyByteBuf buffer) { + List list = new ArrayList<>(); + int size = buffer.readInt(); + for (int i = 0; i < size; i++) { + VirtualEntry entry = getEntryType().createInstance(); + entry.deserializeNBT(buffer.readNbt()); + list.add(entry); } + return list; } - @Contract(" -> new") - private @NotNull ToggleButtonWidget createToggleButton() { - return (ToggleButtonWidget) new ToggleButtonWidget(0, 0, 12, 12, showChannels::getValue, cd -> { - showChannels.setValue(!showChannels.getValue()); - mainGroup.setVisible(showChannels.isFalse()); - channelsGroup.setVisible(showChannels.isTrue()); - requestUpdate(); - }).setTexture( - new GuiTextureGroup(GuiTextures.TOGGLE_BUTTON_BACK.getSubTexture(0, 0, 1, 0.5), - GuiTextures.BUTTON_LIST), - new GuiTextureGroup(GuiTextures.TOGGLE_BUTTON_BACK.getSubTexture(0, 0.5, 1, 0.5), - GuiTextures.BUTTON_LIST)) - .setHoverTooltips("cover.ender_fluid_link.tooltip.list_button"); - } - - @Contract("_ -> new") - private @NotNull Widget createToggleButtonForPrivacy(int currentX) { - return new EnumSelectorWidget<>(currentX, 0, - WIDGET_BOARD, WIDGET_BOARD, Permissions.values(), cover.permission, cover::setPermission); - } - - private ColorBlockWidget createColorBlockWidget(int currentX) { - return new ColorBlockWidget(currentX, 0, WIDGET_BOARD, WIDGET_BOARD).setColorSupplier(cover::getColor); - } - - private ConfirmTextInputWidget createConfirmTextInputWidget(int currentX) { - int GROUP_X = 10; - int textInputWidth = (GROUP_WIDTH - GROUP_X * 2) - currentX - WIDGET_BOARD - 2; - return new ConfirmTextInputWidget(currentX, 0, textInputWidth, WIDGET_BOARD, cover.colorStr, - cover::setChannelName, text -> { - if (text == null || !COLOR_INPUT_PATTERN.matcher(text).matches()) { - return VirtualTank.DEFAULT_COLOR; - } - return text; - }, text -> { - if (text.length() < 8) { - text += "F".repeat(8 - text.length()); - } - return text; - }).setTooltip("cover.ender_fluid_link.tooltip.channel_name"); - } - - @Contract(" -> new") - private @NotNull ToggleButtonWidget createWorkingEnabledButton() { - return new ToggleButtonWidget(116, 82, WIDGET_BOARD, WIDGET_BOARD, GuiTextures.BUTTON_POWER, - cover::isWorkingEnabled, cover::setWorkingEnabled); - } - - private void addEnumSelectorWidgets() { - mainGroup.addWidget(new EnumSelectorWidget<>(146, 82, WIDGET_BOARD, WIDGET_BOARD, List.of(IO.IN, IO.OUT), - cover.io, cover::setIo)); - mainGroup.addWidget(new EnumSelectorWidget<>(146, 107, WIDGET_BOARD, WIDGET_BOARD, ManualIOMode.VALUES, - cover.manualIOMode, cover::setManualIOMode) - .setHoverTooltips("cover.universal.manual_import_export.mode.description")); - } - - private void addChannelWidgets(List entries) { - channelsGroup.clearAllWidgets(); - int y = 1; - SelectableWidgetGroup selectedWidget = null; - for (var entry : entries.stream().sorted(Comparator.comparing(VirtualEntry::getColorStr)).toList()) { - SelectableWidgetGroup channelWidget = createChannelWidget(entry, 10, y); - if (cover.getChannelName(entry).equals(cover.getChannelName())) { - selectedWidget = channelWidget; - } - channelsGroup.addWidget(channelWidget); - y += 22; + @Override + public void serialize(FriendlyByteBuf buffer, List list) { + buffer.writeInt(list.size()); + for (VirtualEntry entry : list) { + buffer.writeNbt(entry.serializeNBT()); } - channelsGroup.setSelected(selectedWidget); - if (selectedWidget != null) selectedWidget.onSelected(); - channelsGroup.setClientSideWidget(); } - private @NotNull SelectableWidgetGroup createChannelWidget(@NotNull VirtualEntry entry, int x, int y) { - int currentX = 0; - int MARGIN = 2; - int availableWidth = TOTAL_WIDTH - (BUTTON_SIZE + MARGIN) * 3; - - final MutableBoolean canSelect = new MutableBoolean(false); - var des = entry.getDescription(); - TextBoxWidget textBoxWidget = new TextBoxWidget(BUTTON_SIZE + MARGIN, - !des.isEmpty() ? 0 : 4, availableWidth, List.of(entry.getColorStr())).setCenter(true); - SelectableWidgetGroup channelGroup = new SelectableWidgetGroup(x, y, TOTAL_WIDTH, BUTTON_SIZE) { - - @Override - public boolean allowSelected(double mouseX, double mouseY, int button) { - return canSelect.getValue() && super.allowSelected(mouseX, mouseY, button); - } - }; - channelGroup.setOnSelected(group -> { - if (cover.getChannelName().equals(cover.getChannelName(entry))) return; - writeClientAction(0, buffer -> { - // send new channel name to server - String newChannelColorStr = entry.getColorStr(); - buffer.writeUtf(newChannelColorStr); - }); - playButtonClickSound(); - }).setSelectedTexture(1, -1); - - // Color block - ColorBlockWidget colorBlockWidget = new ColorBlockWidget(currentX, 0, BUTTON_SIZE, BUTTON_SIZE) - .setCurrentColor(VirtualEntry.parseColor(entry.getColorStr())); - channelGroup.addWidget(colorBlockWidget); - currentX += BUTTON_SIZE + MARGIN; - - // Text box - channelGroup.addWidget(textBoxWidget); - currentX += availableWidth + MARGIN; - if (!des.isEmpty()) { - var desText = new TextTexture(ChatFormatting.DARK_GRAY + des).setDropShadow(false); - desText.setType(TextTexture.TextType.ROLL).setRollSpeed(0.7f); - channelGroup.addWidget(new ImageWidget(BUTTON_SIZE + MARGIN, 10, availableWidth, 8, desText)); - } - - // Slot - Widget slotWidget = cover.addVirtualEntryWidget(entry, currentX, 0, BUTTON_SIZE, BUTTON_SIZE, false); - channelGroup.addWidget(slotWidget); - currentX += BUTTON_SIZE + MARGIN; - - // Clear Description button - channelGroup.addWidget( - new ButtonWidget(currentX, 0, BUTTON_SIZE, BUTTON_SIZE, GuiTextures.BUTTON_CLEAR_GRID, press -> { - writeClientAction(200, buffer -> buffer.writeUtf(cover.getChannelName(entry))); - requestUpdate(); - }) { - - @Override - public boolean isMouseOverElement(double mouseX, double mouseY) { - var isOver = super.isMouseOverElement(mouseX, mouseY); - if (canSelect.getValue() == isOver) canSelect.setValue(!isOver); - return isOver; - } - }.appendHoverTooltips("cover.ender_fluid_link.tooltip.clear_button")); - - return channelGroup; + @Override + public boolean areEqual(@NotNull List t1, @NotNull List t2) { + if (t1.size() != t2.size()) return false; + return t1.equals(t2); } + } + + private class VirtualEntryAdapter implements IByteBufAdapter { - private void requestUpdate() { - writeClientAction(100, buffer -> buffer.writeBoolean(showChannels.isTrue())); + @Override + public VirtualEntry deserialize(FriendlyByteBuf buffer) { + VirtualEntry entry = getEntryType().createInstance(); + entry.deserializeNBT(buffer.readNbt()); + return entry; } @Override - public void handleClientAction(int id, FriendlyByteBuf buffer) { - super.handleClientAction(id, buffer); - if (id == 0) { - String newChannelColorStr = buffer.readUtf(); - cover.setChannelName(newChannelColorStr); - } else if (id == 100) { - if (!buffer.readBoolean()) return; - var entries = VirtualEnderRegistry.getInstance().getEntryNames(cover.getOwner(), cover.getEntryType()) - .stream().map(name -> VirtualEnderRegistry.getInstance().getEntry(cover.getOwner(), - cover.getEntryType(), name)) - .sorted(Comparator.comparing(VirtualEntry::getColorStr)); - writeUpdateInfo(101, buf -> { - var list = entries.toList(); - buf.writeVarInt(list.size()); - for (var entry : list) { - buf.writeNbt(entry.serializeNBT()); - } - }); - } else if (id == 200) { - String channelName = buffer.readUtf(); - VirtualEnderRegistry.getInstance().getEntry(cover.getOwner(), cover.getEntryType(), channelName) - .setDescription(""); - } + public void serialize(FriendlyByteBuf buffer, VirtualEntry entry) { + buffer.writeNbt(entry.serializeNBT()); } @Override - public void readUpdateInfo(int id, FriendlyByteBuf buffer) { - super.readUpdateInfo(id, buffer); - if (id == 101) { - int size = buffer.readVarInt(); - List entries = new ArrayList<>(); - for (int i = 0; i < size; i++) { - VirtualEntry entry = cover.getEntryType().createInstance(); - entry.deserializeNBT(Objects.requireNonNull(buffer.readNbt())); - entries.add(entry); - } - addChannelWidgets(entries); - } + public boolean areEqual(@NotNull VirtualEntry t1, @NotNull VirtualEntry t2) { + return t1.equals(t2); } } } diff --git a/src/main/java/com/gregtechceu/gtceu/common/cover/ender/EnderFluidLinkCover.java b/src/main/java/com/gregtechceu/gtceu/common/cover/ender/EnderFluidLinkCover.java index 3ad32ee9b38..32d0b2f8fc0 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/cover/ender/EnderFluidLinkCover.java +++ b/src/main/java/com/gregtechceu/gtceu/common/cover/ender/EnderFluidLinkCover.java @@ -5,12 +5,16 @@ import com.gregtechceu.gtceu.api.cover.filter.FilterHandler; import com.gregtechceu.gtceu.api.cover.filter.FilterHandlers; import com.gregtechceu.gtceu.api.cover.filter.FluidFilter; -import com.gregtechceu.gtceu.api.gui.GuiTextures; -import com.gregtechceu.gtceu.api.gui.widget.TankWidget; import com.gregtechceu.gtceu.api.misc.virtualregistry.EntryTypes; import com.gregtechceu.gtceu.api.misc.virtualregistry.VirtualEnderRegistry; import com.gregtechceu.gtceu.api.misc.virtualregistry.VirtualEntry; import com.gregtechceu.gtceu.api.misc.virtualregistry.entries.VirtualTank; +import com.gregtechceu.gtceu.api.mui.base.widget.IWidget; +import com.gregtechceu.gtceu.api.mui.value.sync.FluidSlotSyncHandler; +import com.gregtechceu.gtceu.api.mui.value.sync.PanelSyncManager; +import com.gregtechceu.gtceu.api.mui.value.sync.SyncHandlers; +import com.gregtechceu.gtceu.api.mui.widget.ParentWidget; +import com.gregtechceu.gtceu.api.mui.widgets.slot.FluidSlot; import com.gregtechceu.gtceu.api.sync_system.annotations.SaveField; import com.gregtechceu.gtceu.api.sync_system.annotations.SyncToClient; import com.gregtechceu.gtceu.api.transfer.fluid.IFluidHandlerModifiable; @@ -21,6 +25,8 @@ import net.minecraft.core.Direction; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.FluidUtil; +import net.minecraftforge.fluids.IFluidTank; +import net.minecraftforge.fluids.capability.IFluidHandler; import lombok.Getter; import org.jetbrains.annotations.NotNull; @@ -35,7 +41,50 @@ public class EnderFluidLinkCover extends AbstractEnderLinkCover { @SaveField @SyncToClient - protected VirtualTank visualTank; + protected VirtualTank visualTank = new VirtualTank(); + + // todo make this a proper class + protected final IFluidTank tankSwitchShim = new IFluidTank() { + + private IFluidTank getDelegate() { + return getEntry().getFluidTank(); + } + + @Override + public @NotNull FluidStack getFluid() { + return getDelegate().getFluid(); + } + + @Override + public int getFluidAmount() { + return getDelegate().getFluidAmount(); + } + + @Override + public int getCapacity() { + return getDelegate().getCapacity(); + } + + @Override + public boolean isFluidValid(FluidStack fluidStack) { + return getDelegate().isFluidValid(fluidStack); + } + + @Override + public int fill(FluidStack fluidStack, IFluidHandler.FluidAction fluidAction) { + return getDelegate().fill(fluidStack, fluidAction); + } + + @Override + public @NotNull FluidStack drain(int i, IFluidHandler.FluidAction fluidAction) { + return getDelegate().drain(i, fluidAction); + } + + @Override + public @NotNull FluidStack drain(FluidStack fluidStack, IFluidHandler.FluidAction fluidAction) { + return getDelegate().drain(fluidStack, fluidAction); + } + }; @Getter @SaveField @@ -51,6 +100,13 @@ public EnderFluidLinkCover(CoverDefinition definition, ICoverable coverHolder, D .getOrCreateEntry(getOwner(), EntryTypes.ENDER_FLUID, getChannelName())); } + @Override + public void onLoad() { + super.onLoad(); + if (!coverHolder.isRemote()) visualTank = VirtualEnderRegistry.getInstance() + .getOrCreateEntry(getOwner(), EntryTypes.ENDER_FLUID, getChannelName()); + } + @Override protected VirtualTank getEntry() { return visualTank; @@ -115,14 +171,23 @@ private int doTransferFluids(int platformTransferLimit) { ////////////////////////////////////// @Override - protected Widget addVirtualEntryWidget(VirtualEntry entry, int x, int y, int width, int height, boolean canClick) { - return new TankWidget(((VirtualTank) entry).getFluidTank(), 0, x, y, width, height, canClick, canClick) - .setBackground(GuiTextures.FLUID_SLOT); - } - - @NotNull - @Override - protected String getUITitle() { - return "cover.ender_fluid_link.title"; + protected IWidget createVirtualEntryWidget(PanelSyncManager manager, VirtualEntry entry, int w, int h, int index) { + if (!(entry instanceof VirtualTank tank)) return new ParentWidget<>().size(w, h); + + manager.getOrCreateSyncHandler("ender_link_cover_fluid_slot", index, FluidSlotSyncHandler.class, + () -> SyncHandlers.fluidSlot(index == -1 ? tankSwitchShim : tank.getFluidTank())); + + return new FluidSlot() + .syncHandler("ender_link_cover_fluid_slot", index) + .marginLeft(3) + .size(w, h) + // return new FluidSlot() + // .syncHandler(manager.getOrCreateSyncHandler( + // ModularSyncManager.AUTO_SYNC_PREFIX + coverDefinition.getId().getPath(), + // FluidSlotSyncHandler.class, + // () -> new FluidSlotSyncHandler(((VirtualTank) entry).getFluidTank()))) + // .marginLeft(3) + // .size(w, h) + ; } } diff --git a/src/main/java/com/gregtechceu/gtceu/common/cover/ender/EnderItemLinkCover.java b/src/main/java/com/gregtechceu/gtceu/common/cover/ender/EnderItemLinkCover.java index 8338b7e0e40..7839007f72f 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/cover/ender/EnderItemLinkCover.java +++ b/src/main/java/com/gregtechceu/gtceu/common/cover/ender/EnderItemLinkCover.java @@ -5,19 +5,20 @@ import com.gregtechceu.gtceu.api.cover.filter.FilterHandler; import com.gregtechceu.gtceu.api.cover.filter.FilterHandlers; import com.gregtechceu.gtceu.api.cover.filter.ItemFilter; -import com.gregtechceu.gtceu.api.gui.widget.SlotWidget; import com.gregtechceu.gtceu.api.misc.virtualregistry.EntryTypes; import com.gregtechceu.gtceu.api.misc.virtualregistry.VirtualEnderRegistry; import com.gregtechceu.gtceu.api.misc.virtualregistry.VirtualEntry; import com.gregtechceu.gtceu.api.misc.virtualregistry.entries.VirtualItemStorage; +import com.gregtechceu.gtceu.api.mui.base.widget.IWidget; +import com.gregtechceu.gtceu.api.mui.value.sync.PanelSyncManager; +import com.gregtechceu.gtceu.api.mui.widget.ParentWidget; +import com.gregtechceu.gtceu.api.mui.widgets.slot.ItemSlot; +import com.gregtechceu.gtceu.api.mui.widgets.slot.ModularSlot; import com.gregtechceu.gtceu.api.sync_system.SyncDataHolder; import com.gregtechceu.gtceu.api.sync_system.annotations.SaveField; import com.gregtechceu.gtceu.api.sync_system.annotations.SyncToClient; import com.gregtechceu.gtceu.utils.GTTransferUtils; -import com.lowdragmc.lowdraglib.gui.widget.Widget; -import com.lowdragmc.lowdraglib.gui.widget.WidgetGroup; - import net.minecraft.core.Direction; import net.minecraft.world.item.ItemStack; import net.minecraftforge.items.IItemHandler; @@ -49,6 +50,13 @@ public EnderItemLinkCover(CoverDefinition definition, ICoverable coverHolder, Di getChannelName())); } + @Override + public void onLoad() { + super.onLoad(); + if (!coverHolder.isRemote()) storage = VirtualEnderRegistry.getInstance().getOrCreateEntry(getOwner(), + EntryTypes.ENDER_ITEM, getChannelName()); + } + @Override public boolean canAttach() { return true; @@ -101,16 +109,13 @@ private int doTransferItems(int max) { } @Override - protected Widget addVirtualEntryWidget(VirtualEntry entry, int x, int y, int width, int height, boolean canClick) { - WidgetGroup group = new WidgetGroup(x, y, width, height); - for (int i = 0; i < ((VirtualItemStorage) entry).getHandler().getSlots(); i++) { - group.addWidget(new SlotWidget(((VirtualItemStorage) entry).getHandler(), i, 8 * i, 0, canClick, canClick)); - } - return group; - } - - @Override - protected String getUITitle() { - return "cover.ender_item_link.title"; + protected IWidget createVirtualEntryWidget(PanelSyncManager manager, VirtualEntry entry, int w, int h, int index) { + if (!(entry instanceof VirtualItemStorage itemStorage)) return new ParentWidget<>().size(w, h); + manager.getOrCreateSlot("ender_item_link_cover_" + index, 0, + () -> new ModularSlot(itemStorage.getHandler(), 0)); + return new ItemSlot() + .syncHandler("ender_item_link_cover_" + index) + .marginLeft(3) + .size(w, h); } } diff --git a/src/main/java/com/gregtechceu/gtceu/common/cover/ender/EnderRedstoneLinkCover.java b/src/main/java/com/gregtechceu/gtceu/common/cover/ender/EnderRedstoneLinkCover.java index d2f3d2c3d6e..826edc41204 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/cover/ender/EnderRedstoneLinkCover.java +++ b/src/main/java/com/gregtechceu/gtceu/common/cover/ender/EnderRedstoneLinkCover.java @@ -5,13 +5,13 @@ import com.gregtechceu.gtceu.api.misc.virtualregistry.EntryTypes; import com.gregtechceu.gtceu.api.misc.virtualregistry.VirtualEntry; import com.gregtechceu.gtceu.api.misc.virtualregistry.entries.VirtualRedstone; +import com.gregtechceu.gtceu.api.mui.base.widget.IWidget; +import com.gregtechceu.gtceu.api.mui.value.sync.PanelSyncManager; +import com.gregtechceu.gtceu.api.mui.widget.ParentWidget; import com.gregtechceu.gtceu.api.sync_system.SyncDataHolder; import com.gregtechceu.gtceu.api.sync_system.annotations.SaveField; import com.gregtechceu.gtceu.api.sync_system.annotations.SyncToClient; -import com.lowdragmc.lowdraglib.gui.widget.Widget; -import com.lowdragmc.lowdraglib.gui.widget.WidgetGroup; - import net.minecraft.core.Direction; import lombok.Getter; @@ -32,7 +32,7 @@ public class EnderRedstoneLinkCover extends AbstractEnderLinkCover().size(w, h); } @Override diff --git a/src/main/java/com/gregtechceu/gtceu/common/mui/GTGuiTextures.java b/src/main/java/com/gregtechceu/gtceu/common/mui/GTGuiTextures.java index 36588fefcf2..e2b82391e79 100644 --- a/src/main/java/com/gregtechceu/gtceu/common/mui/GTGuiTextures.java +++ b/src/main/java/com/gregtechceu/gtceu/common/mui/GTGuiTextures.java @@ -46,6 +46,18 @@ public static class IDs { public static final UITexture INDICATOR_NO_STEAM_STEEL = fullImage( "textures/gui/base/indicator_no_steam_steel.png"); public static final UITexture TANK_ICON = fullImage("textures/gui/base/tank_icon.png"); + public static final UITexture IO_BOTH = fullImage("textures/gui/icon/io_mode/both.png"); + public static final UITexture IO_EXPORT = fullImage("textures/gui/icon/io_mode/export.png"); + public static final UITexture IO_IMPORT = fullImage("textures/gui/icon/io_mode/import.png"); + public static final UITexture IO_NONE = fullImage("textures/gui/icon/io_mode/none.png"); + public static final UITexture MANUAL_IO_DISABLED = fullImage("textures/gui/icon/manual_io_mode/disabled.png"); + public static final UITexture MANUAL_IO_FILTERED = fullImage("textures/gui/icon/manual_io_mode/filtered.png"); + public static final UITexture MANUAL_IO_UNFILTERED = fullImage("textures/gui/icon/manual_io_mode/unfiltered.png"); + public static final UITexture SEPERATOR_SIMPLE = UITexture.builder() + .location(GTCEu.MOD_ID, "textures/gui/icon/seperator/seperator_simple.png") + .imageSize(16, 5) + .adaptable(2) + .build(); // BACKGROUNDS public static final UITexture BACKGROUND = UITexture.builder() @@ -443,6 +455,8 @@ public static class IDs { public static final UITexture BUTTON_REDSTONE_OFF = fullImage("textures/gui/widget/button_redstone_off.png"); public static final UITexture BUTTON_THROTTLE_PLUS = fullImage("textures/gui/widget/button_throttle_plus.png"); public static final UITexture BUTTON_THROTTLE_MINUS = fullImage("textures/gui/widget/button_throttle_minus.png"); + public static final UITexture OVERLAY_LOCK_CLOSED = fullImage("textures/gui/overlay/lock_closed.png"); + public static final UITexture OVERLAY_LOCK_OPEN = fullImage("textures/gui/overlay/lock_open.png"); public static final UITexture BUTTON_EU = fullImage("textures/gui/overlay/mode_eu.png"); public static final UITexture BUTTON_PERCENT = fullImage("textures/gui/overlay/mode_percent.png"); public static final UITexture BUTTON_MAINTENANCE = fullImage("textures/gui/widget/button_maintenance.png"); diff --git a/src/main/java/com/gregtechceu/gtceu/utils/serialization/network/ByteBufAdapters.java b/src/main/java/com/gregtechceu/gtceu/utils/serialization/network/ByteBufAdapters.java index 84f566e7a10..e888dc43988 100644 --- a/src/main/java/com/gregtechceu/gtceu/utils/serialization/network/ByteBufAdapters.java +++ b/src/main/java/com/gregtechceu/gtceu/utils/serialization/network/ByteBufAdapters.java @@ -18,6 +18,7 @@ import java.math.BigDecimal; import java.math.BigInteger; import java.util.Objects; +import java.util.UUID; public class ByteBufAdapters { @@ -139,6 +140,31 @@ public boolean areEqual(@NotNull GTRecipe t1, @NotNull GTRecipe t2) { } }; + public static final IByteBufAdapter UUID = new IByteBufAdapter<>() { + + @Override + public UUID deserialize(FriendlyByteBuf buffer) { + if (!buffer.readBoolean()) { + return null; + } + return buffer.readUUID(); + } + + @Override + public void serialize(FriendlyByteBuf buffer, UUID u) { + if (u == null) { + buffer.writeBoolean(false); + return; + } + buffer.writeUUID(u); + } + + @Override + public boolean areEqual(@NotNull UUID t1, @NotNull UUID t2) { + return EqualityTest.wrapNullSafe(java.util.UUID::equals).areEqual(t1, t2); + } + }; + public static IByteBufAdapter makeAdapter(@NotNull IByteBufDeserializer deserializer, @NotNull IByteBufSerializer serializer, @Nullable EqualityTest tester) { diff --git a/src/main/resources/assets/gtceu/textures/gui/icon/seperator/seperator_simple.png b/src/main/resources/assets/gtceu/textures/gui/icon/seperator/seperator_simple.png new file mode 100644 index 00000000000..2b3163a346d Binary files /dev/null and b/src/main/resources/assets/gtceu/textures/gui/icon/seperator/seperator_simple.png differ diff --git a/src/main/resources/assets/gtceu/textures/gui/overlay/lock_closed.png b/src/main/resources/assets/gtceu/textures/gui/overlay/lock_closed.png new file mode 100644 index 00000000000..d8b7f4fcd67 Binary files /dev/null and b/src/main/resources/assets/gtceu/textures/gui/overlay/lock_closed.png differ diff --git a/src/main/resources/assets/gtceu/textures/gui/overlay/lock_open.png b/src/main/resources/assets/gtceu/textures/gui/overlay/lock_open.png new file mode 100644 index 00000000000..6235a9c72eb Binary files /dev/null and b/src/main/resources/assets/gtceu/textures/gui/overlay/lock_open.png differ