Fix filter dupe, allow Schematicannon to place brackets

This commit is contained in:
reidbhuntley 2021-05-22 21:50:31 -04:00
parent bfc8c3e306
commit 73895604c8
16 changed files with 166 additions and 73 deletions

View file

@ -107,28 +107,28 @@ public class DeployerMovementBehaviour extends MovementBehaviour {
.isVecInside(pos.subtract(schematicWorld.anchor)))
return;
BlockState blockState = schematicWorld.getBlockState(pos);
ItemRequirement requirement = ItemRequirement.of(blockState);
ItemRequirement requirement = ItemRequirement.of(blockState, schematicWorld.getTileEntity(pos));
if (requirement.isInvalid() || requirement.isEmpty())
return;
if (AllBlocks.BELT.has(blockState))
return;
List<ItemStack> requiredItems = requirement.getRequiredItems();
ItemStack firstRequired = requiredItems.isEmpty() ? ItemStack.EMPTY : requiredItems.get(0);
List<ItemRequirement.StackRequirement> requiredItems = requirement.getRequiredItems();
ItemStack firstRequired = requiredItems.isEmpty() ? ItemStack.EMPTY : requiredItems.get(0).item;
if (!context.contraption.hasUniversalCreativeCrate) {
IItemHandler iItemHandler = context.contraption.inventory;
for (ItemStack required : requiredItems) {
for (ItemRequirement.StackRequirement required : requiredItems) {
int amountFound = ItemHelper
.extract(iItemHandler, s -> ItemRequirement.validate(required, s), ExtractionCountMode.UPTO,
required.getCount(), true)
.extract(iItemHandler, s -> ItemRequirement.validate(required.item, s), ExtractionCountMode.UPTO,
required.item.getCount(), true)
.getCount();
if (amountFound < required.getCount())
if (amountFound < required.item.getCount())
return;
}
for (ItemStack required : requiredItems)
ItemHelper.extract(iItemHandler, s -> ItemRequirement.validate(required, s), ExtractionCountMode.UPTO,
required.getCount(), false);
for (ItemRequirement.StackRequirement required : requiredItems)
ItemHelper.extract(iItemHandler, s -> ItemRequirement.validate(required.item, s), ExtractionCountMode.UPTO,
required.item.getCount(), false);
}
CompoundNBT data = null;

View file

@ -433,7 +433,7 @@ public class CartAssemblerBlock extends AbstractRailBlock
}
@Override
public ItemRequirement getRequiredItems(BlockState state) {
public ItemRequirement getRequiredItems(BlockState state, TileEntity te) {
ArrayList<ItemStack> reuiredItems = new ArrayList<>();
reuiredItems.add(new ItemStack(getRailItem(state)));
reuiredItems.add(new ItemStack(asItem()));

View file

@ -140,8 +140,8 @@ public class EncasedPipeBlock extends Block implements IWrenchable, ISpecialBloc
}
@Override
public ItemRequirement getRequiredItems(BlockState state) {
return ItemRequirement.of(AllBlocks.FLUID_PIPE.getDefaultState());
public ItemRequirement getRequiredItems(BlockState state, TileEntity te) {
return ItemRequirement.of(AllBlocks.FLUID_PIPE.getDefaultState(), te);
}
}

View file

@ -80,8 +80,8 @@ public class GlassFluidPipeBlock extends AxisPipeBlock implements IWaterLoggable
}
@Override
public ItemRequirement getRequiredItems(BlockState state) {
return ItemRequirement.of(AllBlocks.FLUID_PIPE.getDefaultState());
public ItemRequirement getRequiredItems(BlockState state, TileEntity te) {
return ItemRequirement.of(AllBlocks.FLUID_PIPE.getDefaultState(), te);
}
@Override

View file

@ -587,7 +587,7 @@ public class BeltBlock extends HorizontalKineticBlock implements ITE<BeltTileEnt
}
@Override
public ItemRequirement getRequiredItems(BlockState state) {
public ItemRequirement getRequiredItems(BlockState state, TileEntity te) {
List<ItemStack> required = new ArrayList<>();
if (state.get(PART) != BeltPart.MIDDLE)
required.add(AllBlocks.SHAFT.asStack());

View file

@ -4,6 +4,7 @@ import java.util.Optional;
import java.util.function.Function;
import java.util.function.Predicate;
import com.simibubi.create.content.schematics.ItemRequirement;
import com.simibubi.create.foundation.advancement.AllTriggers;
import com.simibubi.create.foundation.advancement.ITriggerable;
import com.simibubi.create.foundation.tileEntity.SmartTileEntity;
@ -81,6 +82,14 @@ public class BracketedTileEntityBehaviour extends TileEntityBehaviour {
return bracket.orElse(Blocks.AIR.getDefaultState());
}
@Override
public ItemRequirement getRequiredItems() {
return ItemRequirement.of(getBracket(), null);
}
@Override
public boolean isSafeNBT() { return true; }
@Override
public void write(CompoundNBT nbt, boolean clientPacket) {
bracket.ifPresent(p -> nbt.put("Bracket", NBTUtil.writeBlockState(p)));

View file

@ -51,8 +51,8 @@ public class EncasedShaftBlock extends AbstractEncasedShaftBlock implements ISpe
}
@Override
public ItemRequirement getRequiredItems(BlockState state) {
return ItemRequirement.of(AllBlocks.SHAFT.getDefaultState());
public ItemRequirement getRequiredItems(BlockState state, TileEntity te) {
return ItemRequirement.of(AllBlocks.SHAFT.getDefaultState(), te);
}
}

View file

@ -22,6 +22,7 @@ import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemUseContext;
import net.minecraft.state.EnumProperty;
import net.minecraft.state.StateContainer.Builder;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.ActionResultType;
import net.minecraft.util.Direction;
import net.minecraft.util.IStringSerializable;
@ -192,8 +193,8 @@ public class BeltFunnelBlock extends AbstractHorizontalFunnelBlock implements IS
}
@Override
public ItemRequirement getRequiredItems(BlockState state) {
return ItemRequirement.of(parent.getDefaultState());
public ItemRequirement getRequiredItems(BlockState state, TileEntity te) {
return ItemRequirement.of(parent.getDefaultState(), te);
}
}

View file

@ -1,10 +1,11 @@
package com.simibubi.create.content.schematics;
import net.minecraft.block.BlockState;
import net.minecraft.tileentity.TileEntity;
public interface ISpecialBlockItemRequirement {
default ItemRequirement getRequiredItems(BlockState state) {
default ItemRequirement getRequiredItems(BlockState state, TileEntity te) {
return ItemRequirement.INVALID;
}

View file

@ -3,6 +3,10 @@ package com.simibubi.create.content.schematics;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import com.simibubi.create.foundation.tileEntity.SmartTileEntity;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
@ -24,6 +28,7 @@ import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.state.properties.SlabType;
import net.minecraft.tileentity.TileEntity;
public class ItemRequirement {
@ -31,8 +36,17 @@ public class ItemRequirement {
CONSUME, DAMAGE
}
ItemUseType usage;
List<ItemStack> requiredItems;
public static class StackRequirement {
public final ItemStack item;
public final ItemUseType usage;
public StackRequirement(ItemUseType usage, ItemStack item) {
this.item = item;
this.usage = usage;
}
}
List<StackRequirement> requiredItems;
public static ItemRequirement INVALID = new ItemRequirement();
public static ItemRequirement NONE = new ItemRequirement();
@ -40,21 +54,43 @@ public class ItemRequirement {
private ItemRequirement() {
}
public ItemRequirement(ItemUseType usage, Item item) {
this(usage, Arrays.asList(new ItemStack(item)));
}
public ItemRequirement(ItemUseType usage, List<ItemStack> requiredItems) {
this.usage = usage;
public ItemRequirement(List<StackRequirement> requiredItems) {
this.requiredItems = requiredItems;
}
public static ItemRequirement of(BlockState state) {
public ItemRequirement(ItemUseType usage, ItemStack items) {
this(Arrays.asList(new StackRequirement(usage, items)));
}
public ItemRequirement(ItemUseType usage, Item item) {
this(usage, new ItemStack(item));
}
public ItemRequirement(ItemUseType usage, List<ItemStack> requiredItems) {
this(requiredItems.stream().map(req -> new StackRequirement(usage, req)).collect(Collectors.toList()));
}
public static ItemRequirement of(BlockState state, TileEntity te) {
Block block = state.getBlock();
ItemRequirement baseRequirement;
if (block instanceof ISpecialBlockItemRequirement) {
baseRequirement = ((ISpecialBlockItemRequirement) block).getRequiredItems(state, te);
} else {
baseRequirement = ofBlockState(state, block);
}
// Behaviours can add additional required items
if (te instanceof SmartTileEntity)
baseRequirement = baseRequirement.with(((SmartTileEntity) te).getRequiredItems());
return baseRequirement;
}
private static ItemRequirement ofBlockState(BlockState state, Block block) {
if (block == Blocks.AIR)
return NONE;
if (block instanceof ISpecialBlockItemRequirement)
return ((ISpecialBlockItemRequirement) block).getRequiredItems(state);
Item item = BlockItem.BLOCK_TO_ITEM.getOrDefault(state.getBlock(), Items.AIR);
@ -125,16 +161,25 @@ public class ItemRequirement {
return INVALID == this;
}
public List<ItemStack> getRequiredItems() {
public List<StackRequirement> getRequiredItems() {
return requiredItems;
}
public ItemUseType getUsage() {
return usage;
}
public static boolean validate(ItemStack required, ItemStack present) {
return required.isEmpty() || required.getItem() == present.getItem();
}
public ItemRequirement with(ItemRequirement other) {
if (this.isInvalid() || other.isInvalid())
return INVALID;
if (this.isEmpty())
return other;
if (other.isEmpty())
return this;
return new ItemRequirement(
Stream.concat(requiredItems.stream(), other.requiredItems.stream()).collect(Collectors.toList())
);
}
}

View file

@ -43,11 +43,11 @@ public class MaterialChecklist {
if (requirement.isInvalid())
return;
for (ItemStack stack : requirement.requiredItems) {
if (requirement.getUsage() == ItemUseType.DAMAGE)
putOrIncrement(damageRequired, stack);
if (requirement.getUsage() == ItemUseType.CONSUME)
putOrIncrement(required, stack);
for (ItemRequirement.StackRequirement stack : requirement.requiredItems) {
if (stack.usage == ItemUseType.DAMAGE)
putOrIncrement(damageRequired, stack.item);
if (stack.usage == ItemUseType.CONSUME)
putOrIncrement(required, stack.item);
}
}

View file

@ -433,6 +433,7 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
boolean shouldSkip = false;
BlockState blockState = Blocks.AIR.getDefaultState();
TileEntity tileEntity = null;
ItemRequirement requirement;
if (entityMode) {
@ -442,8 +443,9 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
} else {
blockState = BlockHelper.setZeroAge(blockReader.getBlockState(target));
requirement = ItemRequirement.of(blockState);
shouldSkip = !shouldPlace(target, blockState);
tileEntity = blockReader.getTileEntity(target);
requirement = ItemRequirement.of(blockState, tileEntity);
shouldSkip = !shouldPlace(target, blockState, tileEntity);
}
if (shouldSkip || requirement.isInvalid()) {
@ -453,10 +455,10 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
}
// Find item
List<ItemStack> requiredItems = requirement.getRequiredItems();
List<ItemRequirement.StackRequirement> requiredItems = requirement.getRequiredItems();
if (!requirement.isEmpty()) {
for (ItemStack required : requiredItems) {
if (!grabItemsFromAttachedInventories(required, requirement.getUsage(), true)) {
for (ItemRequirement.StackRequirement required : requiredItems) {
if (!grabItemsFromAttachedInventories(required.item, required.usage, true)) {
if (skipMissing) {
statusMsg = "skipping";
blockSkipped = true;
@ -467,15 +469,15 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
return;
}
missingItem = required;
missingItem = required.item;
state = State.PAUSED;
statusMsg = "missingBlock";
return;
}
}
for (ItemStack required : requiredItems)
grabItemsFromAttachedInventories(required, requirement.getUsage(), false);
for (ItemRequirement.StackRequirement required : requiredItems)
grabItemsFromAttachedInventories(required.item, required.usage, false);
}
// Success
@ -485,7 +487,7 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
else
statusMsg = "clearing";
ItemStack icon = requirement.isEmpty() || requiredItems.isEmpty() ? ItemStack.EMPTY : requiredItems.get(0);
ItemStack icon = requirement.isEmpty() || requiredItems.isEmpty() ? ItemStack.EMPTY : requiredItems.get(0).item;
if (entityMode)
launchEntity(target, icon, blockReader.getEntities()
.collect(Collectors.toList())
@ -759,7 +761,7 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
deferredBlocks.clear();
}
protected boolean shouldPlace(BlockPos pos, BlockState state) {
protected boolean shouldPlace(BlockPos pos, BlockState state, TileEntity te) {
if (world == null)
return false;
BlockState toReplace = world.getBlockState(pos);
@ -790,7 +792,7 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
&& (toReplace.hasTileEntity() || (toReplaceOther != null && toReplaceOther.hasTileEntity())))
return false;
if (shouldIgnoreBlockState(state))
if (shouldIgnoreBlockState(state, te))
return false;
if (replaceMode == 3)
@ -809,12 +811,12 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
return false;
}
protected boolean shouldIgnoreBlockState(BlockState state) {
protected boolean shouldIgnoreBlockState(BlockState state, TileEntity te) {
// Block doesnt have a mapping (Water, lava, etc)
if (state.getBlock() == Blocks.STRUCTURE_VOID)
return true;
ItemRequirement requirement = ItemRequirement.of(state);
ItemRequirement requirement = ItemRequirement.of(state, te);
if (requirement.isEmpty())
return false;
if (requirement.isInvalid())
@ -951,15 +953,17 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
if (schematicLoaded) {
blocksToPlace = blocksPlaced;
for (BlockPos pos : blockReader.getAllPositions()) {
BlockState required = blockReader.getBlockState(pos.add(schematicAnchor));
BlockPos relPos = pos.add(schematicAnchor);
BlockState required = blockReader.getBlockState(relPos);
TileEntity requiredTE = blockReader.getTileEntity(relPos);
if (!getWorld().isAreaLoaded(pos.add(schematicAnchor), 0)) {
checklist.warnBlockNotLoaded();
continue;
}
if (!shouldPlace(pos.add(schematicAnchor), required))
if (!shouldPlace(pos.add(schematicAnchor), required, requiredTE))
continue;
ItemRequirement requirement = ItemRequirement.of(required);
ItemRequirement requirement = ItemRequirement.of(required, blockReader.getTileEntity(relPos));
if (requirement.isEmpty())
continue;
if (requirement.isInvalid())

View file

@ -6,6 +6,7 @@ import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import com.simibubi.create.content.schematics.ItemRequirement;
import com.simibubi.create.foundation.tileEntity.behaviour.BehaviourType;
import com.simibubi.create.foundation.utility.IPartialSafeNBT;
@ -13,6 +14,7 @@ import com.simibubi.create.foundation.utility.IPartialSafeNBT;
import net.minecraft.block.BlockState;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.tileentity.ITickableTileEntity;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.tileentity.TileEntityType;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
@ -120,6 +122,7 @@ public abstract class SmartTileEntity extends SyncedTileEntity implements ITicka
behaviourList.forEach(tb -> tb.write(compound, clientPacket));
}
@Override
public void writeSafe(CompoundNBT compound, boolean clientPacket) {
super.write(compound);
behaviourList.forEach(tb -> {
@ -128,6 +131,14 @@ public abstract class SmartTileEntity extends SyncedTileEntity implements ITicka
});
}
public ItemRequirement getRequiredItems() {
return behaviourList.stream().reduce(
ItemRequirement.NONE,
(a,b) -> a.with(b.getRequiredItems()),
(a,b) -> a.with(b)
);
}
@Override
public void remove() {
forEachBehaviour(TileEntityBehaviour::remove);

View file

@ -1,8 +1,10 @@
package com.simibubi.create.foundation.tileEntity;
import com.simibubi.create.content.schematics.ItemRequirement;
import com.simibubi.create.foundation.tileEntity.behaviour.BehaviourType;
import net.minecraft.block.BlockState;
import net.minecraft.item.Item;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.math.BlockPos;
@ -44,6 +46,8 @@ public abstract class TileEntityBehaviour {
public boolean isSafeNBT() { return false; }
public ItemRequirement getRequiredItems() { return ItemRequirement.NONE; }
public void onBlockChanged(BlockState oldState) {
}

View file

@ -4,6 +4,7 @@ import java.util.function.Consumer;
import java.util.function.Supplier;
import com.simibubi.create.content.logistics.item.filter.FilterItem;
import com.simibubi.create.content.schematics.ItemRequirement;
import com.simibubi.create.foundation.networking.AllPackets;
import com.simibubi.create.foundation.tileEntity.SmartTileEntity;
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
@ -13,6 +14,7 @@ import com.simibubi.create.foundation.utility.VecHelper;
import net.minecraft.block.BlockState;
import net.minecraft.entity.item.ItemEntity;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.util.Direction;
@ -168,6 +170,15 @@ public class FilteringBehaviour extends TileEntityBehaviour {
super.destroy();
}
@Override
public ItemRequirement getRequiredItems() {
Item filterItem = filter.getItem();
if (filterItem instanceof FilterItem)
return new ItemRequirement(ItemRequirement.ItemUseType.CONSUME, filterItem);
return ItemRequirement.NONE;
}
public ItemStack getFilter(Direction side) {
return getFilter();
}

View file

@ -7,6 +7,7 @@ import java.util.Set;
import java.util.function.BiFunction;
import java.util.function.Predicate;
import com.simibubi.create.content.schematics.ItemRequirement;
import com.simibubi.create.foundation.tileEntity.SmartTileEntity;
import com.simibubi.create.foundation.tileEntity.behaviour.ValueBoxTransform;
import com.simibubi.create.foundation.tileEntity.behaviour.ValueBoxTransform.Sided;
@ -58,9 +59,6 @@ public class SidedFilteringBehaviour extends FilteringBehaviour {
removeFilter(d);
}
@Override
public boolean isSafeNBT() { return true; }
@Override
public void write(CompoundNBT nbt, boolean clientPacket) {
nbt.put("Filters", NBTHelper.writeCompoundList(sidedFilters.entrySet(), entry -> {
@ -122,6 +120,15 @@ public class SidedFilteringBehaviour extends FilteringBehaviour {
super.destroy();
}
@Override
public ItemRequirement getRequiredItems() {
return sidedFilters.values().stream().reduce(
ItemRequirement.NONE,
(a,b) -> a.with(b.getRequiredItems()),
(a,b) -> a.with(b)
);
}
public void removeFilter(Direction side) {
if (!sidedFilters.containsKey(side))
return;