Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
3edfe12
Add layout and camera for a crafting plan graph view
claude Oct 11, 2026
855510d
Add a pannable and zoomable graph view for crafting plans
claude Oct 11, 2026
3336244
Default to the crafting plan graph and remember the chosen view
claude Oct 11, 2026
bb6c7b5
Collapse large crafting plan graphs to an overview that fits
claude Oct 11, 2026
7103193
Move crafting plan buttons out of the view toggler
claude Oct 11, 2026
ba466c2
Calm down the crafting plan graph styling
claude Oct 11, 2026
e846aaf
Color the whole path to failed nodes in the crafting plan graph
claude Oct 11, 2026
c9bb478
Animate crafting nodes in the crafting plan graph
claude Oct 11, 2026
06b40bb
Experiment: running border animation for crafting nodes
claude Oct 11, 2026
cb35f97
Use a running border for crafting nodes and fix gaps in flowing edges
claude Oct 11, 2026
08071df
Keep completed jobs in the crafting plan graph and add keyboard controls
claude Oct 11, 2026
f48f9e9
Show collapsed crafting plan graph nodes as a stack with a count pill
claude Oct 11, 2026
553173b
Always show the crafting plan graph legend and stop folding completed…
claude Oct 11, 2026
096c54e
Address review findings in the crafting plan views
claude Oct 11, 2026
ae97d81
Show the root of the crafting plan graph as a larger node
claude Oct 11, 2026
ae428b6
Show crafting jobs whose inputs were refused as blocked instead of fa…
claude Oct 12, 2026
d13965f
Show the graph view button first
claude Oct 12, 2026
c46a51f
Hide the crafting plan tree list view by default
claude Oct 12, 2026
862ff10
Update Integrated Crafting to 1.7.2-840
claude Oct 12, 2026
3c7cf42
Show the progress of crafting jobs in the crafting plan views
claude Oct 12, 2026
30b6373
Only show the crafting plan durations in the progress bar for running…
claude Oct 12, 2026
a7f1b4c
Show the owner and channel of running jobs on the top line of the pla…
claude Oct 12, 2026
f75a781
Update Integrated Crafting to 1.7.2-852
claude Oct 14, 2026
c6146dd
Apply review suggestions for crafting plan graph
claude Oct 16, 2026
61d0c14
Zoom crafting plan graphs smoothly instead of in fixed levels
claude Oct 16, 2026
0abfff8
Rename the default crafting plan view config option to graph
claude Oct 16, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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.30.0-1139
integrateddynamics_version=1.37.1-2122
integratedterminalscompat_version=1.0.0-209
integratedcrafting_version=1.7.1-765
integratedcrafting_version=1.7.2-852
integratedtunnels_version=1.12.0-772
commoncapabilities_version=2.11.6-376
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,10 @@ public class GeneralConfig extends DummyConfig {
public static int terminalStoragePacketMaxInstances = 512;
@ConfigurableProperty(category = "core", comment = "The maximum number of terminal storage crafting recipes that can be sent in a single packet. Reduce this when you have packet overflows.", isCommandable = true, configLocation = ModConfig.Type.SERVER)
public static int terminalStoragePacketMaxRecipes = 128;
@ConfigurableProperty(category = "core", comment = "If crafting plans should default to the tree-based view. If false, it will default to the flattened view.", isCommandable = true, configLocation = ModConfig.Type.COMMON)
public static boolean terminalStorageDefaultToCraftingPlanTree = false;
@ConfigurableProperty(category = "core", comment = "If crafting plans should default to the graph-based view. If false, it will default to the flattened view.", isCommandable = true, configLocation = ModConfig.Type.COMMON)
public static boolean terminalStorageDefaultToCraftingPlanGraph = true;
@ConfigurableProperty(category = "core", comment = "If crafting plans can also be shown as a tree list, next to the graph and compact views.", isCommandable = true, configLocation = ModConfig.Type.CLIENT)
public static boolean terminalStorageCraftingPlanTreeListEnabled = false;
@ConfigurableProperty(category = "core", comment = "The limit for the number of leaves in a tree-based crafting plan after which it won't be sent to the client anymore.", isCommandable = true, configLocation = ModConfig.Type.SERVER)
public static int terminalStorageMaxTreePlanSize = 64;
@ConfigurableProperty(category = "core", comment = "If storage terminals can be ender-upgraded with an eye of ender to gain a tab with the player's ender chest contents.", isCommandable = true, configLocation = ModConfig.Type.SERVER)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,10 @@ public enum TerminalCraftingJobStatus {
*/
PENDING_INPUTS(Helpers.RGBAToInt(245, 172, 3, 150), true, 4),
/**
* The recipe inputs could not be inserted into the crafting handler.
* The recipe inputs could not be inserted into the crafting handler, for example because it is busy.
* They will be inserted again later.
*/
INVALID_INPUTS(Helpers.RGBAToInt(250, 10, 13, 150), true, 5),
INVALID_INPUTS(Helpers.RGBAToInt(245, 120, 3, 150), true, 5),
/**
* The output is actively being crafted.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -315,22 +315,24 @@ protected static <I> void groupDependenciesByPrototype(IndexedEntries indexedEnt
long quantity = IndexedEntries.getQuantity(outputs);

if (plan.getStatus() == TerminalCraftingJobStatus.ERROR
|| plan.getStatus() == TerminalCraftingJobStatus.INVALID
|| plan.getStatus() == TerminalCraftingJobStatus.INVALID_INPUTS) {
|| plan.getStatus() == TerminalCraftingJobStatus.INVALID) {
if (plan.getDependencies().isEmpty()) {
entry.setQuantityMissing(entry.getQuantityMissing() + quantity);
} else {
entry.setQuantityToCraft(entry.getQuantityToCraft() + quantity);
}
}
// Inputs that the target refused are inserted again later
if (plan.getStatus() == TerminalCraftingJobStatus.QUEUEING
|| plan.getStatus() == TerminalCraftingJobStatus.PENDING_DEPENDENCIES
|| plan.getStatus() == TerminalCraftingJobStatus.PENDING_INPUTS
|| plan.getStatus() == TerminalCraftingJobStatus.INVALID_INPUTS
|| plan.getStatus() == TerminalCraftingJobStatus.UNSTARTED) {
entry.setQuantityToCraft(entry.getQuantityToCraft() + quantity);
}
// Finished jobs with nothing left to craft are done, not crafting
if (plan.getStatus() == TerminalCraftingJobStatus.CRAFTING ||
plan.getStatus() == TerminalCraftingJobStatus.FINISHED) {
(plan.getStatus() == TerminalCraftingJobStatus.FINISHED && plan.getCraftingQuantity() > 0)) {
entry.setQuantityCrafting(entry.getQuantityCrafting() + quantity);
}
}
Expand Down Expand Up @@ -559,6 +561,36 @@ public static <I> TerminalCraftingPlanStatic<I> deserialize(HolderLookup.Provide
return plan;
}

/**
* @param craftingPlan A crafting plan.
* @param <I> The plan identifier type.
* @return A copy of the plan in which the plan and all of its dependencies are finished,
* with nothing left to craft and no ingredients left in their buffers.
*/
public static <I> TerminalCraftingPlanStatic<I> asCompleted(ITerminalCraftingPlan<I> craftingPlan) {
return asCompleted(craftingPlan, Collections.emptyMap());
}

/**
* @param craftingPlan A running crafting plan.
* @param knownOutputs Outputs per job id, used instead of the remaining outputs, which are empty once crafted.
* @param <I> The id type.
* @return A copy of the plan in which everything has been crafted.
*/
public static <I> TerminalCraftingPlanStatic<I> asCompleted(ITerminalCraftingPlan<I> craftingPlan,
Map<I, List<IPrototypedIngredient<?, ?>>> knownOutputs) {
List<ITerminalCraftingPlan<I>> dependencies = Lists.newArrayList();
for (ITerminalCraftingPlan<I> dependency : craftingPlan.getDependencies()) {
dependencies.add(asCompleted(dependency, knownOutputs));
}
return new TerminalCraftingPlanStatic<>(craftingPlan.getId(), dependencies,
knownOutputs.getOrDefault(craftingPlan.getId(), craftingPlan.getOutputs()),
TerminalCraftingJobStatus.FINISHED, 0,
Math.max(craftingPlan.getCraftingQuantityTotal(), craftingPlan.getCraftingQuantity()),
Collections.emptyList(), Collections.emptyList(), Label.RUNNING, craftingPlan.getTickDuration(),
craftingPlan.getEstimatedTickDurationTotal(), 0, craftingPlan.getChannel(), craftingPlan.getInitiatorName());
}

public static enum Label {
RUNNING("gui.integratedterminals.terminal_storage.craftingplan.label.running"),
VALID("gui.integratedterminals.terminal_storage.craftingplan.label.valid"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,15 @@
import org.cyclops.cyclopscore.client.gui.component.button.ButtonText;
import org.cyclops.cyclopscore.client.gui.container.ContainerScreenExtended;
import org.cyclops.cyclopscore.helper.GuiHelpers;
import org.cyclops.cyclopscore.helper.Helpers;
import org.cyclops.cyclopscore.helper.L10NHelpers;
import org.cyclops.cyclopscore.helper.RenderHelpers;
import org.cyclops.integrateddynamics.api.part.PartPos;
import org.cyclops.integratedterminals.Capabilities;
import org.cyclops.integratedterminals.IntegratedTerminals;
import org.cyclops.integratedterminals.Reference;
import org.cyclops.integratedterminals.api.terminalstorage.crafting.ITerminalCraftingPlanFlat;
import org.cyclops.integratedterminals.api.terminalstorage.crafting.TerminalCraftingJobStatus;
import org.cyclops.integratedterminals.client.gui.container.component.GuiCraftingPlan;
import org.cyclops.integratedterminals.client.gui.container.component.GuiCraftingPlanProgressBar;
import org.cyclops.integratedterminals.core.client.gui.CraftingJobGuiData;
import org.cyclops.integratedterminals.core.terminalstorage.crafting.HandlerWrappedTerminalCraftingPlan;
import org.cyclops.integratedterminals.inventory.container.ContainerTerminalCraftingJobs;
Expand All @@ -52,11 +51,6 @@ public class ContainerScreenTerminalCraftingJobs extends ContainerScreenExtended
private static final int COLUMN_INFO = 132;
private static final int COLUMN_INFO_SPACING = 6;
private static final int PROGRESS_BAR_OFFSET_Y = 8;
private static final int PROGRESS_BAR_HEIGHT = 8;

private static final int BORDER_COLOR = Helpers.RGBAToInt(0, 0, 0, 180);
private static final int TRACK_COLOR = Helpers.RGBAToInt(0, 0, 0, 100);
private static final int FILL_COLOR = TerminalCraftingJobStatus.CRAFTING.getColor() | 0xFF000000;

private final Player player;

Expand Down Expand Up @@ -196,44 +190,15 @@ protected boolean isHoveringOutputs(HandlerWrappedTerminalCraftingPlan plan, dou
&& mouseX < OUTPUT_SLOT_X + 4 + GuiHelpers.SLOT_SIZE_INNER * outputs;
}

/**
* Draw how far a job has come as a bar, with the time it has been running on the left,
* the completed percentage in the middle, and the estimated time until it is done on the right.
*/
protected void drawProgressBar(GuiGraphics guiGraphics, ITerminalCraftingPlanFlat<?> plan, int x, int y, int width) {
int progress = GuiCraftingPlan.getProgress(plan);
int filled = progress > 0 ? width * progress / 100 : 0;

// A sunken track, so that the numbers inside the bar stay readable over both the track and the fill
guiGraphics.fill(x, y, x + width, y + PROGRESS_BAR_HEIGHT, BORDER_COLOR);
guiGraphics.fill(x + 1, y + 1, x + width - 1, y + PROGRESS_BAR_HEIGHT - 1, TRACK_COLOR);
if (filled > 1) {
guiGraphics.fill(x + 1, y + 1, x + filled - 1, y + PROGRESS_BAR_HEIGHT - 1, FILL_COLOR);
}

long tickDuration = plan.getTickDuration();
if (tickDuration >= 0) {
drawProgressBarString(guiGraphics, GuiCraftingPlan.getDurationValue(tickDuration), x + 2, y);
}
if (progress >= 0) {
String progressString = L10NHelpers.localize("gui.integratedterminals.terminal_crafting_job.craftingplan.progress.short", progress);
drawProgressBarString(guiGraphics, progressString, x + (width - scaledWidth(progressString)) / 2, y);
}
if (plan.getStatus().isValid()) {
String remainingString = GuiCraftingPlan.getDurationValue(plan.getEstimatedTickDurationRemaining());
drawProgressBarString(guiGraphics, remainingString, x + width - 2 - scaledWidth(remainingString), y);
}
GuiCraftingPlanProgressBar.draw(guiGraphics, GuiCraftingPlan.getProgress(plan), plan.getTickDuration(),
plan.getEstimatedTickDurationRemaining(), plan.getStatus().isValid(), x, y, width);
}

protected int scaledWidth(String string) {
return font.width(string) / 2;
}

protected void drawProgressBarString(GuiGraphics guiGraphics, String string, int x, int y) {
RenderHelpers.drawScaledString(guiGraphics.pose(), guiGraphics.bufferSource(), font, string,
x, y + 2, 0.5f, 16777215, true, Font.DisplayMode.NORMAL);
}

protected List<Component> getPlanTooltipLines(ITerminalCraftingPlanFlat<?> plan) {
List<Component> lines = Lists.newArrayList();

Expand Down
Loading
Loading