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:
@@ -24,6 +24,7 @@
|
|||||||
package appeng.api;
|
package appeng.api;
|
||||||
|
|
||||||
import appeng.api.client.IClientHelper;
|
import appeng.api.client.IClientHelper;
|
||||||
|
import appeng.api.crafting.ICraftingHelper;
|
||||||
import appeng.api.definitions.IDefinitions;
|
import appeng.api.definitions.IDefinitions;
|
||||||
import appeng.api.features.IRegistryContainer;
|
import appeng.api.features.IRegistryContainer;
|
||||||
import appeng.api.networking.IGridHelper;
|
import appeng.api.networking.IGridHelper;
|
||||||
@@ -48,6 +49,11 @@ public interface IAppEngApi {
|
|||||||
*/
|
*/
|
||||||
IStorageHelper storage();
|
IStorageHelper storage();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return A helper for working with crafting related tasks.
|
||||||
|
*/
|
||||||
|
ICraftingHelper crafting();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return A helper to create {@link IGridNode} and other grid related objects.
|
* @return A helper to create {@link IGridNode} and other grid related objects.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -0,0 +1,108 @@
|
|||||||
|
/*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020 TeamAppliedEnergistics
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package appeng.api.crafting;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.item.crafting.ICraftingRecipe;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
|
import appeng.api.networking.crafting.ICraftingPatternDetails;
|
||||||
|
import appeng.api.storage.data.IAEItemStack;
|
||||||
|
|
||||||
|
public interface ICraftingHelper {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks that the given item stack is an encoded pattern.
|
||||||
|
*/
|
||||||
|
boolean isEncodedPattern(@Nullable IAEItemStack item);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks that the given item stack is an encoded pattern.
|
||||||
|
*/
|
||||||
|
boolean isEncodedPattern(ItemStack item);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encodes a processing pattern which represents the ability to convert the
|
||||||
|
* given inputs into the given outputs using some process external to the ME
|
||||||
|
* system.
|
||||||
|
*
|
||||||
|
* @param stack If null, a new item will be created to hold the encoded pattern.
|
||||||
|
* Otherwise the given item must already contains an encoded
|
||||||
|
* pattern that will be overwritten.
|
||||||
|
* @return A new encoded pattern, or the given stack with the pattern encoded in
|
||||||
|
* it.
|
||||||
|
*/
|
||||||
|
ItemStack encodeProcessingPattern(@Nullable ItemStack stack, ItemStack[] in, ItemStack[] out);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encodes a crafting pattern which represents a Vanilla crafting recipe.
|
||||||
|
*
|
||||||
|
* @param stack If null, a new item will be created to hold the
|
||||||
|
* encoded pattern. Otherwise the given item must
|
||||||
|
* already contains an encoded pattern that will be
|
||||||
|
* overwritten.
|
||||||
|
* @param recipe The Vanilla crafting recipe to be encoded.
|
||||||
|
* @param in The items in the crafting grid, which are used to
|
||||||
|
* determine what items are supplied from the ME system
|
||||||
|
* to craft using this pattern.
|
||||||
|
* @param out What is to be expected as the result of this crafting
|
||||||
|
* operation by the ME system.
|
||||||
|
* @param allowSubstitutes Controls whether the ME system will allow the use of
|
||||||
|
* equivalent items to craft this recipe.
|
||||||
|
*/
|
||||||
|
ItemStack encodeCraftingPattern(@Nullable ItemStack stack, ICraftingRecipe recipe, ItemStack[] in, ItemStack out,
|
||||||
|
boolean allowSubstitutes);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Same as {@link #decodePattern(ItemStack, World, boolean)} with no auto
|
||||||
|
* recovery of changed recipe ids.
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
default ICraftingPatternDetails decodePattern(@Nonnull ItemStack itemStack, @Nonnull World world) {
|
||||||
|
return decodePattern(itemStack, world, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodes an encoded crafting pattern and returns the pattern details.
|
||||||
|
* <p>
|
||||||
|
* The item backing the {@link ItemStack} needs to be an item returned by the
|
||||||
|
* encode methods of this class.
|
||||||
|
*
|
||||||
|
* @param itemStack pattern
|
||||||
|
* @param world world used to access the
|
||||||
|
* {@link net.minecraft.item.crafting.RecipeManager}.
|
||||||
|
* @param autoRecovery If true, the method will try to recover from changed
|
||||||
|
* recipe ids by searching the entire recipe manager for a
|
||||||
|
* recipe matching the inputs. If this is successful, the
|
||||||
|
* given item stack will be changed to reflect the new
|
||||||
|
* recipe id.
|
||||||
|
* @return The pattern details if the pattern could be decoded. Otherwise null.
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
ICraftingPatternDetails decodePattern(@Nonnull ItemStack itemStack, @Nonnull World world, boolean autoRecovery);
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
/*
|
|
||||||
* The MIT License (MIT)
|
|
||||||
*
|
|
||||||
* Copyright (c) 2013 AlgorithmX2
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
||||||
* this software and associated documentation files (the "Software"), to deal in
|
|
||||||
* the Software without restriction, including without limitation the rights to
|
|
||||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
|
||||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
|
||||||
* subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
|
||||||
* copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
|
||||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
||||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
||||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package appeng.api.implementations;
|
|
||||||
|
|
||||||
import net.minecraft.item.Item;
|
|
||||||
import net.minecraft.item.ItemStack;
|
|
||||||
import net.minecraft.world.World;
|
|
||||||
|
|
||||||
import appeng.api.networking.crafting.ICraftingPatternDetails;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Implemented on {@link Item}
|
|
||||||
*/
|
|
||||||
public interface ICraftingPatternItem {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Access Details about a pattern
|
|
||||||
*
|
|
||||||
* @param is pattern
|
|
||||||
* @param w crafting world
|
|
||||||
*
|
|
||||||
* @return details of pattern
|
|
||||||
*/
|
|
||||||
ICraftingPatternDetails getPatternForItem(ItemStack is, World w);
|
|
||||||
}
|
|
||||||
@@ -27,18 +27,19 @@ import net.minecraft.inventory.CraftingInventory;
|
|||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
import appeng.api.implementations.ICraftingPatternItem;
|
|
||||||
import appeng.api.storage.data.IAEItemStack;
|
import appeng.api.storage.data.IAEItemStack;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* do not implement provided by {@link ICraftingPatternItem}
|
* Describes a crafting or processing pattern decoded by
|
||||||
*
|
* {@link appeng.api.crafting.ICraftingHelper}.
|
||||||
* caching this INSTANCE will increase performance of validation and checks.
|
* <p>
|
||||||
|
* Do not cache instances of this class unless you handle recipe reloads on the
|
||||||
|
* server and client correctly.
|
||||||
*/
|
*/
|
||||||
public interface ICraftingPatternDetails {
|
public interface ICraftingPatternDetails {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return source item.
|
* @return encodes this crafting pattern into a new item stack.
|
||||||
*/
|
*/
|
||||||
ItemStack getPattern();
|
ItemStack getPattern();
|
||||||
|
|
||||||
@@ -52,7 +53,9 @@ public interface ICraftingPatternDetails {
|
|||||||
boolean isValidItemForSlot(int slotIndex, ItemStack itemStack, World world);
|
boolean isValidItemForSlot(int slotIndex, ItemStack itemStack, World world);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return if this pattern is a crafting pattern ( work bench )
|
* @return if this pattern is for a Vanilla
|
||||||
|
* {@link net.minecraft.item.crafting.IRecipeType#CRAFTING crafting
|
||||||
|
* recipe}.
|
||||||
*/
|
*/
|
||||||
boolean isCraftable();
|
boolean isCraftable();
|
||||||
|
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
|
|
||||||
package appeng.api.networking.crafting;
|
package appeng.api.networking.crafting;
|
||||||
|
|
||||||
|
import appeng.api.crafting.ICraftingHelper;
|
||||||
import appeng.api.storage.data.IAEItemStack;
|
import appeng.api.storage.data.IAEItemStack;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -33,6 +34,9 @@ public interface ICraftingProviderHelper {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Add new Pattern to AE's crafting cache.
|
* Add new Pattern to AE's crafting cache.
|
||||||
|
*
|
||||||
|
* This will only accept instances created by
|
||||||
|
* {@link ICraftingHelper#decodePattern(net.minecraft.item.ItemStack, net.minecraft.world.World)}
|
||||||
*/
|
*/
|
||||||
void addCraftingOption(ICraftingMedium medium, ICraftingPatternDetails api);
|
void addCraftingOption(ICraftingMedium medium, ICraftingPatternDetails api);
|
||||||
|
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ import appeng.container.slot.AppEngSlot;
|
|||||||
import appeng.container.slot.MolecularAssemblerPatternSlot;
|
import appeng.container.slot.MolecularAssemblerPatternSlot;
|
||||||
import appeng.container.slot.OutputSlot;
|
import appeng.container.slot.OutputSlot;
|
||||||
import appeng.container.slot.RestrictedInputSlot;
|
import appeng.container.slot.RestrictedInputSlot;
|
||||||
|
import appeng.core.Api;
|
||||||
import appeng.items.misc.EncodedPatternItem;
|
import appeng.items.misc.EncodedPatternItem;
|
||||||
import appeng.tile.crafting.MolecularAssemblerTileEntity;
|
import appeng.tile.crafting.MolecularAssemblerTileEntity;
|
||||||
import appeng.util.Platform;
|
import appeng.util.Platform;
|
||||||
@@ -79,8 +80,7 @@ public class MolecularAssemblerContainer extends UpgradeableContainer implements
|
|||||||
|
|
||||||
if (is.getItem() instanceof EncodedPatternItem) {
|
if (is.getItem() instanceof EncodedPatternItem) {
|
||||||
final World w = this.getTileEntity().getWorld();
|
final World w = this.getTileEntity().getWorld();
|
||||||
final EncodedPatternItem iep = (EncodedPatternItem) is.getItem();
|
final ICraftingPatternDetails ph = Api.instance().crafting().decodePattern(is, w);
|
||||||
final ICraftingPatternDetails ph = iep.getPatternForItem(is, w);
|
|
||||||
if (ph.isCraftable()) {
|
if (ph.isCraftable()) {
|
||||||
return ph.isValidItemForSlot(slotIndex, i, w);
|
return ph.isValidItemForSlot(slotIndex, i, w);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ package appeng.container.implementations;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
import net.minecraft.entity.player.PlayerInventory;
|
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.IContainerListener;
|
||||||
import net.minecraft.inventory.container.Slot;
|
import net.minecraft.inventory.container.Slot;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.item.crafting.ICraftingRecipe;
|
||||||
import net.minecraft.item.crafting.IRecipe;
|
import net.minecraft.item.crafting.IRecipe;
|
||||||
import net.minecraft.item.crafting.IRecipeType;
|
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.network.PacketBuffer;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
import net.minecraftforge.items.IItemHandler;
|
import net.minecraftforge.items.IItemHandler;
|
||||||
@@ -44,6 +41,7 @@ import net.minecraftforge.items.wrapper.PlayerInvWrapper;
|
|||||||
|
|
||||||
import appeng.api.config.Actionable;
|
import appeng.api.config.Actionable;
|
||||||
import appeng.api.config.SecurityPermissions;
|
import appeng.api.config.SecurityPermissions;
|
||||||
|
import appeng.api.crafting.ICraftingHelper;
|
||||||
import appeng.api.definitions.IDefinitions;
|
import appeng.api.definitions.IDefinitions;
|
||||||
import appeng.api.storage.IMEMonitor;
|
import appeng.api.storage.IMEMonitor;
|
||||||
import appeng.api.storage.ITerminalHost;
|
import appeng.api.storage.ITerminalHost;
|
||||||
@@ -98,8 +96,9 @@ public class PatternTermContainer extends MEMonitorableContainer
|
|||||||
private final PatternTermSlot craftSlot;
|
private final PatternTermSlot craftSlot;
|
||||||
private final RestrictedInputSlot patternSlotIN;
|
private final RestrictedInputSlot patternSlotIN;
|
||||||
private final RestrictedInputSlot patternSlotOUT;
|
private final RestrictedInputSlot patternSlotOUT;
|
||||||
|
private final ICraftingHelper craftingHelper = Api.INSTANCE.crafting();
|
||||||
|
|
||||||
private IRecipe<CraftingInventory> currentRecipe;
|
private ICraftingRecipe currentRecipe;
|
||||||
@GuiSync(97)
|
@GuiSync(97)
|
||||||
public boolean craftingMode = true;
|
public boolean craftingMode = true;
|
||||||
@GuiSync(96)
|
@GuiSync(96)
|
||||||
@@ -206,17 +205,17 @@ public class PatternTermContainer extends MEMonitorableContainer
|
|||||||
final ItemStack[] out = this.getOutputs();
|
final ItemStack[] out = this.getOutputs();
|
||||||
|
|
||||||
// if there is no input, this would be silly.
|
// if there is no input, this would be silly.
|
||||||
if (in == null || out == null) {
|
if (in == null || out == null || isCraftingMode() && currentRecipe == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// first check the output slots, should either be null, or a pattern
|
// 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;
|
return;
|
||||||
} // if nothing is there we should snag a new pattern.
|
} // if nothing is there we should snag a new pattern.
|
||||||
else if (output.isEmpty()) {
|
else if (output.isEmpty()) {
|
||||||
output = this.patternSlotIN.getStack();
|
output = this.patternSlotIN.getStack();
|
||||||
if (output.isEmpty() || !this.isPattern(output)) {
|
if (output.isEmpty() || !isPattern(output)) {
|
||||||
return; // no blanks.
|
return; // no blanks.
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -226,34 +225,17 @@ public class PatternTermContainer extends MEMonitorableContainer
|
|||||||
this.patternSlotIN.putStack(ItemStack.EMPTY);
|
this.patternSlotIN.putStack(ItemStack.EMPTY);
|
||||||
}
|
}
|
||||||
|
|
||||||
// add a new encoded pattern.
|
// let the crafting helper create a new encoded pattern
|
||||||
Optional<ItemStack> maybePattern = Api.instance().definitions().items().encodedPattern().maybeStack(1);
|
output = null;
|
||||||
if (maybePattern.isPresent()) {
|
|
||||||
output = maybePattern.get();
|
|
||||||
this.patternSlotOUT.putStack(output);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// encode the slot.
|
if (this.isCraftingMode()) {
|
||||||
final CompoundNBT encodedValue = new CompoundNBT();
|
output = craftingHelper.encodeCraftingPattern(output, this.currentRecipe, in, out[0], isSubstitute());
|
||||||
|
} else {
|
||||||
final ListNBT tagIn = new ListNBT();
|
output = craftingHelper.encodeProcessingPattern(output, in, out);
|
||||||
final ListNBT tagOut = new ListNBT();
|
|
||||||
|
|
||||||
for (final ItemStack i : in) {
|
|
||||||
tagIn.add(this.createItemTag(i));
|
|
||||||
}
|
}
|
||||||
|
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() {
|
private ItemStack[] getInputs() {
|
||||||
@@ -308,21 +290,7 @@ public class PatternTermContainer extends MEMonitorableContainer
|
|||||||
}
|
}
|
||||||
|
|
||||||
final IDefinitions definitions = Api.instance().definitions();
|
final IDefinitions definitions = Api.instance().definitions();
|
||||||
|
return definitions.materials().blankPattern().isSameAs(output);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -33,11 +33,11 @@ import net.minecraft.world.World;
|
|||||||
import net.minecraftforge.common.ForgeHooks;
|
import net.minecraftforge.common.ForgeHooks;
|
||||||
import net.minecraftforge.items.IItemHandler;
|
import net.minecraftforge.items.IItemHandler;
|
||||||
|
|
||||||
|
import appeng.api.crafting.ICraftingHelper;
|
||||||
import appeng.api.definitions.IDefinitions;
|
import appeng.api.definitions.IDefinitions;
|
||||||
import appeng.api.definitions.IItems;
|
import appeng.api.definitions.IItems;
|
||||||
import appeng.api.definitions.IMaterials;
|
import appeng.api.definitions.IMaterials;
|
||||||
import appeng.api.features.INetworkEncodable;
|
import appeng.api.features.INetworkEncodable;
|
||||||
import appeng.api.implementations.ICraftingPatternItem;
|
|
||||||
import appeng.api.implementations.items.IBiometricCard;
|
import appeng.api.implementations.items.IBiometricCard;
|
||||||
import appeng.api.implementations.items.ISpatialStorageCell;
|
import appeng.api.implementations.items.ISpatialStorageCell;
|
||||||
import appeng.api.implementations.items.IStorageComponent;
|
import appeng.api.implementations.items.IStorageComponent;
|
||||||
@@ -88,10 +88,7 @@ public class RestrictedInputSlot extends AppEngSlot {
|
|||||||
|
|
||||||
public boolean isValid(final ItemStack is, final World theWorld) {
|
public boolean isValid(final ItemStack is, final World theWorld) {
|
||||||
if (this.which == PlacableItemType.VALID_ENCODED_PATTERN_W_OUTPUT) {
|
if (this.which == PlacableItemType.VALID_ENCODED_PATTERN_W_OUTPUT) {
|
||||||
final ICraftingPatternDetails ap = is.getItem() instanceof ICraftingPatternItem
|
return Api.instance().crafting().decodePattern(is, theWorld) != null;
|
||||||
? ((ICraftingPatternItem) is.getItem()).getPatternForItem(is, theWorld)
|
|
||||||
: null;
|
|
||||||
return ap != null;
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -126,39 +123,24 @@ public class RestrictedInputSlot extends AppEngSlot {
|
|||||||
final IDefinitions definitions = Api.instance().definitions();
|
final IDefinitions definitions = Api.instance().definitions();
|
||||||
final IMaterials materials = definitions.materials();
|
final IMaterials materials = definitions.materials();
|
||||||
final IItems items = definitions.items();
|
final IItems items = definitions.items();
|
||||||
|
final ICraftingHelper crafting = Api.instance().crafting();
|
||||||
|
|
||||||
switch (this.which) {
|
switch (this.which) {
|
||||||
case ENCODED_CRAFTING_PATTERN:
|
case ENCODED_CRAFTING_PATTERN:
|
||||||
if (i.getItem() instanceof ICraftingPatternItem) {
|
final ICraftingPatternDetails de = crafting.decodePattern(i, this.p.player.world);
|
||||||
final ICraftingPatternItem b = (ICraftingPatternItem) i.getItem();
|
if (de != null) {
|
||||||
final ICraftingPatternDetails de = b.getPatternForItem(i, this.p.player.world);
|
return de.isCraftable();
|
||||||
if (de != null) {
|
|
||||||
return de.isCraftable();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
case VALID_ENCODED_PATTERN_W_OUTPUT:
|
case VALID_ENCODED_PATTERN_W_OUTPUT:
|
||||||
case ENCODED_PATTERN_W_OUTPUT:
|
case ENCODED_PATTERN_W_OUTPUT:
|
||||||
case ENCODED_PATTERN: {
|
case ENCODED_PATTERN:
|
||||||
if (i.getItem() instanceof ICraftingPatternItem) {
|
return crafting.isEncodedPattern(i);
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// ICraftingPatternDetails pattern = i.getItem() instanceof ICraftingPatternItem
|
|
||||||
// ?
|
|
||||||
// ((ICraftingPatternItem)
|
|
||||||
// i.getItem()).getPatternForItem( i ) : null;
|
|
||||||
return false;// pattern != null;
|
|
||||||
}
|
|
||||||
case BLANK_PATTERN:
|
case BLANK_PATTERN:
|
||||||
return materials.blankPattern().isSameAs(i);
|
return materials.blankPattern().isSameAs(i);
|
||||||
|
|
||||||
case PATTERN:
|
case PATTERN:
|
||||||
|
return materials.blankPattern().isSameAs(i) || crafting.isEncodedPattern(i);
|
||||||
if (i.getItem() instanceof ICraftingPatternItem) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return materials.blankPattern().isSameAs(i);
|
|
||||||
|
|
||||||
case INSCRIBER_PLATE:
|
case INSCRIBER_PLATE:
|
||||||
if (materials.namePress().isSameAs(i)) {
|
if (materials.namePress().isSameAs(i)) {
|
||||||
|
|||||||
@@ -21,10 +21,12 @@ package appeng.core;
|
|||||||
import appeng.api.AEAddon;
|
import appeng.api.AEAddon;
|
||||||
import appeng.api.IAppEngApi;
|
import appeng.api.IAppEngApi;
|
||||||
import appeng.api.client.IClientHelper;
|
import appeng.api.client.IClientHelper;
|
||||||
|
import appeng.api.crafting.ICraftingHelper;
|
||||||
import appeng.api.features.IRegistryContainer;
|
import appeng.api.features.IRegistryContainer;
|
||||||
import appeng.api.networking.IGridHelper;
|
import appeng.api.networking.IGridHelper;
|
||||||
import appeng.api.storage.IStorageHelper;
|
import appeng.api.storage.IStorageHelper;
|
||||||
import appeng.core.api.ApiClientHelper;
|
import appeng.core.api.ApiClientHelper;
|
||||||
|
import appeng.core.api.ApiCrafting;
|
||||||
import appeng.core.api.ApiGrid;
|
import appeng.core.api.ApiGrid;
|
||||||
import appeng.core.api.ApiPart;
|
import appeng.core.api.ApiPart;
|
||||||
import appeng.core.api.ApiStorage;
|
import appeng.core.api.ApiStorage;
|
||||||
@@ -59,6 +61,7 @@ public final class Api implements IAppEngApi {
|
|||||||
private final IStorageHelper storageHelper;
|
private final IStorageHelper storageHelper;
|
||||||
private final IGridHelper networkHelper;
|
private final IGridHelper networkHelper;
|
||||||
private final ApiDefinitions definitions;
|
private final ApiDefinitions definitions;
|
||||||
|
private final ICraftingHelper craftingHelper;
|
||||||
private final IClientHelper client;
|
private final IClientHelper client;
|
||||||
|
|
||||||
private Api() {
|
private Api() {
|
||||||
@@ -67,6 +70,7 @@ public final class Api implements IAppEngApi {
|
|||||||
this.registryContainer = new RegistryContainer();
|
this.registryContainer = new RegistryContainer();
|
||||||
this.partHelper = new ApiPart();
|
this.partHelper = new ApiPart();
|
||||||
this.definitions = new ApiDefinitions((PartModels) this.registryContainer.partModels());
|
this.definitions = new ApiDefinitions((PartModels) this.registryContainer.partModels());
|
||||||
|
this.craftingHelper = new ApiCrafting(this.definitions);
|
||||||
this.client = new ApiClientHelper(this.definitions);
|
this.client = new ApiClientHelper(this.definitions);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,6 +88,11 @@ public final class Api implements IAppEngApi {
|
|||||||
return this.storageHelper;
|
return this.storageHelper;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ICraftingHelper crafting() {
|
||||||
|
return this.craftingHelper;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IGridHelper grid() {
|
public IGridHelper grid() {
|
||||||
return this.networkHelper;
|
return this.networkHelper;
|
||||||
|
|||||||
@@ -0,0 +1,167 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of Applied Energistics 2.
|
||||||
|
* Copyright (c) 2020, TeamAppliedEnergistics, All rights reserved.
|
||||||
|
*
|
||||||
|
* Applied Energistics 2 is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Applied Energistics 2 is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package appeng.core.api;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.google.common.base.Preconditions;
|
||||||
|
|
||||||
|
import net.minecraft.inventory.CraftingInventory;
|
||||||
|
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.item.crafting.RecipeManager;
|
||||||
|
import net.minecraft.util.ResourceLocation;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
|
import appeng.api.crafting.ICraftingHelper;
|
||||||
|
import appeng.api.definitions.IItemDefinition;
|
||||||
|
import appeng.api.networking.crafting.ICraftingPatternDetails;
|
||||||
|
import appeng.api.storage.channels.IItemStorageChannel;
|
||||||
|
import appeng.api.storage.data.IAEItemStack;
|
||||||
|
import appeng.container.ContainerNull;
|
||||||
|
import appeng.core.AELog;
|
||||||
|
import appeng.core.Api;
|
||||||
|
import appeng.core.ApiDefinitions;
|
||||||
|
import appeng.helpers.CraftingPatternDetails;
|
||||||
|
import appeng.items.misc.EncodedPatternItem;
|
||||||
|
|
||||||
|
public class ApiCrafting implements ICraftingHelper {
|
||||||
|
|
||||||
|
private final IItemDefinition encodedPattern;
|
||||||
|
|
||||||
|
public ApiCrafting(ApiDefinitions definitions) {
|
||||||
|
this.encodedPattern = definitions.items().encodedPattern();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEncodedPattern(@Nullable IAEItemStack item) {
|
||||||
|
return item != null && item.getItem() instanceof EncodedPatternItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEncodedPattern(ItemStack item) {
|
||||||
|
return !item.isEmpty() && item.getItem() instanceof EncodedPatternItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ItemStack encodeCraftingPattern(@Nullable ItemStack stack, ICraftingRecipe recipe, ItemStack[] in,
|
||||||
|
ItemStack out, boolean allowSubstitutes) {
|
||||||
|
if (stack == null) {
|
||||||
|
stack = encodedPattern.stack(1);
|
||||||
|
} else {
|
||||||
|
Preconditions.checkArgument(isEncodedPattern(stack));
|
||||||
|
}
|
||||||
|
|
||||||
|
EncodedPatternItem.encodeCraftingPattern(stack, in, new ItemStack[] { out }, recipe.getId(), allowSubstitutes);
|
||||||
|
return stack;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ItemStack encodeProcessingPattern(@Nullable ItemStack stack, ItemStack[] in, ItemStack[] out) {
|
||||||
|
if (stack == null) {
|
||||||
|
stack = encodedPattern.stack(1);
|
||||||
|
} else {
|
||||||
|
Preconditions.checkArgument(isEncodedPattern(stack));
|
||||||
|
}
|
||||||
|
|
||||||
|
EncodedPatternItem.encodeProcessingPattern(stack, in, out);
|
||||||
|
return stack;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ICraftingPatternDetails decodePattern(final ItemStack is, final World world, boolean autoRecovery) {
|
||||||
|
if (is == null || world == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
EncodedPatternItem patternItem = getPatternItem(is);
|
||||||
|
if (patternItem == null || !patternItem.isEncodedPattern(is)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The recipe ids encoded in a pattern can go stale. This code attempts to find
|
||||||
|
// the new id
|
||||||
|
// based on the stored inputs/outputs if that happens.
|
||||||
|
ResourceLocation recipeId = patternItem.getCraftingRecipeId(is);
|
||||||
|
if (recipeId != null) {
|
||||||
|
IRecipe<?> recipe = world.getRecipeManager().getRecipes(IRecipeType.CRAFTING).get(recipeId);
|
||||||
|
if (!(recipe instanceof ICraftingRecipe)) {
|
||||||
|
if (!autoRecovery || !attemptRecovery(patternItem, is, world)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We use the shared itemstack for an identity lookup.
|
||||||
|
IAEItemStack ais = Api.instance().storage().getStorageChannel(IItemStorageChannel.class).createStack(is);
|
||||||
|
|
||||||
|
return new CraftingPatternDetails(ais, world);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean attemptRecovery(EncodedPatternItem patternItem, ItemStack itemStack, World world) {
|
||||||
|
|
||||||
|
RecipeManager recipeManager = world.getRecipeManager();
|
||||||
|
|
||||||
|
List<IAEItemStack> ingredients = patternItem.getIngredients(itemStack);
|
||||||
|
List<IAEItemStack> products = patternItem.getProducts(itemStack);
|
||||||
|
if (ingredients.size() < 9 || products.size() < 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ResourceLocation currentRecipeId = patternItem.getCraftingRecipeId(itemStack);
|
||||||
|
|
||||||
|
// Fill a crafting inventory with the ingredients to find a suitable recipe
|
||||||
|
CraftingInventory testInventory = new CraftingInventory(new ContainerNull(), 3, 3);
|
||||||
|
for (int x = 0; x < 9; x++) {
|
||||||
|
final IAEItemStack ais = ingredients.get(x);
|
||||||
|
final ItemStack gs = ais != null ? ais.createItemStack() : ItemStack.EMPTY;
|
||||||
|
testInventory.setInventorySlotContents(x, gs);
|
||||||
|
}
|
||||||
|
|
||||||
|
ICraftingRecipe potentialRecipe = recipeManager.getRecipe(IRecipeType.CRAFTING, testInventory, world)
|
||||||
|
.orElse(null);
|
||||||
|
|
||||||
|
if (potentialRecipe != null) {
|
||||||
|
// Check that it matches the expected output
|
||||||
|
if (products.get(0).isSameType(potentialRecipe.getCraftingResult(testInventory))) {
|
||||||
|
// Yay we found a match, reencode the pattern
|
||||||
|
AELog.debug("Re-Encoding pattern from %s -> %s", currentRecipeId, potentialRecipe.getId());
|
||||||
|
ItemStack[] in = ingredients.stream().map(ais -> ais != null ? ais.createItemStack() : ItemStack.EMPTY)
|
||||||
|
.toArray(ItemStack[]::new);
|
||||||
|
ItemStack out = products.get(0).createItemStack();
|
||||||
|
encodeCraftingPattern(itemStack, potentialRecipe, in, out, patternItem.allowsSubstitution(itemStack));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AELog.debug("Failed to recover encoded crafting pattern for recipe %s", currentRecipeId);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static EncodedPatternItem getPatternItem(ItemStack itemStack) {
|
||||||
|
if (itemStack.getItem() instanceof EncodedPatternItem) {
|
||||||
|
return (EncodedPatternItem) itemStack.getItem();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -101,7 +101,7 @@ public class CraftRequestPacket extends BasePacket {
|
|||||||
if (futureJob != null) {
|
if (futureJob != null) {
|
||||||
futureJob.cancel(true);
|
futureJob.cancel(true);
|
||||||
}
|
}
|
||||||
AELog.debug(e);
|
AELog.info(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+44
-49
@@ -25,13 +25,15 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import com.google.common.base.Preconditions;
|
||||||
|
|
||||||
import net.minecraft.inventory.CraftingInventory;
|
import net.minecraft.inventory.CraftingInventory;
|
||||||
import net.minecraft.item.Item;
|
import net.minecraft.item.Item;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.item.crafting.ICraftingRecipe;
|
import net.minecraft.item.crafting.ICraftingRecipe;
|
||||||
|
import net.minecraft.item.crafting.IRecipe;
|
||||||
import net.minecraft.item.crafting.IRecipeType;
|
import net.minecraft.item.crafting.IRecipeType;
|
||||||
import net.minecraft.nbt.CompoundNBT;
|
import net.minecraft.util.ResourceLocation;
|
||||||
import net.minecraft.nbt.ListNBT;
|
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
import appeng.api.networking.crafting.ICraftingPatternDetails;
|
import appeng.api.networking.crafting.ICraftingPatternDetails;
|
||||||
@@ -39,12 +41,11 @@ import appeng.api.storage.channels.IItemStorageChannel;
|
|||||||
import appeng.api.storage.data.IAEItemStack;
|
import appeng.api.storage.data.IAEItemStack;
|
||||||
import appeng.container.ContainerNull;
|
import appeng.container.ContainerNull;
|
||||||
import appeng.core.Api;
|
import appeng.core.Api;
|
||||||
|
import appeng.items.misc.EncodedPatternItem;
|
||||||
import appeng.util.Platform;
|
import appeng.util.Platform;
|
||||||
import appeng.util.item.AEItemStack;
|
|
||||||
|
|
||||||
public class PatternHelper implements ICraftingPatternDetails, Comparable<PatternHelper> {
|
public class CraftingPatternDetails implements ICraftingPatternDetails, Comparable<CraftingPatternDetails> {
|
||||||
|
|
||||||
private final ItemStack patternItem;
|
|
||||||
private final CraftingInventory crafting = new CraftingInventory(new ContainerNull(), 3, 3);
|
private final CraftingInventory crafting = new CraftingInventory(new ContainerNull(), 3, 3);
|
||||||
private final CraftingInventory testFrame = new CraftingInventory(new ContainerNull(), 3, 3);
|
private final CraftingInventory testFrame = new CraftingInventory(new ContainerNull(), 3, 3);
|
||||||
private final ItemStack correctOutput;
|
private final ItemStack correctOutput;
|
||||||
@@ -53,79 +54,73 @@ public class PatternHelper implements ICraftingPatternDetails, Comparable<Patter
|
|||||||
private final IAEItemStack[] condensedOutputs;
|
private final IAEItemStack[] condensedOutputs;
|
||||||
private final IAEItemStack[] inputs;
|
private final IAEItemStack[] inputs;
|
||||||
private final IAEItemStack[] outputs;
|
private final IAEItemStack[] outputs;
|
||||||
private final boolean isCrafting;
|
private final boolean isCraftable;
|
||||||
private final boolean canSubstitute;
|
private final boolean canSubstitute;
|
||||||
private final Set<TestLookup> failCache = new HashSet<>();
|
private final Set<TestLookup> failCache = new HashSet<>();
|
||||||
private final Set<TestLookup> passCache = new HashSet<>();
|
private final Set<TestLookup> passCache = new HashSet<>();
|
||||||
private final IAEItemStack pattern;
|
private final IAEItemStack pattern;
|
||||||
private int priority = 0;
|
private int priority = 0;
|
||||||
|
|
||||||
public PatternHelper(final ItemStack is, final World w) {
|
public CraftingPatternDetails(final IAEItemStack is, final World w) {
|
||||||
final CompoundNBT encodedValue = is.getTag();
|
Preconditions.checkArgument(is.getItem() instanceof EncodedPatternItem,
|
||||||
|
"itemStack is not a ICraftingPatternItem");
|
||||||
|
|
||||||
if (encodedValue == null) {
|
final EncodedPatternItem templateItem = (EncodedPatternItem) is.getItem();
|
||||||
throw new IllegalArgumentException("No pattern here!");
|
final ItemStack itemStack = is.createItemStack();
|
||||||
}
|
|
||||||
|
|
||||||
final ListNBT inTag = encodedValue.getList("in", 10);
|
final List<IAEItemStack> ingredients = templateItem.getIngredients(itemStack);
|
||||||
final ListNBT outTag = encodedValue.getList("out", 10);
|
final List<IAEItemStack> products = templateItem.getProducts(itemStack);
|
||||||
this.isCrafting = encodedValue.getBoolean("crafting");
|
final ResourceLocation recipeId = templateItem.getCraftingRecipeId(itemStack);
|
||||||
|
|
||||||
this.canSubstitute = this.isCrafting && encodedValue.getBoolean("substitute");
|
this.pattern = is.copy();
|
||||||
this.patternItem = is;
|
this.isCraftable = recipeId != null;
|
||||||
this.pattern = AEItemStack.fromItemStack(is);
|
this.canSubstitute = templateItem.allowsSubstitution(itemStack);
|
||||||
|
|
||||||
final List<IAEItemStack> in = new ArrayList<>();
|
final List<IAEItemStack> in = new ArrayList<>();
|
||||||
final List<IAEItemStack> out = new ArrayList<>();
|
final List<IAEItemStack> out = new ArrayList<>();
|
||||||
|
|
||||||
for (int x = 0; x < inTag.size(); x++) {
|
for (int x = 0; x < 9; x++) {
|
||||||
CompoundNBT ingredient = inTag.getCompound(x);
|
final IAEItemStack ais = ingredients.get(x);
|
||||||
final ItemStack gs = ItemStack.read(ingredient);
|
final ItemStack gs = ais != null ? ais.createItemStack() : ItemStack.EMPTY;
|
||||||
|
|
||||||
if (!ingredient.isEmpty() && gs.isEmpty()) {
|
|
||||||
throw new IllegalArgumentException("No pattern here!");
|
|
||||||
}
|
|
||||||
|
|
||||||
this.crafting.setInventorySlotContents(x, gs);
|
this.crafting.setInventorySlotContents(x, gs);
|
||||||
|
|
||||||
if (!gs.isEmpty() && (!this.isCrafting || !gs.hasTag())) {
|
if (!gs.isEmpty() && (!this.isCraftable) || !gs.hasTag()) {
|
||||||
this.markItemAs(x, gs, TestStatus.ACCEPT);
|
this.markItemAs(x, gs, TestStatus.ACCEPT);
|
||||||
}
|
}
|
||||||
|
|
||||||
in.add(Api.instance().storage().getStorageChannel(IItemStorageChannel.class).createStack(gs));
|
in.add(ais != null ? ais.copy() : null);
|
||||||
this.testFrame.setInventorySlotContents(x, gs);
|
this.testFrame.setInventorySlotContents(x, gs);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.isCrafting) {
|
if (this.isCraftable) {
|
||||||
this.standardRecipe = w.getRecipeManager().getRecipe(IRecipeType.CRAFTING, this.crafting, w).orElse(null);
|
IRecipe<?> recipe = w.getRecipeManager().getRecipes(IRecipeType.CRAFTING).get(recipeId);
|
||||||
|
|
||||||
if (this.standardRecipe != null) {
|
if (recipe == null || recipe.getType() != IRecipeType.CRAFTING) {
|
||||||
this.correctOutput = this.standardRecipe.getCraftingResult(this.crafting);
|
throw new IllegalStateException("recipe id is not a crafting recipe");
|
||||||
out.add(Api.instance().storage().getStorageChannel(IItemStorageChannel.class)
|
|
||||||
.createStack(this.correctOutput));
|
|
||||||
} else {
|
|
||||||
throw new IllegalStateException("No pattern here!");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.standardRecipe = (ICraftingRecipe) recipe;
|
||||||
|
this.correctOutput = this.standardRecipe.getCraftingResult(this.crafting);
|
||||||
|
|
||||||
|
out.add(Api.instance().storage().getStorageChannel(IItemStorageChannel.class)
|
||||||
|
.createStack(this.correctOutput));
|
||||||
} else {
|
} else {
|
||||||
this.standardRecipe = null;
|
this.standardRecipe = null;
|
||||||
this.correctOutput = ItemStack.EMPTY;
|
this.correctOutput = ItemStack.EMPTY;
|
||||||
|
|
||||||
for (int x = 0; x < outTag.size(); x++) {
|
for (int x = 0; x < 3; x++) {
|
||||||
CompoundNBT resultItemTag = outTag.getCompound(x);
|
final IAEItemStack ais = products.get(x);
|
||||||
final ItemStack gs = ItemStack.read(resultItemTag);
|
final ItemStack gs = ais.createItemStack();
|
||||||
|
|
||||||
if (!resultItemTag.isEmpty() && gs.isEmpty()) {
|
|
||||||
throw new IllegalArgumentException("No pattern here!");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!gs.isEmpty()) {
|
if (!gs.isEmpty()) {
|
||||||
out.add(Api.instance().storage().getStorageChannel(IItemStorageChannel.class).createStack(gs));
|
out.add(ais.copy());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.outputs = out.toArray(new IAEItemStack[0]);
|
|
||||||
this.inputs = in.toArray(new IAEItemStack[0]);
|
this.inputs = in.toArray(new IAEItemStack[0]);
|
||||||
|
this.outputs = out.toArray(new IAEItemStack[0]);
|
||||||
|
|
||||||
final Map<IAEItemStack, IAEItemStack> tmpOutputs = new HashMap<>();
|
final Map<IAEItemStack, IAEItemStack> tmpOutputs = new HashMap<>();
|
||||||
|
|
||||||
@@ -190,12 +185,12 @@ public class PatternHelper implements ICraftingPatternDetails, Comparable<Patter
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ItemStack getPattern() {
|
public ItemStack getPattern() {
|
||||||
return this.patternItem;
|
return this.pattern.createItemStack();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized boolean isValidItemForSlot(final int slotIndex, final ItemStack i, final World w) {
|
public synchronized boolean isValidItemForSlot(final int slotIndex, final ItemStack i, final World w) {
|
||||||
if (!this.isCrafting) {
|
if (!this.isCraftable) {
|
||||||
throw new IllegalStateException("Only crafting recipes supported.");
|
throw new IllegalStateException("Only crafting recipes supported.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -241,7 +236,7 @@ public class PatternHelper implements ICraftingPatternDetails, Comparable<Patter
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isCraftable() {
|
public boolean isCraftable() {
|
||||||
return this.isCrafting;
|
return this.isCraftable;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -271,7 +266,7 @@ public class PatternHelper implements ICraftingPatternDetails, Comparable<Patter
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ItemStack getOutput(final CraftingInventory craftingInv, final World w) {
|
public ItemStack getOutput(final CraftingInventory craftingInv, final World w) {
|
||||||
if (!this.isCrafting) {
|
if (!this.isCraftable) {
|
||||||
throw new IllegalStateException("Only crafting recipes supported.");
|
throw new IllegalStateException("Only crafting recipes supported.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -323,7 +318,7 @@ public class PatternHelper implements ICraftingPatternDetails, Comparable<Patter
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int compareTo(final PatternHelper o) {
|
public int compareTo(final CraftingPatternDetails o) {
|
||||||
return Integer.compare(o.priority, this.priority);
|
return Integer.compare(o.priority, this.priority);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -341,7 +336,7 @@ public class PatternHelper implements ICraftingPatternDetails, Comparable<Patter
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
final PatternHelper other = (PatternHelper) obj;
|
final CraftingPatternDetails other = (CraftingPatternDetails) obj;
|
||||||
|
|
||||||
if (this.pattern != null && other.pattern != null) {
|
if (this.pattern != null && other.pattern != null) {
|
||||||
return this.pattern.equals(other.pattern);
|
return this.pattern.equals(other.pattern);
|
||||||
@@ -57,7 +57,6 @@ import appeng.api.config.Actionable;
|
|||||||
import appeng.api.config.Settings;
|
import appeng.api.config.Settings;
|
||||||
import appeng.api.config.Upgrades;
|
import appeng.api.config.Upgrades;
|
||||||
import appeng.api.config.YesNo;
|
import appeng.api.config.YesNo;
|
||||||
import appeng.api.implementations.ICraftingPatternItem;
|
|
||||||
import appeng.api.implementations.IUpgradeableHost;
|
import appeng.api.implementations.IUpgradeableHost;
|
||||||
import appeng.api.implementations.tiles.ICraftingMachine;
|
import appeng.api.implementations.tiles.ICraftingMachine;
|
||||||
import appeng.api.networking.GridFlags;
|
import appeng.api.networking.GridFlags;
|
||||||
@@ -407,21 +406,15 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void addToCraftingList(final ItemStack is) {
|
private void addToCraftingList(final ItemStack is) {
|
||||||
if (is.isEmpty()) {
|
final ICraftingPatternDetails details = Api.instance().crafting().decodePattern(is,
|
||||||
return;
|
this.iHost.getTileEntity().getWorld());
|
||||||
}
|
|
||||||
|
|
||||||
if (is.getItem() instanceof ICraftingPatternItem) {
|
if (details != null) {
|
||||||
final ICraftingPatternItem cpi = (ICraftingPatternItem) is.getItem();
|
if (this.craftingList == null) {
|
||||||
final ICraftingPatternDetails details = cpi.getPatternForItem(is, this.iHost.getTileEntity().getWorld());
|
this.craftingList = new ArrayList<>();
|
||||||
|
|
||||||
if (details != null) {
|
|
||||||
if (this.craftingList == null) {
|
|
||||||
this.craftingList = new ArrayList<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
this.craftingList.add(details);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.craftingList.add(details);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,37 +18,50 @@
|
|||||||
|
|
||||||
package appeng.items.misc;
|
package appeng.items.misc;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.WeakHashMap;
|
import java.util.WeakHashMap;
|
||||||
|
|
||||||
|
import com.google.common.base.Preconditions;
|
||||||
|
|
||||||
import net.minecraft.client.util.ITooltipFlag;
|
import net.minecraft.client.util.ITooltipFlag;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
import net.minecraft.entity.player.PlayerInventory;
|
import net.minecraft.entity.player.PlayerInventory;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.item.ItemUseContext;
|
import net.minecraft.item.ItemUseContext;
|
||||||
|
import net.minecraft.nbt.CompoundNBT;
|
||||||
|
import net.minecraft.nbt.INBT;
|
||||||
|
import net.minecraft.nbt.ListNBT;
|
||||||
import net.minecraft.util.ActionResult;
|
import net.minecraft.util.ActionResult;
|
||||||
import net.minecraft.util.ActionResultType;
|
import net.minecraft.util.ActionResultType;
|
||||||
import net.minecraft.util.Hand;
|
import net.minecraft.util.Hand;
|
||||||
|
import net.minecraft.util.ResourceLocation;
|
||||||
import net.minecraft.util.text.ITextComponent;
|
import net.minecraft.util.text.ITextComponent;
|
||||||
import net.minecraft.util.text.StringTextComponent;
|
import net.minecraft.util.text.StringTextComponent;
|
||||||
import net.minecraft.util.text.TextFormatting;
|
import net.minecraft.util.text.TextFormatting;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
import net.minecraftforge.api.distmarker.Dist;
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||||
|
import net.minecraftforge.common.util.Constants;
|
||||||
|
|
||||||
import appeng.api.implementations.ICraftingPatternItem;
|
|
||||||
import appeng.api.networking.crafting.ICraftingPatternDetails;
|
import appeng.api.networking.crafting.ICraftingPatternDetails;
|
||||||
|
import appeng.api.storage.channels.IItemStorageChannel;
|
||||||
import appeng.api.storage.data.IAEItemStack;
|
import appeng.api.storage.data.IAEItemStack;
|
||||||
import appeng.core.Api;
|
import appeng.core.Api;
|
||||||
import appeng.core.AppEng;
|
import appeng.core.AppEng;
|
||||||
import appeng.core.localization.GuiText;
|
import appeng.core.localization.GuiText;
|
||||||
import appeng.helpers.InvalidPatternHelper;
|
import appeng.helpers.InvalidPatternHelper;
|
||||||
import appeng.helpers.PatternHelper;
|
|
||||||
import appeng.items.AEBaseItem;
|
import appeng.items.AEBaseItem;
|
||||||
import appeng.util.Platform;
|
import appeng.util.Platform;
|
||||||
|
|
||||||
public class EncodedPatternItem extends AEBaseItem implements ICraftingPatternItem {
|
public class EncodedPatternItem extends AEBaseItem {
|
||||||
|
|
||||||
|
public static final String NBT_INGREDIENTS = "in";
|
||||||
|
public static final String NBT_PRODUCTS = "out";
|
||||||
|
public static final String NBT_SUBSITUTE = "substitute";
|
||||||
|
public static final String NBT_RECIPE_ID = "recipe";
|
||||||
|
|
||||||
// rather simple client side caching.
|
// rather simple client side caching.
|
||||||
private static final Map<ItemStack, ItemStack> SIMPLE_CACHE = new WeakHashMap<>();
|
private static final Map<ItemStack, ItemStack> SIMPLE_CACHE = new WeakHashMap<>();
|
||||||
|
|
||||||
@@ -95,7 +108,7 @@ public class EncodedPatternItem extends AEBaseItem implements ICraftingPatternIt
|
|||||||
@OnlyIn(Dist.CLIENT)
|
@OnlyIn(Dist.CLIENT)
|
||||||
public void addInformation(final ItemStack stack, final World world, final List<ITextComponent> lines,
|
public void addInformation(final ItemStack stack, final World world, final List<ITextComponent> lines,
|
||||||
final ITooltipFlag advancedTooltips) {
|
final ITooltipFlag advancedTooltips) {
|
||||||
final ICraftingPatternDetails details = this.getPatternForItem(stack, world);
|
final ICraftingPatternDetails details = Api.instance().crafting().decodePattern(stack, world);
|
||||||
|
|
||||||
if (details == null) {
|
if (details == null) {
|
||||||
if (!stack.hasTag()) {
|
if (!stack.hasTag()) {
|
||||||
@@ -181,15 +194,6 @@ public class EncodedPatternItem extends AEBaseItem implements ICraftingPatternIt
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public ICraftingPatternDetails getPatternForItem(final ItemStack is, final World w) {
|
|
||||||
try {
|
|
||||||
return new PatternHelper(is, w);
|
|
||||||
} catch (final Throwable t) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public ItemStack getOutput(final ItemStack item) {
|
public ItemStack getOutput(final ItemStack item) {
|
||||||
ItemStack out = SIMPLE_CACHE.get(item);
|
ItemStack out = SIMPLE_CACHE.get(item);
|
||||||
|
|
||||||
@@ -202,11 +206,127 @@ public class EncodedPatternItem extends AEBaseItem implements ICraftingPatternIt
|
|||||||
return ItemStack.EMPTY;
|
return ItemStack.EMPTY;
|
||||||
}
|
}
|
||||||
|
|
||||||
final ICraftingPatternDetails details = this.getPatternForItem(item, w);
|
final ICraftingPatternDetails details = Api.instance().crafting().decodePattern(item, w);
|
||||||
|
|
||||||
out = details != null ? details.getOutputs()[0].createItemStack() : ItemStack.EMPTY;
|
out = details != null ? details.getOutputs()[0].createItemStack() : ItemStack.EMPTY;
|
||||||
|
|
||||||
SIMPLE_CACHE.put(item, out);
|
SIMPLE_CACHE.put(item, out);
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isEncodedPattern(ItemStack itemStack) {
|
||||||
|
return itemStack != null && !itemStack.isEmpty() && itemStack.getItem() == this && itemStack.getTag() != null
|
||||||
|
&& itemStack.getTag().contains(NBT_INGREDIENTS, Constants.NBT.TAG_LIST)
|
||||||
|
&& itemStack.getTag().contains(NBT_PRODUCTS, Constants.NBT.TAG_LIST);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResourceLocation getCraftingRecipeId(ItemStack itemStack) {
|
||||||
|
Preconditions.checkArgument(itemStack.getItem() == this, "Given item stack %s is not an encoded pattern.",
|
||||||
|
itemStack);
|
||||||
|
final CompoundNBT tag = itemStack.getTag();
|
||||||
|
Preconditions.checkArgument(tag != null, "itemStack missing a NBT tag");
|
||||||
|
|
||||||
|
return new ResourceLocation(tag.getString(NBT_RECIPE_ID));
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<IAEItemStack> getIngredients(ItemStack itemStack) {
|
||||||
|
Preconditions.checkArgument(itemStack.getItem() == this, "Given item stack %s is not an encoded pattern.",
|
||||||
|
itemStack);
|
||||||
|
final CompoundNBT tag = itemStack.getTag();
|
||||||
|
Preconditions.checkArgument(tag != null, "itemStack missing a NBT tag");
|
||||||
|
|
||||||
|
final ListNBT inTag = tag.getList(NBT_INGREDIENTS, 10);
|
||||||
|
Preconditions.checkArgument(inTag.size() < 10, "Cannot use more than 9 ingredients");
|
||||||
|
|
||||||
|
final List<IAEItemStack> in = new ArrayList<>(inTag.size());
|
||||||
|
for (int x = 0; x < inTag.size(); x++) {
|
||||||
|
CompoundNBT ingredient = inTag.getCompound(x);
|
||||||
|
final ItemStack gs = ItemStack.read(ingredient);
|
||||||
|
|
||||||
|
Preconditions.checkArgument(!(!ingredient.isEmpty() && gs.isEmpty()), "invalid itemStack in slot", x);
|
||||||
|
|
||||||
|
in.add(Api.instance().storage().getStorageChannel(IItemStorageChannel.class).createStack(gs));
|
||||||
|
}
|
||||||
|
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<IAEItemStack> getProducts(ItemStack itemStack) {
|
||||||
|
Preconditions.checkArgument(itemStack.getItem() == this, "Given item stack %s is not an encoded pattern.",
|
||||||
|
itemStack);
|
||||||
|
final CompoundNBT tag = itemStack.getTag();
|
||||||
|
Preconditions.checkArgument(tag != null, "itemStack missing a NBT tag");
|
||||||
|
|
||||||
|
final ListNBT outTag = tag.getList(NBT_PRODUCTS, 10);
|
||||||
|
Preconditions.checkArgument(outTag.size() < 4, "Cannot use more than 3 ingredients");
|
||||||
|
|
||||||
|
final List<IAEItemStack> out = new ArrayList<>(outTag.size());
|
||||||
|
for (int x = 0; x < outTag.size(); x++) {
|
||||||
|
CompoundNBT ingredient = outTag.getCompound(x);
|
||||||
|
final ItemStack gs = ItemStack.read(ingredient);
|
||||||
|
|
||||||
|
Preconditions.checkArgument(!(!ingredient.isEmpty() && gs.isEmpty()), "invalid itemStack in slot", x);
|
||||||
|
|
||||||
|
out.add(Api.instance().storage().getStorageChannel(IItemStorageChannel.class).createStack(gs));
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean allowsSubstitution(ItemStack itemStack) {
|
||||||
|
final CompoundNBT tag = itemStack.getTag();
|
||||||
|
|
||||||
|
Preconditions.checkArgument(tag != null, "itemStack missing a NBT tag");
|
||||||
|
|
||||||
|
return getCraftingRecipeId(itemStack) == null && tag.getBoolean(NBT_SUBSITUTE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use the public API instead {@link appeng.core.api.ApiCrafting}
|
||||||
|
*/
|
||||||
|
public static void encodeCraftingPattern(ItemStack stack, ItemStack[] in, ItemStack[] out,
|
||||||
|
ResourceLocation recipeId, boolean allowSubstitutes) {
|
||||||
|
CompoundNBT encodedValue = encodeInputsAndOutputs(in, out);
|
||||||
|
encodedValue.putString(EncodedPatternItem.NBT_RECIPE_ID, recipeId.toString());
|
||||||
|
encodedValue.putBoolean(EncodedPatternItem.NBT_SUBSITUTE, allowSubstitutes);
|
||||||
|
stack.setTag(encodedValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use the public API instead {@link appeng.core.api.ApiCrafting}
|
||||||
|
*/
|
||||||
|
public static void encodeProcessingPattern(ItemStack stack, ItemStack[] in, ItemStack[] out) {
|
||||||
|
stack.setTag(encodeInputsAndOutputs(in, out));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static CompoundNBT encodeInputsAndOutputs(ItemStack[] in, ItemStack[] out) {
|
||||||
|
final CompoundNBT encodedValue = new CompoundNBT();
|
||||||
|
|
||||||
|
final ListNBT tagIn = new ListNBT();
|
||||||
|
final ListNBT tagOut = new ListNBT();
|
||||||
|
|
||||||
|
for (final ItemStack i : in) {
|
||||||
|
tagIn.add(createItemTag(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (final ItemStack i : out) {
|
||||||
|
tagOut.add(createItemTag(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
encodedValue.put(EncodedPatternItem.NBT_INGREDIENTS, tagIn);
|
||||||
|
encodedValue.put(EncodedPatternItem.NBT_PRODUCTS, tagOut);
|
||||||
|
return encodedValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static INBT createItemTag(final ItemStack i) {
|
||||||
|
final CompoundNBT c = new CompoundNBT();
|
||||||
|
|
||||||
|
if (!i.isEmpty()) {
|
||||||
|
i.write(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ import java.util.concurrent.Executors;
|
|||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
import java.util.concurrent.ThreadFactory;
|
import java.util.concurrent.ThreadFactory;
|
||||||
|
|
||||||
|
import com.google.common.base.Preconditions;
|
||||||
import com.google.common.collect.HashMultimap;
|
import com.google.common.collect.HashMultimap;
|
||||||
import com.google.common.collect.ImmutableCollection;
|
import com.google.common.collect.ImmutableCollection;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
@@ -80,6 +81,7 @@ import appeng.crafting.CraftingJob;
|
|||||||
import appeng.crafting.CraftingLink;
|
import appeng.crafting.CraftingLink;
|
||||||
import appeng.crafting.CraftingLinkNexus;
|
import appeng.crafting.CraftingLinkNexus;
|
||||||
import appeng.crafting.CraftingWatcher;
|
import appeng.crafting.CraftingWatcher;
|
||||||
|
import appeng.helpers.CraftingPatternDetails;
|
||||||
import appeng.me.cluster.implementations.CraftingCPUCluster;
|
import appeng.me.cluster.implementations.CraftingCPUCluster;
|
||||||
import appeng.me.helpers.BaseActionSource;
|
import appeng.me.helpers.BaseActionSource;
|
||||||
import appeng.me.helpers.GenericInterestManager;
|
import appeng.me.helpers.GenericInterestManager;
|
||||||
@@ -303,6 +305,8 @@ public class CraftingGridCache
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addCraftingOption(final ICraftingMedium medium, final ICraftingPatternDetails api) {
|
public void addCraftingOption(final ICraftingMedium medium, final ICraftingPatternDetails api) {
|
||||||
|
Preconditions.checkArgument(api.getClass() == CraftingPatternDetails.class,
|
||||||
|
"Only supports internal ICraftingPatternDetails for now");
|
||||||
List<ICraftingMedium> details = this.craftingMethods.get(api);
|
List<ICraftingMedium> details = this.craftingMethods.get(api);
|
||||||
if (details == null) {
|
if (details == null) {
|
||||||
details = new ArrayList<>();
|
details = new ArrayList<>();
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ import net.minecraftforge.fml.hooks.BasicEventHooks;
|
|||||||
import appeng.api.config.Actionable;
|
import appeng.api.config.Actionable;
|
||||||
import appeng.api.config.FuzzyMode;
|
import appeng.api.config.FuzzyMode;
|
||||||
import appeng.api.config.PowerMultiplier;
|
import appeng.api.config.PowerMultiplier;
|
||||||
import appeng.api.implementations.ICraftingPatternItem;
|
import appeng.api.crafting.ICraftingHelper;
|
||||||
import appeng.api.networking.IGrid;
|
import appeng.api.networking.IGrid;
|
||||||
import appeng.api.networking.IGridHost;
|
import appeng.api.networking.IGridHost;
|
||||||
import appeng.api.networking.IGridNode;
|
import appeng.api.networking.IGridNode;
|
||||||
@@ -1056,9 +1056,9 @@ public final class CraftingCPUCluster implements IAECluster, ICraftingCPU {
|
|||||||
for (int x = 0; x < list.size(); x++) {
|
for (int x = 0; x < list.size(); x++) {
|
||||||
final CompoundNBT item = list.getCompound(x);
|
final CompoundNBT item = list.getCompound(x);
|
||||||
final IAEItemStack pattern = AEItemStack.fromNBT(item);
|
final IAEItemStack pattern = AEItemStack.fromNBT(item);
|
||||||
if (pattern != null && pattern.getItem() instanceof ICraftingPatternItem) {
|
ICraftingHelper craftingHelper = Api.instance().crafting();
|
||||||
final ICraftingPatternItem cpi = (ICraftingPatternItem) pattern.getItem();
|
if (craftingHelper.isEncodedPattern(pattern)) {
|
||||||
final ICraftingPatternDetails details = cpi.getPatternForItem(pattern.createItemStack(),
|
final ICraftingPatternDetails details = craftingHelper.decodePattern(pattern.createItemStack(),
|
||||||
this.getWorld());
|
this.getWorld());
|
||||||
if (details != null) {
|
if (details != null) {
|
||||||
final TaskProgress tp = new TaskProgress();
|
final TaskProgress tp = new TaskProgress();
|
||||||
|
|||||||
@@ -28,12 +28,12 @@ import net.minecraft.util.ResourceLocation;
|
|||||||
import net.minecraftforge.items.IItemHandler;
|
import net.minecraftforge.items.IItemHandler;
|
||||||
|
|
||||||
import appeng.api.config.SecurityPermissions;
|
import appeng.api.config.SecurityPermissions;
|
||||||
import appeng.api.implementations.ICraftingPatternItem;
|
|
||||||
import appeng.api.networking.crafting.ICraftingPatternDetails;
|
import appeng.api.networking.crafting.ICraftingPatternDetails;
|
||||||
import appeng.api.parts.IPartModel;
|
import appeng.api.parts.IPartModel;
|
||||||
import appeng.api.storage.data.IAEItemStack;
|
import appeng.api.storage.data.IAEItemStack;
|
||||||
import appeng.container.implementations.MEMonitorableContainer;
|
import appeng.container.implementations.MEMonitorableContainer;
|
||||||
import appeng.container.implementations.PatternTermContainer;
|
import appeng.container.implementations.PatternTermContainer;
|
||||||
|
import appeng.core.Api;
|
||||||
import appeng.core.AppEng;
|
import appeng.core.AppEng;
|
||||||
import appeng.helpers.Reflected;
|
import appeng.helpers.Reflected;
|
||||||
import appeng.items.parts.PartModels;
|
import appeng.items.parts.PartModels;
|
||||||
@@ -107,23 +107,20 @@ public class PatternTerminalPart extends AbstractTerminalPart {
|
|||||||
final ItemStack removedStack, final ItemStack newStack) {
|
final ItemStack removedStack, final ItemStack newStack) {
|
||||||
if (inv == this.pattern && slot == 1) {
|
if (inv == this.pattern && slot == 1) {
|
||||||
final ItemStack is = this.pattern.getStackInSlot(1);
|
final ItemStack is = this.pattern.getStackInSlot(1);
|
||||||
if (!is.isEmpty() && is.getItem() instanceof ICraftingPatternItem) {
|
final ICraftingPatternDetails details = Api.instance().crafting().decodePattern(is,
|
||||||
final ICraftingPatternItem pattern = (ICraftingPatternItem) is.getItem();
|
this.getHost().getTile().getWorld());
|
||||||
final ICraftingPatternDetails details = pattern.getPatternForItem(is,
|
if (details != null) {
|
||||||
this.getHost().getTile().getWorld());
|
this.setCraftingRecipe(details.isCraftable());
|
||||||
if (details != null) {
|
this.setSubstitution(details.canSubstitute());
|
||||||
this.setCraftingRecipe(details.isCraftable());
|
|
||||||
this.setSubstitution(details.canSubstitute());
|
|
||||||
|
|
||||||
for (int x = 0; x < this.crafting.getSlots() && x < details.getInputs().length; x++) {
|
for (int x = 0; x < this.crafting.getSlots() && x < details.getInputs().length; x++) {
|
||||||
final IAEItemStack item = details.getInputs()[x];
|
final IAEItemStack item = details.getInputs()[x];
|
||||||
this.crafting.setStackInSlot(x, item == null ? ItemStack.EMPTY : item.createItemStack());
|
this.crafting.setStackInSlot(x, item == null ? ItemStack.EMPTY : item.createItemStack());
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int x = 0; x < this.output.getSlots() && x < details.getOutputs().length; x++) {
|
for (int x = 0; x < this.output.getSlots() && x < details.getOutputs().length; x++) {
|
||||||
final IAEItemStack item = details.getOutputs()[x];
|
final IAEItemStack item = details.getOutputs()[x];
|
||||||
this.output.setStackInSlot(x, item == null ? ItemStack.EMPTY : item.createItemStack());
|
this.output.setStackInSlot(x, item == null ? ItemStack.EMPTY : item.createItemStack());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (inv == this.crafting) {
|
} else if (inv == this.crafting) {
|
||||||
|
|||||||
@@ -226,8 +226,7 @@ public class MolecularAssemblerTileEntity extends AENetworkInvTileEntity
|
|||||||
|
|
||||||
if (!myPat.isEmpty() && myPat.getItem() instanceof EncodedPatternItem) {
|
if (!myPat.isEmpty() && myPat.getItem() instanceof EncodedPatternItem) {
|
||||||
final World w = this.getWorld();
|
final World w = this.getWorld();
|
||||||
final EncodedPatternItem iep = (EncodedPatternItem) myPat.getItem();
|
final ICraftingPatternDetails ph = Api.instance().crafting().decodePattern(myPat, w);
|
||||||
final ICraftingPatternDetails ph = iep.getPatternForItem(myPat, w);
|
|
||||||
if (ph != null && ph.isCraftable()) {
|
if (ph != null && ph.isCraftable()) {
|
||||||
this.forcePlan = true;
|
this.forcePlan = true;
|
||||||
this.myPlan = ph;
|
this.myPlan = ph;
|
||||||
@@ -253,8 +252,7 @@ public class MolecularAssemblerTileEntity extends AENetworkInvTileEntity
|
|||||||
if (!is.isEmpty() && is.getItem() instanceof EncodedPatternItem) {
|
if (!is.isEmpty() && is.getItem() instanceof EncodedPatternItem) {
|
||||||
if (!ItemStack.areItemsEqual(is, this.myPattern)) {
|
if (!ItemStack.areItemsEqual(is, this.myPattern)) {
|
||||||
final World w = this.getWorld();
|
final World w = this.getWorld();
|
||||||
final EncodedPatternItem iep = (EncodedPatternItem) is.getItem();
|
final ICraftingPatternDetails ph = Api.instance().crafting().decodePattern(is, w);
|
||||||
final ICraftingPatternDetails ph = iep.getPatternForItem(is, w);
|
|
||||||
|
|
||||||
if (ph != null && ph.isCraftable()) {
|
if (ph != null && ph.isCraftable()) {
|
||||||
this.progress = 0;
|
this.progress = 0;
|
||||||
|
|||||||
@@ -10,12 +10,14 @@ import net.minecraft.world.IBlockReader;
|
|||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* To be implemented on blocks that "hide" another block inside, so connected textures can still be accomplished.
|
* To be implemented on blocks that "hide" another block inside, so connected
|
||||||
|
* textures can still be accomplished.
|
||||||
*/
|
*/
|
||||||
public interface IFacade {
|
public interface IFacade {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated Use {@link #getFacade(IBlockReader, BlockPos, Direction, BlockPos)}
|
* @deprecated Use
|
||||||
|
* {@link #getFacade(IBlockReader, BlockPos, Direction, BlockPos)}
|
||||||
*/
|
*/
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@Deprecated
|
@Deprecated
|
||||||
@@ -24,20 +26,18 @@ public interface IFacade {
|
|||||||
/**
|
/**
|
||||||
* Gets the blockstate this facade appears as.
|
* Gets the blockstate this facade appears as.
|
||||||
*
|
*
|
||||||
* @param world
|
* @param world {@link World}
|
||||||
* {@link World}
|
* @param pos The Blocks position
|
||||||
* @param pos
|
* @param side The side being rendered, NOT the side being connected from.
|
||||||
* The Blocks position
|
* <p>
|
||||||
* @param side
|
* This value can be null if no side is specified. Please
|
||||||
* The side being rendered, NOT the side being connected from.
|
* handle this appropriately.
|
||||||
* <p>
|
* @param connection The position of the block being connected to.
|
||||||
* This value can be null if no side is specified. Please handle this appropriately.
|
|
||||||
* @param connection
|
|
||||||
* The position of the block being connected to.
|
|
||||||
* @return The blockstate which your block appears as.
|
* @return The blockstate which your block appears as.
|
||||||
*/
|
*/
|
||||||
@Nonnull
|
@Nonnull
|
||||||
default BlockState getFacade(@Nonnull IBlockReader world, @Nonnull BlockPos pos, @Nullable Direction side, @Nonnull BlockPos connection) {
|
default BlockState getFacade(@Nonnull IBlockReader world, @Nonnull BlockPos pos, @Nullable Direction side,
|
||||||
|
@Nonnull BlockPos connection) {
|
||||||
return getFacade(world, pos, side);
|
return getFacade(world, pos, side);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user