缺失强制下单
This commit is contained in:
parent
16a5fab01e
commit
9cee5f27e2
|
|
@ -0,0 +1,7 @@
|
|||
package com.extendedae_plus.api.crafting;
|
||||
|
||||
public interface IForceCraftStartSync {
|
||||
void eap$clientSetForceCraftStart(boolean forceStart);
|
||||
|
||||
boolean eap$consumeForceCraftStartFlag();
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
package com.extendedae_plus.api.crafting;
|
||||
|
||||
import appeng.api.stacks.KeyCounter;
|
||||
|
||||
public interface IForcedCraftingPlan {
|
||||
KeyCounter eap$getManualMissingItems();
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
package com.extendedae_plus.api.crafting;
|
||||
|
||||
import appeng.api.stacks.AEKey;
|
||||
import appeng.api.stacks.KeyCounter;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public interface IManualCraftingState {
|
||||
void eap$setManualWaiting(KeyCounter manualWaiting);
|
||||
|
||||
long eap$getManualWaitingAmount(AEKey what);
|
||||
|
||||
Map<AEKey, Long> eap$getManualWaitingSnapshot();
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
package com.extendedae_plus.content;
|
||||
|
||||
import appeng.api.stacks.AEKey;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public final class ClientManualCraftingStatusStore {
|
||||
private static volatile int containerId = -1;
|
||||
private static volatile Map<AEKey, Long> manualWaiting = Collections.emptyMap();
|
||||
|
||||
private ClientManualCraftingStatusStore() {
|
||||
}
|
||||
|
||||
public static void setStatus(int menuContainerId, Map<AEKey, Long> snapshot) {
|
||||
containerId = menuContainerId;
|
||||
manualWaiting = Collections.unmodifiableMap(new LinkedHashMap<>(snapshot));
|
||||
}
|
||||
|
||||
public static long getManualWaitingAmount(int menuContainerId, AEKey key) {
|
||||
if (key == null || menuContainerId != containerId) {
|
||||
return 0;
|
||||
}
|
||||
return manualWaiting.getOrDefault(key, 0L);
|
||||
}
|
||||
|
||||
public static void clear() {
|
||||
containerId = -1;
|
||||
manualWaiting = Collections.emptyMap();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
package com.extendedae_plus.crafting;
|
||||
|
||||
import appeng.api.crafting.IPatternDetails;
|
||||
import appeng.api.networking.crafting.ICraftingPlan;
|
||||
import appeng.api.stacks.GenericStack;
|
||||
import appeng.api.stacks.KeyCounter;
|
||||
import com.extendedae_plus.api.crafting.IForcedCraftingPlan;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class ForcedCraftingPlan implements ICraftingPlan, IForcedCraftingPlan {
|
||||
private final ICraftingPlan delegate;
|
||||
private final KeyCounter manualMissingItems;
|
||||
|
||||
public ForcedCraftingPlan(ICraftingPlan delegate) {
|
||||
this.delegate = delegate;
|
||||
this.manualMissingItems = copy(delegate.missingItems());
|
||||
}
|
||||
|
||||
@Override
|
||||
public KeyCounter eap$getManualMissingItems() {
|
||||
return copy(this.manualMissingItems);
|
||||
}
|
||||
|
||||
@Override
|
||||
public GenericStack finalOutput() {
|
||||
return this.delegate.finalOutput();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long bytes() {
|
||||
return this.delegate.bytes();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean simulation() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean multiplePaths() {
|
||||
return this.delegate.multiplePaths();
|
||||
}
|
||||
|
||||
@Override
|
||||
public KeyCounter usedItems() {
|
||||
return this.delegate.usedItems();
|
||||
}
|
||||
|
||||
@Override
|
||||
public KeyCounter emittedItems() {
|
||||
return this.delegate.emittedItems();
|
||||
}
|
||||
|
||||
@Override
|
||||
public KeyCounter missingItems() {
|
||||
return new KeyCounter();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<IPatternDetails, Long> patternTimes() {
|
||||
return this.delegate.patternTimes();
|
||||
}
|
||||
|
||||
private static KeyCounter copy(KeyCounter source) {
|
||||
var copy = new KeyCounter();
|
||||
for (var entry : source) {
|
||||
copy.add(entry.getKey(), entry.getLongValue());
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,8 @@ package com.extendedae_plus.init;
|
|||
|
||||
import com.extendedae_plus.ExtendedAEPlus;
|
||||
import com.extendedae_plus.network.*;
|
||||
import com.extendedae_plus.network.crafting.ForceCraftStartFlagC2SPacket;
|
||||
import com.extendedae_plus.network.crafting.ManualCraftingStatusS2CPacket;
|
||||
import com.extendedae_plus.network.packet.EAPConfigButtonPacket;
|
||||
import com.extendedae_plus.network.upload.EncodeWithShiftFlagC2SPacket;
|
||||
import net.neoforged.neoforge.network.event.RegisterPayloadHandlersEvent;
|
||||
|
|
@ -57,6 +59,12 @@ public class ModNetwork {
|
|||
registrar.playToClient(com.extendedae_plus.network.LabelNetworkListS2CPacket.TYPE,
|
||||
com.extendedae_plus.network.LabelNetworkListS2CPacket.STREAM_CODEC,
|
||||
com.extendedae_plus.network.LabelNetworkListS2CPacket::handle);
|
||||
registrar.playToServer(ForceCraftStartFlagC2SPacket.TYPE,
|
||||
ForceCraftStartFlagC2SPacket.STREAM_CODEC,
|
||||
ForceCraftStartFlagC2SPacket::handle);
|
||||
registrar.playToClient(ManualCraftingStatusS2CPacket.TYPE,
|
||||
ManualCraftingStatusS2CPacket.STREAM_CODEC,
|
||||
ManualCraftingStatusS2CPacket::handle);
|
||||
|
||||
registrar.playToServer(EAPConfigButtonPacket.TYPE, EAPConfigButtonPacket.STREAM_CODEC, EAPConfigButtonPacket::handleOnServer);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
package com.extendedae_plus.mixin.ae2.accessor;
|
||||
|
||||
import appeng.api.crafting.IPatternDetails;
|
||||
import appeng.api.stacks.GenericStack;
|
||||
import appeng.crafting.CraftingLink;
|
||||
import appeng.crafting.execution.ExecutingCraftingJob;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
|
|
@ -11,4 +13,16 @@ import java.util.Map;
|
|||
public interface ExecutingCraftingJobAccessor {
|
||||
@Accessor("tasks")
|
||||
Map<IPatternDetails, ExecutingCraftingJobTaskProgressAccessor> eap$getTasks();
|
||||
|
||||
@Accessor("finalOutput")
|
||||
GenericStack eap$getFinalOutput();
|
||||
|
||||
@Accessor("remainingAmount")
|
||||
long eap$getRemainingAmount();
|
||||
|
||||
@Accessor("remainingAmount")
|
||||
void eap$setRemainingAmount(long remainingAmount);
|
||||
|
||||
@Accessor("link")
|
||||
CraftingLink eap$getLink();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,14 +3,17 @@ package com.extendedae_plus.mixin.ae2.client.gui;
|
|||
import appeng.client.gui.WidgetContainer;
|
||||
import appeng.client.gui.me.crafting.CraftConfirmScreen;
|
||||
import appeng.core.localization.GuiText;
|
||||
import appeng.menu.me.crafting.CraftingPlanSummary;
|
||||
import com.extendedae_plus.mixin.ae2.accessor.AEBaseScreenAccessor;
|
||||
import com.extendedae_plus.mixin.ae2.accessor.WidgetContainerAccessor;
|
||||
import com.extendedae_plus.network.crafting.ForceCraftStartFlagC2SPacket;
|
||||
import net.minecraft.client.gui.components.AbstractWidget;
|
||||
import net.minecraft.client.gui.components.Button;
|
||||
import net.minecraft.client.gui.components.Tooltip;
|
||||
import net.minecraft.client.gui.screens.Screen;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.neoforged.fml.ModList;
|
||||
import net.neoforged.neoforge.network.PacketDistributor;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
|
|
@ -27,22 +30,48 @@ public class CraftConfirmScreenMixin {
|
|||
private static final Component EAP_BOOKMARK_TEXT = Component.translatable("gui.extendedae_plus.add_bookmark");
|
||||
@Unique
|
||||
private static final Component EAP_BOOKMARK_TOOLTIP = Component.translatable("tooltip.extendedae_plus.add_missing_to_jei_bookmark");
|
||||
@Unique
|
||||
private static final Component EAP_START_TEXT = GuiText.Start.text();
|
||||
@Unique
|
||||
private static final Component EAP_FORCE_START_TEXT = Component.translatable("gui.extendedae_plus.force_start");
|
||||
@Unique
|
||||
private static final Component EAP_FORCE_START_TOOLTIP = Component.translatable("tooltip.extendedae_plus.force_start");
|
||||
|
||||
@Inject(method = "updateBeforeRender", at = @At("TAIL"), remap = false)
|
||||
private void eap$updateCancelButtonText(CallbackInfo ci) {
|
||||
if (!ModList.get().isLoaded("jei")){
|
||||
return;
|
||||
}
|
||||
|
||||
private void eap$updateButtons(CallbackInfo ci) {
|
||||
CraftConfirmScreen self = (CraftConfirmScreen) (Object) this;
|
||||
try {
|
||||
WidgetContainer widgets = ((AEBaseScreenAccessor<?>) self).eap$getWidgets();
|
||||
if (widgets == null) return;
|
||||
|
||||
AbstractWidget cancelWidget = ((WidgetContainerAccessor) widgets).eap$getWidgetsMap().get("cancel");
|
||||
if (!(cancelWidget instanceof Button cancelButton)) return;
|
||||
|
||||
var widgetsMap = ((WidgetContainerAccessor) widgets).eap$getWidgetsMap();
|
||||
boolean shiftDown = Screen.hasShiftDown();
|
||||
CraftingPlanSummary plan = self.getMenu().getPlan();
|
||||
boolean forceStart = shiftDown && plan != null && plan.isSimulation();
|
||||
|
||||
AbstractWidget startWidget = widgetsMap.get("start");
|
||||
if (startWidget instanceof Button startButton) {
|
||||
if (forceStart) {
|
||||
startButton.active = !self.getMenu().hasNoCPU();
|
||||
startButton.setMessage(EAP_FORCE_START_TEXT);
|
||||
startButton.setTooltip(Tooltip.create(EAP_FORCE_START_TOOLTIP));
|
||||
} else {
|
||||
startButton.setMessage(EAP_START_TEXT);
|
||||
startButton.setTooltip(null);
|
||||
}
|
||||
}
|
||||
|
||||
AbstractWidget selectCpuWidget = widgetsMap.get("selectCpu");
|
||||
if (forceStart && selectCpuWidget instanceof Button selectCpuButton) {
|
||||
selectCpuButton.active = true;
|
||||
}
|
||||
|
||||
if (!ModList.get().isLoaded("jei")) {
|
||||
return;
|
||||
}
|
||||
|
||||
AbstractWidget cancelWidget = widgetsMap.get("cancel");
|
||||
if (!(cancelWidget instanceof Button cancelButton)) return;
|
||||
|
||||
if (shiftDown) {
|
||||
cancelButton.setMessage(EAP_BOOKMARK_TEXT);
|
||||
|
|
@ -54,4 +83,12 @@ public class CraftConfirmScreenMixin {
|
|||
} catch (Throwable ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "start", at = @At("HEAD"), remap = false)
|
||||
private void eap$syncForceStartFlagBeforeStart(CallbackInfo ci) {
|
||||
CraftConfirmScreen self = (CraftConfirmScreen) (Object) this;
|
||||
var plan = self.getMenu().getPlan();
|
||||
boolean forceStart = Screen.hasShiftDown() && plan != null && plan.isSimulation();
|
||||
PacketDistributor.sendToServer(new ForceCraftStartFlagC2SPacket(forceStart));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,68 @@
|
|||
package com.extendedae_plus.mixin.ae2.client.gui;
|
||||
|
||||
import appeng.api.stacks.AmountFormat;
|
||||
import appeng.api.util.AEColor;
|
||||
import appeng.client.gui.me.crafting.CraftingCPUScreen;
|
||||
import appeng.client.gui.me.crafting.CraftingStatusTableRenderer;
|
||||
import appeng.core.AEConfig;
|
||||
import appeng.menu.me.crafting.CraftingStatusEntry;
|
||||
import com.extendedae_plus.content.ClientManualCraftingStatusStore;
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Mixin(value = CraftingStatusTableRenderer.class, remap = false)
|
||||
public abstract class CraftingStatusTableRendererMixin {
|
||||
@Unique
|
||||
private static final int EAP_BACKGROUND_ALPHA = 0x5A000000;
|
||||
|
||||
@Inject(method = "getEntryBackgroundColor", at = @At("RETURN"), cancellable = true)
|
||||
private void eap$markManualWaitingEntries(CraftingStatusEntry entry, CallbackInfoReturnable<Integer> cir) {
|
||||
if (!AEConfig.instance().isUseColoredCraftingStatus()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.eap$getManualWaitingAmount(entry) > 0) {
|
||||
cir.setReturnValue(AEColor.PURPLE.blackVariant | EAP_BACKGROUND_ALPHA);
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "getEntryTooltip", at = @At("RETURN"), cancellable = true)
|
||||
private void eap$appendManualWaitingTooltip(CraftingStatusEntry entry,
|
||||
CallbackInfoReturnable<List<Component>> cir) {
|
||||
long manualWaiting = this.eap$getManualWaitingAmount(entry);
|
||||
if (manualWaiting <= 0 || entry.getWhat() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
List<Component> lines = new ArrayList<>(cir.getReturnValue());
|
||||
lines.add(Component.translatable(
|
||||
"tooltip.extendedae_plus.crafting.manual_waiting",
|
||||
entry.getWhat().formatAmount(manualWaiting, AmountFormat.FULL)).withStyle(ChatFormatting.AQUA));
|
||||
cir.setReturnValue(lines);
|
||||
}
|
||||
|
||||
@Unique
|
||||
private long eap$getManualWaitingAmount(CraftingStatusEntry entry) {
|
||||
if (entry == null || entry.getWhat() == null) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
var mc = Minecraft.getInstance();
|
||||
if (mc == null || !(mc.screen instanceof CraftingCPUScreen<?> craftingScreen)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ClientManualCraftingStatusStore.getManualWaitingAmount(
|
||||
craftingScreen.getMenu().containerId,
|
||||
entry.getWhat());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,171 @@
|
|||
package com.extendedae_plus.mixin.ae2.crafting;
|
||||
|
||||
import appeng.api.config.Actionable;
|
||||
import appeng.api.networking.IGrid;
|
||||
import appeng.api.networking.crafting.ICraftingPlan;
|
||||
import appeng.api.networking.crafting.ICraftingRequester;
|
||||
import appeng.api.networking.crafting.ICraftingSubmitResult;
|
||||
import appeng.api.networking.security.IActionSource;
|
||||
import appeng.api.stacks.AEKey;
|
||||
import appeng.api.stacks.KeyCounter;
|
||||
import appeng.crafting.execution.CraftingCpuLogic;
|
||||
import appeng.crafting.execution.ExecutingCraftingJob;
|
||||
import appeng.crafting.inv.ListCraftingInventory;
|
||||
import appeng.me.cluster.implementations.CraftingCPUCluster;
|
||||
import com.extendedae_plus.api.crafting.IForcedCraftingPlan;
|
||||
import com.extendedae_plus.api.crafting.IManualCraftingState;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
@Mixin(value = CraftingCpuLogic.class, remap = false)
|
||||
public abstract class CraftingCpuLogicManualWaitingMixin implements IManualCraftingState {
|
||||
@Shadow
|
||||
private CraftingCPUCluster cluster;
|
||||
|
||||
@Shadow
|
||||
private ExecutingCraftingJob job;
|
||||
|
||||
@Shadow
|
||||
private ListCraftingInventory inventory;
|
||||
|
||||
@Shadow
|
||||
protected abstract void postChange(AEKey what);
|
||||
|
||||
@Unique
|
||||
private final Map<AEKey, Long> eap$manualWaitingFor = new LinkedHashMap<>();
|
||||
|
||||
@Override
|
||||
public void eap$setManualWaiting(KeyCounter manualWaiting) {
|
||||
this.eap$clearManualWaitingInternal(false);
|
||||
for (var entry : manualWaiting) {
|
||||
if (entry.getKey() != null && entry.getLongValue() > 0) {
|
||||
this.eap$manualWaitingFor.put(entry.getKey(), entry.getLongValue());
|
||||
this.postChange(entry.getKey());
|
||||
}
|
||||
}
|
||||
if (!this.eap$manualWaitingFor.isEmpty()) {
|
||||
this.cluster.markDirty();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long eap$getManualWaitingAmount(AEKey what) {
|
||||
if (what == null) {
|
||||
return 0;
|
||||
}
|
||||
return this.eap$manualWaitingFor.getOrDefault(what, 0L);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<AEKey, Long> eap$getManualWaitingSnapshot() {
|
||||
return new LinkedHashMap<>(this.eap$manualWaitingFor);
|
||||
}
|
||||
|
||||
@Inject(method = "trySubmitJob", at = @At("RETURN"))
|
||||
private void eap$initManualWaitingForForcedPlan(IGrid grid, ICraftingPlan plan, IActionSource src,
|
||||
@Nullable ICraftingRequester requester, CallbackInfoReturnable<ICraftingSubmitResult> cir) {
|
||||
if (!cir.getReturnValue().successful()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (plan instanceof IForcedCraftingPlan forcedPlan) {
|
||||
this.eap$setManualWaiting(forcedPlan.eap$getManualMissingItems());
|
||||
} else {
|
||||
this.eap$clearManualWaitingInternal(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "insert", at = @At("RETURN"), cancellable = true)
|
||||
private void eap$consumeManualWaitingAfterVanilla(AEKey what, long amount, Actionable type,
|
||||
CallbackInfoReturnable<Long> cir) {
|
||||
long vanillaInserted = cir.getReturnValue();
|
||||
if (what == null || this.job == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
long remainingAmount = amount - vanillaInserted;
|
||||
if (remainingAmount <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
long manualWaiting = this.eap$getManualWaitingAmount(what);
|
||||
if (manualWaiting <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
long consumed = Math.min(remainingAmount, manualWaiting);
|
||||
if (type == Actionable.MODULATE) {
|
||||
this.eap$decreaseManualWaiting(what, consumed);
|
||||
this.cluster.markDirty();
|
||||
this.postChange(what);
|
||||
this.inventory.insert(what, consumed, Actionable.MODULATE);
|
||||
}
|
||||
|
||||
cir.setReturnValue(vanillaInserted + consumed);
|
||||
}
|
||||
|
||||
@Inject(method = "getWaitingFor", at = @At("RETURN"), cancellable = true)
|
||||
private void eap$appendManualWaitingToStatus(AEKey template, CallbackInfoReturnable<Long> cir) {
|
||||
if (template == null) {
|
||||
return;
|
||||
}
|
||||
long manualWaiting = this.eap$getManualWaitingAmount(template);
|
||||
if (manualWaiting > 0) {
|
||||
cir.setReturnValue(cir.getReturnValue() + manualWaiting);
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "getAllWaitingFor", at = @At("TAIL"))
|
||||
private void eap$appendManualWaitingKeys(Set<AEKey> waitingFor, CallbackInfo ci) {
|
||||
waitingFor.addAll(this.eap$manualWaitingFor.keySet());
|
||||
}
|
||||
|
||||
@Inject(method = "getAllItems", at = @At("TAIL"))
|
||||
private void eap$appendManualWaitingItems(KeyCounter out, CallbackInfo ci) {
|
||||
for (var entry : this.eap$manualWaitingFor.entrySet()) {
|
||||
out.add(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "finishJob", at = @At("HEAD"))
|
||||
private void eap$clearManualWaitingOnFinish(boolean success, CallbackInfo ci) {
|
||||
this.eap$clearManualWaitingInternal(true);
|
||||
}
|
||||
|
||||
@Unique
|
||||
private void eap$decreaseManualWaiting(AEKey what, long amount) {
|
||||
long current = this.eap$manualWaitingFor.getOrDefault(what, 0L);
|
||||
if (current <= amount) {
|
||||
this.eap$manualWaitingFor.remove(what);
|
||||
} else {
|
||||
this.eap$manualWaitingFor.put(what, current - amount);
|
||||
}
|
||||
}
|
||||
|
||||
@Unique
|
||||
private void eap$clearManualWaitingInternal(boolean notifyChanges) {
|
||||
if (this.eap$manualWaitingFor.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
var previousKeys = new ArrayList<>(this.eap$manualWaitingFor.keySet());
|
||||
this.eap$manualWaitingFor.clear();
|
||||
if (notifyChanges) {
|
||||
for (var key : previousKeys) {
|
||||
this.postChange(key);
|
||||
}
|
||||
}
|
||||
this.cluster.markDirty();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
package com.extendedae_plus.mixin.ae2.menu;
|
||||
|
||||
import appeng.api.networking.crafting.ICraftingPlan;
|
||||
import appeng.menu.me.crafting.CraftConfirmMenu;
|
||||
import com.extendedae_plus.api.crafting.IForceCraftStartSync;
|
||||
import com.extendedae_plus.crafting.ForcedCraftingPlan;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(value = CraftConfirmMenu.class, remap = false)
|
||||
public abstract class CraftConfirmMenuForceStartMixin implements IForceCraftStartSync {
|
||||
@Shadow
|
||||
private ICraftingPlan result;
|
||||
|
||||
@Unique
|
||||
private boolean eap$pendingForceCraftStart;
|
||||
|
||||
@Unique
|
||||
private ICraftingPlan eap$originalSimulationResult;
|
||||
|
||||
@Override
|
||||
public void eap$clientSetForceCraftStart(boolean forceStart) {
|
||||
this.eap$pendingForceCraftStart = forceStart;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean eap$consumeForceCraftStartFlag() {
|
||||
boolean flag = this.eap$pendingForceCraftStart;
|
||||
this.eap$pendingForceCraftStart = false;
|
||||
return flag;
|
||||
}
|
||||
|
||||
@Inject(method = "startJob", at = @At("HEAD"))
|
||||
private void eap$wrapSimulationPlanForForceStart(CallbackInfo ci) {
|
||||
CraftConfirmMenu self = (CraftConfirmMenu) (Object) this;
|
||||
if (self.isClientSide()) {
|
||||
return;
|
||||
}
|
||||
if (!this.eap$consumeForceCraftStartFlag()) {
|
||||
return;
|
||||
}
|
||||
if (this.result == null || !this.result.simulation()) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.eap$originalSimulationResult = this.result;
|
||||
this.result = new ForcedCraftingPlan(this.result);
|
||||
}
|
||||
|
||||
@Inject(method = "startJob", at = @At("RETURN"))
|
||||
private void eap$restoreOriginalPlanAfterSubmit(CallbackInfo ci) {
|
||||
if (this.eap$originalSimulationResult == null) {
|
||||
return;
|
||||
}
|
||||
this.result = this.eap$originalSimulationResult;
|
||||
this.eap$originalSimulationResult = null;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
package com.extendedae_plus.mixin.ae2.menu;
|
||||
|
||||
import appeng.api.stacks.AEKey;
|
||||
import appeng.me.cluster.implementations.CraftingCPUCluster;
|
||||
import appeng.menu.me.crafting.CraftingCPUMenu;
|
||||
import com.extendedae_plus.api.crafting.IManualCraftingState;
|
||||
import com.extendedae_plus.network.crafting.ManualCraftingStatusS2CPacket;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@Mixin(value = CraftingCPUMenu.class, remap = false)
|
||||
public abstract class CraftingCPUMenuManualStatusMixin {
|
||||
@Shadow
|
||||
private CraftingCPUCluster cpu;
|
||||
|
||||
@Unique
|
||||
private Map<AEKey, Long> eap$lastManualWaitingSnapshot = Collections.emptyMap();
|
||||
|
||||
@Inject(method = "broadcastChanges", at = @At("TAIL"))
|
||||
private void eap$syncManualWaitingStatus(CallbackInfo ci) {
|
||||
CraftingCPUMenu self = (CraftingCPUMenu) (Object) this;
|
||||
if (self.isClientSide() || !(self.getPlayer() instanceof ServerPlayer serverPlayer)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Map<AEKey, Long> snapshot = Collections.emptyMap();
|
||||
if (this.cpu != null && this.cpu.craftingLogic instanceof IManualCraftingState manualState) {
|
||||
snapshot = manualState.eap$getManualWaitingSnapshot();
|
||||
}
|
||||
|
||||
if (snapshot.equals(this.eap$lastManualWaitingSnapshot)) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.eap$lastManualWaitingSnapshot = new LinkedHashMap<>(snapshot);
|
||||
serverPlayer.connection.send(new ManualCraftingStatusS2CPacket(self.containerId, snapshot));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
package com.extendedae_plus.network.crafting;
|
||||
|
||||
import appeng.menu.me.crafting.CraftConfirmMenu;
|
||||
import com.extendedae_plus.ExtendedAEPlus;
|
||||
import com.extendedae_plus.api.crafting.IForceCraftStartSync;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.network.codec.StreamCodec;
|
||||
import net.minecraft.network.protocol.common.custom.CustomPacketPayload;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.neoforged.neoforge.network.handling.IPayloadContext;
|
||||
|
||||
public class ForceCraftStartFlagC2SPacket implements CustomPacketPayload {
|
||||
public static final Type<ForceCraftStartFlagC2SPacket> TYPE = new Type<>(
|
||||
ResourceLocation.fromNamespaceAndPath(ExtendedAEPlus.MODID, "force_craft_start_flag"));
|
||||
|
||||
public static final StreamCodec<FriendlyByteBuf, ForceCraftStartFlagC2SPacket> STREAM_CODEC = StreamCodec.of(
|
||||
(buf, pkt) -> buf.writeBoolean(pkt.forceStart),
|
||||
buf -> new ForceCraftStartFlagC2SPacket(buf.readBoolean())
|
||||
);
|
||||
|
||||
private final boolean forceStart;
|
||||
|
||||
public ForceCraftStartFlagC2SPacket(boolean forceStart) {
|
||||
this.forceStart = forceStart;
|
||||
}
|
||||
|
||||
public boolean forceStart() {
|
||||
return this.forceStart;
|
||||
}
|
||||
|
||||
public static void handle(final ForceCraftStartFlagC2SPacket msg, final IPayloadContext ctx) {
|
||||
ctx.enqueueWork(() -> {
|
||||
if (!(ctx.player() instanceof ServerPlayer player)) {
|
||||
return;
|
||||
}
|
||||
if (player.containerMenu instanceof CraftConfirmMenu menu
|
||||
&& menu instanceof IForceCraftStartSync sync) {
|
||||
sync.eap$clientSetForceCraftStart(msg.forceStart());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type<? extends CustomPacketPayload> type() {
|
||||
return TYPE;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
package com.extendedae_plus.network.crafting;
|
||||
|
||||
import appeng.api.stacks.AEKey;
|
||||
import com.extendedae_plus.ExtendedAEPlus;
|
||||
import com.extendedae_plus.content.ClientManualCraftingStatusStore;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf;
|
||||
import net.minecraft.network.codec.StreamCodec;
|
||||
import net.minecraft.network.protocol.common.custom.CustomPacketPayload;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.neoforged.api.distmarker.Dist;
|
||||
import net.neoforged.api.distmarker.OnlyIn;
|
||||
import net.neoforged.neoforge.network.handling.IPayloadContext;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class ManualCraftingStatusS2CPacket implements CustomPacketPayload {
|
||||
public static final Type<ManualCraftingStatusS2CPacket> TYPE = new Type<>(
|
||||
ResourceLocation.fromNamespaceAndPath(ExtendedAEPlus.MODID, "manual_crafting_status"));
|
||||
|
||||
public static final StreamCodec<RegistryFriendlyByteBuf, ManualCraftingStatusS2CPacket> STREAM_CODEC = StreamCodec.of(
|
||||
(buf, pkt) -> {
|
||||
buf.writeInt(pkt.containerId);
|
||||
buf.writeVarInt(pkt.manualWaiting.size());
|
||||
for (var entry : pkt.manualWaiting.entrySet()) {
|
||||
AEKey.writeKey(buf, entry.getKey());
|
||||
buf.writeVarLong(entry.getValue());
|
||||
}
|
||||
},
|
||||
buf -> {
|
||||
int containerId = buf.readInt();
|
||||
int size = buf.readVarInt();
|
||||
Map<AEKey, Long> snapshot = new LinkedHashMap<>(size);
|
||||
for (int i = 0; i < size; i++) {
|
||||
snapshot.put(AEKey.readKey(buf), buf.readVarLong());
|
||||
}
|
||||
return new ManualCraftingStatusS2CPacket(containerId, snapshot);
|
||||
}
|
||||
);
|
||||
|
||||
private final int containerId;
|
||||
private final Map<AEKey, Long> manualWaiting;
|
||||
|
||||
public ManualCraftingStatusS2CPacket(int containerId, Map<AEKey, Long> manualWaiting) {
|
||||
this.containerId = containerId;
|
||||
this.manualWaiting = manualWaiting;
|
||||
}
|
||||
|
||||
public static void handle(final ManualCraftingStatusS2CPacket msg, final IPayloadContext ctx) {
|
||||
ctx.enqueueWork(() -> handleClient(msg));
|
||||
}
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
private static void handleClient(ManualCraftingStatusS2CPacket msg) {
|
||||
var mc = Minecraft.getInstance();
|
||||
if (mc == null || mc.player == null || mc.player.containerMenu == null) {
|
||||
ClientManualCraftingStatusStore.clear();
|
||||
return;
|
||||
}
|
||||
if (mc.player.containerMenu.containerId != msg.containerId) {
|
||||
return;
|
||||
}
|
||||
ClientManualCraftingStatusStore.setStatus(msg.containerId, msg.manualWaiting);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type<? extends CustomPacketPayload> type() {
|
||||
return TYPE;
|
||||
}
|
||||
}
|
||||
|
|
@ -303,5 +303,8 @@
|
|||
"extendedae_plus.screen.global_controller_title": "Pattern Provider Status Controller",
|
||||
|
||||
"gui.extendedae_plus.add_bookmark": "Add Bookmark",
|
||||
"tooltip.extendedae_plus.add_missing_to_jei_bookmark": "Add missing items to JEI bookmarks"
|
||||
"tooltip.extendedae_plus.add_missing_to_jei_bookmark": "Add missing items to JEI bookmarks",
|
||||
"gui.extendedae_plus.force_start": "Force Start",
|
||||
"tooltip.extendedae_plus.force_start": "Submit this job immediately and keep missing entries as manual waiting",
|
||||
"tooltip.extendedae_plus.crafting.manual_waiting": "Manual waiting: %s"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -299,5 +299,8 @@
|
|||
"extendedae_plus.screen.global_controller_title": "样板供应器状态控制器",
|
||||
|
||||
"gui.extendedae_plus.add_bookmark": "添加书签",
|
||||
"tooltip.extendedae_plus.add_missing_to_jei_bookmark": "添加缺失物品到JEI书签"
|
||||
"tooltip.extendedae_plus.add_missing_to_jei_bookmark": "添加缺失物品到JEI书签",
|
||||
"gui.extendedae_plus.force_start": "强制开始",
|
||||
"tooltip.extendedae_plus.force_start": "忽略当前缺失项并直接提交任务",
|
||||
"tooltip.extendedae_plus.crafting.manual_waiting": "手动等待: %s"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,6 +46,8 @@
|
|||
"ae2.helpers.PatternProviderLogicUpgradesMixin",
|
||||
"ae2.helpers.patternprovider.PatternProviderLogicTickerMixin",
|
||||
"ae2.menu.AEBaseMenuUpgradesDedupMixin",
|
||||
"ae2.menu.CraftConfirmMenuForceStartMixin",
|
||||
"ae2.menu.CraftingCPUMenuManualStatusMixin",
|
||||
"ae2.menu.ContainerPatternEncodingTermMenuMixin",
|
||||
"ae2.menu.MEStorageMenuMixin",
|
||||
"ae2.menu.PatternEncodingTermMenuMixin",
|
||||
|
|
@ -53,6 +55,7 @@
|
|||
"ae2.menu.PatternProviderMenuDoublingMixin",
|
||||
"ae2.menu.PatternProviderMenuUpgradesMixin",
|
||||
"ae2.network.PatternAccessTerminalPacketMixin",
|
||||
"ae2.crafting.CraftingCpuLogicManualWaitingMixin",
|
||||
"ae2.parts.automation.IOBusPartChannelCardMixin",
|
||||
"ae2.parts.storagebus.StorageBusPartChannelCardMixin",
|
||||
"ae2WTlib.ContainerUWirelessExPatternTerminalMixin",
|
||||
|
|
@ -81,6 +84,7 @@
|
|||
"ae2.accessor.WidgetContainerAccessor",
|
||||
"ae2.client.gui.AEBaseScreenMixin",
|
||||
"ae2.client.gui.CraftConfirmScreenMixin",
|
||||
"ae2.client.gui.CraftingStatusTableRendererMixin",
|
||||
"ae2.client.gui.InterfaceScreenMixin",
|
||||
"ae2.client.gui.PatternEncodingTermScreenMixin",
|
||||
"ae2.client.gui.PatternEncodingTermUploadMixin",
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user