Merge pull request #1645 from reidbhuntley/deployer

A few more bug fixes
This commit is contained in:
simibubi 2021-05-25 14:11:36 +02:00 committed by GitHub
commit 83e269e498
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 228 additions and 95 deletions

View File

@ -8,6 +8,12 @@ import java.util.List;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import com.simibubi.create.content.contraptions.components.structureMovement.mounted.CartAssemblerBlockItem;
import net.minecraft.block.DoublePlantBlock;
import net.minecraft.state.properties.DoubleBlockHalf;
import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.lang3.tuple.Pair;
import com.google.common.collect.Multimap; import com.google.common.collect.Multimap;
@ -277,7 +283,9 @@ public class DeployerHandler {
return; return;
if (useItem == DENY) if (useItem == DENY)
return; return;
if (item instanceof BlockItem && !clickedState.isReplaceable(new BlockItemUseContext(itemusecontext))) if (item instanceof BlockItem
&& !(item instanceof CartAssemblerBlockItem)
&& !clickedState.isReplaceable(new BlockItemUseContext(itemusecontext)))
return; return;
// Reposition fire placement for convenience // Reposition fire placement for convenience
@ -349,8 +357,22 @@ public class DeployerHandler {
prevHeldItem.onBlockDestroyed(world, blockstate, pos, player); prevHeldItem.onBlockDestroyed(world, blockstate, pos, player);
if (prevHeldItem.isEmpty() && !heldItem.isEmpty()) if (prevHeldItem.isEmpty() && !heldItem.isEmpty())
net.minecraftforge.event.ForgeEventFactory.onPlayerDestroyItem(player, heldItem, Hand.MAIN_HAND); net.minecraftforge.event.ForgeEventFactory.onPlayerDestroyItem(player, heldItem, Hand.MAIN_HAND);
if (!blockstate.removedByPlayer(world, pos, player, canHarvest, world.getFluidState(pos)))
return true;
BlockPos posUp = pos.up();
BlockState stateUp = world.getBlockState(posUp);
if (blockstate.getBlock() instanceof DoublePlantBlock
&& blockstate.get(DoublePlantBlock.HALF) == DoubleBlockHalf.LOWER
&& stateUp.getBlock() == blockstate.getBlock()
&& stateUp.get(DoublePlantBlock.HALF) == DoubleBlockHalf.UPPER
) {
// hack to prevent DoublePlantBlock from dropping a duplicate item
world.setBlockState(pos, Blocks.AIR.getDefaultState(), 35);
world.setBlockState(posUp, Blocks.AIR.getDefaultState(), 35);
} else {
if (!blockstate.removedByPlayer(world, pos, player, canHarvest, world.getFluidState(pos)))
return true;
}
blockstate.getBlock() blockstate.getBlock()
.onPlayerDestroy(world, pos, blockstate); .onPlayerDestroy(world, pos, blockstate);

View File

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

View File

@ -89,8 +89,7 @@ public class AirCurrent {
protected void tickAffectedEntities(World world, Direction facing) { protected void tickAffectedEntities(World world, Direction facing) {
for (Iterator<Entity> iterator = caughtEntities.iterator(); iterator.hasNext();) { for (Iterator<Entity> iterator = caughtEntities.iterator(); iterator.hasNext();) {
Entity entity = iterator.next(); Entity entity = iterator.next();
if (!entity.isAlive() || !entity.getBoundingBox() if (!entity.isAlive() || !entity.getBoundingBox().intersects(bounds) || isPlayerCreativeFlying(entity)) {
.intersects(bounds)) {
iterator.remove(); iterator.remove();
continue; continue;
} }
@ -389,4 +388,12 @@ public class AirCurrent {
isClientPlayerInAirCurrent = false; isClientPlayerInAirCurrent = false;
} }
public static boolean isPlayerCreativeFlying(Entity entity) {
if (entity instanceof PlayerEntity) {
PlayerEntity player = (PlayerEntity) entity;
return player.isCreative() && player.abilities.isFlying;
}
return false;
}
} }

View File

@ -49,7 +49,7 @@ public class NozzleTileEntity extends SmartTileEntity {
compound.putFloat("Range", range); compound.putFloat("Range", range);
compound.putBoolean("Pushing", pushing); compound.putBoolean("Pushing", pushing);
} }
@Override @Override
protected void fromTag(BlockState state, CompoundNBT compound, boolean clientPacket) { protected void fromTag(BlockState state, CompoundNBT compound, boolean clientPacket) {
super.fromTag(state, compound, clientPacket); super.fromTag(state, compound, clientPacket);
@ -95,8 +95,7 @@ public class NozzleTileEntity extends SmartTileEntity {
continue; continue;
double distance = diff.length(); double distance = diff.length();
if (distance > range || entity.isSneaking() if (distance > range || entity.isSneaking() || AirCurrent.isPlayerCreativeFlying(entity)) {
|| (entity instanceof PlayerEntity && ((PlayerEntity) entity).isCreative())) {
iterator.remove(); iterator.remove();
continue; continue;
} }
@ -153,10 +152,8 @@ public class NozzleTileEntity extends SmartTileEntity {
.subtract(center); .subtract(center);
double distance = diff.length(); double distance = diff.length();
if (distance > range || entity.isSneaking() if (distance > range || entity.isSneaking() || AirCurrent.isPlayerCreativeFlying(entity))
|| (entity instanceof PlayerEntity && ((PlayerEntity) entity).isCreative())) {
continue; continue;
}
boolean canSee = canSee(entity); boolean canSee = canSee(entity);
if (!canSee) { if (!canSee) {

View File

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

View File

@ -288,6 +288,11 @@ public abstract class LinearActuatorTileEntity extends KineticTileEntity
} }
} }
public void onLengthBroken() {
offset = 0;
sendData();
}
@Override @Override
public boolean isValid() { public boolean isValid() {
return !isRemoved(); return !isRemoved();
@ -311,4 +316,4 @@ public abstract class LinearActuatorTileEntity extends KineticTileEntity
public BlockPos getBlockPosition() { public BlockPos getBlockPosition() {
return pos; return pos;
} }
} }

View File

@ -9,6 +9,7 @@ import java.util.function.Predicate;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllShapes; import com.simibubi.create.AllShapes;
import com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.PistonState; import com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.PistonState;
import com.simibubi.create.content.contraptions.components.structureMovement.pulley.PulleyTileEntity;
import com.simibubi.create.content.contraptions.wrench.IWrenchable; import com.simibubi.create.content.contraptions.wrench.IWrenchable;
import com.simibubi.create.foundation.block.ProperDirectionalBlock; import com.simibubi.create.foundation.block.ProperDirectionalBlock;
import com.simibubi.create.foundation.utility.placement.IPlacementHelper; import com.simibubi.create.foundation.utility.placement.IPlacementHelper;
@ -29,6 +30,7 @@ import net.minecraft.item.ItemStack;
import net.minecraft.pathfinding.PathType; import net.minecraft.pathfinding.PathType;
import net.minecraft.state.StateContainer.Builder; import net.minecraft.state.StateContainer.Builder;
import net.minecraft.state.properties.BlockStateProperties; import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.ActionResultType; import net.minecraft.util.ActionResultType;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis; import net.minecraft.util.Direction.Axis;
@ -71,7 +73,7 @@ public class PistonExtensionPoleBlock extends ProperDirectionalBlock implements
public boolean isToolEffective(BlockState state, ToolType tool) { public boolean isToolEffective(BlockState state, ToolType tool) {
return tool == ToolType.AXE || tool == ToolType.PICKAXE; return tool == ToolType.AXE || tool == ToolType.PICKAXE;
} }
@Override @Override
public PushReaction getPushReaction(BlockState state) { public PushReaction getPushReaction(BlockState state) {
return PushReaction.NORMAL; return PushReaction.NORMAL;
@ -117,6 +119,13 @@ public class PistonExtensionPoleBlock extends ProperDirectionalBlock implements
.forEach(p -> worldIn.destroyBlock(p, !player.isCreative())); .forEach(p -> worldIn.destroyBlock(p, !player.isCreative()));
worldIn.setBlockState(basePos, worldIn.getBlockState(basePos) worldIn.setBlockState(basePos, worldIn.getBlockState(basePos)
.with(MechanicalPistonBlock.STATE, PistonState.RETRACTED)); .with(MechanicalPistonBlock.STATE, PistonState.RETRACTED));
TileEntity te = worldIn.getTileEntity(basePos);
if (te instanceof MechanicalPistonTileEntity) {
MechanicalPistonTileEntity baseTE = (MechanicalPistonTileEntity) te;
baseTE.offset = 0;
baseTE.onLengthBroken();
}
} }
super.onBlockHarvested(worldIn, pos, state, player); super.onBlockHarvested(worldIn, pos, state, player);
@ -168,7 +177,7 @@ public class PistonExtensionPoleBlock extends ProperDirectionalBlock implements
} }
return state; return state;
} }
@Override @Override
public boolean allowsMovement(BlockState state, IBlockReader reader, BlockPos pos, PathType type) { public boolean allowsMovement(BlockState state, IBlockReader reader, BlockPos pos, PathType type) {
return false; return false;

View File

@ -43,11 +43,11 @@ public class PulleyBlock extends HorizontalAxisKineticBlock implements ITE<Pulle
private static void onRopeBroken(World world, BlockPos pulleyPos) { private static void onRopeBroken(World world, BlockPos pulleyPos) {
TileEntity te = world.getTileEntity(pulleyPos); TileEntity te = world.getTileEntity(pulleyPos);
if (!(te instanceof PulleyTileEntity)) if (te instanceof PulleyTileEntity) {
return; PulleyTileEntity pulley = (PulleyTileEntity) te;
PulleyTileEntity pulley = (PulleyTileEntity) te; pulley.initialOffset = 0;
pulley.offset = 0; pulley.onLengthBroken();
pulley.sendData(); }
} }
@Override @Override
@ -98,7 +98,7 @@ public class PulleyBlock extends HorizontalAxisKineticBlock implements ITE<Pulle
super(properties); super(properties);
setDefaultState(super.getDefaultState().with(BlockStateProperties.WATERLOGGED, false)); setDefaultState(super.getDefaultState().with(BlockStateProperties.WATERLOGGED, false));
} }
@Override @Override
public boolean allowsMovement(BlockState state, IBlockReader reader, BlockPos pos, PathType type) { public boolean allowsMovement(BlockState state, IBlockReader reader, BlockPos pos, PathType type) {
return false; return false;

View File

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

View File

@ -78,15 +78,15 @@ public class GlassFluidPipeBlock extends AxisPipeBlock implements IWaterLoggable
return state.get(BlockStateProperties.WATERLOGGED) ? Fluids.WATER.getStillFluidState(false) return state.get(BlockStateProperties.WATERLOGGED) ? Fluids.WATER.getStillFluidState(false)
: Fluids.EMPTY.getDefaultState(); : Fluids.EMPTY.getDefaultState();
} }
@Override @Override
public ItemRequirement getRequiredItems(BlockState state) { public ItemRequirement getRequiredItems(BlockState state, TileEntity te) {
return ItemRequirement.of(AllBlocks.FLUID_PIPE.getDefaultState()); return ItemRequirement.of(AllBlocks.FLUID_PIPE.getDefaultState(), te);
} }
@Override @Override
public boolean allowsMovement(BlockState state, IBlockReader reader, BlockPos pos, PathType type) { public boolean allowsMovement(BlockState state, IBlockReader reader, BlockPos pos, PathType type) {
return false; return false;
} }
} }

View File

@ -126,7 +126,7 @@ public class BeltBlock extends HorizontalKineticBlock implements ITE<BeltTileEnt
/* /*
* FIXME * FIXME
* *
* @Override * @Override
* public Material getMaterial(BlockState state) { * public Material getMaterial(BlockState state) {
* return state.get(CASING) ? Material.WOOD : Material.WOOL; * return state.get(CASING) ? Material.WOOD : Material.WOOL;
@ -587,7 +587,7 @@ public class BeltBlock extends HorizontalKineticBlock implements ITE<BeltTileEnt
} }
@Override @Override
public ItemRequirement getRequiredItems(BlockState state) { public ItemRequirement getRequiredItems(BlockState state, TileEntity te) {
List<ItemStack> required = new ArrayList<>(); List<ItemStack> required = new ArrayList<>();
if (state.get(PART) != BeltPart.MIDDLE) if (state.get(PART) != BeltPart.MIDDLE)
required.add(AllBlocks.SHAFT.asStack()); required.add(AllBlocks.SHAFT.asStack());

View File

@ -4,6 +4,7 @@ import java.util.Optional;
import java.util.function.Function; import java.util.function.Function;
import java.util.function.Predicate; 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.AllTriggers;
import com.simibubi.create.foundation.advancement.ITriggerable; import com.simibubi.create.foundation.advancement.ITriggerable;
import com.simibubi.create.foundation.tileEntity.SmartTileEntity; import com.simibubi.create.foundation.tileEntity.SmartTileEntity;
@ -38,7 +39,7 @@ public class BracketedTileEntityBehaviour extends TileEntityBehaviour {
this.pred = pred; this.pred = pred;
bracket = Optional.empty(); bracket = Optional.empty();
} }
public BracketedTileEntityBehaviour withTrigger(Function<BlockState, ITriggerable> trigger) { public BracketedTileEntityBehaviour withTrigger(Function<BlockState, ITriggerable> trigger) {
this.trigger = trigger; this.trigger = trigger;
return this; return this;
@ -54,7 +55,7 @@ public class BracketedTileEntityBehaviour extends TileEntityBehaviour {
reRender = true; reRender = true;
tileEntity.notifyUpdate(); tileEntity.notifyUpdate();
} }
public void triggerAdvancements(World world, PlayerEntity player, BlockState state) { public void triggerAdvancements(World world, PlayerEntity player, BlockState state) {
if (trigger == null) if (trigger == null)
return; return;
@ -81,6 +82,14 @@ public class BracketedTileEntityBehaviour extends TileEntityBehaviour {
return bracket.orElse(Blocks.AIR.getDefaultState()); return bracket.orElse(Blocks.AIR.getDefaultState());
} }
@Override
public ItemRequirement getRequiredItems() {
return ItemRequirement.of(getBracket(), null);
}
@Override
public boolean isSafeNBT() { return true; }
@Override @Override
public void write(CompoundNBT nbt, boolean clientPacket) { public void write(CompoundNBT nbt, boolean clientPacket) {
bracket.ifPresent(p -> nbt.put("Bracket", NBTUtil.writeBlockState(p))); bracket.ifPresent(p -> nbt.put("Bracket", NBTUtil.writeBlockState(p)));

View File

@ -22,11 +22,11 @@ public class EncasedShaftBlock extends AbstractEncasedShaftBlock implements ISpe
public static EncasedShaftBlock andesite(Properties properties) { public static EncasedShaftBlock andesite(Properties properties) {
return new EncasedShaftBlock(properties, AllBlocks.ANDESITE_CASING); return new EncasedShaftBlock(properties, AllBlocks.ANDESITE_CASING);
} }
public static EncasedShaftBlock brass(Properties properties) { public static EncasedShaftBlock brass(Properties properties) {
return new EncasedShaftBlock(properties, AllBlocks.BRASS_CASING); return new EncasedShaftBlock(properties, AllBlocks.BRASS_CASING);
} }
protected EncasedShaftBlock(Properties properties, BlockEntry<CasingBlock> casing) { protected EncasedShaftBlock(Properties properties, BlockEntry<CasingBlock> casing) {
super(properties); super(properties);
this.casing = casing; this.casing = casing;
@ -36,7 +36,7 @@ public class EncasedShaftBlock extends AbstractEncasedShaftBlock implements ISpe
public TileEntity createTileEntity(BlockState state, IBlockReader world) { public TileEntity createTileEntity(BlockState state, IBlockReader world) {
return AllTileEntities.ENCASED_SHAFT.create(); return AllTileEntities.ENCASED_SHAFT.create();
} }
public BlockEntry<CasingBlock> getCasing() { public BlockEntry<CasingBlock> getCasing() {
return casing; return casing;
} }
@ -49,10 +49,10 @@ public class EncasedShaftBlock extends AbstractEncasedShaftBlock implements ISpe
KineticTileEntity.switchToBlockState(context.getWorld(), context.getPos(), AllBlocks.SHAFT.getDefaultState().with(AXIS, state.get(AXIS))); KineticTileEntity.switchToBlockState(context.getWorld(), context.getPos(), AllBlocks.SHAFT.getDefaultState().with(AXIS, state.get(AXIS)));
return ActionResultType.SUCCESS; return ActionResultType.SUCCESS;
} }
@Override @Override
public ItemRequirement getRequiredItems(BlockState state) { public ItemRequirement getRequiredItems(BlockState state, TileEntity te) {
return ItemRequirement.of(AllBlocks.SHAFT.getDefaultState()); 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.item.ItemUseContext;
import net.minecraft.state.EnumProperty; import net.minecraft.state.EnumProperty;
import net.minecraft.state.StateContainer.Builder; import net.minecraft.state.StateContainer.Builder;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.ActionResultType; import net.minecraft.util.ActionResultType;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
import net.minecraft.util.IStringSerializable; import net.minecraft.util.IStringSerializable;
@ -192,8 +193,8 @@ public class BeltFunnelBlock extends AbstractHorizontalFunnelBlock implements IS
} }
@Override @Override
public ItemRequirement getRequiredItems(BlockState state) { public ItemRequirement getRequiredItems(BlockState state, TileEntity te) {
return ItemRequirement.of(parent.getDefaultState()); return ItemRequirement.of(parent.getDefaultState(), te);
} }
} }

View File

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

View File

@ -3,6 +3,10 @@ package com.simibubi.create.content.schematics;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; 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.Block;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
@ -24,6 +28,7 @@ import net.minecraft.item.ItemStack;
import net.minecraft.item.Items; import net.minecraft.item.Items;
import net.minecraft.state.properties.BlockStateProperties; import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.state.properties.SlabType; import net.minecraft.state.properties.SlabType;
import net.minecraft.tileentity.TileEntity;
public class ItemRequirement { public class ItemRequirement {
@ -31,8 +36,17 @@ public class ItemRequirement {
CONSUME, DAMAGE CONSUME, DAMAGE
} }
ItemUseType usage; public static class StackRequirement {
List<ItemStack> requiredItems; 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 INVALID = new ItemRequirement();
public static ItemRequirement NONE = new ItemRequirement(); public static ItemRequirement NONE = new ItemRequirement();
@ -40,21 +54,43 @@ public class ItemRequirement {
private ItemRequirement() { private ItemRequirement() {
} }
public ItemRequirement(ItemUseType usage, Item item) { public ItemRequirement(List<StackRequirement> requiredItems) {
this(usage, Arrays.asList(new ItemStack(item)));
}
public ItemRequirement(ItemUseType usage, List<ItemStack> requiredItems) {
this.usage = usage;
this.requiredItems = 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(); 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) if (block == Blocks.AIR)
return NONE; return NONE;
if (block instanceof ISpecialBlockItemRequirement)
return ((ISpecialBlockItemRequirement) block).getRequiredItems(state);
Item item = BlockItem.BLOCK_TO_ITEM.getOrDefault(state.getBlock(), Items.AIR); Item item = BlockItem.BLOCK_TO_ITEM.getOrDefault(state.getBlock(), Items.AIR);
@ -125,16 +161,25 @@ public class ItemRequirement {
return INVALID == this; return INVALID == this;
} }
public List<ItemStack> getRequiredItems() { public List<StackRequirement> getRequiredItems() {
return requiredItems; return requiredItems;
} }
public ItemUseType getUsage() {
return usage;
}
public static boolean validate(ItemStack required, ItemStack present) { public static boolean validate(ItemStack required, ItemStack present) {
return required.isEmpty() || required.getItem() == present.getItem(); 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()) if (requirement.isInvalid())
return; return;
for (ItemStack stack : requirement.requiredItems) { for (ItemRequirement.StackRequirement stack : requirement.requiredItems) {
if (requirement.getUsage() == ItemUseType.DAMAGE) if (stack.usage == ItemUseType.DAMAGE)
putOrIncrement(damageRequired, stack); putOrIncrement(damageRequired, stack.item);
if (requirement.getUsage() == ItemUseType.CONSUME) if (stack.usage == ItemUseType.CONSUME)
putOrIncrement(required, stack); putOrIncrement(required, stack.item);
} }
} }

View File

@ -11,6 +11,7 @@ import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllItems; import com.simibubi.create.AllItems;
import com.simibubi.create.AllSoundEvents; import com.simibubi.create.AllSoundEvents;
import com.simibubi.create.AllTags.AllBlockTags; import com.simibubi.create.AllTags.AllBlockTags;
import com.simibubi.create.content.contraptions.components.structureMovement.BlockMovementTraits;
import com.simibubi.create.content.contraptions.relays.belt.BeltBlock; import com.simibubi.create.content.contraptions.relays.belt.BeltBlock;
import com.simibubi.create.content.contraptions.relays.belt.BeltPart; import com.simibubi.create.content.contraptions.relays.belt.BeltPart;
import com.simibubi.create.content.contraptions.relays.belt.BeltSlope; import com.simibubi.create.content.contraptions.relays.belt.BeltSlope;
@ -432,6 +433,7 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
boolean shouldSkip = false; boolean shouldSkip = false;
BlockState blockState = Blocks.AIR.getDefaultState(); BlockState blockState = Blocks.AIR.getDefaultState();
TileEntity tileEntity = null;
ItemRequirement requirement; ItemRequirement requirement;
if (entityMode) { if (entityMode) {
@ -441,8 +443,9 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
} else { } else {
blockState = BlockHelper.setZeroAge(blockReader.getBlockState(target)); blockState = BlockHelper.setZeroAge(blockReader.getBlockState(target));
requirement = ItemRequirement.of(blockState); tileEntity = blockReader.getTileEntity(target);
shouldSkip = !shouldPlace(target, blockState); requirement = ItemRequirement.of(blockState, tileEntity);
shouldSkip = !shouldPlace(target, blockState, tileEntity);
} }
if (shouldSkip || requirement.isInvalid()) { if (shouldSkip || requirement.isInvalid()) {
@ -452,10 +455,10 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
} }
// Find item // Find item
List<ItemStack> requiredItems = requirement.getRequiredItems(); List<ItemRequirement.StackRequirement> requiredItems = requirement.getRequiredItems();
if (!requirement.isEmpty()) { if (!requirement.isEmpty()) {
for (ItemStack required : requiredItems) { for (ItemRequirement.StackRequirement required : requiredItems) {
if (!grabItemsFromAttachedInventories(required, requirement.getUsage(), true)) { if (!grabItemsFromAttachedInventories(required.item, required.usage, true)) {
if (skipMissing) { if (skipMissing) {
statusMsg = "skipping"; statusMsg = "skipping";
blockSkipped = true; blockSkipped = true;
@ -466,15 +469,15 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
return; return;
} }
missingItem = required; missingItem = required.item;
state = State.PAUSED; state = State.PAUSED;
statusMsg = "missingBlock"; statusMsg = "missingBlock";
return; return;
} }
} }
for (ItemStack required : requiredItems) for (ItemRequirement.StackRequirement required : requiredItems)
grabItemsFromAttachedInventories(required, requirement.getUsage(), false); grabItemsFromAttachedInventories(required.item, required.usage, false);
} }
// Success // Success
@ -484,7 +487,7 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
else else
statusMsg = "clearing"; 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) if (entityMode)
launchEntity(target, icon, blockReader.getEntities() launchEntity(target, icon, blockReader.getEntities()
.collect(Collectors.toList()) .collect(Collectors.toList())
@ -728,8 +731,7 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
} }
public static boolean shouldDeferBlock(BlockState state) { public static boolean shouldDeferBlock(BlockState state) {
Block block = state.getBlock(); return state.getBlock().is(AllBlocks.GANTRY_CARRIAGE.get()) || BlockMovementTraits.isBrittle(state);
return block instanceof AbstractRailBlock || block.is(AllBlocks.GANTRY_CARRIAGE.get());
} }
public void finishedPrinting() { public void finishedPrinting() {
@ -759,7 +761,7 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
deferredBlocks.clear(); deferredBlocks.clear();
} }
protected boolean shouldPlace(BlockPos pos, BlockState state) { protected boolean shouldPlace(BlockPos pos, BlockState state, TileEntity te) {
if (world == null) if (world == null)
return false; return false;
BlockState toReplace = world.getBlockState(pos); BlockState toReplace = world.getBlockState(pos);
@ -790,7 +792,7 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
&& (toReplace.hasTileEntity() || (toReplaceOther != null && toReplaceOther.hasTileEntity()))) && (toReplace.hasTileEntity() || (toReplaceOther != null && toReplaceOther.hasTileEntity())))
return false; return false;
if (shouldIgnoreBlockState(state)) if (shouldIgnoreBlockState(state, te))
return false; return false;
if (replaceMode == 3) if (replaceMode == 3)
@ -809,12 +811,12 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
return false; return false;
} }
protected boolean shouldIgnoreBlockState(BlockState state) { protected boolean shouldIgnoreBlockState(BlockState state, TileEntity te) {
// Block doesnt have a mapping (Water, lava, etc) // Block doesnt have a mapping (Water, lava, etc)
if (state.getBlock() == Blocks.STRUCTURE_VOID) if (state.getBlock() == Blocks.STRUCTURE_VOID)
return true; return true;
ItemRequirement requirement = ItemRequirement.of(state); ItemRequirement requirement = ItemRequirement.of(state, te);
if (requirement.isEmpty()) if (requirement.isEmpty())
return false; return false;
if (requirement.isInvalid()) if (requirement.isInvalid())
@ -951,15 +953,17 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
if (schematicLoaded) { if (schematicLoaded) {
blocksToPlace = blocksPlaced; blocksToPlace = blocksPlaced;
for (BlockPos pos : blockReader.getAllPositions()) { 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)) { if (!getWorld().isAreaLoaded(pos.add(schematicAnchor), 0)) {
checklist.warnBlockNotLoaded(); checklist.warnBlockNotLoaded();
continue; continue;
} }
if (!shouldPlace(pos.add(schematicAnchor), required)) if (!shouldPlace(pos.add(schematicAnchor), required, requiredTE))
continue; continue;
ItemRequirement requirement = ItemRequirement.of(required); ItemRequirement requirement = ItemRequirement.of(required, blockReader.getTileEntity(relPos));
if (requirement.isEmpty()) if (requirement.isEmpty())
continue; continue;
if (requirement.isInvalid()) if (requirement.isInvalid())

View File

@ -6,6 +6,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.function.Consumer; 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.tileEntity.behaviour.BehaviourType;
import com.simibubi.create.foundation.utility.IPartialSafeNBT; 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.block.BlockState;
import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.CompoundNBT;
import net.minecraft.tileentity.ITickableTileEntity; import net.minecraft.tileentity.ITickableTileEntity;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.tileentity.TileEntityType; import net.minecraft.tileentity.TileEntityType;
import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.fluids.capability.CapabilityFluidHandler; 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)); behaviourList.forEach(tb -> tb.write(compound, clientPacket));
} }
@Override
public void writeSafe(CompoundNBT compound, boolean clientPacket) { public void writeSafe(CompoundNBT compound, boolean clientPacket) {
super.write(compound); super.write(compound);
behaviourList.forEach(tb -> { 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 @Override
public void remove() { public void remove() {
forEachBehaviour(TileEntityBehaviour::remove); forEachBehaviour(TileEntityBehaviour::remove);

View File

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

View File

@ -4,6 +4,7 @@ import java.util.function.Consumer;
import java.util.function.Supplier; import java.util.function.Supplier;
import com.simibubi.create.content.logistics.item.filter.FilterItem; 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.networking.AllPackets;
import com.simibubi.create.foundation.tileEntity.SmartTileEntity; import com.simibubi.create.foundation.tileEntity.SmartTileEntity;
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; 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.block.BlockState;
import net.minecraft.entity.item.ItemEntity; import net.minecraft.entity.item.ItemEntity;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.CompoundNBT;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
@ -168,6 +170,15 @@ public class FilteringBehaviour extends TileEntityBehaviour {
super.destroy(); 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) { public ItemStack getFilter(Direction side) {
return getFilter(); return getFilter();
} }

View File

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