diff --git a/src/main/java/com/simibubi/create/AllBlocks.java b/src/main/java/com/simibubi/create/AllBlocks.java index b4e8735af..aaa71a97b 100644 --- a/src/main/java/com/simibubi/create/AllBlocks.java +++ b/src/main/java/com/simibubi/create/AllBlocks.java @@ -29,6 +29,7 @@ import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock; import com.simibubi.create.modules.economy.ShopShelfBlock; import com.simibubi.create.modules.gardens.CocoaLogBlock; import com.simibubi.create.modules.logistics.block.BeltFunnelBlock; +import com.simibubi.create.modules.logistics.block.EntityDetectorBlock; import com.simibubi.create.modules.logistics.block.ExtractorBlock; import com.simibubi.create.modules.logistics.block.FlexcrateBlock; import com.simibubi.create.modules.logistics.block.LinkedExtractorBlock; @@ -107,6 +108,7 @@ public enum AllBlocks { EXTRACTOR(new ExtractorBlock()), LINKED_EXTRACTOR(new LinkedExtractorBlock()), BELT_FUNNEL(new BeltFunnelBlock()), + ENTITY_DETECTOR(new EntityDetectorBlock()), // Symmetry SYMMETRY_PLANE(new PlaneSymmetryBlock()), diff --git a/src/main/java/com/simibubi/create/AllItems.java b/src/main/java/com/simibubi/create/AllItems.java index c97e7dd1c..bccf22f4d 100644 --- a/src/main/java/com/simibubi/create/AllItems.java +++ b/src/main/java/com/simibubi/create/AllItems.java @@ -39,16 +39,18 @@ public enum AllItems { PLACEMENT_HANDGUN( new BuilderGunItem(new Properties().setTEISR(() -> () -> renderUsing(AllItemRenderers.BUILDER_GUN)))), - ANDESITE_ALLOY_CUBE(new Item(standardProperties())), - BLAZE_BRASS_CUBE(new Item(standardProperties())), + ANDESITE_ALLOY_CUBE(new Item(standardProperties())), BLAZE_BRASS_CUBE(new Item(standardProperties())), CHORUS_CHROME_CUBE(new Item(standardProperties().rarity(Rarity.UNCOMMON))), CHROMATIC_COMPOUND_CUBE(new ChromaticCompoundCubeItem(standardProperties().rarity(Rarity.UNCOMMON))), SHADOW_STEEL_CUBE(new Item(standardProperties().rarity(Rarity.UNCOMMON))), - - BLAZING_PICKAXE(new Item(standardProperties())), - BLAZING_SHOVEL(new Item(standardProperties())), - BLAZING_AXE(new Item(standardProperties())), - BLAZING_SWORD(new Item(standardProperties())), + ROSE_QUARTZ(new Item(standardProperties())), REFINED_ROSE_QUARTZ(new Item(standardProperties())), + REFINED_RADIANCE_CUBE(new Item(standardProperties())), + + BLAZING_PICKAXE(new Item(standardProperties())), BLAZING_SHOVEL(new Item(standardProperties())), + BLAZING_AXE(new Item(standardProperties())), BLAZING_SWORD(new Item(standardProperties())), + + ROSE_QUARTZ_PICKAXE(new Item(standardProperties())), ROSE_QUARTZ_SHOVEL(new Item(standardProperties())), + ROSE_QUARTZ_AXE(new Item(standardProperties())), ROSE_QUARTZ_SWORD(new Item(standardProperties())), TREE_FERTILIZER(new TreeFertilizerItem(standardProperties())), diff --git a/src/main/java/com/simibubi/create/AllTileEntities.java b/src/main/java/com/simibubi/create/AllTileEntities.java index c7c93feae..738c00ee1 100644 --- a/src/main/java/com/simibubi/create/AllTileEntities.java +++ b/src/main/java/com/simibubi/create/AllTileEntities.java @@ -26,9 +26,13 @@ import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntity; import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntityRenderer; import com.simibubi.create.modules.economy.ShopShelfTileEntity; import com.simibubi.create.modules.logistics.block.BeltFunnelTileEntity; +import com.simibubi.create.modules.logistics.block.EntityDetectorTileEntity; +import com.simibubi.create.modules.logistics.block.EntityDetectorTileEntityRenderer; import com.simibubi.create.modules.logistics.block.ExtractorTileEntity; +import com.simibubi.create.modules.logistics.block.ExtractorTileEntityRenderer; import com.simibubi.create.modules.logistics.block.FlexcrateTileEntity; import com.simibubi.create.modules.logistics.block.LinkedExtractorTileEntity; +import com.simibubi.create.modules.logistics.block.LinkedExtractorTileEntityRenderer; import com.simibubi.create.modules.logistics.block.LinkedTileEntityRenderer; import com.simibubi.create.modules.logistics.block.RedstoneBridgeTileEntity; import com.simibubi.create.modules.logistics.block.StockswitchTileEntity; @@ -61,10 +65,8 @@ public enum AllTileEntities { MOTOR(MotorTileEntity::new, AllBlocks.MOTOR), GEARBOX(GearboxTileEntity::new, AllBlocks.GEARBOX), TURNTABLE(TurntableTileEntity::new, AllBlocks.TURNTABLE), ENCASED_SHAFT(EncasedShaftTileEntity::new, AllBlocks.ENCASED_SHAFT, AllBlocks.ENCASED_BELT), - ENCASED_FAN(EncasedFanTileEntity::new, AllBlocks.ENCASED_FAN), - CLUTCH(ClutchTileEntity::new, AllBlocks.CLUTCH), - GEARSHIFT(GearshiftTileEntity::new, AllBlocks.GEARSHIFT), - BELT(BeltTileEntity::new, AllBlocks.BELT), + ENCASED_FAN(EncasedFanTileEntity::new, AllBlocks.ENCASED_FAN), CLUTCH(ClutchTileEntity::new, AllBlocks.CLUTCH), + GEARSHIFT(GearshiftTileEntity::new, AllBlocks.GEARSHIFT), BELT(BeltTileEntity::new, AllBlocks.BELT), MECHANICAL_PISTON(MechanicalPistonTileEntity::new, AllBlocks.MECHANICAL_PISTON, AllBlocks.STICKY_MECHANICAL_PISTON), DRILL(DrillTileEntity::new, AllBlocks.DRILL), CRUSHING_WHEEL(CrushingWheelTileEntity::new, AllBlocks.CRUSHING_WHEEL), @@ -74,10 +76,10 @@ public enum AllTileEntities { // Logistics REDSTONE_BRIDGE(RedstoneBridgeTileEntity::new, AllBlocks.REDSTONE_BRIDGE), STOCKSWITCH(StockswitchTileEntity::new, AllBlocks.STOCKSWITCH), - FLEXCRATE(FlexcrateTileEntity::new, AllBlocks.FLEXCRATE), - EXTRACTOR(ExtractorTileEntity::new, AllBlocks.EXTRACTOR), + FLEXCRATE(FlexcrateTileEntity::new, AllBlocks.FLEXCRATE), EXTRACTOR(ExtractorTileEntity::new, AllBlocks.EXTRACTOR), LINKED_EXTRACTOR(LinkedExtractorTileEntity::new, AllBlocks.LINKED_EXTRACTOR), BELT_FUNNEL(BeltFunnelTileEntity::new, AllBlocks.BELT_FUNNEL), + ENTITY_DETECTOR(EntityDetectorTileEntity::new, AllBlocks.ENTITY_DETECTOR), // Economy SHOP_SHELF(ShopShelfTileEntity::new, AllBlocks.SHOP_SHELF), @@ -125,7 +127,9 @@ public enum AllTileEntities { bind(CrushingWheelTileEntity.class, new KineticTileEntityRenderer()); bind(WaterWheelTileEntity.class, new KineticTileEntityRenderer()); bind(RedstoneBridgeTileEntity.class, new LinkedTileEntityRenderer()); - bind(LinkedExtractorTileEntity.class, new LinkedTileEntityRenderer()); + bind(LinkedExtractorTileEntity.class, new LinkedExtractorTileEntityRenderer()); + bind(ExtractorTileEntity.class, new ExtractorTileEntityRenderer()); + bind(EntityDetectorTileEntity.class, new EntityDetectorTileEntityRenderer()); } @OnlyIn(Dist.CLIENT) diff --git a/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/AllBeltAttachments.java b/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/AllBeltAttachments.java index 969705aca..3ff066bfe 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/AllBeltAttachments.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/AllBeltAttachments.java @@ -15,10 +15,12 @@ import net.minecraft.nbt.ListNBT; import net.minecraft.nbt.NBTUtil; import net.minecraft.util.math.BlockPos; import net.minecraft.world.IWorld; +import net.minecraft.world.World; public enum AllBeltAttachments { BELT_FUNNEL(AllBlocks.BELT_FUNNEL), + BELT_OBSERVER(AllBlocks.ENTITY_DETECTOR), ; @@ -29,7 +31,7 @@ public enum AllBeltAttachments { } public interface IBeltAttachment { - public Optional getValidAttachmentFor(BeltTileEntity te); + public List getPotentialAttachmentLocations(BeltTileEntity te); public Optional getValidBeltPositionFor(IWorld world, BlockPos pos, BlockState state); @@ -80,10 +82,19 @@ public enum AllBeltAttachments { public void findAttachments(BeltTileEntity belt) { for (AllBeltAttachments ba : AllBeltAttachments.values()) { - Optional validAttachmentFor = ba.attachment.getValidAttachmentFor(belt); - if (validAttachmentFor.isPresent()) { - BlockPos pos = validAttachmentFor.get(); - addAttachment(belt.getWorld(), pos); + List attachmentPositions = ba.attachment.getPotentialAttachmentLocations(belt); + World world = belt.getWorld(); + for (BlockPos potentialPos : attachmentPositions) { + if (!world.isBlockPresent(potentialPos)) + continue; + BlockState state = world.getBlockState(potentialPos); + if (!(state.getBlock() instanceof IBeltAttachment)) + continue; + Optional validBeltPos = ((IBeltAttachment) state.getBlock()).getValidBeltPositionFor(world, potentialPos, state); + if (!validBeltPos.isPresent()) + continue; + if (validBeltPos.get().equals(belt.getPos())) + addAttachment(world, potentialPos); } } } diff --git a/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltTileEntity.java b/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltTileEntity.java index 48cb63294..1eea21399 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltTileEntity.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/relays/belt/BeltTileEntity.java @@ -134,13 +134,13 @@ public class BeltTileEntity extends KineticTileEntity implements ITickableTileEn passengers.forEach((entity, info) -> { if (!canTransport(entity)) toRemove.add(entity); - if (info.ticksSinceLastCollision > 0) { + if (info.ticksSinceLastCollision > 1) { toRemove.add(entity); } info.tick(); }); toRemove.forEach(e -> { - if (e instanceof ItemEntity) + if (e instanceof ItemEntity && ((ItemEntity) e).getAge() < 0) ((ItemEntity) e).setAgeToCreativeDespawnTime(); passengers.remove(e); }); @@ -188,8 +188,10 @@ public class BeltTileEntity extends KineticTileEntity implements ITickableTileEn BeltTileEntity belt = (BeltTileEntity) te; for (BeltAttachmentState state : belt.attachmentTracker.attachments) { - if (state.attachment.handleEntity(belt, entityIn, state)) + if (state.attachment.handleEntity(belt, entityIn, state)) { + info.ticksSinceLastCollision--; return; + } } final Direction beltFacing = blockState.get(BlockStateProperties.HORIZONTAL_FACING); @@ -242,6 +244,7 @@ public class BeltTileEntity extends KineticTileEntity implements ITickableTileEn .grow(-Math.abs(checkDistance.x), -Math.abs(checkDistance.y), -Math.abs(checkDistance.z))) .isEmpty()) { entityIn.setMotion(0, 0, 0); + info.ticksSinceLastCollision--; return; } } diff --git a/src/main/java/com/simibubi/create/modules/logistics/block/BeltFunnelBlock.java b/src/main/java/com/simibubi/create/modules/logistics/block/BeltFunnelBlock.java index 320660dfc..004383143 100644 --- a/src/main/java/com/simibubi/create/modules/logistics/block/BeltFunnelBlock.java +++ b/src/main/java/com/simibubi/create/modules/logistics/block/BeltFunnelBlock.java @@ -1,5 +1,7 @@ package com.simibubi.create.modules.logistics.block; +import java.util.Arrays; +import java.util.List; import java.util.Optional; import com.simibubi.create.AllBlocks; @@ -7,6 +9,8 @@ import com.simibubi.create.foundation.block.IWithTileEntity; import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.modules.contraptions.relays.belt.AllBeltAttachments.BeltAttachmentState; import com.simibubi.create.modules.contraptions.relays.belt.AllBeltAttachments.IBeltAttachment; +import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock; +import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Slope; import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntity; import net.minecraft.block.Block; @@ -113,13 +117,8 @@ public class BeltFunnelBlock extends HorizontalBlock implements IBeltAttachment, } @Override - public Optional getValidAttachmentFor(BeltTileEntity te) { - BlockPos validPos = te.getPos().up(); - BlockState blockState = te.getWorld().getBlockState(validPos); - if (blockState.getBlock() != this - || blockState.get(HORIZONTAL_FACING).getAxis() != te.getBlockState().get(HORIZONTAL_FACING).getAxis()) - return Optional.empty(); - return Optional.of(validPos); + public List getPotentialAttachmentLocations(BeltTileEntity te) { + return Arrays.asList(te.getPos().up()); } @Override @@ -136,7 +135,8 @@ public class BeltFunnelBlock extends HorizontalBlock implements IBeltAttachment, public boolean handleEntity(BeltTileEntity te, Entity entity, BeltAttachmentState state) { if (!(entity instanceof ItemEntity)) return false; - if (entity.getPositionVec().distanceTo(VecHelper.getCenterOf(te.getPos())) > .4f) + boolean slope = te.getBlockState().get(BeltBlock.SLOPE) != Slope.HORIZONTAL; + if (entity.getPositionVec().distanceTo(VecHelper.getCenterOf(te.getPos())) > (slope ? .6f : .4f)) return false; entity.setMotion(Vec3d.ZERO); diff --git a/src/main/java/com/simibubi/create/modules/logistics/block/EntityDetectorBlock.java b/src/main/java/com/simibubi/create/modules/logistics/block/EntityDetectorBlock.java new file mode 100644 index 000000000..5aad21ed4 --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/logistics/block/EntityDetectorBlock.java @@ -0,0 +1,241 @@ +package com.simibubi.create.modules.logistics.block; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Optional; +import java.util.Random; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.foundation.block.IWithTileEntity; +import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.modules.contraptions.relays.belt.AllBeltAttachments.BeltAttachmentState; +import com.simibubi.create.modules.contraptions.relays.belt.AllBeltAttachments.IBeltAttachment; +import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock; +import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Part; +import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Slope; +import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntity; + +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.block.HorizontalBlock; +import net.minecraft.entity.Entity; +import net.minecraft.entity.item.ItemEntity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.BlockItemUseContext; +import net.minecraft.item.ItemStack; +import net.minecraft.state.BooleanProperty; +import net.minecraft.state.StateContainer.Builder; +import net.minecraft.state.properties.BlockStateProperties; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.Direction; +import net.minecraft.util.Hand; +import net.minecraft.util.Direction.Axis; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.BlockRayTraceResult; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.IBlockReader; +import net.minecraft.world.IWorld; +import net.minecraft.world.World; + +public class EntityDetectorBlock extends HorizontalBlock + implements IWithTileEntity, IBeltAttachment, IBlockWithFilter { + + public static BooleanProperty POWERED = BlockStateProperties.POWERED; + public static BooleanProperty BELT = BooleanProperty.create("belt"); + + private static final List itemPositions = new ArrayList<>(Direction.values().length); + + public EntityDetectorBlock() { + super(Properties.from(Blocks.ANDESITE)); + setDefaultState(getDefaultState().with(POWERED, false).with(BELT, false)); + cacheItemPositions(); + } + + @Override + public TileEntity createTileEntity(BlockState state, IBlockReader world) { + return new EntityDetectorTileEntity(); + } + + @Override + public boolean hasTileEntity(BlockState state) { + return true; + } + + @Override + public BlockState updatePostPlacement(BlockState stateIn, Direction facing, BlockState facingState, IWorld worldIn, + BlockPos currentPos, BlockPos facingPos) { + if (facing == stateIn.get(HORIZONTAL_FACING)) + stateIn = stateIn.with(BELT, shouldHaveExtension(stateIn, worldIn, currentPos)); + return stateIn; + } + + @Override + protected void fillStateContainer(Builder builder) { + builder.add(POWERED, HORIZONTAL_FACING, BELT); + super.fillStateContainer(builder); + } + + private boolean shouldHaveExtension(BlockState state, IWorld world, BlockPos pos) { + Direction direction = state.get(HORIZONTAL_FACING); + BlockState blockState = world.getBlockState(pos.offset(direction)); + + if (!AllBlocks.BELT.typeOf(blockState)) + return false; + if (blockState.get(BeltBlock.SLOPE) != Slope.HORIZONTAL) + return false; + if (blockState.get(BeltBlock.PART) != Part.MIDDLE) + return false; + if (blockState.get(BeltBlock.HORIZONTAL_FACING).getAxis() == direction.getAxis()) + return false; + + return true; + } + + @Override + public BlockState getStateForPlacement(BlockItemUseContext context) { + BlockState state = getDefaultState(); + + if (context.getFace().getAxis().isHorizontal()) { + state = state.with(HORIZONTAL_FACING, context.getFace().getOpposite()); + } else { + state = state.with(HORIZONTAL_FACING, context.getPlacementHorizontalFacing()); + } + + state = state.with(BELT, shouldHaveExtension(state, context.getWorld(), context.getPos())); + + return state; + } + + @Override + public List getPotentialAttachmentLocations(BeltTileEntity te) { + Direction side = te.getBlockState().get(BeltBlock.HORIZONTAL_FACING).rotateY(); + return Arrays.asList(te.getPos().offset(side), te.getPos().offset(side.getOpposite())); + } + + @Override + public Optional getValidBeltPositionFor(IWorld world, BlockPos pos, BlockState state) { + if (!state.get(BELT)) + return Optional.empty(); + return Optional.of(pos.offset(state.get(HORIZONTAL_FACING))); + } + + @Override + public boolean canProvidePower(BlockState state) { + return state.get(POWERED); + } + + @Override + public int getWeakPower(BlockState blockState, IBlockReader blockAccess, BlockPos pos, Direction side) { + return canProvidePower(blockState) ? 15 : 0; + } + + @Override + public boolean canConnectRedstone(BlockState state, IBlockReader world, BlockPos pos, Direction side) { + return side != state.get(HORIZONTAL_FACING).getOpposite(); + } + + @Override + public boolean onBlockActivated(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand handIn, + BlockRayTraceResult hit) { + return handleActivatedFilterSlots(state, worldIn, pos, player, handIn, hit); + } + + @Override + public void onReplaced(BlockState state, World worldIn, BlockPos pos, BlockState newState, boolean isMoving) { + if (newState.getBlock() != this || newState.with(POWERED, false) != state.with(POWERED, false)) + onAttachmentRemoved(worldIn, pos, state); + if (state.hasTileEntity() && state.getBlock() != newState.getBlock()) { + worldIn.removeTileEntity(pos); + } + } + + @Override + public void onBlockAdded(BlockState state, World worldIn, BlockPos pos, BlockState oldState, boolean isMoving) { + if (oldState.getBlock() != this || oldState.with(POWERED, false) != state.with(POWERED, false)) + onAttachmentPlaced(worldIn, pos, state); + } + + @Override + public boolean handleEntity(BeltTileEntity te, Entity entity, BeltAttachmentState state) { + + if (state.processingEntity != entity) { + state.processingEntity = entity; + state.processingDuration = 0; + withTileEntityDo(te.getWorld(), state.attachmentPos, detectorTE -> { + ItemStack filter = detectorTE.getFilter(); + if (filter.isEmpty()) + return; + if (!(entity instanceof ItemEntity) + || !ItemStack.areItemsEqual(((ItemEntity) entity).getItem(), filter)) { + state.processingDuration = -1; + return; + } + }); + } + + if (entity.getPositionVec().distanceTo(VecHelper.getCenterOf(te.getPos())) > .5f) + return false; + if (state.processingDuration == -1) { + return false; + } + + World world = te.getWorld(); + BlockState blockState = world.getBlockState(state.attachmentPos); + if (blockState.get(POWERED)) + return false; + + state.processingDuration = -1; + world.setBlockState(state.attachmentPos, blockState.with(POWERED, true)); + world.getPendingBlockTicks().scheduleTick(state.attachmentPos, this, 4); + world.notifyNeighborsOfStateChange(state.attachmentPos, this); + + return false; + } + + @Override + public void tick(BlockState state, World worldIn, BlockPos pos, Random random) { + worldIn.setBlockState(pos, state.with(POWERED, false)); + worldIn.notifyNeighborsOfStateChange(pos, this); + } + + private void cacheItemPositions() { + if (!itemPositions.isEmpty()) + return; + + Vec3d position = Vec3d.ZERO; + Vec3d shift = VecHelper.getCenterOf(BlockPos.ZERO); + float zFightOffset = 1 / 128f; + + for (int i = 0; i < 4; i++) { + Direction facing = Direction.byHorizontalIndex(i); + position = new Vec3d(8f / 16f + zFightOffset, 15f / 16f, 17.75f / 16f); + + float angle = facing.getHorizontalAngle(); + if (facing.getAxis() == Axis.X) + angle = -angle; + + position = VecHelper.rotate(position.subtract(shift), angle, Axis.Y).add(shift); + + itemPositions.add(position); + } + } + + @Override + public float getItemHitboxScale() { + return 1.76f / 16f; + } + + @Override + public Vec3d getFilterPosition(BlockState state) { + Direction facing = state.get(HORIZONTAL_FACING); + return itemPositions.get(facing.getHorizontalIndex()); + } + + @Override + public Direction getFilterFacing(BlockState state) { + return state.get(HORIZONTAL_FACING); + } + +} diff --git a/src/main/java/com/simibubi/create/modules/logistics/block/EntityDetectorTileEntity.java b/src/main/java/com/simibubi/create/modules/logistics/block/EntityDetectorTileEntity.java new file mode 100644 index 000000000..d09902dc2 --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/logistics/block/EntityDetectorTileEntity.java @@ -0,0 +1,41 @@ +package com.simibubi.create.modules.logistics.block; + +import com.simibubi.create.AllTileEntities; +import com.simibubi.create.foundation.block.SyncedTileEntity; + +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.CompoundNBT; + +public class EntityDetectorTileEntity extends SyncedTileEntity implements IHaveFilter { + + private ItemStack filter; + + public EntityDetectorTileEntity() { + super(AllTileEntities.ENTITY_DETECTOR.type); + filter = ItemStack.EMPTY; + } + + @Override + public CompoundNBT write(CompoundNBT compound) { + compound.put("Filter", filter.serializeNBT()); + return super.write(compound); + } + + @Override + public void read(CompoundNBT compound) { + filter = ItemStack.read(compound.getCompound("Filter")); + super.read(compound); + } + + @Override + public void setFilter(ItemStack stack) { + filter = stack; + sendData(); + } + + @Override + public ItemStack getFilter() { + return filter; + } + +} diff --git a/src/main/java/com/simibubi/create/modules/logistics/block/EntityDetectorTileEntityRenderer.java b/src/main/java/com/simibubi/create/modules/logistics/block/EntityDetectorTileEntityRenderer.java new file mode 100644 index 000000000..c824f1f10 --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/logistics/block/EntityDetectorTileEntityRenderer.java @@ -0,0 +1,30 @@ +package com.simibubi.create.modules.logistics.block; + +import com.mojang.blaze3d.platform.GLX; + +import net.minecraft.client.renderer.tileentity.TileEntityRenderer; +import net.minecraft.state.properties.BlockStateProperties; + +public class EntityDetectorTileEntityRenderer extends TileEntityRenderer { + + private FilteredTileEntityRenderer filterRenderer; + + public EntityDetectorTileEntityRenderer() { + filterRenderer = new FilteredTileEntityRenderer(); + } + + @Override + public void render(EntityDetectorTileEntity tileEntityIn, double x, double y, double z, float partialTicks, + int destroyStage) { + super.render(tileEntityIn, x, y, z, partialTicks, destroyStage); + + int i = tileEntityIn.getWorld().getCombinedLight(tileEntityIn.getPos().up() + .offset(tileEntityIn.getBlockState().get(BlockStateProperties.HORIZONTAL_FACING)), 0); + int j = i % 65536; + int k = i / 65536; + GLX.glMultiTexCoord2f(GLX.GL_TEXTURE1, (float) j, (float) k); + + filterRenderer.render(tileEntityIn, x, y, z, partialTicks, destroyStage); + } + +} diff --git a/src/main/java/com/simibubi/create/modules/logistics/block/ExtractorBlock.java b/src/main/java/com/simibubi/create/modules/logistics/block/ExtractorBlock.java index 7d5291ce2..47e5aa606 100644 --- a/src/main/java/com/simibubi/create/modules/logistics/block/ExtractorBlock.java +++ b/src/main/java/com/simibubi/create/modules/logistics/block/ExtractorBlock.java @@ -1,5 +1,10 @@ package com.simibubi.create.modules.logistics.block; +import java.util.ArrayList; +import java.util.List; + +import com.simibubi.create.foundation.utility.VecHelper; + import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; @@ -12,8 +17,10 @@ import net.minecraft.state.properties.BlockStateProperties; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.Direction; import net.minecraft.util.Hand; +import net.minecraft.util.Direction.Axis; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockRayTraceResult; +import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.shapes.ISelectionContext; import net.minecraft.util.math.shapes.VoxelShape; import net.minecraft.util.math.shapes.VoxelShapes; @@ -21,16 +28,18 @@ import net.minecraft.world.IBlockReader; import net.minecraft.world.IWorldReader; import net.minecraft.world.World; -public class ExtractorBlock extends HorizontalBlock { +public class ExtractorBlock extends HorizontalBlock implements IBlockWithFilter { public static BooleanProperty POWERED = BlockStateProperties.POWERED; public static final VoxelShape SHAPE_NORTH = makeCuboidShape(4, 2, -1, 12, 10, 5), SHAPE_SOUTH = makeCuboidShape(4, 2, 11, 12, 10, 17), SHAPE_WEST = makeCuboidShape(-1, 2, 4, 5, 10, 12), SHAPE_EAST = makeCuboidShape(11, 2, 4, 17, 10, 12); - + private static final List itemPositions = new ArrayList<>(Direction.values().length); + public ExtractorBlock() { super(Properties.from(Blocks.ANDESITE)); setDefaultState(getDefaultState().with(POWERED, false)); + cacheItemPositions(); } @Override @@ -52,7 +61,7 @@ public class ExtractorBlock extends HorizontalBlock { @Override public boolean onBlockActivated(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand handIn, BlockRayTraceResult hit) { - return false; + return handleActivatedFilterSlots(state, worldIn, pos, player, handIn, hit); } @Override @@ -71,6 +80,8 @@ public class ExtractorBlock extends HorizontalBlock { @Override public void onBlockAdded(BlockState state, World worldIn, BlockPos pos, BlockState oldState, boolean isMoving) { updateObservedInventory(state, worldIn, pos); + + cacheItemPositions(); } @Override @@ -125,4 +136,43 @@ public class ExtractorBlock extends HorizontalBlock { return VoxelShapes.empty(); } + private void cacheItemPositions() { +// if (!itemPositions.isEmpty()) +// return; + itemPositions.clear(); + + Vec3d position = Vec3d.ZERO; + Vec3d shift = VecHelper.getCenterOf(BlockPos.ZERO); + float zFightOffset = 1 / 128f; + + for (int i = 0; i < 4; i++) { + Direction facing = Direction.byHorizontalIndex(i); + position = new Vec3d(8f / 16f + zFightOffset, 10.5f / 16f, 2.25f / 16f); + + float angle = facing.getHorizontalAngle(); + if (facing.getAxis() == Axis.X) + angle = -angle; + + position = VecHelper.rotate(position.subtract(shift), angle, Axis.Y).add(shift); + + itemPositions.add(position); + } + } + + @Override + public float getItemHitboxScale() { + return 1.76f / 16f; + } + + @Override + public Vec3d getFilterPosition(BlockState state) { + Direction facing = state.get(HORIZONTAL_FACING).getOpposite(); + return itemPositions.get(facing.getHorizontalIndex()); + } + + @Override + public Direction getFilterFacing(BlockState state) { + return state.get(HORIZONTAL_FACING).getOpposite(); + } + } diff --git a/src/main/java/com/simibubi/create/modules/logistics/block/ExtractorTileEntity.java b/src/main/java/com/simibubi/create/modules/logistics/block/ExtractorTileEntity.java index 87fb62cb8..135ed11bc 100644 --- a/src/main/java/com/simibubi/create/modules/logistics/block/ExtractorTileEntity.java +++ b/src/main/java/com/simibubi/create/modules/logistics/block/ExtractorTileEntity.java @@ -3,15 +3,18 @@ package com.simibubi.create.modules.logistics.block; import com.simibubi.create.AllTileEntities; import com.simibubi.create.foundation.block.SyncedTileEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.CompoundNBT; import net.minecraft.state.properties.BlockStateProperties; import net.minecraft.tileentity.ITickableTileEntity; import net.minecraft.util.math.BlockPos; import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.items.IItemHandler; -public class ExtractorTileEntity extends SyncedTileEntity implements IExtractor, ITickableTileEntity { +public class ExtractorTileEntity extends SyncedTileEntity implements IExtractor, ITickableTileEntity, IHaveFilter { private State state; + private ItemStack filter; private int cooldown; private LazyOptional inventory; private boolean initialize; @@ -20,6 +23,7 @@ public class ExtractorTileEntity extends SyncedTileEntity implements IExtractor, super(AllTileEntities.EXTRACTOR.type); state = State.WAITING_FOR_INVENTORY; inventory = LazyOptional.empty(); + filter = ItemStack.EMPTY; } @Override @@ -27,6 +31,18 @@ public class ExtractorTileEntity extends SyncedTileEntity implements IExtractor, return state; } + @Override + public void read(CompoundNBT compound) { + filter = ItemStack.read(compound.getCompound("Filter")); + super.read(compound); + } + + @Override + public CompoundNBT write(CompoundNBT compound) { + compound.put("Filter", filter.serializeNBT()); + return super.write(compound); + } + @Override public void onLoad() { initialize = true; @@ -68,4 +84,15 @@ public class ExtractorTileEntity extends SyncedTileEntity implements IExtractor, this.inventory = inventory; } + @Override + public void setFilter(ItemStack stack) { + filter = stack; + sendData(); + } + + @Override + public ItemStack getFilter() { + return filter; + } + } diff --git a/src/main/java/com/simibubi/create/modules/logistics/block/ExtractorTileEntityRenderer.java b/src/main/java/com/simibubi/create/modules/logistics/block/ExtractorTileEntityRenderer.java new file mode 100644 index 000000000..3146efe77 --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/logistics/block/ExtractorTileEntityRenderer.java @@ -0,0 +1,20 @@ +package com.simibubi.create.modules.logistics.block; + +import net.minecraft.client.renderer.tileentity.TileEntityRenderer; + +public class ExtractorTileEntityRenderer extends TileEntityRenderer { + + FilteredTileEntityRenderer filterRenderer; + + public ExtractorTileEntityRenderer() { + filterRenderer = new FilteredTileEntityRenderer(); + } + + @Override + public void render(ExtractorTileEntity tileEntityIn, double x, double y, double z, float partialTicks, + int destroyStage) { + super.render(tileEntityIn, x, y, z, partialTicks, destroyStage); + filterRenderer.render(tileEntityIn, x, y, z, partialTicks, destroyStage); + } + +} diff --git a/src/main/java/com/simibubi/create/modules/logistics/block/FilteredTileEntityRenderer.java b/src/main/java/com/simibubi/create/modules/logistics/block/FilteredTileEntityRenderer.java new file mode 100644 index 000000000..15c31f7b7 --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/logistics/block/FilteredTileEntityRenderer.java @@ -0,0 +1,74 @@ +package com.simibubi.create.modules.logistics.block; + +import com.mojang.blaze3d.platform.GlStateManager; +import com.simibubi.create.foundation.utility.TessellatorHelper; + +import net.minecraft.block.BlockState; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.ItemRenderer; +import net.minecraft.client.renderer.model.IBakedModel; +import net.minecraft.client.renderer.model.ItemCameraTransforms.TransformType; +import net.minecraft.item.ItemStack; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.Direction; +import net.minecraft.util.Direction.Axis; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; + +@SuppressWarnings("deprecation") +public class FilteredTileEntityRenderer { + + public void render(T tileEntityIn, double x, double y, double z, + float partialTicks, int destroyStage) { + BlockState state = tileEntityIn.getBlockState(); + IBlockWithFilter block = (IBlockWithFilter) state.getBlock(); + Direction facing = block.getFilterFacing(state); + float scale = block.getItemHitboxScale(); + + TessellatorHelper.prepareForDrawing(); + + Vec3d position = block.getFilterPosition(state); + BlockPos pos = tileEntityIn.getPos(); + GlStateManager.translated(pos.getX(), pos.getY(), pos.getZ()); + + renderFilterItem(tileEntityIn.getFilter(), position, facing, scale - 2 / 16f); + + TessellatorHelper.cleanUpAfterDrawing(); + + } + + private void renderFilterItem(ItemStack stack, Vec3d position, Direction facing, float scaleDiff) { + ItemRenderer itemRenderer = Minecraft.getInstance().getItemRenderer(); + boolean vertical = facing.getAxis().isVertical(); + + IBakedModel modelWithOverrides = itemRenderer.getModelWithOverrides(stack); + boolean blockItem = modelWithOverrides.isGui3d(); + + float offX = 0; + float offY = 0; + float offZ = !blockItem ? 1 / 4f + 2 * scaleDiff - 1/16f : 1/16f; + if (vertical) + offZ = -offZ; + + float rotX = vertical ? 90 : 0 - (blockItem ? -67.5f : 67.5f); + float rotY = vertical ? 0 : facing.getHorizontalAngle() + (blockItem ? 180 : 0); + float rotZ = vertical && facing == Direction.DOWN ? 180 : 0; + if (facing.getAxis() == Axis.X) { + rotY = -rotY; + } + + float scale = !blockItem ? .25f : .5f; + scale *= 1 + 8 * scaleDiff; + + GlStateManager.pushMatrix(); + GlStateManager.translated(position.x, position.y, position.z); + GlStateManager.rotatef(rotZ, 0, 0, 1); + GlStateManager.rotatef(rotY, 0, 1, 0); + GlStateManager.rotatef(rotX, 1, 0, 0); + GlStateManager.scaled(scale, scale, scale); + GlStateManager.translatef(offX, offY, offZ); + itemRenderer.renderItem(stack, TransformType.FIXED); + GlStateManager.popMatrix(); + } + +} diff --git a/src/main/java/com/simibubi/create/modules/logistics/block/IBlockWithFilter.java b/src/main/java/com/simibubi/create/modules/logistics/block/IBlockWithFilter.java new file mode 100644 index 000000000..02f95149a --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/logistics/block/IBlockWithFilter.java @@ -0,0 +1,141 @@ +package com.simibubi.create.modules.logistics.block; + +import com.mojang.blaze3d.platform.GlStateManager; +import com.simibubi.create.foundation.utility.TessellatorHelper; + +import net.minecraft.block.BlockState; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.BufferBuilder; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.WorldRenderer; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.client.world.ClientWorld; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.Direction; +import net.minecraft.util.Direction.Axis; +import net.minecraft.util.Hand; +import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.BlockRayTraceResult; +import net.minecraft.util.math.Vec3d; +import net.minecraft.util.math.Vec3i; +import net.minecraft.world.World; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.client.event.DrawBlockHighlightEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod.EventBusSubscriber; + +@EventBusSubscriber(value = Dist.CLIENT) +public interface IBlockWithFilter { + + public Vec3d getFilterPosition(BlockState state); + + public Direction getFilterFacing(BlockState state); + + public default float getItemHitboxScale() { + return 2 / 16f; + } + + public default boolean handleActivatedFilterSlots(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, + Hand handIn, BlockRayTraceResult hit) { + TileEntity te = worldIn.getTileEntity(pos); + if (te == null || !(te instanceof IHaveFilter)) + return false; + + IHaveFilter actor = (IHaveFilter) te; + Vec3d vec = new Vec3d(pos); + Vec3d position = vec.add(getFilterPosition(state)); + ItemStack stack = player.getHeldItem(handIn); + float scale = getItemHitboxScale(); + + if (new AxisAlignedBB(position, position).grow(scale * 2).contains(hit.getHitVec())) { + if (worldIn.isRemote) + return true; + actor.setFilter(stack); + return true; + } + + return false; + } + + @SubscribeEvent + @OnlyIn(Dist.CLIENT) + public static void onDrawBlockHighlight(DrawBlockHighlightEvent event) { + if (event.getTarget() == null || !(event.getTarget() instanceof BlockRayTraceResult)) + return; + + BlockRayTraceResult result = (BlockRayTraceResult) event.getTarget(); + ClientWorld world = Minecraft.getInstance().world; + BlockPos pos = result.getPos(); + BlockState state = world.getBlockState(pos); + + if (!(state.getBlock() instanceof IBlockWithFilter)) + return; + + IBlockWithFilter filterBlock = (IBlockWithFilter) state.getBlock(); + Vec3d vec = new Vec3d(pos); + Vec3d position = filterBlock.getFilterPosition(state).add(vec); + float scale = filterBlock.getItemHitboxScale(); + + AxisAlignedBB bb = new AxisAlignedBB(position, position).grow(scale, scale / 1.25f, scale).offset(0, -scale / 16f, 0); + boolean contains = bb.grow(scale).contains(result.getHitVec()); + + TessellatorHelper.prepareForDrawing(); + GlStateManager.enableBlend(); + GlStateManager.blendFuncSeparate(GlStateManager.SourceFactor.SRC_ALPHA, + GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SourceFactor.ONE, + GlStateManager.DestFactor.ZERO); + GlStateManager.disableTexture(); + GlStateManager.depthMask(false); + + Tessellator tessellator = Tessellator.getInstance(); + BufferBuilder bufferbuilder = tessellator.getBuffer(); + bufferbuilder.begin(3, DefaultVertexFormats.POSITION_COLOR); + bb = bb.grow(1 / 128f); + Vec3d center = bb.getCenter().subtract(vec); + bb = bb.offset(center); + Direction facing = filterBlock.getFilterFacing(state); + Vec3i direction = facing.getDirectionVec(); + GlStateManager.pushMatrix(); + GlStateManager.translated(position.x, position.y, position.z); + GlStateManager.rotated(22.5f, direction.getZ(), 0, -direction.getX()); + GlStateManager.translated(-center.x, -center.y, -center.z); + GlStateManager.translated(-position.x, -position.y, -position.z); + + if (contains) { + GlStateManager.lineWidth(2); + WorldRenderer.drawBoundingBox(bufferbuilder, bb.minX, bb.minY, bb.minZ, bb.maxX, bb.maxY, bb.maxZ, .5f, 1, .75f, 1f); + } else { + GlStateManager.lineWidth(2); + WorldRenderer.drawBoundingBox(bufferbuilder, bb.minX, bb.minY, bb.minZ, bb.maxX, bb.maxY, bb.maxZ, .25f, .5f, .35f, 1f); + } + + tessellator.draw(); + + GlStateManager.popMatrix(); + GlStateManager.enableTexture(); + GlStateManager.depthMask(true); + + if (contains) { + float textScale = 1/128f; + GlStateManager.translated(position.x, position.y, position.z); + GlStateManager.rotated(facing.getHorizontalAngle() * (facing.getAxis() == Axis.X ? -1 : 1), 0, 1, 0); + GlStateManager.scaled(textScale, -textScale, textScale); + GlStateManager.translated(17.5f, -5f, -5f); + GlStateManager.rotated(67.5f, 1, 0, 0); + + String text = "Filter"; + Minecraft.getInstance().fontRenderer.drawString(text, 0, 0, 0x88FFBB); + GlStateManager.translated(0, 0, -1/4f); + Minecraft.getInstance().fontRenderer.drawString(text, 1, 1, 0x224433); + } + GlStateManager.disableBlend(); + + GlStateManager.lineWidth(1); + TessellatorHelper.cleanUpAfterDrawing(); + } + +} diff --git a/src/main/java/com/simibubi/create/modules/logistics/block/IBlockWithFrequency.java b/src/main/java/com/simibubi/create/modules/logistics/block/IBlockWithFrequency.java index d5bc08d25..bdbd6e901 100644 --- a/src/main/java/com/simibubi/create/modules/logistics/block/IBlockWithFrequency.java +++ b/src/main/java/com/simibubi/create/modules/logistics/block/IBlockWithFrequency.java @@ -15,6 +15,7 @@ import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.Direction; import net.minecraft.util.Hand; +import net.minecraft.util.Direction.Axis; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockRayTraceResult; @@ -30,13 +31,14 @@ import net.minecraftforge.fml.common.Mod.EventBusSubscriber; public interface IBlockWithFrequency { public Pair getFrequencyItemPositions(BlockState state); + public Direction getFrequencyItemFacing(BlockState state); public default float getItemHitboxScale() { return 2 / 16f; } - public default boolean handleActivated(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, + public default boolean handleActivatedFrequencySlots(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand handIn, BlockRayTraceResult hit) { TileEntity te = worldIn.getTileEntity(pos); if (te == null || !(te instanceof IHaveWireless)) @@ -87,6 +89,7 @@ public interface IBlockWithFrequency { Vec3d first = positions.getLeft().add(vec); Vec3d second = positions.getRight().add(vec); float scale = freqBlock.getItemHitboxScale(); + Direction facing = freqBlock.getFrequencyItemFacing(state); AxisAlignedBB firstBB = new AxisAlignedBB(first, first).grow(scale); AxisAlignedBB secondBB = new AxisAlignedBB(second, second).grow(scale); @@ -100,7 +103,8 @@ public interface IBlockWithFrequency { GlStateManager.depthMask(false); GlStateManager.matrixMode(5889); - if (firstBB.contains(result.getHitVec())) { + boolean firstContains = firstBB.contains(result.getHitVec()); + if (firstContains) { GlStateManager.lineWidth(2); WorldRenderer.drawSelectionBoundingBox(firstBB.grow(1 / 128f), 1, 1, .5f, 1f); } else { @@ -108,7 +112,8 @@ public interface IBlockWithFrequency { WorldRenderer.drawSelectionBoundingBox(firstBB.grow(1 / 128f), .5f, .5f, .2f, 1f); } - if (secondBB.contains(result.getHitVec())) { + boolean secondContains = secondBB.contains(result.getHitVec()); + if (secondContains) { GlStateManager.lineWidth(2); WorldRenderer.drawSelectionBoundingBox(secondBB.grow(1 / 128f), 1, 1, .5f, 1f); } else { @@ -119,6 +124,49 @@ public interface IBlockWithFrequency { GlStateManager.matrixMode(5888); GlStateManager.depthMask(true); GlStateManager.enableTexture(); + + if (firstContains) { + GlStateManager.pushMatrix(); + float textScale = 1 / 128f; + GlStateManager.translated(first.x, first.y, first.z); + if (facing.getAxis().isVertical()) { + GlStateManager.rotated(180, 0, 1, 0); + GlStateManager.rotated(facing == Direction.UP ? -90 : 90, 1, 0, 0); + } else { + GlStateManager.rotated(facing.getHorizontalAngle() * (facing.getAxis() == Axis.X ? -1 : 1), 0, 1, 0); + } + GlStateManager.scaled(textScale, -textScale, textScale); + GlStateManager.translated(19.5f, -5f, 10f); + + String text = "Freq. #2"; + Minecraft.getInstance().fontRenderer.drawString(text, 0, 0, 0xFFFF99); + GlStateManager.translated(0, 0, -1 / 4f); + Minecraft.getInstance().fontRenderer.drawString(text, 1, 1, 0x444433); + GlStateManager.popMatrix(); + } + + if (secondContains) { + GlStateManager.pushMatrix(); + float textScale = 1 / 128f; + GlStateManager.translated(second.x, second.y, second.z); + if (facing.getAxis().isVertical()) { + GlStateManager.rotated(180, 0, 1, 0); + GlStateManager.rotated(facing == Direction.UP ? -90 : 90, 1, 0, 0); + } else { + GlStateManager.rotated(facing.getHorizontalAngle() * (facing.getAxis() == Axis.X ? -1 : 1), 0, 1, 0); + } + GlStateManager.scaled(textScale, -textScale, textScale); + GlStateManager.translated(19.5f, -5f, 10f); + + String text = "Freq. #1"; + Minecraft.getInstance().fontRenderer.drawString(text, 0, 0, 0xFFFF99); + GlStateManager.translated(0, 0, -1 / 4f); + Minecraft.getInstance().fontRenderer.drawString(text, 1, 1, 0x444433); + GlStateManager.popMatrix(); + } + + GlStateManager.disableBlend(); + GlStateManager.disableBlend(); GlStateManager.lineWidth(1); TessellatorHelper.cleanUpAfterDrawing(); diff --git a/src/main/java/com/simibubi/create/modules/logistics/block/IExtractor.java b/src/main/java/com/simibubi/create/modules/logistics/block/IExtractor.java index 508031616..0e073d6fb 100644 --- a/src/main/java/com/simibubi/create/modules/logistics/block/IExtractor.java +++ b/src/main/java/com/simibubi/create/modules/logistics/block/IExtractor.java @@ -44,9 +44,15 @@ public interface IExtractor extends ITickableTileEntity, IInventoryManipulator { boolean hasInventory = getInventory().isPresent(); ItemStack toExtract = ItemStack.EMPTY; - if (hasSpace && hasInventory) + if (hasSpace && hasInventory) { toExtract = extract(true); + ItemStack filter = (this instanceof IHaveFilter) ? filter = ((IHaveFilter) this).getFilter() + : ItemStack.EMPTY; + if (!filter.isEmpty() && !ItemStack.areItemsEqual(toExtract, filter)) + toExtract = ItemStack.EMPTY; + } + if (state == State.WAITING_FOR_ENTITY) { if (hasSpace) setState(State.RUNNING); @@ -79,8 +85,13 @@ public interface IExtractor extends ITickableTileEntity, IInventoryManipulator { boolean hasInventory = getInventory().isPresent(); ItemStack toExtract = ItemStack.EMPTY; - if (hasSpace && hasInventory) + if (hasSpace && hasInventory) { toExtract = extract(true); + ItemStack filter = (this instanceof IHaveFilter) ? filter = ((IHaveFilter) this).getFilter() + : ItemStack.EMPTY; + if (!filter.isEmpty() && !ItemStack.areItemsEqual(toExtract, filter)) + toExtract = ItemStack.EMPTY; + } if (getState() == State.WAITING_FOR_INVENTORY) { if (!hasInventory) { @@ -101,9 +112,11 @@ public interface IExtractor extends ITickableTileEntity, IInventoryManipulator { default ItemStack extract(boolean simulate) { IItemHandler inv = getInventory().orElse(null); ItemStack extracting = ItemStack.EMPTY; + ItemStack filter = (this instanceof IHaveFilter) ? filter = ((IHaveFilter) this).getFilter() : ItemStack.EMPTY; + int extractionCount = filter.isEmpty() ? EXTRACTION_COUNT : filter.getCount(); for (int slot = 0; slot < inv.getSlots(); slot++) { - ItemStack stack = inv.extractItem(slot, EXTRACTION_COUNT - extracting.getCount(), true); + ItemStack stack = inv.extractItem(slot, extractionCount - extracting.getCount(), true); ItemStack compare = stack.copy(); compare.setCount(extracting.getCount()); if (!extracting.isEmpty() && !extracting.equals(compare, false)) @@ -116,7 +129,7 @@ public interface IExtractor extends ITickableTileEntity, IInventoryManipulator { if (!simulate) inv.extractItem(slot, stack.getCount(), false); - if (extracting.getCount() >= EXTRACTION_COUNT) + if (extracting.getCount() >= extractionCount) break; } diff --git a/src/main/java/com/simibubi/create/modules/logistics/block/IHaveFilter.java b/src/main/java/com/simibubi/create/modules/logistics/block/IHaveFilter.java new file mode 100644 index 000000000..7784babd3 --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/logistics/block/IHaveFilter.java @@ -0,0 +1,10 @@ +package com.simibubi.create.modules.logistics.block; + +import net.minecraft.item.ItemStack; + +public interface IHaveFilter { + + public void setFilter(ItemStack stack); + public ItemStack getFilter(); + +} diff --git a/src/main/java/com/simibubi/create/modules/logistics/block/LinkedExtractorBlock.java b/src/main/java/com/simibubi/create/modules/logistics/block/LinkedExtractorBlock.java index a3f50baef..40ba35221 100644 --- a/src/main/java/com/simibubi/create/modules/logistics/block/LinkedExtractorBlock.java +++ b/src/main/java/com/simibubi/create/modules/logistics/block/LinkedExtractorBlock.java @@ -35,12 +35,12 @@ public class LinkedExtractorBlock extends ExtractorBlock implements IBlockWithFr public BlockRenderLayer getRenderLayer() { return BlockRenderLayer.CUTOUT; } - + @Override public boolean hasTileEntity(BlockState state) { return true; } - + @Override public TileEntity createTileEntity(BlockState state, IBlockReader world) { return new LinkedExtractorTileEntity(); @@ -60,7 +60,7 @@ public class LinkedExtractorBlock extends ExtractorBlock implements IBlockWithFr public boolean onBlockActivated(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand handIn, BlockRayTraceResult hit) { return super.onBlockActivated(state, worldIn, pos, player, handIn, hit) - || handleActivated(state, worldIn, pos, player, handIn, hit); + || handleActivatedFrequencySlots(state, worldIn, pos, player, handIn, hit); } private void cacheItemPositions() { @@ -74,7 +74,7 @@ public class LinkedExtractorBlock extends ExtractorBlock implements IBlockWithFr for (int i = 0; i < 4; i++) { Direction facing = Direction.byHorizontalIndex(i); - first = new Vec3d(11.5f / 16f + zFightOffset, 4f / 16f, 14f / 16f ); + first = new Vec3d(11.5f / 16f + zFightOffset, 4f / 16f, 14f / 16f); second = new Vec3d(11.5f / 16f + zFightOffset, 8f / 16f, 14f / 16f); float angle = facing.getHorizontalAngle(); @@ -88,10 +88,10 @@ public class LinkedExtractorBlock extends ExtractorBlock implements IBlockWithFr } } - + @Override public float getItemHitboxScale() { - return 3/32f; + return 3 / 32f; } @Override @@ -104,5 +104,5 @@ public class LinkedExtractorBlock extends ExtractorBlock implements IBlockWithFr public Direction getFrequencyItemFacing(BlockState state) { return state.get(HORIZONTAL_FACING).rotateYCCW(); } - + } diff --git a/src/main/java/com/simibubi/create/modules/logistics/block/LinkedExtractorTileEntity.java b/src/main/java/com/simibubi/create/modules/logistics/block/LinkedExtractorTileEntity.java index 7945b0029..a4d1ec03f 100644 --- a/src/main/java/com/simibubi/create/modules/logistics/block/LinkedExtractorTileEntity.java +++ b/src/main/java/com/simibubi/create/modules/logistics/block/LinkedExtractorTileEntity.java @@ -5,6 +5,8 @@ import static net.minecraft.state.properties.BlockStateProperties.POWERED; import com.simibubi.create.AllTileEntities; import com.simibubi.create.modules.logistics.IReceiveWireless; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.CompoundNBT; import net.minecraft.state.properties.BlockStateProperties; import net.minecraft.tileentity.ITickableTileEntity; import net.minecraft.util.math.BlockPos; @@ -12,11 +14,12 @@ import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.items.IItemHandler; public class LinkedExtractorTileEntity extends LinkedTileEntity - implements IReceiveWireless, ITickableTileEntity, IExtractor { + implements IReceiveWireless, ITickableTileEntity, IExtractor, IHaveFilter { public boolean receivedSignal; private State state; + private ItemStack filter; private int cooldown; private LazyOptional inventory; @@ -24,13 +27,26 @@ public class LinkedExtractorTileEntity extends LinkedTileEntity super(AllTileEntities.LINKED_EXTRACTOR.type); state = State.WAITING_FOR_INVENTORY; inventory = LazyOptional.empty(); + filter = ItemStack.EMPTY; } @Override public void setSignal(boolean powered) { receivedSignal = powered; } - + + @Override + public void read(CompoundNBT compound) { + filter = ItemStack.read(compound.getCompound("Filter")); + super.read(compound); + } + + @Override + public CompoundNBT write(CompoundNBT compound) { + compound.put("Filter", filter.serializeNBT()); + return super.write(compound); + } + @Override public void tick() { IExtractor.super.tick(); @@ -75,4 +91,15 @@ public class LinkedExtractorTileEntity extends LinkedTileEntity this.inventory = inventory; } + @Override + public void setFilter(ItemStack stack) { + filter = stack; + sendData(); + } + + @Override + public ItemStack getFilter() { + return filter; + } + } diff --git a/src/main/java/com/simibubi/create/modules/logistics/block/LinkedExtractorTileEntityRenderer.java b/src/main/java/com/simibubi/create/modules/logistics/block/LinkedExtractorTileEntityRenderer.java new file mode 100644 index 000000000..e066e8579 --- /dev/null +++ b/src/main/java/com/simibubi/create/modules/logistics/block/LinkedExtractorTileEntityRenderer.java @@ -0,0 +1,23 @@ +package com.simibubi.create.modules.logistics.block; + +import net.minecraft.client.renderer.tileentity.TileEntityRenderer; + +public class LinkedExtractorTileEntityRenderer extends TileEntityRenderer { + + LinkedTileEntityRenderer linkRenderer; + FilteredTileEntityRenderer filterRenderer; + + public LinkedExtractorTileEntityRenderer() { + linkRenderer = new LinkedTileEntityRenderer(); + filterRenderer = new FilteredTileEntityRenderer(); + } + + @Override + public void render(LinkedExtractorTileEntity tileEntityIn, double x, double y, double z, float partialTicks, + int destroyStage) { + super.render(tileEntityIn, x, y, z, partialTicks, destroyStage); + linkRenderer.render(tileEntityIn, x, y, z, partialTicks, destroyStage); + filterRenderer.render(tileEntityIn, x, y, z, partialTicks, destroyStage); + } + +} diff --git a/src/main/java/com/simibubi/create/modules/logistics/block/LinkedTileEntityRenderer.java b/src/main/java/com/simibubi/create/modules/logistics/block/LinkedTileEntityRenderer.java index d18190fa4..ca5dc0ca9 100644 --- a/src/main/java/com/simibubi/create/modules/logistics/block/LinkedTileEntityRenderer.java +++ b/src/main/java/com/simibubi/create/modules/logistics/block/LinkedTileEntityRenderer.java @@ -23,8 +23,6 @@ public class LinkedTileEntityRenderer extends TileEntityRenderer