Skip to content

Commit

Permalink
Normalized crafting progress across items/fluids/etc. (#8266)
Browse files Browse the repository at this point in the history
Fixes #7321, and replace
#8045.

Normalizes the progress of each key type to their "unit" amount (i.e. 1
bucket for fluid) and shows progress in percent.

---------

Co-authored-by: Simba98 <[email protected]>

(cherry picked from commit 5759cb7)
  • Loading branch information
shartte committed Dec 7, 2024
1 parent 41f89e1 commit aa8e68f
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 39 deletions.
4 changes: 2 additions & 2 deletions src/main/java/appeng/client/gui/widgets/CPUSelectionList.java
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ public Tooltip getTooltip(int mouseX, int mouseY) {
Tooltips.ofAmount(currentJob)).append(" ").append(currentJob.what().getDisplayName()));
tooltipLines.add(
ButtonToolTips.CpuStatusCraftedIn.text(
Tooltips.ofNumber(cpu.progress()),
Tooltips.ofPercent(cpu.progress()),
Tooltips.ofDuration(cpu.elapsedTimeNanos(), TimeUnit.NANOSECONDS)));
}
return new Tooltip(tooltipLines);
Expand Down Expand Up @@ -215,7 +215,7 @@ public void drawBackgroundLayer(GuiGraphics guiGraphics, Rect2i bounds, Point mo
infoBar.add(currentJob.what(), 0.6f);

// Draw a bar at the bottom of the button to indicate job progress
var progress = (int) (cpu.progress() * (buttonBg.getSrcWidth() - 1) / Math.max(1, cpu.totalItems()));
var progress = (int) (cpu.progress() * (buttonBg.getSrcWidth() - 1));
guiGraphics.fill(
x + 1,
y + buttonBg.getSrcHeight() - 2,
Expand Down
7 changes: 4 additions & 3 deletions src/main/java/appeng/crafting/execution/CraftingCpuLogic.java
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,8 @@ public int executeCrafting(int maxPatterns, CraftingService craftingService, IEn
for (var expectedContainerItem : expectedContainerItems) {
job.waitingFor.insert(expectedContainerItem.getKey(), expectedContainerItem.getLongValue(),
Actionable.MODULATE);
job.timeTracker.addMaxItems(expectedContainerItem.getLongValue());
job.timeTracker.addMaxItems(expectedContainerItem.getLongValue(),
expectedContainerItem.getKey().getType());
}

cluster.markDirty();
Expand Down Expand Up @@ -275,7 +276,7 @@ public long insert(AEKey what, long amount, Actionable type) {
}

if (type == Actionable.MODULATE) {
job.timeTracker.decrementItems(amount);
job.timeTracker.decrementItems(amount, what.getType()); // Process Fluid and Items
job.waitingFor.extract(what, amount, Actionable.MODULATE);
cluster.markDirty();
}
Expand Down Expand Up @@ -415,7 +416,7 @@ public ElapsedTimeTracker getElapsedTimeTracker() {
if (this.job != null) {
return this.job.timeTracker;
} else {
return new ElapsedTimeTracker(0);
return new ElapsedTimeTracker();
}
}

Expand Down
94 changes: 72 additions & 22 deletions src/main/java/appeng/crafting/execution/ElapsedTimeTracker.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,69 +18,119 @@

package appeng.crafting.execution;

import com.google.common.collect.Iterables;

import net.minecraft.nbt.CompoundTag;
import net.minecraft.util.Mth;

import it.unimi.dsi.fastutil.objects.Reference2LongMap;
import it.unimi.dsi.fastutil.objects.Reference2LongOpenHashMap;

import appeng.api.stacks.AEKeyType;
import appeng.api.stacks.AEKeyTypes;

public class ElapsedTimeTracker {
private static final String NBT_ELAPSED_TIME = "elapsedTime";
private static final String NBT_START_ITEM_COUNT = "startItemCount";
private static final String NBT_REMAINING_ITEM_COUNT = "remainingItemCount";
private static final String NBT_STARTED_WORK = "startedWork";
private static final String NBT_COMPLETED_WORK = "completedWork";

private long lastTime = System.nanoTime();
private long elapsedTime = 0;
// TODO 1.21 rename: "start item count" is not a good name:
// this item count can increase when container items are scheduled.
private long startItemCount;
private long remainingItemCount;

public ElapsedTimeTracker(long startItemCount) {
this.startItemCount = startItemCount;
this.remainingItemCount = startItemCount;

private final Reference2LongMap<AEKeyType> startedWorkByType = new Reference2LongOpenHashMap<>(
Iterables.size(AEKeyTypes.getAll()));
private final Reference2LongMap<AEKeyType> completedWorkByType = new Reference2LongOpenHashMap<>(
Iterables.size(AEKeyTypes.getAll()));

public ElapsedTimeTracker() {
}

public ElapsedTimeTracker(CompoundTag data) {
this.elapsedTime = data.getLong(NBT_ELAPSED_TIME);
this.startItemCount = data.getLong(NBT_START_ITEM_COUNT);
this.remainingItemCount = data.getLong(NBT_REMAINING_ITEM_COUNT);
readLongByTypeMap(data.getCompound(NBT_STARTED_WORK), startedWorkByType);
readLongByTypeMap(data.getCompound(NBT_COMPLETED_WORK), completedWorkByType);
}

public CompoundTag writeToNBT() {
CompoundTag data = new CompoundTag();
data.putLong(NBT_ELAPSED_TIME, elapsedTime);
data.putLong(NBT_START_ITEM_COUNT, startItemCount);
data.putLong(NBT_REMAINING_ITEM_COUNT, remainingItemCount);
data.put(NBT_STARTED_WORK, writeLongByTypeMap(startedWorkByType));
data.put(NBT_COMPLETED_WORK, writeLongByTypeMap(completedWorkByType));
return data;
}

private static void readLongByTypeMap(CompoundTag tag, Reference2LongMap<AEKeyType> output) {
for (var keyType : AEKeyTypes.getAll()) {
output.put(keyType, tag.getLong(keyType.getId().toString()));
}
}

private static CompoundTag writeLongByTypeMap(Reference2LongMap<AEKeyType> input) {
CompoundTag result = new CompoundTag();
for (var entry : input.reference2LongEntrySet()) {
result.putLong(entry.getKey().getId().toString(), entry.getLongValue());
}
return result;
}

private void updateTime() {
long currentTime = System.nanoTime();
this.elapsedTime = this.elapsedTime + (currentTime - this.lastTime);
this.lastTime = currentTime;
}

void decrementItems(long itemDiff) {
void decrementItems(long itemDiff, AEKeyType keyType) {
updateTime();
this.remainingItemCount -= itemDiff;
completedWorkByType.merge(keyType, itemDiff, this::saturatedSum);
}

private long saturatedSum(long a, long b) {
var result = a + b;
return result < 0 ? Long.MAX_VALUE : result;
}

void addMaxItems(long itemDiff) {
void addMaxItems(long itemDiff, AEKeyType keyType) {
updateTime();
this.startItemCount += itemDiff;
this.remainingItemCount += itemDiff;
startedWorkByType.merge(keyType, itemDiff, this::saturatedSum);
}

public long getElapsedTime() {
if (remainingItemCount > 0) {
boolean allDone = true;
for (var keyType : AEKeyTypes.getAll()) {
if (completedWorkByType.getLong(keyType) < startedWorkByType.getLong(keyType)) {
allDone = false;
break;
}
}

if (!allDone) {
return this.elapsedTime + (System.nanoTime() - this.lastTime);
} else {
return this.elapsedTime;
}
}

// TODO: 1.21.4 Change the network packet and screen to use this rather than the counts below
public float getProgress() {
double startedUnits = 0;
double completedUnits = 0;
for (var keyType : AEKeyTypes.getAll()) {
var startedForType = startedWorkByType.getLong(keyType);
var completedForType = completedWorkByType.getLong(keyType);
startedUnits += startedForType / (double) keyType.getAmountPerUnit();
completedUnits += completedForType / (double) keyType.getAmountPerUnit();
}

return Mth.clamp((float) (completedUnits / startedUnits), 0, 1);
}

@Deprecated(forRemoval = true)
public long getRemainingItemCount() {
return this.remainingItemCount;
return (int) (Integer.MAX_VALUE - (double) getProgress() * Integer.MAX_VALUE);
}

@Deprecated(forRemoval = true)
public long getStartItemCount() {
return this.startItemCount;
return Integer.MAX_VALUE;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -70,18 +70,18 @@ interface CraftingDifferenceListener {
this.waitingFor = new ListCraftingInventory(postCraftingDifference::onCraftingDifference);

// Fill waiting for and tasks
long totalPending = 0;
this.timeTracker = new ElapsedTimeTracker();
for (var entry : plan.emittedItems()) {
waitingFor.insert(entry.getKey(), entry.getLongValue(), Actionable.MODULATE);
totalPending += entry.getLongValue();
timeTracker.addMaxItems(entry.getLongValue(), entry.getKey().getType());
}
for (var entry : plan.patternTimes().entrySet()) {
tasks.computeIfAbsent(entry.getKey(), p -> new TaskProgress()).value += entry.getValue();
for (var output : entry.getKey().getOutputs()) {
totalPending += output.amount() * entry.getValue();
var amount = output.amount() * entry.getValue() * output.what().getAmountPerUnit();
timeTracker.addMaxItems(amount, output.what().getType());
}
}
this.timeTracker = new ElapsedTimeTracker(totalPending);
this.link = link;
this.playerId = playerId;
}
Expand Down
16 changes: 8 additions & 8 deletions src/main/java/appeng/menu/me/crafting/CraftingStatusMenu.java
Original file line number Diff line number Diff line change
Expand Up @@ -146,15 +146,18 @@ private CraftingCpuList createCpuList() {
for (var cpu : lastCpuSet) {
var serial = getOrAssignCpuSerial(cpu);
var status = cpu.getJobStatus();
var progress = 0f;
if (status != null && status.totalItems() > 0) {
progress = (float) (status.progress() / (double) status.totalItems());
}
entries.add(new CraftingCpuListEntry(
serial,
cpu.getAvailableStorage(),
cpu.getCoProcessors(),
cpu.getName(),
cpu.getSelectionMode(),
status != null ? status.crafting() : null,
status != null ? status.totalItems() : 0,
status != null ? status.progress() : 0,
progress,
status != null ? status.elapsedTimeNanos() : 0));
}
entries.sort(CPU_COMPARATOR);
Expand Down Expand Up @@ -225,8 +228,7 @@ public record CraftingCpuListEntry(
Component name,
CpuSelectionMode mode,
GenericStack currentJob,
long totalItems,
long progress,
float progress,
long elapsedTimeNanos) {
public static CraftingCpuListEntry readFromPacket(FriendlyByteBuf data) {
return new CraftingCpuListEntry(
Expand All @@ -236,8 +238,7 @@ public static CraftingCpuListEntry readFromPacket(FriendlyByteBuf data) {
data.readBoolean() ? data.readComponent() : null,
data.readEnum(CpuSelectionMode.class),
GenericStack.readBuffer(data),
data.readVarLong(),
data.readVarLong(),
data.readFloat(),
data.readVarLong());
}

Expand All @@ -251,8 +252,7 @@ public void writeToPacket(FriendlyByteBuf data) {
}
data.writeEnum(mode);
GenericStack.writeBuffer(currentJob, data);
data.writeVarLong(totalItems);
data.writeVarLong(progress);
data.writeFloat(progress);
data.writeVarLong(elapsedTimeNanos);
}
}
Expand Down

0 comments on commit aa8e68f

Please sign in to comment.