Skip to content
Merged
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,6 @@ org.gradle.caching=true
cyclopscore_version=1.26.2-808
integrateddynamics_version=1.32.0-1630
integratedterminalscompat_version=1.0.0-167
integratedcrafting_version=1.4.1-442
integratedcrafting_version=1.5.0-689
integratedtunnels_version=1.8.44-484
commoncapabilities_version=2.9.12-263
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ public class GeneralConfig extends DummyConfig {
@ConfigurableProperty(category = "machine", comment = "The update frequency in milliseconds for the crafting jobs gui.", isCommandable = true)
public static int guiTerminalCraftingJobsUpdateFrequency = 1000;

@ConfigurableProperty(category = "machine", comment = "If a toast should be shown when a crafting job that you requested has been completed.", isCommandable = true, configLocation = ModConfig.Type.CLIENT)
public static boolean craftingJobFinishedToast = true;

@ConfigurableProperty(category = "core", comment = "The number of threads that the crafting plan calculator can use.", minimalValue = 1, requiresMcRestart = true, configLocation = ModConfig.Type.SERVER)
public static int craftingPlannerThreads = 2;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,8 +157,23 @@ public default ITerminalCraftingPlanFlat<I> deserializeCraftingPlanFlat(HolderLo
* @param player The player that started the crafting job.
* @throws CraftingJobStartException If the crafting job failed to start.
*/
@Deprecated // TODO: rm in next major
public default void startCraftingJob(INetwork network, int channel, ITerminalCraftingPlan<I> craftingPlan,
ServerPlayer player) throws CraftingJobStartException {
startCraftingJob(network, channel, craftingPlan, player, true);
}

/**
* Start the given crafting plan.
* @param network The network in which the plan should be started.
* @param channel The channel to get the options for.
* @param craftingPlan A crafting plan.
* @param player The player that started the crafting job.
* @param notifyOnCompletion If the player wants to be notified once the crafting job is completed.
* @throws CraftingJobStartException If the crafting job failed to start.
*/
public void startCraftingJob(INetwork network, int channel, ITerminalCraftingPlan<I> craftingPlan,
ServerPlayer player) throws CraftingJobStartException;
ServerPlayer player, boolean notifyOnCompletion) throws CraftingJobStartException;

/**
* @param network The network in which the plan should be started.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import net.minecraft.ChatFormatting;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.components.Checkbox;
import net.minecraft.client.gui.components.Tooltip;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
Expand Down Expand Up @@ -51,7 +53,7 @@ public ContainerScreenTerminalStorageCraftingPlan(C container, Inventory invento
addRenderableWidget(this.guiCraftingPlan);

if (this.craftingPlanFlat != null) {
addRenderableWidget(new ButtonText(leftPos + 8, topPos + 198, 80, 20,
addRenderableWidget(new ButtonText(leftPos + 8, topPos + 198, 62, 20,
Component.translatable("gui.integratedterminals.craftingplan.view.flat"),
Component.translatable("gui.integratedterminals.craftingplan.view.flat").withStyle(ChatFormatting.ITALIC),
(b) -> {
Expand All @@ -66,7 +68,7 @@ public ContainerScreenTerminalStorageCraftingPlan(C container, Inventory invento
addRenderableWidget(this.guiCraftingPlanFlat);

if (this.craftingPlan != null) {
addRenderableWidget(new ButtonText(leftPos + 8, topPos + 198, 80, 20,
addRenderableWidget(new ButtonText(leftPos + 8, topPos + 198, 62, 20,
Component.translatable("gui.integratedterminals.craftingplan.view.tree"),
Component.translatable("gui.integratedterminals.craftingplan.view.tree").withStyle(ChatFormatting.ITALIC),
(b) -> {
Expand Down Expand Up @@ -121,6 +123,13 @@ public void init() {
(b) -> returnToCraftingOptionAmount(),
true));

addRenderableWidget(Checkbox.builder(Component.translatable("gui.integratedterminals.terminal_storage.step.craft.notify"), font)
.pos(leftPos + 72, topPos + 200)
.selected(getMenu().isNotifyOnCompletion())
.tooltip(Tooltip.create(Component.translatable("gui.integratedterminals.terminal_storage.step.craft.notify.info")))
.onValueChange((widget, selected) -> getMenu().setNotifyOnCompletion(selected))
.build());

addRenderableWidget(buttonConfirm = new ButtonText(leftPos + 221 + 10 - 50, topPos + 198, 50, 20,
Component.translatable("gui.integratedterminals.terminal_storage.step.craft"),
Component.translatable("gui.integratedterminals.terminal_storage.step.craft").withStyle(ChatFormatting.YELLOW),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
package org.cyclops.integratedterminals.client.gui.toast;

import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.components.toasts.Toast;
import net.minecraft.client.gui.components.toasts.ToastComponent;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.FormattedCharSequence;
import org.cyclops.commoncapabilities.api.ingredient.IngredientComponent;
import org.cyclops.integratedterminals.Capabilities;
import org.cyclops.integratedterminals.Reference;
import org.cyclops.integratedterminals.client.gui.container.ContainerScreenTerminalStorage;

import java.util.List;

/**
* A toast that shows an ingredient icon alongside a title and a wrapping subtitle.
*
* Toasts with an equal token replace each other instead of being queued,
* so the token determines how toasts are grouped.
*
* @param <T> The instance type.
* @param <M> The matching condition parameter.
* @author rubensworks
*/
public class CraftingJobToast<T, M> implements Toast {

private static final ResourceLocation BACKGROUND_SPRITE = ResourceLocation.fromNamespaceAndPath(Reference.MOD_ID, "toast/crafting_job");
private static final int DISPLAY_MILLIS = 5000;
private static final int MARGIN = 7;
private static final int ICON_LEFT = 7;
private static final int ICON_SIZE = 16;
private static final int TEXT_LEFT = ICON_LEFT + ICON_SIZE + 5;
private static final int LINE_SPACING = 12;

private final Object token;
private final IngredientComponent<T, M> ingredientComponent;
private T instance;
private Component title;
private List<FormattedCharSequence> subtitleLines;
private long lastChangedAt = Long.MIN_VALUE;
private boolean changed = true;

public CraftingJobToast(Object token, IngredientComponent<T, M> ingredientComponent, T instance,
Component title, Component subtitle) {
this.token = token;
this.ingredientComponent = ingredientComponent;
this.instance = instance;
this.title = title;
this.subtitleLines = splitSubtitle(subtitle);
}

public IngredientComponent<T, M> getIngredientComponent() {
return ingredientComponent;
}

/**
* @return The shown output, where the quantity is the total that was crafted.
*/
public T getInstance() {
return instance;
}

/**
* Update the contents of this toast in-place, without queueing a new one.
* @param newInstance The new output.
* @param newTitle The new title.
* @param newSubtitle The new subtitle.
*/
public void reset(T newInstance, Component newTitle, Component newSubtitle) {
this.instance = newInstance;
this.title = newTitle;
this.subtitleLines = splitSubtitle(newSubtitle);
this.changed = true;
}

private List<FormattedCharSequence> splitSubtitle(Component text) {
return Minecraft.getInstance().font.split(text, width() - TEXT_LEFT - MARGIN);
}

@Override
public int height() {
return 20 + Math.max(1, subtitleLines.size()) * LINE_SPACING;
}

@Override
public Visibility render(GuiGraphics graphics, ToastComponent toastComponent, long timeSinceLastVisible) {
if (changed) {
lastChangedAt = timeSinceLastVisible;
changed = false;
}

graphics.blitSprite(BACKGROUND_SPRITE, 0, 0, width(), height());

// Drawing through the storage handler keeps this working for items, fluids, energy, and any
// ingredient component that other mods add. No screen is needed, as the background layer
// draws the instance itself and only the foreground layer renders tooltips.
this.ingredientComponent.getCapability(Capabilities.IngredientComponentTerminalStorageHandler.INGREDIENT)
.ifPresent(handler -> handler.drawInstance(graphics, this.instance,
this.ingredientComponent.getMatcher().getQuantity(this.instance), null, null,
ContainerScreenTerminalStorage.DrawLayer.BACKGROUND, 0, ICON_LEFT, 8, 0, 0, null));

var font = toastComponent.getMinecraft().font;
graphics.drawString(font, title, TEXT_LEFT, 7, 0xFFFFFF, false);
for (int i = 0; i < subtitleLines.size(); i++) {
graphics.drawString(font, subtitleLines.get(i), TEXT_LEFT, 18 + i * LINE_SPACING, 0xAAAAAA, false);
}

return timeSinceLastVisible - lastChangedAt < (long) (DISPLAY_MILLIS * toastComponent.getNotificationDisplayTimeMultiplier())
? Visibility.SHOW
: Visibility.HIDE;
}

@Override
public Object getToken() {
return token;
}

}
Loading
Loading