filename:
common/src/main/java/rearth/oritech/client/ui/ItemFilterScreen.java
branch:
1.21
back to repo
package rearth.oritech.client.ui;
import com.mojang.blaze3d.systems.RenderSystem;
import io.wispforest.owo.ui.base.BaseOwoHandledScreen;
import io.wispforest.owo.ui.component.ButtonComponent;
import io.wispforest.owo.ui.component.Components;
import io.wispforest.owo.ui.container.Containers;
import io.wispforest.owo.ui.container.FlowLayout;
import io.wispforest.owo.ui.core.*;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.text.Text;
import org.jetbrains.annotations.NotNull;
import rearth.oritech.Oritech;
import rearth.oritech.block.entity.pipes.ItemFilterBlockEntity;
import rearth.oritech.network.NetworkContent;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Predicate;
import static rearth.oritech.client.ui.BasicMachineScreen.ITEM_SLOT;
public class ItemFilterScreen extends BaseOwoHandledScreen<FlowLayout, ItemFilterScreenHandler> {
private ButtonComponent whiteListButton;
private ButtonComponent nbtButton;
private ButtonComponent componentButton;
private final FlowLayout[] gridContainers = new FlowLayout[12];
private Map<Integer, ItemStack> cachedItems;
public ItemFilterScreen(ItemFilterScreenHandler handler, PlayerInventory inventory, Text title) {
super(handler, inventory, title);
}
@Override
protected @NotNull OwoUIAdapter<FlowLayout> createAdapter() {
return OwoUIAdapter.create(this, Containers::verticalFlow);
}
public void updateItemFilters() {
cachedItems = handler.blockEntity.getFilterSettings().items();
Oritech.LOGGER.debug("loading item filters: " + cachedItems);
for (int i = 0; i < 12; i++) {
var storedStack = cachedItems.getOrDefault(i, ItemStack.EMPTY);
var container = gridContainers[i];
// if empty and one is set, remove it
// otherwise just add a new display
if (container.children().size() == 2) {
container.removeChild(container.children().get(1));
}
if (storedStack.isEmpty()) continue;
var itemComponent = Components.item(storedStack);
itemComponent.positioning(Positioning.absolute(1, 1));
itemComponent.showOverlay(true);
itemComponent.setTooltipFromStack(true);
container.child(itemComponent);
}
}
private void updateButtons() {
var data = handler.blockEntity.getFilterSettings();
var textWhitelistTooltip = data.useWhitelist() ?
Text.translatable("tooltip.oritech.item_filter.whitelist")
: Text.translatable("tooltip.oritech.item_filter.blacklist");
var textNbtTooltip = data.useNbt() ?
Text.translatable("tooltip.oritech.item_filter.nbt")
: Text.translatable("tooltip.oritech.item_filter.no_nbt");
var textNbtComponent = data.useComponents() ?
Text.translatable("tooltip.oritech.item_filter.component")
: Text.translatable("tooltip.oritech.item_filter.no_component");
whiteListButton.tooltip(textWhitelistTooltip);
nbtButton.tooltip(textNbtTooltip);
componentButton.tooltip(textNbtComponent);
}
@Override
protected void build(FlowLayout rootComponent) {
rootComponent
.surface(Surface.VANILLA_TRANSLUCENT)
.horizontalAlignment(HorizontalAlignment.CENTER)
.verticalAlignment(VerticalAlignment.CENTER);
var overlay = Containers.horizontalFlow(Sizing.fixed(176), Sizing.fixed(166));
var gridContainer = Containers.grid(Sizing.content(0), Sizing.content(0), 3, 4);
for (int x = 0; x < 4; x++) {
for (int y = 0; y < 3; y++) {
var slotContainer = Containers.horizontalFlow(Sizing.fixed(19), Sizing.fixed(18));
var background = Components.texture(ITEM_SLOT, 0, 0, 18, 17, 18, 17).positioning(Positioning.absolute(0, 0));
int finalX = x;
int finalY = y;
background.mouseDown().subscribe(((mouseX, mouseY, button) -> onItemFrameBackgroundClicked(slotContainer, finalX, finalY)));
slotContainer.child(background);
var idIndex = y * 4 + x;
gridContainers[idIndex] = slotContainer;
gridContainer.child(slotContainer.margins(Insets.of(0, 2, 0, 0)), y, x);
}
}
overlay.child(gridContainer.positioning(Positioning.absolute(5, 18)));
var buttonWidth = 60;
// sorry to whoever is reading this for this cursed section
whiteListButton = Components.button(Text.literal(" ").append(Text.translatable("title.oritech.item_filter.whitelist").withColor(BasicMachineScreen.GRAY_TEXT_COLOR)), buttonComponent -> toggleWhitelist());
whiteListButton.horizontalSizing(Sizing.fixed(buttonWidth));
whiteListButton.renderer(createToggleRenderer(ignored -> ItemFilterScreen.this.handler.blockEntity.getFilterSettings().useWhitelist()));
whiteListButton.textShadow(false);
overlay.child(whiteListButton.positioning(Positioning.absolute(83, 18)));
nbtButton = Components.button(Text.literal(" ").append(Text.translatable("title.oritech.item_filter.nbt").withColor(BasicMachineScreen.GRAY_TEXT_COLOR)), buttonComponent -> toggleNbt());
nbtButton.horizontalSizing(Sizing.fixed(buttonWidth));
nbtButton.renderer(createToggleRenderer(ignored -> ItemFilterScreen.this.handler.blockEntity.getFilterSettings().useNbt()));
nbtButton.textShadow(false);
overlay.child(nbtButton.positioning(Positioning.absolute(83, 38)));
componentButton = Components.button(Text.literal(" ").append(Text.translatable("title.oritech.item_filter.component").withColor(BasicMachineScreen.GRAY_TEXT_COLOR)), buttonComponent -> toggleComponent());
componentButton.horizontalSizing(Sizing.fixed(buttonWidth));
componentButton.renderer(createToggleRenderer(ignored -> ItemFilterScreen.this.handler.blockEntity.getFilterSettings().useComponents()));
componentButton.textShadow(false);
overlay.child(componentButton.positioning(Positioning.absolute(83, 58)));
addTitle(overlay);
rootComponent.child(
Components.texture(BasicMachineScreen.BACKGROUND, 0, 0, 176, 166, 176, 166)
).child(
overlay.positioning(Positioning.relative(50, 50))
);
updateButtons();
updateItemFilters();
}
public static ButtonComponent.Renderer createToggleRenderer(Predicate<ButtonComponent> activeSupplier) {
return (owoUIDrawContext, button, v) -> {
RenderSystem.enableDepthTest();
var isOn = activeSupplier.test(button);
var normalTexture = isOn ? Oritech.id("textures/gui/modular/toggle_on.png") : Oritech.id("textures/gui/modular/toggle_off.png");
var hoverTexture = isOn ? Oritech.id("textures/gui/modular/toggle_on_hover.png") : Oritech.id("textures/gui/modular/toggle_off_hover.png");
owoUIDrawContext.drawTexture(button.isHovered() ? hoverTexture : normalTexture, button.x(), button.y(), 30, 16, 0, 0, 30, 16, 30, 16);
};
}
private void addTitle(FlowLayout overlay) {
var blockTitle = handler.blockEntity.getCachedState().getBlock().getName();
var label = Components.label(blockTitle);
label.color(new Color(64 / 255f, 64 / 255f, 64 / 255f));
label.sizing(Sizing.fixed(176), Sizing.content(2));
label.horizontalTextAlignment(HorizontalAlignment.CENTER);
label.zIndex(1);
overlay.child(label.positioning(Positioning.relative(50, 2)));
}
private void sendUpdateToServer() {
NetworkContent.UI_CHANNEL.clientHandle().send(new NetworkContent.ItemFilterSyncPacket(handler.blockPos, handler.blockEntity.getFilterSettings()));
}
private void toggleWhitelist() {
var data = handler.blockEntity.getFilterSettings();
var whitelist = data.useWhitelist();
var newWhitelist = !whitelist;
var newData = new ItemFilterBlockEntity.FilterData(data.useNbt(), newWhitelist, data.useComponents(), data.items());
updateFilterSettings(newData); // this is only on client
updateButtons();
sendUpdateToServer();
}
private void toggleNbt() {
var data = handler.blockEntity.getFilterSettings();
var nbt = data.useNbt();
var newNbt = !nbt;
var newData = new ItemFilterBlockEntity.FilterData(newNbt, data.useWhitelist(), data.useComponents(), data.items());
updateFilterSettings(newData); // this is only on client
updateButtons();
sendUpdateToServer();
}
private void toggleComponent() {
var data = handler.blockEntity.getFilterSettings();
var component = data.useComponents();
var nbt = data.useNbt();
var newComponent = !component;
if (newComponent)
nbt = true;
var newData = new ItemFilterBlockEntity.FilterData(nbt, data.useWhitelist(), newComponent, data.items());
updateFilterSettings(newData); // this is only on client
updateButtons();
sendUpdateToServer();
}
private boolean onItemFrameBackgroundClicked(FlowLayout slotContainer, int x, int y) {
if (slotContainer.children().size() >= 2) {
slotContainer.removeChild(slotContainer.children().get(1));
}
var heldItem = this.handler.getCursorStack();
if (heldItem.isEmpty()) {
var idIndex = y * 4 + x;
var oldData = handler.blockEntity.getFilterSettings();
var itemFilters = new HashMap<>(oldData.items());
itemFilters.remove(idIndex);
var newData = new ItemFilterBlockEntity.FilterData(oldData.useNbt(), oldData.useWhitelist(), oldData.useComponents(), itemFilters);
updateFilterSettings(newData); // this is only on client
sendUpdateToServer();
return false;
}
var displayStack = new ItemStack(heldItem.getItem(), 1);
if (heldItem.getComponents() != null)
displayStack.applyComponentsFrom(heldItem.getComponents());
var itemComponent = Components.item(displayStack);
itemComponent.positioning(Positioning.absolute(1, 1));
itemComponent.showOverlay(true);
itemComponent.setTooltipFromStack(true);
slotContainer.child(itemComponent);
var idIndex = y * 4 + x;
var oldData = handler.blockEntity.getFilterSettings();
var itemFilters = new HashMap<>(oldData.items());
itemFilters.put(idIndex, displayStack);
var newData = new ItemFilterBlockEntity.FilterData(oldData.useNbt(), oldData.useWhitelist(), oldData.useComponents(), itemFilters);
updateFilterSettings(newData); // this is only on client
Oritech.LOGGER.debug("stored map: " + itemFilters);
sendUpdateToServer();
return true;
}
private void updateFilterSettings(ItemFilterBlockEntity.FilterData filterData) {
handler.blockEntity.setFilterSettings(filterData);
cachedItems = filterData.items();
}
}