Refactored crafting patterns (#4458)

* Deduplicate crafting patterns internals

This should save a bit memory for duplicate patterns as well as speed up
loading new patterns on reloading chunks.

* Encode recipe id in pattern
* Use the recipe id directly for looking it up
* Slightly refactored how patterns encode whether they are crafting patterns or not.
* Renamed PatternHelper.
* Added APIs to encode patterns. (#4463)
* Removed ICraftingPatternItem.
* Renamed isCrafting to isCraftable

Co-authored-by: shartte <shartte@users.noreply.github.com>
This commit is contained in:
yueh
2020-07-12 16:21:30 +02:00
committed by GitHub
parent 06735f5c39
commit 9bb23bcac8
19 changed files with 551 additions and 243 deletions
@@ -38,6 +38,7 @@ import appeng.container.slot.AppEngSlot;
import appeng.container.slot.MolecularAssemblerPatternSlot;
import appeng.container.slot.OutputSlot;
import appeng.container.slot.RestrictedInputSlot;
import appeng.core.Api;
import appeng.items.misc.EncodedPatternItem;
import appeng.tile.crafting.MolecularAssemblerTileEntity;
import appeng.util.Platform;
@@ -79,8 +80,7 @@ public class MolecularAssemblerContainer extends UpgradeableContainer implements
if (is.getItem() instanceof EncodedPatternItem) {
final World w = this.getTileEntity().getWorld();
final EncodedPatternItem iep = (EncodedPatternItem) is.getItem();
final ICraftingPatternDetails ph = iep.getPatternForItem(is, w);
final ICraftingPatternDetails ph = Api.instance().crafting().decodePattern(is, w);
if (ph.isCraftable()) {
return ph.isValidItemForSlot(slotIndex, i, w);
}
@@ -20,7 +20,6 @@ package appeng.container.implementations;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory;
@@ -32,11 +31,9 @@ import net.minecraft.inventory.container.CraftingResultSlot;
import net.minecraft.inventory.container.IContainerListener;
import net.minecraft.inventory.container.Slot;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.ICraftingRecipe;
import net.minecraft.item.crafting.IRecipe;
import net.minecraft.item.crafting.IRecipeType;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.nbt.INBT;
import net.minecraft.nbt.ListNBT;
import net.minecraft.network.PacketBuffer;
import net.minecraft.world.World;
import net.minecraftforge.items.IItemHandler;
@@ -44,6 +41,7 @@ import net.minecraftforge.items.wrapper.PlayerInvWrapper;
import appeng.api.config.Actionable;
import appeng.api.config.SecurityPermissions;
import appeng.api.crafting.ICraftingHelper;
import appeng.api.definitions.IDefinitions;
import appeng.api.storage.IMEMonitor;
import appeng.api.storage.ITerminalHost;
@@ -98,8 +96,9 @@ public class PatternTermContainer extends MEMonitorableContainer
private final PatternTermSlot craftSlot;
private final RestrictedInputSlot patternSlotIN;
private final RestrictedInputSlot patternSlotOUT;
private final ICraftingHelper craftingHelper = Api.INSTANCE.crafting();
private IRecipe<CraftingInventory> currentRecipe;
private ICraftingRecipe currentRecipe;
@GuiSync(97)
public boolean craftingMode = true;
@GuiSync(96)
@@ -206,17 +205,17 @@ public class PatternTermContainer extends MEMonitorableContainer
final ItemStack[] out = this.getOutputs();
// if there is no input, this would be silly.
if (in == null || out == null) {
if (in == null || out == null || isCraftingMode() && currentRecipe == null) {
return;
}
// first check the output slots, should either be null, or a pattern
if (!output.isEmpty() && !this.isPattern(output)) {
if (!output.isEmpty() && !craftingHelper.isEncodedPattern(output)) {
return;
} // if nothing is there we should snag a new pattern.
else if (output.isEmpty()) {
output = this.patternSlotIN.getStack();
if (output.isEmpty() || !this.isPattern(output)) {
if (output.isEmpty() || !isPattern(output)) {
return; // no blanks.
}
@@ -226,34 +225,17 @@ public class PatternTermContainer extends MEMonitorableContainer
this.patternSlotIN.putStack(ItemStack.EMPTY);
}
// add a new encoded pattern.
Optional<ItemStack> maybePattern = Api.instance().definitions().items().encodedPattern().maybeStack(1);
if (maybePattern.isPresent()) {
output = maybePattern.get();
this.patternSlotOUT.putStack(output);
}
// let the crafting helper create a new encoded pattern
output = null;
}
// encode the slot.
final CompoundNBT encodedValue = new CompoundNBT();
final ListNBT tagIn = new ListNBT();
final ListNBT tagOut = new ListNBT();
for (final ItemStack i : in) {
tagIn.add(this.createItemTag(i));
if (this.isCraftingMode()) {
output = craftingHelper.encodeCraftingPattern(output, this.currentRecipe, in, out[0], isSubstitute());
} else {
output = craftingHelper.encodeProcessingPattern(output, in, out);
}
this.patternSlotOUT.putStack(output);
for (final ItemStack i : out) {
tagOut.add(this.createItemTag(i));
}
encodedValue.put("in", tagIn);
encodedValue.put("out", tagOut);
encodedValue.putBoolean("crafting", this.isCraftingMode());
encodedValue.putBoolean("substitute", this.isSubstitute());
output.setTag(encodedValue);
}
private ItemStack[] getInputs() {
@@ -308,21 +290,7 @@ public class PatternTermContainer extends MEMonitorableContainer
}
final IDefinitions definitions = Api.instance().definitions();
boolean isPattern = definitions.items().encodedPattern().isSameAs(output);
isPattern |= definitions.materials().blankPattern().isSameAs(output);
return isPattern;
}
private INBT createItemTag(final ItemStack i) {
final CompoundNBT c = new CompoundNBT();
if (!i.isEmpty()) {
i.write(c);
}
return c;
return definitions.materials().blankPattern().isSameAs(output);
}
@Override
@@ -33,11 +33,11 @@ import net.minecraft.world.World;
import net.minecraftforge.common.ForgeHooks;
import net.minecraftforge.items.IItemHandler;
import appeng.api.crafting.ICraftingHelper;
import appeng.api.definitions.IDefinitions;
import appeng.api.definitions.IItems;
import appeng.api.definitions.IMaterials;
import appeng.api.features.INetworkEncodable;
import appeng.api.implementations.ICraftingPatternItem;
import appeng.api.implementations.items.IBiometricCard;
import appeng.api.implementations.items.ISpatialStorageCell;
import appeng.api.implementations.items.IStorageComponent;
@@ -88,10 +88,7 @@ public class RestrictedInputSlot extends AppEngSlot {
public boolean isValid(final ItemStack is, final World theWorld) {
if (this.which == PlacableItemType.VALID_ENCODED_PATTERN_W_OUTPUT) {
final ICraftingPatternDetails ap = is.getItem() instanceof ICraftingPatternItem
? ((ICraftingPatternItem) is.getItem()).getPatternForItem(is, theWorld)
: null;
return ap != null;
return Api.instance().crafting().decodePattern(is, theWorld) != null;
}
return true;
}
@@ -126,39 +123,24 @@ public class RestrictedInputSlot extends AppEngSlot {
final IDefinitions definitions = Api.instance().definitions();
final IMaterials materials = definitions.materials();
final IItems items = definitions.items();
final ICraftingHelper crafting = Api.instance().crafting();
switch (this.which) {
case ENCODED_CRAFTING_PATTERN:
if (i.getItem() instanceof ICraftingPatternItem) {
final ICraftingPatternItem b = (ICraftingPatternItem) i.getItem();
final ICraftingPatternDetails de = b.getPatternForItem(i, this.p.player.world);
if (de != null) {
return de.isCraftable();
}
final ICraftingPatternDetails de = crafting.decodePattern(i, this.p.player.world);
if (de != null) {
return de.isCraftable();
}
return false;
case VALID_ENCODED_PATTERN_W_OUTPUT:
case ENCODED_PATTERN_W_OUTPUT:
case ENCODED_PATTERN: {
if (i.getItem() instanceof ICraftingPatternItem) {
return true;
}
// ICraftingPatternDetails pattern = i.getItem() instanceof ICraftingPatternItem
// ?
// ((ICraftingPatternItem)
// i.getItem()).getPatternForItem( i ) : null;
return false;// pattern != null;
}
case ENCODED_PATTERN:
return crafting.isEncodedPattern(i);
case BLANK_PATTERN:
return materials.blankPattern().isSameAs(i);
case PATTERN:
if (i.getItem() instanceof ICraftingPatternItem) {
return true;
}
return materials.blankPattern().isSameAs(i);
return materials.blankPattern().isSameAs(i) || crafting.isEncodedPattern(i);
case INSCRIBER_PLATE:
if (materials.namePress().isSameAs(i)) {