diff --git a/src/main/java/ru/dbotthepony/mc/otm/item/ItemPortableCondensationDrive.java b/src/main/java/ru/dbotthepony/mc/otm/item/ItemPortableCondensationDrive.java index 149386306..42579bf01 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/item/ItemPortableCondensationDrive.java +++ b/src/main/java/ru/dbotthepony/mc/otm/item/ItemPortableCondensationDrive.java @@ -1,15 +1,26 @@ package ru.dbotthepony.mc.otm.item; import net.minecraft.ChatFormatting; +import net.minecraft.client.Minecraft; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.ListTag; +import net.minecraft.nbt.Tag; +import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.TextComponent; import net.minecraft.stats.Stats; +import net.minecraft.tags.ItemTags; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.MenuProvider; import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.TooltipFlag; +import net.minecraft.world.item.context.UseOnContext; import net.minecraft.world.level.Level; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.capabilities.ICapabilityProvider; @@ -18,16 +29,22 @@ import net.minecraftforge.event.entity.player.EntityItemPickupEvent; import net.minecraftforge.event.entity.player.PlayerEvent; import net.minecraftforge.eventbus.api.Event; import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fmllegacy.network.NetworkEvent; +import net.minecraftforge.registries.RegistryManager; import ru.dbotthepony.mc.otm.OverdriveThatMatters; import ru.dbotthepony.mc.otm.capability.MatteryCapability; import ru.dbotthepony.mc.otm.capability.drive.DrivePool; import ru.dbotthepony.mc.otm.capability.drive.IMatteryDrive; import ru.dbotthepony.mc.otm.capability.drive.MatteryDrive; +import ru.dbotthepony.mc.otm.menu.DriveViewerMenu; import javax.annotation.Nonnull; import javax.annotation.Nullable; +import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.UUID; +import java.util.function.Supplier; public class ItemPortableCondensationDrive extends Item { public ItemPortableCondensationDrive() { @@ -48,38 +65,45 @@ public class ItemPortableCondensationDrive extends Item { var item = event.getItem().getItem().getItem(); for (var stack : event.getPlayer().getInventory().items) { - if (stack.getItem() instanceof ItemPortableCondensationDrive) { - var cap = stack.getCapability(MatteryCapability.DRIVE).resolve().get(); + if (stack.getItem() instanceof ItemPortableCondensationDrive drive) { + var _cap = stack.getCapability(MatteryCapability.DRIVE).resolve(); - var copy = event.getItem().getItem().copy(); - var remaining = cap.insertItem(event.getItem().getItem(), false); + if (_cap.isPresent()) { + var cap = _cap.get(); + var filter = drive.getFilterSettings(stack); - if (remaining.getCount() == event.getItem().getItem().getCount()) { - continue; - } + if (filter.matches(event.getItem().getItem())) { + var copy = event.getItem().getItem().copy(); + var remaining = cap.insertItem(event.getItem().getItem(), false); - copy.setCount(copy.getCount() - remaining.getCount()); + if (remaining.getCount() == event.getItem().getItem().getCount()) { + continue; + } - event.setCanceled(true); + copy.setCount(copy.getCount() - remaining.getCount()); - net.minecraftforge.fmllegacy.hooks.BasicEventHooks.firePlayerItemPickupEvent(event.getPlayer(), event.getItem(), copy); + event.setCanceled(true); - if (remaining.getCount() > 0) { - event.getItem().getItem().setCount(remaining.getCount()); - event.getPlayer().take(event.getItem(), amount - remaining.getCount()); + net.minecraftforge.fmllegacy.hooks.BasicEventHooks.firePlayerItemPickupEvent(event.getPlayer(), event.getItem(), copy); - event.getPlayer().awardStat(Stats.ITEM_PICKED_UP.get(item), amount - remaining.getCount()); - event.getPlayer().onItemPickup(event.getItem()); + if (remaining.getCount() > 0) { + event.getItem().getItem().setCount(remaining.getCount()); + event.getPlayer().take(event.getItem(), amount - remaining.getCount()); - amount = remaining.getCount(); - } else { - event.getPlayer().take(event.getItem(), amount); + event.getPlayer().awardStat(Stats.ITEM_PICKED_UP.get(item), amount - remaining.getCount()); + event.getPlayer().onItemPickup(event.getItem()); - event.getPlayer().awardStat(Stats.ITEM_PICKED_UP.get(item), amount); - event.getPlayer().onItemPickup(event.getItem()); + amount = remaining.getCount(); + } else { + event.getPlayer().take(event.getItem(), amount); - event.getItem().discard(); - return; + event.getPlayer().awardStat(Stats.ITEM_PICKED_UP.get(item), amount); + event.getPlayer().onItemPickup(event.getItem()); + + event.getItem().discard(); + return; + } + } } } } @@ -140,4 +164,109 @@ public class ItemPortableCondensationDrive extends Item { public ICapabilityProvider initCapabilities(ItemStack stack, @Nullable CompoundTag nbt) { return new DriveCapability(stack); } + + public static class FilterSettings { + public static final int MAX_FILTERS = 12; + public final ItemStack[] items = new ItemStack[MAX_FILTERS]; + public boolean match_nbt; + public boolean match_tag; + public boolean blacklist; + + public FilterSettings() { + Arrays.fill(items, ItemStack.EMPTY); + } + + public FilterSettings(CompoundTag tag) { + this(); + + var list = tag.getList("filter", Tag.TAG_COMPOUND); + var i = 0; + + for (var get_tag : list) { + if (get_tag instanceof CompoundTag compound) { + items[i++] = ItemStack.of(compound); + } + } + + match_nbt = tag.getBoolean("match_nbt"); + match_tag = tag.getBoolean("match_tag"); + blacklist = tag.getBoolean("blacklist"); + } + + public void serializeNBT(CompoundTag compound) { + var list = new ListTag(); + + for (int i = 0; i < MAX_FILTERS; i++) { + list.add(items[i].serializeNBT()); + } + + compound.put("filter", list); + compound.putBoolean("match_nbt", match_nbt); + compound.putBoolean("match_tag", match_tag); + compound.putBoolean("blacklist", blacklist); + } + + public void serializeNBT(ItemStack drive) { + serializeNBT(drive.getOrCreateTag()); + } + + public boolean matches(ItemStack stack) { + if (blacklist) { + for (var item : items) { + if (!match_nbt && ItemStack.isSame(item, stack)) { + return false; + } + + if (match_tag) { + var this_tags = item.getItem().getTags(); + var stack_tatgs = stack.getItem().getTags(); + + for (var tag1 : this_tags) { + if (stack_tatgs.contains(tag1)) { + return false; + } + } + } + + if (match_nbt && ItemStack.isSameItemSameTags(item, stack)) { + return false; + } + } + + return true; + } else { + for (var item : items) { + boolean same = ItemStack.isSame(item, stack); + + if (!same && match_tag) { + var this_tags = item.getItem().getTags(); + var stack_tatgs = stack.getItem().getTags(); + + for (var tag1 : this_tags) { + if (stack_tatgs.contains(tag1)) { + same = true; + break; + } + } + } + + if (match_nbt) { + if (same && ItemStack.tagMatches(item, stack)) { + return true; + } + } else { + if (same) { + return true; + } + } + } + + return false; + } + } + } + + public FilterSettings getFilterSettings(ItemStack drive) { + return new FilterSettings(drive.getOrCreateTag()); + } } diff --git a/src/main/java/ru/dbotthepony/mc/otm/menu/DriveViewerMenu.java b/src/main/java/ru/dbotthepony/mc/otm/menu/DriveViewerMenu.java index 5f5262874..38812a8f2 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/menu/DriveViewerMenu.java +++ b/src/main/java/ru/dbotthepony/mc/otm/menu/DriveViewerMenu.java @@ -18,6 +18,7 @@ import ru.dbotthepony.mc.otm.block.entity.BlockEntityDriveViewer; import ru.dbotthepony.mc.otm.capability.MatteryCapability; import ru.dbotthepony.mc.otm.capability.drive.IItemViewListener; import ru.dbotthepony.mc.otm.capability.drive.IMatteryDrive; +import ru.dbotthepony.mc.otm.item.ItemPortableCondensationDrive; import ru.dbotthepony.mc.otm.menu.slot.MatterySlot; import ru.dbotthepony.mc.otm.network.MatteryNetworking; import ru.dbotthepony.mc.otm.network.SetCarriedPacket; @@ -490,4 +491,99 @@ public class DriveViewerMenu extends PoweredMatteryMenu { }); } } + + public enum FilterSwitch { + MATCH_NBT, + MATCH_TAG, + BLACKLIST + } + + public ItemPortableCondensationDrive.FilterSettings getFilter() { + if (drive_slot.getItem().isEmpty()) + return null; + + if (drive_slot.getItem().getItem() instanceof ItemPortableCondensationDrive item) + return item.getFilterSettings(drive_slot.getItem()); + + return null; + } + + public record FilterSetPacket(int id, int slot, ItemStack value) { + public void write(FriendlyByteBuf buffer) { + buffer.writeInt(id); + buffer.writeInt(slot); + buffer.writeItem(value); + } + + public static FilterSetPacket read(FriendlyByteBuf buffer) { + return new FilterSetPacket(buffer.readInt(), buffer.readInt(), buffer.readItem()); + } + + public void play(Supplier context) { + context.get().setPacketHandled(true); + + if (slot < 0 || slot >= ItemPortableCondensationDrive.FilterSettings.MAX_FILTERS) + return; + + if (value.getCount() > 1) + value.setCount(1); + + context.get().enqueueWork(() -> { + var ply = context.get().getSender(); + + if (ply.containerMenu instanceof DriveViewerMenu menu && menu.containerId == id) { + if (menu.drive_slot.getItem().isEmpty()) + return; + + if (menu.drive_slot.getItem().getItem() instanceof ItemPortableCondensationDrive drive) { + var filter = drive.getFilterSettings(menu.drive_slot.getItem()); + filter.items[slot] = value; + filter.serializeNBT(menu.drive_slot.getItem()); + } + } + }); + } + } + + public record FilterSwitchPacket(int id, FilterSwitch type, boolean value) { + public void write(FriendlyByteBuf buffer) { + buffer.writeInt(id); + buffer.writeEnum(type); + buffer.writeBoolean(value); + } + + public static FilterSwitchPacket read(FriendlyByteBuf buffer) { + return new FilterSwitchPacket(buffer.readInt(), buffer.readEnum(FilterSwitch.class), buffer.readBoolean()); + } + + public void play(Supplier context) { + context.get().setPacketHandled(true); + context.get().enqueueWork(() -> { + var ply = context.get().getSender(); + + if (ply.containerMenu instanceof DriveViewerMenu menu && menu.containerId == id) { + var settings = menu.getFilter(); + + if (settings == null) + return; + + switch (type) { + case MATCH_NBT -> { + settings.match_nbt = value; + } + + case MATCH_TAG -> { + settings.match_tag = value; + } + + case BLACKLIST -> { + settings.blacklist = value; + } + } + + settings.serializeNBT(menu.drive_slot.getItem()); + } + }); + } + } } diff --git a/src/main/java/ru/dbotthepony/mc/otm/menu/MatteryMenu.java b/src/main/java/ru/dbotthepony/mc/otm/menu/MatteryMenu.java index 9bdbb7ca0..4475e2372 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/menu/MatteryMenu.java +++ b/src/main/java/ru/dbotthepony/mc/otm/menu/MatteryMenu.java @@ -27,6 +27,12 @@ public abstract class MatteryMenu extends AbstractContainerMenu { public final ArrayList inventory_slots = new ArrayList<>(); public final ArrayList main_slots = new ArrayList<>(); + protected final Set locked_inventory_slots = new HashSet<>(); + + protected boolean isInventorySlotLocked(int index) { + return locked_inventory_slots.contains(index); + } + @Nullable protected ContainerSynchronizer synchronizer; @@ -73,7 +79,18 @@ public abstract class MatteryMenu extends AbstractContainerMenu { for (int i = 0; i < 3; ++i) { for (int j = 0; j < 9; ++j) { - var slot = new MatterySlot(inventory, j + i * 9 + 9, 8 + j * 18, 14 + i * 18); + var slot = new MatterySlot(inventory, j + i * 9 + 9, 8 + j * 18, 14 + i * 18) { + @Override + public boolean mayPlace(ItemStack p_40231_) { + return !isInventorySlotLocked(index); + } + + @Override + public boolean mayPickup(Player p_40228_) { + return !isInventorySlotLocked(index); + } + }; + inventory_slots.add(slot); this.addSlot(slot); @@ -87,7 +104,18 @@ public abstract class MatteryMenu extends AbstractContainerMenu { MatterySlot last = null; for (int k = 0; k < 9; ++k) { - last = new MatterySlot(inventory, k, 8 + k * 18, 14 + 58); + last = new MatterySlot(inventory, k, 8 + k * 18, 14 + 58) { + @Override + public boolean mayPlace(ItemStack p_40231_) { + return !isInventorySlotLocked(index); + } + + @Override + public boolean mayPickup(Player p_40228_) { + return !isInventorySlotLocked(index); + } + }; + this.addSlot(last); inventory_slots.add(last); } diff --git a/src/main/java/ru/dbotthepony/mc/otm/network/MatteryNetworking.java b/src/main/java/ru/dbotthepony/mc/otm/network/MatteryNetworking.java index f06a8567d..1f387364c 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/network/MatteryNetworking.java +++ b/src/main/java/ru/dbotthepony/mc/otm/network/MatteryNetworking.java @@ -7,6 +7,7 @@ import net.minecraftforge.fmllegacy.network.NetworkRegistry; import net.minecraftforge.fmllegacy.network.PacketDistributor; import net.minecraftforge.fmllegacy.network.simple.SimpleChannel; import ru.dbotthepony.mc.otm.OverdriveThatMatters; +import ru.dbotthepony.mc.otm.item.ItemPortableCondensationDrive; import ru.dbotthepony.mc.otm.menu.DriveViewerMenu; import ru.dbotthepony.mc.otm.network.android.*; @@ -200,5 +201,23 @@ public class MatteryNetworking { SetCarriedPacket::play, Optional.of(NetworkDirection.PLAY_TO_CLIENT) ); + + CHANNEL.registerMessage( + next_network_id++, + DriveViewerMenu.FilterSwitchPacket.class, + DriveViewerMenu.FilterSwitchPacket::write, + DriveViewerMenu.FilterSwitchPacket::read, + DriveViewerMenu.FilterSwitchPacket::play, + Optional.of(NetworkDirection.PLAY_TO_SERVER) + ); + + CHANNEL.registerMessage( + next_network_id++, + DriveViewerMenu.FilterSetPacket.class, + DriveViewerMenu.FilterSetPacket::write, + DriveViewerMenu.FilterSetPacket::read, + DriveViewerMenu.FilterSetPacket::play, + Optional.of(NetworkDirection.PLAY_TO_SERVER) + ); } } diff --git a/src/main/java/ru/dbotthepony/mc/otm/screen/DriveViewerScreen.java b/src/main/java/ru/dbotthepony/mc/otm/screen/DriveViewerScreen.java index 425df0015..24e837d0a 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/screen/DriveViewerScreen.java +++ b/src/main/java/ru/dbotthepony/mc/otm/screen/DriveViewerScreen.java @@ -1,11 +1,16 @@ package ru.dbotthepony.mc.otm.screen; import com.mojang.blaze3d.platform.InputConstants; +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.PoseStack; +import net.minecraft.client.gui.components.Button; import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.TranslatableComponent; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.inventory.ClickAction; import net.minecraft.world.inventory.ClickType; import net.minecraft.world.item.ItemStack; +import ru.dbotthepony.mc.otm.item.ItemPortableCondensationDrive; import ru.dbotthepony.mc.otm.menu.DriveViewerMenu; import ru.dbotthepony.mc.otm.menu.slot.MatterySlot; import ru.dbotthepony.mc.otm.menu.widget.GaugeWidget; @@ -14,6 +19,7 @@ import ru.dbotthepony.mc.otm.screen.panels.*; import javax.annotation.Nonnull; import javax.annotation.Nullable; +import java.util.ArrayList; import java.util.List; public class DriveViewerScreen extends MatteryScreen implements MatteryScreen.IMatteryScreenGaugeGetter, MatteryScreen.IMatteryScreenBatteryGetter { @@ -44,15 +50,49 @@ public class DriveViewerScreen extends MatteryScreen implements autoAttachToFrame(frame); + var view_panels = new ArrayList(); + var settings_panels = new ArrayList(); + + var view_button = frame.addTab(FramePanel.FrameTabPosition.TOP); + var settings_button = frame.addTab(FramePanel.FrameTabPosition.TOP); + + view_button.bindOnOpen(() -> { + for (var panel : view_panels) { + panel.setVisible(true); + } + }); + + view_button.bindOnClose(() -> { + for (var panel : view_panels) { + panel.setVisible(false); + } + }); + + settings_button.bindOnOpen(() -> { + for (var panel : settings_panels) { + panel.setVisible(true); + } + }); + + settings_button.bindOnClose(() -> { + for (var panel : settings_panels) { + panel.setVisible(false); + } + }); + var grid = new GridPanel(this, frame, 0, 0, 0, 0, GRID_WIDTH, GRID_HEIGHT); grid.setDock(Dock.FILL); grid.setDockMargin(2, 2, 2, 2); + var scroll_bar = new ScrollBarPanel(this, frame, 0, 0, 0); scroll_bar.setDock(Dock.RIGHT); scroll_bar.setupRowMultiplier(() -> { return menu.view.getItems().size() / GRID_WIDTH; }); + view_panels.add(grid); + view_panels.add(scroll_bar); + for (int i = 0; i < GRID_WIDTH * GRID_HEIGHT; i++) { final int index = i; @@ -90,6 +130,146 @@ public class DriveViewerScreen extends MatteryScreen implements }; } + var dock_left = new FlexGridPanel(this, frame, 0, 0, 90, 0); + dock_left.setDock(Dock.LEFT); + dock_left.setDockMargin(4, 0, 4, 0); + + var grid_filter = new FlexGridPanel(this, frame); + grid_filter.setDock(Dock.FILL); + + settings_panels.add(dock_left); + settings_panels.add(grid_filter); + + for (int i = 0; i < ItemPortableCondensationDrive.FilterSettings.MAX_FILTERS; i++) { + final int index = i; + + new AbstractSlotPanel(this, grid_filter, 0, 0) { + @Nonnull + @Override + protected ItemStack getItemStack() { + var filter = menu.getFilter(); + + if (filter == null) + return ItemStack.EMPTY; + + return filter.items[index]; + } + + private boolean clicking = false; + + @Override + protected boolean mouseClickedInner(double mouse_x, double mouse_y, int flag) { + clicking = true; + return true; + } + + @Override + protected boolean mouseReleasedInner(double mouse_x, double mouse_y, int flag) { + if (clicking) + MatteryNetworking.send(new DriveViewerMenu.FilterSetPacket(menu.containerId, index, menu.getCarried())); + + clicking = false; + + return true; + } + }; + } + + final var no = new TranslatableComponent("otm.filter.no"); + final var yes = new TranslatableComponent("otm.filter.yes"); + + var match_nbt = new ButtonPanel(this, dock_left, 0, 0, 90, 20, new TranslatableComponent("otm.filter.match_nbt", no)) { + @Override + public void tick() { + super.tick(); + + var filter = menu.getFilter(); + + if (filter != null) { + getOrCreateWidget().setMessage(new TranslatableComponent("otm.filter.match_nbt", filter.match_nbt ? yes : no)); + getOrCreateWidget().active = !isWidgetDisabled(); + } else { + getOrCreateWidget().active = false; + } + } + + @Override + protected void onPress() { + super.onPress(); + + var filter = menu.getFilter(); + + if (filter != null) { + MatteryNetworking.send(new DriveViewerMenu.FilterSwitchPacket(menu.containerId, DriveViewerMenu.FilterSwitch.MATCH_NBT, !filter.match_nbt)); + disableFor(20); + } + } + }; + + var match_tag = new ButtonPanel(this, dock_left, 0, 0, 90, 20, new TranslatableComponent("otm.filter.match_tag", no)) { + @Override + public void tick() { + super.tick(); + + var filter = menu.getFilter(); + + if (filter != null) { + getOrCreateWidget().setMessage(new TranslatableComponent("otm.filter.match_tag", filter.match_tag ? yes : no)); + getOrCreateWidget().active = !isWidgetDisabled(); + } else { + getOrCreateWidget().active = false; + } + } + + @Override + protected void onPress() { + super.onPress(); + + var filter = menu.getFilter(); + + if (filter != null) { + MatteryNetworking.send(new DriveViewerMenu.FilterSwitchPacket(menu.containerId, DriveViewerMenu.FilterSwitch.MATCH_TAG, !filter.match_tag)); + disableFor(20); + } + } + }; + + var blacklist = new ButtonPanel(this, dock_left, 0, 0, 90, 20, new TranslatableComponent("otm.filter.blacklist", no)) { + @Override + public void tick() { + super.tick(); + + var filter = menu.getFilter(); + + if (filter != null) { + getOrCreateWidget().setMessage(new TranslatableComponent("otm.filter.blacklist", filter.blacklist ? yes : no)); + getOrCreateWidget().active = !isWidgetDisabled(); + } else { + getOrCreateWidget().active = false; + } + } + + @Override + protected void onPress() { + super.onPress(); + + var filter = menu.getFilter(); + + if (filter != null) { + MatteryNetworking.send(new DriveViewerMenu.FilterSwitchPacket(menu.containerId, DriveViewerMenu.FilterSwitch.BLACKLIST, !filter.blacklist)); + disableFor(20); + } + } + }; + + match_nbt.setDockMargin(0, 4, 0, 0); + match_tag.setDockMargin(0, 4, 0, 0); + blacklist.setDockMargin(0, 4, 0, 0); + + for (var panel : settings_panels) { + panel.setVisible(false); + } + return frame; } } diff --git a/src/main/java/ru/dbotthepony/mc/otm/screen/panels/EditBoxPanel.java b/src/main/java/ru/dbotthepony/mc/otm/screen/panels/EditBoxPanel.java index 066593add..ab7919965 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/screen/panels/EditBoxPanel.java +++ b/src/main/java/ru/dbotthepony/mc/otm/screen/panels/EditBoxPanel.java @@ -28,6 +28,8 @@ public class EditBoxPanel extends MinecraftWidgetPanel { @Override public void tick() { + super.tick(); + if (widget != null) widget.tick(); } diff --git a/src/main/java/ru/dbotthepony/mc/otm/screen/panels/EditablePanel.java b/src/main/java/ru/dbotthepony/mc/otm/screen/panels/EditablePanel.java index f8bde92ce..18a7227a3 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/screen/panels/EditablePanel.java +++ b/src/main/java/ru/dbotthepony/mc/otm/screen/panels/EditablePanel.java @@ -135,6 +135,10 @@ public class EditablePanel implements GuiEventListener { this(screen, parent, 0, 0, 10, 10); } + public EditablePanel(@Nonnull MatteryScreen screen, @Nullable EditablePanel parent, float x, float y) { + this(screen, parent, x, y, 10, 10); + } + public float getRenderX() { return parent_x; } diff --git a/src/main/java/ru/dbotthepony/mc/otm/screen/panels/FlexGridPanel.java b/src/main/java/ru/dbotthepony/mc/otm/screen/panels/FlexGridPanel.java index dfad22858..af03e8729 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/screen/panels/FlexGridPanel.java +++ b/src/main/java/ru/dbotthepony/mc/otm/screen/panels/FlexGridPanel.java @@ -1,5 +1,6 @@ package ru.dbotthepony.mc.otm.screen.panels; +import ru.dbotthepony.mc.otm.OverdriveThatMatters; import ru.dbotthepony.mc.otm.screen.MatteryScreen; import javax.annotation.Nonnull; @@ -20,12 +21,19 @@ public class FlexGridPanel extends EditablePanel { BOTTOM_RIGHT } - protected FlexAlign align; + protected FlexAlign align = FlexAlign.MIDDLE_CENTER; public int panels_per_row = 1; public FlexGridPanel(@Nonnull MatteryScreen screen, @Nullable EditablePanel parent, float x, float y, float width, float height) { super(screen, parent, x, y, width, height); - align = FlexAlign.MIDDLE_CENTER; + } + + public FlexGridPanel(@Nonnull MatteryScreen screen, @Nullable EditablePanel parent, float x, float y) { + super(screen, parent, x, y); + } + + public FlexGridPanel(@Nonnull MatteryScreen screen, @Nullable EditablePanel parent) { + super(screen, parent); } public FlexAlign getAlign() { @@ -71,44 +79,59 @@ public class FlexGridPanel extends EditablePanel { desired_width = min_width; } - // ширину на середину для позиционирования по центру - this_width /= 2; - - int index = 0; + int index; // определение высоты всех рядов вместе float total_height = 0; - panels_per_row = 0; - boolean calculate_row_width = true; - for (int row = 0; row < rows; row++) { - float max_height = 0; - float total_width = 0; + // утютю никаких goto + // зато код чище некуда! + while (desired_width <= this_width) { + index = 0; + total_height = 0; - for (int i = index; i < children.size(); i++) { - var child = children.get(i); - var gain_width = child.getWidth() + child.getDockMargin().left() + child.getDockMargin().right(); + panels_per_row = 0; + boolean calculate_row_width = true; - index = i; + for (int row = 0; row < rows; row++) { + float max_height = 0; + float total_width = 0; - if (gain_width + total_width > desired_width) { - if (calculate_row_width) { - panels_per_row = i + 1; - calculate_row_width = false; + for (int i = index; i < children.size(); i++) { + var child = children.get(i); + var gain_width = child.getWidth() + child.getDockMargin().left() + child.getDockMargin().right(); + + index = i; + + if (gain_width + total_width > desired_width) { + if (calculate_row_width) { + panels_per_row = i + 1; + calculate_row_width = false; + } + + break; } - break; + max_height = Math.max(max_height, child.getHeight() + child.getDockMargin().top() + child.getDockMargin().bottom()); + total_width += gain_width; } - max_height = Math.max(max_height, child.getHeight() + child.getDockMargin().top() + child.getDockMargin().bottom()); - total_width += gain_width; + total_height += max_height; } - total_height += max_height; + if (index + 1 < children.size() && desired_width != this_width) { + // не все панели уместились. ну чтож + desired_width = Math.min(desired_width + min_width, this_width); + } else { + break; + } } index = 0; + // ширину на середину для позиционирования по центру + this_width /= 2; + // определение точки по середине по высоте float h_middle = (getHeight() - getDockPadding().bottom() - getDockPadding().top() - total_height) / 2; diff --git a/src/main/java/ru/dbotthepony/mc/otm/screen/panels/FramePanel.java b/src/main/java/ru/dbotthepony/mc/otm/screen/panels/FramePanel.java index c81d07615..22d61a39d 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/screen/panels/FramePanel.java +++ b/src/main/java/ru/dbotthepony/mc/otm/screen/panels/FramePanel.java @@ -58,6 +58,19 @@ public class FramePanel extends EditablePanel implements NarratableEntry { this.on_close = on_close; } + public FrameTabPanel(FrameTabPosition position) { + super(FramePanel.this.screen, FramePanel.this, 0, 0, position.width, position.height); + tab_position = position; + } + + public void bindOnOpen(Runnable value) { + on_open = value; + } + + public void bindOnClose(Runnable value) { + on_close = value; + } + @Override protected void innerRender(PoseStack stack, float mouse_x, float mouse_y, float flag) { if (tab_position == FrameTabPosition.TOP) { @@ -150,18 +163,26 @@ public class FramePanel extends EditablePanel implements NarratableEntry { public FrameTabPanel addTab(FrameTabPosition position, Runnable on_open, Runnable on_close) { var tab = new FrameTabPanel(position, on_open, on_close); + doAddTab(tab); + return tab; + } + protected void doAddTab(FrameTabPanel tab) { if (top_tabs.size() == 0 && left_tabs.size() == 0 && right_tabs.size() == 0 && bottom_tabs.size() == 0) { tab.active = true; } - switch (position) { + switch (tab.tab_position) { case TOP -> top_tabs.add(tab); case LEFT -> left_tabs.add(tab); case RIGHT -> right_tabs.add(tab); case BOTTOM -> bottom_tabs.add(tab); } + } + public FrameTabPanel addTab(FrameTabPosition position) { + var tab = new FrameTabPanel(position); + doAddTab(tab); return tab; } diff --git a/src/main/java/ru/dbotthepony/mc/otm/screen/panels/MinecraftWidgetPanel.java b/src/main/java/ru/dbotthepony/mc/otm/screen/panels/MinecraftWidgetPanel.java index f51e85202..a98e2ebb1 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/screen/panels/MinecraftWidgetPanel.java +++ b/src/main/java/ru/dbotthepony/mc/otm/screen/panels/MinecraftWidgetPanel.java @@ -21,6 +21,8 @@ public class MinecraftWidgetPanel extends EditablePane protected T widget; private final WidgetFactory factory; + private int disable_ticks = 0; + @Nullable public T getWidget() { return widget; @@ -35,6 +37,30 @@ public class MinecraftWidgetPanel extends EditablePane } + public void disableFor(int ticks) { + disable_ticks = ticks; + + if (ticks > 0) { + getOrCreateWidget().active = false; + } + } + + public boolean isWidgetDisabled() { + return disable_ticks > 0; + } + + @Override + public void tick() { + super.tick(); + + if (disable_ticks > 0) { + disable_ticks--; + + if (disable_ticks <= 0) + getOrCreateWidget().active = true; + } + } + private void recreate() { if (widget == null) { return; diff --git a/src/main/resources/assets/overdrive_that_matters/lang/en_us.json b/src/main/resources/assets/overdrive_that_matters/lang/en_us.json index 418cf7dd1..d117a20a4 100644 --- a/src/main/resources/assets/overdrive_that_matters/lang/en_us.json +++ b/src/main/resources/assets/overdrive_that_matters/lang/en_us.json @@ -48,6 +48,13 @@ "otm.android_station.research.item": "Requires %s x%s", "otm.android_station.research.missing_predecessors": "%s needs to be researched first", + "otm.filter.yes": "Yes", + "otm.filter.no": "No", + + "otm.filter.match_nbt": "Match NBT: %s", + "otm.filter.match_tag": "Match tag: %s", + "otm.filter.blacklist": "Blacklist: %s", + "otm.matter_bottler.switch_mode": "Switch work mode", "android_feature.overdrive_that_matters.air_bags": "Air bags",