Skip to content

Commit

Permalink
Dynamically generate temporary crafting patterns for however many EMC…
Browse files Browse the repository at this point in the history
…-able items have been requested

(involves some hijacking of the auto-crafting system)
  • Loading branch information
62832 committed May 12, 2024
1 parent bdd2be0 commit f852f19
Show file tree
Hide file tree
Showing 7 changed files with 256 additions and 12 deletions.
33 changes: 25 additions & 8 deletions src/main/java/gripe/_90/appliede/me/service/KnowledgeService.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
Expand Down Expand Up @@ -42,6 +43,7 @@ public class KnowledgeService implements IGridService, IGridServiceProvider {
private final List<IManagedGridNode> moduleNodes = new ArrayList<>();
private final Map<UUID, Supplier<IKnowledgeProvider>> providers = new HashMap<>();
private final EMCStorage storage = new EMCStorage(this);
private final List<IPatternDetails> temporaryPatterns = new ArrayList<>();
private final TeamProjectEHandler.Proxy tpeHandler = new TeamProjectEHandler.Proxy();

private final IGrid grid;
Expand Down Expand Up @@ -129,18 +131,33 @@ public Set<AEItemKey> getKnownItems() {
.collect(Collectors.toSet());
}

public List<IPatternDetails> getPatterns() {
var patterns = new ArrayList<IPatternDetails>();
public List<IPatternDetails> getPatterns(IManagedGridNode node) {
if (!moduleNodes.isEmpty() && node.equals(moduleNodes.get(0))) {
var patterns = new ArrayList<IPatternDetails>();

for (var tier = storage.getHighestTier(); tier > 1; tier--) {
patterns.add(new TransmutationPattern(null, tier));
}
for (var tier = storage.getHighestTier(); tier > 1; tier--) {
patterns.add(new TransmutationPattern(null, tier));
}

for (var item : getKnownItems()) {
patterns.add(new TransmutationPattern(item, 1));
}

for (var item : getKnownItems()) {
patterns.add(new TransmutationPattern(item, 1));
patterns.addAll(temporaryPatterns);
return patterns;
}

return patterns;
return Collections.emptyList();
}

public void addTemporaryPattern(IPatternDetails pattern) {
temporaryPatterns.add(pattern);
updatePatterns();
}

public void removeTemporaryPattern(IPatternDetails pattern) {
temporaryPatterns.remove(pattern);
updatePatterns();
}

void updatePatterns() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package gripe._90.appliede.me.service;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Objects;

import org.jetbrains.annotations.Nullable;
Expand All @@ -19,13 +21,15 @@

public final class TransmutationPattern implements IPatternDetails {
private static final String NBT_ITEM = "item";
private static final String NBT_AMOUNT = "amount";
private static final String NBT_TIER = "tier";

private final AEItemKey definition;

@Nullable
private final AEItemKey item;

private final long amount;
private final int tier;

public TransmutationPattern(AEItemKey definition) {
Expand All @@ -34,21 +38,25 @@ public TransmutationPattern(AEItemKey definition) {

if (tag.contains(NBT_ITEM)) {
item = AEItemKey.fromTag(tag.getCompound(NBT_ITEM));
amount = tag.getLong(NBT_AMOUNT);
tier = 1;
} else {
item = null;
amount = 1;
tier = tag.getInt(NBT_TIER);
}
}

public TransmutationPattern(@Nullable AEItemKey item, int tier) {
public TransmutationPattern(@Nullable AEItemKey item, long amount, int tier) {
this.item = item;
this.amount = amount;
this.tier = item != null ? 1 : tier;

var tag = new CompoundTag();

if (item != null) {
tag.put(NBT_ITEM, item.toTag());
tag.putLong(NBT_AMOUNT, amount);
}

if (tier > 1) {
Expand All @@ -58,21 +66,46 @@ public TransmutationPattern(@Nullable AEItemKey item, int tier) {
definition = AEItemKey.of(AppliedE.TRANSMUTATION_PATTERN.get(), tag);
}

public TransmutationPattern(@Nullable AEItemKey item, int tier) {
this(item, 1, tier);
}

public TransmutationPattern(AEItemKey item, long amount) {
this(item, amount, 1);
}

@Override
public AEItemKey getDefinition() {
return definition;
}

@Override
public IInput[] getInputs() {
return new IInput[] {new Input(item != null ? IEMCProxy.INSTANCE.getValue(item.toStack()) : 1, tier)};
if (item == null) {
return new IInput[] {new Input(1, tier)};
}

var inputs = new ArrayList<IInput>();
var itemEmc = IEMCProxy.INSTANCE.getValue(item.toStack());
var totalEmc = BigInteger.valueOf(itemEmc).multiply(BigInteger.valueOf(amount));
var currentTier = 1;

while (totalEmc.divide(AppliedE.TIER_LIMIT).signum() == 1) {
inputs.add(new Input(totalEmc.remainder(AppliedE.TIER_LIMIT).longValue(), currentTier));
totalEmc = totalEmc.divide(AppliedE.TIER_LIMIT);
currentTier++;
}

inputs.add(new Input(totalEmc.longValue(), currentTier));

return inputs.toArray(new IInput[0]);
}

@Override
public GenericStack[] getOutputs() {
return new GenericStack[] {
item != null
? new GenericStack(item, 1)
? new GenericStack(item, amount)
: new GenericStack(EMCKey.tier(tier - 1), AppliedE.TIER_LIMIT.longValue())
};
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package gripe._90.appliede.mixin.crafting;

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 net.minecraft.world.entity.player.Player;

import appeng.api.networking.IGrid;
import appeng.api.networking.crafting.ICraftingPlan;
import appeng.api.stacks.AEItemKey;
import appeng.menu.me.crafting.CraftConfirmMenu;

import gripe._90.appliede.me.service.KnowledgeService;
import gripe._90.appliede.me.service.TransmutationPattern;

@Mixin(value = CraftConfirmMenu.class, remap = false)
public abstract class CraftConfirmMenuMixin {
@Shadow
private ICraftingPlan result;

@Unique
private boolean appliede$submitted = false;

@Shadow
protected abstract IGrid getGrid();

// spotless:off
@Inject(
method = "startJob",
at = @At(
value = "INVOKE",
target = "Lappeng/menu/me/crafting/CraftConfirmMenu;setAutoStart(Z)V"))
// spotless:on
private void setSubmitted(CallbackInfo ci) {
appliede$submitted = true;
}

@Inject(method = "removed", at = @At("TAIL"), remap = true)
private void clearTemporaryPatterns(Player player, CallbackInfo ci) {
if (getGrid() != null && result != null && !appliede$submitted) {
for (var pattern : result.patternTimes().keySet()) {
if (pattern instanceof TransmutationPattern && pattern.getOutputs()[0].what() instanceof AEItemKey) {
getGrid().getService(KnowledgeService.class).removeTemporaryPattern(pattern);
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package gripe._90.appliede.mixin.crafting;

import java.util.Iterator;
import java.util.Map;

import org.spongepowered.asm.mixin.Final;
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 org.spongepowered.asm.mixin.injection.callback.LocalCapture;

import net.minecraft.world.level.Level;

import appeng.api.crafting.IPatternDetails;
import appeng.api.networking.energy.IEnergyService;
import appeng.api.stacks.AEItemKey;
import appeng.crafting.execution.CraftingCpuLogic;
import appeng.crafting.execution.ExecutingCraftingJob;
import appeng.me.cluster.implementations.CraftingCPUCluster;
import appeng.me.service.CraftingService;

import gripe._90.appliede.me.service.KnowledgeService;
import gripe._90.appliede.me.service.TransmutationPattern;

@Mixin(value = CraftingCpuLogic.class, remap = false)
public abstract class CraftingCPULogicMixin {
@Shadow
@Final
CraftingCPUCluster cluster;

@Inject(
method = "executeCrafting",
at = @At(value = "INVOKE", target = "Ljava/util/Iterator;remove()V"),
locals = LocalCapture.CAPTURE_FAILEXCEPTION)
private void removeOnFinishStep(
int maxPatterns,
CraftingService craftingService,
IEnergyService energyService,
Level level,
CallbackInfoReturnable<Integer> cir,
ExecutingCraftingJob job,
int pushedPatterns,
Iterator<?> it,
Map.Entry<IPatternDetails, ?> task) {
appliede$removeTemporaryPattern(task.getKey());
}

@Inject(
method = "finishJob",
at = @At(value = "INVOKE", target = "Ljava/util/Map$Entry;getKey()Ljava/lang/Object;"),
locals = LocalCapture.CAPTURE_FAILEXCEPTION)
private void removeOnCancel(
boolean success, CallbackInfo ci, Iterator<?> iter, Map.Entry<IPatternDetails, ?> entry) {
appliede$removeTemporaryPattern(entry.getKey());
}

@Unique
private void appliede$removeTemporaryPattern(IPatternDetails pattern) {
if (pattern instanceof TransmutationPattern && pattern.getOutputs()[0].what() instanceof AEItemKey) {
var grid = cluster.getGrid();

if (grid != null) {
grid.getService(KnowledgeService.class).removeTemporaryPattern(pattern);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package gripe._90.appliede.mixin.crafting;

import java.util.ArrayList;
import java.util.Iterator;

import org.spongepowered.asm.mixin.Final;
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.LocalCapture;

import appeng.api.crafting.IPatternDetails;
import appeng.api.networking.IGridNode;
import appeng.api.networking.crafting.ICraftingService;
import appeng.api.stacks.AEItemKey;
import appeng.api.stacks.KeyCounter;
import appeng.crafting.CraftingCalculation;
import appeng.crafting.CraftingTreeNode;
import appeng.crafting.CraftingTreeProcess;
import appeng.crafting.inv.CraftingSimulationState;

import gripe._90.appliede.me.service.KnowledgeService;
import gripe._90.appliede.me.service.TransmutationPattern;

@Mixin(value = CraftingTreeNode.class, remap = false)
public abstract class CraftingTreeNodeMixin {
@Shadow
private ArrayList<CraftingTreeProcess> nodes;

@Shadow
@Final
private CraftingCalculation job;

@Unique
private long appliede$requestedAmount;

@Inject(method = "request", at = @At("HEAD"))
private void trackRequested(
CraftingSimulationState inv, long requestedAmount, KeyCounter containerItems, CallbackInfo ci) {
appliede$requestedAmount = requestedAmount;
}

// spotless:off
@Inject(
method = "buildChildPatterns",
at = @At(
value = "INVOKE",
target = "Ljava/util/ArrayList;add(Ljava/lang/Object;)Z"),
locals = LocalCapture.CAPTURE_FAILEXCEPTION,
cancellable = true)
// spotless:on
private void recalculatePattern(
CallbackInfo ci,
IGridNode gridNode,
ICraftingService craftingService,
Iterator<IPatternDetails> iterator,
IPatternDetails details) {
if (details instanceof TransmutationPattern && details.getOutputs()[0].what() instanceof AEItemKey item) {
ci.cancel();
var newPattern = new TransmutationPattern(item, appliede$requestedAmount);
gridNode.getGrid().getService(KnowledgeService.class).addTemporaryPattern(newPattern);
nodes.add(new CraftingTreeProcess(craftingService, job, newPattern, (CraftingTreeNode) (Object) this));
}
}
}
2 changes: 1 addition & 1 deletion src/main/java/gripe/_90/appliede/part/EMCModulePart.java
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ public void mountInventories(IStorageMounts mounts) {
@Override
public List<IPatternDetails> getAvailablePatterns() {
var grid = getMainNode().getGrid();
return grid != null ? grid.getService(KnowledgeService.class).getPatterns() : List.of();
return grid != null ? grid.getService(KnowledgeService.class).getPatterns(getMainNode()) : List.of();
}

@Override
Expand Down
3 changes: 3 additions & 0 deletions src/main/resources/appliede.mixins.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
"mixins": [
"ae2wtlib.AE2wtlibMixin",
"aecapfix.EMCInterfacePartMixin",
"crafting.CraftConfirmMenuMixin",
"crafting.CraftingCPULogicMixin",
"crafting.CraftingTreeNodeMixin",
"main.MEStorageMenuMixin",
"main.P2PTunnelAttunementAccessor",
"main.TransmutationOfflineAccessor",
Expand Down

0 comments on commit f852f19

Please sign in to comment.