Skip to content
Open
6 changes: 5 additions & 1 deletion docs/content/Modpacks/Changes/v8.0.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -151,4 +151,8 @@ A few regexes for fixing all the MCMeta files is follows, run them in order:
- Calling the battery buffer constructor with the following args gives the same behaviour as a charger machine: `(info, tier, inventorySize, BatteryBufferMachine.AMPS_PER_BATTERY_CHARGER, 0)`
- Refactored Jade provider code. Use the `MachineInfoProvider` class for jade providers for a specific machine type, and `MachineTraitProvider` for providers for a specific machine trait.
- `GTUtil.getMoltenFluid(Material)` has been moved to `Material.getHotFluid()`.
- `ICopyable::copyConfig`'s `CompoundTag` argument should now be mutated by reference instead of a new one returned (and thus, the return type has been changed to `void`).
- `ICopyable::copyConfig`'s `CompoundTag` argument should now be mutated by reference instead of a new one returned (and thus, the return type has been changed to `void`).
- The API for using filters has changed:
- Instead of using the `ItemFilter` or `FluidFilter` interfaces, use `Filter<ItemStack>` or `Filter<FluidStack>`
- Filters are no longer hardcoded to either item or fluid, instead filters are grouped based on their filterable type (ItemStack, FluidStack, etc)
- FilterHandler no longer has wrappers for item and fluid filter handlers, it now represents a generic filter holder for filters with a specific filterable type.
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package com.gregtechceu.gtceu.api.cover.filter;

import com.gregtechceu.gtceu.api.transfer.item.CustomItemStackHandler;

import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.item.ItemStack;

import brachy.modularui.factory.GuiData;
import brachy.modularui.screen.UISettings;
import brachy.modularui.value.sync.PanelSyncManager;
import brachy.modularui.value.sync.SyncHandlers;
import brachy.modularui.widgets.layout.Flow;
import brachy.modularui.widgets.layout.Grid;
import brachy.modularui.widgets.slot.ItemSlot;
import brachy.modularui.widgets.slot.SlotGroup;
import lombok.Getter;
import org.jetbrains.annotations.Nullable;

import java.util.Objects;

public class CompositeFilter<T> extends Filter<T> {

private final Class<T> filterableType;

private final CustomItemStackHandler itemStacks = new CustomItemStackHandler(9) {

@Override
public void onContentsChanged(int slot) {
onFilterItemChanged(slot);
}

@Override
public int getSlotLimit(int slot) {
return 1;
}
};

@Getter
@SuppressWarnings("unchecked")
protected @Nullable Filter<T>[] filters = (Filter<T>[]) new Filter[9];

public CompositeFilter(ItemStack stack, Class<T> filterableType) {
super(stack);

var tag = stack.getOrCreateTag();
this.filterableType = filterableType;
this.itemStacks.setFilter(s -> Filters.isValidFilter(filterableType, s.getItem()));

if (tag.isEmpty()) return;
itemStacks.deserializeNBT(tag.getCompound("filters"));

for (int i = 0; i < 9; i++) {
var item = itemStacks.getStackInSlot(i);
if (item.isEmpty()) continue;
filters[i] = Filters.loadFilter(filterableType, item);
Objects.requireNonNull(filters[i]).setOnUpdated($ -> updateAndSaveFilter());
}
}

@Override
protected @Nullable CompoundTag writeFilterNBT() {
if (itemStacks.toList().stream().allMatch(i -> i == ItemStack.EMPTY)) return null;
Comment thread
gustovafing marked this conversation as resolved.
Outdated

var tag = new CompoundTag();
tag.put("filters", itemStacks.serializeNBT());
return tag;
}

private void onFilterItemChanged(int slot) {
var newItem = itemStacks.getStackInSlot(slot);
Comment thread
gustovafing marked this conversation as resolved.
Outdated
filters[slot] = null;
if (!newItem.isEmpty()) {
filters[slot] = Filters.loadFilter(filterableType, newItem);
Objects.requireNonNull(filters[slot]).setOnUpdated($ -> updateAndSaveFilter());
}

updateAndSaveFilter();
}

@Override
public boolean supportsAmounts() {
return false;
}

@Override
public boolean test(T t) {
for (int i=0; i<9; i++) {
Filter<T> filter = filters[i];
if (filter != null && filter.test(t)) return true;
}
return false;
}

@Override
public Flow getFilterUI(GuiData data, PanelSyncManager syncManager, UISettings settings) {
SlotGroup slotGroup = new SlotGroup("filters", 9);

Grid filterGrid = new Grid()
.coverChildren()
.gridOfSizeWidth(9, 3, (x, y, i) -> new ItemSlot()
.slot(SyncHandlers.itemSlot(itemStacks, i).slotGroup(slotGroup)));

return Flow.row()
.coverChildrenHeight()
.child(filterGrid.horizontalCenter());
}
}
91 changes: 81 additions & 10 deletions src/main/java/com/gregtechceu/gtceu/api/cover/filter/Filter.java
Original file line number Diff line number Diff line change
@@ -1,34 +1,105 @@
package com.gregtechceu.gtceu.api.cover.filter;

import com.gregtechceu.gtceu.common.mui.GTGuiTextures;
import com.gregtechceu.gtceu.common.mui.GTMuiWidgets;

import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.item.ItemStack;

import brachy.modularui.factory.GuiData;
import brachy.modularui.screen.ModularPanel;
import brachy.modularui.screen.UISettings;
import brachy.modularui.value.sync.PanelSyncManager;
import brachy.modularui.widgets.Dialog;
import brachy.modularui.widgets.SlotGroupWidget;
import brachy.modularui.widgets.layout.Flow;
import lombok.Getter;
import lombok.Setter;
import org.apache.commons.lang3.NotImplementedException;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.Range;

import java.util.function.Consumer;
import java.util.function.Predicate;

public interface Filter<T, S extends Filter<T, S>> extends Predicate<T> {
public abstract class Filter<T> implements Predicate<T> {

@Setter
private Consumer<Filter<T>> onUpdated = $ -> {};

@Getter
protected final ItemStack filterItemStack;

public Filter(ItemStack stack) {
this.filterItemStack = stack;
}

/**
* @return Filter panel when opened by itself (including the player inventory)
*/
ModularPanel<?> getPanel(GuiData data, PanelSyncManager syncManager, UISettings settings);
@SuppressWarnings("deprecation")
public ModularPanel<?> getPanel(GuiData data, PanelSyncManager syncManager, UISettings settings,
boolean displayPlayerInventory) {
return new Dialog<>(BuiltInRegistries.ITEM.getKey(filterItemStack.getItem()).toString())
.disablePanelsBelow(false)
.draggable(true)
.closeOnOutOfBoundsClick(false)
.child(GTMuiWidgets.createTitleBar(() -> filterItemStack, 176, GTGuiTextures.BACKGROUND))
.child(getFilterUI(data, syncManager, settings).top(10))
.childIf(displayPlayerInventory, () -> SlotGroupWidget.playerInventory(false).left(7).bottom(7));
}

/**
* Writes this filter to the filter item's NBT and calls the {@link #onUpdated} listener.
*/
public void updateAndSaveFilter() {
filterItemStack.setTag(writeFilterNBT());
onUpdated.accept(this);
}

/**
* Called when a filter is loaded by a filter handler.
*
* @param handler The filter handler
*/
public void onFilterLoaded(FilterHandler<T> handler) {}

Flow getFilterUI(GuiData data, PanelSyncManager syncManager, UISettings settings);
/**
* @return The filter UI.
*/
public abstract Flow getFilterUI(GuiData data, PanelSyncManager syncManager, UISettings settings);

CompoundTag saveFilter();
/**
* Writes this filter's data to a tag
*
* @return The data tag.
*/
@Nullable
protected abstract CompoundTag writeFilterNBT();

void setOnUpdated(Consumer<S> onUpdated);
/**
* @return Whether this filter supports querying for exact content amounts.
*/
public abstract boolean supportsAmounts();
Comment thread
gustovafing marked this conversation as resolved.
Outdated

default boolean isBlackList() {
return false;
}
/**
* Tests if the given stack matches this filter.
*
* @return If the given stack matches this filter.
*/
@Override
public abstract boolean test(T t);

default boolean isBlank() {
return false;
/**
* Retrieves the given amount that matches the filter for the stack. {@link #supportsAmounts()} should be checked
* before calling this.
*
* @return The exact amount that matches the filter.<br>
* If the stack is not matched by this filter, 0 is returned instead.
*/
@Range(from = 0, to = Integer.MAX_VALUE)
public int testAmount(T stack) {
throw new NotImplementedException("This filter does not support testing amounts.");
}
}
Loading
Loading