Skip to content

Commit

Permalink
Implement fluid covers (#272)
Browse files Browse the repository at this point in the history
* refactor: extract enum selection to EnumSelectorWidget

* refactor: cleanup PumpCover

* fix: leveling issues on covers

* refactor: rework pump cover logic

The pump cover now uses millibuckets in all its variables and all
conversions from or to the necessary unit to be either displayed or used
are done in-place.

* fix: use correct covers for ZPM and UV tiers

* style: reformat multi tier covers in GTItems

* fix: correctly apply stack size on item filters in robot arms (part 1)

This is the first half of the fix. The second half will be separating
the change callback from item stack updating.

* feat: add fluid regulator cover

* fix: correctly apply stack size on item filters in robot arms (part 2)

Separate persisting filters from onUpdate callback & automatically apply
stack size config in robot arm.

* fix: errors on loading fluid filter

* fix: filter ui not updating when removing filter

* feat: fluid filter stack size & fluid regulator GUI

* refactor: PumpCover visibility & cleanup

* feat: TRANSFER_EXACT mode for fluid regulator cover

* fix: correct initial transfer per second for pump cover

* chore: update IFluidTransfer implementations for next LDLib version

* feat: KEEP_EXACT mode for fluid regulator cover

* chore: update LDLib to 1.0.17

* fix: stack/transfer size input visibility in fluid regulator & robot arm

* fix: cases where supply amount > max transfer left in fluid regulator

* refactor: cleanup item voiding covers

* fix: UI title on item voiding cover

* fix: stack size input visibility in advanced item voiding cover

* feat: fluid voiding covers (UI only)

* refactor: move enumerateDistinctFluids() to PumpCover

* feat: implement logic for fluid voiding covers

* refactor: move platform specific fluid calculation out of BucketMode
  • Loading branch information
screret committed Nov 23, 2023
1 parent 093b290 commit 5030f18
Show file tree
Hide file tree
Showing 39 changed files with 1,767 additions and 443 deletions.
Original file line number Diff line number Diff line change
@@ -1,22 +1,26 @@
package com.gregtechceu.gtceu.api.capability.recipe;

import com.gregtechceu.gtceu.api.gui.widget.EnumSelectorWidget;
import com.lowdragmc.lowdraglib.gui.texture.IGuiTexture;
import com.lowdragmc.lowdraglib.gui.texture.ResourceTexture;
import lombok.Getter;

/**
* The capability can be input or output or both
*/
public enum IO {
public enum IO implements EnumSelectorWidget.SelectableEnum {
IN("gtceu.io.import", "import"),
OUT("gtceu.io.export", "export"),
BOTH("gtceu.io.both", "both"),
NONE("gtceu.io.none", "none");

public final String localeName;
@Getter
public final String tooltip;
@Getter
public final IGuiTexture icon;

IO(String localeName, String textureName) {
this.localeName = localeName;
IO(String tooltip, String textureName) {
this.tooltip = tooltip;
this.icon = new ResourceTexture("gtceu:textures/gui/icon/io_mode/" + textureName + ".png");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,7 @@ public interface Filter<T, S extends Filter<T, S>> extends Predicate<T> {

void setOnUpdated(Consumer<S> onUpdated);

default boolean isBlackList() {
return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,14 @@ public abstract class FilterHandler<T, F extends Filter<T, F>> implements IEnhan

@Persisted @DescSynced @Getter
private @NotNull ItemStack filterItem = ItemStack.EMPTY;

private @Nullable F filter;
private @Nullable ItemStackTransfer filterSlot;
private @Nullable WidgetGroup filterGroup;

private @NotNull Consumer<F> onFilterLoaded = (filter) -> {};
private @NotNull Consumer<F> onFilterRemoved = (filter) -> {};
private @NotNull Consumer<F> onFilterUpdated = (filter) -> {};

public FilterHandler(IEnhancedManaged container) {
this.container = container;
Expand Down Expand Up @@ -74,8 +75,7 @@ public F getFilter() {
if (this.filterItem.isEmpty()) {
return getEmptyFilter();
} else {
this.filter = loadFilter(this.filterItem);
this.onFilterLoaded.accept(this.filter);
loadFilterFromItem();
}
}

Expand All @@ -92,6 +92,11 @@ public FilterHandler<T, F> onFilterRemoved(Consumer<F> onFilterRemoved) {
return this;
}

public FilterHandler<T, F> onFilterUpdated(Consumer<F> onFilterUpdated) {
this.onFilterUpdated = onFilterUpdated;
return this;
}

///////////////////////////////////////
//***** FILTER HANDLING ******//
///////////////////////////////////////
Expand All @@ -118,15 +123,20 @@ private void updateFilter() {
this.filterItem = filterContainer.getStackInSlot(0);

if (this.filter != null) {
this.filter = null;
this.onFilterRemoved.accept(this.filter);
}
this.filter = null;

loadFilterFromItem();
}

private void loadFilterFromItem() {
if (!this.filterItem.isEmpty()) {
this.filter = loadFilter(this.filterItem);
filter.setOnUpdated(this.onFilterUpdated);

this.onFilterLoaded.accept(this.filter);
}

updateFilterGroupUI();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,14 @@ static FluidFilter loadFilter(ItemStack itemStack) {
return FILTERS.get(itemStack.getItem()).apply(itemStack);
}

/**
* Retrieves the configured fluid amount for the supplied fluid.
*
* @return The amount configured for the supplied fluid stack.<br>
* If the stack is not matched by this filter, 0 is returned instead.
*/
long testFluidAmount(FluidStack fluidStack);

/**
* An empty fluid filter that allows all fluids.<br>
* ONLY TO BE USED FOR FLUID MATCHING! All other functionality will throw an exception.
Expand All @@ -35,6 +43,11 @@ public boolean test(FluidStack fluidStack) {
return true;
}

@Override
public long testFluidAmount(FluidStack fluidStack) {
return Long.MAX_VALUE;
}

@Override
public WidgetGroup openConfigurator(int x, int y) {
throw new NotImplementedException("Not available for empty fluid filter");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,6 @@ static ItemFilter loadFilter(ItemStack itemStack) {
*/
int testItemCount(ItemStack itemStack);

default boolean isBlackList() {
return false;
}


/**
* An empty item filter that allows all items.<br>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
package com.gregtechceu.gtceu.api.cover.filter;

import com.gregtechceu.gtceu.api.gui.GuiTextures;
import com.gregtechceu.gtceu.api.gui.widget.ScrollablePhantomFluidWidget;
import com.gregtechceu.gtceu.api.gui.widget.ToggleButtonWidget;
import com.lowdragmc.lowdraglib.gui.widget.PhantomFluidWidget;
import com.lowdragmc.lowdraglib.gui.widget.WidgetGroup;
import com.lowdragmc.lowdraglib.misc.FluidStorage;
import com.lowdragmc.lowdraglib.side.fluid.FluidStack;
import lombok.Getter;
import lombok.Setter;
import net.minecraft.MethodsReturnNonnullByDefault;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;
Expand All @@ -32,8 +31,14 @@ public class SimpleFluidFilter implements FluidFilter {
protected boolean ignoreNbt;
@Getter
protected FluidStack[] matches = new FluidStack[9];
@Setter
protected Consumer<FluidFilter> onUpdated;

protected Consumer<FluidFilter> itemWriter = filter -> {};
protected Consumer<FluidFilter> onUpdated = filter -> itemWriter.accept(filter);

@Getter
protected long maxStackSize = 1L;

private FluidStorage[] fluidStorageSlots = new FluidStorage[9];

protected SimpleFluidFilter() {
Arrays.fill(matches, FluidStack.empty());
Expand All @@ -43,9 +48,9 @@ public static SimpleFluidFilter loadFilter(ItemStack itemStack) {
return loadFilter(itemStack.getOrCreateTag(), filter -> itemStack.setTag(filter.saveFilter()));
}

public static SimpleFluidFilter loadFilter(CompoundTag tag, Consumer<FluidFilter> onUpdated) {
private static SimpleFluidFilter loadFilter(CompoundTag tag, Consumer<FluidFilter> itemWriter) {
var handler = new SimpleFluidFilter();
handler.setOnUpdated(onUpdated);
handler.itemWriter = itemWriter;
handler.isBlackList = tag.getBoolean("isBlackList");
handler.ignoreNbt = tag.getBoolean("matchNbt");
var list = tag.getList("matches", Tag.TAG_COMPOUND);
Expand All @@ -55,6 +60,14 @@ public static SimpleFluidFilter loadFilter(CompoundTag tag, Consumer<FluidFilter
return handler;
}

@Override
public void setOnUpdated(Consumer<FluidFilter> onUpdated) {
this.onUpdated = filter -> {
this.itemWriter.accept(filter);
onUpdated.accept(filter);
};
}

public CompoundTag saveFilter() {
var tag = new CompoundTag();
tag.putBoolean("isBlackList", isBlackList);
Expand All @@ -80,17 +93,33 @@ public void setIgnoreNbt(boolean ingoreNbt) {

public WidgetGroup openConfigurator(int x, int y) {
WidgetGroup group = new WidgetGroup(x, y, 18 * 3 + 25, 18 * 3); // 80 55
fluidStorageSlots = new FluidStorage[9];
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
final int index = i * 3 + j;
var handler = new FluidStorage(1000);
handler.setFluid(matches[index]);
var tank = new PhantomFluidWidget(handler, i * 18, j * 18);
tank.setShowAmount(false);

fluidStorageSlots[index] = new FluidStorage(maxStackSize);
fluidStorageSlots[index].setFluid(matches[index]);

var tank = new ScrollablePhantomFluidWidget(fluidStorageSlots[index], i * 18, j * 18) {
@Override
public void updateScreen() {
super.updateScreen();
setShowAmount(maxStackSize > 1L);
}

@Override
public void detectAndSendChanges() {
super.detectAndSendChanges();
setShowAmount(maxStackSize > 1L);
}
};

tank.setChangeListener(() -> {
matches[index] = handler.getFluidInTank(0);
matches[index] = fluidStorageSlots[index].getFluidInTank(0);
onUpdated.accept(this);
}).setBackground(GuiTextures.SLOT);

group.addWidget(tank);
}
}
Expand All @@ -103,17 +132,45 @@ public WidgetGroup openConfigurator(int x, int y) {

@Override
public boolean test(FluidStack other) {
boolean found = false;
for (var match : matches) {
if (ignoreNbt) {
found = match.getFluid() == other.getFluid();
} else {
found = match.isFluidEqual(other);
}
if (found) {
break;
return testFluidAmount(other) > 0L;
}

@Override
public long testFluidAmount(FluidStack fluidStack) {
long totalFluidAmount = getTotalConfiguredFluidAmount(fluidStack);

if (isBlackList) {
return (totalFluidAmount > 0L) ? 0L : Long.MAX_VALUE;
}

return totalFluidAmount;
}

public long getTotalConfiguredFluidAmount(FluidStack fluidStack) {
long totalAmount = 0L;

for (var candidate : matches) {
if (ignoreNbt && candidate.getFluid() == fluidStack.getFluid()) {
totalAmount += candidate.getAmount();
} else if (candidate.isFluidEqual(fluidStack)) {
totalAmount += candidate.getAmount();
}
}
return isBlackList != found;

return totalAmount;
}

public void setMaxStackSize(long maxStackSize) {
this.maxStackSize = maxStackSize;

for (FluidStorage slot : fluidStorageSlots) {
if (slot != null)
slot.setCapacity(maxStackSize);
}

for (FluidStack match : matches) {
if (!match.isEmpty())
match.setAmount(Math.min(match.getAmount(), maxStackSize));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import com.lowdragmc.lowdraglib.misc.ItemStackTransfer;
import com.lowdragmc.lowdraglib.side.item.ItemTransferHelper;
import lombok.Getter;
import lombok.Setter;
import net.minecraft.MethodsReturnNonnullByDefault;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;
Expand All @@ -26,13 +25,15 @@
@ParametersAreNonnullByDefault
@MethodsReturnNonnullByDefault
public class SimpleItemFilter implements ItemFilter {
@Getter
protected boolean isBlackList;
@Getter
protected boolean ignoreNbt;
@Getter
protected ItemStack[] matches = new ItemStack[9];
@Setter
protected Consumer<ItemFilter> onUpdated;

protected Consumer<ItemFilter> itemWriter = filter -> {};
protected Consumer<ItemFilter> onUpdated = filter -> itemWriter.accept(filter);

@Getter
protected int maxStackSize;
Expand All @@ -47,9 +48,9 @@ public static SimpleItemFilter loadFilter(ItemStack itemStack) {
return loadFilter(itemStack.getOrCreateTag(), filter -> itemStack.setTag(filter.saveFilter()));
}

public static SimpleItemFilter loadFilter(CompoundTag tag, Consumer<ItemFilter> onUpdated) {
private static SimpleItemFilter loadFilter(CompoundTag tag, Consumer<ItemFilter> itemWriter) {
var handler = new SimpleItemFilter();
handler.setOnUpdated(onUpdated);
handler.itemWriter = itemWriter;
handler.isBlackList = tag.getBoolean("isBlackList");
handler.ignoreNbt = tag.getBoolean("matchNbt");
var list = tag.getList("matches", Tag.TAG_COMPOUND);
Expand All @@ -59,6 +60,14 @@ public static SimpleItemFilter loadFilter(CompoundTag tag, Consumer<ItemFilter>
return handler;
}

@Override
public void setOnUpdated(Consumer<ItemFilter> onUpdated) {
this.onUpdated = filter -> {
this.itemWriter.accept(filter);
onUpdated.accept(filter);
};
}

public CompoundTag saveFilter() {
var tag = new CompoundTag();
tag.putBoolean("isBlackList", isBlackList);
Expand All @@ -74,32 +83,23 @@ public CompoundTag saveFilter() {

public void setBlackList(boolean blackList) {
isBlackList = blackList;
if (blackList) {
setMaxStackSize(1);
} else {
setMaxStackSize(Integer.MAX_VALUE);
}
onUpdated.accept(this);
}

@Override
public boolean isBlackList() {
return isBlackList;
}

public void setIgnoreNbt(boolean ingoreNbt) {
this.ignoreNbt = ingoreNbt;
onUpdated.accept(this);
}

public WidgetGroup openConfigurator(int x, int y) {
WidgetGroup group = new WidgetGroup(x, y, 18 * 3 + 25, 18 * 3); // 80 55
var filterSlots = new PhantomSlotWidget[9];
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
final int index = i * 3 + j;

var handler = new ItemStackTransfer(matches[index]);
filterSlots[i] = new PhantomSlotWidget(handler, 0, i * 18, j * 18) {

var slot = new PhantomSlotWidget(handler, 0, i * 18, j * 18) {
@Override
public void updateScreen() {
super.updateScreen();
Expand All @@ -112,11 +112,12 @@ public void detectAndSendChanges() {
setMaxStackSize(maxStackSize);
}
};
var slot = filterSlots[i];

slot.setChangeListener(() -> {
matches[index] = handler.getStackInSlot(0);
onUpdated.accept(this);
}).setBackground(GuiTextures.SLOT);

group.addWidget(slot);
}
}
Expand Down
Loading

0 comments on commit 5030f18

Please sign in to comment.