Skip to content

Commit

Permalink
Add = operator to crafting amount screen to only craft whats needed t…
Browse files Browse the repository at this point in the history
…o reach a certain stored amount (#7382)

Closes #7156.

---------

Co-authored-by: Sebastian Hartte <shartte@users.noreply.github.com>
  • Loading branch information
62832 and shartte committed Oct 1, 2023
1 parent 2839aad commit 4569032
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 21 deletions.
3 changes: 2 additions & 1 deletion guidebook/items-blocks-machines/terminals.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,8 @@ mouse/key shortcuts:

* Left-click grabs a stack, right-click grabs half a stack.
* If an item or fluid or etc. is able to be [autocrafted](../ae2-mechanics/autocrafting.md),
whatever you have bound to "pick block" (usually middle-click) brings up a UI to specify the amount to be crafted.
whatever you have bound to "pick block" (usually middle-click) brings up a UI to specify the amount to be crafted. You can also input formulas like `3*64/2`,
or type `=32` to only craft the number of items needed to reach 32 in your storage.
* Holding shift will freeze the displayed items in-place, stopping them from re-organizing themselves when quantities change or new items enter the system.
* Right-clicking with a bucket or other fluid container will deposit the fluid, left-clicking a fluid in the terminal with
an empty fluid container will withdraw the fluid.
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/appeng/client/gui/MathExpressionParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ public static Optional<BigDecimal> parse(String expression, DecimalFormat decima
}
}
} else {
if (number.size() < 1) {
if (number.isEmpty()) {
return Optional.empty();
} else {
number.push(number.pop().negate());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,11 @@ protected void updateBeforeRender() {

private void confirm() {
int amount = this.amountToCraft.getIntValue().orElse(0);
boolean craftMissingAmount = this.amountToCraft.startsWithEquals();
if (amount <= 0) {
return;
}
menu.confirm(amount, hasShiftDown());
menu.confirm(amount, craftMissingAmount, hasShiftDown());
}

}
15 changes: 14 additions & 1 deletion src/main/java/appeng/client/gui/widgets/NumberEntryWidget.java
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,15 @@ public void populateScreen(Consumer<AbstractWidget> addWidget, Rect2i bounds, AE
this.validate();
}

/**
* Returns whether the text field begins with an equals sign. This is used by crafting request screens in order to
* request just enough of an item to bring the total stored amount to the input amount, rather than requesting the
* input amount itself.
*/
public boolean startsWithEquals() {
return textField.getValue().startsWith("=");
}

/**
* Returns the integer value currently in the text-field, if it is a valid number and is within the allowed min/max
* value.
Expand Down Expand Up @@ -296,7 +305,11 @@ private void addQty(long delta) {
* Retrieves the numeric representation of the value entered by the user, if it is convertible.
*/
private Optional<BigDecimal> getValueInternal() {
return MathExpressionParser.parse(textField.getValue(), decimalFormat);
var textValue = textField.getValue();
if (textValue.startsWith("=")) {
textValue = textValue.substring(1);
}
return MathExpressionParser.parse(textValue, decimalFormat);
}

/*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,28 +29,32 @@
public class ConfirmAutoCraftPacket extends BasePacket {

private final int amount;
private final boolean craftMissingAmount;
private final boolean autoStart;

public ConfirmAutoCraftPacket(FriendlyByteBuf stream) {
this.autoStart = stream.readBoolean();
this.craftMissingAmount = stream.readBoolean();
this.amount = stream.readInt();
}

public ConfirmAutoCraftPacket(int craftAmt, boolean autoStart) {
public ConfirmAutoCraftPacket(int craftAmt, boolean craftMissingAmount, boolean autoStart) {
this.amount = craftAmt;
this.craftMissingAmount = craftMissingAmount;
this.autoStart = autoStart;

final FriendlyByteBuf data = new FriendlyByteBuf(Unpooled.buffer());
data.writeInt(this.getPacketID());
data.writeBoolean(autoStart);
data.writeBoolean(craftMissingAmount);
data.writeInt(this.amount);
this.configureWrite(data);
}

@Override
public void serverPacketData(ServerPlayer player) {
if (player.containerMenu instanceof CraftAmountMenu menu) {
menu.confirm(amount, autoStart);
menu.confirm(amount, craftMissingAmount, autoStart);
}
}
}
52 changes: 37 additions & 15 deletions src/main/java/appeng/menu/me/crafting/CraftAmountMenu.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@

import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.MenuType;
import net.minecraft.world.level.Level;

Expand Down Expand Up @@ -103,31 +102,54 @@ private void setWhatToCraft(AEKey whatToCraft, int initialAmount) {
* Confirms the craft request. If called client-side, automatically sends a packet to the server to perform the
* action there instead.
*
* @param amount The number of items to craft.
* @param autoStart Start crafting immediately when the planning is done.
* @param amount The number of items to craft.
* @param craftMissingAmount Craft only as much as needed to have <code>amount</code>
* @param autoStart Start crafting immediately when the planning is done.
*/
public void confirm(int amount, boolean autoStart) {
public void confirm(int amount, boolean craftMissingAmount, boolean autoStart) {
if (!isServerSide()) {
NetworkHandler.instance().sendToServer(new ConfirmAutoCraftPacket(amount, autoStart));
NetworkHandler.instance().sendToServer(new ConfirmAutoCraftPacket(amount, craftMissingAmount, autoStart));
return;
}

if (this.whatToCraft == null) {
return;
}

if (craftMissingAmount) {
var host = getActionHost();
if (host != null) {
var node = host.getActionableNode();
if (node != null) {
var storage = node.getGrid().getStorageService();
var existingAmount = (int) Math.min(storage.getCachedInventory().get(whatToCraft),
Integer.MAX_VALUE);
if (existingAmount > amount) {
amount = 0;
} else {
amount -= existingAmount;
}
}
}
}

var locator = getLocator();
if (locator != null) {
Player player = this.getPlayerInventory().player;
MenuOpener.open(CraftConfirmMenu.TYPE, player, locator);

if (player.containerMenu instanceof CraftConfirmMenu ccc) {
ccc.setAutoStart(autoStart);
ccc.planJob(
whatToCraft,
amount,
CalculationStrategy.REPORT_MISSING_ITEMS);
broadcastChanges();
var player = getPlayer();
if (amount > 0) {
MenuOpener.open(CraftConfirmMenu.TYPE, player, locator);

if (player.containerMenu instanceof CraftConfirmMenu ccc) {
ccc.setAutoStart(autoStart);
ccc.planJob(
whatToCraft,
amount,
CalculationStrategy.REPORT_MISSING_ITEMS);
broadcastChanges();
}
} else {
// When the amount to craft is 0, return to the previous menu without crafting
this.host.returnToMainMenu(player, this);
}
}
}
Expand Down

0 comments on commit 4569032

Please sign in to comment.